17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid 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 <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier static Image *scrtmp;
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier static
177dd7cddfSDavid du Colombier Rectangle
scrpos(Rectangle r,uint p0,uint p1,uint tot)187dd7cddfSDavid du Colombier scrpos(Rectangle r, uint p0, uint p1, uint tot)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier Rectangle q;
217dd7cddfSDavid du Colombier int h;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier q = r;
247dd7cddfSDavid du Colombier h = q.max.y-q.min.y;
257dd7cddfSDavid du Colombier if(tot == 0)
267dd7cddfSDavid du Colombier return q;
277dd7cddfSDavid du Colombier if(tot > 1024*1024){
287dd7cddfSDavid du Colombier tot>>=10;
297dd7cddfSDavid du Colombier p0>>=10;
307dd7cddfSDavid du Colombier p1>>=10;
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier if(p0 > 0)
337dd7cddfSDavid du Colombier q.min.y += h*p0/tot;
347dd7cddfSDavid du Colombier if(p1 < tot)
357dd7cddfSDavid du Colombier q.max.y -= h*(tot-p1)/tot;
367dd7cddfSDavid du Colombier if(q.max.y < q.min.y+2){
377dd7cddfSDavid du Colombier if(q.min.y+2 <= r.max.y)
387dd7cddfSDavid du Colombier q.max.y = q.min.y+2;
397dd7cddfSDavid du Colombier else
407dd7cddfSDavid du Colombier q.min.y = q.max.y-2;
417dd7cddfSDavid du Colombier }
427dd7cddfSDavid du Colombier return q;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier void
scrlresize(void)467dd7cddfSDavid du Colombier scrlresize(void)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier freeimage(scrtmp);
499a747e4fSDavid du Colombier scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);
507dd7cddfSDavid du Colombier if(scrtmp == nil)
517dd7cddfSDavid du Colombier error("scroll alloc");
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier void
textscrdraw(Text * t)557dd7cddfSDavid du Colombier textscrdraw(Text *t)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier Rectangle r, r1, r2;
587dd7cddfSDavid du Colombier Image *b;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier if(t->w==nil || t!=&t->w->body)
617dd7cddfSDavid du Colombier return;
627dd7cddfSDavid du Colombier if(scrtmp == nil)
637dd7cddfSDavid du Colombier scrlresize();
647dd7cddfSDavid du Colombier r = t->scrollr;
657dd7cddfSDavid du Colombier b = scrtmp;
667dd7cddfSDavid du Colombier r1 = r;
677dd7cddfSDavid du Colombier r1.min.x = 0;
687dd7cddfSDavid du Colombier r1.max.x = Dx(r);
697dd7cddfSDavid du Colombier r2 = scrpos(r1, t->org, t->org+t->nchars, t->file->nc);
707dd7cddfSDavid du Colombier if(!eqrect(r2, t->lastsr)){
717dd7cddfSDavid du Colombier t->lastsr = r2;
727dd7cddfSDavid du Colombier draw(b, r1, t->cols[BORD], nil, ZP);
737dd7cddfSDavid du Colombier draw(b, r2, t->cols[BACK], nil, ZP);
747dd7cddfSDavid du Colombier r2.min.x = r2.max.x-1;
757dd7cddfSDavid du Colombier draw(b, r2, t->cols[BORD], nil, ZP);
767dd7cddfSDavid du Colombier draw(t->b, r, b, nil, Pt(0, r1.min.y));
777dd7cddfSDavid du Colombier /*flushimage(display, 1);/*BUG?*/
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier void
scrsleep(uint dt)827dd7cddfSDavid du Colombier scrsleep(uint dt)
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier Timer *timer;
857dd7cddfSDavid du Colombier static Alt alts[3];
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier timer = timerstart(dt);
887dd7cddfSDavid du Colombier alts[0].c = timer->c;
897dd7cddfSDavid du Colombier alts[0].v = nil;
907dd7cddfSDavid du Colombier alts[0].op = CHANRCV;
917dd7cddfSDavid du Colombier alts[1].c = mousectl->c;
927dd7cddfSDavid du Colombier alts[1].v = &mousectl->Mouse;
937dd7cddfSDavid du Colombier alts[1].op = CHANRCV;
947dd7cddfSDavid du Colombier alts[2].op = CHANEND;
957dd7cddfSDavid du Colombier for(;;)
967dd7cddfSDavid du Colombier switch(alt(alts)){
977dd7cddfSDavid du Colombier case 0:
987dd7cddfSDavid du Colombier timerstop(timer);
997dd7cddfSDavid du Colombier return;
1007dd7cddfSDavid du Colombier case 1:
1017dd7cddfSDavid du Colombier timercancel(timer);
1027dd7cddfSDavid du Colombier return;
1037dd7cddfSDavid du Colombier }
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier void
textscroll(Text * t,int but)1077dd7cddfSDavid du Colombier textscroll(Text *t, int but)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier uint p0, oldp0;
1107dd7cddfSDavid du Colombier Rectangle s;
1117dd7cddfSDavid du Colombier int x, y, my, h, first;
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier s = insetrect(t->scrollr, 1);
1147dd7cddfSDavid du Colombier h = s.max.y-s.min.y;
1157dd7cddfSDavid du Colombier x = (s.min.x+s.max.x)/2;
1167dd7cddfSDavid du Colombier oldp0 = ~0;
1177dd7cddfSDavid du Colombier first = TRUE;
1187dd7cddfSDavid du Colombier do{
1197dd7cddfSDavid du Colombier flushimage(display, 1);
1207dd7cddfSDavid du Colombier my = mouse->xy.y;
1217dd7cddfSDavid du Colombier if(my < s.min.y)
1227dd7cddfSDavid du Colombier my = s.min.y;
1237dd7cddfSDavid du Colombier if(my >= s.max.y)
1247dd7cddfSDavid du Colombier my = s.max.y;
1257dd7cddfSDavid du Colombier if(!eqpt(mouse->xy, Pt(x, my))){
1267dd7cddfSDavid du Colombier moveto(mousectl, Pt(x, my));
1277dd7cddfSDavid du Colombier readmouse(mousectl); /* absorb event generated by moveto() */
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier if(but == 2){
1307dd7cddfSDavid du Colombier y = my;
131*ded93d44SDavid du Colombier p0 = (vlong)t->file->nc*(y-s.min.y)/h;
132*ded93d44SDavid du Colombier if(p0 >= t->q1)
133*ded93d44SDavid du Colombier p0 = textbacknl(t, p0, 2);
1347dd7cddfSDavid du Colombier if(oldp0 != p0)
1357dd7cddfSDavid du Colombier textsetorigin(t, p0, FALSE);
1367dd7cddfSDavid du Colombier oldp0 = p0;
1377dd7cddfSDavid du Colombier readmouse(mousectl);
1387dd7cddfSDavid du Colombier continue;
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier if(but == 1)
1417dd7cddfSDavid du Colombier p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
1427dd7cddfSDavid du Colombier else
1437dd7cddfSDavid du Colombier p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
1447dd7cddfSDavid du Colombier if(oldp0 != p0)
1457dd7cddfSDavid du Colombier textsetorigin(t, p0, TRUE);
1467dd7cddfSDavid du Colombier oldp0 = p0;
1477dd7cddfSDavid du Colombier /* debounce */
1487dd7cddfSDavid du Colombier if(first){
1497dd7cddfSDavid du Colombier flushimage(display, 1);
1507dd7cddfSDavid du Colombier sleep(200);
1517dd7cddfSDavid du Colombier nbrecv(mousectl->c, &mousectl->Mouse);
1527dd7cddfSDavid du Colombier first = FALSE;
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier scrsleep(80);
1557dd7cddfSDavid du Colombier }while(mouse->buttons & (1<<(but-1)));
1567dd7cddfSDavid du Colombier while(mouse->buttons)
1577dd7cddfSDavid du Colombier readmouse(mousectl);
1587dd7cddfSDavid du Colombier }
159