17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include "dat.h"
117dd7cddfSDavid du Colombier #include "fns.h"
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier static Image *scrtmp;
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier static
167dd7cddfSDavid du Colombier void
scrtemps(void)177dd7cddfSDavid du Colombier scrtemps(void)
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier int h;
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier if(scrtmp)
227dd7cddfSDavid du Colombier return;
2359cc4ca5SDavid du Colombier h = BIG*Dy(screen->r);
24*9a747e4fSDavid du Colombier scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DWhite);
257dd7cddfSDavid du Colombier if(scrtmp == nil)
267dd7cddfSDavid du Colombier error("scrtemps");
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier
2959cc4ca5SDavid du Colombier void
freescrtemps(void)3059cc4ca5SDavid du Colombier freescrtemps(void)
3159cc4ca5SDavid du Colombier {
3259cc4ca5SDavid du Colombier freeimage(scrtmp);
3359cc4ca5SDavid du Colombier scrtmp = nil;
3459cc4ca5SDavid du Colombier }
3559cc4ca5SDavid du Colombier
367dd7cddfSDavid du Colombier static
377dd7cddfSDavid du Colombier Rectangle
scrpos(Rectangle r,uint p0,uint p1,uint tot)387dd7cddfSDavid du Colombier scrpos(Rectangle r, uint p0, uint p1, uint tot)
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier Rectangle q;
417dd7cddfSDavid du Colombier int h;
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier q = r;
447dd7cddfSDavid du Colombier h = q.max.y-q.min.y;
457dd7cddfSDavid du Colombier if(tot == 0)
467dd7cddfSDavid du Colombier return q;
477dd7cddfSDavid du Colombier if(tot > 1024*1024){
487dd7cddfSDavid du Colombier tot>>=10;
497dd7cddfSDavid du Colombier p0>>=10;
507dd7cddfSDavid du Colombier p1>>=10;
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier if(p0 > 0)
537dd7cddfSDavid du Colombier q.min.y += h*p0/tot;
547dd7cddfSDavid du Colombier if(p1 < tot)
557dd7cddfSDavid du Colombier q.max.y -= h*(tot-p1)/tot;
567dd7cddfSDavid du Colombier if(q.max.y < q.min.y+2){
577dd7cddfSDavid du Colombier if(q.min.y+2 <= r.max.y)
587dd7cddfSDavid du Colombier q.max.y = q.min.y+2;
597dd7cddfSDavid du Colombier else
607dd7cddfSDavid du Colombier q.min.y = q.max.y-2;
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier return q;
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier void
wscrdraw(Window * w)667dd7cddfSDavid du Colombier wscrdraw(Window *w)
677dd7cddfSDavid du Colombier {
687dd7cddfSDavid du Colombier Rectangle r, r1, r2;
697dd7cddfSDavid du Colombier Image *b;
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier scrtemps();
727dd7cddfSDavid du Colombier if(w->i == nil)
737dd7cddfSDavid du Colombier error("scrdraw");
747dd7cddfSDavid du Colombier r = w->scrollr;
757dd7cddfSDavid du Colombier b = scrtmp;
767dd7cddfSDavid du Colombier r1 = r;
777dd7cddfSDavid du Colombier r1.min.x = 0;
787dd7cddfSDavid du Colombier r1.max.x = Dx(r);
797dd7cddfSDavid du Colombier r2 = scrpos(r1, w->org, w->org+w->nchars, w->nr);
807dd7cddfSDavid du Colombier if(!eqrect(r2, w->lastsr)){
817dd7cddfSDavid du Colombier w->lastsr = r2;
827dd7cddfSDavid du Colombier /* move r1, r2 to (0,0) to avoid clipping */
837dd7cddfSDavid du Colombier r2 = rectsubpt(r2, r1.min);
847dd7cddfSDavid du Colombier r1 = rectsubpt(r1, r1.min);
857dd7cddfSDavid du Colombier draw(b, r1, w->cols[BORD], nil, ZP);
867dd7cddfSDavid du Colombier draw(b, r2, w->cols[BACK], nil, ZP);
877dd7cddfSDavid du Colombier r2.min.x = r2.max.x-1;
887dd7cddfSDavid du Colombier draw(b, r2, w->cols[BORD], nil, ZP);
897dd7cddfSDavid du Colombier draw(w->i, r, b, nil, Pt(0, r1.min.y));
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier void
wscrsleep(Window * w,uint dt)947dd7cddfSDavid du Colombier wscrsleep(Window *w, uint dt)
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier Timer *timer;
977dd7cddfSDavid du Colombier int y, b;
987dd7cddfSDavid du Colombier static Alt alts[3];
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier timer = timerstart(dt);
1017dd7cddfSDavid du Colombier y = w->mc.xy.y;
1027dd7cddfSDavid du Colombier b = w->mc.buttons;
1037dd7cddfSDavid du Colombier alts[0].c = timer->c;
1047dd7cddfSDavid du Colombier alts[0].v = nil;
1057dd7cddfSDavid du Colombier alts[0].op = CHANRCV;
1067dd7cddfSDavid du Colombier alts[1].c = w->mc.c;
1077dd7cddfSDavid du Colombier alts[1].v = &w->mc.Mouse;
1087dd7cddfSDavid du Colombier alts[1].op = CHANRCV;
1097dd7cddfSDavid du Colombier alts[2].op = CHANEND;
1107dd7cddfSDavid du Colombier for(;;)
1117dd7cddfSDavid du Colombier switch(alt(alts)){
1127dd7cddfSDavid du Colombier case 0:
1137dd7cddfSDavid du Colombier timerstop(timer);
1147dd7cddfSDavid du Colombier return;
1157dd7cddfSDavid du Colombier case 1:
1167dd7cddfSDavid du Colombier if(abs(w->mc.xy.y-y)>2 || w->mc.buttons!=b){
1177dd7cddfSDavid du Colombier timercancel(timer);
1187dd7cddfSDavid du Colombier return;
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier break;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier void
wscroll(Window * w,int but)1257dd7cddfSDavid du Colombier wscroll(Window *w, int but)
1267dd7cddfSDavid du Colombier {
1277dd7cddfSDavid du Colombier uint p0, oldp0;
1287dd7cddfSDavid du Colombier Rectangle s;
1297dd7cddfSDavid du Colombier int x, y, my, h, first;
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier s = insetrect(w->scrollr, 1);
1327dd7cddfSDavid du Colombier h = s.max.y-s.min.y;
1337dd7cddfSDavid du Colombier x = (s.min.x+s.max.x)/2;
1347dd7cddfSDavid du Colombier oldp0 = ~0;
1357dd7cddfSDavid du Colombier first = TRUE;
1367dd7cddfSDavid du Colombier do{
1377dd7cddfSDavid du Colombier flushimage(display, 1);
1387dd7cddfSDavid du Colombier if(w->mc.xy.x<s.min.x || s.max.x<=w->mc.xy.x){
1397dd7cddfSDavid du Colombier readmouse(&w->mc);
1407dd7cddfSDavid du Colombier }else{
1417dd7cddfSDavid du Colombier my = w->mc.xy.y;
1427dd7cddfSDavid du Colombier if(my < s.min.y)
1437dd7cddfSDavid du Colombier my = s.min.y;
1447dd7cddfSDavid du Colombier if(my >= s.max.y)
1457dd7cddfSDavid du Colombier my = s.max.y;
1467dd7cddfSDavid du Colombier if(!eqpt(w->mc.xy, Pt(x, my))){
1477dd7cddfSDavid du Colombier wmovemouse(w, Pt(x, my));
1487dd7cddfSDavid du Colombier readmouse(&w->mc); /* absorb event generated by moveto() */
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier if(but == 2){
1517dd7cddfSDavid du Colombier y = my;
1527dd7cddfSDavid du Colombier if(y > s.max.y-2)
1537dd7cddfSDavid du Colombier y = s.max.y-2;
1547dd7cddfSDavid du Colombier if(w->nr > 1024*1024)
1557dd7cddfSDavid du Colombier p0 = ((w->nr>>10)*(y-s.min.y)/h)<<10;
1567dd7cddfSDavid du Colombier else
1577dd7cddfSDavid du Colombier p0 = w->nr*(y-s.min.y)/h;
1587dd7cddfSDavid du Colombier if(oldp0 != p0)
1597dd7cddfSDavid du Colombier wsetorigin(w, p0, FALSE);
1607dd7cddfSDavid du Colombier oldp0 = p0;
1617dd7cddfSDavid du Colombier readmouse(&w->mc);
1627dd7cddfSDavid du Colombier continue;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier if(but == 1)
1657dd7cddfSDavid du Colombier p0 = wbacknl(w, w->org, (my-s.min.y)/w->font->height);
1667dd7cddfSDavid du Colombier else
1677dd7cddfSDavid du Colombier p0 = w->org+frcharofpt(w, Pt(s.max.x, my));
1687dd7cddfSDavid du Colombier if(oldp0 != p0)
1697dd7cddfSDavid du Colombier wsetorigin(w, p0, TRUE);
1707dd7cddfSDavid du Colombier oldp0 = p0;
1717dd7cddfSDavid du Colombier /* debounce */
1727dd7cddfSDavid du Colombier if(first){
1737dd7cddfSDavid du Colombier flushimage(display, 1);
1747dd7cddfSDavid du Colombier sleep(200);
1757dd7cddfSDavid du Colombier nbrecv(w->mc.c, &w->mc.Mouse);
1767dd7cddfSDavid du Colombier first = FALSE;
1777dd7cddfSDavid du Colombier }
1787dd7cddfSDavid du Colombier wscrsleep(w, 100);
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier }while(w->mc.buttons & (1<<(but-1)));
1817dd7cddfSDavid du Colombier while(w->mc.buttons)
1827dd7cddfSDavid du Colombier readmouse(&w->mc);
1837dd7cddfSDavid du Colombier }
184