1/*
2 * tkWinCursor.c --
3 *
4 *	This file contains Win32 specific cursor related 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 * RCS: @(#) $Id: tkWinCursor.c,v 1.10.2.2 2004/01/28 23:37:28 patthoyts Exp $
12 */
13
14#include "tkWinInt.h"
15
16/*
17 * The following data structure contains the system specific data
18 * necessary to control Windows cursors.
19 */
20
21typedef struct {
22    TkCursor info;		/* Generic cursor info used by tkCursor.c */
23    HCURSOR winCursor;		/* Win32 cursor handle. */
24    int system;			/* 1 if cursor is a system cursor, else 0. */
25} TkWinCursor;
26
27/*
28 * The HAND cursor is only present when WINVER >= 0x0500. If this is
29 * not available at runtime, it will default to the unix-style cursor.
30 */
31#ifndef IDC_HAND
32#define IDC_HAND MAKEINTRESOURCE(32649)
33#endif
34
35/*
36 * The table below is used to map from the name of a predefined cursor
37 * to its resource identifier.
38 */
39
40static struct CursorName {
41    char *name;
42    LPCTSTR id;
43} cursorNames[] = {
44    {"starting",		IDC_APPSTARTING},
45    {"arrow",			IDC_ARROW},
46    {"ibeam",			IDC_IBEAM},
47    {"icon",			IDC_ICON},
48    {"no",			IDC_NO},
49    {"size",			IDC_SIZEALL},
50    {"size_ne_sw",		IDC_SIZENESW},
51    {"size_ns",			IDC_SIZENS},
52    {"size_nw_se",		IDC_SIZENWSE},
53    {"size_we",			IDC_SIZEWE},
54    {"uparrow",			IDC_UPARROW},
55    {"wait",			IDC_WAIT},
56    {"crosshair",		IDC_CROSS},
57    {"fleur",			IDC_SIZEALL},
58    {"sb_v_double_arrow",	IDC_SIZENS},
59    {"sb_h_double_arrow",	IDC_SIZEWE},
60    {"center_ptr",		IDC_UPARROW},
61    {"watch",			IDC_WAIT},
62    {"xterm",			IDC_IBEAM},
63    {"hand2",			IDC_HAND},
64    {NULL,			0}
65};
66
67/*
68 * The default cursor is used whenever no other cursor has been specified.
69 */
70
71#define TK_DEFAULT_CURSOR	IDC_ARROW
72
73
74/*
75 *----------------------------------------------------------------------
76 *
77 * TkGetCursorByName --
78 *
79 *	Retrieve a system cursor by name.
80 *
81 * Results:
82 *	Returns a new cursor, or NULL on errors.
83 *
84 * Side effects:
85 *	Allocates a new cursor.
86 *
87 *----------------------------------------------------------------------
88 */
89
90TkCursor *
91TkGetCursorByName(interp, tkwin, string)
92    Tcl_Interp *interp;		/* Interpreter to use for error reporting. */
93    Tk_Window tkwin;		/* Window in which cursor will be used. */
94    Tk_Uid string;		/* Description of cursor.  See manual entry
95				 * for details on legal syntax. */
96{
97    struct CursorName *namePtr;
98    TkWinCursor *cursorPtr;
99    int argc;
100    CONST char **argv = NULL;
101
102    /*
103     * All cursor names are valid lists of one element (for
104     * Unix-compatability), even unadorned system cursor names.
105     */
106
107    if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
108	return NULL;
109    }
110    if (argc == 0) {
111	goto badCursorSpec;
112    }
113
114    cursorPtr = (TkWinCursor *) ckalloc(sizeof(TkWinCursor));
115    cursorPtr->info.cursor = (Tk_Cursor) cursorPtr;
116    cursorPtr->winCursor = NULL;
117    cursorPtr->system = 0;
118
119    if (argv[0][0] == '@') {
120	/*
121	 * Check for system cursor of type @<filename>, where only
122	 * the name is allowed.  This accepts any of:
123	 *	-cursor @/winnt/cursors/globe.ani
124	 *	-cursor @C:/Winnt/cursors/E_arrow.cur
125	 *	-cursor {@C:/Program\ Files/Cursors/bart.ani}
126	 *      -cursor {{@C:/Program Files/Cursors/bart.ani}}
127	 *	-cursor [list @[file join "C:/Program Files" Cursors bart.ani]]
128	 */
129
130	if (Tcl_IsSafe(interp)) {
131	    Tcl_AppendResult(interp, "can't get cursor from a file in",
132		    " a safe interpreter", (char *) NULL);
133	    ckfree((char *) argv);
134	    ckfree((char *) cursorPtr);
135	    return NULL;
136	}
137	cursorPtr->winCursor = LoadCursorFromFile(&(argv[0][1]));
138    } else {
139	/*
140	 * Check for the cursor in the system cursor set.
141	 */
142	for (namePtr = cursorNames; namePtr->name != NULL; namePtr++) {
143	    if (strcmp(namePtr->name, argv[0]) == 0) {
144		cursorPtr->winCursor = LoadCursor(NULL, namePtr->id);
145		break;
146	    }
147	}
148
149	if (cursorPtr->winCursor == NULL) {
150	    /*
151	     * Hmm, it is not in the system cursor set.  Check to see
152	     * if it is one of our application resources.
153	     */
154	    cursorPtr->winCursor = LoadCursor(Tk_GetHINSTANCE(), argv[0]);
155	} else {
156	    cursorPtr->system = 1;
157	}
158    }
159
160    if (cursorPtr->winCursor == NULL) {
161	ckfree((char *) cursorPtr);
162    badCursorSpec:
163	ckfree((char *) argv);
164	Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"",
165		(char *) NULL);
166	return NULL;
167    } else {
168	ckfree((char *) argv);
169	return (TkCursor *) cursorPtr;
170    }
171}
172
173/*
174 *----------------------------------------------------------------------
175 *
176 * TkCreateCursorFromData --
177 *
178 *	Creates a cursor from the source and mask bits.
179 *
180 * Results:
181 *	Returns a new cursor, or NULL on errors.
182 *
183 * Side effects:
184 *	Allocates a new cursor.
185 *
186 *----------------------------------------------------------------------
187 */
188
189TkCursor *
190TkCreateCursorFromData(tkwin, source, mask, width, height, xHot, yHot,
191	fgColor, bgColor)
192    Tk_Window tkwin;		/* Window in which cursor will be used. */
193    CONST char *source;		/* Bitmap data for cursor shape. */
194    CONST char *mask;		/* Bitmap data for cursor mask. */
195    int width, height;		/* Dimensions of cursor. */
196    int xHot, yHot;		/* Location of hot-spot in cursor. */
197    XColor fgColor;		/* Foreground color for cursor. */
198    XColor bgColor;		/* Background color for cursor. */
199{
200    return NULL;
201}
202
203/*
204 *----------------------------------------------------------------------
205 *
206 * TkpFreeCursor --
207 *
208 *	This procedure is called to release a cursor allocated by
209 *	TkGetCursorByName.
210 *
211 * Results:
212 *	None.
213 *
214 * Side effects:
215 *	The cursor data structure is deallocated.
216 *
217 *----------------------------------------------------------------------
218 */
219
220void
221TkpFreeCursor(cursorPtr)
222    TkCursor *cursorPtr;
223{
224    TkWinCursor *winCursorPtr = (TkWinCursor *) cursorPtr;
225}
226
227/*
228 *----------------------------------------------------------------------
229 *
230 * TkpSetCursor --
231 *
232 *	Set the global cursor.  If the cursor is None, then use the
233 *	default Tk cursor.
234 *
235 * Results:
236 *	None.
237 *
238 * Side effects:
239 *	Changes the mouse cursor.
240 *
241 *----------------------------------------------------------------------
242 */
243
244void
245TkpSetCursor(cursor)
246    TkpCursor cursor;
247{
248    HCURSOR hcursor;
249    TkWinCursor *winCursor = (TkWinCursor *) cursor;
250
251    if (winCursor == NULL || winCursor->winCursor == NULL) {
252	hcursor = LoadCursor(NULL, TK_DEFAULT_CURSOR);
253    } else {
254	hcursor = winCursor->winCursor;
255    }
256
257    if (hcursor != NULL) {
258	SetCursor(hcursor);
259    }
260}
261