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

Annotation of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkbitmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: text/plain
File size: 37323 byte(s)
License and property (keyword) changes.
1 dashley 69 /* $Header$ */
2 dashley 25
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 dashley 69 /* End of tkbitmap.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25