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 also 6 * avoids interactions with the X server. 7 * 8 * Copyright (c) 1990-1994 The Regents of the University of California. 9 * Copyright (c) 1994-1998 Sun Microsystems, Inc. 10 * 11 * See the file "license.terms" for information on usage and redistribution of 12 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 13 * 14 * RCS: @(#) $Id$ 15 */ 16 17#include "tkInt.h" 18 19/* 20 * The includes below are for pre-defined bitmaps. 21 * 22 * Platform-specific issue: Windows complains when the bitmaps are included, 23 * because an array of characters is being initialized with integers as 24 * elements. For lint purposes, the following pragmas temporarily turn off 25 * that warning message. 26 */ 27 28#if (defined(__WIN32__) || defined(_WIN32)) && !defined(__GNUC__) 29#pragma warning (disable : 4305) 30#endif 31 32#include "error.xbm" 33#include "gray12.xbm" 34#include "gray25.xbm" 35#include "gray50.xbm" 36#include "gray75.xbm" 37#include "hourglass.xbm" 38#include "info.xbm" 39#include "questhead.xbm" 40#include "question.xbm" 41#include "warning.xbm" 42 43#if (defined(__WIN32__) || defined(_WIN32)) && !defined(__GNUC__) 44#pragma warning (default : 4305) 45#endif 46 47/* 48 * One of the following data structures exists for each bitmap that is 49 * currently in use. Each structure is indexed with both "idTable" and 50 * "nameTable". 51 */ 52 53typedef struct TkBitmap { 54 Pixmap bitmap; /* X identifier for bitmap. None means this 55 * bitmap was created by Tk_DefineBitmap and 56 * it isn't currently in use. */ 57 int width, height; /* Dimensions of bitmap. */ 58 Display *display; /* Display for which bitmap is valid. */ 59 int screenNum; /* Screen on which bitmap is valid. */ 60 int resourceRefCount; /* Number of active uses of this bitmap (each 61 * active use corresponds to a call to 62 * Tk_AllocBitmapFromObj or Tk_GetBitmap). If 63 * this count is 0, then this TkBitmap 64 * structure is no longer valid and it isn't 65 * present in nameTable: it is being kept 66 * around only because there are objects 67 * referring to it. The structure is freed 68 * when resourceRefCount and objRefCount are 69 * both 0. */ 70 int objRefCount; /* Number of Tcl_Obj's that reference this 71 * structure. */ 72 Tcl_HashEntry *nameHashPtr; /* Entry in nameTable for this structure 73 * (needed when deleting). */ 74 Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure (needed 75 * when deleting). */ 76 struct TkBitmap *nextPtr; /* Points to the next TkBitmap structure with 77 * the same name. All bitmaps with the same 78 * name (but different displays or screens) 79 * are chained together off a single entry in 80 * nameTable. */ 81} TkBitmap; 82 83/* 84 * Used in bitmapDataTable, stored in the TkDisplay structure, to map between 85 * in-core data about a bitmap to its TkBitmap structure. 86 */ 87 88typedef struct { 89 const char *source; /* Bitmap bits. */ 90 int width, height; /* Dimensions of bitmap. */ 91} DataKey; 92 93typedef struct ThreadSpecificData { 94 int initialized; /* 0 means table below needs initializing. */ 95 Tcl_HashTable predefBitmapTable; 96 /* Hash table created by Tk_DefineBitmap to 97 * map from a name to a collection of in-core 98 * data about a bitmap. The table is indexed 99 * by the address of the data for the bitmap, 100 * and the entries contain pointers to 101 * TkPredefBitmap structures. */ 102} ThreadSpecificData; 103static Tcl_ThreadDataKey dataKey; 104 105/* 106 * Forward declarations for functions defined in this file: 107 */ 108 109static void BitmapInit(TkDisplay *dispPtr); 110static void DupBitmapObjProc(Tcl_Obj *srcObjPtr, 111 Tcl_Obj *dupObjPtr); 112static void FreeBitmap(TkBitmap *bitmapPtr); 113static void FreeBitmapObjProc(Tcl_Obj *objPtr); 114static TkBitmap * GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, 115 const char *name); 116static TkBitmap * GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); 117static void InitBitmapObj(Tcl_Obj *objPtr); 118 119/* 120 * The following structure defines the implementation of the "bitmap" Tcl 121 * object, which maps a string bitmap name to a TkBitmap object. The ptr1 122 * field of the Tcl_Obj points to a TkBitmap object. 123 */ 124 125Tcl_ObjType tkBitmapObjType = { 126 "bitmap", /* name */ 127 FreeBitmapObjProc, /* freeIntRepProc */ 128 DupBitmapObjProc, /* dupIntRepProc */ 129 NULL, /* updateStringProc */ 130 NULL /* setFromAnyProc */ 131}; 132 133/* 134 *---------------------------------------------------------------------- 135 * 136 * Tk_AllocBitmapFromObj -- 137 * 138 * Given a Tcl_Obj *, map the value to a corresponding Pixmap structure 139 * based on the tkwin given. 140 * 141 * Results: 142 * The return value is the X identifer for the desired bitmap (i.e. a 143 * Pixmap with a single plane), unless string couldn't be parsed 144 * correctly. In this case, None is returned and an error message is left 145 * in the interp's result. The caller should never modify the bitmap that 146 * is returned, and should eventually call Tk_FreeBitmapFromObj when the 147 * bitmap is no longer needed. 148 * 149 * Side effects: 150 * The bitmap is added to an internal database with a reference count. 151 * For each call to this function, there should eventually be a call to 152 * Tk_FreeBitmapFromObj, so that the database can be cleaned up when 153 * bitmaps aren't needed anymore. 154 * 155 *---------------------------------------------------------------------- 156 */ 157 158Pixmap 159Tk_AllocBitmapFromObj( 160 Tcl_Interp *interp, /* Interp for error results. This may be 161 * NULL. */ 162 Tk_Window tkwin, /* Need the screen the bitmap is used on.*/ 163 Tcl_Obj *objPtr) /* Object describing bitmap; see manual entry 164 * for legal syntax of string value. */ 165{ 166 TkBitmap *bitmapPtr; 167 168 if (objPtr->typePtr != &tkBitmapObjType) { 169 InitBitmapObj(objPtr); 170 } 171 bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; 172 173 /* 174 * If the object currently points to a TkBitmap, see if it's the one we 175 * want. If so, increment its reference count and return. 176 */ 177 178 if (bitmapPtr != NULL) { 179 if (bitmapPtr->resourceRefCount == 0) { 180 /* 181 * This is a stale reference: it refers to a TkBitmap that's no 182 * longer in use. Clear the reference. 183 */ 184 185 FreeBitmapObjProc(objPtr); 186 bitmapPtr = NULL; 187 } else if ((Tk_Display(tkwin) == bitmapPtr->display) 188 && (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) { 189 bitmapPtr->resourceRefCount++; 190 return bitmapPtr->bitmap; 191 } 192 } 193 194 /* 195 * The object didn't point to the TkBitmap that we wanted. Search the list 196 * of TkBitmaps with the same name to see if one of the others is the 197 * right one. 198 */ 199 200 if (bitmapPtr != NULL) { 201 TkBitmap *firstBitmapPtr = (TkBitmap *) 202 Tcl_GetHashValue(bitmapPtr->nameHashPtr); 203 FreeBitmapObjProc(objPtr); 204 for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL; 205 bitmapPtr = bitmapPtr->nextPtr) { 206 if ((Tk_Display(tkwin) == bitmapPtr->display) && 207 (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) { 208 bitmapPtr->resourceRefCount++; 209 bitmapPtr->objRefCount++; 210 objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; 211 return bitmapPtr->bitmap; 212 } 213 } 214 } 215 216 /* 217 * Still no luck. Call GetBitmap to allocate a new TkBitmap object. 218 */ 219 220 bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr)); 221 objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; 222 if (bitmapPtr == NULL) { 223 return None; 224 } 225 bitmapPtr->objRefCount++; 226 return bitmapPtr->bitmap; 227} 228 229/* 230 *---------------------------------------------------------------------- 231 * 232 * Tk_GetBitmap -- 233 * 234 * Given a string describing a bitmap, locate (or create if necessary) a 235 * bitmap that fits the description. 236 * 237 * Results: 238 * The return value is the X identifer for the desired bitmap (i.e. a 239 * Pixmap with a single plane), unless string couldn't be parsed 240 * correctly. In this case, None is returned and an error message is left 241 * in the interp's result. The caller should never modify the bitmap that 242 * is returned, and should eventually call Tk_FreeBitmap when the bitmap 243 * is no longer needed. 244 * 245 * Side effects: 246 * The bitmap is added to an internal database with a reference count. 247 * For each call to this function, there should eventually be a call to 248 * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps 249 * aren't needed anymore. 250 * 251 *---------------------------------------------------------------------- 252 */ 253 254Pixmap 255Tk_GetBitmap( 256 Tcl_Interp *interp, /* Interpreter to use for error reporting, 257 * this may be NULL. */ 258 Tk_Window tkwin, /* Window in which bitmap will be used. */ 259 const char *string) /* Description of bitmap. See manual entry for 260 * details on legal syntax. */ 261{ 262 TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string); 263 264 if (bitmapPtr == NULL) { 265 return None; 266 } 267 return bitmapPtr->bitmap; 268} 269 270/* 271 *---------------------------------------------------------------------- 272 * 273 * GetBitmap -- 274 * 275 * Given a string describing a bitmap, locate (or create if necessary) a 276 * bitmap that fits the description. This routine returns the internal 277 * data structure for the bitmap. This avoids extra hash table lookups in 278 * Tk_AllocBitmapFromObj. 279 * 280 * Results: 281 * The return value is the X identifer for the desired bitmap (i.e. a 282 * Pixmap with a single plane), unless string couldn't be parsed 283 * correctly. In this case, None is returned and an error message is left 284 * in the interp's result. The caller should never modify the bitmap that 285 * is returned, and should eventually call Tk_FreeBitmap when the bitmap 286 * is no longer needed. 287 * 288 * Side effects: 289 * The bitmap is added to an internal database with a reference count. 290 * For each call to this function, there should eventually be a call to 291 * Tk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can be 292 * cleaned up when bitmaps aren't needed anymore. 293 * 294 *---------------------------------------------------------------------- 295 */ 296 297static TkBitmap * 298GetBitmap( 299 Tcl_Interp *interp, /* Interpreter to use for error reporting, 300 * this may be NULL. */ 301 Tk_Window tkwin, /* Window in which bitmap will be used. */ 302 const char *string) /* Description of bitmap. See manual entry for 303 * details on legal syntax. */ 304{ 305 Tcl_HashEntry *nameHashPtr, *predefHashPtr; 306 TkBitmap *bitmapPtr, *existingBitmapPtr; 307 TkPredefBitmap *predefPtr; 308 Pixmap bitmap; 309 int isNew, width, height, dummy2; 310 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; 311 ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 312 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); 313 314 if (!dispPtr->bitmapInit) { 315 BitmapInit(dispPtr); 316 } 317 318 nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string, 319 &isNew); 320 if (!isNew) { 321 existingBitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr); 322 for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL; 323 bitmapPtr = bitmapPtr->nextPtr) { 324 if ( (Tk_Display(tkwin) == bitmapPtr->display) && 325 (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum) ) { 326 bitmapPtr->resourceRefCount++; 327 return bitmapPtr; 328 } 329 } 330 } else { 331 existingBitmapPtr = NULL; 332 } 333 334 /* 335 * No suitable bitmap exists. Create a new bitmap from the information 336 * contained in the string. If the string starts with "@" then the rest of 337 * the string is a file name containing the bitmap. Otherwise the string 338 * must refer to a bitmap defined by a call to Tk_DefineBitmap. 339 */ 340 341 if (*string == '@') { /* INTL: ISO char */ 342 Tcl_DString buffer; 343 int result; 344 345 if (Tcl_IsSafe(interp)) { 346 Tcl_AppendResult(interp, "can't specify bitmap with '@' in a", 347 " safe interpreter", NULL); 348 goto error; 349 } 350 351 /* 352 * Note that we need to cast away the const from the string because 353 * Tcl_TranslateFileName is non-const, even though it doesn't modify 354 * the string. 355 */ 356 357 string = Tcl_TranslateFileName(interp, (char *) string + 1, &buffer); 358 if (string == NULL) { 359 goto error; 360 } 361 result = TkReadBitmapFile(Tk_Display(tkwin), 362 RootWindowOfScreen(Tk_Screen(tkwin)), string, 363 (unsigned int *) &width, (unsigned int *) &height, 364 &bitmap, &dummy2, &dummy2); 365 if (result != BitmapSuccess) { 366 if (interp != NULL) { 367 Tcl_AppendResult(interp, "error reading bitmap file \"", 368 string, "\"", NULL); 369 } 370 Tcl_DStringFree(&buffer); 371 goto error; 372 } 373 Tcl_DStringFree(&buffer); 374 } else { 375 predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, string); 376 if (predefHashPtr == NULL) { 377 /* 378 * The following platform specific call allows the user to define 379 * bitmaps that may only exist during run time. If it returns None 380 * nothing was found and we return the error. 381 */ 382 383 bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string, 384 &width, &height); 385 386 if (bitmap == None) { 387 if (interp != NULL) { 388 Tcl_AppendResult(interp, "bitmap \"", string, 389 "\" not defined", NULL); 390 } 391 goto error; 392 } 393 } else { 394 predefPtr = (TkPredefBitmap *) Tcl_GetHashValue(predefHashPtr); 395 width = predefPtr->width; 396 height = predefPtr->height; 397 if (predefPtr->native) { 398 bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin), 399 predefPtr->source); 400 if (bitmap == None) { 401 Tcl_Panic("native bitmap creation failed"); 402 } 403 } else { 404 bitmap = XCreateBitmapFromData(Tk_Display(tkwin), 405 RootWindowOfScreen(Tk_Screen(tkwin)), 406 predefPtr->source, (unsigned)width, (unsigned)height); 407 } 408 } 409 } 410 411 /* 412 * Add information about this bitmap to our database. 413 */ 414 415 bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap)); 416 bitmapPtr->bitmap = bitmap; 417 bitmapPtr->width = width; 418 bitmapPtr->height = height; 419 bitmapPtr->display = Tk_Display(tkwin); 420 bitmapPtr->screenNum = Tk_ScreenNumber(tkwin); 421 bitmapPtr->resourceRefCount = 1; 422 bitmapPtr->objRefCount = 0; 423 bitmapPtr->nameHashPtr = nameHashPtr; 424 bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable, 425 (char *) bitmap, &isNew); 426 if (!isNew) { 427 Tcl_Panic("bitmap already registered in Tk_GetBitmap"); 428 } 429 bitmapPtr->nextPtr = existingBitmapPtr; 430 Tcl_SetHashValue(nameHashPtr, bitmapPtr); 431 Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr); 432 return bitmapPtr; 433 434 error: 435 if (isNew) { 436 Tcl_DeleteHashEntry(nameHashPtr); 437 } 438 return NULL; 439} 440 441/* 442 *---------------------------------------------------------------------- 443 * 444 * Tk_DefineBitmap -- 445 * 446 * This function associates a textual name with a binary bitmap 447 * description, so that the name may be used to refer to the bitmap in 448 * future calls to Tk_GetBitmap. 449 * 450 * Results: 451 * A standard Tcl result. If an error occurs then TCL_ERROR is returned 452 * and a message is left in the interp's result. 453 * 454 * Side effects: 455 * "Name" is entered into the bitmap table and may be used from here on 456 * to refer to the given bitmap. 457 * 458 *---------------------------------------------------------------------- 459 */ 460 461int 462Tk_DefineBitmap( 463 Tcl_Interp *interp, /* Interpreter to use for error reporting. */ 464 const char *name, /* Name to use for bitmap. Must not already be 465 * defined as a bitmap. */ 466 const char *source, /* Address of bits for bitmap. */ 467 int width, /* Width of bitmap. */ 468 int height) /* Height of bitmap. */ 469{ 470 int isNew; 471 Tcl_HashEntry *predefHashPtr; 472 TkPredefBitmap *predefPtr; 473 ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 474 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); 475 476 /* 477 * Initialize the Bitmap module if not initialized already for this 478 * thread. Since the current TkDisplay structure cannot be introspected 479 * from here, pass a NULL pointer to BitmapInit, which will know to 480 * initialize only the data in the ThreadSpecificData structure for the 481 * current thread. 482 */ 483 484 if (!tsdPtr->initialized) { 485 BitmapInit(NULL); 486 } 487 488 predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable, 489 name, &isNew); 490 if (!isNew) { 491 Tcl_AppendResult(interp, "bitmap \"", name, "\" is already defined", 492 NULL); 493 return TCL_ERROR; 494 } 495 predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap)); 496 predefPtr->source = source; 497 predefPtr->width = width; 498 predefPtr->height = height; 499 predefPtr->native = 0; 500 Tcl_SetHashValue(predefHashPtr, predefPtr); 501 return TCL_OK; 502} 503 504/* 505 *-------------------------------------------------------------- 506 * 507 * Tk_NameOfBitmap -- 508 * 509 * Given a bitmap, return a textual string identifying the bitmap. 510 * 511 * Results: 512 * The return value is the string name associated with bitmap. 513 * 514 * Side effects: 515 * None. 516 * 517 *-------------------------------------------------------------- 518 */ 519 520const char * 521Tk_NameOfBitmap( 522 Display *display, /* Display for which bitmap was allocated. */ 523 Pixmap bitmap) /* Bitmap whose name is wanted. */ 524{ 525 Tcl_HashEntry *idHashPtr; 526 TkBitmap *bitmapPtr; 527 TkDisplay *dispPtr = TkGetDisplay(display); 528 529 if (dispPtr == NULL || !dispPtr->bitmapInit) { 530 unknown: 531 Tcl_Panic("Tk_NameOfBitmap received unknown bitmap argument"); 532 } 533 534 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); 535 if (idHashPtr == NULL) { 536 goto unknown; 537 } 538 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr); 539 return bitmapPtr->nameHashPtr->key.string; 540} 541 542/* 543 *-------------------------------------------------------------- 544 * 545 * Tk_SizeOfBitmap -- 546 * 547 * Given a bitmap managed by this module, returns the width and height of 548 * the bitmap. 549 * 550 * Results: 551 * The words at *widthPtr and *heightPtr are filled in with the 552 * dimenstions of bitmap. 553 * 554 * Side effects: 555 * If bitmap isn't managed by this module then the function panics.. 556 * 557 *-------------------------------------------------------------- 558 */ 559 560void 561Tk_SizeOfBitmap( 562 Display *display, /* Display for which bitmap was allocated. */ 563 Pixmap bitmap, /* Bitmap whose size is wanted. */ 564 int *widthPtr, /* Store bitmap width here. */ 565 int *heightPtr) /* Store bitmap height here. */ 566{ 567 Tcl_HashEntry *idHashPtr; 568 TkBitmap *bitmapPtr; 569 TkDisplay *dispPtr = TkGetDisplay(display); 570 571 if (!dispPtr->bitmapInit) { 572 unknownBitmap: 573 Tcl_Panic("Tk_SizeOfBitmap received unknown bitmap argument"); 574 } 575 576 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); 577 if (idHashPtr == NULL) { 578 goto unknownBitmap; 579 } 580 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr); 581 *widthPtr = bitmapPtr->width; 582 *heightPtr = bitmapPtr->height; 583} 584 585/* 586 *---------------------------------------------------------------------- 587 * 588 * FreeBitmap -- 589 * 590 * This function does all the work of releasing a bitmap allocated by 591 * Tk_GetBitmap or TkGetBitmapFromData. It is invoked by both 592 * Tk_FreeBitmap and Tk_FreeBitmapFromObj 593 * 594 * Results: 595 * None. 596 * 597 * Side effects: 598 * The reference count associated with bitmap is decremented, and it is 599 * officially deallocated if no-one is using it anymore. 600 * 601 *---------------------------------------------------------------------- 602 */ 603 604static void 605FreeBitmap( 606 TkBitmap *bitmapPtr) /* Bitmap to be released. */ 607{ 608 TkBitmap *prevPtr; 609 610 bitmapPtr->resourceRefCount--; 611 if (bitmapPtr->resourceRefCount > 0) { 612 return; 613 } 614 615 Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap); 616 Tcl_DeleteHashEntry(bitmapPtr->idHashPtr); 617 prevPtr = (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr); 618 if (prevPtr == bitmapPtr) { 619 if (bitmapPtr->nextPtr == NULL) { 620 Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr); 621 } else { 622 Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr); 623 } 624 } else { 625 while (prevPtr->nextPtr != bitmapPtr) { 626 prevPtr = prevPtr->nextPtr; 627 } 628 prevPtr->nextPtr = bitmapPtr->nextPtr; 629 } 630 if (bitmapPtr->objRefCount == 0) { 631 ckfree((char *) bitmapPtr); 632 } 633} 634 635/* 636 *---------------------------------------------------------------------- 637 * 638 * Tk_FreeBitmap -- 639 * 640 * This function is called to release a bitmap allocated by Tk_GetBitmap 641 * or TkGetBitmapFromData. 642 * 643 * Results: 644 * None. 645 * 646 * Side effects: 647 * The reference count associated with bitmap is decremented, and it is 648 * officially deallocated if no-one is using it anymore. 649 * 650 *---------------------------------------------------------------------- 651 */ 652 653void 654Tk_FreeBitmap( 655 Display *display, /* Display for which bitmap was allocated. */ 656 Pixmap bitmap) /* Bitmap to be released. */ 657{ 658 Tcl_HashEntry *idHashPtr; 659 TkDisplay *dispPtr = TkGetDisplay(display); 660 661 if (!dispPtr->bitmapInit) { 662 Tcl_Panic("Tk_FreeBitmap called before Tk_GetBitmap"); 663 } 664 665 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); 666 if (idHashPtr == NULL) { 667 Tcl_Panic("Tk_FreeBitmap received unknown bitmap argument"); 668 } 669 FreeBitmap((TkBitmap *) Tcl_GetHashValue(idHashPtr)); 670} 671 672/* 673 *---------------------------------------------------------------------- 674 * 675 * Tk_FreeBitmapFromObj -- 676 * 677 * This function is called to release a bitmap allocated by 678 * Tk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *; it only 679 * gets rid of the hash table entry for this bitmap and clears the cached 680 * value that is normally stored in the object. 681 * 682 * Results: 683 * None. 684 * 685 * Side effects: 686 * The reference count associated with the bitmap represented by objPtr 687 * is decremented, and the bitmap is released to X if there are no 688 * remaining uses for it. 689 * 690 *---------------------------------------------------------------------- 691 */ 692 693void 694Tk_FreeBitmapFromObj( 695 Tk_Window tkwin, /* The window this bitmap lives in. Needed for 696 * the display value. */ 697 Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ 698{ 699 FreeBitmap(GetBitmapFromObj(tkwin, objPtr)); 700} 701 702/* 703 *--------------------------------------------------------------------------- 704 * 705 * FreeBitmapObjProc -- 706 * 707 * This proc is called to release an object reference to a bitmap. 708 * Called when the object's internal rep is released or when the cached 709 * bitmapPtr needs to be changed. 710 * 711 * Results: 712 * None. 713 * 714 * Side effects: 715 * The object reference count is decremented. When both it and the hash 716 * ref count go to zero, the color's resources are released. 717 * 718 *--------------------------------------------------------------------------- 719 */ 720 721static void 722FreeBitmapObjProc( 723 Tcl_Obj *objPtr) /* The object we are releasing. */ 724{ 725 TkBitmap *bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; 726 727 if (bitmapPtr != NULL) { 728 bitmapPtr->objRefCount--; 729 if ((bitmapPtr->objRefCount == 0) 730 && (bitmapPtr->resourceRefCount == 0)) { 731 ckfree((char *) bitmapPtr); 732 } 733 objPtr->internalRep.twoPtrValue.ptr1 = NULL; 734 } 735} 736 737/* 738 *--------------------------------------------------------------------------- 739 * 740 * DupBitmapObjProc -- 741 * 742 * When a cached bitmap object is duplicated, this is called to update 743 * the internal reps. 744 * 745 * Results: 746 * None. 747 * 748 * Side effects: 749 * The color's objRefCount is incremented and the internal rep of the 750 * copy is set to point to it. 751 * 752 *--------------------------------------------------------------------------- 753 */ 754 755static void 756DupBitmapObjProc( 757 Tcl_Obj *srcObjPtr, /* The object we are copying from. */ 758 Tcl_Obj *dupObjPtr) /* The object we are copying to. */ 759{ 760 TkBitmap *bitmapPtr = (TkBitmap *) srcObjPtr->internalRep.twoPtrValue.ptr1; 761 762 dupObjPtr->typePtr = srcObjPtr->typePtr; 763 dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; 764 765 if (bitmapPtr != NULL) { 766 bitmapPtr->objRefCount++; 767 } 768} 769 770/* 771 *---------------------------------------------------------------------- 772 * 773 * Tk_GetBitmapFromData -- 774 * 775 * Given a description of the bits for a bitmap, make a bitmap that has 776 * the given properties. *** NOTE: this function is obsolete and really 777 * shouldn't be used anymore. *** 778 * 779 * Results: 780 * The return value is the X identifer for the desired bitmap (a 781 * one-plane Pixmap), unless it couldn't be created properly. In this 782 * case, None is returned and an error message is left in the interp's 783 * result. The caller should never modify the bitmap that is returned, 784 * and should eventually call Tk_FreeBitmap when the bitmap is no longer 785 * needed. 786 * 787 * Side effects: 788 * The bitmap is added to an internal database with a reference count. 789 * For each call to this function, there should eventually be a call to 790 * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps 791 * aren't needed anymore. 792 * 793 *---------------------------------------------------------------------- 794 */ 795 796 /* ARGSUSED */ 797Pixmap 798Tk_GetBitmapFromData( 799 Tcl_Interp *interp, /* Interpreter to use for error reporting. */ 800 Tk_Window tkwin, /* Window in which bitmap will be used. */ 801 const char *source, /* Bitmap data for bitmap shape. */ 802 int width, int height) /* Dimensions of bitmap. */ 803{ 804 DataKey nameKey; 805 Tcl_HashEntry *dataHashPtr; 806 int isNew; 807 char string[16 + TCL_INTEGER_SPACE]; 808 char *name; 809 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; 810 ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 811 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); 812 813 if (!tsdPtr->initialized) { 814 BitmapInit(dispPtr); 815 } 816 817 nameKey.source = source; 818 nameKey.width = width; 819 nameKey.height = height; 820 dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable, 821 (char *) &nameKey, &isNew); 822 if (!isNew) { 823 name = (char *) Tcl_GetHashValue(dataHashPtr); 824 } else { 825 dispPtr->bitmapAutoNumber++; 826 sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber); 827 name = string; 828 Tcl_SetHashValue(dataHashPtr, name); 829 if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) { 830 Tcl_DeleteHashEntry(dataHashPtr); 831 return TCL_ERROR; 832 } 833 } 834 return Tk_GetBitmap(interp, tkwin, name); 835} 836 837/* 838 *---------------------------------------------------------------------- 839 * 840 * Tk_GetBitmapFromObj -- 841 * 842 * Returns the bitmap referred to by a Tcl object. The bitmap must 843 * already have been allocated via a call to Tk_AllocBitmapFromObj or 844 * Tk_GetBitmap. 845 * 846 * Results: 847 * Returns the Pixmap that matches the tkwin and the string rep of 848 * objPtr. 849 * 850 * Side effects: 851 * If the object is not already a bitmap, the conversion will free any 852 * old internal representation. 853 * 854 *---------------------------------------------------------------------- 855 */ 856 857Pixmap 858Tk_GetBitmapFromObj( 859 Tk_Window tkwin, 860 Tcl_Obj *objPtr) /* The object from which to get pixels. */ 861{ 862 TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr); 863 864 return bitmapPtr->bitmap; 865} 866 867/* 868 *---------------------------------------------------------------------- 869 * 870 * GetBitmapFromObj -- 871 * 872 * Returns the bitmap referred to by a Tcl object. The bitmap must 873 * already have been allocated via a call to Tk_AllocBitmapFromObj or 874 * Tk_GetBitmap. 875 * 876 * Results: 877 * Returns the TkBitmap * that matches the tkwin and the string rep of 878 * objPtr. 879 * 880 * Side effects: 881 * If the object is not already a bitmap, the conversion will free any 882 * old internal representation. 883 * 884 *---------------------------------------------------------------------- 885 */ 886 887static TkBitmap * 888GetBitmapFromObj( 889 Tk_Window tkwin, /* Window in which the bitmap will be used. */ 890 Tcl_Obj *objPtr) /* The object that describes the desired 891 * bitmap. */ 892{ 893 TkBitmap *bitmapPtr; 894 Tcl_HashEntry *hashPtr; 895 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; 896 897 if (objPtr->typePtr != &tkBitmapObjType) { 898 InitBitmapObj(objPtr); 899 } 900 901 bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; 902 if (bitmapPtr != NULL) { 903 if ((bitmapPtr->resourceRefCount > 0) 904 && (Tk_Display(tkwin) == bitmapPtr->display)) { 905 return bitmapPtr; 906 } 907 hashPtr = bitmapPtr->nameHashPtr; 908 FreeBitmapObjProc(objPtr); 909 } else { 910 hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, 911 Tcl_GetString(objPtr)); 912 if (hashPtr == NULL) { 913 goto error; 914 } 915 } 916 917 /* 918 * At this point we've got a hash table entry, off of which hang one or 919 * more TkBitmap structures. See if any of them will work. 920 */ 921 922 for (bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr); 923 bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) { 924 if (Tk_Display(tkwin) == bitmapPtr->display) { 925 objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; 926 bitmapPtr->objRefCount++; 927 return bitmapPtr; 928 } 929 } 930 931 error: 932 Tcl_Panic("GetBitmapFromObj called with non-existent bitmap!"); 933 /* 934 * The following code isn't reached; it's just there to please compilers. 935 */ 936 return NULL; 937} 938 939/* 940 *---------------------------------------------------------------------- 941 * 942 * InitBitmapObj -- 943 * 944 * Bookeeping function to change an objPtr to a bitmap type. 945 * 946 * Results: 947 * None. 948 * 949 * Side effects: 950 * The old internal rep of the object is freed. The internal rep is 951 * cleared. The final form of the object is set by either 952 * Tk_AllocBitmapFromObj or GetBitmapFromObj. 953 * 954 *---------------------------------------------------------------------- 955 */ 956 957static void 958InitBitmapObj( 959 Tcl_Obj *objPtr) /* The object to convert. */ 960{ 961 const Tcl_ObjType *typePtr; 962 963 /* 964 * Free the old internalRep before setting the new one. 965 */ 966 967 Tcl_GetString(objPtr); 968 typePtr = objPtr->typePtr; 969 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { 970 (*typePtr->freeIntRepProc)(objPtr); 971 } 972 objPtr->typePtr = &tkBitmapObjType; 973 objPtr->internalRep.twoPtrValue.ptr1 = NULL; 974} 975 976/* 977 *---------------------------------------------------------------------- 978 * 979 * BitmapInit -- 980 * 981 * Initializes hash tables used by this module. Initializes tables stored 982 * in TkDisplay structure if a TkDisplay pointer is passed in. Also 983 * initializes the thread-local data in the current thread's 984 * ThreadSpecificData structure. 985 * 986 * Results: 987 * None. 988 * 989 * Side effects: 990 * Read the code. 991 * 992 *---------------------------------------------------------------------- 993 */ 994 995static void 996BitmapInit( 997 TkDisplay *dispPtr) /* TkDisplay structure encapsulating 998 * thread-specific data used by this module, 999 * or NULL if unavailable. */ 1000{ 1001 Tcl_Interp *dummy; 1002 ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 1003 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); 1004 1005 /* 1006 * First initialize the data in the ThreadSpecificData strucuture, if 1007 * needed. 1008 */ 1009 1010 if (!tsdPtr->initialized) { 1011 tsdPtr->initialized = 1; 1012 dummy = Tcl_CreateInterp(); 1013 Tcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS); 1014 1015 Tk_DefineBitmap(dummy, "error", (char *) error_bits, 1016 error_width, error_height); 1017 Tk_DefineBitmap(dummy, "gray75", (char *) gray75_bits, 1018 gray75_width, gray75_height); 1019 Tk_DefineBitmap(dummy, "gray50", (char *) gray50_bits, 1020 gray50_width, gray50_height); 1021 Tk_DefineBitmap(dummy, "gray25", (char *) gray25_bits, 1022 gray25_width, gray25_height); 1023 Tk_DefineBitmap(dummy, "gray12", (char *) gray12_bits, 1024 gray12_width, gray12_height); 1025 Tk_DefineBitmap(dummy, "hourglass", (char *) hourglass_bits, 1026 hourglass_width, hourglass_height); 1027 Tk_DefineBitmap(dummy, "info", (char *) info_bits, 1028 info_width, info_height); 1029 Tk_DefineBitmap(dummy, "questhead", (char *) questhead_bits, 1030 questhead_width, questhead_height); 1031 Tk_DefineBitmap(dummy, "question", (char *) question_bits, 1032 question_width, question_height); 1033 Tk_DefineBitmap(dummy, "warning", (char *) warning_bits, 1034 warning_width, warning_height); 1035 1036 TkpDefineNativeBitmaps(); 1037 Tcl_DeleteInterp(dummy); 1038 } 1039 1040 /* 1041 * Was a valid TkDisplay pointer passed? If so, initialize the Bitmap 1042 * module tables in that structure. 1043 */ 1044 1045 if (dispPtr != NULL) { 1046 dispPtr->bitmapInit = 1; 1047 Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS); 1048 Tcl_InitHashTable(&dispPtr->bitmapDataTable, 1049 sizeof(DataKey) / sizeof(int)); 1050 1051 /* 1052 * The call below is tricky: can't use sizeof(IdKey) because it gets 1053 * padded with extra unpredictable bytes on some 64-bit machines. 1054 */ 1055 1056 /* 1057 * The comment above doesn't make sense... 1058 */ 1059 1060 Tcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS); 1061 } 1062} 1063 1064/* 1065 *---------------------------------------------------------------------- 1066 * 1067 * TkReadBitmapFile -- 1068 * 1069 * Loads a bitmap image in X bitmap format into the specified drawable. 1070 * This is equivelent to the XReadBitmapFile in X. 1071 * 1072 * Results: 1073 * Sets the size, hotspot, and bitmap on success. 1074 * 1075 * Side effects: 1076 * Creates a new bitmap from the file data. 1077 * 1078 *---------------------------------------------------------------------- 1079 */ 1080 1081int 1082TkReadBitmapFile( 1083 Display *display, 1084 Drawable d, 1085 const char *filename, 1086 unsigned int *width_return, 1087 unsigned int *height_return, 1088 Pixmap *bitmap_return, 1089 int *x_hot_return, 1090 int *y_hot_return) 1091{ 1092 char *data; 1093 1094 data = TkGetBitmapData(NULL, NULL, (char *) filename, 1095 (int *) width_return, (int *) height_return, x_hot_return, 1096 y_hot_return); 1097 if (data == NULL) { 1098 return BitmapFileInvalid; 1099 } 1100 1101 *bitmap_return = XCreateBitmapFromData(display, d, data, *width_return, 1102 *height_return); 1103 ckfree(data); 1104 return BitmapSuccess; 1105} 1106 1107/* 1108 *---------------------------------------------------------------------- 1109 * 1110 * TkDebugBitmap -- 1111 * 1112 * This function returns debugging information about a bitmap. 1113 * 1114 * Results: 1115 * The return value is a list with one sublist for each TkBitmap 1116 * corresponding to "name". Each sublist has two elements that contain 1117 * the resourceRefCount and objRefCount fields from the TkBitmap 1118 * structure. 1119 * 1120 * Side effects: 1121 * None. 1122 * 1123 *---------------------------------------------------------------------- 1124 */ 1125 1126Tcl_Obj * 1127TkDebugBitmap( 1128 Tk_Window tkwin, /* The window in which the bitmap will be used 1129 * (not currently used). */ 1130 char *name) /* Name of the desired color. */ 1131{ 1132 TkBitmap *bitmapPtr; 1133 Tcl_HashEntry *hashPtr; 1134 Tcl_Obj *resultPtr, *objPtr; 1135 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; 1136 1137 resultPtr = Tcl_NewObj(); 1138 hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name); 1139 if (hashPtr != NULL) { 1140 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr); 1141 if (bitmapPtr == NULL) { 1142 Tcl_Panic("TkDebugBitmap found empty hash table entry"); 1143 } 1144 for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) { 1145 objPtr = Tcl_NewObj(); 1146 Tcl_ListObjAppendElement(NULL, objPtr, 1147 Tcl_NewIntObj(bitmapPtr->resourceRefCount)); 1148 Tcl_ListObjAppendElement(NULL, objPtr, 1149 Tcl_NewIntObj(bitmapPtr->objRefCount)); 1150 Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); 1151 } 1152 } 1153 return resultPtr; 1154} 1155 1156/* 1157 *---------------------------------------------------------------------- 1158 * 1159 * TkGetBitmapPredefTable -- 1160 * 1161 * This function is used by tkMacBitmap.c to access the thread-specific 1162 * predefBitmap table that maps from the names of the predefined bitmaps 1163 * to data associated with those bitmaps. It is required because the 1164 * table is allocated in thread-local storage and is not visible outside 1165 * this file. 1166 1167 * Results: 1168 * Returns a pointer to the predefined bitmap hash table for the current 1169 * thread. 1170 * 1171 * Side effects: 1172 * None. 1173 * 1174 *---------------------------------------------------------------------- 1175 */ 1176 1177Tcl_HashTable * 1178TkGetBitmapPredefTable(void) 1179{ 1180 ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 1181 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); 1182 1183 return &tsdPtr->predefBitmapTable; 1184} 1185 1186/* 1187 * Local Variables: 1188 * mode: c 1189 * c-basic-offset: 4 1190 * fill-column: 78 1191 * End: 1192 */ 1193