/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkscale.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkscale.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkScale.c --   * tkScale.c --
5   *   *
6   *      This module implements a scale widgets for the Tk toolkit.   *      This module implements a scale widgets for the Tk toolkit.
7   *      A scale displays a slider that can be adjusted to change a   *      A scale displays a slider that can be adjusted to change a
8   *      value;  it also displays numeric labels and a textual label,   *      value;  it also displays numeric labels and a textual label,
9   *      if desired.   *      if desired.
10   *         *      
11   *      The modifications to use floating-point values are based on   *      The modifications to use floating-point values are based on
12   *      an implementation by Paul Mackerras.  The -variable option   *      an implementation by Paul Mackerras.  The -variable option
13   *      is due to Henning Schulzrinne.  All of these are used with   *      is due to Henning Schulzrinne.  All of these are used with
14   *      permission.   *      permission.
15   *   *
16   * Copyright (c) 1990-1994 The Regents of the University of California.   * Copyright (c) 1990-1994 The Regents of the University of California.
17   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
18   * Copyright (c) 1998-2000 by Scriptics Corporation.   * Copyright (c) 1998-2000 by Scriptics Corporation.
19   *   *
20   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
21   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
22   *   *
23   * RCS: @(#) $Id: tkscale.c,v 1.1.1.1 2001/06/13 05:07:45 dtashley Exp $   * RCS: @(#) $Id: tkscale.c,v 1.1.1.1 2001/06/13 05:07:45 dtashley Exp $
24   */   */
25    
26  #include "tkPort.h"  #include "tkPort.h"
27  #include "default.h"  #include "default.h"
28  #include "tkInt.h"  #include "tkInt.h"
29  #include "tclMath.h"  #include "tclMath.h"
30  #include "tkScale.h"  #include "tkScale.h"
31    
32  /*  /*
33   * The following table defines the legal values for the -orient option.   * The following table defines the legal values for the -orient option.
34   * It is used together with the "enum orient" declaration in tkScale.h.   * It is used together with the "enum orient" declaration in tkScale.h.
35   */   */
36    
37  static char *orientStrings[] = {  static char *orientStrings[] = {
38      "horizontal", "vertical", (char *) NULL      "horizontal", "vertical", (char *) NULL
39  };  };
40    
41  /*  /*
42   * The following table defines the legal values for the -state option.   * The following table defines the legal values for the -state option.
43   * It is used together with the "enum state" declaration in tkScale.h.   * It is used together with the "enum state" declaration in tkScale.h.
44   */   */
45    
46  static char *stateStrings[] = {  static char *stateStrings[] = {
47      "active", "disabled", "normal", (char *) NULL      "active", "disabled", "normal", (char *) NULL
48  };  };
49    
50  static Tk_OptionSpec optionSpecs[] = {  static Tk_OptionSpec optionSpecs[] = {
51      {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",      {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
52          DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder),          DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder),
53          0, (ClientData) DEF_SCALE_ACTIVE_BG_MONO, 0},          0, (ClientData) DEF_SCALE_ACTIVE_BG_MONO, 0},
54      {TK_OPTION_BORDER, "-background", "background", "Background",      {TK_OPTION_BORDER, "-background", "background", "Background",
55          DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder),          DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder),
56          0, (ClientData) DEF_SCALE_BG_MONO, 0},          0, (ClientData) DEF_SCALE_BG_MONO, 0},
57      {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",      {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
58          DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement),          DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement),
59          0, 0, 0},          0, 0, 0},
60      {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,      {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
61          (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
62      {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,      {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
63          (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
64      {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",      {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
65          DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth),          DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth),
66          0, 0, 0},          0, 0, 0},
67      {TK_OPTION_STRING, "-command", "command", "Command",      {TK_OPTION_STRING, "-command", "command", "Command",
68          DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command),          DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command),
69          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
70      {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",      {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
71          DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor),          DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor),
72          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
73      {TK_OPTION_INT, "-digits", "digits", "Digits",      {TK_OPTION_INT, "-digits", "digits", "Digits",
74          DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits),          DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits),
75          0, 0, 0},          0, 0, 0},
76      {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,      {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
77          (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},          (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
78      {TK_OPTION_FONT, "-font", "font", "Font",      {TK_OPTION_FONT, "-font", "font", "Font",
79          DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0},          DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0},
80      {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",      {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
81          DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0,          DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0,
82          (ClientData) DEF_SCALE_FG_MONO, 0},          (ClientData) DEF_SCALE_FG_MONO, 0},
83      {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1,      {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1,
84          Tk_Offset(TkScale, fromValue), 0, 0, 0},          Tk_Offset(TkScale, fromValue), 0, 0, 0},
85      {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",      {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
86          "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR,          "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR,
87          -1, Tk_Offset(TkScale, highlightBorder),          -1, Tk_Offset(TkScale, highlightBorder),
88          0, (ClientData) DEF_SCALE_HIGHLIGHT_BG_MONO, 0},          0, (ClientData) DEF_SCALE_HIGHLIGHT_BG_MONO, 0},
89      {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",      {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
90          DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr),          DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr),
91          0, 0, 0},          0, 0, 0},
92      {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",      {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
93          "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1,          "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1,
94          Tk_Offset(TkScale, highlightWidth), 0, 0, 0},          Tk_Offset(TkScale, highlightWidth), 0, 0, 0},
95      {TK_OPTION_STRING, "-label", "label", "Label",      {TK_OPTION_STRING, "-label", "label", "Label",
96          DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label),          DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label),
97          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
98      {TK_OPTION_PIXELS, "-length", "length", "Length",      {TK_OPTION_PIXELS, "-length", "length", "Length",
99          DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0},          DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0},
100      {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",      {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
101          DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient),          DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient),
102          0, (ClientData) orientStrings, 0},          0, (ClientData) orientStrings, 0},
103      {TK_OPTION_RELIEF, "-relief", "relief", "Relief",      {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
104          DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0},          DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0},
105      {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",      {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
106          DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay),          DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay),
107          0, 0, 0},          0, 0, 0},
108      {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",      {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
109          DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval),          DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval),
110          0, 0, 0},          0, 0, 0},
111      {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution",      {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution",
112          DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution),          DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution),
113          0, 0, 0},          0, 0, 0},
114      {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue",      {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue",
115          DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue),          DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue),
116          0, 0, 0},          0, 0, 0},
117      {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength",      {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
118          DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength),          DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength),
119          0, 0, 0},          0, 0, 0},
120      {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",      {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
121          DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief),          DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief),
122          0, 0, 0},          0, 0, 0},
123      {TK_OPTION_STRING_TABLE, "-state", "state", "State",      {TK_OPTION_STRING_TABLE, "-state", "state", "State",
124          DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state),          DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state),
125          0, (ClientData) stateStrings, 0},          0, (ClientData) stateStrings, 0},
126      {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",      {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
127          DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1,          DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1,
128          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
129      {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",      {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
130          DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval),          DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval),
131          0, 0, 0},          0, 0, 0},
132      {TK_OPTION_DOUBLE, "-to", "to", "To",      {TK_OPTION_DOUBLE, "-to", "to", "To",
133          DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0},          DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0},
134      {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background",      {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background",
135          DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr),          DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr),
136          0, (ClientData) DEF_SCALE_TROUGH_MONO, 0},          0, (ClientData) DEF_SCALE_TROUGH_MONO, 0},
137      {TK_OPTION_STRING, "-variable", "variable", "Variable",      {TK_OPTION_STRING, "-variable", "variable", "Variable",
138          DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1,          DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1,
139          TK_OPTION_NULL_OK, 0, 0},          TK_OPTION_NULL_OK, 0, 0},
140      {TK_OPTION_PIXELS, "-width", "width", "Width",      {TK_OPTION_PIXELS, "-width", "width", "Width",
141          DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0},          DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0},
142      {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,      {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
143          (char *) NULL, 0, -1, 0, 0, 0}          (char *) NULL, 0, -1, 0, 0, 0}
144  };  };
145    
146  /*  /*
147   * The following tables define the scale widget commands and map the   * The following tables define the scale widget commands and map the
148   * indexes into the string tables into a single enumerated type used   * indexes into the string tables into a single enumerated type used
149   * to dispatch the scale widget command.   * to dispatch the scale widget command.
150   */   */
151    
152  static char *commandNames[] = {  static char *commandNames[] = {
153      "cget", "configure", "coords", "get", "identify", "set", (char *) NULL      "cget", "configure", "coords", "get", "identify", "set", (char *) NULL
154  };  };
155    
156  enum command {  enum command {
157      COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,      COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,
158      COMMAND_IDENTIFY, COMMAND_SET      COMMAND_IDENTIFY, COMMAND_SET
159  };  };
160    
161  /*  /*
162   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
163   */   */
164    
165  static void             ComputeFormat _ANSI_ARGS_((TkScale *scalePtr));  static void             ComputeFormat _ANSI_ARGS_((TkScale *scalePtr));
166  static void             ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr));  static void             ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr));
167  static int              ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp,  static int              ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp,
168                              TkScale *scalePtr, int objc,                              TkScale *scalePtr, int objc,
169                              Tcl_Obj *CONST objv[]));                              Tcl_Obj *CONST objv[]));
170  static void             DestroyScale _ANSI_ARGS_((char *memPtr));  static void             DestroyScale _ANSI_ARGS_((char *memPtr));
171  static void             ScaleCmdDeletedProc _ANSI_ARGS_((  static void             ScaleCmdDeletedProc _ANSI_ARGS_((
172                              ClientData clientData));                              ClientData clientData));
173  static void             ScaleEventProc _ANSI_ARGS_((ClientData clientData,  static void             ScaleEventProc _ANSI_ARGS_((ClientData clientData,
174                              XEvent *eventPtr));                              XEvent *eventPtr));
175  static char *           ScaleVarProc _ANSI_ARGS_((ClientData clientData,  static char *           ScaleVarProc _ANSI_ARGS_((ClientData clientData,
176                              Tcl_Interp *interp, char *name1, char *name2,                              Tcl_Interp *interp, char *name1, char *name2,
177                              int flags));                              int flags));
178  static int              ScaleWidgetObjCmd _ANSI_ARGS_((ClientData clientData,  static int              ScaleWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
179                              Tcl_Interp *interp, int objc,                              Tcl_Interp *interp, int objc,
180                              Tcl_Obj *CONST objv[]));                              Tcl_Obj *CONST objv[]));
181  static void             ScaleWorldChanged _ANSI_ARGS_((  static void             ScaleWorldChanged _ANSI_ARGS_((
182                              ClientData instanceData));                              ClientData instanceData));
183  static void             ScaleSetVariable _ANSI_ARGS_((TkScale *scalePtr));  static void             ScaleSetVariable _ANSI_ARGS_((TkScale *scalePtr));
184    
185  /*  /*
186   * The structure below defines scale class behavior by means of procedures   * The structure below defines scale class behavior by means of procedures
187   * that can be invoked from generic window code.   * that can be invoked from generic window code.
188   */   */
189    
190  static TkClassProcs scaleClass = {  static TkClassProcs scaleClass = {
191      NULL,                       /* createProc. */      NULL,                       /* createProc. */
192      ScaleWorldChanged,          /* geometryProc. */      ScaleWorldChanged,          /* geometryProc. */
193      NULL                        /* modalProc. */      NULL                        /* modalProc. */
194  };  };
195    
196    
197  /*  /*
198   *--------------------------------------------------------------   *--------------------------------------------------------------
199   *   *
200   * Tk_ScaleObjCmd --   * Tk_ScaleObjCmd --
201   *   *
202   *      This procedure is invoked to process the "scale" Tcl   *      This procedure is invoked to process the "scale" Tcl
203   *      command.  See the user documentation for details on what   *      command.  See the user documentation for details on what
204   *      it does.   *      it does.
205   *   *
206   * Results:   * Results:
207   *      A standard Tcl result.   *      A standard Tcl result.
208   *   *
209   * Side effects:   * Side effects:
210   *      See the user documentation.   *      See the user documentation.
211   *   *
212   *--------------------------------------------------------------   *--------------------------------------------------------------
213   */   */
214    
215  int  int
216  Tk_ScaleObjCmd(clientData, interp, objc, objv)  Tk_ScaleObjCmd(clientData, interp, objc, objv)
217      ClientData clientData;      /* Either NULL or pointer to option table. */      ClientData clientData;      /* Either NULL or pointer to option table. */
218      Tcl_Interp *interp;         /* Current interpreter. */      Tcl_Interp *interp;         /* Current interpreter. */
219      int objc;                   /* Number of arguments. */      int objc;                   /* Number of arguments. */
220      Tcl_Obj *CONST objv[];      /* Argument values. */      Tcl_Obj *CONST objv[];      /* Argument values. */
221  {  {
222      register TkScale *scalePtr;      register TkScale *scalePtr;
223      Tk_OptionTable optionTable;      Tk_OptionTable optionTable;
224      Tk_Window tkwin;      Tk_Window tkwin;
225    
226      optionTable = (Tk_OptionTable) clientData;      optionTable = (Tk_OptionTable) clientData;
227      if (optionTable == NULL) {      if (optionTable == NULL) {
228          Tcl_CmdInfo info;          Tcl_CmdInfo info;
229          char *name;          char *name;
230    
231          /*          /*
232           * We haven't created the option table for this widget class           * We haven't created the option table for this widget class
233           * yet.  Do it now and save the table as the clientData for           * yet.  Do it now and save the table as the clientData for
234           * the command, so we'll have access to it in future           * the command, so we'll have access to it in future
235           * invocations of the command.           * invocations of the command.
236           */           */
237    
238          optionTable = Tk_CreateOptionTable(interp, optionSpecs);          optionTable = Tk_CreateOptionTable(interp, optionSpecs);
239          name = Tcl_GetString(objv[0]);          name = Tcl_GetString(objv[0]);
240          Tcl_GetCommandInfo(interp, name, &info);          Tcl_GetCommandInfo(interp, name, &info);
241          info.objClientData = (ClientData) optionTable;          info.objClientData = (ClientData) optionTable;
242          Tcl_SetCommandInfo(interp, name, &info);          Tcl_SetCommandInfo(interp, name, &info);
243      }      }
244    
245      if (objc < 2) {      if (objc < 2) {
246          Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");          Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
247          return TCL_ERROR;          return TCL_ERROR;
248      }      }
249    
250      tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),      tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
251              Tcl_GetString(objv[1]), (char *) NULL);              Tcl_GetString(objv[1]), (char *) NULL);
252      if (tkwin == NULL) {      if (tkwin == NULL) {
253          return TCL_ERROR;          return TCL_ERROR;
254      }      }
255    
256      Tk_SetClass(tkwin, "Scale");      Tk_SetClass(tkwin, "Scale");
257      scalePtr = TkpCreateScale(tkwin);      scalePtr = TkpCreateScale(tkwin);
258    
259      /*      /*
260       * Initialize fields that won't be initialized by ConfigureScale,       * Initialize fields that won't be initialized by ConfigureScale,
261       * or which ConfigureScale expects to have reasonable values       * or which ConfigureScale expects to have reasonable values
262       * (e.g. resource pointers).       * (e.g. resource pointers).
263       */       */
264    
265      scalePtr->tkwin             = tkwin;      scalePtr->tkwin             = tkwin;
266      scalePtr->display           = Tk_Display(tkwin);      scalePtr->display           = Tk_Display(tkwin);
267      scalePtr->interp            = interp;      scalePtr->interp            = interp;
268      scalePtr->widgetCmd         = Tcl_CreateObjCommand(interp,      scalePtr->widgetCmd         = Tcl_CreateObjCommand(interp,
269              Tk_PathName(scalePtr->tkwin), ScaleWidgetObjCmd,              Tk_PathName(scalePtr->tkwin), ScaleWidgetObjCmd,
270              (ClientData) scalePtr, ScaleCmdDeletedProc);              (ClientData) scalePtr, ScaleCmdDeletedProc);
271      scalePtr->optionTable       = optionTable;      scalePtr->optionTable       = optionTable;
272      scalePtr->orient            = ORIENT_VERTICAL;      scalePtr->orient            = ORIENT_VERTICAL;
273      scalePtr->width             = 0;      scalePtr->width             = 0;
274      scalePtr->length            = 0;      scalePtr->length            = 0;
275      scalePtr->value             = 0.0;      scalePtr->value             = 0.0;
276      scalePtr->varNamePtr        = NULL;      scalePtr->varNamePtr        = NULL;
277      scalePtr->fromValue         = 0.0;      scalePtr->fromValue         = 0.0;
278      scalePtr->toValue           = 0.0;      scalePtr->toValue           = 0.0;
279      scalePtr->tickInterval      = 0.0;      scalePtr->tickInterval      = 0.0;
280      scalePtr->resolution        = 1.0;      scalePtr->resolution        = 1.0;
281      scalePtr->digits            = 0;      scalePtr->digits            = 0;
282      scalePtr->bigIncrement      = 0.0;      scalePtr->bigIncrement      = 0.0;
283      scalePtr->command           = NULL;      scalePtr->command           = NULL;
284      scalePtr->repeatDelay       = 0;      scalePtr->repeatDelay       = 0;
285      scalePtr->repeatInterval    = 0;      scalePtr->repeatInterval    = 0;
286      scalePtr->label             = NULL;      scalePtr->label             = NULL;
287      scalePtr->labelLength       = 0;      scalePtr->labelLength       = 0;
288      scalePtr->state             = STATE_NORMAL;      scalePtr->state             = STATE_NORMAL;
289      scalePtr->borderWidth       = 0;      scalePtr->borderWidth       = 0;
290      scalePtr->bgBorder          = NULL;      scalePtr->bgBorder          = NULL;
291      scalePtr->activeBorder      = NULL;      scalePtr->activeBorder      = NULL;
292      scalePtr->sliderRelief      = TK_RELIEF_RAISED;      scalePtr->sliderRelief      = TK_RELIEF_RAISED;
293      scalePtr->troughColorPtr    = NULL;      scalePtr->troughColorPtr    = NULL;
294      scalePtr->troughGC          = None;      scalePtr->troughGC          = None;
295      scalePtr->copyGC            = None;      scalePtr->copyGC            = None;
296      scalePtr->tkfont            = NULL;      scalePtr->tkfont            = NULL;
297      scalePtr->textColorPtr      = NULL;      scalePtr->textColorPtr      = NULL;
298      scalePtr->textGC            = None;      scalePtr->textGC            = None;
299      scalePtr->relief            = TK_RELIEF_FLAT;      scalePtr->relief            = TK_RELIEF_FLAT;
300      scalePtr->highlightWidth    = 0;      scalePtr->highlightWidth    = 0;
301      scalePtr->highlightBorder   = NULL;      scalePtr->highlightBorder   = NULL;
302      scalePtr->highlightColorPtr = NULL;      scalePtr->highlightColorPtr = NULL;
303      scalePtr->inset             = 0;      scalePtr->inset             = 0;
304      scalePtr->sliderLength      = 0;      scalePtr->sliderLength      = 0;
305      scalePtr->showValue         = 0;      scalePtr->showValue         = 0;
306      scalePtr->horizLabelY       = 0;      scalePtr->horizLabelY       = 0;
307      scalePtr->horizValueY       = 0;      scalePtr->horizValueY       = 0;
308      scalePtr->horizTroughY      = 0;      scalePtr->horizTroughY      = 0;
309      scalePtr->horizTickY        = 0;      scalePtr->horizTickY        = 0;
310      scalePtr->vertTickRightX    = 0;      scalePtr->vertTickRightX    = 0;
311      scalePtr->vertValueRightX   = 0;      scalePtr->vertValueRightX   = 0;
312      scalePtr->vertTroughX       = 0;      scalePtr->vertTroughX       = 0;
313      scalePtr->vertLabelX        = 0;      scalePtr->vertLabelX        = 0;
314      scalePtr->fontHeight        = 0;      scalePtr->fontHeight        = 0;
315      scalePtr->cursor            = None;      scalePtr->cursor            = None;
316      scalePtr->takeFocusPtr      = NULL;      scalePtr->takeFocusPtr      = NULL;
317      scalePtr->flags             = NEVER_SET;      scalePtr->flags             = NEVER_SET;
318    
319      TkSetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);      TkSetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);
320      Tk_CreateEventHandler(scalePtr->tkwin,      Tk_CreateEventHandler(scalePtr->tkwin,
321              ExposureMask|StructureNotifyMask|FocusChangeMask,              ExposureMask|StructureNotifyMask|FocusChangeMask,
322              ScaleEventProc, (ClientData) scalePtr);              ScaleEventProc, (ClientData) scalePtr);
323    
324      if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin)      if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin)
325              != TCL_OK) ||              != TCL_OK) ||
326              (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {              (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {
327          Tk_DestroyWindow(scalePtr->tkwin);          Tk_DestroyWindow(scalePtr->tkwin);
328          return TCL_ERROR;          return TCL_ERROR;
329      }      }
330    
331      Tcl_SetResult(interp, Tk_PathName(scalePtr->tkwin), TCL_STATIC);      Tcl_SetResult(interp, Tk_PathName(scalePtr->tkwin), TCL_STATIC);
332      return TCL_OK;      return TCL_OK;
333  }  }
334    
335  /*  /*
336   *--------------------------------------------------------------   *--------------------------------------------------------------
337   *   *
338   * ScaleWidgetObjCmd --   * ScaleWidgetObjCmd --
339   *   *
340   *      This procedure is invoked to process the Tcl command   *      This procedure is invoked to process the Tcl command
341   *      that corresponds to a widget managed by this module.   *      that corresponds to a widget managed by this module.
342   *      See the user documentation for details on what it does.   *      See the user documentation for details on what it does.
343   *   *
344   * Results:   * Results:
345   *      A standard Tcl result.   *      A standard Tcl result.
346   *   *
347   * Side effects:   * Side effects:
348   *      See the user documentation.   *      See the user documentation.
349   *   *
350   *--------------------------------------------------------------   *--------------------------------------------------------------
351   */   */
352    
353  static int  static int
354  ScaleWidgetObjCmd(clientData, interp, objc, objv)  ScaleWidgetObjCmd(clientData, interp, objc, objv)
355      ClientData clientData;              /* Information about scale      ClientData clientData;              /* Information about scale
356                                           * widget. */                                           * widget. */
357      Tcl_Interp *interp;                 /* Current interpreter. */      Tcl_Interp *interp;                 /* Current interpreter. */
358      int objc;                           /* Number of arguments. */      int objc;                           /* Number of arguments. */
359      Tcl_Obj *CONST objv[];              /* Argument strings. */      Tcl_Obj *CONST objv[];              /* Argument strings. */
360  {  {
361      TkScale *scalePtr = (TkScale *) clientData;      TkScale *scalePtr = (TkScale *) clientData;
362      Tcl_Obj *objPtr;      Tcl_Obj *objPtr;
363      int index, result;      int index, result;
364    
365      if (objc < 2) {      if (objc < 2) {
366          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");          Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
367          return TCL_ERROR;          return TCL_ERROR;
368      }      }
369      result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,      result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
370              "option", 0, &index);              "option", 0, &index);
371      if (result != TCL_OK) {      if (result != TCL_OK) {
372          return result;          return result;
373      }      }
374      Tcl_Preserve((ClientData) scalePtr);      Tcl_Preserve((ClientData) scalePtr);
375    
376      switch (index) {      switch (index) {
377          case COMMAND_CGET: {          case COMMAND_CGET: {
378              if (objc != 3) {              if (objc != 3) {
379                  Tcl_WrongNumArgs(interp, 1, objv, "cget option");                  Tcl_WrongNumArgs(interp, 1, objv, "cget option");
380                  goto error;                  goto error;
381              }              }
382              objPtr = Tk_GetOptionValue(interp, (char *) scalePtr,              objPtr = Tk_GetOptionValue(interp, (char *) scalePtr,
383                      scalePtr->optionTable, objv[2], scalePtr->tkwin);                      scalePtr->optionTable, objv[2], scalePtr->tkwin);
384              if (objPtr == NULL) {              if (objPtr == NULL) {
385                   goto error;                   goto error;
386              } else {              } else {
387                  Tcl_SetObjResult(interp, objPtr);                  Tcl_SetObjResult(interp, objPtr);
388              }              }
389              break;              break;
390          }          }
391          case COMMAND_CONFIGURE: {          case COMMAND_CONFIGURE: {
392              if (objc <= 3) {              if (objc <= 3) {
393                  objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr,                  objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr,
394                          scalePtr->optionTable,                          scalePtr->optionTable,
395                          (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,                          (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
396                          scalePtr->tkwin);                          scalePtr->tkwin);
397                  if (objPtr == NULL) {                  if (objPtr == NULL) {
398                      goto error;                      goto error;
399                  } else {                  } else {
400                      Tcl_SetObjResult(interp, objPtr);                      Tcl_SetObjResult(interp, objPtr);
401                  }                  }
402              } else {              } else {
403                  result = ConfigureScale(interp, scalePtr, objc-2, objv+2);                  result = ConfigureScale(interp, scalePtr, objc-2, objv+2);
404              }              }
405              break;              break;
406          }          }
407          case COMMAND_COORDS: {          case COMMAND_COORDS: {
408              int x, y ;              int x, y ;
409              double value;              double value;
410              char buf[TCL_INTEGER_SPACE * 2];              char buf[TCL_INTEGER_SPACE * 2];
411    
412              if ((objc != 2) && (objc != 3)) {              if ((objc != 2) && (objc != 3)) {
413                  Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");                  Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
414                  goto error;                  goto error;
415              }              }
416              if (objc == 3) {              if (objc == 3) {
417                  if (Tcl_GetDoubleFromObj(interp, objv[2], &value)                  if (Tcl_GetDoubleFromObj(interp, objv[2], &value)
418                          != TCL_OK) {                          != TCL_OK) {
419                      goto error;                      goto error;
420                  }                  }
421              } else {              } else {
422                  value = scalePtr->value;                  value = scalePtr->value;
423              }              }
424              if (scalePtr->orient == ORIENT_VERTICAL) {              if (scalePtr->orient == ORIENT_VERTICAL) {
425                  x = scalePtr->vertTroughX + scalePtr->width/2                  x = scalePtr->vertTroughX + scalePtr->width/2
426                          + scalePtr->borderWidth;                          + scalePtr->borderWidth;
427                  y = TkScaleValueToPixel(scalePtr, value);                  y = TkScaleValueToPixel(scalePtr, value);
428              } else {              } else {
429                  x = TkScaleValueToPixel(scalePtr, value);                  x = TkScaleValueToPixel(scalePtr, value);
430                  y = scalePtr->horizTroughY + scalePtr->width/2                  y = scalePtr->horizTroughY + scalePtr->width/2
431                          + scalePtr->borderWidth;                          + scalePtr->borderWidth;
432              }              }
433              sprintf(buf, "%d %d", x, y);              sprintf(buf, "%d %d", x, y);
434              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
435              break;              break;
436          }          }
437          case COMMAND_GET: {          case COMMAND_GET: {
438              double value;              double value;
439              int x, y;              int x, y;
440              char buf[TCL_DOUBLE_SPACE];              char buf[TCL_DOUBLE_SPACE];
441    
442              if ((objc != 2) && (objc != 4)) {              if ((objc != 2) && (objc != 4)) {
443                  Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");                  Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
444                  goto error;                  goto error;
445              }              }
446              if (objc == 2) {              if (objc == 2) {
447                  value = scalePtr->value;                  value = scalePtr->value;
448              } else {              } else {
449                  if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)                  if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
450                          || (Tcl_GetIntFromObj(interp, objv[3], &y)                          || (Tcl_GetIntFromObj(interp, objv[3], &y)
451                          != TCL_OK)) {                          != TCL_OK)) {
452                      goto error;                      goto error;
453                  }                  }
454                  value = TkScalePixelToValue(scalePtr, x, y);                  value = TkScalePixelToValue(scalePtr, x, y);
455              }              }
456              sprintf(buf, scalePtr->format, value);              sprintf(buf, scalePtr->format, value);
457              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
458              break;              break;
459          }          }
460          case COMMAND_IDENTIFY: {          case COMMAND_IDENTIFY: {
461              int x, y, thing;              int x, y, thing;
462    
463              if (objc != 4) {              if (objc != 4) {
464                  Tcl_WrongNumArgs(interp, 1, objv, "identify x y");                  Tcl_WrongNumArgs(interp, 1, objv, "identify x y");
465                  goto error;                  goto error;
466              }              }
467              if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)              if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
468                      || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {                      || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
469                  goto error;                  goto error;
470              }              }
471              thing = TkpScaleElement(scalePtr, x,y);              thing = TkpScaleElement(scalePtr, x,y);
472              switch (thing) {              switch (thing) {
473                  case TROUGH1:                  case TROUGH1:
474                      Tcl_SetResult(interp, "trough1", TCL_STATIC);                      Tcl_SetResult(interp, "trough1", TCL_STATIC);
475                      break;                      break;
476                  case SLIDER:                  case SLIDER:
477                      Tcl_SetResult(interp, "slider", TCL_STATIC);                      Tcl_SetResult(interp, "slider", TCL_STATIC);
478                      break;                      break;
479                  case TROUGH2:                  case TROUGH2:
480                      Tcl_SetResult(interp, "trough2", TCL_STATIC);                      Tcl_SetResult(interp, "trough2", TCL_STATIC);
481                      break;                      break;
482              }              }
483              break;              break;
484          }          }
485          case COMMAND_SET: {          case COMMAND_SET: {
486              double value;              double value;
487    
488              if (objc != 3) {              if (objc != 3) {
489                  Tcl_WrongNumArgs(interp, 1, objv, "set value");                  Tcl_WrongNumArgs(interp, 1, objv, "set value");
490                  goto error;                  goto error;
491              }              }
492              if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {              if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {
493                  goto error;                  goto error;
494              }              }
495              if (scalePtr->state != STATE_DISABLED) {              if (scalePtr->state != STATE_DISABLED) {
496                TkScaleSetValue(scalePtr, value, 1, 1);                TkScaleSetValue(scalePtr, value, 1, 1);
497              }              }
498              break;              break;
499          }          }
500      }      }
501      Tcl_Release((ClientData) scalePtr);      Tcl_Release((ClientData) scalePtr);
502      return result;      return result;
503    
504      error:      error:
505      Tcl_Release((ClientData) scalePtr);      Tcl_Release((ClientData) scalePtr);
506      return TCL_ERROR;      return TCL_ERROR;
507  }  }
508    
509  /*  /*
510   *----------------------------------------------------------------------   *----------------------------------------------------------------------
511   *   *
512   * DestroyScale --   * DestroyScale --
513   *   *
514   *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release   *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
515   *      to clean up the internal structure of a button at a safe time   *      to clean up the internal structure of a button at a safe time
516   *      (when no-one is using it anymore).   *      (when no-one is using it anymore).
517   *   *
518   * Results:   * Results:
519   *      None.   *      None.
520   *   *
521   * Side effects:   * Side effects:
522   *      Everything associated with the scale is freed up.   *      Everything associated with the scale is freed up.
523   *   *
524   *----------------------------------------------------------------------   *----------------------------------------------------------------------
525   */   */
526    
527  static void  static void
528  DestroyScale(memPtr)  DestroyScale(memPtr)
529      char *memPtr;       /* Info about scale widget. */      char *memPtr;       /* Info about scale widget. */
530  {  {
531      register TkScale *scalePtr = (TkScale *) memPtr;      register TkScale *scalePtr = (TkScale *) memPtr;
532    
533      scalePtr->flags |= SCALE_DELETED;      scalePtr->flags |= SCALE_DELETED;
534    
535      Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);      Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
536      if (scalePtr->flags & REDRAW_PENDING) {      if (scalePtr->flags & REDRAW_PENDING) {
537          Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);          Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);
538      }      }
539    
540      /*      /*
541       * Free up all the stuff that requires special handling, then       * Free up all the stuff that requires special handling, then
542       * let Tk_FreeOptions handle all the standard option-related       * let Tk_FreeOptions handle all the standard option-related
543       * stuff.       * stuff.
544       */       */
545    
546      if (scalePtr->varNamePtr != NULL) {      if (scalePtr->varNamePtr != NULL) {
547          Tcl_UntraceVar(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr),          Tcl_UntraceVar(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr),
548                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
549                  ScaleVarProc, (ClientData) scalePtr);                  ScaleVarProc, (ClientData) scalePtr);
550      }      }
551      if (scalePtr->troughGC != None) {      if (scalePtr->troughGC != None) {
552          Tk_FreeGC(scalePtr->display, scalePtr->troughGC);          Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
553      }      }
554      if (scalePtr->copyGC != None) {      if (scalePtr->copyGC != None) {
555          Tk_FreeGC(scalePtr->display, scalePtr->copyGC);          Tk_FreeGC(scalePtr->display, scalePtr->copyGC);
556      }      }
557      if (scalePtr->textGC != None) {      if (scalePtr->textGC != None) {
558          Tk_FreeGC(scalePtr->display, scalePtr->textGC);          Tk_FreeGC(scalePtr->display, scalePtr->textGC);
559      }      }
560      Tk_FreeConfigOptions((char *) scalePtr, scalePtr->optionTable,      Tk_FreeConfigOptions((char *) scalePtr, scalePtr->optionTable,
561              scalePtr->tkwin);              scalePtr->tkwin);
562      scalePtr->tkwin = NULL;      scalePtr->tkwin = NULL;
563      TkpDestroyScale(scalePtr);      TkpDestroyScale(scalePtr);
564  }  }
565    
566  /*  /*
567   *----------------------------------------------------------------------   *----------------------------------------------------------------------
568   *   *
569   * ConfigureScale --   * ConfigureScale --
570   *   *
571   *      This procedure is called to process an argv/argc list, plus   *      This procedure is called to process an argv/argc list, plus
572   *      the Tk option database, in order to configure (or   *      the Tk option database, in order to configure (or
573   *      reconfigure) a scale widget.   *      reconfigure) a scale widget.
574   *   *
575   * Results:   * Results:
576   *      The return value is a standard Tcl result.  If TCL_ERROR is   *      The return value is a standard Tcl result.  If TCL_ERROR is
577   *      returned, then the interp's result contains an error message.   *      returned, then the interp's result contains an error message.
578   *   *
579   * Side effects:   * Side effects:
580   *      Configuration information, such as colors, border width,   *      Configuration information, such as colors, border width,
581   *      etc. get set for scalePtr;  old resources get freed,   *      etc. get set for scalePtr;  old resources get freed,
582   *      if there were any.   *      if there were any.
583   *   *
584   *----------------------------------------------------------------------   *----------------------------------------------------------------------
585   */   */
586    
587  static int  static int
588  ConfigureScale(interp, scalePtr, objc, objv)  ConfigureScale(interp, scalePtr, objc, objv)
589      Tcl_Interp *interp;         /* Used for error reporting. */      Tcl_Interp *interp;         /* Used for error reporting. */
590      register TkScale *scalePtr; /* Information about widget;  may or may      register TkScale *scalePtr; /* Information about widget;  may or may
591                                   * not already have values for some fields. */                                   * not already have values for some fields. */
592      int objc;                   /* Number of valid entries in objv. */      int objc;                   /* Number of valid entries in objv. */
593      Tcl_Obj *CONST objv[];      /* Argument values. */      Tcl_Obj *CONST objv[];      /* Argument values. */
594  {  {
595      Tk_SavedOptions savedOptions;      Tk_SavedOptions savedOptions;
596      Tcl_Obj *errorResult = NULL;      Tcl_Obj *errorResult = NULL;
597      int error;      int error;
598      double oldValue = scalePtr->value;      double oldValue = scalePtr->value;
599    
600      /*      /*
601       * Eliminate any existing trace on a variable monitored by the scale.       * Eliminate any existing trace on a variable monitored by the scale.
602       */       */
603    
604      if (scalePtr->varNamePtr != NULL) {      if (scalePtr->varNamePtr != NULL) {
605          Tcl_UntraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),          Tcl_UntraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
606                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
607                  ScaleVarProc, (ClientData) scalePtr);                  ScaleVarProc, (ClientData) scalePtr);
608      }      }
609    
610      for (error = 0; error <= 1; error++) {      for (error = 0; error <= 1; error++) {
611          if (!error) {          if (!error) {
612              /*              /*
613               * First pass: set options to new values.               * First pass: set options to new values.
614               */               */
615    
616              if (Tk_SetOptions(interp, (char *) scalePtr,              if (Tk_SetOptions(interp, (char *) scalePtr,
617                      scalePtr->optionTable, objc, objv,                      scalePtr->optionTable, objc, objv,
618                      scalePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {                      scalePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
619                  continue;                  continue;
620              }              }
621          } else {          } else {
622              /*              /*
623               * Second pass: restore options to old values.               * Second pass: restore options to old values.
624               */               */
625    
626              errorResult = Tcl_GetObjResult(interp);              errorResult = Tcl_GetObjResult(interp);
627              Tcl_IncrRefCount(errorResult);              Tcl_IncrRefCount(errorResult);
628              Tk_RestoreSavedOptions(&savedOptions);              Tk_RestoreSavedOptions(&savedOptions);
629          }          }
630    
631          /*          /*
632           * If the scale is tied to the value of a variable, then set           * If the scale is tied to the value of a variable, then set
633           * the scale's value from the value of the variable, if it exists           * the scale's value from the value of the variable, if it exists
634           * and it holds a valid double value.           * and it holds a valid double value.
635           */           */
636    
637          if (scalePtr->varNamePtr != NULL) {          if (scalePtr->varNamePtr != NULL) {
638              double value;              double value;
639              Tcl_Obj *valuePtr;              Tcl_Obj *valuePtr;
640    
641              valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,              valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
642                      TCL_GLOBAL_ONLY);                      TCL_GLOBAL_ONLY);
643              if ((valuePtr != NULL) &&              if ((valuePtr != NULL) &&
644                      (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {                      (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
645                  scalePtr->value = TkRoundToResolution(scalePtr, value);                  scalePtr->value = TkRoundToResolution(scalePtr, value);
646              }              }
647          }          }
648    
649          /*          /*
650           * Several options need special processing, such as parsing the           * Several options need special processing, such as parsing the
651           * orientation and creating GCs.           * orientation and creating GCs.
652           */           */
653    
654          scalePtr->fromValue = TkRoundToResolution(scalePtr,          scalePtr->fromValue = TkRoundToResolution(scalePtr,
655                  scalePtr->fromValue);                  scalePtr->fromValue);
656          scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);          scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
657          scalePtr->tickInterval = TkRoundToResolution(scalePtr,          scalePtr->tickInterval = TkRoundToResolution(scalePtr,
658                  scalePtr->tickInterval);                  scalePtr->tickInterval);
659    
660          /*          /*
661           * Make sure that the tick interval has the right sign so that           * Make sure that the tick interval has the right sign so that
662           * addition moves from fromValue to toValue.           * addition moves from fromValue to toValue.
663           */           */
664    
665          if ((scalePtr->tickInterval < 0)          if ((scalePtr->tickInterval < 0)
666                  ^ ((scalePtr->toValue - scalePtr->fromValue) <  0)) {                  ^ ((scalePtr->toValue - scalePtr->fromValue) <  0)) {
667            scalePtr->tickInterval = -scalePtr->tickInterval;            scalePtr->tickInterval = -scalePtr->tickInterval;
668          }          }
669    
670          ComputeFormat(scalePtr);          ComputeFormat(scalePtr);
671    
672          scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0;          scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0;
673    
674          Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);          Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
675    
676          if (scalePtr->highlightWidth < 0) {          if (scalePtr->highlightWidth < 0) {
677              scalePtr->highlightWidth = 0;              scalePtr->highlightWidth = 0;
678          }          }
679          scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;          scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
680          break;          break;
681      }      }
682      if (!error) {      if (!error) {
683          Tk_FreeSavedOptions(&savedOptions);          Tk_FreeSavedOptions(&savedOptions);
684      }      }
685    
686      /*      /*
687       * Set the scale value to itself;  all this does is to make sure       * Set the scale value to itself;  all this does is to make sure
688       * that the scale's value is within the new acceptable range for       * that the scale's value is within the new acceptable range for
689       * the scale.  We don't set the var here because we need to make       * the scale.  We don't set the var here because we need to make
690       * special checks for possibly changed varNamePtr.       * special checks for possibly changed varNamePtr.
691       */       */
692    
693      TkScaleSetValue(scalePtr, scalePtr->value, 0, 1);      TkScaleSetValue(scalePtr, scalePtr->value, 0, 1);
694    
695      /*      /*
696       * Reestablish the variable trace, if it is needed.       * Reestablish the variable trace, if it is needed.
697       */       */
698    
699      if (scalePtr->varNamePtr != NULL) {      if (scalePtr->varNamePtr != NULL) {
700          Tcl_Obj *valuePtr;          Tcl_Obj *valuePtr;
701    
702          /*          /*
703           * Set the associated variable only when the new value differs           * Set the associated variable only when the new value differs
704           * from the current value, or the variable doesn't yet exist           * from the current value, or the variable doesn't yet exist
705           */           */
706          valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,          valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
707                  TCL_GLOBAL_ONLY);                  TCL_GLOBAL_ONLY);
708          if ((valuePtr == NULL) || (scalePtr->value != oldValue)          if ((valuePtr == NULL) || (scalePtr->value != oldValue)
709                  || (Tcl_GetDoubleFromObj(NULL, valuePtr, &oldValue) != TCL_OK)                  || (Tcl_GetDoubleFromObj(NULL, valuePtr, &oldValue) != TCL_OK)
710                  || (scalePtr->value != oldValue)) {                  || (scalePtr->value != oldValue)) {
711              ScaleSetVariable(scalePtr);              ScaleSetVariable(scalePtr);
712          }          }
713          Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),          Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
714                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                  TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
715                  ScaleVarProc, (ClientData) scalePtr);                  ScaleVarProc, (ClientData) scalePtr);
716      }      }
717    
718      ScaleWorldChanged((ClientData) scalePtr);      ScaleWorldChanged((ClientData) scalePtr);
719      if (error) {      if (error) {
720          Tcl_SetObjResult(interp, errorResult);          Tcl_SetObjResult(interp, errorResult);
721          Tcl_DecrRefCount(errorResult);          Tcl_DecrRefCount(errorResult);
722          return TCL_ERROR;          return TCL_ERROR;
723      } else {      } else {
724          return TCL_OK;          return TCL_OK;
725      }      }
726  }  }
727    
728  /*  /*
729   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
730   *   *
731   * ScaleWorldChanged --   * ScaleWorldChanged --
732   *   *
733   *      This procedure is called when the world has changed in some   *      This procedure is called when the world has changed in some
734   *      way and the widget needs to recompute all its graphics contexts   *      way and the widget needs to recompute all its graphics contexts
735   *      and determine its new geometry.   *      and determine its new geometry.
736   *   *
737   * Results:   * Results:
738   *      None.   *      None.
739   *   *
740   * Side effects:   * Side effects:
741   *      Scale will be relayed out and redisplayed.   *      Scale will be relayed out and redisplayed.
742   *   *
743   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
744   */   */
745    
746  static void  static void
747  ScaleWorldChanged(instanceData)  ScaleWorldChanged(instanceData)
748      ClientData instanceData;    /* Information about widget. */      ClientData instanceData;    /* Information about widget. */
749  {  {
750      XGCValues gcValues;      XGCValues gcValues;
751      GC gc;      GC gc;
752      TkScale *scalePtr;      TkScale *scalePtr;
753    
754      scalePtr = (TkScale *) instanceData;      scalePtr = (TkScale *) instanceData;
755    
756      gcValues.foreground = scalePtr->troughColorPtr->pixel;      gcValues.foreground = scalePtr->troughColorPtr->pixel;
757      gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);      gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);
758      if (scalePtr->troughGC != None) {      if (scalePtr->troughGC != None) {
759          Tk_FreeGC(scalePtr->display, scalePtr->troughGC);          Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
760      }      }
761      scalePtr->troughGC = gc;      scalePtr->troughGC = gc;
762    
763      gcValues.font = Tk_FontId(scalePtr->tkfont);      gcValues.font = Tk_FontId(scalePtr->tkfont);
764      gcValues.foreground = scalePtr->textColorPtr->pixel;      gcValues.foreground = scalePtr->textColorPtr->pixel;
765      gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);      gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);
766      if (scalePtr->textGC != None) {      if (scalePtr->textGC != None) {
767          Tk_FreeGC(scalePtr->display, scalePtr->textGC);          Tk_FreeGC(scalePtr->display, scalePtr->textGC);
768      }      }
769      scalePtr->textGC = gc;      scalePtr->textGC = gc;
770    
771      if (scalePtr->copyGC == None) {      if (scalePtr->copyGC == None) {
772          gcValues.graphics_exposures = False;          gcValues.graphics_exposures = False;
773          scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,          scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,
774              &gcValues);              &gcValues);
775      }      }
776      scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;      scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
777    
778      /*      /*
779       * Recompute display-related information, and let the geometry       * Recompute display-related information, and let the geometry
780       * manager know how much space is needed now.       * manager know how much space is needed now.
781       */       */
782    
783      ComputeScaleGeometry(scalePtr);      ComputeScaleGeometry(scalePtr);
784    
785      TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);      TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
786  }  }
787    
788  /*  /*
789   *----------------------------------------------------------------------   *----------------------------------------------------------------------
790   *   *
791   * ComputeFormat --   * ComputeFormat --
792   *   *
793   *      This procedure is invoked to recompute the "format" field   *      This procedure is invoked to recompute the "format" field
794   *      of a scale's widget record, which determines how the value   *      of a scale's widget record, which determines how the value
795   *      of the scale is converted to a string.   *      of the scale is converted to a string.
796   *   *
797   * Results:   * Results:
798   *      None.   *      None.
799   *   *
800   * Side effects:   * Side effects:
801   *      The format field of scalePtr is modified.   *      The format field of scalePtr is modified.
802   *   *
803   *----------------------------------------------------------------------   *----------------------------------------------------------------------
804   */   */
805    
806  static void  static void
807  ComputeFormat(scalePtr)  ComputeFormat(scalePtr)
808      TkScale *scalePtr;                  /* Information about scale widget. */      TkScale *scalePtr;                  /* Information about scale widget. */
809  {  {
810      double maxValue, x;      double maxValue, x;
811      int mostSigDigit, numDigits, leastSigDigit, afterDecimal;      int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
812      int eDigits, fDigits;      int eDigits, fDigits;
813    
814      /*      /*
815       * Compute the displacement from the decimal of the most significant       * Compute the displacement from the decimal of the most significant
816       * digit required for any number in the scale's range.       * digit required for any number in the scale's range.
817       */       */
818    
819      maxValue = fabs(scalePtr->fromValue);      maxValue = fabs(scalePtr->fromValue);
820      x = fabs(scalePtr->toValue);      x = fabs(scalePtr->toValue);
821      if (x > maxValue) {      if (x > maxValue) {
822          maxValue = x;          maxValue = x;
823      }      }
824      if (maxValue == 0) {      if (maxValue == 0) {
825          maxValue = 1;          maxValue = 1;
826      }      }
827      mostSigDigit = (int) floor(log10(maxValue));      mostSigDigit = (int) floor(log10(maxValue));
828    
829      /*      /*
830       * If the number of significant digits wasn't specified explicitly,       * If the number of significant digits wasn't specified explicitly,
831       * compute it. It's the difference between the most significant       * compute it. It's the difference between the most significant
832       * digit needed to represent any number on the scale and the       * digit needed to represent any number on the scale and the
833       * most significant digit of the smallest difference between       * most significant digit of the smallest difference between
834       * numbers on the scale.  In other words, display enough digits so       * numbers on the scale.  In other words, display enough digits so
835       * that at least one digit will be different between any two adjacent       * that at least one digit will be different between any two adjacent
836       * positions of the scale.       * positions of the scale.
837       */       */
838    
839      numDigits = scalePtr->digits;      numDigits = scalePtr->digits;
840      if (numDigits <= 0) {      if (numDigits <= 0) {
841          if  (scalePtr->resolution > 0) {          if  (scalePtr->resolution > 0) {
842              /*              /*
843               * A resolution was specified for the scale, so just use it.               * A resolution was specified for the scale, so just use it.
844               */               */
845    
846              leastSigDigit = (int) floor(log10(scalePtr->resolution));              leastSigDigit = (int) floor(log10(scalePtr->resolution));
847          } else {          } else {
848              /*              /*
849               * No resolution was specified, so compute the difference               * No resolution was specified, so compute the difference
850               * in value between adjacent pixels and use it for the least               * in value between adjacent pixels and use it for the least
851               * significant digit.               * significant digit.
852               */               */
853    
854              x = fabs(scalePtr->fromValue - scalePtr->toValue);              x = fabs(scalePtr->fromValue - scalePtr->toValue);
855              if (scalePtr->length > 0) {              if (scalePtr->length > 0) {
856                  x /= scalePtr->length;                  x /= scalePtr->length;
857              }              }
858              if (x > 0){              if (x > 0){
859                  leastSigDigit = (int) floor(log10(x));                  leastSigDigit = (int) floor(log10(x));
860              } else {              } else {
861                  leastSigDigit = 0;                  leastSigDigit = 0;
862              }              }
863          }          }
864          numDigits = mostSigDigit - leastSigDigit + 1;          numDigits = mostSigDigit - leastSigDigit + 1;
865          if (numDigits < 1) {          if (numDigits < 1) {
866              numDigits = 1;              numDigits = 1;
867          }          }
868      }      }
869    
870      /*      /*
871       * Compute the number of characters required using "e" format and       * Compute the number of characters required using "e" format and
872       * "f" format, and then choose whichever one takes fewer characters.       * "f" format, and then choose whichever one takes fewer characters.
873       */       */
874    
875      eDigits = numDigits + 4;      eDigits = numDigits + 4;
876      if (numDigits > 1) {      if (numDigits > 1) {
877          eDigits++;                      /* Decimal point. */          eDigits++;                      /* Decimal point. */
878      }      }
879      afterDecimal = numDigits - mostSigDigit - 1;      afterDecimal = numDigits - mostSigDigit - 1;
880      if (afterDecimal < 0) {      if (afterDecimal < 0) {
881          afterDecimal = 0;          afterDecimal = 0;
882      }      }
883      fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;      fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
884      if (afterDecimal > 0) {      if (afterDecimal > 0) {
885          fDigits++;                      /* Decimal point. */          fDigits++;                      /* Decimal point. */
886      }      }
887      if (mostSigDigit < 0) {      if (mostSigDigit < 0) {
888          fDigits++;                      /* Zero to left of decimal point. */          fDigits++;                      /* Zero to left of decimal point. */
889      }      }
890      if (fDigits <= eDigits) {      if (fDigits <= eDigits) {
891          sprintf(scalePtr->format, "%%.%df", afterDecimal);          sprintf(scalePtr->format, "%%.%df", afterDecimal);
892      } else {      } else {
893          sprintf(scalePtr->format, "%%.%de", numDigits-1);          sprintf(scalePtr->format, "%%.%de", numDigits-1);
894      }      }
895  }  }
896    
897  /*  /*
898   *----------------------------------------------------------------------   *----------------------------------------------------------------------
899   *   *
900   * ComputeScaleGeometry --   * ComputeScaleGeometry --
901   *   *
902   *      This procedure is called to compute various geometrical   *      This procedure is called to compute various geometrical
903   *      information for a scale, such as where various things get   *      information for a scale, such as where various things get
904   *      displayed.  It's called when the window is reconfigured.   *      displayed.  It's called when the window is reconfigured.
905   *   *
906   * Results:   * Results:
907   *      None.   *      None.
908   *   *
909   * Side effects:   * Side effects:
910   *      Display-related numbers get changed in *scalePtr.  The   *      Display-related numbers get changed in *scalePtr.  The
911   *      geometry manager gets told about the window's preferred size.   *      geometry manager gets told about the window's preferred size.
912   *   *
913   *----------------------------------------------------------------------   *----------------------------------------------------------------------
914   */   */
915    
916  static void  static void
917  ComputeScaleGeometry(scalePtr)  ComputeScaleGeometry(scalePtr)
918      register TkScale *scalePtr;         /* Information about widget. */      register TkScale *scalePtr;         /* Information about widget. */
919  {  {
920      char valueString[PRINT_CHARS];      char valueString[PRINT_CHARS];
921      int tmp, valuePixels, x, y, extraSpace;      int tmp, valuePixels, x, y, extraSpace;
922      Tk_FontMetrics fm;      Tk_FontMetrics fm;
923    
924      Tk_GetFontMetrics(scalePtr->tkfont, &fm);      Tk_GetFontMetrics(scalePtr->tkfont, &fm);
925      scalePtr->fontHeight = fm.linespace + SPACING;      scalePtr->fontHeight = fm.linespace + SPACING;
926    
927      /*      /*
928       * Horizontal scales are simpler than vertical ones because       * Horizontal scales are simpler than vertical ones because
929       * all sizes are the same (the height of a line of text);       * all sizes are the same (the height of a line of text);
930       * handle them first and then quit.       * handle them first and then quit.
931       */       */
932    
933      if (scalePtr->orient == ORIENT_HORIZONTAL) {      if (scalePtr->orient == ORIENT_HORIZONTAL) {
934          y = scalePtr->inset;          y = scalePtr->inset;
935          extraSpace = 0;          extraSpace = 0;
936          if (scalePtr->labelLength != 0) {          if (scalePtr->labelLength != 0) {
937              scalePtr->horizLabelY = y + SPACING;              scalePtr->horizLabelY = y + SPACING;
938              y += scalePtr->fontHeight;              y += scalePtr->fontHeight;
939              extraSpace = SPACING;              extraSpace = SPACING;
940          }          }
941          if (scalePtr->showValue) {          if (scalePtr->showValue) {
942              scalePtr->horizValueY = y + SPACING;              scalePtr->horizValueY = y + SPACING;
943              y += scalePtr->fontHeight;              y += scalePtr->fontHeight;
944              extraSpace = SPACING;              extraSpace = SPACING;
945          } else {          } else {
946              scalePtr->horizValueY = y;              scalePtr->horizValueY = y;
947          }          }
948          y += extraSpace;          y += extraSpace;
949          scalePtr->horizTroughY = y;          scalePtr->horizTroughY = y;
950          y += scalePtr->width + 2*scalePtr->borderWidth;          y += scalePtr->width + 2*scalePtr->borderWidth;
951          if (scalePtr->tickInterval != 0) {          if (scalePtr->tickInterval != 0) {
952              scalePtr->horizTickY = y + SPACING;              scalePtr->horizTickY = y + SPACING;
953              y += scalePtr->fontHeight + SPACING;              y += scalePtr->fontHeight + SPACING;
954          }          }
955          Tk_GeometryRequest(scalePtr->tkwin,          Tk_GeometryRequest(scalePtr->tkwin,
956                  scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);                  scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);
957          Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);          Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
958          return;          return;
959      }      }
960    
961      /*      /*
962       * Vertical scale:  compute the amount of space needed to display       * Vertical scale:  compute the amount of space needed to display
963       * the scales value by formatting strings for the two end points;       * the scales value by formatting strings for the two end points;
964       * use whichever length is longer.       * use whichever length is longer.
965       */       */
966    
967      sprintf(valueString, scalePtr->format, scalePtr->fromValue);      sprintf(valueString, scalePtr->format, scalePtr->fromValue);
968      valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);      valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
969    
970      sprintf(valueString, scalePtr->format, scalePtr->toValue);      sprintf(valueString, scalePtr->format, scalePtr->toValue);
971      tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);      tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
972      if (valuePixels < tmp) {      if (valuePixels < tmp) {
973          valuePixels = tmp;          valuePixels = tmp;
974      }      }
975    
976      /*      /*
977       * Assign x-locations to the elements of the scale, working from       * Assign x-locations to the elements of the scale, working from
978       * left to right.       * left to right.
979       */       */
980    
981      x = scalePtr->inset;      x = scalePtr->inset;
982      if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {      if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {
983          scalePtr->vertTickRightX = x + SPACING + valuePixels;          scalePtr->vertTickRightX = x + SPACING + valuePixels;
984          scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels          scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels
985                  + fm.ascent/2;                  + fm.ascent/2;
986          x = scalePtr->vertValueRightX + SPACING;          x = scalePtr->vertValueRightX + SPACING;
987      } else if (scalePtr->tickInterval != 0) {      } else if (scalePtr->tickInterval != 0) {
988          scalePtr->vertTickRightX = x + SPACING + valuePixels;          scalePtr->vertTickRightX = x + SPACING + valuePixels;
989          scalePtr->vertValueRightX = scalePtr->vertTickRightX;          scalePtr->vertValueRightX = scalePtr->vertTickRightX;
990          x = scalePtr->vertTickRightX + SPACING;          x = scalePtr->vertTickRightX + SPACING;
991      } else if (scalePtr->showValue) {      } else if (scalePtr->showValue) {
992          scalePtr->vertTickRightX = x;          scalePtr->vertTickRightX = x;
993          scalePtr->vertValueRightX = x + SPACING + valuePixels;          scalePtr->vertValueRightX = x + SPACING + valuePixels;
994          x = scalePtr->vertValueRightX + SPACING;          x = scalePtr->vertValueRightX + SPACING;
995      } else {      } else {
996          scalePtr->vertTickRightX = x;          scalePtr->vertTickRightX = x;
997          scalePtr->vertValueRightX = x;          scalePtr->vertValueRightX = x;
998      }      }
999      scalePtr->vertTroughX = x;      scalePtr->vertTroughX = x;
1000      x += 2*scalePtr->borderWidth + scalePtr->width;      x += 2*scalePtr->borderWidth + scalePtr->width;
1001      if (scalePtr->labelLength == 0) {      if (scalePtr->labelLength == 0) {
1002          scalePtr->vertLabelX = 0;          scalePtr->vertLabelX = 0;
1003      } else {      } else {
1004          scalePtr->vertLabelX = x + fm.ascent/2;          scalePtr->vertLabelX = x + fm.ascent/2;
1005          x = scalePtr->vertLabelX + fm.ascent/2          x = scalePtr->vertLabelX + fm.ascent/2
1006              + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,              + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
1007                      scalePtr->labelLength);                      scalePtr->labelLength);
1008      }      }
1009      Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,      Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,
1010              scalePtr->length + 2*scalePtr->inset);              scalePtr->length + 2*scalePtr->inset);
1011      Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);      Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
1012  }  }
1013    
1014  /*  /*
1015   *--------------------------------------------------------------   *--------------------------------------------------------------
1016   *   *
1017   * ScaleEventProc --   * ScaleEventProc --
1018   *   *
1019   *      This procedure is invoked by the Tk dispatcher for various   *      This procedure is invoked by the Tk dispatcher for various
1020   *      events on scales.   *      events on scales.
1021   *   *
1022   * Results:   * Results:
1023   *      None.   *      None.
1024   *   *
1025   * Side effects:   * Side effects:
1026   *      When the window gets deleted, internal structures get   *      When the window gets deleted, internal structures get
1027   *      cleaned up.  When it gets exposed, it is redisplayed.   *      cleaned up.  When it gets exposed, it is redisplayed.
1028   *   *
1029   *--------------------------------------------------------------   *--------------------------------------------------------------
1030   */   */
1031    
1032  static void  static void
1033  ScaleEventProc(clientData, eventPtr)  ScaleEventProc(clientData, eventPtr)
1034      ClientData clientData;      /* Information about window. */      ClientData clientData;      /* Information about window. */
1035      XEvent *eventPtr;           /* Information about event. */      XEvent *eventPtr;           /* Information about event. */
1036  {  {
1037      TkScale *scalePtr = (TkScale *) clientData;      TkScale *scalePtr = (TkScale *) clientData;
1038    
1039      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {      if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
1040          TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);          TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
1041      } else if (eventPtr->type == DestroyNotify) {      } else if (eventPtr->type == DestroyNotify) {
1042          DestroyScale((char *) clientData);          DestroyScale((char *) clientData);
1043      } else if (eventPtr->type == ConfigureNotify) {      } else if (eventPtr->type == ConfigureNotify) {
1044          ComputeScaleGeometry(scalePtr);          ComputeScaleGeometry(scalePtr);
1045          TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);          TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
1046      } else if (eventPtr->type == FocusIn) {      } else if (eventPtr->type == FocusIn) {
1047          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
1048              scalePtr->flags |= GOT_FOCUS;              scalePtr->flags |= GOT_FOCUS;
1049              if (scalePtr->highlightWidth > 0) {              if (scalePtr->highlightWidth > 0) {
1050                  TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);                  TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
1051              }              }
1052          }          }
1053      } else if (eventPtr->type == FocusOut) {      } else if (eventPtr->type == FocusOut) {
1054          if (eventPtr->xfocus.detail != NotifyInferior) {          if (eventPtr->xfocus.detail != NotifyInferior) {
1055              scalePtr->flags &= ~GOT_FOCUS;              scalePtr->flags &= ~GOT_FOCUS;
1056              if (scalePtr->highlightWidth > 0) {              if (scalePtr->highlightWidth > 0) {
1057                  TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);                  TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
1058              }              }
1059          }          }
1060      }      }
1061  }  }
1062    
1063  /*  /*
1064   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1065   *   *
1066   * ScaleCmdDeletedProc --   * ScaleCmdDeletedProc --
1067   *   *
1068   *      This procedure is invoked when a widget command is deleted.  If   *      This procedure is invoked when a widget command is deleted.  If
1069   *      the widget isn't already in the process of being destroyed,   *      the widget isn't already in the process of being destroyed,
1070   *      this command destroys it.   *      this command destroys it.
1071   *   *
1072   * Results:   * Results:
1073   *      None.   *      None.
1074   *   *
1075   * Side effects:   * Side effects:
1076   *      The widget is destroyed.   *      The widget is destroyed.
1077   *   *
1078   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1079   */   */
1080    
1081  static void  static void
1082  ScaleCmdDeletedProc(clientData)  ScaleCmdDeletedProc(clientData)
1083      ClientData clientData;      /* Pointer to widget record for widget. */      ClientData clientData;      /* Pointer to widget record for widget. */
1084  {  {
1085      TkScale *scalePtr = (TkScale *) clientData;      TkScale *scalePtr = (TkScale *) clientData;
1086      Tk_Window tkwin = scalePtr->tkwin;      Tk_Window tkwin = scalePtr->tkwin;
1087    
1088      /*      /*
1089       * This procedure could be invoked either because the window was       * This procedure could be invoked either because the window was
1090       * destroyed and the command was then deleted (in which case tkwin       * destroyed and the command was then deleted (in which case tkwin
1091       * is NULL) or because the command was deleted, and then this procedure       * is NULL) or because the command was deleted, and then this procedure
1092       * destroys the widget.       * destroys the widget.
1093       */       */
1094    
1095      if (!(scalePtr->flags & SCALE_DELETED)) {      if (!(scalePtr->flags & SCALE_DELETED)) {
1096          scalePtr->flags |= SCALE_DELETED;          scalePtr->flags |= SCALE_DELETED;
1097          Tk_DestroyWindow(tkwin);          Tk_DestroyWindow(tkwin);
1098      }      }
1099  }  }
1100    
1101  /*  /*
1102   *--------------------------------------------------------------   *--------------------------------------------------------------
1103   *   *
1104   * TkEventuallyRedrawScale --   * TkEventuallyRedrawScale --
1105   *   *
1106   *      Arrange for part or all of a scale widget to redrawn at   *      Arrange for part or all of a scale widget to redrawn at
1107   *      the next convenient time in the future.   *      the next convenient time in the future.
1108   *   *
1109   * Results:   * Results:
1110   *      None.   *      None.
1111   *   *
1112   * Side effects:   * Side effects:
1113   *      If "what" is REDRAW_SLIDER then just the slider and the   *      If "what" is REDRAW_SLIDER then just the slider and the
1114   *      value readout will be redrawn;  if "what" is REDRAW_ALL   *      value readout will be redrawn;  if "what" is REDRAW_ALL
1115   *      then the entire widget will be redrawn.   *      then the entire widget will be redrawn.
1116   *   *
1117   *--------------------------------------------------------------   *--------------------------------------------------------------
1118   */   */
1119    
1120  void  void
1121  TkEventuallyRedrawScale(scalePtr, what)  TkEventuallyRedrawScale(scalePtr, what)
1122      register TkScale *scalePtr; /* Information about widget. */      register TkScale *scalePtr; /* Information about widget. */
1123      int what;                   /* What to redraw:  REDRAW_SLIDER      int what;                   /* What to redraw:  REDRAW_SLIDER
1124                                   * or REDRAW_ALL. */                                   * or REDRAW_ALL. */
1125  {  {
1126      if ((what == 0) || (scalePtr->tkwin == NULL)      if ((what == 0) || (scalePtr->tkwin == NULL)
1127              || !Tk_IsMapped(scalePtr->tkwin)) {              || !Tk_IsMapped(scalePtr->tkwin)) {
1128          return;          return;
1129      }      }
1130      if (!(scalePtr->flags & REDRAW_PENDING)) {      if (!(scalePtr->flags & REDRAW_PENDING)) {
1131          scalePtr->flags |= REDRAW_PENDING;          scalePtr->flags |= REDRAW_PENDING;
1132          Tcl_DoWhenIdle(TkpDisplayScale, (ClientData) scalePtr);          Tcl_DoWhenIdle(TkpDisplayScale, (ClientData) scalePtr);
1133      }      }
1134      scalePtr->flags |= what;      scalePtr->flags |= what;
1135  }  }
1136    
1137  /*  /*
1138   *--------------------------------------------------------------   *--------------------------------------------------------------
1139   *   *
1140   * TkRoundToResolution --   * TkRoundToResolution --
1141   *   *
1142   *      Round a given floating-point value to the nearest multiple   *      Round a given floating-point value to the nearest multiple
1143   *      of the scale's resolution.   *      of the scale's resolution.
1144   *   *
1145   * Results:   * Results:
1146   *      The return value is the rounded result.   *      The return value is the rounded result.
1147   *   *
1148   * Side effects:   * Side effects:
1149   *      None.   *      None.
1150   *   *
1151   *--------------------------------------------------------------   *--------------------------------------------------------------
1152   */   */
1153    
1154  double  double
1155  TkRoundToResolution(scalePtr, value)  TkRoundToResolution(scalePtr, value)
1156      TkScale *scalePtr;          /* Information about scale widget. */      TkScale *scalePtr;          /* Information about scale widget. */
1157      double value;               /* Value to round. */      double value;               /* Value to round. */
1158  {  {
1159      double rem, new, tick;      double rem, new, tick;
1160    
1161      if (scalePtr->resolution <= 0) {      if (scalePtr->resolution <= 0) {
1162          return value;          return value;
1163      }      }
1164      tick = floor(value/scalePtr->resolution);      tick = floor(value/scalePtr->resolution);
1165      new = scalePtr->resolution * tick;      new = scalePtr->resolution * tick;
1166      rem = value - new;      rem = value - new;
1167      if (rem < 0) {      if (rem < 0) {
1168          if (rem <= -scalePtr->resolution/2) {          if (rem <= -scalePtr->resolution/2) {
1169              new = (tick - 1.0) * scalePtr->resolution;              new = (tick - 1.0) * scalePtr->resolution;
1170          }          }
1171      } else {      } else {
1172          if (rem >= scalePtr->resolution/2) {          if (rem >= scalePtr->resolution/2) {
1173              new = (tick + 1.0) * scalePtr->resolution;              new = (tick + 1.0) * scalePtr->resolution;
1174          }          }
1175      }      }
1176      return new;      return new;
1177  }  }
1178    
1179  /*  /*
1180   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1181   *   *
1182   * ScaleVarProc --   * ScaleVarProc --
1183   *   *
1184   *      This procedure is invoked by Tcl whenever someone modifies a   *      This procedure is invoked by Tcl whenever someone modifies a
1185   *      variable associated with a scale widget.   *      variable associated with a scale widget.
1186   *   *
1187   * Results:   * Results:
1188   *      NULL is always returned.   *      NULL is always returned.
1189   *   *
1190   * Side effects:   * Side effects:
1191   *      The value displayed in the scale will change to match the   *      The value displayed in the scale will change to match the
1192   *      variable's new value.  If the variable has a bogus value then   *      variable's new value.  If the variable has a bogus value then
1193   *      it is reset to the value of the scale.   *      it is reset to the value of the scale.
1194   *   *
1195   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1196   */   */
1197    
1198      /* ARGSUSED */      /* ARGSUSED */
1199  static char *  static char *
1200  ScaleVarProc(clientData, interp, name1, name2, flags)  ScaleVarProc(clientData, interp, name1, name2, flags)
1201      ClientData clientData;      /* Information about button. */      ClientData clientData;      /* Information about button. */
1202      Tcl_Interp *interp;         /* Interpreter containing variable. */      Tcl_Interp *interp;         /* Interpreter containing variable. */
1203      char *name1;                /* Name of variable. */      char *name1;                /* Name of variable. */
1204      char *name2;                /* Second part of variable name. */      char *name2;                /* Second part of variable name. */
1205      int flags;                  /* Information about what happened. */      int flags;                  /* Information about what happened. */
1206  {  {
1207      register TkScale *scalePtr = (TkScale *) clientData;      register TkScale *scalePtr = (TkScale *) clientData;
1208      char *resultStr;      char *resultStr;
1209      double value;      double value;
1210      Tcl_Obj *valuePtr;      Tcl_Obj *valuePtr;
1211      int result;      int result;
1212    
1213      /*      /*
1214       * If the variable is unset, then immediately recreate it unless       * If the variable is unset, then immediately recreate it unless
1215       * the whole interpreter is going away.       * the whole interpreter is going away.
1216       */       */
1217    
1218      if (flags & TCL_TRACE_UNSETS) {      if (flags & TCL_TRACE_UNSETS) {
1219          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {          if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1220              Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),              Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
1221                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,                      TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1222                      ScaleVarProc, clientData);                      ScaleVarProc, clientData);
1223              scalePtr->flags |= NEVER_SET;              scalePtr->flags |= NEVER_SET;
1224              TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);              TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
1225          }          }
1226          return (char *) NULL;          return (char *) NULL;
1227      }      }
1228    
1229      /*      /*
1230       * If we came here because we updated the variable (in TkScaleSetValue),       * If we came here because we updated the variable (in TkScaleSetValue),
1231       * then ignore the trace.  Otherwise update the scale with the value       * then ignore the trace.  Otherwise update the scale with the value
1232       * of the variable.       * of the variable.
1233       */       */
1234    
1235      if (scalePtr->flags & SETTING_VAR) {      if (scalePtr->flags & SETTING_VAR) {
1236          return (char *) NULL;          return (char *) NULL;
1237      }      }
1238      resultStr = NULL;      resultStr = NULL;
1239      valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,      valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
1240              TCL_GLOBAL_ONLY);              TCL_GLOBAL_ONLY);
1241      result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);      result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);
1242      if (result != TCL_OK) {      if (result != TCL_OK) {
1243          resultStr = "can't assign non-numeric value to scale variable";          resultStr = "can't assign non-numeric value to scale variable";
1244          ScaleSetVariable(scalePtr);          ScaleSetVariable(scalePtr);
1245      } else {      } else {
1246          scalePtr->value = TkRoundToResolution(scalePtr, value);          scalePtr->value = TkRoundToResolution(scalePtr, value);
1247    
1248          /*          /*
1249           * This code is a bit tricky because it sets the scale's value before           * This code is a bit tricky because it sets the scale's value before
1250           * calling TkScaleSetValue.  This way, TkScaleSetValue won't bother           * calling TkScaleSetValue.  This way, TkScaleSetValue won't bother
1251           * to set the variable again or to invoke the -command.  However, it           * to set the variable again or to invoke the -command.  However, it
1252           * also won't redisplay the scale, so we have to ask for that           * also won't redisplay the scale, so we have to ask for that
1253           * explicitly.           * explicitly.
1254           */           */
1255    
1256          TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);          TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
1257      }      }
1258      TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);      TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
1259    
1260      return resultStr;      return resultStr;
1261  }  }
1262    
1263  /*  /*
1264   *--------------------------------------------------------------   *--------------------------------------------------------------
1265   *   *
1266   * TkScaleSetValue --   * TkScaleSetValue --
1267   *   *
1268   *      This procedure changes the value of a scale and invokes   *      This procedure changes the value of a scale and invokes
1269   *      a Tcl command to reflect the current position of a scale   *      a Tcl command to reflect the current position of a scale
1270   *   *
1271   * Results:   * Results:
1272   *      None.   *      None.
1273   *   *
1274   * Side effects:   * Side effects:
1275   *      A Tcl command is invoked, and an additional error-processing   *      A Tcl command is invoked, and an additional error-processing
1276   *      command may also be invoked.  The scale's slider is redrawn.   *      command may also be invoked.  The scale's slider is redrawn.
1277   *   *
1278   *--------------------------------------------------------------   *--------------------------------------------------------------
1279   */   */
1280    
1281  void  void
1282  TkScaleSetValue(scalePtr, value, setVar, invokeCommand)  TkScaleSetValue(scalePtr, value, setVar, invokeCommand)
1283      register TkScale *scalePtr; /* Info about widget. */      register TkScale *scalePtr; /* Info about widget. */
1284      double value;               /* New value for scale.  Gets adjusted      double value;               /* New value for scale.  Gets adjusted
1285                                   * if it's off the scale. */                                   * if it's off the scale. */
1286      int setVar;                 /* Non-zero means reflect new value through      int setVar;                 /* Non-zero means reflect new value through
1287                                   * to associated variable, if any. */                                   * to associated variable, if any. */
1288      int invokeCommand;          /* Non-zero means invoked -command option      int invokeCommand;          /* Non-zero means invoked -command option
1289                                   * to notify of new value, 0 means don't. */                                   * to notify of new value, 0 means don't. */
1290  {  {
1291      value = TkRoundToResolution(scalePtr, value);      value = TkRoundToResolution(scalePtr, value);
1292      if ((value < scalePtr->fromValue)      if ((value < scalePtr->fromValue)
1293              ^ (scalePtr->toValue < scalePtr->fromValue)) {              ^ (scalePtr->toValue < scalePtr->fromValue)) {
1294          value = scalePtr->fromValue;          value = scalePtr->fromValue;
1295      }      }
1296      if ((value > scalePtr->toValue)      if ((value > scalePtr->toValue)
1297              ^ (scalePtr->toValue < scalePtr->fromValue)) {              ^ (scalePtr->toValue < scalePtr->fromValue)) {
1298          value = scalePtr->toValue;          value = scalePtr->toValue;
1299      }      }
1300      if (scalePtr->flags & NEVER_SET) {      if (scalePtr->flags & NEVER_SET) {
1301          scalePtr->flags &= ~NEVER_SET;          scalePtr->flags &= ~NEVER_SET;
1302      } else if (scalePtr->value == value) {      } else if (scalePtr->value == value) {
1303          return;          return;
1304      }      }
1305      scalePtr->value = value;      scalePtr->value = value;
1306      if (invokeCommand) {      if (invokeCommand) {
1307          scalePtr->flags |= INVOKE_COMMAND;          scalePtr->flags |= INVOKE_COMMAND;
1308      }      }
1309      TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);      TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
1310    
1311      if (setVar && scalePtr->varNamePtr) {      if (setVar && scalePtr->varNamePtr) {
1312          ScaleSetVariable(scalePtr);          ScaleSetVariable(scalePtr);
1313      }      }
1314  }  }
1315    
1316  /*  /*
1317   *--------------------------------------------------------------   *--------------------------------------------------------------
1318   *   *
1319   * ScaleSetVariable --   * ScaleSetVariable --
1320   *   *
1321   *      This procedure sets the variable associated with a scale, if any.   *      This procedure sets the variable associated with a scale, if any.
1322   *   *
1323   * Results:   * Results:
1324   *      None.   *      None.
1325   *   *
1326   * Side effects:   * Side effects:
1327   *      Other write traces on the variable will trigger.   *      Other write traces on the variable will trigger.
1328   *   *
1329   *--------------------------------------------------------------   *--------------------------------------------------------------
1330   */   */
1331    
1332  static void  static void
1333  ScaleSetVariable(scalePtr)  ScaleSetVariable(scalePtr)
1334      register TkScale *scalePtr; /* Info about widget. */      register TkScale *scalePtr; /* Info about widget. */
1335  {  {
1336      if (scalePtr->varNamePtr != NULL) {      if (scalePtr->varNamePtr != NULL) {
1337          char string[PRINT_CHARS];          char string[PRINT_CHARS];
1338          sprintf(string, scalePtr->format, scalePtr->value);          sprintf(string, scalePtr->format, scalePtr->value);
1339          scalePtr->flags |= SETTING_VAR;          scalePtr->flags |= SETTING_VAR;
1340          Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,          Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
1341                  Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);                  Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
1342          scalePtr->flags &= ~SETTING_VAR;          scalePtr->flags &= ~SETTING_VAR;
1343      }      }
1344  }  }
1345    
1346  /*  /*
1347   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1348   *   *
1349   * TkScalePixelToValue --   * TkScalePixelToValue --
1350   *   *
1351   *      Given a pixel within a scale window, return the scale   *      Given a pixel within a scale window, return the scale
1352   *      reading corresponding to that pixel.   *      reading corresponding to that pixel.
1353   *   *
1354   * Results:   * Results:
1355   *      A double-precision scale reading.  If the value is outside   *      A double-precision scale reading.  If the value is outside
1356   *      the legal range for the scale then it's rounded to the nearest   *      the legal range for the scale then it's rounded to the nearest
1357   *      end of the scale.   *      end of the scale.
1358   *   *
1359   * Side effects:   * Side effects:
1360   *      None.   *      None.
1361   *   *
1362   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1363   */   */
1364    
1365  double  double
1366  TkScalePixelToValue(scalePtr, x, y)  TkScalePixelToValue(scalePtr, x, y)
1367      register TkScale *scalePtr;         /* Information about widget. */      register TkScale *scalePtr;         /* Information about widget. */
1368      int x, y;                           /* Coordinates of point within      int x, y;                           /* Coordinates of point within
1369                                           * window. */                                           * window. */
1370  {  {
1371      double value, pixelRange;      double value, pixelRange;
1372    
1373      if (scalePtr->orient == ORIENT_VERTICAL) {      if (scalePtr->orient == ORIENT_VERTICAL) {
1374          pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength          pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
1375                  - 2*scalePtr->inset - 2*scalePtr->borderWidth;                  - 2*scalePtr->inset - 2*scalePtr->borderWidth;
1376          value = y;          value = y;
1377      } else {      } else {
1378          pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength          pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
1379                  - 2*scalePtr->inset - 2*scalePtr->borderWidth;                  - 2*scalePtr->inset - 2*scalePtr->borderWidth;
1380          value = x;          value = x;
1381      }      }
1382    
1383      if (pixelRange <= 0) {      if (pixelRange <= 0) {
1384          /*          /*
1385           * Not enough room for the slider to actually slide:  just return           * Not enough room for the slider to actually slide:  just return
1386           * the scale's current value.           * the scale's current value.
1387           */           */
1388    
1389          return scalePtr->value;          return scalePtr->value;
1390      }      }
1391      value -= scalePtr->sliderLength/2 + scalePtr->inset      value -= scalePtr->sliderLength/2 + scalePtr->inset
1392                  + scalePtr->borderWidth;                  + scalePtr->borderWidth;
1393      value /= pixelRange;      value /= pixelRange;
1394      if (value < 0) {      if (value < 0) {
1395          value = 0;          value = 0;
1396      }      }
1397      if (value > 1) {      if (value > 1) {
1398          value = 1;          value = 1;
1399      }      }
1400      value = scalePtr->fromValue +      value = scalePtr->fromValue +
1401                  value * (scalePtr->toValue - scalePtr->fromValue);                  value * (scalePtr->toValue - scalePtr->fromValue);
1402      return TkRoundToResolution(scalePtr, value);      return TkRoundToResolution(scalePtr, value);
1403  }  }
1404    
1405  /*  /*
1406   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1407   *   *
1408   * TkScaleValueToPixel --   * TkScaleValueToPixel --
1409   *   *
1410   *      Given a reading of the scale, return the x-coordinate or   *      Given a reading of the scale, return the x-coordinate or
1411   *      y-coordinate corresponding to that reading, depending on   *      y-coordinate corresponding to that reading, depending on
1412   *      whether the scale is vertical or horizontal, respectively.   *      whether the scale is vertical or horizontal, respectively.
1413   *   *
1414   * Results:   * Results:
1415   *      An integer value giving the pixel location corresponding   *      An integer value giving the pixel location corresponding
1416   *      to reading.  The value is restricted to lie within the   *      to reading.  The value is restricted to lie within the
1417   *      defined range for the scale.   *      defined range for the scale.
1418   *   *
1419   * Side effects:   * Side effects:
1420   *      None.   *      None.
1421   *   *
1422   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1423   */   */
1424    
1425  int  int
1426  TkScaleValueToPixel(scalePtr, value)  TkScaleValueToPixel(scalePtr, value)
1427      register TkScale *scalePtr;         /* Information about widget. */      register TkScale *scalePtr;         /* Information about widget. */
1428      double value;                       /* Reading of the widget. */      double value;                       /* Reading of the widget. */
1429  {  {
1430      int y, pixelRange;      int y, pixelRange;
1431      double valueRange;      double valueRange;
1432    
1433      valueRange = scalePtr->toValue - scalePtr->fromValue;      valueRange = scalePtr->toValue - scalePtr->fromValue;
1434      pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)      pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)
1435              ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin))              ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin))
1436          - scalePtr->sliderLength - 2*scalePtr->inset - 2*scalePtr->borderWidth;          - scalePtr->sliderLength - 2*scalePtr->inset - 2*scalePtr->borderWidth;
1437      if (valueRange == 0) {      if (valueRange == 0) {
1438          y = 0;          y = 0;
1439      } else {      } else {
1440          y = (int) ((value - scalePtr->fromValue) * pixelRange          y = (int) ((value - scalePtr->fromValue) * pixelRange
1441                    / valueRange + 0.5);                    / valueRange + 0.5);
1442          if (y < 0) {          if (y < 0) {
1443              y = 0;              y = 0;
1444          } else if (y > pixelRange) {          } else if (y > pixelRange) {
1445              y = pixelRange;              y = pixelRange;
1446          }          }
1447      }      }
1448      y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;      y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
1449      return y;      return y;
1450  }  }
1451    
1452  /* End of tkscale.c */  /* End of tkscale.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25