diff options
| author | rsc <devnull@localhost> | 2005-11-06 22:16:48 +0000 |
|---|---|---|
| committer | rsc <devnull@localhost> | 2005-11-06 22:16:48 +0000 |
| commit | e830a908498c8f0270948fd08c50f6d773315880 (patch) | |
| tree | a16fe62419a4e3a95ab2d8d3a70f1a870d0bb55c /src/cmd/9term/scrl.c | |
| parent | a6c0ff35ee294c0a808e1792eb4f43820fed8f16 (diff) | |
| download | plan9port-e830a908498c8f0270948fd08c50f6d773315880.tar.gz plan9port-e830a908498c8f0270948fd08c50f6d773315880.zip | |
New 9term using rio sources more directly.
Diffstat (limited to 'src/cmd/9term/scrl.c')
| -rw-r--r-- | src/cmd/9term/scrl.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/cmd/9term/scrl.c b/src/cmd/9term/scrl.c new file mode 100644 index 00000000..8a614ad6 --- /dev/null +++ b/src/cmd/9term/scrl.c @@ -0,0 +1,183 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <cursor.h> +#include <mouse.h> +#include <keyboard.h> +#include <frame.h> +#include <fcall.h> +#include "dat.h" +#include "fns.h" + +static Image *scrtmp; + +static +void +scrtemps(void) +{ + int h; + + if(scrtmp) + return; + h = BIG*Dy(screen->r); + scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DWhite); + if(scrtmp == nil) + error("scrtemps"); +} + +void +freescrtemps(void) +{ + freeimage(scrtmp); + scrtmp = nil; +} + +static +Rectangle +scrpos(Rectangle r, uint p0, uint p1, uint tot) +{ + Rectangle q; + int h; + + q = r; + 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; +} + +void +wscrdraw(Window *w) +{ + Rectangle r, r1, r2; + Image *b; + + scrtemps(); + if(w->i == nil) + error("scrdraw"); + r = w->scrollr; + b = scrtmp; + r1 = r; + r1.min.x = 0; + r1.max.x = Dx(r); + r2 = scrpos(r1, w->org, w->org+w->f.nchars, w->nr); + if(!eqrect(r2, w->lastsr)){ + w->lastsr = r2; + /* move r1, r2 to (0,0) to avoid clipping */ + r2 = rectsubpt(r2, r1.min); + r1 = rectsubpt(r1, r1.min); + draw(b, r1, w->f.cols[BORD], nil, ZP); + draw(b, r2, w->f.cols[BACK], nil, ZP); + r2.min.x = r2.max.x-1; + draw(b, r2, w->f.cols[BORD], nil, ZP); + draw(w->i, r, b, nil, Pt(0, r1.min.y)); + } +} + +void +wscrsleep(Window *w, uint dt) +{ + Timer *timer; + int y, b; + static Alt alts[3]; + + timer = timerstart(dt); + y = w->mc.m.xy.y; + b = w->mc.m.buttons; + alts[0].c = timer->c; + alts[0].v = nil; + alts[0].op = CHANRCV; + alts[1].c = w->mc.c; + alts[1].v = &w->mc.m; + alts[1].op = CHANRCV; + alts[2].op = CHANEND; + for(;;) + switch(alt(alts)){ + case 0: + timerstop(timer); + return; + case 1: + if(abs(w->mc.m.xy.y-y)>2 || w->mc.m.buttons!=b){ + timercancel(timer); + return; + } + break; + } +} + +void +wscroll(Window *w, int but) +{ + uint p0, oldp0; + Rectangle s; + int x, y, my, h, first; + + s = insetrect(w->scrollr, 1); + h = s.max.y-s.min.y; + x = (s.min.x+s.max.x)/2; + oldp0 = ~0; + first = TRUE; + do{ + flushimage(display, 1); + if(w->mc.m.xy.x<s.min.x || s.max.x<=w->mc.m.xy.x){ + readmouse(&w->mc); + }else{ + my = w->mc.m.xy.y; + if(my < s.min.y) + my = s.min.y; + if(my >= s.max.y) + my = s.max.y; + if(!eqpt(w->mc.m.xy, Pt(x, my))){ + wmovemouse(w, Pt(x, my)); + readmouse(&w->mc); /* absorb event generated by moveto() */ + } + if(but == 2){ + y = my; + if(y > s.max.y-2) + y = s.max.y-2; + if(w->nr > 1024*1024) + p0 = ((w->nr>>10)*(y-s.min.y)/h)<<10; + else + p0 = w->nr*(y-s.min.y)/h; + if(oldp0 != p0) + wsetorigin(w, p0, FALSE); + oldp0 = p0; + readmouse(&w->mc); + continue; + } + if(but == 1) + p0 = wbacknl(w, w->org, (my-s.min.y)/w->f.font->height); + else + p0 = w->org+frcharofpt(&w->f, Pt(s.max.x, my)); + if(oldp0 != p0) + wsetorigin(w, p0, TRUE); + oldp0 = p0; + /* debounce */ + if(first){ + flushimage(display, 1); + sleep(200); + nbrecv(w->mc.c, &w->mc.m); + first = FALSE; + } + wscrsleep(w, 100); + } + }while(w->mc.m.buttons & (1<<(but-1))); + while(w->mc.m.buttons) + readmouse(&w->mc); +} |
