Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 "dat.h"
11
#include "fns.h"
12
 
13
static Image *scrtmp;
14
 
15
static
16
void
17
scrtemps(void)
18
{
19
	int h;
20
 
21
	if(scrtmp)
22
		return;
23
	h = BIG*Dy(screen->r);
24
	scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DWhite);
25
	if(scrtmp == nil)
26
		error("scrtemps");
27
}
28
 
29
void
30
freescrtemps(void)
31
{
32
	freeimage(scrtmp);
33
	scrtmp = nil;
34
}
35
 
36
static
37
Rectangle
38
scrpos(Rectangle r, uint p0, uint p1, uint tot)
39
{
40
	Rectangle q;
41
	int h;
42
 
43
	q = r;
44
	h = q.max.y-q.min.y;
45
	if(tot == 0)
46
		return q;
47
	if(tot > 1024*1024){
48
		tot>>=10;
49
		p0>>=10;
50
		p1>>=10;
51
	}
52
	if(p0 > 0)
53
		q.min.y += h*p0/tot;
54
	if(p1 < tot)
55
		q.max.y -= h*(tot-p1)/tot;
56
	if(q.max.y < q.min.y+2){
57
		if(q.min.y+2 <= r.max.y)
58
			q.max.y = q.min.y+2;
59
		else
60
			q.min.y = q.max.y-2;
61
	}
62
	return q;
63
}
64
 
65
void
66
wscrdraw(Window *w)
67
{
68
	Rectangle r, r1, r2;
69
	Image *b;
70
 
71
	scrtemps();
72
	if(w->i == nil)
73
		error("scrdraw");
74
	r = w->scrollr;
75
	b = scrtmp;
76
	r1 = r;
77
	r1.min.x = 0;
78
	r1.max.x = Dx(r);
79
	r2 = scrpos(r1, w->org, w->org+w->nchars, w->nr);
80
	if(!eqrect(r2, w->lastsr)){
81
		w->lastsr = r2;
82
		/* move r1, r2 to (0,0) to avoid clipping */
83
		r2 = rectsubpt(r2, r1.min);
84
		r1 = rectsubpt(r1, r1.min);
85
		draw(b, r1, w->cols[BORD], nil, ZP);
86
		draw(b, r2, w->cols[BACK], nil, ZP);
87
		r2.min.x = r2.max.x-1;
88
		draw(b, r2, w->cols[BORD], nil, ZP);
89
		draw(w->i, r, b, nil, Pt(0, r1.min.y));
90
	}
91
}
92
 
93
void
94
wscrsleep(Window *w, uint dt)
95
{
96
	Timer	*timer;
97
	int y, b;
98
	static Alt alts[3];
99
 
100
	timer = timerstart(dt);
101
	y = w->mc.xy.y;
102
	b = w->mc.buttons;
103
	alts[0].c = timer->c;
104
	alts[0].v = nil;
105
	alts[0].op = CHANRCV;
106
	alts[1].c = w->mc.c;
107
	alts[1].v = &w->mc.Mouse;
108
	alts[1].op = CHANRCV;
109
	alts[2].op = CHANEND;
110
	for(;;)
111
		switch(alt(alts)){
112
		case 0:
113
			timerstop(timer);
114
			return;
115
		case 1:
116
			if(abs(w->mc.xy.y-y)>2 || w->mc.buttons!=b){
117
				timercancel(timer);
118
				return;
119
			}
120
			break;
121
		}
122
}
123
 
124
void
125
wscroll(Window *w, int but)
126
{
127
	uint p0, oldp0;
128
	Rectangle s;
129
	int x, y, my, h, first;
130
 
131
	s = insetrect(w->scrollr, 1);
132
	h = s.max.y-s.min.y;
133
	x = (s.min.x+s.max.x)/2;
134
	oldp0 = ~0;
135
	first = TRUE;
136
	do{
137
		flushimage(display, 1);
138
		if(w->mc.xy.x<s.min.x || s.max.x<=w->mc.xy.x){
139
			readmouse(&w->mc);
140
		}else{
141
			my = w->mc.xy.y;
142
			if(my < s.min.y)
143
				my = s.min.y;
144
			if(my >= s.max.y)
145
				my = s.max.y;
146
			if(!eqpt(w->mc.xy, Pt(x, my))){
147
				wmovemouse(w, Pt(x, my));
148
				readmouse(&w->mc);		/* absorb event generated by moveto() */
149
			}
150
			if(but == 2){
151
				y = my;
152
				if(y > s.max.y-2)
153
					y = s.max.y-2;
154
				if(w->nr > 1024*1024)
155
					p0 = ((w->nr>>10)*(y-s.min.y)/h)<<10;
156
				else
157
					p0 = w->nr*(y-s.min.y)/h;
158
				if(oldp0 != p0)
159
					wsetorigin(w, p0, FALSE);
160
				oldp0 = p0;
161
				readmouse(&w->mc);
162
				continue;
163
			}
164
			if(but == 1)
165
				p0 = wbacknl(w, w->org, (my-s.min.y)/w->font->height);
166
			else
167
				p0 = w->org+frcharofpt(w, Pt(s.max.x, my));
168
			if(oldp0 != p0)
169
				wsetorigin(w, p0, TRUE);
170
			oldp0 = p0;
171
			/* debounce */
172
			if(first){
173
				flushimage(display, 1);
174
				sleep(200);
175
				nbrecv(w->mc.c, &w->mc.Mouse);
176
				first = FALSE;
177
			}
178
			wscrsleep(w, 100);
179
		}
180
	}while(w->mc.buttons & (1<<(but-1)));
181
	while(w->mc.buttons)
182
		readmouse(&w->mc);
183
}