xref: /plan9/sys/src/libframe/frselect.c (revision 5d459b5a09e427ae1acd4e6afcf028853c73946e)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <frame.h>
7 
8 static
9 int
region(int a,int b)10 region(int a, int b)
11 {
12 	if(a < b)
13 		return -1;
14 	if(a == b)
15 		return 0;
16 	return 1;
17 }
18 
19 void
frselect(Frame * f,Mousectl * mc)20 frselect(Frame *f, Mousectl *mc)	/* when called, button 1 is down */
21 {
22 	ulong p0, p1, q;
23 	Point mp, pt0, pt1, qt;
24 	int reg, b, scrled;
25 
26 	mp = mc->xy;
27 	b = mc->buttons;
28 
29 	f->modified = 0;
30 	frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 0);
31 	p0 = p1 = frcharofpt(f, mp);
32 	f->p0 = p0;
33 	f->p1 = p1;
34 	pt0 = frptofchar(f, p0);
35 	pt1 = frptofchar(f, p1);
36 	frdrawsel(f, pt0, p0, p1, 1);
37 	reg = 0;
38 	do{
39 		scrled = 0;
40 		if(f->scroll){
41 			if(mp.y < f->r.min.y){
42 				(*f->scroll)(f, -(f->r.min.y-mp.y)/(int)f->font->height-1);
43 				p0 = f->p1;
44 				p1 = f->p0;
45 				scrled = 1;
46 			}else if(mp.y > f->r.max.y){
47 				(*f->scroll)(f, (mp.y-f->r.max.y)/(int)f->font->height+1);
48 				p0 = f->p0;
49 				p1 = f->p1;
50 				scrled = 1;
51 			}
52 			if(scrled){
53 				if(reg != region(p1, p0))
54 					q = p0, p0 = p1, p1 = q;	/* undo the swap that will happen below */
55 				pt0 = frptofchar(f, p0);
56 				pt1 = frptofchar(f, p1);
57 				reg = region(p1, p0);
58 			}
59 		}
60 		q = frcharofpt(f, mp);
61 		if(p1 != q){
62 			if(reg != region(q, p0)){	/* crossed starting point; reset */
63 				if(reg > 0)
64 					frdrawsel(f, pt0, p0, p1, 0);
65 				else if(reg < 0)
66 					frdrawsel(f, pt1, p1, p0, 0);
67 				p1 = p0;
68 				pt1 = pt0;
69 				reg = region(q, p0);
70 				if(reg == 0)
71 					frdrawsel(f, pt0, p0, p1, 1);
72 			}
73 			qt = frptofchar(f, q);
74 			if(reg > 0){
75 				if(q > p1)
76 					frdrawsel(f, pt1, p1, q, 1);
77 				else if(q < p1)
78 					frdrawsel(f, qt, q, p1, 0);
79 			}else if(reg < 0){
80 				if(q > p1)
81 					frdrawsel(f, pt1, p1, q, 0);
82 				else
83 					frdrawsel(f, qt, q, p1, 1);
84 			}
85 			p1 = q;
86 			pt1 = qt;
87 		}
88 		f->modified = 0;
89 		if(p0 < p1) {
90 			f->p0 = p0;
91 			f->p1 = p1;
92 		}
93 		else {
94 			f->p0 = p1;
95 			f->p1 = p0;
96 		}
97 		if(scrled)
98 			(*f->scroll)(f, 0);
99 		flushimage(f->display, 1);
100 		if(!scrled)
101 			readmouse(mc);
102 		mp = mc->xy;
103 	}while(mc->buttons == b);
104 }
105 
106 void
frselectpaint(Frame * f,Point p0,Point p1,Image * col)107 frselectpaint(Frame *f, Point p0, Point p1, Image *col)
108 {
109 	int n;
110 	Point q0, q1;
111 
112 	q0 = p0;
113 	q1 = p1;
114 	q0.y += f->font->height;
115 	q1.y += f->font->height;
116 	n = (p1.y-p0.y)/f->font->height;
117 	if(f->b == nil)
118 		drawerror(f->display, "frselectpaint b==0");
119 	if(p0.y == f->r.max.y)
120 		return;
121 	if(n == 0)
122 		draw(f->b, Rpt(p0, q1), col, nil, ZP);
123 	else{
124 		if(p0.x >= f->r.max.x)
125 			p0.x = f->r.max.x-1;
126 		draw(f->b, Rect(p0.x, p0.y, f->r.max.x, q0.y), col, nil, ZP);
127 		if(n > 1)
128 			draw(f->b, Rect(f->r.min.x, q0.y, f->r.max.x, p1.y),
129 				col, nil, ZP);
130 		draw(f->b, Rect(f->r.min.x, p1.y, q1.x, q1.y),
131 			col, nil, ZP);
132 	}
133 }
134