xref: /plan9/sys/src/cmd/samterm/scroll.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <libg.h>
4 #include <frame.h>
5 #include "flayer.h"
6 #include "samterm.h"
7 
8 extern Bitmap *darkgrey;
9 extern Mouse mouse;
10 
11 Rectangle
12 scrpos(Rectangle r, long p0, long p1, long tot)
13 {
14 	long h;
15 	Rectangle q;
16 
17 	q = inset(r, 1);
18 	h = q.max.y-q.min.y;
19 	if(tot == 0)
20 		return q;
21 	if(tot > 1024L*1024L)
22 		tot>>=10, p0>>=10, p1>>=10;
23 	if(p0 > 0)
24 		q.min.y += h*p0/tot;
25 	if(p1 < tot)
26 		q.max.y -= h*(tot-p1)/tot;
27 	if(q.max.y < q.min.y+2){
28 		if(q.min.y+2 <= r.max.y)
29 			q.max.y = q.min.y+2;
30 		else
31 			q.min.y = q.max.y-2;
32 	}
33 	return q;
34 }
35 
36 void
37 scrflip(Flayer *l, Rectangle r)
38 {
39 	if(rectclip(&r, l->scroll))
40 		bitblt(l->f.b, r.min, l->f.b, r, F&~D);
41 }
42 
43 void
44 scrdraw(Flayer *l, long tot)
45 {
46 	Rectangle r, r1, r2;
47 	Bitmap *b;
48 	static Bitmap *x;
49 	int h;
50 
51 	if(l->f.b == 0)
52 		panic("scrdraw");
53 	r = l->scroll;
54 	r.min.x += 1;	/* border between margin and bar */
55 	r1 = r;
56 	if(l->visible == All){
57 		if(x == 0){
58 			if (screensize(0, &h) == 0)
59 				h = 2048;
60 			x = balloc(Rect(0, 0, 32, h), l->f.b->ldepth);
61 			if(x == 0)
62 				panic("scrdraw balloc");
63 		}
64 		b = x;
65 		r1.min.x = 0;
66 		r1.max.x = Dx(r);
67 	}else
68 		b = l->f.b;
69 	bitblt(b, r1.min, b, r1, F);
70 	texture(b, inset(r1, 1), darkgrey, S);
71 	r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot);
72 	bitblt(b, r2.min, b, r2, 0);
73 	if(b!=l->f.b)
74 		bitblt(l->f.b, r.min, b, r1, S);
75 }
76 
77 void
78 scroll(Flayer *l, int but)
79 {
80 	int in = 0, oin;
81 	long tot = scrtotal(l);
82 	Rectangle scr, r, s, rt;
83 	int x, y, my, oy, h;
84 	long p0;
85 
86 	s = inset(l->scroll, 1);
87 	x = s.min.x+FLSCROLLWID/2;
88 	scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot);
89 	r = scr;
90 	y = scr.min.y;
91 	my = mouse.xy.y;
92 	do{
93 		oin = in;
94 		in = abs(x-mouse.xy.x)<=FLSCROLLWID/2;
95 		if(oin != in)
96 			scrflip(l, r);
97 		if(in){
98 			oy = y;
99 			my = mouse.xy.y;
100 			if(my < s.min.y)
101 				my = s.min.y;
102 			if(my >= s.max.y)
103 				my = s.max.y;
104 			if(!eqpt(mouse.xy, Pt(x, my)))
105 				cursorset(Pt(x, my));
106 			if(but == 1){
107 				p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my));
108 				rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
109 				y = rt.min.y;
110 			}else if(but == 2){
111 				y = my;
112 				if(y > s.max.y-2)
113 					y = s.max.y-2;
114 			}else if(but == 3){
115 				p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
116 				rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
117 				y = rt.min.y;
118 			}
119 			if(y != oy){
120 				scrflip(l, r);
121 				r = raddp(scr, Pt(0, y-scr.min.y));
122 				scrflip(l, r);
123 			}
124 		}
125 	}while(button(but));
126 	if(in){
127 		h = s.max.y-s.min.y;
128 		scrflip(l, r);
129 		p0 = 0;
130 		if(but == 1)
131 			p0 = (long)(my-s.min.y)/l->f.font->height+1;
132 		else if(but == 2){
133 			if(tot > 1024L*1024L)
134 				p0 = ((tot>>10)*(y-s.min.y)/h)<<10;
135 			else
136 				p0 = tot*(y-s.min.y)/h;
137 		}else if(but == 3){
138 			p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
139 			if(p0 > tot)
140 				p0 = tot;
141 		}
142 		scrorigin(l, but, p0);
143 	}
144 }
145