tkBitmap.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:36k
源码类别:

通讯编程

开发平台:

Visual C++

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