OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkCursor.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
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.1.1.1 2002-01-16 10:25:51 markom 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.