180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <bio.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include "win.h"
680ee5cbfSDavid du Colombier
780ee5cbfSDavid du Colombier Window*
newwindow(void)880ee5cbfSDavid du Colombier newwindow(void)
980ee5cbfSDavid du Colombier {
1080ee5cbfSDavid du Colombier char buf[12];
1180ee5cbfSDavid du Colombier Window *w;
1280ee5cbfSDavid du Colombier
1380ee5cbfSDavid du Colombier w = emalloc(sizeof(Window));
1480ee5cbfSDavid du Colombier w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
1580ee5cbfSDavid du Colombier if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
1680ee5cbfSDavid du Colombier error("can't open window ctl file: %r");
1780ee5cbfSDavid du Colombier ctlprint(w->ctl, "noscroll\n");
1880ee5cbfSDavid du Colombier w->id = atoi(buf);
1980ee5cbfSDavid du Colombier w->event = winopenfile(w, "event");
2080ee5cbfSDavid du Colombier w->addr = -1; /* will be opened when needed */
2180ee5cbfSDavid du Colombier w->body = nil;
2280ee5cbfSDavid du Colombier w->data = -1;
2380ee5cbfSDavid du Colombier w->cevent = chancreate(sizeof(Event*), 0);
2480ee5cbfSDavid du Colombier if(w->cevent == nil)
2580ee5cbfSDavid du Colombier error("cevent is nil: %r");
2680ee5cbfSDavid du Colombier return w;
2780ee5cbfSDavid du Colombier }
2880ee5cbfSDavid du Colombier
2980ee5cbfSDavid du Colombier void
winsetdump(Window * w,char * dir,char * cmd)3080ee5cbfSDavid du Colombier winsetdump(Window *w, char *dir, char *cmd)
3180ee5cbfSDavid du Colombier {
3280ee5cbfSDavid du Colombier if(dir != nil)
3380ee5cbfSDavid du Colombier ctlprint(w->ctl, "dumpdir %s\n", dir);
3480ee5cbfSDavid du Colombier if(cmd != nil)
3580ee5cbfSDavid du Colombier ctlprint(w->ctl, "dump %s\n", cmd);
3680ee5cbfSDavid du Colombier }
3780ee5cbfSDavid du Colombier
3880ee5cbfSDavid du Colombier void
wineventproc(void * v)3980ee5cbfSDavid du Colombier wineventproc(void *v)
4080ee5cbfSDavid du Colombier {
4180ee5cbfSDavid du Colombier Window *w;
4280ee5cbfSDavid du Colombier int i;
4380ee5cbfSDavid du Colombier
4480ee5cbfSDavid du Colombier threadsetname("wineventproc");
4580ee5cbfSDavid du Colombier w = v;
4680ee5cbfSDavid du Colombier for(i=0; ; i++){
4780ee5cbfSDavid du Colombier if(i >= NEVENT)
4880ee5cbfSDavid du Colombier i = 0;
4980ee5cbfSDavid du Colombier wingetevent(w, &w->e[i]);
5080ee5cbfSDavid du Colombier sendp(w->cevent, &w->e[i]);
5180ee5cbfSDavid du Colombier }
5280ee5cbfSDavid du Colombier }
5380ee5cbfSDavid du Colombier
5480ee5cbfSDavid du Colombier int
winopenfile(Window * w,char * f)5580ee5cbfSDavid du Colombier winopenfile(Window *w, char *f)
5680ee5cbfSDavid du Colombier {
5780ee5cbfSDavid du Colombier char buf[64];
5880ee5cbfSDavid du Colombier int fd;
5980ee5cbfSDavid du Colombier
6080ee5cbfSDavid du Colombier sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
6180ee5cbfSDavid du Colombier fd = open(buf, ORDWR|OCEXEC);
6280ee5cbfSDavid du Colombier if(fd < 0)
6380ee5cbfSDavid du Colombier error("can't open window file %s: %r", f);
6480ee5cbfSDavid du Colombier return fd;
6580ee5cbfSDavid du Colombier }
6680ee5cbfSDavid du Colombier
6780ee5cbfSDavid du Colombier void
wintagwrite(Window * w,char * s,int n)6880ee5cbfSDavid du Colombier wintagwrite(Window *w, char *s, int n)
6980ee5cbfSDavid du Colombier {
7080ee5cbfSDavid du Colombier int fd;
7180ee5cbfSDavid du Colombier
7280ee5cbfSDavid du Colombier fd = winopenfile(w, "tag");
7380ee5cbfSDavid du Colombier if(write(fd, s, n) != n)
7480ee5cbfSDavid du Colombier error("tag write: %r");
7580ee5cbfSDavid du Colombier close(fd);
7680ee5cbfSDavid du Colombier }
7780ee5cbfSDavid du Colombier
7880ee5cbfSDavid du Colombier void
winname(Window * w,char * s)7980ee5cbfSDavid du Colombier winname(Window *w, char *s)
8080ee5cbfSDavid du Colombier {
8180ee5cbfSDavid du Colombier ctlprint(w->ctl, "name %s\n", s);
8280ee5cbfSDavid du Colombier }
8380ee5cbfSDavid du Colombier
8480ee5cbfSDavid du Colombier void
winopenbody(Window * w,int mode)8580ee5cbfSDavid du Colombier winopenbody(Window *w, int mode)
8680ee5cbfSDavid du Colombier {
8780ee5cbfSDavid du Colombier char buf[256];
8880ee5cbfSDavid du Colombier
8980ee5cbfSDavid du Colombier sprint(buf, "/mnt/wsys/%d/body", w->id);
9080ee5cbfSDavid du Colombier w->body = Bopen(buf, mode|OCEXEC);
9180ee5cbfSDavid du Colombier if(w->body == nil)
9280ee5cbfSDavid du Colombier error("can't open window body file: %r");
9380ee5cbfSDavid du Colombier }
9480ee5cbfSDavid du Colombier
9580ee5cbfSDavid du Colombier void
winclosebody(Window * w)9680ee5cbfSDavid du Colombier winclosebody(Window *w)
9780ee5cbfSDavid du Colombier {
9880ee5cbfSDavid du Colombier if(w->body != nil){
9980ee5cbfSDavid du Colombier Bterm(w->body);
10080ee5cbfSDavid du Colombier w->body = nil;
10180ee5cbfSDavid du Colombier }
10280ee5cbfSDavid du Colombier }
10380ee5cbfSDavid du Colombier
10480ee5cbfSDavid du Colombier void
winwritebody(Window * w,char * s,int n)10580ee5cbfSDavid du Colombier winwritebody(Window *w, char *s, int n)
10680ee5cbfSDavid du Colombier {
10780ee5cbfSDavid du Colombier if(w->body == nil)
10880ee5cbfSDavid du Colombier winopenbody(w, OWRITE);
10980ee5cbfSDavid du Colombier if(Bwrite(w->body, s, n) != n)
11080ee5cbfSDavid du Colombier error("write error to window: %r");
11180ee5cbfSDavid du Colombier }
11280ee5cbfSDavid du Colombier
11380ee5cbfSDavid du Colombier int
wingetec(Window * w)11480ee5cbfSDavid du Colombier wingetec(Window *w)
11580ee5cbfSDavid du Colombier {
11680ee5cbfSDavid du Colombier if(w->nbuf == 0){
11780ee5cbfSDavid du Colombier w->nbuf = read(w->event, w->buf, sizeof w->buf);
11880ee5cbfSDavid du Colombier if(w->nbuf <= 0){
11980ee5cbfSDavid du Colombier /* probably because window has exited, and only called by wineventproc, so just shut down */
12080ee5cbfSDavid du Colombier threadexits(nil);
12180ee5cbfSDavid du Colombier }
12280ee5cbfSDavid du Colombier w->bufp = w->buf;
12380ee5cbfSDavid du Colombier }
12480ee5cbfSDavid du Colombier w->nbuf--;
12580ee5cbfSDavid du Colombier return *w->bufp++;
12680ee5cbfSDavid du Colombier }
12780ee5cbfSDavid du Colombier
12880ee5cbfSDavid du Colombier int
wingeten(Window * w)12980ee5cbfSDavid du Colombier wingeten(Window *w)
13080ee5cbfSDavid du Colombier {
13180ee5cbfSDavid du Colombier int n, c;
13280ee5cbfSDavid du Colombier
13380ee5cbfSDavid du Colombier n = 0;
13480ee5cbfSDavid du Colombier while('0'<=(c=wingetec(w)) && c<='9')
13580ee5cbfSDavid du Colombier n = n*10+(c-'0');
13680ee5cbfSDavid du Colombier if(c != ' ')
13780ee5cbfSDavid du Colombier error("event number syntax");
13880ee5cbfSDavid du Colombier return n;
13980ee5cbfSDavid du Colombier }
14080ee5cbfSDavid du Colombier
14180ee5cbfSDavid du Colombier int
wingeter(Window * w,char * buf,int * nb)14280ee5cbfSDavid du Colombier wingeter(Window *w, char *buf, int *nb)
14380ee5cbfSDavid du Colombier {
14480ee5cbfSDavid du Colombier Rune r;
14580ee5cbfSDavid du Colombier int n;
14680ee5cbfSDavid du Colombier
14780ee5cbfSDavid du Colombier r = wingetec(w);
14880ee5cbfSDavid du Colombier buf[0] = r;
14980ee5cbfSDavid du Colombier n = 1;
15080ee5cbfSDavid du Colombier if(r >= Runeself) {
15180ee5cbfSDavid du Colombier while(!fullrune(buf, n))
15280ee5cbfSDavid du Colombier buf[n++] = wingetec(w);
15380ee5cbfSDavid du Colombier chartorune(&r, buf);
15480ee5cbfSDavid du Colombier }
15580ee5cbfSDavid du Colombier *nb = n;
15680ee5cbfSDavid du Colombier return r;
15780ee5cbfSDavid du Colombier }
15880ee5cbfSDavid du Colombier
15980ee5cbfSDavid du Colombier void
wingetevent(Window * w,Event * e)16080ee5cbfSDavid du Colombier wingetevent(Window *w, Event *e)
16180ee5cbfSDavid du Colombier {
16280ee5cbfSDavid du Colombier int i, nb;
16380ee5cbfSDavid du Colombier
16480ee5cbfSDavid du Colombier e->c1 = wingetec(w);
16580ee5cbfSDavid du Colombier e->c2 = wingetec(w);
16680ee5cbfSDavid du Colombier e->q0 = wingeten(w);
16780ee5cbfSDavid du Colombier e->q1 = wingeten(w);
16880ee5cbfSDavid du Colombier e->flag = wingeten(w);
16980ee5cbfSDavid du Colombier e->nr = wingeten(w);
17080ee5cbfSDavid du Colombier if(e->nr > EVENTSIZE)
17180ee5cbfSDavid du Colombier error("event string too long");
17280ee5cbfSDavid du Colombier e->nb = 0;
17380ee5cbfSDavid du Colombier for(i=0; i<e->nr; i++){
17480ee5cbfSDavid du Colombier e->r[i] = wingeter(w, e->b+e->nb, &nb);
17580ee5cbfSDavid du Colombier e->nb += nb;
17680ee5cbfSDavid du Colombier }
17780ee5cbfSDavid du Colombier e->r[e->nr] = 0;
17880ee5cbfSDavid du Colombier e->b[e->nb] = 0;
17980ee5cbfSDavid du Colombier if(wingetec(w) != '\n')
18080ee5cbfSDavid du Colombier error("event syntax error");
18180ee5cbfSDavid du Colombier }
18280ee5cbfSDavid du Colombier
18380ee5cbfSDavid du Colombier void
winwriteevent(Window * w,Event * e)18480ee5cbfSDavid du Colombier winwriteevent(Window *w, Event *e)
18580ee5cbfSDavid du Colombier {
186*9a747e4fSDavid du Colombier fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
18780ee5cbfSDavid du Colombier }
18880ee5cbfSDavid du Colombier
18980ee5cbfSDavid du Colombier static int
nrunes(char * s,int nb)19080ee5cbfSDavid du Colombier nrunes(char *s, int nb)
19180ee5cbfSDavid du Colombier {
19280ee5cbfSDavid du Colombier int i, n;
19380ee5cbfSDavid du Colombier Rune r;
19480ee5cbfSDavid du Colombier
19580ee5cbfSDavid du Colombier n = 0;
19680ee5cbfSDavid du Colombier for(i=0; i<nb; n++)
19780ee5cbfSDavid du Colombier i += chartorune(&r, s+i);
19880ee5cbfSDavid du Colombier return n;
19980ee5cbfSDavid du Colombier }
20080ee5cbfSDavid du Colombier
20180ee5cbfSDavid du Colombier void
winread(Window * w,uint q0,uint q1,char * data)20280ee5cbfSDavid du Colombier winread(Window *w, uint q0, uint q1, char *data)
20380ee5cbfSDavid du Colombier {
20480ee5cbfSDavid du Colombier int m, n, nr;
20580ee5cbfSDavid du Colombier char buf[256];
20680ee5cbfSDavid du Colombier
20780ee5cbfSDavid du Colombier if(w->addr < 0)
20880ee5cbfSDavid du Colombier w->addr = winopenfile(w, "addr");
20980ee5cbfSDavid du Colombier if(w->data < 0)
21080ee5cbfSDavid du Colombier w->data = winopenfile(w, "data");
21180ee5cbfSDavid du Colombier m = q0;
21280ee5cbfSDavid du Colombier while(m < q1){
21380ee5cbfSDavid du Colombier n = sprint(buf, "#%d", m);
21480ee5cbfSDavid du Colombier if(write(w->addr, buf, n) != n)
21580ee5cbfSDavid du Colombier error("error writing addr: %r");
21680ee5cbfSDavid du Colombier n = read(w->data, buf, sizeof buf);
21780ee5cbfSDavid du Colombier if(n <= 0)
21880ee5cbfSDavid du Colombier error("reading data: %r");
21980ee5cbfSDavid du Colombier nr = nrunes(buf, n);
22080ee5cbfSDavid du Colombier while(m+nr >q1){
22180ee5cbfSDavid du Colombier do; while(n>0 && (buf[--n]&0xC0)==0x80);
22280ee5cbfSDavid du Colombier --nr;
22380ee5cbfSDavid du Colombier }
22480ee5cbfSDavid du Colombier if(n == 0)
22580ee5cbfSDavid du Colombier break;
22680ee5cbfSDavid du Colombier memmove(data, buf, n);
22780ee5cbfSDavid du Colombier data += n;
22880ee5cbfSDavid du Colombier *data = 0;
22980ee5cbfSDavid du Colombier m += nr;
23080ee5cbfSDavid du Colombier }
23180ee5cbfSDavid du Colombier }
23280ee5cbfSDavid du Colombier
23380ee5cbfSDavid du Colombier void
windormant(Window * w)23480ee5cbfSDavid du Colombier windormant(Window *w)
23580ee5cbfSDavid du Colombier {
23680ee5cbfSDavid du Colombier if(w->addr >= 0){
23780ee5cbfSDavid du Colombier close(w->addr);
23880ee5cbfSDavid du Colombier w->addr = -1;
23980ee5cbfSDavid du Colombier }
24080ee5cbfSDavid du Colombier if(w->body != nil){
24180ee5cbfSDavid du Colombier Bterm(w->body);
24280ee5cbfSDavid du Colombier w->body = nil;
24380ee5cbfSDavid du Colombier }
24480ee5cbfSDavid du Colombier if(w->data >= 0){
24580ee5cbfSDavid du Colombier close(w->data);
24680ee5cbfSDavid du Colombier w->data = -1;
24780ee5cbfSDavid du Colombier }
24880ee5cbfSDavid du Colombier }
24980ee5cbfSDavid du Colombier
25080ee5cbfSDavid du Colombier
25180ee5cbfSDavid du Colombier int
windel(Window * w,int sure)25280ee5cbfSDavid du Colombier windel(Window *w, int sure)
25380ee5cbfSDavid du Colombier {
25480ee5cbfSDavid du Colombier if(sure)
25580ee5cbfSDavid du Colombier write(w->ctl, "delete\n", 7);
25680ee5cbfSDavid du Colombier else if(write(w->ctl, "del\n", 4) != 4)
25780ee5cbfSDavid du Colombier return 0;
25880ee5cbfSDavid du Colombier /* event proc will die due to read error from event file */
25980ee5cbfSDavid du Colombier windormant(w);
26080ee5cbfSDavid du Colombier close(w->ctl);
26180ee5cbfSDavid du Colombier w->ctl = -1;
26280ee5cbfSDavid du Colombier close(w->event);
26380ee5cbfSDavid du Colombier w->event = -1;
26480ee5cbfSDavid du Colombier return 1;
26580ee5cbfSDavid du Colombier }
26680ee5cbfSDavid du Colombier
26780ee5cbfSDavid du Colombier void
winclean(Window * w)26880ee5cbfSDavid du Colombier winclean(Window *w)
26980ee5cbfSDavid du Colombier {
27080ee5cbfSDavid du Colombier if(w->body)
27180ee5cbfSDavid du Colombier Bflush(w->body);
27280ee5cbfSDavid du Colombier ctlprint(w->ctl, "clean\n");
27380ee5cbfSDavid du Colombier }
27480ee5cbfSDavid du Colombier
27580ee5cbfSDavid du Colombier int
winsetaddr(Window * w,char * addr,int errok)27680ee5cbfSDavid du Colombier winsetaddr(Window *w, char *addr, int errok)
27780ee5cbfSDavid du Colombier {
27880ee5cbfSDavid du Colombier if(w->addr < 0)
27980ee5cbfSDavid du Colombier w->addr = winopenfile(w, "addr");
28080ee5cbfSDavid du Colombier if(write(w->addr, addr, strlen(addr)) < 0){
28180ee5cbfSDavid du Colombier if(!errok)
28280ee5cbfSDavid du Colombier error("error writing addr(%s): %r", addr);
28380ee5cbfSDavid du Colombier return 0;
28480ee5cbfSDavid du Colombier }
28580ee5cbfSDavid du Colombier return 1;
28680ee5cbfSDavid du Colombier }
28780ee5cbfSDavid du Colombier
28880ee5cbfSDavid du Colombier int
winselect(Window * w,char * addr,int errok)28980ee5cbfSDavid du Colombier winselect(Window *w, char *addr, int errok)
29080ee5cbfSDavid du Colombier {
29180ee5cbfSDavid du Colombier if(winsetaddr(w, addr, errok)){
29280ee5cbfSDavid du Colombier ctlprint(w->ctl, "dot=addr\n");
29380ee5cbfSDavid du Colombier return 1;
29480ee5cbfSDavid du Colombier }
29580ee5cbfSDavid du Colombier return 0;
29680ee5cbfSDavid du Colombier }
29780ee5cbfSDavid du Colombier
29880ee5cbfSDavid du Colombier char*
winreadbody(Window * w,int * np)29980ee5cbfSDavid du Colombier winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
30080ee5cbfSDavid du Colombier {
30180ee5cbfSDavid du Colombier char *s;
30280ee5cbfSDavid du Colombier int m, na, n;
30380ee5cbfSDavid du Colombier
30480ee5cbfSDavid du Colombier if(w->body != nil)
30580ee5cbfSDavid du Colombier winclosebody(w);
30680ee5cbfSDavid du Colombier winopenbody(w, OREAD);
30780ee5cbfSDavid du Colombier s = nil;
30880ee5cbfSDavid du Colombier na = 0;
30980ee5cbfSDavid du Colombier n = 0;
31080ee5cbfSDavid du Colombier for(;;){
31180ee5cbfSDavid du Colombier if(na < n+512){
31280ee5cbfSDavid du Colombier na += 1024;
31380ee5cbfSDavid du Colombier s = realloc(s, na+1);
31480ee5cbfSDavid du Colombier }
31580ee5cbfSDavid du Colombier m = Bread(w->body, s+n, na-n);
31680ee5cbfSDavid du Colombier if(m <= 0)
31780ee5cbfSDavid du Colombier break;
31880ee5cbfSDavid du Colombier n += m;
31980ee5cbfSDavid du Colombier }
32080ee5cbfSDavid du Colombier s[n] = 0;
32180ee5cbfSDavid du Colombier winclosebody(w);
32280ee5cbfSDavid du Colombier *np = n;
32380ee5cbfSDavid du Colombier return s;
32480ee5cbfSDavid du Colombier }
325