137da2899SCharles.Forsyth #include <lib9.h>
237da2899SCharles.Forsyth #include <kernel.h>
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "keyboard.h"
537da2899SCharles.Forsyth #include "tk.h"
637da2899SCharles.Forsyth
737da2899SCharles.Forsyth /* Widget Commands (+ means implemented)
837da2899SCharles.Forsyth +bbox
937da2899SCharles.Forsyth +cget
1037da2899SCharles.Forsyth +configure
1137da2899SCharles.Forsyth +delete
1237da2899SCharles.Forsyth +get
1337da2899SCharles.Forsyth +icursor
1437da2899SCharles.Forsyth +index
1537da2899SCharles.Forsyth scan
1637da2899SCharles.Forsyth +selection
1737da2899SCharles.Forsyth +xview
1837da2899SCharles.Forsyth +see
1937da2899SCharles.Forsyth */
2037da2899SCharles.Forsyth
2137da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsyth #define CNTL(c) ((c)&0x1f)
2437da2899SCharles.Forsyth #define DEL 0x7f
2537da2899SCharles.Forsyth
2637da2899SCharles.Forsyth /* Layout constants */
2737da2899SCharles.Forsyth enum {
2837da2899SCharles.Forsyth Entrypady = 0,
2937da2899SCharles.Forsyth Entrypadx = 0,
3037da2899SCharles.Forsyth Inswidth = 2,
3137da2899SCharles.Forsyth
3237da2899SCharles.Forsyth Ecursoron = 1<<0,
3337da2899SCharles.Forsyth Ecenter = 1<<1,
3437da2899SCharles.Forsyth Eright = 1<<2,
3537da2899SCharles.Forsyth Eleft = 1<<3,
3637da2899SCharles.Forsyth Ewordsel = 1<<4,
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth Ejustify = Ecenter|Eleft|Eright
3937da2899SCharles.Forsyth };
4037da2899SCharles.Forsyth
4137da2899SCharles.Forsyth static TkStab tkjust[] =
4237da2899SCharles.Forsyth {
4337da2899SCharles.Forsyth "left", Eleft,
4437da2899SCharles.Forsyth "right", Eright,
4537da2899SCharles.Forsyth "center", Ecenter,
4637da2899SCharles.Forsyth nil
4737da2899SCharles.Forsyth };
4837da2899SCharles.Forsyth
4937da2899SCharles.Forsyth static
5037da2899SCharles.Forsyth TkEbind b[] =
5137da2899SCharles.Forsyth {
5237da2899SCharles.Forsyth {TkKey, "%W delete sel.first sel.last; %W insert insert {%A};%W see insert"},
5337da2899SCharles.Forsyth {TkKey|CNTL('a'), "%W icursor 0;%W see insert;%W selection clear"},
5437da2899SCharles.Forsyth {TkKey|Home, "%W icursor 0;%W see insert;%W selection clear"},
5537da2899SCharles.Forsyth {TkKey|CNTL('d'), "%W delete insert; %W see insert"},
5637da2899SCharles.Forsyth {TkKey|CNTL('e'), "%W icursor end; %W see insert;%W selection clear"},
5737da2899SCharles.Forsyth {TkKey|End, "%W icursor end; %W see insert;%W selection clear"},
5837da2899SCharles.Forsyth {TkKey|CNTL('h'), "%W tkEntryBS;%W see insert"},
5937da2899SCharles.Forsyth {TkKey|CNTL('k'), "%W delete insert end;%W see insert"},
6037da2899SCharles.Forsyth {TkKey|CNTL('u'), "%W delete 0 end;%W see insert"},
6137da2899SCharles.Forsyth {TkKey|CNTL('w'), "%W delete sel.first sel.last; %W tkEntryBW;%W see insert"},
6237da2899SCharles.Forsyth {TkKey|DEL, "%W tkEntryBS 1;%W see insert"},
6337da2899SCharles.Forsyth {TkKey|CNTL('\\'), "%W selection clear"},
6437da2899SCharles.Forsyth {TkKey|CNTL('/'), "%W selection range 0 end"},
6537da2899SCharles.Forsyth {TkKey|Left, "%W icursor insert-1;%W selection clear;%W selection from insert;%W see insert"},
6637da2899SCharles.Forsyth {TkKey|Right, "%W icursor insert+1;%W selection clear;%W selection from insert;%W see insert"},
6737da2899SCharles.Forsyth {TkButton1P, "focus %W; %W tkEntryB1P %X"},
6837da2899SCharles.Forsyth {TkButton1P|TkMotion, "%W tkEntryB1M %X"},
6937da2899SCharles.Forsyth {TkButton1R, "%W tkEntryB1R"},
7037da2899SCharles.Forsyth {TkButton1P|TkDouble, "%W tkEntryB1P %X;%W selection word @%x"},
7137da2899SCharles.Forsyth {TkButton2P, "%W tkEntryB2P %x"},
7237da2899SCharles.Forsyth {TkButton2P|TkMotion, "%W xview scroll %x scr"},
7337da2899SCharles.Forsyth {TkFocusin, "%W tkEntryFocus in"},
7437da2899SCharles.Forsyth {TkFocusout, "%W tkEntryFocus out"},
7537da2899SCharles.Forsyth {TkKey|APP|'\t', ""},
7637da2899SCharles.Forsyth {TkKey|BackTab, ""},
7737da2899SCharles.Forsyth };
7837da2899SCharles.Forsyth
7937da2899SCharles.Forsyth typedef struct TkEntry TkEntry;
8037da2899SCharles.Forsyth struct TkEntry
8137da2899SCharles.Forsyth {
8237da2899SCharles.Forsyth Rune* text;
8337da2899SCharles.Forsyth int textlen;
8437da2899SCharles.Forsyth
8537da2899SCharles.Forsyth char* xscroll;
8637da2899SCharles.Forsyth char* show;
8737da2899SCharles.Forsyth int flag;
8837da2899SCharles.Forsyth int oldx;
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsyth int icursor; /* index of insertion cursor */
9137da2899SCharles.Forsyth int anchor; /* selection anchor point */
9237da2899SCharles.Forsyth int sel0; /* index of start of selection */
9337da2899SCharles.Forsyth int sel1; /* index of end of selection */
9437da2899SCharles.Forsyth
9537da2899SCharles.Forsyth int x0; /* x-offset of visible area */
9637da2899SCharles.Forsyth
9737da2899SCharles.Forsyth /* derived values */
9837da2899SCharles.Forsyth int v0; /* index of first visible character */
9937da2899SCharles.Forsyth int v1; /* index of last visible character + 1 */
10037da2899SCharles.Forsyth int xlen; /* length of text in pixels*/
10137da2899SCharles.Forsyth int xv0; /* position of first visible character */
10237da2899SCharles.Forsyth int xsel0; /* position of start of selection */
10337da2899SCharles.Forsyth int xsel1; /* position of end of selection */
10437da2899SCharles.Forsyth int xicursor; /* position of insertion cursor */
10537da2899SCharles.Forsyth };
10637da2899SCharles.Forsyth
10737da2899SCharles.Forsyth static void blinkreset(Tk*);
10837da2899SCharles.Forsyth
10937da2899SCharles.Forsyth static
11037da2899SCharles.Forsyth TkOption opts[] =
11137da2899SCharles.Forsyth {
11237da2899SCharles.Forsyth "xscrollcommand", OPTtext, O(TkEntry, xscroll), nil,
11337da2899SCharles.Forsyth "justify", OPTstab, O(TkEntry, flag), tkjust,
11437da2899SCharles.Forsyth "show", OPTtext, O(TkEntry, show), nil,
11537da2899SCharles.Forsyth nil
11637da2899SCharles.Forsyth };
11737da2899SCharles.Forsyth
11837da2899SCharles.Forsyth static int
xinset(Tk * tk)11937da2899SCharles.Forsyth xinset(Tk *tk)
12037da2899SCharles.Forsyth {
12137da2899SCharles.Forsyth return Entrypadx + tk->highlightwidth;
12237da2899SCharles.Forsyth }
12337da2899SCharles.Forsyth
12437da2899SCharles.Forsyth static int
yinset(Tk * tk)12537da2899SCharles.Forsyth yinset(Tk *tk)
12637da2899SCharles.Forsyth {
12737da2899SCharles.Forsyth return Entrypady + tk->highlightwidth;
12837da2899SCharles.Forsyth }
12937da2899SCharles.Forsyth
13037da2899SCharles.Forsyth static void
tksizeentry(Tk * tk)13137da2899SCharles.Forsyth tksizeentry(Tk *tk)
13237da2899SCharles.Forsyth {
13337da2899SCharles.Forsyth if((tk->flag & Tksetwidth) == 0)
13437da2899SCharles.Forsyth tk->req.width = tk->env->wzero*25 + 2*xinset(tk) + Inswidth;
13537da2899SCharles.Forsyth if((tk->flag & Tksetheight) == 0)
13637da2899SCharles.Forsyth tk->req.height = tk->env->font->height+ 2*yinset(tk);
13737da2899SCharles.Forsyth }
13837da2899SCharles.Forsyth
13937da2899SCharles.Forsyth int
entrytextwidth(Tk * tk,int n)14037da2899SCharles.Forsyth entrytextwidth(Tk *tk, int n)
14137da2899SCharles.Forsyth {
14237da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
14337da2899SCharles.Forsyth Rune c;
14437da2899SCharles.Forsyth Font *f;
14537da2899SCharles.Forsyth
14637da2899SCharles.Forsyth f = tk->env->font;
14737da2899SCharles.Forsyth if (tke->show != nil) {
14837da2899SCharles.Forsyth chartorune(&c, tke->show);
14937da2899SCharles.Forsyth return n * runestringnwidth(f, &c, 1);
15037da2899SCharles.Forsyth }
15137da2899SCharles.Forsyth return runestringnwidth(f, tke->text, n);
15237da2899SCharles.Forsyth }
15337da2899SCharles.Forsyth
15437da2899SCharles.Forsyth static int
x2index(Tk * tk,int x,int * xc)15537da2899SCharles.Forsyth x2index(Tk *tk, int x, int *xc)
15637da2899SCharles.Forsyth {
15737da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
15837da2899SCharles.Forsyth int t0, t1, r, q;
15937da2899SCharles.Forsyth
16037da2899SCharles.Forsyth t0 = 0;
16137da2899SCharles.Forsyth t1 = tke->textlen;
16237da2899SCharles.Forsyth while (t0 <= t1) {
16337da2899SCharles.Forsyth r = (t0 + t1) / 2;
16437da2899SCharles.Forsyth q = entrytextwidth(tk, r);
16537da2899SCharles.Forsyth if (q == x) {
16637da2899SCharles.Forsyth if (xc != nil)
16737da2899SCharles.Forsyth *xc = q;
16837da2899SCharles.Forsyth return r;
16937da2899SCharles.Forsyth }
17037da2899SCharles.Forsyth if (q < x)
17137da2899SCharles.Forsyth t0 = r + 1;
17237da2899SCharles.Forsyth else
17337da2899SCharles.Forsyth t1 = r - 1;
17437da2899SCharles.Forsyth }
17537da2899SCharles.Forsyth if (xc != nil)
17637da2899SCharles.Forsyth *xc = t1 > 0 ? entrytextwidth(tk, t1) : 0;
17737da2899SCharles.Forsyth if (t1 < 0)
17837da2899SCharles.Forsyth t1 = 0;
17937da2899SCharles.Forsyth return t1;
18037da2899SCharles.Forsyth }
18137da2899SCharles.Forsyth
18237da2899SCharles.Forsyth /*
18337da2899SCharles.Forsyth * recalculate derived values
18437da2899SCharles.Forsyth */
18537da2899SCharles.Forsyth static void
recalcentry(Tk * tk)18637da2899SCharles.Forsyth recalcentry(Tk *tk)
18737da2899SCharles.Forsyth {
18837da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
18937da2899SCharles.Forsyth int x, avail, locked;
19037da2899SCharles.Forsyth
19137da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
19237da2899SCharles.Forsyth
19337da2899SCharles.Forsyth tke->xlen = entrytextwidth(tk, tke->textlen) + Inswidth;
19437da2899SCharles.Forsyth
19537da2899SCharles.Forsyth avail = tk->act.width - 2*xinset(tk);
19637da2899SCharles.Forsyth if (tke->xlen < avail) {
19737da2899SCharles.Forsyth switch(tke->flag & Ejustify) {
19837da2899SCharles.Forsyth default:
19937da2899SCharles.Forsyth tke->x0 = 0;
20037da2899SCharles.Forsyth break;
20137da2899SCharles.Forsyth case Eright:
20237da2899SCharles.Forsyth tke->x0 = -(avail - tke->xlen);
20337da2899SCharles.Forsyth break;
20437da2899SCharles.Forsyth case Ecenter:
20537da2899SCharles.Forsyth tke->x0 = -(avail - tke->xlen) / 2;
20637da2899SCharles.Forsyth break;
20737da2899SCharles.Forsyth }
20837da2899SCharles.Forsyth }
20937da2899SCharles.Forsyth
21037da2899SCharles.Forsyth tke->v0 = x2index(tk, tke->x0, &tke->xv0);
21137da2899SCharles.Forsyth tke->v1 = x2index(tk, tk->act.width + tke->x0, &x);
21237da2899SCharles.Forsyth /* perhaps include partial last character */
21337da2899SCharles.Forsyth if (tke->v1 < tke->textlen && x < avail + tke->x0)
21437da2899SCharles.Forsyth tke->v1++;
21537da2899SCharles.Forsyth tke->xsel0 = entrytextwidth(tk, tke->sel0);
21637da2899SCharles.Forsyth tke->xsel1 = entrytextwidth(tk, tke->sel1);
21737da2899SCharles.Forsyth tke->xicursor = entrytextwidth(tk, tke->icursor);
21837da2899SCharles.Forsyth
21937da2899SCharles.Forsyth if (locked)
22037da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
22137da2899SCharles.Forsyth }
22237da2899SCharles.Forsyth
22337da2899SCharles.Forsyth char*
tkentry(TkTop * t,char * arg,char ** ret)22437da2899SCharles.Forsyth tkentry(TkTop *t, char *arg, char **ret)
22537da2899SCharles.Forsyth {
22637da2899SCharles.Forsyth Tk *tk;
22737da2899SCharles.Forsyth char *e;
22837da2899SCharles.Forsyth TkName *names;
22937da2899SCharles.Forsyth TkEntry *tke;
23037da2899SCharles.Forsyth TkOptab tko[3];
23137da2899SCharles.Forsyth
23237da2899SCharles.Forsyth tk = tknewobj(t, TKentry, sizeof(Tk)+sizeof(TkEntry));
23337da2899SCharles.Forsyth if(tk == nil)
23437da2899SCharles.Forsyth return TkNomem;
23537da2899SCharles.Forsyth
23637da2899SCharles.Forsyth tk->relief = TKsunken;
237*c9ccdbd5Sforsyth tk->borderwidth = 1;
23837da2899SCharles.Forsyth tk->flag |= Tktakefocus;
23937da2899SCharles.Forsyth tk->highlightwidth = 1;
24037da2899SCharles.Forsyth
24137da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
24237da2899SCharles.Forsyth
24337da2899SCharles.Forsyth tko[0].ptr = tk;
24437da2899SCharles.Forsyth tko[0].optab = tkgeneric;
24537da2899SCharles.Forsyth tko[1].ptr = tke;
24637da2899SCharles.Forsyth tko[1].optab = opts;
24737da2899SCharles.Forsyth tko[2].ptr = nil;
24837da2899SCharles.Forsyth
24937da2899SCharles.Forsyth names = nil;
25037da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
25137da2899SCharles.Forsyth if(e != nil) {
25237da2899SCharles.Forsyth tkfreeobj(tk);
25337da2899SCharles.Forsyth return e;
25437da2899SCharles.Forsyth }
25537da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
25637da2899SCharles.Forsyth tksizeentry(tk);
25737da2899SCharles.Forsyth e = tkbindings(t, tk, b, nelem(b));
25837da2899SCharles.Forsyth
25937da2899SCharles.Forsyth if(e != nil) {
26037da2899SCharles.Forsyth tkfreeobj(tk);
26137da2899SCharles.Forsyth return e;
26237da2899SCharles.Forsyth }
26337da2899SCharles.Forsyth
26437da2899SCharles.Forsyth e = tkaddchild(t, tk, &names);
26537da2899SCharles.Forsyth tkfreename(names);
26637da2899SCharles.Forsyth if(e != nil) {
26737da2899SCharles.Forsyth tkfreeobj(tk);
26837da2899SCharles.Forsyth return e;
26937da2899SCharles.Forsyth }
27037da2899SCharles.Forsyth tk->name->link = nil;
27137da2899SCharles.Forsyth recalcentry(tk);
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth return tkvalue(ret, "%s", tk->name->name);
27437da2899SCharles.Forsyth }
27537da2899SCharles.Forsyth
27637da2899SCharles.Forsyth static char*
tkentrycget(Tk * tk,char * arg,char ** val)27737da2899SCharles.Forsyth tkentrycget(Tk *tk, char *arg, char **val)
27837da2899SCharles.Forsyth {
27937da2899SCharles.Forsyth TkOptab tko[3];
28037da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
28137da2899SCharles.Forsyth
28237da2899SCharles.Forsyth tko[0].ptr = tk;
28337da2899SCharles.Forsyth tko[0].optab = tkgeneric;
28437da2899SCharles.Forsyth tko[1].ptr = tke;
28537da2899SCharles.Forsyth tko[1].optab = opts;
28637da2899SCharles.Forsyth tko[2].ptr = nil;
28737da2899SCharles.Forsyth
28837da2899SCharles.Forsyth return tkgencget(tko, arg, val, tk->env->top);
28937da2899SCharles.Forsyth }
29037da2899SCharles.Forsyth
29137da2899SCharles.Forsyth void
tkfreeentry(Tk * tk)29237da2899SCharles.Forsyth tkfreeentry(Tk *tk)
29337da2899SCharles.Forsyth {
29437da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
29537da2899SCharles.Forsyth
29637da2899SCharles.Forsyth free(tke->xscroll);
29737da2899SCharles.Forsyth free(tke->text);
29837da2899SCharles.Forsyth free(tke->show);
29937da2899SCharles.Forsyth }
30037da2899SCharles.Forsyth
30137da2899SCharles.Forsyth static void
tkentrytext(Image * i,Rectangle s,Tk * tk,TkEnv * env)30237da2899SCharles.Forsyth tkentrytext(Image *i, Rectangle s, Tk *tk, TkEnv *env)
30337da2899SCharles.Forsyth {
30437da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
30537da2899SCharles.Forsyth Point dp;
30637da2899SCharles.Forsyth int s0, s1, xs0, xs1, j;
30737da2899SCharles.Forsyth Rectangle r;
30837da2899SCharles.Forsyth Rune showr, *text;
30937da2899SCharles.Forsyth
31037da2899SCharles.Forsyth dp = Pt(s.min.x - (tke->x0 - tke->xv0), s.min.y);
31137da2899SCharles.Forsyth if (tke->show) {
31237da2899SCharles.Forsyth chartorune(&showr, tke->show);
31337da2899SCharles.Forsyth text = mallocz(sizeof(Rune) * (tke->textlen+1), 0);
31437da2899SCharles.Forsyth if (text == nil)
31537da2899SCharles.Forsyth return;
31637da2899SCharles.Forsyth for (j = 0; j < tke->textlen; j++)
31737da2899SCharles.Forsyth text[j] = showr;
31837da2899SCharles.Forsyth } else
31937da2899SCharles.Forsyth text = tke->text;
32037da2899SCharles.Forsyth
32137da2899SCharles.Forsyth runestringn(i, dp, tkgc(env, TkCforegnd), dp, env->font,
32237da2899SCharles.Forsyth text+tke->v0, tke->v1-tke->v0);
32337da2899SCharles.Forsyth
32437da2899SCharles.Forsyth if (tke->sel0 < tke->v1 && tke->sel1 > tke->v0) {
32537da2899SCharles.Forsyth if (tke->sel0 < tke->v0) {
32637da2899SCharles.Forsyth s0 = tke->v0;
32737da2899SCharles.Forsyth xs0 = tke->xv0 - tke->x0;
32837da2899SCharles.Forsyth } else {
32937da2899SCharles.Forsyth s0 = tke->sel0;
33037da2899SCharles.Forsyth xs0 = tke->xsel0 - tke->x0;
33137da2899SCharles.Forsyth }
33237da2899SCharles.Forsyth
33337da2899SCharles.Forsyth if (tke->sel1 > tke->v1) {
33437da2899SCharles.Forsyth s1 = tke->v1;
33537da2899SCharles.Forsyth xs1 = s.max.x;
33637da2899SCharles.Forsyth } else {
33737da2899SCharles.Forsyth s1 = tke->sel1;
33837da2899SCharles.Forsyth xs1 = tke->xsel1 - tke->x0;
33937da2899SCharles.Forsyth }
34037da2899SCharles.Forsyth
34137da2899SCharles.Forsyth r = rectaddpt(Rect(xs0, 0, xs1, env->font->height), s.min);
34237da2899SCharles.Forsyth tktextsdraw(i, r, env, 1);
34337da2899SCharles.Forsyth runestringn(i, r.min, tkgc(env, TkCselectfgnd), r.min, env->font,
34437da2899SCharles.Forsyth text+s0, s1-s0);
34537da2899SCharles.Forsyth }
34637da2899SCharles.Forsyth
34737da2899SCharles.Forsyth if((tke->flag&Ecursoron) && tke->icursor >= tke->v0 && tke->icursor <= tke->v1) {
34837da2899SCharles.Forsyth r = Rect(
34937da2899SCharles.Forsyth tke->xicursor - tke->x0, 0,
35037da2899SCharles.Forsyth tke->xicursor - tke->x0 + Inswidth, env->font->height
35137da2899SCharles.Forsyth );
35237da2899SCharles.Forsyth draw(i, rectaddpt(r, s.min), tkgc(env, TkCforegnd), nil, ZP);
35337da2899SCharles.Forsyth }
35437da2899SCharles.Forsyth if (tke->show)
35537da2899SCharles.Forsyth free(text);
35637da2899SCharles.Forsyth }
35737da2899SCharles.Forsyth
35837da2899SCharles.Forsyth char*
tkdrawentry(Tk * tk,Point orig)35937da2899SCharles.Forsyth tkdrawentry(Tk *tk, Point orig)
36037da2899SCharles.Forsyth {
36137da2899SCharles.Forsyth Point p;
36237da2899SCharles.Forsyth TkEnv *env;
36337da2899SCharles.Forsyth Rectangle r, s;
36437da2899SCharles.Forsyth Image *i;
36537da2899SCharles.Forsyth int xp, yp;
36637da2899SCharles.Forsyth
36737da2899SCharles.Forsyth env = tk->env;
36837da2899SCharles.Forsyth
36937da2899SCharles.Forsyth r.min = ZP;
37037da2899SCharles.Forsyth r.max.x = tk->act.width + 2*tk->borderwidth;
37137da2899SCharles.Forsyth r.max.y = tk->act.height + 2*tk->borderwidth;
37237da2899SCharles.Forsyth i = tkitmp(env, r.max, TkCbackgnd);
37337da2899SCharles.Forsyth if(i == nil)
37437da2899SCharles.Forsyth return nil;
37537da2899SCharles.Forsyth
37637da2899SCharles.Forsyth xp = tk->borderwidth + xinset(tk);
37737da2899SCharles.Forsyth yp = tk->borderwidth + yinset(tk);
37837da2899SCharles.Forsyth s = r;
37937da2899SCharles.Forsyth s.min.x += xp;
38037da2899SCharles.Forsyth s.max.x -= xp;
38137da2899SCharles.Forsyth s.min.y += yp;
38237da2899SCharles.Forsyth s.max.y -= yp;
38337da2899SCharles.Forsyth tkentrytext(i, s, tk, env);
38437da2899SCharles.Forsyth
38537da2899SCharles.Forsyth tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);
38637da2899SCharles.Forsyth
38737da2899SCharles.Forsyth if (tkhaskeyfocus(tk))
38837da2899SCharles.Forsyth tkbox(i, insetrect(r, tk->borderwidth), tk->highlightwidth, tkgc(tk->env, TkChighlightfgnd));
38937da2899SCharles.Forsyth
39037da2899SCharles.Forsyth p.x = tk->act.x + orig.x;
39137da2899SCharles.Forsyth p.y = tk->act.y + orig.y;
39237da2899SCharles.Forsyth r = rectaddpt(r, p);
39337da2899SCharles.Forsyth draw(tkimageof(tk), r, i, nil, ZP);
39437da2899SCharles.Forsyth
39537da2899SCharles.Forsyth return nil;
39637da2899SCharles.Forsyth }
39737da2899SCharles.Forsyth
39837da2899SCharles.Forsyth char*
tkentrysh(Tk * tk)39937da2899SCharles.Forsyth tkentrysh(Tk *tk)
40037da2899SCharles.Forsyth {
40137da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
40237da2899SCharles.Forsyth int dx, top, bot;
40337da2899SCharles.Forsyth char *val, *cmd, *v, *e;
40437da2899SCharles.Forsyth
40537da2899SCharles.Forsyth if(tke->xscroll == nil)
40637da2899SCharles.Forsyth return nil;
40737da2899SCharles.Forsyth
40837da2899SCharles.Forsyth bot = 0;
40937da2899SCharles.Forsyth top = Tkfpscalar;
41037da2899SCharles.Forsyth
41137da2899SCharles.Forsyth if(tke->text != 0 && tke->textlen != 0) {
41237da2899SCharles.Forsyth dx = tk->act.width - 2*xinset(tk);
41337da2899SCharles.Forsyth
41437da2899SCharles.Forsyth if (tke->xlen > dx) {
41537da2899SCharles.Forsyth bot = TKI2F(tke->x0) / tke->xlen;
41637da2899SCharles.Forsyth top = TKI2F(tke->x0 + dx) / tke->xlen;
41737da2899SCharles.Forsyth }
41837da2899SCharles.Forsyth }
41937da2899SCharles.Forsyth
42037da2899SCharles.Forsyth val = mallocz(Tkminitem, 0);
42137da2899SCharles.Forsyth if(val == nil)
42237da2899SCharles.Forsyth return TkNomem;
42337da2899SCharles.Forsyth v = tkfprint(val, bot);
42437da2899SCharles.Forsyth *v++ = ' ';
42537da2899SCharles.Forsyth tkfprint(v, top);
42637da2899SCharles.Forsyth cmd = mallocz(Tkminitem, 0);
42737da2899SCharles.Forsyth if(cmd == nil) {
42837da2899SCharles.Forsyth free(val);
42937da2899SCharles.Forsyth return TkNomem;
43037da2899SCharles.Forsyth }
43137da2899SCharles.Forsyth sprint(cmd, "%s %s", tke->xscroll, val);
43237da2899SCharles.Forsyth e = tkexec(tk->env->top, cmd, nil);
43337da2899SCharles.Forsyth free(cmd);
43437da2899SCharles.Forsyth free(val);
43537da2899SCharles.Forsyth return e;
43637da2899SCharles.Forsyth }
43737da2899SCharles.Forsyth
43837da2899SCharles.Forsyth void
tkentrygeom(Tk * tk)43937da2899SCharles.Forsyth tkentrygeom(Tk *tk)
44037da2899SCharles.Forsyth {
44137da2899SCharles.Forsyth char *e;
44237da2899SCharles.Forsyth e = tkentrysh(tk);
44337da2899SCharles.Forsyth if ((e != nil) && /* XXX - Tad: should propagate not print */
44437da2899SCharles.Forsyth (tk->name != nil))
44537da2899SCharles.Forsyth print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e);
44637da2899SCharles.Forsyth recalcentry(tk);
44737da2899SCharles.Forsyth }
44837da2899SCharles.Forsyth
44937da2899SCharles.Forsyth static char*
tkentryconf(Tk * tk,char * arg,char ** val)45037da2899SCharles.Forsyth tkentryconf(Tk *tk, char *arg, char **val)
45137da2899SCharles.Forsyth {
45237da2899SCharles.Forsyth char *e;
45337da2899SCharles.Forsyth TkGeom g;
45437da2899SCharles.Forsyth int bd;
45537da2899SCharles.Forsyth TkOptab tko[3];
45637da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
45737da2899SCharles.Forsyth
45837da2899SCharles.Forsyth tko[0].ptr = tk;
45937da2899SCharles.Forsyth tko[0].optab = tkgeneric;
46037da2899SCharles.Forsyth tko[1].ptr = tke;
46137da2899SCharles.Forsyth tko[1].optab = opts;
46237da2899SCharles.Forsyth tko[2].ptr = nil;
46337da2899SCharles.Forsyth
46437da2899SCharles.Forsyth if(*arg == '\0')
46537da2899SCharles.Forsyth return tkconflist(tko, val);
46637da2899SCharles.Forsyth
46737da2899SCharles.Forsyth bd = tk->borderwidth;
46837da2899SCharles.Forsyth g = tk->req;
46937da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
47037da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
47137da2899SCharles.Forsyth tksizeentry(tk);
47237da2899SCharles.Forsyth tkgeomchg(tk, &g, bd);
47337da2899SCharles.Forsyth recalcentry(tk);
47437da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
47537da2899SCharles.Forsyth return e;
47637da2899SCharles.Forsyth }
47737da2899SCharles.Forsyth
47837da2899SCharles.Forsyth static char*
tkentryparseindex(Tk * tk,char * buf,int * index)47937da2899SCharles.Forsyth tkentryparseindex(Tk *tk, char *buf, int *index)
48037da2899SCharles.Forsyth {
48137da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
48237da2899SCharles.Forsyth TkEnv *env;
48337da2899SCharles.Forsyth char *mod;
48437da2899SCharles.Forsyth int i, x, locked, modstart;
48537da2899SCharles.Forsyth
48637da2899SCharles.Forsyth modstart = 0;
48737da2899SCharles.Forsyth for(mod = buf; *mod != '\0'; mod++)
48837da2899SCharles.Forsyth if(*mod == '-' || *mod == '+') {
48937da2899SCharles.Forsyth modstart = *mod;
49037da2899SCharles.Forsyth *mod = '\0';
49137da2899SCharles.Forsyth break;
49237da2899SCharles.Forsyth }
49337da2899SCharles.Forsyth if(strcmp(buf, "end") == 0)
49437da2899SCharles.Forsyth i = tke->textlen;
49537da2899SCharles.Forsyth else
49637da2899SCharles.Forsyth if(strcmp(buf, "anchor") == 0)
49737da2899SCharles.Forsyth i = tke->anchor;
49837da2899SCharles.Forsyth else
49937da2899SCharles.Forsyth if(strcmp(buf, "insert") == 0)
50037da2899SCharles.Forsyth i = tke->icursor;
50137da2899SCharles.Forsyth else
50237da2899SCharles.Forsyth if(strcmp(buf, "sel.first") == 0)
50337da2899SCharles.Forsyth i = tke->sel0;
50437da2899SCharles.Forsyth else
50537da2899SCharles.Forsyth if(strcmp(buf, "sel.last") == 0)
50637da2899SCharles.Forsyth i = tke->sel1;
50737da2899SCharles.Forsyth else
50837da2899SCharles.Forsyth if(buf[0] >= '0' && buf[0] <= '9')
50937da2899SCharles.Forsyth i = atoi(buf);
51037da2899SCharles.Forsyth else
51137da2899SCharles.Forsyth if(buf[0] == '@') {
51237da2899SCharles.Forsyth x = atoi(buf+1) - xinset(tk);
51337da2899SCharles.Forsyth if(tke->textlen == 0) {
51437da2899SCharles.Forsyth *index = 0;
51537da2899SCharles.Forsyth return nil;
51637da2899SCharles.Forsyth }
51737da2899SCharles.Forsyth env = tk->env;
51837da2899SCharles.Forsyth locked = lockdisplay(env->top->display);
51937da2899SCharles.Forsyth i = x2index(tk, x + tke->x0, nil); /* XXX could possibly select nearest character? */
52037da2899SCharles.Forsyth if(locked)
52137da2899SCharles.Forsyth unlockdisplay(env->top->display);
52237da2899SCharles.Forsyth }
52337da2899SCharles.Forsyth else
52437da2899SCharles.Forsyth return TkBadix;
52537da2899SCharles.Forsyth
52637da2899SCharles.Forsyth if(i < 0 || i > tke->textlen)
52737da2899SCharles.Forsyth return TkBadix;
52837da2899SCharles.Forsyth if(modstart) {
52937da2899SCharles.Forsyth *mod = modstart;
53037da2899SCharles.Forsyth i += atoi(mod);
53137da2899SCharles.Forsyth if(i < 0)
53237da2899SCharles.Forsyth i = 0;
53337da2899SCharles.Forsyth if(i > tke->textlen)
53437da2899SCharles.Forsyth i = tke->textlen;
53537da2899SCharles.Forsyth }
53637da2899SCharles.Forsyth *index = i;
53737da2899SCharles.Forsyth return nil;
53837da2899SCharles.Forsyth }
53937da2899SCharles.Forsyth
54037da2899SCharles.Forsyth /*
54137da2899SCharles.Forsyth * return bounding box of character at index, in coords relative to
54237da2899SCharles.Forsyth * the top left position of the text.
54337da2899SCharles.Forsyth */
54437da2899SCharles.Forsyth static Rectangle
tkentrybbox(Tk * tk,int index)54537da2899SCharles.Forsyth tkentrybbox(Tk *tk, int index)
54637da2899SCharles.Forsyth {
54737da2899SCharles.Forsyth TkEntry *tke;
54837da2899SCharles.Forsyth TkEnv *env;
54937da2899SCharles.Forsyth Display *d;
55037da2899SCharles.Forsyth int x, cw, locked;
55137da2899SCharles.Forsyth Rectangle r;
55237da2899SCharles.Forsyth
55337da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
55437da2899SCharles.Forsyth env = tk->env;
55537da2899SCharles.Forsyth
55637da2899SCharles.Forsyth d = env->top->display;
55737da2899SCharles.Forsyth
55837da2899SCharles.Forsyth locked = lockdisplay(d);
55937da2899SCharles.Forsyth x = entrytextwidth(tk, index);
56037da2899SCharles.Forsyth if (index < tke->textlen)
56137da2899SCharles.Forsyth cw = entrytextwidth(tk, index+1) - x;
56237da2899SCharles.Forsyth else
56337da2899SCharles.Forsyth cw = Inswidth;
56437da2899SCharles.Forsyth if(locked)
56537da2899SCharles.Forsyth unlockdisplay(d);
56637da2899SCharles.Forsyth
56737da2899SCharles.Forsyth r.min.x = x;
56837da2899SCharles.Forsyth r.min.y = 0;
56937da2899SCharles.Forsyth r.max.x = x + cw;
57037da2899SCharles.Forsyth r.max.y = env->font->height;
57137da2899SCharles.Forsyth return r;
57237da2899SCharles.Forsyth }
57337da2899SCharles.Forsyth
57437da2899SCharles.Forsyth static void
tkentrysee(Tk * tk,int index,int jump)57537da2899SCharles.Forsyth tkentrysee(Tk *tk, int index, int jump)
57637da2899SCharles.Forsyth {
57737da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
57837da2899SCharles.Forsyth int dx, margin;
57937da2899SCharles.Forsyth Rectangle r;
58037da2899SCharles.Forsyth
58137da2899SCharles.Forsyth r = tkentrybbox(tk, index);
58237da2899SCharles.Forsyth dx = tk->act.width - 2*xinset(tk);
58337da2899SCharles.Forsyth if (jump)
58437da2899SCharles.Forsyth margin = dx / 4;
58537da2899SCharles.Forsyth else
58637da2899SCharles.Forsyth margin = 0;
58737da2899SCharles.Forsyth if (r.min.x <= tke->x0 || r.max.x > tke->x0 + dx) {
58837da2899SCharles.Forsyth if (r.min.x <= tke->x0) {
58937da2899SCharles.Forsyth tke->x0 = r.min.x - margin;
59037da2899SCharles.Forsyth if (tke->x0 < 0)
59137da2899SCharles.Forsyth tke->x0 = 0;
59237da2899SCharles.Forsyth } else if (r.max.x >= tke->x0 + dx) {
59337da2899SCharles.Forsyth tke->x0 = r.max.x - dx + margin;
59437da2899SCharles.Forsyth if (tke->x0 > tke->xlen - dx)
59537da2899SCharles.Forsyth tke->x0 = tke->xlen - dx;
59637da2899SCharles.Forsyth }
59737da2899SCharles.Forsyth tk->dirty = tkrect(tk, 0);
59837da2899SCharles.Forsyth }
59937da2899SCharles.Forsyth r = rectaddpt(r, Pt(xinset(tk) - tke->x0, yinset(tk)));
60037da2899SCharles.Forsyth tksee(tk, r, r.min);
60137da2899SCharles.Forsyth }
60237da2899SCharles.Forsyth
60337da2899SCharles.Forsyth static char*
tkentryseecmd(Tk * tk,char * arg,char ** val)60437da2899SCharles.Forsyth tkentryseecmd(Tk *tk, char *arg, char **val)
60537da2899SCharles.Forsyth {
60637da2899SCharles.Forsyth int index;
60737da2899SCharles.Forsyth char *e, *buf;
60837da2899SCharles.Forsyth
60937da2899SCharles.Forsyth USED(val);
61037da2899SCharles.Forsyth
61137da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
61237da2899SCharles.Forsyth if(buf == nil)
61337da2899SCharles.Forsyth return TkNomem;
61437da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
61537da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &index);
61637da2899SCharles.Forsyth free(buf);
61737da2899SCharles.Forsyth if(e != nil)
61837da2899SCharles.Forsyth return e;
61937da2899SCharles.Forsyth
62037da2899SCharles.Forsyth tkentrysee(tk, index, 1);
62137da2899SCharles.Forsyth recalcentry(tk);
62237da2899SCharles.Forsyth
62337da2899SCharles.Forsyth return nil;
62437da2899SCharles.Forsyth }
62537da2899SCharles.Forsyth
62637da2899SCharles.Forsyth static char*
tkentrybboxcmd(Tk * tk,char * arg,char ** val)62737da2899SCharles.Forsyth tkentrybboxcmd(Tk *tk, char *arg, char **val)
62837da2899SCharles.Forsyth {
62937da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
63037da2899SCharles.Forsyth char *r, *buf;
63137da2899SCharles.Forsyth int index;
63237da2899SCharles.Forsyth Rectangle bbox;
63337da2899SCharles.Forsyth
63437da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
63537da2899SCharles.Forsyth if(buf == nil)
63637da2899SCharles.Forsyth return TkNomem;
63737da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
63837da2899SCharles.Forsyth r = tkentryparseindex(tk, buf, &index);
63937da2899SCharles.Forsyth free(buf);
64037da2899SCharles.Forsyth if(r != nil)
64137da2899SCharles.Forsyth return r;
64237da2899SCharles.Forsyth bbox = rectaddpt(tkentrybbox(tk, index), Pt(xinset(tk) - tke->x0, yinset(tk)));
64337da2899SCharles.Forsyth return tkvalue(val, "%d %d %d %d", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y);
64437da2899SCharles.Forsyth }
64537da2899SCharles.Forsyth
64637da2899SCharles.Forsyth static char*
tkentryindex(Tk * tk,char * arg,char ** val)64737da2899SCharles.Forsyth tkentryindex(Tk *tk, char *arg, char **val)
64837da2899SCharles.Forsyth {
64937da2899SCharles.Forsyth int index;
65037da2899SCharles.Forsyth char *r, *buf;
65137da2899SCharles.Forsyth
65237da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
65337da2899SCharles.Forsyth if(buf == nil)
65437da2899SCharles.Forsyth return TkNomem;
65537da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
65637da2899SCharles.Forsyth r = tkentryparseindex(tk, buf, &index);
65737da2899SCharles.Forsyth free(buf);
65837da2899SCharles.Forsyth if(r != nil)
65937da2899SCharles.Forsyth return r;
66037da2899SCharles.Forsyth return tkvalue(val, "%d", index);
66137da2899SCharles.Forsyth }
66237da2899SCharles.Forsyth
66337da2899SCharles.Forsyth static char*
tkentryicursor(Tk * tk,char * arg,char ** val)66437da2899SCharles.Forsyth tkentryicursor(Tk *tk, char *arg, char **val)
66537da2899SCharles.Forsyth {
66637da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
66737da2899SCharles.Forsyth int index, locked;
66837da2899SCharles.Forsyth char *r, *buf;
66937da2899SCharles.Forsyth
67037da2899SCharles.Forsyth USED(val);
67137da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
67237da2899SCharles.Forsyth if(buf == nil)
67337da2899SCharles.Forsyth return TkNomem;
67437da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
67537da2899SCharles.Forsyth r = tkentryparseindex(tk, buf, &index);
67637da2899SCharles.Forsyth free(buf);
67737da2899SCharles.Forsyth if(r != nil)
67837da2899SCharles.Forsyth return r;
67937da2899SCharles.Forsyth tke->icursor = index;
68037da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
68137da2899SCharles.Forsyth tke->xicursor = entrytextwidth(tk, tke->icursor);
68237da2899SCharles.Forsyth if (locked)
68337da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
68437da2899SCharles.Forsyth
68537da2899SCharles.Forsyth blinkreset(tk);
68637da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
68737da2899SCharles.Forsyth return nil;
68837da2899SCharles.Forsyth }
68937da2899SCharles.Forsyth
69037da2899SCharles.Forsyth static int
adjustforins(int i,int n,int q)69137da2899SCharles.Forsyth adjustforins(int i, int n, int q)
69237da2899SCharles.Forsyth {
69337da2899SCharles.Forsyth if (i <= q)
69437da2899SCharles.Forsyth q += n;
69537da2899SCharles.Forsyth return q;
69637da2899SCharles.Forsyth }
69737da2899SCharles.Forsyth
69837da2899SCharles.Forsyth static int
adjustfordel(int d0,int d1,int q)69937da2899SCharles.Forsyth adjustfordel(int d0, int d1, int q)
70037da2899SCharles.Forsyth {
70137da2899SCharles.Forsyth if (d1 <= q)
70237da2899SCharles.Forsyth q -= d1 - d0;
70337da2899SCharles.Forsyth else if (d0 <= q && q <= d1)
70437da2899SCharles.Forsyth q = d0;
70537da2899SCharles.Forsyth return q;
70637da2899SCharles.Forsyth }
70737da2899SCharles.Forsyth
70837da2899SCharles.Forsyth static char*
tkentryget(Tk * tk,char * arg,char ** val)70937da2899SCharles.Forsyth tkentryget(Tk *tk, char *arg, char **val)
71037da2899SCharles.Forsyth {
71137da2899SCharles.Forsyth TkTop *top;
71237da2899SCharles.Forsyth TkEntry *tke;
71337da2899SCharles.Forsyth int first, last;
71437da2899SCharles.Forsyth char *e, *buf;
71537da2899SCharles.Forsyth
71637da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
71737da2899SCharles.Forsyth if(tke->text == nil)
71837da2899SCharles.Forsyth return nil;
71937da2899SCharles.Forsyth
72037da2899SCharles.Forsyth arg = tkskip(arg, " \t");
72137da2899SCharles.Forsyth if(*arg == '\0')
72237da2899SCharles.Forsyth return tkvalue(val, "%.*S", tke->textlen, tke->text);
72337da2899SCharles.Forsyth
72437da2899SCharles.Forsyth top = tk->env->top;
72537da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
72637da2899SCharles.Forsyth if(buf == nil)
72737da2899SCharles.Forsyth return TkNomem;
72837da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+Tkmaxitem, nil);
72937da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &first);
73037da2899SCharles.Forsyth if(e != nil) {
73137da2899SCharles.Forsyth free(buf);
73237da2899SCharles.Forsyth return e;
73337da2899SCharles.Forsyth }
73437da2899SCharles.Forsyth last = first+1;
73537da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
73637da2899SCharles.Forsyth if(buf[0] != '\0') {
73737da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &last);
73837da2899SCharles.Forsyth if(e != nil) {
73937da2899SCharles.Forsyth free(buf);
74037da2899SCharles.Forsyth return e;
74137da2899SCharles.Forsyth }
74237da2899SCharles.Forsyth }
74337da2899SCharles.Forsyth free(buf);
74437da2899SCharles.Forsyth if(last <= first || tke->textlen == 0 || first == tke->textlen)
74537da2899SCharles.Forsyth return tkvalue(val, "%S", L"");
74637da2899SCharles.Forsyth return tkvalue(val, "%.*S", last-first, tke->text+first);
74737da2899SCharles.Forsyth }
74837da2899SCharles.Forsyth
74937da2899SCharles.Forsyth static char*
tkentryinsert(Tk * tk,char * arg,char ** val)75037da2899SCharles.Forsyth tkentryinsert(Tk *tk, char *arg, char **val)
75137da2899SCharles.Forsyth {
75237da2899SCharles.Forsyth TkTop *top;
75337da2899SCharles.Forsyth TkEntry *tke;
75437da2899SCharles.Forsyth int ins, i, n, locked;
75537da2899SCharles.Forsyth char *e, *t, *text, *buf;
75637da2899SCharles.Forsyth Rune *etext;
75737da2899SCharles.Forsyth
75837da2899SCharles.Forsyth USED(val);
75937da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
76037da2899SCharles.Forsyth
76137da2899SCharles.Forsyth top = tk->env->top;
76237da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
76337da2899SCharles.Forsyth if(buf == nil)
76437da2899SCharles.Forsyth return TkNomem;
76537da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+Tkmaxitem, nil);
76637da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &ins);
76737da2899SCharles.Forsyth free(buf);
76837da2899SCharles.Forsyth if(e != nil)
76937da2899SCharles.Forsyth return e;
77037da2899SCharles.Forsyth
77137da2899SCharles.Forsyth if(*arg == '\0')
77237da2899SCharles.Forsyth return nil;
77337da2899SCharles.Forsyth
77437da2899SCharles.Forsyth n = strlen(arg) + 1;
77537da2899SCharles.Forsyth if(n < Tkmaxitem)
77637da2899SCharles.Forsyth n = Tkmaxitem;
77737da2899SCharles.Forsyth text = malloc(n);
77837da2899SCharles.Forsyth if(text == nil)
77937da2899SCharles.Forsyth return TkNomem;
78037da2899SCharles.Forsyth
78137da2899SCharles.Forsyth tkword(top, arg, text, text+n, nil);
78237da2899SCharles.Forsyth n = utflen(text);
78337da2899SCharles.Forsyth etext = realloc(tke->text, (tke->textlen+n+1)*sizeof(Rune));
78437da2899SCharles.Forsyth if(etext == nil) {
78537da2899SCharles.Forsyth free(text);
78637da2899SCharles.Forsyth return TkNomem;
78737da2899SCharles.Forsyth }
78837da2899SCharles.Forsyth tke->text = etext;
78937da2899SCharles.Forsyth
79037da2899SCharles.Forsyth memmove(tke->text+ins+n, tke->text+ins, (tke->textlen-ins)*sizeof(Rune));
79137da2899SCharles.Forsyth t = text;
79237da2899SCharles.Forsyth for(i=0; i<n; i++)
79337da2899SCharles.Forsyth t += chartorune(tke->text+ins+i, t);
79437da2899SCharles.Forsyth free(text);
79537da2899SCharles.Forsyth
79637da2899SCharles.Forsyth tke->textlen += n;
79737da2899SCharles.Forsyth
79837da2899SCharles.Forsyth tke->sel0 = adjustforins(ins, n, tke->sel0);
79937da2899SCharles.Forsyth tke->sel1 = adjustforins(ins, n, tke->sel1);
80037da2899SCharles.Forsyth tke->icursor = adjustforins(ins, n, tke->icursor);
80137da2899SCharles.Forsyth tke->anchor = adjustforins(ins, n, tke->anchor);
80237da2899SCharles.Forsyth
80337da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
80437da2899SCharles.Forsyth if (ins < tke->v0)
80537da2899SCharles.Forsyth tke->x0 += entrytextwidth(tk, tke->v0 + n) + (tke->x0 - tke->xv0);
80637da2899SCharles.Forsyth if (locked)
80737da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
80837da2899SCharles.Forsyth recalcentry(tk);
80937da2899SCharles.Forsyth
81037da2899SCharles.Forsyth e = tkentrysh(tk);
81137da2899SCharles.Forsyth blinkreset(tk);
81237da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
81337da2899SCharles.Forsyth
81437da2899SCharles.Forsyth return e;
81537da2899SCharles.Forsyth }
81637da2899SCharles.Forsyth
81737da2899SCharles.Forsyth static char*
tkentrydelete(Tk * tk,char * arg,char ** val)81837da2899SCharles.Forsyth tkentrydelete(Tk *tk, char *arg, char **val)
81937da2899SCharles.Forsyth {
82037da2899SCharles.Forsyth TkTop *top;
82137da2899SCharles.Forsyth TkEntry *tke;
82237da2899SCharles.Forsyth int d0, d1, locked;
82337da2899SCharles.Forsyth char *e, *buf;
82437da2899SCharles.Forsyth Rune *text;
82537da2899SCharles.Forsyth
82637da2899SCharles.Forsyth USED(val);
82737da2899SCharles.Forsyth
82837da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
82937da2899SCharles.Forsyth
83037da2899SCharles.Forsyth top = tk->env->top;
83137da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
83237da2899SCharles.Forsyth if(buf == nil)
83337da2899SCharles.Forsyth return TkNomem;
83437da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+Tkmaxitem, nil);
83537da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &d0);
83637da2899SCharles.Forsyth if(e != nil) {
83737da2899SCharles.Forsyth free(buf);
83837da2899SCharles.Forsyth return e;
83937da2899SCharles.Forsyth }
84037da2899SCharles.Forsyth
84137da2899SCharles.Forsyth d1 = d0+1;
84237da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
84337da2899SCharles.Forsyth if(buf[0] != '\0') {
84437da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &d1);
84537da2899SCharles.Forsyth if(e != nil) {
84637da2899SCharles.Forsyth free(buf);
84737da2899SCharles.Forsyth return e;
84837da2899SCharles.Forsyth }
84937da2899SCharles.Forsyth }
85037da2899SCharles.Forsyth free(buf);
85137da2899SCharles.Forsyth if(d1 <= d0 || tke->textlen == 0 || d0 >= tke->textlen)
85237da2899SCharles.Forsyth return nil;
85337da2899SCharles.Forsyth
85437da2899SCharles.Forsyth memmove(tke->text+d0, tke->text+d1, (tke->textlen-d1)*sizeof(Rune));
85537da2899SCharles.Forsyth tke->textlen -= d1 - d0;
85637da2899SCharles.Forsyth
85737da2899SCharles.Forsyth text = realloc(tke->text, (tke->textlen+1) * sizeof(Rune));
85837da2899SCharles.Forsyth if (text != nil)
85937da2899SCharles.Forsyth tke->text = text;
86037da2899SCharles.Forsyth tke->sel0 = adjustfordel(d0, d1, tke->sel0);
86137da2899SCharles.Forsyth tke->sel1 = adjustfordel(d0, d1, tke->sel1);
86237da2899SCharles.Forsyth tke->icursor = adjustfordel(d0, d1, tke->icursor);
86337da2899SCharles.Forsyth tke->anchor = adjustfordel(d0, d1, tke->anchor);
86437da2899SCharles.Forsyth
86537da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
86637da2899SCharles.Forsyth if (d1 < tke->v0)
86737da2899SCharles.Forsyth tke->x0 = entrytextwidth(tk, tke->v0 - (d1 - d0)) + (tke->x0 - tke->xv0);
86837da2899SCharles.Forsyth else if (d0 < tke->v0)
86937da2899SCharles.Forsyth tke->x0 = entrytextwidth(tk, d0);
87037da2899SCharles.Forsyth if (locked)
87137da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
87237da2899SCharles.Forsyth recalcentry(tk);
87337da2899SCharles.Forsyth
87437da2899SCharles.Forsyth e = tkentrysh(tk);
87537da2899SCharles.Forsyth blinkreset(tk);
87637da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
87737da2899SCharles.Forsyth
87837da2899SCharles.Forsyth return e;
87937da2899SCharles.Forsyth }
88037da2899SCharles.Forsyth
88137da2899SCharles.Forsyth /* Used for both backspace and DEL. If a selection exists, delete it.
88237da2899SCharles.Forsyth * Otherwise delete the character to the left(right) of the insertion
88337da2899SCharles.Forsyth * cursor, if any.
88437da2899SCharles.Forsyth */
88537da2899SCharles.Forsyth static char*
tkentrybs(Tk * tk,char * arg,char ** val)88637da2899SCharles.Forsyth tkentrybs(Tk *tk, char *arg, char **val)
88737da2899SCharles.Forsyth {
88837da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
88937da2899SCharles.Forsyth char *buf, *e;
89037da2899SCharles.Forsyth int ix;
89137da2899SCharles.Forsyth
89237da2899SCharles.Forsyth USED(val);
89337da2899SCharles.Forsyth USED(arg);
89437da2899SCharles.Forsyth
89537da2899SCharles.Forsyth if(tke->textlen == 0)
89637da2899SCharles.Forsyth return nil;
89737da2899SCharles.Forsyth
89837da2899SCharles.Forsyth if(tke->sel0 < tke->sel1)
89937da2899SCharles.Forsyth return tkentrydelete(tk, "sel.first sel.last", nil);
90037da2899SCharles.Forsyth
90137da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
90237da2899SCharles.Forsyth if(buf == nil)
90337da2899SCharles.Forsyth return TkNomem;
90437da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
90537da2899SCharles.Forsyth ix = -1;
90637da2899SCharles.Forsyth if(buf[0] != '\0') {
90737da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &ix);
90837da2899SCharles.Forsyth if(e != nil) {
90937da2899SCharles.Forsyth free(buf);
91037da2899SCharles.Forsyth return e;
91137da2899SCharles.Forsyth }
91237da2899SCharles.Forsyth }
91337da2899SCharles.Forsyth if(ix > -1) { /* DEL */
91437da2899SCharles.Forsyth if(tke->icursor >= tke->textlen) {
91537da2899SCharles.Forsyth free(buf);
91637da2899SCharles.Forsyth return nil;
91737da2899SCharles.Forsyth }
91837da2899SCharles.Forsyth }
91937da2899SCharles.Forsyth else { /* backspace */
92037da2899SCharles.Forsyth if(tke->icursor == 0) {
92137da2899SCharles.Forsyth free(buf);
92237da2899SCharles.Forsyth return nil;
92337da2899SCharles.Forsyth }
92437da2899SCharles.Forsyth tke->icursor--;
92537da2899SCharles.Forsyth }
92637da2899SCharles.Forsyth snprint(buf, Tkmaxitem, "%d", tke->icursor);
92737da2899SCharles.Forsyth e = tkentrydelete(tk, buf, nil);
92837da2899SCharles.Forsyth free(buf);
92937da2899SCharles.Forsyth return e;
93037da2899SCharles.Forsyth }
93137da2899SCharles.Forsyth
93237da2899SCharles.Forsyth static char*
tkentrybw(Tk * tk,char * arg,char ** val)93337da2899SCharles.Forsyth tkentrybw(Tk *tk, char *arg, char **val)
93437da2899SCharles.Forsyth {
93537da2899SCharles.Forsyth int start;
93637da2899SCharles.Forsyth Rune *text;
93737da2899SCharles.Forsyth TkEntry *tke;
93837da2899SCharles.Forsyth char buf[32];
93937da2899SCharles.Forsyth
94037da2899SCharles.Forsyth USED(val);
94137da2899SCharles.Forsyth USED(arg);
94237da2899SCharles.Forsyth
94337da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
94437da2899SCharles.Forsyth if(tke->textlen == 0 || tke->icursor == 0)
94537da2899SCharles.Forsyth return nil;
94637da2899SCharles.Forsyth
94737da2899SCharles.Forsyth text = tke->text;
94837da2899SCharles.Forsyth start = tke->icursor-1;
94937da2899SCharles.Forsyth while(start > 0 && !tkiswordchar(text[start]))
95037da2899SCharles.Forsyth --start;
95137da2899SCharles.Forsyth while(start > 0 && tkiswordchar(text[start-1]))
95237da2899SCharles.Forsyth --start;
95337da2899SCharles.Forsyth
95437da2899SCharles.Forsyth snprint(buf, sizeof(buf), "%d %d", start, tke->icursor);
95537da2899SCharles.Forsyth return tkentrydelete(tk, buf, nil);
95637da2899SCharles.Forsyth }
95737da2899SCharles.Forsyth
95837da2899SCharles.Forsyth char*
tkentryselect(Tk * tk,char * arg,char ** val)95937da2899SCharles.Forsyth tkentryselect(Tk *tk, char *arg, char **val)
96037da2899SCharles.Forsyth {
96137da2899SCharles.Forsyth TkTop *top;
96237da2899SCharles.Forsyth int start, from, to, locked;
96337da2899SCharles.Forsyth TkEntry *tke;
96437da2899SCharles.Forsyth char *e, *buf;
96537da2899SCharles.Forsyth
96637da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
96737da2899SCharles.Forsyth if(buf == nil)
96837da2899SCharles.Forsyth return TkNomem;
96937da2899SCharles.Forsyth
97037da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
97137da2899SCharles.Forsyth
97237da2899SCharles.Forsyth top = tk->env->top;
97337da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+Tkmaxitem, nil);
97437da2899SCharles.Forsyth if(strcmp(buf, "clear") == 0) {
97537da2899SCharles.Forsyth tke->sel0 = 0;
97637da2899SCharles.Forsyth tke->sel1 = 0;
97737da2899SCharles.Forsyth }
97837da2899SCharles.Forsyth else
97937da2899SCharles.Forsyth if(strcmp(buf, "from") == 0) {
98037da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
98137da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &tke->anchor);
98237da2899SCharles.Forsyth tke->flag &= ~Ewordsel;
98337da2899SCharles.Forsyth free(buf);
98437da2899SCharles.Forsyth return e;
98537da2899SCharles.Forsyth }
98637da2899SCharles.Forsyth else
98737da2899SCharles.Forsyth if(strcmp(buf, "to") == 0) {
98837da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
98937da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &to);
99037da2899SCharles.Forsyth if(e != nil) {
99137da2899SCharles.Forsyth free(buf);
99237da2899SCharles.Forsyth return e;
99337da2899SCharles.Forsyth }
99437da2899SCharles.Forsyth
99537da2899SCharles.Forsyth if(to < tke->anchor) {
99637da2899SCharles.Forsyth if(tke->flag & Ewordsel)
99737da2899SCharles.Forsyth while(to > 0 && tkiswordchar(tke->text[to-1]))
99837da2899SCharles.Forsyth --to;
99937da2899SCharles.Forsyth tke->sel0 = to;
100037da2899SCharles.Forsyth tke->sel1 = tke->anchor;
100137da2899SCharles.Forsyth }
100237da2899SCharles.Forsyth else
100337da2899SCharles.Forsyth if(to >= tke->anchor) {
100437da2899SCharles.Forsyth if(tke->flag & Ewordsel)
100537da2899SCharles.Forsyth while(to < tke->textlen &&
100637da2899SCharles.Forsyth tkiswordchar(tke->text[to]))
100737da2899SCharles.Forsyth to++;
100837da2899SCharles.Forsyth tke->sel0 = tke->anchor;
100937da2899SCharles.Forsyth tke->sel1 = to;
101037da2899SCharles.Forsyth }
101137da2899SCharles.Forsyth tkentrysee(tk, to, 0);
101237da2899SCharles.Forsyth recalcentry(tk);
101337da2899SCharles.Forsyth }
101437da2899SCharles.Forsyth else
101537da2899SCharles.Forsyth if(strcmp(buf, "word") == 0) { /* inferno invention */
101637da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
101737da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &start);
101837da2899SCharles.Forsyth if(e != nil) {
101937da2899SCharles.Forsyth free(buf);
102037da2899SCharles.Forsyth return e;
102137da2899SCharles.Forsyth }
102237da2899SCharles.Forsyth from = start;
102337da2899SCharles.Forsyth while(from > 0 && tkiswordchar(tke->text[from-1]))
102437da2899SCharles.Forsyth --from;
102537da2899SCharles.Forsyth to = start;
102637da2899SCharles.Forsyth while(to < tke->textlen && tkiswordchar(tke->text[to]))
102737da2899SCharles.Forsyth to++;
102837da2899SCharles.Forsyth tke->sel0 = from;
102937da2899SCharles.Forsyth tke->sel1 = to;
103037da2899SCharles.Forsyth tke->anchor = from;
103137da2899SCharles.Forsyth tke->icursor = from;
103237da2899SCharles.Forsyth tke->flag |= Ewordsel;
103337da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
103437da2899SCharles.Forsyth tke->xicursor = entrytextwidth(tk, tke->icursor);
103537da2899SCharles.Forsyth if (locked)
103637da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
103737da2899SCharles.Forsyth }
103837da2899SCharles.Forsyth else
103937da2899SCharles.Forsyth if(strcmp(buf, "present") == 0) {
104037da2899SCharles.Forsyth e = tkvalue(val, "%d", tke->sel1 > tke->sel0);
104137da2899SCharles.Forsyth free(buf);
104237da2899SCharles.Forsyth return e;
104337da2899SCharles.Forsyth }
104437da2899SCharles.Forsyth else
104537da2899SCharles.Forsyth if(strcmp(buf, "range") == 0) {
104637da2899SCharles.Forsyth arg = tkword(top, arg, buf, buf+Tkmaxitem, nil);
104737da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &from);
104837da2899SCharles.Forsyth if(e != nil) {
104937da2899SCharles.Forsyth free(buf);
105037da2899SCharles.Forsyth return e;
105137da2899SCharles.Forsyth }
105237da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
105337da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &to);
105437da2899SCharles.Forsyth if(e != nil) {
105537da2899SCharles.Forsyth free(buf);
105637da2899SCharles.Forsyth return e;
105737da2899SCharles.Forsyth }
105837da2899SCharles.Forsyth tke->sel0 = from;
105937da2899SCharles.Forsyth tke->sel1 = to;
106037da2899SCharles.Forsyth if(to <= from) {
106137da2899SCharles.Forsyth tke->sel0 = 0;
106237da2899SCharles.Forsyth tke->sel1 = 0;
106337da2899SCharles.Forsyth }
106437da2899SCharles.Forsyth }
106537da2899SCharles.Forsyth else
106637da2899SCharles.Forsyth if(strcmp(buf, "adjust") == 0) {
106737da2899SCharles.Forsyth tkword(top, arg, buf, buf+Tkmaxitem, nil);
106837da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &to);
106937da2899SCharles.Forsyth if(e != nil) {
107037da2899SCharles.Forsyth free(buf);
107137da2899SCharles.Forsyth return e;
107237da2899SCharles.Forsyth }
107337da2899SCharles.Forsyth if(tke->sel0 == 0 && tke->sel1 == 0) {
107437da2899SCharles.Forsyth tke->sel0 = tke->anchor;
107537da2899SCharles.Forsyth tke->sel1 = to;
107637da2899SCharles.Forsyth }
107737da2899SCharles.Forsyth else {
107837da2899SCharles.Forsyth if(abs(tke->sel0-to) < abs(tke->sel1-to)) {
107937da2899SCharles.Forsyth tke->sel0 = to;
108037da2899SCharles.Forsyth tke->anchor = tke->sel1;
108137da2899SCharles.Forsyth }
108237da2899SCharles.Forsyth else {
108337da2899SCharles.Forsyth tke->sel1 = to;
108437da2899SCharles.Forsyth tke->anchor = tke->sel0;
108537da2899SCharles.Forsyth }
108637da2899SCharles.Forsyth }
108737da2899SCharles.Forsyth if(tke->sel0 > tke->sel1) {
108837da2899SCharles.Forsyth to = tke->sel0;
108937da2899SCharles.Forsyth tke->sel0 = tke->sel1;
109037da2899SCharles.Forsyth tke->sel1 = to;
109137da2899SCharles.Forsyth }
109237da2899SCharles.Forsyth }
109337da2899SCharles.Forsyth else {
109437da2899SCharles.Forsyth free(buf);
109537da2899SCharles.Forsyth return TkBadcm;
109637da2899SCharles.Forsyth }
109737da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
109837da2899SCharles.Forsyth tke->xsel0 = entrytextwidth(tk, tke->sel0);
109937da2899SCharles.Forsyth tke->xsel1 = entrytextwidth(tk, tke->sel1);
110037da2899SCharles.Forsyth if (locked)
110137da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
110237da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
110337da2899SCharles.Forsyth free(buf);
110437da2899SCharles.Forsyth return nil;
110537da2899SCharles.Forsyth }
110637da2899SCharles.Forsyth
110737da2899SCharles.Forsyth
110837da2899SCharles.Forsyth static char*
tkentryb2p(Tk * tk,char * arg,char ** val)110937da2899SCharles.Forsyth tkentryb2p(Tk *tk, char *arg, char **val)
111037da2899SCharles.Forsyth {
111137da2899SCharles.Forsyth TkEntry *tke;
111237da2899SCharles.Forsyth char *buf;
111337da2899SCharles.Forsyth
111437da2899SCharles.Forsyth USED(val);
111537da2899SCharles.Forsyth
111637da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
111737da2899SCharles.Forsyth buf = malloc(Tkmaxitem);
111837da2899SCharles.Forsyth if (buf == nil)
111937da2899SCharles.Forsyth return TkNomem;
112037da2899SCharles.Forsyth
112137da2899SCharles.Forsyth tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil);
112237da2899SCharles.Forsyth tke->oldx = atoi(buf);
112337da2899SCharles.Forsyth return nil;
112437da2899SCharles.Forsyth }
112537da2899SCharles.Forsyth
112637da2899SCharles.Forsyth static char*
tkentryxview(Tk * tk,char * arg,char ** val)112737da2899SCharles.Forsyth tkentryxview(Tk *tk, char *arg, char **val)
112837da2899SCharles.Forsyth {
112937da2899SCharles.Forsyth int locked;
113037da2899SCharles.Forsyth TkEnv *env;
113137da2899SCharles.Forsyth TkEntry *tke;
113237da2899SCharles.Forsyth char *buf, *v;
113337da2899SCharles.Forsyth int dx, top, bot, amount, ix, x;
113437da2899SCharles.Forsyth char *e;
113537da2899SCharles.Forsyth
113637da2899SCharles.Forsyth tke = TKobj(TkEntry, tk);
113737da2899SCharles.Forsyth env = tk->env;
113837da2899SCharles.Forsyth dx = tk->act.width - 2*xinset(tk);
113937da2899SCharles.Forsyth
114037da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
114137da2899SCharles.Forsyth if(buf == nil)
114237da2899SCharles.Forsyth return TkNomem;
114337da2899SCharles.Forsyth
114437da2899SCharles.Forsyth if(*arg == '\0') {
114537da2899SCharles.Forsyth if (tke->textlen == 0 || tke->xlen < dx) {
114637da2899SCharles.Forsyth bot = TKI2F(0);
114737da2899SCharles.Forsyth top = TKI2F(1);
114837da2899SCharles.Forsyth } else {
114937da2899SCharles.Forsyth bot = TKI2F(tke->x0) / tke->xlen;
115037da2899SCharles.Forsyth top = TKI2F(tke->x0 + dx) / tke->xlen;
115137da2899SCharles.Forsyth }
115237da2899SCharles.Forsyth v = tkfprint(buf, bot);
115337da2899SCharles.Forsyth *v++ = ' ';
115437da2899SCharles.Forsyth tkfprint(v, top);
115537da2899SCharles.Forsyth e = tkvalue(val, "%s", buf);
115637da2899SCharles.Forsyth free(buf);
115737da2899SCharles.Forsyth return e;
115837da2899SCharles.Forsyth }
115937da2899SCharles.Forsyth
116037da2899SCharles.Forsyth arg = tkitem(buf, arg);
116137da2899SCharles.Forsyth if(strcmp(buf, "moveto") == 0) {
116237da2899SCharles.Forsyth e = tkfracword(env->top, &arg, &top, nil);
116337da2899SCharles.Forsyth if (e != nil) {
116437da2899SCharles.Forsyth free(buf);
116537da2899SCharles.Forsyth return e;
116637da2899SCharles.Forsyth }
116737da2899SCharles.Forsyth tke->x0 = TKF2I(top*tke->xlen);
116837da2899SCharles.Forsyth }
116937da2899SCharles.Forsyth else
117037da2899SCharles.Forsyth if(strcmp(buf, "scroll") == 0) {
117137da2899SCharles.Forsyth arg = tkitem(buf, arg);
117237da2899SCharles.Forsyth amount = atoi(buf);
117337da2899SCharles.Forsyth if(*arg == 'p') /* Pages */
117437da2899SCharles.Forsyth amount *= (9*tke->xlen)/10;
117537da2899SCharles.Forsyth else
117637da2899SCharles.Forsyth if(*arg == 's') { /* Inferno-ism, "scr", must be used in the context of button2p */
117737da2899SCharles.Forsyth x = amount;
117837da2899SCharles.Forsyth amount = x < tke->oldx ? env->wzero : (x > tke->oldx ? -env->wzero : 0);
117937da2899SCharles.Forsyth tke->oldx = x;
118037da2899SCharles.Forsyth }
118137da2899SCharles.Forsyth tke->x0 += amount;
118237da2899SCharles.Forsyth }
118337da2899SCharles.Forsyth else {
118437da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &ix);
118537da2899SCharles.Forsyth if(e != nil) {
118637da2899SCharles.Forsyth free(buf);
118737da2899SCharles.Forsyth return e;
118837da2899SCharles.Forsyth }
118937da2899SCharles.Forsyth locked = lockdisplay(env->top->display);
119037da2899SCharles.Forsyth tke->x0 = entrytextwidth(tk, ix);
119137da2899SCharles.Forsyth if (locked)
119237da2899SCharles.Forsyth unlockdisplay(env->top->display);
119337da2899SCharles.Forsyth }
119437da2899SCharles.Forsyth free(buf);
119537da2899SCharles.Forsyth
119637da2899SCharles.Forsyth if (tke->x0 > tke->xlen - dx)
119737da2899SCharles.Forsyth tke->x0 = tke->xlen - dx;
119837da2899SCharles.Forsyth if (tke->x0 < 0)
119937da2899SCharles.Forsyth tke->x0 = 0;
120037da2899SCharles.Forsyth recalcentry(tk);
120137da2899SCharles.Forsyth e = tkentrysh(tk);
120237da2899SCharles.Forsyth blinkreset(tk);
120337da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
120437da2899SCharles.Forsyth return e;
120537da2899SCharles.Forsyth }
120637da2899SCharles.Forsyth
120737da2899SCharles.Forsyth static void
autoselect(Tk * tk,void * v,int cancelled)120837da2899SCharles.Forsyth autoselect(Tk *tk, void *v, int cancelled)
120937da2899SCharles.Forsyth {
121037da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
121137da2899SCharles.Forsyth Rectangle hitr;
121237da2899SCharles.Forsyth char buf[32];
121337da2899SCharles.Forsyth Point p;
121437da2899SCharles.Forsyth
121537da2899SCharles.Forsyth USED(v);
121637da2899SCharles.Forsyth
121737da2899SCharles.Forsyth if (cancelled)
121837da2899SCharles.Forsyth return;
121937da2899SCharles.Forsyth
122037da2899SCharles.Forsyth p = tkscrn2local(tk, Pt(tke->oldx, 0));
122137da2899SCharles.Forsyth p.y = 0;
122237da2899SCharles.Forsyth if (tkvisiblerect(tk, &hitr) && ptinrect(p, hitr))
122337da2899SCharles.Forsyth return;
122437da2899SCharles.Forsyth
122537da2899SCharles.Forsyth snprint(buf, sizeof(buf), "to @%d", p.x);
122637da2899SCharles.Forsyth tkentryselect(tk, buf, nil);
122737da2899SCharles.Forsyth tkdirty(tk);
122837da2899SCharles.Forsyth tkupdate(tk->env->top);
122937da2899SCharles.Forsyth }
123037da2899SCharles.Forsyth
123137da2899SCharles.Forsyth static char*
tkentryb1p(Tk * tk,char * arg,char ** ret)123237da2899SCharles.Forsyth tkentryb1p(Tk *tk, char* arg, char **ret)
123337da2899SCharles.Forsyth {
123437da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
123537da2899SCharles.Forsyth Point p;
123637da2899SCharles.Forsyth int i, locked, x;
123737da2899SCharles.Forsyth char buf[32], *e;
123837da2899SCharles.Forsyth USED(ret);
123937da2899SCharles.Forsyth
124037da2899SCharles.Forsyth x = atoi(arg);
124137da2899SCharles.Forsyth p = tkscrn2local(tk, Pt(x, 0));
124237da2899SCharles.Forsyth sprint(buf, "@%d", p.x);
124337da2899SCharles.Forsyth e = tkentryparseindex(tk, buf, &i);
124437da2899SCharles.Forsyth if (e != nil)
124537da2899SCharles.Forsyth return e;
124637da2899SCharles.Forsyth tke->sel0 = 0;
124737da2899SCharles.Forsyth tke->sel1 = 0;
124837da2899SCharles.Forsyth tke->icursor = i;
124937da2899SCharles.Forsyth tke->anchor = i;
125037da2899SCharles.Forsyth tke->flag &= ~Ewordsel;
125137da2899SCharles.Forsyth
125237da2899SCharles.Forsyth locked = lockdisplay(tk->env->top->display);
125337da2899SCharles.Forsyth tke->xsel0 = 0;
125437da2899SCharles.Forsyth tke->xsel1 = 0;
125537da2899SCharles.Forsyth tke->xicursor = entrytextwidth(tk, tke->icursor);
125637da2899SCharles.Forsyth if (locked)
125737da2899SCharles.Forsyth unlockdisplay(tk->env->top->display);
125837da2899SCharles.Forsyth
125937da2899SCharles.Forsyth tke->oldx = x;
126037da2899SCharles.Forsyth blinkreset(tk);
126137da2899SCharles.Forsyth tkrepeat(tk, autoselect, nil, TkRptpause, TkRptinterval);
126237da2899SCharles.Forsyth tk->dirty = tkrect(tk, 0);
126337da2899SCharles.Forsyth return nil;
126437da2899SCharles.Forsyth }
126537da2899SCharles.Forsyth
126637da2899SCharles.Forsyth static char*
tkentryb1m(Tk * tk,char * arg,char ** ret)126737da2899SCharles.Forsyth tkentryb1m(Tk *tk, char* arg, char **ret)
126837da2899SCharles.Forsyth {
126937da2899SCharles.Forsyth TkEntry *tke = TKobj(TkEntry, tk);
127037da2899SCharles.Forsyth Point p;
127137da2899SCharles.Forsyth Rectangle hitr;
127237da2899SCharles.Forsyth char buf[32];
127337da2899SCharles.Forsyth USED(ret);
127437da2899SCharles.Forsyth
127537da2899SCharles.Forsyth p.x = atoi(arg);
127637da2899SCharles.Forsyth tke->oldx = p.x;
127737da2899SCharles.Forsyth p = tkscrn2local(tk, p);
127837da2899SCharles.Forsyth p.y = 0;
127937da2899SCharles.Forsyth if (!tkvisiblerect(tk, &hitr) || !ptinrect(p, hitr))
128037da2899SCharles.Forsyth return nil;
128137da2899SCharles.Forsyth snprint(buf, sizeof(buf), "to @%d", p.x);
128237da2899SCharles.Forsyth tkentryselect(tk, buf, nil);
128337da2899SCharles.Forsyth return nil;
128437da2899SCharles.Forsyth }
128537da2899SCharles.Forsyth
128637da2899SCharles.Forsyth static char*
tkentryb1r(Tk * tk,char * arg,char ** ret)128737da2899SCharles.Forsyth tkentryb1r(Tk *tk, char* arg, char **ret)
128837da2899SCharles.Forsyth {
128937da2899SCharles.Forsyth USED(tk);
129037da2899SCharles.Forsyth USED(arg);
129137da2899SCharles.Forsyth USED(ret);
129237da2899SCharles.Forsyth tkcancelrepeat(tk);
129337da2899SCharles.Forsyth return nil;
129437da2899SCharles.Forsyth }
129537da2899SCharles.Forsyth
129637da2899SCharles.Forsyth static void
blinkreset(Tk * tk)129737da2899SCharles.Forsyth blinkreset(Tk *tk)
129837da2899SCharles.Forsyth {
129937da2899SCharles.Forsyth TkEntry *e = TKobj(TkEntry, tk);
130037da2899SCharles.Forsyth if (!tkhaskeyfocus(tk) || tk->flag&Tkdisabled)
130137da2899SCharles.Forsyth return;
130237da2899SCharles.Forsyth e->flag |= Ecursoron;
130337da2899SCharles.Forsyth tkblinkreset(tk);
130437da2899SCharles.Forsyth }
130537da2899SCharles.Forsyth
130637da2899SCharles.Forsyth static void
showcaret(Tk * tk,int on)130737da2899SCharles.Forsyth showcaret(Tk *tk, int on)
130837da2899SCharles.Forsyth {
130937da2899SCharles.Forsyth TkEntry *e = TKobj(TkEntry, tk);
131037da2899SCharles.Forsyth
131137da2899SCharles.Forsyth if (on)
131237da2899SCharles.Forsyth e->flag |= Ecursoron;
131337da2899SCharles.Forsyth else
131437da2899SCharles.Forsyth e->flag &= ~Ecursoron;
131537da2899SCharles.Forsyth tk->dirty = tkrect(tk, 0);
131637da2899SCharles.Forsyth }
131737da2899SCharles.Forsyth
131837da2899SCharles.Forsyth char*
tkentryfocus(Tk * tk,char * arg,char ** ret)131937da2899SCharles.Forsyth tkentryfocus(Tk *tk, char* arg, char **ret)
132037da2899SCharles.Forsyth {
132137da2899SCharles.Forsyth int on = 0;
132237da2899SCharles.Forsyth USED(ret);
132337da2899SCharles.Forsyth
132437da2899SCharles.Forsyth if (tk->flag&Tkdisabled)
132537da2899SCharles.Forsyth return nil;
132637da2899SCharles.Forsyth
132737da2899SCharles.Forsyth if(strcmp(arg, " in") == 0) {
132837da2899SCharles.Forsyth tkblink(tk, showcaret);
132937da2899SCharles.Forsyth on = 1;
133037da2899SCharles.Forsyth }
133137da2899SCharles.Forsyth else
133237da2899SCharles.Forsyth tkblink(nil, nil);
133337da2899SCharles.Forsyth
133437da2899SCharles.Forsyth showcaret(tk, on);
133537da2899SCharles.Forsyth return nil;
133637da2899SCharles.Forsyth }
133737da2899SCharles.Forsyth
133837da2899SCharles.Forsyth static
133937da2899SCharles.Forsyth TkCmdtab tkentrycmd[] =
134037da2899SCharles.Forsyth {
134137da2899SCharles.Forsyth "cget", tkentrycget,
134237da2899SCharles.Forsyth "configure", tkentryconf,
134337da2899SCharles.Forsyth "delete", tkentrydelete,
134437da2899SCharles.Forsyth "get", tkentryget,
134537da2899SCharles.Forsyth "icursor", tkentryicursor,
134637da2899SCharles.Forsyth "index", tkentryindex,
134737da2899SCharles.Forsyth "insert", tkentryinsert,
134837da2899SCharles.Forsyth "selection", tkentryselect,
134937da2899SCharles.Forsyth "xview", tkentryxview,
135037da2899SCharles.Forsyth "tkEntryBS", tkentrybs,
135137da2899SCharles.Forsyth "tkEntryBW", tkentrybw,
135237da2899SCharles.Forsyth "tkEntryB1P", tkentryb1p,
135337da2899SCharles.Forsyth "tkEntryB1M", tkentryb1m,
135437da2899SCharles.Forsyth "tkEntryB1R", tkentryb1r,
135537da2899SCharles.Forsyth "tkEntryB2P", tkentryb2p,
135637da2899SCharles.Forsyth "tkEntryFocus", tkentryfocus,
135737da2899SCharles.Forsyth "bbox", tkentrybboxcmd,
135837da2899SCharles.Forsyth "see", tkentryseecmd,
135937da2899SCharles.Forsyth nil
136037da2899SCharles.Forsyth };
136137da2899SCharles.Forsyth
136237da2899SCharles.Forsyth TkMethod entrymethod = {
136337da2899SCharles.Forsyth "entry",
136437da2899SCharles.Forsyth tkentrycmd,
136537da2899SCharles.Forsyth tkfreeentry,
136637da2899SCharles.Forsyth tkdrawentry,
136737da2899SCharles.Forsyth tkentrygeom
136837da2899SCharles.Forsyth };
1369