137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "tk.h"
437da2899SCharles.Forsyth #include "canvs.h"
537da2899SCharles.Forsyth #include "textw.h"
637da2899SCharles.Forsyth #include "kernel.h"
737da2899SCharles.Forsyth
837da2899SCharles.Forsyth TkCtxt*
tknewctxt(Display * d)937da2899SCharles.Forsyth tknewctxt(Display *d)
1037da2899SCharles.Forsyth {
1137da2899SCharles.Forsyth TkCtxt *c;
1237da2899SCharles.Forsyth c = malloc(sizeof(TkCtxt));
1337da2899SCharles.Forsyth if(c == nil)
1437da2899SCharles.Forsyth return nil;
1537da2899SCharles.Forsyth c->lock = libqlalloc();
1637da2899SCharles.Forsyth if(c->lock == nil){
1737da2899SCharles.Forsyth free(c);
1837da2899SCharles.Forsyth return nil;
1937da2899SCharles.Forsyth }
2037da2899SCharles.Forsyth if (tkextnnewctxt(c) != 0) {
2137da2899SCharles.Forsyth free(c->lock);
2237da2899SCharles.Forsyth free(c);
2337da2899SCharles.Forsyth return nil;
2437da2899SCharles.Forsyth }
2537da2899SCharles.Forsyth c->display = d;
2637da2899SCharles.Forsyth return c;
2737da2899SCharles.Forsyth }
2837da2899SCharles.Forsyth
2937da2899SCharles.Forsyth void
tkfreectxt(TkCtxt * c)3037da2899SCharles.Forsyth tkfreectxt(TkCtxt *c)
3137da2899SCharles.Forsyth {
3237da2899SCharles.Forsyth int locked;
3337da2899SCharles.Forsyth Display *d;
3437da2899SCharles.Forsyth
3537da2899SCharles.Forsyth if(c == nil)
3637da2899SCharles.Forsyth return;
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth tkextnfreectxt(c);
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth d = c->display;
4137da2899SCharles.Forsyth locked = lockdisplay(d);
4237da2899SCharles.Forsyth tkfreecolcache(c);
4337da2899SCharles.Forsyth freeimage(c->i);
4437da2899SCharles.Forsyth freeimage(c->ia);
4537da2899SCharles.Forsyth if(locked)
4637da2899SCharles.Forsyth unlockdisplay(d);
4737da2899SCharles.Forsyth libqlfree(c->lock);
4837da2899SCharles.Forsyth free(c);
4937da2899SCharles.Forsyth }
5037da2899SCharles.Forsyth
5137da2899SCharles.Forsyth Image*
tkitmp(TkEnv * e,Point p,int fillcol)5237da2899SCharles.Forsyth tkitmp(TkEnv *e, Point p, int fillcol)
5337da2899SCharles.Forsyth {
5437da2899SCharles.Forsyth Image *i, **ip;
5537da2899SCharles.Forsyth TkTop *t;
5637da2899SCharles.Forsyth TkCtxt *ti;
5737da2899SCharles.Forsyth Display *d;
5837da2899SCharles.Forsyth Rectangle r;
5937da2899SCharles.Forsyth ulong pix;
6037da2899SCharles.Forsyth int alpha;
6137da2899SCharles.Forsyth
6237da2899SCharles.Forsyth t = e->top;
6337da2899SCharles.Forsyth ti = t->ctxt;
6437da2899SCharles.Forsyth d = t->display;
6537da2899SCharles.Forsyth
6637da2899SCharles.Forsyth pix = e->colors[fillcol];
6737da2899SCharles.Forsyth alpha = (pix & 0xff) != 0xff;
6837da2899SCharles.Forsyth ip = alpha ? &ti->ia : &ti->i;
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth if(*ip != nil) {
7137da2899SCharles.Forsyth i = *ip;
7237da2899SCharles.Forsyth if(p.x <= i->r.max.x && p.y <= i->r.max.y) {
7337da2899SCharles.Forsyth r.min = ZP;
7437da2899SCharles.Forsyth r.max = p;
7537da2899SCharles.Forsyth if (alpha)
7637da2899SCharles.Forsyth drawop(i, r, nil, nil, ZP, Clear);
7737da2899SCharles.Forsyth draw(i, r, tkgc(e, fillcol), nil, ZP);
7837da2899SCharles.Forsyth return i;
7937da2899SCharles.Forsyth }
8037da2899SCharles.Forsyth r = i->r;
8137da2899SCharles.Forsyth freeimage(i);
8237da2899SCharles.Forsyth if(p.x < r.max.x)
8337da2899SCharles.Forsyth p.x = r.max.x;
8437da2899SCharles.Forsyth if(p.y < r.max.y)
8537da2899SCharles.Forsyth p.y = r.max.y;
8637da2899SCharles.Forsyth }
8737da2899SCharles.Forsyth
8837da2899SCharles.Forsyth r.min = ZP;
8937da2899SCharles.Forsyth r.max = p;
9037da2899SCharles.Forsyth *ip = allocimage(d, r, alpha?RGBA32:d->image->chan, 0, pix);
9137da2899SCharles.Forsyth
9237da2899SCharles.Forsyth return *ip;
9337da2899SCharles.Forsyth }
9437da2899SCharles.Forsyth
9537da2899SCharles.Forsyth void
tkgeomchg(Tk * tk,TkGeom * g,int bd)9637da2899SCharles.Forsyth tkgeomchg(Tk *tk, TkGeom *g, int bd)
9737da2899SCharles.Forsyth {
9837da2899SCharles.Forsyth int w, h;
9937da2899SCharles.Forsyth void (*geomfn)(Tk*);
10037da2899SCharles.Forsyth if(memcmp(&tk->req, g, sizeof(TkGeom)) == 0 && bd == tk->borderwidth)
10137da2899SCharles.Forsyth return;
10237da2899SCharles.Forsyth
10337da2899SCharles.Forsyth geomfn = tkmethod[tk->type]->geom;
10437da2899SCharles.Forsyth if(geomfn != nil)
10537da2899SCharles.Forsyth geomfn(tk);
10637da2899SCharles.Forsyth
10737da2899SCharles.Forsyth if(tk->master != nil) {
10837da2899SCharles.Forsyth tkpackqit(tk->master);
10937da2899SCharles.Forsyth tkrunpack(tk->env->top);
11037da2899SCharles.Forsyth }
11137da2899SCharles.Forsyth else
11237da2899SCharles.Forsyth if(tk->geom != nil) {
11337da2899SCharles.Forsyth w = tk->req.width;
11437da2899SCharles.Forsyth h = tk->req.height;
11537da2899SCharles.Forsyth tk->req.width = 0;
11637da2899SCharles.Forsyth tk->req.height = 0;
11737da2899SCharles.Forsyth tk->geom(tk, tk->act.x, tk->act.y, w, h);
11837da2899SCharles.Forsyth if (tk->slave) {
11937da2899SCharles.Forsyth tkpackqit(tk);
12037da2899SCharles.Forsyth tkrunpack(tk->env->top);
12137da2899SCharles.Forsyth }
12237da2899SCharles.Forsyth }
12337da2899SCharles.Forsyth tkdeliver(tk, TkConfigure, g);
12437da2899SCharles.Forsyth }
12537da2899SCharles.Forsyth
12637da2899SCharles.Forsyth /*
12737da2899SCharles.Forsyth * return the widget within tk with by point p (in widget coords)
12837da2899SCharles.Forsyth */
12937da2899SCharles.Forsyth Tk*
tkinwindow(Tk * tk,Point p,int descend)13037da2899SCharles.Forsyth tkinwindow(Tk *tk, Point p, int descend)
13137da2899SCharles.Forsyth {
13237da2899SCharles.Forsyth Tk *f;
13337da2899SCharles.Forsyth Point q;
13437da2899SCharles.Forsyth if (ptinrect(p, tkrect(tk, 1)) == 0)
13537da2899SCharles.Forsyth return nil;
13637da2899SCharles.Forsyth for (;;) {
13737da2899SCharles.Forsyth if (descend && tkmethod[tk->type]->inwindow != nil)
13837da2899SCharles.Forsyth f = tkmethod[tk->type]->inwindow(tk, &p);
13937da2899SCharles.Forsyth else {
140*6e425a9dSCharles.Forsyth q = p;
14137da2899SCharles.Forsyth for (f = tk->slave; f; f = f->next) {
14237da2899SCharles.Forsyth q.x = p.x - (f->act.x + f->borderwidth);
14337da2899SCharles.Forsyth q.y = p.y - (f->act.y + f->borderwidth);
14437da2899SCharles.Forsyth if (ptinrect(q, tkrect(f, 1)))
14537da2899SCharles.Forsyth break;
14637da2899SCharles.Forsyth }
14737da2899SCharles.Forsyth p = q;
14837da2899SCharles.Forsyth }
14937da2899SCharles.Forsyth if (f == nil || f == tk)
15037da2899SCharles.Forsyth return tk;
15137da2899SCharles.Forsyth tk = f;
15237da2899SCharles.Forsyth }
15337da2899SCharles.Forsyth }
15437da2899SCharles.Forsyth
15537da2899SCharles.Forsyth Tk*
tkfindfocus(TkTop * t,int x,int y,int descend)15637da2899SCharles.Forsyth tkfindfocus(TkTop *t, int x, int y, int descend)
15737da2899SCharles.Forsyth {
15837da2899SCharles.Forsyth Point p, q;
15937da2899SCharles.Forsyth Tk *tk, *f;
16037da2899SCharles.Forsyth TkWin *tkw;
16137da2899SCharles.Forsyth p.x = x;
16237da2899SCharles.Forsyth p.y = y;
16337da2899SCharles.Forsyth for(f = t->windows; f != nil; f = TKobj(TkWin, f)->next) {
16437da2899SCharles.Forsyth assert(f->flag&Tkwindow);
16537da2899SCharles.Forsyth if(f->flag & Tkmapped) {
16637da2899SCharles.Forsyth tkw = TKobj(TkWin, f);
16737da2899SCharles.Forsyth q.x = p.x - (tkw->act.x+f->borderwidth);
16837da2899SCharles.Forsyth q.y = p.y - (tkw->act.y+f->borderwidth);
16937da2899SCharles.Forsyth tk = tkinwindow(f, q, descend);
17037da2899SCharles.Forsyth if(tk != nil)
17137da2899SCharles.Forsyth return tk;
17237da2899SCharles.Forsyth }
17337da2899SCharles.Forsyth }
17437da2899SCharles.Forsyth return nil;
17537da2899SCharles.Forsyth }
17637da2899SCharles.Forsyth
17737da2899SCharles.Forsyth void
tkmovewin(Tk * tk,Point p)17837da2899SCharles.Forsyth tkmovewin(Tk *tk, Point p)
17937da2899SCharles.Forsyth {
18037da2899SCharles.Forsyth TkWin *tkw;
18137da2899SCharles.Forsyth if((tk->flag & Tkwindow) == 0)
18237da2899SCharles.Forsyth return;
18337da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
18437da2899SCharles.Forsyth if(! eqpt(p, tkw->req)){
18537da2899SCharles.Forsyth tkw->req = p;
18637da2899SCharles.Forsyth tkw->changed = 1;
18737da2899SCharles.Forsyth }
18837da2899SCharles.Forsyth }
18937da2899SCharles.Forsyth
19037da2899SCharles.Forsyth void
tkmoveresize(Tk * tk,int x,int y,int w,int h)19137da2899SCharles.Forsyth tkmoveresize(Tk *tk, int x, int y, int w, int h)
19237da2899SCharles.Forsyth {
19337da2899SCharles.Forsyth TkWin *tkw;
19437da2899SCharles.Forsyth USED(x);
19537da2899SCharles.Forsyth USED(y);
19637da2899SCharles.Forsyth assert(tk->flag&Tkwindow);
19737da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
19837da2899SCharles.Forsyth if(w < 0)
19937da2899SCharles.Forsyth w = 0;
20037da2899SCharles.Forsyth if(h < 0)
20137da2899SCharles.Forsyth h = 0;
20237da2899SCharles.Forsyth //print("moveresize %s %d %d +[%d %d], callerpc %lux\n", tk->name->name, x, y, w, h, getcallerpc(&tk));
20337da2899SCharles.Forsyth tk->req.width = w;
20437da2899SCharles.Forsyth tk->req.height = h;
20537da2899SCharles.Forsyth tk->act = tk->req;
20637da2899SCharles.Forsyth /* XXX perhaps should actually suspend the window here? */
20737da2899SCharles.Forsyth tkw->changed = 1;
20837da2899SCharles.Forsyth }
20937da2899SCharles.Forsyth
21037da2899SCharles.Forsyth static void
tkexterncreatewin(Tk * tk,Rectangle r)21137da2899SCharles.Forsyth tkexterncreatewin(Tk *tk, Rectangle r)
21237da2899SCharles.Forsyth {
21337da2899SCharles.Forsyth TkWin *tkw;
21437da2899SCharles.Forsyth TkTop *top;
21537da2899SCharles.Forsyth char *name;
21637da2899SCharles.Forsyth
21737da2899SCharles.Forsyth top = tk->env->top;
21837da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
21937da2899SCharles.Forsyth
22037da2899SCharles.Forsyth /*
22137da2899SCharles.Forsyth * for a choicebutton menu, use the name of the choicebutton which created it
22237da2899SCharles.Forsyth */
22337da2899SCharles.Forsyth if(tk->name == nil){
22437da2899SCharles.Forsyth name = tkw->cbname;
22537da2899SCharles.Forsyth assert(name != nil);
22637da2899SCharles.Forsyth } else
22737da2899SCharles.Forsyth name = tk->name->name;
22837da2899SCharles.Forsyth
22937da2899SCharles.Forsyth tkw->reqid++;
23037da2899SCharles.Forsyth tkwreq(top, "!reshape %s %d %d %d %d %d", name, tkw->reqid, r.min.x, r.min.y, r.max.x, r.max.y);
23137da2899SCharles.Forsyth tkw->changed = 0;
23237da2899SCharles.Forsyth tk->flag |= Tksuspended;
23337da2899SCharles.Forsyth }
23437da2899SCharles.Forsyth
23537da2899SCharles.Forsyth /*
23637da2899SCharles.Forsyth * return non-zero if the window size has changed (XXX choose better return value/function name!)
23737da2899SCharles.Forsyth */
23837da2899SCharles.Forsyth int
tkupdatewinsize(Tk * tk)23937da2899SCharles.Forsyth tkupdatewinsize(Tk *tk)
24037da2899SCharles.Forsyth {
24137da2899SCharles.Forsyth TkWin *tkw;
24237da2899SCharles.Forsyth Image *previ;
24337da2899SCharles.Forsyth Rectangle r, or;
24437da2899SCharles.Forsyth int bw2;
24537da2899SCharles.Forsyth
24637da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
24737da2899SCharles.Forsyth bw2 = 2*tk->borderwidth;
24837da2899SCharles.Forsyth r.min.x = tkw->req.x;
24937da2899SCharles.Forsyth r.min.y = tkw->req.y;
25037da2899SCharles.Forsyth r.max.x = r.min.x + tk->act.width + bw2;
25137da2899SCharles.Forsyth r.max.y = r.min.y + tk->act.height + bw2;
25237da2899SCharles.Forsyth previ = tkw->image;
25337da2899SCharles.Forsyth if(previ != nil){
25437da2899SCharles.Forsyth or.min.x = tkw->act.x;
25537da2899SCharles.Forsyth or.min.y = tkw->act.y;
25637da2899SCharles.Forsyth or.max.x = tkw->act.x + Dx(previ->r);
25737da2899SCharles.Forsyth or.max.y = tkw->act.y + Dy(previ->r);
25837da2899SCharles.Forsyth if(eqrect(or, r))
25937da2899SCharles.Forsyth return 0;
26037da2899SCharles.Forsyth }
26137da2899SCharles.Forsyth tkexterncreatewin(tk, r);
26237da2899SCharles.Forsyth return 1;
26337da2899SCharles.Forsyth }
26437da2899SCharles.Forsyth
26537da2899SCharles.Forsyth static char*
tkdrawslaves1(Tk * tk,Point orig,Image * dst,int * dirty)26637da2899SCharles.Forsyth tkdrawslaves1(Tk *tk, Point orig, Image *dst, int *dirty)
26737da2899SCharles.Forsyth {
26837da2899SCharles.Forsyth Tk *f;
26937da2899SCharles.Forsyth char *e = nil;
27037da2899SCharles.Forsyth Point worig;
27137da2899SCharles.Forsyth Rectangle r, oclip;
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth worig.x = orig.x + tk->act.x + tk->borderwidth;
27437da2899SCharles.Forsyth worig.y = orig.y + tk->act.y + tk->borderwidth;
27537da2899SCharles.Forsyth
27637da2899SCharles.Forsyth r = rectaddpt(tk->dirty, worig);
27737da2899SCharles.Forsyth if (Dx(r) > 0 && rectXrect(r, dst->clipr)) {
27837da2899SCharles.Forsyth e = tkmethod[tk->type]->draw(tk, orig);
27937da2899SCharles.Forsyth tk->dirty = bbnil;
28037da2899SCharles.Forsyth *dirty = 1;
28137da2899SCharles.Forsyth }
28237da2899SCharles.Forsyth if(e != nil)
28337da2899SCharles.Forsyth return e;
28437da2899SCharles.Forsyth
28537da2899SCharles.Forsyth /*
28637da2899SCharles.Forsyth * grids need clipping
28737da2899SCharles.Forsyth * XXX BUG: they can't, 'cos text widgets don't clip appropriately.
28837da2899SCharles.Forsyth */
28937da2899SCharles.Forsyth if (tk->grid != nil) {
29037da2899SCharles.Forsyth r = rectaddpt(tkrect(tk, 0), worig);
29137da2899SCharles.Forsyth if (rectclip(&r, dst->clipr) == 0)
29237da2899SCharles.Forsyth return nil;
29337da2899SCharles.Forsyth oclip = dst->clipr;
29437da2899SCharles.Forsyth replclipr(dst, 0, r);
29537da2899SCharles.Forsyth }
29637da2899SCharles.Forsyth for(f = tk->slave; e == nil && f; f = f->next)
29737da2899SCharles.Forsyth e = tkdrawslaves1(f, worig, dst, dirty);
29837da2899SCharles.Forsyth if (tk->grid != nil)
29937da2899SCharles.Forsyth replclipr(dst, 0, oclip);
30037da2899SCharles.Forsyth return e;
30137da2899SCharles.Forsyth }
30237da2899SCharles.Forsyth
30337da2899SCharles.Forsyth char*
tkdrawslaves(Tk * tk,Point orig,int * dirty)30437da2899SCharles.Forsyth tkdrawslaves(Tk *tk, Point orig, int *dirty)
30537da2899SCharles.Forsyth {
30637da2899SCharles.Forsyth Image *i;
30737da2899SCharles.Forsyth char *e;
30837da2899SCharles.Forsyth i = tkimageof(tk);
30937da2899SCharles.Forsyth if (i == nil)
31037da2899SCharles.Forsyth return nil;
31137da2899SCharles.Forsyth e = tkdrawslaves1(tk, orig, i, dirty);
31237da2899SCharles.Forsyth return e;
31337da2899SCharles.Forsyth }
31437da2899SCharles.Forsyth
31537da2899SCharles.Forsyth char*
tkupdate(TkTop * t)31637da2899SCharles.Forsyth tkupdate(TkTop *t)
31737da2899SCharles.Forsyth {
31837da2899SCharles.Forsyth Tk* tk;
31937da2899SCharles.Forsyth int locked;
32037da2899SCharles.Forsyth TkWin *tkw;
32137da2899SCharles.Forsyth Display *d;
32237da2899SCharles.Forsyth char *e;
32337da2899SCharles.Forsyth int dirty = 0;
32437da2899SCharles.Forsyth if(t->noupdate)
32537da2899SCharles.Forsyth return nil;
32637da2899SCharles.Forsyth
32737da2899SCharles.Forsyth d = t->display;
32837da2899SCharles.Forsyth locked = lockdisplay(d);
32937da2899SCharles.Forsyth tk = t->windows;
33037da2899SCharles.Forsyth while(tk) {
33137da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
33237da2899SCharles.Forsyth if((tk->flag & (Tkmapped|Tksuspended)) == Tkmapped) {
33337da2899SCharles.Forsyth if (tkupdatewinsize(tk) == 0){
33437da2899SCharles.Forsyth e = tkdrawslaves(tk, ZP, &dirty);
33537da2899SCharles.Forsyth if(e != nil)
33637da2899SCharles.Forsyth return e;
33737da2899SCharles.Forsyth }
33837da2899SCharles.Forsyth }
33937da2899SCharles.Forsyth tk = tkw->next;
34037da2899SCharles.Forsyth }
34137da2899SCharles.Forsyth if (dirty || t->dirty) {
34237da2899SCharles.Forsyth flushimage(d, 1);
34337da2899SCharles.Forsyth t->dirty = 0;
34437da2899SCharles.Forsyth }
34537da2899SCharles.Forsyth if(locked)
34637da2899SCharles.Forsyth unlockdisplay(d);
34737da2899SCharles.Forsyth return nil;
34837da2899SCharles.Forsyth }
34937da2899SCharles.Forsyth
35037da2899SCharles.Forsyth int
tkischild(Tk * tk,Tk * child)35137da2899SCharles.Forsyth tkischild(Tk *tk, Tk *child)
35237da2899SCharles.Forsyth {
35337da2899SCharles.Forsyth while(child != nil && child != tk){
35437da2899SCharles.Forsyth if(child->master)
35537da2899SCharles.Forsyth child = child->master;
35637da2899SCharles.Forsyth else
35737da2899SCharles.Forsyth child = child->parent;
35837da2899SCharles.Forsyth }
35937da2899SCharles.Forsyth return child == tk;
36037da2899SCharles.Forsyth }
36137da2899SCharles.Forsyth
36237da2899SCharles.Forsyth void
tksetbits(Tk * tk,int mask)36337da2899SCharles.Forsyth tksetbits(Tk *tk, int mask)
36437da2899SCharles.Forsyth {
36537da2899SCharles.Forsyth tk->flag |= mask;
36637da2899SCharles.Forsyth for(tk = tk->slave; tk; tk = tk->next)
36737da2899SCharles.Forsyth tksetbits(tk, mask);
36837da2899SCharles.Forsyth }
36937da2899SCharles.Forsyth
37037da2899SCharles.Forsyth char*
tkmap(Tk * tk)37137da2899SCharles.Forsyth tkmap(Tk *tk)
37237da2899SCharles.Forsyth {
37337da2899SCharles.Forsyth /*
37437da2899SCharles.Forsyth is this necessary?
37537da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
37637da2899SCharles.Forsyth if(tkw->image != nil)
37737da2899SCharles.Forsyth tkwreq(tk->env->top, "raise %s", tk->name->name);
37837da2899SCharles.Forsyth */
37937da2899SCharles.Forsyth
38037da2899SCharles.Forsyth if(tk->flag & Tkmapped)
38137da2899SCharles.Forsyth return nil;
38237da2899SCharles.Forsyth
38337da2899SCharles.Forsyth tk->flag |= Tkmapped;
38437da2899SCharles.Forsyth tkmoveresize(tk, 0, 0, tk->act.width, tk->act.height);
38537da2899SCharles.Forsyth tkdeliver(tk, TkMap, nil);
38637da2899SCharles.Forsyth return nil;
38737da2899SCharles.Forsyth //tkupdate(tk->env->top);
38837da2899SCharles.Forsyth }
38937da2899SCharles.Forsyth
39037da2899SCharles.Forsyth void
tkunmap(Tk * tk)39137da2899SCharles.Forsyth tkunmap(Tk *tk)
39237da2899SCharles.Forsyth {
39337da2899SCharles.Forsyth TkTop *t;
39437da2899SCharles.Forsyth TkCtxt *c;
39537da2899SCharles.Forsyth
39637da2899SCharles.Forsyth while(tk->master)
39737da2899SCharles.Forsyth tk = tk->master;
39837da2899SCharles.Forsyth
39937da2899SCharles.Forsyth if((tk->flag & Tkmapped) == 0)
40037da2899SCharles.Forsyth return;
40137da2899SCharles.Forsyth
40237da2899SCharles.Forsyth t = tk->env->top;
40337da2899SCharles.Forsyth c = t->ctxt;
40437da2899SCharles.Forsyth
40537da2899SCharles.Forsyth if(tkischild(tk, c->mgrab))
40637da2899SCharles.Forsyth tksetmgrab(t, nil);
40737da2899SCharles.Forsyth if(tkischild(tk, c->entered)){
40837da2899SCharles.Forsyth tkdeliver(c->entered, TkLeave, nil);
40937da2899SCharles.Forsyth c->entered = nil;
41037da2899SCharles.Forsyth }
41137da2899SCharles.Forsyth if(tk == t->root)
41237da2899SCharles.Forsyth tksetglobalfocus(t, 0);
41337da2899SCharles.Forsyth
41437da2899SCharles.Forsyth tk->flag &= ~(Tkmapped|Tksuspended);
41537da2899SCharles.Forsyth
41637da2899SCharles.Forsyth tkdestroywinimage(tk);
41737da2899SCharles.Forsyth tkdeliver(tk, TkUnmap, nil);
41837da2899SCharles.Forsyth tkenterleave(t);
41937da2899SCharles.Forsyth /* XXX should unmap menus too */
42037da2899SCharles.Forsyth }
42137da2899SCharles.Forsyth
42237da2899SCharles.Forsyth Image*
tkimageof(Tk * tk)42337da2899SCharles.Forsyth tkimageof(Tk *tk)
42437da2899SCharles.Forsyth {
42537da2899SCharles.Forsyth while(tk) {
42637da2899SCharles.Forsyth if(tk->flag & Tkwindow)
42737da2899SCharles.Forsyth return TKobj(TkWin, tk)->image;
42837da2899SCharles.Forsyth if(tk->parent != nil) {
42937da2899SCharles.Forsyth tk = tk->parent;
43037da2899SCharles.Forsyth switch(tk->type) {
43137da2899SCharles.Forsyth case TKmenu:
43237da2899SCharles.Forsyth return TKobj(TkWin, tk)->image;
43337da2899SCharles.Forsyth case TKcanvas:
43437da2899SCharles.Forsyth return TKobj(TkCanvas, tk)->image;
43537da2899SCharles.Forsyth case TKtext:
43637da2899SCharles.Forsyth return TKobj(TkText, tk)->image;
43737da2899SCharles.Forsyth }
43837da2899SCharles.Forsyth abort();
43937da2899SCharles.Forsyth }
44037da2899SCharles.Forsyth tk = tk->master;
44137da2899SCharles.Forsyth }
44237da2899SCharles.Forsyth return nil;
44337da2899SCharles.Forsyth }
44437da2899SCharles.Forsyth
44537da2899SCharles.Forsyth void
tktopopt(Tk * tk,char * opt)44637da2899SCharles.Forsyth tktopopt(Tk *tk, char *opt)
44737da2899SCharles.Forsyth {
44837da2899SCharles.Forsyth TkTop *t;
44937da2899SCharles.Forsyth TkWin *tkw;
45037da2899SCharles.Forsyth TkOptab tko[4];
45137da2899SCharles.Forsyth
45237da2899SCharles.Forsyth tkw = TKobj(TkWin, tk);
45337da2899SCharles.Forsyth
45437da2899SCharles.Forsyth t = tk->env->top;
45537da2899SCharles.Forsyth
45637da2899SCharles.Forsyth tko[0].ptr = tkw;
45737da2899SCharles.Forsyth tko[0].optab = tktop;
45837da2899SCharles.Forsyth tko[1].ptr = tk;
45937da2899SCharles.Forsyth tko[1].optab = tkgeneric;
46037da2899SCharles.Forsyth tko[2].ptr = t;
46137da2899SCharles.Forsyth tko[2].optab = tktopdbg;
46237da2899SCharles.Forsyth tko[3].ptr = nil;
46337da2899SCharles.Forsyth
46437da2899SCharles.Forsyth tkparse(t, opt, tko, nil);
46537da2899SCharles.Forsyth }
46637da2899SCharles.Forsyth
46737da2899SCharles.Forsyth /* general compare - compare top-left corners, y takes priority */
46837da2899SCharles.Forsyth static int
tkfcmpgen(void * ap,void * bp)46937da2899SCharles.Forsyth tkfcmpgen(void *ap, void *bp)
47037da2899SCharles.Forsyth {
47137da2899SCharles.Forsyth TkWinfo *a = ap, *b = bp;
47237da2899SCharles.Forsyth
47337da2899SCharles.Forsyth if (a->r.min.y > b->r.min.y)
47437da2899SCharles.Forsyth return 1;
47537da2899SCharles.Forsyth if (a->r.min.y < b->r.min.y)
47637da2899SCharles.Forsyth return -1;
47737da2899SCharles.Forsyth if (a->r.min.x > b->r.min.x)
47837da2899SCharles.Forsyth return 1;
47937da2899SCharles.Forsyth if (a->r.min.x < b->r.min.x)
48037da2899SCharles.Forsyth return -1;
48137da2899SCharles.Forsyth return 0;
48237da2899SCharles.Forsyth }
48337da2899SCharles.Forsyth
48437da2899SCharles.Forsyth /* compare x-coords only */
48537da2899SCharles.Forsyth static int
tkfcmpx(void * ap,void * bp)48637da2899SCharles.Forsyth tkfcmpx(void *ap, void *bp)
48737da2899SCharles.Forsyth {
48837da2899SCharles.Forsyth TkWinfo *a = ap, *b = bp;
48937da2899SCharles.Forsyth return a->r.min.x - b->r.min.x;
49037da2899SCharles.Forsyth }
49137da2899SCharles.Forsyth
49237da2899SCharles.Forsyth /* compare y-coords only */
49337da2899SCharles.Forsyth static int
tkfcmpy(void * ap,void * bp)49437da2899SCharles.Forsyth tkfcmpy(void *ap, void *bp)
49537da2899SCharles.Forsyth {
49637da2899SCharles.Forsyth TkWinfo *a = ap, *b = bp;
49737da2899SCharles.Forsyth return a->r.min.y - b->r.min.y;
49837da2899SCharles.Forsyth }
49937da2899SCharles.Forsyth
50037da2899SCharles.Forsyth static void
tkfintervalintersect(int min1,int max1,int min2,int max2,int * min,int * max)50137da2899SCharles.Forsyth tkfintervalintersect(int min1, int max1, int min2, int max2, int *min, int *max)
50237da2899SCharles.Forsyth {
50337da2899SCharles.Forsyth if (min1 < min2)
50437da2899SCharles.Forsyth min1 = min2;
50537da2899SCharles.Forsyth if (max1 > max2)
50637da2899SCharles.Forsyth max1 = max2;
50737da2899SCharles.Forsyth if (max1 > min1) {
50837da2899SCharles.Forsyth *min = min1;
50937da2899SCharles.Forsyth *max = max1;
51037da2899SCharles.Forsyth } else
51137da2899SCharles.Forsyth *max = *min; /* no intersection */
51237da2899SCharles.Forsyth }
51337da2899SCharles.Forsyth
51437da2899SCharles.Forsyth void
tksortfocusorder(TkWinfo * inf,int n)51537da2899SCharles.Forsyth tksortfocusorder(TkWinfo *inf, int n)
51637da2899SCharles.Forsyth {
51737da2899SCharles.Forsyth int i;
51837da2899SCharles.Forsyth Rectangle overlap, r;
51937da2899SCharles.Forsyth int (*cmpfn)(void*, void*);
52037da2899SCharles.Forsyth
52137da2899SCharles.Forsyth overlap = inf[0].r;
52237da2899SCharles.Forsyth for (i = 0; i < n; i++) {
52337da2899SCharles.Forsyth r = inf[i].r;
52437da2899SCharles.Forsyth tkfintervalintersect(overlap.min.x, overlap.max.x,
52537da2899SCharles.Forsyth r.min.x, r.max.x, &overlap.min.x, &overlap.max.x);
52637da2899SCharles.Forsyth tkfintervalintersect(overlap.min.y, overlap.max.y,
52737da2899SCharles.Forsyth r.min.y, r.max.y, &overlap.min.y, &overlap.max.y);
52837da2899SCharles.Forsyth }
52937da2899SCharles.Forsyth
53037da2899SCharles.Forsyth if (Dx(overlap) > 0)
53137da2899SCharles.Forsyth cmpfn = tkfcmpy;
53237da2899SCharles.Forsyth else if (Dy(overlap) > 0)
53337da2899SCharles.Forsyth cmpfn = tkfcmpx;
53437da2899SCharles.Forsyth else
53537da2899SCharles.Forsyth cmpfn = tkfcmpgen;
53637da2899SCharles.Forsyth
53737da2899SCharles.Forsyth qsort(inf, n, sizeof(*inf), cmpfn);
53837da2899SCharles.Forsyth }
53937da2899SCharles.Forsyth
54037da2899SCharles.Forsyth void
tkappendfocusorder(Tk * tk)54137da2899SCharles.Forsyth tkappendfocusorder(Tk *tk)
54237da2899SCharles.Forsyth {
54337da2899SCharles.Forsyth TkTop *tkt;
54437da2899SCharles.Forsyth tkt = tk->env->top;
54537da2899SCharles.Forsyth if (tk->flag & Tktakefocus)
54637da2899SCharles.Forsyth tkt->focusorder[tkt->nfocus++] = tk;
54737da2899SCharles.Forsyth if (tkmethod[tk->type]->focusorder != nil)
54837da2899SCharles.Forsyth tkmethod[tk->type]->focusorder(tk);
54937da2899SCharles.Forsyth }
55037da2899SCharles.Forsyth
55137da2899SCharles.Forsyth void
tkbuildfocusorder(TkTop * tkt)55237da2899SCharles.Forsyth tkbuildfocusorder(TkTop *tkt)
55337da2899SCharles.Forsyth {
55437da2899SCharles.Forsyth Tk *tk;
55537da2899SCharles.Forsyth int n;
55637da2899SCharles.Forsyth
55737da2899SCharles.Forsyth if (tkt->focusorder != nil)
55837da2899SCharles.Forsyth free(tkt->focusorder);
55937da2899SCharles.Forsyth n = 0;
56037da2899SCharles.Forsyth for (tk = tkt->root; tk != nil; tk = tk->siblings)
56137da2899SCharles.Forsyth if (tk->flag & Tktakefocus)
56237da2899SCharles.Forsyth n++;
56337da2899SCharles.Forsyth if (n == 0) {
56437da2899SCharles.Forsyth tkt->focusorder = nil;
56537da2899SCharles.Forsyth return;
56637da2899SCharles.Forsyth }
56737da2899SCharles.Forsyth
56837da2899SCharles.Forsyth tkt->focusorder = malloc(sizeof(*tkt->focusorder) * n);
56937da2899SCharles.Forsyth tkt->nfocus = 0;
57037da2899SCharles.Forsyth if (tkt->focusorder == nil)
57137da2899SCharles.Forsyth return;
57237da2899SCharles.Forsyth
57337da2899SCharles.Forsyth tkappendfocusorder(tkt->root);
57437da2899SCharles.Forsyth }
57537da2899SCharles.Forsyth
57637da2899SCharles.Forsyth void
tkdirtyfocusorder(TkTop * tkt)57737da2899SCharles.Forsyth tkdirtyfocusorder(TkTop *tkt)
57837da2899SCharles.Forsyth {
57937da2899SCharles.Forsyth free(tkt->focusorder);
58037da2899SCharles.Forsyth tkt->focusorder = nil;
58137da2899SCharles.Forsyth tkt->nfocus = 0;
58237da2899SCharles.Forsyth }
58337da2899SCharles.Forsyth
58437da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
58537da2899SCharles.Forsyth #define OA(t, e) ((long)(((t*)0)->e))
58637da2899SCharles.Forsyth
58737da2899SCharles.Forsyth typedef struct TkSee TkSee;
58837da2899SCharles.Forsyth struct TkSee {
58937da2899SCharles.Forsyth int r[4];
59037da2899SCharles.Forsyth int p[2];
59137da2899SCharles.Forsyth int query;
59237da2899SCharles.Forsyth };
59337da2899SCharles.Forsyth
59437da2899SCharles.Forsyth static
59537da2899SCharles.Forsyth TkOption seeopts[] = {
59637da2899SCharles.Forsyth "rectangle", OPTfrac, OA(TkSee, r), IAUX(4),
59737da2899SCharles.Forsyth "point", OPTfrac, OA(TkSee, p), IAUX(2),
59837da2899SCharles.Forsyth "where", OPTbool, O(TkSee, query), nil,
59937da2899SCharles.Forsyth nil
60037da2899SCharles.Forsyth };
60137da2899SCharles.Forsyth
60237da2899SCharles.Forsyth char*
tkseecmd(TkTop * t,char * arg,char ** ret)60337da2899SCharles.Forsyth tkseecmd(TkTop *t, char *arg, char **ret)
60437da2899SCharles.Forsyth {
60537da2899SCharles.Forsyth TkOptab tko[2];
60637da2899SCharles.Forsyth TkSee opts;
60737da2899SCharles.Forsyth TkName *names;
60837da2899SCharles.Forsyth Tk *tk;
60937da2899SCharles.Forsyth char *e;
61037da2899SCharles.Forsyth Rectangle vr;
61137da2899SCharles.Forsyth Point vp;
61237da2899SCharles.Forsyth
61337da2899SCharles.Forsyth opts.r[0] = bbnil.min.x;
61437da2899SCharles.Forsyth opts.r[1] = bbnil.min.y;
61537da2899SCharles.Forsyth opts.r[2] = bbnil.max.x;
61637da2899SCharles.Forsyth opts.r[3] = bbnil.max.y;
61737da2899SCharles.Forsyth opts.p[0] = bbnil.max.x;
61837da2899SCharles.Forsyth opts.p[1] = bbnil.max.y;
61937da2899SCharles.Forsyth opts.query = 0;
62037da2899SCharles.Forsyth
62137da2899SCharles.Forsyth tko[0].ptr = &opts;
62237da2899SCharles.Forsyth tko[0].optab = seeopts;
62337da2899SCharles.Forsyth tko[1].ptr = nil;
62437da2899SCharles.Forsyth names = nil;
62537da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
62637da2899SCharles.Forsyth if (e != nil)
62737da2899SCharles.Forsyth return e;
62837da2899SCharles.Forsyth if (names == nil)
62937da2899SCharles.Forsyth return TkBadwp;
63037da2899SCharles.Forsyth tk = tklook(t, names->name, 0);
63137da2899SCharles.Forsyth tkfreename(names);
63237da2899SCharles.Forsyth if (tk == nil)
63337da2899SCharles.Forsyth return TkBadwp;
63437da2899SCharles.Forsyth if (opts.query) {
63537da2899SCharles.Forsyth if (!tkvisiblerect(tk, &vr))
63637da2899SCharles.Forsyth return nil;
63737da2899SCharles.Forsyth /* XXX should this be converted into screen coords? */
63837da2899SCharles.Forsyth return tkvalue(ret, "%d %d %d %d", vr.min.x, vr.min.y, vr.max.x, vr.max.y);
63937da2899SCharles.Forsyth }
64037da2899SCharles.Forsyth vr.min.x = opts.r[0];
64137da2899SCharles.Forsyth vr.min.y = opts.r[1];
64237da2899SCharles.Forsyth vr.max.x = opts.r[2];
64337da2899SCharles.Forsyth vr.max.y = opts.r[3];
64437da2899SCharles.Forsyth vp.x = opts.p[0];
64537da2899SCharles.Forsyth vp.y = opts.p[1];
64637da2899SCharles.Forsyth
64737da2899SCharles.Forsyth if (eqrect(vr, bbnil))
64837da2899SCharles.Forsyth vr = tkrect(tk, 1);
64937da2899SCharles.Forsyth if (eqpt(vp, bbnil.max))
65037da2899SCharles.Forsyth vp = vr.min;
65137da2899SCharles.Forsyth tksee(tk, vr, vp);
65237da2899SCharles.Forsyth return nil;
65337da2899SCharles.Forsyth }
65437da2899SCharles.Forsyth
65537da2899SCharles.Forsyth /*
65637da2899SCharles.Forsyth * make rectangle r in widget tk visible if possible;
65737da2899SCharles.Forsyth * if not possible, at least make point p visible.
65837da2899SCharles.Forsyth */
65937da2899SCharles.Forsyth void
tksee(Tk * tk,Rectangle r,Point p)66037da2899SCharles.Forsyth tksee(Tk *tk, Rectangle r, Point p)
66137da2899SCharles.Forsyth {
66237da2899SCharles.Forsyth Point g;
66337da2899SCharles.Forsyth //print("tksee %R, %P in %s\n", r, p, tk->name->name);
66437da2899SCharles.Forsyth g = Pt(tk->borderwidth, tk->borderwidth);
66537da2899SCharles.Forsyth if(tk->parent != nil) {
66637da2899SCharles.Forsyth g = addpt(g, tkmethod[tk->parent->type]->relpos(tk));
66737da2899SCharles.Forsyth tk = tk->parent;
66837da2899SCharles.Forsyth } else {
66937da2899SCharles.Forsyth g.x += tk->act.x;
67037da2899SCharles.Forsyth g.y += tk->act.y;
67137da2899SCharles.Forsyth tk = tk->master;
67237da2899SCharles.Forsyth }
67337da2899SCharles.Forsyth r = rectaddpt(r, g);
67437da2899SCharles.Forsyth p = addpt(p, g);
67537da2899SCharles.Forsyth while (tk != nil) {
67637da2899SCharles.Forsyth if (tkmethod[tk->type]->see != nil){
67737da2899SCharles.Forsyth //print("see r %R, p %P in %s\n", r, p, tk->name->name);
67837da2899SCharles.Forsyth tkmethod[tk->type]->see(tk, &r, &p);
67937da2899SCharles.Forsyth //print("now r %R, p %P\n", r, p);
68037da2899SCharles.Forsyth }
68137da2899SCharles.Forsyth g = Pt(tk->borderwidth, tk->borderwidth);
68237da2899SCharles.Forsyth if (tk->parent != nil) {
68337da2899SCharles.Forsyth g = addpt(g, tkmethod[tk->parent->type]->relpos(tk));
68437da2899SCharles.Forsyth tk = tk->parent;
68537da2899SCharles.Forsyth } else {
68637da2899SCharles.Forsyth g.x += tk->act.x;
68737da2899SCharles.Forsyth g.y += tk->act.y;
68837da2899SCharles.Forsyth tk = tk->master;
68937da2899SCharles.Forsyth }
69037da2899SCharles.Forsyth r = rectaddpt(r, g);
69137da2899SCharles.Forsyth p = addpt(p, g);
69237da2899SCharles.Forsyth }
69337da2899SCharles.Forsyth }
694