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