fill /acme

This commit is contained in:
cinap_lenrek 2011-04-14 17:27:24 +00:00
parent 71cfa9c637
commit a150899221
114 changed files with 14220 additions and 0 deletions

View file

@ -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;
}
}
}

View file

@ -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;
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,10 @@
enum
{
Matchwin,
Entrywin,
Dictwin
};
#define MAXTAG 20
#define MAXMATCH 100
#define BUFSIZE 4096

26
acme/bin/source/adict/man Normal file
View file

@ -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.

View file

@ -0,0 +1,11 @@
</$objtype/mkfile
TARG=adict
HFILES=win.h
OFILES=adict.$O\
win.$O\
BIN= /acme/bin/$objtype
</sys/src/cmd/mkone

315
acme/bin/source/adict/win.c Normal file
View file

@ -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;
}

View file

@ -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);