summaryrefslogtreecommitdiff
path: root/appl/acme/scrl.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/acme/scrl.b')
-rw-r--r--appl/acme/scrl.b187
1 files changed, 187 insertions, 0 deletions
diff --git a/appl/acme/scrl.b b/appl/acme/scrl.b
new file mode 100644
index 00000000..e25fc709
--- /dev/null
+++ b/appl/acme/scrl.b
@@ -0,0 +1,187 @@
+implement Scroll;
+
+include "common.m";
+
+sys : Sys;
+drawm : Draw;
+acme : Acme;
+graph : Graph;
+utils : Utils;
+gui : Gui;
+dat : Dat;
+framem : Framem;
+textm : Textm;
+timerm : Timerm;
+
+BORD, BACK : import Framem;
+FALSE, TRUE, XXX, Maxblock : import Dat;
+error, warning : import utils;
+Point, Rect, Image, Display : import drawm;
+draw : import graph;
+black, white, display : import gui;
+mouse, cmouse : import dat;
+Frame : import framem;
+Timer : import Dat;
+Text : import textm;
+frgetmouse : import acme;
+mainwin : import gui;
+
+init(mods : ref Dat->Mods)
+{
+ sys = mods.sys;
+ drawm = mods.draw;
+ acme = mods.acme;
+ graph = mods.graph;
+ utils = mods.utils;
+ gui = mods.gui;
+ dat = mods.dat;
+ framem = mods.framem;
+ textm = mods.textm;
+ timerm = mods.timerm;
+}
+
+scrpos(r : Rect, p0 : int, p1 : int, tot : int) : Rect
+{
+ h : int;
+ q : Rect;
+
+ q = r;
+ # q = r.inset(1);
+ h = q.max.y-q.min.y;
+ if(tot == 0)
+ return q;
+ if(tot > 1024*1024){
+ tot >>= 10;
+ p0 >>= 10;
+ p1 >>= 10;
+ }
+ if(p0 > 0)
+ q.min.y += h*p0/tot;
+ if(p1 < tot)
+ q.max.y -= h*(tot-p1)/tot;
+ if(q.max.y < q.min.y+2){
+ if(q.min.y+2 <= r.max.y)
+ q.max.y = q.min.y+2;
+ else
+ q.min.y = q.max.y-2;
+ }
+ return q;
+}
+
+scrx : ref Image;
+
+scrresize()
+{
+ scrx = nil;
+ h := 1024;
+ if (display != nil)
+ h = display.image.r.dy();
+ rr := Rect((0, 0), (32, h));
+ scrx = graph->balloc(rr, mainwin.chans, Draw->White);
+ if(scrx == nil)
+ error("scroll balloc");
+}
+
+scrdraw(t : ref Text)
+{
+ r, r1, r2 : Rect;
+
+ if(t.w==nil || t.what!=Textm->Body || t != t.w.body)
+ return;
+ if(scrx == nil)
+ scrresize();
+ r = t.scrollr;
+ b := scrx;
+ r1 = r;
+ # r.min.x += 1; # border between margin and bar
+ r1.min.x = 0;
+ r1.max.x = r.dx();
+ r2 = scrpos(r1, t.org, t.org+t.frame.nchars, t.file.buf.nc);
+ if(!r2.eq(t.lastsr)){
+ t.lastsr = r2;
+ draw(b, r1, t.frame.cols[BORD], nil, (0, 0));
+ draw(b, r2, t.frame.cols[BACK], nil, (0, 0));
+ r2.min.x = r2.max.x-1;
+ draw(b, r2, t.frame.cols[BORD], nil, (0, 0));
+ draw(t.frame.b, r, b, nil, (0, r1.min.y));
+ # bflush();
+ }
+}
+
+scrsleep(dt : int)
+{
+ timer : ref Timer;
+
+ timer = timerm->timerstart(dt);
+ graph->bflush();
+ # only run from mouse task, so safe to use cmouse
+ alt{
+ <-(timer.c) =>
+ timerm->timerstop(timer);
+ *mouse = *<-cmouse =>
+ spawn timerm->timerwaittask(timer);
+ }
+}
+
+scroll(t : ref Text, but : int)
+{
+ p0, oldp0 : int;
+ s : Rect;
+ x, y, my, h, first : int;
+
+ s = t.scrollr.inset(1);
+ h = s.max.y-s.min.y;
+ x = (s.min.x+s.max.x)/2;
+ oldp0 = ~0;
+ first = TRUE;
+ do{
+ graph->bflush();
+ my = mouse.xy.y;
+ if(my < s.min.y)
+ my = s.min.y;
+ if(my >= s.max.y)
+ my = s.max.y;
+ if(but == 2){
+ y = my;
+ if(y > s.max.y-2)
+ y = s.max.y-2;
+ if(t.file.buf.nc > 1024*1024)
+ p0 = ((t.file.buf.nc>>10)*(y-s.min.y)/h)<<10;
+ else
+ p0 = t.file.buf.nc*(y-s.min.y)/h;
+ if(oldp0 != p0)
+ t.setorigin(p0, FALSE);
+ oldp0 = p0;
+ frgetmouse();
+ continue;
+ }
+ if(but == 1) {
+ p0 = t.backnl(t.org, (my-s.min.y)/t.frame.font.height);
+ if(p0 == t.org)
+ p0 = t.backnl(t.org, 1);
+ }
+ else {
+ p0 = t.org+framem->frcharofpt(t.frame, (s.max.x, my));
+ if(p0 == t.org)
+ p0 = t.forwnl(t.org, 1);
+ }
+ if(oldp0 != p0)
+ t.setorigin(p0, TRUE);
+ oldp0 = p0;
+ # debounce
+ if(first){
+ graph->bflush();
+ sys->sleep(200);
+ alt {
+ *mouse = *<-cmouse =>
+ ;
+ * =>
+ ;
+ }
+ first = FALSE;
+ }
+ scrsleep(80);
+ }while(mouse.buttons & (1<<(but-1)));
+ while(mouse.buttons)
+ frgetmouse();
+}