xref: /plan9-contrib/sys/src/cmd/acme/scrl.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <cursor.h>
6 #include <mouse.h>
7 #include <keyboard.h>
8 #include <frame.h>
9 #include <fcall.h>
10 #include <plumb.h>
11 #include "dat.h"
12 #include "fns.h"
13 
14 static Image *scrtmp;
15 
16 static
17 Rectangle
18 scrpos(Rectangle r, uint p0, uint p1, uint tot)
19 {
20 	Rectangle q;
21 	int h;
22 
23 	q = r;
24 	h = q.max.y-q.min.y;
25 	if(tot == 0)
26 		return q;
27 	if(tot > 1024*1024){
28 		tot>>=10;
29 		p0>>=10;
30 		p1>>=10;
31 	}
32 	if(p0 > 0)
33 		q.min.y += h*p0/tot;
34 	if(p1 < tot)
35 		q.max.y -= h*(tot-p1)/tot;
36 	if(q.max.y < q.min.y+2){
37 		if(q.min.y+2 <= r.max.y)
38 			q.max.y = q.min.y+2;
39 		else
40 			q.min.y = q.max.y-2;
41 	}
42 	return q;
43 }
44 
45 void
46 scrlresize(void)
47 {
48 	freeimage(scrtmp);
49 	scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);
50 	if(scrtmp == nil)
51 		error("scroll alloc");
52 }
53 
54 void
55 textscrdraw(Text *t)
56 {
57 	Rectangle r, r1, r2;
58 	Image *b;
59 
60 	if(t->w==nil || t!=&t->w->body)
61 		return;
62 	if(scrtmp == nil)
63 		scrlresize();
64 	r = t->scrollr;
65 	b = scrtmp;
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->file->nc);
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
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
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 		if(mouse->xy.x<s.min.x || s.max.x<=mouse->xy.x){
121 			readmouse(mousectl);
122 		}else{
123 			my = mouse->xy.y;
124 			if(my < s.min.y)
125 				my = s.min.y;
126 			if(my >= s.max.y)
127 				my = s.max.y;
128 			if(!eqpt(mouse->xy, Pt(x, my))){
129 				moveto(mousectl, Pt(x, my));
130 				readmouse(mousectl);		/* absorb event generated by moveto() */
131 			}
132 			if(but == 2){
133 				y = my;
134 				if(y > s.max.y-2)
135 					y = s.max.y-2;
136 				if(t->file->nc > 1024*1024)
137 					p0 = ((t->file->nc>>10)*(y-s.min.y)/h)<<10;
138 				else
139 					p0 = t->file->nc*(y-s.min.y)/h;
140 				if(oldp0 != p0)
141 					textsetorigin(t, p0, FALSE);
142 				oldp0 = p0;
143 				readmouse(mousectl);
144 				continue;
145 			}
146 			if(but == 1)
147 				p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
148 			else
149 				p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
150 			if(oldp0 != p0)
151 				textsetorigin(t, p0, TRUE);
152 			oldp0 = p0;
153 			/* debounce */
154 			if(first){
155 				flushimage(display, 1);
156 				sleep(200);
157 				nbrecv(mousectl->c, &mousectl->Mouse);
158 				first = FALSE;
159 			}
160 			scrsleep(80);
161 		}
162 	}while(mouse->buttons & (1<<(but-1)));
163 	while(mouse->buttons)
164 		readmouse(mousectl);
165 }
166