#include "lib9.h"#include "draw.h"#include "tk.h"#include "canvs.h" #define O(t, e) ((long)(&((t*)0)->e)) /* Window Options (+ means implemented) +tags +width +height +window +anchor*/ staticTkOption windopts[] ={ "width", OPTdist, O(TkCwind, width), nil, "height", OPTdist, O(TkCwind, height), nil, "anchor", OPTstab, O(TkCwind, flags), tkanchor, "window", OPTwinp, O(TkCwind, sub), nil, nil}; staticTkOption itemopts[] ={ "tags", OPTctag, O(TkCitem, tags), nil, nil}; static voidtkcvswindsize(TkCitem *i){ Tk *s; int bw; Point p; TkGeom old; TkCwind *w; w = TKobj(TkCwind, i); s = w->sub; if(s == nil) return; if(w->width != s->act.width || w->height != s->act.height) { old = s->act; s->act.width = w->width; s->act.height = w->height; if(s->slave) { tkpackqit(s); tkrunpack(s->env->top); } tkdeliver(s, TkConfigure, &old); } p = tkcvsanchor(i->p.drawpt[0], s->act.width, s->act.height, w->flags); s->act.x = p.x; s->act.y = p.y; bw = 2*s->borderwidth; i->p.bb.min = p; i->p.bb.max.x = p.x + s->act.width + bw; i->p.bb.max.y = p.y + s->act.height + bw;} TkCitem*tkcvsfindwin(Tk *tk){ Tk *parent, *sub; TkCitem *i; TkCanvas *c; TkCwind *w; sub = tkfindsub(tk); if(sub == nil) return nil; parent = sub->parent; if(parent->type != TKcanvas) return nil; /* inconsistent */ c = TKobj(TkCanvas, parent); for(i = c->head; i != nil; i = i->next) { if(i->type == TkCVwindow) { w = TKobj(TkCwind, i); if(w->sub == sub) return i; } } return nil;} voidtkcvsforgetsub(Tk *sub, Tk *tk){ TkCwind *w; TkCitem *i; i = tkcvsfindwin(sub); if(i == nil) return; w = TKobj(TkCwind, i); if(w->focus == tk) {if(0)print("tkcsvsforget sub %p %q focus %p %q\n", sub, tkname(sub), tk, tkname(tk)); w->focus = nil; }} static voidtkcvswindgeom(Tk *sub, int x, int y, int w, int h){ TkCitem *i; Tk *parent; TkCanvas *c; TkCwind *win; USED(x); USED(y); parent = sub->parent; win = nil; c = TKobj(TkCanvas, parent); for(i = c->head; i; i = i->next) { if(i->type == TkCVwindow) { win = TKobj(TkCwind, i); if(win->sub == sub) break; } } tkbbmax(&c->update, &i->p.bb); if((win->flags & Tksetwidth) == 0) win->width = w; if ((win->flags & Tksetheight) == 0) win->height = h; sub->req.width = w; sub->req.height = h; tkcvswindsize(i); tkbbmax(&c->update, &i->p.bb); tkcvsdirty(parent);} static voidtkcvssubdestry(Tk *sub){ Tk *tk; TkCitem *i; TkCanvas *c; TkCwind *win; tk = sub->parent; if(tk == nil) return; if(0)print("tkcvssubdestry %p %q\n", sub, tkname(sub)); i = tkcvsfindwin(sub); if(i == nil) return; win = TKobj(TkCwind, i); if(win->sub != sub){ if(win->sub != nil) print("inconsistent tkcvssubdestry %p %q\n", sub, tkname(sub)); return; } c = TKobj(TkCanvas, tk); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); win->focus = nil; win->sub = nil; sub->parent = nil; sub->geom = nil;} Pointtkcvsrelpos(Tk *sub){ Tk *tk; TkCitem *i; TkCanvas *c; TkCwind *win; tk = sub->parent; if(tk == nil) return ZP; c = TKobj(TkCanvas, tk); for(i = c->head; i; i = i->next) { if(i->type == TkCVwindow) { win = TKobj(TkCwind, i); if(win->sub == sub) return subpt(i->p.bb.min, c->view); } } return ZP;} static char*tkcvswindchk(Tk *tk, TkCwind *w, Tk *oldsub){ Tk *sub; sub = w->sub; if (sub != oldsub) { w->sub = oldsub; if(sub == nil) return nil; if(sub->flag & Tkwindow) return TkIstop; if(sub->master != nil || sub->parent != nil) return TkWpack; if (oldsub != nil) { oldsub->parent = nil; oldsub->geom = nil; oldsub->destroyed = nil; } w->sub = sub; w->focus = nil; sub->parent = tk; tksetbits(w->sub, Tksubsub); sub->geom = tkcvswindgeom; sub->destroyed = tkcvssubdestry; if(w->width == 0) w->width = sub->req.width; if(w->height == 0) w->height = sub->req.height; } return nil;} char*tkcvswindcreat(Tk* tk, char *arg, char **val){ char *e; TkCwind *w; TkCitem *i; TkCanvas *c; TkOptab tko[3]; c = TKobj(TkCanvas, tk); i = tkcnewitem(tk, TkCVwindow, sizeof(TkCitem)+sizeof(TkCwind)); if(i == nil) return TkNomem; w = TKobj(TkCwind, i); w->flags = Tkcenter; e = tkparsepts(tk->env->top, &i->p, &arg, 0); if(e != nil) { tkcvsfreeitem(i); return e; } if(i->p.npoint != 1) { tkcvsfreeitem(i); return TkFewpt; } tko[0].ptr = w; tko[0].optab = windopts; tko[1].ptr = i; tko[1].optab = itemopts; tko[2].ptr = nil; e = tkparse(tk->env->top, arg, tko, nil); if(e != nil) { tkcvsfreeitem(i); return e; } e = tkcvswindchk(tk, w, nil); if(e != nil) { tkcvsfreeitem(i); return e; } e = tkcaddtag(tk, i, 1); if(e != nil) { tkcvsfreeitem(i); return e; } e = tkvalue(val, "%d", i->id); if(e != nil) { tkcvsfreeitem(i); return e; } tkcvsappend(c, i); tkcvswindsize(i); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); return nil;} char*tkcvswindcget(TkCitem *i, char *arg, char **val){ TkOptab tko[3]; TkCwind *w = TKobj(TkCwind, i); tko[0].ptr = w; tko[0].optab = windopts; tko[1].ptr = i; tko[1].optab = itemopts; tko[2].ptr = nil; return tkgencget(tko, arg, val, i->env->top);} char*tkcvswindconf(Tk *tk, TkCitem *i, char *arg){ char *e; int dx, dy; TkOptab tko[3]; TkCwind *w = TKobj(TkCwind, i); Tk *oldsub; tko[0].ptr = w; tko[0].optab = windopts; tko[1].ptr = i; tko[1].optab = itemopts; tko[2].ptr = nil; dx = w->width; dy = w->height; w->width = -1; w->height = -1; oldsub = w->sub; e = tkparse(tk->env->top, arg, tko, nil); if(e == nil) { e = tkcvswindchk(tk, w, oldsub); if(e != nil) return e; if(w->width == -1) w->width = dx; else w->flags |= Tksetwidth; if(w->height == -1) w->height = dy; else w->flags |= Tksetheight; tkcvswindsize(i); } else { w->width = dx; w->height = dy; } return e;} voidtkcvswindfree(TkCitem *i){ Tk *sub; TkCwind *w; w = TKobj(TkCwind, i); sub = w->sub; if(sub != nil) { sub->parent = nil; sub->geom = nil; sub->destroyed = nil; } w->focus = nil; w->sub = nil;} voidtkcvswinddraw(Image *img, TkCitem *i, TkEnv *pe){ TkCwind *w; Point rel; Rectangle r; Tk *sub; USED(img); /* See tkimageof */ USED(pe); w = TKobj(TkCwind, i); sub = w->sub; if(sub != nil) { int dirty; r = i->p.bb; rel.x = r.min.x + sub->borderwidth; rel.y = r.min.y + sub->borderwidth; if (rectclip(&r, img->clipr)) { sub->dirty = rectsubpt(r, rel); sub->flag |= Tkrefresh; tkdrawslaves(sub, ZP, &dirty); /* XXX - Tad: propagate err? */ } }} char*tkcvswindcoord(TkCitem *i, char *arg, int x, int y){ char *e; TkCpoints p;/* TkCwind *w; int xi, yi;*/ if(arg == nil) { tkxlatepts(i->p.parampt, i->p.npoint, x, y); tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y)); tkcvswindsize(i);/* w = TKobj(TkCwind, i); xi = TKF2I(x); yi = TKF2I(y); if (w->sub != nil) { w->sub->act.x += xi; w->sub->act.y += yi; } i->p.bb = rectaddpt(i->p.bb, Pt(xi, yi));*/ } else { e = tkparsepts(i->env->top, &p, &arg, 0); if(e != nil) return e; if(p.npoint != 1) { tkfreepoint(&p); return TkFewpt; } tkfreepoint(&i->p); i->p = p; tkcvswindsize(i); } return nil;}
#include "lib9.h"
#include "draw.h"
#include "tk.h"
#include "canvs.h"
#define O(t, e) ((long)(&((t*)0)->e))
/* Window Options (+ means implemented)
+tags
+width
+height
+window
+anchor
*/
static
TkOption windopts[] =
{
"width", OPTdist, O(TkCwind, width), nil,
"height", OPTdist, O(TkCwind, height), nil,
"anchor", OPTstab, O(TkCwind, flags), tkanchor,
"window", OPTwinp, O(TkCwind, sub), nil,
nil
};
static
TkOption itemopts[] =
{
"tags", OPTctag, O(TkCitem, tags), nil,
nil
};
static void
tkcvswindsize(TkCitem *i)
{
Tk *s;
int bw;
Point p;
TkGeom old;
TkCwind *w;
w = TKobj(TkCwind, i);
s = w->sub;
if(s == nil)
return;
if(w->width != s->act.width || w->height != s->act.height) {
old = s->act;
s->act.width = w->width;
s->act.height = w->height;
if(s->slave) {
tkpackqit(s);
tkrunpack(s->env->top);
}
tkdeliver(s, TkConfigure, &old);
}
p = tkcvsanchor(i->p.drawpt[0], s->act.width, s->act.height, w->flags);
s->act.x = p.x;
s->act.y = p.y;
bw = 2*s->borderwidth;
i->p.bb.min = p;
i->p.bb.max.x = p.x + s->act.width + bw;
i->p.bb.max.y = p.y + s->act.height + bw;
}
TkCitem*
tkcvsfindwin(Tk *tk)
{
Tk *parent, *sub;
TkCitem *i;
TkCanvas *c;
TkCwind *w;
sub = tkfindsub(tk);
if(sub == nil)
return nil;
parent = sub->parent;
if(parent->type != TKcanvas)
return nil; /* inconsistent */
c = TKobj(TkCanvas, parent);
for(i = c->head; i != nil; i = i->next) {
if(i->type == TkCVwindow) {
w = TKobj(TkCwind, i);
if(w->sub == sub)
return i;
}
}
return nil;
}
void
tkcvsforgetsub(Tk *sub, Tk *tk)
{
TkCwind *w;
TkCitem *i;
i = tkcvsfindwin(sub);
if(i == nil)
return;
w = TKobj(TkCwind, i);
if(w->focus == tk) {
if(0)print("tkcsvsforget sub %p %q focus %p %q\n", sub, tkname(sub), tk, tkname(tk));
w->focus = nil;
}
}
static void
tkcvswindgeom(Tk *sub, int x, int y, int w, int h)
{
TkCitem *i;
Tk *parent;
TkCanvas *c;
TkCwind *win;
USED(x);
USED(y);
parent = sub->parent;
win = nil;
c = TKobj(TkCanvas, parent);
for(i = c->head; i; i = i->next) {
if(i->type == TkCVwindow) {
win = TKobj(TkCwind, i);
if(win->sub == sub)
break;
}
}
tkbbmax(&c->update, &i->p.bb);
if((win->flags & Tksetwidth) == 0)
win->width = w;
if ((win->flags & Tksetheight) == 0)
win->height = h;
sub->req.width = w;
sub->req.height = h;
tkcvswindsize(i);
tkbbmax(&c->update, &i->p.bb);
tkcvsdirty(parent);
}
static void
tkcvssubdestry(Tk *sub)
{
Tk *tk;
TkCitem *i;
TkCanvas *c;
TkCwind *win;
tk = sub->parent;
if(tk == nil)
return;
if(0)print("tkcvssubdestry %p %q\n", sub, tkname(sub));
i = tkcvsfindwin(sub);
if(i == nil)
return;
win = TKobj(TkCwind, i);
if(win->sub != sub){
if(win->sub != nil)
print("inconsistent tkcvssubdestry %p %q\n", sub, tkname(sub));
return;
}
c = TKobj(TkCanvas, tk);
tkbbmax(&c->update, &i->p.bb);
tkcvssetdirty(tk);
win->focus = nil;
win->sub = nil;
sub->parent = nil;
sub->geom = nil;
}
Point
tkcvsrelpos(Tk *sub)
{
Tk *tk;
TkCitem *i;
TkCanvas *c;
TkCwind *win;
tk = sub->parent;
if(tk == nil)
return ZP;
c = TKobj(TkCanvas, tk);
for(i = c->head; i; i = i->next) {
if(i->type == TkCVwindow) {
win = TKobj(TkCwind, i);
if(win->sub == sub)
return subpt(i->p.bb.min, c->view);
}
}
return ZP;
}
static char*
tkcvswindchk(Tk *tk, TkCwind *w, Tk *oldsub)
{
Tk *sub;
sub = w->sub;
if (sub != oldsub) {
w->sub = oldsub;
if(sub == nil)
return nil;
if(sub->flag & Tkwindow)
return TkIstop;
if(sub->master != nil || sub->parent != nil)
return TkWpack;
if (oldsub != nil) {
oldsub->parent = nil;
oldsub->geom = nil;
oldsub->destroyed = nil;
}
w->sub = sub;
w->focus = nil;
sub->parent = tk;
tksetbits(w->sub, Tksubsub);
sub->geom = tkcvswindgeom;
sub->destroyed = tkcvssubdestry;
if(w->width == 0)
w->width = sub->req.width;
if(w->height == 0)
w->height = sub->req.height;
}
return nil;
}
char*
tkcvswindcreat(Tk* tk, char *arg, char **val)
{
char *e;
TkCwind *w;
TkCitem *i;
TkCanvas *c;
TkOptab tko[3];
c = TKobj(TkCanvas, tk);
i = tkcnewitem(tk, TkCVwindow, sizeof(TkCitem)+sizeof(TkCwind));
if(i == nil)
return TkNomem;
w = TKobj(TkCwind, i);
w->flags = Tkcenter;
e = tkparsepts(tk->env->top, &i->p, &arg, 0);
if(e != nil) {
tkcvsfreeitem(i);
return e;
}
if(i->p.npoint != 1) {
tkcvsfreeitem(i);
return TkFewpt;
}
tko[0].ptr = w;
tko[0].optab = windopts;
tko[1].ptr = i;
tko[1].optab = itemopts;
tko[2].ptr = nil;
e = tkparse(tk->env->top, arg, tko, nil);
if(e != nil) {
tkcvsfreeitem(i);
return e;
}
e = tkcvswindchk(tk, w, nil);
if(e != nil) {
tkcvsfreeitem(i);
return e;
}
e = tkcaddtag(tk, i, 1);
if(e != nil) {
tkcvsfreeitem(i);
return e;
}
e = tkvalue(val, "%d", i->id);
if(e != nil) {
tkcvsfreeitem(i);
return e;
}
tkcvsappend(c, i);
tkcvswindsize(i);
tkbbmax(&c->update, &i->p.bb);
tkcvssetdirty(tk);
return nil;
}
char*
tkcvswindcget(TkCitem *i, char *arg, char **val)
{
TkOptab tko[3];
TkCwind *w = TKobj(TkCwind, i);
tko[0].ptr = w;
tko[0].optab = windopts;
tko[1].ptr = i;
tko[1].optab = itemopts;
tko[2].ptr = nil;
return tkgencget(tko, arg, val, i->env->top);
}
char*
tkcvswindconf(Tk *tk, TkCitem *i, char *arg)
{
char *e;
int dx, dy;
TkOptab tko[3];
TkCwind *w = TKobj(TkCwind, i);
Tk *oldsub;
tko[0].ptr = w;
tko[0].optab = windopts;
tko[1].ptr = i;
tko[1].optab = itemopts;
tko[2].ptr = nil;
dx = w->width;
dy = w->height;
w->width = -1;
w->height = -1;
oldsub = w->sub;
e = tkparse(tk->env->top, arg, tko, nil);
if(e == nil) {
e = tkcvswindchk(tk, w, oldsub);
if(e != nil)
return e;
if(w->width == -1)
w->width = dx;
else
w->flags |= Tksetwidth;
if(w->height == -1)
w->height = dy;
else
w->flags |= Tksetheight;
tkcvswindsize(i);
} else {
w->width = dx;
w->height = dy;
}
return e;
}
void
tkcvswindfree(TkCitem *i)
{
Tk *sub;
TkCwind *w;
w = TKobj(TkCwind, i);
sub = w->sub;
if(sub != nil) {
sub->parent = nil;
sub->geom = nil;
sub->destroyed = nil;
}
w->focus = nil;
w->sub = nil;
}
void
tkcvswinddraw(Image *img, TkCitem *i, TkEnv *pe)
{
TkCwind *w;
Point rel;
Rectangle r;
Tk *sub;
USED(img); /* See tkimageof */
USED(pe);
w = TKobj(TkCwind, i);
sub = w->sub;
if(sub != nil) {
int dirty;
r = i->p.bb;
rel.x = r.min.x + sub->borderwidth;
rel.y = r.min.y + sub->borderwidth;
if (rectclip(&r, img->clipr)) {
sub->dirty = rectsubpt(r, rel);
sub->flag |= Tkrefresh;
tkdrawslaves(sub, ZP, &dirty); /* XXX - Tad: propagate err? */
}
}
}
char*
tkcvswindcoord(TkCitem *i, char *arg, int x, int y)
{
char *e;
TkCpoints p;
/*
TkCwind *w;
int xi, yi;
*/
if(arg == nil) {
tkxlatepts(i->p.parampt, i->p.npoint, x, y);
tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
tkcvswindsize(i);
/*
w = TKobj(TkCwind, i);
xi = TKF2I(x);
yi = TKF2I(y);
if (w->sub != nil) {
w->sub->act.x += xi;
w->sub->act.y += yi;
}
i->p.bb = rectaddpt(i->p.bb, Pt(xi, yi));
*/
}
else {
e = tkparsepts(i->env->top, &p, &arg, 0);
if(e != nil)
return e;
if(p.npoint != 1) {
tkfreepoint(&p);
return TkFewpt;
}
tkfreepoint(&i->p);
i->p = p;
tkcvswindsize(i);
}
return nil;
}