ref: 0d2a10e4416dc7e9d94c8f37e4b0b27ddf2ccc73
parent: 479ecb171f1221861208ad62bc8b3ee412644489
author: Aidan Wiggins <akw@oneiri.one>
date: Mon Oct 27 15:32:04 EDT 2025
samterm: Roll our own kbd proc Now we can process Kshift characters so we may do Kshift+(Kup|Kdown) for moving one line at a time (as in rio). Also included is the ability to "extend" a selection in the direction of the initial selection, i.e. if we have: And, now, I don't mind a bit of a breeze, if anything I prefer it, but thon was aggressive. If we were to select "mind" to "breeze", then a shift+left-click to the right of "breeze" will extend the selection forward to that point, and if we were to shift+left-click to a point before "mind", the selection would reverse.
--- a/sys/src/cmd/samterm/flayer.c
+++ b/sys/src/cmd/samterm/flayer.c
@@ -23,7 +23,7 @@
Image *maincols[NCOL];
Image *cmdcols[NCOL];
-int sel;
+ulong sel;
void
flstart(Rectangle r)
@@ -253,7 +253,7 @@
}
int
-flselect(Flayer *l, ulong *p)
+flselect(Flayer *l)
{static int clickcount;
static Point clickpt = {-10, -10};@@ -264,7 +264,7 @@
dt = mousep->msec - l->click;
dx = abs(mousep->xy.x - clickpt.x);
dy = abs(mousep->xy.y - clickpt.y);
- *p = sel = frcharofpt(&l->f, mousep->xy) + l->origin;
+ sel = frcharofpt(&l->f, mousep->xy) + l->origin;
l->click = mousep->msec;
clickpt = mousep->xy;
@@ -284,7 +284,9 @@
{ulong fp0, fp1;
- if(l->visible==None || !flprepare(l)){+ if(sel != l->p0 && sel != l->p1)
+ sel = p0;
+ if(!flprepare(l)){l->p0 = p0, l->p1 = p1;
return;
}
--- a/sys/src/cmd/samterm/flayer.h
+++ b/sys/src/cmd/samterm/flayer.h
@@ -36,7 +36,7 @@
Rectangle flrect(Flayer*, Rectangle);
void flrefresh(Flayer*, Rectangle, int);
void flresize(Rectangle);
-int flselect(Flayer*, ulong*);
+int flselect(Flayer*);
void flsetselect(Flayer*, long, long);
void flstart(Rectangle);
void flupfront(Flayer*);
@@ -49,4 +49,4 @@
extern Image *maincols[NCOL];
extern Image *cmdcols[NCOL];
-extern int sel;
+extern ulong sel;
--- a/sys/src/cmd/samterm/io.c
+++ b/sys/src/cmd/samterm/io.c
@@ -16,6 +16,7 @@
int kbdc;
int resized;
int scrselecting;
+int shifted;
uchar *hostp;
uchar *hoststop;
uchar *plumbbase;
@@ -23,12 +24,77 @@
uchar *plumbstop;
Channel *plumbc;
Channel *hostc;
-Mousectl *mousectl;
+Mousectl *mousectl;
Mouse *mousep;
-Keyboardctl *keyboardctl;
-void panic(char*);
+Channel *kbdchan;
+static void
+kbdproc(void *arg)
+{+ Channel *c = arg;
+ char buf[1024], *p;
+ int cfd, kfd, n;
+
+ threadsetname("kbdproc");+ if((cfd = open("/dev/consctl", OWRITE)) < 0){+ chanprint(c, "%r");
+ return;
+ }
+ fprint(cfd, "rawon");
+
+ if(sendp(c, nil) <= 0)
+ return;
+
+ if((kfd = open("/dev/kbd", OREAD)) >= 0)+ while((n = read(kfd, buf, sizeof(buf))) > 0)
+ for(p = buf; p < buf+n; p += strlen(p)+1)
+ chanprint(c, "%s", p);
+}
+
+static Channel*
+initkbd(void)
+{+ Channel *c;
+ char *e;
+
+ c = chancreate(sizeof(char*), 20);
+ procrfork(kbdproc, c, 4096, RFCFDG);
+ if(e = recvp(c)){+ chanfree(c);
+ c = nil;
+ werrstr("%s", e);+ free(e);
+ }
+ return c;
+}
+
void
+kbdkey(char *s)
+{+ Rune r;
+ int type;
+
+ if(s == nil)
+ return;
+
+ type = *s++;
+ chartorune(&r, s);
+ if(r != Runeerror){+ switch(type){+ case 'k':
+ case 'K':
+ shifted = r == Kshift;
+ kbdc = -1;
+ break;
+ case 'c':
+ kbdc = r;
+ break;
+ }
+ }
+ free(s);
+}
+
+void
initio(void)
{ threadsetname("main");@@ -38,11 +104,7 @@
threadexitsall("mouse");}
mousep = mousectl;
- keyboardctl = initkeyboard(nil);
- if(keyboardctl == nil){- fprint(2, "samterm: keyboard init failed: %r\n");
- threadexitsall("kbd");- }
+ kbdchan = initkbd();
hoststart();
plumbstart();
}
@@ -82,7 +144,7 @@
waitforio(void)
{Alt alts[NRes+1];
- Rune r;
+ char *s;
int i;
ulong type;
@@ -100,8 +162,8 @@
if(block & (1<<RHost))
alts[RHost].op = CHANNOP;
- alts[RKeyboard].c = keyboardctl->c;
- alts[RKeyboard].v = &r;
+ alts[RKeyboard].c = kbdchan;
+ alts[RKeyboard].v = &s;
alts[RKeyboard].op = CHANRCV;
if(block & (1<<RKeyboard))
alts[RKeyboard].op = CHANNOP;
@@ -135,7 +197,7 @@
externload(i);
break;
case RKeyboard:
- kbdc = r;
+ kbdkey(s);
break;
case RMouse:
break;
@@ -268,12 +330,12 @@
int
ecankbd(void)
{- Rune r;
+ char *s;
if(kpeekc >= 0)
return 1;
- if(nbrecv(keyboardctl->c, &r) > 0){- kpeekc = r;
+ if(nbrecv(kbdchan, &s) > 0){+ kbdkey(s);
return 1;
}
return 0;
@@ -283,7 +345,7 @@
ekbd(void)
{int c;
- Rune r;
+ char *s;
if(kpeekc >= 0){c = kpeekc;
@@ -290,11 +352,12 @@
kpeekc = -1;
return c;
}
- if(recv(keyboardctl->c, &r) < 0){+ if(recv(kbdchan, &s) < 0){fprint(2, "samterm: keybard recv error: %r\n");
panic("kbd");}
- return r;
+ kbdkey(s);
+ return kpeekc;
}
int
--- a/sys/src/cmd/samterm/main.c
+++ b/sys/src/cmd/samterm/main.c
@@ -35,7 +35,6 @@
Text *t;
Rectangle r;
Flayer *nwhich;
- ulong p;
rfork(RFENVG|RFNAMEG);
@@ -106,19 +105,23 @@
scroll(which, (mousep->buttons&8) ? 4 : 1);
else if(nwhich && nwhich!=which)
current(nwhich);
- else if(ptinrect(mousep->xy, which->f.r)){- t = which->user1;
- nclick = flselect(which, &p);
- if(nclick > 0){- if(nclick > 1)
- outTsl(Ttclick, t->tag, p);
- else
- outTsl(Tdclick, t->tag, p);
- t->lock++;
- }else if(t!=&cmd)
- outcmd();
- if(mousep->buttons&1)
- chord = mousep->buttons;
+ else if(nwhich && ptinrect(mousep->xy, which->f.r)){+ if(shifted)
+ extendsel(which);
+ else{+ t = which->user1;
+ nclick = flselect(which);
+ if(nclick > 0){+ if(nclick > 1)
+ outTsl(Ttclick, t->tag, sel);
+ else
+ outTsl(Tdclick, t->tag, sel);
+ t->lock++;
+ }else if(t!=&cmd)
+ outcmd();
+ if(mousep->buttons&1)
+ chord = mousep->buttons;
+ }
}
}else if((mousep->buttons&2) && which){if(scr)
@@ -136,6 +139,20 @@
}
}
+void
+extendsel(Flayer *l)
+{+ ulong p;
+ do{+ p = l->origin+frcharofpt(&l->f, mousep->xy);
+ if(p < sel)
+ flsetselect(l, p, sel);
+ else
+ flsetselect(l, sel, p);
+ if(readmouse(mousectl) < 0)
+ panic("mouse");+ }while(mousep->buttons & (1|8));
+}
void
resize(void)
@@ -447,6 +464,9 @@
nontypingkey(int c)
{ switch(c){+ case Kalt:
+ case Kctl:
+ case Kshift:
case Kup:
case Kdown:
case Khome:
@@ -459,6 +479,7 @@
case Kenq:
case Kstx:
case Kbel:
+ case -1:
return 1;
}
return 0;
@@ -520,7 +541,7 @@
break;
}
}
- if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0]))
+ if(c == '\n' || p >= buf+nelem(buf))
break;
}
if(p > buf){@@ -542,7 +563,7 @@
}
if(c==Kdown){flushtyping(0);
- center(l, l->origin, l->f.maxlines/3);
+ center(l, l->origin, shifted? 1: l->f.maxlines/3);
}else if(c==Kpgdown){flushtyping(0);
center(l, l->origin, l->f.maxlines);
@@ -549,7 +570,7 @@
/* backspacing immediately after outcmd(): sorry */
}else if(c==Kup){flushtyping(0);
- center(l, l->origin, -(l->f.maxlines/3));
+ center(l, l->origin, shifted? -1: -(l->f.maxlines/3));
}else if(c==Kpgup){flushtyping(0);
center(l, l->origin, -l->f.maxlines);
--- a/sys/src/cmd/samterm/samterm.h
+++ b/sys/src/cmd/samterm/samterm.h
@@ -89,6 +89,7 @@
extern int exiting;
extern int autoindent;
extern int spacesindent;
+extern int shifted;
Rune *gettext(Flayer*, long, ulong*);
void *alloc(ulong n);
@@ -119,6 +120,7 @@
int xmenuhit(int, Menu*);
void buttons(int);
int getr(Rectangle*);
+void extendsel(Flayer*);
void current(Flayer*);
void duplicate(Flayer*, Rectangle, Font*, int);
void startfile(Text*);
--
⑨