xref: /plan9-contrib/sys/src/cmd/proof/screen.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libg.h>
33e12c5d1SDavid du Colombier #include <libc.h>
43e12c5d1SDavid du Colombier #include <stdarg.h>
53e12c5d1SDavid du Colombier #include <bio.h>
63e12c5d1SDavid du Colombier #include "proof.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier Bitmap	screen;
93e12c5d1SDavid du Colombier Mouse 	mouse;
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier static	int	checkmouse(void);
123e12c5d1SDavid du Colombier static	int	buttondown(void);
133e12c5d1SDavid du Colombier static	char	*getmousestr(void);
143e12c5d1SDavid du Colombier static	char	*getkbdstr(int);
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier extern	Cursor	blot;
173e12c5d1SDavid du Colombier extern	char	*track;
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier void
203e12c5d1SDavid du Colombier mapscreen(void)
213e12c5d1SDavid du Colombier {
223e12c5d1SDavid du Colombier 	binit(0, 0, "proof");
233e12c5d1SDavid du Colombier 	einit(Ekeyboard|Emouse);
243e12c5d1SDavid du Colombier }
253e12c5d1SDavid du Colombier 
263e12c5d1SDavid du Colombier void
273e12c5d1SDavid du Colombier clearscreen(void)
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier 	bitblt(&screen, screen.r.min, &screen, screen.r, 0);
303e12c5d1SDavid du Colombier }
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier void
333e12c5d1SDavid du Colombier screenprint(char *fmt, ...)
343e12c5d1SDavid du Colombier {
353e12c5d1SDavid du Colombier 	char buf[100];
363e12c5d1SDavid du Colombier 	Point p;
373e12c5d1SDavid du Colombier 	va_list args;
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier 	va_start(args, fmt);
403e12c5d1SDavid du Colombier 	doprint(buf, &buf[sizeof buf], fmt, args);
413e12c5d1SDavid du Colombier 	va_end(args);
42*219b2ee8SDavid du Colombier 	p = Pt(screen.clipr.min.x+40, screen.clipr.max.y-40);
433e12c5d1SDavid du Colombier 	string(&screen, p, font, buf, S);
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier #define	Viewkey	0xb2
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier char *
503e12c5d1SDavid du Colombier getcmdstr(void)
513e12c5d1SDavid du Colombier {
523e12c5d1SDavid du Colombier 	Event ev;
533e12c5d1SDavid du Colombier 	int e;
54*219b2ee8SDavid du Colombier 	static ulong timekey = 0;
553e12c5d1SDavid du Colombier 	ulong tracktm = 0;
563e12c5d1SDavid du Colombier 	Dir dir;
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier 	if(track){
59*219b2ee8SDavid du Colombier 		if(timekey == 0)
603e12c5d1SDavid du Colombier 			timekey = etimer(0, 5000);
613e12c5d1SDavid du Colombier 		if(dirstat(track, &dir) >= 0)
623e12c5d1SDavid du Colombier 			tracktm = dir.mtime;
633e12c5d1SDavid du Colombier 	}
643e12c5d1SDavid du Colombier 	for (;;) {
653e12c5d1SDavid du Colombier 		e = event(&ev);
663e12c5d1SDavid du Colombier 		if ((e & Emouse) && ev.mouse.buttons) {
673e12c5d1SDavid du Colombier 			mouse = ev.mouse;
683e12c5d1SDavid du Colombier 			return getmousestr();
693e12c5d1SDavid du Colombier 		} else if (e & Ekeyboard)
703e12c5d1SDavid du Colombier 			return getkbdstr(ev.kbdc);	/* sadly, no way to unget */
713e12c5d1SDavid du Colombier 		else if (e & timekey) {
723e12c5d1SDavid du Colombier 			if((dirstat(track, &dir) >= 0) && (tracktm < dir.mtime))
733e12c5d1SDavid du Colombier 				return "q\n";
743e12c5d1SDavid du Colombier 		}
753e12c5d1SDavid du Colombier 	}
763e12c5d1SDavid du Colombier }
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier char *
793e12c5d1SDavid du Colombier getkbdstr(int c0)
803e12c5d1SDavid du Colombier {
813e12c5d1SDavid du Colombier 	static char buf[100];
823e12c5d1SDavid du Colombier 	char *p;
833e12c5d1SDavid du Colombier 	int c;
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier 	if (c0 == '\n')
863e12c5d1SDavid du Colombier 		return "";
873e12c5d1SDavid du Colombier 	buf[0] = c0;
883e12c5d1SDavid du Colombier 	buf[1] = 0;
893e12c5d1SDavid du Colombier 	screenprint("%s", buf);
903e12c5d1SDavid du Colombier 	for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) {
913e12c5d1SDavid du Colombier 		if (c == '\b' && p > buf) {
923e12c5d1SDavid du Colombier 			*--p = ' ';
933e12c5d1SDavid du Colombier 		} else {
943e12c5d1SDavid du Colombier 			*p++ = c;
953e12c5d1SDavid du Colombier 			*p = 0;
963e12c5d1SDavid du Colombier 		}
973e12c5d1SDavid du Colombier 		screenprint("%s", buf);
983e12c5d1SDavid du Colombier 	}
993e12c5d1SDavid du Colombier 	*p = 0;
1003e12c5d1SDavid du Colombier 	return buf;
1013e12c5d1SDavid du Colombier }
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier 
1043e12c5d1SDavid du Colombier #define button3(b)	((b) & 4)
1053e12c5d1SDavid du Colombier #define button2(b)	((b) & 2)
1063e12c5d1SDavid du Colombier #define button1(b)	((b) & 1)
1073e12c5d1SDavid du Colombier #define button23(b)	((b) & 6)
1083e12c5d1SDavid du Colombier #define button123(b)	((b) & 7)
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier #define	butcvt(b)	(1 << ((b) - 1))
1113e12c5d1SDavid du Colombier 
1123e12c5d1SDavid du Colombier int buttondown(void)	/* report state of buttons, if any */
1133e12c5d1SDavid du Colombier {
1143e12c5d1SDavid du Colombier 	if (!ecanmouse())	/* no event pending */
1153e12c5d1SDavid du Colombier 		return 0;
1163e12c5d1SDavid du Colombier 	mouse = emouse();	/* something, but it could be motion */
1173e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier int waitdown(void)	/* wait until some button is down */
1213e12c5d1SDavid du Colombier {
1223e12c5d1SDavid du Colombier 	while (!(mouse.buttons & 7))
1233e12c5d1SDavid du Colombier 		mouse = emouse();
1243e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier int waitup(void)
1283e12c5d1SDavid du Colombier {
1293e12c5d1SDavid du Colombier 	while (mouse.buttons & 7)
1303e12c5d1SDavid du Colombier 		mouse = emouse();
1313e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
1343e12c5d1SDavid du Colombier char *m3[]	= { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 };
1353e12c5d1SDavid du Colombier char *m2[]	= { 0 };
1363e12c5d1SDavid du Colombier 
1373e12c5d1SDavid du Colombier enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit };
1383e12c5d1SDavid du Colombier 
1393e12c5d1SDavid du Colombier Menu	mbut3	= { m3, 0, 0 };
1403e12c5d1SDavid du Colombier Menu	mbut2	= { m2, 0, 0 };
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier int	last_hit;
1433e12c5d1SDavid du Colombier int	last_but;
1443e12c5d1SDavid du Colombier 
145*219b2ee8SDavid du Colombier char *pan(void)
1463e12c5d1SDavid du Colombier {
147*219b2ee8SDavid du Colombier 	Point dd, xy, lastxy, min, max;
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier 	cursorswitch(&blot);
150*219b2ee8SDavid du Colombier 	waitdown();
151*219b2ee8SDavid du Colombier 	xy = mouse.xy;
152*219b2ee8SDavid du Colombier 	do{
153*219b2ee8SDavid du Colombier 		lastxy = mouse.xy;
154*219b2ee8SDavid du Colombier 		mouse = emouse();
155*219b2ee8SDavid du Colombier 		dd = sub(mouse.xy, lastxy);
156*219b2ee8SDavid du Colombier 		min = add(screen.clipr.min, dd);
157*219b2ee8SDavid du Colombier 		max = add(screen.clipr.max, dd);
158*219b2ee8SDavid du Colombier 		bitblt(&screen, add(screen.r.min, sub(mouse.xy, lastxy)), &screen, screen.r, S);
159*219b2ee8SDavid du Colombier 		if(mouse.xy.x < lastxy.x)	/* moved left, clear right */
160*219b2ee8SDavid du Colombier 			bitblt(&screen, Pt(max.x, screen.r.min.y), &screen,
161*219b2ee8SDavid du Colombier 				Rect(max.x, screen.r.min.y, screen.r.max.x, screen.r.max.y), 0);
162*219b2ee8SDavid du Colombier 		else	/* moved right, clear left*/
163*219b2ee8SDavid du Colombier 			bitblt(&screen, screen.r.min, &screen,
164*219b2ee8SDavid du Colombier 				Rect(screen.r.min.x, screen.r.min.y, min.x, screen.r.max.y), 0);
165*219b2ee8SDavid du Colombier 		if(mouse.xy.y < lastxy.y)	/* moved up, clear down */
166*219b2ee8SDavid du Colombier 			bitblt(&screen, Pt(screen.r.min.x, max.y), &screen,
167*219b2ee8SDavid du Colombier 				Rect(screen.r.min.x, max.y, screen.r.max.x, screen.r.max.y), 0);
168*219b2ee8SDavid du Colombier 		else		/* moved down, clear up */
169*219b2ee8SDavid du Colombier 			bitblt(&screen, screen.r.min, &screen,
170*219b2ee8SDavid du Colombier 				Rect(screen.r.min.x, screen.r.min.y, screen.r.max.x, min.y), 0);
171*219b2ee8SDavid du Colombier 		bflush();
172*219b2ee8SDavid du Colombier 	}while(mouse.buttons);
1733e12c5d1SDavid du Colombier 
174*219b2ee8SDavid du Colombier 	xyoffset = add(xyoffset, sub(mouse.xy, xy));
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 	cursorswitch(0);
1773e12c5d1SDavid du Colombier 	return "p";
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier char *getmousestr(void)
1813e12c5d1SDavid du Colombier {
1823e12c5d1SDavid du Colombier 	static char buf[20];
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier 	checkmouse();
1853e12c5d1SDavid du Colombier 	if (last_but == 2) {
1863e12c5d1SDavid du Colombier 		return "c";
1873e12c5d1SDavid du Colombier 	} else if (last_but == 3) {
1883e12c5d1SDavid du Colombier 		switch (last_hit) {
1893e12c5d1SDavid du Colombier 		case Next:
1903e12c5d1SDavid du Colombier 			return "";
1913e12c5d1SDavid du Colombier 		case Prev:
1923e12c5d1SDavid du Colombier 			return "-1";
1933e12c5d1SDavid du Colombier 		case Page:
1943e12c5d1SDavid du Colombier 			screenprint("page? ");
1953e12c5d1SDavid du Colombier 			return "c";
1963e12c5d1SDavid du Colombier 		case Again:
1973e12c5d1SDavid du Colombier 			return "p";
1983e12c5d1SDavid du Colombier 		case Bigger:
1993e12c5d1SDavid du Colombier 			sprint(buf, "m%g", mag * 1.1);
2003e12c5d1SDavid du Colombier 			return buf;
2013e12c5d1SDavid du Colombier 		case Smaller:
2023e12c5d1SDavid du Colombier 			sprint(buf, "m%g", mag / 1.1);
2033e12c5d1SDavid du Colombier 			return buf;
2043e12c5d1SDavid du Colombier 		case Pan:
205*219b2ee8SDavid du Colombier 			return pan();
2063e12c5d1SDavid du Colombier 		case Quit:
2073e12c5d1SDavid du Colombier 			return "q";
2083e12c5d1SDavid du Colombier 		default:
2093e12c5d1SDavid du Colombier 			return "c";
2103e12c5d1SDavid du Colombier 		}
2113e12c5d1SDavid du Colombier 	} else {		/* button 1 or bail out */
2123e12c5d1SDavid du Colombier 		return "c";
2133e12c5d1SDavid du Colombier 	}
2143e12c5d1SDavid du Colombier }
2153e12c5d1SDavid du Colombier 
2163e12c5d1SDavid du Colombier int
2173e12c5d1SDavid du Colombier checkmouse(void)	/* return button touched if any */
2183e12c5d1SDavid du Colombier {
2193e12c5d1SDavid du Colombier 	int c, b;
2203e12c5d1SDavid du Colombier 	char *p;
2213e12c5d1SDavid du Colombier 	extern int confirm(int);
2223e12c5d1SDavid du Colombier 
2233e12c5d1SDavid du Colombier 	b = waitdown();
2243e12c5d1SDavid du Colombier 	last_but = 0;
2253e12c5d1SDavid du Colombier 	last_hit = -1;
2263e12c5d1SDavid du Colombier 	c = 0;
2273e12c5d1SDavid du Colombier 	if (button3(b)) {
2283e12c5d1SDavid du Colombier 		last_hit = menuhit(3, &mouse, &mbut3);
2293e12c5d1SDavid du Colombier 		last_but = 3;
2303e12c5d1SDavid du Colombier 	} else if (button2(b)) {
2313e12c5d1SDavid du Colombier 		last_hit = menuhit(2, &mouse, &mbut2);
2323e12c5d1SDavid du Colombier 		last_but = 2;
2333e12c5d1SDavid du Colombier 	} else {		/* button1() */
2343e12c5d1SDavid du Colombier 		last_but = 1;
2353e12c5d1SDavid du Colombier 	}
2363e12c5d1SDavid du Colombier 	waitup();
2373e12c5d1SDavid du Colombier 	if (last_but == 3 && last_hit >= 0) {
2383e12c5d1SDavid du Colombier 		p = m3[last_hit];
2393e12c5d1SDavid du Colombier 		c = p[strlen(p) - 1];
2403e12c5d1SDavid du Colombier 	}
2413e12c5d1SDavid du Colombier 	if (c == '?' && !confirm(last_but))
2423e12c5d1SDavid du Colombier 		last_hit = -1;
2433e12c5d1SDavid du Colombier 	return last_but;
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier 
2463e12c5d1SDavid du Colombier Cursor deadmouse = {
2473e12c5d1SDavid du Colombier 	{ 0, 0},	/* offset */
2483e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2493e12c5d1SDavid du Colombier 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
2503e12c5d1SDavid du Colombier 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
2513e12c5d1SDavid du Colombier 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
2523e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2533e12c5d1SDavid du Colombier 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
2543e12c5d1SDavid du Colombier 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
2553e12c5d1SDavid du Colombier 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
2563e12c5d1SDavid du Colombier };
2573e12c5d1SDavid du Colombier 
2583e12c5d1SDavid du Colombier Cursor blot ={
2593e12c5d1SDavid du Colombier 	{ 0, 0 },
2603e12c5d1SDavid du Colombier 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2613e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2623e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2633e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
2643e12c5d1SDavid du Colombier 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2653e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2663e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2673e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
2683e12c5d1SDavid du Colombier };
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier Cursor skull ={
2713e12c5d1SDavid du Colombier 	{ 0, 0 },
2723e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
2733e12c5d1SDavid du Colombier 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
2743e12c5d1SDavid du Colombier 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
2753e12c5d1SDavid du Colombier 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
2763e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
2773e12c5d1SDavid du Colombier 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
2783e12c5d1SDavid du Colombier 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
2793e12c5d1SDavid du Colombier 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
2803e12c5d1SDavid du Colombier };
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier confirm(int but)	/* ask for confirmation if menu item ends with '?' */
2833e12c5d1SDavid du Colombier {
2843e12c5d1SDavid du Colombier 	int c;
2853e12c5d1SDavid du Colombier 	static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 };
2863e12c5d1SDavid du Colombier 
2873e12c5d1SDavid du Colombier 	cursorswitch(&skull);
2883e12c5d1SDavid du Colombier 	c = waitdown();
2893e12c5d1SDavid du Colombier 	waitup();
2903e12c5d1SDavid du Colombier 	cursorswitch(0);
2913e12c5d1SDavid du Colombier 	return but == but_cvt[c];
2923e12c5d1SDavid du Colombier }
293