xref: /plan9/sys/src/cmd/proof/screen.c (revision bfe6f91441b5ecf57fd2b06aea5c3ac4bd5daaa1)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <cursor.h>
5 #include <event.h>
6 #include <bio.h>
7 #include "proof.h"
8 
9 static	int	checkmouse(void);
10 static	int	buttondown(void);
11 static	char	*getmousestr(void);
12 static	char	*getkbdstr(int);
13 
14 extern	Cursor	blot;
15 extern	char	*track;
16 
17 Mouse	mouse;
18 
19 void
mapscreen(void)20 mapscreen(void)
21 {
22 	if(initdraw(0, 0, "proof") < 0){
23 		fprint(2, "proof: initdraw failed: %r\n");
24 		exits("initdraw");
25 	}
26 	einit(Ekeyboard|Emouse);
27 }
28 
29 void
clearscreen(void)30 clearscreen(void)
31 {
32 	draw(screen, screen->r, display->black, nil, ZP);
33 }
34 
35 void
screenprint(char * fmt,...)36 screenprint(char *fmt, ...)
37 {
38 	char buf[100];
39 	Point p;
40 	va_list args;
41 
42 	va_start(args, fmt);
43 	vseprint(buf, &buf[sizeof buf], fmt, args);
44 	va_end(args);
45 	p = Pt(screen->clipr.min.x+40, screen->clipr.max.y-40);
46 	string(screen, p, display->black, ZP, font, buf);
47 }
48 
49 #define	Viewkey	0xb2
50 
51 char *
getcmdstr(void)52 getcmdstr(void)
53 {
54 	Event ev;
55 	int e;
56 	static ulong timekey = 0;
57 	ulong tracktm = 0;
58 	Dir *dir;
59 
60 	if(track){
61 		if(timekey == 0)
62 			timekey = etimer(0, 5000);
63 		dir = dirstat(track);
64 		if(dir != nil){
65 			tracktm = dir->mtime;
66 			free(dir);
67 		}
68 	}
69 	for (;;) {
70 		e = event(&ev);
71 		if(resized){
72 			resized = 0;
73 			return "p";
74 		}
75 		if ((e & Emouse) && ev.mouse.buttons) {
76 			mouse = ev.mouse;
77 			return getmousestr();
78 		} else if (e & Ekeyboard)
79 			return getkbdstr(ev.kbdc);	/* sadly, no way to unget */
80 		else if (e & timekey) {
81 			if((dir = dirstat(track)) != nil){
82 				if(tracktm < dir->mtime){
83 					free(dir);
84 					return "q";
85 				}
86 				free(dir);
87 			}
88 		}
89 	}
90 }
91 
92 static char *
getkbdstr(int c0)93 getkbdstr(int c0)
94 {
95 	static char buf[100];
96 	char *p;
97 	int c;
98 
99 	if (c0 == '\n')
100 		return "";
101 	buf[0] = c0;
102 	buf[1] = 0;
103 	screenprint("%s", buf);
104 	for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) {
105 		if (c == '\b' && p > buf) {
106 			*--p = ' ';
107 		} else {
108 			*p++ = c;
109 			*p = 0;
110 		}
111 		screenprint("%s", buf);
112 	}
113 	*p = 0;
114 	return buf;
115 }
116 
117 
118 #define button3(b)	((b) & 4)
119 #define button2(b)	((b) & 2)
120 #define button1(b)	((b) & 1)
121 #define button23(b)	((b) & 6)
122 #define button123(b)	((b) & 7)
123 
124 #define	butcvt(b)	(1 << ((b) - 1))
125 
buttondown(void)126 static int buttondown(void)	/* report state of buttons, if any */
127 {
128 	if (!ecanmouse())	/* no event pending */
129 		return 0;
130 	mouse = emouse();	/* something, but it could be motion */
131 	return mouse.buttons & 7;
132 }
133 
waitdown(void)134 int waitdown(void)	/* wait until some button is down */
135 {
136 	while (!(mouse.buttons & 7))
137 		mouse = emouse();
138 	return mouse.buttons & 7;
139 }
140 
waitup(void)141 int waitup(void)
142 {
143 	while (mouse.buttons & 7)
144 		mouse = emouse();
145 	return mouse.buttons & 7;
146 }
147 
148 char *m3[]	= { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 };
149 char *m2[]	= { 0 };
150 
151 enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit };
152 
153 Menu	mbut3	= { m3, 0, 0 };
154 Menu	mbut2	= { m2, 0, 0 };
155 
156 int	last_hit;
157 int	last_but;
158 
pan(void)159 char *pan(void)
160 {
161 	Point dd, xy, lastxy, min, max;
162 
163 	esetcursor(&blot);
164 	waitdown();
165 	xy = mouse.xy;
166 	do{
167 		lastxy = mouse.xy;
168 		mouse = emouse();
169 		dd = subpt(mouse.xy, lastxy);
170 		min = addpt(screen->clipr.min, dd);
171 		max = addpt(screen->clipr.max, dd);
172 		draw(screen, rectaddpt(screen->r, subpt(mouse.xy, lastxy)),
173 			screen, nil, screen->r.min);
174 		if(mouse.xy.x < lastxy.x)	/* moved left, clear right */
175 			draw(screen, Rect(max.x, screen->r.min.y, screen->r.max.x, screen->r.max.y),
176 				display->white, nil, ZP);
177 		else	/* moved right, clear left*/
178 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, min.x, screen->r.max.y),
179 				display->white, nil, ZP);
180 		if(mouse.xy.y < lastxy.y)	/* moved up, clear down */
181 			draw(screen, Rect(screen->r.min.x, max.y, screen->r.max.x, screen->r.max.y),
182 				display->white, nil, ZP);
183 		else		/* moved down, clear up */
184 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, min.y),
185 				display->white, nil, ZP);
186 		flushimage(display, 1);
187 	}while(mouse.buttons);
188 
189 	xyoffset = addpt(xyoffset, subpt(mouse.xy, xy));
190 
191 	esetcursor(0);
192 	return "p";
193 }
194 
195 static char *
getmousestr(void)196 getmousestr(void)
197 {
198 	static char buf[64];
199 
200 	checkmouse();
201 	if (last_but == 1)
202 		return "p";	/* repaint after panning */
203 	if (last_but == 2) {
204 		return "c";
205 	} else if (last_but == 3) {
206 		switch (last_hit) {
207 		case Next:
208 			return "";
209 		case Prev:
210 			return "-1";
211 		case Page:
212 			screenprint("page? ");
213 			return "c";
214 		case Again:
215 			return "p";
216 		case Bigger:
217 			snprint(buf, sizeof buf, "m%g", mag * 1.1);
218 			return buf;
219 		case Smaller:
220 			snprint(buf, sizeof buf, "m%g", mag / 1.1);
221 			return buf;
222 		case Pan:
223 			return pan();
224 		case Quit:
225 			return "q";
226 		default:
227 			return "c";
228 		}
229 	} else {		/* button 1 or bail out */
230 		return "c";
231 	}
232 }
233 
234 static int
checkmouse(void)235 checkmouse(void)	/* return button touched if any */
236 {
237 	int c, b;
238 	char *p;
239 	extern int confirm(int);
240 
241 	b = waitdown();
242 	last_but = 0;
243 	last_hit = -1;
244 	c = 0;
245 	if (button3(b)) {
246 		last_hit = emenuhit(3, &mouse, &mbut3);
247 		last_but = 3;
248 	} else if (button2(b)) {
249 		last_hit = emenuhit(2, &mouse, &mbut2);
250 		last_but = 2;
251 	} else {		/* button1() */
252 		pan();
253 		last_but = 1;
254 	}
255 	waitup();
256 	if (last_but == 3 && last_hit >= 0) {
257 		p = m3[last_hit];
258 		c = p[strlen(p) - 1];
259 	}
260 	if (c == '?' && !confirm(last_but))
261 		last_hit = -1;
262 	return last_but;
263 }
264 
265 Cursor deadmouse = {
266 	{ 0, 0},	/* offset */
267 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
269 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
270 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
271 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
273 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
274 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
275 };
276 
277 Cursor blot ={
278 	{ 0, 0 },
279 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
280 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
281 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
282 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
283 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
284 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
285 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
286 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
287 };
288 
289 Cursor skull ={
290 	{ 0, 0 },
291 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
292 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
293 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
294 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
295 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
296 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
297 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
298 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
299 };
300 
confirm(int but)301 confirm(int but)	/* ask for confirmation if menu item ends with '?' */
302 {
303 	int c;
304 	static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 };
305 
306 	esetcursor(&skull);
307 	c = waitdown();
308 	waitup();
309 	esetcursor(0);
310 	return but == but_cvt[c];
311 }
312