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
drawtable(Box * b,Page * p,Image * im)16 drawtable(Box *b, Page *p, Image *im)
17 {
18 Rectangle r, cr;
19 Tablecell *c;
20 Table *t;
21
22 t = ((Itable *)b->i)->table;
23 r = rectsubpt(b->r, p->pos);
24 draw(im, r, getcolor(t->background.color), nil, ZP);
25 if(t->border)
26 border(im, r, t->border, display->black, ZP);
27 for(c=t->cells; c!=nil; c=c->next){
28 cr = rectsubpt(c->lay->r, p->pos);
29 if(c->background.color != t->background.color)
30 draw(im, cr, getcolor(c->background.color), nil, ZP);
31 if(t->border)
32 border(im, cr, t->border, display->black, ZP);
33 laydraw(p, im, c->lay);
34 }
35 }
36
37 enum
38 {
39 Tablemax = 2000,
40 Ttoplevel = 1<<0,
41
42 };
43
44 static
45 void
settable(Table * t)46 settable(Table *t)
47 {
48 Tablecell *c;
49 Lay *lay;
50
51 for(c=t->cells; c!=nil; c=c->next){
52 lay = layitems(c->content, Rect(0,0,0,0), FALSE);
53 c->minw = Dx(lay->r);
54 layfree(lay);
55 if(dimenkind(c->wspec) == Dnone){
56 lay = layitems(c->content, Rect(0,0,Tablemax,0), FALSE);
57 c->maxw = Dx(lay->r);
58 layfree(lay);
59 }
60 }
61 }
62
63 void
settables(Page * p)64 settables(Page *p)
65 {
66 Table *t;
67 Item *i;
68
69 if(p->doc==nil)
70 return;
71 for(i=p->items; i!=nil; i=i->next)
72 if(i->tag == Itabletag)
73 ((Itable *)i)->table->flags |= Ttoplevel;
74
75 for(t=p->doc->tables; t!=nil; t=t->next)
76 settable(t);
77 }
78
79 static
80 int
cellwidth(Table * t,Tablecell * c,int sep)81 cellwidth(Table *t, Tablecell *c, int sep)
82 {
83 int w, i, n;
84
85 n = c->colspan;
86 if(n == 1)
87 return t->cols[c->col].width;
88 if(n == 0)
89 n = t->ncol - c->col;
90
91 w = t->cellspacing*(n-1) + n*sep;
92 for(i=c->col; i<c->col+n; i++)
93 w += t->cols[i].width;
94
95 return w;
96 }
97
98 static
99 int
cellheight(Table * t,Tablecell * c,int sep)100 cellheight(Table *t, Tablecell *c, int sep)
101 {
102 int h, i, n;
103
104 n = c->rowspan;
105 if(n == 1)
106 return t->rows[c->row].height;
107 if(n == 0)
108 n = t->nrow - c->row;
109
110 h = t->cellspacing*(n-1) + n*sep;
111 for(i=c->row; i<c->row+n; i++)
112 h += t->rows[i].height;
113
114 return h;
115 }
116
117 static
118 int
getwidth(int * w,int n)119 getwidth(int *w, int n)
120 {
121 int i, tot;
122
123 tot = 0;
124 for(i=0; i<n; i++)
125 tot += w[i];
126
127 return tot;
128 }
129
130 static
131 void
fixcols(Table * t,int * width,int sep,int domax)132 fixcols(Table *t, int *width, int sep, int domax)
133 {
134 Tablecell *c;
135 int w, aw, i, d, n, rem;
136
137
138 for(c=t->cells; c!=nil; c=c->next){
139 if(c->colspan == 1)
140 continue;
141
142 n = c->colspan;
143 if(n == 0)
144 n = t->ncol - c->col;
145
146 w = domax ? c->maxw : c->minw;
147 w -= t->cellspacing*(n-1) + n*sep;
148
149 aw = 0;
150 for(i=c->col; i<c->col+n; i++)
151 aw += width[i];
152
153 rem = w-aw;
154 if(rem <= 0)
155 continue;
156
157 for(i=c->col; i<c->col+n; i++){
158 if(aw > 0){
159 d = width[i]*100/aw;
160 d = d*rem/100;
161 }else
162 d = rem/n;
163 width[i] += d;
164 }
165 }
166 }
167
168 static
169 int
tablewidth(Table * t,int tw,int sep)170 tablewidth(Table *t, int tw, int sep)
171 {
172 Tablecell *c;
173 int i, w, tmin, tmax, d;
174 int *maxw, *minw;
175 int totw;
176
177 maxw = emalloc(sizeof(int)*t->ncol);
178 minw = emalloc(sizeof(int)*t->ncol);
179 for(c=t->cells; c!=nil; c=c->next){
180 if(dimenkind(c->wspec) != Dnone){
181 d = c->minw;
182 c->minw = c->maxw = max(dimwidth(c->wspec, tw), c->minw);
183 c->minw = d;
184 }
185 if(c->colspan != 1)
186 continue;
187 maxw[c->col] = max(maxw[c->col], c->maxw);
188 minw[c->col] = max(minw[c->col], c->minw);
189 }
190 totw = 0;
191 fixcols(t, maxw, sep, TRUE);
192 tmax = getwidth(maxw, t->ncol);
193 if(tmax <= tw){
194 d = 0;
195 if(tw>tmax && dimenkind(t->width)!=Dnone && t->availw!=Tablemax)
196 d = (tw-tmax)/t->ncol;
197 for(i=0; i<t->ncol; i++){
198 t->cols[i].width = maxw[i] + d;
199 totw += t->cols[i].width;
200 }
201 }else{
202 fixcols(t, minw, sep, FALSE);
203 tmin = getwidth(minw, t->ncol);
204 w = tw - tmin;
205 d = tmax - tmin;
206 for(i=0; i<t->ncol; i++){
207 if(w<=0 || d<=0)
208 t->cols[i].width = minw[i];
209 else
210 t->cols[i].width = minw[i] + (maxw[i] - minw[i])*w/d;
211 totw += t->cols[i].width;
212 }
213 }
214 free(minw);
215 free(maxw);
216
217 return totw;
218 }
219
220 static
221 void
fixrows(Table * t,int sep)222 fixrows(Table *t, int sep)
223 {
224 Tablecell *c;
225 Lay *lay;
226 int h, ah, i, d, n, rem;
227
228 for(c=t->cells; c!=nil; c=c->next){
229 if(c->rowspan == 1)
230 continue;
231 n = c->rowspan;
232 if(n==0 || c->row+n>t->nrow)
233 n = t->nrow - c->row;
234
235 lay = layitems(c->content, Rect(0,0,cellwidth(t, c, sep),0), FALSE);
236 h = max(Dy(lay->r), c->hspec);
237 layfree(lay);
238 h -= t->cellspacing*(n-1) + n*sep;
239 ah = 0;
240 for(i=c->row; i<c->row+n; i++)
241 ah += t->rows[i].height;
242
243 rem = h-ah;
244 if(rem <= 0)
245 continue;
246
247 for(i=c->row; i<c->row+n; i++){
248 if(ah > 0){
249 d = t->rows[i].height*100/ah;
250 d = d*rem/100;
251 }else
252 d = rem/n;
253
254 t->rows[i].height += d;
255 }
256 }
257 }
258
259 static
260 int
tableheight(Table * t,int sep)261 tableheight(Table *t, int sep)
262 {
263 Tablecell *c;
264 Lay *lay;
265 int i, h, toth;
266
267 for(i=0; i<t->nrow; i++){
268 h = 0;
269 for(c=t->rows[i].cells; c!=nil; c=c->nextinrow){
270 if(c->rowspan != 1)
271 continue;
272 lay = layitems(c->content, Rect(0, 0, cellwidth(t, c, sep), 0), FALSE);
273 h = max(h, max(Dy(lay->r), c->hspec));
274 layfree(lay);
275 }
276 t->rows[i].height = h;
277 }
278 fixrows(t, sep);
279 toth = 0;
280 for(i=0; i<t->nrow; i++)
281 toth += t->rows[i].height;
282
283 return toth;
284 }
285
286 void
tablesize(Table * t,int availw)287 tablesize(Table *t, int availw)
288 {
289 int w, sep, hsep, vsep;
290
291 t->availw = availw;
292 sep = 2*(t->border+t->cellpadding);
293 hsep = t->cellspacing*(t->ncol+1) + 2*t->border + t->ncol*sep;
294 vsep = t->cellspacing*(t->nrow+1) + 2*t->border + t->nrow*sep;
295 w = dimwidth(t->width, availw);
296 w -= hsep;
297 w = w>0 ? w : 0;
298 t->totw = tablewidth(t, w, sep);
299 t->totw += hsep;
300 t->toth = tableheight(t, sep);
301 t->toth += vsep;
302 }
303
304 void
laytable(Itable * it,Rectangle r)305 laytable(Itable *it, Rectangle r)
306 {
307 Rectangle cr;
308 Tablecell *c;
309 Table *t;
310 int x, y, h, w;
311 int sep, i;
312
313 t = it->table;
314
315 sep = (t->cellpadding+t->border) * 2;
316 r = insetrect(r, t->cellspacing+t->border);
317 for(c=t->cells; c!=nil; c=c->next){
318 w = cellwidth(t, c, sep);
319 h = cellheight(t, c, sep);
320 x = r.min.x;
321 if(c->col > 0)
322 for(i=0; i<c->col; i++)
323 x += t->cols[i].width + sep + t->cellspacing;
324 y = r.min.y;
325 if(c->row > 0)
326 for(i=0;i <c->row; i++)
327 y += t->rows[i].height + sep + t->cellspacing;
328 cr = Rect(x, y, x+w+sep, y+h+sep);
329 c->lay = layitems(c->content, insetrect(cr, sep/2), TRUE);
330 c->lay->r = cr;
331 }
332 }
333