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

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

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

to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkwinx.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/tkwinx.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
 /* $Header: /IjuScripter, IjuConsole/Source/Tk Base/tkWinX.c 1     1/02/01 3:18a Dtashley $ */  
   
 /*  
  * tkWinX.c --  
  *  
  *      This file contains Windows emulation procedures for X routines.  
  *  
  * Copyright (c) 1995-1996 Sun Microsystems, Inc.  
  * Copyright (c) 1994 Software Research Associates, 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: tkWinX.c,v 1.10 2000/04/19 01:06:51 ericm Exp $  
  */  
   
 #include "tkWinInt.h"  
   
 /*  
  * The zmouse.h file includes the definition for WM_MOUSEWHEEL.  
  */  
   
 #include <zmouse.h>  
   
 /*  
  * Declarations of static variables used in this file.  
  */  
   
 static char winScreenName[] = ":0"; /* Default name of windows display. */  
 static HINSTANCE tkInstance;        /* Application instance handle. */  
 static int childClassInitialized;   /* Registered child class? */  
 static WNDCLASS childClass;         /* Window class for child windows. */  
 static int tkPlatformId;            /* version of Windows platform */  
   
 TCL_DECLARE_MUTEX(winXMutex)  
   
 /*  
  * Thread local storage.  Notice that now each thread must have its  
  * own TkDisplay structure, since this structure contains most of  
  * the thread-specific date for threads.  
  */  
 typedef struct ThreadSpecificData {  
     TkDisplay *winDisplay;       /* TkDisplay structure that *  
                                   *  represents Windows screen. */  
     int updatingClipboard;      /* If 1, we are updating the clipboard */  
 } ThreadSpecificData;  
 static Tcl_ThreadDataKey dataKey;  
   
 /*  
  * Forward declarations of procedures used in this file.  
  */  
   
 static void             GenerateXEvent _ANSI_ARGS_((HWND hwnd, UINT message,  
                             WPARAM wParam, LPARAM lParam));  
 static unsigned int     GetState _ANSI_ARGS_((UINT message, WPARAM wParam,  
                             LPARAM lParam));  
 static void             GetTranslatedKey _ANSI_ARGS_((XKeyEvent *xkey));  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkGetServerInfo --  
  *  
  *      Given a window, this procedure returns information about  
  *      the window server for that window.  This procedure provides  
  *      the guts of the "winfo server" command.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkGetServerInfo(interp, tkwin)  
     Tcl_Interp *interp;         /* The server information is returned in  
                                  * this interpreter's result. */  
     Tk_Window tkwin;            /* Token for window;  this selects a  
                                  * particular display and server. */  
 {  
     char buffer[60];  
     OSVERSIONINFO os;  
   
     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
     GetVersionEx(&os);  
     sprintf(buffer, "Windows %d.%d %d Win32", os.dwMajorVersion,  
             os.dwMinorVersion, os.dwBuildNumber);  
     Tcl_SetResult(interp, buffer, TCL_VOLATILE);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_GetHINSTANCE --  
  *  
  *      Retrieves the global instance handle used by the Tk library.  
  *  
  * Results:  
  *      Returns the global instance handle.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 HINSTANCE  
 Tk_GetHINSTANCE()  
 {  
     return tkInstance;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinXInit --  
  *  
  *      Initialize Xlib emulation layer.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Sets up various data structures.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkWinXInit(hInstance)  
     HINSTANCE hInstance;  
 {  
     OSVERSIONINFO os;  
   
     if (childClassInitialized != 0) {  
         return;  
     }  
     childClassInitialized = 1;  
   
     tkInstance = hInstance;  
   
     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
     GetVersionEx(&os);  
     tkPlatformId = os.dwPlatformId;  
   
     /*  
      * When threads are enabled, we cannot use CLASSDC because  
      * threads will then write into the same device context.  
      *  
      * This is a hack; we should add a subsystem that manages  
      * device context on a per-thread basis.  See also tkWinWm.c,  
      * which also initializes a WNDCLASS structure.  
      */  
   
 #ifdef TCL_THREADS  
     childClass.style = CS_HREDRAW | CS_VREDRAW;  
 #else  
     childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;  
 #endif  
   
     childClass.cbClsExtra = 0;  
     childClass.cbWndExtra = 0;  
     childClass.hInstance = hInstance;  
     childClass.hbrBackground = NULL;  
     childClass.lpszMenuName = NULL;  
   
     /*  
      * Register the Child window class.  
      */  
   
     childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME;  
     childClass.lpfnWndProc = TkWinChildProc;  
     childClass.hIcon = NULL;  
     childClass.hCursor = NULL;  
   
     if (!RegisterClass(&childClass)) {  
         panic("Unable to register TkChild class");  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinXCleanup --  
  *  
  *      Removes the registered classes for Tk.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Removes window classes from the system.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkWinXCleanup(hInstance)  
     HINSTANCE hInstance;  
 {  
     /*  
      * Clean up our own class.  
      */  
       
     if (childClassInitialized) {  
         childClassInitialized = 0;  
         UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);  
     }  
   
     /*  
      * And let the window manager clean up its own class(es).  
      */  
       
     TkWinWmCleanup(hInstance);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinGetPlatformId --  
  *  
  *      Determines whether running under NT, 95, or Win32s, to allow  
  *      runtime conditional code.  
  *  
  * Results:  
  *      The return value is one of:  
  *          VER_PLATFORM_WIN32s         Win32s on Windows 3.1.  
  *          VER_PLATFORM_WIN32_WINDOWS  Win32 on Windows 95.  
  *          VER_PLATFORM_WIN32_NT       Win32 on Windows NT  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int              
 TkWinGetPlatformId()  
 {  
     return tkPlatformId;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkGetDefaultScreenName --  
  *  
  *      Returns the name of the screen that Tk should use during  
  *      initialization.  
  *  
  * Results:  
  *      Returns a statically allocated string.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 char *  
 TkGetDefaultScreenName(interp, screenName)  
     Tcl_Interp *interp;         /* Not used. */  
     char *screenName;           /* If NULL, use default string. */  
 {  
     if ((screenName == NULL) || (screenName[0] == '\0')) {  
         screenName = winScreenName;  
     }  
     return screenName;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpOpenDisplay --  
  *  
  *      Create the Display structure and fill it with device  
  *      specific information.  
  *  
  * Results:  
  *      Returns a TkDisplay structure on success or NULL on failure.  
  *  
  * Side effects:  
  *      Allocates a new TkDisplay structure.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 TkDisplay *  
 TkpOpenDisplay(display_name)  
     char *display_name;  
 {  
     Screen *screen;  
     HDC dc;  
     TkWinDrawable *twdPtr;  
     Display *display;  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     if (tsdPtr->winDisplay != NULL) {  
         if (strcmp(tsdPtr->winDisplay->display->display_name, display_name)  
                 == 0) {  
             return tsdPtr->winDisplay;  
         } else {  
             return NULL;  
         }  
     }  
   
     display = (Display *) ckalloc(sizeof(Display));  
     display->display_name = (char *) ckalloc(strlen(display_name)+1);  
     strcpy(display->display_name, display_name);  
   
     display->cursor_font = 1;  
     display->nscreens = 1;  
     display->request = 1;  
     display->qlen = 0;  
   
     screen = (Screen *) ckalloc(sizeof(Screen));  
     screen->display = display;  
   
     dc = GetDC(NULL);  
     screen->width = GetDeviceCaps(dc, HORZRES);  
     screen->height = GetDeviceCaps(dc, VERTRES);  
     screen->mwidth = MulDiv(screen->width, 254,  
             GetDeviceCaps(dc, LOGPIXELSX) * 10);  
     screen->mheight = MulDiv(screen->height, 254,  
             GetDeviceCaps(dc, LOGPIXELSY) * 10);  
       
     /*  
      * Set up the root window.  
      */  
   
     twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable));  
     if (twdPtr == NULL) {  
         return None;  
     }  
     twdPtr->type = TWD_WINDOW;  
     twdPtr->window.winPtr = NULL;  
     twdPtr->window.handle = NULL;  
     screen->root = (Window)twdPtr;  
   
     /*  
      * On windows, when creating a color bitmap, need two pieces of  
      * information: the number of color planes and the number of  
      * pixels per plane.  Need to remember both quantities so that  
      * when constructing an HBITMAP for offscreen rendering, we can  
      * specify the correct value for the number of planes.  Otherwise  
      * the HBITMAP won't be compatible with the HWND and we'll just  
      * get blank spots copied onto the screen.  
      */  
   
     screen->ext_data = (XExtData *) GetDeviceCaps(dc, PLANES);  
     screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * (int) screen->ext_data;  
   
     screen->root_visual = (Visual *) ckalloc(sizeof(Visual));  
     screen->root_visual->visualid = 0;  
     if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {  
         screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE);  
         screen->root_visual->class = PseudoColor;  
         screen->root_visual->red_mask = 0x0;  
         screen->root_visual->green_mask = 0x0;  
         screen->root_visual->blue_mask = 0x0;  
     } else {  
         if (screen->root_depth == 4) {  
             screen->root_visual->class = StaticColor;  
             screen->root_visual->map_entries = 16;  
         } else if (screen->root_depth == 8) {  
             screen->root_visual->class = StaticColor;  
             screen->root_visual->map_entries = 256;  
         } else if (screen->root_depth == 12) {  
             screen->root_visual->class = TrueColor;  
             screen->root_visual->map_entries = 32;  
             screen->root_visual->red_mask = 0xf0;  
             screen->root_visual->green_mask = 0xf000;  
             screen->root_visual->blue_mask = 0xf00000;  
         } else if (screen->root_depth == 16) {  
             screen->root_visual->class = TrueColor;  
             screen->root_visual->map_entries = 64;  
             screen->root_visual->red_mask = 0xf8;  
             screen->root_visual->green_mask = 0xfc00;  
             screen->root_visual->blue_mask = 0xf80000;  
         } else if (screen->root_depth >= 24) {  
             screen->root_visual->class = TrueColor;  
             screen->root_visual->map_entries = 256;  
             screen->root_visual->red_mask = 0xff;  
             screen->root_visual->green_mask = 0xff00;  
             screen->root_visual->blue_mask = 0xff0000;  
         }  
     }  
     screen->root_visual->bits_per_rgb = screen->root_depth;  
     ReleaseDC(NULL, dc);  
   
     /*  
      * Note that these pixel values are not palette relative.  
      */  
   
     screen->white_pixel = RGB(255, 255, 255);  
     screen->black_pixel = RGB(0, 0, 0);  
   
     display->screens            = screen;  
     display->nscreens           = 1;  
     display->default_screen     = 0;  
     screen->cmap = XCreateColormap(display, None, screen->root_visual,  
             AllocNone);  
     tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));  
     tsdPtr->winDisplay->display = display;  
     tsdPtr->updatingClipboard = FALSE;  
     return tsdPtr->winDisplay;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpCloseDisplay --  
  *  
  *      Closes and deallocates a Display structure created with the  
  *      TkpOpenDisplay function.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Frees up memory.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkpCloseDisplay(dispPtr)  
     TkDisplay *dispPtr;  
 {  
     Display *display = dispPtr->display;  
     HWND hwnd;  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     if (dispPtr != tsdPtr->winDisplay) {  
         panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");  
         return;  
     }  
   
     /*  
      * Force the clipboard to be rendered if we are the clipboard owner.  
      */  
       
     if (dispPtr->clipWindow) {  
         hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));  
         if (GetClipboardOwner() == hwnd) {  
             OpenClipboard(hwnd);  
             EmptyClipboard();  
             TkWinClipboardRender(dispPtr, CF_TEXT);  
             CloseClipboard();  
         }  
     }  
   
     tsdPtr->winDisplay = NULL;  
   
     if (display->display_name != (char *) NULL) {  
         ckfree(display->display_name);  
     }  
     if (display->screens != (Screen *) NULL) {  
         if (display->screens->root_visual != NULL) {  
             ckfree((char *) display->screens->root_visual);  
         }  
         if (display->screens->root != None) {  
             ckfree((char *) display->screens->root);  
         }  
         if (display->screens->cmap != None) {  
             XFreeColormap(display, display->screens->cmap);  
         }  
         ckfree((char *) display->screens);  
     }  
     ckfree((char *) display);  
     ckfree((char *) dispPtr);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * XBell --  
  *  
  *      Generate a beep.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Plays a sounds out the system speakers.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 XBell(display, percent)  
     Display* display;  
     int percent;  
 {  
     MessageBeep(MB_OK);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinChildProc --  
  *  
  *      Callback from Windows whenever an event occurs on a child  
  *      window.  
  *  
  * Results:  
  *      Standard Windows return value.  
  *  
  * Side effects:  
  *      May process events off the Tk event queue.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 LRESULT CALLBACK  
 TkWinChildProc(hwnd, message, wParam, lParam)  
     HWND hwnd;  
     UINT message;  
     WPARAM wParam;  
     LPARAM lParam;  
 {  
     LRESULT result;  
   
     switch (message) {  
         case WM_SETCURSOR:  
             /*  
              * Short circuit the WM_SETCURSOR message since we set  
              * the cursor elsewhere.  
              */  
   
             result = TRUE;  
             break;  
   
         case WM_CREATE:  
         case WM_ERASEBKGND:  
             result = 0;  
             break;  
   
         case WM_PAINT:  
             GenerateXEvent(hwnd, message, wParam, lParam);  
             result = DefWindowProc(hwnd, message, wParam, lParam);  
             break;  
   
         case TK_CLAIMFOCUS:  
         case TK_GEOMETRYREQ:  
         case TK_ATTACHWINDOW:  
         case TK_DETACHWINDOW:  
             result =  TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);  
             break;  
   
         default:  
             if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam,  
                     &result)) {  
                 result = DefWindowProc(hwnd, message, wParam, lParam);  
             }  
             break;  
     }  
   
     /*  
      * Handle any newly queued events before returning control to Windows.  
      */  
   
     Tcl_ServiceAll();  
     return result;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_TranslateWinEvent --  
  *  
  *      This function is called by widget window procedures to handle  
  *      the translation from Win32 events to Tk events.  
  *  
  * Results:  
  *      Returns 1 if the event was handled, else 0.  
  *  
  * Side effects:  
  *      Depends on the event.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)  
     HWND hwnd;  
     UINT message;  
     WPARAM wParam;  
     LPARAM lParam;  
     LRESULT *resultPtr;  
 {  
     *resultPtr = 0;  
     switch (message) {  
         case WM_RENDERFORMAT: {  
             TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);  
             if (winPtr) {  
                 TkWinClipboardRender(winPtr->dispPtr, wParam);  
             }  
             return 1;  
         }  
   
         case WM_COMMAND:  
         case WM_NOTIFY:  
         case WM_VSCROLL:  
         case WM_HSCROLL: {  
             /*  
              * Reflect these messages back to the sender so that they  
              * can be handled by the window proc for the control.  Note  
              * that we need to be careful not to reflect a message that  
              * is targeted to this window, or we will loop.  
              */  
   
             HWND target = (message == WM_NOTIFY)  
                 ? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;  
             if (target && target != hwnd) {  
                 *resultPtr = SendMessage(target, message, wParam, lParam);  
                 return 1;  
             }  
             break;  
         }  
   
         case WM_LBUTTONDOWN:  
         case WM_LBUTTONDBLCLK:  
         case WM_MBUTTONDOWN:  
         case WM_MBUTTONDBLCLK:  
         case WM_RBUTTONDOWN:  
         case WM_RBUTTONDBLCLK:  
         case WM_LBUTTONUP:  
         case WM_MBUTTONUP:  
         case WM_RBUTTONUP:  
         case WM_MOUSEMOVE:  
             Tk_PointerEvent(hwnd, (short) LOWORD(lParam),  
                     (short) HIWORD(lParam));  
             return 1;  
   
         case WM_CLOSE:  
         case WM_SETFOCUS:  
         case WM_KILLFOCUS:  
         case WM_DESTROYCLIPBOARD:  
         case WM_CHAR:  
         case WM_SYSKEYDOWN:  
         case WM_SYSKEYUP:  
         case WM_KEYDOWN:  
         case WM_KEYUP:  
         case WM_MOUSEWHEEL:  
             GenerateXEvent(hwnd, message, wParam, lParam);  
             return 1;  
         case WM_MENUCHAR:  
             GenerateXEvent(hwnd, message, wParam, lParam);  
             /* MNC_CLOSE is the only one that looks right.  This is a hack. */  
             *resultPtr = MAKELONG (0, MNC_CLOSE);  
             return 1;  
     }  
     return 0;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * GenerateXEvent --  
  *  
  *      This routine generates an X event from the corresponding  
  *      Windows event.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Queues one or more X events.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 GenerateXEvent(hwnd, message, wParam, lParam)  
     HWND hwnd;  
     UINT message;  
     WPARAM wParam;  
     LPARAM lParam;  
 {  
     XEvent event;  
     TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     if (!winPtr || winPtr->window == None) {  
         return;  
     }  
   
     event.xany.serial = winPtr->display->request++;  
     event.xany.send_event = False;  
     event.xany.display = winPtr->display;  
     event.xany.window = winPtr->window;  
   
     switch (message) {  
         case WM_PAINT: {  
             PAINTSTRUCT ps;  
   
             event.type = Expose;  
             BeginPaint(hwnd, &ps);  
             event.xexpose.x = ps.rcPaint.left;  
             event.xexpose.y = ps.rcPaint.top;  
             event.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;  
             event.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;  
             EndPaint(hwnd, &ps);  
             event.xexpose.count = 0;  
             break;  
         }  
   
         case WM_CLOSE:  
             event.type = ClientMessage;  
             event.xclient.message_type =  
                 Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");  
             event.xclient.format = 32;  
             event.xclient.data.l[0] =  
                 Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");  
             break;  
   
         case WM_SETFOCUS:  
         case WM_KILLFOCUS: {  
             TkWindow *otherWinPtr = (TkWindow *)Tk_HWNDToWindow((HWND) wParam);  
               
             /*  
              * Compare toplevel windows to avoid reporting focus  
              * changes within the same toplevel.  
              */  
   
             while (!(winPtr->flags & TK_TOP_LEVEL)) {  
                 winPtr = winPtr->parentPtr;  
                 if (winPtr == NULL) {  
                     return;  
                 }  
             }  
             while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {  
                 otherWinPtr = otherWinPtr->parentPtr;  
             }  
             if (otherWinPtr == winPtr) {  
                 return;  
             }  
   
             event.xany.window = winPtr->window;  
             event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;  
             event.xfocus.mode = NotifyNormal;  
             event.xfocus.detail = NotifyNonlinear;  
             break;  
         }  
   
         case WM_DESTROYCLIPBOARD:  
             if (tsdPtr->updatingClipboard == TRUE) {  
                 /*  
                  * We want to avoid this event if we are the ones that caused  
                  * this event.  
                  */  
                 return;  
             }  
             event.type = SelectionClear;  
             event.xselectionclear.selection =  
                 Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");  
             event.xselectionclear.time = TkpGetMS();  
             break;  
               
         case WM_MOUSEWHEEL:  
             /*  
              * The mouse wheel event is closer to a key event than a  
              * mouse event in that the message is sent to the window  
              * that has focus.  
              */  
               
         case WM_CHAR:  
         case WM_SYSKEYDOWN:  
         case WM_SYSKEYUP:  
         case WM_KEYDOWN:  
         case WM_KEYUP: {  
             unsigned int state = GetState(message, wParam, lParam);  
             Time time = TkpGetMS();  
             POINT clientPoint;  
             POINTS rootPoint;   /* Note: POINT and POINTS are different */  
             DWORD msgPos;  
   
             /*  
              * Compute the screen and window coordinates of the event.  
              */  
               
             msgPos = GetMessagePos();  
             rootPoint = MAKEPOINTS(msgPos);  
             clientPoint.x = rootPoint.x;  
             clientPoint.y = rootPoint.y;  
             ScreenToClient(hwnd, &clientPoint);  
   
             /*  
              * Set up the common event fields.  
              */  
   
             event.xbutton.root = RootWindow(winPtr->display,  
                     winPtr->screenNum);  
             event.xbutton.subwindow = None;  
             event.xbutton.x = clientPoint.x;  
             event.xbutton.y = clientPoint.y;  
             event.xbutton.x_root = rootPoint.x;  
             event.xbutton.y_root = rootPoint.y;  
             event.xbutton.state = state;  
             event.xbutton.time = time;  
             event.xbutton.same_screen = True;  
   
             /*  
              * Now set up event specific fields.  
              */  
   
             switch (message) {  
                 case WM_MOUSEWHEEL:  
                     /*  
                      * We have invented a new X event type to handle  
                      * this event.  It still uses the KeyPress struct.  
                      * However, the keycode field has been overloaded  
                      * to hold the zDelta of the wheel.  
                      */  
                       
                     event.type = MouseWheelEvent;  
                     event.xany.send_event = -1;  
                     event.xkey.keycode = (short) HIWORD(wParam);  
                     break;  
                 case WM_SYSKEYDOWN:  
                 case WM_KEYDOWN:  
                     /*  
                      * Check for translated characters in the event queue.  
                      * Setting xany.send_event to -1 indicates to the  
                      * Windows implementation of XLookupString that this  
                      * event was generated by windows and that the Windows  
                      * extension xkey.trans_chars is filled with the  
                      * characters that came from the TranslateMessage  
                      * call.  If it is not -1, xkey.keycode is the  
                      * virtual key being sent programmatically by generic  
                      * code.  
                      */  
   
                     event.type = KeyPress;  
                     event.xany.send_event = -1;  
                     event.xkey.keycode = wParam;  
                     GetTranslatedKey(&event.xkey);  
                     break;  
   
                 case WM_SYSKEYUP:  
                 case WM_KEYUP:  
                     /*  
                      * We don't check for translated characters on keyup  
                      * because Tk won't know what to do with them.  Instead, we  
                      * wait for the WM_CHAR messages which will follow.  
                      */  
                     event.type = KeyRelease;  
                     event.xkey.keycode = wParam;  
                     event.xkey.nbytes = 0;  
                     break;  
   
                 case WM_CHAR:  
                     /*  
                      * Synthesize both a KeyPress and a KeyRelease.  
                      * Strings generated by Input Method Editor are handled  
                      * in the following manner:  
                      * 1. A series of WM_KEYDOWN & WM_KEYUP messages that  
                      *    cause GetTranslatedKey() to be called and return  
                      *    immediately because the WM_KEYDOWNs have no  
                      *    associated WM_CHAR messages -- the IME window is  
                      *    accumulating the characters and translating them  
                      *    itself.  In the "bind" command, you get an event  
                      *    with a mystery keysym and %A == "" for each  
                      *    WM_KEYDOWN that actually was meant for the IME.  
                      * 2. A WM_KEYDOWN corresponding to the "confirm typing"  
                      *    character.  This causes GetTranslatedKey() to be  
                      *    called.  
                      * 3. A WM_IME_NOTIFY message saying that the IME is  
                      *    done.  A side effect of this message is that  
                      *    GetTranslatedKey() thinks this means that there  
                      *    are no WM_CHAR messages and returns immediately.  
                      *    In the "bind" command, you get an another event  
                      *    with a mystery keysym and %A == "".  
                      * 4. A sequence of WM_CHAR messages that correspond to  
                      *    the characters in the IME window.  A bunch of  
                      *    simulated KeyPress/KeyRelease events will be  
                      *    generated, one for each character.  Adjacent  
                      *    WM_CHAR messages may actually specify the high  
                      *    and low bytes of a multi-byte character -- in that  
                      *    case the two WM_CHAR messages will be combined into  
                      *    one event.  It is the event-consumer's  
                      *    responsibility to convert the string returned from  
                      *    XLookupString from system encoding to UTF-8.  
                      * 5. And finally we get the WM_KEYUP for the "confirm  
                      *    typing" character.  
                      */  
   
                     event.type = KeyPress;  
                     event.xany.send_event = -1;  
                     event.xkey.keycode = 0;  
                     event.xkey.nbytes = 1;  
                     event.xkey.trans_chars[0] = (char) wParam;  
   
                     if (IsDBCSLeadByte((BYTE) wParam)) {  
                         MSG msg;  
   
                         if ((PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0)  
                                 && (msg.message == WM_CHAR)) {  
                             GetMessage(&msg, NULL, 0, 0);  
                             event.xkey.nbytes = 2;  
                             event.xkey.trans_chars[1] = (char) msg.wParam;  
                         }  
                     }  
                     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);  
                     event.type = KeyRelease;  
                     break;  
             }  
             break;  
         }  
   
         default:  
             return;  
     }  
     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * GetState --  
  *  
  *      This function constructs a state mask for the mouse buttons  
  *      and modifier keys as they were before the event occured.  
  *  
  * Results:  
  *      Returns a composite value of all the modifier and button state  
  *      flags that were set at the time the event occurred.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static unsigned int  
 GetState(message, wParam, lParam)  
     UINT message;               /* Win32 message type */  
     WPARAM wParam;              /* wParam of message, used if key message */  
     LPARAM lParam;              /* lParam of message, used if key message */  
 {  
     int mask;  
     int prevState;              /* 1 if key was previously down */  
     unsigned int state = TkWinGetModifierState();  
   
     /*  
      * If the event is a key press or release, we check for modifier  
      * keys so we can report the state of the world before the event.  
      */  
   
     if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN  
             || message == WM_SYSKEYUP || message == WM_KEYUP) {  
         mask = 0;  
         prevState = HIWORD(lParam) & KF_REPEAT;  
         switch(wParam) {  
             case VK_SHIFT:  
                 mask = ShiftMask;  
                 break;  
             case VK_CONTROL:  
                 mask = ControlMask;  
                 break;  
             case VK_MENU:  
                 mask = ALT_MASK;  
                 break;  
             case VK_CAPITAL:  
                 if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {  
                     mask = LockMask;  
                     prevState = ((state & mask) ^ prevState) ? 0 : 1;  
                 }  
                 break;  
             case VK_NUMLOCK:  
                 if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {  
                     mask = Mod1Mask;  
                     prevState = ((state & mask) ^ prevState) ? 0 : 1;  
                 }  
                 break;  
             case VK_SCROLL:  
                 if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {  
                     mask = Mod3Mask;  
                     prevState = ((state & mask) ^ prevState) ? 0 : 1;  
                 }  
                 break;  
         }  
         if (prevState) {  
             state |= mask;  
         } else {  
             state &= ~mask;  
         }  
     }  
     return state;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * GetTranslatedKey --  
  *  
  *      Retrieves WM_CHAR messages that are placed on the system queue  
  *      by the TranslateMessage system call and places them in the  
  *      given KeyPress event.  
  *  
  * Results:  
  *      Sets the trans_chars and nbytes member of the key event.  
  *  
  * Side effects:  
  *      Removes any WM_CHAR messages waiting on the top of the system  
  *      event queue.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 GetTranslatedKey(xkey)  
     XKeyEvent *xkey;  
 {  
     MSG msg;  
     char buf[XMaxTransChars];  
       
     xkey->nbytes = 0;  
   
     while ((xkey->nbytes < XMaxTransChars)  
             && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {  
         if ((msg.message == WM_CHAR) || (msg.message == WM_SYSCHAR)) {  
             GetMessage(&msg, NULL, 0, 0);  
   
             /*  
              * If this is a normal character message, we may need to strip  
              * off the Alt modifier (e.g. Alt-digits).  Note that we don't  
              * want to do this for system messages, because those were  
              * presumably generated as an Alt-char sequence (e.g. accelerator  
              * keys).  
              */  
   
             if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {  
                 xkey->state = 0;  
             }  
             buf[xkey->nbytes] = (char) msg.wParam;  
             xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;  
             xkey->nbytes++;  
         } else {  
             break;  
         }  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_FreeXId --  
  *  
  *      This inteface is not needed under Windows.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 Tk_FreeXId(display, xid)  
     Display *display;  
     XID xid;  
 {  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinResendEvent --  
  *  
  *      This function converts an X event into a Windows event and  
  *      invokes the specified windo procedure.  
  *  
  * Results:  
  *      A standard Windows result.  
  *  
  * Side effects:  
  *      Invokes the window procedure  
  *  
  *----------------------------------------------------------------------  
  */  
   
 LRESULT  
 TkWinResendEvent(wndproc, hwnd, eventPtr)  
     WNDPROC wndproc;  
     HWND hwnd;  
     XEvent *eventPtr;  
 {  
     UINT msg;  
     WPARAM wparam;  
     LPARAM lparam;  
   
     if (eventPtr->type == ButtonPress) {  
         switch (eventPtr->xbutton.button) {  
             case Button1:  
                 msg = WM_LBUTTONDOWN;  
                 wparam = MK_LBUTTON;  
                 break;  
             case Button2:  
                 msg = WM_MBUTTONDOWN;  
                 wparam = MK_MBUTTON;  
                 break;  
             case Button3:  
                 msg = WM_RBUTTONDOWN;  
                 wparam = MK_RBUTTON;  
                 break;  
             default:  
                 return 0;  
         }  
         if (eventPtr->xbutton.state & Button1Mask) {  
             wparam |= MK_LBUTTON;  
         }  
         if (eventPtr->xbutton.state & Button2Mask) {  
             wparam |= MK_MBUTTON;  
         }  
         if (eventPtr->xbutton.state & Button3Mask) {  
             wparam |= MK_RBUTTON;  
         }  
         if (eventPtr->xbutton.state & ShiftMask) {  
             wparam |= MK_SHIFT;  
         }  
         if (eventPtr->xbutton.state & ControlMask) {  
             wparam |= MK_CONTROL;  
         }  
         lparam = MAKELPARAM((short) eventPtr->xbutton.x,  
                 (short) eventPtr->xbutton.y);  
     } else {  
         return 0;  
     }  
     return CallWindowProc(wndproc, hwnd, msg, wparam, lparam);  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkpGetMS --  
  *  
  *      Return a relative time in milliseconds.  It doesn't matter  
  *      when the epoch was.  
  *  
  * Results:  
  *      Number of milliseconds.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 unsigned long  
 TkpGetMS()  
 {  
     return GetTickCount();  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkWinUpdatingClipboard --  
  *  
  *  
  * Results:  
  *      Number of milliseconds.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 void  
 TkWinUpdatingClipboard(int mode)  
 {  
     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)  
             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));  
   
     tsdPtr->updatingClipboard = mode;  
 }  
   
   
 /* $History: tkWinX.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 3:18a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKWINX.C */  
1    /* $Header$ */
2    
3    /*
4     * tkWinX.c --
5     *
6     *      This file contains Windows emulation procedures for X routines.
7     *
8     * Copyright (c) 1995-1996 Sun Microsystems, Inc.
9     * Copyright (c) 1994 Software Research Associates, 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: tkWinX.c,v 1.10 2000/04/19 01:06:51 ericm Exp $
16     */
17    
18    #include "tkWinInt.h"
19    
20    /*
21     * The zmouse.h file includes the definition for WM_MOUSEWHEEL.
22     */
23    
24    #include <zmouse.h>
25    
26    /*
27     * Declarations of static variables used in this file.
28     */
29    
30    static char winScreenName[] = ":0"; /* Default name of windows display. */
31    static HINSTANCE tkInstance;        /* Application instance handle. */
32    static int childClassInitialized;   /* Registered child class? */
33    static WNDCLASS childClass;         /* Window class for child windows. */
34    static int tkPlatformId;            /* version of Windows platform */
35    
36    TCL_DECLARE_MUTEX(winXMutex)
37    
38    /*
39     * Thread local storage.  Notice that now each thread must have its
40     * own TkDisplay structure, since this structure contains most of
41     * the thread-specific date for threads.
42     */
43    typedef struct ThreadSpecificData {
44        TkDisplay *winDisplay;       /* TkDisplay structure that *
45                                      *  represents Windows screen. */
46        int updatingClipboard;      /* If 1, we are updating the clipboard */
47    } ThreadSpecificData;
48    static Tcl_ThreadDataKey dataKey;
49    
50    /*
51     * Forward declarations of procedures used in this file.
52     */
53    
54    static void             GenerateXEvent _ANSI_ARGS_((HWND hwnd, UINT message,
55                                WPARAM wParam, LPARAM lParam));
56    static unsigned int     GetState _ANSI_ARGS_((UINT message, WPARAM wParam,
57                                LPARAM lParam));
58    static void             GetTranslatedKey _ANSI_ARGS_((XKeyEvent *xkey));
59    
60    /*
61     *----------------------------------------------------------------------
62     *
63     * TkGetServerInfo --
64     *
65     *      Given a window, this procedure returns information about
66     *      the window server for that window.  This procedure provides
67     *      the guts of the "winfo server" command.
68     *
69     * Results:
70     *      None.
71     *
72     * Side effects:
73     *      None.
74     *
75     *----------------------------------------------------------------------
76     */
77    
78    void
79    TkGetServerInfo(interp, tkwin)
80        Tcl_Interp *interp;         /* The server information is returned in
81                                     * this interpreter's result. */
82        Tk_Window tkwin;            /* Token for window;  this selects a
83                                     * particular display and server. */
84    {
85        char buffer[60];
86        OSVERSIONINFO os;
87    
88        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
89        GetVersionEx(&os);
90        sprintf(buffer, "Windows %d.%d %d Win32", os.dwMajorVersion,
91                os.dwMinorVersion, os.dwBuildNumber);
92        Tcl_SetResult(interp, buffer, TCL_VOLATILE);
93    }
94    
95    /*
96     *----------------------------------------------------------------------
97     *
98     * Tk_GetHINSTANCE --
99     *
100     *      Retrieves the global instance handle used by the Tk library.
101     *
102     * Results:
103     *      Returns the global instance handle.
104     *
105     * Side effects:
106     *      None.
107     *
108     *----------------------------------------------------------------------
109     */
110    
111    HINSTANCE
112    Tk_GetHINSTANCE()
113    {
114        return tkInstance;
115    }
116    
117    /*
118     *----------------------------------------------------------------------
119     *
120     * TkWinXInit --
121     *
122     *      Initialize Xlib emulation layer.
123     *
124     * Results:
125     *      None.
126     *
127     * Side effects:
128     *      Sets up various data structures.
129     *
130     *----------------------------------------------------------------------
131     */
132    
133    void
134    TkWinXInit(hInstance)
135        HINSTANCE hInstance;
136    {
137        OSVERSIONINFO os;
138    
139        if (childClassInitialized != 0) {
140            return;
141        }
142        childClassInitialized = 1;
143    
144        tkInstance = hInstance;
145    
146        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
147        GetVersionEx(&os);
148        tkPlatformId = os.dwPlatformId;
149    
150        /*
151         * When threads are enabled, we cannot use CLASSDC because
152         * threads will then write into the same device context.
153         *
154         * This is a hack; we should add a subsystem that manages
155         * device context on a per-thread basis.  See also tkWinWm.c,
156         * which also initializes a WNDCLASS structure.
157         */
158    
159    #ifdef TCL_THREADS
160        childClass.style = CS_HREDRAW | CS_VREDRAW;
161    #else
162        childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
163    #endif
164    
165        childClass.cbClsExtra = 0;
166        childClass.cbWndExtra = 0;
167        childClass.hInstance = hInstance;
168        childClass.hbrBackground = NULL;
169        childClass.lpszMenuName = NULL;
170    
171        /*
172         * Register the Child window class.
173         */
174    
175        childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME;
176        childClass.lpfnWndProc = TkWinChildProc;
177        childClass.hIcon = NULL;
178        childClass.hCursor = NULL;
179    
180        if (!RegisterClass(&childClass)) {
181            panic("Unable to register TkChild class");
182        }
183    }
184    
185    /*
186     *----------------------------------------------------------------------
187     *
188     * TkWinXCleanup --
189     *
190     *      Removes the registered classes for Tk.
191     *
192     * Results:
193     *      None.
194     *
195     * Side effects:
196     *      Removes window classes from the system.
197     *
198     *----------------------------------------------------------------------
199     */
200    
201    void
202    TkWinXCleanup(hInstance)
203        HINSTANCE hInstance;
204    {
205        /*
206         * Clean up our own class.
207         */
208        
209        if (childClassInitialized) {
210            childClassInitialized = 0;
211            UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);
212        }
213    
214        /*
215         * And let the window manager clean up its own class(es).
216         */
217        
218        TkWinWmCleanup(hInstance);
219    }
220    
221    /*
222     *----------------------------------------------------------------------
223     *
224     * TkWinGetPlatformId --
225     *
226     *      Determines whether running under NT, 95, or Win32s, to allow
227     *      runtime conditional code.
228     *
229     * Results:
230     *      The return value is one of:
231     *          VER_PLATFORM_WIN32s         Win32s on Windows 3.1.
232     *          VER_PLATFORM_WIN32_WINDOWS  Win32 on Windows 95.
233     *          VER_PLATFORM_WIN32_NT       Win32 on Windows NT
234     *
235     * Side effects:
236     *      None.
237     *
238     *----------------------------------------------------------------------
239     */
240    
241    int            
242    TkWinGetPlatformId()
243    {
244        return tkPlatformId;
245    }
246    
247    /*
248     *----------------------------------------------------------------------
249     *
250     * TkGetDefaultScreenName --
251     *
252     *      Returns the name of the screen that Tk should use during
253     *      initialization.
254     *
255     * Results:
256     *      Returns a statically allocated string.
257     *
258     * Side effects:
259     *      None.
260     *
261     *----------------------------------------------------------------------
262     */
263    
264    char *
265    TkGetDefaultScreenName(interp, screenName)
266        Tcl_Interp *interp;         /* Not used. */
267        char *screenName;           /* If NULL, use default string. */
268    {
269        if ((screenName == NULL) || (screenName[0] == '\0')) {
270            screenName = winScreenName;
271        }
272        return screenName;
273    }
274    
275    /*
276     *----------------------------------------------------------------------
277     *
278     * TkpOpenDisplay --
279     *
280     *      Create the Display structure and fill it with device
281     *      specific information.
282     *
283     * Results:
284     *      Returns a TkDisplay structure on success or NULL on failure.
285     *
286     * Side effects:
287     *      Allocates a new TkDisplay structure.
288     *
289     *----------------------------------------------------------------------
290     */
291    
292    TkDisplay *
293    TkpOpenDisplay(display_name)
294        char *display_name;
295    {
296        Screen *screen;
297        HDC dc;
298        TkWinDrawable *twdPtr;
299        Display *display;
300        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
301                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
302    
303        if (tsdPtr->winDisplay != NULL) {
304            if (strcmp(tsdPtr->winDisplay->display->display_name, display_name)
305                    == 0) {
306                return tsdPtr->winDisplay;
307            } else {
308                return NULL;
309            }
310        }
311    
312        display = (Display *) ckalloc(sizeof(Display));
313        display->display_name = (char *) ckalloc(strlen(display_name)+1);
314        strcpy(display->display_name, display_name);
315    
316        display->cursor_font = 1;
317        display->nscreens = 1;
318        display->request = 1;
319        display->qlen = 0;
320    
321        screen = (Screen *) ckalloc(sizeof(Screen));
322        screen->display = display;
323    
324        dc = GetDC(NULL);
325        screen->width = GetDeviceCaps(dc, HORZRES);
326        screen->height = GetDeviceCaps(dc, VERTRES);
327        screen->mwidth = MulDiv(screen->width, 254,
328                GetDeviceCaps(dc, LOGPIXELSX) * 10);
329        screen->mheight = MulDiv(screen->height, 254,
330                GetDeviceCaps(dc, LOGPIXELSY) * 10);
331        
332        /*
333         * Set up the root window.
334         */
335    
336        twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable));
337        if (twdPtr == NULL) {
338            return None;
339        }
340        twdPtr->type = TWD_WINDOW;
341        twdPtr->window.winPtr = NULL;
342        twdPtr->window.handle = NULL;
343        screen->root = (Window)twdPtr;
344    
345        /*
346         * On windows, when creating a color bitmap, need two pieces of
347         * information: the number of color planes and the number of
348         * pixels per plane.  Need to remember both quantities so that
349         * when constructing an HBITMAP for offscreen rendering, we can
350         * specify the correct value for the number of planes.  Otherwise
351         * the HBITMAP won't be compatible with the HWND and we'll just
352         * get blank spots copied onto the screen.
353         */
354    
355        screen->ext_data = (XExtData *) GetDeviceCaps(dc, PLANES);
356        screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * (int) screen->ext_data;
357    
358        screen->root_visual = (Visual *) ckalloc(sizeof(Visual));
359        screen->root_visual->visualid = 0;
360        if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
361            screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE);
362            screen->root_visual->class = PseudoColor;
363            screen->root_visual->red_mask = 0x0;
364            screen->root_visual->green_mask = 0x0;
365            screen->root_visual->blue_mask = 0x0;
366        } else {
367            if (screen->root_depth == 4) {
368                screen->root_visual->class = StaticColor;
369                screen->root_visual->map_entries = 16;
370            } else if (screen->root_depth == 8) {
371                screen->root_visual->class = StaticColor;
372                screen->root_visual->map_entries = 256;
373            } else if (screen->root_depth == 12) {
374                screen->root_visual->class = TrueColor;
375                screen->root_visual->map_entries = 32;
376                screen->root_visual->red_mask = 0xf0;
377                screen->root_visual->green_mask = 0xf000;
378                screen->root_visual->blue_mask = 0xf00000;
379            } else if (screen->root_depth == 16) {
380                screen->root_visual->class = TrueColor;
381                screen->root_visual->map_entries = 64;
382                screen->root_visual->red_mask = 0xf8;
383                screen->root_visual->green_mask = 0xfc00;
384                screen->root_visual->blue_mask = 0xf80000;
385            } else if (screen->root_depth >= 24) {
386                screen->root_visual->class = TrueColor;
387                screen->root_visual->map_entries = 256;
388                screen->root_visual->red_mask = 0xff;
389                screen->root_visual->green_mask = 0xff00;
390                screen->root_visual->blue_mask = 0xff0000;
391            }
392        }
393        screen->root_visual->bits_per_rgb = screen->root_depth;
394        ReleaseDC(NULL, dc);
395    
396        /*
397         * Note that these pixel values are not palette relative.
398         */
399    
400        screen->white_pixel = RGB(255, 255, 255);
401        screen->black_pixel = RGB(0, 0, 0);
402    
403        display->screens            = screen;
404        display->nscreens           = 1;
405        display->default_screen     = 0;
406        screen->cmap = XCreateColormap(display, None, screen->root_visual,
407                AllocNone);
408        tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
409        tsdPtr->winDisplay->display = display;
410        tsdPtr->updatingClipboard = FALSE;
411        return tsdPtr->winDisplay;
412    }
413    
414    /*
415     *----------------------------------------------------------------------
416     *
417     * TkpCloseDisplay --
418     *
419     *      Closes and deallocates a Display structure created with the
420     *      TkpOpenDisplay function.
421     *
422     * Results:
423     *      None.
424     *
425     * Side effects:
426     *      Frees up memory.
427     *
428     *----------------------------------------------------------------------
429     */
430    
431    void
432    TkpCloseDisplay(dispPtr)
433        TkDisplay *dispPtr;
434    {
435        Display *display = dispPtr->display;
436        HWND hwnd;
437        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
438                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
439    
440        if (dispPtr != tsdPtr->winDisplay) {
441            panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");
442            return;
443        }
444    
445        /*
446         * Force the clipboard to be rendered if we are the clipboard owner.
447         */
448        
449        if (dispPtr->clipWindow) {
450            hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));
451            if (GetClipboardOwner() == hwnd) {
452                OpenClipboard(hwnd);
453                EmptyClipboard();
454                TkWinClipboardRender(dispPtr, CF_TEXT);
455                CloseClipboard();
456            }
457        }
458    
459        tsdPtr->winDisplay = NULL;
460    
461        if (display->display_name != (char *) NULL) {
462            ckfree(display->display_name);
463        }
464        if (display->screens != (Screen *) NULL) {
465            if (display->screens->root_visual != NULL) {
466                ckfree((char *) display->screens->root_visual);
467            }
468            if (display->screens->root != None) {
469                ckfree((char *) display->screens->root);
470            }
471            if (display->screens->cmap != None) {
472                XFreeColormap(display, display->screens->cmap);
473            }
474            ckfree((char *) display->screens);
475        }
476        ckfree((char *) display);
477        ckfree((char *) dispPtr);
478    }
479    
480    /*
481     *----------------------------------------------------------------------
482     *
483     * XBell --
484     *
485     *      Generate a beep.
486     *
487     * Results:
488     *      None.
489     *
490     * Side effects:
491     *      Plays a sounds out the system speakers.
492     *
493     *----------------------------------------------------------------------
494     */
495    
496    void
497    XBell(display, percent)
498        Display* display;
499        int percent;
500    {
501        MessageBeep(MB_OK);
502    }
503    
504    /*
505     *----------------------------------------------------------------------
506     *
507     * TkWinChildProc --
508     *
509     *      Callback from Windows whenever an event occurs on a child
510     *      window.
511     *
512     * Results:
513     *      Standard Windows return value.
514     *
515     * Side effects:
516     *      May process events off the Tk event queue.
517     *
518     *----------------------------------------------------------------------
519     */
520    
521    LRESULT CALLBACK
522    TkWinChildProc(hwnd, message, wParam, lParam)
523        HWND hwnd;
524        UINT message;
525        WPARAM wParam;
526        LPARAM lParam;
527    {
528        LRESULT result;
529    
530        switch (message) {
531            case WM_SETCURSOR:
532                /*
533                 * Short circuit the WM_SETCURSOR message since we set
534                 * the cursor elsewhere.
535                 */
536    
537                result = TRUE;
538                break;
539    
540            case WM_CREATE:
541            case WM_ERASEBKGND:
542                result = 0;
543                break;
544    
545            case WM_PAINT:
546                GenerateXEvent(hwnd, message, wParam, lParam);
547                result = DefWindowProc(hwnd, message, wParam, lParam);
548                break;
549    
550            case TK_CLAIMFOCUS:
551            case TK_GEOMETRYREQ:
552            case TK_ATTACHWINDOW:
553            case TK_DETACHWINDOW:
554                result =  TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);
555                break;
556    
557            default:
558                if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam,
559                        &result)) {
560                    result = DefWindowProc(hwnd, message, wParam, lParam);
561                }
562                break;
563        }
564    
565        /*
566         * Handle any newly queued events before returning control to Windows.
567         */
568    
569        Tcl_ServiceAll();
570        return result;
571    }
572    
573    /*
574     *----------------------------------------------------------------------
575     *
576     * Tk_TranslateWinEvent --
577     *
578     *      This function is called by widget window procedures to handle
579     *      the translation from Win32 events to Tk events.
580     *
581     * Results:
582     *      Returns 1 if the event was handled, else 0.
583     *
584     * Side effects:
585     *      Depends on the event.
586     *
587     *----------------------------------------------------------------------
588     */
589    
590    int
591    Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)
592        HWND hwnd;
593        UINT message;
594        WPARAM wParam;
595        LPARAM lParam;
596        LRESULT *resultPtr;
597    {
598        *resultPtr = 0;
599        switch (message) {
600            case WM_RENDERFORMAT: {
601                TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
602                if (winPtr) {
603                    TkWinClipboardRender(winPtr->dispPtr, wParam);
604                }
605                return 1;
606            }
607    
608            case WM_COMMAND:
609            case WM_NOTIFY:
610            case WM_VSCROLL:
611            case WM_HSCROLL: {
612                /*
613                 * Reflect these messages back to the sender so that they
614                 * can be handled by the window proc for the control.  Note
615                 * that we need to be careful not to reflect a message that
616                 * is targeted to this window, or we will loop.
617                 */
618    
619                HWND target = (message == WM_NOTIFY)
620                    ? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;
621                if (target && target != hwnd) {
622                    *resultPtr = SendMessage(target, message, wParam, lParam);
623                    return 1;
624                }
625                break;
626            }
627    
628            case WM_LBUTTONDOWN:
629            case WM_LBUTTONDBLCLK:
630            case WM_MBUTTONDOWN:
631            case WM_MBUTTONDBLCLK:
632            case WM_RBUTTONDOWN:
633            case WM_RBUTTONDBLCLK:
634            case WM_LBUTTONUP:
635            case WM_MBUTTONUP:
636            case WM_RBUTTONUP:
637            case WM_MOUSEMOVE:
638                Tk_PointerEvent(hwnd, (short) LOWORD(lParam),
639                        (short) HIWORD(lParam));
640                return 1;
641    
642            case WM_CLOSE:
643            case WM_SETFOCUS:
644            case WM_KILLFOCUS:
645            case WM_DESTROYCLIPBOARD:
646            case WM_CHAR:
647            case WM_SYSKEYDOWN:
648            case WM_SYSKEYUP:
649            case WM_KEYDOWN:
650            case WM_KEYUP:
651            case WM_MOUSEWHEEL:
652                GenerateXEvent(hwnd, message, wParam, lParam);
653                return 1;
654            case WM_MENUCHAR:
655                GenerateXEvent(hwnd, message, wParam, lParam);
656                /* MNC_CLOSE is the only one that looks right.  This is a hack. */
657                *resultPtr = MAKELONG (0, MNC_CLOSE);
658                return 1;
659        }
660        return 0;
661    }
662    
663    /*
664     *----------------------------------------------------------------------
665     *
666     * GenerateXEvent --
667     *
668     *      This routine generates an X event from the corresponding
669     *      Windows event.
670     *
671     * Results:
672     *      None.
673     *
674     * Side effects:
675     *      Queues one or more X events.
676     *
677     *----------------------------------------------------------------------
678     */
679    
680    static void
681    GenerateXEvent(hwnd, message, wParam, lParam)
682        HWND hwnd;
683        UINT message;
684        WPARAM wParam;
685        LPARAM lParam;
686    {
687        XEvent event;
688        TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
689        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
690                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
691    
692        if (!winPtr || winPtr->window == None) {
693            return;
694        }
695    
696        event.xany.serial = winPtr->display->request++;
697        event.xany.send_event = False;
698        event.xany.display = winPtr->display;
699        event.xany.window = winPtr->window;
700    
701        switch (message) {
702            case WM_PAINT: {
703                PAINTSTRUCT ps;
704    
705                event.type = Expose;
706                BeginPaint(hwnd, &ps);
707                event.xexpose.x = ps.rcPaint.left;
708                event.xexpose.y = ps.rcPaint.top;
709                event.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;
710                event.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;
711                EndPaint(hwnd, &ps);
712                event.xexpose.count = 0;
713                break;
714            }
715    
716            case WM_CLOSE:
717                event.type = ClientMessage;
718                event.xclient.message_type =
719                    Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
720                event.xclient.format = 32;
721                event.xclient.data.l[0] =
722                    Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");
723                break;
724    
725            case WM_SETFOCUS:
726            case WM_KILLFOCUS: {
727                TkWindow *otherWinPtr = (TkWindow *)Tk_HWNDToWindow((HWND) wParam);
728                
729                /*
730                 * Compare toplevel windows to avoid reporting focus
731                 * changes within the same toplevel.
732                 */
733    
734                while (!(winPtr->flags & TK_TOP_LEVEL)) {
735                    winPtr = winPtr->parentPtr;
736                    if (winPtr == NULL) {
737                        return;
738                    }
739                }
740                while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {
741                    otherWinPtr = otherWinPtr->parentPtr;
742                }
743                if (otherWinPtr == winPtr) {
744                    return;
745                }
746    
747                event.xany.window = winPtr->window;
748                event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
749                event.xfocus.mode = NotifyNormal;
750                event.xfocus.detail = NotifyNonlinear;
751                break;
752            }
753    
754            case WM_DESTROYCLIPBOARD:
755                if (tsdPtr->updatingClipboard == TRUE) {
756                    /*
757                     * We want to avoid this event if we are the ones that caused
758                     * this event.
759                     */
760                    return;
761                }
762                event.type = SelectionClear;
763                event.xselectionclear.selection =
764                    Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
765                event.xselectionclear.time = TkpGetMS();
766                break;
767                
768            case WM_MOUSEWHEEL:
769                /*
770                 * The mouse wheel event is closer to a key event than a
771                 * mouse event in that the message is sent to the window
772                 * that has focus.
773                 */
774                
775            case WM_CHAR:
776            case WM_SYSKEYDOWN:
777            case WM_SYSKEYUP:
778            case WM_KEYDOWN:
779            case WM_KEYUP: {
780                unsigned int state = GetState(message, wParam, lParam);
781                Time time = TkpGetMS();
782                POINT clientPoint;
783                POINTS rootPoint;   /* Note: POINT and POINTS are different */
784                DWORD msgPos;
785    
786                /*
787                 * Compute the screen and window coordinates of the event.
788                 */
789                
790                msgPos = GetMessagePos();
791                rootPoint = MAKEPOINTS(msgPos);
792                clientPoint.x = rootPoint.x;
793                clientPoint.y = rootPoint.y;
794                ScreenToClient(hwnd, &clientPoint);
795    
796                /*
797                 * Set up the common event fields.
798                 */
799    
800                event.xbutton.root = RootWindow(winPtr->display,
801                        winPtr->screenNum);
802                event.xbutton.subwindow = None;
803                event.xbutton.x = clientPoint.x;
804                event.xbutton.y = clientPoint.y;
805                event.xbutton.x_root = rootPoint.x;
806                event.xbutton.y_root = rootPoint.y;
807                event.xbutton.state = state;
808                event.xbutton.time = time;
809                event.xbutton.same_screen = True;
810    
811                /*
812                 * Now set up event specific fields.
813                 */
814    
815                switch (message) {
816                    case WM_MOUSEWHEEL:
817                        /*
818                         * We have invented a new X event type to handle
819                         * this event.  It still uses the KeyPress struct.
820                         * However, the keycode field has been overloaded
821                         * to hold the zDelta of the wheel.
822                         */
823                        
824                        event.type = MouseWheelEvent;
825                        event.xany.send_event = -1;
826                        event.xkey.keycode = (short) HIWORD(wParam);
827                        break;
828                    case WM_SYSKEYDOWN:
829                    case WM_KEYDOWN:
830                        /*
831                         * Check for translated characters in the event queue.
832                         * Setting xany.send_event to -1 indicates to the
833                         * Windows implementation of XLookupString that this
834                         * event was generated by windows and that the Windows
835                         * extension xkey.trans_chars is filled with the
836                         * characters that came from the TranslateMessage
837                         * call.  If it is not -1, xkey.keycode is the
838                         * virtual key being sent programmatically by generic
839                         * code.
840                         */
841    
842                        event.type = KeyPress;
843                        event.xany.send_event = -1;
844                        event.xkey.keycode = wParam;
845                        GetTranslatedKey(&event.xkey);
846                        break;
847    
848                    case WM_SYSKEYUP:
849                    case WM_KEYUP:
850                        /*
851                         * We don't check for translated characters on keyup
852                         * because Tk won't know what to do with them.  Instead, we
853                         * wait for the WM_CHAR messages which will follow.
854                         */
855                        event.type = KeyRelease;
856                        event.xkey.keycode = wParam;
857                        event.xkey.nbytes = 0;
858                        break;
859    
860                    case WM_CHAR:
861                        /*
862                         * Synthesize both a KeyPress and a KeyRelease.
863                         * Strings generated by Input Method Editor are handled
864                         * in the following manner:
865                         * 1. A series of WM_KEYDOWN & WM_KEYUP messages that
866                         *    cause GetTranslatedKey() to be called and return
867                         *    immediately because the WM_KEYDOWNs have no
868                         *    associated WM_CHAR messages -- the IME window is
869                         *    accumulating the characters and translating them
870                         *    itself.  In the "bind" command, you get an event
871                         *    with a mystery keysym and %A == "" for each
872                         *    WM_KEYDOWN that actually was meant for the IME.
873                         * 2. A WM_KEYDOWN corresponding to the "confirm typing"
874                         *    character.  This causes GetTranslatedKey() to be
875                         *    called.
876                         * 3. A WM_IME_NOTIFY message saying that the IME is
877                         *    done.  A side effect of this message is that
878                         *    GetTranslatedKey() thinks this means that there
879                         *    are no WM_CHAR messages and returns immediately.
880                         *    In the "bind" command, you get an another event
881                         *    with a mystery keysym and %A == "".
882                         * 4. A sequence of WM_CHAR messages that correspond to
883                         *    the characters in the IME window.  A bunch of
884                         *    simulated KeyPress/KeyRelease events will be
885                         *    generated, one for each character.  Adjacent
886                         *    WM_CHAR messages may actually specify the high
887                         *    and low bytes of a multi-byte character -- in that
888                         *    case the two WM_CHAR messages will be combined into
889                         *    one event.  It is the event-consumer's
890                         *    responsibility to convert the string returned from
891                         *    XLookupString from system encoding to UTF-8.
892                         * 5. And finally we get the WM_KEYUP for the "confirm
893                         *    typing" character.
894                         */
895    
896                        event.type = KeyPress;
897                        event.xany.send_event = -1;
898                        event.xkey.keycode = 0;
899                        event.xkey.nbytes = 1;
900                        event.xkey.trans_chars[0] = (char) wParam;
901    
902                        if (IsDBCSLeadByte((BYTE) wParam)) {
903                            MSG msg;
904    
905                            if ((PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0)
906                                    && (msg.message == WM_CHAR)) {
907                                GetMessage(&msg, NULL, 0, 0);
908                                event.xkey.nbytes = 2;
909                                event.xkey.trans_chars[1] = (char) msg.wParam;
910                            }
911                        }
912                        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
913                        event.type = KeyRelease;
914                        break;
915                }
916                break;
917            }
918    
919            default:
920                return;
921        }
922        Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
923    }
924    
925    /*
926     *----------------------------------------------------------------------
927     *
928     * GetState --
929     *
930     *      This function constructs a state mask for the mouse buttons
931     *      and modifier keys as they were before the event occured.
932     *
933     * Results:
934     *      Returns a composite value of all the modifier and button state
935     *      flags that were set at the time the event occurred.
936     *
937     * Side effects:
938     *      None.
939     *
940     *----------------------------------------------------------------------
941     */
942    
943    static unsigned int
944    GetState(message, wParam, lParam)
945        UINT message;               /* Win32 message type */
946        WPARAM wParam;              /* wParam of message, used if key message */
947        LPARAM lParam;              /* lParam of message, used if key message */
948    {
949        int mask;
950        int prevState;              /* 1 if key was previously down */
951        unsigned int state = TkWinGetModifierState();
952    
953        /*
954         * If the event is a key press or release, we check for modifier
955         * keys so we can report the state of the world before the event.
956         */
957    
958        if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN
959                || message == WM_SYSKEYUP || message == WM_KEYUP) {
960            mask = 0;
961            prevState = HIWORD(lParam) & KF_REPEAT;
962            switch(wParam) {
963                case VK_SHIFT:
964                    mask = ShiftMask;
965                    break;
966                case VK_CONTROL:
967                    mask = ControlMask;
968                    break;
969                case VK_MENU:
970                    mask = ALT_MASK;
971                    break;
972                case VK_CAPITAL:
973                    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
974                        mask = LockMask;
975                        prevState = ((state & mask) ^ prevState) ? 0 : 1;
976                    }
977                    break;
978                case VK_NUMLOCK:
979                    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
980                        mask = Mod1Mask;
981                        prevState = ((state & mask) ^ prevState) ? 0 : 1;
982                    }
983                    break;
984                case VK_SCROLL:
985                    if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
986                        mask = Mod3Mask;
987                        prevState = ((state & mask) ^ prevState) ? 0 : 1;
988                    }
989                    break;
990            }
991            if (prevState) {
992                state |= mask;
993            } else {
994                state &= ~mask;
995            }
996        }
997        return state;
998    }
999    
1000    /*
1001     *----------------------------------------------------------------------
1002     *
1003     * GetTranslatedKey --
1004     *
1005     *      Retrieves WM_CHAR messages that are placed on the system queue
1006     *      by the TranslateMessage system call and places them in the
1007     *      given KeyPress event.
1008     *
1009     * Results:
1010     *      Sets the trans_chars and nbytes member of the key event.
1011     *
1012     * Side effects:
1013     *      Removes any WM_CHAR messages waiting on the top of the system
1014     *      event queue.
1015     *
1016     *----------------------------------------------------------------------
1017     */
1018    
1019    static void
1020    GetTranslatedKey(xkey)
1021        XKeyEvent *xkey;
1022    {
1023        MSG msg;
1024        char buf[XMaxTransChars];
1025        
1026        xkey->nbytes = 0;
1027    
1028        while ((xkey->nbytes < XMaxTransChars)
1029                && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
1030            if ((msg.message == WM_CHAR) || (msg.message == WM_SYSCHAR)) {
1031                GetMessage(&msg, NULL, 0, 0);
1032    
1033                /*
1034                 * If this is a normal character message, we may need to strip
1035                 * off the Alt modifier (e.g. Alt-digits).  Note that we don't
1036                 * want to do this for system messages, because those were
1037                 * presumably generated as an Alt-char sequence (e.g. accelerator
1038                 * keys).
1039                 */
1040    
1041                if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
1042                    xkey->state = 0;
1043                }
1044                buf[xkey->nbytes] = (char) msg.wParam;
1045                xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
1046                xkey->nbytes++;
1047            } else {
1048                break;
1049            }
1050        }
1051    }
1052    
1053    /*
1054     *----------------------------------------------------------------------
1055     *
1056     * Tk_FreeXId --
1057     *
1058     *      This inteface is not needed under Windows.
1059     *
1060     * Results:
1061     *      None.
1062     *
1063     * Side effects:
1064     *      None.
1065     *
1066     *----------------------------------------------------------------------
1067     */
1068    
1069    void
1070    Tk_FreeXId(display, xid)
1071        Display *display;
1072        XID xid;
1073    {
1074    }
1075    
1076    /*
1077     *----------------------------------------------------------------------
1078     *
1079     * TkWinResendEvent --
1080     *
1081     *      This function converts an X event into a Windows event and
1082     *      invokes the specified windo procedure.
1083     *
1084     * Results:
1085     *      A standard Windows result.
1086     *
1087     * Side effects:
1088     *      Invokes the window procedure
1089     *
1090     *----------------------------------------------------------------------
1091     */
1092    
1093    LRESULT
1094    TkWinResendEvent(wndproc, hwnd, eventPtr)
1095        WNDPROC wndproc;
1096        HWND hwnd;
1097        XEvent *eventPtr;
1098    {
1099        UINT msg;
1100        WPARAM wparam;
1101        LPARAM lparam;
1102    
1103        if (eventPtr->type == ButtonPress) {
1104            switch (eventPtr->xbutton.button) {
1105                case Button1:
1106                    msg = WM_LBUTTONDOWN;
1107                    wparam = MK_LBUTTON;
1108                    break;
1109                case Button2:
1110                    msg = WM_MBUTTONDOWN;
1111                    wparam = MK_MBUTTON;
1112                    break;
1113                case Button3:
1114                    msg = WM_RBUTTONDOWN;
1115                    wparam = MK_RBUTTON;
1116                    break;
1117                default:
1118                    return 0;
1119            }
1120            if (eventPtr->xbutton.state & Button1Mask) {
1121                wparam |= MK_LBUTTON;
1122            }
1123            if (eventPtr->xbutton.state & Button2Mask) {
1124                wparam |= MK_MBUTTON;
1125            }
1126            if (eventPtr->xbutton.state & Button3Mask) {
1127                wparam |= MK_RBUTTON;
1128            }
1129            if (eventPtr->xbutton.state & ShiftMask) {
1130                wparam |= MK_SHIFT;
1131            }
1132            if (eventPtr->xbutton.state & ControlMask) {
1133                wparam |= MK_CONTROL;
1134            }
1135            lparam = MAKELPARAM((short) eventPtr->xbutton.x,
1136                    (short) eventPtr->xbutton.y);
1137        } else {
1138            return 0;
1139        }
1140        return CallWindowProc(wndproc, hwnd, msg, wparam, lparam);
1141    }
1142    
1143    /*
1144     *----------------------------------------------------------------------
1145     *
1146     * TkpGetMS --
1147     *
1148     *      Return a relative time in milliseconds.  It doesn't matter
1149     *      when the epoch was.
1150     *
1151     * Results:
1152     *      Number of milliseconds.
1153     *
1154     * Side effects:
1155     *      None.
1156     *
1157     *----------------------------------------------------------------------
1158     */
1159    
1160    unsigned long
1161    TkpGetMS()
1162    {
1163        return GetTickCount();
1164    }
1165    
1166    /*
1167     *----------------------------------------------------------------------
1168     *
1169     * TkWinUpdatingClipboard --
1170     *
1171     *
1172     * Results:
1173     *      Number of milliseconds.
1174     *
1175     * Side effects:
1176     *      None.
1177     *
1178     *----------------------------------------------------------------------
1179     */
1180    
1181    void
1182    TkWinUpdatingClipboard(int mode)
1183    {
1184        ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1185                Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1186    
1187        tsdPtr->updatingClipboard = mode;
1188    }
1189    
1190    /* End of tkwinx.c */

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25