/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinscrlbr.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinscrlbr.c

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

to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkwinscrlbr.c revision 29 by dashley, Sat Oct 8 07:08:47 2016 UTC projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkwinscrlbr.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkwinscrlbr.c,v 1.1.1.1 2001/06/13 05:14:22 dtashley Exp $ */  
   
 /*  
  * tkWinScrollbar.c --  
  *  
  *      This file implements the Windows specific portion of the scrollbar  
  *      widget.  
  *  
  * Copyright (c) 1996 by Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkwinscrlbr.c,v 1.1.1.1 2001/06/13 05:14:22 dtashley Exp $  
  */  
   
 #include "tkWinInt.h"  
 #include "tkScrollbar.h"  
   
   
 /*  
  * The following constant is used to specify the maximum scroll position.  
  * This value is limited by the Win32 API to either 16-bits or 32-bits,  
  * depending on the context.  For now we'll just use a value small  
  * enough to fit in 16-bits, but which gives us 4-digits of precision.  
  */  
   
 #define MAX_SCROLL 10000  
   
 /*  
  * Declaration of Windows specific scrollbar structure.  
  */  
   
 typedef struct WinScrollbar {  
     TkScrollbar info;           /* Generic scrollbar info. */  
     WNDPROC oldProc;            /* Old window procedure. */  
     int lastVertical;           /* 1 if was vertical at last refresh. */  
     HWND hwnd;                  /* Current window handle. */  
     int winFlags;               /* Various flags; see below. */  
 } WinScrollbar;  
   
 /*  
  * Flag bits for native scrollbars:  
  *  
  * IN_MODAL_LOOP:               Non-zero means this scrollbar is in the middle  
  *                              of a modal loop.  
  * ALREADY_DEAD:                Non-zero means this scrollbar has been  
  *                              destroyed, but has not been cleaned up.  
  */  
   
 #define IN_MODAL_LOOP   1  
 #define ALREADY_DEAD    2  
   
 /*  
  * Cached system metrics used to determine scrollbar geometry.  
  */  
   
 static int initialized = 0;  
 static int hArrowWidth, hThumb; /* Horizontal control metrics. */  
 static int vArrowWidth, vArrowHeight, vThumb; /* Vertical control metrics. */  
   
 TCL_DECLARE_MUTEX(winScrlbrMutex)  
   
 /*  
  * This variable holds the default width for a scrollbar in string  
  * form for use in a Tk_ConfigSpec.  
  */  
   
 static char defWidth[TCL_INTEGER_SPACE];  
   
 /*  
  * Declarations for functions defined in this file.  
  */  
   
 static Window           CreateProc _ANSI_ARGS_((Tk_Window tkwin,  
                             Window parent, ClientData instanceData));  
 static void             ModalLoopProc _ANSI_ARGS_((Tk_Window tkwin,  
                             XEvent *eventPtr));  
 static int              ScrollbarBindProc _ANSI_ARGS_((ClientData clientData,  
                             Tcl_Interp *interp, XEvent *eventPtr,  
                             Tk_Window tkwin, KeySym keySym));  
 static LRESULT CALLBACK ScrollbarProc _ANSI_ARGS_((HWND hwnd, UINT message,  
                             WPARAM wParam, LPARAM lParam));  
 static void             UpdateScrollbar _ANSI_ARGS_((  
                             WinScrollbar *scrollPtr));  
 static void             UpdateScrollbarMetrics _ANSI_ARGS_((void));  
   
 /*  
  * The class procedure table for the scrollbar widget.  
  */  
   
 TkClassProcs tkpScrollbarProcs = {  
     CreateProc,                 /* createProc */  
     NULL,                       /* geometryProc */  
     ModalLoopProc,              /* modalProc */  
 };  
   
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpCreateScrollbar --  
  *  
  *      Allocate a new TkScrollbar structure.  
  *  
  * Results:  
  *      Returns a newly allocated TkScrollbar structure.  
  *  
  * Side effects:  
  *      Registers an event handler for the widget.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 TkScrollbar *  
 TkpCreateScrollbar(tkwin)  
     Tk_Window tkwin;  
 {  
     WinScrollbar *scrollPtr;  
     TkWindow *winPtr = (TkWindow *)tkwin;  
       
     if (!initialized) {  
         Tcl_MutexLock(&winScrlbrMutex);  
         UpdateScrollbarMetrics();  
         initialized = 1;  
         Tcl_MutexUnlock(&winScrlbrMutex);  
     }  
   
     scrollPtr = (WinScrollbar *) ckalloc(sizeof(WinScrollbar));  
     scrollPtr->winFlags = 0;  
     scrollPtr->hwnd = NULL;  
   
     Tk_CreateEventHandler(tkwin,  
             ExposureMask|StructureNotifyMask|FocusChangeMask,  
             TkScrollbarEventProc, (ClientData) scrollPtr);  
   
     if (!Tcl_GetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL)) {  
         Tcl_SetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL,  
                 (ClientData)1);  
         TkCreateBindingProcedure(winPtr->mainPtr->interp,  
                 winPtr->mainPtr->bindingTable,  
                 (ClientData)Tk_GetUid("Scrollbar"), "<ButtonPress>",  
                 ScrollbarBindProc, NULL, NULL);  
     }  
   
     return (TkScrollbar*) scrollPtr;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * UpdateScrollbar --  
  *  
  *      This function updates the position and size of the scrollbar  
  *      thumb based on the current settings.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Moves the thumb.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 UpdateScrollbar(scrollPtr)  
     WinScrollbar *scrollPtr;  
 {  
     SCROLLINFO scrollInfo;  
     double thumbSize;  
   
     /*  
      * Update the current scrollbar position and shape.  
      */  
   
     scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;  
     scrollInfo.cbSize = sizeof(scrollInfo);  
     scrollInfo.nMin = 0;  
     scrollInfo.nMax = MAX_SCROLL;  
     thumbSize = (scrollPtr->info.lastFraction - scrollPtr->info.firstFraction);  
     scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1;  
     if (thumbSize < 1.0) {  
         scrollInfo.nPos = (int)  
             ((scrollPtr->info.firstFraction / (1.0-thumbSize))  
                     * (MAX_SCROLL - (scrollInfo.nPage - 1)));  
     } else {  
         scrollInfo.nPos = 0;  
     }  
     SetScrollInfo(scrollPtr->hwnd, SB_CTL, &scrollInfo, TRUE);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * CreateProc --  
  *  
  *      This function creates a new Scrollbar control, subclasses  
  *      the instance, and generates a new Window object.  
  *  
  * Results:  
  *      Returns the newly allocated Window object, or None on failure.  
  *  
  * Side effects:  
  *      Causes a new Scrollbar control to come into existence.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static Window  
 CreateProc(tkwin, parentWin, instanceData)  
     Tk_Window tkwin;            /* Token for window. */  
     Window parentWin;           /* Parent of new window. */  
     ClientData instanceData;    /* Scrollbar instance data. */  
 {  
     DWORD style;  
     Window window;  
     HWND parent;  
     TkWindow *winPtr;  
     WinScrollbar *scrollPtr = (WinScrollbar *)instanceData;  
   
     parent = Tk_GetHWND(parentWin);  
   
     if (scrollPtr->info.vertical) {  
         style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS  
             | SBS_VERT | SBS_RIGHTALIGN;  
     } else {  
         style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS  
             | SBS_HORZ | SBS_BOTTOMALIGN;  
     }  
   
     scrollPtr->hwnd = CreateWindow("SCROLLBAR", NULL, style,  
             Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),  
             parent, NULL, Tk_GetHINSTANCE(), NULL);  
   
     /*  
      * Ensure new window is inserted into the stacking order at the correct  
      * place.  
      */  
   
     SetWindowPos(scrollPtr->hwnd, HWND_TOP, 0, 0, 0, 0,  
                     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);  
   
     for (winPtr = ((TkWindow*)tkwin)->nextPtr; winPtr != NULL;  
          winPtr = winPtr->nextPtr) {  
         if ((winPtr->window != None) && !(winPtr->flags & TK_TOP_LEVEL)) {  
             TkWinSetWindowPos(scrollPtr->hwnd, Tk_GetHWND(winPtr->window),  
                     Below);  
             break;  
         }  
     }  
   
     scrollPtr->lastVertical = scrollPtr->info.vertical;  
     scrollPtr->oldProc = (WNDPROC)SetWindowLong(scrollPtr->hwnd, GWL_WNDPROC,  
             (DWORD) ScrollbarProc);  
     window = Tk_AttachHWND(tkwin, scrollPtr->hwnd);  
   
     UpdateScrollbar(scrollPtr);  
     return window;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * TkpDisplayScrollbar --  
  *  
  *      This procedure redraws the contents of a scrollbar 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:  
  *      None.  
  *  
  * Side effects:  
  *      Information appears on the screen.  
  *  
  *--------------------------------------------------------------  
  */  
   
 void  
 TkpDisplayScrollbar(clientData)  
     ClientData clientData;      /* Information about window. */  
 {  
     WinScrollbar *scrollPtr = (WinScrollbar *) clientData;  
     Tk_Window tkwin = scrollPtr->info.tkwin;  
   
     scrollPtr->info.flags &= ~REDRAW_PENDING;  
     if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {  
         return;  
     }  
   
     /*  
      * Destroy and recreate the scrollbar control if the orientation  
      * has changed.  
      */  
   
     if (scrollPtr->lastVertical != scrollPtr->info.vertical) {  
         HWND hwnd = Tk_GetHWND(Tk_WindowId(tkwin));  
   
         SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) scrollPtr->oldProc);  
         DestroyWindow(hwnd);  
   
         CreateProc(tkwin, Tk_WindowId(Tk_Parent(tkwin)),  
                 (ClientData) scrollPtr);  
     } else {  
         UpdateScrollbar(scrollPtr);  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpDestroyScrollbar --  
  *  
  *      Free data structures associated with the scrollbar control.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Restores the default control state.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkpDestroyScrollbar(scrollPtr)  
     TkScrollbar *scrollPtr;  
 {  
     WinScrollbar *winScrollPtr = (WinScrollbar *)scrollPtr;  
     HWND hwnd = winScrollPtr->hwnd;  
     if (hwnd) {  
         SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) winScrollPtr->oldProc);  
         if (winScrollPtr->winFlags & IN_MODAL_LOOP) {  
             ((TkWindow *)scrollPtr->tkwin)->flags |= TK_DONT_DESTROY_WINDOW;  
             SetParent(hwnd, NULL);  
         }  
     }  
     winScrollPtr->winFlags |= ALREADY_DEAD;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * UpdateScrollbarMetrics --  
  *  
  *      This function retrieves the current system metrics for a  
  *      scrollbar.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Updates the geometry cache info for all scrollbars.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 UpdateScrollbarMetrics()  
 {  
     Tk_ConfigSpec *specPtr;  
   
     hArrowWidth = GetSystemMetrics(SM_CXHSCROLL);  
     hThumb = GetSystemMetrics(SM_CXHTHUMB);  
     vArrowWidth = GetSystemMetrics(SM_CXVSCROLL);  
     vArrowHeight = GetSystemMetrics(SM_CYVSCROLL);  
     vThumb = GetSystemMetrics(SM_CYVTHUMB);  
   
     sprintf(defWidth, "%d", vArrowWidth);  
     for (specPtr = tkpScrollbarConfigSpecs; specPtr->type != TK_CONFIG_END;  
             specPtr++) {  
         if (specPtr->offset == Tk_Offset(TkScrollbar, width)) {  
             specPtr->defValue = defWidth;  
         }  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpComputeScrollbarGeometry --  
  *  
  *      After changes in a scrollbar's size or configuration, this  
  *      procedure recomputes various geometry information used in  
  *      displaying the scrollbar.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The scrollbar will be displayed differently.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkpComputeScrollbarGeometry(scrollPtr)  
     register TkScrollbar *scrollPtr;    /* Scrollbar whose geometry may  
                                          * have changed. */  
 {  
     int fieldLength, minThumbSize;  
   
     /*  
      * Windows doesn't use focus rings on scrollbars, but we still  
      * perform basic sanity checks to appease backwards compatibility.  
      */  
   
     if (scrollPtr->highlightWidth < 0) {  
         scrollPtr->highlightWidth = 0;  
     }  
   
     if (scrollPtr->vertical) {  
         scrollPtr->arrowLength = vArrowHeight;  
         fieldLength = Tk_Height(scrollPtr->tkwin);  
         minThumbSize = vThumb;  
     } else {  
         scrollPtr->arrowLength = hArrowWidth;  
         fieldLength = Tk_Width(scrollPtr->tkwin);  
         minThumbSize = hThumb;  
     }  
     fieldLength -= 2*scrollPtr->arrowLength;  
     if (fieldLength < 0) {  
         fieldLength = 0;  
     }  
     scrollPtr->sliderFirst = (int) ((double)fieldLength  
             * scrollPtr->firstFraction);  
     scrollPtr->sliderLast = (int) ((double)fieldLength  
             * scrollPtr->lastFraction);  
   
     /*  
      * Adjust the slider so that some piece of it is always  
      * displayed in the scrollbar and so that it has at least  
      * a minimal width (so it can be grabbed with the mouse).  
      */  
   
     if (scrollPtr->sliderFirst > fieldLength) {  
         scrollPtr->sliderFirst = fieldLength;  
     }  
     if (scrollPtr->sliderFirst < 0) {  
         scrollPtr->sliderFirst = 0;  
     }  
     if (scrollPtr->sliderLast < (scrollPtr->sliderFirst  
             + minThumbSize)) {  
         scrollPtr->sliderLast = scrollPtr->sliderFirst + minThumbSize;  
     }  
     if (scrollPtr->sliderLast > fieldLength) {  
         scrollPtr->sliderLast = fieldLength;  
     }  
     scrollPtr->sliderFirst += scrollPtr->arrowLength;  
     scrollPtr->sliderLast += scrollPtr->arrowLength;  
   
     /*  
      * Register the desired geometry for the window (leave enough space  
      * for the two arrows plus a minimum-size slider, plus border around  
      * the whole window, if any).  Then arrange for the window to be  
      * redisplayed.  
      */  
   
     if (scrollPtr->vertical) {  
         Tk_GeometryRequest(scrollPtr->tkwin,  
                 scrollPtr->width, 2*scrollPtr->arrowLength + minThumbSize);  
     } else {  
         Tk_GeometryRequest(scrollPtr->tkwin,  
                 2*scrollPtr->arrowLength + minThumbSize, scrollPtr->width);  
     }  
     Tk_SetInternalBorder(scrollPtr->tkwin, 0);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ScrollbarProc --  
  *  
  *      This function is call by Windows whenever an event occurs on  
  *      a scrollbar control created by Tk.  
  *  
  * Results:  
  *      Standard Windows return value.  
  *  
  * Side effects:  
  *      May generate events.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static LRESULT CALLBACK  
 ScrollbarProc(hwnd, message, wParam, lParam)  
     HWND hwnd;  
     UINT message;  
     WPARAM wParam;  
     LPARAM lParam;  
 {  
     LRESULT result;  
     POINT point;  
     WinScrollbar *scrollPtr;  
     Tk_Window tkwin = Tk_HWNDToWindow(hwnd);  
   
     if (tkwin == NULL) {  
         panic("ScrollbarProc called on an invalid HWND");  
     }  
     scrollPtr = (WinScrollbar *)((TkWindow*)tkwin)->instanceData;  
   
     switch(message) {  
         case WM_HSCROLL:  
         case WM_VSCROLL: {  
             Tcl_Interp *interp;  
             Tcl_DString cmdString;  
             int command = LOWORD(wParam);  
             int code;  
   
             GetCursorPos(&point);  
             Tk_TranslateWinEvent(NULL, WM_MOUSEMOVE, 0,  
                     MAKELPARAM(point.x, point.y), &result);  
   
             if (command == SB_ENDSCROLL) {  
                 return 0;  
             }  
   
             /*  
              * Bail out immediately if there isn't a command to invoke.  
              */  
   
             if (scrollPtr->info.commandSize == 0) {  
                 Tcl_ServiceAll();  
                 return 0;  
             }  
                   
             Tcl_DStringInit(&cmdString);  
             Tcl_DStringAppend(&cmdString, scrollPtr->info.command,  
                     scrollPtr->info.commandSize);  
                   
             if (command == SB_LINELEFT || command == SB_LINERIGHT) {  
                 Tcl_DStringAppendElement(&cmdString, "scroll");  
                 Tcl_DStringAppendElement(&cmdString,  
                         (command == SB_LINELEFT ) ? "-1" : "1");  
                 Tcl_DStringAppendElement(&cmdString, "units");  
             } else if (command == SB_PAGELEFT || command == SB_PAGERIGHT) {  
                 Tcl_DStringAppendElement(&cmdString, "scroll");  
                 Tcl_DStringAppendElement(&cmdString,  
                         (command == SB_PAGELEFT ) ? "-1" : "1");  
                 Tcl_DStringAppendElement(&cmdString, "pages");  
             } else {  
                 char valueString[TCL_DOUBLE_SPACE];  
                 double pos = 0.0;  
                 switch (command) {  
                     case SB_THUMBPOSITION:  
                         pos = ((double)HIWORD(wParam)) / MAX_SCROLL;  
                         break;  
   
                     case SB_THUMBTRACK:  
                         pos = ((double)HIWORD(wParam)) / MAX_SCROLL;  
                         break;  
   
                     case SB_TOP:  
                         pos = 0.0;  
                         break;  
   
                     case SB_BOTTOM:  
                         pos = 1.0;  
                         break;  
                 }  
                 sprintf(valueString, "%g", pos);  
                 Tcl_DStringAppendElement(&cmdString, "moveto");  
                 Tcl_DStringAppendElement(&cmdString, valueString);  
             }  
   
             interp = scrollPtr->info.interp;  
             code = Tcl_GlobalEval(interp, cmdString.string);  
             if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) {  
                 Tcl_AddErrorInfo(interp, "\n    (scrollbar command)");  
                 Tcl_BackgroundError(interp);  
             }            
             Tcl_DStringFree(&cmdString);                  
   
             Tcl_ServiceAll();  
             return 0;  
         }  
   
         default:  
             if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {  
                 return result;  
             }  
     }  
     return CallWindowProc(scrollPtr->oldProc, hwnd, message, wParam, lParam);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpConfigureScrollbar --  
  *  
  *      This procedure is called after the generic code has finished  
  *      processing configuration options, in order to configure  
  *      platform specific options.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkpConfigureScrollbar(scrollPtr)  
     register TkScrollbar *scrollPtr;    /* Information about widget;  may or  
                                          * may not already have values for  
                                          * some fields. */  
 {  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ScrollbarBindProc --  
  *  
  *      This procedure is invoked when the default <ButtonPress>  
  *      binding on the Scrollbar bind tag fires.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The event enters a modal loop.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 ScrollbarBindProc(clientData, interp, eventPtr, tkwin, keySym)  
     ClientData clientData;  
     Tcl_Interp *interp;  
     XEvent *eventPtr;  
     Tk_Window tkwin;  
     KeySym keySym;  
 {  
     TkWindow *winPtr = (TkWindow*)tkwin;  
     if (eventPtr->type == ButtonPress) {  
         winPtr->flags |= TK_DEFER_MODAL;  
     }  
     return TCL_OK;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ModalLoopProc --  
  *  
  *      This function is invoked at the end of the event processing  
  *      whenever the ScrollbarBindProc has been invoked for a ButtonPress  
  *      event.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Enters a modal loop.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 ModalLoopProc(tkwin, eventPtr)  
     Tk_Window tkwin;  
     XEvent *eventPtr;  
 {  
     TkWindow *winPtr = (TkWindow*)tkwin;  
     WinScrollbar *scrollPtr = (WinScrollbar *) winPtr->instanceData;  
     int oldMode;  
   
     if (scrollPtr->hwnd) {  
         Tcl_Preserve((ClientData)scrollPtr);  
         scrollPtr->winFlags |= IN_MODAL_LOOP;  
         oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);  
         TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);  
         (void) Tcl_SetServiceMode(oldMode);  
         scrollPtr->winFlags &= ~IN_MODAL_LOOP;  
         if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {  
             DestroyWindow(scrollPtr->hwnd);  
         }  
         Tcl_Release((ClientData)scrollPtr);  
     }  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * TkpScrollbarPosition --  
  *  
  *      Determine the scrollbar element corresponding to a  
  *      given position.  
  *  
  * Results:  
  *      One of TOP_ARROW, TOP_GAP, etc., indicating which element  
  *      of the scrollbar covers the position given by (x, y).  If  
  *      (x,y) is outside the scrollbar entirely, then OUTSIDE is  
  *      returned.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
 int  
 TkpScrollbarPosition(scrollPtr, x, y)  
     register TkScrollbar *scrollPtr;    /* Scrollbar widget record. */  
     int x, y;                           /* Coordinates within scrollPtr's  
                                          * window. */  
 {  
     int length, width, tmp;  
   
     if (scrollPtr->vertical) {  
         length = Tk_Height(scrollPtr->tkwin);  
         width = Tk_Width(scrollPtr->tkwin);  
     } else {  
         tmp = x;  
         x = y;  
         y = tmp;  
         length = Tk_Width(scrollPtr->tkwin);  
         width = Tk_Height(scrollPtr->tkwin);  
     }  
   
     if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))  
             || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {  
         return OUTSIDE;  
     }  
   
     /*  
      * All of the calculations in this procedure mirror those in  
      * TkpDisplayScrollbar.  Be sure to keep the two consistent.  
      */  
   
     if (y < (scrollPtr->inset + scrollPtr->arrowLength)) {  
         return TOP_ARROW;  
     }  
     if (y < scrollPtr->sliderFirst) {  
         return TOP_GAP;  
     }  
     if (y < scrollPtr->sliderLast) {  
         return SLIDER;  
     }  
     if (y >= (length - (scrollPtr->arrowLength + scrollPtr->inset))) {  
         return BOTTOM_ARROW;  
     }  
     return BOTTOM_GAP;  
 }  
   
   
 /* $History: tkWinScrlbr.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 3:19a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKWINSCRLBR.C */  
1    /* $Header$ */
2    
3    /*
4     * tkWinScrollbar.c --
5     *
6     *      This file implements the Windows specific portion of the scrollbar
7     *      widget.
8     *
9     * Copyright (c) 1996 by Sun Microsystems, Inc.
10     *
11     * See the file "license.terms" for information on usage and redistribution
12     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13     *
14     * RCS: @(#) $Id: tkwinscrlbr.c,v 1.1.1.1 2001/06/13 05:14:22 dtashley Exp $
15     */
16    
17    #include "tkWinInt.h"
18    #include "tkScrollbar.h"
19    
20    
21    /*
22     * The following constant is used to specify the maximum scroll position.
23     * This value is limited by the Win32 API to either 16-bits or 32-bits,
24     * depending on the context.  For now we'll just use a value small
25     * enough to fit in 16-bits, but which gives us 4-digits of precision.
26     */
27    
28    #define MAX_SCROLL 10000
29    
30    /*
31     * Declaration of Windows specific scrollbar structure.
32     */
33    
34    typedef struct WinScrollbar {
35        TkScrollbar info;           /* Generic scrollbar info. */
36        WNDPROC oldProc;            /* Old window procedure. */
37        int lastVertical;           /* 1 if was vertical at last refresh. */
38        HWND hwnd;                  /* Current window handle. */
39        int winFlags;               /* Various flags; see below. */
40    } WinScrollbar;
41    
42    /*
43     * Flag bits for native scrollbars:
44     *
45     * IN_MODAL_LOOP:               Non-zero means this scrollbar is in the middle
46     *                              of a modal loop.
47     * ALREADY_DEAD:                Non-zero means this scrollbar has been
48     *                              destroyed, but has not been cleaned up.
49     */
50    
51    #define IN_MODAL_LOOP   1
52    #define ALREADY_DEAD    2
53    
54    /*
55     * Cached system metrics used to determine scrollbar geometry.
56     */
57    
58    static int initialized = 0;
59    static int hArrowWidth, hThumb; /* Horizontal control metrics. */
60    static int vArrowWidth, vArrowHeight, vThumb; /* Vertical control metrics. */
61    
62    TCL_DECLARE_MUTEX(winScrlbrMutex)
63    
64    /*
65     * This variable holds the default width for a scrollbar in string
66     * form for use in a Tk_ConfigSpec.
67     */
68    
69    static char defWidth[TCL_INTEGER_SPACE];
70    
71    /*
72     * Declarations for functions defined in this file.
73     */
74    
75    static Window           CreateProc _ANSI_ARGS_((Tk_Window tkwin,
76                                Window parent, ClientData instanceData));
77    static void             ModalLoopProc _ANSI_ARGS_((Tk_Window tkwin,
78                                XEvent *eventPtr));
79    static int              ScrollbarBindProc _ANSI_ARGS_((ClientData clientData,
80                                Tcl_Interp *interp, XEvent *eventPtr,
81                                Tk_Window tkwin, KeySym keySym));
82    static LRESULT CALLBACK ScrollbarProc _ANSI_ARGS_((HWND hwnd, UINT message,
83                                WPARAM wParam, LPARAM lParam));
84    static void             UpdateScrollbar _ANSI_ARGS_((
85                                WinScrollbar *scrollPtr));
86    static void             UpdateScrollbarMetrics _ANSI_ARGS_((void));
87    
88    /*
89     * The class procedure table for the scrollbar widget.
90     */
91    
92    TkClassProcs tkpScrollbarProcs = {
93        CreateProc,                 /* createProc */
94        NULL,                       /* geometryProc */
95        ModalLoopProc,              /* modalProc */
96    };
97    
98    
99    /*
100     *----------------------------------------------------------------------
101     *
102     * TkpCreateScrollbar --
103     *
104     *      Allocate a new TkScrollbar structure.
105     *
106     * Results:
107     *      Returns a newly allocated TkScrollbar structure.
108     *
109     * Side effects:
110     *      Registers an event handler for the widget.
111     *
112     *----------------------------------------------------------------------
113     */
114    
115    TkScrollbar *
116    TkpCreateScrollbar(tkwin)
117        Tk_Window tkwin;
118    {
119        WinScrollbar *scrollPtr;
120        TkWindow *winPtr = (TkWindow *)tkwin;
121        
122        if (!initialized) {
123            Tcl_MutexLock(&winScrlbrMutex);
124            UpdateScrollbarMetrics();
125            initialized = 1;
126            Tcl_MutexUnlock(&winScrlbrMutex);
127        }
128    
129        scrollPtr = (WinScrollbar *) ckalloc(sizeof(WinScrollbar));
130        scrollPtr->winFlags = 0;
131        scrollPtr->hwnd = NULL;
132    
133        Tk_CreateEventHandler(tkwin,
134                ExposureMask|StructureNotifyMask|FocusChangeMask,
135                TkScrollbarEventProc, (ClientData) scrollPtr);
136    
137        if (!Tcl_GetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL)) {
138            Tcl_SetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL,
139                    (ClientData)1);
140            TkCreateBindingProcedure(winPtr->mainPtr->interp,
141                    winPtr->mainPtr->bindingTable,
142                    (ClientData)Tk_GetUid("Scrollbar"), "<ButtonPress>",
143                    ScrollbarBindProc, NULL, NULL);
144        }
145    
146        return (TkScrollbar*) scrollPtr;
147    }
148    
149    /*
150     *----------------------------------------------------------------------
151     *
152     * UpdateScrollbar --
153     *
154     *      This function updates the position and size of the scrollbar
155     *      thumb based on the current settings.
156     *
157     * Results:
158     *      None.
159     *
160     * Side effects:
161     *      Moves the thumb.
162     *
163     *----------------------------------------------------------------------
164     */
165    
166    static void
167    UpdateScrollbar(scrollPtr)
168        WinScrollbar *scrollPtr;
169    {
170        SCROLLINFO scrollInfo;
171        double thumbSize;
172    
173        /*
174         * Update the current scrollbar position and shape.
175         */
176    
177        scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
178        scrollInfo.cbSize = sizeof(scrollInfo);
179        scrollInfo.nMin = 0;
180        scrollInfo.nMax = MAX_SCROLL;
181        thumbSize = (scrollPtr->info.lastFraction - scrollPtr->info.firstFraction);
182        scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1;
183        if (thumbSize < 1.0) {
184            scrollInfo.nPos = (int)
185                ((scrollPtr->info.firstFraction / (1.0-thumbSize))
186                        * (MAX_SCROLL - (scrollInfo.nPage - 1)));
187        } else {
188            scrollInfo.nPos = 0;
189        }
190        SetScrollInfo(scrollPtr->hwnd, SB_CTL, &scrollInfo, TRUE);
191    }
192    
193    /*
194     *----------------------------------------------------------------------
195     *
196     * CreateProc --
197     *
198     *      This function creates a new Scrollbar control, subclasses
199     *      the instance, and generates a new Window object.
200     *
201     * Results:
202     *      Returns the newly allocated Window object, or None on failure.
203     *
204     * Side effects:
205     *      Causes a new Scrollbar control to come into existence.
206     *
207     *----------------------------------------------------------------------
208     */
209    
210    static Window
211    CreateProc(tkwin, parentWin, instanceData)
212        Tk_Window tkwin;            /* Token for window. */
213        Window parentWin;           /* Parent of new window. */
214        ClientData instanceData;    /* Scrollbar instance data. */
215    {
216        DWORD style;
217        Window window;
218        HWND parent;
219        TkWindow *winPtr;
220        WinScrollbar *scrollPtr = (WinScrollbar *)instanceData;
221    
222        parent = Tk_GetHWND(parentWin);
223    
224        if (scrollPtr->info.vertical) {
225            style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
226                | SBS_VERT | SBS_RIGHTALIGN;
227        } else {
228            style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
229                | SBS_HORZ | SBS_BOTTOMALIGN;
230        }
231    
232        scrollPtr->hwnd = CreateWindow("SCROLLBAR", NULL, style,
233                Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
234                parent, NULL, Tk_GetHINSTANCE(), NULL);
235    
236        /*
237         * Ensure new window is inserted into the stacking order at the correct
238         * place.
239         */
240    
241        SetWindowPos(scrollPtr->hwnd, HWND_TOP, 0, 0, 0, 0,
242                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
243    
244        for (winPtr = ((TkWindow*)tkwin)->nextPtr; winPtr != NULL;
245             winPtr = winPtr->nextPtr) {
246            if ((winPtr->window != None) && !(winPtr->flags & TK_TOP_LEVEL)) {
247                TkWinSetWindowPos(scrollPtr->hwnd, Tk_GetHWND(winPtr->window),
248                        Below);
249                break;
250            }
251        }
252    
253        scrollPtr->lastVertical = scrollPtr->info.vertical;
254        scrollPtr->oldProc = (WNDPROC)SetWindowLong(scrollPtr->hwnd, GWL_WNDPROC,
255                (DWORD) ScrollbarProc);
256        window = Tk_AttachHWND(tkwin, scrollPtr->hwnd);
257    
258        UpdateScrollbar(scrollPtr);
259        return window;
260    }
261    
262    /*
263     *--------------------------------------------------------------
264     *
265     * TkpDisplayScrollbar --
266     *
267     *      This procedure redraws the contents of a scrollbar window.
268     *      It is invoked as a do-when-idle handler, so it only runs
269     *      when there's nothing else for the application to do.
270     *
271     * Results:
272     *      None.
273     *
274     * Side effects:
275     *      Information appears on the screen.
276     *
277     *--------------------------------------------------------------
278     */
279    
280    void
281    TkpDisplayScrollbar(clientData)
282        ClientData clientData;      /* Information about window. */
283    {
284        WinScrollbar *scrollPtr = (WinScrollbar *) clientData;
285        Tk_Window tkwin = scrollPtr->info.tkwin;
286    
287        scrollPtr->info.flags &= ~REDRAW_PENDING;
288        if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
289            return;
290        }
291    
292        /*
293         * Destroy and recreate the scrollbar control if the orientation
294         * has changed.
295         */
296    
297        if (scrollPtr->lastVertical != scrollPtr->info.vertical) {
298            HWND hwnd = Tk_GetHWND(Tk_WindowId(tkwin));
299    
300            SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) scrollPtr->oldProc);
301            DestroyWindow(hwnd);
302    
303            CreateProc(tkwin, Tk_WindowId(Tk_Parent(tkwin)),
304                    (ClientData) scrollPtr);
305        } else {
306            UpdateScrollbar(scrollPtr);
307        }
308    }
309    
310    /*
311     *----------------------------------------------------------------------
312     *
313     * TkpDestroyScrollbar --
314     *
315     *      Free data structures associated with the scrollbar control.
316     *
317     * Results:
318     *      None.
319     *
320     * Side effects:
321     *      Restores the default control state.
322     *
323     *----------------------------------------------------------------------
324     */
325    
326    void
327    TkpDestroyScrollbar(scrollPtr)
328        TkScrollbar *scrollPtr;
329    {
330        WinScrollbar *winScrollPtr = (WinScrollbar *)scrollPtr;
331        HWND hwnd = winScrollPtr->hwnd;
332        if (hwnd) {
333            SetWindowLong(hwnd, GWL_WNDPROC, (DWORD) winScrollPtr->oldProc);
334            if (winScrollPtr->winFlags & IN_MODAL_LOOP) {
335                ((TkWindow *)scrollPtr->tkwin)->flags |= TK_DONT_DESTROY_WINDOW;
336                SetParent(hwnd, NULL);
337            }
338        }
339        winScrollPtr->winFlags |= ALREADY_DEAD;
340    }
341    
342    /*
343     *----------------------------------------------------------------------
344     *
345     * UpdateScrollbarMetrics --
346     *
347     *      This function retrieves the current system metrics for a
348     *      scrollbar.
349     *
350     * Results:
351     *      None.
352     *
353     * Side effects:
354     *      Updates the geometry cache info for all scrollbars.
355     *
356     *----------------------------------------------------------------------
357     */
358    
359    void
360    UpdateScrollbarMetrics()
361    {
362        Tk_ConfigSpec *specPtr;
363    
364        hArrowWidth = GetSystemMetrics(SM_CXHSCROLL);
365        hThumb = GetSystemMetrics(SM_CXHTHUMB);
366        vArrowWidth = GetSystemMetrics(SM_CXVSCROLL);
367        vArrowHeight = GetSystemMetrics(SM_CYVSCROLL);
368        vThumb = GetSystemMetrics(SM_CYVTHUMB);
369    
370        sprintf(defWidth, "%d", vArrowWidth);
371        for (specPtr = tkpScrollbarConfigSpecs; specPtr->type != TK_CONFIG_END;
372                specPtr++) {
373            if (specPtr->offset == Tk_Offset(TkScrollbar, width)) {
374                specPtr->defValue = defWidth;
375            }
376        }
377    }
378    
379    /*
380     *----------------------------------------------------------------------
381     *
382     * TkpComputeScrollbarGeometry --
383     *
384     *      After changes in a scrollbar's size or configuration, this
385     *      procedure recomputes various geometry information used in
386     *      displaying the scrollbar.
387     *
388     * Results:
389     *      None.
390     *
391     * Side effects:
392     *      The scrollbar will be displayed differently.
393     *
394     *----------------------------------------------------------------------
395     */
396    
397    void
398    TkpComputeScrollbarGeometry(scrollPtr)
399        register TkScrollbar *scrollPtr;    /* Scrollbar whose geometry may
400                                             * have changed. */
401    {
402        int fieldLength, minThumbSize;
403    
404        /*
405         * Windows doesn't use focus rings on scrollbars, but we still
406         * perform basic sanity checks to appease backwards compatibility.
407         */
408    
409        if (scrollPtr->highlightWidth < 0) {
410            scrollPtr->highlightWidth = 0;
411        }
412    
413        if (scrollPtr->vertical) {
414            scrollPtr->arrowLength = vArrowHeight;
415            fieldLength = Tk_Height(scrollPtr->tkwin);
416            minThumbSize = vThumb;
417        } else {
418            scrollPtr->arrowLength = hArrowWidth;
419            fieldLength = Tk_Width(scrollPtr->tkwin);
420            minThumbSize = hThumb;
421        }
422        fieldLength -= 2*scrollPtr->arrowLength;
423        if (fieldLength < 0) {
424            fieldLength = 0;
425        }
426        scrollPtr->sliderFirst = (int) ((double)fieldLength
427                * scrollPtr->firstFraction);
428        scrollPtr->sliderLast = (int) ((double)fieldLength
429                * scrollPtr->lastFraction);
430    
431        /*
432         * Adjust the slider so that some piece of it is always
433         * displayed in the scrollbar and so that it has at least
434         * a minimal width (so it can be grabbed with the mouse).
435         */
436    
437        if (scrollPtr->sliderFirst > fieldLength) {
438            scrollPtr->sliderFirst = fieldLength;
439        }
440        if (scrollPtr->sliderFirst < 0) {
441            scrollPtr->sliderFirst = 0;
442        }
443        if (scrollPtr->sliderLast < (scrollPtr->sliderFirst
444                + minThumbSize)) {
445            scrollPtr->sliderLast = scrollPtr->sliderFirst + minThumbSize;
446        }
447        if (scrollPtr->sliderLast > fieldLength) {
448            scrollPtr->sliderLast = fieldLength;
449        }
450        scrollPtr->sliderFirst += scrollPtr->arrowLength;
451        scrollPtr->sliderLast += scrollPtr->arrowLength;
452    
453        /*
454         * Register the desired geometry for the window (leave enough space
455         * for the two arrows plus a minimum-size slider, plus border around
456         * the whole window, if any).  Then arrange for the window to be
457         * redisplayed.
458         */
459    
460        if (scrollPtr->vertical) {
461            Tk_GeometryRequest(scrollPtr->tkwin,
462                    scrollPtr->width, 2*scrollPtr->arrowLength + minThumbSize);
463        } else {
464            Tk_GeometryRequest(scrollPtr->tkwin,
465                    2*scrollPtr->arrowLength + minThumbSize, scrollPtr->width);
466        }
467        Tk_SetInternalBorder(scrollPtr->tkwin, 0);
468    }
469    
470    /*
471     *----------------------------------------------------------------------
472     *
473     * ScrollbarProc --
474     *
475     *      This function is call by Windows whenever an event occurs on
476     *      a scrollbar control created by Tk.
477     *
478     * Results:
479     *      Standard Windows return value.
480     *
481     * Side effects:
482     *      May generate events.
483     *
484     *----------------------------------------------------------------------
485     */
486    
487    static LRESULT CALLBACK
488    ScrollbarProc(hwnd, message, wParam, lParam)
489        HWND hwnd;
490        UINT message;
491        WPARAM wParam;
492        LPARAM lParam;
493    {
494        LRESULT result;
495        POINT point;
496        WinScrollbar *scrollPtr;
497        Tk_Window tkwin = Tk_HWNDToWindow(hwnd);
498    
499        if (tkwin == NULL) {
500            panic("ScrollbarProc called on an invalid HWND");
501        }
502        scrollPtr = (WinScrollbar *)((TkWindow*)tkwin)->instanceData;
503    
504        switch(message) {
505            case WM_HSCROLL:
506            case WM_VSCROLL: {
507                Tcl_Interp *interp;
508                Tcl_DString cmdString;
509                int command = LOWORD(wParam);
510                int code;
511    
512                GetCursorPos(&point);
513                Tk_TranslateWinEvent(NULL, WM_MOUSEMOVE, 0,
514                        MAKELPARAM(point.x, point.y), &result);
515    
516                if (command == SB_ENDSCROLL) {
517                    return 0;
518                }
519    
520                /*
521                 * Bail out immediately if there isn't a command to invoke.
522                 */
523    
524                if (scrollPtr->info.commandSize == 0) {
525                    Tcl_ServiceAll();
526                    return 0;
527                }
528                    
529                Tcl_DStringInit(&cmdString);
530                Tcl_DStringAppend(&cmdString, scrollPtr->info.command,
531                        scrollPtr->info.commandSize);
532                    
533                if (command == SB_LINELEFT || command == SB_LINERIGHT) {
534                    Tcl_DStringAppendElement(&cmdString, "scroll");
535                    Tcl_DStringAppendElement(&cmdString,
536                            (command == SB_LINELEFT ) ? "-1" : "1");
537                    Tcl_DStringAppendElement(&cmdString, "units");
538                } else if (command == SB_PAGELEFT || command == SB_PAGERIGHT) {
539                    Tcl_DStringAppendElement(&cmdString, "scroll");
540                    Tcl_DStringAppendElement(&cmdString,
541                            (command == SB_PAGELEFT ) ? "-1" : "1");
542                    Tcl_DStringAppendElement(&cmdString, "pages");
543                } else {
544                    char valueString[TCL_DOUBLE_SPACE];
545                    double pos = 0.0;
546                    switch (command) {
547                        case SB_THUMBPOSITION:
548                            pos = ((double)HIWORD(wParam)) / MAX_SCROLL;
549                            break;
550    
551                        case SB_THUMBTRACK:
552                            pos = ((double)HIWORD(wParam)) / MAX_SCROLL;
553                            break;
554    
555                        case SB_TOP:
556                            pos = 0.0;
557                            break;
558    
559                        case SB_BOTTOM:
560                            pos = 1.0;
561                            break;
562                    }
563                    sprintf(valueString, "%g", pos);
564                    Tcl_DStringAppendElement(&cmdString, "moveto");
565                    Tcl_DStringAppendElement(&cmdString, valueString);
566                }
567    
568                interp = scrollPtr->info.interp;
569                code = Tcl_GlobalEval(interp, cmdString.string);
570                if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) {
571                    Tcl_AddErrorInfo(interp, "\n    (scrollbar command)");
572                    Tcl_BackgroundError(interp);
573                }          
574                Tcl_DStringFree(&cmdString);                
575    
576                Tcl_ServiceAll();
577                return 0;
578            }
579    
580            default:
581                if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
582                    return result;
583                }
584        }
585        return CallWindowProc(scrollPtr->oldProc, hwnd, message, wParam, lParam);
586    }
587    
588    /*
589     *----------------------------------------------------------------------
590     *
591     * TkpConfigureScrollbar --
592     *
593     *      This procedure is called after the generic code has finished
594     *      processing configuration options, in order to configure
595     *      platform specific options.
596     *
597     * Results:
598     *      None.
599     *
600     * Side effects:
601     *      None.
602     *
603     *----------------------------------------------------------------------
604     */
605    
606    void
607    TkpConfigureScrollbar(scrollPtr)
608        register TkScrollbar *scrollPtr;    /* Information about widget;  may or
609                                             * may not already have values for
610                                             * some fields. */
611    {
612    }
613    
614    /*
615     *--------------------------------------------------------------
616     *
617     * ScrollbarBindProc --
618     *
619     *      This procedure is invoked when the default <ButtonPress>
620     *      binding on the Scrollbar bind tag fires.
621     *
622     * Results:
623     *      None.
624     *
625     * Side effects:
626     *      The event enters a modal loop.
627     *
628     *--------------------------------------------------------------
629     */
630    
631    static int
632    ScrollbarBindProc(clientData, interp, eventPtr, tkwin, keySym)
633        ClientData clientData;
634        Tcl_Interp *interp;
635        XEvent *eventPtr;
636        Tk_Window tkwin;
637        KeySym keySym;
638    {
639        TkWindow *winPtr = (TkWindow*)tkwin;
640        if (eventPtr->type == ButtonPress) {
641            winPtr->flags |= TK_DEFER_MODAL;
642        }
643        return TCL_OK;
644    }
645    
646    /*
647     *----------------------------------------------------------------------
648     *
649     * ModalLoopProc --
650     *
651     *      This function is invoked at the end of the event processing
652     *      whenever the ScrollbarBindProc has been invoked for a ButtonPress
653     *      event.
654     *
655     * Results:
656     *      None.
657     *
658     * Side effects:
659     *      Enters a modal loop.
660     *
661     *----------------------------------------------------------------------
662     */
663    
664    static void
665    ModalLoopProc(tkwin, eventPtr)
666        Tk_Window tkwin;
667        XEvent *eventPtr;
668    {
669        TkWindow *winPtr = (TkWindow*)tkwin;
670        WinScrollbar *scrollPtr = (WinScrollbar *) winPtr->instanceData;
671        int oldMode;
672    
673        if (scrollPtr->hwnd) {
674            Tcl_Preserve((ClientData)scrollPtr);
675            scrollPtr->winFlags |= IN_MODAL_LOOP;
676            oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
677            TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr);
678            (void) Tcl_SetServiceMode(oldMode);
679            scrollPtr->winFlags &= ~IN_MODAL_LOOP;
680            if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) {
681                DestroyWindow(scrollPtr->hwnd);
682            }
683            Tcl_Release((ClientData)scrollPtr);
684        }
685    }
686    
687    /*
688     *--------------------------------------------------------------
689     *
690     * TkpScrollbarPosition --
691     *
692     *      Determine the scrollbar element corresponding to a
693     *      given position.
694     *
695     * Results:
696     *      One of TOP_ARROW, TOP_GAP, etc., indicating which element
697     *      of the scrollbar covers the position given by (x, y).  If
698     *      (x,y) is outside the scrollbar entirely, then OUTSIDE is
699     *      returned.
700     *
701     * Side effects:
702     *      None.
703     *
704     *--------------------------------------------------------------
705     */
706    
707    int
708    TkpScrollbarPosition(scrollPtr, x, y)
709        register TkScrollbar *scrollPtr;    /* Scrollbar widget record. */
710        int x, y;                           /* Coordinates within scrollPtr's
711                                             * window. */
712    {
713        int length, width, tmp;
714    
715        if (scrollPtr->vertical) {
716            length = Tk_Height(scrollPtr->tkwin);
717            width = Tk_Width(scrollPtr->tkwin);
718        } else {
719            tmp = x;
720            x = y;
721            y = tmp;
722            length = Tk_Width(scrollPtr->tkwin);
723            width = Tk_Height(scrollPtr->tkwin);
724        }
725    
726        if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))
727                || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {
728            return OUTSIDE;
729        }
730    
731        /*
732         * All of the calculations in this procedure mirror those in
733         * TkpDisplayScrollbar.  Be sure to keep the two consistent.
734         */
735    
736        if (y < (scrollPtr->inset + scrollPtr->arrowLength)) {
737            return TOP_ARROW;
738        }
739        if (y < scrollPtr->sliderFirst) {
740            return TOP_GAP;
741        }
742        if (y < scrollPtr->sliderLast) {
743            return SLIDER;
744        }
745        if (y >= (length - (scrollPtr->arrowLength + scrollPtr->inset))) {
746            return BOTTOM_ARROW;
747        }
748        return BOTTOM_GAP;
749    }
750    
751    /* End of tkwinscrlbr.c */

Legend:
Removed from v.29  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25