/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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" voiddrawtable(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, }; staticvoidsettable(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); } }} voidsettables(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);} staticintcellwidth(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;} staticintcellheight(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;} staticintgetwidth(int *w, int n){ int i, tot; tot = 0; for(i=0; i<n; i++) tot += w[i]; return tot;} staticvoidfixcols(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; } }} staticinttablewidth(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;} staticvoidfixrows(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; } }} staticinttableheight(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;} voidtablesize(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;} voidlaytable(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; }}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
}
}