137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "tk.h"
437da2899SCharles.Forsyth #include "textw.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth #define istring u.string
737da2899SCharles.Forsyth #define iwin u.win
837da2899SCharles.Forsyth #define imark u.mark
937da2899SCharles.Forsyth #define iline u.line
1037da2899SCharles.Forsyth
1137da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
1237da2899SCharles.Forsyth
1337da2899SCharles.Forsyth static char* tktwincget(Tk*, char*, char**);
1437da2899SCharles.Forsyth static char* tktwinconfigure(Tk*, char*, char**);
1537da2899SCharles.Forsyth static char* tktwincreate(Tk*, char*, char**);
1637da2899SCharles.Forsyth static char* tktwinnames(Tk*, char*, char**);
1737da2899SCharles.Forsyth static int winowned(Tk *tk, Tk *sub);
1837da2899SCharles.Forsyth
1937da2899SCharles.Forsyth static
2037da2899SCharles.Forsyth TkStab tkalign[] =
2137da2899SCharles.Forsyth {
2237da2899SCharles.Forsyth "top", Tktop,
2337da2899SCharles.Forsyth "bottom", Tkbottom,
2437da2899SCharles.Forsyth "center", Tkcenter,
2537da2899SCharles.Forsyth "baseline", Tkbaseline,
2637da2899SCharles.Forsyth nil
2737da2899SCharles.Forsyth };
2837da2899SCharles.Forsyth
2937da2899SCharles.Forsyth static
3037da2899SCharles.Forsyth TkOption twinopts[] =
3137da2899SCharles.Forsyth {
3237da2899SCharles.Forsyth "align", OPTstab, O(TkTwind, align), tkalign,
3337da2899SCharles.Forsyth "create", OPTtext, O(TkTwind, create), nil,
3437da2899SCharles.Forsyth "padx", OPTnndist, O(TkTwind, padx), nil,
3537da2899SCharles.Forsyth "pady", OPTnndist, O(TkTwind, pady), nil,
3637da2899SCharles.Forsyth "stretch", OPTstab, O(TkTwind, stretch), tkbool,
3737da2899SCharles.Forsyth "window", OPTwinp, O(TkTwind, sub), nil,
3837da2899SCharles.Forsyth "ascent", OPTdist, O(TkTwind, ascent), nil,
3937da2899SCharles.Forsyth nil
4037da2899SCharles.Forsyth };
4137da2899SCharles.Forsyth
4237da2899SCharles.Forsyth TkCmdtab
4337da2899SCharles.Forsyth tktwincmd[] =
4437da2899SCharles.Forsyth {
4537da2899SCharles.Forsyth "cget", tktwincget,
4637da2899SCharles.Forsyth "configure", tktwinconfigure,
4737da2899SCharles.Forsyth "create", tktwincreate,
4837da2899SCharles.Forsyth "names", tktwinnames,
4937da2899SCharles.Forsyth nil
5037da2899SCharles.Forsyth };
5137da2899SCharles.Forsyth
5237da2899SCharles.Forsyth int
tktfindsubitem(Tk * sub,TkTindex * ix)5337da2899SCharles.Forsyth tktfindsubitem(Tk *sub, TkTindex *ix)
5437da2899SCharles.Forsyth {
5537da2899SCharles.Forsyth Tk *tk, *isub;
5637da2899SCharles.Forsyth TkText *tkt;
5737da2899SCharles.Forsyth
5837da2899SCharles.Forsyth tk = sub->parent;
5937da2899SCharles.Forsyth if(tk != nil) {
6037da2899SCharles.Forsyth tkt = TKobj(TkText, tk);
6137da2899SCharles.Forsyth tktstartind(tkt, ix);
6237da2899SCharles.Forsyth do {
6337da2899SCharles.Forsyth if(ix->item->kind == TkTwin) {
6437da2899SCharles.Forsyth isub = ix->item->iwin->sub;
6537da2899SCharles.Forsyth if(isub != nil &&
6637da2899SCharles.Forsyth isub->name != nil &&
6737da2899SCharles.Forsyth strcmp(isub->name->name, sub->name->name) == 0)
6837da2899SCharles.Forsyth return 1;
6937da2899SCharles.Forsyth }
7037da2899SCharles.Forsyth } while(tktadjustind(tkt, TkTbyitem, ix));
7137da2899SCharles.Forsyth }
7237da2899SCharles.Forsyth return 0;
7337da2899SCharles.Forsyth }
7437da2899SCharles.Forsyth
7537da2899SCharles.Forsyth static void
tktwindsize(Tk * tk,TkTindex * ix)7637da2899SCharles.Forsyth tktwindsize(Tk *tk, TkTindex *ix)
7737da2899SCharles.Forsyth {
7837da2899SCharles.Forsyth Tk *s;
7937da2899SCharles.Forsyth TkTitem *i;
8037da2899SCharles.Forsyth TkTwind *w;
8137da2899SCharles.Forsyth
8237da2899SCharles.Forsyth
8337da2899SCharles.Forsyth i = ix->item;
8437da2899SCharles.Forsyth /* assert(i->kind == TkTwin); */
8537da2899SCharles.Forsyth
8637da2899SCharles.Forsyth w = i->iwin;
8737da2899SCharles.Forsyth s = w->sub;
8837da2899SCharles.Forsyth if(s == nil)
8937da2899SCharles.Forsyth return;
9037da2899SCharles.Forsyth
9137da2899SCharles.Forsyth if(w->width != s->act.width || w->height != s->act.height) {
9237da2899SCharles.Forsyth s->act.width = w->width;
9337da2899SCharles.Forsyth s->act.height = w->height;
9437da2899SCharles.Forsyth if(s->slave) {
9537da2899SCharles.Forsyth tkpackqit(s);
9637da2899SCharles.Forsyth tkrunpack(tk->env->top);
9737da2899SCharles.Forsyth }
9837da2899SCharles.Forsyth }
9937da2899SCharles.Forsyth
10037da2899SCharles.Forsyth tktfixgeom(tk, tktprevwrapline(tk, ix->line), ix->line, 0);
10137da2899SCharles.Forsyth tktextsize(tk, 1);
10237da2899SCharles.Forsyth }
10337da2899SCharles.Forsyth
104*c9c0d12eSforsyth void
tktxtforgetsub(Tk * sub,Tk * tk)105*c9c0d12eSforsyth tktxtforgetsub(Tk *sub, Tk *tk)
10637da2899SCharles.Forsyth {
107*c9c0d12eSforsyth TkTwind *w;
108*c9c0d12eSforsyth TkTindex ix;
109*c9c0d12eSforsyth
110*c9c0d12eSforsyth if(!tktfindsubitem(sub, &ix))
111*c9c0d12eSforsyth return;
112*c9c0d12eSforsyth w = ix.item->iwin;
113*c9c0d12eSforsyth if(w->focus == tk) {
114*c9c0d12eSforsyth if(0)print("tktxtforget sub %p %q focus %p %q\n", sub, tkname(sub), tk, tkname(tk));
115*c9c0d12eSforsyth w->focus = nil;
116*c9c0d12eSforsyth }
11737da2899SCharles.Forsyth }
11837da2899SCharles.Forsyth
11937da2899SCharles.Forsyth static void
tktwingeom(Tk * sub,int x,int y,int w,int h)12037da2899SCharles.Forsyth tktwingeom(Tk *sub, int x, int y, int w, int h)
12137da2899SCharles.Forsyth {
12237da2899SCharles.Forsyth TkTindex ix;
12337da2899SCharles.Forsyth Tk *tk;
12437da2899SCharles.Forsyth TkTwind *win;
12537da2899SCharles.Forsyth
12637da2899SCharles.Forsyth USED(x);
12737da2899SCharles.Forsyth USED(y);
12837da2899SCharles.Forsyth
12937da2899SCharles.Forsyth tk = sub->parent;
13037da2899SCharles.Forsyth if(!tktfindsubitem(sub, &ix)) {
13137da2899SCharles.Forsyth print("tktwingeom: %s not found\n", sub->name->name);
13237da2899SCharles.Forsyth return;
13337da2899SCharles.Forsyth }
13437da2899SCharles.Forsyth
13537da2899SCharles.Forsyth win = ix.item->iwin;
13637da2899SCharles.Forsyth
13737da2899SCharles.Forsyth win->width = w;
13837da2899SCharles.Forsyth win->height = h;
13937da2899SCharles.Forsyth
14037da2899SCharles.Forsyth sub->req.width = w;
14137da2899SCharles.Forsyth sub->req.height = h;
14237da2899SCharles.Forsyth tktwindsize(tk, &ix);
14337da2899SCharles.Forsyth }
14437da2899SCharles.Forsyth
14537da2899SCharles.Forsyth static void
tktdestroyed(Tk * sub)14637da2899SCharles.Forsyth tktdestroyed(Tk *sub)
14737da2899SCharles.Forsyth {
14837da2899SCharles.Forsyth TkTindex ix;
14937da2899SCharles.Forsyth Tk *tk;
15037da2899SCharles.Forsyth
15137da2899SCharles.Forsyth if(tktfindsubitem(sub, &ix)) {
15237da2899SCharles.Forsyth ix.item->iwin->sub = nil;
15337da2899SCharles.Forsyth ix.item->iwin->focus = nil;
15437da2899SCharles.Forsyth if((tk = sub->parent) != nil) {
15537da2899SCharles.Forsyth tktfixgeom(tk, tktprevwrapline(tk, ix.line), ix.line, 0);
15637da2899SCharles.Forsyth tktextsize(tk, 1);
15737da2899SCharles.Forsyth sub->parent = nil;
15837da2899SCharles.Forsyth }
15937da2899SCharles.Forsyth }
16037da2899SCharles.Forsyth }
16137da2899SCharles.Forsyth
16237da2899SCharles.Forsyth void
tktdirty(Tk * sub)16337da2899SCharles.Forsyth tktdirty(Tk *sub)
16437da2899SCharles.Forsyth {
16537da2899SCharles.Forsyth Tk *tk, *parent, *isub;
16637da2899SCharles.Forsyth TkText *tkt;
16737da2899SCharles.Forsyth TkTindex ix;
16837da2899SCharles.Forsyth
16937da2899SCharles.Forsyth parent = nil;
17037da2899SCharles.Forsyth for(tk = sub; tk && parent == nil; tk = tk->master)
17137da2899SCharles.Forsyth parent = tk->parent;
17237da2899SCharles.Forsyth if(tk == nil)
17337da2899SCharles.Forsyth return;
17437da2899SCharles.Forsyth
17537da2899SCharles.Forsyth tkt = TKobj(TkText, parent);
17637da2899SCharles.Forsyth tktstartind(tkt, &ix);
17737da2899SCharles.Forsyth do {
17837da2899SCharles.Forsyth if(ix.item->kind == TkTwin) {
17937da2899SCharles.Forsyth isub = ix.item->iwin->sub;
18037da2899SCharles.Forsyth if(isub != nil) {
18137da2899SCharles.Forsyth tktfixgeom(parent, tktprevwrapline(parent, ix.line), ix.line, 0);
18237da2899SCharles.Forsyth if (sub->flag & Tktransparent)
18337da2899SCharles.Forsyth parent->flag |= Tkrefresh; /* XXX could be more efficient, by drawing the background locally? */
18437da2899SCharles.Forsyth return;
18537da2899SCharles.Forsyth }
18637da2899SCharles.Forsyth }
18737da2899SCharles.Forsyth } while(tktadjustind(tkt, TkTbyitem, &ix));
18837da2899SCharles.Forsyth tktextsize(parent, 1);
18937da2899SCharles.Forsyth }
19037da2899SCharles.Forsyth
19137da2899SCharles.Forsyth static char*
tktwinchk(Tk * tk,TkTwind * w,Tk * oldsub)19237da2899SCharles.Forsyth tktwinchk(Tk *tk, TkTwind *w, Tk *oldsub)
19337da2899SCharles.Forsyth {
19437da2899SCharles.Forsyth Tk *sub;
19537da2899SCharles.Forsyth
19637da2899SCharles.Forsyth sub = w->sub;
19737da2899SCharles.Forsyth if (sub != oldsub) {
19837da2899SCharles.Forsyth w->sub = oldsub;
19937da2899SCharles.Forsyth if(sub == nil)
20037da2899SCharles.Forsyth return nil;
20137da2899SCharles.Forsyth
20237da2899SCharles.Forsyth if(sub->flag & Tkwindow)
20337da2899SCharles.Forsyth return TkIstop;
20437da2899SCharles.Forsyth
20537da2899SCharles.Forsyth if(sub->master != nil || sub->parent != nil)
20637da2899SCharles.Forsyth return TkWpack;
20737da2899SCharles.Forsyth
20837da2899SCharles.Forsyth if (oldsub != nil) {
20937da2899SCharles.Forsyth oldsub->parent = nil;
21037da2899SCharles.Forsyth oldsub->geom = nil;
21137da2899SCharles.Forsyth oldsub->destroyed = nil;
21237da2899SCharles.Forsyth }
21337da2899SCharles.Forsyth w->sub = sub;
21437da2899SCharles.Forsyth w->focus = nil;
21537da2899SCharles.Forsyth
21637da2899SCharles.Forsyth sub->parent = tk;
21737da2899SCharles.Forsyth tksetbits(sub, Tksubsub);
21837da2899SCharles.Forsyth sub->geom = tktwingeom;
21937da2899SCharles.Forsyth sub->destroyed = tktdestroyed;
22037da2899SCharles.Forsyth
22137da2899SCharles.Forsyth w->width = sub->req.width;
22237da2899SCharles.Forsyth w->height = sub->req.height;
22337da2899SCharles.Forsyth w->owned = winowned(tk, sub);
22437da2899SCharles.Forsyth }
22537da2899SCharles.Forsyth
22637da2899SCharles.Forsyth return nil;
22737da2899SCharles.Forsyth }
22837da2899SCharles.Forsyth
22937da2899SCharles.Forsyth
23037da2899SCharles.Forsyth /* Text Window Command (+ means implemented)
23137da2899SCharles.Forsyth +cget
23237da2899SCharles.Forsyth +configure
23337da2899SCharles.Forsyth +create
23437da2899SCharles.Forsyth +names
23537da2899SCharles.Forsyth */
23637da2899SCharles.Forsyth
23737da2899SCharles.Forsyth static char*
tktwincget(Tk * tk,char * arg,char ** val)23837da2899SCharles.Forsyth tktwincget(Tk *tk, char *arg, char **val)
23937da2899SCharles.Forsyth {
24037da2899SCharles.Forsyth char *e;
24137da2899SCharles.Forsyth TkTindex ix;
24237da2899SCharles.Forsyth TkOptab tko[2];
24337da2899SCharles.Forsyth
24437da2899SCharles.Forsyth e = tktindparse(tk, &arg, &ix);
24537da2899SCharles.Forsyth if(e != nil)
24637da2899SCharles.Forsyth return e;
24737da2899SCharles.Forsyth if(ix.item->kind != TkTwin)
24837da2899SCharles.Forsyth return TkBadwp;
24937da2899SCharles.Forsyth
25037da2899SCharles.Forsyth tko[0].ptr = ix.item->iwin;
25137da2899SCharles.Forsyth tko[0].optab = twinopts;
25237da2899SCharles.Forsyth tko[1].ptr = nil;
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth return tkgencget(tko, arg, val, tk->env->top);
25537da2899SCharles.Forsyth }
25637da2899SCharles.Forsyth
25737da2899SCharles.Forsyth static char*
tktwinconfigure(Tk * tk,char * arg,char ** val)25837da2899SCharles.Forsyth tktwinconfigure(Tk *tk, char *arg, char **val)
25937da2899SCharles.Forsyth {
26037da2899SCharles.Forsyth char *e;
26137da2899SCharles.Forsyth TkTindex ix;
26237da2899SCharles.Forsyth TkOptab tko[2];
26337da2899SCharles.Forsyth Tk *oldsub;
26437da2899SCharles.Forsyth
26537da2899SCharles.Forsyth USED(val);
26637da2899SCharles.Forsyth
26737da2899SCharles.Forsyth e = tktindparse(tk, &arg, &ix);
26837da2899SCharles.Forsyth if(e != nil)
26937da2899SCharles.Forsyth return e;
27037da2899SCharles.Forsyth if(ix.item->kind != TkTwin)
27137da2899SCharles.Forsyth return TkBadwp;
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth oldsub = ix.item->iwin->sub;
27437da2899SCharles.Forsyth
27537da2899SCharles.Forsyth tko[0].ptr = ix.item->iwin;
27637da2899SCharles.Forsyth tko[0].optab = twinopts;
27737da2899SCharles.Forsyth tko[1].ptr = nil;
27837da2899SCharles.Forsyth
27937da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
28037da2899SCharles.Forsyth if(e != nil)
28137da2899SCharles.Forsyth return e;
28237da2899SCharles.Forsyth
28337da2899SCharles.Forsyth e = tktwinchk(tk, ix.item->iwin, oldsub);
28437da2899SCharles.Forsyth if(e != nil)
28537da2899SCharles.Forsyth return e;
28637da2899SCharles.Forsyth
28737da2899SCharles.Forsyth tktwindsize(tk, &ix);
28837da2899SCharles.Forsyth return nil;
28937da2899SCharles.Forsyth }
29037da2899SCharles.Forsyth
29137da2899SCharles.Forsyth /*
29237da2899SCharles.Forsyth * return true if tk is an ancestor of sub
29337da2899SCharles.Forsyth */
29437da2899SCharles.Forsyth static int
winowned(Tk * tk,Tk * sub)29537da2899SCharles.Forsyth winowned(Tk *tk, Tk *sub)
29637da2899SCharles.Forsyth {
29737da2899SCharles.Forsyth int len;
29837da2899SCharles.Forsyth if (tk->name == nil || sub->name == nil)
29937da2899SCharles.Forsyth return 0;
30037da2899SCharles.Forsyth len = strlen(tk->name->name);
30137da2899SCharles.Forsyth if (strncmp(tk->name->name, sub->name->name, len) == 0 &&
30237da2899SCharles.Forsyth sub->name->name[len] == '.')
30337da2899SCharles.Forsyth return 1;
30437da2899SCharles.Forsyth return 0;
30537da2899SCharles.Forsyth }
30637da2899SCharles.Forsyth
30737da2899SCharles.Forsyth static char*
tktwincreate(Tk * tk,char * arg,char ** val)30837da2899SCharles.Forsyth tktwincreate(Tk *tk, char *arg, char **val)
30937da2899SCharles.Forsyth {
31037da2899SCharles.Forsyth char *e;
31137da2899SCharles.Forsyth TkTindex ix;
31237da2899SCharles.Forsyth TkTitem *i;
31337da2899SCharles.Forsyth TkText *tkt;
31437da2899SCharles.Forsyth TkOptab tko[2];
31537da2899SCharles.Forsyth
31637da2899SCharles.Forsyth USED(val);
31737da2899SCharles.Forsyth
31837da2899SCharles.Forsyth tkt = TKobj(TkText, tk);
31937da2899SCharles.Forsyth
32037da2899SCharles.Forsyth e = tktindparse(tk, &arg, &ix);
32137da2899SCharles.Forsyth if(e != nil)
32237da2899SCharles.Forsyth return e;
32337da2899SCharles.Forsyth
32437da2899SCharles.Forsyth e = tktnewitem(TkTwin, 0, &i);
32537da2899SCharles.Forsyth if(e != nil)
32637da2899SCharles.Forsyth return e;
32737da2899SCharles.Forsyth
32837da2899SCharles.Forsyth i->iwin = malloc(sizeof(TkTwind));
32937da2899SCharles.Forsyth if(i->iwin == nil) {
33037da2899SCharles.Forsyth tktfreeitems(tkt, i, 1);
33137da2899SCharles.Forsyth return TkNomem;
33237da2899SCharles.Forsyth }
33337da2899SCharles.Forsyth
33437da2899SCharles.Forsyth memset(i->iwin, 0, sizeof(TkTwind));
33537da2899SCharles.Forsyth i->iwin->align = Tkcenter;
33637da2899SCharles.Forsyth i->iwin->ascent = -1;
33737da2899SCharles.Forsyth
33837da2899SCharles.Forsyth tko[0].ptr = i->iwin;
33937da2899SCharles.Forsyth tko[0].optab = twinopts;
34037da2899SCharles.Forsyth tko[1].ptr = nil;
34137da2899SCharles.Forsyth
34237da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
34337da2899SCharles.Forsyth if(e != nil) {
34437da2899SCharles.Forsyth err1:
34537da2899SCharles.Forsyth tktfreeitems(tkt, i, 1);
34637da2899SCharles.Forsyth return e;
34737da2899SCharles.Forsyth }
34837da2899SCharles.Forsyth
34937da2899SCharles.Forsyth e = tktwinchk(tk, i->iwin, nil);
35037da2899SCharles.Forsyth if(e != nil)
35137da2899SCharles.Forsyth goto err1;
35237da2899SCharles.Forsyth
35337da2899SCharles.Forsyth e = tktsplititem(&ix);
35437da2899SCharles.Forsyth if(e != nil)
35537da2899SCharles.Forsyth goto err1;
35637da2899SCharles.Forsyth
35737da2899SCharles.Forsyth tktiteminsert(tkt, &ix, i);
35837da2899SCharles.Forsyth if(e != nil)
35937da2899SCharles.Forsyth goto err1;
36037da2899SCharles.Forsyth
36137da2899SCharles.Forsyth tktadjustind(tkt, TkTbyitemback, &ix);
36237da2899SCharles.Forsyth tktwindsize(tk, &ix);
36337da2899SCharles.Forsyth
36437da2899SCharles.Forsyth return nil;
36537da2899SCharles.Forsyth }
36637da2899SCharles.Forsyth
36737da2899SCharles.Forsyth static char*
tktwinnames(Tk * tk,char * arg,char ** val)36837da2899SCharles.Forsyth tktwinnames(Tk *tk, char *arg, char **val)
36937da2899SCharles.Forsyth {
37037da2899SCharles.Forsyth char *e, *fmt;
37137da2899SCharles.Forsyth TkTindex ix;
37237da2899SCharles.Forsyth TkText *tkt = TKobj(TkText, tk);
37337da2899SCharles.Forsyth
37437da2899SCharles.Forsyth USED(arg);
37537da2899SCharles.Forsyth
37637da2899SCharles.Forsyth tktstartind(tkt, &ix);
37737da2899SCharles.Forsyth fmt = "%s";
37837da2899SCharles.Forsyth do {
3795849851aSforsyth if(ix.item->kind == TkTwin &&
3805849851aSforsyth ix.item->iwin->sub != nil &&
3815849851aSforsyth ix.item->iwin->sub->name != nil) {
38237da2899SCharles.Forsyth e = tkvalue(val, fmt, ix.item->iwin->sub->name->name);
38337da2899SCharles.Forsyth if(e != nil)
38437da2899SCharles.Forsyth return e;
38537da2899SCharles.Forsyth fmt = " %s";
38637da2899SCharles.Forsyth }
38737da2899SCharles.Forsyth } while(tktadjustind(tkt, TkTbyitem, &ix));
38837da2899SCharles.Forsyth return nil;
38937da2899SCharles.Forsyth }
390