xref: /plan9/sys/src/cmd/samterm/scroll.c (revision 671dfc474d1a5bcbeda8be1356d2abfa05b91489)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <mouse.h>
67dd7cddfSDavid du Colombier #include <keyboard.h>
73e12c5d1SDavid du Colombier #include <frame.h>
83e12c5d1SDavid du Colombier #include "flayer.h"
93e12c5d1SDavid du Colombier #include "samterm.h"
103e12c5d1SDavid du Colombier 
117dd7cddfSDavid du Colombier static Image *scrtmp;
127dd7cddfSDavid du Colombier static Image *scrback;
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier void
scrtemps(void)157dd7cddfSDavid du Colombier scrtemps(void)
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier 	int h;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier 	if(scrtmp)
207dd7cddfSDavid du Colombier 		return;
217dd7cddfSDavid du Colombier 	if(screensize(0, &h) == 0)
227dd7cddfSDavid du Colombier 		h = 2048;
239a747e4fSDavid du Colombier 	scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0);
249a747e4fSDavid du Colombier 	scrback = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, 0);
257dd7cddfSDavid du Colombier 	if(scrtmp==0 || scrback==0)
267dd7cddfSDavid du Colombier 		panic("scrtemps");
277dd7cddfSDavid du Colombier }
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier Rectangle
scrpos(Rectangle r,long p0,long p1,long tot)303e12c5d1SDavid du Colombier scrpos(Rectangle r, long p0, long p1, long tot)
313e12c5d1SDavid du Colombier {
323e12c5d1SDavid du Colombier 	Rectangle q;
337dd7cddfSDavid du Colombier 	int h;
343e12c5d1SDavid du Colombier 
357dd7cddfSDavid du Colombier 	q = r;
363e12c5d1SDavid du Colombier 	h = q.max.y-q.min.y;
373e12c5d1SDavid du Colombier 	if(tot == 0)
383e12c5d1SDavid du Colombier 		return q;
393e12c5d1SDavid du Colombier 	if(tot > 1024L*1024L)
403e12c5d1SDavid du Colombier 		tot>>=10, p0>>=10, p1>>=10;
413e12c5d1SDavid du Colombier 	if(p0 > 0)
423e12c5d1SDavid du Colombier 		q.min.y += h*p0/tot;
433e12c5d1SDavid du Colombier 	if(p1 < tot)
443e12c5d1SDavid du Colombier 		q.max.y -= h*(tot-p1)/tot;
453e12c5d1SDavid du Colombier 	if(q.max.y < q.min.y+2){
463e12c5d1SDavid du Colombier 		if(q.min.y+2 <= r.max.y)
473e12c5d1SDavid du Colombier 			q.max.y = q.min.y+2;
483e12c5d1SDavid du Colombier 		else
493e12c5d1SDavid du Colombier 			q.min.y = q.max.y-2;
503e12c5d1SDavid du Colombier 	}
513e12c5d1SDavid du Colombier 	return q;
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier void
scrmark(Flayer * l,Rectangle r)557dd7cddfSDavid du Colombier scrmark(Flayer *l, Rectangle r)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier 	r.max.x--;
58*671dfc47SDavid du Colombier 	if(rectclip(&r, l->scroll)) {
59*671dfc47SDavid du Colombier 		if (l->f.b == nil)
60*671dfc47SDavid du Colombier 			panic("scrmark: nil l->f.b");
617dd7cddfSDavid du Colombier 		draw(l->f.b, r, l->f.cols[HIGH], nil, ZP);
627dd7cddfSDavid du Colombier 	}
63*671dfc47SDavid du Colombier }
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier void
scrunmark(Flayer * l,Rectangle r)667dd7cddfSDavid du Colombier scrunmark(Flayer *l, Rectangle r)
673e12c5d1SDavid du Colombier {
68*671dfc47SDavid du Colombier 	if(rectclip(&r, l->scroll)) {
69*671dfc47SDavid du Colombier 		if (l->f.b == nil)
70*671dfc47SDavid du Colombier 			panic("scrunmark: nil l->f.b");
717dd7cddfSDavid du Colombier 		draw(l->f.b, r, scrback, nil, Pt(0, r.min.y-l->scroll.min.y));
723e12c5d1SDavid du Colombier 	}
73*671dfc47SDavid du Colombier }
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier void
scrdraw(Flayer * l,long tot)763e12c5d1SDavid du Colombier scrdraw(Flayer *l, long tot)
773e12c5d1SDavid du Colombier {
783e12c5d1SDavid du Colombier 	Rectangle r, r1, r2;
797dd7cddfSDavid du Colombier 	Image *b;
803e12c5d1SDavid du Colombier 
817dd7cddfSDavid du Colombier 	scrtemps();
823e12c5d1SDavid du Colombier 	if(l->f.b == 0)
833e12c5d1SDavid du Colombier 		panic("scrdraw");
843e12c5d1SDavid du Colombier 	r = l->scroll;
853e12c5d1SDavid du Colombier 	r1 = r;
863e12c5d1SDavid du Colombier 	if(l->visible == All){
877dd7cddfSDavid du Colombier 		b = scrtmp;
883e12c5d1SDavid du Colombier 		r1.min.x = 0;
893e12c5d1SDavid du Colombier 		r1.max.x = Dx(r);
903e12c5d1SDavid du Colombier 	}else
913e12c5d1SDavid du Colombier 		b = l->f.b;
923e12c5d1SDavid du Colombier 	r2 = scrpos(r1, l->origin, l->origin+l->f.nchars, tot);
937dd7cddfSDavid du Colombier 	if(!eqrect(r2, l->lastsr)){
947dd7cddfSDavid du Colombier 		l->lastsr = r2;
957dd7cddfSDavid du Colombier 		draw(b, r1, l->f.cols[BORD], nil, ZP);
967dd7cddfSDavid du Colombier 		draw(b, r2, l->f.cols[BACK], nil, r2.min);
977dd7cddfSDavid du Colombier 		r2 = r1;
987dd7cddfSDavid du Colombier 		r2.min.x = r2.max.x-1;
997dd7cddfSDavid du Colombier 		draw(b, r2, l->f.cols[BORD], nil, ZP);
1003e12c5d1SDavid du Colombier 		if(b!=l->f.b)
1017dd7cddfSDavid du Colombier 			draw(l->f.b, r, b, nil, r1.min);
1027dd7cddfSDavid du Colombier 	}
1033e12c5d1SDavid du Colombier }
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier void
scroll(Flayer * l,int but)1063e12c5d1SDavid du Colombier scroll(Flayer *l, int but)
1073e12c5d1SDavid du Colombier {
1083e12c5d1SDavid du Colombier 	int in = 0, oin;
1093e12c5d1SDavid du Colombier 	long tot = scrtotal(l);
1103e12c5d1SDavid du Colombier 	Rectangle scr, r, s, rt;
1113e12c5d1SDavid du Colombier 	int x, y, my, oy, h;
1123e12c5d1SDavid du Colombier 	long p0;
1133e12c5d1SDavid du Colombier 
1147dd7cddfSDavid du Colombier 	s = l->scroll;
1153e12c5d1SDavid du Colombier 	x = s.min.x+FLSCROLLWID/2;
1163e12c5d1SDavid du Colombier 	scr = scrpos(l->scroll, l->origin, l->origin+l->f.nchars, tot);
1173e12c5d1SDavid du Colombier 	r = scr;
1183e12c5d1SDavid du Colombier 	y = scr.min.y;
1197dd7cddfSDavid du Colombier 	my = mousep->xy.y;
1207dd7cddfSDavid du Colombier 	draw(scrback, Rect(0,0,Dx(l->scroll), Dy(l->scroll)), l->f.b, nil, l->scroll.min);
1213e12c5d1SDavid du Colombier 	do{
1223e12c5d1SDavid du Colombier 		oin = in;
1237dd7cddfSDavid du Colombier 		in = abs(x-mousep->xy.x)<=FLSCROLLWID/2;
1247dd7cddfSDavid du Colombier 		if(oin && !in)
1257dd7cddfSDavid du Colombier 			scrunmark(l, r);
1263e12c5d1SDavid du Colombier 		if(in){
1277dd7cddfSDavid du Colombier 			scrmark(l, r);
1283e12c5d1SDavid du Colombier 			oy = y;
1297dd7cddfSDavid du Colombier 			my = mousep->xy.y;
1303e12c5d1SDavid du Colombier 			if(my < s.min.y)
1313e12c5d1SDavid du Colombier 				my = s.min.y;
1323e12c5d1SDavid du Colombier 			if(my >= s.max.y)
1333e12c5d1SDavid du Colombier 				my = s.max.y;
1347dd7cddfSDavid du Colombier 			if(!eqpt(mousep->xy, Pt(x, my)))
1357dd7cddfSDavid du Colombier 				moveto(mousectl, Pt(x, my));
1363e12c5d1SDavid du Colombier 			if(but == 1){
1373e12c5d1SDavid du Colombier 				p0 = l->origin-frcharofpt(&l->f, Pt(s.max.x, my));
1383e12c5d1SDavid du Colombier 				rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
1393e12c5d1SDavid du Colombier 				y = rt.min.y;
1403e12c5d1SDavid du Colombier 			}else if(but == 2){
1413e12c5d1SDavid du Colombier 				y = my;
1423e12c5d1SDavid du Colombier 				if(y > s.max.y-2)
1433e12c5d1SDavid du Colombier 					y = s.max.y-2;
1443e12c5d1SDavid du Colombier 			}else if(but == 3){
1453e12c5d1SDavid du Colombier 				p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
1463e12c5d1SDavid du Colombier 				rt = scrpos(l->scroll, p0, p0+l->f.nchars, tot);
1473e12c5d1SDavid du Colombier 				y = rt.min.y;
1483e12c5d1SDavid du Colombier 			}
1493e12c5d1SDavid du Colombier 			if(y != oy){
1507dd7cddfSDavid du Colombier 				scrunmark(l, r);
1517dd7cddfSDavid du Colombier 				r = rectaddpt(scr, Pt(0, y-scr.min.y));
1527dd7cddfSDavid du Colombier 				scrmark(l, r);
1533e12c5d1SDavid du Colombier 			}
1543e12c5d1SDavid du Colombier 		}
1553e12c5d1SDavid du Colombier 	}while(button(but));
1563e12c5d1SDavid du Colombier 	if(in){
1573e12c5d1SDavid du Colombier 		h = s.max.y-s.min.y;
1587dd7cddfSDavid du Colombier 		scrunmark(l, r);
1593e12c5d1SDavid du Colombier 		p0 = 0;
1603e12c5d1SDavid du Colombier 		if(but == 1)
1613e12c5d1SDavid du Colombier 			p0 = (long)(my-s.min.y)/l->f.font->height+1;
1623e12c5d1SDavid du Colombier 		else if(but == 2){
1633e12c5d1SDavid du Colombier 			if(tot > 1024L*1024L)
1643e12c5d1SDavid du Colombier 				p0 = ((tot>>10)*(y-s.min.y)/h)<<10;
1653e12c5d1SDavid du Colombier 			else
1663e12c5d1SDavid du Colombier 				p0 = tot*(y-s.min.y)/h;
1673e12c5d1SDavid du Colombier 		}else if(but == 3){
1683e12c5d1SDavid du Colombier 			p0 = l->origin+frcharofpt(&l->f, Pt(s.max.x, my));
1693e12c5d1SDavid du Colombier 			if(p0 > tot)
1703e12c5d1SDavid du Colombier 				p0 = tot;
1713e12c5d1SDavid du Colombier 		}
1723e12c5d1SDavid du Colombier 		scrorigin(l, but, p0);
1733e12c5d1SDavid du Colombier 	}
1743e12c5d1SDavid du Colombier }
175