/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkbitmap.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkbitmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 3 months ago) by dashley
File MIME type: text/plain
File size: 37323 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkBitmap.c --
5 *
6 * This file maintains a database of read-only bitmaps for the Tk
7 * toolkit. This allows bitmaps to be shared between widgets and
8 * also avoids interactions with the X server.
9 *
10 * Copyright (c) 1990-1994 The Regents of the University of California.
11 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
12 *
13 * See the file "license.terms" for information on usage and redistribution
14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 *
16 * RCS: @(#) $Id: tkbitmap.c,v 1.1.1.1 2001/06/13 04:54:29 dtashley Exp $
17 */
18
19 #include "tkPort.h"
20 #include "tkInt.h"
21
22 /*
23 * The includes below are for pre-defined bitmaps.
24 *
25 * Platform-specific issue: Windows complains when the bitmaps are
26 * included, because an array of characters is being initialized with
27 * integers as elements. For lint purposes, the following pragmas
28 * temporarily turn off that warning message.
29 */
30
31 #if defined(__WIN32__) || defined(_WIN32)
32 #pragma warning (disable : 4305)
33 #endif
34
35 #include "error.bmp"
36 #include "gray12.bmp"
37 #include "gray25.bmp"
38 #include "gray50.bmp"
39 #include "gray75.bmp"
40 #include "hourglass.bmp"
41 #include "info.bmp"
42 #include "questhead.bmp"
43 #include "question.bmp"
44 #include "warning.bmp"
45
46 #if defined(__WIN32__) || defined(_WIN32)
47 #pragma warning (default : 4305)
48 #endif
49
50 /*
51 * One of the following data structures exists for each bitmap that is
52 * currently in use. Each structure is indexed with both "idTable" and
53 * "nameTable".
54 */
55
56 typedef struct TkBitmap {
57 Pixmap bitmap; /* X identifier for bitmap. None means this
58 * bitmap was created by Tk_DefineBitmap
59 * and it isn't currently in use. */
60 int width, height; /* Dimensions of bitmap. */
61 Display *display; /* Display for which bitmap is valid. */
62 int resourceRefCount; /* Number of active uses of this bitmap (each
63 * active use corresponds to a call to
64 * Tk_AllocBitmapFromObj or Tk_GetBitmap).
65 * If this count is 0, then this TkBitmap
66 * structure is no longer valid and it isn't
67 * present in nameTable: it is being kept
68 * around only because there are objects
69 * referring to it. The structure is freed
70 * when resourceRefCount and objRefCount
71 * are both 0. */
72 int objRefCount; /* Number of Tcl_Obj's that reference
73 * this structure. */
74 Tcl_HashEntry *nameHashPtr; /* Entry in nameTable for this structure
75 * (needed when deleting). */
76 Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure
77 * (needed when deleting). */
78 struct TkBitmap *nextPtr; /* Points to the next TkBitmap structure with
79 * the same name. All bitmaps with the
80 * same name (but different displays) are
81 * chained together off a single entry in
82 * nameTable. */
83 } TkBitmap;
84
85 /*
86 * Used in bitmapDataTable, stored in the TkDisplay structure, to map
87 * between in-core data about a bitmap to its TkBitmap structure.
88 */
89
90 typedef struct {
91 char *source; /* Bitmap bits. */
92 int width, height; /* Dimensions of bitmap. */
93 } DataKey;
94
95 typedef struct ThreadSpecificData {
96 int initialized; /* 0 means table below needs initializing. */
97 Tcl_HashTable predefBitmapTable;
98 /* Hash table created by Tk_DefineBitmap
99 * to map from a name to a collection
100 * of in-core data about a bitmap. The
101 * table is indexed by the address of the
102 * data for the bitmap, and the entries
103 * contain pointers to TkPredefBitmap
104 * structures. */
105 } ThreadSpecificData;
106 static Tcl_ThreadDataKey dataKey;
107
108 /*
109 * Forward declarations for procedures defined in this file:
110 */
111
112 static void BitmapInit _ANSI_ARGS_((TkDisplay *dispPtr));
113 static void DupBitmapObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
114 Tcl_Obj *dupObjPtr));
115 static void FreeBitmap _ANSI_ARGS_((TkBitmap *bitmapPtr));
116 static void FreeBitmapObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
117 static TkBitmap * GetBitmap _ANSI_ARGS_((Tcl_Interp *interp,
118 Tk_Window tkwin, CONST char *name));
119 static TkBitmap * GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
120 Tcl_Obj *objPtr));
121 static void InitBitmapObj _ANSI_ARGS_((Tcl_Obj *objPtr));
122
123 /*
124 * The following structure defines the implementation of the "bitmap" Tcl
125 * object, which maps a string bitmap name to a TkBitmap object. The
126 * ptr1 field of the Tcl_Obj points to a TkBitmap object.
127 */
128
129 static Tcl_ObjType bitmapObjType = {
130 "bitmap", /* name */
131 FreeBitmapObjProc, /* freeIntRepProc */
132 DupBitmapObjProc, /* dupIntRepProc */
133 NULL, /* updateStringProc */
134 NULL /* setFromAnyProc */
135 };
136
137 /*
138 *----------------------------------------------------------------------
139 *
140 * Tk_AllocBitmapFromObj --
141 *
142 * Given a Tcl_Obj *, map the value to a corresponding
143 * Pixmap structure based on the tkwin given.
144 *
145 * Results:
146 * The return value is the X identifer for the desired bitmap
147 * (i.e. a Pixmap with a single plane), unless string couldn't be
148 * parsed correctly. In this case, None is returned and an error
149 * message is left in the interp's result. The caller should never
150 * modify the bitmap that is returned, and should eventually call
151 * Tk_FreeBitmapFromObj when the bitmap is no longer needed.
152 *
153 * Side effects:
154 * The bitmap is added to an internal database with a reference count.
155 * For each call to this procedure, there should eventually be a call
156 * to Tk_FreeBitmapFromObj, so that the database can be cleaned up
157 * when bitmaps aren't needed anymore.
158 *
159 *----------------------------------------------------------------------
160 */
161
162 Pixmap
163 Tk_AllocBitmapFromObj(interp, tkwin, objPtr)
164 Tcl_Interp *interp; /* Interp for error results. This may
165 * be NULL. */
166 Tk_Window tkwin; /* Need the screen the bitmap is used on.*/
167 Tcl_Obj *objPtr; /* Object describing bitmap; see manual
168 * entry for legal syntax of string value. */
169 {
170 TkBitmap *bitmapPtr;
171
172 if (objPtr->typePtr != &bitmapObjType) {
173 InitBitmapObj(objPtr);
174 }
175 bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
176
177 /*
178 * If the object currently points to a TkBitmap, see if it's the
179 * one we want. If so, increment its reference count and return.
180 */
181
182 if (bitmapPtr != NULL) {
183 if (bitmapPtr->resourceRefCount == 0) {
184 /*
185 * This is a stale reference: it refers to a TkBitmap that's
186 * no longer in use. Clear the reference.
187 */
188
189 FreeBitmapObjProc(objPtr);
190 bitmapPtr = NULL;
191 } else if (Tk_Display(tkwin) == bitmapPtr->display) {
192 bitmapPtr->resourceRefCount++;
193 return bitmapPtr->bitmap;
194 }
195 }
196
197 /*
198 * The object didn't point to the TkBitmap that we wanted. Search
199 * the list of TkBitmaps with the same name to see if one of the
200 * others is the right one.
201 */
202
203 if (bitmapPtr != NULL) {
204 TkBitmap *firstBitmapPtr =
205 (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr);
206 FreeBitmapObjProc(objPtr);
207 for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL;
208 bitmapPtr = bitmapPtr->nextPtr) {
209 if (Tk_Display(tkwin) == bitmapPtr->display) {
210 bitmapPtr->resourceRefCount++;
211 bitmapPtr->objRefCount++;
212 objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
213 return bitmapPtr->bitmap;
214 }
215 }
216 }
217
218 /*
219 * Still no luck. Call GetBitmap to allocate a new TkBitmap object.
220 */
221
222 bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr));
223 objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
224 if (bitmapPtr == NULL) {
225 return None;
226 }
227 bitmapPtr->objRefCount++;
228 return bitmapPtr->bitmap;
229 }
230
231 /*
232 *----------------------------------------------------------------------
233 *
234 * Tk_GetBitmap --
235 *
236 * Given a string describing a bitmap, locate (or create if necessary)
237 * a bitmap that fits the description.
238 *
239 * Results:
240 * The return value is the X identifer for the desired bitmap
241 * (i.e. a Pixmap with a single plane), unless string couldn't be
242 * parsed correctly. In this case, None is returned and an error
243 * message is left in the interp's result. The caller should never
244 * modify the bitmap that is returned, and should eventually call
245 * Tk_FreeBitmap when the bitmap is no longer needed.
246 *
247 * Side effects:
248 * The bitmap is added to an internal database with a reference count.
249 * For each call to this procedure, there should eventually be a call
250 * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
251 * aren't needed anymore.
252 *
253 *----------------------------------------------------------------------
254 */
255
256 Pixmap
257 Tk_GetBitmap(interp, tkwin, string)
258 Tcl_Interp *interp; /* Interpreter to use for error reporting,
259 * this may be NULL. */
260 Tk_Window tkwin; /* Window in which bitmap will be used. */
261 CONST char *string; /* Description of bitmap. See manual entry
262 * for details on legal syntax. */
263 {
264 TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string);
265 if (bitmapPtr == NULL) {
266 return None;
267 }
268 return bitmapPtr->bitmap;
269 }
270
271 /*
272 *----------------------------------------------------------------------
273 *
274 * GetBitmap --
275 *
276 * Given a string describing a bitmap, locate (or create if necessary)
277 * a bitmap that fits the description. This routine returns the
278 * internal data structure for the bitmap. This avoids extra
279 * hash table lookups in Tk_AllocBitmapFromObj.
280 *
281 * Results:
282 * The return value is the X identifer for the desired bitmap
283 * (i.e. a Pixmap with a single plane), unless string couldn't be
284 * parsed correctly. In this case, None is returned and an error
285 * message is left in the interp's result. The caller should never
286 * modify the bitmap that is returned, and should eventually call
287 * Tk_FreeBitmap when the bitmap is no longer needed.
288 *
289 * Side effects:
290 * The bitmap is added to an internal database with a reference count.
291 * For each call to this procedure, there should eventually be a call
292 * to Tk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can
293 * be cleaned up when bitmaps aren't needed anymore.
294 *
295 *----------------------------------------------------------------------
296 */
297
298 static TkBitmap *
299 GetBitmap(interp, tkwin, string)
300 Tcl_Interp *interp; /* Interpreter to use for error reporting,
301 * this may be NULL. */
302 Tk_Window tkwin; /* Window in which bitmap will be used. */
303 CONST char *string; /* Description of bitmap. See manual entry
304 * for details on legal syntax. */
305 {
306 Tcl_HashEntry *nameHashPtr, *predefHashPtr;
307 TkBitmap *bitmapPtr, *existingBitmapPtr;
308 TkPredefBitmap *predefPtr;
309 int new;
310 Pixmap bitmap;
311 int width, height;
312 int dummy2;
313 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
314 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
315 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
316
317 if (!dispPtr->bitmapInit) {
318 BitmapInit(dispPtr);
319 }
320
321 nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string, &new);
322 if (!new) {
323 existingBitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
324 for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL;
325 bitmapPtr = bitmapPtr->nextPtr) {
326 if (Tk_Display(tkwin) == bitmapPtr->display) {
327 bitmapPtr->resourceRefCount++;
328 return bitmapPtr;
329 }
330 }
331 } else {
332 existingBitmapPtr = NULL;
333 }
334
335 /*
336 * No suitable bitmap exists. Create a new bitmap from the
337 * information contained in the string. If the string starts
338 * with "@" then the rest of the string is a file name containing
339 * the bitmap. Otherwise the string must refer to a bitmap
340 * defined by a call to Tk_DefineBitmap.
341 */
342
343 if (*string == '@') { /* INTL: ISO char */
344 Tcl_DString buffer;
345 int result;
346
347 if (Tcl_IsSafe(interp)) {
348 Tcl_AppendResult(interp, "can't specify bitmap with '@' in a",
349 " safe interpreter", (char *) NULL);
350 goto error;
351 }
352
353 /*
354 * Note that we need to cast away the CONST from the string because
355 * Tcl_TranslateFileName is non const, even though it doesn't modify
356 * the string.
357 */
358
359 string = Tcl_TranslateFileName(interp, (char *) string + 1, &buffer);
360 if (string == NULL) {
361 goto error;
362 }
363 result = TkReadBitmapFile(Tk_Display(tkwin),
364 RootWindowOfScreen(Tk_Screen(tkwin)), string,
365 (unsigned int *) &width, (unsigned int *) &height,
366 &bitmap, &dummy2, &dummy2);
367 if (result != BitmapSuccess) {
368 if (interp != NULL) {
369 Tcl_AppendResult(interp, "error reading bitmap file \"", string,
370 "\"", (char *) NULL);
371 }
372 Tcl_DStringFree(&buffer);
373 goto error;
374 }
375 Tcl_DStringFree(&buffer);
376 } else {
377 predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable,
378 string);
379 if (predefHashPtr == NULL) {
380 /*
381 * The following platform specific call allows the user to
382 * define bitmaps that may only exist during run time. If
383 * it returns None nothing was found and we return the error.
384 */
385 bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string,
386 &width, &height);
387
388 if (bitmap == None) {
389 if (interp != NULL) {
390 Tcl_AppendResult(interp, "bitmap \"", string,
391 "\" not defined", (char *) NULL);
392 }
393 goto error;
394 }
395 } else {
396 predefPtr = (TkPredefBitmap *) Tcl_GetHashValue(predefHashPtr);
397 width = predefPtr->width;
398 height = predefPtr->height;
399 if (predefPtr->native) {
400 bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin),
401 predefPtr->source);
402 if (bitmap == None) {
403 panic("native bitmap creation failed");
404 }
405 } else {
406 bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
407 RootWindowOfScreen(Tk_Screen(tkwin)),
408 predefPtr->source,
409 (unsigned) width, (unsigned) height);
410 }
411 }
412 }
413
414 /*
415 * Add information about this bitmap to our database.
416 */
417
418 bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
419 bitmapPtr->bitmap = bitmap;
420 bitmapPtr->width = width;
421 bitmapPtr->height = height;
422 bitmapPtr->display = Tk_Display(tkwin);
423 bitmapPtr->resourceRefCount = 1;
424 bitmapPtr->objRefCount = 0;
425 bitmapPtr->nameHashPtr = nameHashPtr;
426 bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable,
427 (char *) bitmap, &new);
428 if (!new) {
429 panic("bitmap already registered in Tk_GetBitmap");
430 }
431 bitmapPtr->nextPtr = existingBitmapPtr;
432 Tcl_SetHashValue(nameHashPtr, bitmapPtr);
433 Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr);
434 return bitmapPtr;
435
436 error:
437 if (new) {
438 Tcl_DeleteHashEntry(nameHashPtr);
439 }
440 return NULL;
441 }
442
443 /*
444 *----------------------------------------------------------------------
445 *
446 * Tk_DefineBitmap --
447 *
448 * This procedure associates a textual name with a binary bitmap
449 * description, so that the name may be used to refer to the
450 * bitmap in future calls to Tk_GetBitmap.
451 *
452 * Results:
453 * A standard Tcl result. If an error occurs then TCL_ERROR is
454 * returned and a message is left in the interp's result.
455 *
456 * Side effects:
457 * "Name" is entered into the bitmap table and may be used from
458 * here on to refer to the given bitmap.
459 *
460 *----------------------------------------------------------------------
461 */
462
463 int
464 Tk_DefineBitmap(interp, name, source, width, height)
465 Tcl_Interp *interp; /* Interpreter to use for error reporting. */
466 CONST char *name; /* Name to use for bitmap. Must not already
467 * be defined as a bitmap. */
468 char *source; /* Address of bits for bitmap. */
469 int width; /* Width of bitmap. */
470 int height; /* Height of bitmap. */
471 {
472 int new;
473 Tcl_HashEntry *predefHashPtr;
474 TkPredefBitmap *predefPtr;
475 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
476 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
477
478 /*
479 * Initialize the Bitmap module if not initialized already for this
480 * thread. Since the current TkDisplay structure cannot be
481 * introspected from here, pass a NULL pointer to BitmapInit,
482 * which will know to initialize only the data in the
483 * ThreadSpecificData structure for the current thread.
484 */
485
486 if (!tsdPtr->initialized) {
487 BitmapInit((TkDisplay *) NULL);
488 }
489
490 predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable,
491 name, &new);
492 if (!new) {
493 Tcl_AppendResult(interp, "bitmap \"", name,
494 "\" is already defined", (char *) NULL);
495 return TCL_ERROR;
496 }
497 predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap));
498 predefPtr->source = source;
499 predefPtr->width = width;
500 predefPtr->height = height;
501 predefPtr->native = 0;
502 Tcl_SetHashValue(predefHashPtr, predefPtr);
503 return TCL_OK;
504 }
505
506 /*
507 *--------------------------------------------------------------
508 *
509 * Tk_NameOfBitmap --
510 *
511 * Given a bitmap, return a textual string identifying the
512 * bitmap.
513 *
514 * Results:
515 * The return value is the string name associated with bitmap.
516 *
517 * Side effects:
518 * None.
519 *
520 *--------------------------------------------------------------
521 */
522
523 char *
524 Tk_NameOfBitmap(display, bitmap)
525 Display *display; /* Display for which bitmap was
526 * allocated. */
527 Pixmap bitmap; /* Bitmap whose name is wanted. */
528 {
529 Tcl_HashEntry *idHashPtr;
530 TkBitmap *bitmapPtr;
531 TkDisplay *dispPtr = TkGetDisplay(display);
532
533 if (dispPtr == NULL || !dispPtr->bitmapInit) {
534 unknown:
535 panic("Tk_NameOfBitmap received unknown bitmap argument");
536 }
537
538 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
539 if (idHashPtr == NULL) {
540 goto unknown;
541 }
542 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
543 return bitmapPtr->nameHashPtr->key.string;
544 }
545
546 /*
547 *--------------------------------------------------------------
548 *
549 * Tk_SizeOfBitmap --
550 *
551 * Given a bitmap managed by this module, returns the width
552 * and height of the bitmap.
553 *
554 * Results:
555 * The words at *widthPtr and *heightPtr are filled in with
556 * the dimenstions of bitmap.
557 *
558 * Side effects:
559 * If bitmap isn't managed by this module then the procedure
560 * panics..
561 *
562 *--------------------------------------------------------------
563 */
564
565 void
566 Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
567 Display *display; /* Display for which bitmap was
568 * allocated. */
569 Pixmap bitmap; /* Bitmap whose size is wanted. */
570 int *widthPtr; /* Store bitmap width here. */
571 int *heightPtr; /* Store bitmap height here. */
572 {
573 Tcl_HashEntry *idHashPtr;
574 TkBitmap *bitmapPtr;
575 TkDisplay *dispPtr = TkGetDisplay(display);
576
577 if (!dispPtr->bitmapInit) {
578 unknownBitmap:
579 panic("Tk_SizeOfBitmap received unknown bitmap argument");
580 }
581
582 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
583 if (idHashPtr == NULL) {
584 goto unknownBitmap;
585 }
586 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
587 *widthPtr = bitmapPtr->width;
588 *heightPtr = bitmapPtr->height;
589 }
590
591 /*
592 *----------------------------------------------------------------------
593 *
594 * FreeBitmap --
595 *
596 * This procedure does all the work of releasing a bitmap allocated by
597 * Tk_GetBitmap or TkGetBitmapFromData. It is invoked by both
598 * Tk_FreeBitmap and Tk_FreeBitmapFromObj
599 *
600 * Results:
601 * None.
602 *
603 * Side effects:
604 * The reference count associated with bitmap is decremented, and
605 * it is officially deallocated if no-one is using it anymore.
606 *
607 *----------------------------------------------------------------------
608 */
609
610 static void
611 FreeBitmap(bitmapPtr)
612 TkBitmap *bitmapPtr; /* Bitmap to be released. */
613 {
614 TkBitmap *prevPtr;
615
616 bitmapPtr->resourceRefCount--;
617 if (bitmapPtr->resourceRefCount > 0) {
618 return;
619 }
620
621 Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
622 Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);
623 prevPtr = (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr);
624 if (prevPtr == bitmapPtr) {
625 if (bitmapPtr->nextPtr == NULL) {
626 Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);
627 } else {
628 Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);
629 }
630 } else {
631 while (prevPtr->nextPtr != bitmapPtr) {
632 prevPtr = prevPtr->nextPtr;
633 }
634 prevPtr->nextPtr = bitmapPtr->nextPtr;
635 }
636 if (bitmapPtr->objRefCount == 0) {
637 ckfree((char *) bitmapPtr);
638 }
639 }
640
641 /*
642 *----------------------------------------------------------------------
643 *
644 * Tk_FreeBitmap --
645 *
646 * This procedure is called to release a bitmap allocated by
647 * Tk_GetBitmap or TkGetBitmapFromData.
648 *
649 * Results:
650 * None.
651 *
652 * Side effects:
653 * The reference count associated with bitmap is decremented, and
654 * it is officially deallocated if no-one is using it anymore.
655 *
656 *----------------------------------------------------------------------
657 */
658
659 void
660 Tk_FreeBitmap(display, bitmap)
661 Display *display; /* Display for which bitmap was
662 * allocated. */
663 Pixmap bitmap; /* Bitmap to be released. */
664 {
665 Tcl_HashEntry *idHashPtr;
666 TkDisplay *dispPtr = TkGetDisplay(display);
667
668 if (!dispPtr->bitmapInit) {
669 panic("Tk_FreeBitmap called before Tk_GetBitmap");
670 }
671
672 idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
673 if (idHashPtr == NULL) {
674 panic("Tk_FreeBitmap received unknown bitmap argument");
675 }
676 FreeBitmap((TkBitmap *) Tcl_GetHashValue(idHashPtr));
677 }
678
679 /*
680 *----------------------------------------------------------------------
681 *
682 * Tk_FreeBitmapFromObj --
683 *
684 * This procedure is called to release a bitmap allocated by
685 * Tk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *;
686 * it only gets rid of the hash table entry for this bitmap
687 * and clears the cached value that is normally stored in the object.
688 *
689 * Results:
690 * None.
691 *
692 * Side effects:
693 * The reference count associated with the bitmap represented by
694 * objPtr is decremented, and the bitmap is released to X if there are
695 * no remaining uses for it.
696 *
697 *----------------------------------------------------------------------
698 */
699
700 void
701 Tk_FreeBitmapFromObj(tkwin, objPtr)
702 Tk_Window tkwin; /* The window this bitmap lives in. Needed
703 * for the display value. */
704 Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */
705 {
706 FreeBitmap(GetBitmapFromObj(tkwin, objPtr));
707 }
708
709 /*
710 *---------------------------------------------------------------------------
711 *
712 * FreeBitmapObjProc --
713 *
714 * This proc is called to release an object reference to a bitmap.
715 * Called when the object's internal rep is released or when
716 * the cached bitmapPtr needs to be changed.
717 *
718 * Results:
719 * None.
720 *
721 * Side effects:
722 * The object reference count is decremented. When both it
723 * and the hash ref count go to zero, the color's resources
724 * are released.
725 *
726 *---------------------------------------------------------------------------
727 */
728
729 static void
730 FreeBitmapObjProc(objPtr)
731 Tcl_Obj *objPtr; /* The object we are releasing. */
732 {
733 TkBitmap *bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
734
735 if (bitmapPtr != NULL) {
736 bitmapPtr->objRefCount--;
737 if ((bitmapPtr->objRefCount == 0)
738 && (bitmapPtr->resourceRefCount == 0)) {
739 ckfree((char *) bitmapPtr);
740 }
741 objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
742 }
743 }
744
745 /*
746 *---------------------------------------------------------------------------
747 *
748 * DupBitmapObjProc --
749 *
750 * When a cached bitmap object is duplicated, this is called to
751 * update the internal reps.
752 *
753 * Results:
754 * None.
755 *
756 * Side effects:
757 * The color's objRefCount is incremented and the internal rep
758 * of the copy is set to point to it.
759 *
760 *---------------------------------------------------------------------------
761 */
762
763 static void
764 DupBitmapObjProc(srcObjPtr, dupObjPtr)
765 Tcl_Obj *srcObjPtr; /* The object we are copying from. */
766 Tcl_Obj *dupObjPtr; /* The object we are copying to. */
767 {
768 TkBitmap *bitmapPtr = (TkBitmap *) srcObjPtr->internalRep.twoPtrValue.ptr1;
769
770 dupObjPtr->typePtr = srcObjPtr->typePtr;
771 dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
772
773 if (bitmapPtr != NULL) {
774 bitmapPtr->objRefCount++;
775 }
776 }
777
778 /*
779 *----------------------------------------------------------------------
780 *
781 * Tk_GetBitmapFromData --
782 *
783 * Given a description of the bits for a bitmap, make a bitmap that
784 * has the given properties. *** NOTE: this procedure is obsolete
785 * and really shouldn't be used anymore. ***
786 *
787 * Results:
788 * The return value is the X identifer for the desired bitmap
789 * (a one-plane Pixmap), unless it couldn't be created properly.
790 * In this case, None is returned and an error message is left in
791 * the interp's result. The caller should never modify the bitmap that
792 * is returned, and should eventually call Tk_FreeBitmap when the
793 * bitmap is no longer needed.
794 *
795 * Side effects:
796 * The bitmap is added to an internal database with a reference count.
797 * For each call to this procedure, there should eventually be a call
798 * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
799 * aren't needed anymore.
800 *
801 *----------------------------------------------------------------------
802 */
803
804 /* ARGSUSED */
805 Pixmap
806 Tk_GetBitmapFromData(interp, tkwin, source, width, height)
807 Tcl_Interp *interp; /* Interpreter to use for error reporting. */
808 Tk_Window tkwin; /* Window in which bitmap will be used. */
809 char *source; /* Bitmap data for bitmap shape. */
810 int width, height; /* Dimensions of bitmap. */
811 {
812 DataKey nameKey;
813 Tcl_HashEntry *dataHashPtr;
814 int new;
815 char string[16 + TCL_INTEGER_SPACE];
816 char *name;
817 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
818
819 BitmapInit(dispPtr);
820
821 nameKey.source = source;
822 nameKey.width = width;
823 nameKey.height = height;
824 dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable,
825 (char *) &nameKey, &new);
826 if (!new) {
827 name = (char *) Tcl_GetHashValue(dataHashPtr);
828 } else {
829 dispPtr->bitmapAutoNumber++;
830 sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber);
831 name = string;
832 Tcl_SetHashValue(dataHashPtr, name);
833 if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
834 Tcl_DeleteHashEntry(dataHashPtr);
835 return TCL_ERROR;
836 }
837 }
838 return Tk_GetBitmap(interp, tkwin, name);
839 }
840
841 /*
842 *----------------------------------------------------------------------
843 *
844 * Tk_GetBitmapFromObj --
845 *
846 * Returns the bitmap referred to by a Tcl object. The bitmap must
847 * already have been allocated via a call to Tk_AllocBitmapFromObj
848 * or Tk_GetBitmap.
849 *
850 * Results:
851 * Returns the Pixmap that matches the tkwin and the string rep
852 * of objPtr.
853 *
854 * Side effects:
855 * If the object is not already a bitmap, the conversion will free
856 * any old internal representation.
857 *
858 *----------------------------------------------------------------------
859 */
860
861 Pixmap
862 Tk_GetBitmapFromObj(tkwin, objPtr)
863 Tk_Window tkwin;
864 Tcl_Obj *objPtr; /* The object from which to get pixels. */
865 {
866 TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr);
867 return bitmapPtr->bitmap;
868 }
869
870 /*
871 *----------------------------------------------------------------------
872 *
873 * GetBitmapFromObj --
874 *
875 * Returns the bitmap referred to by a Tcl object. The bitmap must
876 * already have been allocated via a call to Tk_AllocBitmapFromObj
877 * or Tk_GetBitmap.
878 *
879 * Results:
880 * Returns the TkBitmap * that matches the tkwin and the string rep
881 * of objPtr.
882 *
883 * Side effects:
884 * If the object is not already a bitmap, the conversion will free
885 * any old internal representation.
886 *
887 *----------------------------------------------------------------------
888 */
889
890 static TkBitmap *
891 GetBitmapFromObj(tkwin, objPtr)
892 Tk_Window tkwin; /* Window in which the bitmap will be used. */
893 Tcl_Obj *objPtr; /* The object that describes the desired
894 * bitmap. */
895 {
896 TkBitmap *bitmapPtr;
897 Tcl_HashEntry *hashPtr;
898 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
899
900 if (objPtr->typePtr != &bitmapObjType) {
901 InitBitmapObj(objPtr);
902 }
903
904 bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
905 if (bitmapPtr != NULL) {
906 if ((bitmapPtr->resourceRefCount > 0)
907 && (Tk_Display(tkwin) == bitmapPtr->display)) {
908 return bitmapPtr;
909 }
910 hashPtr = bitmapPtr->nameHashPtr;
911 FreeBitmapObjProc(objPtr);
912 } else {
913 hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable,
914 Tcl_GetString(objPtr));
915 if (hashPtr == NULL) {
916 goto error;
917 }
918 }
919
920 /*
921 * At this point we've got a hash table entry, off of which hang
922 * one or more TkBitmap structures. See if any of them will work.
923 */
924
925 for (bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr);
926 bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) {
927 if (Tk_Display(tkwin) == bitmapPtr->display) {
928 objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
929 bitmapPtr->objRefCount++;
930 return bitmapPtr;
931 }
932 }
933
934 error:
935 panic("GetBitmapFromObj called with non-existent bitmap!");
936 /*
937 * The following code isn't reached; it's just there to please compilers.
938 */
939 return NULL;
940 }
941
942 /*
943 *----------------------------------------------------------------------
944 *
945 * InitBitmapObj --
946 *
947 * Bookeeping procedure to change an objPtr to a bitmap type.
948 *
949 * Results:
950 * None.
951 *
952 * Side effects:
953 * The old internal rep of the object is freed. The internal
954 * rep is cleared. The final form of the object is set
955 * by either Tk_AllocBitmapFromObj or GetBitmapFromObj.
956 *
957 *----------------------------------------------------------------------
958 */
959
960 static void
961 InitBitmapObj(objPtr)
962 Tcl_Obj *objPtr; /* The object to convert. */
963 {
964 Tcl_ObjType *typePtr;
965
966 /*
967 * Free the old internalRep before setting the new one.
968 */
969
970 Tcl_GetString(objPtr);
971 typePtr = objPtr->typePtr;
972 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
973 (*typePtr->freeIntRepProc)(objPtr);
974 }
975 objPtr->typePtr = &bitmapObjType;
976 objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
977 }
978
979 /*
980 *----------------------------------------------------------------------
981 *
982 * BitmapInit --
983 * Initializes hash tables used by this module. Initializes
984 * tables stored in TkDisplay structure if a TkDisplay pointer
985 * is passed in. Iinitializes the thread-local data
986 * in the current thread's ThreadSpecificData structure.
987 *
988 * Results:
989 * None.
990 *
991 * Side effects:
992 * Read the code.
993 *
994 *----------------------------------------------------------------------
995 */
996
997 static void
998 BitmapInit(dispPtr)
999 TkDisplay *dispPtr; /* TkDisplay structure encapsulating
1000 * thread-specific data used by this
1001 * module, or NULL if unavailable. */
1002 {
1003 Tcl_Interp *dummy;
1004 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1005 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1006
1007 /*
1008 * First initialize the data in the ThreadSpecificData strucuture,
1009 * if needed.
1010 */
1011
1012 if (!tsdPtr->initialized) {
1013 tsdPtr->initialized = 1;
1014 dummy = Tcl_CreateInterp();
1015 Tcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS);
1016
1017 Tk_DefineBitmap(dummy, "error", (char *) error_bits,
1018 error_width, error_height);
1019 Tk_DefineBitmap(dummy, "gray75", (char *) gray75_bits,
1020 gray75_width, gray75_height);
1021 Tk_DefineBitmap(dummy, "gray50", (char *) gray50_bits,
1022 gray50_width, gray50_height);
1023 Tk_DefineBitmap(dummy, "gray25", (char *) gray25_bits,
1024 gray25_width, gray25_height);
1025 Tk_DefineBitmap(dummy, "gray12", (char *) gray12_bits,
1026 gray12_width, gray12_height);
1027 Tk_DefineBitmap(dummy, "hourglass", (char *) hourglass_bits,
1028 hourglass_width, hourglass_height);
1029 Tk_DefineBitmap(dummy, "info", (char *) info_bits,
1030 info_width, info_height);
1031 Tk_DefineBitmap(dummy, "questhead", (char *) questhead_bits,
1032 questhead_width, questhead_height);
1033 Tk_DefineBitmap(dummy, "question", (char *) question_bits,
1034 question_width, question_height);
1035 Tk_DefineBitmap(dummy, "warning", (char *) warning_bits,
1036 warning_width, warning_height);
1037
1038 TkpDefineNativeBitmaps();
1039 Tcl_DeleteInterp(dummy);
1040 }
1041
1042 /*
1043 * Was a valid TkDisplay pointer passed? If so, initialize the
1044 * Bitmap module tables in that structure.
1045 */
1046
1047 if (dispPtr != NULL) {
1048 dispPtr->bitmapInit = 1;
1049 Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS);
1050 Tcl_InitHashTable(&dispPtr->bitmapDataTable, sizeof(DataKey)
1051 /sizeof(int));
1052
1053 /*
1054 * The call below is tricky: can't use sizeof(IdKey) because it
1055 * gets padded with extra unpredictable bytes on some 64-bit
1056 * machines.
1057 */
1058
1059 /*
1060 * The comment above doesn't make sense...
1061 */
1062 Tcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS);
1063 }
1064 }
1065
1066 /*
1067 *----------------------------------------------------------------------
1068 *
1069 * TkReadBitmapFile --
1070 *
1071 * Loads a bitmap image in X bitmap format into the specified
1072 * drawable. This is equivelent to the XReadBitmapFile in X.
1073 *
1074 * Results:
1075 * Sets the size, hotspot, and bitmap on success.
1076 *
1077 * Side effects:
1078 * Creates a new bitmap from the file data.
1079 *
1080 *----------------------------------------------------------------------
1081 */
1082
1083 int
1084 TkReadBitmapFile(display, d, filename, width_return, height_return,
1085 bitmap_return, x_hot_return, y_hot_return)
1086 Display* display;
1087 Drawable d;
1088 CONST char* filename;
1089 unsigned int* width_return;
1090 unsigned int* height_return;
1091 Pixmap* bitmap_return;
1092 int* x_hot_return;
1093 int* y_hot_return;
1094 {
1095 char *data;
1096
1097 data = TkGetBitmapData(NULL, NULL, (char *) filename,
1098 (int *) width_return, (int *) height_return, x_hot_return,
1099 y_hot_return);
1100 if (data == NULL) {
1101 return BitmapFileInvalid;
1102 }
1103
1104 *bitmap_return = XCreateBitmapFromData(display, d, data, *width_return,
1105 *height_return);
1106
1107 ckfree(data);
1108 return BitmapSuccess;
1109 }
1110
1111 /*
1112 *----------------------------------------------------------------------
1113 *
1114 * TkDebugBitmap --
1115 *
1116 * This procedure returns debugging information about a bitmap.
1117 *
1118 * Results:
1119 * The return value is a list with one sublist for each TkBitmap
1120 * corresponding to "name". Each sublist has two elements that
1121 * contain the resourceRefCount and objRefCount fields from the
1122 * TkBitmap structure.
1123 *
1124 * Side effects:
1125 * None.
1126 *
1127 *----------------------------------------------------------------------
1128 */
1129
1130 Tcl_Obj *
1131 TkDebugBitmap(tkwin, name)
1132 Tk_Window tkwin; /* The window in which the bitmap will be
1133 * used (not currently used). */
1134 char *name; /* Name of the desired color. */
1135 {
1136 TkBitmap *bitmapPtr;
1137 Tcl_HashEntry *hashPtr;
1138 Tcl_Obj *resultPtr, *objPtr;
1139 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
1140
1141 resultPtr = Tcl_NewObj();
1142 hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name);
1143 if (hashPtr != NULL) {
1144 bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr);
1145 if (bitmapPtr == NULL) {
1146 panic("TkDebugBitmap found empty hash table entry");
1147 }
1148 for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) {
1149 objPtr = Tcl_NewObj();
1150 Tcl_ListObjAppendElement(NULL, objPtr,
1151 Tcl_NewIntObj(bitmapPtr->resourceRefCount));
1152 Tcl_ListObjAppendElement(NULL, objPtr,
1153 Tcl_NewIntObj(bitmapPtr->objRefCount));
1154 Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
1155 }
1156 }
1157 return resultPtr;
1158 }
1159
1160
1161 /*
1162 *----------------------------------------------------------------------
1163 *
1164 * TkGetBitmapPredefTable --
1165 * This procedure is used by tkMacBitmap.c to access the thread-
1166 * specific predefBitmap table that maps from the names of
1167 * the predefined bitmaps to data associated with those
1168 * bitmaps. It is required because the table is allocated in
1169 * thread-local storage and is not visible outside this file.
1170
1171 * Results:
1172 * Returns a pointer to the predefined bitmap hash table for
1173 * the current thread.
1174 *
1175 * Side effects:
1176 * None.
1177 *
1178 *----------------------------------------------------------------------
1179 */
1180 Tcl_HashTable *
1181 TkGetBitmapPredefTable()
1182 {
1183 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1184 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1185
1186 return &tsdPtr->predefBitmapTable;
1187 }
1188
1189 /* End of tkbitmap.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25