From 5540d37849de2cd41ee069643a4a4d83a222bfc8 Mon Sep 17 00:00:00 2001 From: Derek Stevens Date: Sat, 12 Jun 2021 23:54:54 -0600 Subject: [PATCH] add gitignore, clang-format, build script; merge src's patch for spaces in filenames --- .clang-format | 23 + .gitignore | 1 + acme.c | 1953 +++++++++++++++--------------- addr.c | 506 ++++---- buff.c | 506 ++++---- build.sh | 8 + cols.c | 1091 ++++++++--------- disk.c | 181 ++- ecmd.c | 2312 +++++++++++++++++------------------ edit.c | 1310 +++++++++++--------- elog.c | 563 +++++---- exec.c | 3144 ++++++++++++++++++++++++------------------------ file.c | 455 ++++--- fns.h | 1 + fsys.c | 1203 +++++++++---------- logf.c | 271 ++--- look.c | 1593 +++++++++++++------------ mail/html.c | 112 +- mail/html.o | Bin 17352 -> 0 bytes mail/mail.c | 1122 +++++++++-------- mail/mail.o | Bin 65248 -> 0 bytes mail/mesg.c | 2442 +++++++++++++++++++------------------ mail/mesg.o | Bin 118240 -> 0 bytes mail/o.Mail | Bin 392472 -> 0 bytes mail/reply.c | 1000 ++++++++-------- mail/reply.o | Bin 55328 -> 0 bytes mail/util.c | 139 +-- mail/util.o | Bin 20784 -> 0 bytes mail/win.c | 583 +++++---- mail/win.o | Bin 39264 -> 0 bytes regx.c | 1411 +++++++++++----------- rows.c | 1534 ++++++++++++------------ scrl.c | 256 ++-- text.c | 3174 ++++++++++++++++++++++++------------------------- time.c | 185 ++- util.c | 749 ++++++------ wind.c | 1201 ++++++++++--------- xfid.c | 2041 ++++++++++++++++--------------- 38 files changed, 15300 insertions(+), 15770 deletions(-) create mode 100644 .clang-format create mode 100755 build.sh delete mode 100644 mail/html.o delete mode 100644 mail/mail.o delete mode 100644 mail/mesg.o delete mode 100755 mail/o.Mail delete mode 100644 mail/reply.o delete mode 100644 mail/util.o delete mode 100644 mail/win.o diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a699815 --- /dev/null +++ b/.clang-format @@ -0,0 +1,23 @@ +TabWidth: 2 +IndentWidth: 2 +ContinuationIndentWidth: 2 +UseTab: Never +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +PenaltyReturnTypeOnItsOwnLine: 255 +IndentCaseLabels: true +SpaceBeforeParens: ControlStatements +AlignAfterOpenBracket: AlwaysBreak +BinPackArguments: false +BinPackArguments: false +PointerAlignment: Left +BreakBeforeBraces: Attach +SortIncludes: false +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AlignEscapedNewlines: Left + diff --git a/.gitignore b/.gitignore index 16f5e7d..633ca46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/*.o **/o.* +acme diff --git a/acme.c b/acme.c index 79d51c4..5cbe271 100644 --- a/acme.c +++ b/acme.c @@ -11,403 +11,383 @@ #include #include "dat.h" #include "fns.h" - /* for generating syms in mkfile only: */ - #include - #include "edit.h" +/* for generating syms in mkfile only: */ +#include +#include "edit.h" -void mousethread(void*); -void keyboardthread(void*); -void waitthread(void*); -void xfidallocthread(void*); -void newwindowthread(void*); -void plumbproc(void*); -int timefmt(Fmt*); +void mousethread(void*); +void keyboardthread(void*); +void waitthread(void*); +void xfidallocthread(void*); +void newwindowthread(void*); +void plumbproc(void*); +int timefmt(Fmt*); -Reffont **fontcache; -int nfontcache; -char wdir[512] = "."; -Reffont *reffonts[2]; -int snarffd = -1; -int mainpid; -int swapscrollbuttons = FALSE; -char *mtpt; +Reffont** fontcache; +int nfontcache; +char wdir[512] = "."; +Reffont* reffonts[2]; +int snarffd = -1; +int mainpid; +int swapscrollbuttons = FALSE; +char* mtpt; -enum{ - NSnarf = 1000 /* less than 1024, I/O buffer size */ +enum { + NSnarf = 1000 /* less than 1024, I/O buffer size */ }; -Rune snarfrune[NSnarf+1]; +Rune snarfrune[NSnarf + 1]; -char *fontnames[2] = -{ - "/lib/font/bit/lucsans/typeunicode.7.font", - "/lib/font/bit/lucm/unicode.9.font" -}; +char* fontnames[2] = { + "/lib/font/bit/lucsans/typeunicode.7.font", + "/lib/font/bit/lucm/unicode.9.font"}; -Command *command; +Command* command; -void shutdownthread(void*); -void acmeerrorinit(void); -void readfile(Column*, char*); -static int shutdown(void*, char*); +void shutdownthread(void*); +void acmeerrorinit(void); +void readfile(Column*, char*); +static int shutdown(void*, char*); -void -derror(Display *d, char *errorstr) -{ - USED(d); - error(errorstr); +void derror(Display* d, char* errorstr) { + USED(d); + error(errorstr); } -void -threadmain(int argc, char *argv[]) -{ - int i; - char *p, *loadfile; - Column *c; - int ncol; - Display *d; +void threadmain(int argc, char* argv[]) { + int i; + char *p, *loadfile; + Column* c; + int ncol; + Display* d; - rfork(RFENVG|RFNAMEG); + rfork(RFENVG | RFNAMEG); - ncol = -1; + ncol = -1; - loadfile = nil; - ARGBEGIN{ - case 'D': - {extern int _threaddebuglevel; - _threaddebuglevel = ~0; - } - break; - case 'a': - globalindent[AUTOINDENT] = TRUE; - break; - case 'b': - bartflag = TRUE; - break; - case 'c': - p = ARGF(); - if(p == nil) - goto Usage; - ncol = atoi(p); - if(ncol <= 0) - goto Usage; - break; - case 'f': - fontnames[0] = ARGF(); - if(fontnames[0] == nil) - goto Usage; - break; - case 'F': - fontnames[1] = ARGF(); - if(fontnames[1] == nil) - goto Usage; - break; - case 'i': - globalindent[SPACESINDENT] = TRUE; - break; - case 'l': - loadfile = ARGF(); - if(loadfile == nil) - goto Usage; - break; - case 'm': - mtpt = ARGF(); - if(mtpt == nil) - goto Usage; - break; - case 'r': - swapscrollbuttons = TRUE; - break; - case 'W': - winsize = ARGF(); - if(winsize == nil) - goto Usage; - break; - default: - Usage: - fprint(2, "usage: acme -aib -c ncol -f fontname -F fixedwidthfontname -l loadfile -W winsize\n"); - threadexitsall("usage"); - }ARGEND + loadfile = nil; + ARGBEGIN { + case 'D': { + extern int _threaddebuglevel; + _threaddebuglevel = ~0; + } break; + case 'a': + globalindent[AUTOINDENT] = TRUE; + break; + case 'b': + bartflag = TRUE; + break; + case 'c': + p = ARGF(); + if (p == nil) + goto Usage; + ncol = atoi(p); + if (ncol <= 0) + goto Usage; + break; + case 'f': + fontnames[0] = ARGF(); + if (fontnames[0] == nil) + goto Usage; + break; + case 'F': + fontnames[1] = ARGF(); + if (fontnames[1] == nil) + goto Usage; + break; + case 'i': + globalindent[SPACESINDENT] = TRUE; + break; + case 'l': + loadfile = ARGF(); + if (loadfile == nil) + goto Usage; + break; + case 'm': + mtpt = ARGF(); + if (mtpt == nil) + goto Usage; + break; + case 'r': + swapscrollbuttons = TRUE; + break; + case 'W': + winsize = ARGF(); + if (winsize == nil) + goto Usage; + break; + default: + Usage: + fprint( + 2, + "usage: acme -aib -c ncol -f fontname -F fixedwidthfontname -l " + "loadfile -W winsize\n"); + threadexitsall("usage"); + } + ARGEND - fontnames[0] = estrdup(fontnames[0]); - fontnames[1] = estrdup(fontnames[1]); + fontnames[0] = estrdup(fontnames[0]); + fontnames[1] = estrdup(fontnames[1]); - quotefmtinstall(); - fmtinstall('t', timefmt); + quotefmtinstall(); + fmtinstall('t', timefmt); - cputype = getenv("cputype"); - objtype = getenv("objtype"); - home = getenv("HOME"); - acmeshell = getenv("acmeshell"); - if(acmeshell && *acmeshell == '\0') - acmeshell = nil; - p = getenv("tabstop"); - if(p != nil){ - maxtab = strtoul(p, nil, 0); - free(p); - } - if(maxtab == 0) - maxtab = 4; - if(loadfile) - rowloadfonts(loadfile); - putenv("font", fontnames[0]); - snarffd = open("/dev/snarf", OREAD|OCEXEC); -/* - if(cputype){ - sprint(buf, "/acme/bin/%s", cputype); - bind(buf, "/bin", MBEFORE); - } - bind("/acme/bin", "/bin", MBEFORE); -*/ - getwd(wdir, sizeof wdir); + cputype = getenv("cputype"); + objtype = getenv("objtype"); + home = getenv("HOME"); + acmeshell = getenv("acmeshell"); + if (acmeshell && *acmeshell == '\0') + acmeshell = nil; + p = getenv("tabstop"); + if (p != nil) { + maxtab = strtoul(p, nil, 0); + free(p); + } + if (maxtab == 0) + maxtab = 4; + if (loadfile) + rowloadfonts(loadfile); + putenv("font", fontnames[0]); + snarffd = open("/dev/snarf", OREAD | OCEXEC); + /* + if(cputype){ + sprint(buf, "/acme/bin/%s", cputype); + bind(buf, "/bin", MBEFORE); + } + bind("/acme/bin", "/bin", MBEFORE); + */ + getwd(wdir, sizeof wdir); -/* - if(geninitdraw(nil, derror, fontnames[0], "acme", nil, Refnone) < 0){ - fprint(2, "acme: can't open display: %r\n"); - threadexitsall("geninitdraw"); - } -*/ - if(initdraw(derror, fontnames[0], "acme") < 0){ - fprint(2, "acme: can't open display: %r\n"); - threadexitsall("initdraw"); - } + /* + if(geninitdraw(nil, derror, fontnames[0], "acme", nil, Refnone) < 0){ + fprint(2, "acme: can't open display: %r\n"); + threadexitsall("geninitdraw"); + } + */ + if (initdraw(derror, fontnames[0], "acme") < 0) { + fprint(2, "acme: can't open display: %r\n"); + threadexitsall("initdraw"); + } - d = display; - font = d->defaultfont; -/*assert(font); */ + d = display; + font = d->defaultfont; + /*assert(font); */ - reffont.f = font; - reffonts[0] = &reffont; - incref(&reffont.ref); /* one to hold up 'font' variable */ - incref(&reffont.ref); /* one to hold up reffonts[0] */ - fontcache = emalloc(sizeof(Reffont*)); - nfontcache = 1; - fontcache[0] = &reffont; + reffont.f = font; + reffonts[0] = &reffont; + incref(&reffont.ref); /* one to hold up 'font' variable */ + incref(&reffont.ref); /* one to hold up reffonts[0] */ + fontcache = emalloc(sizeof(Reffont*)); + nfontcache = 1; + fontcache[0] = &reffont; - iconinit(); - timerinit(); - rxinit(); + iconinit(); + timerinit(); + rxinit(); - cwait = threadwaitchan(); - ccommand = chancreate(sizeof(Command**), 0); - ckill = chancreate(sizeof(Rune*), 0); - cxfidalloc = chancreate(sizeof(Xfid*), 0); - cxfidfree = chancreate(sizeof(Xfid*), 0); - cnewwindow = chancreate(sizeof(Channel*), 0); - cerr = chancreate(sizeof(char*), 0); - cedit = chancreate(sizeof(int), 0); - cexit = chancreate(sizeof(int), 0); - cwarn = chancreate(sizeof(void*), 1); - if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){ - fprint(2, "acme: can't create initial channels: %r\n"); - threadexitsall("channels"); - } - chansetname(ccommand, "ccommand"); - chansetname(ckill, "ckill"); - chansetname(cxfidalloc, "cxfidalloc"); - chansetname(cxfidfree, "cxfidfree"); - chansetname(cnewwindow, "cnewwindow"); - chansetname(cerr, "cerr"); - chansetname(cedit, "cedit"); - chansetname(cexit, "cexit"); - chansetname(cwarn, "cwarn"); + cwait = threadwaitchan(); + ccommand = chancreate(sizeof(Command**), 0); + ckill = chancreate(sizeof(Rune*), 0); + cxfidalloc = chancreate(sizeof(Xfid*), 0); + cxfidfree = chancreate(sizeof(Xfid*), 0); + cnewwindow = chancreate(sizeof(Channel*), 0); + cerr = chancreate(sizeof(char*), 0); + cedit = chancreate(sizeof(int), 0); + cexit = chancreate(sizeof(int), 0); + cwarn = chancreate(sizeof(void*), 1); + if ( + cwait == nil || ccommand == nil || ckill == nil || cxfidalloc == nil || + cxfidfree == nil || cerr == nil || cexit == nil || cwarn == nil) { + fprint(2, "acme: can't create initial channels: %r\n"); + threadexitsall("channels"); + } + chansetname(ccommand, "ccommand"); + chansetname(ckill, "ckill"); + chansetname(cxfidalloc, "cxfidalloc"); + chansetname(cxfidfree, "cxfidfree"); + chansetname(cnewwindow, "cnewwindow"); + chansetname(cerr, "cerr"); + chansetname(cedit, "cedit"); + chansetname(cexit, "cexit"); + chansetname(cwarn, "cwarn"); - mousectl = initmouse(nil, screen); - if(mousectl == nil){ - fprint(2, "acme: can't initialize mouse: %r\n"); - threadexitsall("mouse"); - } - mouse = &mousectl->m; - keyboardctl = initkeyboard(nil); - if(keyboardctl == nil){ - fprint(2, "acme: can't initialize keyboard: %r\n"); - threadexitsall("keyboard"); - } - mainpid = getpid(); - startplumbing(); -/* - plumbeditfd = plumbopen("edit", OREAD|OCEXEC); - if(plumbeditfd < 0) - fprint(2, "acme: can't initialize plumber: %r\n"); - else{ - cplumb = chancreate(sizeof(Plumbmsg*), 0); - threadcreate(plumbproc, nil, STACK); - } - plumbsendfd = plumbopen("send", OWRITE|OCEXEC); -*/ + mousectl = initmouse(nil, screen); + if (mousectl == nil) { + fprint(2, "acme: can't initialize mouse: %r\n"); + threadexitsall("mouse"); + } + mouse = &mousectl->m; + keyboardctl = initkeyboard(nil); + if (keyboardctl == nil) { + fprint(2, "acme: can't initialize keyboard: %r\n"); + threadexitsall("keyboard"); + } + mainpid = getpid(); + startplumbing(); + /* + plumbeditfd = plumbopen("edit", OREAD|OCEXEC); + if(plumbeditfd < 0) + fprint(2, "acme: can't initialize plumber: %r\n"); + else{ + cplumb = chancreate(sizeof(Plumbmsg*), 0); + threadcreate(plumbproc, nil, STACK); + } + plumbsendfd = plumbopen("send", OWRITE|OCEXEC); + */ - fsysinit(); + fsysinit(); - #define WPERCOL 8 - disk = diskinit(); - if(!loadfile || !rowload(&row, loadfile, TRUE)){ - rowinit(&row, screen->clipr); - if(ncol < 0){ - if(argc == 0) - ncol = 2; - else{ - ncol = (argc+(WPERCOL-1))/WPERCOL; - if(ncol < 2) - ncol = 2; - } - } - if(ncol == 0) - ncol = 2; - for(i=0; i=row.ncol) - readfile(c, argv[i]); - else - readfile(row.col[i/WPERCOL], argv[i]); - } - } - flushimage(display, 1); +#define WPERCOL 8 + disk = diskinit(); + if (!loadfile || !rowload(&row, loadfile, TRUE)) { + rowinit(&row, screen->clipr); + if (ncol < 0) { + if (argc == 0) + ncol = 2; + else { + ncol = (argc + (WPERCOL - 1)) / WPERCOL; + if (ncol < 2) + ncol = 2; + } + } + if (ncol == 0) + ncol = 2; + for (i = 0; i < ncol; i++) { + c = rowadd(&row, nil, -1); + if (c == nil && i == 0) + error("initializing columns"); + } + c = row.col[row.ncol - 1]; + if (argc == 0) + readfile(c, wdir); + else + for (i = 0; i < argc; i++) { + p = utfrrune(argv[i], '/'); + if ((p != nil && strcmp(p, "/guide") == 0) || i / WPERCOL >= row.ncol) + readfile(c, argv[i]); + else + readfile(row.col[i / WPERCOL], argv[i]); + } + } + flushimage(display, 1); - acmeerrorinit(); - threadcreate(keyboardthread, nil, STACK); - threadcreate(mousethread, nil, STACK); - threadcreate(waitthread, nil, STACK); - threadcreate(xfidallocthread, nil, STACK); - threadcreate(newwindowthread, nil, STACK); -/* threadcreate(shutdownthread, nil, STACK); */ - threadnotify(shutdown, 1); - recvul(cexit); - killprocs(); - threadexitsall(nil); + acmeerrorinit(); + threadcreate(keyboardthread, nil, STACK); + threadcreate(mousethread, nil, STACK); + threadcreate(waitthread, nil, STACK); + threadcreate(xfidallocthread, nil, STACK); + threadcreate(newwindowthread, nil, STACK); + /* threadcreate(shutdownthread, nil, STACK); */ + threadnotify(shutdown, 1); + recvul(cexit); + killprocs(); + threadexitsall(nil); } -void -readfile(Column *c, char *s) -{ - Window *w; - Rune rb[256]; - int nr; - Runestr rs; +void readfile(Column* c, char* s) { + Window* w; + Rune rb[256]; + int nr; + Runestr rs; - w = coladd(c, nil, nil, -1); - if(s[0] != '/') - runesnprint(rb, sizeof rb, "%s/%s", wdir, s); - else - runesnprint(rb, sizeof rb, "%s", s); - nr = runestrlen(rb); - rs = cleanrname(runestr(rb, nr)); - winsetname(w, rs.r, rs.nr); - textload(&w->body, 0, s, 1); - w->body.file->mod = FALSE; - w->dirty = FALSE; - winsettag(w); - winresize(w, w->r, FALSE, TRUE); - textscrdraw(&w->body); - textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc); - xfidlog(w, "new"); + w = coladd(c, nil, nil, -1); + if (s[0] != '/') + runesnprint(rb, sizeof rb, "%s/%s", wdir, s); + else + runesnprint(rb, sizeof rb, "%s", s); + nr = runestrlen(rb); + rs = cleanrname(runestr(rb, nr)); + winsetname(w, rs.r, rs.nr); + textload(&w->body, 0, s, 1); + w->body.file->mod = FALSE; + w->dirty = FALSE; + winsettag(w); + winresize(w, w->r, FALSE, TRUE); + textscrdraw(&w->body); + textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc); + xfidlog(w, "new"); } -char *ignotes[] = { - "sys: write on closed pipe", - "sys: ttin", - "sys: ttou", - "sys: tstp", - nil -}; +char* ignotes[] = + {"sys: write on closed pipe", "sys: ttin", "sys: ttou", "sys: tstp", nil}; -char *oknotes[] ={ - "delete", - "hangup", - "kill", - "exit", - nil -}; +char* oknotes[] = {"delete", "hangup", "kill", "exit", nil}; -int dumping; +int dumping; -static int -shutdown(void *v, char *msg) -{ - int i; +static int shutdown(void* v, char* msg) { + int i; - USED(v); + USED(v); - for(i=0; ignotes[i]; i++) - if(strncmp(ignotes[i], msg, strlen(ignotes[i])) == 0) - return 1; + for (i = 0; ignotes[i]; i++) + if (strncmp(ignotes[i], msg, strlen(ignotes[i])) == 0) + return 1; - killprocs(); - if(!dumping && strcmp(msg, "kill")!=0 && strcmp(msg, "exit")!=0 && getpid()==mainpid){ - dumping = TRUE; - rowdump(&row, nil); - } - for(i=0; oknotes[i]; i++) - if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0) - threadexitsall(msg); - print("acme: %s\n", msg); - return 0; + killprocs(); + if ( + !dumping && strcmp(msg, "kill") != 0 && strcmp(msg, "exit") != 0 && + getpid() == mainpid) { + dumping = TRUE; + rowdump(&row, nil); + } + for (i = 0; oknotes[i]; i++) + if (strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0) + threadexitsall(msg); + print("acme: %s\n", msg); + return 0; } /* void shutdownthread(void *v) { - char *msg; - Channel *c; + char *msg; + Channel *c; - USED(v); + USED(v); - threadsetname("shutdown"); - c = threadnotechan(); - while((msg = recvp(c)) != nil) - shutdown(nil, msg); + threadsetname("shutdown"); + c = threadnotechan(); + while((msg = recvp(c)) != nil) + shutdown(nil, msg); } */ -void -killprocs(void) -{ - Command *c; +void killprocs(void) { + Command* c; - fsysclose(); -/* if(display) */ -/* flushimage(display, 1); */ + fsysclose(); + /* if(display) */ + /* flushimage(display, 1); */ - for(c=command; c; c=c->next) - postnote(PNGROUP, c->pid, "hangup"); + for (c = command; c; c = c->next) + postnote(PNGROUP, c->pid, "hangup"); } static int errorfd; int erroutfd; -void -acmeerrorproc(void *v) -{ - char *buf, *s; - int n; +void acmeerrorproc(void* v) { + char *buf, *s; + int n; - USED(v); - threadsetname("acmeerrorproc"); - buf = emalloc(8192+1); - while((n=read(errorfd, buf, 8192)) >= 0){ - buf[n] = '\0'; - s = estrdup(buf); - sendp(cerr, s); - free(s); - } - free(buf); + USED(v); + threadsetname("acmeerrorproc"); + buf = emalloc(8192 + 1); + while ((n = read(errorfd, buf, 8192)) >= 0) { + buf[n] = '\0'; + s = estrdup(buf); + sendp(cerr, s); + free(s); + } + free(buf); } -void -acmeerrorinit(void) -{ - int pfd[2]; +void acmeerrorinit(void) { + int pfd[2]; - if(pipe(pfd) < 0) - error("can't create pipe"); + if (pipe(pfd) < 0) + error("can't create pipe"); #if 0 sprint(acmeerrorfile, "/srv/acme.%s.%d", getuser(), mainpid); fd = create(acmeerrorfile, OWRITE, 0666); @@ -424,671 +404,629 @@ acmeerrorinit(void) sprint(buf, "/fd/%d", pfd[1]); errorfd = open(buf, OREAD|OCEXEC); #endif - fcntl(pfd[0], F_SETFD, FD_CLOEXEC); - fcntl(pfd[1], F_SETFD, FD_CLOEXEC); - erroutfd = pfd[0]; - errorfd = pfd[1]; - if(errorfd < 0) - error("can't re-open acmeerror file"); - proccreate(acmeerrorproc, nil, STACK); + fcntl(pfd[0], F_SETFD, FD_CLOEXEC); + fcntl(pfd[1], F_SETFD, FD_CLOEXEC); + erroutfd = pfd[0]; + errorfd = pfd[1]; + if (errorfd < 0) + error("can't re-open acmeerror file"); + proccreate(acmeerrorproc, nil, STACK); } /* void plumbproc(void *v) { - Plumbmsg *m; + Plumbmsg *m; - USED(v); - threadsetname("plumbproc"); - for(;;){ - m = threadplumbrecv(plumbeditfd); - if(m == nil) - threadexits(nil); - sendp(cplumb, m); - } + USED(v); + threadsetname("plumbproc"); + for(;;){ + m = threadplumbrecv(plumbeditfd); + if(m == nil) + threadexits(nil); + sendp(cplumb, m); + } } */ -void -keyboardthread(void *v) -{ - Rune r; - Timer *timer; - Text *t; - enum { KTimer, KKey, NKALT }; - static Alt alts[NKALT+1]; +void keyboardthread(void* v) { + Rune r; + Timer* timer; + Text* t; + enum { KTimer, KKey, NKALT }; + static Alt alts[NKALT + 1]; - USED(v); - alts[KTimer].c = nil; - alts[KTimer].v = nil; - alts[KTimer].op = CHANNOP; - alts[KKey].c = keyboardctl->c; - alts[KKey].v = &r; - alts[KKey].op = CHANRCV; - alts[NKALT].op = CHANEND; + USED(v); + alts[KTimer].c = nil; + alts[KTimer].v = nil; + alts[KTimer].op = CHANNOP; + alts[KKey].c = keyboardctl->c; + alts[KKey].v = &r; + alts[KKey].op = CHANRCV; + alts[NKALT].op = CHANEND; - timer = nil; - typetext = nil; - threadsetname("keyboardthread"); - for(;;){ - switch(alt(alts)){ - case KTimer: - timerstop(timer); - t = typetext; - if(t!=nil && t->what==Tag){ - winlock(t->w, 'K'); - wincommit(t->w, t); - winunlock(t->w); - flushimage(display, 1); - } - alts[KTimer].c = nil; - alts[KTimer].op = CHANNOP; - break; - case KKey: - casekeyboard: - typetext = rowtype(&row, r, mouse->xy); - t = typetext; - if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright)) /* scrolling doesn't change activecol */ - activecol = t->col; - if(t!=nil && t->w!=nil) - t->w->body.file->curtext = &t->w->body; - if(timer != nil) - timercancel(timer); - if(t!=nil && t->what==Tag) { - timer = timerstart(500); - alts[KTimer].c = timer->c; - alts[KTimer].op = CHANRCV; - }else{ - timer = nil; - alts[KTimer].c = nil; - alts[KTimer].op = CHANNOP; - } - if(nbrecv(keyboardctl->c, &r) > 0) - goto casekeyboard; - flushimage(display, 1); - break; - } - } + timer = nil; + typetext = nil; + threadsetname("keyboardthread"); + for (;;) { + switch (alt(alts)) { + case KTimer: + timerstop(timer); + t = typetext; + if (t != nil && t->what == Tag) { + winlock(t->w, 'K'); + wincommit(t->w, t); + winunlock(t->w); + flushimage(display, 1); + } + alts[KTimer].c = nil; + alts[KTimer].op = CHANNOP; + break; + case KKey: + casekeyboard: + typetext = rowtype(&row, r, mouse->xy); + t = typetext; + if ( + t != nil && t->col != nil && + !(r == Kdown || r == Kleft || + r == Kright)) /* scrolling doesn't change activecol */ + activecol = t->col; + if (t != nil && t->w != nil) + t->w->body.file->curtext = &t->w->body; + if (timer != nil) + timercancel(timer); + if (t != nil && t->what == Tag) { + timer = timerstart(500); + alts[KTimer].c = timer->c; + alts[KTimer].op = CHANRCV; + } else { + timer = nil; + alts[KTimer].c = nil; + alts[KTimer].op = CHANNOP; + } + if (nbrecv(keyboardctl->c, &r) > 0) + goto casekeyboard; + flushimage(display, 1); + break; + } + } } -void -mousethread(void *v) -{ - Text *t, *argt; - int but; - uint q0, q1; - Window *w; - Plumbmsg *pm; - Mouse m; - char *act; - enum { MResize, MMouse, MPlumb, MWarnings, NMALT }; - static Alt alts[NMALT+1]; +void mousethread(void* v) { + Text *t, *argt; + int but; + uint q0, q1; + Window* w; + Plumbmsg* pm; + Mouse m; + char* act; + enum { MResize, MMouse, MPlumb, MWarnings, NMALT }; + static Alt alts[NMALT + 1]; - USED(v); - threadsetname("mousethread"); - alts[MResize].c = mousectl->resizec; - alts[MResize].v = nil; - alts[MResize].op = CHANRCV; - alts[MMouse].c = mousectl->c; - alts[MMouse].v = &mousectl->m; - alts[MMouse].op = CHANRCV; - alts[MPlumb].c = cplumb; - alts[MPlumb].v = ± - alts[MPlumb].op = CHANRCV; - alts[MWarnings].c = cwarn; - alts[MWarnings].v = nil; - alts[MWarnings].op = CHANRCV; - if(cplumb == nil) - alts[MPlumb].op = CHANNOP; - alts[NMALT].op = CHANEND; + USED(v); + threadsetname("mousethread"); + alts[MResize].c = mousectl->resizec; + alts[MResize].v = nil; + alts[MResize].op = CHANRCV; + alts[MMouse].c = mousectl->c; + alts[MMouse].v = &mousectl->m; + alts[MMouse].op = CHANRCV; + alts[MPlumb].c = cplumb; + alts[MPlumb].v = ± + alts[MPlumb].op = CHANRCV; + alts[MWarnings].c = cwarn; + alts[MWarnings].v = nil; + alts[MWarnings].op = CHANRCV; + if (cplumb == nil) + alts[MPlumb].op = CHANNOP; + alts[NMALT].op = CHANEND; - for(;;){ - qlock(&row.lk); - flushwarnings(); - qunlock(&row.lk); - flushimage(display, 1); - switch(alt(alts)){ - case MResize: - if(getwindow(display, Refnone) < 0) - error("attach to window"); - draw(screen, screen->r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - iconinit(); - scrlresize(); - rowresize(&row, screen->clipr); - break; - case MPlumb: - if(strcmp(pm->type, "text") == 0){ - act = plumblookup(pm->attr, "action"); - if(act==nil || strcmp(act, "showfile")==0) - plumblook(pm); - else if(strcmp(act, "showdata")==0) - plumbshow(pm); - } - plumbfree(pm); - break; - case MWarnings: - break; - case MMouse: - /* - * Make a copy so decisions are consistent; mousectl changes - * underfoot. Can't just receive into m because this introduces - * another race; see /sys/src/libdraw/mouse.c. - */ - m = mousectl->m; - qlock(&row.lk); - t = rowwhich(&row, m.xy); + for (;;) { + qlock(&row.lk); + flushwarnings(); + qunlock(&row.lk); + flushimage(display, 1); + switch (alt(alts)) { + case MResize: + if (getwindow(display, Refnone) < 0) + error("attach to window"); + draw( + screen, + screen->r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + iconinit(); + scrlresize(); + rowresize(&row, screen->clipr); + break; + case MPlumb: + if (strcmp(pm->type, "text") == 0) { + act = plumblookup(pm->attr, "action"); + if (act == nil || strcmp(act, "showfile") == 0) + plumblook(pm); + else if (strcmp(act, "showdata") == 0) + plumbshow(pm); + } + plumbfree(pm); + break; + case MWarnings: + break; + case MMouse: + /* + * Make a copy so decisions are consistent; mousectl changes + * underfoot. Can't just receive into m because this introduces + * another race; see /sys/src/libdraw/mouse.c. + */ + m = mousectl->m; + qlock(&row.lk); + t = rowwhich(&row, m.xy); - if((t!=mousetext && t!=nil && t->w!=nil) && - (mousetext==nil || mousetext->w==nil || t->w->id!=mousetext->w->id)) { - xfidlog(t->w, "focus"); - } + if ( + (t != mousetext && t != nil && t->w != nil) && + (mousetext == nil || mousetext->w == nil || + t->w->id != mousetext->w->id)) { + xfidlog(t->w, "focus"); + } - if(t!=mousetext && mousetext!=nil && mousetext->w!=nil){ - winlock(mousetext->w, 'M'); - mousetext->eq0 = ~0; - wincommit(mousetext->w, mousetext); - winunlock(mousetext->w); - } - mousetext = t; - if(t == nil) - goto Continue; - w = t->w; - if(t==nil || m.buttons==0) - goto Continue; - but = 0; - if(m.buttons == 1) - but = 1; - else if(m.buttons == 2) - but = 2; - else if(m.buttons == 4) - but = 3; - barttext = t; - if(t->what==Body && ptinrect(m.xy, t->scrollr)){ - if(but){ - if(swapscrollbuttons){ - if(but == 1) - but = 3; - else if(but == 3) - but = 1; - } - winlock(w, 'M'); - t->eq0 = ~0; - textscroll(t, but); - winunlock(w); - } - goto Continue; - } - /* scroll buttons, wheels, etc. */ - if(w != nil && (m.buttons & (8|16))){ - if(m.buttons & 8) - but = Kscrolloneup; - else - but = Kscrollonedown; - winlock(w, 'M'); - t->eq0 = ~0; - texttype(t, but); - winunlock(w); - goto Continue; - } - if(ptinrect(m.xy, t->scrollr)){ - if(but){ - if(t->what == Columntag) - rowdragcol(&row, t->col, but); - else if(t->what == Tag){ - coldragwin(t->col, t->w, but); - if(t->w) - barttext = &t->w->body; - } - if(t->col) - activecol = t->col; - } - goto Continue; - } - if(m.buttons){ - if(w) - winlock(w, 'M'); - t->eq0 = ~0; - if(w) - wincommit(w, t); - else - textcommit(t, TRUE); - if(m.buttons & 1){ - textselect(t); - if(w) - winsettag(w); - argtext = t; - seltext = t; - if(t->col) - activecol = t->col; /* button 1 only */ - if(t->w!=nil && t==&t->w->body) - activewin = t->w; - }else if(m.buttons & 2){ - if(textselect2(t, &q0, &q1, &argt)) - execute(t, q0, q1, FALSE, argt); - }else if(m.buttons & 4){ - if(textselect3(t, &q0, &q1)) - look3(t, q0, q1, FALSE); - } - if(w) - winunlock(w); - goto Continue; - } - Continue: - qunlock(&row.lk); - break; - } - } + if (t != mousetext && mousetext != nil && mousetext->w != nil) { + winlock(mousetext->w, 'M'); + mousetext->eq0 = ~0; + wincommit(mousetext->w, mousetext); + winunlock(mousetext->w); + } + mousetext = t; + if (t == nil) + goto Continue; + w = t->w; + if (t == nil || m.buttons == 0) + goto Continue; + but = 0; + if (m.buttons == 1) + but = 1; + else if (m.buttons == 2) + but = 2; + else if (m.buttons == 4) + but = 3; + barttext = t; + if (t->what == Body && ptinrect(m.xy, t->scrollr)) { + if (but) { + if (swapscrollbuttons) { + if (but == 1) + but = 3; + else if (but == 3) + but = 1; + } + winlock(w, 'M'); + t->eq0 = ~0; + textscroll(t, but); + winunlock(w); + } + goto Continue; + } + /* scroll buttons, wheels, etc. */ + if (w != nil && (m.buttons & (8 | 16))) { + if (m.buttons & 8) + but = Kscrolloneup; + else + but = Kscrollonedown; + winlock(w, 'M'); + t->eq0 = ~0; + texttype(t, but); + winunlock(w); + goto Continue; + } + if (ptinrect(m.xy, t->scrollr)) { + if (but) { + if (t->what == Columntag) + rowdragcol(&row, t->col, but); + else if (t->what == Tag) { + coldragwin(t->col, t->w, but); + if (t->w) + barttext = &t->w->body; + } + if (t->col) + activecol = t->col; + } + goto Continue; + } + if (m.buttons) { + if (w) + winlock(w, 'M'); + t->eq0 = ~0; + if (w) + wincommit(w, t); + else + textcommit(t, TRUE); + if (m.buttons & 1) { + textselect(t); + if (w) + winsettag(w); + argtext = t; + seltext = t; + if (t->col) + activecol = t->col; /* button 1 only */ + if (t->w != nil && t == &t->w->body) + activewin = t->w; + } else if (m.buttons & 2) { + if (textselect2(t, &q0, &q1, &argt)) + execute(t, q0, q1, FALSE, argt); + } else if (m.buttons & 4) { + if (textselect3(t, &q0, &q1)) + look3(t, q0, q1, FALSE); + } + if (w) + winunlock(w); + goto Continue; + } + Continue: + qunlock(&row.lk); + break; + } + } } /* - * There is a race between process exiting and our finding out it was ever created. - * This structure keeps a list of processes that have exited we haven't heard of. + * There is a race between process exiting and our finding out it was ever + * created. This structure keeps a list of processes that have exited we haven't + * heard of. */ typedef struct Pid Pid; -struct Pid -{ - int pid; - char msg[ERRMAX]; - Pid *next; +struct Pid { + int pid; + char msg[ERRMAX]; + Pid* next; }; -void -waitthread(void *v) -{ - Waitmsg *w; - Command *c, *lc; - uint pid; - int found, ncmd; - Rune *cmd; - char *err; - Text *t; - Pid *pids, *p, *lastp; - enum { WErr, WKill, WWait, WCmd, NWALT }; - Alt alts[NWALT+1]; +void waitthread(void* v) { + Waitmsg* w; + Command *c, *lc; + uint pid; + int found, ncmd; + Rune* cmd; + char* err; + Text* t; + Pid *pids, *p, *lastp; + enum { WErr, WKill, WWait, WCmd, NWALT }; + Alt alts[NWALT + 1]; - USED(v); - threadsetname("waitthread"); - pids = nil; - alts[WErr].c = cerr; - alts[WErr].v = &err; - alts[WErr].op = CHANRCV; - alts[WKill].c = ckill; - alts[WKill].v = &cmd; - alts[WKill].op = CHANRCV; - alts[WWait].c = cwait; - alts[WWait].v = &w; - alts[WWait].op = CHANRCV; - alts[WCmd].c = ccommand; - alts[WCmd].v = &c; - alts[WCmd].op = CHANRCV; - alts[NWALT].op = CHANEND; + USED(v); + threadsetname("waitthread"); + pids = nil; + alts[WErr].c = cerr; + alts[WErr].v = &err; + alts[WErr].op = CHANRCV; + alts[WKill].c = ckill; + alts[WKill].v = &cmd; + alts[WKill].op = CHANRCV; + alts[WWait].c = cwait; + alts[WWait].v = &w; + alts[WWait].op = CHANRCV; + alts[WCmd].c = ccommand; + alts[WCmd].v = &c; + alts[WCmd].op = CHANRCV; + alts[NWALT].op = CHANEND; - command = nil; - for(;;){ - switch(alt(alts)){ - case WErr: - qlock(&row.lk); - warning(nil, "%s", err); - free(err); - flushimage(display, 1); - qunlock(&row.lk); - break; - case WKill: - found = FALSE; - ncmd = runestrlen(cmd); - for(c=command; c; c=c->next){ - /* -1 for blank */ - if(runeeq(c->name, c->nname-1, cmd, ncmd) == TRUE){ - if(postnote(PNGROUP, c->pid, "kill") < 0) - warning(nil, "kill %S: %r\n", cmd); - found = TRUE; - } - } - if(!found) - warning(nil, "Kill: no process %S\n", cmd); - free(cmd); - break; - case WWait: - pid = w->pid; - lc = nil; - for(c=command; c; c=c->next){ - if(c->pid == pid){ - if(lc) - lc->next = c->next; - else - command = c->next; - break; - } - lc = c; - } - qlock(&row.lk); - t = &row.tag; - textcommit(t, TRUE); - if(c == nil){ - /* helper processes use this exit status */ - if(strncmp(w->msg, "libthread", 9) != 0){ - p = emalloc(sizeof(Pid)); - p->pid = pid; - strncpy(p->msg, w->msg, sizeof(p->msg)); - p->next = pids; - pids = p; - } - }else{ - if(search(t, c->name, c->nname)){ - textdelete(t, t->q0, t->q1, TRUE); - textsetselect(t, 0, 0); - } - if(w->msg[0]) - warning(c->md, "%.*S: exit %s\n", c->nname-1, c->name, w->msg); - flushimage(display, 1); - } - qunlock(&row.lk); - free(w); - Freecmd: - if(c){ - if(c->iseditcmd) - sendul(cedit, 0); - free(c->text); - free(c->name); - fsysdelid(c->md); - free(c); - } - break; - case WCmd: - /* has this command already exited? */ - lastp = nil; - for(p=pids; p!=nil; p=p->next){ - if(p->pid == c->pid){ - if(p->msg[0]) - warning(c->md, "%s\n", p->msg); - if(lastp == nil) - pids = p->next; - else - lastp->next = p->next; - free(p); - goto Freecmd; - } - lastp = p; - } - c->next = command; - command = c; - qlock(&row.lk); - t = &row.tag; - textcommit(t, TRUE); - textinsert(t, 0, c->name, c->nname, TRUE); - textsetselect(t, 0, 0); - flushimage(display, 1); - qunlock(&row.lk); - break; - } - } + command = nil; + for (;;) { + switch (alt(alts)) { + case WErr: + qlock(&row.lk); + warning(nil, "%s", err); + free(err); + flushimage(display, 1); + qunlock(&row.lk); + break; + case WKill: + found = FALSE; + ncmd = runestrlen(cmd); + for (c = command; c; c = c->next) { + /* -1 for blank */ + if (runeeq(c->name, c->nname - 1, cmd, ncmd) == TRUE) { + if (postnote(PNGROUP, c->pid, "kill") < 0) + warning(nil, "kill %S: %r\n", cmd); + found = TRUE; + } + } + if (!found) + warning(nil, "Kill: no process %S\n", cmd); + free(cmd); + break; + case WWait: + pid = w->pid; + lc = nil; + for (c = command; c; c = c->next) { + if (c->pid == pid) { + if (lc) + lc->next = c->next; + else + command = c->next; + break; + } + lc = c; + } + qlock(&row.lk); + t = &row.tag; + textcommit(t, TRUE); + if (c == nil) { + /* helper processes use this exit status */ + if (strncmp(w->msg, "libthread", 9) != 0) { + p = emalloc(sizeof(Pid)); + p->pid = pid; + strncpy(p->msg, w->msg, sizeof(p->msg)); + p->next = pids; + pids = p; + } + } else { + if (search(t, c->name, c->nname)) { + textdelete(t, t->q0, t->q1, TRUE); + textsetselect(t, 0, 0); + } + if (w->msg[0]) + warning(c->md, "%.*S: exit %s\n", c->nname - 1, c->name, w->msg); + flushimage(display, 1); + } + qunlock(&row.lk); + free(w); + Freecmd: + if (c) { + if (c->iseditcmd) + sendul(cedit, 0); + free(c->text); + free(c->name); + fsysdelid(c->md); + free(c); + } + break; + case WCmd: + /* has this command already exited? */ + lastp = nil; + for (p = pids; p != nil; p = p->next) { + if (p->pid == c->pid) { + if (p->msg[0]) + warning(c->md, "%s\n", p->msg); + if (lastp == nil) + pids = p->next; + else + lastp->next = p->next; + free(p); + goto Freecmd; + } + lastp = p; + } + c->next = command; + command = c; + qlock(&row.lk); + t = &row.tag; + textcommit(t, TRUE); + textinsert(t, 0, c->name, c->nname, TRUE); + textsetselect(t, 0, 0); + flushimage(display, 1); + qunlock(&row.lk); + break; + } + } } -void -xfidallocthread(void *v) -{ - Xfid *xfree, *x; - enum { Alloc, Free, N }; - static Alt alts[N+1]; +void xfidallocthread(void* v) { + Xfid *xfree, *x; + enum { Alloc, Free, N }; + static Alt alts[N + 1]; - USED(v); - threadsetname("xfidallocthread"); - alts[Alloc].c = cxfidalloc; - alts[Alloc].v = nil; - alts[Alloc].op = CHANRCV; - alts[Free].c = cxfidfree; - alts[Free].v = &x; - alts[Free].op = CHANRCV; - alts[N].op = CHANEND; + USED(v); + threadsetname("xfidallocthread"); + alts[Alloc].c = cxfidalloc; + alts[Alloc].v = nil; + alts[Alloc].op = CHANRCV; + alts[Free].c = cxfidfree; + alts[Free].v = &x; + alts[Free].op = CHANRCV; + alts[N].op = CHANEND; - xfree = nil; - for(;;){ - switch(alt(alts)){ - case Alloc: - x = xfree; - if(x) - xfree = x->next; - else{ - x = emalloc(sizeof(Xfid)); - x->c = chancreate(sizeof(void(*)(Xfid*)), 0); - chansetname(x->c, "xc%p", x->c); - x->arg = x; - threadcreate(xfidctl, x->arg, STACK); - } - sendp(cxfidalloc, x); - break; - case Free: - x->next = xfree; - xfree = x; - break; - } - } + xfree = nil; + for (;;) { + switch (alt(alts)) { + case Alloc: + x = xfree; + if (x) + xfree = x->next; + else { + x = emalloc(sizeof(Xfid)); + x->c = chancreate(sizeof(void (*)(Xfid*)), 0); + chansetname(x->c, "xc%p", x->c); + x->arg = x; + threadcreate(xfidctl, x->arg, STACK); + } + sendp(cxfidalloc, x); + break; + case Free: + x->next = xfree; + xfree = x; + break; + } + } } -/* this thread, in the main proc, allows fsysproc to get a window made without doing graphics */ -void -newwindowthread(void *v) -{ - Window *w; +/* this thread, in the main proc, allows fsysproc to get a window made without + * doing graphics */ +void newwindowthread(void* v) { + Window* w; - USED(v); - threadsetname("newwindowthread"); + USED(v); + threadsetname("newwindowthread"); - for(;;){ - /* only fsysproc is talking to us, so synchronization is trivial */ - recvp(cnewwindow); - w = makenewwindow(nil); - winsettag(w); - xfidlog(w, "new"); - sendp(cnewwindow, w); - } + for (;;) { + /* only fsysproc is talking to us, so synchronization is trivial */ + recvp(cnewwindow); + w = makenewwindow(nil); + winsettag(w); + xfidlog(w, "new"); + sendp(cnewwindow, w); + } } -Reffont* -rfget(int fix, int save, int setfont, char *name) -{ - Reffont *r; - Font *f; - int i; +Reffont* rfget(int fix, int save, int setfont, char* name) { + Reffont* r; + Font* f; + int i; - r = nil; - if(name == nil){ - name = fontnames[fix]; - r = reffonts[fix]; - } - if(r == nil){ - for(i=0; if->name) == 0){ - r = fontcache[i]; - goto Found; - } - f = openfont(display, name); - if(f == nil){ - warning(nil, "can't open font file %s: %r\n", name); - return nil; - } - r = emalloc(sizeof(Reffont)); - r->f = f; - fontcache = erealloc(fontcache, (nfontcache+1)*sizeof(Reffont*)); - fontcache[nfontcache++] = r; - } - Found: - if(save){ - incref(&r->ref); - if(reffonts[fix]) - rfclose(reffonts[fix]); - reffonts[fix] = r; - if(name != fontnames[fix]){ - free(fontnames[fix]); - fontnames[fix] = estrdup(name); - } - } - if(setfont){ - reffont.f = r->f; - incref(&r->ref); - rfclose(reffonts[0]); - font = r->f; - reffonts[0] = r; - incref(&r->ref); - iconinit(); - } - incref(&r->ref); - return r; + r = nil; + if (name == nil) { + name = fontnames[fix]; + r = reffonts[fix]; + } + if (r == nil) { + for (i = 0; i < nfontcache; i++) + if (strcmp(name, fontcache[i]->f->name) == 0) { + r = fontcache[i]; + goto Found; + } + f = openfont(display, name); + if (f == nil) { + warning(nil, "can't open font file %s: %r\n", name); + return nil; + } + r = emalloc(sizeof(Reffont)); + r->f = f; + fontcache = erealloc(fontcache, (nfontcache + 1) * sizeof(Reffont*)); + fontcache[nfontcache++] = r; + } +Found: + if (save) { + incref(&r->ref); + if (reffonts[fix]) + rfclose(reffonts[fix]); + reffonts[fix] = r; + if (name != fontnames[fix]) { + free(fontnames[fix]); + fontnames[fix] = estrdup(name); + } + } + if (setfont) { + reffont.f = r->f; + incref(&r->ref); + rfclose(reffonts[0]); + font = r->f; + reffonts[0] = r; + incref(&r->ref); + iconinit(); + } + incref(&r->ref); + return r; } -void -rfclose(Reffont *r) -{ - int i; +void rfclose(Reffont* r) { + int i; - if(decref(&r->ref) == 0){ - for(i=0; i= nfontcache) - warning(nil, "internal error: can't find font in cache\n"); - else{ - nfontcache--; - memmove(fontcache+i, fontcache+i+1, (nfontcache-i)*sizeof(Reffont*)); - } - freefont(r->f); - free(r); - } + if (decref(&r->ref) == 0) { + for (i = 0; i < nfontcache; i++) + if (r == fontcache[i]) + break; + if (i >= nfontcache) + warning(nil, "internal error: can't find font in cache\n"); + else { + nfontcache--; + memmove( + fontcache + i, + fontcache + i + 1, + (nfontcache - i) * sizeof(Reffont*)); + } + freefont(r->f); + free(r); + } } Cursor boxcursor = { - {-7, -7}, - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, - 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, - 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, - 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, - 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} -}; + {-7, -7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x70, 0x0E, 0x70, + 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, + 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00}}; Cursor2 boxcursor2 = { - {-15, -15}, - {0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xC0, 0x03, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF}, - {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0x00, 0x00, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00} -}; + {-15, -15}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, + 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, + 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, + 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, + 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, + 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, + 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, + 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, + 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, + 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, + 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, + 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -void -iconinit(void) -{ - Rectangle r; - Image *tmp; +void iconinit(void) { + Rectangle r; + Image* tmp; - if(tagcols[BACK] == nil) { - /* Black */ - tagcols[BACK] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DBlack); - tagcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x1F9B92FF); - tagcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x797979FF); - tagcols[TEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x797979FF); - tagcols[HTEXT] = display->black; + if (tagcols[BACK] == nil) { + /* Black */ + tagcols[BACK] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DBlack); + tagcols[HIGH] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x1F9B92FF); + tagcols[BORD] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x797979FF); + tagcols[TEXT] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x797979FF); + tagcols[HTEXT] = display->black; - /* Blue */ - textcols[BACK] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000F19FF); - textcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x1F9B92FF); - textcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x93A1A1FF); - textcols[TEXT] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x93A1A1FF); - textcols[HTEXT] = display->black; - } + /* Blue */ + textcols[BACK] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x000F19FF); + textcols[HIGH] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x1F9B92FF); + textcols[BORD] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x93A1A1FF); + textcols[TEXT] = + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x93A1A1FF); + textcols[HTEXT] = display->black; + } - r = Rect(0, 0, Scrollwid+ButtonBorder, font->height+1); - if(button && eqrect(r, button->r)) - return; + r = Rect(0, 0, Scrollwid + ButtonBorder, font->height + 1); + if (button && eqrect(r, button->r)) + return; - if(button){ - freeimage(button); - freeimage(modbutton); - freeimage(colbutton); - } + if (button) { + freeimage(button); + freeimage(modbutton); + freeimage(colbutton); + } - button = allocimage(display, r, screen->chan, 0, DNofill); - draw(button, r, tagcols[BACK], nil, r.min); - r.max.x -= ButtonBorder; - border(button, r, ButtonBorder, tagcols[BORD], ZP); + button = allocimage(display, r, screen->chan, 0, DNofill); + draw(button, r, tagcols[BACK], nil, r.min); + r.max.x -= ButtonBorder; + border(button, r, ButtonBorder, tagcols[BORD], ZP); - r = button->r; - modbutton = allocimage(display, r, screen->chan, 0, DNofill); - draw(modbutton, r, tagcols[BACK], nil, r.min); - r.max.x -= ButtonBorder; - border(modbutton, r, ButtonBorder, tagcols[BORD], ZP); - r = insetrect(r, ButtonBorder); - tmp = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x09998DFF); - draw(modbutton, r, tmp, nil, ZP); - freeimage(tmp); + r = button->r; + modbutton = allocimage(display, r, screen->chan, 0, DNofill); + draw(modbutton, r, tagcols[BACK], nil, r.min); + r.max.x -= ButtonBorder; + border(modbutton, r, ButtonBorder, tagcols[BORD], ZP); + r = insetrect(r, ButtonBorder); + tmp = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x09998DFF); + draw(modbutton, r, tmp, nil, ZP); + freeimage(tmp); - r = button->r; - colbutton = allocimage(display, r, screen->chan, 0, 0x586E75FF); + r = button->r; + colbutton = allocimage(display, r, screen->chan, 0, 0x586E75FF); - but2col = allocimage(display, r, screen->chan, 1, 0x797979FF); - but3col = allocimage(display, r, screen->chan, 1, 0x36D3C6FF); + but2col = allocimage(display, r, screen->chan, 1, 0x797979FF); + but3col = allocimage(display, r, screen->chan, 1, 0x36D3C6FF); } /* @@ -1099,77 +1037,76 @@ iconinit(void) /* rio truncates larges snarf buffers, so this avoids using the * service if the string is huge */ -#define MAXSNARF 100*1024 +#define MAXSNARF 100 * 1024 -void -acmeputsnarf(void) -{ - int i, n; - Fmt f; - char *s; +void acmeputsnarf(void) { + int i, n; + Fmt f; + char* s; - if(snarfbuf.nc==0) - return; - if(snarfbuf.nc > MAXSNARF) - return; + if (snarfbuf.nc == 0) + return; + if (snarfbuf.nc > MAXSNARF) + return; - fmtstrinit(&f); - for(i=0; i= NSnarf) - n = NSnarf; - bufread(&snarfbuf, i, snarfrune, n); - if(fmtprint(&f, "%.*S", n, snarfrune) < 0) - break; - } - s = fmtstrflush(&f); - if(s && s[0]) - putsnarf(s); - free(s); + fmtstrinit(&f); + for (i = 0; i < snarfbuf.nc; i += n) { + n = snarfbuf.nc - i; + if (n >= NSnarf) + n = NSnarf; + bufread(&snarfbuf, i, snarfrune, n); + if (fmtprint(&f, "%.*S", n, snarfrune) < 0) + break; + } + s = fmtstrflush(&f); + if (s && s[0]) + putsnarf(s); + free(s); } -void -acmegetsnarf(void) -{ - char *s; - int nb, nr, nulls, len; - Rune *r; +void acmegetsnarf(void) { + char* s; + int nb, nr, nulls, len; + Rune* r; - s = getsnarf(); - if(s == nil || s[0]==0){ - free(s); - return; - } + s = getsnarf(); + if (s == nil || s[0] == 0) { + free(s); + return; + } - len = strlen(s); - r = runemalloc(len+1); - cvttorunes(s, len, r, &nb, &nr, &nulls); - bufreset(&snarfbuf); - bufinsert(&snarfbuf, 0, r, nr); - free(r); - free(s); + len = strlen(s); + r = runemalloc(len + 1); + cvttorunes(s, len, r, &nb, &nr, &nulls); + bufreset(&snarfbuf); + bufinsert(&snarfbuf, 0, r, nr); + free(r); + free(s); } -int -ismtpt(char *file) -{ - int n; +int ismtpt(char* file) { + int n; - if(mtpt == nil) - return 0; + if (mtpt == nil) + return 0; - /* This is not foolproof, but it will stop a lot of them. */ - n = strlen(mtpt); - return strncmp(file, mtpt, n) == 0 && ((n > 0 && mtpt[n-1] == '/') || file[n] == '/' || file[n] == 0); + /* This is not foolproof, but it will stop a lot of them. */ + n = strlen(mtpt); + return strncmp(file, mtpt, n) == 0 && + ((n > 0 && mtpt[n - 1] == '/') || file[n] == '/' || file[n] == 0); } -int -timefmt(Fmt *f) -{ - Tm *tm; +int timefmt(Fmt* f) { + Tm* tm; - tm = localtime(va_arg(f->args, ulong)); - return fmtprint(f, "%04d/%02d/%02d %02d:%02d:%02d", - tm->year+1900, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec); + tm = localtime(va_arg(f->args, ulong)); + return fmtprint( + f, + "%04d/%02d/%02d %02d:%02d:%02d", + tm->year + 1900, + tm->mon + 1, + tm->mday, + tm->hour, + tm->min, + tm->sec); } - diff --git a/addr.c b/addr.c index 6aee899..feeb82b 100644 --- a/addr.c +++ b/addr.c @@ -12,41 +12,29 @@ #include "dat.h" #include "fns.h" -enum -{ - None = 0, - Fore = '+', - Back = '-' -}; +enum { None = 0, Fore = '+', Back = '-' }; -enum -{ - Char, - Line -}; +enum { Char, Line }; -int -isaddrc(int r) -{ - if(r && utfrune("0123456789+-/$.#,;?", r)!=nil) - return TRUE; - return FALSE; +int isaddrc(int r) { + if (r && utfrune("0123456789+-/$.#,;?", r) != nil) + return TRUE; + return FALSE; } /* - * quite hard: could be almost anything but white space, but we are a little conservative, - * aiming for regular expressions of alphanumerics and no white space + * quite hard: could be almost anything but white space, but we are a little + * conservative, aiming for regular expressions of alphanumerics and no white + * space */ -int -isregexc(int r) -{ - if(r == 0) - return FALSE; - if(isalnum(r)) - return TRUE; - if(utfrune("^+-.*?#,;[]()$", r)!=nil) - return TRUE; - return FALSE; +int isregexc(int r) { + if (r == 0) + return FALSE; + if (isalnum(r)) + return TRUE; + if (utfrune("^+-.*?#,;[]()$", r) != nil) + return TRUE; + return FALSE; } // nlcounttopos starts at q0 and advances nl lines, @@ -54,242 +42,246 @@ isregexc(int r) // and then nr chars, being careful not to walk past // the end of the current line. // It returns the final position. -long -nlcounttopos(Text *t, long q0, long nl, long nr) -{ - while(nl > 0 && q0 < t->file->b.nc) { - if(textreadc(t, q0++) == '\n') - nl--; - } - if(nl > 0) - return q0; - while(nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') { - q0++; - nr--; - } - return q0; +long nlcounttopos(Text* t, long q0, long nl, long nr) { + while (nl > 0 && q0 < t->file->b.nc) { + if (textreadc(t, q0++) == '\n') + nl--; + } + if (nl > 0) + return q0; + while (nr > 0 && q0 < t->file->b.nc && textreadc(t, q0) != '\n') { + q0++; + nr--; + } + return q0; } -Range -number(uint showerr, Text *t, Range r, int line, int dir, int size, int *evalp) -{ - uint q0, q1; +Range number( + uint showerr, Text* t, Range r, int line, int dir, int size, int* evalp) { + uint q0, q1; - if(size == Char){ - if(dir == Fore) - line = r.q1+line; - else if(dir == Back){ - if(r.q0==0 && line>0) - r.q0 = t->file->b.nc; - line = r.q0 - line; - } - if(line<0 || line>t->file->b.nc) - goto Rescue; - *evalp = TRUE; - return range(line, line); - } - q0 = r.q0; - q1 = r.q1; - switch(dir){ - case None: - q0 = 0; - q1 = 0; - Forward: - while(line>0 && q1file->b.nc) - if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc) - if(--line > 0) - q0 = q1; - if(line==1 && q1==t->file->b.nc) // 6 goes to end of 5-line file - break; - if(line > 0) - goto Rescue; - break; - case Fore: - if(q1 > 0) - while(q1file->b.nc && textreadc(t, q1-1) != '\n') - q1++; - q0 = q1; - goto Forward; - case Back: - if(q0 < t->file->b.nc) - while(q0>0 && textreadc(t, q0-1)!='\n') - q0--; - q1 = q0; - while(line>0 && q0>0){ - if(textreadc(t, q0-1) == '\n'){ - if(--line >= 0) - q1 = q0; - } - --q0; - } - /* :1-1 is :0 = #0, but :1-2 is an error */ - if(line > 1) - goto Rescue; - while(q0>0 && textreadc(t, q0-1)!='\n') - --q0; - } - *evalp = TRUE; - return range(q0, q1); + if (size == Char) { + if (dir == Fore) + line = r.q1 + line; + else if (dir == Back) { + if (r.q0 == 0 && line > 0) + r.q0 = t->file->b.nc; + line = r.q0 - line; + } + if (line < 0 || line > t->file->b.nc) + goto Rescue; + *evalp = TRUE; + return range(line, line); + } + q0 = r.q0; + q1 = r.q1; + switch (dir) { + case None: + q0 = 0; + q1 = 0; + Forward: + while (line > 0 && q1 < t->file->b.nc) + if (textreadc(t, q1++) == '\n' || q1 == t->file->b.nc) + if (--line > 0) + q0 = q1; + if (line == 1 && q1 == t->file->b.nc) // 6 goes to end of 5-line file + break; + if (line > 0) + goto Rescue; + break; + case Fore: + if (q1 > 0) + while (q1 < t->file->b.nc && textreadc(t, q1 - 1) != '\n') + q1++; + q0 = q1; + goto Forward; + case Back: + if (q0 < t->file->b.nc) + while (q0 > 0 && textreadc(t, q0 - 1) != '\n') + q0--; + q1 = q0; + while (line > 0 && q0 > 0) { + if (textreadc(t, q0 - 1) == '\n') { + if (--line >= 0) + q1 = q0; + } + --q0; + } + /* :1-1 is :0 = #0, but :1-2 is an error */ + if (line > 1) + goto Rescue; + while (q0 > 0 && textreadc(t, q0 - 1) != '\n') + --q0; + } + *evalp = TRUE; + return range(q0, q1); - Rescue: - if(showerr) - warning(nil, "address out of range\n"); - *evalp = FALSE; - return r; +Rescue: + if (showerr) + warning(nil, "address out of range\n"); + *evalp = FALSE; + return r; } +Range regexp( + uint showerr, Text* t, Range lim, Range r, Rune* pat, int dir, int* foundp) { + int found; + Rangeset sel; + int q; -Range -regexp(uint showerr, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp) -{ - int found; - Rangeset sel; - int q; - - if(pat[0] == '\0' && rxnull()){ - if(showerr) - warning(nil, "no previous regular expression\n"); - *foundp = FALSE; - return r; - } - if(pat[0] && rxcompile(pat) == FALSE){ - *foundp = FALSE; - return r; - } - if(dir == Back) - found = rxbexecute(t, r.q0, &sel); - else{ - if(lim.q0 < 0) - q = Infinity; - else - q = lim.q1; - found = rxexecute(t, nil, r.q1, q, &sel); - } - if(!found && showerr) - warning(nil, "no match for regexp\n"); - *foundp = found; - return sel.r[0]; + if (pat[0] == '\0' && rxnull()) { + if (showerr) + warning(nil, "no previous regular expression\n"); + *foundp = FALSE; + return r; + } + if (pat[0] && rxcompile(pat) == FALSE) { + *foundp = FALSE; + return r; + } + if (dir == Back) + found = rxbexecute(t, r.q0, &sel); + else { + if (lim.q0 < 0) + q = Infinity; + else + q = lim.q1; + found = rxexecute(t, nil, r.q1, q, &sel); + } + if (!found && showerr) + warning(nil, "no match for regexp\n"); + *foundp = found; + return sel.r[0]; } -Range -address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint), int *evalp, uint *qp) -{ - int dir, size, npat; - int prevc, c, nc, n; - uint q; - Rune *pat; - Range r, nr; +Range address( + uint showerr, Text* t, Range lim, Range ar, void* a, uint q0, uint q1, + int (*getc)(void*, uint), int* evalp, uint* qp) { + int dir, size, npat; + int prevc, c, nc, n; + uint q; + Rune* pat; + Range r, nr; - r = ar; - q = q0; - dir = None; - size = Line; - c = 0; - while(q < q1){ - prevc = c; - c = (*getc)(a, q++); - switch(c){ - default: - *qp = q-1; - return r; - case ';': - ar = r; - /* fall through */ - case ',': - if(prevc == 0) /* lhs defaults to 0 */ - r.q0 = 0; - if(q>=q1 && t!=nil && t->file!=nil) /* rhs defaults to $ */ - r.q1 = t->file->b.nc; - else{ - nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q); - r.q1 = nr.q1; - } - *qp = q; - return r; - case '+': - case '-': - if(*evalp && (prevc=='+' || prevc=='-')) - if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?') - r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one */ - dir = c; - break; - case '.': - case '$': - if(q != q0+1){ - *qp = q-1; - return r; - } - if(*evalp) - if(c == '.') - r = ar; - else - r = range(t->file->b.nc, t->file->b.nc); - if(q < q1) - dir = Fore; - else - dir = None; - break; - case '#': - if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'= q1 && t != nil && t->file != nil) /* rhs defaults to $ */ + r.q1 = t->file->b.nc; + else { + nr = address(showerr, t, lim, ar, a, q, q1, getc, evalp, &q); + r.q1 = nr.q1; + } + *qp = q; + return r; + case '+': + case '-': + if (*evalp && (prevc == '+' || prevc == '-')) + if ((nc = (*getc)(a, q)) != '#' && nc != '/' && nc != '?') + r = number(showerr, t, r, 1, prevc, Line, evalp); /* do previous one + */ + dir = c; + break; + case '.': + case '$': + if (q != q0 + 1) { + *qp = q - 1; + return r; + } + if (*evalp) + if (c == '.') + r = ar; + else + r = range(t->file->b.nc, t->file->b.nc); + if (q < q1) + dir = Fore; + else + dir = None; + break; + case '#': + if (q == q1 || (c = (*getc)(a, q++)) < '0' || '9' < c) { + *qp = q - 1; + return r; + } + size = Char; + /* fall through */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = c - '0'; + while (q < q1) { + nc = (*getc)(a, q++); + if (nc < '0' || '9' < nc) { + q--; + break; + } + n = n * 10 + (nc - '0'); + } + if (*evalp) + r = number(showerr, t, r, n, dir, size, evalp); + dir = None; + size = Line; + break; + case '?': + dir = Back; + /* fall through */ + case '/': + npat = 0; + pat = nil; + while (q < q1) { + c = (*getc)(a, q++); + switch (c) { + case '\n': + --q; + goto out; + case '\\': + pat = runerealloc(pat, npat + 1); + pat[npat++] = c; + if (q == q1) + goto out; + c = (*getc)(a, q++); + break; + case '/': + goto out; + } + pat = runerealloc(pat, npat + 1); + pat[npat++] = c; + } + out: + pat = runerealloc(pat, npat + 1); + pat[npat] = 0; + if (*evalp) + r = regexp(showerr, t, lim, r, pat, dir, evalp); + free(pat); + dir = None; + size = Line; + break; + } + } + if (*evalp && dir != None) + r = number(showerr, t, r, 1, dir, Line, evalp); /* do previous one */ + *qp = q; + return r; } diff --git a/buff.c b/buff.c index bb938ca..a02c0a6 100644 --- a/buff.c +++ b/buff.c @@ -12,47 +12,37 @@ #include "dat.h" #include "fns.h" -enum -{ - Slop = 100 /* room to grow with reallocation */ +enum { + Slop = 100 /* room to grow with reallocation */ }; -static -void -sizecache(Buffer *b, uint n) -{ - if(n <= b->cmax) - return; - b->cmax = n+Slop; - b->c = runerealloc(b->c, b->cmax); +static void sizecache(Buffer* b, uint n) { + if (n <= b->cmax) + return; + b->cmax = n + Slop; + b->c = runerealloc(b->c, b->cmax); } -static -void -addblock(Buffer *b, uint i, uint n) -{ - if(i > b->nbl) - error("internal error: addblock"); +static void addblock(Buffer* b, uint i, uint n) { + if (i > b->nbl) + error("internal error: addblock"); - b->bl = realloc(b->bl, (b->nbl+1)*sizeof b->bl[0]); - if(i < b->nbl) - memmove(b->bl+i+1, b->bl+i, (b->nbl-i)*sizeof(Block*)); - b->bl[i] = disknewblock(disk, n); - b->nbl++; + b->bl = realloc(b->bl, (b->nbl + 1) * sizeof b->bl[0]); + if (i < b->nbl) + memmove(b->bl + i + 1, b->bl + i, (b->nbl - i) * sizeof(Block*)); + b->bl[i] = disknewblock(disk, n); + b->nbl++; } -static -void -delblock(Buffer *b, uint i) -{ - if(i >= b->nbl) - error("internal error: delblock"); +static void delblock(Buffer* b, uint i) { + if (i >= b->nbl) + error("internal error: delblock"); - diskrelease(disk, b->bl[i]); - b->nbl--; - if(i < b->nbl) - memmove(b->bl+i, b->bl+i+1, (b->nbl-i)*sizeof(Block*)); - b->bl = realloc(b->bl, b->nbl*sizeof b->bl[0]); + diskrelease(disk, b->bl[i]); + b->nbl--; + if (i < b->nbl) + memmove(b->bl + i, b->bl + i + 1, (b->nbl - i) * sizeof(Block*)); + b->bl = realloc(b->bl, b->nbl * sizeof b->bl[0]); } /* @@ -60,266 +50,246 @@ delblock(Buffer *b, uint i) * If at very end, q0 will fall on end of cache block. */ -static -void -flush(Buffer *b) -{ - if(b->cdirty || b->cnc==0){ - if(b->cnc == 0) - delblock(b, b->cbi); - else - diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc); - b->cdirty = FALSE; - } +static void flush(Buffer* b) { + if (b->cdirty || b->cnc == 0) { + if (b->cnc == 0) + delblock(b, b->cbi); + else + diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc); + b->cdirty = FALSE; + } } -static -void -setcache(Buffer *b, uint q0) -{ - Block **blp, *bl; - uint i, q; +static void setcache(Buffer* b, uint q0) { + Block **blp, *bl; + uint i, q; - if(q0 > b->nc) - error("internal error: setcache"); - /* - * flush and reload if q0 is not in cache. - */ - if(b->nc == 0 || (b->cq<=q0 && q0cq+b->cnc)) - return; - /* - * if q0 is at end of file and end of cache, continue to grow this block - */ - if(q0==b->nc && q0==b->cq+b->cnc && b->cnccq){ - q = 0; - i = 0; - }else{ - q = b->cq; - i = b->cbi; - } - blp = &b->bl[i]; - while(q+(*blp)->u.n <= q0 && q+(*blp)->u.n < b->nc){ - q += (*blp)->u.n; - i++; - blp++; - if(i >= b->nbl) - error("block not found"); - } - bl = *blp; - /* remember position */ - b->cbi = i; - b->cq = q; - sizecache(b, bl->u.n); - b->cnc = bl->u.n; - /*read block*/ - diskread(disk, bl, b->c, b->cnc); + if (q0 > b->nc) + error("internal error: setcache"); + /* + * flush and reload if q0 is not in cache. + */ + if (b->nc == 0 || (b->cq <= q0 && q0 < b->cq + b->cnc)) + return; + /* + * if q0 is at end of file and end of cache, continue to grow this block + */ + if (q0 == b->nc && q0 == b->cq + b->cnc && b->cnc < Maxblock) + return; + flush(b); + /* find block */ + if (q0 < b->cq) { + q = 0; + i = 0; + } else { + q = b->cq; + i = b->cbi; + } + blp = &b->bl[i]; + while (q + (*blp)->u.n <= q0 && q + (*blp)->u.n < b->nc) { + q += (*blp)->u.n; + i++; + blp++; + if (i >= b->nbl) + error("block not found"); + } + bl = *blp; + /* remember position */ + b->cbi = i; + b->cq = q; + sizecache(b, bl->u.n); + b->cnc = bl->u.n; + /*read block*/ + diskread(disk, bl, b->c, b->cnc); } -void -bufinsert(Buffer *b, uint q0, Rune *s, uint n) -{ - uint i, m, t, off; +void bufinsert(Buffer* b, uint q0, Rune* s, uint n) { + uint i, m, t, off; - if(q0 > b->nc) - error("internal error: bufinsert"); + if (q0 > b->nc) + error("internal error: bufinsert"); - while(n > 0){ - setcache(b, q0); - off = q0-b->cq; - if(b->cnc+n <= Maxblock){ - /* Everything fits in one block. */ - t = b->cnc+n; - m = n; - if(b->bl == nil){ /* allocate */ - if(b->cnc != 0) - error("internal error: bufinsert1 cnc!=0"); - addblock(b, 0, t); - b->cbi = 0; - } - sizecache(b, t); - runemove(b->c+off+m, b->c+off, b->cnc-off); - runemove(b->c+off, s, m); - b->cnc = t; - goto Tail; - } - /* - * We must make a new block. If q0 is at - * the very beginning or end of this block, - * just make a new block and fill it. - */ - if(q0==b->cq || q0==b->cq+b->cnc){ - if(b->cdirty) - flush(b); - m = min(n, Maxblock); - if(b->bl == nil){ /* allocate */ - if(b->cnc != 0) - error("internal error: bufinsert2 cnc!=0"); - i = 0; - }else{ - i = b->cbi; - if(q0 > b->cq) - i++; - } - addblock(b, i, m); - sizecache(b, m); - runemove(b->c, s, m); - b->cq = q0; - b->cbi = i; - b->cnc = m; - goto Tail; - } - /* - * Split the block; cut off the right side and - * let go of it. - */ - m = b->cnc-off; - if(m > 0){ - i = b->cbi+1; - addblock(b, i, m); - diskwrite(disk, &b->bl[i], b->c+off, m); - b->cnc -= m; - } - /* - * Now at end of block. Take as much input - * as possible and tack it on end of block. - */ - m = min(n, Maxblock-b->cnc); - sizecache(b, b->cnc+m); - runemove(b->c+b->cnc, s, m); - b->cnc += m; + while (n > 0) { + setcache(b, q0); + off = q0 - b->cq; + if (b->cnc + n <= Maxblock) { + /* Everything fits in one block. */ + t = b->cnc + n; + m = n; + if (b->bl == nil) { /* allocate */ + if (b->cnc != 0) + error("internal error: bufinsert1 cnc!=0"); + addblock(b, 0, t); + b->cbi = 0; + } + sizecache(b, t); + runemove(b->c + off + m, b->c + off, b->cnc - off); + runemove(b->c + off, s, m); + b->cnc = t; + goto Tail; + } + /* + * We must make a new block. If q0 is at + * the very beginning or end of this block, + * just make a new block and fill it. + */ + if (q0 == b->cq || q0 == b->cq + b->cnc) { + if (b->cdirty) + flush(b); + m = min(n, Maxblock); + if (b->bl == nil) { /* allocate */ + if (b->cnc != 0) + error("internal error: bufinsert2 cnc!=0"); + i = 0; + } else { + i = b->cbi; + if (q0 > b->cq) + i++; + } + addblock(b, i, m); + sizecache(b, m); + runemove(b->c, s, m); + b->cq = q0; + b->cbi = i; + b->cnc = m; + goto Tail; + } + /* + * Split the block; cut off the right side and + * let go of it. + */ + m = b->cnc - off; + if (m > 0) { + i = b->cbi + 1; + addblock(b, i, m); + diskwrite(disk, &b->bl[i], b->c + off, m); + b->cnc -= m; + } + /* + * Now at end of block. Take as much input + * as possible and tack it on end of block. + */ + m = min(n, Maxblock - b->cnc); + sizecache(b, b->cnc + m); + runemove(b->c + b->cnc, s, m); + b->cnc += m; Tail: - b->nc += m; - q0 += m; - s += m; - n -= m; - b->cdirty = TRUE; - } + b->nc += m; + q0 += m; + s += m; + n -= m; + b->cdirty = TRUE; + } } -void -bufdelete(Buffer *b, uint q0, uint q1) -{ - uint m, n, off; +void bufdelete(Buffer* b, uint q0, uint q1) { + uint m, n, off; - if(!(q0<=q1 && q0<=b->nc && q1<=b->nc)) - error("internal error: bufdelete"); - while(q1 > q0){ - setcache(b, q0); - off = q0-b->cq; - if(q1 > b->cq+b->cnc) - n = b->cnc - off; - else - n = q1-q0; - m = b->cnc - (off+n); - if(m > 0) - runemove(b->c+off, b->c+off+n, m); - b->cnc -= n; - b->cdirty = TRUE; - q1 -= n; - b->nc -= n; - } + if (!(q0 <= q1 && q0 <= b->nc && q1 <= b->nc)) + error("internal error: bufdelete"); + while (q1 > q0) { + setcache(b, q0); + off = q0 - b->cq; + if (q1 > b->cq + b->cnc) + n = b->cnc - off; + else + n = q1 - q0; + m = b->cnc - (off + n); + if (m > 0) + runemove(b->c + off, b->c + off + n, m); + b->cnc -= n; + b->cdirty = TRUE; + q1 -= n; + b->nc -= n; + } } -static int -bufloader(void *v, uint q0, Rune *r, int nr) -{ - bufinsert(v, q0, r, nr); - return nr; +static int bufloader(void* v, uint q0, Rune* r, int nr) { + bufinsert(v, q0, r, nr); + return nr; } -uint -loadfile(int fd, uint q0, int *nulls, int(*f)(void*, uint, Rune*, int), void *arg, DigestState *h) -{ - char *p; - Rune *r; - int l, m, n, nb, nr; - uint q1; +uint loadfile( + int fd, uint q0, int* nulls, int (*f)(void*, uint, Rune*, int), void* arg, + DigestState* h) { + char* p; + Rune* r; + int l, m, n, nb, nr; + uint q1; - p = emalloc((Maxblock+UTFmax+1)*sizeof p[0]); - r = runemalloc(Maxblock); - m = 0; - n = 1; - q1 = q0; - /* - * At top of loop, may have m bytes left over from - * last pass, possibly representing a partial rune. - */ - while(n > 0){ - n = read(fd, p+m, Maxblock); - if(n < 0){ - warning(nil, "read error in Buffer.load"); - break; - } - if(h != nil) - sha1((uchar*)p+m, n, nil, h); - m += n; - p[m] = 0; - l = m; - if(n > 0) - l -= UTFmax; - cvttorunes(p, l, r, &nb, &nr, nulls); - memmove(p, p+nb, m-nb); - m -= nb; - q1 += (*f)(arg, q1, r, nr); - } - free(p); - free(r); - return q1-q0; + p = emalloc((Maxblock + UTFmax + 1) * sizeof p[0]); + r = runemalloc(Maxblock); + m = 0; + n = 1; + q1 = q0; + /* + * At top of loop, may have m bytes left over from + * last pass, possibly representing a partial rune. + */ + while (n > 0) { + n = read(fd, p + m, Maxblock); + if (n < 0) { + warning(nil, "read error in Buffer.load"); + break; + } + if (h != nil) + sha1((uchar*)p + m, n, nil, h); + m += n; + p[m] = 0; + l = m; + if (n > 0) + l -= UTFmax; + cvttorunes(p, l, r, &nb, &nr, nulls); + memmove(p, p + nb, m - nb); + m -= nb; + q1 += (*f)(arg, q1, r, nr); + } + free(p); + free(r); + return q1 - q0; } -uint -bufload(Buffer *b, uint q0, int fd, int *nulls, DigestState *h) -{ - if(q0 > b->nc) - error("internal error: bufload"); - return loadfile(fd, q0, nulls, bufloader, b, h); +uint bufload(Buffer* b, uint q0, int fd, int* nulls, DigestState* h) { + if (q0 > b->nc) + error("internal error: bufload"); + return loadfile(fd, q0, nulls, bufloader, b, h); } -void -bufread(Buffer *b, uint q0, Rune *s, uint n) -{ - uint m; +void bufread(Buffer* b, uint q0, Rune* s, uint n) { + uint m; - if(!(q0<=b->nc && q0+n<=b->nc)) - error("bufread: internal error"); + if (!(q0 <= b->nc && q0 + n <= b->nc)) + error("bufread: internal error"); - while(n > 0){ - setcache(b, q0); - m = min(n, b->cnc-(q0-b->cq)); - runemove(s, b->c+(q0-b->cq), m); - q0 += m; - s += m; - n -= m; - } + while (n > 0) { + setcache(b, q0); + m = min(n, b->cnc - (q0 - b->cq)); + runemove(s, b->c + (q0 - b->cq), m); + q0 += m; + s += m; + n -= m; + } } -void -bufreset(Buffer *b) -{ - int i; +void bufreset(Buffer* b) { + int i; - b->nc = 0; - b->cnc = 0; - b->cq = 0; - b->cdirty = 0; - b->cbi = 0; - /* delete backwards to avoid n² behavior */ - for(i=b->nbl-1; --i>=0; ) - delblock(b, i); + b->nc = 0; + b->cnc = 0; + b->cq = 0; + b->cdirty = 0; + b->cbi = 0; + /* delete backwards to avoid n² behavior */ + for (i = b->nbl - 1; --i >= 0;) + delblock(b, i); } -void -bufclose(Buffer *b) -{ - bufreset(b); - free(b->c); - b->c = nil; - b->cnc = 0; - free(b->bl); - b->bl = nil; - b->nbl = 0; +void bufclose(Buffer* b) { + bufreset(b); + free(b->c); + b->c = nil; + b->cnc = 0; + free(b->bl); + b->bl = nil; + b->nbl = 0; } diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..b39d5a4 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +clang-format -i ./*.c +clang-format -i ./mail/*.c + +mk + +mv o.acme acme diff --git a/cols.c b/cols.c index 0c7aaf0..f05ac1c 100644 --- a/cols.c +++ b/cols.c @@ -12,575 +12,604 @@ #include "dat.h" #include "fns.h" -static Rune Lheader[] = { - 'N', 'e', 'w', ' ', - 'C', 'u', 't', ' ', - 'P', 'a', 's', 't', 'e', ' ', - 'S', 'n', 'a', 'r', 'f', ' ', - 'S', 'o', 'r', 't', ' ', - 'Z', 'e', 'r', 'o', 'x', ' ', - 'D', 'e', 'l', 'c', 'o', 'l', ' ', - 0 -}; +static Rune Lheader[] = {'N', 'e', 'w', ' ', 'C', 'u', 't', ' ', 'P', 'a', + 's', 't', 'e', ' ', 'S', 'n', 'a', 'r', 'f', ' ', + 'S', 'o', 'r', 't', ' ', 'Z', 'e', 'r', 'o', 'x', + ' ', 'D', 'e', 'l', 'c', 'o', 'l', ' ', 0}; -void -colinit(Column *c, Rectangle r) -{ - Rectangle r1; - Text *t; +void colinit(Column* c, Rectangle r) { + Rectangle r1; + Text* t; - draw(screen, r, allocimage(display,Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - c->r = r; - c->w = nil; - c->nw = 0; - t = &c->tag; - t->w = nil; - t->col = c; - r1 = r; - r1.max.y = r1.min.y + font->height; - textinit(t, fileaddtext(nil, t), r1, &reffont, tagcols); - t->what = Columntag; - r1.min.y = r1.max.y; - r1.max.y += Border; - draw(screen, r1, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - textinsert(t, 0, Lheader, 38, TRUE); - textsetselect(t, t->file->b.nc, t->file->b.nc); - draw(screen, t->scrollr, colbutton, nil, colbutton->r.min); - c->safe = TRUE; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + c->r = r; + c->w = nil; + c->nw = 0; + t = &c->tag; + t->w = nil; + t->col = c; + r1 = r; + r1.max.y = r1.min.y + font->height; + textinit(t, fileaddtext(nil, t), r1, &reffont, tagcols); + t->what = Columntag; + r1.min.y = r1.max.y; + r1.max.y += Border; + draw( + screen, + r1, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + textinsert(t, 0, Lheader, 38, TRUE); + textsetselect(t, t->file->b.nc, t->file->b.nc); + draw(screen, t->scrollr, colbutton, nil, colbutton->r.min); + c->safe = TRUE; } -Window* -coladd(Column *c, Window *w, Window *clone, int y) -{ - Rectangle r, r1; - Window *v; - int i, j, minht, ymax, buggered; +Window* coladd(Column* c, Window* w, Window* clone, int y) { + Rectangle r, r1; + Window* v; + int i, j, minht, ymax, buggered; - v = nil; - r = c->r; - r.min.y = c->tag.fr.r.max.y+Border; - if(ynw>0){ /* steal half of last window by default */ - v = c->w[c->nw-1]; - y = v->body.fr.r.min.y+Dy(v->body.fr.r)/2; - } - /* look for window we'll land on */ - for(i=0; inw; i++){ - v = c->w[i]; - if(y < v->r.max.y) - break; - } - buggered = 0; - if(c->nw > 0){ - if(i < c->nw) - i++; /* new window will go after v */ - /* - * if landing window (v) is too small, grow it first. - */ - minht = v->tag.fr.font->height+Border+1; - j = 0; - while(!c->safe || v->body.fr.maxlines<=3 || Dy(v->body.all) <= minht){ - if(++j > 10){ - buggered = 1; /* too many windows in column */ - break; - } - colgrow(c, v, 1); - } + v = nil; + r = c->r; + r.min.y = c->tag.fr.r.max.y + Border; + if (y < r.min.y && c->nw > 0) { /* steal half of last window by default */ + v = c->w[c->nw - 1]; + y = v->body.fr.r.min.y + Dy(v->body.fr.r) / 2; + } + /* look for window we'll land on */ + for (i = 0; i < c->nw; i++) { + v = c->w[i]; + if (y < v->r.max.y) + break; + } + buggered = 0; + if (c->nw > 0) { + if (i < c->nw) + i++; /* new window will go after v */ + /* + * if landing window (v) is too small, grow it first. + */ + minht = v->tag.fr.font->height + Border + 1; + j = 0; + while (!c->safe || v->body.fr.maxlines <= 3 || Dy(v->body.all) <= minht) { + if (++j > 10) { + buggered = 1; /* too many windows in column */ + break; + } + colgrow(c, v, 1); + } - /* - * figure out where to split v to make room for w - */ - - /* new window stops where next window begins */ - if(i < c->nw) - ymax = c->w[i]->r.min.y-Border; - else - ymax = c->r.max.y; - - /* new window must start after v's tag ends */ - y = max(y, v->tagtop.max.y+Border); - - /* new window must start early enough to end before ymax */ - y = min(y, ymax - minht); - - /* if y is too small, too many windows in column */ - if(y < v->tagtop.max.y+Border) - buggered = 1; + /* + * figure out where to split v to make room for w + */ - /* - * resize & redraw v - */ - r = v->r; - r.max.y = ymax; - draw(screen, r, textcols[BACK], nil, ZP); - r1 = r; - y = min(y, ymax-(v->tag.fr.font->height*v->taglines+v->body.fr.font->height+Border+1)); - r1.max.y = min(y, v->body.fr.r.min.y+v->body.fr.nlines*v->body.fr.font->height); - r1.min.y = winresize(v, r1, FALSE, FALSE); - r1.max.y = r1.min.y+Border; - draw(screen, r1, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - - /* - * leave r with w's coordinates - */ - r.min.y = r1.max.y; - } - if(w == nil){ - w = emalloc(sizeof(Window)); - w->col = c; - draw(screen, r, textcols[BACK], nil, ZP); - wininit(w, clone, r); - }else{ - w->col = c; - winresize(w, r, FALSE, TRUE); - } - w->tag.col = c; - w->tag.row = c->row; - w->body.col = c; - w->body.row = c->row; - c->w = realloc(c->w, (c->nw+1)*sizeof(Window*)); - memmove(c->w+i+1, c->w+i, (c->nw-i)*sizeof(Window*)); - c->nw++; - c->w[i] = w; - c->safe = TRUE; - - /* if there were too many windows, redraw the whole column */ - if(buggered) - colresize(c, c->r); + /* new window stops where next window begins */ + if (i < c->nw) + ymax = c->w[i]->r.min.y - Border; + else + ymax = c->r.max.y; - savemouse(w); - /* near the button, but in the body */ - moveto(mousectl, addpt(w->tag.scrollr.max, Pt(3, 3))); - barttext = &w->body; - return w; + /* new window must start after v's tag ends */ + y = max(y, v->tagtop.max.y + Border); + + /* new window must start early enough to end before ymax */ + y = min(y, ymax - minht); + + /* if y is too small, too many windows in column */ + if (y < v->tagtop.max.y + Border) + buggered = 1; + + /* + * resize & redraw v + */ + r = v->r; + r.max.y = ymax; + draw(screen, r, textcols[BACK], nil, ZP); + r1 = r; + y = min( + y, + ymax - (v->tag.fr.font->height * v->taglines + v->body.fr.font->height + + Border + 1)); + r1.max.y = + min(y, v->body.fr.r.min.y + v->body.fr.nlines * v->body.fr.font->height); + r1.min.y = winresize(v, r1, FALSE, FALSE); + r1.max.y = r1.min.y + Border; + draw( + screen, + r1, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + + /* + * leave r with w's coordinates + */ + r.min.y = r1.max.y; + } + if (w == nil) { + w = emalloc(sizeof(Window)); + w->col = c; + draw(screen, r, textcols[BACK], nil, ZP); + wininit(w, clone, r); + } else { + w->col = c; + winresize(w, r, FALSE, TRUE); + } + w->tag.col = c; + w->tag.row = c->row; + w->body.col = c; + w->body.row = c->row; + c->w = realloc(c->w, (c->nw + 1) * sizeof(Window*)); + memmove(c->w + i + 1, c->w + i, (c->nw - i) * sizeof(Window*)); + c->nw++; + c->w[i] = w; + c->safe = TRUE; + + /* if there were too many windows, redraw the whole column */ + if (buggered) + colresize(c, c->r); + + savemouse(w); + /* near the button, but in the body */ + moveto(mousectl, addpt(w->tag.scrollr.max, Pt(3, 3))); + barttext = &w->body; + return w; } -void -colclose(Column *c, Window *w, int dofree) -{ - Rectangle r; - int i, didmouse, up; +void colclose(Column* c, Window* w, int dofree) { + Rectangle r; + int i, didmouse, up; - /* w is locked */ - if(!c->safe) - colgrow(c, w, 1); - for(i=0; inw; i++) - if(c->w[i] == w) - goto Found; - error("can't find window"); - Found: - r = w->r; - w->tag.col = nil; - w->body.col = nil; - w->col = nil; - didmouse = restoremouse(w); - if(dofree){ - windelete(w); - winclose(w); - } - c->nw--; - memmove(c->w+i, c->w+i+1, (c->nw-i)*sizeof(Window*)); - c->w = realloc(c->w, c->nw*sizeof(Window*)); - if(c->nw == 0){ - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - return; - } - up = 0; - if(i == c->nw){ /* extend last window down */ - w = c->w[i-1]; - r.min.y = w->r.min.y; - r.max.y = c->r.max.y; - }else{ /* extend next window up */ - up = 1; - w = c->w[i]; - r.max.y = w->r.max.y; - } - draw(screen, r, textcols[BACK], nil, ZP); - if(c->safe) { - if(!didmouse && up) - w->showdel = TRUE; - winresize(w, r, FALSE, TRUE); - if(!didmouse && up) - movetodel(w); - } + /* w is locked */ + if (!c->safe) + colgrow(c, w, 1); + for (i = 0; i < c->nw; i++) + if (c->w[i] == w) + goto Found; + error("can't find window"); +Found: + r = w->r; + w->tag.col = nil; + w->body.col = nil; + w->col = nil; + didmouse = restoremouse(w); + if (dofree) { + windelete(w); + winclose(w); + } + c->nw--; + memmove(c->w + i, c->w + i + 1, (c->nw - i) * sizeof(Window*)); + c->w = realloc(c->w, c->nw * sizeof(Window*)); + if (c->nw == 0) { + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + return; + } + up = 0; + if (i == c->nw) { /* extend last window down */ + w = c->w[i - 1]; + r.min.y = w->r.min.y; + r.max.y = c->r.max.y; + } else { /* extend next window up */ + up = 1; + w = c->w[i]; + r.max.y = w->r.max.y; + } + draw(screen, r, textcols[BACK], nil, ZP); + if (c->safe) { + if (!didmouse && up) + w->showdel = TRUE; + winresize(w, r, FALSE, TRUE); + if (!didmouse && up) + movetodel(w); + } } -void -colcloseall(Column *c) -{ - int i; - Window *w; +void colcloseall(Column* c) { + int i; + Window* w; - if(c == activecol) - activecol = nil; - textclose(&c->tag); - for(i=0; inw; i++){ - w = c->w[i]; - winclose(w); - } - c->nw = 0; - free(c->w); - free(c); - clearmouse(); + if (c == activecol) + activecol = nil; + textclose(&c->tag); + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + winclose(w); + } + c->nw = 0; + free(c->w); + free(c); + clearmouse(); } -void -colmousebut(Column *c) -{ - moveto(mousectl, divpt(addpt(c->tag.scrollr.min, c->tag.scrollr.max), 2)); +void colmousebut(Column* c) { + moveto(mousectl, divpt(addpt(c->tag.scrollr.min, c->tag.scrollr.max), 2)); } -void -colresize(Column *c, Rectangle r) -{ - int i; - Rectangle r1, r2; - Window *w; +void colresize(Column* c, Rectangle r) { + int i; + Rectangle r1, r2; + Window* w; - clearmouse(); - r1 = r; - r1.max.y = r1.min.y + c->tag.fr.font->height; - textresize(&c->tag, r1, TRUE); - draw(screen, c->tag.scrollr, colbutton, nil, colbutton->r.min); - r1.min.y = r1.max.y; - r1.max.y += Border; - draw(screen, r1, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r1.max.y = r.max.y; - for(i=0; inw; i++){ - w = c->w[i]; - w->maxlines = 0; - if(i == c->nw-1) - r1.max.y = r.max.y; - else{ - r1.max.y = r1.min.y; - if(Dy(c->r) != 0){ - r1.max.y += (Dy(w->r)+Border)*Dy(r)/Dy(c->r); - } - } - r1.max.y = max(r1.max.y, r1.min.y + Border+font->height); - r2 = r1; - r2.max.y = r2.min.y+Border; - draw(screen, r2, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r1.min.y = r2.max.y; - r1.min.y = winresize(w, r1, FALSE, i==c->nw-1); - } - c->r = r; + clearmouse(); + r1 = r; + r1.max.y = r1.min.y + c->tag.fr.font->height; + textresize(&c->tag, r1, TRUE); + draw(screen, c->tag.scrollr, colbutton, nil, colbutton->r.min); + r1.min.y = r1.max.y; + r1.max.y += Border; + draw( + screen, + r1, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r1.max.y = r.max.y; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + w->maxlines = 0; + if (i == c->nw - 1) + r1.max.y = r.max.y; + else { + r1.max.y = r1.min.y; + if (Dy(c->r) != 0) { + r1.max.y += (Dy(w->r) + Border) * Dy(r) / Dy(c->r); + } + } + r1.max.y = max(r1.max.y, r1.min.y + Border + font->height); + r2 = r1; + r2.max.y = r2.min.y + Border; + draw( + screen, + r2, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r1.min.y = r2.max.y; + r1.min.y = winresize(w, r1, FALSE, i == c->nw - 1); + } + c->r = r; } -static -int -colcmp(const void *a, const void *b) -{ - Rune *r1, *r2; - int i, nr1, nr2; +static int colcmp(const void* a, const void* b) { + Rune *r1, *r2; + int i, nr1, nr2; - r1 = (*(Window**)a)->body.file->name; - nr1 = (*(Window**)a)->body.file->nname; - r2 = (*(Window**)b)->body.file->name; - nr2 = (*(Window**)b)->body.file->nname; - for(i=0; ibody.file->name; + nr1 = (*(Window**)a)->body.file->nname; + r2 = (*(Window**)b)->body.file->name; + nr2 = (*(Window**)b)->body.file->nname; + for (i = 0; i < nr1 && i < nr2; i++) { + if (*r1 != *r2) + return *r1 - *r2; + r1++; + r2++; + } + return nr1 - nr2; } -void -colsort(Column *c) -{ - int i, y; - Rectangle r, r1, *rp; - Window **wp, *w; +void colsort(Column* c) { + int i, y; + Rectangle r, r1, *rp; + Window **wp, *w; - if(c->nw == 0) - return; - clearmouse(); - rp = emalloc(c->nw*sizeof(Rectangle)); - wp = emalloc(c->nw*sizeof(Window*)); - memmove(wp, c->w, c->nw*sizeof(Window*)); - qsort(wp, c->nw, sizeof(Window*), colcmp); - for(i=0; inw; i++) - rp[i] = wp[i]->r; - r = c->r; - r.min.y = c->tag.fr.r.max.y; - draw(screen, r, textcols[BACK], nil, ZP); - y = r.min.y; - for(i=0; inw; i++){ - w = wp[i]; - r.min.y = y; - if(i == c->nw-1) - r.max.y = c->r.max.y; - else - r.max.y = r.min.y+Dy(w->r)+Border; - r1 = r; - r1.max.y = r1.min.y+Border; - draw(screen, r1, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r.min.y = r1.max.y; - y = winresize(w, r, FALSE, i==c->nw-1); - } - free(rp); - free(c->w); - c->w = wp; + if (c->nw == 0) + return; + clearmouse(); + rp = emalloc(c->nw * sizeof(Rectangle)); + wp = emalloc(c->nw * sizeof(Window*)); + memmove(wp, c->w, c->nw * sizeof(Window*)); + qsort(wp, c->nw, sizeof(Window*), colcmp); + for (i = 0; i < c->nw; i++) + rp[i] = wp[i]->r; + r = c->r; + r.min.y = c->tag.fr.r.max.y; + draw(screen, r, textcols[BACK], nil, ZP); + y = r.min.y; + for (i = 0; i < c->nw; i++) { + w = wp[i]; + r.min.y = y; + if (i == c->nw - 1) + r.max.y = c->r.max.y; + else + r.max.y = r.min.y + Dy(w->r) + Border; + r1 = r; + r1.max.y = r1.min.y + Border; + draw( + screen, + r1, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r.min.y = r1.max.y; + y = winresize(w, r, FALSE, i == c->nw - 1); + } + free(rp); + free(c->w); + c->w = wp; } -void -colgrow(Column *c, Window *w, int but) -{ - Rectangle r, cr; - int i, j, k, l, y1, y2, *nl, *ny, tot, nnl, onl, dnl, h; - Window *v; +void colgrow(Column* c, Window* w, int but) { + Rectangle r, cr; + int i, j, k, l, y1, y2, *nl, *ny, tot, nnl, onl, dnl, h; + Window* v; - for(i=0; inw; i++) - if(c->w[i] == w) - goto Found; - error("can't find window"); + for (i = 0; i < c->nw; i++) + if (c->w[i] == w) + goto Found; + error("can't find window"); - Found: - cr = c->r; - if(but < 0){ /* make sure window fills its own space properly */ - r = w->r; - if(i==c->nw-1 || c->safe==FALSE) - r.max.y = cr.max.y; - else - r.max.y = c->w[i+1]->r.min.y - Border; - winresize(w, r, FALSE, TRUE); - return; - } - cr.min.y = c->w[0]->r.min.y; - if(but == 3){ /* full size */ - if(i != 0){ - v = c->w[0]; - c->w[0] = w; - c->w[i] = v; - } - draw(screen, cr, textcols[BACK], nil, ZP); - winresize(w, cr, FALSE, TRUE); - for(i=1; inw; i++) - c->w[i]->body.fr.maxlines = 0; - c->safe = FALSE; - return; - } - /* store old #lines for each window */ - onl = w->body.fr.maxlines; - nl = emalloc(c->nw * sizeof(int)); - ny = emalloc(c->nw * sizeof(int)); - tot = 0; - for(j=0; jnw; j++){ - l = c->w[j]->taglines-1 + c->w[j]->body.fr.maxlines; - nl[j] = l; - tot += l; - } - /* approximate new #lines for this window */ - if(but == 2){ /* as big as can be */ - memset(nl, 0, c->nw * sizeof(int)); - goto Pack; - } - nnl = min(onl + max(min(5, w->taglines-1+w->maxlines), onl/2), tot); - if(nnl < w->taglines-1+w->maxlines) - nnl = (w->taglines-1+w->maxlines + nnl)/2; - if(nnl == 0) - nnl = 2; - dnl = nnl - onl; - /* compute new #lines for each window */ - for(k=1; knw; k++){ - /* prune from later window */ - j = i+k; - if(jnw && nl[j]){ - l = min(dnl, max(1, nl[j]/2)); - nl[j] -= l; - nl[i] += l; - dnl -= l; - } - /* prune from earlier window */ - j = i-k; - if(j>=0 && nl[j]){ - l = min(dnl, max(1, nl[j]/2)); - nl[j] -= l; - nl[i] += l; - dnl -= l; - } - } - Pack: - /* pack everyone above */ - y1 = cr.min.y; - for(j=0; jw[j]; - r = v->r; - r.min.y = y1; - r.max.y = y1+Dy(v->tagtop); - if(nl[j]) - r.max.y += 1 + nl[j]*v->body.fr.font->height; - r.min.y = winresize(v, r, c->safe, FALSE); - r.max.y += Border; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - y1 = r.max.y; - } - /* scan to see new size of everyone below */ - y2 = c->r.max.y; - for(j=c->nw-1; j>i; j--){ - v = c->w[j]; - r = v->r; - r.min.y = y2-Dy(v->tagtop); - if(nl[j]) - r.min.y -= 1 + nl[j]*v->body.fr.font->height; - r.min.y -= Border; - ny[j] = r.min.y; - y2 = r.min.y; - } - /* compute new size of window */ - r = w->r; - r.min.y = y1; - r.max.y = y2; - h = w->body.fr.font->height; - if(Dy(r) < Dy(w->tagtop)+1+h+Border) - r.max.y = r.min.y + Dy(w->tagtop)+1+h+Border; - /* draw window */ - r.max.y = winresize(w, r, c->safe, TRUE); - if(i < c->nw-1){ - r.min.y = r.max.y; - r.max.y += Border; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - for(j=i+1; jnw; j++) - ny[j] -= (y2-r.max.y); - } - /* pack everyone below */ - y1 = r.max.y; - for(j=i+1; jnw; j++){ - v = c->w[j]; - r = v->r; - r.min.y = y1; - r.max.y = y1+Dy(v->tagtop); - if(nl[j]) - r.max.y += 1 + nl[j]*v->body.fr.font->height; - y1 = winresize(v, r, c->safe, j==c->nw-1); - if(j < c->nw-1){ /* no border on last window */ - r.min.y = y1; - r.max.y += Border; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - y1 = r.max.y; - } - } - free(nl); - free(ny); - c->safe = TRUE; - winmousebut(w); +Found: + cr = c->r; + if (but < 0) { /* make sure window fills its own space properly */ + r = w->r; + if (i == c->nw - 1 || c->safe == FALSE) + r.max.y = cr.max.y; + else + r.max.y = c->w[i + 1]->r.min.y - Border; + winresize(w, r, FALSE, TRUE); + return; + } + cr.min.y = c->w[0]->r.min.y; + if (but == 3) { /* full size */ + if (i != 0) { + v = c->w[0]; + c->w[0] = w; + c->w[i] = v; + } + draw(screen, cr, textcols[BACK], nil, ZP); + winresize(w, cr, FALSE, TRUE); + for (i = 1; i < c->nw; i++) + c->w[i]->body.fr.maxlines = 0; + c->safe = FALSE; + return; + } + /* store old #lines for each window */ + onl = w->body.fr.maxlines; + nl = emalloc(c->nw * sizeof(int)); + ny = emalloc(c->nw * sizeof(int)); + tot = 0; + for (j = 0; j < c->nw; j++) { + l = c->w[j]->taglines - 1 + c->w[j]->body.fr.maxlines; + nl[j] = l; + tot += l; + } + /* approximate new #lines for this window */ + if (but == 2) { /* as big as can be */ + memset(nl, 0, c->nw * sizeof(int)); + goto Pack; + } + nnl = min(onl + max(min(5, w->taglines - 1 + w->maxlines), onl / 2), tot); + if (nnl < w->taglines - 1 + w->maxlines) + nnl = (w->taglines - 1 + w->maxlines + nnl) / 2; + if (nnl == 0) + nnl = 2; + dnl = nnl - onl; + /* compute new #lines for each window */ + for (k = 1; k < c->nw; k++) { + /* prune from later window */ + j = i + k; + if (j < c->nw && nl[j]) { + l = min(dnl, max(1, nl[j] / 2)); + nl[j] -= l; + nl[i] += l; + dnl -= l; + } + /* prune from earlier window */ + j = i - k; + if (j >= 0 && nl[j]) { + l = min(dnl, max(1, nl[j] / 2)); + nl[j] -= l; + nl[i] += l; + dnl -= l; + } + } +Pack: + /* pack everyone above */ + y1 = cr.min.y; + for (j = 0; j < i; j++) { + v = c->w[j]; + r = v->r; + r.min.y = y1; + r.max.y = y1 + Dy(v->tagtop); + if (nl[j]) + r.max.y += 1 + nl[j] * v->body.fr.font->height; + r.min.y = winresize(v, r, c->safe, FALSE); + r.max.y += Border; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + y1 = r.max.y; + } + /* scan to see new size of everyone below */ + y2 = c->r.max.y; + for (j = c->nw - 1; j > i; j--) { + v = c->w[j]; + r = v->r; + r.min.y = y2 - Dy(v->tagtop); + if (nl[j]) + r.min.y -= 1 + nl[j] * v->body.fr.font->height; + r.min.y -= Border; + ny[j] = r.min.y; + y2 = r.min.y; + } + /* compute new size of window */ + r = w->r; + r.min.y = y1; + r.max.y = y2; + h = w->body.fr.font->height; + if (Dy(r) < Dy(w->tagtop) + 1 + h + Border) + r.max.y = r.min.y + Dy(w->tagtop) + 1 + h + Border; + /* draw window */ + r.max.y = winresize(w, r, c->safe, TRUE); + if (i < c->nw - 1) { + r.min.y = r.max.y; + r.max.y += Border; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + for (j = i + 1; j < c->nw; j++) + ny[j] -= (y2 - r.max.y); + } + /* pack everyone below */ + y1 = r.max.y; + for (j = i + 1; j < c->nw; j++) { + v = c->w[j]; + r = v->r; + r.min.y = y1; + r.max.y = y1 + Dy(v->tagtop); + if (nl[j]) + r.max.y += 1 + nl[j] * v->body.fr.font->height; + y1 = winresize(v, r, c->safe, j == c->nw - 1); + if (j < c->nw - 1) { /* no border on last window */ + r.min.y = y1; + r.max.y += Border; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + y1 = r.max.y; + } + } + free(nl); + free(ny); + c->safe = TRUE; + winmousebut(w); } -void -coldragwin(Column *c, Window *w, int but) -{ - Rectangle r; - int i, b; - Point p, op; - Window *v; - Column *nc; +void coldragwin(Column* c, Window* w, int but) { + Rectangle r; + int i, b; + Point p, op; + Window* v; + Column* nc; - clearmouse(); - setcursor2(mousectl, &boxcursor, &boxcursor2); - b = mouse->buttons; - op = mouse->xy; - while(mouse->buttons == b) - readmouse(mousectl); - setcursor(mousectl, nil); - if(mouse->buttons){ - while(mouse->buttons) - readmouse(mousectl); - return; - } + clearmouse(); + setcursor2(mousectl, &boxcursor, &boxcursor2); + b = mouse->buttons; + op = mouse->xy; + while (mouse->buttons == b) + readmouse(mousectl); + setcursor(mousectl, nil); + if (mouse->buttons) { + while (mouse->buttons) + readmouse(mousectl); + return; + } - for(i=0; inw; i++) - if(c->w[i] == w) - goto Found; - error("can't find window"); + for (i = 0; i < c->nw; i++) + if (c->w[i] == w) + goto Found; + error("can't find window"); - Found: - if(w->tagexpand) /* force recomputation of window tag size */ - w->taglines = 1; - p = mouse->xy; - if(abs(p.x-op.x)<5 && abs(p.y-op.y)<5){ - colgrow(c, w, but); - winmousebut(w); - return; - } - /* is it a flick to the right? */ - if(abs(p.y-op.y)<10 && p.x>op.x+30 && rowwhichcol(c->row, p)==c) - p.x = op.x+Dx(w->r); /* yes: toss to next column */ - nc = rowwhichcol(c->row, p); - if(nc!=nil && nc!=c){ - colclose(c, w, FALSE); - coladd(nc, w, nil, p.y); - winmousebut(w); - return; - } - if(i==0 && c->nw==1) - return; /* can't do it */ - if((i>0 && p.yw[i-1]->r.min.y) || (inw-1 && p.y>w->r.max.y) - || (i==0 && p.y>w->r.max.y)){ - /* shuffle */ - colclose(c, w, FALSE); - coladd(c, w, nil, p.y); - winmousebut(w); - return; - } - if(i == 0) - return; - v = c->w[i-1]; - if(p.y < v->tagtop.max.y) - p.y = v->tagtop.max.y; - if(p.y > w->r.max.y-Dy(w->tagtop)-Border) - p.y = w->r.max.y-Dy(w->tagtop)-Border; - r = v->r; - r.max.y = p.y; - if(r.max.y > v->body.fr.r.min.y){ - r.max.y -= (r.max.y-v->body.fr.r.min.y)%v->body.fr.font->height; - if(v->body.fr.r.min.y == v->body.fr.r.max.y) - r.max.y++; - } - r.min.y = winresize(v, r, c->safe, FALSE); - r.max.y = r.min.y+Border; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r.min.y = r.max.y; - if(i == c->nw-1) - r.max.y = c->r.max.y; - else - r.max.y = c->w[i+1]->r.min.y-Border; - winresize(w, r, c->safe, TRUE); - c->safe = TRUE; - winmousebut(w); +Found: + if (w->tagexpand) /* force recomputation of window tag size */ + w->taglines = 1; + p = mouse->xy; + if (abs(p.x - op.x) < 5 && abs(p.y - op.y) < 5) { + colgrow(c, w, but); + winmousebut(w); + return; + } + /* is it a flick to the right? */ + if (abs(p.y - op.y) < 10 && p.x > op.x + 30 && rowwhichcol(c->row, p) == c) + p.x = op.x + Dx(w->r); /* yes: toss to next column */ + nc = rowwhichcol(c->row, p); + if (nc != nil && nc != c) { + colclose(c, w, FALSE); + coladd(nc, w, nil, p.y); + winmousebut(w); + return; + } + if (i == 0 && c->nw == 1) + return; /* can't do it */ + if ( + (i > 0 && p.y < c->w[i - 1]->r.min.y) || + (i < c->nw - 1 && p.y > w->r.max.y) || (i == 0 && p.y > w->r.max.y)) { + /* shuffle */ + colclose(c, w, FALSE); + coladd(c, w, nil, p.y); + winmousebut(w); + return; + } + if (i == 0) + return; + v = c->w[i - 1]; + if (p.y < v->tagtop.max.y) + p.y = v->tagtop.max.y; + if (p.y > w->r.max.y - Dy(w->tagtop) - Border) + p.y = w->r.max.y - Dy(w->tagtop) - Border; + r = v->r; + r.max.y = p.y; + if (r.max.y > v->body.fr.r.min.y) { + r.max.y -= (r.max.y - v->body.fr.r.min.y) % v->body.fr.font->height; + if (v->body.fr.r.min.y == v->body.fr.r.max.y) + r.max.y++; + } + r.min.y = winresize(v, r, c->safe, FALSE); + r.max.y = r.min.y + Border; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r.min.y = r.max.y; + if (i == c->nw - 1) + r.max.y = c->r.max.y; + else + r.max.y = c->w[i + 1]->r.min.y - Border; + winresize(w, r, c->safe, TRUE); + c->safe = TRUE; + winmousebut(w); } -Text* -colwhich(Column *c, Point p) -{ - int i; - Window *w; +Text* colwhich(Column* c, Point p) { + int i; + Window* w; - if(!ptinrect(p, c->r)) - return nil; - if(ptinrect(p, c->tag.all)) - return &c->tag; - for(i=0; inw; i++){ - w = c->w[i]; - if(ptinrect(p, w->r)){ - if(ptinrect(p, w->tagtop) || ptinrect(p, w->tag.all)) - return &w->tag; - /* exclude partial line at bottom */ - if(p.x >= w->body.scrollr.max.x && p.y >= w->body.fr.r.max.y) - return nil; - return &w->body; - } - } - return nil; + if (!ptinrect(p, c->r)) + return nil; + if (ptinrect(p, c->tag.all)) + return &c->tag; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + if (ptinrect(p, w->r)) { + if (ptinrect(p, w->tagtop) || ptinrect(p, w->tag.all)) + return &w->tag; + /* exclude partial line at bottom */ + if (p.x >= w->body.scrollr.max.x && p.y >= w->body.fr.r.max.y) + return nil; + return &w->body; + } + } + return nil; } -int -colclean(Column *c) -{ - int i, clean; +int colclean(Column* c) { + int i, clean; - clean = TRUE; - for(i=0; inw; i++) - clean &= winclean(c->w[i], TRUE); - return clean; + clean = TRUE; + for (i = 0; i < c->nw; i++) + clean &= winclean(c->w[i], TRUE); + return clean; } diff --git a/disk.c b/disk.c index c3ada9c..05e4c80 100644 --- a/disk.c +++ b/disk.c @@ -12,122 +12,107 @@ #include "dat.h" #include "fns.h" -static Block *blist; +static Block* blist; -int -tempfile(void) -{ - char buf[128]; - int i, fd; +int tempfile(void) { + char buf[128]; + int i, fd; - snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser()); - for(i='A'; i<='Z'; i++){ - buf[5] = i; - if(access(buf, AEXIST) == 0) - continue; - fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600); - if(fd >= 0) - return fd; - } - return -1; + snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser()); + for (i = 'A'; i <= 'Z'; i++) { + buf[5] = i; + if (access(buf, AEXIST) == 0) + continue; + fd = create(buf, ORDWR | ORCLOSE | OCEXEC, 0600); + if (fd >= 0) + return fd; + } + return -1; } -Disk* -diskinit() -{ - Disk *d; +Disk* diskinit() { + Disk* d; - d = emalloc(sizeof(Disk)); - d->fd = tempfile(); - if(d->fd < 0){ - fprint(2, "acme: can't create temp file: %r\n"); - threadexitsall("diskinit"); - } - return d; + d = emalloc(sizeof(Disk)); + d->fd = tempfile(); + if (d->fd < 0) { + fprint(2, "acme: can't create temp file: %r\n"); + threadexitsall("diskinit"); + } + return d; } -static -uint -ntosize(uint n, uint *ip) -{ - uint size; +static uint ntosize(uint n, uint* ip) { + uint size; - if(n > Maxblock) - error("internal error: ntosize"); - size = n; - if(size & (Blockincr-1)) - size += Blockincr - (size & (Blockincr-1)); - /* last bucket holds blocks of exactly Maxblock */ - if(ip) - *ip = size/Blockincr; - return size * sizeof(Rune); + if (n > Maxblock) + error("internal error: ntosize"); + size = n; + if (size & (Blockincr - 1)) + size += Blockincr - (size & (Blockincr - 1)); + /* last bucket holds blocks of exactly Maxblock */ + if (ip) + *ip = size / Blockincr; + return size * sizeof(Rune); } -Block* -disknewblock(Disk *d, uint n) -{ - uint i, j, size; - Block *b; +Block* disknewblock(Disk* d, uint n) { + uint i, j, size; + Block* b; - size = ntosize(n, &i); - b = d->free[i]; - if(b) - d->free[i] = b->u.next; - else{ - /* allocate in chunks to reduce malloc overhead */ - if(blist == nil){ - blist = emalloc(100*sizeof(Block)); - for(j=0; j<100-1; j++) - blist[j].u.next = &blist[j+1]; - } - b = blist; - blist = b->u.next; - b->addr = d->addr; - if(d->addr+size < d->addr){ - error("temp file overflow"); - } - d->addr += size; - } - b->u.n = n; - return b; + size = ntosize(n, &i); + b = d->free[i]; + if (b) + d->free[i] = b->u.next; + else { + /* allocate in chunks to reduce malloc overhead */ + if (blist == nil) { + blist = emalloc(100 * sizeof(Block)); + for (j = 0; j < 100 - 1; j++) + blist[j].u.next = &blist[j + 1]; + } + b = blist; + blist = b->u.next; + b->addr = d->addr; + if (d->addr + size < d->addr) { + error("temp file overflow"); + } + d->addr += size; + } + b->u.n = n; + return b; } -void -diskrelease(Disk *d, Block *b) -{ - uint i; +void diskrelease(Disk* d, Block* b) { + uint i; - ntosize(b->u.n, &i); - b->u.next = d->free[i]; - d->free[i] = b; + ntosize(b->u.n, &i); + b->u.next = d->free[i]; + d->free[i] = b; } -void -diskwrite(Disk *d, Block **bp, Rune *r, uint n) -{ - int size, nsize; - Block *b; +void diskwrite(Disk* d, Block** bp, Rune* r, uint n) { + int size, nsize; + Block* b; - b = *bp; - size = ntosize(b->u.n, nil); - nsize = ntosize(n, nil); - if(size != nsize){ - diskrelease(d, b); - b = disknewblock(d, n); - *bp = b; - } - if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) - error("write error to temp file"); - b->u.n = n; + b = *bp; + size = ntosize(b->u.n, nil); + nsize = ntosize(n, nil); + if (size != nsize) { + diskrelease(d, b); + b = disknewblock(d, n); + *bp = b; + } + if (pwrite(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune)) + error("write error to temp file"); + b->u.n = n; } -void -diskread(Disk *d, Block *b, Rune *r, uint n) -{ - if(n > b->u.n) - error("internal error: diskread"); +void diskread(Disk* d, Block* b, Rune* r, uint n) { + if (n > b->u.n) + error("internal error: diskread"); - ntosize(b->u.n, nil); - if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune)) - error("read error from temp file"); + ntosize(b->u.n, nil); + if (pread(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune)) + error("read error from temp file"); } diff --git a/ecmd.c b/ecmd.c index ef92e33..cdc5765 100644 --- a/ecmd.c +++ b/ecmd.c @@ -13,1365 +13,1273 @@ #include "edit.h" #include "fns.h" -int Glooping; -int nest; -char Enoname[] = "no file name given"; +int Glooping; +int nest; +char Enoname[] = "no file name given"; -Address addr; -File *menu; -Rangeset sel; -extern Text* curtext; -Rune *collection; -int ncollection; +Address addr; +File* menu; +Rangeset sel; +extern Text* curtext; +Rune* collection; +int ncollection; -int append(File*, Cmd*, long); -int pdisplay(File*); -void pfilename(File*); -void looper(File*, Cmd*, int); -void filelooper(Cmd*, int); -void linelooper(File*, Cmd*); -Address lineaddr(long, Address, int); -int filematch(File*, String*); -File *tofile(String*); -Rune* cmdname(File *f, String *s, int); -void runpipe(Text*, int, Rune*, int, int); +int append(File*, Cmd*, long); +int pdisplay(File*); +void pfilename(File*); +void looper(File*, Cmd*, int); +void filelooper(Cmd*, int); +void linelooper(File*, Cmd*); +Address lineaddr(long, Address, int); +int filematch(File*, String*); +File* tofile(String*); +Rune* cmdname(File* f, String* s, int); +void runpipe(Text*, int, Rune*, int, int); -void -clearcollection(void) -{ - free(collection); - collection = nil; - ncollection = 0; +void clearcollection(void) { + free(collection); + collection = nil; + ncollection = 0; } -void -resetxec(void) -{ - Glooping = nest = 0; - clearcollection(); +void resetxec(void) { + Glooping = nest = 0; + clearcollection(); } -void -mkaddr(Address *a, File *f) -{ - a->r.q0 = f->curtext->q0; - a->r.q1 = f->curtext->q1; - a->f = f; +void mkaddr(Address* a, File* f) { + a->r.q0 = f->curtext->q0; + a->r.q1 = f->curtext->q1; + a->f = f; } -int -cmdexec(Text *t, Cmd *cp) -{ - int i; - Addr *ap; - File *f; - Window *w; - Address dot; +int cmdexec(Text* t, Cmd* cp) { + int i; + Addr* ap; + File* f; + Window* w; + Address dot; - if(t == nil) - w = nil; - else - w = t->w; - if(w==nil && (cp->addr==0 || cp->addr->type!='"') && - !utfrune("bBnqUXY!", cp->cmdc) && - !(cp->cmdc=='D' && cp->u.text)) - editerror("no current window"); - i = cmdlookup(cp->cmdc); /* will be -1 for '{' */ - f = nil; - if(t && t->w){ - t = &t->w->body; - f = t->file; - f->curtext = t; - } - if(i>=0 && cmdtab[i].defaddr != aNo){ - if((ap=cp->addr)==0 && cp->cmdc!='\n'){ - cp->addr = ap = newaddr(); - ap->type = '.'; - if(cmdtab[i].defaddr == aAll) - ap->type = '*'; - }else if(ap && ap->type=='"' && ap->next==0 && cp->cmdc!='\n'){ - ap->next = newaddr(); - ap->next->type = '.'; - if(cmdtab[i].defaddr == aAll) - ap->next->type = '*'; - } - if(cp->addr){ /* may be false for '\n' (only) */ - static Address none = {0,0,nil}; - if(f){ - mkaddr(&dot, f); - addr = cmdaddress(ap, dot, 0); - }else /* a " */ - addr = cmdaddress(ap, none, 0); - f = addr.f; - t = f->curtext; - } - } - switch(cp->cmdc){ - case '{': - mkaddr(&dot, f); - if(cp->addr != nil) - dot = cmdaddress(cp->addr, dot, 0); - for(cp = cp->u.cmd; cp; cp = cp->next){ - if(dot.r.q1 > t->file->b.nc) - editerror("dot extends past end of buffer during { command"); - t->q0 = dot.r.q0; - t->q1 = dot.r.q1; - cmdexec(t, cp); - } - break; - default: - if(i < 0) - editerror("unknown command %c in cmdexec", cp->cmdc); - i = (*cmdtab[i].fn)(t, cp); - return i; - } - return 1; + if (t == nil) + w = nil; + else + w = t->w; + if ( + w == nil && (cp->addr == 0 || cp->addr->type != '"') && + !utfrune("bBnqUXY!", cp->cmdc) && !(cp->cmdc == 'D' && cp->u.text)) + editerror("no current window"); + i = cmdlookup(cp->cmdc); /* will be -1 for '{' */ + f = nil; + if (t && t->w) { + t = &t->w->body; + f = t->file; + f->curtext = t; + } + if (i >= 0 && cmdtab[i].defaddr != aNo) { + if ((ap = cp->addr) == 0 && cp->cmdc != '\n') { + cp->addr = ap = newaddr(); + ap->type = '.'; + if (cmdtab[i].defaddr == aAll) + ap->type = '*'; + } else if (ap && ap->type == '"' && ap->next == 0 && cp->cmdc != '\n') { + ap->next = newaddr(); + ap->next->type = '.'; + if (cmdtab[i].defaddr == aAll) + ap->next->type = '*'; + } + if (cp->addr) { /* may be false for '\n' (only) */ + static Address none = {0, 0, nil}; + if (f) { + mkaddr(&dot, f); + addr = cmdaddress(ap, dot, 0); + } else /* a " */ + addr = cmdaddress(ap, none, 0); + f = addr.f; + t = f->curtext; + } + } + switch (cp->cmdc) { + case '{': + mkaddr(&dot, f); + if (cp->addr != nil) + dot = cmdaddress(cp->addr, dot, 0); + for (cp = cp->u.cmd; cp; cp = cp->next) { + if (dot.r.q1 > t->file->b.nc) + editerror("dot extends past end of buffer during { command"); + t->q0 = dot.r.q0; + t->q1 = dot.r.q1; + cmdexec(t, cp); + } + break; + default: + if (i < 0) + editerror("unknown command %c in cmdexec", cp->cmdc); + i = (*cmdtab[i].fn)(t, cp); + return i; + } + return 1; } -char* -edittext(Window *w, int q, Rune *r, int nr) -{ - File *f; +char* edittext(Window* w, int q, Rune* r, int nr) { + File* f; - f = w->body.file; - switch(editing){ - case Inactive: - return "permission denied"; - case Inserting: - eloginsert(f, q, r, nr); - return nil; - case Collecting: - collection = runerealloc(collection, ncollection+nr+1); - runemove(collection+ncollection, r, nr); - ncollection += nr; - collection[ncollection] = '\0'; - return nil; - default: - return "unknown state in edittext"; - } + f = w->body.file; + switch (editing) { + case Inactive: + return "permission denied"; + case Inserting: + eloginsert(f, q, r, nr); + return nil; + case Collecting: + collection = runerealloc(collection, ncollection + nr + 1); + runemove(collection + ncollection, r, nr); + ncollection += nr; + collection[ncollection] = '\0'; + return nil; + default: + return "unknown state in edittext"; + } } /* string is known to be NUL-terminated */ -Rune* -filelist(Text *t, Rune *r, int nr) -{ - if(nr == 0) - return nil; - r = skipbl(r, nr, &nr); - if(r[0] != '<') - return runestrdup(r); - /* use < command to collect text */ - clearcollection(); - runpipe(t, '<', r+1, nr-1, Collecting); - return collection; +Rune* filelist(Text* t, Rune* r, int nr) { + if (nr == 0) + return nil; + r = skipbl(r, nr, &nr); + if (r[0] != '<') + return runestrdup(r); + /* use < command to collect text */ + clearcollection(); + runpipe(t, '<', r + 1, nr - 1, Collecting); + return collection; } -int -a_cmd(Text *t, Cmd *cp) -{ - return append(t->file, cp, addr.r.q1); +int a_cmd(Text* t, Cmd* cp) { return append(t->file, cp, addr.r.q1); } + +int b_cmd(Text* t, Cmd* cp) { + File* f; + + USED(t); + f = tofile(cp->u.text); + if (nest == 0) + pfilename(f); + curtext = f->curtext; + return TRUE; } -int -b_cmd(Text *t, Cmd *cp) -{ - File *f; +int B_cmd(Text* t, Cmd* cp) { + Rune *list, *r, *s; + int nr; - USED(t); - f = tofile(cp->u.text); - if(nest == 0) - pfilename(f); - curtext = f->curtext; - return TRUE; + list = filelist(t, cp->u.text->r, cp->u.text->n); + if (list == nil) + editerror(Enoname); + r = list; + nr = runestrlen(r); + r = skipbl(r, nr, &nr); + if (nr == 0) + new (t, t, nil, 0, 0, r, 0); + else + while (nr > 0) { + s = findbl(r, nr, &nr); + *s = '\0'; + new (t, t, nil, 0, 0, r, runestrlen(r)); + if (nr > 0) + r = skipbl(s + 1, nr - 1, &nr); + } + clearcollection(); + return TRUE; } -int -B_cmd(Text *t, Cmd *cp) -{ - Rune *list, *r, *s; - int nr; - - list = filelist(t, cp->u.text->r, cp->u.text->n); - if(list == nil) - editerror(Enoname); - r = list; - nr = runestrlen(r); - r = skipbl(r, nr, &nr); - if(nr == 0) - new(t, t, nil, 0, 0, r, 0); - else while(nr > 0){ - s = findbl(r, nr, &nr); - *s = '\0'; - new(t, t, nil, 0, 0, r, runestrlen(r)); - if(nr > 0) - r = skipbl(s+1, nr-1, &nr); - } - clearcollection(); - return TRUE; +int c_cmd(Text* t, Cmd* cp) { + elogreplace(t->file, addr.r.q0, addr.r.q1, cp->u.text->r, cp->u.text->n); + t->q0 = addr.r.q0; + t->q1 = addr.r.q1; + return TRUE; } -int -c_cmd(Text *t, Cmd *cp) -{ - elogreplace(t->file, addr.r.q0, addr.r.q1, cp->u.text->r, cp->u.text->n); - t->q0 = addr.r.q0; - t->q1 = addr.r.q1; - return TRUE; +int d_cmd(Text* t, Cmd* cp) { + USED(cp); + if (addr.r.q1 > addr.r.q0) + elogdelete(t->file, addr.r.q0, addr.r.q1); + t->q0 = addr.r.q0; + t->q1 = addr.r.q0; + return TRUE; } -int -d_cmd(Text *t, Cmd *cp) -{ - USED(cp); - if(addr.r.q1 > addr.r.q0) - elogdelete(t->file, addr.r.q0, addr.r.q1); - t->q0 = addr.r.q0; - t->q1 = addr.r.q0; - return TRUE; +void D1(Text* t) { + if (t->w->body.file->ntext > 1 || winclean(t->w, FALSE)) + colclose(t->col, t->w, TRUE); } -void -D1(Text *t) -{ - if(t->w->body.file->ntext>1 || winclean(t->w, FALSE)) - colclose(t->col, t->w, TRUE); +int D_cmd(Text* t, Cmd* cp) { + Rune *list, *r, *s, *n; + int nr, nn; + Window* w; + Runestr dir, rs; + char buf[128]; + + list = filelist(t, cp->u.text->r, cp->u.text->n); + if (list == nil) { + D1(t); + return TRUE; + } + dir = dirname(t, nil, 0); + r = list; + nr = runestrlen(r); + r = skipbl(r, nr, &nr); + do { + s = findbl(r, nr, &nr); + *s = '\0'; + /* first time through, could be empty string, meaning delete file empty name + */ + nn = runestrlen(r); + if (r[0] == '/' || nn == 0 || dir.nr == 0) { + rs.r = runestrdup(r); + rs.nr = nn; + } else { + n = runemalloc(dir.nr + 1 + nn); + runemove(n, dir.r, dir.nr); + n[dir.nr] = '/'; + runemove(n + dir.nr + 1, r, nn); + rs = cleanrname(runestr(n, dir.nr + 1 + nn)); + } + w = lookfile(rs.r, rs.nr); + if (w == nil) { + snprint(buf, sizeof buf, "no such file %.*S", rs.nr, rs.r); + free(rs.r); + editerror(buf); + } + free(rs.r); + D1(&w->body); + if (nr > 0) + r = skipbl(s + 1, nr - 1, &nr); + } while (nr > 0); + clearcollection(); + free(dir.r); + return TRUE; } -int -D_cmd(Text *t, Cmd *cp) -{ - Rune *list, *r, *s, *n; - int nr, nn; - Window *w; - Runestr dir, rs; - char buf[128]; - - list = filelist(t, cp->u.text->r, cp->u.text->n); - if(list == nil){ - D1(t); - return TRUE; - } - dir = dirname(t, nil, 0); - r = list; - nr = runestrlen(r); - r = skipbl(r, nr, &nr); - do{ - s = findbl(r, nr, &nr); - *s = '\0'; - /* first time through, could be empty string, meaning delete file empty name */ - nn = runestrlen(r); - if(r[0]=='/' || nn==0 || dir.nr==0){ - rs.r = runestrdup(r); - rs.nr = nn; - }else{ - n = runemalloc(dir.nr+1+nn); - runemove(n, dir.r, dir.nr); - n[dir.nr] = '/'; - runemove(n+dir.nr+1, r, nn); - rs = cleanrname(runestr(n, dir.nr+1+nn)); - } - w = lookfile(rs.r, rs.nr); - if(w == nil){ - snprint(buf, sizeof buf, "no such file %.*S", rs.nr, rs.r); - free(rs.r); - editerror(buf); - } - free(rs.r); - D1(&w->body); - if(nr > 0) - r = skipbl(s+1, nr-1, &nr); - }while(nr > 0); - clearcollection(); - free(dir.r); - return TRUE; +static int readloader(void* v, uint q0, Rune* r, int nr) { + if (nr > 0) + eloginsert(v, q0, r, nr); + return 0; } -static int -readloader(void *v, uint q0, Rune *r, int nr) -{ - if(nr > 0) - eloginsert(v, q0, r, nr); - return 0; +int e_cmd(Text* t, Cmd* cp) { + Rune* name; + File* f; + int i, isdir, q0, q1, fd, nulls, samename, allreplaced; + char *s, tmp[128]; + Dir* d; + + f = t->file; + q0 = addr.r.q0; + q1 = addr.r.q1; + if (cp->cmdc == 'e') { + if (winclean(t->w, TRUE) == FALSE) + editerror(""); /* winclean generated message already */ + q0 = 0; + q1 = f->b.nc; + } + allreplaced = (q0 == 0 && q1 == f->b.nc); + name = cmdname(f, cp->u.text, cp->cmdc == 'e'); + if (name == nil) + editerror(Enoname); + i = runestrlen(name); + samename = runeeq(name, i, t->file->name, t->file->nname); + s = runetobyte(name, i); + free(name); + fd = open(s, OREAD); + if (fd < 0) { + snprint(tmp, sizeof tmp, "can't open %s: %r", s); + free(s); + editerror(tmp); + } + d = dirfstat(fd); + isdir = (d != nil && (d->qid.type & QTDIR)); + free(d); + if (isdir) { + close(fd); + snprint(tmp, sizeof tmp, "%s is a directory", s); + free(s); + editerror(tmp); + } + elogdelete(f, q0, q1); + nulls = 0; + loadfile(fd, q1, &nulls, readloader, f, nil); + free(s); + close(fd); + if (nulls) + warning(nil, "%s: NUL bytes elided\n", s); + else if (allreplaced && samename) + f->editclean = TRUE; + return TRUE; } -int -e_cmd(Text *t, Cmd *cp) -{ - Rune *name; - File *f; - int i, isdir, q0, q1, fd, nulls, samename, allreplaced; - char *s, tmp[128]; - Dir *d; +static Rune Lempty[] = {0}; +int f_cmd(Text* t, Cmd* cp) { + Rune* name; + String* str; + String empty; - f = t->file; - q0 = addr.r.q0; - q1 = addr.r.q1; - if(cp->cmdc == 'e'){ - if(winclean(t->w, TRUE)==FALSE) - editerror(""); /* winclean generated message already */ - q0 = 0; - q1 = f->b.nc; - } - allreplaced = (q0==0 && q1==f->b.nc); - name = cmdname(f, cp->u.text, cp->cmdc=='e'); - if(name == nil) - editerror(Enoname); - i = runestrlen(name); - samename = runeeq(name, i, t->file->name, t->file->nname); - s = runetobyte(name, i); - free(name); - fd = open(s, OREAD); - if(fd < 0){ - snprint(tmp, sizeof tmp, "can't open %s: %r", s); - free(s); - editerror(tmp); - } - d = dirfstat(fd); - isdir = (d!=nil && (d->qid.type&QTDIR)); - free(d); - if(isdir){ - close(fd); - snprint(tmp, sizeof tmp, "%s is a directory", s); - free(s); - editerror(tmp); - } - elogdelete(f, q0, q1); - nulls = 0; - loadfile(fd, q1, &nulls, readloader, f, nil); - free(s); - close(fd); - if(nulls) - warning(nil, "%s: NUL bytes elided\n", s); - else if(allreplaced && samename) - f->editclean = TRUE; - return TRUE; + if (cp->u.text == nil) { + empty.n = 0; + empty.r = Lempty; + str = ∅ + } else + str = cp->u.text; + name = cmdname(t->file, str, TRUE); + free(name); + pfilename(t->file); + return TRUE; } -static Rune Lempty[] = { 0 }; -int -f_cmd(Text *t, Cmd *cp) -{ - Rune *name; - String *str; - String empty; - - if(cp->u.text == nil){ - empty.n = 0; - empty.r = Lempty; - str = ∅ - }else - str = cp->u.text; - name = cmdname(t->file, str, TRUE); - free(name); - pfilename(t->file); - return TRUE; +int g_cmd(Text* t, Cmd* cp) { + if (t->file != addr.f) { + warning(nil, "internal error: g_cmd f!=addr.f\n"); + return FALSE; + } + if (rxcompile(cp->re->r) == FALSE) + editerror("bad regexp in g command"); + if (rxexecute(t, nil, addr.r.q0, addr.r.q1, &sel) ^ cp->cmdc == 'v') { + t->q0 = addr.r.q0; + t->q1 = addr.r.q1; + return cmdexec(t, cp->u.cmd); + } + return TRUE; } -int -g_cmd(Text *t, Cmd *cp) -{ - if(t->file != addr.f){ - warning(nil, "internal error: g_cmd f!=addr.f\n"); - return FALSE; - } - if(rxcompile(cp->re->r) == FALSE) - editerror("bad regexp in g command"); - if(rxexecute(t, nil, addr.r.q0, addr.r.q1, &sel) ^ cp->cmdc=='v'){ - t->q0 = addr.r.q0; - t->q1 = addr.r.q1; - return cmdexec(t, cp->u.cmd); - } - return TRUE; +int i_cmd(Text* t, Cmd* cp) { return append(t->file, cp, addr.r.q0); } + +void copy(File* f, Address addr2) { + long p; + int ni; + Rune* buf; + + buf = fbufalloc(); + for (p = addr.r.q0; p < addr.r.q1; p += ni) { + ni = addr.r.q1 - p; + if (ni > RBUFSIZE) + ni = RBUFSIZE; + bufread(&f->b, p, buf, ni); + eloginsert(addr2.f, addr2.r.q1, buf, ni); + } + fbuffree(buf); } -int -i_cmd(Text *t, Cmd *cp) -{ - return append(t->file, cp, addr.r.q0); +void move(File* f, Address addr2) { + if (addr.f != addr2.f || addr.r.q1 <= addr2.r.q0) { + elogdelete(f, addr.r.q0, addr.r.q1); + copy(f, addr2); + } else if (addr.r.q0 >= addr2.r.q1) { + copy(f, addr2); + elogdelete(f, addr.r.q0, addr.r.q1); + } else if (addr.r.q0 == addr2.r.q0 && addr.r.q1 == addr2.r.q1) { + ; /* move to self; no-op */ + } else + editerror("move overlaps itself"); } -void -copy(File *f, Address addr2) -{ - long p; - int ni; - Rune *buf; +int m_cmd(Text* t, Cmd* cp) { + Address dot, addr2; - buf = fbufalloc(); - for(p=addr.r.q0; p RBUFSIZE) - ni = RBUFSIZE; - bufread(&f->b, p, buf, ni); - eloginsert(addr2.f, addr2.r.q1, buf, ni); - } - fbuffree(buf); + mkaddr(&dot, t->file); + addr2 = cmdaddress(cp->u.mtaddr, dot, 0); + if (cp->cmdc == 'm') + move(t->file, addr2); + else + copy(t->file, addr2); + return TRUE; } -void -move(File *f, Address addr2) -{ - if(addr.f!=addr2.f || addr.r.q1<=addr2.r.q0){ - elogdelete(f, addr.r.q0, addr.r.q1); - copy(f, addr2); - }else if(addr.r.q0 >= addr2.r.q1){ - copy(f, addr2); - elogdelete(f, addr.r.q0, addr.r.q1); - }else if(addr.r.q0==addr2.r.q0 && addr.r.q1==addr2.r.q1){ - ; /* move to self; no-op */ - }else - editerror("move overlaps itself"); +int p_cmd(Text* t, Cmd* cp) { + USED(cp); + return pdisplay(t->file); } -int -m_cmd(Text *t, Cmd *cp) -{ - Address dot, addr2; +int s_cmd(Text* t, Cmd* cp) { + int i, j, k, c, m, n, nrp, didsub; + long p1, op, delta; + String* buf; + Rangeset* rp; + char* err; + Rune* rbuf; - mkaddr(&dot, t->file); - addr2 = cmdaddress(cp->u.mtaddr, dot, 0); - if(cp->cmdc == 'm') - move(t->file, addr2); - else - copy(t->file, addr2); - return TRUE; -} - -int -p_cmd(Text *t, Cmd *cp) -{ - USED(cp); - return pdisplay(t->file); -} - -int -s_cmd(Text *t, Cmd *cp) -{ - int i, j, k, c, m, n, nrp, didsub; - long p1, op, delta; - String *buf; - Rangeset *rp; - char *err; - Rune *rbuf; - - n = cp->num; - op= -1; - if(rxcompile(cp->re->r) == FALSE) - editerror("bad regexp in s command"); - nrp = 0; - rp = nil; - delta = 0; - didsub = FALSE; - for(p1 = addr.r.q0; p1<=addr.r.q1 && rxexecute(t, nil, p1, addr.r.q1, &sel); ){ - if(sel.r[0].q0 == sel.r[0].q1){ /* empty match? */ - if(sel.r[0].q0 == op){ - p1++; - continue; - } - p1 = sel.r[0].q1+1; - }else - p1 = sel.r[0].q1; - op = sel.r[0].q1; - if(--n>0) - continue; - nrp++; - rp = erealloc(rp, nrp*sizeof(Rangeset)); - rp[nrp-1] = sel; - } - rbuf = fbufalloc(); - buf = allocstring(0); - for(m=0; mn = 0; - buf->r[0] = '\0'; - sel = rp[m]; - for(i = 0; iu.text->n; i++) - if((c = cp->u.text->r[i])=='\\' && iu.text->n-1){ - c = cp->u.text->r[++i]; - if('1'<=c && c<='9') { - j = c-'0'; - if(sel.r[j].q1-sel.r[j].q0>RBUFSIZE){ - err = "replacement string too long"; - goto Err; - } - bufread(&t->file->b, sel.r[j].q0, rbuf, sel.r[j].q1-sel.r[j].q0); - for(k=0; kRBUFSIZE){ - err = "right hand side too long in substitution"; - goto Err; - } - bufread(&t->file->b, sel.r[0].q0, rbuf, sel.r[0].q1-sel.r[0].q0); - for(k=0; kfile, sel.r[0].q0, sel.r[0].q1, buf->r, buf->n); - delta -= sel.r[0].q1-sel.r[0].q0; - delta += buf->n; - didsub = 1; - if(!cp->flag) - break; - } - free(rp); - freestring(buf); - fbuffree(rbuf); - if(!didsub && nest==0) - editerror("no substitution"); - t->q0 = addr.r.q0; - t->q1 = addr.r.q1; - return TRUE; + n = cp->num; + op = -1; + if (rxcompile(cp->re->r) == FALSE) + editerror("bad regexp in s command"); + nrp = 0; + rp = nil; + delta = 0; + didsub = FALSE; + for (p1 = addr.r.q0; + p1 <= addr.r.q1 && rxexecute(t, nil, p1, addr.r.q1, &sel);) { + if (sel.r[0].q0 == sel.r[0].q1) { /* empty match? */ + if (sel.r[0].q0 == op) { + p1++; + continue; + } + p1 = sel.r[0].q1 + 1; + } else + p1 = sel.r[0].q1; + op = sel.r[0].q1; + if (--n > 0) + continue; + nrp++; + rp = erealloc(rp, nrp * sizeof(Rangeset)); + rp[nrp - 1] = sel; + } + rbuf = fbufalloc(); + buf = allocstring(0); + for (m = 0; m < nrp; m++) { + buf->n = 0; + buf->r[0] = '\0'; + sel = rp[m]; + for (i = 0; i < cp->u.text->n; i++) + if ((c = cp->u.text->r[i]) == '\\' && i < cp->u.text->n - 1) { + c = cp->u.text->r[++i]; + if ('1' <= c && c <= '9') { + j = c - '0'; + if (sel.r[j].q1 - sel.r[j].q0 > RBUFSIZE) { + err = "replacement string too long"; + goto Err; + } + bufread(&t->file->b, sel.r[j].q0, rbuf, sel.r[j].q1 - sel.r[j].q0); + for (k = 0; k < sel.r[j].q1 - sel.r[j].q0; k++) + Straddc(buf, rbuf[k]); + } else + Straddc(buf, c); + } else if (c != '&') + Straddc(buf, c); + else { + if (sel.r[0].q1 - sel.r[0].q0 > RBUFSIZE) { + err = "right hand side too long in substitution"; + goto Err; + } + bufread(&t->file->b, sel.r[0].q0, rbuf, sel.r[0].q1 - sel.r[0].q0); + for (k = 0; k < sel.r[0].q1 - sel.r[0].q0; k++) + Straddc(buf, rbuf[k]); + } + elogreplace(t->file, sel.r[0].q0, sel.r[0].q1, buf->r, buf->n); + delta -= sel.r[0].q1 - sel.r[0].q0; + delta += buf->n; + didsub = 1; + if (!cp->flag) + break; + } + free(rp); + freestring(buf); + fbuffree(rbuf); + if (!didsub && nest == 0) + editerror("no substitution"); + t->q0 = addr.r.q0; + t->q1 = addr.r.q1; + return TRUE; Err: - free(rp); - freestring(buf); - fbuffree(rbuf); - editerror(err); - return FALSE; + free(rp); + freestring(buf); + fbuffree(rbuf); + editerror(err); + return FALSE; } -int -u_cmd(Text *t, Cmd *cp) -{ - int n, oseq, flag; +int u_cmd(Text* t, Cmd* cp) { + int n, oseq, flag; - n = cp->num; - flag = TRUE; - if(n < 0){ - n = -n; - flag = FALSE; - } - oseq = -1; - while(n-->0 && t->file->seq!=oseq){ - oseq = t->file->seq; - undo(t, nil, nil, flag, 0, nil, 0); - } - return TRUE; + n = cp->num; + flag = TRUE; + if (n < 0) { + n = -n; + flag = FALSE; + } + oseq = -1; + while (n-- > 0 && t->file->seq != oseq) { + oseq = t->file->seq; + undo(t, nil, nil, flag, 0, nil, 0); + } + return TRUE; } -int -w_cmd(Text *t, Cmd *cp) -{ - Rune *r; - File *f; +int w_cmd(Text* t, Cmd* cp) { + Rune* r; + File* f; - f = t->file; - if(f->seq == seq) - editerror("can't write file with pending modifications"); - r = cmdname(f, cp->u.text, FALSE); - if(r == nil) - editerror("no name specified for 'w' command"); - putfile(f, addr.r.q0, addr.r.q1, r, runestrlen(r)); - /* r is freed by putfile */ - return TRUE; + f = t->file; + if (f->seq == seq) + editerror("can't write file with pending modifications"); + r = cmdname(f, cp->u.text, FALSE); + if (r == nil) + editerror("no name specified for 'w' command"); + putfile(f, addr.r.q0, addr.r.q1, r, runestrlen(r)); + /* r is freed by putfile */ + return TRUE; } -int -x_cmd(Text *t, Cmd *cp) -{ - if(cp->re) - looper(t->file, cp, cp->cmdc=='x'); - else - linelooper(t->file, cp); - return TRUE; +int x_cmd(Text* t, Cmd* cp) { + if (cp->re) + looper(t->file, cp, cp->cmdc == 'x'); + else + linelooper(t->file, cp); + return TRUE; } -int -X_cmd(Text *t, Cmd *cp) -{ - USED(t); +int X_cmd(Text* t, Cmd* cp) { + USED(t); - filelooper(cp, cp->cmdc=='X'); - return TRUE; + filelooper(cp, cp->cmdc == 'X'); + return TRUE; } -void -runpipe(Text *t, int cmd, Rune *cr, int ncr, int state) -{ - Rune *r, *s; - int n; - Runestr dir; - Window *w; - QLock *q; +void runpipe(Text* t, int cmd, Rune* cr, int ncr, int state) { + Rune *r, *s; + int n; + Runestr dir; + Window* w; + QLock* q; - r = skipbl(cr, ncr, &n); - if(n == 0) - editerror("no command specified for %c", cmd); - w = nil; - if(state == Inserting){ - w = t->w; - t->q0 = addr.r.q0; - t->q1 = addr.r.q1; - if(cmd == '<' || cmd=='|') - elogdelete(t->file, t->q0, t->q1); - } - s = runemalloc(n+2); - s[0] = cmd; - runemove(s+1, r, n); - n++; - dir.r = nil; - dir.nr = 0; - if(t != nil) - dir = dirname(t, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - editing = state; - if(t!=nil && t->w!=nil) - incref(&t->w->ref); /* run will decref */ - run(w, runetobyte(s, n), dir.r, dir.nr, TRUE, nil, nil, TRUE); - free(s); - if(t!=nil && t->w!=nil) - winunlock(t->w); - qunlock(&row.lk); - recvul(cedit); - /* - * The editoutlk exists only so that we can tell when - * the editout file has been closed. It can get closed *after* - * the process exits because, since the process cannot be - * connected directly to editout (no 9P kernel support), - * the process is actually connected to a pipe to another - * process (arranged via 9pserve) that reads from the pipe - * and then writes the data in the pipe to editout using - * 9P transactions. This process might still have a couple - * writes left to copy after the original process has exited. - */ - if(w) - q = &w->editoutlk; - else - q = &editoutlk; - qlock(q); /* wait for file to close */ - qunlock(q); - qlock(&row.lk); - editing = Inactive; - if(t!=nil && t->w!=nil) - winlock(t->w, 'M'); + r = skipbl(cr, ncr, &n); + if (n == 0) + editerror("no command specified for %c", cmd); + w = nil; + if (state == Inserting) { + w = t->w; + t->q0 = addr.r.q0; + t->q1 = addr.r.q1; + if (cmd == '<' || cmd == '|') + elogdelete(t->file, t->q0, t->q1); + } + s = runemalloc(n + 2); + s[0] = cmd; + runemove(s + 1, r, n); + n++; + dir.r = nil; + dir.nr = 0; + if (t != nil) + dir = dirname(t, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + editing = state; + if (t != nil && t->w != nil) + incref(&t->w->ref); /* run will decref */ + run(w, runetobyte(s, n), dir.r, dir.nr, TRUE, nil, nil, TRUE); + free(s); + if (t != nil && t->w != nil) + winunlock(t->w); + qunlock(&row.lk); + recvul(cedit); + /* + * The editoutlk exists only so that we can tell when + * the editout file has been closed. It can get closed *after* + * the process exits because, since the process cannot be + * connected directly to editout (no 9P kernel support), + * the process is actually connected to a pipe to another + * process (arranged via 9pserve) that reads from the pipe + * and then writes the data in the pipe to editout using + * 9P transactions. This process might still have a couple + * writes left to copy after the original process has exited. + */ + if (w) + q = &w->editoutlk; + else + q = &editoutlk; + qlock(q); /* wait for file to close */ + qunlock(q); + qlock(&row.lk); + editing = Inactive; + if (t != nil && t->w != nil) + winlock(t->w, 'M'); } -int -pipe_cmd(Text *t, Cmd *cp) -{ - runpipe(t, cp->cmdc, cp->u.text->r, cp->u.text->n, Inserting); - return TRUE; +int pipe_cmd(Text* t, Cmd* cp) { + runpipe(t, cp->cmdc, cp->u.text->r, cp->u.text->n, Inserting); + return TRUE; } -long -nlcount(Text *t, long q0, long q1, long *pnr) -{ - long nl, start; - Rune *buf; - int i, nbuf; +long nlcount(Text* t, long q0, long q1, long* pnr) { + long nl, start; + Rune* buf; + int i, nbuf; - buf = fbufalloc(); - nbuf = 0; - i = nl = 0; - start = q0; - while(q0 < q1){ - if(i == nbuf){ - nbuf = q1-q0; - if(nbuf > RBUFSIZE) - nbuf = RBUFSIZE; - bufread(&t->file->b, q0, buf, nbuf); - i = 0; - } - if(buf[i++] == '\n') { - start = q0+1; - nl++; - } - q0++; - } - fbuffree(buf); - if(pnr != nil) - *pnr = q0 - start; - return nl; + buf = fbufalloc(); + nbuf = 0; + i = nl = 0; + start = q0; + while (q0 < q1) { + if (i == nbuf) { + nbuf = q1 - q0; + if (nbuf > RBUFSIZE) + nbuf = RBUFSIZE; + bufread(&t->file->b, q0, buf, nbuf); + i = 0; + } + if (buf[i++] == '\n') { + start = q0 + 1; + nl++; + } + q0++; + } + fbuffree(buf); + if (pnr != nil) + *pnr = q0 - start; + return nl; } enum { - PosnLine = 0, - PosnChars = 1, - PosnLineChars = 2, + PosnLine = 0, + PosnChars = 1, + PosnLineChars = 2, }; -void -printposn(Text *t, int mode) -{ - long l1, l2, r1, r2; +void printposn(Text* t, int mode) { + long l1, l2, r1, r2; - if (t != nil && t->file != nil && t->file->name != nil) - warning(nil, "%.*S:", t->file->nname, t->file->name); - - switch(mode) { - case PosnChars: - warning(nil, "#%d", addr.r.q0); - if(addr.r.q1 != addr.r.q0) - warning(nil, ",#%d", addr.r.q1); - warning(nil, "\n"); - return; - - default: - case PosnLine: - l1 = 1+nlcount(t, 0, addr.r.q0, nil); - l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, nil); - /* check if addr ends with '\n' */ - if(addr.r.q1>0 && addr.r.q1>addr.r.q0 && textreadc(t, addr.r.q1-1)=='\n') - --l2; - warning(nil, "%lud", l1); - if(l2 != l1) - warning(nil, ",%lud", l2); - warning(nil, "\n"); - return; + if (t != nil && t->file != nil && t->file->name != nil) + warning(nil, "%.*S:", t->file->nname, t->file->name); - case PosnLineChars: - l1 = 1+nlcount(t, 0, addr.r.q0, &r1); - l2 = l1+nlcount(t, addr.r.q0, addr.r.q1, &r2); - if(l2 == l1) - r2 += r1; - warning(nil, "%lud+#%d", l1, r1); - if(l2 != l1) - warning(nil, ",%lud+#%d", l2, r2); - warning(nil, "\n"); - return; - } + switch (mode) { + case PosnChars: + warning(nil, "#%d", addr.r.q0); + if (addr.r.q1 != addr.r.q0) + warning(nil, ",#%d", addr.r.q1); + warning(nil, "\n"); + return; + + default: + case PosnLine: + l1 = 1 + nlcount(t, 0, addr.r.q0, nil); + l2 = l1 + nlcount(t, addr.r.q0, addr.r.q1, nil); + /* check if addr ends with '\n' */ + if ( + addr.r.q1 > 0 && addr.r.q1 > addr.r.q0 && + textreadc(t, addr.r.q1 - 1) == '\n') + --l2; + warning(nil, "%lud", l1); + if (l2 != l1) + warning(nil, ",%lud", l2); + warning(nil, "\n"); + return; + + case PosnLineChars: + l1 = 1 + nlcount(t, 0, addr.r.q0, &r1); + l2 = l1 + nlcount(t, addr.r.q0, addr.r.q1, &r2); + if (l2 == l1) + r2 += r1; + warning(nil, "%lud+#%d", l1, r1); + if (l2 != l1) + warning(nil, ",%lud+#%d", l2, r2); + warning(nil, "\n"); + return; + } } -int -eq_cmd(Text *t, Cmd *cp) -{ - int mode; +int eq_cmd(Text* t, Cmd* cp) { + int mode; - switch(cp->u.text->n){ - case 0: - mode = PosnLine; - break; - case 1: - if(cp->u.text->r[0] == '#'){ - mode = PosnChars; - break; - } - if(cp->u.text->r[0] == '+'){ - mode = PosnLineChars; - break; - } - default: - SET(mode); - editerror("newline expected"); - } - printposn(t, mode); - return TRUE; + switch (cp->u.text->n) { + case 0: + mode = PosnLine; + break; + case 1: + if (cp->u.text->r[0] == '#') { + mode = PosnChars; + break; + } + if (cp->u.text->r[0] == '+') { + mode = PosnLineChars; + break; + } + default: + SET(mode); + editerror("newline expected"); + } + printposn(t, mode); + return TRUE; } -int -nl_cmd(Text *t, Cmd *cp) -{ - Address a; - File *f; +int nl_cmd(Text* t, Cmd* cp) { + Address a; + File* f; - f = t->file; - if(cp->addr == 0){ - /* First put it on newline boundaries */ - mkaddr(&a, f); - addr = lineaddr(0, a, -1); - a = lineaddr(0, a, 1); - addr.r.q1 = a.r.q1; - if(addr.r.q0==t->q0 && addr.r.q1==t->q1){ - mkaddr(&a, f); - addr = lineaddr(1, a, 1); - } - } - textshow(t, addr.r.q0, addr.r.q1, 1); - return TRUE; + f = t->file; + if (cp->addr == 0) { + /* First put it on newline boundaries */ + mkaddr(&a, f); + addr = lineaddr(0, a, -1); + a = lineaddr(0, a, 1); + addr.r.q1 = a.r.q1; + if (addr.r.q0 == t->q0 && addr.r.q1 == t->q1) { + mkaddr(&a, f); + addr = lineaddr(1, a, 1); + } + } + textshow(t, addr.r.q0, addr.r.q1, 1); + return TRUE; } -int -append(File *f, Cmd *cp, long p) -{ - if(cp->u.text->n > 0) - eloginsert(f, p, cp->u.text->r, cp->u.text->n); - f->curtext->q0 = p; - f->curtext->q1 = p; - return TRUE; +int append(File* f, Cmd* cp, long p) { + if (cp->u.text->n > 0) + eloginsert(f, p, cp->u.text->r, cp->u.text->n); + f->curtext->q0 = p; + f->curtext->q1 = p; + return TRUE; } -int -pdisplay(File *f) -{ - long p1, p2; - int np; - Rune *buf; +int pdisplay(File* f) { + long p1, p2; + int np; + Rune* buf; - p1 = addr.r.q0; - p2 = addr.r.q1; - if(p2 > f->b.nc) - p2 = f->b.nc; - buf = fbufalloc(); - while(p1 < p2){ - np = p2-p1; - if(np>RBUFSIZE-1) - np = RBUFSIZE-1; - bufread(&f->b, p1, buf, np); - buf[np] = '\0'; - warning(nil, "%S", buf); - p1 += np; - } - fbuffree(buf); - f->curtext->q0 = addr.r.q0; - f->curtext->q1 = addr.r.q1; - return TRUE; + p1 = addr.r.q0; + p2 = addr.r.q1; + if (p2 > f->b.nc) + p2 = f->b.nc; + buf = fbufalloc(); + while (p1 < p2) { + np = p2 - p1; + if (np > RBUFSIZE - 1) + np = RBUFSIZE - 1; + bufread(&f->b, p1, buf, np); + buf[np] = '\0'; + warning(nil, "%S", buf); + p1 += np; + } + fbuffree(buf); + f->curtext->q0 = addr.r.q0; + f->curtext->q1 = addr.r.q1; + return TRUE; } -void -pfilename(File *f) -{ - int dirty; - Window *w; +void pfilename(File* f) { + int dirty; + Window* w; - w = f->curtext->w; - /* same check for dirty as in settag, but we know ncache==0 */ - dirty = !w->isdir && !w->isscratch && f->mod; - warning(nil, "%c%c%c %.*S\n", " '"[dirty], - '+', " ."[curtext!=nil && curtext->file==f], f->nname, f->name); + w = f->curtext->w; + /* same check for dirty as in settag, but we know ncache==0 */ + dirty = !w->isdir && !w->isscratch && f->mod; + warning( + nil, + "%c%c%c %.*S\n", + " '"[dirty], + '+', + " ."[curtext != nil && curtext->file == f], + f -> nname, + f -> name); } -void -loopcmd(File *f, Cmd *cp, Range *rp, long nrp) -{ - long i; +void loopcmd(File* f, Cmd* cp, Range* rp, long nrp) { + long i; - for(i=0; icurtext->q0 = rp[i].q0; - f->curtext->q1 = rp[i].q1; - cmdexec(f->curtext, cp); - } + for (i = 0; i < nrp; i++) { + f->curtext->q0 = rp[i].q0; + f->curtext->q1 = rp[i].q1; + cmdexec(f->curtext, cp); + } } -void -looper(File *f, Cmd *cp, int xy) -{ - long p, op, nrp; - Range r, tr; - Range *rp; +void looper(File* f, Cmd* cp, int xy) { + long p, op, nrp; + Range r, tr; + Range* rp; - r = addr.r; - op= xy? -1 : r.q0; - nest++; - if(rxcompile(cp->re->r) == FALSE) - editerror("bad regexp in %c command", cp->cmdc); - nrp = 0; - rp = nil; - for(p = r.q0; p<=r.q1; ){ - if(!rxexecute(f->curtext, nil, p, r.q1, &sel)){ /* no match, but y should still run */ - if(xy || op>r.q1) - break; - tr.q0 = op, tr.q1 = r.q1; - p = r.q1+1; /* exit next loop */ - }else{ - if(sel.r[0].q0==sel.r[0].q1){ /* empty match? */ - if(sel.r[0].q0==op){ - p++; - continue; - } - p = sel.r[0].q1+1; - }else - p = sel.r[0].q1; - if(xy) - tr = sel.r[0]; - else - tr.q0 = op, tr.q1 = sel.r[0].q0; - } - op = sel.r[0].q1; - nrp++; - rp = erealloc(rp, nrp*sizeof(Range)); - rp[nrp-1] = tr; - } - loopcmd(f, cp->u.cmd, rp, nrp); - free(rp); - --nest; + r = addr.r; + op = xy ? -1 : r.q0; + nest++; + if (rxcompile(cp->re->r) == FALSE) + editerror("bad regexp in %c command", cp->cmdc); + nrp = 0; + rp = nil; + for (p = r.q0; p <= r.q1;) { + if (!rxexecute(f->curtext, nil, p, r.q1, &sel)) { /* no match, but y should + still run */ + if (xy || op > r.q1) + break; + tr.q0 = op, tr.q1 = r.q1; + p = r.q1 + 1; /* exit next loop */ + } else { + if (sel.r[0].q0 == sel.r[0].q1) { /* empty match? */ + if (sel.r[0].q0 == op) { + p++; + continue; + } + p = sel.r[0].q1 + 1; + } else + p = sel.r[0].q1; + if (xy) + tr = sel.r[0]; + else + tr.q0 = op, tr.q1 = sel.r[0].q0; + } + op = sel.r[0].q1; + nrp++; + rp = erealloc(rp, nrp * sizeof(Range)); + rp[nrp - 1] = tr; + } + loopcmd(f, cp->u.cmd, rp, nrp); + free(rp); + --nest; } -void -linelooper(File *f, Cmd *cp) -{ - long nrp, p; - Range r, linesel; - Address a, a3; - Range *rp; +void linelooper(File* f, Cmd* cp) { + long nrp, p; + Range r, linesel; + Address a, a3; + Range* rp; - nest++; - nrp = 0; - rp = nil; - r = addr.r; - a3.f = f; - a3.r.q0 = a3.r.q1 = r.q0; - a = lineaddr(0, a3, 1); - linesel = a.r; - for(p = r.q0; p= r.q1) - break; - if(linesel.q1 >= r.q1) - linesel.q1 = r.q1; - if(linesel.q1 > linesel.q0) - if(linesel.q0>=a3.r.q1 && linesel.q1>a3.r.q1){ - a3.r = linesel; - nrp++; - rp = erealloc(rp, nrp*sizeof(Range)); - rp[nrp-1] = linesel; - continue; - } - break; - } - loopcmd(f, cp->u.cmd, rp, nrp); - free(rp); - --nest; + nest++; + nrp = 0; + rp = nil; + r = addr.r; + a3.f = f; + a3.r.q0 = a3.r.q1 = r.q0; + a = lineaddr(0, a3, 1); + linesel = a.r; + for (p = r.q0; p < r.q1; p = a3.r.q1) { + a3.r.q0 = a3.r.q1; + if (p != r.q0 || linesel.q1 == p) { + a = lineaddr(1, a3, 1); + linesel = a.r; + } + if (linesel.q0 >= r.q1) + break; + if (linesel.q1 >= r.q1) + linesel.q1 = r.q1; + if (linesel.q1 > linesel.q0) + if (linesel.q0 >= a3.r.q1 && linesel.q1 > a3.r.q1) { + a3.r = linesel; + nrp++; + rp = erealloc(rp, nrp * sizeof(Range)); + rp[nrp - 1] = linesel; + continue; + } + break; + } + loopcmd(f, cp->u.cmd, rp, nrp); + free(rp); + --nest; } -struct Looper -{ - Cmd *cp; - int XY; - Window **w; - int nw; -} loopstruct; /* only one; X and Y can't nest */ +struct Looper { + Cmd* cp; + int XY; + Window** w; + int nw; +} loopstruct; /* only one; X and Y can't nest */ -void -alllooper(Window *w, void *v) -{ - Text *t; - struct Looper *lp; - Cmd *cp; +void alllooper(Window* w, void* v) { + Text* t; + struct Looper* lp; + Cmd* cp; - lp = v; - cp = lp->cp; -/* if(w->isscratch || w->isdir) */ -/* return; */ - t = &w->body; - /* only use this window if it's the current window for the file */ - if(t->file->curtext != t) - return; -/* if(w->nopen[QWevent] > 0) */ -/* return; */ - /* no auto-execute on files without names */ - if(cp->re==nil && t->file->nname==0) - return; - if(cp->re==nil || filematch(t->file, cp->re)==lp->XY){ - lp->w = erealloc(lp->w, (lp->nw+1)*sizeof(Window*)); - lp->w[lp->nw++] = w; - } + lp = v; + cp = lp->cp; + /* if(w->isscratch || w->isdir) */ + /* return; */ + t = &w->body; + /* only use this window if it's the current window for the file */ + if (t->file->curtext != t) + return; + /* if(w->nopen[QWevent] > 0) */ + /* return; */ + /* no auto-execute on files without names */ + if (cp->re == nil && t->file->nname == 0) + return; + if (cp->re == nil || filematch(t->file, cp->re) == lp->XY) { + lp->w = erealloc(lp->w, (lp->nw + 1) * sizeof(Window*)); + lp->w[lp->nw++] = w; + } } -void -alllocker(Window *w, void *v) -{ - if(v) - incref(&w->ref); - else - winclose(w); +void alllocker(Window* w, void* v) { + if (v) + incref(&w->ref); + else + winclose(w); } -void -filelooper(Cmd *cp, int XY) -{ - int i; +void filelooper(Cmd* cp, int XY) { + int i; - if(Glooping++) - editerror("can't nest %c command", "YX"[XY]); - nest++; + if (Glooping++) + editerror("can't nest %c command", "YX"[XY]); + nest++; - loopstruct.cp = cp; - loopstruct.XY = XY; - if(loopstruct.w) /* error'ed out last time */ - free(loopstruct.w); - loopstruct.w = nil; - loopstruct.nw = 0; - allwindows(alllooper, &loopstruct); - /* - * add a ref to all windows to keep safe windows accessed by X - * that would not otherwise have a ref to hold them up during - * the shenanigans. note this with globalincref so that any - * newly created windows start with an extra reference. - */ - allwindows(alllocker, (void*)1); - globalincref = 1; - for(i=0; ibody, cp->u.cmd); - allwindows(alllocker, (void*)0); - globalincref = 0; - free(loopstruct.w); - loopstruct.w = nil; + loopstruct.cp = cp; + loopstruct.XY = XY; + if (loopstruct.w) /* error'ed out last time */ + free(loopstruct.w); + loopstruct.w = nil; + loopstruct.nw = 0; + allwindows(alllooper, &loopstruct); + /* + * add a ref to all windows to keep safe windows accessed by X + * that would not otherwise have a ref to hold them up during + * the shenanigans. note this with globalincref so that any + * newly created windows start with an extra reference. + */ + allwindows(alllocker, (void*)1); + globalincref = 1; + for (i = 0; i < loopstruct.nw; i++) + cmdexec(&loopstruct.w[i]->body, cp->u.cmd); + allwindows(alllocker, (void*)0); + globalincref = 0; + free(loopstruct.w); + loopstruct.w = nil; - --Glooping; - --nest; + --Glooping; + --nest; } -void -nextmatch(File *f, String *r, long p, int sign) -{ - if(rxcompile(r->r) == FALSE) - editerror("bad regexp in command address"); - if(sign >= 0){ - if(!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel)) - editerror("no match for regexp"); - if(sel.r[0].q0==sel.r[0].q1 && sel.r[0].q0==p){ - if(++p>f->b.nc) - p = 0; - if(!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel)) - editerror("address"); - } - }else{ - if(!rxbexecute(f->curtext, p, &sel)) - editerror("no match for regexp"); - if(sel.r[0].q0==sel.r[0].q1 && sel.r[0].q1==p){ - if(--p<0) - p = f->b.nc; - if(!rxbexecute(f->curtext, p, &sel)) - editerror("address"); - } - } +void nextmatch(File* f, String* r, long p, int sign) { + if (rxcompile(r->r) == FALSE) + editerror("bad regexp in command address"); + if (sign >= 0) { + if (!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel)) + editerror("no match for regexp"); + if (sel.r[0].q0 == sel.r[0].q1 && sel.r[0].q0 == p) { + if (++p > f->b.nc) + p = 0; + if (!rxexecute(f->curtext, nil, p, 0x7FFFFFFFL, &sel)) + editerror("address"); + } + } else { + if (!rxbexecute(f->curtext, p, &sel)) + editerror("no match for regexp"); + if (sel.r[0].q0 == sel.r[0].q1 && sel.r[0].q1 == p) { + if (--p < 0) + p = f->b.nc; + if (!rxbexecute(f->curtext, p, &sel)) + editerror("address"); + } + } } -File *matchfile(String*); -Address charaddr(long, Address, int); -Address lineaddr(long, Address, int); +File* matchfile(String*); +Address charaddr(long, Address, int); +Address lineaddr(long, Address, int); -Address -cmdaddress(Addr *ap, Address a, int sign) -{ - File *f = a.f; - Address a1, a2; +Address cmdaddress(Addr* ap, Address a, int sign) { + File* f = a.f; + Address a1, a2; - do{ - switch(ap->type){ - case 'l': - case '#': - a = (*(ap->type=='#'?charaddr:lineaddr))(ap->num, a, sign); - break; + do { + switch (ap->type) { + case 'l': + case '#': + a = (*(ap->type == '#' ? charaddr : lineaddr))(ap->num, a, sign); + break; - case '.': - mkaddr(&a, f); - break; + case '.': + mkaddr(&a, f); + break; - case '$': - a.r.q0 = a.r.q1 = f->b.nc; - break; + case '$': + a.r.q0 = a.r.q1 = f->b.nc; + break; - case '\'': -editerror("can't handle '"); -/* a.r = f->mark; */ - break; + case '\'': + editerror("can't handle '"); + /* a.r = f->mark; */ + break; - case '?': - sign = -sign; - if(sign == 0) - sign = -1; - /* fall through */ - case '/': - nextmatch(f, ap->u.re, sign>=0? a.r.q1 : a.r.q0, sign); - a.r = sel.r[0]; - break; + case '?': + sign = -sign; + if (sign == 0) + sign = -1; + /* fall through */ + case '/': + nextmatch(f, ap->u.re, sign >= 0 ? a.r.q1 : a.r.q0, sign); + a.r = sel.r[0]; + break; - case '"': - f = matchfile(ap->u.re); - mkaddr(&a, f); - break; + case '"': + f = matchfile(ap->u.re); + mkaddr(&a, f); + break; - case '*': - a.r.q0 = 0, a.r.q1 = f->b.nc; - return a; + case '*': + a.r.q0 = 0, a.r.q1 = f->b.nc; + return a; - case ',': - case ';': - if(ap->u.left) - a1 = cmdaddress(ap->u.left, a, 0); - else - a1.f = a.f, a1.r.q0 = a1.r.q1 = 0; - if(ap->type == ';'){ - f = a1.f; - a = a1; - f->curtext->q0 = a1.r.q0; - f->curtext->q1 = a1.r.q1; - } - if(ap->next) - a2 = cmdaddress(ap->next, a, 0); - else - a2.f = a.f, a2.r.q0 = a2.r.q1 = f->b.nc; - if(a1.f != a2.f) - editerror("addresses in different files"); - a.f = a1.f, a.r.q0 = a1.r.q0, a.r.q1 = a2.r.q1; - if(a.r.q1 < a.r.q0) - editerror("addresses out of order"); - return a; + case ',': + case ';': + if (ap->u.left) + a1 = cmdaddress(ap->u.left, a, 0); + else + a1.f = a.f, a1.r.q0 = a1.r.q1 = 0; + if (ap->type == ';') { + f = a1.f; + a = a1; + f->curtext->q0 = a1.r.q0; + f->curtext->q1 = a1.r.q1; + } + if (ap->next) + a2 = cmdaddress(ap->next, a, 0); + else + a2.f = a.f, a2.r.q0 = a2.r.q1 = f->b.nc; + if (a1.f != a2.f) + editerror("addresses in different files"); + a.f = a1.f, a.r.q0 = a1.r.q0, a.r.q1 = a2.r.q1; + if (a.r.q1 < a.r.q0) + editerror("addresses out of order"); + return a; - case '+': - case '-': - sign = 1; - if(ap->type == '-') - sign = -1; - if(ap->next==0 || ap->next->type=='+' || ap->next->type=='-') - a = lineaddr(1L, a, sign); - break; - default: - error("cmdaddress"); - return a; - } - }while(ap = ap->next); /* assign = */ - return a; + case '+': + case '-': + sign = 1; + if (ap->type == '-') + sign = -1; + if (ap->next == 0 || ap->next->type == '+' || ap->next->type == '-') + a = lineaddr(1L, a, sign); + break; + default: + error("cmdaddress"); + return a; + } + } while (ap = ap->next); /* assign = */ + return a; } -struct Tofile{ - File *f; - String *r; +struct Tofile { + File* f; + String* r; }; -void -alltofile(Window *w, void *v) -{ - Text *t; - struct Tofile *tp; +void alltofile(Window* w, void* v) { + Text* t; + struct Tofile* tp; - tp = v; - if(tp->f != nil) - return; - if(w->isscratch || w->isdir) - return; - t = &w->body; - /* only use this window if it's the current window for the file */ - if(t->file->curtext != t) - return; -/* if(w->nopen[QWevent] > 0) */ -/* return; */ - if(runeeq(tp->r->r, tp->r->n, t->file->name, t->file->nname)) - tp->f = t->file; + tp = v; + if (tp->f != nil) + return; + if (w->isscratch || w->isdir) + return; + t = &w->body; + /* only use this window if it's the current window for the file */ + if (t->file->curtext != t) + return; + /* if(w->nopen[QWevent] > 0) */ + /* return; */ + if (runeeq(tp->r->r, tp->r->n, t->file->name, t->file->nname)) + tp->f = t->file; } -File* -tofile(String *r) -{ - struct Tofile t; - String rr; +File* tofile(String* r) { + struct Tofile t; + String rr; - rr.r = skipbl(r->r, r->n, &rr.n); - t.f = nil; - t.r = &rr; - allwindows(alltofile, &t); - if(t.f == nil) - editerror("no such file\"%S\"", rr.r); - return t.f; + rr.r = skipbl(r->r, r->n, &rr.n); + t.f = nil; + t.r = &rr; + allwindows(alltofile, &t); + if (t.f == nil) + editerror("no such file\"%S\"", rr.r); + return t.f; } -void -allmatchfile(Window *w, void *v) -{ - struct Tofile *tp; - Text *t; +void allmatchfile(Window* w, void* v) { + struct Tofile* tp; + Text* t; - tp = v; - if(w->isscratch || w->isdir) - return; - t = &w->body; - /* only use this window if it's the current window for the file */ - if(t->file->curtext != t) - return; -/* if(w->nopen[QWevent] > 0) */ -/* return; */ - if(filematch(w->body.file, tp->r)){ - if(tp->f != nil) - editerror("too many files match \"%S\"", tp->r->r); - tp->f = w->body.file; - } + tp = v; + if (w->isscratch || w->isdir) + return; + t = &w->body; + /* only use this window if it's the current window for the file */ + if (t->file->curtext != t) + return; + /* if(w->nopen[QWevent] > 0) */ + /* return; */ + if (filematch(w->body.file, tp->r)) { + if (tp->f != nil) + editerror("too many files match \"%S\"", tp->r->r); + tp->f = w->body.file; + } } -File* -matchfile(String *r) -{ - struct Tofile tf; +File* matchfile(String* r) { + struct Tofile tf; - tf.f = nil; - tf.r = r; - allwindows(allmatchfile, &tf); + tf.f = nil; + tf.r = r; + allwindows(allmatchfile, &tf); - if(tf.f == nil) - editerror("no file matches \"%S\"", r->r); - return tf.f; + if (tf.f == nil) + editerror("no file matches \"%S\"", r->r); + return tf.f; } -int -filematch(File *f, String *r) -{ - char *buf; - Rune *rbuf; - Window *w; - int match, i, dirty; - Rangeset s; +int filematch(File* f, String* r) { + char* buf; + Rune* rbuf; + Window* w; + int match, i, dirty; + Rangeset s; - /* compile expr first so if we get an error, we haven't allocated anything */ - if(rxcompile(r->r) == FALSE) - editerror("bad regexp in file match"); - buf = fbufalloc(); - w = f->curtext->w; - /* same check for dirty as in settag, but we know ncache==0 */ - dirty = !w->isdir && !w->isscratch && f->mod; - snprint(buf, BUFSIZE, "%c%c%c %.*S\n", " '"[dirty], - '+', " ."[curtext!=nil && curtext->file==f], f->nname, f->name); - rbuf = bytetorune(buf, &i); - fbuffree(buf); - match = rxexecute(nil, rbuf, 0, i, &s); - free(rbuf); - return match; + /* compile expr first so if we get an error, we haven't allocated anything */ + if (rxcompile(r->r) == FALSE) + editerror("bad regexp in file match"); + buf = fbufalloc(); + w = f->curtext->w; + /* same check for dirty as in settag, but we know ncache==0 */ + dirty = !w->isdir && !w->isscratch && f->mod; + snprint( + buf, + BUFSIZE, + "%c%c%c %.*S\n", + " '"[dirty], + '+', + " ."[curtext != nil && curtext->file == f], + f -> nname, + f -> name); + rbuf = bytetorune(buf, &i); + fbuffree(buf); + match = rxexecute(nil, rbuf, 0, i, &s); + free(rbuf); + return match; } -Address -charaddr(long l, Address addr, int sign) -{ - if(sign == 0) - addr.r.q0 = addr.r.q1 = l; - else if(sign < 0) - addr.r.q1 = addr.r.q0 -= l; - else if(sign > 0) - addr.r.q0 = addr.r.q1 += l; - if(addr.r.q0<0 || addr.r.q1>addr.f->b.nc) - editerror("address out of range"); - return addr; +Address charaddr(long l, Address addr, int sign) { + if (sign == 0) + addr.r.q0 = addr.r.q1 = l; + else if (sign < 0) + addr.r.q1 = addr.r.q0 -= l; + else if (sign > 0) + addr.r.q0 = addr.r.q1 += l; + if (addr.r.q0 < 0 || addr.r.q1 > addr.f->b.nc) + editerror("address out of range"); + return addr; } -Address -lineaddr(long l, Address addr, int sign) -{ - int n; - int c; - File *f = addr.f; - Address a; - long p; +Address lineaddr(long l, Address addr, int sign) { + int n; + int c; + File* f = addr.f; + Address a; + long p; - a.f = f; - if(sign >= 0){ - if(l == 0){ - if(sign==0 || addr.r.q1==0){ - a.r.q0 = a.r.q1 = 0; - return a; - } - a.r.q0 = addr.r.q1; - p = addr.r.q1-1; - }else{ - if(sign==0 || addr.r.q1==0){ - p = 0; - n = 1; - }else{ - p = addr.r.q1-1; - n = textreadc(f->curtext, p++)=='\n'; - } - while(n < l){ - if(p >= f->b.nc) - editerror("address out of range"); - if(textreadc(f->curtext, p++) == '\n') - n++; - } - a.r.q0 = p; - } - while(p < f->b.nc && textreadc(f->curtext, p++)!='\n') - ; - a.r.q1 = p; - }else{ - p = addr.r.q0; - if(l == 0) - a.r.q1 = addr.r.q0; - else{ - for(n = 0; ncurtext, p-1); - if(c != '\n' || ++n != l) - p--; - } - } - a.r.q1 = p; - if(p > 0) - p--; - } - while(p > 0 && textreadc(f->curtext, p-1)!='\n') /* lines start after a newline */ - p--; - a.r.q0 = p; - } - return a; + a.f = f; + if (sign >= 0) { + if (l == 0) { + if (sign == 0 || addr.r.q1 == 0) { + a.r.q0 = a.r.q1 = 0; + return a; + } + a.r.q0 = addr.r.q1; + p = addr.r.q1 - 1; + } else { + if (sign == 0 || addr.r.q1 == 0) { + p = 0; + n = 1; + } else { + p = addr.r.q1 - 1; + n = textreadc(f->curtext, p++) == '\n'; + } + while (n < l) { + if (p >= f->b.nc) + editerror("address out of range"); + if (textreadc(f->curtext, p++) == '\n') + n++; + } + a.r.q0 = p; + } + while (p < f->b.nc && textreadc(f->curtext, p++) != '\n') + ; + a.r.q1 = p; + } else { + p = addr.r.q0; + if (l == 0) + a.r.q1 = addr.r.q0; + else { + for (n = 0; n < l;) { /* always runs once */ + if (p == 0) { + if (++n != l) + editerror("address out of range"); + } else { + c = textreadc(f->curtext, p - 1); + if (c != '\n' || ++n != l) + p--; + } + } + a.r.q1 = p; + if (p > 0) + p--; + } + while (p > 0 && textreadc(f->curtext, p - 1) != + '\n') /* lines start after a newline */ + p--; + a.r.q0 = p; + } + return a; } -struct Filecheck -{ - File *f; - Rune *r; - int nr; +struct Filecheck { + File* f; + Rune* r; + int nr; }; -void -allfilecheck(Window *w, void *v) -{ - struct Filecheck *fp; - File *f; +void allfilecheck(Window* w, void* v) { + struct Filecheck* fp; + File* f; - fp = v; - f = w->body.file; - if(w->body.file == fp->f) - return; - if(runeeq(fp->r, fp->nr, f->name, f->nname)) - warning(nil, "warning: duplicate file name \"%.*S\"\n", fp->nr, fp->r); + fp = v; + f = w->body.file; + if (w->body.file == fp->f) + return; + if (runeeq(fp->r, fp->nr, f->name, f->nname)) + warning(nil, "warning: duplicate file name \"%.*S\"\n", fp->nr, fp->r); } -Rune* -cmdname(File *f, String *str, int set) -{ - Rune *r, *s; - int n; - struct Filecheck fc; - Runestr newname; +Rune* cmdname(File* f, String* str, int set) { + Rune *r, *s; + int n; + struct Filecheck fc; + Runestr newname; - r = nil; - n = str->n; - s = str->r; - if(n == 0){ - /* no name; use existing */ - if(f->nname == 0) - return nil; - r = runemalloc(f->nname+1); - runemove(r, f->name, f->nname); - return r; - } - s = skipbl(s, n, &n); - if(n == 0) - goto Return; + r = nil; + n = str->n; + s = str->r; + if (n == 0) { + /* no name; use existing */ + if (f->nname == 0) + return nil; + r = runemalloc(f->nname + 1); + runemove(r, f->name, f->nname); + return r; + } + s = skipbl(s, n, &n); + if (n == 0) + goto Return; - if(s[0] == '/'){ - r = runemalloc(n+1); - runemove(r, s, n); - }else{ - newname = dirname(f->curtext, runestrdup(s), n); - n = newname.nr; - r = runemalloc(n+1); /* NUL terminate */ - runemove(r, newname.r, n); - free(newname.r); - } - fc.f = f; - fc.r = r; - fc.nr = n; - allwindows(allfilecheck, &fc); - if(f->nname == 0) - set = TRUE; + if (s[0] == '/') { + r = runemalloc(n + 1); + runemove(r, s, n); + } else { + newname = dirname(f->curtext, runestrdup(s), n); + n = newname.nr; + r = runemalloc(n + 1); /* NUL terminate */ + runemove(r, newname.r, n); + free(newname.r); + } + fc.f = f; + fc.r = r; + fc.nr = n; + allwindows(allfilecheck, &fc); + if (f->nname == 0) + set = TRUE; - Return: - if(set && !runeeq(r, n, f->name, f->nname)){ - filemark(f); - f->mod = TRUE; - f->curtext->w->dirty = TRUE; - winsetname(f->curtext->w, r, n); - } - return r; +Return: + if (set && !runeeq(r, n, f->name, f->nname)) { + filemark(f); + f->mod = TRUE; + f->curtext->w->dirty = TRUE; + winsetname(f->curtext->w, r, n); + } + return r; } diff --git a/edit.c b/edit.c index d3f8205..e4ba23d 100644 --- a/edit.c +++ b/edit.c @@ -13,672 +13,842 @@ #include "edit.h" #include "fns.h" -static char linex[]="\n"; -static char wordx[]=" \t\n"; -struct cmdtab cmdtab[]={ -/* cmdc text regexp addr defcmd defaddr count token fn */ - '\n', 0, 0, 0, 0, aDot, 0, 0, nl_cmd, - 'a', 1, 0, 0, 0, aDot, 0, 0, a_cmd, - 'b', 0, 0, 0, 0, aNo, 0, linex, b_cmd, - 'c', 1, 0, 0, 0, aDot, 0, 0, c_cmd, - 'd', 0, 0, 0, 0, aDot, 0, 0, d_cmd, - 'e', 0, 0, 0, 0, aNo, 0, wordx, e_cmd, - 'f', 0, 0, 0, 0, aNo, 0, wordx, f_cmd, - 'g', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, - 'i', 1, 0, 0, 0, aDot, 0, 0, i_cmd, - 'm', 0, 0, 1, 0, aDot, 0, 0, m_cmd, - 'p', 0, 0, 0, 0, aDot, 0, 0, p_cmd, - 'r', 0, 0, 0, 0, aDot, 0, wordx, e_cmd, - 's', 0, 1, 0, 0, aDot, 1, 0, s_cmd, - 't', 0, 0, 1, 0, aDot, 0, 0, m_cmd, - 'u', 0, 0, 0, 0, aNo, 2, 0, u_cmd, - 'v', 0, 1, 0, 'p', aDot, 0, 0, g_cmd, - 'w', 0, 0, 0, 0, aAll, 0, wordx, w_cmd, - 'x', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, - 'y', 0, 1, 0, 'p', aDot, 0, 0, x_cmd, - '=', 0, 0, 0, 0, aDot, 0, linex, eq_cmd, - 'B', 0, 0, 0, 0, aNo, 0, linex, B_cmd, - 'D', 0, 0, 0, 0, aNo, 0, linex, D_cmd, - 'X', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, - 'Y', 0, 1, 0, 'f', aNo, 0, 0, X_cmd, - '<', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, - '|', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, - '>', 0, 0, 0, 0, aDot, 0, linex, pipe_cmd, -/* deliberately unimplemented: - 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd, - 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd, - 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd, - '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd, - */ - 0, 0, 0, 0, 0, 0, 0, 0 -}; +static char linex[] = "\n"; +static char wordx[] = " \t\n"; +struct cmdtab cmdtab[] = { + /* cmdc text regexp addr defcmd defaddr count token fn */ + '\n', + 0, + 0, + 0, + 0, + aDot, + 0, + 0, + nl_cmd, + 'a', + 1, + 0, + 0, + 0, + aDot, + 0, + 0, + a_cmd, + 'b', + 0, + 0, + 0, + 0, + aNo, + 0, + linex, + b_cmd, + 'c', + 1, + 0, + 0, + 0, + aDot, + 0, + 0, + c_cmd, + 'd', + 0, + 0, + 0, + 0, + aDot, + 0, + 0, + d_cmd, + 'e', + 0, + 0, + 0, + 0, + aNo, + 0, + wordx, + e_cmd, + 'f', + 0, + 0, + 0, + 0, + aNo, + 0, + wordx, + f_cmd, + 'g', + 0, + 1, + 0, + 'p', + aDot, + 0, + 0, + g_cmd, + 'i', + 1, + 0, + 0, + 0, + aDot, + 0, + 0, + i_cmd, + 'm', + 0, + 0, + 1, + 0, + aDot, + 0, + 0, + m_cmd, + 'p', + 0, + 0, + 0, + 0, + aDot, + 0, + 0, + p_cmd, + 'r', + 0, + 0, + 0, + 0, + aDot, + 0, + wordx, + e_cmd, + 's', + 0, + 1, + 0, + 0, + aDot, + 1, + 0, + s_cmd, + 't', + 0, + 0, + 1, + 0, + aDot, + 0, + 0, + m_cmd, + 'u', + 0, + 0, + 0, + 0, + aNo, + 2, + 0, + u_cmd, + 'v', + 0, + 1, + 0, + 'p', + aDot, + 0, + 0, + g_cmd, + 'w', + 0, + 0, + 0, + 0, + aAll, + 0, + wordx, + w_cmd, + 'x', + 0, + 1, + 0, + 'p', + aDot, + 0, + 0, + x_cmd, + 'y', + 0, + 1, + 0, + 'p', + aDot, + 0, + 0, + x_cmd, + '=', + 0, + 0, + 0, + 0, + aDot, + 0, + linex, + eq_cmd, + 'B', + 0, + 0, + 0, + 0, + aNo, + 0, + linex, + B_cmd, + 'D', + 0, + 0, + 0, + 0, + aNo, + 0, + linex, + D_cmd, + 'X', + 0, + 1, + 0, + 'f', + aNo, + 0, + 0, + X_cmd, + 'Y', + 0, + 1, + 0, + 'f', + aNo, + 0, + 0, + X_cmd, + '<', + 0, + 0, + 0, + 0, + aDot, + 0, + linex, + pipe_cmd, + '|', + 0, + 0, + 0, + 0, + aDot, + 0, + linex, + pipe_cmd, + '>', + 0, + 0, + 0, + 0, + aDot, + 0, + linex, + pipe_cmd, + /* deliberately unimplemented: + 'k', 0, 0, 0, 0, aDot, 0, 0, k_cmd, + 'n', 0, 0, 0, 0, aNo, 0, 0, n_cmd, + 'q', 0, 0, 0, 0, aNo, 0, 0, q_cmd, + '!', 0, 0, 0, 0, aNo, 0, linex, plan9_cmd, + */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0}; -Cmd *parsecmd(int); -Addr *compoundaddr(void); -Addr *simpleaddr(void); -void freecmd(void); -void okdelim(int); +Cmd* parsecmd(int); +Addr* compoundaddr(void); +Addr* simpleaddr(void); +void freecmd(void); +void okdelim(int); -Rune *cmdstartp; -Rune *cmdendp; -Rune *cmdp; -Channel *editerrc; +Rune* cmdstartp; +Rune* cmdendp; +Rune* cmdp; +Channel* editerrc; -String *lastpat; -int patset; +String* lastpat; +int patset; -List cmdlist; -List addrlist; -List stringlist; -Text *curtext; -int editing = Inactive; +List cmdlist; +List addrlist; +List stringlist; +Text* curtext; +int editing = Inactive; -String* newstring(int); +String* newstring(int); -void -editthread(void *v) -{ - Cmd *cmdp; +void editthread(void* v) { + Cmd* cmdp; - USED(v); - threadsetname("editthread"); - while((cmdp=parsecmd(0)) != 0){ - if(cmdexec(curtext, cmdp) == 0) - break; - freecmd(); - } - sendp(editerrc, nil); + USED(v); + threadsetname("editthread"); + while ((cmdp = parsecmd(0)) != 0) { + if (cmdexec(curtext, cmdp) == 0) + break; + freecmd(); + } + sendp(editerrc, nil); } -void -allelogterm(Window *w, void *x) -{ - USED(x); - elogterm(w->body.file); +void allelogterm(Window* w, void* x) { + USED(x); + elogterm(w->body.file); } -void -alleditinit(Window *w, void *x) -{ - USED(x); - textcommit(&w->tag, TRUE); - textcommit(&w->body, TRUE); - w->body.file->editclean = FALSE; +void alleditinit(Window* w, void* x) { + USED(x); + textcommit(&w->tag, TRUE); + textcommit(&w->body, TRUE); + w->body.file->editclean = FALSE; } -void -allupdate(Window *w, void *x) -{ - Text *t; - int i; - File *f; +void allupdate(Window* w, void* x) { + Text* t; + int i; + File* f; - USED(x); - t = &w->body; - f = t->file; - if(f->curtext != t) /* do curtext only */ - return; - if(f->elog.type == Null) - elogterm(f); - else if(f->elog.type != Empty){ - elogapply(f); - if(f->editclean){ - f->mod = FALSE; - for(i=0; intext; i++) - f->text[i]->w->dirty = FALSE; - } - } - textsetselect(t, t->q0, t->q1); - textscrdraw(t); - winsettag(w); + USED(x); + t = &w->body; + f = t->file; + if (f->curtext != t) /* do curtext only */ + return; + if (f->elog.type == Null) + elogterm(f); + else if (f->elog.type != Empty) { + elogapply(f); + if (f->editclean) { + f->mod = FALSE; + for (i = 0; i < f->ntext; i++) + f->text[i]->w->dirty = FALSE; + } + } + textsetselect(t, t->q0, t->q1); + textscrdraw(t); + winsettag(w); } -void -editerror(char *fmt, ...) -{ - va_list arg; - char *s; +void editerror(char* fmt, ...) { + va_list arg; + char* s; - va_start(arg, fmt); - s = vsmprint(fmt, arg); - va_end(arg); - freecmd(); - allwindows(allelogterm, nil); /* truncate the edit logs */ - sendp(editerrc, s); - threadexits(nil); + va_start(arg, fmt); + s = vsmprint(fmt, arg); + va_end(arg); + freecmd(); + allwindows(allelogterm, nil); /* truncate the edit logs */ + sendp(editerrc, s); + threadexits(nil); } -void -editcmd(Text *ct, Rune *r, uint n) -{ - char *err; +void editcmd(Text* ct, Rune* r, uint n) { + char* err; - if(n == 0) - return; - if(2*n > RBUFSIZE){ - warning(nil, "string too long\n"); - return; - } + if (n == 0) + return; + if (2 * n > RBUFSIZE) { + warning(nil, "string too long\n"); + return; + } - allwindows(alleditinit, nil); - if(cmdstartp) - free(cmdstartp); - cmdstartp = runemalloc(n+2); - runemove(cmdstartp, r, n); - if(r[n-1] != '\n') - cmdstartp[n++] = '\n'; - cmdstartp[n] = '\0'; - cmdendp = cmdstartp+n; - cmdp = cmdstartp; - if(ct->w == nil) - curtext = nil; - else - curtext = &ct->w->body; - resetxec(); - if(editerrc == nil){ - editerrc = chancreate(sizeof(char*), 0); - chansetname(editerrc, "editerrc"); - lastpat = allocstring(0); - } - threadcreate(editthread, nil, STACK); - err = recvp(editerrc); - editing = Inactive; - if(err != nil){ - if(err[0] != '\0') - warning(nil, "Edit: %s\n", err); - free(err); - } + allwindows(alleditinit, nil); + if (cmdstartp) + free(cmdstartp); + cmdstartp = runemalloc(n + 2); + runemove(cmdstartp, r, n); + if (r[n - 1] != '\n') + cmdstartp[n++] = '\n'; + cmdstartp[n] = '\0'; + cmdendp = cmdstartp + n; + cmdp = cmdstartp; + if (ct->w == nil) + curtext = nil; + else + curtext = &ct->w->body; + resetxec(); + if (editerrc == nil) { + editerrc = chancreate(sizeof(char*), 0); + chansetname(editerrc, "editerrc"); + lastpat = allocstring(0); + } + threadcreate(editthread, nil, STACK); + err = recvp(editerrc); + editing = Inactive; + if (err != nil) { + if (err[0] != '\0') + warning(nil, "Edit: %s\n", err); + free(err); + } - /* update everyone whose edit log has data */ - allwindows(allupdate, nil); + /* update everyone whose edit log has data */ + allwindows(allupdate, nil); } -int -getch(void) -{ - if(cmdp == cmdendp) - return -1; - return *cmdp++; +int getch(void) { + if (cmdp == cmdendp) + return -1; + return *cmdp++; } -int -nextc(void) -{ - if(cmdp == cmdendp) - return -1; - return *cmdp; +int nextc(void) { + if (cmdp == cmdendp) + return -1; + return *cmdp; } -void -ungetch(void) -{ - if(--cmdp < cmdstartp) - error("ungetch"); +void ungetch(void) { + if (--cmdp < cmdstartp) + error("ungetch"); } -long -getnum(int signok) -{ - long n; - int c, sign; +long getnum(int signok) { + long n; + int c, sign; - n = 0; - sign = 1; - if(signok>1 && nextc()=='-'){ - sign = -1; - getch(); - } - if((c=nextc())<'0' || '9' 1 && nextc() == '-') { + sign = -1; + getch(); + } + if ((c = nextc()) < '0' || '9' < c) /* no number defaults to 1 */ + return sign; + while ('0' <= (c = getch()) && c <= '9') + n = n * 10 + (c - '0'); + ungetch(); + return sign * n; } -int -cmdskipbl(void) -{ - int c; - do - c = getch(); - while(c==' ' || c=='\t'); - if(c >= 0) - ungetch(); - return c; +int cmdskipbl(void) { + int c; + do + c = getch(); + while (c == ' ' || c == '\t'); + if (c >= 0) + ungetch(); + return c; } /* * Check that list has room for one more element. */ -void -growlist(List *l) -{ - if(l->u.listptr==0 || l->nalloc==0){ - l->nalloc = INCR; - l->u.listptr = emalloc(INCR*sizeof(void*)); - l->nused = 0; - }else if(l->nused == l->nalloc){ - l->u.listptr = erealloc(l->u.listptr, (l->nalloc+INCR)*sizeof(void*)); - memset(l->u.ptr+l->nalloc, 0, INCR*sizeof(void*)); - l->nalloc += INCR; - } +void growlist(List* l) { + if (l->u.listptr == 0 || l->nalloc == 0) { + l->nalloc = INCR; + l->u.listptr = emalloc(INCR * sizeof(void*)); + l->nused = 0; + } else if (l->nused == l->nalloc) { + l->u.listptr = erealloc(l->u.listptr, (l->nalloc + INCR) * sizeof(void*)); + memset(l->u.ptr + l->nalloc, 0, INCR * sizeof(void*)); + l->nalloc += INCR; + } } /* * Remove the ith element from the list */ -void -dellist(List *l, int i) -{ - memmove(&l->u.ptr[i], &l->u.ptr[i+1], (l->nused-(i+1))*sizeof(void*)); - l->nused--; +void dellist(List* l, int i) { + memmove(&l->u.ptr[i], &l->u.ptr[i + 1], (l->nused - (i + 1)) * sizeof(void*)); + l->nused--; } /* * Add a new element, whose position is i, to the list */ -void -inslist(List *l, int i, void *v) -{ - growlist(l); - memmove(&l->u.ptr[i+1], &l->u.ptr[i], (l->nused-i)*sizeof(void*)); - l->u.ptr[i] = v; - l->nused++; +void inslist(List* l, int i, void* v) { + growlist(l); + memmove(&l->u.ptr[i + 1], &l->u.ptr[i], (l->nused - i) * sizeof(void*)); + l->u.ptr[i] = v; + l->nused++; } -void -listfree(List *l) -{ - free(l->u.listptr); - free(l); +void listfree(List* l) { + free(l->u.listptr); + free(l); } -String* -allocstring(int n) -{ - String *s; +String* allocstring(int n) { + String* s; - s = emalloc(sizeof(String)); - s->n = n; - s->nalloc = n+10; - s->r = emalloc(s->nalloc*sizeof(Rune)); - s->r[n] = '\0'; - return s; + s = emalloc(sizeof(String)); + s->n = n; + s->nalloc = n + 10; + s->r = emalloc(s->nalloc * sizeof(Rune)); + s->r[n] = '\0'; + return s; } -void -freestring(String *s) -{ - free(s->r); - free(s); +void freestring(String* s) { + free(s->r); + free(s); } -Cmd* -newcmd(void){ - Cmd *p; +Cmd* newcmd(void) { + Cmd* p; - p = emalloc(sizeof(Cmd)); - inslist(&cmdlist, cmdlist.nused, p); - return p; + p = emalloc(sizeof(Cmd)); + inslist(&cmdlist, cmdlist.nused, p); + return p; } -String* -newstring(int n) -{ - String *p; +String* newstring(int n) { + String* p; - p = allocstring(n); - inslist(&stringlist, stringlist.nused, p); - return p; + p = allocstring(n); + inslist(&stringlist, stringlist.nused, p); + return p; } -Addr* -newaddr(void) -{ - Addr *p; +Addr* newaddr(void) { + Addr* p; - p = emalloc(sizeof(Addr)); - inslist(&addrlist, addrlist.nused, p); - return p; + p = emalloc(sizeof(Addr)); + inslist(&addrlist, addrlist.nused, p); + return p; } -void -freecmd(void) -{ - int i; +void freecmd(void) { + int i; - while(cmdlist.nused > 0) - free(cmdlist.u.ucharptr[--cmdlist.nused]); - while(addrlist.nused > 0) - free(addrlist.u.ucharptr[--addrlist.nused]); - while(stringlist.nused>0){ - i = --stringlist.nused; - freestring(stringlist.u.stringptr[i]); - } + while (cmdlist.nused > 0) + free(cmdlist.u.ucharptr[--cmdlist.nused]); + while (addrlist.nused > 0) + free(addrlist.u.ucharptr[--addrlist.nused]); + while (stringlist.nused > 0) { + i = --stringlist.nused; + freestring(stringlist.u.stringptr[i]); + } } -void -okdelim(int c) -{ - if(c=='\\' || ('a'<=c && c<='z') - || ('A'<=c && c<='Z') || ('0'<=c && c<='9')) - editerror("bad delimiter %c\n", c); +void okdelim(int c) { + if ( + c == '\\' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9')) + editerror("bad delimiter %c\n", c); } -void -atnl(void) -{ - int c; +void atnl(void) { + int c; - cmdskipbl(); - c = getch(); - if(c != '\n') - editerror("newline expected (saw %C)", c); + cmdskipbl(); + c = getch(); + if (c != '\n') + editerror("newline expected (saw %C)", c); } -void -Straddc(String *s, int c) -{ - if(s->n+1 >= s->nalloc){ - s->nalloc += 10; - s->r = erealloc(s->r, s->nalloc*sizeof(Rune)); - } - s->r[s->n++] = c; - s->r[s->n] = '\0'; +void Straddc(String* s, int c) { + if (s->n + 1 >= s->nalloc) { + s->nalloc += 10; + s->r = erealloc(s->r, s->nalloc * sizeof(Rune)); + } + s->r[s->n++] = c; + s->r[s->n] = '\0'; } -void -getrhs(String *s, int delim, int cmd) -{ - int c; +void getrhs(String* s, int delim, int cmd) { + int c; - while((c = getch())>0 && c!=delim && c!='\n'){ - if(c == '\\'){ - if((c=getch()) <= 0) - error("bad right hand side"); - if(c == '\n'){ - ungetch(); - c='\\'; - }else if(c == 'n') - c='\n'; - else if(c!=delim && (cmd=='s' || c!='\\')) /* s does its own */ - Straddc(s, '\\'); - } - Straddc(s, c); - } - ungetch(); /* let client read whether delimiter, '\n' or whatever */ + while ((c = getch()) > 0 && c != delim && c != '\n') { + if (c == '\\') { + if ((c = getch()) <= 0) + error("bad right hand side"); + if (c == '\n') { + ungetch(); + c = '\\'; + } else if (c == 'n') + c = '\n'; + else if (c != delim && (cmd == 's' || c != '\\')) /* s does its own */ + Straddc(s, '\\'); + } + Straddc(s, c); + } + ungetch(); /* let client read whether delimiter, '\n' or whatever */ } -String * -collecttoken(char *end) -{ - String *s = newstring(0); - int c; +String* collecttoken(char* end) { + String* s = newstring(0); + int c; - while((c=nextc())==' ' || c=='\t') - Straddc(s, getch()); /* blanks significant for getname() */ - while((c=getch())>0 && utfrune(end, c)==0) - Straddc(s, c); - if(c != '\n') - atnl(); - return s; + while ((c = nextc()) == ' ' || c == '\t') + Straddc(s, getch()); /* blanks significant for getname() */ + while ((c = getch()) > 0 && utfrune(end, c) == 0) + Straddc(s, c); + if (c != '\n') + atnl(); + return s; } -String * -collecttext(void) -{ - String *s; - int begline, i, c, delim; +String* collecttext(void) { + String* s; + int begline, i, c, delim; - s = newstring(0); - if(cmdskipbl()=='\n'){ - getch(); - i = 0; - do{ - begline = i; - while((c = getch())>0 && c!='\n') - i++, Straddc(s, c); - i++, Straddc(s, '\n'); - if(c < 0) - goto Return; - }while(s->r[begline]!='.' || s->r[begline+1]!='\n'); - s->r[s->n-2] = '\0'; - s->n -= 2; - }else{ - okdelim(delim = getch()); - getrhs(s, delim, 'a'); - if(nextc()==delim) - getch(); - atnl(); - } - Return: - return s; + s = newstring(0); + if (cmdskipbl() == '\n') { + getch(); + i = 0; + do { + begline = i; + while ((c = getch()) > 0 && c != '\n') + i++, Straddc(s, c); + i++, Straddc(s, '\n'); + if (c < 0) + goto Return; + } while (s->r[begline] != '.' || s->r[begline + 1] != '\n'); + s->r[s->n - 2] = '\0'; + s->n -= 2; + } else { + okdelim(delim = getch()); + getrhs(s, delim, 'a'); + if (nextc() == delim) + getch(); + atnl(); + } +Return: + return s; } -int -cmdlookup(int c) -{ - int i; +int cmdlookup(int c) { + int i; - for(i=0; cmdtab[i].cmdc; i++) - if(cmdtab[i].cmdc == c) - return i; - return -1; + for (i = 0; cmdtab[i].cmdc; i++) + if (cmdtab[i].cmdc == c) + return i; + return -1; } -Cmd* -parsecmd(int nest) -{ - int i, c; - struct cmdtab *ct; - Cmd *cp, *ncp; - Cmd cmd; +Cmd* parsecmd(int nest) { + int i, c; + struct cmdtab* ct; + Cmd *cp, *ncp; + Cmd cmd; - cmd.next = cmd.u.cmd = 0; - cmd.re = 0; - cmd.flag = cmd.num = 0; - cmd.addr = compoundaddr(); - if(cmdskipbl() == -1) - return 0; - if((c=getch())==-1) - return 0; - cmd.cmdc = c; - if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ - getch(); /* the 'd' */ - cmd.cmdc='c'|0x100; - } - i = cmdlookup(cmd.cmdc); - if(i >= 0){ - if(cmd.cmdc == '\n') - goto Return; /* let nl_cmd work it all out */ - ct = &cmdtab[i]; - if(ct->defaddr==aNo && cmd.addr) - editerror("command takes no address"); - if(ct->count) - cmd.num = getnum(ct->count); - if(ct->regexp){ - /* x without pattern -> .*\n, indicated by cmd.re==0 */ - /* X without pattern is all files */ - if((ct->cmdc!='x' && ct->cmdc!='X') || - ((c = nextc())!=' ' && c!='\t' && c!='\n')){ - cmdskipbl(); - if((c = getch())=='\n' || c<0) - editerror("no address"); - okdelim(c); - cmd.re = getregexp(c); - if(ct->cmdc == 's'){ - cmd.u.text = newstring(0); - getrhs(cmd.u.text, c, 's'); - if(nextc() == c){ - getch(); - if(nextc() == 'g') - cmd.flag = getch(); - } - - } - } - } - if(ct->addr && (cmd.u.mtaddr=simpleaddr())==0) - editerror("bad address"); - if(ct->defcmd){ - if(cmdskipbl() == '\n'){ - getch(); - cmd.u.cmd = newcmd(); - cmd.u.cmd->cmdc = ct->defcmd; - }else if((cmd.u.cmd = parsecmd(nest))==0) - error("defcmd"); - }else if(ct->text) - cmd.u.text = collecttext(); - else if(ct->token) - cmd.u.text = collecttoken(ct->token); - else - atnl(); - }else - switch(cmd.cmdc){ - case '{': - cp = 0; - do{ - if(cmdskipbl()=='\n') - getch(); - ncp = parsecmd(nest+1); - if(cp) - cp->next = ncp; - else - cmd.u.cmd = ncp; - }while(cp = ncp); - break; - case '}': - atnl(); - if(nest==0) - editerror("right brace with no left brace"); - return 0; - default: - editerror("unknown command %c", cmd.cmdc); - } - Return: - cp = newcmd(); - *cp = cmd; - return cp; + cmd.next = cmd.u.cmd = 0; + cmd.re = 0; + cmd.flag = cmd.num = 0; + cmd.addr = compoundaddr(); + if (cmdskipbl() == -1) + return 0; + if ((c = getch()) == -1) + return 0; + cmd.cmdc = c; + if (cmd.cmdc == 'c' && nextc() == 'd') { /* sleazy two-character case */ + getch(); /* the 'd' */ + cmd.cmdc = 'c' | 0x100; + } + i = cmdlookup(cmd.cmdc); + if (i >= 0) { + if (cmd.cmdc == '\n') + goto Return; /* let nl_cmd work it all out */ + ct = &cmdtab[i]; + if (ct->defaddr == aNo && cmd.addr) + editerror("command takes no address"); + if (ct->count) + cmd.num = getnum(ct->count); + if (ct->regexp) { + /* x without pattern -> .*\n, indicated by cmd.re==0 */ + /* X without pattern is all files */ + if ( + (ct->cmdc != 'x' && ct->cmdc != 'X') || + ((c = nextc()) != ' ' && c != '\t' && c != '\n')) { + cmdskipbl(); + if ((c = getch()) == '\n' || c < 0) + editerror("no address"); + okdelim(c); + cmd.re = getregexp(c); + if (ct->cmdc == 's') { + cmd.u.text = newstring(0); + getrhs(cmd.u.text, c, 's'); + if (nextc() == c) { + getch(); + if (nextc() == 'g') + cmd.flag = getch(); + } + } + } + } + if (ct->addr && (cmd.u.mtaddr = simpleaddr()) == 0) + editerror("bad address"); + if (ct->defcmd) { + if (cmdskipbl() == '\n') { + getch(); + cmd.u.cmd = newcmd(); + cmd.u.cmd->cmdc = ct->defcmd; + } else if ((cmd.u.cmd = parsecmd(nest)) == 0) + error("defcmd"); + } else if (ct->text) + cmd.u.text = collecttext(); + else if (ct->token) + cmd.u.text = collecttoken(ct->token); + else + atnl(); + } else + switch (cmd.cmdc) { + case '{': + cp = 0; + do { + if (cmdskipbl() == '\n') + getch(); + ncp = parsecmd(nest + 1); + if (cp) + cp->next = ncp; + else + cmd.u.cmd = ncp; + } while (cp = ncp); + break; + case '}': + atnl(); + if (nest == 0) + editerror("right brace with no left brace"); + return 0; + default: + editerror("unknown command %c", cmd.cmdc); + } +Return: + cp = newcmd(); + *cp = cmd; + return cp; } -String* -getregexp(int delim) -{ - String *buf, *r; - int i, c; +String* getregexp(int delim) { + String *buf, *r; + int i, c; - buf = allocstring(0); - for(i=0; ; i++){ - if((c = getch())=='\\'){ - if(nextc()==delim) - c = getch(); - else if(nextc()=='\\'){ - Straddc(buf, c); - c = getch(); - } - }else if(c==delim || c=='\n') - break; - if(i >= RBUFSIZE) - editerror("regular expression too long"); - Straddc(buf, c); - } - if(c!=delim && c) - ungetch(); - if(buf->n > 0){ - patset = TRUE; - freestring(lastpat); - lastpat = buf; - }else - freestring(buf); - if(lastpat->n == 0) - editerror("no regular expression defined"); - r = newstring(lastpat->n); - runemove(r->r, lastpat->r, lastpat->n); /* newstring put \0 at end */ - return r; + buf = allocstring(0); + for (i = 0;; i++) { + if ((c = getch()) == '\\') { + if (nextc() == delim) + c = getch(); + else if (nextc() == '\\') { + Straddc(buf, c); + c = getch(); + } + } else if (c == delim || c == '\n') + break; + if (i >= RBUFSIZE) + editerror("regular expression too long"); + Straddc(buf, c); + } + if (c != delim && c) + ungetch(); + if (buf->n > 0) { + patset = TRUE; + freestring(lastpat); + lastpat = buf; + } else + freestring(buf); + if (lastpat->n == 0) + editerror("no regular expression defined"); + r = newstring(lastpat->n); + runemove(r->r, lastpat->r, lastpat->n); /* newstring put \0 at end */ + return r; } -Addr * -simpleaddr(void) -{ - Addr addr; - Addr *ap, *nap; +Addr* simpleaddr(void) { + Addr addr; + Addr *ap, *nap; - addr.num = 0; - addr.next = 0; - addr.u.left = 0; - switch(cmdskipbl()){ - case '#': - addr.type = getch(); - addr.num = getnum(1); - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - addr.num = getnum(1); - addr.type='l'; - break; - case '/': case '?': case '"': - addr.u.re = getregexp(addr.type = getch()); - break; - case '.': - case '$': - case '+': - case '-': - case '\'': - addr.type = getch(); - break; - default: - return 0; - } - if(addr.next = simpleaddr()) - switch(addr.next->type){ - case '.': - case '$': - case '\'': - if(addr.type!='"') - case '"': - editerror("bad address syntax"); - break; - case 'l': - case '#': - if(addr.type=='"') - break; - /* fall through */ - case '/': - case '?': - if(addr.type!='+' && addr.type!='-'){ - /* insert the missing '+' */ - nap = newaddr(); - nap->type='+'; - nap->next = addr.next; - addr.next = nap; - } - break; - case '+': - case '-': - break; - default: - error("simpleaddr"); - } - ap = newaddr(); - *ap = addr; - return ap; + addr.num = 0; + addr.next = 0; + addr.u.left = 0; + switch (cmdskipbl()) { + case '#': + addr.type = getch(); + addr.num = getnum(1); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + addr.num = getnum(1); + addr.type = 'l'; + break; + case '/': + case '?': + case '"': + addr.u.re = getregexp(addr.type = getch()); + break; + case '.': + case '$': + case '+': + case '-': + case '\'': + addr.type = getch(); + break; + default: + return 0; + } + if (addr.next = simpleaddr()) + switch (addr.next->type) { + case '.': + case '$': + case '\'': + if (addr.type != '"') + case '"': + editerror("bad address syntax"); + break; + case 'l': + case '#': + if (addr.type == '"') + break; + /* fall through */ + case '/': + case '?': + if (addr.type != '+' && addr.type != '-') { + /* insert the missing '+' */ + nap = newaddr(); + nap->type = '+'; + nap->next = addr.next; + addr.next = nap; + } + break; + case '+': + case '-': + break; + default: + error("simpleaddr"); + } + ap = newaddr(); + *ap = addr; + return ap; } -Addr * -compoundaddr(void) -{ - Addr addr; - Addr *ap, *next; +Addr* compoundaddr(void) { + Addr addr; + Addr *ap, *next; - addr.u.left = simpleaddr(); - if((addr.type = cmdskipbl())!=',' && addr.type!=';') - return addr.u.left; - getch(); - next = addr.next = compoundaddr(); - if(next && (next->type==',' || next->type==';') && next->u.left==0) - editerror("bad address syntax"); - ap = newaddr(); - *ap = addr; - return ap; + addr.u.left = simpleaddr(); + if ((addr.type = cmdskipbl()) != ',' && addr.type != ';') + return addr.u.left; + getch(); + next = addr.next = compoundaddr(); + if (next && (next->type == ',' || next->type == ';') && next->u.left == 0) + editerror("bad address syntax"); + ap = newaddr(); + *ap = addr; + return ap; } diff --git a/elog.c b/elog.c index c5650f0..6410378 100644 --- a/elog.c +++ b/elog.c @@ -14,7 +14,7 @@ #include "edit.h" static char Wsequence[] = "warning: changes out of sequence\n"; -static int warned = FALSE; +static int warned = FALSE; /* * Log of changes made by editing commands. Three reasons for this: @@ -27,328 +27,321 @@ static int warned = FALSE; */ typedef struct Buflog Buflog; -struct Buflog -{ - short type; /* Replace, Filename */ - uint q0; /* location of change (unused in f) */ - uint nd; /* # runes to delete */ - uint nr; /* # runes in string or file name */ +struct Buflog { + short type; /* Replace, Filename */ + uint q0; /* location of change (unused in f) */ + uint nd; /* # runes to delete */ + uint nr; /* # runes in string or file name */ }; -enum -{ - Buflogsize = sizeof(Buflog)/sizeof(Rune) -}; +enum { Buflogsize = sizeof(Buflog) / sizeof(Rune) }; /* * Minstring shouldn't be very big or we will do lots of I/O for small changes. * Maxstring is RBUFSIZE so we can fbufalloc() once and not realloc elog.r. */ -enum -{ - Minstring = 16, /* distance beneath which we merge changes */ - Maxstring = RBUFSIZE /* maximum length of change we will merge into one */ +enum { + Minstring = 16, /* distance beneath which we merge changes */ + Maxstring = RBUFSIZE /* maximum length of change we will merge into one */ }; -void -eloginit(File *f) -{ - if(f->elog.type != Empty) - return; - f->elog.type = Null; - if(f->elogbuf == nil) - f->elogbuf = emalloc(sizeof(Buffer)); - if(f->elog.r == nil) - f->elog.r = fbufalloc(); - bufreset(f->elogbuf); +void eloginit(File* f) { + if (f->elog.type != Empty) + return; + f->elog.type = Null; + if (f->elogbuf == nil) + f->elogbuf = emalloc(sizeof(Buffer)); + if (f->elog.r == nil) + f->elog.r = fbufalloc(); + bufreset(f->elogbuf); } -void -elogclose(File *f) -{ - if(f->elogbuf){ - bufclose(f->elogbuf); - free(f->elogbuf); - f->elogbuf = nil; - } +void elogclose(File* f) { + if (f->elogbuf) { + bufclose(f->elogbuf); + free(f->elogbuf); + f->elogbuf = nil; + } } -void -elogreset(File *f) -{ - f->elog.type = Null; - f->elog.nd = 0; - f->elog.nr = 0; +void elogreset(File* f) { + f->elog.type = Null; + f->elog.nd = 0; + f->elog.nr = 0; } -void -elogterm(File *f) -{ - elogreset(f); - if(f->elogbuf) - bufreset(f->elogbuf); - f->elog.type = Empty; - fbuffree(f->elog.r); - f->elog.r = nil; - warned = FALSE; +void elogterm(File* f) { + elogreset(f); + if (f->elogbuf) + bufreset(f->elogbuf); + f->elog.type = Empty; + fbuffree(f->elog.r); + f->elog.r = nil; + warned = FALSE; } -void -elogflush(File *f) -{ - Buflog b; +void elogflush(File* f) { + Buflog b; - b.type = f->elog.type; - b.q0 = f->elog.q0; - b.nd = f->elog.nd; - b.nr = f->elog.nr; - switch(f->elog.type){ - default: - warning(nil, "unknown elog type 0x%ux\n", f->elog.type); - break; - case Null: - break; - case Insert: - case Replace: - if(f->elog.nr > 0) - bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr); - /* fall through */ - case Delete: - bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize); - break; - } - elogreset(f); + b.type = f->elog.type; + b.q0 = f->elog.q0; + b.nd = f->elog.nd; + b.nr = f->elog.nr; + switch (f->elog.type) { + default: + warning(nil, "unknown elog type 0x%ux\n", f->elog.type); + break; + case Null: + break; + case Insert: + case Replace: + if (f->elog.nr > 0) + bufinsert(f->elogbuf, f->elogbuf->nc, f->elog.r, f->elog.nr); + /* fall through */ + case Delete: + bufinsert(f->elogbuf, f->elogbuf->nc, (Rune*)&b, Buflogsize); + break; + } + elogreset(f); } -void -elogreplace(File *f, int q0, int q1, Rune *r, int nr) -{ - uint gap; +void elogreplace(File* f, int q0, int q1, Rune* r, int nr) { + uint gap; - if(q0==q1 && nr==0) - return; - eloginit(f); - if(f->elog.type!=Null && q0elog.q0){ - if(warned++ == 0) - warning(nil, Wsequence); - elogflush(f); - } - /* try to merge with previous */ - gap = q0 - (f->elog.q0+f->elog.nd); /* gap between previous and this */ - if(f->elog.type==Replace && f->elog.nr+gap+nr 0){ - bufread(&f->b, f->elog.q0+f->elog.nd, f->elog.r+f->elog.nr, gap); - f->elog.nr += gap; - } - f->elog.nd += gap + q1-q0; - runemove(f->elog.r+f->elog.nr, r, nr); - f->elog.nr += nr; - return; - } - } - elogflush(f); - f->elog.type = Replace; - f->elog.q0 = q0; - f->elog.nd = q1-q0; - f->elog.nr = nr; - if(nr > RBUFSIZE) - editerror("internal error: replacement string too large(%d)", nr); - runemove(f->elog.r, r, nr); + if (q0 == q1 && nr == 0) + return; + eloginit(f); + if (f->elog.type != Null && q0 < f->elog.q0) { + if (warned++ == 0) + warning(nil, Wsequence); + elogflush(f); + } + /* try to merge with previous */ + gap = q0 - (f->elog.q0 + f->elog.nd); /* gap between previous and this */ + if (f->elog.type == Replace && f->elog.nr + gap + nr < Maxstring) { + if (gap < Minstring) { + if (gap > 0) { + bufread(&f->b, f->elog.q0 + f->elog.nd, f->elog.r + f->elog.nr, gap); + f->elog.nr += gap; + } + f->elog.nd += gap + q1 - q0; + runemove(f->elog.r + f->elog.nr, r, nr); + f->elog.nr += nr; + return; + } + } + elogflush(f); + f->elog.type = Replace; + f->elog.q0 = q0; + f->elog.nd = q1 - q0; + f->elog.nr = nr; + if (nr > RBUFSIZE) + editerror("internal error: replacement string too large(%d)", nr); + runemove(f->elog.r, r, nr); } -void -eloginsert(File *f, int q0, Rune *r, int nr) -{ - int n; +void eloginsert(File* f, int q0, Rune* r, int nr) { + int n; - if(nr == 0) - return; - eloginit(f); - if(f->elog.type!=Null && q0elog.q0){ - if(warned++ == 0) - warning(nil, Wsequence); - elogflush(f); - } - /* try to merge with previous */ - if(f->elog.type==Insert && q0==f->elog.q0 && f->elog.nr+nrelog.r+f->elog.nr, r, nr); - f->elog.nr += nr; - return; - } - while(nr > 0){ - elogflush(f); - f->elog.type = Insert; - f->elog.q0 = q0; - n = nr; - if(n > RBUFSIZE) - n = RBUFSIZE; - f->elog.nr = n; - runemove(f->elog.r, r, n); - r += n; - nr -= n; - } + if (nr == 0) + return; + eloginit(f); + if (f->elog.type != Null && q0 < f->elog.q0) { + if (warned++ == 0) + warning(nil, Wsequence); + elogflush(f); + } + /* try to merge with previous */ + if ( + f->elog.type == Insert && q0 == f->elog.q0 && f->elog.nr + nr < Maxstring) { + runemove(f->elog.r + f->elog.nr, r, nr); + f->elog.nr += nr; + return; + } + while (nr > 0) { + elogflush(f); + f->elog.type = Insert; + f->elog.q0 = q0; + n = nr; + if (n > RBUFSIZE) + n = RBUFSIZE; + f->elog.nr = n; + runemove(f->elog.r, r, n); + r += n; + nr -= n; + } } -void -elogdelete(File *f, int q0, int q1) -{ - if(q0 == q1) - return; - eloginit(f); - if(f->elog.type!=Null && q0elog.q0+f->elog.nd){ - if(warned++ == 0) - warning(nil, Wsequence); - elogflush(f); - } - /* try to merge with previous */ - if(f->elog.type==Delete && f->elog.q0+f->elog.nd==q0){ - f->elog.nd += q1-q0; - return; - } - elogflush(f); - f->elog.type = Delete; - f->elog.q0 = q0; - f->elog.nd = q1-q0; +void elogdelete(File* f, int q0, int q1) { + if (q0 == q1) + return; + eloginit(f); + if (f->elog.type != Null && q0 < f->elog.q0 + f->elog.nd) { + if (warned++ == 0) + warning(nil, Wsequence); + elogflush(f); + } + /* try to merge with previous */ + if (f->elog.type == Delete && f->elog.q0 + f->elog.nd == q0) { + f->elog.nd += q1 - q0; + return; + } + elogflush(f); + f->elog.type = Delete; + f->elog.q0 = q0; + f->elog.nd = q1 - q0; } #define tracelog 0 -void -elogapply(File *f) -{ - Buflog b; - Rune *buf; - uint i, n, up, mod; - uint tq0, tq1; - Buffer *log; - Text *t; - int owner; +void elogapply(File* f) { + Buflog b; + Rune* buf; + uint i, n, up, mod; + uint tq0, tq1; + Buffer* log; + Text* t; + int owner; - elogflush(f); - log = f->elogbuf; - t = f->curtext; + elogflush(f); + log = f->elogbuf; + t = f->curtext; - buf = fbufalloc(); - mod = FALSE; + buf = fbufalloc(); + mod = FALSE; - owner = 0; - if(t->w){ - owner = t->w->owner; - if(owner == 0) - t->w->owner = 'E'; - } + owner = 0; + if (t->w) { + owner = t->w->owner; + if (owner == 0) + t->w->owner = 'E'; + } - /* - * The edit commands have already updated the selection in t->q0, t->q1, - * but using coordinates relative to the unmodified buffer. As we apply the log, - * we have to update the coordinates to be relative to the modified buffer. - * Textinsert and textdelete will do this for us; our only work is to apply the - * convention that an insertion at t->q0==t->q1 is intended to select the - * inserted text. - */ + /* + * The edit commands have already updated the selection in t->q0, t->q1, + * but using coordinates relative to the unmodified buffer. As we apply the + * log, we have to update the coordinates to be relative to the modified + * buffer. Textinsert and textdelete will do this for us; our only work is to + * apply the convention that an insertion at t->q0==t->q1 is intended to + * select the inserted text. + */ - /* - * We constrain the addresses in here (with textconstrain()) because - * overlapping changes will generate bogus addresses. We will warn - * about changes out of sequence but proceed anyway; here we must - * keep things in range. - */ + /* + * We constrain the addresses in here (with textconstrain()) because + * overlapping changes will generate bogus addresses. We will warn + * about changes out of sequence but proceed anyway; here we must + * keep things in range. + */ - while(log->nc > 0){ - up = log->nc-Buflogsize; - bufread(log, up, (Rune*)&b, Buflogsize); - switch(b.type){ - default: - fprint(2, "elogapply: 0x%ux\n", b.type); - abort(); - break; + while (log->nc > 0) { + up = log->nc - Buflogsize; + bufread(log, up, (Rune*)&b, Buflogsize); + switch (b.type) { + default: + fprint(2, "elogapply: 0x%ux\n", b.type); + abort(); + break; - case Replace: - if(tracelog) - warning(nil, "elog replace %d %d (%d %d)\n", - b.q0, b.q0+b.nd, t->q0, t->q1); - if(!mod){ - mod = TRUE; - filemark(f); - } - textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1); - textdelete(t, tq0, tq1, TRUE); - up -= b.nr; - for(i=0; i RBUFSIZE) - n = RBUFSIZE; - bufread(log, up+i, buf, n); - textinsert(t, tq0+i, buf, n, TRUE); - } - if(t->q0 == b.q0 && t->q1 == b.q0) - t->q1 += b.nr; - break; + case Replace: + if (tracelog) + warning( + nil, + "elog replace %d %d (%d %d)\n", + b.q0, + b.q0 + b.nd, + t->q0, + t->q1); + if (!mod) { + mod = TRUE; + filemark(f); + } + textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1); + textdelete(t, tq0, tq1, TRUE); + up -= b.nr; + for (i = 0; i < b.nr; i += n) { + n = b.nr - i; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(log, up + i, buf, n); + textinsert(t, tq0 + i, buf, n, TRUE); + } + if (t->q0 == b.q0 && t->q1 == b.q0) + t->q1 += b.nr; + break; - case Delete: - if(tracelog) - warning(nil, "elog delete %d %d (%d %d)\n", - b.q0, b.q0+b.nd, t->q0, t->q1); - if(!mod){ - mod = TRUE; - filemark(f); - } - textconstrain(t, b.q0, b.q0+b.nd, &tq0, &tq1); - textdelete(t, tq0, tq1, TRUE); - break; + case Delete: + if (tracelog) + warning( + nil, + "elog delete %d %d (%d %d)\n", + b.q0, + b.q0 + b.nd, + t->q0, + t->q1); + if (!mod) { + mod = TRUE; + filemark(f); + } + textconstrain(t, b.q0, b.q0 + b.nd, &tq0, &tq1); + textdelete(t, tq0, tq1, TRUE); + break; - case Insert: - if(tracelog) - warning(nil, "elog insert %d %d (%d %d)\n", - b.q0, b.q0+b.nr, t->q0, t->q1); - if(!mod){ - mod = TRUE; - filemark(f); - } - textconstrain(t, b.q0, b.q0, &tq0, &tq1); - up -= b.nr; - for(i=0; i RBUFSIZE) - n = RBUFSIZE; - bufread(log, up+i, buf, n); - textinsert(t, tq0+i, buf, n, TRUE); - } - if(t->q0 == b.q0 && t->q1 == b.q0) - t->q1 += b.nr; - break; + case Insert: + if (tracelog) + warning( + nil, + "elog insert %d %d (%d %d)\n", + b.q0, + b.q0 + b.nr, + t->q0, + t->q1); + if (!mod) { + mod = TRUE; + filemark(f); + } + textconstrain(t, b.q0, b.q0, &tq0, &tq1); + up -= b.nr; + for (i = 0; i < b.nr; i += n) { + n = b.nr - i; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(log, up + i, buf, n); + textinsert(t, tq0 + i, buf, n, TRUE); + } + if (t->q0 == b.q0 && t->q1 == b.q0) + t->q1 += b.nr; + break; -/* case Filename: - f->seq = u.seq; - fileunsetname(f, epsilon); - f->mod = u.mod; - up -= u.n; - free(f->name); - if(u.n == 0) - f->name = nil; - else - f->name = runemalloc(u.n); - bufread(delta, up, f->name, u.n); - f->nname = u.n; - break; -*/ - } - bufdelete(log, up, log->nc); - } - fbuffree(buf); - elogterm(f); - - /* - * Bad addresses will cause bufload to crash, so double check. - * If changes were out of order, we expect problems so don't complain further. - */ - if(t->q0 > f->b.nc || t->q1 > f->b.nc || t->q0 > t->q1){ - if(!warned) - warning(nil, "elogapply: can't happen %d %d %d\n", t->q0, t->q1, f->b.nc); - t->q1 = min(t->q1, f->b.nc); - t->q0 = min(t->q0, t->q1); - } + /* case Filename: + f->seq = u.seq; + fileunsetname(f, epsilon); + f->mod = u.mod; + up -= u.n; + free(f->name); + if(u.n == 0) + f->name = nil; + else + f->name = runemalloc(u.n); + bufread(delta, up, f->name, u.n); + f->nname = u.n; + break; + */ + } + bufdelete(log, up, log->nc); + } + fbuffree(buf); + elogterm(f); - if(t->w) - t->w->owner = owner; + /* + * Bad addresses will cause bufload to crash, so double check. + * If changes were out of order, we expect problems so don't complain further. + */ + if (t->q0 > f->b.nc || t->q1 > f->b.nc || t->q0 > t->q1) { + if (!warned) + warning(nil, "elogapply: can't happen %d %d %d\n", t->q0, t->q1, f->b.nc); + t->q1 = min(t->q1, f->b.nc); + t->q0 = min(t->q0, t->q1); + } + + if (t->w) + t->w->owner = owner; } diff --git a/exec.c b/exec.c index 6229d36..073e7b1 100644 --- a/exec.c +++ b/exec.c @@ -14,7 +14,7 @@ #include "dat.h" #include "fns.h" -Buffer snarfbuf; +Buffer snarfbuf; /* * These functions get called as: @@ -33,1655 +33,1617 @@ Buffer snarfbuf; */ void doabort(Text*, Text*, Text*, int, int, Rune*, int); -void del(Text*, Text*, Text*, int, int, Rune*, int); -void delcol(Text*, Text*, Text*, int, int, Rune*, int); -void dotfiles(Text*, Text*, Text*, int, int, Rune*, int); -void dump(Text*, Text*, Text*, int, int, Rune*, int); -void edit(Text*, Text*, Text*, int, int, Rune*, int); -void xexit(Text*, Text*, Text*, int, int, Rune*, int); -void fontx(Text*, Text*, Text*, int, int, Rune*, int); -void get(Text*, Text*, Text*, int, int, Rune*, int); -void id(Text*, Text*, Text*, int, int, Rune*, int); -void incl(Text*, Text*, Text*, int, int, Rune*, int); -void indent(Text*, Text*, Text*, int, int, Rune*, int); -void xkill(Text*, Text*, Text*, int, int, Rune*, int); -void local(Text*, Text*, Text*, int, int, Rune*, int); -void look(Text*, Text*, Text*, int, int, Rune*, int); -void newcol(Text*, Text*, Text*, int, int, Rune*, int); -void paste(Text*, Text*, Text*, int, int, Rune*, int); -void put(Text*, Text*, Text*, int, int, Rune*, int); -void putall(Text*, Text*, Text*, int, int, Rune*, int); -void sendx(Text*, Text*, Text*, int, int, Rune*, int); -void sort(Text*, Text*, Text*, int, int, Rune*, int); -void tab(Text*, Text*, Text*, int, int, Rune*, int); -void zeroxx(Text*, Text*, Text*, int, int, Rune*, int); +void del(Text*, Text*, Text*, int, int, Rune*, int); +void delcol(Text*, Text*, Text*, int, int, Rune*, int); +void dotfiles(Text*, Text*, Text*, int, int, Rune*, int); +void dump(Text*, Text*, Text*, int, int, Rune*, int); +void edit(Text*, Text*, Text*, int, int, Rune*, int); +void xexit(Text*, Text*, Text*, int, int, Rune*, int); +void fontx(Text*, Text*, Text*, int, int, Rune*, int); +void get(Text*, Text*, Text*, int, int, Rune*, int); +void id(Text*, Text*, Text*, int, int, Rune*, int); +void incl(Text*, Text*, Text*, int, int, Rune*, int); +void indent(Text*, Text*, Text*, int, int, Rune*, int); +void xkill(Text*, Text*, Text*, int, int, Rune*, int); +void local(Text*, Text*, Text*, int, int, Rune*, int); +void look(Text*, Text*, Text*, int, int, Rune*, int); +void newcol(Text*, Text*, Text*, int, int, Rune*, int); +void paste(Text*, Text*, Text*, int, int, Rune*, int); +void put(Text*, Text*, Text*, int, int, Rune*, int); +void putall(Text*, Text*, Text*, int, int, Rune*, int); +void sendx(Text*, Text*, Text*, int, int, Rune*, int); +void sort(Text*, Text*, Text*, int, int, Rune*, int); +void tab(Text*, Text*, Text*, int, int, Rune*, int); +void zeroxx(Text*, Text*, Text*, int, int, Rune*, int); typedef struct Exectab Exectab; -struct Exectab -{ - Rune *name; - void (*fn)(Text*, Text*, Text*, int, int, Rune*, int); - int mark; - int flag1; - int flag2; +struct Exectab { + Rune* name; + void (*fn)(Text*, Text*, Text*, int, int, Rune*, int); + int mark; + int flag1; + int flag2; }; -static Rune LAbort[] = { 'A', 'b', 'o', 'r', 't', 0 }; -static Rune LCut[] = { 'C', 'u', 't', 0 }; -static Rune LDel[] = { 'D', 'e', 'l', 0 }; -static Rune LDelcol[] = { 'D', 'e', 'l', 'c', 'o', 'l', 0 }; -static Rune LDelete[] = { 'D', 'e', 'l', 'e', 't', 'e', 0 }; -static Rune LDump[] = { 'D', 'u', 'm', 'p', 0 }; -static Rune LEdit[] = { 'E', 'd', 'i', 't', 0 }; -static Rune LExit[] = { 'E', 'x', 'i', 't', 0 }; -static Rune LFont[] = { 'F', 'o', 'n', 't', 0 }; -static Rune LGet[] = { 'G', 'e', 't', 0 }; -static Rune LID[] = { 'I', 'D', 0 }; -static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 }; -static Rune LIndent[] = { 'I', 'n', 'd', 'e', 'n', 't', 0 }; -static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 }; -static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 }; -static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 }; -static Rune LLook[] = { 'L', 'o', 'o', 'k', 0 }; -static Rune LNew[] = { 'N', 'e', 'w', 0 }; -static Rune LNewcol[] = { 'N', 'e', 'w', 'c', 'o', 'l', 0 }; -static Rune LPaste[] = { 'P', 'a', 's', 't', 'e', 0 }; -static Rune LPut[] = { 'P', 'u', 't', 0 }; -static Rune LPutall[] = { 'P', 'u', 't', 'a', 'l', 'l', 0 }; -static Rune LRedo[] = { 'R', 'e', 'd', 'o', 0 }; -static Rune LSend[] = { 'S', 'e', 'n', 'd', 0 }; -static Rune LSnarf[] = { 'S', 'n', 'a', 'r', 'f', 0 }; -static Rune LSort[] = { 'S', 'o', 'r', 't', 0 }; -static Rune LSpaces[] = { 'S', 'p', 'a', 'c', 'e', 's', 0 }; -static Rune LTab[] = { 'T', 'a', 'b', 0 }; -static Rune LUndo[] = { 'U', 'n', 'd', 'o', 0 }; -static Rune LZerox[] = { 'Z', 'e', 'r', 'o', 'x', 0 }; +static Rune LAbort[] = {'A', 'b', 'o', 'r', 't', 0}; +static Rune LCut[] = {'C', 'u', 't', 0}; +static Rune LDel[] = {'D', 'e', 'l', 0}; +static Rune LDelcol[] = {'D', 'e', 'l', 'c', 'o', 'l', 0}; +static Rune LDelete[] = {'D', 'e', 'l', 'e', 't', 'e', 0}; +static Rune LDump[] = {'D', 'u', 'm', 'p', 0}; +static Rune LEdit[] = {'E', 'd', 'i', 't', 0}; +static Rune LExit[] = {'E', 'x', 'i', 't', 0}; +static Rune LFont[] = {'F', 'o', 'n', 't', 0}; +static Rune LGet[] = {'G', 'e', 't', 0}; +static Rune LID[] = {'I', 'D', 0}; +static Rune LIncl[] = {'I', 'n', 'c', 'l', 0}; +static Rune LIndent[] = {'I', 'n', 'd', 'e', 'n', 't', 0}; +static Rune LKill[] = {'K', 'i', 'l', 'l', 0}; +static Rune LLoad[] = {'L', 'o', 'a', 'd', 0}; +static Rune LLocal[] = {'L', 'o', 'c', 'a', 'l', 0}; +static Rune LLook[] = {'L', 'o', 'o', 'k', 0}; +static Rune LNew[] = {'N', 'e', 'w', 0}; +static Rune LNewcol[] = {'N', 'e', 'w', 'c', 'o', 'l', 0}; +static Rune LPaste[] = {'P', 'a', 's', 't', 'e', 0}; +static Rune LPut[] = {'P', 'u', 't', 0}; +static Rune LPutall[] = {'P', 'u', 't', 'a', 'l', 'l', 0}; +static Rune LRedo[] = {'R', 'e', 'd', 'o', 0}; +static Rune LSend[] = {'S', 'e', 'n', 'd', 0}; +static Rune LSnarf[] = {'S', 'n', 'a', 'r', 'f', 0}; +static Rune LSort[] = {'S', 'o', 'r', 't', 0}; +static Rune LSpaces[] = {'S', 'p', 'a', 'c', 'e', 's', 0}; +static Rune LTab[] = {'T', 'a', 'b', 0}; +static Rune LUndo[] = {'U', 'n', 'd', 'o', 0}; +static Rune LZerox[] = {'Z', 'e', 'r', 'o', 'x', 0}; Exectab exectab[] = { - { LAbort, doabort, FALSE, XXX, XXX, }, - { LCut, cut, TRUE, TRUE, TRUE }, - { LDel, del, FALSE, FALSE, XXX }, - { LDelcol, delcol, FALSE, XXX, XXX }, - { LDelete, del, FALSE, TRUE, XXX }, - { LDump, dump, FALSE, TRUE, XXX }, - { LEdit, edit, FALSE, XXX, XXX }, - { LExit, xexit, FALSE, XXX, XXX }, - { LFont, fontx, FALSE, XXX, XXX }, - { LGet, get, FALSE, TRUE, XXX }, - { LID, id, FALSE, XXX, XXX }, - { LIncl, incl, FALSE, XXX, XXX }, - { LIndent, indent, FALSE, AUTOINDENT, XXX }, - { LKill, xkill, FALSE, XXX, XXX }, - { LLoad, dump, FALSE, FALSE, XXX }, - { LLocal, local, FALSE, XXX, XXX }, - { LLook, look, FALSE, XXX, XXX }, - { LNew, new, FALSE, XXX, XXX }, - { LNewcol, newcol, FALSE, XXX, XXX }, - { LPaste, paste, TRUE, TRUE, XXX }, - { LPut, put, FALSE, XXX, XXX }, - { LPutall, putall, FALSE, XXX, XXX }, - { LRedo, undo, FALSE, FALSE, XXX }, - { LSend, sendx, TRUE, XXX, XXX }, - { LSnarf, cut, FALSE, TRUE, FALSE }, - { LSort, sort, FALSE, XXX, XXX }, - { LSpaces, indent, FALSE, SPACESINDENT, XXX }, - { LTab, tab, FALSE, XXX, XXX }, - { LUndo, undo, FALSE, TRUE, XXX }, - { LZerox, zeroxx, FALSE, XXX, XXX }, - { nil, 0, 0, 0, 0 } -}; + { + LAbort, + doabort, + FALSE, + XXX, + XXX, + }, + {LCut, cut, TRUE, TRUE, TRUE}, + {LDel, del, FALSE, FALSE, XXX}, + {LDelcol, delcol, FALSE, XXX, XXX}, + {LDelete, del, FALSE, TRUE, XXX}, + {LDump, dump, FALSE, TRUE, XXX}, + {LEdit, edit, FALSE, XXX, XXX}, + {LExit, xexit, FALSE, XXX, XXX}, + {LFont, fontx, FALSE, XXX, XXX}, + {LGet, get, FALSE, TRUE, XXX}, + {LID, id, FALSE, XXX, XXX}, + {LIncl, incl, FALSE, XXX, XXX}, + {LIndent, indent, FALSE, AUTOINDENT, XXX}, + {LKill, xkill, FALSE, XXX, XXX}, + {LLoad, dump, FALSE, FALSE, XXX}, + {LLocal, local, FALSE, XXX, XXX}, + {LLook, look, FALSE, XXX, XXX}, + {LNew, new, FALSE, XXX, XXX}, + {LNewcol, newcol, FALSE, XXX, XXX}, + {LPaste, paste, TRUE, TRUE, XXX}, + {LPut, put, FALSE, XXX, XXX}, + {LPutall, putall, FALSE, XXX, XXX}, + {LRedo, undo, FALSE, FALSE, XXX}, + {LSend, sendx, TRUE, XXX, XXX}, + {LSnarf, cut, FALSE, TRUE, FALSE}, + {LSort, sort, FALSE, XXX, XXX}, + {LSpaces, indent, FALSE, SPACESINDENT, XXX}, + {LTab, tab, FALSE, XXX, XXX}, + {LUndo, undo, FALSE, TRUE, XXX}, + {LZerox, zeroxx, FALSE, XXX, XXX}, + {nil, 0, 0, 0, 0}}; -Exectab* -lookup(Rune *r, int n) -{ - Exectab *e; - int nr; +Exectab* lookup(Rune* r, int n) { + Exectab* e; + int nr; - r = skipbl(r, n, &n); - if(n == 0) - return nil; - findbl(r, n, &nr); - nr = n-nr; - for(e=exectab; e->name; e++) - if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE) - return e; - return nil; + r = skipbl(r, n, &n); + if (n == 0) + return nil; + findbl(r, n, &nr); + nr = n - nr; + for (e = exectab; e->name; e++) + if (runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE) + return e; + return nil; } -int -isexecc(int c) -{ - if(isfilec(c)) - return 1; - return c=='<' || c=='|' || c=='>'; +int isexecc(int c) { + if (isfilec(c)) + return 1; + return c == '<' || c == '|' || c == '>'; } -void -execute(Text *t, uint aq0, uint aq1, int external, Text *argt) -{ - uint q0, q1; - Rune *r, *s; - char *b, *a, *aa; - Exectab *e; - int c, n, f; - Runestr dir; +void execute(Text* t, uint aq0, uint aq1, int external, Text* argt) { + uint q0, q1; + Rune *r, *s; + char *b, *a, *aa; + Exectab* e; + int c, n, f; + Runestr dir; - q0 = aq0; - q1 = aq1; - if(q1 == q0){ /* expand to find word (actually file name) */ - /* if in selection, choose selection */ - if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){ - q0 = t->q0; - q1 = t->q1; - }else{ - while(q1file->b.nc && isexecc(c=textreadc(t, q1)) && c!=':') - q1++; - while(q0>0 && isexecc(c=textreadc(t, q0-1)) && c!=':') - q0--; - if(q1 == q0) - return; - } - } - r = runemalloc(q1-q0); - bufread(&t->file->b, q0, r, q1-q0); - e = lookup(r, q1-q0); - if(!external && t->w!=nil && t->w->nopen[QWevent]>0){ - f = 0; - if(e) - f |= 1; - if(q0!=aq0 || q1!=aq1){ - bufread(&t->file->b, aq0, r, aq1-aq0); - f |= 2; - } - aa = getbytearg(argt, TRUE, TRUE, &a); - if(a){ - if(strlen(a) > EVENTSIZE){ /* too big; too bad */ - free(r); - free(aa); - free(a); - warning(nil, "argument string too long\n"); - return; - } - f |= 8; - } - c = 'x'; - if(t->what == Body) - c = 'X'; - n = aq1-aq0; - if(n <= EVENTSIZE) - winevent(t->w, "%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r); - else - winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f, n); - if(q0!=aq0 || q1!=aq1){ - n = q1-q0; - bufread(&t->file->b, q0, r, n); - if(n <= EVENTSIZE) - winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r); - else - winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1, n); - } - if(a){ - winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(a), a); - if(aa) - winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(aa), aa); - else - winevent(t->w, "%c0 0 0 0 \n", c); - } - free(r); - free(aa); - free(a); - return; - } - if(e){ - if(e->mark && seltext!=nil) - if(seltext->what == Body){ - seq++; - filemark(seltext->w->body.file); - } - s = skipbl(r, q1-q0, &n); - s = findbl(s, n, &n); - s = skipbl(s, n, &n); - (*e->fn)(t, seltext, argt, e->flag1, e->flag2, s, n); - free(r); - return; - } + q0 = aq0; + q1 = aq1; + if (q1 == q0) { /* expand to find word (actually file name) */ + /* if in selection, choose selection */ + if (t->q1 > t->q0 && t->q0 <= q0 && q0 <= t->q1) { + q0 = t->q0; + q1 = t->q1; + } else { + while (q1 < t->file->b.nc && isexecc(c = textreadc(t, q1)) && c != ':') + q1++; + while (q0 > 0 && isexecc(c = textreadc(t, q0 - 1)) && c != ':') + q0--; + if (q1 == q0) + return; + } + } + r = runemalloc(q1 - q0); + bufread(&t->file->b, q0, r, q1 - q0); + e = lookup(r, q1 - q0); + if (!external && t->w != nil && t->w->nopen[QWevent] > 0) { + f = 0; + if (e) + f |= 1; + if (q0 != aq0 || q1 != aq1) { + bufread(&t->file->b, aq0, r, aq1 - aq0); + f |= 2; + } + aa = getbytearg(argt, TRUE, TRUE, &a); + if (a) { + if (strlen(a) > EVENTSIZE) { /* too big; too bad */ + free(r); + free(aa); + free(a); + warning(nil, "argument string too long\n"); + return; + } + f |= 8; + } + c = 'x'; + if (t->what == Body) + c = 'X'; + n = aq1 - aq0; + if (n <= EVENTSIZE) + winevent(t->w, "%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r); + else + winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f, n); + if (q0 != aq0 || q1 != aq1) { + n = q1 - q0; + bufread(&t->file->b, q0, r, n); + if (n <= EVENTSIZE) + winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r); + else + winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1, n); + } + if (a) { + winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(a), a); + if (aa) + winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(aa), aa); + else + winevent(t->w, "%c0 0 0 0 \n", c); + } + free(r); + free(aa); + free(a); + return; + } + if (e) { + if (e->mark && seltext != nil) + if (seltext->what == Body) { + seq++; + filemark(seltext->w->body.file); + } + s = skipbl(r, q1 - q0, &n); + s = findbl(s, n, &n); + s = skipbl(s, n, &n); + (*e->fn)(t, seltext, argt, e->flag1, e->flag2, s, n); + free(r); + return; + } - b = runetobyte(r, q1-q0); - free(r); - dir = dirname(t, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - aa = getbytearg(argt, TRUE, TRUE, &a); - if(t->w) - incref(&t->w->ref); - run(t->w, b, dir.r, dir.nr, TRUE, aa, a, FALSE); + b = runetobyte(r, q1 - q0); + free(r); + dir = dirname(t, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + aa = getbytearg(argt, TRUE, TRUE, &a); + if (t->w) + incref(&t->w->ref); + run(t->w, b, dir.r, dir.nr, TRUE, aa, a, FALSE); } -char* -printarg(Text *argt, uint q0, uint q1) -{ - char *buf; +char* printarg(Text* argt, uint q0, uint q1) { + char* buf; - if(argt->what!=Body || argt->file->name==nil) - return nil; - buf = emalloc(argt->file->nname+32); - if(q0 == q1) - sprint(buf, "%.*S:#%d", argt->file->nname, argt->file->name, q0); - else - sprint(buf, "%.*S:#%d,#%d", argt->file->nname, argt->file->name, q0, q1); - return buf; + if (argt->what != Body || argt->file->name == nil) + return nil; + buf = emalloc(argt->file->nname + 32); + if (q0 == q1) + sprint(buf, "%.*S:#%d", argt->file->nname, argt->file->name, q0); + else + sprint(buf, "%.*S:#%d,#%d", argt->file->nname, argt->file->name, q0, q1); + return buf; } -char* -getarg(Text *argt, int doaddr, int dofile, Rune **rp, int *nrp) -{ - int n; - Expand e; - char *a; +char* getarg(Text* argt, int doaddr, int dofile, Rune** rp, int* nrp) { + int n; + Expand e; + char* a; - *rp = nil; - *nrp = 0; - if(argt == nil) - return nil; - a = nil; - textcommit(argt, TRUE); - if(expand(argt, argt->q0, argt->q1, &e)){ - free(e.bname); - if(e.nname && dofile){ - e.name = runerealloc(e.name, e.nname+1); - if(doaddr) - a = printarg(argt, e.q0, e.q1); - *rp = e.name; - *nrp = e.nname; - return a; - } - free(e.name); - }else{ - e.q0 = argt->q0; - e.q1 = argt->q1; - } - n = e.q1 - e.q0; - *rp = runemalloc(n+1); - bufread(&argt->file->b, e.q0, *rp, n); - if(doaddr) - a = printarg(argt, e.q0, e.q1); - *nrp = n; - return a; + *rp = nil; + *nrp = 0; + if (argt == nil) + return nil; + a = nil; + textcommit(argt, TRUE); + if (expand(argt, argt->q0, argt->q1, &e)) { + free(e.bname); + if (e.nname && dofile) { + e.name = runerealloc(e.name, e.nname + 1); + if (doaddr) + a = printarg(argt, e.q0, e.q1); + *rp = e.name; + *nrp = e.nname; + return a; + } + free(e.name); + } else { + e.q0 = argt->q0; + e.q1 = argt->q1; + } + n = e.q1 - e.q0; + *rp = runemalloc(n + 1); + bufread(&argt->file->b, e.q0, *rp, n); + if (doaddr) + a = printarg(argt, e.q0, e.q1); + *nrp = n; + return a; } -char* -getbytearg(Text *argt, int doaddr, int dofile, char **bp) -{ - Rune *r; - int n; - char *aa; +char* getbytearg(Text* argt, int doaddr, int dofile, char** bp) { + Rune* r; + int n; + char* aa; - *bp = nil; - aa = getarg(argt, doaddr, dofile, &r, &n); - if(r == nil) - return nil; - *bp = runetobyte(r, n); - free(r); - return aa; + *bp = nil; + aa = getarg(argt, doaddr, dofile, &r, &n); + if (r == nil) + return nil; + *bp = runetobyte(r, n); + free(r); + return aa; } -void -doabort(Text *__0, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - static int n; +void doabort(Text* __0, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + static int n; - USED(__0); - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); + USED(__0); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - if(n++ == 0) - warning(nil, "executing Abort again will call abort()\n"); - else - abort(); + if (n++ == 0) + warning(nil, "executing Abort again will call abort()\n"); + else + abort(); } -void -newcol(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - Column *c; - Window *w; +void newcol(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + Column* c; + Window* w; - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - c = rowadd(et->row, nil, -1); - if(c) { - w = coladd(c, nil, nil, -1); - winsettag(w); - xfidlog(w, "new"); - } + c = rowadd(et->row, nil, -1); + if (c) { + w = coladd(c, nil, nil, -1); + winsettag(w); + xfidlog(w, "new"); + } } -void -delcol(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - int i; - Column *c; - Window *w; +void delcol(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + int i; + Column* c; + Window* w; - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - c = et->col; - if(c==nil || colclean(c)==0) - return; - for(i=0; inw; i++){ - w = c->w[i]; - if(w->nopen[QWevent]+w->nopen[QWaddr]+w->nopen[QWdata]+w->nopen[QWxdata] > 0){ - warning(nil, "can't delete column; %.*S is running an external command\n", w->body.file->nname, w->body.file->name); - return; - } - } - rowclose(et->col->row, et->col, TRUE); + c = et->col; + if (c == nil || colclean(c) == 0) + return; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + if ( + w->nopen[QWevent] + w->nopen[QWaddr] + w->nopen[QWdata] + + w->nopen[QWxdata] > + 0) { + warning( + nil, + "can't delete column; %.*S is running an external command\n", + w->body.file->nname, + w->body.file->name); + return; + } + } + rowclose(et->col->row, et->col, TRUE); } -void -del(Text *et, Text *_0, Text *_1, int flag1, int _2, Rune *_3, int _4) -{ - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); +void del(Text* et, Text* _0, Text* _1, int flag1, int _2, Rune* _3, int _4) { + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); - if(et->col==nil || et->w == nil) - return; - if(flag1 || et->w->body.file->ntext>1 || winclean(et->w, FALSE)) - colclose(et->col, et->w, TRUE); + if (et->col == nil || et->w == nil) + return; + if (flag1 || et->w->body.file->ntext > 1 || winclean(et->w, FALSE)) + colclose(et->col, et->w, TRUE); } -void -sort(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); +void sort(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - if(et->col) - colsort(et->col); + if (et->col) + colsort(et->col); } -uint -seqof(Window *w, int isundo) -{ - /* if it's undo, see who changed with us */ - if(isundo) - return w->body.file->seq; - /* if it's redo, see who we'll be sync'ed up with */ - return fileredoseq(w->body.file); +uint seqof(Window* w, int isundo) { + /* if it's undo, see who changed with us */ + if (isundo) + return w->body.file->seq; + /* if it's redo, see who we'll be sync'ed up with */ + return fileredoseq(w->body.file); } -void -undo(Text *et, Text *_0, Text *_1, int flag1, int _2, Rune *_3, int _4) -{ - int i, j; - Column *c; - Window *w; - uint seq; +void undo(Text* et, Text* _0, Text* _1, int flag1, int _2, Rune* _3, int _4) { + int i, j; + Column* c; + Window* w; + uint seq; - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); - if(et==nil || et->w== nil) - return; - seq = seqof(et->w, flag1); - if(seq == 0){ - /* nothing to undo */ - return; - } - /* - * Undo the executing window first. Its display will update. other windows - * in the same file will not call show() and jump to a different location in the file. - * Simultaneous changes to other files will be chaotic, however. - */ - winundo(et->w, flag1); - for(i=0; inw; j++){ - w = c->w[j]; - if(w == et->w) - continue; - if(seqof(w, flag1) == seq) - winundo(w, flag1); - } - } + if (et == nil || et->w == nil) + return; + seq = seqof(et->w, flag1); + if (seq == 0) { + /* nothing to undo */ + return; + } + /* + * Undo the executing window first. Its display will update. other windows + * in the same file will not call show() and jump to a different location in + * the file. Simultaneous changes to other files will be chaotic, however. + */ + winundo(et->w, flag1); + for (i = 0; i < row.ncol; i++) { + c = row.col[i]; + for (j = 0; j < c->nw; j++) { + w = c->w[j]; + if (w == et->w) + continue; + if (seqof(w, flag1) == seq) + winundo(w, flag1); + } + } } -char* -getname(Text *t, Text *argt, Rune *arg, int narg, int isput) -{ - char *s; - Rune *r; - int i, n, promote; - Runestr dir; +char* getname(Text* t, Text* argt, Rune* arg, int narg, int isput) { + char* s; + Rune* r; + int i, n, promote; + Runestr dir; - getarg(argt, FALSE, TRUE, &r, &n); - promote = FALSE; - if(r == nil) - promote = TRUE; - else if(isput){ - /* if are doing a Put, want to synthesize name even for non-existent file */ - /* best guess is that file name doesn't contain a slash */ - promote = TRUE; - for(i=0; ifile->name, t->file->nname); - return s; - } - /* prefix with directory name if necessary */ - dir.r = nil; - dir.nr = 0; - if(n>0 && arg[0]!='/'){ - dir = dirname(t, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - } - if(dir.r){ - r = runemalloc(dir.nr+n+1); - runemove(r, dir.r, dir.nr); - free(dir.r); - if(dir.nr>0 && r[dir.nr]!='/' && n>0 && arg[0]!='/') - r[dir.nr++] = '/'; - runemove(r+dir.nr, arg, n); - n += dir.nr; - }else{ - r = runemalloc(n+1); - runemove(r, arg, n); - } - } - s = runetobyte(r, n); - free(r); - if(strlen(s) == 0){ - free(s); - s = nil; - } - return s; + getarg(argt, FALSE, TRUE, &r, &n); + promote = FALSE; + if (r == nil) + promote = TRUE; + else if (isput) { + /* if are doing a Put, want to synthesize name even for non-existent file */ + /* best guess is that file name doesn't contain a slash */ + promote = TRUE; + for (i = 0; i < n; i++) + if (r[i] == '/') { + promote = FALSE; + break; + } + if (promote) { + t = argt; + arg = r; + narg = n; + } + } + if (promote) { + n = narg; + if (n <= 0) { + s = runetobyte(t->file->name, t->file->nname); + return s; + } + /* prefix with directory name if necessary */ + dir.r = nil; + dir.nr = 0; + if (n > 0 && arg[0] != '/') { + dir = dirname(t, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + } + if (dir.r) { + r = runemalloc(dir.nr + n + 1); + runemove(r, dir.r, dir.nr); + free(dir.r); + if (dir.nr > 0 && r[dir.nr] != '/' && n > 0 && arg[0] != '/') + r[dir.nr++] = '/'; + runemove(r + dir.nr, arg, n); + n += dir.nr; + } else { + r = runemalloc(n + 1); + runemove(r, arg, n); + } + } + s = runetobyte(r, n); + free(r); + if (strlen(s) == 0) { + free(s); + s = nil; + } + return s; } -void -zeroxx(Text *et, Text *t, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - Window *nw; - int c, locked; +void zeroxx(Text* et, Text* t, Text* _1, int _2, int _3, Rune* _4, int _5) { + Window* nw; + int c, locked; - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - locked = FALSE; - if(t!=nil && t->w!=nil && t->w!=et->w){ - locked = TRUE; - c = 'M'; - if(et->w) - c = et->w->owner; - winlock(t->w, c); - } - if(t == nil) - t = et; - if(t==nil || t->w==nil) - return; - t = &t->w->body; - if(t->w->isdir) - warning(nil, "%.*S is a directory; Zerox illegal\n", t->file->nname, t->file->name); - else{ - nw = coladd(t->w->col, nil, t->w, -1); - /* ugly: fix locks so w->unlock works */ - winlock1(nw, t->w->owner); - xfidlog(nw, "zerox"); - } - if(locked) - winunlock(t->w); + locked = FALSE; + if (t != nil && t->w != nil && t->w != et->w) { + locked = TRUE; + c = 'M'; + if (et->w) + c = et->w->owner; + winlock(t->w, c); + } + if (t == nil) + t = et; + if (t == nil || t->w == nil) + return; + t = &t->w->body; + if (t->w->isdir) + warning( + nil, + "%.*S is a directory; Zerox illegal\n", + t->file->nname, + t->file->name); + else { + nw = coladd(t->w->col, nil, t->w, -1); + /* ugly: fix locks so w->unlock works */ + winlock1(nw, t->w->owner); + xfidlog(nw, "zerox"); + } + if (locked) + winunlock(t->w); } typedef struct TextAddr TextAddr; struct TextAddr { - long lorigin; // line+rune for origin - long rorigin; - long lq0; // line+rune for q0 - long rq0; - long lq1; // line+rune for q1 - long rq1; + long lorigin; // line+rune for origin + long rorigin; + long lq0; // line+rune for q0 + long rq0; + long lq1; // line+rune for q1 + long rq1; }; -void -get(Text *et, Text *t, Text *argt, int flag1, int _0, Rune *arg, int narg) -{ - char *name; - Rune *r; - int i, n, dirty, samename, isdir; - TextAddr *addr, *a; - Window *w; - Text *u; - Dir *d; - long q0, q1; +void get( + Text* et, Text* t, Text* argt, int flag1, int _0, Rune* arg, int narg) { + char* name; + Rune* r; + int i, n, dirty, samename, isdir; + TextAddr *addr, *a; + Window* w; + Text* u; + Dir* d; + long q0, q1; - USED(_0); + USED(_0); - if(flag1) - if(et==nil || et->w==nil) - return; - if(!et->w->isdir && (et->w->body.file->b.nc>0 && !winclean(et->w, TRUE))) - return; - w = et->w; - t = &w->body; - name = getname(t, argt, arg, narg, FALSE); - if(name == nil){ - warning(nil, "no file name\n"); - return; - } - if(t->file->ntext>1){ - d = dirstat(name); - isdir = (d!=nil && (d->qid.type & QTDIR)); - free(d); - if(isdir){ - warning(nil, "%s is a directory; can't read with multiple windows on it\n", name); - return; - } - } - addr = emalloc((t->file->ntext)*sizeof(TextAddr)); - for(i=0; ifile->ntext; i++) { - a = &addr[i]; - u = t->file->text[i]; - a->lorigin = nlcount(u, 0, u->org, &a->rorigin); - a->lq0 = nlcount(u, 0, u->q0, &a->rq0); - a->lq1 = nlcount(u, u->q0, u->q1, &a->rq1); - } - r = bytetorune(name, &n); - for(i=0; ifile->ntext; i++){ - u = t->file->text[i]; - /* second and subsequent calls with zero an already empty buffer, but OK */ - textreset(u); - windirfree(u->w); - } - samename = runeeq(r, n, t->file->name, t->file->nname); - textload(t, 0, name, samename); - if(samename){ - t->file->mod = FALSE; - dirty = FALSE; - }else{ - t->file->mod = TRUE; - dirty = TRUE; - } - for(i=0; ifile->ntext; i++) - t->file->text[i]->w->dirty = dirty; - free(name); - free(r); - winsettag(w); - t->file->unread = FALSE; - for(i=0; ifile->ntext; i++){ - u = t->file->text[i]; - textsetselect(&u->w->tag, u->w->tag.file->b.nc, u->w->tag.file->b.nc); - if(samename) { - a = &addr[i]; - // warning(nil, "%d %d %d %d %d %d\n", a->lorigin, a->rorigin, a->lq0, a->rq0, a->lq1, a->rq1); - q0 = nlcounttopos(u, 0, a->lq0, a->rq0); - q1 = nlcounttopos(u, q0, a->lq1, a->rq1); - textsetselect(u, q0, q1); - q0 = nlcounttopos(u, 0, a->lorigin, a->rorigin); - textsetorigin(u, q0, FALSE); - } - textscrdraw(u); - } - free(addr); - xfidlog(w, "get"); + if (flag1) + if (et == nil || et->w == nil) + return; + if (!et->w->isdir && (et->w->body.file->b.nc > 0 && !winclean(et->w, TRUE))) + return; + w = et->w; + t = &w->body; + name = getname(t, argt, arg, narg, FALSE); + if (name == nil) { + warning(nil, "no file name\n"); + return; + } + if (t->file->ntext > 1) { + d = dirstat(name); + isdir = (d != nil && (d->qid.type & QTDIR)); + free(d); + if (isdir) { + warning( + nil, + "%s is a directory; can't read with multiple windows on it\n", + name); + return; + } + } + addr = emalloc((t->file->ntext) * sizeof(TextAddr)); + for (i = 0; i < t->file->ntext; i++) { + a = &addr[i]; + u = t->file->text[i]; + a->lorigin = nlcount(u, 0, u->org, &a->rorigin); + a->lq0 = nlcount(u, 0, u->q0, &a->rq0); + a->lq1 = nlcount(u, u->q0, u->q1, &a->rq1); + } + r = bytetorune(name, &n); + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + /* second and subsequent calls with zero an already empty buffer, but OK */ + textreset(u); + windirfree(u->w); + } + samename = runeeq(r, n, t->file->name, t->file->nname); + textload(t, 0, name, samename); + if (samename) { + t->file->mod = FALSE; + dirty = FALSE; + } else { + t->file->mod = TRUE; + dirty = TRUE; + } + for (i = 0; i < t->file->ntext; i++) + t->file->text[i]->w->dirty = dirty; + free(name); + free(r); + winsettag(w); + t->file->unread = FALSE; + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + textsetselect(&u->w->tag, u->w->tag.file->b.nc, u->w->tag.file->b.nc); + if (samename) { + a = &addr[i]; + // warning(nil, "%d %d %d %d %d %d\n", a->lorigin, a->rorigin, a->lq0, + // a->rq0, a->lq1, a->rq1); + q0 = nlcounttopos(u, 0, a->lq0, a->rq0); + q1 = nlcounttopos(u, q0, a->lq1, a->rq1); + textsetselect(u, q0, q1); + q0 = nlcounttopos(u, 0, a->lorigin, a->rorigin); + textsetorigin(u, q0, FALSE); + } + textscrdraw(u); + } + free(addr); + xfidlog(w, "get"); } -static void -checksha1(char *name, File *f, Dir *d) -{ - int fd, n; - DigestState *h; - uchar out[20]; - uchar *buf; +static void checksha1(char* name, File* f, Dir* d) { + int fd, n; + DigestState* h; + uchar out[20]; + uchar* buf; - fd = open(name, OREAD); - if(fd < 0) - return; - h = sha1(nil, 0, nil, nil); - buf = emalloc(8192); - while((n = read(fd, buf, 8192)) > 0) - sha1(buf, n, nil, h); - free(buf); - close(fd); - sha1(nil, 0, out, h); - if(memcmp(out, f->sha1, sizeof out) == 0) { - f->dev = d->dev; - f->qidpath = d->qid.path; - f->mtime = d->mtime; - } + fd = open(name, OREAD); + if (fd < 0) + return; + h = sha1(nil, 0, nil, nil); + buf = emalloc(8192); + while ((n = read(fd, buf, 8192)) > 0) + sha1(buf, n, nil, h); + free(buf); + close(fd); + sha1(nil, 0, out, h); + if (memcmp(out, f->sha1, sizeof out) == 0) { + f->dev = d->dev; + f->qidpath = d->qid.path; + f->mtime = d->mtime; + } } -void -putfile(File *f, int q0, int q1, Rune *namer, int nname) -{ - uint n, m; - Rune *r; - Biobuf *b; - char *s, *name; - int i, fd, q; - Dir *d, *d1; - Window *w; - int isapp; - DigestState *h; +void putfile(File* f, int q0, int q1, Rune* namer, int nname) { + uint n, m; + Rune* r; + Biobuf* b; + char *s, *name; + int i, fd, q; + Dir *d, *d1; + Window* w; + int isapp; + DigestState* h; - w = f->curtext->w; - name = runetobyte(namer, nname); - d = dirstat(name); - if(d!=nil && runeeq(namer, nname, f->name, f->nname)){ - if(f->dev!=d->dev || f->qidpath!=d->qid.path || f->mtime != d->mtime) - checksha1(name, f, d); - if(f->dev!=d->dev || f->qidpath!=d->qid.path || f->mtime != d->mtime) { - if(f->unread) - warning(nil, "%s not written; file already exists\n", name); - else - warning(nil, "%s modified%s%s since last read\n\twas %t; now %t\n", name, d->muid[0]?" by ":"", d->muid, f->mtime, d->mtime); - f->dev = d->dev; - f->qidpath = d->qid.path; - f->mtime = d->mtime; - goto Rescue1; - } - } + w = f->curtext->w; + name = runetobyte(namer, nname); + d = dirstat(name); + if (d != nil && runeeq(namer, nname, f->name, f->nname)) { + if (f->dev != d->dev || f->qidpath != d->qid.path || f->mtime != d->mtime) + checksha1(name, f, d); + if (f->dev != d->dev || f->qidpath != d->qid.path || f->mtime != d->mtime) { + if (f->unread) + warning(nil, "%s not written; file already exists\n", name); + else + warning( + nil, + "%s modified%s%s since last read\n\twas %t; now %t\n", + name, + d->muid[0] ? " by " : "", + d->muid, + f->mtime, + d->mtime); + f->dev = d->dev; + f->qidpath = d->qid.path; + f->mtime = d->mtime; + goto Rescue1; + } + } - fd = create(name, OWRITE, 0666); - if(fd < 0){ - warning(nil, "can't create file %s: %r\n", name); - goto Rescue1; - } - // Use bio in order to force the writes to be large and - // block-aligned (bio's default is 8K). This is not strictly - // necessary; it works around some buggy underlying - // file systems that mishandle unaligned writes. - // https://codereview.appspot.com/89550043/ - b = emalloc(sizeof *b); - Binit(b, fd, OWRITE); - r = fbufalloc(); - s = fbufalloc(); - free(d); - d = dirfstat(fd); - h = sha1(nil, 0, nil, nil); - isapp = (d!=nil && d->length>0 && (d->qid.type&QTAPPEND)); - if(isapp){ - warning(nil, "%s not written; file is append only\n", name); - goto Rescue2; - } + fd = create(name, OWRITE, 0666); + if (fd < 0) { + warning(nil, "can't create file %s: %r\n", name); + goto Rescue1; + } + // Use bio in order to force the writes to be large and + // block-aligned (bio's default is 8K). This is not strictly + // necessary; it works around some buggy underlying + // file systems that mishandle unaligned writes. + // https://codereview.appspot.com/89550043/ + b = emalloc(sizeof *b); + Binit(b, fd, OWRITE); + r = fbufalloc(); + s = fbufalloc(); + free(d); + d = dirfstat(fd); + h = sha1(nil, 0, nil, nil); + isapp = (d != nil && d->length > 0 && (d->qid.type & QTAPPEND)); + if (isapp) { + warning(nil, "%s not written; file is append only\n", name); + goto Rescue2; + } - for(q=q0; q BUFSIZE/UTFmax) - n = BUFSIZE/UTFmax; - bufread(&f->b, q, r, n); - m = snprint(s, BUFSIZE+1, "%.*S", n, r); - sha1((uchar*)s, m, nil, h); - if(Bwrite(b, s, m) != m){ - warning(nil, "can't write file %s: %r\n", name); - goto Rescue2; - } - } - if(Bflush(b) < 0) { - warning(nil, "can't write file %s: %r\n", name); - goto Rescue2; - } - Bterm(b); - free(b); - b = nil; - if(runeeq(namer, nname, f->name, f->nname)){ - if(q0!=0 || q1!=f->b.nc){ - f->mod = TRUE; - w->dirty = TRUE; - f->unread = TRUE; - }else{ - // In case the file is on NFS, reopen the fd - // before dirfstat to cause the attribute cache - // to be updated (otherwise the mtime in the - // dirfstat below will be stale and not match - // what NFS sees). The file is already written, - // so this should be a no-op when not on NFS. - // Opening for OWRITE (but no truncation) - // in case we don't have read permission. - // (The create above worked, so we probably - // still have write permission.) - close(fd); - fd = open(name, OWRITE); + for (q = q0; q < q1; q += n) { + n = q1 - q; + if (n > BUFSIZE / UTFmax) + n = BUFSIZE / UTFmax; + bufread(&f->b, q, r, n); + m = snprint(s, BUFSIZE + 1, "%.*S", n, r); + sha1((uchar*)s, m, nil, h); + if (Bwrite(b, s, m) != m) { + warning(nil, "can't write file %s: %r\n", name); + goto Rescue2; + } + } + if (Bflush(b) < 0) { + warning(nil, "can't write file %s: %r\n", name); + goto Rescue2; + } + Bterm(b); + free(b); + b = nil; + if (runeeq(namer, nname, f->name, f->nname)) { + if (q0 != 0 || q1 != f->b.nc) { + f->mod = TRUE; + w->dirty = TRUE; + f->unread = TRUE; + } else { + // In case the file is on NFS, reopen the fd + // before dirfstat to cause the attribute cache + // to be updated (otherwise the mtime in the + // dirfstat below will be stale and not match + // what NFS sees). The file is already written, + // so this should be a no-op when not on NFS. + // Opening for OWRITE (but no truncation) + // in case we don't have read permission. + // (The create above worked, so we probably + // still have write permission.) + close(fd); + fd = open(name, OWRITE); - d1 = dirfstat(fd); - if(d1 != nil){ - free(d); - d = d1; - } - f->qidpath = d->qid.path; - f->dev = d->dev; - f->mtime = d->mtime; - sha1(nil, 0, f->sha1, h); - h = nil; - f->mod = FALSE; - w->dirty = FALSE; - f->unread = FALSE; - } - for(i=0; intext; i++){ - f->text[i]->w->putseq = f->seq; - f->text[i]->w->dirty = w->dirty; - } - } - fbuffree(s); - fbuffree(r); - free(h); - free(d); - free(namer); - free(name); - close(fd); - winsettag(w); - return; + d1 = dirfstat(fd); + if (d1 != nil) { + free(d); + d = d1; + } + f->qidpath = d->qid.path; + f->dev = d->dev; + f->mtime = d->mtime; + sha1(nil, 0, f->sha1, h); + h = nil; + f->mod = FALSE; + w->dirty = FALSE; + f->unread = FALSE; + } + for (i = 0; i < f->ntext; i++) { + f->text[i]->w->putseq = f->seq; + f->text[i]->w->dirty = w->dirty; + } + } + fbuffree(s); + fbuffree(r); + free(h); + free(d); + free(namer); + free(name); + close(fd); + winsettag(w); + return; - Rescue2: - if(b != nil) { - Bterm(b); - free(b); - } - free(h); - fbuffree(s); - fbuffree(r); - close(fd); - /* fall through */ +Rescue2: + if (b != nil) { + Bterm(b); + free(b); + } + free(h); + fbuffree(s); + fbuffree(r); + close(fd); + /* fall through */ - Rescue1: - free(d); - free(namer); - free(name); +Rescue1: + free(d); + free(namer); + free(name); } -static void -trimspaces(Text *et) -{ - File *f; - Rune *r; - Text *t; - uint q0, n, delstart; - int c, i, marked; +static void trimspaces(Text* et) { + File* f; + Rune* r; + Text* t; + uint q0, n, delstart; + int c, i, marked; - t = &et->w->body; - f = t->file; - marked = 0; + t = &et->w->body; + f = t->file; + marked = 0; - if(t->w!=nil && et->w!=t->w){ - /* can this happen when t == &et->w->body? */ - c = 'M'; - if(et->w) - c = et->w->owner; - winlock(t->w, c); - } + if (t->w != nil && et->w != t->w) { + /* can this happen when t == &et->w->body? */ + c = 'M'; + if (et->w) + c = et->w->owner; + winlock(t->w, c); + } - r = fbufalloc(); - q0 = f->b.nc; - delstart = q0; /* end of current space run, or 0 if no active run; = q0 to delete spaces before EOF */ - while(q0 > 0) { - n = RBUFSIZE; - if(n > q0) - n = q0; - q0 -= n; - bufread(&f->b, q0, r, n); - for(i=n; ; i--) { - if(i == 0 || (r[i-1] != ' ' && r[i-1] != '\t')) { - // Found non-space or start of buffer. Delete active space run. - if(q0+i < delstart) { - if(!marked) { - marked = 1; - seq++; - filemark(f); - } - textdelete(t, q0+i, delstart, TRUE); - } - if(i == 0) { - /* keep run active into tail of next buffer */ - if(delstart > 0) - delstart = q0; - break; - } - delstart = 0; - if(r[i-1] == '\n') - delstart = q0+i-1; /* delete spaces before this newline */ - } - } - } - fbuffree(r); + r = fbufalloc(); + q0 = f->b.nc; + delstart = q0; /* end of current space run, or 0 if no active run; = q0 to + delete spaces before EOF */ + while (q0 > 0) { + n = RBUFSIZE; + if (n > q0) + n = q0; + q0 -= n; + bufread(&f->b, q0, r, n); + for (i = n;; i--) { + if (i == 0 || (r[i - 1] != ' ' && r[i - 1] != '\t')) { + // Found non-space or start of buffer. Delete active space run. + if (q0 + i < delstart) { + if (!marked) { + marked = 1; + seq++; + filemark(f); + } + textdelete(t, q0 + i, delstart, TRUE); + } + if (i == 0) { + /* keep run active into tail of next buffer */ + if (delstart > 0) + delstart = q0; + break; + } + delstart = 0; + if (r[i - 1] == '\n') + delstart = q0 + i - 1; /* delete spaces before this newline */ + } + } + } + fbuffree(r); - if(t->w!=nil && et->w!=t->w) - winunlock(t->w); + if (t->w != nil && et->w != t->w) + winunlock(t->w); } -void -put(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) -{ - int nname; - Rune *namer; - Window *w; - File *f; - char *name; +void put(Text* et, Text* _0, Text* argt, int _1, int _2, Rune* arg, int narg) { + int nname; + Rune* namer; + Window* w; + File* f; + char* name; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - if(et==nil || et->w==nil || et->w->isdir) - return; - w = et->w; - f = w->body.file; - name = getname(&w->body, argt, arg, narg, TRUE); - if(name == nil){ - warning(nil, "no file name\n"); - return; - } - if(w->indent[NINDENT]) - trimspaces(et); - namer = bytetorune(name, &nname); - putfile(f, 0, f->b.nc, namer, nname); - xfidlog(w, "put"); - free(name); + if (et == nil || et->w == nil || et->w->isdir) + return; + w = et->w; + f = w->body.file; + name = getname(&w->body, argt, arg, narg, TRUE); + if (name == nil) { + warning(nil, "no file name\n"); + return; + } + if (w->indent[NINDENT]) + trimspaces(et); + namer = bytetorune(name, &nname); + putfile(f, 0, f->b.nc, namer, nname); + xfidlog(w, "put"); + free(name); } -void -dump(Text *_0, Text *_1, Text *argt, int isdump, int _2, Rune *arg, int narg) -{ - char *name; +void dump( + Text* _0, Text* _1, Text* argt, int isdump, int _2, Rune* arg, int narg) { + char* name; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - if(narg) - name = runetobyte(arg, narg); - else - getbytearg(argt, FALSE, TRUE, &name); - if(isdump) - rowdump(&row, name); - else - rowload(&row, name, FALSE); - free(name); + if (narg) + name = runetobyte(arg, narg); + else + getbytearg(argt, FALSE, TRUE, &name); + if (isdump) + rowdump(&row, name); + else + rowload(&row, name, FALSE); + free(name); } -void -cut(Text *et, Text *t, Text *_0, int dosnarf, int docut, Rune *_2, int _3) -{ - uint q0, q1, n, locked, c; - Rune *r; +void cut( + Text* et, Text* t, Text* _0, int dosnarf, int docut, Rune* _2, int _3) { + uint q0, q1, n, locked, c; + Rune* r; - USED(_0); - USED(_2); - USED(_3); + USED(_0); + USED(_2); + USED(_3); - /* - * if not executing a mouse chord (et != t) and snarfing (dosnarf) - * and executed Cut or Snarf in window tag (et->w != nil), - * then use the window body selection or the tag selection - * or do nothing at all. - */ - if(et!=t && dosnarf && et->w!=nil){ - if(et->w->body.q1>et->w->body.q0){ - t = &et->w->body; - if(docut) - filemark(t->file); /* seq has been incremented by execute */ - }else if(et->w->tag.q1>et->w->tag.q0) - t = &et->w->tag; - else - t = nil; - } - if(t == nil) /* no selection */ - return; + /* + * if not executing a mouse chord (et != t) and snarfing (dosnarf) + * and executed Cut or Snarf in window tag (et->w != nil), + * then use the window body selection or the tag selection + * or do nothing at all. + */ + if (et != t && dosnarf && et->w != nil) { + if (et->w->body.q1 > et->w->body.q0) { + t = &et->w->body; + if (docut) + filemark(t->file); /* seq has been incremented by execute */ + } else if (et->w->tag.q1 > et->w->tag.q0) + t = &et->w->tag; + else + t = nil; + } + if (t == nil) /* no selection */ + return; - locked = FALSE; - if(t->w!=nil && et->w!=t->w){ - locked = TRUE; - c = 'M'; - if(et->w) - c = et->w->owner; - winlock(t->w, c); - } - if(t->q0 == t->q1){ - if(locked) - winunlock(t->w); - return; - } - if(dosnarf){ - q0 = t->q0; - q1 = t->q1; - bufdelete(&snarfbuf, 0, snarfbuf.nc); - r = fbufalloc(); - while(q0 < q1){ - n = q1 - q0; - if(n > RBUFSIZE) - n = RBUFSIZE; - bufread(&t->file->b, q0, r, n); - bufinsert(&snarfbuf, snarfbuf.nc, r, n); - q0 += n; - } - fbuffree(r); - acmeputsnarf(); - } - if(docut){ - textdelete(t, t->q0, t->q1, TRUE); - textsetselect(t, t->q0, t->q0); - if(t->w){ - textscrdraw(t); - winsettag(t->w); - } - }else if(dosnarf) /* Snarf command */ - argtext = t; - if(locked) - winunlock(t->w); + locked = FALSE; + if (t->w != nil && et->w != t->w) { + locked = TRUE; + c = 'M'; + if (et->w) + c = et->w->owner; + winlock(t->w, c); + } + if (t->q0 == t->q1) { + if (locked) + winunlock(t->w); + return; + } + if (dosnarf) { + q0 = t->q0; + q1 = t->q1; + bufdelete(&snarfbuf, 0, snarfbuf.nc); + r = fbufalloc(); + while (q0 < q1) { + n = q1 - q0; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(&t->file->b, q0, r, n); + bufinsert(&snarfbuf, snarfbuf.nc, r, n); + q0 += n; + } + fbuffree(r); + acmeputsnarf(); + } + if (docut) { + textdelete(t, t->q0, t->q1, TRUE); + textsetselect(t, t->q0, t->q0); + if (t->w) { + textscrdraw(t); + winsettag(t->w); + } + } else if (dosnarf) /* Snarf command */ + argtext = t; + if (locked) + winunlock(t->w); } -void -paste(Text *et, Text *t, Text *_0, int selectall, int tobody, Rune *_1, int _2) -{ - int c; - uint q, q0, q1, n; - Rune *r; +void paste( + Text* et, Text* t, Text* _0, int selectall, int tobody, Rune* _1, int _2) { + int c; + uint q, q0, q1, n; + Rune* r; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - /* if(tobody), use body of executing window (Paste or Send command) */ - if(tobody && et!=nil && et->w!=nil){ - t = &et->w->body; - filemark(t->file); /* seq has been incremented by execute */ - } - if(t == nil) - return; + /* if(tobody), use body of executing window (Paste or Send command) */ + if (tobody && et != nil && et->w != nil) { + t = &et->w->body; + filemark(t->file); /* seq has been incremented by execute */ + } + if (t == nil) + return; - acmegetsnarf(); - if(t==nil || snarfbuf.nc==0) - return; - if(t->w!=nil && et->w!=t->w){ - c = 'M'; - if(et->w) - c = et->w->owner; - winlock(t->w, c); - } - cut(t, t, nil, FALSE, TRUE, nil, 0); - q = 0; - q0 = t->q0; - q1 = t->q0+snarfbuf.nc; - r = fbufalloc(); - while(q0 < q1){ - n = q1 - q0; - if(n > RBUFSIZE) - n = RBUFSIZE; - if(r == nil) - r = runemalloc(n); - bufread(&snarfbuf, q, r, n); - textinsert(t, q0, r, n, TRUE); - q += n; - q0 += n; - } - fbuffree(r); - if(selectall) - textsetselect(t, t->q0, q1); - else - textsetselect(t, q1, q1); - if(t->w){ - textscrdraw(t); - winsettag(t->w); - } - if(t->w!=nil && et->w!=t->w) - winunlock(t->w); + acmegetsnarf(); + if (t == nil || snarfbuf.nc == 0) + return; + if (t->w != nil && et->w != t->w) { + c = 'M'; + if (et->w) + c = et->w->owner; + winlock(t->w, c); + } + cut(t, t, nil, FALSE, TRUE, nil, 0); + q = 0; + q0 = t->q0; + q1 = t->q0 + snarfbuf.nc; + r = fbufalloc(); + while (q0 < q1) { + n = q1 - q0; + if (n > RBUFSIZE) + n = RBUFSIZE; + if (r == nil) + r = runemalloc(n); + bufread(&snarfbuf, q, r, n); + textinsert(t, q0, r, n, TRUE); + q += n; + q0 += n; + } + fbuffree(r); + if (selectall) + textsetselect(t, t->q0, q1); + else + textsetselect(t, q1, q1); + if (t->w) { + textscrdraw(t); + winsettag(t->w); + } + if (t->w != nil && et->w != t->w) + winunlock(t->w); } -void -look(Text *et, Text *t, Text *argt, int _0, int _1, Rune *arg, int narg) -{ - Rune *r; - int n; +void look(Text* et, Text* t, Text* argt, int _0, int _1, Rune* arg, int narg) { + Rune* r; + int n; - USED(_0); - USED(_1); + USED(_0); + USED(_1); - if(et && et->w){ - t = &et->w->body; - if(narg > 0){ - search(t, arg, narg); - return; - } - getarg(argt, FALSE, FALSE, &r, &n); - if(r == nil){ - n = t->q1-t->q0; - r = runemalloc(n); - bufread(&t->file->b, t->q0, r, n); - } - search(t, r, n); - free(r); - } + if (et && et->w) { + t = &et->w->body; + if (narg > 0) { + search(t, arg, narg); + return; + } + getarg(argt, FALSE, FALSE, &r, &n); + if (r == nil) { + n = t->q1 - t->q0; + r = runemalloc(n); + bufread(&t->file->b, t->q0, r, n); + } + search(t, r, n); + free(r); + } } -static Rune Lnl[] = { '\n', 0 }; +static Rune Lnl[] = {'\n', 0}; -void -sendx(Text *et, Text *t, Text *_0, int _1, int _2, Rune *_3, int _4) -{ - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); +void sendx(Text* et, Text* t, Text* _0, int _1, int _2, Rune* _3, int _4) { + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); - if(et->w==nil) - return; - t = &et->w->body; - if(t->q0 != t->q1) - cut(t, t, nil, TRUE, FALSE, nil, 0); - textsetselect(t, t->file->b.nc, t->file->b.nc); - paste(t, t, nil, TRUE, TRUE, nil, 0); - if(textreadc(t, t->file->b.nc-1) != '\n'){ - textinsert(t, t->file->b.nc, Lnl, 1, TRUE); - textsetselect(t, t->file->b.nc, t->file->b.nc); - } - t->iq1 = t->q1; - textshow(t, t->q1, t->q1, 1); + if (et->w == nil) + return; + t = &et->w->body; + if (t->q0 != t->q1) + cut(t, t, nil, TRUE, FALSE, nil, 0); + textsetselect(t, t->file->b.nc, t->file->b.nc); + paste(t, t, nil, TRUE, TRUE, nil, 0); + if (textreadc(t, t->file->b.nc - 1) != '\n') { + textinsert(t, t->file->b.nc, Lnl, 1, TRUE); + textsetselect(t, t->file->b.nc, t->file->b.nc); + } + t->iq1 = t->q1; + textshow(t, t->q1, t->q1, 1); } -void -edit(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) -{ - Rune *r; - int len; +void edit(Text* et, Text* _0, Text* argt, int _1, int _2, Rune* arg, int narg) { + Rune* r; + int len; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - if(et == nil) - return; - getarg(argt, FALSE, TRUE, &r, &len); - seq++; - if(r != nil){ - editcmd(et, r, len); - free(r); - }else - editcmd(et, arg, narg); + if (et == nil) + return; + getarg(argt, FALSE, TRUE, &r, &len); + seq++; + if (r != nil) { + editcmd(et, r, len); + free(r); + } else + editcmd(et, arg, narg); } -void -xexit(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - USED(et); - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); +void xexit(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + USED(et); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - if(rowclean(&row)){ - sendul(cexit, 0); - threadexits(nil); - } + if (rowclean(&row)) { + sendul(cexit, 0); + threadexits(nil); + } } -void -putall(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - int i, j, e; - Window *w; - Column *c; - char *a; +void putall(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + int i, j, e; + Window* w; + Column* c; + char* a; - USED(et); - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); + USED(et); + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); - for(i=0; inw; j++){ - w = c->w[j]; - if(w->isscratch || w->isdir || w->body.file->nname==0) - continue; - if(w->nopen[QWevent] > 0) - continue; - a = runetobyte(w->body.file->name, w->body.file->nname); - e = access(a, 0); - if(w->body.file->mod || w->body.ncache) - if(e < 0) - warning(nil, "no auto-Put of %s: %r\n", a); - else{ - wincommit(w, &w->body); - put(&w->body, nil, nil, XXX, XXX, nil, 0); - } - free(a); - } - } + for (i = 0; i < row.ncol; i++) { + c = row.col[i]; + for (j = 0; j < c->nw; j++) { + w = c->w[j]; + if (w->isscratch || w->isdir || w->body.file->nname == 0) + continue; + if (w->nopen[QWevent] > 0) + continue; + a = runetobyte(w->body.file->name, w->body.file->nname); + e = access(a, 0); + if (w->body.file->mod || w->body.ncache) + if (e < 0) + warning(nil, "no auto-Put of %s: %r\n", a); + else { + wincommit(w, &w->body); + put(&w->body, nil, nil, XXX, XXX, nil, 0); + } + free(a); + } + } } +void id(Text* et, Text* _0, Text* _1, int _2, int _3, Rune* _4, int _5) { + USED(_0); + USED(_1); + USED(_2); + USED(_3); + USED(_4); + USED(_5); -void -id(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5) -{ - USED(_0); - USED(_1); - USED(_2); - USED(_3); - USED(_4); - USED(_5); - - if(et && et->w) - warning(nil, "/mnt/acme/%d/\n", et->w->id); + if (et && et->w) + warning(nil, "/mnt/acme/%d/\n", et->w->id); } -void -local(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) -{ - char *a, *aa; - Runestr dir; +void local( + Text* et, Text* _0, Text* argt, int _1, int _2, Rune* arg, int narg) { + char *a, *aa; + Runestr dir; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - aa = getbytearg(argt, TRUE, TRUE, &a); + aa = getbytearg(argt, TRUE, TRUE, &a); - dir = dirname(et, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - run(nil, runetobyte(arg, narg), dir.r, dir.nr, FALSE, aa, a, FALSE); + dir = dirname(et, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + run(nil, runetobyte(arg, narg), dir.r, dir.nr, FALSE, aa, a, FALSE); } -void -xkill(Text *_0, Text *_1, Text *argt, int _2, int _3, Rune *arg, int narg) -{ - Rune *a, *cmd, *r; - int na; +void xkill( + Text* _0, Text* _1, Text* argt, int _2, int _3, Rune* arg, int narg) { + Rune *a, *cmd, *r; + int na; - USED(_0); - USED(_1); - USED(_2); - USED(_3); + USED(_0); + USED(_1); + USED(_2); + USED(_3); - getarg(argt, FALSE, FALSE, &r, &na); - if(r) - xkill(nil, nil, nil, 0, 0, r, na); - /* loop condition: *arg is not a blank */ - for(;;){ - a = findbl(arg, narg, &na); - if(a == arg) - break; - cmd = runemalloc(narg-na+1); - runemove(cmd, arg, narg-na); - sendp(ckill, cmd); - arg = skipbl(a, na, &narg); - } + getarg(argt, FALSE, FALSE, &r, &na); + if (r) + xkill(nil, nil, nil, 0, 0, r, na); + /* loop condition: *arg is not a blank */ + for (;;) { + a = findbl(arg, narg, &na); + if (a == arg) + break; + cmd = runemalloc(narg - na + 1); + runemove(cmd, arg, narg - na); + sendp(ckill, cmd); + arg = skipbl(a, na, &narg); + } } -static Rune Lfix[] = { 'f', 'i', 'x', 0 }; -static Rune Lvar[] = { 'v', 'a', 'r', 0 }; +static Rune Lfix[] = {'f', 'i', 'x', 0}; +static Rune Lvar[] = {'v', 'a', 'r', 0}; -void -fontx(Text *et, Text *t, Text *argt, int _0, int _1, Rune *arg, int narg) -{ - Rune *a, *r, *flag, *file; - int na, nf; - char *aa; - Reffont *newfont; - Dirlist *dp; - int i, fix; +void fontx(Text* et, Text* t, Text* argt, int _0, int _1, Rune* arg, int narg) { + Rune *a, *r, *flag, *file; + int na, nf; + char* aa; + Reffont* newfont; + Dirlist* dp; + int i, fix; - USED(_0); - USED(_1); + USED(_0); + USED(_1); - if(et==nil || et->w==nil) - return; - t = &et->w->body; - flag = nil; - file = nil; - /* loop condition: *arg is not a blank */ - nf = 0; - for(;;){ - a = findbl(arg, narg, &na); - if(a == arg) - break; - r = runemalloc(narg-na+1); - runemove(r, arg, narg-na); - if(runeeq(r, narg-na, Lfix, 3) || runeeq(r, narg-na, Lvar, 3)){ - free(flag); - flag = r; - }else{ - free(file); - file = r; - nf = narg-na; - } - arg = skipbl(a, na, &narg); - } - getarg(argt, FALSE, TRUE, &r, &na); - if(r) - if(runeeq(r, na, Lfix, 3) || runeeq(r, na, Lvar, 3)){ - free(flag); - flag = r; - }else{ - free(file); - file = r; - nf = na; - } - fix = 1; - if(flag) - fix = runeeq(flag, runestrlen(flag), Lfix, 3); - else if(file == nil){ - newfont = rfget(FALSE, FALSE, FALSE, nil); - if(newfont) - fix = strcmp(newfont->f->name, t->fr.font->name)==0; - } - if(file){ - aa = runetobyte(file, nf); - newfont = rfget(fix, flag!=nil, FALSE, aa); - free(aa); - }else - newfont = rfget(fix, FALSE, FALSE, nil); - if(newfont){ - draw(screen, t->w->r, textcols[BACK], nil, ZP); - rfclose(t->reffont); - t->reffont = newfont; - t->fr.font = newfont->f; - frinittick(&t->fr); - if(t->w->isdir){ - t->all.min.x++; /* force recolumnation; disgusting! */ - for(i=0; iw->ndl; i++){ - dp = t->w->dlp[i]; - aa = runetobyte(dp->r, dp->nr); - dp->wid = stringwidth(newfont->f, aa); - free(aa); - } - } - /* avoid shrinking of window due to quantization */ - colgrow(t->w->col, t->w, -1); - } - free(file); - free(flag); + if (et == nil || et->w == nil) + return; + t = &et->w->body; + flag = nil; + file = nil; + /* loop condition: *arg is not a blank */ + nf = 0; + for (;;) { + a = findbl(arg, narg, &na); + if (a == arg) + break; + r = runemalloc(narg - na + 1); + runemove(r, arg, narg - na); + if (runeeq(r, narg - na, Lfix, 3) || runeeq(r, narg - na, Lvar, 3)) { + free(flag); + flag = r; + } else { + free(file); + file = r; + nf = narg - na; + } + arg = skipbl(a, na, &narg); + } + getarg(argt, FALSE, TRUE, &r, &na); + if (r) + if (runeeq(r, na, Lfix, 3) || runeeq(r, na, Lvar, 3)) { + free(flag); + flag = r; + } else { + free(file); + file = r; + nf = na; + } + fix = 1; + if (flag) + fix = runeeq(flag, runestrlen(flag), Lfix, 3); + else if (file == nil) { + newfont = rfget(FALSE, FALSE, FALSE, nil); + if (newfont) + fix = strcmp(newfont->f->name, t->fr.font->name) == 0; + } + if (file) { + aa = runetobyte(file, nf); + newfont = rfget(fix, flag != nil, FALSE, aa); + free(aa); + } else + newfont = rfget(fix, FALSE, FALSE, nil); + if (newfont) { + draw(screen, t->w->r, textcols[BACK], nil, ZP); + rfclose(t->reffont); + t->reffont = newfont; + t->fr.font = newfont->f; + frinittick(&t->fr); + if (t->w->isdir) { + t->all.min.x++; /* force recolumnation; disgusting! */ + for (i = 0; i < t->w->ndl; i++) { + dp = t->w->dlp[i]; + aa = runetobyte(dp->r, dp->nr); + dp->wid = stringwidth(newfont->f, aa); + free(aa); + } + } + /* avoid shrinking of window due to quantization */ + colgrow(t->w->col, t->w, -1); + } + free(file); + free(flag); } -void -incl(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) -{ - Rune *a, *r; - Window *w; - int na, n, len; +void incl(Text* et, Text* _0, Text* argt, int _1, int _2, Rune* arg, int narg) { + Rune *a, *r; + Window* w; + int na, n, len; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - if(et==nil || et->w==nil) - return; - w = et->w; - n = 0; - getarg(argt, FALSE, TRUE, &r, &len); - if(r){ - n++; - winaddincl(w, r, len); - } - /* loop condition: *arg is not a blank */ - for(;;){ - a = findbl(arg, narg, &na); - if(a == arg) - break; - r = runemalloc(narg-na+1); - runemove(r, arg, narg-na); - n++; - winaddincl(w, r, narg-na); - arg = skipbl(a, na, &narg); - } - if(n==0 && w->nincl){ - for(n=w->nincl; --n>=0; ) - warning(nil, "%S ", w->incl[n]); - warning(nil, "\n"); - } + if (et == nil || et->w == nil) + return; + w = et->w; + n = 0; + getarg(argt, FALSE, TRUE, &r, &len); + if (r) { + n++; + winaddincl(w, r, len); + } + /* loop condition: *arg is not a blank */ + for (;;) { + a = findbl(arg, narg, &na); + if (a == arg) + break; + r = runemalloc(narg - na + 1); + runemove(r, arg, narg - na); + n++; + winaddincl(w, r, narg - na); + arg = skipbl(a, na, &narg); + } + if (n == 0 && w->nincl) { + for (n = w->nincl; --n >= 0;) + warning(nil, "%S ", w->incl[n]); + warning(nil, "\n"); + } } -static Rune LON[] = { 'O', 'N', 0 }; -static Rune LOFF[] = { 'O', 'F', 'F', 0 }; -static Rune Lon[] = { 'o', 'n', 0 }; -static Rune Loff[] = { 'o', 'f', 'f', 0 }; +static Rune LON[] = {'O', 'N', 0}; +static Rune LOFF[] = {'O', 'F', 'F', 0}; +static Rune Lon[] = {'o', 'n', 0}; +static Rune Loff[] = {'o', 'f', 'f', 0}; enum { - IGlobal = -2, - IError = -1, + IGlobal = -2, + IError = -1, }; -static int -indentval(Rune *s, int n, int type) -{ - static char *strs[] = { - [SPACESINDENT] = "Spaces", - [AUTOINDENT] = "Indent", - }; +static int indentval(Rune* s, int n, int type) { + static char* strs[] = { + [SPACESINDENT] = "Spaces", + [AUTOINDENT] = "Indent", + }; - if(n < 2) - return IError; - if(runestrncmp(s, LON, n) == 0){ - globalindent[type] = TRUE; - warning(nil, "%s ON\n", strs[type]); - return IGlobal; - } - if(runestrncmp(s, LOFF, n) == 0){ - globalindent[type] = FALSE; - warning(nil, "%s OFF\n", strs[type]); - return IGlobal; - } - if(runestrncmp(s, Lon, n) == 0) - return TRUE; - if(runestrncmp(s, Loff, n) == 0) - return FALSE; - return IError; + if (n < 2) + return IError; + if (runestrncmp(s, LON, n) == 0) { + globalindent[type] = TRUE; + warning(nil, "%s ON\n", strs[type]); + return IGlobal; + } + if (runestrncmp(s, LOFF, n) == 0) { + globalindent[type] = FALSE; + warning(nil, "%s OFF\n", strs[type]); + return IGlobal; + } + if (runestrncmp(s, Lon, n) == 0) + return TRUE; + if (runestrncmp(s, Loff, n) == 0) + return FALSE; + return IError; } -static void -fixindent(Window *w, void *arg) -{ - int t; +static void fixindent(Window* w, void* arg) { + int t; - t = (int)arg; - w->indent[t] = globalindent[t]; + t = (int)arg; + w->indent[t] = globalindent[t]; } -void -indent(Text *et, Text* _0, Text *argt, int type, int _1, Rune *arg, int narg) -{ - Rune *a, *r; - Window *w; - int na, len, ival; +void indent( + Text* et, Text* _0, Text* argt, int type, int _1, Rune* arg, int narg) { + Rune *a, *r; + Window* w; + int na, len, ival; - USED(_0); - USED(_1); + USED(_0); + USED(_1); - w = nil; - if(et!=nil && et->w!=nil) - w = et->w; - ival = IError; - getarg(argt, FALSE, TRUE, &r, &len); - if(r!=nil && len>0) - ival = indentval(r, len, type); - else{ - a = findbl(arg, narg, &na); - if(a != arg) - ival = indentval(arg, narg-na, type); - } - if(ival == IGlobal) - allwindows(fixindent, (void*)type); - else if(w != nil && ival >= 0) - w->indent[type] = ival; + w = nil; + if (et != nil && et->w != nil) + w = et->w; + ival = IError; + getarg(argt, FALSE, TRUE, &r, &len); + if (r != nil && len > 0) + ival = indentval(r, len, type); + else { + a = findbl(arg, narg, &na); + if (a != arg) + ival = indentval(arg, narg - na, type); + } + if (ival == IGlobal) + allwindows(fixindent, (void*)type); + else if (w != nil && ival >= 0) + w->indent[type] = ival; } -void -tab(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg) -{ - Rune *a, *r; - Window *w; - int na, len, tab; - char *p; +void tab(Text* et, Text* _0, Text* argt, int _1, int _2, Rune* arg, int narg) { + Rune *a, *r; + Window* w; + int na, len, tab; + char* p; - USED(_0); - USED(_1); - USED(_2); + USED(_0); + USED(_1); + USED(_2); - if(et==nil || et->w==nil) - return; - w = et->w; - getarg(argt, FALSE, TRUE, &r, &len); - tab = 0; - if(r!=nil && len>0){ - p = runetobyte(r, len); - if('0'<=p[0] && p[0]<='9') - tab = atoi(p); - free(p); - }else{ - a = findbl(arg, narg, &na); - if(a != arg){ - p = runetobyte(arg, narg-na); - if('0'<=p[0] && p[0]<='9') - tab = atoi(p); - free(p); - } - } - if(tab > 0){ - if(w->body.tabstop != tab){ - w->body.tabstop = tab; - winresize(w, w->r, FALSE, TRUE); - } - }else - warning(nil, "%.*S: Tab %d\n", w->body.file->nname, w->body.file->name, w->body.tabstop); + if (et == nil || et->w == nil) + return; + w = et->w; + getarg(argt, FALSE, TRUE, &r, &len); + tab = 0; + if (r != nil && len > 0) { + p = runetobyte(r, len); + if ('0' <= p[0] && p[0] <= '9') + tab = atoi(p); + free(p); + } else { + a = findbl(arg, narg, &na); + if (a != arg) { + p = runetobyte(arg, narg - na); + if ('0' <= p[0] && p[0] <= '9') + tab = atoi(p); + free(p); + } + } + if (tab > 0) { + if (w->body.tabstop != tab) { + w->body.tabstop = tab; + winresize(w, w->r, FALSE, TRUE); + } + } else + warning( + nil, + "%.*S: Tab %d\n", + w->body.file->nname, + w->body.file->name, + w->body.tabstop); } -void -runproc(void *argvp) -{ - /* args: */ - Window *win; - char *s; - Rune *rdir; - int ndir; - int newns; - char *argaddr; - char *arg; - Command *c; - Channel *cpid; - int iseditcmd; - /* end of args */ - char *e, *t, *name, *filename, *dir, **av, *news; - Rune r, **incl; - int ac, w, inarg, i, n, fd, nincl, winid; - int sfd[3]; - int pipechar; - char buf[512]; - int ret; - /*static void *parg[2]; */ - char *rcarg[4]; - void **argv; - CFsys *fs; - char *shell; +void runproc(void* argvp) { + /* args: */ + Window* win; + char* s; + Rune* rdir; + int ndir; + int newns; + char* argaddr; + char* arg; + Command* c; + Channel* cpid; + int iseditcmd; + /* end of args */ + char *e, *t, *name, *filename, *dir, **av, *news; + Rune r, **incl; + int ac, w, inarg, i, n, fd, nincl, winid; + int sfd[3]; + int pipechar; + char buf[512]; + int ret; + /*static void *parg[2]; */ + char* rcarg[4]; + void** argv; + CFsys* fs; + char* shell; - threadsetname("runproc"); + threadsetname("runproc"); - argv = argvp; - win = argv[0]; - s = argv[1]; - rdir = argv[2]; - ndir = (uintptr)argv[3]; - newns = (uintptr)argv[4]; - argaddr = argv[5]; - arg = argv[6]; - c = argv[7]; - cpid = argv[8]; - iseditcmd = (uintptr)argv[9]; - free(argv); + argv = argvp; + win = argv[0]; + s = argv[1]; + rdir = argv[2]; + ndir = (uintptr)argv[3]; + newns = (uintptr)argv[4]; + argaddr = argv[5]; + arg = argv[6]; + c = argv[7]; + cpid = argv[8]; + iseditcmd = (uintptr)argv[9]; + free(argv); - t = s; - while(*t==' ' || *t=='\n' || *t=='\t') - t++; - for(e=t; *e; e++) - if(*e==' ' || *e=='\n' || *e=='\t' ) - break; - name = emalloc((e-t)+2); - memmove(name, t, e-t); - name[e-t] = 0; - e = utfrrune(name, '/'); - if(e) - memmove(name, e+1, strlen(e+1)+1); /* strcpy but overlaps */ - strcat(name, " "); /* add blank here for ease in waittask */ - c->name = bytetorune(name, &c->nname); - free(name); - pipechar = 0; - if(*t=='<' || *t=='|' || *t=='>') - pipechar = *t++; - c->iseditcmd = iseditcmd; - c->text = s; - if(newns){ - nincl = 0; - incl = nil; - if(win){ - filename = smprint("%.*S", win->body.file->nname, win->body.file->name); - nincl = win->nincl; - if(nincl > 0){ - incl = emalloc(nincl*sizeof(Rune*)); - for(i=0; iincl[i]); - incl[i] = runemalloc(n+1); - runemove(incl[i], win->incl[i], n); - } - } - winid = win->id; - }else{ - filename = nil; - winid = 0; - if(activewin) - winid = activewin->id; - } - rfork(RFNAMEG|RFENVG|RFFDG|RFNOTEG); - sprint(buf, "%d", winid); - putenv("winid", buf); + t = s; + while (*t == ' ' || *t == '\n' || *t == '\t') + t++; + for (e = t; *e; e++) + if (*e == ' ' || *e == '\n' || *e == '\t') + break; + name = emalloc((e - t) + 2); + memmove(name, t, e - t); + name[e - t] = 0; + e = utfrrune(name, '/'); + if (e) + memmove(name, e + 1, strlen(e + 1) + 1); /* strcpy but overlaps */ + strcat(name, " "); /* add blank here for ease in waittask */ + c->name = bytetorune(name, &c->nname); + free(name); + pipechar = 0; + if (*t == '<' || *t == '|' || *t == '>') + pipechar = *t++; + c->iseditcmd = iseditcmd; + c->text = s; + if (newns) { + nincl = 0; + incl = nil; + if (win) { + filename = smprint("%.*S", win->body.file->nname, win->body.file->name); + nincl = win->nincl; + if (nincl > 0) { + incl = emalloc(nincl * sizeof(Rune*)); + for (i = 0; i < nincl; i++) { + n = runestrlen(win->incl[i]); + incl[i] = runemalloc(n + 1); + runemove(incl[i], win->incl[i], n); + } + } + winid = win->id; + } else { + filename = nil; + winid = 0; + if (activewin) + winid = activewin->id; + } + rfork(RFNAMEG | RFENVG | RFFDG | RFNOTEG); + sprint(buf, "%d", winid); + putenv("winid", buf); - if(filename){ - putenv("%", filename); - putenv("samfile", filename); - free(filename); - } - c->md = fsysmount(rdir, ndir, incl, nincl); - if(c->md == nil){ - fprint(2, "child: can't allocate mntdir: %r\n"); - threadexits("fsysmount"); - } - sprint(buf, "%d", c->md->id); - if((fs = nsmount("acme", buf)) == nil){ - fprint(2, "child: can't mount acme: %r\n"); - fsysdelid(c->md); - c->md = nil; - threadexits("nsmount"); - } - if(winid>0 && (pipechar=='|' || pipechar=='>')){ - sprint(buf, "%d/rdsel", winid); - sfd[0] = fsopenfd(fs, buf, OREAD); - }else - sfd[0] = open("/dev/null", OREAD); - if((winid>0 || iseditcmd) && (pipechar=='|' || pipechar=='<')){ - if(iseditcmd){ - if(winid > 0) - sprint(buf, "%d/editout", winid); - else - sprint(buf, "editout"); - }else - sprint(buf, "%d/wrsel", winid); - sfd[1] = fsopenfd(fs, buf, OWRITE); - sfd[2] = fsopenfd(fs, "cons", OWRITE); - }else{ - sfd[1] = fsopenfd(fs, "cons", OWRITE); - sfd[2] = sfd[1]; - } - fsunmount(fs); - }else{ - rfork(RFFDG|RFNOTEG); - fsysclose(); - sfd[0] = open("/dev/null", OREAD); - sfd[1] = open("/dev/null", OWRITE); - sfd[2] = dup(erroutfd, -1); - } - if(win) - winclose(win); + if (filename) { + putenv("%", filename); + putenv("samfile", filename); + free(filename); + } + c->md = fsysmount(rdir, ndir, incl, nincl); + if (c->md == nil) { + fprint(2, "child: can't allocate mntdir: %r\n"); + threadexits("fsysmount"); + } + sprint(buf, "%d", c->md->id); + if ((fs = nsmount("acme", buf)) == nil) { + fprint(2, "child: can't mount acme: %r\n"); + fsysdelid(c->md); + c->md = nil; + threadexits("nsmount"); + } + if (winid > 0 && (pipechar == '|' || pipechar == '>')) { + sprint(buf, "%d/rdsel", winid); + sfd[0] = fsopenfd(fs, buf, OREAD); + } else + sfd[0] = open("/dev/null", OREAD); + if ((winid > 0 || iseditcmd) && (pipechar == '|' || pipechar == '<')) { + if (iseditcmd) { + if (winid > 0) + sprint(buf, "%d/editout", winid); + else + sprint(buf, "editout"); + } else + sprint(buf, "%d/wrsel", winid); + sfd[1] = fsopenfd(fs, buf, OWRITE); + sfd[2] = fsopenfd(fs, "cons", OWRITE); + } else { + sfd[1] = fsopenfd(fs, "cons", OWRITE); + sfd[2] = sfd[1]; + } + fsunmount(fs); + } else { + rfork(RFFDG | RFNOTEG); + fsysclose(); + sfd[0] = open("/dev/null", OREAD); + sfd[1] = open("/dev/null", OWRITE); + sfd[2] = dup(erroutfd, -1); + } + if (win) + winclose(win); - if(argaddr) - putenv("acmeaddr", argaddr); - if(acmeshell != nil) - goto Hard; - if(strlen(t) > sizeof buf-10) /* may need to print into stack */ - goto Hard; - inarg = FALSE; - for(e=t; *e; e+=w){ - w = chartorune(&r, e); - if(r==' ' || r=='\t') - continue; - if(r < ' ') - goto Hard; - if(utfrune("#;&|^$=`'{}()<>[]*?^~`/", r)) - goto Hard; - inarg = TRUE; - } - if(!inarg) - goto Fail; + if (argaddr) + putenv("acmeaddr", argaddr); + if (acmeshell != nil) + goto Hard; + if (strlen(t) > sizeof buf - 10) /* may need to print into stack */ + goto Hard; + inarg = FALSE; + for (e = t; *e; e += w) { + w = chartorune(&r, e); + if (r == ' ' || r == '\t') + continue; + if (r < ' ') + goto Hard; + if (utfrune("#;&|^$=`'{}()<>[]*?^~`/", r)) + goto Hard; + inarg = TRUE; + } + if (!inarg) + goto Fail; - ac = 0; - av = nil; - inarg = FALSE; - for(e=t; *e; e+=w){ - w = chartorune(&r, e); - if(r==' ' || r=='\t'){ - inarg = FALSE; - *e = 0; - continue; - } - if(!inarg){ - inarg = TRUE; - av = realloc(av, (ac+1)*sizeof(char**)); - av[ac++] = e; - } - } - av = realloc(av, (ac+2)*sizeof(char**)); - av[ac++] = arg; - av[ac] = nil; - c->av = av; + ac = 0; + av = nil; + inarg = FALSE; + for (e = t; *e; e += w) { + w = chartorune(&r, e); + if (r == ' ' || r == '\t') { + inarg = FALSE; + *e = 0; + continue; + } + if (!inarg) { + inarg = TRUE; + av = realloc(av, (ac + 1) * sizeof(char**)); + av[ac++] = e; + } + } + av = realloc(av, (ac + 2) * sizeof(char**)); + av[ac++] = arg; + av[ac] = nil; + c->av = av; - dir = nil; - if(rdir != nil) - dir = runetobyte(rdir, ndir); - ret = threadspawnd(sfd, av[0], av, dir); - free(dir); - if(ret >= 0){ - if(cpid) - sendul(cpid, ret); - threadexits(""); - } + dir = nil; + if (rdir != nil) + dir = runetobyte(rdir, ndir); + ret = threadspawnd(sfd, av[0], av, dir); + free(dir); + if (ret >= 0) { + if (cpid) + sendul(cpid, ret); + threadexits(""); + } /* libthread uses execvp so no need to do this */ #if 0 e = av[0]; @@ -1694,121 +1656,119 @@ runproc(void *argvp) sprint(buf, "/bin/%s", av[0]); procexec(cpid, sfd, buf, av); #endif - goto Fail; + goto Fail; Hard: - /* - * ugly: set path = (. $cputype /bin) - * should honor $path if unusual. - */ - if(cputype){ - n = 0; - memmove(buf+n, ".", 2); - n += 2; - i = strlen(cputype)+1; - memmove(buf+n, cputype, i); - n += i; - memmove(buf+n, "/bin", 5); - n += 5; - fd = create("/env/path", OWRITE, 0666); - write(fd, buf, n); - close(fd); - } + /* + * ugly: set path = (. $cputype /bin) + * should honor $path if unusual. + */ + if (cputype) { + n = 0; + memmove(buf + n, ".", 2); + n += 2; + i = strlen(cputype) + 1; + memmove(buf + n, cputype, i); + n += i; + memmove(buf + n, "/bin", 5); + n += 5; + fd = create("/env/path", OWRITE, 0666); + write(fd, buf, n); + close(fd); + } - if(arg){ - news = emalloc(strlen(t) + 1 + 1 + strlen(arg) + 1 + 1); - if(news){ - sprint(news, "%s '%s'", t, arg); /* BUG: what if quote in arg? */ - free(s); - t = news; - c->text = news; - } - } - dir = nil; - if(rdir != nil) - dir = runetobyte(rdir, ndir); - shell = acmeshell; - if(shell == nil) - shell = "rc"; - rcarg[0] = shell; - rcarg[1] = "-c"; - rcarg[2] = t; - rcarg[3] = nil; - ret = threadspawnd(sfd, rcarg[0], rcarg, dir); - free(dir); - if(ret >= 0){ - if(cpid) - sendul(cpid, ret); - threadexits(nil); - } - warning(nil, "exec %s: %r\n", shell); + if (arg) { + news = emalloc(strlen(t) + 1 + 1 + strlen(arg) + 1 + 1); + if (news) { + sprint(news, "%s '%s'", t, arg); /* BUG: what if quote in arg? */ + free(s); + t = news; + c->text = news; + } + } + dir = nil; + if (rdir != nil) + dir = runetobyte(rdir, ndir); + shell = acmeshell; + if (shell == nil) + shell = "rc"; + rcarg[0] = shell; + rcarg[1] = "-c"; + rcarg[2] = t; + rcarg[3] = nil; + ret = threadspawnd(sfd, rcarg[0], rcarg, dir); + free(dir); + if (ret >= 0) { + if (cpid) + sendul(cpid, ret); + threadexits(nil); + } + warning(nil, "exec %s: %r\n", shell); - Fail: - /* threadexec hasn't happened, so send a zero */ - close(sfd[0]); - close(sfd[1]); - if(sfd[2] != sfd[1]) - close(sfd[2]); - sendul(cpid, 0); - threadexits(nil); +Fail: + /* threadexec hasn't happened, so send a zero */ + close(sfd[0]); + close(sfd[1]); + if (sfd[2] != sfd[1]) + close(sfd[2]); + sendul(cpid, 0); + threadexits(nil); } -void -runwaittask(void *v) -{ - Command *c; - Channel *cpid; - void **a; +void runwaittask(void* v) { + Command* c; + Channel* cpid; + void** a; - threadsetname("runwaittask"); - a = v; - c = a[0]; - cpid = a[1]; - free(a); - do - c->pid = recvul(cpid); - while(c->pid == ~0); - free(c->av); - if(c->pid != 0) /* successful exec */ - sendp(ccommand, c); - else{ - if(c->iseditcmd) - sendul(cedit, 0); - free(c->name); - free(c->text); - free(c); - } - chanfree(cpid); + threadsetname("runwaittask"); + a = v; + c = a[0]; + cpid = a[1]; + free(a); + do + c->pid = recvul(cpid); + while (c->pid == ~0); + free(c->av); + if (c->pid != 0) /* successful exec */ + sendp(ccommand, c); + else { + if (c->iseditcmd) + sendul(cedit, 0); + free(c->name); + free(c->text); + free(c); + } + chanfree(cpid); } -void -run(Window *win, char *s, Rune *rdir, int ndir, int newns, char *argaddr, char *xarg, int iseditcmd) -{ - void **arg; - Command *c; - Channel *cpid; +void run( + Window* win, char* s, Rune* rdir, int ndir, int newns, char* argaddr, + char* xarg, int iseditcmd) { + void** arg; + Command* c; + Channel* cpid; - if(s == nil) - return; + if (s == nil) + return; - arg = emalloc(10*sizeof(void*)); - c = emalloc(sizeof *c); - cpid = chancreate(sizeof(ulong), 0); - chansetname(cpid, "cpid %s", s); - arg[0] = win; - arg[1] = s; - arg[2] = rdir; - arg[3] = (void*)(uintptr)ndir; - arg[4] = (void*)(uintptr)newns; - arg[5] = argaddr; - arg[6] = xarg; - arg[7] = c; - arg[8] = cpid; - arg[9] = (void*)(uintptr)iseditcmd; - threadcreate(runproc, arg, STACK); - /* mustn't block here because must be ready to answer mount() call in run() */ - arg = emalloc(2*sizeof(void*)); - arg[0] = c; - arg[1] = cpid; - threadcreate(runwaittask, arg, STACK); + arg = emalloc(10 * sizeof(void*)); + c = emalloc(sizeof *c); + cpid = chancreate(sizeof(ulong), 0); + chansetname(cpid, "cpid %s", s); + arg[0] = win; + arg[1] = s; + arg[2] = rdir; + arg[3] = (void*)(uintptr)ndir; + arg[4] = (void*)(uintptr)newns; + arg[5] = argaddr; + arg[6] = xarg; + arg[7] = c; + arg[8] = cpid; + arg[9] = (void*)(uintptr)iseditcmd; + threadcreate(runproc, arg, STACK); + /* mustn't block here because must be ready to answer mount() call in run() */ + arg = emalloc(2 * sizeof(void*)); + arg[0] = c; + arg[1] = cpid; + threadcreate(runwaittask, arg, STACK); } diff --git a/file.c b/file.c index e1eddc4..e4af18d 100644 --- a/file.c +++ b/file.c @@ -23,289 +23,256 @@ */ typedef struct Undo Undo; -struct Undo -{ - short type; /* Delete, Insert, Filename */ - short mod; /* modify bit */ - uint seq; /* sequence number */ - uint p0; /* location of change (unused in f) */ - uint n; /* # runes in string or file name */ +struct Undo { + short type; /* Delete, Insert, Filename */ + short mod; /* modify bit */ + uint seq; /* sequence number */ + uint p0; /* location of change (unused in f) */ + uint n; /* # runes in string or file name */ }; -enum -{ - Undosize = sizeof(Undo)/sizeof(Rune) -}; +enum { Undosize = sizeof(Undo) / sizeof(Rune) }; -File* -fileaddtext(File *f, Text *t) -{ - if(f == nil){ - f = emalloc(sizeof(File)); - f->unread = TRUE; - } - f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*)); - f->text[f->ntext++] = t; - f->curtext = t; - return f; +File* fileaddtext(File* f, Text* t) { + if (f == nil) { + f = emalloc(sizeof(File)); + f->unread = TRUE; + } + f->text = realloc(f->text, (f->ntext + 1) * sizeof(Text*)); + f->text[f->ntext++] = t; + f->curtext = t; + return f; } -void -filedeltext(File *f, Text *t) -{ - int i; +void filedeltext(File* f, Text* t) { + int i; - for(i=0; intext; i++) - if(f->text[i] == t) - goto Found; - error("can't find text in filedeltext"); + for (i = 0; i < f->ntext; i++) + if (f->text[i] == t) + goto Found; + error("can't find text in filedeltext"); - Found: - f->ntext--; - if(f->ntext == 0){ - fileclose(f); - return; - } - memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*)); - if(f->curtext == t) - f->curtext = f->text[0]; +Found: + f->ntext--; + if (f->ntext == 0) { + fileclose(f); + return; + } + memmove(f->text + i, f->text + i + 1, (f->ntext - i) * sizeof(Text*)); + if (f->curtext == t) + f->curtext = f->text[0]; } -void -fileinsert(File *f, uint p0, Rune *s, uint ns) -{ - if(p0 > f->b.nc) - error("internal error: fileinsert"); - if(f->seq > 0) - fileuninsert(f, &f->delta, p0, ns); - bufinsert(&f->b, p0, s, ns); - if(ns) - f->mod = TRUE; +void fileinsert(File* f, uint p0, Rune* s, uint ns) { + if (p0 > f->b.nc) + error("internal error: fileinsert"); + if (f->seq > 0) + fileuninsert(f, &f->delta, p0, ns); + bufinsert(&f->b, p0, s, ns); + if (ns) + f->mod = TRUE; } -void -fileuninsert(File *f, Buffer *delta, uint p0, uint ns) -{ - Undo u; +void fileuninsert(File* f, Buffer* delta, uint p0, uint ns) { + Undo u; - /* undo an insertion by deleting */ - u.type = Delete; - u.mod = f->mod; - u.seq = f->seq; - u.p0 = p0; - u.n = ns; - bufinsert(delta, delta->nc, (Rune*)&u, Undosize); + /* undo an insertion by deleting */ + u.type = Delete; + u.mod = f->mod; + u.seq = f->seq; + u.p0 = p0; + u.n = ns; + bufinsert(delta, delta->nc, (Rune*)&u, Undosize); } -void -filedelete(File *f, uint p0, uint p1) -{ - if(!(p0<=p1 && p0<=f->b.nc && p1<=f->b.nc)) - error("internal error: filedelete"); - if(f->seq > 0) - fileundelete(f, &f->delta, p0, p1); - bufdelete(&f->b, p0, p1); - if(p1 > p0) - f->mod = TRUE; +void filedelete(File* f, uint p0, uint p1) { + if (!(p0 <= p1 && p0 <= f->b.nc && p1 <= f->b.nc)) + error("internal error: filedelete"); + if (f->seq > 0) + fileundelete(f, &f->delta, p0, p1); + bufdelete(&f->b, p0, p1); + if (p1 > p0) + f->mod = TRUE; } -void -fileundelete(File *f, Buffer *delta, uint p0, uint p1) -{ - Undo u; - Rune *buf; - uint i, n; - - /* undo a deletion by inserting */ - u.type = Insert; - u.mod = f->mod; - u.seq = f->seq; - u.p0 = p0; - u.n = p1-p0; - buf = fbufalloc(); - for(i=p0; i RBUFSIZE) - n = RBUFSIZE; - bufread(&f->b, i, buf, n); - bufinsert(delta, delta->nc, buf, n); - } - fbuffree(buf); - bufinsert(delta, delta->nc, (Rune*)&u, Undosize); +void fileundelete(File* f, Buffer* delta, uint p0, uint p1) { + Undo u; + Rune* buf; + uint i, n; + /* undo a deletion by inserting */ + u.type = Insert; + u.mod = f->mod; + u.seq = f->seq; + u.p0 = p0; + u.n = p1 - p0; + buf = fbufalloc(); + for (i = p0; i < p1; i += n) { + n = p1 - i; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(&f->b, i, buf, n); + bufinsert(delta, delta->nc, buf, n); + } + fbuffree(buf); + bufinsert(delta, delta->nc, (Rune*)&u, Undosize); } -void -filesetname(File *f, Rune *name, int n) -{ - if(f->seq > 0) - fileunsetname(f, &f->delta); - free(f->name); - f->name = runemalloc(n); - runemove(f->name, name, n); - f->nname = n; - f->unread = TRUE; +void filesetname(File* f, Rune* name, int n) { + if (f->seq > 0) + fileunsetname(f, &f->delta); + free(f->name); + f->name = runemalloc(n); + runemove(f->name, name, n); + f->nname = n; + f->unread = TRUE; } -void -fileunsetname(File *f, Buffer *delta) -{ - Undo u; +void fileunsetname(File* f, Buffer* delta) { + Undo u; - /* undo a file name change by restoring old name */ - u.type = Filename; - u.mod = f->mod; - u.seq = f->seq; - u.p0 = 0; /* unused */ - u.n = f->nname; - if(f->nname) - bufinsert(delta, delta->nc, f->name, f->nname); - bufinsert(delta, delta->nc, (Rune*)&u, Undosize); + /* undo a file name change by restoring old name */ + u.type = Filename; + u.mod = f->mod; + u.seq = f->seq; + u.p0 = 0; /* unused */ + u.n = f->nname; + if (f->nname) + bufinsert(delta, delta->nc, f->name, f->nname); + bufinsert(delta, delta->nc, (Rune*)&u, Undosize); } -uint -fileload(File *f, uint p0, int fd, int *nulls, DigestState *h) -{ - if(f->seq > 0) - error("undo in file.load unimplemented"); - return bufload(&f->b, p0, fd, nulls, h); +uint fileload(File* f, uint p0, int fd, int* nulls, DigestState* h) { + if (f->seq > 0) + error("undo in file.load unimplemented"); + return bufload(&f->b, p0, fd, nulls, h); } /* return sequence number of pending redo */ -uint -fileredoseq(File *f) -{ - Undo u; - Buffer *delta; +uint fileredoseq(File* f) { + Undo u; + Buffer* delta; - delta = &f->epsilon; - if(delta->nc == 0) - return 0; - bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize); - return u.seq; + delta = &f->epsilon; + if (delta->nc == 0) + return 0; + bufread(delta, delta->nc - Undosize, (Rune*)&u, Undosize); + return u.seq; } -void -fileundo(File *f, int isundo, uint *q0p, uint *q1p) -{ - Undo u; - Rune *buf; - uint i, j, n, up; - uint stop; - Buffer *delta, *epsilon; +void fileundo(File* f, int isundo, uint* q0p, uint* q1p) { + Undo u; + Rune* buf; + uint i, j, n, up; + uint stop; + Buffer *delta, *epsilon; - if(isundo){ - /* undo; reverse delta onto epsilon, seq decreases */ - delta = &f->delta; - epsilon = &f->epsilon; - stop = f->seq; - }else{ - /* redo; reverse epsilon onto delta, seq increases */ - delta = &f->epsilon; - epsilon = &f->delta; - stop = 0; /* don't know yet */ - } + if (isundo) { + /* undo; reverse delta onto epsilon, seq decreases */ + delta = &f->delta; + epsilon = &f->epsilon; + stop = f->seq; + } else { + /* redo; reverse epsilon onto delta, seq increases */ + delta = &f->epsilon; + epsilon = &f->delta; + stop = 0; /* don't know yet */ + } - buf = fbufalloc(); - while(delta->nc > 0){ - up = delta->nc-Undosize; - bufread(delta, up, (Rune*)&u, Undosize); - if(isundo){ - if(u.seq < stop){ - f->seq = u.seq; - goto Return; - } - }else{ - if(stop == 0) - stop = u.seq; - if(u.seq > stop) - goto Return; - } - switch(u.type){ - default: - fprint(2, "undo: 0x%ux\n", u.type); - abort(); - break; + buf = fbufalloc(); + while (delta->nc > 0) { + up = delta->nc - Undosize; + bufread(delta, up, (Rune*)&u, Undosize); + if (isundo) { + if (u.seq < stop) { + f->seq = u.seq; + goto Return; + } + } else { + if (stop == 0) + stop = u.seq; + if (u.seq > stop) + goto Return; + } + switch (u.type) { + default: + fprint(2, "undo: 0x%ux\n", u.type); + abort(); + break; - case Delete: - f->seq = u.seq; - fileundelete(f, epsilon, u.p0, u.p0+u.n); - f->mod = u.mod; - bufdelete(&f->b, u.p0, u.p0+u.n); - for(j=0; jntext; j++) - textdelete(f->text[j], u.p0, u.p0+u.n, FALSE); - *q0p = u.p0; - *q1p = u.p0; - break; + case Delete: + f->seq = u.seq; + fileundelete(f, epsilon, u.p0, u.p0 + u.n); + f->mod = u.mod; + bufdelete(&f->b, u.p0, u.p0 + u.n); + for (j = 0; j < f->ntext; j++) + textdelete(f->text[j], u.p0, u.p0 + u.n, FALSE); + *q0p = u.p0; + *q1p = u.p0; + break; - case Insert: - f->seq = u.seq; - fileuninsert(f, epsilon, u.p0, u.n); - f->mod = u.mod; - up -= u.n; - for(i=0; i RBUFSIZE) - n = RBUFSIZE; - bufread(delta, up+i, buf, n); - bufinsert(&f->b, u.p0+i, buf, n); - for(j=0; jntext; j++) - textinsert(f->text[j], u.p0+i, buf, n, FALSE); - } - *q0p = u.p0; - *q1p = u.p0+u.n; - break; + case Insert: + f->seq = u.seq; + fileuninsert(f, epsilon, u.p0, u.n); + f->mod = u.mod; + up -= u.n; + for (i = 0; i < u.n; i += n) { + n = u.n - i; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(delta, up + i, buf, n); + bufinsert(&f->b, u.p0 + i, buf, n); + for (j = 0; j < f->ntext; j++) + textinsert(f->text[j], u.p0 + i, buf, n, FALSE); + } + *q0p = u.p0; + *q1p = u.p0 + u.n; + break; - case Filename: - f->seq = u.seq; - fileunsetname(f, epsilon); - f->mod = u.mod; - up -= u.n; - free(f->name); - if(u.n == 0) - f->name = nil; - else - f->name = runemalloc(u.n); - bufread(delta, up, f->name, u.n); - f->nname = u.n; - break; - } - bufdelete(delta, up, delta->nc); - } - if(isundo) - f->seq = 0; - Return: - fbuffree(buf); + case Filename: + f->seq = u.seq; + fileunsetname(f, epsilon); + f->mod = u.mod; + up -= u.n; + free(f->name); + if (u.n == 0) + f->name = nil; + else + f->name = runemalloc(u.n); + bufread(delta, up, f->name, u.n); + f->nname = u.n; + break; + } + bufdelete(delta, up, delta->nc); + } + if (isundo) + f->seq = 0; +Return: + fbuffree(buf); } -void -filereset(File *f) -{ - bufreset(&f->delta); - bufreset(&f->epsilon); - f->seq = 0; +void filereset(File* f) { + bufreset(&f->delta); + bufreset(&f->epsilon); + f->seq = 0; } -void -fileclose(File *f) -{ - free(f->name); - f->nname = 0; - f->name = nil; - free(f->text); - f->ntext = 0; - f->text = nil; - bufclose(&f->b); - bufclose(&f->delta); - bufclose(&f->epsilon); - elogclose(f); - free(f); +void fileclose(File* f) { + free(f->name); + f->nname = 0; + f->name = nil; + free(f->text); + f->ntext = 0; + f->text = nil; + bufclose(&f->b); + bufclose(&f->delta); + bufclose(&f->epsilon); + elogclose(f); + free(f); } -void -filemark(File *f) -{ - if(f->epsilon.nc) - bufdelete(&f->epsilon, 0, f->epsilon.nc); - f->seq = seq; +void filemark(File* f) { + if (f->epsilon.nc) + bufdelete(&f->epsilon, 0, f->epsilon.nc); + f->seq = seq; } diff --git a/fns.h b/fns.h index 8dc0237..0078f44 100644 --- a/fns.h +++ b/fns.h @@ -95,6 +95,7 @@ void flushwarnings(void); void startplumbing(void); long nlcount(Text*, long, long, long*); long nlcounttopos(Text*, long, long, long); +Rune* parsetag(Window*, int*); Runestr runestr(Rune*, uint); Range range(int, int); diff --git a/fsys.c b/fsys.c index 4c395eb..827e5a6 100644 --- a/fsys.c +++ b/fsys.c @@ -12,738 +12,669 @@ #include "dat.h" #include "fns.h" -static int sfd; +static int sfd; -enum -{ - Nhash = 16, - DEBUG = 0 -}; +enum { Nhash = 16, DEBUG = 0 }; -static Fid *fids[Nhash]; +static Fid* fids[Nhash]; -Fid *newfid(int); +Fid* newfid(int); -static Xfid* fsysflush(Xfid*, Fid*); -static Xfid* fsysauth(Xfid*, Fid*); -static Xfid* fsysversion(Xfid*, Fid*); -static Xfid* fsysattach(Xfid*, Fid*); -static Xfid* fsyswalk(Xfid*, Fid*); -static Xfid* fsysopen(Xfid*, Fid*); -static Xfid* fsyscreate(Xfid*, Fid*); -static Xfid* fsysread(Xfid*, Fid*); -static Xfid* fsyswrite(Xfid*, Fid*); -static Xfid* fsysclunk(Xfid*, Fid*); -static Xfid* fsysremove(Xfid*, Fid*); -static Xfid* fsysstat(Xfid*, Fid*); -static Xfid* fsyswstat(Xfid*, Fid*); +static Xfid* fsysflush(Xfid*, Fid*); +static Xfid* fsysauth(Xfid*, Fid*); +static Xfid* fsysversion(Xfid*, Fid*); +static Xfid* fsysattach(Xfid*, Fid*); +static Xfid* fsyswalk(Xfid*, Fid*); +static Xfid* fsysopen(Xfid*, Fid*); +static Xfid* fsyscreate(Xfid*, Fid*); +static Xfid* fsysread(Xfid*, Fid*); +static Xfid* fsyswrite(Xfid*, Fid*); +static Xfid* fsysclunk(Xfid*, Fid*); +static Xfid* fsysremove(Xfid*, Fid*); +static Xfid* fsysstat(Xfid*, Fid*); +static Xfid* fsyswstat(Xfid*, Fid*); -Xfid* (*fcall[Tmax])(Xfid*, Fid*); +Xfid* (*fcall[Tmax])(Xfid*, Fid*); -static void -initfcall(void) -{ - fcall[Tflush] = fsysflush; - fcall[Tversion] = fsysversion; - fcall[Tauth] = fsysauth; - fcall[Tattach] = fsysattach; - fcall[Twalk] = fsyswalk; - fcall[Topen] = fsysopen; - fcall[Tcreate] = fsyscreate; - fcall[Tread] = fsysread; - fcall[Twrite] = fsyswrite; - fcall[Tclunk] = fsysclunk; - fcall[Tremove]= fsysremove; - fcall[Tstat] = fsysstat; - fcall[Twstat] = fsyswstat; +static void initfcall(void) { + fcall[Tflush] = fsysflush; + fcall[Tversion] = fsysversion; + fcall[Tauth] = fsysauth; + fcall[Tattach] = fsysattach; + fcall[Twalk] = fsyswalk; + fcall[Topen] = fsysopen; + fcall[Tcreate] = fsyscreate; + fcall[Tread] = fsysread; + fcall[Twrite] = fsyswrite; + fcall[Tclunk] = fsysclunk; + fcall[Tremove] = fsysremove; + fcall[Tstat] = fsysstat; + fcall[Twstat] = fsyswstat; } char Eperm[] = "permission denied"; char Eexist[] = "file does not exist"; char Enotdir[] = "not a directory"; -Dirtab dirtab[]= -{ - { ".", QTDIR, Qdir, 0500|DMDIR }, - { "acme", QTDIR, Qacme, 0500|DMDIR }, - { "cons", QTFILE, Qcons, 0600 }, - { "consctl", QTFILE, Qconsctl, 0000 }, - { "draw", QTDIR, Qdraw, 0000|DMDIR }, /* to suppress graphics progs started in acme */ - { "editout", QTFILE, Qeditout, 0200 }, - { "index", QTFILE, Qindex, 0400 }, - { "label", QTFILE, Qlabel, 0600 }, - { "log", QTFILE, Qlog, 0400 }, - { "new", QTDIR, Qnew, 0500|DMDIR }, - { nil, } -}; +Dirtab dirtab[] = { + {".", QTDIR, Qdir, 0500 | DMDIR}, + {"acme", QTDIR, Qacme, 0500 | DMDIR}, + {"cons", QTFILE, Qcons, 0600}, + {"consctl", QTFILE, Qconsctl, 0000}, + {"draw", + QTDIR, + Qdraw, + 0000 | DMDIR}, /* to suppress graphics progs started in acme */ + {"editout", QTFILE, Qeditout, 0200}, + {"index", QTFILE, Qindex, 0400}, + {"label", QTFILE, Qlabel, 0600}, + {"log", QTFILE, Qlog, 0400}, + {"new", QTDIR, Qnew, 0500 | DMDIR}, + { + nil, + }}; -Dirtab dirtabw[]= -{ - { ".", QTDIR, Qdir, 0500|DMDIR }, - { "addr", QTFILE, QWaddr, 0600 }, - { "body", QTAPPEND, QWbody, 0600|DMAPPEND }, - { "ctl", QTFILE, QWctl, 0600 }, - { "data", QTFILE, QWdata, 0600 }, - { "editout", QTFILE, QWeditout, 0200 }, - { "errors", QTFILE, QWerrors, 0200 }, - { "event", QTFILE, QWevent, 0600 }, - { "rdsel", QTFILE, QWrdsel, 0400 }, - { "wrsel", QTFILE, QWwrsel, 0200 }, - { "tag", QTAPPEND, QWtag, 0600|DMAPPEND }, - { "xdata", QTFILE, QWxdata, 0600 }, - { nil, } -}; +Dirtab dirtabw[] = { + {".", QTDIR, Qdir, 0500 | DMDIR}, + {"addr", QTFILE, QWaddr, 0600}, + {"body", QTAPPEND, QWbody, 0600 | DMAPPEND}, + {"ctl", QTFILE, QWctl, 0600}, + {"data", QTFILE, QWdata, 0600}, + {"editout", QTFILE, QWeditout, 0200}, + {"errors", QTFILE, QWerrors, 0200}, + {"event", QTFILE, QWevent, 0600}, + {"rdsel", QTFILE, QWrdsel, 0400}, + {"wrsel", QTFILE, QWwrsel, 0200}, + {"tag", QTAPPEND, QWtag, 0600 | DMAPPEND}, + {"xdata", QTFILE, QWxdata, 0600}, + { + nil, + }}; typedef struct Mnt Mnt; -struct Mnt -{ - QLock lk; - int id; - Mntdir *md; +struct Mnt { + QLock lk; + int id; + Mntdir* md; }; -Mnt mnt; +Mnt mnt; -Xfid* respond(Xfid*, Fcall*, char*); -int dostat(int, Dirtab*, uchar*, int, uint); -uint getclock(void); +Xfid* respond(Xfid*, Fcall*, char*); +int dostat(int, Dirtab*, uchar*, int, uint); +uint getclock(void); -char *user = "Wile E. Coyote"; +char* user = "Wile E. Coyote"; static int closing = 0; -int messagesize = Maxblock+IOHDRSZ; /* good start */ +int messagesize = Maxblock + IOHDRSZ; /* good start */ -void fsysproc(void *); +void fsysproc(void*); -void -fsysinit(void) -{ - int p[2]; - char *u; +void fsysinit(void) { + int p[2]; + char* u; - initfcall(); - if(pipe(p) < 0) - error("can't create pipe"); - if(post9pservice(p[0], "acme", mtpt) < 0) - error("can't post service"); - sfd = p[1]; - fmtinstall('F', fcallfmt); - if((u = getuser()) != nil) - user = estrdup(u); - proccreate(fsysproc, nil, STACK); + initfcall(); + if (pipe(p) < 0) + error("can't create pipe"); + if (post9pservice(p[0], "acme", mtpt) < 0) + error("can't post service"); + sfd = p[1]; + fmtinstall('F', fcallfmt); + if ((u = getuser()) != nil) + user = estrdup(u); + proccreate(fsysproc, nil, STACK); } -void -fsysproc(void *v) -{ - int n; - Xfid *x; - Fid *f; - Fcall t; - uchar *buf; +void fsysproc(void* v) { + int n; + Xfid* x; + Fid* f; + Fcall t; + uchar* buf; - threadsetname("fsysproc"); + threadsetname("fsysproc"); - USED(v); - x = nil; - for(;;){ - buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */ - n = read9pmsg(sfd, buf, messagesize); - if(n <= 0){ - if(closing) - break; - error("i/o error on server channel"); - } - if(x == nil){ - sendp(cxfidalloc, nil); - x = recvp(cxfidalloc); - } - x->buf = buf; - if(convM2S(buf, n, &x->fcall) != n) - error("convert error in convM2S"); - if(DEBUG) - fprint(2, "%F\n", &x->fcall); - if(fcall[x->fcall.type] == nil) - x = respond(x, &t, "bad fcall type"); - else{ - switch(x->fcall.type){ - case Tversion: - case Tauth: - case Tflush: - f = nil; - break; - case Tattach: - f = newfid(x->fcall.fid); - break; - default: - f = newfid(x->fcall.fid); - if(!f->busy){ - x->f = f; - x = respond(x, &t, "fid not in use"); - continue; - } - break; - } - x->f = f; - x = (*fcall[x->fcall.type])(x, f); - } - } + USED(v); + x = nil; + for (;;) { + buf = emalloc( + messagesize + + UTFmax); /* overflow for appending partial rune in xfidwrite */ + n = read9pmsg(sfd, buf, messagesize); + if (n <= 0) { + if (closing) + break; + error("i/o error on server channel"); + } + if (x == nil) { + sendp(cxfidalloc, nil); + x = recvp(cxfidalloc); + } + x->buf = buf; + if (convM2S(buf, n, &x->fcall) != n) + error("convert error in convM2S"); + if (DEBUG) + fprint(2, "%F\n", &x->fcall); + if (fcall[x->fcall.type] == nil) + x = respond(x, &t, "bad fcall type"); + else { + switch (x->fcall.type) { + case Tversion: + case Tauth: + case Tflush: + f = nil; + break; + case Tattach: + f = newfid(x->fcall.fid); + break; + default: + f = newfid(x->fcall.fid); + if (!f->busy) { + x->f = f; + x = respond(x, &t, "fid not in use"); + continue; + } + break; + } + x->f = f; + x = (*fcall[x->fcall.type])(x, f); + } + } } -Mntdir* -fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl) -{ - Mntdir *m; - int id; +Mntdir* fsysaddid(Rune* dir, int ndir, Rune** incl, int nincl) { + Mntdir* m; + int id; - qlock(&mnt.lk); - id = ++mnt.id; - m = emalloc(sizeof *m); - m->id = id; - m->dir = dir; - m->ref = 1; /* one for Command, one will be incremented in attach */ - m->ndir = ndir; - m->next = mnt.md; - m->incl = incl; - m->nincl = nincl; - mnt.md = m; - qunlock(&mnt.lk); - return m; + qlock(&mnt.lk); + id = ++mnt.id; + m = emalloc(sizeof *m); + m->id = id; + m->dir = dir; + m->ref = 1; /* one for Command, one will be incremented in attach */ + m->ndir = ndir; + m->next = mnt.md; + m->incl = incl; + m->nincl = nincl; + mnt.md = m; + qunlock(&mnt.lk); + return m; } -void -fsysincid(Mntdir *m) -{ - qlock(&mnt.lk); - m->ref++; - qunlock(&mnt.lk); +void fsysincid(Mntdir* m) { + qlock(&mnt.lk); + m->ref++; + qunlock(&mnt.lk); } -void -fsysdelid(Mntdir *idm) -{ - Mntdir *m, *prev; - int i; - char buf[64]; +void fsysdelid(Mntdir* idm) { + Mntdir *m, *prev; + int i; + char buf[64]; - if(idm == nil) - return; - qlock(&mnt.lk); - if(--idm->ref > 0){ - qunlock(&mnt.lk); - return; - } - prev = nil; - for(m=mnt.md; m; m=m->next){ - if(m == idm){ - if(prev) - prev->next = m->next; - else - mnt.md = m->next; - for(i=0; inincl; i++) - free(m->incl[i]); - free(m->incl); - free(m->dir); - free(m); - qunlock(&mnt.lk); - return; - } - prev = m; - } - qunlock(&mnt.lk); - sprint(buf, "fsysdelid: can't find id %d\n", idm->id); - sendp(cerr, estrdup(buf)); + if (idm == nil) + return; + qlock(&mnt.lk); + if (--idm->ref > 0) { + qunlock(&mnt.lk); + return; + } + prev = nil; + for (m = mnt.md; m; m = m->next) { + if (m == idm) { + if (prev) + prev->next = m->next; + else + mnt.md = m->next; + for (i = 0; i < m->nincl; i++) + free(m->incl[i]); + free(m->incl); + free(m->dir); + free(m); + qunlock(&mnt.lk); + return; + } + prev = m; + } + qunlock(&mnt.lk); + sprint(buf, "fsysdelid: can't find id %d\n", idm->id); + sendp(cerr, estrdup(buf)); } /* * Called only in exec.c:/^run(), from a different FD group */ -Mntdir* -fsysmount(Rune *dir, int ndir, Rune **incl, int nincl) -{ - return fsysaddid(dir, ndir, incl, nincl); +Mntdir* fsysmount(Rune* dir, int ndir, Rune** incl, int nincl) { + return fsysaddid(dir, ndir, incl, nincl); } -void -fsysclose(void) -{ - closing = 1; - /* - * apparently this is not kosher on openbsd. - * perhaps because fsysproc is reading from sfd right now, - * the close hangs indefinitely. - close(sfd); - */ +void fsysclose(void) { + closing = 1; + /* + * apparently this is not kosher on openbsd. + * perhaps because fsysproc is reading from sfd right now, + * the close hangs indefinitely. + close(sfd); + */ } -Xfid* -respond(Xfid *x, Fcall *t, char *err) -{ - int n; +Xfid* respond(Xfid* x, Fcall* t, char* err) { + int n; - if(err){ - t->type = Rerror; - t->ename = err; - }else - t->type = x->fcall.type+1; - t->fid = x->fcall.fid; - t->tag = x->fcall.tag; - if(x->buf == nil) - x->buf = emalloc(messagesize); - n = convS2M(t, x->buf, messagesize); - if(n <= 0) - error("convert error in convS2M"); - if(write(sfd, x->buf, n) != n) - error("write error in respond"); - free(x->buf); - x->buf = nil; - if(DEBUG) - fprint(2, "r: %F\n", t); - return x; + if (err) { + t->type = Rerror; + t->ename = err; + } else + t->type = x->fcall.type + 1; + t->fid = x->fcall.fid; + t->tag = x->fcall.tag; + if (x->buf == nil) + x->buf = emalloc(messagesize); + n = convS2M(t, x->buf, messagesize); + if (n <= 0) + error("convert error in convS2M"); + if (write(sfd, x->buf, n) != n) + error("write error in respond"); + free(x->buf); + x->buf = nil; + if (DEBUG) + fprint(2, "r: %F\n", t); + return x; } -static -Xfid* -fsysversion(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsysversion(Xfid* x, Fid* f) { + Fcall t; - USED(f); - if(x->fcall.msize < 256) - return respond(x, &t, "version: message size too small"); - messagesize = x->fcall.msize; - t.msize = messagesize; - if(strncmp(x->fcall.version, "9P2000", 6) != 0) - return respond(x, &t, "unrecognized 9P version"); - t.version = "9P2000"; - return respond(x, &t, nil); + USED(f); + if (x->fcall.msize < 256) + return respond(x, &t, "version: message size too small"); + messagesize = x->fcall.msize; + t.msize = messagesize; + if (strncmp(x->fcall.version, "9P2000", 6) != 0) + return respond(x, &t, "unrecognized 9P version"); + t.version = "9P2000"; + return respond(x, &t, nil); } -static -Xfid* -fsysauth(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsysauth(Xfid* x, Fid* f) { + Fcall t; - USED(f); - return respond(x, &t, "acme: authentication not required"); + USED(f); + return respond(x, &t, "acme: authentication not required"); } -static -Xfid* -fsysflush(Xfid *x, Fid *f) -{ - USED(f); - sendp(x->c, (void*)xfidflush); - return nil; +static Xfid* fsysflush(Xfid* x, Fid* f) { + USED(f); + sendp(x->c, (void*)xfidflush); + return nil; } -static -Xfid* -fsysattach(Xfid *x, Fid *f) -{ - Fcall t; - int id; - Mntdir *m; - char buf[128]; +static Xfid* fsysattach(Xfid* x, Fid* f) { + Fcall t; + int id; + Mntdir* m; + char buf[128]; - if(strcmp(x->fcall.uname, user) != 0) - return respond(x, &t, Eperm); - f->busy = TRUE; - f->open = FALSE; - f->qid.path = Qdir; - f->qid.type = QTDIR; - f->qid.vers = 0; - f->dir = dirtab; - f->nrpart = 0; - f->w = nil; - t.qid = f->qid; - f->mntdir = nil; - id = atoi(x->fcall.aname); - qlock(&mnt.lk); - for(m=mnt.md; m; m=m->next) - if(m->id == id){ - f->mntdir = m; - m->ref++; - break; - } - if(m == nil && x->fcall.aname[0]){ - snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname); - sendp(cerr, estrdup(buf)); - } - qunlock(&mnt.lk); - return respond(x, &t, nil); + if (strcmp(x->fcall.uname, user) != 0) + return respond(x, &t, Eperm); + f->busy = TRUE; + f->open = FALSE; + f->qid.path = Qdir; + f->qid.type = QTDIR; + f->qid.vers = 0; + f->dir = dirtab; + f->nrpart = 0; + f->w = nil; + t.qid = f->qid; + f->mntdir = nil; + id = atoi(x->fcall.aname); + qlock(&mnt.lk); + for (m = mnt.md; m; m = m->next) + if (m->id == id) { + f->mntdir = m; + m->ref++; + break; + } + if (m == nil && x->fcall.aname[0]) { + snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname); + sendp(cerr, estrdup(buf)); + } + qunlock(&mnt.lk); + return respond(x, &t, nil); } -static -Xfid* -fsyswalk(Xfid *x, Fid *f) -{ - Fcall t; - int c, i, j, id; - Qid q; - uchar type; - ulong path; - Fid *nf; - Dirtab *d, *dir; - Window *w; - char *err; +static Xfid* fsyswalk(Xfid* x, Fid* f) { + Fcall t; + int c, i, j, id; + Qid q; + uchar type; + ulong path; + Fid* nf; + Dirtab *d, *dir; + Window* w; + char* err; - nf = nil; - w = nil; - if(f->open) - return respond(x, &t, "walk of open file"); - if(x->fcall.fid != x->fcall.newfid){ - nf = newfid(x->fcall.newfid); - if(nf->busy) - return respond(x, &t, "newfid already in use"); - nf->busy = TRUE; - nf->open = FALSE; - nf->mntdir = f->mntdir; - if(f->mntdir) - f->mntdir->ref++; - nf->dir = f->dir; - nf->qid = f->qid; - nf->w = f->w; - nf->nrpart = 0; /* not open, so must be zero */ - if(nf->w) - incref(&nf->w->ref); - f = nf; /* walk f */ - } + nf = nil; + w = nil; + if (f->open) + return respond(x, &t, "walk of open file"); + if (x->fcall.fid != x->fcall.newfid) { + nf = newfid(x->fcall.newfid); + if (nf->busy) + return respond(x, &t, "newfid already in use"); + nf->busy = TRUE; + nf->open = FALSE; + nf->mntdir = f->mntdir; + if (f->mntdir) + f->mntdir->ref++; + nf->dir = f->dir; + nf->qid = f->qid; + nf->w = f->w; + nf->nrpart = 0; /* not open, so must be zero */ + if (nf->w) + incref(&nf->w->ref); + f = nf; /* walk f */ + } - t.nwqid = 0; - err = nil; - dir = nil; - id = WIN(f->qid); - q = f->qid; + t.nwqid = 0; + err = nil; + dir = nil; + id = WIN(f->qid); + q = f->qid; - if(x->fcall.nwname > 0){ - for(i=0; ifcall.nwname; i++){ - if((q.type & QTDIR) == 0){ - err = Enotdir; - break; - } + if (x->fcall.nwname > 0) { + for (i = 0; i < x->fcall.nwname; i++) { + if ((q.type & QTDIR) == 0) { + err = Enotdir; + break; + } - if(strcmp(x->fcall.wname[i], "..") == 0){ - type = QTDIR; - path = Qdir; - id = 0; - if(w){ - winclose(w); - w = nil; - } - Accept: - if(i == MAXWELEM){ - err = "name too long"; - break; - } - q.type = type; - q.vers = 0; - q.path = QID(id, path); - t.wqid[t.nwqid++] = q; - continue; - } + if (strcmp(x->fcall.wname[i], "..") == 0) { + type = QTDIR; + path = Qdir; + id = 0; + if (w) { + winclose(w); + w = nil; + } + Accept: + if (i == MAXWELEM) { + err = "name too long"; + break; + } + q.type = type; + q.vers = 0; + q.path = QID(id, path); + t.wqid[t.nwqid++] = q; + continue; + } + + /* is it a numeric name? */ + for (j = 0; (c = x->fcall.wname[i][j]); j++) + if (c < '0' || '9' < c) + goto Regular; + /* yes: it's a directory */ + if (w) /* name has form 27/23; get out before losing w */ + break; + id = atoi(x->fcall.wname[i]); + qlock(&row.lk); + w = lookid(id, FALSE); + if (w == nil) { + qunlock(&row.lk); + break; + } + incref(&w->ref); /* we'll drop reference at end if there's an error */ + path = Qdir; + type = QTDIR; + qunlock(&row.lk); + dir = dirtabw; + goto Accept; - /* is it a numeric name? */ - for(j=0; (c=x->fcall.wname[i][j]); j++) - if(c<'0' || '9'fcall.wname[i]); - qlock(&row.lk); - w = lookid(id, FALSE); - if(w == nil){ - qunlock(&row.lk); - break; - } - incref(&w->ref); /* we'll drop reference at end if there's an error */ - path = Qdir; - type = QTDIR; - qunlock(&row.lk); - dir = dirtabw; - goto Accept; - Regular: - if(strcmp(x->fcall.wname[i], "new") == 0){ - if(w) - error("w set in walk to new"); - sendp(cnewwindow, nil); /* signal newwindowthread */ - w = recvp(cnewwindow); /* receive new window */ - incref(&w->ref); - type = QTDIR; - path = QID(w->id, Qdir); - id = w->id; - dir = dirtabw; - goto Accept; - } + if (strcmp(x->fcall.wname[i], "new") == 0) { + if (w) + error("w set in walk to new"); + sendp(cnewwindow, nil); /* signal newwindowthread */ + w = recvp(cnewwindow); /* receive new window */ + incref(&w->ref); + type = QTDIR; + path = QID(w->id, Qdir); + id = w->id; + dir = dirtabw; + goto Accept; + } - if(id == 0) - d = dirtab; - else - d = dirtabw; - d++; /* skip '.' */ - for(; d->name; d++) - if(strcmp(x->fcall.wname[i], d->name) == 0){ - path = d->qid; - type = d->type; - dir = d; - goto Accept; - } + if (id == 0) + d = dirtab; + else + d = dirtabw; + d++; /* skip '.' */ + for (; d->name; d++) + if (strcmp(x->fcall.wname[i], d->name) == 0) { + path = d->qid; + type = d->type; + dir = d; + goto Accept; + } - break; /* file not found */ - } + break; /* file not found */ + } - if(i==0 && err == nil) - err = Eexist; - } + if (i == 0 && err == nil) + err = Eexist; + } - if(err!=nil || t.nwqidfcall.nwname){ - if(nf){ - nf->busy = FALSE; - fsysdelid(nf->mntdir); - } - }else if(t.nwqid == x->fcall.nwname){ - if(w){ - f->w = w; - w = nil; /* don't drop the reference */ - } - if(dir) - f->dir = dir; - f->qid = q; - } + if (err != nil || t.nwqid < x->fcall.nwname) { + if (nf) { + nf->busy = FALSE; + fsysdelid(nf->mntdir); + } + } else if (t.nwqid == x->fcall.nwname) { + if (w) { + f->w = w; + w = nil; /* don't drop the reference */ + } + if (dir) + f->dir = dir; + f->qid = q; + } - if(w != nil) - winclose(w); + if (w != nil) + winclose(w); - return respond(x, &t, err); + return respond(x, &t, err); } -static -Xfid* -fsysopen(Xfid *x, Fid *f) -{ - Fcall t; - int m; +static Xfid* fsysopen(Xfid* x, Fid* f) { + Fcall t; + int m; - /* can't truncate anything, so just disregard */ - x->fcall.mode &= ~(OTRUNC|OCEXEC); - /* can't execute or remove anything */ - if(x->fcall.mode==OEXEC || (x->fcall.mode&ORCLOSE)) - goto Deny; - switch(x->fcall.mode){ - default: - goto Deny; - case OREAD: - m = 0400; - break; - case OWRITE: - m = 0200; - break; - case ORDWR: - m = 0600; - break; - } - if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m) - goto Deny; + /* can't truncate anything, so just disregard */ + x->fcall.mode &= ~(OTRUNC | OCEXEC); + /* can't execute or remove anything */ + if (x->fcall.mode == OEXEC || (x->fcall.mode & ORCLOSE)) + goto Deny; + switch (x->fcall.mode) { + default: + goto Deny; + case OREAD: + m = 0400; + break; + case OWRITE: + m = 0200; + break; + case ORDWR: + m = 0600; + break; + } + if (((f->dir->perm & ~(DMDIR | DMAPPEND)) & m) != m) + goto Deny; - sendp(x->c, (void*)xfidopen); - return nil; + sendp(x->c, (void*)xfidopen); + return nil; - Deny: - return respond(x, &t, Eperm); +Deny: + return respond(x, &t, Eperm); } -static -Xfid* -fsyscreate(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsyscreate(Xfid* x, Fid* f) { + Fcall t; - USED(f); - return respond(x, &t, Eperm); + USED(f); + return respond(x, &t, Eperm); } -static -int -idcmp(const void *a, const void *b) -{ - return *(int*)a - *(int*)b; +static int idcmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } + +static Xfid* fsysread(Xfid* x, Fid* f) { + Fcall t; + uchar* b; + int i, id, n, o, e, j, k, *ids, nids; + Dirtab *d, dt; + Column* c; + uint clock, len; + char buf[16]; + + if (f->qid.type & QTDIR) { + if (FILE(f->qid) == Qacme) { /* empty dir */ + t.data = nil; + t.count = 0; + respond(x, &t, nil); + return x; + } + o = x->fcall.offset; + e = x->fcall.offset + x->fcall.count; + clock = getclock(); + b = emalloc(messagesize); + id = WIN(f->qid); + n = 0; + if (id > 0) + d = dirtabw; + else + d = dirtab; + d++; /* first entry is '.' */ + for (i = 0; d->name != nil && i < e; i += len) { + len = dostat(WIN(x->f->qid), d, b + n, x->fcall.count - n, clock); + if (len <= BIT16SZ) + break; + if (i >= o) + n += len; + d++; + } + if (id == 0) { + qlock(&row.lk); + nids = 0; + ids = nil; + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (k = 0; k < c->nw; k++) { + ids = realloc(ids, (nids + 1) * sizeof(int)); + ids[nids++] = c->w[k]->id; + } + } + qunlock(&row.lk); + qsort(ids, nids, sizeof ids[0], idcmp); + j = 0; + dt.name = buf; + for (; j < nids && i < e; i += len) { + k = ids[j]; + sprint(dt.name, "%d", k); + dt.qid = QID(k, Qdir); + dt.type = QTDIR; + dt.perm = DMDIR | 0700; + len = dostat(k, &dt, b + n, x->fcall.count - n, clock); + if (len == 0) + break; + if (i >= o) + n += len; + j++; + } + free(ids); + } + t.data = (char*)b; + t.count = n; + respond(x, &t, nil); + free(b); + return x; + } + sendp(x->c, (void*)xfidread); + return nil; } -static -Xfid* -fsysread(Xfid *x, Fid *f) -{ - Fcall t; - uchar *b; - int i, id, n, o, e, j, k, *ids, nids; - Dirtab *d, dt; - Column *c; - uint clock, len; - char buf[16]; - - if(f->qid.type & QTDIR){ - if(FILE(f->qid) == Qacme){ /* empty dir */ - t.data = nil; - t.count = 0; - respond(x, &t, nil); - return x; - } - o = x->fcall.offset; - e = x->fcall.offset+x->fcall.count; - clock = getclock(); - b = emalloc(messagesize); - id = WIN(f->qid); - n = 0; - if(id > 0) - d = dirtabw; - else - d = dirtab; - d++; /* first entry is '.' */ - for(i=0; d->name!=nil && if->qid), d, b+n, x->fcall.count-n, clock); - if(len <= BIT16SZ) - break; - if(i >= o) - n += len; - d++; - } - if(id == 0){ - qlock(&row.lk); - nids = 0; - ids = nil; - for(j=0; jnw; k++){ - ids = realloc(ids, (nids+1)*sizeof(int)); - ids[nids++] = c->w[k]->id; - } - } - qunlock(&row.lk); - qsort(ids, nids, sizeof ids[0], idcmp); - j = 0; - dt.name = buf; - for(; jfcall.count-n, clock); - if(len == 0) - break; - if(i >= o) - n += len; - j++; - } - free(ids); - } - t.data = (char*)b; - t.count = n; - respond(x, &t, nil); - free(b); - return x; - } - sendp(x->c, (void*)xfidread); - return nil; +static Xfid* fsyswrite(Xfid* x, Fid* f) { + USED(f); + sendp(x->c, (void*)xfidwrite); + return nil; } -static -Xfid* -fsyswrite(Xfid *x, Fid *f) -{ - USED(f); - sendp(x->c, (void*)xfidwrite); - return nil; +static Xfid* fsysclunk(Xfid* x, Fid* f) { + fsysdelid(f->mntdir); + sendp(x->c, (void*)xfidclose); + return nil; } -static -Xfid* -fsysclunk(Xfid *x, Fid *f) -{ - fsysdelid(f->mntdir); - sendp(x->c, (void*)xfidclose); - return nil; +static Xfid* fsysremove(Xfid* x, Fid* f) { + Fcall t; + + USED(f); + return respond(x, &t, Eperm); } -static -Xfid* -fsysremove(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsysstat(Xfid* x, Fid* f) { + Fcall t; - USED(f); - return respond(x, &t, Eperm); + t.stat = emalloc(messagesize - IOHDRSZ); + t.nstat = + dostat(WIN(x->f->qid), f->dir, t.stat, messagesize - IOHDRSZ, getclock()); + x = respond(x, &t, nil); + free(t.stat); + return x; } -static -Xfid* -fsysstat(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsyswstat(Xfid* x, Fid* f) { + Fcall t; - t.stat = emalloc(messagesize-IOHDRSZ); - t.nstat = dostat(WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock()); - x = respond(x, &t, nil); - free(t.stat); - return x; + USED(f); + return respond(x, &t, Eperm); } -static -Xfid* -fsyswstat(Xfid *x, Fid *f) -{ - Fcall t; +Fid* newfid(int fid) { + Fid *f, *ff, **fh; - USED(f); - return respond(x, &t, Eperm); + ff = nil; + fh = &fids[fid & (Nhash - 1)]; + for (f = *fh; f; f = f->next) + if (f->fid == fid) + return f; + else if (ff == nil && f->busy == FALSE) + ff = f; + if (ff) { + ff->fid = fid; + return ff; + } + f = emalloc(sizeof *f); + f->fid = fid; + f->next = *fh; + *fh = f; + return f; } -Fid* -newfid(int fid) -{ - Fid *f, *ff, **fh; +uint getclock(void) { return time(0); } - ff = nil; - fh = &fids[fid&(Nhash-1)]; - for(f=*fh; f; f=f->next) - if(f->fid == fid) - return f; - else if(ff==nil && f->busy==FALSE) - ff = f; - if(ff){ - ff->fid = fid; - return ff; - } - f = emalloc(sizeof *f); - f->fid = fid; - f->next = *fh; - *fh = f; - return f; -} - -uint -getclock(void) -{ - return time(0); -} - -int -dostat(int id, Dirtab *dir, uchar *buf, int nbuf, uint clock) -{ - Dir d; - - d.qid.path = QID(id, dir->qid); - d.qid.vers = 0; - d.qid.type = dir->type; - d.mode = dir->perm; - d.length = 0; /* would be nice to do better */ - d.name = dir->name; - d.uid = user; - d.gid = user; - d.muid = user; - d.atime = clock; - d.mtime = clock; - return convD2M(&d, buf, nbuf); +int dostat(int id, Dirtab* dir, uchar* buf, int nbuf, uint clock) { + Dir d; + + d.qid.path = QID(id, dir->qid); + d.qid.vers = 0; + d.qid.type = dir->type; + d.mode = dir->perm; + d.length = 0; /* would be nice to do better */ + d.name = dir->name; + d.uid = user; + d.gid = user; + d.muid = user; + d.atime = clock; + d.mtime = clock; + return convD2M(&d, buf, nbuf); } diff --git a/logf.c b/logf.c index 567b838..50726bd 100644 --- a/logf.c +++ b/logf.c @@ -14,122 +14,114 @@ // State for global log file. typedef struct Log Log; -struct Log -{ - QLock lk; - Rendez r; +struct Log { + QLock lk; + Rendez r; - vlong start; // msg[0] corresponds to 'start' in the global sequence of events - - // queued events (nev=entries in ev, mev=capacity of p) - char **ev; - int nev; - int mev; + vlong start; // msg[0] corresponds to 'start' in the global sequence of events - // open acme/put files that need to read events - Fid **f; - int nf; - int mf; - - // active (blocked) reads waiting for events - Xfid **read; - int nread; - int mread; + // queued events (nev=entries in ev, mev=capacity of p) + char** ev; + int nev; + int mev; + + // open acme/put files that need to read events + Fid** f; + int nf; + int mf; + + // active (blocked) reads waiting for events + Xfid** read; + int nread; + int mread; }; static Log eventlog; -void -xfidlogopen(Xfid *x) -{ - qlock(&eventlog.lk); - if(eventlog.nf >= eventlog.mf) { - eventlog.mf = eventlog.mf*2; - if(eventlog.mf == 0) - eventlog.mf = 8; - eventlog.f = erealloc(eventlog.f, eventlog.mf*sizeof eventlog.f[0]); - } - eventlog.f[eventlog.nf++] = x->f; - x->f->logoff = eventlog.start + eventlog.nev; +void xfidlogopen(Xfid* x) { + qlock(&eventlog.lk); + if (eventlog.nf >= eventlog.mf) { + eventlog.mf = eventlog.mf * 2; + if (eventlog.mf == 0) + eventlog.mf = 8; + eventlog.f = erealloc(eventlog.f, eventlog.mf * sizeof eventlog.f[0]); + } + eventlog.f[eventlog.nf++] = x->f; + x->f->logoff = eventlog.start + eventlog.nev; - qunlock(&eventlog.lk); + qunlock(&eventlog.lk); } -void -xfidlogclose(Xfid *x) -{ - int i; +void xfidlogclose(Xfid* x) { + int i; - qlock(&eventlog.lk); - for(i=0; if) { - eventlog.f[i] = eventlog.f[--eventlog.nf]; - break; - } - } - qunlock(&eventlog.lk); + qlock(&eventlog.lk); + for (i = 0; i < eventlog.nf; i++) { + if (eventlog.f[i] == x->f) { + eventlog.f[i] = eventlog.f[--eventlog.nf]; + break; + } + } + qunlock(&eventlog.lk); } -void -xfidlogread(Xfid *x) -{ - char *p; - int i; - Fcall fc; +void xfidlogread(Xfid* x) { + char* p; + int i; + Fcall fc; - qlock(&eventlog.lk); - if(eventlog.nread >= eventlog.mread) { - eventlog.mread = eventlog.mread*2; - if(eventlog.mread == 0) - eventlog.mread = 8; - eventlog.read = erealloc(eventlog.read, eventlog.mread*sizeof eventlog.read[0]); - } - eventlog.read[eventlog.nread++] = x; - - if(eventlog.r.l == nil) - eventlog.r.l = &eventlog.lk; - x->flushed = FALSE; - while(x->f->logoff >= eventlog.start+eventlog.nev && !x->flushed) - rsleep(&eventlog.r); - - for(i=0; i= eventlog.mread) { + eventlog.mread = eventlog.mread * 2; + if (eventlog.mread == 0) + eventlog.mread = 8; + eventlog.read = + erealloc(eventlog.read, eventlog.mread * sizeof eventlog.read[0]); + } + eventlog.read[eventlog.nread++] = x; - if(x->flushed) { - qunlock(&eventlog.lk); - return; - } + if (eventlog.r.l == nil) + eventlog.r.l = &eventlog.lk; + x->flushed = FALSE; + while (x->f->logoff >= eventlog.start + eventlog.nev && !x->flushed) + rsleep(&eventlog.r); - i = x->f->logoff - eventlog.start; - p = estrdup(eventlog.ev[i]); - x->f->logoff++; - qunlock(&eventlog.lk); + for (i = 0; i < eventlog.nread; i++) { + if (eventlog.read[i] == x) { + eventlog.read[i] = eventlog.read[--eventlog.nread]; + break; + } + } - fc.data = p; - fc.count = strlen(p); - respond(x, &fc, nil); - free(p); + if (x->flushed) { + qunlock(&eventlog.lk); + return; + } + + i = x->f->logoff - eventlog.start; + p = estrdup(eventlog.ev[i]); + x->f->logoff++; + qunlock(&eventlog.lk); + + fc.data = p; + fc.count = strlen(p); + respond(x, &fc, nil); + free(p); } -void -xfidlogflush(Xfid *x) -{ - int i; - Xfid *rx; +void xfidlogflush(Xfid* x) { + int i; + Xfid* rx; - qlock(&eventlog.lk); - for(i=0; ifcall.tag == x->fcall.oldtag) { - rx->flushed = TRUE; - rwakeupall(&eventlog.r); - } - } - qunlock(&eventlog.lk); + qlock(&eventlog.lk); + for (i = 0; i < eventlog.nread; i++) { + rx = eventlog.read[i]; + if (rx->fcall.tag == x->fcall.oldtag) { + rx->flushed = TRUE; + rwakeupall(&eventlog.r); + } + } + qunlock(&eventlog.lk); } /* @@ -153,47 +145,48 @@ xfidlogflush(Xfid *x) * op == "del" for deleted window * - called from winclose */ -void -xfidlog(Window *w, char *op) -{ - int i, n; - vlong min; - File *f; - char *name; +void xfidlog(Window* w, char* op) { + int i, n; + vlong min; + File* f; + char* name; - qlock(&eventlog.lk); - if(eventlog.nev >= eventlog.mev) { - // Remove and free any entries that all readers have read. - min = eventlog.start + eventlog.nev; - for(i=0; i eventlog.f[i]->logoff) - min = eventlog.f[i]->logoff; - } - if(min > eventlog.start) { - n = min - eventlog.start; - for(i=0; i= eventlog.mev) { - eventlog.mev = eventlog.mev*2; - if(eventlog.mev == 0) - eventlog.mev = 8; - eventlog.ev = erealloc(eventlog.ev, eventlog.mev*sizeof eventlog.ev[0]); - } - } - f = w->body.file; - name = runetobyte(f->name, f->nname); - if(name == nil) - name = estrdup(""); - eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name); - free(name); - if(eventlog.r.l == nil) - eventlog.r.l = &eventlog.lk; - rwakeupall(&eventlog.r); - qunlock(&eventlog.lk); + qlock(&eventlog.lk); + if (eventlog.nev >= eventlog.mev) { + // Remove and free any entries that all readers have read. + min = eventlog.start + eventlog.nev; + for (i = 0; i < eventlog.nf; i++) { + if (min > eventlog.f[i]->logoff) + min = eventlog.f[i]->logoff; + } + if (min > eventlog.start) { + n = min - eventlog.start; + for (i = 0; i < n; i++) + free(eventlog.ev[i]); + eventlog.nev -= n; + eventlog.start += n; + memmove( + eventlog.ev, + eventlog.ev + n, + eventlog.nev * sizeof eventlog.ev[0]); + } + + // Otherwise grow. + if (eventlog.nev >= eventlog.mev) { + eventlog.mev = eventlog.mev * 2; + if (eventlog.mev == 0) + eventlog.mev = 8; + eventlog.ev = erealloc(eventlog.ev, eventlog.mev * sizeof eventlog.ev[0]); + } + } + f = w->body.file; + name = runetobyte(f->name, f->nname); + if (name == nil) + name = estrdup(""); + eventlog.ev[eventlog.nev++] = smprint("%d %s %s\n", w->id, op, name); + free(name); + if (eventlog.r.l == nil) + eventlog.r.l = &eventlog.lk; + rwakeupall(&eventlog.r); + qunlock(&eventlog.lk); } diff --git a/look.c b/look.c index 195f430..8b122db 100644 --- a/look.c +++ b/look.c @@ -14,861 +14,882 @@ #include "dat.h" #include "fns.h" -CFid *plumbsendfid; -CFid *plumbeditfid; +CFid* plumbsendfid; +CFid* plumbeditfid; -Window* openfile(Text*, Expand*); +Window* openfile(Text*, Expand*); -int nuntitled; +int nuntitled; -void -plumbthread(void *v) -{ - CFid *fid; - Plumbmsg *m; - Timer *t; +void plumbthread(void* v) { + CFid* fid; + Plumbmsg* m; + Timer* t; - USED(v); - threadsetname("plumbproc"); + USED(v); + threadsetname("plumbproc"); - /* - * Loop so that if plumber is restarted, acme need not be. - */ - for(;;){ - /* - * Connect to plumber. - */ - plumbunmount(); - while((fid = plumbopenfid("edit", OREAD|OCEXEC)) == nil){ - t = timerstart(2000); - recv(t->c, nil); - timerstop(t); - } - plumbeditfid = fid; - plumbsendfid = plumbopenfid("send", OWRITE|OCEXEC); + /* + * Loop so that if plumber is restarted, acme need not be. + */ + for (;;) { + /* + * Connect to plumber. + */ + plumbunmount(); + while ((fid = plumbopenfid("edit", OREAD | OCEXEC)) == nil) { + t = timerstart(2000); + recv(t->c, nil); + timerstop(t); + } + plumbeditfid = fid; + plumbsendfid = plumbopenfid("send", OWRITE | OCEXEC); - /* - * Relay messages. - */ - for(;;){ - m = plumbrecvfid(plumbeditfid); - if(m == nil) - break; - sendp(cplumb, m); - } + /* + * Relay messages. + */ + for (;;) { + m = plumbrecvfid(plumbeditfid); + if (m == nil) + break; + sendp(cplumb, m); + } - /* - * Lost connection. - */ - fid = plumbsendfid; - plumbsendfid = nil; - fsclose(fid); + /* + * Lost connection. + */ + fid = plumbsendfid; + plumbsendfid = nil; + fsclose(fid); - fid = plumbeditfid; - plumbeditfid = nil; - fsclose(fid); - } + fid = plumbeditfid; + plumbeditfid = nil; + fsclose(fid); + } } -void -startplumbing(void) -{ - cplumb = chancreate(sizeof(Plumbmsg*), 0); - chansetname(cplumb, "cplumb"); - threadcreate(plumbthread, nil, STACK); +void startplumbing(void) { + cplumb = chancreate(sizeof(Plumbmsg*), 0); + chansetname(cplumb, "cplumb"); + threadcreate(plumbthread, nil, STACK); } +void look3(Text* t, uint q0, uint q1, int external) { + int n, c, f, expanded; + Text* ct; + Expand e; + Rune* r; + uint p; + Plumbmsg* m; + Runestr dir; + char buf[32]; -void -look3(Text *t, uint q0, uint q1, int external) -{ - int n, c, f, expanded; - Text *ct; - Expand e; - Rune *r; - uint p; - Plumbmsg *m; - Runestr dir; - char buf[32]; + ct = seltext; + if (ct == nil) + seltext = t; + expanded = expand(t, q0, q1, &e); + if (!external && t->w != nil && t->w->nopen[QWevent] > 0) { + /* send alphanumeric expansion to external client */ + if (expanded == FALSE) + return; + f = 0; + if ( + (e.u.at != nil && t->w != nil) || + (e.nname > 0 && lookfile(e.name, e.nname) != nil)) + f = 1; /* acme can do it without loading a file */ + if (q0 != e.q0 || q1 != e.q1) + f |= 2; /* second (post-expand) message follows */ + if (e.nname) + f |= 4; /* it's a file name */ + c = 'l'; + if (t->what == Body) + c = 'L'; + n = q1 - q0; + if (n <= EVENTSIZE) { + r = runemalloc(n); + bufread(&t->file->b, q0, r, n); + winevent(t->w, "%c%d %d %d %d %.*S\n", c, q0, q1, f, n, n, r); + free(r); + } else + winevent(t->w, "%c%d %d %d 0 \n", c, q0, q1, f, n); + if (q0 == e.q0 && q1 == e.q1) + return; + if (e.nname) { + n = e.nname; + if (e.a1 > e.a0) + n += 1 + (e.a1 - e.a0); + r = runemalloc(n); + runemove(r, e.name, e.nname); + if (e.a1 > e.a0) { + r[e.nname] = ':'; + bufread(&e.u.at->file->b, e.a0, r + e.nname + 1, e.a1 - e.a0); + } + } else { + n = e.q1 - e.q0; + r = runemalloc(n); + bufread(&t->file->b, e.q0, r, n); + } + f &= ~2; + if (n <= EVENTSIZE) + winevent(t->w, "%c%d %d %d %d %.*S\n", c, e.q0, e.q1, f, n, n, r); + else + winevent(t->w, "%c%d %d %d 0 \n", c, e.q0, e.q1, f, n); + free(r); + goto Return; + } + if (plumbsendfid != nil) { + /* send whitespace-delimited word to plumber */ + m = emalloc(sizeof(Plumbmsg)); + m->src = estrdup("acme"); + m->dst = nil; + dir = dirname(t, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + if (dir.nr == 0) + m->wdir = estrdup(wdir); + else + m->wdir = runetobyte(dir.r, dir.nr); + free(dir.r); + m->type = estrdup("text"); + m->attr = nil; + buf[0] = '\0'; + if (q1 == q0) { + if (t->q1 > t->q0 && t->q0 <= q0 && q0 <= t->q1) { + q0 = t->q0; + q1 = t->q1; + } else { + p = q0; + while (q0 > 0 && (c = tgetc(t, q0 - 1)) != ' ' && c != '\t' && + c != '\n') + q0--; + while (q1 < t->file->b.nc && (c = tgetc(t, q1)) != ' ' && c != '\t' && + c != '\n') + q1++; + if (q1 == q0) { + plumbfree(m); + goto Return; + } + sprint(buf, "click=%d", p - q0); + m->attr = plumbunpackattr(buf); + } + } + r = runemalloc(q1 - q0); + bufread(&t->file->b, q0, r, q1 - q0); + m->data = runetobyte(r, q1 - q0); + m->ndata = strlen(m->data); + free(r); + if (m->ndata < messagesize - 1024 && plumbsendtofid(plumbsendfid, m) >= 0) { + plumbfree(m); + goto Return; + } + plumbfree(m); + /* plumber failed to match; fall through */ + } - ct = seltext; - if(ct == nil) - seltext = t; - expanded = expand(t, q0, q1, &e); - if(!external && t->w!=nil && t->w->nopen[QWevent]>0){ - /* send alphanumeric expansion to external client */ - if(expanded == FALSE) - return; - f = 0; - if((e.u.at!=nil && t->w!=nil) || (e.nname>0 && lookfile(e.name, e.nname)!=nil)) - f = 1; /* acme can do it without loading a file */ - if(q0!=e.q0 || q1!=e.q1) - f |= 2; /* second (post-expand) message follows */ - if(e.nname) - f |= 4; /* it's a file name */ - c = 'l'; - if(t->what == Body) - c = 'L'; - n = q1-q0; - if(n <= EVENTSIZE){ - r = runemalloc(n); - bufread(&t->file->b, q0, r, n); - winevent(t->w, "%c%d %d %d %d %.*S\n", c, q0, q1, f, n, n, r); - free(r); - }else - winevent(t->w, "%c%d %d %d 0 \n", c, q0, q1, f, n); - if(q0==e.q0 && q1==e.q1) - return; - if(e.nname){ - n = e.nname; - if(e.a1 > e.a0) - n += 1+(e.a1-e.a0); - r = runemalloc(n); - runemove(r, e.name, e.nname); - if(e.a1 > e.a0){ - r[e.nname] = ':'; - bufread(&e.u.at->file->b, e.a0, r+e.nname+1, e.a1-e.a0); - } - }else{ - n = e.q1 - e.q0; - r = runemalloc(n); - bufread(&t->file->b, e.q0, r, n); - } - f &= ~2; - if(n <= EVENTSIZE) - winevent(t->w, "%c%d %d %d %d %.*S\n", c, e.q0, e.q1, f, n, n, r); - else - winevent(t->w, "%c%d %d %d 0 \n", c, e.q0, e.q1, f, n); - free(r); - goto Return; - } - if(plumbsendfid != nil){ - /* send whitespace-delimited word to plumber */ - m = emalloc(sizeof(Plumbmsg)); - m->src = estrdup("acme"); - m->dst = nil; - dir = dirname(t, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - if(dir.nr == 0) - m->wdir = estrdup(wdir); - else - m->wdir = runetobyte(dir.r, dir.nr); - free(dir.r); - m->type = estrdup("text"); - m->attr = nil; - buf[0] = '\0'; - if(q1 == q0){ - if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){ - q0 = t->q0; - q1 = t->q1; - }else{ - p = q0; - while(q0>0 && (c=tgetc(t, q0-1))!=' ' && c!='\t' && c!='\n') - q0--; - while(q1file->b.nc && (c=tgetc(t, q1))!=' ' && c!='\t' && c!='\n') - q1++; - if(q1 == q0){ - plumbfree(m); - goto Return; - } - sprint(buf, "click=%d", p-q0); - m->attr = plumbunpackattr(buf); - } - } - r = runemalloc(q1-q0); - bufread(&t->file->b, q0, r, q1-q0); - m->data = runetobyte(r, q1-q0); - m->ndata = strlen(m->data); - free(r); - if(m->ndata= 0){ - plumbfree(m); - goto Return; - } - plumbfree(m); - /* plumber failed to match; fall through */ - } + /* interpret alphanumeric string ourselves */ + if (expanded == FALSE) + return; + if (e.name || e.u.at) + openfile(t, &e); + else { + if (t->w == nil) + return; + ct = &t->w->body; + if (t->w != ct->w) + winlock(ct->w, 'M'); + if (t == ct) + textsetselect(ct, e.q1, e.q1); + n = e.q1 - e.q0; + r = runemalloc(n); + bufread(&t->file->b, e.q0, r, n); + if (search(ct, r, n) && e.jump) + moveto( + mousectl, + addpt(frptofchar(&ct->fr, ct->fr.p0), Pt(4, ct->fr.font->height - 4))); + if (t->w != ct->w) + winunlock(ct->w); + free(r); + } - /* interpret alphanumeric string ourselves */ - if(expanded == FALSE) - return; - if(e.name || e.u.at) - openfile(t, &e); - else{ - if(t->w == nil) - return; - ct = &t->w->body; - if(t->w != ct->w) - winlock(ct->w, 'M'); - if(t == ct) - textsetselect(ct, e.q1, e.q1); - n = e.q1 - e.q0; - r = runemalloc(n); - bufread(&t->file->b, e.q0, r, n); - if(search(ct, r, n) && e.jump) - moveto(mousectl, addpt(frptofchar(&ct->fr, ct->fr.p0), Pt(4, ct->fr.font->height-4))); - if(t->w != ct->w) - winunlock(ct->w); - free(r); - } - - Return: - free(e.name); - free(e.bname); +Return: + free(e.name); + free(e.bname); } -int -plumbgetc(void *a, uint n) -{ - Rune *r; +int plumbgetc(void* a, uint n) { + Rune* r; - r = a; - if(n>runestrlen(r)) - return 0; - return r[n]; + r = a; + if (n > runestrlen(r)) + return 0; + return r[n]; } -void -plumblook(Plumbmsg *m) -{ - Expand e; - char *addr; +void plumblook(Plumbmsg* m) { + Expand e; + char* addr; - if(m->ndata >= BUFSIZE){ - warning(nil, "insanely long file name (%d bytes) in plumb message (%.32s...)\n", m->ndata, m->data); - return; - } - e.q0 = 0; - e.q1 = 0; - if(m->data[0] == '\0') - return; - e.u.ar = nil; - e.bname = m->data; - e.name = bytetorune(e.bname, &e.nname); - e.jump = TRUE; - e.a0 = 0; - e.a1 = 0; - addr = plumblookup(m->attr, "addr"); - if(addr != nil){ - e.u.ar = bytetorune(addr, &e.a1); - e.agetc = plumbgetc; - } - drawtopwindow(); - openfile(nil, &e); - free(e.name); - free(e.u.at); + if (m->ndata >= BUFSIZE) { + warning( + nil, + "insanely long file name (%d bytes) in plumb message (%.32s...)\n", + m->ndata, + m->data); + return; + } + e.q0 = 0; + e.q1 = 0; + if (m->data[0] == '\0') + return; + e.u.ar = nil; + e.bname = m->data; + e.name = bytetorune(e.bname, &e.nname); + e.jump = TRUE; + e.a0 = 0; + e.a1 = 0; + addr = plumblookup(m->attr, "addr"); + if (addr != nil) { + e.u.ar = bytetorune(addr, &e.a1); + e.agetc = plumbgetc; + } + drawtopwindow(); + openfile(nil, &e); + free(e.name); + free(e.u.at); } -void -plumbshow(Plumbmsg *m) -{ - Window *w; - Rune rb[256], *r; - int nb, nr; - Runestr rs; - char *name, *p, namebuf[16]; +void plumbshow(Plumbmsg* m) { + Window* w; + Rune rb[256], *r; + int nb, nr; + Runestr rs; + char *name, *p, namebuf[16]; - drawtopwindow(); - w = makenewwindow(nil); - name = plumblookup(m->attr, "filename"); - if(name == nil){ - name = namebuf; - nuntitled++; - snprint(namebuf, sizeof namebuf, "Untitled-%d", nuntitled); - } - p = nil; - if(name[0]!='/' && m->wdir!=nil && m->wdir[0]!='\0'){ - nb = strlen(m->wdir) + 1 + strlen(name) + 1; - p = emalloc(nb); - snprint(p, nb, "%s/%s", m->wdir, name); - name = p; - } - cvttorunes(name, strlen(name), rb, &nb, &nr, nil); - free(p); - rs = cleanrname(runestr(rb, nr)); - winsetname(w, rs.r, rs.nr); - r = runemalloc(m->ndata); - cvttorunes(m->data, m->ndata, r, &nb, &nr, nil); - textinsert(&w->body, 0, r, nr, TRUE); - free(r); - w->body.file->mod = FALSE; - w->dirty = FALSE; - winsettag(w); - textscrdraw(&w->body); - textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc); - xfidlog(w, "new"); + drawtopwindow(); + w = makenewwindow(nil); + name = plumblookup(m->attr, "filename"); + if (name == nil) { + name = namebuf; + nuntitled++; + snprint(namebuf, sizeof namebuf, "Untitled-%d", nuntitled); + } + p = nil; + if (name[0] != '/' && m->wdir != nil && m->wdir[0] != '\0') { + nb = strlen(m->wdir) + 1 + strlen(name) + 1; + p = emalloc(nb); + snprint(p, nb, "%s/%s", m->wdir, name); + name = p; + } + cvttorunes(name, strlen(name), rb, &nb, &nr, nil); + free(p); + rs = cleanrname(runestr(rb, nr)); + winsetname(w, rs.r, rs.nr); + r = runemalloc(m->ndata); + cvttorunes(m->data, m->ndata, r, &nb, &nr, nil); + textinsert(&w->body, 0, r, nr, TRUE); + free(r); + w->body.file->mod = FALSE; + w->dirty = FALSE; + winsettag(w); + textscrdraw(&w->body); + textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc); + xfidlog(w, "new"); } -int -search(Text *ct, Rune *r, uint n) -{ - uint q, nb, maxn; - int around; - Rune *s, *b, *c; +int search(Text* ct, Rune* r, uint n) { + uint q, nb, maxn; + int around; + Rune *s, *b, *c; - if(n==0 || n>ct->file->b.nc) - return FALSE; - if(2*n > RBUFSIZE){ - warning(nil, "string too long\n"); - return FALSE; - } - maxn = max(2*n, RBUFSIZE); - s = fbufalloc(); - b = s; - nb = 0; - b[nb] = 0; - around = 0; - q = ct->q1; - for(;;){ - if(q >= ct->file->b.nc){ - q = 0; - around = 1; - nb = 0; - b[nb] = 0; - } - if(nb > 0){ - c = runestrchr(b, r[0]); - if(c == nil){ - q += nb; - nb = 0; - b[nb] = 0; - if(around && q>=ct->q1) - break; - continue; - } - q += (c-b); - nb -= (c-b); - b = c; - } - /* reload if buffer covers neither string nor rest of file */ - if(nbfile->b.nc-q){ - nb = ct->file->b.nc-q; - if(nb >= maxn) - nb = maxn-1; - bufread(&ct->file->b, q, s, nb); - b = s; - b[nb] = '\0'; - } - /* this runeeq is fishy but the null at b[nb] makes it safe */ - if(runeeq(b, n, r, n)==TRUE){ - if(ct->w){ - textshow(ct, q, q+n, 1); - winsettag(ct->w); - }else{ - ct->q0 = q; - ct->q1 = q+n; - } - seltext = ct; - fbuffree(s); - return TRUE; - } - --nb; - b++; - q++; - if(around && q>=ct->q1) - break; - } - fbuffree(s); - return FALSE; + if (n == 0 || n > ct->file->b.nc) + return FALSE; + if (2 * n > RBUFSIZE) { + warning(nil, "string too long\n"); + return FALSE; + } + maxn = max(2 * n, RBUFSIZE); + s = fbufalloc(); + b = s; + nb = 0; + b[nb] = 0; + around = 0; + q = ct->q1; + for (;;) { + if (q >= ct->file->b.nc) { + q = 0; + around = 1; + nb = 0; + b[nb] = 0; + } + if (nb > 0) { + c = runestrchr(b, r[0]); + if (c == nil) { + q += nb; + nb = 0; + b[nb] = 0; + if (around && q >= ct->q1) + break; + continue; + } + q += (c - b); + nb -= (c - b); + b = c; + } + /* reload if buffer covers neither string nor rest of file */ + if (nb < n && nb != ct->file->b.nc - q) { + nb = ct->file->b.nc - q; + if (nb >= maxn) + nb = maxn - 1; + bufread(&ct->file->b, q, s, nb); + b = s; + b[nb] = '\0'; + } + /* this runeeq is fishy but the null at b[nb] makes it safe */ + if (runeeq(b, n, r, n) == TRUE) { + if (ct->w) { + textshow(ct, q, q + n, 1); + winsettag(ct->w); + } else { + ct->q0 = q; + ct->q1 = q + n; + } + seltext = ct; + fbuffree(s); + return TRUE; + } + --nb; + b++; + q++; + if (around && q >= ct->q1) + break; + } + fbuffree(s); + return FALSE; } -int -isfilec(Rune r) -{ - static Rune Lx[] = { '.', '-', '+', '/', ':', 0 }; - if(isalnum(r)) - return TRUE; - if(runestrchr(Lx, r)) - return TRUE; - return FALSE; +int isfilec(Rune r) { + static Rune Lx[] = {'.', '-', '+', '/', ':', 0}; + if (isalnum(r)) + return TRUE; + if (runestrchr(Lx, r)) + return TRUE; + return FALSE; } /* Runestr wrapper for cleanname */ -Runestr -cleanrname(Runestr rs) -{ - char *s; - int nb, nulls; +Runestr cleanrname(Runestr rs) { + char* s; + int nb, nulls; - s = runetobyte(rs.r, rs.nr); - cleanname(s); - cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls); - free(s); - return rs; + s = runetobyte(rs.r, rs.nr); + cleanname(s); + cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls); + free(s); + return rs; } -Runestr -includefile(Rune *dir, Rune *file, int nfile) -{ - int m, n; - char *a; - Rune *r; - static Rune Lslash[] = { '/', 0 }; +Runestr includefile(Rune* dir, Rune* file, int nfile) { + int m, n; + char* a; + Rune* r; + static Rune Lslash[] = {'/', 0}; - m = runestrlen(dir); - a = emalloc((m+1+nfile)*UTFmax+1); - sprint(a, "%S/%.*S", dir, nfile, file); - n = access(a, 0); - free(a); - if(n < 0) - return runestr(nil, 0); - r = runemalloc(m+1+nfile); - runemove(r, dir, m); - runemove(r+m, Lslash, 1); - runemove(r+m+1, file, nfile); - free(file); - return cleanrname(runestr(r, m+1+nfile)); + m = runestrlen(dir); + a = emalloc((m + 1 + nfile) * UTFmax + 1); + sprint(a, "%S/%.*S", dir, nfile, file); + n = access(a, 0); + free(a); + if (n < 0) + return runestr(nil, 0); + r = runemalloc(m + 1 + nfile); + runemove(r, dir, m); + runemove(r + m, Lslash, 1); + runemove(r + m + 1, file, nfile); + free(file); + return cleanrname(runestr(r, m + 1 + nfile)); } -static Rune *objdir; +static Rune* objdir; -Runestr -includename(Text *t, Rune *r, int n) -{ - Window *w; - char buf[128]; - Rune Lsysinclude[] = { '/', 's', 'y', 's', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Rune Lusrinclude[] = { '/', 'u', 's', 'r', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Rune Lusrlocalinclude[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', - '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Rune Lusrlocalplan9include[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l', - '/', 'p', 'l', 'a', 'n', '9', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 }; - Runestr file; - int i; +Runestr includename(Text* t, Rune* r, int n) { + Window* w; + char buf[128]; + Rune Lsysinclude[] = + {'/', 's', 'y', 's', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0}; + Rune Lusrinclude[] = + {'/', 'u', 's', 'r', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0}; + Rune Lusrlocalinclude[] = { + '/', + 'u', + 's', + 'r', + '/', + 'l', + 'o', + 'c', + 'a', + 'l', + '/', + 'i', + 'n', + 'c', + 'l', + 'u', + 'd', + 'e', + 0}; + Rune Lusrlocalplan9include[] = {'/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', + 'l', '/', 'p', 'l', 'a', 'n', '9', '/', 'i', + 'n', 'c', 'l', 'u', 'd', 'e', 0}; + Runestr file; + int i; - if(objdir==nil && objtype!=nil){ - sprint(buf, "/%s/include", objtype); - objdir = bytetorune(buf, &i); - objdir = runerealloc(objdir, i+1); - objdir[i] = '\0'; - } + if (objdir == nil && objtype != nil) { + sprint(buf, "/%s/include", objtype); + objdir = bytetorune(buf, &i); + objdir = runerealloc(objdir, i + 1); + objdir[i] = '\0'; + } - w = t->w; - if(n==0 || r[0]=='/' || w==nil) - goto Rescue; - if(n>2 && r[0]=='.' && r[1]=='/') - goto Rescue; - file.r = nil; - file.nr = 0; - for(i=0; inincl && file.r==nil; i++) - file = includefile(w->incl[i], r, n); + w = t->w; + if (n == 0 || r[0] == '/' || w == nil) + goto Rescue; + if (n > 2 && r[0] == '.' && r[1] == '/') + goto Rescue; + file.r = nil; + file.nr = 0; + for (i = 0; i < w->nincl && file.r == nil; i++) + file = includefile(w->incl[i], r, n); - if(file.r == nil) - file = includefile(Lsysinclude, r, n); - if(file.r == nil) - file = includefile(Lusrlocalplan9include, r, n); - if(file.r == nil) - file = includefile(Lusrlocalinclude, r, n); - if(file.r == nil) - file = includefile(Lusrinclude, r, n); - if(file.r==nil && objdir!=nil) - file = includefile(objdir, r, n); - if(file.r == nil) - goto Rescue; - return file; + if (file.r == nil) + file = includefile(Lsysinclude, r, n); + if (file.r == nil) + file = includefile(Lusrlocalplan9include, r, n); + if (file.r == nil) + file = includefile(Lusrlocalinclude, r, n); + if (file.r == nil) + file = includefile(Lusrinclude, r, n); + if (file.r == nil && objdir != nil) + file = includefile(objdir, r, n); + if (file.r == nil) + goto Rescue; + return file; - Rescue: - return runestr(r, n); +Rescue: + return runestr(r, n); } -Runestr -dirname(Text *t, Rune *r, int n) -{ - Rune *b, c; - uint m, nt; - int slash; - Runestr tmp; +Runestr dirname(Text* t, Rune* r, int n) { + Rune* b; + uint nt; + int slash, i; + Runestr tmp; - b = nil; - if(t==nil || t->w==nil) - goto Rescue; - nt = t->w->tag.file->b.nc; - if(nt == 0) - goto Rescue; - if(n>=1 && r[0]=='/') - goto Rescue; - b = runemalloc(nt+n+1); - bufread(&t->w->tag.file->b, 0, b, nt); - slash = -1; - for(m=0; mw == nil) + goto Rescue; + nt = t->w->tag.file->b.nc; + if (nt == 0) + goto Rescue; + if (n >= 1 && r[0] == '/') + goto Rescue; + b = parsetag(t->w, &i); + slash = -1; + for (i--; i >= 0; i--) { + if (b[i] == '/') { + slash = i; + break; + } + } + if (slash < 0) + goto Rescue; + runemove(b + slash + 1, r, n); + free(r); + return cleanrname(runestr(b, slash + 1 + n)); - Rescue: - free(b); - tmp = runestr(r, n); - if(r) - return cleanrname(tmp); - return tmp; +Rescue: + free(b); + tmp = runestr(r, n); + if (r) + return cleanrname(tmp); + return tmp; } -static int -texthas(Text *t, uint q0, Rune *r) -{ - int i; +static int texthas(Text* t, uint q0, Rune* r) { + int i; - if((int)q0 < 0) - return FALSE; - for(i=0; r[i]; i++) - if(q0+i >= t->file->b.nc || textreadc(t, q0+i) != r[i]) - return FALSE; - return TRUE; + if ((int)q0 < 0) + return FALSE; + for (i = 0; r[i]; i++) + if (q0 + i >= t->file->b.nc || textreadc(t, q0 + i) != r[i]) + return FALSE; + return TRUE; } -int -expandfile(Text *t, uint q0, uint q1, Expand *e) -{ - int i, n, nname, colon, eval; - uint amin, amax; - Rune *r, c; - Window *w; - Runestr rs; - Rune Lhttpcss[] = {'h', 't', 't', 'p', ':', '/', '/', 0}; - Rune Lhttpscss[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 0}; +int expandfile(Text* t, uint q0, uint q1, Expand* e) { + int i, n, nname, colon, eval; + uint amin, amax; + Rune *r, c; + Window* w; + Runestr rs; + Rune Lhttpcss[] = {'h', 't', 't', 'p', ':', '/', '/', 0}; + Rune Lhttpscss[] = {'h', 't', 't', 'p', 's', ':', '/', '/', 0}; - amax = q1; - if(q1 == q0){ - colon = -1; - while(q1file->b.nc && isfilec(c=textreadc(t, q1))){ - if(c == ':' && !texthas(t, q1-4, Lhttpcss) && !texthas(t, q1-5, Lhttpscss)){ - colon = q1; - break; - } - q1++; - } - while(q0>0 && (isfilec(c=textreadc(t, q0-1)) || isaddrc(c) || isregexc(c))){ - q0--; - if(colon<0 && c==':' && !texthas(t, q0-4, Lhttpcss) && !texthas(t, q0-5, Lhttpscss)) - colon = q0; - } - /* - * if it looks like it might begin file: , consume address chars after : - * otherwise terminate expansion at : - */ - if(colon >= 0){ - q1 = colon; - if(colonfile->b.nc-1 && isaddrc(textreadc(t, colon+1))){ - q1 = colon+1; - while(q1file->b.nc && isaddrc(textreadc(t, q1))) - q1++; - } - } - if(q1 > q0) - if(colon >= 0){ /* stop at white space */ - for(amax=colon+1; amaxfile->b.nc; amax++) - if((c=textreadc(t, amax))==' ' || c=='\t' || c=='\n') - break; - }else - amax = t->file->b.nc; - } - amin = amax; - e->q0 = q0; - e->q1 = q1; - n = q1-q0; - if(n == 0) - return FALSE; - /* see if it's a file name */ - r = runemalloc(n+1); - bufread(&t->file->b, q0, r, n); - r[n] = 0; - /* is it a URL? look for http:// and https:// prefix */ - if(runestrncmp(r, Lhttpcss, 7) == 0 || runestrncmp(r, Lhttpscss, 8) == 0){ - // Avoid capturing end-of-sentence punctuation. - if(r[n-1] == '.') { - e->q1--; - n--; - } - e->name = r; - e->nname = n; - e->u.at = t; - e->a0 = e->q1; - e->a1 = e->q1; - return TRUE; - } - /* first, does it have bad chars? */ - nname = -1; - for(i=0; ifile->b.nc && (i==n-1 || isaddrc(textreadc(t, q0+i+1)))) - amin = q0+i; - else - goto Isntfile; - nname = i; - } - } - if(nname == -1) - nname = n; - for(i=0; i, and turn that into an include - * file name if so. Should probably do it for "" too, but that's not - * restrictive enough syntax and checking for a #include earlier on the - * line would be silly. - */ - if(q0>0 && textreadc(t, q0-1)=='<' && q1file->b.nc && textreadc(t, q1)=='>'){ - rs = includename(t, r, nname); - r = rs.r; - nname = rs.nr; - } - else if(amin == q0) - goto Isfile; - else{ - rs = dirname(t, r, nname); - r = rs.r; - nname = rs.nr; - } - e->bname = runetobyte(r, nname); - /* if it's already a window name, it's a file */ - w = lookfile(r, nname); - if(w != nil) - goto Isfile; - /* if it's the name of a file, it's a file */ - if(ismtpt(e->bname) || access(e->bname, 0) < 0){ - free(e->bname); - e->bname = nil; - goto Isntfile; - } + amax = q1; + if (q1 == q0) { + colon = -1; + while (q1 < t->file->b.nc && isfilec(c = textreadc(t, q1))) { + if ( + c == ':' && !texthas(t, q1 - 4, Lhttpcss) && + !texthas(t, q1 - 5, Lhttpscss)) { + colon = q1; + break; + } + q1++; + } + while (q0 > 0 && + (isfilec(c = textreadc(t, q0 - 1)) || isaddrc(c) || isregexc(c))) { + q0--; + if ( + colon < 0 && c == ':' && !texthas(t, q0 - 4, Lhttpcss) && + !texthas(t, q0 - 5, Lhttpscss)) + colon = q0; + } + /* + * if it looks like it might begin file: , consume address chars after : + * otherwise terminate expansion at : + */ + if (colon >= 0) { + q1 = colon; + if (colon < t->file->b.nc - 1 && isaddrc(textreadc(t, colon + 1))) { + q1 = colon + 1; + while (q1 < t->file->b.nc && isaddrc(textreadc(t, q1))) + q1++; + } + } + if (q1 > q0) + if (colon >= 0) { /* stop at white space */ + for (amax = colon + 1; amax < t->file->b.nc; amax++) + if ((c = textreadc(t, amax)) == ' ' || c == '\t' || c == '\n') + break; + } else + amax = t->file->b.nc; + } + amin = amax; + e->q0 = q0; + e->q1 = q1; + n = q1 - q0; + if (n == 0) + return FALSE; + /* see if it's a file name */ + r = runemalloc(n + 1); + bufread(&t->file->b, q0, r, n); + r[n] = 0; + /* is it a URL? look for http:// and https:// prefix */ + if (runestrncmp(r, Lhttpcss, 7) == 0 || runestrncmp(r, Lhttpscss, 8) == 0) { + // Avoid capturing end-of-sentence punctuation. + if (r[n - 1] == '.') { + e->q1--; + n--; + } + e->name = r; + e->nname = n; + e->u.at = t; + e->a0 = e->q1; + e->a1 = e->q1; + return TRUE; + } + /* first, does it have bad chars? */ + nname = -1; + for (i = 0; i < n; i++) { + c = r[i]; + if (c == ':' && nname < 0) { + if ( + q0 + i + 1 < t->file->b.nc && + (i == n - 1 || isaddrc(textreadc(t, q0 + i + 1)))) + amin = q0 + i; + else + goto Isntfile; + nname = i; + } + } + if (nname == -1) + nname = n; + for (i = 0; i < nname; i++) + if (!isfilec(r[i]) && r[i] != ' ') + goto Isntfile; + /* + * See if it's a file name in <>, and turn that into an include + * file name if so. Should probably do it for "" too, but that's not + * restrictive enough syntax and checking for a #include earlier on the + * line would be silly. + */ + if ( + q0 > 0 && textreadc(t, q0 - 1) == '<' && q1 < t->file->b.nc && + textreadc(t, q1) == '>') { + rs = includename(t, r, nname); + r = rs.r; + nname = rs.nr; + } else if (amin == q0) + goto Isfile; + else { + rs = dirname(t, r, nname); + r = rs.r; + nname = rs.nr; + } + e->bname = runetobyte(r, nname); + /* if it's already a window name, it's a file */ + w = lookfile(r, nname); + if (w != nil) + goto Isfile; + /* if it's the name of a file, it's a file */ + if (ismtpt(e->bname) || access(e->bname, 0) < 0) { + free(e->bname); + e->bname = nil; + goto Isntfile; + } - Isfile: - e->name = r; - e->nname = nname; - e->u.at = t; - e->a0 = amin+1; - eval = FALSE; - address(TRUE, nil, range(-1,-1), range(0,0), t, e->a0, amax, tgetc, &eval, (uint*)&e->a1); - return TRUE; +Isfile: + e->name = r; + e->nname = nname; + e->u.at = t; + e->a0 = amin + 1; + eval = FALSE; + address( + TRUE, + nil, + range(-1, -1), + range(0, 0), + t, + e->a0, + amax, + tgetc, + &eval, + (uint*)&e->a1); + return TRUE; - Isntfile: - free(r); - return FALSE; +Isntfile: + free(r); + return FALSE; } -int -expand(Text *t, uint q0, uint q1, Expand *e) -{ - memset(e, 0, sizeof *e); - e->agetc = tgetc; - /* if in selection, choose selection */ - e->jump = TRUE; - if(q1==q0 && t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){ - q0 = t->q0; - q1 = t->q1; - if(t->what == Tag) - e->jump = FALSE; - } +int expand(Text* t, uint q0, uint q1, Expand* e) { + memset(e, 0, sizeof *e); + e->agetc = tgetc; + /* if in selection, choose selection */ + e->jump = TRUE; + if (q1 == q0 && t->q1 > t->q0 && t->q0 <= q0 && q0 <= t->q1) { + q0 = t->q0; + q1 = t->q1; + if (t->what == Tag) + e->jump = FALSE; + } - if(expandfile(t, q0, q1, e)) - return TRUE; + if (expandfile(t, q0, q1, e)) + return TRUE; - if(q0 == q1){ - while(q1file->b.nc && isalnum(textreadc(t, q1))) - q1++; - while(q0>0 && isalnum(textreadc(t, q0-1))) - q0--; - } - e->q0 = q0; - e->q1 = q1; - return q1 > q0; + if (q0 == q1) { + while (q1 < t->file->b.nc && isalnum(textreadc(t, q1))) + q1++; + while (q0 > 0 && isalnum(textreadc(t, q0 - 1))) + q0--; + } + e->q0 = q0; + e->q1 = q1; + return q1 > q0; } -Window* -lookfile(Rune *s, int n) -{ - int i, j, k; - Window *w; - Column *c; - Text *t; +Window* lookfile(Rune* s, int n) { + int i, j, k; + Window* w; + Column* c; + Text* t; - /* avoid terminal slash on directories */ - if(n>1 && s[n-1] == '/') - --n; - for(j=0; jnw; i++){ - w = c->w[i]; - t = &w->body; - k = t->file->nname; - if(k>1 && t->file->name[k-1] == '/') - k--; - if(runeeq(t->file->name, k, s, n)){ - w = w->body.file->curtext->w; - if(w->col != nil) /* protect against race deleting w */ - return w; - } - } - } - return nil; + /* avoid terminal slash on directories */ + if (n > 1 && s[n - 1] == '/') + --n; + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + t = &w->body; + k = t->file->nname; + if (k > 1 && t->file->name[k - 1] == '/') + k--; + if (runeeq(t->file->name, k, s, n)) { + w = w->body.file->curtext->w; + if (w->col != nil) /* protect against race deleting w */ + return w; + } + } + } + return nil; } -Window* -lookid(int id, int dump) -{ - int i, j; - Window *w; - Column *c; +Window* lookid(int id, int dump) { + int i, j; + Window* w; + Column* c; - for(j=0; jnw; i++){ - w = c->w[i]; - if(dump && w->dumpid == id) - return w; - if(!dump && w->id == id) - return w; - } - } - return nil; + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + if (dump && w->dumpid == id) + return w; + if (!dump && w->id == id) + return w; + } + } + return nil; } +Window* openfile(Text* t, Expand* e) { + Range r; + Window *w, *ow; + int eval, i, n; + Rune* rp; + Runestr rs; + uint dummy; -Window* -openfile(Text *t, Expand *e) -{ - Range r; - Window *w, *ow; - int eval, i, n; - Rune *rp; - Runestr rs; - uint dummy; - - r.q0 = 0; - r.q1 = 0; - if(e->nname == 0){ - w = t->w; - if(w == nil) - return nil; - }else{ - w = lookfile(e->name, e->nname); - if(w == nil && e->name[0] != '/'){ - /* - * Unrooted path in new window. - * This can happen if we type a pwd-relative path - * in the topmost tag or the column tags. - * Most of the time plumber takes care of these, - * but plumber might not be running or might not - * be configured to accept plumbed directories. - * Make the name a full path, just like we would if - * opening via the plumber. - */ - n = utflen(wdir)+1+e->nname+1; - rp = runemalloc(n); - runesnprint(rp, n, "%s/%.*S", wdir, e->nname, e->name); - rs = cleanrname(runestr(rp, n-1)); - free(e->name); - e->name = rs.r; - e->nname = rs.nr; - w = lookfile(e->name, e->nname); - } - } - if(w){ - t = &w->body; - if(!t->col->safe && t->fr.maxlines==0) /* window is obscured by full-column window */ - colgrow(t->col, t->col->w[0], 1); - }else{ - ow = nil; - if(t) - ow = t->w; - w = makenewwindow(t); - t = &w->body; - winsetname(w, e->name, e->nname); - if(textload(t, 0, e->bname, 1) >= 0) - t->file->unread = FALSE; - t->file->mod = FALSE; - t->w->dirty = FALSE; - winsettag(t->w); - textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc); - if(ow != nil){ - for(i=ow->nincl; --i>=0; ){ - n = runestrlen(ow->incl[i]); - rp = runemalloc(n); - runemove(rp, ow->incl[i], n); - winaddincl(w, rp, n); - } - for(i=0; i < NINDENT; i++) - w->indent[i] = ow->indent[i]; - }else - for(i=0; i < NINDENT; i++) - w->indent[i] = globalindent[i]; - xfidlog(w, "new"); - } - if(e->a1 == e->a0) - eval = FALSE; - else{ - eval = TRUE; - r = address(TRUE, t, range(-1,-1), range(t->q0, t->q1), e->u.at, e->a0, e->a1, e->agetc, &eval, &dummy); - if(r.q0 > r.q1) { - eval = FALSE; - warning(nil, "addresses out of order\n"); - } - if(eval == FALSE) - e->jump = FALSE; /* don't jump if invalid address */ - } - if(eval == FALSE){ - r.q0 = t->q0; - r.q1 = t->q1; - } - textshow(t, r.q0, r.q1, 1); - winsettag(t->w); - seltext = t; - if(e->jump) - moveto(mousectl, addpt(frptofchar(&t->fr, t->fr.p0), Pt(4, font->height-4))); - return w; + r.q0 = 0; + r.q1 = 0; + if (e->nname == 0) { + w = t->w; + if (w == nil) + return nil; + } else { + w = lookfile(e->name, e->nname); + if (w == nil && e->name[0] != '/') { + /* + * Unrooted path in new window. + * This can happen if we type a pwd-relative path + * in the topmost tag or the column tags. + * Most of the time plumber takes care of these, + * but plumber might not be running or might not + * be configured to accept plumbed directories. + * Make the name a full path, just like we would if + * opening via the plumber. + */ + n = utflen(wdir) + 1 + e->nname + 1; + rp = runemalloc(n); + runesnprint(rp, n, "%s/%.*S", wdir, e->nname, e->name); + rs = cleanrname(runestr(rp, n - 1)); + free(e->name); + e->name = rs.r; + e->nname = rs.nr; + w = lookfile(e->name, e->nname); + } + } + if (w) { + t = &w->body; + if (!t->col->safe && t->fr.maxlines == 0) /* window is obscured by + full-column window */ + colgrow(t->col, t->col->w[0], 1); + } else { + ow = nil; + if (t) + ow = t->w; + w = makenewwindow(t); + t = &w->body; + winsetname(w, e->name, e->nname); + if (textload(t, 0, e->bname, 1) >= 0) + t->file->unread = FALSE; + t->file->mod = FALSE; + t->w->dirty = FALSE; + winsettag(t->w); + textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc); + if (ow != nil) { + for (i = ow->nincl; --i >= 0;) { + n = runestrlen(ow->incl[i]); + rp = runemalloc(n); + runemove(rp, ow->incl[i], n); + winaddincl(w, rp, n); + } + for (i = 0; i < NINDENT; i++) + w->indent[i] = ow->indent[i]; + } else + for (i = 0; i < NINDENT; i++) + w->indent[i] = globalindent[i]; + xfidlog(w, "new"); + } + if (e->a1 == e->a0) + eval = FALSE; + else { + eval = TRUE; + r = address( + TRUE, + t, + range(-1, -1), + range(t->q0, t->q1), + e->u.at, + e->a0, + e->a1, + e->agetc, + &eval, + &dummy); + if (r.q0 > r.q1) { + eval = FALSE; + warning(nil, "addresses out of order\n"); + } + if (eval == FALSE) + e->jump = FALSE; /* don't jump if invalid address */ + } + if (eval == FALSE) { + r.q0 = t->q0; + r.q1 = t->q1; + } + textshow(t, r.q0, r.q1, 1); + winsettag(t->w); + seltext = t; + if (e->jump) + moveto( + mousectl, + addpt(frptofchar(&t->fr, t->fr.p0), Pt(4, font->height - 4))); + return w; } -void -new(Text *et, Text *t, Text *argt, int flag1, int flag2, Rune *arg, int narg) -{ - int ndone; - Rune *a, *f; - int na, nf; - Expand e; - Runestr rs; - Window *w; +void new ( + Text* et, Text* t, Text* argt, int flag1, int flag2, Rune* arg, int narg) { + int ndone; + Rune *a, *f; + int na, nf; + Expand e; + Runestr rs; + Window* w; - getarg(argt, FALSE, TRUE, &a, &na); - if(a){ - new(et, t, nil, flag1, flag2, a, na); - if(narg == 0) - return; - } - /* loop condition: *arg is not a blank */ - for(ndone=0; ; ndone++){ - a = findbl(arg, narg, &na); - if(a == arg){ - if(ndone==0 && et->col!=nil) { - w = coladd(et->col, nil, nil, -1); - winsettag(w); - xfidlog(w, "new"); - } - break; - } - nf = narg-na; - f = runemalloc(nf); - runemove(f, arg, nf); - rs = dirname(et, f, nf); - memset(&e, 0, sizeof e); - e.name = rs.r; - e.nname = rs.nr; - e.bname = runetobyte(rs.r, rs.nr); - e.jump = TRUE; - openfile(et, &e); - free(e.name); - free(e.bname); - arg = skipbl(a, na, &narg); - } + getarg(argt, FALSE, TRUE, &a, &na); + if (a) { + new (et, t, nil, flag1, flag2, a, na); + if (narg == 0) + return; + } + /* loop condition: *arg is not a blank */ + for (ndone = 0;; ndone++) { + a = findbl(arg, narg, &na); + if (a == arg) { + if (ndone == 0 && et->col != nil) { + w = coladd(et->col, nil, nil, -1); + winsettag(w); + xfidlog(w, "new"); + } + break; + } + nf = narg - na; + f = runemalloc(nf); + runemove(f, arg, nf); + rs = dirname(et, f, nf); + memset(&e, 0, sizeof e); + e.name = rs.r; + e.nname = rs.nr; + e.bname = runetobyte(rs.r, rs.nr); + e.jump = TRUE; + openfile(et, &e); + free(e.name); + free(e.bname); + arg = skipbl(a, na, &narg); + } } diff --git a/mail/html.c b/mail/html.c index e3a956b..7e86aee 100644 --- a/mail/html.c +++ b/mail/html.c @@ -7,69 +7,65 @@ #include <9pclient.h> #include "dat.h" -char* -formathtml(char *body, int *np) -{ - int i, j, p[2], q[2]; - Exec *e; - char buf[1024]; - Channel *sync; +char* formathtml(char* body, int* np) { + int i, j, p[2], q[2]; + Exec* e; + char buf[1024]; + Channel* sync; - e = emalloc(sizeof(struct Exec)); - if(pipe(p) < 0 || pipe(q) < 0) - error("can't create pipe: %r"); + e = emalloc(sizeof(struct Exec)); + if (pipe(p) < 0 || pipe(q) < 0) + error("can't create pipe: %r"); - e->p[0] = p[0]; - e->p[1] = p[1]; - e->q[0] = q[0]; - e->q[1] = q[1]; - e->argv = emalloc(3*sizeof(char*)); - e->argv[0] = estrdup("htmlfmt"); - e->argv[1] = estrdup("-cutf-8"); - e->argv[2] = nil; - e->prog = "htmlfmt"; - sync = chancreate(sizeof(int), 0); - e->sync = sync; - proccreate(execproc, e, EXECSTACK); - recvul(sync); - close(p[0]); - close(q[1]); + e->p[0] = p[0]; + e->p[1] = p[1]; + e->q[0] = q[0]; + e->q[1] = q[1]; + e->argv = emalloc(3 * sizeof(char*)); + e->argv[0] = estrdup("htmlfmt"); + e->argv[1] = estrdup("-cutf-8"); + e->argv[2] = nil; + e->prog = "htmlfmt"; + sync = chancreate(sizeof(int), 0); + e->sync = sync; + proccreate(execproc, e, EXECSTACK); + recvul(sync); + close(p[0]); + close(q[1]); - if((i=write(p[1], body, *np)) != *np){ - fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np); - close(p[1]); - close(q[0]); - return body; - } - close(p[1]); + if ((i = write(p[1], body, *np)) != *np) { + fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np); + close(p[1]); + close(q[0]); + return body; + } + close(p[1]); - free(body); - body = nil; - i = 0; - for(;;){ - j = read(q[0], buf, sizeof buf); - if(j <= 0) - break; - body = realloc(body, i+j+1); - if(body == nil) - error("realloc failed: %r"); - memmove(body+i, buf, j); - i += j; - body[i] = '\0'; - } - close(q[0]); + free(body); + body = nil; + i = 0; + for (;;) { + j = read(q[0], buf, sizeof buf); + if (j <= 0) + break; + body = realloc(body, i + j + 1); + if (body == nil) + error("realloc failed: %r"); + memmove(body + i, buf, j); + i += j; + body[i] = '\0'; + } + close(q[0]); - *np = i; - return body; + *np = i; + return body; } -char* -readbody(char *type, char *dir, int *np) -{ - char *body; - - body = readfile(dir, "body", np); - if(body != nil && strcmp(type, "text/html") == 0) - return formathtml(body, np); - return body; +char* readbody(char* type, char* dir, int* np) { + char* body; + + body = readfile(dir, "body", np); + if (body != nil && strcmp(type, "text/html") == 0) + return formathtml(body, np); + return body; } diff --git a/mail/html.o b/mail/html.o deleted file mode 100644 index b9af5f96d81af6002c6e090e953622ea740f5b7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17352 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 diff --git a/mail/mail.c b/mail/mail.c index d79721f..884bbde 100644 --- a/mail/mail.c +++ b/mail/mail.c @@ -7,638 +7,616 @@ #include #include "dat.h" -char *maildir = "Mail/"; /* mountpoint of mail file system */ -char *mboxname = "mbox"; /* mailboxdir/mboxname is mail spool file */ -char *mailboxdir = nil; /* nil == /mail/box/$user */ -char *fsname; /* filesystem for mailboxdir/mboxname is at maildir/fsname */ -char *user; -char *outgoing; -char *srvname; +char* maildir = "Mail/"; /* mountpoint of mail file system */ +char* mboxname = "mbox"; /* mailboxdir/mboxname is mail spool file */ +char* mailboxdir = nil; /* nil == /mail/box/$user */ +char* fsname; /* filesystem for mailboxdir/mboxname is at maildir/fsname */ +char* user; +char* outgoing; +char* srvname; -Window *wbox; -Message mbox; -Message replies; -char *home; -CFid *plumbsendfd; -CFid *plumbseemailfd; -CFid *plumbshowmailfd; -CFid *plumbsendmailfd; -Channel *cplumb; -Channel *cplumbshow; -Channel *cplumbsend; -int wctlfd; -void mainctl(void*); -void plumbproc(void*); -void plumbshowproc(void*); -void plumbsendproc(void*); -void plumbthread(void); -void plumbshowthread(void*); -void plumbsendthread(void*); +Window* wbox; +Message mbox; +Message replies; +char* home; +CFid* plumbsendfd; +CFid* plumbseemailfd; +CFid* plumbshowmailfd; +CFid* plumbsendmailfd; +Channel* cplumb; +Channel* cplumbshow; +Channel* cplumbsend; +int wctlfd; +void mainctl(void*); +void plumbproc(void*); +void plumbshowproc(void*); +void plumbsendproc(void*); +void plumbthread(void); +void plumbshowthread(void*); +void plumbsendthread(void*); -int shortmenu; +int shortmenu; -CFsys *mailfs; -CFsys *acmefs; +CFsys* mailfs; +CFsys* acmefs; -void -usage(void) -{ - fprint(2, "usage: Mail [-sS] [-n srvname] [-o outgoing] [mailboxname [directoryname]]\n"); - threadexitsall("usage"); +void usage(void) { + fprint( + 2, + "usage: Mail [-sS] [-n srvname] [-o outgoing] [mailboxname " + "[directoryname]]\n"); + threadexitsall("usage"); } -void -removeupasfs(void) -{ - char buf[256]; +void removeupasfs(void) { + char buf[256]; - if(strcmp(mboxname, "mbox") == 0) - return; - snprint(buf, sizeof buf, "close %s", mboxname); - fswrite(mbox.ctlfd, buf, strlen(buf)); + if (strcmp(mboxname, "mbox") == 0) + return; + snprint(buf, sizeof buf, "close %s", mboxname); + fswrite(mbox.ctlfd, buf, strlen(buf)); } -int -ismaildir(char *s) -{ - Dir *d; - int ret; +int ismaildir(char* s) { + Dir* d; + int ret; - d = fsdirstat(mailfs, s); - if(d == nil) - return 0; - ret = d->qid.type & QTDIR; - free(d); - return ret; + d = fsdirstat(mailfs, s); + if (d == nil) + return 0; + ret = d->qid.type & QTDIR; + free(d); + return ret; } -void -threadmain(int argc, char *argv[]) -{ - char *s, *name; - char err[ERRMAX], *cmd; - int i, newdir; - Fmt fmt; +void threadmain(int argc, char* argv[]) { + char *s, *name; + char err[ERRMAX], *cmd; + int i, newdir; + Fmt fmt; - doquote = needsrcquote; - quotefmtinstall(); + doquote = needsrcquote; + quotefmtinstall(); - /* open these early so we won't miss notification of new mail messages while we read mbox */ - if((plumbsendfd = plumbopenfid("send", OWRITE|OCEXEC)) == nil) - fprint(2, "warning: open plumb/send: %r\n"); - if((plumbseemailfd = plumbopenfid("seemail", OREAD|OCEXEC)) == nil) - fprint(2, "warning: open plumb/seemail: %r\n"); - if((plumbshowmailfd = plumbopenfid("showmail", OREAD|OCEXEC)) == nil) - fprint(2, "warning: open plumb/showmail: %r\n"); + /* open these early so we won't miss notification of new mail messages while + * we read mbox */ + if ((plumbsendfd = plumbopenfid("send", OWRITE | OCEXEC)) == nil) + fprint(2, "warning: open plumb/send: %r\n"); + if ((plumbseemailfd = plumbopenfid("seemail", OREAD | OCEXEC)) == nil) + fprint(2, "warning: open plumb/seemail: %r\n"); + if ((plumbshowmailfd = plumbopenfid("showmail", OREAD | OCEXEC)) == nil) + fprint(2, "warning: open plumb/showmail: %r\n"); - shortmenu = 0; - srvname = "mail"; - ARGBEGIN{ - case 's': - shortmenu = 1; - break; - case 'S': - shortmenu = 2; - break; - case 'o': - outgoing = EARGF(usage()); - break; - case 'm': - smprint(maildir, "%s/", EARGF(usage())); - break; - case 'n': - srvname = EARGF(usage()); - break; - default: - usage(); - }ARGEND + shortmenu = 0; + srvname = "mail"; + ARGBEGIN { + case 's': + shortmenu = 1; + break; + case 'S': + shortmenu = 2; + break; + case 'o': + outgoing = EARGF(usage()); + break; + case 'm': + smprint(maildir, "%s/", EARGF(usage())); + break; + case 'n': + srvname = EARGF(usage()); + break; + default: + usage(); + } + ARGEND - acmefs = nsmount("acme",nil); - if(acmefs == nil) - error("cannot mount acme: %r"); - mailfs = nsmount(srvname, nil); - if(mailfs == nil) - error("cannot mount %s: %r", srvname); + acmefs = nsmount("acme", nil); + if (acmefs == nil) + error("cannot mount acme: %r"); + mailfs = nsmount(srvname, nil); + if (mailfs == nil) + error("cannot mount %s: %r", srvname); - name = "mbox"; + name = "mbox"; - newdir = 1; - if(argc > 0){ - i = strlen(argv[0]); - if(argc>2 || i==0) - usage(); - /* see if the name is that of an existing /mail/fs directory */ - if(argc==1 && argv[0][0] != '/' && ismaildir(argv[0])){ - name = argv[0]; - mboxname = estrdup(name); - newdir = 0; - }else{ - if(argv[0][i-1] == '/') - argv[0][i-1] = '\0'; - s = strrchr(argv[0], '/'); - if(s == nil) - mboxname = estrdup(argv[0]); - else{ - *s++ = '\0'; - if(*s == '\0') - usage(); - mailboxdir = argv[0]; - mboxname = estrdup(s); - } - if(argc > 1) - name = argv[1]; - else - name = mboxname; - } - } + newdir = 1; + if (argc > 0) { + i = strlen(argv[0]); + if (argc > 2 || i == 0) + usage(); + /* see if the name is that of an existing /mail/fs directory */ + if (argc == 1 && argv[0][0] != '/' && ismaildir(argv[0])) { + name = argv[0]; + mboxname = estrdup(name); + newdir = 0; + } else { + if (argv[0][i - 1] == '/') + argv[0][i - 1] = '\0'; + s = strrchr(argv[0], '/'); + if (s == nil) + mboxname = estrdup(argv[0]); + else { + *s++ = '\0'; + if (*s == '\0') + usage(); + mailboxdir = argv[0]; + mboxname = estrdup(s); + } + if (argc > 1) + name = argv[1]; + else + name = mboxname; + } + } - user = getenv("user"); - if(user == nil) - user = "none"; - home = getenv("home"); - if(home == nil) - home = getenv("HOME"); - if(home == nil) - error("can't find $home"); - if(mailboxdir == nil) - mailboxdir = estrstrdup(home, "/mail"); - if(outgoing == nil) - outgoing = estrstrdup(mailboxdir, "/outgoing"); + user = getenv("user"); + if (user == nil) + user = "none"; + home = getenv("home"); + if (home == nil) + home = getenv("HOME"); + if (home == nil) + error("can't find $home"); + if (mailboxdir == nil) + mailboxdir = estrstrdup(home, "/mail"); + if (outgoing == nil) + outgoing = estrstrdup(mailboxdir, "/outgoing"); - mbox.ctlfd = fsopen(mailfs, estrstrdup(mboxname, "/ctl"), OWRITE); - if(mbox.ctlfd == nil) - error("can't open %s: %r", estrstrdup(mboxname, "/ctl")); + mbox.ctlfd = fsopen(mailfs, estrstrdup(mboxname, "/ctl"), OWRITE); + if (mbox.ctlfd == nil) + error("can't open %s: %r", estrstrdup(mboxname, "/ctl")); - fsname = estrdup(name); - if(newdir && argc > 0){ - s = emalloc(5+strlen(mailboxdir)+strlen(mboxname)+strlen(name)+10+1); - for(i=0; i<10; i++){ - sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname); - if(fswrite(mbox.ctlfd, s, strlen(s)) >= 0) - break; - err[0] = '\0'; - errstr(err, sizeof err); - if(strstr(err, "mbox name in use") == nil) - error("can't create directory %s for mail: %s", name, err); - free(fsname); - fsname = emalloc(strlen(name)+10); - sprint(fsname, "%s-%d", name, i); - } - if(i == 10) - error("can't open %s/%s: %r", mailboxdir, mboxname); - free(s); - } + fsname = estrdup(name); + if (newdir && argc > 0) { + s = emalloc( + 5 + strlen(mailboxdir) + strlen(mboxname) + strlen(name) + 10 + 1); + for (i = 0; i < 10; i++) { + sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname); + if (fswrite(mbox.ctlfd, s, strlen(s)) >= 0) + break; + err[0] = '\0'; + errstr(err, sizeof err); + if (strstr(err, "mbox name in use") == nil) + error("can't create directory %s for mail: %s", name, err); + free(fsname); + fsname = emalloc(strlen(name) + 10); + sprint(fsname, "%s-%d", name, i); + } + if (i == 10) + error("can't open %s/%s: %r", mailboxdir, mboxname); + free(s); + } - s = estrstrdup(fsname, "/"); - mbox.name = estrstrdup(maildir, s); - mbox.level= 0; - readmbox(&mbox, maildir, s); - home = getenv("home"); - if(home == nil) - home = "/"; + s = estrstrdup(fsname, "/"); + mbox.name = estrstrdup(maildir, s); + mbox.level = 0; + readmbox(&mbox, maildir, s); + home = getenv("home"); + if (home == nil) + home = "/"; - wbox = newwindow(); - winname(wbox, mbox.name); - wintagwrite(wbox, "Put Mail Delmesg ", 3+1+4+1+7+1); - threadcreate(mainctl, wbox, STACK); + wbox = newwindow(); + winname(wbox, mbox.name); + wintagwrite(wbox, "Put Mail Delmesg ", 3 + 1 + 4 + 1 + 7 + 1); + threadcreate(mainctl, wbox, STACK); - fmtstrinit(&fmt); - fmtprint(&fmt, "Mail"); - if(shortmenu) - fmtprint(&fmt, " -%c", "sS"[shortmenu-1]); - if(outgoing) - fmtprint(&fmt, " -o %s", outgoing); - fmtprint(&fmt, " %s", name); - cmd = fmtstrflush(&fmt); - if(cmd == nil) - sysfatal("out of memory"); - winsetdump(wbox, "/acme/mail", cmd); - mbox.w = wbox; + fmtstrinit(&fmt); + fmtprint(&fmt, "Mail"); + if (shortmenu) + fmtprint(&fmt, " -%c", "sS"[shortmenu - 1]); + if (outgoing) + fmtprint(&fmt, " -o %s", outgoing); + fmtprint(&fmt, " %s", name); + cmd = fmtstrflush(&fmt); + if (cmd == nil) + sysfatal("out of memory"); + winsetdump(wbox, "/acme/mail", cmd); + mbox.w = wbox; - mesgmenu(wbox, &mbox); - winclean(wbox); + mesgmenu(wbox, &mbox); + winclean(wbox); -/* wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */ - wctlfd = -1; - cplumb = chancreate(sizeof(Plumbmsg*), 0); - cplumbshow = chancreate(sizeof(Plumbmsg*), 0); - if(strcmp(name, "mbox") == 0){ - /* - * Avoid creating multiple windows to send mail by only accepting - * sendmail plumb messages if we're reading the main mailbox. - */ - plumbsendmailfd = plumbopenfid("sendmail", OREAD|OCEXEC); - cplumbsend = chancreate(sizeof(Plumbmsg*), 0); - proccreate(plumbsendproc, nil, STACK); - threadcreate(plumbsendthread, nil, STACK); - } - /* start plumb reader as separate proc ... */ - proccreate(plumbproc, nil, STACK); - proccreate(plumbshowproc, nil, STACK); - threadcreate(plumbshowthread, nil, STACK); - fswrite(mbox.ctlfd, "refresh", 7); - /* ... and use this thread to read the messages */ - plumbthread(); + /* wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */ + wctlfd = -1; + cplumb = chancreate(sizeof(Plumbmsg*), 0); + cplumbshow = chancreate(sizeof(Plumbmsg*), 0); + if (strcmp(name, "mbox") == 0) { + /* + * Avoid creating multiple windows to send mail by only accepting + * sendmail plumb messages if we're reading the main mailbox. + */ + plumbsendmailfd = plumbopenfid("sendmail", OREAD | OCEXEC); + cplumbsend = chancreate(sizeof(Plumbmsg*), 0); + proccreate(plumbsendproc, nil, STACK); + threadcreate(plumbsendthread, nil, STACK); + } + /* start plumb reader as separate proc ... */ + proccreate(plumbproc, nil, STACK); + proccreate(plumbshowproc, nil, STACK); + threadcreate(plumbshowthread, nil, STACK); + fswrite(mbox.ctlfd, "refresh", 7); + /* ... and use this thread to read the messages */ + plumbthread(); } -void -plumbproc(void* v) -{ - Plumbmsg *m; +void plumbproc(void* v) { + Plumbmsg* m; - threadsetname("plumbproc"); - for(;;){ - m = plumbrecvfid(plumbseemailfd); - sendp(cplumb, m); - if(m == nil) - threadexits(nil); - } + threadsetname("plumbproc"); + for (;;) { + m = plumbrecvfid(plumbseemailfd); + sendp(cplumb, m); + if (m == nil) + threadexits(nil); + } } -void -plumbshowproc(void* v) -{ - Plumbmsg *m; +void plumbshowproc(void* v) { + Plumbmsg* m; - threadsetname("plumbshowproc"); - for(;;){ - m = plumbrecvfid(plumbshowmailfd); - sendp(cplumbshow, m); - if(m == nil) - threadexits(nil); - } + threadsetname("plumbshowproc"); + for (;;) { + m = plumbrecvfid(plumbshowmailfd); + sendp(cplumbshow, m); + if (m == nil) + threadexits(nil); + } } -void -plumbsendproc(void* v) -{ - Plumbmsg *m; +void plumbsendproc(void* v) { + Plumbmsg* m; - threadsetname("plumbsendproc"); - for(;;){ - m = plumbrecvfid(plumbsendmailfd); - sendp(cplumbsend, m); - if(m == nil) - threadexits(nil); - } + threadsetname("plumbsendproc"); + for (;;) { + m = plumbrecvfid(plumbsendmailfd); + sendp(cplumbsend, m); + if (m == nil) + threadexits(nil); + } } -void -newmesg(char *name, char *digest) -{ - Dir *d; +void newmesg(char* name, char* digest) { + Dir* d; - if(strncmp(name, mbox.name, strlen(mbox.name)) != 0) - return; /* message is about another mailbox */ - if(mesglookupfile(&mbox, name, digest) != nil) - return; - if(strncmp(name, "Mail/", 5) == 0) - name += 5; - d = fsdirstat(mailfs, name); - if(d == nil) - return; - if(mesgadd(&mbox, mbox.name, d, digest)) - mesgmenunew(wbox, &mbox); - free(d); + if (strncmp(name, mbox.name, strlen(mbox.name)) != 0) + return; /* message is about another mailbox */ + if (mesglookupfile(&mbox, name, digest) != nil) + return; + if (strncmp(name, "Mail/", 5) == 0) + name += 5; + d = fsdirstat(mailfs, name); + if (d == nil) + return; + if (mesgadd(&mbox, mbox.name, d, digest)) + mesgmenunew(wbox, &mbox); + free(d); } -void -showmesg(char *name, char *digest) -{ - char *n; - char *mb; +void showmesg(char* name, char* digest) { + char* n; + char* mb; - mb = mbox.name; - if(strncmp(name, mb, strlen(mb)) != 0) - return; /* message is about another mailbox */ - n = estrdup(name+strlen(mb)); - if(n[strlen(n)-1] != '/') - n = egrow(n, "/", nil); - mesgopen(&mbox, mbox.name, name+strlen(mb), nil, 1, digest); - free(n); + mb = mbox.name; + if (strncmp(name, mb, strlen(mb)) != 0) + return; /* message is about another mailbox */ + n = estrdup(name + strlen(mb)); + if (n[strlen(n) - 1] != '/') + n = egrow(n, "/", nil); + mesgopen(&mbox, mbox.name, name + strlen(mb), nil, 1, digest); + free(n); } -void -delmesg(char *name, char *digest, int dodel, char *save) -{ - Message *m; +void delmesg(char* name, char* digest, int dodel, char* save) { + Message* m; - m = mesglookupfile(&mbox, name, digest); - if(m != nil){ - if(save) - mesgcommand(m, estrstrdup("Save ", save)); - if(dodel) - mesgmenumarkdel(wbox, &mbox, m, 1); - else{ - /* notification came from plumber - message is gone */ - mesgmenudel(wbox, &mbox, m); - if(!m->opened) - mesgdel(&mbox, m); - } - } + m = mesglookupfile(&mbox, name, digest); + if (m != nil) { + if (save) + mesgcommand(m, estrstrdup("Save ", save)); + if (dodel) + mesgmenumarkdel(wbox, &mbox, m, 1); + else { + /* notification came from plumber - message is gone */ + mesgmenudel(wbox, &mbox, m); + if (!m->opened) + mesgdel(&mbox, m); + } + } } -void -plumbthread(void) -{ - Plumbmsg *m; - Plumbattr *a; - char *type, *digest; +void plumbthread(void) { + Plumbmsg* m; + Plumbattr* a; + char *type, *digest; - threadsetname("plumbthread"); - while((m = recvp(cplumb)) != nil){ - a = m->attr; - digest = plumblookup(a, "digest"); - type = plumblookup(a, "mailtype"); - if(type == nil) - fprint(2, "Mail: plumb message with no mailtype attribute\n"); - else if(strcmp(type, "new") == 0) - newmesg(m->data, digest); - else if(strcmp(type, "delete") == 0) - delmesg(m->data, digest, 0, nil); - else - fprint(2, "Mail: unknown plumb attribute %s\n", type); - plumbfree(m); - } - threadexits(nil); + threadsetname("plumbthread"); + while ((m = recvp(cplumb)) != nil) { + a = m->attr; + digest = plumblookup(a, "digest"); + type = plumblookup(a, "mailtype"); + if (type == nil) + fprint(2, "Mail: plumb message with no mailtype attribute\n"); + else if (strcmp(type, "new") == 0) + newmesg(m->data, digest); + else if (strcmp(type, "delete") == 0) + delmesg(m->data, digest, 0, nil); + else + fprint(2, "Mail: unknown plumb attribute %s\n", type); + plumbfree(m); + } + threadexits(nil); } -void -plumbshowthread(void *v) -{ - Plumbmsg *m; +void plumbshowthread(void* v) { + Plumbmsg* m; - USED(v); - threadsetname("plumbshowthread"); - while((m = recvp(cplumbshow)) != nil){ - showmesg(m->data, plumblookup(m->attr, "digest")); - plumbfree(m); - } - threadexits(nil); + USED(v); + threadsetname("plumbshowthread"); + while ((m = recvp(cplumbshow)) != nil) { + showmesg(m->data, plumblookup(m->attr, "digest")); + plumbfree(m); + } + threadexits(nil); } -void -plumbsendthread(void *v) -{ - Plumbmsg *m; +void plumbsendthread(void* v) { + Plumbmsg* m; - USED(v); - threadsetname("plumbsendthread"); - while((m = recvp(cplumbsend)) != nil){ - mkreply(nil, "Mail", m->data, m->attr, nil); - plumbfree(m); - } - threadexits(nil); + USED(v); + threadsetname("plumbsendthread"); + while ((m = recvp(cplumbsend)) != nil) { + mkreply(nil, "Mail", m->data, m->attr, nil); + plumbfree(m); + } + threadexits(nil); } -int -mboxcommand(Window *w, char *s) -{ - char *args[10], **targs, *save; - Window *sbox; - Message *m, *next; - int ok, nargs, i, j; - CFid *searchfd; - char buf[128], *res; +int mboxcommand(Window* w, char* s) { + char *args[10], **targs, *save; + Window* sbox; + Message *m, *next; + int ok, nargs, i, j; + CFid* searchfd; + char buf[128], *res; - nargs = tokenize(s, args, nelem(args)); - if(nargs == 0) - return 0; - if(strcmp(args[0], "Mail") == 0){ - if(nargs == 1) - mkreply(nil, "Mail", "", nil, nil); - else - mkreply(nil, "Mail", args[1], nil, nil); - return 1; - } - if(strcmp(s, "Del") == 0){ - if(mbox.dirty){ - mbox.dirty = 0; - fprint(2, "mail: mailbox not written\n"); - return 1; - } - if(w != mbox.w){ - windel(w, 1); - return 1; - } - ok = 1; - for(m=mbox.head; m!=nil; m=next){ - next = m->next; - if(m->w){ - if(windel(m->w, 0)) - m->w = nil; - else - ok = 0; - } - } - for(m=replies.head; m!=nil; m=next){ - next = m->next; - if(m->w){ - if(windel(m->w, 0)) - m->w = nil; - else - ok = 0; - } - } - if(ok){ - windel(w, 1); - removeupasfs(); - threadexitsall(nil); - } - return 1; - } - if(strcmp(s, "Put") == 0){ - rewritembox(wbox, &mbox); - return 1; - } - if(strcmp(s, "Get") == 0){ - fswrite(mbox.ctlfd, "refresh", 7); - return 1; - } - if(strcmp(s, "Delmesg") == 0){ - save = nil; - if(nargs > 1) - save = args[1]; - s = winselection(w); - if(s == nil) - return 1; - nargs = 1; - for(i=0; s[i]; i++) - if(s[i] == '\n') - nargs++; - targs = emalloc(nargs*sizeof(char*)); /* could be too many for a local array */ - nargs = getfields(s, targs, nargs, 1, "\n"); - for(i=0; inext; + if (m->w) { + if (windel(m->w, 0)) + m->w = nil; + else + ok = 0; + } + } + for (m = replies.head; m != nil; m = next) { + next = m->next; + if (m->w) { + if (windel(m->w, 0)) + m->w = nil; + else + ok = 0; + } + } + if (ok) { + windel(w, 1); + removeupasfs(); + threadexitsall(nil); + } + return 1; + } + if (strcmp(s, "Put") == 0) { + rewritembox(wbox, &mbox); + return 1; + } + if (strcmp(s, "Get") == 0) { + fswrite(mbox.ctlfd, "refresh", 7); + return 1; + } + if (strcmp(s, "Delmesg") == 0) { + save = nil; + if (nargs > 1) + save = args[1]; + s = winselection(w); + if (s == nil) + return 1; + nargs = 1; + for (i = 0; s[i]; i++) + if (s[i] == '\n') + nargs++; + targs = + emalloc(nargs * sizeof(char*)); /* could be too many for a local array */ + nargs = getfields(s, targs, nargs, 1, "\n"); + for (i = 0; i < nargs; i++) { + if (!isdigit(targs[i][0])) + continue; + j = atoi(targs[i]); /* easy way to parse the number! */ + if (j == 0) + continue; + snprint(buf, sizeof buf, "%s%d", mbox.name, j); + delmesg(buf, nil, 1, save); + } + free(s); + free(targs); + return 1; + } + if (strcmp(s, "Search") == 0) { + if (nargs <= 1) + return 1; + s = estrstrdup(mboxname, "/search"); + searchfd = fsopen(mailfs, s, ORDWR); + if (searchfd == nil) + return 1; + save = estrdup(args[1]); + for (i = 2; i < nargs; i++) + save = eappend(save, " ", args[i]); + fswrite(searchfd, save, strlen(save)); + fsseek(searchfd, 0, 0); + j = fsread(searchfd, buf, sizeof buf - 1); + if (j == 0) { + fprint(2, "[%s] search %s: no results found\n", mboxname, save); + fsclose(searchfd); + free(save); + return 1; + } + free(save); + buf[j] = '\0'; + res = estrdup(buf); + j = fsread(searchfd, buf, sizeof buf - 1); + for (; j != 0; j = fsread(searchfd, buf, sizeof buf - 1), buf[j] = '\0') + res = eappend(res, "", buf); + fsclose(searchfd); - sbox = newwindow(); - winname(sbox, s); - free(s); - threadcreate(mainctl, sbox, STACK); - winopenbody(sbox, OWRITE); + sbox = newwindow(); + winname(sbox, s); + free(s); + threadcreate(mainctl, sbox, STACK); + winopenbody(sbox, OWRITE); - /* show results in reverse order */ - m = mbox.tail; - save = nil; - for(s=strrchr(res, ' '); s!=nil || save!=res; s=strrchr(res, ' ')){ - if(s != nil){ - save = s+1; - *s = '\0'; - } - else save = res; - save = estrstrdup(save, "/"); - for(; m && strcmp(save, m->name) != 0; m=m->prev); - free(save); - if(m == nil) - break; - fsprint(sbox->body, "%s%s\n", m->name, info(m, 0, 0)); - m = m->prev; - } - free(res); - winclean(sbox); - winclosebody(sbox); - return 1; - } - return 0; + /* show results in reverse order */ + m = mbox.tail; + save = nil; + for (s = strrchr(res, ' '); s != nil || save != res; + s = strrchr(res, ' ')) { + if (s != nil) { + save = s + 1; + *s = '\0'; + } else + save = res; + save = estrstrdup(save, "/"); + for (; m && strcmp(save, m->name) != 0; m = m->prev) + ; + free(save); + if (m == nil) + break; + fsprint(sbox->body, "%s%s\n", m->name, info(m, 0, 0)); + m = m->prev; + } + free(res); + winclean(sbox); + winclosebody(sbox); + return 1; + } + return 0; } -void -mainctl(void *v) -{ - Window *w; - Event *e, *e2, *eq, *ea; - int na, nopen; - char *s, *t, *buf; +void mainctl(void* v) { + Window* w; + Event *e, *e2, *eq, *ea; + int na, nopen; + char *s, *t, *buf; - w = v; - winincref(w); - proccreate(wineventproc, w, STACK); + w = v; + winincref(w); + proccreate(wineventproc, w, STACK); - for(;;){ - e = recvp(w->cevent); - switch(e->c1){ - default: - Unknown: - print("unknown message %c%c\n", e->c1, e->c2); - break; - - case 'E': /* write to body; can't affect us */ - break; - - case 'F': /* generated by our actions; ignore */ - break; - - case 'K': /* type away; we don't care */ - break; - - case 'M': - switch(e->c2){ - case 'x': - case 'X': - ea = nil; - e2 = nil; - if(e->flag & 2) - e2 = recvp(w->cevent); - if(e->flag & 8){ - ea = recvp(w->cevent); - na = ea->nb; - recvp(w->cevent); - }else - na = 0; - s = e->b; - /* if it's a known command, do it */ - if((e->flag&2) && e->nb==0) - s = e2->b; - if(na){ - t = emalloc(strlen(s)+1+na+1); - sprint(t, "%s %s", s, ea->b); - s = t; - } - /* if it's a long message, it can't be for us anyway */ - if(!mboxcommand(w, s)) /* send it back */ - winwriteevent(w, e); - if(na) - free(s); - break; - - case 'l': - case 'L': - buf = nil; - eq = e; - if(e->flag & 2){ - e2 = recvp(w->cevent); - eq = e2; - } - s = eq->b; - if(eq->q1>eq->q0 && eq->nb==0){ - buf = emalloc((eq->q1-eq->q0)*UTFmax+1); - winread(w, eq->q0, eq->q1, buf); - s = buf; - } - nopen = 0; - do{ - /* skip 'deleted' string if present' */ - if(strncmp(s, deleted, strlen(deleted)) == 0) - s += strlen(deleted); - /* skip mail box name if present */ - if(strncmp(s, mbox.name, strlen(mbox.name)) == 0) - s += strlen(mbox.name); - nopen += mesgopen(&mbox, mbox.name, s, nil, 0, nil); - while(*s!='\0' && *s++!='\n') - ; - }while(*s); - if(nopen == 0) /* send it back */ - winwriteevent(w, e); - free(buf); - break; - - case 'I': /* modify away; we don't care */ - case 'D': - case 'd': - case 'i': - break; - - default: - goto Unknown; - } - } - } + for (;;) { + e = recvp(w->cevent); + switch (e->c1) { + default: + Unknown: + print("unknown message %c%c\n", e->c1, e->c2); + break; + + case 'E': /* write to body; can't affect us */ + break; + + case 'F': /* generated by our actions; ignore */ + break; + + case 'K': /* type away; we don't care */ + break; + + case 'M': + switch (e->c2) { + case 'x': + case 'X': + ea = nil; + e2 = nil; + if (e->flag & 2) + e2 = recvp(w->cevent); + if (e->flag & 8) { + ea = recvp(w->cevent); + na = ea->nb; + recvp(w->cevent); + } else + na = 0; + s = e->b; + /* if it's a known command, do it */ + if ((e->flag & 2) && e->nb == 0) + s = e2->b; + if (na) { + t = emalloc(strlen(s) + 1 + na + 1); + sprint(t, "%s %s", s, ea->b); + s = t; + } + /* if it's a long message, it can't be for us anyway */ + if (!mboxcommand(w, s)) /* send it back */ + winwriteevent(w, e); + if (na) + free(s); + break; + + case 'l': + case 'L': + buf = nil; + eq = e; + if (e->flag & 2) { + e2 = recvp(w->cevent); + eq = e2; + } + s = eq->b; + if (eq->q1 > eq->q0 && eq->nb == 0) { + buf = emalloc((eq->q1 - eq->q0) * UTFmax + 1); + winread(w, eq->q0, eq->q1, buf); + s = buf; + } + nopen = 0; + do { + /* skip 'deleted' string if present' */ + if (strncmp(s, deleted, strlen(deleted)) == 0) + s += strlen(deleted); + /* skip mail box name if present */ + if (strncmp(s, mbox.name, strlen(mbox.name)) == 0) + s += strlen(mbox.name); + nopen += mesgopen(&mbox, mbox.name, s, nil, 0, nil); + while (*s != '\0' && *s++ != '\n') + ; + } while (*s); + if (nopen == 0) /* send it back */ + winwriteevent(w, e); + free(buf); + break; + + case 'I': /* modify away; we don't care */ + case 'D': + case 'd': + case 'i': + break; + + default: + goto Unknown; + } + } + } } - diff --git a/mail/mail.o b/mail/mail.o deleted file mode 100644 index 331d8bdd1dd9cd1824f41bb8775761a4f091f366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65248 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