OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkScale.c] - Diff between revs 579 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 579 Rev 1765
/*
/*
 * tkScale.c --
 * tkScale.c --
 *
 *
 *      This module implements a scale widgets for the Tk toolkit.
 *      This module implements a scale widgets for the Tk toolkit.
 *      A scale displays a slider that can be adjusted to change a
 *      A scale displays a slider that can be adjusted to change a
 *      value;  it also displays numeric labels and a textual label,
 *      value;  it also displays numeric labels and a textual label,
 *      if desired.
 *      if desired.
 *
 *
 *      The modifications to use floating-point values are based on
 *      The modifications to use floating-point values are based on
 *      an implementation by Paul Mackerras.  The -variable option
 *      an implementation by Paul Mackerras.  The -variable option
 *      is due to Henning Schulzrinne.  All of these are used with
 *      is due to Henning Schulzrinne.  All of these are used with
 *      permission.
 *      permission.
 *
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: tkScale.c,v 1.1.1.1 2002-01-16 10:25:52 markom Exp $
 * RCS: @(#) $Id: tkScale.c,v 1.1.1.1 2002-01-16 10:25:52 markom Exp $
 */
 */
 
 
#include "tkPort.h"
#include "tkPort.h"
#include "default.h"
#include "default.h"
#include "tkInt.h"
#include "tkInt.h"
#include "tclMath.h"
#include "tclMath.h"
#include "tkScale.h"
#include "tkScale.h"
 
 
static Tk_ConfigSpec configSpecs[] = {
static Tk_ConfigSpec configSpecs[] = {
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
        DEF_SCALE_ACTIVE_BG_COLOR, Tk_Offset(TkScale, activeBorder),
        DEF_SCALE_ACTIVE_BG_COLOR, Tk_Offset(TkScale, activeBorder),
        TK_CONFIG_COLOR_ONLY},
        TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
    {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
        DEF_SCALE_ACTIVE_BG_MONO, Tk_Offset(TkScale, activeBorder),
        DEF_SCALE_ACTIVE_BG_MONO, Tk_Offset(TkScale, activeBorder),
        TK_CONFIG_MONO_ONLY},
        TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
    {TK_CONFIG_BORDER, "-background", "background", "Background",
        DEF_SCALE_BG_COLOR, Tk_Offset(TkScale, bgBorder),
        DEF_SCALE_BG_COLOR, Tk_Offset(TkScale, bgBorder),
        TK_CONFIG_COLOR_ONLY},
        TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_BORDER, "-background", "background", "Background",
    {TK_CONFIG_BORDER, "-background", "background", "Background",
        DEF_SCALE_BG_MONO, Tk_Offset(TkScale, bgBorder),
        DEF_SCALE_BG_MONO, Tk_Offset(TkScale, bgBorder),
        TK_CONFIG_MONO_ONLY},
        TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
    {TK_CONFIG_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
        DEF_SCALE_BIG_INCREMENT, Tk_Offset(TkScale, bigIncrement), 0},
        DEF_SCALE_BIG_INCREMENT, Tk_Offset(TkScale, bigIncrement), 0},
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
        (char *) NULL, 0, 0},
        (char *) NULL, 0, 0},
    {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
    {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
        (char *) NULL, 0, 0},
        (char *) NULL, 0, 0},
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
        DEF_SCALE_BORDER_WIDTH, Tk_Offset(TkScale, borderWidth), 0},
        DEF_SCALE_BORDER_WIDTH, Tk_Offset(TkScale, borderWidth), 0},
    {TK_CONFIG_STRING, "-command", "command", "Command",
    {TK_CONFIG_STRING, "-command", "command", "Command",
        DEF_SCALE_COMMAND, Tk_Offset(TkScale, command), TK_CONFIG_NULL_OK},
        DEF_SCALE_COMMAND, Tk_Offset(TkScale, command), TK_CONFIG_NULL_OK},
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
        DEF_SCALE_CURSOR, Tk_Offset(TkScale, cursor), TK_CONFIG_NULL_OK},
        DEF_SCALE_CURSOR, Tk_Offset(TkScale, cursor), TK_CONFIG_NULL_OK},
    {TK_CONFIG_INT, "-digits", "digits", "Digits",
    {TK_CONFIG_INT, "-digits", "digits", "Digits",
        DEF_SCALE_DIGITS, Tk_Offset(TkScale, digits), 0},
        DEF_SCALE_DIGITS, Tk_Offset(TkScale, digits), 0},
    {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
    {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
        (char *) NULL, 0, 0},
        (char *) NULL, 0, 0},
    {TK_CONFIG_FONT, "-font", "font", "Font",
    {TK_CONFIG_FONT, "-font", "font", "Font",
        DEF_SCALE_FONT, Tk_Offset(TkScale, tkfont),
        DEF_SCALE_FONT, Tk_Offset(TkScale, tkfont),
        0},
        0},
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
        DEF_SCALE_FG_COLOR, Tk_Offset(TkScale, textColorPtr),
        DEF_SCALE_FG_COLOR, Tk_Offset(TkScale, textColorPtr),
        TK_CONFIG_COLOR_ONLY},
        TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
        DEF_SCALE_FG_MONO, Tk_Offset(TkScale, textColorPtr),
        DEF_SCALE_FG_MONO, Tk_Offset(TkScale, textColorPtr),
        TK_CONFIG_MONO_ONLY},
        TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_DOUBLE, "-from", "from", "From",
    {TK_CONFIG_DOUBLE, "-from", "from", "From",
        DEF_SCALE_FROM, Tk_Offset(TkScale, fromValue), 0},
        DEF_SCALE_FROM, Tk_Offset(TkScale, fromValue), 0},
    {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
    {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
        "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG,
        "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG,
        Tk_Offset(TkScale, highlightBgColorPtr), 0},
        Tk_Offset(TkScale, highlightBgColorPtr), 0},
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
        DEF_SCALE_HIGHLIGHT, Tk_Offset(TkScale, highlightColorPtr), 0},
        DEF_SCALE_HIGHLIGHT, Tk_Offset(TkScale, highlightColorPtr), 0},
    {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
    {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
        "HighlightThickness",
        "HighlightThickness",
        DEF_SCALE_HIGHLIGHT_WIDTH, Tk_Offset(TkScale, highlightWidth), 0},
        DEF_SCALE_HIGHLIGHT_WIDTH, Tk_Offset(TkScale, highlightWidth), 0},
    {TK_CONFIG_STRING, "-label", "label", "Label",
    {TK_CONFIG_STRING, "-label", "label", "Label",
        DEF_SCALE_LABEL, Tk_Offset(TkScale, label), TK_CONFIG_NULL_OK},
        DEF_SCALE_LABEL, Tk_Offset(TkScale, label), TK_CONFIG_NULL_OK},
    {TK_CONFIG_PIXELS, "-length", "length", "Length",
    {TK_CONFIG_PIXELS, "-length", "length", "Length",
        DEF_SCALE_LENGTH, Tk_Offset(TkScale, length), 0},
        DEF_SCALE_LENGTH, Tk_Offset(TkScale, length), 0},
    {TK_CONFIG_UID, "-orient", "orient", "Orient",
    {TK_CONFIG_UID, "-orient", "orient", "Orient",
        DEF_SCALE_ORIENT, Tk_Offset(TkScale, orientUid), 0},
        DEF_SCALE_ORIENT, Tk_Offset(TkScale, orientUid), 0},
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
        DEF_SCALE_RELIEF, Tk_Offset(TkScale, relief), 0},
        DEF_SCALE_RELIEF, Tk_Offset(TkScale, relief), 0},
    {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
    {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
        DEF_SCALE_REPEAT_DELAY, Tk_Offset(TkScale, repeatDelay), 0},
        DEF_SCALE_REPEAT_DELAY, Tk_Offset(TkScale, repeatDelay), 0},
    {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
    {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
        DEF_SCALE_REPEAT_INTERVAL, Tk_Offset(TkScale, repeatInterval), 0},
        DEF_SCALE_REPEAT_INTERVAL, Tk_Offset(TkScale, repeatInterval), 0},
    {TK_CONFIG_DOUBLE, "-resolution", "resolution", "Resolution",
    {TK_CONFIG_DOUBLE, "-resolution", "resolution", "Resolution",
        DEF_SCALE_RESOLUTION, Tk_Offset(TkScale, resolution), 0},
        DEF_SCALE_RESOLUTION, Tk_Offset(TkScale, resolution), 0},
    {TK_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
    {TK_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
        DEF_SCALE_SHOW_VALUE, Tk_Offset(TkScale, showValue), 0},
        DEF_SCALE_SHOW_VALUE, Tk_Offset(TkScale, showValue), 0},
    {TK_CONFIG_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
    {TK_CONFIG_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
        DEF_SCALE_SLIDER_LENGTH, Tk_Offset(TkScale, sliderLength), 0},
        DEF_SCALE_SLIDER_LENGTH, Tk_Offset(TkScale, sliderLength), 0},
    {TK_CONFIG_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
    {TK_CONFIG_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
        DEF_SCALE_SLIDER_RELIEF, Tk_Offset(TkScale, sliderRelief),
        DEF_SCALE_SLIDER_RELIEF, Tk_Offset(TkScale, sliderRelief),
        TK_CONFIG_DONT_SET_DEFAULT},
        TK_CONFIG_DONT_SET_DEFAULT},
    {TK_CONFIG_UID, "-state", "state", "State",
    {TK_CONFIG_UID, "-state", "state", "State",
        DEF_SCALE_STATE, Tk_Offset(TkScale, state), 0},
        DEF_SCALE_STATE, Tk_Offset(TkScale, state), 0},
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
        DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocus),
        DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocus),
        TK_CONFIG_NULL_OK},
        TK_CONFIG_NULL_OK},
    {TK_CONFIG_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
    {TK_CONFIG_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
        DEF_SCALE_TICK_INTERVAL, Tk_Offset(TkScale, tickInterval), 0},
        DEF_SCALE_TICK_INTERVAL, Tk_Offset(TkScale, tickInterval), 0},
    {TK_CONFIG_DOUBLE, "-to", "to", "To",
    {TK_CONFIG_DOUBLE, "-to", "to", "To",
        DEF_SCALE_TO, Tk_Offset(TkScale, toValue), 0},
        DEF_SCALE_TO, Tk_Offset(TkScale, toValue), 0},
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
        DEF_SCALE_TROUGH_COLOR, Tk_Offset(TkScale, troughColorPtr),
        DEF_SCALE_TROUGH_COLOR, Tk_Offset(TkScale, troughColorPtr),
        TK_CONFIG_COLOR_ONLY},
        TK_CONFIG_COLOR_ONLY},
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
    {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
        DEF_SCALE_TROUGH_MONO, Tk_Offset(TkScale, troughColorPtr),
        DEF_SCALE_TROUGH_MONO, Tk_Offset(TkScale, troughColorPtr),
        TK_CONFIG_MONO_ONLY},
        TK_CONFIG_MONO_ONLY},
    {TK_CONFIG_STRING, "-variable", "variable", "Variable",
    {TK_CONFIG_STRING, "-variable", "variable", "Variable",
        DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varName), TK_CONFIG_NULL_OK},
        DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varName), TK_CONFIG_NULL_OK},
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
        DEF_SCALE_WIDTH, Tk_Offset(TkScale, width), 0},
        DEF_SCALE_WIDTH, Tk_Offset(TkScale, width), 0},
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
        (char *) NULL, 0, 0}
        (char *) NULL, 0, 0}
};
};
 
 
/*
/*
 * Forward declarations for procedures defined later in this file:
 * Forward declarations for procedures defined later in this file:
 */
 */
 
 
static void             ComputeFormat _ANSI_ARGS_((TkScale *scalePtr));
static void             ComputeFormat _ANSI_ARGS_((TkScale *scalePtr));
static void             ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr));
static void             ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr));
static int              ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp,
static int              ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp,
                            TkScale *scalePtr, int argc, char **argv,
                            TkScale *scalePtr, int argc, char **argv,
                            int flags));
                            int flags));
static void             DestroyScale _ANSI_ARGS_((char *memPtr));
static void             DestroyScale _ANSI_ARGS_((char *memPtr));
static void             ScaleCmdDeletedProc _ANSI_ARGS_((
static void             ScaleCmdDeletedProc _ANSI_ARGS_((
                            ClientData clientData));
                            ClientData clientData));
static void             ScaleEventProc _ANSI_ARGS_((ClientData clientData,
static void             ScaleEventProc _ANSI_ARGS_((ClientData clientData,
                            XEvent *eventPtr));
                            XEvent *eventPtr));
static char *           ScaleVarProc _ANSI_ARGS_((ClientData clientData,
static char *           ScaleVarProc _ANSI_ARGS_((ClientData clientData,
                            Tcl_Interp *interp, char *name1, char *name2,
                            Tcl_Interp *interp, char *name1, char *name2,
                            int flags));
                            int flags));
static int              ScaleWidgetCmd _ANSI_ARGS_((ClientData clientData,
static int              ScaleWidgetCmd _ANSI_ARGS_((ClientData clientData,
                            Tcl_Interp *interp, int argc, char **argv));
                            Tcl_Interp *interp, int argc, char **argv));
static void             ScaleWorldChanged _ANSI_ARGS_((
static void             ScaleWorldChanged _ANSI_ARGS_((
                            ClientData instanceData));
                            ClientData instanceData));
 
 
/*
/*
 * The structure below defines scale class behavior by means of procedures
 * The structure below defines scale class behavior by means of procedures
 * that can be invoked from generic window code.
 * that can be invoked from generic window code.
 */
 */
 
 
static TkClassProcs scaleClass = {
static TkClassProcs scaleClass = {
    NULL,                       /* createProc. */
    NULL,                       /* createProc. */
    ScaleWorldChanged,          /* geometryProc. */
    ScaleWorldChanged,          /* geometryProc. */
    NULL                        /* modalProc. */
    NULL                        /* modalProc. */
};
};
 
 


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_ScaleCmd --
 * Tk_ScaleCmd --
 *
 *
 *      This procedure is invoked to process the "scale" Tcl
 *      This procedure is invoked to process the "scale" Tcl
 *      command.  See the user documentation for details on what
 *      command.  See the user documentation for details on what
 *      it does.
 *      it does.
 *
 *
 * Results:
 * Results:
 *      A standard Tcl result.
 *      A standard Tcl result.
 *
 *
 * Side effects:
 * Side effects:
 *      See the user documentation.
 *      See the user documentation.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
int
int
Tk_ScaleCmd(clientData, interp, argc, argv)
Tk_ScaleCmd(clientData, interp, argc, argv)
    ClientData clientData;              /* Main window associated with
    ClientData clientData;              /* Main window associated with
                                 * interpreter. */
                                 * interpreter. */
    Tcl_Interp *interp;         /* Current interpreter. */
    Tcl_Interp *interp;         /* Current interpreter. */
    int argc;                   /* Number of arguments. */
    int argc;                   /* Number of arguments. */
    char **argv;                /* Argument strings. */
    char **argv;                /* Argument strings. */
{
{
    Tk_Window tkwin = (Tk_Window) clientData;
    Tk_Window tkwin = (Tk_Window) clientData;
    register TkScale *scalePtr;
    register TkScale *scalePtr;
    Tk_Window new;
    Tk_Window new;
 
 
    if (argc < 2) {
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_AppendResult(interp, "wrong # args: should be \"",
                argv[0], " pathName ?options?\"", (char *) NULL);
                argv[0], " pathName ?options?\"", (char *) NULL);
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
 
 
    new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
    new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
    if (new == NULL) {
    if (new == NULL) {
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
    scalePtr = TkpCreateScale(new);
    scalePtr = TkpCreateScale(new);
 
 
    /*
    /*
     * Initialize fields that won't be initialized by ConfigureScale,
     * Initialize fields that won't be initialized by ConfigureScale,
     * or which ConfigureScale expects to have reasonable values
     * or which ConfigureScale expects to have reasonable values
     * (e.g. resource pointers).
     * (e.g. resource pointers).
     */
     */
 
 
    scalePtr->tkwin = new;
    scalePtr->tkwin = new;
    scalePtr->display = Tk_Display(new);
    scalePtr->display = Tk_Display(new);
    scalePtr->interp = interp;
    scalePtr->interp = interp;
    scalePtr->widgetCmd = Tcl_CreateCommand(interp,
    scalePtr->widgetCmd = Tcl_CreateCommand(interp,
            Tk_PathName(scalePtr->tkwin), ScaleWidgetCmd,
            Tk_PathName(scalePtr->tkwin), ScaleWidgetCmd,
            (ClientData) scalePtr, ScaleCmdDeletedProc);
            (ClientData) scalePtr, ScaleCmdDeletedProc);
    scalePtr->orientUid = NULL;
    scalePtr->orientUid = NULL;
    scalePtr->vertical = 0;
    scalePtr->vertical = 0;
    scalePtr->width = 0;
    scalePtr->width = 0;
    scalePtr->length = 0;
    scalePtr->length = 0;
    scalePtr->value = 0;
    scalePtr->value = 0;
    scalePtr->varName = NULL;
    scalePtr->varName = NULL;
    scalePtr->fromValue = 0;
    scalePtr->fromValue = 0;
    scalePtr->toValue = 0;
    scalePtr->toValue = 0;
    scalePtr->tickInterval = 0;
    scalePtr->tickInterval = 0;
    scalePtr->resolution = 1;
    scalePtr->resolution = 1;
    scalePtr->bigIncrement = 0.0;
    scalePtr->bigIncrement = 0.0;
    scalePtr->command = NULL;
    scalePtr->command = NULL;
    scalePtr->repeatDelay = 0;
    scalePtr->repeatDelay = 0;
    scalePtr->repeatInterval = 0;
    scalePtr->repeatInterval = 0;
    scalePtr->label = NULL;
    scalePtr->label = NULL;
    scalePtr->labelLength = 0;
    scalePtr->labelLength = 0;
    scalePtr->state = tkNormalUid;
    scalePtr->state = tkNormalUid;
    scalePtr->borderWidth = 0;
    scalePtr->borderWidth = 0;
    scalePtr->bgBorder = NULL;
    scalePtr->bgBorder = NULL;
    scalePtr->activeBorder = NULL;
    scalePtr->activeBorder = NULL;
    scalePtr->sliderRelief = TK_RELIEF_RAISED;
    scalePtr->sliderRelief = TK_RELIEF_RAISED;
    scalePtr->troughColorPtr = NULL;
    scalePtr->troughColorPtr = NULL;
    scalePtr->troughGC = None;
    scalePtr->troughGC = None;
    scalePtr->copyGC = None;
    scalePtr->copyGC = None;
    scalePtr->tkfont = NULL;
    scalePtr->tkfont = NULL;
    scalePtr->textColorPtr = NULL;
    scalePtr->textColorPtr = NULL;
    scalePtr->textGC = None;
    scalePtr->textGC = None;
    scalePtr->relief = TK_RELIEF_FLAT;
    scalePtr->relief = TK_RELIEF_FLAT;
    scalePtr->highlightWidth = 0;
    scalePtr->highlightWidth = 0;
    scalePtr->highlightBgColorPtr = NULL;
    scalePtr->highlightBgColorPtr = NULL;
    scalePtr->highlightColorPtr = NULL;
    scalePtr->highlightColorPtr = NULL;
    scalePtr->inset = 0;
    scalePtr->inset = 0;
    scalePtr->sliderLength = 0;
    scalePtr->sliderLength = 0;
    scalePtr->showValue = 0;
    scalePtr->showValue = 0;
    scalePtr->horizLabelY = 0;
    scalePtr->horizLabelY = 0;
    scalePtr->horizValueY = 0;
    scalePtr->horizValueY = 0;
    scalePtr->horizTroughY = 0;
    scalePtr->horizTroughY = 0;
    scalePtr->horizTickY = 0;
    scalePtr->horizTickY = 0;
    scalePtr->vertTickRightX = 0;
    scalePtr->vertTickRightX = 0;
    scalePtr->vertValueRightX = 0;
    scalePtr->vertValueRightX = 0;
    scalePtr->vertTroughX = 0;
    scalePtr->vertTroughX = 0;
    scalePtr->vertLabelX = 0;
    scalePtr->vertLabelX = 0;
    scalePtr->cursor = None;
    scalePtr->cursor = None;
    scalePtr->takeFocus = NULL;
    scalePtr->takeFocus = NULL;
    scalePtr->flags = NEVER_SET;
    scalePtr->flags = NEVER_SET;
 
 
    Tk_SetClass(scalePtr->tkwin, "Scale");
    Tk_SetClass(scalePtr->tkwin, "Scale");
    TkSetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);
    TkSetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);
    Tk_CreateEventHandler(scalePtr->tkwin,
    Tk_CreateEventHandler(scalePtr->tkwin,
            ExposureMask|StructureNotifyMask|FocusChangeMask,
            ExposureMask|StructureNotifyMask|FocusChangeMask,
            ScaleEventProc, (ClientData) scalePtr);
            ScaleEventProc, (ClientData) scalePtr);
    if (ConfigureScale(interp, scalePtr, argc-2, argv+2, 0) != TCL_OK) {
    if (ConfigureScale(interp, scalePtr, argc-2, argv+2, 0) != TCL_OK) {
        goto error;
        goto error;
    }
    }
 
 
    interp->result = Tk_PathName(scalePtr->tkwin);
    interp->result = Tk_PathName(scalePtr->tkwin);
    return TCL_OK;
    return TCL_OK;
 
 
    error:
    error:
    Tk_DestroyWindow(scalePtr->tkwin);
    Tk_DestroyWindow(scalePtr->tkwin);
    return TCL_ERROR;
    return TCL_ERROR;
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * ScaleWidgetCmd --
 * ScaleWidgetCmd --
 *
 *
 *      This procedure is invoked to process the Tcl command
 *      This procedure is invoked to process the Tcl command
 *      that corresponds to a widget managed by this module.
 *      that corresponds to a widget managed by this module.
 *      See the user documentation for details on what it does.
 *      See the user documentation for details on what it does.
 *
 *
 * Results:
 * Results:
 *      A standard Tcl result.
 *      A standard Tcl result.
 *
 *
 * Side effects:
 * Side effects:
 *      See the user documentation.
 *      See the user documentation.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
static int
static int
ScaleWidgetCmd(clientData, interp, argc, argv)
ScaleWidgetCmd(clientData, interp, argc, argv)
    ClientData clientData;              /* Information about scale
    ClientData clientData;              /* Information about scale
                                         * widget. */
                                         * widget. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
    char **argv;                        /* Argument strings. */
{
{
    register TkScale *scalePtr = (TkScale *) clientData;
    register TkScale *scalePtr = (TkScale *) clientData;
    int result = TCL_OK;
    int result = TCL_OK;
    size_t length;
    size_t length;
    int c;
    int c;
 
 
    if (argc < 2) {
    if (argc < 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_AppendResult(interp, "wrong # args: should be \"",
                argv[0], " option ?arg arg ...?\"", (char *) NULL);
                argv[0], " option ?arg arg ...?\"", (char *) NULL);
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
    Tcl_Preserve((ClientData) scalePtr);
    Tcl_Preserve((ClientData) scalePtr);
    c = argv[1][0];
    c = argv[1][0];
    length = strlen(argv[1]);
    length = strlen(argv[1]);
    if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
    if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
            && (length >= 2)) {
            && (length >= 2)) {
        if (argc != 3) {
        if (argc != 3) {
            Tcl_AppendResult(interp, "wrong # args: should be \"",
            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    argv[0], " cget option\"",
                    argv[0], " cget option\"",
                    (char *) NULL);
                    (char *) NULL);
            goto error;
            goto error;
        }
        }
        result = Tk_ConfigureValue(interp, scalePtr->tkwin, configSpecs,
        result = Tk_ConfigureValue(interp, scalePtr->tkwin, configSpecs,
                (char *) scalePtr, argv[2], 0);
                (char *) scalePtr, argv[2], 0);
    } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
    } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
            && (length >= 3)) {
            && (length >= 3)) {
        if (argc == 2) {
        if (argc == 2) {
            result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
            result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
                    (char *) scalePtr, (char *) NULL, 0);
                    (char *) scalePtr, (char *) NULL, 0);
        } else if (argc == 3) {
        } else if (argc == 3) {
            result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
            result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
                    (char *) scalePtr, argv[2], 0);
                    (char *) scalePtr, argv[2], 0);
        } else {
        } else {
            result = ConfigureScale(interp, scalePtr, argc-2, argv+2,
            result = ConfigureScale(interp, scalePtr, argc-2, argv+2,
                    TK_CONFIG_ARGV_ONLY);
                    TK_CONFIG_ARGV_ONLY);
        }
        }
    } else if ((c == 'c') && (strncmp(argv[1], "coords", length) == 0)
    } else if ((c == 'c') && (strncmp(argv[1], "coords", length) == 0)
            && (length >= 3)) {
            && (length >= 3)) {
        int x, y ;
        int x, y ;
        double value;
        double value;
 
 
        if ((argc != 2) && (argc != 3)) {
        if ((argc != 2) && (argc != 3)) {
            Tcl_AppendResult(interp, "wrong # args: should be \"",
            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    argv[0], " coords ?value?\"", (char *) NULL);
                    argv[0], " coords ?value?\"", (char *) NULL);
            goto error;
            goto error;
        }
        }
        if (argc == 3) {
        if (argc == 3) {
            if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
            if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
                goto error;
                goto error;
            }
            }
        } else {
        } else {
            value = scalePtr->value;
            value = scalePtr->value;
        }
        }
        if (scalePtr->vertical) {
        if (scalePtr->vertical) {
            x = scalePtr->vertTroughX + scalePtr->width/2
            x = scalePtr->vertTroughX + scalePtr->width/2
                    + scalePtr->borderWidth;
                    + scalePtr->borderWidth;
            y = TkpValueToPixel(scalePtr, value);
            y = TkpValueToPixel(scalePtr, value);
        } else {
        } else {
            x = TkpValueToPixel(scalePtr, value);
            x = TkpValueToPixel(scalePtr, value);
            y = scalePtr->horizTroughY + scalePtr->width/2
            y = scalePtr->horizTroughY + scalePtr->width/2
                    + scalePtr->borderWidth;
                    + scalePtr->borderWidth;
        }
        }
        sprintf(interp->result, "%d %d", x, y);
        sprintf(interp->result, "%d %d", x, y);
    } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
    } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
        double value;
        double value;
        int x, y;
        int x, y;
 
 
        if ((argc != 2) && (argc != 4)) {
        if ((argc != 2) && (argc != 4)) {
            Tcl_AppendResult(interp, "wrong # args: should be \"",
            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    argv[0], " get ?x y?\"", (char *) NULL);
                    argv[0], " get ?x y?\"", (char *) NULL);
            goto error;
            goto error;
        }
        }
        if (argc == 2) {
        if (argc == 2) {
            value = scalePtr->value;
            value = scalePtr->value;
        } else {
        } else {
            if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
            if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
                    || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
                    || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
                goto error;
                goto error;
            }
            }
            value = TkpPixelToValue(scalePtr, x, y);
            value = TkpPixelToValue(scalePtr, x, y);
        }
        }
        sprintf(interp->result, scalePtr->format, value);
        sprintf(interp->result, scalePtr->format, value);
    } else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
    } else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
        int x, y, thing;
        int x, y, thing;
 
 
        if (argc != 4) {
        if (argc != 4) {
            Tcl_AppendResult(interp, "wrong # args: should be \"",
            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    argv[0], " identify x y\"", (char *) NULL);
                    argv[0], " identify x y\"", (char *) NULL);
            goto error;
            goto error;
        }
        }
        if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
        if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
                || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
                || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
            goto error;
            goto error;
        }
        }
        thing = TkpScaleElement(scalePtr, x,y);
        thing = TkpScaleElement(scalePtr, x,y);
        switch (thing) {
        switch (thing) {
            case TROUGH1:       interp->result = "trough1";     break;
            case TROUGH1:       interp->result = "trough1";     break;
            case SLIDER:        interp->result = "slider";      break;
            case SLIDER:        interp->result = "slider";      break;
            case TROUGH2:       interp->result = "trough2";     break;
            case TROUGH2:       interp->result = "trough2";     break;
        }
        }
    } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) {
    } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) {
        double value;
        double value;
 
 
        if (argc != 3) {
        if (argc != 3) {
            Tcl_AppendResult(interp, "wrong # args: should be \"",
            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    argv[0], " set value\"", (char *) NULL);
                    argv[0], " set value\"", (char *) NULL);
            goto error;
            goto error;
        }
        }
        if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
        if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
            goto error;
            goto error;
        }
        }
        if (scalePtr->state != tkDisabledUid) {
        if (scalePtr->state != tkDisabledUid) {
            TkpSetScaleValue(scalePtr, value, 1, 1);
            TkpSetScaleValue(scalePtr, value, 1, 1);
        }
        }
    } else {
    } else {
        Tcl_AppendResult(interp, "bad option \"", argv[1],
        Tcl_AppendResult(interp, "bad option \"", argv[1],
                "\": must be cget, configure, coords, get, identify, or set",
                "\": must be cget, configure, coords, get, identify, or set",
                (char *) NULL);
                (char *) NULL);
        goto error;
        goto error;
    }
    }
    Tcl_Release((ClientData) scalePtr);
    Tcl_Release((ClientData) scalePtr);
    return result;
    return result;
 
 
    error:
    error:
    Tcl_Release((ClientData) scalePtr);
    Tcl_Release((ClientData) scalePtr);
    return TCL_ERROR;
    return TCL_ERROR;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * DestroyScale --
 * DestroyScale --
 *
 *
 *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
 *      This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
 *      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
 *      (when no-one is using it anymore).
 *      (when no-one is using it anymore).
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Everything associated with the scale is freed up.
 *      Everything associated with the scale is freed up.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
DestroyScale(memPtr)
DestroyScale(memPtr)
    char *memPtr;       /* Info about scale widget. */
    char *memPtr;       /* Info about scale widget. */
{
{
    register TkScale *scalePtr = (TkScale *) memPtr;
    register TkScale *scalePtr = (TkScale *) memPtr;
 
 
    /*
    /*
     * Free up all the stuff that requires special handling, then
     * Free up all the stuff that requires special handling, then
     * let Tk_FreeOptions handle all the standard option-related
     * let Tk_FreeOptions handle all the standard option-related
     * stuff.
     * stuff.
     */
     */
 
 
    if (scalePtr->varName != NULL) {
    if (scalePtr->varName != NULL) {
        Tcl_UntraceVar(scalePtr->interp, scalePtr->varName,
        Tcl_UntraceVar(scalePtr->interp, scalePtr->varName,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                ScaleVarProc, (ClientData) scalePtr);
                ScaleVarProc, (ClientData) scalePtr);
    }
    }
    if (scalePtr->troughGC != None) {
    if (scalePtr->troughGC != None) {
        Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
        Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
    }
    }
    if (scalePtr->copyGC != None) {
    if (scalePtr->copyGC != None) {
        Tk_FreeGC(scalePtr->display, scalePtr->copyGC);
        Tk_FreeGC(scalePtr->display, scalePtr->copyGC);
    }
    }
    if (scalePtr->textGC != None) {
    if (scalePtr->textGC != None) {
        Tk_FreeGC(scalePtr->display, scalePtr->textGC);
        Tk_FreeGC(scalePtr->display, scalePtr->textGC);
    }
    }
    Tk_FreeOptions(configSpecs, (char *) scalePtr, scalePtr->display, 0);
    Tk_FreeOptions(configSpecs, (char *) scalePtr, scalePtr->display, 0);
    TkpDestroyScale(scalePtr);
    TkpDestroyScale(scalePtr);
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * ConfigureScale --
 * ConfigureScale --
 *
 *
 *      This procedure is called to process an argv/argc list, plus
 *      This procedure is called to process an argv/argc list, plus
 *      the Tk option database, in order to configure (or
 *      the Tk option database, in order to configure (or
 *      reconfigure) a scale widget.
 *      reconfigure) a scale widget.
 *
 *
 * Results:
 * Results:
 *      The return value is a standard Tcl result.  If TCL_ERROR is
 *      The return value is a standard Tcl result.  If TCL_ERROR is
 *      returned, then interp->result contains an error message.
 *      returned, then interp->result contains an error message.
 *
 *
 * Side effects:
 * Side effects:
 *      Configuration information, such as colors, border width,
 *      Configuration information, such as colors, border width,
 *      etc. get set for scalePtr;  old resources get freed,
 *      etc. get set for scalePtr;  old resources get freed,
 *      if there were any.
 *      if there were any.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static int
static int
ConfigureScale(interp, scalePtr, argc, argv, flags)
ConfigureScale(interp, scalePtr, argc, argv, flags)
    Tcl_Interp *interp;         /* Used for error reporting. */
    Tcl_Interp *interp;         /* Used for error reporting. */
    register TkScale *scalePtr; /* Information about widget;  may or may
    register TkScale *scalePtr; /* Information about widget;  may or may
                                 * not already have values for some fields. */
                                 * not already have values for some fields. */
    int argc;                   /* Number of valid entries in argv. */
    int argc;                   /* Number of valid entries in argv. */
    char **argv;                /* Arguments. */
    char **argv;                /* Arguments. */
    int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
    int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
{
{
    size_t length;
    size_t length;
 
 
    /*
    /*
     * Eliminate any existing trace on a variable monitored by the scale.
     * Eliminate any existing trace on a variable monitored by the scale.
     */
     */
 
 
    if (scalePtr->varName != NULL) {
    if (scalePtr->varName != NULL) {
        Tcl_UntraceVar(interp, scalePtr->varName,
        Tcl_UntraceVar(interp, scalePtr->varName,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                ScaleVarProc, (ClientData) scalePtr);
                ScaleVarProc, (ClientData) scalePtr);
    }
    }
 
 
    if (Tk_ConfigureWidget(interp, scalePtr->tkwin, configSpecs,
    if (Tk_ConfigureWidget(interp, scalePtr->tkwin, configSpecs,
            argc, argv, (char *) scalePtr, flags) != TCL_OK) {
            argc, argv, (char *) scalePtr, flags) != TCL_OK) {
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
 
 
    /*
    /*
     * If the scale is tied to the value of a variable, then set up
     * If the scale is tied to the value of a variable, then set up
     * a trace on the variable's value and set the scale's value from
     * a trace on the variable's value and set the scale's value from
     * the value of the variable, if it exists.
     * the value of the variable, if it exists.
     */
     */
 
 
    if (scalePtr->varName != NULL) {
    if (scalePtr->varName != NULL) {
        char *stringValue, *end;
        char *stringValue, *end;
        double value;
        double value;
 
 
        stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
        stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
        if (stringValue != NULL) {
        if (stringValue != NULL) {
            value = strtod(stringValue, &end);
            value = strtod(stringValue, &end);
            if ((end != stringValue) && (*end == 0)) {
            if ((end != stringValue) && (*end == 0)) {
                scalePtr->value = TkRoundToResolution(scalePtr, value);
                scalePtr->value = TkRoundToResolution(scalePtr, value);
            }
            }
        }
        }
        Tcl_TraceVar(interp, scalePtr->varName,
        Tcl_TraceVar(interp, scalePtr->varName,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                ScaleVarProc, (ClientData) scalePtr);
                ScaleVarProc, (ClientData) scalePtr);
    }
    }
 
 
    /*
    /*
     * Several options need special processing, such as parsing the
     * Several options need special processing, such as parsing the
     * orientation and creating GCs.
     * orientation and creating GCs.
     */
     */
 
 
    length = strlen(scalePtr->orientUid);
    length = strlen(scalePtr->orientUid);
    if (strncmp(scalePtr->orientUid, "vertical", length) == 0) {
    if (strncmp(scalePtr->orientUid, "vertical", length) == 0) {
        scalePtr->vertical = 1;
        scalePtr->vertical = 1;
    } else if (strncmp(scalePtr->orientUid, "horizontal", length) == 0) {
    } else if (strncmp(scalePtr->orientUid, "horizontal", length) == 0) {
        scalePtr->vertical = 0;
        scalePtr->vertical = 0;
    } else {
    } else {
        Tcl_AppendResult(interp, "bad orientation \"", scalePtr->orientUid,
        Tcl_AppendResult(interp, "bad orientation \"", scalePtr->orientUid,
                "\": must be vertical or horizontal", (char *) NULL);
                "\": must be vertical or horizontal", (char *) NULL);
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
 
 
    scalePtr->fromValue = TkRoundToResolution(scalePtr, scalePtr->fromValue);
    scalePtr->fromValue = TkRoundToResolution(scalePtr, scalePtr->fromValue);
    scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
    scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
    scalePtr->tickInterval = TkRoundToResolution(scalePtr,
    scalePtr->tickInterval = TkRoundToResolution(scalePtr,
            scalePtr->tickInterval);
            scalePtr->tickInterval);
 
 
    /*
    /*
     * Make sure that the tick interval has the right sign so that
     * Make sure that the tick interval has the right sign so that
     * addition moves from fromValue to toValue.
     * addition moves from fromValue to toValue.
     */
     */
 
 
    if ((scalePtr->tickInterval < 0)
    if ((scalePtr->tickInterval < 0)
            ^ ((scalePtr->toValue - scalePtr->fromValue) <  0)) {
            ^ ((scalePtr->toValue - scalePtr->fromValue) <  0)) {
        scalePtr->tickInterval = -scalePtr->tickInterval;
        scalePtr->tickInterval = -scalePtr->tickInterval;
    }
    }
 
 
    /*
    /*
     * 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
     * that the scale's value is within the new acceptable range for
     * that the scale's value is within the new acceptable range for
     * the scale and reflect the value in the associated variable,
     * the scale and reflect the value in the associated variable,
     * if any.
     * if any.
     */
     */
 
 
    ComputeFormat(scalePtr);
    ComputeFormat(scalePtr);
    TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
    TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
 
 
    if (scalePtr->label != NULL) {
    if (scalePtr->label != NULL) {
        scalePtr->labelLength = strlen(scalePtr->label);
        scalePtr->labelLength = strlen(scalePtr->label);
    } else {
    } else {
        scalePtr->labelLength = 0;
        scalePtr->labelLength = 0;
    }
    }
 
 
    if ((scalePtr->state != tkNormalUid)
    if ((scalePtr->state != tkNormalUid)
            && (scalePtr->state != tkDisabledUid)
            && (scalePtr->state != tkDisabledUid)
            && (scalePtr->state != tkActiveUid)) {
            && (scalePtr->state != tkActiveUid)) {
        Tcl_AppendResult(interp, "bad state value \"", scalePtr->state,
        Tcl_AppendResult(interp, "bad state value \"", scalePtr->state,
                "\": must be normal, active, or disabled", (char *) NULL);
                "\": must be normal, active, or disabled", (char *) NULL);
        scalePtr->state = tkNormalUid;
        scalePtr->state = tkNormalUid;
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
 
 
    Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
    Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
 
 
    if (scalePtr->highlightWidth < 0) {
    if (scalePtr->highlightWidth < 0) {
        scalePtr->highlightWidth = 0;
        scalePtr->highlightWidth = 0;
    }
    }
    scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
    scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
 
 
    ScaleWorldChanged((ClientData) scalePtr);
    ScaleWorldChanged((ClientData) scalePtr);
    return TCL_OK;
    return TCL_OK;
}
}


/*
/*
 *---------------------------------------------------------------------------
 *---------------------------------------------------------------------------
 *
 *
 * ScaleWorldChanged --
 * ScaleWorldChanged --
 *
 *
 *      This procedure is called when the world has changed in some
 *      This procedure is called when the world has changed in some
 *      way and the widget needs to recompute all its graphics contexts
 *      way and the widget needs to recompute all its graphics contexts
 *      and determine its new geometry.
 *      and determine its new geometry.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Scale will be relayed out and redisplayed.
 *      Scale will be relayed out and redisplayed.
 *
 *
 *---------------------------------------------------------------------------
 *---------------------------------------------------------------------------
 */
 */
 
 
static void
static void
ScaleWorldChanged(instanceData)
ScaleWorldChanged(instanceData)
    ClientData instanceData;    /* Information about widget. */
    ClientData instanceData;    /* Information about widget. */
{
{
    XGCValues gcValues;
    XGCValues gcValues;
    GC gc;
    GC gc;
    TkScale *scalePtr;
    TkScale *scalePtr;
 
 
    scalePtr = (TkScale *) instanceData;
    scalePtr = (TkScale *) instanceData;
 
 
    gcValues.foreground = scalePtr->troughColorPtr->pixel;
    gcValues.foreground = scalePtr->troughColorPtr->pixel;
    gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground, &gcValues,
    gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground, &gcValues,
                       scalePtr->troughColorPtr, NULL);
                       scalePtr->troughColorPtr, NULL);
    if (scalePtr->troughGC != None) {
    if (scalePtr->troughGC != None) {
        Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
        Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
    }
    }
    scalePtr->troughGC = gc;
    scalePtr->troughGC = gc;
 
 
    gcValues.font = Tk_FontId(scalePtr->tkfont);
    gcValues.font = Tk_FontId(scalePtr->tkfont);
    gcValues.foreground = scalePtr->textColorPtr->pixel;
    gcValues.foreground = scalePtr->textColorPtr->pixel;
    gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground | GCFont, &gcValues,
    gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground | GCFont, &gcValues,
                       scalePtr->textColorPtr, NULL);
                       scalePtr->textColorPtr, NULL);
    if (scalePtr->textGC != None) {
    if (scalePtr->textGC != None) {
        Tk_FreeGC(scalePtr->display, scalePtr->textGC);
        Tk_FreeGC(scalePtr->display, scalePtr->textGC);
    }
    }
    scalePtr->textGC = gc;
    scalePtr->textGC = gc;
 
 
    if (scalePtr->copyGC == None) {
    if (scalePtr->copyGC == None) {
        gcValues.graphics_exposures = False;
        gcValues.graphics_exposures = False;
        scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,
        scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,
            &gcValues);
            &gcValues);
    }
    }
    scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
    scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
 
 
    /*
    /*
     * Recompute display-related information, and let the geometry
     * Recompute display-related information, and let the geometry
     * manager know how much space is needed now.
     * manager know how much space is needed now.
     */
     */
 
 
    ComputeScaleGeometry(scalePtr);
    ComputeScaleGeometry(scalePtr);
 
 
    TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
    TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * ComputeFormat --
 * ComputeFormat --
 *
 *
 *      This procedure is invoked to recompute the "format" field
 *      This procedure is invoked to recompute the "format" field
 *      of a scale's widget record, which determines how the value
 *      of a scale's widget record, which determines how the value
 *      of the scale is converted to a string.
 *      of the scale is converted to a string.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The format field of scalePtr is modified.
 *      The format field of scalePtr is modified.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
ComputeFormat(scalePtr)
ComputeFormat(scalePtr)
    TkScale *scalePtr;                  /* Information about scale widget. */
    TkScale *scalePtr;                  /* Information about scale widget. */
{
{
    double maxValue, x;
    double maxValue, x;
    int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
    int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
    int eDigits, fDigits;
    int eDigits, fDigits;
 
 
    /*
    /*
     * Compute the displacement from the decimal of the most significant
     * Compute the displacement from the decimal of the most significant
     * digit required for any number in the scale's range.
     * digit required for any number in the scale's range.
     */
     */
 
 
    maxValue = fabs(scalePtr->fromValue);
    maxValue = fabs(scalePtr->fromValue);
    x = fabs(scalePtr->toValue);
    x = fabs(scalePtr->toValue);
    if (x > maxValue) {
    if (x > maxValue) {
        maxValue = x;
        maxValue = x;
    }
    }
    if (maxValue == 0) {
    if (maxValue == 0) {
        maxValue = 1;
        maxValue = 1;
    }
    }
    mostSigDigit = (int) floor(log10(maxValue));
    mostSigDigit = (int) floor(log10(maxValue));
 
 
    /*
    /*
     * If the number of significant digits wasn't specified explicitly,
     * If the number of significant digits wasn't specified explicitly,
     * compute it. It's the difference between the most significant
     * compute it. It's the difference between the most significant
     * digit needed to represent any number on the scale and the
     * digit needed to represent any number on the scale and the
     * most significant digit of the smallest difference between
     * most significant digit of the smallest difference between
     * numbers on the scale.  In other words, display enough digits so
     * numbers on the scale.  In other words, display enough digits so
     * that at least one digit will be different between any two adjacent
     * that at least one digit will be different between any two adjacent
     * positions of the scale.
     * positions of the scale.
     */
     */
 
 
    numDigits = scalePtr->digits;
    numDigits = scalePtr->digits;
    if (numDigits <= 0) {
    if (numDigits <= 0) {
        if  (scalePtr->resolution > 0) {
        if  (scalePtr->resolution > 0) {
            /*
            /*
             * A resolution was specified for the scale, so just use it.
             * A resolution was specified for the scale, so just use it.
             */
             */
 
 
            leastSigDigit = (int) floor(log10(scalePtr->resolution));
            leastSigDigit = (int) floor(log10(scalePtr->resolution));
        } else {
        } else {
            /*
            /*
             * No resolution was specified, so compute the difference
             * No resolution was specified, so compute the difference
             * in value between adjacent pixels and use it for the least
             * in value between adjacent pixels and use it for the least
             * significant digit.
             * significant digit.
             */
             */
 
 
            x = fabs(scalePtr->fromValue - scalePtr->toValue);
            x = fabs(scalePtr->fromValue - scalePtr->toValue);
            if (scalePtr->length > 0) {
            if (scalePtr->length > 0) {
                x /= scalePtr->length;
                x /= scalePtr->length;
            }
            }
            if (x > 0){
            if (x > 0){
                leastSigDigit = (int) floor(log10(x));
                leastSigDigit = (int) floor(log10(x));
            } else {
            } else {
                leastSigDigit = 0;
                leastSigDigit = 0;
            }
            }
        }
        }
        numDigits = mostSigDigit - leastSigDigit + 1;
        numDigits = mostSigDigit - leastSigDigit + 1;
        if (numDigits < 1) {
        if (numDigits < 1) {
            numDigits = 1;
            numDigits = 1;
        }
        }
    }
    }
 
 
    /*
    /*
     * Compute the number of characters required using "e" format and
     * Compute the number of characters required using "e" format and
     * "f" format, and then choose whichever one takes fewer characters.
     * "f" format, and then choose whichever one takes fewer characters.
     */
     */
 
 
    eDigits = numDigits + 4;
    eDigits = numDigits + 4;
    if (numDigits > 1) {
    if (numDigits > 1) {
        eDigits++;                      /* Decimal point. */
        eDigits++;                      /* Decimal point. */
    }
    }
    afterDecimal = numDigits - mostSigDigit - 1;
    afterDecimal = numDigits - mostSigDigit - 1;
    if (afterDecimal < 0) {
    if (afterDecimal < 0) {
        afterDecimal = 0;
        afterDecimal = 0;
    }
    }
    fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
    fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
    if (afterDecimal > 0) {
    if (afterDecimal > 0) {
        fDigits++;                      /* Decimal point. */
        fDigits++;                      /* Decimal point. */
    }
    }
    if (mostSigDigit < 0) {
    if (mostSigDigit < 0) {
        fDigits++;                      /* Zero to left of decimal point. */
        fDigits++;                      /* Zero to left of decimal point. */
    }
    }
    if (fDigits <= eDigits) {
    if (fDigits <= eDigits) {
        sprintf(scalePtr->format, "%%.%df", afterDecimal);
        sprintf(scalePtr->format, "%%.%df", afterDecimal);
    } else {
    } else {
        sprintf(scalePtr->format, "%%.%de", numDigits-1);
        sprintf(scalePtr->format, "%%.%de", numDigits-1);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * ComputeScaleGeometry --
 * ComputeScaleGeometry --
 *
 *
 *      This procedure is called to compute various geometrical
 *      This procedure is called to compute various geometrical
 *      information for a scale, such as where various things get
 *      information for a scale, such as where various things get
 *      displayed.  It's called when the window is reconfigured.
 *      displayed.  It's called when the window is reconfigured.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Display-related numbers get changed in *scalePtr.  The
 *      Display-related numbers get changed in *scalePtr.  The
 *      geometry manager gets told about the window's preferred size.
 *      geometry manager gets told about the window's preferred size.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
ComputeScaleGeometry(scalePtr)
ComputeScaleGeometry(scalePtr)
    register TkScale *scalePtr;         /* Information about widget. */
    register TkScale *scalePtr;         /* Information about widget. */
{
{
    char valueString[PRINT_CHARS];
    char valueString[PRINT_CHARS];
    int tmp, valuePixels, x, y, extraSpace;
    int tmp, valuePixels, x, y, extraSpace;
    Tk_FontMetrics fm;
    Tk_FontMetrics fm;
 
 
    /*
    /*
     * Horizontal scales are simpler than vertical ones because
     * Horizontal scales are simpler than vertical ones because
     * all sizes are the same (the height of a line of text);
     * all sizes are the same (the height of a line of text);
     * handle them first and then quit.
     * handle them first and then quit.
     */
     */
 
 
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
    if (!scalePtr->vertical) {
    if (!scalePtr->vertical) {
        y = scalePtr->inset;
        y = scalePtr->inset;
        extraSpace = 0;
        extraSpace = 0;
        if (scalePtr->labelLength != 0) {
        if (scalePtr->labelLength != 0) {
            scalePtr->horizLabelY = y + SPACING;
            scalePtr->horizLabelY = y + SPACING;
            y += fm.linespace + SPACING;
            y += fm.linespace + SPACING;
            extraSpace = SPACING;
            extraSpace = SPACING;
        }
        }
        if (scalePtr->showValue) {
        if (scalePtr->showValue) {
            scalePtr->horizValueY = y + SPACING;
            scalePtr->horizValueY = y + SPACING;
            y += fm.linespace + SPACING;
            y += fm.linespace + SPACING;
            extraSpace = SPACING;
            extraSpace = SPACING;
        } else {
        } else {
            scalePtr->horizValueY = y;
            scalePtr->horizValueY = y;
        }
        }
        y += extraSpace;
        y += extraSpace;
        scalePtr->horizTroughY = y;
        scalePtr->horizTroughY = y;
        y += scalePtr->width + 2*scalePtr->borderWidth;
        y += scalePtr->width + 2*scalePtr->borderWidth;
        if (scalePtr->tickInterval != 0) {
        if (scalePtr->tickInterval != 0) {
            scalePtr->horizTickY = y + SPACING;
            scalePtr->horizTickY = y + SPACING;
            y += fm.linespace + 2*SPACING;
            y += fm.linespace + 2*SPACING;
        }
        }
        Tk_GeometryRequest(scalePtr->tkwin,
        Tk_GeometryRequest(scalePtr->tkwin,
                scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);
                scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);
        Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
        Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
        return;
        return;
    }
    }
 
 
    /*
    /*
     * Vertical scale:  compute the amount of space needed to display
     * Vertical scale:  compute the amount of space needed to display
     * the scales value by formatting strings for the two end points;
     * the scales value by formatting strings for the two end points;
     * use whichever length is longer.
     * use whichever length is longer.
     */
     */
 
 
    sprintf(valueString, scalePtr->format, scalePtr->fromValue);
    sprintf(valueString, scalePtr->format, scalePtr->fromValue);
    valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
    valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
 
 
    sprintf(valueString, scalePtr->format, scalePtr->toValue);
    sprintf(valueString, scalePtr->format, scalePtr->toValue);
    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
    tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
    if (valuePixels < tmp) {
    if (valuePixels < tmp) {
        valuePixels = tmp;
        valuePixels = tmp;
    }
    }
 
 
    /*
    /*
     * Assign x-locations to the elements of the scale, working from
     * Assign x-locations to the elements of the scale, working from
     * left to right.
     * left to right.
     */
     */
 
 
    x = scalePtr->inset;
    x = scalePtr->inset;
    if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {
    if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {
        scalePtr->vertTickRightX = x + SPACING + valuePixels;
        scalePtr->vertTickRightX = x + SPACING + valuePixels;
        scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels
        scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels
                + fm.ascent/2;
                + fm.ascent/2;
        x = scalePtr->vertValueRightX + SPACING;
        x = scalePtr->vertValueRightX + SPACING;
    } else if (scalePtr->tickInterval != 0) {
    } else if (scalePtr->tickInterval != 0) {
        scalePtr->vertTickRightX = x + SPACING + valuePixels;
        scalePtr->vertTickRightX = x + SPACING + valuePixels;
        scalePtr->vertValueRightX = scalePtr->vertTickRightX;
        scalePtr->vertValueRightX = scalePtr->vertTickRightX;
        x = scalePtr->vertTickRightX + SPACING;
        x = scalePtr->vertTickRightX + SPACING;
    } else if (scalePtr->showValue) {
    } else if (scalePtr->showValue) {
        scalePtr->vertTickRightX = x;
        scalePtr->vertTickRightX = x;
        scalePtr->vertValueRightX = x + SPACING + valuePixels;
        scalePtr->vertValueRightX = x + SPACING + valuePixels;
        x = scalePtr->vertValueRightX + SPACING;
        x = scalePtr->vertValueRightX + SPACING;
    } else {
    } else {
        scalePtr->vertTickRightX = x;
        scalePtr->vertTickRightX = x;
        scalePtr->vertValueRightX = x;
        scalePtr->vertValueRightX = x;
    }
    }
    scalePtr->vertTroughX = x;
    scalePtr->vertTroughX = x;
    x += 2*scalePtr->borderWidth + scalePtr->width;
    x += 2*scalePtr->borderWidth + scalePtr->width;
    if (scalePtr->labelLength == 0) {
    if (scalePtr->labelLength == 0) {
        scalePtr->vertLabelX = 0;
        scalePtr->vertLabelX = 0;
    } else {
    } else {
        scalePtr->vertLabelX = x + fm.ascent/2;
        scalePtr->vertLabelX = x + fm.ascent/2;
        x = scalePtr->vertLabelX + fm.ascent/2
        x = scalePtr->vertLabelX + fm.ascent/2
                + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
                + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
                        scalePtr->labelLength);
                        scalePtr->labelLength);
    }
    }
    Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,
    Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,
            scalePtr->length + 2*scalePtr->inset);
            scalePtr->length + 2*scalePtr->inset);
    Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
    Tk_SetInternalBorder(scalePtr->tkwin, scalePtr->inset);
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * ScaleEventProc --
 * ScaleEventProc --
 *
 *
 *      This procedure is invoked by the Tk dispatcher for various
 *      This procedure is invoked by the Tk dispatcher for various
 *      events on scales.
 *      events on scales.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      When the window gets deleted, internal structures get
 *      When the window gets deleted, internal structures get
 *      cleaned up.  When it gets exposed, it is redisplayed.
 *      cleaned up.  When it gets exposed, it is redisplayed.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
static void
static void
ScaleEventProc(clientData, eventPtr)
ScaleEventProc(clientData, eventPtr)
    ClientData clientData;      /* Information about window. */
    ClientData clientData;      /* Information about window. */
    XEvent *eventPtr;           /* Information about event. */
    XEvent *eventPtr;           /* Information about event. */
{
{
    TkScale *scalePtr = (TkScale *) clientData;
    TkScale *scalePtr = (TkScale *) clientData;
 
 
    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
    if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
        TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
        TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
    } else if (eventPtr->type == DestroyNotify) {
    } else if (eventPtr->type == DestroyNotify) {
        if (scalePtr->tkwin != NULL) {
        if (scalePtr->tkwin != NULL) {
            scalePtr->tkwin = NULL;
            scalePtr->tkwin = NULL;
            Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
            Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
        }
        }
        if (scalePtr->flags & REDRAW_ALL) {
        if (scalePtr->flags & REDRAW_ALL) {
            Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);
            Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);
        }
        }
        Tcl_EventuallyFree((ClientData) scalePtr, DestroyScale);
        Tcl_EventuallyFree((ClientData) scalePtr, DestroyScale);
    } else if (eventPtr->type == ConfigureNotify) {
    } else if (eventPtr->type == ConfigureNotify) {
        ComputeScaleGeometry(scalePtr);
        ComputeScaleGeometry(scalePtr);
        TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
        TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
    } else if (eventPtr->type == FocusIn) {
    } else if (eventPtr->type == FocusIn) {
        if (eventPtr->xfocus.detail != NotifyInferior) {
        if (eventPtr->xfocus.detail != NotifyInferior) {
            scalePtr->flags |= GOT_FOCUS;
            scalePtr->flags |= GOT_FOCUS;
            if (scalePtr->highlightWidth > 0) {
            if (scalePtr->highlightWidth > 0) {
                TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
                TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
            }
            }
        }
        }
    } else if (eventPtr->type == FocusOut) {
    } else if (eventPtr->type == FocusOut) {
        if (eventPtr->xfocus.detail != NotifyInferior) {
        if (eventPtr->xfocus.detail != NotifyInferior) {
            scalePtr->flags &= ~GOT_FOCUS;
            scalePtr->flags &= ~GOT_FOCUS;
            if (scalePtr->highlightWidth > 0) {
            if (scalePtr->highlightWidth > 0) {
                TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
                TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
            }
            }
        }
        }
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * ScaleCmdDeletedProc --
 * ScaleCmdDeletedProc --
 *
 *
 *      This procedure is invoked when a widget command is deleted.  If
 *      This procedure is invoked when a widget command is deleted.  If
 *      the widget isn't already in the process of being destroyed,
 *      the widget isn't already in the process of being destroyed,
 *      this command destroys it.
 *      this command destroys it.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The widget is destroyed.
 *      The widget is destroyed.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
ScaleCmdDeletedProc(clientData)
ScaleCmdDeletedProc(clientData)
    ClientData clientData;      /* Pointer to widget record for widget. */
    ClientData clientData;      /* Pointer to widget record for widget. */
{
{
    TkScale *scalePtr = (TkScale *) clientData;
    TkScale *scalePtr = (TkScale *) clientData;
    Tk_Window tkwin = scalePtr->tkwin;
    Tk_Window tkwin = scalePtr->tkwin;
 
 
    /*
    /*
     * This procedure could be invoked either because the window was
     * This procedure could be invoked either because the window was
     * destroyed and the command was then deleted (in which case tkwin
     * destroyed and the command was then deleted (in which case tkwin
     * is NULL) or because the command was deleted, and then this procedure
     * is NULL) or because the command was deleted, and then this procedure
     * destroys the widget.
     * destroys the widget.
     */
     */
 
 
    if (tkwin != NULL) {
    if (tkwin != NULL) {
        scalePtr->tkwin = NULL;
        scalePtr->tkwin = NULL;
        Tk_DestroyWindow(tkwin);
        Tk_DestroyWindow(tkwin);
    }
    }
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * TkEventuallyRedrawScale --
 * TkEventuallyRedrawScale --
 *
 *
 *      Arrange for part or all of a scale widget to redrawn at
 *      Arrange for part or all of a scale widget to redrawn at
 *      the next convenient time in the future.
 *      the next convenient time in the future.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      If "what" is REDRAW_SLIDER then just the slider and the
 *      If "what" is REDRAW_SLIDER then just the slider and the
 *      value readout will be redrawn;  if "what" is REDRAW_ALL
 *      value readout will be redrawn;  if "what" is REDRAW_ALL
 *      then the entire widget will be redrawn.
 *      then the entire widget will be redrawn.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
TkEventuallyRedrawScale(scalePtr, what)
TkEventuallyRedrawScale(scalePtr, what)
    register TkScale *scalePtr; /* Information about widget. */
    register TkScale *scalePtr; /* Information about widget. */
    int what;                   /* What to redraw:  REDRAW_SLIDER
    int what;                   /* What to redraw:  REDRAW_SLIDER
                                 * or REDRAW_ALL. */
                                 * or REDRAW_ALL. */
{
{
    if ((what == 0) || (scalePtr->tkwin == NULL)
    if ((what == 0) || (scalePtr->tkwin == NULL)
            || !Tk_IsMapped(scalePtr->tkwin)) {
            || !Tk_IsMapped(scalePtr->tkwin)) {
        return;
        return;
    }
    }
    if ((scalePtr->flags & REDRAW_ALL) == 0) {
    if ((scalePtr->flags & REDRAW_ALL) == 0) {
        Tcl_DoWhenIdle(TkpDisplayScale, (ClientData) scalePtr);
        Tcl_DoWhenIdle(TkpDisplayScale, (ClientData) scalePtr);
    }
    }
    scalePtr->flags |= what;
    scalePtr->flags |= what;
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * TkRoundToResolution --
 * TkRoundToResolution --
 *
 *
 *      Round a given floating-point value to the nearest multiple
 *      Round a given floating-point value to the nearest multiple
 *      of the scale's resolution.
 *      of the scale's resolution.
 *
 *
 * Results:
 * Results:
 *      The return value is the rounded result.
 *      The return value is the rounded result.
 *
 *
 * Side effects:
 * Side effects:
 *      None.
 *      None.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
double
double
TkRoundToResolution(scalePtr, value)
TkRoundToResolution(scalePtr, value)
    TkScale *scalePtr;          /* Information about scale widget. */
    TkScale *scalePtr;          /* Information about scale widget. */
    double value;               /* Value to round. */
    double value;               /* Value to round. */
{
{
    double rem, new;
    double rem, new;
 
 
    if (scalePtr->resolution <= 0) {
    if (scalePtr->resolution <= 0) {
        return value;
        return value;
    }
    }
    new = scalePtr->resolution * floor(value/scalePtr->resolution);
    new = scalePtr->resolution * floor(value/scalePtr->resolution);
    rem = value - new;
    rem = value - new;
    if (rem < 0) {
    if (rem < 0) {
        if (rem <= -scalePtr->resolution/2) {
        if (rem <= -scalePtr->resolution/2) {
            new -= scalePtr->resolution;
            new -= scalePtr->resolution;
        }
        }
    } else {
    } else {
        if (rem >= scalePtr->resolution/2) {
        if (rem >= scalePtr->resolution/2) {
            new += scalePtr->resolution;
            new += scalePtr->resolution;
        }
        }
    }
    }
    return new;
    return new;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * ScaleVarProc --
 * ScaleVarProc --
 *
 *
 *      This procedure is invoked by Tcl whenever someone modifies a
 *      This procedure is invoked by Tcl whenever someone modifies a
 *      variable associated with a scale widget.
 *      variable associated with a scale widget.
 *
 *
 * Results:
 * Results:
 *      NULL is always returned.
 *      NULL is always returned.
 *
 *
 * Side effects:
 * Side effects:
 *      The value displayed in the scale will change to match the
 *      The value displayed in the scale will change to match the
 *      variable's new value.  If the variable has a bogus value then
 *      variable's new value.  If the variable has a bogus value then
 *      it is reset to the value of the scale.
 *      it is reset to the value of the scale.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
    /* ARGSUSED */
    /* ARGSUSED */
static char *
static char *
ScaleVarProc(clientData, interp, name1, name2, flags)
ScaleVarProc(clientData, interp, name1, name2, flags)
    ClientData clientData;      /* Information about button. */
    ClientData clientData;      /* Information about button. */
    Tcl_Interp *interp;         /* Interpreter containing variable. */
    Tcl_Interp *interp;         /* Interpreter containing variable. */
    char *name1;                /* Name of variable. */
    char *name1;                /* Name of variable. */
    char *name2;                /* Second part of variable name. */
    char *name2;                /* Second part of variable name. */
    int flags;                  /* Information about what happened. */
    int flags;                  /* Information about what happened. */
{
{
    register TkScale *scalePtr = (TkScale *) clientData;
    register TkScale *scalePtr = (TkScale *) clientData;
    char *stringValue, *end, *result;
    char *stringValue, *end, *result;
    double value;
    double value;
 
 
    /*
    /*
     * If the variable is unset, then immediately recreate it unless
     * If the variable is unset, then immediately recreate it unless
     * the whole interpreter is going away.
     * the whole interpreter is going away.
     */
     */
 
 
    if (flags & TCL_TRACE_UNSETS) {
    if (flags & TCL_TRACE_UNSETS) {
        if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
        if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
            Tcl_TraceVar(interp, scalePtr->varName,
            Tcl_TraceVar(interp, scalePtr->varName,
                    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
                    ScaleVarProc, clientData);
                    ScaleVarProc, clientData);
            scalePtr->flags |= NEVER_SET;
            scalePtr->flags |= NEVER_SET;
            TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
            TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
        }
        }
        return (char *) NULL;
        return (char *) NULL;
    }
    }
 
 
    /*
    /*
     * If we came here because we updated the variable (in TkpSetScaleValue),
     * If we came here because we updated the variable (in TkpSetScaleValue),
     * then ignore the trace.  Otherwise update the scale with the value
     * then ignore the trace.  Otherwise update the scale with the value
     * of the variable.
     * of the variable.
     */
     */
 
 
    if (scalePtr->flags & SETTING_VAR) {
    if (scalePtr->flags & SETTING_VAR) {
        return (char *) NULL;
        return (char *) NULL;
    }
    }
    result = NULL;
    result = NULL;
    stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
    stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
    if (stringValue != NULL) {
    if (stringValue != NULL) {
        value = strtod(stringValue, &end);
        value = strtod(stringValue, &end);
        if ((end == stringValue) || (*end != 0)) {
        if ((end == stringValue) || (*end != 0)) {
            result = "can't assign non-numeric value to scale variable";
            result = "can't assign non-numeric value to scale variable";
        } else {
        } else {
            scalePtr->value = TkRoundToResolution(scalePtr, value);
            scalePtr->value = TkRoundToResolution(scalePtr, value);
        }
        }
 
 
        /*
        /*
         * 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
         * calling TkpSetScaleValue.  This way, TkpSetScaleValue won't bother
         * calling TkpSetScaleValue.  This way, TkpSetScaleValue won't bother
         * to set the variable again or to invoke the -command.  However, it
         * to set the variable again or to invoke the -command.  However, it
         * 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
         * explicitly.
         * explicitly.
         */
         */
 
 
        TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
        TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
        TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
        TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
    }
    }
 
 
    return result;
    return result;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.