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