13 typedef struct Event Event;
25 char b[EVENTSIZE*UTFmax+1];
65 int label(char*, int);
66 void error(char*, ...);
67 void stdinproc(void*);
68 void stdoutproc(void*);
69 void type(Event*, int, CFid*, CFid*);
70 void sende(Event*, int, CFid*, CFid*, CFid*, int);
71 char *onestring(int, char**);
73 void deltype(uint, uint);
77 fsfidprint(CFid *fid, char *fmt, ...)
84 n = vsnprint(buf, sizeof buf, fmt, arg);
86 return fswrite(fid, buf, n);
92 fprint(2, "usage: win cmd args...\n");
93 threadexitsall("usage");
97 nopipes(void *v, char *msg)
100 if(strcmp(msg, "sys: write on closed pipe") == 0)
113 hangupnote(void *a, char *msg)
115 if(strcmp(msg, "hangup") == 0 && pid != 0){
116 postnote(PNGROUP, pid, "hangup");
119 if(strstr(msg, "child")){
127 threadmain(int argc, char **argv)
139 name = EARGF(usage());
157 notedisable("sys: write on closed pipe");
158 noteenable("sys: child");
161 if((fs = nsmount("acme", "")) == 0)
162 sysfatal("nsmount acme: %r");
163 ctlfd = fsopen(fs, "new/ctl", ORDWR|OCEXEC);
164 if(ctlfd == 0 || fsread(ctlfd, buf, 12) != 12)
167 snprint(buf, sizeof buf, "%d", id);
168 putenv("winid", buf);
169 sprint(buf, "%d/tag", id);
170 fd = fsopenfd(fs, buf, OWRITE|OCEXEC);
171 write(fd, " Send Delete", 12);
173 sprint(buf, "%d/event", id);
174 eventfd = fsopen(fs, buf, ORDWR|OCEXEC);
175 sprint(buf, "%d/addr", id);
176 addrfd = fsopen(fs, buf, ORDWR|OCEXEC);
177 sprint(buf, "%d/data", id);
178 datafd = fsopen(fs, buf, ORDWR|OCEXEC);
179 sprint(buf, "%d/body", id);
180 /* bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC); */
181 if(eventfd==nil || addrfd==nil || datafd==nil)
182 sysfatal("data files: %r");
184 if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0)
185 sysfatal("data files: %r");
189 cwait = threadwaitchan();
190 threadcreate(waitthread, nil, STACK);
191 pid = rcstart(argc, argv, &rcfd, nil);
193 sysfatal("exec failed");
195 getwd(buf1, sizeof buf1);
196 sprint(buf, "name %s/-%s\n0\n", buf1, name);
197 fswrite(ctlfd, buf, strlen(buf));
198 sprint(buf, "dumpdir %s/\n", buf1);
199 fswrite(ctlfd, buf, strlen(buf));
200 sprint(buf, "dump %s\n", onestring(argc, argv));
201 fswrite(ctlfd, buf, strlen(buf));
203 updatewinsize(25, 80, 0, 0);
204 proccreate(stdoutproc, nil, STACK);
215 s = vsmprint(s, arg);
217 fprint(2, "win: %s: %r\n", s);
220 postnote(PNGROUP, pid, "hangup");
225 onestring(int argc, char **argv)
229 static char buf[1024];
234 for(i=0; i<argc; i++){
236 if(p+n+1 >= buf+sizeof buf)
238 memmove(p, argv[i], n);
249 static char buf[8192];
254 nbuf = fsread(efd, buf, sizeof buf);
269 while('0'<=(c=getec(efd)) && c<='9')
272 error("event number syntax");
277 geter(CFid *efd, char *buf, int *nb)
287 while(!fullrune(buf, n))
288 buf[n++] = getec(efd);
296 gete(CFid *efd, Event *e)
304 e->flag = geten(efd);
306 if(e->nr > EVENTSIZE)
307 error("event string too long");
309 for(i=0; i<e->nr; i++){
310 e->r[i] = geter(efd, e->b+e->nb, &nb);
315 if(getec(efd) != '\n')
316 error("event syntax 2");
320 nrunes(char *s, int nb)
327 i += chartorune(&r, s+i);
345 fprint(2, "typing[%d,%d)\n", q.p, q.p+ntyper);
348 fprint(2, "msg %c%c q[%d,%d)... ", e.c1, e.c2, e.q0, e.q1);
353 print("unknown message %c%c\n", e.c1, e.c2);
356 case 'E': /* write to body; can't affect us */
358 fprint(2, "shift typing %d... ", e.q1-e.q0);
362 case 'F': /* generated by our actions; ignore */
371 fprint(2, "shift typing %d... ", e.q1-e.q0);
374 else if(e.q0 <= q.p+ntyper){
376 fprint(2, "type... ");
377 type(&e, fd0, afd, dfd);
393 if(e.flag&1 || (e.c2=='x' && e.nr==0 && e2.nr==0)){
394 /* send it straight back */
395 fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
398 if(e.q0==e.q1 && (e.flag&2)){
404 sende(&e, fd0, cfd, afd, dfd, 0);
405 sende(&blank, fd0, cfd, afd, dfd, 0);
407 sende(&e3, fd0, cfd, afd, dfd, 1);
408 }else if(e.q1 != e.q0)
409 sende(&e, fd0, cfd, afd, dfd, 1);
414 /* just send it back */
417 fsfidprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
441 char x[16], hold[UTFmax];
444 buf = malloc(8192+UTFmax+1);
447 /* Let typing have a go -- maybe there's a rubout waiting. */
449 n = read(fd1, buf+npart, 8192);
454 s = memchr(buf+npart, 0, n);
456 for(t=s; s<buf+npart+n; s++)
457 if(*t = *s) /* assign = */
464 /* hold on to final partial rune */
466 while(n>0 && (buf[n-1]&0xC0)){
469 if((buf[n]&0xC0)!=0x80){
470 if(fullrune(buf+n, npart)){
471 w = chartorune(&r, buf+n);
479 memmove(hold, buf+n, npart);
484 m = sprint(x, "#%d", q.p);
485 if(fswrite(afd, x, m) != m){
486 fprint(2, "stdout writing address: %r; resetting\n");
487 fswrite(afd, "$", 1);
488 m = fsread(afd, x, sizeof x-1);
494 if(fswrite(dfd, buf, n) != n)
495 error("stdout writing body");
496 q.p += nrunes(buf, n);
498 memmove(buf, hold, npart);
505 label(char *sr, int n)
507 char *sl, *el, *er, *r, *p;
510 for(r=er-1; r>=sr; r--)
517 if(el-sr > sizeof wdir - strlen(name) - 20)
518 sr = el - sizeof wdir - strlen(name) - 20;
519 for(sl=el-3; sl>=sr; sl--)
520 if(sl[0]=='\033' && sl[1]==']' && sl[2]==';')
527 * add /-sysname if not present
529 snprint(wdir, sizeof wdir, "name %s", sl+3);
530 p = strrchr(wdir, '/');
531 if(p==nil || *(p+1) != '-'){
532 p = wdir+strlen(wdir);
538 strcat(wdir, "\n0\n");
539 fswrite(ctlfd, wdir, strlen(wdir));
541 memmove(sl, el, er-el);
573 addtype(int c, uint p0, char *b, int nb, int nr)
580 for(i=0; i<nb; i+=w){
581 w = chartorune(&r, b+i);
582 if((r==0x7F||r==3) && c=='K'){
583 write(rcfd, "\x7F", 1);
584 /* toss all typing */
589 /* buglet: more than one delete ignored */
592 if(r=='\n' || r==0x04)
595 typing = realloc(typing, ntypeb+nb);
599 memmove(typing+ntypeb, b, nb);
602 for(p=0; p<p0 && b0<typing+ntypeb; p++){
603 w = chartorune(&r, b0+i);
607 error("typing: findrune");
608 memmove(b0+nb, b0, (typing+ntypeb)-b0);
621 for(i=0; i<ntypeb; i++)
622 if(typing[i]=='\n' || typing[i]==0x04){
625 if(write(fd0, typing, n) != n)
626 error("sending to program");
627 nr = nrunes(typing, i);
631 memmove(typing, typing+i, ntypeb);
635 print("no breakchar\n");
642 deltype(uint p0, uint p1)
650 for(p=0; p<p0 && b0<ntypeb; p++){
651 w = chartorune(&r, typing+b0);
658 for(; p<p1 && b1<ntypeb; p++){
659 w = chartorune(&r, typing+b1);
661 if(r=='\n' || r==0x04)
666 memmove(typing+b0, typing+b1, ntypeb-b1);
672 type(Event *e, int fd0, CFid *afd, CFid *dfd)
678 addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr);
682 n = sprint(buf, "#%d", m);
683 fswrite(afd, buf, n);
684 n = fsread(dfd, buf, sizeof buf);
687 do; while(n>0 && (buf[--n]&0xC0)==0x80);
692 addtype(e->c1, m-q.p, buf, n, nr);
700 sende(Event *e, int fd0, CFid *cfd, CFid *afd, CFid *dfd, int donl)
702 int l, m, n, nr, lastc, end;
703 char abuf[16], buf[128];
706 l = sprint(abuf, "#%d", end);
707 fswrite(afd, abuf, l);
709 fswrite(dfd, e->b, e->nb);
710 addtype(e->c1, ntyper, e->b, e->nb, e->nr);
711 lastc = e->r[e->nr-1];
716 n = sprint(buf, "#%d", m);
717 fswrite(afd, buf, n);
718 n = fsread(dfd, buf, sizeof buf);
721 do; while(n>0 && (buf[--n]&0xC0)==0x80);
726 l = sprint(abuf, "#%d", end);
727 fswrite(afd, abuf, l);
728 fswrite(dfd, buf, n);
729 addtype(e->c1, ntyper, buf, n, nr);
735 if(donl && lastc!='\n'){
736 fswrite(dfd, "\n", 1);
737 addtype(e->c1, ntyper, "\n", 1, 1);
739 fswrite(cfd, "dot=addr", 8);