/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkbitmap.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkbitmap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.25  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25