diff options
Diffstat (limited to 'acme/bin/source/adict/_adict.c')
-rw-r--r-- | acme/bin/source/adict/_adict.c | 584 |
1 files changed, 584 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; + } + } +} |