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