#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <mouse.h>
#include <keyboard.h>
#include <control.h>
#include <bio.h>
#include <ctype.h>
#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; i<Blinelen(b)-1; i++)
if(isspace(s[i]))
s[i] = ' ';
s[i] = '\0';
chanprint(cs->ctl, "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);
}
|