]> git.lizzy.rs Git - plan9front.git/commitdiff
acme: import changes from plan9port (thanks jxy)
authorOri Bernstein <ori@eigenstate.org>
Tue, 22 Sep 2020 18:42:15 +0000 (11:42 -0700)
committerOri Bernstein <ori@eigenstate.org>
Tue, 22 Sep 2020 18:42:15 +0000 (11:42 -0700)
Import the following improvements and bugfixes from plan9port:

4650064a acme: scale window bodies on resize, not including tag space
d28913a9 acme: save/restore multiline tags in Dump/Load
d2df5d6c acme: fix crash in X |cat with multiple windows
3d6e5cb5 acme: preserve window position and selection during Get

sys/src/cmd/acme/acme.c
sys/src/cmd/acme/addr.c
sys/src/cmd/acme/cols.c
sys/src/cmd/acme/ecmd.c
sys/src/cmd/acme/exec.c
sys/src/cmd/acme/fns.h
sys/src/cmd/acme/rows.c
sys/src/cmd/acme/scrl.c
sys/src/cmd/acme/text.c

index e874d35540846de5619d71a0112e1dc37c47f33a..96a7d6b0359daa4181fe45c05caf73e33a809bcc 100644 (file)
@@ -513,8 +513,13 @@ mousethread(void *)
                                but = 2;
                        else if(m.buttons == 4)
                                but = 3;
                                but = 2;
                        else if(m.buttons == 4)
                                but = 3;
+                       else if(m.buttons == 8)
+                               but = 4;
+                       else if(m.buttons == 16)
+                               but = 5;
                        barttext = t;
                        barttext = t;
-                       if(t->what==Body && ptinrect(m.xy, t->scrollr)){
+                       if(t->what==Body && w != nil
+                       && (ptinrect(m.xy, t->scrollr) || (m.buttons & (8|16)))){
                                if(but){
                                        winlock(w, 'M');
                                        t->eq0 = ~0;
                                if(but){
                                        winlock(w, 'M');
                                        t->eq0 = ~0;
@@ -523,18 +528,6 @@ mousethread(void *)
                                }
                                goto Continue;
                        }
                                }
                                goto Continue;
                        }
-                       /* scroll buttons, wheels, etc. */
-                       if(t->what==Body && 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)
                        if(ptinrect(m.xy, t->scrollr)){
                                if(but){
                                        if(t->what == Columntag)
index 94dd88cde57ec701ece0486ec7ba0ac7dc1e6406..0637fab6407fdcd7ba9bd12b79970f2b57c6789c 100644 (file)
@@ -48,6 +48,27 @@ isregexc(int r)
        return FALSE;
 }
 
        return FALSE;
 }
 
+// nlcounttopos starts at q0 and advances nl lines,
+// 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->nc) {
+               if(textreadc(t, q0++) == '\n')
+                       nl--;
+       }
+       if(nl > 0)
+               return q0;
+       while(nr > 0 && q0 < t->file->nc && textreadc(t, q0) != '\n') {
+               q0++;
+               nr--;
+       }
+       return q0;
+}
+
 Range
 number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp)
 {
 Range
 number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp)
 {
index 6beb2edb0511693b65af0147b4e76ec6127e8227..7ac1e1500ad3015f30cb96d4418e109c2dc9e56d 100644 (file)
@@ -186,7 +186,7 @@ colmousebut(Column *c)
 void
 colresize(Column *c, Rectangle r)
 {
 void
 colresize(Column *c, Rectangle r)
 {
-       int i;
+       int i, old, new;
        Rectangle r1, r2;
        Window *w;
 
        Rectangle r1, r2;
        Window *w;
 
@@ -199,6 +199,8 @@ colresize(Column *c, Rectangle r)
        r1.max.y += Border;
        draw(screen, r1, display->black, nil, ZP);
        r1.max.y = r.max.y;
        r1.max.y += Border;
        draw(screen, r1, display->black, nil, ZP);
        r1.max.y = r.max.y;
+       new = Dy(r) - c->nw*(Border + font->height);
+       old = Dy(c->r) - c->nw*(Border + font->height);
        for(i=0; i<c->nw; i++){
                w = c->w[i];
                w->maxlines = 0;
        for(i=0; i<c->nw; i++){
                w = c->w[i];
                w->maxlines = 0;
@@ -206,8 +208,8 @@ colresize(Column *c, Rectangle r)
                        r1.max.y = r.max.y;
                else {
                        r1.max.y = r1.min.y;
                        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);
+                       if(new > 0 && old > 0 && Dy(w->r) > Border+font->height)
+                               r1.max.y += (Dy(w->r)-Border-font->height)*new/old + Border + font->height;
                }
                r2 = r1;
                r2.max.y = r2.min.y+Border;
                }
                r2 = r1;
                r2.max.y = r2.min.y+Border;
index f0266c9429fac7bfd8936a7f2f437d3540c0009e..06d09f38bee179fbe8870f944886493f3168bb99 100644 (file)
@@ -27,7 +27,7 @@ int   append(File*, Cmd*, long);
 int    pdisplay(File*);
 void   pfilename(File*);
 void   looper(File*, Cmd*, int);
 int    pdisplay(File*);
 void   pfilename(File*);
 void   looper(File*, Cmd*, int);
-void   filelooper(Cmd*, int);
+void   filelooper(Text*, Cmd*, int);
 void   linelooper(File*, Cmd*);
 Address        lineaddr(long, Address, int);
 int    filematch(File*, String*);
 void   linelooper(File*, Cmd*);
 Address        lineaddr(long, Address, int);
 int    filematch(File*, String*);
@@ -575,9 +575,9 @@ x_cmd(Text *t, Cmd *cp)
 }
 
 int
 }
 
 int
-X_cmd(Text*, Cmd *cp)
+X_cmd(Text *t, Cmd *cp)
 {
 {
-       filelooper(cp, cp->cmdc=='X');
+       filelooper(t, cp, cp->cmdc=='X');
        return TRUE;
 }
 
        return TRUE;
 }
 
@@ -636,15 +636,16 @@ pipe_cmd(Text *t, Cmd *cp)
 }
 
 long
 }
 
 long
-nlcount(Text *t, long q0, long q1)
+nlcount(Text *t, long q0, long q1, long *pnr)
 {
 {
-       long nl;
+       long nl, start;
        Rune *buf;
        int i, nbuf;
 
        buf = fbufalloc();
        nbuf = 0;
        i = nl = 0;
        Rune *buf;
        int i, nbuf;
 
        buf = fbufalloc();
        nbuf = 0;
        i = nl = 0;
+       start = q0;
        while(q0 < q1){
                if(i == nbuf){
                        nbuf = q1-q0;
        while(q0 < q1){
                if(i == nbuf){
                        nbuf = q1-q0;
@@ -653,24 +654,42 @@ nlcount(Text *t, long q0, long q1)
                        bufread(t->file, q0, buf, nbuf);
                        i = 0;
                }
                        bufread(t->file, q0, buf, nbuf);
                        i = 0;
                }
-               if(buf[i++] == '\n')
+               if(buf[i++] == '\n'){
+                       start = q0+1;
                        nl++;
                        nl++;
+               }
                q0++;
        }
        fbuffree(buf);
                q0++;
        }
        fbuffree(buf);
+       if(pnr != nil)
+               *pnr = q0 - start;
        return nl;
 }
 
        return nl;
 }
 
+enum {
+       PosnLine = 0,
+       PosnChars = 1,
+       PosnLineChars = 2,
+};
+
 void
 void
-printposn(Text *t, int charsonly)
+printposn(Text *t, int mode)
 {
 {
-       long l1, l2;
+       long l1, l2, r1, r2;
 
        if (t != nil && t->file != nil && t->file->name != nil)
                warning(nil, "%.*S:", t->file->nname, t->file->name);
 
        if (t != nil && t->file != nil && t->file->name != nil)
                warning(nil, "%.*S:", t->file->nname, t->file->name);
-       if(!charsonly){
-               l1 = 1+nlcount(t, 0, addr.r.q0);
-               l2 = l1+nlcount(t, addr.r.q0, addr.r.q1);
+       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;
                /* 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;
@@ -679,32 +698,42 @@ printposn(Text *t, int charsonly)
                        warning(nil, ",%lud", l2);
                warning(nil, "\n");
                return;
                        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+#%lud", l1, r1);
+               if(l2 != l1)
+                       warning(nil, ",%lud+#%lud", l2, r2);
+               warning(nil, "\n");
+               return;
        }
        }
-       warning(nil, "#%d", addr.r.q0);
-       if(addr.r.q1 != addr.r.q0)
-               warning(nil, ",#%d", addr.r.q1);
-       warning(nil, "\n");
 }
 
 int
 eq_cmd(Text *t, Cmd *cp)
 {
 }
 
 int
 eq_cmd(Text *t, Cmd *cp)
 {
-       int charsonly;
+       int mode;
 
        switch(cp->text->n){
        case 0:
 
        switch(cp->text->n){
        case 0:
-               charsonly = FALSE;
+               mode = PosnLine;
                break;
        case 1:
                if(cp->text->r[0] == '#'){
                break;
        case 1:
                if(cp->text->r[0] == '#'){
-                       charsonly = TRUE;
+                       mode = PosnChars;
+                       break;
+               }
+               if(cp->text->r[0] == '+'){
+                       mode = PosnLineChars;
                        break;
                }
        default:
                        break;
                }
        default:
-               SET(charsonly);
+               SET(mode);
                editerror("newline expected");
        }
                editerror("newline expected");
        }
-       printposn(t, charsonly);
+       printposn(t, mode);
        return TRUE;
 }
 
        return TRUE;
 }
 
@@ -921,9 +950,10 @@ alllocker(Window *w, void *v)
 }
 
 void
 }
 
 void
-filelooper(Cmd *cp, int XY)
+filelooper(Text *t, Cmd *cp, int XY)
 {
        int i;
 {
        int i;
+       Text *targ;
 
        if(Glooping++)
                editerror("can't nest %c command", "YX"[XY]);
 
        if(Glooping++)
                editerror("can't nest %c command", "YX"[XY]);
@@ -944,8 +974,22 @@ filelooper(Cmd *cp, int XY)
         */
        allwindows(alllocker, (void*)1);
        globalincref = 1;
         */
        allwindows(alllocker, (void*)1);
        globalincref = 1;
-       for(i=0; i<loopstruct.nw; i++)
-               cmdexec(&loopstruct.w[i]->body, cp->cmd);
+       /*
+        * Unlock the window running the X command.
+        * We'll need to lock and unlock each target window in turn.
+        */
+       if(t && t->w)
+               winunlock(t->w);
+       for(i=0; i<loopstruct.nw; i++){
+               targ = &loopstruct.w[i]->body;
+               if(targ && targ->w)
+                       winlock(targ->w, cp->cmdc);
+               cmdexec(targ, cp->cmd);
+               if(targ && targ->w)
+                       winunlock(targ->w);
+       }
+       if(t && t->w)
+               winlock(t->w, cp->cmdc);
        allwindows(alllocker, (void*)0);
        globalincref = 0;
        free(loopstruct.w);
        allwindows(alllocker, (void*)0);
        globalincref = 0;
        free(loopstruct.w);
index 7011ad7b3a88a3c75bf18af2fe5303363637fda9..cff11431212268faa286218cf1df1a634594ebd9 100644 (file)
@@ -506,15 +506,27 @@ zeroxx(Text *et, Text *t, Text*, int, int, Rune*, int)
                winunlock(t->w);
 }
 
                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;
+};
+
 void
 get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
 {
        char *name;
        Rune *r;
        int i, n, dirty, samename, isdir;
 void
 get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
 {
        char *name;
        Rune *r;
        int i, n, dirty, samename, isdir;
+       TextAddr *addr, *a;
        Window *w;
        Text *u;
        Dir *d;
        Window *w;
        Text *u;
        Dir *d;
+       long q0, q1;
 
        if(flag1)
                if(et==nil || et->w==nil)
 
        if(flag1)
                if(et==nil || et->w==nil)
@@ -537,6 +549,14 @@ get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
                        return;
                }
        }
                        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];
        r = bytetorune(name, &n);
        for(i=0; i<t->file->ntext; i++){
                u = t->file->text[i];
@@ -562,8 +582,18 @@ get(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg)
        for(i=0; i<t->file->ntext; i++){
                u = t->file->text[i];
                textsetselect(&u->w->tag, u->w->tag.file->nc, u->w->tag.file->nc);
        for(i=0; i<t->file->ntext; i++){
                u = t->file->text[i];
                textsetselect(&u->w->tag, u->w->tag.file->nc, u->w->tag.file->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);
        }
                textscrdraw(u);
        }
+       free(addr);
        xfidlog(w, "get");
 }
 
        xfidlog(w, "get");
 }
 
index 5b5b7ac21202798ffcb479263ea9f53bae29a8df..02cc06da891f1de094010288dd8e355954719579 100644 (file)
@@ -88,6 +88,8 @@ Rune* skipbl(Rune*, int, int*);
 Rune*  findbl(Rune*, int, int*);
 char*  edittext(Window*, int, Rune*, int);
 void           flushwarnings(void);
 Rune*  findbl(Rune*, int, int*);
 char*  edittext(Window*, int, Rune*, int);
 void           flushwarnings(void);
+long   nlcount(Text*, long, long, long*);
+long   nlcounttopos(Text*, long, long, long);
 
 #define        runemalloc(a)           (Rune*)emalloc((a)*sizeof(Rune))
 #define        runerealloc(a, b)       (Rune*)erealloc((a), (b)*sizeof(Rune))
 
 #define        runemalloc(a)           (Rune*)emalloc((a)*sizeof(Rune))
 #define        runerealloc(a, b)       (Rune*)erealloc((a), (b)*sizeof(Rune))
index 172dfaa9955d2059273d5fd0bdd3bf9e34417dd2..9c2b640003d7589a6177de23a732866530db3ba9 100644 (file)
@@ -293,7 +293,7 @@ rowclean(Row *row)
 void
 rowdump(Row *row, char *file)
 {
 void
 rowdump(Row *row, char *file)
 {
-       int i, j, fd, m, n, dumped;
+       int i, j, fd, m, n, start, dumped;
        uint q0, q1;
        Biobuf *b;
        char *buf, *a, *fontname;
        uint q0, q1;
        Biobuf *b;
        char *buf, *a, *fontname;
@@ -396,10 +396,17 @@ rowdump(Row *row, char *file)
                        m = min(RBUFSIZE, w->tag.file->nc);
                        bufread(w->tag.file, 0, r, m);
                        n = 0;
                        m = min(RBUFSIZE, w->tag.file->nc);
                        bufread(w->tag.file, 0, r, m);
                        n = 0;
-                       while(n<m && r[n]!='\n')
-                               n++;
-                       r[n++] = '\n';
-                       Bprint(b, "%.*S", n, r);
+                       while(n<m) {
+                               start = n;
+                               while(n<m && r[n]!='\n')
+                                       n++;
+                               Bprint(b, "%.*S", n-start, r+start);
+                               if(n<m) {
+                                       Bputc(b, 0xff); // \n in tag becomes 0xff byte (invalid UTF)
+                                       n++;
+                               }
+                       }
+                       Bprint(b, "\n");
                        if(dumped){
                                q0 = 0;
                                q1 = t->file->nc;
                        if(dumped){
                                q0 = 0;
                                q1 = t->file->nc;
@@ -639,6 +646,10 @@ rowload(Row *row, char *file, int initing)
                if(l == nil)
                        goto Rescue2;
                l[Blinelen(b)-1] = 0;
                if(l == nil)
                        goto Rescue2;
                l[Blinelen(b)-1] = 0;
+               /* convert 0xff in multiline tag back to \n */
+               for(i=0; l[i]!=0; i++)
+                       if((uchar)l[i] == 0xff)
+                               l[i] = '\n';
                r = bytetorune(l+5*12, &nr);
                ns = -1;
                for(n=0; n<nr; n++){
                r = bytetorune(l+5*12, &nr);
                ns = -1;
                for(n=0; n<nr; n++){
index 1310bc763fbc2e6888f879abae64a9a2c5ec8ea7..0d417396852ebe954172ceec598eb16037b9118d 100644 (file)
@@ -132,7 +132,7 @@ textscroll(Text *t, int but)
                        readmouse(mousectl);
                        continue;
                }
                        readmouse(mousectl);
                        continue;
                }
-               if(but == 1)
+               if(but == 1 || but == 4)
                        p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
                else
                        p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
                        p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
                else
                        p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
@@ -140,7 +140,7 @@ textscroll(Text *t, int but)
                        textsetorigin(t, p0, TRUE);
                oldp0 = p0;
                /* debounce */
                        textsetorigin(t, p0, TRUE);
                oldp0 = p0;
                /* debounce */
-               if(first){
+               if(first && but < 4){
                        flushimage(display, 1);
                        sleep(200);
                        nbrecv(mousectl->c, &mousectl->Mouse);
                        flushimage(display, 1);
                        sleep(200);
                        nbrecv(mousectl->c, &mousectl->Mouse);
index ebbc5dcfd53fc46593c3788e2bb2887012783b0a..484ec3de12d1e829f785503911e767b3e1b8e4e4 100644 (file)
@@ -1411,7 +1411,7 @@ textsetorigin(Text *t, uint org, int exact)
        Rune *r;
        uint n;
 
        Rune *r;
        uint n;
 
-       if(org>0 && !exact){
+       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->nc; i++){
                /* 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->nc; i++){