diff options
Diffstat (limited to 'libtk/cwind.c')
| -rw-r--r-- | libtk/cwind.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/libtk/cwind.c b/libtk/cwind.c new file mode 100644 index 00000000..dd25eb1b --- /dev/null +++ b/libtk/cwind.c @@ -0,0 +1,410 @@ +#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; +} + +static int +tkcvschkwfocus(TkCwind *w, Tk *tk) +{ + if(w->focus == tk) + return 1; + for(tk = tk->slave; tk; tk = tk->next) + if(tkcvschkwfocus(w, tk)) + return 1; + return 0; +} + +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; + } + } + + if(win->focus != nil) { + if(tkcvschkwfocus(win, sub) == 0) + win->focus = nil; + } + + 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; + + c = TKobj(TkCanvas, tk); + for(i = c->head; i; i = i->next) { + if(i->type == TkCVwindow) { + win = TKobj(TkCwind, i); + if(win->sub == sub) { + tkbbmax(&c->update, &i->p.bb); + tkcvssetdirty(tk); + + win->focus = nil; + win->sub = nil; + sub->parent = nil; + sub->geom = nil; + return; + } + } + } +} + +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(w->focus == sub) + w->focus = nil; + if(sub != nil) { + sub->parent = nil; + sub->geom = nil; + sub->destroyed = 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; +} |
