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.
8 * Copyright 1990-1992 Regents of the University of California
9 * Permission to use, copy, modify, and distribute this
10 * software and its documentation for any purpose and without
11 * fee is hereby granted, provided that the above copyright
12 * notice appear in all copies. The University of California
13 * makes no representations about the suitability of this
14 * software for any purpose. It is provided "as is" without
15 * express or implied warranty.
19 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkBitmap.c,v 1.16 92/08/24 09:45:43 ouster Exp $ SPRITE (Berkeley)";
26 * The includes below are for pre-defined bitmaps.
29 #include "bitmaps/gray50"
30 #include "bitmaps/gray25"
33 * One of the following data structures exists for each bitmap that is
34 * currently in use. Each structure is indexed with both "idTable" and
39 Pixmap bitmap
; /* X identifier for bitmap. None means this
40 * bitmap was created by Tk_DefineBitmap
41 * and it isn't currently in use. */
42 unsigned int width
, height
; /* Dimensions of bitmap. */
43 Display
*display
; /* Display for which bitmap is valid. */
44 int refCount
; /* Number of active uses of bitmap. */
45 Tcl_HashEntry
*hashPtr
; /* Entry in nameTable for this structure
46 * (needed when deleting). */
50 * Hash table to map from a textual description of a bitmap to the
51 * TkBitmap record for the bitmap, and key structure used in that
55 static Tcl_HashTable nameTable
;
57 Tk_Uid name
; /* Textual name for desired bitmap. */
58 Screen
*screen
; /* Screen for which bitmap will be used. */
62 * Hash table that maps from bitmap identifiers to the TkBitmap structure
63 * for the bitmap. This table is indexed by Bitmap ids, and is used by
67 static Tcl_HashTable idTable
;
70 * For each call to Tk_DefineBitmap one of the following structures is
71 * created to hold information about the bitmap.
75 char *source
; /* Bits for bitmap. */
76 unsigned int width
, height
; /* Dimensions of bitmap. */
80 * Hash table create by Tk_DefineBitmap to map from a name to a
81 * collection of in-core data about a bitmap. The table is
82 * indexed by the address of the data for the bitmap, and the entries
83 * contain pointers to PredefBitmap structures.
86 static Tcl_HashTable predefTable
;
89 * Hash table used by Tk_GetBitmapFromData to map from a collection
90 * of in-core data about a bitmap to a Tk_Uid giving an automatically-
91 * generated name for the bitmap:
94 static Tcl_HashTable dataTable
;
96 char *source
; /* Bitmap bits. */
97 unsigned int width
, height
; /* Dimensions of bitmap. */
100 static int initialized
= 0; /* 0 means static structures haven't been
101 * initialized yet. */
104 * Forward declarations for procedures defined in this file:
107 static void BitmapInit
_ANSI_ARGS_((void));
110 *----------------------------------------------------------------------
114 * Given a string describing a bitmap, locate (or create if necessary)
115 * a bitmap that fits the description.
118 * The return value is the X identifer for the desired bitmap
119 * (i.e. a Pixmap with a single plane), unless string couldn't be
120 * parsed correctly. In this case, None is returned and an error
121 * message is left in interp->result. The caller should never
122 * modify the bitmap that is returned, and should eventually call
123 * Tk_FreeBitmap when the bitmap is no longer needed.
126 * The bitmap is added to an internal database with a reference count.
127 * For each call to this procedure, there should eventually be a call
128 * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
129 * aren't needed anymore.
131 *----------------------------------------------------------------------
135 Tk_GetBitmap(interp
, tkwin
, string
)
136 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
137 Tk_Window tkwin
; /* Window in which bitmap will be used. */
138 Tk_Uid string
; /* Description of bitmap. See manual entry
139 * for details on legal syntax. */
142 Tcl_HashEntry
*nameHashPtr
, *idHashPtr
, *predefHashPtr
;
143 register TkBitmap
*bitmapPtr
;
144 PredefBitmap
*predefPtr
;
147 unsigned int width
, height
;
155 key
.screen
= Tk_Screen(tkwin
);
156 nameHashPtr
= Tcl_CreateHashEntry(&nameTable
, (char *) &key
, &new);
158 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(nameHashPtr
);
159 bitmapPtr
->refCount
++;
160 return bitmapPtr
->bitmap
;
164 * No suitable bitmap exists. Create a new bitmap from the
165 * information contained in the string. If the string starts
166 * with "@" then the rest of the string is a file name containing
167 * the bitmap. Otherwise the string must refer to a bitmap
168 * defined by a call to Tk_DefineBitmap.
171 if (*string
== '@') {
172 string
= Tcl_TildeSubst(interp
, string
+ 1);
173 if (string
== NULL
) {
176 if (XReadBitmapFile(Tk_Display(tkwin
),
177 RootWindowOfScreen(Tk_Screen(tkwin
)),
178 string
, &width
, &height
, &bitmap
, &dummy2
, &dummy2
)
180 Tcl_AppendResult(interp
, "error reading bitmap file \"", string
,
181 "\"", (char *) NULL
);
185 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, string
);
186 if (predefHashPtr
== NULL
) {
187 Tcl_AppendResult(interp
, "bitmap \"", string
,
188 "\" not defined", (char *) NULL
);
191 predefPtr
= (PredefBitmap
*) Tcl_GetHashValue(predefHashPtr
);
192 width
= predefPtr
->width
;
193 height
= predefPtr
->height
;
194 bitmap
= XCreateBitmapFromData(Tk_Display(tkwin
),
195 RootWindowOfScreen(Tk_Screen(tkwin
)), predefPtr
->source
,
200 * Add information about this bitmap to our database.
203 bitmapPtr
= (TkBitmap
*) ckalloc(sizeof(TkBitmap
));
204 bitmapPtr
->bitmap
= bitmap
;
205 bitmapPtr
->width
= width
;
206 bitmapPtr
->height
= height
;
207 bitmapPtr
->display
= Tk_Display(tkwin
);
208 bitmapPtr
->refCount
= 1;
209 bitmapPtr
->hashPtr
= nameHashPtr
;
210 idHashPtr
= Tcl_CreateHashEntry(&idTable
, (char *) bitmapPtr
->bitmap
,
213 /* deh patched to support multiple displays */
214 /* panic("bitmap already registered in Tk_GetBitmap"); */
215 bitmapPtr
->refCount
= 1000;
217 Tcl_SetHashValue(nameHashPtr
, bitmapPtr
);
218 Tcl_SetHashValue(idHashPtr
, bitmapPtr
);
219 return bitmapPtr
->bitmap
;
222 Tcl_DeleteHashEntry(nameHashPtr
);
227 *----------------------------------------------------------------------
231 * This procedure associates a textual name with a binary bitmap
232 * description, so that the name may be used to refer to the
233 * bitmap in future calls to Tk_GetBitmap.
236 * A standard Tcl result. If an error occurs then TCL_ERROR is
237 * returned and a message is left in interp->result.
240 * "Name" is entered into the bitmap table and may be used from
241 * here on to refer to the given bitmap.
243 *----------------------------------------------------------------------
247 Tk_DefineBitmap(interp
, name
, source
, width
, height
)
248 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
249 Tk_Uid name
; /* Name to use for bitmap. Must not already
250 * be defined as a bitmap. */
251 char *source
; /* Address of bits for bitmap. */
252 unsigned int width
; /* Width of bitmap. */
253 unsigned int height
; /* Height of bitmap. */
256 Tcl_HashEntry
*predefHashPtr
;
257 PredefBitmap
*predefPtr
;
263 predefHashPtr
= Tcl_CreateHashEntry(&predefTable
, name
, &new);
265 Tcl_AppendResult(interp
, "bitmap \"", name
,
266 "\" is already defined", (char *) NULL
);
269 predefPtr
= (PredefBitmap
*) malloc(sizeof(PredefBitmap
));
270 predefPtr
->source
= source
;
271 predefPtr
->width
= width
;
272 predefPtr
->height
= height
;
273 Tcl_SetHashValue(predefHashPtr
, predefPtr
);
278 *--------------------------------------------------------------
282 * Given a bitmap, return a textual string identifying the
286 * The return value is the string name associated with bitmap.
291 *--------------------------------------------------------------
295 Tk_NameOfBitmap(bitmap
)
296 Pixmap bitmap
; /* Bitmap whose name is wanted. */
298 Tcl_HashEntry
*idHashPtr
;
303 panic("Tk_NameOfBitmap received unknown bitmap argument");
306 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
307 if (idHashPtr
== NULL
) {
310 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
311 return ((NameKey
*) bitmapPtr
->hashPtr
->key
.words
)->name
;
315 *--------------------------------------------------------------
319 * Given a bitmap managed by this module, returns the width
320 * and height of the bitmap..
323 * The words at *widthPtr and *heightPtr are filled in with
324 * the dimenstions of bitmap.
327 * If bitmap isn't managed by this module then the procedure
330 *--------------------------------------------------------------
334 Tk_SizeOfBitmap(bitmap
, widthPtr
, heightPtr
)
335 Pixmap bitmap
; /* Bitmap whose size is wanted. */
336 unsigned int *widthPtr
; /* Store bitmap width here. */
337 unsigned int *heightPtr
; /* Store bitmap height here. */
339 Tcl_HashEntry
*idHashPtr
;
344 panic("Tk_SizeOfBitmap received unknown bitmap argument");
347 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
348 if (idHashPtr
== NULL
) {
351 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
352 *widthPtr
= bitmapPtr
->width
;
353 *heightPtr
= bitmapPtr
->height
;
357 *----------------------------------------------------------------------
361 * This procedure is called to release a bitmap allocated by
362 * Tk_GetBitmap or TkGetBitmapFromData.
368 * The reference count associated with bitmap is decremented, and
369 * it is officially deallocated if no-one is using it anymore.
371 *----------------------------------------------------------------------
375 Tk_FreeBitmap(bitmap
)
376 Pixmap bitmap
; /* Bitmap to be released. */
378 Tcl_HashEntry
*idHashPtr
;
379 register TkBitmap
*bitmapPtr
;
382 panic("Tk_FreeBitmap called before Tk_GetBitmap");
385 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
386 if (idHashPtr
== NULL
) {
387 panic("Tk_FreeBitmap received unknown bitmap argument");
389 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
390 bitmapPtr
->refCount
--;
391 if (bitmapPtr
->refCount
== 0) {
392 XFreePixmap(bitmapPtr
->display
, bitmapPtr
->bitmap
);
393 Tcl_DeleteHashEntry(idHashPtr
);
394 Tcl_DeleteHashEntry(bitmapPtr
->hashPtr
);
395 ckfree((char *) bitmapPtr
);
400 *----------------------------------------------------------------------
402 * Tk_GetBitmapFromData --
404 * Given a description of the bits for a bitmap, make a bitmap that
405 * has the given properties.
408 * The return value is the X identifer for the desired bitmap
409 * (a one-plane Pixmap), unless it couldn't be created properly.
410 * In this case, None is returned and an error message is left in
411 * interp->result. The caller should never modify the bitmap that
412 * is returned, and should eventually call Tk_FreeBitmap when the
413 * bitmap is no longer needed.
416 * The bitmap is added to an internal database with a reference count.
417 * For each call to this procedure, there should eventually be a call
418 * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
419 * aren't needed anymore.
421 *----------------------------------------------------------------------
426 Tk_GetBitmapFromData(interp
, tkwin
, source
, width
, height
)
427 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
428 Tk_Window tkwin
; /* Window in which bitmap will be used. */
429 char *source
; /* Bitmap data for bitmap shape. */
430 unsigned int width
, height
; /* Dimensions of bitmap. */
433 Tcl_HashEntry
*dataHashPtr
;
434 Tk_Uid name
= NULL
; /* Initialization need only to prevent
435 * compiler warning. */
437 static autoNumber
= 0;
447 dataHashPtr
= Tcl_CreateHashEntry(&dataTable
, (char *) &key
, &new);
449 name
= (Tk_Uid
) Tcl_GetHashValue(dataHashPtr
);
452 sprintf(string
, "_tk%d", autoNumber
);
453 name
= Tk_GetUid(string
);
454 Tcl_SetHashValue(dataHashPtr
, name
);
455 if (Tk_DefineBitmap(interp
, name
, source
, width
, height
) != TCL_OK
) {
456 Tcl_DeleteHashEntry(dataHashPtr
);
460 return Tk_GetBitmap(interp
, tkwin
, name
);
464 *----------------------------------------------------------------------
468 * Initialize the structures used for bitmap management.
476 *----------------------------------------------------------------------
484 dummy
= Tcl_CreateInterp();
486 Tcl_InitHashTable(&nameTable
, sizeof(NameKey
)/sizeof(int));
487 Tcl_InitHashTable(&dataTable
, sizeof(DataKey
)/sizeof(int));
488 Tcl_InitHashTable(&predefTable
, TCL_ONE_WORD_KEYS
);
489 Tcl_InitHashTable(&idTable
, TCL_ONE_WORD_KEYS
);
491 Tk_DefineBitmap(dummy
, Tk_GetUid("gray50"), (char *)gray50_bits
,
492 gray50_width
, gray50_height
);
493 Tk_DefineBitmap(dummy
, Tk_GetUid("gray25"),
494 (char *)gray25_bits
, gray25_width
, gray25_height
);
495 Tcl_DeleteInterp(dummy
);