diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libtk/listb.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libtk/listb.c')
| -rw-r--r-- | libtk/listb.c | 1065 |
1 files changed, 1065 insertions, 0 deletions
diff --git a/libtk/listb.c b/libtk/listb.c new file mode 100644 index 00000000..af8850bd --- /dev/null +++ b/libtk/listb.c @@ -0,0 +1,1065 @@ +#include "lib9.h" +#include "draw.h" +#include "keyboard.h" +#include "tk.h" +#include "listb.h" + +#define O(t, e) ((long)(&((t*)0)->e)) + +/* Layout constants */ +enum { + Listpadx = 2, /* X padding of text in listboxes */ +}; + +typedef struct TkLentry TkLentry; +typedef struct TkListbox TkListbox; + +struct TkLentry +{ + TkLentry* link; + int flag; + int width; + char text[TKSTRUCTALIGN]; +}; + +struct TkListbox +{ + TkLentry* head; + TkLentry* anchor; + TkLentry* active; + int yelem; /* Y element at top of box */ + int xdelta; /* h-scroll position */ + int nitem; + int nwidth; + int selmode; + int sborderwidth; + char* xscroll; + char* yscroll; +}; + +TkStab tkselmode[] = +{ + "single", TKsingle, + "browse", TKbrowse, + "multiple", TKmultiple, + "extended", TKextended, + nil +}; + +static +TkOption opts[] = +{ + "xscrollcommand", OPTtext, O(TkListbox, xscroll), nil, + "yscrollcommand", OPTtext, O(TkListbox, yscroll), nil, + "selectmode", OPTstab, O(TkListbox, selmode), tkselmode, + "selectborderwidth", OPTnndist, O(TkListbox, sborderwidth), nil, + nil +}; + +static +TkEbind b[] = +{ + {TkButton1P, "%W tkListbButton1P %y"}, + {TkButton1R, "%W tkListbButton1R"}, + {TkButton1P|TkMotion, "%W tkListbButton1MP %y"}, + {TkMotion, ""}, + {TkKey, "%W tkListbKey 0x%K"}, +}; + + +static int +lineheight(Tk *tk) +{ + TkListbox *l = TKobj(TkListbox, tk); + return tk->env->font->height+2*(l->sborderwidth+tk->highlightwidth); +} + +char* +tklistbox(TkTop *t, char *arg, char **ret) +{ + Tk *tk; + char *e; + TkName *names; + TkListbox *tkl; + TkOptab tko[3]; + + tk = tknewobj(t, TKlistbox, sizeof(Tk)+sizeof(TkListbox)); + if(tk == nil) + return TkNomem; + + tkl = TKobj(TkListbox, tk); + tkl->sborderwidth = 1; + tk->relief = TKsunken; + tk->borderwidth = 2; + tk->highlightwidth = 1; + tk->flag |= Tktakefocus; + tk->req.width = 170; + tk->req.height = lineheight(tk)*10; + + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = tkl; + tko[1].optab = opts; + tko[2].ptr = nil; + + names = nil; + e = tkparse(t, arg, tko, &names); + if(e != nil) { + tkfreeobj(tk); + return e; + } + tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); + + e = tkbindings(t, tk, b, nelem(b)); + if(e != nil) { + tkfreeobj(tk); + return e; + } + + e = tkaddchild(t, tk, &names); + tkfreename(names); + if(e != nil) { + tkfreeobj(tk); + return e; + } + tk->name->link = nil; + + return tkvalue(ret, "%s", tk->name->name); +} + +char* +tklistbcget(Tk *tk, char *arg, char **val) +{ + TkOptab tko[3]; + TkListbox *tkl = TKobj(TkListbox, tk); + + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = tkl; + tko[1].optab = opts; + tko[2].ptr = nil; + + return tkgencget(tko, arg, val, tk->env->top); +} + +void +tkfreelistb(Tk *tk) +{ + TkLentry *e, *next; + TkListbox *l = TKobj(TkListbox, tk); + + for(e = l->head; e; e = next) { + next = e->link; + free(e); + } + if(l->xscroll != nil) + free(l->xscroll); + if(l->yscroll != nil) + free(l->yscroll); +} + +char* +tkdrawlistb(Tk *tk, Point orig) +{ + Point p; + TkEnv *env; + TkLentry *e; + int lh, w, n, ly; + Rectangle r, a; + Image *i, *fg; + TkListbox *l = TKobj(TkListbox, tk); + + env = tk->env; + + r.min = ZP; + r.max.x = tk->act.width + 2*tk->borderwidth; + r.max.y = tk->act.height + 2*tk->borderwidth; + i = tkitmp(env, r.max, TkCbackgnd); + if(i == nil) + return nil; + + w = tk->act.width; + if (w < l->nwidth) + w = l->nwidth; + lh = lineheight(tk); + ly = tk->borderwidth; + p.x = tk->borderwidth+l->sborderwidth+tk->highlightwidth+Listpadx-l->xdelta; + p.y = tk->borderwidth+l->sborderwidth+tk->highlightwidth; + n = 0; + for(e = l->head; e && ly < r.max.y; e = e->link) { + if(n++ < l->yelem) + continue; + + a.min.x = tk->borderwidth; + a.min.y = ly; + a.max.x = a.min.x + tk->act.width; + a.max.y = a.min.y + lh; + if(e->flag & Tkactivated) { + draw(i, a, tkgc(env, TkCselectbgnd), nil, ZP); + } + + if(e->flag & Tkactivated) + fg = tkgc(env, TkCselectfgnd); + else + fg = tkgc(env, TkCforegnd); + string(i, p, fg, p, env->font, e->text); + if((e->flag & Tkactive) && tkhaskeyfocus(tk)) { + a.min.x = tk->borderwidth-l->xdelta; + a.max.x = a.min.x+w; + a = insetrect(a, l->sborderwidth); + tkbox(i, a, tk->highlightwidth, fg); + } + ly += lh; + p.y += lh; + } + + tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief); + + p.x = tk->act.x + orig.x; + p.y = tk->act.y + orig.y; + r = rectaddpt(r, p); + draw(tkimageof(tk), r, i, nil, ZP); + + return nil; +} + +int +tklindex(Tk *tk, char *buf) +{ + int index; + TkListbox *l; + TkLentry *e, *s; + + l = TKobj(TkListbox, tk); + + if(*buf == '@') { + while(*buf && *buf != ',') + buf++; + index = l->yelem + atoi(buf+1)/lineheight(tk); + if (index < 0) + return 0; + if (index > l->nitem) + return l->nitem; + return index; + } + if(*buf >= '0' && *buf <= '9') + return atoi(buf); + + if(strcmp(buf, "end") == 0) { + if(l->nitem == 0) + return 0; + return l->nitem-1; + } + + index = 0; + if(strcmp(buf, "active") == 0) + s = l->active; + else + if(strcmp(buf, "anchor") == 0) + s = l->anchor; + else + return -1; + + for(e = l->head; e; e = e->link) { + if(e == s) + return index; + index++; + } + return -1; +} + +void +tklistsv(Tk *tk) +{ + TkListbox *l; + int nl, lh, top, bot; + char val[Tkminitem], cmd[Tkmaxitem], *v, *e; + + l = TKobj(TkListbox, tk); + if(l->yscroll == nil) + return; + + top = 0; + bot = TKI2F(1); + + if(l->nitem != 0) { + lh = lineheight(tk); + nl = tk->act.height/lh; /* Lines in the box */ + top = TKI2F(l->yelem)/l->nitem; + bot = TKI2F(l->yelem+nl)/l->nitem; + } + + v = tkfprint(val, top); + *v++ = ' '; + tkfprint(v, bot); + snprint(cmd, sizeof(cmd), "%s %s", l->yscroll, val); + e = tkexec(tk->env->top, cmd, nil); + if ((e != nil) && (tk->name != nil)) + print("tk: yscrollcommand \"%s\": %s\n", tk->name->name, e); +} + +void +tklistsh(Tk *tk) +{ + int nl, top, bot; + char val[Tkminitem], cmd[Tkmaxitem], *v, *e; + TkListbox *l = TKobj(TkListbox, tk); + + if(l->xscroll == nil) + return; + + top = 0; + bot = TKI2F(1); + + if(l->nwidth != 0) { + nl = tk->act.width; + top = TKI2F(l->xdelta)/l->nwidth; + bot = TKI2F(l->xdelta+nl)/l->nwidth; + } + + v = tkfprint(val, top); + *v++ = ' '; + tkfprint(v, bot); + snprint(cmd, sizeof(cmd), "%s %s", l->xscroll, val); + e = tkexec(tk->env->top, cmd, nil); + if ((e != nil) && (tk->name != nil)) + print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e); +} + +void +tklistbgeom(Tk *tk) +{ + tklistsv(tk); + tklistsh(tk); +} + +static void +listbresize(Tk *tk) +{ + TkLentry *e; + TkListbox *l = TKobj(TkListbox, tk); + + l->nwidth = 0; + for (e = l->head; e != nil; e = e->link) { + e->width = stringwidth(tk->env->font, e->text)+2*(Listpadx+l->sborderwidth+tk->highlightwidth); + if(e->width > l->nwidth) + l->nwidth = e->width; + } + tklistbgeom(tk); +} + + +/* Widget Commands (+ means implemented) + +activate + bbox + +cget + +configure + +curselection + +delete + +get + +index + +insert + +nearest + +see + +selection + +size + +xview + +yview +*/ + +char* +tklistbconf(Tk *tk, char *arg, char **val) +{ + char *e; + TkGeom g; + int bd, sbw, hlw; + TkOptab tko[3]; + Font *f; + TkListbox *tkl = TKobj(TkListbox, tk); + + sbw = tkl->sborderwidth; + hlw = tk->highlightwidth; + f = tk->env->font; + tko[0].ptr = tk; + tko[0].optab = tkgeneric; + tko[1].ptr = tkl; + tko[1].optab = opts; + tko[2].ptr = nil; + + if(*arg == '\0') + return tkconflist(tko, val); + + g = tk->req; + bd = tk->borderwidth; + e = tkparse(tk->env->top, arg, tko, nil); + tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); + tkgeomchg(tk, &g, bd); + + if (sbw != tkl->sborderwidth || f != tk->env->font || hlw != tk->highlightwidth) + listbresize(tk); + tk->dirty = tkrect(tk, 1); + return e; +} + +static void +entryactivate(Tk *tk, int index) +{ + TkListbox *l = TKobj(TkListbox, tk); + TkLentry *e; + int flag = Tkactive; + + if (l->selmode == TKbrowse) + flag |= Tkactivated; + for(e = l->head; e; e = e->link) { + if(index-- == 0) { + e->flag |= flag; + l->active = e; + } else + e->flag &= ~flag; + } + tk->dirty = tkrect(tk, 1); +} + +char* +tklistbactivate(Tk *tk, char *arg, char **val) +{ + int index; + char buf[Tkmaxitem]; + + USED(val); + tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + index = tklindex(tk, buf); + if(index == -1) + return TkBadix; + + entryactivate(tk, index); + return nil; +} + +char* +tklistbnearest(Tk *tk, char *arg, char **val) +{ + int lh, y, index; + TkListbox *l = TKobj(TkListbox, tk); + + lh = lineheight(tk); /* Line height */ + y = atoi(arg); + index = l->yelem + y/lh; + if(index > l->nitem) + index = l->nitem; + return tkvalue(val, "%d", index); +} + +char* +tklistbindex(Tk *tk, char *arg, char **val) +{ + int index; + char buf[Tkmaxitem]; + tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + index = tklindex(tk, buf); + if(index == -1) + return TkBadix; + return tkvalue(val, "%d", index); +} + +char* +tklistbsize(Tk *tk, char *arg, char **val) +{ + TkListbox *l = TKobj(TkListbox, tk); + + USED(arg); + return tkvalue(val, "%d", l->nitem); +} + +char* +tklistbinsert(Tk *tk, char *arg, char **val) +{ + int n, index; + TkListbox *l; + TkLentry *e, **el; + char *tbuf, buf[Tkmaxitem]; + + USED(val); + l = TKobj(TkListbox, tk); + + arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + if(strcmp(buf, "end") == 0) { + el = &l->head; + if(*el != nil) { + for(e = *el; e->link; e = e->link) + ; + el = &e->link; + } + } + else { + index = tklindex(tk, buf); + if(index == -1) + return TkBadix; + el = &l->head; + for(e = *el; e && index-- > 0; e = e->link) + el = &e->link; + } + + n = strlen(arg); + if(n > Tkmaxitem) { + n = (n*3)/2; + tbuf = malloc(n); + if(tbuf == nil) + return TkNomem; + } + else { + tbuf = buf; + n = sizeof(buf); + } + + while(*arg) { + arg = tkword(tk->env->top, arg, tbuf, &tbuf[n], nil); + e = malloc(sizeof(TkLentry)+strlen(tbuf)+1); + if(e == nil) + return TkNomem; + + e->flag = 0; + strcpy(e->text, tbuf); + e->link = *el; + *el = e; + el = &e->link; + e->width = stringwidth(tk->env->font, e->text)+2*(Listpadx+l->sborderwidth+tk->highlightwidth); + if(e->width > l->nwidth) + l->nwidth = e->width; + l->nitem++; + } + + if(tbuf != buf) + free(tbuf); + + tklistbgeom(tk); + tk->dirty = tkrect(tk, 1); + return nil; +} + +int +tklistbrange(Tk *tk, char *arg, int *s, int *e) +{ + char buf[Tkmaxitem]; + + arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + *s = tklindex(tk, buf); + if(*s == -1) + return -1; + *e = *s; + if(*arg == '\0') + return 0; + + tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + *e = tklindex(tk, buf); + if(*e == -1) + return -1; + return 0; +} + +char* +tklistbselection(Tk *tk, char *arg, char **val) +{ + TkTop *t; + TkLentry *f; + TkListbox *l; + int s, e, indx; + char buf[Tkmaxitem]; + + l = TKobj(TkListbox, tk); + + t = tk->env->top; + arg = tkword(t, arg, buf, buf+sizeof(buf), nil); + if(strcmp(buf, "includes") == 0) { + tkword(t, arg, buf, buf+sizeof(buf), nil); + indx = tklindex(tk, buf); + if(indx == -1) + return TkBadix; + for(f = l->head; f && indx > 0; f = f->link) + indx--; + s = 0; + if(f && (f->flag&Tkactivated)) + s = 1; + return tkvalue(val, "%d", s); + } + + if(strcmp(buf, "anchor") == 0) { + tkword(t, arg, buf, buf+sizeof(buf), nil); + indx = tklindex(tk, buf); + if(indx == -1) + return TkBadix; + for(f = l->head; f && indx > 0; f = f->link) + indx--; + if(f != nil) + l->anchor = f; + return nil; + } + indx = 0; + if(strcmp(buf, "clear") == 0) { + if(tklistbrange(tk, arg, &s, &e) != 0) + return TkBadix; + for(f = l->head; f; f = f->link) { + if(indx <= e && indx++ >= s) + f->flag &= ~Tkactivated; + } + tk->dirty = tkrect(tk, 1); + return nil; + } + if(strcmp(buf, "set") == 0) { + if(tklistbrange(tk, arg, &s, &e) != 0) + return TkBadix; + for(f = l->head; f; f = f->link) { + if(indx <= e && indx++ >= s) + f->flag |= Tkactivated; + } + tk->dirty = tkrect(tk, 1); + return nil; + } + return TkBadcm; +} + +char* +tklistbdelete(Tk *tk, char *arg, char **val) +{ + TkLentry *e, **el; + int start, end, indx, bh; + TkListbox *l = TKobj(TkListbox, tk); + + USED(val); + if(tklistbrange(tk, arg, &start, &end) != 0) + return TkBadix; + + indx = 0; + el = &l->head; + for(e = l->head; e && indx < start; e = e->link) { + indx++; + el = &e->link; + } + while(e != nil && indx <= end) { + *el = e->link; + if(e->width == l->nwidth) + l->nwidth = 0; + if (e == l->anchor) + l->anchor = nil; + if (e == l->active) + l->active = nil; + free(e); + e = *el; + indx++; + l->nitem--; + } + if(l->nwidth == 0) { + for(e = l->head; e; e = e->link) + if(e->width > l->nwidth) + l->nwidth = e->width; + } + bh = tk->act.height/lineheight(tk); /* Box height */ + if(l->yelem + bh > l->nitem) + l->yelem = l->nitem - bh; + if(l->yelem < 0) + l->yelem = 0; + + tklistbgeom(tk); + tk->dirty = tkrect(tk, 1); + return nil; +} + +char* +tklistbget(Tk *tk, char *arg, char **val) +{ + TkLentry *e; + char *r, *fmt; + int start, end, indx; + TkListbox *l = TKobj(TkListbox, tk); + + if(tklistbrange(tk, arg, &start, &end) != 0) + return TkBadix; + + indx = 0; + for(e = l->head; e && indx < start; e = e->link) + indx++; + fmt = "%s"; + while(e != nil && indx <= end) { + r = tkvalue(val, fmt, e->text); + if(r != nil) + return r; + indx++; + fmt = " %s"; + e = e->link; + } + return nil; +} + +char* +tklistbcursel(Tk *tk, char *arg, char **val) +{ + int indx; + TkLentry *e; + char *r, *fmt; + TkListbox *l = TKobj(TkListbox, tk); + + USED(arg); + indx = 0; + fmt = "%d"; + for(e = l->head; e; e = e->link) { + if(e->flag & Tkactivated) { + r = tkvalue(val, fmt, indx); + if(r != nil) + return r; + fmt = " %d"; + } + indx++; + } + return nil; +} + +static char* +tklistbview(Tk *tk, char *arg, char **val, int nl, int *posn, int max) +{ + int top, bot, amount; + char buf[Tkmaxitem]; + char *v, *e; + + top = 0; + if(*arg == '\0') { + if ( max <= nl || max == 0 ) { /* Double test redundant at + * this time, but want to + * protect against future + * calls. -- DBK */ + top = 0; + bot = TKI2F(1); + } + else { + top = TKI2F(*posn)/max; + bot = TKI2F(*posn+nl)/max; + } + v = tkfprint(buf, top); + *v++ = ' '; + tkfprint(v, bot); + return tkvalue(val, "%s", buf); + } + + arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + if(strcmp(buf, "moveto") == 0) { + e = tkfracword(tk->env->top, &arg, &top, nil); + if (e != nil) + return e; + *posn = TKF2I((top+1)*max); + } + else + if(strcmp(buf, "scroll") == 0) { + arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + amount = atoi(buf); + tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + if(buf[0] == 'p') /* Pages */ + amount *= nl; + *posn += amount; + } + else { + top = tklindex(tk, buf); + if(top == -1) + return TkBadix; + *posn = top; + } + + bot = max - nl; + if(*posn > bot) + *posn = bot; + if(*posn < 0) + *posn = 0; + + tk->dirty = tkrect(tk, 1); + return nil; +} + +static int +entrysee(Tk *tk, int index) +{ + TkListbox *l = TKobj(TkListbox, tk); + int bh; + + /* Box height in lines */ + bh = tk->act.height/lineheight(tk); + if (bh > l->nitem) + bh = l->nitem; + if (index >= l->nitem) + index = l->nitem -1; + if (index < 0) + index = 0; + + /* If the item is already visible, do nothing */ + if (l->nitem == 0 || index >= l->yelem && index < l->yelem+bh) + return index; + + if (index < l->yelem) + l->yelem = index; + else + l->yelem = index - (bh-1); + + tklistsv(tk); + tk->dirty = tkrect(tk, 1); + return index; +} + +char* +tklistbsee(Tk *tk, char *arg, char **val) +{ + int index; + char buf[Tkmaxitem]; + + USED(val); + tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); + index = tklindex(tk, buf); + if(index == -1) + return TkBadix; + + entrysee(tk, index); + return nil; +} + +char* +tklistbyview(Tk *tk, char *arg, char **val) +{ + int bh; + char *e; + TkListbox *l = TKobj(TkListbox, tk); + + bh = tk->act.height/lineheight(tk); /* Box height */ + e = tklistbview(tk, arg, val, bh, &l->yelem, l->nitem); + tklistsv(tk); + return e; +} + +char* +tklistbxview(Tk *tk, char *arg, char **val) +{ + char *e; + TkListbox *l = TKobj(TkListbox, tk); + + e = tklistbview(tk, arg, val, tk->act.width, &l->xdelta, l->nwidth); + tklistsh(tk); + return e; +} + +static TkLentry* +entryset(TkListbox *l, int indx, int toggle) +{ + TkLentry *e, *anchor; + + anchor = nil; + for(e = l->head; e; e = e->link) { + if (indx-- == 0) { + anchor = e; + if (toggle) { + e->flag ^= Tkactivated; + break; + } else + e->flag |= Tkactivated; + continue; + } + if (!toggle) + e->flag &= ~Tkactivated; + } + return anchor; +} + +static void +selectto(TkListbox *l, int indx) +{ + TkLentry *e; + int inrange; + + if (l->anchor == nil) + return; + inrange = 0; + for(e = l->head; e; e = e->link) { + if(indx == 0) + inrange = !inrange; + if(e == l->anchor) + inrange = !inrange; + if(inrange || e == l->anchor || indx == 0) + e->flag |= Tkactivated; + else + e->flag &= ~Tkactivated; + indx--; + } +} + +static char* +dragto(Tk *tk, int y) +{ + int indx; + TkLentry *e; + TkListbox *l = TKobj(TkListbox, tk); + + indx = y/lineheight(tk); + if (y < 0) + indx--; /* int division rounds towards 0 */ + if (y < tk->act.height && indx >= l->nitem) + return nil; + indx = entrysee(tk, l->yelem+indx); + entryactivate(tk, indx); + + if(l->selmode == TKsingle || l->selmode == TKmultiple) + return nil; + + if(l->selmode == TKbrowse) { + for(e = l->head; e; e = e->link) { + if(indx-- == 0) { + if (e == l->anchor) + return nil; + l->anchor = e; + e->flag |= Tkactivated; + } else + e->flag &= ~Tkactivated; + } + return nil; + } + /* extended selection mode */ + selectto(l, indx); + tk->dirty = tkrect(tk, 1); + return nil; +} + +static void +autoselect(Tk *tk, void *v, int cancelled) +{ + Point pt; + int y, eh, ne; + + USED(v); + if (cancelled) + return; + + pt = tkposn(tk); + pt.y += tk->borderwidth; + y = tk->env->top->ctxt->mstate.y; + y -= pt.y; + eh = lineheight(tk); + ne = tk->act.height/eh; + if (y >= 0 && y < eh*ne) + return; + dragto(tk, y); + tkdirty(tk); + tkupdate(tk->env->top); +} + +static char* +tklistbbutton1p(Tk *tk, char *arg, char **val) +{ + TkListbox *l = TKobj(TkListbox, tk); + int y, indx; + + USED(val); + + y = atoi(arg); + indx = y/lineheight(tk); + indx += l->yelem; + if (indx < l->nitem) { + l->anchor = entryset(l, indx, l->selmode == TKmultiple); + entryactivate(tk, indx); + entrysee(tk, indx); + } + tkrepeat(tk, autoselect, nil, TkRptpause, TkRptinterval); + return nil; +} + +char * +tklistbbutton1r(Tk *tk, char *arg, char **val) +{ + USED(arg); + USED(val); + tkcancelrepeat(tk); + return nil; +} + +char* +tklistbbutton1m(Tk *tk, char *arg, char **val) +{ + int y, eh, ne; + USED(val); + + eh = lineheight(tk); + ne = tk->act.height/eh; + y = atoi(arg); + /* If outside the box, let autoselect handle it */ + if (y < 0 || y >= ne * eh) + return nil; + return dragto(tk, y); +} + +char* +tklistbkey(Tk *tk, char *arg, char **val) +{ + TkListbox *l = TKobj(TkListbox, tk); + TkLentry *e; + int key, active; + USED(val); + + if(tk->flag & Tkdisabled) + return nil; + + key = atoi(arg); + active = 0; + for (e = l->head; e != nil; e = e->link) { + if (e->flag & Tkactive) + break; + active++; + } + + if (key == '\n' || key == ' ') { + l->anchor = entryset(l, active, l->selmode == TKmultiple); + tk->dirty = tkrect(tk, 0); + return nil; + } + if (key == Up) + active--; + else if (key == Down) + active++; + else + return nil; + + if (active < 0) + active = 0; + if (active >= l->nitem) + active = l->nitem-1; + entryactivate(tk, active); + if (l->selmode == TKextended) { + selectto(l, active); + tk->dirty = tkrect(tk, 0); + } + entrysee(tk, active); + return nil; +} + +static +TkCmdtab tklistcmd[] = +{ + "activate", tklistbactivate, + "cget", tklistbcget, + "configure", tklistbconf, + "curselection", tklistbcursel, + "delete", tklistbdelete, + "get", tklistbget, + "index", tklistbindex, + "insert", tklistbinsert, + "nearest", tklistbnearest, + "selection", tklistbselection, + "see", tklistbsee, + "size", tklistbsize, + "xview", tklistbxview, + "yview", tklistbyview, + "tkListbButton1P", tklistbbutton1p, + "tkListbButton1R", tklistbbutton1r, + "tkListbButton1MP", tklistbbutton1m, + "tkListbKey", tklistbkey, + nil +}; + +TkMethod listboxmethod = { + "listbox", + tklistcmd, + tkfreelistb, + tkdrawlistb, + tklistbgeom +}; |
