plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }