forsyth20100821-1800749be1916 years agoHistory
696 lines · 12.9 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h" #define	O(t, e)		((long)(&((t*)0)->e)) typedef struct Pack Pack;struct Pack {	Tk*	t;	Pack*	next;};static Pack *packorder; static int tkpacker(Tk *); typedef struct TkParam TkParam;struct TkParam{	Point	pad;	Point	ipad;	int	side;	int	anchor;	int	fill;	Tk*	in;	Tk*	before;	Tk*	after;	int	expand;}; TkParam defparam = {	{-1, -1},	/* p.pad */	{-1, -1},	/* p.ipad */	-1,		/* side */	-1,		/* anchor */	-1,		/* fill */	nil,		/* in */	nil, 		/* before */	nil,		/* after */	BoolX	/* expand */}; staticTkStab tkside[] ={	"top",		Tktop,	"bottom",	Tkbottom,	"left",		Tkleft,	"right",	Tkright,	nil}; staticTkStab tkfill[] ={	"none",		0,	"x",		Tkfillx,	"y",		Tkfilly,	"both",		Tkfillx|Tkfilly,	nil}; staticTkOption opts[] ={	"padx",		OPTnndist,	O(TkParam, pad.x),	nil,	"pady",		OPTnndist,	O(TkParam, pad.y),	nil,	"ipadx",	OPTnndist,	O(TkParam, ipad.x),	nil,	"ipady",	OPTnndist,	O(TkParam, ipad.y),	nil,	"side",		OPTstab,	O(TkParam, side),	tkside,	"anchor",	OPTstab,	O(TkParam, anchor),	tkanchor,	"fill",		OPTstab,	O(TkParam, fill),	tkfill,	"in",		OPTwinp,	O(TkParam, in),		nil,	"before",	OPTwinp,	O(TkParam, before),	nil,	"after",	OPTwinp,	O(TkParam, after),	nil,	"expand",	OPTstab,	O(TkParam, expand),	tkbool,	nil}; voidtkdelpack(Tk *t){	Tk *f, **l, *sub, *p; 	sub = tkfindsub(t);	if(sub != nil) {		p = sub->parent;		if(tkmethod[p->type]->forgetsub != nil)			tkmethod[p->type]->forgetsub(sub, t);	} 	if(t->master == nil)		return; 	if(t->master->grid != nil)		tkgriddelslave(t); 	l = &t->master->slave;	for(f = *l; f; f = f->next) {		if(f == t) {			*l = t->next;			break;		}		l = &f->next;	}	t->master = nil;} voidtkappendpack(Tk *parent, Tk *tk, int where){	Tk *f, **l; 	tk->master = parent;	l = &parent->slave;	for(f = *l; f; f = f->next) {		if(where-- == 0)			break;		l = &f->next;	}	*l = tk;	tk->next = f; 	for( ; parent != nil; parent = parent->master)		if(parent->parent != nil){			tk->flag |= Tksubsub;			break;		}} static voidtkpackqrm(Tk *t){	Pack *f, **l; 	l = &packorder;	for(f = *l; f; f = f->next) {		if(f->t == t) {			*l = f->next;			free(f);			break;		}		l = &f->next;	}} /* XXX - Tad: leaky... should propagate  */voidtkpackqit(Tk *t){	Pack *f; 	if(t == nil || (t->flag & Tkdestroy))		return; 	tkpackqrm(t);	f = malloc(sizeof(Pack));	if(f == nil) {		print("tkpackqit: malloc failed\n");		return;	} 	f->t = t;	f->next = packorder;	packorder = f;} voidtkrunpack(TkTop *t){	Tk *tk;	int done; 	while(packorder != nil) {		tk = packorder->t;		if (tk->grid != nil)			done = tkgridder(tk);		else			done = tkpacker(tk);		if (done)			tkpackqrm(tk);	}	tkenterleave(t);	tkdirtyfocusorder(t);} static voidtksetopt(TkParam *p, Tk *tk){	if(p->pad.x != -1)		tk->pad.x = p->pad.x*2;	if(p->pad.y != -1)		tk->pad.y = p->pad.y*2;	if(p->ipad.x != -1)		tk->ipad.x = p->ipad.x*2;	if(p->ipad.y != -1)		tk->ipad.y = p->ipad.y*2;	if(p->side != -1) {		tk->flag &= ~Tkside;		tk->flag |= p->side;	}	if(p->anchor != -1) {		tk->flag &= ~Tkanchor;		tk->flag |= p->anchor;	}	if(p->fill != -1) {		tk->flag &= ~Tkfill;		tk->flag |= p->fill;	}	if(p->expand != BoolX) {		if(p->expand == BoolT) {			tk->flag |= Tkexpand;		}		else			tk->flag &= ~Tkexpand;	}} static char*tkforget(TkTop *t, char *arg){	Tk *tk;	char *buf; 	buf = mallocz(Tkmaxitem, 0);	if(buf == nil)		return TkNomem;	for(;;) {		arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);		if(buf[0] == '\0')			break;		tk = tklook(t, buf, 0);		if(tk == nil) {			tkrunpack(t);			tkerr(t, buf);			free(buf);			return TkBadwp;		}		tkpackqit(tk->master);		tkdelpack(tk);	}	free(buf);	tkrunpack(t);	return nil;} char*tkpropagate(TkTop *t, char *arg){	Tk *tk;	TkStab *s;	char *buf; 	buf = mallocz(Tkmaxitem, 0);	if(buf == nil)		return TkNomem;	arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);	tk = tklook(t, buf, 0);	if(tk == nil) {		tkerr(t, buf);		free(buf);		return TkBadwp;	} 	tkword(t, arg, buf, buf+Tkmaxitem, nil);	for(s = tkbool; s->val; s++) {		if(strcmp(s->val, buf) == 0) {			if(s->con == BoolT) {				tk->flag &= ~Tknoprop;				tkpackqit(tk);				tkrunpack(t);			} else				tk->flag |= Tknoprop;			free(buf);			return nil;		}	}	free(buf);	return TkBadvl;} static char*tkslaves(TkTop *t, char *arg, char **val){	Tk *tk;	char *fmt, *e, *buf; 	buf = mallocz(Tkmaxitem, 0);	if(buf == nil)		return TkNomem;	tkword(t, arg, buf, buf+Tkmaxitem, nil);	tk = tklook(t, buf, 0);	if(tk == nil){		tkerr(t, buf);		free(buf);		return TkBadwp;	}	free(buf); 	fmt = "%s";	for(tk = tk->slave; tk; tk = tk->next) {		if (tk->name != nil) {			e = tkvalue(val, fmt, tk->name->name);			if(e != nil)				return e;			fmt = " %s";		}	}		return nil;} inttkisslave(Tk *in, Tk *tk){	if(in == nil)		return 0;	if(in == tk)		return 1;	for(tk = tk->slave; tk; tk = tk->next)		if(tkisslave(in, tk))			return 1;	return 0;} static char*tkcanpack(Tk *tk, Tk *parent){	if(tkisslave(parent, tk))		return TkRecur;	if (parent->grid != nil) {		if (parent->slave != nil)			return TkIsgrid;		tkfreegrid(parent->grid);		parent->grid = nil;	}	return nil;} char*tkpack(TkTop *t, char *arg, char **val){	TkParam param = defparam;	TkParam *p = &param;	TkOptab tko[2];	Tk *tk, **l, *tkp;	TkName *names, *n;	char *e, *w, *buf; 	buf = mallocz(Tkminitem, 0);	if(buf == nil)		return TkNomem; 	w = tkword(t, arg, buf, buf+Tkminitem, nil);	if(strcmp(buf, "forget") == 0) {		e = tkforget(t, w);		free(buf);		return e;	}	if(strcmp(buf, "propagate") == 0) {		e = tkpropagate(t, w);		free(buf);		return e;	}	if(strcmp(buf, "slaves") == 0) {		e = tkslaves(t, w, val);		free(buf);		return e;	}	free(buf); 	tko[0].ptr = p;	tko[0].optab = opts;	tko[1].ptr = nil; 	names = nil;	e = tkparse(t, arg, tko, &names);	if(e != nil)		return e; 	if((p->before && p->before->master == nil) ||	   (p->after && p->after->master == nil)) {		tkfreename(names);		return TkNotpk;	} 	for(n = names; n; n = n->link) {		tkp = tklook(t, n->name, 0);		if(tkp == nil) {			tkerr(t, n->name);			tkfreename(names);			return TkBadwp;		}		if(tkp->flag & Tkwindow) {			tkfreename(names);			return TkIstop;		}		if(tkp->parent != nil) {			tkfreename(names);			return TkWpack;		}		n->obj = tkp;	} 	e = nil;	for(n = names; n; n = n->link) {		tk = n->obj;		if(tk->master == nil) {			tk->pad = ZP;			tk->ipad = ZP;			tk->flag &= ~(Tkanchor|Tkside|Tkfill|Tkexpand);			tk->flag |= Tktop;		}		if(tk->master != nil) {			tkpackqit(tk->master);			tkdelpack(tk);		}		if(p->before == nil && p->after == nil && p->in == nil) {			tkp = tklook(t, n->name, 1);			if(tkp == nil) {				e = TkBadwp;				tkerr(t, n->name);				goto Error;			}			e = tkcanpack(tk, tkp);			if (e != nil)				goto Error;			tkappendpack(tkp, tk, -1);		}		else {			if(p->in != nil) {				e = tkcanpack(tk, p->in);				if(e != nil)					goto Error;				tkappendpack(p->in, tk, -1);			}			else			if(p->before != nil) {				e = tkcanpack(tk, p->before->master);				if (e != nil)					goto Error;				tk->master = p->before->master;				l = &tk->master->slave;				for(;;) {					if(*l == p->before) {						tk->next = *l;						*l = tk;						break;					}					l = &(*l)->next;				}				p->before = tk;			}			else {				e = tkcanpack(tk, p->after->master);				if (e != nil)					goto Error;				tk->master = p->after->master;				tk->next = p->after->next;				p->after->next = tk;				p->after = tk;			}		}		tksetopt(p, tk);		if (tk->master->flag&Tksubsub)			tksetbits(tk, Tksubsub);		tkpackqit(tk->master);	} Error:	tkfreename(names);	tkrunpack(t); 	return e;} voidtksetslavereq(Tk *slave, TkGeom frame){	Point border;	TkGeom pos, old;	int slave2BW;	void (*geomfn)(Tk*); 	border.x = slave->pad.x;	border.y = slave->pad.y; 	slave2BW = slave->borderwidth * 2; 	pos.width = slave->req.width + slave2BW + slave->ipad.x;	if((slave->flag&Tkfillx) || (pos.width > (frame.width - border.x)))		pos.width = frame.width - border.x; 	pos.height = slave->req.height + slave2BW + slave->ipad.y;	if((slave->flag&Tkfilly) || (pos.height > (frame.height - border.y)))    		pos.height = frame.height - border.y; 	border.x /= 2;	border.y /= 2; 

Lines 1–500 of 696.