diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-04-14 17:27:24 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-04-14 17:27:24 +0000 |
commit | a150899221a5badff9740703b754f901b4f52762 (patch) | |
tree | 3d6911874b0ee763e40490d04f56fc09d89ccfa6 /acme/bin/source/adict | |
parent | 71cfa9c637386ebe00fc6d1bf6215db6657559f4 (diff) | |
download | plan9front-a150899221a5badff9740703b754f901b4f52762.tar.xz |
fill /acme
Diffstat (limited to 'acme/bin/source/adict')
-rw-r--r-- | acme/bin/source/adict/_adict.c | 584 | ||||
-rw-r--r-- | acme/bin/source/adict/_win.c | 315 | ||||
-rw-r--r-- | acme/bin/source/adict/adict.c | 591 | ||||
-rw-r--r-- | acme/bin/source/adict/adict.h | 10 | ||||
-rw-r--r-- | acme/bin/source/adict/man | 26 | ||||
-rw-r--r-- | acme/bin/source/adict/mkfile | 11 | ||||
-rw-r--r-- | acme/bin/source/adict/win.c | 315 | ||||
-rw-r--r-- | acme/bin/source/adict/win.h | 59 |
8 files changed, 1911 insertions, 0 deletions
diff --git a/acme/bin/source/adict/_adict.c b/acme/bin/source/adict/_adict.c new file mode 100644 index 000000000..f2c14f5ea --- /dev/null +++ b/acme/bin/source/adict/_adict.c @@ -0,0 +1,584 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include "win.h" +#include "adict.h" + +char *prog = "adict"; +char *lprog = "/bin/adict"; +char *xprog = "/bin/dict"; +char *dict, *pattern, *curaddr[MAXMATCH], *curone, *args[6], buffer[80]; +char abuffer[80], fbuffer[80], pbuffer[80]; +int curindex, count, Eopen, Mopen; +Win Mwin, Ewin, Dwin; + +void openwin(char*, char*, Win*, int); +void handle(Win*, int); +void rexec(void*); +void pexec(void*); +int getaddr(char*); + +void +usage(void) +{ + threadprint(2, "usage: %s [-d dictname] [pattern]\n", argv0); + threadexitsall(nil); +} + +void +threadmain(int argc, char** argv) +{ + ARGBEGIN{ + case 'd': + dict = strdup(ARGF()); + break; + default: + usage(); + }ARGEND + + /* if running as other name, note that fact */ + if(access(argv0, AEXIST) == 0) + lprog = argv0; + + switch(argc){ + case 1: + pattern = pbuffer; + strcpy(pattern,argv[0]); + if(dict == nil) + dict = "oed"; + break; + case 0: + break; + default: + usage(); + } + + if ((dict == nil) && (pattern == nil)) + openwin(prog,"", &Dwin, Dictwin); + if (pattern == nil) + openwin(prog,"",&Ewin, Entrywin); + if ((count = getaddr(pattern)) <= 1) + openwin(prog,"Prev Next", &Ewin, Entrywin); + else + openwin(prog, "", &Mwin, Matchwin); +} + +static int +procrexec(char *xprog, ...) +{ + int fpipe[2]; + void *rexarg[4]; + Channel *c; + va_list va; + int i; + char *p; + + pipe(fpipe); + va_start(va, xprog); + p = xprog; + for(i=0; p && i+1<nelem(args); i++){ + args[i] = p; + p = va_arg(va, char*); + } + args[i] = nil; + + c = chancreate(sizeof(ulong), 0); + rexarg[0] = xprog; + rexarg[1] = args; + rexarg[2] = fpipe; + rexarg[3] = c; + + proccreate(rexec, rexarg, 8192); + recvul(c); + chanfree(c); + close(fpipe[1]); + return fpipe[0]; +} + +int +getaddr(char *pattern) +{ + /* Get char offset into dictionary of matches. */ + + int fd, i; + Biobuf inbuf; + char *bufptr; +char *obuf; + + if (pattern == nil) { + curone = nil; + curindex = 0; + curaddr[curindex] = nil; + return 0; + } + + sprint(buffer,"/%s/A", pattern); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + Binit(&inbuf, fd, OREAD); + i = 0; + curindex = 0; + while ((bufptr = Brdline(&inbuf, '\n')) != nil && (i < (MAXMATCH-1))) { + bufptr[Blinelen(&inbuf)-1] = 0; +obuf=bufptr; + while (bufptr[0] != '#' && bufptr[0] != 0) bufptr++; +if(bufptr[0] == 0) + print("whoops buf «%s»\n", obuf); + curaddr[i] = malloc(strlen(bufptr)); + strcpy(curaddr[i], bufptr); + i++; + } + curaddr[i] = nil; + if (i == MAXMATCH) + threadprint(2, "Too many matches!\n"); + Bterm(&inbuf); + close(fd); + + curone = curaddr[curindex]; + return(i); +} + +char* +getpattern(char *addr) +{ + /* Get the pattern corresponding to an absolute address.*/ + int fd; + char *res, *t; + + res = nil; + sprint(buffer,"%sh", addr); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + if (read(fd, pbuffer, 80) > 80) + threadprint(2, "Error in getting addres from dict.\n"); + else { + t = pbuffer; + /* remove trailing whitespace, newline */ + if (t != nil){ + while(*t != 0 && *t != '\n') + t++; + if(t == 0 && t > pbuffer) + t--; + while(t >= pbuffer && (*t==' ' || *t=='\n' || *t=='\t' || *t=='\r')) + *t-- = 0; + } + res = pbuffer; + } + close(fd); + return(res); +} + +char* +chgaddr(int dir) +{ + /* Increment or decrement the current address (curone). */ + + int fd; + char *res, *t; + + res = nil; + if (dir < 0) + sprint(buffer,"%s-a", curone); + else + sprint(buffer,"%s+a", curone); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + if (read(fd, abuffer, 80) > 80) + threadprint(2, "Error in getting addres from dict.\n"); + else { + res = abuffer; + while (*res != '#') res++; + t = res; + while ((*t != '\n') && (t != nil)) t++; + if (t != nil) *t = 0; + } + close(fd); + return(res); +} + +void +dispdicts(Win *cwin) +{ + /* Display available dictionaries in window. */ + + int fd, nb, i; + char buf[1024], *t; + + fd = procrexec(xprog, "-d", "?", nil); + wreplace(cwin, "0,$","",0); /* Clear window */ + while ((nb = read(fd, buf, 1024)) > 0) { + t = buf; + i = 0; + if (strncmp("Usage", buf, 5) == 0) { /* Remove first line. */ + while (t[0] != '\n') { + t++; + i++; + } + t++; + i++; + } + wwritebody(cwin, t, nb-i); + } + close(fd); + wclean(cwin); +} + +void +dispentry(Win *cwin) +{ + /* Display the current selection in window. */ + + int fd, nb; + char buf[BUFSIZE]; + + if (curone == nil) { + if (pattern != nil) { + sprint(buf,"Pattern not found.\n"); + wwritebody(cwin, buf, 19); + wclean(cwin); + } + return; + } + sprint(buffer,"%sp", curone); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + wreplace(cwin, "0,$","",0); /* Clear window */ + while ((nb = read(fd, buf, BUFSIZE)) > 0) { + wwritebody(cwin, buf, nb); + } + close(fd); + wclean(cwin); +} + +void +dispmatches(Win *cwin) +{ + /* Display the current matches. */ + + int fd, nb; + char buf[BUFSIZE]; + + sprint(buffer,"/%s/H", pattern); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + while ((nb = read(fd, buf, BUFSIZE)) > 0) + wwritebody(cwin, buf, nb); + close(fd); + wclean(cwin); +} + +char* +format(char *s) +{ + /* Format a string to be written in window tag. Acme doesn't like */ + /* non alpha-num's in the tag line. */ + + char *t, *h; + + t = fbuffer; + if (s == nil) { + *t = 0; + return t; + } + strcpy(t, s); + h = t; + while (*t != 0) { + if (!(((*t >= 'a') && (*t <= 'z')) || + ((*t >= 'A') && (*t <= 'Z')) || + ((*t >= '0') && (*t <= '9')))) + *t = '_'; + t++; + } + if (strlen(h) > MAXTAG) + h[MAXTAG] = 0; + if (strcmp(s,h) == 0) return s; + return h; +} + +void +openwin(char *name, char *buttons, Win *twin, int wintype) +{ + char buf[80]; + + wnew(twin); + if (wintype == Dictwin) + sprint(buf,"%s",name); + else + if ((wintype == Entrywin) && (count > 1)) + sprint(buf,"%s/%s/%s/%d",name, dict, format(pattern), curindex+1); + else + sprint(buf,"%s/%s/%s",name, dict, format(pattern)); + wname(twin, buf); + wtagwrite(twin, buttons, strlen(buttons)); + wclean(twin); + wdormant(twin); + if (wintype == Dictwin) + dispdicts(twin); + if (wintype == Matchwin) { + Mopen = True; + dispmatches(twin); + } + if (wintype == Entrywin) { + Eopen = True; + dispentry(twin); + } + handle(twin, wintype); +} + +void +vopenwin(void *v) +{ + void **arg; + char *name, *buttons; + Win *twin; + int wintype; + + arg = v; + name = arg[0]; + buttons = arg[1]; + twin = arg[2]; + wintype = (int)arg[3]; + sendul(arg[4], 0); + + openwin(name, buttons, twin, wintype); + threadexits(nil); +} + +void +procopenwin(char *name, char *buttons, Win *twin, int wintype) +{ + void *arg[5]; + Channel *c; + + c = chancreate(sizeof(ulong), 0); + arg[0] = name; + arg[1] = buttons; + arg[2] = twin; + arg[3] = (void*)wintype; + arg[4] = c; + proccreate(vopenwin, arg, 8192); + recvul(c); + chanfree(c); +} + +void +rexec(void *v) +{ + void **arg; + char *prog; + char **args; + int *fd; + Channel *c; + + arg = v; + prog = arg[0]; + args = arg[1]; + fd = arg[2]; + c = arg[3]; + + rfork(RFENVG|RFFDG); + dup(fd[1], 1); + close(fd[1]); + close(fd[0]); + procexec(c, prog, args); + threadprint(2, "Remote pipe execution failed: %s %r\n", prog); +abort(); + threadexits(nil); +} + +void +pexec(void *v) +{ + void **arg; + char *prog; + char **args; + Channel *c; + + arg = v; + prog = arg[0]; + args = arg[1]; + c = arg[2]; + + procexec(c, prog, args); + threadprint(2, "Remote execution failed: %s %r\n", prog); +abort(); + threadexits(nil); +} + +void +procpexec(char *prog, char **args) +{ + void *rexarg[4]; + Channel *c; + + c = chancreate(sizeof(ulong), 0); + rexarg[0] = prog; + rexarg[1] = args; + rexarg[2] = c; + + proccreate(pexec, rexarg, 8192); + recvul(c); + chanfree(c); +} + +void +kill(void) +{ + /* Kill all processes related to this one. */ + int fd; + + sprint(buffer, "/proc/%d/notepg", getpid()); + fd = open(buffer, OWRITE); + rfork(RFNOTEG); + write(fd, "kill", 4); +} + +int +command(char *com, Win *w, int wintype) +{ + char *buf; + + if (strncmp(com, "Del", 3) == 0) { + switch(wintype){ + case Entrywin: + if (wdel(w)) { + Eopen = False; + threadexits(nil); + } + break; + case Dictwin: + if (wdel(w)) + threadexits(nil); + break; + case Matchwin: + kill(); + if (Eopen) + if (~wdel(&Ewin)) /* Remove the entry window */ + wdel(&Ewin); + if (!wdel(w)) + wdel(w); + threadexits(nil); + break; + } + return True; + } + if (strncmp(com, "Next", 4) == 0){ + if (curone != nil) { + curone = chgaddr(1); + buf = getpattern(curone); + sprint(buffer,"%s/%s/%s", prog, dict, format(buf)); + wname(w, buffer); + dispentry(w); + } + return True; + } + if (strncmp(com, "Prev",4) == 0){ + if (curone != nil) { + curone = chgaddr(-1); + buf = getpattern(curone); + sprint(buffer,"%s/%s/%s", prog, dict, format(buf)); + wname(w, buffer); + dispentry(w); + } + return True; + } + if (strncmp(com, "Nmatch",6) == 0){ + if (curaddr[++curindex] == nil) + curindex = 0; + curone = curaddr[curindex]; + if (curone != nil) { + sprint(buffer,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1); + wname(w, buffer); + dispentry(w); + } + return True; + } + return False; +} + +void +handle(Win *w, int wintype) +{ + Event e, e2, ea, etoss; + char *s, *t, buf[80]; + int tmp, na; + + while (True) { + wevent(w, &e); + switch(e.c2){ + default: + /* threadprint(2,"unknown message %c%c\n", e.c1, e.c2); */ + break; + case 'i': + /* threadprint(2,"'%s' inserted in tag at %d\n", e.b, e.q0);*/ + break; + case 'I': + /* threadprint(2,"'%s' inserted in body at %d\n", e.b, e.q0);*/ + break; + case 'd': + /* threadprint(2, "'%s' deleted in tag at %d\n", e.b, e.q0);*/ + break; + case 'D': + /* threadprint(2, "'%s' deleted in body at %d\n", e.b, e.q0);*/ + break; + case 'x': + case 'X': /* Execute command. */ + if (e.flag & 2) + wevent(w, &e2); + if(e.flag & 8){ + wevent(w, &ea); + wevent(w, &etoss); + na = ea.nb; + } else + na = 0; + s = e.b; + if ((e.flag & 2) && e.nb == 0) + s = e2.b; + if(na){ + t = malloc(strlen(s)+1+na+1); + snprint(t, strlen(s)+1+na+1, "%s %s", s, ea.b); + s = t; + } + /* if it's a long message, it can't be for us anyway */ + if(!command(s, w, wintype)) /* send it back */ + wwriteevent(w, &e); + if(na) + free(s); + break; + case 'l': + case 'L': /* Look for something. */ + if (e.flag & 2) + wevent(w, &e); + wclean(w); /* Set clean bit. */ + if (wintype == Dictwin) { + strcpy(buf, e.b); + args[0] = lprog; + args[1] = "-d"; + args[2] = buf; + args[3] = nil; + procpexec(lprog, args); /* New adict with chosen dict. */ + } + if (wintype == Entrywin) { + strcpy(buf, e.b); + args[0] = lprog; + args[1] = "-d"; + args[2] = dict; + args[3] = buf; + args[4] = nil; + procpexec(lprog, args); /* New adict with chosen pattern. */ + } + if (wintype == Matchwin) { + tmp = atoi(e.b) - 1; + if ((tmp >= 0) && (tmp < MAXMATCH) && (curaddr[tmp] != nil)) { + curindex = tmp; + curone = curaddr[curindex]; + /* Display selected match. */ + if (Eopen) { + sprint(buf,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1); + wname(&Ewin, buf); + dispentry(&Ewin); + } + else + procopenwin(prog,"Nmatch Prev Next", &Ewin, Entrywin); + } + } + break; + } + } +} diff --git a/acme/bin/source/adict/_win.c b/acme/bin/source/adict/_win.c new file mode 100644 index 000000000..18657c572 --- /dev/null +++ b/acme/bin/source/adict/_win.c @@ -0,0 +1,315 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include "win.h" + +void* +erealloc(void *p, uint n) +{ + p = realloc(p, n); + if(p == nil) + threadprint(2, "realloc failed: %r"); + return p; +} + +void +wnew(Win *w) +{ + char buf[12]; + + w->ctl = open("/mnt/acme/new/ctl", ORDWR); + if(w->ctl<0 || read(w->ctl, buf, 12)!=12) + threadprint (2, "can't open window ctl file: %r"); + ctlwrite(w, "noscroll\n"); + w->winid = atoi(buf); + w->event = openfile(w, "event"); + w->addr = -1; /* will be opened when needed */ + w->body = nil; + w->data = -1; +} + +int +openfile(Win *w, char *f) +{ + char buf[64]; + int fd; + + sprint(buf, "/mnt/acme/%d/%s", w->winid, f); + fd = open(buf, ORDWR|OCEXEC); + if(fd < 0) + threadprint (2,"can't open window %s file: %r", f); + return fd; +} + +void +openbody(Win *w, int mode) +{ + char buf[64]; + + sprint(buf, "/mnt/acme/%d/body", w->winid); + w->body = Bopen(buf, mode|OCEXEC); + if(w->body == nil) + threadprint(2,"can't open window body file: %r"); +} + +void +wwritebody(Win *w, char *s, int n) +{ + if(w->body == nil) + openbody(w, OWRITE); + if(Bwrite(w->body, s, n) != n) + threadprint(2,"write error to window: %r"); + Bflush(w->body); +} + +void +wreplace(Win *w, char *addr, char *repl, int nrepl) +{ + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(w->data < 0) + w->data = openfile(w, "data"); + if(write(w->addr, addr, strlen(addr)) < 0){ + threadprint(2, "mail: warning: badd address %s:%r\n", addr); + return; + } + if(write(w->data, repl, nrepl) != nrepl) + threadprint(2, "writing data: %r"); +} + +static int +nrunes(char *s, int nb) +{ + int i, n; + Rune r; + + n = 0; + for(i=0; i<nb; n++) + i += chartorune(&r, s+i); + return n; +} + +void +wread(Win *w, uint q0, uint q1, char *data) +{ + int m, n, nr; + char buf[256]; + + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(w->data < 0) + w->data = openfile(w, "data"); + m = q0; + while(m < q1){ + n = sprint(buf, "#%d", m); + if(write(w->addr, buf, n) != n) + threadprint(2,"writing addr: %r"); + n = read(w->data, buf, sizeof buf); + if(n <= 0) + threadprint(2,"reading data: %r"); + nr = nrunes(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 +wselect(Win *w, char *addr) +{ + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(write(w->addr, addr, strlen(addr)) < 0) + threadprint(2,"writing addr"); + ctlwrite(w, "dot=addr\n"); +} + +void +wtagwrite(Win *w, char *s, int n) +{ + int fd; + + fd = openfile(w, "tag"); + if(write(fd, s, n) != n) + threadprint(2,"tag write: %r"); + close(fd); +} + +void +ctlwrite(Win *w, char *s) +{ + int n; + + n = strlen(s); + if(write(w->ctl, s, n) != n) + threadprint(2,"write error to ctl file: %r"); +} + +int +wdel(Win *w) +{ + if(write(w->ctl, "del\n", 4) != 4) + return False; + wdormant(w); + close(w->ctl); + w->ctl = -1; + close(w->event); + w->event = -1; + return True; +} + +void +wname(Win *w, char *s) +{ + char buf[128]; + + sprint(buf, "name %s\n", s); + ctlwrite(w, buf); +} + +void +wclean(Win *w) +{ + if(w->body) + Bflush(w->body); + ctlwrite(w, "clean\n"); +} + +void +wdormant(Win *w) +{ + if(w->addr >= 0){ + close(w->addr); + w->addr = -1; + } + if(w->body != nil){ + Bterm(w->body); + w->body = nil; + } + if(w->data >= 0){ + close(w->data); + w->data = -1; + } +} + +int +getec(Win *w) +{ + if(w->nbuf == 0){ + w->nbuf = read(w->event, w->buf, sizeof w->buf); + if(w->nbuf <= 0) + threadprint(2,"event read error: %r"); + w->bufp = w->buf; + } + w->nbuf--; + return *w->bufp++; +} + +int +geten(Win *w) +{ + int n, c; + + n = 0; + while('0'<=(c=getec(w)) && c<='9') + n = n*10+(c-'0'); + if(c != ' ') + threadprint(2, "event number syntax"); + return n; +} + +int +geter(Win *w, char *buf, int *nb) +{ + Rune r; + int n; + + r = getec(w); + buf[0] = r; + n = 1; + if(r < Runeself) + goto Return; + while(!fullrune(buf, n)) + buf[n++] = getec(w); + chartorune(&r, buf); + Return: + *nb = n; + return r; +} + + +void +wevent(Win *w, Event *e) +{ + int i, nb; + + e->c1 = getec(w); + e->c2 = getec(w); + e->q0 = geten(w); + e->q1 = geten(w); + e->flag = geten(w); + e->nr = geten(w); + if(e->nr > EVENTSIZE) + threadprint(2, "wevent: event string too long"); + e->nb = 0; + for(i=0; i<e->nr; i++){ + e->r[i] = geter(w, e->b+e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if(getec(w) != '\n') + threadprint(2, "wevent: event syntax 2"); +} + +void +wslave(Win *w, Channel *ce) +{ + Event e; + + while(recv(ce, &e) >= 0) + wevent(w, &e); +} + +void +wwriteevent(Win *w, Event *e) +{ + threadprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); +} + +int +wreadall(Win *w, char **sp) +{ + char *s; + int m, na, n; + + if(w->body != nil) + Bterm(w->body); + openbody(w, OREAD); + s = nil; + na = 0; + n = 0; + for(;;){ + if(na < n+512){ + na += 1024; + s = erealloc(s, na+1); + } + m = Bread(w->body, s+n, na-n); + if(m <= 0) + break; + n += m; + } + s[n] = 0; + Bterm(w->body); + w->body = nil; + *sp = s; + return n; +} diff --git a/acme/bin/source/adict/adict.c b/acme/bin/source/adict/adict.c new file mode 100644 index 000000000..7ce53e5c2 --- /dev/null +++ b/acme/bin/source/adict/adict.c @@ -0,0 +1,591 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include "win.h" +#include "adict.h" + +enum +{ + STACK = 8192, +}; + +char *prog = "adict"; +char *lprog = "/bin/adict"; +char *xprog = "/bin/dict"; +char *dict, *pattern, *curaddr[MAXMATCH], *curone, *args[6], buffer[80]; +char abuffer[80], fbuffer[80], pbuffer[80]; +int curindex, count, Eopen, Mopen; +Win Mwin, Ewin, Dwin; + +void openwin(char*, char*, Win*, int); +void handle(Win*, int); +void rexec(void*); +void pexec(void*); +int getaddr(char*); + +void +usage(void) +{ + fprint(2, "usage: %s [-d dictname] [pattern]\n", argv0); + threadexitsall(nil); +} + +int mainstacksize = STACK; + +void +threadmain(int argc, char** argv) +{ + ARGBEGIN{ + case 'd': + dict = strdup(ARGF()); + break; + default: + usage(); + }ARGEND + + /* if running as other name, note that fact */ + if(access(argv0, AEXIST) == 0) + lprog = argv0; + + switch(argc){ + case 1: + pattern = pbuffer; + strcpy(pattern,argv[0]); + if(dict == nil) + dict = "pgw"; + break; + case 0: + break; + default: + usage(); + } + + if ((dict == nil) && (pattern == nil)) + openwin(prog,"", &Dwin, Dictwin); + if (pattern == nil) + openwin(prog,"",&Ewin, Entrywin); + if ((count = getaddr(pattern)) <= 1) + openwin(prog,"Prev Next", &Ewin, Entrywin); + else + openwin(prog, "", &Mwin, Matchwin); +} + +static int +procrexec(char *xprog, ...) +{ + int fpipe[2]; + void *rexarg[4]; + Channel *c; + va_list va; + int i; + char *p; + + pipe(fpipe); + va_start(va, xprog); + p = xprog; + for(i=0; p && i+1<nelem(args); i++){ + args[i] = p; + p = va_arg(va, char*); + } + args[i] = nil; + + c = chancreate(sizeof(ulong), 0); + rexarg[0] = xprog; + rexarg[1] = args; + rexarg[2] = fpipe; + rexarg[3] = c; + + proccreate(rexec, rexarg, STACK); + recvul(c); + chanfree(c); + close(fpipe[1]); + return fpipe[0]; +} + +int +getaddr(char *pattern) +{ + /* Get char offset into dictionary of matches. */ + + int fd, i; + Biobuf inbuf; + char *bufptr; +char *obuf; + + if (pattern == nil) { + curone = nil; + curindex = 0; + curaddr[curindex] = nil; + return 0; + } + + sprint(buffer,"/%s/A", pattern); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + Binit(&inbuf, fd, OREAD); + i = 0; + curindex = 0; + while ((bufptr = Brdline(&inbuf, '\n')) != nil && (i < (MAXMATCH-1))) { + bufptr[Blinelen(&inbuf)-1] = 0; +obuf=bufptr; + while (bufptr[0] != '#' && bufptr[0] != 0) bufptr++; +if(bufptr[0] == 0) + print("whoops buf «%s»\n", obuf); + curaddr[i] = malloc(strlen(bufptr)); + strcpy(curaddr[i], bufptr); + i++; + } + curaddr[i] = nil; + if (i == MAXMATCH) + fprint(2, "Too many matches!\n"); + Bterm(&inbuf); + close(fd); + + curone = curaddr[curindex]; + return(i); +} + +char* +getpattern(char *addr) +{ + /* Get the pattern corresponding to an absolute address.*/ + int fd; + char *res, *t; + + res = nil; + sprint(buffer,"%sh", addr); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + if (read(fd, pbuffer, 80) > 80) + fprint(2, "Error in getting addres from dict.\n"); + else { + t = pbuffer; + /* remove trailing whitespace, newline */ + if (t != nil){ + while(*t != 0 && *t != '\n') + t++; + if(t == 0 && t > pbuffer) + t--; + while(t >= pbuffer && (*t==' ' || *t=='\n' || *t=='\t' || *t=='\r')) + *t-- = 0; + } + res = pbuffer; + } + close(fd); + return(res); +} + +char* +chgaddr(int dir) +{ + /* Increment or decrement the current address (curone). */ + + int fd; + char *res, *t; + + res = nil; + if (dir < 0) + sprint(buffer,"%s-a", curone); + else + sprint(buffer,"%s+a", curone); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + if (read(fd, abuffer, 80) > 80) + fprint(2, "Error in getting addres from dict.\n"); + else { + res = abuffer; + while (*res != '#') res++; + t = res; + while ((*t != '\n') && (t != nil)) t++; + if (t != nil) *t = 0; + } + close(fd); + return(res); +} + +void +dispdicts(Win *cwin) +{ + /* Display available dictionaries in window. */ + + int fd, nb, i; + char buf[1024], *t; + + fd = procrexec(xprog, "-d", "?", nil); + wreplace(cwin, "0,$","",0); /* Clear window */ + while ((nb = read(fd, buf, 1024)) > 0) { + t = buf; + i = 0; + if (strncmp("Usage", buf, 5) == 0) { /* Remove first line. */ + while (t[0] != '\n') { + t++; + i++; + } + t++; + i++; + } + wwritebody(cwin, t, nb-i); + } + close(fd); + wclean(cwin); +} + +void +dispentry(Win *cwin) +{ + /* Display the current selection in window. */ + + int fd, nb; + char buf[BUFSIZE]; + + if (curone == nil) { + if (pattern != nil) { + sprint(buf,"Pattern not found.\n"); + wwritebody(cwin, buf, 19); + wclean(cwin); + } + return; + } + sprint(buffer,"%sp", curone); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + wreplace(cwin, "0,$","",0); /* Clear window */ + while ((nb = read(fd, buf, BUFSIZE)) > 0) { + wwritebody(cwin, buf, nb); + } + close(fd); + wclean(cwin); +} + +void +dispmatches(Win *cwin) +{ + /* Display the current matches. */ + + int fd, nb; + char buf[BUFSIZE]; + + sprint(buffer,"/%s/H", pattern); + fd = procrexec(xprog, "-d", dict, "-c", buffer, nil); + while ((nb = read(fd, buf, BUFSIZE)) > 0) + wwritebody(cwin, buf, nb); + close(fd); + wclean(cwin); +} + +char* +format(char *s) +{ + /* Format a string to be written in window tag. Acme doesn't like */ + /* non alpha-num's in the tag line. */ + + char *t, *h; + + t = fbuffer; + if (s == nil) { + *t = 0; + return t; + } + strcpy(t, s); + h = t; + while (*t != 0) { + if (!(((*t >= 'a') && (*t <= 'z')) || + ((*t >= 'A') && (*t <= 'Z')) || + ((*t >= '0') && (*t <= '9')))) + *t = '_'; + t++; + } + if (strlen(h) > MAXTAG) + h[MAXTAG] = 0; + if (strcmp(s,h) == 0) return s; + return h; +} + +void +openwin(char *name, char *buttons, Win *twin, int wintype) +{ + char buf[80]; + + wnew(twin); + if (wintype == Dictwin) + sprint(buf,"%s",name); + else + if ((wintype == Entrywin) && (count > 1)) + sprint(buf,"%s/%s/%s/%d",name, dict, format(pattern), curindex+1); + else + sprint(buf,"%s/%s/%s",name, dict, format(pattern)); + wname(twin, buf); + wtagwrite(twin, buttons, strlen(buttons)); + wclean(twin); + wdormant(twin); + if (wintype == Dictwin) + dispdicts(twin); + if (wintype == Matchwin) { + Mopen = True; + dispmatches(twin); + } + if (wintype == Entrywin) { + Eopen = True; + dispentry(twin); + } + handle(twin, wintype); +} + +void +vopenwin(void *v) +{ + void **arg; + char *name, *buttons; + Win *twin; + int wintype; + + arg = v; + name = arg[0]; + buttons = arg[1]; + twin = arg[2]; + wintype = (int)arg[3]; + sendul(arg[4], 0); + + openwin(name, buttons, twin, wintype); + threadexits(nil); +} + +void +procopenwin(char *name, char *buttons, Win *twin, int wintype) +{ + void *arg[5]; + Channel *c; + + c = chancreate(sizeof(ulong), 0); + arg[0] = name; + arg[1] = buttons; + arg[2] = twin; + arg[3] = (void*)wintype; + arg[4] = c; + proccreate(vopenwin, arg, STACK); + recvul(c); + chanfree(c); +} + +void +rexec(void *v) +{ + void **arg; + char *prog; + char **args; + int *fd; + Channel *c; + + arg = v; + prog = arg[0]; + args = arg[1]; + fd = arg[2]; + c = arg[3]; + + rfork(RFENVG|RFFDG); + dup(fd[1], 1); + close(fd[1]); + close(fd[0]); + procexec(c, prog, args); + fprint(2, "Remote pipe execution failed: %s %r\n", prog); +abort(); + threadexits(nil); +} + +void +pexec(void *v) +{ + void **arg; + char *prog; + char **args; + Channel *c; + + arg = v; + prog = arg[0]; + args = arg[1]; + c = arg[2]; + + procexec(c, prog, args); + fprint(2, "Remote execution failed: %s %r\n", prog); +abort(); + threadexits(nil); +} + +void +procpexec(char *prog, char **args) +{ + void *rexarg[4]; + Channel *c; + + c = chancreate(sizeof(ulong), 0); + rexarg[0] = prog; + rexarg[1] = args; + rexarg[2] = c; + + proccreate(pexec, rexarg, STACK); + recvul(c); + chanfree(c); +} + +void +kill(void) +{ + /* Kill all processes related to this one. */ + int fd; + + sprint(buffer, "/proc/%d/notepg", getpid()); + fd = open(buffer, OWRITE); + rfork(RFNOTEG); + write(fd, "kill", 4); +} + +int +command(char *com, Win *w, int wintype) +{ + char *buf; + + if (strncmp(com, "Del", 3) == 0) { + switch(wintype){ + case Entrywin: + if (wdel(w)) { + Eopen = False; + threadexits(nil); + } + break; + case Dictwin: + if (wdel(w)) + threadexits(nil); + break; + case Matchwin: + kill(); + if (Eopen) + if (~wdel(&Ewin)) /* Remove the entry window */ + wdel(&Ewin); + if (!wdel(w)) + wdel(w); + threadexits(nil); + break; + } + return True; + } + if (strncmp(com, "Next", 4) == 0){ + if (curone != nil) { + curone = chgaddr(1); + buf = getpattern(curone); + sprint(buffer,"%s/%s/%s", prog, dict, format(buf)); + wname(w, buffer); + dispentry(w); + } + return True; + } + if (strncmp(com, "Prev",4) == 0){ + if (curone != nil) { + curone = chgaddr(-1); + buf = getpattern(curone); + sprint(buffer,"%s/%s/%s", prog, dict, format(buf)); + wname(w, buffer); + dispentry(w); + } + return True; + } + if (strncmp(com, "Nmatch",6) == 0){ + if (curaddr[++curindex] == nil) + curindex = 0; + curone = curaddr[curindex]; + if (curone != nil) { + sprint(buffer,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1); + wname(w, buffer); + dispentry(w); + } + return True; + } + return False; +} + +void +handle(Win *w, int wintype) +{ + Event e, e2, ea, etoss; + char *s, *t, buf[80]; + int tmp, na; + + while (True) { + wevent(w, &e); + switch(e.c2){ + default: + /* fprint(2,"unknown message %c%c\n", e.c1, e.c2); */ + break; + case 'i': + /* fprint(2,"'%s' inserted in tag at %d\n", e.b, e.q0);*/ + break; + case 'I': + /* fprint(2,"'%s' inserted in body at %d\n", e.b, e.q0);*/ + break; + case 'd': + /* fprint(2, "'%s' deleted in tag at %d\n", e.b, e.q0);*/ + break; + case 'D': + /* fprint(2, "'%s' deleted in body at %d\n", e.b, e.q0);*/ + break; + case 'x': + case 'X': /* Execute command. */ + if (e.flag & 2) + wevent(w, &e2); + if(e.flag & 8){ + wevent(w, &ea); + wevent(w, &etoss); + na = ea.nb; + } else + na = 0; + s = e.b; + if ((e.flag & 2) && e.nb == 0) + s = e2.b; + if(na){ + t = malloc(strlen(s)+1+na+1); + snprint(t, strlen(s)+1+na+1, "%s %s", s, ea.b); + s = t; + } + /* if it's a long message, it can't be for us anyway */ + if(!command(s, w, wintype)) /* send it back */ + wwriteevent(w, &e); + if(na) + free(s); + break; + case 'l': + case 'L': /* Look for something. */ + if (e.flag & 2) + wevent(w, &e); + wclean(w); /* Set clean bit. */ + if (wintype == Dictwin) { + strcpy(buf, e.b); + args[0] = lprog; + args[1] = "-d"; + args[2] = buf; + args[3] = nil; + procpexec(lprog, args); /* New adict with chosen dict. */ + } + if (wintype == Entrywin) { + strcpy(buf, e.b); + args[0] = lprog; + args[1] = "-d"; + args[2] = dict; + args[3] = buf; + args[4] = nil; + procpexec(lprog, args); /* New adict with chosen pattern. */ + } + if (wintype == Matchwin) { + tmp = atoi(e.b) - 1; + if ((tmp >= 0) && (tmp < MAXMATCH) && (curaddr[tmp] != nil)) { + curindex = tmp; + curone = curaddr[curindex]; + /* Display selected match. */ + if (Eopen) { + sprint(buf,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1); + wname(&Ewin, buf); + dispentry(&Ewin); + } + else + procopenwin(prog,"Nmatch Prev Next", &Ewin, Entrywin); + } + } + break; + } + } +} diff --git a/acme/bin/source/adict/adict.h b/acme/bin/source/adict/adict.h new file mode 100644 index 000000000..fffaa5454 --- /dev/null +++ b/acme/bin/source/adict/adict.h @@ -0,0 +1,10 @@ +enum +{ + Matchwin, + Entrywin, + Dictwin +}; + +#define MAXTAG 20 +#define MAXMATCH 100 +#define BUFSIZE 4096 diff --git a/acme/bin/source/adict/man b/acme/bin/source/adict/man new file mode 100644 index 000000000..ad15bf079 --- /dev/null +++ b/acme/bin/source/adict/man @@ -0,0 +1,26 @@ +adict [-d dictionary] [pattern] + + adict with no arguments opens a window that displays all the currently +available dictionaries. To select a dictionary, click the right mouse button on +its name. + +-d dictionary Opens a window that interfaces to the specified dictionary. To + look up a word, enter it in the window, and click the right mouse button on it. + +[pattern] If no dictionary is specified, adict looks up the pattern in "oed" (Oxford + English Dictionary). If more than one entry is found, adict opens a window + displaying the headers of the matching entries. To display a particular entry + click the right mouse button on the number to its left. + +Quit Exit and remove all windows associated with this one. + +Nmatch Display the next matching entry. + +Next Display the next entry in the dictionary. + +Prev Display the previous entry in the dictionary. + + Nmatch works independently of Prev and Next. + + Any word in the window displaying an entry can be looked up in the selected +dictionary by clicking the right mouse button on that word.
\ No newline at end of file diff --git a/acme/bin/source/adict/mkfile b/acme/bin/source/adict/mkfile new file mode 100644 index 000000000..14a079874 --- /dev/null +++ b/acme/bin/source/adict/mkfile @@ -0,0 +1,11 @@ +</$objtype/mkfile + +TARG=adict + +HFILES=win.h + +OFILES=adict.$O\ + win.$O\ + +BIN= /acme/bin/$objtype +</sys/src/cmd/mkone diff --git a/acme/bin/source/adict/win.c b/acme/bin/source/adict/win.c new file mode 100644 index 000000000..e8b2ee257 --- /dev/null +++ b/acme/bin/source/adict/win.c @@ -0,0 +1,315 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include "win.h" + +void* +erealloc(void *p, uint n) +{ + p = realloc(p, n); + if(p == nil) + fprint(2, "realloc failed: %r"); + return p; +} + +void +wnew(Win *w) +{ + char buf[12]; + + w->ctl = open("/mnt/acme/new/ctl", ORDWR); + if(w->ctl<0 || read(w->ctl, buf, 12)!=12) + fprint (2, "can't open window ctl file: %r"); + ctlwrite(w, "noscroll\n"); + w->winid = atoi(buf); + w->event = openfile(w, "event"); + w->addr = -1; /* will be opened when needed */ + w->body = nil; + w->data = -1; +} + +int +openfile(Win *w, char *f) +{ + char buf[64]; + int fd; + + sprint(buf, "/mnt/acme/%d/%s", w->winid, f); + fd = open(buf, ORDWR|OCEXEC); + if(fd < 0) + fprint (2,"can't open window %s file: %r", f); + return fd; +} + +void +openbody(Win *w, int mode) +{ + char buf[64]; + + sprint(buf, "/mnt/acme/%d/body", w->winid); + w->body = Bopen(buf, mode|OCEXEC); + if(w->body == nil) + fprint(2,"can't open window body file: %r"); +} + +void +wwritebody(Win *w, char *s, int n) +{ + if(w->body == nil) + openbody(w, OWRITE); + if(Bwrite(w->body, s, n) != n) + fprint(2,"write error to window: %r"); + Bflush(w->body); +} + +void +wreplace(Win *w, char *addr, char *repl, int nrepl) +{ + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(w->data < 0) + w->data = openfile(w, "data"); + if(write(w->addr, addr, strlen(addr)) < 0){ + fprint(2, "mail: warning: badd address %s:%r\n", addr); + return; + } + if(write(w->data, repl, nrepl) != nrepl) + fprint(2, "writing data: %r"); +} + +static int +nrunes(char *s, int nb) +{ + int i, n; + Rune r; + + n = 0; + for(i=0; i<nb; n++) + i += chartorune(&r, s+i); + return n; +} + +void +wread(Win *w, uint q0, uint q1, char *data) +{ + int m, n, nr; + char buf[256]; + + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(w->data < 0) + w->data = openfile(w, "data"); + m = q0; + while(m < q1){ + n = sprint(buf, "#%d", m); + if(write(w->addr, buf, n) != n) + fprint(2,"writing addr: %r"); + n = read(w->data, buf, sizeof buf); + if(n <= 0) + fprint(2,"reading data: %r"); + nr = nrunes(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 +wselect(Win *w, char *addr) +{ + if(w->addr < 0) + w->addr = openfile(w, "addr"); + if(write(w->addr, addr, strlen(addr)) < 0) + fprint(2,"writing addr"); + ctlwrite(w, "dot=addr\n"); +} + +void +wtagwrite(Win *w, char *s, int n) +{ + int fd; + + fd = openfile(w, "tag"); + if(write(fd, s, n) != n) + fprint(2,"tag write: %r"); + close(fd); +} + +void +ctlwrite(Win *w, char *s) +{ + int n; + + n = strlen(s); + if(write(w->ctl, s, n) != n) + fprint(2,"write error to ctl file: %r"); +} + +int +wdel(Win *w) +{ + if(write(w->ctl, "del\n", 4) != 4) + return False; + wdormant(w); + close(w->ctl); + w->ctl = -1; + close(w->event); + w->event = -1; + return True; +} + +void +wname(Win *w, char *s) +{ + char buf[128]; + + sprint(buf, "name %s\n", s); + ctlwrite(w, buf); +} + +void +wclean(Win *w) +{ + if(w->body) + Bflush(w->body); + ctlwrite(w, "clean\n"); +} + +void +wdormant(Win *w) +{ + if(w->addr >= 0){ + close(w->addr); + w->addr = -1; + } + if(w->body != nil){ + Bterm(w->body); + w->body = nil; + } + if(w->data >= 0){ + close(w->data); + w->data = -1; + } +} + +int +getec(Win *w) +{ + if(w->nbuf == 0){ + w->nbuf = read(w->event, w->buf, sizeof w->buf); + if(w->nbuf <= 0) + fprint(2,"event read error: %r"); + w->bufp = w->buf; + } + w->nbuf--; + return *w->bufp++; +} + +int +geten(Win *w) +{ + int n, c; + + n = 0; + while('0'<=(c=getec(w)) && c<='9') + n = n*10+(c-'0'); + if(c != ' ') + fprint(2, "event number syntax"); + return n; +} + +int +geter(Win *w, char *buf, int *nb) +{ + Rune r; + int n; + + r = getec(w); + buf[0] = r; + n = 1; + if(r < Runeself) + goto Return; + while(!fullrune(buf, n)) + buf[n++] = getec(w); + chartorune(&r, buf); + Return: + *nb = n; + return r; +} + + +void +wevent(Win *w, Event *e) +{ + int i, nb; + + e->c1 = getec(w); + e->c2 = getec(w); + e->q0 = geten(w); + e->q1 = geten(w); + e->flag = geten(w); + e->nr = geten(w); + if(e->nr > EVENTSIZE) + fprint(2, "wevent: event string too long"); + e->nb = 0; + for(i=0; i<e->nr; i++){ + e->r[i] = geter(w, e->b+e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if(getec(w) != '\n') + fprint(2, "wevent: event syntax 2"); +} + +void +wslave(Win *w, Channel *ce) +{ + Event e; + + while(recv(ce, &e) >= 0) + wevent(w, &e); +} + +void +wwriteevent(Win *w, Event *e) +{ + fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); +} + +int +wreadall(Win *w, char **sp) +{ + char *s; + int m, na, n; + + if(w->body != nil) + Bterm(w->body); + openbody(w, OREAD); + s = nil; + na = 0; + n = 0; + for(;;){ + if(na < n+512){ + na += 1024; + s = erealloc(s, na+1); + } + m = Bread(w->body, s+n, na-n); + if(m <= 0) + break; + n += m; + } + s[n] = 0; + Bterm(w->body); + w->body = nil; + *sp = s; + return n; +} diff --git a/acme/bin/source/adict/win.h b/acme/bin/source/adict/win.h new file mode 100644 index 000000000..8e1698aa1 --- /dev/null +++ b/acme/bin/source/adict/win.h @@ -0,0 +1,59 @@ +enum +{ + False, + True, + EVENTSIZE=256, +}; + + +typedef struct Event Event; +struct Event +{ + int c1; + int c2; + int q0; + int q1; + int flag; + int nb; + int nr; + char b[EVENTSIZE*UTFmax+1]; + Rune r[EVENTSIZE+1]; +}; + + +typedef struct Win Win; +struct Win +{ + int winid; + int addr; + Biobuf *body; + int ctl; + int data; + int event; + char buf[512]; + char *bufp; + int nbuf; +}; + +int dead(Win*); +void wnew(Win*); +void wwritebody(Win*, char *s, int n); +void wread(Win*, uint, uint, char*); +void wclean(Win*); +void wname(Win*, char*); +void wdormant(Win*); +void wevent(Win*, Event*); +void wtagwrite(Win*, char*, int); +void wwriteevent(Win*, Event*); +void wslave(Win*, Channel*); /* chan(Event) */ +void wreplace(Win*, char*, char*, int); +void wselect(Win*, char*); +int wdel(Win*); +int wreadall(Win*, char**); + +void ctlwrite(Win*, char*); +int getec(Win*); +int geten(Win*); +int geter(Win*, char*, int*); +int openfile(Win*, char*); +void openbody(Win*, int); |