scroll.c (3328B)
1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <mouse.h> 6 #include <cursor.h> 7 #include <keyboard.h> 8 #include <frame.h> 9 #include "flayer.h" 10 #include "samterm.h" 11 12 static Image *scrtmp; 13 static Image *scrback; 14 15 void 16 scrtemps(void) 17 { 18 int h; 19 20 if(scrtmp) 21 return; 22 if(screensize(0, &h) == 0) 23 h = 2048; 24 scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0); 25 scrback = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0); 26 if(scrtmp==0 || scrback==0) 27 panic("scrtemps"); 28 } 29 30 Rectangle 31 scrpos(Rectangle r, long p0, long p1, long tot) 32 { 33 Rectangle q; 34 int h; 35 36 q = r; 37 h = q.max.y-q.min.y; 38 if(tot == 0) 39 return q; 40 if(tot > 1024L*1024L) 41 tot>>=10, p0>>=10, p1>>=10; 42 if(p0 > 0) 43 q.min.y += h*p0/tot; 44 if(p1 < tot) 45 q.max.y -= h*(tot-p1)/tot; 46 if(q.max.y < q.min.y+2){ 47 if(q.min.y+2 <= r.max.y) 48 q.max.y = q.min.y+2; 49 else 50 q.min.y = q.max.y-2; 51 } 52 return q; 53 } 54 55 void 56 scrmark(Flayer *l, Rectangle r) 57 { 58 r.max.x--; 59 if(rectclip(&r, l->scroll)) 60 draw(l->f.b, r, l->f.cols[HIGH], nil, ZP); 61 } 62 63 void 64 scrunmark(Flayer *l, Rectangle r) 65 { 66 if(rectclip(&r, l->scroll)) 67 draw(l->f.b, r, scrback, nil, Pt(0, r.min.y-l->scroll.min.y)); 68 } 69 70 void 71 scrdraw(Flayer *l, long tot) 72 { 73 Rectangle r, r1, r2; 74 Image *b; 75 76 scrtemps(); 77 if(l->f.b == 0) 78 panic("scrdraw"); 79 r = l->scroll; 80 r1 = r; 81 if(l->visible == All){ 82 b = scrtmp; 83 r1.min.x = 0; 84 r1.max.x = Dx(r); 85 }else 86 b = l->f.b; 87 r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot); 88 if(!eqrect(r2, l->lastsr)){ 89 l->lastsr = r2; 90 draw(b, r1, l->f.cols[BORD], nil, ZP); 91 draw(b, r2, l->f.cols[BACK], nil, r2.min); 92 r2 = r1; 93 r2.min.x = r2.max.x-1; 94 draw(b, r2, l->f.cols[BORD], nil, ZP); 95 if(b!=l->f.b) 96 draw(l->f.b, r, b, nil, r1.min); 97 } 98 } 99 100 void 101 scroll(Flayer *l, int but) 102 { 103 int in = 0, oin; 104 long tot = scrtotal(l); 105 Rectangle scr, r, s, rt; 106 int x, y, my, oy, h; 107 long p0; 108 109 s = l->scroll; 110 x = s.min.x+FLSCROLLWID(l)/2; 111 scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot); 112 r = scr; 113 y = scr.min.y; 114 my = mousep->xy.y; 115 draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min); 116 do{ 117 oin = in; 118 in = abs(x-mousep->xy.x)<=FLSCROLLWID(l)/2; 119 if(oin && !in) 120 scrunmark(l, r); 121 if(in){ 122 scrmark(l, r); 123 oy = y; 124 my = mousep->xy.y; 125 if(my < s.min.y) 126 my = s.min.y; 127 if(my >= s.max.y) 128 my = s.max.y; 129 if(!eqpt(mousep->xy, Pt(x, my))) 130 moveto(mousectl, Pt(x, my)); 131 if(but == 1){ 132 p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my)); 133 rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); 134 y = rt.min.y; 135 }else if(but == 2){ 136 y = my; 137 if(y > s.max.y-2) 138 y = s.max.y-2; 139 }else if(but == 3){ 140 p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); 141 rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); 142 y = rt.min.y; 143 } 144 if(y != oy){ 145 scrunmark(l, r); 146 r = rectaddpt(scr, Pt(0, y-scr.min.y)); 147 scrmark(l, r); 148 } 149 } 150 }while(button(but)); 151 if(in){ 152 h = s.max.y-s.min.y; 153 scrunmark(l, r); 154 p0 = 0; 155 if(but == 1) 156 p0 = (long)(my-s.min.y)/l->f.font->height+1; 157 else if(but == 2){ 158 if(tot > 1024L*1024L) 159 p0 = ((tot>>10)*(y-s.min.y)/h)<<10; 160 else 161 p0 = tot*(y-s.min.y)/h; 162 }else if(but == 3){ 163 p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); 164 if(p0 > tot) 165 p0 = tot; 166 } 167 scrorigin(l, but, p0); 168 } 169 }