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