1 /**
2 ** mscursor.c ---- the mouse cursor related stuff
3 **
4 ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5 ** [e-mail: csaba@vuse.vanderbilt.edu]
6 **
7 ** This file is part of the GRX graphics library.
8 **
9 ** The GRX graphics library is free software; you can redistribute it
10 ** and/or modify it under some conditions; see the "copying.grx" file
11 ** for details.
12 **
13 ** This library is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 **
17 **/
18
19 #include <stdarg.h>
20
21 #include "mouse/input.h"
22 #include "libgrx.h"
23 #include "clipping.h"
24 #include "mempeek.h"
25
26 #define MSCURSOR (MOUINFO->cursor)
27 #define CURSORMODE (MOUINFO->cursmode)
28 #define SPECIALMODE (MOUINFO->cursmode != GR_M_CUR_NORMAL)
29 #define BLOCKED 1
30 #define ERASED 2
31
draw_special(void)32 static void draw_special(void)
33 {
34 int xpos = MSCURSOR->xcord;
35 int ypos = MSCURSOR->ycord;
36 int check = MOUINFO->docheck;
37 GrContext csave;
38 MOUINFO->docheck = FALSE;
39 GrSaveContext(&csave);
40 GrSetContext(SCRN);
41 switch(CURSORMODE) {
42 case GR_M_CUR_RUBBER:
43 GrBox(xpos,ypos,MOUINFO->x1,MOUINFO->y1,MOUINFO->curscolor);
44 break;
45 case GR_M_CUR_LINE:
46 GrLine(xpos,ypos,MOUINFO->x1,MOUINFO->y1,MOUINFO->curscolor);
47 break;
48 case GR_M_CUR_BOX:
49 GrBox(
50 (xpos + MOUINFO->x1),(ypos + MOUINFO->y1),
51 (xpos + MOUINFO->x2),(ypos + MOUINFO->y2),
52 MOUINFO->curscolor
53 );
54 break;
55 }
56 GrSetContext(&csave);
57 MOUINFO->docheck = check;
58 }
59
move_mouse(void)60 static void move_mouse(void)
61 {
62 if((MOUINFO->xpos != MSCURSOR->xcord) ||
63 (MOUINFO->ypos != MSCURSOR->ycord)) {
64 int check = MOUINFO->docheck;
65 int dospec = SPECIALMODE && MSCURSOR->displayed;
66 MOUINFO->docheck = FALSE;
67 if(dospec) draw_special();
68 GrMoveCursor(MSCURSOR,MOUINFO->xpos,MOUINFO->ypos);
69 if(dospec) draw_special();
70 MOUINFO->docheck = check;
71 }
72 }
73
draw_mouse(void)74 static void draw_mouse(void)
75 {
76 int check = MOUINFO->docheck;
77 MOUINFO->docheck = FALSE;
78 GrDisplayCursor(MSCURSOR);
79 if(SPECIALMODE) draw_special();
80 MOUINFO->docheck = check;
81 }
82
erase_mouse(void)83 static void erase_mouse(void)
84 {
85 int check = MOUINFO->docheck;
86 MOUINFO->docheck = FALSE;
87 if(SPECIALMODE) draw_special();
88 GrEraseCursor(MSCURSOR);
89 MOUINFO->docheck = check;
90 }
91
GrMouseDisplayCursor(void)92 void GrMouseDisplayCursor(void)
93 {
94 if(MOUINFO->msstatus != 2) GrMouseInit();
95 if(MOUINFO->msstatus != 2) return;
96 if(MOUINFO->cursor == NULL) return;
97 if(MOUINFO->displayed != FALSE) return;
98 move_mouse();
99 draw_mouse();
100 MOUINFO->displayed = TRUE;
101 MOUINFO->docheck = TRUE;
102 MOUINFO->blockflag = 0;
103 }
104
GrMouseEraseCursor(void)105 void GrMouseEraseCursor(void)
106 {
107 if(MOUINFO->msstatus != 2) return;
108 if(MOUINFO->cursor == NULL) return;
109 if(MOUINFO->displayed == FALSE) return;
110 if(MOUINFO->blockflag != 0) return;
111 MOUINFO->displayed = FALSE;
112 MOUINFO->docheck = FALSE;
113 erase_mouse();
114 }
115
GrMouseSetCursor(GrCursor * C)116 void GrMouseSetCursor(GrCursor *C)
117 {
118 if(!MOUINFO->displayed && C && (C != MSCURSOR) && COMPATIBLE(C)) {
119 GrCursor *oldcursor = MSCURSOR;
120 if(C->displayed) GrEraseCursor(C);
121 MOUINFO->cursor = C;
122 if(MOUINFO->owncursor) GrDestroyCursor(oldcursor);
123 MOUINFO->owncursor = FALSE;
124 }
125 }
126
GrMouseSetColors(GrColor fg,GrColor bg)127 void GrMouseSetColors(GrColor fg,GrColor bg)
128 {
129 static char ptr12x16bits[] = {
130 0,1,0,0,0,0,0,0,0,0,0,0,
131 1,2,1,0,0,0,0,0,0,0,0,0,
132 1,2,2,1,0,0,0,0,0,0,0,0,
133 1,2,2,2,1,0,0,0,0,0,0,0,
134 1,2,2,2,2,1,0,0,0,0,0,0,
135 1,2,2,2,2,2,1,0,0,0,0,0,
136 1,2,2,2,2,2,2,1,0,0,0,0,
137 1,2,2,2,2,2,2,2,1,0,0,0,
138 1,2,2,2,2,2,2,2,2,1,0,0,
139 1,2,2,2,2,2,2,2,2,2,1,0,
140 1,2,2,2,2,2,2,2,2,2,2,1,
141 1,2,2,2,2,1,1,1,1,1,1,0,
142 1,2,2,2,1,0,0,0,0,0,0,0,
143 1,2,2,1,0,0,0,0,0,0,0,0,
144 1,2,1,0,0,0,0,0,0,0,0,0,
145 0,1,0,0,0,0,0,0,0,0,0,0,
146 };
147 GrCursor *newc;
148 GrColor cols[3];
149 if(MOUINFO->displayed) return;
150 cols[0] = 2;
151 cols[1] = bg;
152 cols[2] = fg;
153 newc = GrBuildCursor(ptr12x16bits,12,12,16,1,1,cols);
154 if(!newc) return;
155 GrMouseSetCursor(newc);
156 MOUINFO->owncursor = TRUE;
157 }
158
GrMouseSetCursorMode(int mode,...)159 void GrMouseSetCursorMode(int mode,...)
160 {
161 va_list ap;
162 if(MOUINFO->displayed) return;
163 va_start(ap,mode);
164 switch(mode) {
165 case GR_M_CUR_BOX:
166 MOUINFO->x2 = va_arg(ap,int);
167 MOUINFO->y2 = va_arg(ap,int);
168 case GR_M_CUR_RUBBER:
169 case GR_M_CUR_LINE:
170 MOUINFO->cursmode = mode;
171 MOUINFO->x1 = va_arg(ap,int);
172 MOUINFO->y1 = va_arg(ap,int);
173 MOUINFO->curscolor = GrXorModeColor(va_arg(ap,GrColor));
174 break;
175 default:
176 MOUINFO->cursmode = GR_M_CUR_NORMAL;
177 break;
178 }
179 va_end(ap);
180 }
181
block(GrContext * c,int x1,int y1,int x2,int y2)182 static int block(GrContext *c,int x1,int y1,int x2,int y2)
183 {
184 int mx1,my1,mx2,my2,oldblock = MOUINFO->blockflag;
185 if(!c) c = CURC;
186 if(!MOUINFO->displayed) return(0);
187 if(!MOUINFO->docheck) return(0);
188 if(!c->gc_onscreen) return(0);
189 if(oldblock & ERASED) return(0);
190 MOUINFO->blockflag = BLOCKED;
191 isort(x1,x2); x1 += c->gc_xoffset; x2 += c->gc_xoffset;
192 isort(y1,y2); y1 += c->gc_yoffset; y2 += c->gc_yoffset;
193 mx1 = MSCURSOR->xwpos;
194 my1 = MSCURSOR->ywpos;
195 mx2 = MSCURSOR->xwork + mx1 - 1;
196 my2 = MSCURSOR->ywork + my1 - 1;
197 if(SPECIALMODE) {
198 int cx1,cy1,cx2,cy2;
199 switch(CURSORMODE) {
200 case GR_M_CUR_RUBBER:
201 case GR_M_CUR_LINE:
202 cx1 = MSCURSOR->xcord;
203 cy1 = MSCURSOR->ycord;
204 cx2 = MOUINFO->x1;
205 cy2 = MOUINFO->y1;
206 break;
207 case GR_M_CUR_BOX:
208 cx1 = MSCURSOR->xcord + MOUINFO->x1;
209 cy1 = MSCURSOR->ycord + MOUINFO->y1;
210 cx2 = MSCURSOR->xcord + MOUINFO->x2;
211 cy2 = MSCURSOR->ycord + MOUINFO->y2;
212 break;
213 default:
214 return(0);
215 }
216 isort(cx1,cx2); mx1 = imin(cx1,mx1); mx2 = imax(mx2,cx2);
217 isort(cy1,cy2); my1 = imin(cy1,my1); my2 = imax(my2,cy2);
218 }
219 x1 = imax(x1,mx1); y1 = imax(y1,my1);
220 x2 = imin(x2,mx2); y2 = imin(y2,my2);
221 if((x1 <= x2) && (y1 <= y2)) {
222 MOUINFO->blockflag = oldblock | ERASED;
223 MOUINFO->docheck = FALSE;
224 erase_mouse();
225 return(ERASED);
226 }
227 return((oldblock & BLOCKED) ? 0 : BLOCKED);
228 }
229
unblock(int flags)230 static void unblock(int flags)
231 {
232 if(!MOUINFO->displayed) return;
233 if(flags & MOUINFO->blockflag & ERASED) {
234 if(!(MOUINFO->blockflag & BLOCKED) || (flags & BLOCKED)) {
235 _GrUpdateInputs();
236 move_mouse();
237 MOUINFO->blockflag &= ~BLOCKED;
238 }
239 draw_mouse();
240 MOUINFO->blockflag &= ~ERASED;
241 MOUINFO->docheck = TRUE;
242 return;
243 }
244 if(flags & MOUINFO->blockflag & BLOCKED) {
245 if(!(MOUINFO->blockflag & ERASED)) {
246 int updflag;
247 test_unblock(updflag);
248 if(updflag) {
249 _GrUpdateInputs();
250 move_mouse();
251 }
252 }
253 MOUINFO->blockflag &= ~BLOCKED;
254 }
255 }
256
GrMouseUpdateCursor(void)257 void GrMouseUpdateCursor(void)
258 {
259 if(MOUINFO->displayed && !MOUINFO->blockflag) {
260 _GrUpdateInputs();
261 move_mouse();
262 }
263 }
264
_GrInitMouseCursor(void)265 void _GrInitMouseCursor(void)
266 {
267 if(MSCURSOR && !COMPATIBLE(MSCURSOR)) {
268 if(MOUINFO->owncursor) {
269 GrCursor *obsolete = MSCURSOR;
270 MOUINFO->cursor = NULL;
271 MOUINFO->owncursor = FALSE;
272 GrDestroyCursor(obsolete);
273 }
274 MOUINFO->cursor = NULL;
275 }
276 if(MSCURSOR == NULL) {
277 GrMouseSetColors(GrAllocColor(255,0,0),GrBlack());
278 }
279 if(MSCURSOR && MSCURSOR->displayed) {
280 GrEraseCursor(MSCURSOR);
281 }
282 MOUINFO->cursmode = GR_M_CUR_NORMAL;
283 MOUINFO->displayed = FALSE;
284 MOUINFO->blockflag = 0;
285 MOUINFO->docheck = FALSE;
286 MOUINFO->block = block;
287 MOUINFO->unblock = unblock;
288 }
289
290