xref: /plan9/sys/src/cmd/rio/rio.c (revision 666b04c8ce76f8147f9ff295e0d8b14ed1d420f1)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier /*
157dd7cddfSDavid du Colombier  *  WASHINGTON (AP) - The Food and Drug Administration warned
167dd7cddfSDavid du Colombier  * consumers Wednesday not to use ``Rio'' hair relaxer products
177dd7cddfSDavid du Colombier  * because they may cause severe hair loss or turn hair green....
187dd7cddfSDavid du Colombier  *    The FDA urged consumers who have experienced problems with Rio
197dd7cddfSDavid du Colombier  * to notify their local FDA office, local health department or the
207dd7cddfSDavid du Colombier  * company at 1‑800‑543‑3002.
217dd7cddfSDavid du Colombier  */
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier void		resize(void);
247dd7cddfSDavid du Colombier void		move(void);
257dd7cddfSDavid du Colombier void		delete(void);
267dd7cddfSDavid du Colombier void		hide(void);
277dd7cddfSDavid du Colombier void		unhide(int);
287dd7cddfSDavid du Colombier void		newtile(int);
297dd7cddfSDavid du Colombier Image	*sweep(void);
307dd7cddfSDavid du Colombier Image	*bandsize(Window*);
317dd7cddfSDavid du Colombier Image*	drag(Window*, Rectangle*);
327dd7cddfSDavid du Colombier void		refresh(Rectangle);
337dd7cddfSDavid du Colombier void		resized(void);
347dd7cddfSDavid du Colombier Channel	*exitchan;	/* chan(int) */
357dd7cddfSDavid du Colombier Channel	*winclosechan; /* chan(Window*); */
367dd7cddfSDavid du Colombier Rectangle	viewr;
379a747e4fSDavid du Colombier int		threadrforkflag = 0;	/* should be RFENVG but that hides rio from plumber */
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier void	mousethread(void*);
407dd7cddfSDavid du Colombier void	keyboardthread(void*);
417dd7cddfSDavid du Colombier void winclosethread(void*);
427dd7cddfSDavid du Colombier void deletethread(void*);
437dd7cddfSDavid du Colombier void	initcmd(void*);
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier char		*fontname;
467dd7cddfSDavid du Colombier int		mainpid;
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier enum
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier 	New,
517dd7cddfSDavid du Colombier 	Reshape,
527dd7cddfSDavid du Colombier 	Move,
537dd7cddfSDavid du Colombier 	Delete,
547dd7cddfSDavid du Colombier 	Hide,
557dd7cddfSDavid du Colombier 	Exit,
567dd7cddfSDavid du Colombier };
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier enum
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier 	Cut,
617dd7cddfSDavid du Colombier 	Paste,
627dd7cddfSDavid du Colombier 	Snarf,
637dd7cddfSDavid du Colombier 	Plumb,
647dd7cddfSDavid du Colombier 	Send,
657dd7cddfSDavid du Colombier 	Scroll,
667dd7cddfSDavid du Colombier };
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier char		*menu2str[] = {
697dd7cddfSDavid du Colombier  [Cut]		"cut",
707dd7cddfSDavid du Colombier  [Paste]		"paste",
717dd7cddfSDavid du Colombier  [Snarf]		"snarf",
727dd7cddfSDavid du Colombier  [Plumb]		"plumb",
737dd7cddfSDavid du Colombier  [Send]		"send",
747dd7cddfSDavid du Colombier  [Scroll]		"scroll",
757dd7cddfSDavid du Colombier 			nil
767dd7cddfSDavid du Colombier };
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier Menu menu2 =
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier 	menu2str
817dd7cddfSDavid du Colombier };
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier int	Hidden = Exit+1;
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier char		*menu3str[100] = {
867dd7cddfSDavid du Colombier  [New]		"New",
877dd7cddfSDavid du Colombier  [Reshape]	"Resize",
887dd7cddfSDavid du Colombier  [Move]		"Move",
897dd7cddfSDavid du Colombier  [Delete]		"Delete",
907dd7cddfSDavid du Colombier  [Hide]		"Hide",
917dd7cddfSDavid du Colombier  [Exit]		"Exit",
927dd7cddfSDavid du Colombier 			nil
937dd7cddfSDavid du Colombier };
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier Menu menu3 =
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier 	menu3str
987dd7cddfSDavid du Colombier };
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier char *rcargv[] = { "rc", "-i", nil };
10180ee5cbfSDavid du Colombier char *kbdargv[] = { "rc", "-c", nil, nil };
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier int errorshouldabort = 0;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier void
derror(Display *,char * errorstr)1067dd7cddfSDavid du Colombier derror(Display*, char *errorstr)
1077dd7cddfSDavid du Colombier {
1087dd7cddfSDavid du Colombier 	error(errorstr);
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier void
usage(void)11280ee5cbfSDavid du Colombier usage(void)
11380ee5cbfSDavid du Colombier {
11480ee5cbfSDavid du Colombier 	fprint(2, "usage: rio [-f font] [-i initcmd] [-k kbdcmd] [-s]\n");
11580ee5cbfSDavid du Colombier 	exits("usage");
11680ee5cbfSDavid du Colombier }
11780ee5cbfSDavid du Colombier 
11880ee5cbfSDavid du Colombier void
threadmain(int argc,char * argv[])1197dd7cddfSDavid du Colombier threadmain(int argc, char *argv[])
1207dd7cddfSDavid du Colombier {
12180ee5cbfSDavid du Colombier 	char *initstr, *kbdin, *s;
1227dd7cddfSDavid du Colombier 	static void *arg[1];
1237dd7cddfSDavid du Colombier 	char buf[256];
12480ee5cbfSDavid du Colombier 	Image *i;
12580ee5cbfSDavid du Colombier 	Rectangle r;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	if(strstr(argv[0], ".out") == nil){
1287dd7cddfSDavid du Colombier 		menu3str[Exit] = nil;
1297dd7cddfSDavid du Colombier 		Hidden--;
1307dd7cddfSDavid du Colombier 	}
1317dd7cddfSDavid du Colombier 	initstr = nil;
13280ee5cbfSDavid du Colombier 	kbdin = nil;
1337dd7cddfSDavid du Colombier 	maxtab = 0;
1347dd7cddfSDavid du Colombier 	ARGBEGIN{
1357dd7cddfSDavid du Colombier 	case 'f':
1367dd7cddfSDavid du Colombier 		fontname = ARGF();
13780ee5cbfSDavid du Colombier 		if(fontname == nil)
13880ee5cbfSDavid du Colombier 			usage();
1397dd7cddfSDavid du Colombier 		break;
1407dd7cddfSDavid du Colombier 	case 'i':
1417dd7cddfSDavid du Colombier 		initstr = ARGF();
14280ee5cbfSDavid du Colombier 		if(initstr == nil)
14380ee5cbfSDavid du Colombier 			usage();
14480ee5cbfSDavid du Colombier 		break;
14580ee5cbfSDavid du Colombier 	case 'k':
14680ee5cbfSDavid du Colombier 		if(kbdin != nil)
14780ee5cbfSDavid du Colombier 			usage();
14880ee5cbfSDavid du Colombier 		kbdin = ARGF();
14980ee5cbfSDavid du Colombier 		if(kbdin == nil)
15080ee5cbfSDavid du Colombier 			usage();
1517dd7cddfSDavid du Colombier 		break;
1527dd7cddfSDavid du Colombier 	case 's':
1537dd7cddfSDavid du Colombier 		scrolling = TRUE;
1547dd7cddfSDavid du Colombier 		break;
1557dd7cddfSDavid du Colombier 	}ARGEND
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier 	mainpid = getpid();
1587dd7cddfSDavid du Colombier 	if(getwd(buf, sizeof buf) == nil)
1597dd7cddfSDavid du Colombier 		startdir = estrdup(".");
1607dd7cddfSDavid du Colombier 	else
1617dd7cddfSDavid du Colombier 		startdir = estrdup(buf);
1627dd7cddfSDavid du Colombier 	if(fontname == nil)
1637dd7cddfSDavid du Colombier 		fontname = getenv("font");
1647dd7cddfSDavid du Colombier 	if(fontname == nil)
1657dd7cddfSDavid du Colombier 		fontname = "/lib/font/bit/lucm/unicode.9.font";
1667dd7cddfSDavid du Colombier 	s = getenv("tabstop");
1677dd7cddfSDavid du Colombier 	if(s != nil)
1687dd7cddfSDavid du Colombier 		maxtab = strtol(s, nil, 0);
1697dd7cddfSDavid du Colombier 	if(maxtab == 0)
1707dd7cddfSDavid du Colombier 		maxtab = 4;
1719a747e4fSDavid du Colombier 	free(s);
1727dd7cddfSDavid du Colombier 	/* check font before barging ahead */
1737dd7cddfSDavid du Colombier 	if(access(fontname, 0) < 0){
1749a747e4fSDavid du Colombier 		fprint(2, "rio: can't access %s: %r\n", fontname);
1757dd7cddfSDavid du Colombier 		exits("font open");
1767dd7cddfSDavid du Colombier 	}
1777dd7cddfSDavid du Colombier 	putenv("font", fontname);
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier 	snarffd = open("/dev/snarf", OREAD|OCEXEC);
1807dd7cddfSDavid du Colombier 
18114414594SDavid du Colombier 	if(geninitdraw(nil, derror, nil, "rio", nil, Refnone) < 0){
1829a747e4fSDavid du Colombier 		fprint(2, "rio: can't open display: %r\n");
18314414594SDavid du Colombier 		exits("display open");
18414414594SDavid du Colombier 	}
1857dd7cddfSDavid du Colombier 	iconinit();
1867dd7cddfSDavid du Colombier 	view = screen;
1877dd7cddfSDavid du Colombier 	viewr = view->r;
1887dd7cddfSDavid du Colombier 	mousectl = initmouse(nil, screen);
1897dd7cddfSDavid du Colombier 	if(mousectl == nil)
1907dd7cddfSDavid du Colombier 		error("can't find mouse");
1917dd7cddfSDavid du Colombier 	mouse = mousectl;
1927dd7cddfSDavid du Colombier 	keyboardctl = initkeyboard(nil);
1937dd7cddfSDavid du Colombier 	if(keyboardctl == nil)
1947dd7cddfSDavid du Colombier 		error("can't find keyboard");
1957dd7cddfSDavid du Colombier 	wscreen = allocscreen(screen, background, 0);
1967dd7cddfSDavid du Colombier 	if(wscreen == nil)
1977dd7cddfSDavid du Colombier 		error("can't allocate screen");
1987dd7cddfSDavid du Colombier 	draw(view, viewr, background, nil, ZP);
1997dd7cddfSDavid du Colombier 	flushimage(display, 1);
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	exitchan = chancreate(sizeof(int), 0);
2027dd7cddfSDavid du Colombier 	winclosechan = chancreate(sizeof(Window*), 0);
2037dd7cddfSDavid du Colombier 	deletechan = chancreate(sizeof(char*), 0);
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	timerinit();
2067dd7cddfSDavid du Colombier 	threadcreate(keyboardthread, nil, STACK);
2077dd7cddfSDavid du Colombier 	threadcreate(mousethread, nil, STACK);
2087dd7cddfSDavid du Colombier 	threadcreate(winclosethread, nil, STACK);
2097dd7cddfSDavid du Colombier 	threadcreate(deletethread, nil, STACK);
2107dd7cddfSDavid du Colombier 	filsys = filsysinit(xfidinit());
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier 	if(filsys == nil)
2137dd7cddfSDavid du Colombier 		fprint(2, "rio: can't create file system server: %r\n");
2147dd7cddfSDavid du Colombier 	else{
2157dd7cddfSDavid du Colombier 		errorshouldabort = 1;	/* suicide if there's trouble after this */
2167dd7cddfSDavid du Colombier 		if(initstr)
2177dd7cddfSDavid du Colombier 			proccreate(initcmd, initstr, STACK);
21880ee5cbfSDavid du Colombier 		if(kbdin){
21980ee5cbfSDavid du Colombier 			kbdargv[2] = kbdin;
22080ee5cbfSDavid du Colombier 			r = screen->r;
22180ee5cbfSDavid du Colombier 			r.max.x = r.min.x+300;
22280ee5cbfSDavid du Colombier 			r.max.y = r.min.y+80;
22380ee5cbfSDavid du Colombier 			i = allocwindow(wscreen, r, Refbackup, DWhite);
2243ff48bf5SDavid du Colombier 			wkeyboard = new(i, FALSE, scrolling, 0, nil, "/bin/rc", kbdargv);
22580ee5cbfSDavid du Colombier 			if(wkeyboard == nil)
22680ee5cbfSDavid du Colombier 				error("can't create keyboard window");
22780ee5cbfSDavid du Colombier 		}
228d9306527SDavid du Colombier 		threadnotify(shutdown, 1);
2297dd7cddfSDavid du Colombier 		recv(exitchan, nil);
2307dd7cddfSDavid du Colombier 	}
2317dd7cddfSDavid du Colombier 	killprocs();
2327dd7cddfSDavid du Colombier 	threadexitsall(nil);
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier /*
2367dd7cddfSDavid du Colombier  * /dev/snarf updates when the file is closed, so we must open our own
2377dd7cddfSDavid du Colombier  * fd here rather than use snarffd
2387dd7cddfSDavid du Colombier  */
2397dd7cddfSDavid du Colombier void
putsnarf(void)2407dd7cddfSDavid du Colombier putsnarf(void)
2417dd7cddfSDavid du Colombier {
2427dd7cddfSDavid du Colombier 	int fd, i, n;
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier 	if(snarffd<0 || nsnarf==0)
2457dd7cddfSDavid du Colombier 		return;
2467dd7cddfSDavid du Colombier 	fd = open("/dev/snarf", OWRITE);
2477dd7cddfSDavid du Colombier 	if(fd < 0)
2487dd7cddfSDavid du Colombier 		return;
2497dd7cddfSDavid du Colombier 	/* snarf buffer could be huge, so fprint will truncate; do it in blocks */
2507dd7cddfSDavid du Colombier 	for(i=0; i<nsnarf; i+=n){
2517dd7cddfSDavid du Colombier 		n = nsnarf-i;
2527dd7cddfSDavid du Colombier 		if(n >= 256)
2537dd7cddfSDavid du Colombier 			n = 256;
2549a747e4fSDavid du Colombier 		if(fprint(fd, "%.*S", n, snarf+i) < 0)
2557dd7cddfSDavid du Colombier 			break;
2567dd7cddfSDavid du Colombier 	}
2577dd7cddfSDavid du Colombier 	close(fd);
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier void
getsnarf(void)2617dd7cddfSDavid du Colombier getsnarf(void)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier 	int i, n, nb, nulls;
2647dd7cddfSDavid du Colombier 	char *sn, buf[1024];
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier 	if(snarffd < 0)
2677dd7cddfSDavid du Colombier 		return;
2687dd7cddfSDavid du Colombier 	sn = nil;
2697dd7cddfSDavid du Colombier 	i = 0;
2707dd7cddfSDavid du Colombier 	seek(snarffd, 0, 0);
2717dd7cddfSDavid du Colombier 	while((n = read(snarffd, buf, sizeof buf)) > 0){
2727dd7cddfSDavid du Colombier 		sn = erealloc(sn, i+n+1);
2737dd7cddfSDavid du Colombier 		memmove(sn+i, buf, n);
2747dd7cddfSDavid du Colombier 		i += n;
2757dd7cddfSDavid du Colombier 		sn[i] = 0;
2767dd7cddfSDavid du Colombier 	}
2777dd7cddfSDavid du Colombier 	if(i > 0){
2787dd7cddfSDavid du Colombier 		snarf = runerealloc(snarf, i+1);
2797dd7cddfSDavid du Colombier 		cvttorunes(sn, i, snarf, &nb, &nsnarf, &nulls);
2807dd7cddfSDavid du Colombier 		free(sn);
2817dd7cddfSDavid du Colombier 	}
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier 
2847dd7cddfSDavid du Colombier void
initcmd(void * arg)2857dd7cddfSDavid du Colombier initcmd(void *arg)
2867dd7cddfSDavid du Colombier {
2877dd7cddfSDavid du Colombier 	char *cmd;
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier 	cmd = arg;
2907dd7cddfSDavid du Colombier 	rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);
291f19e7b74SDavid du Colombier 	procexecl(nil, "/bin/rc", "rc", "-c", cmd, nil);
2929a747e4fSDavid du Colombier 	fprint(2, "rio: exec failed: %r\n");
2937dd7cddfSDavid du Colombier 	exits("exec");
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier char *oknotes[] =
2977dd7cddfSDavid du Colombier {
2987dd7cddfSDavid du Colombier 	"delete",
2997dd7cddfSDavid du Colombier 	"hangup",
3007dd7cddfSDavid du Colombier 	"kill",
3017dd7cddfSDavid du Colombier 	"exit",
3027dd7cddfSDavid du Colombier 	nil
3037dd7cddfSDavid du Colombier };
3047dd7cddfSDavid du Colombier 
305d9306527SDavid du Colombier int
shutdown(void *,char * msg)3069a747e4fSDavid du Colombier shutdown(void *, char *msg)
3077dd7cddfSDavid du Colombier {
3087dd7cddfSDavid du Colombier 	int i;
309f366f900SDavid du Colombier 	static Lock shutdownlk;
3107dd7cddfSDavid du Colombier 
3117dd7cddfSDavid du Colombier 	killprocs();
3127dd7cddfSDavid du Colombier 	for(i=0; oknotes[i]; i++)
313f366f900SDavid du Colombier 		if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0){
314f366f900SDavid du Colombier 			lock(&shutdownlk);	/* only one can threadexitsall */
3157dd7cddfSDavid du Colombier 			threadexitsall(msg);
316f366f900SDavid du Colombier 		}
3179a747e4fSDavid du Colombier 	fprint(2, "rio %d: abort: %s\n", getpid(), msg);
3187dd7cddfSDavid du Colombier 	abort();
3197dd7cddfSDavid du Colombier 	exits(msg);
320d9306527SDavid du Colombier 	return 0;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier 
3237dd7cddfSDavid du Colombier void
killprocs(void)3247dd7cddfSDavid du Colombier killprocs(void)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier 	int i;
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 	for(i=0; i<nwindow; i++)
3297dd7cddfSDavid du Colombier 		postnote(PNGROUP, window[i]->pid, "hangup");
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier void
keyboardthread(void *)3337dd7cddfSDavid du Colombier keyboardthread(void*)
3347dd7cddfSDavid du Colombier {
3357dd7cddfSDavid du Colombier 	Rune buf[2][20], *rp;
3367dd7cddfSDavid du Colombier 	int n, i;
3377dd7cddfSDavid du Colombier 
33859cc4ca5SDavid du Colombier 	threadsetname("keyboardthread");
3397dd7cddfSDavid du Colombier 	n = 0;
3407dd7cddfSDavid du Colombier 	for(;;){
3417dd7cddfSDavid du Colombier 		rp = buf[n];
3427dd7cddfSDavid du Colombier 		n = 1-n;
3437dd7cddfSDavid du Colombier 		recv(keyboardctl->c, rp);
3447dd7cddfSDavid du Colombier 		for(i=1; i<nelem(buf[0])-1; i++)
3457dd7cddfSDavid du Colombier 			if(nbrecv(keyboardctl->c, rp+i) <= 0)
3467dd7cddfSDavid du Colombier 				break;
3477dd7cddfSDavid du Colombier 		rp[i] = L'\0';
3487dd7cddfSDavid du Colombier 		if(input != nil)
3497dd7cddfSDavid du Colombier 			sendp(input->ck, rp);
3507dd7cddfSDavid du Colombier 	}
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier 
35380ee5cbfSDavid du Colombier /*
35480ee5cbfSDavid du Colombier  * Used by /dev/kbdin
35580ee5cbfSDavid du Colombier  */
35680ee5cbfSDavid du Colombier void
keyboardsend(char * s,int cnt)35780ee5cbfSDavid du Colombier keyboardsend(char *s, int cnt)
35880ee5cbfSDavid du Colombier {
35980ee5cbfSDavid du Colombier 	Rune *r;
36080ee5cbfSDavid du Colombier 	int i, nb, nr;
36180ee5cbfSDavid du Colombier 
36280ee5cbfSDavid du Colombier 	r = runemalloc(cnt);
36380ee5cbfSDavid du Colombier 	/* BUGlet: partial runes will be converted to error runes */
36480ee5cbfSDavid du Colombier 	cvttorunes(s, cnt, r, &nb, &nr, nil);
36580ee5cbfSDavid du Colombier 	for(i=0; i<nr; i++)
36680ee5cbfSDavid du Colombier 		send(keyboardctl->c, &r[i]);
36780ee5cbfSDavid du Colombier 	free(r);
36880ee5cbfSDavid du Colombier }
36980ee5cbfSDavid du Colombier 
3707dd7cddfSDavid du Colombier int
portion(int x,int lo,int hi)3717dd7cddfSDavid du Colombier portion(int x, int lo, int hi)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier 	x -= lo;
3747dd7cddfSDavid du Colombier 	hi -= lo;
3757dd7cddfSDavid du Colombier 	if(x < 20)
3767dd7cddfSDavid du Colombier 		return 0;
3777dd7cddfSDavid du Colombier 	if(x > hi-20)
3787dd7cddfSDavid du Colombier 		return 2;
3797dd7cddfSDavid du Colombier 	return 1;
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier int
whichcorner(Window * w,Point p)3837dd7cddfSDavid du Colombier whichcorner(Window *w, Point p)
3847dd7cddfSDavid du Colombier {
3857dd7cddfSDavid du Colombier 	int i, j;
3867dd7cddfSDavid du Colombier 
3877dd7cddfSDavid du Colombier 	i = portion(p.x, w->screenr.min.x, w->screenr.max.x);
3887dd7cddfSDavid du Colombier 	j = portion(p.y, w->screenr.min.y, w->screenr.max.y);
3897dd7cddfSDavid du Colombier 	return 3*j+i;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier void
cornercursor(Window * w,Point p,int force)3937dd7cddfSDavid du Colombier cornercursor(Window *w, Point p, int force)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier 	if(w!=nil && winborder(w, p))
3967dd7cddfSDavid du Colombier 		riosetcursor(corners[whichcorner(w, p)], force);
3977dd7cddfSDavid du Colombier 	else
3987dd7cddfSDavid du Colombier 		wsetcursor(w, force);
3997dd7cddfSDavid du Colombier }
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier /* thread to allow fsysproc to synchronize window closing with main proc */
4027dd7cddfSDavid du Colombier void
winclosethread(void *)4037dd7cddfSDavid du Colombier winclosethread(void*)
4047dd7cddfSDavid du Colombier {
4057dd7cddfSDavid du Colombier 	Window *w;
4067dd7cddfSDavid du Colombier 
40759cc4ca5SDavid du Colombier 	threadsetname("winclosethread");
4087dd7cddfSDavid du Colombier 	for(;;){
4097dd7cddfSDavid du Colombier 		w = recvp(winclosechan);
4107dd7cddfSDavid du Colombier 		wclose(w);
4117dd7cddfSDavid du Colombier 	}
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier 
4147dd7cddfSDavid du Colombier /* thread to make Deleted windows that the client still holds disappear offscreen after an interval */
4157dd7cddfSDavid du Colombier void
deletethread(void *)4167dd7cddfSDavid du Colombier deletethread(void*)
4177dd7cddfSDavid du Colombier {
4187dd7cddfSDavid du Colombier 	char *s;
4197dd7cddfSDavid du Colombier 	Image *i;
4207dd7cddfSDavid du Colombier 
42159cc4ca5SDavid du Colombier 	threadsetname("deletethread");
4227dd7cddfSDavid du Colombier 	for(;;){
4237dd7cddfSDavid du Colombier 		s = recvp(deletechan);
4247dd7cddfSDavid du Colombier 		i = namedimage(display, s);
4257dd7cddfSDavid du Colombier 		if(i != nil){
4267dd7cddfSDavid du Colombier 			/* move it off-screen to hide it, since client is slow in letting it go */
4277dd7cddfSDavid du Colombier 			originwindow(i, i->r.min, view->r.max);
4287dd7cddfSDavid du Colombier 		}
4297dd7cddfSDavid du Colombier 		freeimage(i);
4307dd7cddfSDavid du Colombier 		free(s);
4317dd7cddfSDavid du Colombier 	}
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier 
4347dd7cddfSDavid du Colombier void
deletetimeoutproc(void * v)4357dd7cddfSDavid du Colombier deletetimeoutproc(void *v)
4367dd7cddfSDavid du Colombier {
4377dd7cddfSDavid du Colombier 	char *s;
4387dd7cddfSDavid du Colombier 
4399a747e4fSDavid du Colombier 	s = v;
4407dd7cddfSDavid du Colombier 	sleep(750);	/* remove window from screen after 3/4 of a second */
4417dd7cddfSDavid du Colombier 	sendp(deletechan, s);
4427dd7cddfSDavid du Colombier }
4437dd7cddfSDavid du Colombier 
44480ee5cbfSDavid du Colombier /*
44580ee5cbfSDavid du Colombier  * Button 6 - keyboard toggle - has been pressed.
44680ee5cbfSDavid du Colombier  * Send event to keyboard, wait for button up, send that.
44780ee5cbfSDavid du Colombier  * Note: there is no coordinate translation done here; this
44880ee5cbfSDavid du Colombier  * is just about getting button 6 to the keyboard simulator.
44980ee5cbfSDavid du Colombier  */
45080ee5cbfSDavid du Colombier void
keyboardhide(void)45180ee5cbfSDavid du Colombier keyboardhide(void)
45280ee5cbfSDavid du Colombier {
45380ee5cbfSDavid du Colombier 	send(wkeyboard->mc.c, mouse);
45480ee5cbfSDavid du Colombier 	do
45580ee5cbfSDavid du Colombier 		readmouse(mousectl);
45680ee5cbfSDavid du Colombier 	while(mouse->buttons & (1<<5));
45780ee5cbfSDavid du Colombier 	send(wkeyboard->mc.c, mouse);
45880ee5cbfSDavid du Colombier }
45980ee5cbfSDavid du Colombier 
4607dd7cddfSDavid du Colombier void
mousethread(void *)4617dd7cddfSDavid du Colombier mousethread(void*)
4627dd7cddfSDavid du Colombier {
4637dd7cddfSDavid du Colombier 	int sending, inside, scrolling, moving, band;
46480ee5cbfSDavid du Colombier 	Window *oin, *w, *winput;
4657dd7cddfSDavid du Colombier 	Image *i;
4667dd7cddfSDavid du Colombier 	Rectangle r;
4677dd7cddfSDavid du Colombier 	Point xy;
4687dd7cddfSDavid du Colombier 	Mouse tmp;
4697dd7cddfSDavid du Colombier 	enum {
4707dd7cddfSDavid du Colombier 		MReshape,
4717dd7cddfSDavid du Colombier 		MMouse,
4727dd7cddfSDavid du Colombier 		NALT
4737dd7cddfSDavid du Colombier 	};
4747dd7cddfSDavid du Colombier 	static Alt alts[NALT+1];
4757dd7cddfSDavid du Colombier 
47659cc4ca5SDavid du Colombier 	threadsetname("mousethread");
4777dd7cddfSDavid du Colombier 	sending = FALSE;
4787dd7cddfSDavid du Colombier 	scrolling = FALSE;
4797dd7cddfSDavid du Colombier 	moving = FALSE;
4807dd7cddfSDavid du Colombier 
4817dd7cddfSDavid du Colombier 	alts[MReshape].c = mousectl->resizec;
4827dd7cddfSDavid du Colombier 	alts[MReshape].v = nil;
4837dd7cddfSDavid du Colombier 	alts[MReshape].op = CHANRCV;
4847dd7cddfSDavid du Colombier 	alts[MMouse].c = mousectl->c;
4857dd7cddfSDavid du Colombier 	alts[MMouse].v = &mousectl->Mouse;
4867dd7cddfSDavid du Colombier 	alts[MMouse].op = CHANRCV;
4877dd7cddfSDavid du Colombier 	alts[NALT].op = CHANEND;
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier 	for(;;)
4907dd7cddfSDavid du Colombier 	    switch(alt(alts)){
4917dd7cddfSDavid du Colombier 		case MReshape:
4927dd7cddfSDavid du Colombier 			resized();
4937dd7cddfSDavid du Colombier 			break;
4947dd7cddfSDavid du Colombier 		case MMouse:
49580ee5cbfSDavid du Colombier 			if(wkeyboard!=nil && (mouse->buttons & (1<<5))){
49680ee5cbfSDavid du Colombier 				keyboardhide();
49780ee5cbfSDavid du Colombier 				break;
49880ee5cbfSDavid du Colombier 			}
4997dd7cddfSDavid du Colombier 		Again:
50080ee5cbfSDavid du Colombier 			winput = input;
50180ee5cbfSDavid du Colombier 			/* override everything for the keyboard window */
50280ee5cbfSDavid du Colombier 			if(wkeyboard!=nil && ptinrect(mouse->xy, wkeyboard->screenr)){
50380ee5cbfSDavid du Colombier 				/* make sure it's on top; this call is free if it is */
50480ee5cbfSDavid du Colombier 				wtopme(wkeyboard);
50580ee5cbfSDavid du Colombier 				winput = wkeyboard;
50680ee5cbfSDavid du Colombier 			}
50780ee5cbfSDavid du Colombier 			if(winput!=nil && winput->i!=nil){
5087dd7cddfSDavid du Colombier 				/* convert to logical coordinates */
50980ee5cbfSDavid du Colombier 				xy.x = mouse->xy.x + (winput->i->r.min.x-winput->screenr.min.x);
51080ee5cbfSDavid du Colombier 				xy.y = mouse->xy.y + (winput->i->r.min.y-winput->screenr.min.y);
5119847521cSDavid du Colombier 
5129847521cSDavid du Colombier 				/* the up and down scroll buttons are not subject to the usual rules */
5139847521cSDavid du Colombier 				if((mouse->buttons&(8|16)) && !winput->mouseopen)
5149847521cSDavid du Colombier 					goto Sending;
5159847521cSDavid du Colombier 
51680ee5cbfSDavid du Colombier 				inside = ptinrect(mouse->xy, insetrect(winput->screenr, Selborder));
51780ee5cbfSDavid du Colombier 				if(winput->mouseopen)
5187dd7cddfSDavid du Colombier 					scrolling = FALSE;
5197dd7cddfSDavid du Colombier 				else if(scrolling)
5207dd7cddfSDavid du Colombier 					scrolling = mouse->buttons;
5217dd7cddfSDavid du Colombier 				else
52280ee5cbfSDavid du Colombier 					scrolling = mouse->buttons && ptinrect(xy, winput->scrollr);
52376f6a3b8SDavid du Colombier 				/* topped will be zero or less if window has been bottomed */
52480ee5cbfSDavid du Colombier 				if(sending == FALSE && !scrolling && winborder(winput, mouse->xy) && winput->topped>0){
5257dd7cddfSDavid du Colombier 					moving = TRUE;
52680ee5cbfSDavid du Colombier 				}else if(inside && (scrolling || winput->mouseopen || (mouse->buttons&1)))
5277dd7cddfSDavid du Colombier 					sending = TRUE;
5287dd7cddfSDavid du Colombier 			}else
5297dd7cddfSDavid du Colombier 				sending = FALSE;
5307dd7cddfSDavid du Colombier 			if(sending){
5319847521cSDavid du Colombier 			Sending:
5327dd7cddfSDavid du Colombier 				if(mouse->buttons == 0){
53380ee5cbfSDavid du Colombier 					cornercursor(winput, mouse->xy, 0);
5347dd7cddfSDavid du Colombier 					sending = FALSE;
5357dd7cddfSDavid du Colombier 				}else
53680ee5cbfSDavid du Colombier 					wsetcursor(winput, 0);
5377dd7cddfSDavid du Colombier 				tmp = mousectl->Mouse;
5387dd7cddfSDavid du Colombier 				tmp.xy = xy;
53980ee5cbfSDavid du Colombier 				send(winput->mc.c, &tmp);
5407dd7cddfSDavid du Colombier 				continue;
5417dd7cddfSDavid du Colombier 			}
5427dd7cddfSDavid du Colombier 			w = wpointto(mouse->xy);
5437dd7cddfSDavid du Colombier 			/* change cursor if over anyone's border */
5447dd7cddfSDavid du Colombier 			if(w != nil)
5457dd7cddfSDavid du Colombier 				cornercursor(w, mouse->xy, 0);
5467dd7cddfSDavid du Colombier 			else
5477dd7cddfSDavid du Colombier 				riosetcursor(nil, 0);
5487dd7cddfSDavid du Colombier 			if(moving && (mouse->buttons&7)){
54980ee5cbfSDavid du Colombier 				oin = winput;
5507dd7cddfSDavid du Colombier 				band = mouse->buttons & 3;
5517dd7cddfSDavid du Colombier 				sweeping = 1;
5527dd7cddfSDavid du Colombier 				if(band)
55380ee5cbfSDavid du Colombier 					i = bandsize(winput);
5547dd7cddfSDavid du Colombier 				else
55580ee5cbfSDavid du Colombier 					i = drag(winput, &r);
5567dd7cddfSDavid du Colombier 				sweeping = 0;
5577dd7cddfSDavid du Colombier 				if(i != nil){
55880ee5cbfSDavid du Colombier 					if(winput == oin){
5597dd7cddfSDavid du Colombier 						if(band)
56080ee5cbfSDavid du Colombier 							wsendctlmesg(winput, Reshaped, i->r, i);
5617dd7cddfSDavid du Colombier 						else
56280ee5cbfSDavid du Colombier 							wsendctlmesg(winput, Moved, r, i);
56380ee5cbfSDavid du Colombier 						cornercursor(winput, mouse->xy, 1);
5647dd7cddfSDavid du Colombier 					}else
5657dd7cddfSDavid du Colombier 						freeimage(i);
5667dd7cddfSDavid du Colombier 				}
5677dd7cddfSDavid du Colombier 			}
5687dd7cddfSDavid du Colombier 			if(w != nil)
5697dd7cddfSDavid du Colombier 				cornercursor(w, mouse->xy, 0);
5707dd7cddfSDavid du Colombier 			/* we're not sending the event, but if button is down maybe we should */
5717dd7cddfSDavid du Colombier 			if(mouse->buttons){
57276f6a3b8SDavid du Colombier 				/* w->topped will be zero or less if window has been bottomed */
57380ee5cbfSDavid du Colombier 				if(w==nil || (w==winput && w->topped>0)){
5749a747e4fSDavid du Colombier 					if(mouse->buttons & 1){
5757dd7cddfSDavid du Colombier 						;
5769a747e4fSDavid du Colombier 					}else if(mouse->buttons & 2){
57780ee5cbfSDavid du Colombier 						if(winput && !winput->mouseopen)
57880ee5cbfSDavid du Colombier 							button2menu(winput);
5797dd7cddfSDavid du Colombier 					}else if(mouse->buttons & 4)
5807dd7cddfSDavid du Colombier 						button3menu();
5817dd7cddfSDavid du Colombier 				}else{
5827dd7cddfSDavid du Colombier 					/* if button 1 event in the window, top the window and wait for button up. */
5837dd7cddfSDavid du Colombier 					/* otherwise, top the window and pass the event on */
5847dd7cddfSDavid du Colombier 					if(wtop(mouse->xy) && (mouse->buttons!=1 || winborder(w, mouse->xy)))
5857dd7cddfSDavid du Colombier 						goto Again;
5867dd7cddfSDavid du Colombier 					goto Drain;
5877dd7cddfSDavid du Colombier 				}
5887dd7cddfSDavid du Colombier 			}
5897dd7cddfSDavid du Colombier 			moving = FALSE;
5907dd7cddfSDavid du Colombier 			break;
5917dd7cddfSDavid du Colombier 
5927dd7cddfSDavid du Colombier 		Drain:
5937dd7cddfSDavid du Colombier 			do
5947dd7cddfSDavid du Colombier 				readmouse(mousectl);
5957dd7cddfSDavid du Colombier 			while(mousectl->buttons);
5967dd7cddfSDavid du Colombier 			moving = FALSE;
5977dd7cddfSDavid du Colombier 			goto Again;	/* recalculate mouse position, cursor */
5987dd7cddfSDavid du Colombier 		}
5997dd7cddfSDavid du Colombier }
6007dd7cddfSDavid du Colombier 
6017dd7cddfSDavid du Colombier void
resized(void)6027dd7cddfSDavid du Colombier resized(void)
6037dd7cddfSDavid du Colombier {
6047dd7cddfSDavid du Colombier 	Image *im;
6057dd7cddfSDavid du Colombier 	int i, j, ishidden;
6067dd7cddfSDavid du Colombier 	Rectangle r;
6077dd7cddfSDavid du Colombier 	Point o, n;
6087dd7cddfSDavid du Colombier 	Window *w;
6097dd7cddfSDavid du Colombier 
6107dd7cddfSDavid du Colombier 	if(getwindow(display, Refnone) < 0)
6117dd7cddfSDavid du Colombier 		error("failed to re-attach window");
61259cc4ca5SDavid du Colombier 	freescrtemps();
6137dd7cddfSDavid du Colombier 	view = screen;
6147dd7cddfSDavid du Colombier 	freescreen(wscreen);
6157dd7cddfSDavid du Colombier 	wscreen = allocscreen(screen, background, 0);
6167dd7cddfSDavid du Colombier 	if(wscreen == nil)
6177dd7cddfSDavid du Colombier 		error("can't re-allocate screen");
6187dd7cddfSDavid du Colombier 	draw(view, view->r, background, nil, ZP);
6197dd7cddfSDavid du Colombier 	o = subpt(viewr.max, viewr.min);
6207dd7cddfSDavid du Colombier 	n = subpt(view->clipr.max, view->clipr.min);
6217dd7cddfSDavid du Colombier 	for(i=0; i<nwindow; i++){
6227dd7cddfSDavid du Colombier 		w = window[i];
6237dd7cddfSDavid du Colombier 		if(w->deleted)
6247dd7cddfSDavid du Colombier 			continue;
6257dd7cddfSDavid du Colombier 		r = rectsubpt(w->i->r, viewr.min);
6267dd7cddfSDavid du Colombier 		r.min.x = (r.min.x*n.x)/o.x;
6277dd7cddfSDavid du Colombier 		r.min.y = (r.min.y*n.y)/o.y;
6287dd7cddfSDavid du Colombier 		r.max.x = (r.max.x*n.x)/o.x;
6297dd7cddfSDavid du Colombier 		r.max.y = (r.max.y*n.y)/o.y;
6307dd7cddfSDavid du Colombier 		r = rectaddpt(r, screen->clipr.min);
6317dd7cddfSDavid du Colombier 		ishidden = 0;
6327dd7cddfSDavid du Colombier 		for(j=0; j<nhidden; j++)
6337dd7cddfSDavid du Colombier 			if(w == hidden[j]){
6347dd7cddfSDavid du Colombier 				ishidden = 1;
6357dd7cddfSDavid du Colombier 				break;
6367dd7cddfSDavid du Colombier 			}
637*666b04c8SDavid du Colombier 		if(ishidden){
6389a747e4fSDavid du Colombier 			im = allocimage(display, r, screen->chan, 0, DWhite);
639*666b04c8SDavid du Colombier 			r = ZR;
640*666b04c8SDavid du Colombier 		}else
6417dd7cddfSDavid du Colombier 			im = allocwindow(wscreen, r, Refbackup, DWhite);
6427dd7cddfSDavid du Colombier 		if(im)
6437dd7cddfSDavid du Colombier 			wsendctlmesg(w, Reshaped, r, im);
6447dd7cddfSDavid du Colombier 	}
6457dd7cddfSDavid du Colombier 	viewr = screen->r;
646e862f8a5SDavid du Colombier 	flushimage(display, 1);
647e862f8a5SDavid du Colombier }
6487dd7cddfSDavid du Colombier 
6497dd7cddfSDavid du Colombier void
button3menu(void)6507dd7cddfSDavid du Colombier button3menu(void)
6517dd7cddfSDavid du Colombier {
6527dd7cddfSDavid du Colombier 	int i;
6537dd7cddfSDavid du Colombier 
6547dd7cddfSDavid du Colombier 	for(i=0; i<nhidden; i++)
6557dd7cddfSDavid du Colombier 		menu3str[i+Hidden] = hidden[i]->label;
6567dd7cddfSDavid du Colombier 	menu3str[i+Hidden] = nil;
6577dd7cddfSDavid du Colombier 
6587dd7cddfSDavid du Colombier 	sweeping = 1;
6597dd7cddfSDavid du Colombier 	switch(i = menuhit(3, mousectl, &menu3, wscreen)){
6607dd7cddfSDavid du Colombier 	case -1:
6617dd7cddfSDavid du Colombier 		break;
6627dd7cddfSDavid du Colombier 	case New:
6633ff48bf5SDavid du Colombier 		new(sweep(), FALSE, scrolling, 0, nil, "/bin/rc", nil);
6647dd7cddfSDavid du Colombier 		break;
6657dd7cddfSDavid du Colombier 	case Reshape:
6667dd7cddfSDavid du Colombier 		resize();
6677dd7cddfSDavid du Colombier 		break;
6687dd7cddfSDavid du Colombier 	case Move:
6697dd7cddfSDavid du Colombier 		move();
6707dd7cddfSDavid du Colombier 		break;
6717dd7cddfSDavid du Colombier 	case Delete:
6727dd7cddfSDavid du Colombier 		delete();
6737dd7cddfSDavid du Colombier 		break;
6747dd7cddfSDavid du Colombier 	case Hide:
6757dd7cddfSDavid du Colombier 		hide();
6767dd7cddfSDavid du Colombier 		break;
6777dd7cddfSDavid du Colombier 	case Exit:
6787dd7cddfSDavid du Colombier 		if(Hidden > Exit){
6797dd7cddfSDavid du Colombier 			send(exitchan, nil);
6807dd7cddfSDavid du Colombier 			break;
6817dd7cddfSDavid du Colombier 		}
6827dd7cddfSDavid du Colombier 		/* else fall through */
6837dd7cddfSDavid du Colombier 	default:
6847dd7cddfSDavid du Colombier 		unhide(i);
6857dd7cddfSDavid du Colombier 		break;
6867dd7cddfSDavid du Colombier 	}
6877dd7cddfSDavid du Colombier 	sweeping = 0;
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier void
button2menu(Window * w)6917dd7cddfSDavid du Colombier button2menu(Window *w)
6927dd7cddfSDavid du Colombier {
6937dd7cddfSDavid du Colombier 	if(w->deleted)
6947dd7cddfSDavid du Colombier 		return;
6957dd7cddfSDavid du Colombier 	incref(w);
6967dd7cddfSDavid du Colombier 	if(w->scrolling)
6977dd7cddfSDavid du Colombier 		menu2str[Scroll] = "noscroll";
6987dd7cddfSDavid du Colombier 	else
6997dd7cddfSDavid du Colombier 		menu2str[Scroll] = "scroll";
7007dd7cddfSDavid du Colombier 	switch(menuhit(2, mousectl, &menu2, wscreen)){
7017dd7cddfSDavid du Colombier 	case Cut:
7027dd7cddfSDavid du Colombier 		wsnarf(w);
7037dd7cddfSDavid du Colombier 		wcut(w);
7047dd7cddfSDavid du Colombier 		wscrdraw(w);
7057dd7cddfSDavid du Colombier 		break;
7067dd7cddfSDavid du Colombier 
7077dd7cddfSDavid du Colombier 	case Snarf:
7087dd7cddfSDavid du Colombier 		wsnarf(w);
7097dd7cddfSDavid du Colombier 		break;
7107dd7cddfSDavid du Colombier 
7117dd7cddfSDavid du Colombier 	case Paste:
7127dd7cddfSDavid du Colombier 		getsnarf();
7137dd7cddfSDavid du Colombier 		wpaste(w);
7147dd7cddfSDavid du Colombier 		wscrdraw(w);
7157dd7cddfSDavid du Colombier 		break;
7167dd7cddfSDavid du Colombier 
7177dd7cddfSDavid du Colombier 	case Plumb:
7187dd7cddfSDavid du Colombier 		wplumb(w);
7197dd7cddfSDavid du Colombier 		break;
7207dd7cddfSDavid du Colombier 
7217dd7cddfSDavid du Colombier 	case Send:
7227dd7cddfSDavid du Colombier 		getsnarf();
7237dd7cddfSDavid du Colombier 		wsnarf(w);
7247dd7cddfSDavid du Colombier 		if(nsnarf == 0)
7257dd7cddfSDavid du Colombier 			break;
7267dd7cddfSDavid du Colombier 		if(w->rawing){
7277dd7cddfSDavid du Colombier 			waddraw(w, snarf, nsnarf);
72859cc4ca5SDavid du Colombier 			if(snarf[nsnarf-1]!='\n' && snarf[nsnarf-1]!='\004')
7297dd7cddfSDavid du Colombier 				waddraw(w, L"\n", 1);
7307dd7cddfSDavid du Colombier 		}else{
7317dd7cddfSDavid du Colombier 			winsert(w, snarf, nsnarf, w->nr);
73259cc4ca5SDavid du Colombier 			if(snarf[nsnarf-1]!='\n' && snarf[nsnarf-1]!='\004')
7337dd7cddfSDavid du Colombier 				winsert(w, L"\n", 1, w->nr);
7347dd7cddfSDavid du Colombier 		}
7357dd7cddfSDavid du Colombier 		wsetselect(w, w->nr, w->nr);
7367dd7cddfSDavid du Colombier 		wshow(w, w->nr);
7377dd7cddfSDavid du Colombier 		break;
7387dd7cddfSDavid du Colombier 
7397dd7cddfSDavid du Colombier 	case Scroll:
7407dd7cddfSDavid du Colombier 		if(w->scrolling ^= 1)
7417dd7cddfSDavid du Colombier 			wshow(w, w->nr);
7427dd7cddfSDavid du Colombier 		break;
7437dd7cddfSDavid du Colombier 	}
7447dd7cddfSDavid du Colombier 	wclose(w);
7457dd7cddfSDavid du Colombier 	wsendctlmesg(w, Wakeup, ZR, nil);
7467dd7cddfSDavid du Colombier 	flushimage(display, 1);
7477dd7cddfSDavid du Colombier }
7487dd7cddfSDavid du Colombier 
7497dd7cddfSDavid du Colombier Point
onscreen(Point p)7507dd7cddfSDavid du Colombier onscreen(Point p)
7517dd7cddfSDavid du Colombier {
7527dd7cddfSDavid du Colombier 	p.x = max(screen->clipr.min.x, p.x);
7537dd7cddfSDavid du Colombier 	p.x = min(screen->clipr.max.x, p.x);
7547dd7cddfSDavid du Colombier 	p.y = max(screen->clipr.min.y, p.y);
7557dd7cddfSDavid du Colombier 	p.y = min(screen->clipr.max.y, p.y);
7567dd7cddfSDavid du Colombier 	return p;
7577dd7cddfSDavid du Colombier }
7587dd7cddfSDavid du Colombier 
7597dd7cddfSDavid du Colombier Image*
sweep(void)7607dd7cddfSDavid du Colombier sweep(void)
7617dd7cddfSDavid du Colombier {
7627dd7cddfSDavid du Colombier 	Image *i, *oi;
7637dd7cddfSDavid du Colombier 	Rectangle r;
7647dd7cddfSDavid du Colombier 	Point p0, p;
7657dd7cddfSDavid du Colombier 
7667dd7cddfSDavid du Colombier 	i = nil;
76759cc4ca5SDavid du Colombier 	menuing = TRUE;
7687dd7cddfSDavid du Colombier 	riosetcursor(&crosscursor, 1);
7697dd7cddfSDavid du Colombier 	while(mouse->buttons == 0)
7707dd7cddfSDavid du Colombier 		readmouse(mousectl);
7717dd7cddfSDavid du Colombier 	p0 = onscreen(mouse->xy);
7727dd7cddfSDavid du Colombier 	p = p0;
7737dd7cddfSDavid du Colombier 	r.min = p;
7747dd7cddfSDavid du Colombier 	r.max = p;
7757dd7cddfSDavid du Colombier 	oi = nil;
7767dd7cddfSDavid du Colombier 	while(mouse->buttons == 4){
7777dd7cddfSDavid du Colombier 		readmouse(mousectl);
7787dd7cddfSDavid du Colombier 		if(mouse->buttons != 4 && mouse->buttons != 0)
7797dd7cddfSDavid du Colombier 			break;
7807dd7cddfSDavid du Colombier 		if(!eqpt(mouse->xy, p)){
7817dd7cddfSDavid du Colombier 			p = onscreen(mouse->xy);
7827dd7cddfSDavid du Colombier 			r = canonrect(Rpt(p0, p));
7837dd7cddfSDavid du Colombier 			if(Dx(r)>5 && Dy(r)>5){
7847dd7cddfSDavid du Colombier 				i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */
7857dd7cddfSDavid du Colombier 				freeimage(oi);
7867dd7cddfSDavid du Colombier 				if(i == nil)
7877dd7cddfSDavid du Colombier 					goto Rescue;
7887dd7cddfSDavid du Colombier 				oi = i;
7897dd7cddfSDavid du Colombier 				border(i, r, Selborder, red, ZP);
7907dd7cddfSDavid du Colombier 				flushimage(display, 1);
7917dd7cddfSDavid du Colombier 			}
7927dd7cddfSDavid du Colombier 		}
7937dd7cddfSDavid du Colombier 	}
7947dd7cddfSDavid du Colombier 	if(mouse->buttons != 0)
7957dd7cddfSDavid du Colombier 		goto Rescue;
7967dd7cddfSDavid du Colombier 	if(i==nil || Dx(i->r)<100 || Dy(i->r)<3*font->height)
7977dd7cddfSDavid du Colombier 		goto Rescue;
7987dd7cddfSDavid du Colombier 	oi = i;
7997dd7cddfSDavid du Colombier 	i = allocwindow(wscreen, oi->r, Refbackup, DWhite);
8007dd7cddfSDavid du Colombier 	freeimage(oi);
8017dd7cddfSDavid du Colombier 	if(i == nil)
8027dd7cddfSDavid du Colombier 		goto Rescue;
8037dd7cddfSDavid du Colombier 	border(i, r, Selborder, red, ZP);
8047dd7cddfSDavid du Colombier 	cornercursor(input, mouse->xy, 1);
80559cc4ca5SDavid du Colombier 	goto Return;
8067dd7cddfSDavid du Colombier 
8077dd7cddfSDavid du Colombier  Rescue:
8087dd7cddfSDavid du Colombier 	freeimage(i);
80959cc4ca5SDavid du Colombier 	i = nil;
8107dd7cddfSDavid du Colombier 	cornercursor(input, mouse->xy, 1);
8117dd7cddfSDavid du Colombier 	while(mouse->buttons)
8127dd7cddfSDavid du Colombier 		readmouse(mousectl);
81359cc4ca5SDavid du Colombier 
81459cc4ca5SDavid du Colombier  Return:
81559cc4ca5SDavid du Colombier 	moveto(mousectl, mouse->xy);	/* force cursor update; ugly */
81659cc4ca5SDavid du Colombier 	menuing = FALSE;
81759cc4ca5SDavid du Colombier 	return i;
8187dd7cddfSDavid du Colombier }
8197dd7cddfSDavid du Colombier 
82015b88db3SDavid du Colombier void
drawedge(Image ** bp,Rectangle r)82115b88db3SDavid du Colombier drawedge(Image **bp, Rectangle r)
82215b88db3SDavid du Colombier {
82315b88db3SDavid du Colombier 	Image *b = *bp;
82415b88db3SDavid du Colombier 	if(b != nil && Dx(b->r) == Dx(r) && Dy(b->r) == Dy(r))
82515b88db3SDavid du Colombier 		originwindow(b, r.min, r.min);
82615b88db3SDavid du Colombier 	else{
82715b88db3SDavid du Colombier 		freeimage(b);
82815b88db3SDavid du Colombier 		*bp = allocwindow(wscreen, r, Refbackup, DRed);
82915b88db3SDavid du Colombier 	}
83015b88db3SDavid du Colombier }
83115b88db3SDavid du Colombier 
83215b88db3SDavid du Colombier void
drawborder(Rectangle r,int show)83315b88db3SDavid du Colombier drawborder(Rectangle r, int show)
83415b88db3SDavid du Colombier {
83515b88db3SDavid du Colombier 	static Image *b[4];
83615b88db3SDavid du Colombier 	int i;
83715b88db3SDavid du Colombier 	if(show == 0){
83815b88db3SDavid du Colombier 		for(i = 0; i < 4; i++){
83915b88db3SDavid du Colombier 			freeimage(b[i]);
84015b88db3SDavid du Colombier 			b[i] = nil;
84115b88db3SDavid du Colombier 		}
84215b88db3SDavid du Colombier 	}else{
84315b88db3SDavid du Colombier 		r = canonrect(r);
84415b88db3SDavid du Colombier 		drawedge(&b[0], Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
84515b88db3SDavid du Colombier 		drawedge(&b[1], Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
84615b88db3SDavid du Colombier 		drawedge(&b[2], Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
84715b88db3SDavid du Colombier 		drawedge(&b[3], Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
84815b88db3SDavid du Colombier 	}
84915b88db3SDavid du Colombier }
85015b88db3SDavid du Colombier 
8517dd7cddfSDavid du Colombier Image*
drag(Window * w,Rectangle * rp)8527dd7cddfSDavid du Colombier drag(Window *w, Rectangle *rp)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier 	Image *i, *ni;
8557dd7cddfSDavid du Colombier 	Point p, op, d, dm, om;
8567dd7cddfSDavid du Colombier 	Rectangle r;
8577dd7cddfSDavid du Colombier 
8587dd7cddfSDavid du Colombier 	i = w->i;
85959cc4ca5SDavid du Colombier 	menuing = TRUE;
8607dd7cddfSDavid du Colombier 	om = mouse->xy;
8617dd7cddfSDavid du Colombier 	riosetcursor(&boxcursor, 1);
8627dd7cddfSDavid du Colombier 	dm = subpt(mouse->xy, w->screenr.min);
8637dd7cddfSDavid du Colombier 	d = subpt(i->r.max, i->r.min);
8647dd7cddfSDavid du Colombier 	op = subpt(mouse->xy, dm);
86515b88db3SDavid du Colombier 	drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1);
8667dd7cddfSDavid du Colombier 	flushimage(display, 1);
8677dd7cddfSDavid du Colombier 	while(mouse->buttons == 4){
8687dd7cddfSDavid du Colombier 		p = subpt(mouse->xy, dm);
8697dd7cddfSDavid du Colombier 		if(!eqpt(p, op)){
87015b88db3SDavid du Colombier 			drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1);
8717dd7cddfSDavid du Colombier 			flushimage(display, 1);
8727dd7cddfSDavid du Colombier 			op = p;
8737dd7cddfSDavid du Colombier 		}
8747dd7cddfSDavid du Colombier 		readmouse(mousectl);
8757dd7cddfSDavid du Colombier 	}
8767dd7cddfSDavid du Colombier 	r = Rect(op.x, op.y, op.x+d.x, op.y+d.y);
87715b88db3SDavid du Colombier 	drawborder(r, 0);
87880ee5cbfSDavid du Colombier 	cornercursor(w, mouse->xy, 1);
87959cc4ca5SDavid du Colombier 	moveto(mousectl, mouse->xy);	/* force cursor update; ugly */
88059cc4ca5SDavid du Colombier 	menuing = FALSE;
8817dd7cddfSDavid du Colombier 	flushimage(display, 1);
8827dd7cddfSDavid du Colombier 	if(mouse->buttons!=0 || (ni=allocwindow(wscreen, r, Refbackup, DWhite))==nil){
8837dd7cddfSDavid du Colombier 		moveto(mousectl, om);
8847dd7cddfSDavid du Colombier 		while(mouse->buttons)
8857dd7cddfSDavid du Colombier 			readmouse(mousectl);
8867dd7cddfSDavid du Colombier 		*rp = Rect(0, 0, 0, 0);
8877dd7cddfSDavid du Colombier 		return nil;
8887dd7cddfSDavid du Colombier 	}
8897dd7cddfSDavid du Colombier 	draw(ni, ni->r, i, nil, i->r.min);
8907dd7cddfSDavid du Colombier 	*rp = r;
8917dd7cddfSDavid du Colombier 	return ni;
8927dd7cddfSDavid du Colombier }
8937dd7cddfSDavid du Colombier 
894ea15f0ccSDavid du Colombier Point
cornerpt(Rectangle r,Point p,int which)895ea15f0ccSDavid du Colombier cornerpt(Rectangle r, Point p, int which)
896ea15f0ccSDavid du Colombier {
897ea15f0ccSDavid du Colombier 	switch(which){
898ea15f0ccSDavid du Colombier 	case 0:	/* top left */
899ea15f0ccSDavid du Colombier 		p = Pt(r.min.x, r.min.y);
900ea15f0ccSDavid du Colombier 		break;
901ea15f0ccSDavid du Colombier 	case 2:	/* top right */
902ea15f0ccSDavid du Colombier 		p = Pt(r.max.x,r.min.y);
903ea15f0ccSDavid du Colombier 		break;
904ea15f0ccSDavid du Colombier 	case 6:	/* bottom left */
905ea15f0ccSDavid du Colombier 		p = Pt(r.min.x, r.max.y);
906ea15f0ccSDavid du Colombier 		break;
907ea15f0ccSDavid du Colombier 	case 8:	/* bottom right */
908ea15f0ccSDavid du Colombier 		p = Pt(r.max.x, r.max.y);
909ea15f0ccSDavid du Colombier 		break;
910ea15f0ccSDavid du Colombier 	case 1:	/* top edge */
911ea15f0ccSDavid du Colombier 		p = Pt(p.x,r.min.y);
912ea15f0ccSDavid du Colombier 		break;
913ea15f0ccSDavid du Colombier 	case 5:	/* right edge */
914ea15f0ccSDavid du Colombier 		p = Pt(r.max.x, p.y);
915ea15f0ccSDavid du Colombier 		break;
916ea15f0ccSDavid du Colombier 	case 7:	/* bottom edge */
917ea15f0ccSDavid du Colombier 		p = Pt(p.x, r.max.y);
918ea15f0ccSDavid du Colombier 		break;
919ea15f0ccSDavid du Colombier 	case 3:		/* left edge */
920ea15f0ccSDavid du Colombier 		p = Pt(r.min.x, p.y);
921ea15f0ccSDavid du Colombier 		break;
922ea15f0ccSDavid du Colombier 	}
923ea15f0ccSDavid du Colombier 	return p;
924ea15f0ccSDavid du Colombier }
925ea15f0ccSDavid du Colombier 
9267dd7cddfSDavid du Colombier Rectangle
whichrect(Rectangle r,Point p,int which)9277dd7cddfSDavid du Colombier whichrect(Rectangle r, Point p, int which)
9287dd7cddfSDavid du Colombier {
9297dd7cddfSDavid du Colombier 	switch(which){
9307dd7cddfSDavid du Colombier 	case 0:	/* top left */
9317dd7cddfSDavid du Colombier 		r = Rect(p.x, p.y, r.max.x, r.max.y);
9327dd7cddfSDavid du Colombier 		break;
9337dd7cddfSDavid du Colombier 	case 2:	/* top right */
9347dd7cddfSDavid du Colombier 		r = Rect(r.min.x, p.y, p.x, r.max.y);
9357dd7cddfSDavid du Colombier 		break;
9367dd7cddfSDavid du Colombier 	case 6:	/* bottom left */
9377dd7cddfSDavid du Colombier 		r = Rect(p.x, r.min.y, r.max.x, p.y);
9387dd7cddfSDavid du Colombier 		break;
9397dd7cddfSDavid du Colombier 	case 8:	/* bottom right */
9407dd7cddfSDavid du Colombier 		r = Rect(r.min.x, r.min.y, p.x, p.y);
9417dd7cddfSDavid du Colombier 		break;
9427dd7cddfSDavid du Colombier 	case 1:	/* top edge */
9437dd7cddfSDavid du Colombier 		r = Rect(r.min.x, p.y, r.max.x, r.max.y);
9447dd7cddfSDavid du Colombier 		break;
9457dd7cddfSDavid du Colombier 	case 5:	/* right edge */
9467dd7cddfSDavid du Colombier 		r = Rect(r.min.x, r.min.y, p.x, r.max.y);
9477dd7cddfSDavid du Colombier 		break;
9487dd7cddfSDavid du Colombier 	case 7:	/* bottom edge */
9497dd7cddfSDavid du Colombier 		r = Rect(r.min.x, r.min.y, r.max.x, p.y);
9507dd7cddfSDavid du Colombier 		break;
9517dd7cddfSDavid du Colombier 	case 3:		/* left edge */
9527dd7cddfSDavid du Colombier 		r = Rect(p.x, r.min.y, r.max.x, r.max.y);
9537dd7cddfSDavid du Colombier 		break;
9547dd7cddfSDavid du Colombier 	}
9557dd7cddfSDavid du Colombier 	return canonrect(r);
9567dd7cddfSDavid du Colombier }
9577dd7cddfSDavid du Colombier 
9587dd7cddfSDavid du Colombier Image*
bandsize(Window * w)9597dd7cddfSDavid du Colombier bandsize(Window *w)
9607dd7cddfSDavid du Colombier {
9617dd7cddfSDavid du Colombier 	Image *i;
9627dd7cddfSDavid du Colombier 	Rectangle r, or;
9637dd7cddfSDavid du Colombier 	Point p, startp;
9647dd7cddfSDavid du Colombier 	int which, but;
9657dd7cddfSDavid du Colombier 
9667dd7cddfSDavid du Colombier 	p = mouse->xy;
967314a20f0SDavid du Colombier 	but = mouse->buttons;
9687dd7cddfSDavid du Colombier 	which = whichcorner(w, p);
96950e5f38dSDavid du Colombier 	p = cornerpt(w->screenr, p, which);
97050e5f38dSDavid du Colombier 	wmovemouse(w, p);
971ea15f0ccSDavid du Colombier 	readmouse(mousectl);
9727dd7cddfSDavid du Colombier 	r = whichrect(w->screenr, p, which);
97315b88db3SDavid du Colombier 	drawborder(r, 1);
9747dd7cddfSDavid du Colombier 	or = r;
97550e5f38dSDavid du Colombier 	startp = p;
976314a20f0SDavid du Colombier 
9777dd7cddfSDavid du Colombier 	while(mouse->buttons == but){
9787dd7cddfSDavid du Colombier 		p = onscreen(mouse->xy);
9797dd7cddfSDavid du Colombier 		r = whichrect(w->screenr, p, which);
98059cc4ca5SDavid du Colombier 		if(!eqrect(r, or) && goodrect(r)){
98115b88db3SDavid du Colombier 			drawborder(r, 1);
9827dd7cddfSDavid du Colombier 			flushimage(display, 1);
9837dd7cddfSDavid du Colombier 			or = r;
9847dd7cddfSDavid du Colombier 		}
9857dd7cddfSDavid du Colombier 		readmouse(mousectl);
9867dd7cddfSDavid du Colombier 	}
9877dd7cddfSDavid du Colombier 	p = mouse->xy;
98815b88db3SDavid du Colombier 	drawborder(or, 0);
9897dd7cddfSDavid du Colombier 	flushimage(display, 1);
99080ee5cbfSDavid du Colombier 	wsetcursor(w, 1);
9917dd7cddfSDavid du Colombier 	if(mouse->buttons!=0 || Dx(or)<100 || Dy(or)<3*font->height){
9927dd7cddfSDavid du Colombier 		while(mouse->buttons)
9937dd7cddfSDavid du Colombier 			readmouse(mousectl);
9947dd7cddfSDavid du Colombier 		return nil;
9957dd7cddfSDavid du Colombier 	}
9967dd7cddfSDavid du Colombier 	if(abs(p.x-startp.x)+abs(p.y-startp.y) <= 1)
9977dd7cddfSDavid du Colombier 		return nil;
9987dd7cddfSDavid du Colombier 	i = allocwindow(wscreen, or, Refbackup, DWhite);
9997dd7cddfSDavid du Colombier 	if(i == nil)
10007dd7cddfSDavid du Colombier 		return nil;
10017dd7cddfSDavid du Colombier 	border(i, r, Selborder, red, ZP);
10027dd7cddfSDavid du Colombier 	return i;
10037dd7cddfSDavid du Colombier }
10047dd7cddfSDavid du Colombier 
10057dd7cddfSDavid du Colombier Window*
pointto(int wait)10067dd7cddfSDavid du Colombier pointto(int wait)
10077dd7cddfSDavid du Colombier {
10087dd7cddfSDavid du Colombier 	Window *w;
10097dd7cddfSDavid du Colombier 
101059cc4ca5SDavid du Colombier 	menuing = TRUE;
10117dd7cddfSDavid du Colombier 	riosetcursor(&sightcursor, 1);
10127dd7cddfSDavid du Colombier 	while(mouse->buttons == 0)
10137dd7cddfSDavid du Colombier 		readmouse(mousectl);
10147dd7cddfSDavid du Colombier 	if(mouse->buttons == 4)
10157dd7cddfSDavid du Colombier 		w = wpointto(mouse->xy);
10167dd7cddfSDavid du Colombier 	else
10177dd7cddfSDavid du Colombier 		w = nil;
101861e02cf5SDavid du Colombier 	if(wait){
101914414594SDavid du Colombier 		while(mouse->buttons){
102014414594SDavid du Colombier 			if(mouse->buttons!=4 && w !=nil){	/* cancel */
102114414594SDavid du Colombier 				cornercursor(input, mouse->xy, 0);
102214414594SDavid du Colombier 				w = nil;
102314414594SDavid du Colombier 			}
10247dd7cddfSDavid du Colombier 			readmouse(mousectl);
102514414594SDavid du Colombier 		}
102661e02cf5SDavid du Colombier 		if(w != nil && wpointto(mouse->xy) != w)
102761e02cf5SDavid du Colombier 			w = nil;
102861e02cf5SDavid du Colombier 	}
10297dd7cddfSDavid du Colombier 	cornercursor(input, mouse->xy, 0);
103059cc4ca5SDavid du Colombier 	moveto(mousectl, mouse->xy);	/* force cursor update; ugly */
103159cc4ca5SDavid du Colombier 	menuing = FALSE;
10327dd7cddfSDavid du Colombier 	return w;
10337dd7cddfSDavid du Colombier }
10347dd7cddfSDavid du Colombier 
10357dd7cddfSDavid du Colombier void
delete(void)10367dd7cddfSDavid du Colombier delete(void)
10377dd7cddfSDavid du Colombier {
10387dd7cddfSDavid du Colombier 	Window *w;
10397dd7cddfSDavid du Colombier 
10407dd7cddfSDavid du Colombier 	w = pointto(TRUE);
10417dd7cddfSDavid du Colombier 	if(w)
10427dd7cddfSDavid du Colombier 		wsendctlmesg(w, Deleted, ZR, nil);
10437dd7cddfSDavid du Colombier }
10447dd7cddfSDavid du Colombier 
10457dd7cddfSDavid du Colombier void
resize(void)10467dd7cddfSDavid du Colombier resize(void)
10477dd7cddfSDavid du Colombier {
10487dd7cddfSDavid du Colombier 	Window *w;
10497dd7cddfSDavid du Colombier 	Image *i;
10507dd7cddfSDavid du Colombier 
10517dd7cddfSDavid du Colombier 	w = pointto(TRUE);
10527dd7cddfSDavid du Colombier 	if(w == nil)
10537dd7cddfSDavid du Colombier 		return;
10547dd7cddfSDavid du Colombier 	i = sweep();
10557dd7cddfSDavid du Colombier 	if(i)
10567dd7cddfSDavid du Colombier 		wsendctlmesg(w, Reshaped, i->r, i);
10577dd7cddfSDavid du Colombier }
10587dd7cddfSDavid du Colombier 
10597dd7cddfSDavid du Colombier void
move(void)10607dd7cddfSDavid du Colombier move(void)
10617dd7cddfSDavid du Colombier {
10627dd7cddfSDavid du Colombier 	Window *w;
10637dd7cddfSDavid du Colombier 	Image *i;
10647dd7cddfSDavid du Colombier 	Rectangle r;
10657dd7cddfSDavid du Colombier 
10667dd7cddfSDavid du Colombier 	w = pointto(FALSE);
10677dd7cddfSDavid du Colombier 	if(w == nil)
10687dd7cddfSDavid du Colombier 		return;
10697dd7cddfSDavid du Colombier 	i = drag(w, &r);
10707dd7cddfSDavid du Colombier 	if(i)
10717dd7cddfSDavid du Colombier 		wsendctlmesg(w, Moved, r, i);
10727dd7cddfSDavid du Colombier 	cornercursor(input, mouse->xy, 1);
10737dd7cddfSDavid du Colombier }
10747dd7cddfSDavid du Colombier 
107580ee5cbfSDavid du Colombier int
whide(Window * w)107680ee5cbfSDavid du Colombier whide(Window *w)
10777dd7cddfSDavid du Colombier {
10787dd7cddfSDavid du Colombier 	Image *i;
107980ee5cbfSDavid du Colombier 	int j;
10807dd7cddfSDavid du Colombier 
108180ee5cbfSDavid du Colombier 	for(j=0; j<nhidden; j++)
108280ee5cbfSDavid du Colombier 		if(hidden[j] == w)	/* already hidden */
108380ee5cbfSDavid du Colombier 			return -1;
10847dd7cddfSDavid du Colombier 	i = allocimage(display, w->screenr, w->i->chan, 0, DWhite);
10857dd7cddfSDavid du Colombier 	if(i){
10867dd7cddfSDavid du Colombier 		hidden[nhidden++] = w;
10877dd7cddfSDavid du Colombier 		wsendctlmesg(w, Reshaped, ZR, i);
108880ee5cbfSDavid du Colombier 		return 1;
10897dd7cddfSDavid du Colombier 	}
109080ee5cbfSDavid du Colombier 	return 0;
109180ee5cbfSDavid du Colombier }
109280ee5cbfSDavid du Colombier 
109380ee5cbfSDavid du Colombier int
wunhide(int h)109480ee5cbfSDavid du Colombier wunhide(int h)
109580ee5cbfSDavid du Colombier {
109680ee5cbfSDavid du Colombier 	Image *i;
109780ee5cbfSDavid du Colombier 	Window *w;
109880ee5cbfSDavid du Colombier 
109980ee5cbfSDavid du Colombier 	w = hidden[h];
110080ee5cbfSDavid du Colombier 	i = allocwindow(wscreen, w->i->r, Refbackup, DWhite);
110180ee5cbfSDavid du Colombier 	if(i){
110280ee5cbfSDavid du Colombier 		--nhidden;
110380ee5cbfSDavid du Colombier 		memmove(hidden+h, hidden+h+1, (nhidden-h)*sizeof(Window*));
110480ee5cbfSDavid du Colombier 		wsendctlmesg(w, Reshaped, w->i->r, i);
110580ee5cbfSDavid du Colombier 		return 1;
110680ee5cbfSDavid du Colombier 	}
110780ee5cbfSDavid du Colombier 	return 0;
110880ee5cbfSDavid du Colombier }
110980ee5cbfSDavid du Colombier 
111080ee5cbfSDavid du Colombier void
hide(void)111180ee5cbfSDavid du Colombier hide(void)
111280ee5cbfSDavid du Colombier {
111380ee5cbfSDavid du Colombier 	Window *w;
111480ee5cbfSDavid du Colombier 
111580ee5cbfSDavid du Colombier 	w = pointto(TRUE);
111680ee5cbfSDavid du Colombier 	if(w == nil)
111780ee5cbfSDavid du Colombier 		return;
111880ee5cbfSDavid du Colombier 	whide(w);
11197dd7cddfSDavid du Colombier }
11207dd7cddfSDavid du Colombier 
11217dd7cddfSDavid du Colombier void
unhide(int h)11227dd7cddfSDavid du Colombier unhide(int h)
11237dd7cddfSDavid du Colombier {
11247dd7cddfSDavid du Colombier 	Window *w;
11257dd7cddfSDavid du Colombier 
11267dd7cddfSDavid du Colombier 	h -= Hidden;
11277dd7cddfSDavid du Colombier 	w = hidden[h];
11287dd7cddfSDavid du Colombier 	if(w == nil)
11297dd7cddfSDavid du Colombier 		return;
113080ee5cbfSDavid du Colombier 	wunhide(h);
11317dd7cddfSDavid du Colombier }
11327dd7cddfSDavid du Colombier 
11337dd7cddfSDavid du Colombier Window*
new(Image * i,int hideit,int scrollit,int pid,char * dir,char * cmd,char ** argv)11343ff48bf5SDavid du Colombier new(Image *i, int hideit, int scrollit, int pid, char *dir, char *cmd, char **argv)
11357dd7cddfSDavid du Colombier {
11367dd7cddfSDavid du Colombier 	Window *w;
11377dd7cddfSDavid du Colombier 	Mousectl *mc;
11387dd7cddfSDavid du Colombier 	Channel *cm, *ck, *cctl, *cpid;
11397dd7cddfSDavid du Colombier 	void **arg;
11407dd7cddfSDavid du Colombier 
11417dd7cddfSDavid du Colombier 	if(i == nil)
11427dd7cddfSDavid du Colombier 		return nil;
11437dd7cddfSDavid du Colombier 	cm = chancreate(sizeof(Mouse), 0);
11447dd7cddfSDavid du Colombier 	ck = chancreate(sizeof(Rune*), 0);
11457dd7cddfSDavid du Colombier 	cctl = chancreate(sizeof(Wctlmesg), 4);
11467dd7cddfSDavid du Colombier 	cpid = chancreate(sizeof(int), 0);
11477dd7cddfSDavid du Colombier 	if(cm==nil || ck==nil || cctl==nil)
11487dd7cddfSDavid du Colombier 		error("new: channel alloc failed");
11497dd7cddfSDavid du Colombier 	mc = emalloc(sizeof(Mousectl));
11507dd7cddfSDavid du Colombier 	*mc = *mousectl;
11517dd7cddfSDavid du Colombier 	mc->image = i;
11527dd7cddfSDavid du Colombier 	mc->c = cm;
11533ff48bf5SDavid du Colombier 	w = wmk(i, mc, ck, cctl, scrollit);
115459cc4ca5SDavid du Colombier 	free(mc);	/* wmk copies *mc */
11557dd7cddfSDavid du Colombier 	window = erealloc(window, ++nwindow*sizeof(Window*));
11567dd7cddfSDavid du Colombier 	window[nwindow-1] = w;
11579a747e4fSDavid du Colombier 	if(hideit){
11589a747e4fSDavid du Colombier 		hidden[nhidden++] = w;
11599a747e4fSDavid du Colombier 		w->screenr = ZR;
11609a747e4fSDavid du Colombier 	}
11617dd7cddfSDavid du Colombier 	threadcreate(winctl, w, 8192);
11629a747e4fSDavid du Colombier 	if(!hideit)
11637dd7cddfSDavid du Colombier 		wcurrent(w);
11647dd7cddfSDavid du Colombier 	flushimage(display, 1);
11657dd7cddfSDavid du Colombier 	if(pid == 0){
11667dd7cddfSDavid du Colombier 		arg = emalloc(5*sizeof(void*));
11677dd7cddfSDavid du Colombier 		arg[0] = w;
11687dd7cddfSDavid du Colombier 		arg[1] = cpid;
11697dd7cddfSDavid du Colombier 		arg[2] = cmd;
11707dd7cddfSDavid du Colombier 		if(argv == nil)
11717dd7cddfSDavid du Colombier 			arg[3] = rcargv;
11727dd7cddfSDavid du Colombier 		else
11737dd7cddfSDavid du Colombier 			arg[3] = argv;
11747dd7cddfSDavid du Colombier 		arg[4] = dir;
11757dd7cddfSDavid du Colombier 		proccreate(winshell, arg, 8192);
11767dd7cddfSDavid du Colombier 		pid = recvul(cpid);
11777dd7cddfSDavid du Colombier 		free(arg);
11787dd7cddfSDavid du Colombier 	}
117980ee5cbfSDavid du Colombier 	if(pid == 0){
118080ee5cbfSDavid du Colombier 		/* window creation failed */
118180ee5cbfSDavid du Colombier 		wsendctlmesg(w, Deleted, ZR, nil);
118280ee5cbfSDavid du Colombier 		chanfree(cpid);
118380ee5cbfSDavid du Colombier 		return nil;
118480ee5cbfSDavid du Colombier 	}
11859a747e4fSDavid du Colombier 	wsetpid(w, pid, 1);
11867dd7cddfSDavid du Colombier 	wsetname(w);
1187ce941d97SDavid du Colombier 	if(dir)
1188ce941d97SDavid du Colombier 		w->dir = estrdup(dir);
118959cc4ca5SDavid du Colombier 	chanfree(cpid);
11907dd7cddfSDavid du Colombier 	return w;
11917dd7cddfSDavid du Colombier }
1192