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