ref: 9f76a7f6819ac04552b4fb6588156f3e4089d1d7
dir: /libtk/cwind.c/
#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;
}