shithub: fork

Download patch

ref: e1bb0942d72079e7659cff7a6743d7a3508b7eea
parent: ffcdfa59715eb8241bd2be721831e6c43fa3a7b3
author: qwx <qwx@sciops.net>
date: Mon Nov 3 05:19:57 EST 2025

Subject: [PATCH] samterm: Make scrollbar act like rio's

Now, if you hold-click on the scrollbar, it will continuously scroll;
this is instad of just showing where the scrollbar would be placed once
the mouse is released.  This uses the same host-flushing mechanism
needed by frscroll().

Also, instead of the following scrollbar-to-line mapping,

————————————————
|[0]| Line 0
|[1]| Line 1
|[2]| Line 2

we should match rio's:

————————————————
|[1]| Line 0
|[1]| Line 1
|[2]| Line 2

--- a/sys/src/cmd/jamterm/io.c
+++ b/sys/src/cmd/jamterm/io.c
@@ -55,13 +55,6 @@
 }
 
 void
-getmouse(void)
-{
-	if(readmouse(mousectl) < 0)
-		panic("mouse");
-}
-
-void
 mouseunblock(void)
 {
 	got &= ~(1<<RMouse);
@@ -73,13 +66,6 @@
 	block = (1<<RKeyboard)|(1<<RPlumb);
 }
 
-int
-button(int but)
-{
-	getmouse();
-	return mousep->buttons&(1<<(but-1));
-}
-
 void
 externload(int i)
 {
@@ -185,7 +171,30 @@
 	return (char*)hostp;
 }
 
+/*
+ * when doing consecutive scrolling operations outside of the main loop
+ * in threadmain(), we need to wait for any RHost messages we've sent to
+ * come back from the host.
+ */
 void
+forcenter(Flayer *l, ulong a, int n)
+{
+	Text *t = l->user1;
+
+	flushdisplay();
+	center(l, a, n);
+	if(n > 0 && !t->lock)
+		/* no msg sent */
+		return;
+
+	do{
+		block = ~(1 << RHost);
+		waitforio();
+		rcv();
+	}while(t->lock);
+}
+
+void
 frscroll(Frame *f, int n)
 {
 	Flayer *l = which;
@@ -218,22 +227,8 @@
 			l->p1 = l->origin+f->p1;
 		}
 	}
-
-	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);
+	forcenter(l, l->origin, n);
 	scrselecting = 0;
 }
 
--- a/sys/src/cmd/jamterm/main.c
+++ b/sys/src/cmd/jamterm/main.c
@@ -319,7 +319,8 @@
 buttons(int updown)
 {
 	while(((mousep->buttons&7)!=0) != updown)
-		getmouse();
+		if(readmouse(mousectl) < 0)
+			panic("mouse");
 }
 
 void
--- a/sys/src/cmd/jamterm/samterm.h
+++ b/sys/src/cmd/jamterm/samterm.h
@@ -100,15 +100,14 @@
 void	outcmd(void);
 void	rinit(Rasp*);
 void	startnewfile(int, Text*);
-void	getmouse(void);
 void	mouseunblock(void);
 void	kbdblock(void);
 void	hoststart(void);
 int	plumbstart(void);
-int	button(int but);
 int	load(char*, int);
 int	waitforio(void);
 int	rcvchar(void);
+void	forcenter(Flayer*, ulong, int);
 void	frscroll(Frame*, int);
 int	getch(void);
 int	kbdchar(void);
@@ -163,7 +162,6 @@
 void	flushtyping(int);
 void	dumperrmsg(int, int, int, int);
 int	screensize(int*,int*);
-void	getmouse(void);
 Rectangle inflatepoint(Point);
 int	promptrect(Rectangle*, Flayer*, int);
 Rectangle	defaultcmdrect(void);
--- a/sys/src/cmd/jamterm/scroll.c
+++ b/sys/src/cmd/jamterm/scroll.c
@@ -9,7 +9,6 @@
 #include "samterm.h"
 
 static Image *scrtmp;
-static Image *scrback;
 
 void
 scrtemps(void)
@@ -21,8 +20,7 @@
 	if(screensize(0, &h) == 0)
 		h = 2048;
 	scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0);
-	scrback = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0);
-	if(scrtmp==0 || scrback==0)
+	if(scrtmp==0)
 		panic("scrtemps");
 }
 
@@ -52,27 +50,6 @@
 }
 
 void
-scrmark(Flayer *l, Rectangle r)
-{
-	r.max.x--;
-	if(rectclip(&r, l->scroll)) {
-		if (l->f.b == nil)
-			panic("scrmark: nil l->f.b");
-		draw(l->f.b, r, l->f.cols[HIGH], nil, ZP);
-	}
-}
-
-void
-scrunmark(Flayer *l, Rectangle r)
-{
-	if(rectclip(&r, l->scroll)) {
-		if (l->f.b == nil)
-			panic("scrunmark: nil l->f.b");
-		draw(l->f.b, r, scrback, nil, Pt(0, r.min.y-l->scroll.min.y));
-	}
-}
-
-void
 scrdraw(Flayer *l, long tot)
 {
 	Rectangle r, r1, r2;
@@ -105,65 +82,46 @@
 void
 scroll(Flayer *l, int but)
 {
-	int in = 0, oin;
-	long tot = scrtotal(l);
-	Rectangle scr, r, s, rt;
-	int x, y, my, oy, n;
-	long p0, o;
+	Rectangle s;
+	int my, n;
+	long o, tot;
+	int once;
 
 	if(l->visible==None)
 		return;
 
+	once = 0;
 	s = l->scroll;
-	x = s.min.x+FLSCROLLWID/2;
-	scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot);
-	r = scr;
-	y = scr.min.y;
-	my = mousep->xy.y;
-	draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min);
+	tot = scrtotal(l);
 	do{
-		oin = in;
-		in = (but > 3) || (but == 2) || abs(x-mousep->xy.x)<=FLSCROLLWID/2;
-		if(oin && !in)
-			scrunmark(l, r);
-		if(in){
-			scrmark(l, r);
-			oy = y;
-			my = mousep->xy.y;
-			if(my < s.min.y)
-				my = s.min.y;
-			if(my >= s.max.y)
-				my = s.max.y;
-			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;
-			}else if(but == 2){
-				y = my;
-				if(y > s.max.y-2)
-					y = s.max.y-2;
-			}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;
-			}
-			if(y != oy){
-				scrunmark(l, r);
-				r = rectaddpt(scr, Pt(0, y-scr.min.y));
-				scrmark(l, r);
-			}
-		}
-	}while(but <= 3 && button(but));
-	if(in){
-		scrunmark(l, r);
+		my = mousep->xy.y;
+		if(my < s.min.y)
+			my = s.min.y;
+		if(my > s.max.y)
+			my = s.max.y;
+		my -= s.min.y;
 		if(but == 2){
+			o = (tot / (s.max.y - s.min.y)) * my;
 			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;
+			n = my/l->f.font->height;
+			if(n == 0)
+				n++;
+			if(but == 1 || but == 4)
+				n = -n;
+			if(!once){
+				if(but == 4 || but == 5){
+					center(l, o, n);
+					return;
+				}
+				once++;
+				sleep(175);
+			}
+			sleep(25);
 		}
-		center(l, o, n);
-	}
+		forcenter(l, o, n);
+		if(nbrecv(mousectl->c, mousectl) < 0)
+			panic("mouse");
+	}while(mousectl->buttons & (1 << (but-1)));
 }
--