xref: /inferno-os/libtk/packr.c (revision 5849851a19380dbb62a47d9c4d868a81e42fa79b)
137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "tk.h"
437da2899SCharles.Forsyth 
537da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
637da2899SCharles.Forsyth 
737da2899SCharles.Forsyth typedef struct Pack Pack;
837da2899SCharles.Forsyth struct Pack
937da2899SCharles.Forsyth {
1037da2899SCharles.Forsyth 	Tk*	t;
1137da2899SCharles.Forsyth 	Pack*	next;
1237da2899SCharles.Forsyth };
1337da2899SCharles.Forsyth static Pack *packorder;
1437da2899SCharles.Forsyth 
1537da2899SCharles.Forsyth static int tkpacker(Tk *);
1637da2899SCharles.Forsyth 
1737da2899SCharles.Forsyth typedef struct TkParam TkParam;
1837da2899SCharles.Forsyth struct TkParam
1937da2899SCharles.Forsyth {
2037da2899SCharles.Forsyth 	Point	pad;
2137da2899SCharles.Forsyth 	Point	ipad;
2237da2899SCharles.Forsyth 	int	side;
2337da2899SCharles.Forsyth 	int	anchor;
2437da2899SCharles.Forsyth 	int	fill;
2537da2899SCharles.Forsyth 	Tk*	in;
2637da2899SCharles.Forsyth 	Tk*	before;
2737da2899SCharles.Forsyth 	Tk*	after;
2837da2899SCharles.Forsyth 	int	expand;
2937da2899SCharles.Forsyth };
3037da2899SCharles.Forsyth 
3137da2899SCharles.Forsyth TkParam defparam = {
3237da2899SCharles.Forsyth 	{-1, -1},	/* p.pad */
3337da2899SCharles.Forsyth 	{-1, -1},	/* p.ipad */
3437da2899SCharles.Forsyth 	-1,		/* side */
3537da2899SCharles.Forsyth 	-1,		/* anchor */
3637da2899SCharles.Forsyth 	-1,		/* fill */
3737da2899SCharles.Forsyth 	nil,		/* in */
3837da2899SCharles.Forsyth 	nil, 		/* before */
3937da2899SCharles.Forsyth 	nil,		/* after */
4037da2899SCharles.Forsyth 	BoolX	/* expand */
4137da2899SCharles.Forsyth };
4237da2899SCharles.Forsyth 
4337da2899SCharles.Forsyth static
4437da2899SCharles.Forsyth TkStab tkside[] =
4537da2899SCharles.Forsyth {
4637da2899SCharles.Forsyth 	"top",		Tktop,
4737da2899SCharles.Forsyth 	"bottom",	Tkbottom,
4837da2899SCharles.Forsyth 	"left",		Tkleft,
4937da2899SCharles.Forsyth 	"right",	Tkright,
5037da2899SCharles.Forsyth 	nil
5137da2899SCharles.Forsyth };
5237da2899SCharles.Forsyth 
5337da2899SCharles.Forsyth static
5437da2899SCharles.Forsyth TkStab tkfill[] =
5537da2899SCharles.Forsyth {
5637da2899SCharles.Forsyth 	"none",		0,
5737da2899SCharles.Forsyth 	"x",		Tkfillx,
5837da2899SCharles.Forsyth 	"y",		Tkfilly,
5937da2899SCharles.Forsyth 	"both",		Tkfillx|Tkfilly,
6037da2899SCharles.Forsyth 	nil
6137da2899SCharles.Forsyth };
6237da2899SCharles.Forsyth 
6337da2899SCharles.Forsyth static
6437da2899SCharles.Forsyth TkOption opts[] =
6537da2899SCharles.Forsyth {
6637da2899SCharles.Forsyth 	"padx",		OPTnndist,	O(TkParam, pad.x),	nil,
6737da2899SCharles.Forsyth 	"pady",		OPTnndist,	O(TkParam, pad.y),	nil,
6837da2899SCharles.Forsyth 	"ipadx",	OPTnndist,	O(TkParam, ipad.x),	nil,
6937da2899SCharles.Forsyth 	"ipady",	OPTnndist,	O(TkParam, ipad.y),	nil,
7037da2899SCharles.Forsyth 	"side",		OPTstab,	O(TkParam, side),	tkside,
7137da2899SCharles.Forsyth 	"anchor",	OPTstab,	O(TkParam, anchor),	tkanchor,
7237da2899SCharles.Forsyth 	"fill",		OPTstab,	O(TkParam, fill),	tkfill,
7337da2899SCharles.Forsyth 	"in",		OPTwinp,	O(TkParam, in),		nil,
7437da2899SCharles.Forsyth 	"before",	OPTwinp,	O(TkParam, before),	nil,
7537da2899SCharles.Forsyth 	"after",	OPTwinp,	O(TkParam, after),	nil,
7637da2899SCharles.Forsyth 	"expand",	OPTstab,	O(TkParam, expand),	tkbool,
7737da2899SCharles.Forsyth 	nil
7837da2899SCharles.Forsyth };
7937da2899SCharles.Forsyth 
8037da2899SCharles.Forsyth void
tkdelpack(Tk * t)8137da2899SCharles.Forsyth tkdelpack(Tk *t)
8237da2899SCharles.Forsyth {
83*5849851aSforsyth 	Tk *f, **l, *sub, *p;
84*5849851aSforsyth 
85*5849851aSforsyth 	sub = tkfindsub(t);
86*5849851aSforsyth 	if(sub != nil) {
87*5849851aSforsyth 		p = sub->parent;
88*5849851aSforsyth 		if(tkmethod[p->type]->forgetsub != nil)
89*5849851aSforsyth 			tkmethod[p->type]->forgetsub(sub, t);
90*5849851aSforsyth 	}
9137da2899SCharles.Forsyth 
9237da2899SCharles.Forsyth 	if(t->master == nil)
9337da2899SCharles.Forsyth 		return;
9437da2899SCharles.Forsyth 
9537da2899SCharles.Forsyth 	if(t->master->grid != nil)
9637da2899SCharles.Forsyth 		tkgriddelslave(t);
9737da2899SCharles.Forsyth 
9837da2899SCharles.Forsyth 	l = &t->master->slave;
9937da2899SCharles.Forsyth 	for(f = *l; f; f = f->next) {
10037da2899SCharles.Forsyth 		if(f == t) {
10137da2899SCharles.Forsyth 			*l = t->next;
10237da2899SCharles.Forsyth 			break;
10337da2899SCharles.Forsyth 		}
10437da2899SCharles.Forsyth 		l = &f->next;
10537da2899SCharles.Forsyth 	}
10637da2899SCharles.Forsyth 	t->master = nil;
10737da2899SCharles.Forsyth }
10837da2899SCharles.Forsyth 
10937da2899SCharles.Forsyth void
tkappendpack(Tk * parent,Tk * tk,int where)11037da2899SCharles.Forsyth tkappendpack(Tk *parent, Tk *tk, int where)
11137da2899SCharles.Forsyth {
11237da2899SCharles.Forsyth 	Tk *f, **l;
11337da2899SCharles.Forsyth 
11437da2899SCharles.Forsyth 	tk->master = parent;
11537da2899SCharles.Forsyth 	l = &parent->slave;
11637da2899SCharles.Forsyth 	for(f = *l; f; f = f->next) {
11737da2899SCharles.Forsyth 		if(where-- == 0)
11837da2899SCharles.Forsyth 			break;
11937da2899SCharles.Forsyth 		l = &f->next;
12037da2899SCharles.Forsyth 	}
12137da2899SCharles.Forsyth 	*l = tk;
12237da2899SCharles.Forsyth 	tk->next = f;
12337da2899SCharles.Forsyth 
12437da2899SCharles.Forsyth 	for( ; parent != nil; parent = parent->master)
12537da2899SCharles.Forsyth 		if(parent->parent != nil){
12637da2899SCharles.Forsyth 			tk->flag |= Tksubsub;
12737da2899SCharles.Forsyth 			break;
12837da2899SCharles.Forsyth 		}
12937da2899SCharles.Forsyth }
13037da2899SCharles.Forsyth 
13137da2899SCharles.Forsyth static void
tkpackqrm(Tk * t)13237da2899SCharles.Forsyth tkpackqrm(Tk *t)
13337da2899SCharles.Forsyth {
13437da2899SCharles.Forsyth 	Pack *f, **l;
13537da2899SCharles.Forsyth 
13637da2899SCharles.Forsyth 	l = &packorder;
13737da2899SCharles.Forsyth 	for(f = *l; f; f = f->next) {
13837da2899SCharles.Forsyth 		if(f->t == t) {
13937da2899SCharles.Forsyth 			*l = f->next;
14037da2899SCharles.Forsyth 			free(f);
14137da2899SCharles.Forsyth 			break;
14237da2899SCharles.Forsyth 		}
14337da2899SCharles.Forsyth 		l = &f->next;
14437da2899SCharles.Forsyth 	}
14537da2899SCharles.Forsyth }
14637da2899SCharles.Forsyth 
14737da2899SCharles.Forsyth /* XXX - Tad: leaky... should propagate  */
14837da2899SCharles.Forsyth void
tkpackqit(Tk * t)14937da2899SCharles.Forsyth tkpackqit(Tk *t)
15037da2899SCharles.Forsyth {
15137da2899SCharles.Forsyth 	Pack *f;
15237da2899SCharles.Forsyth 
15337da2899SCharles.Forsyth 	if(t == nil || (t->flag & Tkdestroy))
15437da2899SCharles.Forsyth 		return;
15537da2899SCharles.Forsyth 
15637da2899SCharles.Forsyth 	tkpackqrm(t);
15737da2899SCharles.Forsyth 	f = malloc(sizeof(Pack));
15837da2899SCharles.Forsyth 	if(f == nil) {
15937da2899SCharles.Forsyth 		print("tkpackqit: malloc failed\n");
16037da2899SCharles.Forsyth 		return;
16137da2899SCharles.Forsyth 	}
16237da2899SCharles.Forsyth 
16337da2899SCharles.Forsyth 	f->t = t;
16437da2899SCharles.Forsyth 	f->next = packorder;
16537da2899SCharles.Forsyth 	packorder = f;
16637da2899SCharles.Forsyth }
16737da2899SCharles.Forsyth 
16837da2899SCharles.Forsyth void
tkrunpack(TkTop * t)16937da2899SCharles.Forsyth tkrunpack(TkTop *t)
17037da2899SCharles.Forsyth {
17137da2899SCharles.Forsyth 	Tk *tk;
17237da2899SCharles.Forsyth 	int done;
17337da2899SCharles.Forsyth 
17437da2899SCharles.Forsyth 	while(packorder != nil) {
17537da2899SCharles.Forsyth 		tk = packorder->t;
17637da2899SCharles.Forsyth 		if (tk->grid != nil)
17737da2899SCharles.Forsyth 			done = tkgridder(tk);
17837da2899SCharles.Forsyth 		else
17937da2899SCharles.Forsyth 			done = tkpacker(tk);
18037da2899SCharles.Forsyth 		if (done)
18137da2899SCharles.Forsyth 			tkpackqrm(tk);
18237da2899SCharles.Forsyth 	}
18337da2899SCharles.Forsyth 	tkenterleave(t);
18437da2899SCharles.Forsyth 	tkdirtyfocusorder(t);
18537da2899SCharles.Forsyth }
18637da2899SCharles.Forsyth 
18737da2899SCharles.Forsyth static void
tksetopt(TkParam * p,Tk * tk)18837da2899SCharles.Forsyth tksetopt(TkParam *p, Tk *tk)
18937da2899SCharles.Forsyth {
19037da2899SCharles.Forsyth 	if(p->pad.x != -1)
19137da2899SCharles.Forsyth 		tk->pad.x = p->pad.x*2;
19237da2899SCharles.Forsyth 	if(p->pad.y != -1)
19337da2899SCharles.Forsyth 		tk->pad.y = p->pad.y*2;
19437da2899SCharles.Forsyth 	if(p->ipad.x != -1)
19537da2899SCharles.Forsyth 		tk->ipad.x = p->ipad.x*2;
19637da2899SCharles.Forsyth 	if(p->ipad.y != -1)
19737da2899SCharles.Forsyth 		tk->ipad.y = p->ipad.y*2;
19837da2899SCharles.Forsyth 	if(p->side != -1) {
19937da2899SCharles.Forsyth 		tk->flag &= ~Tkside;
20037da2899SCharles.Forsyth 		tk->flag |= p->side;
20137da2899SCharles.Forsyth 	}
20237da2899SCharles.Forsyth 	if(p->anchor != -1) {
20337da2899SCharles.Forsyth 		tk->flag &= ~Tkanchor;
20437da2899SCharles.Forsyth 		tk->flag |= p->anchor;
20537da2899SCharles.Forsyth 	}
20637da2899SCharles.Forsyth 	if(p->fill != -1) {
20737da2899SCharles.Forsyth 		tk->flag &= ~Tkfill;
20837da2899SCharles.Forsyth 		tk->flag |= p->fill;
20937da2899SCharles.Forsyth 	}
21037da2899SCharles.Forsyth 	if(p->expand != BoolX) {
21137da2899SCharles.Forsyth 		if(p->expand == BoolT) {
21237da2899SCharles.Forsyth 			tk->flag |= Tkexpand;
21337da2899SCharles.Forsyth 		}
21437da2899SCharles.Forsyth 		else
21537da2899SCharles.Forsyth 			tk->flag &= ~Tkexpand;
21637da2899SCharles.Forsyth 	}
21737da2899SCharles.Forsyth }
21837da2899SCharles.Forsyth 
21937da2899SCharles.Forsyth static char*
tkforget(TkTop * t,char * arg)22037da2899SCharles.Forsyth tkforget(TkTop *t, char *arg)
22137da2899SCharles.Forsyth {
22237da2899SCharles.Forsyth 	Tk *tk;
22337da2899SCharles.Forsyth 	char *buf;
22437da2899SCharles.Forsyth 
22537da2899SCharles.Forsyth 	buf = mallocz(Tkmaxitem, 0);
22637da2899SCharles.Forsyth 	if(buf == nil)
22737da2899SCharles.Forsyth 		return TkNomem;
22837da2899SCharles.Forsyth 	for(;;) {
22937da2899SCharles.Forsyth 		arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
23037da2899SCharles.Forsyth 		if(buf[0] == '\0')
23137da2899SCharles.Forsyth 			break;
23237da2899SCharles.Forsyth 		tk = tklook(t, buf, 0);
23337da2899SCharles.Forsyth 		if(tk == nil) {
23437da2899SCharles.Forsyth 			tkrunpack(t);
23537da2899SCharles.Forsyth 			tkerr(t, buf);
23637da2899SCharles.Forsyth 			free(buf);
23737da2899SCharles.Forsyth 			return TkBadwp;
23837da2899SCharles.Forsyth 		}
23937da2899SCharles.Forsyth 		tkpackqit(tk->master);
24037da2899SCharles.Forsyth 		tkdelpack(tk);
24137da2899SCharles.Forsyth 	}
24237da2899SCharles.Forsyth 	free(buf);
24337da2899SCharles.Forsyth 	tkrunpack(t);
24437da2899SCharles.Forsyth 	return nil;
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth 
24737da2899SCharles.Forsyth char*
tkpropagate(TkTop * t,char * arg)24837da2899SCharles.Forsyth tkpropagate(TkTop *t, char *arg)
24937da2899SCharles.Forsyth {
25037da2899SCharles.Forsyth 	Tk *tk;
25137da2899SCharles.Forsyth 	TkStab *s;
25237da2899SCharles.Forsyth 	char *buf;
25337da2899SCharles.Forsyth 
25437da2899SCharles.Forsyth 	buf = mallocz(Tkmaxitem, 0);
25537da2899SCharles.Forsyth 	if(buf == nil)
25637da2899SCharles.Forsyth 		return TkNomem;
25737da2899SCharles.Forsyth 	arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
25837da2899SCharles.Forsyth 	tk = tklook(t, buf, 0);
25937da2899SCharles.Forsyth 	if(tk == nil) {
26037da2899SCharles.Forsyth 		tkerr(t, buf);
26137da2899SCharles.Forsyth 		free(buf);
26237da2899SCharles.Forsyth 		return TkBadwp;
26337da2899SCharles.Forsyth 	}
26437da2899SCharles.Forsyth 
26537da2899SCharles.Forsyth 	tkword(t, arg, buf, buf+Tkmaxitem, nil);
26637da2899SCharles.Forsyth 	for(s = tkbool; s->val; s++) {
26737da2899SCharles.Forsyth 		if(strcmp(s->val, buf) == 0) {
26837da2899SCharles.Forsyth 			if(s->con == BoolT) {
26937da2899SCharles.Forsyth 				tk->flag &= ~Tknoprop;
27037da2899SCharles.Forsyth 				tkpackqit(tk);
27137da2899SCharles.Forsyth 				tkrunpack(t);
27237da2899SCharles.Forsyth 			} else
27337da2899SCharles.Forsyth 				tk->flag |= Tknoprop;
27437da2899SCharles.Forsyth 			free(buf);
27537da2899SCharles.Forsyth 			return nil;
27637da2899SCharles.Forsyth 		}
27737da2899SCharles.Forsyth 	}
27837da2899SCharles.Forsyth 	free(buf);
27937da2899SCharles.Forsyth 	return TkBadvl;
28037da2899SCharles.Forsyth }
28137da2899SCharles.Forsyth 
28237da2899SCharles.Forsyth static char*
tkslaves(TkTop * t,char * arg,char ** val)28337da2899SCharles.Forsyth tkslaves(TkTop *t, char *arg, char **val)
28437da2899SCharles.Forsyth {
28537da2899SCharles.Forsyth 	Tk *tk;
28637da2899SCharles.Forsyth 	char *fmt, *e, *buf;
28737da2899SCharles.Forsyth 
28837da2899SCharles.Forsyth 	buf = mallocz(Tkmaxitem, 0);
28937da2899SCharles.Forsyth 	if(buf == nil)
29037da2899SCharles.Forsyth 		return TkNomem;
29137da2899SCharles.Forsyth 	tkword(t, arg, buf, buf+Tkmaxitem, nil);
29237da2899SCharles.Forsyth 	tk = tklook(t, buf, 0);
29337da2899SCharles.Forsyth 	if(tk == nil){
29437da2899SCharles.Forsyth 		tkerr(t, buf);
29537da2899SCharles.Forsyth 		free(buf);
29637da2899SCharles.Forsyth 		return TkBadwp;
29737da2899SCharles.Forsyth 	}
29837da2899SCharles.Forsyth 	free(buf);
29937da2899SCharles.Forsyth 
30037da2899SCharles.Forsyth 	fmt = "%s";
30137da2899SCharles.Forsyth 	for(tk = tk->slave; tk; tk = tk->next) {
30237da2899SCharles.Forsyth 		if (tk->name != nil) {
30337da2899SCharles.Forsyth 			e = tkvalue(val, fmt, tk->name->name);
30437da2899SCharles.Forsyth 			if(e != nil)
30537da2899SCharles.Forsyth 				return e;
30637da2899SCharles.Forsyth 			fmt = " %s";
30737da2899SCharles.Forsyth 		}
30837da2899SCharles.Forsyth 	}
30937da2899SCharles.Forsyth 
31037da2899SCharles.Forsyth 	return nil;
31137da2899SCharles.Forsyth }
31237da2899SCharles.Forsyth 
31337da2899SCharles.Forsyth int
tkisslave(Tk * in,Tk * tk)31437da2899SCharles.Forsyth tkisslave(Tk *in, Tk *tk)
31537da2899SCharles.Forsyth {
31637da2899SCharles.Forsyth 	if(in == nil)
31737da2899SCharles.Forsyth 		return 0;
31837da2899SCharles.Forsyth 	if(in == tk)
31937da2899SCharles.Forsyth 		return 1;
32037da2899SCharles.Forsyth 	for(tk = tk->slave; tk; tk = tk->next)
32137da2899SCharles.Forsyth 		if(tkisslave(in, tk))
32237da2899SCharles.Forsyth 			return 1;
32337da2899SCharles.Forsyth 	return 0;
32437da2899SCharles.Forsyth }
32537da2899SCharles.Forsyth 
32637da2899SCharles.Forsyth static char*
tkcanpack(Tk * tk,Tk * parent)32737da2899SCharles.Forsyth tkcanpack(Tk *tk, Tk *parent)
32837da2899SCharles.Forsyth {
32937da2899SCharles.Forsyth 	if(tkisslave(parent, tk))
33037da2899SCharles.Forsyth 		return TkRecur;
33137da2899SCharles.Forsyth 	if (parent->grid != nil) {
33237da2899SCharles.Forsyth 		if (parent->slave != nil)
33337da2899SCharles.Forsyth 			return TkIsgrid;
33437da2899SCharles.Forsyth 		tkfreegrid(parent->grid);
33537da2899SCharles.Forsyth 		parent->grid = nil;
33637da2899SCharles.Forsyth 	}
33737da2899SCharles.Forsyth 	return nil;
33837da2899SCharles.Forsyth }
33937da2899SCharles.Forsyth 
34037da2899SCharles.Forsyth char*
tkpack(TkTop * t,char * arg,char ** val)34137da2899SCharles.Forsyth tkpack(TkTop *t, char *arg, char **val)
34237da2899SCharles.Forsyth {
34337da2899SCharles.Forsyth 	TkParam param = defparam;
34437da2899SCharles.Forsyth 	TkParam *p = &param;
34537da2899SCharles.Forsyth 	TkOptab tko[2];
34637da2899SCharles.Forsyth 	Tk *tk, **l, *tkp;
34737da2899SCharles.Forsyth 	TkName *names, *n;
34837da2899SCharles.Forsyth 	char *e, *w, *buf;
34937da2899SCharles.Forsyth 
35037da2899SCharles.Forsyth 	buf = mallocz(Tkminitem, 0);
35137da2899SCharles.Forsyth 	if(buf == nil)
35237da2899SCharles.Forsyth 		return TkNomem;
35337da2899SCharles.Forsyth 
35437da2899SCharles.Forsyth 	w = tkword(t, arg, buf, buf+Tkminitem, nil);
35537da2899SCharles.Forsyth 	if(strcmp(buf, "forget") == 0) {
35637da2899SCharles.Forsyth 		e = tkforget(t, w);
35737da2899SCharles.Forsyth 		free(buf);
35837da2899SCharles.Forsyth 		return e;
35937da2899SCharles.Forsyth 	}
36037da2899SCharles.Forsyth 	if(strcmp(buf, "propagate") == 0) {
36137da2899SCharles.Forsyth 		e = tkpropagate(t, w);
36237da2899SCharles.Forsyth 		free(buf);
36337da2899SCharles.Forsyth 		return e;
36437da2899SCharles.Forsyth 	}
36537da2899SCharles.Forsyth 	if(strcmp(buf, "slaves") == 0) {
36637da2899SCharles.Forsyth 		e = tkslaves(t, w, val);
36737da2899SCharles.Forsyth 		free(buf);
36837da2899SCharles.Forsyth 		return e;
36937da2899SCharles.Forsyth 	}
37037da2899SCharles.Forsyth 	free(buf);
37137da2899SCharles.Forsyth 
37237da2899SCharles.Forsyth 	tko[0].ptr = p;
37337da2899SCharles.Forsyth 	tko[0].optab = opts;
37437da2899SCharles.Forsyth 	tko[1].ptr = nil;
37537da2899SCharles.Forsyth 
37637da2899SCharles.Forsyth 	names = nil;
37737da2899SCharles.Forsyth 	e = tkparse(t, arg, tko, &names);
37837da2899SCharles.Forsyth 	if(e != nil)
37937da2899SCharles.Forsyth 		return e;
38037da2899SCharles.Forsyth 
38137da2899SCharles.Forsyth 	if((p->before && p->before->master == nil) ||
38237da2899SCharles.Forsyth 	   (p->after && p->after->master == nil)) {
38337da2899SCharles.Forsyth 		tkfreename(names);
38437da2899SCharles.Forsyth 		return TkNotpk;
38537da2899SCharles.Forsyth 	}
38637da2899SCharles.Forsyth 
38737da2899SCharles.Forsyth 	for(n = names; n; n = n->link) {
38837da2899SCharles.Forsyth 		tkp = tklook(t, n->name, 0);
38937da2899SCharles.Forsyth 		if(tkp == nil) {
39037da2899SCharles.Forsyth 			tkerr(t, n->name);
39137da2899SCharles.Forsyth 			tkfreename(names);
39237da2899SCharles.Forsyth 			return TkBadwp;
39337da2899SCharles.Forsyth 		}
39437da2899SCharles.Forsyth 		if(tkp->flag & Tkwindow) {
39537da2899SCharles.Forsyth 			tkfreename(names);
39637da2899SCharles.Forsyth 			return TkIstop;
39737da2899SCharles.Forsyth 		}
39837da2899SCharles.Forsyth 		if(tkp->parent != nil) {
39937da2899SCharles.Forsyth 			tkfreename(names);
40037da2899SCharles.Forsyth 			return TkWpack;
40137da2899SCharles.Forsyth 		}
40237da2899SCharles.Forsyth 		n->obj = tkp;
40337da2899SCharles.Forsyth 	}
40437da2899SCharles.Forsyth 
40537da2899SCharles.Forsyth 	e = nil;
40637da2899SCharles.Forsyth 	for(n = names; n; n = n->link) {
40737da2899SCharles.Forsyth 		tk = n->obj;
40837da2899SCharles.Forsyth 		if(tk->master == nil) {
40937da2899SCharles.Forsyth 			tk->pad = ZP;
41037da2899SCharles.Forsyth 			tk->ipad = ZP;
41137da2899SCharles.Forsyth 			tk->flag &= ~(Tkanchor|Tkside|Tkfill|Tkexpand);
41237da2899SCharles.Forsyth 			tk->flag |= Tktop;
41337da2899SCharles.Forsyth 		}
41437da2899SCharles.Forsyth 		if(tk->master != nil) {
41537da2899SCharles.Forsyth 			tkpackqit(tk->master);
41637da2899SCharles.Forsyth 			tkdelpack(tk);
41737da2899SCharles.Forsyth 		}
41837da2899SCharles.Forsyth 		if(p->before == nil && p->after == nil && p->in == nil) {
41937da2899SCharles.Forsyth 			tkp = tklook(t, n->name, 1);
42037da2899SCharles.Forsyth 			if(tkp == nil) {
42137da2899SCharles.Forsyth 				e = TkBadwp;
42237da2899SCharles.Forsyth 				tkerr(t, n->name);
42337da2899SCharles.Forsyth 				goto Error;
42437da2899SCharles.Forsyth 			}
42537da2899SCharles.Forsyth 			e = tkcanpack(tk, tkp);
42637da2899SCharles.Forsyth 			if (e != nil)
42737da2899SCharles.Forsyth 				goto Error;
42837da2899SCharles.Forsyth 			tkappendpack(tkp, tk, -1);
42937da2899SCharles.Forsyth 		}
43037da2899SCharles.Forsyth 		else {
43137da2899SCharles.Forsyth 			if(p->in != nil) {
43237da2899SCharles.Forsyth 				e = tkcanpack(tk, p->in);
43337da2899SCharles.Forsyth 				if(e != nil)
43437da2899SCharles.Forsyth 					goto Error;
43537da2899SCharles.Forsyth 				tkappendpack(p->in, tk, -1);
43637da2899SCharles.Forsyth 			}
43737da2899SCharles.Forsyth 			else
43837da2899SCharles.Forsyth 			if(p->before != nil) {
43937da2899SCharles.Forsyth 				e = tkcanpack(tk, p->before->master);
44037da2899SCharles.Forsyth 				if (e != nil)
44137da2899SCharles.Forsyth 					goto Error;
44237da2899SCharles.Forsyth 				tk->master = p->before->master;
44337da2899SCharles.Forsyth 				l = &tk->master->slave;
44437da2899SCharles.Forsyth 				for(;;) {
44537da2899SCharles.Forsyth 					if(*l == p->before) {
44637da2899SCharles.Forsyth 						tk->next = *l;
44737da2899SCharles.Forsyth 						*l = tk;
44837da2899SCharles.Forsyth 						break;
44937da2899SCharles.Forsyth 					}
45037da2899SCharles.Forsyth 					l = &(*l)->next;
45137da2899SCharles.Forsyth 				}
45237da2899SCharles.Forsyth 				p->before = tk;
45337da2899SCharles.Forsyth 			}
45437da2899SCharles.Forsyth 			else {
45537da2899SCharles.Forsyth 				e = tkcanpack(tk, p->after->master);
45637da2899SCharles.Forsyth 				if (e != nil)
45737da2899SCharles.Forsyth 					goto Error;
45837da2899SCharles.Forsyth 				tk->master = p->after->master;
45937da2899SCharles.Forsyth 				tk->next = p->after->next;
46037da2899SCharles.Forsyth 				p->after->next = tk;
46137da2899SCharles.Forsyth 				p->after = tk;
46237da2899SCharles.Forsyth 			}
46337da2899SCharles.Forsyth 		}
46437da2899SCharles.Forsyth 		tksetopt(p, tk);
46537da2899SCharles.Forsyth 		if (tk->master->flag&Tksubsub)
46637da2899SCharles.Forsyth 			tksetbits(tk, Tksubsub);
46737da2899SCharles.Forsyth 		tkpackqit(tk->master);
46837da2899SCharles.Forsyth 	}
46937da2899SCharles.Forsyth 
47037da2899SCharles.Forsyth Error:
47137da2899SCharles.Forsyth 	tkfreename(names);
47237da2899SCharles.Forsyth 	tkrunpack(t);
47337da2899SCharles.Forsyth 
47437da2899SCharles.Forsyth 	return e;
47537da2899SCharles.Forsyth }
47637da2899SCharles.Forsyth 
47737da2899SCharles.Forsyth void
tksetslavereq(Tk * slave,TkGeom frame)47837da2899SCharles.Forsyth tksetslavereq(Tk *slave, TkGeom frame)
47937da2899SCharles.Forsyth {
48037da2899SCharles.Forsyth 	Point border;
48137da2899SCharles.Forsyth 	TkGeom pos, old;
48237da2899SCharles.Forsyth 	int slave2BW;
48337da2899SCharles.Forsyth 	void (*geomfn)(Tk*);
48437da2899SCharles.Forsyth 
48537da2899SCharles.Forsyth 	border.x = slave->pad.x;
48637da2899SCharles.Forsyth 	border.y = slave->pad.y;
48737da2899SCharles.Forsyth 
48837da2899SCharles.Forsyth 	slave2BW = slave->borderwidth * 2;
48937da2899SCharles.Forsyth 
49037da2899SCharles.Forsyth 	pos.width = slave->req.width + slave2BW + slave->ipad.x;
49137da2899SCharles.Forsyth 	if((slave->flag&Tkfillx) || (pos.width > (frame.width - border.x)))
49237da2899SCharles.Forsyth 		pos.width = frame.width - border.x;
49337da2899SCharles.Forsyth 
49437da2899SCharles.Forsyth 	pos.height = slave->req.height + slave2BW + slave->ipad.y;
49537da2899SCharles.Forsyth 	if((slave->flag&Tkfilly) || (pos.height > (frame.height - border.y)))
49637da2899SCharles.Forsyth     		pos.height = frame.height - border.y;
49737da2899SCharles.Forsyth 
49837da2899SCharles.Forsyth 	border.x /= 2;
49937da2899SCharles.Forsyth 	border.y /= 2;
50037da2899SCharles.Forsyth 
50137da2899SCharles.Forsyth 	if(slave->flag & Tknorth)
50237da2899SCharles.Forsyth 		pos.y = frame.y + border.y;
50337da2899SCharles.Forsyth 	else
50437da2899SCharles.Forsyth 	if(slave->flag & Tksouth)
50537da2899SCharles.Forsyth 		pos.y = frame.y + frame.height - pos.height - border.y;
50637da2899SCharles.Forsyth 	else
50737da2899SCharles.Forsyth 		pos.y = frame.y + (frame.height - pos.height)/2;
50837da2899SCharles.Forsyth 
50937da2899SCharles.Forsyth 	if(slave->flag & Tkwest)
51037da2899SCharles.Forsyth 		pos.x = frame.x + border.x;
51137da2899SCharles.Forsyth 	else
51237da2899SCharles.Forsyth 	if(slave->flag & Tkeast)
51337da2899SCharles.Forsyth 		pos.x = frame.x + frame.width - pos.width - border.x;
51437da2899SCharles.Forsyth 	else
51537da2899SCharles.Forsyth 		pos.x = frame.x + (frame.width - pos.width)/2;
51637da2899SCharles.Forsyth 
51737da2899SCharles.Forsyth 	pos.width -= slave2BW;
51837da2899SCharles.Forsyth 	pos.height -= slave2BW;
51937da2899SCharles.Forsyth 
52037da2899SCharles.Forsyth 	if(memcmp(&slave->act, &pos, sizeof(TkGeom)) != 0) {
52137da2899SCharles.Forsyth 		old = slave->act;
52237da2899SCharles.Forsyth 		slave->act = pos;
52337da2899SCharles.Forsyth 		geomfn = tkmethod[slave->type]->geom;
52437da2899SCharles.Forsyth 		if(geomfn != nil)
52537da2899SCharles.Forsyth 			geomfn(slave);
52637da2899SCharles.Forsyth 		if(slave->slave)
52737da2899SCharles.Forsyth 			tkpackqit(slave);
52837da2899SCharles.Forsyth 		tkdeliver(slave, TkConfigure, &old);
52937da2899SCharles.Forsyth 
53037da2899SCharles.Forsyth 		slave->dirty = tkrect(slave, 1);
53137da2899SCharles.Forsyth 		slave->flag |= Tkrefresh;
53237da2899SCharles.Forsyth 	}
53337da2899SCharles.Forsyth }
53437da2899SCharles.Forsyth static int
tkexpandx(Tk * slave,int cavityWidth)53537da2899SCharles.Forsyth tkexpandx(Tk* slave, int cavityWidth)
53637da2899SCharles.Forsyth {
53737da2899SCharles.Forsyth 	int numExpand, minExpand, curExpand, childWidth;
53837da2899SCharles.Forsyth 
53937da2899SCharles.Forsyth 	minExpand = cavityWidth;
54037da2899SCharles.Forsyth 	numExpand = 0;
54137da2899SCharles.Forsyth 	for( ;slave != nil; slave = slave->next) {
54237da2899SCharles.Forsyth 		childWidth = slave->req.width + slave->borderwidth*2 +
54337da2899SCharles.Forsyth 				slave->pad.x + slave->ipad.x;
54437da2899SCharles.Forsyth 		if(slave->flag & (Tktop|Tkbottom)) {
54537da2899SCharles.Forsyth 			curExpand = (cavityWidth - childWidth)/numExpand;
54637da2899SCharles.Forsyth 			if (curExpand < minExpand)
54737da2899SCharles.Forsyth 				minExpand = curExpand;
54837da2899SCharles.Forsyth 		}
54937da2899SCharles.Forsyth 		else {
55037da2899SCharles.Forsyth 	    		cavityWidth -= childWidth;
55137da2899SCharles.Forsyth 	    		if(slave->flag & Tkexpand)
55237da2899SCharles.Forsyth 				numExpand++;
55337da2899SCharles.Forsyth 		}
55437da2899SCharles.Forsyth 	}
55537da2899SCharles.Forsyth 	curExpand = cavityWidth/numExpand;
55637da2899SCharles.Forsyth 	if(curExpand < minExpand)
55737da2899SCharles.Forsyth 		minExpand = curExpand;
55837da2899SCharles.Forsyth 
55937da2899SCharles.Forsyth 	return (minExpand < 0) ? 0 : minExpand;
56037da2899SCharles.Forsyth }
56137da2899SCharles.Forsyth 
56237da2899SCharles.Forsyth static int
tkexpandy(Tk * slave,int cavityHeight)56337da2899SCharles.Forsyth tkexpandy(Tk *slave, int cavityHeight)
56437da2899SCharles.Forsyth {
56537da2899SCharles.Forsyth 	int numExpand, minExpand, curExpand, childHeight;
56637da2899SCharles.Forsyth 
56737da2899SCharles.Forsyth 	minExpand = cavityHeight;
56837da2899SCharles.Forsyth 	numExpand = 0;
56937da2899SCharles.Forsyth 	for ( ;slave != nil; slave = slave->next) {
57037da2899SCharles.Forsyth 		childHeight = slave->req.height + slave->borderwidth*2 +
57137da2899SCharles.Forsyth 			+ slave->pad.y + slave->ipad.y;
57237da2899SCharles.Forsyth 		if(slave->flag & (Tkleft|Tkright)) {
57337da2899SCharles.Forsyth 			curExpand = (cavityHeight - childHeight)/numExpand;
57437da2899SCharles.Forsyth 			if(curExpand < minExpand)
57537da2899SCharles.Forsyth 				minExpand = curExpand;
57637da2899SCharles.Forsyth 		}
57737da2899SCharles.Forsyth 		else {
57837da2899SCharles.Forsyth 			cavityHeight -= childHeight;
57937da2899SCharles.Forsyth 			if(slave->flag & Tkexpand)
58037da2899SCharles.Forsyth 				numExpand++;
58137da2899SCharles.Forsyth 		}
58237da2899SCharles.Forsyth 	}
58337da2899SCharles.Forsyth 	curExpand = cavityHeight/numExpand;
58437da2899SCharles.Forsyth 	if(curExpand < minExpand)
58537da2899SCharles.Forsyth 		minExpand = curExpand;
58637da2899SCharles.Forsyth 
58737da2899SCharles.Forsyth 	return (minExpand < 0) ? 0 : minExpand;
58837da2899SCharles.Forsyth }
58937da2899SCharles.Forsyth 
59037da2899SCharles.Forsyth static int
tkpacker(Tk * master)59137da2899SCharles.Forsyth tkpacker(Tk *master)
59237da2899SCharles.Forsyth {
59337da2899SCharles.Forsyth 	Tk *slave;
59437da2899SCharles.Forsyth 	TkGeom frame, cavity, pos;
59537da2899SCharles.Forsyth 	int maxwidth, maxheight, tmp, slave2BW;
59637da2899SCharles.Forsyth 
59737da2899SCharles.Forsyth 	pos.width = 0;
59837da2899SCharles.Forsyth 	pos.height = 0;
59937da2899SCharles.Forsyth 	maxwidth = 0;
60037da2899SCharles.Forsyth 	maxheight = 0;
60137da2899SCharles.Forsyth 
60237da2899SCharles.Forsyth 	master->flag |= Tkrefresh;
60337da2899SCharles.Forsyth 
60437da2899SCharles.Forsyth 	for (slave = master->slave; slave != nil; slave = slave->next) {
60537da2899SCharles.Forsyth 		slave2BW = slave->borderwidth*2;
60637da2899SCharles.Forsyth 		if(slave->flag & (Tktop|Tkbottom)) {
60737da2899SCharles.Forsyth 	    		tmp = slave->req.width + slave2BW +
60837da2899SCharles.Forsyth 		    		slave->pad.x + slave->ipad.x + pos.width;
60937da2899SCharles.Forsyth 			if(tmp > maxwidth)
61037da2899SCharles.Forsyth 				maxwidth = tmp;
61137da2899SCharles.Forsyth 	    		pos.height += slave->req.height + slave2BW +
61237da2899SCharles.Forsyth 		    		slave->pad.y + slave->ipad.y;
61337da2899SCharles.Forsyth 		}
61437da2899SCharles.Forsyth 		else {
61537da2899SCharles.Forsyth 	    		tmp = slave->req.height + slave2BW +
61637da2899SCharles.Forsyth 		    		slave->pad.y + slave->ipad.y + pos.height;
61737da2899SCharles.Forsyth 	    		if(tmp > maxheight)
61837da2899SCharles.Forsyth 				maxheight = tmp;
61937da2899SCharles.Forsyth 	    		pos.width += slave->req.width + slave2BW +
62037da2899SCharles.Forsyth 		    		+ slave->pad.x + slave->ipad.x;
62137da2899SCharles.Forsyth 		}
62237da2899SCharles.Forsyth 	}
62337da2899SCharles.Forsyth 	if(pos.width > maxwidth)
62437da2899SCharles.Forsyth 		maxwidth = pos.width;
62537da2899SCharles.Forsyth 	if(pos.height > maxheight)
62637da2899SCharles.Forsyth 		maxheight = pos.height;
62737da2899SCharles.Forsyth 
62837da2899SCharles.Forsyth 	if(maxwidth != master->req.width || maxheight != master->req.height)
62937da2899SCharles.Forsyth 	if((master->flag & Tknoprop) == 0) {
63037da2899SCharles.Forsyth 		if(master->geom != nil) {
63137da2899SCharles.Forsyth 			master->geom(master, master->act.x, master->act.y,
63237da2899SCharles.Forsyth 					maxwidth, maxheight);
63337da2899SCharles.Forsyth 		} else {
63437da2899SCharles.Forsyth 			master->req.width = maxwidth;
63537da2899SCharles.Forsyth 			master->req.height = maxheight;
63637da2899SCharles.Forsyth 			tkpackqit(master->master);
63737da2899SCharles.Forsyth 		}
63837da2899SCharles.Forsyth 		return 0;
63937da2899SCharles.Forsyth     	}
64037da2899SCharles.Forsyth 
64137da2899SCharles.Forsyth     	cavity.x = 0;
64237da2899SCharles.Forsyth 	cavity.y = 0;
64337da2899SCharles.Forsyth 	pos.x = 0;
64437da2899SCharles.Forsyth 	pos.y = 0;
64537da2899SCharles.Forsyth 	cavity.width = master->act.width;
64637da2899SCharles.Forsyth 	cavity.height = master->act.height;
64737da2899SCharles.Forsyth 
64837da2899SCharles.Forsyth 	for(slave = master->slave; slave != nil; slave = slave->next) {
64937da2899SCharles.Forsyth 		slave2BW = slave->borderwidth*2;
65037da2899SCharles.Forsyth 		if(slave->flag & (Tktop|Tkbottom)) {
65137da2899SCharles.Forsyth 	    		frame.width = cavity.width;
65237da2899SCharles.Forsyth 	    		frame.height = slave->req.height + slave2BW +
65337da2899SCharles.Forsyth 		    			slave->pad.y + slave->ipad.y;
65437da2899SCharles.Forsyth 	    		if(slave->flag & Tkexpand)
65537da2899SCharles.Forsyth 				frame.height += tkexpandy(slave, cavity.height);
65637da2899SCharles.Forsyth 	    		cavity.height -= frame.height;
65737da2899SCharles.Forsyth 	    		if(cavity.height < 0) {
65837da2899SCharles.Forsyth 				frame.height += cavity.height;
65937da2899SCharles.Forsyth 				cavity.height = 0;
66037da2899SCharles.Forsyth 	    		}
66137da2899SCharles.Forsyth 	    		frame.x = cavity.x;
66237da2899SCharles.Forsyth 	    		if(slave->flag & Tktop) {
66337da2899SCharles.Forsyth 				frame.y = cavity.y;
66437da2899SCharles.Forsyth 				cavity.y += frame.height;
66537da2899SCharles.Forsyth 	    		}
66637da2899SCharles.Forsyth 			else
66737da2899SCharles.Forsyth 				frame.y = cavity.y + cavity.height;
66837da2899SCharles.Forsyth 		}
66937da2899SCharles.Forsyth 		else {
67037da2899SCharles.Forsyth 	    		frame.height = cavity.height;
67137da2899SCharles.Forsyth 	    		frame.width = slave->req.width + slave2BW +
67237da2899SCharles.Forsyth 					slave->pad.x + slave->ipad.x;
67337da2899SCharles.Forsyth 	    		if(slave->flag & Tkexpand)
67437da2899SCharles.Forsyth 				frame.width += tkexpandx(slave, cavity.width);
67537da2899SCharles.Forsyth 	    		cavity.width -= frame.width;
67637da2899SCharles.Forsyth 	    		if(cavity.width < 0) {
67737da2899SCharles.Forsyth 				frame.width += cavity.width;
67837da2899SCharles.Forsyth 				cavity.width = 0;
67937da2899SCharles.Forsyth 	    		}
68037da2899SCharles.Forsyth 	    		frame.y = cavity.y;
68137da2899SCharles.Forsyth 	    		if(slave->flag & Tkleft) {
68237da2899SCharles.Forsyth 				frame.x = cavity.x;
68337da2899SCharles.Forsyth 				cavity.x += frame.width;
68437da2899SCharles.Forsyth 	    		}
68537da2899SCharles.Forsyth 			else
68637da2899SCharles.Forsyth 				frame.x = cavity.x + cavity.width;
68737da2899SCharles.Forsyth 		}
68837da2899SCharles.Forsyth 
68937da2899SCharles.Forsyth 		tksetslavereq(slave, frame);
69037da2899SCharles.Forsyth 	}
69137da2899SCharles.Forsyth 
69237da2899SCharles.Forsyth 	master->dirty = tkrect(master, 1);
69337da2899SCharles.Forsyth 	tkdirty(master);
69437da2899SCharles.Forsyth 	return 1;
69537da2899SCharles.Forsyth }
69637da2899SCharles.Forsyth 
697