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