/[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

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

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25