summaryrefslogtreecommitdiff
path: root/libtk/cwind.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libtk/cwind.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libtk/cwind.c')
-rw-r--r--libtk/cwind.c410
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;
+}