tkUnixScale.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:21k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkUnixScale.c --
  3.  *
  4.  * This file implements the X specific portion of the scrollbar
  5.  * widget.
  6.  *
  7.  * Copyright (c) 1996 by Sun Microsystems, Inc.
  8.  * Copyright (c) 1998-2000 by Scriptics Corporation.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tkUnixScale.c,v 1.8.4.2 2007/04/29 02:24:01 das Exp $
  14.  */
  15. #include "tkScale.h"
  16. #include "tkInt.h"
  17. /*
  18.  * Forward declarations for procedures defined later in this file:
  19.  */
  20. static void DisplayHorizontalScale _ANSI_ARGS_((TkScale *scalePtr,
  21.     Drawable drawable, XRectangle *drawnAreaPtr));
  22. static void DisplayHorizontalValue _ANSI_ARGS_((TkScale *scalePtr,
  23.     Drawable drawable, double value, int top));
  24. static void DisplayVerticalScale _ANSI_ARGS_((TkScale *scalePtr,
  25.     Drawable drawable, XRectangle *drawnAreaPtr));
  26. static void DisplayVerticalValue _ANSI_ARGS_((TkScale *scalePtr,
  27.     Drawable drawable, double value, int rightEdge));
  28. /*
  29.  *----------------------------------------------------------------------
  30.  *
  31.  * TkpCreateScale --
  32.  *
  33.  * Allocate a new TkScale structure.
  34.  *
  35.  * Results:
  36.  * Returns a newly allocated TkScale structure.
  37.  *
  38.  * Side effects:
  39.  * None.
  40.  *
  41.  *----------------------------------------------------------------------
  42.  */
  43. TkScale *
  44. TkpCreateScale(tkwin)
  45.     Tk_Window tkwin;
  46. {
  47.     return (TkScale *) ckalloc(sizeof(TkScale));
  48. }
  49. /*
  50.  *----------------------------------------------------------------------
  51.  *
  52.  * TkpDestroyScale --
  53.  *
  54.  * Destroy a TkScale structure.  It's necessary to do this with
  55.  * Tcl_EventuallyFree to allow the Tcl_Preserve(scalePtr) to work
  56.  * as expected in TkpDisplayScale. (hobbs)
  57.  *
  58.  * Results:
  59.  * None
  60.  *
  61.  * Side effects:
  62.  * Memory is freed.
  63.  *
  64.  *----------------------------------------------------------------------
  65.  */
  66. void
  67. TkpDestroyScale(scalePtr)
  68.     TkScale *scalePtr;
  69. {
  70.     Tcl_EventuallyFree((ClientData) scalePtr, TCL_DYNAMIC);
  71. }
  72. /*
  73.  *--------------------------------------------------------------
  74.  *
  75.  * DisplayVerticalScale --
  76.  *
  77.  * This procedure redraws the contents of a vertical scale
  78.  * window.  It is invoked as a do-when-idle handler, so it only
  79.  * runs when there's nothing else for the application to do.
  80.  *
  81.  * Results:
  82.  * There is no return value.  If only a part of the scale needs
  83.  * to be redrawn, then drawnAreaPtr is modified to reflect the
  84.  * area that was actually modified.
  85.  *
  86.  * Side effects:
  87.  * Information appears on the screen.
  88.  *
  89.  *--------------------------------------------------------------
  90.  */
  91. static void
  92. DisplayVerticalScale(scalePtr, drawable, drawnAreaPtr)
  93.     TkScale *scalePtr; /* Widget record for scale. */
  94.     Drawable drawable; /* Where to display scale (window
  95.  * or pixmap). */
  96.     XRectangle *drawnAreaPtr; /* Initally contains area of window;
  97.  * if only a part of the scale is
  98.  * redrawn, gets modified to reflect
  99.  * the part of the window that was
  100.  * redrawn. */
  101. {
  102.     Tk_Window tkwin = scalePtr->tkwin;
  103.     int x, y, width, height, shadowWidth;
  104.     double tickValue, tickInterval = scalePtr->tickInterval;
  105.     Tk_3DBorder sliderBorder;
  106.     /*
  107.      * Display the information from left to right across the window.
  108.      */
  109.     if (!(scalePtr->flags & REDRAW_OTHER)) {
  110. drawnAreaPtr->x = scalePtr->vertTickRightX;
  111. drawnAreaPtr->y = scalePtr->inset;
  112. drawnAreaPtr->width = scalePtr->vertTroughX + scalePtr->width
  113. + 2*scalePtr->borderWidth - scalePtr->vertTickRightX;
  114. drawnAreaPtr->height -= 2*scalePtr->inset;
  115.     }
  116.     Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
  117.     drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
  118.     drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
  119.     if (scalePtr->flags & REDRAW_OTHER) {
  120. /*
  121.  * Display the tick marks.
  122.  */
  123. if (tickInterval != 0) {
  124.     double ticks, maxTicks;
  125.     /*
  126.      * Ensure that we will only draw enough of the tick values
  127.      * such that they don't overlap
  128.      */
  129.     ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
  130.     / tickInterval);
  131.     maxTicks = (double) Tk_Height(tkwin)
  132. / (double) scalePtr->fontHeight;
  133.     if (ticks > maxTicks) {
  134. tickInterval *= (ticks / maxTicks);
  135.     }
  136.     for (tickValue = scalePtr->fromValue; ;
  137.  tickValue += tickInterval) {
  138. /*
  139.  * The TkRoundToResolution call gets rid of accumulated
  140.  * round-off errors, if any.
  141.  */
  142. tickValue = TkRoundToResolution(scalePtr, tickValue);
  143. if (scalePtr->toValue >= scalePtr->fromValue) {
  144.     if (tickValue > scalePtr->toValue) {
  145. break;
  146.     }
  147. } else {
  148.     if (tickValue < scalePtr->toValue) {
  149. break;
  150.     }
  151. }
  152. DisplayVerticalValue(scalePtr, drawable, tickValue,
  153. scalePtr->vertTickRightX);
  154.     }
  155. }
  156.     }
  157.     /*
  158.      * Display the value, if it is desired.
  159.      */
  160.     if (scalePtr->showValue) {
  161. DisplayVerticalValue(scalePtr, drawable, scalePtr->value,
  162. scalePtr->vertValueRightX);
  163.     }
  164.     /*
  165.      * Display the trough and the slider.
  166.      */
  167.     Tk_Draw3DRectangle(tkwin, drawable,
  168.     scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset,
  169.     scalePtr->width + 2*scalePtr->borderWidth,
  170.     Tk_Height(tkwin) - 2*scalePtr->inset, scalePtr->borderWidth,
  171.     TK_RELIEF_SUNKEN);
  172.     XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
  173.     scalePtr->vertTroughX + scalePtr->borderWidth,
  174.     scalePtr->inset + scalePtr->borderWidth,
  175.     (unsigned) scalePtr->width,
  176.     (unsigned) (Tk_Height(tkwin) - 2*scalePtr->inset
  177. - 2*scalePtr->borderWidth));
  178.     if (scalePtr->state == STATE_ACTIVE) {
  179. sliderBorder = scalePtr->activeBorder;
  180.     } else {
  181. sliderBorder = scalePtr->bgBorder;
  182.     }
  183.     width = scalePtr->width;
  184.     height = scalePtr->sliderLength/2;
  185.     x = scalePtr->vertTroughX + scalePtr->borderWidth;
  186.     y = TkScaleValueToPixel(scalePtr, scalePtr->value) - height;
  187.     shadowWidth = scalePtr->borderWidth/2;
  188.     if (shadowWidth == 0) {
  189. shadowWidth = 1;
  190.     }
  191.     Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
  192.     2*height, shadowWidth, scalePtr->sliderRelief);
  193.     x += shadowWidth;
  194.     y += shadowWidth;
  195.     width -= 2*shadowWidth;
  196.     height -= shadowWidth;
  197.     Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
  198.     height, shadowWidth, scalePtr->sliderRelief);
  199.     Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height,
  200.     width, height, shadowWidth, scalePtr->sliderRelief);
  201.     /*
  202.      * Draw the label to the right of the scale.
  203.      */
  204.     if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
  205. Tk_FontMetrics fm;
  206. Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  207. Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  208. scalePtr->tkfont, scalePtr->label, 
  209.                 scalePtr->labelLength, scalePtr->vertLabelX,
  210.                 scalePtr->inset + (3*fm.ascent)/2);
  211.     }
  212. }
  213. /*
  214.  *----------------------------------------------------------------------
  215.  *
  216.  * DisplayVerticalValue --
  217.  *
  218.  * This procedure is called to display values (scale readings)
  219.  * for vertically-oriented scales.
  220.  *
  221.  * Results:
  222.  * None.
  223.  *
  224.  * Side effects:
  225.  * The numerical value corresponding to value is displayed with
  226.  * its right edge at "rightEdge", and at a vertical position in
  227.  * the scale that corresponds to "value".
  228.  *
  229.  *----------------------------------------------------------------------
  230.  */
  231. static void
  232. DisplayVerticalValue(scalePtr, drawable, value, rightEdge)
  233.     register TkScale *scalePtr; /* Information about widget in which to
  234.  * display value. */
  235.     Drawable drawable; /* Pixmap or window in which to draw
  236.  * the value. */
  237.     double value; /* Y-coordinate of number to display,
  238.  * specified in application coords, not
  239.  * in pixels (we'll compute pixels). */
  240.     int rightEdge; /* X-coordinate of right edge of text,
  241.  * specified in pixels. */
  242. {
  243.     register Tk_Window tkwin = scalePtr->tkwin;
  244.     int y, width, length;
  245.     char valueString[PRINT_CHARS];
  246.     Tk_FontMetrics fm;
  247.     Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  248.     y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
  249.     sprintf(valueString, scalePtr->format, value);
  250.     length = (int) strlen(valueString);
  251.     width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
  252.     /*
  253.      * Adjust the y-coordinate if necessary to keep the text entirely
  254.      * inside the window.
  255.      */
  256.     if ((y - fm.ascent) < (scalePtr->inset + SPACING)) {
  257. y = scalePtr->inset + SPACING + fm.ascent;
  258.     }
  259.     if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) {
  260. y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent;
  261.     }
  262.     Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  263.     scalePtr->tkfont, valueString, length, rightEdge - width, y);
  264. }
  265. /*
  266.  *--------------------------------------------------------------
  267.  *
  268.  * DisplayHorizontalScale --
  269.  *
  270.  * This procedure redraws the contents of a horizontal scale
  271.  * window.  It is invoked as a do-when-idle handler, so it only
  272.  * runs when there's nothing else for the application to do.
  273.  *
  274.  * Results:
  275.  * There is no return value.  If only a part of the scale needs
  276.  * to be redrawn, then drawnAreaPtr is modified to reflect the
  277.  * area that was actually modified.
  278.  *
  279.  * Side effects:
  280.  * Information appears on the screen.
  281.  *
  282.  *--------------------------------------------------------------
  283.  */
  284. static void
  285. DisplayHorizontalScale(scalePtr, drawable, drawnAreaPtr)
  286.     TkScale *scalePtr; /* Widget record for scale. */
  287.     Drawable drawable; /* Where to display scale (window
  288.  * or pixmap). */
  289.     XRectangle *drawnAreaPtr; /* Initally contains area of window;
  290.  * if only a part of the scale is
  291.  * redrawn, gets modified to reflect
  292.  * the part of the window that was
  293.  * redrawn. */
  294. {
  295.     register Tk_Window tkwin = scalePtr->tkwin;
  296.     int x, y, width, height, shadowWidth;
  297.     double tickValue, tickInterval = scalePtr->tickInterval;
  298.     Tk_3DBorder sliderBorder;
  299.     /*
  300.      * Display the information from bottom to top across the window.
  301.      */
  302.     if (!(scalePtr->flags & REDRAW_OTHER)) {
  303. drawnAreaPtr->x = scalePtr->inset;
  304. drawnAreaPtr->y = scalePtr->horizValueY;
  305. drawnAreaPtr->width -= 2*scalePtr->inset;
  306. drawnAreaPtr->height = scalePtr->horizTroughY + scalePtr->width
  307. + 2*scalePtr->borderWidth - scalePtr->horizValueY;
  308.     }
  309.     Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
  310.     drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
  311.     drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
  312.     if (scalePtr->flags & REDRAW_OTHER) {
  313. /*
  314.  * Display the tick marks.
  315.  */
  316. if (tickInterval != 0) {
  317.     char valueString[PRINT_CHARS];
  318.     double ticks, maxTicks;
  319.     /*
  320.      * Ensure that we will only draw enough of the tick values
  321.      * such that they don't overlap.  We base this off the width that
  322.      * fromValue would take.  Not exact, but better than no constraint.
  323.      */
  324.     ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
  325.     / tickInterval);
  326.     sprintf(valueString, scalePtr->format, scalePtr->fromValue);
  327.     maxTicks = (double) Tk_Width(tkwin)
  328. / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
  329.     if (ticks > maxTicks) {
  330. tickInterval *= (ticks / maxTicks);
  331.     }
  332.     for (tickValue = scalePtr->fromValue; ;
  333.  tickValue += tickInterval) {
  334. /*
  335.  * The TkRoundToResolution call gets rid of accumulated
  336.  * round-off errors, if any.
  337.  */
  338. tickValue = TkRoundToResolution(scalePtr, tickValue);
  339. if (scalePtr->toValue >= scalePtr->fromValue) {
  340.     if (tickValue > scalePtr->toValue) {
  341. break;
  342.     }
  343. } else {
  344.     if (tickValue < scalePtr->toValue) {
  345. break;
  346.     }
  347. }
  348. DisplayHorizontalValue(scalePtr, drawable, tickValue,
  349. scalePtr->horizTickY);
  350.     }
  351. }
  352.     }
  353.     /*
  354.      * Display the value, if it is desired.
  355.      */
  356.     if (scalePtr->showValue) {
  357. DisplayHorizontalValue(scalePtr, drawable, scalePtr->value,
  358. scalePtr->horizValueY);
  359.     }
  360.     /*
  361.      * Display the trough and the slider.
  362.      */
  363.     y = scalePtr->horizTroughY;
  364.     Tk_Draw3DRectangle(tkwin, drawable,
  365.     scalePtr->bgBorder, scalePtr->inset, y,
  366.     Tk_Width(tkwin) - 2*scalePtr->inset,
  367.     scalePtr->width + 2*scalePtr->borderWidth,
  368.     scalePtr->borderWidth, TK_RELIEF_SUNKEN);
  369.     XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
  370.     scalePtr->inset + scalePtr->borderWidth,
  371.     y + scalePtr->borderWidth,
  372.     (unsigned) (Tk_Width(tkwin) - 2*scalePtr->inset
  373. - 2*scalePtr->borderWidth),
  374.     (unsigned) scalePtr->width);
  375.     if (scalePtr->state == STATE_ACTIVE) {
  376. sliderBorder = scalePtr->activeBorder;
  377.     } else {
  378. sliderBorder = scalePtr->bgBorder;
  379.     }
  380.     width = scalePtr->sliderLength/2;
  381.     height = scalePtr->width;
  382.     x = TkScaleValueToPixel(scalePtr, scalePtr->value) - width;
  383.     y += scalePtr->borderWidth;
  384.     shadowWidth = scalePtr->borderWidth/2;
  385.     if (shadowWidth == 0) {
  386. shadowWidth = 1;
  387.     }
  388.     Tk_Draw3DRectangle(tkwin, drawable, sliderBorder,
  389.     x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief);
  390.     x += shadowWidth;
  391.     y += shadowWidth;
  392.     width -= shadowWidth;
  393.     height -= 2*shadowWidth;
  394.     Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height,
  395.     shadowWidth, scalePtr->sliderRelief);
  396.     Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y,
  397.     width, height, shadowWidth, scalePtr->sliderRelief);
  398.     /*
  399.      * Draw the label at the top of the scale.
  400.      */
  401.     if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
  402. Tk_FontMetrics fm;
  403. Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  404. Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  405. scalePtr->tkfont, scalePtr->label, 
  406.                 scalePtr->labelLength, scalePtr->inset + fm.ascent/2, 
  407.                 scalePtr->horizLabelY + fm.ascent);
  408.     }
  409. }
  410. /*
  411.  *----------------------------------------------------------------------
  412.  *
  413.  * DisplayHorizontalValue --
  414.  *
  415.  * This procedure is called to display values (scale readings)
  416.  * for horizontally-oriented scales.
  417.  *
  418.  * Results:
  419.  * None.
  420.  *
  421.  * Side effects:
  422.  * The numerical value corresponding to value is displayed with
  423.  * its bottom edge at "bottom", and at a horizontal position in
  424.  * the scale that corresponds to "value".
  425.  *
  426.  *----------------------------------------------------------------------
  427.  */
  428. static void
  429. DisplayHorizontalValue(scalePtr, drawable, value, top)
  430.     register TkScale *scalePtr; /* Information about widget in which to
  431.  * display value. */
  432.     Drawable drawable; /* Pixmap or window in which to draw
  433.  * the value. */
  434.     double value; /* X-coordinate of number to display,
  435.  * specified in application coords, not
  436.  * in pixels (we'll compute pixels). */
  437.     int top; /* Y-coordinate of top edge of text,
  438.  * specified in pixels. */
  439. {
  440.     register Tk_Window tkwin = scalePtr->tkwin;
  441.     int x, y, length, width;
  442.     char valueString[PRINT_CHARS];
  443.     Tk_FontMetrics fm;
  444.     x = TkScaleValueToPixel(scalePtr, value);
  445.     Tk_GetFontMetrics(scalePtr->tkfont, &fm);
  446.     y = top + fm.ascent;
  447.     sprintf(valueString, scalePtr->format, value);
  448.     length = (int) strlen(valueString);
  449.     width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
  450.     /*
  451.      * Adjust the x-coordinate if necessary to keep the text entirely
  452.      * inside the window.
  453.      */
  454.     x -= (width)/2;
  455.     if (x < (scalePtr->inset + SPACING)) {
  456. x = scalePtr->inset + SPACING;
  457.     }
  458.     /*
  459.      * Check the right border so use starting point +text width
  460.      * for the check.
  461.      */
  462.     if (x + width >= (Tk_Width(tkwin) - scalePtr->inset)) {
  463. x = Tk_Width(tkwin) - scalePtr->inset - SPACING - width;
  464.     }
  465.     Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
  466.     scalePtr->tkfont, valueString, length, x, y);
  467. }
  468. /*
  469.  *----------------------------------------------------------------------
  470.  *
  471.  * TkpDisplayScale --
  472.  *
  473.  * This procedure is invoked as an idle handler to redisplay
  474.  * the contents of a scale widget.
  475.  *
  476.  * Results:
  477.  * None.
  478.  *
  479.  * Side effects:
  480.  * The scale gets redisplayed.
  481.  *
  482.  *----------------------------------------------------------------------
  483.  */
  484. void
  485. TkpDisplayScale(clientData)
  486.     ClientData clientData; /* Widget record for scale. */
  487. {
  488.     TkScale *scalePtr = (TkScale *) clientData;
  489.     Tk_Window tkwin = scalePtr->tkwin;
  490.     Tcl_Interp *interp = scalePtr->interp;
  491.     Pixmap pixmap;
  492.     int result;
  493.     char string[PRINT_CHARS];
  494.     XRectangle drawnArea;
  495.     scalePtr->flags &= ~REDRAW_PENDING;
  496.     if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
  497. goto done;
  498.     }
  499.     /*
  500.      * Invoke the scale's command if needed.
  501.      */
  502.     Tcl_Preserve((ClientData) scalePtr);
  503.     if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
  504. Tcl_Preserve((ClientData) interp);
  505. sprintf(string, scalePtr->format, scalePtr->value);
  506. result = Tcl_VarEval(interp, scalePtr->command, " ", string,
  507. (char *) NULL);
  508. if (result != TCL_OK) {
  509.     Tcl_AddErrorInfo(interp, "n    (command executed by scale)");
  510.     Tcl_BackgroundError(interp);
  511. }
  512. Tcl_Release((ClientData) interp);
  513.     }
  514.     scalePtr->flags &= ~INVOKE_COMMAND;
  515.     if (scalePtr->flags & SCALE_DELETED) {
  516. Tcl_Release((ClientData) scalePtr);
  517. return;
  518.     }
  519.     Tcl_Release((ClientData) scalePtr);
  520. #ifndef TK_NO_DOUBLE_BUFFERING
  521.     /*
  522.      * In order to avoid screen flashes, this procedure redraws
  523.      * the scale in a pixmap, then copies the pixmap to the
  524.      * screen in a single operation.  This means that there's no
  525.      * point in time where the on-sreen image has been cleared.
  526.      */
  527.     pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin),
  528.     Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
  529. #else
  530.     pixmap = Tk_WindowId(tkwin);
  531. #endif /* TK_NO_DOUBLE_BUFFERING */
  532.     drawnArea.x = 0;
  533.     drawnArea.y = 0;
  534.     drawnArea.width = Tk_Width(tkwin);
  535.     drawnArea.height = Tk_Height(tkwin);
  536.     /*
  537.      * Much of the redisplay is done totally differently for
  538.      * horizontal and vertical scales.  Handle the part that's
  539.      * different.
  540.      */
  541.     if (scalePtr->orient == ORIENT_VERTICAL) {
  542. DisplayVerticalScale(scalePtr, pixmap, &drawnArea);
  543.     } else {
  544. DisplayHorizontalScale(scalePtr, pixmap, &drawnArea);
  545.     }
  546.     /*
  547.      * Now handle the part of redisplay that is the same for
  548.      * horizontal and vertical scales:  border and traversal
  549.      * highlight.
  550.      */
  551.     if (scalePtr->flags & REDRAW_OTHER) {
  552. if (scalePtr->relief != TK_RELIEF_FLAT) {
  553.     Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder,
  554.     scalePtr->highlightWidth, scalePtr->highlightWidth,
  555.     Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
  556.     Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
  557.     scalePtr->borderWidth, scalePtr->relief);
  558. }
  559. if (scalePtr->highlightWidth != 0) {
  560.     GC gc;
  561.     
  562.     if (scalePtr->flags & GOT_FOCUS) {
  563. gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);
  564.     } else {
  565. gc = Tk_GCForColor(
  566.                         Tk_3DBorderColor(scalePtr->highlightBorder), pixmap);
  567.     }
  568.     Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap);
  569. }
  570.     }
  571. #ifndef TK_NO_DOUBLE_BUFFERING
  572.     /*
  573.      * Copy the information from the off-screen pixmap onto the screen,
  574.      * then delete the pixmap.
  575.      */
  576.     XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin),
  577.     scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width,
  578.     drawnArea.height, drawnArea.x, drawnArea.y);
  579.     Tk_FreePixmap(scalePtr->display, pixmap);
  580. #endif /* TK_NO_DOUBLE_BUFFERING */
  581.     done:
  582.     scalePtr->flags &= ~REDRAW_ALL;
  583. }
  584. /*
  585.  *----------------------------------------------------------------------
  586.  *
  587.  * TkpScaleElement --
  588.  *
  589.  * Determine which part of a scale widget lies under a given
  590.  * point.
  591.  *
  592.  * Results:
  593.  * The return value is either TROUGH1, SLIDER, TROUGH2, or
  594.  * OTHER, depending on which of the scale's active elements
  595.  * (if any) is under the point at (x,y).
  596.  *
  597.  * Side effects:
  598.  * None.
  599.  *
  600.  *----------------------------------------------------------------------
  601.  */
  602. int
  603. TkpScaleElement(scalePtr, x, y)
  604.     TkScale *scalePtr; /* Widget record for scale. */
  605.     int x, y; /* Coordinates within scalePtr's window. */
  606. {
  607.     int sliderFirst;
  608.     if (scalePtr->orient == ORIENT_VERTICAL) {
  609. if ((x < scalePtr->vertTroughX)
  610. || (x >= (scalePtr->vertTroughX + 2*scalePtr->borderWidth +
  611. scalePtr->width))) {
  612.     return OTHER;
  613. }
  614. if ((y < scalePtr->inset)
  615. || (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) {
  616.     return OTHER;
  617. }
  618. sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)
  619. - scalePtr->sliderLength/2;
  620. if (y < sliderFirst) {
  621.     return TROUGH1;
  622. }
  623. if (y < (sliderFirst+scalePtr->sliderLength)) {
  624.     return SLIDER;
  625. }
  626. return TROUGH2;
  627.     }
  628.     if ((y < scalePtr->horizTroughY)
  629.     || (y >= (scalePtr->horizTroughY + 2*scalePtr->borderWidth +
  630.     scalePtr->width))) {
  631. return OTHER;
  632.     }
  633.     if ((x < scalePtr->inset)
  634.     || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) {
  635. return OTHER;
  636.     }
  637.     sliderFirst = TkScaleValueToPixel(scalePtr, scalePtr->value)
  638.     - scalePtr->sliderLength/2;
  639.     if (x < sliderFirst) {
  640. return TROUGH1;
  641.     }
  642.     if (x < (sliderFirst+scalePtr->sliderLength)) {
  643. return SLIDER;
  644.     }
  645.     return TROUGH2;
  646. }