text: /*
   * tkUnixScale.c --
   *
   *	This file implements the X specific portion of the scrollbar widget.
   *
   * Copyright (c) 1996 by Sun Microsystems, Inc.
   * Copyright (c) 1998-2000 by Scriptics Corporation.
   *
   * See the file "license.terms" for information on usage and redistribution of
   * this file, and for a DISCLAIMER OF ALL WARRANTIES.
   *
   * RCS: @(#) $Id$
   */
  
  #include "tkInt.h"
  #include "tkScale.h"
  
  /*
   * Forward declarations for functions defined later in this file:
   */
  
  static void		DisplayHorizontalScale(TkScale *scalePtr,
  			    Drawable drawable, XRectangle *drawnAreaPtr);
  static void		DisplayHorizontalValue(TkScale *scalePtr,
  			    Drawable drawable, double value, int top);
  static void		DisplayVerticalScale(TkScale *scalePtr,
  			    Drawable drawable, XRectangle *drawnAreaPtr);
  static void		DisplayVerticalValue(TkScale *scalePtr,
  			    Drawable drawable, double value, int rightEdge);
  
  /*
   *----------------------------------------------------------------------
   *
   * TkpCreateScale --
   *
   *	Allocate a new TkScale structure.
   *
   * Results:
   *	Returns a newly allocated TkScale structure.
   *
   * Side effects:
   *	None.
   *
   *----------------------------------------------------------------------
   */
  
  TkScale *
  TkpCreateScale(
      Tk_Window tkwin)
  {
      return (TkScale *) ckalloc(sizeof(TkScale));
  }
  
  /*
   *----------------------------------------------------------------------
   *
   * TkpDestroyScale --
   *
   *	Destroy a TkScale structure. It's necessary to do this with
   *	Tcl_EventuallyFree to allow the Tcl_Preserve(scalePtr) to work as
   *	expected in TkpDisplayScale. (hobbs)
   *
   * Results:
   *	None
   *
   * Side effects:
   *	Memory is freed.
   *
   *----------------------------------------------------------------------
   */
  
  void
  TkpDestroyScale(
      TkScale *scalePtr)
  {
      Tcl_EventuallyFree(scalePtr, TCL_DYNAMIC);
  }
  
  /*
   *--------------------------------------------------------------
   *
   * DisplayVerticalScale --
   *
   *	This function redraws the contents of a vertical scale window. It is
   *	invoked as a do-when-idle handler, so it only runs when there's
   *	nothing else for the application to do.
   *
   * Results:
   *	There is no return value. If only a part of the scale needs to be
   *	redrawn, then drawnAreaPtr is modified to reflect the area that was
   *	actually modified.
   *
   * Side effects:
   *	Information appears on the screen.
   *
   *--------------------------------------------------------------
   */
  
  static void
  DisplayVerticalScale(
      TkScale *scalePtr,		/* Widget record for scale. */
      Drawable drawable,		/* Where to display scale (window or
  				 * pixmap). */
      XRectangle *drawnAreaPtr)	/* Initally contains area of window; if only a
  				 * part of the scale is redrawn, gets modified
  				 * to reflect the part of the window that was
  				 * redrawn. */
  {
      Tk_Window tkwin = scalePtr->tkwin;
      int x, y, width, height, shadowWidth;
      double tickValue, tickInterval = scalePtr->tickInterval;
      Tk_3DBorder sliderBorder;
  
      /*
       * Display the information from left to right across the window.
       */
  
      if (!(scalePtr->flags & REDRAW_OTHER)) {
  	drawnAreaPtr->x = scalePtr->vertTickRightX;
  	drawnAreaPtr->y = scalePtr->inset;
  	drawnAreaPtr->width = scalePtr->vertTroughX + scalePtr->width
  		+ 2*scalePtr->borderWidth - scalePtr->vertTickRightX;
  	drawnAreaPtr->height -= 2*scalePtr->inset;
      }
      Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
  	    drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
  	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
      if (scalePtr->flags & REDRAW_OTHER) {
  	/*
  	 * Display the tick marks.
  	 */
  
  	if (tickInterval != 0) {
  	    double ticks, maxTicks;
  
  	    /*
  	     * Ensure that we will only draw enough of the tick values such
  	     * that they don't overlap
  	     */
  
  	    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
  		    / tickInterval);
  	    maxTicks = (double) Tk_Height(tkwin)
  		    / (double) scalePtr->fontHeight;
  	    if (ticks > maxTicks) {
  		tickInterval *= (ticks / maxTicks);
  	    }
  	    for (tickValue = scalePtr->fromValue; ;
  		    tickValue += tickInterval) {
  		/*
  		 * The TkRoundToResolution call gets rid of accumulated
  		 * round-off errors, if any.
  		 */
  
  		tickValue = TkRoundToResolution(scalePtr, tickValue);
  		if (scalePtr->toValue >= scalePtr->fromValue) {
  		    if (tickValue > scalePtr->toValue) {
  			break;
  		    }
  		} else {
  		    if (tickValue < scalePtr->toValue) {
  			break;
  		    }
  		}
  		DisplayVerticalValue(scalePtr, drawable, tickValue,
  			scalePtr->vertTickRightX);
  	    }
  	}
      }
  
      /*
       * Display the value, if it is desired.
       */
  
      if (scalePtr->showValue) {
  	DisplayVerticalValue(scalePtr, drawable, scalePtr->value,
  		scalePtr->vertValueRightX);
      }
  
      /*
       * Display the trough and the slider.
       */
  
      Tk_Draw3DRectangle(tkwin, drawable,
  	    scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset,
  	    scalePtr->width + 2*scalePtr->borderWidth,
  	    Tk_Height(tkwin) - 2*scalePtr->inset, scalePtr->borderWidth,
  	    TK_RELIEF_SUNKEN);
      XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
  	    scalePtr->vertTroughX + scalePtr->borderWidth,
  	    scalePtr->inset + scalePtr->borderWidth,
  	    (unsigned) scalePtr->width,
  	    (unsigned) (Tk_Height(tkwin) - 2*scalePtr->inset
  		- 2*scalePtr->borderWidth));
      if (scalePtr->state == STATE_ACTIVE) {
  	sliderBorder = scalePtr->activeBorder;
      } else {
  	sliderBorder = scalePtr->bgBorder;
      }
      width = scalePtr->width;
      height = scalePtr->sliderLength/2;
      x = scalePtr->vertTroughX + scalePtr->borderWidth;
      y = TkScaleValueToPixel(scalePtr, scalePtr->value) - height;
      shadowWidth = scalePtr->borderWidth/2;
      if (shadowWidth == 0) {
  	shadowWidth = 1;
      }
      Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
  	    2*height, shadowWidth, scalePtr->sliderRelief);
      x += shadowWidth;
      y += shadowWidth;
      width -= 2*shadowWidth;
      height -= shadowWidth;
      Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
  	    height, shadowWidth, scalePtr->sliderRelief);
      Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height,
  	    width, height, shadowWidth, scalePtr->sliderRelief);
  
      /*
       * Draw the label to the right of the scale.
       */
  
      if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
  	Tk_FontMetrics fm;
  
  	Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  	Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  		scalePtr->tkfont, scalePtr->label,
                  scalePtr->labelLength, scalePtr->vertLabelX,
                  scalePtr->inset + (3*fm.ascent)/2);
      }
  }
  
  /*
   *----------------------------------------------------------------------
   *
   * DisplayVerticalValue --
   *
   *	This function is called to display values (scale readings) for
   *	vertically-oriented scales.
   *
   * Results:
   *	None.
   *
   * Side effects:
   *	The numerical value corresponding to value is displayed with its right
   *	edge at "rightEdge", and at a vertical position in the scale that
   *	corresponds to "value".
   *
   *----------------------------------------------------------------------
   */
  
  static void
  DisplayVerticalValue(
      register TkScale *scalePtr,	/* Information about widget in which to
  				 * display value. */
      Drawable drawable,		/* Pixmap or window in which to draw the
  				 * value. */
      double value,		/* Y-coordinate of number to display,
  				 * specified in application coords, not in
  				 * pixels (we'll compute pixels). */
      int rightEdge)		/* X-coordinate of right edge of text,
  				 * specified in pixels. */
  {
      register Tk_Window tkwin = scalePtr->tkwin;
      int y, width, length;
      char valueString[PRINT_CHARS];
      Tk_FontMetrics fm;
  
      Tk_GetFontMetrics(scalePtr->tkfont, &fm);
      y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
      sprintf(valueString, scalePtr->format, value);
      length = (int) strlen(valueString);
      width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
  
      /*
       * Adjust the y-coordinate if necessary to keep the text entirely inside
       * the window.
       */
  
      if ((y - fm.ascent) < (scalePtr->inset + SPACING)) {
  	y = scalePtr->inset + SPACING + fm.ascent;
      }
      if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) {
  	y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent;
      }
      Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  	    scalePtr->tkfont, valueString, length, rightEdge - width, y);
  }
  
  /*
   *--------------------------------------------------------------
   *
   * DisplayHorizontalScale --
   *
   *	This function redraws the contents of a horizontal scale window. It is
   *	invoked as a do-when-idle handler, so it only runs when there's
   *	nothing else for the application to do.
   *
   * Results:
   *	There is no return value. If only a part of the scale needs to be
   *	redrawn, then drawnAreaPtr is modified to reflect the area that was
   *	actually modified.
   *
   * Side effects:
   *	Information appears on the screen.
   *
   *--------------------------------------------------------------
   */
  
  static void
  DisplayHorizontalScale(
      TkScale *scalePtr,		/* Widget record for scale. */
      Drawable drawable,		/* Where to display scale (window or
  				 * pixmap). */
      XRectangle *drawnAreaPtr)	/* Initally contains area of window; if only a
  				 * part of the scale is redrawn, gets modified
  				 * to reflect the part of the window that was
  				 * redrawn. */
  {
      register Tk_Window tkwin = scalePtr->tkwin;
      int x, y, width, height, shadowWidth;
      double tickValue, tickInterval = scalePtr->tickInterval;
      Tk_3DBorder sliderBorder;
  
      /*
       * Display the information from bottom to top across the window.
       */
  
      if (!(scalePtr->flags & REDRAW_OTHER)) {
  	drawnAreaPtr->x = scalePtr->inset;
  	drawnAreaPtr->y = scalePtr->horizValueY;
  	drawnAreaPtr->width -= 2*scalePtr->inset;
  	drawnAreaPtr->height = scalePtr->horizTroughY + scalePtr->width
  		+ 2*scalePtr->borderWidth - scalePtr->horizValueY;
      }
      Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
  	    drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
  	    drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
      if (scalePtr->flags & REDRAW_OTHER) {
  	/*
  	 * Display the tick marks.
  	 */
  
  	if (tickInterval != 0) {
  	    char valueString[PRINT_CHARS];
  	    double ticks, maxTicks;
  
  	    /*
  	     * Ensure that we will only draw enough of the tick values such
  	     * that they don't overlap. We base this off the width that
  	     * fromValue would take. Not exact, but better than no constraint.
  	     */
  
  	    ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
  		    / tickInterval);
  	    sprintf(valueString, scalePtr->format, scalePtr->fromValue);
  	    maxTicks = (double) Tk_Width(tkwin)
  		    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
  	    if (ticks > maxTicks) {
  		tickInterval *= (ticks / maxTicks);
  	    }
  	    for (tickValue = scalePtr->fromValue; ;
  		 tickValue += tickInterval) {
  		/*
  		 * The TkRoundToResolution call gets rid of accumulated
  		 * round-off errors, if any.
  		 */
  
  		tickValue = TkRoundToResolution(scalePtr, tickValue);
  		if (scalePtr->toValue >= scalePtr->fromValue) {
  		    if (tickValue > scalePtr->toValue) {
  			break;
  		    }
  		} else {
  		    if (tickValue < scalePtr->toValue) {
  			break;
  		    }
  		}
  		DisplayHorizontalValue(scalePtr, drawable, tickValue,
  			scalePtr->horizTickY);
  	    }
  	}
      }
  
      /*
       * Display the value, if it is desired.
       */
  
      if (scalePtr->showValue) {
  	DisplayHorizontalValue(scalePtr, drawable, scalePtr->value,
  		scalePtr->horizValueY);
      }
  
      /*
       * Display the trough and the slider.
       */
  
      y = scalePtr->horizTroughY;
      Tk_Draw3DRectangle(tkwin, drawable,
  	    scalePtr->bgBorder, scalePtr->inset, y,
  	    Tk_Width(tkwin) - 2*scalePtr->inset,
  	    scalePtr->width + 2*scalePtr->borderWidth,
  	    scalePtr->borderWidth, TK_RELIEF_SUNKEN);
      XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
  	    scalePtr->inset + scalePtr->borderWidth,
  	    y + scalePtr->borderWidth,
  	    (unsigned) (Tk_Width(tkwin) - 2*scalePtr->inset
  		- 2*scalePtr->borderWidth),
  	    (unsigned) scalePtr->width);
      if (scalePtr->state == STATE_ACTIVE) {
  	sliderBorder = scalePtr->activeBorder;
      } else {
  	sliderBorder = scalePtr->bgBorder;
      }
      width = scalePtr->sliderLength/2;
      height = scalePtr->width;
      x = TkScaleValueToPixel(scalePtr, scalePtr->value) - width;
      y += scalePtr->borderWidth;
      shadowWidth = scalePtr->borderWidth/2;
      if (shadowWidth == 0) {
  	shadowWidth = 1;
      }
      Tk_Draw3DRectangle(tkwin, drawable, sliderBorder,
  	    x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief);
      x += shadowWidth;
      y += shadowWidth;
      width -= shadowWidth;
      height -= 2*shadowWidth;
      Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height,
  	    shadowWidth, scalePtr->sliderRelief);
      Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y,
  	    width, height, shadowWidth, scalePtr->sliderRelief);
  
      /*
       * Draw the label at the top of the scale.
       */
  
      if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
  	Tk_FontMetrics fm;
  
  	Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  	Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  		scalePtr->tkfont, scalePtr->label,
                  scalePtr->labelLength, scalePtr->inset + fm.ascent/2,
                  scalePtr->horizLabelY + fm.ascent);
      }
  }
  
  /*
   *----------------------------------------------------------------------
   *
   * DisplayHorizontalValue --
   *
   *	This function is called to display values (scale readings) for
   *	horizontally-oriented scales.
   *
   * Results:
   *	None.
   *
   * Side effects:
   *	The numerical value corresponding to value is displayed with its
   *	bottom edge at "bottom", and at a horizontal position in the scale
   *	that corresponds to "value".
   *
   *----------------------------------------------------------------------
   */
  
  static void
  DisplayHorizontalValue(
      register TkScale *scalePtr,	/* Information about widget in which to
  				 * display value. */
      Drawable drawable,		/* Pixmap or window in which to draw the
  				 * value. */
      double value,		/* X-coordinate of number to display,
  				 * specified in application coords, not in
  				 * pixels (we'll compute pixels). */
      int top)			/* Y-coordinate of top edge of text, specified
  				 * in pixels. */
  {
      register Tk_Window tkwin = scalePtr->tkwin;
      int x, y, length, width;
      char valueString[PRINT_CHARS];
      Tk_FontMetrics fm;
  
      x = TkScaleValueToPixel(scalePtr, value);
      Tk_GetFontMetrics(scalePtr->tkfont, &fm);
      y = top + fm.ascent;
      sprintf(valueString, scalePtr->format, value);
      length = (int) strlen(valueString);
      width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
  
      /*
       * Adjust the x-coordinate if necessary to keep the text entirely inside
       * the window.
       */
  
      x -= (width)/2;
      if (x < (scalePtr->inset + SPACING)) {
  	x = scalePtr->inset + SPACING;
      }
  
      /*
       * Check the right border so use starting point +text width for the check.
       */
  
      if (x + width >= (Tk_Width(tkwin) - scalePtr->inset)) {
  	x = Tk_Width(tkwin) - scalePtr->inset - SPACING - width;
      }
      Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  	    scalePtr->tkfont, valueString, length, x, y);
  }
  
  /*
   *----------------------------------------------------------------------
   *
   * TkpDisplayScale --
   *
   *	This function is invoked as an idle handler to redisplay the contents
   *	of a scale widget.
   *
   * Results:
   *	None.
   *
   * Side effects:
   *	The scale gets redisplayed.
   *
   *----------------------------------------------------------------------
   */
  
  void
  TkpDisplayScale(
      ClientData clientData)	/* Widget record for scale. */
  {
      TkScale *scalePtr = (TkScale *) clientData;
      Tk_Window tkwin = scalePtr->tkwin;
      Tcl_Interp *interp = scalePtr->interp;
      Pixmap pixmap;
      int result;
      char string[PRINT_CHARS];
      XRectangle drawnArea;
  
      scalePtr->flags &= ~REDRAW_PENDING;
      if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
  	goto done;
      }
  
      /*
       * Invoke the scale's command if needed.
       */
  
      Tcl_Preserve(scalePtr);
      if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
  	Tcl_Preserve(interp);
  	sprintf(string, scalePtr->format, scalePtr->value);
  	result = Tcl_VarEval(interp, scalePtr->command, " ", string,
  		(char *) NULL);
  	if (result != TCL_OK) {
  	    Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
  	    Tcl_BackgroundException(interp, result);
  	}
  	Tcl_Release(interp);
      }
      scalePtr->flags &= ~INVOKE_COMMAND;
      if (scalePtr->flags & SCALE_DELETED) {
  	Tcl_Release(scalePtr);
  	return;
      }
      Tcl_Release(scalePtr);
  
  #ifndef TK_NO_DOUBLE_BUFFERING
      /*
       * In order to avoid screen flashes, this function redraws the scale in a
       * pixmap, then copies the pixmap to the screen in a single operation.
       * This means that there's no point in time where the on-sreen image has
       * been cleared.
       */
  
      pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin),
  	    Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
  #else
      pixmap = Tk_WindowId(tkwin);
  #endif /* TK_NO_DOUBLE_BUFFERING */
      drawnArea.x = 0;
      drawnArea.y = 0;
      drawnArea.width = Tk_Width(tkwin);
      drawnArea.height = Tk_Height(tkwin);
  
      /*
       * Much of the redisplay is done totally differently for horizontal and
       * vertical scales. Handle the part that's different.
       */
  
      if (scalePtr->orient == ORIENT_VERTICAL) {
  	DisplayVerticalScale(scalePtr, pixmap, &drawnArea);
      } else {
  	DisplayHorizontalScale(scalePtr, pixmap, &drawnArea);
      }
  
      /*
       * Now handle the part of redisplay that is the same for horizontal and
       * vertical scales: border and traversal highlight.
       */
  
      if (scalePtr->flags & REDRAW_OTHER) {
  	if (scalePtr->relief != TK_RELIEF_FLAT) {
  	    Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder,
  		    scalePtr->highlightWidth, scalePtr->highlightWidth,
  		    Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
  		    Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
  		    scalePtr->borderWidth, scalePtr->relief);
  	}
  	if (scalePtr->highlightWidth != 0) {
  	    GC gc;
  
  	    if (scalePtr->flags & GOT_FOCUS) {
  		gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);
  	    } else {
  		gc = Tk_GCForColor(
                          Tk_3DBorderColor(scalePtr->highlightBorder), pixmap);
  	    }
  	    Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap);
  	}
      }
  
  #ifndef TK_NO_DOUBLE_BUFFERING
      /*
       * Copy the information from the off-screen pixmap onto the screen, then
       * delete the pixmap.
       */
  
      XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin),
  	    scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width,
  	    drawnArea.height, drawnArea.x, drawnArea.y);
      Tk_FreePixmap(scalePtr->display, pixmap);
  #endif /* TK_NO_DOUBLE_BUFFERING */
  
    done:
      scalePtr->flags &= ~REDRAW_ALL;
  }
  
  /*
   *----------------------------------------------------------------------
   *
   * TkpScaleElement --
   *
   *	Determine which part of a scale widget lies under a given point.
   *
   * Results:
   *	The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER,
   *	depending on which of the scale's active elements (if any) is under
   *	the point at (x,y).
   *
   * Side effects:
   *	None.
   *
   *----------------------------------------------------------------------
   */
  
  int
  TkpScaleElement(
      TkScale *scalePtr,		/* Widget record for scale. */
      int x, int y)		/* Coordinates within scalePtr's window. */
  {
      int sliderFirst;
  
      if (scalePtr->orient == ORIENT_VERTICAL) {
  	if ((x < scalePtr->vertTroughX)
  		|| (x >= (scalePtr->vertTroughX + 2*scalePtr->borderWidth +
  		scalePtr->width))) {
  	    return OTHER;
  	}
  	if ((y < scalePtr->inset)
  		|| (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) {
  	    return OTHER;
  	}
  	sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)
  		- scalePtr->sliderLength/2;
  	if (y < sliderFirst) {
  	    return TROUGH1;
  	}
  	if (y < (sliderFirst+scalePtr->sliderLength)) {
  	    return SLIDER;
  	}
  	return TROUGH2;
      }
  
      if ((y < scalePtr->horizTroughY)
  	    || (y >= (scalePtr->horizTroughY + 2*scalePtr->borderWidth +
  	    scalePtr->width))) {
  	return OTHER;
      }
      if ((x < scalePtr->inset)
  	    || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) {
  	return OTHER;
      }
      sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)
  	    - scalePtr->sliderLength/2;
      if (x < sliderFirst) {
  	return TROUGH1;
      }
      if (x < (sliderFirst+scalePtr->sliderLength)) {
  	return SLIDER;
      }
      return TROUGH2;
  }
  
  /*
   * Local Variables:
   * mode: c
   * c-basic-offset: 4
   * fill-column: 78
   * End:
   */
  