137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "keyboard.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth #include "listb.h"
637da2899SCharles.Forsyth
737da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth /* Layout constants */
1037da2899SCharles.Forsyth enum {
1137da2899SCharles.Forsyth Listpadx = 2, /* X padding of text in listboxes */
1237da2899SCharles.Forsyth };
1337da2899SCharles.Forsyth
1437da2899SCharles.Forsyth typedef struct TkLentry TkLentry;
1537da2899SCharles.Forsyth typedef struct TkListbox TkListbox;
1637da2899SCharles.Forsyth
1737da2899SCharles.Forsyth struct TkLentry
1837da2899SCharles.Forsyth {
1937da2899SCharles.Forsyth TkLentry* link;
2037da2899SCharles.Forsyth int flag;
2137da2899SCharles.Forsyth int width;
2237da2899SCharles.Forsyth char text[TKSTRUCTALIGN];
2337da2899SCharles.Forsyth };
2437da2899SCharles.Forsyth
2537da2899SCharles.Forsyth struct TkListbox
2637da2899SCharles.Forsyth {
2737da2899SCharles.Forsyth TkLentry* head;
2837da2899SCharles.Forsyth TkLentry* anchor;
2937da2899SCharles.Forsyth TkLentry* active;
3037da2899SCharles.Forsyth int yelem; /* Y element at top of box */
3137da2899SCharles.Forsyth int xdelta; /* h-scroll position */
3237da2899SCharles.Forsyth int nitem;
3337da2899SCharles.Forsyth int nwidth;
3437da2899SCharles.Forsyth int selmode;
3537da2899SCharles.Forsyth int sborderwidth;
3637da2899SCharles.Forsyth char* xscroll;
3737da2899SCharles.Forsyth char* yscroll;
3837da2899SCharles.Forsyth };
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth TkStab tkselmode[] =
4137da2899SCharles.Forsyth {
4237da2899SCharles.Forsyth "single", TKsingle,
4337da2899SCharles.Forsyth "browse", TKbrowse,
4437da2899SCharles.Forsyth "multiple", TKmultiple,
4537da2899SCharles.Forsyth "extended", TKextended,
4637da2899SCharles.Forsyth nil
4737da2899SCharles.Forsyth };
4837da2899SCharles.Forsyth
4937da2899SCharles.Forsyth static
5037da2899SCharles.Forsyth TkOption opts[] =
5137da2899SCharles.Forsyth {
5237da2899SCharles.Forsyth "xscrollcommand", OPTtext, O(TkListbox, xscroll), nil,
5337da2899SCharles.Forsyth "yscrollcommand", OPTtext, O(TkListbox, yscroll), nil,
5437da2899SCharles.Forsyth "selectmode", OPTstab, O(TkListbox, selmode), tkselmode,
5537da2899SCharles.Forsyth "selectborderwidth", OPTnndist, O(TkListbox, sborderwidth), nil,
5637da2899SCharles.Forsyth nil
5737da2899SCharles.Forsyth };
5837da2899SCharles.Forsyth
5937da2899SCharles.Forsyth static
6037da2899SCharles.Forsyth TkEbind b[] =
6137da2899SCharles.Forsyth {
6237da2899SCharles.Forsyth {TkButton1P, "%W tkListbButton1P %y"},
6337da2899SCharles.Forsyth {TkButton1R, "%W tkListbButton1R"},
6437da2899SCharles.Forsyth {TkButton1P|TkMotion, "%W tkListbButton1MP %y"},
6537da2899SCharles.Forsyth {TkMotion, ""},
6637da2899SCharles.Forsyth {TkKey, "%W tkListbKey 0x%K"},
6737da2899SCharles.Forsyth };
6837da2899SCharles.Forsyth
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth static int
lineheight(Tk * tk)7137da2899SCharles.Forsyth lineheight(Tk *tk)
7237da2899SCharles.Forsyth {
7337da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
7437da2899SCharles.Forsyth return tk->env->font->height+2*(l->sborderwidth+tk->highlightwidth);
7537da2899SCharles.Forsyth }
7637da2899SCharles.Forsyth
7737da2899SCharles.Forsyth char*
tklistbox(TkTop * t,char * arg,char ** ret)7837da2899SCharles.Forsyth tklistbox(TkTop *t, char *arg, char **ret)
7937da2899SCharles.Forsyth {
8037da2899SCharles.Forsyth Tk *tk;
8137da2899SCharles.Forsyth char *e;
8237da2899SCharles.Forsyth TkName *names;
8337da2899SCharles.Forsyth TkListbox *tkl;
8437da2899SCharles.Forsyth TkOptab tko[3];
8537da2899SCharles.Forsyth
8637da2899SCharles.Forsyth tk = tknewobj(t, TKlistbox, sizeof(Tk)+sizeof(TkListbox));
8737da2899SCharles.Forsyth if(tk == nil)
8837da2899SCharles.Forsyth return TkNomem;
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsyth tkl = TKobj(TkListbox, tk);
9137da2899SCharles.Forsyth tkl->sborderwidth = 1;
9237da2899SCharles.Forsyth tk->relief = TKsunken;
93c9ccdbd5Sforsyth tk->borderwidth = 1;
9437da2899SCharles.Forsyth tk->highlightwidth = 1;
9537da2899SCharles.Forsyth tk->flag |= Tktakefocus;
9637da2899SCharles.Forsyth tk->req.width = 170;
9737da2899SCharles.Forsyth tk->req.height = lineheight(tk)*10;
9837da2899SCharles.Forsyth
9937da2899SCharles.Forsyth tko[0].ptr = tk;
10037da2899SCharles.Forsyth tko[0].optab = tkgeneric;
10137da2899SCharles.Forsyth tko[1].ptr = tkl;
10237da2899SCharles.Forsyth tko[1].optab = opts;
10337da2899SCharles.Forsyth tko[2].ptr = nil;
10437da2899SCharles.Forsyth
10537da2899SCharles.Forsyth names = nil;
10637da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
10737da2899SCharles.Forsyth if(e != nil) {
10837da2899SCharles.Forsyth tkfreeobj(tk);
10937da2899SCharles.Forsyth return e;
11037da2899SCharles.Forsyth }
11137da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
11237da2899SCharles.Forsyth
11337da2899SCharles.Forsyth e = tkbindings(t, tk, b, nelem(b));
11437da2899SCharles.Forsyth if(e != nil) {
11537da2899SCharles.Forsyth tkfreeobj(tk);
11637da2899SCharles.Forsyth return e;
11737da2899SCharles.Forsyth }
11837da2899SCharles.Forsyth
11937da2899SCharles.Forsyth e = tkaddchild(t, tk, &names);
12037da2899SCharles.Forsyth tkfreename(names);
12137da2899SCharles.Forsyth if(e != nil) {
12237da2899SCharles.Forsyth tkfreeobj(tk);
12337da2899SCharles.Forsyth return e;
12437da2899SCharles.Forsyth }
12537da2899SCharles.Forsyth tk->name->link = nil;
12637da2899SCharles.Forsyth
12737da2899SCharles.Forsyth return tkvalue(ret, "%s", tk->name->name);
12837da2899SCharles.Forsyth }
12937da2899SCharles.Forsyth
13037da2899SCharles.Forsyth char*
tklistbcget(Tk * tk,char * arg,char ** val)13137da2899SCharles.Forsyth tklistbcget(Tk *tk, char *arg, char **val)
13237da2899SCharles.Forsyth {
13337da2899SCharles.Forsyth TkOptab tko[3];
13437da2899SCharles.Forsyth TkListbox *tkl = TKobj(TkListbox, tk);
13537da2899SCharles.Forsyth
13637da2899SCharles.Forsyth tko[0].ptr = tk;
13737da2899SCharles.Forsyth tko[0].optab = tkgeneric;
13837da2899SCharles.Forsyth tko[1].ptr = tkl;
13937da2899SCharles.Forsyth tko[1].optab = opts;
14037da2899SCharles.Forsyth tko[2].ptr = nil;
14137da2899SCharles.Forsyth
14237da2899SCharles.Forsyth return tkgencget(tko, arg, val, tk->env->top);
14337da2899SCharles.Forsyth }
14437da2899SCharles.Forsyth
14537da2899SCharles.Forsyth void
tkfreelistb(Tk * tk)14637da2899SCharles.Forsyth tkfreelistb(Tk *tk)
14737da2899SCharles.Forsyth {
14837da2899SCharles.Forsyth TkLentry *e, *next;
14937da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
15037da2899SCharles.Forsyth
15137da2899SCharles.Forsyth for(e = l->head; e; e = next) {
15237da2899SCharles.Forsyth next = e->link;
15337da2899SCharles.Forsyth free(e);
15437da2899SCharles.Forsyth }
15537da2899SCharles.Forsyth if(l->xscroll != nil)
15637da2899SCharles.Forsyth free(l->xscroll);
15737da2899SCharles.Forsyth if(l->yscroll != nil)
15837da2899SCharles.Forsyth free(l->yscroll);
15937da2899SCharles.Forsyth }
16037da2899SCharles.Forsyth
16137da2899SCharles.Forsyth char*
tkdrawlistb(Tk * tk,Point orig)16237da2899SCharles.Forsyth tkdrawlistb(Tk *tk, Point orig)
16337da2899SCharles.Forsyth {
16437da2899SCharles.Forsyth Point p;
16537da2899SCharles.Forsyth TkEnv *env;
16637da2899SCharles.Forsyth TkLentry *e;
16737da2899SCharles.Forsyth int lh, w, n, ly;
16837da2899SCharles.Forsyth Rectangle r, a;
16937da2899SCharles.Forsyth Image *i, *fg;
17037da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
17137da2899SCharles.Forsyth
17237da2899SCharles.Forsyth env = tk->env;
17337da2899SCharles.Forsyth
17437da2899SCharles.Forsyth r.min = ZP;
17537da2899SCharles.Forsyth r.max.x = tk->act.width + 2*tk->borderwidth;
17637da2899SCharles.Forsyth r.max.y = tk->act.height + 2*tk->borderwidth;
17737da2899SCharles.Forsyth i = tkitmp(env, r.max, TkCbackgnd);
17837da2899SCharles.Forsyth if(i == nil)
17937da2899SCharles.Forsyth return nil;
18037da2899SCharles.Forsyth
18137da2899SCharles.Forsyth w = tk->act.width;
18237da2899SCharles.Forsyth if (w < l->nwidth)
18337da2899SCharles.Forsyth w = l->nwidth;
18437da2899SCharles.Forsyth lh = lineheight(tk);
18537da2899SCharles.Forsyth ly = tk->borderwidth;
18637da2899SCharles.Forsyth p.x = tk->borderwidth+l->sborderwidth+tk->highlightwidth+Listpadx-l->xdelta;
18737da2899SCharles.Forsyth p.y = tk->borderwidth+l->sborderwidth+tk->highlightwidth;
18837da2899SCharles.Forsyth n = 0;
18937da2899SCharles.Forsyth for(e = l->head; e && ly < r.max.y; e = e->link) {
19037da2899SCharles.Forsyth if(n++ < l->yelem)
19137da2899SCharles.Forsyth continue;
19237da2899SCharles.Forsyth
19337da2899SCharles.Forsyth a.min.x = tk->borderwidth;
19437da2899SCharles.Forsyth a.min.y = ly;
19537da2899SCharles.Forsyth a.max.x = a.min.x + tk->act.width;
19637da2899SCharles.Forsyth a.max.y = a.min.y + lh;
19737da2899SCharles.Forsyth if(e->flag & Tkactivated) {
19837da2899SCharles.Forsyth draw(i, a, tkgc(env, TkCselectbgnd), nil, ZP);
19937da2899SCharles.Forsyth }
20037da2899SCharles.Forsyth
20137da2899SCharles.Forsyth if(e->flag & Tkactivated)
20237da2899SCharles.Forsyth fg = tkgc(env, TkCselectfgnd);
20337da2899SCharles.Forsyth else
20437da2899SCharles.Forsyth fg = tkgc(env, TkCforegnd);
20537da2899SCharles.Forsyth string(i, p, fg, p, env->font, e->text);
20637da2899SCharles.Forsyth if((e->flag & Tkactive) && tkhaskeyfocus(tk)) {
20737da2899SCharles.Forsyth a.min.x = tk->borderwidth-l->xdelta;
20837da2899SCharles.Forsyth a.max.x = a.min.x+w;
20937da2899SCharles.Forsyth a = insetrect(a, l->sborderwidth);
21037da2899SCharles.Forsyth tkbox(i, a, tk->highlightwidth, fg);
21137da2899SCharles.Forsyth }
21237da2899SCharles.Forsyth ly += lh;
21337da2899SCharles.Forsyth p.y += lh;
21437da2899SCharles.Forsyth }
21537da2899SCharles.Forsyth
21637da2899SCharles.Forsyth tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);
21737da2899SCharles.Forsyth
21837da2899SCharles.Forsyth p.x = tk->act.x + orig.x;
21937da2899SCharles.Forsyth p.y = tk->act.y + orig.y;
22037da2899SCharles.Forsyth r = rectaddpt(r, p);
22137da2899SCharles.Forsyth draw(tkimageof(tk), r, i, nil, ZP);
22237da2899SCharles.Forsyth
22337da2899SCharles.Forsyth return nil;
22437da2899SCharles.Forsyth }
22537da2899SCharles.Forsyth
22637da2899SCharles.Forsyth int
tklindex(Tk * tk,char * buf)22737da2899SCharles.Forsyth tklindex(Tk *tk, char *buf)
22837da2899SCharles.Forsyth {
22937da2899SCharles.Forsyth int index;
23037da2899SCharles.Forsyth TkListbox *l;
23137da2899SCharles.Forsyth TkLentry *e, *s;
23237da2899SCharles.Forsyth
23337da2899SCharles.Forsyth l = TKobj(TkListbox, tk);
23437da2899SCharles.Forsyth
23537da2899SCharles.Forsyth if(*buf == '@') {
23637da2899SCharles.Forsyth while(*buf && *buf != ',')
23737da2899SCharles.Forsyth buf++;
23837da2899SCharles.Forsyth index = l->yelem + atoi(buf+1)/lineheight(tk);
23937da2899SCharles.Forsyth if (index < 0)
24037da2899SCharles.Forsyth return 0;
24137da2899SCharles.Forsyth if (index > l->nitem)
24237da2899SCharles.Forsyth return l->nitem;
24337da2899SCharles.Forsyth return index;
24437da2899SCharles.Forsyth }
24537da2899SCharles.Forsyth if(*buf >= '0' && *buf <= '9')
24637da2899SCharles.Forsyth return atoi(buf);
24737da2899SCharles.Forsyth
24837da2899SCharles.Forsyth if(strcmp(buf, "end") == 0) {
24937da2899SCharles.Forsyth if(l->nitem == 0)
25037da2899SCharles.Forsyth return 0;
25137da2899SCharles.Forsyth return l->nitem-1;
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth index = 0;
25537da2899SCharles.Forsyth if(strcmp(buf, "active") == 0)
25637da2899SCharles.Forsyth s = l->active;
25737da2899SCharles.Forsyth else
25837da2899SCharles.Forsyth if(strcmp(buf, "anchor") == 0)
25937da2899SCharles.Forsyth s = l->anchor;
26037da2899SCharles.Forsyth else
26137da2899SCharles.Forsyth return -1;
26237da2899SCharles.Forsyth
26337da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
26437da2899SCharles.Forsyth if(e == s)
26537da2899SCharles.Forsyth return index;
26637da2899SCharles.Forsyth index++;
26737da2899SCharles.Forsyth }
26837da2899SCharles.Forsyth return -1;
26937da2899SCharles.Forsyth }
27037da2899SCharles.Forsyth
27137da2899SCharles.Forsyth void
tklistsv(Tk * tk)27237da2899SCharles.Forsyth tklistsv(Tk *tk)
27337da2899SCharles.Forsyth {
27437da2899SCharles.Forsyth TkListbox *l;
27537da2899SCharles.Forsyth int nl, lh, top, bot;
27637da2899SCharles.Forsyth char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
27737da2899SCharles.Forsyth
27837da2899SCharles.Forsyth l = TKobj(TkListbox, tk);
27937da2899SCharles.Forsyth if(l->yscroll == nil)
28037da2899SCharles.Forsyth return;
28137da2899SCharles.Forsyth
28237da2899SCharles.Forsyth top = 0;
28337da2899SCharles.Forsyth bot = TKI2F(1);
28437da2899SCharles.Forsyth
28537da2899SCharles.Forsyth if(l->nitem != 0) {
28637da2899SCharles.Forsyth lh = lineheight(tk);
28737da2899SCharles.Forsyth nl = tk->act.height/lh; /* Lines in the box */
28837da2899SCharles.Forsyth top = TKI2F(l->yelem)/l->nitem;
28937da2899SCharles.Forsyth bot = TKI2F(l->yelem+nl)/l->nitem;
29037da2899SCharles.Forsyth }
29137da2899SCharles.Forsyth
29237da2899SCharles.Forsyth v = tkfprint(val, top);
29337da2899SCharles.Forsyth *v++ = ' ';
29437da2899SCharles.Forsyth tkfprint(v, bot);
29537da2899SCharles.Forsyth snprint(cmd, sizeof(cmd), "%s %s", l->yscroll, val);
29637da2899SCharles.Forsyth e = tkexec(tk->env->top, cmd, nil);
29737da2899SCharles.Forsyth if ((e != nil) && (tk->name != nil))
29837da2899SCharles.Forsyth print("tk: yscrollcommand \"%s\": %s\n", tk->name->name, e);
29937da2899SCharles.Forsyth }
30037da2899SCharles.Forsyth
30137da2899SCharles.Forsyth void
tklistsh(Tk * tk)30237da2899SCharles.Forsyth tklistsh(Tk *tk)
30337da2899SCharles.Forsyth {
30437da2899SCharles.Forsyth int nl, top, bot;
30537da2899SCharles.Forsyth char val[Tkminitem], cmd[Tkmaxitem], *v, *e;
30637da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
30737da2899SCharles.Forsyth
30837da2899SCharles.Forsyth if(l->xscroll == nil)
30937da2899SCharles.Forsyth return;
31037da2899SCharles.Forsyth
31137da2899SCharles.Forsyth top = 0;
31237da2899SCharles.Forsyth bot = TKI2F(1);
31337da2899SCharles.Forsyth
31437da2899SCharles.Forsyth if(l->nwidth != 0) {
31537da2899SCharles.Forsyth nl = tk->act.width;
31637da2899SCharles.Forsyth top = TKI2F(l->xdelta)/l->nwidth;
31737da2899SCharles.Forsyth bot = TKI2F(l->xdelta+nl)/l->nwidth;
31837da2899SCharles.Forsyth }
31937da2899SCharles.Forsyth
32037da2899SCharles.Forsyth v = tkfprint(val, top);
32137da2899SCharles.Forsyth *v++ = ' ';
32237da2899SCharles.Forsyth tkfprint(v, bot);
32337da2899SCharles.Forsyth snprint(cmd, sizeof(cmd), "%s %s", l->xscroll, val);
32437da2899SCharles.Forsyth e = tkexec(tk->env->top, cmd, nil);
32537da2899SCharles.Forsyth if ((e != nil) && (tk->name != nil))
32637da2899SCharles.Forsyth print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e);
32737da2899SCharles.Forsyth }
32837da2899SCharles.Forsyth
32937da2899SCharles.Forsyth void
tklistbgeom(Tk * tk)33037da2899SCharles.Forsyth tklistbgeom(Tk *tk)
33137da2899SCharles.Forsyth {
33237da2899SCharles.Forsyth tklistsv(tk);
33337da2899SCharles.Forsyth tklistsh(tk);
33437da2899SCharles.Forsyth }
33537da2899SCharles.Forsyth
33637da2899SCharles.Forsyth static void
listbresize(Tk * tk)33737da2899SCharles.Forsyth listbresize(Tk *tk)
33837da2899SCharles.Forsyth {
33937da2899SCharles.Forsyth TkLentry *e;
34037da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
34137da2899SCharles.Forsyth
34237da2899SCharles.Forsyth l->nwidth = 0;
34337da2899SCharles.Forsyth for (e = l->head; e != nil; e = e->link) {
34437da2899SCharles.Forsyth e->width = stringwidth(tk->env->font, e->text)+2*(Listpadx+l->sborderwidth+tk->highlightwidth);
34537da2899SCharles.Forsyth if(e->width > l->nwidth)
34637da2899SCharles.Forsyth l->nwidth = e->width;
34737da2899SCharles.Forsyth }
34837da2899SCharles.Forsyth tklistbgeom(tk);
34937da2899SCharles.Forsyth }
35037da2899SCharles.Forsyth
35137da2899SCharles.Forsyth
35237da2899SCharles.Forsyth /* Widget Commands (+ means implemented)
35337da2899SCharles.Forsyth +activate
35437da2899SCharles.Forsyth bbox
35537da2899SCharles.Forsyth +cget
35637da2899SCharles.Forsyth +configure
35737da2899SCharles.Forsyth +curselection
35837da2899SCharles.Forsyth +delete
35937da2899SCharles.Forsyth +get
36037da2899SCharles.Forsyth +index
36137da2899SCharles.Forsyth +insert
36237da2899SCharles.Forsyth +nearest
36337da2899SCharles.Forsyth +see
36437da2899SCharles.Forsyth +selection
36537da2899SCharles.Forsyth +size
36637da2899SCharles.Forsyth +xview
36737da2899SCharles.Forsyth +yview
36837da2899SCharles.Forsyth */
36937da2899SCharles.Forsyth
37037da2899SCharles.Forsyth char*
tklistbconf(Tk * tk,char * arg,char ** val)37137da2899SCharles.Forsyth tklistbconf(Tk *tk, char *arg, char **val)
37237da2899SCharles.Forsyth {
37337da2899SCharles.Forsyth char *e;
37437da2899SCharles.Forsyth TkGeom g;
37537da2899SCharles.Forsyth int bd, sbw, hlw;
37637da2899SCharles.Forsyth TkOptab tko[3];
37737da2899SCharles.Forsyth Font *f;
37837da2899SCharles.Forsyth TkListbox *tkl = TKobj(TkListbox, tk);
37937da2899SCharles.Forsyth
38037da2899SCharles.Forsyth sbw = tkl->sborderwidth;
38137da2899SCharles.Forsyth hlw = tk->highlightwidth;
38237da2899SCharles.Forsyth f = tk->env->font;
38337da2899SCharles.Forsyth tko[0].ptr = tk;
38437da2899SCharles.Forsyth tko[0].optab = tkgeneric;
38537da2899SCharles.Forsyth tko[1].ptr = tkl;
38637da2899SCharles.Forsyth tko[1].optab = opts;
38737da2899SCharles.Forsyth tko[2].ptr = nil;
38837da2899SCharles.Forsyth
38937da2899SCharles.Forsyth if(*arg == '\0')
39037da2899SCharles.Forsyth return tkconflist(tko, val);
39137da2899SCharles.Forsyth
39237da2899SCharles.Forsyth g = tk->req;
39337da2899SCharles.Forsyth bd = tk->borderwidth;
39437da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
39537da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
39637da2899SCharles.Forsyth tkgeomchg(tk, &g, bd);
39737da2899SCharles.Forsyth
39837da2899SCharles.Forsyth if (sbw != tkl->sborderwidth || f != tk->env->font || hlw != tk->highlightwidth)
39937da2899SCharles.Forsyth listbresize(tk);
40037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
40137da2899SCharles.Forsyth return e;
40237da2899SCharles.Forsyth }
40337da2899SCharles.Forsyth
40437da2899SCharles.Forsyth static void
entryactivate(Tk * tk,int index)40537da2899SCharles.Forsyth entryactivate(Tk *tk, int index)
40637da2899SCharles.Forsyth {
40737da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
40837da2899SCharles.Forsyth TkLentry *e;
40937da2899SCharles.Forsyth int flag = Tkactive;
41037da2899SCharles.Forsyth
41137da2899SCharles.Forsyth if (l->selmode == TKbrowse)
41237da2899SCharles.Forsyth flag |= Tkactivated;
41337da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
41437da2899SCharles.Forsyth if(index-- == 0) {
41537da2899SCharles.Forsyth e->flag |= flag;
41637da2899SCharles.Forsyth l->active = e;
41737da2899SCharles.Forsyth } else
41837da2899SCharles.Forsyth e->flag &= ~flag;
41937da2899SCharles.Forsyth }
42037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
42137da2899SCharles.Forsyth }
42237da2899SCharles.Forsyth
42337da2899SCharles.Forsyth char*
tklistbactivate(Tk * tk,char * arg,char ** val)42437da2899SCharles.Forsyth tklistbactivate(Tk *tk, char *arg, char **val)
42537da2899SCharles.Forsyth {
42637da2899SCharles.Forsyth int index;
42737da2899SCharles.Forsyth char buf[Tkmaxitem];
42837da2899SCharles.Forsyth
42937da2899SCharles.Forsyth USED(val);
43037da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
43137da2899SCharles.Forsyth index = tklindex(tk, buf);
43237da2899SCharles.Forsyth if(index == -1)
43337da2899SCharles.Forsyth return TkBadix;
43437da2899SCharles.Forsyth
43537da2899SCharles.Forsyth entryactivate(tk, index);
43637da2899SCharles.Forsyth return nil;
43737da2899SCharles.Forsyth }
43837da2899SCharles.Forsyth
43937da2899SCharles.Forsyth char*
tklistbnearest(Tk * tk,char * arg,char ** val)44037da2899SCharles.Forsyth tklistbnearest(Tk *tk, char *arg, char **val)
44137da2899SCharles.Forsyth {
44237da2899SCharles.Forsyth int lh, y, index;
44337da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
44437da2899SCharles.Forsyth
44537da2899SCharles.Forsyth lh = lineheight(tk); /* Line height */
44637da2899SCharles.Forsyth y = atoi(arg);
44737da2899SCharles.Forsyth index = l->yelem + y/lh;
44837da2899SCharles.Forsyth if(index > l->nitem)
44937da2899SCharles.Forsyth index = l->nitem;
45037da2899SCharles.Forsyth return tkvalue(val, "%d", index);
45137da2899SCharles.Forsyth }
45237da2899SCharles.Forsyth
45337da2899SCharles.Forsyth char*
tklistbindex(Tk * tk,char * arg,char ** val)45437da2899SCharles.Forsyth tklistbindex(Tk *tk, char *arg, char **val)
45537da2899SCharles.Forsyth {
45637da2899SCharles.Forsyth int index;
45737da2899SCharles.Forsyth char buf[Tkmaxitem];
45837da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
45937da2899SCharles.Forsyth index = tklindex(tk, buf);
46037da2899SCharles.Forsyth if(index == -1)
46137da2899SCharles.Forsyth return TkBadix;
46237da2899SCharles.Forsyth return tkvalue(val, "%d", index);
46337da2899SCharles.Forsyth }
46437da2899SCharles.Forsyth
46537da2899SCharles.Forsyth char*
tklistbsize(Tk * tk,char * arg,char ** val)46637da2899SCharles.Forsyth tklistbsize(Tk *tk, char *arg, char **val)
46737da2899SCharles.Forsyth {
46837da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
46937da2899SCharles.Forsyth
47037da2899SCharles.Forsyth USED(arg);
47137da2899SCharles.Forsyth return tkvalue(val, "%d", l->nitem);
47237da2899SCharles.Forsyth }
47337da2899SCharles.Forsyth
47437da2899SCharles.Forsyth char*
tklistbinsert(Tk * tk,char * arg,char ** val)47537da2899SCharles.Forsyth tklistbinsert(Tk *tk, char *arg, char **val)
47637da2899SCharles.Forsyth {
47737da2899SCharles.Forsyth int n, index;
47837da2899SCharles.Forsyth TkListbox *l;
47937da2899SCharles.Forsyth TkLentry *e, **el;
48037da2899SCharles.Forsyth char *tbuf, buf[Tkmaxitem];
48137da2899SCharles.Forsyth
48237da2899SCharles.Forsyth USED(val);
48337da2899SCharles.Forsyth l = TKobj(TkListbox, tk);
48437da2899SCharles.Forsyth
48537da2899SCharles.Forsyth arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
48637da2899SCharles.Forsyth if(strcmp(buf, "end") == 0) {
48737da2899SCharles.Forsyth el = &l->head;
48837da2899SCharles.Forsyth if(*el != nil) {
48937da2899SCharles.Forsyth for(e = *el; e->link; e = e->link)
49037da2899SCharles.Forsyth ;
49137da2899SCharles.Forsyth el = &e->link;
49237da2899SCharles.Forsyth }
49337da2899SCharles.Forsyth }
49437da2899SCharles.Forsyth else {
49537da2899SCharles.Forsyth index = tklindex(tk, buf);
49637da2899SCharles.Forsyth if(index == -1)
49737da2899SCharles.Forsyth return TkBadix;
49837da2899SCharles.Forsyth el = &l->head;
49937da2899SCharles.Forsyth for(e = *el; e && index-- > 0; e = e->link)
50037da2899SCharles.Forsyth el = &e->link;
50137da2899SCharles.Forsyth }
50237da2899SCharles.Forsyth
50337da2899SCharles.Forsyth n = strlen(arg);
50437da2899SCharles.Forsyth if(n > Tkmaxitem) {
50537da2899SCharles.Forsyth n = (n*3)/2;
50637da2899SCharles.Forsyth tbuf = malloc(n);
50737da2899SCharles.Forsyth if(tbuf == nil)
50837da2899SCharles.Forsyth return TkNomem;
50937da2899SCharles.Forsyth }
51037da2899SCharles.Forsyth else {
51137da2899SCharles.Forsyth tbuf = buf;
51237da2899SCharles.Forsyth n = sizeof(buf);
51337da2899SCharles.Forsyth }
51437da2899SCharles.Forsyth
51537da2899SCharles.Forsyth while(*arg) {
51637da2899SCharles.Forsyth arg = tkword(tk->env->top, arg, tbuf, &tbuf[n], nil);
51737da2899SCharles.Forsyth e = malloc(sizeof(TkLentry)+strlen(tbuf)+1);
51837da2899SCharles.Forsyth if(e == nil)
51937da2899SCharles.Forsyth return TkNomem;
52037da2899SCharles.Forsyth
52137da2899SCharles.Forsyth e->flag = 0;
52237da2899SCharles.Forsyth strcpy(e->text, tbuf);
52337da2899SCharles.Forsyth e->link = *el;
52437da2899SCharles.Forsyth *el = e;
52537da2899SCharles.Forsyth el = &e->link;
52637da2899SCharles.Forsyth e->width = stringwidth(tk->env->font, e->text)+2*(Listpadx+l->sborderwidth+tk->highlightwidth);
52737da2899SCharles.Forsyth if(e->width > l->nwidth)
52837da2899SCharles.Forsyth l->nwidth = e->width;
52937da2899SCharles.Forsyth l->nitem++;
53037da2899SCharles.Forsyth }
53137da2899SCharles.Forsyth
53237da2899SCharles.Forsyth if(tbuf != buf)
53337da2899SCharles.Forsyth free(tbuf);
53437da2899SCharles.Forsyth
53537da2899SCharles.Forsyth tklistbgeom(tk);
53637da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
53737da2899SCharles.Forsyth return nil;
53837da2899SCharles.Forsyth }
53937da2899SCharles.Forsyth
54037da2899SCharles.Forsyth int
tklistbrange(Tk * tk,char * arg,int * s,int * e)54137da2899SCharles.Forsyth tklistbrange(Tk *tk, char *arg, int *s, int *e)
54237da2899SCharles.Forsyth {
54337da2899SCharles.Forsyth char buf[Tkmaxitem];
54437da2899SCharles.Forsyth
54537da2899SCharles.Forsyth arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
54637da2899SCharles.Forsyth *s = tklindex(tk, buf);
54737da2899SCharles.Forsyth if(*s == -1)
54837da2899SCharles.Forsyth return -1;
54937da2899SCharles.Forsyth *e = *s;
55037da2899SCharles.Forsyth if(*arg == '\0')
55137da2899SCharles.Forsyth return 0;
55237da2899SCharles.Forsyth
55337da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
55437da2899SCharles.Forsyth *e = tklindex(tk, buf);
55537da2899SCharles.Forsyth if(*e == -1)
55637da2899SCharles.Forsyth return -1;
55737da2899SCharles.Forsyth return 0;
55837da2899SCharles.Forsyth }
55937da2899SCharles.Forsyth
56037da2899SCharles.Forsyth char*
tklistbselection(Tk * tk,char * arg,char ** val)56137da2899SCharles.Forsyth tklistbselection(Tk *tk, char *arg, char **val)
56237da2899SCharles.Forsyth {
56337da2899SCharles.Forsyth TkTop *t;
56437da2899SCharles.Forsyth TkLentry *f;
56537da2899SCharles.Forsyth TkListbox *l;
56637da2899SCharles.Forsyth int s, e, indx;
56737da2899SCharles.Forsyth char buf[Tkmaxitem];
56837da2899SCharles.Forsyth
56937da2899SCharles.Forsyth l = TKobj(TkListbox, tk);
57037da2899SCharles.Forsyth
57137da2899SCharles.Forsyth t = tk->env->top;
57237da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+sizeof(buf), nil);
57337da2899SCharles.Forsyth if(strcmp(buf, "includes") == 0) {
57437da2899SCharles.Forsyth tkword(t, arg, buf, buf+sizeof(buf), nil);
57537da2899SCharles.Forsyth indx = tklindex(tk, buf);
57637da2899SCharles.Forsyth if(indx == -1)
57737da2899SCharles.Forsyth return TkBadix;
57837da2899SCharles.Forsyth for(f = l->head; f && indx > 0; f = f->link)
57937da2899SCharles.Forsyth indx--;
58037da2899SCharles.Forsyth s = 0;
58137da2899SCharles.Forsyth if(f && (f->flag&Tkactivated))
58237da2899SCharles.Forsyth s = 1;
58337da2899SCharles.Forsyth return tkvalue(val, "%d", s);
58437da2899SCharles.Forsyth }
58537da2899SCharles.Forsyth
58637da2899SCharles.Forsyth if(strcmp(buf, "anchor") == 0) {
58737da2899SCharles.Forsyth tkword(t, arg, buf, buf+sizeof(buf), nil);
58837da2899SCharles.Forsyth indx = tklindex(tk, buf);
58937da2899SCharles.Forsyth if(indx == -1)
59037da2899SCharles.Forsyth return TkBadix;
59137da2899SCharles.Forsyth for(f = l->head; f && indx > 0; f = f->link)
59237da2899SCharles.Forsyth indx--;
59337da2899SCharles.Forsyth if(f != nil)
59437da2899SCharles.Forsyth l->anchor = f;
59537da2899SCharles.Forsyth return nil;
59637da2899SCharles.Forsyth }
59737da2899SCharles.Forsyth indx = 0;
59837da2899SCharles.Forsyth if(strcmp(buf, "clear") == 0) {
59937da2899SCharles.Forsyth if(tklistbrange(tk, arg, &s, &e) != 0)
60037da2899SCharles.Forsyth return TkBadix;
60137da2899SCharles.Forsyth for(f = l->head; f; f = f->link) {
60237da2899SCharles.Forsyth if(indx <= e && indx++ >= s)
60337da2899SCharles.Forsyth f->flag &= ~Tkactivated;
60437da2899SCharles.Forsyth }
60537da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
60637da2899SCharles.Forsyth return nil;
60737da2899SCharles.Forsyth }
60837da2899SCharles.Forsyth if(strcmp(buf, "set") == 0) {
60937da2899SCharles.Forsyth if(tklistbrange(tk, arg, &s, &e) != 0)
61037da2899SCharles.Forsyth return TkBadix;
61137da2899SCharles.Forsyth for(f = l->head; f; f = f->link) {
61237da2899SCharles.Forsyth if(indx <= e && indx++ >= s)
61337da2899SCharles.Forsyth f->flag |= Tkactivated;
61437da2899SCharles.Forsyth }
61537da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
61637da2899SCharles.Forsyth return nil;
61737da2899SCharles.Forsyth }
61837da2899SCharles.Forsyth return TkBadcm;
61937da2899SCharles.Forsyth }
62037da2899SCharles.Forsyth
62137da2899SCharles.Forsyth char*
tklistbdelete(Tk * tk,char * arg,char ** val)62237da2899SCharles.Forsyth tklistbdelete(Tk *tk, char *arg, char **val)
62337da2899SCharles.Forsyth {
62437da2899SCharles.Forsyth TkLentry *e, **el;
62537da2899SCharles.Forsyth int start, end, indx, bh;
62637da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
62737da2899SCharles.Forsyth
62837da2899SCharles.Forsyth USED(val);
62937da2899SCharles.Forsyth if(tklistbrange(tk, arg, &start, &end) != 0)
63037da2899SCharles.Forsyth return TkBadix;
63137da2899SCharles.Forsyth
63237da2899SCharles.Forsyth indx = 0;
63337da2899SCharles.Forsyth el = &l->head;
63437da2899SCharles.Forsyth for(e = l->head; e && indx < start; e = e->link) {
63537da2899SCharles.Forsyth indx++;
63637da2899SCharles.Forsyth el = &e->link;
63737da2899SCharles.Forsyth }
63837da2899SCharles.Forsyth while(e != nil && indx <= end) {
63937da2899SCharles.Forsyth *el = e->link;
64037da2899SCharles.Forsyth if(e->width == l->nwidth)
64137da2899SCharles.Forsyth l->nwidth = 0;
64237da2899SCharles.Forsyth if (e == l->anchor)
64337da2899SCharles.Forsyth l->anchor = nil;
64437da2899SCharles.Forsyth if (e == l->active)
64537da2899SCharles.Forsyth l->active = nil;
64637da2899SCharles.Forsyth free(e);
64737da2899SCharles.Forsyth e = *el;
64837da2899SCharles.Forsyth indx++;
64937da2899SCharles.Forsyth l->nitem--;
65037da2899SCharles.Forsyth }
65137da2899SCharles.Forsyth if(l->nwidth == 0) {
65237da2899SCharles.Forsyth for(e = l->head; e; e = e->link)
65337da2899SCharles.Forsyth if(e->width > l->nwidth)
65437da2899SCharles.Forsyth l->nwidth = e->width;
65537da2899SCharles.Forsyth }
65637da2899SCharles.Forsyth bh = tk->act.height/lineheight(tk); /* Box height */
65737da2899SCharles.Forsyth if(l->yelem + bh > l->nitem)
65837da2899SCharles.Forsyth l->yelem = l->nitem - bh;
65937da2899SCharles.Forsyth if(l->yelem < 0)
66037da2899SCharles.Forsyth l->yelem = 0;
66137da2899SCharles.Forsyth
66237da2899SCharles.Forsyth tklistbgeom(tk);
66337da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
66437da2899SCharles.Forsyth return nil;
66537da2899SCharles.Forsyth }
66637da2899SCharles.Forsyth
66737da2899SCharles.Forsyth char*
tklistbget(Tk * tk,char * arg,char ** val)66837da2899SCharles.Forsyth tklistbget(Tk *tk, char *arg, char **val)
66937da2899SCharles.Forsyth {
67037da2899SCharles.Forsyth TkLentry *e;
67137da2899SCharles.Forsyth char *r, *fmt;
67237da2899SCharles.Forsyth int start, end, indx;
67337da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
67437da2899SCharles.Forsyth
67537da2899SCharles.Forsyth if(tklistbrange(tk, arg, &start, &end) != 0)
67637da2899SCharles.Forsyth return TkBadix;
67737da2899SCharles.Forsyth
67837da2899SCharles.Forsyth indx = 0;
67937da2899SCharles.Forsyth for(e = l->head; e && indx < start; e = e->link)
68037da2899SCharles.Forsyth indx++;
68137da2899SCharles.Forsyth fmt = "%s";
68237da2899SCharles.Forsyth while(e != nil && indx <= end) {
68337da2899SCharles.Forsyth r = tkvalue(val, fmt, e->text);
68437da2899SCharles.Forsyth if(r != nil)
68537da2899SCharles.Forsyth return r;
68637da2899SCharles.Forsyth indx++;
68737da2899SCharles.Forsyth fmt = " %s";
68837da2899SCharles.Forsyth e = e->link;
68937da2899SCharles.Forsyth }
69037da2899SCharles.Forsyth return nil;
69137da2899SCharles.Forsyth }
69237da2899SCharles.Forsyth
69337da2899SCharles.Forsyth char*
tklistbcursel(Tk * tk,char * arg,char ** val)69437da2899SCharles.Forsyth tklistbcursel(Tk *tk, char *arg, char **val)
69537da2899SCharles.Forsyth {
69637da2899SCharles.Forsyth int indx;
69737da2899SCharles.Forsyth TkLentry *e;
69837da2899SCharles.Forsyth char *r, *fmt;
69937da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
70037da2899SCharles.Forsyth
70137da2899SCharles.Forsyth USED(arg);
70237da2899SCharles.Forsyth indx = 0;
70337da2899SCharles.Forsyth fmt = "%d";
70437da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
70537da2899SCharles.Forsyth if(e->flag & Tkactivated) {
70637da2899SCharles.Forsyth r = tkvalue(val, fmt, indx);
70737da2899SCharles.Forsyth if(r != nil)
70837da2899SCharles.Forsyth return r;
70937da2899SCharles.Forsyth fmt = " %d";
71037da2899SCharles.Forsyth }
71137da2899SCharles.Forsyth indx++;
71237da2899SCharles.Forsyth }
71337da2899SCharles.Forsyth return nil;
71437da2899SCharles.Forsyth }
71537da2899SCharles.Forsyth
71637da2899SCharles.Forsyth static char*
tklistbview(Tk * tk,char * arg,char ** val,int nl,int * posn,int max)71737da2899SCharles.Forsyth tklistbview(Tk *tk, char *arg, char **val, int nl, int *posn, int max)
71837da2899SCharles.Forsyth {
71937da2899SCharles.Forsyth int top, bot, amount;
72037da2899SCharles.Forsyth char buf[Tkmaxitem];
72137da2899SCharles.Forsyth char *v, *e;
72237da2899SCharles.Forsyth
72337da2899SCharles.Forsyth top = 0;
72437da2899SCharles.Forsyth if(*arg == '\0') {
72537da2899SCharles.Forsyth if ( max <= nl || max == 0 ) { /* Double test redundant at
72637da2899SCharles.Forsyth * this time, but want to
72737da2899SCharles.Forsyth * protect against future
72837da2899SCharles.Forsyth * calls. -- DBK */
72937da2899SCharles.Forsyth top = 0;
73037da2899SCharles.Forsyth bot = TKI2F(1);
73137da2899SCharles.Forsyth }
73237da2899SCharles.Forsyth else {
73337da2899SCharles.Forsyth top = TKI2F(*posn)/max;
73437da2899SCharles.Forsyth bot = TKI2F(*posn+nl)/max;
73537da2899SCharles.Forsyth }
73637da2899SCharles.Forsyth v = tkfprint(buf, top);
73737da2899SCharles.Forsyth *v++ = ' ';
73837da2899SCharles.Forsyth tkfprint(v, bot);
73937da2899SCharles.Forsyth return tkvalue(val, "%s", buf);
74037da2899SCharles.Forsyth }
74137da2899SCharles.Forsyth
74237da2899SCharles.Forsyth arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
74337da2899SCharles.Forsyth if(strcmp(buf, "moveto") == 0) {
74437da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &top, nil);
74537da2899SCharles.Forsyth if (e != nil)
74637da2899SCharles.Forsyth return e;
74737da2899SCharles.Forsyth *posn = TKF2I((top+1)*max);
74837da2899SCharles.Forsyth }
74937da2899SCharles.Forsyth else
75037da2899SCharles.Forsyth if(strcmp(buf, "scroll") == 0) {
75137da2899SCharles.Forsyth arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
75237da2899SCharles.Forsyth amount = atoi(buf);
75337da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
75437da2899SCharles.Forsyth if(buf[0] == 'p') /* Pages */
75537da2899SCharles.Forsyth amount *= nl;
75637da2899SCharles.Forsyth *posn += amount;
75737da2899SCharles.Forsyth }
75837da2899SCharles.Forsyth else {
75937da2899SCharles.Forsyth top = tklindex(tk, buf);
76037da2899SCharles.Forsyth if(top == -1)
76137da2899SCharles.Forsyth return TkBadix;
76237da2899SCharles.Forsyth *posn = top;
76337da2899SCharles.Forsyth }
76437da2899SCharles.Forsyth
76537da2899SCharles.Forsyth bot = max - nl;
76637da2899SCharles.Forsyth if(*posn > bot)
76737da2899SCharles.Forsyth *posn = bot;
76837da2899SCharles.Forsyth if(*posn < 0)
76937da2899SCharles.Forsyth *posn = 0;
77037da2899SCharles.Forsyth
77137da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
77237da2899SCharles.Forsyth return nil;
77337da2899SCharles.Forsyth }
77437da2899SCharles.Forsyth
77537da2899SCharles.Forsyth static int
entrysee(Tk * tk,int index)77637da2899SCharles.Forsyth entrysee(Tk *tk, int index)
77737da2899SCharles.Forsyth {
77837da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
77937da2899SCharles.Forsyth int bh;
78037da2899SCharles.Forsyth
78137da2899SCharles.Forsyth /* Box height in lines */
78237da2899SCharles.Forsyth bh = tk->act.height/lineheight(tk);
78337da2899SCharles.Forsyth if (bh > l->nitem)
78437da2899SCharles.Forsyth bh = l->nitem;
78537da2899SCharles.Forsyth if (index >= l->nitem)
78637da2899SCharles.Forsyth index = l->nitem -1;
78737da2899SCharles.Forsyth if (index < 0)
78837da2899SCharles.Forsyth index = 0;
78937da2899SCharles.Forsyth
79037da2899SCharles.Forsyth /* If the item is already visible, do nothing */
79137da2899SCharles.Forsyth if (l->nitem == 0 || index >= l->yelem && index < l->yelem+bh)
79237da2899SCharles.Forsyth return index;
79337da2899SCharles.Forsyth
79437da2899SCharles.Forsyth if (index < l->yelem)
79537da2899SCharles.Forsyth l->yelem = index;
79637da2899SCharles.Forsyth else
79737da2899SCharles.Forsyth l->yelem = index - (bh-1);
79837da2899SCharles.Forsyth
79937da2899SCharles.Forsyth tklistsv(tk);
80037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
80137da2899SCharles.Forsyth return index;
80237da2899SCharles.Forsyth }
80337da2899SCharles.Forsyth
80437da2899SCharles.Forsyth char*
tklistbsee(Tk * tk,char * arg,char ** val)80537da2899SCharles.Forsyth tklistbsee(Tk *tk, char *arg, char **val)
80637da2899SCharles.Forsyth {
80737da2899SCharles.Forsyth int index;
80837da2899SCharles.Forsyth char buf[Tkmaxitem];
80937da2899SCharles.Forsyth
81037da2899SCharles.Forsyth USED(val);
81137da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil);
81237da2899SCharles.Forsyth index = tklindex(tk, buf);
81337da2899SCharles.Forsyth if(index == -1)
81437da2899SCharles.Forsyth return TkBadix;
81537da2899SCharles.Forsyth
81637da2899SCharles.Forsyth entrysee(tk, index);
81737da2899SCharles.Forsyth return nil;
81837da2899SCharles.Forsyth }
81937da2899SCharles.Forsyth
82037da2899SCharles.Forsyth char*
tklistbyview(Tk * tk,char * arg,char ** val)82137da2899SCharles.Forsyth tklistbyview(Tk *tk, char *arg, char **val)
82237da2899SCharles.Forsyth {
82337da2899SCharles.Forsyth int bh;
82437da2899SCharles.Forsyth char *e;
82537da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
82637da2899SCharles.Forsyth
82737da2899SCharles.Forsyth bh = tk->act.height/lineheight(tk); /* Box height */
82837da2899SCharles.Forsyth e = tklistbview(tk, arg, val, bh, &l->yelem, l->nitem);
82937da2899SCharles.Forsyth tklistsv(tk);
83037da2899SCharles.Forsyth return e;
83137da2899SCharles.Forsyth }
83237da2899SCharles.Forsyth
83337da2899SCharles.Forsyth char*
tklistbxview(Tk * tk,char * arg,char ** val)83437da2899SCharles.Forsyth tklistbxview(Tk *tk, char *arg, char **val)
83537da2899SCharles.Forsyth {
83637da2899SCharles.Forsyth char *e;
83737da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
83837da2899SCharles.Forsyth
83937da2899SCharles.Forsyth e = tklistbview(tk, arg, val, tk->act.width, &l->xdelta, l->nwidth);
84037da2899SCharles.Forsyth tklistsh(tk);
84137da2899SCharles.Forsyth return e;
84237da2899SCharles.Forsyth }
84337da2899SCharles.Forsyth
84437da2899SCharles.Forsyth static TkLentry*
entryset(TkListbox * l,int indx,int toggle)84537da2899SCharles.Forsyth entryset(TkListbox *l, int indx, int toggle)
84637da2899SCharles.Forsyth {
84737da2899SCharles.Forsyth TkLentry *e, *anchor;
84837da2899SCharles.Forsyth
84937da2899SCharles.Forsyth anchor = nil;
85037da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
85137da2899SCharles.Forsyth if (indx-- == 0) {
85237da2899SCharles.Forsyth anchor = e;
85337da2899SCharles.Forsyth if (toggle) {
85437da2899SCharles.Forsyth e->flag ^= Tkactivated;
85537da2899SCharles.Forsyth break;
85637da2899SCharles.Forsyth } else
85737da2899SCharles.Forsyth e->flag |= Tkactivated;
85837da2899SCharles.Forsyth continue;
85937da2899SCharles.Forsyth }
86037da2899SCharles.Forsyth if (!toggle)
86137da2899SCharles.Forsyth e->flag &= ~Tkactivated;
86237da2899SCharles.Forsyth }
86337da2899SCharles.Forsyth return anchor;
86437da2899SCharles.Forsyth }
86537da2899SCharles.Forsyth
86637da2899SCharles.Forsyth static void
selectto(TkListbox * l,int indx)86737da2899SCharles.Forsyth selectto(TkListbox *l, int indx)
86837da2899SCharles.Forsyth {
86937da2899SCharles.Forsyth TkLentry *e;
87037da2899SCharles.Forsyth int inrange;
87137da2899SCharles.Forsyth
87237da2899SCharles.Forsyth if (l->anchor == nil)
87337da2899SCharles.Forsyth return;
87437da2899SCharles.Forsyth inrange = 0;
87537da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
87637da2899SCharles.Forsyth if(indx == 0)
87737da2899SCharles.Forsyth inrange = !inrange;
87837da2899SCharles.Forsyth if(e == l->anchor)
87937da2899SCharles.Forsyth inrange = !inrange;
88037da2899SCharles.Forsyth if(inrange || e == l->anchor || indx == 0)
88137da2899SCharles.Forsyth e->flag |= Tkactivated;
88237da2899SCharles.Forsyth else
88337da2899SCharles.Forsyth e->flag &= ~Tkactivated;
88437da2899SCharles.Forsyth indx--;
88537da2899SCharles.Forsyth }
88637da2899SCharles.Forsyth }
88737da2899SCharles.Forsyth
88837da2899SCharles.Forsyth static char*
dragto(Tk * tk,int y)88937da2899SCharles.Forsyth dragto(Tk *tk, int y)
89037da2899SCharles.Forsyth {
89137da2899SCharles.Forsyth int indx;
89237da2899SCharles.Forsyth TkLentry *e;
89337da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
89437da2899SCharles.Forsyth
89537da2899SCharles.Forsyth indx = y/lineheight(tk);
89637da2899SCharles.Forsyth if (y < 0)
89737da2899SCharles.Forsyth indx--; /* int division rounds towards 0 */
89837da2899SCharles.Forsyth if (y < tk->act.height && indx >= l->nitem)
89937da2899SCharles.Forsyth return nil;
90037da2899SCharles.Forsyth indx = entrysee(tk, l->yelem+indx);
90137da2899SCharles.Forsyth entryactivate(tk, indx);
90237da2899SCharles.Forsyth
90337da2899SCharles.Forsyth if(l->selmode == TKsingle || l->selmode == TKmultiple)
90437da2899SCharles.Forsyth return nil;
90537da2899SCharles.Forsyth
90637da2899SCharles.Forsyth if(l->selmode == TKbrowse) {
90737da2899SCharles.Forsyth for(e = l->head; e; e = e->link) {
90837da2899SCharles.Forsyth if(indx-- == 0) {
90937da2899SCharles.Forsyth if (e == l->anchor)
91037da2899SCharles.Forsyth return nil;
91137da2899SCharles.Forsyth l->anchor = e;
91237da2899SCharles.Forsyth e->flag |= Tkactivated;
91337da2899SCharles.Forsyth } else
91437da2899SCharles.Forsyth e->flag &= ~Tkactivated;
91537da2899SCharles.Forsyth }
91637da2899SCharles.Forsyth return nil;
91737da2899SCharles.Forsyth }
91837da2899SCharles.Forsyth /* extended selection mode */
91937da2899SCharles.Forsyth selectto(l, indx);
92037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
92137da2899SCharles.Forsyth return nil;
92237da2899SCharles.Forsyth }
92337da2899SCharles.Forsyth
92437da2899SCharles.Forsyth static void
autoselect(Tk * tk,void * v,int cancelled)92537da2899SCharles.Forsyth autoselect(Tk *tk, void *v, int cancelled)
92637da2899SCharles.Forsyth {
92737da2899SCharles.Forsyth Point pt;
92837da2899SCharles.Forsyth int y, eh, ne;
92937da2899SCharles.Forsyth
93037da2899SCharles.Forsyth USED(v);
93137da2899SCharles.Forsyth if (cancelled)
93237da2899SCharles.Forsyth return;
93337da2899SCharles.Forsyth
93437da2899SCharles.Forsyth pt = tkposn(tk);
93537da2899SCharles.Forsyth pt.y += tk->borderwidth;
93637da2899SCharles.Forsyth y = tk->env->top->ctxt->mstate.y;
93737da2899SCharles.Forsyth y -= pt.y;
93837da2899SCharles.Forsyth eh = lineheight(tk);
93937da2899SCharles.Forsyth ne = tk->act.height/eh;
94037da2899SCharles.Forsyth if (y >= 0 && y < eh*ne)
94137da2899SCharles.Forsyth return;
94237da2899SCharles.Forsyth dragto(tk, y);
94337da2899SCharles.Forsyth tkdirty(tk);
94437da2899SCharles.Forsyth tkupdate(tk->env->top);
94537da2899SCharles.Forsyth }
94637da2899SCharles.Forsyth
94737da2899SCharles.Forsyth static char*
tklistbbutton1p(Tk * tk,char * arg,char ** val)94837da2899SCharles.Forsyth tklistbbutton1p(Tk *tk, char *arg, char **val)
94937da2899SCharles.Forsyth {
95037da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
95137da2899SCharles.Forsyth int y, indx;
95237da2899SCharles.Forsyth
95337da2899SCharles.Forsyth USED(val);
95437da2899SCharles.Forsyth
95537da2899SCharles.Forsyth y = atoi(arg);
95637da2899SCharles.Forsyth indx = y/lineheight(tk);
95737da2899SCharles.Forsyth indx += l->yelem;
95837da2899SCharles.Forsyth if (indx < l->nitem) {
95937da2899SCharles.Forsyth l->anchor = entryset(l, indx, l->selmode == TKmultiple);
96037da2899SCharles.Forsyth entryactivate(tk, indx);
96137da2899SCharles.Forsyth entrysee(tk, indx);
96237da2899SCharles.Forsyth }
96337da2899SCharles.Forsyth tkrepeat(tk, autoselect, nil, TkRptpause, TkRptinterval);
96437da2899SCharles.Forsyth return nil;
96537da2899SCharles.Forsyth }
96637da2899SCharles.Forsyth
96737da2899SCharles.Forsyth char *
tklistbbutton1r(Tk * tk,char * arg,char ** val)96837da2899SCharles.Forsyth tklistbbutton1r(Tk *tk, char *arg, char **val)
96937da2899SCharles.Forsyth {
97037da2899SCharles.Forsyth USED(arg);
97137da2899SCharles.Forsyth USED(val);
97237da2899SCharles.Forsyth tkcancelrepeat(tk);
97337da2899SCharles.Forsyth return nil;
97437da2899SCharles.Forsyth }
97537da2899SCharles.Forsyth
97637da2899SCharles.Forsyth char*
tklistbbutton1m(Tk * tk,char * arg,char ** val)97737da2899SCharles.Forsyth tklistbbutton1m(Tk *tk, char *arg, char **val)
97837da2899SCharles.Forsyth {
97937da2899SCharles.Forsyth int y, eh, ne;
98037da2899SCharles.Forsyth USED(val);
98137da2899SCharles.Forsyth
98237da2899SCharles.Forsyth eh = lineheight(tk);
98337da2899SCharles.Forsyth ne = tk->act.height/eh;
98437da2899SCharles.Forsyth y = atoi(arg);
98537da2899SCharles.Forsyth /* If outside the box, let autoselect handle it */
98637da2899SCharles.Forsyth if (y < 0 || y >= ne * eh)
98737da2899SCharles.Forsyth return nil;
98837da2899SCharles.Forsyth return dragto(tk, y);
98937da2899SCharles.Forsyth }
99037da2899SCharles.Forsyth
99137da2899SCharles.Forsyth char*
tklistbkey(Tk * tk,char * arg,char ** val)99237da2899SCharles.Forsyth tklistbkey(Tk *tk, char *arg, char **val)
99337da2899SCharles.Forsyth {
99437da2899SCharles.Forsyth TkListbox *l = TKobj(TkListbox, tk);
99537da2899SCharles.Forsyth TkLentry *e;
99637da2899SCharles.Forsyth int key, active;
99737da2899SCharles.Forsyth USED(val);
99837da2899SCharles.Forsyth
99937da2899SCharles.Forsyth if(tk->flag & Tkdisabled)
100037da2899SCharles.Forsyth return nil;
100137da2899SCharles.Forsyth
1002*48c2bcd8Sforsyth key = strtol(arg, nil, 0);
100337da2899SCharles.Forsyth active = 0;
100437da2899SCharles.Forsyth for (e = l->head; e != nil; e = e->link) {
100537da2899SCharles.Forsyth if (e->flag & Tkactive)
100637da2899SCharles.Forsyth break;
100737da2899SCharles.Forsyth active++;
100837da2899SCharles.Forsyth }
100937da2899SCharles.Forsyth
101037da2899SCharles.Forsyth if (key == '\n' || key == ' ') {
101137da2899SCharles.Forsyth l->anchor = entryset(l, active, l->selmode == TKmultiple);
101237da2899SCharles.Forsyth tk->dirty = tkrect(tk, 0);
101337da2899SCharles.Forsyth return nil;
101437da2899SCharles.Forsyth }
101537da2899SCharles.Forsyth if (key == Up)
101637da2899SCharles.Forsyth active--;
101737da2899SCharles.Forsyth else if (key == Down)
101837da2899SCharles.Forsyth active++;
101937da2899SCharles.Forsyth else
102037da2899SCharles.Forsyth return nil;
102137da2899SCharles.Forsyth
102237da2899SCharles.Forsyth if (active < 0)
102337da2899SCharles.Forsyth active = 0;
102437da2899SCharles.Forsyth if (active >= l->nitem)
102537da2899SCharles.Forsyth active = l->nitem-1;
102637da2899SCharles.Forsyth entryactivate(tk, active);
102737da2899SCharles.Forsyth if (l->selmode == TKextended) {
102837da2899SCharles.Forsyth selectto(l, active);
102937da2899SCharles.Forsyth tk->dirty = tkrect(tk, 0);
103037da2899SCharles.Forsyth }
103137da2899SCharles.Forsyth entrysee(tk, active);
103237da2899SCharles.Forsyth return nil;
103337da2899SCharles.Forsyth }
103437da2899SCharles.Forsyth
103537da2899SCharles.Forsyth static
103637da2899SCharles.Forsyth TkCmdtab tklistcmd[] =
103737da2899SCharles.Forsyth {
103837da2899SCharles.Forsyth "activate", tklistbactivate,
103937da2899SCharles.Forsyth "cget", tklistbcget,
104037da2899SCharles.Forsyth "configure", tklistbconf,
104137da2899SCharles.Forsyth "curselection", tklistbcursel,
104237da2899SCharles.Forsyth "delete", tklistbdelete,
104337da2899SCharles.Forsyth "get", tklistbget,
104437da2899SCharles.Forsyth "index", tklistbindex,
104537da2899SCharles.Forsyth "insert", tklistbinsert,
104637da2899SCharles.Forsyth "nearest", tklistbnearest,
104737da2899SCharles.Forsyth "selection", tklistbselection,
104837da2899SCharles.Forsyth "see", tklistbsee,
104937da2899SCharles.Forsyth "size", tklistbsize,
105037da2899SCharles.Forsyth "xview", tklistbxview,
105137da2899SCharles.Forsyth "yview", tklistbyview,
105237da2899SCharles.Forsyth "tkListbButton1P", tklistbbutton1p,
105337da2899SCharles.Forsyth "tkListbButton1R", tklistbbutton1r,
105437da2899SCharles.Forsyth "tkListbButton1MP", tklistbbutton1m,
105537da2899SCharles.Forsyth "tkListbKey", tklistbkey,
105637da2899SCharles.Forsyth nil
105737da2899SCharles.Forsyth };
105837da2899SCharles.Forsyth
105937da2899SCharles.Forsyth TkMethod listboxmethod = {
106037da2899SCharles.Forsyth "listbox",
106137da2899SCharles.Forsyth tklistcmd,
106237da2899SCharles.Forsyth tkfreelistb,
106337da2899SCharles.Forsyth tkdrawlistb,
106437da2899SCharles.Forsyth tklistbgeom
106537da2899SCharles.Forsyth };
1066