tacme: revise multiline tag code - 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 a2db69c8bda889f30ea38dae5473689cde108458
 (DIR) parent cb1ac4c41dd0c1bfb621685cc2f6e73c7e369f57
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Fri,  7 Mar 2008 11:07:17 -0500
       
       acme: revise multiline tag code
       
       Diffstat:
         M src/cmd/acme/cols.c                 |      53 +++++++++++++++----------------
         M src/cmd/acme/mkfile                 |      16 ++++++++++++++++
         M src/cmd/acme/rows.c                 |      23 ++++++-----------------
         M src/cmd/acme/text.c                 |      31 ++++---------------------------
         M src/cmd/acme/wind.c                 |      42 +++++++++++---------------------
       
       5 files changed, 66 insertions(+), 99 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c
       t@@ -53,7 +53,7 @@ coladd(Column *c, Window *w, Window *clone, int y)
        {
                Rectangle r, r1;
                Window *v;
       -        int i, j, minht, t;
       +        int i, j, minht, ymax;
        
                v = nil;
                r = c->r;
       t@@ -72,31 +72,38 @@ coladd(Column *c, Window *w, Window *clone, int y)
                        if(i < c->nw)
                                i++;        /* new window will go after v */
                        /*
       -                 * if v's too small, grow it first.
       +                 * 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){
       -fprint(2, "oops: dy=%d\n", Dy(v->body.all));
       +                                fprint(2, "coladd: bug dy=%d\n", Dy(v->body.all));
                                        break;
                                }
                                colgrow(c, v, 1);
                        }
       +
       +                /*
       +                 * figure out where to split v to make room for w
       +                 */
                        if(i == c->nw)
       -                        t = c->r.max.y;
       +                        ymax = c->r.max.y;
                        else
       -                        t = c->w[i]->r.min.y-Border;
       +                        ymax = c->w[i]->r.min.y-Border;
                        y = min(y, v->body.all.min.y+Dy(v->body.all)/2);
       -                if(t - y < minht)
       -                        y = t - minht;
       -                if(y < v->body.all.min.y)
       -                        y = v->body.all.min.y;
       +                y = min(y, ymax - minht);
       +                y = max(y, v->body.all.min.y);
       +                ymax = max(ymax, y+minht);
                        r = v->r;
       -                r.max.y = t;
       +                r.max.y = ymax;
       +
       +                /*
       +                 * redraw w
       +                 */
                        draw(screen, r, textcols[BACK], nil, ZP);
                        r1 = r;
       -                y = min(y, t-(v->tag.fr.font->height*v->taglines+v->body.fr.font->height+Border+1));
       +                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;
       t@@ -151,8 +158,8 @@ colclose(Column *c, Window *w, int dofree)
                        windelete(w);
                        winclose(w);
                }
       -        memmove(c->w+i, c->w+i+1, (c->nw-i-1)*sizeof(Window*));
                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, display->white, nil, ZP);
       t@@ -219,8 +226,7 @@ colresize(Column *c, Rectangle r)
                                r1.max.y = r.max.y;
                        else
                                r1.max.y = r1.min.y+(Dy(w->r)+Border)*Dy(r)/Dy(c->r);
       -                if(Dy(r1) < Border+font->height)
       -                        r1.max.y = r1.min.y + Border+font->height;
       +                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, display->black, nil, ZP);
       t@@ -307,7 +313,7 @@ colgrow(Column *c, Window *w, int but)
                        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;
       +                        r.max.y = c->w[i+1]->r.min.y - Border;
                        winresize(w, r, FALSE, TRUE);
                        return;
                }
       t@@ -342,7 +348,7 @@ colgrow(Column *c, Window *w, int but)
                }
                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;
       +                nnl = (w->taglines-1+w->maxlines + nnl)/2;
                if(nnl == 0)
                        nnl = 2;
                dnl = nnl - onl;
       t@@ -400,7 +406,7 @@ colgrow(Column *c, Window *w, int but)
                if(Dy(r) < Dy(w->tagtop)+1+h+Border)
                        r.max.y = r.min.y + Dy(w->tagtop)+1+h+Border;
                /* draw window */
       -        winresize(w, r, c->safe, TRUE);
       +        r.max.y = winresize(w, r, c->safe, i==c->nw-1);
                if(i < c->nw-1){
                        r.min.y = r.max.y;
                        r.max.y += Border;
       t@@ -417,7 +423,7 @@ colgrow(Column *c, Window *w, int but)
                        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+1==c->nw);
       +                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;
       t@@ -425,12 +431,6 @@ colgrow(Column *c, Window *w, int but)
                                y1 = r.max.y;
                        }
                }
       -/*
       -        r = w->r;
       -        r.min.y = y1;
       -        r.max.y = c->r.max.y;
       -        draw(screen, r, textcols[BACK], nil, ZP);
       -*/
                free(nl);
                free(ny);
                c->safe = TRUE;
       t@@ -465,9 +465,8 @@ coldragwin(Column *c, Window *w, int but)
                error("can't find window");
        
          Found:
       -/* TAG - force recompute tag size (if in auto-expand mode) on mouse op. */
       -        w->taglines = 1;
       -/* END TAG */
       +        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);
 (DIR) diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile
       t@@ -33,3 +33,19 @@ HFILES=dat.h\
        <$PLAN9/src/mkdirs
        
        edit.$O ecmd.$O elog.$O:        edit.h
       +
       +likeplan9:V:
       +        mkdir -p likeplan9
       +        rm -f likeplan9/*
       +        for i in *.c
       +        do
       +                9 sed 's/->(fcall|lk|b|fr|ref|m|u|u1)\./->/g;
       +                        s/\.(fcall|lk|b|fr|ref|m|u|u1)([^a-zA-Z0-9_])/\2/g
       +                        s/&(([a-zA-Z0-9_]|->|\.)*)->(fcall|lk|b|fr|ref|m|u|u1)([^a-zA-Z0-9_])/\1\4/g
       +                        s/range\(([^,()]+), ([^,()]+)\)/(Range){\1, \2}/g
       +                ' $i >likeplan9/$i
       +        done
       +
       +diffplan9:V:
       +        mk likeplan9
       +        9 diff -n plan9 likeplan9 | sed 's;likeplan9/;;'
 (DIR) diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c
       t@@ -217,8 +217,8 @@ rowclose(Row *row, Column *c, int dofree)
                r = c->r;
                if(dofree)
                        colcloseall(c);
       -        memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
                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, display->white, nil, ZP);
       t@@ -282,17 +282,13 @@ rowtype(Row *row, Rune r, Point p)
                        else{
                                winlock(w, 'K');
                                wintype(w, t, r);
       -/*
       - * TAG If we typed in the tag, might need to make it
       - * bigger to show text.  \n causes tag to expand.
       - */
       +                        /* 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);
                                }
       -/* END TAG */
                                winunlock(w);
                        }
                }
       t@@ -319,7 +315,7 @@ rowdump(Row *row, char *file)
                uint q0, q1;
                Biobuf *b;
                char *buf, *a, *fontname;
       -        Rune *r, *rp;
       +        Rune *r;
                Column *c;
                Window *w, *w1;
                Text *t;
       t@@ -417,17 +413,10 @@ rowdump(Row *row, char *file)
                                Bwrite(b, buf, strlen(buf));
                                m = min(RBUFSIZE, w->tag.file->b.nc);
                                bufread(&w->tag.file->b, 0, r, m);
       -                        if(dodollarsigns && r[0] == '$'){
       -                                rp = runestrdup(r);
       -                                expandenv(&rp, (uint*)&m);
       -                        }else
       -                                rp = r;
                                n = 0;
       -                        while(n<m && rp[n]!='\n')
       +                        while(n<m && r[n]!='\n')
                                        n++;
       -                        Bprint(b, "%.*S\n", n, rp);
       -                        if(rp != r)
       -                                free(rp);
       +                        Bprint(b, "%.*S\n", n, r);
                                if(dumped){
                                        q0 = 0;
                                        q1 = t->file->b.nc;
       t@@ -705,6 +694,7 @@ rowload(Row *row, char *file, int initing)
                                                Bterm(bout);
                                                free(bout);
                                                close(fd);
       +                                        remove(buf);
                                                goto Rescue2;
                                        }
                                        Bputrune(bout, rune);
       t@@ -731,7 +721,6 @@ rowload(Row *row, char *file, int initing)
                        w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines));
                }
                Bterm(b);
       -
                fbuffree(buf);
                return TRUE;
        
 (DIR) diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
       t@@ -75,7 +75,7 @@ textresize(Text *t, Rectangle r, int keepextra)
        
                if(Dy(r) <= 0)
                        r.max.y = r.min.y;
       -        if(!keepextra)
       +        else if(!keepextra)
                        r.max.y -= Dy(r)%t->fr.font->height;
                odx = Dx(t->all);
                t->all = r;
       t@@ -84,8 +84,9 @@ textresize(Text *t, Rectangle r, int keepextra)
                t->lastsr = nullrect;
                r.min.x += Scrollwid+Scrollgap;
                frclear(&t->fr, 0);
       -        textredraw(t, r, t->fr.font, screen, odx);
       +        textredraw(t, r, t->fr.font, t->fr.b, odx);
                if(keepextra && t->fr.r.max.y < t->all.max.y){
       +                /* 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;
       t@@ -197,7 +198,7 @@ textload(Text *t, uint q0, char *file, int setqid)
                char *tmp;
                Text *u;
        
       -        if(t->ncache!=0 || t->file->b.nc || t->w==nil || t!=&t->w->body || (t->w->isdir && t->file->nname==0))
       +        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");
       t@@ -653,20 +654,13 @@ texttype(Text *t, Rune r)
                uint q0, q1;
                int nnb, nb, n, i;
                int nr;
       -        Point p;
                Rune *rp;
                Text *u;
        
       -/*
       - * TAG
       - * Used to disallow \n in tag here.
       - * Also if typing in tag, mark that resize might be necessary.
       - */
                if(t->what!=Body && t->what!=Tag && r=='\n')
                        return;
                if(t->what == Tag)
                        t->w->tagsafe = FALSE;
       -/* END TAG */
        
                nr = 1;
                rp = &r;
       t@@ -684,17 +678,13 @@ texttype(Text *t, Rune r)
                        }
                        return;
                case Kdown:
       -/* TAG */
                        if(t->what == Tag)
                                goto Tagdown;
       -/* END TAG */
                        n = t->fr.maxlines/3;
                        goto case_Down;
                case Kscrollonedown:
       -/* TAG */
                        if(t->what == Tag)
                                goto Tagdown;
       -/* END TAG */
                        n = mousescrollsize(t->fr.maxlines);
                        if(n <= 0)
                                n = 1;
       t@@ -706,17 +696,13 @@ texttype(Text *t, Rune r)
                        textsetorigin(t, q0, TRUE);
                        return;
                case Kup:
       -/* TAG */
                        if(t->what == Tag)
                                goto Tagup;
       -/* END TAG */
                        n = t->fr.maxlines/3;
                        goto case_Up;
                case Kscrolloneup:
       -/* TAG */
                        if(t->what == Tag)
                                goto Tagup;
       -/* END TAG */
                        n = mousescrollsize(t->fr.maxlines);
                        goto case_Up;
                case Kpgup:
       t@@ -748,7 +734,6 @@ texttype(Text *t, Rune r)
                                q0++;
                        textshow(t, q0, q0, TRUE);
                        return;
       -/* TAG policy here */
                Tagdown:
                        /* expand tag to show all text */
                        if(!t->w->tagexpand){
       t@@ -762,17 +747,9 @@ texttype(Text *t, Rune r)
                        if(t->w->tagexpand){
                                t->w->tagexpand = FALSE;
                                t->w->taglines = 1;
       -                        /* move mouse to stay in tag */
       -                        p = mouse->xy;
       -                        if(ptinrect(p, t->w->tag.all) 
       -                        && !ptinrect(p, t->w->tagtop)){
       -                                p.y = t->w->tagtop.min.y + Dy(t->w->tagtop)/2;
       -                                moveto(mousectl, p);
       -                        }
                                winresize(t->w, t->w->r, FALSE, TRUE);
                        }
                        return;
       -/* END TAG */
                }
                if(t->what == Body){
                        seq++;
 (DIR) diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c
       t@@ -36,8 +36,8 @@ wininit(Window *w, Window *clone, Rectangle r)
        
                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);
       t@@ -53,7 +53,6 @@ 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 += w->taglines*font->height + 1;
                if(r1.max.y < r1.min.y)
       t@@ -66,7 +65,6 @@ 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@@ -82,7 +80,6 @@ wininit(Window *w, Window *clone, Rectangle r)
                w->filemenu = TRUE;
                w->maxlines = w->body.fr.maxlines;
                w->autoindent = globalautoindent;
       -/*assert(w->body.w == w); */
                if(clone){
                        w->dirty = clone->dirty;
                        w->autoindent = clone->autoindent;
       t@@ -119,8 +116,6 @@ wintaglines(Window *w, Rectangle r)
                int n;
                Rune rune;
        
       -/* TAG policy here */
       -
                if(!w->tagexpand)
                        return 1;
                w->tag.fr.noredraw = 1;
       t@@ -151,57 +146,50 @@ winresize(Window *w, Rectangle r, int safe, int keepextra)
                Point p;
                Rectangle r1;
        
       -if(0) fprint(2, "winresize %d %R safe=%d keep=%d h=%d\n", w->id, r, safe, keepextra, font->height);
       +        /* tagtop is first line of tag */
                w->tagtop = r;
                w->tagtop.max.y = r.min.y+font->height;
        
       -/* 
       - * TAG If necessary, recompute the number of lines that should
       - * be in the tag.
       - */
                r1 = r;
                r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height);
       -        y = r1.max.y;
                mouseintag = ptinrect(mouse->xy, w->tag.all);
       -        if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1))
       +
       +        /* If needed, recompute number of lines in tag. */
       +        if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){
                        w->taglines = wintaglines(w, r);
       -/* END TAG */
       +                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, resize & redraw tag. */
                y = r1.max.y;
                tagresized = 0;
       -if(0) fprint(2, "winresize tag %R %R\n", w->tag.all, r1);
                if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){
                        tagresized = 1;
       -if(0) fprint(2, "resize tag %R => %R\n", w->tag.all, r1);
                        textresize(&w->tag, r1, TRUE);
       -if(0) fprint(2, "=> %R (%R)\n", w->tag.all, w->tag.fr.r);
                        y = w->tag.fr.r.max.y;
                        windrawbutton(w);
                        w->tagsafe = TRUE;
       -/* TAG */
       +
                        /* 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(!mouseintag && ptinrect(mouse->xy, w->tag.all)){
                                p = mouse->xy;
                                p.y = w->tag.all.max.y+3;
                                moveto(mousectl, p);
                        }
       -/* END TAG */
                }
       -
                
       +        /* If needed, resize & redraw body. */
                r1 = r;
                r1.min.y = y;
                if(tagresized || !safe || !eqrect(w->body.all, r1)){
                        oy = y;
       -if(0) fprint(2, "resizing body; safe=%d all=%R r1=%R\n", safe, w->body.all, r1);
                        if(y+1+w->body.fr.font->height <= r.max.y){        /* room for one line */
                                r1.min.y = y;
                                r1.max.y = y+1;
       t@@ -213,10 +201,9 @@ if(0) fprint(2, "resizing body; safe=%d all=%R r1=%R\n", safe, w->body.all, r1);
                                r1.min.y = y;
                                r1.max.y = y;
                        }
       -if(0) fprint(2, "resizing body; new r=%R; r1=%R\n", r, r1);
       +                y = textresize(&w->body, r1, keepextra);
                        w->r = r;
       -                w->r.max.y = textresize(&w->body, r1, keepextra);
       -if(0) fprint(2, "after textresize: body.all=%R\n", w->body.all);
       +                w->r.max.y = y;
                        textscrdraw(&w->body);
                        w->body.all.min.y = oy;
                }
       t@@ -354,6 +341,7 @@ winsetname(Window *w, Rune *name, int n)
                int i;
                static Rune Lslashguide[] = { '/', 'g', 'u', 'i', 'd', 'e', 0 };
                static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
       +
                t = &w->body;
                if(runeeq(t->file->name, t->file->nname, name, n) == TRUE)
                        return;
       t@@ -559,7 +547,6 @@ wincommit(Window *w, Text *t)
                for(i=0; i<w->tag.file->b.nc; i++)
                        if(r[i]==' ' || r[i]=='\t')
                                break;
       -        expandenv(&r, (uint*)&i);
                if(runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE){
                        seq++;
                        filemark(w->body.file);
       t@@ -678,4 +665,3 @@ winevent(Window *w, char *fmt, ...)
                        sendp(x->c, nil);
                }
        }
       -