#include #include #include #include #include #include #include #include "univ.h" void RequestLines(Pad*); static Image *scrtemp; static Image *scrback; void ScrollTemps( void ){ int h; if( scrback ) return; #define BIG 3 h = BIG*Dy( screen->r ); if( (scrback = allocimage( display, Rect(0,0,32,h), screen->chan, 0, 0 ))==0 ) panic( "ScrollTemps" ); } Rectangle scrollbar( Rectangle r, int from, int to, int lo, int hi ){ int rh = Dy(r), h = hi-lo; dprint(1, "scrollbar( %R, from.%d, to.%d, lo.0, hi.%d )", r, from, to, hi); ScrollTemps(); r.max.y -= muldiv(hi-to, rh, h); r.min.y += muldiv(from-lo, rh, h); dprint(0, "r = %R", r); dprint(-1, "scrollbar()"); return r; } Rectangle ScrollPos( Rectangle r, long lo, long hi, long tot ){ Rectangle q; int h; dprint(1, "ScrollPos(%R, lo.%d, hi.%d, tot.%d)", r, lo, hi, tot); q = r; if( tot == 0 ) return q; h = q.max.y-q.min.y; if( tot > 1024L*1024L ) tot>>=10, lo>>=10, hi>>=10; if( lo > 0 ) q.min.y += h*lo/tot; if( hi < tot-1 ) q.max.y -= h*(tot-hi-1)/tot; if( q.max.y < q.min.y+2 ){ if( q.min.y+2 <= r.max.y ) q.max.y = q.min.y+2; else q.min.y = q.max.y-2; } dprint(-1, "ScrollPos() => %R", q); return q; } long ScrollTotal( Pad *p ){ /* was in ClipPaint */ long lines; Line *l, *lsent=&p->sentinel; if( lsent->key ) lines = lsent->key; else for( lines=0, l=lsent->down; l!=lsent ; l=l->down ) lines++; return (p->nlines=lines); } void PaintScroll( Pad *p ){ long tot = ScrollTotal( p ); Rectangle r1, r2; dprint(1, "PaintScroll(p.%s)", p? p->name: ""); dprint(0, "tot == %d", tot); ScrollTemps(); r1 = p->scroll; r2 = scrollbar( r1, p->lo, p->hi, 0, tot ); if( !eqrect( r2, p->bar ) ){ p->bar = r2; draw( screen, r1, padcols[BACK], nil, ZP ); draw( screen, r2, padcols[BORD], nil, r2.min ); } dprint(-1, "PaintScroll(...)"); } void Doscroll( Pad *p, int but ){ Rectangle r, s; int lo, delta; Line *l, *lsent = &p->sentinel; int x, dy, y, y0, y1, y2, yscale; int x0 = p->scroll.min.x; int x1 = p->scroll.max.x; int lines = ScrollTotal(p); if( but!=2 ) return; dprint(1, "Doscroll()"); y0 = p->scroll.min.y; yscale = p->scroll.max.y - y0; s = insetrect(p->scroll, 1); x = (s.min.x+s.max.x)/2; delta = p->hi - p->lo + 1; r = scrollbar( p->scroll, p->lo, p->hi+1, 0, lines+1 ); y = r.min.y; draw(scrback, Rect(0,0,Dx(p->scroll),Dy(p->scroll)), screen, nil, p->scroll.min); while(button(but)){ if( ptinrect(mousep->xy, p->scroll) ) { y1 = y; y2 = mousep->xy.y; if(y2 < p->scroll.min.y) y2 = p->scroll.min.y; if(y2 >= p->scroll.max.y) y2 = p->scroll.max.y; y = y2; if(y > p->scroll.max.y-2) y = p->scroll.max.y-2; if(y != y1){ Rectangle clr, set; dy = y - y0; lo = muldiv(dy, lines, yscale) - (delta >> 1); if (lo < 0) lo = 0; else if ((lo + delta) > lines) lo = lines - delta; s = scrollbar(p->scroll, lo, lo+delta, 0, lines+1); if (s.min.y-r.min.y > 0) { /* down */ clr = Rect(x0, r.min.y, x1, s.min.y); set = Rect(x0, r.max.y, x1, s.max.y); } else { /* up */ clr = Rect(x0, s.max.y, x1, r.max.y); set = Rect(x0, s.min.y, x1, r.min.y); } draw(screen, clr, padcols[BACK], nil, ZPoint); draw(screen, set, padcols[BORD], nil, ZPoint); r = s; y = r.min.y; } } jnap: waitMOUSE(); } if( ptinrect(mousep->xy,p->scroll) ){ Scrolly = mousep->xy.y; Paint(p); Scrolly = 0; RequestLines(p); dprint(-1, "Doscroll()"); return; } draw(screen, p->scroll, scrback, nil, ZPoint); dprint(-1, "Doscroll()"); }