1 /*
2 * GraphApp - Cross-Platform Graphics Programming Library.
3 *
4 * File: cursors.c -- change the mouse cursor's shape.
5 * Platform: Windows Version: 2.35 Date: 1998/04/04
6 *
7 * Version: 1.00 Changes: Original version by Lachlan Patrick.
8 * Version: 1.05 Changes: Moved setcursor() into context.c
9 * Version: 2.00 Changes: New object class mechanism.
10 * Version: 2.30 Changes: Now uses cursor_base.
11 * Version: 2.35 Changes: New reference count technique.
12 */
13
14 /* Copyright (C) 1993-1998 Lachlan Patrick
15
16 This file is part of GraphApp, a cross-platform C graphics library.
17
18 GraphApp is free software; you can redistribute it and/or modify it
19 under the terms of the GNU Library General Public License.
20 GraphApp is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY.
22
23 See the file COPYLIB.TXT for details.
24 */
25
26 /* Changes for Windows:
27
28 add cross cursor
29
30 */
31
32 #include "internal.h"
33
34 __declspec(dllexport) cursor ArrowCursor = NULL;
35 __declspec(dllexport) cursor BlankCursor = NULL;
36 __declspec(dllexport) cursor WatchCursor = NULL;
37 __declspec(dllexport) cursor CaretCursor = NULL;
38 __declspec(dllexport) cursor TextCursor = NULL;
39 __declspec(dllexport) cursor HandCursor = NULL;
40 __declspec(dllexport) cursor CrossCursor = NULL;
41
42 /*
43 * Define the 'Hand' image shape:
44 */
45
46 static rgb cursor_cmap [] = {
47 0x00000000L,
48 0x00FFFFFFL,
49 0xFFFFFFFFL,
50 };
51
52 static GAbyte hand_pixels [] = {
53 2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,
54 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,
55 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,
56 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,
57 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,
58 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,
59 2,0,0,0,2,0,1,1,0,0,0,0,0,2,2,2,
60 0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,2,
61 2,0,1,1,0,0,1,1,0,1,0,1,0,1,0,0,
62 2,2,0,1,1,0,1,1,1,1,1,1,0,1,0,0,
63 2,2,0,1,1,0,1,1,1,1,1,1,1,1,0,0,
64 2,2,2,0,1,1,1,1,1,1,1,1,1,1,0,0,
65 2,2,2,2,0,1,1,1,1,1,1,1,1,1,0,0,
66 2,2,2,2,0,1,1,1,1,1,1,1,1,0,0,2,
67 2,2,2,2,2,0,1,1,1,1,1,1,1,0,0,2,
68 2,2,2,2,2,0,1,1,1,1,1,1,1,0,0,2,
69 };
70
71 static imagedata hand_imagedata = {
72 8, /* depth */
73 16, /* width */
74 16, /* height */
75 3, /* cmapsize */
76 cursor_cmap,
77 hand_pixels
78 };
79
80 static image hand_image = & hand_imagedata;
81 static point hand_hotspot = {7,0};
82
83 /*
84 * Private cursor destructor.
85 */
private_delcursor(cursor c)86 static void private_delcursor(cursor c)
87 {
88 DestroyCursor(c->handle);
89 }
90
91 /*
92 * Private constructor.
93 */
get_cursor_base(void)94 static object get_cursor_base(void)
95 {
96 static object cursor_base = NULL;
97
98 if (! cursor_base)
99 cursor_base = new_object(BaseObject, 0, NULL);
100 return cursor_base;
101 }
102
new_cursor_object(HCURSOR hc)103 static cursor new_cursor_object(HCURSOR hc)
104 {
105 cursor c = new_object(CursorObject, hc, get_cursor_base());
106 if (c) {
107 c->rect = rect(0,0,16,16);
108 c->depth = 1;
109 c->die = private_delcursor;
110 }
111 return c;
112 }
113
114 /*
115 * Public constructors.
116 */
createcursor(point offset,GAbyte * white,GAbyte * black)117 cursor createcursor(point offset, GAbyte *white, GAbyte *black)
118 {
119 cursor c;
120 HCURSOR hc;
121 GAbyte *andmask; /* andmask = ~blackmask & ~whitemask */
122 GAbyte *xormask; /* xormask = ~blackmask & whitemask */
123 int w, y;
124 int max_width, max_height, row_bytes;
125
126 /* Library cursors: D = (D | whitemask) & ~blackmask */
127 /* MS-Windows does: D = (D & andmask) ^ xormask */
128
129 /* Determine the best cursor size: */
130 max_width = GetSystemMetrics(SM_CXCURSOR);
131 max_height = GetSystemMetrics(SM_CYCURSOR);
132 row_bytes = (max_width + 7) / 8;
133
134 /* Create the data arrays: */
135 andmask = array(max_height * row_bytes, GAbyte);
136 xormask = array(max_height * row_bytes, GAbyte);
137
138 /* Assign the data into the arrays: */
139 for (y=0; y < max_height; y++) {
140 for (w=0; w < row_bytes; w++) {
141 if ((w<2) && (y<16)) {
142 andmask[w+y*row_bytes] = ~(black[w+y*2]) & ~(white[w+y*2]);
143 xormask[w+y*row_bytes] = ~(black[w+y*2]) & (white[w+y*2]);
144 }
145 else {
146 andmask[w+y*row_bytes] = 0xFF;
147 xormask[w+y*row_bytes] = 0x00;
148 }
149 }
150 }
151
152 /* Create the cursor: */
153 hc = CreateCursor (this_instance, -offset.x, -offset.y,
154 max_width, max_height,
155 (void FAR *) andmask, (void FAR *) xormask);
156
157 c = new_cursor_object(hc);
158
159 /* Clean up: */
160 discard(andmask);
161 discard(xormask);
162
163 return c;
164 }
165
form_and_byte(image img,int x,int y)166 static GAbyte form_and_byte(image img, int x, int y)
167 {
168 int i;
169 rgb pixel;
170 GAbyte result = 0x00;
171
172 for (i=0; i<8; i++) {
173 result <<= 1;
174 pixel = get_monochrome_pixel(img, x+i, y);
175 if (pixel == Transparent)
176 result |= 0x01;
177 }
178 return result;
179 }
180
form_xor_byte(image img,int x,int y)181 static GAbyte form_xor_byte(image img, int x, int y)
182 {
183 int i;
184 rgb pixel;
185 GAbyte result = 0x00;
186
187 for (i=0; i<8; i++) {
188 result <<= 1;
189 pixel = get_monochrome_pixel(img, x+i, y);
190 if (pixel == White)
191 result |= 0x01;
192 }
193 return result;
194 }
195
newcursor(point p,image img)196 cursor newcursor(point p, image img)
197 {
198 cursor c;
199 HCURSOR hc;
200 GAbyte *andmask;
201 GAbyte *xormask;
202 int w, y;
203 int max_width, max_height, row_bytes;
204
205 if (! img) return NULL;
206
207 /* Determine the best cursor size: */
208 max_width = GetSystemMetrics(SM_CXCURSOR);
209 max_height = GetSystemMetrics(SM_CYCURSOR);
210 row_bytes = (max_width + 7) / 8;
211
212 /* Create the data arrays: */
213 andmask = array(max_height * row_bytes, GAbyte);
214 xormask = array(max_height * row_bytes, GAbyte);
215
216 /* Assign the data into the arrays: */
217 for (y=0; y < max_height; y++) {
218 for (w=0; w < row_bytes; w++) {
219 andmask[w+y*row_bytes] = form_and_byte(img, w*8, y);
220 xormask[w+y*row_bytes] = form_xor_byte(img, w*8, y);
221 }
222 }
223
224 /* Create the cursor: */
225 hc = CreateCursor (this_instance, p.x, p.y,
226 max_width, max_height,
227 (void FAR *) andmask, (void FAR *) xormask);
228
229 c = new_cursor_object(hc);
230
231 /* Clean up: */
232 discard(andmask);
233 discard(xormask);
234
235 return c;
236 }
237
238 #ifdef UNUSED
239 /*
240 * Load a cursor from resources.
241 */
load_hotspot(const char * filename)242 static point load_hotspot(const char *filename)
243 {
244 FILE *file;
245 char line[100];
246 int i, x, y;
247 point p = pt(0,0);
248
249 file = fopen(filename, "rt");
250 while (fgets(line, sizeof(line)-2, file)) {
251 if ( (! strncmp(line, "point", 5))
252 || (! strncmp(line, "/* point", 8)) )
253 {
254 i = 5;
255 x = y = 0;
256 while (line[i] && (! isdigit(line[i])) )
257 i++; /* skip "hotspot = {" */
258 x = atoi(line+i);
259 while (line[i] && isdigit(line[i]))
260 i++; /* skip x-location */
261 while (line[i] && (! isdigit(line[i])) )
262 i++; /* skip comma */
263 y = atoi(line+i);
264 p = pt(x,y);
265 break;
266 }
267 }
268 fclose(file);
269 return p;
270 }
271
load_image_cursor(const char * filename)272 static cursor load_image_cursor(const char *filename)
273 {
274 cursor c = NULL;
275 image img;
276 point p;
277
278 img = loadimage(filename);
279 if (img) {
280 p = load_hotspot(filename);
281 c = newcursor(p, img);
282 delimage(img);
283 }
284 return c;
285 }
286
loadcursor(const char * name)287 cursor loadcursor(const char *name)
288 {
289 HCURSOR hc;
290 cursor c;
291
292 if (this_instance == 0)
293 return ArrowCursor;
294
295 hc = LoadCursor(this_instance, name);
296
297 if (hc) c = new_cursor_object(hc);
298 else c = load_image_cursor(name);
299
300 if (c) c->text = new_string(name);
301
302 return c;
303 }
304 #endif
305
306 /*
307 * Private cursor initialisation routines.
308 */
make_special_cursor(const char * name,LPCSTR idc)309 static cursor make_special_cursor(const char *name, LPCSTR idc)
310 {
311 cursor c;
312
313 if (idc) c = new_cursor_object(LoadCursor(0, idc));
314 else c = new_cursor_object(NULL);
315
316 if (c) {
317 c->text = new_string(name);
318 protect_object(c);
319 }
320 return c;
321 }
322
323 PROTECTED
init_cursors(void)324 void init_cursors(void)
325 {
326 ArrowCursor = make_special_cursor("ArrowCursor", IDC_ARROW);
327 BlankCursor = make_special_cursor("BlankCursor", NULL);
328 WatchCursor = make_special_cursor("WatchCursor", IDC_WAIT);
329 CaretCursor = make_special_cursor("CaretCursor", IDC_IBEAM);
330 TextCursor = make_special_cursor("TextCursor", IDC_IBEAM);
331 CrossCursor = make_special_cursor("CrossCursor", IDC_CROSS);
332
333 HandCursor = newcursor(hand_hotspot, hand_image);
334 if (HandCursor) {
335 settext(HandCursor, "HandCursor");
336 protect_object(HandCursor);
337 }
338
339 setcursor(ArrowCursor);
340 }
341