ref: 03040ba3c0f62b0ea0ac86b84d63cda4f59f970b
parent: 78e2f69c0d7e4c17227e1ec0545cbb2a0ae1e96e
author: Aidan Wiggins <akw@oneiri.one>
date: Sat Oct 25 10:57:47 EDT 2025
samterm: Simplify scrolling mechanics This keeps Torigin messages contained to mostly center(). So now center() takes an origin and line offset, to then move either locally on the terminal (n > 0), or via messages to & from the host (n <= 0). With this, Kup/Kdown go by 1/3 of the screen (as in rio), and Kpgup/Kpgdown go by # of lines on the screen, so a Kpgup undoes a Kpgdown. This also makes scrolling look smoother by flushing the display only when necessary.
--- a/sys/src/cmd/samterm/io.c
+++ b/sys/src/cmd/samterm/io.c
@@ -15,6 +15,7 @@
int block;
int kbdc;
int resized;
+int scrselecting;
uchar *hostp;
uchar *hoststop;
uchar *plumbbase;
@@ -47,6 +48,13 @@
}
void
+flushdisplay(void)
+{+ if(display->bufp > display->buf)
+ flushimage(display, 1);
+}
+
+void
getmouse(void)
{if(readmouse(mousectl) < 0)
@@ -128,8 +136,8 @@
if(got & ~block)
return got & ~block;
- if(display->bufp > display->buf)
- flushimage(display, 1);
+ if(!scrselecting)
+ flushdisplay();
type = alt(alts);
switch(type){case RHost:
@@ -182,7 +190,6 @@
{Flayer *l = which;
Text *t = l->user1;
- long p;
if(nbrecv(mousectl->c, &mousectl->Mouse) < 0)
panic("mouse");@@ -195,11 +202,14 @@
l->p0 = sel;
l->p1 = l->origin+f->p0;
}
- scrorigin(l, 1, -n+1);
}else if(n == 0){+ flushdisplay();
sleep(25);
return;
}else{+ /* don't scroll off the end */
+ if(l->origin+f->nchars == t->rasp.nrunes)
+ return;
if(sel >= l->origin+f->p1){l->p0 = l->origin+f->p1;
l->p1 = sel;
@@ -207,20 +217,24 @@
l->p0 = sel;
l->p1 = l->origin+f->p1;
}
- p = l->origin;
- if(l->origin+f->nchars != t->rasp.nrunes)
- p += frcharofpt(f, Pt(l->scroll.max.x, l->scroll.min.y + n * f->font->height));
- scrorigin(l, 2, p);
}
+ flushdisplay();
+ center(l, l->origin, n);
+ if(n > 0 && !t->lock)
+ /* no msg sent */
+ return;
+
/*
* we must pull io from host while we are in frame(2)
*/
+ scrselecting = 1;
do{block = ~(1 << RHost);
waitforio();
rcv();
}while(t->lock);
+ scrselecting = 0;
}
int
--- a/sys/src/cmd/samterm/main.c
+++ b/sys/src/cmd/samterm/main.c
@@ -312,26 +312,6 @@
}
}
-void
-scrorigin(Flayer *l, int but, long p0)
-{- Text *t=(Text *)l->user1;
-
- if(t->tag == Untagged)
- return;
-
- switch(but){- case 1:
- outTsll(Torigin, t->tag, l->origin, p0);
- break;
- case 2:
- outTsll(Torigin, t->tag, p0, 1L);
- break;
- case 3:
- horigin(t->tag,p0);
- }
-}
-
int
alnum(int c)
{@@ -415,40 +395,25 @@
return p>=o? p : o;
}
-int
-center(Flayer *l, long a)
+void
+center(Flayer *l, long a, int n)
{Text *t;
t = l->user1;
- if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){- if(a > t->rasp.nrunes)
- a = t->rasp.nrunes;
- outTsll(Torigin, t->tag, a, 2L);
- return 1;
- }
- return 0;
-}
+ if(t->lock || t->tag == Untagged)
+ return;
-int
-onethird(Flayer *l, long a)
-{- Text *t;
- Rectangle s;
- long lines;
+ if(n > 0)
+ a += frcharofpt(&l->f, Pt(l->scroll.max.x, l->scroll.min.y + n * l->f.font->height));
+ if(a > t->rasp.nrunes)
+ a = t->rasp.nrunes;
- t = l->user1;
- if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){- if(a > t->rasp.nrunes)
- a = t->rasp.nrunes;
- s = insetrect(l->scroll, 1);
- lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3;
- if (lines < 2)
- lines = 2;
- outTsll(Torigin, t->tag, a, lines);
- return 1;
- }
- return 0;
+ if(n > 0)
+ /* we can center locally */
+ horigin(t->tag, a);
+ else
+ outTsll(Torigin, t->tag, a, -n+1);
}
void
@@ -506,7 +471,7 @@
Rune buf[100];
Rune *p = buf;
int c, backspacing;
- long a, a0;
+ long a;
int scrollkey;
scrollkey = 0;
@@ -571,38 +536,46 @@
typeend = a;
if(c=='\n' || typeend-typestart>100)
flushtyping(0);
- onethird(l, a);
+ if(a < l->origin || a > l->origin+l->f.nchars)
+ center(l, a, -(l->f.maxlines/3));
}
- if(c==Kdown || c==Kpgdown){+ if(c==Kdown){flushtyping(0);
- center(l, l->origin+l->f.nchars+1);
+ center(l, l->origin, l->f.maxlines/3);
+ }else if(c==Kpgdown){+ flushtyping(0);
+ center(l, l->origin, l->f.maxlines);
/* backspacing immediately after outcmd(): sorry */
- }else if(c==Kup || c==Kpgup){+ }else if(c==Kup){flushtyping(0);
- a0 = l->origin-l->f.nchars;
- if(a0 < 0)
- a0 = 0;
- center(l, a0);
- }else if(c == Kright){+ center(l, l->origin, -(l->f.maxlines/3));
+ }else if(c==Kpgup){flushtyping(0);
- a0 = l->p1;
- if(a0 < t->rasp.nrunes)
- a0++;
- flsetselect(l, a0, a0);
- center(l, a0);
+ center(l, l->origin, -l->f.maxlines);
}else if(c == Kleft){flushtyping(0);
- a0 = l->p0;
- if(a0 > 0)
- a0--;
- flsetselect(l, a0, a0);
- center(l, a0);
- }else if(c == Khome){+ if(l->p0 > 0){+ l->p0--;
+ flsetselect(l, l->p0, l->p0);
+ if(l->p0 < l->origin || l->p0 > l->origin+l->f.nchars)
+ center(l, l->p0, 0);
+ }
+ }else if(c == Kright){flushtyping(0);
- center(l, 0);
+ if(l->p1 < t->rasp.nrunes){+ l->p1++;
+ if(l->p1 == l->origin+l->f.nchars && l->p1 != t->rasp.nrunes)
+ center(l, l->origin, 1);
+ else if(l->p1 < l->origin || l->p1 > l->origin+l->f.nchars)
+ center(l, l->p1, 0);
+ flsetselect(l, l->p1, l->p1);
+ }
+ }else if(c == Khome){+ flushtyping(0);
+ center(l, 0, 0);
}else if(c == Kend){flushtyping(0);
- center(l, t->rasp.nrunes);
+ center(l, t->rasp.nrunes, -(l->f.maxlines/3));
}else if(c == Ksoh || c == Kenq){flushtyping(1);
if(c == Ksoh)
@@ -664,7 +637,7 @@
flushtyping(0);
a = t->rasp.nrunes;
flsetselect(l, a, a);
- center(l, a);
+ center(l, a, 0);
}else if(c == Kbel){int i;
if(work == nil)
--- a/sys/src/cmd/samterm/mesg.c
+++ b/sys/src/cmd/samterm/mesg.c
@@ -207,8 +207,11 @@
if(m == cmd.tag){ for(i=0; i<NL; i++){lp = &cmd.l[i];
- if(lp->textfn)
- center(lp, l>=0? l : lp->p1);
+ if(lp->textfn){+ l = l >= 0? l: lp->p1;
+ if(l < lp->origin || l > lp->origin+lp->f.nchars)
+ center(lp, l, -1);
+ }
}
}
break;
--- a/sys/src/cmd/samterm/samterm.h
+++ b/sys/src/cmd/samterm/samterm.h
@@ -116,7 +116,7 @@
void cut(Text*, int, int, int);
void paste(Text*, int);
void snarf(Text*, int);
-int center(Flayer*, long);
+void center(Flayer*, long, int);
int xmenuhit(int, Menu*);
void buttons(int);
int getr(Rectangle*);
@@ -154,7 +154,6 @@
void rresize(Rasp *, long, long, long);
void rdata(Rasp*, long, long, Rune*);
void rclean(Rasp*);
-void scrorigin(Flayer*, int, long);
long scrtotal(Flayer*);
void flnewlyvisible(Flayer*);
char *rcvstring(void);
--- a/sys/src/cmd/samterm/scroll.c
+++ b/sys/src/cmd/samterm/scroll.c
@@ -108,8 +108,8 @@
int in = 0, oin;
long tot = scrtotal(l);
Rectangle scr, r, s, rt;
- int x, y, my, oy, h;
- long p0;
+ int x, y, my, oy, n;
+ long p0, o;
if(l->visible==None)
return;
@@ -155,23 +155,15 @@
}
}while(but <= 3 && button(but));
if(in){- h = s.max.y-s.min.y;
scrunmark(l, r);
- p0 = 0;
- if(but == 1 || but == 4){- but = 1;
- p0 = (long)(my-s.min.y)/l->f.font->height+1;
- }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 || but == 5){- but = 3;
- p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
- if(p0 > tot)
- p0 = tot;
+ if(but == 2){+ n = 0;
+ o = (tot / (s.max.y - s.min.y)) * (my - s.min.y);
+ }else{+ n = (my - s.min.y)/l->f.font->height;
+ n *= (but == 1 || but == 4)? -1: 1;
+ o = l->origin;
}
- scrorigin(l, but, p0);
+ center(l, o, n);
}
}
--
⑨