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 = ¶m;
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