diff options
Diffstat (limited to 'appl/acme/scrl.b')
| -rw-r--r-- | appl/acme/scrl.b | 187 |
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(); +} |
