forsyth20121205-174063a80cc13 years agoHistory
438 lines · 7.1 KB · C
RawDownload
#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;}