all repos — acme @ 5540d37849de2cd41ee069643a4a4d83a222bfc8

fork of the acme editor from plan9port - keybinds, tweaks, config.h, etc

add gitignore, clang-format, build script; merge src's patch for spaces in filenames
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmDFna4ACgkQO3+8IhRO
Y5gt+g//QDqhbx9dpOB9Bm3DYMv2qGkX/HbQzcKxYOZw6xX35UirWNZK6wOid0/Z
hGtYmWaqGs1spbgKMnOfYFSvLkFR/wv8TnVSrf4+Se+JntCHrwUrFRpwYzXgzgxR
Rl6ELstzwyG0vLSNhvxkKoOQeLwpdFK0Bbo9tZCVgaClT2n8XoL0RDzvLjJ0q67k
7cs/5aiJ4IBm9igNVa4KIdo1vJNHeS5gjdFOhn9nMpKNePisUXb0ahTjajSLeemD
junZ+Ua1x4/eG1OtuBrM4WvbJ7JAXjC8VrIcCBt+L1jSG1/QfUNeFUdGmAoA5FM4
fyB7QCzMR3EVm0oYwvd7ykoIsk0iisOgzW5rPLmH98ahyH32jzeQ+mcPc258W5vh
Nj6OjabcA36rwEQ9j863bqSJ8xoG5JGDx/1Q0tG5R3jAGpPjG2QH9aO/gdx9+PRY
WiQTJX1QPZipI1W7tAfqoQCKT8fubwSr3tW3x/Rr85G66Xt2G5BACNluC4rbBfK1
P8ip/lz8qMiMeBAQ1tVTnsT1KEZ+TizApjefT03w0J9vEsxclpBuqQ+q+AlYueHO
88PWaRVFuNxFpb4BmMxclPtsHUHBD7Ck67wt/UfNkkLIomKGXNU9alxggQobEBfA
ky+/H6ecCZqD+KxCkCFTle7AHlCrn5JodNtvRNQeKCawFe90oNQ=
=7eoh
-----END PGP SIGNATURE-----
commit

5540d37849de2cd41ee069643a4a4d83a222bfc8

parent

cf57dbe2351443a389786881fff5dc387a972bd4

A .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 +
M .gitignore.gitignore

@@ -1,2 +1,3 @@

**/*.o **/o.* +acme
M acme.cacme.c

@@ -11,403 +11,383 @@ #include <plumb.h>

#include <libsec.h> #include "dat.h" #include "fns.h" - /* for generating syms in mkfile only: */ - #include <bio.h> - #include "edit.h" +/* for generating syms in mkfile only: */ +#include <bio.h> +#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<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); +#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 @@ /* reopen pfd[1] close on exec */

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 = &pm; - 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 = &pm; + 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; 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; + 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; 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); - } + 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 @@

/* 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<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); + 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); } -
M addr.caddr.c

@@ -12,41 +12,29 @@ #include <libsec.h>

#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 @@ // being careful not to walk past the end of the text,

// 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 && 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); + 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'<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; + 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' < 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; }
M buff.cbuff.c

@@ -12,47 +12,37 @@ #include <libsec.h>

#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 @@ * Move cache so b->cq <= q0 < b->cq+b->cnc.

* 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 && 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); + 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; }
A build.sh

@@ -0,0 +1,8 @@

+#!/bin/sh + +clang-format -i ./*.c +clang-format -i ./mail/*.c + +mk + +mv o.acme acme
M cols.ccols.c

@@ -12,575 +12,604 @@ #include <libsec.h>

#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(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); - } + 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; + + /* + * 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); - /* - * 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; + /* + * 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; - /* - * 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); + /* 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; + 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; 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); - } + /* 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; i<c->nw; 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; 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; + 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; i<nr1 && i<nr2; i++){ - if(*r1 != *r2) - return *r1-*r2; - r1++; - r2++; - } - return 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; 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; 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; + 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; i<c->nw; 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; 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); +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; i<c->nw; 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.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); +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; 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; + 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; i<c->nw; 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; }
M disk.cdisk.c

@@ -12,122 +12,107 @@ #include <libsec.h>

#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"); }
M ecmd.cecmd.c

@@ -13,1365 +13,1273 @@ #include "dat.h"

#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; +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; + USED(t); + f = tofile(cp->u.text); + if (nest == 0) + pfilename(f); + curtext = f->curtext; + return TRUE; } -int -B_cmd(Text *t, Cmd *cp) -{ - Rune *list, *r, *s; - int nr; +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; + 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]; +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; + 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; +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; + 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; } -static Rune Lempty[] = { 0 }; -int -f_cmd(Text *t, Cmd *cp) -{ - Rune *name; - String *str; - String empty; +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 = &empty; - }else - str = cp->u.text; - name = cmdname(t->file, str, TRUE); - free(name); - pfilename(t->file); - return TRUE; + if (cp->u.text == nil) { + empty.n = 0; + empty.r = Lempty; + str = &empty; + } 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); -} +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; +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); + 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); } -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 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 -m_cmd(Text *t, Cmd *cp) -{ - Address dot, addr2; +int m_cmd(Text* t, Cmd* cp) { + Address dot, addr2; - 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; + 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 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; +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; 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; + 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; i<nrp; i++){ - f->curtext->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; 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; + 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; i<loopstruct.nw; i++) - cmdexec(&loopstruct.w[i]->body, 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; 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; + 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; }
M edit.cedit.c

@@ -13,672 +13,842 @@ #include "dat.h"

#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; i<f->ntext; 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'<c) /* no number defaults to 1 */ - return sign; - while('0'<=(c=getch()) && c<='9') - n = n*10 + (c-'0'); - ungetch(); - return sign*n; + n = 0; + sign = 1; + if (signok > 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; }
M elog.celog.c

@@ -14,7 +14,7 @@ #include "fns.h"

#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 @@ * Insert and Delete

*/ 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 && 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); + 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 && 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; - } + 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 && 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; +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 < 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 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 < 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 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); -/* 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); - } + /* + * 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; + if (t->w) + t->w->owner = owner; }
M exec.cexec.c

@@ -14,7 +14,7 @@ #include <9pclient.h>

#include "dat.h" #include "fns.h" -Buffer snarfbuf; +Buffer snarfbuf; /* * These functions get called as:

@@ -33,1655 +33,1617 @@ * n: length of s (s is *not* NUL-terminated)

*/ 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(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; - } + 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; 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); + 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; 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); - } - } + 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; 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; + 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; 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"); + 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<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); + 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; 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; + 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; 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); - } - } + 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; 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); + 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; 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); + 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 @@ }

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); }
M file.cfile.c

@@ -23,289 +23,256 @@ * same sequence number represent simultaneous changes.

*/ 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; i<f->ntext; 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; +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); - + /* 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; j<f->ntext; 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<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 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; }
M fns.hfns.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);
M fsys.cfsys.c

@@ -12,738 +12,669 @@ #include <libsec.h>

#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; 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)); + 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; i < x->fcall.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'<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; - 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.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 (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]; +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; + 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* -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; +static Xfid* fsysremove(Xfid* x, Fid* f) { + Fcall t; - USED(f); - return respond(x, &t, Eperm); + USED(f); + return respond(x, &t, Eperm); } -static -Xfid* -fsysstat(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsysstat(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; + 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* -fsyswstat(Xfid *x, Fid *f) -{ - Fcall t; +static Xfid* fsyswstat(Xfid* x, Fid* f) { + Fcall t; - USED(f); - return respond(x, &t, Eperm); + USED(f); + return respond(x, &t, Eperm); } -Fid* -newfid(int fid) -{ - Fid *f, *ff, **fh; +Fid* newfid(int fid) { + Fid *f, *ff, **fh; - 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; + 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); -} +uint getclock(void) { return time(0); } -int -dostat(int id, Dirtab *dir, uchar *buf, int nbuf, uint clock) -{ - Dir d; +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); + 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); }
M logf.clogf.c

@@ -14,122 +14,114 @@ #include "fns.h"

// 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; i<eventlog.nf; i++) { - if(eventlog.f[i] == x->f) { - 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.nread; i++) { - if(eventlog.read[i] == x) { - eventlog.read[i] = eventlog.read[--eventlog.nread]; - break; - } - } + 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.nread; i++) { + if (eventlog.read[i] == x) { + eventlog.read[i] = eventlog.read[--eventlog.nread]; + break; + } + } - if(x->flushed) { - qunlock(&eventlog.lk); - return; - } + if (x->flushed) { + qunlock(&eventlog.lk); + return; + } - i = x->f->logoff - eventlog.start; - p = estrdup(eventlog.ev[i]); - x->f->logoff++; - qunlock(&eventlog.lk); + 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); + 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; i<eventlog.nread; i++) { - rx = eventlog.read[i]; - if(rx->fcall.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 @@ *

* 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.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]); + } - 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); + // 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); }
M look.clook.c

@@ -14,861 +14,882 @@ #include <libsec.h>

#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(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 */ - } + /* 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(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; + 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; i<w->nincl && 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; m<nt; m++){ - c = b[m]; - if(c == '/') - slash = m; - if(c==' ' || c=='\t') - break; - } - if(slash < 0) - goto Rescue; - runemove(b+slash+1, r, n); - free(r); - return cleanrname(runestr(b, slash+1+n)); + 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 = 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(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])) - 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; - } + 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(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; + 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; 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; + /* 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; 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; + 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); + } }
M mail/html.cmail/html.c

@@ -7,69 +7,65 @@ #include <plumb.h>

#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; }
M mail/mail.cmail/mail.c

@@ -7,638 +7,616 @@ #include <plumb.h>

#include <ctype.h> #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; 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); + 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; 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; + } + } + } +}
M mail/mesg.cmail/mesg.c

@@ -7,1418 +7,1362 @@ #include <9pclient.h>

#include <plumb.h> #include "dat.h" -enum -{ - DIRCHUNK = 32*sizeof(Dir) -}; +enum { DIRCHUNK = 32 * sizeof(Dir) }; -char regexchars[] = "\\/[].+?()*^$"; -char deleted[] = "(deleted)-"; -char deletedrx[] = "\\(deleted\\)-"; -char deletedrx01[] = "(\\(deleted\\)-)?"; -char deletedaddr[] = "-#0;/^\\(deleted\\)-/"; +char regexchars[] = "\\/[].+?()*^$"; +char deleted[] = "(deleted)-"; +char deletedrx[] = "\\(deleted\\)-"; +char deletedrx01[] = "(\\(deleted\\)-)?"; +char deletedaddr[] = "-#0;/^\\(deleted\\)-/"; -struct{ - char *type; - char *port; - char *suffix; +struct { + char* type; + char* port; + char* suffix; } ports[] = { - "text/", "edit", ".txt", /* must be first for plumbport() */ - "image/gif", "image", ".gif", - "image/jpeg", "image", ".jpg", - "image/jpeg", "image", ".jpeg", - "image/png", "image", ".png", - "application/postscript", "postscript", ".ps", - "application/pdf", "postscript", ".pdf", - "application/msword", "msword", ".doc", - "application/rtf", "msword", ".rtf", - nil, nil -}; + "text/", + "edit", + ".txt", /* must be first for plumbport() */ + "image/gif", + "image", + ".gif", + "image/jpeg", + "image", + ".jpg", + "image/jpeg", + "image", + ".jpeg", + "image/png", + "image", + ".png", + "application/postscript", + "postscript", + ".ps", + "application/pdf", + "postscript", + ".pdf", + "application/msword", + "msword", + ".doc", + "application/rtf", + "msword", + ".rtf", + nil, + nil}; -char *goodtypes[] = { - "text", - "text/plain", - "message/rfc822", - "text/richtext", - "text/tab-separated-values", - "application/octet-stream", - nil -}; +char* goodtypes[] = { + "text", + "text/plain", + "message/rfc822", + "text/richtext", + "text/tab-separated-values", + "application/octet-stream", + nil}; -char *okheaders[] = -{ - "From:", - "Date:", - "To:", - "CC:", - "Subject:", - nil -}; +char* okheaders[] = {"From:", "Date:", "To:", "CC:", "Subject:", nil}; -char *extraheaders[] = -{ - "Resent-From:", - "Resent-To:", - "Sort:", - nil -}; +char* extraheaders[] = {"Resent-From:", "Resent-To:", "Sort:", nil}; -char* -line(char *data, char **pp) -{ - char *p, *q; +char* line(char* data, char** pp) { + char *p, *q; - for(p=data; *p!='\0' && *p!='\n'; p++) - ; - if(*p == '\n') - *pp = p+1; - else - *pp = p; - q = emalloc(p-data + 1); - memmove(q, data, p-data); - return q; + for (p = data; *p != '\0' && *p != '\n'; p++) + ; + if (*p == '\n') + *pp = p + 1; + else + *pp = p; + q = emalloc(p - data + 1); + memmove(q, data, p - data); + return q; } -static char* -mkaddrs(char *t, char **colon) -{ - int i, nf, inquote; - char **f, *s; - Fmt fmt; - - inquote = 0; - nf = 2; - for(s=t; *s; s++){ - if(*s == '\'') - inquote = !inquote; - if(*s == ' ' && !inquote) - nf++; - } - f = emalloc(nf*sizeof f[0]); - nf = tokenize(t, f, nf); - if(colon){ - fmtstrinit(&fmt); - for(i=0; i+1<nf; i+=2){ - if(i > 0) - fmtprint(&fmt, ", "); - if(f[i][0] == 0 || strcmp(f[i], f[i+1]) == 0) - fmtprint(&fmt, "%s", f[i+1]); - else - fmtprint(&fmt, "%s <%s>", f[i], f[i+1]); - } - *colon = fmtstrflush(&fmt); - } - fmtstrinit(&fmt); - for(i=0; i+1<nf; i+=2){ - if(i > 0) - fmtprint(&fmt, ", "); - fmtprint(&fmt, "%s", f[i+1]); - } - free(f); - return fmtstrflush(&fmt); +static char* mkaddrs(char* t, char** colon) { + int i, nf, inquote; + char **f, *s; + Fmt fmt; + + inquote = 0; + nf = 2; + for (s = t; *s; s++) { + if (*s == '\'') + inquote = !inquote; + if (*s == ' ' && !inquote) + nf++; + } + f = emalloc(nf * sizeof f[0]); + nf = tokenize(t, f, nf); + if (colon) { + fmtstrinit(&fmt); + for (i = 0; i + 1 < nf; i += 2) { + if (i > 0) + fmtprint(&fmt, ", "); + if (f[i][0] == 0 || strcmp(f[i], f[i + 1]) == 0) + fmtprint(&fmt, "%s", f[i + 1]); + else + fmtprint(&fmt, "%s <%s>", f[i], f[i + 1]); + } + *colon = fmtstrflush(&fmt); + } + fmtstrinit(&fmt); + for (i = 0; i + 1 < nf; i += 2) { + if (i > 0) + fmtprint(&fmt, ", "); + fmtprint(&fmt, "%s", f[i + 1]); + } + free(f); + return fmtstrflush(&fmt); } -int -loadinfo(Message *m, char *dir) -{ - int n; - char *data, *p, *s, *t; +int loadinfo(Message* m, char* dir) { + int n; + char *data, *p, *s, *t; + + data = readfile(dir, "info", &n); + if (data == nil) + return 0; - data = readfile(dir, "info", &n); - if(data == nil) - return 0; - - p = data; - while((s = line(p, &p)) != nil && *s != 0){ - t = strchr(s, ' '); - if(t == nil) - continue; - *t++ = 0; - if(strcmp(s, "from") == 0){ - free(m->from); - m->from = mkaddrs(t, &m->fromcolon); - }else if(strcmp(s, "sender") == 0){ - free(m->sender); - m->sender = mkaddrs(t, nil); - }else if(strcmp(s, "to") == 0){ - free(m->to); - m->to = mkaddrs(t, nil); - }else if(strcmp(s, "cc") == 0){ - free(m->cc); - m->cc = mkaddrs(t, nil); - }else if(strcmp(s, "replyto") == 0){ - free(m->replyto); - m->replyto = mkaddrs(t, nil); - }else if(strcmp(s, "subject") == 0){ - free(m->subject); - m->subject = estrdup(t); - }else if(strcmp(s, "type") == 0){ - free(m->type); - m->type = estrdup(t); - }else if(strcmp(s, "unixdate") == 0 && (t=strchr(t, ' ')) != nil){ - free(m->date); - m->date = estrdup(t+1); - }else if(strcmp(s, "digest") == 0){ - free(m->digest); - m->digest = estrdup(t); - }else if(strcmp(s, "filename") == 0){ - free(m->filename); - m->filename = estrdup(t); - } - free(s); - } - free(s); - free(data); - if(m->replyto == nil){ - if(m->sender) - m->replyto = estrdup(m->sender); - else if(m->from) - m->replyto = estrdup(m->from); - else - m->replyto = estrdup(""); - } - if(m->from == nil) - m->from = estrdup(""); - if(m->to == nil) - m->to = estrdup(""); - if(m->cc == nil) - m->cc = estrdup(""); - if(m->subject == nil) - m->subject = estrdup(""); - if(m->type == nil) - m->type = estrdup(""); - if(m->date == nil) - m->date = estrdup(""); - if(m->disposition == nil) - m->disposition = estrdup(""); - if(m->filename == nil) - m->filename = estrdup(""); - if(m->digest == nil) - m->digest = estrdup(""); - return 1; + p = data; + while ((s = line(p, &p)) != nil && *s != 0) { + t = strchr(s, ' '); + if (t == nil) + continue; + *t++ = 0; + if (strcmp(s, "from") == 0) { + free(m->from); + m->from = mkaddrs(t, &m->fromcolon); + } else if (strcmp(s, "sender") == 0) { + free(m->sender); + m->sender = mkaddrs(t, nil); + } else if (strcmp(s, "to") == 0) { + free(m->to); + m->to = mkaddrs(t, nil); + } else if (strcmp(s, "cc") == 0) { + free(m->cc); + m->cc = mkaddrs(t, nil); + } else if (strcmp(s, "replyto") == 0) { + free(m->replyto); + m->replyto = mkaddrs(t, nil); + } else if (strcmp(s, "subject") == 0) { + free(m->subject); + m->subject = estrdup(t); + } else if (strcmp(s, "type") == 0) { + free(m->type); + m->type = estrdup(t); + } else if (strcmp(s, "unixdate") == 0 && (t = strchr(t, ' ')) != nil) { + free(m->date); + m->date = estrdup(t + 1); + } else if (strcmp(s, "digest") == 0) { + free(m->digest); + m->digest = estrdup(t); + } else if (strcmp(s, "filename") == 0) { + free(m->filename); + m->filename = estrdup(t); + } + free(s); + } + free(s); + free(data); + if (m->replyto == nil) { + if (m->sender) + m->replyto = estrdup(m->sender); + else if (m->from) + m->replyto = estrdup(m->from); + else + m->replyto = estrdup(""); + } + if (m->from == nil) + m->from = estrdup(""); + if (m->to == nil) + m->to = estrdup(""); + if (m->cc == nil) + m->cc = estrdup(""); + if (m->subject == nil) + m->subject = estrdup(""); + if (m->type == nil) + m->type = estrdup(""); + if (m->date == nil) + m->date = estrdup(""); + if (m->disposition == nil) + m->disposition = estrdup(""); + if (m->filename == nil) + m->filename = estrdup(""); + if (m->digest == nil) + m->digest = estrdup(""); + return 1; } -int -isnumeric(char *s) -{ - while(*s){ - if(!isdigit(*s)) - return 0; - s++; - } - return 1; +int isnumeric(char* s) { + while (*s) { + if (!isdigit(*s)) + return 0; + s++; + } + return 1; } -CFid* -mailopen(char *name, int mode) -{ - if(strncmp(name, "Mail/", 5) != 0) - return nil; - return fsopen(mailfs, name+5, mode); +CFid* mailopen(char* name, int mode) { + if (strncmp(name, "Mail/", 5) != 0) + return nil; + return fsopen(mailfs, name + 5, mode); } -Dir* -loaddir(char *name, int *np) -{ - CFid *fid; - Dir *dp; +Dir* loaddir(char* name, int* np) { + CFid* fid; + Dir* dp; - fid = mailopen(name, OREAD); - if(fid == nil) - return nil; - *np = fsdirreadall(fid, &dp); - fsclose(fid); - return dp; + fid = mailopen(name, OREAD); + if (fid == nil) + return nil; + *np = fsdirreadall(fid, &dp); + fsclose(fid); + return dp; } -void -readmbox(Message *mbox, char *dir, char *subdir) -{ - char *name; - Dir *d, *dirp; - int i, n; +void readmbox(Message* mbox, char* dir, char* subdir) { + char* name; + Dir *d, *dirp; + int i, n; - name = estrstrdup(dir, subdir); - dirp = loaddir(name, &n); - mbox->recursed = 1; - if(dirp) - for(i=0; i<n; i++){ - d = &dirp[i]; - if(isnumeric(d->name)) - mesgadd(mbox, name, d, nil); - } - free(dirp); - free(name); + name = estrstrdup(dir, subdir); + dirp = loaddir(name, &n); + mbox->recursed = 1; + if (dirp) + for (i = 0; i < n; i++) { + d = &dirp[i]; + if (isnumeric(d->name)) + mesgadd(mbox, name, d, nil); + } + free(dirp); + free(name); } /* add message to box, in increasing numerical order */ -int -mesgadd(Message *mbox, char *dir, Dir *d, char *digest) -{ - Message *m; - char *name; - int loaded; +int mesgadd(Message* mbox, char* dir, Dir* d, char* digest) { + Message* m; + char* name; + int loaded; - m = emalloc(sizeof(Message)); - m->name = estrstrdup(d->name, "/"); - m->next = nil; - m->prev = mbox->tail; - m->level= mbox->level+1; - m->recursed = 0; - name = estrstrdup(dir, m->name); - loaded = loadinfo(m, name); - free(name); - /* if two upas/fs are running, we can get misled, so check digest before accepting message */ - if(loaded==0 || (digest!=nil && m->digest!=nil && strcmp(digest, m->digest)!=0)){ - mesgfreeparts(m); - free(m); - return 0; - } - if(mbox->tail != nil) - mbox->tail->next = m; - mbox->tail = m; - if(mbox->head == nil) - mbox->head = m; + m = emalloc(sizeof(Message)); + m->name = estrstrdup(d->name, "/"); + m->next = nil; + m->prev = mbox->tail; + m->level = mbox->level + 1; + m->recursed = 0; + name = estrstrdup(dir, m->name); + loaded = loadinfo(m, name); + free(name); + /* if two upas/fs are running, we can get misled, so check digest before + * accepting message */ + if ( + loaded == 0 || + (digest != nil && m->digest != nil && strcmp(digest, m->digest) != 0)) { + mesgfreeparts(m); + free(m); + return 0; + } + if (mbox->tail != nil) + mbox->tail->next = m; + mbox->tail = m; + if (mbox->head == nil) + mbox->head = m; - if (m->level != 1){ - m->recursed = 1; - readmbox(m, dir, m->name); - } - return 1; + if (m->level != 1) { + m->recursed = 1; + readmbox(m, dir, m->name); + } + return 1; } -int -thisyear(char *year) -{ - static char now[10]; - char *s; +int thisyear(char* year) { + static char now[10]; + char* s; - if(now[0] == '\0'){ - s = ctime(time(nil)); - strcpy(now, s+24); - } - return strncmp(year, now, 4) == 0; + if (now[0] == '\0') { + s = ctime(time(nil)); + strcpy(now, s + 24); + } + return strncmp(year, now, 4) == 0; } -char* -stripdate(char *as) -{ - int n; - char *s, *fld[10]; +char* stripdate(char* as) { + int n; + char *s, *fld[10]; - as = estrdup(as); - s = estrdup(as); - n = tokenize(s, fld, 10); - if(n > 5){ - sprint(as, "%.3s ", fld[0]); /* day */ - /* some dates have 19 Apr, some Apr 19 */ - if(strlen(fld[1])<4 && isnumeric(fld[1])) - sprint(as+strlen(as), "%.3s %.3s ", fld[1], fld[2]); /* date, month */ - else - sprint(as+strlen(as), "%.3s %.3s ", fld[2], fld[1]); /* date, month */ - /* do we use time or year? depends on whether year matches this one */ - if(thisyear(fld[5])){ - if(strchr(fld[3], ':') != nil) - sprint(as+strlen(as), "%.5s ", fld[3]); /* time */ - else if(strchr(fld[4], ':') != nil) - sprint(as+strlen(as), "%.5s ", fld[4]); /* time */ - }else - sprint(as+strlen(as), "%.4s ", fld[5]); /* year */ - } - free(s); - return as; + as = estrdup(as); + s = estrdup(as); + n = tokenize(s, fld, 10); + if (n > 5) { + sprint(as, "%.3s ", fld[0]); /* day */ + /* some dates have 19 Apr, some Apr 19 */ + if (strlen(fld[1]) < 4 && isnumeric(fld[1])) + sprint(as + strlen(as), "%.3s %.3s ", fld[1], fld[2]); /* date, month */ + else + sprint(as + strlen(as), "%.3s %.3s ", fld[2], fld[1]); /* date, month */ + /* do we use time or year? depends on whether year matches this one */ + if (thisyear(fld[5])) { + if (strchr(fld[3], ':') != nil) + sprint(as + strlen(as), "%.5s ", fld[3]); /* time */ + else if (strchr(fld[4], ':') != nil) + sprint(as + strlen(as), "%.5s ", fld[4]); /* time */ + } else + sprint(as + strlen(as), "%.4s ", fld[5]); /* year */ + } + free(s); + return as; } -char* -readfile(char *dir, char *name, int *np) -{ - char *file, *data; - int len; - Dir *d; - CFid *fid; - char buf[1]; +char* readfile(char* dir, char* name, int* np) { + char *file, *data; + int len; + Dir* d; + CFid* fid; + char buf[1]; - if(np != nil) - *np = 0; - file = estrstrdup(dir, name); - fid = mailopen(file, OREAD); - if(fid == nil) - return nil; - d = fsdirfstat(fid); - if(d && d->length == 0){ - /* some files, e.g. body, are not loaded until we read them */ - fsread(fid, buf, 1); - fsseek(fid, 0, 0); - free(d); - d = fsdirfstat(fid); - } - free(file); - len = 0; - if(d != nil) - len = d->length; - free(d); - data = emalloc(len+1); - len = fsreadn(fid, data, len); - if(len <= 0){ - fsclose(fid); - free(data); - return nil; - } - fsclose(fid); - if(np != nil) - *np = len; - return data; + if (np != nil) + *np = 0; + file = estrstrdup(dir, name); + fid = mailopen(file, OREAD); + if (fid == nil) + return nil; + d = fsdirfstat(fid); + if (d && d->length == 0) { + /* some files, e.g. body, are not loaded until we read them */ + fsread(fid, buf, 1); + fsseek(fid, 0, 0); + free(d); + d = fsdirfstat(fid); + } + free(file); + len = 0; + if (d != nil) + len = d->length; + free(d); + data = emalloc(len + 1); + len = fsreadn(fid, data, len); + if (len <= 0) { + fsclose(fid); + free(data); + return nil; + } + fsclose(fid); + if (np != nil) + *np = len; + return data; } -char* -info(Message *m, int ind, int ogf) -{ - char *i; - int j, len, lens; - char *p; - char fmt[80], s[80]; +char* info(Message* m, int ind, int ogf) { + char* i; + int j, len, lens; + char* p; + char fmt[80], s[80]; - if (ogf) - p=m->to; - else - p=m->fromcolon; + if (ogf) + p = m->to; + else + p = m->fromcolon; - if(ind==0 && shortmenu){ - len = 30; - lens = 30; - if(shortmenu > 1){ - len = 10; - lens = 25; - } - if(ind==0 && m->subject[0]=='\0'){ - snprint(fmt, sizeof fmt, " %%-%d.%ds", len, len); - snprint(s, sizeof s, fmt, p); - }else{ - snprint(fmt, sizeof fmt, " %%-%d.%ds %%-%d.%ds", len, len, lens, lens); - snprint(s, sizeof s, fmt, p, m->subject); - } - i = estrdup(s); + if (ind == 0 && shortmenu) { + len = 30; + lens = 30; + if (shortmenu > 1) { + len = 10; + lens = 25; + } + if (ind == 0 && m->subject[0] == '\0') { + snprint(fmt, sizeof fmt, " %%-%d.%ds", len, len); + snprint(s, sizeof s, fmt, p); + } else { + snprint(fmt, sizeof fmt, " %%-%d.%ds %%-%d.%ds", len, len, lens, lens); + snprint(s, sizeof s, fmt, p, m->subject); + } + i = estrdup(s); - return i; - } + return i; + } - i = estrdup(""); - i = eappend(i, "\t", p); - i = egrow(i, "\t", stripdate(m->date)); - if(ind == 0){ - if(strcmp(m->type, "text")!=0 && strncmp(m->type, "text/", 5)!=0 && - strncmp(m->type, "multipart/", 10)!=0) - i = egrow(i, "\t(", estrstrdup(m->type, ")")); - }else if(strncmp(m->type, "multipart/", 10) != 0) - i = egrow(i, "\t(", estrstrdup(m->type, ")")); - if(m->subject[0] != '\0'){ - i = eappend(i, "\n", nil); - for(j=0; j<ind; j++) - i = eappend(i, "\t", nil); - i = eappend(i, "\t", m->subject); - } - return i; + i = estrdup(""); + i = eappend(i, "\t", p); + i = egrow(i, "\t", stripdate(m->date)); + if (ind == 0) { + if ( + strcmp(m->type, "text") != 0 && strncmp(m->type, "text/", 5) != 0 && + strncmp(m->type, "multipart/", 10) != 0) + i = egrow(i, "\t(", estrstrdup(m->type, ")")); + } else if (strncmp(m->type, "multipart/", 10) != 0) + i = egrow(i, "\t(", estrstrdup(m->type, ")")); + if (m->subject[0] != '\0') { + i = eappend(i, "\n", nil); + for (j = 0; j < ind; j++) + i = eappend(i, "\t", nil); + i = eappend(i, "\t", m->subject); + } + return i; } -void -mesgmenu0(Window *w, Message *mbox, char *realdir, char *dir, int ind, CFid *fd, int onlyone, int dotail) -{ - int i; - Message *m; - char *name, *tmp; - int ogf=0; +void mesgmenu0( + Window* w, Message* mbox, char* realdir, char* dir, int ind, CFid* fd, + int onlyone, int dotail) { + int i; + Message* m; + char *name, *tmp; + int ogf = 0; - if(strstr(realdir, "outgoing") != nil) - ogf=1; + if (strstr(realdir, "outgoing") != nil) + ogf = 1; - /* show mail box in reverse order, pieces in forward order */ - if(ind > 0) - m = mbox->head; - else - m = mbox->tail; - while(m != nil){ - for(i=0; i<ind; i++) - fsprint(fd, "\t"); - if(ind != 0) - fsprint(fd, " "); - name = estrstrdup(dir, m->name); - tmp = info(m, ind, ogf); - fsprint(fd, "%s%s\n", name, tmp); - free(tmp); - if(dotail && m->tail) - mesgmenu0(w, m, realdir, name, ind+1, fd, 0, dotail); - free(name); - if(ind) - m = m->next; - else - m = m->prev; - if(onlyone) - m = nil; - } + /* show mail box in reverse order, pieces in forward order */ + if (ind > 0) + m = mbox->head; + else + m = mbox->tail; + while (m != nil) { + for (i = 0; i < ind; i++) + fsprint(fd, "\t"); + if (ind != 0) + fsprint(fd, " "); + name = estrstrdup(dir, m->name); + tmp = info(m, ind, ogf); + fsprint(fd, "%s%s\n", name, tmp); + free(tmp); + if (dotail && m->tail) + mesgmenu0(w, m, realdir, name, ind + 1, fd, 0, dotail); + free(name); + if (ind) + m = m->next; + else + m = m->prev; + if (onlyone) + m = nil; + } } -void -mesgmenu(Window *w, Message *mbox) -{ - winopenbody(w, OWRITE); - mesgmenu0(w, mbox, mbox->name, "", 0, w->body, 0, !shortmenu); - winclosebody(w); +void mesgmenu(Window* w, Message* mbox) { + winopenbody(w, OWRITE); + mesgmenu0(w, mbox, mbox->name, "", 0, w->body, 0, !shortmenu); + winclosebody(w); } /* one new message has arrived, as mbox->tail */ -void -mesgmenunew(Window *w, Message *mbox) -{ - Biobuf *b; +void mesgmenunew(Window* w, Message* mbox) { + Biobuf* b; - winselect(w, "0", 0); - w->data = winopenfile(w, "data"); - b = emalloc(sizeof(Biobuf)); - mesgmenu0(w, mbox, mbox->name, "", 0, w->data, 1, !shortmenu); - free(b); - if(!mbox->dirty) - winclean(w); - /* select tag line plus following indented lines, but not final newline (it's distinctive) */ - winselect(w, "0/.*\\n((\t.*\\n)*\t.*)?/", 1); - fsclose(w->addr); - fsclose(w->data); - w->addr = nil; - w->data = nil; + winselect(w, "0", 0); + w->data = winopenfile(w, "data"); + b = emalloc(sizeof(Biobuf)); + mesgmenu0(w, mbox, mbox->name, "", 0, w->data, 1, !shortmenu); + free(b); + if (!mbox->dirty) + winclean(w); + /* select tag line plus following indented lines, but not final newline (it's + * distinctive) */ + winselect(w, "0/.*\\n((\t.*\\n)*\t.*)?/", 1); + fsclose(w->addr); + fsclose(w->data); + w->addr = nil; + w->data = nil; } -char* -name2regexp(char *prefix, char *s) -{ - char *buf, *p, *q; +char* name2regexp(char* prefix, char* s) { + char *buf, *p, *q; - buf = emalloc(strlen(prefix)+2*strlen(s)+50); /* leave room to append more */ - p = buf; - *p++ = '0'; - *p++ = '/'; - *p++ = '^'; - strcpy(p, prefix); - p += strlen(prefix); - for(q=s; *q!='\0'; q++){ - if(strchr(regexchars, *q) != nil) - *p++ = '\\'; - *p++ = *q; - } - *p++ = '/'; - *p = '\0'; - return buf; + buf = emalloc( + strlen(prefix) + 2 * strlen(s) + 50); /* leave room to append more */ + p = buf; + *p++ = '0'; + *p++ = '/'; + *p++ = '^'; + strcpy(p, prefix); + p += strlen(prefix); + for (q = s; *q != '\0'; q++) { + if (strchr(regexchars, *q) != nil) + *p++ = '\\'; + *p++ = *q; + } + *p++ = '/'; + *p = '\0'; + return buf; } -void -mesgmenumarkdel(Window *w, Message *mbox, Message *m, int writeback) -{ - char *buf; - +void mesgmenumarkdel(Window* w, Message* mbox, Message* m, int writeback) { + char* buf; - if(m->deleted) - return; - m->writebackdel = writeback; - if(w->data == nil) - w->data = winopenfile(w, "data"); - buf = name2regexp("", m->name); - strcat(buf, "-#0"); - if(winselect(w, buf, 1)) - fswrite(w->data, deleted, 10); - free(buf); - fsclose(w->data); - fsclose(w->addr); - w->addr = nil; - w->data = nil; - mbox->dirty = 1; - m->deleted = 1; + if (m->deleted) + return; + m->writebackdel = writeback; + if (w->data == nil) + w->data = winopenfile(w, "data"); + buf = name2regexp("", m->name); + strcat(buf, "-#0"); + if (winselect(w, buf, 1)) + fswrite(w->data, deleted, 10); + free(buf); + fsclose(w->data); + fsclose(w->addr); + w->addr = nil; + w->data = nil; + mbox->dirty = 1; + m->deleted = 1; } -void -mesgmenumarkundel(Window *w, Message *v, Message *m) -{ - char *buf; +void mesgmenumarkundel(Window* w, Message* v, Message* m) { + char* buf; - USED(v); - if(m->deleted == 0) - return; - if(w->data == nil) - w->data = winopenfile(w, "data"); - buf = name2regexp(deletedrx, m->name); - if(winselect(w, buf, 1)) - if(winsetaddr(w, deletedaddr, 1)) - fswrite(w->data, "", 0); - free(buf); - fsclose(w->data); - fsclose(w->addr); - w->addr = nil; - w->data = nil; - m->deleted = 0; + USED(v); + if (m->deleted == 0) + return; + if (w->data == nil) + w->data = winopenfile(w, "data"); + buf = name2regexp(deletedrx, m->name); + if (winselect(w, buf, 1)) + if (winsetaddr(w, deletedaddr, 1)) + fswrite(w->data, "", 0); + free(buf); + fsclose(w->data); + fsclose(w->addr); + w->addr = nil; + w->data = nil; + m->deleted = 0; } -void -mesgmenudel(Window *w, Message *mbox, Message *m) -{ - char *buf; +void mesgmenudel(Window* w, Message* mbox, Message* m) { + char* buf; - if(w->data ==nil) - w->data = winopenfile(w, "data"); - buf = name2regexp(deletedrx01, m->name); - if(winsetaddr(w, buf, 1) && winsetaddr(w, ".,./.*\\n(\t.*\\n)*/", 1)) - fswrite(w->data, "", 0); - free(buf); - fsclose(w->data); - fsclose(w->addr); - w->addr = nil; - w->data = nil; -/* assume caller knows best mbox->dirty = 1; */ - m->deleted = 1; + if (w->data == nil) + w->data = winopenfile(w, "data"); + buf = name2regexp(deletedrx01, m->name); + if (winsetaddr(w, buf, 1) && winsetaddr(w, ".,./.*\\n(\t.*\\n)*/", 1)) + fswrite(w->data, "", 0); + free(buf); + fsclose(w->data); + fsclose(w->addr); + w->addr = nil; + w->data = nil; + /* assume caller knows best mbox->dirty = 1; */ + m->deleted = 1; } -void -mesgmenumark(Window *w, char *which, char *mark) -{ - char *buf; +void mesgmenumark(Window* w, char* which, char* mark) { + char* buf; - if(w->data == nil) - w->data = winopenfile(w, "data"); - buf = name2regexp(deletedrx01, which); - if(winsetaddr(w, buf, 1) && winsetaddr(w, "+0-#1", 1)) /* go to end of line */ - fswrite(w->data, mark, strlen(mark)); - free(buf); - fsclose(w->data); - fsclose(w->addr); - w->addr = nil; - w->data = nil; - if(!mbox.dirty) - winclean(w); + if (w->data == nil) + w->data = winopenfile(w, "data"); + buf = name2regexp(deletedrx01, which); + if (winsetaddr(w, buf, 1) && winsetaddr(w, "+0-#1", 1)) /* go to end of line + */ + fswrite(w->data, mark, strlen(mark)); + free(buf); + fsclose(w->data); + fsclose(w->addr); + w->addr = nil; + w->data = nil; + if (!mbox.dirty) + winclean(w); } -void -mesgfreeparts(Message *m) -{ - free(m->name); - free(m->replyname); - free(m->from); - free(m->to); - free(m->cc); - free(m->replyto); - free(m->date); - free(m->subject); - free(m->type); - free(m->disposition); - free(m->filename); - free(m->digest); +void mesgfreeparts(Message* m) { + free(m->name); + free(m->replyname); + free(m->from); + free(m->to); + free(m->cc); + free(m->replyto); + free(m->date); + free(m->subject); + free(m->type); + free(m->disposition); + free(m->filename); + free(m->digest); } -void -mesgdel(Message *mbox, Message *m) -{ - Message *n, *next; +void mesgdel(Message* mbox, Message* m) { + Message *n, *next; - if(m->opened) - error("internal error: deleted message still open in mesgdel\n"); - /* delete subparts */ - for(n=m->head; n!=nil; n=next){ - next = n->next; - mesgdel(m, n); - } - /* remove this message from list */ - if(m->next) - m->next->prev = m->prev; - else - mbox->tail = m->prev; - if(m->prev) - m->prev->next = m->next; - else - mbox->head = m->next; + if (m->opened) + error("internal error: deleted message still open in mesgdel\n"); + /* delete subparts */ + for (n = m->head; n != nil; n = next) { + next = n->next; + mesgdel(m, n); + } + /* remove this message from list */ + if (m->next) + m->next->prev = m->prev; + else + mbox->tail = m->prev; + if (m->prev) + m->prev->next = m->next; + else + mbox->head = m->next; - mesgfreeparts(m); + mesgfreeparts(m); } -int -mesgsave(Message *m, char *s, int save) -{ - int ofd, n, k, ret; - char *t, *raw, *unixheader, *all; +int mesgsave(Message* m, char* s, int save) { + int ofd, n, k, ret; + char *t, *raw, *unixheader, *all; - if(save){ - if(fsprint(mbox.ctlfd, "save %q %q", s, m->name) < 0){ - fprint(2, "Mail: can't save %s to %s: %r\n", m->name, s); - return 0; - } - return 1; - } - - t = estrstrdup(mbox.name, m->name); - raw = readfile(t, "raw", &n); - unixheader = readfile(t, "unixheader", &k); - if(raw==nil || unixheader==nil){ - fprint(2, "Mail: can't read %s: %r\n", t); - free(t); - return 0; - } - free(t); + if (save) { + if (fsprint(mbox.ctlfd, "save %q %q", s, m->name) < 0) { + fprint(2, "Mail: can't save %s to %s: %r\n", m->name, s); + return 0; + } + return 1; + } - all = emalloc(n+k+1); - memmove(all, unixheader, k); - memmove(all+k, raw, n); - memmove(all+k+n, "\n", 1); - n = k+n+1; - free(unixheader); - free(raw); - ret = 1; - s = estrdup(s); - if(s[0] != '/') - s = egrow(estrdup(mailboxdir), "/", s); - ofd = open(s, OWRITE); - if(ofd < 0){ - fprint(2, "Mail: can't open %s: %r\n", s); - ret = 0; - }else if(seek(ofd, 0LL, 2)<0 || write(ofd, all, n)!=n){ - fprint(2, "Mail: save failed: can't write %s: %r\n", s); - ret = 0; - } - free(all); - close(ofd); - free(s); - return ret; + t = estrstrdup(mbox.name, m->name); + raw = readfile(t, "raw", &n); + unixheader = readfile(t, "unixheader", &k); + if (raw == nil || unixheader == nil) { + fprint(2, "Mail: can't read %s: %r\n", t); + free(t); + return 0; + } + free(t); + + all = emalloc(n + k + 1); + memmove(all, unixheader, k); + memmove(all + k, raw, n); + memmove(all + k + n, "\n", 1); + n = k + n + 1; + free(unixheader); + free(raw); + ret = 1; + s = estrdup(s); + if (s[0] != '/') + s = egrow(estrdup(mailboxdir), "/", s); + ofd = open(s, OWRITE); + if (ofd < 0) { + fprint(2, "Mail: can't open %s: %r\n", s); + ret = 0; + } else if (seek(ofd, 0LL, 2) < 0 || write(ofd, all, n) != n) { + fprint(2, "Mail: save failed: can't write %s: %r\n", s); + ret = 0; + } + free(all); + close(ofd); + free(s); + return ret; } -int -mesgcommand(Message *m, char *cmd) -{ - char *s; - char *args[10]; - int save, ok, ret, nargs; +int mesgcommand(Message* m, char* cmd) { + char* s; + char* args[10]; + int save, ok, ret, nargs; - s = cmd; - ret = 1; - nargs = tokenize(s, args, nelem(args)); - if(nargs == 0) - return 0; - if(strcmp(args[0], "Post") == 0){ - mesgsend(m); - goto Return; - } - if(strncmp(args[0], "Save", 4) == 0 || strncmp(args[0], "Write", 5) == 0){ - if(m->isreply) - goto Return; - save = args[0][0]=='S'; - if(save) - s = estrdup("\t[saved"); - else - s = estrdup("\t[wrote"); - if(nargs==1 || strcmp(args[1], "")==0){ - ok = mesgsave(m, "stored", save); - }else{ - ok = mesgsave(m, args[1], save); - s = eappend(s, " ", args[1]); - } - if(ok){ - s = egrow(s, "]", nil); - mesgmenumark(mbox.w, m->name, s); - } - free(s); - goto Return; - } - if(strcmp(args[0], "Reply")==0){ - if(nargs>=2 && strcmp(args[1], "all")==0) - mkreply(m, "Replyall", nil, nil, nil); - else - mkreply(m, "Reply", nil, nil, nil); - goto Return; - } - if(strcmp(args[0], "Q") == 0){ - s = winselection(m->w); /* will be freed by mkreply */ - if(nargs>=3 && strcmp(args[1], "Reply")==0 && strcmp(args[2], "all")==0) - mkreply(m, "QReplyall", nil, nil, s); - else - mkreply(m, "QReply", nil, nil, s); - goto Return; - } - if(strcmp(args[0], "Del") == 0){ - if(windel(m->w, 0)){ - windecref(m->w); - m->w = nil; - if(m->isreply) - delreply(m); - else{ - m->opened = 0; - m->tagposted = 0; - } - free(cmd); - threadexits(nil); - } - goto Return; - } - if(strcmp(args[0], "Delmesg") == 0){ - if(!m->isreply){ - mesgmenumarkdel(wbox, &mbox, m, 1); - free(cmd); /* mesgcommand might not return */ - mesgcommand(m, estrdup("Del")); - return 1; - } - goto Return; - } - if(strcmp(args[0], "UnDelmesg") == 0){ - if(!m->isreply && m->deleted) - mesgmenumarkundel(wbox, &mbox, m); - goto Return; - } -/* if(strcmp(args[0], "Headers") == 0){ */ -/* m->showheaders(); */ -/* return True; */ -/* } */ + s = cmd; + ret = 1; + nargs = tokenize(s, args, nelem(args)); + if (nargs == 0) + return 0; + if (strcmp(args[0], "Post") == 0) { + mesgsend(m); + goto Return; + } + if (strncmp(args[0], "Save", 4) == 0 || strncmp(args[0], "Write", 5) == 0) { + if (m->isreply) + goto Return; + save = args[0][0] == 'S'; + if (save) + s = estrdup("\t[saved"); + else + s = estrdup("\t[wrote"); + if (nargs == 1 || strcmp(args[1], "") == 0) { + ok = mesgsave(m, "stored", save); + } else { + ok = mesgsave(m, args[1], save); + s = eappend(s, " ", args[1]); + } + if (ok) { + s = egrow(s, "]", nil); + mesgmenumark(mbox.w, m->name, s); + } + free(s); + goto Return; + } + if (strcmp(args[0], "Reply") == 0) { + if (nargs >= 2 && strcmp(args[1], "all") == 0) + mkreply(m, "Replyall", nil, nil, nil); + else + mkreply(m, "Reply", nil, nil, nil); + goto Return; + } + if (strcmp(args[0], "Q") == 0) { + s = winselection(m->w); /* will be freed by mkreply */ + if ( + nargs >= 3 && strcmp(args[1], "Reply") == 0 && + strcmp(args[2], "all") == 0) + mkreply(m, "QReplyall", nil, nil, s); + else + mkreply(m, "QReply", nil, nil, s); + goto Return; + } + if (strcmp(args[0], "Del") == 0) { + if (windel(m->w, 0)) { + windecref(m->w); + m->w = nil; + if (m->isreply) + delreply(m); + else { + m->opened = 0; + m->tagposted = 0; + } + free(cmd); + threadexits(nil); + } + goto Return; + } + if (strcmp(args[0], "Delmesg") == 0) { + if (!m->isreply) { + mesgmenumarkdel(wbox, &mbox, m, 1); + free(cmd); /* mesgcommand might not return */ + mesgcommand(m, estrdup("Del")); + return 1; + } + goto Return; + } + if (strcmp(args[0], "UnDelmesg") == 0) { + if (!m->isreply && m->deleted) + mesgmenumarkundel(wbox, &mbox, m); + goto Return; + } + /* if(strcmp(args[0], "Headers") == 0){ */ + /* m->showheaders(); */ + /* return True; */ + /* } */ - ret = 0; + ret = 0; - Return: - free(cmd); - return ret; +Return: + free(cmd); + return ret; } -void -mesgtagpost(Message *m) -{ - if(m->tagposted) - return; - wintagwrite(m->w, " Post", 5); - m->tagposted = 1; +void mesgtagpost(Message* m) { + if (m->tagposted) + return; + wintagwrite(m->w, " Post", 5); + m->tagposted = 1; } /* need to expand selection more than default word */ #pragma varargck argpos eval 2 -long -eval(Window *w, char *s, ...) -{ - char buf[64]; - va_list arg; +long eval(Window* w, char* s, ...) { + char buf[64]; + va_list arg; - va_start(arg, s); - vsnprint(buf, sizeof buf, s, arg); - va_end(arg); + va_start(arg, s); + vsnprint(buf, sizeof buf, s, arg); + va_end(arg); - if(winsetaddr(w, buf, 1)==0) - return -1; + if (winsetaddr(w, buf, 1) == 0) + return -1; - if(fspread(w->addr, buf, 24, 0) != 24) - return -1; - return strtol(buf, 0, 10); + if (fspread(w->addr, buf, 24, 0) != 24) + return -1; + return strtol(buf, 0, 10); } -int -isemail(char *s) -{ - int nat; +int isemail(char* s) { + int nat; - nat = 0; - for(; *s; s++) - if(*s == '@') - nat++; - else if(!isalpha(*s) && !isdigit(*s) && !strchr("_.-+/", *s)) - return 0; - return nat==1; + nat = 0; + for (; *s; s++) + if (*s == '@') + nat++; + else if (!isalpha(*s) && !isdigit(*s) && !strchr("_.-+/", *s)) + return 0; + return nat == 1; } -char addrdelim[] = "/[ \t\\n<>()\\[\\]]/"; -char* -expandaddr(Window *w, Event *e) -{ - char *s; - long q0, q1; +char addrdelim[] = "/[ \t\\n<>()\\[\\]]/"; +char* expandaddr(Window* w, Event* e) { + char* s; + long q0, q1; - if(e->q0 != e->q1) /* cannot happen */ - return nil; + if (e->q0 != e->q1) /* cannot happen */ + return nil; - q0 = eval(w, "#%d-%s", e->q0, addrdelim); - if(q0 == -1) /* bad char not found */ - q0 = 0; - else /* increment past bad char */ - q0++; + q0 = eval(w, "#%d-%s", e->q0, addrdelim); + if (q0 == -1) /* bad char not found */ + q0 = 0; + else /* increment past bad char */ + q0++; - q1 = eval(w, "#%d+%s", e->q0, addrdelim); - if(q1 < 0){ - q1 = eval(w, "$"); - if(q1 < 0) - return nil; - } - if(q0 >= q1) - return nil; - s = emalloc((q1-q0)*UTFmax+1); - winread(w, q0, q1, s); - return s; + q1 = eval(w, "#%d+%s", e->q0, addrdelim); + if (q1 < 0) { + q1 = eval(w, "$"); + if (q1 < 0) + return nil; + } + if (q0 >= q1) + return nil; + s = emalloc((q1 - q0) * UTFmax + 1); + winread(w, q0, q1, s); + return s; } -int -replytoaddr(Window *w, Message *m, Event *e, char *s) -{ - int did; - char *buf; - Plumbmsg *pm; +int replytoaddr(Window* w, Message* m, Event* e, char* s) { + int did; + char* buf; + Plumbmsg* pm; - buf = nil; - did = 0; - if(e->flag & 2){ - /* autoexpanded; use our own bigger expansion */ - buf = expandaddr(w, e); - if(buf == nil) - return 0; - s = buf; - } - if(isemail(s)){ - did = 1; - pm = emalloc(sizeof(Plumbmsg)); - pm->src = estrdup("Mail"); - pm->dst = estrdup("sendmail"); - pm->data = estrdup(s); - pm->ndata = -1; - if(m->subject && m->subject[0]){ - pm->attr = emalloc(sizeof(Plumbattr)); - pm->attr->name = estrdup("Subject"); - if(tolower(m->subject[0]) != 'r' || tolower(m->subject[1]) != 'e' || m->subject[2] != ':') - pm->attr->value = estrstrdup("Re: ", m->subject); - else - pm->attr->value = estrdup(m->subject); - pm->attr->next = nil; - } - if(plumbsendtofid(plumbsendfd, pm) < 0) - fprint(2, "error writing plumb message: %r\n"); - plumbfree(pm); - } - free(buf); - return did; + buf = nil; + did = 0; + if (e->flag & 2) { + /* autoexpanded; use our own bigger expansion */ + buf = expandaddr(w, e); + if (buf == nil) + return 0; + s = buf; + } + if (isemail(s)) { + did = 1; + pm = emalloc(sizeof(Plumbmsg)); + pm->src = estrdup("Mail"); + pm->dst = estrdup("sendmail"); + pm->data = estrdup(s); + pm->ndata = -1; + if (m->subject && m->subject[0]) { + pm->attr = emalloc(sizeof(Plumbattr)); + pm->attr->name = estrdup("Subject"); + if ( + tolower(m->subject[0]) != 'r' || tolower(m->subject[1]) != 'e' || + m->subject[2] != ':') + pm->attr->value = estrstrdup("Re: ", m->subject); + else + pm->attr->value = estrdup(m->subject); + pm->attr->next = nil; + } + if (plumbsendtofid(plumbsendfd, pm) < 0) + fprint(2, "error writing plumb message: %r\n"); + plumbfree(pm); + } + free(buf); + return did; } +void mesgctl(void* v) { + Message* m; + Window* w; + Event *e, *eq, *e2, *ea; + int na, nopen, i, j; + char *os, *s, *t, *buf; -void -mesgctl(void *v) -{ - Message *m; - Window *w; - Event *e, *eq, *e2, *ea; - int na, nopen, i, j; - char *os, *s, *t, *buf; + m = v; + w = m->w; + threadsetname("mesgctl"); + winincref(w); + proccreate(wineventproc, w, STACK); + for (;;) { + e = recvp(w->cevent); + switch (e->c1) { + default: + Unk: + print("unknown message %c%c\n", e->c1, e->c2); + break; - m = v; - w = m->w; - threadsetname("mesgctl"); - winincref(w); - proccreate(wineventproc, w, STACK); - for(;;){ - e = recvp(w->cevent); - switch(e->c1){ - default: - Unk: - print("unknown message %c%c\n", e->c1, e->c2); - break; + case 'E': /* write to body; can't affect us */ + break; - case 'E': /* write to body; can't affect us */ - break; + case 'F': /* generated by our actions; ignore */ + break; - case 'F': /* generated by our actions; ignore */ - break; + case 'K': /* type away; we don't care */ + case 'M': + switch (e->c2) { + case 'x': /* mouse only */ + case 'X': + ea = nil; + eq = e; + if (e->flag & 2) { + e2 = recvp(w->cevent); + eq = e2; + } + if (e->flag & 8) { + ea = recvp(w->cevent); + recvp(w->cevent); + na = ea->nb; + } else + na = 0; + if (eq->q1 > eq->q0 && eq->nb == 0) { + s = emalloc((eq->q1 - eq->q0) * UTFmax + 1); + winread(w, eq->q0, eq->q1, s); + } else + s = estrdup(eq->b); + if (na) { + t = emalloc(strlen(s) + 1 + na + 1); + sprint(t, "%s %s", s, ea->b); + free(s); + s = t; + } + if (!mesgcommand(m, s)) /* send it back */ + winwriteevent(w, e); + break; - case 'K': /* type away; we don't care */ - case 'M': - switch(e->c2){ - case 'x': /* mouse only */ - case 'X': - ea = nil; - eq = e; - if(e->flag & 2){ - e2 = recvp(w->cevent); - eq = e2; - } - if(e->flag & 8){ - ea = recvp(w->cevent); - recvp(w->cevent); - na = ea->nb; - }else - na = 0; - if(eq->q1>eq->q0 && eq->nb==0){ - s = emalloc((eq->q1-eq->q0)*UTFmax+1); - winread(w, eq->q0, eq->q1, s); - }else - s = estrdup(eq->b); - if(na){ - t = emalloc(strlen(s)+1+na+1); - sprint(t, "%s %s", s, ea->b); - free(s); - s = t; - } - if(!mesgcommand(m, s)) /* send it back */ - winwriteevent(w, e); - break; + case 'l': /* mouse only */ + 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; + } + os = s; + nopen = 0; + do { + /* skip mail box name if present */ + if (strncmp(s, mbox.name, strlen(mbox.name)) == 0) + s += strlen(mbox.name); + if (strstr(s, "body") != nil) { + /* strip any known extensions */ + for (i = 0; ports[i].suffix != nil; i++) { + j = strlen(ports[i].suffix); + if ( + strlen(s) > j && + strcmp(s + strlen(s) - j, ports[i].suffix) == 0) { + s[strlen(s) - j] = '\0'; + break; + } + } + if (strlen(s) > 5 && strcmp(s + strlen(s) - 5, "/body") == 0) + s[strlen(s) - 4] = '\0'; /* leave / in place */ + } + nopen += mesgopen(&mbox, mbox.name, s, m, 0, nil); + while (*s != 0 && *s++ != '\n') + ; + } while (*s); + if (nopen == 0 && e->c1 == 'L') + nopen += replytoaddr(w, m, e, os); + if (nopen == 0) + winwriteevent(w, e); + free(buf); + break; - case 'l': /* mouse only */ - 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; - } - os = s; - nopen = 0; - do{ - /* skip mail box name if present */ - if(strncmp(s, mbox.name, strlen(mbox.name)) == 0) - s += strlen(mbox.name); - if(strstr(s, "body") != nil){ - /* strip any known extensions */ - for(i=0; ports[i].suffix!=nil; i++){ - j = strlen(ports[i].suffix); - if(strlen(s)>j && strcmp(s+strlen(s)-j, ports[i].suffix)==0){ - s[strlen(s)-j] = '\0'; - break; - } - } - if(strlen(s)>5 && strcmp(s+strlen(s)-5, "/body")==0) - s[strlen(s)-4] = '\0'; /* leave / in place */ - } - nopen += mesgopen(&mbox, mbox.name, s, m, 0, nil); - while(*s!=0 && *s++!='\n') - ; - }while(*s); - if(nopen == 0 && e->c1 == 'L') - nopen += replytoaddr(w, m, e, os); - if(nopen == 0) - winwriteevent(w, e); - free(buf); - break; + case 'I': /* modify away; we don't care */ + case 'D': + mesgtagpost(m); + /* fall through */ + case 'd': + case 'i': + break; - case 'I': /* modify away; we don't care */ - case 'D': - mesgtagpost(m); - /* fall through */ - case 'd': - case 'i': - break; - - default: - goto Unk; - } - } - } + default: + goto Unk; + } + } + } } -void -mesgline(Message *m, char *header, char *value) -{ - if(strlen(value) > 0) - fsprint(m->w->body, "%s: %s\n", header, value); +void mesgline(Message* m, char* header, char* value) { + if (strlen(value) > 0) + fsprint(m->w->body, "%s: %s\n", header, value); } -int -isprintable(char *type) -{ - int i; +int isprintable(char* type) { + int i; - for(i=0; goodtypes[i]!=nil; i++) - if(strcmp(type, goodtypes[i])==0) - return 1; - return 0; + for (i = 0; goodtypes[i] != nil; i++) + if (strcmp(type, goodtypes[i]) == 0) + return 1; + return 0; } -char* -ext(char *type) -{ - int i; +char* ext(char* type) { + int i; - for(i=0; ports[i].type!=nil; i++) - if(strcmp(type, ports[i].type)==0) - return ports[i].suffix; - return ""; + for (i = 0; ports[i].type != nil; i++) + if (strcmp(type, ports[i].type) == 0) + return ports[i].suffix; + return ""; } -void -mimedisplay(Message *m, char *name, char *rootdir, Window *w, int fileonly) -{ - char *dest; +void mimedisplay( + Message* m, char* name, char* rootdir, Window* w, int fileonly) { + char* dest; - if(strcmp(m->disposition, "file")==0 || strlen(m->filename)!=0 || !fileonly){ - if(strlen(m->filename) == 0) - dest = estrstrdup("a", ext(m->type)); - else - dest = estrdup(m->filename); - if(m->filename[0] != '/') - dest = egrow(estrdup(home), "/", dest); - fsprint(w->body, "\t9p read %s/%s/%sbody > %s\n", - srvname, mboxname, name, dest); - free(dest); - } + if ( + strcmp(m->disposition, "file") == 0 || strlen(m->filename) != 0 || + !fileonly) { + if (strlen(m->filename) == 0) + dest = estrstrdup("a", ext(m->type)); + else + dest = estrdup(m->filename); + if (m->filename[0] != '/') + dest = egrow(estrdup(home), "/", dest); + fsprint( + w->body, + "\t9p read %s/%s/%sbody > %s\n", + srvname, + mboxname, + name, + dest); + free(dest); + } } -void -printheader(char *dir, CFid *fid, char **okheaders) -{ - char *s; - char *lines[100]; - int i, j, n; +void printheader(char* dir, CFid* fid, char** okheaders) { + char* s; + char* lines[100]; + int i, j, n; - s = readfile(dir, "header", nil); - if(s == nil) - return; - n = getfields(s, lines, nelem(lines), 0, "\n"); - for(i=0; i<n; i++) - for(j=0; okheaders[j]; j++) - if(cistrncmp(lines[i], okheaders[j], strlen(okheaders[j])) == 0) - fsprint(fid, "%s\n", lines[i]); - free(s); + s = readfile(dir, "header", nil); + if (s == nil) + return; + n = getfields(s, lines, nelem(lines), 0, "\n"); + for (i = 0; i < n; i++) + for (j = 0; okheaders[j]; j++) + if (cistrncmp(lines[i], okheaders[j], strlen(okheaders[j])) == 0) + fsprint(fid, "%s\n", lines[i]); + free(s); } -void -mesgload(Message *m, char *rootdir, char *file, Window *w) -{ - char *s, *subdir, *name, *dir; - Message *mp, *thisone; - int n; +void mesgload(Message* m, char* rootdir, char* file, Window* w) { + char *s, *subdir, *name, *dir; + Message *mp, *thisone; + int n; - dir = estrstrdup(rootdir, file); + dir = estrstrdup(rootdir, file); - if(strcmp(m->type, "message/rfc822") != 0){ /* suppress headers of envelopes */ - if(strlen(m->from) > 0){ - fsprint(w->body, "From: %s\n", m->from); - mesgline(m, "Date", m->date); - mesgline(m, "To", m->to); - mesgline(m, "CC", m->cc); - mesgline(m, "Subject", m->subject); - printheader(dir, w->body, extraheaders); - }else{ - printheader(dir, w->body, okheaders); - printheader(dir, w->body, extraheaders); - } - fsprint(w->body, "\n"); - } + if (strcmp(m->type, "message/rfc822") != 0) { /* suppress headers of envelopes + */ + if (strlen(m->from) > 0) { + fsprint(w->body, "From: %s\n", m->from); + mesgline(m, "Date", m->date); + mesgline(m, "To", m->to); + mesgline(m, "CC", m->cc); + mesgline(m, "Subject", m->subject); + printheader(dir, w->body, extraheaders); + } else { + printheader(dir, w->body, okheaders); + printheader(dir, w->body, extraheaders); + } + fsprint(w->body, "\n"); + } - if(m->level == 1 && m->recursed == 0){ - m->recursed = 1; - readmbox(m, rootdir, m->name); - } - if(m->head == nil){ /* single part message */ - if(strcmp(m->type, "text")==0 || strncmp(m->type, "text/", 5)==0){ - mimedisplay(m, m->name, rootdir, w, 1); - s = readbody(m->type, dir, &n); - winwritebody(w, s, n); - free(s); - }else - mimedisplay(m, m->name, rootdir, w, 0); - }else{ - /* multi-part message, either multipart/* or message/rfc822 */ - thisone = nil; - if(strcmp(m->type, "multipart/alternative") == 0){ - thisone = m->head; /* in case we can't find a good one */ - for(mp=m->head; mp!=nil; mp=mp->next) - if(isprintable(mp->type)){ - thisone = mp; - break; - } - } - for(mp=m->head; mp!=nil; mp=mp->next){ - if(thisone!=nil && mp!=thisone) - continue; - subdir = estrstrdup(dir, mp->name); - name = estrstrdup(file, mp->name); - /* skip first element in name because it's already in window name */ - if(mp != m->head) - fsprint(w->body, "\n===> %s (%s) [%s]\n", strchr(name, '/')+1, mp->type, mp->disposition); - if(strcmp(mp->type, "text")==0 || strncmp(mp->type, "text/", 5)==0){ - mimedisplay(mp, name, rootdir, w, 1); - printheader(subdir, w->body, okheaders); - printheader(subdir, w->body, extraheaders); - winwritebody(w, "\n", 1); - s = readbody(mp->type, subdir, &n); - winwritebody(w, s, n); - free(s); - }else{ - if(strncmp(mp->type, "multipart/", 10)==0 || strcmp(mp->type, "message/rfc822")==0){ - mp->w = w; - mesgload(mp, rootdir, name, w); - mp->w = nil; - }else - mimedisplay(mp, name, rootdir, w, 0); - } - free(name); - free(subdir); - } - } - free(dir); + if (m->level == 1 && m->recursed == 0) { + m->recursed = 1; + readmbox(m, rootdir, m->name); + } + if (m->head == nil) { /* single part message */ + if (strcmp(m->type, "text") == 0 || strncmp(m->type, "text/", 5) == 0) { + mimedisplay(m, m->name, rootdir, w, 1); + s = readbody(m->type, dir, &n); + winwritebody(w, s, n); + free(s); + } else + mimedisplay(m, m->name, rootdir, w, 0); + } else { + /* multi-part message, either multipart/* or message/rfc822 */ + thisone = nil; + if (strcmp(m->type, "multipart/alternative") == 0) { + thisone = m->head; /* in case we can't find a good one */ + for (mp = m->head; mp != nil; mp = mp->next) + if (isprintable(mp->type)) { + thisone = mp; + break; + } + } + for (mp = m->head; mp != nil; mp = mp->next) { + if (thisone != nil && mp != thisone) + continue; + subdir = estrstrdup(dir, mp->name); + name = estrstrdup(file, mp->name); + /* skip first element in name because it's already in window name */ + if (mp != m->head) + fsprint( + w->body, + "\n===> %s (%s) [%s]\n", + strchr(name, '/') + 1, + mp->type, + mp->disposition); + if (strcmp(mp->type, "text") == 0 || strncmp(mp->type, "text/", 5) == 0) { + mimedisplay(mp, name, rootdir, w, 1); + printheader(subdir, w->body, okheaders); + printheader(subdir, w->body, extraheaders); + winwritebody(w, "\n", 1); + s = readbody(mp->type, subdir, &n); + winwritebody(w, s, n); + free(s); + } else { + if ( + strncmp(mp->type, "multipart/", 10) == 0 || + strcmp(mp->type, "message/rfc822") == 0) { + mp->w = w; + mesgload(mp, rootdir, name, w); + mp->w = nil; + } else + mimedisplay(mp, name, rootdir, w, 0); + } + free(name); + free(subdir); + } + } + free(dir); } -int -tokenizec(char *str, char **args, int max, char *splitc) -{ - int i, na; - int intok = 0; - char *p; +int tokenizec(char* str, char** args, int max, char* splitc) { + int i, na; + int intok = 0; + char* p; + + if (max <= 0) + return 0; - if(max <= 0) - return 0; - -/* if(strchr(str, ',') || strchr(str, '"') || strchr(str, '<') || strchr(str, '(')) */ -/* splitc = ","; */ - for(na=0; *str != '\0';str++){ - if(strchr(splitc, *str) == nil){ - if(intok) - continue; - args[na++] = str; - intok = 1; - }else{ - /* it's a separator/skip character */ - *str = '\0'; - if(intok){ - intok = 0; - if(na >= max) - break; - } - } - } - for(i=0; i<na; i++){ - while(*args[i] && strchr(" \t\r\n", *args[i])) - args[i]++; - p = args[i]+strlen(args[i]); - while(p>args[i] && strchr(" \t\r\n", *(p-1))) - *--p = 0; - } - return na; + /* if(strchr(str, ',') || strchr(str, '"') || strchr(str, '<') || strchr(str, + * '(')) */ + /* splitc = ","; */ + for (na = 0; *str != '\0'; str++) { + if (strchr(splitc, *str) == nil) { + if (intok) + continue; + args[na++] = str; + intok = 1; + } else { + /* it's a separator/skip character */ + *str = '\0'; + if (intok) { + intok = 0; + if (na >= max) + break; + } + } + } + for (i = 0; i < na; i++) { + while (*args[i] && strchr(" \t\r\n", *args[i])) + args[i]++; + p = args[i] + strlen(args[i]); + while (p > args[i] && strchr(" \t\r\n", *(p - 1))) + *--p = 0; + } + return na; } -Message* -mesglookup(Message *mbox, char *name, char *digest) -{ - int n; - Message *m; - char *t; +Message* mesglookup(Message* mbox, char* name, char* digest) { + int n; + Message* m; + char* t; - if(digest && digest[0]){ - /* can find exactly */ - for(m=mbox->head; m!=nil; m=m->next) - if(strcmp(digest, m->digest) == 0) - break; - return m; - } + if (digest && digest[0]) { + /* can find exactly */ + for (m = mbox->head; m != nil; m = m->next) + if (strcmp(digest, m->digest) == 0) + break; + return m; + } - n = strlen(name); - if(n == 0) - return nil; - if(name[n-1] == '/') - t = estrdup(name); - else - t = estrstrdup(name, "/"); - for(m=mbox->head; m!=nil; m=m->next) - if(strcmp(t, m->name) == 0) - break; - free(t); - return m; + n = strlen(name); + if (n == 0) + return nil; + if (name[n - 1] == '/') + t = estrdup(name); + else + t = estrstrdup(name, "/"); + for (m = mbox->head; m != nil; m = m->next) + if (strcmp(t, m->name) == 0) + break; + free(t); + return m; } /* * Find plumb port, knowing type is text, given file name (by extension) */ -int -plumbportbysuffix(char *file) -{ - char *suf; - int i, nsuf, nfile; +int plumbportbysuffix(char* file) { + char* suf; + int i, nsuf, nfile; - nfile = strlen(file); - for(i=0; ports[i].type!=nil; i++){ - suf = ports[i].suffix; - nsuf = strlen(suf); - if(nfile > nsuf) - if(cistrncmp(file+nfile-nsuf, suf, nsuf) == 0) - return i; - } - return 0; + nfile = strlen(file); + for (i = 0; ports[i].type != nil; i++) { + suf = ports[i].suffix; + nsuf = strlen(suf); + if (nfile > nsuf) + if (cistrncmp(file + nfile - nsuf, suf, nsuf) == 0) + return i; + } + return 0; } /* * Find plumb port using type and file name (by extension) */ -int -plumbport(char *type, char *file) -{ - int i; +int plumbport(char* type, char* file) { + int i; - for(i=0; ports[i].type!=nil; i++) - if(strncmp(type, ports[i].type, strlen(ports[i].type)) == 0) - return i; - /* see if it's a text type */ - for(i=0; goodtypes[i]!=nil; i++) - if(strncmp(type, goodtypes[i], strlen(goodtypes[i])) == 0) - return plumbportbysuffix(file); - return -1; + for (i = 0; ports[i].type != nil; i++) + if (strncmp(type, ports[i].type, strlen(ports[i].type)) == 0) + return i; + /* see if it's a text type */ + for (i = 0; goodtypes[i] != nil; i++) + if (strncmp(type, goodtypes[i], strlen(goodtypes[i])) == 0) + return plumbportbysuffix(file); + return -1; } -void -plumb(Message *m, char *dir) -{ - int i; - char *port; - Plumbmsg *pm; +void plumb(Message* m, char* dir) { + int i; + char* port; + Plumbmsg* pm; - if(strlen(m->type) == 0) - return; - i = plumbport(m->type, m->filename); - if(i < 0) - fprint(2, "can't find destination for message subpart\n"); - else{ - port = ports[i].port; - pm = emalloc(sizeof(Plumbmsg)); - pm->src = estrdup("Mail"); - if(port) - pm->dst = estrdup(port); - else - pm->dst = nil; - pm->wdir = nil; - pm->type = estrdup("text"); - pm->ndata = -1; - pm->data = estrstrdup(dir, "body"); - pm->data = eappend(pm->data, "", ports[i].suffix); - if(plumbsendtofid(plumbsendfd, pm) < 0) - fprint(2, "error writing plumb message: %r\n"); - plumbfree(pm); - } + if (strlen(m->type) == 0) + return; + i = plumbport(m->type, m->filename); + if (i < 0) + fprint(2, "can't find destination for message subpart\n"); + else { + port = ports[i].port; + pm = emalloc(sizeof(Plumbmsg)); + pm->src = estrdup("Mail"); + if (port) + pm->dst = estrdup(port); + else + pm->dst = nil; + pm->wdir = nil; + pm->type = estrdup("text"); + pm->ndata = -1; + pm->data = estrstrdup(dir, "body"); + pm->data = eappend(pm->data, "", ports[i].suffix); + if (plumbsendtofid(plumbsendfd, pm) < 0) + fprint(2, "error writing plumb message: %r\n"); + plumbfree(pm); + } } -int -mesgopen(Message *mbox, char *dir, char *s, Message *mesg, int plumbed, char *digest) -{ - char *t, *u, *v; - Message *m; - char *direlem[10]; - int i, ndirelem, reuse; +int mesgopen( + Message* mbox, char* dir, char* s, Message* mesg, int plumbed, char* digest) { + char *t, *u, *v; + Message* m; + char* direlem[10]; + int i, ndirelem, reuse; - /* find white-space-delimited first word */ - for(t=s; *t!='\0' && !isspace(*t); t++) - ; - u = emalloc(t-s+1); - memmove(u, s, t-s); - /* separate it on slashes */ - ndirelem = tokenizec(u, direlem, nelem(direlem), "/"); - if(ndirelem <= 0){ - Error: - free(u); - return 0; - } - /*XXX - if(plumbed) - drawtopwindow(); - */ - /* open window for message */ - m = mesglookup(mbox, direlem[0], digest); - if(m == nil) - goto Error; - if(mesg!=nil && m!=mesg) /* string looked like subpart but isn't part of this message */ - goto Error; - if(m->opened == 0){ - if(m->w == nil){ - reuse = 0; - m->w = newwindow(); - }else{ - reuse = 1; - /* re-use existing window */ - if(winsetaddr(m->w, "0,$", 1)){ - if(m->w->data == nil) - m->w->data = winopenfile(m->w, "data"); - fswrite(m->w->data, "", 0); - } - } - v = estrstrdup(mbox->name, m->name); - winname(m->w, v); - free(v); - if(!reuse){ - if(m->deleted) - wintagwrite(m->w, "Q Reply all UnDelmesg Save ", 2+6+4+10+5); - else - wintagwrite(m->w, "Q Reply all Delmesg Save ", 2+6+4+8+5); - } - threadcreate(mesgctl, m, STACK); - winopenbody(m->w, OWRITE); - mesgload(m, dir, m->name, m->w); - winclosebody(m->w); - /* sleep(100); */ - winclean(m->w); - m->opened = 1; - if(ndirelem == 1){ - free(u); - return 1; - } - } - if(ndirelem == 1 && plumbport(m->type, m->filename) <= 0){ - /* make sure dot is visible */ - ctlprint(m->w->ctl, "show\n"); - return 0; - } - /* walk to subpart */ - dir = estrstrdup(dir, m->name); - for(i=1; i<ndirelem; i++){ - m = mesglookup(m, direlem[i], digest); - if(m == nil) - break; - dir = egrow(dir, m->name, nil); - } - if(m != nil && plumbport(m->type, m->filename) > 0) - plumb(m, dir); - free(dir); - free(u); - return 1; + /* find white-space-delimited first word */ + for (t = s; *t != '\0' && !isspace(*t); t++) + ; + u = emalloc(t - s + 1); + memmove(u, s, t - s); + /* separate it on slashes */ + ndirelem = tokenizec(u, direlem, nelem(direlem), "/"); + if (ndirelem <= 0) { + Error: + free(u); + return 0; + } + /*XXX + if(plumbed) + drawtopwindow(); + */ + /* open window for message */ + m = mesglookup(mbox, direlem[0], digest); + if (m == nil) + goto Error; + if (mesg != nil && m != mesg) /* string looked like subpart but isn't part of + this message */ + goto Error; + if (m->opened == 0) { + if (m->w == nil) { + reuse = 0; + m->w = newwindow(); + } else { + reuse = 1; + /* re-use existing window */ + if (winsetaddr(m->w, "0,$", 1)) { + if (m->w->data == nil) + m->w->data = winopenfile(m->w, "data"); + fswrite(m->w->data, "", 0); + } + } + v = estrstrdup(mbox->name, m->name); + winname(m->w, v); + free(v); + if (!reuse) { + if (m->deleted) + wintagwrite(m->w, "Q Reply all UnDelmesg Save ", 2 + 6 + 4 + 10 + 5); + else + wintagwrite(m->w, "Q Reply all Delmesg Save ", 2 + 6 + 4 + 8 + 5); + } + threadcreate(mesgctl, m, STACK); + winopenbody(m->w, OWRITE); + mesgload(m, dir, m->name, m->w); + winclosebody(m->w); + /* sleep(100); */ + winclean(m->w); + m->opened = 1; + if (ndirelem == 1) { + free(u); + return 1; + } + } + if (ndirelem == 1 && plumbport(m->type, m->filename) <= 0) { + /* make sure dot is visible */ + ctlprint(m->w->ctl, "show\n"); + return 0; + } + /* walk to subpart */ + dir = estrstrdup(dir, m->name); + for (i = 1; i < ndirelem; i++) { + m = mesglookup(m, direlem[i], digest); + if (m == nil) + break; + dir = egrow(dir, m->name, nil); + } + if (m != nil && plumbport(m->type, m->filename) > 0) + plumb(m, dir); + free(dir); + free(u); + return 1; } -void -rewritembox(Window *w, Message *mbox) -{ - Message *m, *next; - char *deletestr, *t; - int nopen; +void rewritembox(Window* w, Message* mbox) { + Message *m, *next; + char *deletestr, *t; + int nopen; - deletestr = estrstrdup("delete ", fsname); + deletestr = estrstrdup("delete ", fsname); - nopen = 0; - for(m=mbox->head; m!=nil; m=next){ - next = m->next; - if(m->deleted == 0) - continue; - if(m->opened){ - nopen++; - continue; - } - if(m->writebackdel){ - /* messages deleted by plumb message are not removed again */ - t = estrdup(m->name); - if(strlen(t) > 0) - t[strlen(t)-1] = '\0'; - deletestr = egrow(deletestr, " ", t); - } - mesgmenudel(w, mbox, m); - mesgdel(mbox, m); - } - if(fswrite(mbox->ctlfd, deletestr, strlen(deletestr)) < 0) - fprint(2, "Mail: warning: error removing mail message files: %r\n"); - free(deletestr); - winselect(w, "0", 0); - if(nopen == 0) - winclean(w); - mbox->dirty = 0; + nopen = 0; + for (m = mbox->head; m != nil; m = next) { + next = m->next; + if (m->deleted == 0) + continue; + if (m->opened) { + nopen++; + continue; + } + if (m->writebackdel) { + /* messages deleted by plumb message are not removed again */ + t = estrdup(m->name); + if (strlen(t) > 0) + t[strlen(t) - 1] = '\0'; + deletestr = egrow(deletestr, " ", t); + } + mesgmenudel(w, mbox, m); + mesgdel(mbox, m); + } + if (fswrite(mbox->ctlfd, deletestr, strlen(deletestr)) < 0) + fprint(2, "Mail: warning: error removing mail message files: %r\n"); + free(deletestr); + winselect(w, "0", 0); + if (nopen == 0) + winclean(w); + mbox->dirty = 0; } /* name is a full file name, but it might not belong to us */ -Message* -mesglookupfile(Message *mbox, char *name, char *digest) -{ - int k, n; +Message* mesglookupfile(Message* mbox, char* name, char* digest) { + int k, n; - k = strlen(name); - n = strlen(mbox->name); - if(k==0 || strncmp(name, mbox->name, n) != 0){ -/* fprint(2, "Mail: message %s not in this mailbox\n", name); */ - return nil; - } - return mesglookup(mbox, name+n, digest); + k = strlen(name); + n = strlen(mbox->name); + if (k == 0 || strncmp(name, mbox->name, n) != 0) { + /* fprint(2, "Mail: message %s not in this mailbox\n", name); */ + return nil; + } + return mesglookup(mbox, name + n, digest); }
M mail/reply.cmail/reply.c

@@ -7,574 +7,540 @@ #include <plumb.h>

#include <9pclient.h> #include "dat.h" -static int replyid; +static int replyid; -int -quote(Message *m, CFid *fid, char *dir, char *quotetext) -{ - char *body, *type; - int i, n, nlines; - char **lines; +int quote(Message* m, CFid* fid, char* dir, char* quotetext) { + char *body, *type; + int i, n, nlines; + char** lines; - if(quotetext){ - body = quotetext; - n = strlen(body); - type = nil; - }else{ - /* look for first textual component to quote */ - type = readfile(dir, "type", &n); - if(type == nil){ - print("no type in %s\n", dir); - return 0; - } - if(strncmp(type, "multipart/", 10)==0 || strncmp(type, "message/", 8)==0){ - dir = estrstrdup(dir, "1/"); - if(quote(m, fid, dir, nil)){ - free(type); - free(dir); - return 1; - } - free(dir); - } - if(strncmp(type, "text", 4) != 0){ - free(type); - return 0; - } - body = readbody(m->type, dir, &n); - if(body == nil) - return 0; - } - nlines = 0; - for(i=0; i<n; i++) - if(body[i] == '\n') - nlines++; - nlines++; - lines = emalloc(nlines*sizeof(char*)); - nlines = getfields(body, lines, nlines, 0, "\n"); - /* delete leading and trailing blank lines */ - i = 0; - while(i<nlines && lines[i][0]=='\0') - i++; - while(i<nlines && lines[nlines-1][0]=='\0') - nlines--; - while(i < nlines){ - fsprint(fid, ">%s%s\n", lines[i][0]=='>'? "" : " ", lines[i]); - i++; - } - free(lines); - free(body); /* will free quotetext if non-nil */ - free(type); - return 1; + if (quotetext) { + body = quotetext; + n = strlen(body); + type = nil; + } else { + /* look for first textual component to quote */ + type = readfile(dir, "type", &n); + if (type == nil) { + print("no type in %s\n", dir); + return 0; + } + if ( + strncmp(type, "multipart/", 10) == 0 || + strncmp(type, "message/", 8) == 0) { + dir = estrstrdup(dir, "1/"); + if (quote(m, fid, dir, nil)) { + free(type); + free(dir); + return 1; + } + free(dir); + } + if (strncmp(type, "text", 4) != 0) { + free(type); + return 0; + } + body = readbody(m->type, dir, &n); + if (body == nil) + return 0; + } + nlines = 0; + for (i = 0; i < n; i++) + if (body[i] == '\n') + nlines++; + nlines++; + lines = emalloc(nlines * sizeof(char*)); + nlines = getfields(body, lines, nlines, 0, "\n"); + /* delete leading and trailing blank lines */ + i = 0; + while (i < nlines && lines[i][0] == '\0') + i++; + while (i < nlines && lines[nlines - 1][0] == '\0') + nlines--; + while (i < nlines) { + fsprint(fid, ">%s%s\n", lines[i][0] == '>' ? "" : " ", lines[i]); + i++; + } + free(lines); + free(body); /* will free quotetext if non-nil */ + free(type); + return 1; } -void -mkreply(Message *m, char *label, char *to, Plumbattr *attr, char *quotetext) -{ - char buf[100]; - CFid *fd; - Message *r; - char *dir, *t; - int quotereply; - Plumbattr *a; +void mkreply( + Message* m, char* label, char* to, Plumbattr* attr, char* quotetext) { + char buf[100]; + CFid* fd; + Message* r; + char *dir, *t; + int quotereply; + Plumbattr* a; - quotereply = (label[0] == 'Q'); - - if(quotereply && m && m->replywinid > 0){ - snprint(buf, sizeof buf, "%d/body", m->replywinid); - if((fd = fsopen(acmefs, buf, OWRITE)) != nil){ - dir = estrstrdup(mbox.name, m->name); - quote(m, fd, dir, quotetext); - free(dir); - return; - } - } - - r = emalloc(sizeof(Message)); - r->isreply = 1; - if(m != nil) - r->replyname = estrdup(m->name); - r->next = replies.head; - r->prev = nil; - if(replies.head != nil) - replies.head->prev = r; - replies.head = r; - if(replies.tail == nil) - replies.tail = r; - r->name = emalloc(strlen(mbox.name)+strlen(label)+10); - sprint(r->name, "%s%s%d", mbox.name, label, ++replyid); - r->w = newwindow(); - if(m) - m->replywinid = r->w->id; - winname(r->w, r->name); - ctlprint(r->w->ctl, "cleartag"); - wintagwrite(r->w, "fmt Look Post Undo", 4+5+5+4); - r->tagposted = 1; - threadcreate(mesgctl, r, STACK); - winopenbody(r->w, OWRITE); - if(to!=nil && to[0]!='\0') - fsprint(r->w->body, "%s\n", to); - for(a=attr; a; a=a->next) - fsprint(r->w->body, "%s: %s\n", a->name, a->value); - dir = nil; - if(m != nil){ - dir = estrstrdup(mbox.name, m->name); - if(to == nil && attr == nil){ - /* Reply goes to replyto; Reply all goes to From and To and CC */ - if(strstr(label, "all") == nil) - fsprint(r->w->body, "To: %s\n", m->replyto); - else{ /* Replyall */ - if(strlen(m->from) > 0) - fsprint(r->w->body, "To: %s\n", m->from); - if(strlen(m->to) > 0) - fsprint(r->w->body, "To: %s\n", m->to); - if(strlen(m->cc) > 0) - fsprint(r->w->body, "CC: %s\n", m->cc); - } - } - if(strlen(m->subject) > 0){ - t = "Subject: Re: "; - if(strlen(m->subject) >= 3) - if(tolower(m->subject[0])=='r' && tolower(m->subject[1])=='e' && m->subject[2]==':') - t = "Subject: "; - fsprint(r->w->body, "%s%s\n", t, m->subject); - } - if(!quotereply){ - fsprint(r->w->body, "Include: %sraw\n", dir); - free(dir); - } - } - fsprint(r->w->body, "\n"); - if(m == nil) - fsprint(r->w->body, "\n"); - else if(quotereply){ - quote(m, r->w->body, dir, quotetext); - free(dir); - } - winclosebody(r->w); - if(m==nil && (to==nil || to[0]=='\0')) - winselect(r->w, "0", 0); - else - winselect(r->w, "$", 0); - winclean(r->w); - windormant(r->w); + quotereply = (label[0] == 'Q'); + + if (quotereply && m && m->replywinid > 0) { + snprint(buf, sizeof buf, "%d/body", m->replywinid); + if ((fd = fsopen(acmefs, buf, OWRITE)) != nil) { + dir = estrstrdup(mbox.name, m->name); + quote(m, fd, dir, quotetext); + free(dir); + return; + } + } + + r = emalloc(sizeof(Message)); + r->isreply = 1; + if (m != nil) + r->replyname = estrdup(m->name); + r->next = replies.head; + r->prev = nil; + if (replies.head != nil) + replies.head->prev = r; + replies.head = r; + if (replies.tail == nil) + replies.tail = r; + r->name = emalloc(strlen(mbox.name) + strlen(label) + 10); + sprint(r->name, "%s%s%d", mbox.name, label, ++replyid); + r->w = newwindow(); + if (m) + m->replywinid = r->w->id; + winname(r->w, r->name); + ctlprint(r->w->ctl, "cleartag"); + wintagwrite(r->w, "fmt Look Post Undo", 4 + 5 + 5 + 4); + r->tagposted = 1; + threadcreate(mesgctl, r, STACK); + winopenbody(r->w, OWRITE); + if (to != nil && to[0] != '\0') + fsprint(r->w->body, "%s\n", to); + for (a = attr; a; a = a->next) + fsprint(r->w->body, "%s: %s\n", a->name, a->value); + dir = nil; + if (m != nil) { + dir = estrstrdup(mbox.name, m->name); + if (to == nil && attr == nil) { + /* Reply goes to replyto; Reply all goes to From and To and CC */ + if (strstr(label, "all") == nil) + fsprint(r->w->body, "To: %s\n", m->replyto); + else { /* Replyall */ + if (strlen(m->from) > 0) + fsprint(r->w->body, "To: %s\n", m->from); + if (strlen(m->to) > 0) + fsprint(r->w->body, "To: %s\n", m->to); + if (strlen(m->cc) > 0) + fsprint(r->w->body, "CC: %s\n", m->cc); + } + } + if (strlen(m->subject) > 0) { + t = "Subject: Re: "; + if (strlen(m->subject) >= 3) + if ( + tolower(m->subject[0]) == 'r' && tolower(m->subject[1]) == 'e' && + m->subject[2] == ':') + t = "Subject: "; + fsprint(r->w->body, "%s%s\n", t, m->subject); + } + if (!quotereply) { + fsprint(r->w->body, "Include: %sraw\n", dir); + free(dir); + } + } + fsprint(r->w->body, "\n"); + if (m == nil) + fsprint(r->w->body, "\n"); + else if (quotereply) { + quote(m, r->w->body, dir, quotetext); + free(dir); + } + winclosebody(r->w); + if (m == nil && (to == nil || to[0] == '\0')) + winselect(r->w, "0", 0); + else + winselect(r->w, "$", 0); + winclean(r->w); + windormant(r->w); } -void -delreply(Message *m) -{ - if(m->next == nil) - replies.tail = m->prev; - else - m->next->prev = m->prev; - if(m->prev == nil) - replies.head = m->next; - else - m->prev->next = m->next; - mesgfreeparts(m); - free(m); +void delreply(Message* m) { + if (m->next == nil) + replies.tail = m->prev; + else + m->next->prev = m->prev; + if (m->prev == nil) + replies.head = m->next; + else + m->prev->next = m->next; + mesgfreeparts(m); + free(m); } -/* copy argv to stack and free the incoming strings, so we don't leak argument vectors */ -void -buildargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR]) -{ - int i, n; - char *s, *a; +/* copy argv to stack and free the incoming strings, so we don't leak argument + * vectors */ +void buildargv(char** inargv, char* argv[NARGS + 1], char args[NARGCHAR]) { + int i, n; + char *s, *a; - s = args; - for(i=0; i<NARGS; i++){ - a = inargv[i]; - if(a == nil) - break; - n = strlen(a)+1; - if((s-args)+n >= NARGCHAR) /* too many characters */ - break; - argv[i] = s; - memmove(s, a, n); - s += n; - free(a); - } - argv[i] = nil; + s = args; + for (i = 0; i < NARGS; i++) { + a = inargv[i]; + if (a == nil) + break; + n = strlen(a) + 1; + if ((s - args) + n >= NARGCHAR) /* too many characters */ + break; + argv[i] = s; + memmove(s, a, n); + s += n; + free(a); + } + argv[i] = nil; } -void -execproc(void *v) -{ - struct Exec *e; - int p[2], q[2]; - char *prog; - char *argv[NARGS+1], args[NARGCHAR]; - int fd[3]; +void execproc(void* v) { + struct Exec* e; + int p[2], q[2]; + char* prog; + char *argv[NARGS + 1], args[NARGCHAR]; + int fd[3]; - e = v; - p[0] = e->p[0]; - p[1] = e->p[1]; - q[0] = e->q[0]; - q[1] = e->q[1]; - prog = e->prog; /* known not to be malloc'ed */ - - fd[0] = dup(p[0], -1); - if(q[0]) - fd[1] = dup(q[1], -1); - else - fd[1] = dup(1, -1); - fd[2] = dup(2, -2); - sendul(e->sync, 1); - buildargv(e->argv, argv, args); - free(e->argv); - chanfree(e->sync); - free(e); - - threadexec(nil, fd, prog, argv); - close(fd[0]); - close(fd[1]); - close(fd[2]); + e = v; + p[0] = e->p[0]; + p[1] = e->p[1]; + q[0] = e->q[0]; + q[1] = e->q[1]; + prog = e->prog; /* known not to be malloc'ed */ + + fd[0] = dup(p[0], -1); + if (q[0]) + fd[1] = dup(q[1], -1); + else + fd[1] = dup(1, -1); + fd[2] = dup(2, -2); + sendul(e->sync, 1); + buildargv(e->argv, argv, args); + free(e->argv); + chanfree(e->sync); + free(e); + + threadexec(nil, fd, prog, argv); + close(fd[0]); + close(fd[1]); + close(fd[2]); - fprint(2, "Mail: can't exec %s: %r\n", prog); - threadexits("can't exec"); + fprint(2, "Mail: can't exec %s: %r\n", prog); + threadexits("can't exec"); } -enum{ - ATTACH, - BCC, - CC, - FROM, - INCLUDE, - TO -}; +enum { ATTACH, BCC, CC, FROM, INCLUDE, TO }; -char *headers[] = { - "attach:", - "bcc:", - "cc:", - "from:", - "include:", - "to:", - nil -}; +char* headers[] = {"attach:", "bcc:", "cc:", "from:", "include:", "to:", nil}; -int -whichheader(char *h) -{ - int i; +int whichheader(char* h) { + int i; - for(i=0; headers[i]!=nil; i++) - if(cistrcmp(h, headers[i]) == 0) - return i; - return -1; + for (i = 0; headers[i] != nil; i++) + if (cistrcmp(h, headers[i]) == 0) + return i; + return -1; } -char *tolist[200]; -char *cclist[200]; -char *bcclist[200]; +char* tolist[200]; +char* cclist[200]; +char* bcclist[200]; int ncc, nbcc, nto; -char *attlist[200]; -char included[200]; +char* attlist[200]; +char included[200]; -int -addressed(char *name) -{ - int i; +int addressed(char* name) { + int i; - for(i=0; i<nto; i++) - if(strcmp(name, tolist[i]) == 0) - return 1; - for(i=0; i<ncc; i++) - if(strcmp(name, cclist[i]) == 0) - return 1; - for(i=0; i<nbcc; i++) - if(strcmp(name, bcclist[i]) == 0) - return 1; - return 0; + for (i = 0; i < nto; i++) + if (strcmp(name, tolist[i]) == 0) + return 1; + for (i = 0; i < ncc; i++) + if (strcmp(name, cclist[i]) == 0) + return 1; + for (i = 0; i < nbcc; i++) + if (strcmp(name, bcclist[i]) == 0) + return 1; + return 0; } -char* -skipbl(char *s, char *e) -{ - while(s < e){ - if(*s!=' ' && *s!='\t' && *s!=',') - break; - s++; - } - return s; +char* skipbl(char* s, char* e) { + while (s < e) { + if (*s != ' ' && *s != '\t' && *s != ',') + break; + s++; + } + return s; } -char* -findbl(char *s, char *e) -{ - while(s < e){ - if(*s==' ' || *s=='\t' || *s==',') - break; - s++; - } - return s; +char* findbl(char* s, char* e) { + while (s < e) { + if (*s == ' ' || *s == '\t' || *s == ',') + break; + s++; + } + return s; } /* - * comma-separate possibly blank-separated strings in line; e points before newline + * comma-separate possibly blank-separated strings in line; e points before + * newline */ -void -commas(char *s, char *e) -{ - char *t; +void commas(char* s, char* e) { + char* t; - /* may have initial blanks */ - s = skipbl(s, e); - while(s < e){ - s = findbl(s, e); - if(s == e) - break; - t = skipbl(s, e); - if(t == e) /* no more words */ - break; - /* patch comma */ - *s++ = ','; - while(s < t) - *s++ = ' '; - } + /* may have initial blanks */ + s = skipbl(s, e); + while (s < e) { + s = findbl(s, e); + if (s == e) + break; + t = skipbl(s, e); + if (t == e) /* no more words */ + break; + /* patch comma */ + *s++ = ','; + while (s < t) + *s++ = ' '; + } } -int -print2(int fd, int ofd, char *fmt, ...) -{ - int m, n; - char *s; - va_list arg; +int print2(int fd, int ofd, char* fmt, ...) { + int m, n; + char* s; + va_list arg; - va_start(arg, fmt); - s = vsmprint(fmt, arg); - va_end(arg); - if(s == nil) - return -1; - m = strlen(s); - n = write(fd, s, m); - if(ofd > 0) - write(ofd, s, m); - return n; + va_start(arg, fmt); + s = vsmprint(fmt, arg); + va_end(arg); + if (s == nil) + return -1; + m = strlen(s); + n = write(fd, s, m); + if (ofd > 0) + write(ofd, s, m); + return n; } -void -write2(int fd, int ofd, char *buf, int n, int nofrom) -{ - char *from, *p; - int m; +void write2(int fd, int ofd, char* buf, int n, int nofrom) { + char *from, *p; + int m; - write(fd, buf, n); + write(fd, buf, n); - if(ofd <= 0) - return; + if (ofd <= 0) + return; - if(nofrom == 0){ - write(ofd, buf, n); - return; - } + if (nofrom == 0) { + write(ofd, buf, n); + return; + } - /* need to escape leading From lines to avoid corrupting 'outgoing' mailbox */ - for(p=buf; *p; p+=m){ - from = cistrstr(p, "from"); - if(from == nil) - m = n; - else - m = from - p; - if(m > 0) - write(ofd, p, m); - if(from){ - if(p==buf || from[-1]=='\n') - write(ofd, " ", 1); /* escape with space if From is at start of line */ - write(ofd, from, 4); - m += 4; - } - n -= m; - } + /* need to escape leading From lines to avoid corrupting 'outgoing' mailbox */ + for (p = buf; *p; p += m) { + from = cistrstr(p, "from"); + if (from == nil) + m = n; + else + m = from - p; + if (m > 0) + write(ofd, p, m); + if (from) { + if (p == buf || from[-1] == '\n') + write(ofd, " ", 1); /* escape with space if From is at start of line */ + write(ofd, from, 4); + m += 4; + } + n -= m; + } } -void -mesgsend(Message *m) -{ - char *s, *body, *to; - int i, j, h, n, natt, p[2]; - struct Exec *e; - Channel *sync; - int first, nfld, delit, ofd; - char *copy, *fld[100], *now; +void mesgsend(Message* m) { + char *s, *body, *to; + int i, j, h, n, natt, p[2]; + struct Exec* e; + Channel* sync; + int first, nfld, delit, ofd; + char *copy, *fld[100], *now; - body = winreadbody(m->w, &n); - /* assemble to: list from first line, to: line, and cc: line */ - nto = 0; - natt = 0; - ncc = 0; - nbcc = 0; - first = 1; - to = body; - for(;;){ - for(s=to; *s!='\n'; s++) - if(*s == '\0'){ - free(body); - return; - } - if(s++ == to) /* blank line */ - break; - /* make copy of line to tokenize */ - copy = emalloc(s-to); - memmove(copy, to, s-to); - copy[s-to-1] = '\0'; - nfld = tokenizec(copy, fld, nelem(fld), ", \t"); - if(nfld == 0){ - free(copy); - break; - } - n -= s-to; - switch(h = whichheader(fld[0])){ - case TO: - case FROM: - delit = 1; - commas(to+strlen(fld[0]), s-1); - for(i=1; i<nfld && nto<nelem(tolist); i++) - if(!addressed(fld[i])) - tolist[nto++] = estrdup(fld[i]); - break; - case BCC: - delit = 1; - commas(to+strlen(fld[0]), s-1); - for(i=1; i<nfld && nbcc<nelem(bcclist); i++) - if(!addressed(fld[i])) - bcclist[nbcc++] = estrdup(fld[i]); - break; - case CC: - delit = 1; - commas(to+strlen(fld[0]), s-1); - for(i=1; i<nfld && ncc<nelem(cclist); i++) - if(!addressed(fld[i])) - cclist[ncc++] = estrdup(fld[i]); - break; - case ATTACH: - case INCLUDE: - delit = 1; - for(i=1; i<nfld && natt<nelem(attlist); i++){ - attlist[natt] = estrdup(fld[i]); - included[natt++] = (h == INCLUDE); - } - break; - default: - if(first){ - delit = 1; - for(i=0; i<nfld && nto<nelem(tolist); i++) - tolist[nto++] = estrdup(fld[i]); - }else /* ignore it */ - delit = 0; - break; - } - if(delit){ - /* delete line from body */ - memmove(to, s, n+1); - }else - to = s; - free(copy); - first = 0; - } + body = winreadbody(m->w, &n); + /* assemble to: list from first line, to: line, and cc: line */ + nto = 0; + natt = 0; + ncc = 0; + nbcc = 0; + first = 1; + to = body; + for (;;) { + for (s = to; *s != '\n'; s++) + if (*s == '\0') { + free(body); + return; + } + if (s++ == to) /* blank line */ + break; + /* make copy of line to tokenize */ + copy = emalloc(s - to); + memmove(copy, to, s - to); + copy[s - to - 1] = '\0'; + nfld = tokenizec(copy, fld, nelem(fld), ", \t"); + if (nfld == 0) { + free(copy); + break; + } + n -= s - to; + switch (h = whichheader(fld[0])) { + case TO: + case FROM: + delit = 1; + commas(to + strlen(fld[0]), s - 1); + for (i = 1; i < nfld && nto < nelem(tolist); i++) + if (!addressed(fld[i])) + tolist[nto++] = estrdup(fld[i]); + break; + case BCC: + delit = 1; + commas(to + strlen(fld[0]), s - 1); + for (i = 1; i < nfld && nbcc < nelem(bcclist); i++) + if (!addressed(fld[i])) + bcclist[nbcc++] = estrdup(fld[i]); + break; + case CC: + delit = 1; + commas(to + strlen(fld[0]), s - 1); + for (i = 1; i < nfld && ncc < nelem(cclist); i++) + if (!addressed(fld[i])) + cclist[ncc++] = estrdup(fld[i]); + break; + case ATTACH: + case INCLUDE: + delit = 1; + for (i = 1; i < nfld && natt < nelem(attlist); i++) { + attlist[natt] = estrdup(fld[i]); + included[natt++] = (h == INCLUDE); + } + break; + default: + if (first) { + delit = 1; + for (i = 0; i < nfld && nto < nelem(tolist); i++) + tolist[nto++] = estrdup(fld[i]); + } else /* ignore it */ + delit = 0; + break; + } + if (delit) { + /* delete line from body */ + memmove(to, s, n + 1); + } else + to = s; + free(copy); + first = 0; + } - ofd = open(outgoing, OWRITE|OCEXEC); /* no error check necessary */ - if(ofd > 0){ - /* From dhog Fri Aug 24 22:13:00 EDT 2001 */ - now = ctime(time(0)); - seek(ofd, 0, 2); - fprint(ofd, "From %s %s", user, now); - fprint(ofd, "From: %s\n", user); - fprint(ofd, "Date: %s", now); - for(i=0; i<natt; i++) - if(included[i]) - fprint(ofd, "Include: %s\n", attlist[i]); - else - fprint(ofd, "Attach: %s\n", attlist[i]); - /* needed because mail is by default Latin-1 */ - fprint(ofd, "Content-Type: text/plain; charset=\"UTF-8\"\n"); - fprint(ofd, "Content-Transfer-Encoding: 8bit\n"); - } + ofd = open(outgoing, OWRITE | OCEXEC); /* no error check necessary */ + if (ofd > 0) { + /* From dhog Fri Aug 24 22:13:00 EDT 2001 */ + now = ctime(time(0)); + seek(ofd, 0, 2); + fprint(ofd, "From %s %s", user, now); + fprint(ofd, "From: %s\n", user); + fprint(ofd, "Date: %s", now); + for (i = 0; i < natt; i++) + if (included[i]) + fprint(ofd, "Include: %s\n", attlist[i]); + else + fprint(ofd, "Attach: %s\n", attlist[i]); + /* needed because mail is by default Latin-1 */ + fprint(ofd, "Content-Type: text/plain; charset=\"UTF-8\"\n"); + fprint(ofd, "Content-Transfer-Encoding: 8bit\n"); + } - e = emalloc(sizeof(struct Exec)); - if(pipe(p) < 0) - error("can't create pipe: %r"); - e->p[0] = p[0]; - e->p[1] = p[1]; - e->prog = unsharp("#9/bin/upas/marshal"); - e->argv = emalloc((1+1+2+4*natt+1)*sizeof(char*)); - e->argv[0] = estrdup("marshal"); - e->argv[1] = estrdup("-8"); - j = 2; - if(m->replyname){ - e->argv[j++] = estrdup("-R"); - e->argv[j++] = estrstrdup(mbox.name, m->replyname); - } - for(i=0; i<natt; i++){ - if(included[i]) - e->argv[j++] = estrdup("-A"); - else - e->argv[j++] = estrdup("-a"); - e->argv[j++] = estrdup(attlist[i]); - } - sync = chancreate(sizeof(int), 0); - e->sync = sync; - proccreate(execproc, e, EXECSTACK); - recvul(sync); - /* close(p[0]); */ + e = emalloc(sizeof(struct Exec)); + if (pipe(p) < 0) + error("can't create pipe: %r"); + e->p[0] = p[0]; + e->p[1] = p[1]; + e->prog = unsharp("#9/bin/upas/marshal"); + e->argv = emalloc((1 + 1 + 2 + 4 * natt + 1) * sizeof(char*)); + e->argv[0] = estrdup("marshal"); + e->argv[1] = estrdup("-8"); + j = 2; + if (m->replyname) { + e->argv[j++] = estrdup("-R"); + e->argv[j++] = estrstrdup(mbox.name, m->replyname); + } + for (i = 0; i < natt; i++) { + if (included[i]) + e->argv[j++] = estrdup("-A"); + else + e->argv[j++] = estrdup("-a"); + e->argv[j++] = estrdup(attlist[i]); + } + sync = chancreate(sizeof(int), 0); + e->sync = sync; + proccreate(execproc, e, EXECSTACK); + recvul(sync); + /* close(p[0]); */ - /* using marshal -8, so generate rfc822 headers */ - if(nto > 0){ - print2(p[1], ofd, "To: "); - for(i=0; i<nto-1; i++) - print2(p[1], ofd, "%s, ", tolist[i]); - print2(p[1], ofd, "%s\n", tolist[i]); - } - if(ncc > 0){ - print2(p[1], ofd, "CC: "); - for(i=0; i<ncc-1; i++) - print2(p[1], ofd, "%s, ", cclist[i]); - print2(p[1], ofd, "%s\n", cclist[i]); - } - if(nbcc > 0){ - print2(p[1], ofd, "BCC: "); - for(i=0; i<nbcc-1; i++) - print2(p[1], ofd, "%s, ", bcclist[i]); - print2(p[1], ofd, "%s\n", bcclist[i]); - } + /* using marshal -8, so generate rfc822 headers */ + if (nto > 0) { + print2(p[1], ofd, "To: "); + for (i = 0; i < nto - 1; i++) + print2(p[1], ofd, "%s, ", tolist[i]); + print2(p[1], ofd, "%s\n", tolist[i]); + } + if (ncc > 0) { + print2(p[1], ofd, "CC: "); + for (i = 0; i < ncc - 1; i++) + print2(p[1], ofd, "%s, ", cclist[i]); + print2(p[1], ofd, "%s\n", cclist[i]); + } + if (nbcc > 0) { + print2(p[1], ofd, "BCC: "); + for (i = 0; i < nbcc - 1; i++) + print2(p[1], ofd, "%s, ", bcclist[i]); + print2(p[1], ofd, "%s\n", bcclist[i]); + } - i = strlen(body); - if(i > 0) - write2(p[1], ofd, body, i, 1); + i = strlen(body); + if (i > 0) + write2(p[1], ofd, body, i, 1); - /* guarantee a blank line, to ensure attachments are separated from body */ - if(i==0 || body[i-1]!='\n') - write2(p[1], ofd, "\n\n", 2, 0); - else if(i>1 && body[i-2]!='\n') - write2(p[1], ofd, "\n", 1, 0); + /* guarantee a blank line, to ensure attachments are separated from body */ + if (i == 0 || body[i - 1] != '\n') + write2(p[1], ofd, "\n\n", 2, 0); + else if (i > 1 && body[i - 2] != '\n') + write2(p[1], ofd, "\n", 1, 0); - /* these look like pseudo-attachments in the "outgoing" box */ - if(ofd>0 && natt>0){ - for(i=0; i<natt; i++) - if(included[i]) - fprint(ofd, "=====> Include: %s\n", attlist[i]); - else - fprint(ofd, "=====> Attach: %s\n", attlist[i]); - } - if(ofd > 0) - write(ofd, "\n", 1); + /* these look like pseudo-attachments in the "outgoing" box */ + if (ofd > 0 && natt > 0) { + for (i = 0; i < natt; i++) + if (included[i]) + fprint(ofd, "=====> Include: %s\n", attlist[i]); + else + fprint(ofd, "=====> Attach: %s\n", attlist[i]); + } + if (ofd > 0) + write(ofd, "\n", 1); - for(i=0; i<natt; i++) - free(attlist[i]); - close(ofd); - close(p[1]); - free(body); + for (i = 0; i < natt; i++) + free(attlist[i]); + close(ofd); + close(p[1]); + free(body); - if(m->replyname != nil) - mesgmenumark(mbox.w, m->replyname, "\t[replied]"); - if(m->name[0] == '/') - s = estrdup(m->name); - else - s = estrstrdup(mbox.name, m->name); - s = egrow(s, "-R", nil); - winname(m->w, s); - free(s); - winclean(m->w); - /* mark message unopened because it's no longer the original message */ - m->opened = 0; + if (m->replyname != nil) + mesgmenumark(mbox.w, m->replyname, "\t[replied]"); + if (m->name[0] == '/') + s = estrdup(m->name); + else + s = estrstrdup(mbox.name, m->name); + s = egrow(s, "-R", nil); + winname(m->w, s); + free(s); + winclean(m->w); + /* mark message unopened because it's no longer the original message */ + m->opened = 0; }
M mail/util.cmail/util.c

@@ -6,102 +6,85 @@ #include <plumb.h>

#include <9pclient.h> #include "dat.h" -void* -emalloc(uint n) -{ - void *p; +void* emalloc(uint n) { + void* p; - p = malloc(n); - if(p == nil) - error("can't malloc: %r"); - memset(p, 0, n); - setmalloctag(p, getcallerpc(&n)); - return p; + p = malloc(n); + if (p == nil) + error("can't malloc: %r"); + memset(p, 0, n); + setmalloctag(p, getcallerpc(&n)); + return p; } -void* -erealloc(void *p, uint n) -{ - p = realloc(p, n); - if(p == nil) - error("can't realloc: %r"); - setmalloctag(p, getcallerpc(&n)); - return p; +void* erealloc(void* p, uint n) { + p = realloc(p, n); + if (p == nil) + error("can't realloc: %r"); + setmalloctag(p, getcallerpc(&n)); + return p; } -char* -estrdup(char *s) -{ - char *t; +char* estrdup(char* s) { + char* t; - t = emalloc(strlen(s)+1); - strcpy(t, s); - return t; + t = emalloc(strlen(s) + 1); + strcpy(t, s); + return t; } -char* -estrstrdup(char *s, char *t) -{ - char *u; +char* estrstrdup(char* s, char* t) { + char* u; - u = emalloc(strlen(s)+strlen(t)+1); - strcpy(u, s); - strcat(u, t); - return u; + u = emalloc(strlen(s) + strlen(t) + 1); + strcpy(u, s); + strcat(u, t); + return u; } -char* -eappend(char *s, char *sep, char *t) -{ - char *u; +char* eappend(char* s, char* sep, char* t) { + char* u; - if(t == nil) - u = estrstrdup(s, sep); - else{ - u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1); - strcpy(u, s); - strcat(u, sep); - strcat(u, t); - } - free(s); - return u; + if (t == nil) + u = estrstrdup(s, sep); + else { + u = emalloc(strlen(s) + strlen(sep) + strlen(t) + 1); + strcpy(u, s); + strcat(u, sep); + strcat(u, t); + } + free(s); + return u; } -char* -egrow(char *s, char *sep, char *t) -{ - s = eappend(s, sep, t); - free(t); - return s; +char* egrow(char* s, char* sep, char* t) { + s = eappend(s, sep, t); + free(t); + return s; } -void -error(char *fmt, ...) -{ - Fmt f; - char buf[64]; - va_list arg; +void error(char* fmt, ...) { + Fmt f; + char buf[64]; + va_list arg; - fmtfdinit(&f, 2, buf, sizeof buf); - fmtprint(&f, "Mail: "); - va_start(arg, fmt); - fmtvprint(&f, fmt, arg); - va_end(arg); - fmtprint(&f, "\n"); - fmtfdflush(&f); - threadexitsall(fmt); + fmtfdinit(&f, 2, buf, sizeof buf); + fmtprint(&f, "Mail: "); + va_start(arg, fmt); + fmtvprint(&f, fmt, arg); + va_end(arg); + fmtprint(&f, "\n"); + fmtfdflush(&f); + threadexitsall(fmt); } -void -ctlprint(CFid *fd, char *fmt, ...) -{ - int n; - va_list arg; +void ctlprint(CFid* fd, char* fmt, ...) { + int n; + va_list arg; - va_start(arg, fmt); - n = fsvprint(fd, fmt, arg); - va_end(arg); - if(n <= 0) - error("control file write error: %r"); + va_start(arg, fmt); + n = fsvprint(fd, fmt, arg); + va_end(arg); + if (n <= 0) + error("control file write error: %r"); } -
M mail/win.cmail/win.c

@@ -6,374 +6,325 @@ #include <plumb.h>

#include <9pclient.h> #include "dat.h" -Window* -newwindow(void) -{ - char buf[12]; - Window *w; +Window* newwindow(void) { + char buf[12]; + Window* w; - w = emalloc(sizeof(Window)); - w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC); - if(w->ctl == nil || fsread(w->ctl, buf, 12)!=12) - error("can't open window ctl file: %r"); + w = emalloc(sizeof(Window)); + w->ctl = fsopen(acmefs, "new/ctl", ORDWR | OCEXEC); + if (w->ctl == nil || fsread(w->ctl, buf, 12) != 12) + error("can't open window ctl file: %r"); - w->id = atoi(buf); - w->event = winopenfile(w, "event"); - w->addr = nil; /* will be opened when needed */ - w->body = nil; - w->data = nil; - w->cevent = chancreate(sizeof(Event*), 0); - w->ref = 1; - return w; + w->id = atoi(buf); + w->event = winopenfile(w, "event"); + w->addr = nil; /* will be opened when needed */ + w->body = nil; + w->data = nil; + w->cevent = chancreate(sizeof(Event*), 0); + w->ref = 1; + return w; } -void -winincref(Window *w) -{ - qlock(&w->lk); - ++w->ref; - qunlock(&w->lk); +void winincref(Window* w) { + qlock(&w->lk); + ++w->ref; + qunlock(&w->lk); } -void -windecref(Window *w) -{ - qlock(&w->lk); - if(--w->ref > 0){ - qunlock(&w->lk); - return; - } - fsclose(w->event); - chanfree(w->cevent); - free(w); +void windecref(Window* w) { + qlock(&w->lk); + if (--w->ref > 0) { + qunlock(&w->lk); + return; + } + fsclose(w->event); + chanfree(w->cevent); + free(w); } -void -winsetdump(Window *w, char *dir, char *cmd) -{ - if(dir != nil) - ctlprint(w->ctl, "dumpdir %s\n", dir); - if(cmd != nil) - ctlprint(w->ctl, "dump %s\n", cmd); +void winsetdump(Window* w, char* dir, char* cmd) { + if (dir != nil) + ctlprint(w->ctl, "dumpdir %s\n", dir); + if (cmd != nil) + ctlprint(w->ctl, "dump %s\n", cmd); } -void -wineventproc(void *v) -{ - Window *w; - int i; +void wineventproc(void* v) { + Window* w; + int i; - w = v; - for(i=0; ; i++){ - if(i >= NEVENT) - i = 0; - wingetevent(w, &w->e[i]); - sendp(w->cevent, &w->e[i]); - } + w = v; + for (i = 0;; i++) { + if (i >= NEVENT) + i = 0; + wingetevent(w, &w->e[i]); + sendp(w->cevent, &w->e[i]); + } } -static CFid* -winopenfile1(Window *w, char *f, int m) -{ - char buf[64]; - CFid* fd; +static CFid* winopenfile1(Window* w, char* f, int m) { + char buf[64]; + CFid* fd; - sprint(buf, "%d/%s", w->id, f); - fd = fsopen(acmefs, buf, m|OCEXEC); - if(fd == nil) - error("can't open window file %s: %r", f); - return fd; + sprint(buf, "%d/%s", w->id, f); + fd = fsopen(acmefs, buf, m | OCEXEC); + if (fd == nil) + error("can't open window file %s: %r", f); + return fd; } -CFid* -winopenfile(Window *w, char *f) -{ - return winopenfile1(w, f, ORDWR); -} +CFid* winopenfile(Window* w, char* f) { return winopenfile1(w, f, ORDWR); } -void -wintagwrite(Window *w, char *s, int n) -{ - CFid* fid; +void wintagwrite(Window* w, char* s, int n) { + CFid* fid; - fid = winopenfile(w, "tag"); - if(fswrite(fid, s, n) != n) - error("tag write: %r"); - fsclose(fid); + fid = winopenfile(w, "tag"); + if (fswrite(fid, s, n) != n) + error("tag write: %r"); + fsclose(fid); } -void -winname(Window *w, char *s) -{ - int len; - char *ns, *sp; - Rune r = L'␣'; /* visible space */ +void winname(Window* w, char* s) { + int len; + char *ns, *sp; + Rune r = L'␣'; /* visible space */ - len = 0; - ns = emalloc(strlen(s)*runelen(r) + 1); - for(sp = s; *sp != '\0'; sp++, len++){ - if(isspace(*sp)){ - len += runetochar(ns+len, &r)-1; - continue; - } - *(ns+len) = *sp; - } - ctlprint(w->ctl, "name %s\n", ns); - free(ns); - return; + len = 0; + ns = emalloc(strlen(s) * runelen(r) + 1); + for (sp = s; *sp != '\0'; sp++, len++) { + if (isspace(*sp)) { + len += runetochar(ns + len, &r) - 1; + continue; + } + *(ns + len) = *sp; + } + ctlprint(w->ctl, "name %s\n", ns); + free(ns); + return; } -void -winopenbody(Window *w, int mode) -{ - char buf[256]; - CFid* fid; +void winopenbody(Window* w, int mode) { + char buf[256]; + CFid* fid; - sprint(buf, "%d/body", w->id); - fid = fsopen(acmefs, buf, mode|OCEXEC); - w->body = fid; - if(w->body == nil) - error("can't open window body file: %r"); + sprint(buf, "%d/body", w->id); + fid = fsopen(acmefs, buf, mode | OCEXEC); + w->body = fid; + if (w->body == nil) + error("can't open window body file: %r"); } -void -winclosebody(Window *w) -{ - if(w->body != nil){ - fsclose(w->body); - w->body = nil; - } +void winclosebody(Window* w) { + if (w->body != nil) { + fsclose(w->body); + w->body = nil; + } } -void -winwritebody(Window *w, char *s, int n) -{ - if(w->body == nil) - winopenbody(w, OWRITE); - if(fswrite(w->body, s, n) != n) - error("write error to window: %r"); +void winwritebody(Window* w, char* s, int n) { + if (w->body == nil) + winopenbody(w, OWRITE); + if (fswrite(w->body, s, n) != n) + error("write error to window: %r"); } -int -wingetec(Window *w) -{ - if(w->nbuf == 0){ - w->nbuf = fsread(w->event, w->buf, sizeof w->buf); - if(w->nbuf <= 0){ - /* probably because window has exited, and only called by wineventproc, so just shut down */ - windecref(w); - threadexits(nil); - } - w->bufp = w->buf; - } - w->nbuf--; - return *w->bufp++; +int wingetec(Window* w) { + if (w->nbuf == 0) { + w->nbuf = fsread(w->event, w->buf, sizeof w->buf); + if (w->nbuf <= 0) { + /* probably because window has exited, and only called by wineventproc, so + * just shut down */ + windecref(w); + threadexits(nil); + } + w->bufp = w->buf; + } + w->nbuf--; + return *w->bufp++; } -int -wingeten(Window *w) -{ - int n, c; +int wingeten(Window* w) { + int n, c; - n = 0; - while('0'<=(c=wingetec(w)) && c<='9') - n = n*10+(c-'0'); - if(c != ' ') - error("event number syntax"); - return n; + n = 0; + while ('0' <= (c = wingetec(w)) && c <= '9') + n = n * 10 + (c - '0'); + if (c != ' ') + error("event number syntax"); + return n; } -int -wingeter(Window *w, char *buf, int *nb) -{ - Rune r; - int n; +int wingeter(Window* w, char* buf, int* nb) { + Rune r; + int n; - r = wingetec(w); - buf[0] = r; - n = 1; - if(r >= Runeself) { - while(!fullrune(buf, n)) - buf[n++] = wingetec(w); - chartorune(&r, buf); - } - *nb = n; - return r; + r = wingetec(w); + buf[0] = r; + n = 1; + if (r >= Runeself) { + while (!fullrune(buf, n)) + buf[n++] = wingetec(w); + chartorune(&r, buf); + } + *nb = n; + return r; } -void -wingetevent(Window *w, Event *e) -{ - int i, nb; +void wingetevent(Window* w, Event* e) { + int i, nb; - e->c1 = wingetec(w); - e->c2 = wingetec(w); - e->q0 = wingeten(w); - e->q1 = wingeten(w); - e->flag = wingeten(w); - e->nr = wingeten(w); - if(e->nr > EVENTSIZE) - error("event string too long"); - e->nb = 0; - for(i=0; i<e->nr; i++){ - e->r[i] = wingeter(w, e->b+e->nb, &nb); - e->nb += nb; - } - e->r[e->nr] = 0; - e->b[e->nb] = 0; - if(wingetec(w) != '\n') - error("event syntax error"); + e->c1 = wingetec(w); + e->c2 = wingetec(w); + e->q0 = wingeten(w); + e->q1 = wingeten(w); + e->flag = wingeten(w); + e->nr = wingeten(w); + if (e->nr > EVENTSIZE) + error("event string too long"); + e->nb = 0; + for (i = 0; i < e->nr; i++) { + e->r[i] = wingeter(w, e->b + e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if (wingetec(w) != '\n') + error("event syntax error"); } -void -winwriteevent(Window *w, Event *e) -{ - fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); +void winwriteevent(Window* w, Event* e) { + fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1); } -void -winread(Window *w, uint q0, uint q1, char *data) -{ - int m, n, nr; - char buf[256]; +void winread(Window* w, uint q0, uint q1, char* data) { + int m, n, nr; + char buf[256]; - if(w->addr == nil) - w->addr = winopenfile(w, "addr"); - if(w->data == nil) - w->data = winopenfile(w, "data"); - m = q0; - while(m < q1){ - n = sprint(buf, "#%d", m); - if(fswrite(w->addr, buf, n) != n) - error("error writing addr: %r"); - n = fsread(w->data, buf, sizeof buf); - if(n <= 0) - error("reading data: %r"); - nr = utfnlen(buf, n); - while(m+nr >q1){ - do; while(n>0 && (buf[--n]&0xC0)==0x80); - --nr; - } - if(n == 0) - break; - memmove(data, buf, n); - data += n; - *data = 0; - m += nr; - } + if (w->addr == nil) + w->addr = winopenfile(w, "addr"); + if (w->data == nil) + w->data = winopenfile(w, "data"); + m = q0; + while (m < q1) { + n = sprint(buf, "#%d", m); + if (fswrite(w->addr, buf, n) != n) + error("error writing addr: %r"); + n = fsread(w->data, buf, sizeof buf); + if (n <= 0) + error("reading data: %r"); + nr = utfnlen(buf, n); + while (m + nr > q1) { + do + ; + while (n > 0 && (buf[--n] & 0xC0) == 0x80); + --nr; + } + if (n == 0) + break; + memmove(data, buf, n); + data += n; + *data = 0; + m += nr; + } } -void -windormant(Window *w) -{ - if(w->addr != nil){ - fsclose(w->addr); - w->addr = nil; - } - if(w->body != nil){ - fsclose(w->body); - w->body = nil; - } - if(w->data != nil){ - fsclose(w->data); - w->data = nil; - } +void windormant(Window* w) { + if (w->addr != nil) { + fsclose(w->addr); + w->addr = nil; + } + if (w->body != nil) { + fsclose(w->body); + w->body = nil; + } + if (w->data != nil) { + fsclose(w->data); + w->data = nil; + } } - -int -windel(Window *w, int sure) -{ - if(sure) - fswrite(w->ctl, "delete\n", 7); - else if(fswrite(w->ctl, "del\n", 4) != 4) - return 0; - /* event proc will die due to read error from event file */ - windormant(w); - fsclose(w->ctl); - w->ctl = nil; - return 1; +int windel(Window* w, int sure) { + if (sure) + fswrite(w->ctl, "delete\n", 7); + else if (fswrite(w->ctl, "del\n", 4) != 4) + return 0; + /* event proc will die due to read error from event file */ + windormant(w); + fsclose(w->ctl); + w->ctl = nil; + return 1; } -void -winclean(Window *w) -{ - ctlprint(w->ctl, "clean\n"); -} +void winclean(Window* w) { ctlprint(w->ctl, "clean\n"); } -int -winsetaddr(Window *w, char *addr, int errok) -{ - if(w->addr == nil) - w->addr = winopenfile(w, "addr"); - if(fswrite(w->addr, addr, strlen(addr)) < 0){ - if(!errok) - error("error writing addr(%s): %r", addr); - return 0; - } - return 1; +int winsetaddr(Window* w, char* addr, int errok) { + if (w->addr == nil) + w->addr = winopenfile(w, "addr"); + if (fswrite(w->addr, addr, strlen(addr)) < 0) { + if (!errok) + error("error writing addr(%s): %r", addr); + return 0; + } + return 1; } -int -winselect(Window *w, char *addr, int errok) -{ - if(winsetaddr(w, addr, errok)){ - ctlprint(w->ctl, "dot=addr\n"); - return 1; - } - return 0; +int winselect(Window* w, char* addr, int errok) { + if (winsetaddr(w, addr, errok)) { + ctlprint(w->ctl, "dot=addr\n"); + return 1; + } + return 0; } -char* -winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */ +char* winreadbody( + Window* w, + int* np) /* can't use readfile because acme doesn't report the length */ { - char *s; - int m, na, n; + char* s; + int m, na, n; - if(w->body != nil) - winclosebody(w); - winopenbody(w, OREAD); - s = nil; - na = 0; - n = 0; - for(;;){ - if(na < n+512){ - na += 1024; - s = realloc(s, na+1); - } - m = fsread(w->body, s+n, na-n); - if(m <= 0) - break; - n += m; - } - s[n] = 0; - winclosebody(w); - *np = n; - return s; + if (w->body != nil) + winclosebody(w); + winopenbody(w, OREAD); + s = nil; + na = 0; + n = 0; + for (;;) { + if (na < n + 512) { + na += 1024; + s = realloc(s, na + 1); + } + m = fsread(w->body, s + n, na - n); + if (m <= 0) + break; + n += m; + } + s[n] = 0; + winclosebody(w); + *np = n; + return s; } -char* -winselection(Window *w) -{ - int m, n; - char *buf; - char tmp[256]; - CFid* fid; +char* winselection(Window* w) { + int m, n; + char* buf; + char tmp[256]; + CFid* fid; - fid = winopenfile1(w, "rdsel", OREAD); - if(fid == nil) - error("can't open rdsel: %r"); - n = 0; - buf = nil; - for(;;){ - m = fsread(fid, tmp, sizeof tmp); - if(m <= 0) - break; - buf = erealloc(buf, n+m+1); - memmove(buf+n, tmp, m); - n += m; - buf[n] = '\0'; - } - fsclose(fid); - return buf; + fid = winopenfile1(w, "rdsel", OREAD); + if (fid == nil) + error("can't open rdsel: %r"); + n = 0; + buf = nil; + for (;;) { + m = fsread(fid, tmp, sizeof tmp); + if (m <= 0) + break; + buf = erealloc(buf, n + m + 1); + memmove(buf + n, tmp, m); + n += m; + buf[n] = '\0'; + } + fsclose(fid); + return buf; }
M regx.cregx.c

@@ -12,49 +12,47 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -Rangeset sel; -Rune *lastregexp; +Rangeset sel; +Rune* lastregexp; /* * Machine Information */ typedef struct Inst Inst; -struct Inst -{ - uint type; /* < OPERATOR ==> literal, otherwise action */ - union { - int sid; - int subid; - int class; - Inst *other; - Inst *right; - } u; - union{ - Inst *left; - Inst *next; - } u1; +struct Inst { + uint type; /* < OPERATOR ==> literal, otherwise action */ + union { + int sid; + int subid; + int class; + Inst* other; + Inst* right; + } u; + union { + Inst* left; + Inst* next; + } u1; }; -#define NPROG 1024 -Inst program[NPROG]; -Inst *progp; -Inst *startinst; /* First inst. of program; might not be program[0] */ -Inst *bstartinst; /* same for backwards machine */ -Channel *rechan; /* chan(Inst*) */ +#define NPROG 1024 +Inst program[NPROG]; +Inst* progp; +Inst* startinst; /* First inst. of program; might not be program[0] */ +Inst* bstartinst; /* same for backwards machine */ +Channel* rechan; /* chan(Inst*) */ typedef struct Ilist Ilist; -struct Ilist -{ - Inst *inst; /* Instruction of the thread */ - Rangeset se; - uint startp; /* first char of match */ +struct Ilist { + Inst* inst; /* Instruction of the thread */ + Rangeset se; + uint startp; /* first char of match */ }; -#define NLIST 127 +#define NLIST 127 -Ilist *tl, *nl; /* This list, next list */ -Ilist list[2][NLIST+1]; /* +1 for trailing null */ -static Rangeset sempty; +Ilist *tl, *nl; /* This list, next list */ +Ilist list[2][NLIST + 1]; /* +1 for trailing null */ +static Rangeset sempty; /* * Actions and Tokens

@@ -62,465 +60,427 @@ *

* 0x10000xx are operators, value == precedence * 0x20000xx are tokens, i.e. operands for operators */ -#define OPERATOR 0x1000000 /* Bit set in all operators */ -#define START (OPERATOR+0) /* Start, used for marker on stack */ -#define RBRA (OPERATOR+1) /* Right bracket, ) */ -#define LBRA (OPERATOR+2) /* Left bracket, ( */ -#define OR (OPERATOR+3) /* Alternation, | */ -#define CAT (OPERATOR+4) /* Concatentation, implicit operator */ -#define STAR (OPERATOR+5) /* Closure, * */ -#define PLUS (OPERATOR+6) /* a+ == aa* */ -#define QUEST (OPERATOR+7) /* a? == a|nothing, i.e. 0 or 1 a's */ -#define ANY 0x2000000 /* Any character but newline, . */ -#define NOP (ANY+1) /* No operation, internal use only */ -#define BOL (ANY+2) /* Beginning of line, ^ */ -#define EOL (ANY+3) /* End of line, $ */ -#define CCLASS (ANY+4) /* Character class, [] */ -#define NCCLASS (ANY+5) /* Negated character class, [^] */ -#define END (ANY+0x77) /* Terminate: match found */ +#define OPERATOR 0x1000000 /* Bit set in all operators */ +#define START (OPERATOR + 0) /* Start, used for marker on stack */ +#define RBRA (OPERATOR + 1) /* Right bracket, ) */ +#define LBRA (OPERATOR + 2) /* Left bracket, ( */ +#define OR (OPERATOR + 3) /* Alternation, | */ +#define CAT (OPERATOR + 4) /* Concatentation, implicit operator */ +#define STAR (OPERATOR + 5) /* Closure, * */ +#define PLUS (OPERATOR + 6) /* a+ == aa* */ +#define QUEST (OPERATOR + 7) /* a? == a|nothing, i.e. 0 or 1 a's */ +#define ANY 0x2000000 /* Any character but newline, . */ +#define NOP (ANY + 1) /* No operation, internal use only */ +#define BOL (ANY + 2) /* Beginning of line, ^ */ +#define EOL (ANY + 3) /* End of line, $ */ +#define CCLASS (ANY + 4) /* Character class, [] */ +#define NCCLASS (ANY + 5) /* Negated character class, [^] */ +#define END (ANY + 0x77) /* Terminate: match found */ -#define ISATOR OPERATOR -#define ISAND ANY +#define ISATOR OPERATOR +#define ISAND ANY -#define QUOTED 0x4000000 /* Bit set for \-ed lex characters */ +#define QUOTED 0x4000000 /* Bit set for \-ed lex characters */ /* * Parser Information */ typedef struct Node Node; -struct Node -{ - Inst *first; - Inst *last; +struct Node { + Inst* first; + Inst* last; }; -#define NSTACK 20 -Node andstack[NSTACK]; -Node *andp; -int atorstack[NSTACK]; -int *atorp; -int lastwasand; /* Last token was operand */ -int cursubid; -int subidstack[NSTACK]; -int *subidp; -int backwards; -int nbra; -Rune *exprp; /* pointer to next character in source expression */ -#define DCLASS 10 /* allocation increment */ -int nclass; /* number active */ -int Nclass; /* high water mark */ -Rune **class; -int negateclass; +#define NSTACK 20 +Node andstack[NSTACK]; +Node* andp; +int atorstack[NSTACK]; +int* atorp; +int lastwasand; /* Last token was operand */ +int cursubid; +int subidstack[NSTACK]; +int* subidp; +int backwards; +int nbra; +Rune* exprp; /* pointer to next character in source expression */ +#define DCLASS 10 /* allocation increment */ +int nclass; /* number active */ +int Nclass; /* high water mark */ +Rune** class; +int negateclass; -int addinst(Ilist *l, Inst *inst, Rangeset *sep); -void newmatch(Rangeset*); -void bnewmatch(Rangeset*); -void pushand(Inst*, Inst*); -void pushator(int); -Node *popand(int); -int popator(void); -void startlex(Rune*); -int lex(void); -void operator(int); -void operand(int); -void evaluntil(int); -void optimize(Inst*); -void bldcclass(void); +int addinst(Ilist* l, Inst* inst, Rangeset* sep); +void newmatch(Rangeset*); +void bnewmatch(Rangeset*); +void pushand(Inst*, Inst*); +void pushator(int); +Node* popand(int); +int popator(void); +void startlex(Rune*); +int lex(void); +void operator(int); +void operand(int); +void evaluntil(int); +void optimize(Inst*); +void bldcclass(void); -void -rxinit(void) -{ - rechan = chancreate(sizeof(Inst*), 0); - chansetname(rechan, "rechan"); - lastregexp = runemalloc(1); +void rxinit(void) { + rechan = chancreate(sizeof(Inst*), 0); + chansetname(rechan, "rechan"); + lastregexp = runemalloc(1); } -void -regerror(char *e) -{ - lastregexp[0] = 0; - warning(nil, "regexp: %s\n", e); - sendp(rechan, nil); - threadexits(nil); +void regerror(char* e) { + lastregexp[0] = 0; + warning(nil, "regexp: %s\n", e); + sendp(rechan, nil); + threadexits(nil); } -Inst * -newinst(int t) -{ - if(progp >= &program[NPROG]) - regerror("expression too long"); - progp->type = t; - progp->u1.left = nil; - progp->u.right = nil; - return progp++; +Inst* newinst(int t) { + if (progp >= &program[NPROG]) + regerror("expression too long"); + progp->type = t; + progp->u1.left = nil; + progp->u.right = nil; + return progp++; } -void -realcompile(void *arg) -{ - int token; - Rune *s; +void realcompile(void* arg) { + int token; + Rune* s; - threadsetname("regcomp"); - s = arg; - startlex(s); - atorp = atorstack; - andp = andstack; - subidp = subidstack; - cursubid = 0; - lastwasand = FALSE; - /* Start with a low priority operator to prime parser */ - pushator(START-1); - while((token=lex()) != END){ - if((token&ISATOR) == OPERATOR) - operator(token); - else - operand(token); - } - /* Close with a low priority operator */ - evaluntil(START); - /* Force END */ - operand(END); - evaluntil(START); - if(nbra) - regerror("unmatched `('"); - --andp; /* points to first and only operand */ - sendp(rechan, andp->first); - threadexits(nil); + threadsetname("regcomp"); + s = arg; + startlex(s); + atorp = atorstack; + andp = andstack; + subidp = subidstack; + cursubid = 0; + lastwasand = FALSE; + /* Start with a low priority operator to prime parser */ + pushator(START - 1); + while ((token = lex()) != END) { + if ((token & ISATOR) == OPERATOR) + operator(token); + else + operand(token); + } + /* Close with a low priority operator */ + evaluntil(START); + /* Force END */ + operand(END); + evaluntil(START); + if (nbra) + regerror("unmatched `('"); + --andp; /* points to first and only operand */ + sendp(rechan, andp->first); + threadexits(nil); } /* r is null terminated */ -int -rxcompile(Rune *r) -{ - int i, nr; - Inst *oprogp; +int rxcompile(Rune* r) { + int i, nr; + Inst* oprogp; - nr = runestrlen(r)+1; - if(runeeq(lastregexp, runestrlen(lastregexp)+1, r, nr)==TRUE) - return TRUE; - lastregexp[0] = 0; - for(i=0; i<nclass; i++) - free(class[i]); - nclass = 0; - progp = program; - backwards = FALSE; - bstartinst = nil; - threadcreate(realcompile, r, STACK); - startinst = recvp(rechan); - if(startinst == nil) - return FALSE; - optimize(program); - oprogp = progp; - backwards = TRUE; - threadcreate(realcompile, r, STACK); - bstartinst = recvp(rechan); - if(bstartinst == nil) - return FALSE; - optimize(oprogp); - lastregexp = runerealloc(lastregexp, nr); - runemove(lastregexp, r, nr); - return TRUE; + nr = runestrlen(r) + 1; + if (runeeq(lastregexp, runestrlen(lastregexp) + 1, r, nr) == TRUE) + return TRUE; + lastregexp[0] = 0; + for (i = 0; i < nclass; i++) + free(class[i]); + nclass = 0; + progp = program; + backwards = FALSE; + bstartinst = nil; + threadcreate(realcompile, r, STACK); + startinst = recvp(rechan); + if (startinst == nil) + return FALSE; + optimize(program); + oprogp = progp; + backwards = TRUE; + threadcreate(realcompile, r, STACK); + bstartinst = recvp(rechan); + if (bstartinst == nil) + return FALSE; + optimize(oprogp); + lastregexp = runerealloc(lastregexp, nr); + runemove(lastregexp, r, nr); + return TRUE; } -void -operand(int t) -{ - Inst *i; - if(lastwasand) - operator(CAT); /* catenate is implicit */ - i = newinst(t); - if(t == CCLASS){ - if(negateclass) - i->type = NCCLASS; /* UGH */ - i->u.class = nclass-1; /* UGH */ - } - pushand(i, i); - lastwasand = TRUE; +void operand(int t) { + Inst* i; + if (lastwasand) + operator(CAT); /* catenate is implicit */ + i = newinst(t); + if (t == CCLASS) { + if (negateclass) + i->type = NCCLASS; /* UGH */ + i->u.class = nclass - 1; /* UGH */ + } + pushand(i, i); + lastwasand = TRUE; } -void -operator(int t) -{ - if(t==RBRA && --nbra<0) - regerror("unmatched `)'"); - if(t==LBRA){ - cursubid++; /* silently ignored */ - nbra++; - if(lastwasand) - operator(CAT); - }else - evaluntil(t); - if(t!=RBRA) - pushator(t); - lastwasand = FALSE; - if(t==STAR || t==QUEST || t==PLUS || t==RBRA) - lastwasand = TRUE; /* these look like operands */ +void operator(int t) { + if (t == RBRA && --nbra < 0) + regerror("unmatched `)'"); + if (t == LBRA) { + cursubid++; /* silently ignored */ + nbra++; + if (lastwasand) + operator(CAT); + } else + evaluntil(t); + if (t != RBRA) + pushator(t); + lastwasand = FALSE; + if (t == STAR || t == QUEST || t == PLUS || t == RBRA) + lastwasand = TRUE; /* these look like operands */ } -void -pushand(Inst *f, Inst *l) -{ - if(andp >= &andstack[NSTACK]) - error("operand stack overflow"); - andp->first = f; - andp->last = l; - andp++; +void pushand(Inst* f, Inst* l) { + if (andp >= &andstack[NSTACK]) + error("operand stack overflow"); + andp->first = f; + andp->last = l; + andp++; } -void -pushator(int t) -{ - if(atorp >= &atorstack[NSTACK]) - error("operator stack overflow"); - *atorp++=t; - if(cursubid >= NRange) - *subidp++= -1; - else - *subidp++=cursubid; +void pushator(int t) { + if (atorp >= &atorstack[NSTACK]) + error("operator stack overflow"); + *atorp++ = t; + if (cursubid >= NRange) + *subidp++ = -1; + else + *subidp++ = cursubid; } -Node * -popand(int op) -{ - char buf[64]; +Node* popand(int op) { + char buf[64]; - if(andp <= &andstack[0]) - if(op){ - sprint(buf, "missing operand for %c", op); - regerror(buf); - }else - regerror("malformed regexp"); - return --andp; + if (andp <= &andstack[0]) + if (op) { + sprint(buf, "missing operand for %c", op); + regerror(buf); + } else + regerror("malformed regexp"); + return --andp; } -int -popator() -{ - if(atorp <= &atorstack[0]) - error("operator stack underflow"); - --subidp; - return *--atorp; +int popator() { + if (atorp <= &atorstack[0]) + error("operator stack underflow"); + --subidp; + return *--atorp; } -void -evaluntil(int pri) -{ - Node *op1, *op2, *t; - Inst *inst1, *inst2; +void evaluntil(int pri) { + Node *op1, *op2, *t; + Inst *inst1, *inst2; - while(pri==RBRA || atorp[-1]>=pri){ - switch(popator()){ - case LBRA: - op1 = popand('('); - inst2 = newinst(RBRA); - inst2->u.subid = *subidp; - op1->last->u1.next = inst2; - inst1 = newinst(LBRA); - inst1->u.subid = *subidp; - inst1->u1.next = op1->first; - pushand(inst1, inst2); - return; /* must have been RBRA */ - default: - error("unknown regexp operator"); - break; - case OR: - op2 = popand('|'); - op1 = popand('|'); - inst2 = newinst(NOP); - op2->last->u1.next = inst2; - op1->last->u1.next = inst2; - inst1 = newinst(OR); - inst1->u.right = op1->first; - inst1->u1.left = op2->first; - pushand(inst1, inst2); - break; - case CAT: - op2 = popand(0); - op1 = popand(0); - if(backwards && op2->first->type!=END){ - t = op1; - op1 = op2; - op2 = t; - } - op1->last->u1.next = op2->first; - pushand(op1->first, op2->last); - break; - case STAR: - op2 = popand('*'); - inst1 = newinst(OR); - op2->last->u1.next = inst1; - inst1->u.right = op2->first; - pushand(inst1, inst1); - break; - case PLUS: - op2 = popand('+'); - inst1 = newinst(OR); - op2->last->u1.next = inst1; - inst1->u.right = op2->first; - pushand(op2->first, inst1); - break; - case QUEST: - op2 = popand('?'); - inst1 = newinst(OR); - inst2 = newinst(NOP); - inst1->u1.left = inst2; - inst1->u.right = op2->first; - op2->last->u1.next = inst2; - pushand(inst1, inst2); - break; - } - } + while (pri == RBRA || atorp[-1] >= pri) { + switch (popator()) { + case LBRA: + op1 = popand('('); + inst2 = newinst(RBRA); + inst2->u.subid = *subidp; + op1->last->u1.next = inst2; + inst1 = newinst(LBRA); + inst1->u.subid = *subidp; + inst1->u1.next = op1->first; + pushand(inst1, inst2); + return; /* must have been RBRA */ + default: + error("unknown regexp operator"); + break; + case OR: + op2 = popand('|'); + op1 = popand('|'); + inst2 = newinst(NOP); + op2->last->u1.next = inst2; + op1->last->u1.next = inst2; + inst1 = newinst(OR); + inst1->u.right = op1->first; + inst1->u1.left = op2->first; + pushand(inst1, inst2); + break; + case CAT: + op2 = popand(0); + op1 = popand(0); + if (backwards && op2->first->type != END) { + t = op1; + op1 = op2; + op2 = t; + } + op1->last->u1.next = op2->first; + pushand(op1->first, op2->last); + break; + case STAR: + op2 = popand('*'); + inst1 = newinst(OR); + op2->last->u1.next = inst1; + inst1->u.right = op2->first; + pushand(inst1, inst1); + break; + case PLUS: + op2 = popand('+'); + inst1 = newinst(OR); + op2->last->u1.next = inst1; + inst1->u.right = op2->first; + pushand(op2->first, inst1); + break; + case QUEST: + op2 = popand('?'); + inst1 = newinst(OR); + inst2 = newinst(NOP); + inst1->u1.left = inst2; + inst1->u.right = op2->first; + op2->last->u1.next = inst2; + pushand(inst1, inst2); + break; + } + } } +void optimize(Inst* start) { + Inst *inst, *target; -void -optimize(Inst *start) -{ - Inst *inst, *target; - - for(inst=start; inst->type!=END; inst++){ - target = inst->u1.next; - while(target->type == NOP) - target = target->u1.next; - inst->u1.next = target; - } + for (inst = start; inst->type != END; inst++) { + target = inst->u1.next; + while (target->type == NOP) + target = target->u1.next; + inst->u1.next = target; + } } -void -startlex(Rune *s) -{ - exprp = s; - nbra = 0; +void startlex(Rune* s) { + exprp = s; + nbra = 0; } - -int -lex(void){ - int c; +int lex(void) { + int c; - c = *exprp++; - switch(c){ - case '\\': - if(*exprp) - if((c= *exprp++)=='n') - c='\n'; - break; - case 0: - c = END; - --exprp; /* In case we come here again */ - break; - case '*': - c = STAR; - break; - case '?': - c = QUEST; - break; - case '+': - c = PLUS; - break; - case '|': - c = OR; - break; - case '.': - c = ANY; - break; - case '(': - c = LBRA; - break; - case ')': - c = RBRA; - break; - case '^': - c = BOL; - break; - case '$': - c = EOL; - break; - case '[': - c = CCLASS; - bldcclass(); - break; - } - return c; + c = *exprp++; + switch (c) { + case '\\': + if (*exprp) + if ((c = *exprp++) == 'n') + c = '\n'; + break; + case 0: + c = END; + --exprp; /* In case we come here again */ + break; + case '*': + c = STAR; + break; + case '?': + c = QUEST; + break; + case '+': + c = PLUS; + break; + case '|': + c = OR; + break; + case '.': + c = ANY; + break; + case '(': + c = LBRA; + break; + case ')': + c = RBRA; + break; + case '^': + c = BOL; + break; + case '$': + c = EOL; + break; + case '[': + c = CCLASS; + bldcclass(); + break; + } + return c; } -int -nextrec(void) -{ - if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0)) - regerror("malformed `[]'"); - if(exprp[0] == '\\'){ - exprp++; - if(*exprp=='n'){ - exprp++; - return '\n'; - } - return *exprp++|QUOTED; - } - return *exprp++; +int nextrec(void) { + if (exprp[0] == 0 || (exprp[0] == '\\' && exprp[1] == 0)) + regerror("malformed `[]'"); + if (exprp[0] == '\\') { + exprp++; + if (*exprp == 'n') { + exprp++; + return '\n'; + } + return *exprp++ | QUOTED; + } + return *exprp++; } -void -bldcclass(void) -{ - int c1, c2, n, na; - Rune *classp; +void bldcclass(void) { + int c1, c2, n, na; + Rune* classp; - classp = runemalloc(DCLASS); - n = 0; - na = DCLASS; - /* we have already seen the '[' */ - if(*exprp == '^'){ - classp[n++] = '\n'; /* don't match newline in negate case */ - negateclass = TRUE; - exprp++; - }else - negateclass = FALSE; - while((c1 = nextrec()) != ']'){ - if(c1 == '-'){ + classp = runemalloc(DCLASS); + n = 0; + na = DCLASS; + /* we have already seen the '[' */ + if (*exprp == '^') { + classp[n++] = '\n'; /* don't match newline in negate case */ + negateclass = TRUE; + exprp++; + } else + negateclass = FALSE; + while ((c1 = nextrec()) != ']') { + if (c1 == '-') { Error: - free(classp); - regerror("malformed `[]'"); - } - if(n+4 >= na){ /* 3 runes plus NUL */ - na += DCLASS; - classp = runerealloc(classp, na); - } - if(*exprp == '-'){ - exprp++; /* eat '-' */ - if((c2 = nextrec()) == ']') - goto Error; - classp[n+0] = Runemax; - classp[n+1] = c1; - classp[n+2] = c2; - n += 3; - }else - classp[n++] = c1 & ~QUOTED; - } - classp[n] = 0; - if(nclass == Nclass){ - Nclass += DCLASS; - class = realloc(class, Nclass*sizeof(Rune*)); - } - class[nclass++] = classp; + free(classp); + regerror("malformed `[]'"); + } + if (n + 4 >= na) { /* 3 runes plus NUL */ + na += DCLASS; + classp = runerealloc(classp, na); + } + if (*exprp == '-') { + exprp++; /* eat '-' */ + if ((c2 = nextrec()) == ']') + goto Error; + classp[n + 0] = Runemax; + classp[n + 1] = c1; + classp[n + 2] = c2; + n += 3; + } else + classp[n++] = c1 & ~QUOTED; + } + classp[n] = 0; + if (nclass == Nclass) { + Nclass += DCLASS; + class = realloc(class, Nclass * sizeof(Rune*)); + } + class[nclass++] = classp; } -int -classmatch(int classno, int c, int negate) -{ - Rune *p; +int classmatch(int classno, int c, int negate) { + Rune* p; - p = class[classno]; - while(*p){ - if(*p == Runemax){ - if(p[1]<=c && c<=p[2]) - return !negate; - p += 3; - }else if(*p++ == c) - return !negate; - } - return negate; + p = class[classno]; + while (*p) { + if (*p == Runemax) { + if (p[1] <= c && c <= p[2]) + return !negate; + p += 3; + } else if (*p++ == c) + return !negate; + } + return negate; } /*

@@ -528,313 +488,304 @@ * Note optimization in addinst:

* *l must be pending when addinst called; if *l has been looked * at already, the optimization is a bug. */ -int -addinst(Ilist *l, Inst *inst, Rangeset *sep) -{ - Ilist *p; +int addinst(Ilist* l, Inst* inst, Rangeset* sep) { + Ilist* p; - for(p = l; p->inst; p++){ - if(p->inst==inst){ - if((sep)->r[0].q0 < p->se.r[0].q0) - p->se= *sep; /* this would be bug */ - return 0; /* It's already there */ - } - } - p->inst = inst; - p->se= *sep; - (p+1)->inst = nil; - return 1; + for (p = l; p->inst; p++) { + if (p->inst == inst) { + if ((sep)->r[0].q0 < p->se.r[0].q0) + p->se = *sep; /* this would be bug */ + return 0; /* It's already there */ + } + } + p->inst = inst; + p->se = *sep; + (p + 1)->inst = nil; + return 1; } -int -rxnull(void) -{ - return startinst==nil || bstartinst==nil; -} +int rxnull(void) { return startinst == nil || bstartinst == nil; } /* either t!=nil or r!=nil, and we match the string in the appropriate place */ -int -rxexecute(Text *t, Rune *r, uint startp, uint eof, Rangeset *rp) -{ - int flag; - Inst *inst; - Ilist *tlp; - uint p; - int nnl, ntl; - int nc, c; - int wrapped; - int startchar; +int rxexecute(Text* t, Rune* r, uint startp, uint eof, Rangeset* rp) { + int flag; + Inst* inst; + Ilist* tlp; + uint p; + int nnl, ntl; + int nc, c; + int wrapped; + int startchar; - flag = 0; - p = startp; - startchar = 0; - wrapped = 0; - nnl = 0; - if(startinst->type<OPERATOR) - startchar = startinst->type; - list[0][0].inst = list[1][0].inst = nil; - sel.r[0].q0 = -1; - if(t != nil) - nc = t->file->b.nc; - else - nc = runestrlen(r); - /* Execute machine once for each character */ - for(;;p++){ - doloop: - if(p>=eof || p>=nc){ - switch(wrapped++){ - case 0: /* let loop run one more click */ - case 2: - break; - case 1: /* expired; wrap to beginning */ - if(sel.r[0].q0>=0 || eof!=Infinity) - goto Return; - list[0][0].inst = list[1][0].inst = nil; - p = 0; - goto doloop; - default: - goto Return; - } - c = 0; - }else{ - if(((wrapped && p>=startp) || sel.r[0].q0>0) && nnl==0) - break; - if(t != nil) - c = textreadc(t, p); - else - c = r[p]; - } - /* fast check for first char */ - if(startchar && nnl==0 && c!=startchar) - continue; - tl = list[flag]; - nl = list[flag^=1]; - nl->inst = nil; - ntl = nnl; - nnl = 0; - if(sel.r[0].q0<0 && (!wrapped || p<startp || startp==eof)){ - /* Add first instruction to this list */ - sempty.r[0].q0 = p; - if(addinst(tl, startinst, &sempty)) - if(++ntl >= NLIST){ - Overflow: - warning(nil, "regexp list overflow\n"); - sel.r[0].q0 = -1; - goto Return; - } - } - /* Execute machine until this list is empty */ - for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */ - Switchstmt: - switch(inst->type){ - default: /* regular character */ - if(inst->type==c){ - Addinst: - if(addinst(nl, inst->u1.next, &tlp->se)) - if(++nnl >= NLIST) - goto Overflow; - } - break; - case LBRA: - if(inst->u.subid>=0) - tlp->se.r[inst->u.subid].q0 = p; - inst = inst->u1.next; - goto Switchstmt; - case RBRA: - if(inst->u.subid>=0) - tlp->se.r[inst->u.subid].q1 = p; - inst = inst->u1.next; - goto Switchstmt; - case ANY: - if(c!='\n') - goto Addinst; - break; - case BOL: - if(p==0 || (t!=nil && textreadc(t, p-1)=='\n') || (r!=nil && r[p-1]=='\n')){ - Step: - inst = inst->u1.next; - goto Switchstmt; - } - break; - case EOL: - if(c == '\n') - goto Step; - break; - case CCLASS: - if(c>=0 && classmatch(inst->u.class, c, 0)) - goto Addinst; - break; - case NCCLASS: - if(c>=0 && classmatch(inst->u.class, c, 1)) - goto Addinst; - break; - case OR: - /* evaluate right choice later */ - if(addinst(tlp, inst->u.right, &tlp->se)) - if(++ntl >= NLIST) - goto Overflow; - /* efficiency: advance and re-evaluate */ - inst = inst->u1.left; - goto Switchstmt; - case END: /* Match! */ - tlp->se.r[0].q1 = p; - newmatch(&tlp->se); - break; - } - } - } - Return: - *rp = sel; - return sel.r[0].q0 >= 0; + flag = 0; + p = startp; + startchar = 0; + wrapped = 0; + nnl = 0; + if (startinst->type < OPERATOR) + startchar = startinst->type; + list[0][0].inst = list[1][0].inst = nil; + sel.r[0].q0 = -1; + if (t != nil) + nc = t->file->b.nc; + else + nc = runestrlen(r); + /* Execute machine once for each character */ + for (;; p++) { + doloop: + if (p >= eof || p >= nc) { + switch (wrapped++) { + case 0: /* let loop run one more click */ + case 2: + break; + case 1: /* expired; wrap to beginning */ + if (sel.r[0].q0 >= 0 || eof != Infinity) + goto Return; + list[0][0].inst = list[1][0].inst = nil; + p = 0; + goto doloop; + default: + goto Return; + } + c = 0; + } else { + if (((wrapped && p >= startp) || sel.r[0].q0 > 0) && nnl == 0) + break; + if (t != nil) + c = textreadc(t, p); + else + c = r[p]; + } + /* fast check for first char */ + if (startchar && nnl == 0 && c != startchar) + continue; + tl = list[flag]; + nl = list[flag ^= 1]; + nl->inst = nil; + ntl = nnl; + nnl = 0; + if (sel.r[0].q0 < 0 && (!wrapped || p < startp || startp == eof)) { + /* Add first instruction to this list */ + sempty.r[0].q0 = p; + if (addinst(tl, startinst, &sempty)) + if (++ntl >= NLIST) { + Overflow: + warning(nil, "regexp list overflow\n"); + sel.r[0].q0 = -1; + goto Return; + } + } + /* Execute machine until this list is empty */ + for (tlp = tl; inst = tlp->inst; tlp++) { /* assignment = */ + Switchstmt: + switch (inst->type) { + default: /* regular character */ + if (inst->type == c) { + Addinst: + if (addinst(nl, inst->u1.next, &tlp->se)) + if (++nnl >= NLIST) + goto Overflow; + } + break; + case LBRA: + if (inst->u.subid >= 0) + tlp->se.r[inst->u.subid].q0 = p; + inst = inst->u1.next; + goto Switchstmt; + case RBRA: + if (inst->u.subid >= 0) + tlp->se.r[inst->u.subid].q1 = p; + inst = inst->u1.next; + goto Switchstmt; + case ANY: + if (c != '\n') + goto Addinst; + break; + case BOL: + if ( + p == 0 || (t != nil && textreadc(t, p - 1) == '\n') || + (r != nil && r[p - 1] == '\n')) { + Step: + inst = inst->u1.next; + goto Switchstmt; + } + break; + case EOL: + if (c == '\n') + goto Step; + break; + case CCLASS: + if (c >= 0 && classmatch(inst->u.class, c, 0)) + goto Addinst; + break; + case NCCLASS: + if (c >= 0 && classmatch(inst->u.class, c, 1)) + goto Addinst; + break; + case OR: + /* evaluate right choice later */ + if (addinst(tlp, inst->u.right, &tlp->se)) + if (++ntl >= NLIST) + goto Overflow; + /* efficiency: advance and re-evaluate */ + inst = inst->u1.left; + goto Switchstmt; + case END: /* Match! */ + tlp->se.r[0].q1 = p; + newmatch(&tlp->se); + break; + } + } + } +Return: + *rp = sel; + return sel.r[0].q0 >= 0; } -void -newmatch(Rangeset *sp) -{ - if(sel.r[0].q0<0 || sp->r[0].q0<sel.r[0].q0 || - (sp->r[0].q0==sel.r[0].q0 && sp->r[0].q1>sel.r[0].q1)) - sel = *sp; +void newmatch(Rangeset* sp) { + if ( + sel.r[0].q0 < 0 || sp->r[0].q0 < sel.r[0].q0 || + (sp->r[0].q0 == sel.r[0].q0 && sp->r[0].q1 > sel.r[0].q1)) + sel = *sp; } -int -rxbexecute(Text *t, uint startp, Rangeset *rp) -{ - int flag; - Inst *inst; - Ilist *tlp; - int p; - int nnl, ntl; - int c; - int wrapped; - int startchar; +int rxbexecute(Text* t, uint startp, Rangeset* rp) { + int flag; + Inst* inst; + Ilist* tlp; + int p; + int nnl, ntl; + int c; + int wrapped; + int startchar; - flag = 0; - nnl = 0; - wrapped = 0; - p = startp; - startchar = 0; - if(bstartinst->type<OPERATOR) - startchar = bstartinst->type; - list[0][0].inst = list[1][0].inst = nil; - sel.r[0].q0= -1; - /* Execute machine once for each character, including terminal NUL */ - for(;;--p){ - doloop: - if(p <= 0){ - switch(wrapped++){ - case 0: /* let loop run one more click */ - case 2: - break; - case 1: /* expired; wrap to end */ - if(sel.r[0].q0>=0) - goto Return; - list[0][0].inst = list[1][0].inst = nil; - p = t->file->b.nc; - goto doloop; - case 3: - default: - goto Return; - } - c = 0; - }else{ - if(((wrapped && p<=startp) || sel.r[0].q0>0) && nnl==0) - break; - c = textreadc(t, p-1); - } - /* fast check for first char */ - if(startchar && nnl==0 && c!=startchar) - continue; - tl = list[flag]; - nl = list[flag^=1]; - nl->inst = nil; - ntl = nnl; - nnl = 0; - if(sel.r[0].q0<0 && (!wrapped || p>startp)){ - /* Add first instruction to this list */ - /* the minus is so the optimizations in addinst work */ - sempty.r[0].q0 = -p; - if(addinst(tl, bstartinst, &sempty)) - if(++ntl >= NLIST){ - Overflow: - warning(nil, "regexp list overflow\n"); - sel.r[0].q0 = -1; - goto Return; - } - } - /* Execute machine until this list is empty */ - for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */ - Switchstmt: - switch(inst->type){ - default: /* regular character */ - if(inst->type == c){ - Addinst: - if(addinst(nl, inst->u1.next, &tlp->se)) - if(++nnl >= NLIST) - goto Overflow; - } - break; - case LBRA: - if(inst->u.subid>=0) - tlp->se.r[inst->u.subid].q0 = p; - inst = inst->u1.next; - goto Switchstmt; - case RBRA: - if(inst->u.subid >= 0) - tlp->se.r[inst->u.subid].q1 = p; - inst = inst->u1.next; - goto Switchstmt; - case ANY: - if(c != '\n') - goto Addinst; - break; - case BOL: - if(c=='\n' || p==0){ - Step: - inst = inst->u1.next; - goto Switchstmt; - } - break; - case EOL: - if(p<t->file->b.nc && textreadc(t, p)=='\n') - goto Step; - break; - case CCLASS: - if(c>0 && classmatch(inst->u.class, c, 0)) - goto Addinst; - break; - case NCCLASS: - if(c>0 && classmatch(inst->u.class, c, 1)) - goto Addinst; - break; - case OR: - /* evaluate right choice later */ - if(addinst(tl, inst->u.right, &tlp->se)) - if(++ntl >= NLIST) - goto Overflow; - /* efficiency: advance and re-evaluate */ - inst = inst->u1.left; - goto Switchstmt; - case END: /* Match! */ - tlp->se.r[0].q0 = -tlp->se.r[0].q0; /* minus sign */ - tlp->se.r[0].q1 = p; - bnewmatch(&tlp->se); - break; - } - } - } - Return: - *rp = sel; - return sel.r[0].q0 >= 0; + flag = 0; + nnl = 0; + wrapped = 0; + p = startp; + startchar = 0; + if (bstartinst->type < OPERATOR) + startchar = bstartinst->type; + list[0][0].inst = list[1][0].inst = nil; + sel.r[0].q0 = -1; + /* Execute machine once for each character, including terminal NUL */ + for (;; --p) { + doloop: + if (p <= 0) { + switch (wrapped++) { + case 0: /* let loop run one more click */ + case 2: + break; + case 1: /* expired; wrap to end */ + if (sel.r[0].q0 >= 0) + goto Return; + list[0][0].inst = list[1][0].inst = nil; + p = t->file->b.nc; + goto doloop; + case 3: + default: + goto Return; + } + c = 0; + } else { + if (((wrapped && p <= startp) || sel.r[0].q0 > 0) && nnl == 0) + break; + c = textreadc(t, p - 1); + } + /* fast check for first char */ + if (startchar && nnl == 0 && c != startchar) + continue; + tl = list[flag]; + nl = list[flag ^= 1]; + nl->inst = nil; + ntl = nnl; + nnl = 0; + if (sel.r[0].q0 < 0 && (!wrapped || p > startp)) { + /* Add first instruction to this list */ + /* the minus is so the optimizations in addinst work */ + sempty.r[0].q0 = -p; + if (addinst(tl, bstartinst, &sempty)) + if (++ntl >= NLIST) { + Overflow: + warning(nil, "regexp list overflow\n"); + sel.r[0].q0 = -1; + goto Return; + } + } + /* Execute machine until this list is empty */ + for (tlp = tl; inst = tlp->inst; tlp++) { /* assignment = */ + Switchstmt: + switch (inst->type) { + default: /* regular character */ + if (inst->type == c) { + Addinst: + if (addinst(nl, inst->u1.next, &tlp->se)) + if (++nnl >= NLIST) + goto Overflow; + } + break; + case LBRA: + if (inst->u.subid >= 0) + tlp->se.r[inst->u.subid].q0 = p; + inst = inst->u1.next; + goto Switchstmt; + case RBRA: + if (inst->u.subid >= 0) + tlp->se.r[inst->u.subid].q1 = p; + inst = inst->u1.next; + goto Switchstmt; + case ANY: + if (c != '\n') + goto Addinst; + break; + case BOL: + if (c == '\n' || p == 0) { + Step: + inst = inst->u1.next; + goto Switchstmt; + } + break; + case EOL: + if (p < t->file->b.nc && textreadc(t, p) == '\n') + goto Step; + break; + case CCLASS: + if (c > 0 && classmatch(inst->u.class, c, 0)) + goto Addinst; + break; + case NCCLASS: + if (c > 0 && classmatch(inst->u.class, c, 1)) + goto Addinst; + break; + case OR: + /* evaluate right choice later */ + if (addinst(tl, inst->u.right, &tlp->se)) + if (++ntl >= NLIST) + goto Overflow; + /* efficiency: advance and re-evaluate */ + inst = inst->u1.left; + goto Switchstmt; + case END: /* Match! */ + tlp->se.r[0].q0 = -tlp->se.r[0].q0; /* minus sign */ + tlp->se.r[0].q1 = p; + bnewmatch(&tlp->se); + break; + } + } + } +Return: + *rp = sel; + return sel.r[0].q0 >= 0; } -void -bnewmatch(Rangeset *sp) -{ - int i; +void bnewmatch(Rangeset* sp) { + int i; - if(sel.r[0].q0<0 || sp->r[0].q0>sel.r[0].q1 || (sp->r[0].q0==sel.r[0].q1 && sp->r[0].q1<sel.r[0].q0)) - for(i = 0; i<NRange; i++){ /* note the reversal; q0<=q1 */ - sel.r[i].q0 = sp->r[i].q1; - sel.r[i].q1 = sp->r[i].q0; - } + if ( + sel.r[0].q0 < 0 || sp->r[0].q0 > sel.r[0].q1 || + (sp->r[0].q0 == sel.r[0].q1 && sp->r[0].q1 < sel.r[0].q0)) + for (i = 0; i < NRange; i++) { /* note the reversal; q0<=q1 */ + sel.r[i].q0 = sp->r[i].q1; + sel.r[i].q1 = sp->r[i].q0; + } }
M rows.crows.c

@@ -13,797 +13,851 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -static Rune Lcolhdr[] = { - 'N', 'e', 'w', 'c', 'o', 'l', ' ', - 'K', 'i', 'l', 'l', ' ', - 'P', 'u', 't', 'a', 'l', 'l', ' ', - 'D', 'u', 'm', 'p', ' ', - 'E', 'x', 'i', 't', ' ', - 0 -}; +static Rune Lcolhdr[] = {'N', 'e', 'w', 'c', 'o', 'l', ' ', 'K', 'i', 'l', + 'l', ' ', 'P', 'u', 't', 'a', 'l', 'l', ' ', 'D', + 'u', 'm', 'p', ' ', 'E', 'x', 'i', 't', ' ', 0}; -void -rowinit(Row *row, Rectangle r) -{ - Rectangle r1; - Text *t; +void rowinit(Row* row, Rectangle r) { + Rectangle r1; + Text* t; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - row->r = r; - row->col = nil; - row->ncol = 0; - r1 = r; - r1.max.y = r1.min.y + font->height; - t = &row->tag; - textinit(t, fileaddtext(nil, t), r1, rfget(FALSE, FALSE, FALSE, nil), tagcols); - t->what = Rowtag; - t->row = row; - t->w = nil; - t->col = nil; - 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, Lcolhdr, 29, TRUE); - textsetselect(t, t->file->b.nc, t->file->b.nc); + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + row->r = r; + row->col = nil; + row->ncol = 0; + r1 = r; + r1.max.y = r1.min.y + font->height; + t = &row->tag; + textinit( + t, + fileaddtext(nil, t), + r1, + rfget(FALSE, FALSE, FALSE, nil), + tagcols); + t->what = Rowtag; + t->row = row; + t->w = nil; + t->col = nil; + 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, Lcolhdr, 29, TRUE); + textsetselect(t, t->file->b.nc, t->file->b.nc); } -Column* -rowadd(Row *row, Column *c, int x) -{ - Rectangle r, r1; - Column *d; - int i; +Column* rowadd(Row* row, Column* c, int x) { + Rectangle r, r1; + Column* d; + int i; - d = nil; - r = row->r; - r.min.y = row->tag.fr.r.max.y+Border; - if(x<r.min.x && row->ncol>0){ /*steal 40% of last column by default */ - d = row->col[row->ncol-1]; - x = d->r.min.x + 3*Dx(d->r)/5; - } - /* look for column we'll land on */ - for(i=0; i<row->ncol; i++){ - d = row->col[i]; - if(x < d->r.max.x) - break; - } - if(row->ncol > 0){ - if(i < row->ncol) - i++; /* new column will go after d */ - r = d->r; - if(Dx(r) < 100) - return nil; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r1 = r; - r1.max.x = min(x-Border, r.max.x-50); - if(Dx(r1) < 50) - r1.max.x = r1.min.x+50; - colresize(d, r1); - r1.min.x = r1.max.x; - r1.max.x = r1.min.x+Border; - draw(screen, r1, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r.min.x = r1.max.x; - } - if(c == nil){ - c = emalloc(sizeof(Column)); - colinit(c, r); - incref(&reffont.ref); - }else - colresize(c, r); - c->row = row; - c->tag.row = row; - row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*)); - memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*)); - row->col[i] = c; - row->ncol++; - clearmouse(); - return c; + d = nil; + r = row->r; + r.min.y = row->tag.fr.r.max.y + Border; + if (x < r.min.x && row->ncol > 0) { /*steal 40% of last column by default */ + d = row->col[row->ncol - 1]; + x = d->r.min.x + 3 * Dx(d->r) / 5; + } + /* look for column we'll land on */ + for (i = 0; i < row->ncol; i++) { + d = row->col[i]; + if (x < d->r.max.x) + break; + } + if (row->ncol > 0) { + if (i < row->ncol) + i++; /* new column will go after d */ + r = d->r; + if (Dx(r) < 100) + return nil; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r1 = r; + r1.max.x = min(x - Border, r.max.x - 50); + if (Dx(r1) < 50) + r1.max.x = r1.min.x + 50; + colresize(d, r1); + r1.min.x = r1.max.x; + r1.max.x = r1.min.x + Border; + draw( + screen, + r1, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r.min.x = r1.max.x; + } + if (c == nil) { + c = emalloc(sizeof(Column)); + colinit(c, r); + incref(&reffont.ref); + } else + colresize(c, r); + c->row = row; + c->tag.row = row; + row->col = realloc(row->col, (row->ncol + 1) * sizeof(Column*)); + memmove(row->col + i + 1, row->col + i, (row->ncol - i) * sizeof(Column*)); + row->col[i] = c; + row->ncol++; + clearmouse(); + return c; } -void -rowresize(Row *row, Rectangle r) -{ - int i, deltax; - Rectangle or, r1, r2; - Column *c; +void rowresize(Row* row, Rectangle r) { + int i, deltax; + Rectangle or, r1, r2; + Column* c; - or = row->r; - deltax = r.min.x - or.min.x; - row->r = r; - r1 = r; - r1.max.y = r1.min.y + font->height; - textresize(&row->tag, r1, TRUE); - 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); - r.min.y = r1.max.y; - r1 = r; - r1.max.x = r1.min.x; - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - r1.min.x = r1.max.x; - /* the test should not be necessary, but guarantee we don't lose a pixel */ - if(i == row->ncol-1) - r1.max.x = r.max.x; - else - r1.max.x = (c->r.max.x-or.min.x)*Dx(r)/Dx(or) + deltax; - if(i > 0){ - r2 = r1; - r2.max.x = r2.min.x+Border; - draw(screen, r2, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r1.min.x = r2.max.x; - } - colresize(c, r1); - } + or = row->r; + deltax = r.min.x - or.min.x; + row->r = r; + r1 = r; + r1.max.y = r1.min.y + font->height; + textresize(&row->tag, r1, TRUE); + 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); + r.min.y = r1.max.y; + r1 = r; + r1.max.x = r1.min.x; + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + r1.min.x = r1.max.x; + /* the test should not be necessary, but guarantee we don't lose a pixel */ + if (i == row->ncol - 1) + r1.max.x = r.max.x; + else + r1.max.x = (c->r.max.x - or.min.x) * Dx(r) / Dx(or) + deltax; + if (i > 0) { + r2 = r1; + r2.max.x = r2.min.x + Border; + draw( + screen, + r2, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r1.min.x = r2.max.x; + } + colresize(c, r1); + } } -void -rowdragcol(Row *row, Column *c, int _0) -{ - Rectangle r; - int i, b, x; - Point p, op; - Column *d; +void rowdragcol(Row* row, Column* c, int _0) { + Rectangle r; + int i, b, x; + Point p, op; + Column* d; - USED(_0); + USED(_0); - 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; i<row->ncol; i++) - if(row->col[i] == c) - goto Found; - error("can't find column"); + for (i = 0; i < row->ncol; i++) + if (row->col[i] == c) + goto Found; + error("can't find column"); - Found: - p = mouse->xy; - if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5)) - return; - if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){ - /* shuffle */ - x = c->r.min.x; - rowclose(row, c, FALSE); - if(rowadd(row, c, p.x) == nil) /* whoops! */ - if(rowadd(row, c, x) == nil) /* WHOOPS! */ - if(rowadd(row, c, -1)==nil){ /* shit! */ - rowclose(row, c, TRUE); - return; - } - colmousebut(c); - return; - } - if(i == 0) - return; - d = row->col[i-1]; - if(p.x < d->r.min.x+80+Scrollwid) - p.x = d->r.min.x+80+Scrollwid; - if(p.x > c->r.max.x-80-Scrollwid) - p.x = c->r.max.x-80-Scrollwid; - r = d->r; - r.max.x = c->r.max.x; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r.max.x = p.x; - colresize(d, r); - r = c->r; - r.min.x = p.x; - r.max.x = r.min.x; - r.max.x += Border; - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - r.min.x = r.max.x; - r.max.x = c->r.max.x; - colresize(c, r); - colmousebut(c); +Found: + p = mouse->xy; + if ((abs(p.x - op.x) < 5 && abs(p.y - op.y) < 5)) + return; + if ( + (i > 0 && p.x < row->col[i - 1]->r.min.x) || + (i < row->ncol - 1 && p.x > c->r.max.x)) { + /* shuffle */ + x = c->r.min.x; + rowclose(row, c, FALSE); + if (rowadd(row, c, p.x) == nil) /* whoops! */ + if (rowadd(row, c, x) == nil) /* WHOOPS! */ + if (rowadd(row, c, -1) == nil) { /* shit! */ + rowclose(row, c, TRUE); + return; + } + colmousebut(c); + return; + } + if (i == 0) + return; + d = row->col[i - 1]; + if (p.x < d->r.min.x + 80 + Scrollwid) + p.x = d->r.min.x + 80 + Scrollwid; + if (p.x > c->r.max.x - 80 - Scrollwid) + p.x = c->r.max.x - 80 - Scrollwid; + r = d->r; + r.max.x = c->r.max.x; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r.max.x = p.x; + colresize(d, r); + r = c->r; + r.min.x = p.x; + r.max.x = r.min.x; + r.max.x += Border; + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + r.min.x = r.max.x; + r.max.x = c->r.max.x; + colresize(c, r); + colmousebut(c); } -void -rowclose(Row *row, Column *c, int dofree) -{ - Rectangle r; - int i; +void rowclose(Row* row, Column* c, int dofree) { + Rectangle r; + int i; - for(i=0; i<row->ncol; i++) - if(row->col[i] == c) - goto Found; - error("can't find column"); - Found: - r = c->r; - if(dofree) - colcloseall(c); - row->ncol--; - memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*)); - row->col = realloc(row->col, row->ncol*sizeof(Column*)); - if(row->ncol == 0){ - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - return; - } - if(i == row->ncol){ /* extend last column right */ - c = row->col[i-1]; - r.min.x = c->r.min.x; - r.max.x = row->r.max.x; - }else{ /* extend next window left */ - c = row->col[i]; - r.max.x = c->r.max.x; - } - draw(screen, r, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - colresize(c, r); + for (i = 0; i < row->ncol; i++) + if (row->col[i] == c) + goto Found; + error("can't find column"); +Found: + r = c->r; + if (dofree) + colcloseall(c); + row->ncol--; + memmove(row->col + i, row->col + i + 1, (row->ncol - i) * sizeof(Column*)); + row->col = realloc(row->col, row->ncol * sizeof(Column*)); + if (row->ncol == 0) { + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + return; + } + if (i == row->ncol) { /* extend last column right */ + c = row->col[i - 1]; + r.min.x = c->r.min.x; + r.max.x = row->r.max.x; + } else { /* extend next window left */ + c = row->col[i]; + r.max.x = c->r.max.x; + } + draw( + screen, + r, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + colresize(c, r); } -Column* -rowwhichcol(Row *row, Point p) -{ - int i; - Column *c; +Column* rowwhichcol(Row* row, Point p) { + int i; + Column* c; - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - if(ptinrect(p, c->r)) - return c; - } - return nil; + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + if (ptinrect(p, c->r)) + return c; + } + return nil; } -Text* -rowwhich(Row *row, Point p) -{ - Column *c; +Text* rowwhich(Row* row, Point p) { + Column* c; - if(ptinrect(p, row->tag.all)) - return &row->tag; - c = rowwhichcol(row, p); - if(c) - return colwhich(c, p); - return nil; + if (ptinrect(p, row->tag.all)) + return &row->tag; + c = rowwhichcol(row, p); + if (c) + return colwhich(c, p); + return nil; } -Text* -rowtype(Row *row, Rune r, Point p) -{ - Window *w; - Text *t; +Text* rowtype(Row* row, Rune r, Point p) { + Window* w; + Text* t; - if(r == 0) - r = Runeerror; + if (r == 0) + r = Runeerror; - clearmouse(); - qlock(&row->lk); - if(bartflag) - t = barttext; - else - t = rowwhich(row, p); - if(t!=nil && !(t->what==Tag && ptinrect(p, t->scrollr))){ - w = t->w; - if(w == nil) - texttype(t, r); - else{ - winlock(w, 'K'); - wintype(w, t, r); - /* Expand tag if necessary */ - if(t->what == Tag){ - t->w->tagsafe = FALSE; - if(r == '\n') - t->w->tagexpand = TRUE; - winresize(w, w->r, TRUE, TRUE); - } - winunlock(w); - } - } - qunlock(&row->lk); - return t; + clearmouse(); + qlock(&row->lk); + if (bartflag) + t = barttext; + else + t = rowwhich(row, p); + if (t != nil && !(t->what == Tag && ptinrect(p, t->scrollr))) { + w = t->w; + if (w == nil) + texttype(t, r); + else { + winlock(w, 'K'); + wintype(w, t, r); + /* Expand tag if necessary */ + if (t->what == Tag) { + t->w->tagsafe = FALSE; + if (r == '\n') + t->w->tagexpand = TRUE; + winresize(w, w->r, TRUE, TRUE); + } + winunlock(w); + } + } + qunlock(&row->lk); + return t; } -int -rowclean(Row *row) -{ - int clean; - int i; +int rowclean(Row* row) { + int clean; + int i; - clean = TRUE; - for(i=0; i<row->ncol; i++) - clean &= colclean(row->col[i]); - return clean; + clean = TRUE; + for (i = 0; i < row->ncol; i++) + clean &= colclean(row->col[i]); + return clean; } -void -rowdump(Row *row, char *file) -{ - int i, j, fd, m, n, dumped; - uint q0, q1; - Biobuf *b; - char *buf, *a, *fontname; - Rune *r; - Column *c; - Window *w, *w1; - Text *t; +void rowdump(Row* row, char* file) { + int i, j, fd, m, n, dumped; + uint q0, q1; + Biobuf* b; + char *buf, *a, *fontname; + Rune* r; + Column* c; + Window *w, *w1; + Text* t; - if(row->ncol == 0) - return; - buf = fbufalloc(); - if(file == nil){ - if(home == nil){ - warning(nil, "can't find file for dump: $home not defined\n"); - goto Rescue; - } - sprint(buf, "%s/acme.dump", home); - file = buf; - } - fd = create(file, OWRITE, 0600); - if(fd < 0){ - warning(nil, "can't open %s: %r\n", file); - goto Rescue; - } - b = emalloc(sizeof(Biobuf)); - Binit(b, fd, OWRITE); - r = fbufalloc(); - Bprint(b, "%s\n", wdir); - Bprint(b, "%s\n", fontnames[0]); - Bprint(b, "%s\n", fontnames[1]); - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - Bprint(b, "%11.7f", 100.0*(c->r.min.x-row->r.min.x)/Dx(row->r)); - if(i == row->ncol-1) - Bputc(b, '\n'); - else - Bputc(b, ' '); - } - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - for(j=0; j<c->nw; j++) - c->w[j]->body.file->dumpid = 0; - } - m = min(RBUFSIZE, row->tag.file->b.nc); - bufread(&row->tag.file->b, 0, r, m); - n = 0; - while(n<m && r[n]!='\n') - n++; - Bprint(b, "w %.*S\n", n, r); - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - m = min(RBUFSIZE, c->tag.file->b.nc); - bufread(&c->tag.file->b, 0, r, m); - n = 0; - while(n<m && r[n]!='\n') - n++; - Bprint(b, "c%11d %.*S\n", i, n, r); - } - for(i=0; i<row->ncol; i++){ - c = row->col[i]; - for(j=0; j<c->nw; j++){ - w = c->w[j]; - wincommit(w, &w->tag); - t = &w->body; - /* windows owned by others get special treatment */ - if(w->nopen[QWevent] > 0) - if(w->dumpstr == nil) - continue; - /* zeroxes of external windows are tossed */ - if(t->file->ntext > 1) - for(n=0; n<t->file->ntext; n++){ - w1 = t->file->text[n]->w; - if(w == w1) - continue; - if(w1->nopen[QWevent]) - goto Continue2; - } - fontname = ""; - if(t->reffont->f != font) - fontname = t->reffont->f->name; - if(t->file->nname) - a = runetobyte(t->file->name, t->file->nname); - else - a = emalloc(1); - if(t->file->dumpid){ - dumped = FALSE; - Bprint(b, "x%11d %11d %11d %11d %11.7f %s\n", i, t->file->dumpid, - w->body.q0, w->body.q1, - 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), - fontname); - }else if(w->dumpstr){ - dumped = FALSE; - Bprint(b, "e%11d %11d %11d %11d %11.7f %s\n", i, t->file->dumpid, - 0, 0, - 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), - fontname); - }else if((w->dirty==FALSE && access(a, 0)==0) || w->isdir){ - dumped = FALSE; - t->file->dumpid = w->id; - Bprint(b, "f%11d %11d %11d %11d %11.7f %s\n", i, w->id, - w->body.q0, w->body.q1, - 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), - fontname); - }else{ - dumped = TRUE; - t->file->dumpid = w->id; - Bprint(b, "F%11d %11d %11d %11d %11.7f %11d %s\n", i, j, - w->body.q0, w->body.q1, - 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), - w->body.file->b.nc, fontname); - } - free(a); - winctlprint(w, buf, 0); - Bwrite(b, buf, strlen(buf)); - m = min(RBUFSIZE, w->tag.file->b.nc); - bufread(&w->tag.file->b, 0, r, m); - n = 0; - while(n<m && r[n]!='\n') - n++; - Bprint(b, "%.*S\n", n, r); - if(dumped){ - q0 = 0; - q1 = t->file->b.nc; - while(q0 < q1){ - n = q1 - q0; - if(n > BUFSIZE/UTFmax) - n = BUFSIZE/UTFmax; - bufread(&t->file->b, q0, r, n); - Bprint(b, "%.*S", n, r); - q0 += n; - } - } - if(w->dumpstr){ - if(w->dumpdir) - Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr); - else - Bprint(b, "\n%s\n", w->dumpstr); - } + if (row->ncol == 0) + return; + buf = fbufalloc(); + if (file == nil) { + if (home == nil) { + warning(nil, "can't find file for dump: $home not defined\n"); + goto Rescue; + } + sprint(buf, "%s/acme.dump", home); + file = buf; + } + fd = create(file, OWRITE, 0600); + if (fd < 0) { + warning(nil, "can't open %s: %r\n", file); + goto Rescue; + } + b = emalloc(sizeof(Biobuf)); + Binit(b, fd, OWRITE); + r = fbufalloc(); + Bprint(b, "%s\n", wdir); + Bprint(b, "%s\n", fontnames[0]); + Bprint(b, "%s\n", fontnames[1]); + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + Bprint(b, "%11.7f", 100.0 * (c->r.min.x - row->r.min.x) / Dx(row->r)); + if (i == row->ncol - 1) + Bputc(b, '\n'); + else + Bputc(b, ' '); + } + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + for (j = 0; j < c->nw; j++) + c->w[j]->body.file->dumpid = 0; + } + m = min(RBUFSIZE, row->tag.file->b.nc); + bufread(&row->tag.file->b, 0, r, m); + n = 0; + while (n < m && r[n] != '\n') + n++; + Bprint(b, "w %.*S\n", n, r); + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + m = min(RBUFSIZE, c->tag.file->b.nc); + bufread(&c->tag.file->b, 0, r, m); + n = 0; + while (n < m && r[n] != '\n') + n++; + Bprint(b, "c%11d %.*S\n", i, n, r); + } + for (i = 0; i < row->ncol; i++) { + c = row->col[i]; + for (j = 0; j < c->nw; j++) { + w = c->w[j]; + wincommit(w, &w->tag); + t = &w->body; + /* windows owned by others get special treatment */ + if (w->nopen[QWevent] > 0) + if (w->dumpstr == nil) + continue; + /* zeroxes of external windows are tossed */ + if (t->file->ntext > 1) + for (n = 0; n < t->file->ntext; n++) { + w1 = t->file->text[n]->w; + if (w == w1) + continue; + if (w1->nopen[QWevent]) + goto Continue2; + } + fontname = ""; + if (t->reffont->f != font) + fontname = t->reffont->f->name; + if (t->file->nname) + a = runetobyte(t->file->name, t->file->nname); + else + a = emalloc(1); + if (t->file->dumpid) { + dumped = FALSE; + Bprint( + b, + "x%11d %11d %11d %11d %11.7f %s\n", + i, + t->file->dumpid, + w->body.q0, + w->body.q1, + 100.0 * (w->r.min.y - c->r.min.y) / Dy(c->r), + fontname); + } else if (w->dumpstr) { + dumped = FALSE; + Bprint( + b, + "e%11d %11d %11d %11d %11.7f %s\n", + i, + t->file->dumpid, + 0, + 0, + 100.0 * (w->r.min.y - c->r.min.y) / Dy(c->r), + fontname); + } else if ((w->dirty == FALSE && access(a, 0) == 0) || w->isdir) { + dumped = FALSE; + t->file->dumpid = w->id; + Bprint( + b, + "f%11d %11d %11d %11d %11.7f %s\n", + i, + w->id, + w->body.q0, + w->body.q1, + 100.0 * (w->r.min.y - c->r.min.y) / Dy(c->r), + fontname); + } else { + dumped = TRUE; + t->file->dumpid = w->id; + Bprint( + b, + "F%11d %11d %11d %11d %11.7f %11d %s\n", + i, + j, + w->body.q0, + w->body.q1, + 100.0 * (w->r.min.y - c->r.min.y) / Dy(c->r), + w->body.file->b.nc, + fontname); + } + free(a); + winctlprint(w, buf, 0); + Bwrite(b, buf, strlen(buf)); + m = min(RBUFSIZE, w->tag.file->b.nc); + bufread(&w->tag.file->b, 0, r, m); + n = 0; + while (n < m && r[n] != '\n') + n++; + Bprint(b, "%.*S\n", n, r); + if (dumped) { + q0 = 0; + q1 = t->file->b.nc; + while (q0 < q1) { + n = q1 - q0; + if (n > BUFSIZE / UTFmax) + n = BUFSIZE / UTFmax; + bufread(&t->file->b, q0, r, n); + Bprint(b, "%.*S", n, r); + q0 += n; + } + } + if (w->dumpstr) { + if (w->dumpdir) + Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr); + else + Bprint(b, "\n%s\n", w->dumpstr); + } Continue2:; - } - } - Bterm(b); - close(fd); - free(b); - fbuffree(r); + } + } + Bterm(b); + close(fd); + free(b); + fbuffree(r); - Rescue: - fbuffree(buf); +Rescue: + fbuffree(buf); } -static -char* -rdline(Biobuf *b, int *linep) -{ - char *l; +static char* rdline(Biobuf* b, int* linep) { + char* l; - l = Brdline(b, '\n'); - if(l) - (*linep)++; - return l; + l = Brdline(b, '\n'); + if (l) + (*linep)++; + return l; } /* * Get font names from load file so we don't load fonts we won't use */ -void -rowloadfonts(char *file) -{ - int i; - Biobuf *b; - char *l; +void rowloadfonts(char* file) { + int i; + Biobuf* b; + char* l; - b = Bopen(file, OREAD); - if(b == nil) - return; - /* current directory */ - l = Brdline(b, '\n'); - if(l == nil) - goto Return; - /* global fonts */ - for(i=0; i<2; i++){ - l = Brdline(b, '\n'); - if(l == nil) - goto Return; - l[Blinelen(b)-1] = 0; - if(*l && strcmp(l, fontnames[i])!=0){ - free(fontnames[i]); - fontnames[i] = estrdup(l); - } - } - Return: - Bterm(b); + b = Bopen(file, OREAD); + if (b == nil) + return; + /* current directory */ + l = Brdline(b, '\n'); + if (l == nil) + goto Return; + /* global fonts */ + for (i = 0; i < 2; i++) { + l = Brdline(b, '\n'); + if (l == nil) + goto Return; + l[Blinelen(b) - 1] = 0; + if (*l && strcmp(l, fontnames[i]) != 0) { + free(fontnames[i]); + fontnames[i] = estrdup(l); + } + } +Return: + Bterm(b); } -int -rowload(Row *row, char *file, int initing) -{ - int i, j, line, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd, done; - double percent; - Biobuf *b, *bout; - char *buf, *l, *t, *fontname; - Rune *r, *fontr; - int rune; - Column *c, *c1, *c2; - uint q0, q1; - Rectangle r1, r2; - Window *w; +int rowload(Row* row, char* file, int initing) { + int i, j, line, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd, done; + double percent; + Biobuf *b, *bout; + char *buf, *l, *t, *fontname; + Rune *r, *fontr; + int rune; + Column *c, *c1, *c2; + uint q0, q1; + Rectangle r1, r2; + Window* w; - buf = fbufalloc(); - if(file == nil){ - if(home == nil){ - warning(nil, "can't find file for load: $home not defined\n"); - goto Rescue1; - } - sprint(buf, "%s/acme.dump", home); - file = buf; - } - b = Bopen(file, OREAD); - if(b == nil){ - warning(nil, "can't open load file %s: %r\n", file); - goto Rescue1; - } - /* current directory */ - line = 0; - l = rdline(b, &line); - if(l == nil) - goto Rescue2; - l[Blinelen(b)-1] = 0; - if(chdir(l) < 0){ - warning(nil, "can't chdir %s\n", l); - goto Rescue2; - } - /* global fonts */ - for(i=0; i<2; i++){ - l = rdline(b, &line); - if(l == nil) - goto Rescue2; - l[Blinelen(b)-1] = 0; - if(*l && strcmp(l, fontnames[i])!=0) - rfget(i, TRUE, i==0 && initing, l); - } - if(initing && row->ncol==0) - rowinit(row, screen->clipr); - l = rdline(b, &line); - if(l == nil) - goto Rescue2; - j = Blinelen(b)/12; - if(j<=0 || j>10) - goto Rescue2; - for(i=0; i<j; i++){ - percent = atof(l+i*12); - if(percent<0 || percent>=100) - goto Rescue2; - x = row->r.min.x+percent*Dx(row->r)/100+0.5; - if(i < row->ncol){ - if(i == 0) - continue; - c1 = row->col[i-1]; - c2 = row->col[i]; - r1 = c1->r; - r2 = c2->r; - if(x<Border) - x = Border; - r1.max.x = x-Border; - r2.min.x = x; - if(Dx(r1) < 50 || Dx(r2) < 50) - continue; - draw(screen, Rpt(r1.min, r2.max), allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - colresize(c1, r1); - colresize(c2, r2); - r2.min.x = x-Border; - r2.max.x = x; - draw(screen, r2, allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x222222FF), nil, ZP); - } - if(i >= row->ncol) - rowadd(row, nil, x); - } - done = 0; - while(!done){ - l = rdline(b, &line); - if(l == nil) - break; - switch(l[0]){ - case 'c': - l[Blinelen(b)-1] = 0; - i = atoi(l+1+0*12); - r = bytetorune(l+1*12, &nr); - ns = -1; - for(n=0; n<nr; n++){ - if(r[n] == '/') - ns = n; - if(r[n] == ' ') - break; - } - textdelete(&row->col[i]->tag, 0, row->col[i]->tag.file->b.nc, TRUE); - textinsert(&row->col[i]->tag, 0, r+n+1, nr-(n+1), TRUE); - free(r); - break; - case 'w': - l[Blinelen(b)-1] = 0; - r = bytetorune(l+2, &nr); - ns = -1; - for(n=0; n<nr; n++){ - if(r[n] == '/') - ns = n; - if(r[n] == ' ') - break; - } - textdelete(&row->tag, 0, row->tag.file->b.nc, TRUE); - textinsert(&row->tag, 0, r, nr, TRUE); - free(r); - break; - default: - done = 1; - break; - } - } - for(;;){ - if(l == nil) - break; - dumpid = 0; - switch(l[0]){ - case 'e': - if(Blinelen(b) < 1+5*12+1) - goto Rescue2; - l = rdline(b, &line); /* ctl line; ignored */ - if(l == nil) - goto Rescue2; - l = rdline(b, &line); /* directory */ - if(l == nil) - goto Rescue2; - l[Blinelen(b)-1] = 0; - if(*l == '\0'){ - if(home == nil) - r = bytetorune("./", &nr); - else{ - t = emalloc(strlen(home)+1+1); - sprint(t, "%s/", home); - r = bytetorune(t, &nr); - free(t); - } - }else - r = bytetorune(l, &nr); - l = rdline(b, &line); /* command */ - if(l == nil) - goto Rescue2; - t = emalloc(Blinelen(b)+1); - memmove(t, l, Blinelen(b)); - run(nil, t, r, nr, TRUE, nil, nil, FALSE); - /* r is freed in run() */ - goto Nextline; - case 'f': - if(Blinelen(b) < 1+5*12+1) - goto Rescue2; - fontname = l+1+5*12; - ndumped = -1; - break; - case 'F': - if(Blinelen(b) < 1+6*12+1) - goto Rescue2; - fontname = l+1+6*12; - ndumped = atoi(l+1+5*12+1); - break; - case 'x': - if(Blinelen(b) < 1+5*12+1) - goto Rescue2; - fontname = l+1+5*12; - ndumped = -1; - dumpid = atoi(l+1+1*12); - break; - default: - goto Rescue2; - } - l[Blinelen(b)-1] = 0; - fontr = nil; - nfontr = 0; - if(*fontname) - fontr = bytetorune(fontname, &nfontr); - i = atoi(l+1+0*12); - j = atoi(l+1+1*12); - q0 = atoi(l+1+2*12); - q1 = atoi(l+1+3*12); - percent = atof(l+1+4*12); - if(i<0 || i>10) - goto Rescue2; - if(i > row->ncol) - i = row->ncol; - c = row->col[i]; - y = c->r.min.y+(percent*Dy(c->r))/100+0.5; - if(y<c->r.min.y || y>=c->r.max.y) - y = -1; - if(dumpid == 0) - w = coladd(c, nil, nil, y); - else - w = coladd(c, nil, lookid(dumpid, TRUE), y); - if(w == nil) - goto Nextline; - w->dumpid = j; - l = rdline(b, &line); - if(l == nil) - goto Rescue2; - l[Blinelen(b)-1] = 0; - r = bytetorune(l+5*12, &nr); - ns = -1; - for(n=0; n<nr; n++){ - if(r[n] == '/') - ns = n; - if(r[n] == ' ') - break; - } - if(dumpid == 0) - winsetname(w, r, n); - for(; n<nr; n++) - if(r[n] == '|') - break; - wincleartag(w); - textinsert(&w->tag, w->tag.file->b.nc, r+n+1, nr-(n+1), TRUE); - if(ndumped >= 0){ - /* simplest thing is to put it in a file and load that */ - sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser()); - fd = create(buf, OWRITE, 0600); - if(fd < 0){ - free(r); - warning(nil, "can't create temp file: %r\n"); - goto Rescue2; - } - bout = emalloc(sizeof(Biobuf)); - Binit(bout, fd, OWRITE); - for(n=0; n<ndumped; n++){ - rune = Bgetrune(b); - if(rune == '\n') - line++; - if(rune == Beof){ - free(r); - Bterm(bout); - free(bout); - close(fd); - remove(buf); - goto Rescue2; - } - Bputrune(bout, rune); - } - Bterm(bout); - free(bout); - textload(&w->body, 0, buf, 1); - remove(buf); - close(fd); - w->body.file->mod = TRUE; - for(n=0; n<w->body.file->ntext; n++) - w->body.file->text[n]->w->dirty = TRUE; - winsettag(w); - }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-') - get(&w->body, nil, nil, FALSE, XXX, nil, 0); - if(fontr){ - fontx(&w->body, nil, nil, 0, 0, fontr, nfontr); - free(fontr); - } - free(r); - if(q0>w->body.file->b.nc || q1>w->body.file->b.nc || q0>q1) - q0 = q1 = 0; - textshow(&w->body, q0, q1, 1); - w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines)); - xfidlog(w, "new"); -Nextline: - l = rdline(b, &line); - } - Bterm(b); - fbuffree(buf); - return TRUE; + buf = fbufalloc(); + if (file == nil) { + if (home == nil) { + warning(nil, "can't find file for load: $home not defined\n"); + goto Rescue1; + } + sprint(buf, "%s/acme.dump", home); + file = buf; + } + b = Bopen(file, OREAD); + if (b == nil) { + warning(nil, "can't open load file %s: %r\n", file); + goto Rescue1; + } + /* current directory */ + line = 0; + l = rdline(b, &line); + if (l == nil) + goto Rescue2; + l[Blinelen(b) - 1] = 0; + if (chdir(l) < 0) { + warning(nil, "can't chdir %s\n", l); + goto Rescue2; + } + /* global fonts */ + for (i = 0; i < 2; i++) { + l = rdline(b, &line); + if (l == nil) + goto Rescue2; + l[Blinelen(b) - 1] = 0; + if (*l && strcmp(l, fontnames[i]) != 0) + rfget(i, TRUE, i == 0 && initing, l); + } + if (initing && row->ncol == 0) + rowinit(row, screen->clipr); + l = rdline(b, &line); + if (l == nil) + goto Rescue2; + j = Blinelen(b) / 12; + if (j <= 0 || j > 10) + goto Rescue2; + for (i = 0; i < j; i++) { + percent = atof(l + i * 12); + if (percent < 0 || percent >= 100) + goto Rescue2; + x = row->r.min.x + percent * Dx(row->r) / 100 + 0.5; + if (i < row->ncol) { + if (i == 0) + continue; + c1 = row->col[i - 1]; + c2 = row->col[i]; + r1 = c1->r; + r2 = c2->r; + if (x < Border) + x = Border; + r1.max.x = x - Border; + r2.min.x = x; + if (Dx(r1) < 50 || Dx(r2) < 50) + continue; + draw( + screen, + Rpt(r1.min, r2.max), + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + colresize(c1, r1); + colresize(c2, r2); + r2.min.x = x - Border; + r2.max.x = x; + draw( + screen, + r2, + allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0x222222FF), + nil, + ZP); + } + if (i >= row->ncol) + rowadd(row, nil, x); + } + done = 0; + while (!done) { + l = rdline(b, &line); + if (l == nil) + break; + switch (l[0]) { + case 'c': + l[Blinelen(b) - 1] = 0; + i = atoi(l + 1 + 0 * 12); + r = bytetorune(l + 1 * 12, &nr); + ns = -1; + for (n = 0; n < nr; n++) { + if (r[n] == '/') + ns = n; + if (r[n] == ' ') + break; + } + textdelete(&row->col[i]->tag, 0, row->col[i]->tag.file->b.nc, TRUE); + textinsert(&row->col[i]->tag, 0, r + n + 1, nr - (n + 1), TRUE); + free(r); + break; + case 'w': + l[Blinelen(b) - 1] = 0; + r = bytetorune(l + 2, &nr); + ns = -1; + for (n = 0; n < nr; n++) { + if (r[n] == '/') + ns = n; + if (r[n] == ' ') + break; + } + textdelete(&row->tag, 0, row->tag.file->b.nc, TRUE); + textinsert(&row->tag, 0, r, nr, TRUE); + free(r); + break; + default: + done = 1; + break; + } + } + for (;;) { + if (l == nil) + break; + dumpid = 0; + switch (l[0]) { + case 'e': + if (Blinelen(b) < 1 + 5 * 12 + 1) + goto Rescue2; + l = rdline(b, &line); /* ctl line; ignored */ + if (l == nil) + goto Rescue2; + l = rdline(b, &line); /* directory */ + if (l == nil) + goto Rescue2; + l[Blinelen(b) - 1] = 0; + if (*l == '\0') { + if (home == nil) + r = bytetorune("./", &nr); + else { + t = emalloc(strlen(home) + 1 + 1); + sprint(t, "%s/", home); + r = bytetorune(t, &nr); + free(t); + } + } else + r = bytetorune(l, &nr); + l = rdline(b, &line); /* command */ + if (l == nil) + goto Rescue2; + t = emalloc(Blinelen(b) + 1); + memmove(t, l, Blinelen(b)); + run(nil, t, r, nr, TRUE, nil, nil, FALSE); + /* r is freed in run() */ + goto Nextline; + case 'f': + if (Blinelen(b) < 1 + 5 * 12 + 1) + goto Rescue2; + fontname = l + 1 + 5 * 12; + ndumped = -1; + break; + case 'F': + if (Blinelen(b) < 1 + 6 * 12 + 1) + goto Rescue2; + fontname = l + 1 + 6 * 12; + ndumped = atoi(l + 1 + 5 * 12 + 1); + break; + case 'x': + if (Blinelen(b) < 1 + 5 * 12 + 1) + goto Rescue2; + fontname = l + 1 + 5 * 12; + ndumped = -1; + dumpid = atoi(l + 1 + 1 * 12); + break; + default: + goto Rescue2; + } + l[Blinelen(b) - 1] = 0; + fontr = nil; + nfontr = 0; + if (*fontname) + fontr = bytetorune(fontname, &nfontr); + i = atoi(l + 1 + 0 * 12); + j = atoi(l + 1 + 1 * 12); + q0 = atoi(l + 1 + 2 * 12); + q1 = atoi(l + 1 + 3 * 12); + percent = atof(l + 1 + 4 * 12); + if (i < 0 || i > 10) + goto Rescue2; + if (i > row->ncol) + i = row->ncol; + c = row->col[i]; + y = c->r.min.y + (percent * Dy(c->r)) / 100 + 0.5; + if (y < c->r.min.y || y >= c->r.max.y) + y = -1; + if (dumpid == 0) + w = coladd(c, nil, nil, y); + else + w = coladd(c, nil, lookid(dumpid, TRUE), y); + if (w == nil) + goto Nextline; + w->dumpid = j; + l = rdline(b, &line); + if (l == nil) + goto Rescue2; + l[Blinelen(b) - 1] = 0; + r = bytetorune(l + 5 * 12, &nr); + ns = -1; + for (n = 0; n < nr; n++) { + if (r[n] == '/') + ns = n; + if (r[n] == ' ') + break; + } + if (dumpid == 0) + winsetname(w, r, n); + for (; n < nr; n++) + if (r[n] == '|') + break; + wincleartag(w); + textinsert(&w->tag, w->tag.file->b.nc, r + n + 1, nr - (n + 1), TRUE); + if (ndumped >= 0) { + /* simplest thing is to put it in a file and load that */ + sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser()); + fd = create(buf, OWRITE, 0600); + if (fd < 0) { + free(r); + warning(nil, "can't create temp file: %r\n"); + goto Rescue2; + } + bout = emalloc(sizeof(Biobuf)); + Binit(bout, fd, OWRITE); + for (n = 0; n < ndumped; n++) { + rune = Bgetrune(b); + if (rune == '\n') + line++; + if (rune == Beof) { + free(r); + Bterm(bout); + free(bout); + close(fd); + remove(buf); + goto Rescue2; + } + Bputrune(bout, rune); + } + Bterm(bout); + free(bout); + textload(&w->body, 0, buf, 1); + remove(buf); + close(fd); + w->body.file->mod = TRUE; + for (n = 0; n < w->body.file->ntext; n++) + w->body.file->text[n]->w->dirty = TRUE; + winsettag(w); + } else if (dumpid == 0 && r[ns + 1] != '+' && r[ns + 1] != '-') + get(&w->body, nil, nil, FALSE, XXX, nil, 0); + if (fontr) { + fontx(&w->body, nil, nil, 0, 0, fontr, nfontr); + free(fontr); + } + free(r); + if (q0 > w->body.file->b.nc || q1 > w->body.file->b.nc || q0 > q1) + q0 = q1 = 0; + textshow(&w->body, q0, q1, 1); + w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines)); + xfidlog(w, "new"); + Nextline: + l = rdline(b, &line); + } + Bterm(b); + fbuffree(buf); + return TRUE; Rescue2: - warning(nil, "bad load file %s:%d\n", file, line); - Bterm(b); + warning(nil, "bad load file %s:%d\n", file, line); + Bterm(b); Rescue1: - fbuffree(buf); - return FALSE; + fbuffree(buf); + return FALSE; } -void -allwindows(void (*f)(Window*, void*), void *arg) -{ - int i, j; - Column *c; +void allwindows(void (*f)(Window*, void*), void* arg) { + int i, j; + Column* c; - for(i=0; i<row.ncol; i++){ - c = row.col[i]; - for(j=0; j<c->nw; j++) - (*f)(c->w[j], arg); - } + for (i = 0; i < row.ncol; i++) { + c = row.col[i]; + for (j = 0; j < c->nw; j++) + (*f)(c->w[j], arg); + } }
M scrl.cscrl.c

@@ -12,148 +12,142 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -static Image *scrtmp; +static Image* scrtmp; -static -Rectangle -scrpos(Rectangle r, uint p0, uint p1, uint tot) -{ - Rectangle q; - int h; +static Rectangle scrpos(Rectangle r, uint p0, uint p1, uint tot) { + Rectangle q; + int h; - q = r; - h = q.max.y-q.min.y; - if(tot == 0) - return q; - if(tot > 1024*1024){ - tot>>=10; - p0>>=10; - p1>>=10; - } - if(p0 > 0) - q.min.y += h*p0/tot; - if(p1 < tot) - q.max.y -= h*(tot-p1)/tot; - if(q.max.y < q.min.y+2){ - if(q.min.y+2 <= r.max.y) - q.max.y = q.min.y+2; - else - q.min.y = q.max.y-2; - } - return q; + q = r; + h = q.max.y - q.min.y; + if (tot == 0) + return q; + if (tot > 1024 * 1024) { + tot >>= 10; + p0 >>= 10; + p1 >>= 10; + } + if (p0 > 0) + q.min.y += h * p0 / tot; + if (p1 < tot) + q.max.y -= h * (tot - p1) / tot; + if (q.max.y < q.min.y + 2) { + if (q.min.y + 2 <= r.max.y) + q.max.y = q.min.y + 2; + else + q.min.y = q.max.y - 2; + } + return q; } -void -scrlresize(void) -{ - freeimage(scrtmp); - scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill); - if(scrtmp == nil) - error("scroll alloc"); +void scrlresize(void) { + freeimage(scrtmp); + scrtmp = allocimage( + display, + Rect(0, 0, 32, screen->r.max.y), + screen->chan, + 0, + DNofill); + if (scrtmp == nil) + error("scroll alloc"); } -void -textscrdraw(Text *t) -{ - Rectangle r, r1, r2; - Image *b; +void textscrdraw(Text* t) { + Rectangle r, r1, r2; + Image* b; - if(t->w==nil || t!=&t->w->body) - return; - if(scrtmp == nil) - scrlresize(); - r = t->scrollr; - b = scrtmp; - r1 = r; - r1.min.x = 0; - r1.max.x = Dx(r); - r2 = scrpos(r1, t->org, t->org+t->fr.nchars, t->file->b.nc); - if(!eqrect(r2, t->lastsr)){ - t->lastsr = r2; - draw(b, r1, t->fr.cols[BORD], nil, ZP); - draw(b, r2, t->fr.cols[BACK], nil, ZP); - r2.min.x = r2.max.x-1; - draw(b, r2, t->fr.cols[BORD], nil, ZP); - draw(t->fr.b, r, b, nil, Pt(0, r1.min.y)); -/*flushimage(display, 1); // BUG? */ - } + if (t->w == nil || t != &t->w->body) + return; + if (scrtmp == nil) + scrlresize(); + r = t->scrollr; + b = scrtmp; + r1 = r; + r1.min.x = 0; + r1.max.x = Dx(r); + r2 = scrpos(r1, t->org, t->org + t->fr.nchars, t->file->b.nc); + if (!eqrect(r2, t->lastsr)) { + t->lastsr = r2; + draw(b, r1, t->fr.cols[BORD], nil, ZP); + draw(b, r2, t->fr.cols[BACK], nil, ZP); + r2.min.x = r2.max.x - 1; + draw(b, r2, t->fr.cols[BORD], nil, ZP); + draw(t->fr.b, r, b, nil, Pt(0, r1.min.y)); + /*flushimage(display, 1); // BUG? */ + } } -void -scrsleep(uint dt) -{ - Timer *timer; - static Alt alts[3]; +void scrsleep(uint dt) { + Timer* timer; + static Alt alts[3]; - timer = timerstart(dt); - alts[0].c = timer->c; - alts[0].v = nil; - alts[0].op = CHANRCV; - alts[1].c = mousectl->c; - alts[1].v = &mousectl->m; - alts[1].op = CHANRCV; - alts[2].op = CHANEND; - for(;;) - switch(alt(alts)){ - case 0: - timerstop(timer); - return; - case 1: - timercancel(timer); - return; - } + timer = timerstart(dt); + alts[0].c = timer->c; + alts[0].v = nil; + alts[0].op = CHANRCV; + alts[1].c = mousectl->c; + alts[1].v = &mousectl->m; + alts[1].op = CHANRCV; + alts[2].op = CHANEND; + for (;;) + switch (alt(alts)) { + case 0: + timerstop(timer); + return; + case 1: + timercancel(timer); + return; + } } -void -textscroll(Text *t, int but) -{ - uint p0, oldp0; - Rectangle s; - int x, y, my, h, first; +void textscroll(Text* t, int but) { + uint p0, oldp0; + Rectangle s; + int x, y, my, h, first; - s = insetrect(t->scrollr, 1); - h = s.max.y-s.min.y; - x = (s.min.x+s.max.x)/2; - oldp0 = ~0; - first = TRUE; - do{ - flushimage(display, 1); - my = mouse->xy.y; - if(my < s.min.y) - my = s.min.y; - if(my >= s.max.y) - my = s.max.y; - if(!eqpt(mouse->xy, Pt(x, my))){ - moveto(mousectl, Pt(x, my)); - readmouse(mousectl); /* absorb event generated by moveto() */ - } - if(but == 2){ - y = my; - p0 = (vlong)t->file->b.nc*(y-s.min.y)/h; - if(p0 >= t->q1) - p0 = textbacknl(t, p0, 2); - if(oldp0 != p0) - textsetorigin(t, p0, FALSE); - oldp0 = p0; - readmouse(mousectl); - continue; - } - if(but == 1) - p0 = textbacknl(t, t->org, (my-s.min.y)/t->fr.font->height); - else - p0 = t->org+frcharofpt(&t->fr, Pt(s.max.x, my)); - if(oldp0 != p0) - textsetorigin(t, p0, TRUE); - oldp0 = p0; - /* debounce */ - if(first){ - flushimage(display, 1); - sleep(200); - nbrecv(mousectl->c, &mousectl->m); - first = FALSE; - } - scrsleep(80); - }while(mouse->buttons & (1<<(but-1))); - while(mouse->buttons) - readmouse(mousectl); + s = insetrect(t->scrollr, 1); + h = s.max.y - s.min.y; + x = (s.min.x + s.max.x) / 2; + oldp0 = ~0; + first = TRUE; + do { + flushimage(display, 1); + my = mouse->xy.y; + if (my < s.min.y) + my = s.min.y; + if (my >= s.max.y) + my = s.max.y; + if (!eqpt(mouse->xy, Pt(x, my))) { + moveto(mousectl, Pt(x, my)); + readmouse(mousectl); /* absorb event generated by moveto() */ + } + if (but == 2) { + y = my; + p0 = (vlong)t->file->b.nc * (y - s.min.y) / h; + if (p0 >= t->q1) + p0 = textbacknl(t, p0, 2); + if (oldp0 != p0) + textsetorigin(t, p0, FALSE); + oldp0 = p0; + readmouse(mousectl); + continue; + } + if (but == 1) + p0 = textbacknl(t, t->org, (my - s.min.y) / t->fr.font->height); + else + p0 = t->org + frcharofpt(&t->fr, Pt(s.max.x, my)); + if (oldp0 != p0) + textsetorigin(t, p0, TRUE); + oldp0 = p0; + /* debounce */ + if (first) { + flushimage(display, 1); + sleep(200); + nbrecv(mousectl->c, &mousectl->m); + first = FALSE; + } + scrsleep(80); + } while (mouse->buttons & (1 << (but - 1))); + while (mouse->buttons) + readmouse(mousectl); }
M text.ctext.c

@@ -13,1711 +13,1653 @@ #include <complete.h>

#include "dat.h" #include "fns.h" -Image *tagcols[NCOL]; -Image *textcols[NCOL]; -static Rune Ldot[] = { '.', 0 }; +Image* tagcols[NCOL]; +Image* textcols[NCOL]; +static Rune Ldot[] = {'.', 0}; -enum{ - TABDIR = 3 /* width of tabs in directory windows */ +enum { + TABDIR = 3 /* width of tabs in directory windows */ }; -void -textinit(Text *t, File *f, Rectangle r, Reffont *rf, Image *cols[NCOL]) -{ - t->file = f; - t->all = r; - t->scrollr = r; - t->scrollr.max.x = r.min.x+Scrollwid; - t->lastsr = nullrect; - r.min.x += Scrollwid+Scrollgap; - t->eq0 = ~0; - t->ncache = 0; - t->reffont = rf; - t->tabstop = maxtab; - memmove(t->fr.cols, cols, sizeof t->fr.cols); - textredraw(t, r, rf->f, screen, -1); +void textinit(Text* t, File* f, Rectangle r, Reffont* rf, Image* cols[NCOL]) { + t->file = f; + t->all = r; + t->scrollr = r; + t->scrollr.max.x = r.min.x + Scrollwid; + t->lastsr = nullrect; + r.min.x += Scrollwid + Scrollgap; + t->eq0 = ~0; + t->ncache = 0; + t->reffont = rf; + t->tabstop = maxtab; + memmove(t->fr.cols, cols, sizeof t->fr.cols); + textredraw(t, r, rf->f, screen, -1); } -void -textredraw(Text *t, Rectangle r, Font *f, Image *b, int odx) -{ - int maxt; - Rectangle rr; +void textredraw(Text* t, Rectangle r, Font* f, Image* b, int odx) { + int maxt; + Rectangle rr; - frinit(&t->fr, r, f, b, t->fr.cols); - rr = t->fr.r; - rr.min.x -= Scrollwid+Scrollgap; /* back fill to scroll bar */ - if(!t->fr.noredraw) - draw(t->fr.b, rr, t->fr.cols[BACK], nil, ZP); - /* use no wider than 3-space tabs in a directory */ - maxt = maxtab; - if(t->what == Body){ - if(t->w->isdir) - maxt = min(TABDIR, maxtab); - else - maxt = t->tabstop; - } - t->fr.maxtab = maxt*stringwidth(f, "0"); - if(t->what==Body && t->w->isdir && odx!=Dx(t->all)){ - if(t->fr.maxlines > 0){ - textreset(t); - textcolumnate(t, t->w->dlp, t->w->ndl); - textshow(t, 0, 0, 1); - } - }else{ - textfill(t); - textsetselect(t, t->q0, t->q1); - } + frinit(&t->fr, r, f, b, t->fr.cols); + rr = t->fr.r; + rr.min.x -= Scrollwid + Scrollgap; /* back fill to scroll bar */ + if (!t->fr.noredraw) + draw(t->fr.b, rr, t->fr.cols[BACK], nil, ZP); + /* use no wider than 3-space tabs in a directory */ + maxt = maxtab; + if (t->what == Body) { + if (t->w->isdir) + maxt = min(TABDIR, maxtab); + else + maxt = t->tabstop; + } + t->fr.maxtab = maxt * stringwidth(f, "0"); + if (t->what == Body && t->w->isdir && odx != Dx(t->all)) { + if (t->fr.maxlines > 0) { + textreset(t); + textcolumnate(t, t->w->dlp, t->w->ndl); + textshow(t, 0, 0, 1); + } + } else { + textfill(t); + textsetselect(t, t->q0, t->q1); + } } -int -textresize(Text *t, Rectangle r, int keepextra) -{ - int odx; +int textresize(Text* t, Rectangle r, int keepextra) { + int odx; - if(Dy(r) <= 0) - r.max.y = r.min.y; - else if(!keepextra) - r.max.y -= Dy(r)%t->fr.font->height; - odx = Dx(t->all); - t->all = r; - t->scrollr = r; - t->scrollr.max.x = r.min.x+Scrollwid; - t->lastsr = nullrect; - r.min.x += Scrollwid+Scrollgap; - frclear(&t->fr, 0); - textredraw(t, r, t->fr.font, t->fr.b, odx); - if(keepextra && t->fr.r.max.y < t->all.max.y && !t->fr.noredraw){ - /* draw background in bottom fringe of window */ - r.min.x -= Scrollgap; - r.min.y = t->fr.r.max.y; - r.max.y = t->all.max.y; - draw(screen, r, t->fr.cols[BACK], nil, ZP); - } - return t->all.max.y; + if (Dy(r) <= 0) + r.max.y = r.min.y; + else if (!keepextra) + r.max.y -= Dy(r) % t->fr.font->height; + odx = Dx(t->all); + t->all = r; + t->scrollr = r; + t->scrollr.max.x = r.min.x + Scrollwid; + t->lastsr = nullrect; + r.min.x += Scrollwid + Scrollgap; + frclear(&t->fr, 0); + textredraw(t, r, t->fr.font, t->fr.b, odx); + if (keepextra && t->fr.r.max.y < t->all.max.y && !t->fr.noredraw) { + /* draw background in bottom fringe of window */ + r.min.x -= Scrollgap; + r.min.y = t->fr.r.max.y; + r.max.y = t->all.max.y; + draw(screen, r, t->fr.cols[BACK], nil, ZP); + } + return t->all.max.y; } -void -textclose(Text *t) -{ - free(t->cache); - frclear(&t->fr, 1); - filedeltext(t->file, t); - t->file = nil; - rfclose(t->reffont); - if(argtext == t) - argtext = nil; - if(typetext == t) - typetext = nil; - if(seltext == t) - seltext = nil; - if(mousetext == t) - mousetext = nil; - if(barttext == t) - barttext = nil; +void textclose(Text* t) { + free(t->cache); + frclear(&t->fr, 1); + filedeltext(t->file, t); + t->file = nil; + rfclose(t->reffont); + if (argtext == t) + argtext = nil; + if (typetext == t) + typetext = nil; + if (seltext == t) + seltext = nil; + if (mousetext == t) + mousetext = nil; + if (barttext == t) + barttext = nil; } -int -dircmp(const void *a, const void *b) -{ - Dirlist *da, *db; - int i, n; +int dircmp(const void* a, const void* b) { + Dirlist *da, *db; + int i, n; - da = *(Dirlist**)a; - db = *(Dirlist**)b; - n = min(da->nr, db->nr); - i = memcmp(da->r, db->r, n*sizeof(Rune)); - if(i) - return i; - return da->nr - db->nr; + da = *(Dirlist**)a; + db = *(Dirlist**)b; + n = min(da->nr, db->nr); + i = memcmp(da->r, db->r, n * sizeof(Rune)); + if (i) + return i; + return da->nr - db->nr; } -void -textcolumnate(Text *t, Dirlist **dlp, int ndl) -{ - int i, j, w, colw, mint, maxt, ncol, nrow; - Dirlist *dl; - uint q1; - static Rune Lnl[] = { '\n', 0 }; - static Rune Ltab[] = { '\t', 0 }; +void textcolumnate(Text* t, Dirlist** dlp, int ndl) { + int i, j, w, colw, mint, maxt, ncol, nrow; + Dirlist* dl; + uint q1; + static Rune Lnl[] = {'\n', 0}; + static Rune Ltab[] = {'\t', 0}; - if(t->file->ntext > 1) - return; - mint = stringwidth(t->fr.font, "0"); - /* go for narrower tabs if set more than 3 wide */ - t->fr.maxtab = min(maxtab, TABDIR)*mint; - maxt = t->fr.maxtab; - colw = 0; - for(i=0; i<ndl; i++){ - dl = dlp[i]; - w = dl->wid; - if(maxt-w%maxt < mint || w%maxt==0) - w += mint; - if(w % maxt) - w += maxt-(w%maxt); - if(w > colw) - colw = w; - } - if(colw == 0) - ncol = 1; - else - ncol = max(1, Dx(t->fr.r)/colw); - nrow = (ndl+ncol-1)/ncol; + if (t->file->ntext > 1) + return; + mint = stringwidth(t->fr.font, "0"); + /* go for narrower tabs if set more than 3 wide */ + t->fr.maxtab = min(maxtab, TABDIR) * mint; + maxt = t->fr.maxtab; + colw = 0; + for (i = 0; i < ndl; i++) { + dl = dlp[i]; + w = dl->wid; + if (maxt - w % maxt < mint || w % maxt == 0) + w += mint; + if (w % maxt) + w += maxt - (w % maxt); + if (w > colw) + colw = w; + } + if (colw == 0) + ncol = 1; + else + ncol = max(1, Dx(t->fr.r) / colw); + nrow = (ndl + ncol - 1) / ncol; - q1 = 0; - for(i=0; i<nrow; i++){ - for(j=i; j<ndl; j+=nrow){ - dl = dlp[j]; - fileinsert(t->file, q1, dl->r, dl->nr); - q1 += dl->nr; - if(j+nrow >= ndl) - break; - w = dl->wid; - if(maxt-w%maxt < mint){ - fileinsert(t->file, q1, Ltab, 1); - q1++; - w += mint; - } - do{ - fileinsert(t->file, q1, Ltab, 1); - q1++; - w += maxt-(w%maxt); - }while(w < colw); - } - fileinsert(t->file, q1, Lnl, 1); - q1++; - } + q1 = 0; + for (i = 0; i < nrow; i++) { + for (j = i; j < ndl; j += nrow) { + dl = dlp[j]; + fileinsert(t->file, q1, dl->r, dl->nr); + q1 += dl->nr; + if (j + nrow >= ndl) + break; + w = dl->wid; + if (maxt - w % maxt < mint) { + fileinsert(t->file, q1, Ltab, 1); + q1++; + w += mint; + } + do { + fileinsert(t->file, q1, Ltab, 1); + q1++; + w += maxt - (w % maxt); + } while (w < colw); + } + fileinsert(t->file, q1, Lnl, 1); + q1++; + } } -int -textload(Text *t, uint q0, char *file, int setqid) -{ - Rune *rp; - Dirlist *dl, **dlp; - int fd, i, j, n, ndl, nulls; - uint q, q1; - Dir *d, *dbuf; - char *tmp; - Text *u; - DigestState *h; +int textload(Text* t, uint q0, char* file, int setqid) { + Rune* rp; + Dirlist *dl, **dlp; + int fd, i, j, n, ndl, nulls; + uint q, q1; + Dir *d, *dbuf; + char* tmp; + Text* u; + DigestState* h; - if(t->ncache!=0 || t->file->b.nc || t->w==nil || t!=&t->w->body) - error("text.load"); - if(t->w->isdir && t->file->nname==0){ - warning(nil, "empty directory name"); - return -1; - } - if(ismtpt(file)){ - warning(nil, "will not open self mount point %s\n", file); - return -1; - } - fd = open(file, OREAD); - if(fd < 0){ - warning(nil, "can't open %s: %r\n", file); - return -1; - } - d = dirfstat(fd); - if(d == nil){ - warning(nil, "can't fstat %s: %r\n", file); - goto Rescue; - } - nulls = FALSE; - h = nil; - if(d->qid.type & QTDIR){ - /* this is checked in get() but it's possible the file changed underfoot */ - if(t->file->ntext > 1){ - warning(nil, "%s is a directory; can't read with multiple windows on it\n", file); - goto Rescue; - } - t->w->isdir = TRUE; - t->w->filemenu = FALSE; - if(t->file->nname > 0 && t->file->name[t->file->nname-1] != '/'){ - rp = runemalloc(t->file->nname+1); - runemove(rp, t->file->name, t->file->nname); - rp[t->file->nname] = '/'; - winsetname(t->w, rp, t->file->nname+1); - free(rp); - } - dlp = nil; - ndl = 0; - dbuf = nil; - while((n=dirread(fd, &dbuf)) > 0){ - for(i=0; i<n; i++){ - dl = emalloc(sizeof(Dirlist)); - j = strlen(dbuf[i].name); - tmp = emalloc(j+1+1); - memmove(tmp, dbuf[i].name, j); - if(dbuf[i].qid.type & QTDIR) - tmp[j++] = '/'; - tmp[j] = '\0'; - dl->r = bytetorune(tmp, &dl->nr); - dl->wid = stringwidth(t->fr.font, tmp); - free(tmp); - ndl++; - dlp = realloc(dlp, ndl*sizeof(Dirlist*)); - dlp[ndl-1] = dl; - } - free(dbuf); - } - qsort(dlp, ndl, sizeof(Dirlist*), dircmp); - t->w->dlp = dlp; - t->w->ndl = ndl; - textcolumnate(t, dlp, ndl); - q1 = t->file->b.nc; - }else{ - t->w->isdir = FALSE; - t->w->filemenu = TRUE; - if(q0 == 0) - h = sha1(nil, 0, nil, nil); - q1 = q0 + fileload(t->file, q0, fd, &nulls, h); - } - if(setqid){ - if(h != nil) { - sha1(nil, 0, t->file->sha1, h); - h = nil; - } else { - memset(t->file->sha1, 0, sizeof t->file->sha1); - } - t->file->dev = d->dev; - t->file->mtime = d->mtime; - t->file->qidpath = d->qid.path; - } - close(fd); - rp = fbufalloc(); - for(q=q0; q<q1; q+=n){ - n = q1-q; - if(n > RBUFSIZE) - n = RBUFSIZE; - bufread(&t->file->b, q, rp, n); - if(q < t->org) - t->org += n; - else if(q <= t->org+t->fr.nchars) - frinsert(&t->fr, rp, rp+n, q-t->org); - if(t->fr.lastlinefull) - break; - } - fbuffree(rp); - for(i=0; i<t->file->ntext; i++){ - u = t->file->text[i]; - if(u != t){ - if(u->org > u->file->b.nc) /* will be 0 because of reset(), but safety first */ - u->org = 0; - textresize(u, u->all, TRUE); - textbacknl(u, u->org, 0); /* go to beginning of line */ - } - textsetselect(u, q0, q0); - } - if(nulls) - warning(nil, "%s: NUL bytes elided\n", file); - free(d); - return q1-q0; + if (t->ncache != 0 || t->file->b.nc || t->w == nil || t != &t->w->body) + error("text.load"); + if (t->w->isdir && t->file->nname == 0) { + warning(nil, "empty directory name"); + return -1; + } + if (ismtpt(file)) { + warning(nil, "will not open self mount point %s\n", file); + return -1; + } + fd = open(file, OREAD); + if (fd < 0) { + warning(nil, "can't open %s: %r\n", file); + return -1; + } + d = dirfstat(fd); + if (d == nil) { + warning(nil, "can't fstat %s: %r\n", file); + goto Rescue; + } + nulls = FALSE; + h = nil; + if (d->qid.type & QTDIR) { + /* this is checked in get() but it's possible the file changed underfoot */ + if (t->file->ntext > 1) { + warning( + nil, + "%s is a directory; can't read with multiple windows on it\n", + file); + goto Rescue; + } + t->w->isdir = TRUE; + t->w->filemenu = FALSE; + if (t->file->nname > 0 && t->file->name[t->file->nname - 1] != '/') { + rp = runemalloc(t->file->nname + 1); + runemove(rp, t->file->name, t->file->nname); + rp[t->file->nname] = '/'; + winsetname(t->w, rp, t->file->nname + 1); + free(rp); + } + dlp = nil; + ndl = 0; + dbuf = nil; + while ((n = dirread(fd, &dbuf)) > 0) { + for (i = 0; i < n; i++) { + dl = emalloc(sizeof(Dirlist)); + j = strlen(dbuf[i].name); + tmp = emalloc(j + 1 + 1); + memmove(tmp, dbuf[i].name, j); + if (dbuf[i].qid.type & QTDIR) + tmp[j++] = '/'; + tmp[j] = '\0'; + dl->r = bytetorune(tmp, &dl->nr); + dl->wid = stringwidth(t->fr.font, tmp); + free(tmp); + ndl++; + dlp = realloc(dlp, ndl * sizeof(Dirlist*)); + dlp[ndl - 1] = dl; + } + free(dbuf); + } + qsort(dlp, ndl, sizeof(Dirlist*), dircmp); + t->w->dlp = dlp; + t->w->ndl = ndl; + textcolumnate(t, dlp, ndl); + q1 = t->file->b.nc; + } else { + t->w->isdir = FALSE; + t->w->filemenu = TRUE; + if (q0 == 0) + h = sha1(nil, 0, nil, nil); + q1 = q0 + fileload(t->file, q0, fd, &nulls, h); + } + if (setqid) { + if (h != nil) { + sha1(nil, 0, t->file->sha1, h); + h = nil; + } else { + memset(t->file->sha1, 0, sizeof t->file->sha1); + } + t->file->dev = d->dev; + t->file->mtime = d->mtime; + t->file->qidpath = d->qid.path; + } + close(fd); + rp = fbufalloc(); + for (q = q0; q < q1; q += n) { + n = q1 - q; + if (n > RBUFSIZE) + n = RBUFSIZE; + bufread(&t->file->b, q, rp, n); + if (q < t->org) + t->org += n; + else if (q <= t->org + t->fr.nchars) + frinsert(&t->fr, rp, rp + n, q - t->org); + if (t->fr.lastlinefull) + break; + } + fbuffree(rp); + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + if (u != t) { + if (u->org > u->file->b.nc) /* will be 0 because of reset(), but safety + first */ + u->org = 0; + textresize(u, u->all, TRUE); + textbacknl(u, u->org, 0); /* go to beginning of line */ + } + textsetselect(u, q0, q0); + } + if (nulls) + warning(nil, "%s: NUL bytes elided\n", file); + free(d); + return q1 - q0; - Rescue: - close(fd); - return -1; +Rescue: + close(fd); + return -1; } -uint -textbsinsert(Text *t, uint q0, Rune *r, uint n, int tofile, int *nrp) -{ - Rune *bp, *tp, *up; - int i, initial; +uint textbsinsert(Text* t, uint q0, Rune* r, uint n, int tofile, int* nrp) { + Rune *bp, *tp, *up; + int i, initial; - if(t->what == Tag){ /* can't happen but safety first: mustn't backspace over file name */ - Err: - textinsert(t, q0, r, n, tofile); - *nrp = n; - return q0; - } - bp = r; - for(i=0; i<n; i++) - if(*bp++ == '\b'){ - --bp; - initial = 0; - tp = runemalloc(n); - runemove(tp, r, i); - up = tp+i; - for(; i<n; i++){ - *up = *bp++; - if(*up == '\b') - if(up == tp) - initial++; - else - --up; - else - up++; - } - if(initial){ - if(initial > q0) - initial = q0; - q0 -= initial; - textdelete(t, q0, q0+initial, tofile); - } - n = up-tp; - textinsert(t, q0, tp, n, tofile); - free(tp); - *nrp = n; - return q0; - } - goto Err; + if (t->what == Tag) { /* can't happen but safety first: mustn't backspace over + file name */ + Err: + textinsert(t, q0, r, n, tofile); + *nrp = n; + return q0; + } + bp = r; + for (i = 0; i < n; i++) + if (*bp++ == '\b') { + --bp; + initial = 0; + tp = runemalloc(n); + runemove(tp, r, i); + up = tp + i; + for (; i < n; i++) { + *up = *bp++; + if (*up == '\b') + if (up == tp) + initial++; + else + --up; + else + up++; + } + if (initial) { + if (initial > q0) + initial = q0; + q0 -= initial; + textdelete(t, q0, q0 + initial, tofile); + } + n = up - tp; + textinsert(t, q0, tp, n, tofile); + free(tp); + *nrp = n; + return q0; + } + goto Err; } -void -textinsert(Text *t, uint q0, Rune *r, uint n, int tofile) -{ - int c, i; - Text *u; +void textinsert(Text* t, uint q0, Rune* r, uint n, int tofile) { + int c, i; + Text* u; - if(tofile && t->ncache != 0) - error("text.insert"); - if(n == 0) - return; - if(tofile){ - fileinsert(t->file, q0, r, n); - if(t->what == Body){ - t->w->dirty = TRUE; - t->w->utflastqid = -1; - } - if(t->file->ntext > 1) - for(i=0; i<t->file->ntext; i++){ - u = t->file->text[i]; - if(u != t){ - u->w->dirty = TRUE; /* always a body */ - textinsert(u, q0, r, n, FALSE); - textsetselect(u, u->q0, u->q1); - textscrdraw(u); - } - } - - } - if(q0 < t->iq1) - t->iq1 += n; - if(q0 < t->q1) - t->q1 += n; - if(q0 < t->q0) - t->q0 += n; - if(q0 < t->org) - t->org += n; - else if(q0 <= t->org+t->fr.nchars) - frinsert(&t->fr, r, r+n, q0-t->org); - if(t->w){ - c = 'i'; - if(t->what == Body) - c = 'I'; - if(n <= EVENTSIZE) - winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q0+n, n, n, r); - else - winevent(t->w, "%c%d %d 0 0 \n", c, q0, q0+n, n); - } + if (tofile && t->ncache != 0) + error("text.insert"); + if (n == 0) + return; + if (tofile) { + fileinsert(t->file, q0, r, n); + if (t->what == Body) { + t->w->dirty = TRUE; + t->w->utflastqid = -1; + } + if (t->file->ntext > 1) + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + if (u != t) { + u->w->dirty = TRUE; /* always a body */ + textinsert(u, q0, r, n, FALSE); + textsetselect(u, u->q0, u->q1); + textscrdraw(u); + } + } + } + if (q0 < t->iq1) + t->iq1 += n; + if (q0 < t->q1) + t->q1 += n; + if (q0 < t->q0) + t->q0 += n; + if (q0 < t->org) + t->org += n; + else if (q0 <= t->org + t->fr.nchars) + frinsert(&t->fr, r, r + n, q0 - t->org); + if (t->w) { + c = 'i'; + if (t->what == Body) + c = 'I'; + if (n <= EVENTSIZE) + winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q0 + n, n, n, r); + else + winevent(t->w, "%c%d %d 0 0 \n", c, q0, q0 + n, n); + } } -void -typecommit(Text *t) -{ - if(t->w != nil) - wincommit(t->w, t); - else - textcommit(t, TRUE); +void typecommit(Text* t) { + if (t->w != nil) + wincommit(t->w, t); + else + textcommit(t, TRUE); } -void -textfill(Text *t) -{ - Rune *rp; - int i, n, m, nl; +void textfill(Text* t) { + Rune* rp; + int i, n, m, nl; - if(t->fr.lastlinefull || t->nofill) - return; - if(t->ncache > 0) - typecommit(t); - rp = fbufalloc(); - do{ - n = t->file->b.nc-(t->org+t->fr.nchars); - if(n == 0) - break; - if(n > 2000) /* educated guess at reasonable amount */ - n = 2000; - bufread(&t->file->b, t->org+t->fr.nchars, rp, n); - /* - * it's expensive to frinsert more than we need, so - * count newlines. - */ - nl = t->fr.maxlines-t->fr.nlines; - m = 0; - for(i=0; i<n; ){ - if(rp[i++] == '\n'){ - m++; - if(m >= nl) - break; - } - } - frinsert(&t->fr, rp, rp+i, t->fr.nchars); - }while(t->fr.lastlinefull == FALSE); - fbuffree(rp); + if (t->fr.lastlinefull || t->nofill) + return; + if (t->ncache > 0) + typecommit(t); + rp = fbufalloc(); + do { + n = t->file->b.nc - (t->org + t->fr.nchars); + if (n == 0) + break; + if (n > 2000) /* educated guess at reasonable amount */ + n = 2000; + bufread(&t->file->b, t->org + t->fr.nchars, rp, n); + /* + * it's expensive to frinsert more than we need, so + * count newlines. + */ + nl = t->fr.maxlines - t->fr.nlines; + m = 0; + for (i = 0; i < n;) { + if (rp[i++] == '\n') { + m++; + if (m >= nl) + break; + } + } + frinsert(&t->fr, rp, rp + i, t->fr.nchars); + } while (t->fr.lastlinefull == FALSE); + fbuffree(rp); } -void -textdelete(Text *t, uint q0, uint q1, int tofile) -{ - uint n, p0, p1; - int i, c; - Text *u; +void textdelete(Text* t, uint q0, uint q1, int tofile) { + uint n, p0, p1; + int i, c; + Text* u; - if(tofile && t->ncache != 0) - error("text.delete"); - n = q1-q0; - if(n == 0) - return; - if(tofile){ - filedelete(t->file, q0, q1); - if(t->what == Body){ - t->w->dirty = TRUE; - t->w->utflastqid = -1; - } - if(t->file->ntext > 1) - for(i=0; i<t->file->ntext; i++){ - u = t->file->text[i]; - if(u != t){ - u->w->dirty = TRUE; /* always a body */ - textdelete(u, q0, q1, FALSE); - textsetselect(u, u->q0, u->q1); - textscrdraw(u); - } - } - } - if(q0 < t->iq1) - t->iq1 -= min(n, t->iq1-q0); - if(q0 < t->q0) - t->q0 -= min(n, t->q0-q0); - if(q0 < t->q1) - t->q1 -= min(n, t->q1-q0); - if(q1 <= t->org) - t->org -= n; - else if(q0 < t->org+t->fr.nchars){ - p1 = q1 - t->org; - if(p1 > t->fr.nchars) - p1 = t->fr.nchars; - if(q0 < t->org){ - t->org = q0; - p0 = 0; - }else - p0 = q0 - t->org; - frdelete(&t->fr, p0, p1); - textfill(t); - } - if(t->w){ - c = 'd'; - if(t->what == Body) - c = 'D'; - winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1); - } + if (tofile && t->ncache != 0) + error("text.delete"); + n = q1 - q0; + if (n == 0) + return; + if (tofile) { + filedelete(t->file, q0, q1); + if (t->what == Body) { + t->w->dirty = TRUE; + t->w->utflastqid = -1; + } + if (t->file->ntext > 1) + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + if (u != t) { + u->w->dirty = TRUE; /* always a body */ + textdelete(u, q0, q1, FALSE); + textsetselect(u, u->q0, u->q1); + textscrdraw(u); + } + } + } + if (q0 < t->iq1) + t->iq1 -= min(n, t->iq1 - q0); + if (q0 < t->q0) + t->q0 -= min(n, t->q0 - q0); + if (q0 < t->q1) + t->q1 -= min(n, t->q1 - q0); + if (q1 <= t->org) + t->org -= n; + else if (q0 < t->org + t->fr.nchars) { + p1 = q1 - t->org; + if (p1 > t->fr.nchars) + p1 = t->fr.nchars; + if (q0 < t->org) { + t->org = q0; + p0 = 0; + } else + p0 = q0 - t->org; + frdelete(&t->fr, p0, p1); + textfill(t); + } + if (t->w) { + c = 'd'; + if (t->what == Body) + c = 'D'; + winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1); + } } -void -textconstrain(Text *t, uint q0, uint q1, uint *p0, uint *p1) -{ - *p0 = min(q0, t->file->b.nc); - *p1 = min(q1, t->file->b.nc); +void textconstrain(Text* t, uint q0, uint q1, uint* p0, uint* p1) { + *p0 = min(q0, t->file->b.nc); + *p1 = min(q1, t->file->b.nc); } -Rune -textreadc(Text *t, uint q) -{ - Rune r; +Rune textreadc(Text* t, uint q) { + Rune r; - if(t->cq0<=q && q<t->cq0+t->ncache) - r = t->cache[q-t->cq0]; - else - bufread(&t->file->b, q, &r, 1); - return r; + if (t->cq0 <= q && q < t->cq0 + t->ncache) + r = t->cache[q - t->cq0]; + else + bufread(&t->file->b, q, &r, 1); + return r; } -static int -spacesindentbswidth(Text *t) -{ - uint q, col; - Rune r; +static int spacesindentbswidth(Text* t) { + uint q, col; + Rune r; - col = textbswidth(t, 0x15); - q = t->q0; - while(q > 0){ - r = textreadc(t, q-1); - if(r != ' ') - break; - q--; - if(--col % t->tabstop == 0) - break; - } - if(t->q0 == q) - return 1; - return t->q0-q; + col = textbswidth(t, 0x15); + q = t->q0; + while (q > 0) { + r = textreadc(t, q - 1); + if (r != ' ') + break; + q--; + if (--col % t->tabstop == 0) + break; + } + if (t->q0 == q) + return 1; + return t->q0 - q; } -int -textbswidth(Text *t, Rune c) -{ - uint q, eq; - Rune r; - int skipping; +int textbswidth(Text* t, Rune c) { + uint q, eq; + Rune r; + int skipping; - /* there is known to be at least one character to erase */ - if(c == 0x08){ /* ^H: erase character */ - if(t->what == Body && t->w->indent[SPACESINDENT]) - return spacesindentbswidth(t); - return 1; - } - q = t->q0; - skipping = TRUE; - while(q > 0){ - r = textreadc(t, q-1); - if(r == '\n'){ /* eat at most one more character */ - if(q == t->q0) /* eat the newline */ - --q; - break; - } - if(c == 0x17){ - eq = isalnum(r); - if(eq && skipping) /* found one; stop skipping */ - skipping = FALSE; - else if(!eq && !skipping) - break; - } - --q; - } - return t->q0-q; + /* there is known to be at least one character to erase */ + if (c == 0x08) { /* ^H: erase character */ + if (t->what == Body && t->w->indent[SPACESINDENT]) + return spacesindentbswidth(t); + return 1; + } + q = t->q0; + skipping = TRUE; + while (q > 0) { + r = textreadc(t, q - 1); + if (r == '\n') { /* eat at most one more character */ + if (q == t->q0) /* eat the newline */ + --q; + break; + } + if (c == 0x17) { + eq = isalnum(r); + if (eq && skipping) /* found one; stop skipping */ + skipping = FALSE; + else if (!eq && !skipping) + break; + } + --q; + } + return t->q0 - q; } -int -textfilewidth(Text *t, uint q0, int oneelement) -{ - uint q; - Rune r; +int textfilewidth(Text* t, uint q0, int oneelement) { + uint q; + Rune r; - q = q0; - while(q > 0){ - r = textreadc(t, q-1); - if(r <= ' ') - break; - if(oneelement && r=='/') - break; - --q; - } - return q0-q; + q = q0; + while (q > 0) { + r = textreadc(t, q - 1); + if (r <= ' ') + break; + if (oneelement && r == '/') + break; + --q; + } + return q0 - q; } -Rune* -textcomplete(Text *t) -{ - int i, nstr, npath; - uint q; - Rune tmp[200]; - Rune *str, *path; - Rune *rp; - Completion *c; - char *s, *dirs; - Runestr dir; +Rune* textcomplete(Text* t) { + int i, nstr, npath; + uint q; + Rune tmp[200]; + Rune *str, *path; + Rune* rp; + Completion* c; + char *s, *dirs; + Runestr dir; - /* control-f: filename completion; works back to white space or / */ - if(t->q0<t->file->b.nc && textreadc(t, t->q0)>' ') /* must be at end of word */ - return nil; - nstr = textfilewidth(t, t->q0, TRUE); - str = runemalloc(nstr); - npath = textfilewidth(t, t->q0-nstr, FALSE); - path = runemalloc(npath); + /* control-f: filename completion; works back to white space or / */ + if (t->q0 < t->file->b.nc && textreadc(t, t->q0) > ' ') /* must be at end of + word */ + return nil; + nstr = textfilewidth(t, t->q0, TRUE); + str = runemalloc(nstr); + npath = textfilewidth(t, t->q0 - nstr, FALSE); + path = runemalloc(npath); - c = nil; - rp = nil; - dirs = nil; + c = nil; + rp = nil; + dirs = nil; - q = t->q0-nstr; - for(i=0; i<nstr; i++) - str[i] = textreadc(t, q++); - q = t->q0-nstr-npath; - for(i=0; i<npath; i++) - path[i] = textreadc(t, q++); - /* is path rooted? if not, we need to make it relative to window path */ - if(npath>0 && path[0]=='/') - dir = runestr(path, npath); - else{ - dir = dirname(t, nil, 0); - if(dir.nr + 1 + npath > nelem(tmp)){ - free(dir.r); - goto Return; - } - if(dir.nr == 0){ - dir.nr = 1; - dir.r = runestrdup(Ldot); - } - runemove(tmp, dir.r, dir.nr); - tmp[dir.nr] = '/'; - runemove(tmp+dir.nr+1, path, npath); - free(dir.r); - dir.r = tmp; - dir.nr += 1+npath; - dir = cleanrname(dir); - } + q = t->q0 - nstr; + for (i = 0; i < nstr; i++) + str[i] = textreadc(t, q++); + q = t->q0 - nstr - npath; + for (i = 0; i < npath; i++) + path[i] = textreadc(t, q++); + /* is path rooted? if not, we need to make it relative to window path */ + if (npath > 0 && path[0] == '/') + dir = runestr(path, npath); + else { + dir = dirname(t, nil, 0); + if (dir.nr + 1 + npath > nelem(tmp)) { + free(dir.r); + goto Return; + } + if (dir.nr == 0) { + dir.nr = 1; + dir.r = runestrdup(Ldot); + } + runemove(tmp, dir.r, dir.nr); + tmp[dir.nr] = '/'; + runemove(tmp + dir.nr + 1, path, npath); + free(dir.r); + dir.r = tmp; + dir.nr += 1 + npath; + dir = cleanrname(dir); + } - s = smprint("%.*S", nstr, str); - dirs = smprint("%.*S", dir.nr, dir.r); - c = complete(dirs, s); - free(s); - if(c == nil){ - warning(nil, "error attempting completion: %r\n"); - goto Return; - } + s = smprint("%.*S", nstr, str); + dirs = smprint("%.*S", dir.nr, dir.r); + c = complete(dirs, s); + free(s); + if (c == nil) { + warning(nil, "error attempting completion: %r\n"); + goto Return; + } - if(!c->advance){ - warning(nil, "%.*S%s%.*S*%s\n", - dir.nr, dir.r, - dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "", - nstr, str, - c->nmatch ? "" : ": no matches in:"); - for(i=0; i<c->nfile; i++) - warning(nil, " %s\n", c->filename[i]); - } + if (!c->advance) { + warning( + nil, + "%.*S%s%.*S*%s\n", + dir.nr, + dir.r, + dir.nr > 0 && dir.r[dir.nr - 1] != '/' ? "/" : "", + nstr, + str, + c->nmatch ? "" : ": no matches in:"); + for (i = 0; i < c->nfile; i++) + warning(nil, " %s\n", c->filename[i]); + } - if(c->advance) - rp = runesmprint("%s", c->string); - else - rp = nil; - Return: - freecompletion(c); - free(dirs); - free(str); - free(path); - return rp; + if (c->advance) + rp = runesmprint("%s", c->string); + else + rp = nil; +Return: + freecompletion(c); + free(dirs); + free(str); + free(path); + return rp; } -void -texttype(Text *t, Rune r) -{ - uint q0, q1; - int nnb, nb, n, i; - int nr; - Rune *rp; - Text *u; +void texttype(Text* t, Rune r) { + uint q0, q1; + int nnb, nb, n, i; + int nr; + Rune* rp; + Text* u; - if(t->what!=Body && t->what!=Tag && r=='\n') - return; - if(t->what == Tag) - t->w->tagsafe = FALSE; + if (t->what != Body && t->what != Tag && r == '\n') + return; + if (t->what == Tag) + t->w->tagsafe = FALSE; - nr = 1; - rp = &r; - switch(r){ - case Kleft: - typecommit(t); - if(t->q0 > 0) - textshow(t, t->q0-1, t->q0-1, TRUE); - return; - case Kright: - typecommit(t); - if(t->q1 < t->file->b.nc) - textshow(t, t->q1+1, t->q1+1, TRUE); - return; - case Kdown: - typecommit(t); - q0 = t->q0; - nnb = 0; - if(t->q0>0 && textreadc(t, t->q0-1)!='\n') - nnb = textbswidth(t, 0x15); - while(q0<t->file->b.nc && textreadc(t, q0)!='\n') - q0++; - if (q0 == t->file->b.nc) { - textshow(t, q0, q0, TRUE); - return; - } - q0++; - while(nnb>=0 && q0<t->file->b.nc) { - if (textreadc(t, q0)=='\n') - break; - nnb--; - if (nnb >= 0) - q0++; - } - textshow(t, q0, q0, TRUE); - return; - case Kscrollonedown: - if(t->what == Tag) - goto Tagdown; - n = mousescrollsize(t->fr.maxlines); - if(n <= 0) - n = 1; - goto case_Down; - case Kpgdown: - n = 2*t->fr.maxlines/3; - case_Down: - q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height)); - textsetorigin(t, q0, TRUE); - return; - case Kup: - typecommit(t); - nnb = 0; - if(t->q0>0 && textreadc(t, t->q0-1)!='\n') - nnb = textbswidth(t, 0x15); - q1 = nnb; - if(t->q0-nnb > 1 && textreadc(t, t->q0-nnb-1)=='\n') - nnb++; - q0 = t->q0-nnb; - textshow(t, q0, q0, TRUE); - - nnb = textbswidth(t, 0x15); - if (nnb <= 1) + nr = 1; + rp = &r; + switch (r) { + case Kleft: + typecommit(t); + if (t->q0 > 0) + textshow(t, t->q0 - 1, t->q0 - 1, TRUE); + return; + case Kright: + typecommit(t); + if (t->q1 < t->file->b.nc) + textshow(t, t->q1 + 1, t->q1 + 1, TRUE); return; - q0 = q0-nnb; - while (q1>0 && textreadc(t, q0)!='\n') { - q1--; + case Kdown: + typecommit(t); + q0 = t->q0; + nnb = 0; + if (t->q0 > 0 && textreadc(t, t->q0 - 1) != '\n') + nnb = textbswidth(t, 0x15); + while (q0 < t->file->b.nc && textreadc(t, q0) != '\n') + q0++; + if (q0 == t->file->b.nc) { + textshow(t, q0, q0, TRUE); + return; + } q0++; - } - textshow(t, q0, q0, TRUE); - return; - case Kscrolloneup: - if(t->what == Tag) - goto Tagup; - n = mousescrollsize(t->fr.maxlines); - goto case_Up; - case Kpgup: - n = 2*t->fr.maxlines/3; - case_Up: - q0 = textbacknl(t, t->org, n); - textsetorigin(t, q0, TRUE); - return; - case Khome: - case 0x01: /* ^A: beginning of line */ - typecommit(t); - /* go to where ^U would erase, if not already at BOL */ - nnb = 0; - if(t->q0>0 && textreadc(t, t->q0-1)!='\n') - nnb = textbswidth(t, 0x15); - textshow(t, t->q0-nnb, t->q0-nnb, TRUE); - return; - case Kend: - case 0x05: /* ^E: end of line */ - typecommit(t); - q0 = t->q0; - while(q0<t->file->b.nc && textreadc(t, q0)!='\n') - q0++; - textshow(t, q0, q0, TRUE); - return; - case 0x03: /* Ctrl-c: copy */ - case Kcmd+'c': /* %C: copy */ - typecommit(t); - cut(t, t, nil, TRUE, FALSE, nil, 0); - return; - case 0x1a: /* Ctrl-z: undo */ - case Kcmd+'z': /* %Z: undo */ - typecommit(t); - undo(t, nil, nil, TRUE, 0, nil, 0); - return; - case 0x19: /* Ctrl-y: redo */ - case Kcmd+'Z': /* %-shift-Z: redo */ - typecommit(t); - undo(t, nil, nil, FALSE, 0, nil, 0); - return; - case 0x13: /* Ctrl-S: put file */ - case Kcmd+'s': - typecommit(t); - put(&(t->w)->body, nil, nil, XXX, XXX, nil, 0); - return; - Tagdown: - /* expand tag to show all text */ - if(!t->w->tagexpand){ - t->w->tagexpand = TRUE; - winresize(t->w, t->w->r, FALSE, TRUE); - } - return; + while (nnb >= 0 && q0 < t->file->b.nc) { + if (textreadc(t, q0) == '\n') + break; + nnb--; + if (nnb >= 0) + q0++; + } + textshow(t, q0, q0, TRUE); + return; + case Kscrollonedown: + if (t->what == Tag) + goto Tagdown; + n = mousescrollsize(t->fr.maxlines); + if (n <= 0) + n = 1; + goto case_Down; + case Kpgdown: + n = 2 * t->fr.maxlines / 3; + case_Down: + q0 = + t->org + frcharofpt( + &t->fr, + Pt(t->fr.r.min.x, t->fr.r.min.y + n * t->fr.font->height)); + textsetorigin(t, q0, TRUE); + return; + case Kup: + typecommit(t); + nnb = 0; + if (t->q0 > 0 && textreadc(t, t->q0 - 1) != '\n') + nnb = textbswidth(t, 0x15); + q1 = nnb; + if (t->q0 - nnb > 1 && textreadc(t, t->q0 - nnb - 1) == '\n') + nnb++; + q0 = t->q0 - nnb; + textshow(t, q0, q0, TRUE); - Tagup: - /* shrink tag to single line */ - if(t->w->tagexpand){ - t->w->tagexpand = FALSE; - t->w->taglines = 1; - winresize(t->w, t->w->r, FALSE, TRUE); - } - return; - } - if(t->what == Body){ - seq++; - filemark(t->file); - } - /* cut/paste must be done after the seq++/filemark */ - switch(r){ - case 0x18: /* Ctrl-X: cut */ - case Kcmd+'x': /* %X: cut */ - typecommit(t); - if(t->what == Body){ - seq++; - filemark(t->file); - } - cut(t, t, nil, TRUE, TRUE, nil, 0); - textshow(t, t->q0, t->q0, 1); - t->iq1 = t->q0; - return; - case 0x16: /* Ctrl-V: paste */ - case Kcmd+'v': /* %V: paste */ - typecommit(t); - if(t->what == Body){ - seq++; - filemark(t->file); - } - paste(t, t, nil, TRUE, FALSE, nil, 0); - textshow(t, t->q0, t->q1, 1); - t->iq1 = t->q1; - return; - } - if(t->q1 > t->q0){ - if(t->ncache != 0) - error("text.type"); - cut(t, t, nil, TRUE, TRUE, nil, 0); - t->eq0 = ~0; - } - textshow(t, t->q0, t->q0, 1); - switch(r){ - case 0x06: /* ^F: complete */ - case Kins: - typecommit(t); - rp = textcomplete(t); - if(rp == nil) - return; - nr = runestrlen(rp); - break; /* fall through to normal insertion case */ - case 0x1B: - if(t->eq0 != ~0) { - if(t->eq0 <= t->q0) - textsetselect(t, t->eq0, t->q0); - else - textsetselect(t, t->q0, t->eq0); - } - if(t->ncache > 0) - typecommit(t); - t->iq1 = t->q0; - return; - case 0x08: /* ^H: erase character */ - case 0x15: /* ^U: erase line */ - case 0x17: /* ^W: erase word */ - if(t->q0 == 0) /* nothing to erase */ - return; - nnb = textbswidth(t, r); - q1 = t->q0; - q0 = q1-nnb; - /* if selection is at beginning of window, avoid deleting invisible text */ - if(q0 < t->org){ - q0 = t->org; - nnb = q1-q0; - } - if(nnb <= 0) - return; - for(i=0; i<t->file->ntext; i++){ - u = t->file->text[i]; - u->nofill = TRUE; - nb = nnb; - n = u->ncache; - if(n > 0){ - if(q1 != u->cq0+n) - error("text.type backspace"); - if(n > nb) - n = nb; - u->ncache -= n; - textdelete(u, q1-n, q1, FALSE); - nb -= n; - } - if(u->eq0==q1 || u->eq0==~0) - u->eq0 = q0; - if(nb && u==t) - textdelete(u, q0, q0+nb, TRUE); - if(u != t) - textsetselect(u, u->q0, u->q1); - else - textsetselect(t, q0, q0); - u->nofill = FALSE; - } - for(i=0; i<t->file->ntext; i++) - textfill(t->file->text[i]); - t->iq1 = t->q0; - return; - case '\t': - if(t->what == Body && t->w->indent[SPACESINDENT]){ - nnb = textbswidth(t, 0x15); - if(nnb == 1 && textreadc(t, t->q0-1) == '\n') - nnb = 0; - nnb = t->tabstop - nnb % t->tabstop; - rp = runemalloc(nnb); - for(nr = 0; nr < nnb; nr++) - rp[nr] = ' '; - } - break; - case '\n': - if(t->what == Body && t->w->indent[AUTOINDENT]){ - /* find beginning of previous line using backspace code */ - nnb = textbswidth(t, 0x15); /* ^U case */ - rp = runemalloc(nnb + 1); - nr = 0; - rp[nr++] = r; - for(i=0; i<nnb; i++){ - r = textreadc(t, t->q0-nnb+i); - if(r != ' ' && r != '\t') - break; - rp[nr++] = r; - } - } - break; /* fall through to normal code */ - } - /* otherwise ordinary character; just insert, typically in caches of all texts */ - for(i=0; i<t->file->ntext; i++){ - u = t->file->text[i]; - if(u->eq0 == ~0) - u->eq0 = t->q0; - if(u->ncache == 0) - u->cq0 = t->q0; - else if(t->q0 != u->cq0+u->ncache) - error("text.type cq1"); - /* - * Change the tag before we add to ncache, - * so that if the window body is resized the - * commit will not find anything in ncache. - */ - if(u->what==Body && u->ncache == 0){ - u->needundo = TRUE; - winsettag(t->w); - u->needundo = FALSE; - } - textinsert(u, t->q0, rp, nr, FALSE); - if(u != t) - textsetselect(u, u->q0, u->q1); - if(u->ncache+nr > u->ncachealloc){ - u->ncachealloc += 10 + nr; - u->cache = runerealloc(u->cache, u->ncachealloc); - } - runemove(u->cache+u->ncache, rp, nr); - u->ncache += nr; - } - if(rp != &r) - free(rp); - textsetselect(t, t->q0+nr, t->q0+nr); - if(r=='\n' && t->w!=nil) - wincommit(t->w, t); - t->iq1 = t->q0; + nnb = textbswidth(t, 0x15); + if (nnb <= 1) + return; + q0 = q0 - nnb; + while (q1 > 0 && textreadc(t, q0) != '\n') { + q1--; + q0++; + } + textshow(t, q0, q0, TRUE); + return; + case Kscrolloneup: + if (t->what == Tag) + goto Tagup; + n = mousescrollsize(t->fr.maxlines); + goto case_Up; + case Kpgup: + n = 2 * t->fr.maxlines / 3; + case_Up: + q0 = textbacknl(t, t->org, n); + textsetorigin(t, q0, TRUE); + return; + case Khome: + case 0x01: /* ^A: beginning of line */ + typecommit(t); + /* go to where ^U would erase, if not already at BOL */ + nnb = 0; + if (t->q0 > 0 && textreadc(t, t->q0 - 1) != '\n') + nnb = textbswidth(t, 0x15); + textshow(t, t->q0 - nnb, t->q0 - nnb, TRUE); + return; + case Kend: + case 0x05: /* ^E: end of line */ + typecommit(t); + q0 = t->q0; + while (q0 < t->file->b.nc && textreadc(t, q0) != '\n') + q0++; + textshow(t, q0, q0, TRUE); + return; + case 0x03: /* Ctrl-c: copy */ + case Kcmd + 'c': /* %C: copy */ + typecommit(t); + cut(t, t, nil, TRUE, FALSE, nil, 0); + return; + case 0x1a: /* Ctrl-z: undo */ + case Kcmd + 'z': /* %Z: undo */ + typecommit(t); + undo(t, nil, nil, TRUE, 0, nil, 0); + return; + case 0x19: /* Ctrl-y: redo */ + case Kcmd + 'Z': /* %-shift-Z: redo */ + typecommit(t); + undo(t, nil, nil, FALSE, 0, nil, 0); + return; + case 0x13: /* Ctrl-S: put file */ + case Kcmd + 's': + typecommit(t); + put(&(t->w)->body, nil, nil, XXX, XXX, nil, 0); + return; + Tagdown: + /* expand tag to show all text */ + if (!t->w->tagexpand) { + t->w->tagexpand = TRUE; + winresize(t->w, t->w->r, FALSE, TRUE); + } + return; + + Tagup: + /* shrink tag to single line */ + if (t->w->tagexpand) { + t->w->tagexpand = FALSE; + t->w->taglines = 1; + winresize(t->w, t->w->r, FALSE, TRUE); + } + return; + } + if (t->what == Body) { + seq++; + filemark(t->file); + } + /* cut/paste must be done after the seq++/filemark */ + switch (r) { + case 0x18: /* Ctrl-X: cut */ + case Kcmd + 'x': /* %X: cut */ + typecommit(t); + if (t->what == Body) { + seq++; + filemark(t->file); + } + cut(t, t, nil, TRUE, TRUE, nil, 0); + textshow(t, t->q0, t->q0, 1); + t->iq1 = t->q0; + return; + case 0x16: /* Ctrl-V: paste */ + case Kcmd + 'v': /* %V: paste */ + typecommit(t); + if (t->what == Body) { + seq++; + filemark(t->file); + } + paste(t, t, nil, TRUE, FALSE, nil, 0); + textshow(t, t->q0, t->q1, 1); + t->iq1 = t->q1; + return; + } + if (t->q1 > t->q0) { + if (t->ncache != 0) + error("text.type"); + cut(t, t, nil, TRUE, TRUE, nil, 0); + t->eq0 = ~0; + } + textshow(t, t->q0, t->q0, 1); + switch (r) { + case 0x06: /* ^F: complete */ + case Kins: + typecommit(t); + rp = textcomplete(t); + if (rp == nil) + return; + nr = runestrlen(rp); + break; /* fall through to normal insertion case */ + case 0x1B: + if (t->eq0 != ~0) { + if (t->eq0 <= t->q0) + textsetselect(t, t->eq0, t->q0); + else + textsetselect(t, t->q0, t->eq0); + } + if (t->ncache > 0) + typecommit(t); + t->iq1 = t->q0; + return; + case 0x08: /* ^H: erase character */ + case 0x15: /* ^U: erase line */ + case 0x17: /* ^W: erase word */ + if (t->q0 == 0) /* nothing to erase */ + return; + nnb = textbswidth(t, r); + q1 = t->q0; + q0 = q1 - nnb; + /* if selection is at beginning of window, avoid deleting invisible text + */ + if (q0 < t->org) { + q0 = t->org; + nnb = q1 - q0; + } + if (nnb <= 0) + return; + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + u->nofill = TRUE; + nb = nnb; + n = u->ncache; + if (n > 0) { + if (q1 != u->cq0 + n) + error("text.type backspace"); + if (n > nb) + n = nb; + u->ncache -= n; + textdelete(u, q1 - n, q1, FALSE); + nb -= n; + } + if (u->eq0 == q1 || u->eq0 == ~0) + u->eq0 = q0; + if (nb && u == t) + textdelete(u, q0, q0 + nb, TRUE); + if (u != t) + textsetselect(u, u->q0, u->q1); + else + textsetselect(t, q0, q0); + u->nofill = FALSE; + } + for (i = 0; i < t->file->ntext; i++) + textfill(t->file->text[i]); + t->iq1 = t->q0; + return; + case '\t': + if (t->what == Body && t->w->indent[SPACESINDENT]) { + nnb = textbswidth(t, 0x15); + if (nnb == 1 && textreadc(t, t->q0 - 1) == '\n') + nnb = 0; + nnb = t->tabstop - nnb % t->tabstop; + rp = runemalloc(nnb); + for (nr = 0; nr < nnb; nr++) + rp[nr] = ' '; + } + break; + case '\n': + if (t->what == Body && t->w->indent[AUTOINDENT]) { + /* find beginning of previous line using backspace code */ + nnb = textbswidth(t, 0x15); /* ^U case */ + rp = runemalloc(nnb + 1); + nr = 0; + rp[nr++] = r; + for (i = 0; i < nnb; i++) { + r = textreadc(t, t->q0 - nnb + i); + if (r != ' ' && r != '\t') + break; + rp[nr++] = r; + } + } + break; /* fall through to normal code */ + } + /* otherwise ordinary character; just insert, typically in caches of all texts + */ + for (i = 0; i < t->file->ntext; i++) { + u = t->file->text[i]; + if (u->eq0 == ~0) + u->eq0 = t->q0; + if (u->ncache == 0) + u->cq0 = t->q0; + else if (t->q0 != u->cq0 + u->ncache) + error("text.type cq1"); + /* + * Change the tag before we add to ncache, + * so that if the window body is resized the + * commit will not find anything in ncache. + */ + if (u->what == Body && u->ncache == 0) { + u->needundo = TRUE; + winsettag(t->w); + u->needundo = FALSE; + } + textinsert(u, t->q0, rp, nr, FALSE); + if (u != t) + textsetselect(u, u->q0, u->q1); + if (u->ncache + nr > u->ncachealloc) { + u->ncachealloc += 10 + nr; + u->cache = runerealloc(u->cache, u->ncachealloc); + } + runemove(u->cache + u->ncache, rp, nr); + u->ncache += nr; + } + if (rp != &r) + free(rp); + textsetselect(t, t->q0 + nr, t->q0 + nr); + if (r == '\n' && t->w != nil) + wincommit(t->w, t); + t->iq1 = t->q0; } - -void -textcommit(Text *t, int tofile) -{ - if(t->ncache == 0) - return; - if(tofile) - fileinsert(t->file, t->cq0, t->cache, t->ncache); - if(t->what == Body){ - t->w->dirty = TRUE; - t->w->utflastqid = -1; - } - t->ncache = 0; +void textcommit(Text* t, int tofile) { + if (t->ncache == 0) + return; + if (tofile) + fileinsert(t->file, t->cq0, t->cache, t->ncache); + if (t->what == Body) { + t->w->dirty = TRUE; + t->w->utflastqid = -1; + } + t->ncache = 0; } -static Text *clicktext; -static uint clickmsec; -static Text *selecttext; -static uint selectq; +static Text* clicktext; +static uint clickmsec; +static Text* selecttext; +static uint selectq; /* * called from frame library */ -void -framescroll(Frame *f, int dl) -{ - if(f != &selecttext->fr) - error("frameselect not right frame"); - textframescroll(selecttext, dl); +void framescroll(Frame* f, int dl) { + if (f != &selecttext->fr) + error("frameselect not right frame"); + textframescroll(selecttext, dl); } -void -textframescroll(Text *t, int dl) -{ - uint q0; +void textframescroll(Text* t, int dl) { + uint q0; - if(dl == 0){ - scrsleep(100); - return; - } - if(dl < 0){ - q0 = textbacknl(t, t->org, -dl); - if(selectq > t->org+t->fr.p0) - textsetselect(t, t->org+t->fr.p0, selectq); - else - textsetselect(t, selectq, t->org+t->fr.p0); - }else{ - if(t->org+t->fr.nchars == t->file->b.nc) - return; - q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+dl*t->fr.font->height)); - if(selectq > t->org+t->fr.p1) - textsetselect(t, t->org+t->fr.p1, selectq); - else - textsetselect(t, selectq, t->org+t->fr.p1); - } - textsetorigin(t, q0, TRUE); + if (dl == 0) { + scrsleep(100); + return; + } + if (dl < 0) { + q0 = textbacknl(t, t->org, -dl); + if (selectq > t->org + t->fr.p0) + textsetselect(t, t->org + t->fr.p0, selectq); + else + textsetselect(t, selectq, t->org + t->fr.p0); + } else { + if (t->org + t->fr.nchars == t->file->b.nc) + return; + q0 = t->org + frcharofpt( + &t->fr, + Pt(t->fr.r.min.x, t->fr.r.min.y + dl * t->fr.font->height)); + if (selectq > t->org + t->fr.p1) + textsetselect(t, t->org + t->fr.p1, selectq); + else + textsetselect(t, selectq, t->org + t->fr.p1); + } + textsetorigin(t, q0, TRUE); } - -void -textselect(Text *t) -{ - uint q0, q1; - int b, x, y; - int state; - enum { None, Cut, Paste }; +void textselect(Text* t) { + uint q0, q1; + int b, x, y; + int state; + enum { None, Cut, Paste }; - selecttext = t; - /* - * To have double-clicking and chording, we double-click - * immediately if it might make sense. - */ - b = mouse->buttons; - q0 = t->q0; - q1 = t->q1; - selectq = t->org+frcharofpt(&t->fr, mouse->xy); - if(clicktext==t && mouse->msec-clickmsec<500) - if(q0==q1 && selectq==q0){ - textdoubleclick(t, &q0, &q1); - textsetselect(t, q0, q1); - flushimage(display, 1); - x = mouse->xy.x; - y = mouse->xy.y; - /* stay here until something interesting happens */ - do - readmouse(mousectl); - while(mouse->buttons==b && abs(mouse->xy.x-x)<3 && abs(mouse->xy.y-y)<3); - mouse->xy.x = x; /* in case we're calling frselect */ - mouse->xy.y = y; - q0 = t->q0; /* may have changed */ - q1 = t->q1; - selectq = q0; - } - if(mouse->buttons == b){ - t->fr.scroll = framescroll; - frselect(&t->fr, mousectl); - /* horrible botch: while asleep, may have lost selection altogether */ - if(selectq > t->file->b.nc) - selectq = t->org + t->fr.p0; - t->fr.scroll = nil; - if(selectq < t->org) - q0 = selectq; - else - q0 = t->org + t->fr.p0; - if(selectq > t->org+t->fr.nchars) - q1 = selectq; - else - q1 = t->org+t->fr.p1; - } - if(q0 == q1){ - if(q0==t->q0 && clicktext==t && mouse->msec-clickmsec<500){ - textdoubleclick(t, &q0, &q1); - clicktext = nil; - }else{ - clicktext = t; - clickmsec = mouse->msec; - } - }else - clicktext = nil; - textsetselect(t, q0, q1); - flushimage(display, 1); - state = None; /* what we've done; undo when possible */ - while(mouse->buttons){ - mouse->msec = 0; - b = mouse->buttons; - if((b&1) && (b&6)){ - if(state==None && t->what==Body){ - seq++; - filemark(t->w->body.file); - } - if(b & 2){ - if(state==Paste && t->what==Body){ - winundo(t->w, TRUE); - textsetselect(t, q0, t->q1); - state = None; - }else if(state != Cut){ - cut(t, t, nil, TRUE, TRUE, nil, 0); - state = Cut; - } - }else{ - if(state==Cut && t->what==Body){ - winundo(t->w, TRUE); - textsetselect(t, q0, t->q1); - state = None; - }else if(state != Paste){ - paste(t, t, nil, TRUE, FALSE, nil, 0); - state = Paste; - } - } - textscrdraw(t); - clearmouse(); - } - flushimage(display, 1); - while(mouse->buttons == b) - readmouse(mousectl); - clicktext = nil; - } + selecttext = t; + /* + * To have double-clicking and chording, we double-click + * immediately if it might make sense. + */ + b = mouse->buttons; + q0 = t->q0; + q1 = t->q1; + selectq = t->org + frcharofpt(&t->fr, mouse->xy); + if (clicktext == t && mouse->msec - clickmsec < 500) + if (q0 == q1 && selectq == q0) { + textdoubleclick(t, &q0, &q1); + textsetselect(t, q0, q1); + flushimage(display, 1); + x = mouse->xy.x; + y = mouse->xy.y; + /* stay here until something interesting happens */ + do + readmouse(mousectl); + while (mouse->buttons == b && abs(mouse->xy.x - x) < 3 && + abs(mouse->xy.y - y) < 3); + mouse->xy.x = x; /* in case we're calling frselect */ + mouse->xy.y = y; + q0 = t->q0; /* may have changed */ + q1 = t->q1; + selectq = q0; + } + if (mouse->buttons == b) { + t->fr.scroll = framescroll; + frselect(&t->fr, mousectl); + /* horrible botch: while asleep, may have lost selection altogether */ + if (selectq > t->file->b.nc) + selectq = t->org + t->fr.p0; + t->fr.scroll = nil; + if (selectq < t->org) + q0 = selectq; + else + q0 = t->org + t->fr.p0; + if (selectq > t->org + t->fr.nchars) + q1 = selectq; + else + q1 = t->org + t->fr.p1; + } + if (q0 == q1) { + if (q0 == t->q0 && clicktext == t && mouse->msec - clickmsec < 500) { + textdoubleclick(t, &q0, &q1); + clicktext = nil; + } else { + clicktext = t; + clickmsec = mouse->msec; + } + } else + clicktext = nil; + textsetselect(t, q0, q1); + flushimage(display, 1); + state = None; /* what we've done; undo when possible */ + while (mouse->buttons) { + mouse->msec = 0; + b = mouse->buttons; + if ((b & 1) && (b & 6)) { + if (state == None && t->what == Body) { + seq++; + filemark(t->w->body.file); + } + if (b & 2) { + if (state == Paste && t->what == Body) { + winundo(t->w, TRUE); + textsetselect(t, q0, t->q1); + state = None; + } else if (state != Cut) { + cut(t, t, nil, TRUE, TRUE, nil, 0); + state = Cut; + } + } else { + if (state == Cut && t->what == Body) { + winundo(t->w, TRUE); + textsetselect(t, q0, t->q1); + state = None; + } else if (state != Paste) { + paste(t, t, nil, TRUE, FALSE, nil, 0); + state = Paste; + } + } + textscrdraw(t); + clearmouse(); + } + flushimage(display, 1); + while (mouse->buttons == b) + readmouse(mousectl); + clicktext = nil; + } } -void -textshow(Text *t, uint q0, uint q1, int doselect) -{ - int qe; - int nl; - int tsd; - int nc; - uint q; +void textshow(Text* t, uint q0, uint q1, int doselect) { + int qe; + int nl; + int tsd; + int nc; + uint q; - if(t->what != Body){ - if(doselect) - textsetselect(t, q0, q1); - return; - } - if(t->w!=nil && t->fr.maxlines==0) - colgrow(t->col, t->w, 1); - if(doselect) - textsetselect(t, q0, q1); - qe = t->org+t->fr.nchars; - tsd = FALSE; /* do we call textscrdraw? */ - nc = t->file->b.nc+t->ncache; - if(t->org <= q0){ - if(nc==0 || q0<qe) - tsd = TRUE; - else if(q0==qe && qe==nc){ - if(textreadc(t, nc-1) == '\n'){ - if(t->fr.nlines<t->fr.maxlines) - tsd = TRUE; - }else - tsd = TRUE; - } - } - if(tsd) - textscrdraw(t); - else{ - if(t->w->nopen[QWevent] > 0) - nl = 3*t->fr.maxlines/4; - else - nl = t->fr.maxlines/4; - q = textbacknl(t, q0, nl); - /* avoid going backwards if trying to go forwards - long lines! */ - if(!(q0>t->org && q<t->org)) - textsetorigin(t, q, TRUE); - while(q0 > t->org+t->fr.nchars) - textsetorigin(t, t->org+1, FALSE); - } + if (t->what != Body) { + if (doselect) + textsetselect(t, q0, q1); + return; + } + if (t->w != nil && t->fr.maxlines == 0) + colgrow(t->col, t->w, 1); + if (doselect) + textsetselect(t, q0, q1); + qe = t->org + t->fr.nchars; + tsd = FALSE; /* do we call textscrdraw? */ + nc = t->file->b.nc + t->ncache; + if (t->org <= q0) { + if (nc == 0 || q0 < qe) + tsd = TRUE; + else if (q0 == qe && qe == nc) { + if (textreadc(t, nc - 1) == '\n') { + if (t->fr.nlines < t->fr.maxlines) + tsd = TRUE; + } else + tsd = TRUE; + } + } + if (tsd) + textscrdraw(t); + else { + if (t->w->nopen[QWevent] > 0) + nl = 3 * t->fr.maxlines / 4; + else + nl = t->fr.maxlines / 4; + q = textbacknl(t, q0, nl); + /* avoid going backwards if trying to go forwards - long lines! */ + if (!(q0 > t->org && q < t->org)) + textsetorigin(t, q, TRUE); + while (q0 > t->org + t->fr.nchars) + textsetorigin(t, t->org + 1, FALSE); + } } -static -int -region(int a, int b) -{ - if(a < b) - return -1; - if(a == b) - return 0; - return 1; +static int region(int a, int b) { + if (a < b) + return -1; + if (a == b) + return 0; + return 1; } -void -selrestore(Frame *f, Point pt0, uint p0, uint p1) -{ - if(p1<=f->p0 || p0>=f->p1){ - /* no overlap */ - frdrawsel0(f, pt0, p0, p1, f->cols[BACK], f->cols[TEXT]); - return; - } - if(p0>=f->p0 && p1<=f->p1){ - /* entirely inside */ - frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]); - return; - } +void selrestore(Frame* f, Point pt0, uint p0, uint p1) { + if (p1 <= f->p0 || p0 >= f->p1) { + /* no overlap */ + frdrawsel0(f, pt0, p0, p1, f->cols[BACK], f->cols[TEXT]); + return; + } + if (p0 >= f->p0 && p1 <= f->p1) { + /* entirely inside */ + frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]); + return; + } - /* they now are known to overlap */ + /* they now are known to overlap */ - /* before selection */ - if(p0 < f->p0){ - frdrawsel0(f, pt0, p0, f->p0, f->cols[BACK], f->cols[TEXT]); - p0 = f->p0; - pt0 = frptofchar(f, p0); - } - /* after selection */ - if(p1 > f->p1){ - frdrawsel0(f, frptofchar(f, f->p1), f->p1, p1, f->cols[BACK], f->cols[TEXT]); - p1 = f->p1; - } - /* inside selection */ - frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]); + /* before selection */ + if (p0 < f->p0) { + frdrawsel0(f, pt0, p0, f->p0, f->cols[BACK], f->cols[TEXT]); + p0 = f->p0; + pt0 = frptofchar(f, p0); + } + /* after selection */ + if (p1 > f->p1) { + frdrawsel0( + f, + frptofchar(f, f->p1), + f->p1, + p1, + f->cols[BACK], + f->cols[TEXT]); + p1 = f->p1; + } + /* inside selection */ + frdrawsel0(f, pt0, p0, p1, f->cols[HIGH], f->cols[HTEXT]); } -void -textsetselect(Text *t, uint q0, uint q1) -{ - int p0, p1, ticked; +void textsetselect(Text* t, uint q0, uint q1) { + int p0, p1, ticked; - /* t->fr.p0 and t->fr.p1 are always right; t->q0 and t->q1 may be off */ - t->q0 = q0; - t->q1 = q1; - /* compute desired p0,p1 from q0,q1 */ - p0 = q0-t->org; - p1 = q1-t->org; - ticked = 1; - if(p0 < 0){ - ticked = 0; - p0 = 0; - } - if(p1 < 0) - p1 = 0; - if(p0 > t->fr.nchars) - p0 = t->fr.nchars; - if(p1 > t->fr.nchars){ - ticked = 0; - p1 = t->fr.nchars; - } - if(p0==t->fr.p0 && p1==t->fr.p1){ - if(p0 == p1 && ticked != t->fr.ticked) - frtick(&t->fr, frptofchar(&t->fr, p0), ticked); - return; - } - if(p0 > p1) - sysfatal("acme: textsetselect p0=%d p1=%d q0=%ud q1=%ud t->org=%d nchars=%d", p0, p1, q0, q1, (int)t->org, (int)t->fr.nchars); - /* screen disagrees with desired selection */ - if(t->fr.p1<=p0 || p1<=t->fr.p0 || p0==p1 || t->fr.p1==t->fr.p0){ - /* no overlap or too easy to bother trying */ - frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p0), t->fr.p0, t->fr.p1, 0); - if(p0 != p1 || ticked) - frdrawsel(&t->fr, frptofchar(&t->fr, p0), p0, p1, 1); - goto Return; - } - /* overlap; avoid unnecessary painting */ - if(p0 < t->fr.p0){ - /* extend selection backwards */ - frdrawsel(&t->fr, frptofchar(&t->fr, p0), p0, t->fr.p0, 1); - }else if(p0 > t->fr.p0){ - /* trim first part of selection */ - frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p0), t->fr.p0, p0, 0); - } - if(p1 > t->fr.p1){ - /* extend selection forwards */ - frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p1), t->fr.p1, p1, 1); - }else if(p1 < t->fr.p1){ - /* trim last part of selection */ - frdrawsel(&t->fr, frptofchar(&t->fr, p1), p1, t->fr.p1, 0); - } + /* t->fr.p0 and t->fr.p1 are always right; t->q0 and t->q1 may be off */ + t->q0 = q0; + t->q1 = q1; + /* compute desired p0,p1 from q0,q1 */ + p0 = q0 - t->org; + p1 = q1 - t->org; + ticked = 1; + if (p0 < 0) { + ticked = 0; + p0 = 0; + } + if (p1 < 0) + p1 = 0; + if (p0 > t->fr.nchars) + p0 = t->fr.nchars; + if (p1 > t->fr.nchars) { + ticked = 0; + p1 = t->fr.nchars; + } + if (p0 == t->fr.p0 && p1 == t->fr.p1) { + if (p0 == p1 && ticked != t->fr.ticked) + frtick(&t->fr, frptofchar(&t->fr, p0), ticked); + return; + } + if (p0 > p1) + sysfatal( + "acme: textsetselect p0=%d p1=%d q0=%ud q1=%ud t->org=%d nchars=%d", + p0, + p1, + q0, + q1, + (int)t->org, + (int)t->fr.nchars); + /* screen disagrees with desired selection */ + if (t->fr.p1 <= p0 || p1 <= t->fr.p0 || p0 == p1 || t->fr.p1 == t->fr.p0) { + /* no overlap or too easy to bother trying */ + frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p0), t->fr.p0, t->fr.p1, 0); + if (p0 != p1 || ticked) + frdrawsel(&t->fr, frptofchar(&t->fr, p0), p0, p1, 1); + goto Return; + } + /* overlap; avoid unnecessary painting */ + if (p0 < t->fr.p0) { + /* extend selection backwards */ + frdrawsel(&t->fr, frptofchar(&t->fr, p0), p0, t->fr.p0, 1); + } else if (p0 > t->fr.p0) { + /* trim first part of selection */ + frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p0), t->fr.p0, p0, 0); + } + if (p1 > t->fr.p1) { + /* extend selection forwards */ + frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p1), t->fr.p1, p1, 1); + } else if (p1 < t->fr.p1) { + /* trim last part of selection */ + frdrawsel(&t->fr, frptofchar(&t->fr, p1), p1, t->fr.p1, 0); + } - Return: - t->fr.p0 = p0; - t->fr.p1 = p1; +Return: + t->fr.p0 = p0; + t->fr.p1 = p1; } /* * Release the button in less than DELAY ms and it's considered a null selection * if the mouse hardly moved, regardless of whether it crossed a char boundary. */ -enum { - DELAY = 2, - MINMOVE = 4 -}; +enum { DELAY = 2, MINMOVE = 4 }; -uint -xselect(Frame *f, Mousectl *mc, Image *col, uint *p1p) /* when called, button is down */ +uint xselect( + Frame* f, Mousectl* mc, Image* col, + uint* p1p) /* when called, button is down */ { - uint p0, p1, q, tmp; - ulong msec; - Point mp, pt0, pt1, qt; - int reg, b; + uint p0, p1, q, tmp; + ulong msec; + Point mp, pt0, pt1, qt; + int reg, b; - mp = mc->m.xy; - b = mc->m.buttons; - msec = mc->m.msec; + mp = mc->m.xy; + b = mc->m.buttons; + msec = mc->m.msec; - /* remove tick */ - if(f->p0 == f->p1) - frtick(f, frptofchar(f, f->p0), 0); - p0 = p1 = frcharofpt(f, mp); - pt0 = frptofchar(f, p0); - pt1 = frptofchar(f, p1); - reg = 0; - frtick(f, pt0, 1); - do{ - q = frcharofpt(f, mc->m.xy); - if(p1 != q){ - if(p0 == p1) - frtick(f, pt0, 0); - if(reg != region(q, p0)){ /* crossed starting point; reset */ - if(reg > 0) - selrestore(f, pt0, p0, p1); - else if(reg < 0) - selrestore(f, pt1, p1, p0); - p1 = p0; - pt1 = pt0; - reg = region(q, p0); - if(reg == 0) - frdrawsel0(f, pt0, p0, p1, col, display->white); - } - qt = frptofchar(f, q); - if(reg > 0){ - if(q > p1) - frdrawsel0(f, pt1, p1, q, col, display->white); + /* remove tick */ + if (f->p0 == f->p1) + frtick(f, frptofchar(f, f->p0), 0); + p0 = p1 = frcharofpt(f, mp); + pt0 = frptofchar(f, p0); + pt1 = frptofchar(f, p1); + reg = 0; + frtick(f, pt0, 1); + do { + q = frcharofpt(f, mc->m.xy); + if (p1 != q) { + if (p0 == p1) + frtick(f, pt0, 0); + if (reg != region(q, p0)) { /* crossed starting point; reset */ + if (reg > 0) + selrestore(f, pt0, p0, p1); + else if (reg < 0) + selrestore(f, pt1, p1, p0); + p1 = p0; + pt1 = pt0; + reg = region(q, p0); + if (reg == 0) + frdrawsel0(f, pt0, p0, p1, col, display->white); + } + qt = frptofchar(f, q); + if (reg > 0) { + if (q > p1) + frdrawsel0(f, pt1, p1, q, col, display->white); - else if(q < p1) - selrestore(f, qt, q, p1); - }else if(reg < 0){ - if(q > p1) - selrestore(f, pt1, p1, q); - else - frdrawsel0(f, qt, q, p1, col, display->white); - } - p1 = q; - pt1 = qt; - } - if(p0 == p1) - frtick(f, pt0, 1); - flushimage(f->display, 1); - readmouse(mc); - }while(mc->m.buttons == b); - if(mc->m.msec-msec < DELAY && p0!=p1 - && abs(mp.x-mc->m.xy.x)<MINMOVE - && abs(mp.y-mc->m.xy.y)<MINMOVE) { - if(reg > 0) - selrestore(f, pt0, p0, p1); - else if(reg < 0) - selrestore(f, pt1, p1, p0); - p1 = p0; - } - if(p1 < p0){ - tmp = p0; - p0 = p1; - p1 = tmp; - } - pt0 = frptofchar(f, p0); - if(p0 == p1) - frtick(f, pt0, 0); - selrestore(f, pt0, p0, p1); - /* restore tick */ - if(f->p0 == f->p1) - frtick(f, frptofchar(f, f->p0), 1); - flushimage(f->display, 1); - *p1p = p1; - return p0; + else if (q < p1) + selrestore(f, qt, q, p1); + } else if (reg < 0) { + if (q > p1) + selrestore(f, pt1, p1, q); + else + frdrawsel0(f, qt, q, p1, col, display->white); + } + p1 = q; + pt1 = qt; + } + if (p0 == p1) + frtick(f, pt0, 1); + flushimage(f->display, 1); + readmouse(mc); + } while (mc->m.buttons == b); + if ( + mc->m.msec - msec < DELAY && p0 != p1 && abs(mp.x - mc->m.xy.x) < MINMOVE && + abs(mp.y - mc->m.xy.y) < MINMOVE) { + if (reg > 0) + selrestore(f, pt0, p0, p1); + else if (reg < 0) + selrestore(f, pt1, p1, p0); + p1 = p0; + } + if (p1 < p0) { + tmp = p0; + p0 = p1; + p1 = tmp; + } + pt0 = frptofchar(f, p0); + if (p0 == p1) + frtick(f, pt0, 0); + selrestore(f, pt0, p0, p1); + /* restore tick */ + if (f->p0 == f->p1) + frtick(f, frptofchar(f, f->p0), 1); + flushimage(f->display, 1); + *p1p = p1; + return p0; } -int -textselect23(Text *t, uint *q0, uint *q1, Image *high, int mask) -{ - uint p0, p1; - int buts; +int textselect23(Text* t, uint* q0, uint* q1, Image* high, int mask) { + uint p0, p1; + int buts; - p0 = xselect(&t->fr, mousectl, high, &p1); - buts = mousectl->m.buttons; - if((buts & mask) == 0){ - *q0 = p0+t->org; - *q1 = p1+t->org; - } + p0 = xselect(&t->fr, mousectl, high, &p1); + buts = mousectl->m.buttons; + if ((buts & mask) == 0) { + *q0 = p0 + t->org; + *q1 = p1 + t->org; + } - while(mousectl->m.buttons) - readmouse(mousectl); - return buts; + while (mousectl->m.buttons) + readmouse(mousectl); + return buts; } -int -textselect2(Text *t, uint *q0, uint *q1, Text **tp) -{ - int buts; +int textselect2(Text* t, uint* q0, uint* q1, Text** tp) { + int buts; - *tp = nil; - buts = textselect23(t, q0, q1, but2col, 4); - if(buts & 4) - return 0; - if(buts & 1){ /* pick up argument */ - *tp = argtext; - return 1; - } - return 1; + *tp = nil; + buts = textselect23(t, q0, q1, but2col, 4); + if (buts & 4) + return 0; + if (buts & 1) { /* pick up argument */ + *tp = argtext; + return 1; + } + return 1; } -int -textselect3(Text *t, uint *q0, uint *q1) -{ - int h; +int textselect3(Text* t, uint* q0, uint* q1) { + int h; - h = (textselect23(t, q0, q1, but3col, 1|2) == 0); - return h; + h = (textselect23(t, q0, q1, but3col, 1 | 2) == 0); + return h; } -static Rune left1[] = { '{', '[', '(', '<', 0xab, 0 }; -static Rune right1[] = { '}', ']', ')', '>', 0xbb, 0 }; -static Rune left2[] = { '\n', 0 }; -static Rune left3[] = { '\'', '"', '`', 0 }; +static Rune left1[] = {'{', '[', '(', '<', 0xab, 0}; +static Rune right1[] = {'}', ']', ')', '>', 0xbb, 0}; +static Rune left2[] = {'\n', 0}; +static Rune left3[] = {'\'', '"', '`', 0}; -static -Rune *left[] = { - left1, - left2, - left3, - nil -}; -static -Rune *right[] = { - right1, - left2, - left3, - nil -}; +static Rune* left[] = {left1, left2, left3, nil}; +static Rune* right[] = {right1, left2, left3, nil}; -void -textdoubleclick(Text *t, uint *q0, uint *q1) -{ - int c, i; - Rune *r, *l, *p; - uint q; +void textdoubleclick(Text* t, uint* q0, uint* q1) { + int c, i; + Rune *r, *l, *p; + uint q; - if(textclickhtmlmatch(t, q0, q1)) - return; + if (textclickhtmlmatch(t, q0, q1)) + return; - for(i=0; left[i]!=nil; i++){ - q = *q0; - l = left[i]; - r = right[i]; - /* try matching character to left, looking right */ - if(q == 0) - c = '\n'; - else - c = textreadc(t, q-1); - p = runestrchr(l, c); - if(p != nil){ - if(textclickmatch(t, c, r[p-l], 1, &q)) - *q1 = q-(c!='\n'); - return; - } - /* try matching character to right, looking left */ - if(q == t->file->b.nc) - c = '\n'; - else - c = textreadc(t, q); - p = runestrchr(r, c); - if(p != nil){ - if(textclickmatch(t, c, l[p-r], -1, &q)){ - *q1 = *q0+(*q0<t->file->b.nc && c=='\n'); - *q0 = q; - if(c!='\n' || q!=0 || textreadc(t, 0)=='\n') - (*q0)++; - } - return; - } - } + for (i = 0; left[i] != nil; i++) { + q = *q0; + l = left[i]; + r = right[i]; + /* try matching character to left, looking right */ + if (q == 0) + c = '\n'; + else + c = textreadc(t, q - 1); + p = runestrchr(l, c); + if (p != nil) { + if (textclickmatch(t, c, r[p - l], 1, &q)) + *q1 = q - (c != '\n'); + return; + } + /* try matching character to right, looking left */ + if (q == t->file->b.nc) + c = '\n'; + else + c = textreadc(t, q); + p = runestrchr(r, c); + if (p != nil) { + if (textclickmatch(t, c, l[p - r], -1, &q)) { + *q1 = *q0 + (*q0 < t->file->b.nc && c == '\n'); + *q0 = q; + if (c != '\n' || q != 0 || textreadc(t, 0) == '\n') + (*q0)++; + } + return; + } + } - /* try filling out word to right */ - while(*q1<t->file->b.nc && isalnum(textreadc(t, *q1))) - (*q1)++; - /* try filling out word to left */ - while(*q0>0 && isalnum(textreadc(t, *q0-1))) - (*q0)--; + /* try filling out word to right */ + while (*q1 < t->file->b.nc && isalnum(textreadc(t, *q1))) + (*q1)++; + /* try filling out word to left */ + while (*q0 > 0 && isalnum(textreadc(t, *q0 - 1))) + (*q0)--; } -int -textclickmatch(Text *t, int cl, int cr, int dir, uint *q) -{ - Rune c; - int nest; +int textclickmatch(Text* t, int cl, int cr, int dir, uint* q) { + Rune c; + int nest; - nest = 1; - for(;;){ - if(dir > 0){ - if(*q == t->file->b.nc) - break; - c = textreadc(t, *q); - (*q)++; - }else{ - if(*q == 0) - break; - (*q)--; - c = textreadc(t, *q); - } - if(c == cr){ - if(--nest==0) - return 1; - }else if(c == cl) - nest++; - } - return cl=='\n' && nest==1; + nest = 1; + for (;;) { + if (dir > 0) { + if (*q == t->file->b.nc) + break; + c = textreadc(t, *q); + (*q)++; + } else { + if (*q == 0) + break; + (*q)--; + c = textreadc(t, *q); + } + if (c == cr) { + if (--nest == 0) + return 1; + } else if (c == cl) + nest++; + } + return cl == '\n' && nest == 1; } // Is the text starting at location q an html tag? // Return 1 for <a>, -1 for </a>, 0 for no tag or <a />. // Set *q1, if non-nil, to the location after the tag. -static int -ishtmlstart(Text *t, uint q, uint *q1) -{ - int c, c1, c2; +static int ishtmlstart(Text* t, uint q, uint* q1) { + int c, c1, c2; - if(q+2 > t->file->b.nc) - return 0; - if(textreadc(t, q++) != '<') - return 0; - c = textreadc(t, q++); - c1 = c; - c2 = c; - while(c != '>') { - if(q >= t->file->b.nc) - return 0; - c2 = c; - c = textreadc(t, q++); - } - if(q1) - *q1 = q; - if(c1 == '/') // closing tag - return -1; - if(c2 == '/' || c2 == '!') // open + close tag or comment - return 0; - return 1; + if (q + 2 > t->file->b.nc) + return 0; + if (textreadc(t, q++) != '<') + return 0; + c = textreadc(t, q++); + c1 = c; + c2 = c; + while (c != '>') { + if (q >= t->file->b.nc) + return 0; + c2 = c; + c = textreadc(t, q++); + } + if (q1) + *q1 = q; + if (c1 == '/') // closing tag + return -1; + if (c2 == '/' || c2 == '!') // open + close tag or comment + return 0; + return 1; } // Is the text ending at location q an html tag? // Return 1 for <a>, -1 for </a>, 0 for no tag or <a />. // Set *q0, if non-nil, to the start of the tag. -static int -ishtmlend(Text *t, uint q, uint *q0) -{ - int c, c1, c2; +static int ishtmlend(Text* t, uint q, uint* q0) { + int c, c1, c2; - if(q < 2) - return 0; - if(textreadc(t, --q) != '>') - return 0; - c = textreadc(t, --q); - c1 = c; - c2 = c; - while(c != '<') { - if(q == 0) - return 0; - c1 = c; - c = textreadc(t, --q); - } - if(q0) - *q0 = q; - if(c1 == '/') // closing tag - return -1; - if(c2 == '/' || c2 == '!') // open + close tag or comment - return 0; - return 1; + if (q < 2) + return 0; + if (textreadc(t, --q) != '>') + return 0; + c = textreadc(t, --q); + c1 = c; + c2 = c; + while (c != '<') { + if (q == 0) + return 0; + c1 = c; + c = textreadc(t, --q); + } + if (q0) + *q0 = q; + if (c1 == '/') // closing tag + return -1; + if (c2 == '/' || c2 == '!') // open + close tag or comment + return 0; + return 1; } -int -textclickhtmlmatch(Text *t, uint *q0, uint *q1) -{ - int depth, n; - uint q, nq; +int textclickhtmlmatch(Text* t, uint* q0, uint* q1) { + int depth, n; + uint q, nq; - q = *q0; - // after opening tag? scan forward for closing tag - if(ishtmlend(t, q, nil) == 1) { - depth = 1; - while(q < t->file->b.nc) { - n = ishtmlstart(t, q, &nq); - if(n != 0) { - depth += n; - if(depth == 0) { - *q1 = q; - return 1; - } - q = nq; - continue; - } - q++; - } - } + q = *q0; + // after opening tag? scan forward for closing tag + if (ishtmlend(t, q, nil) == 1) { + depth = 1; + while (q < t->file->b.nc) { + n = ishtmlstart(t, q, &nq); + if (n != 0) { + depth += n; + if (depth == 0) { + *q1 = q; + return 1; + } + q = nq; + continue; + } + q++; + } + } - // before closing tag? scan backward for opening tag - if(ishtmlstart(t, q, nil) == -1) { - depth = -1; - while(q > 0) { - n = ishtmlend(t, q, &nq); - if(n != 0) { - depth += n; - if(depth == 0) { - *q0 = q; - return 1; - } - q = nq; - continue; - } - q--; - } - } + // before closing tag? scan backward for opening tag + if (ishtmlstart(t, q, nil) == -1) { + depth = -1; + while (q > 0) { + n = ishtmlend(t, q, &nq); + if (n != 0) { + depth += n; + if (depth == 0) { + *q0 = q; + return 1; + } + q = nq; + continue; + } + q--; + } + } - return 0; + return 0; } -uint -textbacknl(Text *t, uint p, uint n) -{ - int i, j; +uint textbacknl(Text* t, uint p, uint n) { + int i, j; - /* look for start of this line if n==0 */ - if(n==0 && p>0 && textreadc(t, p-1)!='\n') - n = 1; - i = n; - while(i-->0 && p>0){ - --p; /* it's at a newline now; back over it */ - if(p == 0) - break; - /* at 128 chars, call it a line anyway */ - for(j=128; --j>0 && p>0; p--) - if(textreadc(t, p-1)=='\n') - break; - } - return p; + /* look for start of this line if n==0 */ + if (n == 0 && p > 0 && textreadc(t, p - 1) != '\n') + n = 1; + i = n; + while (i-- > 0 && p > 0) { + --p; /* it's at a newline now; back over it */ + if (p == 0) + break; + /* at 128 chars, call it a line anyway */ + for (j = 128; --j > 0 && p > 0; p--) + if (textreadc(t, p - 1) == '\n') + break; + } + return p; } -void -textsetorigin(Text *t, uint org, int exact) -{ - int i, a, fixup; - Rune *r; - uint n; +void textsetorigin(Text* t, uint org, int exact) { + int i, a, fixup; + Rune* r; + uint n; - if(org>0 && !exact && textreadc(t, org-1) != '\n'){ - /* org is an estimate of the char posn; find a newline */ - /* don't try harder than 256 chars */ - for(i=0; i<256 && org<t->file->b.nc; i++){ - if(textreadc(t, org) == '\n'){ - org++; - break; - } - org++; - } - } - a = org-t->org; - fixup = 0; - if(a>=0 && a<t->fr.nchars){ - frdelete(&t->fr, 0, a); - fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ - } - else if(a<0 && -a<t->fr.nchars){ - n = t->org - org; - r = runemalloc(n); - bufread(&t->file->b, org, r, n); - frinsert(&t->fr, r, r+n, 0); - free(r); - }else - frdelete(&t->fr, 0, t->fr.nchars); - t->org = org; - textfill(t); - textscrdraw(t); - textsetselect(t, t->q0, t->q1); - if(fixup && t->fr.p1 > t->fr.p0) - frdrawsel(&t->fr, frptofchar(&t->fr, t->fr.p1-1), t->fr.p1-1, t->fr.p1, 1); + if (org > 0 && !exact && textreadc(t, org - 1) != '\n') { + /* org is an estimate of the char posn; find a newline */ + /* don't try harder than 256 chars */ + for (i = 0; i < 256 && org < t->file->b.nc; i++) { + if (textreadc(t, org) == '\n') { + org++; + break; + } + org++; + } + } + a = org - t->org; + fixup = 0; + if (a >= 0 && a < t->fr.nchars) { + frdelete(&t->fr, 0, a); + fixup = 1; /* frdelete can leave end of last line in wrong selection mode; + it doesn't know what follows */ + } else if (a < 0 && -a < t->fr.nchars) { + n = t->org - org; + r = runemalloc(n); + bufread(&t->file->b, org, r, n); + frinsert(&t->fr, r, r + n, 0); + free(r); + } else + frdelete(&t->fr, 0, t->fr.nchars); + t->org = org; + textfill(t); + textscrdraw(t); + textsetselect(t, t->q0, t->q1); + if (fixup && t->fr.p1 > t->fr.p0) + frdrawsel( + &t->fr, + frptofchar(&t->fr, t->fr.p1 - 1), + t->fr.p1 - 1, + t->fr.p1, + 1); } -void -textreset(Text *t) -{ - t->file->seq = 0; - t->eq0 = ~0; - /* do t->delete(0, t->nc, TRUE) without building backup stuff */ - textsetselect(t, t->org, t->org); - frdelete(&t->fr, 0, t->fr.nchars); - t->org = 0; - t->q0 = 0; - t->q1 = 0; - filereset(t->file); - bufreset(&t->file->b); +void textreset(Text* t) { + t->file->seq = 0; + t->eq0 = ~0; + /* do t->delete(0, t->nc, TRUE) without building backup stuff */ + textsetselect(t, t->org, t->org); + frdelete(&t->fr, 0, t->fr.nchars); + t->org = 0; + t->q0 = 0; + t->q1 = 0; + filereset(t->file); + bufreset(&t->file->b); }
M time.ctime.c

@@ -12,113 +12,96 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -static Channel* ctimer; /* chan(Timer*)[100] */ -static Timer *timer; +static Channel* ctimer; /* chan(Timer*)[100] */ +static Timer* timer; -static -uint -msec(void) -{ - return nsec()/1000000; -} +static uint msec(void) { return nsec() / 1000000; } -void -timerstop(Timer *t) -{ - t->next = timer; - timer = t; +void timerstop(Timer* t) { + t->next = timer; + timer = t; } -void -timercancel(Timer *t) -{ - t->cancel = TRUE; -} +void timercancel(Timer* t) { t->cancel = TRUE; } -static -void -timerproc(void *v) -{ - int i, nt, na, dt, del; - Timer **t, *x; - uint old, new; +static void timerproc(void* v) { + int i, nt, na, dt, del; + Timer **t, *x; + uint old, new; - USED(v); - threadsetname("timerproc"); - rfork(RFFDG); - t = nil; - na = 0; - nt = 0; - old = msec(); - for(;;){ - sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not be noticeable */ - new = msec(); - dt = new-old; - old = new; - if(dt < 0) /* timer wrapped; go around, losing a tick */ - continue; - for(i=0; i<nt; i++){ - x = t[i]; - x->dt -= dt; - del = FALSE; - if(x->cancel){ - timerstop(x); - del = TRUE; - }else if(x->dt <= 0){ - /* - * avoid possible deadlock if client is - * now sending on ctimer - */ - if(nbsendul(x->c, 0) > 0) - del = TRUE; - } - if(del){ - memmove(&t[i], &t[i+1], (nt-i-1)*sizeof t[0]); - --nt; - --i; - } - } - if(nt == 0){ - x = recvp(ctimer); - gotit: - if(nt == na){ - na += 10; - t = realloc(t, na*sizeof(Timer*)); - if(t == nil) - error("timer realloc failed"); - } - t[nt++] = x; - old = msec(); - } - if(nbrecv(ctimer, &x) > 0) - goto gotit; - } + USED(v); + threadsetname("timerproc"); + rfork(RFFDG); + t = nil; + na = 0; + nt = 0; + old = msec(); + for (;;) { + sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not + be noticeable */ + new = msec(); + dt = new - old; + old = new; + if (dt < 0) /* timer wrapped; go around, losing a tick */ + continue; + for (i = 0; i < nt; i++) { + x = t[i]; + x->dt -= dt; + del = FALSE; + if (x->cancel) { + timerstop(x); + del = TRUE; + } else if (x->dt <= 0) { + /* + * avoid possible deadlock if client is + * now sending on ctimer + */ + if (nbsendul(x->c, 0) > 0) + del = TRUE; + } + if (del) { + memmove(&t[i], &t[i + 1], (nt - i - 1) * sizeof t[0]); + --nt; + --i; + } + } + if (nt == 0) { + x = recvp(ctimer); + gotit: + if (nt == na) { + na += 10; + t = realloc(t, na * sizeof(Timer*)); + if (t == nil) + error("timer realloc failed"); + } + t[nt++] = x; + old = msec(); + } + if (nbrecv(ctimer, &x) > 0) + goto gotit; + } } -void -timerinit(void) -{ - ctimer = chancreate(sizeof(Timer*), 100); - chansetname(ctimer, "ctimer"); - proccreate(timerproc, nil, STACK); +void timerinit(void) { + ctimer = chancreate(sizeof(Timer*), 100); + chansetname(ctimer, "ctimer"); + proccreate(timerproc, nil, STACK); } -Timer* -timerstart(int dt) -{ - Timer *t; +Timer* timerstart(int dt) { + Timer* t; - t = timer; - if(t) - timer = timer->next; - else{ - t = emalloc(sizeof(Timer)); - t->c = chancreate(sizeof(int), 0); - chansetname(t->c, "tc%p", t->c); - } - t->next = nil; - t->dt = dt; - t->cancel = FALSE; - sendp(ctimer, t); - return t; + t = timer; + if (t) + timer = timer->next; + else { + t = emalloc(sizeof(Timer)); + t->c = chancreate(sizeof(int), 0); + chansetname(t->c, "tc%p", t->c); + } + t->next = nil; + t->dt = dt; + t->cancel = FALSE; + sendp(ctimer, t); + return t; }
M util.cutil.c

@@ -12,124 +12,112 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -static Point prevmouse; -static Window *mousew; +static Point prevmouse; +static Window* mousew; -Range -range(int q0, int q1) -{ - Range r; +Range range(int q0, int q1) { + Range r; - r.q0 = q0; - r.q1 = q1; - return r; + r.q0 = q0; + r.q1 = q1; + return r; } -Runestr -runestr(Rune *r, uint n) -{ - Runestr rs; +Runestr runestr(Rune* r, uint n) { + Runestr rs; - rs.r = r; - rs.nr = n; - return rs; + rs.r = r; + rs.nr = n; + return rs; } -void -cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls) -{ - uchar *q; - Rune *s; - int j, w; +void cvttorunes(char* p, int n, Rune* r, int* nb, int* nr, int* nulls) { + uchar* q; + Rune* s; + int j, w; - /* - * Always guaranteed that n bytes may be interpreted - * without worrying about partial runes. This may mean - * reading up to UTFmax-1 more bytes than n; the caller - * knows this. If n is a firm limit, the caller should - * set p[n] = 0. - */ - q = (uchar*)p; - s = r; - for(j=0; j<n; j+=w){ - if(*q < Runeself){ - w = 1; - *s = *q++; - }else{ - w = chartorune(s, (char*)q); - q += w; - } - if(*s) - s++; - else if(nulls) - *nulls = TRUE; - } - *nb = (char*)q-p; - *nr = s-r; + /* + * Always guaranteed that n bytes may be interpreted + * without worrying about partial runes. This may mean + * reading up to UTFmax-1 more bytes than n; the caller + * knows this. If n is a firm limit, the caller should + * set p[n] = 0. + */ + q = (uchar*)p; + s = r; + for (j = 0; j < n; j += w) { + if (*q < Runeself) { + w = 1; + *s = *q++; + } else { + w = chartorune(s, (char*)q); + q += w; + } + if (*s) + s++; + else if (nulls) + *nulls = TRUE; + } + *nb = (char*)q - p; + *nr = s - r; } -void -error(char *s) -{ - fprint(2, "acme: %s: %r\n", s); - threadexitsall(nil); +void error(char* s) { + fprint(2, "acme: %s: %r\n", s); + threadexitsall(nil); } -Window* -errorwin1(Rune *dir, int ndir, Rune **incl, int nincl) -{ - Window *w; - Rune *r; - int i, n; - static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 }; +Window* errorwin1(Rune* dir, int ndir, Rune** incl, int nincl) { + Window* w; + Rune* r; + int i, n; + static Rune Lpluserrors[] = {'+', 'E', 'r', 'r', 'o', 'r', 's', 0}; - r = runemalloc(ndir+8); - if((n = ndir) != 0){ - runemove(r, dir, ndir); - r[n++] = L'/'; - } - runemove(r+n, Lpluserrors, 7); - n += 7; - w = lookfile(r, n); - if(w == nil){ - if(row.ncol == 0) - if(rowadd(&row, nil, -1) == nil) - error("can't create column to make error window"); - w = coladd(row.col[row.ncol-1], nil, nil, -1); - w->filemenu = FALSE; - winsetname(w, r, n); - xfidlog(w, "new"); - } - free(r); - for(i=nincl; --i>=0; ){ - n = runestrlen(incl[i]); - r = runemalloc(n); - runemove(r, incl[i], n); - winaddincl(w, r, n); - } - for(i=0; i<NINDENT; i++) - w->indent[i] = globalindent[i]; - return w; + r = runemalloc(ndir + 8); + if ((n = ndir) != 0) { + runemove(r, dir, ndir); + r[n++] = L'/'; + } + runemove(r + n, Lpluserrors, 7); + n += 7; + w = lookfile(r, n); + if (w == nil) { + if (row.ncol == 0) + if (rowadd(&row, nil, -1) == nil) + error("can't create column to make error window"); + w = coladd(row.col[row.ncol - 1], nil, nil, -1); + w->filemenu = FALSE; + winsetname(w, r, n); + xfidlog(w, "new"); + } + free(r); + for (i = nincl; --i >= 0;) { + n = runestrlen(incl[i]); + r = runemalloc(n); + runemove(r, incl[i], n); + winaddincl(w, r, n); + } + for (i = 0; i < NINDENT; i++) + w->indent[i] = globalindent[i]; + return w; } /* make new window, if necessary; return with it locked */ -Window* -errorwin(Mntdir *md, int owner) -{ - Window *w; +Window* errorwin(Mntdir* md, int owner) { + Window* w; - for(;;){ - if(md == nil) - w = errorwin1(nil, 0, nil, 0); - else - w = errorwin1(md->dir, md->ndir, md->incl, md->nincl); - winlock(w, owner); - if(w->col != nil) - break; - /* window was deleted too fast */ - winunlock(w); - } - return w; + for (;;) { + if (md == nil) + w = errorwin1(nil, 0, nil, 0); + else + w = errorwin1(md->dir, md->ndir, md->incl, md->nincl); + winlock(w, owner); + if (w->col != nil) + break; + /* window was deleted too fast */ + winunlock(w); + } + return w; } /*

@@ -137,360 +125,315 @@ * Incoming window should be locked.

* It will be unlocked and returned window * will be locked in its place. */ -Window* -errorwinforwin(Window *w) -{ - int i, n, nincl, owner; - Rune **incl; - Runestr dir; - Text *t; +Window* errorwinforwin(Window* w) { + int i, n, nincl, owner; + Rune** incl; + Runestr dir; + Text* t; - t = &w->body; - dir = dirname(t, nil, 0); - if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */ - free(dir.r); - dir.r = nil; - dir.nr = 0; - } - incl = nil; - nincl = w->nincl; - if(nincl > 0){ - incl = emalloc(nincl*sizeof(Rune*)); - for(i=0; i<nincl; i++){ - n = runestrlen(w->incl[i]); - incl[i] = runemalloc(n+1); - runemove(incl[i], w->incl[i], n); - } - } - owner = w->owner; - winunlock(w); - for(;;){ - w = errorwin1(dir.r, dir.nr, incl, nincl); - winlock(w, owner); - if(w->col != nil) - break; - /* window deleted too fast */ - winunlock(w); - } - return w; + t = &w->body; + dir = dirname(t, nil, 0); + if (dir.nr == 1 && dir.r[0] == '.') { /* sigh */ + free(dir.r); + dir.r = nil; + dir.nr = 0; + } + incl = nil; + nincl = w->nincl; + if (nincl > 0) { + incl = emalloc(nincl * sizeof(Rune*)); + for (i = 0; i < nincl; i++) { + n = runestrlen(w->incl[i]); + incl[i] = runemalloc(n + 1); + runemove(incl[i], w->incl[i], n); + } + } + owner = w->owner; + winunlock(w); + for (;;) { + w = errorwin1(dir.r, dir.nr, incl, nincl); + winlock(w, owner); + if (w->col != nil) + break; + /* window deleted too fast */ + winunlock(w); + } + return w; } typedef struct Warning Warning; -struct Warning{ - Mntdir *md; - Buffer buf; - Warning *next; +struct Warning { + Mntdir* md; + Buffer buf; + Warning* next; }; -static Warning *warnings; +static Warning* warnings; -static -void -addwarningtext(Mntdir *md, Rune *r, int nr) -{ - Warning *warn; +static void addwarningtext(Mntdir* md, Rune* r, int nr) { + Warning* warn; - for(warn = warnings; warn; warn=warn->next){ - if(warn->md == md){ - bufinsert(&warn->buf, warn->buf.nc, r, nr); - return; - } - } - warn = emalloc(sizeof(Warning)); - warn->next = warnings; - warn->md = md; - if(md) - fsysincid(md); - warnings = warn; - bufinsert(&warn->buf, 0, r, nr); - nbsendp(cwarn, 0); + for (warn = warnings; warn; warn = warn->next) { + if (warn->md == md) { + bufinsert(&warn->buf, warn->buf.nc, r, nr); + return; + } + } + warn = emalloc(sizeof(Warning)); + warn->next = warnings; + warn->md = md; + if (md) + fsysincid(md); + warnings = warn; + bufinsert(&warn->buf, 0, r, nr); + nbsendp(cwarn, 0); } /* called while row is locked */ -void -flushwarnings(void) -{ - Warning *warn, *next; - Window *w; - Text *t; - int owner, nr, q0, n; - Rune *r; +void flushwarnings(void) { + Warning *warn, *next; + Window* w; + Text* t; + int owner, nr, q0, n; + Rune* r; - for(warn=warnings; warn; warn=next) { - w = errorwin(warn->md, 'E'); - t = &w->body; - owner = w->owner; - if(owner == 0) - w->owner = 'E'; - wincommit(w, t); - /* - * Most commands don't generate much output. For instance, - * Edit ,>cat goes through /dev/cons and is already in blocks - * because of the i/o system, but a few can. Edit ,p will - * put the entire result into a single hunk. So it's worth doing - * this in blocks (and putting the text in a buffer in the first - * place), to avoid a big memory footprint. - */ - r = fbufalloc(); - q0 = t->file->b.nc; - for(n = 0; n < warn->buf.nc; n += nr){ - nr = warn->buf.nc - n; - if(nr > RBUFSIZE) - nr = RBUFSIZE; - bufread(&warn->buf, n, r, nr); - textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr); - } - textshow(t, q0, t->file->b.nc, 1); - free(r); - winsettag(t->w); - textscrdraw(t); - w->owner = owner; - w->dirty = FALSE; - winunlock(w); - bufclose(&warn->buf); - next = warn->next; - if(warn->md) - fsysdelid(warn->md); - free(warn); - } - warnings = nil; + for (warn = warnings; warn; warn = next) { + w = errorwin(warn->md, 'E'); + t = &w->body; + owner = w->owner; + if (owner == 0) + w->owner = 'E'; + wincommit(w, t); + /* + * Most commands don't generate much output. For instance, + * Edit ,>cat goes through /dev/cons and is already in blocks + * because of the i/o system, but a few can. Edit ,p will + * put the entire result into a single hunk. So it's worth doing + * this in blocks (and putting the text in a buffer in the first + * place), to avoid a big memory footprint. + */ + r = fbufalloc(); + q0 = t->file->b.nc; + for (n = 0; n < warn->buf.nc; n += nr) { + nr = warn->buf.nc - n; + if (nr > RBUFSIZE) + nr = RBUFSIZE; + bufread(&warn->buf, n, r, nr); + textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr); + } + textshow(t, q0, t->file->b.nc, 1); + free(r); + winsettag(t->w); + textscrdraw(t); + w->owner = owner; + w->dirty = FALSE; + winunlock(w); + bufclose(&warn->buf); + next = warn->next; + if (warn->md) + fsysdelid(warn->md); + free(warn); + } + warnings = nil; } -void -warning(Mntdir *md, char *s, ...) -{ - Rune *r; - va_list arg; +void warning(Mntdir* md, char* s, ...) { + Rune* r; + va_list arg; - va_start(arg, s); - r = runevsmprint(s, arg); - va_end(arg); - if(r == nil) - error("runevsmprint failed"); - addwarningtext(md, r, runestrlen(r)); - free(r); + va_start(arg, s); + r = runevsmprint(s, arg); + va_end(arg); + if (r == nil) + error("runevsmprint failed"); + addwarningtext(md, r, runestrlen(r)); + free(r); } -int -runeeq(Rune *s1, uint n1, Rune *s2, uint n2) -{ - if(n1 != n2) - return FALSE; - return memcmp(s1, s2, n1*sizeof(Rune)) == 0; +int runeeq(Rune* s1, uint n1, Rune* s2, uint n2) { + if (n1 != n2) + return FALSE; + return memcmp(s1, s2, n1 * sizeof(Rune)) == 0; } -uint -min(uint a, uint b) -{ - if(a < b) - return a; - return b; +uint min(uint a, uint b) { + if (a < b) + return a; + return b; } -uint -max(uint a, uint b) -{ - if(a > b) - return a; - return b; +uint max(uint a, uint b) { + if (a > b) + return a; + return b; } -char* -runetobyte(Rune *r, int n) -{ - char *s; +char* runetobyte(Rune* r, int n) { + char* s; - if(r == nil) - return nil; - s = emalloc(n*UTFmax+1); - setmalloctag(s, getcallerpc(&r)); - snprint(s, n*UTFmax+1, "%.*S", n, r); - return s; + if (r == nil) + return nil; + s = emalloc(n * UTFmax + 1); + setmalloctag(s, getcallerpc(&r)); + snprint(s, n * UTFmax + 1, "%.*S", n, r); + return s; } -Rune* -bytetorune(char *s, int *ip) -{ - Rune *r; - int nb, nr; +Rune* bytetorune(char* s, int* ip) { + Rune* r; + int nb, nr; - nb = strlen(s); - r = runemalloc(nb+1); - cvttorunes(s, nb, r, &nb, &nr, nil); - r[nr] = '\0'; - *ip = nr; - return r; + nb = strlen(s); + r = runemalloc(nb + 1); + cvttorunes(s, nb, r, &nb, &nr, nil); + r[nr] = '\0'; + *ip = nr; + return r; } -int -isalnum(Rune c) -{ - /* - * Hard to get absolutely right. Use what we know about ASCII - * and assume anything above the Latin control characters is - * potentially an alphanumeric. - */ - if(c <= ' ') - return FALSE; - if(0x7F<=c && c<=0xA0) - return FALSE; - if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) - return FALSE; - return TRUE; +int isalnum(Rune c) { + /* + * Hard to get absolutely right. Use what we know about ASCII + * and assume anything above the Latin control characters is + * potentially an alphanumeric. + */ + if (c <= ' ') + return FALSE; + if (0x7F <= c && c <= 0xA0) + return FALSE; + if (utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c)) + return FALSE; + return TRUE; } -int -rgetc(void *v, uint n) -{ - return ((Rune*)v)[n]; -} +int rgetc(void* v, uint n) { return ((Rune*)v)[n]; } -int -tgetc(void *a, uint n) -{ - Text *t; +int tgetc(void* a, uint n) { + Text* t; - t = a; - if(n >= t->file->b.nc) - return 0; - return textreadc(t, n); + t = a; + if (n >= t->file->b.nc) + return 0; + return textreadc(t, n); } -Rune* -skipbl(Rune *r, int n, int *np) -{ - while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){ - --n; - r++; - } - *np = n; - return r; +Rune* skipbl(Rune* r, int n, int* np) { + while (n > 0 && (*r == ' ' || *r == '\t' || *r == '\n')) { + --n; + r++; + } + *np = n; + return r; } -Rune* -findbl(Rune *r, int n, int *np) -{ - while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){ - --n; - r++; - } - *np = n; - return r; +Rune* findbl(Rune* r, int n, int* np) { + while (n > 0 && *r != ' ' && *r != '\t' && *r != '\n') { + --n; + r++; + } + *np = n; + return r; } -void -savemouse(Window *w) -{ - prevmouse = mouse->xy; - mousew = w; +void savemouse(Window* w) { + prevmouse = mouse->xy; + mousew = w; } -int -restoremouse(Window *w) -{ - int did; +int restoremouse(Window* w) { + int did; - did = 0; - if(mousew!=nil && mousew==w) { - moveto(mousectl, prevmouse); - did = 1; - } - mousew = nil; - return did; + did = 0; + if (mousew != nil && mousew == w) { + moveto(mousectl, prevmouse); + did = 1; + } + mousew = nil; + return did; } -void -clearmouse() -{ - mousew = nil; -} +void clearmouse() { mousew = nil; } -char* -estrdup(char *s) -{ - char *t; +char* estrdup(char* s) { + char* t; - t = strdup(s); - if(t == nil) - error("strdup failed"); - setmalloctag(t, getcallerpc(&s)); - return t; + t = strdup(s); + if (t == nil) + error("strdup failed"); + setmalloctag(t, getcallerpc(&s)); + return t; } -void* -emalloc(uint n) -{ - void *p; +void* emalloc(uint n) { + void* p; - p = malloc(n); - if(p == nil) - error("malloc failed"); - setmalloctag(p, getcallerpc(&n)); - memset(p, 0, n); - return p; + p = malloc(n); + if (p == nil) + error("malloc failed"); + setmalloctag(p, getcallerpc(&n)); + memset(p, 0, n); + return p; } -void* -erealloc(void *p, uint n) -{ - p = realloc(p, n); - if(p == nil) - error("realloc failed"); - setmalloctag(p, getcallerpc(&n)); - return p; +void* erealloc(void* p, uint n) { + p = realloc(p, n); + if (p == nil) + error("realloc failed"); + setmalloctag(p, getcallerpc(&n)); + return p; } /* * Heuristic city. */ -Window* -makenewwindow(Text *t) -{ - Column *c; - Window *w, *bigw, *emptyw; - Text *emptyb; - int i, y, el; +Window* makenewwindow(Text* t) { + Column* c; + Window *w, *bigw, *emptyw; + Text* emptyb; + int i, y, el; - if(activecol) - c = activecol; - else if(seltext && seltext->col) - c = seltext->col; - else if(t && t->col) - c = t->col; - else{ - if(row.ncol==0 && rowadd(&row, nil, -1)==nil) - error("can't make column"); - c = row.col[row.ncol-1]; - } - activecol = c; - if(t==nil || t->w==nil || c->nw==0) - return coladd(c, nil, nil, -1); + if (activecol) + c = activecol; + else if (seltext && seltext->col) + c = seltext->col; + else if (t && t->col) + c = t->col; + else { + if (row.ncol == 0 && rowadd(&row, nil, -1) == nil) + error("can't make column"); + c = row.col[row.ncol - 1]; + } + activecol = c; + if (t == nil || t->w == nil || c->nw == 0) + return coladd(c, nil, nil, -1); - /* find biggest window and biggest blank spot */ - emptyw = c->w[0]; - bigw = emptyw; - for(i=1; i<c->nw; i++){ - w = c->w[i]; - /* use >= to choose one near bottom of screen */ - if(w->body.fr.maxlines >= bigw->body.fr.maxlines) - bigw = w; - if(w->body.fr.maxlines-w->body.fr.nlines >= emptyw->body.fr.maxlines-emptyw->body.fr.nlines) - emptyw = w; - } - emptyb = &emptyw->body; - el = emptyb->fr.maxlines-emptyb->fr.nlines; - /* if empty space is big, use it */ - if(el>15 || (el>3 && el>(bigw->body.fr.maxlines-1)/2)) - y = emptyb->fr.r.min.y+emptyb->fr.nlines*font->height; - else{ - /* if this window is in column and isn't much smaller, split it */ - if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3) - bigw = t->w; - y = (bigw->r.min.y + bigw->r.max.y)/2; - } - w = coladd(c, nil, nil, y); - if(w->body.fr.maxlines < 2) - colgrow(w->col, w, 1); - return w; + /* find biggest window and biggest blank spot */ + emptyw = c->w[0]; + bigw = emptyw; + for (i = 1; i < c->nw; i++) { + w = c->w[i]; + /* use >= to choose one near bottom of screen */ + if (w->body.fr.maxlines >= bigw->body.fr.maxlines) + bigw = w; + if ( + w->body.fr.maxlines - w->body.fr.nlines >= + emptyw->body.fr.maxlines - emptyw->body.fr.nlines) + emptyw = w; + } + emptyb = &emptyw->body; + el = emptyb->fr.maxlines - emptyb->fr.nlines; + /* if empty space is big, use it */ + if (el > 15 || (el > 3 && el > (bigw->body.fr.maxlines - 1) / 2)) + y = emptyb->fr.r.min.y + emptyb->fr.nlines * font->height; + else { + /* if this window is in column and isn't much smaller, split it */ + if (t->col == c && Dy(t->w->r) > 2 * Dy(bigw->r) / 3) + bigw = t->w; + y = (bigw->r.min.y + bigw->r.max.y) / 2; + } + w = coladd(c, nil, nil, y); + if (w->body.fr.maxlines < 2) + colgrow(w->col, w, 1); + return w; }
M wind.cwind.c

@@ -12,699 +12,690 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -int winid; +int winid; -void -wininit(Window *w, Window *clone, Rectangle r) -{ - Rectangle r1, br; - File *f; - Reffont *rf; - Rune *rp; - int nc, i; +void wininit(Window* w, Window* clone, Rectangle r) { + Rectangle r1, br; + File* f; + Reffont* rf; + Rune* rp; + int nc, i; - w->tag.w = w; - w->taglines = 1; - w->tagexpand = TRUE; - w->body.w = w; - w->id = ++winid; - incref(&w->ref); - if(globalincref) - incref(&w->ref); - w->ctlfid = ~0; - w->utflastqid = -1; - r1 = r; + w->tag.w = w; + w->taglines = 1; + w->tagexpand = TRUE; + w->body.w = w; + w->id = ++winid; + incref(&w->ref); + if (globalincref) + incref(&w->ref); + w->ctlfid = ~0; + w->utflastqid = -1; + r1 = r; - w->tagtop = r; - w->tagtop.max.y = r.min.y + font->height; - r1.max.y = r1.min.y + w->taglines*font->height; + w->tagtop = r; + w->tagtop.max.y = r.min.y + font->height; + r1.max.y = r1.min.y + w->taglines * font->height; - incref(&reffont.ref); - f = fileaddtext(nil, &w->tag); - textinit(&w->tag, f, r1, &reffont, tagcols); - w->tag.what = Tag; - /* tag is a copy of the contents, not a tracked image */ - if(clone){ - textdelete(&w->tag, 0, w->tag.file->b.nc, TRUE); - nc = clone->tag.file->b.nc; - rp = runemalloc(nc); - bufread(&clone->tag.file->b, 0, rp, nc); - textinsert(&w->tag, 0, rp, nc, TRUE); - free(rp); - filereset(w->tag.file); - textsetselect(&w->tag, nc, nc); - } - r1 = r; - r1.min.y += w->taglines*font->height + 1; - if(r1.max.y < r1.min.y) - r1.max.y = r1.min.y; - f = nil; - if(clone){ - f = clone->body.file; - w->body.org = clone->body.org; - w->isscratch = clone->isscratch; - rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name); - }else - rf = rfget(FALSE, FALSE, FALSE, nil); - f = fileaddtext(f, &w->body); - w->body.what = Body; - textinit(&w->body, f, r1, rf, textcols); - r1.min.y -= 1; - r1.max.y = r1.min.y+1; - draw(screen, r1, tagcols[BORD], nil, ZP); - textscrdraw(&w->body); - w->r = r; - br.min = w->tag.scrollr.min; - br.max.x = br.min.x + Dx(button->r); - br.max.y = br.min.y + Dy(button->r); - draw(screen, br, button, nil, button->r.min); - w->filemenu = TRUE; - w->maxlines = w->body.fr.maxlines; - for(i=0; i<NINDENT; i++) - w->indent[i] = globalindent[i]; - if(clone){ - w->dirty = clone->dirty; - for(i=0; i<NINDENT; i++) - w->indent[i] = clone->indent[i]; - textsetselect(&w->body, clone->body.q0, clone->body.q1); - winsettag(w); - } + incref(&reffont.ref); + f = fileaddtext(nil, &w->tag); + textinit(&w->tag, f, r1, &reffont, tagcols); + w->tag.what = Tag; + /* tag is a copy of the contents, not a tracked image */ + if (clone) { + textdelete(&w->tag, 0, w->tag.file->b.nc, TRUE); + nc = clone->tag.file->b.nc; + rp = runemalloc(nc); + bufread(&clone->tag.file->b, 0, rp, nc); + textinsert(&w->tag, 0, rp, nc, TRUE); + free(rp); + filereset(w->tag.file); + textsetselect(&w->tag, nc, nc); + } + r1 = r; + r1.min.y += w->taglines * font->height + 1; + if (r1.max.y < r1.min.y) + r1.max.y = r1.min.y; + f = nil; + if (clone) { + f = clone->body.file; + w->body.org = clone->body.org; + w->isscratch = clone->isscratch; + rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name); + } else + rf = rfget(FALSE, FALSE, FALSE, nil); + f = fileaddtext(f, &w->body); + w->body.what = Body; + textinit(&w->body, f, r1, rf, textcols); + r1.min.y -= 1; + r1.max.y = r1.min.y + 1; + draw(screen, r1, tagcols[BORD], nil, ZP); + textscrdraw(&w->body); + w->r = r; + br.min = w->tag.scrollr.min; + br.max.x = br.min.x + Dx(button->r); + br.max.y = br.min.y + Dy(button->r); + draw(screen, br, button, nil, button->r.min); + w->filemenu = TRUE; + w->maxlines = w->body.fr.maxlines; + for (i = 0; i < NINDENT; i++) + w->indent[i] = globalindent[i]; + if (clone) { + w->dirty = clone->dirty; + for (i = 0; i < NINDENT; i++) + w->indent[i] = clone->indent[i]; + textsetselect(&w->body, clone->body.q0, clone->body.q1); + winsettag(w); + } } /* * Draw the appropriate button. */ -void -windrawbutton(Window *w) -{ - Image *b; - Rectangle br; +void windrawbutton(Window* w) { + Image* b; + Rectangle br; - b = button; - if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache)) - b = modbutton; - br.min = w->tag.scrollr.min; - br.max.x = br.min.x + Dx(b->r); - br.max.y = br.min.y + Dy(b->r); - draw(screen, br, b, nil, b->r.min); + b = button; + if (!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache)) + b = modbutton; + br.min = w->tag.scrollr.min; + br.max.x = br.min.x + Dx(b->r); + br.max.y = br.min.y + Dy(b->r); + draw(screen, br, b, nil, b->r.min); } -int -delrunepos(Window *w) -{ - int n; - Rune rune; +int delrunepos(Window* w) { + int n; + Rune rune; - for(n=0; n<w->tag.file->b.nc; n++) { - bufread(&w->tag.file->b, n, &rune, 1); - if(rune == ' ') - break; - } - n += 2; - if(n >= w->tag.file->b.nc) - return -1; - return n; + for (n = 0; n < w->tag.file->b.nc; n++) { + bufread(&w->tag.file->b, n, &rune, 1); + if (rune == ' ') + break; + } + n += 2; + if (n >= w->tag.file->b.nc) + return -1; + return n; } -void -movetodel(Window *w) -{ - int n; +void movetodel(Window* w) { + int n; - n = delrunepos(w); - if(n < 0) - return; - moveto(mousectl, addpt(frptofchar(&w->tag.fr, n), Pt(4, w->tag.fr.font->height-4))); + n = delrunepos(w); + if (n < 0) + return; + moveto( + mousectl, + addpt(frptofchar(&w->tag.fr, n), Pt(4, w->tag.fr.font->height - 4))); } /* * Compute number of tag lines required * to display entire tag text. */ -int -wintaglines(Window *w, Rectangle r) -{ - int n; - Rune rune; - Point p; +int wintaglines(Window* w, Rectangle r) { + int n; + Rune rune; + Point p; - if(!w->tagexpand && !w->showdel) - return 1; - w->showdel = FALSE; - w->tag.fr.noredraw = 1; - textresize(&w->tag, r, TRUE); - w->tag.fr.noredraw = 0; - w->tagsafe = FALSE; + if (!w->tagexpand && !w->showdel) + return 1; + w->showdel = FALSE; + w->tag.fr.noredraw = 1; + textresize(&w->tag, r, TRUE); + w->tag.fr.noredraw = 0; + w->tagsafe = FALSE; - if(!w->tagexpand) { - /* use just as many lines as needed to show the Del */ - n = delrunepos(w); - if(n < 0) - return 1; - p = subpt(frptofchar(&w->tag.fr, n), w->tag.fr.r.min); - return 1 + p.y / w->tag.fr.font->height; - } + if (!w->tagexpand) { + /* use just as many lines as needed to show the Del */ + n = delrunepos(w); + if (n < 0) + return 1; + p = subpt(frptofchar(&w->tag.fr, n), w->tag.fr.r.min); + return 1 + p.y / w->tag.fr.font->height; + } - /* can't use more than we have */ - if(w->tag.fr.nlines >= w->tag.fr.maxlines) - return w->tag.fr.maxlines; + /* can't use more than we have */ + if (w->tag.fr.nlines >= w->tag.fr.maxlines) + return w->tag.fr.maxlines; - /* if tag ends with \n, include empty line at end for typing */ - n = w->tag.fr.nlines; - if(w->tag.file->b.nc > 0){ - bufread(&w->tag.file->b, w->tag.file->b.nc-1, &rune, 1); - if(rune == '\n') - n++; - } - if(n == 0) - n = 1; - return n; + /* if tag ends with \n, include empty line at end for typing */ + n = w->tag.fr.nlines; + if (w->tag.file->b.nc > 0) { + bufread(&w->tag.file->b, w->tag.file->b.nc - 1, &rune, 1); + if (rune == '\n') + n++; + } + if (n == 0) + n = 1; + return n; } -int -winresize(Window *w, Rectangle r, int safe, int keepextra) -{ - int oy, y, mouseintag, mouseinbody; - Point p; - Rectangle r1; +int winresize(Window* w, Rectangle r, int safe, int keepextra) { + int oy, y, mouseintag, mouseinbody; + Point p; + Rectangle r1; - mouseintag = ptinrect(mouse->xy, w->tag.all); - mouseinbody = ptinrect(mouse->xy, w->body.all); + mouseintag = ptinrect(mouse->xy, w->tag.all); + mouseinbody = ptinrect(mouse->xy, w->body.all); - /* tagtop is first line of tag */ - w->tagtop = r; - w->tagtop.max.y = r.min.y+font->height; + /* tagtop is first line of tag */ + w->tagtop = r; + w->tagtop.max.y = r.min.y + font->height; - r1 = r; - r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height); + r1 = r; + r1.max.y = min(r.max.y, r1.min.y + w->taglines * font->height); - /* If needed, recompute number of lines in tag. */ - if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){ - w->taglines = wintaglines(w, r); - r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height); - } + /* If needed, recompute number of lines in tag. */ + if (!safe || !w->tagsafe || !eqrect(w->tag.all, r1)) { + w->taglines = wintaglines(w, r); + r1.max.y = min(r.max.y, r1.min.y + w->taglines * font->height); + } - /* If needed, resize & redraw tag. */ - y = r1.max.y; - if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){ - textresize(&w->tag, r1, TRUE); - y = w->tag.fr.r.max.y; - windrawbutton(w); - w->tagsafe = TRUE; + /* If needed, resize & redraw tag. */ + y = r1.max.y; + if (!safe || !w->tagsafe || !eqrect(w->tag.all, r1)) { + textresize(&w->tag, r1, TRUE); + y = w->tag.fr.r.max.y; + windrawbutton(w); + w->tagsafe = TRUE; - /* If mouse is in tag, pull up as tag closes. */ - if(mouseintag && !ptinrect(mouse->xy, w->tag.all)){ - p = mouse->xy; - p.y = w->tag.all.max.y-3; - moveto(mousectl, p); - } + /* If mouse is in tag, pull up as tag closes. */ + if (mouseintag && !ptinrect(mouse->xy, w->tag.all)) { + p = mouse->xy; + p.y = w->tag.all.max.y - 3; + moveto(mousectl, p); + } - /* If mouse is in body, push down as tag expands. */ - if(mouseinbody && ptinrect(mouse->xy, w->tag.all)){ - p = mouse->xy; - p.y = w->tag.all.max.y+3; - moveto(mousectl, p); - } - } + /* If mouse is in body, push down as tag expands. */ + if (mouseinbody && ptinrect(mouse->xy, w->tag.all)) { + p = mouse->xy; + p.y = w->tag.all.max.y + 3; + moveto(mousectl, p); + } + } - /* If needed, resize & redraw body. */ - r1 = r; - r1.min.y = y; - if(!safe || !eqrect(w->body.all, r1)){ - oy = y; - if(y+1+w->body.fr.font->height <= r.max.y){ /* room for one line */ - r1.min.y = y; - r1.max.y = y+1; - draw(screen, r1, tagcols[BORD], nil, ZP); - y++; - r1.min.y = min(y, r.max.y); - r1.max.y = r.max.y; - }else{ - r1.min.y = y; - r1.max.y = y; - } - y = textresize(&w->body, r1, keepextra); - w->r = r; - w->r.max.y = y; - textscrdraw(&w->body); - w->body.all.min.y = oy; - } - w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines)); - return w->r.max.y; + /* If needed, resize & redraw body. */ + r1 = r; + r1.min.y = y; + if (!safe || !eqrect(w->body.all, r1)) { + oy = y; + if (y + 1 + w->body.fr.font->height <= r.max.y) { /* room for one line */ + r1.min.y = y; + r1.max.y = y + 1; + draw(screen, r1, tagcols[BORD], nil, ZP); + y++; + r1.min.y = min(y, r.max.y); + r1.max.y = r.max.y; + } else { + r1.min.y = y; + r1.max.y = y; + } + y = textresize(&w->body, r1, keepextra); + w->r = r; + w->r.max.y = y; + textscrdraw(&w->body); + w->body.all.min.y = oy; + } + w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines)); + return w->r.max.y; } -void -winlock1(Window *w, int owner) -{ - incref(&w->ref); - qlock(&w->lk); - w->owner = owner; +void winlock1(Window* w, int owner) { + incref(&w->ref); + qlock(&w->lk); + w->owner = owner; } -void -winlock(Window *w, int owner) -{ - int i; - File *f; +void winlock(Window* w, int owner) { + int i; + File* f; - f = w->body.file; - for(i=0; i<f->ntext; i++) - winlock1(f->text[i]->w, owner); + f = w->body.file; + for (i = 0; i < f->ntext; i++) + winlock1(f->text[i]->w, owner); } -void -winunlock(Window *w) -{ - int i; - File *f; +void winunlock(Window* w) { + int i; + File* f; - /* - * subtle: loop runs backwards to avoid tripping over - * winclose indirectly editing f->text and freeing f - * on the last iteration of the loop. - */ - f = w->body.file; - for(i=f->ntext-1; i>=0; i--){ - w = f->text[i]->w; - w->owner = 0; - qunlock(&w->lk); - winclose(w); - } + /* + * subtle: loop runs backwards to avoid tripping over + * winclose indirectly editing f->text and freeing f + * on the last iteration of the loop. + */ + f = w->body.file; + for (i = f->ntext - 1; i >= 0; i--) { + w = f->text[i]->w; + w->owner = 0; + qunlock(&w->lk); + winclose(w); + } } -void -winmousebut(Window *w) -{ - moveto(mousectl, addpt(w->tag.scrollr.min, - divpt(Pt(Dx(w->tag.scrollr), font->height), 2))); +void winmousebut(Window* w) { + moveto( + mousectl, + addpt(w->tag.scrollr.min, divpt(Pt(Dx(w->tag.scrollr), font->height), 2))); } -void -windirfree(Window *w) -{ - int i; - Dirlist *dl; +void windirfree(Window* w) { + int i; + Dirlist* dl; - if(w->isdir){ - for(i=0; i<w->ndl; i++){ - dl = w->dlp[i]; - free(dl->r); - free(dl); - } - free(w->dlp); - } - w->dlp = nil; - w->ndl = 0; + if (w->isdir) { + for (i = 0; i < w->ndl; i++) { + dl = w->dlp[i]; + free(dl->r); + free(dl); + } + free(w->dlp); + } + w->dlp = nil; + w->ndl = 0; } -void -winclose(Window *w) -{ - int i; +void winclose(Window* w) { + int i; - if(decref(&w->ref) == 0){ - xfidlog(w, "del"); - windirfree(w); - textclose(&w->tag); - textclose(&w->body); - if(activewin == w) - activewin = nil; - for(i=0; i<w->nincl; i++) - free(w->incl[i]); - free(w->incl); - free(w->events); - free(w); - } + if (decref(&w->ref) == 0) { + xfidlog(w, "del"); + windirfree(w); + textclose(&w->tag); + textclose(&w->body); + if (activewin == w) + activewin = nil; + for (i = 0; i < w->nincl; i++) + free(w->incl[i]); + free(w->incl); + free(w->events); + free(w); + } } -void -windelete(Window *w) -{ - Xfid *x; +void windelete(Window* w) { + Xfid* x; - x = w->eventx; - if(x){ - w->nevents = 0; - free(w->events); - w->events = nil; - w->eventx = nil; - sendp(x->c, nil); /* wake him up */ - } + x = w->eventx; + if (x) { + w->nevents = 0; + free(w->events); + w->events = nil; + w->eventx = nil; + sendp(x->c, nil); /* wake him up */ + } +} + +void winundo(Window* w, int isundo) { + Text* body; + int i; + File* f; + Window* v; + + w->utflastqid = -1; + body = &w->body; + fileundo(body->file, isundo, &body->q0, &body->q1); + textshow(body, body->q0, body->q1, 1); + f = body->file; + for (i = 0; i < f->ntext; i++) { + v = f->text[i]->w; + v->dirty = (f->seq != v->putseq); + if (v != w) { + v->body.q0 = v->body.fr.p0 + v->body.org; + v->body.q1 = v->body.fr.p1 + v->body.org; + } + } + winsettag(w); } -void -winundo(Window *w, int isundo) -{ - Text *body; - int i; - File *f; - Window *v; +void winsetname(Window* w, Rune* name, int n) { + Text* t; + Window* v; + int i; + static Rune Lslashguide[] = {'/', 'g', 'u', 'i', 'd', 'e', 0}; + static Rune Lpluserrors[] = {'+', 'E', 'r', 'r', 'o', 'r', 's', 0}; - w->utflastqid = -1; - body = &w->body; - fileundo(body->file, isundo, &body->q0, &body->q1); - textshow(body, body->q0, body->q1, 1); - f = body->file; - for(i=0; i<f->ntext; i++){ - v = f->text[i]->w; - v->dirty = (f->seq != v->putseq); - if(v != w){ - v->body.q0 = v->body.fr.p0+v->body.org; - v->body.q1 = v->body.fr.p1+v->body.org; - } - } - winsettag(w); + t = &w->body; + if (runeeq(t->file->name, t->file->nname, name, n) == TRUE) + return; + w->isscratch = FALSE; + if (n >= 6 && runeeq(Lslashguide, 6, name + (n - 6), 6)) + w->isscratch = TRUE; + else if (n >= 7 && runeeq(Lpluserrors, 7, name + (n - 7), 7)) + w->isscratch = TRUE; + filesetname(t->file, name, n); + for (i = 0; i < t->file->ntext; i++) { + v = t->file->text[i]->w; + winsettag(v); + v->isscratch = w->isscratch; + } } -void -winsetname(Window *w, Rune *name, int n) -{ - Text *t; - Window *v; - int i; - static Rune Lslashguide[] = { '/', 'g', 'u', 'i', 'd', 'e', 0 }; - static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 }; +void wintype(Window* w, Text* t, Rune r) { + int i; - t = &w->body; - if(runeeq(t->file->name, t->file->nname, name, n) == TRUE) - return; - w->isscratch = FALSE; - if(n>=6 && runeeq(Lslashguide, 6, name+(n-6), 6)) - w->isscratch = TRUE; - else if(n>=7 && runeeq(Lpluserrors, 7, name+(n-7), 7)) - w->isscratch = TRUE; - filesetname(t->file, name, n); - for(i=0; i<t->file->ntext; i++){ - v = t->file->text[i]->w; - winsettag(v); - v->isscratch = w->isscratch; - } + texttype(t, r); + if (t->what == Body) + for (i = 0; i < t->file->ntext; i++) + textscrdraw(t->file->text[i]); + winsettag(w); } -void -wintype(Window *w, Text *t, Rune r) -{ - int i; +void wincleartag(Window* w) { + int i, n; + Rune* r; - texttype(t, r); - if(t->what == Body) - for(i=0; i<t->file->ntext; i++) - textscrdraw(t->file->text[i]); - winsettag(w); + /* w must be committed */ + n = w->tag.file->b.nc; + r = parsetag(w, &i); + for (; i < n; i++) + if (r[i] == '|') + break; + if (i == n) + return; + i++; + textdelete(&w->tag, i, n, TRUE); + free(r); + w->tag.file->mod = FALSE; + if (w->tag.q0 > i) + w->tag.q0 = i; + if (w->tag.q1 > i) + w->tag.q1 = i; + textsetselect(&w->tag, w->tag.q0, w->tag.q1); } -void -wincleartag(Window *w) -{ - int i, n; - Rune *r; +Rune* parsetag(Window* w, int* len) { + static Rune Ldelsnarf[] = + {' ', 'D', 'e', 'l', ' ', 'S', 'n', 'a', 'r', 'f', 0}; + static Rune Lspacepipe[] = {' ', '|', 0}; + static Rune Ltabpipe[] = {' ', '|', 0}; + int i; + Rune *r, *p, *pipe; - /* w must be committed */ - n = w->tag.file->b.nc; - r = runemalloc(n); - bufread(&w->tag.file->b, 0, r, n); - for(i=0; i<n; i++) - if(r[i]==' ' || r[i]=='\t') - break; - for(; i<n; i++) - if(r[i] == '|') - break; - if(i == n) - return; - i++; - textdelete(&w->tag, i, n, TRUE); - free(r); - w->tag.file->mod = FALSE; - if(w->tag.q0 > i) - w->tag.q0 = i; - if(w->tag.q1 > i) - w->tag.q1 = i; - textsetselect(&w->tag, w->tag.q0, w->tag.q1); + r = runemalloc(w->tag.file->b.nc + 1); + bufread(&w->tag.file->b, 0, r, w->tag.file->b.nc); + r[w->tag.file->b.nc] = '\0'; + + for (i = 0; i < w->tag.file->b.nc; i++) + if (r[i] == ' ' || r[i] == '\t') + break; + + /* + * " |" or "\t|" ends left half of tag + * If we find " Del Snarf" in the left half of the tag + * (before the pipe), that ends the file name. + */ + pipe = runestrstr(r, Lspacepipe); + if ((p = runestrstr(r, Ltabpipe)) != nil && (pipe == nil || p < pipe)) + pipe = p; + if ((p = runestrstr(r, Ldelsnarf)) != nil && (pipe == nil || p < pipe)) + i = p - r; + else { + for (i = 0; i < w->tag.file->b.nc; i++) + if (r[i] == ' ' || r[i] == '\t') + break; + } + *len = i; + return r; } -void -winsettag1(Window *w) -{ - int i, j, k, n, bar, dirty, resize; - Rune *new, *old, *r; - uint q0, q1; - static Rune Ldelsnarf[] = { ' ', 'D', 'e', 'l', ' ', - 'S', 'n', 'a', 'r', 'f', 0 }; - static Rune Lundo[] = { ' ', 'U', 'n', 'd', 'o', 0 }; - static Rune Lredo[] = { ' ', 'R', 'e', 'd', 'o', 0 }; - static Rune Lget[] = { ' ', 'G', 'e', 't', 0 }; - static Rune Lput[] = { ' ', 'P', 'u', 't', 0 }; - static Rune Llook[] = { ' ', 'L', 'o', 'o', 'k', ' ', 0 }; - static Rune Lpipe[] = { ' ', '|', 0 }; +void winsettag1(Window* w) { + int i, j, k, n, bar, dirty, resize; + Rune* new, *old, *r; + uint q0, q1; + static Rune Ldelsnarf[] = + {' ', 'D', 'e', 'l', ' ', 'S', 'n', 'a', 'r', 'f', 0}; + static Rune Lundo[] = {' ', 'U', 'n', 'd', 'o', 0}; + static Rune Lredo[] = {' ', 'R', 'e', 'd', 'o', 0}; + static Rune Lget[] = {' ', 'G', 'e', 't', 0}; + static Rune Lput[] = {' ', 'P', 'u', 't', 0}; + static Rune Llook[] = {' ', 'L', 'o', 'o', 'k', ' ', 0}; + static Rune Lpipe[] = {' ', '|', 0}; - /* there are races that get us here with stuff in the tag cache, so we take extra care to sync it */ - if(w->tag.ncache!=0 || w->tag.file->mod) - wincommit(w, &w->tag); /* check file name; also guarantees we can modify tag contents */ - old = runemalloc(w->tag.file->b.nc+1); - bufread(&w->tag.file->b, 0, old, w->tag.file->b.nc); - old[w->tag.file->b.nc] = '\0'; - for(i=0; i<w->tag.file->b.nc; i++) - if(old[i]==' ' || old[i]=='\t') - break; - if(runeeq(old, i, w->body.file->name, w->body.file->nname) == FALSE){ - textdelete(&w->tag, 0, i, TRUE); - textinsert(&w->tag, 0, w->body.file->name, w->body.file->nname, TRUE); - free(old); - old = runemalloc(w->tag.file->b.nc+1); - bufread(&w->tag.file->b, 0, old, w->tag.file->b.nc); - old[w->tag.file->b.nc] = '\0'; - } + /* there are races that get us here with stuff in the tag cache, so we take + * extra care to sync it */ + if (w->tag.ncache != 0 || w->tag.file->mod) + wincommit(w, &w->tag); /* check file name; also guarantees we can modify tag + contents */ + old = parsetag(w, &i); + if (runeeq(old, i, w->body.file->name, w->body.file->nname) == FALSE) { + textdelete(&w->tag, 0, i, TRUE); + textinsert(&w->tag, 0, w->body.file->name, w->body.file->nname, TRUE); + free(old); + old = runemalloc(w->tag.file->b.nc + 1); + bufread(&w->tag.file->b, 0, old, w->tag.file->b.nc); + old[w->tag.file->b.nc] = '\0'; + } - /* compute the text for the whole tag, replacing current only if it differs */ - new = runemalloc(w->body.file->nname+100); - i = 0; - runemove(new+i, w->body.file->name, w->body.file->nname); - i += w->body.file->nname; - runemove(new+i, Ldelsnarf, 10); - i += 10; - if(w->filemenu){ - if(w->body.needundo || w->body.file->delta.nc>0 || w->body.ncache){ - runemove(new+i, Lundo, 5); - i += 5; - } - if(w->body.file->epsilon.nc > 0){ - runemove(new+i, Lredo, 5); - i += 5; - } - dirty = w->body.file->nname && (w->body.ncache || w->body.file->seq!=w->putseq); - if(!w->isdir && dirty){ - runemove(new+i, Lput, 4); - i += 4; - } - } - if(w->isdir){ - runemove(new+i, Lget, 4); - i += 4; - } - runemove(new+i, Lpipe, 2); - i += 2; - r = runestrchr(old, '|'); - if(r) - k = r-old+1; - else{ - k = w->tag.file->b.nc; - if(w->body.file->seq == 0){ - runemove(new+i, Llook, 6); - i += 6; - } - } - new[i] = 0; + /* compute the text for the whole tag, replacing current only if it differs */ + new = runemalloc(w->body.file->nname + 100); + i = 0; + runemove(new + i, w->body.file->name, w->body.file->nname); + i += w->body.file->nname; + runemove(new + i, Ldelsnarf, 10); + i += 10; + if (w->filemenu) { + if (w->body.needundo || w->body.file->delta.nc > 0 || w->body.ncache) { + runemove(new + i, Lundo, 5); + i += 5; + } + if (w->body.file->epsilon.nc > 0) { + runemove(new + i, Lredo, 5); + i += 5; + } + dirty = + w->body.file->nname && (w->body.ncache || w->body.file->seq != w->putseq); + if (!w->isdir && dirty) { + runemove(new + i, Lput, 4); + i += 4; + } + } + if (w->isdir) { + runemove(new + i, Lget, 4); + i += 4; + } + runemove(new + i, Lpipe, 2); + i += 2; + r = runestrchr(old, '|'); + if (r) + k = r - old + 1; + else { + k = w->tag.file->b.nc; + if (w->body.file->seq == 0) { + runemove(new + i, Llook, 6); + i += 6; + } + } + new[i] = 0; - /* replace tag if the new one is different */ - resize = 0; - if(runeeq(new, i, old, k) == FALSE){ - resize = 1; - n = k; - if(n > i) - n = i; - for(j=0; j<n; j++) - if(old[j] != new[j]) - break; - q0 = w->tag.q0; - q1 = w->tag.q1; - textdelete(&w->tag, j, k, TRUE); - textinsert(&w->tag, j, new+j, i-j, TRUE); - /* try to preserve user selection */ - r = runestrchr(old, '|'); - if(r){ - bar = r-old; - if(q0 > bar){ - bar = (runestrchr(new, '|')-new)-bar; - w->tag.q0 = q0+bar; - w->tag.q1 = q1+bar; - } - } - } - free(old); - free(new); - w->tag.file->mod = FALSE; - n = w->tag.file->b.nc+w->tag.ncache; - if(w->tag.q0 > n) - w->tag.q0 = n; - if(w->tag.q1 > n) - w->tag.q1 = n; - textsetselect(&w->tag, w->tag.q0, w->tag.q1); - windrawbutton(w); - if(resize){ - w->tagsafe = 0; - winresize(w, w->r, TRUE, TRUE); - } + /* replace tag if the new one is different */ + resize = 0; + if (runeeq(new, i, old, k) == FALSE) { + resize = 1; + n = k; + if (n > i) + n = i; + for (j = 0; j < n; j++) + if (old[j] != new[j]) + break; + q0 = w->tag.q0; + q1 = w->tag.q1; + textdelete(&w->tag, j, k, TRUE); + textinsert(&w->tag, j, new + j, i - j, TRUE); + /* try to preserve user selection */ + r = runestrchr(old, '|'); + if (r) { + bar = r - old; + if (q0 > bar) { + bar = (runestrchr(new, '|') - new) - bar; + w->tag.q0 = q0 + bar; + w->tag.q1 = q1 + bar; + } + } + } + free(old); + free(new); + w->tag.file->mod = FALSE; + n = w->tag.file->b.nc + w->tag.ncache; + if (w->tag.q0 > n) + w->tag.q0 = n; + if (w->tag.q1 > n) + w->tag.q1 = n; + textsetselect(&w->tag, w->tag.q0, w->tag.q1); + windrawbutton(w); + if (resize) { + w->tagsafe = 0; + winresize(w, w->r, TRUE, TRUE); + } } -void -winsettag(Window *w) -{ - int i; - File *f; - Window *v; +void winsettag(Window* w) { + int i; + File* f; + Window* v; - f = w->body.file; - for(i=0; i<f->ntext; i++){ - v = f->text[i]->w; - if(v->col->safe || v->body.fr.maxlines>0) - winsettag1(v); - } + f = w->body.file; + for (i = 0; i < f->ntext; i++) { + v = f->text[i]->w; + if (v->col->safe || v->body.fr.maxlines > 0) + winsettag1(v); + } } -void -wincommit(Window *w, Text *t) -{ - Rune *r; - int i; - File *f; +void wincommit(Window* w, Text* t) { + Rune* r; + int i; + File* f; - textcommit(t, TRUE); - f = t->file; - if(f->ntext > 1) - for(i=0; i<f->ntext; i++) - textcommit(f->text[i], FALSE); /* no-op for t */ - if(t->what == Body) - return; - r = runemalloc(w->tag.file->b.nc); - bufread(&w->tag.file->b, 0, r, w->tag.file->b.nc); - for(i=0; i<w->tag.file->b.nc; i++) - if(r[i]==' ' || r[i]=='\t') - break; - if(runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE){ - seq++; - filemark(w->body.file); - w->body.file->mod = TRUE; - w->dirty = TRUE; - winsetname(w, r, i); - winsettag(w); - } - free(r); + textcommit(t, TRUE); + f = t->file; + if (f->ntext > 1) + for (i = 0; i < f->ntext; i++) + textcommit(f->text[i], FALSE); /* no-op for t */ + if (t->what == Body) + return; + r = parsetag(w, &i); + if (runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE) { + seq++; + filemark(w->body.file); + w->body.file->mod = TRUE; + w->dirty = TRUE; + winsetname(w, r, i); + winsettag(w); + } + free(r); } -void -winaddincl(Window *w, Rune *r, int n) -{ - char *a; - Dir *d; - Runestr rs; +void winaddincl(Window* w, Rune* r, int n) { + char* a; + Dir* d; + Runestr rs; - a = runetobyte(r, n); - d = dirstat(a); - if(d == nil){ - if(a[0] == '/') - goto Rescue; - rs = dirname(&w->body, r, n); - r = rs.r; - n = rs.nr; - free(a); - a = runetobyte(r, n); - d = dirstat(a); - if(d == nil) - goto Rescue; - r = runerealloc(r, n+1); - r[n] = 0; - } - free(a); - if((d->qid.type&QTDIR) == 0){ - free(d); - warning(nil, "%s: not a directory\n", a); - free(r); - return; - } - free(d); - w->nincl++; - w->incl = realloc(w->incl, w->nincl*sizeof(Rune*)); - memmove(w->incl+1, w->incl, (w->nincl-1)*sizeof(Rune*)); - w->incl[0] = runemalloc(n+1); - runemove(w->incl[0], r, n); - free(r); - return; + a = runetobyte(r, n); + d = dirstat(a); + if (d == nil) { + if (a[0] == '/') + goto Rescue; + rs = dirname(&w->body, r, n); + r = rs.r; + n = rs.nr; + free(a); + a = runetobyte(r, n); + d = dirstat(a); + if (d == nil) + goto Rescue; + r = runerealloc(r, n + 1); + r[n] = 0; + } + free(a); + if ((d->qid.type & QTDIR) == 0) { + free(d); + warning(nil, "%s: not a directory\n", a); + free(r); + return; + } + free(d); + w->nincl++; + w->incl = realloc(w->incl, w->nincl * sizeof(Rune*)); + memmove(w->incl + 1, w->incl, (w->nincl - 1) * sizeof(Rune*)); + w->incl[0] = runemalloc(n + 1); + runemove(w->incl[0], r, n); + free(r); + return; Rescue: - warning(nil, "%s: %r\n", a); - free(r); - free(a); - return; + warning(nil, "%s: %r\n", a); + free(r); + free(a); + return; } -int -winclean(Window *w, int conservative) -{ - if(w->isscratch || w->isdir) /* don't whine if it's a guide file, error window, etc. */ - return TRUE; - if(!conservative && w->nopen[QWevent]>0) - return TRUE; - if(w->dirty){ - if(w->body.file->nname) - warning(nil, "%.*S modified\n", w->body.file->nname, w->body.file->name); - else{ - if(w->body.file->b.nc < 100) /* don't whine if it's too small */ - return TRUE; - warning(nil, "unnamed file modified\n"); - } - w->dirty = FALSE; - return FALSE; - } - return TRUE; +int winclean(Window* w, int conservative) { + if (w->isscratch || w->isdir) /* don't whine if it's a guide file, error + window, etc. */ + return TRUE; + if (!conservative && w->nopen[QWevent] > 0) + return TRUE; + if (w->dirty) { + if (w->body.file->nname) + warning(nil, "%.*S modified\n", w->body.file->nname, w->body.file->name); + else { + if (w->body.file->b.nc < 100) /* don't whine if it's too small */ + return TRUE; + warning(nil, "unnamed file modified\n"); + } + w->dirty = FALSE; + return FALSE; + } + return TRUE; } -char* -winctlprint(Window *w, char *buf, int fonts) -{ - sprint(buf, "%11d %11d %11d %11d %11d ", w->id, w->tag.file->b.nc, - w->body.file->b.nc, w->isdir, w->dirty); - if(fonts) - return smprint("%s%11d %q %11d ", buf, Dx(w->body.fr.r), - w->body.reffont->f->name, w->body.fr.maxtab); - return buf; +char* winctlprint(Window* w, char* buf, int fonts) { + sprint( + buf, + "%11d %11d %11d %11d %11d ", + w->id, + w->tag.file->b.nc, + w->body.file->b.nc, + w->isdir, + w->dirty); + if (fonts) + return smprint( + "%s%11d %q %11d ", + buf, + Dx(w->body.fr.r), + w->body.reffont->f->name, + w->body.fr.maxtab); + return buf; } -void -winevent(Window *w, char *fmt, ...) -{ - int n; - char *b; - Xfid *x; - va_list arg; +void winevent(Window* w, char* fmt, ...) { + int n; + char* b; + Xfid* x; + va_list arg; - if(w->nopen[QWevent] == 0) - return; - if(w->owner == 0) - error("no window owner"); - va_start(arg, fmt); - b = vsmprint(fmt, arg); - va_end(arg); - if(b == nil) - error("vsmprint failed"); - n = strlen(b); - w->events = erealloc(w->events, w->nevents+1+n); - w->events[w->nevents++] = w->owner; - memmove(w->events+w->nevents, b, n); - free(b); - w->nevents += n; - x = w->eventx; - if(x){ - w->eventx = nil; - sendp(x->c, nil); - } + if (w->nopen[QWevent] == 0) + return; + if (w->owner == 0) + error("no window owner"); + va_start(arg, fmt); + b = vsmprint(fmt, arg); + va_end(arg); + if (b == nil) + error("vsmprint failed"); + n = strlen(b); + w->events = erealloc(w->events, w->nevents + 1 + n); + w->events[w->nevents++] = w->owner; + memmove(w->events + w->nevents, b, n); + free(b); + w->nevents += n; + x = w->eventx; + if (x) { + w->eventx = nil; + sendp(x->c, nil); + } }
M xfid.cxfid.c

@@ -12,1114 +12,1079 @@ #include <libsec.h>

#include "dat.h" #include "fns.h" -enum -{ - Ctlsize = 5*12 -}; +enum { Ctlsize = 5 * 12 }; -char Edel[] = "deleted window"; -char Ebadctl[] = "ill-formed control message"; -char Ebadaddr[] = "bad address syntax"; -char Eaddr[] = "address out of range"; -char Einuse[] = "already in use"; -char Ebadevent[] = "bad event syntax"; +char Edel[] = "deleted window"; +char Ebadctl[] = "ill-formed control message"; +char Ebadaddr[] = "bad address syntax"; +char Eaddr[] = "address out of range"; +char Einuse[] = "already in use"; +char Ebadevent[] = "bad event syntax"; extern char Eperm[]; -static -void -clampaddr(Window *w) -{ - if(w->addr.q0 < 0) - w->addr.q0 = 0; - if(w->addr.q1 < 0) - w->addr.q1 = 0; - if(w->addr.q0 > w->body.file->b.nc) - w->addr.q0 = w->body.file->b.nc; - if(w->addr.q1 > w->body.file->b.nc) - w->addr.q1 = w->body.file->b.nc; +static void clampaddr(Window* w) { + if (w->addr.q0 < 0) + w->addr.q0 = 0; + if (w->addr.q1 < 0) + w->addr.q1 = 0; + if (w->addr.q0 > w->body.file->b.nc) + w->addr.q0 = w->body.file->b.nc; + if (w->addr.q1 > w->body.file->b.nc) + w->addr.q1 = w->body.file->b.nc; } -void -xfidctl(void *arg) -{ - Xfid *x; - void (*f)(Xfid*); +void xfidctl(void* arg) { + Xfid* x; + void (*f)(Xfid*); - threadsetname("xfidctlthread"); - x = arg; - for(;;){ - f = (void(*)(Xfid*))recvp(x->c); - (*f)(x); - flushimage(display, 1); - sendp(cxfidfree, x); - } + threadsetname("xfidctlthread"); + x = arg; + for (;;) { + f = (void (*)(Xfid*))recvp(x->c); + (*f)(x); + flushimage(display, 1); + sendp(cxfidfree, x); + } } -void -xfidflush(Xfid *x) -{ - Fcall fc; - int i, j; - Window *w; - Column *c; - Xfid *wx; +void xfidflush(Xfid* x) { + Fcall fc; + int i, j; + Window* w; + Column* c; + Xfid* wx; - xfidlogflush(x); + xfidlogflush(x); - /* search windows for matching tag */ - qlock(&row.lk); - for(j=0; j<row.ncol; j++){ - c = row.col[j]; - for(i=0; i<c->nw; i++){ - w = c->w[i]; - winlock(w, 'E'); - wx = w->eventx; - if(wx!=nil && wx->fcall.tag==x->fcall.oldtag){ - w->eventx = nil; - wx->flushed = TRUE; - sendp(wx->c, nil); - winunlock(w); - goto out; - } - winunlock(w); - } - } + /* search windows for matching tag */ + qlock(&row.lk); + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + winlock(w, 'E'); + wx = w->eventx; + if (wx != nil && wx->fcall.tag == x->fcall.oldtag) { + w->eventx = nil; + wx->flushed = TRUE; + sendp(wx->c, nil); + winunlock(w); + goto out; + } + winunlock(w); + } + } out: - qunlock(&row.lk); - respond(x, &fc, nil); + qunlock(&row.lk); + respond(x, &fc, nil); } -void -xfidopen(Xfid *x) -{ - Fcall fc; - Window *w; - Text *t; - char *s; - Rune *r; - int m, n, q, q0, q1; +void xfidopen(Xfid* x) { + Fcall fc; + Window* w; + Text* t; + char* s; + Rune* r; + int m, n, q, q0, q1; - w = x->f->w; - t = &w->body; - q = FILE(x->f->qid); - if(w){ - winlock(w, 'E'); - switch(q){ - case QWaddr: - if(w->nopen[q]++ == 0){ - w->addr = range(0, 0); - w->limit = range(-1,-1); - } - break; - case QWdata: - case QWxdata: - w->nopen[q]++; - break; - case QWevent: - if(w->nopen[q]++ == 0){ - if(!w->isdir && w->col!=nil){ - w->filemenu = FALSE; - winsettag(w); - } - } - break; - case QWrdsel: - /* - * Use a temporary file. - * A pipe would be the obvious, but we can't afford the - * broken pipe notification. Using the code to read QWbody - * is n², which should probably also be fixed. Even then, - * though, we'd need to squirrel away the data in case it's - * modified during the operation, e.g. by |sort - */ - if(w->rdselfd > 0){ - winunlock(w); - respond(x, &fc, Einuse); - return; - } - w->rdselfd = tempfile(); - if(w->rdselfd < 0){ - winunlock(w); - respond(x, &fc, "can't create temp file"); - return; - } - w->nopen[q]++; - q0 = t->q0; - q1 = t->q1; - r = fbufalloc(); - s = fbufalloc(); - while(q0 < q1){ - n = q1 - q0; - if(n > BUFSIZE/UTFmax) - n = BUFSIZE/UTFmax; - bufread(&t->file->b, q0, r, n); - m = snprint(s, BUFSIZE+1, "%.*S", n, r); - if(write(w->rdselfd, s, m) != m){ - warning(nil, "can't write temp file for pipe command %r\n"); - break; - } - q0 += n; - } - fbuffree(s); - fbuffree(r); - break; - case QWwrsel: - w->nopen[q]++; - seq++; - filemark(t->file); - cut(t, t, nil, FALSE, TRUE, nil, 0); - w->wrselrange = range(t->q1, t->q1); - w->nomark = TRUE; - break; - case QWeditout: - if(editing == FALSE){ - winunlock(w); - respond(x, &fc, Eperm); - return; - } - if(!canqlock(&w->editoutlk)){ - winunlock(w); - respond(x, &fc, Einuse); - return; - } - w->wrselrange = range(t->q1, t->q1); - break; - } - winunlock(w); - } - else{ - switch(q){ - case Qlog: - xfidlogopen(x); - break; - case Qeditout: - if(!canqlock(&editoutlk)){ - respond(x, &fc, Einuse); - return; - } - break; - } - } - fc.qid = x->f->qid; - fc.iounit = messagesize-IOHDRSZ; - x->f->open = TRUE; - respond(x, &fc, nil); + w = x->f->w; + t = &w->body; + q = FILE(x->f->qid); + if (w) { + winlock(w, 'E'); + switch (q) { + case QWaddr: + if (w->nopen[q]++ == 0) { + w->addr = range(0, 0); + w->limit = range(-1, -1); + } + break; + case QWdata: + case QWxdata: + w->nopen[q]++; + break; + case QWevent: + if (w->nopen[q]++ == 0) { + if (!w->isdir && w->col != nil) { + w->filemenu = FALSE; + winsettag(w); + } + } + break; + case QWrdsel: + /* + * Use a temporary file. + * A pipe would be the obvious, but we can't afford the + * broken pipe notification. Using the code to read QWbody + * is n², which should probably also be fixed. Even then, + * though, we'd need to squirrel away the data in case it's + * modified during the operation, e.g. by |sort + */ + if (w->rdselfd > 0) { + winunlock(w); + respond(x, &fc, Einuse); + return; + } + w->rdselfd = tempfile(); + if (w->rdselfd < 0) { + winunlock(w); + respond(x, &fc, "can't create temp file"); + return; + } + w->nopen[q]++; + q0 = t->q0; + q1 = t->q1; + r = fbufalloc(); + s = fbufalloc(); + while (q0 < q1) { + n = q1 - q0; + if (n > BUFSIZE / UTFmax) + n = BUFSIZE / UTFmax; + bufread(&t->file->b, q0, r, n); + m = snprint(s, BUFSIZE + 1, "%.*S", n, r); + if (write(w->rdselfd, s, m) != m) { + warning(nil, "can't write temp file for pipe command %r\n"); + break; + } + q0 += n; + } + fbuffree(s); + fbuffree(r); + break; + case QWwrsel: + w->nopen[q]++; + seq++; + filemark(t->file); + cut(t, t, nil, FALSE, TRUE, nil, 0); + w->wrselrange = range(t->q1, t->q1); + w->nomark = TRUE; + break; + case QWeditout: + if (editing == FALSE) { + winunlock(w); + respond(x, &fc, Eperm); + return; + } + if (!canqlock(&w->editoutlk)) { + winunlock(w); + respond(x, &fc, Einuse); + return; + } + w->wrselrange = range(t->q1, t->q1); + break; + } + winunlock(w); + } else { + switch (q) { + case Qlog: + xfidlogopen(x); + break; + case Qeditout: + if (!canqlock(&editoutlk)) { + respond(x, &fc, Einuse); + return; + } + break; + } + } + fc.qid = x->f->qid; + fc.iounit = messagesize - IOHDRSZ; + x->f->open = TRUE; + respond(x, &fc, nil); } -void -xfidclose(Xfid *x) -{ - Fcall fc; - Window *w; - int q; - Text *t; +void xfidclose(Xfid* x) { + Fcall fc; + Window* w; + int q; + Text* t; - w = x->f->w; - x->f->busy = FALSE; - x->f->w = nil; - if(x->f->open == FALSE){ - if(w != nil) - winclose(w); - respond(x, &fc, nil); - return; - } + w = x->f->w; + x->f->busy = FALSE; + x->f->w = nil; + if (x->f->open == FALSE) { + if (w != nil) + winclose(w); + respond(x, &fc, nil); + return; + } - q = FILE(x->f->qid); - x->f->open = FALSE; - if(w){ - winlock(w, 'E'); - switch(q){ - case QWctl: - if(w->ctlfid!=~0 && w->ctlfid==x->f->fid){ - w->ctlfid = ~0; - qunlock(&w->ctllock); - } - break; - case QWdata: - case QWxdata: - w->nomark = FALSE; - /* fall through */ - case QWaddr: - case QWevent: /* BUG: do we need to shut down Xfid? */ - if(--w->nopen[q] == 0){ - if(q == QWdata || q == QWxdata) - w->nomark = FALSE; - if(q==QWevent && !w->isdir && w->col!=nil){ - w->filemenu = TRUE; - winsettag(w); - } - if(q == QWevent){ - free(w->dumpstr); - free(w->dumpdir); - w->dumpstr = nil; - w->dumpdir = nil; - } - } - break; - case QWrdsel: - close(w->rdselfd); - w->rdselfd = 0; - break; - case QWwrsel: - w->nomark = FALSE; - t = &w->body; - /* before: only did this if !w->noscroll, but that didn't seem right in practice */ - textshow(t, min(w->wrselrange.q0, t->file->b.nc), - min(w->wrselrange.q1, t->file->b.nc), 1); - textscrdraw(t); - break; - case QWeditout: - qunlock(&w->editoutlk); - break; - } - winunlock(w); - winclose(w); - } - else{ - switch(q){ - case Qeditout: - qunlock(&editoutlk); - break; - } - } - respond(x, &fc, nil); + q = FILE(x->f->qid); + x->f->open = FALSE; + if (w) { + winlock(w, 'E'); + switch (q) { + case QWctl: + if (w->ctlfid != ~0 && w->ctlfid == x->f->fid) { + w->ctlfid = ~0; + qunlock(&w->ctllock); + } + break; + case QWdata: + case QWxdata: + w->nomark = FALSE; + /* fall through */ + case QWaddr: + case QWevent: /* BUG: do we need to shut down Xfid? */ + if (--w->nopen[q] == 0) { + if (q == QWdata || q == QWxdata) + w->nomark = FALSE; + if (q == QWevent && !w->isdir && w->col != nil) { + w->filemenu = TRUE; + winsettag(w); + } + if (q == QWevent) { + free(w->dumpstr); + free(w->dumpdir); + w->dumpstr = nil; + w->dumpdir = nil; + } + } + break; + case QWrdsel: + close(w->rdselfd); + w->rdselfd = 0; + break; + case QWwrsel: + w->nomark = FALSE; + t = &w->body; + /* before: only did this if !w->noscroll, but that didn't seem right in + * practice */ + textshow( + t, + min(w->wrselrange.q0, t->file->b.nc), + min(w->wrselrange.q1, t->file->b.nc), + 1); + textscrdraw(t); + break; + case QWeditout: + qunlock(&w->editoutlk); + break; + } + winunlock(w); + winclose(w); + } else { + switch (q) { + case Qeditout: + qunlock(&editoutlk); + break; + } + } + respond(x, &fc, nil); } -void -xfidread(Xfid *x) -{ - Fcall fc; - int n, q; - uint off; - char *b; - char buf[256]; - Window *w; +void xfidread(Xfid* x) { + Fcall fc; + int n, q; + uint off; + char* b; + char buf[256]; + Window* w; - q = FILE(x->f->qid); - w = x->f->w; - if(w == nil){ - fc.count = 0; - switch(q){ - case Qcons: - case Qlabel: - break; - case Qindex: - xfidindexread(x); - return; - case Qlog: - xfidlogread(x); - return; - default: - warning(nil, "unknown qid %d\n", q); - break; - } - respond(x, &fc, nil); - return; - } - winlock(w, 'F'); - if(w->col == nil){ - winunlock(w); - respond(x, &fc, Edel); - return; - } - off = x->fcall.offset; - switch(q){ - case QWaddr: - textcommit(&w->body, TRUE); - clampaddr(w); - sprint(buf, "%11d %11d ", w->addr.q0, w->addr.q1); - goto Readbuf; + q = FILE(x->f->qid); + w = x->f->w; + if (w == nil) { + fc.count = 0; + switch (q) { + case Qcons: + case Qlabel: + break; + case Qindex: + xfidindexread(x); + return; + case Qlog: + xfidlogread(x); + return; + default: + warning(nil, "unknown qid %d\n", q); + break; + } + respond(x, &fc, nil); + return; + } + winlock(w, 'F'); + if (w->col == nil) { + winunlock(w); + respond(x, &fc, Edel); + return; + } + off = x->fcall.offset; + switch (q) { + case QWaddr: + textcommit(&w->body, TRUE); + clampaddr(w); + sprint(buf, "%11d %11d ", w->addr.q0, w->addr.q1); + goto Readbuf; - case QWbody: - xfidutfread(x, &w->body, w->body.file->b.nc, QWbody); - break; + case QWbody: + xfidutfread(x, &w->body, w->body.file->b.nc, QWbody); + break; - case QWctl: - b = winctlprint(w, buf, 1); - goto Readb; + case QWctl: + b = winctlprint(w, buf, 1); + goto Readb; - Readbuf: - b = buf; - Readb: - n = strlen(b); - if(off > n) - off = n; - if(off+x->fcall.count > n) - x->fcall.count = n-off; - fc.count = x->fcall.count; - fc.data = b+off; - respond(x, &fc, nil); - if(b != buf) - free(b); - break; + Readbuf: + b = buf; + Readb: + n = strlen(b); + if (off > n) + off = n; + if (off + x->fcall.count > n) + x->fcall.count = n - off; + fc.count = x->fcall.count; + fc.data = b + off; + respond(x, &fc, nil); + if (b != buf) + free(b); + break; - case QWevent: - xfideventread(x, w); - break; + case QWevent: + xfideventread(x, w); + break; - case QWdata: - /* BUG: what should happen if q1 > q0? */ - if(w->addr.q0 > w->body.file->b.nc){ - respond(x, &fc, Eaddr); - break; - } - w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->b.nc); - w->addr.q1 = w->addr.q0; - break; + case QWdata: + /* BUG: what should happen if q1 > q0? */ + if (w->addr.q0 > w->body.file->b.nc) { + respond(x, &fc, Eaddr); + break; + } + w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->b.nc); + w->addr.q1 = w->addr.q0; + break; - case QWxdata: - /* BUG: what should happen if q1 > q0? */ - if(w->addr.q0 > w->body.file->b.nc){ - respond(x, &fc, Eaddr); - break; - } - w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->addr.q1); - break; + case QWxdata: + /* BUG: what should happen if q1 > q0? */ + if (w->addr.q0 > w->body.file->b.nc) { + respond(x, &fc, Eaddr); + break; + } + w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->addr.q1); + break; - case QWtag: - xfidutfread(x, &w->tag, w->tag.file->b.nc, QWtag); - break; + case QWtag: + xfidutfread(x, &w->tag, w->tag.file->b.nc, QWtag); + break; - case QWrdsel: - seek(w->rdselfd, off, 0); - n = x->fcall.count; - if(n > BUFSIZE) - n = BUFSIZE; - b = fbufalloc(); - n = read(w->rdselfd, b, n); - if(n < 0){ - respond(x, &fc, "I/O error in temp file"); - break; - } - fc.count = n; - fc.data = b; - respond(x, &fc, nil); - fbuffree(b); - break; + case QWrdsel: + seek(w->rdselfd, off, 0); + n = x->fcall.count; + if (n > BUFSIZE) + n = BUFSIZE; + b = fbufalloc(); + n = read(w->rdselfd, b, n); + if (n < 0) { + respond(x, &fc, "I/O error in temp file"); + break; + } + fc.count = n; + fc.data = b; + respond(x, &fc, nil); + fbuffree(b); + break; - default: - sprint(buf, "unknown qid %d in read", q); - respond(x, &fc, nil); - } - winunlock(w); + default: + sprint(buf, "unknown qid %d in read", q); + respond(x, &fc, nil); + } + winunlock(w); } -static int -shouldscroll(Text *t, uint q0, int qid) -{ - if(qid == Qcons) - return TRUE; - return t->org <= q0 && q0 <= t->org+t->fr.nchars; +static int shouldscroll(Text* t, uint q0, int qid) { + if (qid == Qcons) + return TRUE; + return t->org <= q0 && q0 <= t->org + t->fr.nchars; } -static Rune* -fullrunewrite(Xfid *x, int *inr) -{ - int q, cnt, c, nb, nr; - Rune *r; +static Rune* fullrunewrite(Xfid* x, int* inr) { + int q, cnt, c, nb, nr; + Rune* r; - q = x->f->nrpart; - cnt = x->fcall.count; - if(q > 0){ - memmove(x->fcall.data+q, x->fcall.data, cnt); /* there's room; see fsysproc */ - memmove(x->fcall.data, x->f->rpart, q); - cnt += q; - x->f->nrpart = 0; - } - r = runemalloc(cnt); - cvttorunes(x->fcall.data, cnt-UTFmax, r, &nb, &nr, nil); - /* approach end of buffer */ - while(fullrune(x->fcall.data+nb, cnt-nb)){ - c = nb; - nb += chartorune(&r[nr], x->fcall.data+c); - if(r[nr]) - nr++; - } - if(nb < cnt){ - memmove(x->f->rpart, x->fcall.data+nb, cnt-nb); - x->f->nrpart = cnt-nb; - } - *inr = nr; - return r; + q = x->f->nrpart; + cnt = x->fcall.count; + if (q > 0) { + memmove( + x->fcall.data + q, + x->fcall.data, + cnt); /* there's room; see fsysproc */ + memmove(x->fcall.data, x->f->rpart, q); + cnt += q; + x->f->nrpart = 0; + } + r = runemalloc(cnt); + cvttorunes(x->fcall.data, cnt - UTFmax, r, &nb, &nr, nil); + /* approach end of buffer */ + while (fullrune(x->fcall.data + nb, cnt - nb)) { + c = nb; + nb += chartorune(&r[nr], x->fcall.data + c); + if (r[nr]) + nr++; + } + if (nb < cnt) { + memmove(x->f->rpart, x->fcall.data + nb, cnt - nb); + x->f->nrpart = cnt - nb; + } + *inr = nr; + return r; } -void -xfidwrite(Xfid *x) -{ - Fcall fc; - int c, qid, nb, nr, eval; - char buf[64], *err; - Window *w; - Rune *r; - Range a; - Text *t; - uint q0, tq0, tq1; +void xfidwrite(Xfid* x) { + Fcall fc; + int c, qid, nb, nr, eval; + char buf[64], *err; + Window* w; + Rune* r; + Range a; + Text* t; + uint q0, tq0, tq1; - qid = FILE(x->f->qid); - w = x->f->w; - if(w){ - c = 'F'; - if(qid==QWtag || qid==QWbody) - c = 'E'; - winlock(w, c); - if(w->col == nil){ - winunlock(w); - respond(x, &fc, Edel); - return; - } - } - x->fcall.data[x->fcall.count] = 0; - switch(qid){ - case Qcons: - w = errorwin(x->f->mntdir, 'X'); - t=&w->body; - goto BodyTag; + qid = FILE(x->f->qid); + w = x->f->w; + if (w) { + c = 'F'; + if (qid == QWtag || qid == QWbody) + c = 'E'; + winlock(w, c); + if (w->col == nil) { + winunlock(w); + respond(x, &fc, Edel); + return; + } + } + x->fcall.data[x->fcall.count] = 0; + switch (qid) { + case Qcons: + w = errorwin(x->f->mntdir, 'X'); + t = &w->body; + goto BodyTag; - case Qlabel: - fc.count = x->fcall.count; - respond(x, &fc, nil); - break; + case Qlabel: + fc.count = x->fcall.count; + respond(x, &fc, nil); + break; - case QWaddr: - x->fcall.data[x->fcall.count] = 0; - r = bytetorune(x->fcall.data, &nr); - t = &w->body; - wincommit(w, t); - eval = TRUE; - a = address(FALSE, t, w->limit, w->addr, r, 0, nr, rgetc, &eval, (uint*)&nb); - free(r); - if(nb < nr){ - respond(x, &fc, Ebadaddr); - break; - } - if(!eval){ - respond(x, &fc, Eaddr); - break; - } - w->addr = a; - fc.count = x->fcall.count; - respond(x, &fc, nil); - break; + case QWaddr: + x->fcall.data[x->fcall.count] = 0; + r = bytetorune(x->fcall.data, &nr); + t = &w->body; + wincommit(w, t); + eval = TRUE; + a = address( + FALSE, + t, + w->limit, + w->addr, + r, + 0, + nr, + rgetc, + &eval, + (uint*)&nb); + free(r); + if (nb < nr) { + respond(x, &fc, Ebadaddr); + break; + } + if (!eval) { + respond(x, &fc, Eaddr); + break; + } + w->addr = a; + fc.count = x->fcall.count; + respond(x, &fc, nil); + break; - case Qeditout: - case QWeditout: - r = fullrunewrite(x, &nr); - if(w) - err = edittext(w, w->wrselrange.q1, r, nr); - else - err = edittext(nil, 0, r, nr); - free(r); - if(err != nil){ - respond(x, &fc, err); - break; - } - fc.count = x->fcall.count; - respond(x, &fc, nil); - break; + case Qeditout: + case QWeditout: + r = fullrunewrite(x, &nr); + if (w) + err = edittext(w, w->wrselrange.q1, r, nr); + else + err = edittext(nil, 0, r, nr); + free(r); + if (err != nil) { + respond(x, &fc, err); + break; + } + fc.count = x->fcall.count; + respond(x, &fc, nil); + break; - case QWerrors: - w = errorwinforwin(w); - t = &w->body; - goto BodyTag; + case QWerrors: + w = errorwinforwin(w); + t = &w->body; + goto BodyTag; - case QWbody: - case QWwrsel: - t = &w->body; - goto BodyTag; + case QWbody: + case QWwrsel: + t = &w->body; + goto BodyTag; - case QWctl: - xfidctlwrite(x, w); - break; + case QWctl: + xfidctlwrite(x, w); + break; - case QWdata: - a = w->addr; - t = &w->body; - wincommit(w, t); - if(a.q0>t->file->b.nc || a.q1>t->file->b.nc){ - respond(x, &fc, Eaddr); - break; - } - r = runemalloc(x->fcall.count); - cvttorunes(x->fcall.data, x->fcall.count, r, &nb, &nr, nil); - if(w->nomark == FALSE){ - seq++; - filemark(t->file); - } - q0 = a.q0; - if(a.q1 > q0){ - textdelete(t, q0, a.q1, TRUE); - w->addr.q1 = q0; - } - tq0 = t->q0; - tq1 = t->q1; - textinsert(t, q0, r, nr, TRUE); - if(tq0 >= q0) - tq0 += nr; - if(tq1 >= q0) - tq1 += nr; - textsetselect(t, tq0, tq1); - if(shouldscroll(t, q0, qid)) - textshow(t, q0+nr, q0+nr, 0); - textscrdraw(t); - winsettag(w); - free(r); - w->addr.q0 += nr; - w->addr.q1 = w->addr.q0; - fc.count = x->fcall.count; - respond(x, &fc, nil); - break; + case QWdata: + a = w->addr; + t = &w->body; + wincommit(w, t); + if (a.q0 > t->file->b.nc || a.q1 > t->file->b.nc) { + respond(x, &fc, Eaddr); + break; + } + r = runemalloc(x->fcall.count); + cvttorunes(x->fcall.data, x->fcall.count, r, &nb, &nr, nil); + if (w->nomark == FALSE) { + seq++; + filemark(t->file); + } + q0 = a.q0; + if (a.q1 > q0) { + textdelete(t, q0, a.q1, TRUE); + w->addr.q1 = q0; + } + tq0 = t->q0; + tq1 = t->q1; + textinsert(t, q0, r, nr, TRUE); + if (tq0 >= q0) + tq0 += nr; + if (tq1 >= q0) + tq1 += nr; + textsetselect(t, tq0, tq1); + if (shouldscroll(t, q0, qid)) + textshow(t, q0 + nr, q0 + nr, 0); + textscrdraw(t); + winsettag(w); + free(r); + w->addr.q0 += nr; + w->addr.q1 = w->addr.q0; + fc.count = x->fcall.count; + respond(x, &fc, nil); + break; - case QWevent: - xfideventwrite(x, w); - break; + case QWevent: + xfideventwrite(x, w); + break; - case QWtag: - t = &w->tag; - goto BodyTag; + case QWtag: + t = &w->tag; + goto BodyTag; - BodyTag: - r = fullrunewrite(x, &nr); - if(nr > 0){ - wincommit(w, t); - if(qid == QWwrsel){ - q0 = w->wrselrange.q1; - if(q0 > t->file->b.nc) - q0 = t->file->b.nc; - }else - q0 = t->file->b.nc; - if(qid == QWtag) - textinsert(t, q0, r, nr, TRUE); - else{ - if(w->nomark == FALSE){ - seq++; - filemark(t->file); - } - q0 = textbsinsert(t, q0, r, nr, TRUE, &nr); - textsetselect(t, t->q0, t->q1); /* insert could leave it somewhere else */ - if(qid!=QWwrsel && shouldscroll(t, q0, qid)) - textshow(t, q0+nr, q0+nr, 1); - textscrdraw(t); - } - winsettag(w); - if(qid == QWwrsel) - w->wrselrange.q1 += nr; - free(r); - } - fc.count = x->fcall.count; - respond(x, &fc, nil); - break; + BodyTag: + r = fullrunewrite(x, &nr); + if (nr > 0) { + wincommit(w, t); + if (qid == QWwrsel) { + q0 = w->wrselrange.q1; + if (q0 > t->file->b.nc) + q0 = t->file->b.nc; + } else + q0 = t->file->b.nc; + if (qid == QWtag) + textinsert(t, q0, r, nr, TRUE); + else { + if (w->nomark == FALSE) { + seq++; + filemark(t->file); + } + q0 = textbsinsert(t, q0, r, nr, TRUE, &nr); + textsetselect( + t, + t->q0, + t->q1); /* insert could leave it somewhere else */ + if (qid != QWwrsel && shouldscroll(t, q0, qid)) + textshow(t, q0 + nr, q0 + nr, 1); + textscrdraw(t); + } + winsettag(w); + if (qid == QWwrsel) + w->wrselrange.q1 += nr; + free(r); + } + fc.count = x->fcall.count; + respond(x, &fc, nil); + break; - default: - sprint(buf, "unknown qid %d in write", qid); - respond(x, &fc, buf); - break; - } - if(w) - winunlock(w); + default: + sprint(buf, "unknown qid %d in write", qid); + respond(x, &fc, buf); + break; + } + if (w) + winunlock(w); } -void -xfidctlwrite(Xfid *x, Window *w) -{ - Fcall fc; - int i, m, n, nb, nr, nulls; - Rune *r; - char *err, *p, *pp, *q, *e; - int isfbuf, scrdraw, settag; - Text *t; +void xfidctlwrite(Xfid* x, Window* w) { + Fcall fc; + int i, m, n, nb, nr, nulls; + Rune* r; + char *err, *p, *pp, *q, *e; + int isfbuf, scrdraw, settag; + Text* t; - err = nil; - e = x->fcall.data+x->fcall.count; - scrdraw = FALSE; - settag = FALSE; - isfbuf = TRUE; - if(x->fcall.count < RBUFSIZE) - r = fbufalloc(); - else{ - isfbuf = FALSE; - r = emalloc(x->fcall.count*UTFmax+1); - } - x->fcall.data[x->fcall.count] = 0; - textcommit(&w->tag, TRUE); - for(n=0; n<x->fcall.count; n+=m){ - p = x->fcall.data+n; - if(strncmp(p, "lock", 4) == 0){ /* make window exclusive use */ - qlock(&w->ctllock); - w->ctlfid = x->f->fid; - m = 4; - }else - if(strncmp(p, "unlock", 6) == 0){ /* release exclusive use */ - w->ctlfid = ~0; - qunlock(&w->ctllock); - m = 6; - }else - if(strncmp(p, "clean", 5) == 0){ /* mark window 'clean', seq=0 */ - t = &w->body; - t->eq0 = ~0; - filereset(t->file); - t->file->mod = FALSE; - w->dirty = FALSE; - settag = TRUE; - m = 5; - }else - if(strncmp(p, "dirty", 5) == 0){ /* mark window 'dirty' */ - t = &w->body; - /* doesn't change sequence number, so "Put" won't appear. it shouldn't. */ - t->file->mod = TRUE; - w->dirty = TRUE; - settag = TRUE; - m = 5; - }else - if(strncmp(p, "show", 4) == 0){ /* show dot */ - t = &w->body; - textshow(t, t->q0, t->q1, 1); - m = 4; - }else - if(strncmp(p, "name ", 5) == 0){ /* set file name */ - pp = p+5; - m = 5; - q = memchr(pp, '\n', e-pp); - if(q==nil || q==pp){ - err = Ebadctl; - break; - } - *q = 0; - nulls = FALSE; - cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); - if(nulls){ - err = "nulls in file name"; - break; - } - for(i=0; i<nr; i++) - if(r[i] <= ' '){ - err = "bad character in file name"; - goto out; - } -out: - seq++; - filemark(w->body.file); - winsetname(w, r, nr); - m += (q+1) - pp; - }else - if(strncmp(p, "dump ", 5) == 0){ /* set dump string */ - pp = p+5; - m = 5; - q = memchr(pp, '\n', e-pp); - if(q==nil || q==pp){ - err = Ebadctl; - break; - } - *q = 0; - nulls = FALSE; - cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); - if(nulls){ - err = "nulls in dump string"; - break; - } - w->dumpstr = runetobyte(r, nr); - m += (q+1) - pp; - }else - if(strncmp(p, "dumpdir ", 8) == 0){ /* set dump directory */ - pp = p+8; - m = 8; - q = memchr(pp, '\n', e-pp); - if(q==nil || q==pp){ - err = Ebadctl; - break; - } - *q = 0; - nulls = FALSE; - cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); - if(nulls){ - err = "nulls in dump directory string"; - break; - } - w->dumpdir = runetobyte(r, nr); - m += (q+1) - pp; - }else - if(strncmp(p, "delete", 6) == 0){ /* delete for sure */ - colclose(w->col, w, TRUE); - m = 6; - }else - if(strncmp(p, "del", 3) == 0){ /* delete, but check dirty */ - if(!winclean(w, TRUE)){ - err = "file dirty"; - break; - } - colclose(w->col, w, TRUE); - m = 3; - }else - if(strncmp(p, "get", 3) == 0){ /* get file */ - get(&w->body, nil, nil, FALSE, XXX, nil, 0); - m = 3; - }else - if(strncmp(p, "put", 3) == 0){ /* put file */ - put(&w->body, nil, nil, XXX, XXX, nil, 0); - m = 3; - }else - if(strncmp(p, "dot=addr", 8) == 0){ /* set dot */ - textcommit(&w->body, TRUE); - clampaddr(w); - w->body.q0 = w->addr.q0; - w->body.q1 = w->addr.q1; - textsetselect(&w->body, w->body.q0, w->body.q1); - settag = TRUE; - m = 8; - }else - if(strncmp(p, "addr=dot", 8) == 0){ /* set addr */ - w->addr.q0 = w->body.q0; - w->addr.q1 = w->body.q1; - m = 8; - }else - if(strncmp(p, "limit=addr", 10) == 0){ /* set limit */ - textcommit(&w->body, TRUE); - clampaddr(w); - w->limit.q0 = w->addr.q0; - w->limit.q1 = w->addr.q1; - m = 10; - }else - if(strncmp(p, "nomark", 6) == 0){ /* turn off automatic marking */ - w->nomark = TRUE; - m = 6; - }else - if(strncmp(p, "mark", 4) == 0){ /* mark file */ - seq++; - filemark(w->body.file); - settag = TRUE; - m = 4; - }else - if(strncmp(p, "nomenu", 6) == 0){ /* turn off automatic menu */ - w->filemenu = FALSE; - settag = TRUE; - m = 6; - }else - if(strncmp(p, "menu", 4) == 0){ /* enable automatic menu */ - w->filemenu = TRUE; - settag = TRUE; - m = 4; - }else - if(strncmp(p, "cleartag", 8) == 0){ /* wipe tag right of bar */ - wincleartag(w); - settag = TRUE; - m = 8; - }else{ - err = Ebadctl; - break; - } - while(p[m] == '\n') - m++; - } + err = nil; + e = x->fcall.data + x->fcall.count; + scrdraw = FALSE; + settag = FALSE; + isfbuf = TRUE; + if (x->fcall.count < RBUFSIZE) + r = fbufalloc(); + else { + isfbuf = FALSE; + r = emalloc(x->fcall.count * UTFmax + 1); + } + x->fcall.data[x->fcall.count] = 0; + textcommit(&w->tag, TRUE); + for (n = 0; n < x->fcall.count; n += m) { + p = x->fcall.data + n; + if (strncmp(p, "lock", 4) == 0) { /* make window exclusive use */ + qlock(&w->ctllock); + w->ctlfid = x->f->fid; + m = 4; + } else if (strncmp(p, "unlock", 6) == 0) { /* release exclusive use */ + w->ctlfid = ~0; + qunlock(&w->ctllock); + m = 6; + } else if (strncmp(p, "clean", 5) == 0) { /* mark window 'clean', seq=0 */ + t = &w->body; + t->eq0 = ~0; + filereset(t->file); + t->file->mod = FALSE; + w->dirty = FALSE; + settag = TRUE; + m = 5; + } else if (strncmp(p, "dirty", 5) == 0) { /* mark window 'dirty' */ + t = &w->body; + /* doesn't change sequence number, so "Put" won't appear. it shouldn't. + */ + t->file->mod = TRUE; + w->dirty = TRUE; + settag = TRUE; + m = 5; + } else if (strncmp(p, "show", 4) == 0) { /* show dot */ + t = &w->body; + textshow(t, t->q0, t->q1, 1); + m = 4; + } else if (strncmp(p, "name ", 5) == 0) { /* set file name */ + pp = p + 5; + m = 5; + q = memchr(pp, '\n', e - pp); + if (q == nil || q == pp) { + err = Ebadctl; + break; + } + *q = 0; + nulls = FALSE; + cvttorunes(pp, q - pp, r, &nb, &nr, &nulls); + if (nulls) { + err = "nulls in file name"; + break; + } + for (i = 0; i < nr; i++) + if (r[i] <= ' ') { + err = "bad character in file name"; + goto out; + } + out: + seq++; + filemark(w->body.file); + winsetname(w, r, nr); + m += (q + 1) - pp; + } else if (strncmp(p, "dump ", 5) == 0) { /* set dump string */ + pp = p + 5; + m = 5; + q = memchr(pp, '\n', e - pp); + if (q == nil || q == pp) { + err = Ebadctl; + break; + } + *q = 0; + nulls = FALSE; + cvttorunes(pp, q - pp, r, &nb, &nr, &nulls); + if (nulls) { + err = "nulls in dump string"; + break; + } + w->dumpstr = runetobyte(r, nr); + m += (q + 1) - pp; + } else if (strncmp(p, "dumpdir ", 8) == 0) { /* set dump directory */ + pp = p + 8; + m = 8; + q = memchr(pp, '\n', e - pp); + if (q == nil || q == pp) { + err = Ebadctl; + break; + } + *q = 0; + nulls = FALSE; + cvttorunes(pp, q - pp, r, &nb, &nr, &nulls); + if (nulls) { + err = "nulls in dump directory string"; + break; + } + w->dumpdir = runetobyte(r, nr); + m += (q + 1) - pp; + } else if (strncmp(p, "delete", 6) == 0) { /* delete for sure */ + colclose(w->col, w, TRUE); + m = 6; + } else if (strncmp(p, "del", 3) == 0) { /* delete, but check dirty */ + if (!winclean(w, TRUE)) { + err = "file dirty"; + break; + } + colclose(w->col, w, TRUE); + m = 3; + } else if (strncmp(p, "get", 3) == 0) { /* get file */ + get(&w->body, nil, nil, FALSE, XXX, nil, 0); + m = 3; + } else if (strncmp(p, "put", 3) == 0) { /* put file */ + put(&w->body, nil, nil, XXX, XXX, nil, 0); + m = 3; + } else if (strncmp(p, "dot=addr", 8) == 0) { /* set dot */ + textcommit(&w->body, TRUE); + clampaddr(w); + w->body.q0 = w->addr.q0; + w->body.q1 = w->addr.q1; + textsetselect(&w->body, w->body.q0, w->body.q1); + settag = TRUE; + m = 8; + } else if (strncmp(p, "addr=dot", 8) == 0) { /* set addr */ + w->addr.q0 = w->body.q0; + w->addr.q1 = w->body.q1; + m = 8; + } else if (strncmp(p, "limit=addr", 10) == 0) { /* set limit */ + textcommit(&w->body, TRUE); + clampaddr(w); + w->limit.q0 = w->addr.q0; + w->limit.q1 = w->addr.q1; + m = 10; + } else if (strncmp(p, "nomark", 6) == 0) { /* turn off automatic marking */ + w->nomark = TRUE; + m = 6; + } else if (strncmp(p, "mark", 4) == 0) { /* mark file */ + seq++; + filemark(w->body.file); + settag = TRUE; + m = 4; + } else if (strncmp(p, "nomenu", 6) == 0) { /* turn off automatic menu */ + w->filemenu = FALSE; + settag = TRUE; + m = 6; + } else if (strncmp(p, "menu", 4) == 0) { /* enable automatic menu */ + w->filemenu = TRUE; + settag = TRUE; + m = 4; + } else if (strncmp(p, "cleartag", 8) == 0) { /* wipe tag right of bar */ + wincleartag(w); + settag = TRUE; + m = 8; + } else { + err = Ebadctl; + break; + } + while (p[m] == '\n') + m++; + } - if(isfbuf) - fbuffree(r); - else - free(r); - if(err) - n = 0; - fc.count = n; - respond(x, &fc, err); - if(settag) - winsettag(w); - if(scrdraw) - textscrdraw(&w->body); + if (isfbuf) + fbuffree(r); + else + free(r); + if (err) + n = 0; + fc.count = n; + respond(x, &fc, err); + if (settag) + winsettag(w); + if (scrdraw) + textscrdraw(&w->body); } -void -xfideventwrite(Xfid *x, Window *w) -{ - Fcall fc; - int m, n; - Rune *r; - char *err, *p, *q; - int isfbuf; - Text *t; - int c; - uint q0, q1; - - err = nil; - isfbuf = TRUE; - if(x->fcall.count < RBUFSIZE) - r = fbufalloc(); - else{ - isfbuf = FALSE; - r = emalloc(x->fcall.count*UTFmax+1); - } - for(n=0; n<x->fcall.count; n+=m){ - p = x->fcall.data+n; - w->owner = *p++; /* disgusting */ - c = *p++; - while(*p == ' ') - p++; - q0 = strtoul(p, &q, 10); - if(q == p) - goto Rescue; - p = q; - while(*p == ' ') - p++; - q1 = strtoul(p, &q, 10); - if(q == p) - goto Rescue; - p = q; - while(*p == ' ') - p++; - if(*p++ != '\n') - goto Rescue; - m = p-(x->fcall.data+n); - if('a'<=c && c<='z') - t = &w->tag; - else if('A'<=c && c<='Z') - t = &w->body; - else - goto Rescue; - if(q0>t->file->b.nc || q1>t->file->b.nc || q0>q1) - goto Rescue; +void xfideventwrite(Xfid* x, Window* w) { + Fcall fc; + int m, n; + Rune* r; + char *err, *p, *q; + int isfbuf; + Text* t; + int c; + uint q0, q1; - qlock(&row.lk); /* just like mousethread */ - switch(c){ - case 'x': - case 'X': - execute(t, q0, q1, TRUE, nil); - break; - case 'l': - case 'L': - look3(t, q0, q1, TRUE); - break; - default: - qunlock(&row.lk); - goto Rescue; - } - qunlock(&row.lk); + err = nil; + isfbuf = TRUE; + if (x->fcall.count < RBUFSIZE) + r = fbufalloc(); + else { + isfbuf = FALSE; + r = emalloc(x->fcall.count * UTFmax + 1); + } + for (n = 0; n < x->fcall.count; n += m) { + p = x->fcall.data + n; + w->owner = *p++; /* disgusting */ + c = *p++; + while (*p == ' ') + p++; + q0 = strtoul(p, &q, 10); + if (q == p) + goto Rescue; + p = q; + while (*p == ' ') + p++; + q1 = strtoul(p, &q, 10); + if (q == p) + goto Rescue; + p = q; + while (*p == ' ') + p++; + if (*p++ != '\n') + goto Rescue; + m = p - (x->fcall.data + n); + if ('a' <= c && c <= 'z') + t = &w->tag; + else if ('A' <= c && c <= 'Z') + t = &w->body; + else + goto Rescue; + if (q0 > t->file->b.nc || q1 > t->file->b.nc || q0 > q1) + goto Rescue; - } + qlock(&row.lk); /* just like mousethread */ + switch (c) { + case 'x': + case 'X': + execute(t, q0, q1, TRUE, nil); + break; + case 'l': + case 'L': + look3(t, q0, q1, TRUE); + break; + default: + qunlock(&row.lk); + goto Rescue; + } + qunlock(&row.lk); + } - Out: - if(isfbuf) - fbuffree(r); - else - free(r); - if(err) - n = 0; - fc.count = n; - respond(x, &fc, err); - return; +Out: + if (isfbuf) + fbuffree(r); + else + free(r); + if (err) + n = 0; + fc.count = n; + respond(x, &fc, err); + return; - Rescue: - err = Ebadevent; - goto Out; +Rescue: + err = Ebadevent; + goto Out; } -void -xfidutfread(Xfid *x, Text *t, uint q1, int qid) -{ - Fcall fc; - Window *w; - Rune *r; - char *b, *b1; - uint q, off, boff; - int m, n, nr, nb; +void xfidutfread(Xfid* x, Text* t, uint q1, int qid) { + Fcall fc; + Window* w; + Rune* r; + char *b, *b1; + uint q, off, boff; + int m, n, nr, nb; - w = t->w; - wincommit(w, t); - off = x->fcall.offset; - r = fbufalloc(); - b = fbufalloc(); - b1 = fbufalloc(); - n = 0; - if(qid==w->utflastqid && off>=w->utflastboff && w->utflastq<=q1){ - boff = w->utflastboff; - q = w->utflastq; - }else{ - /* BUG: stupid code: scan from beginning */ - boff = 0; - q = 0; - } - w->utflastqid = qid; - while(q<q1 && n<x->fcall.count){ - /* - * Updating here avoids partial rune problem: we're always on a - * char boundary. The cost is we will usually do one more read - * than we really need, but that's better than being n^2. - */ - w->utflastboff = boff; - w->utflastq = q; - nr = q1-q; - if(nr > BUFSIZE/UTFmax) - nr = BUFSIZE/UTFmax; - bufread(&t->file->b, q, r, nr); - nb = snprint(b, BUFSIZE+1, "%.*S", nr, r); - if(boff >= off){ - m = nb; - if(boff+m > off+x->fcall.count) - m = off+x->fcall.count - boff; - memmove(b1+n, b, m); - n += m; - }else if(boff+nb > off){ - if(n != 0) - error("bad count in utfrune"); - m = nb - (off-boff); - if(m > x->fcall.count) - m = x->fcall.count; - memmove(b1, b+(off-boff), m); - n += m; - } - boff += nb; - q += nr; - } - fbuffree(r); - fbuffree(b); - fc.count = n; - fc.data = b1; - respond(x, &fc, nil); - fbuffree(b1); + w = t->w; + wincommit(w, t); + off = x->fcall.offset; + r = fbufalloc(); + b = fbufalloc(); + b1 = fbufalloc(); + n = 0; + if (qid == w->utflastqid && off >= w->utflastboff && w->utflastq <= q1) { + boff = w->utflastboff; + q = w->utflastq; + } else { + /* BUG: stupid code: scan from beginning */ + boff = 0; + q = 0; + } + w->utflastqid = qid; + while (q < q1 && n < x->fcall.count) { + /* + * Updating here avoids partial rune problem: we're always on a + * char boundary. The cost is we will usually do one more read + * than we really need, but that's better than being n^2. + */ + w->utflastboff = boff; + w->utflastq = q; + nr = q1 - q; + if (nr > BUFSIZE / UTFmax) + nr = BUFSIZE / UTFmax; + bufread(&t->file->b, q, r, nr); + nb = snprint(b, BUFSIZE + 1, "%.*S", nr, r); + if (boff >= off) { + m = nb; + if (boff + m > off + x->fcall.count) + m = off + x->fcall.count - boff; + memmove(b1 + n, b, m); + n += m; + } else if (boff + nb > off) { + if (n != 0) + error("bad count in utfrune"); + m = nb - (off - boff); + if (m > x->fcall.count) + m = x->fcall.count; + memmove(b1, b + (off - boff), m); + n += m; + } + boff += nb; + q += nr; + } + fbuffree(r); + fbuffree(b); + fc.count = n; + fc.data = b1; + respond(x, &fc, nil); + fbuffree(b1); } -int -xfidruneread(Xfid *x, Text *t, uint q0, uint q1) -{ - Fcall fc; - Window *w; - Rune *r, junk; - char *b, *b1; - uint q, boff; - int i, rw, m, n, nr, nb; +int xfidruneread(Xfid* x, Text* t, uint q0, uint q1) { + Fcall fc; + Window* w; + Rune *r, junk; + char *b, *b1; + uint q, boff; + int i, rw, m, n, nr, nb; - w = t->w; - wincommit(w, t); - r = fbufalloc(); - b = fbufalloc(); - b1 = fbufalloc(); - n = 0; - q = q0; - boff = 0; - while(q<q1 && n<x->fcall.count){ - nr = q1-q; - if(nr > BUFSIZE/UTFmax) - nr = BUFSIZE/UTFmax; - bufread(&t->file->b, q, r, nr); - nb = snprint(b, BUFSIZE+1, "%.*S", nr, r); - m = nb; - if(boff+m > x->fcall.count){ - i = x->fcall.count - boff; - /* copy whole runes only */ - m = 0; - nr = 0; - while(m < i){ - rw = chartorune(&junk, b+m); - if(m+rw > i) - break; - m += rw; - nr++; - } - if(m == 0) - break; - } - memmove(b1+n, b, m); - n += m; - boff += nb; - q += nr; - } - fbuffree(r); - fbuffree(b); - fc.count = n; - fc.data = b1; - respond(x, &fc, nil); - fbuffree(b1); - return q-q0; + w = t->w; + wincommit(w, t); + r = fbufalloc(); + b = fbufalloc(); + b1 = fbufalloc(); + n = 0; + q = q0; + boff = 0; + while (q < q1 && n < x->fcall.count) { + nr = q1 - q; + if (nr > BUFSIZE / UTFmax) + nr = BUFSIZE / UTFmax; + bufread(&t->file->b, q, r, nr); + nb = snprint(b, BUFSIZE + 1, "%.*S", nr, r); + m = nb; + if (boff + m > x->fcall.count) { + i = x->fcall.count - boff; + /* copy whole runes only */ + m = 0; + nr = 0; + while (m < i) { + rw = chartorune(&junk, b + m); + if (m + rw > i) + break; + m += rw; + nr++; + } + if (m == 0) + break; + } + memmove(b1 + n, b, m); + n += m; + boff += nb; + q += nr; + } + fbuffree(r); + fbuffree(b); + fc.count = n; + fc.data = b1; + respond(x, &fc, nil); + fbuffree(b1); + return q - q0; } -void -xfideventread(Xfid *x, Window *w) -{ - Fcall fc; - int i, n; +void xfideventread(Xfid* x, Window* w) { + Fcall fc; + int i, n; - i = 0; - x->flushed = FALSE; - while(w->nevents == 0){ - if(i){ - if(!x->flushed) - respond(x, &fc, "window shut down"); - return; - } - w->eventx = x; - winunlock(w); - recvp(x->c); - winlock(w, 'F'); - i++; - } + i = 0; + x->flushed = FALSE; + while (w->nevents == 0) { + if (i) { + if (!x->flushed) + respond(x, &fc, "window shut down"); + return; + } + w->eventx = x; + winunlock(w); + recvp(x->c); + winlock(w, 'F'); + i++; + } - n = w->nevents; - if(n > x->fcall.count) - n = x->fcall.count; - fc.count = n; - fc.data = w->events; - respond(x, &fc, nil); - w->nevents -= n; - if(w->nevents){ - memmove(w->events, w->events+n, w->nevents); - w->events = erealloc(w->events, w->nevents); - }else{ - free(w->events); - w->events = nil; - } + n = w->nevents; + if (n > x->fcall.count) + n = x->fcall.count; + fc.count = n; + fc.data = w->events; + respond(x, &fc, nil); + w->nevents -= n; + if (w->nevents) { + memmove(w->events, w->events + n, w->nevents); + w->events = erealloc(w->events, w->nevents); + } else { + free(w->events); + w->events = nil; + } } -void -xfidindexread(Xfid *x) -{ - Fcall fc; - int i, j, m, n, nmax, isbuf, cnt, off; - Window *w; - char *b; - Rune *r; - Column *c; +void xfidindexread(Xfid* x) { + Fcall fc; + int i, j, m, n, nmax, isbuf, cnt, off; + Window* w; + char* b; + Rune* r; + Column* c; - qlock(&row.lk); - nmax = 0; - for(j=0; j<row.ncol; j++){ - c = row.col[j]; - for(i=0; i<c->nw; i++){ - w = c->w[i]; - nmax += Ctlsize + w->tag.file->b.nc*UTFmax + 1; - } - } - nmax++; - isbuf = (nmax<=RBUFSIZE); - if(isbuf) - b = (char*)x->buf; - else - b = emalloc(nmax); - r = fbufalloc(); - n = 0; - for(j=0; j<row.ncol; j++){ - c = row.col[j]; - for(i=0; i<c->nw; i++){ - w = c->w[i]; - /* only show the currently active window of a set */ - if(w->body.file->curtext != &w->body) - continue; - winctlprint(w, b+n, 0); - n += Ctlsize; - m = min(RBUFSIZE, w->tag.file->b.nc); - bufread(&w->tag.file->b, 0, r, m); - m = n + snprint(b+n, nmax-n-1, "%.*S", m, r); - while(n<m && b[n]!='\n') - n++; - b[n++] = '\n'; - } - } - qunlock(&row.lk); - off = x->fcall.offset; - cnt = x->fcall.count; - if(off > n) - off = n; - if(off+cnt > n) - cnt = n-off; - fc.count = cnt; - memmove(r, b+off, cnt); - fc.data = (char*)r; - if(!isbuf) - free(b); - respond(x, &fc, nil); - fbuffree(r); + qlock(&row.lk); + nmax = 0; + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + nmax += Ctlsize + w->tag.file->b.nc * UTFmax + 1; + } + } + nmax++; + isbuf = (nmax <= RBUFSIZE); + if (isbuf) + b = (char*)x->buf; + else + b = emalloc(nmax); + r = fbufalloc(); + n = 0; + for (j = 0; j < row.ncol; j++) { + c = row.col[j]; + for (i = 0; i < c->nw; i++) { + w = c->w[i]; + /* only show the currently active window of a set */ + if (w->body.file->curtext != &w->body) + continue; + winctlprint(w, b + n, 0); + n += Ctlsize; + m = min(RBUFSIZE, w->tag.file->b.nc); + bufread(&w->tag.file->b, 0, r, m); + m = n + snprint(b + n, nmax - n - 1, "%.*S", m, r); + while (n < m && b[n] != '\n') + n++; + b[n++] = '\n'; + } + } + qunlock(&row.lk); + off = x->fcall.offset; + cnt = x->fcall.count; + if (off > n) + off = n; + if (off + cnt > n) + cnt = n - off; + fc.count = cnt; + memmove(r, b + off, cnt); + fc.data = (char*)r; + if (!isbuf) + free(b); + respond(x, &fc, nil); + fbuffree(r); }