Thanks for sharing this! I'd already backported a few of the features, but I hadn't yet got around to looking at the chording code etc. It's great to have selection working! I'm not sure if I did something wrong (I've checked the changes a few times) but scrolling only works "sometimes", mostly it seems to get stuck when scrolling back up? Can anyone confirm? In my experience sam's scrolling seems to be pretty broken (at least in the plan9port version) so it might not have anything to do with these changes.

All the best,

P.S. where does Kcmd come from? I've grepped the plan9port tree but I don't see a definition?

On Fri, 27 May 2016 at 00:05 <trebol55555@yandex.ru> wrote:
The 9front sam in

        https://bitbucket.org/kremlin_/front9port
        https://bitbucket.org/iru/sam9f-unix

doesn't exchange the snarf buffer with X, and the pipe in /srv doesn't
work.

This diff will makes the minimal changes to have those features of 9front
sam in the last p9p. The code fell off from the front.

trebol.


diff -rpuN src/cmd/sam/cmd.c sam/cmd.c
--- src/cmd/sam/cmd.c   2016-04-18 19:07:22.000000000 +0100
+++ sam/cmd.c   2016-05-25 23:56:34.040909362 +0100
@@ -35,6 +35,8 @@ struct cmdtab cmdtab[]={
        '>',    0,      0,      0,      0,      aDot,   0,      linex,  plan9_cmd,
        '<',    0,      0,      0,      0,      aDot,   0,      linex,  plan9_cmd,
        '|',    0,      0,      0,      0,      aDot,   0,      linex,  plan9_cmd,
+       '^',    0,      0,      0,      0,      aDot,   0,      linex,  plan9_cmd,
+       '_',    0,      0,      0,      0,      aDot,   0,      linex,  plan9_cmd,
        '=',    0,      0,      0,      0,      aDot,   0,      linex,  eq_cmd,
        'c'|0x100,0,    0,      0,      0,      aNo,    0,      wordx,  cd_cmd,
        0,      0,      0,      0,      0,      0,      0,      0
@@ -76,7 +78,13 @@ inputc(void)

     Again:
        nbuf = 0;
-       if(downloaded){
+       if(cmdbufpos > cmdbuf.nc && cmdbuf.nc > 0){
+               cmdbufpos = 0;
+               bufreset(&cmdbuf);
+       }
+       if(cmdbufpos < cmdbuf.nc && cmdbuf.nc > 0)
+               bufread(&cmdbuf, cmdbufpos++, &r, 1);
+       else if(downloaded){
                while(termoutp == terminp){
                        cmdupdate();
                        if(patset)
diff -rpuN src/cmd/sam/sam.h sam/sam.h
--- src/cmd/sam/sam.h   2016-04-18 19:07:22.000000000 +0100
+++ sam/sam.h   2016-05-25 23:45:05.652931784 +0100
@@ -369,6 +369,8 @@ extern int  quitok;
 extern Address addr;
 extern Buffer  snarfbuf;
 extern Buffer  plan9buf;
+extern Buffer  cmdbuf;
+extern int     cmdbufpos;
 extern List    file;
 extern List    tempfile;
 extern File    *cmd;
diff -rpuN src/cmd/sam/shell.c sam/shell.c
--- src/cmd/sam/shell.c 2016-04-18 19:07:22.000000000 +0100
+++ sam/shell.c 2016-05-25 23:46:25.262692361 +0100
@@ -6,6 +6,8 @@ extern  jmp_buf mainloop;
 char   errfile[64];
 String plan9cmd;       /* null terminated */
 Buffer plan9buf;
+Buffer cmdbuf;
+int    cmdbufpos;
 void   checkerrs(void);

 void
@@ -40,7 +42,7 @@ plan9(File *f, int type, String *s, int
        }
        if(type!='!' && pipe(pipe1)==-1)
                error(Epipe);
-       if(type=='|')
+       if(type=='|' || type=='_')
                snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
        if((pid=fork()) == 0){
                setname(f);
@@ -61,14 +63,14 @@ plan9(File *f, int type, String *s, int
                        }
                }
                if(type != '!') {
-                       if(type=='<' || type=='|')
-                               dup(pipe1[1], 1);
-                       else if(type == '>')
+                       if(type == '>')
                                dup(pipe1[0], 0);
+                       else
+                               dup(pipe1[1], 1);
                        close(pipe1[0]);
                        close(pipe1[1]);
                }
-               if(type == '|'){
+               if(type == '|' || type == '_'){
                        if(pipe(pipe2) == -1)
                                exits("pipe");
                        if((pid = fork())==0){
@@ -100,7 +102,7 @@ plan9(File *f, int type, String *s, int
                        close(pipe2[0]);
                        close(pipe2[1]);
                }
-               if(type=='<'){
+               if(type=='<' || type=='^'){
                        close(0);       /* so it won't read from terminal */
                        open("/dev/null", 0);
                }
@@ -128,9 +130,14 @@ plan9(File *f, int type, String *s, int
                writeio(f);
                bpipeok = 0;
                closeio((Posn)-1);
+       }else if(type == '^' || type == '_'){
+               int nulls;
+               close(pipe1[1]);
+               bufload(&cmdbuf, cmdbufpos, pipe1[0], &nulls);
+               close(pipe1[0]);
        }
        retcode = waitfor(pid);
-       if(type=='|' || type=='<')
+       if(type=='|' || type=='<' || type=='_' || type=='^')
                if(retcode!=0)
                        warn(Wbadstatus);
        if(downloaded)
diff -rpuN src/cmd/samterm/main.c samterm/main.c
--- src/cmd/samterm/main.c      2016-04-18 19:07:22.000000000 +0100
+++ samterm/main.c      2016-05-26 16:12:12.452556184 +0100
@@ -23,11 +23,8 @@ long modified = 0;           /* strange lookahead
 char   hostlock = 1;
 char   hasunlocked = 0;
 int    maxtab = 8;
-int    chord;
 int    autoindent;

-#define chording 0     /* code here for reference but it causes deadlocks */
-
 void
 notifyf(void *a, char *msg)
 {
@@ -39,7 +36,7 @@ notifyf(void *a, char *msg)
 void
 threadmain(int argc, char *argv[])
 {
-       int i, got, scr, w;
+       int i, got, scr, chord, w;
        Text *t;
        Rectangle r;
        Flayer *nwhich;
@@ -85,6 +82,7 @@ threadmain(int argc, char *argv[])

        got = 0;
        if(protodebug) print("loop\n");
+       chord = 0;
        for(;;got = waitforio()){
                if(hasunlocked && RESIZED())
                        resize();
@@ -108,19 +106,32 @@ threadmain(int argc, char *argv[])
                                continue;
                        }
                        nwhich = flwhich(mousep->xy);
-                       scr = which && ptinrect(mousep->xy, which->scroll);
+                       scr = which && (ptinrect(mousep->xy, which->scroll) ||
+                               mousep->buttons&(8|16));
                        if(mousep->buttons)
                                flushtyping(1);
-                       if(chording && chord==1 && !mousep->buttons)
+                       if((mousep->buttons&1)==0)
                                chord = 0;
-                       if(chording && chord)
+                       if(chord && which && which==nwhich){
                                chord |= mousep->buttons;
-                       else if(mousep->buttons&1){
+                               t = (Text *)which->user1;
+                               if(!t->lock){
+                                       w = which-t->l;
+                                       if(chord&2){
+                                               cut(t, w, 1, 1);
+                                               chord &= ~2;
+                                       }
+                                       if(chord&4){
+                                               paste(t, w);
+                                               chord &= ~4;
+                                       }
+                               }
+                       }else if(mousep->buttons&(1|8)){
                                if(nwhich){
                                        if(nwhich!=which)
                                                current(nwhich);
                                        else if(scr)
-                                               scroll(which, 1);
+                                               scroll(which, (mousep->buttons&8) ? 4 : 1);
                                        else{
                                                t=(Text *)which->user1;
                                                if(flselect(which)){
@@ -137,27 +148,14 @@ threadmain(int argc, char *argv[])
                                        scroll(which, 2);
                                else
                                        menu2hit();
-                       }else if((mousep->buttons&4)){
+                       }else if(mousep->buttons&(4|16)){
                                if(scr)
-                                       scroll(which, 3);
+                                       scroll(which, (mousep->buttons&16) ? 5 : 3);
                                else
                                        menu3hit();
                        }
                        mouseunblock();
                }
-               if(chording && chord){
-                       t = (Text*)which->user1;
-                       if(!t->lock && !hostlock){
-                               w = which-t->l;
-                               if(chord&2){
-                                       cut(t, w, 1, 1);
-                                       chord &= ~2;
-                               }else if(chord&4){
-                                       paste(t, w);
-                                       chord &= ~4;
-                               }
-                       }
-               }
        }
 }

@@ -497,6 +495,7 @@ flushtyping(int clearesc)
 #define        CUT     (Kcmd+'x')
 #define        COPY    (Kcmd+'c')
 #define        PASTE   (Kcmd+'v')
+#define        Kstx    0x02

 int
 nontypingkey(int c)
@@ -512,6 +511,7 @@ nontypingkey(int c)
        case PAGEUP:
        case RIGHTARROW:
        case SCROLLKEY:
+       case Kstx:
                return 1;
        }
        if(c >= Kcmd)
@@ -669,6 +669,15 @@ type(Flayer *l, int res)   /* what a blood
                                }
                        }
                }
+       }else if(c == Kstx){
+               t = &cmd;
+               for(l=t->l; l->textfn==0; l++)
+                       ;
+               current(l);
+               flushtyping(0);
+               a = t->rasp.nrunes;
+               flsetselect(l, a, a);
+               center(l, a);
        }else{
                if(c==ESC && typeesc>=0){
                        l->p0 = typeesc;
diff -rpuN src/cmd/samterm/scroll.c samterm/scroll.c
--- src/cmd/samterm/scroll.c    2016-04-18 19:07:22.000000000 +0100
+++ samterm/scroll.c    2016-05-26 02:07:31.922977720 +0100
@@ -115,7 +115,7 @@ scroll(Flayer *l, int but)
        draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min);
        do{
                oin = in;
-               in = abs(x-mousep->xy.x)<=FLSCROLLWID(l)/2;
+               in = (but > 3) || (but == 2) || abs(x-mousep->xy.x)<=FLSCROLLWID(l)/2;
                if(oin && !in)
                        scrunmark(l, r);
                if(in){
@@ -126,9 +126,7 @@ scroll(Flayer *l, int but)
                                my = s.min.y;
                        if(my >= s.max.y)
                                my = s.max.y;
-                       if(!eqpt(mousep->xy, Pt(x, my)))
-                               moveto(mousectl, Pt(x, my));
-                       if(but == 1){
+                       if(but == 1 || but == 4){
                                p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my));
                                rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
                                y = rt.min.y;
@@ -136,7 +134,7 @@ scroll(Flayer *l, int but)
                                y = my;
                                if(y > s.max.y-2)
                                        y = s.max.y-2;
-                       }else if(but == 3){
+                       }else if(but == 3 || but == 5){
                                p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
                                rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
                                y = rt.min.y;
@@ -147,19 +145,21 @@ scroll(Flayer *l, int but)
                                scrmark(l, r);
                        }
                }
-       }while(button(but));
+       }while(but <= 3 && button(but));
        if(in){
                h = s.max.y-s.min.y;
                scrunmark(l, r);
                p0 = 0;
-               if(but == 1)
+               if(but == 1 || but == 4){
+                       but = 1;
                        p0 = (long)(my-s.min.y)/l->f.font->height+1;
-               else if(but == 2){
+               }else if(but == 2){
                        if(tot > 1024L*1024L)
                                p0 = ((tot>>10)*(y-s.min.y)/h)<<10;
                        else
                                p0 = tot*(y-s.min.y)/h;
-               }else if(but == 3){
+               }else if(but == 3 || but == 5){
+                       but = 3;
                        p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
                        if(p0 > tot)
                                p0 = tot;