|
|
1.1 root 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
6: * also avoids interactions with the X server.
7: *
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.
16: */
17:
18: #ifndef lint
19: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkBitmap.c,v 1.16 92/08/24 09:45:43 ouster Exp $ SPRITE (Berkeley)";
20: #endif /* not lint */
21:
22: #include "tkconfig.h"
23: #include "tk.h"
24:
25: /*
26: * The includes below are for pre-defined bitmaps.
27: */
28:
29: #include "bitmaps/gray50"
30: #include "bitmaps/gray25"
31:
32: /*
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
35: * "nameTable".
36: */
37:
38: typedef struct {
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). */
47: } TkBitmap;
48:
49: /*
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
52: * hash table:
53: */
54:
55: static Tcl_HashTable nameTable;
56: typedef struct {
57: Tk_Uid name; /* Textual name for desired bitmap. */
58: Screen *screen; /* Screen for which bitmap will be used. */
59: } NameKey;
60:
61: /*
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
64: * Tk_FreeBitmap.
65: */
66:
67: static Tcl_HashTable idTable;
68:
69: /*
70: * For each call to Tk_DefineBitmap one of the following structures is
71: * created to hold information about the bitmap.
72: */
73:
74: typedef struct {
75: char *source; /* Bits for bitmap. */
76: unsigned int width, height; /* Dimensions of bitmap. */
77: } PredefBitmap;
78:
79: /*
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.
84: */
85:
86: static Tcl_HashTable predefTable;
87:
88: /*
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:
92: */
93:
94: static Tcl_HashTable dataTable;
95: typedef struct {
96: char *source; /* Bitmap bits. */
97: unsigned int width, height; /* Dimensions of bitmap. */
98: } DataKey;
99:
100: static int initialized = 0; /* 0 means static structures haven't been
101: * initialized yet. */
102:
103: /*
104: * Forward declarations for procedures defined in this file:
105: */
106:
107: static void BitmapInit _ANSI_ARGS_((void));
108:
109: /*
110: *----------------------------------------------------------------------
111: *
112: * Tk_GetBitmap --
113: *
114: * Given a string describing a bitmap, locate (or create if necessary)
115: * a bitmap that fits the description.
116: *
117: * Results:
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.
124: *
125: * Side effects:
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.
130: *
131: *----------------------------------------------------------------------
132: */
133:
134: Pixmap
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. */
140: {
141: NameKey key;
142: Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
143: register TkBitmap *bitmapPtr;
144: PredefBitmap *predefPtr;
145: int new;
146: Pixmap bitmap;
147: unsigned int width, height;
148: int dummy2;
149:
150: if (!initialized) {
151: BitmapInit();
152: }
153:
154: key.name = string;
155: key.screen = Tk_Screen(tkwin);
156: nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &key, &new);
157: if (!new) {
158: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
159: bitmapPtr->refCount++;
160: return bitmapPtr->bitmap;
161: }
162:
163: /*
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.
169: */
170:
171: if (*string == '@') {
172: string = Tcl_TildeSubst(interp, string + 1);
173: if (string == NULL) {
174: goto error;
175: }
176: if (XReadBitmapFile(Tk_Display(tkwin),
177: RootWindowOfScreen(Tk_Screen(tkwin)),
178: string, &width, &height, &bitmap, &dummy2, &dummy2)
179: != BitmapSuccess) {
180: Tcl_AppendResult(interp, "error reading bitmap file \"", string,
181: "\"", (char *) NULL);
182: goto error;
183: }
184: } else {
185: predefHashPtr = Tcl_FindHashEntry(&predefTable, string);
186: if (predefHashPtr == NULL) {
187: Tcl_AppendResult(interp, "bitmap \"", string,
188: "\" not defined", (char *) NULL);
189: goto error;
190: }
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,
196: width, height);
197: }
198:
199: /*
200: * Add information about this bitmap to our database.
201: */
202:
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,
211: &new);
212: if (!new) {
213: /* deh patched to support multiple displays */
214: /* panic("bitmap already registered in Tk_GetBitmap"); */
215: bitmapPtr->refCount = 1000;
216: }
217: Tcl_SetHashValue(nameHashPtr, bitmapPtr);
218: Tcl_SetHashValue(idHashPtr, bitmapPtr);
219: return bitmapPtr->bitmap;
220:
221: error:
222: Tcl_DeleteHashEntry(nameHashPtr);
223: return None;
224: }
225:
226: /*
227: *----------------------------------------------------------------------
228: *
229: * Tk_DefineBitmap --
230: *
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.
234: *
235: * Results:
236: * A standard Tcl result. If an error occurs then TCL_ERROR is
237: * returned and a message is left in interp->result.
238: *
239: * Side effects:
240: * "Name" is entered into the bitmap table and may be used from
241: * here on to refer to the given bitmap.
242: *
243: *----------------------------------------------------------------------
244: */
245:
246: int
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. */
254: {
255: int new;
256: Tcl_HashEntry *predefHashPtr;
257: PredefBitmap *predefPtr;
258:
259: if (!initialized) {
260: BitmapInit();
261: }
262:
263: predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new);
264: if (!new) {
265: Tcl_AppendResult(interp, "bitmap \"", name,
266: "\" is already defined", (char *) NULL);
267: return TCL_ERROR;
268: }
269: predefPtr = (PredefBitmap *) malloc(sizeof(PredefBitmap));
270: predefPtr->source = source;
271: predefPtr->width = width;
272: predefPtr->height = height;
273: Tcl_SetHashValue(predefHashPtr, predefPtr);
274: return TCL_OK;
275: }
276:
277: /*
278: *--------------------------------------------------------------
279: *
280: * Tk_NameOfBitmap --
281: *
282: * Given a bitmap, return a textual string identifying the
283: * bitmap.
284: *
285: * Results:
286: * The return value is the string name associated with bitmap.
287: *
288: * Side effects:
289: * None.
290: *
291: *--------------------------------------------------------------
292: */
293:
294: Tk_Uid
295: Tk_NameOfBitmap(bitmap)
296: Pixmap bitmap; /* Bitmap whose name is wanted. */
297: {
298: Tcl_HashEntry *idHashPtr;
299: TkBitmap *bitmapPtr;
300:
301: if (!initialized) {
302: unknown:
303: panic("Tk_NameOfBitmap received unknown bitmap argument");
304: }
305:
306: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
307: if (idHashPtr == NULL) {
308: goto unknown;
309: }
310: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
311: return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
312: }
313:
314: /*
315: *--------------------------------------------------------------
316: *
317: * Tk_SizeOfBitmap --
318: *
319: * Given a bitmap managed by this module, returns the width
320: * and height of the bitmap..
321: *
322: * Results:
323: * The words at *widthPtr and *heightPtr are filled in with
324: * the dimenstions of bitmap.
325: *
326: * Side effects:
327: * If bitmap isn't managed by this module then the procedure
328: * panics..
329: *
330: *--------------------------------------------------------------
331: */
332:
333: void
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. */
338: {
339: Tcl_HashEntry *idHashPtr;
340: TkBitmap *bitmapPtr;
341:
342: if (!initialized) {
343: unknownBitmap:
344: panic("Tk_SizeOfBitmap received unknown bitmap argument");
345: }
346:
347: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
348: if (idHashPtr == NULL) {
349: goto unknownBitmap;
350: }
351: bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
352: *widthPtr = bitmapPtr->width;
353: *heightPtr = bitmapPtr->height;
354: }
355:
356: /*
357: *----------------------------------------------------------------------
358: *
359: * Tk_FreeBitmap --
360: *
361: * This procedure is called to release a bitmap allocated by
362: * Tk_GetBitmap or TkGetBitmapFromData.
363: *
364: * Results:
365: * None.
366: *
367: * Side effects:
368: * The reference count associated with bitmap is decremented, and
369: * it is officially deallocated if no-one is using it anymore.
370: *
371: *----------------------------------------------------------------------
372: */
373:
374: void
375: Tk_FreeBitmap(bitmap)
376: Pixmap bitmap; /* Bitmap to be released. */
377: {
378: Tcl_HashEntry *idHashPtr;
379: register TkBitmap *bitmapPtr;
380:
381: if (!initialized) {
382: panic("Tk_FreeBitmap called before Tk_GetBitmap");
383: }
384:
385: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
386: if (idHashPtr == NULL) {
387: panic("Tk_FreeBitmap received unknown bitmap argument");
388: }
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);
396: }
397: }
398:
399: /*
400: *----------------------------------------------------------------------
401: *
402: * Tk_GetBitmapFromData --
403: *
404: * Given a description of the bits for a bitmap, make a bitmap that
405: * has the given properties.
406: *
407: * Results:
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.
414: *
415: * Side effects:
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.
420: *
421: *----------------------------------------------------------------------
422: */
423:
424: /* ARGSUSED */
425: Pixmap
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. */
431: {
432: DataKey key;
433: Tcl_HashEntry *dataHashPtr;
434: Tk_Uid name = NULL; /* Initialization need only to prevent
435: * compiler warning. */
436: int new;
437: static autoNumber = 0;
438: char string[20];
439:
440: if (!initialized) {
441: BitmapInit();
442: }
443:
444: key.source = source;
445: key.width = width;
446: key.height = height;
447: dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &key, &new);
448: if (!new) {
449: name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
450: } else {
451: autoNumber++;
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);
457: return TCL_ERROR;
458: }
459: }
460: return Tk_GetBitmap(interp, tkwin, name);
461: }
462:
463: /*
464: *----------------------------------------------------------------------
465: *
466: * BitmapInit --
467: *
468: * Initialize the structures used for bitmap management.
469: *
470: * Results:
471: * None.
472: *
473: * Side effects:
474: * Read the code.
475: *
476: *----------------------------------------------------------------------
477: */
478:
479: static void
480: BitmapInit()
481: {
482: Tcl_Interp *dummy;
483:
484: dummy = Tcl_CreateInterp();
485: initialized = 1;
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);
490:
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);
496: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.