Blob
1 #include <u.h>2 #include <libc.h>3 #include <draw.h>4 #include <thread.h>5 #include <cursor.h>6 #include <mouse.h>7 #include <keyboard.h>8 #include <frame.h>9 #include <fcall.h>10 #include <plumb.h>11 #include "dat.h"12 #include "fns.h"14 static Image *scrtmp;16 static17 Rectangle18 scrpos(Rectangle r, uint p0, uint p1, uint tot)19 {20 Rectangle q;21 int h;23 q = r;24 h = q.max.y-q.min.y;25 if(tot == 0)26 return q;27 if(tot > 1024*1024){28 tot>>=10;29 p0>>=10;30 p1>>=10;31 }32 if(p0 > 0)33 q.min.y += h*p0/tot;34 if(p1 < tot)35 q.max.y -= h*(tot-p1)/tot;36 if(q.max.y < q.min.y+2){37 if(q.min.y+2 <= r.max.y)38 q.max.y = q.min.y+2;39 else40 q.min.y = q.max.y-2;41 }42 return q;43 }45 void46 scrlresize(void)47 {48 freeimage(scrtmp);49 scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);50 if(scrtmp == nil)51 error("scroll alloc");52 }54 void55 textscrdraw(Text *t)56 {57 Rectangle r, r1, r2;58 Image *b;60 if(t->w==nil || t!=&t->w->body)61 return;62 if(scrtmp == nil)63 scrlresize();64 r = t->scrollr;65 b = scrtmp;66 r1 = r;67 r1.min.x = 0;68 r1.max.x = Dx(r);69 r2 = scrpos(r1, t->org, t->org+t->fr.nchars, t->file->b.nc);70 if(!eqrect(r2, t->lastsr)){71 t->lastsr = r2;72 draw(b, r1, t->fr.cols[BORD], nil, ZP);73 draw(b, r2, t->fr.cols[BACK], nil, ZP);74 r2.min.x = r2.max.x-1;75 draw(b, r2, t->fr.cols[BORD], nil, ZP);76 draw(t->fr.b, r, b, nil, Pt(0, r1.min.y));77 /*flushimage(display, 1); // BUG? */78 }79 }81 void82 scrsleep(uint dt)83 {84 Timer *timer;85 static Alt alts[3];87 timer = timerstart(dt);88 alts[0].c = timer->c;89 alts[0].v = nil;90 alts[0].op = CHANRCV;91 alts[1].c = mousectl->c;92 alts[1].v = &mousectl->m;93 alts[1].op = CHANRCV;94 alts[2].op = CHANEND;95 for(;;)96 switch(alt(alts)){97 case 0:98 timerstop(timer);99 return;100 case 1:101 timercancel(timer);102 return;103 }104 }106 void107 textscroll(Text *t, int but)108 {109 uint p0, oldp0;110 Rectangle s;111 int x, y, my, h, first;113 s = insetrect(t->scrollr, 1);114 h = s.max.y-s.min.y;115 x = (s.min.x+s.max.x)/2;116 oldp0 = ~0;117 first = TRUE;118 do{119 flushimage(display, 1);120 my = mouse->xy.y;121 if(my < s.min.y)122 my = s.min.y;123 if(my >= s.max.y)124 my = s.max.y;125 if(!eqpt(mouse->xy, Pt(x, my))){126 moveto(mousectl, Pt(x, my));127 readmouse(mousectl); /* absorb event generated by moveto() */128 }129 if(but == 2){130 y = my;131 p0 = (vlong)t->file->b.nc*(y-s.min.y)/h;132 if(p0 >= t->q1)133 p0 = textbacknl(t, p0, 2);134 if(oldp0 != p0)135 textsetorigin(t, p0, FALSE);136 oldp0 = p0;137 readmouse(mousectl);138 continue;139 }140 if(but == 1)141 p0 = textbacknl(t, t->org, (my-s.min.y)/t->fr.font->height);142 else143 p0 = t->org+frcharofpt(&t->fr, Pt(s.max.x, my));144 if(oldp0 != p0)145 textsetorigin(t, p0, TRUE);146 oldp0 = p0;147 /* debounce */148 if(first){149 flushimage(display, 1);150 sleep(200);151 nbrecv(mousectl->c, &mousectl->m);152 first = FALSE;153 }154 scrsleep(80);155 }while(mouse->buttons & (1<<(but-1)));156 while(mouse->buttons)157 readmouse(mousectl);158 }