15 char Ebadwr[] = "bad rectangle in wctl request";
16 char Ewalloc[] = "window allocation failed in wctl request";
18 /* >= Top are disallowed if mouse button is pressed */
35 static char *cmds[] = {
40 [Noscroll] = "noscroll",
44 [Current] = "current",
68 static char *params[] = {
80 [Scrolling] = "-scroll",
81 [Noscrolling] = "-noscroll",
86 * Check that newly created window will be of manageable size
91 if(!eqrect(canonrect(r), r))
93 if(Dx(r)<100 || Dy(r)<3*font->height)
95 /* must have some screen and border visible so we can move it out of the way */
96 if(Dx(r) >= Dx(screen->r) && Dy(r) >= Dy(screen->r))
98 /* reasonable sizes only please */
99 if(Dx(r) > BIG*Dx(screen->r))
101 if(Dy(r) > BIG*Dx(screen->r))
108 word(char **sp, char *tab[])
117 while(*s!='\0' && !isspace(*s))
119 for(i=0; tab[i]!=nil; i++)
120 if(strncmp(tab[i], t, strlen(tab[i])) == 0){
128 set(int sign, int neg, int abs, int pos)
141 int minx, miny, dx, dy;
143 dx = min(600, Dx(screen->r) - 2*Borderwidth);
144 dy = min(400, Dy(screen->r) - 2*Borderwidth);
150 return Rect(minx, miny, minx+dx, miny+dy);
154 shift(int *minp, int *maxp, int min, int max)
167 rectonscreen(Rectangle r)
169 shift(&r.min.x, &r.max.x, screen->r.min.x, screen->r.max.x);
170 shift(&r.min.y, &r.max.y, screen->r.min.y, screen->r.max.y);
174 /* permit square brackets, in the manner of %R */
176 riostrtol(char *s, char **t)
180 while(*s!='\0' && (*s==' ' || *s=='\t' || *s=='['))
184 n = strtol(s, t, 10);
186 while((*t)[0] == ']')
193 parsewctl(char **argp, Rectangle r, Rectangle *rp, int *pidp, int *idp, int *hiddenp, int *scrollingp, char **cdp, char *s, char *err)
195 int cmd, param, xy, sign;
200 *scrollingp = scrolling;
202 cmd = word(&s, cmds);
204 strcpy(err, "unrecognized wctl command");
210 strcpy(err, "missing or bad wctl parameter");
211 while((param = word(&s, params)) >= 0){
212 switch(param){ /* special cases */
223 r.min.x = riostrtol(s, &t);
227 r.min.y = riostrtol(s, &t);
231 r.max.x = riostrtol(s, &t);
235 r.max.y = riostrtol(s, &t);
245 while(*s && !isspace(*s))
261 xy = riostrtol(s, &s);
264 strcpy(err, "unrecognized wctl parameter");
267 r.min.x = set(sign, r.min.x-xy, xy, r.min.x+xy);
270 r.min.y = set(sign, r.min.y-xy, xy, r.min.y+xy);
273 r.max.x = set(sign, r.max.x-xy, xy, r.max.x+xy);
276 r.max.y = set(sign, r.max.y-xy, xy, r.max.y+xy);
279 r.max.x = set(sign, r.max.x-xy, r.min.x+xy, r.max.x+xy);
282 r.max.y = set(sign, r.max.y-xy, r.min.y+xy, r.max.y+xy);
295 *rp = rectonscreen(rectaddpt(r, screen->r.min));
299 if(cmd!=New && *s!='\0'){
300 strcpy(err, "extraneous text in wctl message");
311 wctlnew(Rectangle rect, char *arg, int pid, int hideit, int scrollit, char *dir, char *err)
320 argv = emalloc(4*sizeof(char*));
333 i = allocimage(display, rect, screen->chan, 0, DWhite);
335 i = allocwindow(wscreen, rect, Refbackup, DWhite);
337 strcpy(err, Ewalloc);
340 border(i, rect, Selborder, red, ZP);
342 new(i, hideit, scrollit, pid, dir, "/bin/rc", argv);
344 free(argv); /* when new() returns, argv and args have been copied */
349 writewctl(Xfid *x, char *err)
351 int cnt, cmd, j, id, hideit, scrollit, pid;
362 rect = rectsubpt(w->screenr, screen->r.min);
363 cmd = parsewctl(&arg, rect, &rect, &pid, &id, &hideit, &scrollit, &dir, x->data, err);
367 if(mouse->buttons!=0 && cmd>=Top){
368 strcpy(err, "action disallowed when mouse active");
373 for(j=0; j<nwindow; j++)
374 if(window[j]->id == id)
377 strcpy(err, "no such window id");
381 if(w->deleted || w->i==nil){
382 strcpy(err, "window deleted");
389 return wctlnew(rect, arg, pid, hideit, scrollit, dir, err);
395 rect = Rect(rect.min.x, rect.min.y, rect.min.x+Dx(w->screenr), rect.min.y+Dy(w->screenr));
396 rect = rectonscreen(rect);
403 if(eqrect(rect, w->screenr))
405 i = allocwindow(wscreen, rect, Refbackup, DWhite);
407 strcpy(err, Ewalloc);
410 border(i, rect, Selborder, red, ZP);
411 wsendctlmesg(w, Reshaped, i->r, i);
416 wsendctlmesg(w, Wakeup, ZR, nil);
420 wsendctlmesg(w, Wakeup, ZR, nil);
434 strcpy(err, "window already hidden");
437 strcpy(err, "hide failed");
444 for(j=0; j<nhidden; j++)
448 strcpy(err, "window not hidden");
452 strcpy(err, "hide failed");
457 wsendctlmesg(w, Deleted, ZR, nil);
460 strcpy(err, "invalid wctl message");
467 char *buf, *arg, *dir;
468 int cmd, id, pid, hideit, scrollit;
475 threadsetname("WCTLTHREAD");
479 cmd = parsewctl(&arg, ZR, &rect, &pid, &id, &hideit, &scrollit, &dir, buf, err);
483 wctlnew(rect, arg, pid, hideit, scrollit, dir, err);
496 threadsetname("WCTLPROC");
501 buf = emalloc(messagesize);
502 n = read(wctlfd, buf, messagesize-1); /* room for \0 */