]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/abaco/tabs.c
abacos tcs.h is automatically generated
[plan9front.git] / sys / src / cmd / abaco / tabs.c
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
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
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
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
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
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
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
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
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
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
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
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
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 }