4
* This file maintains a database of read-only cursors for the Tk
5
* toolkit. This allows cursors to be shared between widgets and
6
* also avoids round-trips to the X server.
8
* Copyright (c) 1990-1994 The Regents of the University of California.
9
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
11
* See the file "license.terms" for information on usage and redistribution
12
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
* RCS: @(#) $Id: tkCursor.c,v 1.2 1998/09/14 18:23:09 stanton Exp $
21
* A TkCursor structure exists for each cursor that is currently
22
* active. Each structure is indexed with two hash tables defined
23
* below. One of the tables is idTable, and the other is either
24
* nameTable or dataTable, also defined below.
28
* Hash table to map from a textual description of a cursor to the
29
* TkCursor record for the cursor, and key structure used in that
33
static Tcl_HashTable nameTable;
35
Tk_Uid name; /* Textual name for desired cursor. */
36
Display *display; /* Display for which cursor will be used. */
40
* Hash table to map from a collection of in-core data about a
41
* cursor (bitmap contents, etc.) to a TkCursor structure:
44
static Tcl_HashTable dataTable;
46
char *source; /* Cursor bits. */
47
char *mask; /* Mask bits. */
48
int width, height; /* Dimensions of cursor (and data
50
int xHot, yHot; /* Location of cursor hot-spot. */
51
Tk_Uid fg, bg; /* Colors for cursor. */
52
Display *display; /* Display on which cursor will be used. */
56
* Hash table that maps from <display + cursor id> to the TkCursor structure
57
* for the cursor. This table is used by Tk_FreeCursor.
60
static Tcl_HashTable idTable;
62
Display *display; /* Display for which cursor was allocated. */
63
Tk_Cursor cursor; /* Cursor identifier. */
66
static int initialized = 0; /* 0 means static structures haven't been
70
* Forward declarations for procedures defined in this file:
73
static void CursorInit _ANSI_ARGS_((void));
76
*----------------------------------------------------------------------
80
* Given a string describing a cursor, locate (or create if necessary)
81
* a cursor that fits the description.
84
* The return value is the X identifer for the desired cursor,
85
* unless string couldn't be parsed correctly. In this case,
86
* None is returned and an error message is left in interp->result.
87
* The caller should never modify the cursor that is returned, and
88
* should eventually call Tk_FreeCursor when the cursor is no longer
92
* The cursor is added to an internal database with a reference count.
93
* For each call to this procedure, there should eventually be a call
94
* to Tk_FreeCursor, so that the database can be cleaned up when cursors
95
* aren't needed anymore.
97
*----------------------------------------------------------------------
101
Tk_GetCursor(interp, tkwin, string)
102
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
103
Tk_Window tkwin; /* Window in which cursor will be used. */
104
Tk_Uid string; /* Description of cursor. See manual entry
105
* for details on legal syntax. */
109
Tcl_HashEntry *nameHashPtr, *idHashPtr;
110
register TkCursor *cursorPtr;
117
nameKey.name = string;
118
nameKey.display = Tk_Display(tkwin);
119
nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
121
cursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr);
122
cursorPtr->refCount++;
123
return cursorPtr->cursor;
126
cursorPtr = TkGetCursorByName(interp, tkwin, string);
128
if (cursorPtr == NULL) {
129
Tcl_DeleteHashEntry(nameHashPtr);
134
* Add information about this cursor to our database.
137
cursorPtr->refCount = 1;
138
cursorPtr->otherTable = &nameTable;
139
cursorPtr->hashPtr = nameHashPtr;
140
idKey.display = nameKey.display;
141
idKey.cursor = cursorPtr->cursor;
142
idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
144
panic("cursor already registered in Tk_GetCursor");
146
Tcl_SetHashValue(nameHashPtr, cursorPtr);
147
Tcl_SetHashValue(idHashPtr, cursorPtr);
149
return cursorPtr->cursor;
153
*----------------------------------------------------------------------
155
* Tk_GetCursorFromData --
157
* Given a description of the bits and colors for a cursor,
158
* make a cursor that has the given properties.
161
* The return value is the X identifer for the desired cursor,
162
* unless it couldn't be created properly. In this case, None is
163
* returned and an error message is left in interp->result. The
164
* caller should never modify the cursor that is returned, and
165
* should eventually call Tk_FreeCursor when the cursor is no
169
* The cursor is added to an internal database with a reference count.
170
* For each call to this procedure, there should eventually be a call
171
* to Tk_FreeCursor, so that the database can be cleaned up when cursors
172
* aren't needed anymore.
174
*----------------------------------------------------------------------
178
Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
180
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
181
Tk_Window tkwin; /* Window in which cursor will be used. */
182
char *source; /* Bitmap data for cursor shape. */
183
char *mask; /* Bitmap data for cursor mask. */
184
int width, height; /* Dimensions of cursor. */
185
int xHot, yHot; /* Location of hot-spot in cursor. */
186
Tk_Uid fg; /* Foreground color for cursor. */
187
Tk_Uid bg; /* Background color for cursor. */
191
Tcl_HashEntry *dataHashPtr, *idHashPtr;
192
register TkCursor *cursorPtr;
194
XColor fgColor, bgColor;
200
dataKey.source = source;
202
dataKey.width = width;
203
dataKey.height = height;
208
dataKey.display = Tk_Display(tkwin);
209
dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &dataKey, &new);
211
cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr);
212
cursorPtr->refCount++;
213
return cursorPtr->cursor;
217
* No suitable cursor exists yet. Make one using the data
218
* available and add it to the database.
221
if (XParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) {
222
Tcl_AppendResult(interp, "invalid color name \"", fg, "\"",
226
if (XParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) {
227
Tcl_AppendResult(interp, "invalid color name \"", bg, "\"",
232
cursorPtr = TkCreateCursorFromData(tkwin, source, mask, width, height,
233
xHot, yHot, fgColor, bgColor);
235
if (cursorPtr == NULL) {
239
cursorPtr->refCount = 1;
240
cursorPtr->otherTable = &dataTable;
241
cursorPtr->hashPtr = dataHashPtr;
242
idKey.display = dataKey.display;
243
idKey.cursor = cursorPtr->cursor;
244
idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
246
panic("cursor already registered in Tk_GetCursorFromData");
248
Tcl_SetHashValue(dataHashPtr, cursorPtr);
249
Tcl_SetHashValue(idHashPtr, cursorPtr);
250
return cursorPtr->cursor;
253
Tcl_DeleteHashEntry(dataHashPtr);
258
*--------------------------------------------------------------
262
* Given a cursor, return a textual string identifying it.
265
* If cursor was created by Tk_GetCursor, then the return
266
* value is the "string" that was used to create it.
267
* Otherwise the return value is a string giving the X
268
* identifier for the cursor. The storage for the returned
269
* string is only guaranteed to persist up until the next
270
* call to this procedure.
275
*--------------------------------------------------------------
279
Tk_NameOfCursor(display, cursor)
280
Display *display; /* Display for which cursor was allocated. */
281
Tk_Cursor cursor; /* Identifier for cursor whose name is
285
Tcl_HashEntry *idHashPtr;
287
static char string[20];
291
sprintf(string, "cursor id 0x%x", (unsigned int) cursor);
294
idKey.display = display;
295
idKey.cursor = cursor;
296
idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
297
if (idHashPtr == NULL) {
300
cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr);
301
if (cursorPtr->otherTable != &nameTable) {
304
return ((NameKey *) cursorPtr->hashPtr->key.words)->name;
308
*----------------------------------------------------------------------
312
* This procedure is called to release a cursor allocated by
313
* Tk_GetCursor or TkGetCursorFromData.
319
* The reference count associated with cursor is decremented, and
320
* it is officially deallocated if no-one is using it anymore.
322
*----------------------------------------------------------------------
326
Tk_FreeCursor(display, cursor)
327
Display *display; /* Display for which cursor was allocated. */
328
Tk_Cursor cursor; /* Identifier for cursor to be released. */
331
Tcl_HashEntry *idHashPtr;
332
register TkCursor *cursorPtr;
335
panic("Tk_FreeCursor called before Tk_GetCursor");
338
idKey.display = display;
339
idKey.cursor = cursor;
340
idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
341
if (idHashPtr == NULL) {
342
panic("Tk_FreeCursor received unknown cursor argument");
344
cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr);
345
cursorPtr->refCount--;
346
if (cursorPtr->refCount == 0) {
347
Tcl_DeleteHashEntry(cursorPtr->hashPtr);
348
Tcl_DeleteHashEntry(idHashPtr);
349
TkFreeCursor(cursorPtr);
354
*----------------------------------------------------------------------
358
* Initialize the structures used for cursor management.
366
*----------------------------------------------------------------------
373
Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
374
Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
377
* The call below is tricky: can't use sizeof(IdKey) because it
378
* gets padded with extra unpredictable bytes on some 64-bit
382
Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Tk_Cursor))