]> git.zerfleddert.de Git - micropolis/blob - src/tk/tkbitmap.c
cc81cd02c477b6289a25b76909b3b46f8db212a6
[micropolis] / src / tk / tkbitmap.c
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 }
Impressum, Datenschutz