4 * This file maintains a database of read-only pixmaps for the Tk
5 * toolkit. This allows pixmaps to be shared between widgets and
6 * also avoids interactions with the X server.
8 * Copyright 1992 by Sven Delmas
10 * This source is based upon the file tkBitmap.c from:
12 * Copyright 1990-1992 Regents of the University of California
13 * Permission to use, copy, modify, and distribute this
14 * software and its documentation for any purpose and without
15 * fee is hereby granted, provided that the above copyright
16 * notice appear in all copies. The University of California
17 * makes no representations about the suitability of this
18 * software for any purpose. It is provided "as is" without
19 * express or implied warranty.
20 * file: /user6/ouster/wish/RCS/tkBitmap.c,v 1.16
21 * 92/08/24 09:45:43 ouster Exp $ SPRITE (Berkeley);
27 static char *AtFSid
= "$Header: tkPixmap.c[1.1] Mon Sep 28 14:12:35 1992 garfield@cs.tu-berlin.de frozen $";
34 * The includes below are for pre-defined bitmaps.
37 #include "bitmaps/gray50"
38 #include "bitmaps/gray25"
41 * Include the xpm 3 defines for color pixmaps
47 * One of the following data structures exists for each bitmap that is
48 * currently in use. Each structure is indexed with both "idTable" and
53 Pixmap bitmap
; /* X identifier for bitmap. None means this
54 * bitmap was created by Tk_DefinePixmap
55 * and it isn't currently in use. */
56 unsigned int width
, height
; /* Dimensions of bitmap. */
57 Display
*display
; /* Display for which bitmap is valid. */
58 int refCount
; /* Number of active uses of bitmap. */
59 Tcl_HashEntry
*hashPtr
; /* Entry in nameTable for this structure
60 * (needed when deleting). */
64 * Hash table to map from a textual description of a bitmap to the
65 * TkBitmap record for the bitmap, and key structure used in that
69 static Tcl_HashTable nameTable
;
71 Tk_Uid name
; /* Textual name for desired bitmap. */
72 Screen
*screen
; /* Screen for which bitmap will be used. */
76 * Hash table that maps from bitmap identifiers to the TkBitmap structure
77 * for the pixmap. This table is indexed by Bitmap ids, and is used by
81 static Tcl_HashTable idTable
;
84 * For each call to Tk_DefinePixmap one of the following structures is
85 * created to hold information about the pixmap.
89 char *source
; /* Bits for bitmap. */
90 Pixmap pixmap
; /* Pre-defined pixmap */
91 unsigned int width
, height
; /* Dimensions of bitmap. */
95 * Hash table create by Tk_DefinePixmap to map from a name to a
96 * collection of in-core data about a bitmap. The table is
97 * indexed by the address of the data for the bitmap, and the entries
98 * contain pointers to PredefBitmap structures.
101 static Tcl_HashTable predefTable
;
104 * Hash table used by Tk_GetPixmapFromData to map from a collection
105 * of in-core data about a bitmap to a Tk_Uid giving an automatically-
106 * generated name for the bitmap:
109 static Tcl_HashTable dataTable
;
111 char *source
; /* Bitmap bits. */
112 unsigned int width
, height
; /* Dimensions of bitmap. */
115 static int initialized
= 0; /* 0 means static structures haven't been
116 * initialized yet. */
119 * Forward declarations for procedures defined in this file:
122 static void PixmapInit
_ANSI_ARGS_((Tk_Window tkwin
));
125 *----------------------------------------------------------------------
129 * Given a string describing a bitmap or pixmap, locate (or create
130 * if necessary) a pixmap that fits the description.
133 * The return value is the X identifer for the desired pixmap,
134 * unless string couldn't be parsed correctly. In this case,
135 * None is returned and an error message is left in
136 * interp->result. The caller should never modify the pixmap
137 * that is returned, and should eventually call Tk_FreePixmap
138 * when the pixmap is no longer needed.
141 * The pixmap is added to an internal database with a reference count.
142 * For each call to this procedure, there should eventually be a call
143 * to Tk_FreePixmap, so that the database can be cleaned up when pixmaps
144 * aren't needed anymore.
146 *----------------------------------------------------------------------
149 Tk_GetPixmap(interp
, tkwin
, string
)
150 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
151 Tk_Window tkwin
; /* Window in which pixmap will be used. */
152 Tk_Uid string
; /* Description of pixmap. See manual entry
153 * for details on legal syntax. */
156 Tcl_HashEntry
*nameHashPtr
, *idHashPtr
, *predefHashPtr
;
157 register TkBitmap
*bitmapPtr
;
158 PredefBitmap
*predefPtr
;
162 unsigned int width
, height
;
164 XpmAttributes xpm_attributes
;
165 Display
*dpy
= Tk_Display(tkwin
);
172 key
.screen
= Tk_Screen(tkwin
);
173 nameHashPtr
= Tcl_CreateHashEntry(&nameTable
, (char *) &key
, &new);
175 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(nameHashPtr
);
176 bitmapPtr
->refCount
++;
177 return bitmapPtr
->bitmap
;
181 * No suitable bitmap exists. Create a new bitmap from the
182 * information contained in the string. If the string starts
183 * with "@" then the rest of the string is a file name containing
184 * the bitmap. Otherwise the string must refer to a bitmap
185 * defined by a call to Tk_DefinePixmap.
188 if (*string
== '@') {
189 string
= Tcl_TildeSubst(interp
, string
+ 1);
190 if (string
== NULL
) {
194 if (XReadBitmapFile(dpy
, RootWindowOfScreen(Tk_Screen(tkwin
)),
195 string
, &width
, &height
, &bitmap_shape
, &dummy2
, &dummy2
)
198 xpm_attributes
.visual
= Tk_DefaultVisual(Tk_Screen(tkwin
));
199 xpm_attributes
.colormap
= Tk_DefaultColormap(Tk_Screen(tkwin
));
200 xpm_attributes
.depth
= Tk_DefaultDepth(Tk_Screen(tkwin
));
201 xpm_attributes
.valuemask
= XpmVisual
| XpmColormap
| XpmDepth
;
203 if (XpmReadFileToPixmap(dpy
, RootWindowOfScreen(Tk_Screen(tkwin
)),
204 string
, &bitmap
, &bitmap_shape
,
205 &xpm_attributes
) != BitmapSuccess
) {
206 Tcl_AppendResult(interp
, "error reading bitmap file \"",
207 string
, "\"", (char *) NULL
);
210 width
= xpm_attributes
.width
;
211 height
= xpm_attributes
.height
;
212 XpmFreeAttributes(&xpm_attributes
);
215 bitmap
= XCreatePixmap(dpy
, RootWindowOfScreen(Tk_Screen(tkwin
)),
217 Tk_DefaultDepth(Tk_Screen(tkwin
)));
218 XCopyPlane(dpy
, bitmap_shape
, bitmap
,
219 Tk_DefaultGC(Tk_Screen(tkwin
)),
220 0, 0, width
, height
, 0, 0, 1);
223 /* first try for a display-specific version */
224 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, (char *) &key
);
225 if (predefHashPtr
== NULL
) {
226 /* try for a non-display specific version */
227 key
.screen
= (Screen
*) NULL
;
228 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, (char *) &key
);
229 if (predefHashPtr
== NULL
) {
231 Tcl_AppendResult(interp
, "pixmap \"", string
,
232 "\" not defined", (char *) NULL
);
236 predefPtr
= (PredefBitmap
*) Tcl_GetHashValue(predefHashPtr
);
237 width
= predefPtr
->width
;
238 height
= predefPtr
->height
;
239 if (predefPtr
->source
!= NULL
) {
241 XCreateBitmapFromData(dpy
, Tk_DefaultRootWindow(dpy
),
242 predefPtr
->source
, width
, height
);
243 bitmap
= XCreatePixmap(dpy
, RootWindowOfScreen(Tk_Screen(tkwin
)),
245 Tk_DefaultDepth(Tk_Screen(tkwin
)));
246 XCopyPlane(dpy
, bitmap_shape
, bitmap
,
247 Tk_DefaultGC(Tk_Screen(tkwin
)),
248 0, 0, width
, height
, 0, 0, 1);
250 if (predefPtr
->pixmap
!= None
) {
251 bitmap
= predefPtr
->pixmap
;
254 XCreatePixmap(dpy
, RootWindowOfScreen(Tk_Screen(tkwin
)),
256 Tk_DefaultDepth(Tk_Screen(tkwin
)));
262 * Add information about this bitmap to our database.
265 bitmapPtr
= (TkBitmap
*) ckalloc(sizeof(TkBitmap
));
266 bitmapPtr
->bitmap
= bitmap
;
267 bitmapPtr
->width
= width
;
268 bitmapPtr
->height
= height
;
269 bitmapPtr
->display
= dpy
;
270 bitmapPtr
->refCount
= 1;
271 bitmapPtr
->hashPtr
= nameHashPtr
;
272 idHashPtr
= Tcl_CreateHashEntry(&idTable
, (char *) bitmapPtr
->bitmap
,
275 /* deh patched to support multiple displays */
276 /* panic("pixmap already registered in Tk_GetPixmap"); */
277 bitmapPtr
->refCount
= 1000;
279 Tcl_SetHashValue(nameHashPtr
, bitmapPtr
);
280 Tcl_SetHashValue(idHashPtr
, bitmapPtr
);
281 return bitmapPtr
->bitmap
;
284 Tcl_DeleteHashEntry(nameHashPtr
);
289 *----------------------------------------------------------------------
293 * This procedure associates a textual name with a binary pixmap
294 * description, so that the name may be used to refer to the
295 * pixmap in future calls to Tk_GetPixmap. The pixmap can
296 * be pre-created by the user, or can be created later
297 * by Tk_GetPixmap(). Since pixmaps are display-specific,
298 * a user supplied pixmap will be associated with tkwin's display.
299 * If pixmap is given as None, then a new pixmap will be created
300 * by Tk_GetPixmap for each unique display.
303 * A standard Tcl result. If an error occurs then TCL_ERROR is
304 * returned and a message is left in interp->result.
307 * "Name" is entered into the pixmap table and may be used from
308 * here on to refer to the given pixmap.
310 *----------------------------------------------------------------------
314 Tk_DefinePixmap(interp
, name
, tkwin
, pixmap
, source
, width
, height
)
315 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
316 Tk_Uid name
; /* Name to use for bitmap. Must not already
317 * be defined as a bitmap. */
318 Tk_Window tkwin
; /* any window on screen where pixmap lives */
319 Pixmap pixmap
; /* pixmap to associate with name,
320 * or None to create a new pixmap */
321 char *source
; /* Address of bits for bitmap. */
322 unsigned int width
; /* Width of bitmap. */
323 unsigned int height
; /* Height of bitmap. */
326 Tcl_HashEntry
*predefHashPtr
;
327 PredefBitmap
*predefPtr
;
335 key
.screen
= (pixmap
!= None
) ? Tk_Screen(tkwin
) : (Screen
*)NULL
;
336 predefHashPtr
= Tcl_CreateHashEntry(&predefTable
, (char *) &key
, &new);
338 Tcl_AppendResult(interp
, "bitmap \"", name
,
339 "\" is already defined", (char *) NULL
);
342 predefPtr
= (PredefBitmap
*) malloc(sizeof(PredefBitmap
));
343 predefPtr
->source
= source
;
344 predefPtr
->pixmap
= pixmap
;
345 predefPtr
->width
= width
;
346 predefPtr
->height
= height
;
347 Tcl_SetHashValue(predefHashPtr
, predefPtr
);
352 *--------------------------------------------------------------
356 * Given a pixmap, return a textual string identifying the
360 * The return value is the string name associated with pixmap.
365 *--------------------------------------------------------------
369 Tk_NameOfPixmap(bitmap
)
370 Pixmap bitmap
; /* Bitmap whose name is wanted. */
372 Tcl_HashEntry
*idHashPtr
;
377 panic("Tk_NameOfPixmap received unknown pixmap argument");
380 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
381 if (idHashPtr
== NULL
) {
384 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
385 if (bitmapPtr
->hashPtr
== NULL
) {
386 /* the bitmap has been un-defined */
387 return Tk_GetUid("UndefinedBitmap");
389 return ((NameKey
*) bitmapPtr
->hashPtr
->key
.words
)->name
;
393 *--------------------------------------------------------------
397 * Given a pixmap managed by this module, returns the width
398 * and height of the pixmap..
401 * The words at *widthPtr and *heightPtr are filled in with
402 * the dimenstions of pixmap.
405 * If pixmap isn't managed by this module then the procedure
408 *--------------------------------------------------------------
412 Tk_SizeOfPixmap(bitmap
, widthPtr
, heightPtr
)
413 Pixmap bitmap
; /* Bitmap whose size is wanted. */
414 unsigned int *widthPtr
; /* Store bitmap width here. */
415 unsigned int *heightPtr
; /* Store bitmap height here. */
417 Tcl_HashEntry
*idHashPtr
;
422 panic("Tk_SizeOfPixmap received unknown pixmap argument");
425 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
426 if (idHashPtr
== NULL
) {
429 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
430 *widthPtr
= bitmapPtr
->width
;
431 *heightPtr
= bitmapPtr
->height
;
435 *----------------------------------------------------------------------
439 * This procedure is called to release a pixmap allocated by
446 * The reference count associated with bitmap is decremented, and
447 * it is officially deallocated if no-one is using it anymore.
449 *----------------------------------------------------------------------
453 Tk_FreePixmap(bitmap
)
454 Pixmap bitmap
; /* Bitmap to be released. */
456 Tcl_HashEntry
*idHashPtr
;
457 register TkBitmap
*bitmapPtr
;
460 panic("Tk_FreePixmap called before Tk_GetPixmap");
463 idHashPtr
= Tcl_FindHashEntry(&idTable
, (char *) bitmap
);
464 if (idHashPtr
== NULL
) {
465 panic("Tk_FreePixmap received unknown pixmap argument");
467 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(idHashPtr
);
468 bitmapPtr
->refCount
--;
469 if (bitmapPtr
->refCount
== 0) {
470 XFreePixmap(bitmapPtr
->display
, bitmapPtr
->bitmap
);
471 Tcl_DeleteHashEntry(idHashPtr
);
472 if (bitmapPtr
->hashPtr
!= NULL
) {
473 /* If hashPtr is NULL, the bitmap has been undefined,
474 * and already removed from the name table */
475 Tcl_DeleteHashEntry(bitmapPtr
->hashPtr
);
477 ckfree((char *) bitmapPtr
);
482 *----------------------------------------------------------------------
484 * Tk_GetPixmapFromData --
486 * Given a description of the bits for a pixmap, make a pixmap that
487 * has the given properties.
490 * The return value is the X identifer for the desired pixmap,
491 * unless it couldn't be created properly. In this case, None is
492 * returned and an error message is left in interp->result. The
493 * caller should never modify the bitmap that is returned, and
494 * should eventually call Tk_FreePixmap when the pixmap is no
498 * The pixmap is added to an internal database with a reference count.
499 * For each call to this procedure, there should eventually be a call
500 * to Tk_FreePixmap, so that the database can be cleaned up when pixmaps
501 * aren't needed anymore.
503 *----------------------------------------------------------------------
508 Tk_GetPixmapFromData(interp
, tkwin
, source
, width
, height
)
509 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
510 Tk_Window tkwin
; /* Window in which bitmap will be used. */
511 char *source
; /* Bitmap data for bitmap shape. */
512 unsigned int width
, height
; /* Dimensions of bitmap. */
515 Tcl_HashEntry
*dataHashPtr
;
516 Tk_Uid name
= NULL
; /* Initialization need only to prevent
517 * compiler warning. */
519 static autoNumber
= 0;
529 dataHashPtr
= Tcl_CreateHashEntry(&dataTable
, (char *) &key
, &new);
531 name
= (Tk_Uid
) Tcl_GetHashValue(dataHashPtr
);
534 sprintf(string
, "_tk%d", autoNumber
);
535 name
= Tk_GetUid(string
);
536 Tcl_SetHashValue(dataHashPtr
, name
);
537 if (Tk_DefinePixmap(interp
, name
, tkwin
, None
, source
, width
,
539 Tcl_DeleteHashEntry(dataHashPtr
);
543 return Tk_GetPixmap(interp
, tkwin
, name
);
547 *----------------------------------------------------------------------
551 * Initialize the structures used for pixmap management.
559 *----------------------------------------------------------------------
564 Tk_Window tkwin
; /* any window on screen where pixmap lives */
568 dummy
= Tcl_CreateInterp();
570 Tcl_InitHashTable(&nameTable
, sizeof(NameKey
)/sizeof(int));
571 Tcl_InitHashTable(&dataTable
, sizeof(DataKey
)/sizeof(int));
572 Tcl_InitHashTable(&predefTable
, sizeof(NameKey
)/sizeof(int));
573 Tcl_InitHashTable(&idTable
, TCL_ONE_WORD_KEYS
);
575 Tk_DefinePixmap(dummy
, Tk_GetUid("gray50"), tkwin
, None
,
576 (char *)gray50_bits
, gray50_width
, gray50_height
);
577 Tk_DefinePixmap(dummy
, Tk_GetUid("gray25"), tkwin
, None
,
578 (char *)gray25_bits
, gray25_width
, gray25_height
);
579 Tcl_DeleteInterp(dummy
);
583 *----------------------------------------------------------------------
585 * Tk_UndefinePixmap --
587 * This procedure removes any association "name" with
588 * a bitmap or pixmap. This can be used to undefine
589 * names defined by either Tk_DefinePixmap or Tk_DefinePixmap.
590 * If tkwin is NULL, only display-independent pixmaps will
591 * be removed, otherwise both display-independent and
592 * the pixmap associated with tkwin will be undefined.
595 * A standard Tcl result. If an error occurs then TCL_ERROR is
596 * returned and a message is left in interp->result.
599 * "Name" is removed from the predef table.
601 *----------------------------------------------------------------------
605 Tk_UndefinePixmap(interp
, name
, tkwin
)
606 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
607 Tk_Uid name
; /* Name of bitmap/pixmap to undefine */
608 Tk_Window tkwin
; /* any window on screen where pixmap lives */
611 Tcl_HashEntry
*predefHashPtr
, *nameHashPtr
;
620 key
.screen
= (Screen
*) NULL
;
621 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, (char*)&key
);
622 if (predefHashPtr
!= NULL
) {
624 Tcl_DeleteHashEntry(predefHashPtr
);
627 key
.screen
= Tk_Screen(tkwin
);
628 predefHashPtr
= Tcl_FindHashEntry(&predefTable
, (char*)&key
);
629 if (predefHashPtr
!= NULL
) {
631 Tcl_DeleteHashEntry(predefHashPtr
);
634 Tcl_AppendResult(interp
, "pixmap \"", name
,
635 "\" doesn't exist", (char *) NULL
);
640 * Remove it from the name table if it is there (it might not
641 * have been created yet, it which case we wont find it). We
642 * delete it from the name table and mark the hashPtr as NULL
643 * so that we know it has been deleted. The pixmap still exists,
644 * and well later be freed and removed from idTable by Tk_FreeBitmap().
646 nameHashPtr
= Tcl_FindHashEntry(&nameTable
, (char *) &key
);
647 if (nameHashPtr
!= NULL
) {
648 bitmapPtr
= (TkBitmap
*) Tcl_GetHashValue(nameHashPtr
);
649 /* assert(nameHashPtr == bitmapPtr->hashPtr); */
650 /* assert(bitmapPtr->refCount > 0); */
651 bitmapPtr
->hashPtr
= (Tcl_HashEntry
*) NULL
;
652 Tcl_DeleteHashEntry(nameHashPtr
);