123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963 |
- #include <lib9.h>
- #include <kernel.h>
- #include "draw.h"
- #include "tk.h"
- #include "keyboard.h"
- #define O(t, e) ((long)(&((t*)0)->e))
- typedef struct TkScale TkScale;
- struct TkScale
- {
- int value;
- int bigi;
- int digits;
- int digwidth;
- int from; /* Base of range */
- int to; /* Limit of range */
- int len; /* Length of groove */
- int res; /* Resolution */
- int sv; /* Show value */
- int sl; /* Slider length */
- int sw; /* Slider width div 2 */
- int relief;
- int tick;
- int orient;
- char* command;
- char* label;
- int pixmin;
- int pixmax;
- int pixpos;
- int center;
- int pix;
- int base;
- int flag;
- int jump;
- };
- enum {
- Dragging = (1<<0),
- Autorepeat = (1<<1),
- };
- static
- TkOption opts[] =
- {
- "bigincrement", OPTnnfrac, O(TkScale, bigi), nil,
- "digits", OPTdist, O(TkScale, digits), nil,
- "from", OPTfrac, O(TkScale, from), nil,
- "to", OPTfrac, O(TkScale, to), nil,
- "length", OPTdist, O(TkScale, len), nil,
- "resolution", OPTnnfrac, O(TkScale, res), nil,
- "showrange", OPTignore, 0, nil,
- "showvalue", OPTstab, O(TkScale, sv), tkbool,
- "jump", OPTstab, O(TkScale, jump), tkbool,
- "sliderlength", OPTdist, O(TkScale, sl), nil,
- "sliderrelief", OPTstab, O(TkScale, relief), tkrelief,
- "tickinterval", OPTfrac, O(TkScale, tick), nil,
- "tick", OPTfrac, O(TkScale, tick), nil,
- "label", OPTtext, O(TkScale, label), nil,
- "command", OPTtext, O(TkScale, command), nil,
- "orient", OPTstab, O(TkScale, orient), tkorient,
- nil
- };
- static char trough1[] = "trough1";
- static char trough2[] = "trough2";
- static char slider[] = "slider";
- static
- TkEbind b[] =
- {
- {TkMotion, "%W tkScaleMotion %x %y"},
- {TkButton1P|TkMotion, "%W tkScaleDrag %x %y"},
- {TkButton1P, "%W tkScaleMotion %x %y; %W tkScaleBut1P %x %y"},
- {TkButton1P|TkDouble, "%W tkScaleMotion %x %y; %W tkScaleBut1P %x %y"},
- {TkButton1R, "%W tkScaleDrag %x %y; %W tkScaleBut1R; %W tkScaleMotion %x %y"},
- {TkKey, "%W tkScaleKey 0x%K"},
- };
- enum
- {
- Scalewidth = 18,
- ScalePad = 2,
- ScaleBW = 1,
- ScaleSlider = 16,
- ScaleLen = 80,
- };
- static int
- maximum(int a, int b)
- {
- if (a > b)
- return a;
- return b;
- }
- void
- tksizescale(Tk *tk)
- {
- Point p;
- char buf[32];
- TkScale *tks;
- int fh, w, h, digits, digits2;
- tks = TKobj(TkScale, tk);
- digits = tks->digits;
- if(digits <= 0) {
- digits = tkfprint(buf, tks->from) - buf;
- digits2 = tkfprint(buf, tks->to) - buf;
- digits = maximum(digits, digits2);
- if (tks->res > 0) {
- digits2 = tkfprint(buf, tks->from + tks->res) - buf;
- digits = maximum(digits, digits2);
- digits2 = tkfprint(buf, tks->to - tks->res) - buf;
- digits = maximum(digits, digits2);
- }
- }
- digits *= tk->env->wzero;
- if(tks->sv != BoolT)
- digits = 0;
- tks->digwidth = digits;
- p = tkstringsize(tk, tks->label);
- if(tks->orient == Tkvertical) {
- h = tks->len + 2*ScaleBW + 2*ScalePad;
- w = Scalewidth + 2*ScalePad + 2*ScaleBW;
- if (p.x)
- w += p.x + ScalePad;
- if (tks->sv == BoolT)
- w += digits + ScalePad;
- } else {
- w = maximum(p.x, tks->len + ScaleBW + 2*ScalePad);
- h = Scalewidth + 2*ScalePad + 2*ScaleBW;
- fh = tk->env->font->height;
- if(tks->label != nil)
- h += fh + ScalePad;
- if(tks->sv == BoolT)
- h += fh + ScalePad;
- }
- w += 2*tk->highlightwidth;
- h += 2*tk->highlightwidth;
- if(!(tk->flag & Tksetwidth))
- tk->req.width = w;
- if(!(tk->flag & Tksetheight))
- tk->req.height = h;
- }
- static int
- tkscalecheckvalue(Tk *tk)
- {
- int v;
- TkScale *tks = TKobj(TkScale, tk);
- int limit = 1;
- v = tks->value;
- if (tks->res > 0)
- v = (v / tks->res) * tks->res;
- if (tks->to >= tks->from) {
- if (v < tks->from)
- v = tks->from;
- else if (v > tks->to)
- v = tks->to;
- else
- limit = 0;
- } else {
- if (v < tks->to)
- v = tks->to;
- else if (v > tks->from)
- v = tks->from;
- else
- limit = 0;
- }
- /*
- * it's possible for the value to end up as a non-whole
- * multiple of resolution here, if the end points aren't
- * themselves such a multiple. if so, tough - that's
- * what you asked for! (it does mean that the endpoints
- * are always accessible however, which could be a good thing).
- */
- tks->value = v;
- return limit;
- }
- char*
- tkscale(TkTop *t, char *arg, char **ret)
- {
- Tk *tk;
- char *e;
- TkName *names;
- TkScale *tks;
- TkOptab tko[3];
- tk = tknewobj(t, TKscale, sizeof(Tk)+sizeof(TkScale));
- if(tk == nil)
- return TkNomem;
- tk->flag |= Tktakefocus;
- tks = TKobj(TkScale, tk);
- tks->res = TKI2F(1);
- tks->to = TKI2F(100);
- tks->len = ScaleLen;
- tks->orient = Tkvertical;
- tks->relief = TKraised;
- tks->sl = ScaleSlider;
- tks->sv = BoolT;
- tks->bigi = 0;
- tko[0].ptr = tk;
- tko[0].optab = tkgeneric;
- tko[1].ptr = tks;
- tko[1].optab = opts;
- tko[2].ptr = nil;
- names = nil;
- e = tkparse(t, arg, tko, &names);
- if(e != nil) {
- tkfreeobj(tk);
- return e;
- }
- tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
- tkscalecheckvalue(tk);
- tksizescale(tk);
- if (tks->bigi == 0)
- tks->bigi = TKI2F(TKF2I(tks->to - tks->from) / 10);
- e = tkbindings(t, tk, b, nelem(b));
- if(e != nil) {
- tkfreeobj(tk);
- return e;
- }
- e = tkaddchild(t, tk, &names);
- tkfreename(names);
- if(e != nil) {
- tkfreeobj(tk);
- return e;
- }
- tk->name->link = nil;
- return tkvalue(ret, "%s", tk->name->name);
- }
- static char*
- tkscalecget(Tk *tk, char *arg, char **val)
- {
- TkOptab tko[3];
- TkScale *tks = TKobj(TkScale, tk);
- tko[0].ptr = tk;
- tko[0].optab = tkgeneric;
- tko[1].ptr = tks;
- tko[1].optab = opts;
- tko[2].ptr = nil;
- return tkgencget(tko, arg, val, tk->env->top);
- }
- void
- tkfreescale(Tk *tk)
- {
- TkScale *tks = TKobj(TkScale, tk);
- if(tks->command != nil)
- free(tks->command);
- if(tks->label != nil)
- free(tks->label);
- }
- static void
- tkscalehoriz(Tk *tk, Image *i)
- {
- TkEnv *e;
- char sv[32];
- TkScale *tks;
- Image *d, *l;
- Rectangle r, r2, sr;
- Point p, q;
- int fh, sh, gh, sl, v, w, h, len;
- int fgnd;
- e = tk->env;
- tks = TKobj(TkScale, tk);
- fh = e->font->height;
- fgnd = TkCforegnd;
- if (tk->flag & Tkdisabled)
- fgnd = TkCdisablefgnd;
- r = Rect(0, 0, tk->act.width, tk->act.height);
- r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
- r = insetrect(r, tk->highlightwidth);
- r = insetrect(r, ScalePad);
- if(tks->label != nil) {
- string(i, r.min, tkgc(e, fgnd), ZP, e->font, tks->label);
- r.min.y += fh + ScalePad;
- }
- if(tks->sv == BoolT)
- r.min.y += fh + ScalePad;
- sr = insetrect(r, ScaleBW);
- w = Dx(sr);
- h = Dy(sr);
- sl = tks->sl + 2*ScaleBW;
- l = tkgc(e, TkCbackgndlght);
- d = tkgc(e, TkCbackgnddark);
- tkbevel(i, r.min, w, h, ScaleBW, d, l);
- tks->pixmin = sr.min.x;
- tks->pixmax = sr.max.x;
- sh = h - 2*ScaleBW;
- tks->sw = sh/2;
- w -= sl;
- if (w <= 0)
- w = 1;
- p.x = sr.min.x;
- p.y = sr.max.y;
- if(tks->tick > 0){
- int j, t, l;
- t = tks->tick;
- l = tks->to-tks->from;
- if (l < 0)
- l = -l;
- if (l == 0)
- l = 1;
- r2.min.y = p.y;
- r2.max.y = p.y + ScaleBW + ScalePad;
- for(j = 0; j <= l; j += t){
- r2.min.x = p.x+((vlong)j*w)/l+sl/2;
- r2.max.x = r2.min.x+1;
- draw(i, r2, tkgc(e, fgnd), nil, ZP);
- }
- }
- v = tks->value-tks->from;
- len = tks->to-tks->from;
- if (len != 0)
- p.x += ((vlong)v*w)/len;
- p.y = sr.min.y;
- q = p;
- q.x += tks->sl/2 + 1;
- if(ScaleBW > 1) {
- gh = sh;
- q.y++;
- } else
- gh = sh-1;
- if(tk->flag & Tkactivated) {
- r2.min = p;
- r2.max.x = p.x+sl;
- r2.max.y = sr.max.y;
- draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
- }
- switch(tks->relief) {
- case TKsunken:
- tkbevel(i, p, tks->sl, sh, ScaleBW, d, l);
- tkbevel(i, q, 0, gh, 1, l, d);
- break;
- case TKraised:
- tkbevel(i, p, tks->sl, sh, ScaleBW, l, d);
- tkbevel(i, q, 0, gh, 1, d, l);
- break;
- }
- tks->pixpos = p.x;
- tks->center = p.y + sh/2 + ScaleBW;
- if(tks->sv != BoolT)
- return;
- tkfprint(sv, tks->value);
- if(tks->digits > 0 && tks->digits < strlen(sv))
- sv[tks->digits] = '\0';
- w = stringwidth(e->font, sv);
- p.x = q.x;
- p.x -= w/2;
- p.y = r.min.y - fh - ScalePad;
- if(p.x < tks->pixmin)
- p.x = tks->pixmin;
- if(p.x+w > tks->pixmax)
- p.x = tks->pixmax - w;
-
- string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
- }
- static void
- tkscalevert(Tk *tk, Image *i)
- {
- TkEnv *e;
- TkScale *tks;
- char sv[32];
- Image *d, *l;
- Rectangle r, r2, sr;
- Point p, q;
- int fh, v, sw, gw, w, h, len, sl;
- int fgnd;
- e = tk->env;
- tks = TKobj(TkScale, tk);
- fh = e->font->height;
- fgnd = TkCforegnd;
- if (tk->flag & Tkdisabled)
- fgnd = TkCdisablefgnd;
- r = Rect(0, 0, tk->act.width, tk->act.height);
- r = rectaddpt(r, Pt(tk->borderwidth, tk->borderwidth));
- r = insetrect(r, tk->highlightwidth);
- r = insetrect(r, ScalePad);
- if (tks->sv)
- r.min.x += tks->digwidth + ScalePad;
- if(tks->label != nil) {
- p = stringsize(e->font, tks->label);
- r.max.x -= p.x;
- string(i, Pt(r.max.x, r.min.y), tkgc(e, fgnd), ZP, e->font, tks->label);
- r.max.x -= ScalePad;
- }
- sr = insetrect(r, ScaleBW);
- h = Dy(sr);
- w = Dx(sr);
- sl = tks->sl + 2*ScaleBW;
- l = tkgc(e, TkCbackgndlght);
- d = tkgc(e, TkCbackgnddark);
- tkbevel(i, r.min, w, h, ScaleBW, d, l);
- tks->pixmin = sr.min.y;
- tks->pixmax = sr.max.y;
- sw = w - 2*ScaleBW;
- tks->sw = sw/2;
- h -= sl;
- if (h <= 0)
- h = 1;
- p.x = sr.max.x;
- p.y = sr.min.y;
- if(tks->tick > 0){
- int j, t, l;
- t = tks->tick;
- l = tks->to-tks->from;
- if (l < 0)
- l = -l;
- if (l == 0)
- l = 1;
- r2.min = p;
- r2.max.x = p.x + ScaleBW + ScalePad;
- for(j = 0; j <= l; j += t){
- r2.min.y = p.y+((vlong)j*h)/l+sl/2;
- r2.max.y = r2.min.y+1;
- draw(i, r2, tkgc(e, fgnd), nil, ZP);
- }
- }
- v = tks->value-tks->from;
- len = tks->to-tks->from;
- if (len != 0)
- p.y += ((vlong)v*h)/len;
- p.x = sr.min.x;
- q = p;
- if(ScaleBW > 1) {
- q.x++;
- gw = sw;
- } else
- gw = sw-1;
- q.y += tks->sl/2 + 1;
- if(tk->flag & Tkactivated) {
- r2.min = p;
- r2.max.x = sr.max.x;
- r2.max.y = p.y+sl;
- draw(i, r2, tkgc(e, TkCactivebgnd), nil, ZP);
- }
- switch(tks->relief) {
- case TKsunken:
- tkbevel(i, p, sw, tks->sl, ScaleBW, d, l);
- tkbevel(i, q, gw, 0, 1, l, d);
- break;
- case TKraised:
- tkbevel(i, p, sw, tks->sl, ScaleBW, l, d);
- tkbevel(i, q, gw, 0, 1, d, l);
- break;
- }
- tks->pixpos = p.y;
- tks->center = p.x + sw/2 + ScaleBW;
- if(tks->sv != BoolT)
- return;
- tkfprint(sv, tks->value);
- if(tks->digits > 0 && tks->digits < strlen(sv))
- sv[tks->digits] = '\0';
- p.x = r.min.x - ScalePad - stringwidth(e->font, sv);
- p.y = q.y;
- p.y -= fh/2;
- if (p.y < tks->pixmin)
- p.y = tks->pixmin;
- if (p.y + fh > tks->pixmax)
- p.y = tks->pixmax - fh;
- string(i, p, tkgc(e, fgnd), ZP, e->font, sv);
- }
- char*
- tkdrawscale(Tk *tk, Point orig)
- {
- Point p;
- TkEnv *env;
- TkScale *tks;
- Rectangle r, fr;
- Image *i;
- tks = TKobj(TkScale, tk);
- env = tk->env;
- r.min = ZP;
- r.max.x = tk->act.width + 2*tk->borderwidth;
- r.max.y = tk->act.height + 2*tk->borderwidth;
- i = tkitmp(env, r.max, TkCbackgnd);
- if(i == nil)
- return nil;
- if(tks->orient == Tkvertical)
- tkscalevert(tk, i);
- else
- tkscalehoriz(tk, i);
- tkdrawrelief(i, tk, ZP, TkCbackgnd, tk->relief);
- if (tkhaskeyfocus(tk)) {
- fr = insetrect(r, tk->borderwidth);
- tkbox(i, fr, tk->highlightwidth, tkgc(env, TkChighlightfgnd));
- }
- p.x = tk->act.x + orig.x;
- p.y = tk->act.y + orig.y;
- r = rectaddpt(r, p);
- draw(tkimageof(tk), r, i, nil, ZP);
- return nil;
- }
- /* Widget Commands (+ means implemented)
- +cget
- +configure
- +coords
- +get
- +identify
- +set
- */
- static char*
- tkscaleconf(Tk *tk, char *arg, char **val)
- {
- char *e;
- TkGeom g;
- int bd;
- TkOptab tko[3];
- TkScale *tks = TKobj(TkScale, tk);
- tko[0].ptr = tk;
- tko[0].optab = tkgeneric;
- tko[1].ptr = tks;
- tko[1].optab = opts;
- tko[2].ptr = nil;
- if(*arg == '\0')
- return tkconflist(tko, val);
- g = tk->req;
- bd = tk->borderwidth;
- e = tkparse(tk->env->top, arg, tko, nil);
- tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
- tkscalecheckvalue(tk);
- tksizescale(tk);
- tkgeomchg(tk, &g, bd);
- tk->dirty = tkrect(tk, 1);
- return e;
- }
- char*
- tkscaleposn(TkEnv *env, Tk *tk, char *arg, int *z)
- {
- int x, y;
- TkScale *tks = TKobj(TkScale, tk);
- char *e;
- e = tkfracword(env->top, &arg, &x, env);
- if(e != nil)
- return e;
- e = tkfracword(env->top, &arg, &y, env);
- if(e != nil)
- return e;
- x = TKF2I(x) + tk->borderwidth;
- y = TKF2I(y) + tk->borderwidth;
- if(tks->orient == Tkvertical) {
- if(z != nil) {
- z[0] = x;
- z[1] = y;
- }
- x = y;
- }
- else {
- if(z != nil) {
- z[0] = y;
- z[1] = x;
- }
- }
- if(x > tks->pixmin && x < tks->pixpos)
- return trough1;
- else if(x >= tks->pixpos && x < tks->pixpos+tks->sl+2*ScaleBW)
- return slider;
- else if(x >= tks->pixpos+tks->sl+2*ScaleBW && x < tks->pixmax)
- return trough2;
- return "";
- }
- static char*
- tkscaleident(Tk *tk, char *arg, char **val)
- {
- char *v;
- v = tkscaleposn(tk->env, tk, arg, nil);
- if(v == nil)
- return TkBadvl;
- return tkvalue(val, "%s", v);
- }
- static char*
- tkscalecoords(Tk *tk, char *arg, char **val)
- {
- int p, x, y, l, value;
- TkScale *tks = TKobj(TkScale, tk);
- char *e;
- value = tks->value;
- if(arg != nil && arg[0] != '\0') {
- e = tkfracword(tk->env->top, &arg, &value, tk->env);
- if (e != nil)
- return e;
- }
- value -= tks->from;
- p = tks->pixmax - tks->pixmin;
- l = TKF2I(tks->to-tks->from);
- if (l==0)
- p /= 2;
- else
- p = TKF2I(value*p/l);
- p += tks->pixmin;
- if(tks->orient == Tkvertical) {
- x = tks->center;
- y = p;
- }
- else {
- x = p;
- y = tks->center;
- }
- return tkvalue(val, "%d %d", x, y);
- }
- static char*
- tkscaleget(Tk *tk, char *arg, char **val)
- {
- int x, y, value, v, l;
- char buf[Tkminitem], *e;
- TkScale *tks = TKobj(TkScale, tk);
- value = tks->value;
- if(arg[0] != '\0') {
- e = tkfracword(tk->env->top, &arg, &x, tk->env);
- if (e != nil)
- return e;
- e = tkfracword(tk->env->top, &arg, &y, tk->env);
- if (e != nil)
- return e;
- if(tks->orient == Tkvertical)
- v = TKF2I(y) + tk->borderwidth;
- else
- v = TKF2I(x) + tk->borderwidth;
- if(v < tks->pixmin)
- value = tks->from;
- else
- if(v > tks->pixmax)
- value = tks->to;
- else {
- l = tks->pixmax-tks->pixmin;
- value = 0;
- if (l!=0)
- value = v * ((tks->to-tks->from)/l);
- value += tks->from;
- }
- if(tks->res > 0)
- value = (value/tks->res)*tks->res;
- }
- tkfprint(buf, value);
- return tkvalue(val, "%s", buf);
- }
- static char*
- tkscaleset(Tk *tk, char *arg, char **val)
- {
- TkScale *tks = TKobj(TkScale, tk);
- char *e;
- USED(val);
- e = tkfracword(tk->env->top, &arg, &tks->value, tk->env);
- if (e != nil)
- return e;
- tkscalecheckvalue(tk);
- tk->dirty = tkrect(tk, 1);
- return nil;
- }
- /* tkScaleMotion %x %y */
- static char*
- tkscalemotion(Tk *tk, char *arg, char **val)
- {
- int o, z[2];
- char *v;
- TkScale *tks = TKobj(TkScale, tk);
- extern int tkstylus;
- USED(val);
- v = tkscaleposn(tk->env, tk, arg, z);
- if(v == nil)
- return TkBadvl;
- o = tk->flag;
- if(v != slider || z[0] < tks->center-tks->sw || z[0] > tks->center+tks->sw)
- tk->flag &= ~Tkactivated;
- else if(tkstylus == 0 || tk->env->top->ctxt->mstate.b != 0)
- tk->flag |= Tkactivated;
- if((o & Tkactivated) != (tk->flag & Tkactivated))
- tk->dirty = tkrect(tk, 1);
- return nil;
- }
- static char*
- tkscaledrag(Tk *tk, char *arg, char **val)
- {
- int x, y, v;
- char *e, buf[Tkmaxitem], f[32];
- TkScale *tks = TKobj(TkScale, tk);
- USED(val);
- if((tks->flag & Dragging) == 0)
- return nil;
- if(tks->flag & Autorepeat)
- return nil;
- e = tkfracword(tk->env->top, &arg, &x, tk->env);
- if(e != nil)
- return e;
- e = tkfracword(tk->env->top, &arg, &y, tk->env);
- if(e != nil)
- return e;
- if(tks->orient == Tkvertical)
- v = TKF2I(y) + tk->borderwidth;
- else
- v = TKF2I(x) + tk->borderwidth;
- v -= tks->pix;
- x = tks->pixmax-tks->pixmin;
- if (x!=tks->sl)
- v = tks->base + (vlong)v * (tks->to-tks->from)/(x-tks->sl);
- else
- v = tks->base;
- if(tks->res > 0) {
- int a = tks->res / 2;
- if (v < 0)
- a = -a;
- v = ((v+a)/tks->res)*tks->res;
- }
- tks->value = v;
- tkscalecheckvalue(tk);
- if(tks->command != nil && tks->jump != BoolT) {
- tkfprint(f, tks->value);
- snprint(buf, sizeof(buf), "%s %s", tks->command, f);
- e = tkexec(tk->env->top, buf, nil);
- }
- tk->dirty = tkrect(tk, 1);
- return e;
- }
- static int
- sgn(int v)
- {
- return v >= 0 ? 1 : -1;
- }
- static char*
- stepscale(Tk *tk, char *pos, int *end)
- {
- TkScale *tks = TKobj(TkScale, tk);
- char *e, buf[Tkmaxitem], f[32];
- int s;
- s = sgn(tks->to - tks->from);
- if(pos == trough1) {
- tks->value -= s * tks->bigi;
- } else {
- /* trough2 */
- tks->value += s * tks->bigi;
- }
- s = !tkscalecheckvalue(tk);
- if (end != nil)
- *end = s;
- e = nil;
- if(tks->command != nil) {
- /* XXX perhaps should only send command if value has actually changed */
- tkfprint(f, tks->value);
- snprint(buf, sizeof(buf), "%s %s", tks->command, f);
- e = tkexec(tk->env->top, buf, nil);
- }
- return e;
- }
- static void
- screpeat(Tk *tk, void *v, int cancelled)
- {
- char *e, *pos;
- int repeat;
- TkScale *tks = TKobj(TkScale, tk);
- pos = v;
- if (cancelled) {
- tks->flag &= ~Autorepeat;
- return;
- }
- e = stepscale(tk, pos, &repeat);
- if(e != nil || !repeat) {
- tks->flag &= ~Autorepeat;
- tkcancelrepeat(tk);
- }
- tk->dirty = tkrect(tk, 1);
- tkupdate(tk->env->top);
- }
- static char*
- tkscalebut1p(Tk *tk, char *arg, char **val)
- {
- int z[2];
- char *v, *e;
- TkScale *tks = TKobj(TkScale, tk);
- int repeat;
- USED(val);
- v = tkscaleposn(tk->env, tk, arg, z);
- if(v == nil)
- return TkBadvl;
- e = nil;
- if(v[0] == '\0' || z[0] < tks->center-tks->sw || z[0] > tks->center+tks->sw)
- return nil;
- if(v == slider) {
- tks->flag |= Dragging;
- tks->relief = TKsunken;
- tks->pix = z[1];
- tks->base = tks->value;
- tkscalecheckvalue(tk);
- } else {
- e = stepscale(tk, v, &repeat);
- if (e == nil && repeat) {
- tks->flag |= Autorepeat;
- tkrepeat(tk, screpeat, v, TkRptpause, TkRptinterval);
- }
- }
- tk->dirty = tkrect(tk, 1);
- return e;
- }
- static char*
- tkscalebut1r(Tk *tk, char *arg, char **val)
- {
- TkScale *tks = TKobj(TkScale, tk);
- char *e, buf[Tkmaxitem], f[32];
- USED(val);
- USED(arg);
- if(tks->flag & Autorepeat) {
- tkcancelrepeat(tk);
- tks->flag &= ~Autorepeat;
- }
- e = nil;
- if (tks->flag & Dragging) {
- if (tks->command != nil && tks->jump == BoolT && (tks->flag & Dragging)) {
- tkfprint(f, tks->value);
- snprint(buf, sizeof(buf), "%s %s", tks->command, f);
- e = tkexec(tk->env->top, buf, nil);
- }
- tks->relief = TKraised;
- tks->flag &= ~Dragging;
- tk->dirty = tkrect(tk, 1);
- }
- return e;
- }
- static char*
- tkscalekey(Tk *tk, char *arg, char **val)
- {
- char *e;
- int key;
- char *pos = nil;
- USED(arg);
- USED(val);
- if(tk->flag & Tkdisabled)
- return nil;
- key = strtol(arg, nil, 0);
- if (key == Up || key == Left)
- pos = trough1;
- else if (key == Down || key == Right)
- pos = trough2;
- if (pos != nil) {
- e = stepscale(tk, pos, nil);
- tk->dirty = tkrect(tk, 1);
- return e;
- }
- return nil;
- }
- TkCmdtab tkscalecmd[] =
- {
- "cget", tkscalecget,
- "configure", tkscaleconf,
- "set", tkscaleset,
- "identify", tkscaleident,
- "get", tkscaleget,
- "coords", tkscalecoords,
- "tkScaleMotion", tkscalemotion,
- "tkScaleDrag", tkscaledrag,
- "tkScaleBut1P", tkscalebut1p,
- "tkScaleBut1R", tkscalebut1r,
- "tkScaleKey", tkscalekey,
- nil
- };
- TkMethod scalemethod = {
- "scale",
- tkscalecmd,
- tkfreescale,
- tkdrawscale
- };
|