#include #include #include #include #include #include #include #include #include #define STACK 32*1024 typedef struct { char *cmd; int p[2]; /* p[1] is write to program; p[0] set to prog fd 0*/ int q[2]; /* q[0] is read from program; q[1] set to prog fd 1 */ Channel *sync; /* chan(ulong) */ }Exec; Controlset *cs; int ctldeletequits = 1; Channel *cread; Channel *cwrite; Channel *cexit; char *colornames[3] = { "white", "black", "red" }; char *label = "front"; void execproc(void *v) { Channel *sync; Exec *e; int p[2], q[2]; char *cmd; threadsetname("execproc"); e = v; p[0] = e->p[0]; p[1] = e->p[1]; q[0] = e->q[0]; q[1] = e->q[1]; cmd = e->cmd; sync = e->sync; rfork(RFFDG); free(e); dup(p[0], 0); close(p[0]); close(p[1]); if(q[0]){ dup(q[1], 1); close(q[0]); close(q[1]); } if(0) close(2); procexecl(sync, "/bin/rc", "rc", "-c", cmd, 0); sysfatal("can't exec"); } void readproc(void *v) { Biobuf *b; int i, n; char *s; b = v; n = 0; for(;;){ if((s=Brdline(b, '\n')) == nil) sendul(cexit, 0); for(i=0; ictl, "tarea add %q", s); chanprint(cs->ctl, "tarea scroll 1"); chanprint(cs->ctl, "slider max %d", ++n); } } void writeproc(void *v) { int fd; char *s; fd = (int)v; for(;;){ s = recvp(cwrite); fprint(fd, "%s\n", s+6); chanprint(cs->ctl, "entry value %q", ""); free(s); } } void backend(char *cmd) { Exec *e; Channel *sync; Biobuf bi; int p[2], q[2]; if(pipe(p)<0 || pipe(q)<0) sysfatal("can't create pipe: %r"); sync = chancreate(sizeof(ulong), 0); if(sync == nil) sysfatal("can't create channel: %r"); e = malloc(sizeof(Exec)); if(e == nil) sysfatal("can't malloc: %r"); e->p[0] = p[0]; e->p[1] = p[1]; e->q[0] = q[0]; e->q[1] = q[1]; e->cmd = cmd; e->sync = sync; proccreate(execproc, e, STACK); recvul(sync); chanfree(sync); close(p[0]); close(q[1]); Binit(&bi, q[0], OREAD); proccreate(readproc, &bi, STACK); proccreate(writeproc, (void *)p[1], STACK); } void resizecontrolset(Controlset*) { Rectangle r, r1, r2, r3; if(getwindow(display, Refnone) < 0) sysfatal("resize failed: %r"); r = insetrect(screen->r, 10); r1 = r; r1.min.x += stringwidth(font, "0") +20; r1.max.y -= 1+font->height+1+10; r2 = r; r2.min.y = r1.max.y+10; chanprint(cs->ctl, "tarea rect %R \ntarea show", r1); chanprint(cs->ctl, "entry rect %R \nentry show", r2); r3 = r; r3.max.x = r1.min.x-10; r3.max.y = r1.max.y; chanprint(cs->ctl, "slider rect %R \nslider show", r3); } int mainstacksize = STACK; void threadmain(int argc, char *argv[]) { Control *entry, *tarea, *slider; int i; ARGBEGIN{ case 'c': for(i=0; i<3; i++){ colornames[i] = ARGF(); if(colornames[i] == nil) goto Usage; } break; case 'l': label = ARGF(); if(label == nil) goto Usage; break; default: Usage: fprint(2, "Usage: front name: %d\n", argc); exits("usage"); }ARGEND if(argc != 1) goto Usage; if(initdraw(0, 0, label) < 0) sysfatal("can't open display"); initcontrols(); cs = newcontrolset(screen, nil, nil, nil); cs->clicktotype = 1; slider = createslider(cs, "slider"); chanprint(cs->ctl, "slider border 1"); chanprint(cs->ctl, "slider border 1"); chanprint(cs->ctl, "slider image %s", colornames[0]); chanprint(cs->ctl, "slider bordercolor %s", colornames[1]); chanprint(cs->ctl, "slider indicatorcolor %s", colornames[2]); chanprint(cs->ctl, "slider format %q", "%q: tarea topline %d"); chanprint(cs->ctl, "slider absolute 0"); entry = createentry(cs, "entry"); chanprint(cs->ctl, "entry border 1"); chanprint(cs->ctl, "entry format %q", "%q:%s"); tarea = createtext(cs, "tarea"); chanprint(cs->ctl, "tarea border 1"); cread = chancreate(sizeof(char *), 0); cwrite = chancreate(sizeof(char *), 0); cexit = chancreate(sizeof(int), 0); if(cread==nil || cwrite==nil || cexit==nil) sysfatal("can't create channels. %r"); controlwire(entry, "event", cwrite); controlwire(tarea, "event", cs->ctl); controlwire(slider, "event", cs->ctl); activate(slider); activate(entry); activate(tarea); resizecontrolset(cs); backend(argv[0]); recvul(cexit); threadexitsall(nil); }