xref: /plan9/sys/src/cmd/acme/scrl.c (revision ded93d448500000b5015fa25ce7726536dfedc06)
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
scrpos(Rectangle r,uint p0,uint p1,uint tot)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
scrlresize(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
textscrdraw(Text * t)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
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->file->nc*(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