ref: dde3628d54073e0569bf565e6ec861e42cfa35f6
dir: /sys/src/cmd/abaco/tabs.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <memdraw.h> #include <thread.h> #include <cursor.h> #include <mouse.h> #include <keyboard.h> #include <frame.h> #include <plumb.h> #include <html.h> #include "dat.h" #include "fns.h" void drawtable(Box *b, Page *p, Image *im) { Rectangle r, cr; Tablecell *c; Table *t; t = ((Itable *)b->i)->table; r = rectsubpt(b->r, p->pos); draw(im, r, getcolor(t->background.color), nil, ZP); if(t->border) border(im, r, t->border, display->black, ZP); for(c=t->cells; c!=nil; c=c->next){ cr = rectsubpt(c->lay->r, p->pos); if(c->background.color != t->background.color) draw(im, cr, getcolor(c->background.color), nil, ZP); if(t->border) border(im, cr, t->border, display->black, ZP); laydraw(p, im, c->lay); } } enum { Tablemax = 2000, Ttoplevel = 1<<0, }; static void settable(Table *t) { Tablecell *c; Lay *lay; for(c=t->cells; c!=nil; c=c->next){ lay = layitems(c->content, Rect(0,0,0,0), FALSE); c->minw = Dx(lay->r); layfree(lay); if(dimenkind(c->wspec) == Dnone){ lay = layitems(c->content, Rect(0,0,Tablemax,0), FALSE); c->maxw = Dx(lay->r); layfree(lay); } } } void settables(Page *p) { Table *t; Item *i; if(p->doc==nil) return; for(i=p->items; i!=nil; i=i->next) if(i->tag == Itabletag) ((Itable *)i)->table->flags |= Ttoplevel; for(t=p->doc->tables; t!=nil; t=t->next) settable(t); } static int cellwidth(Table *t, Tablecell *c, int sep) { int w, i, n; n = c->colspan; if(n == 1) return t->cols[c->col].width; if(n == 0) n = t->ncol - c->col; w = t->cellspacing*(n-1) + n*sep; for(i=c->col; i<c->col+n; i++) w += t->cols[i].width; return w; } static int cellheight(Table *t, Tablecell *c, int sep) { int h, i, n; n = c->rowspan; if(n == 1) return t->rows[c->row].height; if(n == 0) n = t->nrow - c->row; h = t->cellspacing*(n-1) + n*sep; for(i=c->row; i<c->row+n; i++) h += t->rows[i].height; return h; } static int getwidth(int *w, int n) { int i, tot; tot = 0; for(i=0; i<n; i++) tot += w[i]; return tot; } static void fixcols(Table *t, int *width, int sep, int domax) { Tablecell *c; int w, aw, i, d, n, rem; for(c=t->cells; c!=nil; c=c->next){ if(c->colspan == 1) continue; n = c->colspan; if(n == 0) n = t->ncol - c->col; w = domax ? c->maxw : c->minw; w -= t->cellspacing*(n-1) + n*sep; aw = 0; for(i=c->col; i<c->col+n; i++) aw += width[i]; rem = w-aw; if(rem <= 0) continue; for(i=c->col; i<c->col+n; i++){ if(aw > 0){ d = width[i]*100/aw; d = d*rem/100; }else d = rem/n; width[i] += d; } } } static int tablewidth(Table *t, int tw, int sep) { Tablecell *c; int i, w, tmin, tmax, d; int *maxw, *minw; int totw; maxw = emalloc(sizeof(int)*t->ncol); minw = emalloc(sizeof(int)*t->ncol); for(c=t->cells; c!=nil; c=c->next){ if(dimenkind(c->wspec) != Dnone){ d = c->minw; c->minw = c->maxw = max(dimwidth(c->wspec, tw), c->minw); c->minw = d; } if(c->colspan != 1) continue; maxw[c->col] = max(maxw[c->col], c->maxw); minw[c->col] = max(minw[c->col], c->minw); } totw = 0; fixcols(t, maxw, sep, TRUE); tmax = getwidth(maxw, t->ncol); if(tmax <= tw){ d = 0; if(tw>tmax && dimenkind(t->width)!=Dnone && t->availw!=Tablemax) d = (tw-tmax)/t->ncol; for(i=0; i<t->ncol; i++){ t->cols[i].width = maxw[i] + d; totw += t->cols[i].width; } }else{ fixcols(t, minw, sep, FALSE); tmin = getwidth(minw, t->ncol); w = tw - tmin; d = tmax - tmin; for(i=0; i<t->ncol; i++){ if(w<=0 || d<=0) t->cols[i].width = minw[i]; else t->cols[i].width = minw[i] + (maxw[i] - minw[i])*w/d; totw += t->cols[i].width; } } free(minw); free(maxw); return totw; } static void fixrows(Table *t, int sep) { Tablecell *c; Lay *lay; int h, ah, i, d, n, rem; for(c=t->cells; c!=nil; c=c->next){ if(c->rowspan == 1) continue; n = c->rowspan; if(n==0 || c->row+n>t->nrow) n = t->nrow - c->row; lay = layitems(c->content, Rect(0,0,cellwidth(t, c, sep),0), FALSE); h = max(Dy(lay->r), c->hspec); layfree(lay); h -= t->cellspacing*(n-1) + n*sep; ah = 0; for(i=c->row; i<c->row+n; i++) ah += t->rows[i].height; rem = h-ah; if(rem <= 0) continue; for(i=c->row; i<c->row+n; i++){ if(ah > 0){ d = t->rows[i].height*100/ah; d = d*rem/100; }else d = rem/n; t->rows[i].height += d; } } } static int tableheight(Table *t, int sep) { Tablecell *c; Lay *lay; int i, h, toth; for(i=0; i<t->nrow; i++){ h = 0; for(c=t->rows[i].cells; c!=nil; c=c->nextinrow){ if(c->rowspan != 1) continue; lay = layitems(c->content, Rect(0, 0, cellwidth(t, c, sep), 0), FALSE); h = max(h, max(Dy(lay->r), c->hspec)); layfree(lay); } t->rows[i].height = h; } fixrows(t, sep); toth = 0; for(i=0; i<t->nrow; i++) toth += t->rows[i].height; return toth; } void tablesize(Table *t, int availw) { int w, sep, hsep, vsep; t->availw = availw; sep = 2*(t->border+t->cellpadding); hsep = t->cellspacing*(t->ncol+1) + 2*t->border + t->ncol*sep; vsep = t->cellspacing*(t->nrow+1) + 2*t->border + t->nrow*sep; w = dimwidth(t->width, availw); w -= hsep; w = w>0 ? w : 0; t->totw = tablewidth(t, w, sep); t->totw += hsep; t->toth = tableheight(t, sep); t->toth += vsep; } void laytable(Itable *it, Rectangle r) { Rectangle cr; Tablecell *c; Table *t; int x, y, h, w; int sep, i; t = it->table; sep = (t->cellpadding+t->border) * 2; r = insetrect(r, t->cellspacing+t->border); for(c=t->cells; c!=nil; c=c->next){ w = cellwidth(t, c, sep); h = cellheight(t, c, sep); x = r.min.x; if(c->col > 0) for(i=0; i<c->col; i++) x += t->cols[i].width + sep + t->cellspacing; y = r.min.y; if(c->row > 0) for(i=0;i <c->row; i++) y += t->rows[i].height + sep + t->cellspacing; cr = Rect(x, y, x+w+sep, y+h+sep); c->lay = layitems(c->content, insetrect(cr, sep/2), TRUE); c->lay->r = cr; } }