341 lines · 6.3 KB · C
RawDownload
/*  * 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;	}}