17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <regexp.h>
117dd7cddfSDavid du Colombier #include <plumb.h>
127dd7cddfSDavid du Colombier #include "dat.h"
137dd7cddfSDavid du Colombier #include "fns.h"
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier Window* openfile(Text*, Expand*);
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier int nuntitled;
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier void
look3(Text * t,uint q0,uint q1,int external)207dd7cddfSDavid du Colombier look3(Text *t, uint q0, uint q1, int external)
217dd7cddfSDavid du Colombier {
227dd7cddfSDavid du Colombier int n, c, f, expanded;
237dd7cddfSDavid du Colombier Text *ct;
247dd7cddfSDavid du Colombier Expand e;
257dd7cddfSDavid du Colombier Rune *r;
267dd7cddfSDavid du Colombier uint p;
277dd7cddfSDavid du Colombier Plumbmsg *m;
287dd7cddfSDavid du Colombier Runestr dir;
297dd7cddfSDavid du Colombier char buf[32];
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier ct = seltext;
327dd7cddfSDavid du Colombier if(ct == nil)
337dd7cddfSDavid du Colombier seltext = t;
347dd7cddfSDavid du Colombier expanded = expand(t, q0, q1, &e);
357dd7cddfSDavid du Colombier if(!external && t->w!=nil && t->w->nopen[QWevent]>0){
367dd7cddfSDavid du Colombier /* send alphanumeric expansion to external client */
377dd7cddfSDavid du Colombier if(expanded == FALSE)
387dd7cddfSDavid du Colombier return;
397dd7cddfSDavid du Colombier f = 0;
407dd7cddfSDavid du Colombier if((e.at!=nil && t->w!=nil) || (e.nname>0 && lookfile(e.name, e.nname)!=nil))
417dd7cddfSDavid du Colombier f = 1; /* acme can do it without loading a file */
427dd7cddfSDavid du Colombier if(q0!=e.q0 || q1!=e.q1)
437dd7cddfSDavid du Colombier f |= 2; /* second (post-expand) message follows */
447dd7cddfSDavid du Colombier if(e.nname)
457dd7cddfSDavid du Colombier f |= 4; /* it's a file name */
467dd7cddfSDavid du Colombier c = 'l';
477dd7cddfSDavid du Colombier if(t->what == Body)
487dd7cddfSDavid du Colombier c = 'L';
497dd7cddfSDavid du Colombier n = q1-q0;
507dd7cddfSDavid du Colombier if(n <= EVENTSIZE){
517dd7cddfSDavid du Colombier r = runemalloc(n);
527dd7cddfSDavid du Colombier bufread(t->file, q0, r, n);
537dd7cddfSDavid du Colombier winevent(t->w, "%c%d %d %d %d %.*S\n", c, q0, q1, f, n, n, r);
547dd7cddfSDavid du Colombier free(r);
557dd7cddfSDavid du Colombier }else
567dd7cddfSDavid du Colombier winevent(t->w, "%c%d %d %d 0 \n", c, q0, q1, f, n);
577dd7cddfSDavid du Colombier if(q0==e.q0 && q1==e.q1)
587dd7cddfSDavid du Colombier return;
597dd7cddfSDavid du Colombier if(e.nname){
607dd7cddfSDavid du Colombier n = e.nname;
617dd7cddfSDavid du Colombier if(e.a1 > e.a0)
627dd7cddfSDavid du Colombier n += 1+(e.a1-e.a0);
637dd7cddfSDavid du Colombier r = runemalloc(n);
647dd7cddfSDavid du Colombier runemove(r, e.name, e.nname);
657dd7cddfSDavid du Colombier if(e.a1 > e.a0){
667dd7cddfSDavid du Colombier r[e.nname] = ':';
677dd7cddfSDavid du Colombier bufread(e.at->file, e.a0, r+e.nname+1, e.a1-e.a0);
687dd7cddfSDavid du Colombier }
697dd7cddfSDavid du Colombier }else{
707dd7cddfSDavid du Colombier n = e.q1 - e.q0;
717dd7cddfSDavid du Colombier r = runemalloc(n);
727dd7cddfSDavid du Colombier bufread(t->file, e.q0, r, n);
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier f &= ~2;
757dd7cddfSDavid du Colombier if(n <= EVENTSIZE)
767dd7cddfSDavid du Colombier winevent(t->w, "%c%d %d %d %d %.*S\n", c, e.q0, e.q1, f, n, n, r);
777dd7cddfSDavid du Colombier else
787dd7cddfSDavid du Colombier winevent(t->w, "%c%d %d %d 0 \n", c, e.q0, e.q1, f, n);
797dd7cddfSDavid du Colombier free(r);
807dd7cddfSDavid du Colombier goto Return;
817dd7cddfSDavid du Colombier }
827dd7cddfSDavid du Colombier if(plumbsendfd >= 0){
837dd7cddfSDavid du Colombier /* send whitespace-delimited word to plumber */
847dd7cddfSDavid du Colombier m = emalloc(sizeof(Plumbmsg));
8559cc4ca5SDavid du Colombier m->src = estrdup("acme");
867dd7cddfSDavid du Colombier m->dst = nil;
877dd7cddfSDavid du Colombier dir = dirname(t, nil, 0);
887dd7cddfSDavid du Colombier if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
897dd7cddfSDavid du Colombier free(dir.r);
907dd7cddfSDavid du Colombier dir.r = nil;
917dd7cddfSDavid du Colombier dir.nr = 0;
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier if(dir.nr == 0)
9459cc4ca5SDavid du Colombier m->wdir = estrdup(wdir);
957dd7cddfSDavid du Colombier else
967dd7cddfSDavid du Colombier m->wdir = runetobyte(dir.r, dir.nr);
977dd7cddfSDavid du Colombier free(dir.r);
9859cc4ca5SDavid du Colombier m->type = estrdup("text");
997dd7cddfSDavid du Colombier m->attr = nil;
1007dd7cddfSDavid du Colombier buf[0] = '\0';
1017dd7cddfSDavid du Colombier if(q1 == q0){
1027dd7cddfSDavid du Colombier if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
1037dd7cddfSDavid du Colombier q0 = t->q0;
1047dd7cddfSDavid du Colombier q1 = t->q1;
1057dd7cddfSDavid du Colombier }else{
1067dd7cddfSDavid du Colombier p = q0;
1077dd7cddfSDavid du Colombier while(q0>0 && (c=tgetc(t, q0-1))!=' ' && c!='\t' && c!='\n')
1087dd7cddfSDavid du Colombier q0--;
1097dd7cddfSDavid du Colombier while(q1<t->file->nc && (c=tgetc(t, q1))!=' ' && c!='\t' && c!='\n')
1107dd7cddfSDavid du Colombier q1++;
1117dd7cddfSDavid du Colombier if(q1 == q0){
1127dd7cddfSDavid du Colombier plumbfree(m);
1137dd7cddfSDavid du Colombier goto Return;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier sprint(buf, "click=%d", p-q0);
1167dd7cddfSDavid du Colombier m->attr = plumbunpackattr(buf);
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier }
1197dd7cddfSDavid du Colombier r = runemalloc(q1-q0);
1207dd7cddfSDavid du Colombier bufread(t->file, q0, r, q1-q0);
1217dd7cddfSDavid du Colombier m->data = runetobyte(r, q1-q0);
1227dd7cddfSDavid du Colombier m->ndata = strlen(m->data);
1237dd7cddfSDavid du Colombier free(r);
1249a747e4fSDavid du Colombier if(m->ndata<messagesize-1024 && plumbsend(plumbsendfd, m) >= 0){
1257dd7cddfSDavid du Colombier plumbfree(m);
1267dd7cddfSDavid du Colombier goto Return;
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier plumbfree(m);
1297dd7cddfSDavid du Colombier /* plumber failed to match; fall through */
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier /* interpret alphanumeric string ourselves */
1337dd7cddfSDavid du Colombier if(expanded == FALSE)
1347dd7cddfSDavid du Colombier return;
1357dd7cddfSDavid du Colombier if(e.name || e.at)
1367dd7cddfSDavid du Colombier openfile(t, &e);
1377dd7cddfSDavid du Colombier else{
1387dd7cddfSDavid du Colombier if(t->w == nil)
1397dd7cddfSDavid du Colombier return;
1407dd7cddfSDavid du Colombier ct = &t->w->body;
1417dd7cddfSDavid du Colombier if(t->w != ct->w)
1427dd7cddfSDavid du Colombier winlock(ct->w, 'M');
1437dd7cddfSDavid du Colombier if(t == ct)
1447dd7cddfSDavid du Colombier textsetselect(ct, e.q1, e.q1);
1457dd7cddfSDavid du Colombier n = e.q1 - e.q0;
1467dd7cddfSDavid du Colombier r = runemalloc(n);
1477dd7cddfSDavid du Colombier bufread(t->file, e.q0, r, n);
1487dd7cddfSDavid du Colombier if(search(ct, r, n) && e.jump)
1497dd7cddfSDavid du Colombier moveto(mousectl, addpt(frptofchar(ct, ct->p0), Pt(4, ct->font->height-4)));
1507dd7cddfSDavid du Colombier if(t->w != ct->w)
1517dd7cddfSDavid du Colombier winunlock(ct->w);
1527dd7cddfSDavid du Colombier free(r);
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier Return:
1567dd7cddfSDavid du Colombier free(e.name);
1577dd7cddfSDavid du Colombier free(e.bname);
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier int
plumbgetc(void * a,uint n)1617dd7cddfSDavid du Colombier plumbgetc(void *a, uint n)
1627dd7cddfSDavid du Colombier {
1637dd7cddfSDavid du Colombier Rune *r;
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier r = a;
166c93608ccSDavid du Colombier if(n>runestrlen(r))
1677dd7cddfSDavid du Colombier return 0;
1687dd7cddfSDavid du Colombier return r[n];
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier
1717dd7cddfSDavid du Colombier void
plumblook(Plumbmsg * m)1727dd7cddfSDavid du Colombier plumblook(Plumbmsg *m)
1737dd7cddfSDavid du Colombier {
1747dd7cddfSDavid du Colombier Expand e;
1757dd7cddfSDavid du Colombier char *addr;
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier if(m->ndata >= BUFSIZE){
1787dd7cddfSDavid du Colombier warning(nil, "insanely long file name (%d bytes) in plumb message (%.32s...)\n", m->ndata, m->data);
1797dd7cddfSDavid du Colombier return;
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier e.q0 = 0;
1827dd7cddfSDavid du Colombier e.q1 = 0;
1837dd7cddfSDavid du Colombier if(m->data[0] == '\0')
1847dd7cddfSDavid du Colombier return;
1857dd7cddfSDavid du Colombier e.ar = nil;
1867dd7cddfSDavid du Colombier e.bname = m->data;
1877dd7cddfSDavid du Colombier e.name = bytetorune(e.bname, &e.nname);
1887dd7cddfSDavid du Colombier e.jump = TRUE;
1897dd7cddfSDavid du Colombier e.a0 = 0;
1907dd7cddfSDavid du Colombier e.a1 = 0;
1917dd7cddfSDavid du Colombier addr = plumblookup(m->attr, "addr");
1927dd7cddfSDavid du Colombier if(addr != nil){
1937dd7cddfSDavid du Colombier e.ar = bytetorune(addr, &e.a1);
1947dd7cddfSDavid du Colombier e.agetc = plumbgetc;
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier openfile(nil, &e);
1977dd7cddfSDavid du Colombier free(e.name);
1987dd7cddfSDavid du Colombier free(e.at);
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier void
plumbshow(Plumbmsg * m)2027dd7cddfSDavid du Colombier plumbshow(Plumbmsg *m)
2037dd7cddfSDavid du Colombier {
2047dd7cddfSDavid du Colombier Window *w;
2057dd7cddfSDavid du Colombier Rune rb[256], *r;
2067dd7cddfSDavid du Colombier int nb, nr;
2077dd7cddfSDavid du Colombier Runestr rs;
2087dd7cddfSDavid du Colombier char *name, *p, namebuf[16];
2097dd7cddfSDavid du Colombier
210d9306527SDavid du Colombier w = makenewwindow(nil);
2117dd7cddfSDavid du Colombier name = plumblookup(m->attr, "filename");
2127dd7cddfSDavid du Colombier if(name == nil){
2137dd7cddfSDavid du Colombier name = namebuf;
2147dd7cddfSDavid du Colombier nuntitled++;
2157dd7cddfSDavid du Colombier snprint(namebuf, sizeof namebuf, "Untitled-%d", nuntitled);
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier p = nil;
2187dd7cddfSDavid du Colombier if(name[0]!='/' && m->wdir!=nil && m->wdir[0]!='\0'){
2197dd7cddfSDavid du Colombier nb = strlen(m->wdir) + 1 + strlen(name) + 1;
2207dd7cddfSDavid du Colombier p = emalloc(nb);
2217dd7cddfSDavid du Colombier snprint(p, nb, "%s/%s", m->wdir, name);
2227dd7cddfSDavid du Colombier name = p;
2237dd7cddfSDavid du Colombier }
2247dd7cddfSDavid du Colombier cvttorunes(name, strlen(name), rb, &nb, &nr, nil);
2257dd7cddfSDavid du Colombier free(p);
2267dd7cddfSDavid du Colombier rs = cleanrname((Runestr){rb, nr});
2277dd7cddfSDavid du Colombier winsetname(w, rs.r, rs.nr);
2287dd7cddfSDavid du Colombier r = runemalloc(m->ndata);
2297dd7cddfSDavid du Colombier cvttorunes(m->data, m->ndata, r, &nb, &nr, nil);
2307dd7cddfSDavid du Colombier textinsert(&w->body, 0, r, nr, TRUE);
2319a747e4fSDavid du Colombier free(r);
2327dd7cddfSDavid du Colombier w->body.file->mod = FALSE;
2337dd7cddfSDavid du Colombier w->dirty = FALSE;
2347dd7cddfSDavid du Colombier winsettag(w);
2357dd7cddfSDavid du Colombier textscrdraw(&w->body);
2367dd7cddfSDavid du Colombier textsetselect(&w->tag, w->tag.file->nc, w->tag.file->nc);
2377dd7cddfSDavid du Colombier }
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier int
search(Text * ct,Rune * r,uint n)2407dd7cddfSDavid du Colombier search(Text *ct, Rune *r, uint n)
2417dd7cddfSDavid du Colombier {
2427dd7cddfSDavid du Colombier uint q, nb, maxn;
2437dd7cddfSDavid du Colombier int around;
2447dd7cddfSDavid du Colombier Rune *s, *b, *c;
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier if(n==0 || n>ct->file->nc)
2477dd7cddfSDavid du Colombier return FALSE;
2487dd7cddfSDavid du Colombier if(2*n > RBUFSIZE){
2497dd7cddfSDavid du Colombier warning(nil, "string too long\n");
2507dd7cddfSDavid du Colombier return FALSE;
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier maxn = max(2*n, RBUFSIZE);
2537dd7cddfSDavid du Colombier s = fbufalloc();
2547dd7cddfSDavid du Colombier b = s;
2557dd7cddfSDavid du Colombier nb = 0;
2567dd7cddfSDavid du Colombier b[nb] = 0;
2577dd7cddfSDavid du Colombier around = 0;
2587dd7cddfSDavid du Colombier q = ct->q1;
2597dd7cddfSDavid du Colombier for(;;){
2607dd7cddfSDavid du Colombier if(q >= ct->file->nc){
2617dd7cddfSDavid du Colombier q = 0;
2627dd7cddfSDavid du Colombier around = 1;
2637dd7cddfSDavid du Colombier nb = 0;
2647dd7cddfSDavid du Colombier b[nb] = 0;
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier if(nb > 0){
26759cc4ca5SDavid du Colombier c = runestrchr(b, r[0]);
2687dd7cddfSDavid du Colombier if(c == nil){
2697dd7cddfSDavid du Colombier q += nb;
2707dd7cddfSDavid du Colombier nb = 0;
2717dd7cddfSDavid du Colombier b[nb] = 0;
2727dd7cddfSDavid du Colombier if(around && q>=ct->q1)
2737dd7cddfSDavid du Colombier break;
2747dd7cddfSDavid du Colombier continue;
2757dd7cddfSDavid du Colombier }
2767dd7cddfSDavid du Colombier q += (c-b);
2777dd7cddfSDavid du Colombier nb -= (c-b);
2787dd7cddfSDavid du Colombier b = c;
2797dd7cddfSDavid du Colombier }
2807dd7cddfSDavid du Colombier /* reload if buffer covers neither string nor rest of file */
2817dd7cddfSDavid du Colombier if(nb<n && nb!=ct->file->nc-q){
2827dd7cddfSDavid du Colombier nb = ct->file->nc-q;
2837dd7cddfSDavid du Colombier if(nb >= maxn)
2847dd7cddfSDavid du Colombier nb = maxn-1;
2857dd7cddfSDavid du Colombier bufread(ct->file, q, s, nb);
2867dd7cddfSDavid du Colombier b = s;
2877dd7cddfSDavid du Colombier b[nb] = '\0';
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier /* this runeeq is fishy but the null at b[nb] makes it safe */
2907dd7cddfSDavid du Colombier if(runeeq(b, n, r, n)==TRUE){
2917dd7cddfSDavid du Colombier if(ct->w){
2929a747e4fSDavid du Colombier textshow(ct, q, q+n, 1);
2937dd7cddfSDavid du Colombier winsettag(ct->w);
2947dd7cddfSDavid du Colombier }else{
2957dd7cddfSDavid du Colombier ct->q0 = q;
2967dd7cddfSDavid du Colombier ct->q1 = q+n;
2977dd7cddfSDavid du Colombier }
2987dd7cddfSDavid du Colombier seltext = ct;
2997dd7cddfSDavid du Colombier fbuffree(s);
3007dd7cddfSDavid du Colombier return TRUE;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier --nb;
3037dd7cddfSDavid du Colombier b++;
3047dd7cddfSDavid du Colombier q++;
305*a4aad0eeSDavid du Colombier if(around && q>=ct->q1)
306*a4aad0eeSDavid du Colombier break;
3077dd7cddfSDavid du Colombier }
3087dd7cddfSDavid du Colombier fbuffree(s);
3097dd7cddfSDavid du Colombier return FALSE;
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier int
isfilec(Rune r)3137dd7cddfSDavid du Colombier isfilec(Rune r)
3147dd7cddfSDavid du Colombier {
3157dd7cddfSDavid du Colombier if(isalnum(r))
3167dd7cddfSDavid du Colombier return TRUE;
31759cc4ca5SDavid du Colombier if(runestrchr(L".-+/:", r))
3187dd7cddfSDavid du Colombier return TRUE;
3197dd7cddfSDavid du Colombier return FALSE;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier
322fe853e23SDavid du Colombier /* Runestr wrapper for cleanname */
3237dd7cddfSDavid du Colombier Runestr
cleanrname(Runestr rs)3247dd7cddfSDavid du Colombier cleanrname(Runestr rs)
3257dd7cddfSDavid du Colombier {
326b1ffb6adSDavid du Colombier char *s;
327b1ffb6adSDavid du Colombier int nb, nulls;
3287dd7cddfSDavid du Colombier
329b1ffb6adSDavid du Colombier s = runetobyte(rs.r, rs.nr);
330b1ffb6adSDavid du Colombier cleanname(s);
331b1ffb6adSDavid du Colombier cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls);
332b1ffb6adSDavid du Colombier free(s);
333b1ffb6adSDavid du Colombier return rs;
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier
3367dd7cddfSDavid du Colombier Runestr
includefile(Rune * dir,Rune * file,int nfile)3377dd7cddfSDavid du Colombier includefile(Rune *dir, Rune *file, int nfile)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier int m, n;
3407dd7cddfSDavid du Colombier char *a;
3417dd7cddfSDavid du Colombier Rune *r;
3427dd7cddfSDavid du Colombier
3437dd7cddfSDavid du Colombier m = runestrlen(dir);
3447dd7cddfSDavid du Colombier a = emalloc((m+1+nfile)*UTFmax+1);
3457dd7cddfSDavid du Colombier sprint(a, "%S/%.*S", dir, nfile, file);
3467dd7cddfSDavid du Colombier n = access(a, 0);
3477dd7cddfSDavid du Colombier free(a);
3487dd7cddfSDavid du Colombier if(n < 0)
3497dd7cddfSDavid du Colombier return (Runestr){nil, 0};
3507dd7cddfSDavid du Colombier r = runemalloc(m+1+nfile);
3517dd7cddfSDavid du Colombier runemove(r, dir, m);
3527dd7cddfSDavid du Colombier runemove(r+m, L"/", 1);
3537dd7cddfSDavid du Colombier runemove(r+m+1, file, nfile);
3547dd7cddfSDavid du Colombier free(file);
3557dd7cddfSDavid du Colombier return cleanrname((Runestr){r, m+1+nfile});
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier static Rune *objdir;
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier Runestr
includename(Text * t,Rune * r,int n)3617dd7cddfSDavid du Colombier includename(Text *t, Rune *r, int n)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier Window *w;
3647dd7cddfSDavid du Colombier char buf[128];
3657dd7cddfSDavid du Colombier Runestr file;
3667dd7cddfSDavid du Colombier int i;
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier if(objdir==nil && objtype!=nil){
3697dd7cddfSDavid du Colombier sprint(buf, "/%s/include", objtype);
3707dd7cddfSDavid du Colombier objdir = bytetorune(buf, &i);
3717dd7cddfSDavid du Colombier objdir = runerealloc(objdir, i+1);
3727dd7cddfSDavid du Colombier objdir[i] = '\0';
3737dd7cddfSDavid du Colombier }
3747dd7cddfSDavid du Colombier
3757dd7cddfSDavid du Colombier w = t->w;
3767dd7cddfSDavid du Colombier if(n==0 || r[0]=='/' || w==nil)
3777dd7cddfSDavid du Colombier goto Rescue;
3787dd7cddfSDavid du Colombier if(n>2 && r[0]=='.' && r[1]=='/')
3797dd7cddfSDavid du Colombier goto Rescue;
3807dd7cddfSDavid du Colombier file.r = nil;
3817dd7cddfSDavid du Colombier file.nr = 0;
3827dd7cddfSDavid du Colombier for(i=0; i<w->nincl && file.r==nil; i++)
3837dd7cddfSDavid du Colombier file = includefile(w->incl[i], r, n);
3847dd7cddfSDavid du Colombier
3857dd7cddfSDavid du Colombier if(file.r == nil)
3867dd7cddfSDavid du Colombier file = includefile(L"/sys/include", r, n);
3877dd7cddfSDavid du Colombier if(file.r==nil && objdir!=nil)
3887dd7cddfSDavid du Colombier file = includefile(objdir, r, n);
3897dd7cddfSDavid du Colombier if(file.r == nil)
3907dd7cddfSDavid du Colombier goto Rescue;
3917dd7cddfSDavid du Colombier return file;
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier Rescue:
3947dd7cddfSDavid du Colombier return (Runestr){r, n};
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier Runestr
dirname(Text * t,Rune * r,int n)3987dd7cddfSDavid du Colombier dirname(Text *t, Rune *r, int n)
3997dd7cddfSDavid du Colombier {
4007dd7cddfSDavid du Colombier Rune *b, c;
4017dd7cddfSDavid du Colombier uint m, nt;
4027dd7cddfSDavid du Colombier int slash;
4037dd7cddfSDavid du Colombier Runestr tmp;
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier b = nil;
40659cc4ca5SDavid du Colombier if(t==nil || t->w==nil)
4077dd7cddfSDavid du Colombier goto Rescue;
4087dd7cddfSDavid du Colombier nt = t->w->tag.file->nc;
4097dd7cddfSDavid du Colombier if(nt == 0)
4107dd7cddfSDavid du Colombier goto Rescue;
4117dd7cddfSDavid du Colombier if(n>=1 && r[0]=='/')
4127dd7cddfSDavid du Colombier goto Rescue;
4137dd7cddfSDavid du Colombier b = runemalloc(nt+n+1);
4147dd7cddfSDavid du Colombier bufread(t->w->tag.file, 0, b, nt);
4157dd7cddfSDavid du Colombier slash = -1;
4167dd7cddfSDavid du Colombier for(m=0; m<nt; m++){
4177dd7cddfSDavid du Colombier c = b[m];
4187dd7cddfSDavid du Colombier if(c == '/')
4197dd7cddfSDavid du Colombier slash = m;
4207dd7cddfSDavid du Colombier if(c==' ' || c=='\t')
4217dd7cddfSDavid du Colombier break;
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier if(slash < 0)
4247dd7cddfSDavid du Colombier goto Rescue;
4257dd7cddfSDavid du Colombier runemove(b+slash+1, r, n);
4267dd7cddfSDavid du Colombier free(r);
4277dd7cddfSDavid du Colombier return cleanrname((Runestr){b, slash+1+n});
4287dd7cddfSDavid du Colombier
4297dd7cddfSDavid du Colombier Rescue:
4307dd7cddfSDavid du Colombier free(b);
4317dd7cddfSDavid du Colombier tmp = (Runestr){r, n};
4327dd7cddfSDavid du Colombier if(r)
4337dd7cddfSDavid du Colombier return cleanrname(tmp);
4347dd7cddfSDavid du Colombier return tmp;
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier
4377dd7cddfSDavid du Colombier int
expandfile(Text * t,uint q0,uint q1,Expand * e)4387dd7cddfSDavid du Colombier expandfile(Text *t, uint q0, uint q1, Expand *e)
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier int i, n, nname, colon, eval;
4417dd7cddfSDavid du Colombier uint amin, amax;
4427dd7cddfSDavid du Colombier Rune *r, c;
4437dd7cddfSDavid du Colombier Window *w;
4447dd7cddfSDavid du Colombier Runestr rs;
4457dd7cddfSDavid du Colombier
4467dd7cddfSDavid du Colombier amax = q1;
4477dd7cddfSDavid du Colombier if(q1 == q0){
4487dd7cddfSDavid du Colombier colon = -1;
4497dd7cddfSDavid du Colombier while(q1<t->file->nc && isfilec(c=textreadc(t, q1))){
4507dd7cddfSDavid du Colombier if(c == ':'){
4517dd7cddfSDavid du Colombier colon = q1;
4527dd7cddfSDavid du Colombier break;
4537dd7cddfSDavid du Colombier }
4547dd7cddfSDavid du Colombier q1++;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier while(q0>0 && (isfilec(c=textreadc(t, q0-1)) || isaddrc(c) || isregexc(c))){
4577dd7cddfSDavid du Colombier q0--;
4587dd7cddfSDavid du Colombier if(colon<0 && c==':')
4597dd7cddfSDavid du Colombier colon = q0;
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier /*
4627dd7cddfSDavid du Colombier * if it looks like it might begin file: , consume address chars after :
4637dd7cddfSDavid du Colombier * otherwise terminate expansion at :
4647dd7cddfSDavid du Colombier */
4657dd7cddfSDavid du Colombier if(colon >= 0){
4667dd7cddfSDavid du Colombier q1 = colon;
4677dd7cddfSDavid du Colombier if(colon<t->file->nc-1 && isaddrc(textreadc(t, colon+1))){
4687dd7cddfSDavid du Colombier q1 = colon+1;
4698d724f71SDavid du Colombier while(q1<t->file->nc && isaddrc(textreadc(t, q1)))
4707dd7cddfSDavid du Colombier q1++;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier }
4737dd7cddfSDavid du Colombier if(q1 > q0)
4747dd7cddfSDavid du Colombier if(colon >= 0){ /* stop at white space */
4757dd7cddfSDavid du Colombier for(amax=colon+1; amax<t->file->nc; amax++)
4767dd7cddfSDavid du Colombier if((c=textreadc(t, amax))==' ' || c=='\t' || c=='\n')
4777dd7cddfSDavid du Colombier break;
4787dd7cddfSDavid du Colombier }else
4797dd7cddfSDavid du Colombier amax = t->file->nc;
4807dd7cddfSDavid du Colombier }
4817dd7cddfSDavid du Colombier amin = amax;
4827dd7cddfSDavid du Colombier e->q0 = q0;
4837dd7cddfSDavid du Colombier e->q1 = q1;
4847dd7cddfSDavid du Colombier n = q1-q0;
4857dd7cddfSDavid du Colombier if(n == 0)
4867dd7cddfSDavid du Colombier return FALSE;
4877dd7cddfSDavid du Colombier /* see if it's a file name */
4887dd7cddfSDavid du Colombier r = runemalloc(n);
4897dd7cddfSDavid du Colombier bufread(t->file, q0, r, n);
4907dd7cddfSDavid du Colombier /* first, does it have bad chars? */
4917dd7cddfSDavid du Colombier nname = -1;
4927dd7cddfSDavid du Colombier for(i=0; i<n; i++){
4937dd7cddfSDavid du Colombier c = r[i];
4947dd7cddfSDavid du Colombier if(c==':' && nname<0){
4957dd7cddfSDavid du Colombier if(q0+i+1<t->file->nc && (i==n-1 || isaddrc(textreadc(t, q0+i+1))))
4967dd7cddfSDavid du Colombier amin = q0+i;
4977dd7cddfSDavid du Colombier else
4987dd7cddfSDavid du Colombier goto Isntfile;
4997dd7cddfSDavid du Colombier nname = i;
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier }
5027dd7cddfSDavid du Colombier if(nname == -1)
5037dd7cddfSDavid du Colombier nname = n;
5047dd7cddfSDavid du Colombier for(i=0; i<nname; i++)
5057dd7cddfSDavid du Colombier if(!isfilec(r[i]))
5067dd7cddfSDavid du Colombier goto Isntfile;
5077dd7cddfSDavid du Colombier /*
5087dd7cddfSDavid du Colombier * See if it's a file name in <>, and turn that into an include
5097dd7cddfSDavid du Colombier * file name if so. Should probably do it for "" too, but that's not
5107dd7cddfSDavid du Colombier * restrictive enough syntax and checking for a #include earlier on the
5117dd7cddfSDavid du Colombier * line would be silly.
5127dd7cddfSDavid du Colombier */
5137dd7cddfSDavid du Colombier if(q0>0 && textreadc(t, q0-1)=='<' && q1<t->file->nc && textreadc(t, q1)=='>'){
5147dd7cddfSDavid du Colombier rs = includename(t, r, nname);
5157dd7cddfSDavid du Colombier r = rs.r;
5167dd7cddfSDavid du Colombier nname = rs.nr;
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier else if(amin == q0)
5197dd7cddfSDavid du Colombier goto Isfile;
5207dd7cddfSDavid du Colombier else{
5217dd7cddfSDavid du Colombier rs = dirname(t, r, nname);
5227dd7cddfSDavid du Colombier r = rs.r;
5237dd7cddfSDavid du Colombier nname = rs.nr;
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier e->bname = runetobyte(r, nname);
5267dd7cddfSDavid du Colombier /* if it's already a window name, it's a file */
5277dd7cddfSDavid du Colombier w = lookfile(r, nname);
5287dd7cddfSDavid du Colombier if(w != nil)
5297dd7cddfSDavid du Colombier goto Isfile;
5307dd7cddfSDavid du Colombier /* if it's the name of a file, it's a file */
5317dd7cddfSDavid du Colombier if(access(e->bname, 0) < 0){
5327dd7cddfSDavid du Colombier free(e->bname);
5337dd7cddfSDavid du Colombier e->bname = nil;
5347dd7cddfSDavid du Colombier goto Isntfile;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier Isfile:
5387dd7cddfSDavid du Colombier e->name = r;
5397dd7cddfSDavid du Colombier e->nname = nname;
5407dd7cddfSDavid du Colombier e->at = t;
5417dd7cddfSDavid du Colombier e->a0 = amin+1;
5427dd7cddfSDavid du Colombier eval = FALSE;
54359cc4ca5SDavid du Colombier address(nil, nil, (Range){-1,-1}, (Range){0, 0}, t, e->a0, amax, tgetc, &eval, (uint*)&e->a1);
5447dd7cddfSDavid du Colombier return TRUE;
5457dd7cddfSDavid du Colombier
5467dd7cddfSDavid du Colombier Isntfile:
5477dd7cddfSDavid du Colombier free(r);
5487dd7cddfSDavid du Colombier return FALSE;
5497dd7cddfSDavid du Colombier }
5507dd7cddfSDavid du Colombier
5517dd7cddfSDavid du Colombier int
expand(Text * t,uint q0,uint q1,Expand * e)5527dd7cddfSDavid du Colombier expand(Text *t, uint q0, uint q1, Expand *e)
5537dd7cddfSDavid du Colombier {
5547dd7cddfSDavid du Colombier memset(e, 0, sizeof *e);
5557dd7cddfSDavid du Colombier e->agetc = tgetc;
5567dd7cddfSDavid du Colombier /* if in selection, choose selection */
5577dd7cddfSDavid du Colombier e->jump = TRUE;
5587dd7cddfSDavid du Colombier if(q1==q0 && t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
5597dd7cddfSDavid du Colombier q0 = t->q0;
5607dd7cddfSDavid du Colombier q1 = t->q1;
5617dd7cddfSDavid du Colombier if(t->what == Tag)
5627dd7cddfSDavid du Colombier e->jump = FALSE;
5637dd7cddfSDavid du Colombier }
5647dd7cddfSDavid du Colombier
5657dd7cddfSDavid du Colombier if(expandfile(t, q0, q1, e))
5667dd7cddfSDavid du Colombier return TRUE;
5677dd7cddfSDavid du Colombier
5687dd7cddfSDavid du Colombier if(q0 == q1){
5697dd7cddfSDavid du Colombier while(q1<t->file->nc && isalnum(textreadc(t, q1)))
5707dd7cddfSDavid du Colombier q1++;
5717dd7cddfSDavid du Colombier while(q0>0 && isalnum(textreadc(t, q0-1)))
5727dd7cddfSDavid du Colombier q0--;
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier e->q0 = q0;
5757dd7cddfSDavid du Colombier e->q1 = q1;
5767dd7cddfSDavid du Colombier return q1 > q0;
5777dd7cddfSDavid du Colombier }
5787dd7cddfSDavid du Colombier
5797dd7cddfSDavid du Colombier Window*
lookfile(Rune * s,int n)5807dd7cddfSDavid du Colombier lookfile(Rune *s, int n)
5817dd7cddfSDavid du Colombier {
5827dd7cddfSDavid du Colombier int i, j, k;
5837dd7cddfSDavid du Colombier Window *w;
5847dd7cddfSDavid du Colombier Column *c;
5857dd7cddfSDavid du Colombier Text *t;
5867dd7cddfSDavid du Colombier
5877dd7cddfSDavid du Colombier /* avoid terminal slash on directories */
5887dd7cddfSDavid du Colombier if(n>1 && s[n-1] == '/')
5897dd7cddfSDavid du Colombier --n;
5907dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){
5917dd7cddfSDavid du Colombier c = row.col[j];
5927dd7cddfSDavid du Colombier for(i=0; i<c->nw; i++){
5937dd7cddfSDavid du Colombier w = c->w[i];
5947dd7cddfSDavid du Colombier t = &w->body;
5957dd7cddfSDavid du Colombier k = t->file->nname;
596106486e8SDavid du Colombier if(k>1 && t->file->name[k-1] == '/')
5977dd7cddfSDavid du Colombier k--;
5987dd7cddfSDavid du Colombier if(runeeq(t->file->name, k, s, n)){
5997dd7cddfSDavid du Colombier w = w->body.file->curtext->w;
6007dd7cddfSDavid du Colombier if(w->col != nil) /* protect against race deleting w */
6017dd7cddfSDavid du Colombier return w;
6027dd7cddfSDavid du Colombier }
6037dd7cddfSDavid du Colombier }
6047dd7cddfSDavid du Colombier }
6057dd7cddfSDavid du Colombier return nil;
6067dd7cddfSDavid du Colombier }
6077dd7cddfSDavid du Colombier
6087dd7cddfSDavid du Colombier Window*
lookid(int id,int dump)6097dd7cddfSDavid du Colombier lookid(int id, int dump)
6107dd7cddfSDavid du Colombier {
6117dd7cddfSDavid du Colombier int i, j;
6127dd7cddfSDavid du Colombier Window *w;
6137dd7cddfSDavid du Colombier Column *c;
6147dd7cddfSDavid du Colombier
6157dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){
6167dd7cddfSDavid du Colombier c = row.col[j];
6177dd7cddfSDavid du Colombier for(i=0; i<c->nw; i++){
6187dd7cddfSDavid du Colombier w = c->w[i];
6197dd7cddfSDavid du Colombier if(dump && w->dumpid == id)
6207dd7cddfSDavid du Colombier return w;
6217dd7cddfSDavid du Colombier if(!dump && w->id == id)
6227dd7cddfSDavid du Colombier return w;
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier }
6257dd7cddfSDavid du Colombier return nil;
6267dd7cddfSDavid du Colombier }
6277dd7cddfSDavid du Colombier
6287dd7cddfSDavid du Colombier
6297dd7cddfSDavid du Colombier Window*
openfile(Text * t,Expand * e)6307dd7cddfSDavid du Colombier openfile(Text *t, Expand *e)
6317dd7cddfSDavid du Colombier {
6327dd7cddfSDavid du Colombier Range r;
6337dd7cddfSDavid du Colombier Window *w, *ow;
6347dd7cddfSDavid du Colombier int eval, i, n;
6357dd7cddfSDavid du Colombier Rune *rp;
6367dd7cddfSDavid du Colombier uint dummy;
6377dd7cddfSDavid du Colombier
6387dd7cddfSDavid du Colombier if(e->nname == 0){
6397dd7cddfSDavid du Colombier w = t->w;
6407dd7cddfSDavid du Colombier if(w == nil)
6417dd7cddfSDavid du Colombier return nil;
6427dd7cddfSDavid du Colombier }else
6437dd7cddfSDavid du Colombier w = lookfile(e->name, e->nname);
6447dd7cddfSDavid du Colombier if(w){
6457dd7cddfSDavid du Colombier t = &w->body;
6467dd7cddfSDavid du Colombier if(!t->col->safe && t->maxlines==0) /* window is obscured by full-column window */
6477dd7cddfSDavid du Colombier colgrow(t->col, t->col->w[0], 1);
6487dd7cddfSDavid du Colombier }else{
6497dd7cddfSDavid du Colombier ow = nil;
6507dd7cddfSDavid du Colombier if(t)
6517dd7cddfSDavid du Colombier ow = t->w;
652d9306527SDavid du Colombier w = makenewwindow(t);
6537dd7cddfSDavid du Colombier t = &w->body;
6547dd7cddfSDavid du Colombier winsetname(w, e->name, e->nname);
6557dd7cddfSDavid du Colombier textload(t, 0, e->bname, 1);
6567dd7cddfSDavid du Colombier t->file->mod = FALSE;
6577dd7cddfSDavid du Colombier t->w->dirty = FALSE;
6587dd7cddfSDavid du Colombier winsettag(t->w);
6597dd7cddfSDavid du Colombier textsetselect(&t->w->tag, t->w->tag.file->nc, t->w->tag.file->nc);
6604fec87e5SDavid du Colombier if(ow != nil){
6617dd7cddfSDavid du Colombier for(i=ow->nincl; --i>=0; ){
6627dd7cddfSDavid du Colombier n = runestrlen(ow->incl[i]);
6637dd7cddfSDavid du Colombier rp = runemalloc(n);
6647dd7cddfSDavid du Colombier runemove(rp, ow->incl[i], n);
6657dd7cddfSDavid du Colombier winaddincl(w, rp, n);
6667dd7cddfSDavid du Colombier }
6674fec87e5SDavid du Colombier w->autoindent = ow->autoindent;
6684fec87e5SDavid du Colombier }else
6694fec87e5SDavid du Colombier w->autoindent = globalautoindent;
6707dd7cddfSDavid du Colombier }
6717dd7cddfSDavid du Colombier if(e->a1 == e->a0)
6727dd7cddfSDavid du Colombier eval = FALSE;
6737dd7cddfSDavid du Colombier else{
6747dd7cddfSDavid du Colombier eval = TRUE;
67559cc4ca5SDavid du Colombier r = address(nil, t, (Range){-1, -1}, (Range){t->q0, t->q1}, e->at, e->a0, e->a1, e->agetc, &eval, &dummy);
6769a747e4fSDavid du Colombier if(eval == FALSE)
6779a747e4fSDavid du Colombier e->jump = FALSE; /* don't jump if invalid address */
6787dd7cddfSDavid du Colombier }
6797dd7cddfSDavid du Colombier if(eval == FALSE){
6807dd7cddfSDavid du Colombier r.q0 = t->q0;
6817dd7cddfSDavid du Colombier r.q1 = t->q1;
6827dd7cddfSDavid du Colombier }
6839a747e4fSDavid du Colombier textshow(t, r.q0, r.q1, 1);
6847dd7cddfSDavid du Colombier winsettag(t->w);
6857dd7cddfSDavid du Colombier seltext = t;
6867dd7cddfSDavid du Colombier if(e->jump)
6877dd7cddfSDavid du Colombier moveto(mousectl, addpt(frptofchar(t, t->p0), Pt(4, font->height-4)));
6887dd7cddfSDavid du Colombier return w;
6897dd7cddfSDavid du Colombier }
6907dd7cddfSDavid du Colombier
6917dd7cddfSDavid du Colombier void
new(Text * et,Text * t,Text * argt,int flag1,int flag2,Rune * arg,int narg)6927dd7cddfSDavid du Colombier new(Text *et, Text *t, Text *argt, int flag1, int flag2, Rune *arg, int narg)
6937dd7cddfSDavid du Colombier {
6947dd7cddfSDavid du Colombier int ndone;
6957dd7cddfSDavid du Colombier Rune *a, *f;
6967dd7cddfSDavid du Colombier int na, nf;
6977dd7cddfSDavid du Colombier Expand e;
6987dd7cddfSDavid du Colombier Runestr rs;
6997dd7cddfSDavid du Colombier
7007dd7cddfSDavid du Colombier getarg(argt, FALSE, TRUE, &a, &na);
7017dd7cddfSDavid du Colombier if(a){
7027dd7cddfSDavid du Colombier new(et, t, nil, flag1, flag2, a, na);
7037dd7cddfSDavid du Colombier if(narg == 0)
7047dd7cddfSDavid du Colombier return;
7057dd7cddfSDavid du Colombier }
7067dd7cddfSDavid du Colombier /* loop condition: *arg is not a blank */
7077dd7cddfSDavid du Colombier for(ndone=0; ; ndone++){
7087dd7cddfSDavid du Colombier a = findbl(arg, narg, &na);
7097dd7cddfSDavid du Colombier if(a == arg){
7107dd7cddfSDavid du Colombier if(ndone==0 && et->col!=nil)
7117dd7cddfSDavid du Colombier winsettag(coladd(et->col, nil, nil, -1));
7127dd7cddfSDavid du Colombier break;
7137dd7cddfSDavid du Colombier }
7147dd7cddfSDavid du Colombier nf = narg-na;
7157dd7cddfSDavid du Colombier f = runemalloc(nf);
7167dd7cddfSDavid du Colombier runemove(f, arg, nf);
7177dd7cddfSDavid du Colombier rs = dirname(et, f, nf);
7187dd7cddfSDavid du Colombier f = rs.r;
7197dd7cddfSDavid du Colombier nf = rs.nr;
7207dd7cddfSDavid du Colombier memset(&e, 0, sizeof e);
7217dd7cddfSDavid du Colombier e.name = f;
7227dd7cddfSDavid du Colombier e.nname = nf;
7237dd7cddfSDavid du Colombier e.bname = runetobyte(f, nf);
7247dd7cddfSDavid du Colombier e.jump = TRUE;
7257dd7cddfSDavid du Colombier openfile(et, &e);
7267dd7cddfSDavid du Colombier free(f);
7277dd7cddfSDavid du Colombier free(e.bname);
7287dd7cddfSDavid du Colombier arg = skipbl(a, na, &narg);
7297dd7cddfSDavid du Colombier }
7307dd7cddfSDavid du Colombier }
731