xref: /plan9/sys/src/cmd/abaco/rows.c (revision 7ab27030036b6c877a6f81728daeda263d1ca3cf)
1*7ab27030SDavid du Colombier #include <u.h>
2*7ab27030SDavid du Colombier #include <libc.h>
3*7ab27030SDavid du Colombier #include <draw.h>
4*7ab27030SDavid du Colombier #include <memdraw.h>
5*7ab27030SDavid du Colombier #include <thread.h>
6*7ab27030SDavid du Colombier #include <cursor.h>
7*7ab27030SDavid du Colombier #include <mouse.h>
8*7ab27030SDavid du Colombier #include <keyboard.h>
9*7ab27030SDavid du Colombier #include <frame.h>
10*7ab27030SDavid du Colombier #include <plumb.h>
11*7ab27030SDavid du Colombier #include <html.h>
12*7ab27030SDavid du Colombier #include "dat.h"
13*7ab27030SDavid du Colombier #include "fns.h"
14*7ab27030SDavid du Colombier 
15*7ab27030SDavid du Colombier void
rowinit(Row * row,Rectangle r)16*7ab27030SDavid du Colombier rowinit(Row *row, Rectangle r)
17*7ab27030SDavid du Colombier {
18*7ab27030SDavid du Colombier 	Rectangle r1;
19*7ab27030SDavid du Colombier 	Text *t;
20*7ab27030SDavid du Colombier 
21*7ab27030SDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
22*7ab27030SDavid du Colombier 	row->r = r;
23*7ab27030SDavid du Colombier 	row->col = nil;
24*7ab27030SDavid du Colombier 	row->ncol = 0;
25*7ab27030SDavid du Colombier 	r1 = r;
26*7ab27030SDavid du Colombier 	r1.max.y = r1.min.y + font->height;
27*7ab27030SDavid du Colombier 	t = &row->tag;
28*7ab27030SDavid du Colombier 	textinit(t, screen, r1, font, tagcols);
29*7ab27030SDavid du Colombier 	t->what = Rowtag;
30*7ab27030SDavid du Colombier 	t->row = row;
31*7ab27030SDavid du Colombier 	t->w = nil;
32*7ab27030SDavid du Colombier 	t->col = nil;
33*7ab27030SDavid du Colombier 	r1.min.y = r1.max.y;
34*7ab27030SDavid du Colombier 	r1.max.y += Border;
35*7ab27030SDavid du Colombier 	draw(screen, r1, display->black, nil, ZP);
36*7ab27030SDavid du Colombier 	textinsert(t, 0, L"Newcol Google Exit ", 19);
37*7ab27030SDavid du Colombier 	textsetselect(t, t->rs.nr, t->rs.nr);
38*7ab27030SDavid du Colombier }
39*7ab27030SDavid du Colombier 
40*7ab27030SDavid du Colombier Column*
rowadd(Row * row,Column * c,int x)41*7ab27030SDavid du Colombier rowadd(Row *row, Column *c, int x)
42*7ab27030SDavid du Colombier {
43*7ab27030SDavid du Colombier 	Rectangle r, r1;
44*7ab27030SDavid du Colombier 	Column *d;
45*7ab27030SDavid du Colombier 	int i;
46*7ab27030SDavid du Colombier 
47*7ab27030SDavid du Colombier 	d = nil;
48*7ab27030SDavid du Colombier 	r = row->r;
49*7ab27030SDavid du Colombier 	r.min.y = row->tag.r.max.y+Border;
50*7ab27030SDavid du Colombier 	if(x<r.min.x && row->ncol>0){	/*steal 40% of last column by default */
51*7ab27030SDavid du Colombier 		d = row->col[row->ncol-1];
52*7ab27030SDavid du Colombier 		x = d->r.min.x + 3*Dx(d->r)/5;
53*7ab27030SDavid du Colombier 	}
54*7ab27030SDavid du Colombier 	/* look for column we'll land on */
55*7ab27030SDavid du Colombier 	for(i=0; i<row->ncol; i++){
56*7ab27030SDavid du Colombier 		d = row->col[i];
57*7ab27030SDavid du Colombier 		if(x < d->r.max.x)
58*7ab27030SDavid du Colombier 			break;
59*7ab27030SDavid du Colombier 	}
60*7ab27030SDavid du Colombier 	if(row->ncol > 0){
61*7ab27030SDavid du Colombier 		if(i < row->ncol)
62*7ab27030SDavid du Colombier 			i++;	/* new column will go after d */
63*7ab27030SDavid du Colombier 		r = d->r;
64*7ab27030SDavid du Colombier 		if(Dx(r) < 100)
65*7ab27030SDavid du Colombier 			return nil;
66*7ab27030SDavid du Colombier 		draw(screen, r, display->white, nil, ZP);
67*7ab27030SDavid du Colombier 		r1 = r;
68*7ab27030SDavid du Colombier 		r1.max.x = min(x, r.max.x-50);
69*7ab27030SDavid du Colombier 		if(Dx(r1) < 50)
70*7ab27030SDavid du Colombier 			r1.max.x = r1.min.x+50;
71*7ab27030SDavid du Colombier 		colresize(d, r1);
72*7ab27030SDavid du Colombier 		r1.min.x = r1.max.x;
73*7ab27030SDavid du Colombier 		r1.max.x = r1.min.x+Border;
74*7ab27030SDavid du Colombier 		draw(screen, r1, display->black, nil, ZP);
75*7ab27030SDavid du Colombier 		r.min.x = r1.max.x;
76*7ab27030SDavid du Colombier 	}
77*7ab27030SDavid du Colombier 	if(c == nil){
78*7ab27030SDavid du Colombier 		c = emalloc(sizeof(Column));
79*7ab27030SDavid du Colombier 		colinit(c, r);
80*7ab27030SDavid du Colombier 	}else
81*7ab27030SDavid du Colombier 		colresize(c, r);
82*7ab27030SDavid du Colombier 	c->row = row;
83*7ab27030SDavid du Colombier 	c->tag.row = row;
84*7ab27030SDavid du Colombier 	row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*));
85*7ab27030SDavid du Colombier 	memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*));
86*7ab27030SDavid du Colombier 	row->col[i] = c;
87*7ab27030SDavid du Colombier 	row->ncol++;
88*7ab27030SDavid du Colombier 	clearmouse();
89*7ab27030SDavid du Colombier 	return c;
90*7ab27030SDavid du Colombier }
91*7ab27030SDavid du Colombier 
92*7ab27030SDavid du Colombier void
rowresize(Row * row,Rectangle r)93*7ab27030SDavid du Colombier rowresize(Row *row, Rectangle r)
94*7ab27030SDavid du Colombier {
95*7ab27030SDavid du Colombier 	int i, dx, odx;
96*7ab27030SDavid du Colombier 	Rectangle r1, r2;
97*7ab27030SDavid du Colombier 	Column *c;
98*7ab27030SDavid du Colombier 
99*7ab27030SDavid du Colombier 	dx = Dx(r);
100*7ab27030SDavid du Colombier 	odx = Dx(row->r);
101*7ab27030SDavid du Colombier 	row->r = r;
102*7ab27030SDavid du Colombier 	r1 = r;
103*7ab27030SDavid du Colombier 	r1.max.y = r1.min.y + font->height;
104*7ab27030SDavid du Colombier 	textresize(&row->tag, screen, r1);
105*7ab27030SDavid du Colombier 	r1.min.y = r1.max.y;
106*7ab27030SDavid du Colombier 	r1.max.y += Border;
107*7ab27030SDavid du Colombier 	draw(screen, r1, display->black, nil, ZP);
108*7ab27030SDavid du Colombier 	r.min.y = r1.max.y;
109*7ab27030SDavid du Colombier 	r1 = r;
110*7ab27030SDavid du Colombier 	r1.max.x = r1.min.x;
111*7ab27030SDavid du Colombier 	for(i=0; i<row->ncol; i++){
112*7ab27030SDavid du Colombier 		c = row->col[i];
113*7ab27030SDavid du Colombier 		r1.min.x = r1.max.x;
114*7ab27030SDavid du Colombier 		if(i == row->ncol-1)
115*7ab27030SDavid du Colombier 			r1.max.x = r.max.x;
116*7ab27030SDavid du Colombier 		else
117*7ab27030SDavid du Colombier 			r1.max.x = r1.min.x+Dx(c->r)*dx/odx;
118*7ab27030SDavid du Colombier 		if(i > 0){
119*7ab27030SDavid du Colombier 			r2 = r1;
120*7ab27030SDavid du Colombier 			r2.max.x = r2.min.x+Border;
121*7ab27030SDavid du Colombier 			draw(screen, r2, display->black, nil, ZP);
122*7ab27030SDavid du Colombier 			r1.min.x = r2.max.x;
123*7ab27030SDavid du Colombier 		}
124*7ab27030SDavid du Colombier 		colresize(c, r1);
125*7ab27030SDavid du Colombier 	}
126*7ab27030SDavid du Colombier }
127*7ab27030SDavid du Colombier 
128*7ab27030SDavid du Colombier void
rowdragcol(Row * row,Column * c,int)129*7ab27030SDavid du Colombier rowdragcol(Row *row, Column *c, int)
130*7ab27030SDavid du Colombier {
131*7ab27030SDavid du Colombier 	Rectangle r;
132*7ab27030SDavid du Colombier 	int i, b, x;
133*7ab27030SDavid du Colombier 	Point p, op;
134*7ab27030SDavid du Colombier 	Column *d;
135*7ab27030SDavid du Colombier 
136*7ab27030SDavid du Colombier 	clearmouse();
137*7ab27030SDavid du Colombier 	setcursor(mousectl, &boxcursor);
138*7ab27030SDavid du Colombier 	b = mouse->buttons;
139*7ab27030SDavid du Colombier 	op = mouse->xy;
140*7ab27030SDavid du Colombier 	while(mouse->buttons == b)
141*7ab27030SDavid du Colombier 		readmouse(mousectl);
142*7ab27030SDavid du Colombier 	setcursor(mousectl, nil);
143*7ab27030SDavid du Colombier 	if(mouse->buttons){
144*7ab27030SDavid du Colombier 		while(mouse->buttons)
145*7ab27030SDavid du Colombier 			readmouse(mousectl);
146*7ab27030SDavid du Colombier 		return;
147*7ab27030SDavid du Colombier 	}
148*7ab27030SDavid du Colombier 
149*7ab27030SDavid du Colombier 	for(i=0; i<row->ncol; i++)
150*7ab27030SDavid du Colombier 		if(row->col[i] == c)
151*7ab27030SDavid du Colombier 			goto Found;
152*7ab27030SDavid du Colombier 	error("can't find column");
153*7ab27030SDavid du Colombier 
154*7ab27030SDavid du Colombier   Found:
155*7ab27030SDavid du Colombier 	if(i == 0)
156*7ab27030SDavid du Colombier 		return;
157*7ab27030SDavid du Colombier 	p = mouse->xy;
158*7ab27030SDavid du Colombier 	if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5))
159*7ab27030SDavid du Colombier 		return;
160*7ab27030SDavid du Colombier 	if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){
161*7ab27030SDavid du Colombier 		/* shuffle */
162*7ab27030SDavid du Colombier 		x = c->r.min.x;
163*7ab27030SDavid du Colombier 		rowclose(row, c, FALSE);
164*7ab27030SDavid du Colombier 		if(rowadd(row, c, p.x) == nil)	/* whoops! */
165*7ab27030SDavid du Colombier 		if(rowadd(row, c, x) == nil)		/* WHOOPS! */
166*7ab27030SDavid du Colombier 		if(rowadd(row, c, -1)==nil){		/* shit! */
167*7ab27030SDavid du Colombier 			rowclose(row, c, TRUE);
168*7ab27030SDavid du Colombier 			return;
169*7ab27030SDavid du Colombier 		}
170*7ab27030SDavid du Colombier 		colmousebut(c);
171*7ab27030SDavid du Colombier 		return;
172*7ab27030SDavid du Colombier 	}
173*7ab27030SDavid du Colombier 	d = row->col[i-1];
174*7ab27030SDavid du Colombier 	if(p.x < d->r.min.x+80+Scrollsize)
175*7ab27030SDavid du Colombier 		p.x = d->r.min.x+80+Scrollsize;
176*7ab27030SDavid du Colombier 	if(p.x > c->r.max.x-80-Scrollsize)
177*7ab27030SDavid du Colombier 		p.x = c->r.max.x-80-Scrollsize;
178*7ab27030SDavid du Colombier 	r = d->r;
179*7ab27030SDavid du Colombier 	r.max.x = c->r.max.x;
180*7ab27030SDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
181*7ab27030SDavid du Colombier 	r.max.x = p.x;
182*7ab27030SDavid du Colombier 	colresize(d, r);
183*7ab27030SDavid du Colombier 	r = c->r;
184*7ab27030SDavid du Colombier 	r.min.x = p.x;
185*7ab27030SDavid du Colombier 	r.max.x = r.min.x;
186*7ab27030SDavid du Colombier 	r.max.x += Border;
187*7ab27030SDavid du Colombier 	draw(screen, r, display->black, nil, ZP);
188*7ab27030SDavid du Colombier 	r.min.x = r.max.x;
189*7ab27030SDavid du Colombier 	r.max.x = c->r.max.x;
190*7ab27030SDavid du Colombier 	colresize(c, r);
191*7ab27030SDavid du Colombier 	colmousebut(c);
192*7ab27030SDavid du Colombier }
193*7ab27030SDavid du Colombier 
194*7ab27030SDavid du Colombier void
rowclose(Row * row,Column * c,int dofree)195*7ab27030SDavid du Colombier rowclose(Row *row, Column *c, int dofree)
196*7ab27030SDavid du Colombier {
197*7ab27030SDavid du Colombier 	Rectangle r;
198*7ab27030SDavid du Colombier 	int i;
199*7ab27030SDavid du Colombier 
200*7ab27030SDavid du Colombier 	for(i=0; i<row->ncol; i++)
201*7ab27030SDavid du Colombier 		if(row->col[i] == c)
202*7ab27030SDavid du Colombier 			goto Found;
203*7ab27030SDavid du Colombier 	error("can't find column");
204*7ab27030SDavid du Colombier   Found:
205*7ab27030SDavid du Colombier 	r = c->r;
206*7ab27030SDavid du Colombier 	if(dofree)
207*7ab27030SDavid du Colombier 		colcloseall(c);
208*7ab27030SDavid du Colombier 	memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
209*7ab27030SDavid du Colombier 	row->ncol--;
210*7ab27030SDavid du Colombier 	row->col = realloc(row->col, row->ncol*sizeof(Column*));
211*7ab27030SDavid du Colombier 	if(row->ncol == 0){
212*7ab27030SDavid du Colombier 		draw(screen, r, display->white, nil, ZP);
213*7ab27030SDavid du Colombier 		return;
214*7ab27030SDavid du Colombier 	}
215*7ab27030SDavid du Colombier 	if(i == row->ncol){		/* extend last column right */
216*7ab27030SDavid du Colombier 		c = row->col[i-1];
217*7ab27030SDavid du Colombier 		r.min.x = c->r.min.x;
218*7ab27030SDavid du Colombier 		r.max.x = row->r.max.x;
219*7ab27030SDavid du Colombier 	}else{			/* extend next window left */
220*7ab27030SDavid du Colombier 		c = row->col[i];
221*7ab27030SDavid du Colombier 		r.max.x = c->r.max.x;
222*7ab27030SDavid du Colombier 	}
223*7ab27030SDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
224*7ab27030SDavid du Colombier 	colresize(c, r);
225*7ab27030SDavid du Colombier }
226*7ab27030SDavid du Colombier 
227*7ab27030SDavid du Colombier Column*
rowwhichcol(Row * row,Point p)228*7ab27030SDavid du Colombier rowwhichcol(Row *row, Point p)
229*7ab27030SDavid du Colombier {
230*7ab27030SDavid du Colombier 	int i;
231*7ab27030SDavid du Colombier 	Column *c;
232*7ab27030SDavid du Colombier 
233*7ab27030SDavid du Colombier 	for(i=0; i<row->ncol; i++){
234*7ab27030SDavid du Colombier 		c = row->col[i];
235*7ab27030SDavid du Colombier 		if(ptinrect(p, c->r))
236*7ab27030SDavid du Colombier 			return c;
237*7ab27030SDavid du Colombier 	}
238*7ab27030SDavid du Colombier 	return nil;
239*7ab27030SDavid du Colombier }
240*7ab27030SDavid du Colombier 
241*7ab27030SDavid du Colombier Text*
rowwhich(Row * row,Point p,Rune r,int key)242*7ab27030SDavid du Colombier rowwhich(Row *row, Point p, Rune r, int key)
243*7ab27030SDavid du Colombier {
244*7ab27030SDavid du Colombier 	Column *c;
245*7ab27030SDavid du Colombier 
246*7ab27030SDavid du Colombier 	if(ptinrect(p, row->tag.all))
247*7ab27030SDavid du Colombier 		return &row->tag;
248*7ab27030SDavid du Colombier 	c = rowwhichcol(row, p);
249*7ab27030SDavid du Colombier 	if(c)
250*7ab27030SDavid du Colombier 		return colwhich(c, p, r, key);
251*7ab27030SDavid du Colombier 	return nil;
252*7ab27030SDavid du Colombier }
253