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