OSDN Git Service

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