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" 13 14 static Image *scrtmp; 15 16 static 17 Rectangle 18 scrpos(Rectangle r, uint p0, uint p1, uint tot) 19 { 20 Rectangle q; 21 int h; 22 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 else 40 q.min.y = q.max.y-2; 41 } 42 return q; 43 } 44 45 void 46 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 } 53 54 void 55 textscrdraw(Text *t) 56 { 57 Rectangle r, r1, r2; 58 Image *b; 59 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->nchars, t->file->nc); 70 if(!eqrect(r2, t->lastsr)){ 71 t->lastsr = r2; 72 draw(b, r1, t->cols[BORD], nil, ZP); 73 draw(b, r2, t->cols[BACK], nil, ZP); 74 r2.min.x = r2.max.x-1; 75 draw(b, r2, t->cols[BORD], nil, ZP); 76 draw(t->b, r, b, nil, Pt(0, r1.min.y)); 77 /*flushimage(display, 1);/*BUG?*/ 78 } 79 } 80 81 void 82 scrsleep(uint dt) 83 { 84 Timer *timer; 85 static Alt alts[3]; 86 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->Mouse; 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 } 105 106 void 107 textscroll(Text *t, int but) 108 { 109 uint p0, oldp0; 110 Rectangle s; 111 int x, y, my, h, first; 112 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->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->font->height); 142 else 143 p0 = t->org+frcharofpt(t, 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->Mouse); 152 first = FALSE; 153 } 154 scrsleep(80); 155 }while(mouse->buttons & (1<<(but-1))); 156 while(mouse->buttons) 157 readmouse(mousectl); 158 } 159