xref: /plan9/sys/src/cmd/abaco/scrl.c (revision 7ab27030036b6c877a6f81728daeda263d1ca3cf)
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
scrlresize(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
scrpos(Rectangle r,uint p0,uint p1,uint tot)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
textscrdraw(Text * t)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
scrsleep(uint dt)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
textscroll(Text * t,int but)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
pagescrldraw(Page * p)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
pagescroll(Page * p,int but,int horizontal)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
pagescrollxy(Page * p,int x,int y)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