xref: /plan9/sys/src/cmd/rio/wctl.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
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 #include <ctype.h>
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier char	Ebadwr[]		= "bad rectangle in wctl request";
167dd7cddfSDavid du Colombier char	Ewalloc[]		= "window allocation failed in wctl request";
177dd7cddfSDavid du Colombier 
1880ee5cbfSDavid du Colombier /* >= Top are disallowed if mouse button is pressed */
197dd7cddfSDavid du Colombier enum
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier 	New,
227dd7cddfSDavid du Colombier 	Resize,
237dd7cddfSDavid du Colombier 	Move,
2480ee5cbfSDavid du Colombier 	Scroll,
2580ee5cbfSDavid du Colombier 	Noscroll,
269a747e4fSDavid du Colombier 	Set,
277dd7cddfSDavid du Colombier 	Top,
287dd7cddfSDavid du Colombier 	Bottom,
297dd7cddfSDavid du Colombier 	Current,
3080ee5cbfSDavid du Colombier 	Hide,
3180ee5cbfSDavid du Colombier 	Unhide,
3280ee5cbfSDavid du Colombier 	Delete,
337dd7cddfSDavid du Colombier };
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier static char *cmds[] = {
367dd7cddfSDavid du Colombier 	[New]	= "new",
377dd7cddfSDavid du Colombier 	[Resize]	= "resize",
387dd7cddfSDavid du Colombier 	[Move]	= "move",
3980ee5cbfSDavid du Colombier 	[Scroll]	= "scroll",
4080ee5cbfSDavid du Colombier 	[Noscroll]	= "noscroll",
419a747e4fSDavid du Colombier 	[Set]		= "set",
427dd7cddfSDavid du Colombier 	[Top]	= "top",
437dd7cddfSDavid du Colombier 	[Bottom]	= "bottom",
447dd7cddfSDavid du Colombier 	[Current]	= "current",
4580ee5cbfSDavid du Colombier 	[Hide]	= "hide",
4680ee5cbfSDavid du Colombier 	[Unhide]	= "unhide",
4780ee5cbfSDavid du Colombier 	[Delete]	= "delete",
487dd7cddfSDavid du Colombier 	nil
497dd7cddfSDavid du Colombier };
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier enum
527dd7cddfSDavid du Colombier {
537dd7cddfSDavid du Colombier 	Cd,
547dd7cddfSDavid du Colombier 	Deltax,
557dd7cddfSDavid du Colombier 	Deltay,
56*3ff48bf5SDavid du Colombier 	Hidden,
57*3ff48bf5SDavid du Colombier 	Id,
58*3ff48bf5SDavid du Colombier 	Maxx,
59*3ff48bf5SDavid du Colombier 	Maxy,
60*3ff48bf5SDavid du Colombier 	Minx,
61*3ff48bf5SDavid du Colombier 	Miny,
627dd7cddfSDavid du Colombier 	PID,
63*3ff48bf5SDavid du Colombier 	R,
64*3ff48bf5SDavid du Colombier 	Scrolling,
65*3ff48bf5SDavid du Colombier 	Noscrolling,
667dd7cddfSDavid du Colombier };
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier static char *params[] = {
697dd7cddfSDavid du Colombier 	[Cd]	 			= "-cd",
707dd7cddfSDavid du Colombier 	[Deltax]			= "-dx",
717dd7cddfSDavid du Colombier 	[Deltay]			= "-dy",
72*3ff48bf5SDavid du Colombier 	[Hidden]			= "-hide",
73*3ff48bf5SDavid du Colombier 	[Id]				= "-id",
74*3ff48bf5SDavid du Colombier 	[Maxx]			= "-maxx",
75*3ff48bf5SDavid du Colombier 	[Maxy]			= "-maxy",
76*3ff48bf5SDavid du Colombier 	[Minx]			= "-minx",
77*3ff48bf5SDavid du Colombier 	[Miny]			= "-miny",
787dd7cddfSDavid du Colombier 	[PID]				= "-pid",
79*3ff48bf5SDavid du Colombier 	[R]				= "-r",
80*3ff48bf5SDavid du Colombier 	[Scrolling]			= "-scroll",
81*3ff48bf5SDavid du Colombier 	[Noscrolling]		= "-noscroll",
827dd7cddfSDavid du Colombier 	nil
837dd7cddfSDavid du Colombier };
847dd7cddfSDavid du Colombier 
8559cc4ca5SDavid du Colombier /*
8659cc4ca5SDavid du Colombier  * Check that newly created window will be of manageable size
8759cc4ca5SDavid du Colombier  */
887dd7cddfSDavid du Colombier int
goodrect(Rectangle r)897dd7cddfSDavid du Colombier goodrect(Rectangle r)
907dd7cddfSDavid du Colombier {
917dd7cddfSDavid du Colombier 	if(!eqrect(canonrect(r), r))
927dd7cddfSDavid du Colombier 		return 0;
937dd7cddfSDavid du Colombier 	if(Dx(r)<100 || Dy(r)<3*font->height)
947dd7cddfSDavid du Colombier 		return 0;
9559cc4ca5SDavid du Colombier 	/* must have some screen and border visible so we can move it out of the way */
9659cc4ca5SDavid du Colombier 	if(Dx(r) >= Dx(screen->r) && Dy(r) >= Dy(screen->r))
977dd7cddfSDavid du Colombier 		return 0;
9859cc4ca5SDavid du Colombier 	/* reasonable sizes only please */
9959cc4ca5SDavid du Colombier 	if(Dx(r) > BIG*Dx(screen->r))
10059cc4ca5SDavid du Colombier 		return 0;
10159cc4ca5SDavid du Colombier 	if(Dy(r) > BIG*Dx(screen->r))
1027dd7cddfSDavid du Colombier 		return 0;
1037dd7cddfSDavid du Colombier 	return 1;
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier static
1077dd7cddfSDavid du Colombier int
word(char ** sp,char * tab[])1087dd7cddfSDavid du Colombier word(char **sp, char *tab[])
1097dd7cddfSDavid du Colombier {
1107dd7cddfSDavid du Colombier 	char *s, *t;
1117dd7cddfSDavid du Colombier 	int i;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	s = *sp;
1147dd7cddfSDavid du Colombier 	while(isspace(*s))
1157dd7cddfSDavid du Colombier 		s++;
1167dd7cddfSDavid du Colombier 	t = s;
1177dd7cddfSDavid du Colombier 	while(*s!='\0' && !isspace(*s))
1187dd7cddfSDavid du Colombier 		s++;
1197dd7cddfSDavid du Colombier 	for(i=0; tab[i]!=nil; i++)
1207dd7cddfSDavid du Colombier 		if(strncmp(tab[i], t, strlen(tab[i])) == 0){
1217dd7cddfSDavid du Colombier 			*sp = s;
1227dd7cddfSDavid du Colombier 			return i;
1237dd7cddfSDavid du Colombier 	}
1247dd7cddfSDavid du Colombier 	return -1;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier int
set(int sign,int neg,int abs,int pos)1287dd7cddfSDavid du Colombier set(int sign, int neg, int abs, int pos)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 	if(sign < 0)
1317dd7cddfSDavid du Colombier 		return neg;
1327dd7cddfSDavid du Colombier 	if(sign > 0)
1337dd7cddfSDavid du Colombier 		return pos;
1347dd7cddfSDavid du Colombier 	return abs;
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier Rectangle
newrect(void)1387dd7cddfSDavid du Colombier newrect(void)
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier 	static int i = 0;
1417dd7cddfSDavid du Colombier 	int minx, miny, dx, dy;
1427dd7cddfSDavid du Colombier 
14380ee5cbfSDavid du Colombier 	dx = min(600, Dx(screen->r) - 2*Borderwidth);
14480ee5cbfSDavid du Colombier 	dy = min(400, Dy(screen->r) - 2*Borderwidth);
1457dd7cddfSDavid du Colombier 	minx = 32 + 16*i;
1467dd7cddfSDavid du Colombier 	miny = 32 + 16*i;
1477dd7cddfSDavid du Colombier 	i++;
1487dd7cddfSDavid du Colombier 	i %= 10;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	return Rect(minx, miny, minx+dx, miny+dy);
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier void
shift(int * minp,int * maxp,int min,int max)1547dd7cddfSDavid du Colombier shift(int *minp, int *maxp, int min, int max)
1557dd7cddfSDavid du Colombier {
1567dd7cddfSDavid du Colombier 	if(*minp < min){
1577dd7cddfSDavid du Colombier 		*maxp += min-*minp;
1587dd7cddfSDavid du Colombier 		*minp = min;
1597dd7cddfSDavid du Colombier 	}
1607dd7cddfSDavid du Colombier 	if(*maxp > max){
1617dd7cddfSDavid du Colombier 		*minp += max-*maxp;
1627dd7cddfSDavid du Colombier 		*maxp = max;
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier Rectangle
rectonscreen(Rectangle r)1677dd7cddfSDavid du Colombier rectonscreen(Rectangle r)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier 	shift(&r.min.x, &r.max.x, screen->r.min.x, screen->r.max.x);
1707dd7cddfSDavid du Colombier 	shift(&r.min.y, &r.max.y, screen->r.min.y, screen->r.max.y);
1717dd7cddfSDavid du Colombier 	return r;
1727dd7cddfSDavid du Colombier }
1737dd7cddfSDavid du Colombier 
17480ee5cbfSDavid du Colombier /* permit square brackets, in the manner of %R */
1757dd7cddfSDavid du Colombier int
riostrtol(char * s,char ** t)17680ee5cbfSDavid du Colombier riostrtol(char *s, char **t)
17780ee5cbfSDavid du Colombier {
17880ee5cbfSDavid du Colombier 	int n;
17980ee5cbfSDavid du Colombier 
18080ee5cbfSDavid du Colombier 	while(*s!='\0' && (*s==' ' || *s=='\t' || *s=='['))
18180ee5cbfSDavid du Colombier 		s++;
18280ee5cbfSDavid du Colombier 	if(*s == '[')
18380ee5cbfSDavid du Colombier 		s++;
18480ee5cbfSDavid du Colombier 	n = strtol(s, t, 10);
18580ee5cbfSDavid du Colombier 	if(*t != s)
18680ee5cbfSDavid du Colombier 		while((*t)[0] == ']')
18780ee5cbfSDavid du Colombier 			(*t)++;
18880ee5cbfSDavid du Colombier 	return n;
18980ee5cbfSDavid du Colombier }
19080ee5cbfSDavid du Colombier 
19180ee5cbfSDavid du Colombier 
19280ee5cbfSDavid du Colombier int
parsewctl(char ** argp,Rectangle r,Rectangle * rp,int * pidp,int * idp,int * hiddenp,int * scrollingp,char ** cdp,char * s,char * err)193*3ff48bf5SDavid du Colombier parsewctl(char **argp, Rectangle r, Rectangle *rp, int *pidp, int *idp, int *hiddenp, int *scrollingp, char **cdp, char *s, char *err)
1947dd7cddfSDavid du Colombier {
1957dd7cddfSDavid du Colombier 	int cmd, param, xy, sign;
1967dd7cddfSDavid du Colombier 	char *t;
1977dd7cddfSDavid du Colombier 
1989a747e4fSDavid du Colombier 	*pidp = 0;
1999a747e4fSDavid du Colombier 	*hiddenp = 0;
200*3ff48bf5SDavid du Colombier 	*scrollingp = scrolling;
2017dd7cddfSDavid du Colombier 	*cdp = nil;
2027dd7cddfSDavid du Colombier 	cmd = word(&s, cmds);
2037dd7cddfSDavid du Colombier 	if(cmd < 0){
2047dd7cddfSDavid du Colombier 		strcpy(err, "unrecognized wctl command");
2057dd7cddfSDavid du Colombier 		return -1;
2067dd7cddfSDavid du Colombier 	}
2077dd7cddfSDavid du Colombier 	if(cmd == New)
2087dd7cddfSDavid du Colombier 		r = newrect();
2097dd7cddfSDavid du Colombier 
2107dd7cddfSDavid du Colombier 	strcpy(err, "missing or bad wctl parameter");
2117dd7cddfSDavid du Colombier 	while((param = word(&s, params)) >= 0){
212*3ff48bf5SDavid du Colombier 		switch(param){	/* special cases */
213*3ff48bf5SDavid du Colombier 		case Hidden:
2149a747e4fSDavid du Colombier 			*hiddenp = 1;
2159a747e4fSDavid du Colombier 			continue;
216*3ff48bf5SDavid du Colombier 		case Scrolling:
217*3ff48bf5SDavid du Colombier 			*scrollingp = 1;
218*3ff48bf5SDavid du Colombier 			continue;
219*3ff48bf5SDavid du Colombier 		case Noscrolling:
220*3ff48bf5SDavid du Colombier 			*scrollingp = 0;
221*3ff48bf5SDavid du Colombier 			continue;
222*3ff48bf5SDavid du Colombier 		case R:
22380ee5cbfSDavid du Colombier 			r.min.x = riostrtol(s, &t);
2247dd7cddfSDavid du Colombier 			if(t == s)
2257dd7cddfSDavid du Colombier 				return -1;
2267dd7cddfSDavid du Colombier 			s = t;
22780ee5cbfSDavid du Colombier 			r.min.y = riostrtol(s, &t);
2287dd7cddfSDavid du Colombier 			if(t == s)
2297dd7cddfSDavid du Colombier 				return -1;
2307dd7cddfSDavid du Colombier 			s = t;
23180ee5cbfSDavid du Colombier 			r.max.x = riostrtol(s, &t);
2327dd7cddfSDavid du Colombier 			if(t == s)
2337dd7cddfSDavid du Colombier 				return -1;
2347dd7cddfSDavid du Colombier 			s = t;
23580ee5cbfSDavid du Colombier 			r.max.y = riostrtol(s, &t);
2367dd7cddfSDavid du Colombier 			if(t == s)
2377dd7cddfSDavid du Colombier 				return -1;
2387dd7cddfSDavid du Colombier 			s = t;
2397dd7cddfSDavid du Colombier 			continue;
2407dd7cddfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 		while(isspace(*s))
2427dd7cddfSDavid du Colombier 			s++;
2437dd7cddfSDavid du Colombier 		if(param == Cd){
2447dd7cddfSDavid du Colombier 			*cdp = s;
2457dd7cddfSDavid du Colombier 			while(*s && !isspace(*s))
2467dd7cddfSDavid du Colombier 				s++;
2477dd7cddfSDavid du Colombier 			if(*s != '\0')
2487dd7cddfSDavid du Colombier 				*s++ = '\0';
2497dd7cddfSDavid du Colombier 			continue;
2507dd7cddfSDavid du Colombier 		}
2517dd7cddfSDavid du Colombier 		sign = 0;
2527dd7cddfSDavid du Colombier 		if(*s == '-'){
2537dd7cddfSDavid du Colombier 			sign = -1;
2547dd7cddfSDavid du Colombier 			s++;
2557dd7cddfSDavid du Colombier 		}else if(*s == '+'){
2567dd7cddfSDavid du Colombier 			sign = +1;
2577dd7cddfSDavid du Colombier 			s++;
2587dd7cddfSDavid du Colombier 		}
2597dd7cddfSDavid du Colombier 		if(!isdigit(*s))
2607dd7cddfSDavid du Colombier 			return -1;
26180ee5cbfSDavid du Colombier 		xy = riostrtol(s, &s);
2627dd7cddfSDavid du Colombier 		switch(param){
2637dd7cddfSDavid du Colombier 		case -1:
2647dd7cddfSDavid du Colombier 			strcpy(err, "unrecognized wctl parameter");
2657dd7cddfSDavid du Colombier 			return -1;
2667dd7cddfSDavid du Colombier 		case Minx:
2677dd7cddfSDavid du Colombier 			r.min.x = set(sign, r.min.x-xy, xy, r.min.x+xy);
2687dd7cddfSDavid du Colombier 			break;
2697dd7cddfSDavid du Colombier 		case Miny:
2707dd7cddfSDavid du Colombier 			r.min.y = set(sign, r.min.y-xy, xy, r.min.y+xy);
2717dd7cddfSDavid du Colombier 			break;
2727dd7cddfSDavid du Colombier 		case Maxx:
2737dd7cddfSDavid du Colombier 			r.max.x = set(sign, r.max.x-xy, xy, r.max.x+xy);
2747dd7cddfSDavid du Colombier 			break;
2757dd7cddfSDavid du Colombier 		case Maxy:
2767dd7cddfSDavid du Colombier 			r.max.y = set(sign, r.max.y-xy, xy, r.max.y+xy);
2777dd7cddfSDavid du Colombier 			break;
2787dd7cddfSDavid du Colombier 		case Deltax:
2797dd7cddfSDavid du Colombier 			r.max.x = set(sign, r.max.x-xy, r.min.x+xy, r.max.x+xy);
2807dd7cddfSDavid du Colombier 			break;
2817dd7cddfSDavid du Colombier 		case Deltay:
2827dd7cddfSDavid du Colombier 			r.max.y = set(sign, r.max.y-xy, r.min.y+xy, r.max.y+xy);
2837dd7cddfSDavid du Colombier 			break;
28480ee5cbfSDavid du Colombier 		case Id:
28580ee5cbfSDavid du Colombier 			if(idp != nil)
28680ee5cbfSDavid du Colombier 				*idp = xy;
28780ee5cbfSDavid du Colombier 			break;
2887dd7cddfSDavid du Colombier 		case PID:
2897dd7cddfSDavid du Colombier 			if(pidp != nil)
2907dd7cddfSDavid du Colombier 				*pidp = xy;
2917dd7cddfSDavid du Colombier 			break;
2927dd7cddfSDavid du Colombier 		}
2937dd7cddfSDavid du Colombier 	}
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier 	*rp = rectonscreen(rectaddpt(r, screen->r.min));
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	while(isspace(*s))
2987dd7cddfSDavid du Colombier 		s++;
2997dd7cddfSDavid du Colombier 	if(cmd!=New && *s!='\0'){
3007dd7cddfSDavid du Colombier 		strcpy(err, "extraneous text in wctl message");
3017dd7cddfSDavid du Colombier 		return -1;
3027dd7cddfSDavid du Colombier 	}
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier 	if(argp)
3057dd7cddfSDavid du Colombier 		*argp = s;
3067dd7cddfSDavid du Colombier 
3077dd7cddfSDavid du Colombier 	return cmd;
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier int
wctlnew(Rectangle rect,char * arg,int pid,int hideit,int scrollit,char * dir,char * err)311*3ff48bf5SDavid du Colombier wctlnew(Rectangle rect, char *arg, int pid, int hideit, int scrollit, char *dir, char *err)
3127dd7cddfSDavid du Colombier {
3137dd7cddfSDavid du Colombier 	char **argv;
3147dd7cddfSDavid du Colombier 	Image *i;
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier 	if(!goodrect(rect)){
3177dd7cddfSDavid du Colombier 		strcpy(err, Ebadwr);
3187dd7cddfSDavid du Colombier 		return -1;
3197dd7cddfSDavid du Colombier 	}
3207dd7cddfSDavid du Colombier 	argv = emalloc(4*sizeof(char*));
3217dd7cddfSDavid du Colombier 	argv[0] = "rc";
3227dd7cddfSDavid du Colombier 	argv[1] = "-c";
3237dd7cddfSDavid du Colombier 	while(isspace(*arg))
3247dd7cddfSDavid du Colombier 		arg++;
3257dd7cddfSDavid du Colombier 	if(*arg == '\0'){
3267dd7cddfSDavid du Colombier 		argv[1] = "-i";
3277dd7cddfSDavid du Colombier 		argv[2] = nil;
3287dd7cddfSDavid du Colombier 	}else{
3297dd7cddfSDavid du Colombier 		argv[2] = arg;
3307dd7cddfSDavid du Colombier 		argv[3] = nil;
3317dd7cddfSDavid du Colombier 	}
3329a747e4fSDavid du Colombier 	if(hideit)
3339a747e4fSDavid du Colombier 		i = allocimage(display, rect, screen->chan, 0, DWhite);
3349a747e4fSDavid du Colombier 	else
3357dd7cddfSDavid du Colombier 		i = allocwindow(wscreen, rect, Refbackup, DWhite);
3367dd7cddfSDavid du Colombier 	if(i == nil){
3377dd7cddfSDavid du Colombier 		strcpy(err, Ewalloc);
3387dd7cddfSDavid du Colombier 		return -1;
3397dd7cddfSDavid du Colombier 	}
3407dd7cddfSDavid du Colombier 	border(i, rect, Selborder, red, ZP);
3417dd7cddfSDavid du Colombier 
342*3ff48bf5SDavid du Colombier 	new(i, hideit, scrollit, pid, dir, "/bin/rc", argv);
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier 	free(argv);	/* when new() returns, argv and args have been copied */
3457dd7cddfSDavid du Colombier 	return 1;
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier 
3487dd7cddfSDavid du Colombier int
writewctl(Xfid * x,char * err)3497dd7cddfSDavid du Colombier writewctl(Xfid *x, char *err)
3507dd7cddfSDavid du Colombier {
351*3ff48bf5SDavid du Colombier 	int cnt, cmd, j, id, hideit, scrollit, pid;
3527dd7cddfSDavid du Colombier 	Image *i;
3537dd7cddfSDavid du Colombier 	char *arg, *dir;
3547dd7cddfSDavid du Colombier 	Rectangle rect;
3557dd7cddfSDavid du Colombier 	Window *w;
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier 	w = x->f->w;
3587dd7cddfSDavid du Colombier 	cnt = x->count;
3597dd7cddfSDavid du Colombier 	x->data[cnt] = '\0';
36080ee5cbfSDavid du Colombier 	id = 0;
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 	rect = rectsubpt(w->screenr, screen->r.min);
363*3ff48bf5SDavid du Colombier 	cmd = parsewctl(&arg, rect, &rect, &pid, &id, &hideit, &scrollit, &dir, x->data, err);
3647dd7cddfSDavid du Colombier 	if(cmd < 0)
3657dd7cddfSDavid du Colombier 		return -1;
3667dd7cddfSDavid du Colombier 
36780ee5cbfSDavid du Colombier 	if(mouse->buttons!=0 && cmd>=Top){
36880ee5cbfSDavid du Colombier 		strcpy(err, "action disallowed when mouse active");
36980ee5cbfSDavid du Colombier 		return -1;
37080ee5cbfSDavid du Colombier 	}
37180ee5cbfSDavid du Colombier 
37280ee5cbfSDavid du Colombier 	if(id != 0){
37380ee5cbfSDavid du Colombier 		for(j=0; j<nwindow; j++)
37480ee5cbfSDavid du Colombier 			if(window[j]->id == id)
37580ee5cbfSDavid du Colombier 				break;
37680ee5cbfSDavid du Colombier 		if(j == nwindow){
37780ee5cbfSDavid du Colombier 			strcpy(err, "no such window id");
37880ee5cbfSDavid du Colombier 			return -1;
37980ee5cbfSDavid du Colombier 		}
38080ee5cbfSDavid du Colombier 		w = window[j];
38180ee5cbfSDavid du Colombier 		if(w->deleted || w->i==nil){
38280ee5cbfSDavid du Colombier 			strcpy(err, "window deleted");
38380ee5cbfSDavid du Colombier 			return -1;
38480ee5cbfSDavid du Colombier 		}
38580ee5cbfSDavid du Colombier 	}
38680ee5cbfSDavid du Colombier 
3877dd7cddfSDavid du Colombier 	switch(cmd){
3887dd7cddfSDavid du Colombier 	case New:
389*3ff48bf5SDavid du Colombier 		return wctlnew(rect, arg, pid, hideit, scrollit, dir, err);
3909a747e4fSDavid du Colombier 	case Set:
3919a747e4fSDavid du Colombier 		if(pid > 0)
3929a747e4fSDavid du Colombier 			wsetpid(w, pid, 0);
3939a747e4fSDavid du Colombier 		return 1;
3947dd7cddfSDavid du Colombier 	case Move:
3957dd7cddfSDavid du Colombier 		rect = Rect(rect.min.x, rect.min.y, rect.min.x+Dx(w->screenr), rect.min.y+Dy(w->screenr));
3967dd7cddfSDavid du Colombier 		rect = rectonscreen(rect);
3977dd7cddfSDavid du Colombier 		/* fall through */
3987dd7cddfSDavid du Colombier 	case Resize:
3997dd7cddfSDavid du Colombier 		if(!goodrect(rect)){
4007dd7cddfSDavid du Colombier 			strcpy(err, Ebadwr);
4017dd7cddfSDavid du Colombier 			return -1;
4027dd7cddfSDavid du Colombier 		}
4037dd7cddfSDavid du Colombier 		if(eqrect(rect, w->screenr))
4047dd7cddfSDavid du Colombier 			return 1;
4057dd7cddfSDavid du Colombier 		i = allocwindow(wscreen, rect, Refbackup, DWhite);
4067dd7cddfSDavid du Colombier 		if(i == nil){
4077dd7cddfSDavid du Colombier 			strcpy(err, Ewalloc);
4087dd7cddfSDavid du Colombier 			return -1;
4097dd7cddfSDavid du Colombier 		}
4107dd7cddfSDavid du Colombier 		border(i, rect, Selborder, red, ZP);
4117dd7cddfSDavid du Colombier 		wsendctlmesg(w, Reshaped, i->r, i);
4127dd7cddfSDavid du Colombier 		return 1;
41380ee5cbfSDavid du Colombier 	case Scroll:
41480ee5cbfSDavid du Colombier 		w->scrolling = 1;
41580ee5cbfSDavid du Colombier 		wshow(w, w->nr);
41680ee5cbfSDavid du Colombier 		wsendctlmesg(w, Wakeup, ZR, nil);
41780ee5cbfSDavid du Colombier 		return 1;
41880ee5cbfSDavid du Colombier 	case Noscroll:
41980ee5cbfSDavid du Colombier 		w->scrolling = 0;
42080ee5cbfSDavid du Colombier 		wsendctlmesg(w, Wakeup, ZR, nil);
42180ee5cbfSDavid du Colombier 		return 1;
4227dd7cddfSDavid du Colombier 	case Top:
4237dd7cddfSDavid du Colombier 		wtopme(w);
4247dd7cddfSDavid du Colombier 		return 1;
4257dd7cddfSDavid du Colombier 	case Bottom:
4267dd7cddfSDavid du Colombier 		wbottomme(w);
4277dd7cddfSDavid du Colombier 		return 1;
4287dd7cddfSDavid du Colombier 	case Current:
4297dd7cddfSDavid du Colombier 		wcurrent(w);
4307dd7cddfSDavid du Colombier 		return 1;
43180ee5cbfSDavid du Colombier 	case Hide:
43280ee5cbfSDavid du Colombier 		switch(whide(w)){
43380ee5cbfSDavid du Colombier 		case -1:
43480ee5cbfSDavid du Colombier 			strcpy(err, "window already hidden");
43580ee5cbfSDavid du Colombier 			return -1;
43680ee5cbfSDavid du Colombier 		case 0:
43780ee5cbfSDavid du Colombier 			strcpy(err, "hide failed");
43880ee5cbfSDavid du Colombier 			return -1;
43980ee5cbfSDavid du Colombier 		default:
44080ee5cbfSDavid du Colombier 			break;
44180ee5cbfSDavid du Colombier 		}
44280ee5cbfSDavid du Colombier 		return 1;
44380ee5cbfSDavid du Colombier 	case Unhide:
44480ee5cbfSDavid du Colombier 		for(j=0; j<nhidden; j++)
44580ee5cbfSDavid du Colombier 			if(hidden[j] == w)
44680ee5cbfSDavid du Colombier 				break;
44780ee5cbfSDavid du Colombier 		if(j == nhidden){
44880ee5cbfSDavid du Colombier 			strcpy(err, "window not hidden");
44980ee5cbfSDavid du Colombier 			return -1;
45080ee5cbfSDavid du Colombier 		}
45180ee5cbfSDavid du Colombier 		if(wunhide(j) == 0){
45280ee5cbfSDavid du Colombier 			strcpy(err, "hide failed");
45380ee5cbfSDavid du Colombier 			return -1;
45480ee5cbfSDavid du Colombier 		}
45580ee5cbfSDavid du Colombier 		return 1;
45680ee5cbfSDavid du Colombier 	case Delete:
45780ee5cbfSDavid du Colombier 		wsendctlmesg(w, Deleted, ZR, nil);
45880ee5cbfSDavid du Colombier 		return 1;
4597dd7cddfSDavid du Colombier 	}
4607dd7cddfSDavid du Colombier 	strcpy(err, "invalid wctl message");
4617dd7cddfSDavid du Colombier 	return -1;
4627dd7cddfSDavid du Colombier }
4637dd7cddfSDavid du Colombier 
4647dd7cddfSDavid du Colombier void
wctlthread(void * v)4657dd7cddfSDavid du Colombier wctlthread(void *v)
4667dd7cddfSDavid du Colombier {
4677dd7cddfSDavid du Colombier 	char *buf, *arg, *dir;
468*3ff48bf5SDavid du Colombier 	int cmd, id, pid, hideit, scrollit;
4697dd7cddfSDavid du Colombier 	Rectangle rect;
4709a747e4fSDavid du Colombier 	char err[ERRMAX];
4717dd7cddfSDavid du Colombier 	Channel *c;
4727dd7cddfSDavid du Colombier 
4737dd7cddfSDavid du Colombier 	c = v;
4747dd7cddfSDavid du Colombier 
4757dd7cddfSDavid du Colombier 	threadsetname("WCTLTHREAD");
4767dd7cddfSDavid du Colombier 
4777dd7cddfSDavid du Colombier 	for(;;){
4787dd7cddfSDavid du Colombier 		buf = recvp(c);
479*3ff48bf5SDavid du Colombier 		cmd = parsewctl(&arg, ZR, &rect, &pid, &id, &hideit, &scrollit, &dir, buf, err);
4807dd7cddfSDavid du Colombier 
4817dd7cddfSDavid du Colombier 		switch(cmd){
4827dd7cddfSDavid du Colombier 		case New:
483*3ff48bf5SDavid du Colombier 			wctlnew(rect, arg, pid, hideit, scrollit, dir, err);
4847dd7cddfSDavid du Colombier 		}
4857dd7cddfSDavid du Colombier 		free(buf);
4867dd7cddfSDavid du Colombier 	}
4877dd7cddfSDavid du Colombier }
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier void
wctlproc(void * v)4907dd7cddfSDavid du Colombier wctlproc(void *v)
4917dd7cddfSDavid du Colombier {
4927dd7cddfSDavid du Colombier 	char *buf;
4937dd7cddfSDavid du Colombier 	int n, eofs;
4947dd7cddfSDavid du Colombier 	Channel *c;
4957dd7cddfSDavid du Colombier 
4967dd7cddfSDavid du Colombier 	threadsetname("WCTLPROC");
4977dd7cddfSDavid du Colombier 	c = v;
4987dd7cddfSDavid du Colombier 
4997dd7cddfSDavid du Colombier 	eofs = 0;
5007dd7cddfSDavid du Colombier 	for(;;){
5019a747e4fSDavid du Colombier 		buf = emalloc(messagesize);
5029a747e4fSDavid du Colombier 		n = read(wctlfd, buf, messagesize-1);	/* room for \0 */
5037dd7cddfSDavid du Colombier 		if(n < 0)
5047dd7cddfSDavid du Colombier 			break;
5057dd7cddfSDavid du Colombier 		if(n == 0){
5067dd7cddfSDavid du Colombier 			if(++eofs > 20)
5077dd7cddfSDavid du Colombier 				break;
5087dd7cddfSDavid du Colombier 			continue;
5097dd7cddfSDavid du Colombier 		}
5107dd7cddfSDavid du Colombier 		eofs = 0;
5117dd7cddfSDavid du Colombier 
5127dd7cddfSDavid du Colombier 		buf[n] = '\0';
5137dd7cddfSDavid du Colombier 		sendp(c, buf);
5147dd7cddfSDavid du Colombier 	}
5157dd7cddfSDavid du Colombier }
516