1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 #include <thread.h> 6 #include <cursor.h> 7 #include <mouse.h> 8 #include <keyboard.h> 9 #include <frame.h> 10 #include <plumb.h> 11 #include <html.h> 12 #include "dat.h" 13 #include "fns.h" 14 15 static Image *vscrtmp; 16 static Image *hscrtmp; 17 18 void 19 scrlresize(void) 20 { 21 freeimage(vscrtmp); 22 freeimage(hscrtmp); 23 vscrtmp = eallocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill); 24 hscrtmp = eallocimage(display, Rect(0, 0, screen->r.max.x, 32), screen->chan, 0, DNofill); 25 } 26 27 static 28 Rectangle 29 scrpos(Rectangle r, uint p0, uint p1, uint tot) 30 { 31 Rectangle q; 32 int h; 33 34 q = r; 35 h = q.max.y-q.min.y; 36 if(tot == 0) 37 return q; 38 if(tot > 1024*1024){ 39 tot>>=10; 40 p0>>=10; 41 p1>>=10; 42 } 43 if(p0 > 0) 44 q.min.y += h*p0/tot; 45 if(p1 < tot) 46 q.max.y -= h*(tot-p1)/tot; 47 if(q.max.y < q.min.y+2){ 48 if(q.min.y+2 <= r.max.y) 49 q.max.y = q.min.y+2; 50 else 51 q.min.y = q.max.y-2; 52 } 53 return q; 54 } 55 56 void 57 textscrdraw(Text *t) 58 { 59 Rectangle r, r1, r2; 60 Image *b; 61 62 if(vscrtmp == nil) 63 scrlresize(); 64 r = t->scrollr; 65 b = vscrtmp; 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->rs.nr); 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->rs.nr*(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 160 enum 161 { 162 Scrbord = 1, 163 }; 164 165 void 166 pagescrldraw(Page *p) 167 { 168 Rectangle r1; 169 int t, d, l, h; 170 171 if(vscrtmp == nil) 172 scrlresize(); 173 174 r1 = Rect(0,0,Dx(p->hscrollr), Dy(p->hscrollr)); 175 d = Dx(r1); 176 t = Dx(p->lay->r); 177 l = muldiv(p->pos.x, d, t); 178 h = muldiv(p->pos.x+d, d, t); 179 draw(hscrtmp, r1, tagcols[HIGH], nil, ZP); 180 r1.max.x = r1.min.x+h; 181 r1.min.x += l; 182 r1.min.y += Scrbord; 183 r1.max.y -= Scrbord; 184 draw(hscrtmp, r1, tagcols[BACK], nil, ZP); 185 186 r1 = Rect(0,0,Dx(p->vscrollr), Dy(p->vscrollr)); 187 d = Dy(r1); 188 t = Dy(p->lay->r); 189 l = muldiv(p->pos.y, d, t); 190 h = muldiv(p->pos.y+d, d, t); 191 draw(vscrtmp, r1, tagcols[HIGH], nil, ZP); 192 r1.max.y = r1.min.y+h; 193 r1.min.y += l; 194 r1.max.x -= Scrbord; 195 r1.min.x += Scrbord; 196 draw(vscrtmp, r1, tagcols[BACK], nil, ZP); 197 198 draw(screen, p->vscrollr, vscrtmp, nil, vscrtmp->r.min); 199 draw(screen, p->hscrollr, hscrtmp, nil, hscrtmp->r.min); 200 } 201 202 void 203 pagescroll(Page *p, int but, int horizontal) 204 { 205 uint oldp0, p0; 206 Rectangle s; 207 Point mxy; 208 int i, m, om, first, d, size; 209 int smin, smax, ss, *pos; 210 211 if(horizontal){ 212 s = insetrect(p->hscrollr, 1); 213 ss = s.max.x - s.min.x; 214 i = (s.min.y+s.max.y)/2; 215 d = Dx(p->r); 216 size = Dx(p->lay->r); 217 p0 = p->pos.x; 218 pos = &p->pos.x; 219 smin = s.min.x; 220 smax = s.max.x; 221 om = mouse->xy.x; 222 }else{ 223 s = insetrect(p->vscrollr, 1); 224 ss = s.max.y-s.min.y; 225 i = (s.min.x+s.max.x)/2; 226 d = Dy(p->r); 227 size = Dy(p->lay->r); 228 p0 = p->pos.y; 229 pos = &p->pos.y; 230 smin = s.min.y; 231 smax = s.max.y; 232 om = mouse->xy.y; 233 } 234 oldp0 = ~0; 235 first = TRUE; 236 do{ 237 flushimage(display, 1); 238 if(horizontal) 239 m = mouse->xy.x; 240 else 241 m = mouse->xy.y; 242 243 if(m > om) 244 m += (m-om)*Panspeed; 245 else if(m < om) 246 m -= (om-m)*Panspeed; 247 248 if(m < smin) 249 m = smin; 250 if(m > smax) 251 m = smax; 252 253 om = m; 254 if(horizontal) 255 mxy = Pt(m, i); 256 else 257 mxy = Pt(i, m); 258 if(!eqpt(mouse->xy, mxy)){ 259 moveto(mousectl, mxy); 260 readmouse(mousectl); /* absorb event generated by moveto() */ 261 } 262 if(but == 2){ 263 p0 = muldiv(m-smin, size, ss); 264 p0 = max(p0, 0); 265 p0 = min(p0,size-d); 266 if(oldp0 != p0){ 267 *pos = p0; 268 pageredraw(p); 269 } 270 oldp0 = p0; 271 readmouse(mousectl); 272 continue; 273 } 274 if(but == 1) 275 p0 -= (d/2); 276 else 277 p0 += d/2; 278 p0 = min(p0, size-d); 279 p0 = max(p0, 0); 280 if(oldp0 != p0){ 281 *pos = p0; 282 pageredraw(p); 283 } 284 oldp0 = p0; 285 /* debounce */ 286 if(first){ 287 flushimage(display, 1); 288 sleep(200); 289 nbrecv(mousectl->c, &mousectl->Mouse); 290 first = FALSE; 291 } 292 scrsleep(80); 293 }while(mouse->buttons & (1<<(but-1))); 294 while(mouse->buttons) 295 readmouse(mousectl); 296 } 297 298 int 299 pagescrollxy(Page *p, int x, int y) 300 { 301 int scrled; 302 303 scrled = FALSE; 304 if(x != 0){ 305 p->pos.x += x; 306 p->pos.x = max(p->pos.x, 0); 307 p->pos.x = min(p->pos.x, Dx(p->lay->r)-Dx(p->r)); 308 scrled =TRUE; 309 } 310 if(y != 0){ 311 p->pos.y += y; 312 p->pos.y = max(p->pos.y, 0); 313 p->pos.y = min(p->pos.y, Dy(p->lay->r)-Dy(p->r)); 314 scrled =TRUE; 315 } 316 return scrled; 317 } 318