ref: 522979e76a67e0a0d5d677ef9ded8b43844497f4
parent: e1bb0942d72079e7659cff7a6743d7a3508b7eea
author: qwx <qwx@sciops.net>
date: Mon Nov 3 05:21:44 EST 2025
jamterm: scroll by 1 line with shift, extend selection with shift click (thanks akw) Subject: [PATCH] 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/jamterm/flayer.c
+++ b/sys/src/cmd/jamterm/flayer.c
@@ -23,7 +23,7 @@
Image *maincols[NCOL];
Image *cmdcols[NCOL];
-int sel;
+ulong sel;
void
flstart(Rectangle r)
@@ -274,7 +274,7 @@
}
int
-flselect(Flayer *l, ulong *p)
+flselect(Flayer *l)
{static int clickcount;
static Point clickpt = {-10, -10};@@ -285,7 +285,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;
@@ -305,7 +305,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/jamterm/flayer.h
+++ b/sys/src/cmd/jamterm/flayer.h
@@ -40,7 +40,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*);
@@ -53,4 +53,4 @@
extern Image *maincols[NCOL];
extern Image *cmdcols[NCOL];
-extern int sel;
+extern ulong sel;
--- a/sys/src/cmd/jamterm/io.c
+++ b/sys/src/cmd/jamterm/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, "jamterm: 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){- fprint(2, "jamterm: keybard recv error: %r\n");
+ 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/jamterm/main.c
+++ b/sys/src/cmd/jamterm/main.c
@@ -36,7 +36,6 @@
Text *t;
Rectangle r;
Flayer *nwhich;
- ulong p;
rfork(RFENVG|RFNAMEG);
@@ -108,19 +107,23 @@
current(nwhich, 1, 1);
if(ptinrect(mousep->xy, which->scroll) || mousep->buttons & 8)
scroll(which, (mousep->buttons&8) ? 4 : 1);
- 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(nwhich && nwhich!=which)
@@ -142,6 +145,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)
@@ -499,6 +516,9 @@
nontypingkey(int c)
{ switch(c){+ case Kalt:
+ case Kctl:
+ case Kshift:
case Kup:
case Kdown:
case Khome:
@@ -512,6 +532,7 @@
case Kstx:
case Kbel:
case Ksyn:
+ case -1:
return 1;
}
return 0;
@@ -573,7 +594,7 @@
break;
}
}
- if(c == '\n' || p >= buf+sizeof(buf)/sizeof(buf[0]))
+ if(c == '\n' || p >= buf+nelem(buf))
break;
}
if(p > buf){@@ -596,7 +617,7 @@
if(c==Kdown){flushtyping(0);
//scrorigin(l, 3, l->origin+frcharofpt(&l->f, Pt(l->scroll.max.x, l->scroll.min.y + l->f.font->height)));
- center(l, l->origin, l->f.maxlines/3);
+ center(l, l->origin, shifted? 1: l->f.maxlines/3);
}else if(c==Kpgdown){flushtyping(0);
//scrorigin(l, 3, l->origin+frcharofpt(&l->f, Pt(l->scroll.max.x, l->scroll.max.y - l->f.font->height)));
@@ -605,7 +626,7 @@
}else if(c==Kup){flushtyping(0);
//scrorigin(l, 1, 2);
- center(l, l->origin, -(l->f.maxlines/3));
+ center(l, l->origin, shifted? -1: -(l->f.maxlines/3));
}else if(c==Kpgup){flushtyping(0);
//scrorigin(l, 1, Dy(l->scroll)/l->f.font->height);
--- a/sys/src/cmd/jamterm/samterm.h
+++ b/sys/src/cmd/jamterm/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);
void warpmouse(Flayer*);
+void extendsel(Flayer*);
void current(Flayer*, int, int);
void duplicate(Flayer*, Rectangle, Font*, int);
void startfile(Text*);
--
⑨