xref: /inferno-os/libtk/canvs.c (revision 5849851a19380dbb62a47d9c4d868a81e42fa79b)
137da2899SCharles.Forsyth #include <lib9.h>
237da2899SCharles.Forsyth #include <kernel.h>
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth #include "canvs.h"
637da2899SCharles.Forsyth 
737da2899SCharles.Forsyth /* Widget Commands (+ means implemented)
837da2899SCharles.Forsyth 	+addtag
937da2899SCharles.Forsyth 		except halo and start options of closest spec
1037da2899SCharles.Forsyth 	+bbox
1137da2899SCharles.Forsyth 	+bind
1237da2899SCharles.Forsyth 	+canvasx
1337da2899SCharles.Forsyth 	+canvasy
1437da2899SCharles.Forsyth 	+cget
1537da2899SCharles.Forsyth 	+configure
1637da2899SCharles.Forsyth 	+coords
1737da2899SCharles.Forsyth 	+create
1837da2899SCharles.Forsyth 	+dchars
1937da2899SCharles.Forsyth 	+delete
2037da2899SCharles.Forsyth 	+dtag
2137da2899SCharles.Forsyth 	+find
2237da2899SCharles.Forsyth 	+focus
2337da2899SCharles.Forsyth 	+gettags
2437da2899SCharles.Forsyth 	+icursor
2537da2899SCharles.Forsyth 	+index
2637da2899SCharles.Forsyth 	+insert
2737da2899SCharles.Forsyth 	+itemcget
2837da2899SCharles.Forsyth 	+itemconfigure
2937da2899SCharles.Forsyth 	+lower
3037da2899SCharles.Forsyth 	+move
3137da2899SCharles.Forsyth 	 postscript
3237da2899SCharles.Forsyth 	+raise
3337da2899SCharles.Forsyth 	+scale
3437da2899SCharles.Forsyth 	 scan
3537da2899SCharles.Forsyth 	+select
3637da2899SCharles.Forsyth 	+type
3737da2899SCharles.Forsyth 	+xview
3837da2899SCharles.Forsyth 	+yview
3937da2899SCharles.Forsyth */
4037da2899SCharles.Forsyth 
4137da2899SCharles.Forsyth static
4237da2899SCharles.Forsyth TkStab tkbuffer[] = {
4337da2899SCharles.Forsyth 	"visible",	TkCbufvisible,
4437da2899SCharles.Forsyth 	"all",		TkCbufall,
4537da2899SCharles.Forsyth 	"none",	TkCbufnone,
4637da2899SCharles.Forsyth 	"auto",	TkCbufauto,
4737da2899SCharles.Forsyth 
4837da2899SCharles.Forsyth 	/* backwards compatibility */
4937da2899SCharles.Forsyth 	"1",		TkCbufall,
5037da2899SCharles.Forsyth 	"yes",	TkCbufall,
5137da2899SCharles.Forsyth 	"off",		TkCbufall,
5237da2899SCharles.Forsyth 	"0",		TkCbufauto,
5337da2899SCharles.Forsyth 	"no",		TkCbufauto,
5437da2899SCharles.Forsyth 	"off",		TkCbufauto,
5537da2899SCharles.Forsyth 	nil
5637da2899SCharles.Forsyth };
5737da2899SCharles.Forsyth 
5837da2899SCharles.Forsyth #define	O(t, e)		((long)(&((t*)0)->e))
5937da2899SCharles.Forsyth #define OA(t, e)	((long)(((t*)0)->e))
6037da2899SCharles.Forsyth 
6137da2899SCharles.Forsyth static
6237da2899SCharles.Forsyth TkOption opts[] =
6337da2899SCharles.Forsyth {
6437da2899SCharles.Forsyth 	"closeenough",		OPTfrac,	O(TkCanvas, close),	nil,
6537da2899SCharles.Forsyth 	"confine",		OPTfrac,	O(TkCanvas, confine),	nil,
6637da2899SCharles.Forsyth 	"scrollregion",		OPTfrac,	OA(TkCanvas, scrollr),	IAUX(4),
6737da2899SCharles.Forsyth 	"xscrollincrement",	OPTfrac,	O(TkCanvas, xscrolli),	nil,
6837da2899SCharles.Forsyth 	"yscrollincrement",	OPTfrac,	O(TkCanvas, yscrolli),	nil,
6937da2899SCharles.Forsyth 	"xscrollcommand",	OPTtext,	O(TkCanvas, xscroll),	nil,
7037da2899SCharles.Forsyth 	"yscrollcommand",	OPTtext,	O(TkCanvas, yscroll),	nil,
7137da2899SCharles.Forsyth 	"width",		OPTnnfrac,	O(TkCanvas, width),	nil,
7237da2899SCharles.Forsyth 	"height",		OPTnnfrac,	O(TkCanvas, height),	nil,
7337da2899SCharles.Forsyth 	"buffer",		OPTstab,	O(TkCanvas, buffer),		tkbuffer,
7437da2899SCharles.Forsyth 	"buffered",		OPTstab,	O(TkCanvas, buffer),	tkbool,	/* backwards compatibility */
7537da2899SCharles.Forsyth 	"selectborderwidth",	OPTnndist, O(TkCanvas, sborderwidth), nil,
7637da2899SCharles.Forsyth 	nil
7737da2899SCharles.Forsyth };
7837da2899SCharles.Forsyth 
7937da2899SCharles.Forsyth int cvslshape[] = { TKI2F(8), TKI2F(10), TKI2F(3) };
8037da2899SCharles.Forsyth Rectangle	bbnil = { 1000000, 1000000, -1000000, -1000000 };
8137da2899SCharles.Forsyth Rectangle	huger = { -1000000, -1000000, 1000000, 1000000 };
8237da2899SCharles.Forsyth 
8337da2899SCharles.Forsyth static void tkcvsgeom(Tk *tk);
8437da2899SCharles.Forsyth 
8537da2899SCharles.Forsyth 
8637da2899SCharles.Forsyth static void
tkcvsf2i(Tk * tk,TkCanvas * tkc)8737da2899SCharles.Forsyth tkcvsf2i(Tk *tk, TkCanvas *tkc)
8837da2899SCharles.Forsyth {
8937da2899SCharles.Forsyth 	Rectangle r;
9037da2899SCharles.Forsyth 	tk->req.width = TKF2I(tkc->width);
9137da2899SCharles.Forsyth 	tk->req.height = TKF2I(tkc->height);
9237da2899SCharles.Forsyth 
9337da2899SCharles.Forsyth 	r.min.x = TKF2I(tkc->scrollr[0]);
9437da2899SCharles.Forsyth 	r.min.y = TKF2I(tkc->scrollr[1]);
9537da2899SCharles.Forsyth 	r.max.x = TKF2I(tkc->scrollr[2]);
9637da2899SCharles.Forsyth 	r.max.y = TKF2I(tkc->scrollr[3]);
9737da2899SCharles.Forsyth 
9837da2899SCharles.Forsyth 	/*
9937da2899SCharles.Forsyth 	 * make sure that the region is big enough to hold
10037da2899SCharles.Forsyth 	 * the actually displayed area
10137da2899SCharles.Forsyth 	 */
10237da2899SCharles.Forsyth 	if (Dx(r) < tk->act.width)
10337da2899SCharles.Forsyth 		r.max.x = r.min.x + tk->act.width;
10437da2899SCharles.Forsyth 	if (Dy(r) < tk->act.height)
10537da2899SCharles.Forsyth 		r.max.y = r.min.y + tk->act.height;
10637da2899SCharles.Forsyth 	tkc->region = r;
10737da2899SCharles.Forsyth 
10837da2899SCharles.Forsyth 	/*
10937da2899SCharles.Forsyth 	 * make sure that the view origin is at a valid
11037da2899SCharles.Forsyth 	 * position with respect to the scroll region.
11137da2899SCharles.Forsyth 	 */
11237da2899SCharles.Forsyth 	if (tkc->view.x + tk->act.width > r.max.x)
11337da2899SCharles.Forsyth 		tkc->view.x = r.max.x - tk->act.width;
11437da2899SCharles.Forsyth 	if (tkc->view.x < r.min.x)
11537da2899SCharles.Forsyth 		tkc->view.x = r.min.x;
11637da2899SCharles.Forsyth 
11737da2899SCharles.Forsyth 	if (tkc->view.y + tk->act.height > r.max.y)
11837da2899SCharles.Forsyth 		tkc->view.y = r.max.y - tk->act.height;
11937da2899SCharles.Forsyth 	if (tkc->view.y < r.min.y)
12037da2899SCharles.Forsyth 		tkc->view.y = r.min.y;
12137da2899SCharles.Forsyth 
12237da2899SCharles.Forsyth }
12337da2899SCharles.Forsyth 
12437da2899SCharles.Forsyth char*
tkcanvas(TkTop * t,char * arg,char ** ret)12537da2899SCharles.Forsyth tkcanvas(TkTop *t, char *arg, char **ret)
12637da2899SCharles.Forsyth {
12737da2899SCharles.Forsyth 	Tk *tk;
12837da2899SCharles.Forsyth 	char *e;
12937da2899SCharles.Forsyth 	TkCanvas *tkc;
13037da2899SCharles.Forsyth 	TkName *names;
13137da2899SCharles.Forsyth 	TkOptab tko[3];
13237da2899SCharles.Forsyth 
13337da2899SCharles.Forsyth 	tk = tknewobj(t, TKcanvas, sizeof(Tk)+sizeof(TkCanvas));
13437da2899SCharles.Forsyth 	if(tk == nil)
13537da2899SCharles.Forsyth 		return TkNomem;
13637da2899SCharles.Forsyth 
13737da2899SCharles.Forsyth 	tkc = TKobj(TkCanvas, tk);
13837da2899SCharles.Forsyth 	tkc->close = TKI2F(1);
13937da2899SCharles.Forsyth 	tkc->xscrolli = TKI2F(1);
14037da2899SCharles.Forsyth 	tkc->yscrolli = TKI2F(1);
14137da2899SCharles.Forsyth 	tkc->width = TKI2F(360);
14237da2899SCharles.Forsyth 	tkc->height = TKI2F(270);
14337da2899SCharles.Forsyth 	tkc->actions = 0;
14437da2899SCharles.Forsyth 	tkc->actlim = Tksweep;
14537da2899SCharles.Forsyth 	tkc->mask = nil;
14637da2899SCharles.Forsyth 	tkc->sborderwidth = 1;
14737da2899SCharles.Forsyth 
14837da2899SCharles.Forsyth 	tko[0].ptr = tkc;
14937da2899SCharles.Forsyth 	tko[0].optab = opts;
15037da2899SCharles.Forsyth 	tko[1].ptr = tk;
15137da2899SCharles.Forsyth 	tko[1].optab = tkgeneric;
15237da2899SCharles.Forsyth 	tko[2].ptr = nil;
15337da2899SCharles.Forsyth 
15437da2899SCharles.Forsyth 	names = nil;
15537da2899SCharles.Forsyth 	e = tkparse(t, arg, tko, &names);
15637da2899SCharles.Forsyth 	if(e != nil)
15737da2899SCharles.Forsyth 		goto err;
15837da2899SCharles.Forsyth 	if(names == nil) {
15937da2899SCharles.Forsyth 		/* tkerr(t, arg); XXX */
16037da2899SCharles.Forsyth 		e = TkBadwp;
16137da2899SCharles.Forsyth 		goto err;
16237da2899SCharles.Forsyth 	}
16337da2899SCharles.Forsyth 
16437da2899SCharles.Forsyth 	tkc->current = tkmkname("current");
16537da2899SCharles.Forsyth 	if(tkc->current == nil) {
16637da2899SCharles.Forsyth 		e = TkNomem;
16737da2899SCharles.Forsyth 		goto err;
16837da2899SCharles.Forsyth 	}
16937da2899SCharles.Forsyth 
17037da2899SCharles.Forsyth 	tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
17137da2899SCharles.Forsyth 	tkcvsf2i(tk, tkc);
17237da2899SCharles.Forsyth 
17337da2899SCharles.Forsyth 	e = tkaddchild(t, tk, &names);
17437da2899SCharles.Forsyth 	tkfreename(names);
17537da2899SCharles.Forsyth 	if(e != nil) {
17637da2899SCharles.Forsyth 		tkfreename(tkc->current);
17737da2899SCharles.Forsyth 		tkc->current = nil;
17837da2899SCharles.Forsyth 		goto err;
17937da2899SCharles.Forsyth 	}
18037da2899SCharles.Forsyth 	tk->name->link = nil;
18137da2899SCharles.Forsyth 
18237da2899SCharles.Forsyth 	e = tkvalue(ret, "%s", tk->name->name);
18337da2899SCharles.Forsyth 	if(e == nil)
18437da2899SCharles.Forsyth 	        return nil;
18537da2899SCharles.Forsyth 
18637da2899SCharles.Forsyth 	tkfreename(tkc->current);
18737da2899SCharles.Forsyth 	return e;
18837da2899SCharles.Forsyth err:
18937da2899SCharles.Forsyth 	tkfreeobj(tk);
19037da2899SCharles.Forsyth 	return e;
19137da2899SCharles.Forsyth }
19237da2899SCharles.Forsyth 
19337da2899SCharles.Forsyth void
tkcvsdirty(Tk * sub)19437da2899SCharles.Forsyth tkcvsdirty(Tk *sub)
19537da2899SCharles.Forsyth {
19637da2899SCharles.Forsyth 	TkCanvas *c;
19737da2899SCharles.Forsyth 	Tk *tk, *parent;
19837da2899SCharles.Forsyth 	Rectangle r;
19937da2899SCharles.Forsyth 	Point rel;
20037da2899SCharles.Forsyth 
20137da2899SCharles.Forsyth 	rel = ZP;
20237da2899SCharles.Forsyth 	for(tk = sub; tk;  tk = tk->master) {
20337da2899SCharles.Forsyth 		rel.x += tk->borderwidth + tk->act.x;
20437da2899SCharles.Forsyth 		rel.y += tk->borderwidth + tk->act.y;
20537da2899SCharles.Forsyth 		if (tk->parent != nil)
20637da2899SCharles.Forsyth 			break;
20737da2899SCharles.Forsyth 	}
20837da2899SCharles.Forsyth 	if (tk == nil)
20937da2899SCharles.Forsyth 		return;
21037da2899SCharles.Forsyth 	parent = tk->parent;
21137da2899SCharles.Forsyth 	c = TKobj(TkCanvas, parent);
21237da2899SCharles.Forsyth 	r = rectaddpt(sub->dirty, rel);
21337da2899SCharles.Forsyth 	tkbbmax(&c->update, &r);
21437da2899SCharles.Forsyth 	tkcvssetdirty(parent);
21537da2899SCharles.Forsyth }
21637da2899SCharles.Forsyth 
21737da2899SCharles.Forsyth static void
tkcvsfocusorder(Tk * tk)21837da2899SCharles.Forsyth tkcvsfocusorder(Tk *tk)
21937da2899SCharles.Forsyth {
22037da2899SCharles.Forsyth 	TkCanvas *tkc = TKobj(TkCanvas, tk);
22137da2899SCharles.Forsyth 	TkCwind *win;
22237da2899SCharles.Forsyth 	TkCitem *it;
22337da2899SCharles.Forsyth 	TkWinfo *inf;
22437da2899SCharles.Forsyth 	int i, n;
22537da2899SCharles.Forsyth 
22637da2899SCharles.Forsyth 	n = 0;
22737da2899SCharles.Forsyth 	for (it = tkc->head; it != nil; it = it->next) {
22837da2899SCharles.Forsyth 		if (it->type == TkCVwindow) {
22937da2899SCharles.Forsyth 			win = TKobj(TkCwind, it);
23037da2899SCharles.Forsyth 			if (win->sub != nil)
23137da2899SCharles.Forsyth 				n++;
23237da2899SCharles.Forsyth 		}
23337da2899SCharles.Forsyth 	}
23437da2899SCharles.Forsyth 	if (n == 0)
23537da2899SCharles.Forsyth 		return;
23637da2899SCharles.Forsyth 
23737da2899SCharles.Forsyth 	inf = malloc(sizeof(*inf) * n);
23837da2899SCharles.Forsyth 	if (inf == nil)
23937da2899SCharles.Forsyth 		return;
24037da2899SCharles.Forsyth 
24137da2899SCharles.Forsyth 	i = 0;
24237da2899SCharles.Forsyth 	for (it = tkc->head; it != nil; it = it->next) {
24337da2899SCharles.Forsyth 		if (it->type == TkCVwindow) {
24437da2899SCharles.Forsyth 			win = TKobj(TkCwind, it);
24537da2899SCharles.Forsyth 			if (win->sub != nil) {
24637da2899SCharles.Forsyth 				inf[i].w = win->sub;
24737da2899SCharles.Forsyth 				inf[i].r = it->p.bb;
24837da2899SCharles.Forsyth 				i++;
24937da2899SCharles.Forsyth 			}
25037da2899SCharles.Forsyth 		}
25137da2899SCharles.Forsyth 	}
25237da2899SCharles.Forsyth 
25337da2899SCharles.Forsyth 	tksortfocusorder(inf, n);
25437da2899SCharles.Forsyth 	for (i = 0; i < n; i++)
25537da2899SCharles.Forsyth 		tkappendfocusorder(inf[i].w);
25637da2899SCharles.Forsyth }
25737da2899SCharles.Forsyth 
25837da2899SCharles.Forsyth static char*
tkcvscget(Tk * tk,char * arg,char ** val)25937da2899SCharles.Forsyth tkcvscget(Tk *tk, char *arg, char **val)
26037da2899SCharles.Forsyth {
26137da2899SCharles.Forsyth 	TkOptab tko[3];
26237da2899SCharles.Forsyth 	TkCanvas *tkc = TKobj(TkCanvas, tk);
26337da2899SCharles.Forsyth 
26437da2899SCharles.Forsyth 	tko[0].ptr = tkc;
26537da2899SCharles.Forsyth 	tko[0].optab = opts;
26637da2899SCharles.Forsyth 	tko[1].ptr = tk;
26737da2899SCharles.Forsyth 	tko[1].optab = tkgeneric;
26837da2899SCharles.Forsyth 	tko[2].ptr = nil;
26937da2899SCharles.Forsyth 
27037da2899SCharles.Forsyth 	return tkgencget(tko, arg, val, tk->env->top);
27137da2899SCharles.Forsyth }
27237da2899SCharles.Forsyth 
27337da2899SCharles.Forsyth static char*
tkcvsconf(Tk * tk,char * arg,char ** val)27437da2899SCharles.Forsyth tkcvsconf(Tk *tk, char *arg, char **val)
27537da2899SCharles.Forsyth {
27637da2899SCharles.Forsyth 	char *e;
27737da2899SCharles.Forsyth 	int bd;
27837da2899SCharles.Forsyth 	TkGeom g;
27937da2899SCharles.Forsyth 	Rectangle r;
28037da2899SCharles.Forsyth 	TkOptab tko[3];
28137da2899SCharles.Forsyth 	TkCanvas *c = TKobj(TkCanvas, tk);
28237da2899SCharles.Forsyth 
28337da2899SCharles.Forsyth 	tko[0].ptr = c;
28437da2899SCharles.Forsyth 	tko[0].optab = opts;
28537da2899SCharles.Forsyth 	tko[1].ptr = tk;
28637da2899SCharles.Forsyth 	tko[1].optab = tkgeneric;
28737da2899SCharles.Forsyth 	tko[2].ptr = nil;
28837da2899SCharles.Forsyth 
28937da2899SCharles.Forsyth 	if(*arg == '\0')
29037da2899SCharles.Forsyth 		return tkconflist(tko, val);
29137da2899SCharles.Forsyth 
29237da2899SCharles.Forsyth 	r.min = c->view;
29337da2899SCharles.Forsyth 	r.max.x = r.min.x+tk->act.width;
29437da2899SCharles.Forsyth 	r.max.y = r.min.y+tk->act.height;
29537da2899SCharles.Forsyth 	tkbbmax(&c->update, &r);
29637da2899SCharles.Forsyth 	tkbbmax(&c->update, &c->region);
29737da2899SCharles.Forsyth 
29837da2899SCharles.Forsyth 	bd = tk->borderwidth;
29937da2899SCharles.Forsyth 	g = tk->req;
30037da2899SCharles.Forsyth 	e = tkparse(tk->env->top, arg, tko, nil);
30137da2899SCharles.Forsyth 	if(e != nil)
30237da2899SCharles.Forsyth 		return e;
30337da2899SCharles.Forsyth 	tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
30437da2899SCharles.Forsyth 
30537da2899SCharles.Forsyth 	tkcvsf2i(tk, c);
30637da2899SCharles.Forsyth 
30737da2899SCharles.Forsyth 	tkcvsgeom(tk);
30837da2899SCharles.Forsyth 	tkgeomchg(tk, &g, bd);
30937da2899SCharles.Forsyth 	tkbbmax(&c->update, &c->region);
31037da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 1);
31137da2899SCharles.Forsyth 	return nil;
31237da2899SCharles.Forsyth }
31337da2899SCharles.Forsyth 
31437da2899SCharles.Forsyth void
tkcvsfreeitem(TkCitem * i)31537da2899SCharles.Forsyth tkcvsfreeitem(TkCitem *i)
31637da2899SCharles.Forsyth {
31737da2899SCharles.Forsyth 	int locked;
31837da2899SCharles.Forsyth 	Display *d;
31937da2899SCharles.Forsyth 
32037da2899SCharles.Forsyth 	d = i->env->top->display;
32137da2899SCharles.Forsyth 
32237da2899SCharles.Forsyth 	locked = lockdisplay(d);
32337da2899SCharles.Forsyth 	tkcimethod[i->type].free(i);
32437da2899SCharles.Forsyth 	if(locked)
32537da2899SCharles.Forsyth 		unlockdisplay(d);
32637da2899SCharles.Forsyth 
32737da2899SCharles.Forsyth 	tkfreepoint(&i->p);
32837da2899SCharles.Forsyth 	tkputenv(i->env);
32937da2899SCharles.Forsyth 	free(i);
33037da2899SCharles.Forsyth }
33137da2899SCharles.Forsyth 
33237da2899SCharles.Forsyth void
tkfreecanv(Tk * tk)33337da2899SCharles.Forsyth tkfreecanv(Tk *tk)
33437da2899SCharles.Forsyth {
33537da2899SCharles.Forsyth 	Display *d;
33637da2899SCharles.Forsyth 	int j, locked;
33737da2899SCharles.Forsyth 	TkCanvas *c;
33837da2899SCharles.Forsyth 	TkName *n, *nn;
33937da2899SCharles.Forsyth 	TkCtag *t, *tt;
34037da2899SCharles.Forsyth 	TkCitem *i, *next;
34137da2899SCharles.Forsyth 
34237da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
34337da2899SCharles.Forsyth 	for(i = c->head; i; i = next) {
34437da2899SCharles.Forsyth 		next = i->next;
34537da2899SCharles.Forsyth 		tkcvsfreeitem(i);
34637da2899SCharles.Forsyth 	}
34737da2899SCharles.Forsyth 
34837da2899SCharles.Forsyth 	if(c->xscroll != nil)
34937da2899SCharles.Forsyth 		free(c->xscroll);
35037da2899SCharles.Forsyth 	if(c->yscroll != nil)
35137da2899SCharles.Forsyth 		free(c->yscroll);
35237da2899SCharles.Forsyth 
35337da2899SCharles.Forsyth 	for(j = 0; j < TkChash; j++) {
35437da2899SCharles.Forsyth 		for(n = c->thash[j]; n; n = nn) {
35537da2899SCharles.Forsyth 			nn = n->link;
35637da2899SCharles.Forsyth 			for(t = n->obj; t; t = tt) {
35737da2899SCharles.Forsyth 				tt = t->taglist;
35837da2899SCharles.Forsyth 				free(t);
35937da2899SCharles.Forsyth 			}
36037da2899SCharles.Forsyth 			tkfreebind(n->prop.binds);
36137da2899SCharles.Forsyth 			free(n);
36237da2899SCharles.Forsyth 		}
36337da2899SCharles.Forsyth 	}
36437da2899SCharles.Forsyth 
36537da2899SCharles.Forsyth 	free(c->current);
36637da2899SCharles.Forsyth 
36737da2899SCharles.Forsyth 	if((c->ialloc && c->image != nil) || c->mask != nil) {
36837da2899SCharles.Forsyth 		if (c->ialloc && c->image != nil)
36937da2899SCharles.Forsyth 			d = c->image->display;
37037da2899SCharles.Forsyth 		else
37137da2899SCharles.Forsyth 			d = c->mask->display;
37237da2899SCharles.Forsyth 		locked = lockdisplay(d);
37337da2899SCharles.Forsyth 		if (c->image != nil && c->ialloc)
37437da2899SCharles.Forsyth 			freeimage(c->image);
37537da2899SCharles.Forsyth 		if (c->mask != nil)
37637da2899SCharles.Forsyth 			freeimage(c->mask);
37737da2899SCharles.Forsyth 		if(locked)
37837da2899SCharles.Forsyth 			unlockdisplay(d);
37937da2899SCharles.Forsyth 	}
38037da2899SCharles.Forsyth }
38137da2899SCharles.Forsyth 
38237da2899SCharles.Forsyth char*
tkdrawcanv(Tk * tk,Point orig)38337da2899SCharles.Forsyth tkdrawcanv(Tk *tk, Point orig)
38437da2899SCharles.Forsyth {
38537da2899SCharles.Forsyth 	Image *dst;
38637da2899SCharles.Forsyth 	TkCitem *i;
38737da2899SCharles.Forsyth 	Display *d;
38837da2899SCharles.Forsyth 	TkCanvas *c;
38937da2899SCharles.Forsyth 	Rectangle r, bufr, oclipr;
39037da2899SCharles.Forsyth 	int vis, alpha, buffer;
39137da2899SCharles.Forsyth 	Point rel, p;
39237da2899SCharles.Forsyth 	TkCimeth *imeth;
39337da2899SCharles.Forsyth 
39437da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
39537da2899SCharles.Forsyth 	d = tk->env->top->display;
39637da2899SCharles.Forsyth 	dst = tkimageof(tk);
39737da2899SCharles.Forsyth 	/*
39837da2899SCharles.Forsyth 	 * translation from local to screen coords
39937da2899SCharles.Forsyth 	 */
40037da2899SCharles.Forsyth 	rel.x = orig.x + tk->act.x + tk->borderwidth;
40137da2899SCharles.Forsyth 	rel.y = orig.y + tk->act.y + tk->borderwidth;
40237da2899SCharles.Forsyth 
40337da2899SCharles.Forsyth 	buffer = c->buffer;
40437da2899SCharles.Forsyth 	if (buffer == TkCbufauto)
40537da2899SCharles.Forsyth 		buffer = TkCbufvisible;
40637da2899SCharles.Forsyth /*		buffer = (dst == TKobj(TkWin, tk->env->top->root)->image) ? TkCbufvisible : TkCbufnone; */
40737da2899SCharles.Forsyth 
40837da2899SCharles.Forsyth 	if (buffer == TkCbufnone) {
40937da2899SCharles.Forsyth 		if(c->image != nil && c->ialloc)
41037da2899SCharles.Forsyth 			freeimage(c->image);
41137da2899SCharles.Forsyth 		c->image = dst;
41237da2899SCharles.Forsyth 		c->ialloc = 0;
41337da2899SCharles.Forsyth 
41437da2899SCharles.Forsyth 		r = tkrect(tk, 0);
41537da2899SCharles.Forsyth 		bufr = r;
41637da2899SCharles.Forsyth 		rectclip(&bufr, tk->dirty);
41737da2899SCharles.Forsyth 		oclipr = dst->clipr;
41837da2899SCharles.Forsyth 
41937da2899SCharles.Forsyth 		replclipr(dst, 0, rectaddpt(bufr, rel));
42037da2899SCharles.Forsyth 		draw(dst, rectaddpt(bufr, rel), tkgc(tk->env, TkCbackgnd), nil, ZP);
42137da2899SCharles.Forsyth 
42237da2899SCharles.Forsyth 		p = subpt(rel, c->view);
42337da2899SCharles.Forsyth 		p.x = TKI2F(p.x);
42437da2899SCharles.Forsyth 		p.y = TKI2F(p.y);
42537da2899SCharles.Forsyth 		bufr = rectaddpt(bufr, c->view);
42637da2899SCharles.Forsyth 		for(i = c->head; i; i = i->next) {
42737da2899SCharles.Forsyth 			if(rectXrect(i->p.bb, bufr)) {
42837da2899SCharles.Forsyth 				imeth = &tkcimethod[i->type];
42937da2899SCharles.Forsyth 				imeth->coord(i, nil, p.x, p.y);
43037da2899SCharles.Forsyth 				imeth->draw(dst, i, tk->env);
43137da2899SCharles.Forsyth 				imeth->coord(i, nil, -p.x, -p.y);
43237da2899SCharles.Forsyth 			}
43337da2899SCharles.Forsyth 		}
43437da2899SCharles.Forsyth 		replclipr(dst, 0, oclipr);
43537da2899SCharles.Forsyth 	} else {
43637da2899SCharles.Forsyth 		if (c->buffer == TkCbufall)
43737da2899SCharles.Forsyth 			bufr = c->region;
43837da2899SCharles.Forsyth 		else {
43937da2899SCharles.Forsyth 			bufr.min = c->view;
44037da2899SCharles.Forsyth 			bufr.max.x = c->view.x + tk->act.width;
44137da2899SCharles.Forsyth 			bufr.max.y = c->view.y + tk->act.height;
44237da2899SCharles.Forsyth 		}
44337da2899SCharles.Forsyth 		alpha = (tk->env->colors[TkCbackgnd] & 0xff) != 0xff;
44437da2899SCharles.Forsyth 		if(c->image == nil || eqrect(bufr, c->image->r) == 0) {
44537da2899SCharles.Forsyth 			if(c->image != nil && c->ialloc)
44637da2899SCharles.Forsyth 				freeimage(c->image);
44737da2899SCharles.Forsyth 			c->image = allocimage(d, bufr, alpha?RGBA32:d->image->chan, 0, tk->env->colors[TkCbackgnd]);
44837da2899SCharles.Forsyth 			c->ialloc = 1;
44937da2899SCharles.Forsyth 			c->update = bufr;
45037da2899SCharles.Forsyth 			tkcvssetdirty(tk);		/* unnecessary? */
45137da2899SCharles.Forsyth 		}
45237da2899SCharles.Forsyth 
45337da2899SCharles.Forsyth 		if(c->image == nil)
45437da2899SCharles.Forsyth 			return nil;
45537da2899SCharles.Forsyth 
45637da2899SCharles.Forsyth 		r = c->update;
45737da2899SCharles.Forsyth 		if (rectclip(&r, c->image->r)) {
45837da2899SCharles.Forsyth 			if (alpha)
45937da2899SCharles.Forsyth 				drawop(c->image, c->update, nil, nil, ZP, Clear);
46037da2899SCharles.Forsyth 			draw(c->image, c->update, tkgc(tk->env, TkCbackgnd), nil, c->view);
46137da2899SCharles.Forsyth 			replclipr(c->image, 0, r);
46237da2899SCharles.Forsyth 			for(i = c->head; i; i = i->next) {
46337da2899SCharles.Forsyth 				if(rectXrect(i->p.bb, r))
46437da2899SCharles.Forsyth 					tkcimethod[i->type].draw(c->image, i, tk->env);
46537da2899SCharles.Forsyth 			}
46637da2899SCharles.Forsyth 			replclipr(c->image, 0, c->image->r);
46737da2899SCharles.Forsyth 		}
46837da2899SCharles.Forsyth 		/*
46937da2899SCharles.Forsyth 		 * if the visible area of the canvas image doesn't
47037da2899SCharles.Forsyth 		 * fit completely within the dirty rectangle,
47137da2899SCharles.Forsyth 		 * then we'll need to draw the background behind it
47237da2899SCharles.Forsyth 		 */
47337da2899SCharles.Forsyth 		r = tkrect(tk, 0);
47437da2899SCharles.Forsyth 		bufr = rectsubpt(bufr, c->view);
47537da2899SCharles.Forsyth 		vis = rectclip(&bufr, tkrect(tk, 0));
47637da2899SCharles.Forsyth 
47737da2899SCharles.Forsyth 		if (!vis || !rectinrect(tk->dirty, bufr))
47837da2899SCharles.Forsyth 			draw(dst, rectaddpt(tk->dirty, rel), tkgc(tk->env, TkCbackgnd), nil, c->view);
47937da2899SCharles.Forsyth 
48037da2899SCharles.Forsyth 		if (vis && rectclip(&bufr, tk->dirty))
48137da2899SCharles.Forsyth 			draw(dst, rectaddpt(bufr, rel), c->image, nil, addpt(bufr.min, c->view));
48237da2899SCharles.Forsyth 	}
48337da2899SCharles.Forsyth 
48437da2899SCharles.Forsyth 
48537da2899SCharles.Forsyth 	/*
48637da2899SCharles.Forsyth 	 * if the border is dirty too, then draw that
48737da2899SCharles.Forsyth 	 */
48837da2899SCharles.Forsyth 	if (!rectinrect(tk->dirty, bufr)) {
48937da2899SCharles.Forsyth 		r.min = addpt(r.min, rel);
49037da2899SCharles.Forsyth 		r.min.x -= tk->borderwidth;
49137da2899SCharles.Forsyth 		r.min.y -= tk->borderwidth;
49237da2899SCharles.Forsyth 		tkdrawrelief(dst, tk, r.min, TkCbackgnd, tk->relief);
49337da2899SCharles.Forsyth 	}
49437da2899SCharles.Forsyth 	c->update = bbnil;
49537da2899SCharles.Forsyth 	return nil;
49637da2899SCharles.Forsyth }
49737da2899SCharles.Forsyth 
49837da2899SCharles.Forsyth void
tkcvsappend(TkCanvas * c,TkCitem * i)49937da2899SCharles.Forsyth tkcvsappend(TkCanvas *c, TkCitem *i)
50037da2899SCharles.Forsyth {
50137da2899SCharles.Forsyth 	if(c->head == nil)
50237da2899SCharles.Forsyth 		c->head = i;
50337da2899SCharles.Forsyth 	else
50437da2899SCharles.Forsyth 		c->tail->next = i;
50537da2899SCharles.Forsyth 	c->tail = i;
50637da2899SCharles.Forsyth }
50737da2899SCharles.Forsyth 
50837da2899SCharles.Forsyth void
tkcvssv(Tk * tk)50937da2899SCharles.Forsyth tkcvssv(Tk *tk)
51037da2899SCharles.Forsyth {
51137da2899SCharles.Forsyth 	TkCanvas *c;
51237da2899SCharles.Forsyth 	int top, bot, height;
51337da2899SCharles.Forsyth 	char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
51437da2899SCharles.Forsyth 
51537da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
51637da2899SCharles.Forsyth 	if(c->yscroll == nil)
51737da2899SCharles.Forsyth 		return;
51837da2899SCharles.Forsyth 
51937da2899SCharles.Forsyth 	top = 0;
52037da2899SCharles.Forsyth 	bot = TKI2F(1);
52137da2899SCharles.Forsyth 
52237da2899SCharles.Forsyth 	height = Dy(c->region);
52337da2899SCharles.Forsyth 	if(height != 0) {
52437da2899SCharles.Forsyth 		top = TKI2F(c->view.y)/height;
52537da2899SCharles.Forsyth 		bot = TKI2F(c->view.y+tk->act.height)/height;
52637da2899SCharles.Forsyth 	}
52737da2899SCharles.Forsyth 
52837da2899SCharles.Forsyth 	v = tkfprint(val, top);
52937da2899SCharles.Forsyth 	*v++ = ' ';
53037da2899SCharles.Forsyth 	tkfprint(v, bot);
53137da2899SCharles.Forsyth 	snprint(cmd, sizeof(cmd), "%s %s", c->yscroll, val);
53237da2899SCharles.Forsyth 	e = tkexec(tk->env->top, cmd, nil);
53337da2899SCharles.Forsyth 	if ((e != nil) && (tk->name != nil))
53437da2899SCharles.Forsyth 		print("tk: yscrollcommand \"%s\": %s\n", tk->name->name, e);
53537da2899SCharles.Forsyth }
53637da2899SCharles.Forsyth 
53737da2899SCharles.Forsyth void
tkcvssh(Tk * tk)53837da2899SCharles.Forsyth tkcvssh(Tk *tk)
53937da2899SCharles.Forsyth {
54037da2899SCharles.Forsyth 	int top, bot, width;
54137da2899SCharles.Forsyth 	TkCanvas *c = TKobj(TkCanvas, tk);
54237da2899SCharles.Forsyth 	char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
54337da2899SCharles.Forsyth 
54437da2899SCharles.Forsyth 	if(c->xscroll == nil)
54537da2899SCharles.Forsyth 		return;
54637da2899SCharles.Forsyth 
54737da2899SCharles.Forsyth 	top = 0;
54837da2899SCharles.Forsyth 	bot = TKI2F(1);
54937da2899SCharles.Forsyth 
55037da2899SCharles.Forsyth 	width = Dx(c->region);
55137da2899SCharles.Forsyth 	if(width != 0) {
55237da2899SCharles.Forsyth 		top = TKI2F(c->view.x)/width;
55337da2899SCharles.Forsyth 		bot = TKI2F(c->view.x+tk->act.width)/width;
55437da2899SCharles.Forsyth 	}
55537da2899SCharles.Forsyth 
55637da2899SCharles.Forsyth 	v = tkfprint(val, top);
55737da2899SCharles.Forsyth 	*v++ = ' ';
55837da2899SCharles.Forsyth 	tkfprint(v, bot);
55937da2899SCharles.Forsyth 	snprint(cmd, sizeof(cmd), "%s %s", c->xscroll, val);
56037da2899SCharles.Forsyth 	e = tkexec(tk->env->top, cmd, nil);
56137da2899SCharles.Forsyth 	if ((e != nil) && (tk->name != nil))
56237da2899SCharles.Forsyth 		print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e);
56337da2899SCharles.Forsyth }
56437da2899SCharles.Forsyth 
56537da2899SCharles.Forsyth static void
tkcvsgeom(Tk * tk)56637da2899SCharles.Forsyth tkcvsgeom(Tk *tk)
56737da2899SCharles.Forsyth {
56837da2899SCharles.Forsyth 	TkCanvas *c;
56937da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
57037da2899SCharles.Forsyth 
57137da2899SCharles.Forsyth 	tkcvsf2i(tk, c);
57237da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 1);
57337da2899SCharles.Forsyth 	c->update = c->region;
57437da2899SCharles.Forsyth 
57537da2899SCharles.Forsyth 	tkcvssv(tk);
57637da2899SCharles.Forsyth 	tkcvssh(tk);
57737da2899SCharles.Forsyth }
57837da2899SCharles.Forsyth 
57937da2899SCharles.Forsyth char*
tkcvstags(Tk * tk,char * arg,char ** val,int af)58037da2899SCharles.Forsyth tkcvstags(Tk *tk, char *arg, char **val, int af)
58137da2899SCharles.Forsyth {
58237da2899SCharles.Forsyth 	TkTop *o;
58337da2899SCharles.Forsyth 	int x, y;
58437da2899SCharles.Forsyth 	TkName *f;
58537da2899SCharles.Forsyth 	TkCtag *t, *tt;
58637da2899SCharles.Forsyth 	char *fmt;
58737da2899SCharles.Forsyth 	TkCpoints p;
58837da2899SCharles.Forsyth 	TkCanvas *c;
58937da2899SCharles.Forsyth 	TkCitem *i, *b;
59037da2899SCharles.Forsyth 	int d, dist, dx, dy;
59137da2899SCharles.Forsyth 	char tag[Tkmaxitem], buf[Tkmaxitem];
59237da2899SCharles.Forsyth 	char *e;
59337da2899SCharles.Forsyth 
59437da2899SCharles.Forsyth 	USED(val);
59537da2899SCharles.Forsyth 
59637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
59737da2899SCharles.Forsyth 
59837da2899SCharles.Forsyth 	o = tk->env->top;
59937da2899SCharles.Forsyth 	if(af == TkCadd) {
60037da2899SCharles.Forsyth 		arg = tkword(o, arg, tag, tag+sizeof(tag), nil);
60137da2899SCharles.Forsyth 		if(tag[0] == '\0' || (tag[0] >= '0' && tag[0] <= '9'))
60237da2899SCharles.Forsyth 			return TkBadtg;
60337da2899SCharles.Forsyth 	}
60437da2899SCharles.Forsyth 
60537da2899SCharles.Forsyth 	fmt = "%d";
60637da2899SCharles.Forsyth 	arg = tkword(o, arg, buf, buf+sizeof(buf), nil);
60737da2899SCharles.Forsyth 	if(strcmp(buf, "above") == 0) {
60837da2899SCharles.Forsyth 		tkword(o, arg, buf, buf+sizeof(buf), nil);
60937da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
61037da2899SCharles.Forsyth 		if(f == nil)
61137da2899SCharles.Forsyth 			return TkBadtg;
61237da2899SCharles.Forsyth 
61337da2899SCharles.Forsyth 		t = tkclasttag(c->head, f->obj);
61437da2899SCharles.Forsyth 		if(t == nil)
61537da2899SCharles.Forsyth 			return TkBadtg;
61637da2899SCharles.Forsyth 
61737da2899SCharles.Forsyth 		for(i = t->item->next; i; i = i->next) {
61837da2899SCharles.Forsyth 			if(af == TkCadd) {
61937da2899SCharles.Forsyth 				i->tags = tkmkname(tag);
62037da2899SCharles.Forsyth 				if(i->tags == nil)
62137da2899SCharles.Forsyth 					return TkNomem;
62237da2899SCharles.Forsyth 				tkcaddtag(tk, i, 0);
62337da2899SCharles.Forsyth 			}
62437da2899SCharles.Forsyth 			else {
62537da2899SCharles.Forsyth 				e = tkvalue(val, fmt, i->id);
62637da2899SCharles.Forsyth 				if(e != nil)
62737da2899SCharles.Forsyth 					return e;
62837da2899SCharles.Forsyth 				fmt = " %d";
62937da2899SCharles.Forsyth 			}
63037da2899SCharles.Forsyth 		}
63137da2899SCharles.Forsyth 		return nil;
63237da2899SCharles.Forsyth 	}
63337da2899SCharles.Forsyth 
63437da2899SCharles.Forsyth 	if(strcmp(buf, "all") == 0) {
63537da2899SCharles.Forsyth 		for(i = c->head; i; i = i->next) {
63637da2899SCharles.Forsyth 			if(af == TkCadd) {
63737da2899SCharles.Forsyth 				i->tags = tkmkname(tag);
63837da2899SCharles.Forsyth 				if(i->tags == nil)
63937da2899SCharles.Forsyth 					return TkNomem;
64037da2899SCharles.Forsyth 				tkcaddtag(tk, i, 0);
64137da2899SCharles.Forsyth 			}
64237da2899SCharles.Forsyth 			else {
64337da2899SCharles.Forsyth 				e = tkvalue(val, fmt, i->id);
64437da2899SCharles.Forsyth 				if(e != nil)
64537da2899SCharles.Forsyth 					return e;
64637da2899SCharles.Forsyth 				fmt = " %d";
64737da2899SCharles.Forsyth 			}
64837da2899SCharles.Forsyth 		}
64937da2899SCharles.Forsyth 		return nil;
65037da2899SCharles.Forsyth 	}
65137da2899SCharles.Forsyth 
65237da2899SCharles.Forsyth 	if(strcmp(buf, "below") == 0) {
65337da2899SCharles.Forsyth 		tkword(o, arg, buf, buf+sizeof(buf), nil);
65437da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
65537da2899SCharles.Forsyth 		if(f == nil)
65637da2899SCharles.Forsyth 			return TkBadtg;
65737da2899SCharles.Forsyth 		tt = f->obj;
65837da2899SCharles.Forsyth 		for(b = c->head; b; b = b->next) {
65937da2899SCharles.Forsyth 			for(t = tt; t; t = t->itemlist)
66037da2899SCharles.Forsyth 				if(t->item == b)
66137da2899SCharles.Forsyth 					goto found;
66237da2899SCharles.Forsyth 		}
66337da2899SCharles.Forsyth 	found:
66437da2899SCharles.Forsyth 		for(i = c->head; i != b; i = i->next) {
66537da2899SCharles.Forsyth 			if(af == TkCadd) {
66637da2899SCharles.Forsyth 				i->tags = tkmkname(tag);
66737da2899SCharles.Forsyth 				if(i->tags == nil)
66837da2899SCharles.Forsyth 					return TkNomem;
66937da2899SCharles.Forsyth 				tkcaddtag(tk, i, 0);
67037da2899SCharles.Forsyth 			}
67137da2899SCharles.Forsyth 			else {
67237da2899SCharles.Forsyth 				e = tkvalue(val, fmt, i->id);
67337da2899SCharles.Forsyth 				if(e != nil)
67437da2899SCharles.Forsyth 					return e;
67537da2899SCharles.Forsyth 				fmt = " %d";
67637da2899SCharles.Forsyth 			}
67737da2899SCharles.Forsyth 		}
67837da2899SCharles.Forsyth 		return nil;
67937da2899SCharles.Forsyth 	}
68037da2899SCharles.Forsyth 
68137da2899SCharles.Forsyth 	if(strcmp(buf, "closest") == 0) {
68237da2899SCharles.Forsyth 		e = tkfracword(o, &arg, &x, nil);
68337da2899SCharles.Forsyth 		if (e == nil)
68437da2899SCharles.Forsyth 			e = tkfracword(o, &arg, &y, nil);
68537da2899SCharles.Forsyth 		if (e != nil)
68637da2899SCharles.Forsyth 			return e;
68737da2899SCharles.Forsyth 		if(*arg != '\0')
68837da2899SCharles.Forsyth 			return "!not implemented";
68937da2899SCharles.Forsyth 
69037da2899SCharles.Forsyth 		x = TKF2I(x);
69137da2899SCharles.Forsyth 		y = TKF2I(y);
69237da2899SCharles.Forsyth 		i = nil;
69337da2899SCharles.Forsyth 		dist = 0;
69437da2899SCharles.Forsyth 		for(b = c->head; b != nil; b = b->next) {
69537da2899SCharles.Forsyth 			dx = x - (b->p.bb.min.x + Dx(b->p.bb)/2);
69637da2899SCharles.Forsyth 			dy = y - (b->p.bb.min.y + Dy(b->p.bb)/2);
69737da2899SCharles.Forsyth 			d = dx*dx + dy*dy;
69837da2899SCharles.Forsyth 			if(d < dist || dist == 0) {
69937da2899SCharles.Forsyth 				i = b;
70037da2899SCharles.Forsyth 				dist = d;
70137da2899SCharles.Forsyth 			}
70237da2899SCharles.Forsyth 		}
70337da2899SCharles.Forsyth 		if(i == nil)
70437da2899SCharles.Forsyth 			return nil;
70537da2899SCharles.Forsyth 
70637da2899SCharles.Forsyth 		if(af == TkCadd) {
70737da2899SCharles.Forsyth 			i->tags = tkmkname(tag);
70837da2899SCharles.Forsyth 			if(i->tags == nil)
70937da2899SCharles.Forsyth 				e = TkNomem;
71037da2899SCharles.Forsyth 			else
71137da2899SCharles.Forsyth 				tkcaddtag(tk, i, 0);
71237da2899SCharles.Forsyth 		}
71337da2899SCharles.Forsyth 		else
71437da2899SCharles.Forsyth 			e = tkvalue(val, fmt, i->id);
71537da2899SCharles.Forsyth 		return e;
71637da2899SCharles.Forsyth 	}
71737da2899SCharles.Forsyth 
71837da2899SCharles.Forsyth 	if(strcmp(buf, "withtag") == 0) {
71937da2899SCharles.Forsyth 		tkword(o, arg, buf, buf+sizeof(buf), nil);
72037da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
72137da2899SCharles.Forsyth 		if(f == nil)
72237da2899SCharles.Forsyth 			return TkBadtg;
72337da2899SCharles.Forsyth 		for(t = f->obj; t; t = t->taglist) {
72437da2899SCharles.Forsyth 			i = t->item;
72537da2899SCharles.Forsyth 			if(af == TkCadd) {
72637da2899SCharles.Forsyth 				i->tags = tkmkname(tag);
72737da2899SCharles.Forsyth 				if(i->tags == nil)
72837da2899SCharles.Forsyth 					return TkNomem;
72937da2899SCharles.Forsyth 				tkcaddtag(tk, i, 0);
73037da2899SCharles.Forsyth 			}
73137da2899SCharles.Forsyth 			else {
73237da2899SCharles.Forsyth 				e = tkvalue(val, fmt, i->id);
73337da2899SCharles.Forsyth 				if(e != nil)
73437da2899SCharles.Forsyth 					return e;
73537da2899SCharles.Forsyth 				fmt = " %d";
73637da2899SCharles.Forsyth 			}
73737da2899SCharles.Forsyth 		}
73837da2899SCharles.Forsyth 		return nil;
73937da2899SCharles.Forsyth 	}
74037da2899SCharles.Forsyth 
74137da2899SCharles.Forsyth 	if(strcmp(buf, "enclosed") == 0) {
74237da2899SCharles.Forsyth 		e = tkparsepts(o, &p, &arg, 0);
74337da2899SCharles.Forsyth 		if(e != nil)
74437da2899SCharles.Forsyth 			goto done;
74537da2899SCharles.Forsyth 		if(p.npoint != 2) {
74637da2899SCharles.Forsyth 			e = TkFewpt;
74737da2899SCharles.Forsyth 			goto done;
74837da2899SCharles.Forsyth 		}
74937da2899SCharles.Forsyth 		for(i = c->head; i; i = i->next) {
75037da2899SCharles.Forsyth 			if(rectinrect(i->p.bb, p.bb)) {
75137da2899SCharles.Forsyth 				if(af == TkCadd) {
75237da2899SCharles.Forsyth 					i->tags = tkmkname(tag);
75337da2899SCharles.Forsyth 					if(i->tags == nil) {
75437da2899SCharles.Forsyth 						e = TkNomem;
75537da2899SCharles.Forsyth 						goto done;
75637da2899SCharles.Forsyth 					}
75737da2899SCharles.Forsyth 					tkcaddtag(tk, i, 0);
75837da2899SCharles.Forsyth 				}
75937da2899SCharles.Forsyth 				else {
76037da2899SCharles.Forsyth 					e = tkvalue(val, fmt, i->id);
76137da2899SCharles.Forsyth 					if(e != nil)
76237da2899SCharles.Forsyth 						goto done;
76337da2899SCharles.Forsyth 					fmt = " %d";
76437da2899SCharles.Forsyth 				}
76537da2899SCharles.Forsyth 			}
76637da2899SCharles.Forsyth 		}
76737da2899SCharles.Forsyth 		goto done;
76837da2899SCharles.Forsyth 	}
76937da2899SCharles.Forsyth 
77037da2899SCharles.Forsyth 	if(strcmp(buf, "overlapping") == 0) {
77137da2899SCharles.Forsyth 		e = tkparsepts(o, &p, &arg, 0);
77237da2899SCharles.Forsyth 		if(e != nil)
77337da2899SCharles.Forsyth 			goto done;
77437da2899SCharles.Forsyth 		if(p.npoint != 2) {
77537da2899SCharles.Forsyth 			e = TkFewpt;
77637da2899SCharles.Forsyth 			goto done;
77737da2899SCharles.Forsyth 		}
77837da2899SCharles.Forsyth 		for(i = c->head; i; i = i->next) {
77937da2899SCharles.Forsyth 			if(rectXrect(i->p.bb, p.bb)) {
78037da2899SCharles.Forsyth 				if(af == TkCadd) {
78137da2899SCharles.Forsyth 					i->tags = tkmkname(tag);
78237da2899SCharles.Forsyth 					if(i->tags == nil) {
78337da2899SCharles.Forsyth 						e = TkNomem;
78437da2899SCharles.Forsyth 						goto done;
78537da2899SCharles.Forsyth 					}
78637da2899SCharles.Forsyth 					tkcaddtag(tk, i, 0);
78737da2899SCharles.Forsyth 				}
78837da2899SCharles.Forsyth 				else {
78937da2899SCharles.Forsyth 					e = tkvalue(val, "%d ", i->id);
79037da2899SCharles.Forsyth 					if(e != nil)
79137da2899SCharles.Forsyth 						goto done;
79237da2899SCharles.Forsyth 				}
79337da2899SCharles.Forsyth 			}
79437da2899SCharles.Forsyth 		}
79537da2899SCharles.Forsyth 		goto done;
79637da2899SCharles.Forsyth 	}
79737da2899SCharles.Forsyth 
79837da2899SCharles.Forsyth 	return TkBadcm;
79937da2899SCharles.Forsyth 
80037da2899SCharles.Forsyth done: 		 /* both no error and error do the same thing */
80137da2899SCharles.Forsyth 	tkfreepoint(&p);
80237da2899SCharles.Forsyth 	return e;
80337da2899SCharles.Forsyth }
80437da2899SCharles.Forsyth 
80537da2899SCharles.Forsyth static char*
tkcvsaddtag(Tk * tk,char * arg,char ** val)80637da2899SCharles.Forsyth tkcvsaddtag(Tk *tk, char *arg, char **val)
80737da2899SCharles.Forsyth {
80837da2899SCharles.Forsyth 	return tkcvstags(tk, arg, val, TkCadd);
80937da2899SCharles.Forsyth }
81037da2899SCharles.Forsyth 
81137da2899SCharles.Forsyth static char*
tkcvsfind(Tk * tk,char * arg,char ** val)81237da2899SCharles.Forsyth tkcvsfind(Tk *tk, char *arg, char **val)
81337da2899SCharles.Forsyth {
81437da2899SCharles.Forsyth 	return tkcvstags(tk, arg, val, TkCfind);
81537da2899SCharles.Forsyth }
81637da2899SCharles.Forsyth 
81737da2899SCharles.Forsyth static void
tksweepcanv(Tk * tk)81837da2899SCharles.Forsyth tksweepcanv(Tk *tk)
81937da2899SCharles.Forsyth {
82037da2899SCharles.Forsyth 	int j, k;
82137da2899SCharles.Forsyth 	TkCtag *t, *tt;
82237da2899SCharles.Forsyth 	TkName **np, *n, *nn;
82337da2899SCharles.Forsyth 	TkCitem *i;
82437da2899SCharles.Forsyth 	TkCanvas *c;
82537da2899SCharles.Forsyth 	TkAction *a;
82637da2899SCharles.Forsyth 
82737da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
82837da2899SCharles.Forsyth 
82937da2899SCharles.Forsyth 	for(j = 0; j < TkChash; j++)
83037da2899SCharles.Forsyth 		for(n = c->thash[j]; n != nil; n = n->link)
83137da2899SCharles.Forsyth 			n->ref = 0;
83237da2899SCharles.Forsyth 
83337da2899SCharles.Forsyth 	for(i = c->head; i != nil; i = i->next)
83437da2899SCharles.Forsyth 		for(t = i->stag; t != nil; t = t->itemlist)
83537da2899SCharles.Forsyth 			t->name->ref = 1;
83637da2899SCharles.Forsyth 
83737da2899SCharles.Forsyth 	k = 0;
83837da2899SCharles.Forsyth 	for(j = 0; j < TkChash; j++) {
83937da2899SCharles.Forsyth 		np = &c->thash[j];
84037da2899SCharles.Forsyth 		for(n = *np; n != nil; n = nn) {
84137da2899SCharles.Forsyth 			nn = n->link;
84237da2899SCharles.Forsyth 			if(n->ref == 0) {
84337da2899SCharles.Forsyth 				for(t = n->obj; t != nil; t = tt) {
84437da2899SCharles.Forsyth 					tt = t->taglist;
84537da2899SCharles.Forsyth 					free(t);
84637da2899SCharles.Forsyth 				}
84737da2899SCharles.Forsyth 				tkfreebind(n->prop.binds);
84837da2899SCharles.Forsyth 				free(n);
84937da2899SCharles.Forsyth 				*np = nn;
85037da2899SCharles.Forsyth 			} else {
85137da2899SCharles.Forsyth 				np = &n->link;
85237da2899SCharles.Forsyth 				for(a = n->prop.binds; a != nil; a = a->link)
85337da2899SCharles.Forsyth 					k++;
85437da2899SCharles.Forsyth 			}
85537da2899SCharles.Forsyth 		}
85637da2899SCharles.Forsyth 	}
85737da2899SCharles.Forsyth 
85837da2899SCharles.Forsyth 	c->actions = k;
85937da2899SCharles.Forsyth 	k = 3 * k / 2;
86037da2899SCharles.Forsyth 	if (k < Tksweep)
86137da2899SCharles.Forsyth 		c->actlim = Tksweep;
86237da2899SCharles.Forsyth 	else
86337da2899SCharles.Forsyth 		c->actlim = k;
86437da2899SCharles.Forsyth }
86537da2899SCharles.Forsyth 
86637da2899SCharles.Forsyth /*
86737da2899SCharles.Forsyth  * extension to tcl/tk:
86837da2899SCharles.Forsyth  * grab set tag
86937da2899SCharles.Forsyth  * grab release tag
87037da2899SCharles.Forsyth  * grab ifunset tag
87137da2899SCharles.Forsyth  */
87237da2899SCharles.Forsyth static char*
tkcvsgrab(Tk * tk,char * arg,char ** val)87337da2899SCharles.Forsyth tkcvsgrab(Tk *tk, char *arg, char **val)
87437da2899SCharles.Forsyth {
87537da2899SCharles.Forsyth 	TkCtag *t;
87637da2899SCharles.Forsyth 	TkName *f;
87737da2899SCharles.Forsyth 	TkCanvas *c;
87837da2899SCharles.Forsyth 	char buf[Tkmaxitem];
87937da2899SCharles.Forsyth 
88037da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
88137da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
88237da2899SCharles.Forsyth 	if (strcmp(buf, "status") == 0) {
88337da2899SCharles.Forsyth 		if (c->grab != nil)
88437da2899SCharles.Forsyth 			return tkvalue(val, "%d", c->grab->id);
88537da2899SCharles.Forsyth 	}
88637da2899SCharles.Forsyth 	else if (strcmp(buf, "release") == 0) {
88737da2899SCharles.Forsyth 		c->grab = nil;
88837da2899SCharles.Forsyth 	}
88937da2899SCharles.Forsyth 	else if (strcmp(buf, "set") == 0 || strcmp(buf, "ifunset") == 0) {
89037da2899SCharles.Forsyth 		if (buf[0] == 'i' && c->grab != nil)
89137da2899SCharles.Forsyth 			return nil;
89237da2899SCharles.Forsyth 		tkword(tk->env->top, arg, buf, buf + sizeof(buf), nil);
89337da2899SCharles.Forsyth 
89437da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
89537da2899SCharles.Forsyth 		if(f == nil || f->obj == nil)
89637da2899SCharles.Forsyth 			return TkBadtg;
89737da2899SCharles.Forsyth 
89837da2899SCharles.Forsyth 		c = TKobj(TkCanvas, tk);
89937da2899SCharles.Forsyth 		t = tkcfirsttag(c->head, f->obj);
90037da2899SCharles.Forsyth 		if(t == nil)
90137da2899SCharles.Forsyth 			return TkBadtg;
90237da2899SCharles.Forsyth 		c->grab = t->item;
90337da2899SCharles.Forsyth 	}
90437da2899SCharles.Forsyth 	else
90537da2899SCharles.Forsyth 		return TkBadvl;
90637da2899SCharles.Forsyth 	return nil;
90737da2899SCharles.Forsyth }
90837da2899SCharles.Forsyth 
90937da2899SCharles.Forsyth static char*
tkcvsbind(Tk * tk,char * arg,char ** val)91037da2899SCharles.Forsyth tkcvsbind(Tk *tk, char *arg, char **val)
91137da2899SCharles.Forsyth {
91237da2899SCharles.Forsyth 	Rune r;
91337da2899SCharles.Forsyth 	TkCtag *t;
91437da2899SCharles.Forsyth 	TkName *f;
91537da2899SCharles.Forsyth 	TkAction *a;
91637da2899SCharles.Forsyth 	TkCanvas *c;
91737da2899SCharles.Forsyth 	int event, mode;
91837da2899SCharles.Forsyth 	char *cmd, buf[Tkmaxitem];
91937da2899SCharles.Forsyth 	char *e;
92037da2899SCharles.Forsyth 
92137da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
92237da2899SCharles.Forsyth 	if (c->actions >= c->actlim)
92337da2899SCharles.Forsyth 		tksweepcanv(tk);
92437da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
92537da2899SCharles.Forsyth 
92637da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
92737da2899SCharles.Forsyth 	if(f == nil) {
92837da2899SCharles.Forsyth 		f = tkctaglook(tk, tkmkname(buf), buf);
92937da2899SCharles.Forsyth 		if(f == nil)
93037da2899SCharles.Forsyth 			return TkNomem;
93137da2899SCharles.Forsyth 	}
93237da2899SCharles.Forsyth 
93337da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
93437da2899SCharles.Forsyth 	if(buf[0] == '<') {
93537da2899SCharles.Forsyth 		event = tkseqparse(buf+1);
93637da2899SCharles.Forsyth 		if(event == -1)
93737da2899SCharles.Forsyth 			return TkBadsq;
93837da2899SCharles.Forsyth 	}
93937da2899SCharles.Forsyth 	else {
94037da2899SCharles.Forsyth 		chartorune(&r, buf);
94137da2899SCharles.Forsyth 		event = TkKey | r;
94237da2899SCharles.Forsyth 	}
94337da2899SCharles.Forsyth 	if(event == 0)
94437da2899SCharles.Forsyth 		return TkBadsq;
94537da2899SCharles.Forsyth 
94637da2899SCharles.Forsyth 	arg = tkskip(arg, " \t");
94737da2899SCharles.Forsyth 	if(*arg == '\0') {
94837da2899SCharles.Forsyth 		for(t = f->obj; t; t = t->taglist) {
94937da2899SCharles.Forsyth 			for(a = t->name->prop.binds; a; a = a->link)
95037da2899SCharles.Forsyth 				if(event == a->event)
95137da2899SCharles.Forsyth 					return tkvalue(val, "%s", a->arg);
95237da2899SCharles.Forsyth 			for(a = t->name->prop.binds; a; a = a->link)
95337da2899SCharles.Forsyth 				if(event & a->event)
95437da2899SCharles.Forsyth 					return tkvalue(val, "%s", a->arg);
95537da2899SCharles.Forsyth 		}
95637da2899SCharles.Forsyth 		return nil;
95737da2899SCharles.Forsyth 	}
95837da2899SCharles.Forsyth 
95937da2899SCharles.Forsyth 	mode = TkArepl;
96037da2899SCharles.Forsyth 	if(*arg == '+') {
96137da2899SCharles.Forsyth 		mode = TkAadd;
96237da2899SCharles.Forsyth 		arg++;
96337da2899SCharles.Forsyth 	}
96437da2899SCharles.Forsyth 	else if(*arg == '-'){
96537da2899SCharles.Forsyth 		mode = TkAsub;
96637da2899SCharles.Forsyth 		arg++;
96737da2899SCharles.Forsyth 	}
96837da2899SCharles.Forsyth 
96937da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
97037da2899SCharles.Forsyth 	cmd = strdup(buf);
97137da2899SCharles.Forsyth 	if(cmd == nil)
97237da2899SCharles.Forsyth 		return TkNomem;
97337da2899SCharles.Forsyth 	e = tkaction(&f->prop.binds, event, TkDynamic, cmd, mode);
97437da2899SCharles.Forsyth 	if(e == nil)
97537da2899SCharles.Forsyth 		c->actions++;
97637da2899SCharles.Forsyth 	return e;
97737da2899SCharles.Forsyth }
97837da2899SCharles.Forsyth 
97937da2899SCharles.Forsyth static char*
tkcvscreate(Tk * tk,char * arg,char ** val)98037da2899SCharles.Forsyth tkcvscreate(Tk *tk, char *arg, char **val)
98137da2899SCharles.Forsyth {
98237da2899SCharles.Forsyth 	TkCimeth *m;
98337da2899SCharles.Forsyth 	char buf[Tkmaxitem];
98437da2899SCharles.Forsyth 
98537da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
98637da2899SCharles.Forsyth 	for(m = tkcimethod; m->name; m++)
98737da2899SCharles.Forsyth 		if(strcmp(buf, m->name) == 0)
98837da2899SCharles.Forsyth 			return m->create(tk, arg, val);
98937da2899SCharles.Forsyth 
99037da2899SCharles.Forsyth 	return TkBadit;
99137da2899SCharles.Forsyth }
99237da2899SCharles.Forsyth 
99337da2899SCharles.Forsyth static char*
tkcvsbbox(Tk * tk,char * arg,char ** val)99437da2899SCharles.Forsyth tkcvsbbox(Tk *tk, char *arg, char **val)
99537da2899SCharles.Forsyth {
99637da2899SCharles.Forsyth 	TkName *f;
99737da2899SCharles.Forsyth 	TkCtag *t;
99837da2899SCharles.Forsyth 	Rectangle bb;
99937da2899SCharles.Forsyth 	char buf[Tkmaxitem];
100037da2899SCharles.Forsyth 
100137da2899SCharles.Forsyth 	bb = bbnil;
100237da2899SCharles.Forsyth 	for(;;) {
100337da2899SCharles.Forsyth 		arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
100437da2899SCharles.Forsyth 		if(buf[0] == '\0')
100537da2899SCharles.Forsyth 			break;
100637da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
100737da2899SCharles.Forsyth 		if(f == nil)
100837da2899SCharles.Forsyth 			return TkBadtg;
100937da2899SCharles.Forsyth 		for(t = f->obj; t; t = t->taglist)
101037da2899SCharles.Forsyth 			tkbbmax(&bb, &t->item->p.bb);
101137da2899SCharles.Forsyth 	}
101237da2899SCharles.Forsyth 	return tkvalue(val, "%d %d %d %d", bb.min.x, bb.min.y, bb.max.x, bb.max.y);
101337da2899SCharles.Forsyth }
101437da2899SCharles.Forsyth 
101537da2899SCharles.Forsyth static char*
tkcvscanvx(Tk * tk,char * arg,char ** val)101637da2899SCharles.Forsyth tkcvscanvx(Tk *tk, char *arg, char **val)
101737da2899SCharles.Forsyth {
101837da2899SCharles.Forsyth 	int x, s;
101937da2899SCharles.Forsyth 	TkCanvas *c;
102037da2899SCharles.Forsyth 	Point p;
102137da2899SCharles.Forsyth 	char buf[Tkmaxitem];
102237da2899SCharles.Forsyth 
102337da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
102437da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
102537da2899SCharles.Forsyth 	if(buf[0] == '\0')
102637da2899SCharles.Forsyth 		return TkBadvl;
102737da2899SCharles.Forsyth 
102837da2899SCharles.Forsyth 	p = tkposn(tk);
102937da2899SCharles.Forsyth 	x = atoi(buf) + c->view.x - (p.x + tk->borderwidth);
103037da2899SCharles.Forsyth 
103137da2899SCharles.Forsyth 	if(*arg) {
103237da2899SCharles.Forsyth 		tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
103337da2899SCharles.Forsyth 		s = atoi(buf);
103437da2899SCharles.Forsyth 		if (s) {
103537da2899SCharles.Forsyth 			if (x>=0)
103637da2899SCharles.Forsyth 				x = ((x+s/2)/s)*s;
103737da2899SCharles.Forsyth 			else
103837da2899SCharles.Forsyth 				x = ((x-s/2)/s)*s;
103937da2899SCharles.Forsyth 		}
104037da2899SCharles.Forsyth 	}
104137da2899SCharles.Forsyth 	return tkvalue(val, "%d", x);
104237da2899SCharles.Forsyth }
104337da2899SCharles.Forsyth 
104437da2899SCharles.Forsyth static char*
tkcvscanvy(Tk * tk,char * arg,char ** val)104537da2899SCharles.Forsyth tkcvscanvy(Tk *tk, char *arg, char **val)
104637da2899SCharles.Forsyth {
104737da2899SCharles.Forsyth 	int y, s;
104837da2899SCharles.Forsyth 	TkCanvas *c;
104937da2899SCharles.Forsyth 	Point p;
105037da2899SCharles.Forsyth 	char buf[Tkmaxitem];
105137da2899SCharles.Forsyth 
105237da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
105337da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
105437da2899SCharles.Forsyth 	if(buf[0] == '\0')
105537da2899SCharles.Forsyth 		return TkBadvl;
105637da2899SCharles.Forsyth 
105737da2899SCharles.Forsyth 	p = tkposn(tk);
105837da2899SCharles.Forsyth 	y = atoi(buf) + c->view.y - (p.y + tk->borderwidth);
105937da2899SCharles.Forsyth 
106037da2899SCharles.Forsyth 	if(*arg) {
106137da2899SCharles.Forsyth 		tkitem(buf, arg);
106237da2899SCharles.Forsyth 		s = atoi(buf);
106337da2899SCharles.Forsyth 		if (s) {
106437da2899SCharles.Forsyth 			if (y>=0)
106537da2899SCharles.Forsyth 				y = ((y+s/2)/s)*s;
106637da2899SCharles.Forsyth 			else
106737da2899SCharles.Forsyth 				y = ((y-s/2)/s)*s;
106837da2899SCharles.Forsyth 		}
106937da2899SCharles.Forsyth 	}
107037da2899SCharles.Forsyth 	return tkvalue(val, "%d", y);
107137da2899SCharles.Forsyth }
107237da2899SCharles.Forsyth 
107337da2899SCharles.Forsyth static char *
tkcvsscreenx(Tk * tk,char * arg,char ** val)107437da2899SCharles.Forsyth tkcvsscreenx(Tk *tk, char *arg, char **val)
107537da2899SCharles.Forsyth {
107637da2899SCharles.Forsyth 	int x;
107737da2899SCharles.Forsyth 	TkCanvas *c;
107837da2899SCharles.Forsyth 	Point p;
107937da2899SCharles.Forsyth 	char buf[Tkmaxitem];
108037da2899SCharles.Forsyth 
108137da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
108237da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
108337da2899SCharles.Forsyth 	if(buf[0] == '\0')
108437da2899SCharles.Forsyth 		return TkBadvl;
108537da2899SCharles.Forsyth 	p = tkposn(tk);
108637da2899SCharles.Forsyth 	x = atoi(buf) - c->view.x + (p.x + tk->borderwidth);
108737da2899SCharles.Forsyth 	return tkvalue(val, "%d", x);
108837da2899SCharles.Forsyth }
108937da2899SCharles.Forsyth 
109037da2899SCharles.Forsyth static char *
tkcvsscreeny(Tk * tk,char * arg,char ** val)109137da2899SCharles.Forsyth tkcvsscreeny(Tk *tk, char *arg, char **val)
109237da2899SCharles.Forsyth {
109337da2899SCharles.Forsyth 	int y;
109437da2899SCharles.Forsyth 	TkCanvas *c;
109537da2899SCharles.Forsyth 	Point p;
109637da2899SCharles.Forsyth 	char buf[Tkmaxitem];
109737da2899SCharles.Forsyth 
109837da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
109937da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
110037da2899SCharles.Forsyth 	if(buf[0] == '\0')
110137da2899SCharles.Forsyth 		return TkBadvl;
110237da2899SCharles.Forsyth 	p = tkposn(tk);
110337da2899SCharles.Forsyth 	y = atoi(buf) - c->view.y + (p.y + tk->borderwidth);
110437da2899SCharles.Forsyth 	return tkvalue(val, "%d", y);
110537da2899SCharles.Forsyth }
110637da2899SCharles.Forsyth 
110737da2899SCharles.Forsyth static char*
tkcvscoords(Tk * tk,char * arg,char ** val)110837da2899SCharles.Forsyth tkcvscoords(Tk *tk, char *arg, char **val)
110937da2899SCharles.Forsyth {
111037da2899SCharles.Forsyth 	int i;
111137da2899SCharles.Forsyth 	Point *p;
111237da2899SCharles.Forsyth 	TkCtag *t;
111337da2899SCharles.Forsyth 	TkName *f;
111437da2899SCharles.Forsyth 	TkCanvas *c;
111537da2899SCharles.Forsyth 	TkCitem *item;
111637da2899SCharles.Forsyth 	char *fmt, *e, *v, buf[Tkmaxitem];
111737da2899SCharles.Forsyth 
111837da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
111937da2899SCharles.Forsyth 	if(buf[0] == '\0')
112037da2899SCharles.Forsyth 		return TkBadvl;
112137da2899SCharles.Forsyth 
112237da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
112337da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
112437da2899SCharles.Forsyth 		return TkBadtg;
112537da2899SCharles.Forsyth 
112637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
112737da2899SCharles.Forsyth 
112837da2899SCharles.Forsyth 	t = tkcfirsttag(c->head, f->obj);
112937da2899SCharles.Forsyth 	if(t == nil)
113037da2899SCharles.Forsyth 		return TkBadtg;
113137da2899SCharles.Forsyth 
113237da2899SCharles.Forsyth 	item = t->item;
113337da2899SCharles.Forsyth 
113437da2899SCharles.Forsyth 	if(*arg == '\0') {
113537da2899SCharles.Forsyth 		fmt = "%s";
113637da2899SCharles.Forsyth 		p = item->p.parampt;
113737da2899SCharles.Forsyth 		for(i = 0; i < item->p.npoint; i++) {
113837da2899SCharles.Forsyth 			v = tkfprint(buf, p->x);
113937da2899SCharles.Forsyth 			*v++ = ' ';
114037da2899SCharles.Forsyth 			tkfprint(v, p->y);
114137da2899SCharles.Forsyth 			e = tkvalue(val, fmt, buf);
114237da2899SCharles.Forsyth 			if(e != nil)
114337da2899SCharles.Forsyth 				return e;
114437da2899SCharles.Forsyth 			fmt = " %s";
114537da2899SCharles.Forsyth 			p++;
114637da2899SCharles.Forsyth 		}
114737da2899SCharles.Forsyth 		return nil;
114837da2899SCharles.Forsyth 	}
114937da2899SCharles.Forsyth 
115037da2899SCharles.Forsyth 	tkbbmax(&c->update, &item->p.bb);
115137da2899SCharles.Forsyth 	e = tkcimethod[item->type].coord(item, arg, 0, 0);
115237da2899SCharles.Forsyth 	tkbbmax(&c->update, &item->p.bb);
115337da2899SCharles.Forsyth 	tkcvssetdirty(tk);
115437da2899SCharles.Forsyth 	return e;
115537da2899SCharles.Forsyth }
115637da2899SCharles.Forsyth 
115737da2899SCharles.Forsyth static char*
tkcvsscale(Tk * tk,char * arg,char ** val)115837da2899SCharles.Forsyth tkcvsscale(Tk *tk, char *arg, char **val)
115937da2899SCharles.Forsyth {
116037da2899SCharles.Forsyth 	TkName *f;
116137da2899SCharles.Forsyth 	TkCtag *t;
116237da2899SCharles.Forsyth 	TkCanvas *c;
116337da2899SCharles.Forsyth 	TkCpoints pts;
116437da2899SCharles.Forsyth 	TkCitem *item;
116537da2899SCharles.Forsyth 	int j;
116637da2899SCharles.Forsyth 	char *e, buf[Tkmaxitem];
116737da2899SCharles.Forsyth 	Point *p, *d, origin, scalef;
116837da2899SCharles.Forsyth 
116937da2899SCharles.Forsyth 	USED(val);
117037da2899SCharles.Forsyth 
117137da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
117237da2899SCharles.Forsyth 
117337da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
117437da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
117537da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
117637da2899SCharles.Forsyth 		return TkBadtg;
117737da2899SCharles.Forsyth 
117837da2899SCharles.Forsyth 	e = tkparsepts(tk->env->top, &pts, &arg, 0);
117937da2899SCharles.Forsyth 	if(e != nil)
118037da2899SCharles.Forsyth 		return e;
118137da2899SCharles.Forsyth 	if(pts.npoint != 2) {
118237da2899SCharles.Forsyth 		tkfreepoint(&pts);
118337da2899SCharles.Forsyth 		return TkFewpt;
118437da2899SCharles.Forsyth 	}
118537da2899SCharles.Forsyth 	origin = pts.parampt[0];
118637da2899SCharles.Forsyth 	scalef = pts.parampt[1];
118737da2899SCharles.Forsyth 	tkfreepoint(&pts);
118837da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
118937da2899SCharles.Forsyth 		item = t->item;
119037da2899SCharles.Forsyth 		p = item->p.parampt;
119137da2899SCharles.Forsyth 		d = item->p.drawpt;
119237da2899SCharles.Forsyth 		for(j = 0; j < item->p.npoint; j++) {
119337da2899SCharles.Forsyth 			p->x -= origin.x;
119437da2899SCharles.Forsyth 			p->y -= origin.y;
119537da2899SCharles.Forsyth 			p->x = TKF2I(p->x*scalef.x);
119637da2899SCharles.Forsyth 			p->y = TKF2I(p->y*scalef.y);
119737da2899SCharles.Forsyth 			p->x += origin.x;
119837da2899SCharles.Forsyth 			p->y += origin.y;
119937da2899SCharles.Forsyth 			d->x = TKF2I(p->x);
120037da2899SCharles.Forsyth 			d->y = TKF2I(p->y);
120137da2899SCharles.Forsyth 			d++;
120237da2899SCharles.Forsyth 			p++;
120337da2899SCharles.Forsyth 		}
120437da2899SCharles.Forsyth 		tkbbmax(&c->update, &item->p.bb);
120537da2899SCharles.Forsyth 		e = tkcimethod[item->type].coord(item, nil, 0, 0);
120637da2899SCharles.Forsyth 		tkbbmax(&c->update, &item->p.bb);
120737da2899SCharles.Forsyth 		if(e != nil)
120837da2899SCharles.Forsyth 			return e;
120937da2899SCharles.Forsyth 
121037da2899SCharles.Forsyth 		tkcvssetdirty(tk);
121137da2899SCharles.Forsyth 	}
121237da2899SCharles.Forsyth 	return nil;
121337da2899SCharles.Forsyth }
121437da2899SCharles.Forsyth 
121537da2899SCharles.Forsyth static char*
tkcvsdtag(Tk * tk,char * arg,char ** val)121637da2899SCharles.Forsyth tkcvsdtag(Tk *tk, char *arg, char **val)
121737da2899SCharles.Forsyth {
121837da2899SCharles.Forsyth 	TkName *f, *dt;
121937da2899SCharles.Forsyth 	char buf[Tkmaxitem];
122037da2899SCharles.Forsyth 	TkCtag **l, *t, *it, *tf;
122137da2899SCharles.Forsyth 
122237da2899SCharles.Forsyth 	USED(val);
122337da2899SCharles.Forsyth 
122437da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
122537da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
122637da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
122737da2899SCharles.Forsyth 		return TkBadtg;
122837da2899SCharles.Forsyth 
122937da2899SCharles.Forsyth /*
123037da2899SCharles.Forsyth 	XXX this code doesn't appear to work properly.
123137da2899SCharles.Forsyth 	fix it later. for the moment, it's just a somewhat more
123237da2899SCharles.Forsyth 	efficient substitute for the later code, so just use that
123337da2899SCharles.Forsyth 	instead.
123437da2899SCharles.Forsyth 
123537da2899SCharles.Forsyth 	if(*arg == '\0') {
123637da2899SCharles.Forsyth 		for(t = f->obj; t; t = tf) {
123737da2899SCharles.Forsyth 			l = &t->item->stag;
123837da2899SCharles.Forsyth 			for(it = *l; it; it = it->itemlist) {
123937da2899SCharles.Forsyth 				if(it->item == t->item) {
124037da2899SCharles.Forsyth 					*l = it->itemlist;
124137da2899SCharles.Forsyth 					break;
124237da2899SCharles.Forsyth 				}
124337da2899SCharles.Forsyth 				l = &it->itemlist;
124437da2899SCharles.Forsyth 			}
124537da2899SCharles.Forsyth 
124637da2899SCharles.Forsyth 			tf = t->taglist;
124737da2899SCharles.Forsyth 			free(t);
124837da2899SCharles.Forsyth 		}
124937da2899SCharles.Forsyth 		f->obj = nil;
125037da2899SCharles.Forsyth 		return nil;
125137da2899SCharles.Forsyth 	}
125237da2899SCharles.Forsyth */
125337da2899SCharles.Forsyth 	if (*arg == '\0')
125437da2899SCharles.Forsyth 		dt = f;
125537da2899SCharles.Forsyth 	else {
125637da2899SCharles.Forsyth 		tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
125737da2899SCharles.Forsyth 		dt = tkctaglook(tk, nil, buf);
125837da2899SCharles.Forsyth 		if(dt == nil || dt->obj == nil)
125937da2899SCharles.Forsyth 			return TkBadtg;
126037da2899SCharles.Forsyth 	}
126137da2899SCharles.Forsyth 
126237da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
126337da2899SCharles.Forsyth 		l = (TkCtag **)&dt->obj;
126437da2899SCharles.Forsyth 		for(it = dt->obj; it; it = it->taglist) {
126537da2899SCharles.Forsyth 			if(t->item == it->item) {
126637da2899SCharles.Forsyth 				*l = it->taglist;
126737da2899SCharles.Forsyth 				l = &t->item->stag;
126837da2899SCharles.Forsyth 				for(tf = *l; tf; tf = tf->itemlist) {
126937da2899SCharles.Forsyth 					if(tf == it) {
127037da2899SCharles.Forsyth 						*l = tf->itemlist;
127137da2899SCharles.Forsyth 						break;
127237da2899SCharles.Forsyth 					}
127337da2899SCharles.Forsyth 					l = &tf->itemlist;
127437da2899SCharles.Forsyth 				}
127537da2899SCharles.Forsyth 				free(it);
127637da2899SCharles.Forsyth 				break;
127737da2899SCharles.Forsyth 			}
127837da2899SCharles.Forsyth 			l = &it->taglist;
127937da2899SCharles.Forsyth 		}
128037da2899SCharles.Forsyth 	}
128137da2899SCharles.Forsyth 	return nil;
128237da2899SCharles.Forsyth }
128337da2899SCharles.Forsyth 
128437da2899SCharles.Forsyth static char*
tkcvsdchars(Tk * tk,char * arg,char ** val)128537da2899SCharles.Forsyth tkcvsdchars(Tk *tk, char *arg, char **val)
128637da2899SCharles.Forsyth {
128737da2899SCharles.Forsyth 	TkCtag *t;
128837da2899SCharles.Forsyth 	TkName *f;
128937da2899SCharles.Forsyth 	char *e, buf[Tkmaxitem];
129037da2899SCharles.Forsyth 
129137da2899SCharles.Forsyth 	USED(val);
129237da2899SCharles.Forsyth 
129337da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
129437da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
129537da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
129637da2899SCharles.Forsyth 		return TkBadtg;
129737da2899SCharles.Forsyth 
129837da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
129937da2899SCharles.Forsyth 		if(t->item->type == TkCVtext) {
130037da2899SCharles.Forsyth 			e = tkcvstextdchar(tk, t->item, arg);
130137da2899SCharles.Forsyth 			if(e != nil)
130237da2899SCharles.Forsyth 				return e;
130337da2899SCharles.Forsyth 		}
130437da2899SCharles.Forsyth 	}
130537da2899SCharles.Forsyth 
130637da2899SCharles.Forsyth 	return nil;
130737da2899SCharles.Forsyth }
130837da2899SCharles.Forsyth 
130937da2899SCharles.Forsyth static char*
tkcvsindex(Tk * tk,char * arg,char ** val)131037da2899SCharles.Forsyth tkcvsindex(Tk *tk, char *arg, char **val)
131137da2899SCharles.Forsyth {
131237da2899SCharles.Forsyth 	TkCtag *t;
131337da2899SCharles.Forsyth 	TkName *f;
131437da2899SCharles.Forsyth 	char *e, buf[Tkmaxitem];
131537da2899SCharles.Forsyth 
131637da2899SCharles.Forsyth 	USED(val);
131737da2899SCharles.Forsyth 
131837da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
131937da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
132037da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
132137da2899SCharles.Forsyth 		return TkBadtg;
132237da2899SCharles.Forsyth 
132337da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
132437da2899SCharles.Forsyth 		if(t->item->type == TkCVtext) {
132537da2899SCharles.Forsyth 			e = tkcvstextindex(tk, t->item, arg, val);
132637da2899SCharles.Forsyth 			if(e != nil)
132737da2899SCharles.Forsyth 				return e;
132837da2899SCharles.Forsyth 			return nil;
132937da2899SCharles.Forsyth 		}
133037da2899SCharles.Forsyth 	}
133137da2899SCharles.Forsyth 	return nil;
133237da2899SCharles.Forsyth }
133337da2899SCharles.Forsyth 
133437da2899SCharles.Forsyth static char*
tkcvsicursor(Tk * tk,char * arg,char ** val)133537da2899SCharles.Forsyth tkcvsicursor(Tk *tk, char *arg, char **val)
133637da2899SCharles.Forsyth {
133737da2899SCharles.Forsyth 	TkCtag *t;
133837da2899SCharles.Forsyth 	TkName *f;
133937da2899SCharles.Forsyth 	char *e, buf[Tkmaxitem];
134037da2899SCharles.Forsyth 
134137da2899SCharles.Forsyth 	USED(val);
134237da2899SCharles.Forsyth 
134337da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
134437da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
134537da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
134637da2899SCharles.Forsyth 		return TkBadtg;
134737da2899SCharles.Forsyth 
134837da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
134937da2899SCharles.Forsyth 		if(t->item->type == TkCVtext) {
135037da2899SCharles.Forsyth 			e = tkcvstexticursor(tk, t->item, arg);
135137da2899SCharles.Forsyth 			if(e != nil)
135237da2899SCharles.Forsyth 				return e;
135337da2899SCharles.Forsyth 			return nil;
135437da2899SCharles.Forsyth 		}
135537da2899SCharles.Forsyth 	}
135637da2899SCharles.Forsyth 	return nil;
135737da2899SCharles.Forsyth }
135837da2899SCharles.Forsyth 
135937da2899SCharles.Forsyth static char*
tkcvsinsert(Tk * tk,char * arg,char ** val)136037da2899SCharles.Forsyth tkcvsinsert(Tk *tk, char *arg, char **val)
136137da2899SCharles.Forsyth {
136237da2899SCharles.Forsyth 	TkCtag *t;
136337da2899SCharles.Forsyth 	TkName *f;
136437da2899SCharles.Forsyth 	char *e, buf[Tkmaxitem];
136537da2899SCharles.Forsyth 
136637da2899SCharles.Forsyth 	USED(val);
136737da2899SCharles.Forsyth 
136837da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
136937da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
137037da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
137137da2899SCharles.Forsyth 		return TkBadtg;
137237da2899SCharles.Forsyth 
137337da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
137437da2899SCharles.Forsyth 		if(t->item->type == TkCVtext) {
137537da2899SCharles.Forsyth 			e = tkcvstextinsert(tk, t->item, arg);
137637da2899SCharles.Forsyth 			if(e != nil)
137737da2899SCharles.Forsyth 				return e;
137837da2899SCharles.Forsyth 		}
137937da2899SCharles.Forsyth 	}
138037da2899SCharles.Forsyth 
138137da2899SCharles.Forsyth 	return nil;
138237da2899SCharles.Forsyth }
138337da2899SCharles.Forsyth 
138437da2899SCharles.Forsyth static char*
tkcvsselect(Tk * tk,char * arg,char ** val)138537da2899SCharles.Forsyth tkcvsselect(Tk *tk, char *arg, char **val)
138637da2899SCharles.Forsyth {
138737da2899SCharles.Forsyth 	int op;
138837da2899SCharles.Forsyth 	TkCtag *t;
138937da2899SCharles.Forsyth 	TkName *f;
139037da2899SCharles.Forsyth 	TkCanvas *c;
139137da2899SCharles.Forsyth 	char buf[Tkmaxitem];
139237da2899SCharles.Forsyth 
139337da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
139437da2899SCharles.Forsyth 
139537da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
139637da2899SCharles.Forsyth 	if(strcmp(buf, "clear") == 0) {
139737da2899SCharles.Forsyth 		tkcvstextclr(tk);
139837da2899SCharles.Forsyth 		return nil;
139937da2899SCharles.Forsyth 	}
140037da2899SCharles.Forsyth 	if(strcmp(buf, "item") == 0) {
140137da2899SCharles.Forsyth 		if(c->selection)
140237da2899SCharles.Forsyth 			return tkvalue(val, "%d", c->selection->id);
140337da2899SCharles.Forsyth 		return nil;
140437da2899SCharles.Forsyth 	}
140537da2899SCharles.Forsyth 
140637da2899SCharles.Forsyth 	if(strcmp(buf, "to") == 0)
140737da2899SCharles.Forsyth 		op = TkCselto;
140837da2899SCharles.Forsyth 	else
140937da2899SCharles.Forsyth 	if(strcmp(buf, "from") == 0)
141037da2899SCharles.Forsyth 		op = TkCselfrom;
141137da2899SCharles.Forsyth 	else
141237da2899SCharles.Forsyth 	if(strcmp(buf, "adjust") == 0)
141337da2899SCharles.Forsyth 		op = TkCseladjust;
141437da2899SCharles.Forsyth 	else
141537da2899SCharles.Forsyth 		return TkBadcm;
141637da2899SCharles.Forsyth 
141737da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
141837da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
141937da2899SCharles.Forsyth 	if(f == nil)
142037da2899SCharles.Forsyth 		return TkBadtg;
142137da2899SCharles.Forsyth 
142237da2899SCharles.Forsyth 	t = tkcfirsttag(c->head, f->obj);
142337da2899SCharles.Forsyth 	if(t == nil)
142437da2899SCharles.Forsyth 		return TkBadtg;
142537da2899SCharles.Forsyth 
142637da2899SCharles.Forsyth 	return tkcvstextselect(tk, t->item, arg, op);
142737da2899SCharles.Forsyth }
142837da2899SCharles.Forsyth 
142937da2899SCharles.Forsyth static char*
tkcvsitemcget(Tk * tk,char * arg,char ** val)143037da2899SCharles.Forsyth tkcvsitemcget(Tk *tk, char *arg, char **val)
143137da2899SCharles.Forsyth {
143237da2899SCharles.Forsyth 	TkName *f;
143337da2899SCharles.Forsyth 	TkCtag *t;
143437da2899SCharles.Forsyth 	TkCitem *i;
143537da2899SCharles.Forsyth 	char buf[Tkmaxitem];
143637da2899SCharles.Forsyth 
143737da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
143837da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
143937da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
144037da2899SCharles.Forsyth 		return TkBadtg;
144137da2899SCharles.Forsyth 
144237da2899SCharles.Forsyth 	for(i = TKobj(TkCanvas, tk)->head; i; i = i->next) {
144337da2899SCharles.Forsyth 		for(t = f->obj; t; t = t->taglist)
144437da2899SCharles.Forsyth 			if(i == t->item)
144537da2899SCharles.Forsyth 				return tkcimethod[i->type].cget(i, arg, val);
144637da2899SCharles.Forsyth 	}
144737da2899SCharles.Forsyth 	return nil;
144837da2899SCharles.Forsyth }
144937da2899SCharles.Forsyth 
145037da2899SCharles.Forsyth static char*
tkcvsitemconf(Tk * tk,char * arg,char ** val)145137da2899SCharles.Forsyth tkcvsitemconf(Tk *tk, char *arg, char **val)
145237da2899SCharles.Forsyth {
145337da2899SCharles.Forsyth 	char *e;
145437da2899SCharles.Forsyth 	TkName *f;
145537da2899SCharles.Forsyth 	TkCtag *t;
145637da2899SCharles.Forsyth 	TkCitem *i;
145737da2899SCharles.Forsyth 	TkCanvas *c;
145837da2899SCharles.Forsyth 	char buf[Tkmaxitem];
145937da2899SCharles.Forsyth 
146037da2899SCharles.Forsyth 	USED(val);
146137da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
146237da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
146337da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
146437da2899SCharles.Forsyth 		return TkBadtg;
146537da2899SCharles.Forsyth 
146637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
146737da2899SCharles.Forsyth 	for(t = f->obj; t; t = t->taglist) {
146837da2899SCharles.Forsyth 		for(i = c->head; i; i = i->next) {
146937da2899SCharles.Forsyth 			if(i == t->item) {
147037da2899SCharles.Forsyth 				tkbbmax(&c->update, &i->p.bb);
147137da2899SCharles.Forsyth 				e = tkcimethod[i->type].conf(tk, i, arg);
147237da2899SCharles.Forsyth 				tkbbmax(&c->update, &i->p.bb);
147337da2899SCharles.Forsyth 				tkcvssetdirty(tk);
147437da2899SCharles.Forsyth 				if(e != nil)
147537da2899SCharles.Forsyth 					return e;
147637da2899SCharles.Forsyth 			}
147737da2899SCharles.Forsyth 		}
147837da2899SCharles.Forsyth 	}
147937da2899SCharles.Forsyth 	return nil;
148037da2899SCharles.Forsyth }
148137da2899SCharles.Forsyth 
148237da2899SCharles.Forsyth static void
tkcvsfreename(TkCanvas * c,TkName * n)148337da2899SCharles.Forsyth tkcvsfreename(TkCanvas *c, TkName *n)
148437da2899SCharles.Forsyth {
148537da2899SCharles.Forsyth 	ulong h;
148637da2899SCharles.Forsyth 	char *p, *s;
148737da2899SCharles.Forsyth 	TkName *f, **l;
148837da2899SCharles.Forsyth 
148937da2899SCharles.Forsyth 	/* just free implicit ones for now */
149037da2899SCharles.Forsyth 	if(n == nil)
149137da2899SCharles.Forsyth 		return;
149237da2899SCharles.Forsyth 	s = n->name;
149337da2899SCharles.Forsyth 	if(s == nil || (s[0] < '0' || s[0] > '9'))
149437da2899SCharles.Forsyth 		return;
149537da2899SCharles.Forsyth 	h = 0;
149637da2899SCharles.Forsyth 	for(p = s; *p; p++)
149737da2899SCharles.Forsyth 		h += 3*h + *p;
149837da2899SCharles.Forsyth 	l = &c->thash[h%TkChash];
149937da2899SCharles.Forsyth 	for(f = *l; f; l = &f->link, f = *l)
150037da2899SCharles.Forsyth 		if(f == n){
150137da2899SCharles.Forsyth 			*l = f->link;
150237da2899SCharles.Forsyth 			tkfreebind(f->prop.binds);
150337da2899SCharles.Forsyth 			free(f);
150437da2899SCharles.Forsyth 			return;
150537da2899SCharles.Forsyth 		}
150637da2899SCharles.Forsyth }
150737da2899SCharles.Forsyth 
150837da2899SCharles.Forsyth static char*
tkcvsdelete(Tk * tk,char * arg,char ** val)150937da2899SCharles.Forsyth tkcvsdelete(Tk *tk, char *arg, char **val)
151037da2899SCharles.Forsyth {
151137da2899SCharles.Forsyth 	TkName *f;
151237da2899SCharles.Forsyth 	TkCanvas *c;
151337da2899SCharles.Forsyth 	char buf[Tkmaxitem];
151437da2899SCharles.Forsyth 	TkCitem *item, *prev, *i;
151537da2899SCharles.Forsyth 	TkCtag *t, *inext, **l, *dit, *it;
151637da2899SCharles.Forsyth 
151737da2899SCharles.Forsyth 	USED(val);
151837da2899SCharles.Forsyth 
151937da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
152037da2899SCharles.Forsyth 	for(;;) {
152137da2899SCharles.Forsyth 		arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
152237da2899SCharles.Forsyth 		if(buf[0] == '\0')
152337da2899SCharles.Forsyth 			break;
152437da2899SCharles.Forsyth 		f = tkctaglook(tk, nil, buf);
152537da2899SCharles.Forsyth 		if(f == nil || f->obj == nil)
152637da2899SCharles.Forsyth 			return nil;
152737da2899SCharles.Forsyth 		while(f->obj) {
152837da2899SCharles.Forsyth 			t = f->obj;
152937da2899SCharles.Forsyth 			item = t->item;
153037da2899SCharles.Forsyth 			for(it = item->stag; it; it = inext) {
153137da2899SCharles.Forsyth 				inext = it->itemlist;
153237da2899SCharles.Forsyth 				l = (TkCtag **)&it->name->obj;
153337da2899SCharles.Forsyth 				for(dit = *l; dit; dit = dit->taglist) {
153437da2899SCharles.Forsyth 					if(dit->item == item) {
153537da2899SCharles.Forsyth 						*l = dit->taglist;
153637da2899SCharles.Forsyth 						if(dit != t){
153737da2899SCharles.Forsyth 							tkcvsfreename(c, dit->name);
153837da2899SCharles.Forsyth 							free(dit);
153937da2899SCharles.Forsyth 						}
154037da2899SCharles.Forsyth 						break;
154137da2899SCharles.Forsyth 					}
154237da2899SCharles.Forsyth 					l = &dit->taglist;
154337da2899SCharles.Forsyth 				}
154437da2899SCharles.Forsyth 			}
154537da2899SCharles.Forsyth 			tkbbmax(&c->update, &item->p.bb);
154637da2899SCharles.Forsyth 			tkcvssetdirty(tk);
154737da2899SCharles.Forsyth 			prev = nil;
154837da2899SCharles.Forsyth 			for(i = c->head; i; i = i->next) {
154937da2899SCharles.Forsyth 				if(i == item)
155037da2899SCharles.Forsyth 					break;
155137da2899SCharles.Forsyth 				prev = i;
155237da2899SCharles.Forsyth 			}
155337da2899SCharles.Forsyth 			if(prev == nil)
155437da2899SCharles.Forsyth 				c->head = i->next;
155537da2899SCharles.Forsyth 			else
155637da2899SCharles.Forsyth 				prev->next = i->next;
155737da2899SCharles.Forsyth 			if(c->tail == item)
155837da2899SCharles.Forsyth 				c->tail = prev;
155937da2899SCharles.Forsyth 			if(c->focus == item)
156037da2899SCharles.Forsyth 				c->focus = nil;
156137da2899SCharles.Forsyth 			if(c->mouse == item)
156237da2899SCharles.Forsyth 				c->mouse = nil;
156337da2899SCharles.Forsyth 			if(c->selection == item)
156437da2899SCharles.Forsyth 				c->selection = nil;
156537da2899SCharles.Forsyth 			if(c->curtag.item == item)
156637da2899SCharles.Forsyth 				c->current->obj = nil;
156737da2899SCharles.Forsyth 			if (c->grab == item)
156837da2899SCharles.Forsyth 				c->grab = nil;
156937da2899SCharles.Forsyth 
157037da2899SCharles.Forsyth 			tkcvsfreeitem(item);
157137da2899SCharles.Forsyth 			free(t);
157237da2899SCharles.Forsyth 		}
157337da2899SCharles.Forsyth 	}
157437da2899SCharles.Forsyth 	return nil;
157537da2899SCharles.Forsyth }
157637da2899SCharles.Forsyth 
157737da2899SCharles.Forsyth static char*
tkcvsfocus(Tk * tk,char * arg,char ** val)157837da2899SCharles.Forsyth tkcvsfocus(Tk *tk, char *arg, char **val)
157937da2899SCharles.Forsyth {
158037da2899SCharles.Forsyth 	TkName *f;
158137da2899SCharles.Forsyth 	TkCtag *t;
158237da2899SCharles.Forsyth 	TkCanvas *c;
158337da2899SCharles.Forsyth 	TkCitem *i, *focus;
158437da2899SCharles.Forsyth 	char buf[Tkmaxitem];
158537da2899SCharles.Forsyth 
158637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
158737da2899SCharles.Forsyth 
158837da2899SCharles.Forsyth 	if(*arg == '\0') {
158937da2899SCharles.Forsyth 		if(c->focus == nil)
159037da2899SCharles.Forsyth 			return nil;
159137da2899SCharles.Forsyth 		return tkvalue(val, "%d", c->focus->id);
159237da2899SCharles.Forsyth 	}
159337da2899SCharles.Forsyth 
159437da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
159537da2899SCharles.Forsyth 	if(buf[0] == '\0')
159637da2899SCharles.Forsyth 		return TkBadvl;
159737da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
159837da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
159937da2899SCharles.Forsyth 		return nil;
160037da2899SCharles.Forsyth 
160137da2899SCharles.Forsyth 	focus = c->focus;
160237da2899SCharles.Forsyth 	if(focus != nil && focus->type == TkCVtext)
160337da2899SCharles.Forsyth 		tkcvstextfocus(tk, focus, 0);
160437da2899SCharles.Forsyth 
160537da2899SCharles.Forsyth 	for(i = c->head; i; i = i->next) {
160637da2899SCharles.Forsyth 		if(i->type == TkCVtext || i->type == TkCVwindow) {
160737da2899SCharles.Forsyth 			for(t = f->obj; t; t = t->taglist)
160837da2899SCharles.Forsyth 				if(t->item == i)
160937da2899SCharles.Forsyth 					focus = i;
161037da2899SCharles.Forsyth 		}
161137da2899SCharles.Forsyth 	}
161237da2899SCharles.Forsyth 
161337da2899SCharles.Forsyth 	if(focus != nil && focus->type == TkCVtext)
161437da2899SCharles.Forsyth 		tkcvstextfocus(tk, focus, 1);
161537da2899SCharles.Forsyth 
161637da2899SCharles.Forsyth 	c->focus = focus;
161737da2899SCharles.Forsyth 	return nil;
161837da2899SCharles.Forsyth }
161937da2899SCharles.Forsyth 
162037da2899SCharles.Forsyth static char*
tkcvsgettags(Tk * tk,char * arg,char ** val)162137da2899SCharles.Forsyth tkcvsgettags(Tk *tk, char *arg, char **val)
162237da2899SCharles.Forsyth {
162337da2899SCharles.Forsyth 	TkCtag *t;
162437da2899SCharles.Forsyth 	TkName *f;
162537da2899SCharles.Forsyth 	TkCanvas *c;
162637da2899SCharles.Forsyth 	char *fmt, *e, buf[Tkmaxitem];
162737da2899SCharles.Forsyth 
162837da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
162937da2899SCharles.Forsyth 	if(buf[0] == '\0')
163037da2899SCharles.Forsyth 		return TkBadvl;
163137da2899SCharles.Forsyth 
163237da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
163337da2899SCharles.Forsyth 	if(f == nil)
163437da2899SCharles.Forsyth 		return TkBadtg;
163537da2899SCharles.Forsyth 
163637da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
163737da2899SCharles.Forsyth 	t = tkclasttag(c->head, f->obj);
163837da2899SCharles.Forsyth 	if(t == nil)
163937da2899SCharles.Forsyth 		return TkBadtg;
164037da2899SCharles.Forsyth 	fmt = "%s";
164137da2899SCharles.Forsyth 	t = t->item->stag;
164237da2899SCharles.Forsyth 	while(t) {
164337da2899SCharles.Forsyth 		/* XXX when might t->name be legally nil? */
164437da2899SCharles.Forsyth 		if (t->name != nil) {
164537da2899SCharles.Forsyth 			if (strcmp(t->name->name, "all")) {
164637da2899SCharles.Forsyth 				e = tkvalue(val, fmt, t->name->name);
164737da2899SCharles.Forsyth 				if(e != nil)
164837da2899SCharles.Forsyth 					return e;
164937da2899SCharles.Forsyth 				fmt = " %s";
165037da2899SCharles.Forsyth 			}
165137da2899SCharles.Forsyth 		}
165237da2899SCharles.Forsyth 		t = t->itemlist;
165337da2899SCharles.Forsyth 	}
165437da2899SCharles.Forsyth 	return nil;
165537da2899SCharles.Forsyth }
165637da2899SCharles.Forsyth 
165737da2899SCharles.Forsyth static char*
tkcvslower(Tk * tk,char * arg,char ** val)165837da2899SCharles.Forsyth tkcvslower(Tk *tk, char *arg, char **val)
165937da2899SCharles.Forsyth {
166037da2899SCharles.Forsyth 	TkCtag *t;
166137da2899SCharles.Forsyth 	TkCanvas *c;
166237da2899SCharles.Forsyth 	TkName *f, *b;
166337da2899SCharles.Forsyth 	char buf[Tkmaxitem];
166437da2899SCharles.Forsyth 	TkCitem *it, **l, **below, *items, **itemtail, *prev, *iprev;
166537da2899SCharles.Forsyth 
166637da2899SCharles.Forsyth 	USED(val);
166737da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
166837da2899SCharles.Forsyth 
166937da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
167037da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
167137da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
167237da2899SCharles.Forsyth 		return nil;
167337da2899SCharles.Forsyth 
167437da2899SCharles.Forsyth 	below = &c->head;
167537da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
167637da2899SCharles.Forsyth 	if(buf[0] != '\0') {
167737da2899SCharles.Forsyth 		b = tkctaglook(tk, nil, buf);
167837da2899SCharles.Forsyth 		if(b == nil || f->obj == nil)
167937da2899SCharles.Forsyth 			return TkBadtg;
168037da2899SCharles.Forsyth 		for(it = c->head; it; it = it->next) {
168137da2899SCharles.Forsyth 			for(t = b->obj; t; t = t->taglist)
168237da2899SCharles.Forsyth 				if(t->item == it)
168337da2899SCharles.Forsyth 					goto found;
168437da2899SCharles.Forsyth 			below = &it->next;
168537da2899SCharles.Forsyth 		}
168637da2899SCharles.Forsyth 	found:;
168737da2899SCharles.Forsyth 	}
168837da2899SCharles.Forsyth 	l = &c->head;
168937da2899SCharles.Forsyth 	prev = iprev = nil;
169037da2899SCharles.Forsyth 	itemtail = &items;;
169137da2899SCharles.Forsyth 	for (it = *l; it != nil; it = *l) {
169237da2899SCharles.Forsyth 		for (t = f->obj; t; t = t->taglist) {
169337da2899SCharles.Forsyth 			if(t->item == it) {
169437da2899SCharles.Forsyth 				if (it == *below || below == &it->next)
169537da2899SCharles.Forsyth 					below = l;
169637da2899SCharles.Forsyth 				if (it == c->tail)
169737da2899SCharles.Forsyth 					c->tail = prev;
169837da2899SCharles.Forsyth 				*l = it->next;
169937da2899SCharles.Forsyth 				*itemtail = it;
170037da2899SCharles.Forsyth 				iprev = it;
170137da2899SCharles.Forsyth 				itemtail = &it->next;
170237da2899SCharles.Forsyth 				tkbbmax(&c->update, &it->p.bb);
170337da2899SCharles.Forsyth 				goto next;
170437da2899SCharles.Forsyth 			}
170537da2899SCharles.Forsyth 		}
170637da2899SCharles.Forsyth 		prev = it;
170737da2899SCharles.Forsyth 		l = &it->next;
170837da2899SCharles.Forsyth next:;
170937da2899SCharles.Forsyth 	}
171037da2899SCharles.Forsyth 	if (prev == nil)
171137da2899SCharles.Forsyth 		c->tail = iprev;
171237da2899SCharles.Forsyth 	*itemtail = *below;
171337da2899SCharles.Forsyth 	*below = items;
171437da2899SCharles.Forsyth 	tkcvssetdirty(tk);
171537da2899SCharles.Forsyth 	return nil;
171637da2899SCharles.Forsyth }
171737da2899SCharles.Forsyth 
171837da2899SCharles.Forsyth static char*
tkcvsmove(Tk * tk,char * arg,char ** val)171937da2899SCharles.Forsyth tkcvsmove(Tk *tk, char *arg, char **val)
172037da2899SCharles.Forsyth {
172137da2899SCharles.Forsyth 	TkCtag *t;
172237da2899SCharles.Forsyth 	int fx, fy;
172337da2899SCharles.Forsyth 	TkTop *top;
172437da2899SCharles.Forsyth 	TkCpoints *p;
172537da2899SCharles.Forsyth 	TkName *tag;
172637da2899SCharles.Forsyth 	Rectangle *u;
172737da2899SCharles.Forsyth 	TkCitem *item;
172837da2899SCharles.Forsyth 	char *e;
172937da2899SCharles.Forsyth 	char buf[Tkmaxitem];
173037da2899SCharles.Forsyth 
173137da2899SCharles.Forsyth 	USED(val);
173237da2899SCharles.Forsyth 	top = tk->env->top;
173337da2899SCharles.Forsyth 	arg = tkword(top, arg, buf, buf+sizeof(buf), nil);
173437da2899SCharles.Forsyth 	tag = tkctaglook(tk, nil, buf);
173537da2899SCharles.Forsyth 	if(tag == nil)
173637da2899SCharles.Forsyth 		return nil;
173737da2899SCharles.Forsyth 
173837da2899SCharles.Forsyth 	e = tkfracword(top, &arg, &fx, nil);
173937da2899SCharles.Forsyth 	if (e != nil)
174037da2899SCharles.Forsyth 		return e;
174137da2899SCharles.Forsyth 	e = tkfracword(top, &arg, &fy, nil);
174237da2899SCharles.Forsyth 	if(e != nil)
174337da2899SCharles.Forsyth 		return e;
174437da2899SCharles.Forsyth 
174537da2899SCharles.Forsyth 	u = &TKobj(TkCanvas, tk)->update;
174637da2899SCharles.Forsyth 	for(t = tag->obj; t; t = t->taglist) {
174737da2899SCharles.Forsyth 		item = t->item;
174837da2899SCharles.Forsyth 		p = &item->p;
174937da2899SCharles.Forsyth 		tkbbmax(u, &p->bb);
175037da2899SCharles.Forsyth 		tkcimethod[item->type].coord(item, nil, fx, fy);
175137da2899SCharles.Forsyth 		tkbbmax(u, &p->bb);
175237da2899SCharles.Forsyth 	}
175337da2899SCharles.Forsyth 	tkcvssetdirty(tk);
175437da2899SCharles.Forsyth 	return nil;
175537da2899SCharles.Forsyth }
175637da2899SCharles.Forsyth 
175737da2899SCharles.Forsyth static char*
tkcvsraise(Tk * tk,char * arg,char ** val)175837da2899SCharles.Forsyth tkcvsraise(Tk *tk, char *arg, char **val)
175937da2899SCharles.Forsyth {
176037da2899SCharles.Forsyth 	TkCtag *t;
176137da2899SCharles.Forsyth 	TkCanvas *c;
176237da2899SCharles.Forsyth 	TkName *f, *a;
176337da2899SCharles.Forsyth 	char buf[Tkmaxitem];
176437da2899SCharles.Forsyth 	TkCitem *prev, *it, *above, *items, *itemtail, *next;
176537da2899SCharles.Forsyth 
176637da2899SCharles.Forsyth 	USED(val);
176737da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
176837da2899SCharles.Forsyth 
176937da2899SCharles.Forsyth 	arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
177037da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
177137da2899SCharles.Forsyth 	if(f == nil)
177237da2899SCharles.Forsyth 		return nil;
177337da2899SCharles.Forsyth 
177437da2899SCharles.Forsyth 	above = c->tail;
177537da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
177637da2899SCharles.Forsyth 	if(buf[0] != '\0') {
177737da2899SCharles.Forsyth 		a = tkctaglook(tk, nil, buf);
177837da2899SCharles.Forsyth 		if(a == nil)
177937da2899SCharles.Forsyth 			return TkBadtg;
178037da2899SCharles.Forsyth 		/*
178137da2899SCharles.Forsyth 		 * find topmost item in the display list matching the "above" tag
178237da2899SCharles.Forsyth 		 */
178337da2899SCharles.Forsyth 		for(it = c->head; it != nil; it = it->next) {
178437da2899SCharles.Forsyth 			for(t = a->obj; t; t = t->taglist)
178537da2899SCharles.Forsyth 				if(t->item == it)
178637da2899SCharles.Forsyth 					above = it;
178737da2899SCharles.Forsyth 		}
178837da2899SCharles.Forsyth 	}
178937da2899SCharles.Forsyth 	prev = nil;
179037da2899SCharles.Forsyth 	items = itemtail = nil;
179137da2899SCharles.Forsyth 	for (it = c->head; it != nil; it = next) {
179237da2899SCharles.Forsyth 		next = it->next;
179337da2899SCharles.Forsyth 		for (t = f->obj; t; t = t->taglist) {
179437da2899SCharles.Forsyth 			if(t->item == it) {
179537da2899SCharles.Forsyth 				if (it == above)
179637da2899SCharles.Forsyth 					above = next;
179737da2899SCharles.Forsyth 				if (prev)
179837da2899SCharles.Forsyth 					prev->next = next;
179937da2899SCharles.Forsyth 				else
180037da2899SCharles.Forsyth 					c->head = next;
180137da2899SCharles.Forsyth 				if (itemtail)
180237da2899SCharles.Forsyth 					itemtail->next = it;
180337da2899SCharles.Forsyth 				else
180437da2899SCharles.Forsyth 					items = it;
180537da2899SCharles.Forsyth 				itemtail = it;
180637da2899SCharles.Forsyth 				tkbbmax(&c->update, &it->p.bb);
180737da2899SCharles.Forsyth 				goto next;
180837da2899SCharles.Forsyth 			}
180937da2899SCharles.Forsyth 		}
181037da2899SCharles.Forsyth 		prev = it;
181137da2899SCharles.Forsyth next:;
181237da2899SCharles.Forsyth 	}
181337da2899SCharles.Forsyth 	if (items != nil) {
181437da2899SCharles.Forsyth 		if (above) {
181537da2899SCharles.Forsyth 			itemtail->next = above->next;
181637da2899SCharles.Forsyth 			if (above->next == nil)
181737da2899SCharles.Forsyth 				c->tail = itemtail;
181837da2899SCharles.Forsyth 			above->next = items;
181937da2899SCharles.Forsyth 		} else {
182037da2899SCharles.Forsyth 			if (prev)
182137da2899SCharles.Forsyth 				prev->next = items;
182237da2899SCharles.Forsyth 			else
182337da2899SCharles.Forsyth 				c->head = items;
182437da2899SCharles.Forsyth 			c->tail = itemtail;
182537da2899SCharles.Forsyth 			itemtail->next = nil;
182637da2899SCharles.Forsyth 		}
182737da2899SCharles.Forsyth 	}
182837da2899SCharles.Forsyth 
182937da2899SCharles.Forsyth 	tkcvssetdirty(tk);
183037da2899SCharles.Forsyth 	return nil;
183137da2899SCharles.Forsyth }
183237da2899SCharles.Forsyth 
183337da2899SCharles.Forsyth static char*
tkcvstype(Tk * tk,char * arg,char ** val)183437da2899SCharles.Forsyth tkcvstype(Tk *tk, char *arg, char **val)
183537da2899SCharles.Forsyth {
183637da2899SCharles.Forsyth 	TkCtag *t;
183737da2899SCharles.Forsyth 	TkName *f;
183837da2899SCharles.Forsyth 	TkCanvas *c;
183937da2899SCharles.Forsyth 	char buf[Tkmaxitem];
184037da2899SCharles.Forsyth 
184137da2899SCharles.Forsyth 	tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
184237da2899SCharles.Forsyth 	if(buf[0] == '\0')
184337da2899SCharles.Forsyth 		return TkBadvl;
184437da2899SCharles.Forsyth 
184537da2899SCharles.Forsyth 	f = tkctaglook(tk, nil, buf);
184637da2899SCharles.Forsyth 	if(f == nil || f->obj == nil)
184737da2899SCharles.Forsyth 		return nil;
184837da2899SCharles.Forsyth 
184937da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
185037da2899SCharles.Forsyth 
185137da2899SCharles.Forsyth 	t = tkcfirsttag(c->head, f->obj);
185237da2899SCharles.Forsyth 	if(t == nil)
185337da2899SCharles.Forsyth 		return nil;
185437da2899SCharles.Forsyth 
185537da2899SCharles.Forsyth 	return tkvalue(val, "%s", tkcimethod[t->item->type].name);
185637da2899SCharles.Forsyth }
185737da2899SCharles.Forsyth 
185837da2899SCharles.Forsyth static char*
tkcvsview(Tk * tk,char * arg,char ** val,int nl,int * posn,int min,int max,int inc)185937da2899SCharles.Forsyth tkcvsview(Tk *tk, char *arg, char **val, int nl, int *posn, int min, int max, int inc)
186037da2899SCharles.Forsyth {
186137da2899SCharles.Forsyth 	TkTop *t;
186237da2899SCharles.Forsyth 	int top, bot, diff, amount;
186337da2899SCharles.Forsyth 	char *e;
186437da2899SCharles.Forsyth 	char buf[Tkmaxitem], *v;
186537da2899SCharles.Forsyth 
186637da2899SCharles.Forsyth 	diff = max-min;
186737da2899SCharles.Forsyth 	if(*arg == '\0') {
186837da2899SCharles.Forsyth 		if ( diff == 0 )
186937da2899SCharles.Forsyth 			top = bot = 0;
187037da2899SCharles.Forsyth 		else {
187137da2899SCharles.Forsyth 			top = TKI2F(*posn-min)/diff;
187237da2899SCharles.Forsyth 			bot = TKI2F(*posn+nl-min)/diff;
187337da2899SCharles.Forsyth 		}
187437da2899SCharles.Forsyth 		v = tkfprint(buf, top);
187537da2899SCharles.Forsyth 		*v++ = ' ';
187637da2899SCharles.Forsyth 		tkfprint(v, bot);
187737da2899SCharles.Forsyth 		return tkvalue(val, "%s", buf);
187837da2899SCharles.Forsyth 	}
187937da2899SCharles.Forsyth 
188037da2899SCharles.Forsyth 	t = tk->env->top;
188137da2899SCharles.Forsyth 	arg = tkword(t, arg, buf, buf+sizeof(buf), nil);
188237da2899SCharles.Forsyth 	if(strcmp(buf, "moveto") == 0) {
188337da2899SCharles.Forsyth 		e = tkfrac(&arg, &top, nil);
188437da2899SCharles.Forsyth 		if (e != nil)
188537da2899SCharles.Forsyth 			return e;
188637da2899SCharles.Forsyth 		*posn = min + TKF2I((top+1)*diff);
188737da2899SCharles.Forsyth 	}
188837da2899SCharles.Forsyth 	else
188937da2899SCharles.Forsyth 	if(strcmp(buf, "scroll") == 0) {
189037da2899SCharles.Forsyth 		arg = tkword(t, arg, buf, buf+sizeof(buf), nil);
189137da2899SCharles.Forsyth 		amount = atoi(buf);
189237da2899SCharles.Forsyth 		tkword(t, arg, buf, buf+sizeof(buf), nil);
189337da2899SCharles.Forsyth 		if(buf[0] == 'p')		/* Pages */
189437da2899SCharles.Forsyth 			amount = amount * nl * 9 /10;
189537da2899SCharles.Forsyth 		else if (inc > 0)
189637da2899SCharles.Forsyth 			amount *= inc;
189737da2899SCharles.Forsyth 		else
189837da2899SCharles.Forsyth 			amount = amount * nl / 10;
189937da2899SCharles.Forsyth 		*posn += amount;
190037da2899SCharles.Forsyth 	}
190137da2899SCharles.Forsyth 	else
190237da2899SCharles.Forsyth 		return TkBadcm;
190337da2899SCharles.Forsyth 
190437da2899SCharles.Forsyth 	bot = max - nl;
190537da2899SCharles.Forsyth 	if(*posn > bot)
190637da2899SCharles.Forsyth 		*posn = bot;
190737da2899SCharles.Forsyth 	if(*posn < min)
190837da2899SCharles.Forsyth 		*posn = min;
190937da2899SCharles.Forsyth 
191037da2899SCharles.Forsyth 	tk->dirty = tkrect(tk, 0);
191137da2899SCharles.Forsyth 	return nil;
191237da2899SCharles.Forsyth }
191337da2899SCharles.Forsyth 
191437da2899SCharles.Forsyth static char*
tkcvsyview(Tk * tk,char * arg,char ** val)191537da2899SCharles.Forsyth tkcvsyview(Tk *tk, char *arg, char **val)
191637da2899SCharles.Forsyth {
191737da2899SCharles.Forsyth 	int si;
191837da2899SCharles.Forsyth 	char *e;
191937da2899SCharles.Forsyth 	TkCanvas *c = TKobj(TkCanvas, tk);
192037da2899SCharles.Forsyth 
192137da2899SCharles.Forsyth 	si = TKF2I(c->yscrolli);
192237da2899SCharles.Forsyth 	e = tkcvsview(tk, arg, val, tk->act.height, &c->view.y, c->region.min.y, c->region.max.y, si);
192337da2899SCharles.Forsyth 	tkcvssv(tk);
192437da2899SCharles.Forsyth 	return e;
192537da2899SCharles.Forsyth }
192637da2899SCharles.Forsyth 
192737da2899SCharles.Forsyth static char*
tkcvsxview(Tk * tk,char * arg,char ** val)192837da2899SCharles.Forsyth tkcvsxview(Tk *tk, char *arg, char **val)
192937da2899SCharles.Forsyth {
193037da2899SCharles.Forsyth 	int si;
193137da2899SCharles.Forsyth 	char *e;
193237da2899SCharles.Forsyth 	TkCanvas *c = TKobj(TkCanvas, tk);
193337da2899SCharles.Forsyth 
193437da2899SCharles.Forsyth 	si = TKF2I(c->xscrolli);
193537da2899SCharles.Forsyth 	e = tkcvsview(tk, arg, val, tk->act.width, &c->view.x, c->region.min.x, c->region.max.x, si);
193637da2899SCharles.Forsyth 	tkcvssh(tk);
193737da2899SCharles.Forsyth 	return e;
193837da2899SCharles.Forsyth }
193937da2899SCharles.Forsyth 
194037da2899SCharles.Forsyth /*
194137da2899SCharles.Forsyth  * return in posn the new view origin such that (preferably) smin and smax
194237da2899SCharles.Forsyth  * lie between cmin and cmax (cmin is the current view origin, and cmax the
194337da2899SCharles.Forsyth  * other end of the visible area).
194437da2899SCharles.Forsyth  * adjust posn (the view origin) so that (preferably) both smin and smax lie
194537da2899SCharles.Forsyth  * inside cmin to cmax. if both smin and smax cannot fit, then
194637da2899SCharles.Forsyth  * at least make sure that spref (smin<=spref<=smax) is visible.
194737da2899SCharles.Forsyth  * return 0 if no adjustment is required (the interval is already visible).
194837da2899SCharles.Forsyth  *
194937da2899SCharles.Forsyth  * attempt to make an adjustment as small as possible that
195037da2899SCharles.Forsyth  * fits these criteria.
195137da2899SCharles.Forsyth  */
195237da2899SCharles.Forsyth static int
tkadjustvis(int * posn,int c0,int c1,int s0,int s1,int spref)195337da2899SCharles.Forsyth tkadjustvis(int *posn, int c0, int c1, int s0, int s1, int spref)
195437da2899SCharles.Forsyth {
195537da2899SCharles.Forsyth 	int d, v;
195637da2899SCharles.Forsyth 
195737da2899SCharles.Forsyth 	d = c1 - c0;		/* visible width */
195837da2899SCharles.Forsyth 
195937da2899SCharles.Forsyth 	/*
196037da2899SCharles.Forsyth 	 * if requested range fits inside visible range,
196137da2899SCharles.Forsyth 	 * no adjustment is necessary
196237da2899SCharles.Forsyth 	 */
196337da2899SCharles.Forsyth 	if (c0 <= s0 && s1 <= c1)
196437da2899SCharles.Forsyth 		return 0;
196537da2899SCharles.Forsyth 
196637da2899SCharles.Forsyth 	/*
196737da2899SCharles.Forsyth 	 * if requested range fits, make it fully visible
196837da2899SCharles.Forsyth 	 */
196937da2899SCharles.Forsyth 	if (s1 - s0 < d) {
197037da2899SCharles.Forsyth 		if (s0 < c0)
197137da2899SCharles.Forsyth 			v = s0;
197237da2899SCharles.Forsyth 		else
197337da2899SCharles.Forsyth 			v = s1 - d;
197437da2899SCharles.Forsyth 	} else {
197537da2899SCharles.Forsyth 		/*
197637da2899SCharles.Forsyth 		 * choose upper or lower end of requested range,
197737da2899SCharles.Forsyth 		 * depending on which end of requested area is already
197837da2899SCharles.Forsyth 		 * visible (if any).
197937da2899SCharles.Forsyth 		 */
198037da2899SCharles.Forsyth 		if (c0 <= s1 && s1 < c1) {		/* overlapping left of visible */
198137da2899SCharles.Forsyth 			v = s1 - d;
198237da2899SCharles.Forsyth 			if (v > spref)
198337da2899SCharles.Forsyth 				v = spref;
198437da2899SCharles.Forsyth 		}
198537da2899SCharles.Forsyth 		else
198637da2899SCharles.Forsyth 		if (c0 <= s0 && s0 < c1) {		/* overlapping right of visible */
198737da2899SCharles.Forsyth 			v = s0;
198837da2899SCharles.Forsyth 			if (v + d <= spref)
198937da2899SCharles.Forsyth 				v = spref - d;
199037da2899SCharles.Forsyth 		}
199137da2899SCharles.Forsyth 		else
199237da2899SCharles.Forsyth 		if (s1 < c0) {				/* left of visible */
199337da2899SCharles.Forsyth 			v = spref;
199437da2899SCharles.Forsyth 			if (v + d > s1)
199537da2899SCharles.Forsyth 				v = s1 - d;
199637da2899SCharles.Forsyth 		}
199737da2899SCharles.Forsyth 		else {					/* right of visible */
199837da2899SCharles.Forsyth 			v = spref - d;
199937da2899SCharles.Forsyth 			if (v < s0)
200037da2899SCharles.Forsyth 				v = s0;
200137da2899SCharles.Forsyth 		}
200237da2899SCharles.Forsyth 	}
200337da2899SCharles.Forsyth 	*posn = v;
200437da2899SCharles.Forsyth 	return 1;
200537da2899SCharles.Forsyth }
200637da2899SCharles.Forsyth 
200737da2899SCharles.Forsyth static void
tkcvsseerect(Tk * tk,Rectangle r,Point p)200837da2899SCharles.Forsyth tkcvsseerect(Tk *tk, Rectangle r, Point p)
200937da2899SCharles.Forsyth {
201037da2899SCharles.Forsyth 	TkCanvas *c;
201137da2899SCharles.Forsyth 	int scrollh, scrollv;
201237da2899SCharles.Forsyth 
201337da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
201437da2899SCharles.Forsyth 
201537da2899SCharles.Forsyth 	scrollh = tkadjustvis(&c->view.x, c->view.x, c->view.x + tk->act.width,
201637da2899SCharles.Forsyth 			r.min.x, r.max.x, p.x);
201737da2899SCharles.Forsyth 	scrollv = tkadjustvis(&c->view.y, c->view.y, c->view.y + tk->act.height,
201837da2899SCharles.Forsyth 			r.min.y, r.max.y, p.y);
201937da2899SCharles.Forsyth 	if (scrollh)
202037da2899SCharles.Forsyth 		tkcvssh(tk);
202137da2899SCharles.Forsyth 	if (scrollv)
202237da2899SCharles.Forsyth 		tkcvssv(tk);
202337da2899SCharles.Forsyth 	if (scrollh || scrollv)
202437da2899SCharles.Forsyth 		tk->dirty = tkrect(tk, 0);
202537da2899SCharles.Forsyth }
202637da2899SCharles.Forsyth 
202737da2899SCharles.Forsyth static char*
tkcvssee(Tk * tk,char * arg,char ** val)202837da2899SCharles.Forsyth tkcvssee(Tk *tk, char *arg, char **val)
202937da2899SCharles.Forsyth {
203037da2899SCharles.Forsyth 	Rectangle r;
203137da2899SCharles.Forsyth 	int n, coords[4];
203237da2899SCharles.Forsyth 	char *e;
203337da2899SCharles.Forsyth 
203437da2899SCharles.Forsyth 	USED(val);
203537da2899SCharles.Forsyth 	n = 0;
203637da2899SCharles.Forsyth 	while (n < 4) {
203737da2899SCharles.Forsyth 		if (*arg == '\0')
203837da2899SCharles.Forsyth 			break;
203937da2899SCharles.Forsyth 		e = tkfracword(tk->env->top, &arg, &coords[n++], nil);
204037da2899SCharles.Forsyth 		if (e != nil)
204137da2899SCharles.Forsyth 			return e;
204237da2899SCharles.Forsyth 	}
204337da2899SCharles.Forsyth 
204437da2899SCharles.Forsyth 	if (n != 2 && n != 4)
204537da2899SCharles.Forsyth 		return TkFewpt;
204637da2899SCharles.Forsyth 
204737da2899SCharles.Forsyth 	r.min.x = TKF2I(coords[0]);
204837da2899SCharles.Forsyth 	r.min.y = TKF2I(coords[1]);
204937da2899SCharles.Forsyth 	if (n == 4) {
205037da2899SCharles.Forsyth 		r.max.x = TKF2I(coords[2]);
205137da2899SCharles.Forsyth 		r.max.y = TKF2I(coords[3]);
205237da2899SCharles.Forsyth 	} else
205337da2899SCharles.Forsyth 		r.max = r.min;
205437da2899SCharles.Forsyth 	r = canonrect(r);
205537da2899SCharles.Forsyth 	/*
205637da2899SCharles.Forsyth 	 * XXX should intersect r with scrollregion here, as you shouldn't
205737da2899SCharles.Forsyth 	 * be able to display things outside the scroll region. (??)
205837da2899SCharles.Forsyth 	 */
205937da2899SCharles.Forsyth 
206037da2899SCharles.Forsyth 	tkcvsseerect(tk, r, r.min);
206137da2899SCharles.Forsyth 	return nil;
206237da2899SCharles.Forsyth }
206337da2899SCharles.Forsyth 
206437da2899SCharles.Forsyth static void
tkcvsseesub(Tk * tk,Rectangle * rr,Point * pp)206537da2899SCharles.Forsyth tkcvsseesub(Tk *tk, Rectangle *rr, Point *pp)
206637da2899SCharles.Forsyth {
206737da2899SCharles.Forsyth 	Rectangle r;
206837da2899SCharles.Forsyth 	Point p;
206937da2899SCharles.Forsyth 	TkCanvas *c;
207037da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
207137da2899SCharles.Forsyth 
207237da2899SCharles.Forsyth 	r = rectaddpt(*rr, c->view);
207337da2899SCharles.Forsyth 	p = addpt(*pp, c->view);
207437da2899SCharles.Forsyth 
207537da2899SCharles.Forsyth 	tkcvsseerect(tk, r, p);
207637da2899SCharles.Forsyth 
207737da2899SCharles.Forsyth 	*rr = rectsubpt(r, c->view);
207837da2899SCharles.Forsyth 	*pp = subpt(p, c->view);
207937da2899SCharles.Forsyth }
208037da2899SCharles.Forsyth 
208137da2899SCharles.Forsyth static void
tkcvsgetimgs(Tk * tk,Image ** image,Image ** mask)208237da2899SCharles.Forsyth tkcvsgetimgs(Tk* tk, Image **image, Image **mask)
208337da2899SCharles.Forsyth {
208437da2899SCharles.Forsyth 	TkCanvas *c;
208537da2899SCharles.Forsyth 	c = TKobj(TkCanvas, tk);
208637da2899SCharles.Forsyth 
208737da2899SCharles.Forsyth 	*image = c->image;
208837da2899SCharles.Forsyth 	*mask = c->mask;		/* XXX this is wrong - the mask image has nothing to do with the main image */
208937da2899SCharles.Forsyth }
209037da2899SCharles.Forsyth 
209137da2899SCharles.Forsyth TkCimeth tkcimethod[] =
209237da2899SCharles.Forsyth {
209337da2899SCharles.Forsyth 	"line",		tkcvslinecreat,
209437da2899SCharles.Forsyth 			tkcvslinedraw,
209537da2899SCharles.Forsyth 			tkcvslinefree,
209637da2899SCharles.Forsyth 			tkcvslinecoord,
209737da2899SCharles.Forsyth 			tkcvslinecget,
209837da2899SCharles.Forsyth 			tkcvslineconf,
209937da2899SCharles.Forsyth 			tkcvslinehit,
210037da2899SCharles.Forsyth 
210137da2899SCharles.Forsyth 	"text",		tkcvstextcreat,
210237da2899SCharles.Forsyth 			tkcvstextdraw,
210337da2899SCharles.Forsyth 			tkcvstextfree,
210437da2899SCharles.Forsyth 			tkcvstextcoord,
210537da2899SCharles.Forsyth 			tkcvstextcget,
210637da2899SCharles.Forsyth 			tkcvstextconf,
210737da2899SCharles.Forsyth 			nil,
210837da2899SCharles.Forsyth 
210937da2899SCharles.Forsyth 	"rectangle",	tkcvsrectcreat,
211037da2899SCharles.Forsyth 			tkcvsrectdraw,
211137da2899SCharles.Forsyth 			tkcvsrectfree,
211237da2899SCharles.Forsyth 			tkcvsrectcoord,
211337da2899SCharles.Forsyth 			tkcvsrectcget,
211437da2899SCharles.Forsyth 			tkcvsrectconf,
211537da2899SCharles.Forsyth 			nil,
211637da2899SCharles.Forsyth 
211737da2899SCharles.Forsyth 	"oval",		tkcvsovalcreat,
211837da2899SCharles.Forsyth 			tkcvsovaldraw,
211937da2899SCharles.Forsyth 			tkcvsovalfree,
212037da2899SCharles.Forsyth 			tkcvsovalcoord,
212137da2899SCharles.Forsyth 			tkcvsovalcget,
212237da2899SCharles.Forsyth 			tkcvsovalconf,
212337da2899SCharles.Forsyth 			tkcvsovalhit,
212437da2899SCharles.Forsyth 
212537da2899SCharles.Forsyth 	"bitmap",	tkcvsbitcreat,
212637da2899SCharles.Forsyth 			tkcvsbitdraw,
212737da2899SCharles.Forsyth 			tkcvsbitfree,
212837da2899SCharles.Forsyth 			tkcvsbitcoord,
212937da2899SCharles.Forsyth 			tkcvsbitcget,
213037da2899SCharles.Forsyth 			tkcvsbitconf,
213137da2899SCharles.Forsyth 			nil,
213237da2899SCharles.Forsyth 
213337da2899SCharles.Forsyth 	"polygon",	tkcvspolycreat,
213437da2899SCharles.Forsyth 			tkcvspolydraw,
213537da2899SCharles.Forsyth 			tkcvspolyfree,
213637da2899SCharles.Forsyth 			tkcvspolycoord,
213737da2899SCharles.Forsyth 			tkcvspolycget,
213837da2899SCharles.Forsyth 			tkcvspolyconf,
213937da2899SCharles.Forsyth 			tkcvspolyhit,
214037da2899SCharles.Forsyth 
214137da2899SCharles.Forsyth 	"window",	tkcvswindcreat,
214237da2899SCharles.Forsyth 			tkcvswinddraw,
214337da2899SCharles.Forsyth 			tkcvswindfree,
214437da2899SCharles.Forsyth 			tkcvswindcoord,
214537da2899SCharles.Forsyth 			tkcvswindcget,
214637da2899SCharles.Forsyth 			tkcvswindconf,
214737da2899SCharles.Forsyth 			nil,
214837da2899SCharles.Forsyth 
214937da2899SCharles.Forsyth 	"image",	tkcvsimgcreat,
215037da2899SCharles.Forsyth 			tkcvsimgdraw,
215137da2899SCharles.Forsyth 			tkcvsimgfree,
215237da2899SCharles.Forsyth 			tkcvsimgcoord,
215337da2899SCharles.Forsyth 			tkcvsimgcget,
215437da2899SCharles.Forsyth 			tkcvsimgconf,
215537da2899SCharles.Forsyth 			nil,
215637da2899SCharles.Forsyth 
215737da2899SCharles.Forsyth 	"arc",		tkcvsarccreat,
215837da2899SCharles.Forsyth 			tkcvsarcdraw,
215937da2899SCharles.Forsyth 			tkcvsarcfree,
216037da2899SCharles.Forsyth 			tkcvsarccoord,
216137da2899SCharles.Forsyth 			tkcvsarccget,
216237da2899SCharles.Forsyth 			tkcvsarcconf,
216337da2899SCharles.Forsyth 			nil,
216437da2899SCharles.Forsyth 	nil
216537da2899SCharles.Forsyth };
216637da2899SCharles.Forsyth 
216737da2899SCharles.Forsyth static
216837da2899SCharles.Forsyth TkCmdtab tkcanvcmd[] =
216937da2899SCharles.Forsyth {
217037da2899SCharles.Forsyth 	"addtag",		tkcvsaddtag,
217137da2899SCharles.Forsyth 	"bbox",			tkcvsbbox,
217237da2899SCharles.Forsyth 	"bind",			tkcvsbind,
217337da2899SCharles.Forsyth 	"cget",			tkcvscget,
217437da2899SCharles.Forsyth 	"configure",		tkcvsconf,
217537da2899SCharles.Forsyth 	"create",		tkcvscreate,
217637da2899SCharles.Forsyth 	"canvasx",		tkcvscanvx,
217737da2899SCharles.Forsyth 	"canvasy",		tkcvscanvy,
217837da2899SCharles.Forsyth 	"coords",		tkcvscoords,
217937da2899SCharles.Forsyth 	"dchars",		tkcvsdchars,
218037da2899SCharles.Forsyth 	"delete",		tkcvsdelete,
218137da2899SCharles.Forsyth 	"dtag",			tkcvsdtag,
218237da2899SCharles.Forsyth 	"find",			tkcvsfind,
218337da2899SCharles.Forsyth 	"focus",		tkcvsfocus,
218437da2899SCharles.Forsyth 	"gettags",		tkcvsgettags,
218537da2899SCharles.Forsyth 	"grab",		tkcvsgrab,
218637da2899SCharles.Forsyth 	"icursor",		tkcvsicursor,
218737da2899SCharles.Forsyth 	"insert",		tkcvsinsert,
218837da2899SCharles.Forsyth 	"index",		tkcvsindex,
218937da2899SCharles.Forsyth 	"itemcget",		tkcvsitemcget,
219037da2899SCharles.Forsyth 	"itemconfigure",	tkcvsitemconf,
219137da2899SCharles.Forsyth 	"lower",		tkcvslower,
219237da2899SCharles.Forsyth 	"move",			tkcvsmove,
219337da2899SCharles.Forsyth 	"raise",		tkcvsraise,
219437da2899SCharles.Forsyth 	"screenx",		tkcvsscreenx,
219537da2899SCharles.Forsyth 	"screeny",		tkcvsscreeny,
219637da2899SCharles.Forsyth 	"see",		tkcvssee,
219737da2899SCharles.Forsyth 	"select",		tkcvsselect,
219837da2899SCharles.Forsyth 	"scale",		tkcvsscale,
219937da2899SCharles.Forsyth 	"type",			tkcvstype,
220037da2899SCharles.Forsyth 	"yview",		tkcvsyview,
220137da2899SCharles.Forsyth 	"xview",		tkcvsxview,
220237da2899SCharles.Forsyth 	nil
220337da2899SCharles.Forsyth };
220437da2899SCharles.Forsyth 
220537da2899SCharles.Forsyth TkMethod canvasmethod = {
220637da2899SCharles.Forsyth 	"canvas",
220737da2899SCharles.Forsyth 	tkcanvcmd,
220837da2899SCharles.Forsyth 	tkfreecanv,
220937da2899SCharles.Forsyth 	tkdrawcanv,
221037da2899SCharles.Forsyth 	tkcvsgeom,
221137da2899SCharles.Forsyth 	tkcvsgetimgs,
221237da2899SCharles.Forsyth 	tkcvsfocusorder,
221337da2899SCharles.Forsyth 	tkcvsdirty,
221437da2899SCharles.Forsyth 	tkcvsrelpos,
221537da2899SCharles.Forsyth 	tkcvsevent,
221637da2899SCharles.Forsyth 	tkcvsseesub,
2217*5849851aSforsyth 	tkcvsinwindow,
2218*5849851aSforsyth 	nil,
2219*5849851aSforsyth 	tkcvsforgetsub,
222037da2899SCharles.Forsyth };
2221