]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkpixmap.c
Fixes for compilation with gcc 15
[micropolis] / src / tk / tkpixmap.c
1 /*
2 * tkPixmap.c --
3 *
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.
7 *
8 * Copyright 1992 by Sven Delmas
9 *
10 * This source is based upon the file tkBitmap.c from:
11 *
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);
22 */
23
24 #if defined(USE_XPM3)
25
26 #ifndef lint
27 static char *AtFSid = "$Header: tkPixmap.c[1.1] Mon Sep 28 14:12:35 1992 garfield@cs.tu-berlin.de frozen $";
28 #endif /* not lint */
29
30 #include "tkconfig.h"
31 #include "tk.h"
32
33 /*
34 * The includes below are for pre-defined bitmaps.
35 */
36
37 #include "bitmaps/gray50"
38 #include "bitmaps/gray25"
39
40 /*
41 * Include the xpm 3 defines for color pixmaps
42 */
43 //#include "xpmtk.h"
44 #include <X11/xpm.h>
45
46 /*
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
49 * "nameTable".
50 */
51
52 typedef struct {
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). */
61 } TkBitmap;
62
63 /*
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
66 * hash table:
67 */
68
69 static Tcl_HashTable nameTable;
70 typedef struct {
71 Tk_Uid name; /* Textual name for desired bitmap. */
72 Screen *screen; /* Screen for which bitmap will be used. */
73 } NameKey;
74
75 /*
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
78 * Tk_FreePixmap.
79 */
80
81 static Tcl_HashTable idTable;
82
83 /*
84 * For each call to Tk_DefinePixmap one of the following structures is
85 * created to hold information about the pixmap.
86 */
87
88 typedef struct {
89 char *source; /* Bits for bitmap. */
90 Pixmap pixmap; /* Pre-defined pixmap */
91 unsigned int width, height; /* Dimensions of bitmap. */
92 } PredefBitmap;
93
94 /*
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.
99 */
100
101 static Tcl_HashTable predefTable;
102
103 /*
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:
107 */
108
109 static Tcl_HashTable dataTable;
110 typedef struct {
111 char *source; /* Bitmap bits. */
112 unsigned int width, height; /* Dimensions of bitmap. */
113 } DataKey;
114
115 static int initialized = 0; /* 0 means static structures haven't been
116 * initialized yet. */
117
118 /*
119 * Forward declarations for procedures defined in this file:
120 */
121
122 static void PixmapInit _ANSI_ARGS_((Tk_Window tkwin));
123 \f
124 /*
125 *----------------------------------------------------------------------
126 *
127 * Tk_GetPixmap --
128 *
129 * Given a string describing a bitmap or pixmap, locate (or create
130 * if necessary) a pixmap that fits the description.
131 *
132 * Results:
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.
139 *
140 * Side effects:
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.
145 *
146 *----------------------------------------------------------------------
147 */
148 Pixmap
149 Tk_GetPixmap (
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. */
154 )
155 {
156 NameKey key;
157 Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
158 register TkBitmap *bitmapPtr;
159 PredefBitmap *predefPtr;
160 int new;
161 Pixmap bitmap;
162 Pixmap bitmap_shape;
163 unsigned int width, height;
164 int dummy2;
165 XpmAttributes xpm_attributes;
166 Display *dpy = Tk_Display(tkwin);
167
168 if (!initialized) {
169 PixmapInit(tkwin);
170 }
171
172 key.name = string;
173 key.screen = Tk_Screen(tkwin);
174 nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &key, &new);
175 if (!new) {
176 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
177 bitmapPtr->refCount++;
178 return bitmapPtr->bitmap;
179 }
180
181 /*
182 * No suitable bitmap exists. Create a new bitmap from the
183 * information contained in the string. If the string starts
184 * with "@" then the rest of the string is a file name containing
185 * the bitmap. Otherwise the string must refer to a bitmap
186 * defined by a call to Tk_DefinePixmap.
187 */
188
189 if (*string == '@') {
190 string = Tcl_TildeSubst(interp, string + 1);
191 if (string == NULL) {
192 goto error;
193 }
194
195 if (XReadBitmapFile(dpy, RootWindowOfScreen(Tk_Screen(tkwin)),
196 string, &width, &height, &bitmap_shape, &dummy2, &dummy2)
197 != BitmapSuccess)
198 {
199 xpm_attributes.visual = Tk_DefaultVisual(Tk_Screen(tkwin));
200 xpm_attributes.colormap = Tk_DefaultColormap(Tk_Screen(tkwin));
201 xpm_attributes.depth = Tk_DefaultDepth(Tk_Screen(tkwin));
202 xpm_attributes.valuemask = XpmVisual | XpmColormap | XpmDepth;
203
204 if (XpmReadFileToPixmap(dpy, RootWindowOfScreen(Tk_Screen(tkwin)),
205 string, &bitmap, &bitmap_shape,
206 &xpm_attributes) != BitmapSuccess) {
207 Tcl_AppendResult(interp, "error reading bitmap file \"",
208 string, "\"", (char *) NULL);
209 goto error;
210 } {
211 width = xpm_attributes.width;
212 height = xpm_attributes.height;
213 XpmFreeAttributes(&xpm_attributes);
214 }
215 } else {
216 bitmap = XCreatePixmap(dpy, RootWindowOfScreen(Tk_Screen(tkwin)),
217 width, height,
218 Tk_DefaultDepth(Tk_Screen(tkwin)));
219 XCopyPlane(dpy, bitmap_shape, bitmap,
220 Tk_DefaultGC(Tk_Screen(tkwin)),
221 0, 0, width, height, 0, 0, 1);
222 }
223 } else {
224 /* first try for a display-specific version */
225 predefHashPtr = Tcl_FindHashEntry(&predefTable, (char *) &key);
226 if (predefHashPtr == NULL) {
227 /* try for a non-display specific version */
228 key.screen = (Screen*) NULL;
229 predefHashPtr = Tcl_FindHashEntry(&predefTable, (char *) &key);
230 if (predefHashPtr == NULL) {
231 /* give up */
232 Tcl_AppendResult(interp, "pixmap \"", string,
233 "\" not defined", (char *) NULL);
234 goto error;
235 }
236 }
237 predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr);
238 width = predefPtr->width;
239 height = predefPtr->height;
240 if (predefPtr->source != NULL) {
241 bitmap_shape =
242 XCreateBitmapFromData(dpy, Tk_DefaultRootWindow(dpy),
243 predefPtr->source, width, height);
244 bitmap = XCreatePixmap(dpy, RootWindowOfScreen(Tk_Screen(tkwin)),
245 width, height,
246 Tk_DefaultDepth(Tk_Screen(tkwin)));
247 XCopyPlane(dpy, bitmap_shape, bitmap,
248 Tk_DefaultGC(Tk_Screen(tkwin)),
249 0, 0, width, height, 0, 0, 1);
250 } else {
251 if (predefPtr->pixmap != None) {
252 bitmap = predefPtr->pixmap;
253 } else {
254 bitmap =
255 XCreatePixmap(dpy, RootWindowOfScreen(Tk_Screen(tkwin)),
256 width, height,
257 Tk_DefaultDepth(Tk_Screen(tkwin)));
258 }
259 }
260 }
261
262 /*
263 * Add information about this bitmap to our database.
264 */
265
266 bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
267 bitmapPtr->bitmap = bitmap;
268 bitmapPtr->width = width;
269 bitmapPtr->height = height;
270 bitmapPtr->display = dpy;
271 bitmapPtr->refCount = 1;
272 bitmapPtr->hashPtr = nameHashPtr;
273 idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) bitmapPtr->bitmap,
274 &new);
275 if (!new) {
276 /* deh patched to support multiple displays */
277 /* panic("pixmap already registered in Tk_GetPixmap"); */
278 bitmapPtr->refCount = 1000;
279 }
280 Tcl_SetHashValue(nameHashPtr, bitmapPtr);
281 Tcl_SetHashValue(idHashPtr, bitmapPtr);
282 return bitmapPtr->bitmap;
283
284 error:
285 Tcl_DeleteHashEntry(nameHashPtr);
286 return None;
287 }
288 \f
289 /*
290 *----------------------------------------------------------------------
291 *
292 * Tk_DefinePixmap --
293 *
294 * This procedure associates a textual name with a binary pixmap
295 * description, so that the name may be used to refer to the
296 * pixmap in future calls to Tk_GetPixmap. The pixmap can
297 * be pre-created by the user, or can be created later
298 * by Tk_GetPixmap(). Since pixmaps are display-specific,
299 * a user supplied pixmap will be associated with tkwin's display.
300 * If pixmap is given as None, then a new pixmap will be created
301 * by Tk_GetPixmap for each unique display.
302 *
303 * Results:
304 * A standard Tcl result. If an error occurs then TCL_ERROR is
305 * returned and a message is left in interp->result.
306 *
307 * Side effects:
308 * "Name" is entered into the pixmap table and may be used from
309 * here on to refer to the given pixmap.
310 *
311 *----------------------------------------------------------------------
312 */
313
314 int
315 Tk_DefinePixmap (
316 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
317 Tk_Uid name, /* Name to use for bitmap. Must not already
318 * be defined as a bitmap. */
319 Tk_Window tkwin, /* any window on screen where pixmap lives */
320 Pixmap pixmap, /* pixmap to associate with name,
321 * or None to create a new pixmap */
322 char *source, /* Address of bits for bitmap. */
323 unsigned int width, /* Width of bitmap. */
324 unsigned int height /* Height of bitmap. */
325 )
326 {
327 int new;
328 Tcl_HashEntry *predefHashPtr;
329 PredefBitmap *predefPtr;
330 NameKey key;
331
332 if (!initialized) {
333 PixmapInit(tkwin);
334 }
335
336 key.name = name;
337 key.screen = (pixmap != None) ? Tk_Screen(tkwin) : (Screen *)NULL;
338 predefHashPtr = Tcl_CreateHashEntry(&predefTable, (char *) &key, &new);
339 if (!new) {
340 Tcl_AppendResult(interp, "bitmap \"", name,
341 "\" is already defined", (char *) NULL);
342 return TCL_ERROR;
343 }
344 predefPtr = (PredefBitmap *) malloc(sizeof(PredefBitmap));
345 predefPtr->source = source;
346 predefPtr->pixmap = pixmap;
347 predefPtr->width = width;
348 predefPtr->height = height;
349 Tcl_SetHashValue(predefHashPtr, predefPtr);
350 return TCL_OK;
351 }
352 \f
353 /*
354 *--------------------------------------------------------------
355 *
356 * Tk_NameOfPixmap --
357 *
358 * Given a pixmap, return a textual string identifying the
359 * pixmap.
360 *
361 * Results:
362 * The return value is the string name associated with pixmap.
363 *
364 * Side effects:
365 * None.
366 *
367 *--------------------------------------------------------------
368 */
369
370 Tk_Uid
371 Tk_NameOfPixmap (
372 Pixmap bitmap /* Bitmap whose name is wanted. */
373 )
374 {
375 Tcl_HashEntry *idHashPtr;
376 TkBitmap *bitmapPtr;
377
378 if (!initialized) {
379 unknown:
380 panic("Tk_NameOfPixmap received unknown pixmap argument");
381 }
382
383 idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
384 if (idHashPtr == NULL) {
385 goto unknown;
386 }
387 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
388 if (bitmapPtr->hashPtr == NULL) {
389 /* the bitmap has been un-defined */
390 return Tk_GetUid("UndefinedBitmap");
391 }
392 return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
393 }
394 \f
395 /*
396 *--------------------------------------------------------------
397 *
398 * Tk_SizeOfPixmap --
399 *
400 * Given a pixmap managed by this module, returns the width
401 * and height of the pixmap..
402 *
403 * Results:
404 * The words at *widthPtr and *heightPtr are filled in with
405 * the dimenstions of pixmap.
406 *
407 * Side effects:
408 * If pixmap isn't managed by this module then the procedure
409 * panics..
410 *
411 *--------------------------------------------------------------
412 */
413
414 void
415 Tk_SizeOfPixmap (
416 Pixmap bitmap, /* Bitmap whose size is wanted. */
417 unsigned int *widthPtr, /* Store bitmap width here. */
418 unsigned int *heightPtr /* Store bitmap height here. */
419 )
420 {
421 Tcl_HashEntry *idHashPtr;
422 TkBitmap *bitmapPtr;
423
424 if (!initialized) {
425 unknownBitmap:
426 panic("Tk_SizeOfPixmap received unknown pixmap argument");
427 }
428
429 idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
430 if (idHashPtr == NULL) {
431 goto unknownBitmap;
432 }
433 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
434 *widthPtr = bitmapPtr->width;
435 *heightPtr = bitmapPtr->height;
436 }
437 \f
438 /*
439 *----------------------------------------------------------------------
440 *
441 * Tk_FreePixmap --
442 *
443 * This procedure is called to release a pixmap allocated by
444 * Tk_GetPixmap.
445 *
446 * Results:
447 * None.
448 *
449 * Side effects:
450 * The reference count associated with bitmap is decremented, and
451 * it is officially deallocated if no-one is using it anymore.
452 *
453 *----------------------------------------------------------------------
454 */
455
456 void
457 Tk_FreePixmap (
458 Pixmap bitmap /* Bitmap to be released. */
459 )
460 {
461 Tcl_HashEntry *idHashPtr;
462 register TkBitmap *bitmapPtr;
463
464 if (!initialized) {
465 panic("Tk_FreePixmap called before Tk_GetPixmap");
466 }
467
468 idHashPtr = Tcl_FindHashEntry(&idTable, (char *) bitmap);
469 if (idHashPtr == NULL) {
470 panic("Tk_FreePixmap received unknown pixmap argument");
471 }
472 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
473 bitmapPtr->refCount--;
474 if (bitmapPtr->refCount == 0) {
475 XFreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
476 Tcl_DeleteHashEntry(idHashPtr);
477 if (bitmapPtr->hashPtr != NULL) {
478 /* If hashPtr is NULL, the bitmap has been undefined,
479 * and already removed from the name table */
480 Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
481 }
482 ckfree((char *) bitmapPtr);
483 }
484 }
485 \f
486 /*
487 *----------------------------------------------------------------------
488 *
489 * Tk_GetPixmapFromData --
490 *
491 * Given a description of the bits for a pixmap, make a pixmap that
492 * has the given properties.
493 *
494 * Results:
495 * The return value is the X identifer for the desired pixmap,
496 * unless it couldn't be created properly. In this case, None is
497 * returned and an error message is left in interp->result. The
498 * caller should never modify the bitmap that is returned, and
499 * should eventually call Tk_FreePixmap when the pixmap is no
500 * longer needed.
501 *
502 * Side effects:
503 * The pixmap is added to an internal database with a reference count.
504 * For each call to this procedure, there should eventually be a call
505 * to Tk_FreePixmap, so that the database can be cleaned up when pixmaps
506 * aren't needed anymore.
507 *
508 *----------------------------------------------------------------------
509 */
510
511 /* ARGSUSED */
512 Pixmap
513 Tk_GetPixmapFromData (
514 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
515 Tk_Window tkwin, /* Window in which bitmap will be used. */
516 char *source, /* Bitmap data for bitmap shape. */
517 unsigned int width,
518 unsigned int height /* Dimensions of bitmap. */
519 )
520 {
521 DataKey key;
522 Tcl_HashEntry *dataHashPtr;
523 Tk_Uid name = NULL; /* Initialization need only to prevent
524 * compiler warning. */
525 int new;
526 static int autoNumber = 0;
527 char string[20];
528
529 if (!initialized) {
530 PixmapInit(tkwin);
531 }
532
533 key.source = source;
534 key.width = width;
535 key.height = height;
536 dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &key, &new);
537 if (!new) {
538 name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
539 } else {
540 autoNumber++;
541 sprintf(string, "_tk%d", autoNumber);
542 name = Tk_GetUid(string);
543 Tcl_SetHashValue(dataHashPtr, name);
544 if (Tk_DefinePixmap(interp, name, tkwin, None, source, width,
545 height) != TCL_OK) {
546 Tcl_DeleteHashEntry(dataHashPtr);
547 return TCL_ERROR;
548 }
549 }
550 return Tk_GetPixmap(interp, tkwin, name);
551 }
552 \f
553 /*
554 *----------------------------------------------------------------------
555 *
556 * PixmapInit --
557 *
558 * Initialize the structures used for pixmap management.
559 *
560 * Results:
561 * None.
562 *
563 * Side effects:
564 * Read the code.
565 *
566 *----------------------------------------------------------------------
567 */
568
569 static void
570 PixmapInit (
571 Tk_Window tkwin /* any window on screen where pixmap lives */
572 )
573 {
574 Tcl_Interp *dummy;
575
576 dummy = Tcl_CreateInterp();
577 initialized = 1;
578 Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
579 Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
580 Tcl_InitHashTable(&predefTable, sizeof(NameKey)/sizeof(int));
581 Tcl_InitHashTable(&idTable, TCL_ONE_WORD_KEYS);
582
583 Tk_DefinePixmap(dummy, Tk_GetUid("gray50"), tkwin, None,
584 (char *)gray50_bits, gray50_width, gray50_height);
585 Tk_DefinePixmap(dummy, Tk_GetUid("gray25"), tkwin, None,
586 (char *)gray25_bits, gray25_width, gray25_height);
587 Tcl_DeleteInterp(dummy);
588 }
589 \f
590 /*
591 *----------------------------------------------------------------------
592 *
593 * Tk_UndefinePixmap --
594 *
595 * This procedure removes any association "name" with
596 * a bitmap or pixmap. This can be used to undefine
597 * names defined by either Tk_DefinePixmap or Tk_DefinePixmap.
598 * If tkwin is NULL, only display-independent pixmaps will
599 * be removed, otherwise both display-independent and
600 * the pixmap associated with tkwin will be undefined.
601 *
602 * Results:
603 * A standard Tcl result. If an error occurs then TCL_ERROR is
604 * returned and a message is left in interp->result.
605 *
606 * Side effects:
607 * "Name" is removed from the predef table.
608 *
609 *----------------------------------------------------------------------
610 */
611
612 int
613 Tk_UndefinePixmap (
614 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
615 Tk_Uid name, /* Name of bitmap/pixmap to undefine */
616 Tk_Window tkwin /* any window on screen where pixmap lives */
617 )
618 {
619 NameKey key;
620 Tcl_HashEntry *predefHashPtr, *nameHashPtr;
621 TkBitmap *bitmapPtr;
622 int cnt = 0;
623
624 if (!initialized) {
625 PixmapInit(tkwin);
626 }
627
628 key.name = name;
629 key.screen = (Screen *) NULL;
630 predefHashPtr = Tcl_FindHashEntry(&predefTable, (char*)&key);
631 if (predefHashPtr != NULL) {
632 ++cnt;
633 Tcl_DeleteHashEntry(predefHashPtr);
634 }
635
636 key.screen = Tk_Screen(tkwin);
637 predefHashPtr = Tcl_FindHashEntry(&predefTable, (char*)&key);
638 if (predefHashPtr != NULL) {
639 ++cnt;
640 Tcl_DeleteHashEntry(predefHashPtr);
641 }
642 if (cnt == 0) {
643 Tcl_AppendResult(interp, "pixmap \"", name,
644 "\" doesn't exist", (char *) NULL);
645 return TCL_ERROR;
646 }
647
648 /*
649 * Remove it from the name table if it is there (it might not
650 * have been created yet, it which case we wont find it). We
651 * delete it from the name table and mark the hashPtr as NULL
652 * so that we know it has been deleted. The pixmap still exists,
653 * and well later be freed and removed from idTable by Tk_FreeBitmap().
654 */
655 nameHashPtr = Tcl_FindHashEntry(&nameTable, (char *) &key);
656 if (nameHashPtr != NULL) {
657 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
658 /* assert(nameHashPtr == bitmapPtr->hashPtr); */
659 /* assert(bitmapPtr->refCount > 0); */
660 bitmapPtr->hashPtr = (Tcl_HashEntry*) NULL;
661 Tcl_DeleteHashEntry(nameHashPtr);
662 }
663 return TCL_OK;
664 }
665
666 #endif
Impressum, Datenschutz