shithub: libscroll

Download patch

ref: 0adb432869b58347d874cd8961584817cd478c26
parent: 25bcd2fab4c8c6bdc15f72140c966612a2409c44
author: spew <spew@palas>
date: Fri Feb 21 19:23:00 EST 2025

add another demo

--- /dev/null
+++ b/scrolldemo/demolines.c
@@ -1,0 +1,180 @@
+/* This example measures distance in lines which results in
+ * more accurate scrolling. The values of p₀, p₁ and tot passed
+ * to scrollpos are in lines. This is to demonstrate that the
+ * caller can choose their own units for the scroll functions.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <cursor.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <frame.h>
+#include "../scroll.h"
+
+typedef struct Text Text;
+struct Text {
+	Frame;
+	Scroll;
+	Rune *text;
+	uint org, len, cap, line, lines;
+};
+
+Image *cols[NCOL];
+char buf[32000];
+Rune lorem[32000];
+
+enum
+{
+	MOUSE,
+	KEYBD,
+	RESIZE,
+	NCHAN,
+};
+
+void
+textinit(Text *t)
+{
+	Rectangle r;
+
+	if(t->text == nil){
+		t->cap = 8192;
+		t->text = mallocz(t->cap*sizeof(*t->text), 1);
+		t->len = 0;
+	}
+	r = scrollinit(t, screen->r, screen, cols);
+	frclear(t, 0);
+	frinit(t, r, display->defaultfont, screen, cols);
+}
+
+void
+textdraw(Text *t)
+{
+	draw(screen, screen->r, cols[BACK], nil, ZP);
+	frinsert(t, t->text+t->org, t->text+t->len, 0);
+	scrollpos(t, t->line, t->line+t->Frame.nlines, t->lines);
+	flushimage(display, 1);
+}
+
+void
+line2org(Text *t, uint line)
+{
+	t->line = line;
+	t->org = 0;
+	while(line > 0)
+		if(t->text[t->org++] == L'\n') line--;
+}
+
+void
+textmouse(Text *t, Mousectl *mc)
+{
+	if(scrollactive(t, mc)){
+		while(mc->buttons == 2){
+			line2org(t, scrollscr(t, mc));
+			textdraw(t);
+			readmouse(mc);
+		}
+		if(mc->buttons == 1 || mc->buttons == 8 || mc->buttons == 4 || mc->buttons == 16){
+			line2org(t, scrollscr(t, mc));
+			textdraw(t);
+		}
+	}
+}
+
+void
+textaddrunes(Text *t, Rune *s)
+{
+	Rune *rp;
+	int len;
+
+	len = runestrlen(s);
+	while(len > t->cap-t->len+1){
+		t->cap *= 2;
+		t->text = realloc(t->text, t->cap*sizeof(*t->text));
+	}
+	runestrecpy(t->text+t->len, t->text+t->cap, s);
+	for(rp = t->text+t->len; *rp != L'\0'; rp++)
+		if(*rp == L'\n') t->lines++;
+	t->len += len;
+}
+
+void
+textresize(Text *t)
+{
+	static char s[512];
+
+	if(getwindow(display, Refnone) < 0)
+		sysfatal("%s: %r", argv0);
+	textinit(t);
+	textdraw(t);
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	Text *text;
+	Keyboardctl *kc;
+	Mousectl *mc;
+	Rune r, *rs;
+	char *s;
+	int len;
+
+	ARGBEGIN{
+	default:
+		sysfatal("foo");
+	}ARGEND
+
+	len = readn(0, buf, sizeof(buf));
+	buf[len] = '\0';
+	for(s = buf, rs = lorem; *s != '\0'; s+=len, rs++)
+		len = chartorune(rs, s);
+	*rs = L'\0';
+
+	if(initdraw(nil, nil, "guitest") < 0)
+		sysfatal("initdraw: %r");
+
+	cols[BACK] = allocimagemix(display, DPurpleblue, DWhite);
+	cols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow);
+	cols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue);
+	cols[TEXT] = display->black;
+	cols[HTEXT] = display->black;
+
+	text = mallocz(sizeof(*text), 1);
+
+	textinit(text);
+	textaddrunes(text, lorem);
+	lorem[0] = L'\0';
+
+	textdraw(text);
+	flushimage(display, 1);
+
+	if((mc = initmouse(nil, screen)) == nil)
+		sysfatal("initmouse failed: %r");
+	if((kc = initkeyboard(nil)) == nil)
+		sysfatal("initkeyboard failed: %r");
+
+	Alt a[NCHAN+1] = {
+		[MOUSE] {mc->c, nil, CHANRCV},
+		[KEYBD] {kc->c, &r, CHANRCV},
+		[RESIZE] {mc->resizec, nil, CHANRCV},
+		[NCHAN] {nil, nil, CHANEND},
+	};
+	for(;;)switch(alt(a)){
+	default:
+		break;
+	case KEYBD:
+		if(r == Kdel)
+			goto End;
+		break;
+	case MOUSE:
+		textmouse(text, mc);
+		break;
+	case RESIZE:
+		textresize(text);
+		break;
+	}
+End:
+	threadexitsall(0);
+}
--- a/scrolldemo/mkfile
+++ b/scrolldemo/mkfile
@@ -1,9 +1,7 @@
 </$objtype/mkfile
 
-TARG=scrolldemo
-BIN=/$objtype/bin
+TARG=scrolldemo demolines
 LIB=../libscroll.$O.a
-OFILES=scrolldemo.$O
 HFILES=../scroll.h
 
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany