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