Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtk/generic/tkBitmap.c
1810 views
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 (c) 1990-1994 The Regents of the University of California.
9
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
10
*
11
* See the file "license.terms" for information on usage and redistribution
12
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
*
14
* SCCS: @(#) tkBitmap.c 1.37 96/07/23 16:54:40
15
*/
16
17
#include "tkInt.h"
18
19
/*
20
* The includes below are for pre-defined bitmaps.
21
*/
22
23
#include "error.bmp"
24
#include "gray12.bmp"
25
#include "gray25.bmp"
26
#include "gray50.bmp"
27
#include "hourglass.bmp"
28
#include "info.bmp"
29
#include "questhead.bmp"
30
#include "question.bmp"
31
#include "warning.bmp"
32
33
/*
34
* One of the following data structures exists for each bitmap that is
35
* currently in use. Each structure is indexed with both "idTable" and
36
* "nameTable".
37
*/
38
39
typedef struct {
40
Pixmap bitmap; /* X identifier for bitmap. None means this
41
* bitmap was created by Tk_DefineBitmap
42
* and it isn't currently in use. */
43
int width, height; /* Dimensions of bitmap. */
44
Display *display; /* Display for which bitmap is valid. */
45
int refCount; /* Number of active uses of bitmap. */
46
Tcl_HashEntry *hashPtr; /* Entry in nameTable for this structure
47
* (needed when deleting). */
48
} TkBitmap;
49
50
/*
51
* Hash table to map from a textual description of a bitmap to the
52
* TkBitmap record for the bitmap, and key structure used in that
53
* hash table:
54
*/
55
56
static Tcl_HashTable nameTable;
57
typedef struct {
58
Tk_Uid name; /* Textual name for desired bitmap. */
59
Screen *screen; /* Screen on which bitmap will be used. */
60
} NameKey;
61
62
/*
63
* Hash table that maps from <display + bitmap id> to the TkBitmap structure
64
* for the bitmap. This table is used by Tk_FreeBitmap.
65
*/
66
67
static Tcl_HashTable idTable;
68
typedef struct {
69
Display *display; /* Display for which bitmap was allocated. */
70
Pixmap pixmap; /* X identifier for pixmap. */
71
} IdKey;
72
73
/*
74
* For each call to Tk_DefineBitmap one of the following structures is
75
* created to hold information about the bitmap.
76
*/
77
78
typedef struct {
79
char *source; /* Bits for bitmap. */
80
int width, height; /* Dimensions of bitmap. */
81
} PredefBitmap;
82
83
/*
84
* Hash table create by Tk_DefineBitmap to map from a name to a
85
* collection of in-core data about a bitmap. The table is
86
* indexed by the address of the data for the bitmap, and the entries
87
* contain pointers to PredefBitmap structures.
88
*/
89
90
static Tcl_HashTable predefTable;
91
92
/*
93
* Hash table used by Tk_GetBitmapFromData to map from a collection
94
* of in-core data about a bitmap to a Tk_Uid giving an automatically-
95
* generated name for the bitmap:
96
*/
97
98
static Tcl_HashTable dataTable;
99
typedef struct {
100
char *source; /* Bitmap bits. */
101
int width, height; /* Dimensions of bitmap. */
102
} DataKey;
103
104
static int initialized = 0; /* 0 means static structures haven't been
105
* initialized yet. */
106
107
/*
108
* Forward declarations for procedures defined in this file:
109
*/
110
111
static void BitmapInit _ANSI_ARGS_((void));
112
113
/*
114
*----------------------------------------------------------------------
115
*
116
* Tk_GetBitmap --
117
*
118
* Given a string describing a bitmap, locate (or create if necessary)
119
* a bitmap that fits the description.
120
*
121
* Results:
122
* The return value is the X identifer for the desired bitmap
123
* (i.e. a Pixmap with a single plane), unless string couldn't be
124
* parsed correctly. In this case, None is returned and an error
125
* message is left in interp->result. The caller should never
126
* modify the bitmap that is returned, and should eventually call
127
* Tk_FreeBitmap when the bitmap is no longer needed.
128
*
129
* Side effects:
130
* The bitmap is added to an internal database with a reference count.
131
* For each call to this procedure, there should eventually be a call
132
* to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
133
* aren't needed anymore.
134
*
135
*----------------------------------------------------------------------
136
*/
137
138
Pixmap
139
Tk_GetBitmap(interp, tkwin, string)
140
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
141
Tk_Window tkwin; /* Window in which bitmap will be used. */
142
Tk_Uid string; /* Description of bitmap. See manual entry
143
* for details on legal syntax. */
144
{
145
NameKey nameKey;
146
IdKey idKey;
147
Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
148
register TkBitmap *bitmapPtr;
149
PredefBitmap *predefPtr;
150
int new;
151
Pixmap bitmap;
152
int width, height;
153
int dummy2;
154
155
if (!initialized) {
156
BitmapInit();
157
}
158
159
nameKey.name = string;
160
nameKey.screen = Tk_Screen(tkwin);
161
nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
162
if (!new) {
163
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
164
bitmapPtr->refCount++;
165
return bitmapPtr->bitmap;
166
}
167
168
/*
169
* No suitable bitmap exists. Create a new bitmap from the
170
* information contained in the string. If the string starts
171
* with "@" then the rest of the string is a file name containing
172
* the bitmap. Otherwise the string must refer to a bitmap
173
* defined by a call to Tk_DefineBitmap.
174
*/
175
176
if (*string == '@') {
177
Tcl_DString buffer;
178
int result;
179
180
string = Tcl_TranslateFileName(interp, string + 1, &buffer);
181
if (string == NULL) {
182
goto error;
183
}
184
result = XReadBitmapFile(Tk_Display(tkwin),
185
RootWindowOfScreen(nameKey.screen), string,
186
(unsigned int *) &width, (unsigned int *) &height,
187
&bitmap, &dummy2, &dummy2);
188
Tcl_DStringFree(&buffer);
189
if (result != BitmapSuccess) {
190
Tcl_AppendResult(interp, "error reading bitmap file \"", string,
191
"\"", (char *) NULL);
192
goto error;
193
}
194
} else {
195
predefHashPtr = Tcl_FindHashEntry(&predefTable, string);
196
if (predefHashPtr == NULL) {
197
/*
198
* The check for a NULL interpreter is a special hack that
199
* allows this procedure to be called from GetShadows in
200
* tk3d.c, where it doesn't have an intepreter handle.
201
*/
202
203
if (interp != NULL) {
204
Tcl_AppendResult(interp, "bitmap \"", string,
205
"\" not defined", (char *) NULL);
206
}
207
goto error;
208
}
209
predefPtr = (PredefBitmap *) Tcl_GetHashValue(predefHashPtr);
210
width = predefPtr->width;
211
height = predefPtr->height;
212
bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
213
RootWindowOfScreen(nameKey.screen), predefPtr->source,
214
(unsigned) width, (unsigned) height);
215
}
216
217
/*
218
* Add information about this bitmap to our database.
219
*/
220
221
bitmapPtr = (TkBitmap *) ckalloc(sizeof(TkBitmap));
222
bitmapPtr->bitmap = bitmap;
223
bitmapPtr->width = width;
224
bitmapPtr->height = height;
225
bitmapPtr->display = Tk_Display(tkwin);
226
bitmapPtr->refCount = 1;
227
bitmapPtr->hashPtr = nameHashPtr;
228
idKey.display = bitmapPtr->display;
229
idKey.pixmap = bitmap;
230
idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
231
&new);
232
if (!new) {
233
panic("bitmap already registered in Tk_GetBitmap");
234
}
235
Tcl_SetHashValue(nameHashPtr, bitmapPtr);
236
Tcl_SetHashValue(idHashPtr, bitmapPtr);
237
return bitmapPtr->bitmap;
238
239
error:
240
Tcl_DeleteHashEntry(nameHashPtr);
241
return None;
242
}
243
244
/*
245
*----------------------------------------------------------------------
246
*
247
* Tk_DefineBitmap --
248
*
249
* This procedure associates a textual name with a binary bitmap
250
* description, so that the name may be used to refer to the
251
* bitmap in future calls to Tk_GetBitmap.
252
*
253
* Results:
254
* A standard Tcl result. If an error occurs then TCL_ERROR is
255
* returned and a message is left in interp->result.
256
*
257
* Side effects:
258
* "Name" is entered into the bitmap table and may be used from
259
* here on to refer to the given bitmap.
260
*
261
*----------------------------------------------------------------------
262
*/
263
264
int
265
Tk_DefineBitmap(interp, name, source, width, height)
266
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
267
Tk_Uid name; /* Name to use for bitmap. Must not already
268
* be defined as a bitmap. */
269
char *source; /* Address of bits for bitmap. */
270
int width; /* Width of bitmap. */
271
int height; /* Height of bitmap. */
272
{
273
int new;
274
Tcl_HashEntry *predefHashPtr;
275
PredefBitmap *predefPtr;
276
277
if (!initialized) {
278
BitmapInit();
279
}
280
281
predefHashPtr = Tcl_CreateHashEntry(&predefTable, name, &new);
282
if (!new) {
283
Tcl_AppendResult(interp, "bitmap \"", name,
284
"\" is already defined", (char *) NULL);
285
return TCL_ERROR;
286
}
287
predefPtr = (PredefBitmap *) ckalloc(sizeof(PredefBitmap));
288
predefPtr->source = source;
289
predefPtr->width = width;
290
predefPtr->height = height;
291
Tcl_SetHashValue(predefHashPtr, predefPtr);
292
return TCL_OK;
293
}
294
295
/*
296
*--------------------------------------------------------------
297
*
298
* Tk_NameOfBitmap --
299
*
300
* Given a bitmap, return a textual string identifying the
301
* bitmap.
302
*
303
* Results:
304
* The return value is the string name associated with bitmap.
305
*
306
* Side effects:
307
* None.
308
*
309
*--------------------------------------------------------------
310
*/
311
312
Tk_Uid
313
Tk_NameOfBitmap(display, bitmap)
314
Display *display; /* Display for which bitmap was
315
* allocated. */
316
Pixmap bitmap; /* Bitmap whose name is wanted. */
317
{
318
IdKey idKey;
319
Tcl_HashEntry *idHashPtr;
320
TkBitmap *bitmapPtr;
321
void *ptr;
322
323
if (!initialized) {
324
unknown:
325
panic("Tk_NameOfBitmap received unknown bitmap argument");
326
}
327
328
idKey.display = display;
329
idKey.pixmap = bitmap;
330
idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
331
if (idHashPtr == NULL) {
332
goto unknown;
333
}
334
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
335
ptr = bitmapPtr->hashPtr->key.words;
336
return ((NameKey *) ptr)->name;
337
}
338
339
/*
340
*--------------------------------------------------------------
341
*
342
* Tk_SizeOfBitmap --
343
*
344
* Given a bitmap managed by this module, returns the width
345
* and height of the bitmap.
346
*
347
* Results:
348
* The words at *widthPtr and *heightPtr are filled in with
349
* the dimenstions of bitmap.
350
*
351
* Side effects:
352
* If bitmap isn't managed by this module then the procedure
353
* panics..
354
*
355
*--------------------------------------------------------------
356
*/
357
358
void
359
Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
360
Display *display; /* Display for which bitmap was
361
* allocated. */
362
Pixmap bitmap; /* Bitmap whose size is wanted. */
363
int *widthPtr; /* Store bitmap width here. */
364
int *heightPtr; /* Store bitmap height here. */
365
{
366
IdKey idKey;
367
Tcl_HashEntry *idHashPtr;
368
TkBitmap *bitmapPtr;
369
370
if (!initialized) {
371
unknownBitmap:
372
panic("Tk_SizeOfBitmap received unknown bitmap argument");
373
}
374
375
idKey.display = display;
376
idKey.pixmap = bitmap;
377
idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
378
if (idHashPtr == NULL) {
379
goto unknownBitmap;
380
}
381
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
382
*widthPtr = bitmapPtr->width;
383
*heightPtr = bitmapPtr->height;
384
}
385
386
/*
387
*----------------------------------------------------------------------
388
*
389
* Tk_FreeBitmap --
390
*
391
* This procedure is called to release a bitmap allocated by
392
* Tk_GetBitmap or TkGetBitmapFromData.
393
*
394
* Results:
395
* None.
396
*
397
* Side effects:
398
* The reference count associated with bitmap is decremented, and
399
* it is officially deallocated if no-one is using it anymore.
400
*
401
*----------------------------------------------------------------------
402
*/
403
404
void
405
Tk_FreeBitmap(display, bitmap)
406
Display *display; /* Display for which bitmap was
407
* allocated. */
408
Pixmap bitmap; /* Bitmap to be released. */
409
{
410
Tcl_HashEntry *idHashPtr;
411
register TkBitmap *bitmapPtr;
412
IdKey idKey;
413
414
if (!initialized) {
415
panic("Tk_FreeBitmap called before Tk_GetBitmap");
416
}
417
418
idKey.display = display;
419
idKey.pixmap = bitmap;
420
idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
421
if (idHashPtr == NULL) {
422
panic("Tk_FreeBitmap received unknown bitmap argument");
423
}
424
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
425
bitmapPtr->refCount--;
426
if (bitmapPtr->refCount == 0) {
427
Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
428
Tcl_DeleteHashEntry(idHashPtr);
429
Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
430
ckfree((char *) bitmapPtr);
431
}
432
}
433
434
/*
435
*----------------------------------------------------------------------
436
*
437
* Tk_GetBitmapFromData --
438
*
439
* Given a description of the bits for a bitmap, make a bitmap that
440
* has the given properties. *** NOTE: this procedure is obsolete
441
* and really shouldn't be used anymore. ***
442
*
443
* Results:
444
* The return value is the X identifer for the desired bitmap
445
* (a one-plane Pixmap), unless it couldn't be created properly.
446
* In this case, None is returned and an error message is left in
447
* interp->result. The caller should never modify the bitmap that
448
* is returned, and should eventually call Tk_FreeBitmap when the
449
* bitmap is no longer needed.
450
*
451
* Side effects:
452
* The bitmap is added to an internal database with a reference count.
453
* For each call to this procedure, there should eventually be a call
454
* to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps
455
* aren't needed anymore.
456
*
457
*----------------------------------------------------------------------
458
*/
459
460
/* ARGSUSED */
461
Pixmap
462
Tk_GetBitmapFromData(interp, tkwin, source, width, height)
463
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
464
Tk_Window tkwin; /* Window in which bitmap will be used. */
465
char *source; /* Bitmap data for bitmap shape. */
466
int width, height; /* Dimensions of bitmap. */
467
{
468
DataKey nameKey;
469
Tcl_HashEntry *dataHashPtr;
470
Tk_Uid name = NULL; /* Initialization need only to prevent
471
* compiler warning. */
472
int new;
473
static int autoNumber = 0;
474
char string[20];
475
476
if (!initialized) {
477
BitmapInit();
478
}
479
480
nameKey.source = source;
481
nameKey.width = width;
482
nameKey.height = height;
483
dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
484
if (!new) {
485
name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
486
} else {
487
autoNumber++;
488
sprintf(string, "_tk%d", autoNumber);
489
name = Tk_GetUid(string);
490
Tcl_SetHashValue(dataHashPtr, name);
491
if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
492
Tcl_DeleteHashEntry(dataHashPtr);
493
return TCL_ERROR;
494
}
495
}
496
return Tk_GetBitmap(interp, tkwin, name);
497
}
498
499
/*
500
*----------------------------------------------------------------------
501
*
502
* BitmapInit --
503
*
504
* Initialize the structures used for bitmap management.
505
*
506
* Results:
507
* None.
508
*
509
* Side effects:
510
* Read the code.
511
*
512
*----------------------------------------------------------------------
513
*/
514
515
static void
516
BitmapInit()
517
{
518
Tcl_Interp *dummy;
519
520
dummy = Tcl_CreateInterp();
521
initialized = 1;
522
Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
523
Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
524
Tcl_InitHashTable(&predefTable, TCL_ONE_WORD_KEYS);
525
526
/*
527
* The call below is tricky: can't use sizeof(IdKey) because it
528
* gets padded with extra unpredictable bytes on some 64-bit
529
* machines.
530
*/
531
532
Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap))
533
/sizeof(int));
534
535
Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits,
536
error_width, error_height);
537
Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits,
538
gray50_width, gray50_height);
539
Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits,
540
gray25_width, gray25_height);
541
Tk_DefineBitmap(dummy, Tk_GetUid("gray12"), (char *) gray12_bits,
542
gray12_width, gray12_height);
543
Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits,
544
hourglass_width, hourglass_height);
545
Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits,
546
info_width, info_height);
547
Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits,
548
questhead_width, questhead_height);
549
Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits,
550
question_width, question_height);
551
Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits,
552
warning_width, warning_height);
553
Tcl_DeleteInterp(dummy);
554
}
555
556