19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include "win.h"
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier void*
erealloc(void * p,uint n)89a747e4fSDavid du Colombier erealloc(void *p, uint n)
99a747e4fSDavid du Colombier {
109a747e4fSDavid du Colombier p = realloc(p, n);
119a747e4fSDavid du Colombier if(p == nil)
12*1fa40b8eSDavid du Colombier fprint(2, "realloc failed: %r");
139a747e4fSDavid du Colombier return p;
149a747e4fSDavid du Colombier }
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier void
wnew(Win * w)179a747e4fSDavid du Colombier wnew(Win *w)
189a747e4fSDavid du Colombier {
199a747e4fSDavid du Colombier char buf[12];
209a747e4fSDavid du Colombier
219a747e4fSDavid du Colombier w->ctl = open("/mnt/acme/new/ctl", ORDWR);
229a747e4fSDavid du Colombier if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
23*1fa40b8eSDavid du Colombier fprint (2, "can't open window ctl file: %r");
249a747e4fSDavid du Colombier ctlwrite(w, "noscroll\n");
259a747e4fSDavid du Colombier w->winid = atoi(buf);
269a747e4fSDavid du Colombier w->event = openfile(w, "event");
279a747e4fSDavid du Colombier w->addr = -1; /* will be opened when needed */
289a747e4fSDavid du Colombier w->body = nil;
299a747e4fSDavid du Colombier w->data = -1;
309a747e4fSDavid du Colombier }
319a747e4fSDavid du Colombier
329a747e4fSDavid du Colombier int
openfile(Win * w,char * f)339a747e4fSDavid du Colombier openfile(Win *w, char *f)
349a747e4fSDavid du Colombier {
359a747e4fSDavid du Colombier char buf[64];
369a747e4fSDavid du Colombier int fd;
379a747e4fSDavid du Colombier
389a747e4fSDavid du Colombier sprint(buf, "/mnt/acme/%d/%s", w->winid, f);
399a747e4fSDavid du Colombier fd = open(buf, ORDWR|OCEXEC);
409a747e4fSDavid du Colombier if(fd < 0)
41*1fa40b8eSDavid du Colombier fprint (2,"can't open window %s file: %r", f);
429a747e4fSDavid du Colombier return fd;
439a747e4fSDavid du Colombier }
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier void
openbody(Win * w,int mode)469a747e4fSDavid du Colombier openbody(Win *w, int mode)
479a747e4fSDavid du Colombier {
489a747e4fSDavid du Colombier char buf[64];
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier sprint(buf, "/mnt/acme/%d/body", w->winid);
519a747e4fSDavid du Colombier w->body = Bopen(buf, mode|OCEXEC);
529a747e4fSDavid du Colombier if(w->body == nil)
53*1fa40b8eSDavid du Colombier fprint(2,"can't open window body file: %r");
549a747e4fSDavid du Colombier }
559a747e4fSDavid du Colombier
569a747e4fSDavid du Colombier void
wwritebody(Win * w,char * s,int n)579a747e4fSDavid du Colombier wwritebody(Win *w, char *s, int n)
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier if(w->body == nil)
609a747e4fSDavid du Colombier openbody(w, OWRITE);
619a747e4fSDavid du Colombier if(Bwrite(w->body, s, n) != n)
62*1fa40b8eSDavid du Colombier fprint(2,"write error to window: %r");
639a747e4fSDavid du Colombier Bflush(w->body);
649a747e4fSDavid du Colombier }
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier void
wreplace(Win * w,char * addr,char * repl,int nrepl)679a747e4fSDavid du Colombier wreplace(Win *w, char *addr, char *repl, int nrepl)
689a747e4fSDavid du Colombier {
699a747e4fSDavid du Colombier if(w->addr < 0)
709a747e4fSDavid du Colombier w->addr = openfile(w, "addr");
719a747e4fSDavid du Colombier if(w->data < 0)
729a747e4fSDavid du Colombier w->data = openfile(w, "data");
739a747e4fSDavid du Colombier if(write(w->addr, addr, strlen(addr)) < 0){
74*1fa40b8eSDavid du Colombier fprint(2, "mail: warning: badd address %s:%r\n", addr);
759a747e4fSDavid du Colombier return;
769a747e4fSDavid du Colombier }
779a747e4fSDavid du Colombier if(write(w->data, repl, nrepl) != nrepl)
78*1fa40b8eSDavid du Colombier fprint(2, "writing data: %r");
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier
819a747e4fSDavid du Colombier static int
nrunes(char * s,int nb)829a747e4fSDavid du Colombier nrunes(char *s, int nb)
839a747e4fSDavid du Colombier {
849a747e4fSDavid du Colombier int i, n;
859a747e4fSDavid du Colombier Rune r;
869a747e4fSDavid du Colombier
879a747e4fSDavid du Colombier n = 0;
889a747e4fSDavid du Colombier for(i=0; i<nb; n++)
899a747e4fSDavid du Colombier i += chartorune(&r, s+i);
909a747e4fSDavid du Colombier return n;
919a747e4fSDavid du Colombier }
929a747e4fSDavid du Colombier
939a747e4fSDavid du Colombier void
wread(Win * w,uint q0,uint q1,char * data)949a747e4fSDavid du Colombier wread(Win *w, uint q0, uint q1, char *data)
959a747e4fSDavid du Colombier {
969a747e4fSDavid du Colombier int m, n, nr;
979a747e4fSDavid du Colombier char buf[256];
989a747e4fSDavid du Colombier
999a747e4fSDavid du Colombier if(w->addr < 0)
1009a747e4fSDavid du Colombier w->addr = openfile(w, "addr");
1019a747e4fSDavid du Colombier if(w->data < 0)
1029a747e4fSDavid du Colombier w->data = openfile(w, "data");
1039a747e4fSDavid du Colombier m = q0;
1049a747e4fSDavid du Colombier while(m < q1){
1059a747e4fSDavid du Colombier n = sprint(buf, "#%d", m);
1069a747e4fSDavid du Colombier if(write(w->addr, buf, n) != n)
107*1fa40b8eSDavid du Colombier fprint(2,"writing addr: %r");
1089a747e4fSDavid du Colombier n = read(w->data, buf, sizeof buf);
1099a747e4fSDavid du Colombier if(n <= 0)
110*1fa40b8eSDavid du Colombier fprint(2,"reading data: %r");
1119a747e4fSDavid du Colombier nr = nrunes(buf, n);
1129a747e4fSDavid du Colombier while(m+nr >q1){
1139a747e4fSDavid du Colombier do; while(n>0 && (buf[--n]&0xC0)==0x80);
1149a747e4fSDavid du Colombier --nr;
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier if(n == 0)
1179a747e4fSDavid du Colombier break;
1189a747e4fSDavid du Colombier memmove(data, buf, n);
1199a747e4fSDavid du Colombier data += n;
1209a747e4fSDavid du Colombier *data = 0;
1219a747e4fSDavid du Colombier m += nr;
1229a747e4fSDavid du Colombier }
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier void
wselect(Win * w,char * addr)1269a747e4fSDavid du Colombier wselect(Win *w, char *addr)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier if(w->addr < 0)
1299a747e4fSDavid du Colombier w->addr = openfile(w, "addr");
1309a747e4fSDavid du Colombier if(write(w->addr, addr, strlen(addr)) < 0)
131*1fa40b8eSDavid du Colombier fprint(2,"writing addr");
1329a747e4fSDavid du Colombier ctlwrite(w, "dot=addr\n");
1339a747e4fSDavid du Colombier }
1349a747e4fSDavid du Colombier
1359a747e4fSDavid du Colombier void
wtagwrite(Win * w,char * s,int n)1369a747e4fSDavid du Colombier wtagwrite(Win *w, char *s, int n)
1379a747e4fSDavid du Colombier {
1389a747e4fSDavid du Colombier int fd;
1399a747e4fSDavid du Colombier
1409a747e4fSDavid du Colombier fd = openfile(w, "tag");
1419a747e4fSDavid du Colombier if(write(fd, s, n) != n)
142*1fa40b8eSDavid du Colombier fprint(2,"tag write: %r");
1439a747e4fSDavid du Colombier close(fd);
1449a747e4fSDavid du Colombier }
1459a747e4fSDavid du Colombier
1469a747e4fSDavid du Colombier void
ctlwrite(Win * w,char * s)1479a747e4fSDavid du Colombier ctlwrite(Win *w, char *s)
1489a747e4fSDavid du Colombier {
1499a747e4fSDavid du Colombier int n;
1509a747e4fSDavid du Colombier
1519a747e4fSDavid du Colombier n = strlen(s);
1529a747e4fSDavid du Colombier if(write(w->ctl, s, n) != n)
153*1fa40b8eSDavid du Colombier fprint(2,"write error to ctl file: %r");
1549a747e4fSDavid du Colombier }
1559a747e4fSDavid du Colombier
1569a747e4fSDavid du Colombier int
wdel(Win * w)1579a747e4fSDavid du Colombier wdel(Win *w)
1589a747e4fSDavid du Colombier {
1599a747e4fSDavid du Colombier if(write(w->ctl, "del\n", 4) != 4)
1609a747e4fSDavid du Colombier return False;
1619a747e4fSDavid du Colombier wdormant(w);
1629a747e4fSDavid du Colombier close(w->ctl);
1639a747e4fSDavid du Colombier w->ctl = -1;
1649a747e4fSDavid du Colombier close(w->event);
1659a747e4fSDavid du Colombier w->event = -1;
1669a747e4fSDavid du Colombier return True;
1679a747e4fSDavid du Colombier }
1689a747e4fSDavid du Colombier
1699a747e4fSDavid du Colombier void
wname(Win * w,char * s)1709a747e4fSDavid du Colombier wname(Win *w, char *s)
1719a747e4fSDavid du Colombier {
1729a747e4fSDavid du Colombier char buf[128];
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier sprint(buf, "name %s\n", s);
1759a747e4fSDavid du Colombier ctlwrite(w, buf);
1769a747e4fSDavid du Colombier }
1779a747e4fSDavid du Colombier
1789a747e4fSDavid du Colombier void
wclean(Win * w)1799a747e4fSDavid du Colombier wclean(Win *w)
1809a747e4fSDavid du Colombier {
1819a747e4fSDavid du Colombier if(w->body)
1829a747e4fSDavid du Colombier Bflush(w->body);
1839a747e4fSDavid du Colombier ctlwrite(w, "clean\n");
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier void
wdormant(Win * w)1879a747e4fSDavid du Colombier wdormant(Win *w)
1889a747e4fSDavid du Colombier {
1899a747e4fSDavid du Colombier if(w->addr >= 0){
1909a747e4fSDavid du Colombier close(w->addr);
1919a747e4fSDavid du Colombier w->addr = -1;
1929a747e4fSDavid du Colombier }
1939a747e4fSDavid du Colombier if(w->body != nil){
1949a747e4fSDavid du Colombier Bterm(w->body);
1959a747e4fSDavid du Colombier w->body = nil;
1969a747e4fSDavid du Colombier }
1979a747e4fSDavid du Colombier if(w->data >= 0){
1989a747e4fSDavid du Colombier close(w->data);
1999a747e4fSDavid du Colombier w->data = -1;
2009a747e4fSDavid du Colombier }
2019a747e4fSDavid du Colombier }
2029a747e4fSDavid du Colombier
2039a747e4fSDavid du Colombier int
getec(Win * w)2049a747e4fSDavid du Colombier getec(Win *w)
2059a747e4fSDavid du Colombier {
2069a747e4fSDavid du Colombier if(w->nbuf == 0){
2079a747e4fSDavid du Colombier w->nbuf = read(w->event, w->buf, sizeof w->buf);
2089a747e4fSDavid du Colombier if(w->nbuf <= 0)
209*1fa40b8eSDavid du Colombier fprint(2,"event read error: %r");
2109a747e4fSDavid du Colombier w->bufp = w->buf;
2119a747e4fSDavid du Colombier }
2129a747e4fSDavid du Colombier w->nbuf--;
2139a747e4fSDavid du Colombier return *w->bufp++;
2149a747e4fSDavid du Colombier }
2159a747e4fSDavid du Colombier
2169a747e4fSDavid du Colombier int
geten(Win * w)2179a747e4fSDavid du Colombier geten(Win *w)
2189a747e4fSDavid du Colombier {
2199a747e4fSDavid du Colombier int n, c;
2209a747e4fSDavid du Colombier
2219a747e4fSDavid du Colombier n = 0;
2229a747e4fSDavid du Colombier while('0'<=(c=getec(w)) && c<='9')
2239a747e4fSDavid du Colombier n = n*10+(c-'0');
2249a747e4fSDavid du Colombier if(c != ' ')
225*1fa40b8eSDavid du Colombier fprint(2, "event number syntax");
2269a747e4fSDavid du Colombier return n;
2279a747e4fSDavid du Colombier }
2289a747e4fSDavid du Colombier
2299a747e4fSDavid du Colombier int
geter(Win * w,char * buf,int * nb)2309a747e4fSDavid du Colombier geter(Win *w, char *buf, int *nb)
2319a747e4fSDavid du Colombier {
2329a747e4fSDavid du Colombier Rune r;
2339a747e4fSDavid du Colombier int n;
2349a747e4fSDavid du Colombier
2359a747e4fSDavid du Colombier r = getec(w);
2369a747e4fSDavid du Colombier buf[0] = r;
2379a747e4fSDavid du Colombier n = 1;
2389a747e4fSDavid du Colombier if(r < Runeself)
2399a747e4fSDavid du Colombier goto Return;
2409a747e4fSDavid du Colombier while(!fullrune(buf, n))
2419a747e4fSDavid du Colombier buf[n++] = getec(w);
2429a747e4fSDavid du Colombier chartorune(&r, buf);
2439a747e4fSDavid du Colombier Return:
2449a747e4fSDavid du Colombier *nb = n;
2459a747e4fSDavid du Colombier return r;
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier
2489a747e4fSDavid du Colombier
2499a747e4fSDavid du Colombier void
wevent(Win * w,Event * e)2509a747e4fSDavid du Colombier wevent(Win *w, Event *e)
2519a747e4fSDavid du Colombier {
2529a747e4fSDavid du Colombier int i, nb;
2539a747e4fSDavid du Colombier
2549a747e4fSDavid du Colombier e->c1 = getec(w);
2559a747e4fSDavid du Colombier e->c2 = getec(w);
2569a747e4fSDavid du Colombier e->q0 = geten(w);
2579a747e4fSDavid du Colombier e->q1 = geten(w);
2589a747e4fSDavid du Colombier e->flag = geten(w);
2599a747e4fSDavid du Colombier e->nr = geten(w);
2609a747e4fSDavid du Colombier if(e->nr > EVENTSIZE)
261*1fa40b8eSDavid du Colombier fprint(2, "wevent: event string too long");
2629a747e4fSDavid du Colombier e->nb = 0;
2639a747e4fSDavid du Colombier for(i=0; i<e->nr; i++){
2649a747e4fSDavid du Colombier e->r[i] = geter(w, e->b+e->nb, &nb);
2659a747e4fSDavid du Colombier e->nb += nb;
2669a747e4fSDavid du Colombier }
2679a747e4fSDavid du Colombier e->r[e->nr] = 0;
2689a747e4fSDavid du Colombier e->b[e->nb] = 0;
2699a747e4fSDavid du Colombier if(getec(w) != '\n')
270*1fa40b8eSDavid du Colombier fprint(2, "wevent: event syntax 2");
2719a747e4fSDavid du Colombier }
2729a747e4fSDavid du Colombier
2739a747e4fSDavid du Colombier void
wslave(Win * w,Channel * ce)2749a747e4fSDavid du Colombier wslave(Win *w, Channel *ce)
2759a747e4fSDavid du Colombier {
2769a747e4fSDavid du Colombier Event e;
2779a747e4fSDavid du Colombier
2789a747e4fSDavid du Colombier while(recv(ce, &e) >= 0)
2799a747e4fSDavid du Colombier wevent(w, &e);
2809a747e4fSDavid du Colombier }
2819a747e4fSDavid du Colombier
2829a747e4fSDavid du Colombier void
wwriteevent(Win * w,Event * e)2839a747e4fSDavid du Colombier wwriteevent(Win *w, Event *e)
2849a747e4fSDavid du Colombier {
285*1fa40b8eSDavid du Colombier fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
2869a747e4fSDavid du Colombier }
2879a747e4fSDavid du Colombier
2889a747e4fSDavid du Colombier int
wreadall(Win * w,char ** sp)2899a747e4fSDavid du Colombier wreadall(Win *w, char **sp)
2909a747e4fSDavid du Colombier {
2919a747e4fSDavid du Colombier char *s;
2929a747e4fSDavid du Colombier int m, na, n;
2939a747e4fSDavid du Colombier
2949a747e4fSDavid du Colombier if(w->body != nil)
2959a747e4fSDavid du Colombier Bterm(w->body);
2969a747e4fSDavid du Colombier openbody(w, OREAD);
2979a747e4fSDavid du Colombier s = nil;
2989a747e4fSDavid du Colombier na = 0;
2999a747e4fSDavid du Colombier n = 0;
3009a747e4fSDavid du Colombier for(;;){
3019a747e4fSDavid du Colombier if(na < n+512){
3029a747e4fSDavid du Colombier na += 1024;
3039a747e4fSDavid du Colombier s = erealloc(s, na+1);
3049a747e4fSDavid du Colombier }
3059a747e4fSDavid du Colombier m = Bread(w->body, s+n, na-n);
3069a747e4fSDavid du Colombier if(m <= 0)
3079a747e4fSDavid du Colombier break;
3089a747e4fSDavid du Colombier n += m;
3099a747e4fSDavid du Colombier }
3109a747e4fSDavid du Colombier s[n] = 0;
3119a747e4fSDavid du Colombier Bterm(w->body);
3129a747e4fSDavid du Colombier w->body = nil;
3139a747e4fSDavid du Colombier *sp = s;
3149a747e4fSDavid du Colombier return n;
3159a747e4fSDavid du Colombier }
316