137da2899SCharles.Forsyth #include <lib9.h>
237da2899SCharles.Forsyth #include <kernel.h>
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth #include "keyboard.h"
637da2899SCharles.Forsyth
737da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth typedef struct TkScale TkScale;
1037da2899SCharles.Forsyth struct TkScale
1137da2899SCharles.Forsyth {
1237da2899SCharles.Forsyth int value;
1337da2899SCharles.Forsyth int bigi;
1437da2899SCharles.Forsyth int digits;
1537da2899SCharles.Forsyth int digwidth;
1637da2899SCharles.Forsyth int from; /* Base of range */
1737da2899SCharles.Forsyth int to; /* Limit of range */
1837da2899SCharles.Forsyth int len; /* Length of groove */
1937da2899SCharles.Forsyth int res; /* Resolution */
2037da2899SCharles.Forsyth int sv; /* Show value */
2137da2899SCharles.Forsyth int sl; /* Slider length */
2237da2899SCharles.Forsyth int sw; /* Slider width div 2 */
2337da2899SCharles.Forsyth int relief;
2437da2899SCharles.Forsyth int tick;
2537da2899SCharles.Forsyth int orient;
2637da2899SCharles.Forsyth char* command;
2737da2899SCharles.Forsyth char* label;
2837da2899SCharles.Forsyth int pixmin;
2937da2899SCharles.Forsyth int pixmax;
3037da2899SCharles.Forsyth int pixpos;
3137da2899SCharles.Forsyth int center;
3237da2899SCharles.Forsyth int pix;
3337da2899SCharles.Forsyth int base;
3437da2899SCharles.Forsyth int flag;
3537da2899SCharles.Forsyth int jump;
3637da2899SCharles.Forsyth };
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth enum {
3937da2899SCharles.Forsyth Dragging = (1<<0),
4037da2899SCharles.Forsyth Autorepeat = (1<<1),
4137da2899SCharles.Forsyth };
4237da2899SCharles.Forsyth
4337da2899SCharles.Forsyth static
4437da2899SCharles.Forsyth TkOption opts[] =
4537da2899SCharles.Forsyth {
4637da2899SCharles.Forsyth "bigincrement", OPTnnfrac, O(TkScale, bigi), nil,
4737da2899SCharles.Forsyth "digits", OPTdist, O(TkScale, digits), nil,
4837da2899SCharles.Forsyth "from", OPTfrac, O(TkScale, from), nil,
4937da2899SCharles.Forsyth "to", OPTfrac, O(TkScale, to), nil,
5037da2899SCharles.Forsyth "length", OPTdist, O(TkScale, len), nil,
5137da2899SCharles.Forsyth "resolution", OPTnnfrac, O(TkScale, res), nil,
5237da2899SCharles.Forsyth "showrange", OPTignore, 0, nil,
5337da2899SCharles.Forsyth "showvalue", OPTstab, O(TkScale, sv), tkbool,
5437da2899SCharles.Forsyth "jump", OPTstab, O(TkScale, jump), tkbool,
5537da2899SCharles.Forsyth "sliderlength", OPTdist, O(TkScale, sl), nil,
5637da2899SCharles.Forsyth "sliderrelief", OPTstab, O(TkScale, relief), tkrelief,
5737da2899SCharles.Forsyth "tickinterval", OPTfrac, O(TkScale, tick), nil,
5837da2899SCharles.Forsyth "tick", OPTfrac, O(TkScale, tick), nil,
5937da2899SCharles.Forsyth "label", OPTtext, O(TkScale, label), nil,
6037da2899SCharles.Forsyth "command", OPTtext, O(TkScale, command), nil,
6137da2899SCharles.Forsyth "orient", OPTstab, O(TkScale, orient), tkorient,
6237da2899SCharles.Forsyth nil
6337da2899SCharles.Forsyth };
6437da2899SCharles.Forsyth
6537da2899SCharles.Forsyth static char trough1[] = "trough1";
6637da2899SCharles.Forsyth static char trough2[] = "trough2";
6737da2899SCharles.Forsyth static char slider[] = "slider";
6837da2899SCharles.Forsyth
6937da2899SCharles.Forsyth static
7037da2899SCharles.Forsyth TkEbind b[] =
7137da2899SCharles.Forsyth {
7237da2899SCharles.Forsyth {TkMotion, "%W tkScaleMotion %x %y"},
7337da2899SCharles.Forsyth {TkButton1P|TkMotion, "%W tkScaleDrag %x %y"},
7437da2899SCharles.Forsyth {TkButton1P, "%W tkScaleMotion %x %y; %W tkScaleBut1P %x %y"},
7537da2899SCharles.Forsyth {TkButton1P|TkDouble, "%W tkScaleMotion %x %y; %W tkScaleBut1P %x %y"},
7637da2899SCharles.Forsyth {TkButton1R, "%W tkScaleDrag %x %y; %W tkScaleBut1R; %W tkScaleMotion %x %y"},
7737da2899SCharles.Forsyth {TkKey, "%W tkScaleKey 0x%K"},
7837da2899SCharles.Forsyth };
7937da2899SCharles.Forsyth
8037da2899SCharles.Forsyth enum
8137da2899SCharles.Forsyth {
8237da2899SCharles.Forsyth Scalewidth = 18,
8337da2899SCharles.Forsyth ScalePad = 2,
84c9ccdbd5Sforsyth ScaleBW = 1,
8537da2899SCharles.Forsyth ScaleSlider = 16,
8637da2899SCharles.Forsyth ScaleLen = 80,
8737da2899SCharles.Forsyth
8837da2899SCharles.Forsyth };
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsyth static int
maximum(int a,int b)9137da2899SCharles.Forsyth maximum(int a, int b)
9237da2899SCharles.Forsyth {
9337da2899SCharles.Forsyth if (a > b)
9437da2899SCharles.Forsyth return a;
9537da2899SCharles.Forsyth return b;
9637da2899SCharles.Forsyth }
9737da2899SCharles.Forsyth
9837da2899SCharles.Forsyth void
tksizescale(Tk * tk)9937da2899SCharles.Forsyth tksizescale(Tk *tk)
10037da2899SCharles.Forsyth {
10137da2899SCharles.Forsyth Point p;
10237da2899SCharles.Forsyth char buf[32];
10337da2899SCharles.Forsyth TkScale *tks;
10437da2899SCharles.Forsyth int fh, w, h, digits, digits2;
10537da2899SCharles.Forsyth
10637da2899SCharles.Forsyth tks = TKobj(TkScale, tk);
10737da2899SCharles.Forsyth
10837da2899SCharles.Forsyth digits = tks->digits;
10937da2899SCharles.Forsyth if(digits <= 0) {
11037da2899SCharles.Forsyth digits = tkfprint(buf, tks->from) - buf;
11137da2899SCharles.Forsyth digits2 = tkfprint(buf, tks->to) - buf;
11237da2899SCharles.Forsyth digits = maximum(digits, digits2);
11337da2899SCharles.Forsyth if (tks->res > 0) {
11437da2899SCharles.Forsyth digits2 = tkfprint(buf, tks->from + tks->res) - buf;
11537da2899SCharles.Forsyth digits = maximum(digits, digits2);
11637da2899SCharles.Forsyth digits2 = tkfprint(buf, tks->to - tks->res) - buf;
11737da2899SCharles.Forsyth digits = maximum(digits, digits2);
11837da2899SCharles.Forsyth }
11937da2899SCharles.Forsyth }
12037da2899SCharles.Forsyth
12137da2899SCharles.Forsyth digits *= tk->env->wzero;
12237da2899SCharles.Forsyth if(tks->sv != BoolT)
12337da2899SCharles.Forsyth digits = 0;
12437da2899SCharles.Forsyth
12537da2899SCharles.Forsyth tks->digwidth = digits;
12637da2899SCharles.Forsyth
12737da2899SCharles.Forsyth p = tkstringsize(tk, tks->label);
12837da2899SCharles.Forsyth if(tks->orient == Tkvertical) {
12937da2899SCharles.Forsyth h = tks->len + 2*ScaleBW + 2*ScalePad;
13037da2899SCharles.Forsyth w = Scalewidth + 2*ScalePad + 2*ScaleBW;
13137da2899SCharles.Forsyth if (p.x)
13237da2899SCharles.Forsyth w += p.x + ScalePad;
13337da2899SCharles.Forsyth if (tks->sv == BoolT)
13437da2899SCharles.Forsyth w += digits + ScalePad;
135c9ccdbd5Sforsyth } else {
13637da2899SCharles.Forsyth w = maximum(p.x, tks->len + ScaleBW + 2*ScalePad);
13737da2899SCharles.Forsyth h = Scalewidth + 2*ScalePad + 2*ScaleBW;
13837da2899SCharles.Forsyth fh = tk->env->font->height;
13937da2899SCharles.Forsyth if(tks->label != nil)
14037da2899SCharles.Forsyth h += fh + ScalePad;
14137da2899SCharles.Forsyth if(tks->sv == BoolT)
14237da2899SCharles.Forsyth h += fh + ScalePad;
14337da2899SCharles.Forsyth }
14437da2899SCharles.Forsyth w += 2*tk->highlightwidth;
14537da2899SCharles.Forsyth h += 2*tk->highlightwidth;
14637da2899SCharles.Forsyth if(!(tk->flag & Tksetwidth))
14737da2899SCharles.Forsyth tk->req.width = w;
14837da2899SCharles.Forsyth if(!(tk->flag & Tksetheight))
14937da2899SCharles.Forsyth tk->req.height = h;
15037da2899SCharles.Forsyth }
15137da2899SCharles.Forsyth
15237da2899SCharles.Forsyth static int
tkscalecheckvalue(Tk * tk)15337da2899SCharles.Forsyth tkscalecheckvalue(Tk *tk)
15437da2899SCharles.Forsyth {
15537da2899SCharles.Forsyth int v;
15637da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
15737da2899SCharles.Forsyth int limit = 1;
15837da2899SCharles.Forsyth
15937da2899SCharles.Forsyth v = tks->value;
16037da2899SCharles.Forsyth if (tks->res > 0)
16137da2899SCharles.Forsyth v = (v / tks->res) * tks->res;
16237da2899SCharles.Forsyth if (tks->to >= tks->from) {
16337da2899SCharles.Forsyth if (v < tks->from)
16437da2899SCharles.Forsyth v = tks->from;
16537da2899SCharles.Forsyth else if (v > tks->to)
16637da2899SCharles.Forsyth v = tks->to;
16737da2899SCharles.Forsyth else
16837da2899SCharles.Forsyth limit = 0;
16937da2899SCharles.Forsyth } else {
17037da2899SCharles.Forsyth if (v < tks->to)
17137da2899SCharles.Forsyth v = tks->to;
17237da2899SCharles.Forsyth else if (v > tks->from)
17337da2899SCharles.Forsyth v = tks->from;
17437da2899SCharles.Forsyth else
17537da2899SCharles.Forsyth limit = 0;
17637da2899SCharles.Forsyth }
17737da2899SCharles.Forsyth /*
17837da2899SCharles.Forsyth * it's possible for the value to end up as a non-whole
17937da2899SCharles.Forsyth * multiple of resolution here, if the end points aren't
18037da2899SCharles.Forsyth * themselves such a multiple. if so, tough - that's
18137da2899SCharles.Forsyth * what you asked for! (it does mean that the endpoints
18237da2899SCharles.Forsyth * are always accessible however, which could be a good thing).
18337da2899SCharles.Forsyth */
18437da2899SCharles.Forsyth tks->value = v;
18537da2899SCharles.Forsyth return limit;
18637da2899SCharles.Forsyth }
18737da2899SCharles.Forsyth
18837da2899SCharles.Forsyth char*
tkscale(TkTop * t,char * arg,char ** ret)18937da2899SCharles.Forsyth tkscale(TkTop *t, char *arg, char **ret)
19037da2899SCharles.Forsyth {
19137da2899SCharles.Forsyth Tk *tk;
19237da2899SCharles.Forsyth char *e;
19337da2899SCharles.Forsyth TkName *names;
19437da2899SCharles.Forsyth TkScale *tks;
19537da2899SCharles.Forsyth TkOptab tko[3];
19637da2899SCharles.Forsyth
19737da2899SCharles.Forsyth tk = tknewobj(t, TKscale, sizeof(Tk)+sizeof(TkScale));
19837da2899SCharles.Forsyth if(tk == nil)
19937da2899SCharles.Forsyth return TkNomem;
20037da2899SCharles.Forsyth
20137da2899SCharles.Forsyth tk->flag |= Tktakefocus;
20237da2899SCharles.Forsyth tks = TKobj(TkScale, tk);
20337da2899SCharles.Forsyth tks->res = TKI2F(1);
20437da2899SCharles.Forsyth tks->to = TKI2F(100);
20537da2899SCharles.Forsyth tks->len = ScaleLen;
20637da2899SCharles.Forsyth tks->orient = Tkvertical;
20737da2899SCharles.Forsyth tks->relief = TKraised;
20837da2899SCharles.Forsyth tks->sl = ScaleSlider;
20937da2899SCharles.Forsyth tks->sv = BoolT;
21037da2899SCharles.Forsyth tks->bigi = 0;
21137da2899SCharles.Forsyth
21237da2899SCharles.Forsyth tko[0].ptr = tk;
21337da2899SCharles.Forsyth tko[0].optab = tkgeneric;
21437da2899SCharles.Forsyth tko[1].ptr = tks;
21537da2899SCharles.Forsyth tko[1].optab = opts;
21637da2899SCharles.Forsyth tko[2].ptr = nil;
21737da2899SCharles.Forsyth
21837da2899SCharles.Forsyth names = nil;
21937da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
22037da2899SCharles.Forsyth if(e != nil) {
22137da2899SCharles.Forsyth tkfreeobj(tk);
22237da2899SCharles.Forsyth return e;
22337da2899SCharles.Forsyth }
22437da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
22537da2899SCharles.Forsyth tkscalecheckvalue(tk);
22637da2899SCharles.Forsyth tksizescale(tk);
22737da2899SCharles.Forsyth if (tks->bigi == 0)
22837da2899SCharles.Forsyth tks->bigi = TKI2F(TKF2I(tks->to - tks->from) / 10);
22937da2899SCharles.Forsyth e = tkbindings(t, tk, b, nelem(b));
23037da2899SCharles.Forsyth
23137da2899SCharles.Forsyth if(e != nil) {
23237da2899SCharles.Forsyth tkfreeobj(tk);
23337da2899SCharles.Forsyth return e;
23437da2899SCharles.Forsyth }
23537da2899SCharles.Forsyth
23637da2899SCharles.Forsyth e = tkaddchild(t, tk, &names);
23737da2899SCharles.Forsyth tkfreename(names);
23837da2899SCharles.Forsyth if(e != nil) {
23937da2899SCharles.Forsyth tkfreeobj(tk);
24037da2899SCharles.Forsyth return e;
24137da2899SCharles.Forsyth }
24237da2899SCharles.Forsyth tk->name->link = nil;
24337da2899SCharles.Forsyth
24437da2899SCharles.Forsyth return tkvalue(ret, "%s", tk->name->name);
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth
24737da2899SCharles.Forsyth static char*
tkscalecget(Tk * tk,char * arg,char ** val)24837da2899SCharles.Forsyth tkscalecget(Tk *tk, char *arg, char **val)
24937da2899SCharles.Forsyth {
25037da2899SCharles.Forsyth TkOptab tko[3];
25137da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
25237da2899SCharles.Forsyth
25337da2899SCharles.Forsyth tko[0].ptr = tk;
25437da2899SCharles.Forsyth tko[0].optab = tkgeneric;
25537da2899SCharles.Forsyth tko[1].ptr = tks;
25637da2899SCharles.Forsyth tko[1].optab = opts;
25737da2899SCharles.Forsyth tko[2].ptr = nil;
25837da2899SCharles.Forsyth
25937da2899SCharles.Forsyth return tkgencget(tko, arg, val, tk->env->top);
26037da2899SCharles.Forsyth }
26137da2899SCharles.Forsyth
26237da2899SCharles.Forsyth void
tkfreescale(Tk * tk)26337da2899SCharles.Forsyth tkfreescale(Tk *tk)
26437da2899SCharles.Forsyth {
26537da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
26637da2899SCharles.Forsyth
26737da2899SCharles.Forsyth if(tks->command != nil)
26837da2899SCharles.Forsyth free(tks->command);
26937da2899SCharles.Forsyth if(tks->label != nil)
27037da2899SCharles.Forsyth free(tks->label);
27137da2899SCharles.Forsyth }
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth static void
tkscalehoriz(Tk * tk,Image * i)27437da2899SCharles.Forsyth tkscalehoriz(Tk *tk, Image *i)
27537da2899SCharles.Forsyth {
27637da2899SCharles.Forsyth TkEnv *e;
27737da2899SCharles.Forsyth char sv[32];
27837da2899SCharles.Forsyth TkScale *tks;
27937da2899SCharles.Forsyth Image *d, *l;
28037da2899SCharles.Forsyth Rectangle r, r2, sr;
28137da2899SCharles.Forsyth Point p, q;
282c9ccdbd5Sforsyth int fh, sh, gh, sl, v, w, h, len;
28337da2899SCharles.Forsyth int fgnd;
28437da2899SCharles.Forsyth
28537da2899SCharles.Forsyth e = tk->env;
28637da2899SCharles.Forsyth tks = TKobj(TkScale, tk);
28737da2899SCharles.Forsyth
28837da2899SCharles.Forsyth
28937da2899SCharles.Forsyth fh = e->font->height;
29037da2899SCharles.Forsyth fgnd = TkCforegnd;
29137da2899SCharles.Forsyth if (tk->flag & Tkdisabled)
29237da2899SCharles.Forsyth fgnd = TkCdisablefgnd;
29337da2899SCharles.Forsyth
29437da2899SCharles.Forsyth r = Rect(0, 0, tk->act.width, tk->act.height);
29537da2899SCharles.Forsyth r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
29637da2899SCharles.Forsyth r = insetrect(r, tk->highlightwidth);
29737da2899SCharles.Forsyth r = insetrect(r, ScalePad);
29837da2899SCharles.Forsyth
29937da2899SCharles.Forsyth if(tks->label != nil) {
30037da2899SCharles.Forsyth string(i, r.min, tkgc(e, fgnd), ZP, e->font, tks->label);
30137da2899SCharles.Forsyth r.min.y += fh + ScalePad;
30237da2899SCharles.Forsyth }
30337da2899SCharles.Forsyth if(tks->sv == BoolT)
30437da2899SCharles.Forsyth r.min.y += fh + ScalePad;
30537da2899SCharles.Forsyth
30637da2899SCharles.Forsyth sr = insetrect(r, ScaleBW);
30737da2899SCharles.Forsyth w = Dx(sr);
30837da2899SCharles.Forsyth h = Dy(sr);
30937da2899SCharles.Forsyth sl = tks->sl + 2*ScaleBW;
31037da2899SCharles.Forsyth
31137da2899SCharles.Forsyth l = tkgc(e, TkCbackgndlght);
31237da2899SCharles.Forsyth d = tkgc(e, TkCbackgnddark);
31337da2899SCharles.Forsyth tkbevel(i, r.min, w, h, ScaleBW, d, l);
31437da2899SCharles.Forsyth
31537da2899SCharles.Forsyth tks->pixmin = sr.min.x;
31637da2899SCharles.Forsyth tks->pixmax = sr.max.x;
31737da2899SCharles.Forsyth
31837da2899SCharles.Forsyth sh = h - 2*ScaleBW;
31937da2899SCharles.Forsyth tks->sw = sh/2;
32037da2899SCharles.Forsyth
32137da2899SCharles.Forsyth w -= sl;
32237da2899SCharles.Forsyth if (w <= 0)
32337da2899SCharles.Forsyth w = 1;
32437da2899SCharles.Forsyth p.x = sr.min.x;
32537da2899SCharles.Forsyth p.y = sr.max.y;
32637da2899SCharles.Forsyth if(tks->tick > 0){
32737da2899SCharles.Forsyth int j, t, l;
32837da2899SCharles.Forsyth t = tks->tick;
32937da2899SCharles.Forsyth l = tks->to-tks->from;
33037da2899SCharles.Forsyth if (l < 0)
33137da2899SCharles.Forsyth l = -l;
33237da2899SCharles.Forsyth if (l == 0)
33337da2899SCharles.Forsyth l = 1;
33437da2899SCharles.Forsyth r2.min.y = p.y;
33537da2899SCharles.Forsyth r2.max.y = p.y + ScaleBW + ScalePad;
33637da2899SCharles.Forsyth for(j = 0; j <= l; j += t){
33737da2899SCharles.Forsyth r2.min.x = p.x+((vlong)j*w)/l+sl/2;
33837da2899SCharles.Forsyth r2.max.x = r2.min.x+1;
33937da2899SCharles.Forsyth draw(i, r2, tkgc(e, fgnd), nil, ZP);
34037da2899SCharles.Forsyth }
34137da2899SCharles.Forsyth }
34237da2899SCharles.Forsyth v = tks->value-tks->from;
34337da2899SCharles.Forsyth len = tks->to-tks->from;
34437da2899SCharles.Forsyth if (len != 0)
34537da2899SCharles.Forsyth p.x += ((vlong)v*w)/len;
34637da2899SCharles.Forsyth p.y = sr.min.y;
34737da2899SCharles.Forsyth q = p;
34837da2899SCharles.Forsyth q.x += tks->sl/2 + 1;
349c9ccdbd5Sforsyth if(ScaleBW > 1) {
350c9ccdbd5Sforsyth gh = sh;
35137da2899SCharles.Forsyth q.y++;
352c9ccdbd5Sforsyth } else
353c9ccdbd5Sforsyth gh = sh-1;
35437da2899SCharles.Forsyth if(tk->flag & Tkactivated) {
35537da2899SCharles.Forsyth r2.min = p;
35637da2899SCharles.Forsyth r2.max.x = p.x+sl;
35737da2899SCharles.Forsyth r2.max.y = sr.max.y;
35837da2899SCharles.Forsyth draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
35937da2899SCharles.Forsyth }
36037da2899SCharles.Forsyth switch(tks->relief) {
36137da2899SCharles.Forsyth case TKsunken:
36237da2899SCharles.Forsyth tkbevel(i, p, tks->sl, sh, ScaleBW, d, l);
363c9ccdbd5Sforsyth tkbevel(i, q, 0, gh, 1, l, d);
36437da2899SCharles.Forsyth break;
36537da2899SCharles.Forsyth case TKraised:
36637da2899SCharles.Forsyth tkbevel(i, p, tks->sl, sh, ScaleBW, l, d);
367c9ccdbd5Sforsyth tkbevel(i, q, 0, gh, 1, d, l);
36837da2899SCharles.Forsyth break;
36937da2899SCharles.Forsyth }
37037da2899SCharles.Forsyth tks->pixpos = p.x;
37137da2899SCharles.Forsyth tks->center = p.y + sh/2 + ScaleBW;
37237da2899SCharles.Forsyth
37337da2899SCharles.Forsyth if(tks->sv != BoolT)
37437da2899SCharles.Forsyth return;
37537da2899SCharles.Forsyth
37637da2899SCharles.Forsyth tkfprint(sv, tks->value);
37737da2899SCharles.Forsyth if(tks->digits > 0 && tks->digits < strlen(sv))
37837da2899SCharles.Forsyth sv[tks->digits] = '\0';
37937da2899SCharles.Forsyth
38037da2899SCharles.Forsyth w = stringwidth(e->font, sv);
38137da2899SCharles.Forsyth p.x = q.x;
38237da2899SCharles.Forsyth p.x -= w/2;
38337da2899SCharles.Forsyth p.y = r.min.y - fh - ScalePad;
38437da2899SCharles.Forsyth if(p.x < tks->pixmin)
38537da2899SCharles.Forsyth p.x = tks->pixmin;
38637da2899SCharles.Forsyth if(p.x+w > tks->pixmax)
38737da2899SCharles.Forsyth p.x = tks->pixmax - w;
38837da2899SCharles.Forsyth
38937da2899SCharles.Forsyth string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
39037da2899SCharles.Forsyth }
39137da2899SCharles.Forsyth
39237da2899SCharles.Forsyth static void
tkscalevert(Tk * tk,Image * i)39337da2899SCharles.Forsyth tkscalevert(Tk *tk, Image *i)
39437da2899SCharles.Forsyth {
39537da2899SCharles.Forsyth TkEnv *e;
39637da2899SCharles.Forsyth TkScale *tks;
39737da2899SCharles.Forsyth char sv[32];
39837da2899SCharles.Forsyth Image *d, *l;
39937da2899SCharles.Forsyth Rectangle r, r2, sr;
40037da2899SCharles.Forsyth Point p, q;
401c9ccdbd5Sforsyth int fh, v, sw, gw, w, h, len, sl;
40237da2899SCharles.Forsyth int fgnd;
40337da2899SCharles.Forsyth
40437da2899SCharles.Forsyth e = tk->env;
40537da2899SCharles.Forsyth tks = TKobj(TkScale, tk);
40637da2899SCharles.Forsyth
40737da2899SCharles.Forsyth fh = e->font->height;
40837da2899SCharles.Forsyth fgnd = TkCforegnd;
40937da2899SCharles.Forsyth if (tk->flag & Tkdisabled)
41037da2899SCharles.Forsyth fgnd = TkCdisablefgnd;
41137da2899SCharles.Forsyth
41237da2899SCharles.Forsyth r = Rect(0, 0, tk->act.width, tk->act.height);
41337da2899SCharles.Forsyth r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
41437da2899SCharles.Forsyth r = insetrect(r, tk->highlightwidth);
41537da2899SCharles.Forsyth r = insetrect(r, ScalePad);
41637da2899SCharles.Forsyth
41737da2899SCharles.Forsyth if (tks->sv)
41837da2899SCharles.Forsyth r.min.x += tks->digwidth + ScalePad;
41937da2899SCharles.Forsyth
42037da2899SCharles.Forsyth if(tks->label != nil) {
42137da2899SCharles.Forsyth p = stringsize(e->font, tks->label);
42237da2899SCharles.Forsyth r.max.x -= p.x;
42337da2899SCharles.Forsyth string(i, Pt(r.max.x, r.min.y), tkgc(e, fgnd), ZP, e->font, tks->label);
42437da2899SCharles.Forsyth r.max.x -= ScalePad;
42537da2899SCharles.Forsyth }
42637da2899SCharles.Forsyth
42737da2899SCharles.Forsyth sr = insetrect(r, ScaleBW);
42837da2899SCharles.Forsyth h = Dy(sr);
42937da2899SCharles.Forsyth w = Dx(sr);
43037da2899SCharles.Forsyth sl = tks->sl + 2*ScaleBW;
43137da2899SCharles.Forsyth
43237da2899SCharles.Forsyth l = tkgc(e, TkCbackgndlght);
43337da2899SCharles.Forsyth d = tkgc(e, TkCbackgnddark);
43437da2899SCharles.Forsyth tkbevel(i, r.min, w, h, ScaleBW, d, l);
43537da2899SCharles.Forsyth
43637da2899SCharles.Forsyth tks->pixmin = sr.min.y;
43737da2899SCharles.Forsyth tks->pixmax = sr.max.y;
43837da2899SCharles.Forsyth
43937da2899SCharles.Forsyth sw = w - 2*ScaleBW;
44037da2899SCharles.Forsyth tks->sw = sw/2;
44137da2899SCharles.Forsyth
44237da2899SCharles.Forsyth h -= sl;
44337da2899SCharles.Forsyth if (h <= 0)
44437da2899SCharles.Forsyth h = 1;
44537da2899SCharles.Forsyth p.x = sr.max.x;
44637da2899SCharles.Forsyth p.y = sr.min.y;
44737da2899SCharles.Forsyth if(tks->tick > 0){
44837da2899SCharles.Forsyth int j, t, l;
44937da2899SCharles.Forsyth t = tks->tick;
45037da2899SCharles.Forsyth l = tks->to-tks->from;
45137da2899SCharles.Forsyth if (l < 0)
45237da2899SCharles.Forsyth l = -l;
45337da2899SCharles.Forsyth if (l == 0)
45437da2899SCharles.Forsyth l = 1;
45537da2899SCharles.Forsyth r2.min = p;
45637da2899SCharles.Forsyth r2.max.x = p.x + ScaleBW + ScalePad;
45737da2899SCharles.Forsyth for(j = 0; j <= l; j += t){
45837da2899SCharles.Forsyth r2.min.y = p.y+((vlong)j*h)/l+sl/2;
45937da2899SCharles.Forsyth r2.max.y = r2.min.y+1;
46037da2899SCharles.Forsyth draw(i, r2, tkgc(e, fgnd), nil, ZP);
46137da2899SCharles.Forsyth }
46237da2899SCharles.Forsyth }
46337da2899SCharles.Forsyth
46437da2899SCharles.Forsyth v = tks->value-tks->from;
46537da2899SCharles.Forsyth len = tks->to-tks->from;
46637da2899SCharles.Forsyth if (len != 0)
46737da2899SCharles.Forsyth p.y += ((vlong)v*h)/len;
46837da2899SCharles.Forsyth p.x = sr.min.x;
46937da2899SCharles.Forsyth q = p;
470c9ccdbd5Sforsyth if(ScaleBW > 1) {
47137da2899SCharles.Forsyth q.x++;
472c9ccdbd5Sforsyth gw = sw;
473c9ccdbd5Sforsyth } else
474c9ccdbd5Sforsyth gw = sw-1;
47537da2899SCharles.Forsyth q.y += tks->sl/2 + 1;
47637da2899SCharles.Forsyth if(tk->flag & Tkactivated) {
47737da2899SCharles.Forsyth r2.min = p;
47837da2899SCharles.Forsyth r2.max.x = sr.max.x;
47937da2899SCharles.Forsyth r2.max.y = p.y+sl;
48037da2899SCharles.Forsyth draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
48137da2899SCharles.Forsyth }
48237da2899SCharles.Forsyth switch(tks->relief) {
48337da2899SCharles.Forsyth case TKsunken:
48437da2899SCharles.Forsyth tkbevel(i, p, sw, tks->sl, ScaleBW, d, l);
4851b078c23Sforsyth tkbevel(i, q, gw, 0, 1, l, d);
48637da2899SCharles.Forsyth break;
48737da2899SCharles.Forsyth case TKraised:
48837da2899SCharles.Forsyth tkbevel(i, p, sw, tks->sl, ScaleBW, l, d);
4891b078c23Sforsyth tkbevel(i, q, gw, 0, 1, d, l);
49037da2899SCharles.Forsyth break;
49137da2899SCharles.Forsyth }
49237da2899SCharles.Forsyth tks->pixpos = p.y;
49337da2899SCharles.Forsyth tks->center = p.x + sw/2 + ScaleBW;
49437da2899SCharles.Forsyth
49537da2899SCharles.Forsyth if(tks->sv != BoolT)
49637da2899SCharles.Forsyth return;
49737da2899SCharles.Forsyth
49837da2899SCharles.Forsyth tkfprint(sv, tks->value);
49937da2899SCharles.Forsyth if(tks->digits > 0 && tks->digits < strlen(sv))
50037da2899SCharles.Forsyth sv[tks->digits] = '\0';
50137da2899SCharles.Forsyth
50237da2899SCharles.Forsyth p.x = r.min.x - ScalePad - stringwidth(e->font, sv);
50337da2899SCharles.Forsyth p.y = q.y;
50437da2899SCharles.Forsyth p.y -= fh/2;
50537da2899SCharles.Forsyth if (p.y < tks->pixmin)
50637da2899SCharles.Forsyth p.y = tks->pixmin;
50737da2899SCharles.Forsyth if (p.y + fh > tks->pixmax)
50837da2899SCharles.Forsyth p.y = tks->pixmax - fh;
50937da2899SCharles.Forsyth string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
51037da2899SCharles.Forsyth }
51137da2899SCharles.Forsyth
51237da2899SCharles.Forsyth char*
tkdrawscale(Tk * tk,Point orig)51337da2899SCharles.Forsyth tkdrawscale(Tk *tk, Point orig)
51437da2899SCharles.Forsyth {
51537da2899SCharles.Forsyth Point p;
51637da2899SCharles.Forsyth TkEnv *env;
51737da2899SCharles.Forsyth TkScale *tks;
51837da2899SCharles.Forsyth Rectangle r, fr;
51937da2899SCharles.Forsyth Image *i;
52037da2899SCharles.Forsyth
52137da2899SCharles.Forsyth tks = TKobj(TkScale, tk);
52237da2899SCharles.Forsyth env = tk->env;
52337da2899SCharles.Forsyth
52437da2899SCharles.Forsyth r.min = ZP;
52537da2899SCharles.Forsyth r.max.x = tk->act.width + 2*tk->borderwidth;
52637da2899SCharles.Forsyth r.max.y = tk->act.height + 2*tk->borderwidth;
52737da2899SCharles.Forsyth i = tkitmp(env, r.max, TkCbackgnd);
52837da2899SCharles.Forsyth if(i == nil)
52937da2899SCharles.Forsyth return nil;
53037da2899SCharles.Forsyth
53137da2899SCharles.Forsyth if(tks->orient == Tkvertical)
53237da2899SCharles.Forsyth tkscalevert(tk, i);
53337da2899SCharles.Forsyth else
53437da2899SCharles.Forsyth tkscalehoriz(tk, i);
53537da2899SCharles.Forsyth
53637da2899SCharles.Forsyth tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);
53737da2899SCharles.Forsyth if (tkhaskeyfocus(tk)) {
53837da2899SCharles.Forsyth fr = insetrect(r, tk->borderwidth);
53937da2899SCharles.Forsyth tkbox(i, fr, tk->highlightwidth, tkgc(env, TkChighlightfgnd));
54037da2899SCharles.Forsyth }
54137da2899SCharles.Forsyth
54237da2899SCharles.Forsyth p.x = tk->act.x + orig.x;
54337da2899SCharles.Forsyth p.y = tk->act.y + orig.y;
54437da2899SCharles.Forsyth r = rectaddpt(r, p);
54537da2899SCharles.Forsyth draw(tkimageof(tk), r, i, nil, ZP);
54637da2899SCharles.Forsyth
54737da2899SCharles.Forsyth return nil;
54837da2899SCharles.Forsyth }
54937da2899SCharles.Forsyth
55037da2899SCharles.Forsyth /* Widget Commands (+ means implemented)
55137da2899SCharles.Forsyth +cget
55237da2899SCharles.Forsyth +configure
55337da2899SCharles.Forsyth +coords
55437da2899SCharles.Forsyth +get
55537da2899SCharles.Forsyth +identify
55637da2899SCharles.Forsyth +set
55737da2899SCharles.Forsyth */
55837da2899SCharles.Forsyth
55937da2899SCharles.Forsyth static char*
tkscaleconf(Tk * tk,char * arg,char ** val)56037da2899SCharles.Forsyth tkscaleconf(Tk *tk, char *arg, char **val)
56137da2899SCharles.Forsyth {
56237da2899SCharles.Forsyth char *e;
56337da2899SCharles.Forsyth TkGeom g;
56437da2899SCharles.Forsyth int bd;
56537da2899SCharles.Forsyth TkOptab tko[3];
56637da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
56737da2899SCharles.Forsyth
56837da2899SCharles.Forsyth tko[0].ptr = tk;
56937da2899SCharles.Forsyth tko[0].optab = tkgeneric;
57037da2899SCharles.Forsyth tko[1].ptr = tks;
57137da2899SCharles.Forsyth tko[1].optab = opts;
57237da2899SCharles.Forsyth tko[2].ptr = nil;
57337da2899SCharles.Forsyth
57437da2899SCharles.Forsyth if(*arg == '\0')
57537da2899SCharles.Forsyth return tkconflist(tko, val);
57637da2899SCharles.Forsyth
57737da2899SCharles.Forsyth g = tk->req;
57837da2899SCharles.Forsyth bd = tk->borderwidth;
57937da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
58037da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
58137da2899SCharles.Forsyth tkscalecheckvalue(tk);
58237da2899SCharles.Forsyth tksizescale(tk);
58337da2899SCharles.Forsyth tkgeomchg(tk, &g, bd);
58437da2899SCharles.Forsyth
58537da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
58637da2899SCharles.Forsyth return e;
58737da2899SCharles.Forsyth }
58837da2899SCharles.Forsyth
58937da2899SCharles.Forsyth char*
tkscaleposn(TkEnv * env,Tk * tk,char * arg,int * z)59037da2899SCharles.Forsyth tkscaleposn(TkEnv *env, Tk *tk, char *arg, int *z)
59137da2899SCharles.Forsyth {
59237da2899SCharles.Forsyth int x, y;
59337da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
59437da2899SCharles.Forsyth char *e;
59537da2899SCharles.Forsyth
59637da2899SCharles.Forsyth e = tkfracword(env->top, &arg, &x, env);
59737da2899SCharles.Forsyth if(e != nil)
59837da2899SCharles.Forsyth return e;
59937da2899SCharles.Forsyth e = tkfracword(env->top, &arg, &y, env);
60037da2899SCharles.Forsyth if(e != nil)
60137da2899SCharles.Forsyth return e;
60237da2899SCharles.Forsyth
60337da2899SCharles.Forsyth x = TKF2I(x) + tk->borderwidth;
60437da2899SCharles.Forsyth y = TKF2I(y) + tk->borderwidth;
60537da2899SCharles.Forsyth
60637da2899SCharles.Forsyth if(tks->orient == Tkvertical) {
60737da2899SCharles.Forsyth if(z != nil) {
60837da2899SCharles.Forsyth z[0] = x;
60937da2899SCharles.Forsyth z[1] = y;
61037da2899SCharles.Forsyth }
61137da2899SCharles.Forsyth x = y;
61237da2899SCharles.Forsyth }
61337da2899SCharles.Forsyth else {
61437da2899SCharles.Forsyth if(z != nil) {
61537da2899SCharles.Forsyth z[0] = y;
61637da2899SCharles.Forsyth z[1] = x;
61737da2899SCharles.Forsyth }
61837da2899SCharles.Forsyth }
61937da2899SCharles.Forsyth if(x > tks->pixmin && x < tks->pixpos)
62037da2899SCharles.Forsyth return trough1;
621c9ccdbd5Sforsyth else if(x >= tks->pixpos && x < tks->pixpos+tks->sl+2*ScaleBW)
62237da2899SCharles.Forsyth return slider;
623c9ccdbd5Sforsyth else if(x >= tks->pixpos+tks->sl+2*ScaleBW && x < tks->pixmax)
62437da2899SCharles.Forsyth return trough2;
62537da2899SCharles.Forsyth
62637da2899SCharles.Forsyth return "";
62737da2899SCharles.Forsyth }
62837da2899SCharles.Forsyth
62937da2899SCharles.Forsyth static char*
tkscaleident(Tk * tk,char * arg,char ** val)63037da2899SCharles.Forsyth tkscaleident(Tk *tk, char *arg, char **val)
63137da2899SCharles.Forsyth {
63237da2899SCharles.Forsyth char *v;
63337da2899SCharles.Forsyth
63437da2899SCharles.Forsyth v = tkscaleposn(tk->env, tk, arg, nil);
63537da2899SCharles.Forsyth if(v == nil)
63637da2899SCharles.Forsyth return TkBadvl;
63737da2899SCharles.Forsyth return tkvalue(val, "%s", v);
63837da2899SCharles.Forsyth }
63937da2899SCharles.Forsyth
64037da2899SCharles.Forsyth static char*
tkscalecoords(Tk * tk,char * arg,char ** val)64137da2899SCharles.Forsyth tkscalecoords(Tk *tk, char *arg, char **val)
64237da2899SCharles.Forsyth {
64337da2899SCharles.Forsyth int p, x, y, l, value;
64437da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
64537da2899SCharles.Forsyth char *e;
64637da2899SCharles.Forsyth
64737da2899SCharles.Forsyth value = tks->value;
64837da2899SCharles.Forsyth if(arg != nil && arg[0] != '\0') {
64937da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &value, tk->env);
65037da2899SCharles.Forsyth if (e != nil)
65137da2899SCharles.Forsyth return e;
65237da2899SCharles.Forsyth }
65337da2899SCharles.Forsyth
65437da2899SCharles.Forsyth value -= tks->from;
65537da2899SCharles.Forsyth p = tks->pixmax - tks->pixmin;
65637da2899SCharles.Forsyth l = TKF2I(tks->to-tks->from);
65737da2899SCharles.Forsyth if (l==0)
65837da2899SCharles.Forsyth p /= 2;
65937da2899SCharles.Forsyth else
66037da2899SCharles.Forsyth p = TKF2I(value*p/l);
66137da2899SCharles.Forsyth p += tks->pixmin;
66237da2899SCharles.Forsyth if(tks->orient == Tkvertical) {
66337da2899SCharles.Forsyth x = tks->center;
66437da2899SCharles.Forsyth y = p;
66537da2899SCharles.Forsyth }
66637da2899SCharles.Forsyth else {
66737da2899SCharles.Forsyth x = p;
66837da2899SCharles.Forsyth y = tks->center;
66937da2899SCharles.Forsyth }
67037da2899SCharles.Forsyth return tkvalue(val, "%d %d", x, y);
67137da2899SCharles.Forsyth }
67237da2899SCharles.Forsyth
67337da2899SCharles.Forsyth static char*
tkscaleget(Tk * tk,char * arg,char ** val)67437da2899SCharles.Forsyth tkscaleget(Tk *tk, char *arg, char **val)
67537da2899SCharles.Forsyth {
67637da2899SCharles.Forsyth int x, y, value, v, l;
67737da2899SCharles.Forsyth char buf[Tkminitem], *e;
67837da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
67937da2899SCharles.Forsyth
68037da2899SCharles.Forsyth value = tks->value;
68137da2899SCharles.Forsyth if(arg[0] != '\0') {
68237da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &x, tk->env);
68337da2899SCharles.Forsyth if (e != nil)
68437da2899SCharles.Forsyth return e;
68537da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &y, tk->env);
68637da2899SCharles.Forsyth if (e != nil)
68737da2899SCharles.Forsyth return e;
68837da2899SCharles.Forsyth if(tks->orient == Tkvertical)
68937da2899SCharles.Forsyth v = TKF2I(y) + tk->borderwidth;
69037da2899SCharles.Forsyth else
69137da2899SCharles.Forsyth v = TKF2I(x) + tk->borderwidth;
69237da2899SCharles.Forsyth
69337da2899SCharles.Forsyth if(v < tks->pixmin)
69437da2899SCharles.Forsyth value = tks->from;
69537da2899SCharles.Forsyth else
69637da2899SCharles.Forsyth if(v > tks->pixmax)
69737da2899SCharles.Forsyth value = tks->to;
69837da2899SCharles.Forsyth else {
69937da2899SCharles.Forsyth l = tks->pixmax-tks->pixmin;
70037da2899SCharles.Forsyth value = 0;
70137da2899SCharles.Forsyth if (l!=0)
70237da2899SCharles.Forsyth value = v * ((tks->to-tks->from)/l);
70337da2899SCharles.Forsyth value += tks->from;
70437da2899SCharles.Forsyth }
70537da2899SCharles.Forsyth if(tks->res > 0)
70637da2899SCharles.Forsyth value = (value/tks->res)*tks->res;
70737da2899SCharles.Forsyth }
70837da2899SCharles.Forsyth tkfprint(buf, value);
70937da2899SCharles.Forsyth return tkvalue(val, "%s", buf);
71037da2899SCharles.Forsyth }
71137da2899SCharles.Forsyth
71237da2899SCharles.Forsyth static char*
tkscaleset(Tk * tk,char * arg,char ** val)71337da2899SCharles.Forsyth tkscaleset(Tk *tk, char *arg, char **val)
71437da2899SCharles.Forsyth {
71537da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
71637da2899SCharles.Forsyth char *e;
71737da2899SCharles.Forsyth
71837da2899SCharles.Forsyth USED(val);
71937da2899SCharles.Forsyth
72037da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &tks->value, tk->env);
72137da2899SCharles.Forsyth if (e != nil)
72237da2899SCharles.Forsyth return e;
72337da2899SCharles.Forsyth tkscalecheckvalue(tk);
72437da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
72537da2899SCharles.Forsyth return nil;
72637da2899SCharles.Forsyth }
72737da2899SCharles.Forsyth
72837da2899SCharles.Forsyth /* tkScaleMotion %x %y */
72937da2899SCharles.Forsyth static char*
tkscalemotion(Tk * tk,char * arg,char ** val)73037da2899SCharles.Forsyth tkscalemotion(Tk *tk, char *arg, char **val)
73137da2899SCharles.Forsyth {
73237da2899SCharles.Forsyth int o, z[2];
73337da2899SCharles.Forsyth char *v;
73437da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
73537da2899SCharles.Forsyth extern int tkstylus;
73637da2899SCharles.Forsyth
73737da2899SCharles.Forsyth USED(val);
73837da2899SCharles.Forsyth v = tkscaleposn(tk->env, tk, arg, z);
73937da2899SCharles.Forsyth if(v == nil)
74037da2899SCharles.Forsyth return TkBadvl;
74137da2899SCharles.Forsyth
74237da2899SCharles.Forsyth o = tk->flag;
74337da2899SCharles.Forsyth if(v != slider || z[0] < tks->center-tks->sw || z[0] > tks->center+tks->sw)
74437da2899SCharles.Forsyth tk->flag &= ~Tkactivated;
74537da2899SCharles.Forsyth else if(tkstylus == 0 || tk->env->top->ctxt->mstate.b != 0)
74637da2899SCharles.Forsyth tk->flag |= Tkactivated;
74737da2899SCharles.Forsyth
74837da2899SCharles.Forsyth if((o & Tkactivated) != (tk->flag & Tkactivated))
74937da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
75037da2899SCharles.Forsyth
75137da2899SCharles.Forsyth return nil;
75237da2899SCharles.Forsyth }
75337da2899SCharles.Forsyth
75437da2899SCharles.Forsyth static char*
tkscaledrag(Tk * tk,char * arg,char ** val)75537da2899SCharles.Forsyth tkscaledrag(Tk *tk, char *arg, char **val)
75637da2899SCharles.Forsyth {
75737da2899SCharles.Forsyth int x, y, v;
75837da2899SCharles.Forsyth char *e, buf[Tkmaxitem], f[32];
75937da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
76037da2899SCharles.Forsyth
76137da2899SCharles.Forsyth USED(val);
76237da2899SCharles.Forsyth if((tks->flag & Dragging) == 0)
76337da2899SCharles.Forsyth return nil;
76437da2899SCharles.Forsyth if(tks->flag & Autorepeat)
76537da2899SCharles.Forsyth return nil;
76637da2899SCharles.Forsyth
76737da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &x, tk->env);
76837da2899SCharles.Forsyth if(e != nil)
76937da2899SCharles.Forsyth return e;
77037da2899SCharles.Forsyth e = tkfracword(tk->env->top, &arg, &y, tk->env);
77137da2899SCharles.Forsyth if(e != nil)
77237da2899SCharles.Forsyth return e;
77337da2899SCharles.Forsyth
77437da2899SCharles.Forsyth if(tks->orient == Tkvertical)
77537da2899SCharles.Forsyth v = TKF2I(y) + tk->borderwidth;
77637da2899SCharles.Forsyth else
77737da2899SCharles.Forsyth v = TKF2I(x) + tk->borderwidth;
77837da2899SCharles.Forsyth
77937da2899SCharles.Forsyth v -= tks->pix;
78037da2899SCharles.Forsyth x = tks->pixmax-tks->pixmin;
78137da2899SCharles.Forsyth if (x!=tks->sl)
78237da2899SCharles.Forsyth v = tks->base + (vlong)v * (tks->to-tks->from)/(x-tks->sl);
78337da2899SCharles.Forsyth else
78437da2899SCharles.Forsyth v = tks->base;
78537da2899SCharles.Forsyth if(tks->res > 0) {
78637da2899SCharles.Forsyth int a = tks->res / 2;
78737da2899SCharles.Forsyth if (v < 0)
78837da2899SCharles.Forsyth a = -a;
78937da2899SCharles.Forsyth v = ((v+a)/tks->res)*tks->res;
79037da2899SCharles.Forsyth }
79137da2899SCharles.Forsyth
79237da2899SCharles.Forsyth tks->value = v;
79337da2899SCharles.Forsyth tkscalecheckvalue(tk);
79437da2899SCharles.Forsyth
79537da2899SCharles.Forsyth if(tks->command != nil && tks->jump != BoolT) {
79637da2899SCharles.Forsyth tkfprint(f, tks->value);
79737da2899SCharles.Forsyth snprint(buf, sizeof(buf), "%s %s", tks->command, f);
79837da2899SCharles.Forsyth e = tkexec(tk->env->top, buf, nil);
79937da2899SCharles.Forsyth }
80037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
80137da2899SCharles.Forsyth return e;
80237da2899SCharles.Forsyth }
80337da2899SCharles.Forsyth
80437da2899SCharles.Forsyth static int
sgn(int v)80537da2899SCharles.Forsyth sgn(int v)
80637da2899SCharles.Forsyth {
80737da2899SCharles.Forsyth return v >= 0 ? 1 : -1;
80837da2899SCharles.Forsyth }
80937da2899SCharles.Forsyth
81037da2899SCharles.Forsyth static char*
stepscale(Tk * tk,char * pos,int * end)81137da2899SCharles.Forsyth stepscale(Tk *tk, char *pos, int *end)
81237da2899SCharles.Forsyth {
81337da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
81437da2899SCharles.Forsyth char *e, buf[Tkmaxitem], f[32];
81537da2899SCharles.Forsyth int s;
81637da2899SCharles.Forsyth
81737da2899SCharles.Forsyth s = sgn(tks->to - tks->from);
81837da2899SCharles.Forsyth if(pos == trough1) {
81937da2899SCharles.Forsyth tks->value -= s * tks->bigi;
82037da2899SCharles.Forsyth } else {
82137da2899SCharles.Forsyth /* trough2 */
82237da2899SCharles.Forsyth tks->value += s * tks->bigi;
82337da2899SCharles.Forsyth }
82437da2899SCharles.Forsyth s = !tkscalecheckvalue(tk);
82537da2899SCharles.Forsyth if (end != nil)
82637da2899SCharles.Forsyth *end = s;
82737da2899SCharles.Forsyth e = nil;
82837da2899SCharles.Forsyth if(tks->command != nil) {
82937da2899SCharles.Forsyth /* XXX perhaps should only send command if value has actually changed */
83037da2899SCharles.Forsyth tkfprint(f, tks->value);
83137da2899SCharles.Forsyth snprint(buf, sizeof(buf), "%s %s", tks->command, f);
83237da2899SCharles.Forsyth e = tkexec(tk->env->top, buf, nil);
83337da2899SCharles.Forsyth }
83437da2899SCharles.Forsyth return e;
83537da2899SCharles.Forsyth }
83637da2899SCharles.Forsyth
83737da2899SCharles.Forsyth static void
screpeat(Tk * tk,void * v,int cancelled)83837da2899SCharles.Forsyth screpeat(Tk *tk, void *v, int cancelled)
83937da2899SCharles.Forsyth {
84037da2899SCharles.Forsyth char *e, *pos;
84137da2899SCharles.Forsyth int repeat;
84237da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
84337da2899SCharles.Forsyth
84437da2899SCharles.Forsyth pos = v;
84537da2899SCharles.Forsyth if (cancelled) {
84637da2899SCharles.Forsyth tks->flag &= ~Autorepeat;
84737da2899SCharles.Forsyth return;
84837da2899SCharles.Forsyth }
84937da2899SCharles.Forsyth e = stepscale(tk, pos, &repeat);
85037da2899SCharles.Forsyth if(e != nil || !repeat) {
85137da2899SCharles.Forsyth tks->flag &= ~Autorepeat;
85237da2899SCharles.Forsyth tkcancelrepeat(tk);
85337da2899SCharles.Forsyth }
85437da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
85537da2899SCharles.Forsyth tkupdate(tk->env->top);
85637da2899SCharles.Forsyth }
85737da2899SCharles.Forsyth
85837da2899SCharles.Forsyth static char*
tkscalebut1p(Tk * tk,char * arg,char ** val)85937da2899SCharles.Forsyth tkscalebut1p(Tk *tk, char *arg, char **val)
86037da2899SCharles.Forsyth {
86137da2899SCharles.Forsyth int z[2];
86237da2899SCharles.Forsyth char *v, *e;
86337da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
86437da2899SCharles.Forsyth int repeat;
86537da2899SCharles.Forsyth
86637da2899SCharles.Forsyth USED(val);
86737da2899SCharles.Forsyth v = tkscaleposn(tk->env, tk, arg, z);
86837da2899SCharles.Forsyth if(v == nil)
86937da2899SCharles.Forsyth return TkBadvl;
87037da2899SCharles.Forsyth
87137da2899SCharles.Forsyth e = nil;
87237da2899SCharles.Forsyth if(v[0] == '\0' || z[0] < tks->center-tks->sw || z[0] > tks->center+tks->sw)
87337da2899SCharles.Forsyth return nil;
87437da2899SCharles.Forsyth if(v == slider) {
87537da2899SCharles.Forsyth tks->flag |= Dragging;
87637da2899SCharles.Forsyth tks->relief = TKsunken;
87737da2899SCharles.Forsyth tks->pix = z[1];
87837da2899SCharles.Forsyth tks->base = tks->value;
87937da2899SCharles.Forsyth tkscalecheckvalue(tk);
88037da2899SCharles.Forsyth } else {
88137da2899SCharles.Forsyth e = stepscale(tk, v, &repeat);
88237da2899SCharles.Forsyth if (e == nil && repeat) {
88337da2899SCharles.Forsyth tks->flag |= Autorepeat;
88437da2899SCharles.Forsyth tkrepeat(tk, screpeat, v, TkRptpause, TkRptinterval);
88537da2899SCharles.Forsyth }
88637da2899SCharles.Forsyth }
88737da2899SCharles.Forsyth
88837da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
88937da2899SCharles.Forsyth return e;
89037da2899SCharles.Forsyth }
89137da2899SCharles.Forsyth
89237da2899SCharles.Forsyth static char*
tkscalebut1r(Tk * tk,char * arg,char ** val)89337da2899SCharles.Forsyth tkscalebut1r(Tk *tk, char *arg, char **val)
89437da2899SCharles.Forsyth {
89537da2899SCharles.Forsyth TkScale *tks = TKobj(TkScale, tk);
89637da2899SCharles.Forsyth char *e, buf[Tkmaxitem], f[32];
89737da2899SCharles.Forsyth USED(val);
89837da2899SCharles.Forsyth USED(arg);
89937da2899SCharles.Forsyth if(tks->flag & Autorepeat) {
90037da2899SCharles.Forsyth tkcancelrepeat(tk);
90137da2899SCharles.Forsyth tks->flag &= ~Autorepeat;
90237da2899SCharles.Forsyth }
90337da2899SCharles.Forsyth e = nil;
90437da2899SCharles.Forsyth if (tks->flag & Dragging) {
90537da2899SCharles.Forsyth if (tks->command != nil && tks->jump == BoolT && (tks->flag & Dragging)) {
90637da2899SCharles.Forsyth tkfprint(f, tks->value);
90737da2899SCharles.Forsyth snprint(buf, sizeof(buf), "%s %s", tks->command, f);
90837da2899SCharles.Forsyth e = tkexec(tk->env->top, buf, nil);
90937da2899SCharles.Forsyth }
91037da2899SCharles.Forsyth tks->relief = TKraised;
91137da2899SCharles.Forsyth tks->flag &= ~Dragging;
91237da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
91337da2899SCharles.Forsyth }
91437da2899SCharles.Forsyth return e;
91537da2899SCharles.Forsyth }
91637da2899SCharles.Forsyth
91737da2899SCharles.Forsyth static char*
tkscalekey(Tk * tk,char * arg,char ** val)91837da2899SCharles.Forsyth tkscalekey(Tk *tk, char *arg, char **val)
91937da2899SCharles.Forsyth {
92037da2899SCharles.Forsyth char *e;
92137da2899SCharles.Forsyth int key;
92237da2899SCharles.Forsyth char *pos = nil;
92337da2899SCharles.Forsyth USED(arg);
92437da2899SCharles.Forsyth USED(val);
92537da2899SCharles.Forsyth
92637da2899SCharles.Forsyth if(tk->flag & Tkdisabled)
92737da2899SCharles.Forsyth return nil;
92837da2899SCharles.Forsyth
929*48c2bcd8Sforsyth key = strtol(arg, nil, 0);
93037da2899SCharles.Forsyth if (key == Up || key == Left)
93137da2899SCharles.Forsyth pos = trough1;
93237da2899SCharles.Forsyth else if (key == Down || key == Right)
93337da2899SCharles.Forsyth pos = trough2;
93437da2899SCharles.Forsyth if (pos != nil) {
93537da2899SCharles.Forsyth e = stepscale(tk, pos, nil);
93637da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
93737da2899SCharles.Forsyth return e;
93837da2899SCharles.Forsyth }
93937da2899SCharles.Forsyth return nil;
94037da2899SCharles.Forsyth }
94137da2899SCharles.Forsyth
94237da2899SCharles.Forsyth TkCmdtab tkscalecmd[] =
94337da2899SCharles.Forsyth {
94437da2899SCharles.Forsyth "cget", tkscalecget,
94537da2899SCharles.Forsyth "configure", tkscaleconf,
94637da2899SCharles.Forsyth "set", tkscaleset,
94737da2899SCharles.Forsyth "identify", tkscaleident,
94837da2899SCharles.Forsyth "get", tkscaleget,
94937da2899SCharles.Forsyth "coords", tkscalecoords,
95037da2899SCharles.Forsyth "tkScaleMotion", tkscalemotion,
95137da2899SCharles.Forsyth "tkScaleDrag", tkscaledrag,
95237da2899SCharles.Forsyth "tkScaleBut1P", tkscalebut1p,
95337da2899SCharles.Forsyth "tkScaleBut1R", tkscalebut1r,
95437da2899SCharles.Forsyth "tkScaleKey", tkscalekey,
95537da2899SCharles.Forsyth nil
95637da2899SCharles.Forsyth };
95737da2899SCharles.Forsyth
95837da2899SCharles.Forsyth TkMethod scalemethod = {
95937da2899SCharles.Forsyth "scale",
96037da2899SCharles.Forsyth tkscalecmd,
96137da2899SCharles.Forsyth tkfreescale,
96237da2899SCharles.Forsyth tkdrawscale
96337da2899SCharles.Forsyth };
964