~ubuntu-branches/ubuntu/dapper/tk8.0/dapper-updates

« back to all changes in this revision

Viewing changes to generic/tkCursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Mike Markley
  • Date: 2001-07-24 21:57:40 UTC
  • Revision ID: james.westby@ubuntu.com-20010724215740-r70t25rtmbqjil2h
Tags: upstream-8.0.5
ImportĀ upstreamĀ versionĀ 8.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * tkCursor.c --
 
3
 *
 
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.
 
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
 * RCS: @(#) $Id: tkCursor.c,v 1.2 1998/09/14 18:23:09 stanton Exp $
 
15
 */
 
16
 
 
17
#include "tkPort.h"
 
18
#include "tkInt.h"
 
19
 
 
20
/*
 
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.
 
25
 */
 
26
 
 
27
/*
 
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
 
30
 * hash table:
 
31
 */
 
32
 
 
33
static Tcl_HashTable nameTable;
 
34
typedef struct {
 
35
    Tk_Uid name;                /* Textual name for desired cursor. */
 
36
    Display *display;           /* Display for which cursor will be used. */
 
37
} NameKey;
 
38
 
 
39
/*
 
40
 * Hash table to map from a collection of in-core data about a
 
41
 * cursor (bitmap contents, etc.) to a TkCursor structure:
 
42
 */
 
43
 
 
44
static Tcl_HashTable dataTable;
 
45
typedef struct {
 
46
    char *source;               /* Cursor bits. */
 
47
    char *mask;                 /* Mask bits. */
 
48
    int width, height;          /* Dimensions of cursor (and data
 
49
                                 * and mask). */
 
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. */
 
53
} DataKey;
 
54
 
 
55
/*
 
56
 * Hash table that maps from <display + cursor id> to the TkCursor structure
 
57
 * for the cursor.  This table is used by Tk_FreeCursor.
 
58
 */
 
59
 
 
60
static Tcl_HashTable idTable;
 
61
typedef struct {
 
62
    Display *display;           /* Display for which cursor was allocated. */
 
63
    Tk_Cursor cursor;           /* Cursor identifier. */
 
64
} IdKey;
 
65
 
 
66
static int initialized = 0;     /* 0 means static structures haven't been
 
67
                                 * initialized yet. */
 
68
 
 
69
/*
 
70
 * Forward declarations for procedures defined in this file:
 
71
 */
 
72
 
 
73
static void             CursorInit _ANSI_ARGS_((void));
 
74
 
 
75
/*
 
76
 *----------------------------------------------------------------------
 
77
 *
 
78
 * Tk_GetCursor --
 
79
 *
 
80
 *      Given a string describing a cursor, locate (or create if necessary)
 
81
 *      a cursor that fits the description.
 
82
 *
 
83
 * Results:
 
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
 
89
 *      needed.
 
90
 *
 
91
 * Side effects:
 
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.
 
96
 *
 
97
 *----------------------------------------------------------------------
 
98
 */
 
99
 
 
100
Tk_Cursor
 
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. */
 
106
{
 
107
    NameKey nameKey;
 
108
    IdKey idKey;
 
109
    Tcl_HashEntry *nameHashPtr, *idHashPtr;
 
110
    register TkCursor *cursorPtr;
 
111
    int new;
 
112
 
 
113
    if (!initialized) {
 
114
        CursorInit();
 
115
    }
 
116
 
 
117
    nameKey.name = string;
 
118
    nameKey.display = Tk_Display(tkwin);
 
119
    nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
 
120
    if (!new) {
 
121
        cursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr);
 
122
        cursorPtr->refCount++;
 
123
        return cursorPtr->cursor;
 
124
    }
 
125
 
 
126
    cursorPtr = TkGetCursorByName(interp, tkwin, string);
 
127
 
 
128
    if (cursorPtr == NULL) {
 
129
        Tcl_DeleteHashEntry(nameHashPtr);
 
130
        return None;
 
131
    }
 
132
 
 
133
    /*
 
134
     * Add information about this cursor to our database.
 
135
     */
 
136
 
 
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);
 
143
    if (!new) {
 
144
        panic("cursor already registered in Tk_GetCursor");
 
145
    }
 
146
    Tcl_SetHashValue(nameHashPtr, cursorPtr);
 
147
    Tcl_SetHashValue(idHashPtr, cursorPtr);
 
148
 
 
149
    return cursorPtr->cursor;
 
150
}
 
151
 
 
152
/*
 
153
 *----------------------------------------------------------------------
 
154
 *
 
155
 * Tk_GetCursorFromData --
 
156
 *
 
157
 *      Given a description of the bits and colors for a cursor,
 
158
 *      make a cursor that has the given properties.
 
159
 *
 
160
 * Results:
 
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
 
166
 *      longer needed.
 
167
 *
 
168
 * Side effects:
 
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.
 
173
 *
 
174
 *----------------------------------------------------------------------
 
175
 */
 
176
 
 
177
Tk_Cursor
 
178
Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
 
179
        xHot, yHot, fg, bg)
 
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. */
 
188
{
 
189
    DataKey dataKey;
 
190
    IdKey idKey;
 
191
    Tcl_HashEntry *dataHashPtr, *idHashPtr;
 
192
    register TkCursor *cursorPtr;
 
193
    int new;
 
194
    XColor fgColor, bgColor;
 
195
 
 
196
    if (!initialized) {
 
197
        CursorInit();
 
198
    }
 
199
 
 
200
    dataKey.source = source;
 
201
    dataKey.mask = mask;
 
202
    dataKey.width = width;
 
203
    dataKey.height = height;
 
204
    dataKey.xHot = xHot;
 
205
    dataKey.yHot = yHot;
 
206
    dataKey.fg = fg;
 
207
    dataKey.bg = bg;
 
208
    dataKey.display = Tk_Display(tkwin);
 
209
    dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &dataKey, &new);
 
210
    if (!new) {
 
211
        cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr);
 
212
        cursorPtr->refCount++;
 
213
        return cursorPtr->cursor;
 
214
    }
 
215
 
 
216
    /*
 
217
     * No suitable cursor exists yet.  Make one using the data
 
218
     * available and add it to the database.
 
219
     */
 
220
 
 
221
    if (XParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) {
 
222
        Tcl_AppendResult(interp, "invalid color name \"", fg, "\"",
 
223
                (char *) NULL);
 
224
        goto error;
 
225
    }
 
226
    if (XParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) {
 
227
        Tcl_AppendResult(interp, "invalid color name \"", bg, "\"",
 
228
                (char *) NULL);
 
229
        goto error;
 
230
    }
 
231
 
 
232
    cursorPtr = TkCreateCursorFromData(tkwin, source, mask, width, height,
 
233
            xHot, yHot, fgColor, bgColor);
 
234
 
 
235
    if (cursorPtr == NULL) {
 
236
        goto error;
 
237
    }
 
238
 
 
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);
 
245
    if (!new) {
 
246
        panic("cursor already registered in Tk_GetCursorFromData");
 
247
    }
 
248
    Tcl_SetHashValue(dataHashPtr, cursorPtr);
 
249
    Tcl_SetHashValue(idHashPtr, cursorPtr);
 
250
    return cursorPtr->cursor;
 
251
 
 
252
    error:
 
253
    Tcl_DeleteHashEntry(dataHashPtr);
 
254
    return None;
 
255
}
 
256
 
 
257
/*
 
258
 *--------------------------------------------------------------
 
259
 *
 
260
 * Tk_NameOfCursor --
 
261
 *
 
262
 *      Given a cursor, return a textual string identifying it.
 
263
 *
 
264
 * Results:
 
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.
 
271
 *
 
272
 * Side effects:
 
273
 *      None.
 
274
 *
 
275
 *--------------------------------------------------------------
 
276
 */
 
277
 
 
278
char *
 
279
Tk_NameOfCursor(display, cursor)
 
280
    Display *display;           /* Display for which cursor was allocated. */
 
281
    Tk_Cursor cursor;           /* Identifier for cursor whose name is
 
282
                                 * wanted. */
 
283
{
 
284
    IdKey idKey;
 
285
    Tcl_HashEntry *idHashPtr;
 
286
    TkCursor *cursorPtr;
 
287
    static char string[20];
 
288
 
 
289
    if (!initialized) {
 
290
        printid:
 
291
        sprintf(string, "cursor id 0x%x", (unsigned int) cursor);
 
292
        return string;
 
293
    }
 
294
    idKey.display = display;
 
295
    idKey.cursor = cursor;
 
296
    idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
 
297
    if (idHashPtr == NULL) {
 
298
        goto printid;
 
299
    }
 
300
    cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr);
 
301
    if (cursorPtr->otherTable != &nameTable) {
 
302
        goto printid;
 
303
    }
 
304
    return ((NameKey *) cursorPtr->hashPtr->key.words)->name;
 
305
}
 
306
 
 
307
/*
 
308
 *----------------------------------------------------------------------
 
309
 *
 
310
 * Tk_FreeCursor --
 
311
 *
 
312
 *      This procedure is called to release a cursor allocated by
 
313
 *      Tk_GetCursor or TkGetCursorFromData.
 
314
 *
 
315
 * Results:
 
316
 *      None.
 
317
 *
 
318
 * Side effects:
 
319
 *      The reference count associated with cursor is decremented, and
 
320
 *      it is officially deallocated if no-one is using it anymore.
 
321
 *
 
322
 *----------------------------------------------------------------------
 
323
 */
 
324
 
 
325
void
 
326
Tk_FreeCursor(display, cursor)
 
327
    Display *display;           /* Display for which cursor was allocated. */
 
328
    Tk_Cursor cursor;           /* Identifier for cursor to be released. */
 
329
{
 
330
    IdKey idKey;
 
331
    Tcl_HashEntry *idHashPtr;
 
332
    register TkCursor *cursorPtr;
 
333
 
 
334
    if (!initialized) {
 
335
        panic("Tk_FreeCursor called before Tk_GetCursor");
 
336
    }
 
337
 
 
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");
 
343
    }
 
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);
 
350
    }
 
351
}
 
352
 
 
353
/*
 
354
 *----------------------------------------------------------------------
 
355
 *
 
356
 * CursorInit --
 
357
 *
 
358
 *      Initialize the structures used for cursor management.
 
359
 *
 
360
 * Results:
 
361
 *      None.
 
362
 *
 
363
 * Side effects:
 
364
 *      Read the code.
 
365
 *
 
366
 *----------------------------------------------------------------------
 
367
 */
 
368
 
 
369
static void
 
370
CursorInit()
 
371
{
 
372
    initialized = 1;
 
373
    Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
 
374
    Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
 
375
 
 
376
    /*
 
377
     * The call below is tricky:  can't use sizeof(IdKey) because it
 
378
     * gets padded with extra unpredictable bytes on some 64-bit
 
379
     * machines.
 
380
     */
 
381
 
 
382
    Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Tk_Cursor))
 
383
            /sizeof(int));
 
384
}