fill /acme
This commit is contained in:
parent
71cfa9c637
commit
a150899221
114 changed files with 14220 additions and 0 deletions
584
acme/bin/source/adict/_adict.c
Normal file
584
acme/bin/source/adict/_adict.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
315
acme/bin/source/adict/_win.c
Normal file
315
acme/bin/source/adict/_win.c
Normal 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;
|
||||
}
|
591
acme/bin/source/adict/adict.c
Normal file
591
acme/bin/source/adict/adict.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
10
acme/bin/source/adict/adict.h
Normal file
10
acme/bin/source/adict/adict.h
Normal 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
26
acme/bin/source/adict/man
Normal 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.
|
11
acme/bin/source/adict/mkfile
Normal file
11
acme/bin/source/adict/mkfile
Normal 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
315
acme/bin/source/adict/win.c
Normal 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;
|
||||
}
|
59
acme/bin/source/adict/win.h
Normal file
59
acme/bin/source/adict/win.h
Normal 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);
|
Loading…
Add table
Add a link
Reference in a new issue