17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier #include <thread.h> 5*9a747e4fSDavid 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 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 467dd7cddfSDavid du Colombier scrlresize(void) 477dd7cddfSDavid du Colombier { 487dd7cddfSDavid du Colombier freeimage(scrtmp); 49*9a747e4fSDavid 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 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 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 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 if(mouse->xy.x<s.min.x || s.max.x<=mouse->xy.x){ 1217dd7cddfSDavid du Colombier readmouse(mousectl); 1227dd7cddfSDavid du Colombier }else{ 1237dd7cddfSDavid du Colombier my = mouse->xy.y; 1247dd7cddfSDavid du Colombier if(my < s.min.y) 1257dd7cddfSDavid du Colombier my = s.min.y; 1267dd7cddfSDavid du Colombier if(my >= s.max.y) 1277dd7cddfSDavid du Colombier my = s.max.y; 1287dd7cddfSDavid du Colombier if(!eqpt(mouse->xy, Pt(x, my))){ 1297dd7cddfSDavid du Colombier moveto(mousectl, Pt(x, my)); 1307dd7cddfSDavid du Colombier readmouse(mousectl); /* absorb event generated by moveto() */ 1317dd7cddfSDavid du Colombier } 1327dd7cddfSDavid du Colombier if(but == 2){ 1337dd7cddfSDavid du Colombier y = my; 1347dd7cddfSDavid du Colombier if(y > s.max.y-2) 1357dd7cddfSDavid du Colombier y = s.max.y-2; 1367dd7cddfSDavid du Colombier if(t->file->nc > 1024*1024) 1377dd7cddfSDavid du Colombier p0 = ((t->file->nc>>10)*(y-s.min.y)/h)<<10; 1387dd7cddfSDavid du Colombier else 1397dd7cddfSDavid du Colombier p0 = t->file->nc*(y-s.min.y)/h; 1407dd7cddfSDavid du Colombier if(oldp0 != p0) 1417dd7cddfSDavid du Colombier textsetorigin(t, p0, FALSE); 1427dd7cddfSDavid du Colombier oldp0 = p0; 1437dd7cddfSDavid du Colombier readmouse(mousectl); 1447dd7cddfSDavid du Colombier continue; 1457dd7cddfSDavid du Colombier } 1467dd7cddfSDavid du Colombier if(but == 1) 1477dd7cddfSDavid du Colombier p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height); 1487dd7cddfSDavid du Colombier else 1497dd7cddfSDavid du Colombier p0 = t->org+frcharofpt(t, Pt(s.max.x, my)); 1507dd7cddfSDavid du Colombier if(oldp0 != p0) 1517dd7cddfSDavid du Colombier textsetorigin(t, p0, TRUE); 1527dd7cddfSDavid du Colombier oldp0 = p0; 1537dd7cddfSDavid du Colombier /* debounce */ 1547dd7cddfSDavid du Colombier if(first){ 1557dd7cddfSDavid du Colombier flushimage(display, 1); 1567dd7cddfSDavid du Colombier sleep(200); 1577dd7cddfSDavid du Colombier nbrecv(mousectl->c, &mousectl->Mouse); 1587dd7cddfSDavid du Colombier first = FALSE; 1597dd7cddfSDavid du Colombier } 1607dd7cddfSDavid du Colombier scrsleep(80); 1617dd7cddfSDavid du Colombier } 1627dd7cddfSDavid du Colombier }while(mouse->buttons & (1<<(but-1))); 1637dd7cddfSDavid du Colombier while(mouse->buttons) 1647dd7cddfSDavid du Colombier readmouse(mousectl); 1657dd7cddfSDavid du Colombier } 166