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 if (l->f.b == nil) 60 panic("scrmark: nil l->f.b"); 61 draw(l->f.b, r, l->f.cols[HIGH], nil, ZP); 62 } 63 } 64 65 void 66 scrunmark(Flayer *l, Rectangle r) 67 { 68 if(rectclip(&r, l->scroll)) { 69 if (l->f.b == nil) 70 panic("scrunmark: nil l->f.b"); 71 draw(l->f.b, r, scrback, nil, Pt(0, r.min.y-l->scroll.min.y)); 72 } 73 } 74 75 void 76 scrdraw(Flayer *l, long tot) 77 { 78 Rectangle r, r1, r2; 79 Image *b; 80 81 scrtemps(); 82 if(l->f.b == 0) 83 panic("scrdraw"); 84 r = l->scroll; 85 r1 = r; 86 if(l->visible == All){ 87 b = scrtmp; 88 r1.min.x = 0; 89 r1.max.x = Dx(r); 90 }else 91 b = l->f.b; 92 r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot); 93 if(!eqrect(r2, l->lastsr)){ 94 l->lastsr = r2; 95 draw(b, r1, l->f.cols[BORD], nil, ZP); 96 draw(b, r2, l->f.cols[BACK], nil, r2.min); 97 r2 = r1; 98 r2.min.x = r2.max.x-1; 99 draw(b, r2, l->f.cols[BORD], nil, ZP); 100 if(b!=l->f.b) 101 draw(l->f.b, r, b, nil, r1.min); 102 } 103 } 104 105 void 106 scroll(Flayer *l, int but) 107 { 108 int in = 0, oin; 109 long tot = scrtotal(l); 110 Rectangle scr, r, s, rt; 111 int x, y, my, oy, h; 112 long p0; 113 114 s = l->scroll; 115 x = s.min.x+FLSCROLLWID/2; 116 scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot); 117 r = scr; 118 y = scr.min.y; 119 my = mousep->xy.y; 120 draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min); 121 do{ 122 oin = in; 123 in = abs(x-mousep->xy.x)<=FLSCROLLWID/2; 124 if(oin && !in) 125 scrunmark(l, r); 126 if(in){ 127 scrmark(l, r); 128 oy = y; 129 my = mousep->xy.y; 130 if(my < s.min.y) 131 my = s.min.y; 132 if(my >= s.max.y) 133 my = s.max.y; 134 if(!eqpt(mousep->xy, Pt(x, my))) 135 moveto(mousectl, Pt(x, my)); 136 if(but == 1){ 137 p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my)); 138 rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); 139 y = rt.min.y; 140 }else if(but == 2){ 141 y = my; 142 if(y > s.max.y-2) 143 y = s.max.y-2; 144 }else if(but == 3){ 145 p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); 146 rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot); 147 y = rt.min.y; 148 } 149 if(y != oy){ 150 scrunmark(l, r); 151 r = rectaddpt(scr, Pt(0, y-scr.min.y)); 152 scrmark(l, r); 153 } 154 } 155 }while(button(but)); 156 if(in){ 157 h = s.max.y-s.min.y; 158 scrunmark(l, r); 159 p0 = 0; 160 if(but == 1) 161 p0 = (long)(my-s.min.y)/l->f.font->height+1; 162 else if(but == 2){ 163 if(tot > 1024L*1024L) 164 p0 = ((tot>>10)*(y-s.min.y)/h)<<10; 165 else 166 p0 = tot*(y-s.min.y)/h; 167 }else if(but == 3){ 168 p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my)); 169 if(p0 > tot) 170 p0 = tot; 171 } 172 scrorigin(l, but, p0); 173 } 174 } 175