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

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

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

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

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25