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 } 333