ref: fbc6ca33a7305c82b720eee9168790d9d937c50d
dir: /win.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <thread.h> #include <regexp.h> #include "mail.h" static int procrd(Biobufhdr *f, void *buf, long len) { return ioread(f->aux, f->fid, buf, len); } static int procwr(Biobufhdr *f, void *buf, long len) { return iowrite(f->aux, f->fid, buf, len); } /* * NB: this function consumes integers with * a trailing space, as generated by acme; * it's not a general purpose number parsing * function. */ static int evgetnum(Biobuf *f) { int c, n; n = 0; while('0'<=(c=Bgetc(f)) && c<='9') n = n*10+(c-'0'); if(c != ' ') sysfatal("event number syntax: %c(%d)", c, c); return n; } static int evgetdata(Biobuf *f, Event *e) { int i, n, o; Rune r; o = 0; n = evgetnum(f); for(i = 0; i < n; i++){ if((r = Bgetrune(f)) == -1) break; o += runetochar(e->text + o, &r); } e->text[o] = 0; return o; } int winevent(Win *w, Event *e) { e->action = Bgetc(w->event); e->type = Bgetc(w->event); e->q0 = evgetnum(w->event); e->q1 = evgetnum(w->event); e->flags = evgetnum(w->event); e->ntext = evgetdata(w->event, e); if(Bgetc(w->event) != '\n') sysfatal("unterminated message"); return e->action; } void winsendevent(Win *w, Event *e) { Bprint(w->event, "%c%c%d %d\n", e->action, e->type, e->q0, e->q1); Bflush(w->event); } int winopen(Win *w, char *f, int mode) { char buf[128]; int fd; snprint(buf, sizeof(buf), "/mnt/wsys/%d/%s", w->id, f); if((fd = open(buf, mode|OCEXEC)) == -1) sysfatal("open %s: %r", buf); return fd; } Biobuf* bwinopen(Win *w, char *f, int mode) { char buf[128]; Biobuf *bfd; snprint(buf, sizeof(buf), "/mnt/wsys/%d/%s", w->id, f); if((bfd = Bopen(buf, mode|OCEXEC)) == nil) sysfatal("open %s: %r", buf); bfd->aux = w->io; Biofn(bfd, (mode == OREAD)?procrd:procwr); return bfd; } Biobuf* bwindata(Win *w, int mode) { int fd; if((fd = dup(w->data, -1)) == -1) sysfatal("dup: %r"); return Bfdopen(fd, mode); } void wininit(Win *w, char *name) { char buf[12]; w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC); if(w->ctl < 0) sysfatal("winopen: %r"); if(read(w->ctl, buf, 12)!=12) sysfatal("read ctl: %r"); if(fprint(w->ctl, "name %s\n", name) == -1) sysfatal("write ctl: %r"); if(fprint(w->ctl, "noscroll\n") == -1) sysfatal("write ctl: %r"); if((w->io = ioproc()) == nil) sysfatal("ioproc alloc: %r"); w->id = atoi(buf); w->event = bwinopen(w, "event", OREAD); w->addr = winopen(w, "addr", ORDWR); w->data = winopen(w, "data", ORDWR); } void winclose(Win *w) { fprint(w->ctl, "del\n"); if(w->data != -1) close(w->data); if(w->addr != -1) close(w->addr); if(w->event != nil) Bterm(w->event); if(w->io) closeioproc(w->io); if(w->ctl != -1) close(w->ctl); } void wintagwrite(Win *w, char *s) { int fd, n; n = strlen(s); fd = winopen(w, "tag", OWRITE); if(write(fd, s, n) != n) sysfatal("tag write: %r"); close(fd); } int wineval(Win *w, char *s, ...) { char buf[25]; va_list arg; va_start(arg, s); vfprint(w->addr, s, arg); va_end(arg); if(pread(w->addr, buf, 24, 0) != 24) return -1; buf[24] = 0; return strtol(buf, nil, 10); } int winread(Win *w, int q0, int q1, char *data, int ndata) { int m, n, nr; char *buf; m = q0; buf = emalloc(Bufsz); while(m < q1){ n = sprint(buf, "#%d", m); if(write(w->addr, buf, n) != n){ fprint(2, "error writing addr: %r"); goto err; } n = read(w->data, buf, Bufsz); if(n <= 0){ fprint(2, "reading data: %r"); goto err; } nr = utfnlen(buf, n); while(m+nr >q1){ do; while(n>0 && (buf[--n]&0xC0)==0x80); --nr; } if(n == 0 || n > ndata) break; memmove(data, buf, n); ndata -= n; data += n; *data = 0; m += nr; } free(buf); return 0; err: free(buf); return -1; } char* winreadsel(Win *w) { int n, q0, q1; char *r; wingetsel(w, &q0, &q1); n = UTFmax*(q1-q0); r = emalloc(n + 1); if(winread(w, q0, q1, r, n) == -1){ free(r); return nil; } return r; } void wingetsel(Win *w, int *q0, int *q1) { char *e, buf[25]; fprint(w->ctl, "addr=dot"); if(pread(w->addr, buf, 24, 0) != 24) sysfatal("read addr: %r"); buf[24] = 0; *q0 = strtol(buf, &e, 10); *q1 = strtol(e, nil, 10); } void winsetsel(Win *w, int q0, int q1) { fprint(w->addr, "#%d,#%d", q0, q1); fprint(w->ctl, "dot=addr"); } static char* expandaddr(Win *w, Event *e) { static char *delim = "/[ \t\\n<>()\\[\\]]/"; char *s; int q0, q1, ns; if(e->q0 != e->q1) return nil; q0 = wineval(w, "#%d-%s", e->q0, delim); if(q0 == -1) /* bad char not found */ q0 = 0; else /* increment past bad char */ q0++; q1 = wineval(w, "#%d+%s", e->q0, delim); if(q1 < 0){ q1 = wineval(w, "$"); if(q1 < 0) return nil; } if(q0 >= q1) return nil; ns = (q1-q0)*UTFmax+1; s = emalloc(ns); winread(w, q0, q1, s, ns); return s; } char* matchaddr(Win *w, Event *e) { char *s; if((s = expandaddr(w, e)) != nil) if(regexec(addrpat, s, nil, 0)) return s; return nil; } int matchmesg(Win *, char *text) { char *p; if(strncmp(text, mbox.path, strlen(mbox.path)) == 0) return 1; if(regexec(mesgpat, text, nil, 0)){ if((p = strchr(text, '/')) != nil) p[1] = 0; return 1; } return 0; }