Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtk/unix/tkUnixCursor.c
1811 views
1
/*
2
* tkUnixCursor.c --
3
*
4
* This file contains X specific cursor manipulation routines.
5
*
6
* Copyright (c) 1995 Sun Microsystems, Inc.
7
*
8
* See the file "license.terms" for information on usage and redistribution
9
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
*
11
* SCCS: @(#) tkUnixCursor.c 1.3 96/07/23 16:56:24
12
*/
13
14
#include "tkInt.h"
15
16
/*
17
* The following data structure is a superset of the TkCursor structure
18
* defined in tkCursor.c. Each system specific cursor module will define
19
* a different cursor structure. All of these structures must have the
20
* same header consisting of the fields in TkCursor.
21
*/
22
23
24
25
typedef struct {
26
TkCursor info; /* Generic cursor info used by tkCursor.c */
27
Display *display; /* Display for which cursor is valid. */
28
} TkUnixCursor;
29
30
/*
31
* The table below is used to map from the name of a cursor to its
32
* index in the official cursor font:
33
*/
34
35
static struct CursorName {
36
char *name;
37
unsigned int shape;
38
} cursorNames[] = {
39
{"X_cursor", XC_X_cursor},
40
{"arrow", XC_arrow},
41
{"based_arrow_down", XC_based_arrow_down},
42
{"based_arrow_up", XC_based_arrow_up},
43
{"boat", XC_boat},
44
{"bogosity", XC_bogosity},
45
{"bottom_left_corner", XC_bottom_left_corner},
46
{"bottom_right_corner", XC_bottom_right_corner},
47
{"bottom_side", XC_bottom_side},
48
{"bottom_tee", XC_bottom_tee},
49
{"box_spiral", XC_box_spiral},
50
{"center_ptr", XC_center_ptr},
51
{"circle", XC_circle},
52
{"clock", XC_clock},
53
{"coffee_mug", XC_coffee_mug},
54
{"cross", XC_cross},
55
{"cross_reverse", XC_cross_reverse},
56
{"crosshair", XC_crosshair},
57
{"diamond_cross", XC_diamond_cross},
58
{"dot", XC_dot},
59
{"dotbox", XC_dotbox},
60
{"double_arrow", XC_double_arrow},
61
{"draft_large", XC_draft_large},
62
{"draft_small", XC_draft_small},
63
{"draped_box", XC_draped_box},
64
{"exchange", XC_exchange},
65
{"fleur", XC_fleur},
66
{"gobbler", XC_gobbler},
67
{"gumby", XC_gumby},
68
{"hand1", XC_hand1},
69
{"hand2", XC_hand2},
70
{"heart", XC_heart},
71
{"icon", XC_icon},
72
{"iron_cross", XC_iron_cross},
73
{"left_ptr", XC_left_ptr},
74
{"left_side", XC_left_side},
75
{"left_tee", XC_left_tee},
76
{"leftbutton", XC_leftbutton},
77
{"ll_angle", XC_ll_angle},
78
{"lr_angle", XC_lr_angle},
79
{"man", XC_man},
80
{"middlebutton", XC_middlebutton},
81
{"mouse", XC_mouse},
82
{"pencil", XC_pencil},
83
{"pirate", XC_pirate},
84
{"plus", XC_plus},
85
{"question_arrow", XC_question_arrow},
86
{"right_ptr", XC_right_ptr},
87
{"right_side", XC_right_side},
88
{"right_tee", XC_right_tee},
89
{"rightbutton", XC_rightbutton},
90
{"rtl_logo", XC_rtl_logo},
91
{"sailboat", XC_sailboat},
92
{"sb_down_arrow", XC_sb_down_arrow},
93
{"sb_h_double_arrow", XC_sb_h_double_arrow},
94
{"sb_left_arrow", XC_sb_left_arrow},
95
{"sb_right_arrow", XC_sb_right_arrow},
96
{"sb_up_arrow", XC_sb_up_arrow},
97
{"sb_v_double_arrow", XC_sb_v_double_arrow},
98
{"shuttle", XC_shuttle},
99
{"sizing", XC_sizing},
100
{"spider", XC_spider},
101
{"spraycan", XC_spraycan},
102
{"star", XC_star},
103
{"target", XC_target},
104
{"tcross", XC_tcross},
105
{"top_left_arrow", XC_top_left_arrow},
106
{"top_left_corner", XC_top_left_corner},
107
{"top_right_corner", XC_top_right_corner},
108
{"top_side", XC_top_side},
109
{"top_tee", XC_top_tee},
110
{"trek", XC_trek},
111
{"ul_angle", XC_ul_angle},
112
{"umbrella", XC_umbrella},
113
{"ur_angle", XC_ur_angle},
114
{"watch", XC_watch},
115
{"xterm", XC_xterm},
116
{NULL, 0}
117
};
118
119
/*
120
* Font to use for cursors:
121
*/
122
123
#ifndef CURSORFONT
124
#define CURSORFONT "cursor"
125
#endif
126
127
128
/*
129
*----------------------------------------------------------------------
130
*
131
* TkGetCursorByName --
132
*
133
* Retrieve a cursor by name. Parse the cursor name into fields
134
* and create a cursor, either from the standard cursor font or
135
* from bitmap files.
136
*
137
* Results:
138
* Returns a new cursor, or NULL on errors.
139
*
140
* Side effects:
141
* Allocates a new cursor.
142
*
143
*----------------------------------------------------------------------
144
*/
145
146
TkCursor *
147
TkGetCursorByName(interp, tkwin, string)
148
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
149
Tk_Window tkwin; /* Window in which cursor will be used. */
150
Tk_Uid string; /* Description of cursor. See manual entry
151
* for details on legal syntax. */
152
{
153
TkUnixCursor *cursorPtr = NULL;
154
Cursor cursor = None;
155
int argc;
156
char **argv = NULL;
157
Pixmap source = None;
158
Pixmap mask = None;
159
Display *display = Tk_Display(tkwin);
160
161
if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
162
return NULL;
163
}
164
if (argc == 0) {
165
goto badString;
166
}
167
if (argv[0][0] != '@') {
168
XColor fg, bg;
169
unsigned int maskIndex;
170
register struct CursorName *namePtr;
171
TkDisplay *dispPtr;
172
173
/*
174
* The cursor is to come from the standard cursor font. If one
175
* arg, it is cursor name (use black and white for fg and bg).
176
* If two args, they are name and fg color (ignore mask). If
177
* three args, they are name, fg, bg. Some of the code below
178
* is stolen from the XCreateFontCursor Xlib procedure.
179
*/
180
181
if (argc > 3) {
182
goto badString;
183
}
184
for (namePtr = cursorNames; ; namePtr++) {
185
if (namePtr->name == NULL) {
186
goto badString;
187
}
188
if ((namePtr->name[0] == argv[0][0])
189
&& (strcmp(namePtr->name, argv[0]) == 0)) {
190
break;
191
}
192
}
193
maskIndex = namePtr->shape + 1;
194
if (argc == 1) {
195
fg.red = fg.green = fg.blue = 0;
196
bg.red = bg.green = bg.blue = 65535;
197
} else {
198
if (XParseColor(display, Tk_Colormap(tkwin), argv[1],
199
&fg) == 0) {
200
Tcl_AppendResult(interp, "invalid color name \"", argv[1],
201
"\"", (char *) NULL);
202
goto cleanup;
203
}
204
if (argc == 2) {
205
bg.red = bg.green = bg.blue = 0;
206
maskIndex = namePtr->shape;
207
} else {
208
if (XParseColor(display, Tk_Colormap(tkwin), argv[2],
209
&bg) == 0) {
210
Tcl_AppendResult(interp, "invalid color name \"", argv[2],
211
"\"", (char *) NULL);
212
goto cleanup;
213
}
214
}
215
}
216
dispPtr = ((TkWindow *) tkwin)->dispPtr;
217
if (dispPtr->cursorFont == None) {
218
dispPtr->cursorFont = XLoadFont(display, CURSORFONT);
219
if (dispPtr->cursorFont == None) {
220
interp->result = "couldn't load cursor font";
221
goto cleanup;
222
}
223
}
224
cursor = XCreateGlyphCursor(display, dispPtr->cursorFont,
225
dispPtr->cursorFont, namePtr->shape, maskIndex,
226
&fg, &bg);
227
} else {
228
int width, height, maskWidth, maskHeight;
229
int xHot, yHot, dummy1, dummy2;
230
XColor fg, bg;
231
232
/*
233
* The cursor is to be created by reading bitmap files. There
234
* should be either two elements in the list (source, color) or
235
* four (source mask fg bg).
236
*/
237
238
if ((argc != 2) && (argc != 4)) {
239
goto badString;
240
}
241
if (XReadBitmapFile(display,
242
RootWindowOfScreen(Tk_Screen(tkwin)), &argv[0][1],
243
(unsigned int *) &width, (unsigned int *) &height,
244
&source, &xHot, &yHot) != BitmapSuccess) {
245
Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
246
&argv[0][1], "\"", (char *) NULL);
247
goto cleanup;
248
}
249
if ((xHot < 0) || (yHot < 0) || (xHot >= width) || (yHot >= height)) {
250
Tcl_AppendResult(interp, "bad hot spot in bitmap file \"",
251
&argv[0][1], "\"", (char *) NULL);
252
goto cleanup;
253
}
254
if (argc == 2) {
255
if (XParseColor(display, Tk_Colormap(tkwin), argv[1],
256
&fg) == 0) {
257
Tcl_AppendResult(interp, "invalid color name \"",
258
argv[1], "\"", (char *) NULL);
259
goto cleanup;
260
}
261
cursor = XCreatePixmapCursor(display, source, source,
262
&fg, &fg, (unsigned) xHot, (unsigned) yHot);
263
} else {
264
if (XReadBitmapFile(display,
265
RootWindowOfScreen(Tk_Screen(tkwin)), argv[1],
266
(unsigned int *) &maskWidth, (unsigned int *) &maskHeight,
267
&mask, &dummy1, &dummy2) != BitmapSuccess) {
268
Tcl_AppendResult(interp, "cleanup reading bitmap file \"",
269
argv[1], "\"", (char *) NULL);
270
goto cleanup;
271
}
272
if ((maskWidth != width) && (maskHeight != height)) {
273
interp->result =
274
"source and mask bitmaps have different sizes";
275
goto cleanup;
276
}
277
if (XParseColor(display, Tk_Colormap(tkwin), argv[2],
278
&fg) == 0) {
279
Tcl_AppendResult(interp, "invalid color name \"", argv[2],
280
"\"", (char *) NULL);
281
goto cleanup;
282
}
283
if (XParseColor(display, Tk_Colormap(tkwin), argv[3],
284
&bg) == 0) {
285
Tcl_AppendResult(interp, "invalid color name \"", argv[3],
286
"\"", (char *) NULL);
287
goto cleanup;
288
}
289
cursor = XCreatePixmapCursor(display, source, mask,
290
&fg, &bg, (unsigned) xHot, (unsigned) yHot);
291
}
292
}
293
294
if (cursor != None) {
295
cursorPtr = (TkUnixCursor *) ckalloc(sizeof(TkUnixCursor));
296
cursorPtr->info.cursor = (Tk_Cursor) cursor;
297
cursorPtr->display = display;
298
}
299
300
cleanup:
301
if (argv != NULL) {
302
ckfree((char *) argv);
303
}
304
if (source != None) {
305
Tk_FreePixmap(display, source);
306
}
307
if (mask != None) {
308
Tk_FreePixmap(display, mask);
309
}
310
return (TkCursor *) cursorPtr;
311
312
313
badString:
314
Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"",
315
(char *) NULL);
316
return NULL;
317
}
318
319
/*
320
*----------------------------------------------------------------------
321
*
322
* TkCreateCursorFromData --
323
*
324
* Creates a cursor from the source and mask bits.
325
*
326
* Results:
327
* Returns a new cursor, or NULL on errors.
328
*
329
* Side effects:
330
* Allocates a new cursor.
331
*
332
*----------------------------------------------------------------------
333
*/
334
335
TkCursor *
336
TkCreateCursorFromData(tkwin, source, mask, width, height, xHot, yHot,
337
fgColor, bgColor)
338
Tk_Window tkwin; /* Window in which cursor will be used. */
339
char *source; /* Bitmap data for cursor shape. */
340
char *mask; /* Bitmap data for cursor mask. */
341
int width, height; /* Dimensions of cursor. */
342
int xHot, yHot; /* Location of hot-spot in cursor. */
343
XColor fgColor; /* Foreground color for cursor. */
344
XColor bgColor; /* Background color for cursor. */
345
{
346
Cursor cursor;
347
Pixmap sourcePixmap, maskPixmap;
348
TkUnixCursor *cursorPtr = NULL;
349
Display *display = Tk_Display(tkwin);
350
351
sourcePixmap = XCreateBitmapFromData(display,
352
RootWindowOfScreen(Tk_Screen(tkwin)), source, (unsigned) width,
353
(unsigned) height);
354
maskPixmap = XCreateBitmapFromData(display,
355
RootWindowOfScreen(Tk_Screen(tkwin)), mask, (unsigned) width,
356
(unsigned) height);
357
cursor = XCreatePixmapCursor(display, sourcePixmap,
358
maskPixmap, &fgColor, &bgColor, (unsigned) xHot, (unsigned) yHot);
359
Tk_FreePixmap(display, sourcePixmap);
360
Tk_FreePixmap(display, maskPixmap);
361
362
if (cursor != None) {
363
cursorPtr = (TkUnixCursor *) ckalloc(sizeof(TkUnixCursor));
364
cursorPtr->info.cursor = (Tk_Cursor) cursor;
365
cursorPtr->display = display;
366
}
367
return (TkCursor *) cursorPtr;
368
}
369
370
/*
371
*----------------------------------------------------------------------
372
*
373
* TkFreeCursor --
374
*
375
* This procedure is called to release a cursor allocated by
376
* TkGetCursorByName.
377
*
378
* Results:
379
* None.
380
*
381
* Side effects:
382
* The cursor data structure is deallocated.
383
*
384
*----------------------------------------------------------------------
385
*/
386
387
void
388
TkFreeCursor(cursorPtr)
389
TkCursor *cursorPtr;
390
{
391
TkUnixCursor *unixCursorPtr = (TkUnixCursor *) cursorPtr;
392
XFreeCursor(unixCursorPtr->display, (Cursor) unixCursorPtr->info.cursor);
393
Tk_FreeXId(unixCursorPtr->display, (XID) unixCursorPtr->info.cursor);
394
ckfree((char *) unixCursorPtr);
395
}
396
397