| #include <u.h> | 
 | #include <libc.h> | 
 | #include <draw.h> | 
 | #include <cursor.h> | 
 | #include <event.h> | 
 | #include <bio.h> | 
 | #include "proof.h" | 
 |  | 
 | static	int	checkmouse(void); | 
 | /* static	int	buttondown(void); */ | 
 | static	char	*getmousestr(void); | 
 | static	char	*getkbdstr(int); | 
 |  | 
 | extern	Cursor	blot; | 
 | extern	char	*track; | 
 |  | 
 | Mouse	mouse; | 
 |  | 
 | void | 
 | mapscreen(void) | 
 | { | 
 | 	if(initdraw(0, 0, "proof") < 0){ | 
 | 		fprint(2, "proof: initdraw failed: %r\n"); | 
 | 		exits("initdraw"); | 
 | 	} | 
 | 	einit(Ekeyboard|Emouse); | 
 | } | 
 |  | 
 | void | 
 | clearscreen(void) | 
 | { | 
 | 	draw(screen, screen->r, display->black, nil, ZP); | 
 | } | 
 |  | 
 | void | 
 | screenprint(char *fmt, ...) | 
 | { | 
 | 	char buf[100]; | 
 | 	Point p; | 
 | 	va_list args; | 
 |  | 
 | 	va_start(args, fmt); | 
 | 	vseprint(buf, &buf[sizeof buf], fmt, args); | 
 | 	va_end(args); | 
 | 	p = Pt(screen->clipr.min.x+40, screen->clipr.max.y-40); | 
 | 	string(screen, p, display->black, ZP, font, buf); | 
 | } | 
 |  | 
 | #define	Viewkey	0xb2 | 
 | #define etimer(x, y) 0 | 
 |  | 
 | char * | 
 | getcmdstr(void) | 
 | { | 
 | 	Event ev; | 
 | 	int e; | 
 | 	static ulong timekey = 0; | 
 | 	ulong tracktm = 0; | 
 | 	Dir *dir; | 
 |  | 
 | 	if(track){ | 
 | 		if(timekey == 0) | 
 | 			timekey = etimer(0, 5000); | 
 | 		dir = dirstat(track); | 
 | 		if(dir != nil){ | 
 | 			tracktm = dir->mtime; | 
 | 			free(dir); | 
 | 		} | 
 | 	} | 
 | 	for (;;) { | 
 | 		e = event(&ev); | 
 | 		if(resized){ | 
 | 			resized = 0; | 
 | 			return "p"; | 
 | 		} | 
 | 		if ((e & Emouse) && ev.mouse.buttons) { | 
 | 			mouse = ev.mouse; | 
 | 			return getmousestr(); | 
 | 		} else if (e & Ekeyboard) | 
 | 			return getkbdstr(ev.kbdc);	/* sadly, no way to unget */ | 
 | 		else if (e & timekey) { | 
 | 			if((dir = dirstat(track)) != nil){ | 
 | 				if(tracktm < dir->mtime){ | 
 | 					free(dir); | 
 | 					return "q"; | 
 | 				} | 
 | 				free(dir); | 
 | 			} | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | static char * | 
 | getkbdstr(int c0) | 
 | { | 
 | 	static char buf[100]; | 
 | 	char *p; | 
 | 	int c; | 
 |  | 
 | 	if (c0 == '\n') | 
 | 		return ""; | 
 | 	buf[0] = c0; | 
 | 	buf[1] = 0; | 
 | 	screenprint("%s", buf); | 
 | 	for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) { | 
 | 		if (c == '\b' && p > buf) { | 
 | 			*--p = ' '; | 
 | 		} else { | 
 | 			*p++ = c; | 
 | 			*p = 0; | 
 | 		} | 
 | 		screenprint("%s", buf); | 
 | 	} | 
 | 	*p = 0; | 
 | 	return buf; | 
 | } | 
 |  | 
 |  | 
 | #define button3(b)	((b) & 4) | 
 | #define button2(b)	((b) & 2) | 
 | #define button1(b)	((b) & 1) | 
 | #define button23(b)	((b) & 6) | 
 | #define button123(b)	((b) & 7) | 
 |  | 
 | #define	butcvt(b)	(1 << ((b) - 1)) | 
 |  | 
 | #if 0 | 
 | static int buttondown(void)	/* report state of buttons, if any */ | 
 | { | 
 | 	if (!ecanmouse())	/* no event pending */ | 
 | 		return 0; | 
 | 	mouse = emouse();	/* something, but it could be motion */ | 
 | 	return mouse.buttons & 7; | 
 | } | 
 | #endif | 
 |  | 
 | int waitdown(void)	/* wait until some button is down */ | 
 | { | 
 | 	while (!(mouse.buttons & 7)) | 
 | 		mouse = emouse(); | 
 | 	return mouse.buttons & 7; | 
 | } | 
 |  | 
 | int waitup(void) | 
 | { | 
 | 	while (mouse.buttons & 7) | 
 | 		mouse = emouse(); | 
 | 	return mouse.buttons & 7; | 
 | } | 
 |  | 
 | char *m3[]	= { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 }; | 
 | char *m2[]	= { 0 }; | 
 |  | 
 | enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit }; | 
 |  | 
 | Menu	mbut3	= { m3, 0, 0 }; | 
 | Menu	mbut2	= { m2, 0, 0 }; | 
 |  | 
 | int	last_hit; | 
 | int	last_but; | 
 |  | 
 | char *pan(void) | 
 | { | 
 | 	Point dd, xy, lastxy, min, max; | 
 |  | 
 | 	esetcursor(&blot); | 
 | 	waitdown(); | 
 | 	xy = mouse.xy; | 
 | 	do{ | 
 | 		lastxy = mouse.xy; | 
 | 		mouse = emouse(); | 
 | 		dd = subpt(mouse.xy, lastxy); | 
 | 		min = addpt(screen->clipr.min, dd); | 
 | 		max = addpt(screen->clipr.max, dd); | 
 | 		draw(screen, rectaddpt(screen->r, subpt(mouse.xy, lastxy)), | 
 | 			screen, nil, screen->r.min); | 
 | 		if(mouse.xy.x < lastxy.x)	/* moved left, clear right */ | 
 | 			draw(screen, Rect(max.x, screen->r.min.y, screen->r.max.x, screen->r.max.y), | 
 | 				display->white, nil, ZP); | 
 | 		else	/* moved right, clear left*/ | 
 | 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, min.x, screen->r.max.y), | 
 | 				display->white, nil, ZP); | 
 | 		if(mouse.xy.y < lastxy.y)	/* moved up, clear down */ | 
 | 			draw(screen, Rect(screen->r.min.x, max.y, screen->r.max.x, screen->r.max.y), | 
 | 				display->white, nil, ZP); | 
 | 		else		/* moved down, clear up */ | 
 | 			draw(screen, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, min.y), | 
 | 				display->white, nil, ZP); | 
 | 		flushimage(display, 1); | 
 | 	}while(mouse.buttons); | 
 |  | 
 | 	xyoffset = addpt(xyoffset, subpt(mouse.xy, xy)); | 
 |  | 
 | 	esetcursor(0); | 
 | 	return "p"; | 
 | } | 
 |  | 
 | static char *getmousestr(void) | 
 | { | 
 | 	static char buf[20]; | 
 |  | 
 | 	checkmouse(); | 
 | 	if (last_but == 1) | 
 | 		return "p";	/* repaint after panning */ | 
 | 	if (last_but == 2) { | 
 | 		return "c"; | 
 | 	} else if (last_but == 3) { | 
 | 		switch (last_hit) { | 
 | 		case Next: | 
 | 			return ""; | 
 | 		case Prev: | 
 | 			return "-1"; | 
 | 		case Page: | 
 | 			screenprint("page? "); | 
 | 			return "c"; | 
 | 		case Again: | 
 | 			return "p"; | 
 | 		case Bigger: | 
 | 			sprint(buf, "m%g", mag * 1.1); | 
 | 			return buf; | 
 | 		case Smaller: | 
 | 			sprint(buf, "m%g", mag / 1.1); | 
 | 			return buf; | 
 | 		case Pan: | 
 | 			return pan(); | 
 | 		case Quit: | 
 | 			return "q"; | 
 | 		default: | 
 | 			return "c"; | 
 | 		} | 
 | 	} else {		/* button 1 or bail out */ | 
 | 		return "c"; | 
 | 	} | 
 | } | 
 |  | 
 | static int | 
 | checkmouse(void)	/* return button touched if any */ | 
 | { | 
 | 	int c, b; | 
 | 	char *p; | 
 | 	extern int confirm(int); | 
 |  | 
 | 	b = waitdown(); | 
 | 	last_but = 0; | 
 | 	last_hit = -1; | 
 | 	c = 0; | 
 | 	if (button3(b)) { | 
 | 		last_hit = emenuhit(3, &mouse, &mbut3); | 
 | 		last_but = 3; | 
 | 	} else if (button2(b)) { | 
 | 		last_hit = emenuhit(2, &mouse, &mbut2); | 
 | 		last_but = 2; | 
 | 	} else {		/* button1() */ | 
 | 		pan(); | 
 | 		last_but = 1; | 
 | 	} | 
 | 	waitup(); | 
 | 	if (last_but == 3 && last_hit >= 0) { | 
 | 		p = m3[last_hit]; | 
 | 		c = p[strlen(p) - 1]; | 
 | 	} | 
 | 	if (c == '?' && !confirm(last_but)) | 
 | 		last_hit = -1; | 
 | 	return last_but; | 
 | } | 
 |  | 
 | Cursor deadmouse = { | 
 | 	{ 0, 0},	/* offset */ | 
 | 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
 | 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41, | 
 | 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0, | 
 | 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, | 
 | 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
 | 	  0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41, | 
 | 	  0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0, | 
 | 	  0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } | 
 | }; | 
 |  | 
 | Cursor blot ={ | 
 | 	{ 0, 0 }, | 
 | 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, | 
 | 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 
 | 	  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } | 
 | }; | 
 |  | 
 | Cursor skull ={ | 
 | 	{ 0, 0 }, | 
 | 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, | 
 | 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0, | 
 | 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27, | 
 | 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, | 
 | 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, | 
 | 	  0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0, | 
 | 	  0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27, | 
 | 	  0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } | 
 | }; | 
 |  | 
 | int | 
 | confirm(int but)	/* ask for confirmation if menu item ends with '?' */ | 
 | { | 
 | 	int c; | 
 | 	static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 }; | 
 |  | 
 | 	esetcursor(&skull); | 
 | 	c = waitdown(); | 
 | 	waitup(); | 
 | 	esetcursor(0); | 
 | 	return but == but_cvt[c]; | 
 | } |