|
|
1.1 ! root 1: /* ! 2: * tkBitmap.c -- ! 3: * ! 4: * This file maintains a database of read-only bitmaps for the Tk ! 5: * toolkit. This allows bitmaps to be shared between widgets and ! 6: * also avoids interactions with the X server. ! 7: * ! 8: * Copyright 1990-1992 Regents of the University of California ! 9: * Permission to use, copy, modify, and distribute this ! 10: * software and its documentation for any purpose and without ! 11: * fee is hereby granted, provided that the above copyright ! 12: * notice appear in all copies. The University of California ! 13: * makes no representations about the suitability of this ! 14: * software for any purpose. It is provided "as is" without ! 15: * express or implied warranty. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkBitmap.c,v 1.16 92/08/24 09:45:43 ouster Exp $ SPRITE (Berkeley)"; ! 20: #endif /* not lint */ ! 21: ! 22: #include "tkconfig.h" ! 23: #include "tk.h" ! 24: ! 25: /* ! 26: * The includes below are for pre-defined bitmaps. ! 27: */ ! 28: ! 29: #include "bitmaps/gray50" ! 30: #include "bitmaps/gray25" ! 31: ! 32: /* ! 33: * One of the following data structures exists for each bitmap that is ! 34: * currently in use. Each structure is indexed with both "idTable" and ! 35: * "nameTable". ! 36: */ ! 37: ! 38: typedef struct { ! 39: Pixmap bitmap; /* X identifier for bitmap. None means this ! 40: * bitmap was created by Tk_DefineBitmap ! 41: * and it isn't currently in use. */ ! 42: unsigned int width, height; /* Dimensions of bitmap. */ ! 43: Display *display; /* Display for which bitmap is valid. */ ! 44: int refCount; /* Number of active uses of bitmap. */ ! 45: Tcl_HashEntry *hashPtr; /* Entry in nameTable for this structure ! 46: * (needed when deleting). */ ! 47: } TkBitmap; ! 48: ! 49: /* ! 50: * Hash table to map from a textual description of a bitmap to the ! 51: * TkBitmap record for the bitmap, and key structure used in that ! 52: * hash table: ! 53: */ ! 54: ! 55: static Tcl_HashTable nameTable; ! 56: typedef struct { ! 57: Tk_Uid name; /* Textual name for desired bitmap. */ ! 58: Screen *screen; /* Screen for which bitmap will be used. */ ! 59: } NameKey; ! 60: ! 61: /* ! 62: * Hash table that maps from bitmap identifiers to the TkBitmap structure ! 63: * for the bitmap. This table is indexed by Bitmap ids, and is used by ! 64: * Tk_FreeBitmap. ! 65: */ ! 66: ! 67: static Tcl_HashTable idTable; ! 68: ! 69: /* ! 70: * For each call to Tk_DefineBitmap one of the following structures is ! 71: * created to hold information about the bitmap. ! 72: */ ! 73: ! 74: typedef struct { ! 75: char *source; /* Bits for bitmap. */ ! 76: unsigned int width, height; /* Dimensions of bitmap. */ ! 77: } PredefBitmap; ! 78: ! 79: /* ! 80: * Hash table create by Tk_DefineBitmap to map from a name to a ! 81: * collection of in-core data about a bitmap. The table is ! 82: * indexed by the address of the data for the bitmap, and the entries ! 83: * contain pointers to PredefBitmap structures. ! 84: */ ! 85: ! 86: static Tcl_HashTable predefTable; ! 87: ! 88: /* ! 89: * Hash table used by Tk_GetBitmapFromData to map from a collection ! 90: * of in-core data about a bitmap to a Tk_Uid giving an automatically- ! 91: * generated name for the bitmap: ! 92: */ ! 93: ! 94: static Tcl_HashTable dataTable; ! 95: typedef struct { ! 96: char *source; /* Bitmap bits. */ ! 97: unsigned int width, height; /* Dimensions of bitmap. */ ! 98: } DataKey; ! 99: ! 100: static int initialized = 0; /* 0 means static structures haven't been ! 101: * initialized yet. */ ! 102: ! 103: /* ! 104: * Forward declarations for procedures defined in this file: ! 105: */ ! 106: ! 107: static void BitmapInit _ANSI_ARGS_((void)); ! 108: ! 109: /* ! 110: *---------------------------------------------------------------------- ! 111: * ! 112: * Tk_GetBitmap -- ! 113: * ! 114: * Given a string describing a bitmap, locate (or create if necessary) ! 115: * a bitmap that fits the description. ! 116: * ! 117: * Results: ! 118: * The return value is the X identifer for the desired bitmap ! 119: * (i.e. a Pixmap with a single plane), unless string couldn't be ! 120: * parsed correctly. In this case, None is returned and an error ! 121: * message is left in interp->result. The caller should never ! 122: * modify the bitmap that is returned, and should eventually call ! 123: * Tk_FreeBitmap when the bitmap is no longer needed. ! 124: * ! 125: * Side effects: ! 126: * The bitmap is added to an internal database with a reference count. ! 127: * For each call to this procedure, there should eventually be a call ! 128: * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps ! 129: * aren't needed anymore. ! 130: * ! 131: *---------------------------------------------------------------------- ! 132: */ ! 133: ! 134: Pixmap ! 135: Tk_GetBitmap(interp, tkwin, string) ! 136: Tcl_Interp *interp; /* Interpreter to use for error reporting. */ ! 137: Tk_Window tkwin; /* Window in which bitmap will be used. */ ! 138: Tk_Uid string; /* Description of bitmap. See manual entry ! 139: * for details on legal syntax. */ ! 140: { ! 141: NameKey key; ! 142: Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr; ! 143: register TkBitmap *bitmapPtr; ! 144: PredefBitmap *predefPtr; ! 145: int new; ! 146: Pixmap bitmap; ! 147: unsigned int width, height; ! 148: int dummy2; ! 149: ! 150: if (!initialized) { ! 151: BitmapInit(); ! 152: } ! 153: ! 154: key.name = string; ! 155: key.screen = Tk_Screen(tkwin); ! 156: nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &key, &new); ! 157: if (!new) { ! 158: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr); ! 159: bitmapPtr->refCount++; ! 160: return bitmapPtr->bitmap; ! 161: } ! 162: ! 163: /* ! 164: * No suitable bitmap exists. Create a new bitmap from the ! 165: * information contained in the string. If the string starts ! 166: * with "@" then the rest of the string is a file name containing ! 167: * the bitmap. Otherwise the string must refer to a bitmap ! 168: * defined by a call to Tk_DefineBitmap. ! 169: */ ! 170: ! 171: if (*string == '@') { ! 172: string = Tcl_TildeSubst(interp, string + 1); ! 173: if (string == NULL) { ! 174: goto error; ! 175: } ! 176: if (XReadBitmapFile(Tk_Display(tkwin), ! 177: RootWindowOfScreen(Tk_Screen(tkwin)), ! 178: string, &width, &height, &bitmap, &dummy2, &dummy2) ! 179: != BitmapSuccess) { ! 180: Tcl_AppendResult(interp, "error reading bitmap file \"", string, ! 181: "\"", (char *) NULL); ! 182: goto error; ! 183: } ! 184: } else { ! 185: predefHashPtr = Tcl_FindHashEntry(&predefTable, string); ! 186: if (predefHashPtr == NULL) { ! 187: Tcl_AppendResult(interp, "bitmap \"", string, ! 188: "\" not defined", (char *) NULL); ! 189: goto error; ! 190: } ! 191: predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr); ! 192: width = predefPtr->width; ! 193: height = predefPtr->height; ! 194: bitmap = XCreateBitmapFromData(Tk_Display(tkwin), ! 195: RootWindowOfScreen(Tk_Screen(tkwin)), predefPtr->source, ! 196: width, height); ! 197: } ! 198: ! 199: /* ! 200: * Add information about this bitmap to our database. ! 201: */ ! 202: ! 203: bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap)); ! 204: bitmapPtr->bitmap = bitmap; ! 205: bitmapPtr->width = width; ! 206: bitmapPtr->height = height; ! 207: bitmapPtr->display = Tk_Display(tkwin); ! 208: bitmapPtr->refCount = 1; ! 209: bitmapPtr->hashPtr = nameHashPtr; ! 210: idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) bitmapPtr->bitmap, ! 211: &new); ! 212: if (!new) { ! 213: /* deh patched to support multiple displays */ ! 214: /* panic("bitmap already registered in Tk_GetBitmap"); */ ! 215: bitmapPtr->refCount = 1000; ! 216: } ! 217: Tcl_SetHashValue(nameHashPtr, bitmapPtr); ! 218: Tcl_SetHashValue(idHashPtr, bitmapPtr); ! 219: return bitmapPtr->bitmap; ! 220: ! 221: error: ! 222: Tcl_DeleteHashEntry(nameHashPtr); ! 223: return None; ! 224: } ! 225: ! 226: /* ! 227: *---------------------------------------------------------------------- ! 228: * ! 229: * Tk_DefineBitmap -- ! 230: * ! 231: * This procedure associates a textual name with a binary bitmap ! 232: * description, so that the name may be used to refer to the ! 233: * bitmap in future calls to Tk_GetBitmap. ! 234: * ! 235: * Results: ! 236: * A standard Tcl result. If an error occurs then TCL_ERROR is ! 237: * returned and a message is left in interp->result. ! 238: * ! 239: * Side effects: ! 240: * "Name" is entered into the bitmap table and may be used from ! 241: * here on to refer to the given bitmap. ! 242: * ! 243: *---------------------------------------------------------------------- ! 244: */ ! 245: ! 246: int ! 247: Tk_DefineBitmap(interp, name, source, width, height) ! 248: Tcl_Interp *interp; /* Interpreter to use for error reporting. */ ! 249: Tk_Uid name; /* Name to use for bitmap. Must not already ! 250: * be defined as a bitmap. */ ! 251: char *source; /* Address of bits for bitmap. */ ! 252: unsigned int width; /* Width of bitmap. */ ! 253: unsigned int height; /* Height of bitmap. */ ! 254: { ! 255: int new; ! 256: Tcl_HashEntry *predefHashPtr; ! 257: PredefBitmap *predefPtr; ! 258: ! 259: if (!initialized) { ! 260: BitmapInit(); ! 261: } ! 262: ! 263: predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new); ! 264: if (!new) { ! 265: Tcl_AppendResult(interp, "bitmap \"", name, ! 266: "\" is already defined", (char *) NULL); ! 267: return TCL_ERROR; ! 268: } ! 269: predefPtr = (PredefBitmap *) malloc(sizeof(PredefBitmap)); ! 270: predefPtr->source = source; ! 271: predefPtr->width = width; ! 272: predefPtr->height = height; ! 273: Tcl_SetHashValue(predefHashPtr, predefPtr); ! 274: return TCL_OK; ! 275: } ! 276: ! 277: /* ! 278: *-------------------------------------------------------------- ! 279: * ! 280: * Tk_NameOfBitmap -- ! 281: * ! 282: * Given a bitmap, return a textual string identifying the ! 283: * bitmap. ! 284: * ! 285: * Results: ! 286: * The return value is the string name associated with bitmap. ! 287: * ! 288: * Side effects: ! 289: * None. ! 290: * ! 291: *-------------------------------------------------------------- ! 292: */ ! 293: ! 294: Tk_Uid ! 295: Tk_NameOfBitmap(bitmap) ! 296: Pixmap bitmap; /* Bitmap whose name is wanted. */ ! 297: { ! 298: Tcl_HashEntry *idHashPtr; ! 299: TkBitmap *bitmapPtr; ! 300: ! 301: if (!initialized) { ! 302: unknown: ! 303: panic("Tk_NameOfBitmap received unknown bitmap argument"); ! 304: } ! 305: ! 306: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap); ! 307: if (idHashPtr == NULL) { ! 308: goto unknown; ! 309: } ! 310: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr); ! 311: return ((NameKey *) bitmapPtr->hashPtr->key.words)->name; ! 312: } ! 313: ! 314: /* ! 315: *-------------------------------------------------------------- ! 316: * ! 317: * Tk_SizeOfBitmap -- ! 318: * ! 319: * Given a bitmap managed by this module, returns the width ! 320: * and height of the bitmap.. ! 321: * ! 322: * Results: ! 323: * The words at *widthPtr and *heightPtr are filled in with ! 324: * the dimenstions of bitmap. ! 325: * ! 326: * Side effects: ! 327: * If bitmap isn't managed by this module then the procedure ! 328: * panics.. ! 329: * ! 330: *-------------------------------------------------------------- ! 331: */ ! 332: ! 333: void ! 334: Tk_SizeOfBitmap(bitmap, widthPtr, heightPtr) ! 335: Pixmap bitmap; /* Bitmap whose size is wanted. */ ! 336: unsigned int *widthPtr; /* Store bitmap width here. */ ! 337: unsigned int *heightPtr; /* Store bitmap height here. */ ! 338: { ! 339: Tcl_HashEntry *idHashPtr; ! 340: TkBitmap *bitmapPtr; ! 341: ! 342: if (!initialized) { ! 343: unknownBitmap: ! 344: panic("Tk_SizeOfBitmap received unknown bitmap argument"); ! 345: } ! 346: ! 347: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap); ! 348: if (idHashPtr == NULL) { ! 349: goto unknownBitmap; ! 350: } ! 351: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr); ! 352: *widthPtr = bitmapPtr->width; ! 353: *heightPtr = bitmapPtr->height; ! 354: } ! 355: ! 356: /* ! 357: *---------------------------------------------------------------------- ! 358: * ! 359: * Tk_FreeBitmap -- ! 360: * ! 361: * This procedure is called to release a bitmap allocated by ! 362: * Tk_GetBitmap or TkGetBitmapFromData. ! 363: * ! 364: * Results: ! 365: * None. ! 366: * ! 367: * Side effects: ! 368: * The reference count associated with bitmap is decremented, and ! 369: * it is officially deallocated if no-one is using it anymore. ! 370: * ! 371: *---------------------------------------------------------------------- ! 372: */ ! 373: ! 374: void ! 375: Tk_FreeBitmap(bitmap) ! 376: Pixmap bitmap; /* Bitmap to be released. */ ! 377: { ! 378: Tcl_HashEntry *idHashPtr; ! 379: register TkBitmap *bitmapPtr; ! 380: ! 381: if (!initialized) { ! 382: panic("Tk_FreeBitmap called before Tk_GetBitmap"); ! 383: } ! 384: ! 385: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap); ! 386: if (idHashPtr == NULL) { ! 387: panic("Tk_FreeBitmap received unknown bitmap argument"); ! 388: } ! 389: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr); ! 390: bitmapPtr->refCount--; ! 391: if (bitmapPtr->refCount == 0) { ! 392: XFreePixmap(bitmapPtr->display, bitmapPtr->bitmap); ! 393: Tcl_DeleteHashEntry(idHashPtr); ! 394: Tcl_DeleteHashEntry(bitmapPtr->hashPtr); ! 395: ckfree((char *) bitmapPtr); ! 396: } ! 397: } ! 398: ! 399: /* ! 400: *---------------------------------------------------------------------- ! 401: * ! 402: * Tk_GetBitmapFromData -- ! 403: * ! 404: * Given a description of the bits for a bitmap, make a bitmap that ! 405: * has the given properties. ! 406: * ! 407: * Results: ! 408: * The return value is the X identifer for the desired bitmap ! 409: * (a one-plane Pixmap), unless it couldn't be created properly. ! 410: * In this case, None is returned and an error message is left in ! 411: * interp->result. The caller should never modify the bitmap that ! 412: * is returned, and should eventually call Tk_FreeBitmap when the ! 413: * bitmap is no longer needed. ! 414: * ! 415: * Side effects: ! 416: * The bitmap is added to an internal database with a reference count. ! 417: * For each call to this procedure, there should eventually be a call ! 418: * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps ! 419: * aren't needed anymore. ! 420: * ! 421: *---------------------------------------------------------------------- ! 422: */ ! 423: ! 424: /* ARGSUSED */ ! 425: Pixmap ! 426: Tk_GetBitmapFromData(interp, tkwin, source, width, height) ! 427: Tcl_Interp *interp; /* Interpreter to use for error reporting. */ ! 428: Tk_Window tkwin; /* Window in which bitmap will be used. */ ! 429: char *source; /* Bitmap data for bitmap shape. */ ! 430: unsigned int width, height; /* Dimensions of bitmap. */ ! 431: { ! 432: DataKey key; ! 433: Tcl_HashEntry *dataHashPtr; ! 434: Tk_Uid name = NULL; /* Initialization need only to prevent ! 435: * compiler warning. */ ! 436: int new; ! 437: static autoNumber = 0; ! 438: char string[20]; ! 439: ! 440: if (!initialized) { ! 441: BitmapInit(); ! 442: } ! 443: ! 444: key.source = source; ! 445: key.width = width; ! 446: key.height = height; ! 447: dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &key, &new); ! 448: if (!new) { ! 449: name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr); ! 450: } else { ! 451: autoNumber++; ! 452: sprintf(string, "_tk%d", autoNumber); ! 453: name = Tk_GetUid(string); ! 454: Tcl_SetHashValue(dataHashPtr, name); ! 455: if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) { ! 456: Tcl_DeleteHashEntry(dataHashPtr); ! 457: return TCL_ERROR; ! 458: } ! 459: } ! 460: return Tk_GetBitmap(interp, tkwin, name); ! 461: } ! 462: ! 463: /* ! 464: *---------------------------------------------------------------------- ! 465: * ! 466: * BitmapInit -- ! 467: * ! 468: * Initialize the structures used for bitmap management. ! 469: * ! 470: * Results: ! 471: * None. ! 472: * ! 473: * Side effects: ! 474: * Read the code. ! 475: * ! 476: *---------------------------------------------------------------------- ! 477: */ ! 478: ! 479: static void ! 480: BitmapInit() ! 481: { ! 482: Tcl_Interp *dummy; ! 483: ! 484: dummy = Tcl_CreateInterp(); ! 485: initialized = 1; ! 486: Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int)); ! 487: Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int)); ! 488: Tcl_InitHashTable(&predefTable, TCL_ONE_WORD_KEYS); ! 489: Tcl_InitHashTable(&idTable, TCL_ONE_WORD_KEYS); ! 490: ! 491: Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *)gray50_bits, ! 492: gray50_width, gray50_height); ! 493: Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), ! 494: (char *)gray25_bits, gray25_width, gray25_height); ! 495: Tcl_DeleteInterp(dummy); ! 496: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.