tcompletion, pageup/pagedown - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c1973705501d05e906bd14a0dc25cc4472b5871f
 (DIR) parent 97fdda4e861f7f66c707d32443f3d8461594b9a5
 (HTM) Author: rsc <devnull@localhost>
       Date:   Mon,  9 Feb 2004 19:32:18 +0000
       
       completion, pageup/pagedown
       
       Diffstat:
         M src/cmd/acme/acme.c                 |       2 ++
         M src/cmd/acme/cols.c                 |       1 +
         M src/cmd/acme/mkfile                 |       2 +-
         M src/cmd/acme/text.c                 |     136 +++++++++++++++++++++++++++++--
         M src/cmd/acme/wind.c                 |       5 +++++
       
       5 files changed, 139 insertions(+), 7 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c
       t@@ -138,6 +138,7 @@ threadmain(int argc, char *argv[])
        
                d = display;
                font = d->defaultfont;
       +//assert(font);
        
                reffont.f = font;
                reffonts[0] = &reffont;
       t@@ -790,6 +791,7 @@ rfget(int fix, int save, int setfont, char *name)
                                }
                        f = openfont(display, name);
                        if(f == nil){
       +                        fprint(2, "can't open font file %s: %r\n", name);
                                warning(nil, "can't open font file %s: %r\n", name);
                                return nil;
                        }
 (DIR) diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c
       t@@ -102,6 +102,7 @@ coladd(Column *c, Window *w, Window *clone, int y)
                        w->col = c;
                        winresize(w, r, FALSE);
                }
       +//assert(w->body.w == w);
                w->tag.col = c;
                w->tag.row = c->row;
                w->body.col = c;
 (DIR) diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile
       t@@ -36,6 +36,6 @@ UPDATE=\
        
        <$PLAN9/src/mkone
        
       -LDFLAGS=$LDFLAGS -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
       +LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
        
        edit.$O ecmd.$O elog.$O:        edit.h
 (DIR) diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
       t@@ -8,11 +8,13 @@
        #include <frame.h>
        #include <fcall.h>
        #include <plumb.h>
       +#include <complete.h>
        #include "dat.h"
        #include "fns.h"
        
        Image        *tagcols[NCOL];
        Image        *textcols[NCOL];
       +static Rune Ldot[] = { '.', 0 };
        
        enum{
                TABDIR = 3        /* width of tabs in directory windows */
       t@@ -526,24 +528,136 @@ textbswidth(Text *t, Rune c)
                return t->q0-q;
        }
        
       +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;
       +}
       +
       +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);
       +
       +        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);
       +        }
       +
       +        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*\n",
       +                        dir.nr, dir.r,
       +                        dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
       +                        nstr, str);
       +                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;
       +}
       +
        void
        texttype(Text *t, Rune r)
        {
                uint q0, q1;
                int nnb, nb, n, i;
       +        int nr;
       +        Rune *rp;
                Text *u;
        
                if(t->what!=Body && r=='\n')
                        return;
       +        nr = 1;
       +        rp = &r;
                switch(r){
       -        case Kdown:
                case Kleft:
       +                if(t->q0 > 0)
       +                        textshow(t, t->q0-1, t->q0-1, TRUE);
       +                return;
                case Kright:
       +                if(t->q1 < t->file->b.nc)
       +                        textshow(t, t->q1+1, t->q1+1, TRUE);
       +                return;
       +        case Kdown:
       +        case Kpgdown:
                        n = t->fr.maxlines/2;
                        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, FALSE);
                        return;
                case Kup:
       +        case Kpgup:
                        n = t->fr.maxlines/2;
                        q0 = textbacknl(t, t->org, n);
                        textsetorigin(t, q0, FALSE);
       t@@ -561,6 +675,13 @@ texttype(Text *t, Rune r)
                }
                textshow(t, t->q0, t->q0, 1);
                switch(r){
       +        case 0x06:        /* ^F: complete */
       +        case Kins:
       +                rp = textcomplete(t);
       +                if(rp == nil)
       +                        return;
       +                nr = runestrlen(rp);
       +                break;        /* fall through to normal insertion case */
                case 0x1B:
                        if(t->eq0 != ~0)
                                textsetselect(t, t->eq0, t->q0);
       t@@ -623,16 +744,19 @@ texttype(Text *t, Rune r)
                                u->cq0 = t->q0;
                        else if(t->q0 != u->cq0+u->ncache)
                                error("text.type cq1");
       -                textinsert(u, t->q0, &r, 1, FALSE);
       +                textinsert(u, t->q0, rp, nr, FALSE);
                        if(u != t)
                                textsetselect(u, u->q0, u->q1);
       -                if(u->ncache == u->ncachealloc){
       -                        u->ncachealloc += 10;
       +                if(u->ncache+nr > u->ncachealloc){
       +                        u->ncachealloc += 10 + nr;
                                u->cache = runerealloc(u->cache, u->ncachealloc);
                        }
       -                u->cache[u->ncache++] = r;
       +                runemove(u->cache+u->ncache, rp, nr);
       +                u->ncache += nr;
                }
       -        textsetselect(t, t->q0+1, t->q0+1);
       +        if(rp != &r)
       +                free(rp);
       +        textsetselect(t, t->q0+nr, t->q0+nr);
                if(r=='\n' && t->w!=nil)
                        wincommit(t->w, t);
        }
 (DIR) diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c
       t@@ -45,6 +45,7 @@ wininit(Window *w, Window *clone, Rectangle r)
                        filereset(w->tag.file);
                        textsetselect(&w->tag, nc, nc);
                }
       +//assert(w->body.w == w);
                r1 = r;
                r1.min.y += font->height + 1;
                if(r1.max.y < r1.min.y)
       t@@ -57,6 +58,7 @@ wininit(Window *w, Window *clone, Rectangle r)
                        rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name);
                }else
                        rf = rfget(FALSE, FALSE, FALSE, nil);
       +//assert(w->body.w == w);
                f = fileaddtext(f, &w->body);
                w->body.what = Body;
                textinit(&w->body, f, r1, rf, textcols);
       t@@ -72,6 +74,7 @@ wininit(Window *w, Window *clone, Rectangle r)
                draw(screen, br, button, nil, button->r.min);
                w->filemenu = TRUE;
                w->maxlines = w->body.fr.maxlines;
       +//assert(w->body.w == w);
                if(clone){
                        w->dirty = clone->dirty;
                        textsetselect(&w->body, clone->body.q0, clone->body.q1);
       t@@ -138,6 +141,7 @@ winlock(Window *w, int owner)
                int i;
                File *f;
        
       +fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
                f = w->body.file;
                for(i=0; i<f->ntext; i++)
                        winlock1(f->text[i]->w, owner);
       t@@ -149,6 +153,7 @@ winunlock(Window *w)
                int i;
                File *f;
        
       +fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
                f = w->body.file;
                for(i=0; i<f->ntext; i++){
                        w = f->text[i]->w;