xref: /plan9/sys/src/cmd/proof/screen.c (revision bfe6f91441b5ecf57fd2b06aea5c3ac4bd5daaa1)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <cursor.h>
57dd7cddfSDavid du Colombier #include <event.h>
63e12c5d1SDavid du Colombier #include <bio.h>
73e12c5d1SDavid du Colombier #include "proof.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier static	int	checkmouse(void);
103e12c5d1SDavid du Colombier static	int	buttondown(void);
113e12c5d1SDavid du Colombier static	char	*getmousestr(void);
123e12c5d1SDavid du Colombier static	char	*getkbdstr(int);
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier extern	Cursor	blot;
153e12c5d1SDavid du Colombier extern	char	*track;
163e12c5d1SDavid du Colombier 
177dd7cddfSDavid du Colombier Mouse	mouse;
187dd7cddfSDavid du Colombier 
193e12c5d1SDavid du Colombier void
mapscreen(void)203e12c5d1SDavid du Colombier mapscreen(void)
213e12c5d1SDavid du Colombier {
227dd7cddfSDavid du Colombier 	if(initdraw(0, 0, "proof") < 0){
237dd7cddfSDavid du Colombier 		fprint(2, "proof: initdraw failed: %r\n");
247dd7cddfSDavid du Colombier 		exits("initdraw");
257dd7cddfSDavid du Colombier 	}
263e12c5d1SDavid du Colombier 	einit(Ekeyboard|Emouse);
273e12c5d1SDavid du Colombier }
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier void
clearscreen(void)303e12c5d1SDavid du Colombier clearscreen(void)
313e12c5d1SDavid du Colombier {
327dd7cddfSDavid du Colombier 	draw(screen, screen->r, display->black, nil, ZP);
333e12c5d1SDavid du Colombier }
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier void
screenprint(char * fmt,...)363e12c5d1SDavid du Colombier screenprint(char *fmt, ...)
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier 	char buf[100];
393e12c5d1SDavid du Colombier 	Point p;
403e12c5d1SDavid du Colombier 	va_list args;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	va_start(args, fmt);
439a747e4fSDavid du Colombier 	vseprint(buf, &buf[sizeof buf], fmt, args);
443e12c5d1SDavid du Colombier 	va_end(args);
457dd7cddfSDavid du Colombier 	p = Pt(screen->clipr.min.x+40, screen->clipr.max.y-40);
467dd7cddfSDavid du Colombier 	string(screen, p, display->black, ZP, font, buf);
473e12c5d1SDavid du Colombier }
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier #define	Viewkey	0xb2
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier char *
getcmdstr(void)523e12c5d1SDavid du Colombier getcmdstr(void)
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier 	Event ev;
553e12c5d1SDavid du Colombier 	int e;
56219b2ee8SDavid du Colombier 	static ulong timekey = 0;
573e12c5d1SDavid du Colombier 	ulong tracktm = 0;
589a747e4fSDavid du Colombier 	Dir *dir;
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier 	if(track){
61219b2ee8SDavid du Colombier 		if(timekey == 0)
623e12c5d1SDavid du Colombier 			timekey = etimer(0, 5000);
639a747e4fSDavid du Colombier 		dir = dirstat(track);
649a747e4fSDavid du Colombier 		if(dir != nil){
659a747e4fSDavid du Colombier 			tracktm = dir->mtime;
669a747e4fSDavid du Colombier 			free(dir);
679a747e4fSDavid du Colombier 		}
683e12c5d1SDavid du Colombier 	}
693e12c5d1SDavid du Colombier 	for (;;) {
703e12c5d1SDavid du Colombier 		e = event(&ev);
717dd7cddfSDavid du Colombier 		if(resized){
727dd7cddfSDavid du Colombier 			resized = 0;
737dd7cddfSDavid du Colombier 			return "p";
747dd7cddfSDavid du Colombier 		}
753e12c5d1SDavid du Colombier 		if ((e & Emouse) && ev.mouse.buttons) {
763e12c5d1SDavid du Colombier 			mouse = ev.mouse;
773e12c5d1SDavid du Colombier 			return getmousestr();
783e12c5d1SDavid du Colombier 		} else if (e & Ekeyboard)
793e12c5d1SDavid du Colombier 			return getkbdstr(ev.kbdc);	/* sadly, no way to unget */
803e12c5d1SDavid du Colombier 		else if (e & timekey) {
819a747e4fSDavid du Colombier 			if((dir = dirstat(track)) != nil){
829a747e4fSDavid du Colombier 				if(tracktm < dir->mtime){
839a747e4fSDavid du Colombier 					free(dir);
847dd7cddfSDavid du Colombier 					return "q";
853e12c5d1SDavid du Colombier 				}
869a747e4fSDavid du Colombier 				free(dir);
873e12c5d1SDavid du Colombier 			}
883e12c5d1SDavid du Colombier 		}
899a747e4fSDavid du Colombier 	}
909a747e4fSDavid du Colombier }
913e12c5d1SDavid du Colombier 
927dd7cddfSDavid du Colombier static char *
getkbdstr(int c0)933e12c5d1SDavid du Colombier getkbdstr(int c0)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier 	static char buf[100];
963e12c5d1SDavid du Colombier 	char *p;
973e12c5d1SDavid du Colombier 	int c;
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	if (c0 == '\n')
1003e12c5d1SDavid du Colombier 		return "";
1013e12c5d1SDavid du Colombier 	buf[0] = c0;
1023e12c5d1SDavid du Colombier 	buf[1] = 0;
1033e12c5d1SDavid du Colombier 	screenprint("%s", buf);
1043e12c5d1SDavid du Colombier 	for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) {
1053e12c5d1SDavid du Colombier 		if (c == '\b' && p > buf) {
1063e12c5d1SDavid du Colombier 			*--p = ' ';
1073e12c5d1SDavid du Colombier 		} else {
1083e12c5d1SDavid du Colombier 			*p++ = c;
1093e12c5d1SDavid du Colombier 			*p = 0;
1103e12c5d1SDavid du Colombier 		}
1113e12c5d1SDavid du Colombier 		screenprint("%s", buf);
1123e12c5d1SDavid du Colombier 	}
1133e12c5d1SDavid du Colombier 	*p = 0;
1143e12c5d1SDavid du Colombier 	return buf;
1153e12c5d1SDavid du Colombier }
1163e12c5d1SDavid du Colombier 
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier #define button3(b)	((b) & 4)
1193e12c5d1SDavid du Colombier #define button2(b)	((b) & 2)
1203e12c5d1SDavid du Colombier #define button1(b)	((b) & 1)
1213e12c5d1SDavid du Colombier #define button23(b)	((b) & 6)
1223e12c5d1SDavid du Colombier #define button123(b)	((b) & 7)
1233e12c5d1SDavid du Colombier 
1243e12c5d1SDavid du Colombier #define	butcvt(b)	(1 << ((b) - 1))
1253e12c5d1SDavid du Colombier 
buttondown(void)1267dd7cddfSDavid du Colombier static int buttondown(void)	/* report state of buttons, if any */
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier 	if (!ecanmouse())	/* no event pending */
1293e12c5d1SDavid du Colombier 		return 0;
1303e12c5d1SDavid du Colombier 	mouse = emouse();	/* something, but it could be motion */
1313e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
waitdown(void)1343e12c5d1SDavid du Colombier int waitdown(void)	/* wait until some button is down */
1353e12c5d1SDavid du Colombier {
1363e12c5d1SDavid du Colombier 	while (!(mouse.buttons & 7))
1373e12c5d1SDavid du Colombier 		mouse = emouse();
1383e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1393e12c5d1SDavid du Colombier }
1403e12c5d1SDavid du Colombier 
waitup(void)1413e12c5d1SDavid du Colombier int waitup(void)
1423e12c5d1SDavid du Colombier {
1433e12c5d1SDavid du Colombier 	while (mouse.buttons & 7)
1443e12c5d1SDavid du Colombier 		mouse = emouse();
1453e12c5d1SDavid du Colombier 	return mouse.buttons & 7;
1463e12c5d1SDavid du Colombier }
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier char *m3[]	= { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 };
1493e12c5d1SDavid du Colombier char *m2[]	= { 0 };
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit };
1523e12c5d1SDavid du Colombier 
1533e12c5d1SDavid du Colombier Menu	mbut3	= { m3, 0, 0 };
1543e12c5d1SDavid du Colombier Menu	mbut2	= { m2, 0, 0 };
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier int	last_hit;
1573e12c5d1SDavid du Colombier int	last_but;
1583e12c5d1SDavid du Colombier 
pan(void)159219b2ee8SDavid du Colombier char *pan(void)
1603e12c5d1SDavid du Colombier {
161219b2ee8SDavid du Colombier 	Point dd, xy, lastxy, min, max;
1623e12c5d1SDavid du Colombier 
1637dd7cddfSDavid du Colombier 	esetcursor(&blot);
164219b2ee8SDavid du Colombier 	waitdown();
165219b2ee8SDavid du Colombier 	xy = mouse.xy;
166219b2ee8SDavid du Colombier 	do{
167219b2ee8SDavid du Colombier 		lastxy = mouse.xy;
168219b2ee8SDavid du Colombier 		mouse = emouse();
1697dd7cddfSDavid du Colombier 		dd = subpt(mouse.xy, lastxy);
1707dd7cddfSDavid du Colombier 		min = addpt(screen->clipr.min, dd);
1717dd7cddfSDavid du Colombier 		max = addpt(screen->clipr.max, dd);
1727dd7cddfSDavid du Colombier 		draw(screen, rectaddpt(screen->r, subpt(mouse.xy, lastxy)),
1737dd7cddfSDavid du Colombier 			screen, nil, screen->r.min);
174219b2ee8SDavid du Colombier 		if(mouse.xy.x < lastxy.x)	/* moved left, clear right */
1757dd7cddfSDavid du Colombier 			draw(screen, Rect(max.x, screen->r.min.y, screen->r.max.x, screen->r.max.y),
1767dd7cddfSDavid du Colombier 				display->white, nil, ZP);
177219b2ee8SDavid du Colombier 		else	/* moved right, clear left*/
1787dd7cddfSDavid du Colombier 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, min.x, screen->r.max.y),
1797dd7cddfSDavid du Colombier 				display->white, nil, ZP);
180219b2ee8SDavid du Colombier 		if(mouse.xy.y < lastxy.y)	/* moved up, clear down */
1817dd7cddfSDavid du Colombier 			draw(screen, Rect(screen->r.min.x, max.y, screen->r.max.x, screen->r.max.y),
1827dd7cddfSDavid du Colombier 				display->white, nil, ZP);
183219b2ee8SDavid du Colombier 		else		/* moved down, clear up */
1847dd7cddfSDavid du Colombier 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, min.y),
1857dd7cddfSDavid du Colombier 				display->white, nil, ZP);
1867dd7cddfSDavid du Colombier 		flushimage(display, 1);
187219b2ee8SDavid du Colombier 	}while(mouse.buttons);
1883e12c5d1SDavid du Colombier 
1897dd7cddfSDavid du Colombier 	xyoffset = addpt(xyoffset, subpt(mouse.xy, xy));
1903e12c5d1SDavid du Colombier 
1917dd7cddfSDavid du Colombier 	esetcursor(0);
1923e12c5d1SDavid du Colombier 	return "p";
1933e12c5d1SDavid du Colombier }
1943e12c5d1SDavid du Colombier 
195*bfe6f914SDavid du Colombier static char *
getmousestr(void)196*bfe6f914SDavid du Colombier getmousestr(void)
1973e12c5d1SDavid du Colombier {
198*bfe6f914SDavid du Colombier 	static char buf[64];
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier 	checkmouse();
2017dd7cddfSDavid du Colombier 	if (last_but == 1)
2027dd7cddfSDavid du Colombier 		return "p";	/* repaint after panning */
2033e12c5d1SDavid du Colombier 	if (last_but == 2) {
2043e12c5d1SDavid du Colombier 		return "c";
2053e12c5d1SDavid du Colombier 	} else if (last_but == 3) {
2063e12c5d1SDavid du Colombier 		switch (last_hit) {
2073e12c5d1SDavid du Colombier 		case Next:
2083e12c5d1SDavid du Colombier 			return "";
2093e12c5d1SDavid du Colombier 		case Prev:
2103e12c5d1SDavid du Colombier 			return "-1";
2113e12c5d1SDavid du Colombier 		case Page:
2123e12c5d1SDavid du Colombier 			screenprint("page? ");
2133e12c5d1SDavid du Colombier 			return "c";
2143e12c5d1SDavid du Colombier 		case Again:
2153e12c5d1SDavid du Colombier 			return "p";
2163e12c5d1SDavid du Colombier 		case Bigger:
217*bfe6f914SDavid du Colombier 			snprint(buf, sizeof buf, "m%g", mag * 1.1);
2183e12c5d1SDavid du Colombier 			return buf;
2193e12c5d1SDavid du Colombier 		case Smaller:
220*bfe6f914SDavid du Colombier 			snprint(buf, sizeof buf, "m%g", mag / 1.1);
2213e12c5d1SDavid du Colombier 			return buf;
2223e12c5d1SDavid du Colombier 		case Pan:
223219b2ee8SDavid du Colombier 			return pan();
2243e12c5d1SDavid du Colombier 		case Quit:
2253e12c5d1SDavid du Colombier 			return "q";
2263e12c5d1SDavid du Colombier 		default:
2273e12c5d1SDavid du Colombier 			return "c";
2283e12c5d1SDavid du Colombier 		}
2293e12c5d1SDavid du Colombier 	} else {		/* button 1 or bail out */
2303e12c5d1SDavid du Colombier 		return "c";
2313e12c5d1SDavid du Colombier 	}
2323e12c5d1SDavid du Colombier }
2333e12c5d1SDavid du Colombier 
2347dd7cddfSDavid du Colombier static int
checkmouse(void)2353e12c5d1SDavid du Colombier checkmouse(void)	/* return button touched if any */
2363e12c5d1SDavid du Colombier {
2373e12c5d1SDavid du Colombier 	int c, b;
2383e12c5d1SDavid du Colombier 	char *p;
2393e12c5d1SDavid du Colombier 	extern int confirm(int);
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier 	b = waitdown();
2423e12c5d1SDavid du Colombier 	last_but = 0;
2433e12c5d1SDavid du Colombier 	last_hit = -1;
2443e12c5d1SDavid du Colombier 	c = 0;
2453e12c5d1SDavid du Colombier 	if (button3(b)) {
2467dd7cddfSDavid du Colombier 		last_hit = emenuhit(3, &mouse, &mbut3);
2473e12c5d1SDavid du Colombier 		last_but = 3;
2483e12c5d1SDavid du Colombier 	} else if (button2(b)) {
2497dd7cddfSDavid du Colombier 		last_hit = emenuhit(2, &mouse, &mbut2);
2503e12c5d1SDavid du Colombier 		last_but = 2;
2513e12c5d1SDavid du Colombier 	} else {		/* button1() */
2527dd7cddfSDavid du Colombier 		pan();
2533e12c5d1SDavid du Colombier 		last_but = 1;
2543e12c5d1SDavid du Colombier 	}
2553e12c5d1SDavid du Colombier 	waitup();
2563e12c5d1SDavid du Colombier 	if (last_but == 3 && last_hit >= 0) {
2573e12c5d1SDavid du Colombier 		p = m3[last_hit];
2583e12c5d1SDavid du Colombier 		c = p[strlen(p) - 1];
2593e12c5d1SDavid du Colombier 	}
2603e12c5d1SDavid du Colombier 	if (c == '?' && !confirm(last_but))
2613e12c5d1SDavid du Colombier 		last_hit = -1;
2623e12c5d1SDavid du Colombier 	return last_but;
2633e12c5d1SDavid du Colombier }
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier Cursor deadmouse = {
2663e12c5d1SDavid du Colombier 	{ 0, 0},	/* offset */
2673e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2683e12c5d1SDavid du Colombier 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
2693e12c5d1SDavid du Colombier 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
2703e12c5d1SDavid du Colombier 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
2713e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2723e12c5d1SDavid du Colombier 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
2733e12c5d1SDavid du Colombier 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
2743e12c5d1SDavid du Colombier 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
2753e12c5d1SDavid du Colombier };
2763e12c5d1SDavid du Colombier 
2773e12c5d1SDavid du Colombier Cursor blot ={
2783e12c5d1SDavid du Colombier 	{ 0, 0 },
2793e12c5d1SDavid du Colombier 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2803e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2813e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2823e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
2833e12c5d1SDavid du Colombier 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2843e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2853e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
2863e12c5d1SDavid du Colombier 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
2873e12c5d1SDavid du Colombier };
2883e12c5d1SDavid du Colombier 
2893e12c5d1SDavid du Colombier Cursor skull ={
2903e12c5d1SDavid du Colombier 	{ 0, 0 },
2913e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
2923e12c5d1SDavid du Colombier 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
2933e12c5d1SDavid du Colombier 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
2943e12c5d1SDavid du Colombier 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
2953e12c5d1SDavid du Colombier 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
2963e12c5d1SDavid du Colombier 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
2973e12c5d1SDavid du Colombier 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
2983e12c5d1SDavid du Colombier 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
2993e12c5d1SDavid du Colombier };
3003e12c5d1SDavid du Colombier 
confirm(int but)3013e12c5d1SDavid du Colombier confirm(int but)	/* ask for confirmation if menu item ends with '?' */
3023e12c5d1SDavid du Colombier {
3033e12c5d1SDavid du Colombier 	int c;
3043e12c5d1SDavid du Colombier 	static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 };
3053e12c5d1SDavid du Colombier 
3067dd7cddfSDavid du Colombier 	esetcursor(&skull);
3073e12c5d1SDavid du Colombier 	c = waitdown();
3083e12c5d1SDavid du Colombier 	waitup();
3097dd7cddfSDavid du Colombier 	esetcursor(0);
3103e12c5d1SDavid du Colombier 	return but == but_cvt[c];
3113e12c5d1SDavid du Colombier }
312