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 *----------------------------------------------------------------------
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. */
143 Tcl_HashEntry
*nameHashPtr
, *idHashPtr
, *predefHashPtr
;
144 register TkBitmap
*bitmapPtr
;
145 PredefBitmap
*predefPtr
;
148 unsigned int width
, height
;
156 key
.screen
= Tk_Screen(tkwin
);
157 nameHashPtr
= Tcl_CreateHashEntry(&nameTable
, (char *) &key
, &new);
159 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(nameHashPtr
);
160 bitmapPtr
->refCount
++;
161 return bitmapPtr
->bitmap
;
165 * No suitable bitmap exists. Create a new bitmap from the
166 * information contained in the string. If the string starts
167 * with "@" then the rest of the string is a file name containing
168 * the bitmap. Otherwise the string must refer to a bitmap
169 * defined by a call to Tk_DefineBitmap.
172 if (*string
== '@') {
173 string
= Tcl_TildeSubst(interp
, string
+ 1);
174 if (string
== NULL
) {
177 if (XReadBitmapFile(Tk_Display(tkwin
),
178 RootWindowOfScreen(Tk_Screen(tkwin
)),
179 string
, &width
, &height
, &bitmap
, &dummy2
, &dummy2
)
181 Tcl_AppendResult(interp
, "error reading bitmap file \"", string
,
182 "\"", (char *) NULL
);
186 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, string
);
187 if (predefHashPtr
== NULL
) {
188 Tcl_AppendResult(interp
, "bitmap \"", string
,
189 "\" not defined", (char *) NULL
);
192 predefPtr
= (PredefBitmap
*) Tcl_GetHashValue(predefHashPtr
);
193 width
= predefPtr
->width
;
194 height
= predefPtr
->height
;
195 bitmap
= XCreateBitmapFromData(Tk_Display(tkwin
),
196 RootWindowOfScreen(Tk_Screen(tkwin
)), predefPtr
->source
,
201 * Add information about this bitmap to our database.
204 bitmapPtr
= (TkBitmap
*) ckalloc(sizeof(TkBitmap
));
205 bitmapPtr
->bitmap
= bitmap
;
206 bitmapPtr
->width
= width
;
207 bitmapPtr
->height
= height
;
208 bitmapPtr
->display
= Tk_Display(tkwin
);
209 bitmapPtr
->refCount
= 1;
210 bitmapPtr
->hashPtr
= nameHashPtr
;
211 idHashPtr
= Tcl_CreateHashEntry(&idTable
, (char *) bitmapPtr
->bitmap
,
214 /* deh patched to support multiple displays */
215 /* panic("bitmap already registered in Tk_GetBitmap"); */
216 bitmapPtr
->refCount
= 1000;
218 Tcl_SetHashValue(nameHashPtr
, bitmapPtr
);
219 Tcl_SetHashValue(idHashPtr
, bitmapPtr
);
220 return bitmapPtr
->bitmap
;
223 Tcl_DeleteHashEntry(nameHashPtr
);
228 *----------------------------------------------------------------------
232 * This procedure associates a textual name with a binary bitmap
233 * description, so that the name may be used to refer to the
234 * bitmap in future calls to Tk_GetBitmap.
237 * A standard Tcl result. If an error occurs then TCL_ERROR is
238 * returned and a message is left in interp->result.
241 * "Name" is entered into the bitmap table and may be used from
242 * here on to refer to the given bitmap.
244 *----------------------------------------------------------------------
249 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
250 Tk_Uid name
, /* Name to use for bitmap. Must not already
251 * be defined as a bitmap. */
252 char *source
, /* Address of bits for bitmap. */
253 unsigned int width
, /* Width of bitmap. */
254 unsigned int height
/* Height of bitmap. */
258 Tcl_HashEntry
*predefHashPtr
;
259 PredefBitmap
*predefPtr
;
265 predefHashPtr
= Tcl_CreateHashEntry(&predefTable
, name
, &new);
267 Tcl_AppendResult(interp
, "bitmap \"", name
,
268 "\" is already defined", (char *) NULL
);
271 predefPtr
= (PredefBitmap
*) malloc(sizeof(PredefBitmap
));
272 predefPtr
->source
= source
;
273 predefPtr
->width
= width
;
274 predefPtr
->height
= height
;
275 Tcl_SetHashValue(predefHashPtr
, predefPtr
);
280 *--------------------------------------------------------------
284 * Given a bitmap, return a textual string identifying the
288 * The return value is the string name associated with bitmap.
293 *--------------------------------------------------------------
298 Pixmap bitmap
/* Bitmap whose name is wanted. */
301 Tcl_HashEntry
*idHashPtr
;
306 panic("Tk_NameOfBitmap received unknown bitmap argument");
309 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
310 if (idHashPtr
== NULL
) {
313 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
314 return ((NameKey
*) bitmapPtr
->hashPtr
->key
.words
)->name
;
318 *--------------------------------------------------------------
322 * Given a bitmap managed by this module, returns the width
323 * and height of the bitmap..
326 * The words at *widthPtr and *heightPtr are filled in with
327 * the dimenstions of bitmap.
330 * If bitmap isn't managed by this module then the procedure
333 *--------------------------------------------------------------
338 Pixmap bitmap
, /* Bitmap whose size is wanted. */
339 unsigned int *widthPtr
, /* Store bitmap width here. */
340 unsigned int *heightPtr
/* Store bitmap height here. */
343 Tcl_HashEntry
*idHashPtr
;
348 panic("Tk_SizeOfBitmap received unknown bitmap argument");
351 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
352 if (idHashPtr
== NULL
) {
355 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
356 *widthPtr
= bitmapPtr
->width
;
357 *heightPtr
= bitmapPtr
->height
;
361 *----------------------------------------------------------------------
365 * This procedure is called to release a bitmap allocated by
366 * Tk_GetBitmap or TkGetBitmapFromData.
372 * The reference count associated with bitmap is decremented, and
373 * it is officially deallocated if no-one is using it anymore.
375 *----------------------------------------------------------------------
380 Pixmap bitmap
/* Bitmap to be released. */
383 Tcl_HashEntry
*idHashPtr
;
384 register TkBitmap
*bitmapPtr
;
387 panic("Tk_FreeBitmap called before Tk_GetBitmap");
390 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
391 if (idHashPtr
== NULL
) {
392 panic("Tk_FreeBitmap received unknown bitmap argument");
394 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
395 bitmapPtr
->refCount
--;
396 if (bitmapPtr
->refCount
== 0) {
397 XFreePixmap(bitmapPtr
->display
, bitmapPtr
->bitmap
);
398 Tcl_DeleteHashEntry(idHashPtr
);
399 Tcl_DeleteHashEntry(bitmapPtr
->hashPtr
);
400 ckfree((char *) bitmapPtr
);
405 *----------------------------------------------------------------------
407 * Tk_GetBitmapFromData --
409 * Given a description of the bits for a bitmap, make a bitmap that
410 * has the given properties.
413 * The return value is the X identifer for the desired bitmap
414 * (a one-plane Pixmap), unless it couldn't be created properly.
415 * In this case, None is returned and an error message is left in
416 * interp->result. The caller should never modify the bitmap that
417 * is returned, and should eventually call Tk_FreeBitmap when the
418 * bitmap is no longer needed.
421 * The bitmap is added to an internal database with a reference count.
422 * For each call to this procedure, there should eventually be a call
423 * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
424 * aren't needed anymore.
426 *----------------------------------------------------------------------
431 Tk_GetBitmapFromData (
432 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
433 Tk_Window tkwin
, /* Window in which bitmap will be used. */
434 char *source
, /* Bitmap data for bitmap shape. */
436 unsigned int height
/* Dimensions of bitmap. */
440 Tcl_HashEntry
*dataHashPtr
;
441 Tk_Uid name
= NULL
; /* Initialization need only to prevent
442 * compiler warning. */
444 static int autoNumber
= 0;
454 dataHashPtr
= Tcl_CreateHashEntry(&dataTable
, (char *) &key
, &new);
456 name
= (Tk_Uid
) Tcl_GetHashValue(dataHashPtr
);
459 sprintf(string
, "_tk%d", autoNumber
);
460 name
= Tk_GetUid(string
);
461 Tcl_SetHashValue(dataHashPtr
, name
);
462 if (Tk_DefineBitmap(interp
, name
, source
, width
, height
) != TCL_OK
) {
463 Tcl_DeleteHashEntry(dataHashPtr
);
467 return Tk_GetBitmap(interp
, tkwin
, name
);
471 *----------------------------------------------------------------------
475 * Initialize the structures used for bitmap management.
483 *----------------------------------------------------------------------
491 dummy
= Tcl_CreateInterp();
493 Tcl_InitHashTable(&nameTable
, sizeof(NameKey
)/sizeof(int));
494 Tcl_InitHashTable(&dataTable
, sizeof(DataKey
)/sizeof(int));
495 Tcl_InitHashTable(&predefTable
, TCL_ONE_WORD_KEYS
);
496 Tcl_InitHashTable(&idTable
, TCL_ONE_WORD_KEYS
);
498 Tk_DefineBitmap(dummy
, Tk_GetUid("gray50"), (char *)gray50_bits
,
499 gray50_width
, gray50_height
);
500 Tk_DefineBitmap(dummy
, Tk_GetUid("gray25"),
501 (char *)gray25_bits
, gray25_width
, gray25_height
);
502 Tcl_DeleteInterp(dummy
);