xref: /plan9/sys/src/cmd/acme/scrl.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include <u.h>
2*7dd7cddfSDavid du Colombier #include <libc.h>
3*7dd7cddfSDavid du Colombier #include <draw.h>
4*7dd7cddfSDavid du Colombier #include <thread.h>
5*7dd7cddfSDavid du Colombier #include <mouse.h>
6*7dd7cddfSDavid du Colombier #include <keyboard.h>
7*7dd7cddfSDavid du Colombier #include <frame.h>
8*7dd7cddfSDavid du Colombier #include <auth.h>
9*7dd7cddfSDavid du Colombier #include <fcall.h>
10*7dd7cddfSDavid du Colombier #include <plumb.h>
11*7dd7cddfSDavid du Colombier #include "dat.h"
12*7dd7cddfSDavid du Colombier #include "fns.h"
13*7dd7cddfSDavid du Colombier 
14*7dd7cddfSDavid du Colombier static Image *scrtmp;
15*7dd7cddfSDavid du Colombier 
16*7dd7cddfSDavid du Colombier static
17*7dd7cddfSDavid du Colombier Rectangle
18*7dd7cddfSDavid du Colombier scrpos(Rectangle r, uint p0, uint p1, uint tot)
19*7dd7cddfSDavid du Colombier {
20*7dd7cddfSDavid du Colombier 	Rectangle q;
21*7dd7cddfSDavid du Colombier 	int h;
22*7dd7cddfSDavid du Colombier 
23*7dd7cddfSDavid du Colombier 	q = r;
24*7dd7cddfSDavid du Colombier 	h = q.max.y-q.min.y;
25*7dd7cddfSDavid du Colombier 	if(tot == 0)
26*7dd7cddfSDavid du Colombier 		return q;
27*7dd7cddfSDavid du Colombier 	if(tot > 1024*1024){
28*7dd7cddfSDavid du Colombier 		tot>>=10;
29*7dd7cddfSDavid du Colombier 		p0>>=10;
30*7dd7cddfSDavid du Colombier 		p1>>=10;
31*7dd7cddfSDavid du Colombier 	}
32*7dd7cddfSDavid du Colombier 	if(p0 > 0)
33*7dd7cddfSDavid du Colombier 		q.min.y += h*p0/tot;
34*7dd7cddfSDavid du Colombier 	if(p1 < tot)
35*7dd7cddfSDavid du Colombier 		q.max.y -= h*(tot-p1)/tot;
36*7dd7cddfSDavid du Colombier 	if(q.max.y < q.min.y+2){
37*7dd7cddfSDavid du Colombier 		if(q.min.y+2 <= r.max.y)
38*7dd7cddfSDavid du Colombier 			q.max.y = q.min.y+2;
39*7dd7cddfSDavid du Colombier 		else
40*7dd7cddfSDavid du Colombier 			q.min.y = q.max.y-2;
41*7dd7cddfSDavid du Colombier 	}
42*7dd7cddfSDavid du Colombier 	return q;
43*7dd7cddfSDavid du Colombier }
44*7dd7cddfSDavid du Colombier 
45*7dd7cddfSDavid du Colombier void
46*7dd7cddfSDavid du Colombier scrlresize(void)
47*7dd7cddfSDavid du Colombier {
48*7dd7cddfSDavid du Colombier 	freeimage(scrtmp);
49*7dd7cddfSDavid du Colombier 	scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), display->chan, 0, DNofill);
50*7dd7cddfSDavid du Colombier 	if(scrtmp == nil)
51*7dd7cddfSDavid du Colombier 		error("scroll alloc");
52*7dd7cddfSDavid du Colombier }
53*7dd7cddfSDavid du Colombier 
54*7dd7cddfSDavid du Colombier void
55*7dd7cddfSDavid du Colombier textscrdraw(Text *t)
56*7dd7cddfSDavid du Colombier {
57*7dd7cddfSDavid du Colombier 	Rectangle r, r1, r2;
58*7dd7cddfSDavid du Colombier 	Image *b;
59*7dd7cddfSDavid du Colombier 
60*7dd7cddfSDavid du Colombier 	if(t->w==nil || t!=&t->w->body)
61*7dd7cddfSDavid du Colombier 		return;
62*7dd7cddfSDavid du Colombier 	if(scrtmp == nil)
63*7dd7cddfSDavid du Colombier 		scrlresize();
64*7dd7cddfSDavid du Colombier 	r = t->scrollr;
65*7dd7cddfSDavid du Colombier 	b = scrtmp;
66*7dd7cddfSDavid du Colombier 	r1 = r;
67*7dd7cddfSDavid du Colombier 	r1.min.x = 0;
68*7dd7cddfSDavid du Colombier 	r1.max.x = Dx(r);
69*7dd7cddfSDavid du Colombier 	r2 = scrpos(r1, t->org, t->org+t->nchars, t->file->nc);
70*7dd7cddfSDavid du Colombier 	if(!eqrect(r2, t->lastsr)){
71*7dd7cddfSDavid du Colombier 		t->lastsr = r2;
72*7dd7cddfSDavid du Colombier 		draw(b, r1, t->cols[BORD], nil, ZP);
73*7dd7cddfSDavid du Colombier 		draw(b, r2, t->cols[BACK], nil, ZP);
74*7dd7cddfSDavid du Colombier 		r2.min.x = r2.max.x-1;
75*7dd7cddfSDavid du Colombier 		draw(b, r2, t->cols[BORD], nil, ZP);
76*7dd7cddfSDavid du Colombier 		draw(t->b, r, b, nil, Pt(0, r1.min.y));
77*7dd7cddfSDavid du Colombier /*flushimage(display, 1);/*BUG?*/
78*7dd7cddfSDavid du Colombier 	}
79*7dd7cddfSDavid du Colombier }
80*7dd7cddfSDavid du Colombier 
81*7dd7cddfSDavid du Colombier void
82*7dd7cddfSDavid du Colombier scrsleep(uint dt)
83*7dd7cddfSDavid du Colombier {
84*7dd7cddfSDavid du Colombier 	Timer	*timer;
85*7dd7cddfSDavid du Colombier 	static Alt alts[3];
86*7dd7cddfSDavid du Colombier 
87*7dd7cddfSDavid du Colombier 	timer = timerstart(dt);
88*7dd7cddfSDavid du Colombier 	alts[0].c = timer->c;
89*7dd7cddfSDavid du Colombier 	alts[0].v = nil;
90*7dd7cddfSDavid du Colombier 	alts[0].op = CHANRCV;
91*7dd7cddfSDavid du Colombier 	alts[1].c = mousectl->c;
92*7dd7cddfSDavid du Colombier 	alts[1].v = &mousectl->Mouse;
93*7dd7cddfSDavid du Colombier 	alts[1].op = CHANRCV;
94*7dd7cddfSDavid du Colombier 	alts[2].op = CHANEND;
95*7dd7cddfSDavid du Colombier 	for(;;)
96*7dd7cddfSDavid du Colombier 		switch(alt(alts)){
97*7dd7cddfSDavid du Colombier 		case 0:
98*7dd7cddfSDavid du Colombier 			timerstop(timer);
99*7dd7cddfSDavid du Colombier 			return;
100*7dd7cddfSDavid du Colombier 		case 1:
101*7dd7cddfSDavid du Colombier 			timercancel(timer);
102*7dd7cddfSDavid du Colombier 			return;
103*7dd7cddfSDavid du Colombier 		}
104*7dd7cddfSDavid du Colombier }
105*7dd7cddfSDavid du Colombier 
106*7dd7cddfSDavid du Colombier void
107*7dd7cddfSDavid du Colombier textscroll(Text *t, int but)
108*7dd7cddfSDavid du Colombier {
109*7dd7cddfSDavid du Colombier 	uint p0, oldp0;
110*7dd7cddfSDavid du Colombier 	Rectangle s;
111*7dd7cddfSDavid du Colombier 	int x, y, my, h, first;
112*7dd7cddfSDavid du Colombier 
113*7dd7cddfSDavid du Colombier 	s = insetrect(t->scrollr, 1);
114*7dd7cddfSDavid du Colombier 	h = s.max.y-s.min.y;
115*7dd7cddfSDavid du Colombier 	x = (s.min.x+s.max.x)/2;
116*7dd7cddfSDavid du Colombier 	oldp0 = ~0;
117*7dd7cddfSDavid du Colombier 	first = TRUE;
118*7dd7cddfSDavid du Colombier 	do{
119*7dd7cddfSDavid du Colombier 		flushimage(display, 1);
120*7dd7cddfSDavid du Colombier 		if(mouse->xy.x<s.min.x || s.max.x<=mouse->xy.x){
121*7dd7cddfSDavid du Colombier 			readmouse(mousectl);
122*7dd7cddfSDavid du Colombier 		}else{
123*7dd7cddfSDavid du Colombier 			my = mouse->xy.y;
124*7dd7cddfSDavid du Colombier 			if(my < s.min.y)
125*7dd7cddfSDavid du Colombier 				my = s.min.y;
126*7dd7cddfSDavid du Colombier 			if(my >= s.max.y)
127*7dd7cddfSDavid du Colombier 				my = s.max.y;
128*7dd7cddfSDavid du Colombier 			if(!eqpt(mouse->xy, Pt(x, my))){
129*7dd7cddfSDavid du Colombier 				moveto(mousectl, Pt(x, my));
130*7dd7cddfSDavid du Colombier 				readmouse(mousectl);		/* absorb event generated by moveto() */
131*7dd7cddfSDavid du Colombier 			}
132*7dd7cddfSDavid du Colombier 			if(but == 2){
133*7dd7cddfSDavid du Colombier 				y = my;
134*7dd7cddfSDavid du Colombier 				if(y > s.max.y-2)
135*7dd7cddfSDavid du Colombier 					y = s.max.y-2;
136*7dd7cddfSDavid du Colombier 				if(t->file->nc > 1024*1024)
137*7dd7cddfSDavid du Colombier 					p0 = ((t->file->nc>>10)*(y-s.min.y)/h)<<10;
138*7dd7cddfSDavid du Colombier 				else
139*7dd7cddfSDavid du Colombier 					p0 = t->file->nc*(y-s.min.y)/h;
140*7dd7cddfSDavid du Colombier 				if(oldp0 != p0)
141*7dd7cddfSDavid du Colombier 					textsetorigin(t, p0, FALSE);
142*7dd7cddfSDavid du Colombier 				oldp0 = p0;
143*7dd7cddfSDavid du Colombier 				readmouse(mousectl);
144*7dd7cddfSDavid du Colombier 				continue;
145*7dd7cddfSDavid du Colombier 			}
146*7dd7cddfSDavid du Colombier 			if(but == 1)
147*7dd7cddfSDavid du Colombier 				p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
148*7dd7cddfSDavid du Colombier 			else
149*7dd7cddfSDavid du Colombier 				p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
150*7dd7cddfSDavid du Colombier 			if(oldp0 != p0)
151*7dd7cddfSDavid du Colombier 				textsetorigin(t, p0, TRUE);
152*7dd7cddfSDavid du Colombier 			oldp0 = p0;
153*7dd7cddfSDavid du Colombier 			/* debounce */
154*7dd7cddfSDavid du Colombier 			if(first){
155*7dd7cddfSDavid du Colombier 				flushimage(display, 1);
156*7dd7cddfSDavid du Colombier 				sleep(200);
157*7dd7cddfSDavid du Colombier 				nbrecv(mousectl->c, &mousectl->Mouse);
158*7dd7cddfSDavid du Colombier 				first = FALSE;
159*7dd7cddfSDavid du Colombier 			}
160*7dd7cddfSDavid du Colombier 			scrsleep(80);
161*7dd7cddfSDavid du Colombier 		}
162*7dd7cddfSDavid du Colombier 	}while(mouse->buttons & (1<<(but-1)));
163*7dd7cddfSDavid du Colombier 	while(mouse->buttons)
164*7dd7cddfSDavid du Colombier 		readmouse(mousectl);
165*7dd7cddfSDavid du Colombier }
166