diff options
Diffstat (limited to 'src/cmd/acme/mail/win.c')
-rw-r--r-- | src/cmd/acme/mail/win.c | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/src/cmd/acme/mail/win.c b/src/cmd/acme/mail/win.c new file mode 100644 index 00000000..73df95a2 --- /dev/null +++ b/src/cmd/acme/mail/win.c @@ -0,0 +1,397 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include <plumb.h> +#include <9pclient.h> /* jpc */ +#include "dat.h" + +extern CFsys *acmefs; /* jpc */ + +Window* +newwindow(void) +{ + char buf[12]; + Window *w; + int n = 0; + + w = emalloc(sizeof(Window)); +/* jpc + w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC); + if(w->ctl<0 || read(w->ctl, buf, 12)!=12) + error("can't open window ctl file: %r"); +*/ +/* w->ctl = fsopenfd(acmefs, "new/ctl", ORDWR|OCEXEC); + if(w->ctl<0 || (n = read(w->ctl, buf, 12))!=12) { + fprint(2,"%d bytes read from %d\n",n,w->ctl); + error("can't open window ctl file: %r"); + } + jpc end */ + w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC); + if(w->ctl == nil || (n = fsread(w->ctl, buf, 12))!=12) { + fprint(2,"%d bytes read from %d\n",n,w->ctl); + error("can't open window ctl file: %r"); + } + + ctlprint(w->ctl, "noscroll\n"); + w->id = atoi(buf); + w->event = winopenfid(w, "event"); + w->addr = nil; /* will be opened when needed */ + w->body = nil; + w->data = nil; + w->cevent = chancreate(sizeof(Event*), 0); + return w; +} + +void +winsetdump(Window *w, char *dir, char *cmd) +{ + if(dir != nil) + ctlprint(w->ctl, "dumpdir %s\n", dir); + if(cmd != nil) + ctlprint(w->ctl, "dump %s\n", cmd); +} + +void +wineventproc(void *v) +{ + Window *w; + int i; + + w = v; + for(i=0; ; i++){ + if(i >= NEVENT) + i = 0; + wingetevent(w, &w->e[i]); + sendp(w->cevent, &w->e[i]); + } +} + +static CFid* +winopenfid1(Window *w, char *f, int m) +{ + char buf[64]; + CFid* fd; + + sprint(buf, "%d/%s", w->id, f); + fd = fsopen(acmefs, buf, m|OCEXEC); + if(fd == nil) + error("can't open window file %s: %r", f); + return fd; +} + +static int +winopenfile1(Window *w, char *f, int m) +{ + char buf[64]; + int fd; + +/* jpc + sprint(buf, "/mnt/wsys/%d/%s", w->id, f); + fd = open(buf, m|OCEXEC); +*/ + sprint(buf, "%d/%s", w->id, f); + fd = fsopenfd(acmefs, buf, m|OCEXEC); + if(fd < 0) + error("can't open window file %s: %r", f); + return fd; +} + +CFid* +winopenfid(Window *w, char *f) +{ + return winopenfid1(w, f, ORDWR); +} + +int +winopenfile(Window *w, char *f) +{ + return winopenfile1(w, f, ORDWR); +} + +void +wintagwrite(Window *w, char *s, int n) +{ + CFid* fid; + + fid = winopenfid(w, "tag"); + if(fswrite(fid, s, n) != n) + error("tag write: %r"); + fsclose(fid); +} + +void +winname(Window *w, char *s) +{ + ctlprint(w->ctl, "name %s\n", s); +} + +void +winopenbody(Window *w, int mode) +{ + char buf[256]; + CFid* fid; + +/* jpc + sprint(buf, "/mnt/wsys/%d/body", w->id); + w->body = Bopen(buf, mode|OCEXEC); +*/ + sprint(buf, "%d/body", w->id); + fid = fsopen(acmefs,buf, mode|OCEXEC); + w->body = fid; // jpcBfdopen(id, mode|OCEXEC); + if(w->body == nil) + error("can't open window body file: %r"); +} + +void +winclosebody(Window *w) +{ + if(w->body != nil){ + // jpc Bterm(w->body); + fsclose(w->body); + w->body = nil; + } +} + +void +winwritebody(Window *w, char *s, int n) +{ + if(w->body == nil) + winopenbody(w, OWRITE); + // jpc if(Bwrite(w->body, s, n) != n) + if(fswrite(w->body, s, n) != n) + error("write error to window: %r"); +} + +int +wingetec(Window *w) +{ + if(w->nbuf == 0){ + w->nbuf = fsread(w->event, w->buf, sizeof w->buf); + if(w->nbuf <= 0){ + /* probably because window has exited, and only called by wineventproc, so just shut down */ + threadexits(nil); + } + w->bufp = w->buf; + } + w->nbuf--; + return *w->bufp++; +} + +int +wingeten(Window *w) +{ + int n, c; + + n = 0; + while('0'<=(c=wingetec(w)) && c<='9') + n = n*10+(c-'0'); + if(c != ' ') + error("event number syntax"); + return n; +} + +int +wingeter(Window *w, char *buf, int *nb) +{ + Rune r; + int n; + + r = wingetec(w); + buf[0] = r; + n = 1; + if(r >= Runeself) { + while(!fullrune(buf, n)) + buf[n++] = wingetec(w); + chartorune(&r, buf); + } + *nb = n; + return r; +} + +void +wingetevent(Window *w, Event *e) +{ + int i, nb; + + e->c1 = wingetec(w); + e->c2 = wingetec(w); + e->q0 = wingeten(w); + e->q1 = wingeten(w); + e->flag = wingeten(w); + e->nr = wingeten(w); + if(e->nr > EVENTSIZE) + error("event string too long"); + e->nb = 0; + for(i=0; i<e->nr; i++){ + e->r[i] = wingeter(w, e->b+e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if(wingetec(w) != '\n') + error("event syntax error"); +} + +void +winwriteevent(Window *w, Event *e) +{ + fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); +} + +void +winread(Window *w, uint q0, uint q1, char *data) +{ + int m, n, nr; + char buf[256]; + + if(w->addr == nil) + w->addr = winopenfid(w, "addr"); + if(w->data == nil) + w->data = winopenfid(w, "data"); + m = q0; + while(m < q1){ + n = sprint(buf, "#%d", m); + if(fswrite(w->addr, buf, n) != n) + error("error writing addr: %r"); + n = fsread(w->data, buf, sizeof buf); + if(n <= 0) + error("reading data: %r"); + nr = utfnlen(buf, n); + while(m+nr >q1){ + do; while(n>0 && (buf[--n]&0xC0)==0x80); + --nr; + } + if(n == 0) + break; + memmove(data, buf, n); + data += n; + *data = 0; + m += nr; + } +} + +void +windormant(Window *w) +{ + if(w->addr != nil){ + fsclose(w->addr); + w->addr = nil; + } + if(w->body != nil){ + fsclose(w->body); + w->body = nil; + } + if(w->data != nil){ + fsclose(w->data); + w->data = nil; + } +} + + +int +windel(Window *w, int sure) +{ + if(sure) { + fswrite(w->ctl, "delete\n", 7); + // fsync(w->ctl); + } + else if(fswrite(w->ctl, "del\n", 4) != 4) { + // fsync(w->ctl); + return 0; + } + /* event proc will die due to read error from event file */ + windormant(w); + fsclose(w->ctl); + w->ctl = nil; + fsclose(w->event); + w->event = nil; + return 1; +} + +void +winclean(Window *w) +{ + // int fd; + // if(w->body) + // Bflush(w->body); + ctlprint(w->ctl, "clean\n"); +} + +int +winsetaddr(Window *w, char *addr, int errok) +{ + if(w->addr == nil) + w->addr = winopenfid(w, "addr"); + if(fswrite(w->addr, addr, strlen(addr)) < 0){ + if(!errok) + error("error writing addr(%s): %r", addr); + return 0; + } + return 1; +} + +int +winselect(Window *w, char *addr, int errok) +{ + if(winsetaddr(w, addr, errok)){ + ctlprint(w->ctl, "dot=addr\n"); + return 1; + } + return 0; +} + +char* +winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */ +{ + char *s; + int m, na, n; + + if(w->body != nil) + winclosebody(w); + winopenbody(w, OREAD); + s = nil; + na = 0; + n = 0; + for(;;){ + if(na < n+512){ + na += 1024; + s = realloc(s, na+1); + } + // jpc m = Bread(w->body, s+n, na-n); + m = fsread(w->body, s+n, na-n); + if(m <= 0) + break; + n += m; + } + s[n] = 0; + winclosebody(w); + *np = n; + return s; +} + +char* +winselection(Window *w) +{ + int m, n; + char *buf; + char tmp[256]; + CFid* fid; + + fid = winopenfid1(w, "rdsel", OREAD); + if(fid == nil) + error("can't open rdsel: %r"); + n = 0; + buf = nil; + for(;;){ + m = fsread(fid, tmp, sizeof tmp); + if(m <= 0) + break; + buf = erealloc(buf, n+m+1); + memmove(buf+n, tmp, m); + n += m; + buf[n] = '\0'; + } + fsclose(fid); + return buf; +} |