1 |
dashley |
69 |
/* $Header$ */
|
2 |
dashley |
25 |
|
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 |
dashley |
69 |
/* End of tkbitmap.c */
|