root/src/w32fns.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_x_display_info
  2. w32_window_to_frame
  3. w32_real_positions
  4. w32_fullscreen_rect
  5. w32_default_color_map
  6. w32_color_map_lookup
  7. add_system_logical_colors_to_map
  8. x_to_w32_color
  9. w32_regenerate_palette
  10. w32_map_color
  11. w32_unmap_color
  12. gamma_correct
  13. w32_defined_color
  14. w32_decode_color
  15. w32_set_foreground_color
  16. w32_set_background_color
  17. w32_set_mouse_color
  18. w32_set_cursor_color
  19. w32_set_border_pixel
  20. w32_set_border_color
  21. w32_set_cursor_type
  22. w32_set_icon_type
  23. w32_set_icon_name
  24. w32_clear_under_internal_border
  25. w32_set_child_frame_border_width
  26. w32_set_internal_border_width
  27. w32_set_menu_bar_lines
  28. w32_set_tab_bar_lines
  29. w32_change_tab_bar_height
  30. w32_set_tool_bar_lines
  31. w32_set_inhibit_double_buffering
  32. w32_change_tool_bar_height
  33. w32_set_title_bar_text
  34. w32_set_name
  35. w32_explicitly_set_name
  36. w32_implicitly_set_name
  37. w32_set_title
  38. w32_set_scroll_bar_default_width
  39. w32_set_scroll_bar_default_height
  40. w32_set_undecorated
  41. w32_set_parent_frame
  42. w32_set_skip_taskbar
  43. w32_set_no_focus_on_map
  44. w32_set_no_accept_focus
  45. w32_set_z_group
  46. w32_load_cursor
  47. w32_init_class
  48. w32_applytheme
  49. w32_createvscrollbar
  50. w32_createhscrollbar
  51. w32_createwindow
  52. my_post_msg
  53. funhook
  54. setup_w32_kbdhook
  55. remove_w32_kbdhook
  56. hook_w32_key
  57. check_w32_winkey_state
  58. reset_w32_kbdhook_state
  59. test_modifier_support
  60. record_keydown
  61. record_keyup
  62. reset_modifiers
  63. sync_modifiers
  64. modifier_set
  65. w32_key_to_modifier
  66. w32_get_modifiers
  67. w32_construct_console_modifiers
  68. w32_get_key_modifiers
  69. map_keypad_keys
  70. register_hot_keys
  71. unregister_hot_keys
  72. w32_name_of_message
  73. w32_msg_pump
  74. find_deferred_msg
  75. send_deferred_msg
  76. complete_deferred_msg
  77. cancel_all_deferred_msgs
  78. w32_msg_worker
  79. signal_user_input
  80. post_character_message
  81. get_wm_chars
  82. deliver_wm_chars
  83. w32_wnd_proc
  84. my_create_window
  85. my_create_tip_window
  86. w32_window
  87. w32_icon
  88. w32_make_gc
  89. unwind_create_frame
  90. do_unwind_create_frame
  91. w32_default_font_parameter
  92. DEFUN
  93. DEFUN
  94. DEFUN
  95. DEFUN
  96. DEFUN
  97. DEFUN
  98. DEFUN
  99. DEFUN
  100. DEFUN
  101. DEFUN
  102. DEFUN
  103. DEFUN
  104. DEFUN
  105. DEFUN
  106. DEFUN
  107. DEFUN
  108. w32_monitor_enum
  109. w32_display_monitor_attributes_list
  110. w32_display_monitor_attributes_list_fallback
  111. DEFUN
  112. DEFUN
  113. w32_display_info_for_name
  114. DEFUN
  115. DEFUN
  116. unwind_create_tip_frame
  117. w32_create_tip_frame
  118. compute_tip_xy
  119. w32_hide_tip
  120. DEFUN
  121. file_dialog_callback
  122. w32_dialog_in_progress
  123. DEFUN
  124. lookup_vk_code
  125. w32_parse_and_hook_hot_key
  126. DEFUN
  127. DEFUN
  128. DEFUN
  129. DEFUN
  130. DEFUN
  131. w32_frame_list_z_order
  132. DEFUN
  133. w32_frame_restack
  134. DEFUN
  135. DEFUN
  136. DEFUN
  137. w32_strerror
  138. w32_last_error
  139. cache_system_info
  140. w32_version_string
  141. _DebPrint
  142. w32_console_toggle_lock_key
  143. w32_kbd_mods_to_emacs
  144. w32_kbd_patch_key
  145. w32_sys_ring_bell
  146. DEFUN
  147. get_dll_version
  148. utf8_mbslen_lim
  149. add_tray_notification
  150. delete_tray_notification
  151. DEFUN
  152. DEFUN
  153. DEFUN
  154. w32_get_resource
  155. DEFUN
  156. syms_of_w32fns
  157. w32_reset_stack_overflow_guard
  158. stack_overflow_handler
  159. my_exception_handler
  160. w32_backtrace
  161. emacs_abort
  162. globals_of_w32fns
  163. ntgui_encode_system

     1 /* Graphical user interface functions for the Microsoft Windows API.
     2 
     3 Copyright (C) 1989, 1992-2023 Free Software Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    12 GNU Emacs is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 /* Added by Kevin Gallo */
    21 
    22 #include <config.h>
    23 /* Override API version to get the latest functionality.  */
    24 #undef _WIN32_WINNT
    25 #define _WIN32_WINNT 0x0600
    26 
    27 #include <signal.h>
    28 #include <stdio.h>
    29 #include <limits.h>
    30 #include <errno.h>
    31 #include <math.h>
    32 #include <fcntl.h>
    33 #include <unistd.h>
    34 
    35 #include <c-ctype.h>
    36 
    37 #include "lisp.h"
    38 #include "w32term.h"
    39 #include "frame.h"
    40 #include "window.h"
    41 #include "buffer.h"
    42 #include "keyboard.h"
    43 #include "blockinput.h"
    44 #include "coding.h"
    45 
    46 #include "w32common.h"
    47 #include "w32inevt.h"
    48 
    49 #ifdef WINDOWSNT
    50 #include <mbstring.h>
    51 #include <mbctype.h>    /* for _getmbcp */
    52 #endif /* WINDOWSNT */
    53 
    54 #if CYGWIN
    55 #include "cygw32.h"
    56 #else
    57 #include "w32.h"
    58 #endif
    59 
    60 #include "pdumper.h"
    61 
    62 #include <basetyps.h>
    63 #include <unknwn.h>
    64 #include <commctrl.h>
    65 #include <commdlg.h>
    66 #include <shellapi.h>
    67 #include <shlwapi.h>
    68 #include <ctype.h>
    69 #include <winspool.h>
    70 #include <objbase.h>
    71 
    72 #include <dlgs.h>
    73 #include <imm.h>
    74 #include <windowsx.h>
    75 
    76 /*
    77   Internal/undocumented constants for Windows Dark mode.
    78   See: https://github.com/microsoft/WindowsAppSDK/issues/41
    79 */
    80 #define DARK_MODE_APP_NAME L"DarkMode_Explorer"
    81 /* For Windows 10 version 1809, 1903, 1909. */
    82 #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE_OLD
    83 #define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19
    84 #endif
    85 /* For Windows 10 version 2004 and higher, and Windows 11. */
    86 #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
    87 #define DWMWA_USE_IMMERSIVE_DARK_MODE 20
    88 #endif
    89 
    90 #ifndef FOF_NO_CONNECTED_ELEMENTS
    91 #define FOF_NO_CONNECTED_ELEMENTS 0x2000
    92 #endif
    93 
    94 extern int w32_console_toggle_lock_key (int, Lisp_Object);
    95 extern void w32_menu_display_help (HWND, HMENU, UINT, UINT);
    96 extern void w32_free_menu_strings (HWND);
    97 
    98 #ifndef IDC_HAND
    99 #define IDC_HAND MAKEINTRESOURCE(32649)
   100 #endif
   101 
   102 /* Prefix for system colors.  */
   103 #define SYSTEM_COLOR_PREFIX "System"
   104 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
   105 
   106 /* State variables for emulating a three button mouse. */
   107 #define LMOUSE 1
   108 #define MMOUSE 2
   109 #define RMOUSE 4
   110 
   111 static int button_state = 0;
   112 static W32Msg saved_mouse_button_msg;
   113 static unsigned mouse_button_timer = 0; /* non-zero when timer is active */
   114 static W32Msg saved_mouse_move_msg;
   115 static unsigned mouse_move_timer = 0;
   116 
   117 /* Window that is tracking the mouse.  */
   118 static HWND track_mouse_window;
   119 
   120 /* Multi-monitor API definitions that are not pulled from the headers
   121    since we are compiling for NT 4.  */
   122 #ifndef MONITOR_DEFAULT_TO_NEAREST
   123 #define MONITOR_DEFAULT_TO_NEAREST 2
   124 #endif
   125 #ifndef MONITORINFOF_PRIMARY
   126 #define MONITORINFOF_PRIMARY 1
   127 #endif
   128 #ifndef SM_XVIRTUALSCREEN
   129 #define SM_XVIRTUALSCREEN 76
   130 #endif
   131 #ifndef SM_YVIRTUALSCREEN
   132 #define SM_YVIRTUALSCREEN 77
   133 #endif
   134 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
   135    To avoid a compile error on one or the other, redefine with a new name.  */
   136 struct MONITOR_INFO
   137 {
   138     DWORD   cbSize;
   139     RECT    rcMonitor;
   140     RECT    rcWork;
   141     DWORD   dwFlags;
   142 };
   143 
   144 #if _WIN32_WINDOWS >= 0x0410
   145 #define C_CHILDREN_TITLEBAR CCHILDREN_TITLEBAR
   146 typedef TITLEBARINFO TITLEBAR_INFO;
   147 #else
   148 #define C_CHILDREN_TITLEBAR 5
   149 typedef struct
   150 {
   151   DWORD cbSize;
   152   RECT  rcTitleBar;
   153   DWORD rgstate[C_CHILDREN_TITLEBAR+1];
   154 } TITLEBAR_INFO, *PTITLEBAR_INFO;
   155 #endif
   156 
   157 #ifndef CCHDEVICENAME
   158 #define CCHDEVICENAME 32
   159 #endif
   160 struct MONITOR_INFO_EX
   161 {
   162     DWORD   cbSize;
   163     RECT    rcMonitor;
   164     RECT    rcWork;
   165     DWORD   dwFlags;
   166     char    szDevice[CCHDEVICENAME];
   167 };
   168 
   169 /* Reportedly, MSVC does not have this in its headers.  */
   170 #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
   171 DECLARE_HANDLE(HMONITOR);
   172 #endif
   173 
   174 typedef BOOL (WINAPI * TrackMouseEvent_Proc)
   175   (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
   176 typedef LONG (WINAPI * ImmGetCompositionString_Proc)
   177   (IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
   178 typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
   179 typedef BOOL (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
   180 typedef BOOL (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
   181                                                       IN COMPOSITIONFORM *form);
   182 /* For toggling IME status.  */
   183 typedef BOOL (WINAPI * ImmGetOpenStatus_Proc) (IN HIMC);
   184 typedef BOOL (WINAPI * ImmSetOpenStatus_Proc) (IN HIMC, IN BOOL);
   185 
   186 typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
   187 typedef BOOL (WINAPI * GetMonitorInfo_Proc)
   188   (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
   189 typedef HMONITOR (WINAPI * MonitorFromWindow_Proc)
   190   (IN HWND hwnd, IN DWORD dwFlags);
   191 typedef BOOL CALLBACK (* MonitorEnum_Proc)
   192   (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData);
   193 typedef BOOL (WINAPI * EnumDisplayMonitors_Proc)
   194   (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
   195 typedef BOOL (WINAPI * GetTitleBarInfo_Proc)
   196   (IN HWND hwnd, OUT TITLEBAR_INFO* info);
   197 
   198 typedef BOOL (WINAPI *IsDebuggerPresent_Proc) (void);
   199 typedef HRESULT (WINAPI *SetThreadDescription_Proc)
   200   (HANDLE hThread, PCWSTR lpThreadDescription);
   201 
   202 typedef HRESULT (WINAPI * SetWindowTheme_Proc)
   203   (IN HWND hwnd, IN LPCWSTR pszSubAppName, IN LPCWSTR pszSubIdList);
   204 typedef HRESULT (WINAPI * DwmSetWindowAttribute_Proc)
   205   (HWND hwnd, DWORD dwAttribute, IN LPCVOID pvAttribute, DWORD cbAttribute);
   206 
   207 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
   208 ImmGetCompositionString_Proc get_composition_string_fn = NULL;
   209 ImmGetContext_Proc get_ime_context_fn = NULL;
   210 ImmGetOpenStatus_Proc get_ime_open_status_fn = NULL;
   211 ImmSetOpenStatus_Proc set_ime_open_status_fn = NULL;
   212 ImmReleaseContext_Proc release_ime_context_fn = NULL;
   213 ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
   214 MonitorFromPoint_Proc monitor_from_point_fn = NULL;
   215 GetMonitorInfo_Proc get_monitor_info_fn = NULL;
   216 MonitorFromWindow_Proc monitor_from_window_fn = NULL;
   217 EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL;
   218 GetTitleBarInfo_Proc get_title_bar_info_fn = NULL;
   219 IsDebuggerPresent_Proc is_debugger_present = NULL;
   220 SetThreadDescription_Proc set_thread_description = NULL;
   221 SetWindowTheme_Proc SetWindowTheme_fn = NULL;
   222 DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL;
   223 
   224 extern AppendMenuW_Proc unicode_append_menu;
   225 
   226 /* Flag to selectively ignore WM_IME_CHAR messages.  */
   227 static int ignore_ime_char = 0;
   228 
   229 /* W95 mousewheel handler */
   230 unsigned int msh_mousewheel = 0;
   231 
   232 /* Timers */
   233 #define MOUSE_BUTTON_ID 1
   234 #define MOUSE_MOVE_ID   2
   235 #define MENU_FREE_ID 3
   236 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
   237    is received.  */
   238 #define MENU_FREE_DELAY 1000
   239 static unsigned menu_free_timer = 0;
   240 
   241 #ifdef GLYPH_DEBUG
   242 static ptrdiff_t image_cache_refcount;
   243 static int dpyinfo_refcount;
   244 #endif
   245 
   246 static HWND w32_visible_system_caret_hwnd;
   247 
   248 static int w32_unicode_gui;
   249 
   250 static bool w32_selection_dialog_open;
   251 
   252 /* From w32menu.c  */
   253 int menubar_in_use = 0;
   254 
   255 /* From w32uniscribe.c  */
   256 extern void syms_of_w32uniscribe (void);
   257 extern int uniscribe_available;
   258 extern int harfbuzz_available;
   259 
   260 #ifdef WINDOWSNT
   261 /* From w32inevt.c */
   262 extern int faked_key;
   263 #endif /* WINDOWSNT */
   264 
   265 /* This gives us the page size and the size of the allocation unit on NT.  */
   266 SYSTEM_INFO sysinfo_cache;
   267 
   268 /* This gives us version, build, and platform identification.  */
   269 OSVERSIONINFO osinfo_cache;
   270 
   271 DWORD_PTR syspage_mask = 0;
   272 
   273 /* The major and minor versions of NT.  */
   274 int w32_major_version;
   275 int w32_minor_version;
   276 int w32_build_number;
   277 
   278 /* If the OS is set to use dark mode.  */
   279 BOOL w32_darkmode = FALSE;
   280 
   281 /* Distinguish between Windows NT and Windows 95.  */
   282 int os_subtype;
   283 
   284 #ifdef HAVE_NTGUI
   285 HINSTANCE hinst = NULL;
   286 #endif
   287 
   288 static unsigned int sound_type = 0xFFFFFFFF;
   289 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
   290 
   291 /* Special virtual key code for indicating "any" key.  */
   292 #define VK_ANY 0xFF
   293 
   294 #ifndef WM_WTSSESSION_CHANGE
   295 /* 32-bit MinGW does not define these constants.  */
   296 # define WM_WTSSESSION_CHANGE  0x02B1
   297 # define WTS_SESSION_LOCK      0x7
   298 #endif
   299 
   300 #ifndef WS_EX_NOACTIVATE
   301 #define WS_EX_NOACTIVATE 0x08000000L
   302 #endif
   303 
   304 /* Keyboard hook state data.  */
   305 static struct
   306 {
   307   int hook_count; /* counter, if several windows are created */
   308   HHOOK hook;     /* hook handle */
   309   HWND console;   /* console window handle */
   310 
   311   int lwindown;      /* Left Windows key currently pressed (and hooked) */
   312   int rwindown;      /* Right Windows key currently pressed (and hooked) */
   313   int winsdown;      /* Number of handled keys currently pressed */
   314   int send_win_up;   /* Pass through the keyup for this Windows key press? */
   315   int suppress_lone; /* Suppress simulated Windows keydown-keyup for this press? */
   316   int winseen;       /* Windows keys seen during this press? */
   317 
   318   char alt_hooked[256];  /* hook Alt+[this key]? */
   319   char lwin_hooked[256]; /* hook left Win+[this key]? */
   320   char rwin_hooked[256]; /* hook right Win+[this key]? */
   321 } kbdhook;
   322 typedef HWND (WINAPI *GetConsoleWindow_Proc) (void);
   323 
   324 /* stdin, from w32console.c */
   325 extern HANDLE keyboard_handle;
   326 
   327 static struct w32_display_info *w32_display_info_for_name (Lisp_Object);
   328 
   329 /* Let the user specify a display with a frame.
   330    nil stands for the selected frame--or, if that is not a w32 frame,
   331    the first display on the list.  */
   332 
   333 struct w32_display_info *
   334 check_x_display_info (Lisp_Object object)
   335 {
   336   if (NILP (object))
   337     {
   338       struct frame *sf = XFRAME (selected_frame);
   339 
   340       if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
   341         return FRAME_DISPLAY_INFO (sf);
   342       else
   343         return &one_w32_display_info;
   344     }
   345   else if (TERMINALP (object))
   346     {
   347       struct terminal *t = decode_live_terminal (object);
   348 
   349       if (t->type != output_w32)
   350         error ("Terminal %d is not a W32 display", t->id);
   351 
   352       return t->display_info.w32;
   353     }
   354   else if (STRINGP (object))
   355     return w32_display_info_for_name (object);
   356   else
   357     {
   358       struct frame *f;
   359 
   360       CHECK_LIVE_FRAME (object);
   361       f = XFRAME (object);
   362       if (! FRAME_W32_P (f))
   363         error ("Non-W32 frame used");
   364       return FRAME_DISPLAY_INFO (f);
   365     }
   366 }
   367 
   368 /* Return the Emacs frame-object corresponding to an w32 window.
   369    It could be the frame's main window or an icon window.  */
   370 
   371 struct frame *
   372 w32_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc)
   373 {
   374   Lisp_Object tail, frame;
   375   struct frame *f;
   376 
   377   FOR_EACH_FRAME (tail, frame)
   378     {
   379       f = XFRAME (frame);
   380       if (!FRAME_W32_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
   381         continue;
   382 
   383       if (FRAME_W32_WINDOW (f) == wdesc)
   384         return f;
   385     }
   386   return 0;
   387 }
   388 
   389 
   390 static Lisp_Object unwind_create_frame (Lisp_Object);
   391 static void unwind_create_tip_frame (Lisp_Object);
   392 static void my_create_window (struct frame *);
   393 static void my_create_tip_window (struct frame *);
   394 
   395 /* TODO: Native Input Method support; see x_create_im.  */
   396 static void w32_set_foreground_color (struct frame *, Lisp_Object, Lisp_Object);
   397 static void w32_set_background_color (struct frame *, Lisp_Object, Lisp_Object);
   398 static void w32_set_mouse_color (struct frame *, Lisp_Object, Lisp_Object);
   399 static void w32_set_border_color (struct frame *, Lisp_Object, Lisp_Object);
   400 static void w32_set_cursor_color (struct frame *, Lisp_Object, Lisp_Object);
   401 static void w32_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
   402 static void w32_set_icon_type (struct frame *, Lisp_Object, Lisp_Object);
   403 static void w32_set_icon_name (struct frame *, Lisp_Object, Lisp_Object);
   404 static void w32_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
   405 static void w32_set_title (struct frame *, Lisp_Object, Lisp_Object);
   406 
   407 
   408 /* Store the screen positions of frame F into XPTR and YPTR.
   409    These are the positions of the containing window manager window,
   410    not Emacs's own window.  */
   411 
   412 void
   413 w32_real_positions (struct frame *f, int *xptr, int *yptr)
   414 {
   415   RECT rect;
   416 
   417   /* Get the bounds of the WM window.  */
   418   GetWindowRect (FRAME_W32_WINDOW (f), &rect);
   419 
   420   if (FRAME_PARENT_FRAME (f))
   421     {
   422       /* For a child window we have to get its coordinates wrt its
   423          parent.  */
   424       HWND parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
   425 
   426       if (parent_hwnd)
   427         MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
   428     }
   429 
   430   *xptr = rect.left;
   431   *yptr = rect.top;
   432 }
   433 
   434 /* Returns the window rectangle appropriate for the given fullscreen mode.
   435    The normal rect parameter was the window's rectangle prior to entering
   436    fullscreen mode.  If multiple monitor support is available, the nearest
   437    monitor to the window is chosen.  */
   438 
   439 void
   440 w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal, RECT *rect)
   441 {
   442   struct MONITOR_INFO mi = { sizeof(mi) };
   443   if (monitor_from_window_fn && get_monitor_info_fn)
   444     {
   445       HMONITOR monitor =
   446         monitor_from_window_fn (hwnd, MONITOR_DEFAULT_TO_NEAREST);
   447       get_monitor_info_fn (monitor, &mi);
   448     }
   449   else
   450     {
   451       mi.rcMonitor.left = 0;
   452       mi.rcMonitor.top = 0;
   453       mi.rcMonitor.right = GetSystemMetrics (SM_CXSCREEN);
   454       mi.rcMonitor.bottom = GetSystemMetrics (SM_CYSCREEN);
   455       mi.rcWork.left = 0;
   456       mi.rcWork.top = 0;
   457       mi.rcWork.right = GetSystemMetrics (SM_CXMAXIMIZED);
   458       mi.rcWork.bottom = GetSystemMetrics (SM_CYMAXIMIZED);
   459     }
   460 
   461   switch (fsmode)
   462     {
   463     case FULLSCREEN_BOTH:
   464       rect->left = mi.rcMonitor.left;
   465       rect->top = mi.rcMonitor.top;
   466       rect->right = mi.rcMonitor.right;
   467       rect->bottom = mi.rcMonitor.bottom;
   468       break;
   469     case FULLSCREEN_WIDTH:
   470       rect->left = mi.rcWork.left;
   471       rect->top = normal.top;
   472       rect->right = mi.rcWork.right;
   473       rect->bottom = normal.bottom;
   474       break;
   475     case FULLSCREEN_HEIGHT:
   476       rect->left = normal.left;
   477       rect->top = mi.rcWork.top;
   478       rect->right = normal.right;
   479       rect->bottom = mi.rcWork.bottom;
   480       break;
   481     default:
   482       *rect = normal;
   483       break;
   484     }
   485 }
   486 
   487 
   488 
   489 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
   490        Sw32_define_rgb_color, 4, 4, 0,
   491        doc: /* Convert RGB numbers to a Windows color reference and associate with NAME.
   492 This adds or updates a named color to `w32-color-map', making it
   493 available for use.  The original entry's RGB ref is returned, or nil
   494 if the entry is new.  */)
   495   (Lisp_Object red, Lisp_Object green, Lisp_Object blue, Lisp_Object name)
   496 {
   497   Lisp_Object rgb;
   498   Lisp_Object oldrgb = Qnil;
   499   Lisp_Object entry;
   500 
   501   CHECK_FIXNUM (red);
   502   CHECK_FIXNUM (green);
   503   CHECK_FIXNUM (blue);
   504   CHECK_STRING (name);
   505 
   506   XSETINT (rgb, RGB (XUFIXNUM (red), XUFIXNUM (green), XUFIXNUM (blue)));
   507 
   508   block_input ();
   509 
   510   /* replace existing entry in w32-color-map or add new entry. */
   511   entry = Fassoc (name, Vw32_color_map, Qnil);
   512   if (NILP (entry))
   513     {
   514       entry = Fcons (name, rgb);
   515       Vw32_color_map = Fcons (entry, Vw32_color_map);
   516     }
   517   else
   518     {
   519       oldrgb = Fcdr (entry);
   520       Fsetcdr (entry, rgb);
   521     }
   522 
   523   unblock_input ();
   524 
   525   return (oldrgb);
   526 }
   527 
   528 /* The default colors for the w32 color map */
   529 typedef struct colormap_t
   530 {
   531   const char *name;
   532   COLORREF colorref;
   533 } colormap_t;
   534 
   535 colormap_t w32_color_map[] =
   536 {
   537   {"snow"                      , PALETTERGB (255,250,250)},
   538   {"ghost white"               , PALETTERGB (248,248,255)},
   539   {"GhostWhite"                , PALETTERGB (248,248,255)},
   540   {"white smoke"               , PALETTERGB (245,245,245)},
   541   {"WhiteSmoke"                , PALETTERGB (245,245,245)},
   542   {"gainsboro"                 , PALETTERGB (220,220,220)},
   543   {"floral white"              , PALETTERGB (255,250,240)},
   544   {"FloralWhite"               , PALETTERGB (255,250,240)},
   545   {"old lace"                  , PALETTERGB (253,245,230)},
   546   {"OldLace"                   , PALETTERGB (253,245,230)},
   547   {"linen"                     , PALETTERGB (250,240,230)},
   548   {"antique white"             , PALETTERGB (250,235,215)},
   549   {"AntiqueWhite"              , PALETTERGB (250,235,215)},
   550   {"papaya whip"               , PALETTERGB (255,239,213)},
   551   {"PapayaWhip"                , PALETTERGB (255,239,213)},
   552   {"blanched almond"           , PALETTERGB (255,235,205)},
   553   {"BlanchedAlmond"            , PALETTERGB (255,235,205)},
   554   {"bisque"                    , PALETTERGB (255,228,196)},
   555   {"peach puff"                , PALETTERGB (255,218,185)},
   556   {"PeachPuff"                 , PALETTERGB (255,218,185)},
   557   {"navajo white"              , PALETTERGB (255,222,173)},
   558   {"NavajoWhite"               , PALETTERGB (255,222,173)},
   559   {"moccasin"                  , PALETTERGB (255,228,181)},
   560   {"cornsilk"                  , PALETTERGB (255,248,220)},
   561   {"ivory"                     , PALETTERGB (255,255,240)},
   562   {"lemon chiffon"             , PALETTERGB (255,250,205)},
   563   {"LemonChiffon"              , PALETTERGB (255,250,205)},
   564   {"seashell"                  , PALETTERGB (255,245,238)},
   565   {"honeydew"                  , PALETTERGB (240,255,240)},
   566   {"mint cream"                , PALETTERGB (245,255,250)},
   567   {"MintCream"                 , PALETTERGB (245,255,250)},
   568   {"azure"                     , PALETTERGB (240,255,255)},
   569   {"alice blue"                , PALETTERGB (240,248,255)},
   570   {"AliceBlue"                 , PALETTERGB (240,248,255)},
   571   {"lavender"                  , PALETTERGB (230,230,250)},
   572   {"lavender blush"            , PALETTERGB (255,240,245)},
   573   {"LavenderBlush"             , PALETTERGB (255,240,245)},
   574   {"misty rose"                , PALETTERGB (255,228,225)},
   575   {"MistyRose"                 , PALETTERGB (255,228,225)},
   576   {"white"                     , PALETTERGB (255,255,255)},
   577   {"black"                     , PALETTERGB (  0,  0,  0)},
   578   {"dark slate gray"           , PALETTERGB ( 47, 79, 79)},
   579   {"DarkSlateGray"             , PALETTERGB ( 47, 79, 79)},
   580   {"dark slate grey"           , PALETTERGB ( 47, 79, 79)},
   581   {"DarkSlateGrey"             , PALETTERGB ( 47, 79, 79)},
   582   {"dim gray"                  , PALETTERGB (105,105,105)},
   583   {"DimGray"                   , PALETTERGB (105,105,105)},
   584   {"dim grey"                  , PALETTERGB (105,105,105)},
   585   {"DimGrey"                   , PALETTERGB (105,105,105)},
   586   {"slate gray"                , PALETTERGB (112,128,144)},
   587   {"SlateGray"                 , PALETTERGB (112,128,144)},
   588   {"slate grey"                , PALETTERGB (112,128,144)},
   589   {"SlateGrey"                 , PALETTERGB (112,128,144)},
   590   {"light slate gray"          , PALETTERGB (119,136,153)},
   591   {"LightSlateGray"            , PALETTERGB (119,136,153)},
   592   {"light slate grey"          , PALETTERGB (119,136,153)},
   593   {"LightSlateGrey"            , PALETTERGB (119,136,153)},
   594   {"gray"                      , PALETTERGB (190,190,190)},
   595   {"grey"                      , PALETTERGB (190,190,190)},
   596   {"light grey"                , PALETTERGB (211,211,211)},
   597   {"LightGrey"                 , PALETTERGB (211,211,211)},
   598   {"light gray"                , PALETTERGB (211,211,211)},
   599   {"LightGray"                 , PALETTERGB (211,211,211)},
   600   {"midnight blue"             , PALETTERGB ( 25, 25,112)},
   601   {"MidnightBlue"              , PALETTERGB ( 25, 25,112)},
   602   {"navy"                      , PALETTERGB (  0,  0,128)},
   603   {"navy blue"                 , PALETTERGB (  0,  0,128)},
   604   {"NavyBlue"                  , PALETTERGB (  0,  0,128)},
   605   {"cornflower blue"           , PALETTERGB (100,149,237)},
   606   {"CornflowerBlue"            , PALETTERGB (100,149,237)},
   607   {"dark slate blue"           , PALETTERGB ( 72, 61,139)},
   608   {"DarkSlateBlue"             , PALETTERGB ( 72, 61,139)},
   609   {"slate blue"                , PALETTERGB (106, 90,205)},
   610   {"SlateBlue"                 , PALETTERGB (106, 90,205)},
   611   {"medium slate blue"         , PALETTERGB (123,104,238)},
   612   {"MediumSlateBlue"           , PALETTERGB (123,104,238)},
   613   {"light slate blue"          , PALETTERGB (132,112,255)},
   614   {"LightSlateBlue"            , PALETTERGB (132,112,255)},
   615   {"medium blue"               , PALETTERGB (  0,  0,205)},
   616   {"MediumBlue"                , PALETTERGB (  0,  0,205)},
   617   {"royal blue"                , PALETTERGB ( 65,105,225)},
   618   {"RoyalBlue"                 , PALETTERGB ( 65,105,225)},
   619   {"blue"                      , PALETTERGB (  0,  0,255)},
   620   {"dodger blue"               , PALETTERGB ( 30,144,255)},
   621   {"DodgerBlue"                , PALETTERGB ( 30,144,255)},
   622   {"deep sky blue"             , PALETTERGB (  0,191,255)},
   623   {"DeepSkyBlue"               , PALETTERGB (  0,191,255)},
   624   {"sky blue"                  , PALETTERGB (135,206,235)},
   625   {"SkyBlue"                   , PALETTERGB (135,206,235)},
   626   {"light sky blue"            , PALETTERGB (135,206,250)},
   627   {"LightSkyBlue"              , PALETTERGB (135,206,250)},
   628   {"steel blue"                , PALETTERGB ( 70,130,180)},
   629   {"SteelBlue"                 , PALETTERGB ( 70,130,180)},
   630   {"light steel blue"          , PALETTERGB (176,196,222)},
   631   {"LightSteelBlue"            , PALETTERGB (176,196,222)},
   632   {"light blue"                , PALETTERGB (173,216,230)},
   633   {"LightBlue"                 , PALETTERGB (173,216,230)},
   634   {"powder blue"               , PALETTERGB (176,224,230)},
   635   {"PowderBlue"                , PALETTERGB (176,224,230)},
   636   {"pale turquoise"            , PALETTERGB (175,238,238)},
   637   {"PaleTurquoise"             , PALETTERGB (175,238,238)},
   638   {"dark turquoise"            , PALETTERGB (  0,206,209)},
   639   {"DarkTurquoise"             , PALETTERGB (  0,206,209)},
   640   {"medium turquoise"          , PALETTERGB ( 72,209,204)},
   641   {"MediumTurquoise"           , PALETTERGB ( 72,209,204)},
   642   {"turquoise"                 , PALETTERGB ( 64,224,208)},
   643   {"cyan"                      , PALETTERGB (  0,255,255)},
   644   {"light cyan"                , PALETTERGB (224,255,255)},
   645   {"LightCyan"                 , PALETTERGB (224,255,255)},
   646   {"cadet blue"                , PALETTERGB ( 95,158,160)},
   647   {"CadetBlue"                 , PALETTERGB ( 95,158,160)},
   648   {"medium aquamarine"         , PALETTERGB (102,205,170)},
   649   {"MediumAquamarine"          , PALETTERGB (102,205,170)},
   650   {"aquamarine"                , PALETTERGB (127,255,212)},
   651   {"dark green"                , PALETTERGB (  0,100,  0)},
   652   {"DarkGreen"                 , PALETTERGB (  0,100,  0)},
   653   {"dark olive green"          , PALETTERGB ( 85,107, 47)},
   654   {"DarkOliveGreen"            , PALETTERGB ( 85,107, 47)},
   655   {"dark sea green"            , PALETTERGB (143,188,143)},
   656   {"DarkSeaGreen"              , PALETTERGB (143,188,143)},
   657   {"sea green"                 , PALETTERGB ( 46,139, 87)},
   658   {"SeaGreen"                  , PALETTERGB ( 46,139, 87)},
   659   {"medium sea green"          , PALETTERGB ( 60,179,113)},
   660   {"MediumSeaGreen"            , PALETTERGB ( 60,179,113)},
   661   {"light sea green"           , PALETTERGB ( 32,178,170)},
   662   {"LightSeaGreen"             , PALETTERGB ( 32,178,170)},
   663   {"pale green"                , PALETTERGB (152,251,152)},
   664   {"PaleGreen"                 , PALETTERGB (152,251,152)},
   665   {"spring green"              , PALETTERGB (  0,255,127)},
   666   {"SpringGreen"               , PALETTERGB (  0,255,127)},
   667   {"lawn green"                , PALETTERGB (124,252,  0)},
   668   {"LawnGreen"                 , PALETTERGB (124,252,  0)},
   669   {"green"                     , PALETTERGB (  0,255,  0)},
   670   {"chartreuse"                , PALETTERGB (127,255,  0)},
   671   {"medium spring green"       , PALETTERGB (  0,250,154)},
   672   {"MediumSpringGreen"         , PALETTERGB (  0,250,154)},
   673   {"green yellow"              , PALETTERGB (173,255, 47)},
   674   {"GreenYellow"               , PALETTERGB (173,255, 47)},
   675   {"lime green"                , PALETTERGB ( 50,205, 50)},
   676   {"LimeGreen"                 , PALETTERGB ( 50,205, 50)},
   677   {"yellow green"              , PALETTERGB (154,205, 50)},
   678   {"YellowGreen"               , PALETTERGB (154,205, 50)},
   679   {"forest green"              , PALETTERGB ( 34,139, 34)},
   680   {"ForestGreen"               , PALETTERGB ( 34,139, 34)},
   681   {"olive drab"                , PALETTERGB (107,142, 35)},
   682   {"OliveDrab"                 , PALETTERGB (107,142, 35)},
   683   {"dark khaki"                , PALETTERGB (189,183,107)},
   684   {"DarkKhaki"                 , PALETTERGB (189,183,107)},
   685   {"khaki"                     , PALETTERGB (240,230,140)},
   686   {"pale goldenrod"            , PALETTERGB (238,232,170)},
   687   {"PaleGoldenrod"             , PALETTERGB (238,232,170)},
   688   {"light goldenrod yellow"    , PALETTERGB (250,250,210)},
   689   {"LightGoldenrodYellow"      , PALETTERGB (250,250,210)},
   690   {"light yellow"              , PALETTERGB (255,255,224)},
   691   {"LightYellow"               , PALETTERGB (255,255,224)},
   692   {"yellow"                    , PALETTERGB (255,255,  0)},
   693   {"gold"                      , PALETTERGB (255,215,  0)},
   694   {"light goldenrod"           , PALETTERGB (238,221,130)},
   695   {"LightGoldenrod"            , PALETTERGB (238,221,130)},
   696   {"goldenrod"                 , PALETTERGB (218,165, 32)},
   697   {"dark goldenrod"            , PALETTERGB (184,134, 11)},
   698   {"DarkGoldenrod"             , PALETTERGB (184,134, 11)},
   699   {"rosy brown"                , PALETTERGB (188,143,143)},
   700   {"RosyBrown"                 , PALETTERGB (188,143,143)},
   701   {"indian red"                , PALETTERGB (205, 92, 92)},
   702   {"IndianRed"                 , PALETTERGB (205, 92, 92)},
   703   {"saddle brown"              , PALETTERGB (139, 69, 19)},
   704   {"SaddleBrown"               , PALETTERGB (139, 69, 19)},
   705   {"sienna"                    , PALETTERGB (160, 82, 45)},
   706   {"peru"                      , PALETTERGB (205,133, 63)},
   707   {"burlywood"                 , PALETTERGB (222,184,135)},
   708   {"beige"                     , PALETTERGB (245,245,220)},
   709   {"wheat"                     , PALETTERGB (245,222,179)},
   710   {"sandy brown"               , PALETTERGB (244,164, 96)},
   711   {"SandyBrown"                , PALETTERGB (244,164, 96)},
   712   {"tan"                       , PALETTERGB (210,180,140)},
   713   {"chocolate"                 , PALETTERGB (210,105, 30)},
   714   {"firebrick"                 , PALETTERGB (178,34, 34)},
   715   {"brown"                     , PALETTERGB (165,42, 42)},
   716   {"dark salmon"               , PALETTERGB (233,150,122)},
   717   {"DarkSalmon"                , PALETTERGB (233,150,122)},
   718   {"salmon"                    , PALETTERGB (250,128,114)},
   719   {"light salmon"              , PALETTERGB (255,160,122)},
   720   {"LightSalmon"               , PALETTERGB (255,160,122)},
   721   {"orange"                    , PALETTERGB (255,165,  0)},
   722   {"dark orange"               , PALETTERGB (255,140,  0)},
   723   {"DarkOrange"                , PALETTERGB (255,140,  0)},
   724   {"coral"                     , PALETTERGB (255,127, 80)},
   725   {"light coral"               , PALETTERGB (240,128,128)},
   726   {"LightCoral"                , PALETTERGB (240,128,128)},
   727   {"tomato"                    , PALETTERGB (255, 99, 71)},
   728   {"orange red"                , PALETTERGB (255, 69,  0)},
   729   {"OrangeRed"                 , PALETTERGB (255, 69,  0)},
   730   {"red"                       , PALETTERGB (255,  0,  0)},
   731   {"hot pink"                  , PALETTERGB (255,105,180)},
   732   {"HotPink"                   , PALETTERGB (255,105,180)},
   733   {"deep pink"                 , PALETTERGB (255, 20,147)},
   734   {"DeepPink"                  , PALETTERGB (255, 20,147)},
   735   {"pink"                      , PALETTERGB (255,192,203)},
   736   {"light pink"                , PALETTERGB (255,182,193)},
   737   {"LightPink"                 , PALETTERGB (255,182,193)},
   738   {"pale violet red"           , PALETTERGB (219,112,147)},
   739   {"PaleVioletRed"             , PALETTERGB (219,112,147)},
   740   {"maroon"                    , PALETTERGB (176, 48, 96)},
   741   {"medium violet red"         , PALETTERGB (199, 21,133)},
   742   {"MediumVioletRed"           , PALETTERGB (199, 21,133)},
   743   {"violet red"                , PALETTERGB (208, 32,144)},
   744   {"VioletRed"                 , PALETTERGB (208, 32,144)},
   745   {"magenta"                   , PALETTERGB (255,  0,255)},
   746   {"violet"                    , PALETTERGB (238,130,238)},
   747   {"plum"                      , PALETTERGB (221,160,221)},
   748   {"orchid"                    , PALETTERGB (218,112,214)},
   749   {"medium orchid"             , PALETTERGB (186, 85,211)},
   750   {"MediumOrchid"              , PALETTERGB (186, 85,211)},
   751   {"dark orchid"               , PALETTERGB (153, 50,204)},
   752   {"DarkOrchid"                , PALETTERGB (153, 50,204)},
   753   {"dark violet"               , PALETTERGB (148,  0,211)},
   754   {"DarkViolet"                , PALETTERGB (148,  0,211)},
   755   {"blue violet"               , PALETTERGB (138, 43,226)},
   756   {"BlueViolet"                , PALETTERGB (138, 43,226)},
   757   {"purple"                    , PALETTERGB (160, 32,240)},
   758   {"medium purple"             , PALETTERGB (147,112,219)},
   759   {"MediumPurple"              , PALETTERGB (147,112,219)},
   760   {"thistle"                   , PALETTERGB (216,191,216)},
   761   {"gray0"                     , PALETTERGB (  0,  0,  0)},
   762   {"grey0"                     , PALETTERGB (  0,  0,  0)},
   763   {"dark grey"                 , PALETTERGB (169,169,169)},
   764   {"DarkGrey"                  , PALETTERGB (169,169,169)},
   765   {"dark gray"                 , PALETTERGB (169,169,169)},
   766   {"DarkGray"                  , PALETTERGB (169,169,169)},
   767   {"dark blue"                 , PALETTERGB (  0,  0,139)},
   768   {"DarkBlue"                  , PALETTERGB (  0,  0,139)},
   769   {"dark cyan"                 , PALETTERGB (  0,139,139)},
   770   {"DarkCyan"                  , PALETTERGB (  0,139,139)},
   771   {"dark magenta"              , PALETTERGB (139,  0,139)},
   772   {"DarkMagenta"               , PALETTERGB (139,  0,139)},
   773   {"dark red"                  , PALETTERGB (139,  0,  0)},
   774   {"DarkRed"                   , PALETTERGB (139,  0,  0)},
   775   {"light green"               , PALETTERGB (144,238,144)},
   776   {"LightGreen"                , PALETTERGB (144,238,144)},
   777 };
   778 
   779 static Lisp_Object
   780 w32_default_color_map (void)
   781 {
   782   int i;
   783   colormap_t *pc = w32_color_map;
   784   Lisp_Object cmap;
   785 
   786   block_input ();
   787 
   788   cmap = Qnil;
   789 
   790   for (i = 0; i < ARRAYELTS (w32_color_map); pc++, i++)
   791     cmap = Fcons (Fcons (build_string (pc->name),
   792                          make_fixnum (pc->colorref)),
   793                   cmap);
   794 
   795   unblock_input ();
   796 
   797   return (cmap);
   798 }
   799 
   800 static Lisp_Object
   801 w32_color_map_lookup (const char *colorname)
   802 {
   803   Lisp_Object tail, ret = Qnil;
   804 
   805   block_input ();
   806 
   807   for (tail = Vw32_color_map; CONSP (tail); tail = XCDR (tail))
   808     {
   809       register Lisp_Object elt, tem;
   810 
   811       elt = XCAR (tail);
   812       if (!CONSP (elt)) continue;
   813 
   814       tem = XCAR (elt);
   815 
   816       if (lstrcmpi (SSDATA (tem), colorname) == 0)
   817         {
   818           ret = Fcdr (elt);
   819           break;
   820         }
   821 
   822       maybe_quit ();
   823     }
   824 
   825   unblock_input ();
   826 
   827   return ret;
   828 }
   829 
   830 
   831 static void
   832 add_system_logical_colors_to_map (Lisp_Object *system_colors)
   833 {
   834   HKEY colors_key;
   835 
   836   /* Other registry operations are done with input blocked.  */
   837   block_input ();
   838 
   839   /* Look for "Control Panel/Colors" under User and Machine registry
   840      settings.  */
   841   if (RegOpenKeyEx (HKEY_CURRENT_USER, "Control Panel\\Colors", 0,
   842                     KEY_READ, &colors_key) == ERROR_SUCCESS
   843       || RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Control Panel\\Colors", 0,
   844                        KEY_READ, &colors_key) == ERROR_SUCCESS)
   845     {
   846       /* List all keys.  */
   847       char color_buffer[64];
   848       char full_name_buffer[MAX_PATH + SYSTEM_COLOR_PREFIX_LEN];
   849       int index = 0;
   850       DWORD name_size, color_size;
   851       char *name_buffer = full_name_buffer + SYSTEM_COLOR_PREFIX_LEN;
   852 
   853       name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
   854       color_size = sizeof (color_buffer);
   855 
   856       strcpy (full_name_buffer, SYSTEM_COLOR_PREFIX);
   857 
   858       while (RegEnumValueA (colors_key, index, name_buffer, &name_size,
   859                             NULL, NULL, (LPBYTE)color_buffer, &color_size)
   860              == ERROR_SUCCESS)
   861         {
   862           unsigned r, g, b;
   863           if (sscanf (color_buffer, " %u %u %u", &r, &g, &b) == 3)
   864             *system_colors = Fcons (Fcons (build_string (full_name_buffer),
   865                                            make_fixnum (RGB (r, g, b))),
   866                                     *system_colors);
   867 
   868           name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
   869           color_size = sizeof (color_buffer);
   870           index++;
   871         }
   872       RegCloseKey (colors_key);
   873     }
   874 
   875   unblock_input ();
   876 }
   877 
   878 
   879 static Lisp_Object
   880 x_to_w32_color (const char * colorname)
   881 {
   882   register Lisp_Object ret = Qnil;
   883 
   884   block_input ();
   885 
   886   unsigned short r, g, b;
   887   if (parse_color_spec (colorname, &r, &g, &b))
   888     {
   889       unblock_input ();
   890       /* Throw away the low 8 bits and return 0xBBGGRR.  */
   891       return make_fixnum ((b & 0xff00) << 8 | (g & 0xff00) | r >> 8);
   892     }
   893 
   894   /* I am not going to attempt to handle any of the CIE color schemes
   895      or TekHVC, since I don't know the algorithms for conversion to
   896      RGB.  */
   897 
   898   /* If we fail to lookup the color name in w32_color_map, then check the
   899      colorname to see if it can be crudely approximated: If the X color
   900      ends in a number (e.g., "darkseagreen2"), strip the number and
   901      return the result of looking up the base color name.  */
   902   ret = w32_color_map_lookup (colorname);
   903   if (NILP (ret))
   904     {
   905       int len = strlen (colorname);
   906 
   907       if (isdigit (colorname[len - 1]))
   908         {
   909           char *ptr, *approx = alloca (len + 1);
   910 
   911           strcpy (approx, colorname);
   912           ptr = &approx[len - 1];
   913           while (ptr > approx && isdigit (*ptr))
   914               *ptr-- = '\0';
   915 
   916           ret = w32_color_map_lookup (approx);
   917         }
   918     }
   919 
   920   unblock_input ();
   921   return ret;
   922 }
   923 
   924 void
   925 w32_regenerate_palette (struct frame *f)
   926 {
   927   struct w32_palette_entry * list;
   928   LOGPALETTE *          log_palette;
   929   HPALETTE              new_palette;
   930   int                   i;
   931 
   932   /* don't bother trying to create palette if not supported */
   933   if (! FRAME_DISPLAY_INFO (f)->has_palette)
   934     return;
   935 
   936   log_palette = (LOGPALETTE *)
   937     alloca (sizeof (LOGPALETTE) +
   938              FRAME_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
   939   log_palette->palVersion = 0x300;
   940   log_palette->palNumEntries = FRAME_DISPLAY_INFO (f)->num_colors;
   941 
   942   list = FRAME_DISPLAY_INFO (f)->color_list;
   943   for (i = 0;
   944        i < FRAME_DISPLAY_INFO (f)->num_colors;
   945        i++, list = list->next)
   946     log_palette->palPalEntry[i] = list->entry;
   947 
   948   new_palette = CreatePalette (log_palette);
   949 
   950   enter_crit ();
   951 
   952   if (FRAME_DISPLAY_INFO (f)->palette)
   953     DeleteObject (FRAME_DISPLAY_INFO (f)->palette);
   954   FRAME_DISPLAY_INFO (f)->palette = new_palette;
   955 
   956   /* Realize display palette and garbage all frames. */
   957   release_frame_dc (f, get_frame_dc (f));
   958 
   959   leave_crit ();
   960 }
   961 
   962 #define W32_COLOR(pe)  RGB (pe.peRed, pe.peGreen, pe.peBlue)
   963 #define SET_W32_COLOR(pe, color) \
   964   do \
   965     { \
   966       pe.peRed = GetRValue (color); \
   967       pe.peGreen = GetGValue (color); \
   968       pe.peBlue = GetBValue (color); \
   969       pe.peFlags = 0; \
   970     } while (0)
   971 
   972 #if 0
   973 /* Keep these around in case we ever want to track color usage. */
   974 void
   975 w32_map_color (struct frame *f, COLORREF color)
   976 {
   977   struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
   978 
   979   if (NILP (Vw32_enable_palette))
   980     return;
   981 
   982   /* check if color is already mapped */
   983   while (list)
   984     {
   985       if (W32_COLOR (list->entry) == color)
   986         {
   987           ++list->refcount;
   988           return;
   989         }
   990       list = list->next;
   991     }
   992 
   993   /* not already mapped, so add to list and recreate Windows palette */
   994   list = xmalloc (sizeof (struct w32_palette_entry));
   995   SET_W32_COLOR (list->entry, color);
   996   list->refcount = 1;
   997   list->next = FRAME_DISPLAY_INFO (f)->color_list;
   998   FRAME_DISPLAY_INFO (f)->color_list = list;
   999   FRAME_DISPLAY_INFO (f)->num_colors++;
  1000 
  1001   /* set flag that palette must be regenerated */
  1002   FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
  1003 }
  1004 
  1005 void
  1006 w32_unmap_color (struct frame *f, COLORREF color)
  1007 {
  1008   struct w32_palette_entry * list = FRAME_DISPLAY_INFO (f)->color_list;
  1009   struct w32_palette_entry **prev = &FRAME_DISPLAY_INFO (f)->color_list;
  1010 
  1011   if (NILP (Vw32_enable_palette))
  1012     return;
  1013 
  1014   /* check if color is already mapped */
  1015   while (list)
  1016     {
  1017       if (W32_COLOR (list->entry) == color)
  1018         {
  1019           if (--list->refcount == 0)
  1020             {
  1021               *prev = list->next;
  1022               xfree (list);
  1023               FRAME_DISPLAY_INFO (f)->num_colors--;
  1024               break;
  1025             }
  1026           else
  1027             return;
  1028         }
  1029       prev = &list->next;
  1030       list = list->next;
  1031     }
  1032 
  1033   /* set flag that palette must be regenerated */
  1034   FRAME_DISPLAY_INFO (f)->regen_palette = TRUE;
  1035 }
  1036 #endif
  1037 
  1038 
  1039 /* Gamma-correct COLOR on frame F.  */
  1040 
  1041 void
  1042 gamma_correct (struct frame *f, COLORREF *color)
  1043 {
  1044   if (f->gamma)
  1045     {
  1046       *color = PALETTERGB (
  1047         pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
  1048         pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
  1049         pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
  1050     }
  1051 }
  1052 
  1053 
  1054 /* Decide if color named COLOR is valid for the display associated with
  1055    the selected frame; if so, return the rgb values in COLOR_DEF.
  1056    If ALLOC is nonzero, allocate a new colormap cell.  */
  1057 
  1058 bool
  1059 w32_defined_color (struct frame *f, const char *color, Emacs_Color *color_def,
  1060                    bool alloc_p, bool _makeIndex)
  1061 {
  1062   register Lisp_Object tem;
  1063   COLORREF w32_color_ref;
  1064 
  1065   tem = x_to_w32_color (color);
  1066 
  1067   if (!NILP (tem))
  1068     {
  1069       if (f)
  1070         {
  1071           /* Apply gamma correction.  */
  1072           w32_color_ref = XUFIXNUM (tem);
  1073           gamma_correct (f, &w32_color_ref);
  1074           XSETINT (tem, w32_color_ref);
  1075         }
  1076 
  1077       /* Map this color to the palette if it is enabled. */
  1078       if (!NILP (Vw32_enable_palette))
  1079         {
  1080           struct w32_palette_entry * entry =
  1081             one_w32_display_info.color_list;
  1082           struct w32_palette_entry ** prev =
  1083             &one_w32_display_info.color_list;
  1084 
  1085           /* check if color is already mapped */
  1086           while (entry)
  1087             {
  1088               if (W32_COLOR (entry->entry) == XUFIXNUM (tem))
  1089                 break;
  1090               prev = &entry->next;
  1091               entry = entry->next;
  1092             }
  1093 
  1094           if (entry == NULL && alloc_p)
  1095             {
  1096               /* not already mapped, so add to list */
  1097               entry = xmalloc (sizeof (struct w32_palette_entry));
  1098               SET_W32_COLOR (entry->entry, XUFIXNUM (tem));
  1099               entry->next = NULL;
  1100               *prev = entry;
  1101               one_w32_display_info.num_colors++;
  1102 
  1103               /* set flag that palette must be regenerated */
  1104               one_w32_display_info.regen_palette = TRUE;
  1105             }
  1106         }
  1107       /* Ensure COLORREF value is snapped to nearest color in (default)
  1108          palette by simulating the PALETTERGB macro.  This works whether
  1109          or not the display device has a palette. */
  1110       w32_color_ref = XUFIXNUM (tem) | 0x2000000;
  1111 
  1112       color_def->pixel = w32_color_ref;
  1113       color_def->red = GetRValue (w32_color_ref) * 256;
  1114       color_def->green = GetGValue (w32_color_ref) * 256;
  1115       color_def->blue = GetBValue (w32_color_ref) * 256;
  1116 
  1117       return 1;
  1118     }
  1119   else
  1120     {
  1121       return 0;
  1122     }
  1123 }
  1124 
  1125 /* Given a string ARG naming a color, compute a pixel value from it
  1126    suitable for screen F.
  1127    If F is not a color screen, return DEF (default) regardless of what
  1128    ARG says.  */
  1129 
  1130 static int
  1131 w32_decode_color (struct frame *f, Lisp_Object arg, int def)
  1132 {
  1133   Emacs_Color cdef;
  1134 
  1135   CHECK_STRING (arg);
  1136 
  1137   if (strcmp (SSDATA (arg), "black") == 0)
  1138     return BLACK_PIX_DEFAULT (f);
  1139   else if (strcmp (SSDATA (arg), "white") == 0)
  1140     return WHITE_PIX_DEFAULT (f);
  1141 
  1142   if ((FRAME_DISPLAY_INFO (f)->n_planes * FRAME_DISPLAY_INFO (f)->n_cbits) == 1)
  1143     return def;
  1144 
  1145   /* w32_defined_color is responsible for coping with failures
  1146      by looking for a near-miss.  */
  1147   if (w32_defined_color (f, SSDATA (arg), &cdef, true, false))
  1148     return cdef.pixel;
  1149 
  1150   /* defined_color failed; return an ultimate default.  */
  1151   return def;
  1152 }
  1153 
  1154 
  1155 
  1156 /* Functions called only from `gui_set_frame_parameters'
  1157    to set individual parameters.
  1158 
  1159    If FRAME_W32_WINDOW (f) is 0,
  1160    the frame is being created and its window does not exist yet.
  1161    In that case, just record the parameter's new value
  1162    in the standard place; do not attempt to change the window.  */
  1163 
  1164 static void
  1165 w32_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1166 {
  1167   struct w32_output *x = f->output_data.w32;
  1168   PIX_TYPE fg, old_fg;
  1169 
  1170   fg = w32_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
  1171   old_fg = FRAME_FOREGROUND_PIXEL (f);
  1172   FRAME_FOREGROUND_PIXEL (f) = fg;
  1173 
  1174   if (FRAME_W32_WINDOW (f) != 0)
  1175     {
  1176       if (x->cursor_pixel == old_fg)
  1177         {
  1178           x->cursor_pixel = fg;
  1179           x->cursor_gc->background = fg;
  1180         }
  1181 
  1182       update_face_from_frame_parameter (f, Qforeground_color, arg);
  1183       if (FRAME_VISIBLE_P (f))
  1184         redraw_frame (f);
  1185     }
  1186 }
  1187 
  1188 static void
  1189 w32_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1190 {
  1191   FRAME_BACKGROUND_PIXEL (f)
  1192     = w32_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
  1193 
  1194   if (FRAME_W32_WINDOW (f) != 0)
  1195     {
  1196       SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
  1197                      FRAME_BACKGROUND_PIXEL (f));
  1198 
  1199       update_face_from_frame_parameter (f, Qbackground_color, arg);
  1200 
  1201       if (FRAME_VISIBLE_P (f))
  1202         redraw_frame (f);
  1203     }
  1204 }
  1205 
  1206 static void
  1207 w32_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1208 {
  1209 #if 0
  1210   Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
  1211   int count;
  1212 #endif
  1213   int mask_color;
  1214 
  1215   if (!NILP (arg))
  1216     f->output_data.w32->mouse_pixel
  1217       = w32_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
  1218   mask_color = FRAME_BACKGROUND_PIXEL (f);
  1219 
  1220   /* Don't let pointers be invisible.  */
  1221   if (mask_color == f->output_data.w32->mouse_pixel
  1222         && mask_color == FRAME_BACKGROUND_PIXEL (f))
  1223     f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
  1224 
  1225 #if 0 /* TODO : Mouse cursor customization.  */
  1226   block_input ();
  1227 
  1228   /* It's not okay to crash if the user selects a screwy cursor.  */
  1229   count = x_catch_errors (FRAME_W32_DISPLAY (f));
  1230 
  1231   if (!NILP (Vx_pointer_shape))
  1232     {
  1233       CHECK_FIXNUM (Vx_pointer_shape);
  1234       cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XFIXNUM (Vx_pointer_shape));
  1235     }
  1236   else
  1237     cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
  1238   x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
  1239 
  1240   if (!NILP (Vx_nontext_pointer_shape))
  1241     {
  1242       CHECK_FIXNUM (Vx_nontext_pointer_shape);
  1243       nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1244                                           XFIXNUM (Vx_nontext_pointer_shape));
  1245     }
  1246   else
  1247     nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
  1248   x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
  1249 
  1250   if (!NILP (Vx_hourglass_pointer_shape))
  1251     {
  1252       CHECK_FIXNUM (Vx_hourglass_pointer_shape);
  1253       hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1254                                             XFIXNUM (Vx_hourglass_pointer_shape));
  1255     }
  1256   else
  1257     hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
  1258   x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
  1259 
  1260   x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
  1261   if (!NILP (Vx_mode_pointer_shape))
  1262     {
  1263       CHECK_FIXNUM (Vx_mode_pointer_shape);
  1264       mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1265                                        XFIXNUM (Vx_mode_pointer_shape));
  1266     }
  1267   else
  1268     mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
  1269   x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
  1270 
  1271   if (!NILP (Vx_sensitive_text_pointer_shape))
  1272     {
  1273       CHECK_FIXNUM (Vx_sensitive_text_pointer_shape);
  1274       hand_cursor
  1275         = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1276                              XFIXNUM (Vx_sensitive_text_pointer_shape));
  1277     }
  1278   else
  1279     hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
  1280 
  1281   if (!NILP (Vx_window_horizontal_drag_shape))
  1282     {
  1283       CHECK_FIXNUM (Vx_window_horizontal_drag_shape);
  1284       horizontal_drag_cursor
  1285         = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1286                              XFIXNUM (Vx_window_horizontal_drag_shape));
  1287     }
  1288   else
  1289     horizontal_drag_cursor
  1290       = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
  1291 
  1292   if (!NILP (Vx_window_vertical_drag_shape))
  1293     {
  1294       CHECK_FIXNUM (Vx_window_vertical_drag_shape);
  1295       vertical_drag_cursor
  1296         = XCreateFontCursor (FRAME_W32_DISPLAY (f),
  1297                              XFIXNUM (Vx_window_vertical_drag_shape));
  1298     }
  1299   else
  1300     vertical_drag_cursor
  1301       = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_v_double_arrow);
  1302 
  1303   /* Check and report errors with the above calls.  */
  1304   x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
  1305   x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
  1306 
  1307   {
  1308     XColor fore_color, back_color;
  1309 
  1310     fore_color.pixel = f->output_data.w32->mouse_pixel;
  1311     back_color.pixel = mask_color;
  1312     XQueryColor (FRAME_W32_DISPLAY (f),
  1313                  DefaultColormap (FRAME_W32_DISPLAY (f),
  1314                                   DefaultScreen (FRAME_W32_DISPLAY (f))),
  1315                  &fore_color);
  1316     XQueryColor (FRAME_W32_DISPLAY (f),
  1317                  DefaultColormap (FRAME_W32_DISPLAY (f),
  1318                                   DefaultScreen (FRAME_W32_DISPLAY (f))),
  1319                  &back_color);
  1320     XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
  1321                     &fore_color, &back_color);
  1322     XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
  1323                     &fore_color, &back_color);
  1324     XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
  1325                     &fore_color, &back_color);
  1326     XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor,
  1327                     &fore_color, &back_color);
  1328     XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
  1329                     &fore_color, &back_color);
  1330   }
  1331 
  1332   if (FRAME_W32_WINDOW (f) != 0)
  1333     XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
  1334 
  1335   if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
  1336     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
  1337   f->output_data.w32->text_cursor = cursor;
  1338 
  1339   if (nontext_cursor != f->output_data.w32->nontext_cursor
  1340       && f->output_data.w32->nontext_cursor != 0)
  1341     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
  1342   f->output_data.w32->nontext_cursor = nontext_cursor;
  1343 
  1344   if (hourglass_cursor != f->output_data.w32->hourglass_cursor
  1345       && f->output_data.w32->hourglass_cursor != 0)
  1346     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
  1347   f->output_data.w32->hourglass_cursor = hourglass_cursor;
  1348 
  1349   if (mode_cursor != f->output_data.w32->modeline_cursor
  1350       && f->output_data.w32->modeline_cursor != 0)
  1351     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
  1352   f->output_data.w32->modeline_cursor = mode_cursor;
  1353 
  1354   if (hand_cursor != f->output_data.w32->hand_cursor
  1355       && f->output_data.w32->hand_cursor != 0)
  1356     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor);
  1357   f->output_data.w32->hand_cursor = hand_cursor;
  1358 
  1359   XFlush (FRAME_W32_DISPLAY (f));
  1360   unblock_input ();
  1361 
  1362   update_face_from_frame_parameter (f, Qmouse_color, arg);
  1363 #endif /* TODO */
  1364 }
  1365 
  1366 static void
  1367 w32_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1368 {
  1369   unsigned long fore_pixel, pixel;
  1370 
  1371   if (!NILP (Vx_cursor_fore_pixel))
  1372     fore_pixel = w32_decode_color (f, Vx_cursor_fore_pixel,
  1373                                  WHITE_PIX_DEFAULT (f));
  1374   else
  1375     fore_pixel = FRAME_BACKGROUND_PIXEL (f);
  1376 
  1377   pixel = w32_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
  1378 
  1379   /* Make sure that the cursor color differs from the background color.  */
  1380   if (pixel == FRAME_BACKGROUND_PIXEL (f))
  1381     {
  1382       pixel = f->output_data.w32->mouse_pixel;
  1383       if (pixel == fore_pixel)
  1384         fore_pixel = FRAME_BACKGROUND_PIXEL (f);
  1385     }
  1386 
  1387   f->output_data.w32->cursor_foreground_pixel = fore_pixel;
  1388   f->output_data.w32->cursor_pixel = pixel;
  1389 
  1390   if (FRAME_W32_WINDOW (f) != 0)
  1391     {
  1392       block_input ();
  1393       /* Update frame's cursor_gc.  */
  1394       f->output_data.w32->cursor_gc->foreground = fore_pixel;
  1395       f->output_data.w32->cursor_gc->background = pixel;
  1396 
  1397       unblock_input ();
  1398 
  1399       if (FRAME_VISIBLE_P (f))
  1400         {
  1401           gui_update_cursor (f, 0);
  1402           gui_update_cursor (f, 1);
  1403         }
  1404     }
  1405 
  1406   update_face_from_frame_parameter (f, Qcursor_color, arg);
  1407 }
  1408 
  1409 /* Set the border-color of frame F to pixel value PIX.
  1410    Note that this does not fully take effect if done before
  1411    F has a window.  */
  1412 
  1413 static void
  1414 w32_set_border_pixel (struct frame *f, int pix)
  1415 {
  1416 
  1417   f->output_data.w32->border_pixel = pix;
  1418 
  1419   if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0)
  1420     {
  1421       if (FRAME_VISIBLE_P (f))
  1422         redraw_frame (f);
  1423     }
  1424 }
  1425 
  1426 /* Set the border-color of frame F to value described by ARG.
  1427    ARG can be a string naming a color.
  1428    The border-color is used for the border that is drawn by the server.
  1429    Note that this does not fully take effect if done before
  1430    F has a window; it must be redone when the window is created.  */
  1431 
  1432 static void
  1433 w32_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1434 {
  1435   int pix;
  1436 
  1437   CHECK_STRING (arg);
  1438   pix = w32_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
  1439   w32_set_border_pixel (f, pix);
  1440   update_face_from_frame_parameter (f, Qborder_color, arg);
  1441 }
  1442 
  1443 
  1444 static void
  1445 w32_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1446 {
  1447   set_frame_cursor_types (f, arg);
  1448 }
  1449 
  1450 static void
  1451 w32_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1452 {
  1453   bool result;
  1454 
  1455   if (NILP (arg) && NILP (oldval))
  1456     return;
  1457 
  1458   if (STRINGP (arg) && STRINGP (oldval)
  1459       && BASE_EQ (Fstring_equal (oldval, arg), Qt))
  1460     return;
  1461 
  1462   if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
  1463     return;
  1464 
  1465   block_input ();
  1466 
  1467   result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg);
  1468   if (result)
  1469     {
  1470       unblock_input ();
  1471       error ("No icon window available");
  1472     }
  1473 
  1474   unblock_input ();
  1475 }
  1476 
  1477 static void
  1478 w32_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1479 {
  1480   if (STRINGP (arg))
  1481     {
  1482       if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt))
  1483         return;
  1484     }
  1485   else if (!NILP (arg) || NILP (oldval))
  1486     return;
  1487 
  1488   fset_icon_name (f, arg);
  1489 
  1490 #if 0
  1491   if (f->output_data.w32->icon_bitmap != 0)
  1492     return;
  1493 
  1494   block_input ();
  1495 
  1496   result = x_text_icon (f,
  1497                         SSDATA ((!NILP (f->icon_name)
  1498                                  ? f->icon_name
  1499                                  : !NILP (f->title)
  1500                                  ? f->title
  1501                                  : f->name)));
  1502 
  1503   if (result)
  1504     {
  1505       unblock_input ();
  1506       error ("No icon window available");
  1507     }
  1508 
  1509   /* If the window was unmapped (and its icon was mapped),
  1510      the new icon is not mapped, so map the window in its stead.  */
  1511   if (FRAME_VISIBLE_P (f))
  1512     {
  1513 #ifdef USE_X_TOOLKIT
  1514       XtPopup (f->output_data.w32->widget, XtGrabNone);
  1515 #endif
  1516       XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
  1517     }
  1518 
  1519   XFlush (FRAME_W32_DISPLAY (f));
  1520   unblock_input ();
  1521 #endif
  1522 }
  1523 
  1524 /**
  1525  * w32_clear_under_internal_border:
  1526  *
  1527  * Clear area of frame F's internal border.  If the internal border face
  1528  * of F has been specified (is not null), fill the area with that face.
  1529  */
  1530 void
  1531 w32_clear_under_internal_border (struct frame *f)
  1532 {
  1533   int border = FRAME_INTERNAL_BORDER_WIDTH (f);
  1534 
  1535   /* Clear border if it's larger than before.  */
  1536   if (border != 0)
  1537     {
  1538       int width = FRAME_PIXEL_WIDTH (f);
  1539       int height = FRAME_PIXEL_HEIGHT (f);
  1540       int face_id =
  1541         (FRAME_PARENT_FRAME (f)
  1542          ? (!NILP (Vface_remapping_alist)
  1543             ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
  1544             : CHILD_FRAME_BORDER_FACE_ID)
  1545          : (!NILP (Vface_remapping_alist)
  1546             ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
  1547             : INTERNAL_BORDER_FACE_ID));
  1548       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  1549 
  1550       block_input ();
  1551       HDC hdc = get_frame_dc (f);
  1552       if (face)
  1553         {
  1554           /* Fill border with internal border face.  */
  1555           unsigned long color = face->background;
  1556 
  1557           w32_fill_area (f, hdc, color, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
  1558           w32_fill_area (f, hdc, color, 0, 0, border, height);
  1559           w32_fill_area (f, hdc, color, width - border, 0, border, height);
  1560           w32_fill_area (f, hdc, color, 0, height - border, width, border);
  1561         }
  1562       else
  1563         {
  1564           w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
  1565           w32_clear_area (f, hdc, 0, 0, border, height);
  1566           w32_clear_area (f, hdc, width - border, 0, border, height);
  1567           w32_clear_area (f, hdc, 0, height - border, width, border);
  1568         }
  1569       release_frame_dc (f, hdc);
  1570       unblock_input ();
  1571     }
  1572 }
  1573 
  1574 /**
  1575  * w32_set_child_frame_border_width:
  1576  *
  1577  * Set width of child frame F's internal border to ARG pixels.
  1578  * ARG < 0 is treated like ARG = 0.
  1579  */
  1580 static void
  1581 w32_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1582 {
  1583   int border;
  1584 
  1585   if (NILP (arg))
  1586     border = -1;
  1587   else if (RANGED_FIXNUMP (0, arg, INT_MAX))
  1588     border = XFIXNAT (arg);
  1589   else
  1590     signal_error ("Invalid child frame border width", arg);
  1591 
  1592   if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
  1593     {
  1594       f->child_frame_border_width = border;
  1595 
  1596       if (FRAME_NATIVE_WINDOW (f) != 0)
  1597         {
  1598           adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width);
  1599 
  1600           if (FRAME_VISIBLE_P (f))
  1601             w32_clear_under_internal_border (f);
  1602         }
  1603     }
  1604 }
  1605 
  1606 
  1607 /**
  1608  * w32_set_internal_border_width:
  1609  *
  1610  * Set width of frame F's internal border to ARG pixels.  ARG < 0 is
  1611  * treated like ARG = 0.
  1612  */
  1613 static void
  1614 w32_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1615 {
  1616   int argval = check_integer_range (arg, INT_MIN, INT_MAX);
  1617   int border = max (argval, 0);
  1618 
  1619   if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
  1620     {
  1621       f->internal_border_width = border;
  1622 
  1623       if (FRAME_NATIVE_WINDOW (f) != 0)
  1624         {
  1625           adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
  1626 
  1627           if (FRAME_VISIBLE_P (f))
  1628             w32_clear_under_internal_border (f);
  1629         }
  1630     }
  1631 }
  1632 
  1633 
  1634 /**
  1635  * w32_set_menu_bar_lines:
  1636  *
  1637  * Set number of lines of frame F's menu bar to VALUE.  An integer
  1638  * greater zero specifies 1 line and turns the menu bar on if it was off
  1639  * before.  Any other value specifies 0 lines and turns the menu bar off
  1640  * if it was on before.
  1641  */
  1642 static void
  1643 w32_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
  1644 {
  1645   /* Right now, menu bars don't work properly in minibuf-only frames;
  1646      most of the commands try to apply themselves to the minibuffer
  1647      frame itself, and get an error because you can't switch buffers in
  1648      or split the minibuffer window.  Child frames don't like menu bars
  1649      either.  */
  1650   if (!FRAME_MINIBUF_ONLY_P (f) && !FRAME_PARENT_FRAME (f))
  1651     {
  1652       boolean old = FRAME_EXTERNAL_MENU_BAR (f);
  1653       boolean new = (FIXNUMP (value) && XFIXNUM (value) > 0) ? true : false;
  1654 
  1655       FRAME_MENU_BAR_LINES (f) = 0;
  1656       FRAME_MENU_BAR_HEIGHT (f) = 0;
  1657 
  1658       if (old != new)
  1659         {
  1660           FRAME_EXTERNAL_MENU_BAR (f) = new;
  1661 
  1662           if (!old)
  1663             /* Make menu bar when there was none.  Emacs 25 waited until
  1664                the next redisplay for this to take effect.  */
  1665             set_frame_menubar (f, true);
  1666           else
  1667             {
  1668               /* Remove menu bar.  */
  1669               free_frame_menubar (f);
  1670 
  1671               /* Adjust the frame size so that the client (text) dimensions
  1672                  remain the same.  Note that we resize twice: The first time
  1673                  upon a request from the window manager who wants to keep
  1674                  the height of the outer rectangle (including decorations)
  1675                  unchanged, and a second time because we want to keep the
  1676                  height of the inner rectangle (without the decorations
  1677                  unchanged).  */
  1678               adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
  1679             }
  1680 
  1681           if (FRAME_W32_WINDOW (f))
  1682             w32_clear_under_internal_border (f);
  1683 
  1684           /* Don't store anything but 1 or 0 in the parameter.  */
  1685           store_frame_param (f, Qmenu_bar_lines, make_fixnum (new ? 1 : 0));
  1686         }
  1687     }
  1688 }
  1689 
  1690 
  1691 /* Set the number of lines used for the tab bar of frame F to VALUE.
  1692    VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL
  1693    is the old number of tab bar lines.  This function changes the
  1694    height of all windows on frame F to match the new tab bar height.
  1695    The frame's height doesn't change.  */
  1696 
  1697 static void
  1698 w32_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
  1699 {
  1700   int nlines;
  1701 
  1702   /* Treat tab bars like menu bars.  */
  1703   if (FRAME_MINIBUF_ONLY_P (f))
  1704     return;
  1705 
  1706   /* Use VALUE only if an int >= 0.  */
  1707   if (RANGED_FIXNUMP (0, value, INT_MAX))
  1708     nlines = XFIXNAT (value);
  1709   else
  1710     nlines = 0;
  1711 
  1712   w32_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
  1713 }
  1714 
  1715 
  1716 /* Set the pixel height of the tab bar of frame F to HEIGHT.  */
  1717 void
  1718 w32_change_tab_bar_height (struct frame *f, int height)
  1719 {
  1720   int unit = FRAME_LINE_HEIGHT (f);
  1721   int old_height = FRAME_TAB_BAR_HEIGHT (f);
  1722 
  1723   /* This differs from the tool bar code in that the tab bar height is
  1724      not rounded up.  Otherwise, if redisplay_tab_bar decides to grow
  1725      the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
  1726      leading to the tab bar height being incorrectly set upon the next
  1727      call to x_set_font.  (bug#59285) */
  1728   int lines = height / unit;
  1729   if (lines == 0 && height != 0)
  1730     lines = 1;
  1731 
  1732   /* Make sure we redisplay all windows in this frame.  */
  1733   fset_redisplay (f);
  1734 
  1735   /* Recalculate tab bar and frame text sizes.  */
  1736   FRAME_TAB_BAR_HEIGHT (f) = height;
  1737   FRAME_TAB_BAR_LINES (f) = lines;
  1738   /* Store the `tab-bar-lines' and `height' frame parameters.  */
  1739   store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
  1740   store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f)));
  1741 
  1742   /* We also have to make sure that the internal border at the top of
  1743      the frame, below the menu bar or tab bar, is redrawn when the
  1744      tab bar disappears.  This is so because the internal border is
  1745      below the tab bar if one is displayed, but is below the menu bar
  1746      if there isn't a tab bar.  The tab bar draws into the area
  1747      below the menu bar.  */
  1748   if (FRAME_W32_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
  1749     {
  1750       clear_frame (f);
  1751       clear_current_matrices (f);
  1752     }
  1753 
  1754   if ((height < old_height) && WINDOWP (f->tab_bar_window))
  1755     clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
  1756 
  1757   if (!f->tab_bar_resized)
  1758     {
  1759       Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
  1760 
  1761       /* As long as tab_bar_resized is false, effectively try to change
  1762          F's native height.  */
  1763       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
  1764         adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
  1765                            1, false, Qtab_bar_lines);
  1766       else
  1767         adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
  1768 
  1769       f->tab_bar_resized = f->tab_bar_redisplayed;
  1770     }
  1771   else
  1772     /* Any other change may leave the native size of F alone.  */
  1773     adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
  1774 
  1775   /* adjust_frame_size might not have done anything, garbage frame
  1776      here.  */
  1777   adjust_frame_glyphs (f);
  1778   SET_FRAME_GARBAGED (f);
  1779   if (FRAME_W32_WINDOW (f))
  1780     w32_clear_under_internal_border (f);
  1781 }
  1782 
  1783 
  1784 /* Set the number of lines used for the tool bar of frame F to VALUE.
  1785    VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL is
  1786    the old number of tool bar lines (and is unused).  This function may
  1787    change the height of all windows on frame F to match the new tool bar
  1788    height.  By design, the frame's height doesn't change (but maybe it
  1789    should if we don't get enough space otherwise).  */
  1790 
  1791 static void
  1792 w32_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
  1793 {
  1794   int nlines;
  1795 
  1796   /* Treat tool bars like menu bars.  */
  1797   if (FRAME_MINIBUF_ONLY_P (f))
  1798     return;
  1799 
  1800   /* Use VALUE only if an integer >= 0.  */
  1801   if (FIXNUMP (value) && XFIXNUM (value) >= 0)
  1802     nlines = XFIXNAT (value);
  1803   else
  1804     nlines = 0;
  1805 
  1806   w32_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
  1807 }
  1808 
  1809 /* Enable or disable double buffering on frame F.
  1810 
  1811    When double buffering is enabled, all drawing happens on a back
  1812    buffer (a bitmap), which is then displayed as a single operation
  1813    after redisplay is complete.  This avoids flicker caused by the
  1814    results of an incomplete redisplay becoming visible.  */
  1815 static void
  1816 w32_set_inhibit_double_buffering (struct frame *f,
  1817                                   Lisp_Object new_value,
  1818                                   /* This parameter is unused.  */
  1819                                   Lisp_Object old_value)
  1820 {
  1821   block_input ();
  1822 
  1823   if (NILP (new_value))
  1824     FRAME_OUTPUT_DATA (f)->want_paint_buffer = 1;
  1825   else
  1826     {
  1827       FRAME_OUTPUT_DATA (f)->want_paint_buffer = 0;
  1828       w32_release_paint_buffer (f);
  1829 
  1830       SET_FRAME_GARBAGED (f);
  1831     }
  1832 
  1833   unblock_input ();
  1834 }
  1835 
  1836 /* Set the pixel height of the tool bar of frame F to HEIGHT.  */
  1837 void
  1838 w32_change_tool_bar_height (struct frame *f, int height)
  1839 {
  1840   int unit = FRAME_LINE_HEIGHT (f);
  1841   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
  1842   int lines = (height + unit - 1) / unit;
  1843   Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
  1844 
  1845   /* Make sure we redisplay all windows in this frame.  */
  1846   windows_or_buffers_changed = 23;
  1847 
  1848   /* Recalculate tool bar and frame text sizes.  */
  1849   FRAME_TOOL_BAR_HEIGHT (f) = height;
  1850   FRAME_TOOL_BAR_LINES (f) = lines;
  1851   /* Store `tool-bar-lines' and `height' frame parameters.  */
  1852   store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
  1853   store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f)));
  1854 
  1855   if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
  1856     {
  1857       clear_frame (f);
  1858       clear_current_matrices (f);
  1859     }
  1860 
  1861   if ((height < old_height) && WINDOWP (f->tool_bar_window))
  1862     clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
  1863 
  1864   if (!f->tool_bar_resized)
  1865     {
  1866       /* As long as tool_bar_resized is false, effectively try to change
  1867          F's native height.  */
  1868       if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
  1869         adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
  1870                            1, false, Qtool_bar_lines);
  1871       else
  1872         adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines);
  1873 
  1874       f->tool_bar_resized =  f->tool_bar_redisplayed;
  1875     }
  1876   else
  1877     /* Any other change may leave the native size of F alone.  */
  1878     adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines);
  1879 
  1880   /* adjust_frame_size might not have done anything, garbage frame
  1881      here.  */
  1882   adjust_frame_glyphs (f);
  1883   SET_FRAME_GARBAGED (f);
  1884   if (FRAME_W32_WINDOW (f))
  1885     w32_clear_under_internal_border (f);
  1886 }
  1887 
  1888 static void
  1889 w32_set_title_bar_text (struct frame *f, Lisp_Object name)
  1890 {
  1891   if (FRAME_W32_WINDOW (f))
  1892     {
  1893       block_input ();
  1894 #ifdef __CYGWIN__
  1895       GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f),
  1896                               GUI_SDATA (GUI_ENCODE_SYSTEM (name)));
  1897 #else
  1898       /* The frame's title many times shows the name of the file
  1899          visited in the selected window's buffer, so it makes sense to
  1900          support non-ASCII characters outside of the current system
  1901          codepage in the title.  */
  1902       if (w32_unicode_filenames)
  1903         {
  1904           Lisp_Object encoded_title = ENCODE_UTF_8 (name);
  1905           wchar_t *title_w;
  1906           int tlen = pMultiByteToWideChar (CP_UTF8, 0, SSDATA (encoded_title),
  1907                                            -1, NULL, 0);
  1908 
  1909           if (tlen > 0)
  1910             {
  1911               /* Windows truncates the title text beyond what fits on
  1912                  a single line, so we can limit the length to some
  1913                  reasonably large value, and use alloca.  */
  1914               if (tlen > 10000)
  1915                 tlen = 10000;
  1916               title_w = alloca ((tlen + 1) * sizeof (wchar_t));
  1917               pMultiByteToWideChar (CP_UTF8, 0, SSDATA (encoded_title), -1,
  1918                                     title_w, tlen);
  1919               title_w[tlen] = L'\0';
  1920               SetWindowTextW (FRAME_W32_WINDOW (f), title_w);
  1921             }
  1922           else  /* Conversion to UTF-16 failed, so we punt.  */
  1923             SetWindowTextA (FRAME_W32_WINDOW (f),
  1924                             SSDATA (ENCODE_SYSTEM (name)));
  1925         }
  1926       else
  1927         SetWindowTextA (FRAME_W32_WINDOW (f), SSDATA (ENCODE_SYSTEM (name)));
  1928 #endif
  1929       unblock_input ();
  1930     }
  1931 }
  1932 
  1933 /* Change the name of frame F to NAME.  If NAME is nil, set F's name to
  1934        w32_id_name.
  1935 
  1936    If EXPLICIT is non-zero, that indicates that lisp code is setting the
  1937        name; if NAME is a string, set F's name to NAME and set
  1938        F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
  1939 
  1940    If EXPLICIT is zero, that indicates that Emacs redisplay code is
  1941        suggesting a new name, which lisp code should override; if
  1942        F->explicit_name is set, ignore the new name; otherwise, set it.  */
  1943 
  1944 static void
  1945 w32_set_name (struct frame *f, Lisp_Object name, bool explicit)
  1946 {
  1947   /* Make sure that requests from lisp code override requests from
  1948      Emacs redisplay code.  */
  1949   if (explicit)
  1950     {
  1951       /* If we're switching from explicit to implicit, we had better
  1952          update the mode lines and thereby update the title.  */
  1953       if (f->explicit_name && NILP (name))
  1954         update_mode_lines = 25;
  1955 
  1956       f->explicit_name = ! NILP (name);
  1957     }
  1958   else if (f->explicit_name)
  1959     return;
  1960 
  1961   /* If NAME is nil, set the name to the w32_id_name.  */
  1962   if (NILP (name))
  1963     {
  1964       /* Check for no change needed in this very common case
  1965          before we do any consing.  */
  1966       if (!strcmp (FRAME_DISPLAY_INFO (f)->w32_id_name,
  1967                    SSDATA (f->name)))
  1968         return;
  1969       name = build_string (FRAME_DISPLAY_INFO (f)->w32_id_name);
  1970     }
  1971   else
  1972     CHECK_STRING (name);
  1973 
  1974   /* Don't change the name if it's already NAME.  */
  1975   if (! NILP (Fstring_equal (name, f->name)))
  1976     return;
  1977 
  1978   fset_name (f, name);
  1979 
  1980   /* For setting the frame title, the title parameter should override
  1981      the name parameter.  */
  1982   if (! NILP (f->title))
  1983     name = f->title;
  1984 
  1985   w32_set_title_bar_text (f, name);
  1986 }
  1987 
  1988 /* This function should be called when the user's lisp code has
  1989    specified a name for the frame; the name will override any set by the
  1990    redisplay code.  */
  1991 static void
  1992 w32_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  1993 {
  1994   w32_set_name (f, arg, true);
  1995 }
  1996 
  1997 /* This function should be called by Emacs redisplay code to set the
  1998    name; names set this way will never override names set by the user's
  1999    lisp code.  */
  2000 void
  2001 w32_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
  2002 {
  2003   w32_set_name (f, arg, false);
  2004 }
  2005 
  2006 /* Change the title of frame F to NAME.
  2007    If NAME is nil, use the frame name as the title.  */
  2008 
  2009 static void
  2010 w32_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
  2011 {
  2012   /* Don't change the title if it's already NAME.  */
  2013   if (EQ (name, f->title))
  2014     return;
  2015 
  2016   update_mode_lines = 26;
  2017 
  2018   fset_title (f, name);
  2019 
  2020   if (NILP (name))
  2021     name = f->name;
  2022 
  2023   w32_set_title_bar_text (f, name);
  2024 }
  2025 
  2026 void
  2027 w32_set_scroll_bar_default_width (struct frame *f)
  2028 {
  2029   int unit = FRAME_COLUMN_WIDTH (f);
  2030 
  2031   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
  2032   FRAME_CONFIG_SCROLL_BAR_COLS (f)
  2033     = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
  2034 }
  2035 
  2036 
  2037 void
  2038 w32_set_scroll_bar_default_height (struct frame *f)
  2039 {
  2040   int unit = FRAME_LINE_HEIGHT (f);
  2041 
  2042   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
  2043   FRAME_CONFIG_SCROLL_BAR_LINES (f)
  2044     = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
  2045 }
  2046 
  2047 /**
  2048  * w32_set_undecorated:
  2049  *
  2050  * Set frame F's `undecorated' parameter.  If non-nil, F's window-system
  2051  * window is drawn without decorations, title, minimize/maximize boxes
  2052  * and external borders.  This usually means that the window cannot be
  2053  * dragged, resized, iconified, maximized or deleted with the mouse.  If
  2054  * nil, draw the frame with all the elements listed above unless these
  2055  * have been suspended via window manager settings.
  2056  *
  2057  * Some window managers may not honor this parameter.
  2058  */
  2059 static void
  2060 w32_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2061 {
  2062   HWND hwnd = FRAME_W32_WINDOW (f);
  2063   DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
  2064   Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
  2065 
  2066   block_input ();
  2067   if (!NILP (new_value) && !FRAME_UNDECORATED (f))
  2068     {
  2069       dwStyle = ((dwStyle & ~WS_THICKFRAME & ~WS_CAPTION)
  2070                  | ((FIXNUMP (border_width) && (XFIXNUM (border_width) > 0))
  2071                     ? WS_BORDER : false));
  2072       SetWindowLong (hwnd, GWL_STYLE, dwStyle);
  2073       SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
  2074                     SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
  2075                     | SWP_FRAMECHANGED);
  2076       FRAME_UNDECORATED (f) = true;
  2077     }
  2078   else if (NILP (new_value) && FRAME_UNDECORATED (f))
  2079     {
  2080       SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_CAPTION
  2081                      | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU);
  2082       SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
  2083                     SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
  2084                     | SWP_FRAMECHANGED);
  2085       FRAME_UNDECORATED (f) = false;
  2086     }
  2087 
  2088   f->output_data.w32->dwStyle = GetWindowLong (hwnd, GWL_STYLE);
  2089 
  2090   unblock_input ();
  2091 }
  2092 
  2093 /**
  2094  * w32_set_parent_frame:
  2095  *
  2096  * Set frame F's `parent-frame' parameter.  If non-nil, make F a child
  2097  * frame of the frame specified by that parameter.  Technically, this
  2098  * makes F's window-system window a child window of the parent frame's
  2099  * window-system window.  If nil, make F's window-system window a
  2100  * top-level window--a child of its display's root window.
  2101  *
  2102  * A child frame is clipped at the native edges of its parent frame.
  2103  * Its `left' and `top' parameters specify positions relative to the
  2104  * top-left corner of its parent frame's native rectangle.  Usually,
  2105  * moving a parent frame moves all its child frames too, keeping their
  2106  * position relative to the parent unaltered.  When a parent frame is
  2107  * iconified or made invisible, its child frames are made invisible.
  2108  * When a parent frame is deleted, its child frames are deleted too.
  2109  *
  2110  * A visible child frame always appears on top of its parent frame thus
  2111  * obscuring parts of it.  When a frame has more than one child frame,
  2112  * their stacking order is specified just as that of non-child frames
  2113  * relative to their display.
  2114  *
  2115  * Whether a child frame has a menu or tool bar may be window-system or
  2116  * window manager dependent.  It's advisable to disable both via the
  2117  * frame parameter settings.
  2118  *
  2119  * Some window managers may not honor this parameter.
  2120  */
  2121 static void
  2122 w32_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2123 {
  2124   struct frame *p = NULL;
  2125 
  2126   if (!NILP (new_value)
  2127       && (!FRAMEP (new_value)
  2128           || !FRAME_LIVE_P (p = XFRAME (new_value))
  2129           || !FRAME_W32_P (p)))
  2130     {
  2131       store_frame_param (f, Qparent_frame, old_value);
  2132       error ("Invalid specification of `parent-frame'");
  2133     }
  2134 
  2135   if (p != FRAME_PARENT_FRAME (f))
  2136     {
  2137       HWND hwnd = FRAME_W32_WINDOW (f);
  2138       HWND hwnd_parent = p ? FRAME_W32_WINDOW (p) : NULL;
  2139       HWND hwnd_value;
  2140 
  2141       block_input ();
  2142       hwnd_value = SetParent (hwnd, hwnd_parent);
  2143       unblock_input ();
  2144 
  2145       if (hwnd_value)
  2146         fset_parent_frame (f, new_value);
  2147       else
  2148         {
  2149           store_frame_param (f, Qparent_frame, old_value);
  2150           error ("Reparenting frame failed");
  2151         }
  2152     }
  2153 }
  2154 
  2155 /**
  2156  * w32_set_skip_taskbar:
  2157  *
  2158  * Set frame F's `skip-taskbar' parameter.  If non-nil, this should
  2159  * remove F's icon from the taskbar associated with the display of F's
  2160  * window-system window and inhibit switching to F's window via
  2161  * <Alt>-<TAB>.  On Windows iconifying F will "roll in" its window at
  2162  * the bottom of the desktop.  If nil, lift these restrictions.
  2163  *
  2164  * Some window managers may not honor this parameter.
  2165  */
  2166 static void
  2167 w32_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2168 {
  2169   if (!EQ (new_value, old_value))
  2170     {
  2171       HWND hwnd = FRAME_W32_WINDOW (f);
  2172       DWORD exStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
  2173 
  2174       block_input ();
  2175       /* Temporarily hide the window while changing its WS_EX_NOACTIVATE
  2176          setting.  */
  2177       ShowWindow (hwnd, SW_HIDE);
  2178       if (!NILP (new_value))
  2179         SetWindowLong (hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
  2180       else
  2181         SetWindowLong (hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
  2182       ShowWindow (hwnd, SW_SHOWNOACTIVATE);
  2183       unblock_input ();
  2184 
  2185       FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
  2186     }
  2187 }
  2188 
  2189 /**
  2190  * w32_set_no_focus_on_map:
  2191  *
  2192  * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
  2193  * that F's window-system window does not want to receive input focus
  2194  * when it is mapped.  (A frame's window is mapped when the frame is
  2195  * displayed for the first time and when the frame changes its state
  2196  * from `iconified' or `invisible' to `visible'.)
  2197  *
  2198  * Some window managers may not honor this parameter.
  2199  */
  2200 static void
  2201 w32_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2202 {
  2203   if (!EQ (new_value, old_value))
  2204     FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
  2205 }
  2206 
  2207 /**
  2208  * w32_set_no_accept_focus:
  2209  *
  2210  * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
  2211  * that F's window-system window does not want to receive input focus
  2212  * via mouse clicks or by moving the mouse into it.
  2213  *
  2214  * If non-nil, this may have the unwanted side-effect that a user cannot
  2215  * scroll a non-selected frame with the mouse.
  2216  *
  2217  * Some window managers may not honor this parameter.
  2218  */
  2219 static void
  2220 w32_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2221 {
  2222   if (!EQ (new_value, old_value))
  2223     FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
  2224 }
  2225 
  2226 /**
  2227  * w32_set_z_group:
  2228  *
  2229  * Set frame F's `z-group' parameter.  If `above', F's window-system
  2230  * window is displayed above all windows that do not have the `above'
  2231  * property set.  If nil, F's window is shown below all windows that
  2232  * have the `above' property set and above all windows that have the
  2233  * `below' property set.  If `below', F's window is displayed below all
  2234  * windows that do not have the `below' property set.
  2235  *
  2236  * Some window managers may not honor this parameter.  The value `below'
  2237  * is not supported on Windows.
  2238  *
  2239  * Internally, this function also handles a value 'above-suspended'.
  2240  * That value is used to temporarily remove F from the 'above' group
  2241  * to make sure that it does not obscure the window of a dialog in
  2242  * progress.
  2243  */
  2244 static void
  2245 w32_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  2246 {
  2247   HWND hwnd = FRAME_W32_WINDOW (f);
  2248 
  2249   if (NILP (new_value))
  2250     {
  2251       block_input ();
  2252       SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  2253                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
  2254                     | SWP_NOOWNERZORDER);
  2255       unblock_input ();
  2256       FRAME_Z_GROUP (f) = z_group_none;
  2257     }
  2258   else if (EQ (new_value, Qabove))
  2259     {
  2260       block_input ();
  2261       SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
  2262                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
  2263                     | SWP_NOOWNERZORDER);
  2264       unblock_input ();
  2265       FRAME_Z_GROUP (f) = z_group_above;
  2266     }
  2267   else if (EQ (new_value, Qabove_suspended))
  2268     {
  2269       block_input ();
  2270       SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  2271                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
  2272                     | SWP_NOOWNERZORDER);
  2273       unblock_input ();
  2274       FRAME_Z_GROUP (f) = z_group_above_suspended;
  2275     }
  2276   else if (EQ (new_value, Qbelow))
  2277     error ("Value `below' for z-group is not supported on Windows");
  2278   else
  2279     error ("Invalid z-group specification");
  2280 }
  2281 
  2282 /* Subroutines for creating a frame.  */
  2283 
  2284 HCURSOR w32_load_cursor (LPCTSTR);
  2285 
  2286 HCURSOR
  2287 w32_load_cursor (LPCTSTR name)
  2288 {
  2289   /* Try first to load cursor from application resource.  */
  2290   HCURSOR cursor = LoadImage ((HINSTANCE) GetModuleHandle (NULL),
  2291                               name, IMAGE_CURSOR, 0, 0,
  2292                               LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
  2293   if (!cursor)
  2294     {
  2295       /* Then try to load a shared predefined cursor.  */
  2296       cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
  2297                           LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
  2298     }
  2299   return cursor;
  2300 }
  2301 
  2302 static LRESULT CALLBACK w32_wnd_proc (HWND, UINT, WPARAM, LPARAM);
  2303 
  2304 #define INIT_WINDOW_CLASS(WC)                     \
  2305   (WC).style = CS_HREDRAW | CS_VREDRAW;           \
  2306   (WC).lpfnWndProc = (WNDPROC) w32_wnd_proc;      \
  2307   (WC).cbClsExtra = 0;                            \
  2308   (WC).cbWndExtra = WND_EXTRA_BYTES;              \
  2309   (WC).hInstance = hinst;                         \
  2310   (WC).hIcon = LoadIcon (hinst, EMACS_CLASS);     \
  2311   (WC).hCursor = w32_load_cursor (IDC_ARROW);     \
  2312   (WC).hbrBackground = NULL;                      \
  2313   (WC).lpszMenuName = NULL;                       \
  2314 
  2315 static BOOL
  2316 w32_init_class (HINSTANCE hinst)
  2317 {
  2318   if (w32_unicode_gui)
  2319     {
  2320       WNDCLASSW  uwc;
  2321       INIT_WINDOW_CLASS(uwc);
  2322       uwc.lpszClassName = L"Emacs";
  2323 
  2324       return RegisterClassW (&uwc);
  2325     }
  2326   else
  2327     {
  2328       WNDCLASS  wc;
  2329       INIT_WINDOW_CLASS(wc);
  2330       wc.lpszClassName = EMACS_CLASS;
  2331 
  2332       return RegisterClassA (&wc);
  2333     }
  2334 }
  2335 
  2336 /* Applies the Windows system theme (light or dark) to the window
  2337    handle HWND.  */
  2338 static void
  2339 w32_applytheme (HWND hwnd)
  2340 {
  2341   if (w32_darkmode)
  2342     {
  2343       /* Set window theme to that of a built-in Windows app (Explorer),
  2344          because it has dark scroll bars and other UI elements.  */
  2345       if (SetWindowTheme_fn)
  2346         SetWindowTheme_fn (hwnd, DARK_MODE_APP_NAME, NULL);
  2347 
  2348       /* Set the titlebar to system dark mode.  */
  2349       if (DwmSetWindowAttribute_fn)
  2350         {
  2351           /* Windows 10 version 2004 and up, Windows 11.  */
  2352           DWORD attr = DWMWA_USE_IMMERSIVE_DARK_MODE;
  2353           /* Windows 10 older than 2004.  */
  2354           if (w32_build_number < 19041)
  2355             attr = DWMWA_USE_IMMERSIVE_DARK_MODE_OLD;
  2356           DwmSetWindowAttribute_fn (hwnd, attr,
  2357                                     &w32_darkmode, sizeof (w32_darkmode));
  2358         }
  2359     }
  2360 }
  2361 
  2362 static HWND
  2363 w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
  2364 {
  2365   HWND hwnd = CreateWindow ("SCROLLBAR", "",
  2366                        /* Clip siblings so we don't draw over child
  2367                           frames.  Apparently this is not always
  2368                           sufficient so we also try to make bar windows
  2369                           bottommost.  */
  2370                        SBS_VERT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  2371                        /* Position and size of scroll bar.  */
  2372                        bar->left, bar->top, bar->width, bar->height,
  2373                        FRAME_W32_WINDOW (f), NULL, hinst, NULL);
  2374   if (hwnd)
  2375     w32_applytheme (hwnd);
  2376   return hwnd;
  2377 }
  2378 
  2379 static HWND
  2380 w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
  2381 {
  2382   HWND hwnd = CreateWindow ("SCROLLBAR", "",
  2383                        /* Clip siblings so we don't draw over child
  2384                           frames.  Apparently this is not always
  2385                           sufficient so we also try to make bar windows
  2386                           bottommost.  */
  2387                        SBS_HORZ | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  2388                        /* Position and size of scroll bar.  */
  2389                        bar->left, bar->top, bar->width, bar->height,
  2390                        FRAME_W32_WINDOW (f), NULL, hinst, NULL);
  2391   if (hwnd)
  2392     w32_applytheme (hwnd);
  2393   return hwnd;
  2394 }
  2395 
  2396 static void
  2397 w32_createwindow (struct frame *f, int *coords)
  2398 {
  2399   HWND hwnd = NULL, parent_hwnd = NULL;
  2400   RECT rect;
  2401   int top, left;
  2402   Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
  2403 
  2404   if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
  2405     {
  2406       parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
  2407       f->output_data.w32->dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
  2408 
  2409       if (FRAME_UNDECORATED (f))
  2410         {
  2411           /* If we want a thin border, specify it here.  */
  2412           if (FIXNUMP (border_width) && (XFIXNUM (border_width) > 0))
  2413             f->output_data.w32->dwStyle |= WS_BORDER;
  2414         }
  2415       else
  2416         /* To decorate a child frame, list all needed elements.  */
  2417         f->output_data.w32->dwStyle |= (WS_THICKFRAME | WS_CAPTION
  2418                                         | WS_MAXIMIZEBOX | WS_MINIMIZEBOX
  2419                                         | WS_SYSMENU);
  2420     }
  2421   else if (FRAME_UNDECORATED (f))
  2422     {
  2423       /* All attempts to start with ~WS_OVERLAPPEDWINDOW or overlapped
  2424          with all other style elements negated failed here.  */
  2425       f->output_data.w32->dwStyle = WS_POPUP;
  2426 
  2427       /* If we want a thin border, specify it here.  */
  2428       if (FIXNUMP (border_width) && (XFIXNUM (border_width) > 0))
  2429         f->output_data.w32->dwStyle |= WS_BORDER;
  2430     }
  2431   else
  2432     f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
  2433 
  2434   /* Always clip children.  */
  2435   f->output_data.w32->dwStyle |= WS_CLIPCHILDREN;
  2436 
  2437   rect.left = rect.top = 0;
  2438   rect.right = FRAME_PIXEL_WIDTH (f);
  2439   rect.bottom = FRAME_PIXEL_HEIGHT (f);
  2440 
  2441   AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
  2442                     FRAME_EXTERNAL_MENU_BAR (f) && !parent_hwnd);
  2443 
  2444   /* Do first time app init */
  2445   w32_init_class (hinst);
  2446 
  2447   if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
  2448     {
  2449       left = f->left_pos;
  2450       top = f->top_pos;
  2451     }
  2452   else
  2453     {
  2454       left = coords[0];
  2455       top = coords[1];
  2456     }
  2457 
  2458   FRAME_W32_WINDOW (f) = hwnd
  2459     = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
  2460                     left, top, rect.right - rect.left, rect.bottom - rect.top,
  2461                     parent_hwnd, NULL, hinst, NULL);
  2462 
  2463   if (hwnd)
  2464     {
  2465       if (FRAME_SKIP_TASKBAR (f))
  2466         SetWindowLong (hwnd, GWL_EXSTYLE,
  2467                        GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
  2468 
  2469       SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
  2470       SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
  2471       SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
  2472       SetWindowLong (hwnd, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
  2473       SetWindowLong (hwnd, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
  2474       SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
  2475 
  2476       /* Enable drag-n-drop.  */
  2477       DragAcceptFiles (hwnd, TRUE);
  2478 
  2479       /* Enable system light/dark theme.  */
  2480       w32_applytheme (hwnd);
  2481 
  2482       /* Do this to discard the default setting specified by our parent. */
  2483       ShowWindow (hwnd, SW_HIDE);
  2484 
  2485       /* Update frame positions. */
  2486       GetWindowRect (hwnd, &rect);
  2487 
  2488       if (parent_hwnd)
  2489         /* For a child window we have to get its coordinates wrt its
  2490            parent.  */
  2491         MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
  2492 
  2493       f->left_pos = rect.left;
  2494       f->top_pos = rect.top;
  2495     }
  2496 }
  2497 
  2498 static void
  2499 my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2500 {
  2501   wmsg->msg.hwnd = hwnd;
  2502   wmsg->msg.message = msg;
  2503   wmsg->msg.wParam = wParam;
  2504   wmsg->msg.lParam = lParam;
  2505   wmsg->msg.time = GetMessageTime ();
  2506 
  2507   post_msg (wmsg);
  2508 }
  2509 
  2510 #ifdef WINDOWSNT
  2511 /* The Windows keyboard hook callback.  */
  2512 static LRESULT CALLBACK
  2513 funhook (int code, WPARAM w, LPARAM l)
  2514 {
  2515   INPUT inputs[2];
  2516   HWND focus = GetFocus ();
  2517   int console = 0;
  2518   KBDLLHOOKSTRUCT const *hs = (KBDLLHOOKSTRUCT*)l;
  2519 
  2520   if (code < 0 || (hs->flags & LLKHF_INJECTED))
  2521     return CallNextHookEx (0, code, w, l);
  2522 
  2523   /* The keyboard hook sees keyboard input on all processes (except
  2524      elevated ones, when Emacs itself is not elevated).  As such,
  2525      care must be taken to only filter out keyboard input when Emacs
  2526      itself is on the foreground.
  2527 
  2528      GetFocus returns a non-NULL window if another application is active,
  2529      and always for a console Emacs process.  For a console Emacs, determine
  2530      focus by checking if the current foreground window is the process's
  2531      console window.  */
  2532   if (focus == NULL && kbdhook.console != NULL)
  2533     {
  2534       if (GetForegroundWindow () == kbdhook.console)
  2535         {
  2536           focus = kbdhook.console;
  2537           console = 1;
  2538         }
  2539     }
  2540 
  2541   /* First, check hooks for the left and right Windows keys.  */
  2542   if (hs->vkCode == VK_LWIN || hs->vkCode == VK_RWIN)
  2543     {
  2544       if (focus != NULL && (w == WM_KEYDOWN || w == WM_SYSKEYDOWN))
  2545         {
  2546           /* The key is being pressed in an Emacs window.  */
  2547           if (hs->vkCode == VK_LWIN && !kbdhook.lwindown)
  2548             {
  2549               kbdhook.lwindown = 1;
  2550               kbdhook.winseen = 1;
  2551               kbdhook.winsdown++;
  2552             }
  2553           else if (hs->vkCode == VK_RWIN && !kbdhook.rwindown)
  2554             {
  2555               kbdhook.rwindown = 1;
  2556               kbdhook.winseen = 1;
  2557               kbdhook.winsdown++;
  2558             }
  2559           /* Returning 1 here drops the keypress without further processing.
  2560              If the keypress was allowed to go through, the normal Windows
  2561              hotkeys would take over.  */
  2562           return 1;
  2563         }
  2564       else if (kbdhook.winsdown > 0 && (w == WM_KEYUP || w == WM_SYSKEYUP))
  2565         {
  2566           /* A key that has been captured earlier is being released now.  */
  2567           if (hs->vkCode == VK_LWIN && kbdhook.lwindown)
  2568             {
  2569               kbdhook.lwindown = 0;
  2570               kbdhook.winsdown--;
  2571             }
  2572           else if (hs->vkCode == VK_RWIN && kbdhook.rwindown)
  2573             {
  2574               kbdhook.rwindown = 0;
  2575               kbdhook.winsdown--;
  2576             }
  2577           if (kbdhook.winsdown == 0 && kbdhook.winseen)
  2578             {
  2579               if (!kbdhook.suppress_lone)
  2580                 {
  2581                   /* The Windows key was pressed, then released,
  2582                      without any other key pressed simultaneously.
  2583                      Normally, this opens the Start menu, but the user
  2584                      can prevent this by setting the
  2585                      w32-pass-[lr]window-to-system variable to
  2586                      NIL.  */
  2587                   if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) ||
  2588                       (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
  2589                     {
  2590                       /* Not prevented - Simulate the keypress to the system.  */
  2591                       memset (inputs, 0, sizeof (inputs));
  2592                       inputs[0].type = INPUT_KEYBOARD;
  2593                       inputs[0].ki.wVk = hs->vkCode;
  2594                       inputs[0].ki.wScan = hs->vkCode;
  2595                       inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
  2596                       inputs[0].ki.time = 0;
  2597                       inputs[1].type = INPUT_KEYBOARD;
  2598                       inputs[1].ki.wVk = hs->vkCode;
  2599                       inputs[1].ki.wScan = hs->vkCode;
  2600                       inputs[1].ki.dwFlags
  2601                         = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
  2602                       inputs[1].ki.time = 0;
  2603                       SendInput (2, inputs, sizeof (INPUT));
  2604                     }
  2605                   else if (focus != NULL)
  2606                     {
  2607                       /* When not passed to system, must simulate privately to Emacs.    */
  2608                       PostMessage (focus, WM_SYSKEYDOWN, hs->vkCode, 0);
  2609                       PostMessage (focus, WM_SYSKEYUP, hs->vkCode, 0);
  2610                     }
  2611                 }
  2612             }
  2613           if (kbdhook.winsdown == 0)
  2614             {
  2615               /* No Windows keys pressed anymore - clear the state flags.  */
  2616               kbdhook.suppress_lone = 0;
  2617               kbdhook.winseen = 0;
  2618             }
  2619           if (!kbdhook.send_win_up)
  2620             {
  2621               /* Swallow this release message, as not to confuse
  2622                  applications who did not get to see the original
  2623                  WM_KEYDOWN message either.  */
  2624               return 1;
  2625             }
  2626           kbdhook.send_win_up = 0;
  2627         }
  2628     }
  2629   else if (kbdhook.winsdown > 0)
  2630     {
  2631       /* Some other key was pressed while a captured Win key is down.
  2632          This is either an Emacs registered hotkey combination, or a
  2633          system hotkey.  */
  2634       if ((kbdhook.lwindown && kbdhook.lwin_hooked[hs->vkCode]) ||
  2635           (kbdhook.rwindown && kbdhook.rwin_hooked[hs->vkCode]))
  2636         {
  2637           /* Hooked Win-x combination, do not pass the keypress to Windows.  */
  2638           kbdhook.suppress_lone = 1;
  2639         }
  2640       else if (!kbdhook.suppress_lone)
  2641         {
  2642           /* Unhooked S-x combination; simulate the combination now
  2643              (will be seen by the system).  */
  2644           memset (inputs, 0, sizeof (inputs));
  2645           inputs[0].type = INPUT_KEYBOARD;
  2646           inputs[0].ki.wVk = kbdhook.lwindown ? VK_LWIN : VK_RWIN;
  2647           inputs[0].ki.wScan = kbdhook.lwindown ? VK_LWIN : VK_RWIN;
  2648           inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
  2649           inputs[0].ki.time = 0;
  2650           inputs[1].type = INPUT_KEYBOARD;
  2651           inputs[1].ki.wVk = hs->vkCode;
  2652           inputs[1].ki.wScan = hs->scanCode;
  2653           inputs[1].ki.dwFlags =
  2654             (hs->flags & LLKHF_EXTENDED) ? KEYEVENTF_EXTENDEDKEY : 0;
  2655           inputs[1].ki.time = 0;
  2656           SendInput (2, inputs, sizeof (INPUT));
  2657           /* Stop processing of this Win sequence here; the
  2658              corresponding keyup messages will come through the normal
  2659              channel when the keys are released.  */
  2660           kbdhook.suppress_lone = 1;
  2661           kbdhook.send_win_up = 1;
  2662           /* Swallow the original keypress (as we want the Win key
  2663              down message simulated above to precede this real message).  */
  2664           return 1;
  2665         }
  2666     }
  2667 
  2668   /* Next, handle the registered Alt-* combinations.  */
  2669   if ((w == WM_SYSKEYDOWN || w == WM_KEYDOWN)
  2670       && kbdhook.alt_hooked[hs->vkCode]
  2671       && focus != NULL
  2672       && (GetAsyncKeyState (VK_MENU) & 0x8000))
  2673     {
  2674       /* Prevent the system from getting this Alt-* key - suppress the
  2675          message and post as a normal keypress to Emacs.  */
  2676       if (console)
  2677         {
  2678           INPUT_RECORD rec;
  2679           DWORD n;
  2680           rec.EventType = KEY_EVENT;
  2681           rec.Event.KeyEvent.bKeyDown = TRUE;
  2682           rec.Event.KeyEvent.wVirtualKeyCode = hs->vkCode;
  2683           rec.Event.KeyEvent.wVirtualScanCode = hs->scanCode;
  2684           rec.Event.KeyEvent.uChar.UnicodeChar = 0;
  2685           rec.Event.KeyEvent.dwControlKeyState =
  2686             ((GetAsyncKeyState (VK_LMENU) & 0x8000) ? LEFT_ALT_PRESSED : 0)
  2687             | ((GetAsyncKeyState (VK_RMENU) & 0x8000) ? RIGHT_ALT_PRESSED : 0)
  2688             | ((GetAsyncKeyState (VK_LCONTROL) & 0x8000) ? LEFT_CTRL_PRESSED : 0)
  2689             | ((GetAsyncKeyState (VK_RCONTROL) & 0x8000) ? RIGHT_CTRL_PRESSED : 0)
  2690             | ((GetAsyncKeyState (VK_SHIFT) & 0x8000) ? SHIFT_PRESSED : 0)
  2691             | ((hs->flags & LLKHF_EXTENDED) ? ENHANCED_KEY : 0);
  2692           if (w32_console_unicode_input)
  2693             WriteConsoleInputW (keyboard_handle, &rec, 1, &n);
  2694           else
  2695             WriteConsoleInputA (keyboard_handle, &rec, 1, &n);
  2696         }
  2697       else
  2698         PostMessage (focus, w, hs->vkCode, 1 | (1<<29));
  2699       return 1;
  2700     }
  2701 
  2702   /* The normal case - pass the message through.  */
  2703   return CallNextHookEx (0, code, w, l);
  2704 }
  2705 
  2706 /* Set up the hook; can be called several times, with matching
  2707    remove_w32_kbdhook calls.  */
  2708 void
  2709 setup_w32_kbdhook (void)
  2710 {
  2711   kbdhook.hook_count++;
  2712 
  2713   /* This hook gets in the way of debugging, since when Emacs stops,
  2714      its input thread stops, and there's nothing to process keyboard
  2715      events, whereas this hook is global, and is invoked in the
  2716      context of the thread that installed it.  So we don't install the
  2717      hook if the process is being debugged. */
  2718   if (w32_kbdhook_active)
  2719     {
  2720       if (is_debugger_present && is_debugger_present ())
  2721         return;
  2722     }
  2723 
  2724   /* Hooking is only available on NT architecture systems, as
  2725      indicated by the w32_kbdhook_active variable.  */
  2726   if (kbdhook.hook_count == 1 && w32_kbdhook_active)
  2727     {
  2728       /* Get the handle of the Emacs console window.  As the
  2729          GetConsoleWindow function is only available on Win2000+, a
  2730          hackish workaround described in Microsoft KB article 124103
  2731          (https://support.microsoft.com/en-us/kb/124103) is used for
  2732          NT 4 systems.  */
  2733       GetConsoleWindow_Proc get_console = (GetConsoleWindow_Proc)
  2734         get_proc_addr (GetModuleHandle ("kernel32.dll"), "GetConsoleWindow");
  2735 
  2736       if (get_console != NULL)
  2737         kbdhook.console = get_console ();
  2738       else
  2739         {
  2740           GUID guid;
  2741           wchar_t *oldTitle = malloc (1024 * sizeof(wchar_t));
  2742           wchar_t newTitle[64];
  2743           int i;
  2744 
  2745           CoCreateGuid (&guid);
  2746           if (oldTitle != NULL && StringFromGUID2 (&guid, newTitle, 64))
  2747             {
  2748               GetConsoleTitleW (oldTitle, 1024);
  2749               SetConsoleTitleW (newTitle);
  2750               for (i = 0; i < 25; i++)
  2751                 {
  2752                   Sleep (40);
  2753                   kbdhook.console = FindWindowW (NULL, newTitle);
  2754                   if (kbdhook.console != NULL)
  2755                     break;
  2756                 }
  2757               SetConsoleTitleW (oldTitle);
  2758             }
  2759           free (oldTitle);
  2760         }
  2761 
  2762       /* Set the hook.  */
  2763       kbdhook.hook = SetWindowsHookEx (WH_KEYBOARD_LL, funhook,
  2764                                        GetModuleHandle (NULL), 0);
  2765     }
  2766 }
  2767 
  2768 /* Remove the hook.  */
  2769 void
  2770 remove_w32_kbdhook (void)
  2771 {
  2772   kbdhook.hook_count--;
  2773   if (kbdhook.hook_count == 0 && w32_kbdhook_active)
  2774     {
  2775       UnhookWindowsHookEx (kbdhook.hook);
  2776       kbdhook.hook = NULL;
  2777     }
  2778 }
  2779 #endif  /* WINDOWSNT */
  2780 
  2781 /* Mark a specific key combination as hooked, preventing it to be
  2782    handled by the system.  */
  2783 static void
  2784 hook_w32_key (int hook, int modifier, int vkey)
  2785 {
  2786   char *tbl = NULL;
  2787 
  2788   switch (modifier)
  2789     {
  2790     case VK_MENU:
  2791       tbl = kbdhook.alt_hooked;
  2792       break;
  2793     case VK_LWIN:
  2794       tbl = kbdhook.lwin_hooked;
  2795       break;
  2796     case VK_RWIN:
  2797       tbl = kbdhook.rwin_hooked;
  2798       break;
  2799     }
  2800 
  2801   if (tbl != NULL && vkey >= 0 && vkey <= 255)
  2802     {
  2803        /* VK_ANY hooks all keys for this modifier */
  2804        if (vkey == VK_ANY)
  2805          memset (tbl, (char)hook, 256);
  2806        else
  2807          tbl[vkey] = (char)hook;
  2808        /* Alt-<modifier>s should go through */
  2809        kbdhook.alt_hooked[VK_MENU] = 0;
  2810        kbdhook.alt_hooked[VK_LMENU] = 0;
  2811        kbdhook.alt_hooked[VK_RMENU] = 0;
  2812        kbdhook.alt_hooked[VK_CONTROL] = 0;
  2813        kbdhook.alt_hooked[VK_LCONTROL] = 0;
  2814        kbdhook.alt_hooked[VK_RCONTROL] = 0;
  2815        kbdhook.alt_hooked[VK_SHIFT] = 0;
  2816        kbdhook.alt_hooked[VK_LSHIFT] = 0;
  2817        kbdhook.alt_hooked[VK_RSHIFT] = 0;
  2818     }
  2819 }
  2820 
  2821 #ifdef WINDOWSNT
  2822 /* Check the current Win key pressed state.  */
  2823 int
  2824 check_w32_winkey_state (int vkey)
  2825 {
  2826   /* The hook code handles grabbing of the Windows keys and Alt-* key
  2827      combinations reserved by the system.  Handling Alt is a bit
  2828      easier, as Windows intends Alt-* shortcuts for application use in
  2829      Windows; hotkeys such as Alt-tab and Alt-escape are special
  2830      cases.  Win-* hotkeys, on the other hand, are primarily meant for
  2831      system use.
  2832 
  2833      As a result, when we want Emacs to be able to grab the Win-*
  2834      keys, we must swallow all Win key presses in a low-level keyboard
  2835      hook.  Unfortunately, this means that the Emacs window procedure
  2836      (and console input handler) never see the keypresses either.
  2837      Thus, to check the modifier states properly, Emacs code must use
  2838      the check_w32_winkey_state function that uses the flags directly
  2839      updated by the hook callback.  */
  2840   switch (vkey)
  2841     {
  2842     case VK_LWIN:
  2843       return kbdhook.lwindown;
  2844     case VK_RWIN:
  2845       return kbdhook.rwindown;
  2846     }
  2847   return 0;
  2848 }
  2849 #endif  /* WINDOWSNT */
  2850 
  2851 /* Reset the keyboard hook state.  Locking the workstation with Win-L
  2852    leaves the Win key(s) "down" from the hook's point of view - the
  2853    keyup event is never seen.  Thus, this function must be called when
  2854    the system is locked.  */
  2855 static void
  2856 reset_w32_kbdhook_state (void)
  2857 {
  2858   kbdhook.lwindown = 0;
  2859   kbdhook.rwindown = 0;
  2860   kbdhook.winsdown = 0;
  2861   kbdhook.send_win_up = 0;
  2862   kbdhook.suppress_lone = 0;
  2863   kbdhook.winseen = 0;
  2864 }
  2865 
  2866 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
  2867    between left and right keys as advertised.  We test for this
  2868    support dynamically, and set a flag when the support is absent.  If
  2869    absent, we keep track of the left and right control and alt keys
  2870    ourselves.  This is particularly necessary on keyboards that rely
  2871    upon the AltGr key, which is represented as having the left control
  2872    and right alt keys pressed.  For these keyboards, we need to know
  2873    when the left alt key has been pressed in addition to the AltGr key
  2874    so that we can properly support M-AltGr-key sequences (such as M-@
  2875    on Swedish keyboards).  */
  2876 
  2877 #define EMACS_LCONTROL 0
  2878 #define EMACS_RCONTROL 1
  2879 #define EMACS_LMENU    2
  2880 #define EMACS_RMENU    3
  2881 
  2882 static int modifiers[4];
  2883 static int modifiers_recorded;
  2884 static int modifier_key_support_tested;
  2885 
  2886 static void
  2887 test_modifier_support (unsigned int wparam)
  2888 {
  2889   unsigned int l, r;
  2890 
  2891   if (wparam != VK_CONTROL && wparam != VK_MENU)
  2892     return;
  2893   if (wparam == VK_CONTROL)
  2894     {
  2895       l = VK_LCONTROL;
  2896       r = VK_RCONTROL;
  2897     }
  2898   else
  2899     {
  2900       l = VK_LMENU;
  2901       r = VK_RMENU;
  2902     }
  2903   if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
  2904     modifiers_recorded = 1;
  2905   else
  2906     modifiers_recorded = 0;
  2907   modifier_key_support_tested = 1;
  2908 }
  2909 
  2910 static void
  2911 record_keydown (unsigned int wparam, unsigned int lparam)
  2912 {
  2913   int i;
  2914 
  2915   if (!modifier_key_support_tested)
  2916     test_modifier_support (wparam);
  2917 
  2918   if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
  2919     return;
  2920 
  2921   if (wparam == VK_CONTROL)
  2922     i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
  2923   else
  2924     i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
  2925 
  2926   modifiers[i] = 1;
  2927 }
  2928 
  2929 static void
  2930 record_keyup (unsigned int wparam, unsigned int lparam)
  2931 {
  2932   int i;
  2933 
  2934   if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
  2935     return;
  2936 
  2937   if (wparam == VK_CONTROL)
  2938     i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
  2939   else
  2940     i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
  2941 
  2942   modifiers[i] = 0;
  2943 }
  2944 
  2945 /* Emacs can lose focus while a modifier key has been pressed.  When
  2946    it regains focus, be conservative and clear all modifiers since
  2947    we cannot reconstruct the left and right modifier state.  */
  2948 static void
  2949 reset_modifiers (void)
  2950 {
  2951   SHORT ctrl, alt;
  2952 
  2953   if (GetFocus () == NULL)
  2954     /* Emacs doesn't have keyboard focus.  Do nothing.  */
  2955     return;
  2956 
  2957   ctrl = GetAsyncKeyState (VK_CONTROL);
  2958   alt = GetAsyncKeyState (VK_MENU);
  2959 
  2960   if (!(ctrl & 0x08000))
  2961     /* Clear any recorded control modifier state.  */
  2962     modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
  2963 
  2964   if (!(alt & 0x08000))
  2965     /* Clear any recorded alt modifier state.  */
  2966     modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
  2967 
  2968   /* Update the state of all modifier keys, because modifiers used in
  2969      hot-key combinations can get stuck on if Emacs loses focus as a
  2970      result of a hot-key being pressed.  */
  2971   {
  2972     BYTE keystate[256];
  2973 
  2974 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
  2975 
  2976     memset (keystate, 0, sizeof (keystate));
  2977     GetKeyboardState (keystate);
  2978     keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
  2979     keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
  2980     keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
  2981     keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
  2982     keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
  2983     keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
  2984     keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
  2985     keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
  2986     keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
  2987     keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
  2988     SetKeyboardState (keystate);
  2989   }
  2990 }
  2991 
  2992 /* Synchronize modifier state with what is reported with the current
  2993    keystroke.  Even if we cannot distinguish between left and right
  2994    modifier keys, we know that, if no modifiers are set, then neither
  2995    the left or right modifier should be set.  */
  2996 static void
  2997 sync_modifiers (void)
  2998 {
  2999   if (!modifiers_recorded)
  3000     return;
  3001 
  3002   if (!(GetKeyState (VK_CONTROL) & 0x8000))
  3003     modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
  3004 
  3005   if (!(GetKeyState (VK_MENU) & 0x8000))
  3006     modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
  3007 }
  3008 
  3009 static int
  3010 modifier_set (int vkey)
  3011 {
  3012   /* Warning: The fact that VK_NUMLOCK is not treated as the other 2
  3013      toggle keys is not an omission!  If you want to add it, you will
  3014      have to make changes in the default sub-case of the WM_KEYDOWN
  3015      switch, because if the NUMLOCK modifier is set, the code there
  3016      will directly convert any key that looks like an ASCII letter,
  3017      and also downcase those that look like upper-case ASCII.  */
  3018   if (vkey == VK_CAPITAL)
  3019     {
  3020       if (NILP (Vw32_enable_caps_lock))
  3021         return 0;
  3022       else
  3023         return (GetKeyState (vkey) & 0x1);
  3024     }
  3025   if (vkey == VK_SCROLL)
  3026     {
  3027       if (NILP (Vw32_scroll_lock_modifier)
  3028           /* w32-scroll-lock-modifier can be any non-nil value that is
  3029              not one of the modifiers, in which case it shall be ignored.  */
  3030           || !(   EQ (Vw32_scroll_lock_modifier, Qhyper)
  3031                || EQ (Vw32_scroll_lock_modifier, Qsuper)
  3032                || EQ (Vw32_scroll_lock_modifier, Qmeta)
  3033                || EQ (Vw32_scroll_lock_modifier, Qalt)
  3034                || EQ (Vw32_scroll_lock_modifier, Qcontrol)
  3035                || EQ (Vw32_scroll_lock_modifier, Qshift)))
  3036         return 0;
  3037       else
  3038         return (GetKeyState (vkey) & 0x1);
  3039     }
  3040 #ifdef WINDOWSNT
  3041   if (w32_kbdhook_active && (vkey == VK_LWIN || vkey == VK_RWIN))
  3042     return check_w32_winkey_state (vkey);
  3043 #endif
  3044 
  3045   if (!modifiers_recorded)
  3046     return (GetKeyState (vkey) & 0x8000);
  3047 
  3048   switch (vkey)
  3049     {
  3050     case VK_LCONTROL:
  3051       return modifiers[EMACS_LCONTROL];
  3052     case VK_RCONTROL:
  3053       return modifiers[EMACS_RCONTROL];
  3054     case VK_LMENU:
  3055       return modifiers[EMACS_LMENU];
  3056     case VK_RMENU:
  3057       return modifiers[EMACS_RMENU];
  3058     }
  3059   return (GetKeyState (vkey) & 0x8000);
  3060 }
  3061 
  3062 /* Convert between the modifier bits W32 uses and the modifier bits
  3063    Emacs uses.  */
  3064 unsigned int w32_key_to_modifier (int);
  3065 
  3066 unsigned int
  3067 w32_key_to_modifier (int key)
  3068 {
  3069   Lisp_Object key_mapping;
  3070 
  3071   switch (key)
  3072     {
  3073     case VK_LWIN:
  3074       key_mapping = Vw32_lwindow_modifier;
  3075       break;
  3076     case VK_RWIN:
  3077       key_mapping = Vw32_rwindow_modifier;
  3078       break;
  3079     case VK_APPS:
  3080       key_mapping = Vw32_apps_modifier;
  3081       break;
  3082     case VK_SCROLL:
  3083       key_mapping = Vw32_scroll_lock_modifier;
  3084       break;
  3085     default:
  3086       key_mapping = Qnil;
  3087     }
  3088 
  3089   /* NB. This code runs in the input thread, asynchronously to the lisp
  3090      thread, so we must be careful to ensure access to lisp data is
  3091      thread-safe.  The following code is safe because the modifier
  3092      variable values are updated atomically from lisp and symbols are
  3093      not relocated by GC.  Also, we don't have to worry about seeing GC
  3094      markbits here.  */
  3095   if (EQ (key_mapping, Qhyper))
  3096     return hyper_modifier;
  3097   if (EQ (key_mapping, Qsuper))
  3098     return super_modifier;
  3099   if (EQ (key_mapping, Qmeta))
  3100     return meta_modifier;
  3101   if (EQ (key_mapping, Qalt))
  3102     return alt_modifier;
  3103   if (EQ (key_mapping, Qctrl))
  3104     return ctrl_modifier;
  3105   if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
  3106     return ctrl_modifier;
  3107   if (EQ (key_mapping, Qshift))
  3108     return shift_modifier;
  3109 
  3110   /* Don't generate any modifier if not explicitly requested.  */
  3111   return 0;
  3112 }
  3113 
  3114 static unsigned int
  3115 w32_get_modifiers (void)
  3116 {
  3117   return ((modifier_set (VK_SHIFT)   ? shift_modifier : 0) |
  3118           (modifier_set (VK_CONTROL) ? ctrl_modifier  : 0) |
  3119           (modifier_set (VK_LWIN)    ? w32_key_to_modifier (VK_LWIN) : 0) |
  3120           (modifier_set (VK_RWIN)    ? w32_key_to_modifier (VK_RWIN) : 0) |
  3121           (modifier_set (VK_APPS)    ? w32_key_to_modifier (VK_APPS) : 0) |
  3122           (modifier_set (VK_SCROLL)  ? w32_key_to_modifier (VK_SCROLL) : 0) |
  3123           (modifier_set (VK_MENU)    ?
  3124            ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
  3125 }
  3126 
  3127 /* We map the VK_* modifiers into console modifier constants
  3128    so that we can use the same routines to handle both console
  3129    and window input.  */
  3130 
  3131 static int
  3132 w32_construct_console_modifiers (void)
  3133 {
  3134   int mods;
  3135 
  3136   mods = 0;
  3137   mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
  3138   mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
  3139   mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
  3140   mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
  3141   mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
  3142   mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
  3143   mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
  3144   mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
  3145   mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
  3146   mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
  3147   mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
  3148 
  3149   return mods;
  3150 }
  3151 
  3152 static int
  3153 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
  3154 {
  3155   int mods;
  3156 
  3157   /* Convert to emacs modifiers.  */
  3158   mods = w32_kbd_mods_to_emacs (w32_construct_console_modifiers (), wparam);
  3159 
  3160   return mods;
  3161 }
  3162 
  3163 unsigned int map_keypad_keys (unsigned int, unsigned int);
  3164 
  3165 unsigned int
  3166 map_keypad_keys (unsigned int virt_key, unsigned int extended)
  3167 {
  3168   if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
  3169     return virt_key;
  3170 
  3171   if (virt_key == VK_RETURN)
  3172     return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
  3173 
  3174   if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
  3175     return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
  3176 
  3177   if (virt_key == VK_INSERT || virt_key == VK_DELETE)
  3178     return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
  3179 
  3180   if (virt_key == VK_CLEAR)
  3181     return (!extended ? VK_NUMPAD_CLEAR : virt_key);
  3182 
  3183   return virt_key;
  3184 }
  3185 
  3186 /* List of special key combinations which w32 would normally capture,
  3187    but Emacs should grab instead.  Not directly visible to lisp, to
  3188    simplify synchronization.  Each item is an integer encoding a virtual
  3189    key code and modifier combination to capture.
  3190    Note: This code is not used if keyboard hooks are active
  3191    (Windows 2000 and later).  */
  3192 static Lisp_Object w32_grabbed_keys;
  3193 
  3194 #define HOTKEY(vk, mods)      make_fixnum (((vk) & 255) | ((mods) << 8))
  3195 #define HOTKEY_ID(k)          (XFIXNAT (k) & 0xbfff)
  3196 #define HOTKEY_VK_CODE(k)     (XFIXNAT (k) & 255)
  3197 #define HOTKEY_MODIFIERS(k)   (XFIXNAT (k) >> 8)
  3198 
  3199 #define RAW_HOTKEY_ID(k)        ((k) & 0xbfff)
  3200 #define RAW_HOTKEY_VK_CODE(k)   ((k) & 255)
  3201 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
  3202 
  3203 /* Register hot-keys for reserved key combinations when Emacs has
  3204    keyboard focus, since this is the only way Emacs can receive key
  3205    combinations like Alt-Tab which are used by the system.  */
  3206 
  3207 static void
  3208 register_hot_keys (HWND hwnd)
  3209 {
  3210   Lisp_Object keylist;
  3211 
  3212   /* Use CONSP, since we are called asynchronously.  */
  3213   for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
  3214     {
  3215       Lisp_Object key = XCAR (keylist);
  3216 
  3217       /* Deleted entries get set to nil.  */
  3218       if (!FIXNUMP (key))
  3219         continue;
  3220 
  3221       RegisterHotKey (hwnd, HOTKEY_ID (key),
  3222                       HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
  3223     }
  3224 }
  3225 
  3226 static void
  3227 unregister_hot_keys (HWND hwnd)
  3228 {
  3229   Lisp_Object keylist;
  3230 
  3231   for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
  3232     {
  3233       Lisp_Object key = XCAR (keylist);
  3234 
  3235       if (!FIXNUMP (key))
  3236         continue;
  3237 
  3238       UnregisterHotKey (hwnd, HOTKEY_ID (key));
  3239     }
  3240 }
  3241 
  3242 #if EMACSDEBUG
  3243 const char*
  3244 w32_name_of_message (UINT msg)
  3245 {
  3246   unsigned i;
  3247   static char buf[64];
  3248   static const struct {
  3249     UINT msg;
  3250     const char* name;
  3251   } msgnames[] = {
  3252 #define M(msg) { msg, # msg }
  3253       M (WM_PAINT),
  3254       M (WM_TIMER),
  3255       M (WM_USER),
  3256       M (WM_MOUSEMOVE),
  3257       M (WM_LBUTTONUP),
  3258       M (WM_KEYDOWN),
  3259       M (WM_EMACS_KILL),
  3260       M (WM_EMACS_CREATEWINDOW),
  3261       M (WM_EMACS_DONE),
  3262       M (WM_EMACS_CREATEVSCROLLBAR),
  3263       M (WM_EMACS_CREATEHSCROLLBAR),
  3264       M (WM_EMACS_SHOWWINDOW),
  3265       M (WM_EMACS_SETWINDOWPOS),
  3266       M (WM_EMACS_DESTROYWINDOW),
  3267       M (WM_EMACS_TRACKPOPUPMENU),
  3268       M (WM_EMACS_SETFOCUS),
  3269       M (WM_EMACS_SETFOREGROUND),
  3270       M (WM_EMACS_SETLOCALE),
  3271       M (WM_EMACS_SETKEYBOARDLAYOUT),
  3272       M (WM_EMACS_REGISTER_HOT_KEY),
  3273       M (WM_EMACS_UNREGISTER_HOT_KEY),
  3274       M (WM_EMACS_TOGGLE_LOCK_KEY),
  3275       M (WM_EMACS_TRACK_CARET),
  3276       M (WM_EMACS_DESTROY_CARET),
  3277       M (WM_EMACS_SHOW_CARET),
  3278       M (WM_EMACS_HIDE_CARET),
  3279       M (WM_EMACS_SETCURSOR),
  3280       M (WM_EMACS_SHOWCURSOR),
  3281       M (WM_EMACS_PAINT),
  3282       M (WM_EMACS_IME_STATUS),
  3283       M (WM_CHAR),
  3284 #undef M
  3285       { 0, 0 }
  3286   };
  3287 
  3288   for (i = 0; msgnames[i].name; ++i)
  3289     if (msgnames[i].msg == msg)
  3290       return msgnames[i].name;
  3291 
  3292   sprintf (buf, "message 0x%04x", (unsigned)msg);
  3293   return buf;
  3294 }
  3295 #endif /* EMACSDEBUG */
  3296 
  3297 /* Here's an overview of how Emacs input works in GUI sessions on
  3298    MS-Windows.  (For description of non-GUI input, see the commentary
  3299    before w32_console_read_socket in w32inevt.c.)
  3300 
  3301    System messages are read and processed by w32_msg_pump below.  This
  3302    function runs in a separate thread.  It handles a small number of
  3303    custom WM_EMACS_* messages (posted by the main thread, look for
  3304    PostMessage calls), and dispatches the rest to w32_wnd_proc, which
  3305    is the main window procedure for the entire Emacs application.
  3306 
  3307    w32_wnd_proc also runs in the same separate input thread.  It
  3308    handles some messages, mostly those that need GDI calls, by itself.
  3309    For the others, it calls my_post_msg, which inserts the messages
  3310    into the input queue serviced by w32_read_socket.
  3311 
  3312    w32_read_socket runs in the main (a.k.a. "Lisp") thread, and is
  3313    called synchronously from keyboard.c when it is known or suspected
  3314    that some input is available.  w32_read_socket either handles
  3315    messages immediately, or converts them into Emacs input events and
  3316    stuffs them into kbd_buffer, where kbd_buffer_get_event can get at
  3317    them and process them when read_char and its callers require
  3318    input.
  3319 
  3320    Under Cygwin with the W32 toolkit, the use of /dev/windows with
  3321    select(2) takes the place of w32_read_socket.
  3322 
  3323    */
  3324 
  3325 /* Main message dispatch loop. */
  3326 
  3327 static void
  3328 w32_msg_pump (deferred_msg * msg_buf)
  3329 {
  3330   MSG msg;
  3331   WPARAM result;
  3332   HWND focus_window;
  3333 
  3334   msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
  3335 
  3336   while ((w32_unicode_gui ? GetMessageW : GetMessageA) (&msg, NULL, 0, 0))
  3337     {
  3338 
  3339       /* DebPrint (("w32_msg_pump: %s time:%u\n", */
  3340       /*            w32_name_of_message (msg.message), msg.time)); */
  3341 
  3342       if (msg.hwnd == NULL)
  3343         {
  3344           switch (msg.message)
  3345             {
  3346             case WM_NULL:
  3347               /* Produced by complete_deferred_msg; just ignore.  */
  3348               break;
  3349             case WM_EMACS_CREATEWINDOW:
  3350               /* Initialize COM for this window. Even though we don't use it,
  3351                  some third party shell extensions can cause it to be used in
  3352                  system dialogs, which causes a crash if it is not initialized.
  3353                  This is a known bug in Windows, which was fixed long ago, but
  3354                  the patch for XP is not publicly available until XP SP3,
  3355                  and older versions will never be patched.  */
  3356               CoInitialize (NULL);
  3357               w32_createwindow ((struct frame *) msg.wParam,
  3358                                 (int *) msg.lParam);
  3359               if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
  3360                 emacs_abort ();
  3361               break;
  3362             case WM_EMACS_SETLOCALE:
  3363               SetThreadLocale (msg.wParam);
  3364               /* Reply is not expected.  */
  3365               break;
  3366             case WM_EMACS_SETKEYBOARDLAYOUT:
  3367               result = (WPARAM) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
  3368               if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
  3369                                       result, 0))
  3370                 emacs_abort ();
  3371               break;
  3372             case WM_EMACS_REGISTER_HOT_KEY:
  3373               focus_window = GetFocus ();
  3374               if (focus_window != NULL)
  3375                 RegisterHotKey (focus_window,
  3376                                 RAW_HOTKEY_ID (msg.wParam),
  3377                                 RAW_HOTKEY_MODIFIERS (msg.wParam),
  3378                                 RAW_HOTKEY_VK_CODE (msg.wParam));
  3379               /* Reply is not expected.  */
  3380               break;
  3381             case WM_EMACS_UNREGISTER_HOT_KEY:
  3382               focus_window = GetFocus ();
  3383               if (focus_window != NULL)
  3384                 UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam));
  3385               /* Mark item as erased.  NB: this code must be
  3386                  thread-safe.  The next line is okay because the cons
  3387                  cell is never made into garbage and is not relocated by
  3388                  GC.  */
  3389               XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil);
  3390               if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
  3391                 emacs_abort ();
  3392               break;
  3393             case WM_EMACS_TOGGLE_LOCK_KEY:
  3394               {
  3395                 int vk_code = (int) msg.wParam;
  3396                 int cur_state = (GetKeyState (vk_code) & 1);
  3397                 int new_state = msg.lParam;
  3398 
  3399                 if (new_state == -1
  3400                     || ((new_state & 1) != cur_state))
  3401                   {
  3402                     one_w32_display_info.faked_key = vk_code;
  3403 
  3404                     keybd_event ((BYTE) vk_code,
  3405                                  (BYTE) MapVirtualKey (vk_code, 0),
  3406                                  KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  3407                     keybd_event ((BYTE) vk_code,
  3408                                  (BYTE) MapVirtualKey (vk_code, 0),
  3409                                  KEYEVENTF_EXTENDEDKEY | 0, 0);
  3410                     keybd_event ((BYTE) vk_code,
  3411                                  (BYTE) MapVirtualKey (vk_code, 0),
  3412                                  KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  3413                     cur_state = !cur_state;
  3414                   }
  3415                 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
  3416                                         cur_state, 0))
  3417                   emacs_abort ();
  3418               }
  3419               break;
  3420             case WM_EMACS_IME_STATUS:
  3421               {
  3422                 focus_window = GetFocus ();
  3423                 if (!set_ime_open_status_fn || !focus_window)
  3424                   break;
  3425 
  3426                 HIMC context = get_ime_context_fn (focus_window);
  3427                 if (!context)
  3428                   break;
  3429 
  3430                 set_ime_open_status_fn (context, msg.wParam != 0);
  3431                 release_ime_context_fn (focus_window, context);
  3432                 break;
  3433               }
  3434 
  3435 #ifdef MSG_DEBUG
  3436               /* Broadcast messages make it here, so you need to be looking
  3437                  for something in particular for this to be useful.  */
  3438             default:
  3439               DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
  3440 #endif
  3441             }
  3442         }
  3443       else
  3444         {
  3445           if (w32_unicode_gui)
  3446             DispatchMessageW (&msg);
  3447           else
  3448             DispatchMessageA (&msg);
  3449         }
  3450 
  3451       /* Exit nested loop when our deferred message has completed.  */
  3452       if (msg_buf->completed)
  3453         break;
  3454     }
  3455 }
  3456 
  3457 deferred_msg * deferred_msg_head;
  3458 
  3459 static deferred_msg *
  3460 find_deferred_msg (HWND hwnd, UINT msg)
  3461 {
  3462   deferred_msg * item;
  3463 
  3464   /* Don't actually need synchronization for read access, since
  3465      modification of single pointer is always atomic.  */
  3466   /* enter_crit (); */
  3467 
  3468   for (item = deferred_msg_head; item != NULL; item = item->next)
  3469     if (item->w32msg.msg.hwnd == hwnd
  3470         && item->w32msg.msg.message == msg)
  3471       break;
  3472 
  3473   /* leave_crit (); */
  3474 
  3475   return item;
  3476 }
  3477 
  3478 static LRESULT
  3479 send_deferred_msg (deferred_msg * msg_buf,
  3480                    HWND hwnd,
  3481                    UINT msg,
  3482                    WPARAM wParam,
  3483                    LPARAM lParam)
  3484 {
  3485   /* Only input thread can send deferred messages.  */
  3486   if (GetCurrentThreadId () != dwWindowsThreadId)
  3487     emacs_abort ();
  3488 
  3489   /* It is an error to send a message that is already deferred.  */
  3490   if (find_deferred_msg (hwnd, msg) != NULL)
  3491     emacs_abort ();
  3492 
  3493   /* Enforced synchronization is not needed because this is the only
  3494      function that alters deferred_msg_head, and the following critical
  3495      section is guaranteed to only be serially reentered (since only the
  3496      input thread can call us).  */
  3497 
  3498   /* enter_crit (); */
  3499 
  3500   msg_buf->completed = 0;
  3501   msg_buf->next = deferred_msg_head;
  3502   deferred_msg_head = msg_buf;
  3503   my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
  3504 
  3505   /* leave_crit (); */
  3506 
  3507   /* Start a new nested message loop to process other messages until
  3508      this one is completed.  */
  3509   w32_msg_pump (msg_buf);
  3510 
  3511   deferred_msg_head = msg_buf->next;
  3512 
  3513   return msg_buf->result;
  3514 }
  3515 
  3516 void
  3517 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
  3518 {
  3519   deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
  3520 
  3521   if (msg_buf == NULL)
  3522     /* Message may have been canceled, so don't abort.  */
  3523     return;
  3524 
  3525   msg_buf->result = result;
  3526   msg_buf->completed = 1;
  3527 
  3528   /* Ensure input thread is woken so it notices the completion.  */
  3529   PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
  3530 }
  3531 
  3532 static void
  3533 cancel_all_deferred_msgs (void)
  3534 {
  3535   deferred_msg * item;
  3536 
  3537   /* Don't actually need synchronization for read access, since
  3538      modification of single pointer is always atomic.  */
  3539   /* enter_crit (); */
  3540 
  3541   for (item = deferred_msg_head; item != NULL; item = item->next)
  3542     {
  3543       item->result = 0;
  3544       item->completed = 1;
  3545     }
  3546 
  3547   /* leave_crit (); */
  3548 
  3549   /* Ensure input thread is woken so it notices the completion.  */
  3550   PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
  3551 }
  3552 
  3553 DWORD WINAPI w32_msg_worker (void *);
  3554 
  3555 DWORD WINAPI
  3556 w32_msg_worker (void *arg)
  3557 {
  3558   MSG msg;
  3559   deferred_msg dummy_buf;
  3560 
  3561   /* Ensure our message queue is created */
  3562 
  3563   PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
  3564 
  3565   if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
  3566     emacs_abort ();
  3567 
  3568   memset (&dummy_buf, 0, sizeof (dummy_buf));
  3569   dummy_buf.w32msg.msg.hwnd = NULL;
  3570   dummy_buf.w32msg.msg.message = WM_NULL;
  3571 
  3572   /* This is the initial message loop which should only exit when the
  3573      application quits.  */
  3574   w32_msg_pump (&dummy_buf);
  3575 
  3576   return 0;
  3577 }
  3578 
  3579 static void
  3580 signal_user_input (void)
  3581 {
  3582   /* Interrupt any lisp that wants to be interrupted by input.  */
  3583   if (!NILP (Vthrow_on_input))
  3584     {
  3585       Vquit_flag = Vthrow_on_input;
  3586       /* Calling maybe_quit from this thread is a bad idea, since this
  3587          unwinds the stack of the Lisp thread, and the Windows runtime
  3588          rightfully barfs.  */
  3589     }
  3590 }
  3591 
  3592 
  3593 static void
  3594 post_character_message (HWND hwnd, UINT msg,
  3595                         WPARAM wParam, LPARAM lParam,
  3596                         DWORD modifiers)
  3597 {
  3598   W32Msg wmsg;
  3599 
  3600   wmsg.dwModifiers = modifiers;
  3601 
  3602   /* Detect quit_char and set quit-flag directly.  Note that we
  3603      still need to post a message to ensure the main thread will be
  3604      woken up if blocked in sys_select, but we do NOT want to post
  3605      the quit_char message itself (because it will usually be as if
  3606      the user had typed quit_char twice).  Instead, we post a dummy
  3607      message that has no particular effect.  */
  3608   {
  3609     int c = wParam;
  3610     if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
  3611       c = make_ctrl_char (c) & 0377;
  3612     if (c == quit_char
  3613         || (wmsg.dwModifiers == 0
  3614             && w32_quit_key && wParam == w32_quit_key))
  3615       {
  3616         Vquit_flag = Qt;
  3617 
  3618         /* The choice of message is somewhat arbitrary, as long as
  3619            the main thread handler just ignores it.  */
  3620         msg = WM_NULL;
  3621 
  3622         /* Interrupt any blocking system calls.  */
  3623         signal_quit ();
  3624 
  3625         /* As a safety precaution, forcibly complete any deferred
  3626            messages.  This is a kludge, but I don't see any particularly
  3627            clean way to handle the situation where a deferred message is
  3628            "dropped" in the lisp thread, and will thus never be
  3629            completed, eg. by the user trying to activate the menubar
  3630            when the lisp thread is busy, and then typing C-g when the
  3631            menubar doesn't open promptly (with the result that the
  3632            menubar never responds at all because the deferred
  3633            WM_INITMENU message is never completed).  Another problem
  3634            situation is when the lisp thread calls SendMessage (to send
  3635            a window manager command) when a message has been deferred;
  3636            the lisp thread gets blocked indefinitely waiting for the
  3637            deferred message to be completed, which itself is waiting for
  3638            the lisp thread to respond.
  3639 
  3640            Note that we don't want to block the input thread waiting for
  3641            a response from the lisp thread (although that would at least
  3642            solve the deadlock problem above), because we want to be able
  3643            to receive C-g to interrupt the lisp thread.  */
  3644         cancel_all_deferred_msgs ();
  3645       }
  3646     else
  3647       signal_user_input ();
  3648   }
  3649 
  3650   my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  3651 }
  3652 
  3653 static int
  3654 get_wm_chars (HWND aWnd, int *buf, int buflen, int ignore_ctrl, int ctrl,
  3655               int *ctrl_cnt, int *is_dead, int vk, int exp)
  3656 {
  3657   MSG msg;
  3658   /* If doubled is at the end, ignore it.  */
  3659   int i = buflen, doubled = 0, code_unit;
  3660 
  3661   if (ctrl_cnt)
  3662     *ctrl_cnt = 0;
  3663   if (is_dead)
  3664     *is_dead = -1;
  3665   eassert (w32_unicode_gui);
  3666   while (buflen
  3667          /* Should be called only when w32_unicode_gui:  */
  3668          && PeekMessageW (&msg, aWnd, WM_KEYFIRST, WM_KEYLAST,
  3669                           PM_NOREMOVE | PM_NOYIELD)
  3670          && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR
  3671              || msg.message == WM_DEADCHAR || msg.message == WM_SYSDEADCHAR
  3672              || msg.message == WM_UNICHAR))
  3673     {
  3674       /* We extract character payload, but in this call we handle only the
  3675          characters which come BEFORE the next keyup/keydown message.  */
  3676       int dead;
  3677 
  3678       GetMessageW (&msg, aWnd, msg.message, msg.message);
  3679       dead = (msg.message == WM_DEADCHAR || msg.message == WM_SYSDEADCHAR);
  3680       if (is_dead)
  3681         *is_dead = (dead ? msg.wParam : -1);
  3682       if (dead)
  3683         continue;
  3684       code_unit = msg.wParam;
  3685       if (doubled)
  3686         {
  3687           /* Had surrogate.  */
  3688           if (msg.message == WM_UNICHAR
  3689               || code_unit < 0xDC00 || code_unit > 0xDFFF)
  3690             { /* Mismatched first surrogate.
  3691                  Pass both code units as if they were two characters.  */
  3692               *buf++ = doubled;
  3693               if (!--buflen)
  3694                 return i; /* Drop the 2nd char if at the end of the buffer.  */
  3695             }
  3696           else /* see https://en.wikipedia.org/wiki/UTF-16 */
  3697             code_unit = (doubled << 10) + code_unit - 0x35FDC00;
  3698           doubled = 0;
  3699         }
  3700       else if (code_unit >= 0xD800 && code_unit <= 0xDBFF)
  3701         {
  3702           /* Handle mismatched 2nd surrogate the same as a normal character.  */
  3703           doubled = code_unit;
  3704           continue;
  3705         }
  3706 
  3707       /* The only "fake" characters delivered by ToUnicode() or
  3708          TranslateMessage() are:
  3709          0x01 .. 0x1a for Ctrl-letter, Enter, Tab, Ctrl-Break, Esc, Backspace
  3710          0x00 and 0x1b .. 0x1f for Control- []\@^_
  3711          0x7f for Control-BackSpace
  3712          0x20 for Control-Space */
  3713       if (ignore_ctrl
  3714           && (code_unit < 0x20 || code_unit == 0x7f
  3715               || (code_unit == 0x20 && ctrl)))
  3716         {
  3717           /* Non-character payload in a WM_CHAR
  3718              (Ctrl-something pressed, see above).  Ignore, and report.  */
  3719           if (ctrl_cnt)
  3720             (*ctrl_cnt)++;
  3721           continue;
  3722         }
  3723       /* Traditionally, Emacs would ignore the character payload of VK_NUMPAD*
  3724          keys, and would treat them later via `function-key-map'.  In addition
  3725          to usual 102-key NUMPAD keys, this map also treats `kp-'-variants of
  3726          space, tab, enter, separator, equal.  TAB  and EQUAL, apparently,
  3727          cannot be generated on Win-GUI branch.  ENTER is already handled
  3728          by the code above.  According to `lispy_function_keys', kp_space is
  3729          generated by not-extended VK_CLEAR.  (kp-tab !=  VK_OEM_NEC_EQUAL!).
  3730 
  3731          We do similarly for backward-compatibility, but ignore only the
  3732          characters restorable later by `function-key-map'.  */
  3733       if (code_unit < 0x7f
  3734           && ((vk >= VK_NUMPAD0 && vk <= VK_DIVIDE)
  3735               || (exp && ((vk >= VK_PRIOR && vk <= VK_DOWN) ||
  3736                      vk == VK_INSERT || vk == VK_DELETE || vk == VK_CLEAR)))
  3737           && strchr ("0123456789/*-+.,", code_unit))
  3738         continue;
  3739       *buf++ = code_unit;
  3740       buflen--;
  3741     }
  3742   return i - buflen;
  3743 }
  3744 
  3745 #ifdef DBG_WM_CHARS
  3746 #  define FPRINTF_WM_CHARS(ARG) fprintf ARG
  3747 #else
  3748 #  define FPRINTF_WM_CHARS(ARG) (void)0
  3749 #endif
  3750 
  3751 /* This is a heuristic only.  This is supposed to track the state of the
  3752    finite automaton in the language environment of Windows.
  3753 
  3754    However, separate windows (if with the same different language
  3755    environments!) should  have different values.  Moreover, switching to a
  3756    non-Emacs window with the same language environment, and using (dead)keys
  3757    there would change the value stored in the kernel, but not this value.  */
  3758 /* A layout may emit deadkey=0.  It looks like this would reset the state
  3759    of the kernel's finite automaton (equivalent to emitting 0-length string,
  3760    which is otherwise impossible in the dead-key map of a layout).
  3761    Be ready to treat the case when this delivers WM_(SYS)DEADCHAR. */
  3762 static int after_deadkey = -1;
  3763 
  3764 static int
  3765 deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, UINT wParam,
  3766                   UINT lParam, int legacy_alt_meta)
  3767 {
  3768   /* An "old style" keyboard description may assign up to 125 UTF-16 code
  3769      points to a keypress.
  3770      (However, the "old style" TranslateMessage() would deliver at most 16 of
  3771      them.)  Be on a safe side, and prepare to treat many more.  */
  3772   int ctrl_cnt, buf[1024], count, is_dead, after_dead = (after_deadkey > 0);
  3773 
  3774   /* Since the keypress processing logic of Windows has a lot of state, it
  3775      is important to call TranslateMessage() for every keyup/keydown, AND
  3776      do it exactly once.  (The actual change of state is done by
  3777      ToUnicode[Ex](), which is called by TranslateMessage().  So one can
  3778      call ToUnicode[Ex]() instead.)
  3779 
  3780      The "usual" message pump calls TranslateMessage() for EVERY event.
  3781      Emacs calls TranslateMessage() very selectively (is it needed for doing
  3782      some tricky stuff with Win95???  With newer Windows, selectiveness is,
  3783      most probably, not needed -- and harms a lot).
  3784 
  3785      So, with the usual message pump, the following call to TranslateMessage()
  3786      is not needed (and is going to be VERY harmful).  With Emacs' message
  3787      pump, the call is needed.  */
  3788   if (do_translate)
  3789     {
  3790       MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
  3791 
  3792       windows_msg.time = GetMessageTime ();
  3793       TranslateMessage (&windows_msg);
  3794     }
  3795   count = get_wm_chars (hwnd, buf, sizeof (buf)/sizeof (*buf), 1,
  3796                         /* The message may have been synthesized by
  3797                            who knows what; be conservative.  */
  3798                         modifier_set (VK_LCONTROL)
  3799                           || modifier_set (VK_RCONTROL)
  3800                           || modifier_set (VK_CONTROL),
  3801                         &ctrl_cnt, &is_dead, wParam,
  3802                         (lParam & 0x1000000L) != 0);
  3803   if (count)
  3804     {
  3805       W32Msg wmsg;
  3806       DWORD console_modifiers = w32_construct_console_modifiers ();
  3807       int *b = buf, strip_ExtraMods = 1, hairy = 0;
  3808       const char *type_CtrlAlt = NULL;
  3809 
  3810       /*  XXXX In fact, there may be another case when we need to do the same:
  3811                What happens if the string defined in the LIGATURES has length
  3812                0?  Probably, we will get count==0, but the state of the finite
  3813                automaton would reset to 0???  */
  3814      after_deadkey = -1;
  3815 
  3816       /* wParam is checked when converting CapsLock to Shift; this is a clone
  3817          of w32_get_key_modifiers ().  */
  3818       wmsg.dwModifiers = w32_kbd_mods_to_emacs (console_modifiers, wParam);
  3819 
  3820       /* What follows is just heuristics; the correct treatment requires
  3821          non-destructive ToUnicode():
  3822            http://search.cpan.org/~ilyaz/UI-KeyboardLayout/lib/UI/KeyboardLayout.pm#Can_an_application_on_Windows_accept_keyboard_events?_Part_IV:_application-specific_modifiers
  3823 
  3824          What one needs to find is:
  3825            * which of the present modifiers AFFECT the resulting char(s)
  3826              (so should be stripped, since their EFFECT is "already
  3827               taken into account" in the string in buf), and
  3828            * which modifiers are not affecting buf, so should be reported to
  3829              the application for further treatment.
  3830 
  3831          Example: assume that we know:
  3832            (A) lCtrl+rCtrl+rAlt modifiers with VK_A key produce a Latin "f"
  3833                ("may be logical" in JCUKEN-flavored Russian keyboard flavors);
  3834            (B) removing any of lCtrl, rCtrl, rAlt changes the produced char;
  3835            (C) Win-modifier is not affecting the produced character
  3836                (this is the common case: happens with all "standard" layouts).
  3837 
  3838          Suppose the user presses Win+lCtrl+rCtrl+rAlt modifiers with VK_A.
  3839          What is the intent of the user?  We need to guess the intent to decide
  3840          which event to deliver to the application.
  3841 
  3842          This looks like a reasonable logic: since Win- modifier doesn't affect
  3843          the output string, the user was pressing Win for SOME OTHER purpose.
  3844          So the user wanted to generate Win-SOMETHING event.  Now, what is
  3845          something?  If one takes the mantra that "character payload is more
  3846          important than the combination of keypresses which resulted in this
  3847          payload", then one should ignore lCtrl+rCtrl+rAlt, ignore VK_A, and
  3848          assume that the user wanted to generate Win-f.
  3849 
  3850          Unfortunately, without non-destructive ToUnicode(), checking (B),(C)
  3851          is out of question.  So we use heuristics (hopefully, covering
  3852          99.9999% of cases).  */
  3853 
  3854       /* Another thing to watch for is a possibility to use AltGr-* and
  3855          Ctrl-Alt-* with different semantic.
  3856 
  3857          Background: the layout defining the KLLF_ALTGR bit are treated
  3858          specially by the kernel: when VK_RMENU (=rightAlt, =AltGr) is pressed
  3859          (released), a press (release) of VK_LCONTROL is emulated (unless Ctrl
  3860          is already down).  As a result, any press/release of AltGr is seen
  3861          by applications as a press/release of lCtrl AND rAlt.  This is
  3862          applicable, in particular, to ToUnicode[Ex]().  (Keyrepeat is covered
  3863          the same way!)
  3864 
  3865            NOTE: it IS possible to see bare rAlt even with KLLF_ALTGR; but this
  3866            requires a good finger coordination: doing (physically)
  3867              Down-lCtrl Down-rAlt Up-lCtrl Down-a
  3868            (doing quick enough, so that key repeat of rAlt [which would
  3869            generate new "fake" Down-lCtrl events] does not happens before 'a'
  3870            is down) results in no "fake" events, so the application will see
  3871            only rAlt down when 'a' is pressed.  (However, fake Up-lCtrl WILL
  3872            be generated when rAlt goes UP.)
  3873 
  3874            In fact, note also that KLLF_ALTGR does not prohibit construction of
  3875            rCtrl-rAlt (just press them in this order!).
  3876 
  3877          Moreover: "traditional" layouts do not define distinct modifier-masks
  3878          for VK_LMENU and VK_RMENU (same for VK_L/RCONTROL).  Instead, they
  3879          rely on the KLLF_ALTGR bit to make the behavior of VK_LMENU and
  3880          VK_RMENU distinct.  As a corollary, for such layouts, the produced
  3881          character is the same for AltGr-* (=rAlt-*) and Ctrl-Alt-* (in any
  3882          combination of handedness).  For description of masks, see
  3883 
  3884            http://search.cpan.org/~ilyaz/UI-KeyboardLayout/lib/UI/KeyboardLayout.pm#Keyboard_input_on_Windows,_Part_I:_what_is_the_kernel_doing?
  3885 
  3886          By default, Emacs was using these coincidences via the following
  3887          heuristics: it was treating:
  3888           (*) keypresses with lCtrl-rAlt modifiers as if they are carrying
  3889               ONLY the character payload (no matter what the actual keyboard
  3890               was defining: if lCtrl-lAlt-b was delivering U+05df=beta, then
  3891               Emacs saw [beta]; if lCtrl-lAlt-b was undefined in the layout,
  3892               the keypress was completely ignored), and
  3893           (*) keypresses with the other combinations of handedness of Ctrl-Alt
  3894               modifiers (e.g., lCtrl-lAlt) as if they NEVER carry a character
  3895               payload (so they were reported "raw": if lCtrl-lAlt-b was
  3896               delivering beta, then Emacs saw event [C-A-b], and not [beta]).
  3897          This worked good for "traditional" layouts: users could type both
  3898          AltGr-x and Ctrl-Alt-x, and one was a character, another a bindable
  3899          event.
  3900 
  3901          However, for layouts which deliver different characters for AltGr-x
  3902          and lCtrl-lAlt-x, this scheme makes the latter character unaccessible
  3903          in Emacs.  While it is easy to access functionality of [C-M-x] in
  3904          Emacs by other means (for example, by the `controlify' prefix, or
  3905          using lCtrl-rCtrl-x, or rCtrl-rAlt-x [in this order]), missing
  3906          characters cannot be reconstructed without a tedious manual work.  */
  3907 
  3908       /* These two cases are often going to be distinguishable, since at most
  3909          one of these character is defined with KBDCTRL | KBDMENU modifier
  3910          bitmap.  (This heuristic breaks if both lCtrl-lAlt- AND lCtrl-rAlt-
  3911          are translated to modifier bitmaps distinct from KBDCTRL | KBDMENU,
  3912          or in the cases when lCtrl-lAlt-* and lCtrl-rAlt-* are generally
  3913          different, but lCtrl-lAlt-x and lCtrl-rAlt-x happen to deliver the
  3914          same character.)
  3915 
  3916          So we have 2 chunks of info:
  3917            (A) is it lCtrl-rAlt-, or lCtrl-lAlt, or some other combination?
  3918            (B) is the delivered character defined with KBDCTRL | KBDMENU bits?
  3919          Basing on (A) and (B), we should decide whether to ignore the
  3920          delivered character.  (Before, Emacs was completely ignoring (B), and
  3921          was treating the 3-state of (A) as a bit.)  This means that we have 6
  3922          bits of customization.
  3923 
  3924          Additionally, a presence of two Ctrl down may be AltGr-rCtrl-.  */
  3925 
  3926       /* Strip all non-Shift modifiers if:
  3927         - more than one UTF-16 code point delivered (can't call VkKeyScanW ())
  3928         - or the character is a result of combining with a prefix key.  */
  3929       if (!after_dead && count == 1 && *b < 0x10000)
  3930         {
  3931           if (console_modifiers & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)
  3932               && console_modifiers & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
  3933             {
  3934               type_CtrlAlt = "bB";   /* generic bindable Ctrl-Alt- modifiers */
  3935               if ((console_modifiers & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
  3936                   == (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
  3937                  /* double-Ctrl:
  3938                     e.g. AltGr-rCtrl on some layouts (in this order!) */
  3939                 type_CtrlAlt = "dD";
  3940               else if ((console_modifiers
  3941                         & (LEFT_CTRL_PRESSED | LEFT_ALT_PRESSED))
  3942                        == (LEFT_CTRL_PRESSED | LEFT_ALT_PRESSED))
  3943                 type_CtrlAlt = "lL"; /* Ctrl-Alt- modifiers on the left */
  3944               else if (!NILP (Vw32_recognize_altgr)
  3945                        && ((console_modifiers
  3946                             & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)))
  3947                           == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
  3948                 type_CtrlAlt = "gG"; /* modifiers as in AltGr */
  3949             }
  3950           else if (wmsg.dwModifiers & (alt_modifier | meta_modifier)
  3951                    || ((console_modifiers
  3952                         & (LEFT_WIN_PRESSED | RIGHT_WIN_PRESSED
  3953                            | APPS_PRESSED | SCROLLLOCK_ON))))
  3954             {
  3955               /* Pure Alt (or combination of Alt, Win, APPS, scrolllock.  */
  3956               type_CtrlAlt = "aA";
  3957             }
  3958           if (type_CtrlAlt)
  3959             {
  3960               /* Out of bound bitmap:  */
  3961               SHORT r = VkKeyScanW (*b), bitmap = 0x1FF;
  3962 
  3963               FPRINTF_WM_CHARS((stderr, "VkKeyScanW %#06x %#04x\n", (int)r,
  3964                                 wParam));
  3965               if ((r & 0xFF) == wParam)
  3966                 bitmap = r>>8; /* *b is reachable via simple interface */
  3967               else
  3968                 {
  3969                   /* VkKeyScanW() (essentially) returns the FIRST key with
  3970                      the specified character; so here the pressed key is the
  3971                      SECONDARY key producing the character.
  3972 
  3973                      Essentially, we have no information about the "role" of
  3974                      modifiers on this key: which contribute into the
  3975                      produced character (so "are consumed"), and which are
  3976                      "extra" (must attach to bindable events).
  3977 
  3978                      The default above would consume ALL modifiers, so the
  3979                      character is reported "as is".  However, on many layouts
  3980                      the ordering of the keys (in the layout table) is not
  3981                      thought out well, so the "secondary" keys are often those
  3982                      which the users would prefer to use with Alt-CHAR.
  3983                      (Moreover - with e.g. Czech-QWERTY - the ASCII
  3984                      punctuation is accessible from two equally [nu]preferable
  3985                      AltGr-keys.)
  3986 
  3987                      SO:   Heuristic: if the reported char is ASCII, AND Meta
  3988                      modifier is a candidate, behave as if Meta is present
  3989                      (fallback to the legacy branch; bug#23251).
  3990 
  3991                      (This would break layouts
  3992                      - delivering ASCII characters
  3993                      - on SECONDARY keys
  3994                      - with not Shift/AltGr-like modifier combinations.
  3995                      All 3 conditions together must be pretty exotic
  3996                      cases - and a workaround exists: use "primary" keys!) */
  3997                   if (*b < 0x80
  3998                       && (wmsg.dwModifiers
  3999                           & (alt_modifier | meta_modifier
  4000                              | super_modifier | hyper_modifier)))
  4001                     return 0;
  4002                 }
  4003               if (*type_CtrlAlt == 'a') /* Simple Alt seen */
  4004                 {
  4005                   if ((bitmap & ~1) == 0) /* 1: KBDSHIFT */
  4006                     {
  4007                       /* In "traditional" layouts, Alt without Ctrl does not
  4008                          change the delivered character.  This detects this
  4009                          situation; it is safe to report this as Alt-something
  4010                           -- as opposed to delivering the reported character
  4011                           without modifiers.  */
  4012                       if (legacy_alt_meta
  4013                           && *b > 0x7f && ('A' <= wParam && wParam <= 'Z'))
  4014                         /* For backward-compatibility with older Emacsen, let
  4015                            this be processed by another branch below (which
  4016                            would convert it to Alt-Latin char via wParam).  */
  4017                         return 0;
  4018                     }
  4019                   else
  4020                     hairy = 1;
  4021                 }
  4022               /* Check whether the delivered character(s) is accessible via
  4023                  KBDCTRL | KBDALT ( | KBDSHIFT ) modifier mask (which is 7).  */
  4024               else if ((bitmap & ~1) != 6)
  4025                 {
  4026                   /* The character is not accessible via plain Ctrl-Alt(-Shift)
  4027                      (which is, probably, same as AltGr) modifiers.
  4028                      Either it was after a prefix key, or is combined with
  4029                      modifier keys which we don't see, or there is an asymmetry
  4030                      between left-hand and right-hand modifiers, or other hairy
  4031                      stuff.  */
  4032                   hairy = 1;
  4033                 }
  4034               /* The best solution is to delegate these tough (but rarely
  4035                  needed) choices to the user.  Temporarily (???), it is
  4036                  implemented as C macros.
  4037 
  4038                  Essentially, there are 3 things to do: return 0 (handle to the
  4039                  legacy processing code [ignoring the character payload]; keep
  4040                  some modifiers (so that they will be processed by the binding
  4041                  system [on top of the character payload]; strip modifiers [so
  4042                  that `self-insert' is going to be triggered with the character
  4043                  payload]).
  4044 
  4045                  The default below should cover 99.9999% of cases:
  4046                    (a) strip Alt- in the hairy case only;
  4047                        (stripping = not ignoring)
  4048                    (l) for lAlt-lCtrl, ignore the char in simple cases only;
  4049                    (g) for what looks like AltGr, ignore the modifiers;
  4050                    (d) for what looks like lCtrl-rCtrl-Alt (probably
  4051                        AltGr-rCtrl), ignore the character in simple cases only;
  4052                    (b) for other cases of Ctrl-Alt, ignore the character in
  4053                        simple cases only.
  4054 
  4055                  Essentially, in all hairy cases, and in looks-like-AltGr case,
  4056                  we keep the character, ignoring the modifiers.  In all the
  4057                  other cases, we ignore the delivered character.  */
  4058 #define S_TYPES_TO_IGNORE_CHARACTER_PAYLOAD "aldb"
  4059 #define S_TYPES_TO_REPORT_CHARACTER_PAYLOAD_WITH_MODIFIERS ""
  4060               if (strchr (S_TYPES_TO_IGNORE_CHARACTER_PAYLOAD,
  4061                           type_CtrlAlt[hairy]))
  4062                 return 0;
  4063               /* If in neither list, report all the modifiers we see COMBINED
  4064                  WITH the reported character.  */
  4065               if (strchr (S_TYPES_TO_REPORT_CHARACTER_PAYLOAD_WITH_MODIFIERS,
  4066                           type_CtrlAlt[hairy]))
  4067                 strip_ExtraMods = 0;
  4068             }
  4069         }
  4070       if (strip_ExtraMods)
  4071         wmsg.dwModifiers = wmsg.dwModifiers & shift_modifier;
  4072 
  4073       signal_user_input ();
  4074       while (count--)
  4075         {
  4076           FPRINTF_WM_CHARS((stderr, "unichar %#06x\n", *b));
  4077           my_post_msg (&wmsg, hwnd, WM_UNICHAR, *b++, lParam);
  4078         }
  4079       if (!ctrl_cnt) /* Process ALSO as ctrl */
  4080         return 1;
  4081       else
  4082         FPRINTF_WM_CHARS((stderr, "extra ctrl char\n"));
  4083       return -1;
  4084     }
  4085   else if (is_dead >= 0)
  4086     {
  4087       FPRINTF_WM_CHARS((stderr, "dead %#06x\n", is_dead));
  4088       after_deadkey = is_dead;
  4089       return 1;
  4090     }
  4091   return 0;
  4092 }
  4093 
  4094 /* Main window procedure */
  4095 
  4096 static LRESULT CALLBACK
  4097 w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  4098 {
  4099   struct frame *f;
  4100   struct w32_display_info *dpyinfo = &one_w32_display_info;
  4101   W32Msg wmsg;
  4102   int windows_translate;
  4103   int key;
  4104 
  4105   /* Note that it is okay to call w32_window_to_frame, even though we are
  4106      not running in the main lisp thread, because frame deletion
  4107      requires the lisp thread to synchronize with this thread.  Thus, if
  4108      a frame struct is returned, it can be used without concern that the
  4109      lisp thread might make it disappear while we are using it.
  4110 
  4111      NB. Walking the frame list in this thread is safe (as long as
  4112      writes of Lisp_Object slots are atomic, which they are on Windows).
  4113      Although delete-frame can destructively modify the frame list while
  4114      we are walking it, a garbage collection cannot occur until after
  4115      delete-frame has synchronized with this thread.
  4116 
  4117      It is also safe to use functions that make GDI calls, such as
  4118      w32_clear_rect, because these functions must obtain a DC handle
  4119      from the frame struct using get_frame_dc which is thread-aware.  */
  4120 
  4121   switch (msg)
  4122     {
  4123     case WM_ERASEBKGND:
  4124       f = w32_window_to_frame (dpyinfo, hwnd);
  4125 
  4126       enter_crit ();
  4127       if (f && (w32_disable_double_buffering
  4128                 || !FRAME_OUTPUT_DATA (f)->paint_buffer))
  4129         {
  4130           HDC hdc = get_frame_dc (f);
  4131           GetUpdateRect (hwnd, &wmsg.rect, FALSE);
  4132           w32_clear_rect (f, hdc, &wmsg.rect);
  4133           release_frame_dc (f, hdc);
  4134 
  4135 #if defined (W32_DEBUG_DISPLAY)
  4136           DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
  4137                      f,
  4138                      wmsg.rect.left, wmsg.rect.top,
  4139                      wmsg.rect.right, wmsg.rect.bottom));
  4140 #endif /* W32_DEBUG_DISPLAY */
  4141         }
  4142       leave_crit ();
  4143       return 1;
  4144     case WM_PALETTECHANGED:
  4145       /* ignore our own changes */
  4146       if ((HWND)wParam != hwnd)
  4147         {
  4148           f = w32_window_to_frame (dpyinfo, hwnd);
  4149           if (f)
  4150             /* get_frame_dc will realize our palette and force all
  4151                frames to be redrawn if needed. */
  4152             release_frame_dc (f, get_frame_dc (f));
  4153         }
  4154       return 0;
  4155     case WM_PAINT:
  4156       {
  4157         PAINTSTRUCT paintStruct;
  4158         RECT update_rect;
  4159         memset (&update_rect, 0, sizeof (update_rect));
  4160 
  4161         f = w32_window_to_frame (dpyinfo, hwnd);
  4162         if (f == 0)
  4163           {
  4164             DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
  4165             return 0;
  4166           }
  4167 
  4168         /* MSDN Docs say not to call BeginPaint if GetUpdateRect
  4169            fails.  Apparently this can happen under some
  4170            circumstances.  */
  4171         if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting)
  4172           {
  4173             enter_crit ();
  4174             BeginPaint (hwnd, &paintStruct);
  4175 
  4176             /* The rectangles returned by GetUpdateRect and BeginPaint
  4177                do not always match.  Play it safe by assuming both areas
  4178                are invalid.  */
  4179             UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint));
  4180 
  4181 #if defined (W32_DEBUG_DISPLAY)
  4182             DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
  4183                        f,
  4184                        wmsg.rect.left, wmsg.rect.top,
  4185                        wmsg.rect.right, wmsg.rect.bottom));
  4186             DebPrint (("  [update region is %d,%d-%d,%d]\n",
  4187                        update_rect.left, update_rect.top,
  4188                        update_rect.right, update_rect.bottom));
  4189 #endif
  4190             /* Under double-buffering, update the frame from the back
  4191                buffer, to prevent a "ghost" of the selection dialog to
  4192                be left on display while the user selects in the dialog.  */
  4193             if (w32_selection_dialog_open
  4194                 && !w32_disable_double_buffering
  4195                 && FRAME_OUTPUT_DATA (f)->paint_dc)
  4196               BitBlt (FRAME_OUTPUT_DATA (f)->paint_buffer_handle,
  4197                       0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
  4198                       FRAME_OUTPUT_DATA (f)->paint_dc, 0, 0, SRCCOPY);
  4199 
  4200             EndPaint (hwnd, &paintStruct);
  4201             leave_crit ();
  4202 
  4203             /* Change the message type to prevent Windows from
  4204                combining WM_PAINT messages in the Lisp thread's queue,
  4205                since Windows assumes that each message queue is
  4206                dedicated to one frame and does not bother checking
  4207                that hwnd matches before combining them.  */
  4208             my_post_msg (&wmsg, hwnd, WM_EMACS_PAINT, wParam, lParam);
  4209 
  4210             return 0;
  4211           }
  4212 
  4213         /* If GetUpdateRect returns 0 (meaning there is no update
  4214            region), assume the whole window needs to be repainted.  */
  4215         GetClientRect (hwnd, &wmsg.rect);
  4216         my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4217         return 0;
  4218       }
  4219 
  4220     case WM_INPUTLANGCHANGE:
  4221       /* Inform lisp thread of keyboard layout changes.  */
  4222       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4223 
  4224       /* The state of the finite automaton is separate per every input
  4225          language environment (so it does not change when one switches
  4226          to a different window with the same environment).  Moreover,
  4227          the experiments show that the state is not remembered when
  4228          one switches back to the pre-previous environment.  */
  4229       after_deadkey = -1;
  4230 
  4231       /* XXXX??? What follows is a COMPLETE misunderstanding of Windows!  */
  4232 
  4233       /* Clear dead keys in the keyboard state; for simplicity only
  4234          preserve modifier key states.  */
  4235       {
  4236         int i;
  4237         BYTE keystate[256];
  4238 
  4239         GetKeyboardState (keystate);
  4240         for (i = 0; i < 256; i++)
  4241           if (1
  4242               && i != VK_SHIFT
  4243               && i != VK_LSHIFT
  4244               && i != VK_RSHIFT
  4245               && i != VK_CAPITAL
  4246               && i != VK_NUMLOCK
  4247               && i != VK_SCROLL
  4248               && i != VK_CONTROL
  4249               && i != VK_LCONTROL
  4250               && i != VK_RCONTROL
  4251               && i != VK_MENU
  4252               && i != VK_LMENU
  4253               && i != VK_RMENU
  4254               && i != VK_LWIN
  4255               && i != VK_RWIN)
  4256             keystate[i] = 0;
  4257         SetKeyboardState (keystate);
  4258       }
  4259       goto dflt;
  4260 
  4261     case WM_HOTKEY:
  4262       /* Synchronize hot keys with normal input.  */
  4263       PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
  4264       return (0);
  4265 
  4266     case WM_KEYUP:
  4267     case WM_SYSKEYUP:
  4268       record_keyup (wParam, lParam);
  4269       goto dflt;
  4270 
  4271     case WM_KEYDOWN:
  4272     case WM_SYSKEYDOWN:
  4273       /* Ignore keystrokes we fake ourself; see below.  */
  4274       if (dpyinfo->faked_key == wParam)
  4275         {
  4276           dpyinfo->faked_key = 0;
  4277           /* Make sure TranslateMessage sees them though (as long as
  4278              they don't produce WM_CHAR messages).  This ensures that
  4279              indicator lights are toggled promptly on Windows 9x, for
  4280              example.  */
  4281           if (wParam < 256 && lispy_function_keys[wParam])
  4282             {
  4283               windows_translate = 1;
  4284               goto translate;
  4285             }
  4286           return 0;
  4287         }
  4288 
  4289       /* Synchronize modifiers with current keystroke.  */
  4290       sync_modifiers ();
  4291       record_keydown (wParam, lParam);
  4292       if (w32_use_fallback_wm_chars_method)
  4293         wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
  4294 
  4295       windows_translate = 0;
  4296 
  4297       switch (wParam)
  4298         {
  4299         case VK_LWIN:
  4300           if (!w32_kbdhook_active && NILP (Vw32_pass_lwindow_to_system))
  4301             {
  4302               /* Prevent system from acting on keyup (which opens the
  4303                  Start menu if no other key was pressed) by simulating a
  4304                  press of Space which we will ignore.  */
  4305               if (GetAsyncKeyState (wParam) & 1)
  4306                 {
  4307                   if (FIXNUMP (Vw32_phantom_key_code))
  4308                     key = XUFIXNUM (Vw32_phantom_key_code) & 255;
  4309                   else
  4310                     key = VK_SPACE;
  4311                   dpyinfo->faked_key = key;
  4312                   keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
  4313                 }
  4314             }
  4315           if (!NILP (Vw32_lwindow_modifier))
  4316             return 0;
  4317           break;
  4318         case VK_RWIN:
  4319           if (!w32_kbdhook_active && NILP (Vw32_pass_rwindow_to_system))
  4320             {
  4321               if (GetAsyncKeyState (wParam) & 1)
  4322                 {
  4323                   if (FIXNUMP (Vw32_phantom_key_code))
  4324                     key = XUFIXNUM (Vw32_phantom_key_code) & 255;
  4325                   else
  4326                     key = VK_SPACE;
  4327                   dpyinfo->faked_key = key;
  4328                   keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
  4329                 }
  4330             }
  4331           if (!NILP (Vw32_rwindow_modifier))
  4332             return 0;
  4333           break;
  4334         case VK_APPS:
  4335           if (!NILP (Vw32_apps_modifier))
  4336             return 0;
  4337           break;
  4338         case VK_MENU:
  4339           if (NILP (Vw32_pass_alt_to_system))
  4340             /* Prevent DefWindowProc from activating the menu bar if an
  4341                Alt key is pressed and released by itself.  */
  4342             return 0;
  4343           windows_translate = 1;
  4344           break;
  4345         case VK_CAPITAL:
  4346           /* Decide whether to treat as modifier or function key.  */
  4347           if (NILP (Vw32_enable_caps_lock))
  4348             goto disable_lock_key;
  4349           windows_translate = 1;
  4350           break;
  4351         case VK_NUMLOCK:
  4352           /* Decide whether to treat as modifier or function key.  */
  4353           if (NILP (Vw32_enable_num_lock))
  4354             goto disable_lock_key;
  4355           windows_translate = 1;
  4356           break;
  4357         case VK_SCROLL:
  4358           /* Decide whether to treat as modifier or function key.  */
  4359           if (NILP (Vw32_scroll_lock_modifier))
  4360             goto disable_lock_key;
  4361           windows_translate = 1;
  4362           break;
  4363         disable_lock_key:
  4364           /* Ensure the appropriate lock key state (and indicator light)
  4365              remains in the same state. We do this by faking another
  4366              press of the relevant key.  Apparently, this really is the
  4367              only way to toggle the state of the indicator lights.  */
  4368           dpyinfo->faked_key = wParam;
  4369           keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
  4370                        KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  4371           keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
  4372                        KEYEVENTF_EXTENDEDKEY | 0, 0);
  4373           keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
  4374                        KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  4375           /* Ensure indicator lights are updated promptly on Windows 9x
  4376              (TranslateMessage apparently does this), after forwarding
  4377              input event.  */
  4378           post_character_message (hwnd, msg, wParam, lParam,
  4379                                   w32_get_key_modifiers (wParam, lParam));
  4380           windows_translate = 1;
  4381           break;
  4382         case VK_CONTROL:
  4383         case VK_SHIFT:
  4384         case VK_PROCESSKEY:  /* Generated by IME.  */
  4385           windows_translate = 1;
  4386           break;
  4387         case VK_CANCEL:
  4388           /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
  4389              which is confusing for purposes of key binding; convert
  4390              VK_CANCEL events into VK_PAUSE events.  */
  4391           wParam = VK_PAUSE;
  4392           break;
  4393         case VK_PAUSE:
  4394           /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
  4395              for purposes of key binding; convert these back into
  4396              VK_NUMLOCK events, at least when we want to see NumLock key
  4397              presses.  (Note that there is never any possibility that
  4398              VK_PAUSE with Ctrl really is C-Pause as per above.)  */
  4399           if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
  4400             wParam = VK_NUMLOCK;
  4401           break;
  4402         default:
  4403           if (w32_unicode_gui && !w32_use_fallback_wm_chars_method)
  4404             {
  4405               /* If this event generates characters or deadkeys, do
  4406                  not interpret it as a "raw combination of modifiers
  4407                  and keysym".  Hide deadkeys, and use the generated
  4408                  character(s) instead of the keysym.  (Backward
  4409                  compatibility: exceptions for numpad keys generating
  4410                  0-9 . , / * - +, and for extra-Alt combined with a
  4411                  non-Latin char.)
  4412 
  4413                  Try to not report modifiers which have effect on
  4414                  which character or deadkey is generated.
  4415 
  4416                  Example (contrived): if rightAlt-? generates f (on a
  4417                  Cyrillic keyboard layout), and Ctrl, leftAlt do not
  4418                  affect the generated character, one wants to report
  4419                  Ctrl-leftAlt-f if the user presses
  4420                  Ctrl-leftAlt-rightAlt-?.  */
  4421               int res;
  4422 #if 0
  4423               /* Some of WM_CHAR may be fed to us directly, some are
  4424                  results of TranslateMessage().  Using 0 as the first
  4425                  argument (in a separate call) might help us
  4426                  distinguish these two cases.
  4427 
  4428                  However, the keypress feeders would most probably
  4429                  expect the "standard" message pump, when
  4430                  TranslateMessage() is called on EVERY KeyDown/KeyUp
  4431                  event.  So they may feed us Down-Ctrl Down-FAKE
  4432                  Char-o and expect us to recognize it as Ctrl-o.
  4433                  Using 0 as the first argument would interfere with
  4434                  this.   */
  4435               deliver_wm_chars (0, hwnd, msg, wParam, lParam, 1);
  4436 #endif
  4437               /* Processing the generated WM_CHAR messages *WHILE* we
  4438                  handle KEYDOWN/UP event is the best choice, since
  4439                  without any fuss, we know all 3 of: scancode, virtual
  4440                  keycode, and expansion.  (Additionally, one knows
  4441                  boundaries of expansion of different keypresses.)  */
  4442               res = deliver_wm_chars (1, hwnd, msg, wParam, lParam, 1);
  4443               windows_translate = -(res != 0);
  4444               if (res > 0) /* Bound to character(s) or a deadkey */
  4445                 break;
  4446               /* deliver_wm_chars may make some branches after this vestigal.  */
  4447             }
  4448           wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
  4449           /* If not defined as a function key, change it to a WM_CHAR message.  */
  4450           if (wParam > 255 || !lispy_function_keys[wParam])
  4451             {
  4452               DWORD modifiers = w32_construct_console_modifiers ();
  4453 
  4454               if (!NILP (Vw32_recognize_altgr)
  4455                   && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
  4456                 {
  4457                   /* Always let TranslateMessage handle AltGr key chords;
  4458                      for some reason, ToAscii doesn't always process AltGr
  4459                      chords correctly.  */
  4460                   windows_translate = 1;
  4461                 }
  4462               else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
  4463                 {
  4464                   /* Handle key chords including any modifiers other
  4465                      than shift directly, in order to preserve as much
  4466                      modifier information as possible.  */
  4467                   if ('A' <= wParam && wParam <= 'Z')
  4468                     {
  4469                       /* Don't translate modified alphabetic keystrokes,
  4470                          so the user doesn't need to constantly switch
  4471                          layout to type control or meta keystrokes when
  4472                          the normal layout translates alphabetic
  4473                          characters to non-ascii characters.  */
  4474                       if (!modifier_set (VK_SHIFT))
  4475                         wParam += ('a' - 'A');
  4476                       msg = WM_CHAR;
  4477                     }
  4478                   else
  4479                     {
  4480                       /* Try to handle other keystrokes by determining the
  4481                          base character (ie. translating the base key plus
  4482                          shift modifier).  */
  4483                       int add;
  4484                       KEY_EVENT_RECORD key;
  4485 
  4486                       key.bKeyDown = TRUE;
  4487                       key.wRepeatCount = 1;
  4488                       key.wVirtualKeyCode = wParam;
  4489                       key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
  4490                       key.uChar.AsciiChar = 0;
  4491                       key.dwControlKeyState = modifiers;
  4492 
  4493                       add = w32_kbd_patch_key (&key, w32_keyboard_codepage);
  4494                       /* 0 means an unrecognized keycode, negative means
  4495                          dead key.  Ignore both.  */
  4496                       while (--add >= 0)
  4497                         {
  4498                           /* Forward asciified character sequence.  */
  4499                           post_character_message
  4500                             (hwnd, WM_CHAR,
  4501                              (unsigned char) key.uChar.AsciiChar, lParam,
  4502                              w32_get_key_modifiers (wParam, lParam));
  4503                           w32_kbd_patch_key (&key, w32_keyboard_codepage);
  4504                         }
  4505                       return 0;
  4506                     }
  4507                 }
  4508               else
  4509                 {
  4510                   /* Let TranslateMessage handle everything else.  */
  4511                   windows_translate = 1;
  4512                 }
  4513             }
  4514         }
  4515 
  4516     if (windows_translate == -1)
  4517       break;
  4518     translate:
  4519       if (windows_translate)
  4520         {
  4521           MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
  4522           windows_msg.time = GetMessageTime ();
  4523           TranslateMessage (&windows_msg);
  4524           goto dflt;
  4525         }
  4526       /* Fall through */
  4527       FALLTHROUGH;
  4528 
  4529     case WM_SYSCHAR:
  4530     case WM_CHAR:
  4531       if (wParam > 255 )
  4532         {
  4533           W32Msg wmsg;
  4534 
  4535           wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
  4536           signal_user_input ();
  4537           my_post_msg (&wmsg, hwnd, WM_UNICHAR, wParam, lParam);
  4538 
  4539         }
  4540       else
  4541         post_character_message (hwnd, msg, wParam, lParam,
  4542                                 w32_get_key_modifiers (wParam, lParam));
  4543       break;
  4544 
  4545     case WM_UNICHAR:
  4546       /* WM_UNICHAR looks promising from the docs, but the exact
  4547          circumstances in which TranslateMessage sends it is one of those
  4548          Microsoft secret API things that EU and US courts are supposed
  4549          to have put a stop to already. Spy++ shows it being sent to Notepad
  4550          and other MS apps, but never to Emacs.
  4551 
  4552          Some third party IMEs send it in accordance with the official
  4553          documentation though, so handle it here.
  4554 
  4555          UNICODE_NOCHAR is used to test for support for this message.
  4556          TRUE indicates that the message is supported.  */
  4557       if (wParam == UNICODE_NOCHAR)
  4558         return TRUE;
  4559 
  4560       {
  4561         W32Msg wmsg;
  4562         wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
  4563         signal_user_input ();
  4564         my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4565       }
  4566       break;
  4567 
  4568     case WM_IME_CHAR:
  4569       /* If we can't get the IME result as Unicode, use default processing,
  4570          which will at least allow characters decodable in the system locale
  4571          get through.  */
  4572       if (!get_composition_string_fn)
  4573         goto dflt;
  4574 
  4575       else if (!ignore_ime_char)
  4576         {
  4577           wchar_t * buffer;
  4578           int size, i;
  4579           W32Msg wmsg;
  4580           HIMC context = get_ime_context_fn (hwnd);
  4581           wmsg.dwModifiers =
  4582             w32_ignore_modifiers_on_IME_input
  4583             ? 0
  4584             : w32_get_key_modifiers (wParam, lParam);
  4585           /* Get buffer size.  */
  4586           size = get_composition_string_fn (context, GCS_RESULTSTR, NULL, 0);
  4587           buffer = alloca (size);
  4588           size = get_composition_string_fn (context, GCS_RESULTSTR,
  4589                                             buffer, size);
  4590           release_ime_context_fn (hwnd, context);
  4591 
  4592           signal_user_input ();
  4593           for (i = 0; i < size / sizeof (wchar_t); i++)
  4594             {
  4595               my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i],
  4596                            lParam);
  4597             }
  4598           /* Ignore the messages for the rest of the
  4599              characters in the string that was output above.  */
  4600           ignore_ime_char = (size / sizeof (wchar_t)) - 1;
  4601         }
  4602       else
  4603         ignore_ime_char--;
  4604 
  4605       break;
  4606 
  4607     case WM_IME_STARTCOMPOSITION:
  4608       if (!set_ime_composition_window_fn)
  4609         goto dflt;
  4610       else
  4611         {
  4612           COMPOSITIONFORM form;
  4613           HIMC context;
  4614           struct window *w;
  4615 
  4616           /* Implementation note: The code below does something that
  4617              one shouldn't do: it accesses the window object from a
  4618              separate thread, while the main (a.k.a. "Lisp") thread
  4619              runs and can legitimately delete and even GC it.  That is
  4620              why we are extra careful not to futz with a window that
  4621              is different from the one recorded when the system caret
  4622              coordinates were last modified.  That is also why we are
  4623              careful not to move the IME window if the window
  4624              described by W was deleted, as indicated by its buffer
  4625              field being reset to nil.  */
  4626           f = w32_window_to_frame (dpyinfo, hwnd);
  4627           if (!(f && FRAME_LIVE_P (f)))
  4628             goto dflt;
  4629           w = XWINDOW (FRAME_SELECTED_WINDOW (f));
  4630           /* Punt if someone changed the frame's selected window
  4631              behind our back. */
  4632           if (w != w32_system_caret_window)
  4633             goto dflt;
  4634 
  4635           form.dwStyle = CFS_RECT;
  4636           form.ptCurrentPos.x = w32_system_caret_x;
  4637           form.ptCurrentPos.y = w32_system_caret_y;
  4638 
  4639           form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
  4640           form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
  4641                              + w32_system_caret_hdr_height);
  4642           form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
  4643                                - WINDOW_RIGHT_MARGIN_WIDTH (w)
  4644                                - WINDOW_RIGHT_FRINGE_WIDTH (w));
  4645           form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
  4646                                 - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
  4647                                 - w32_system_caret_mode_height);
  4648 
  4649           /* Punt if the window was deleted behind our back.  */
  4650           if (!BUFFERP (w->contents))
  4651             goto dflt;
  4652 
  4653           context = get_ime_context_fn (hwnd);
  4654 
  4655           if (!context)
  4656             goto dflt;
  4657 
  4658           set_ime_composition_window_fn (context, &form);
  4659           release_ime_context_fn (hwnd, context);
  4660         }
  4661       /* FIXME: somehow "goto dflt" here instead of "break" causes
  4662          popup dialogs, such as the ones shown by File->Open File and
  4663          w32-select-font, to become hidden behind their parent frame,
  4664          when focus-follows-mouse is in effect.  See bug#11732.  But
  4665          if we don't "goto dflt", users of IME cannot type text
  4666          supported by the input method...  */
  4667       goto dflt;
  4668 
  4669     case WM_IME_ENDCOMPOSITION:
  4670       ignore_ime_char = 0;
  4671       goto dflt;
  4672 
  4673       /* Simulate middle mouse button events when left and right buttons
  4674          are used together, but only if user has two button mouse. */
  4675     case WM_LBUTTONDOWN:
  4676     case WM_RBUTTONDOWN:
  4677       if (w32_num_mouse_buttons > 2)
  4678         goto handle_plain_button;
  4679 
  4680       {
  4681         int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
  4682         int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
  4683 
  4684         if (button_state & this)
  4685           return 0;
  4686 
  4687         /* Don't capture mouse when dropping.  */
  4688         if (button_state == 0 && !EQ (track_mouse, Qdropping))
  4689           SetCapture (hwnd);
  4690 
  4691         button_state |= this;
  4692 
  4693         if (button_state & other)
  4694           {
  4695             if (mouse_button_timer)
  4696               {
  4697                 KillTimer (hwnd, mouse_button_timer);
  4698                 mouse_button_timer = 0;
  4699 
  4700                 /* Generate middle mouse event instead. */
  4701                 msg = WM_MBUTTONDOWN;
  4702                 button_state |= MMOUSE;
  4703               }
  4704             else if (button_state & MMOUSE)
  4705               {
  4706                 /* Ignore button event if we've already generated a
  4707                    middle mouse down event.  This happens if the
  4708                    user releases and press one of the two buttons
  4709                    after we've faked a middle mouse event. */
  4710                 return 0;
  4711               }
  4712             else
  4713               {
  4714                 /* Flush out saved message. */
  4715                 post_msg (&saved_mouse_button_msg);
  4716               }
  4717             wmsg.dwModifiers = w32_get_modifiers ();
  4718             my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4719             signal_user_input ();
  4720 
  4721             /* Clear message buffer. */
  4722             saved_mouse_button_msg.msg.hwnd = 0;
  4723           }
  4724         else
  4725           {
  4726             /* Hold onto message for now. */
  4727             mouse_button_timer =
  4728               SetTimer (hwnd, MOUSE_BUTTON_ID,
  4729                         w32_mouse_button_tolerance, NULL);
  4730             saved_mouse_button_msg.msg.hwnd = hwnd;
  4731             saved_mouse_button_msg.msg.message = msg;
  4732             saved_mouse_button_msg.msg.wParam = wParam;
  4733             saved_mouse_button_msg.msg.lParam = lParam;
  4734             saved_mouse_button_msg.msg.time = GetMessageTime ();
  4735             saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
  4736           }
  4737       }
  4738       return 0;
  4739 
  4740     case WM_LBUTTONUP:
  4741     case WM_RBUTTONUP:
  4742       if (w32_num_mouse_buttons > 2)
  4743         goto handle_plain_button;
  4744 
  4745       {
  4746         int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
  4747         int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
  4748 
  4749         if ((button_state & this) == 0)
  4750           return 0;
  4751 
  4752         button_state &= ~this;
  4753 
  4754         if (button_state & MMOUSE)
  4755           {
  4756             /* Only generate event when second button is released. */
  4757             if ((button_state & other) == 0)
  4758               {
  4759                 msg = WM_MBUTTONUP;
  4760                 button_state &= ~MMOUSE;
  4761 
  4762                 if (button_state) emacs_abort ();
  4763               }
  4764             else
  4765               return 0;
  4766           }
  4767         else
  4768           {
  4769             /* Flush out saved message if necessary. */
  4770             if (saved_mouse_button_msg.msg.hwnd)
  4771               {
  4772                 post_msg (&saved_mouse_button_msg);
  4773               }
  4774           }
  4775         wmsg.dwModifiers = w32_get_modifiers ();
  4776         my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4777         signal_user_input ();
  4778 
  4779         /* Always clear message buffer and cancel timer. */
  4780         saved_mouse_button_msg.msg.hwnd = 0;
  4781         KillTimer (hwnd, mouse_button_timer);
  4782         mouse_button_timer = 0;
  4783 
  4784         if (button_state == 0)
  4785           ReleaseCapture ();
  4786       }
  4787       return 0;
  4788 
  4789     case WM_XBUTTONDOWN:
  4790     case WM_XBUTTONUP:
  4791       if (w32_pass_extra_mouse_buttons_to_system)
  4792         goto dflt;
  4793       /* else fall through and process them.  */
  4794       FALLTHROUGH;
  4795     case WM_MBUTTONDOWN:
  4796     case WM_MBUTTONUP:
  4797     handle_plain_button:
  4798       {
  4799         BOOL up;
  4800         int button;
  4801 
  4802         /* Ignore middle and extra buttons as long as the menu is active.  */
  4803         f = w32_window_to_frame (dpyinfo, hwnd);
  4804         if (f && f->output_data.w32->menubar_active)
  4805           return 0;
  4806 
  4807         if (parse_button (msg, HIWORD (wParam), &button, &up))
  4808           {
  4809             if (up)
  4810               ReleaseCapture ();
  4811             /* Don't capture mouse when dropping.  */
  4812             else if (!EQ (track_mouse, Qdropping))
  4813               SetCapture (hwnd);
  4814             button = (button == 0) ? LMOUSE :
  4815               ((button == 1) ? MMOUSE  : RMOUSE);
  4816             if (up)
  4817               button_state &= ~button;
  4818             else
  4819               button_state |= button;
  4820           }
  4821       }
  4822 
  4823       if (f && (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN
  4824                 || msg == WM_MBUTTONDOWN ||msg == WM_XBUTTONDOWN)
  4825           && !FRAME_NO_ACCEPT_FOCUS (f))
  4826         /* When clicking into a child frame or when clicking into a
  4827            parent frame with the child frame selected and
  4828            `no-accept-focus' is not set, select the clicked frame.  */
  4829         {
  4830           struct frame *p = FRAME_PARENT_FRAME (XFRAME (selected_frame));
  4831 
  4832           if (FRAME_PARENT_FRAME (f) || f == p)
  4833             {
  4834               SetFocus (hwnd);
  4835               SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  4836             }
  4837         }
  4838 
  4839       wmsg.dwModifiers = w32_get_modifiers ();
  4840       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4841       signal_user_input ();
  4842 
  4843       /* Need to return true for XBUTTON messages, false for others,
  4844          to indicate that we processed the message.  */
  4845       return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
  4846 
  4847     case WM_MOUSEMOVE:
  4848       f = w32_window_to_frame (dpyinfo, hwnd);
  4849       if (f)
  4850         {
  4851           /* Ignore mouse movements as long as the menu is active.
  4852              These movements are processed by the window manager
  4853              anyway, and it's wrong to handle them as if they happened
  4854              on the underlying frame.  */
  4855           if (f->output_data.w32->menubar_active)
  4856             return 0;
  4857 
  4858           /* If the mouse moved, and the mouse pointer is invisible,
  4859              make it visible again.  We do this here so as to be able
  4860              to show the mouse pointer even when the main
  4861              (a.k.a. "Lisp") thread is busy doing something.  */
  4862           static int last_x, last_y;
  4863           int x = GET_X_LPARAM (lParam);
  4864           int y = GET_Y_LPARAM (lParam);
  4865 
  4866           if (f->pointer_invisible
  4867               && (x != last_x || y != last_y))
  4868             f->pointer_invisible = false;
  4869 
  4870           last_x = x;
  4871           last_y = y;
  4872         }
  4873 
  4874       /* If the mouse has just moved into the frame, start tracking
  4875          it, so we will be notified when it leaves the frame.  Mouse
  4876          tracking only works under W98 and NT4 and later. On earlier
  4877          versions, there is no way of telling when the mouse leaves the
  4878          frame, so we just have to put up with help-echo and mouse
  4879          highlighting remaining while the frame is not active.  */
  4880       if (track_mouse_event_fn && !track_mouse_window
  4881           /* If the menu bar is active, turning on tracking of mouse
  4882              movement events might send these events to the tooltip
  4883              frame, if the user happens to move the mouse pointer over
  4884              the tooltip.  But since we don't process events for
  4885              tooltip frames, this causes Windows to present a
  4886              hourglass cursor, which is ugly and unexpected.  So don't
  4887              enable tracking mouse events in this case; they will be
  4888              restarted when the menu pops down.  (Confusingly, the
  4889              menubar_active member of f->output_data.w32, tested
  4890              above, is only set when a menu was popped up _not_ from
  4891              the frame's menu bar, but via x-popup-menu.)  */
  4892           && !menubar_in_use)
  4893         {
  4894           TRACKMOUSEEVENT tme;
  4895           tme.cbSize = sizeof (tme);
  4896           tme.dwFlags = TME_LEAVE;
  4897           tme.hwndTrack = hwnd;
  4898           tme.dwHoverTime = HOVER_DEFAULT;
  4899 
  4900           track_mouse_event_fn (&tme);
  4901           track_mouse_window = hwnd;
  4902         }
  4903       FALLTHROUGH;
  4904     case WM_HSCROLL:
  4905     case WM_VSCROLL:
  4906       if (w32_mouse_move_interval <= 0
  4907           || (msg == WM_MOUSEMOVE && button_state == 0))
  4908         {
  4909           wmsg.dwModifiers = w32_get_modifiers ();
  4910           my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4911           return 0;
  4912         }
  4913 
  4914       /* Hang onto mouse move and scroll messages for a bit, to avoid
  4915          sending such events to Emacs faster than it can process them.
  4916          If we get more events before the timer from the first message
  4917          expires, we just replace the first message. */
  4918 
  4919       if (saved_mouse_move_msg.msg.hwnd == 0)
  4920         mouse_move_timer =
  4921           SetTimer (hwnd, MOUSE_MOVE_ID,
  4922                     w32_mouse_move_interval, NULL);
  4923 
  4924       /* Hold onto message for now. */
  4925       saved_mouse_move_msg.msg.hwnd = hwnd;
  4926       saved_mouse_move_msg.msg.message = msg;
  4927       saved_mouse_move_msg.msg.wParam = wParam;
  4928       saved_mouse_move_msg.msg.lParam = lParam;
  4929       saved_mouse_move_msg.msg.time = GetMessageTime ();
  4930       saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
  4931 
  4932       return 0;
  4933 
  4934     case WM_MOUSEWHEEL:
  4935     case WM_DROPFILES:
  4936       wmsg.dwModifiers = w32_get_modifiers ();
  4937       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4938       signal_user_input ();
  4939       return 0;
  4940 
  4941     case WM_APPCOMMAND:
  4942       if (w32_pass_multimedia_buttons_to_system)
  4943         goto dflt;
  4944       /* Otherwise, pass to lisp, the same way we do with mousehwheel.  */
  4945       FALLTHROUGH;
  4946 
  4947       /* FIXME!!!  This is never reached so what's the purpose?  If the
  4948          non-zero return remark below is right we're doing it wrong all
  4949          the time.  */
  4950     case WM_MOUSEHWHEEL:
  4951       wmsg.dwModifiers = w32_get_modifiers ();
  4952       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  4953       signal_user_input ();
  4954       /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
  4955          handled, to prevent the system trying to handle it by faking
  4956          scroll bar events.  */
  4957       return 1;
  4958 
  4959     case WM_TIMER:
  4960       /* Flush out saved messages if necessary. */
  4961       if (wParam == mouse_button_timer)
  4962         {
  4963           if (saved_mouse_button_msg.msg.hwnd)
  4964             {
  4965               post_msg (&saved_mouse_button_msg);
  4966               signal_user_input ();
  4967               saved_mouse_button_msg.msg.hwnd = 0;
  4968             }
  4969           KillTimer (hwnd, mouse_button_timer);
  4970           mouse_button_timer = 0;
  4971         }
  4972       else if (wParam == mouse_move_timer)
  4973         {
  4974           if (saved_mouse_move_msg.msg.hwnd)
  4975             {
  4976               post_msg (&saved_mouse_move_msg);
  4977               saved_mouse_move_msg.msg.hwnd = 0;
  4978             }
  4979           KillTimer (hwnd, mouse_move_timer);
  4980           mouse_move_timer = 0;
  4981         }
  4982       else if (wParam == menu_free_timer)
  4983         {
  4984           KillTimer (hwnd, menu_free_timer);
  4985           menu_free_timer = 0;
  4986           f = w32_window_to_frame (dpyinfo, hwnd);
  4987           /* If a popup menu is active, don't wipe its strings.  */
  4988           if (menubar_in_use
  4989               && current_popup_menu == NULL)
  4990             {
  4991               /* Free memory used by owner-drawn and help-echo strings.  */
  4992               w32_free_menu_strings (hwnd);
  4993               if (f)
  4994                 f->output_data.w32->menubar_active = 0;
  4995               menubar_in_use = 0;
  4996             }
  4997         }
  4998       return 0;
  4999 
  5000     case WM_NCACTIVATE:
  5001       /* Windows doesn't send us focus messages when putting up and
  5002          taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
  5003          The only indication we get that something happened is receiving
  5004          this message afterwards.  So this is a good time to reset our
  5005          keyboard modifiers' state. */
  5006       reset_modifiers ();
  5007       goto dflt;
  5008 
  5009     case WM_INITMENU:
  5010       button_state = 0;
  5011       ReleaseCapture ();
  5012       /* We must ensure menu bar is fully constructed and up to date
  5013          before allowing user interaction with it.  To achieve this
  5014          we send this message to the lisp thread and wait for a
  5015          reply (whose value is not actually needed) to indicate that
  5016          the menu bar is now ready for use, so we can now return.
  5017 
  5018          To remain responsive in the meantime, we enter a nested message
  5019          loop that can process all other messages.
  5020 
  5021          However, we skip all this if the message results from calling
  5022          TrackPopupMenu - in fact, we must NOT attempt to send the lisp
  5023          thread a message because it is blocked on us at this point.  We
  5024          set menubar_active before calling TrackPopupMenu to indicate
  5025          this (there is no possibility of confusion with real menubar
  5026          being active).  */
  5027 
  5028       f = w32_window_to_frame (dpyinfo, hwnd);
  5029       if (f
  5030           && (f->output_data.w32->menubar_active
  5031               /* We can receive this message even in the absence of a
  5032                  menubar (ie. when the system menu is activated) - in this
  5033                  case we do NOT want to forward the message, otherwise it
  5034                  will cause the menubar to suddenly appear when the user
  5035                  had requested it to be turned off!  */
  5036               || f->output_data.w32->menubar_widget == NULL))
  5037         return 0;
  5038 
  5039       {
  5040         deferred_msg msg_buf;
  5041 
  5042         /* Detect if message has already been deferred; in this case
  5043            we cannot return any sensible value to ignore this.  */
  5044         if (find_deferred_msg (hwnd, msg) != NULL)
  5045           emacs_abort ();
  5046 
  5047         menubar_in_use = 1;
  5048 
  5049         return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
  5050       }
  5051 
  5052     case WM_EXITMENULOOP:
  5053       f = w32_window_to_frame (dpyinfo, hwnd);
  5054 
  5055       /* If a menu is still active, check again after a short delay,
  5056          since Windows often (always?) sends the WM_EXITMENULOOP
  5057          before the corresponding WM_COMMAND message.
  5058          Don't do this if a popup menu is active, since it is only
  5059          menubar menus that require cleaning up in this way.
  5060       */
  5061       if (f && menubar_in_use && current_popup_menu == NULL)
  5062         menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
  5063 
  5064       /* If hourglass cursor should be displayed, display it now.  */
  5065       if (f && f->output_data.w32->hourglass_p)
  5066         SetCursor (f->output_data.w32->hourglass_cursor);
  5067 
  5068       goto dflt;
  5069 
  5070     case WM_MENUSELECT:
  5071       /* Direct handling of help_echo in menus.  Should be safe now
  5072          that we generate the help_echo by placing a help event in the
  5073          keyboard buffer.  */
  5074       {
  5075         HMENU menu = (HMENU) lParam;
  5076         UINT menu_item = (UINT) LOWORD (wParam);
  5077         UINT flags = (UINT) HIWORD (wParam);
  5078 
  5079         w32_menu_display_help (hwnd, menu, menu_item, flags);
  5080       }
  5081       return 0;
  5082 
  5083     case WM_MEASUREITEM:
  5084       f = w32_window_to_frame (dpyinfo, hwnd);
  5085       if (f)
  5086         {
  5087           MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
  5088 
  5089           if (pMis->CtlType == ODT_MENU)
  5090             {
  5091               /* Work out dimensions for popup menu titles. */
  5092               char * title = (char *) pMis->itemData;
  5093               HDC hdc = GetDC (hwnd);
  5094               HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
  5095               LOGFONT menu_logfont;
  5096               HFONT old_font;
  5097               SIZE size;
  5098 
  5099               GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
  5100               menu_logfont.lfWeight = FW_BOLD;
  5101               menu_font = CreateFontIndirect (&menu_logfont);
  5102               old_font = SelectObject (hdc, menu_font);
  5103 
  5104               pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
  5105               if (title)
  5106                 {
  5107                   if (unicode_append_menu)
  5108                     GetTextExtentPoint32W (hdc, (WCHAR *) title,
  5109                                            wcslen ((WCHAR *) title),
  5110                                            &size);
  5111                   else
  5112                     GetTextExtentPoint32 (hdc, title, strlen (title), &size);
  5113 
  5114                   pMis->itemWidth = size.cx;
  5115                   if (pMis->itemHeight < size.cy)
  5116                     pMis->itemHeight = size.cy;
  5117                 }
  5118               else
  5119                 pMis->itemWidth = 0;
  5120 
  5121               SelectObject (hdc, old_font);
  5122               DeleteObject (menu_font);
  5123               ReleaseDC (hwnd, hdc);
  5124               return TRUE;
  5125             }
  5126         }
  5127       return 0;
  5128 
  5129     case WM_DRAWITEM:
  5130       f = w32_window_to_frame (dpyinfo, hwnd);
  5131       if (f)
  5132         {
  5133           DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
  5134 
  5135           if (pDis->CtlType == ODT_MENU)
  5136             {
  5137               /* Draw popup menu title. */
  5138               char * title = (char *) pDis->itemData;
  5139               if (title)
  5140                 {
  5141                   HDC hdc = pDis->hDC;
  5142                   HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
  5143                   LOGFONT menu_logfont;
  5144                   HFONT old_font;
  5145 
  5146                   GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
  5147                   menu_logfont.lfWeight = FW_BOLD;
  5148                   menu_font = CreateFontIndirect (&menu_logfont);
  5149                   old_font = SelectObject (hdc, menu_font);
  5150 
  5151                   /* Always draw title as if not selected.  */
  5152                   if (unicode_append_menu)
  5153                     ExtTextOutW (hdc,
  5154                                  pDis->rcItem.left
  5155                                  + GetSystemMetrics (SM_CXMENUCHECK),
  5156                                  pDis->rcItem.top,
  5157                                  ETO_OPAQUE, &pDis->rcItem,
  5158                                  (WCHAR *) title,
  5159                                  wcslen ((WCHAR *) title), NULL);
  5160                   else
  5161                     ExtTextOut (hdc,
  5162                                 pDis->rcItem.left
  5163                                 + GetSystemMetrics (SM_CXMENUCHECK),
  5164                                 pDis->rcItem.top,
  5165                                 ETO_OPAQUE, &pDis->rcItem,
  5166                                 title, strlen (title), NULL);
  5167 
  5168                   SelectObject (hdc, old_font);
  5169                   DeleteObject (menu_font);
  5170                 }
  5171               return TRUE;
  5172             }
  5173         }
  5174       return 0;
  5175 
  5176     case WM_MOUSEACTIVATE:
  5177       /* WM_MOUSEACTIVATE is the only way on Windows to implement the
  5178          `no-accept-focus' frame parameter.  This means that one can't
  5179          use the mouse to scroll a window on a non-selected frame.  */
  5180 
  5181       /* Still not right - can't distinguish between clicks in the
  5182          client area of the frame from clicks forwarded from the scroll
  5183          bars - may have to hook WM_NCHITTEST to remember the mouse
  5184          position and then check if it is in the client area
  5185          ourselves.  */
  5186 
  5187       /* Discard the mouse click that activates a frame, allowing the
  5188          user to click anywhere without changing point (or worse!).
  5189          Don't eat mouse clicks on scrollbars though!!  */
  5190 
  5191       if ((f = w32_window_to_frame (dpyinfo, hwnd))
  5192           && FRAME_NO_ACCEPT_FOCUS (f)
  5193           /* Ignore child frames, they don't accept focus anyway.  */
  5194           && !FRAME_PARENT_FRAME (f))
  5195         {
  5196           Lisp_Object frame;
  5197 
  5198           XSETFRAME (frame, f);
  5199           if (!EQ (selected_frame, frame))
  5200             /* Don't discard the message, GTK doesn't either.  */
  5201             return MA_NOACTIVATE; /* ANDEAT; */
  5202         }
  5203       goto dflt;
  5204 
  5205     case WM_MOUSELEAVE:
  5206       /* No longer tracking mouse.  */
  5207       track_mouse_window = NULL;
  5208       FALLTHROUGH;
  5209 
  5210     case WM_ACTIVATEAPP:
  5211     case WM_ACTIVATE:
  5212     case WM_WINDOWPOSCHANGED:
  5213     case WM_SHOWWINDOW:
  5214       /* Inform lisp thread that a frame might have just been obscured
  5215          or exposed, so should recheck visibility of all frames.  */
  5216       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5217       goto dflt;
  5218 
  5219     case WM_SETTINGCHANGE:
  5220       /* Inform the Lisp thread that some system-wide setting has
  5221          changed, so if Emacs is interested in some of them, it could
  5222          update its internal values.  */
  5223       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5224       goto dflt;
  5225 
  5226     case WM_SETFOCUS:
  5227       dpyinfo->faked_key = 0;
  5228       reset_modifiers ();
  5229       if (!w32_kbdhook_active)
  5230         register_hot_keys (hwnd);
  5231       goto command;
  5232     case WM_KILLFOCUS:
  5233       if (!w32_kbdhook_active)
  5234         unregister_hot_keys (hwnd);
  5235       button_state = 0;
  5236       ReleaseCapture ();
  5237       /* Relinquish the system caret.  */
  5238       if (w32_system_caret_hwnd)
  5239         {
  5240           w32_visible_system_caret_hwnd = NULL;
  5241           w32_system_caret_hwnd = NULL;
  5242           DestroyCaret ();
  5243         }
  5244       goto command;
  5245     case WM_COMMAND:
  5246       menubar_in_use = 0;
  5247       f = w32_window_to_frame (dpyinfo, hwnd);
  5248       if (f && HIWORD (wParam) == 0)
  5249         {
  5250           if (menu_free_timer)
  5251             {
  5252               KillTimer (hwnd, menu_free_timer);
  5253               menu_free_timer = 0;
  5254             }
  5255         }
  5256       FALLTHROUGH;
  5257     case WM_MOVE:
  5258     case WM_SIZE:
  5259     command:
  5260       wmsg.dwModifiers = w32_get_modifiers ();
  5261       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5262       goto dflt;
  5263 
  5264 #ifdef WINDOWSNT
  5265     case WM_CREATE:
  5266       setup_w32_kbdhook ();
  5267       goto dflt;
  5268 #endif
  5269 
  5270     case WM_DESTROY:
  5271 #ifdef WINDOWSNT
  5272       remove_w32_kbdhook ();
  5273 #endif
  5274       CoUninitialize ();
  5275       return 0;
  5276 
  5277     case WM_WTSSESSION_CHANGE:
  5278       if (wParam == WTS_SESSION_LOCK)
  5279         reset_w32_kbdhook_state ();
  5280       goto dflt;
  5281 
  5282     case WM_CLOSE:
  5283       wmsg.dwModifiers = w32_get_modifiers ();
  5284       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5285       return 0;
  5286 
  5287     case WM_ENDSESSION:
  5288       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5289       /* Allow time for Emacs to attempt an orderly shutdown.  If we
  5290          return, the process will be terminated immediately.  FIXME:
  5291          1000 seconds is too long to sleep if the shutdown attempt
  5292          fails (see bug#25875).  But if it fails, we want to find out
  5293          about it, so let's leave 1000 for now.  */
  5294       sleep (1000);
  5295       FALLTHROUGH;
  5296 
  5297     case WM_WINDOWPOSCHANGING:
  5298       /* Don't restrict the sizing of any kind of frames.  If the window
  5299          manager doesn't, there's no reason to do it ourselves.  */
  5300       return 0;
  5301 
  5302     case WM_GETMINMAXINFO:
  5303       /* Hack to allow resizing the Emacs frame above the screen size.
  5304          Note that Windows 9x limits coordinates to 16-bits.  */
  5305       ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
  5306       ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
  5307       return 0;
  5308 
  5309     case WM_SETCURSOR:
  5310       if (LOWORD (lParam) == HTCLIENT)
  5311         {
  5312           f = w32_window_to_frame (dpyinfo, hwnd);
  5313           if (f)
  5314             {
  5315               if (f->output_data.w32->hourglass_p
  5316                   && !menubar_in_use && !current_popup_menu)
  5317                 SetCursor (f->output_data.w32->hourglass_cursor);
  5318               else if (f->pointer_invisible)
  5319                 SetCursor (NULL);
  5320               else
  5321                 SetCursor (f->output_data.w32->current_cursor);
  5322             }
  5323 
  5324           return 0;
  5325         }
  5326       goto dflt;
  5327 
  5328     case WM_EMACS_SETCURSOR:
  5329       {
  5330         HCURSOR cursor = (HCURSOR) wParam;
  5331         f = w32_window_to_frame (dpyinfo, hwnd);
  5332         if (f && cursor)
  5333           {
  5334             f->output_data.w32->current_cursor = cursor;
  5335             /* Don't change the cursor while menu-bar menu is in use.  */
  5336             if (!f->output_data.w32->menubar_active
  5337                 && !f->output_data.w32->hourglass_p)
  5338               {
  5339                 if (f->pointer_invisible)
  5340                   SetCursor (NULL);
  5341                 else
  5342                   SetCursor (cursor);
  5343               }
  5344           }
  5345         return 0;
  5346       }
  5347 
  5348     case WM_EMACS_SHOWCURSOR:
  5349       {
  5350         ShowCursor ((BOOL) wParam);
  5351 
  5352         return 0;
  5353       }
  5354 
  5355     case WM_EMACS_CREATEVSCROLLBAR:
  5356       return (LRESULT) w32_createvscrollbar ((struct frame *) wParam,
  5357                                              (struct scroll_bar *) lParam);
  5358 
  5359     case WM_EMACS_CREATEHSCROLLBAR:
  5360       return (LRESULT) w32_createhscrollbar ((struct frame *) wParam,
  5361                                              (struct scroll_bar *) lParam);
  5362 
  5363     case WM_EMACS_SHOWWINDOW:
  5364       return ShowWindow ((HWND) wParam, (WPARAM) lParam);
  5365 
  5366     case WM_EMACS_BRINGTOTOP:
  5367     case WM_EMACS_SETFOREGROUND:
  5368       {
  5369         HWND foreground_window;
  5370         DWORD foreground_thread, retval;
  5371 
  5372         /* On NT 5.0, and apparently Windows 98, it is necessary to
  5373            attach to the thread that currently has focus in order to
  5374            pull the focus away from it.  */
  5375         foreground_window = GetForegroundWindow ();
  5376         foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
  5377         if (!foreground_window
  5378             || foreground_thread == GetCurrentThreadId ()
  5379             || !AttachThreadInput (GetCurrentThreadId (),
  5380                                    foreground_thread, TRUE))
  5381           foreground_thread = 0;
  5382 
  5383         retval = SetForegroundWindow ((HWND) wParam);
  5384         if (msg == WM_EMACS_BRINGTOTOP)
  5385           retval = BringWindowToTop ((HWND) wParam);
  5386 
  5387         /* Detach from the previous foreground thread.  */
  5388         if (foreground_thread)
  5389           AttachThreadInput (GetCurrentThreadId (),
  5390                              foreground_thread, FALSE);
  5391 
  5392         /* SetFocus to give/remove focus to/from a child window.  */
  5393         if (msg == WM_EMACS_SETFOREGROUND)
  5394           SetFocus ((HWND) wParam);
  5395 
  5396         return retval;
  5397       }
  5398 
  5399     case WM_EMACS_SETWINDOWPOS:
  5400       {
  5401         WINDOWPOS * pos = (WINDOWPOS *) wParam;
  5402         return SetWindowPos (hwnd, pos->hwndInsertAfter,
  5403                              pos->x, pos->y, pos->cx, pos->cy, pos->flags);
  5404       }
  5405 
  5406     case WM_EMACS_DESTROYWINDOW:
  5407       DragAcceptFiles ((HWND) wParam, FALSE);
  5408       return DestroyWindow ((HWND) wParam);
  5409 
  5410     case WM_EMACS_HIDE_CARET:
  5411       return HideCaret (hwnd);
  5412 
  5413     case WM_EMACS_SHOW_CARET:
  5414       return ShowCaret (hwnd);
  5415 
  5416     case WM_EMACS_DESTROY_CARET:
  5417       w32_system_caret_hwnd = NULL;
  5418       w32_visible_system_caret_hwnd = NULL;
  5419       return DestroyCaret ();
  5420 
  5421     case WM_EMACS_TRACK_CARET:
  5422       /* If there is currently no system caret, create one.  */
  5423       if (w32_system_caret_hwnd == NULL)
  5424         {
  5425           /* Use the default caret width, and avoid changing it
  5426              unnecessarily, as it confuses screen reader software.  */
  5427           w32_system_caret_hwnd = hwnd;
  5428           CreateCaret (hwnd, NULL, 0,
  5429                        w32_system_caret_height);
  5430         }
  5431 
  5432       if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
  5433         return 0;
  5434       /* Ensure visible caret gets turned on when requested.  */
  5435       else if (w32_use_visible_system_caret
  5436                && w32_visible_system_caret_hwnd != hwnd)
  5437         {
  5438           w32_visible_system_caret_hwnd = hwnd;
  5439           return ShowCaret (hwnd);
  5440         }
  5441       /* Ensure visible caret gets turned off when requested.  */
  5442       else if (!w32_use_visible_system_caret
  5443                && w32_visible_system_caret_hwnd)
  5444         {
  5445           w32_visible_system_caret_hwnd = NULL;
  5446           return HideCaret (hwnd);
  5447         }
  5448       else
  5449         return 1;
  5450 
  5451     case WM_EMACS_TRACKPOPUPMENU:
  5452       {
  5453         UINT flags;
  5454         POINT *pos;
  5455         int retval;
  5456         pos = (POINT *)lParam;
  5457         flags = TPM_CENTERALIGN;
  5458         if (button_state & LMOUSE)
  5459           flags |= TPM_LEFTBUTTON;
  5460         else if (button_state & RMOUSE)
  5461           flags |= TPM_RIGHTBUTTON;
  5462 
  5463         /* We may have done a SetCapture on the initial mouse down
  5464            event, so for safety, make sure the capture is canceled
  5465            now.  */
  5466         ReleaseCapture ();
  5467         button_state = 0;
  5468 
  5469         /* Use menubar_active to indicate that WM_INITMENU is from
  5470            TrackPopupMenu below, and should be ignored.  */
  5471         f = w32_window_to_frame (dpyinfo, hwnd);
  5472         if (f)
  5473           f->output_data.w32->menubar_active = 1;
  5474 
  5475         if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
  5476                             0, hwnd, NULL))
  5477           {
  5478             MSG amsg;
  5479             /* Eat any mouse messages during popupmenu */
  5480             while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
  5481                                 PM_REMOVE));
  5482             /* Get the menu selection, if any */
  5483             if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
  5484               {
  5485                 retval =  LOWORD (amsg.wParam);
  5486               }
  5487             else
  5488               {
  5489                 retval = 0;
  5490               }
  5491           }
  5492         else
  5493           {
  5494             retval = -1;
  5495           }
  5496 
  5497         return retval;
  5498       }
  5499     case WM_EMACS_FILENOTIFY:
  5500       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5501       return 1;
  5502 
  5503     default:
  5504       /* Check for messages registered at runtime. */
  5505       if (msg == msh_mousewheel)
  5506         {
  5507           wmsg.dwModifiers = w32_get_modifiers ();
  5508           my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
  5509           signal_user_input ();
  5510           return 0;
  5511         }
  5512 
  5513     dflt:
  5514       return (w32_unicode_gui ? DefWindowProcW :  DefWindowProcA) (hwnd, msg, wParam, lParam);
  5515     }
  5516 
  5517   /* The most common default return code for handled messages is 0.  */
  5518   return 0;
  5519 }
  5520 
  5521 /* This function is called from the main (a.k.a. "Lisp") thread, and
  5522    prepares the coordinates to be used by w32_createwindow (which runs
  5523    in the input thread), when necessary.  The calls to
  5524    gui_display_get_arg must be done here, because they can cons Lisp
  5525    objects, and that can only be done in the Lisp thread.  */
  5526 static void
  5527 my_create_window (struct frame * f)
  5528 {
  5529   MSG msg;
  5530   static int coords[2];
  5531   Lisp_Object left, top;
  5532   struct w32_display_info *dpyinfo = &one_w32_display_info;
  5533 
  5534   /* If f->size_hint_flags is set, it means gui_figure_window_size
  5535      already processed the 'top' and 'left' frame parameters and set
  5536      f->top_pos and f->left_pos accordingly.  w32_createwindow will
  5537      then use those value disregarding coords[].  So we don't need to
  5538      compute coords[] in that case.  */
  5539   if (!(f->size_hint_flags & USPosition || f->size_hint_flags & PPosition))
  5540     {
  5541       /* When called with RES_TYPE_NUMBER, and there's no 'top' or
  5542          'left' parameters in the frame's parameter alist,
  5543          gui_display_get_arg will return zero for anything that is
  5544          neither a number nor Qunbound.  If frame parameter alist does
  5545          have 'left' or 'top', they are interpreted by
  5546          gui_figure_window_size, which was already called, and which
  5547          sets f->size_hint_flags.  */
  5548       left = gui_display_get_arg (dpyinfo, Qnil, Qleft, "left", "Left",
  5549                                   RES_TYPE_NUMBER);
  5550       top = gui_display_get_arg (dpyinfo, Qnil, Qtop, "top", "Top",
  5551                                  RES_TYPE_NUMBER);
  5552       if (BASE_EQ (left, Qunbound))
  5553         coords[0] = CW_USEDEFAULT;
  5554       else
  5555         coords[0] = XFIXNUM (left);
  5556       if (BASE_EQ (top, Qunbound))
  5557         coords[1] = CW_USEDEFAULT;
  5558       else
  5559         coords[1] = XFIXNUM (top);
  5560     }
  5561 
  5562   if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW,
  5563                           (WPARAM)f, (LPARAM)coords))
  5564     emacs_abort ();
  5565   GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
  5566 }
  5567 
  5568 
  5569 /* Create a tooltip window. Unlike my_create_window, we do not do this
  5570    indirectly via the Window thread, as we do not need to process Window
  5571    messages for the tooltip.  Creating tooltips indirectly also creates
  5572    deadlocks when tooltips are created for menu items.  */
  5573 static void
  5574 my_create_tip_window (struct frame *f)
  5575 {
  5576   RECT rect;
  5577 
  5578   rect.left = rect.top = 0;
  5579   rect.right = FRAME_PIXEL_WIDTH (f);
  5580   rect.bottom = FRAME_PIXEL_HEIGHT (f);
  5581 
  5582   AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false);
  5583 
  5584   tip_window = FRAME_W32_WINDOW (f)
  5585     = CreateWindow (EMACS_CLASS,
  5586                     f->namebuf,
  5587                     f->output_data.w32->dwStyle,
  5588                     f->left_pos,
  5589                     f->top_pos,
  5590                     rect.right - rect.left,
  5591                     rect.bottom - rect.top,
  5592                     FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
  5593                     NULL,
  5594                     hinst,
  5595                     NULL);
  5596 
  5597   if (tip_window)
  5598     {
  5599       SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
  5600       SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
  5601       SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
  5602       SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
  5603 
  5604       /* Tip frames have no scrollbars.  */
  5605       SetWindowLong (tip_window, WND_VSCROLLBAR_INDEX, 0);
  5606       SetWindowLong (tip_window, WND_HSCROLLBAR_INDEX, 0);
  5607 
  5608       /* Do this to discard the default setting specified by our parent. */
  5609       ShowWindow (tip_window, SW_HIDE);
  5610     }
  5611 }
  5612 
  5613 
  5614 /* Create and set up the w32 window for frame F.  */
  5615 
  5616 static void
  5617 w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
  5618 {
  5619   block_input ();
  5620 
  5621   /* Use the resource name as the top-level window name
  5622      for looking up resources.  Make a non-Lisp copy
  5623      for the window manager, so GC relocation won't bother it.
  5624 
  5625      Elsewhere we specify the window name for the window manager.  */
  5626   f->namebuf = xlispstrdup (Vx_resource_name);
  5627 
  5628   my_create_window (f);
  5629 
  5630   validate_x_resource_name ();
  5631 
  5632   /* w32_set_name normally ignores requests to set the name if the
  5633      requested name is the same as the current name.  This is the one
  5634      place where that assumption isn't correct; f->name is set, but
  5635      the server hasn't been told.  */
  5636   {
  5637     Lisp_Object name;
  5638     int explicit = f->explicit_name;
  5639 
  5640     f->explicit_name = 0;
  5641     name = f->name;
  5642     fset_name (f, Qnil);
  5643     w32_set_name (f, name, explicit);
  5644   }
  5645 
  5646   unblock_input ();
  5647 
  5648   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)
  5649       && !FRAME_PARENT_FRAME (f))
  5650     initialize_frame_menubar (f);
  5651 
  5652   if (FRAME_W32_WINDOW (f) == 0)
  5653     error ("Unable to create window");
  5654 }
  5655 
  5656 /* Handle the icon stuff for this window.  Perhaps later we might
  5657    want an x_set_icon_position which can be called interactively as
  5658    well.  */
  5659 
  5660 static void
  5661 w32_icon (struct frame *f, Lisp_Object parms)
  5662 {
  5663   Lisp_Object icon_x, icon_y;
  5664   struct w32_display_info *dpyinfo = &one_w32_display_info;
  5665 
  5666   /* Set the position of the icon.  Note that Windows 95 groups all
  5667      icons in the tray.  */
  5668   icon_x = gui_display_get_arg (dpyinfo, parms, Qicon_left, 0, 0,
  5669                                 RES_TYPE_NUMBER);
  5670   icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0,
  5671                                 RES_TYPE_NUMBER);
  5672   if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound))
  5673     {
  5674       CHECK_FIXNUM (icon_x);
  5675       CHECK_FIXNUM (icon_y);
  5676     }
  5677   else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound))
  5678     error ("Both left and top icon corners of icon must be specified");
  5679 
  5680   block_input ();
  5681 
  5682   /* TODO: Start up iconic or window? */
  5683 
  5684   unblock_input ();
  5685 }
  5686 
  5687 
  5688 static void
  5689 w32_make_gc (struct frame *f)
  5690 {
  5691   Emacs_GC gc_values;
  5692 
  5693   block_input ();
  5694 
  5695   /* Create the GC's of this frame.
  5696      Note that many default values are used.  */
  5697 
  5698   /* Cursor has cursor-color background, background-color foreground.  */
  5699   gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
  5700   gc_values.background = f->output_data.w32->cursor_pixel;
  5701   f->output_data.w32->cursor_gc
  5702     = XCreateGC (NULL, FRAME_W32_WINDOW (f),
  5703                  (GCForeground | GCBackground),
  5704                  &gc_values);
  5705 
  5706   /* Reliefs.  */
  5707   f->output_data.w32->white_relief.gc = 0;
  5708   f->output_data.w32->black_relief.gc = 0;
  5709 
  5710   unblock_input ();
  5711 }
  5712 
  5713 
  5714 /* Handler for signals raised during Fx_create_frame and
  5715    w32_create_tip_frame.  FRAME is the frame which is partially
  5716    constructed.  */
  5717 
  5718 static Lisp_Object
  5719 unwind_create_frame (Lisp_Object frame)
  5720 {
  5721   struct frame *f = XFRAME (frame);
  5722 
  5723   /* If frame is ``official'', nothing to do.  */
  5724   if (NILP (Fmemq (frame, Vframe_list)))
  5725     {
  5726 #ifdef GLYPH_DEBUG
  5727       struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  5728 
  5729       /* If the frame's image cache refcount is still the same as our
  5730          private shadow variable, it means we are unwinding a frame
  5731          for which we didn't yet call init_frame_faces, where the
  5732          refcount is incremented.  Therefore, we increment it here, so
  5733          that free_frame_faces, called in w32_free_frame_resources
  5734          below, will not mistakenly decrement the counter that was not
  5735          incremented yet to account for this new frame.  */
  5736       if (FRAME_IMAGE_CACHE (f) != NULL
  5737           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
  5738         FRAME_IMAGE_CACHE (f)->refcount++;
  5739 #endif
  5740 
  5741       w32_free_frame_resources (f);
  5742       free_glyphs (f);
  5743 
  5744 #ifdef GLYPH_DEBUG
  5745       /* Check that reference counts are indeed correct.  */
  5746       eassert (dpyinfo->reference_count == dpyinfo_refcount);
  5747       eassert ((dpyinfo->terminal->image_cache == NULL
  5748                 && image_cache_refcount == 0)
  5749                || (dpyinfo->terminal->image_cache != NULL
  5750                    && dpyinfo->terminal->image_cache->refcount == image_cache_refcount));
  5751 #endif
  5752       return Qt;
  5753     }
  5754 
  5755   return Qnil;
  5756 }
  5757 
  5758 static void
  5759 do_unwind_create_frame (Lisp_Object frame)
  5760 {
  5761   unwind_create_frame (frame);
  5762 }
  5763 
  5764 void
  5765 w32_default_font_parameter (struct frame *f, Lisp_Object parms)
  5766 {
  5767   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  5768   Lisp_Object font_param = gui_display_get_arg (dpyinfo,
  5769                                                 parms, Qfont, NULL, NULL,
  5770                                                 RES_TYPE_STRING);
  5771   Lisp_Object font;
  5772   if (BASE_EQ (font_param, Qunbound))
  5773     font_param = Qnil;
  5774   font = !NILP (font_param) ? font_param
  5775     : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
  5776                            RES_TYPE_STRING);
  5777 
  5778   if (!STRINGP (font))
  5779     {
  5780       int i;
  5781       static const char *names[]
  5782         = { "Courier New-10",
  5783             "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
  5784             "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
  5785             "Fixedsys",
  5786             NULL };
  5787 
  5788       for (i = 0; names[i]; i++)
  5789         {
  5790           font = font_open_by_name (f, build_unibyte_string (names[i]));
  5791           if (! NILP (font))
  5792             break;
  5793         }
  5794       if (NILP (font))
  5795         error ("No suitable font was found");
  5796     }
  5797 
  5798   gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
  5799 }
  5800 
  5801 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
  5802        1, 1, 0,
  5803        doc: /* SKIP: real doc in xfns.c.  */)
  5804   (Lisp_Object parameters)
  5805 {
  5806   struct frame *f;
  5807   Lisp_Object frame, tem;
  5808   Lisp_Object name;
  5809   bool minibuffer_only = false;
  5810   long window_prompting = 0;
  5811   specpdl_ref count = SPECPDL_INDEX ();
  5812   Lisp_Object display;
  5813   struct w32_display_info *dpyinfo = NULL;
  5814   Lisp_Object parent, parent_frame;
  5815   struct kboard *kb;
  5816 
  5817   if (!FRAME_W32_P (SELECTED_FRAME ())
  5818       && !FRAME_INITIAL_P (SELECTED_FRAME ()))
  5819     error ("Cannot create a GUI frame in a -nw session");
  5820 
  5821   /* Make copy of frame parameters because the original is in pure
  5822      storage now. */
  5823   parameters = Fcopy_alist (parameters);
  5824 
  5825   /* Use this general default value to start with
  5826      until we know if this frame has a specified name.  */
  5827   Vx_resource_name = Vinvocation_name;
  5828 
  5829   display = gui_display_get_arg (dpyinfo, parameters, Qterminal, 0, 0,
  5830                                  RES_TYPE_NUMBER);
  5831   if (BASE_EQ (display, Qunbound))
  5832     display = gui_display_get_arg (dpyinfo, parameters, Qdisplay, 0, 0,
  5833                                    RES_TYPE_STRING);
  5834   if (BASE_EQ (display, Qunbound))
  5835     display = Qnil;
  5836   dpyinfo = check_x_display_info (display);
  5837   kb = dpyinfo->terminal->kboard;
  5838 
  5839   if (!dpyinfo->terminal->name)
  5840     error ("Terminal is not live, can't create new frames on it");
  5841 
  5842   name = gui_display_get_arg (dpyinfo, parameters, Qname, "name", "Name",
  5843                               RES_TYPE_STRING);
  5844   if (!STRINGP (name)
  5845       && ! BASE_EQ (name, Qunbound)
  5846       && ! NILP (name))
  5847     error ("Invalid frame name--not a string or nil");
  5848 
  5849   if (STRINGP (name))
  5850     Vx_resource_name = name;
  5851 
  5852   /* See if parent window is specified.  */
  5853   parent = gui_display_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
  5854                                 RES_TYPE_NUMBER);
  5855   if (BASE_EQ (parent, Qunbound))
  5856     parent = Qnil;
  5857   else if (!NILP (parent))
  5858     CHECK_FIXNUM (parent);
  5859 
  5860   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
  5861   /* No need to protect DISPLAY because that's not used after passing
  5862      it to make_frame_without_minibuffer.  */
  5863   frame = Qnil;
  5864   tem = gui_display_get_arg (dpyinfo, parameters, Qminibuffer,
  5865                              "minibuffer", "Minibuffer",
  5866                              RES_TYPE_SYMBOL);
  5867   if (EQ (tem, Qnone) || NILP (tem))
  5868     f = make_frame_without_minibuffer (Qnil, kb, display);
  5869   else if (EQ (tem, Qonly))
  5870     {
  5871       f = make_minibuffer_frame ();
  5872       minibuffer_only = true;
  5873     }
  5874   else if (WINDOWP (tem))
  5875     f = make_frame_without_minibuffer (tem, kb, display);
  5876   else
  5877     f = make_frame (true);
  5878 
  5879   XSETFRAME (frame, f);
  5880 
  5881   parent_frame = gui_display_get_arg (dpyinfo, parameters, Qparent_frame,
  5882                                       NULL, NULL,
  5883                                       RES_TYPE_SYMBOL);
  5884   /* Apply `parent-frame' parameter only when no `parent-id' was
  5885      specified.  */
  5886   if (!NILP (parent_frame)
  5887       && (!NILP (parent)
  5888           || !FRAMEP (parent_frame)
  5889           || !FRAME_LIVE_P (XFRAME (parent_frame))
  5890           || !FRAME_W32_P (XFRAME (parent_frame))))
  5891     parent_frame = Qnil;
  5892 
  5893   fset_parent_frame (f, parent_frame);
  5894   store_frame_param (f, Qparent_frame, parent_frame);
  5895 
  5896   tem = gui_display_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
  5897                              RES_TYPE_BOOLEAN);
  5898   FRAME_UNDECORATED (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound);
  5899   store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
  5900 
  5901   tem = gui_display_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
  5902                              RES_TYPE_BOOLEAN);
  5903   FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound);
  5904   store_frame_param (f, Qskip_taskbar,
  5905                      (NILP (tem) || BASE_EQ (tem, Qunbound)) ? Qnil : Qt);
  5906 
  5907   /* By default, make scrollbars the system standard width and height. */
  5908   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
  5909   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
  5910 
  5911   f->terminal = dpyinfo->terminal;
  5912 
  5913   f->output_method = output_w32;
  5914   f->output_data.w32 = xzalloc (sizeof (struct w32_output));
  5915   FRAME_FONTSET (f) = -1;
  5916 
  5917   /* Need to finish setting up of user-defined fringe bitmaps that
  5918      were defined before the first GUI frame was created (e.g., while
  5919      in daemon mode).  */
  5920   if (!f->terminal->reference_count)
  5921     gui_init_fringe (f->terminal->rif);
  5922 
  5923   fset_icon_name (f, gui_display_get_arg (dpyinfo,
  5924                                           parameters,
  5925                                           Qicon_name,
  5926                                           "iconName",
  5927                                           "Title",
  5928                                           RES_TYPE_STRING));
  5929   if (! STRINGP (f->icon_name))
  5930     fset_icon_name (f, Qnil);
  5931 
  5932   /*  FRAME_DISPLAY_INFO (f) = dpyinfo; */
  5933 
  5934   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
  5935   record_unwind_protect (do_unwind_create_frame, frame);
  5936 
  5937 #ifdef GLYPH_DEBUG
  5938   image_cache_refcount =
  5939     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
  5940   dpyinfo_refcount = dpyinfo->reference_count;
  5941 #endif /* GLYPH_DEBUG */
  5942 
  5943   /* Specify the parent under which to make this window - this seems to
  5944      have no effect on Windows because parent_desc is explicitly reset
  5945      below.  */
  5946   if (!NILP (parent))
  5947     {
  5948       /* Cast to UINT_PTR shuts up compiler warnings about cast to
  5949          pointer from integer of different size.  */
  5950       f->output_data.w32->parent_desc = (Window) (UINT_PTR) XFIXNAT (parent);
  5951       f->output_data.w32->explicit_parent = true;
  5952     }
  5953   else
  5954     {
  5955       f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
  5956       f->output_data.w32->explicit_parent = false;
  5957     }
  5958 
  5959   /* Set the name; the functions to which we pass f expect the name to
  5960      be set.  */
  5961   if (BASE_EQ (name, Qunbound) || NILP (name))
  5962     {
  5963       fset_name (f, build_string (dpyinfo->w32_id_name));
  5964       f->explicit_name = false;
  5965     }
  5966   else
  5967     {
  5968       fset_name (f, name);
  5969       f->explicit_name = true;
  5970       /* Use the frame's title when getting resources for this frame.  */
  5971       specbind (Qx_resource_name, name);
  5972     }
  5973 
  5974 #ifdef HAVE_HARFBUZZ
  5975   if (harfbuzz_available)
  5976     register_font_driver (&harfbuzz_font_driver, f);
  5977 #endif
  5978   register_font_driver (&uniscribe_font_driver, f);
  5979   register_font_driver (&w32font_driver, f);
  5980 
  5981   gui_default_parameter (f, parameters, Qfont_backend, Qnil,
  5982                          "fontBackend", "FontBackend", RES_TYPE_STRING);
  5983 
  5984   /* Extract the window parameters from the supplied values
  5985      that are needed to determine window geometry.  */
  5986   w32_default_font_parameter (f, parameters);
  5987 
  5988   /* Default BorderWidth to 0 to match other platforms.  */
  5989   gui_default_parameter (f, parameters, Qborder_width, make_fixnum (0),
  5990                          "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
  5991 
  5992   /* We recognize either internalBorderWidth or internalBorder
  5993      (which is what xterm calls it).  */
  5994   if (NILP (Fassq (Qinternal_border_width, parameters)))
  5995     {
  5996       Lisp_Object value;
  5997 
  5998       value = gui_display_get_arg (dpyinfo, parameters, Qinternal_border_width,
  5999                                    "internalBorder", "internalBorder",
  6000                                    RES_TYPE_NUMBER);
  6001       if (! BASE_EQ (value, Qunbound))
  6002         parameters = Fcons (Fcons (Qinternal_border_width, value),
  6003                             parameters);
  6004     }
  6005 
  6006   gui_default_parameter (f, parameters, Qinternal_border_width, make_fixnum (0),
  6007                          "internalBorderWidth", "internalBorderWidth",
  6008                          RES_TYPE_NUMBER);
  6009 
  6010   /* Same for child frames.  */
  6011   if (NILP (Fassq (Qchild_frame_border_width, parameters)))
  6012     {
  6013       Lisp_Object value;
  6014 
  6015       value = gui_display_get_arg (dpyinfo, parameters, Qchild_frame_border_width,
  6016                                    "childFrameBorder", "childFrameBorder",
  6017                                    RES_TYPE_NUMBER);
  6018       if (!BASE_EQ (value, Qunbound))
  6019         parameters = Fcons (Fcons (Qchild_frame_border_width, value),
  6020                        parameters);
  6021     }
  6022 
  6023   gui_default_parameter (f, parameters, Qchild_frame_border_width, Qnil,
  6024                          "childFrameBorderWidth", "childFrameBorderWidth",
  6025                          RES_TYPE_NUMBER);
  6026   gui_default_parameter (f, parameters, Qright_divider_width, make_fixnum (0),
  6027                          NULL, NULL, RES_TYPE_NUMBER);
  6028   gui_default_parameter (f, parameters, Qbottom_divider_width, make_fixnum (0),
  6029                          NULL, NULL, RES_TYPE_NUMBER);
  6030   gui_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
  6031                          "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
  6032   gui_default_parameter (f, parameters, Qhorizontal_scroll_bars, Qnil,
  6033                          "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
  6034 
  6035   /* Also do the stuff which must be set before the window exists.  */
  6036   gui_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
  6037                          "foreground", "Foreground", RES_TYPE_STRING);
  6038   gui_default_parameter (f, parameters, Qbackground_color, build_string ("white"),
  6039                          "background", "Background", RES_TYPE_STRING);
  6040   gui_default_parameter (f, parameters, Qmouse_color, build_string ("black"),
  6041                          "pointerColor", "Foreground", RES_TYPE_STRING);
  6042   gui_default_parameter (f, parameters, Qborder_color, build_string ("black"),
  6043                          "borderColor", "BorderColor", RES_TYPE_STRING);
  6044   gui_default_parameter (f, parameters, Qscreen_gamma, Qnil,
  6045                          "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
  6046   gui_default_parameter (f, parameters, Qline_spacing, Qnil,
  6047                          "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
  6048   gui_default_parameter (f, parameters, Qleft_fringe, Qnil,
  6049                          "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
  6050   gui_default_parameter (f, parameters, Qright_fringe, Qnil,
  6051                          "rightFringe", "RightFringe", RES_TYPE_NUMBER);
  6052   gui_default_parameter (f, parameters, Qno_focus_on_map, Qnil,
  6053                          NULL, NULL, RES_TYPE_BOOLEAN);
  6054   gui_default_parameter (f, parameters, Qno_accept_focus, Qnil,
  6055                          NULL, NULL, RES_TYPE_BOOLEAN);
  6056   gui_default_parameter (f, parameters, Qno_special_glyphs, Qnil,
  6057                          NULL, NULL, RES_TYPE_BOOLEAN);
  6058   gui_default_parameter (f, parameters, Qalpha_background, Qnil,
  6059                          "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
  6060 
  6061   /* Process alpha here (Bug#16619).  On XP this fails with child
  6062      frames.  For `no-focus-on-map' frames delay processing of alpha
  6063      until the frame becomes visible.  */
  6064   if (!FRAME_NO_FOCUS_ON_MAP (f))
  6065     gui_default_parameter (f, parameters, Qalpha, Qnil,
  6066                          "alpha", "Alpha", RES_TYPE_NUMBER);
  6067 
  6068   /* Init faces first since we need the frame's column width/line
  6069      height in various occasions.  */
  6070   init_frame_faces (f);
  6071 
  6072   /* We have to call adjust_frame_size here since otherwise
  6073      w32_set_tool_bar_lines will already work with the character sizes
  6074      installed by init_frame_faces while the frame's pixel size is still
  6075      calculated from a character size of 1 and we subsequently hit the
  6076      (height >= 0) assertion in window_box_height.
  6077 
  6078      The non-pixelwise code apparently worked around this because it
  6079      had one frame line vs one toolbar line which left us with a zero
  6080      root window height which was obviously wrong as well ...
  6081 
  6082      Also process `min-width' and `min-height' parameters right here
  6083      because `frame-windows-min-size' needs them.  */
  6084   tem = gui_display_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
  6085                              RES_TYPE_NUMBER);
  6086   if (FIXNUMP (tem))
  6087     store_frame_param (f, Qmin_width, tem);
  6088   tem = gui_display_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
  6089                              RES_TYPE_NUMBER);
  6090   if (FIXNUMP (tem))
  6091     store_frame_param (f, Qmin_height, tem);
  6092   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
  6093                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
  6094                      Qx_create_frame_1);
  6095 
  6096   /* The X resources controlling the menu-bar and tool-bar are
  6097      processed specially at startup, and reflected in the mode
  6098      variables; ignore them here.  */
  6099   if (NILP (parent_frame))
  6100     {
  6101       gui_default_parameter (f, parameters, Qmenu_bar_lines,
  6102                              NILP (Vmenu_bar_mode)
  6103                              ? make_fixnum (0) : make_fixnum (1),
  6104                              NULL, NULL, RES_TYPE_NUMBER);
  6105     }
  6106   else
  6107     /* No menu bar for child frames.  */
  6108     store_frame_param (f, Qmenu_bar_lines, make_fixnum (0));
  6109 
  6110   gui_default_parameter (f, parameters, Qtab_bar_lines,
  6111                          NILP (Vtab_bar_mode)
  6112                          ? make_fixnum (0) : make_fixnum (1),
  6113                          NULL, NULL, RES_TYPE_NUMBER);
  6114 
  6115   gui_default_parameter (f, parameters, Qtool_bar_lines,
  6116                          NILP (Vtool_bar_mode)
  6117                          ? make_fixnum (0) : make_fixnum (1),
  6118                          NULL, NULL, RES_TYPE_NUMBER);
  6119 
  6120   gui_default_parameter (f, parameters, Qinhibit_double_buffering, Qnil,
  6121                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
  6122                          RES_TYPE_BOOLEAN);
  6123 
  6124   gui_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
  6125                          "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
  6126   gui_default_parameter (f, parameters, Qtitle, Qnil,
  6127                          "title", "Title", RES_TYPE_STRING);
  6128 
  6129   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
  6130   f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
  6131   f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
  6132   f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
  6133   f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND);
  6134   f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
  6135   f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
  6136   f->output_data.w32->vertical_drag_cursor = w32_load_cursor (IDC_SIZENS);
  6137   f->output_data.w32->left_edge_cursor = w32_load_cursor (IDC_SIZEWE);
  6138   f->output_data.w32->top_left_corner_cursor = w32_load_cursor (IDC_SIZENWSE);
  6139   f->output_data.w32->top_edge_cursor = w32_load_cursor (IDC_SIZENS);
  6140   f->output_data.w32->top_right_corner_cursor = w32_load_cursor (IDC_SIZENESW);
  6141   f->output_data.w32->right_edge_cursor = w32_load_cursor (IDC_SIZEWE);
  6142   f->output_data.w32->bottom_right_corner_cursor = w32_load_cursor (IDC_SIZENWSE);
  6143   f->output_data.w32->bottom_edge_cursor = w32_load_cursor (IDC_SIZENS);
  6144   f->output_data.w32->bottom_left_corner_cursor = w32_load_cursor (IDC_SIZENESW);
  6145 
  6146   f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
  6147 
  6148   window_prompting = gui_figure_window_size (f, parameters, true, true);
  6149 
  6150   tem = gui_display_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0,
  6151                              RES_TYPE_BOOLEAN);
  6152   f->no_split = minibuffer_only || EQ (tem, Qt);
  6153 
  6154   w32_window (f, window_prompting, minibuffer_only);
  6155   w32_icon (f, parameters);
  6156 
  6157   w32_make_gc (f);
  6158 
  6159   /* Now consider the frame official.  */
  6160   f->terminal->reference_count++;
  6161   FRAME_DISPLAY_INFO (f)->reference_count++;
  6162   Vframe_list = Fcons (frame, Vframe_list);
  6163 
  6164   /* We need to do this after creating the window, so that the
  6165      icon-creation functions can say whose icon they're describing.  */
  6166   gui_default_parameter (f, parameters, Qicon_type, Qnil,
  6167                          "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
  6168 
  6169   gui_default_parameter (f, parameters, Qauto_raise, Qnil,
  6170                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  6171   gui_default_parameter (f, parameters, Qauto_lower, Qnil,
  6172                          "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  6173   gui_default_parameter (f, parameters, Qcursor_type, Qbox,
  6174                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
  6175   gui_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
  6176                          "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
  6177   gui_default_parameter (f, parameters, Qscroll_bar_height, Qnil,
  6178                          "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER);
  6179 
  6180   /* Allow set_window_size_hook, now.  */
  6181   f->can_set_window_size = true;
  6182 
  6183   /* Tell the server what size and position, etc, we want, and how
  6184      badly we want them.  This should be done after we have the menu
  6185      bar so that its size can be taken into account.  */
  6186   block_input ();
  6187   w32_wm_set_size_hint (f, window_prompting, false);
  6188   unblock_input ();
  6189 
  6190   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
  6191                      0, true, Qx_create_frame_2);
  6192 
  6193   /* Process fullscreen parameter here in the hope that normalizing a
  6194      fullheight/fullwidth frame will produce the size set by the last
  6195      adjust_frame_size call.  */
  6196   gui_default_parameter (f, parameters, Qfullscreen, Qnil,
  6197                          "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
  6198   gui_default_parameter (f, parameters, Qz_group, Qnil,
  6199                          NULL, NULL, RES_TYPE_SYMBOL);
  6200 
  6201   gui_default_parameter (f, parameters, Qalpha_background, Qnil,
  6202                          "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
  6203 
  6204   /* Make the window appear on the frame and enable display, unless
  6205      the caller says not to.  However, with explicit parent, Emacs
  6206      cannot control visibility, so don't try.  */
  6207   if (!f->output_data.w32->explicit_parent)
  6208     {
  6209       Lisp_Object visibility
  6210         = gui_display_get_arg (dpyinfo, parameters, Qvisibility, 0, 0,
  6211                                RES_TYPE_SYMBOL);
  6212 
  6213       if (EQ (visibility, Qicon))
  6214         w32_iconify_frame (f);
  6215       else
  6216         {
  6217           if (BASE_EQ (visibility, Qunbound))
  6218             visibility = Qt;
  6219 
  6220           if (!NILP (visibility))
  6221             w32_make_frame_visible (f);
  6222           else
  6223             f->was_invisible = true;
  6224         }
  6225 
  6226       store_frame_param (f, Qvisibility, visibility);
  6227     }
  6228 
  6229   /* For `no-focus-on-map' frames set alpha here.  */
  6230   if (FRAME_NO_FOCUS_ON_MAP (f))
  6231     gui_default_parameter (f, parameters, Qalpha, Qnil,
  6232                            "alpha", "Alpha", RES_TYPE_NUMBER);
  6233 
  6234   /* Initialize `default-minibuffer-frame' in case this is the first
  6235      frame on this terminal.  */
  6236   if (FRAME_HAS_MINIBUF_P (f)
  6237       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
  6238           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
  6239     kset_default_minibuffer_frame (kb, frame);
  6240 
  6241   /* All remaining specified parameters, which have not been "used" by
  6242      gui_display_get_arg and friends, now go in the misc. alist of the
  6243      frame.  */
  6244   for (tem = parameters; CONSP (tem); tem = XCDR (tem))
  6245     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
  6246       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
  6247 
  6248   /* Make sure windows on this frame appear in calls to next-window
  6249      and similar functions.  */
  6250   Vwindow_list = Qnil;
  6251 
  6252   return unbind_to (count, frame);
  6253 }
  6254 
  6255 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
  6256        doc: /* SKIP: real doc in xfns.c.  */)
  6257   (Lisp_Object color, Lisp_Object frame)
  6258 {
  6259   Emacs_Color foo;
  6260   struct frame *f = decode_window_system_frame (frame);
  6261 
  6262   CHECK_STRING (color);
  6263 
  6264   if (w32_defined_color (f, SSDATA (color), &foo, false, false))
  6265     return Qt;
  6266   else
  6267     return Qnil;
  6268 }
  6269 
  6270 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
  6271        doc: /* SKIP: real doc in xfns.c.  */)
  6272   (Lisp_Object color, Lisp_Object frame)
  6273 {
  6274   Emacs_Color foo;
  6275   struct frame *f = decode_window_system_frame (frame);
  6276 
  6277   CHECK_STRING (color);
  6278 
  6279   if (w32_defined_color (f, SSDATA (color), &foo, false, false))
  6280     return list3i ((GetRValue (foo.pixel) << 8) | GetRValue (foo.pixel),
  6281                    (GetGValue (foo.pixel) << 8) | GetGValue (foo.pixel),
  6282                    (GetBValue (foo.pixel) << 8) | GetBValue (foo.pixel));
  6283   else
  6284     return Qnil;
  6285 }
  6286 
  6287 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
  6288        doc: /* SKIP: real doc in xfns.c.  */)
  6289   (Lisp_Object display)
  6290 {
  6291   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6292 
  6293   if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
  6294     return Qnil;
  6295 
  6296   return Qt;
  6297 }
  6298 
  6299 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
  6300        Sx_display_grayscale_p, 0, 1, 0,
  6301        doc: /* SKIP: real doc in xfns.c.  */)
  6302   (Lisp_Object display)
  6303 {
  6304   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6305 
  6306   if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
  6307     return Qnil;
  6308 
  6309   return Qt;
  6310 }
  6311 
  6312 DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
  6313        Sx_display_pixel_width, 0, 1, 0,
  6314        doc: /* SKIP: real doc in xfns.c.  */)
  6315   (Lisp_Object display)
  6316 {
  6317   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6318 
  6319   return make_fixnum (w32_display_pixel_width (dpyinfo));
  6320 }
  6321 
  6322 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
  6323        Sx_display_pixel_height, 0, 1, 0,
  6324        doc: /* SKIP: real doc in xfns.c.  */)
  6325   (Lisp_Object display)
  6326 {
  6327   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6328 
  6329   return make_fixnum (w32_display_pixel_height (dpyinfo));
  6330 }
  6331 
  6332 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
  6333        0, 1, 0,
  6334        doc: /* SKIP: real doc in xfns.c.  */)
  6335   (Lisp_Object display)
  6336 {
  6337   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6338 
  6339   return make_fixnum (dpyinfo->n_planes * dpyinfo->n_cbits);
  6340 }
  6341 
  6342 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
  6343        0, 1, 0,
  6344        doc: /* SKIP: real doc in xfns.c.  */)
  6345   (Lisp_Object display)
  6346 {
  6347   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6348   int cap;
  6349 
  6350   /* Don't use NCOLORS: it returns incorrect results under remote
  6351    * desktop.  We force 24+ bit depths to 24-bit, both to prevent an
  6352    * overflow and because probably is more meaningful on Windows
  6353    * anyway.  */
  6354 
  6355   cap = 1 << min (dpyinfo->n_planes * dpyinfo->n_cbits, 24);
  6356   return make_fixnum (cap);
  6357 }
  6358 
  6359 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
  6360        Sx_server_max_request_size,
  6361        0, 1, 0,
  6362        doc: /* SKIP: real doc in xfns.c.  */)
  6363   (Lisp_Object display)
  6364 {
  6365   return make_fixnum (1);
  6366 }
  6367 
  6368 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
  6369        doc: /* SKIP: real doc in xfns.c.  */)
  6370   (Lisp_Object terminal)
  6371 {
  6372   return build_string ("Microsoft Corp.");
  6373 }
  6374 
  6375 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
  6376        doc: /* SKIP: real doc in xfns.c.  */)
  6377   (Lisp_Object terminal)
  6378 {
  6379   return list3i (w32_major_version, w32_minor_version, w32_build_number);
  6380 }
  6381 
  6382 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
  6383        doc: /* SKIP: real doc in xfns.c.  */)
  6384   (Lisp_Object display)
  6385 {
  6386   return make_fixnum (1);
  6387 }
  6388 
  6389 DEFUN ("x-display-mm-height", Fx_display_mm_height,
  6390        Sx_display_mm_height, 0, 1, 0,
  6391        doc: /* SKIP: real doc in xfns.c.  */)
  6392   (Lisp_Object display)
  6393 {
  6394   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6395   HDC hdc;
  6396   double mm_per_pixel;
  6397 
  6398   hdc = GetDC (NULL);
  6399   mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
  6400                   / GetDeviceCaps (hdc, VERTRES));
  6401   ReleaseDC (NULL, hdc);
  6402 
  6403   return make_fixnum (w32_display_pixel_height (dpyinfo) * mm_per_pixel + 0.5);
  6404 }
  6405 
  6406 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
  6407        doc: /* SKIP: real doc in xfns.c.  */)
  6408   (Lisp_Object display)
  6409 {
  6410   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6411   HDC hdc;
  6412   double mm_per_pixel;
  6413 
  6414   hdc = GetDC (NULL);
  6415   mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
  6416                   / GetDeviceCaps (hdc, HORZRES));
  6417   ReleaseDC (NULL, hdc);
  6418 
  6419   return make_fixnum (w32_display_pixel_width (dpyinfo) * mm_per_pixel + 0.5);
  6420 }
  6421 
  6422 DEFUN ("x-display-backing-store", Fx_display_backing_store,
  6423        Sx_display_backing_store, 0, 1, 0,
  6424        doc: /* SKIP: real doc in xfns.c.  */)
  6425   (Lisp_Object display)
  6426 {
  6427   return intern ("not-useful");
  6428 }
  6429 
  6430 DEFUN ("x-display-visual-class", Fx_display_visual_class,
  6431        Sx_display_visual_class, 0, 1, 0,
  6432        doc: /* SKIP: real doc in xfns.c.  */)
  6433   (Lisp_Object display)
  6434 {
  6435   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6436   Lisp_Object result = Qnil;
  6437 
  6438   if (dpyinfo->has_palette)
  6439       result = intern ("pseudo-color");
  6440   else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
  6441       result = intern ("static-gray");
  6442   else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
  6443       result = intern ("static-color");
  6444   else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
  6445       result = intern ("true-color");
  6446 
  6447   return result;
  6448 }
  6449 
  6450 DEFUN ("x-display-save-under", Fx_display_save_under,
  6451        Sx_display_save_under, 0, 1, 0,
  6452        doc: /* SKIP: real doc in xfns.c.  */)
  6453   (Lisp_Object display)
  6454 {
  6455   return Qnil;
  6456 }
  6457 
  6458 static BOOL CALLBACK ALIGN_STACK
  6459 w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData)
  6460 {
  6461   Lisp_Object *monitor_list = (Lisp_Object *) dwData;
  6462 
  6463   *monitor_list = Fcons (make_mint_ptr (monitor), *monitor_list);
  6464 
  6465   return TRUE;
  6466 }
  6467 
  6468 static Lisp_Object
  6469 w32_display_monitor_attributes_list (void)
  6470 {
  6471   Lisp_Object attributes_list = Qnil, primary_monitor_attributes = Qnil;
  6472   Lisp_Object monitor_list = Qnil, monitor_frames, rest, frame;
  6473   int i, n_monitors;
  6474   HMONITOR *monitors;
  6475 
  6476   if (!(enum_display_monitors_fn && get_monitor_info_fn
  6477         && monitor_from_window_fn))
  6478     return Qnil;
  6479 
  6480   if (!enum_display_monitors_fn (NULL, NULL, w32_monitor_enum,
  6481                                  (LPARAM) &monitor_list)
  6482       || NILP (monitor_list))
  6483     return Qnil;
  6484 
  6485   n_monitors = 0;
  6486   for (rest = monitor_list; CONSP (rest); rest = XCDR (rest))
  6487     n_monitors++;
  6488 
  6489   monitors = xmalloc (n_monitors * sizeof (*monitors));
  6490   for (i = 0; i < n_monitors; i++)
  6491     {
  6492       monitors[i] = xmint_pointer (XCAR (monitor_list));
  6493       monitor_list = XCDR (monitor_list);
  6494     }
  6495 
  6496   monitor_frames = Fmake_vector (make_fixnum (n_monitors), Qnil);
  6497   FOR_EACH_FRAME (rest, frame)
  6498     {
  6499       struct frame *f = XFRAME (frame);
  6500 
  6501       if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f))
  6502         {
  6503           HMONITOR monitor =
  6504             monitor_from_window_fn (FRAME_W32_WINDOW (f),
  6505                                     MONITOR_DEFAULT_TO_NEAREST);
  6506 
  6507           for (i = 0; i < n_monitors; i++)
  6508             if (monitors[i] == monitor)
  6509               break;
  6510 
  6511           if (i < n_monitors)
  6512             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
  6513         }
  6514     }
  6515 
  6516   for (i = 0; i < n_monitors; i++)
  6517     {
  6518       Lisp_Object geometry, workarea, name, attributes = Qnil;
  6519       HDC hdc;
  6520       int width_mm, height_mm;
  6521       struct MONITOR_INFO_EX mi;
  6522 
  6523       mi.cbSize = sizeof (mi);
  6524       if (!get_monitor_info_fn (monitors[i], (struct MONITOR_INFO *) &mi))
  6525         continue;
  6526 
  6527       hdc = CreateDCA ("DISPLAY", mi.szDevice, NULL, NULL);
  6528       if (hdc == NULL)
  6529         continue;
  6530       width_mm = GetDeviceCaps (hdc, HORZSIZE);
  6531       height_mm = GetDeviceCaps (hdc, VERTSIZE);
  6532       DeleteDC (hdc);
  6533 
  6534       attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
  6535                           attributes);
  6536 
  6537       name = DECODE_SYSTEM (build_unibyte_string (mi.szDevice));
  6538 
  6539       attributes = Fcons (Fcons (Qname, name), attributes);
  6540 
  6541       attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
  6542                           attributes);
  6543 
  6544       workarea = list4i (mi.rcWork.left, mi.rcWork.top,
  6545                          mi.rcWork.right - mi.rcWork.left,
  6546                          mi.rcWork.bottom - mi.rcWork.top);
  6547       attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
  6548 
  6549       geometry = list4i (mi.rcMonitor.left, mi.rcMonitor.top,
  6550                          mi.rcMonitor.right - mi.rcMonitor.left,
  6551                          mi.rcMonitor.bottom - mi.rcMonitor.top);
  6552       attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
  6553 
  6554       if (mi.dwFlags & MONITORINFOF_PRIMARY)
  6555         primary_monitor_attributes = attributes;
  6556       else
  6557         attributes_list = Fcons (attributes, attributes_list);
  6558     }
  6559 
  6560   if (!NILP (primary_monitor_attributes))
  6561     attributes_list = Fcons (primary_monitor_attributes, attributes_list);
  6562 
  6563   xfree (monitors);
  6564 
  6565   return attributes_list;
  6566 }
  6567 
  6568 static Lisp_Object
  6569 w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo)
  6570 {
  6571   Lisp_Object geometry, workarea, frames, rest, frame, attributes = Qnil;
  6572   HDC hdc;
  6573   double mm_per_pixel;
  6574   int pixel_width, pixel_height, width_mm, height_mm;
  6575   RECT workarea_rect;
  6576 
  6577   /* Fallback: treat (possibly) multiple physical monitors as if they
  6578      formed a single monitor as a whole.  This should provide a
  6579      consistent result at least on single monitor environments.  */
  6580   attributes = Fcons (Fcons (Qname, build_string ("combined screen")),
  6581                       attributes);
  6582 
  6583   frames = Qnil;
  6584   FOR_EACH_FRAME (rest, frame)
  6585     {
  6586       struct frame *f = XFRAME (frame);
  6587 
  6588       if (FRAME_W32_P (f) && !FRAME_TOOLTIP_P (f))
  6589         frames = Fcons (frame, frames);
  6590     }
  6591   attributes = Fcons (Fcons (Qframes, frames), attributes);
  6592 
  6593   pixel_width = w32_display_pixel_width (dpyinfo);
  6594   pixel_height = w32_display_pixel_height (dpyinfo);
  6595 
  6596   hdc = GetDC (NULL);
  6597   mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
  6598                   / GetDeviceCaps (hdc, HORZRES));
  6599   width_mm = pixel_width * mm_per_pixel + 0.5;
  6600   mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
  6601                   / GetDeviceCaps (hdc, VERTRES));
  6602   height_mm = pixel_height * mm_per_pixel + 0.5;
  6603   ReleaseDC (NULL, hdc);
  6604   attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
  6605                       attributes);
  6606 
  6607   /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but
  6608      we don't care.  */
  6609   geometry = list4i (GetSystemMetrics (SM_XVIRTUALSCREEN),
  6610                      GetSystemMetrics (SM_YVIRTUALSCREEN),
  6611                      pixel_width, pixel_height);
  6612   if (SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0))
  6613     workarea = list4i (workarea_rect.left, workarea_rect.top,
  6614                        workarea_rect.right - workarea_rect.left,
  6615                        workarea_rect.bottom - workarea_rect.top);
  6616   else
  6617     workarea = geometry;
  6618   attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
  6619 
  6620   attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
  6621 
  6622   return list1 (attributes);
  6623 }
  6624 
  6625 DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list,
  6626        Sw32_display_monitor_attributes_list,
  6627        0, 1, 0,
  6628        doc: /* Return a list of physical monitor attributes on the W32 display DISPLAY.
  6629 
  6630 The optional argument DISPLAY specifies which display to ask about.
  6631 DISPLAY should be either a frame or a display name (a string).
  6632 If omitted or nil, that stands for the selected frame's display.
  6633 
  6634 Internal use only, use `display-monitor-attributes-list' instead.  */)
  6635   (Lisp_Object display)
  6636 {
  6637   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6638   Lisp_Object attributes_list;
  6639 
  6640   block_input ();
  6641   attributes_list = w32_display_monitor_attributes_list ();
  6642   if (NILP (attributes_list))
  6643     attributes_list = w32_display_monitor_attributes_list_fallback (dpyinfo);
  6644   unblock_input ();
  6645 
  6646   return attributes_list;
  6647 }
  6648 
  6649 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
  6650        doc: /* Set the sound generated when the bell is rung.
  6651 SOUND is `asterisk', `exclamation', `hand', `question', `ok', or `silent'
  6652 to use the corresponding system sound for the bell.  The `silent' sound
  6653 prevents Emacs from making any sound at all.
  6654 SOUND is nil to use the normal beep.  */)
  6655   (Lisp_Object sound)
  6656 {
  6657   CHECK_SYMBOL (sound);
  6658 
  6659   if (NILP (sound))
  6660       sound_type = 0xFFFFFFFF;
  6661   else if (EQ (sound, intern ("asterisk")))
  6662       sound_type = MB_ICONASTERISK;
  6663   else if (EQ (sound, intern ("exclamation")))
  6664       sound_type = MB_ICONEXCLAMATION;
  6665   else if (EQ (sound, intern ("hand")))
  6666       sound_type = MB_ICONHAND;
  6667   else if (EQ (sound, intern ("question")))
  6668       sound_type = MB_ICONQUESTION;
  6669   else if (EQ (sound, intern ("ok")))
  6670       sound_type = MB_OK;
  6671   else if (EQ (sound, intern ("silent")))
  6672       sound_type = MB_EMACS_SILENT;
  6673   else
  6674       sound_type = 0xFFFFFFFF;
  6675 
  6676   return sound;
  6677 }
  6678 
  6679 
  6680 /* Return the display structure for the display named NAME.
  6681    Open a new connection if necessary.  */
  6682 
  6683 static struct w32_display_info *
  6684 w32_display_info_for_name (Lisp_Object name)
  6685 {
  6686   struct w32_display_info *dpyinfo;
  6687 
  6688   CHECK_STRING (name);
  6689 
  6690   for (dpyinfo = &one_w32_display_info; dpyinfo; dpyinfo = dpyinfo->next)
  6691     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
  6692       return dpyinfo;
  6693 
  6694   /* Use this general default value to start with.  */
  6695   Vx_resource_name = Vinvocation_name;
  6696 
  6697   validate_x_resource_name ();
  6698 
  6699   dpyinfo = w32_term_init (name, NULL, SSDATA (Vx_resource_name));
  6700 
  6701   if (dpyinfo == 0)
  6702     error ("Cannot connect to server %s", SDATA (name));
  6703 
  6704   return dpyinfo;
  6705 }
  6706 
  6707 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
  6708        1, 3, 0, doc: /* SKIP: real doc in xfns.c.  */)
  6709   (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
  6710 {
  6711   char *xrm_option;
  6712   struct w32_display_info *dpyinfo;
  6713 
  6714   CHECK_STRING (display);
  6715 
  6716   /* Signal an error in order to encourage correct use from callers.
  6717    * If we ever support multiple window systems in the same Emacs,
  6718    * we'll need callers to be precise about what window system they
  6719    * want.  */
  6720 
  6721   if (strcmp (SSDATA (display), "w32") != 0)
  6722     error ("The name of the display in this Emacs must be \"w32\"");
  6723 
  6724   /* If initialization has already been done, return now to avoid
  6725      overwriting critical parts of one_w32_display_info.  */
  6726   if (window_system_available (NULL))
  6727     return Qnil;
  6728 
  6729   if (! NILP (xrm_string))
  6730     CHECK_STRING (xrm_string);
  6731 
  6732   /* Allow color mapping to be defined externally; first look in user's
  6733      HOME directory, then in Emacs etc dir for a file called rgb.txt. */
  6734   {
  6735     Lisp_Object color_file;
  6736 
  6737     color_file = build_string ("~/rgb.txt");
  6738 
  6739     if (NILP (Ffile_readable_p (color_file)))
  6740       color_file =
  6741         Fexpand_file_name (build_string ("rgb.txt"),
  6742                            Fsymbol_value (intern ("data-directory")));
  6743 
  6744     Vw32_color_map = Fx_load_color_file (color_file);
  6745   }
  6746   if (NILP (Vw32_color_map))
  6747     Vw32_color_map = w32_default_color_map ();
  6748 
  6749   /* Merge in system logical colors.  */
  6750   add_system_logical_colors_to_map (&Vw32_color_map);
  6751 
  6752   if (! NILP (xrm_string))
  6753     xrm_option = SSDATA (xrm_string);
  6754   else
  6755     xrm_option = NULL;
  6756 
  6757   /* Use this general default value to start with.  */
  6758   /* First remove .exe suffix from invocation-name - it looks ugly. */
  6759   {
  6760     char basename[ MAX_PATH ], *str;
  6761 
  6762     lispstpcpy (basename, Vinvocation_name);
  6763     str = strrchr (basename, '.');
  6764     if (str) *str = 0;
  6765     Vinvocation_name = build_string (basename);
  6766   }
  6767   Vx_resource_name = Vinvocation_name;
  6768 
  6769   validate_x_resource_name ();
  6770 
  6771   /* This is what opens the connection and sets x_current_display.
  6772      This also initializes many symbols, such as those used for input.  */
  6773   dpyinfo = w32_term_init (display, xrm_option, SSDATA (Vx_resource_name));
  6774 
  6775   if (dpyinfo == 0)
  6776     {
  6777       if (!NILP (must_succeed))
  6778         fatal ("Cannot connect to server %s.\n",
  6779                SDATA (display));
  6780       else
  6781         error ("Cannot connect to server %s", SDATA (display));
  6782     }
  6783 
  6784   return Qnil;
  6785 }
  6786 
  6787 DEFUN ("x-close-connection", Fx_close_connection,
  6788        Sx_close_connection, 1, 1, 0,
  6789        doc: /* SKIP: real doc in xfns.c.  */)
  6790   (Lisp_Object display)
  6791 {
  6792   struct w32_display_info *dpyinfo = check_x_display_info (display);
  6793 
  6794   if (dpyinfo->reference_count > 0)
  6795     error ("Display still has frames on it");
  6796 
  6797   block_input ();
  6798   image_destroy_all_bitmaps (dpyinfo);
  6799 
  6800   w32_delete_display (dpyinfo);
  6801   unblock_input ();
  6802 
  6803   return Qnil;
  6804 }
  6805 
  6806 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
  6807        doc: /* SKIP: real doc in xfns.c.  */)
  6808   (void)
  6809 {
  6810   Lisp_Object result = Qnil;
  6811   struct w32_display_info *wdi;
  6812 
  6813   for (wdi = x_display_list; wdi; wdi = wdi->next)
  6814     result = Fcons (XCAR (wdi->name_list_element), result);
  6815 
  6816   return result;
  6817 }
  6818 
  6819 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
  6820        doc: /* SKIP: real doc in xfns.c.  */)
  6821   (Lisp_Object on, Lisp_Object display)
  6822 {
  6823   return Qnil;
  6824 }
  6825 
  6826 
  6827 
  6828 /***********************************************************************
  6829                            Window properties
  6830  ***********************************************************************/
  6831 
  6832 #if 0 /* TODO : port window properties to W32 */
  6833 
  6834 DEFUN ("x-change-window-property", Fx_change_window_property,
  6835        Sx_change_window_property, 2, 6, 0,
  6836        doc: /* SKIP: real doc in xfns.c.  */)
  6837   (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
  6838    Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
  6839 {
  6840   struct frame *f = decode_window_system_frame (frame);
  6841   Atom prop_atom;
  6842 
  6843   CHECK_STRING (prop);
  6844   CHECK_STRING (value);
  6845 
  6846   block_input ();
  6847   prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
  6848   XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
  6849                    prop_atom, XA_STRING, 8, PropModeReplace,
  6850                    SDATA (value), SCHARS (value));
  6851 
  6852   /* Make sure the property is set when we return.  */
  6853   XFlush (FRAME_W32_DISPLAY (f));
  6854   unblock_input ();
  6855 
  6856   return value;
  6857 }
  6858 
  6859 
  6860 DEFUN ("x-delete-window-property", Fx_delete_window_property,
  6861        Sx_delete_window_property, 1, 2, 0,
  6862        doc: /* SKIP: real doc in xfns.c.  */)
  6863   (Lisp_Object prop, Lisp_Object frame)
  6864 {
  6865   struct frame *f = decode_window_system_frame (frame);
  6866   Atom prop_atom;
  6867 
  6868   CHECK_STRING (prop);
  6869   block_input ();
  6870   prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
  6871   XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
  6872 
  6873   /* Make sure the property is removed when we return.  */
  6874   XFlush (FRAME_W32_DISPLAY (f));
  6875   unblock_input ();
  6876 
  6877   return prop;
  6878 }
  6879 
  6880 
  6881 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
  6882        1, 6, 0,
  6883        doc: /* SKIP: real doc in xfns.c.  */)
  6884   (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
  6885    Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
  6886 {
  6887   struct frame *f = decode_window_system_frame (frame);
  6888   Atom prop_atom;
  6889   int rc;
  6890   Lisp_Object prop_value = Qnil;
  6891   char *tmp_data = NULL;
  6892   Atom actual_type;
  6893   int actual_format;
  6894   unsigned long actual_size, bytes_remaining;
  6895 
  6896   CHECK_STRING (prop);
  6897   block_input ();
  6898   prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
  6899   rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
  6900                            prop_atom, 0, 0, False, XA_STRING,
  6901                            &actual_type, &actual_format, &actual_size,
  6902                            &bytes_remaining, (unsigned char **) &tmp_data);
  6903   if (rc == Success)
  6904     {
  6905       int size = bytes_remaining;
  6906 
  6907       XFree (tmp_data);
  6908       tmp_data = NULL;
  6909 
  6910       rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
  6911                                prop_atom, 0, bytes_remaining,
  6912                                False, XA_STRING,
  6913                                &actual_type, &actual_format,
  6914                                &actual_size, &bytes_remaining,
  6915                                (unsigned char **) &tmp_data);
  6916       if (rc == Success)
  6917         prop_value = make_string (tmp_data, size);
  6918 
  6919       XFree (tmp_data);
  6920     }
  6921 
  6922   unblock_input ();
  6923 
  6924   return prop_value;
  6925 
  6926   return Qnil;
  6927 }
  6928 
  6929 #endif /* TODO */
  6930 
  6931 /***********************************************************************
  6932                                 Tool tips
  6933  ***********************************************************************/
  6934 
  6935 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
  6936                             Lisp_Object, int, int, int *, int *);
  6937 
  6938 /* The frame of the currently visible tooltip.  */
  6939 Lisp_Object tip_frame;
  6940 
  6941 /* The window-system window corresponding to the frame of the
  6942    currently visible tooltip.  */
  6943 Window tip_window;
  6944 
  6945 /* A timer that hides or deletes the currently visible tooltip when it
  6946    fires.  */
  6947 Lisp_Object tip_timer;
  6948 
  6949 /* STRING argument of last `x-show-tip' call.  */
  6950 Lisp_Object tip_last_string;
  6951 
  6952 /* Normalized FRAME argument of last `x-show-tip' call.  */
  6953 Lisp_Object tip_last_frame;
  6954 
  6955 /* PARMS argument of last `x-show-tip' call.  */
  6956 Lisp_Object tip_last_parms;
  6957 
  6958 
  6959 static void
  6960 unwind_create_tip_frame (Lisp_Object frame)
  6961 {
  6962   Lisp_Object deleted;
  6963 
  6964   deleted = unwind_create_frame (frame);
  6965   if (EQ (deleted, Qt))
  6966     {
  6967       tip_window = NULL;
  6968       tip_frame = Qnil;
  6969     }
  6970 }
  6971 
  6972 
  6973 /* Create a frame for a tooltip on the display described by DPYINFO.
  6974    PARMS is a list of frame parameters.  Value is the frame.
  6975 
  6976    Note that functions called here, esp. gui_default_parameter can
  6977    signal errors, for instance when a specified color name is
  6978    undefined.  We have to make sure that we're in a consistent state
  6979    when this happens.  */
  6980 
  6981 static Lisp_Object
  6982 w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
  6983 {
  6984   struct frame *f;
  6985   Lisp_Object frame;
  6986   Lisp_Object name;
  6987   specpdl_ref count = SPECPDL_INDEX ();
  6988   struct kboard *kb;
  6989   bool face_change_before = face_change;
  6990 
  6991   /* Use this general default value to start with until we know if
  6992      this frame has a specified name.  */
  6993   Vx_resource_name = Vinvocation_name;
  6994 
  6995   kb = dpyinfo->terminal->kboard;
  6996 
  6997   /* The calls to gui_display_get_arg remove elements from PARMS, so
  6998      copy it to avoid destructive changes behind our caller's
  6999      back.  */
  7000   parms = Fcopy_alist (parms);
  7001 
  7002   /* Get the name of the frame to use for resource lookup.  */
  7003   name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name",
  7004                               RES_TYPE_STRING);
  7005   if (!STRINGP (name)
  7006       && !BASE_EQ (name, Qunbound)
  7007       && !NILP (name))
  7008     error ("Invalid frame name--not a string or nil");
  7009   Vx_resource_name = name;
  7010 
  7011   frame = Qnil;
  7012   /* Make a frame without minibuffer nor mode-line.  */
  7013   f = make_frame (false);
  7014   f->wants_modeline = false;
  7015   XSETFRAME (frame, f);
  7016 
  7017   record_unwind_protect (unwind_create_tip_frame, frame);
  7018 
  7019   /* By setting the output method, we're essentially saying that
  7020      the frame is live, as per FRAME_LIVE_P.  If we get a signal
  7021      from this point on, w32_destroy_window might screw up reference
  7022      counts etc.  */
  7023   f->terminal = dpyinfo->terminal;
  7024   f->output_method = output_w32;
  7025   f->output_data.w32 = xzalloc (sizeof (struct w32_output));
  7026 
  7027   FRAME_FONTSET (f)  = -1;
  7028   fset_icon_name (f, Qnil);
  7029   f->tooltip = true;
  7030 
  7031 #ifdef GLYPH_DEBUG
  7032   image_cache_refcount =
  7033     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
  7034   dpyinfo_refcount = dpyinfo->reference_count;
  7035 #endif /* GLYPH_DEBUG */
  7036   FRAME_KBOARD (f) = kb;
  7037 
  7038   /* Set the name; the functions to which we pass f expect the name to
  7039      be set.  */
  7040   if (BASE_EQ (name, Qunbound) || NILP (name))
  7041     {
  7042       fset_name (f, build_string (dpyinfo->w32_id_name));
  7043       f->explicit_name = false;
  7044     }
  7045   else
  7046     {
  7047       fset_name (f, name);
  7048       f->explicit_name = true;
  7049       /* Use the frame's title when getting resources for this frame.  */
  7050       specbind (Qx_resource_name, name);
  7051     }
  7052 
  7053 #ifdef HAVE_HARFBUZZ
  7054   if (harfbuzz_available)
  7055     register_font_driver (&harfbuzz_font_driver, f);
  7056 #endif
  7057   register_font_driver (&uniscribe_font_driver, f);
  7058   register_font_driver (&w32font_driver, f);
  7059 
  7060   gui_default_parameter (f, parms, Qfont_backend, Qnil,
  7061                          "fontBackend", "FontBackend", RES_TYPE_STRING);
  7062 
  7063   /* Extract the window parameters from the supplied values
  7064      that are needed to determine window geometry.  */
  7065   w32_default_font_parameter (f, parms);
  7066 
  7067   gui_default_parameter (f, parms, Qborder_width, make_fixnum (2),
  7068                          "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
  7069   /* This defaults to 2 in order to match xterm.  We recognize either
  7070      internalBorderWidth or internalBorder (which is what xterm calls
  7071      it).  */
  7072   if (NILP (Fassq (Qinternal_border_width, parms)))
  7073     {
  7074       Lisp_Object value;
  7075 
  7076       value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width,
  7077                                    "internalBorder", "internalBorder",
  7078                                    RES_TYPE_NUMBER);
  7079       if (! BASE_EQ (value, Qunbound))
  7080         parms = Fcons (Fcons (Qinternal_border_width, value),
  7081                        parms);
  7082     }
  7083 
  7084   gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1),
  7085                          "internalBorderWidth", "internalBorderWidth",
  7086                          RES_TYPE_NUMBER);
  7087   /* Also do the stuff which must be set before the window exists.  */
  7088   gui_default_parameter (f, parms, Qforeground_color, build_string ("black"),
  7089                          "foreground", "Foreground", RES_TYPE_STRING);
  7090   gui_default_parameter (f, parms, Qbackground_color, build_string ("white"),
  7091                          "background", "Background", RES_TYPE_STRING);
  7092   gui_default_parameter (f, parms, Qmouse_color, build_string ("black"),
  7093                          "pointerColor", "Foreground", RES_TYPE_STRING);
  7094   gui_default_parameter (f, parms, Qcursor_color, build_string ("black"),
  7095                          "cursorColor", "Foreground", RES_TYPE_STRING);
  7096   gui_default_parameter (f, parms, Qborder_color, build_string ("black"),
  7097                          "borderColor", "BorderColor", RES_TYPE_STRING);
  7098   gui_default_parameter (f, parms, Qno_special_glyphs, Qt,
  7099                          NULL, NULL, RES_TYPE_BOOLEAN);
  7100 
  7101   /* Init faces before gui_default_parameter is called for the
  7102      scroll-bar-width parameter because otherwise we end up in
  7103      init_iterator with a null face cache, which should not happen.  */
  7104   init_frame_faces (f);
  7105 
  7106   f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
  7107   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
  7108   f->output_data.w32->explicit_parent = false;
  7109 
  7110   gui_figure_window_size (f, parms, true, true);
  7111 
  7112   /* No fringes on tip frame.  */
  7113   f->fringe_cols = 0;
  7114   f->left_fringe_width = 0;
  7115   f->right_fringe_width = 0;
  7116   /* No dividers on tip frame.  */
  7117   f->right_divider_width = 0;
  7118   f->bottom_divider_width = 0;
  7119 
  7120   block_input ();
  7121   my_create_tip_window (f);
  7122   unblock_input ();
  7123 
  7124   w32_make_gc (f);
  7125 
  7126   gui_default_parameter (f, parms, Qauto_raise, Qnil,
  7127                          "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  7128   gui_default_parameter (f, parms, Qauto_lower, Qnil,
  7129                          "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
  7130   gui_default_parameter (f, parms, Qcursor_type, Qbox,
  7131                          "cursorType", "CursorType", RES_TYPE_SYMBOL);
  7132   /* Process alpha here (Bug#17344).  */
  7133   gui_default_parameter (f, parms, Qalpha, Qnil,
  7134                          "alpha", "Alpha", RES_TYPE_NUMBER);
  7135   gui_default_parameter (f, parms, Qalpha_background, Qnil,
  7136                          "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
  7137   gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
  7138                          "inhibitDoubleBuffering", "InhibitDoubleBuffering",
  7139                          RES_TYPE_BOOLEAN);
  7140 
  7141   /* Add `tooltip' frame parameter's default value. */
  7142   if (NILP (Fframe_parameter (frame, Qtooltip)))
  7143     Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
  7144 
  7145   /* Set up faces after all frame parameters are known.  This call
  7146      also merges in face attributes specified for new frames.
  7147 
  7148      Frame parameters may be changed if .Xdefaults contains
  7149      specifications for the default font.  For example, if there is an
  7150      `Emacs.default.attributeBackground: pink', the `background-color'
  7151      attribute of the frame gets set, which let's the internal border
  7152      of the tooltip frame appear in pink.  Prevent this.  */
  7153   {
  7154     Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
  7155     Lisp_Object fg = Fframe_parameter (frame, Qforeground_color);
  7156     Lisp_Object colors = Qnil;
  7157 
  7158     call2 (Qface_set_after_frame_default, frame, Qnil);
  7159 
  7160     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
  7161       colors = Fcons (Fcons (Qbackground_color, bg), colors);
  7162     if (!EQ (fg, Fframe_parameter (frame, Qforeground_color)))
  7163       colors = Fcons (Fcons (Qforeground_color, fg), colors);
  7164 
  7165     if (!NILP (colors))
  7166       Fmodify_frame_parameters (frame, colors);
  7167   }
  7168 
  7169   f->no_split = true;
  7170 
  7171   /* Now that the frame is official, it counts as a reference to
  7172      its display.  */
  7173   FRAME_DISPLAY_INFO (f)->reference_count++;
  7174   f->terminal->reference_count++;
  7175 
  7176   /* It is now ok to make the frame official even if we get an error
  7177      below.  And the frame needs to be on Vframe_list or making it
  7178      visible won't work.  */
  7179   Vframe_list = Fcons (frame, Vframe_list);
  7180   f->can_set_window_size = true;
  7181   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
  7182                      0, true, Qtip_frame);
  7183 
  7184   /* Setting attributes of faces of the tooltip frame from resources
  7185      and similar will set face_change, which leads to the
  7186      clearing of all current matrices.  Since this isn't necessary
  7187      here, avoid it by resetting face_change to the value it
  7188      had before we created the tip frame.  */
  7189   face_change = face_change_before;
  7190 
  7191   /* Discard the unwind_protect.  */
  7192   return unbind_to (count, frame);
  7193 }
  7194 
  7195 
  7196 /* Compute where to display tip frame F.  PARMS is the list of frame
  7197    parameters for F.  DX and DY are specified offsets from the current
  7198    location of the mouse.  WIDTH and HEIGHT are the width and height
  7199    of the tooltip.  Return coordinates relative to the root window of
  7200    the display in *ROOT_X and *ROOT_Y.  */
  7201 
  7202 static void
  7203 compute_tip_xy (struct frame *f,
  7204                 Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
  7205                 int width, int height, int *root_x, int *root_y)
  7206 {
  7207   Lisp_Object left, top, right, bottom;
  7208   int min_x = 0, min_y = 0, max_x = 0, max_y = 0;
  7209 
  7210   /* User-specified position?  */
  7211   left = Fcdr (Fassq (Qleft, parms));
  7212   top  = Fcdr (Fassq (Qtop, parms));
  7213   right = Fcdr (Fassq (Qright, parms));
  7214   bottom = Fcdr (Fassq (Qbottom, parms));
  7215 
  7216   /* Move the tooltip window where the mouse pointer is.  Resize and
  7217      show it.  */
  7218   if ((!FIXNUMP (left) && !FIXNUMP (right))
  7219       || (!FIXNUMP (top) && !FIXNUMP (bottom)))
  7220     {
  7221       POINT pt;
  7222 
  7223       /* Default min and max values.  */
  7224       min_x = 0;
  7225       min_y = 0;
  7226       max_x = w32_display_pixel_width (FRAME_DISPLAY_INFO (f));
  7227       max_y = w32_display_pixel_height (FRAME_DISPLAY_INFO (f));
  7228 
  7229       block_input ();
  7230       GetCursorPos (&pt);
  7231       *root_x = pt.x;
  7232       *root_y = pt.y;
  7233       unblock_input ();
  7234 
  7235       /* If multiple monitor support is available, constrain the tip onto
  7236          the current monitor. This improves the above by allowing negative
  7237          coordinates if monitor positions are such that they are valid, and
  7238          snaps a tooltip onto a single monitor if we are close to the edge
  7239          where it would otherwise flow onto the other monitor (or into
  7240          nothingness if there is a gap in the overlap).  */
  7241       if (monitor_from_point_fn && get_monitor_info_fn)
  7242         {
  7243           struct MONITOR_INFO info;
  7244           HMONITOR monitor
  7245             = monitor_from_point_fn (pt, MONITOR_DEFAULT_TO_NEAREST);
  7246           info.cbSize = sizeof (info);
  7247 
  7248           if (get_monitor_info_fn (monitor, &info))
  7249             {
  7250               min_x = info.rcWork.left;
  7251               min_y = info.rcWork.top;
  7252               max_x = info.rcWork.right;
  7253               max_y = info.rcWork.bottom;
  7254             }
  7255         }
  7256     }
  7257 
  7258   if (FIXNUMP (top))
  7259     *root_y = XFIXNUM (top);
  7260   else if (FIXNUMP (bottom))
  7261     *root_y = XFIXNUM (bottom) - height;
  7262   else if (*root_y + XFIXNUM (dy) <= min_y)
  7263     *root_y = min_y; /* Can happen for negative dy */
  7264   else if (*root_y + XFIXNUM (dy) + height <= max_y)
  7265     /* It fits below the pointer */
  7266       *root_y += XFIXNUM (dy);
  7267   else if (height + XFIXNUM (dy) + min_y <= *root_y)
  7268     /* It fits above the pointer.  */
  7269     *root_y -= height + XFIXNUM (dy);
  7270   else
  7271     /* Put it on the top.  */
  7272     *root_y = min_y;
  7273 
  7274   if (FIXNUMP (left))
  7275     *root_x = XFIXNUM (left);
  7276   else if (FIXNUMP (right))
  7277     *root_x = XFIXNUM (right) - width;
  7278   else if (*root_x + XFIXNUM (dx) <= min_x)
  7279     *root_x = 0; /* Can happen for negative dx */
  7280   else if (*root_x + XFIXNUM (dx) + width <= max_x)
  7281     /* It fits to the right of the pointer.  */
  7282     *root_x += XFIXNUM (dx);
  7283   else if (width + XFIXNUM (dx) + min_x <= *root_x)
  7284     /* It fits to the left of the pointer.  */
  7285     *root_x -= width + XFIXNUM (dx);
  7286   else
  7287     /* Put it left justified on the screen -- it ought to fit that way.  */
  7288     *root_x = min_x;
  7289 }
  7290 
  7291 /**
  7292  * w32_hide_tip:
  7293  *
  7294  * Hide currently visible tooltip and cancel its timer.
  7295  *
  7296  * This will try to make tooltip_frame invisible (if DELETE is false)
  7297  * or delete tooltip_frame (if DELETE is true).
  7298  *
  7299  * Return Qt if the tooltip was either deleted or made invisible, Qnil
  7300  * otherwise.
  7301  */
  7302 static Lisp_Object
  7303 w32_hide_tip (bool delete)
  7304 {
  7305   if (!NILP (tip_timer))
  7306     {
  7307       call1 (Qcancel_timer, tip_timer);
  7308       tip_timer = Qnil;
  7309     }
  7310 
  7311   if (NILP (tip_frame)
  7312       || (!delete && FRAMEP (tip_frame)
  7313           && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
  7314     return Qnil;
  7315   else
  7316     {
  7317       Lisp_Object was_open = Qnil;
  7318 
  7319       specpdl_ref count = SPECPDL_INDEX ();
  7320       specbind (Qinhibit_redisplay, Qt);
  7321       specbind (Qinhibit_quit, Qt);
  7322 
  7323       if (FRAMEP (tip_frame))
  7324         {
  7325           if (FRAME_LIVE_P (XFRAME (tip_frame)))
  7326             {
  7327               if (delete)
  7328                 {
  7329                   delete_frame (tip_frame, Qnil);
  7330                   tip_frame = Qnil;
  7331                 }
  7332               else
  7333                 w32_make_frame_invisible (XFRAME (tip_frame));
  7334 
  7335               was_open = Qt;
  7336             }
  7337           else
  7338             tip_frame = Qnil;
  7339         }
  7340       else
  7341         tip_frame = Qnil;
  7342 
  7343       return unbind_to (count, was_open);
  7344     }
  7345 }
  7346 
  7347 
  7348 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
  7349        doc: /* SKIP: real doc in xfns.c.  */)
  7350   (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
  7351    Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
  7352 {
  7353   struct frame *tip_f;
  7354   struct window *w;
  7355   int root_x, root_y;
  7356   struct buffer *old_buffer;
  7357   struct text_pos pos;
  7358   int width, height;
  7359   int old_windows_or_buffers_changed = windows_or_buffers_changed;
  7360   specpdl_ref count = SPECPDL_INDEX ();
  7361   Lisp_Object window, size, tip_buf;
  7362   AUTO_STRING (tip, " *tip*");
  7363 
  7364   specbind (Qinhibit_redisplay, Qt);
  7365 
  7366   CHECK_STRING (string);
  7367 
  7368   if (NILP (frame))
  7369     frame = selected_frame;
  7370   decode_window_system_frame (frame);
  7371 
  7372   if (NILP (timeout))
  7373     timeout = Vx_show_tooltip_timeout;
  7374   CHECK_FIXNAT (timeout);
  7375 
  7376   if (NILP (dx))
  7377     dx = make_fixnum (5);
  7378   else
  7379     CHECK_FIXNUM (dx);
  7380 
  7381   if (NILP (dy))
  7382     dy = make_fixnum (-10);
  7383   else
  7384     CHECK_FIXNUM (dy);
  7385 
  7386   if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
  7387     {
  7388       if (FRAME_VISIBLE_P (XFRAME (tip_frame))
  7389           && EQ (frame, tip_last_frame)
  7390           && !NILP (Fequal_including_properties (string, tip_last_string))
  7391           && !NILP (Fequal (parms, tip_last_parms)))
  7392         {
  7393           /* Only DX and DY have changed.  */
  7394           tip_f = XFRAME (tip_frame);
  7395           if (!NILP (tip_timer))
  7396             {
  7397               Lisp_Object timer = tip_timer;
  7398 
  7399               tip_timer = Qnil;
  7400               call1 (Qcancel_timer, timer);
  7401             }
  7402 
  7403           block_input ();
  7404           compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f),
  7405                           FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y);
  7406 
  7407           /* Put tooltip in topmost group and in position.  */
  7408           SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
  7409                         root_x, root_y, 0, 0,
  7410                         SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  7411 
  7412           /* Ensure tooltip is on top of other topmost windows (eg menus).  */
  7413           SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
  7414                         0, 0, 0, 0,
  7415                         SWP_NOMOVE | SWP_NOSIZE
  7416                         | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  7417 
  7418           /* Let redisplay know that we have made the frame visible already.  */
  7419           SET_FRAME_VISIBLE (tip_f, 1);
  7420           ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
  7421           unblock_input ();
  7422 
  7423           goto start_timer;
  7424         }
  7425       else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame))
  7426         {
  7427           bool delete = false;
  7428           Lisp_Object tail, elt, parm, last;
  7429 
  7430           /* Check if every parameter in PARMS has the same value in
  7431              tip_last_parms.  This may destruct tip_last_parms
  7432              which, however, will be recreated below.  */
  7433           for (tail = parms; CONSP (tail); tail = XCDR (tail))
  7434             {
  7435               elt = XCAR (tail);
  7436               parm = Fcar (elt);
  7437               /* The left, top, right and bottom parameters are handled
  7438                  by compute_tip_xy so they can be ignored here.  */
  7439               if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
  7440                   && !EQ (parm, Qright) && !EQ (parm, Qbottom))
  7441                 {
  7442                   last = Fassq (parm, tip_last_parms);
  7443                   if (NILP (Fequal (Fcdr (elt), Fcdr (last))))
  7444                     {
  7445                       /* We lost, delete the old tooltip.  */
  7446                       delete = true;
  7447                       break;
  7448                     }
  7449                   else
  7450                     tip_last_parms =
  7451                       call2 (Qassq_delete_all, parm, tip_last_parms);
  7452                 }
  7453               else
  7454                 tip_last_parms =
  7455                   call2 (Qassq_delete_all, parm, tip_last_parms);
  7456             }
  7457 
  7458           /* Now check if there's a parameter left in tip_last_parms with a
  7459              non-nil value.  */
  7460           for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
  7461             {
  7462               elt = XCAR (tail);
  7463               parm = Fcar (elt);
  7464               if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
  7465                   && !EQ (parm, Qbottom) && !NILP (Fcdr (elt)))
  7466                 {
  7467                   /* We lost, delete the old tooltip.  */
  7468                   delete = true;
  7469                   break;
  7470                 }
  7471             }
  7472 
  7473           w32_hide_tip (delete);
  7474         }
  7475       else
  7476         w32_hide_tip (true);
  7477     }
  7478   else
  7479     w32_hide_tip (true);
  7480 
  7481   tip_last_frame = frame;
  7482   tip_last_string = string;
  7483   tip_last_parms = parms;
  7484 
  7485   /* Block input until the tip has been fully drawn, to avoid crashes
  7486      when drawing tips in menus.  */
  7487   block_input ();
  7488 
  7489   if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame)))
  7490     {
  7491       /* Add default values to frame parameters.  */
  7492       if (NILP (Fassq (Qname, parms)))
  7493         parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
  7494       if (NILP (Fassq (Qinternal_border_width, parms)))
  7495         parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms);
  7496       if (NILP (Fassq (Qborder_width, parms)))
  7497         parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms);
  7498       if (NILP (Fassq (Qborder_color, parms)))
  7499         parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")),
  7500                        parms);
  7501       if (NILP (Fassq (Qbackground_color, parms)))
  7502         parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
  7503                        parms);
  7504 
  7505       /* Create a frame for the tooltip and record it in the global
  7506          variable tip_frame.  */
  7507       struct frame *f;          /* The value is unused.  */
  7508       if (NILP (tip_frame = w32_create_tip_frame (FRAME_DISPLAY_INFO (f), parms)))
  7509         {
  7510           /* Creating the tip frame failed.  */
  7511           unblock_input ();
  7512           return unbind_to (count, Qnil);
  7513         }
  7514     }
  7515 
  7516   tip_f = XFRAME (tip_frame);
  7517   window = FRAME_ROOT_WINDOW (tip_f);
  7518   tip_buf = Fget_buffer_create (tip, Qnil);
  7519   /* We will mark the tip window a "pseudo-window" below, and such
  7520      windows cannot have display margins.  */
  7521   bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
  7522   bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0));
  7523   set_window_buffer (window, tip_buf, false, false);
  7524   w = XWINDOW (window);
  7525   w->pseudo_window_p = true;
  7526   /* Try to avoid that `other-window' select us (Bug#47207).  */
  7527   Fset_window_parameter (window, Qno_other_window, Qt);
  7528 
  7529   /* Set up the frame's root window.  Note: The following code does not
  7530      try to size the window or its frame correctly.  Its only purpose is
  7531      to make the subsequent text size calculations work.  The right
  7532      sizes should get installed when the toolkit gets back to us.  */
  7533   w->left_col = 0;
  7534   w->top_line = 0;
  7535   w->pixel_left = 0;
  7536   w->pixel_top = 0;
  7537 
  7538   if (CONSP (Vx_max_tooltip_size)
  7539       && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
  7540       && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX))
  7541     {
  7542       w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size));
  7543       w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size));
  7544     }
  7545   else
  7546     {
  7547       w->total_cols = 80;
  7548       w->total_lines = 40;
  7549     }
  7550 
  7551   w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f);
  7552   w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f);
  7553   FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w);
  7554   adjust_frame_glyphs (tip_f);
  7555 
  7556   /* Insert STRING into the root window's buffer and fit the frame to
  7557      the buffer.  */
  7558   specpdl_ref count_1 = SPECPDL_INDEX ();
  7559   old_buffer = current_buffer;
  7560   set_buffer_internal_1 (XBUFFER (w->contents));
  7561   bset_truncate_lines (current_buffer, Qnil);
  7562   specbind (Qinhibit_read_only, Qt);
  7563   specbind (Qinhibit_modification_hooks, Qt);
  7564   specbind (Qinhibit_point_motion_hooks, Qt);
  7565   Ferase_buffer ();
  7566   Finsert (1, &string);
  7567   clear_glyph_matrix (w->desired_matrix);
  7568   clear_glyph_matrix (w->current_matrix);
  7569   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
  7570   bool displayed = try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
  7571   if (!displayed && NILP (Vx_max_tooltip_size))
  7572     {
  7573 #ifdef ENABLE_CHECKING
  7574       struct glyph_row *row = w->desired_matrix->rows;
  7575       struct glyph_row *end =
  7576         w->desired_matrix->rows + w->desired_matrix->nrows;
  7577       while (row < end)
  7578         {
  7579           if (!row->displays_text_p
  7580               || row->ends_at_zv_p)
  7581             break;
  7582           ++row;
  7583         }
  7584       eassert (row < end && row->ends_at_zv_p);
  7585 #endif
  7586     }
  7587   /* Calculate size of tooltip window.  */
  7588   size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
  7589                                   make_fixnum (w->pixel_height), Qnil,
  7590                                   Qnil);
  7591   /* Add the frame's internal border to calculated size.  */
  7592   width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
  7593   height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
  7594   /* Calculate position of tooltip frame.  */
  7595   compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
  7596 
  7597   /* Show tooltip frame.  */
  7598   {
  7599     RECT rect;
  7600     int pad = (FIXNUMP (Vw32_tooltip_extra_pixels)
  7601                ? max (0, XFIXNUM (Vw32_tooltip_extra_pixels))
  7602                : FRAME_COLUMN_WIDTH (tip_f));
  7603 
  7604     rect.left = rect.top = 0;
  7605     rect.right = width;
  7606     rect.bottom = height;
  7607     AdjustWindowRect (&rect, tip_f->output_data.w32->dwStyle,
  7608                       FRAME_EXTERNAL_MENU_BAR (tip_f));
  7609 
  7610     /* Position and size tooltip and put it in the topmost group.  */
  7611     SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST,
  7612                   root_x, root_y,
  7613                   rect.right - rect.left + pad,
  7614                   rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  7615 
  7616     /* Ensure tooltip is on top of other topmost windows (eg menus).  */
  7617     SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP,
  7618                   0, 0, 0, 0,
  7619                   SWP_NOMOVE | SWP_NOSIZE
  7620                   | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  7621 
  7622     /* Let redisplay know that we have made the frame visible already.  */
  7623     SET_FRAME_VISIBLE (tip_f, 1);
  7624 
  7625     ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE);
  7626   }
  7627 
  7628   w->must_be_updated_p = true;
  7629   update_single_window (w);
  7630   set_buffer_internal_1 (old_buffer);
  7631   unbind_to (count_1, Qnil);
  7632   unblock_input ();
  7633   windows_or_buffers_changed = old_windows_or_buffers_changed;
  7634 
  7635  start_timer:
  7636   /* Let the tip disappear after timeout seconds.  */
  7637   tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
  7638                      intern ("x-hide-tip"));
  7639 
  7640   return unbind_to (count, Qnil);
  7641 }
  7642 
  7643 
  7644 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
  7645        doc: /* SKIP: real doc in xfns.c.  */)
  7646   (void)
  7647 {
  7648   return w32_hide_tip (!tooltip_reuse_hidden_frame);
  7649 }
  7650 
  7651 /***********************************************************************
  7652                         File selection dialog
  7653  ***********************************************************************/
  7654 
  7655 #define FILE_NAME_TEXT_FIELD edt1
  7656 #define FILE_NAME_COMBO_BOX cmb13
  7657 #define FILE_NAME_LIST lst1
  7658 
  7659 /* Callback for altering the behavior of the Open File dialog.
  7660    Makes the Filename text field contain "Current Directory" and be
  7661    read-only when "Directories" is selected in the filter.  This
  7662    allows us to work around the fact that the standard Open File
  7663    dialog does not support directories.  */
  7664 static UINT_PTR CALLBACK
  7665 file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  7666 {
  7667   if (msg == WM_NOTIFY)
  7668     {
  7669       OFNOTIFYW * notify_w = (OFNOTIFYW *)lParam;
  7670       OFNOTIFYA * notify_a = (OFNOTIFYA *)lParam;
  7671       int dropdown_changed;
  7672       int dir_index;
  7673 #ifdef NTGUI_UNICODE
  7674       const int use_unicode = 1;
  7675 #else /* !NTGUI_UNICODE */
  7676       int use_unicode = w32_unicode_filenames;
  7677 #endif /* NTGUI_UNICODE */
  7678 
  7679       /* Detect when the Filter dropdown is changed.  */
  7680       if (use_unicode)
  7681         dropdown_changed =
  7682           notify_w->hdr.code == CDN_TYPECHANGE
  7683           || notify_w->hdr.code == CDN_INITDONE;
  7684       else
  7685         dropdown_changed =
  7686           notify_a->hdr.code == CDN_TYPECHANGE
  7687           || notify_a->hdr.code == CDN_INITDONE;
  7688       if (dropdown_changed)
  7689         {
  7690           HWND dialog = GetParent (hwnd);
  7691           HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD);
  7692           HWND list = GetDlgItem (dialog, FILE_NAME_LIST);
  7693           int hdr_code;
  7694 
  7695           /* At least on Windows 7, the above attempt to get the window handle
  7696              to the File Name Text Field fails.  The following code does the
  7697              job though.  Note that this code is based on my examination of the
  7698              window hierarchy using Microsoft Spy++.  bk */
  7699           if (edit_control == NULL)
  7700             {
  7701               HWND tmp = GetDlgItem (dialog, FILE_NAME_COMBO_BOX);
  7702               if (tmp)
  7703                 {
  7704                   tmp = GetWindow (tmp, GW_CHILD);
  7705                   if (tmp)
  7706                     edit_control = GetWindow (tmp, GW_CHILD);
  7707                 }
  7708             }
  7709 
  7710           /* Directories is in index 2.  */
  7711           if (use_unicode)
  7712             {
  7713               dir_index = notify_w->lpOFN->nFilterIndex;
  7714               hdr_code = notify_w->hdr.code;
  7715             }
  7716           else
  7717             {
  7718               dir_index = notify_a->lpOFN->nFilterIndex;
  7719               hdr_code = notify_a->hdr.code;
  7720             }
  7721           if (dir_index == 2)
  7722             {
  7723               if (use_unicode)
  7724                 SendMessageW (dialog, CDM_SETCONTROLTEXT, FILE_NAME_TEXT_FIELD,
  7725                               (LPARAM)L"Current Directory");
  7726               else
  7727                 SendMessageA (dialog, CDM_SETCONTROLTEXT, FILE_NAME_TEXT_FIELD,
  7728                               (LPARAM)"Current Directory");
  7729               EnableWindow (edit_control, FALSE);
  7730               /* Note that at least on Windows 7, the above call to EnableWindow
  7731                  disables the window that would ordinarily have focus.  If we
  7732                  do not set focus to some other window here, focus will land in
  7733                  no man's land and the user will be unable to tab through the
  7734                  dialog box (pressing tab will only result in a beep).
  7735                  Avoid that problem by setting focus to the list here.  */
  7736               if (hdr_code == CDN_INITDONE)
  7737                 SetFocus (list);
  7738             }
  7739           else
  7740             {
  7741               /* Don't override default filename on init done.  */
  7742               if (hdr_code == CDN_TYPECHANGE)
  7743                 {
  7744                   if (use_unicode)
  7745                     SendMessageW (dialog, CDM_SETCONTROLTEXT,
  7746                                   FILE_NAME_TEXT_FIELD, (LPARAM)L"");
  7747                   else
  7748                     SendMessageA (dialog, CDM_SETCONTROLTEXT,
  7749                                   FILE_NAME_TEXT_FIELD, (LPARAM)"");
  7750                 }
  7751               EnableWindow (edit_control, TRUE);
  7752             }
  7753         }
  7754     }
  7755   return 0;
  7756 }
  7757 
  7758 /**
  7759  * w32_dialog_in_progress:
  7760  *
  7761  * This function is called by Fx_file_dialog and Fx_select_font and
  7762  * serves to temporarily remove any Emacs frame currently in the
  7763  * 'above' z-group from that group to assure that such a frame does
  7764  * not hide the dialog window.  Frames that are temporarily removed
  7765  * from the 'above' group have their z_group bit-field set to
  7766  * z_group_above_suspended.  Any such frame is moved back to the
  7767  * 'above' group as soon as the dialog finishes and has its z_group
  7768  * bit-field reset to z_group_above.
  7769  *
  7770  * This function does not affect the z-order or the z-group state of
  7771  * the dialog window itself.
  7772  */
  7773 void
  7774 w32_dialog_in_progress (Lisp_Object in_progress)
  7775 {
  7776   Lisp_Object frames, frame;
  7777 
  7778   /* Indicate to w32_wnd_proc that the selection dialog is about to be
  7779      open (or was closed, if IN_PROGRESS is nil).  */
  7780   if (!w32_disable_double_buffering)
  7781     {
  7782       enter_crit ();
  7783       w32_selection_dialog_open = !NILP (in_progress);
  7784       leave_crit ();
  7785     }
  7786 
  7787   /* Don't let frames in `above' z-group obscure dialog windows.  */
  7788   FOR_EACH_FRAME (frames, frame)
  7789     {
  7790       struct frame *f = XFRAME (frame);
  7791 
  7792       if (!NILP (in_progress) && FRAME_Z_GROUP_ABOVE (f))
  7793         w32_set_z_group (f, Qabove_suspended, Qabove);
  7794       else if (NILP (in_progress) && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
  7795         w32_set_z_group (f, Qabove, Qabove_suspended);
  7796     }
  7797 }
  7798 
  7799 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
  7800        doc: /* SKIP: real doc in xfns.c.  */)
  7801   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
  7802 {
  7803   /* Filter index: 1: All Files, 2: Directories only  */
  7804   static const wchar_t filter_w[] = L"All Files (*.*)\0*.*\0Directories\0*|*\0";
  7805 #ifndef NTGUI_UNICODE
  7806   static const char filter_a[] = "All Files (*.*)\0*.*\0Directories\0*|*\0";
  7807 #endif
  7808 
  7809   Lisp_Object filename = default_filename;
  7810   struct frame *f = SELECTED_FRAME ();
  7811   BOOL file_opened = FALSE;
  7812   Lisp_Object orig_dir = dir;
  7813   Lisp_Object orig_prompt = prompt;
  7814 
  7815   /* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
  7816      compatibility) we end up with the old file dialogs. Define a big
  7817      enough struct for the new dialog to trick GetOpenFileName into
  7818      giving us the new dialogs on newer versions of Windows.  */
  7819   struct {
  7820     OPENFILENAMEW details;
  7821 #if _WIN32_WINNT < 0x500 /* < win2k */
  7822       PVOID pvReserved;
  7823       DWORD dwReserved;
  7824       DWORD FlagsEx;
  7825 #endif /* < win2k */
  7826   } new_file_details_w;
  7827 
  7828 #ifdef NTGUI_UNICODE
  7829   wchar_t filename_buf_w[32*1024 + 1]; /* NT kernel maximum */
  7830   OPENFILENAMEW * file_details_w = &new_file_details_w.details;
  7831   const int use_unicode = 1;
  7832 #else /* not NTGUI_UNICODE */
  7833   struct {
  7834     OPENFILENAMEA details;
  7835 #if _WIN32_WINNT < 0x500 /* < win2k */
  7836       PVOID pvReserved;
  7837       DWORD dwReserved;
  7838       DWORD FlagsEx;
  7839 #endif /* < win2k */
  7840   } new_file_details_a;
  7841   wchar_t filename_buf_w[MAX_PATH + 1], dir_w[MAX_PATH];
  7842   char filename_buf_a[MAX_PATH + 1], dir_a[MAX_PATH];
  7843   OPENFILENAMEW * file_details_w = &new_file_details_w.details;
  7844   OPENFILENAMEA * file_details_a = &new_file_details_a.details;
  7845   int use_unicode = w32_unicode_filenames;
  7846   wchar_t *prompt_w;
  7847   char *prompt_a UNINIT;
  7848   int len;
  7849   char fname_ret[MAX_UTF8_PATH];
  7850 #endif /* NTGUI_UNICODE */
  7851 
  7852   {
  7853     /* Note: under NTGUI_UNICODE, we do _NOT_ use ENCODE_FILE: the
  7854        system file encoding expected by the platform APIs (e.g. Cygwin's
  7855        POSIX implementation) may not be the same as the encoding expected
  7856        by the Windows "ANSI" APIs!  */
  7857 
  7858     CHECK_STRING (prompt);
  7859     CHECK_STRING (dir);
  7860 
  7861     dir = Fexpand_file_name (dir, Qnil);
  7862 
  7863     if (STRINGP (filename))
  7864       filename = Ffile_name_nondirectory (filename);
  7865     else
  7866       filename = empty_unibyte_string;
  7867 
  7868 #ifdef CYGWIN
  7869     dir = Fcygwin_convert_file_name_to_windows (dir, Qt);
  7870     if (SCHARS (filename) > 0)
  7871       filename = Fcygwin_convert_file_name_to_windows (filename, Qnil);
  7872 #endif
  7873 
  7874     CHECK_STRING (dir);
  7875     CHECK_STRING (filename);
  7876 
  7877     /* The code in file_dialog_callback that attempts to set the text
  7878        of the file name edit window when handling the CDN_INITDONE
  7879        WM_NOTIFY message does not work.  Setting filename to "Current
  7880        Directory" in the only_dir_p case here does work however.  */
  7881     if (SCHARS (filename) == 0 && ! NILP (only_dir_p))
  7882       filename = build_string ("Current Directory");
  7883 
  7884     /* Convert the values we've computed so far to system form.  */
  7885 #ifdef NTGUI_UNICODE
  7886     to_unicode (prompt, &prompt);
  7887     to_unicode (dir, &dir);
  7888     to_unicode (filename, &filename);
  7889     if (SBYTES (filename) + 1 > sizeof (filename_buf_w))
  7890       report_file_error ("filename too long", default_filename);
  7891 
  7892     memcpy (filename_buf_w, SDATA (filename), SBYTES (filename) + 1);
  7893 #else /* !NTGUI_UNICODE */
  7894     prompt = ENCODE_FILE (prompt);
  7895     dir = ENCODE_FILE (dir);
  7896     filename = ENCODE_FILE (filename);
  7897 
  7898     /* We modify these in-place, so make copies for safety.  */
  7899     dir = Fcopy_sequence (dir);
  7900     unixtodos_filename (SSDATA (dir));
  7901     filename = Fcopy_sequence (filename);
  7902     unixtodos_filename (SSDATA (filename));
  7903     if (SBYTES (filename) >= MAX_UTF8_PATH)
  7904       report_file_error ("filename too long", default_filename);
  7905     if (w32_unicode_filenames)
  7906       {
  7907         filename_to_utf16 (SSDATA (dir), dir_w);
  7908         if (filename_to_utf16 (SSDATA (filename), filename_buf_w) != 0)
  7909           {
  7910             /* filename_to_utf16 sets errno to ENOENT when the file
  7911                name is too long or cannot be converted to UTF-16.  */
  7912             if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0)
  7913               report_file_error ("filename too long", default_filename);
  7914           }
  7915         len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  7916                                     SSDATA (prompt), -1, NULL, 0);
  7917         if (len > 32768)
  7918           len = 32768;
  7919         prompt_w = alloca (len * sizeof (wchar_t));
  7920         pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  7921                               SSDATA (prompt), -1, prompt_w, len);
  7922       }
  7923     else
  7924       {
  7925         filename_to_ansi (SSDATA (dir), dir_a);
  7926         if (filename_to_ansi (SSDATA (filename), filename_buf_a) != '\0')
  7927           {
  7928             /* filename_to_ansi sets errno to ENOENT when the file
  7929                name is too long or cannot be converted to UTF-16.  */
  7930             if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0)
  7931               report_file_error ("filename too long", default_filename);
  7932           }
  7933         len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  7934                                     SSDATA (prompt), -1, NULL, 0);
  7935         if (len > 32768)
  7936           len = 32768;
  7937         prompt_w = alloca (len * sizeof (wchar_t));
  7938         pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  7939                               SSDATA (prompt), -1, prompt_w, len);
  7940         len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL);
  7941         if (len > 32768)
  7942           len = 32768;
  7943         prompt_a = alloca (len);
  7944         pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, prompt_a, len, NULL, NULL);
  7945       }
  7946 #endif /* NTGUI_UNICODE */
  7947 
  7948     /* Fill in the structure for the call to GetOpenFileName below.
  7949        For NTGUI_UNICODE builds (which run only on NT), we just use
  7950        the actual size of the structure.  For non-NTGUI_UNICODE
  7951        builds, we tell the OS we're using an old version of the
  7952        structure if the OS isn't new enough to support the newer
  7953        version.  */
  7954     if (use_unicode)
  7955       {
  7956         memset (&new_file_details_w, 0, sizeof (new_file_details_w));
  7957         if (w32_major_version > 4 && w32_major_version < 95)
  7958           file_details_w->lStructSize = sizeof (new_file_details_w);
  7959         else
  7960           file_details_w->lStructSize = sizeof (*file_details_w);
  7961         /* Set up the inout parameter for the selected file name.  */
  7962         file_details_w->lpstrFile = filename_buf_w;
  7963         file_details_w->nMaxFile =
  7964           sizeof (filename_buf_w) / sizeof (*filename_buf_w);
  7965         file_details_w->hwndOwner = FRAME_W32_WINDOW (f);
  7966         /* Undocumented Bug in Common File Dialog:
  7967            If a filter is not specified, shell links are not resolved.  */
  7968         file_details_w->lpstrFilter = filter_w;
  7969 #ifdef NTGUI_UNICODE
  7970         file_details_w->lpstrInitialDir = (wchar_t*) SDATA (dir);
  7971         file_details_w->lpstrTitle = (guichar_t*) SDATA (prompt);
  7972 #else
  7973         file_details_w->lpstrInitialDir = dir_w;
  7974         file_details_w->lpstrTitle = prompt_w;
  7975 #endif
  7976         file_details_w->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
  7977         file_details_w->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
  7978                                  | OFN_EXPLORER | OFN_ENABLEHOOK);
  7979         if (!NILP (mustmatch))
  7980           {
  7981             /* Require that the path to the parent directory exists.  */
  7982             file_details_w->Flags |= OFN_PATHMUSTEXIST;
  7983             /* If we are looking for a file, require that it exists.  */
  7984             if (NILP (only_dir_p))
  7985               file_details_w->Flags |= OFN_FILEMUSTEXIST;
  7986           }
  7987       }
  7988 #ifndef NTGUI_UNICODE
  7989     else
  7990       {
  7991         memset (&new_file_details_a, 0, sizeof (new_file_details_a));
  7992         if (w32_major_version > 4 && w32_major_version < 95)
  7993           file_details_a->lStructSize = sizeof (new_file_details_a);
  7994         else
  7995           file_details_a->lStructSize = sizeof (*file_details_a);
  7996         file_details_a->lpstrFile = filename_buf_a;
  7997         file_details_a->nMaxFile =
  7998           sizeof (filename_buf_a) / sizeof (*filename_buf_a);
  7999         file_details_a->hwndOwner = FRAME_W32_WINDOW (f);
  8000         file_details_a->lpstrFilter = filter_a;
  8001         file_details_a->lpstrInitialDir = dir_a;
  8002         file_details_a->lpstrTitle = prompt_a;
  8003         file_details_a->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
  8004         file_details_a->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
  8005                                  | OFN_EXPLORER | OFN_ENABLEHOOK);
  8006         if (!NILP (mustmatch))
  8007           {
  8008             /* Require that the path to the parent directory exists.  */
  8009             file_details_a->Flags |= OFN_PATHMUSTEXIST;
  8010             /* If we are looking for a file, require that it exists.  */
  8011             if (NILP (only_dir_p))
  8012               file_details_a->Flags |= OFN_FILEMUSTEXIST;
  8013           }
  8014       }
  8015 #endif  /* !NTGUI_UNICODE */
  8016 
  8017     {
  8018       specpdl_ref count = SPECPDL_INDEX ();
  8019 
  8020       w32_dialog_in_progress (Qt);
  8021 
  8022       /* Prevent redisplay.  */
  8023       specbind (Qinhibit_redisplay, Qt);
  8024       record_unwind_protect (w32_dialog_in_progress, Qnil);
  8025       block_input ();
  8026       if (use_unicode)
  8027         {
  8028           file_details_w->lpfnHook = file_dialog_callback;
  8029 
  8030           file_opened = GetOpenFileNameW (file_details_w);
  8031         }
  8032 #ifndef NTGUI_UNICODE
  8033       else
  8034         {
  8035           file_details_a->lpfnHook = file_dialog_callback;
  8036 
  8037           file_opened = GetOpenFileNameA (file_details_a);
  8038         }
  8039 #endif  /* !NTGUI_UNICODE */
  8040       unblock_input ();
  8041       unbind_to (count, Qnil);
  8042     }
  8043 
  8044     if (file_opened)
  8045       {
  8046         /* Get an Emacs string from the value Windows gave us.  */
  8047 #ifdef NTGUI_UNICODE
  8048         filename = from_unicode_buffer (filename_buf_w);
  8049 #else /* !NTGUI_UNICODE */
  8050         if (use_unicode)
  8051           filename_from_utf16 (filename_buf_w, fname_ret);
  8052         else
  8053           filename_from_ansi (filename_buf_a, fname_ret);
  8054         dostounix_filename (fname_ret);
  8055         filename = DECODE_FILE (build_unibyte_string (fname_ret));
  8056 #endif /* NTGUI_UNICODE */
  8057 
  8058 #ifdef CYGWIN
  8059         filename = Fcygwin_convert_file_name_from_windows (filename, Qt);
  8060 #endif /* CYGWIN */
  8061 
  8062         /* Strip the dummy filename off the end of the string if we
  8063            added it to select a directory.  */
  8064         if ((use_unicode && file_details_w->nFilterIndex == 2)
  8065 #ifndef NTGUI_UNICODE
  8066             || (!use_unicode && file_details_a->nFilterIndex == 2)
  8067 #endif
  8068             )
  8069           filename = Ffile_name_directory (filename);
  8070       }
  8071     /* User canceled the dialog without making a selection.  */
  8072     else if (!CommDlgExtendedError ())
  8073       filename = Qnil;
  8074     /* An error occurred, fallback on reading from the mini-buffer.  */
  8075     else
  8076       filename = Fcompleting_read (
  8077         orig_prompt,
  8078         intern ("read-file-name-internal"),
  8079         orig_dir,
  8080         mustmatch,
  8081         orig_dir,
  8082         Qfile_name_history,
  8083         default_filename,
  8084         Qnil);
  8085   }
  8086 
  8087   /* Make "Cancel" equivalent to C-g.  */
  8088   if (NILP (filename))
  8089     quit ();
  8090 
  8091   return filename;
  8092 }
  8093 
  8094 
  8095 #ifdef WINDOWSNT
  8096 /* Moving files to the system recycle bin.
  8097    Used by `move-file-to-trash' instead of the default moving to ~/.Trash  */
  8098 DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
  8099        Ssystem_move_file_to_trash, 1, 1, 0,
  8100        doc: /* Move file or directory named FILENAME to the recycle bin.  */)
  8101   (Lisp_Object filename)
  8102 {
  8103   Lisp_Object handler;
  8104   Lisp_Object encoded_file;
  8105   Lisp_Object operation;
  8106 
  8107   operation = Qdelete_file;
  8108   if (!NILP (Ffile_directory_p (filename))
  8109       && NILP (Ffile_symlink_p (filename)))
  8110     {
  8111       operation = intern ("delete-directory");
  8112       filename = Fdirectory_file_name (filename);
  8113     }
  8114 
  8115   /* Must have fully qualified file names for moving files to Recycle
  8116      Bin. */
  8117   filename = Fexpand_file_name (filename, Qnil);
  8118 
  8119   handler = Ffind_file_name_handler (filename, operation);
  8120   if (!NILP (handler))
  8121     return call2 (handler, operation, filename);
  8122   else
  8123     {
  8124       const char * path;
  8125       int result;
  8126 
  8127       encoded_file = ENCODE_FILE (filename);
  8128 
  8129       path = map_w32_filename (SSDATA (encoded_file), NULL);
  8130 
  8131       /* The Unicode version of SHFileOperation is not supported on
  8132          Windows 9X. */
  8133       if (w32_unicode_filenames && os_subtype != OS_SUBTYPE_9X)
  8134         {
  8135           SHFILEOPSTRUCTW file_op_w;
  8136           /* We need one more element beyond MAX_PATH because this is
  8137              a list of file names, with the last element double-null
  8138              terminated. */
  8139           wchar_t tmp_path_w[MAX_PATH + 1];
  8140 
  8141           memset (tmp_path_w, 0, sizeof (tmp_path_w));
  8142           filename_to_utf16 (path, tmp_path_w);
  8143 
  8144           /* On Windows, write permission is required to delete/move files.  */
  8145           _wchmod (tmp_path_w, 0666);
  8146 
  8147           memset (&file_op_w, 0, sizeof (file_op_w));
  8148           file_op_w.hwnd = HWND_DESKTOP;
  8149           file_op_w.wFunc = FO_DELETE;
  8150           file_op_w.pFrom = tmp_path_w;
  8151           file_op_w.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
  8152             | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
  8153           file_op_w.fAnyOperationsAborted = FALSE;
  8154 
  8155           result = SHFileOperationW (&file_op_w);
  8156         }
  8157       else
  8158         {
  8159           SHFILEOPSTRUCTA file_op_a;
  8160           char tmp_path_a[MAX_PATH + 1];
  8161 
  8162           memset (tmp_path_a, 0, sizeof (tmp_path_a));
  8163           filename_to_ansi (path, tmp_path_a);
  8164 
  8165           /* If a file cannot be represented in ANSI codepage, don't
  8166              let them inadvertently delete other files because some
  8167              characters are interpreted as a wildcards.  */
  8168           if (_mbspbrk ((unsigned char *)tmp_path_a,
  8169                         (const unsigned char *)"?*"))
  8170             result = ERROR_FILE_NOT_FOUND;
  8171           else
  8172             {
  8173               _chmod (tmp_path_a, 0666);
  8174 
  8175               memset (&file_op_a, 0, sizeof (file_op_a));
  8176               file_op_a.hwnd = HWND_DESKTOP;
  8177               file_op_a.wFunc = FO_DELETE;
  8178               file_op_a.pFrom = tmp_path_a;
  8179               file_op_a.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
  8180                 | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
  8181               file_op_a.fAnyOperationsAborted = FALSE;
  8182 
  8183               result = SHFileOperationA (&file_op_a);
  8184             }
  8185         }
  8186       if (result != 0)
  8187         report_file_error ("Removing old name", list1 (filename));
  8188     }
  8189   return Qnil;
  8190 }
  8191 
  8192 #endif /* WINDOWSNT */
  8193 
  8194 
  8195 /***********************************************************************
  8196                          w32 specialized functions
  8197  ***********************************************************************/
  8198 
  8199 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
  8200        Sw32_send_sys_command, 1, 2, 0,
  8201        doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
  8202 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
  8203 to minimize), #xf120 to restore frame to original size, and #xf100
  8204 to activate the menubar for keyboard access.  #xf140 activates the
  8205 screen saver if defined.
  8206 
  8207 If optional parameter FRAME is not specified, use selected frame.  */)
  8208   (Lisp_Object command, Lisp_Object frame)
  8209 {
  8210   struct frame *f = decode_window_system_frame (frame);
  8211 
  8212   CHECK_FIXNUM (command);
  8213 
  8214   if (FRAME_W32_P (f))
  8215     PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XFIXNUM (command), 0);
  8216 
  8217   return Qnil;
  8218 }
  8219 
  8220 DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
  8221        doc: /* Get Windows to perform OPERATION on DOCUMENT.
  8222 This is a wrapper around the ShellExecute system function, which
  8223 invokes the application registered to handle OPERATION for DOCUMENT.
  8224 
  8225 OPERATION is either nil or a string that names a supported operation.
  8226 What operations can be used depends on the particular DOCUMENT and its
  8227 handler application, but typically it is one of the following common
  8228 operations:
  8229 
  8230  \"open\"    - open DOCUMENT, which could be a file, a directory, or an
  8231                executable program (application).  If it is an application,
  8232                that application is launched in the current buffer's default
  8233                directory.  Otherwise, the application associated with
  8234                DOCUMENT is launched in the buffer's default directory.
  8235  \"opennew\" - like \"open\", but instruct the application to open
  8236                DOCUMENT in a new window.
  8237  \"openas\"  - open the \"Open With\" dialog for DOCUMENT.
  8238  \"print\"   - print DOCUMENT, which must be a file.
  8239  \"printto\" - print DOCUMENT, which must be a file, to a specified printer.
  8240                The printer should be provided in PARAMETERS, see below.
  8241  \"explore\" - start the Windows Explorer on DOCUMENT.
  8242  \"edit\"    - launch an editor and open DOCUMENT for editing; which
  8243                editor is launched depends on the association for the
  8244                specified DOCUMENT.
  8245  \"find\"    - initiate search starting from DOCUMENT, which must specify
  8246                a directory.
  8247  \"delete\"  - move DOCUMENT, a file or a directory, to Recycle Bin.
  8248  \"copy\"    - copy DOCUMENT, which must be a file or a directory, into
  8249                the clipboard.
  8250  \"cut\"     - move DOCUMENT, a file or a directory, into the clipboard.
  8251  \"paste\"   - paste the file whose name is in the clipboard into DOCUMENT,
  8252                which must be a directory.
  8253  \"pastelink\"
  8254            - create a shortcut in DOCUMENT (which must be a directory)
  8255                the file or directory whose name is in the clipboard.
  8256  \"runas\"   - run DOCUMENT, which must be an executable file, with
  8257                elevated privileges (a.k.a. \"as Administrator\").
  8258  \"properties\"
  8259            - open the property sheet dialog for DOCUMENT.
  8260  nil       - invoke the default OPERATION, or \"open\" if default is
  8261                not defined or unavailable.
  8262 
  8263 DOCUMENT is typically the name of a document file or a URL, but can
  8264 also be an executable program to run, or a directory to open in the
  8265 Windows Explorer.  If it is a file or a directory, it must be a local
  8266 one; this function does not support remote file names.
  8267 
  8268 If DOCUMENT is an executable program, the optional third arg PARAMETERS
  8269 can be a string containing command line parameters, separated by blanks,
  8270 that will be passed to the program.  Some values of OPERATION also require
  8271 parameters (e.g., \"printto\" requires the printer address).  Otherwise,
  8272 PARAMETERS should be nil or unspecified.  Note that double quote characters
  8273 in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\".
  8274 
  8275 Optional fourth argument SHOW-FLAG can be used to control how the
  8276 application will be displayed when it is invoked.  If SHOW-FLAG is nil
  8277 or unspecified, the application is displayed as if SHOW-FLAG of 10 was
  8278 specified, otherwise it is an integer between 0 and 11 representing
  8279 a ShowWindow flag:
  8280 
  8281   0 - start hidden
  8282   1 - start as normal-size window
  8283   3 - start in a maximized window
  8284   6 - start in a minimized window
  8285  10 - start as the application itself specifies; this is the default.  */)
  8286   (Lisp_Object operation, Lisp_Object document, Lisp_Object parameters, Lisp_Object show_flag)
  8287 {
  8288   char *errstr;
  8289   Lisp_Object current_dir = BVAR (current_buffer, directory);;
  8290   wchar_t *doc_w = NULL, *params_w = NULL, *ops_w = NULL;
  8291 #ifdef CYGWIN
  8292   intptr_t result;
  8293 #else
  8294   int use_unicode = w32_unicode_filenames;
  8295   char *doc_a = NULL, *params_a = NULL, *ops_a = NULL;
  8296   Lisp_Object absdoc, handler;
  8297   BOOL success;
  8298 #endif
  8299 
  8300   CHECK_STRING (document);
  8301 
  8302 #ifdef CYGWIN
  8303   current_dir = Fcygwin_convert_file_name_to_windows (current_dir, Qt);
  8304   document = Fcygwin_convert_file_name_to_windows (document, Qt);
  8305 
  8306   /* Encode filename, current directory and parameters.  */
  8307   current_dir = GUI_ENCODE_FILE (current_dir);
  8308   document = GUI_ENCODE_FILE (document);
  8309   if (STRINGP (parameters))
  8310     {
  8311       parameters = GUI_ENCODE_SYSTEM (parameters);
  8312       params_w = GUI_SDATA (parameters);
  8313     }
  8314   if (STRINGP (operation))
  8315     {
  8316       operation = GUI_ENCODE_SYSTEM (operation);
  8317       ops_w = GUI_SDATA (operation);
  8318     }
  8319   doc_w = GUI_SDATA (document);
  8320   result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
  8321                                      GUI_SDATA (current_dir),
  8322                                      (FIXNUMP (show_flag)
  8323                                       ? XFIXNUM (show_flag) : SW_SHOWDEFAULT));
  8324 
  8325   if (result > 32)
  8326     return Qt;
  8327 
  8328   switch (result)
  8329     {
  8330     case SE_ERR_ACCESSDENIED:
  8331       errstr = w32_strerror (ERROR_ACCESS_DENIED);
  8332       break;
  8333     case SE_ERR_ASSOCINCOMPLETE:
  8334     case SE_ERR_NOASSOC:
  8335       errstr = w32_strerror (ERROR_NO_ASSOCIATION);
  8336       break;
  8337     case SE_ERR_DDEBUSY:
  8338     case SE_ERR_DDEFAIL:
  8339       errstr = w32_strerror (ERROR_DDE_FAIL);
  8340       break;
  8341     case SE_ERR_DDETIMEOUT:
  8342       errstr = w32_strerror (ERROR_TIMEOUT);
  8343       break;
  8344     case SE_ERR_DLLNOTFOUND:
  8345       errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
  8346       break;
  8347     case SE_ERR_FNF:
  8348       errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
  8349       break;
  8350     case SE_ERR_OOM:
  8351       errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
  8352       break;
  8353     case SE_ERR_PNF:
  8354       errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
  8355       break;
  8356     case SE_ERR_SHARE:
  8357       errstr = w32_strerror (ERROR_SHARING_VIOLATION);
  8358       break;
  8359     default:
  8360       errstr = w32_strerror (0);
  8361       break;
  8362     }
  8363 
  8364 #else  /* !CYGWIN */
  8365 
  8366   const char file_url_str[] = "file:///";
  8367   const int file_url_len = sizeof (file_url_str) - 1;
  8368   int doclen;
  8369 
  8370   if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
  8371     {
  8372       /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
  8373          start a thread in some rare system configurations, for
  8374          unknown reasons.  That thread is started in the context of
  8375          the Emacs process, but out of control of our code, and seems
  8376          to never exit afterwards.  Each such thread reserves 8MB of
  8377          stack space (because that's the value recorded in the Emacs
  8378          executable at link time: Emacs needs a large stack).  So a
  8379          large enough number of invocations of w32-shell-execute can
  8380          potentially cause the Emacs process to run out of available
  8381          address space, which is nasty.  To work around this, we
  8382          convert such URLs to local file names, which seems to prevent
  8383          those threads from starting.  See bug #20220.  */
  8384       char *p = SSDATA (document) + file_url_len;
  8385 
  8386       if (c_isalpha (*p) && p[1] == ':' && IS_DIRECTORY_SEP (p[2]))
  8387         document = Fsubstring_no_properties (document,
  8388                                              make_fixnum (file_url_len), Qnil);
  8389     }
  8390   /* We have a situation here.  If DOCUMENT is a relative file name,
  8391      but its name includes leading directories, i.e. it lives not in
  8392      CURRENT_DIR, but in its subdirectory, then ShellExecute below
  8393      will fail to find it.  So we need to make the file name is
  8394      absolute.  But DOCUMENT does not have to be a file, it can be a
  8395      URL, for example.  So we make it absolute only if it is an
  8396      existing file; if it is a file that does not exist, tough.  */
  8397   absdoc = Fexpand_file_name (document, Qnil);
  8398   /* Don't call file name handlers for file-exists-p, since they might
  8399      attempt to access the file, which could fail or produce undesired
  8400      consequences, see bug#16558 for an example.  */
  8401   handler = Ffind_file_name_handler (absdoc, Qfile_exists_p);
  8402   if (NILP (handler))
  8403     {
  8404       Lisp_Object absdoc_encoded = Fcopy_sequence (ENCODE_FILE (absdoc));
  8405 
  8406       if (faccessat (AT_FDCWD, SSDATA (absdoc_encoded), F_OK, AT_EACCESS) == 0)
  8407         {
  8408           /* ShellExecute fails if DOCUMENT is a UNC with forward
  8409              slashes (expand-file-name above converts all backslashes
  8410              to forward slashes).  Now that we know DOCUMENT is a
  8411              file, we can mirror all forward slashes into backslashes.  */
  8412           unixtodos_filename (SSDATA (absdoc_encoded));
  8413           document = absdoc_encoded;
  8414         }
  8415       else
  8416         document = ENCODE_FILE (document);
  8417     }
  8418   else
  8419     document = ENCODE_FILE (document);
  8420 
  8421   current_dir = ENCODE_FILE (current_dir);
  8422   /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could
  8423      be a URL that is not limited to MAX_PATH characters.  */
  8424   doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  8425                                  SSDATA (document), -1, NULL, 0);
  8426   doc_w = xmalloc (doclen * sizeof (wchar_t));
  8427   pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
  8428                         SSDATA (document), -1, doc_w, doclen);
  8429   if (use_unicode)
  8430     {
  8431       wchar_t current_dir_w[MAX_PATH];
  8432       SHELLEXECUTEINFOW shexinfo_w;
  8433 
  8434       /* Encode the current directory and parameters, and convert
  8435          operation to UTF-16.  */
  8436       filename_to_utf16 (SSDATA (current_dir), current_dir_w);
  8437       if (STRINGP (parameters))
  8438         {
  8439           int len;
  8440 
  8441           parameters = ENCODE_SYSTEM (parameters);
  8442           len = pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags,
  8443                                       SSDATA (parameters), -1, NULL, 0);
  8444           if (len > 32768)
  8445             len = 32768;
  8446           params_w = alloca (len * sizeof (wchar_t));
  8447           pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags,
  8448                                 SSDATA (parameters), -1, params_w, len);
  8449           params_w[len - 1] = 0;
  8450         }
  8451       if (STRINGP (operation))
  8452         {
  8453           /* Assume OPERATION is pure ASCII.  */
  8454           const char *s = SSDATA (operation);
  8455           wchar_t *d;
  8456           int len = SBYTES (operation) + 1;
  8457 
  8458           if (len > 32768)
  8459             len = 32768;
  8460           d = ops_w = alloca (len * sizeof (wchar_t));
  8461           while (d < ops_w + len - 1)
  8462             *d++ = *s++;
  8463           *d = 0;
  8464         }
  8465 
  8466       /* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST
  8467          flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is
  8468          able to invoke verbs from shortcut menu extensions, not just
  8469          static verbs listed in the Registry.  */
  8470       memset (&shexinfo_w, 0, sizeof (shexinfo_w));
  8471       shexinfo_w.cbSize = sizeof (shexinfo_w);
  8472       shexinfo_w.fMask =
  8473         SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
  8474       shexinfo_w.hwnd = NULL;
  8475       shexinfo_w.lpVerb = ops_w;
  8476       shexinfo_w.lpFile = doc_w;
  8477       shexinfo_w.lpParameters = params_w;
  8478       shexinfo_w.lpDirectory = current_dir_w;
  8479       shexinfo_w.nShow =
  8480         (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
  8481       success = ShellExecuteExW (&shexinfo_w);
  8482       xfree (doc_w);
  8483     }
  8484   else
  8485     {
  8486       char current_dir_a[MAX_PATH];
  8487       SHELLEXECUTEINFOA shexinfo_a;
  8488       int codepage = codepage_for_filenames (NULL);
  8489       int ldoc_a = pWideCharToMultiByte (codepage, 0, doc_w, -1, NULL, 0,
  8490                                          NULL, NULL);
  8491 
  8492       doc_a = xmalloc (ldoc_a);
  8493       pWideCharToMultiByte (codepage, 0, doc_w, -1, doc_a, ldoc_a, NULL, NULL);
  8494       filename_to_ansi (SSDATA (current_dir), current_dir_a);
  8495       if (STRINGP (parameters))
  8496         {
  8497           parameters = ENCODE_SYSTEM (parameters);
  8498           params_a = SSDATA (parameters);
  8499         }
  8500       if (STRINGP (operation))
  8501         {
  8502           /* Assume OPERATION is pure ASCII.  */
  8503           ops_a = SSDATA (operation);
  8504         }
  8505       memset (&shexinfo_a, 0, sizeof (shexinfo_a));
  8506       shexinfo_a.cbSize = sizeof (shexinfo_a);
  8507       shexinfo_a.fMask =
  8508         SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
  8509       shexinfo_a.hwnd = NULL;
  8510       shexinfo_a.lpVerb = ops_a;
  8511       shexinfo_a.lpFile = doc_a;
  8512       shexinfo_a.lpParameters = params_a;
  8513       shexinfo_a.lpDirectory = current_dir_a;
  8514       shexinfo_a.nShow =
  8515         (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
  8516       success = ShellExecuteExA (&shexinfo_a);
  8517       xfree (doc_w);
  8518       xfree (doc_a);
  8519     }
  8520 
  8521   if (success)
  8522     return Qt;
  8523 
  8524   errstr = w32_strerror (0);
  8525 
  8526 #endif /* !CYGWIN */
  8527 
  8528   /* The error string might be encoded in the locale's encoding.  */
  8529   if (!NILP (Vlocale_coding_system))
  8530     {
  8531       Lisp_Object decoded =
  8532         code_convert_string_norecord (build_unibyte_string (errstr),
  8533                                       Vlocale_coding_system, 0);
  8534       errstr = SSDATA (decoded);
  8535     }
  8536   error ("ShellExecute failed: %s", errstr);
  8537 }
  8538 
  8539 /* Lookup virtual keycode from string representing the name of a
  8540    non-ascii keystroke into the corresponding virtual key, using
  8541    lispy_function_keys.  */
  8542 static int
  8543 lookup_vk_code (char *key)
  8544 {
  8545   int i;
  8546 
  8547   for (i = 0; i < 256; i++)
  8548     if (lispy_function_keys[i]
  8549         && strcmp (lispy_function_keys[i], key) == 0)
  8550       return i;
  8551 
  8552   if (w32_kbdhook_active)
  8553     {
  8554       /* Alphanumerics map to themselves.  */
  8555       if (key[1] == 0)
  8556       {
  8557         if ((key[0] >= 'A' && key[0] <= 'Z')
  8558             || (key[0] >= '0' && key[0] <= '9'))
  8559           return key[0];
  8560         if (key[0] >= 'a' && key[0] <= 'z')
  8561           return toupper(key[0]);
  8562       }
  8563     }
  8564 
  8565   return -1;
  8566 }
  8567 
  8568 /* Convert a one-element vector style key sequence to a hot key
  8569    definition.  */
  8570 static Lisp_Object
  8571 w32_parse_and_hook_hot_key (Lisp_Object key, int hook)
  8572 {
  8573   /* Copied from Fdefine_key and store_in_keymap.  */
  8574   register Lisp_Object c;
  8575   int vk_code = 0;
  8576   int lisp_modifiers = 0;
  8577   int w32_modifiers;
  8578   Lisp_Object res = Qnil;
  8579   char* vkname;
  8580 
  8581   CHECK_VECTOR (key);
  8582 
  8583   if (ASIZE (key) != 1)
  8584     return Qnil;
  8585 
  8586   c = AREF (key, 0);
  8587 
  8588   if (CONSP (c) && lucid_event_type_list_p (c))
  8589     c = Fevent_convert_list (c);
  8590 
  8591   if (! FIXNUMP (c) && ! SYMBOLP (c))
  8592     error ("Key definition is invalid");
  8593 
  8594   /* Work out the base key and the modifiers.  */
  8595   if (SYMBOLP (c))
  8596     {
  8597       c = parse_modifiers (c);
  8598       lisp_modifiers = XFIXNUM (Fcar (Fcdr (c)));
  8599       c = Fcar (c);
  8600       if (!SYMBOLP (c))
  8601         emacs_abort ();
  8602       vkname = SSDATA (SYMBOL_NAME (c));
  8603       /* [s-], [M-], [h-]: Register all keys for this modifier */
  8604       if (w32_kbdhook_active && vkname[0] == 0)
  8605         vk_code = VK_ANY;
  8606       else
  8607         vk_code = lookup_vk_code (vkname);
  8608     }
  8609   else if (FIXNUMP (c))
  8610     {
  8611       lisp_modifiers = XFIXNUM (c) & ~CHARACTERBITS;
  8612       /* Many ascii characters are their own virtual key code.  */
  8613       vk_code = XFIXNUM (c) & CHARACTERBITS;
  8614     }
  8615 
  8616   if (vk_code < 0 || vk_code > 255)
  8617     return Qnil;
  8618 
  8619   if ((lisp_modifiers & meta_modifier) != 0
  8620       && !NILP (Vw32_alt_is_meta))
  8621     lisp_modifiers |= alt_modifier;
  8622 
  8623   /* Supply defs missing from mingw32.  */
  8624 #ifndef MOD_ALT
  8625 #define MOD_ALT         0x0001
  8626 #define MOD_CONTROL     0x0002
  8627 #define MOD_SHIFT       0x0004
  8628 #define MOD_WIN         0x0008
  8629 #endif
  8630 
  8631   if (w32_kbdhook_active)
  8632     {
  8633       /* Register Alt-x combinations.  */
  8634       if (lisp_modifiers & alt_modifier)
  8635         {
  8636           hook_w32_key (hook, VK_MENU, vk_code);
  8637           res = Qt;
  8638         }
  8639       /* Register Win-x combinations based on modifier mappings.  */
  8640       if (((lisp_modifiers & hyper_modifier)
  8641            && EQ (Vw32_lwindow_modifier, Qhyper))
  8642           || ((lisp_modifiers & super_modifier)
  8643               && EQ (Vw32_lwindow_modifier, Qsuper)))
  8644         {
  8645           hook_w32_key (hook, VK_LWIN, vk_code);
  8646           res = Qt;
  8647         }
  8648       if (((lisp_modifiers & hyper_modifier)
  8649            && EQ (Vw32_rwindow_modifier, Qhyper))
  8650           || ((lisp_modifiers & super_modifier)
  8651               && EQ (Vw32_rwindow_modifier, Qsuper)))
  8652         {
  8653           hook_w32_key (hook, VK_RWIN, vk_code);
  8654           res = Qt;
  8655         }
  8656       return res;
  8657     }
  8658   else
  8659     {
  8660       /* Convert lisp modifiers to Windows hot-key form.  */
  8661       w32_modifiers  = (lisp_modifiers & hyper_modifier)    ? MOD_WIN : 0;
  8662       w32_modifiers |= (lisp_modifiers & alt_modifier)      ? MOD_ALT : 0;
  8663       w32_modifiers |= (lisp_modifiers & ctrl_modifier)     ? MOD_CONTROL : 0;
  8664       w32_modifiers |= (lisp_modifiers & shift_modifier)    ? MOD_SHIFT : 0;
  8665 
  8666       return HOTKEY (vk_code, w32_modifiers);
  8667     }
  8668 }
  8669 
  8670 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
  8671        Sw32_register_hot_key, 1, 1, 0,
  8672        doc: /* Register KEY as a hot-key combination.
  8673 Certain key combinations like Alt-Tab and Win-R are reserved for
  8674 system use on Windows, and therefore are normally intercepted by the
  8675 system.  These key combinations can be used in Emacs by registering
  8676 them as hot-keys, except for Win-L which always locks the computer.
  8677 
  8678 On Windows 98 and ME, KEY must be a one element key definition in
  8679 vector form that would be acceptable to `define-key' (e.g. [A-tab] for
  8680 Alt-Tab).  The meta modifier is interpreted as Alt if
  8681 `w32-alt-is-meta' is t, and hyper is always interpreted as the Windows
  8682 modifier keys.  The return value is the hotkey-id if registered,
  8683 otherwise nil.
  8684 
  8685 On Windows versions since NT, KEY can also be specified as just a
  8686 modifier key, [M-], [s-] or [H-], to indicate that all combinations
  8687 of the respective modifier key should be processed by Emacs instead
  8688 of the operating system.  The super and hyper modifiers are
  8689 interpreted according to the current values of `w32-lwindow-modifier'
  8690 and `w32-rwindow-modifier'.  For instance, setting `w32-lwindow-modifier'
  8691 to `super' and then calling `(w32-register-hot-key [s-])' grabs all
  8692 combinations of the left Windows key to Emacs as keys with the Super
  8693 modifier, but leaves the right Windows key free for the operating
  8694 system keyboard shortcuts.
  8695 
  8696 The return value is t if the call affected any key combinations,
  8697 otherwise nil.  */)
  8698   (Lisp_Object key)
  8699 {
  8700   key = w32_parse_and_hook_hot_key (key, 1);
  8701 
  8702   if (!w32_kbdhook_active
  8703       && !NILP (key) && NILP (Fmemq (key, w32_grabbed_keys)))
  8704     {
  8705       /* Reuse an empty slot if possible.  */
  8706       Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
  8707 
  8708       /* Safe to add new key to list, even if we have focus.  */
  8709       if (NILP (item))
  8710         w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
  8711       else
  8712         XSETCAR (item, key);
  8713 
  8714       /* Notify input thread about new hot-key definition, so that it
  8715          takes effect without needing to switch focus.  */
  8716       PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
  8717                          (WPARAM) XFIXNUM (key), 0);
  8718     }
  8719 
  8720   return key;
  8721 }
  8722 
  8723 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
  8724        Sw32_unregister_hot_key, 1, 1, 0,
  8725        doc: /* Unregister KEY as a hot-key combination.  */)
  8726   (Lisp_Object key)
  8727 {
  8728   Lisp_Object item;
  8729 
  8730   if (!FIXNUMP (key))
  8731     key = w32_parse_and_hook_hot_key (key, 0);
  8732 
  8733   if (w32_kbdhook_active)
  8734     return key;
  8735 
  8736   item = Fmemq (key, w32_grabbed_keys);
  8737 
  8738   if (!NILP (item))
  8739     {
  8740       LPARAM lparam;
  8741 
  8742       eassert (CONSP (item));
  8743       /* Pass the tail of the list as a pointer to a Lisp_Cons cell,
  8744          so that it works in a --with-wide-int build as well.  */
  8745       lparam = (LPARAM) XUNTAG (item, Lisp_Cons, struct Lisp_Cons);
  8746 
  8747       /* Notify input thread about hot-key definition being removed, so
  8748          that it takes effect without needing focus switch.  */
  8749       if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
  8750                              (WPARAM) XFIXNUM (XCAR (item)), lparam))
  8751         {
  8752           MSG msg;
  8753           GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
  8754         }
  8755       return Qt;
  8756     }
  8757   return Qnil;
  8758 }
  8759 
  8760 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
  8761        Sw32_registered_hot_keys, 0, 0, 0,
  8762        doc: /* Return list of registered hot-key IDs.  */)
  8763   (void)
  8764 {
  8765   return Fdelq (Qnil, Fcopy_sequence (w32_grabbed_keys));
  8766 }
  8767 
  8768 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
  8769        Sw32_reconstruct_hot_key, 1, 1, 0,
  8770        doc: /* Convert hot-key ID to a lisp key combination.
  8771 usage: (w32-reconstruct-hot-key ID)  */)
  8772   (Lisp_Object hotkeyid)
  8773 {
  8774   int vk_code, w32_modifiers;
  8775   Lisp_Object key;
  8776 
  8777   CHECK_FIXNUM (hotkeyid);
  8778 
  8779   vk_code = HOTKEY_VK_CODE (hotkeyid);
  8780   w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
  8781 
  8782   if (vk_code < 256 && lispy_function_keys[vk_code])
  8783     key = intern (lispy_function_keys[vk_code]);
  8784   else
  8785     key = make_fixnum (vk_code);
  8786 
  8787   key = Fcons (key, Qnil);
  8788   if (w32_modifiers & MOD_SHIFT)
  8789     key = Fcons (Qshift, key);
  8790   if (w32_modifiers & MOD_CONTROL)
  8791     key = Fcons (Qctrl, key);
  8792   if (w32_modifiers & MOD_ALT)
  8793     key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
  8794   if (w32_modifiers & MOD_WIN)
  8795     key = Fcons (Qhyper, key);
  8796 
  8797   return key;
  8798 }
  8799 
  8800 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
  8801        Sw32_toggle_lock_key, 1, 2, 0,
  8802        doc: /* Toggle the state of the lock key KEY.
  8803 KEY can be `capslock', `kp-numlock', or `scroll'.
  8804 If the optional parameter NEW-STATE is a number, then the state of KEY
  8805 is set to off if the low bit of NEW-STATE is zero, otherwise on.
  8806 If NEW-STATE is omitted or nil, the function toggles the state,
  8807 
  8808 Value is the new state of the key, or nil if the function failed
  8809 to change the state.  */)
  8810   (Lisp_Object key, Lisp_Object new_state)
  8811 {
  8812   int vk_code;
  8813   LPARAM lparam;
  8814 
  8815   if (EQ (key, intern ("capslock")))
  8816     vk_code = VK_CAPITAL;
  8817   else if (EQ (key, intern ("kp-numlock")))
  8818     vk_code = VK_NUMLOCK;
  8819   else if (EQ (key, intern ("scroll")))
  8820     vk_code = VK_SCROLL;
  8821   else
  8822     return Qnil;
  8823 
  8824   if (!dwWindowsThreadId)
  8825     return make_fixnum (w32_console_toggle_lock_key (vk_code, new_state));
  8826 
  8827   if (NILP (new_state))
  8828     lparam = -1;
  8829   else
  8830     lparam = (XUFIXNUM (new_state)) & 1;
  8831   if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
  8832                          (WPARAM) vk_code, lparam))
  8833     {
  8834       MSG msg;
  8835       GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
  8836       return make_fixnum (msg.wParam);
  8837     }
  8838   return Qnil;
  8839 }
  8840 
  8841 DEFUN ("w32-window-exists-p", Fw32_window_exists_p, Sw32_window_exists_p,
  8842        2, 2, 0,
  8843        doc: /* Return non-nil if a window exists with the specified CLASS and NAME.
  8844 
  8845 This is a direct interface to the Windows API FindWindow function.  */)
  8846   (Lisp_Object class, Lisp_Object name)
  8847 {
  8848   HWND hnd;
  8849 
  8850   if (!NILP (class))
  8851     CHECK_STRING (class);
  8852   if (!NILP (name))
  8853     CHECK_STRING (name);
  8854 
  8855   hnd = FindWindow (STRINGP (class) ? ((LPCTSTR) SDATA (class)) : NULL,
  8856                     STRINGP (name)  ? ((LPCTSTR) SDATA (name))  : NULL);
  8857   if (!hnd)
  8858     return Qnil;
  8859   return Qt;
  8860 }
  8861 
  8862 DEFUN ("w32-frame-geometry", Fw32_frame_geometry, Sw32_frame_geometry, 0, 1, 0,
  8863        doc: /* Return geometric attributes of FRAME.
  8864 FRAME must be a live frame and defaults to the selected one.  The return
  8865 value is an association list of the attributes listed below.  All height
  8866 and width values are in pixels.
  8867 
  8868 `outer-position' is a cons of the outer left and top edges of FRAME
  8869   relative to the origin - the position (0, 0) - of FRAME's display.
  8870 
  8871 `outer-size' is a cons of the outer width and height of FRAME.  The
  8872   outer size includes the title bar and the external borders as well as
  8873   any menu and/or tool bar of frame.
  8874 
  8875 `external-border-size' is a cons of the horizontal and vertical width of
  8876   FRAME's external borders as supplied by the window manager.
  8877 
  8878 `title-bar-size' is a cons of the width and height of the title bar of
  8879   FRAME as supplied by the window manager.  If both of them are zero,
  8880   FRAME has no title bar.  If only the width is zero, Emacs was not
  8881   able to retrieve the width information.
  8882 
  8883 `menu-bar-external', if non-nil, means the menu bar is external (never
  8884   included in the inner edges of FRAME).
  8885 
  8886 `menu-bar-size' is a cons of the width and height of the menu bar of
  8887   FRAME.
  8888 
  8889 `tab-bar-size' is a cons of the width and height of the tab bar of
  8890   FRAME.
  8891 
  8892 `tool-bar-external', if non-nil, means the tool bar is external (never
  8893   included in the inner edges of FRAME).
  8894 
  8895 `tool-bar-position' tells on which side the tool bar on FRAME is and can
  8896   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
  8897   has no tool bar.
  8898 
  8899 `tool-bar-size' is a cons of the width and height of the tool bar of
  8900   FRAME.
  8901 
  8902 `internal-border-width' is the width of the internal border of
  8903   FRAME.  */)
  8904   (Lisp_Object frame)
  8905 {
  8906   struct frame *f = decode_live_frame (frame);
  8907 
  8908   MENUBARINFO menu_bar;
  8909   WINDOWINFO window;
  8910   int left, top, right, bottom;
  8911   unsigned int external_border_width, external_border_height;
  8912   int title_bar_width = 0, title_bar_height = 0;
  8913   int single_menu_bar_height, wrapped_menu_bar_height, menu_bar_height;
  8914   int tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
  8915   int tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
  8916   int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
  8917 
  8918   if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
  8919     return Qnil;
  8920 
  8921   block_input ();
  8922   /* Outer rectangle and borders.  */
  8923   window.cbSize = sizeof (window);
  8924   GetWindowInfo (FRAME_W32_WINDOW (f), &window);
  8925   external_border_width = window.cxWindowBorders;
  8926   external_border_height = window.cyWindowBorders;
  8927   /* Title bar.  */
  8928   if (get_title_bar_info_fn)
  8929     {
  8930       TITLEBAR_INFO title_bar;
  8931 
  8932       title_bar.cbSize = sizeof (title_bar);
  8933       title_bar.rcTitleBar.left = title_bar.rcTitleBar.right = 0;
  8934       title_bar.rcTitleBar.top = title_bar.rcTitleBar.bottom = 0;
  8935       for (int i = 0; i < 6; i++)
  8936         title_bar.rgstate[i] = 0;
  8937       if (get_title_bar_info_fn (FRAME_W32_WINDOW (f), &title_bar)
  8938           && !(title_bar.rgstate[0] & 0x00008001))
  8939         {
  8940           title_bar_width
  8941             = title_bar.rcTitleBar.right - title_bar.rcTitleBar.left;
  8942           title_bar_height
  8943             = title_bar.rcTitleBar.bottom - title_bar.rcTitleBar.top;
  8944         }
  8945     }
  8946   else if ((window.dwStyle & WS_CAPTION) == WS_CAPTION)
  8947     title_bar_height = GetSystemMetrics (SM_CYCAPTION);
  8948   /* Menu bar.  */
  8949   menu_bar.cbSize = sizeof (menu_bar);
  8950   menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
  8951   menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
  8952   GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
  8953   single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
  8954   wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
  8955   unblock_input ();
  8956 
  8957   left = window.rcWindow.left;
  8958   top = window.rcWindow.top;
  8959   right = window.rcWindow.right;
  8960   bottom = window.rcWindow.bottom;
  8961 
  8962   /* Menu bar.  */
  8963   menu_bar_height = menu_bar.rcBar.bottom - menu_bar.rcBar.top;
  8964   /* Fix menu bar height reported by GetMenuBarInfo.  */
  8965   if (menu_bar_height > single_menu_bar_height)
  8966     /* A wrapped menu bar.  */
  8967     menu_bar_height += single_menu_bar_height - wrapped_menu_bar_height;
  8968   else if (menu_bar_height > 0)
  8969     /* A single line menu bar.  */
  8970     menu_bar_height = single_menu_bar_height;
  8971 
  8972   return  list (Fcons (Qouter_position,
  8973                        Fcons (make_fixnum (left), make_fixnum (top))),
  8974                 Fcons (Qouter_size,
  8975                        Fcons (make_fixnum (right - left),
  8976                               make_fixnum (bottom - top))),
  8977                 Fcons (Qexternal_border_size,
  8978                        Fcons (make_fixnum (external_border_width),
  8979                               make_fixnum (external_border_height))),
  8980                 Fcons (Qtitle_bar_size,
  8981                        Fcons (make_fixnum (title_bar_width),
  8982                               make_fixnum (title_bar_height))),
  8983                 Fcons (Qmenu_bar_external, Qt),
  8984                 Fcons (Qmenu_bar_size,
  8985                        Fcons (make_fixnum
  8986                               (menu_bar.rcBar.right - menu_bar.rcBar.left),
  8987                               make_fixnum (menu_bar_height))),
  8988                 Fcons (Qtab_bar_size,
  8989                        Fcons (make_fixnum
  8990                               (tab_bar_height
  8991                                ? (right - left - 2 * external_border_width
  8992                                   - 2 * internal_border_width)
  8993                                : 0),
  8994                               make_fixnum (tab_bar_height))),
  8995                 Fcons (Qtool_bar_external, Qnil),
  8996                 Fcons (Qtool_bar_position, tool_bar_height ? Qtop : Qnil),
  8997                 Fcons (Qtool_bar_size,
  8998                        Fcons (make_fixnum
  8999                               (tool_bar_height
  9000                                ? (right - left - 2 * external_border_width
  9001                                   - 2 * internal_border_width)
  9002                                : 0),
  9003                               make_fixnum (tool_bar_height))),
  9004                 Fcons (Qinternal_border_width,
  9005                        make_fixnum (internal_border_width)));
  9006 }
  9007 
  9008 DEFUN ("w32-frame-edges", Fw32_frame_edges, Sw32_frame_edges, 0, 2, 0,
  9009        doc: /* Return edge coordinates of FRAME.
  9010 FRAME must be a live frame and defaults to the selected one.  The return
  9011 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
  9012 in pixels relative to the origin - the position (0, 0) - of FRAME's
  9013 display.
  9014 
  9015 If optional argument TYPE is the symbol `outer-edges', return the outer
  9016 edges of FRAME.  The outer edges comprise the decorations of the window
  9017 manager (like the title bar or external borders) as well as any external
  9018 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
  9019 `native-edges' or nil, return the native edges of FRAME.  The native
  9020 edges exclude the decorations of the window manager and any external
  9021 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
  9022 the inner edges of FRAME.  These edges exclude title bar, any borders,
  9023 menu bar or tool bar of FRAME.  */)
  9024   (Lisp_Object frame, Lisp_Object type)
  9025 {
  9026   struct frame *f = decode_live_frame (frame);
  9027 
  9028   if (FRAME_INITIAL_P (f) || !FRAME_W32_P (f))
  9029     return Qnil;
  9030 
  9031   if (EQ (type, Qouter_edges))
  9032     {
  9033       RECT rectangle;
  9034       BOOL success = false;
  9035 
  9036       block_input ();
  9037       /* Outer frame rectangle, including outer borders and title bar. */
  9038       success = GetWindowRect (FRAME_W32_WINDOW (f), &rectangle);
  9039       unblock_input ();
  9040 
  9041       if (success)
  9042         return list4 (make_fixnum (rectangle.left),
  9043                       make_fixnum (rectangle.top),
  9044                       make_fixnum (rectangle.right),
  9045                       make_fixnum (rectangle.bottom));
  9046       else
  9047         return Qnil;
  9048     }
  9049   else
  9050     {
  9051       RECT rectangle;
  9052       POINT pt;
  9053       int left, top, right, bottom;
  9054       BOOL success;
  9055 
  9056       block_input ();
  9057       /* Inner frame rectangle, excluding borders and title bar.  */
  9058       success = GetClientRect (FRAME_W32_WINDOW (f), &rectangle);
  9059       /* Get top-left corner of native rectangle in screen
  9060          coordinates.  */
  9061       if (!success)
  9062         {
  9063           unblock_input ();
  9064           return Qnil;
  9065         }
  9066 
  9067       pt.x = 0;
  9068       pt.y = 0;
  9069       success = ClientToScreen (FRAME_W32_WINDOW (f), &pt);
  9070       unblock_input ();
  9071 
  9072       if (!success)
  9073         return Qnil;
  9074 
  9075       left = pt.x;
  9076       top = pt.y;
  9077       right = left + rectangle.right;
  9078       bottom = top + rectangle.bottom;
  9079 
  9080       if (EQ (type, Qinner_edges))
  9081         {
  9082           int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
  9083 
  9084           return list4 (make_fixnum (left + internal_border_width),
  9085                         make_fixnum (top
  9086                                      + FRAME_TAB_BAR_HEIGHT (f)
  9087                                      + FRAME_TOOL_BAR_HEIGHT (f)
  9088                                      + internal_border_width),
  9089                         make_fixnum (right - internal_border_width),
  9090                         make_fixnum (bottom - internal_border_width));
  9091         }
  9092       else
  9093         return list4 (make_fixnum (left), make_fixnum (top),
  9094                       make_fixnum (right), make_fixnum (bottom));
  9095     }
  9096 }
  9097 
  9098 /**
  9099  * w32_frame_list_z_order:
  9100  *
  9101  * Recursively add list of all frames on the display specified via
  9102  * DPYINFO and whose window-system window's parent is specified by
  9103  * WINDOW to FRAMES and return FRAMES.
  9104  */
  9105 static Lisp_Object
  9106 w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window)
  9107 {
  9108   Lisp_Object frame, frames = Qnil;
  9109 
  9110   while (window)
  9111     {
  9112       struct frame *f = w32_window_to_frame (dpyinfo, window);
  9113 
  9114       if (f)
  9115         {
  9116           XSETFRAME (frame, f);
  9117           frames = Fcons (frame, frames);
  9118         }
  9119 
  9120       block_input ();
  9121       window = GetNextWindow (window, GW_HWNDNEXT);
  9122       unblock_input ();
  9123     }
  9124 
  9125   return Fnreverse (frames);
  9126 }
  9127 
  9128 DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
  9129        Sw32_frame_list_z_order, 0, 1, 0,
  9130        doc: /* Return list of Emacs' frames, in Z (stacking) order.
  9131 The optional argument DISPLAY specifies which display to ask about.
  9132 DISPLAY should be either a frame or a display name (a string).  If
  9133 omitted or nil, that stands for the selected frame's display.
  9134 
  9135 As a special case, if DISPLAY is non-nil and specifies a live frame,
  9136 return the child frames of that frame in Z (stacking) order.
  9137 
  9138 Frames are listed from topmost (first) to bottommost (last).  */)
  9139   (Lisp_Object display)
  9140 {
  9141   struct w32_display_info *dpyinfo = check_x_display_info (display);
  9142   HWND window;
  9143 
  9144   block_input ();
  9145   if (FRAMEP (display) && FRAME_LIVE_P (XFRAME (display)))
  9146     window = GetWindow (FRAME_W32_WINDOW (XFRAME (display)), GW_CHILD);
  9147   else
  9148     window = GetTopWindow (NULL);
  9149   unblock_input ();
  9150 
  9151   return w32_frame_list_z_order (dpyinfo, window);
  9152 }
  9153 
  9154 /**
  9155  * w32_frame_restack:
  9156  *
  9157  * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil.  In
  9158  * practice this is a two-step action: The first step removes F1's
  9159  * window-system window from the display.  The second step reinserts
  9160  * F1's window below (above if ABOVE_FLAG is true) that of F2.
  9161  */
  9162 static void
  9163 w32_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
  9164 {
  9165   HWND hwnd1 = FRAME_W32_WINDOW (f1);
  9166   HWND hwnd2 = FRAME_W32_WINDOW (f2);
  9167 
  9168   block_input ();
  9169   if (above_flag)
  9170     /* Put F1 above F2 in the z-order.  */
  9171     {
  9172       if (GetNextWindow (hwnd1, GW_HWNDNEXT) != hwnd2)
  9173         {
  9174           /* Make sure F1 is below F2 first because we must not
  9175              change the relative position of F2 wrt any other
  9176              window but F1.  */
  9177           if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
  9178             SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
  9179                           SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  9180                           | SWP_FRAMECHANGED);
  9181           /* Now put F1 above F2.  */
  9182           SetWindowPos (hwnd2, hwnd1, 0, 0, 0, 0,
  9183                         SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  9184                         | SWP_FRAMECHANGED);
  9185         }
  9186     }
  9187   else if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
  9188     /* Put F1 below F2 in the z-order.  */
  9189     SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
  9190                   SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  9191                   | SWP_FRAMECHANGED);
  9192   unblock_input ();
  9193 }
  9194 
  9195 DEFUN ("w32-frame-restack", Fw32_frame_restack, Sw32_frame_restack, 2, 3, 0,
  9196        doc: /* Restack FRAME1 below FRAME2.
  9197 This means that if both frames are visible and the display areas of
  9198 these frames overlap, FRAME2 (partially) obscures FRAME1.  If optional
  9199 third argument ABOVE is non-nil, restack FRAME1 above FRAME2.  This
  9200 means that if both frames are visible and the display areas of these
  9201 frames overlap, FRAME1 (partially) obscures FRAME2.
  9202 
  9203 This may be thought of as an atomic action performed in two steps: The
  9204 first step removes FRAME1's window-system window from the display.  The
  9205 second step reinserts FRAME1's window below (above if ABOVE is true)
  9206 that of FRAME2.  Hence the position of FRAME2 in its display's Z
  9207 \(stacking) order relative to all other frames excluding FRAME1 remains
  9208 unaltered.
  9209 
  9210 Some window managers may refuse to restack windows.  */)
  9211      (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
  9212 {
  9213   struct frame *f1 = decode_live_frame (frame1);
  9214   struct frame *f2 = decode_live_frame (frame2);
  9215 
  9216   if (FRAME_W32_P (f1) && FRAME_W32_P (f2))
  9217     {
  9218       w32_frame_restack (f1, f2, !NILP (above));
  9219       return Qt;
  9220     }
  9221   else
  9222     {
  9223       error ("Cannot restack frames");
  9224       return Qnil;
  9225     }
  9226 }
  9227 
  9228 DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
  9229        Sw32_mouse_absolute_pixel_position, 0, 0, 0,
  9230        doc: /* Return absolute position of mouse cursor in pixels.
  9231 The position is returned as a cons cell (X . Y) of the coordinates of
  9232 the mouse cursor position in pixels relative to a position (0, 0) of the
  9233 selected frame's display.  */)
  9234   (void)
  9235 {
  9236   POINT pt;
  9237 
  9238   block_input ();
  9239   GetCursorPos (&pt);
  9240   unblock_input ();
  9241 
  9242   return Fcons (make_fixnum (pt.x), make_fixnum (pt.y));
  9243 }
  9244 
  9245 DEFUN ("w32-set-mouse-absolute-pixel-position", Fw32_set_mouse_absolute_pixel_position,
  9246        Sw32_set_mouse_absolute_pixel_position, 2, 2, 0,
  9247        doc: /* Move mouse pointer to absolute pixel position (X, Y).
  9248 The coordinates X and Y are interpreted in pixels relative to a position
  9249 \(0, 0) of the selected frame's display.  */)
  9250   (Lisp_Object x, Lisp_Object y)
  9251 {
  9252   UINT trail_num = 0;
  9253   BOOL ret = false;
  9254 
  9255   int xval = check_integer_range (x, INT_MIN, INT_MAX);
  9256   int yval = check_integer_range (y, INT_MIN, INT_MAX);
  9257 
  9258   block_input ();
  9259   /* When "mouse trails" are in effect, moving the mouse cursor
  9260      sometimes leaves behind an annoying "ghost" of the pointer.
  9261      Avoid that by momentarily switching off mouse trails.  */
  9262   if (os_subtype == OS_SUBTYPE_NT
  9263       && w32_major_version + w32_minor_version >= 6)
  9264     ret = SystemParametersInfo (SPI_GETMOUSETRAILS, 0, &trail_num, 0);
  9265   SetCursorPos (xval, yval);
  9266   if (ret)
  9267     SystemParametersInfo (SPI_SETMOUSETRAILS, trail_num, NULL, 0);
  9268   unblock_input ();
  9269 
  9270   return Qnil;
  9271 }
  9272 
  9273 
  9274 #ifdef WINDOWSNT
  9275 typedef BOOL (WINAPI *GetDiskFreeSpaceExW_Proc)
  9276   (LPCWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
  9277 typedef BOOL (WINAPI *GetDiskFreeSpaceExA_Proc)
  9278   (LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
  9279 
  9280 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
  9281        doc: /* SKIP: Real doc in fileio.c.  */)
  9282   (Lisp_Object filename)
  9283 {
  9284   Lisp_Object encoded, value;
  9285 
  9286   CHECK_STRING (filename);
  9287   filename = Fexpand_file_name (filename, Qnil);
  9288   encoded = ENCODE_FILE (filename);
  9289 
  9290   /* If the file name has special constructs in it,
  9291      call the corresponding file name handler.  */
  9292   Lisp_Object handler = Ffind_file_name_handler (encoded, Qfile_system_info);
  9293   if (!NILP (handler))
  9294     {
  9295       value = call2 (handler, Qfile_system_info, encoded);
  9296       if (CONSP (value) || NILP (value))
  9297         return value;
  9298       error ("Invalid handler in `file-name-handler-alist'");
  9299     }
  9300 
  9301   value = Qnil;
  9302 
  9303   /* Determining the required information on Windows turns out, sadly,
  9304      to be more involved than one would hope.  The original Windows API
  9305      call for this will return bogus information on some systems, but we
  9306      must dynamically probe for the replacement api, since that was
  9307      added rather late on.  */
  9308   {
  9309     HMODULE hKernel = GetModuleHandle ("kernel32");
  9310     GetDiskFreeSpaceExW_Proc pfn_GetDiskFreeSpaceExW =
  9311       (GetDiskFreeSpaceExW_Proc) get_proc_addr (hKernel, "GetDiskFreeSpaceExW");
  9312     GetDiskFreeSpaceExA_Proc pfn_GetDiskFreeSpaceExA =
  9313       (GetDiskFreeSpaceExA_Proc) get_proc_addr (hKernel, "GetDiskFreeSpaceExA");
  9314     bool have_pfn_GetDiskFreeSpaceEx =
  9315       ((w32_unicode_filenames && pfn_GetDiskFreeSpaceExW)
  9316        || (!w32_unicode_filenames && pfn_GetDiskFreeSpaceExA));
  9317 
  9318     /* On Windows, we may need to specify the root directory of the
  9319        volume holding FILENAME.  */
  9320     char rootname[MAX_UTF8_PATH];
  9321     wchar_t rootname_w[MAX_PATH];
  9322     char rootname_a[MAX_PATH];
  9323     char *name = SSDATA (encoded);
  9324     BOOL result;
  9325 
  9326     /* find the root name of the volume if given */
  9327     if (isalpha (name[0]) && name[1] == ':')
  9328       {
  9329         rootname[0] = name[0];
  9330         rootname[1] = name[1];
  9331         rootname[2] = '\\';
  9332         rootname[3] = 0;
  9333       }
  9334     else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
  9335       {
  9336         char *str = rootname;
  9337         int slashes = 4;
  9338         do
  9339           {
  9340             if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
  9341               break;
  9342             *str++ = *name++;
  9343           }
  9344         while ( *name );
  9345 
  9346         *str++ = '\\';
  9347         *str = 0;
  9348       }
  9349 
  9350     if (w32_unicode_filenames)
  9351       filename_to_utf16 (rootname, rootname_w);
  9352     else
  9353       filename_to_ansi (rootname, rootname_a);
  9354 
  9355     if (have_pfn_GetDiskFreeSpaceEx)
  9356       {
  9357         /* Unsigned large integers cannot be cast to double, so
  9358            use signed ones instead.  */
  9359         LARGE_INTEGER availbytes;
  9360         LARGE_INTEGER freebytes;
  9361         LARGE_INTEGER totalbytes;
  9362 
  9363         if (w32_unicode_filenames)
  9364           result = pfn_GetDiskFreeSpaceExW (rootname_w,
  9365                                             (ULARGE_INTEGER *)&availbytes,
  9366                                             (ULARGE_INTEGER *)&totalbytes,
  9367                                             (ULARGE_INTEGER *)&freebytes);
  9368         else
  9369           result = pfn_GetDiskFreeSpaceExA (rootname_a,
  9370                                             (ULARGE_INTEGER *)&availbytes,
  9371                                             (ULARGE_INTEGER *)&totalbytes,
  9372                                             (ULARGE_INTEGER *)&freebytes);
  9373         if (result)
  9374           value = list3 (make_float ((double) totalbytes.QuadPart),
  9375                          make_float ((double) freebytes.QuadPart),
  9376                          make_float ((double) availbytes.QuadPart));
  9377       }
  9378     else
  9379       {
  9380         DWORD sectors_per_cluster;
  9381         DWORD bytes_per_sector;
  9382         DWORD free_clusters;
  9383         DWORD total_clusters;
  9384 
  9385         if (w32_unicode_filenames)
  9386           result = GetDiskFreeSpaceW (rootname_w,
  9387                                       &sectors_per_cluster,
  9388                                       &bytes_per_sector,
  9389                                       &free_clusters,
  9390                                       &total_clusters);
  9391         else
  9392           result = GetDiskFreeSpaceA (rootname_a,
  9393                                       &sectors_per_cluster,
  9394                                       &bytes_per_sector,
  9395                                       &free_clusters,
  9396                                       &total_clusters);
  9397         if (result)
  9398           value = list3 (make_float ((double) total_clusters
  9399                                      * sectors_per_cluster * bytes_per_sector),
  9400                          make_float ((double) free_clusters
  9401                                      * sectors_per_cluster * bytes_per_sector),
  9402                          make_float ((double) free_clusters
  9403                                      * sectors_per_cluster * bytes_per_sector));
  9404       }
  9405   }
  9406 
  9407   return value;
  9408 }
  9409 #endif /* WINDOWSNT */
  9410 
  9411 
  9412 #ifdef WINDOWSNT
  9413 DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
  9414        0, 0, 0, doc: /* Return the name of Windows default printer device.  */)
  9415   (void)
  9416 {
  9417   static char pname_buf[2 * MAX_UTF8_PATH + 3 - 1];
  9418   int err;
  9419   HANDLE hPrn;
  9420   PRINTER_INFO_2W *ppi2w = NULL;
  9421   PRINTER_INFO_2A *ppi2a = NULL;
  9422   DWORD dwNeeded = 0, dwReturned = 0;
  9423   char server_name[MAX_UTF8_PATH], share_name[MAX_UTF8_PATH];
  9424   char port_name[MAX_UTF8_PATH];
  9425 
  9426   /* Retrieve the default string from Win.ini (the registry).
  9427    * String will be in form "printername,drivername,portname".
  9428    * This is the most portable way to get the default printer. */
  9429   if (GetProfileString ("windows", "device", ",,", pname_buf, sizeof (pname_buf)) <= 0)
  9430     return Qnil;
  9431   /* printername precedes first "," character */
  9432   strtok (pname_buf, ",");
  9433   /* We want to know more than the printer name */
  9434   if (!OpenPrinter (pname_buf, &hPrn, NULL))
  9435     return Qnil;
  9436   /* GetPrinterW is not supported by unicows.dll.  */
  9437   if (w32_unicode_filenames && os_subtype != OS_SUBTYPE_9X)
  9438     GetPrinterW (hPrn, 2, NULL, 0, &dwNeeded);
  9439   else
  9440     GetPrinterA (hPrn, 2, NULL, 0, &dwNeeded);
  9441   if (dwNeeded == 0)
  9442     {
  9443       ClosePrinter (hPrn);
  9444       return Qnil;
  9445     }
  9446   /* Call GetPrinter again with big enough memory block.  */
  9447   if (w32_unicode_filenames && os_subtype != OS_SUBTYPE_9X)
  9448     {
  9449       /* Allocate memory for the PRINTER_INFO_2 struct.  */
  9450       ppi2w = xmalloc (dwNeeded);
  9451       err = GetPrinterW (hPrn, 2, (LPBYTE)ppi2w, dwNeeded, &dwReturned);
  9452       ClosePrinter (hPrn);
  9453       if (!err)
  9454         {
  9455           xfree (ppi2w);
  9456           return Qnil;
  9457         }
  9458 
  9459       if ((ppi2w->Attributes & PRINTER_ATTRIBUTE_SHARED)
  9460           && ppi2w->pServerName)
  9461         {
  9462           filename_from_utf16 (ppi2w->pServerName, server_name);
  9463           filename_from_utf16 (ppi2w->pShareName, share_name);
  9464         }
  9465       else
  9466         {
  9467           server_name[0] = '\0';
  9468           filename_from_utf16 (ppi2w->pPortName, port_name);
  9469         }
  9470     }
  9471   else
  9472     {
  9473       ppi2a = xmalloc (dwNeeded);
  9474       err = GetPrinterA (hPrn, 2, (LPBYTE)ppi2a, dwNeeded, &dwReturned);
  9475       ClosePrinter (hPrn);
  9476       if (!err)
  9477         {
  9478           xfree (ppi2a);
  9479           return Qnil;
  9480         }
  9481 
  9482       if ((ppi2a->Attributes & PRINTER_ATTRIBUTE_SHARED)
  9483           && ppi2a->pServerName)
  9484         {
  9485           filename_from_ansi (ppi2a->pServerName, server_name);
  9486           filename_from_ansi (ppi2a->pShareName, share_name);
  9487         }
  9488       else
  9489         {
  9490           server_name[0] = '\0';
  9491           filename_from_ansi (ppi2a->pPortName, port_name);
  9492         }
  9493     }
  9494 
  9495   if (server_name[0])
  9496     {
  9497       /* a remote printer */
  9498       if (server_name[0] == '\\')
  9499         snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", server_name,
  9500                   share_name);
  9501       else
  9502         snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", server_name,
  9503                   share_name);
  9504       pname_buf[sizeof (pname_buf) - 1] = '\0';
  9505     }
  9506   else
  9507     {
  9508       /* a local printer */
  9509       strncpy (pname_buf, port_name, sizeof (pname_buf));
  9510       pname_buf[sizeof (pname_buf) - 1] = '\0';
  9511       /* `pPortName' can include several ports, delimited by ','.
  9512        * we only use the first one. */
  9513       strtok (pname_buf, ",");
  9514     }
  9515 
  9516   return DECODE_FILE (build_unibyte_string (pname_buf));
  9517 }
  9518 #endif  /* WINDOWSNT */
  9519 
  9520 
  9521 /* Equivalent of strerror for W32 error codes.  */
  9522 char *
  9523 w32_strerror (int error_no)
  9524 {
  9525   static char buf[500];
  9526   DWORD ret;
  9527 
  9528   if (error_no == 0)
  9529     error_no = GetLastError ();
  9530 
  9531   ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
  9532                        FORMAT_MESSAGE_IGNORE_INSERTS,
  9533                        NULL,
  9534                        error_no,
  9535                        0, /* choose most suitable language */
  9536                        buf, sizeof (buf), NULL);
  9537 
  9538   while (ret > 0 && (buf[ret - 1] == '\n' ||
  9539                      buf[ret - 1] == '\r' ))
  9540       --ret;
  9541   buf[ret] = '\0';
  9542   if (!ret)
  9543     sprintf (buf, "w32 error %d", error_no);
  9544 
  9545   return buf;
  9546 }
  9547 
  9548 /* For convenience when debugging.  (You cannot call GetLastError
  9549    directly from GDB: it will crash, because it uses the __stdcall
  9550    calling convention, not the _cdecl convention assumed by GDB.)  */
  9551 DWORD w32_last_error (void);
  9552 
  9553 DWORD
  9554 w32_last_error (void)
  9555 {
  9556   return GetLastError ();
  9557 }
  9558 
  9559 /* Cache information describing the NT system for later use.  */
  9560 void
  9561 cache_system_info (void)
  9562 {
  9563   union
  9564     {
  9565       struct info
  9566         {
  9567           char  major;
  9568           char  minor;
  9569           short platform;
  9570         } info;
  9571       DWORD data;
  9572     } version;
  9573 
  9574   /* Cache the module handle of Emacs itself.  */
  9575   hinst = GetModuleHandle (NULL);
  9576 
  9577   /* Cache the version of the operating system.  */
  9578   version.data = GetVersion ();
  9579   w32_major_version = version.info.major;
  9580   w32_minor_version = version.info.minor;
  9581 
  9582   if (version.info.platform & 0x8000)
  9583     os_subtype = OS_SUBTYPE_9X;
  9584   else
  9585     os_subtype = OS_SUBTYPE_NT;
  9586 
  9587   /* Cache page size, allocation unit, processor type, etc.  */
  9588   GetSystemInfo (&sysinfo_cache);
  9589   syspage_mask = (DWORD_PTR)sysinfo_cache.dwPageSize - 1;
  9590 
  9591   /* Cache os info.  */
  9592   osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  9593   GetVersionEx (&osinfo_cache);
  9594 
  9595   w32_build_number = osinfo_cache.dwBuildNumber;
  9596   if (os_subtype == OS_SUBTYPE_9X)
  9597     w32_build_number &= 0xffff;
  9598 
  9599   w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
  9600 }
  9601 
  9602 #ifdef WINDOWSNT
  9603 char *
  9604 w32_version_string (void)
  9605 {
  9606   /* NNN.NNN.NNNNNNNNNN */
  9607   static char version_string[3 + 1 + 3 + 1 + 10 + 1];
  9608   _snprintf (version_string, sizeof version_string, "%d.%d.%d",
  9609              w32_major_version, w32_minor_version, w32_build_number);
  9610   return version_string;
  9611 }
  9612 #endif
  9613 
  9614 #ifdef EMACSDEBUG
  9615 void
  9616 _DebPrint (const char *fmt, ...)
  9617 {
  9618   char buf[1024];
  9619   va_list args;
  9620 
  9621   va_start (args, fmt);
  9622   vsprintf (buf, fmt, args);
  9623   va_end (args);
  9624 #if CYGWIN
  9625   fprintf (stderr, "%s", buf);
  9626 #endif
  9627   OutputDebugString (buf);
  9628 }
  9629 #endif
  9630 
  9631 int
  9632 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
  9633 {
  9634   int cur_state = (GetKeyState (vk_code) & 1);
  9635 
  9636   if (NILP (new_state)
  9637       || (FIXNUMP (new_state)
  9638           && ((XUFIXNUM (new_state)) & 1) != cur_state))
  9639     {
  9640 #ifdef WINDOWSNT
  9641       faked_key = vk_code;
  9642 #endif /* WINDOWSNT */
  9643 
  9644       keybd_event ((BYTE) vk_code,
  9645                    (BYTE) MapVirtualKey (vk_code, 0),
  9646                    KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  9647       keybd_event ((BYTE) vk_code,
  9648                    (BYTE) MapVirtualKey (vk_code, 0),
  9649                    KEYEVENTF_EXTENDEDKEY | 0, 0);
  9650       keybd_event ((BYTE) vk_code,
  9651                    (BYTE) MapVirtualKey (vk_code, 0),
  9652                    KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  9653       cur_state = !cur_state;
  9654     }
  9655 
  9656   return cur_state;
  9657 }
  9658 
  9659 /* Translate console modifiers to emacs modifiers.
  9660    German keyboard support (Kai Morgan Zeise 2/18/95).  */
  9661 int
  9662 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
  9663 {
  9664   int retval = 0;
  9665 
  9666   /* If we recognize right-alt and left-ctrl as AltGr, and it has been
  9667      pressed, first remove those modifiers.  */
  9668   if (!NILP (Vw32_recognize_altgr)
  9669       && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
  9670       == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
  9671     mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
  9672 
  9673   if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
  9674     retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
  9675 
  9676   if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
  9677     {
  9678       retval |= ctrl_modifier;
  9679       if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
  9680           == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
  9681         retval |= meta_modifier;
  9682     }
  9683 
  9684   if (mods & LEFT_WIN_PRESSED)
  9685     retval |= w32_key_to_modifier (VK_LWIN);
  9686   if (mods & RIGHT_WIN_PRESSED)
  9687     retval |= w32_key_to_modifier (VK_RWIN);
  9688   if (mods & APPS_PRESSED)
  9689     retval |= w32_key_to_modifier (VK_APPS);
  9690   if (mods & SCROLLLOCK_ON)
  9691     retval |= w32_key_to_modifier (VK_SCROLL);
  9692 
  9693   /* Just in case someone wanted the original behavior, make it
  9694      optional by setting w32-capslock-is-shiftlock to t.  */
  9695   if (NILP (Vw32_capslock_is_shiftlock)
  9696       /* Keys that should _not_ be affected by CapsLock.  */
  9697       && (    (key == VK_BACK)
  9698            || (key == VK_TAB)
  9699            || (key == VK_CLEAR)
  9700            || (key == VK_RETURN)
  9701            || (key == VK_ESCAPE)
  9702            || ((key >= VK_SPACE) && (key <= VK_HELP))
  9703            || ((key >= VK_NUMPAD0) && (key <= VK_F24))
  9704            || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
  9705          ))
  9706     {
  9707       /* Only consider shift state.  */
  9708       if ((mods & SHIFT_PRESSED) != 0)
  9709         retval |= shift_modifier;
  9710     }
  9711   else
  9712     {
  9713       /* Ignore CapsLock state if not enabled.  */
  9714       if (NILP (Vw32_enable_caps_lock))
  9715         mods &= ~CAPSLOCK_ON;
  9716       if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
  9717         retval |= shift_modifier;
  9718     }
  9719 
  9720   return retval;
  9721 }
  9722 
  9723 /* The return code indicates key code size.  cpID is the codepage to
  9724    use for translation to Unicode; -1 means use the current console
  9725    input codepage.  */
  9726 int
  9727 w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
  9728 {
  9729   unsigned int key_code = event->wVirtualKeyCode;
  9730   unsigned int mods = event->dwControlKeyState;
  9731   BYTE keystate[256];
  9732   static BYTE ansi_code[4];
  9733   static int isdead = 0;
  9734 
  9735   if (isdead == 2)
  9736     {
  9737       event->uChar.AsciiChar = ansi_code[2];
  9738       isdead = 0;
  9739       return 1;
  9740     }
  9741   if (event->uChar.AsciiChar != 0)
  9742     return 1;
  9743 
  9744   memset (keystate, 0, sizeof (keystate));
  9745   keystate[key_code] = 0x80;
  9746   if (mods & SHIFT_PRESSED)
  9747     keystate[VK_SHIFT] = 0x80;
  9748   if (mods & CAPSLOCK_ON)
  9749     keystate[VK_CAPITAL] = 1;
  9750   /* If we recognize right-alt and left-ctrl as AltGr, set the key
  9751      states accordingly before invoking ToAscii.  */
  9752   if (!NILP (Vw32_recognize_altgr)
  9753       && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
  9754     {
  9755       keystate[VK_CONTROL] = 0x80;
  9756       keystate[VK_LCONTROL] = 0x80;
  9757       keystate[VK_MENU] = 0x80;
  9758       keystate[VK_RMENU] = 0x80;
  9759     }
  9760 
  9761 #if 0
  9762   /* Because of an OS bug, ToAscii corrupts the stack when called to
  9763      convert a dead key in console mode on NT4.  Unfortunately, trying
  9764      to check for dead keys using MapVirtualKey doesn't work either -
  9765      these functions apparently use internal information about keyboard
  9766      layout which doesn't get properly updated in console programs when
  9767      changing layout (though apparently it gets partly updated,
  9768      otherwise ToAscii wouldn't crash).  */
  9769   if (is_dead_key (event->wVirtualKeyCode))
  9770     return 0;
  9771 #endif
  9772 
  9773   /* On NT, call ToUnicode instead and then convert to the current
  9774      console input codepage.  */
  9775   if (os_subtype == OS_SUBTYPE_NT)
  9776     {
  9777       WCHAR buf[128];
  9778 
  9779       isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
  9780                           keystate, buf, 128, 0);
  9781       if (isdead > 0)
  9782         {
  9783           /* When we are called from the GUI message processing code,
  9784              we are passed the current keyboard codepage, a positive
  9785              number, to use below.  */
  9786           if (cpId == -1)
  9787             cpId = GetConsoleCP ();
  9788 
  9789           event->uChar.UnicodeChar = buf[isdead - 1];
  9790           isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
  9791                                         (LPSTR)ansi_code, 4, NULL, NULL);
  9792         }
  9793       else
  9794         isdead = 0;
  9795     }
  9796   else
  9797     {
  9798       isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
  9799                         keystate, (LPWORD) ansi_code, 0);
  9800     }
  9801 
  9802   if (isdead == 0)
  9803     return 0;
  9804   event->uChar.AsciiChar = ansi_code[0];
  9805   return isdead;
  9806 }
  9807 
  9808 
  9809 void
  9810 w32_sys_ring_bell (struct frame *f)
  9811 {
  9812   if (sound_type == 0xFFFFFFFF)
  9813     {
  9814       Beep (666, 100);
  9815     }
  9816   else if (sound_type == MB_EMACS_SILENT)
  9817     {
  9818       /* Do nothing.  */
  9819     }
  9820   else
  9821     MessageBeep (sound_type);
  9822 }
  9823 
  9824 DEFUN ("w32--menu-bar-in-use", Fw32__menu_bar_in_use, Sw32__menu_bar_in_use,
  9825        0, 0, 0,
  9826        doc: /* Return non-nil when a menu-bar menu is being used.
  9827 Internal use only.  */)
  9828   (void)
  9829 {
  9830   return menubar_in_use ? Qt : Qnil;
  9831 }
  9832 
  9833 #if defined WINDOWSNT && !defined HAVE_DBUS
  9834 
  9835 /***********************************************************************
  9836                           Tray notifications
  9837  ***********************************************************************/
  9838 /* A private struct declaration to avoid compile-time limits.  */
  9839 typedef struct MY_NOTIFYICONDATAW {
  9840   DWORD cbSize;
  9841   HWND hWnd;
  9842   UINT uID;
  9843   UINT uFlags;
  9844   UINT uCallbackMessage;
  9845   HICON hIcon;
  9846   WCHAR szTip[128];
  9847   DWORD dwState;
  9848   DWORD dwStateMask;
  9849   WCHAR szInfo[256];
  9850   _ANONYMOUS_UNION union {
  9851     UINT uTimeout;
  9852     UINT uVersion;
  9853   } DUMMYUNIONNAME;
  9854   WCHAR szInfoTitle[64];
  9855   DWORD dwInfoFlags;
  9856   GUID guidItem;
  9857   HICON hBalloonIcon;
  9858 } MY_NOTIFYICONDATAW;
  9859 
  9860 #define MYNOTIFYICONDATAW_V1_SIZE offsetof (MY_NOTIFYICONDATAW, szTip[64])
  9861 #define MYNOTIFYICONDATAW_V2_SIZE offsetof (MY_NOTIFYICONDATAW, guidItem)
  9862 #define MYNOTIFYICONDATAW_V3_SIZE offsetof (MY_NOTIFYICONDATAW, hBalloonIcon)
  9863 #ifndef NIF_INFO
  9864 # define NIF_INFO     0x00000010
  9865 #endif
  9866 #ifndef NIIF_NONE
  9867 # define NIIF_NONE    0x00000000
  9868 #endif
  9869 #ifndef NIIF_INFO
  9870 # define NIIF_INFO    0x00000001
  9871 #endif
  9872 #ifndef NIIF_WARNING
  9873 # define NIIF_WARNING 0x00000002
  9874 #endif
  9875 #ifndef NIIF_ERROR
  9876 # define NIIF_ERROR   0x00000003
  9877 #endif
  9878 
  9879 
  9880 #define EMACS_TRAY_NOTIFICATION_ID  42  /* arbitrary */
  9881 #define EMACS_NOTIFICATION_MSG      (WM_APP + 1)
  9882 
  9883 enum NI_Severity {
  9884   Ni_None,
  9885   Ni_Info,
  9886   Ni_Warn,
  9887   Ni_Err
  9888 };
  9889 
  9890 /* Report the version of a DLL given by its name.  The return value is
  9891    constructed using MAKEDLLVERULL.  */
  9892 static ULONGLONG
  9893 get_dll_version (const char *dll_name)
  9894 {
  9895   ULONGLONG version = 0;
  9896   HINSTANCE hdll = LoadLibrary (dll_name);
  9897 
  9898   if (hdll)
  9899     {
  9900       DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)
  9901         get_proc_addr (hdll, "DllGetVersion");
  9902 
  9903       if (pDllGetVersion)
  9904         {
  9905           DLLVERSIONINFO dvi;
  9906           HRESULT result;
  9907 
  9908           memset (&dvi, 0, sizeof(dvi));
  9909           dvi.cbSize = sizeof(dvi);
  9910           result = pDllGetVersion (&dvi);
  9911           if (SUCCEEDED (result))
  9912             version = MAKEDLLVERULL (dvi.dwMajorVersion, dvi.dwMinorVersion,
  9913                                      0, 0);
  9914         }
  9915       FreeLibrary (hdll);
  9916     }
  9917 
  9918   return version;
  9919 }
  9920 
  9921 /* Return the number of bytes in UTF-8 encoded string STR that
  9922    corresponds to at most LIM characters.  If STR ends before LIM
  9923    characters, return the number of bytes in STR including the
  9924    terminating null byte.  */
  9925 static int
  9926 utf8_mbslen_lim (const char *str, int lim)
  9927 {
  9928   const char *p = str;
  9929   int mblen = 0, nchars = 0;
  9930 
  9931   while (*p && nchars < lim)
  9932     {
  9933       int nbytes = CHAR_BYTES (*p);
  9934 
  9935       mblen += nbytes;
  9936       nchars++;
  9937       p += nbytes;
  9938     }
  9939 
  9940   if (!*p && nchars < lim)
  9941     mblen++;
  9942 
  9943   return mblen;
  9944 }
  9945 
  9946 /* Low-level subroutine to show tray notifications.  All strings are
  9947    supposed to be unibyte UTF-8 encoded by the caller.  */
  9948 static EMACS_INT
  9949 add_tray_notification (struct frame *f, const char *icon, const char *tip,
  9950                        enum NI_Severity severity, unsigned timeout,
  9951                        const char *title, const char *msg)
  9952 {
  9953   EMACS_INT retval = EMACS_TRAY_NOTIFICATION_ID;
  9954 
  9955   if (FRAME_W32_P (f))
  9956     {
  9957       MY_NOTIFYICONDATAW nidw;
  9958       ULONGLONG shell_dll_version = get_dll_version ("Shell32.dll");
  9959       wchar_t tipw[128], msgw[256], titlew[64];
  9960       int tiplen;
  9961 
  9962       memset (&nidw, 0, sizeof(nidw));
  9963 
  9964       /* MSDN says the full struct is supported since Vista, whose
  9965          Shell32.dll version is said to be 6.0.6.  But DllGetVersion
  9966          cannot report the 3rd field value, it reports "build number"
  9967          instead, which is something else.  So we use the Windows 7's
  9968          version 6.1 as cutoff, and Vista loses.  (Actually, the loss
  9969          is not a real one, since we don't expose the hBalloonIcon
  9970          member of the struct to Lisp.)  */
  9971       if (shell_dll_version >= MAKEDLLVERULL (6, 1, 0, 0)) /* >= Windows 7 */
  9972         nidw.cbSize = sizeof (nidw);
  9973       else if (shell_dll_version >= MAKEDLLVERULL (6, 0, 0, 0)) /* XP */
  9974         nidw.cbSize = MYNOTIFYICONDATAW_V3_SIZE;
  9975       else if (shell_dll_version >= MAKEDLLVERULL (5, 0, 0, 0)) /* W2K */
  9976         nidw.cbSize = MYNOTIFYICONDATAW_V2_SIZE;
  9977       else
  9978         nidw.cbSize = MYNOTIFYICONDATAW_V1_SIZE;                /* < W2K */
  9979       nidw.hWnd = FRAME_W32_WINDOW (f);
  9980       nidw.uID = EMACS_TRAY_NOTIFICATION_ID;
  9981       nidw.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
  9982       nidw.uCallbackMessage = EMACS_NOTIFICATION_MSG;
  9983       if (!*icon)
  9984         nidw.hIcon = LoadIcon (hinst, EMACS_CLASS);
  9985       else
  9986         {
  9987           if (w32_unicode_filenames)
  9988             {
  9989               wchar_t icon_w[MAX_PATH];
  9990 
  9991               if (filename_to_utf16 (icon, icon_w) != 0)
  9992                 {
  9993                   errno = ENOENT;
  9994                   return -1;
  9995                 }
  9996               nidw.hIcon = LoadImageW (NULL, icon_w, IMAGE_ICON, 0, 0,
  9997                                        LR_DEFAULTSIZE | LR_LOADFROMFILE);
  9998             }
  9999           else
 10000             {
 10001               char icon_a[MAX_PATH];
 10002 
 10003               if (filename_to_ansi (icon, icon_a) != 0)
 10004                 {
 10005                   errno = ENOENT;
 10006                   return -1;
 10007                 }
 10008               nidw.hIcon = LoadImageA (NULL, icon_a, IMAGE_ICON, 0, 0,
 10009                                        LR_DEFAULTSIZE | LR_LOADFROMFILE);
 10010             }
 10011         }
 10012       if (!nidw.hIcon)
 10013         {
 10014           switch (GetLastError ())
 10015             {
 10016             case ERROR_FILE_NOT_FOUND:
 10017               errno = ENOENT;
 10018               break;
 10019             default:
 10020               errno = ENOMEM;
 10021               break;
 10022             }
 10023           return -1;
 10024         }
 10025 
 10026       /* Windows 9X and NT4 support only 64 characters in the Tip,
 10027          later versions support up to 128.  */
 10028       if (nidw.cbSize == MYNOTIFYICONDATAW_V1_SIZE)
 10029         {
 10030           tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 10031                                          tip, utf8_mbslen_lim (tip, 63),
 10032                                          tipw, 64);
 10033           if (tiplen >= 63)
 10034             tipw[63] = 0;
 10035         }
 10036       else
 10037         {
 10038           tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 10039                                          tip, utf8_mbslen_lim (tip, 127),
 10040                                          tipw, 128);
 10041           if (tiplen >= 127)
 10042             tipw[127] = 0;
 10043         }
 10044       if (tiplen == 0)
 10045         {
 10046           errno = EINVAL;
 10047           retval = -1;
 10048           goto done;
 10049         }
 10050       wcscpy (nidw.szTip, tipw);
 10051 
 10052       /* The rest of the structure is only supported since Windows 2000.  */
 10053       if (nidw.cbSize > MYNOTIFYICONDATAW_V1_SIZE)
 10054         {
 10055           int slen;
 10056 
 10057           slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 10058                                              msg, utf8_mbslen_lim (msg, 255),
 10059                                              msgw, 256);
 10060           if (slen >= 255)
 10061             msgw[255] = 0;
 10062           else if (slen == 0)
 10063             {
 10064               errno = EINVAL;
 10065               retval = -1;
 10066               goto done;
 10067             }
 10068           wcscpy (nidw.szInfo, msgw);
 10069           nidw.uTimeout = timeout;
 10070           slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
 10071                                        title, utf8_mbslen_lim (title, 63),
 10072                                        titlew, 64);
 10073           if (slen >= 63)
 10074             titlew[63] = 0;
 10075           else if (slen == 0)
 10076             {
 10077               errno = EINVAL;
 10078               retval = -1;
 10079               goto done;
 10080             }
 10081           wcscpy (nidw.szInfoTitle, titlew);
 10082 
 10083           switch (severity)
 10084             {
 10085             case Ni_None:
 10086               nidw.dwInfoFlags = NIIF_NONE;
 10087               break;
 10088             case Ni_Info:
 10089             default:
 10090               nidw.dwInfoFlags = NIIF_INFO;
 10091               break;
 10092             case Ni_Warn:
 10093               nidw.dwInfoFlags = NIIF_WARNING;
 10094               break;
 10095             case Ni_Err:
 10096               nidw.dwInfoFlags = NIIF_ERROR;
 10097               break;
 10098             }
 10099         }
 10100 
 10101       if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw))
 10102         {
 10103           /* GetLastError returns meaningless results when
 10104              Shell_NotifyIcon fails.  */
 10105           DebPrint (("Shell_NotifyIcon ADD failed (err=%d)\n",
 10106                      GetLastError ()));
 10107           errno = EINVAL;
 10108           retval = -1;
 10109         }
 10110     done:
 10111       if (*icon && !DestroyIcon (nidw.hIcon))
 10112         DebPrint (("DestroyIcon failed (err=%d)\n", GetLastError ()));
 10113     }
 10114   return retval;
 10115 }
 10116 
 10117 /* Low-level subroutine to remove a tray notification.  Note: we only
 10118    pass the minimum data about the notification: its ID and the handle
 10119    of the window to which it sends messages.  MSDN doesn't say this is
 10120    enough, but it works in practice.  This allows us to avoid keeping
 10121    the notification data around after we show the notification.  */
 10122 static void
 10123 delete_tray_notification (struct frame *f, int id)
 10124 {
 10125   if (FRAME_W32_P (f))
 10126     {
 10127       MY_NOTIFYICONDATAW nidw;
 10128 
 10129       memset (&nidw, 0, sizeof(nidw));
 10130       nidw.hWnd = FRAME_W32_WINDOW (f);
 10131       nidw.uID = id;
 10132 
 10133       if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
 10134         {
 10135           /* GetLastError returns meaningless results when
 10136              Shell_NotifyIcon fails.  */
 10137           DebPrint (("Shell_NotifyIcon DELETE failed\n"));
 10138           errno = EINVAL;
 10139           return;
 10140         }
 10141     }
 10142   return;
 10143 }
 10144 
 10145 DEFUN ("w32-notification-notify",
 10146        Fw32_notification_notify, Sw32_notification_notify,
 10147        0, MANY, 0,
 10148        doc: /* Display an MS-Windows tray notification as specified by PARAMS.
 10149 
 10150 Value is the integer unique ID of the notification that can be used
 10151 to remove the notification using `w32-notification-close', which see.
 10152 If the function fails, the return value is nil.
 10153 
 10154 Tray notifications, a.k.a. \"taskbar messages\", are messages that
 10155 inform the user about events unrelated to the current user activity,
 10156 such as a significant system event, by briefly displaying informative
 10157 text in a balloon from an icon in the notification area of the taskbar.
 10158 
 10159 Parameters in PARAMS are specified as keyword/value pairs.  All the
 10160 parameters are optional, but if no parameters are specified, the
 10161 function will do nothing and return nil.
 10162 
 10163 The following parameters are supported:
 10164 
 10165 :icon ICON       -- Display ICON in the system tray.  If ICON is a string,
 10166                     it should specify a file name from which to load the
 10167                     icon; the specified file should be a .ico Windows icon
 10168                     file.  If ICON is not a string, or if this parameter
 10169                     is not specified, the standard Emacs icon will be used.
 10170 
 10171 :tip TIP         -- Use TIP as the tooltip for the notification.  If TIP
 10172                     is a string, this is the text of a tooltip that will
 10173                     be shown when the mouse pointer hovers over the tray
 10174                     icon added by the notification.  If TIP is not a
 10175                     string, or if this parameter is not specified, the
 10176                     default tooltip text is \"Emacs notification\".  The
 10177                     tooltip text can be up to 127 characters long (63
 10178                     on Windows versions before W2K).  Longer strings
 10179                     will be truncated.
 10180 
 10181 :level LEVEL     -- Notification severity level, one of `info',
 10182                     `warning', or `error'.  If given, the value
 10183                     determines the icon displayed to the left of the
 10184                     notification title, but only if the `:title'
 10185                     parameter (see below) is also specified and is a
 10186                     string.
 10187 
 10188 :title TITLE     -- The title of the notification.  If TITLE is a string,
 10189                     it is displayed in a larger font immediately above
 10190                     the body text.  The title text can be up to 63
 10191                     characters long; longer text will be truncated.
 10192 
 10193 :body BODY       -- The body of the notification.  If BODY is a string,
 10194                     it specifies the text of the notification message.
 10195                     Use embedded newlines to control how the text is
 10196                     broken into lines.  The body text can be up to 255
 10197                     characters long, and will be truncated if it's longer.
 10198 
 10199 Note that versions of Windows before W2K support only `:icon' and `:tip'.
 10200 You can pass the other parameters, but they will be ignored on those
 10201 old systems.
 10202 
 10203 There can be at most one active notification at any given time.  An
 10204 active notification must be removed by calling `w32-notification-close'
 10205 before a new one can be shown.
 10206 
 10207 usage: (w32-notification-notify &rest PARAMS)  */)
 10208   (ptrdiff_t nargs, Lisp_Object *args)
 10209 {
 10210   struct frame *f = SELECTED_FRAME ();
 10211   Lisp_Object arg_plist, lres;
 10212   EMACS_INT retval;
 10213   char *icon, *tip, *title, *msg;
 10214   enum NI_Severity severity;
 10215   unsigned timeout = 0;
 10216 
 10217   if (nargs == 0)
 10218     return Qnil;
 10219 
 10220   arg_plist = Flist (nargs, args);
 10221 
 10222   /* Icon.  */
 10223   lres = plist_get (arg_plist, QCicon);
 10224   if (STRINGP (lres))
 10225     icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil)));
 10226   else
 10227     icon = (char *)"";
 10228 
 10229   /* Tip.  */
 10230   lres = plist_get (arg_plist, QCtip);
 10231   if (STRINGP (lres))
 10232     tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
 10233   else
 10234     tip = (char *)"Emacs notification";
 10235 
 10236   /* Severity.  */
 10237   lres = plist_get (arg_plist, QClevel);
 10238   if (NILP (lres))
 10239     severity = Ni_None;
 10240   else if (EQ (lres, Qinfo))
 10241     severity = Ni_Info;
 10242   else if (EQ (lres, Qwarning))
 10243     severity = Ni_Warn;
 10244   else if (EQ (lres, Qerror))
 10245     severity = Ni_Err;
 10246   else
 10247     severity = Ni_Info;
 10248 
 10249   /* Title.  */
 10250   lres = plist_get (arg_plist, QCtitle);
 10251   if (STRINGP (lres))
 10252     title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
 10253   else
 10254     title = (char *)"";
 10255 
 10256   /* Notification body text.  */
 10257   lres = plist_get (arg_plist, QCbody);
 10258   if (STRINGP (lres))
 10259     msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1));
 10260   else
 10261     msg = (char *)"";
 10262 
 10263   /* Do it!  */
 10264   retval = add_tray_notification (f, icon, tip, severity, timeout, title, msg);
 10265   return (retval < 0 ? Qnil : make_fixnum (retval));
 10266 }
 10267 
 10268 DEFUN ("w32-notification-close",
 10269        Fw32_notification_close, Sw32_notification_close,
 10270        1, 1, 0,
 10271        doc: /* Remove the MS-Windows tray notification specified by its ID.  */)
 10272   (Lisp_Object id)
 10273 {
 10274   struct frame *f = SELECTED_FRAME ();
 10275 
 10276   if (FIXNUMP (id))
 10277     delete_tray_notification (f, XFIXNUM (id));
 10278 
 10279   return Qnil;
 10280 }
 10281 
 10282 #endif  /* WINDOWSNT && !HAVE_DBUS */
 10283 
 10284 DEFUN ("w32-get-ime-open-status",
 10285        Fw32_get_ime_open_status, Sw32_get_ime_open_status,
 10286        0, 0, 0,
 10287        doc: /* Return non-nil if IME is active, otherwise return nil.
 10288 
 10289 IME, the MS-Windows Input Method Editor, can be active or inactive.
 10290 This function returns non-nil if the IME is active, otherwise nil.  */)
 10291   (void)
 10292 {
 10293   struct frame *sf =
 10294     FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame))
 10295     ? XFRAME  (selected_frame)
 10296     : NULL;
 10297 
 10298   if (sf)
 10299     {
 10300       HWND current_window = FRAME_W32_WINDOW (sf);
 10301       HIMC context = get_ime_context_fn (current_window);
 10302       if (context)
 10303         {
 10304           BOOL retval = get_ime_open_status_fn (context);
 10305           release_ime_context_fn (current_window, context);
 10306 
 10307           return retval ? Qt : Qnil;
 10308         }
 10309     }
 10310 
 10311   return Qnil;
 10312 }
 10313 
 10314 DEFUN ("w32-set-ime-open-status",
 10315        Fw32_set_ime_open_status, Sw32_set_ime_open_status,
 10316        1, 1, 0,
 10317        doc: /* Open or close the IME according to STATUS.
 10318 
 10319 This function activates the IME, the MS-Windows Input Method Editor,
 10320 if STATUS is non-nil, otherwise it deactivates the IME.  */)
 10321   (Lisp_Object status)
 10322 {
 10323   unsigned ime_status = NILP (status) ? 0 : 1;
 10324 
 10325   PostThreadMessage (dwWindowsThreadId, WM_EMACS_IME_STATUS, ime_status, 0);
 10326   return Qnil;
 10327 }
 10328 
 10329 
 10330 #ifdef WINDOWSNT
 10331 /***********************************************************************
 10332                           Reading Registry
 10333  ***********************************************************************/
 10334 DEFUN ("w32-read-registry",
 10335        Fw32_read_registry, Sw32_read_registry,
 10336        3, 3, 0,
 10337        doc: /* Return the value stored in MS-Windows Registry under ROOT/KEY/NAME.
 10338 
 10339 ROOT is a symbol, one of `HKCR', `HKCU', `HKLM', `HKU', or `HKCC'.
 10340 It can also be nil, which means try `HKCU', and if that fails, try `HKLM'.
 10341 
 10342 KEY and NAME must be strings, and NAME must not include slashes.
 10343 KEY can use either forward- or back-slashes.
 10344 To access the default value of KEY (if it is defined), use NAME
 10345 that is an empty string.
 10346 
 10347 If the named KEY or its subkey called NAME don't exist, or cannot be
 10348 accessed by the current user, the function returns nil.  Otherwise,
 10349 the return value depends on the type of the data stored in Registry:
 10350 
 10351   If the data type is REG_NONE, the function returns t.
 10352   If the data type is REG_DWORD or REG_QWORD, the function returns
 10353     its integer value.  If the value is too large for a fixnum,
 10354     the function returns a bignum.
 10355   If the data type is REG_BINARY, the function returns a vector whose
 10356     elements are individual bytes of the value.
 10357   If the data type is REG_SZ, the function returns a string.
 10358   If the data type is REG_EXPAND_SZ, the function returns a string
 10359     with all the %..% references to environment variables replaced
 10360     by the values of those variables.  If the expansion fails, or
 10361     some variables are not defined in the environment, some or all
 10362     of the environment variables will remain unexpanded.
 10363   If the data type is REG_MULTI_SZ, the function returns a list whose
 10364     elements are the individual strings.
 10365 
 10366 Note that this function doesn't know whether a string value is a file
 10367 name, so file names will be returned with backslashes, which may need
 10368 to be converted to forward slashes by the caller.  */)
 10369   (Lisp_Object root, Lisp_Object key, Lisp_Object name)
 10370 {
 10371   CHECK_SYMBOL (root);
 10372   CHECK_STRING (key);
 10373   CHECK_STRING (name);
 10374 
 10375   HKEY rootkey = HKEY_CURRENT_USER;
 10376   if (EQ (root, QHKCR))
 10377     rootkey = HKEY_CLASSES_ROOT;
 10378   else if (EQ (root, QHKCU))
 10379     rootkey = HKEY_CURRENT_USER;
 10380   else if (EQ (root, QHKLM))
 10381     rootkey = HKEY_LOCAL_MACHINE;
 10382   else if (EQ (root, QHKU))
 10383     rootkey = HKEY_USERS;
 10384   else if (EQ (root, QHKCC))
 10385     rootkey = HKEY_CURRENT_CONFIG;
 10386   else if (!NILP (root))
 10387     error ("unknown root key: %s", SDATA (SYMBOL_NAME (root)));
 10388 
 10389   Lisp_Object val = w32_read_registry (rootkey, key, name);
 10390   if (NILP (val) && NILP (root))
 10391     val = w32_read_registry (HKEY_LOCAL_MACHINE, key, name);
 10392 
 10393   return val;
 10394 }
 10395 
 10396 #endif  /* WINDOWSNT */
 10397 
 10398 /* Query a value from the Windows Registry (under HKCU and HKLM),
 10399    where `key' is the registry key, `name' is the name, and `lpdwtype'
 10400    is a pointer to the return value's type. `lpwdtype' can be NULL if
 10401    you do not care about the type.
 10402 
 10403    Returns: pointer to the value, or null pointer if the key/name does
 10404    not exist. */
 10405 LPBYTE
 10406 w32_get_resource (const char *key, const char *name, LPDWORD lpdwtype)
 10407 {
 10408   LPBYTE lpvalue;
 10409   HKEY hrootkey = NULL;
 10410   DWORD cbData;
 10411 
 10412   /* Check both the current user and the local machine to see if
 10413      we have any resources.  */
 10414 
 10415   if (RegOpenKeyEx (HKEY_CURRENT_USER, key, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
 10416     {
 10417       lpvalue = NULL;
 10418 
 10419       if (RegQueryValueEx (hrootkey, name, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
 10420           && (lpvalue = xmalloc (cbData)) != NULL
 10421           && RegQueryValueEx (hrootkey, name, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
 10422         {
 10423           RegCloseKey (hrootkey);
 10424           return (lpvalue);
 10425         }
 10426 
 10427       xfree (lpvalue);
 10428 
 10429       RegCloseKey (hrootkey);
 10430     }
 10431 
 10432   if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
 10433     {
 10434       lpvalue = NULL;
 10435 
 10436       if (RegQueryValueEx (hrootkey, name, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
 10437           && (lpvalue = xmalloc (cbData)) != NULL
 10438           && RegQueryValueEx (hrootkey, name, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
 10439         {
 10440           RegCloseKey (hrootkey);
 10441           return (lpvalue);
 10442         }
 10443 
 10444       xfree (lpvalue);
 10445 
 10446       RegCloseKey (hrootkey);
 10447     }
 10448 
 10449   return (NULL);
 10450 }
 10451 
 10452 #ifdef WINDOWSNT
 10453 
 10454 /***********************************************************************
 10455                             Wallpaper
 10456  ***********************************************************************/
 10457 
 10458 typedef BOOL (WINAPI * SystemParametersInfoW_Proc) (UINT,UINT,PVOID,UINT);
 10459 SystemParametersInfoW_Proc system_parameters_info_w_fn = NULL;
 10460 
 10461 DEFUN ("w32-set-wallpaper", Fw32_set_wallpaper, Sw32_set_wallpaper, 1, 1, 0,
 10462        doc: /* Set the desktop wallpaper image to IMAGE-FILE.  */)
 10463   (Lisp_Object image_file)
 10464 {
 10465   Lisp_Object encoded = ENCODE_FILE (Fexpand_file_name (image_file, Qnil));
 10466   char *fname = SSDATA (encoded);
 10467   BOOL result = false;
 10468   DWORD err = 0;
 10469 
 10470   /* UNICOWS.DLL seems to have SystemParametersInfoW, but it doesn't
 10471      seem to be worth the hassle to support that on Windows 9X for the
 10472      benefit of this minor feature.  Let them use on Windows 9X only
 10473      image file names that can be encoded by the system codepage.  */
 10474   if (w32_unicode_filenames && system_parameters_info_w_fn)
 10475     {
 10476       wchar_t fname_w[MAX_PATH];
 10477 
 10478       if (filename_to_utf16 (fname, fname_w) != 0)
 10479         err = ERROR_FILE_NOT_FOUND;
 10480       else
 10481         result = SystemParametersInfoW (SPI_SETDESKWALLPAPER, 0, fname_w,
 10482                                         SPIF_SENDCHANGE);
 10483     }
 10484   else
 10485     {
 10486       char fname_a[MAX_PATH];
 10487 
 10488       if (filename_to_ansi (fname, fname_a) != 0)
 10489         err = ERROR_FILE_NOT_FOUND;
 10490       else
 10491         result = SystemParametersInfoA (SPI_SETDESKWALLPAPER, 0, fname_a,
 10492                                         SPIF_SENDCHANGE);
 10493     }
 10494   if (!result)
 10495     {
 10496       if (err == ERROR_FILE_NOT_FOUND)
 10497         error ("Wallpaper file %s does not exist or cannot be accessed", fname);
 10498       else
 10499         {
 10500           err = GetLastError ();
 10501           if (err)
 10502             error ("Could not set desktop wallpaper: %s", w32_strerror (err));
 10503           else
 10504             error ("Could not set desktop wallpaper (wrong image type?)");
 10505         }
 10506     }
 10507 
 10508   return Qnil;
 10509 }
 10510 #endif
 10511 
 10512 /***********************************************************************
 10513                             Initialization
 10514  ***********************************************************************/
 10515 
 10516 /* Keep this list in the same order as frame_parms in frame.c.
 10517    Use 0 for unsupported frame parameters.  */
 10518 
 10519 frame_parm_handler w32_frame_parm_handlers[] =
 10520 {
 10521   gui_set_autoraise,
 10522   gui_set_autolower,
 10523   w32_set_background_color,
 10524   w32_set_border_color,
 10525   gui_set_border_width,
 10526   w32_set_cursor_color,
 10527   w32_set_cursor_type,
 10528   gui_set_font,
 10529   w32_set_foreground_color,
 10530   w32_set_icon_name,
 10531   w32_set_icon_type,
 10532   w32_set_child_frame_border_width,
 10533   w32_set_internal_border_width,
 10534   gui_set_right_divider_width,
 10535   gui_set_bottom_divider_width,
 10536   w32_set_menu_bar_lines,
 10537   w32_set_mouse_color,
 10538   w32_explicitly_set_name,
 10539   gui_set_scroll_bar_width,
 10540   gui_set_scroll_bar_height,
 10541   w32_set_title,
 10542   gui_set_unsplittable,
 10543   gui_set_vertical_scroll_bars,
 10544   gui_set_horizontal_scroll_bars,
 10545   gui_set_visibility,
 10546   w32_set_tab_bar_lines,
 10547   w32_set_tool_bar_lines,
 10548   0, /* x_set_scroll_bar_foreground, */
 10549   0, /* x_set_scroll_bar_background, */
 10550   gui_set_screen_gamma,
 10551   gui_set_line_spacing,
 10552   gui_set_left_fringe,
 10553   gui_set_right_fringe,
 10554   0, /* x_set_wait_for_wm, */
 10555   gui_set_fullscreen,
 10556   gui_set_font_backend,
 10557   gui_set_alpha,
 10558   0, /* x_set_sticky */
 10559   0, /* x_set_tool_bar_position */
 10560   w32_set_inhibit_double_buffering,
 10561   w32_set_undecorated,
 10562   w32_set_parent_frame,
 10563   w32_set_skip_taskbar,
 10564   w32_set_no_focus_on_map,
 10565   w32_set_no_accept_focus,
 10566   w32_set_z_group,
 10567   0, /* x_set_override_redirect */
 10568   gui_set_no_special_glyphs,
 10569   gui_set_alpha_background,
 10570   0, /* x_set_use_frame_synchronization */
 10571 };
 10572 
 10573 void
 10574 syms_of_w32fns (void)
 10575 {
 10576   globals_of_w32fns ();
 10577   track_mouse_window = NULL;
 10578 
 10579   w32_visible_system_caret_hwnd = NULL;
 10580   PDUMPER_IGNORE (w32_visible_system_caret_hwnd);
 10581 
 10582   DEFSYM (Qundefined_color, "undefined-color");
 10583   DEFSYM (Qcancel_timer, "cancel-timer");
 10584   DEFSYM (Qhyper, "hyper");
 10585   DEFSYM (Qsuper, "super");
 10586   DEFSYM (Qmeta, "meta");
 10587   DEFSYM (Qalt, "alt");
 10588   DEFSYM (Qctrl, "ctrl");
 10589   DEFSYM (Qcontrol, "control");
 10590   DEFSYM (Qshift, "shift");
 10591   DEFSYM (Qfont_parameter, "font-parameter");
 10592   DEFSYM (Qgeometry, "geometry");
 10593   DEFSYM (Qworkarea, "workarea");
 10594   DEFSYM (Qmm_size, "mm-size");
 10595   DEFSYM (Qframes, "frames");
 10596   DEFSYM (Qtip_frame, "tip-frame");
 10597   DEFSYM (Qassq_delete_all, "assq-delete-all");
 10598   DEFSYM (Qunicode_sip, "unicode-sip");
 10599 #if defined WINDOWSNT && !defined HAVE_DBUS
 10600   DEFSYM (QCicon, ":icon");
 10601   DEFSYM (QCtip, ":tip");
 10602   DEFSYM (QClevel, ":level");
 10603   DEFSYM (Qinfo, "info");
 10604   DEFSYM (Qwarning, "warning");
 10605   DEFSYM (QCtitle, ":title");
 10606   DEFSYM (QCbody, ":body");
 10607 #endif
 10608 
 10609 #ifdef WINDOWSNT
 10610   DEFSYM (QHKCR, "HKCR");
 10611   DEFSYM (QHKCU, "HKCU");
 10612   DEFSYM (QHKLM, "HKLM");
 10613   DEFSYM (QHKU,  "HKU");
 10614   DEFSYM (QHKCC, "HKCC");
 10615 #endif
 10616 
 10617   /* Symbols used elsewhere, but only in MS-Windows-specific code.  */
 10618   DEFSYM (Qgnutls, "gnutls");
 10619   DEFSYM (Qlibxml2, "libxml2");
 10620   DEFSYM (Qserif, "serif");
 10621   DEFSYM (Qzlib, "zlib");
 10622   DEFSYM (Qlcms2, "lcms2");
 10623   DEFSYM (Qjson, "json");
 10624 
 10625   Fput (Qundefined_color, Qerror_conditions,
 10626         pure_list (Qundefined_color, Qerror));
 10627   Fput (Qundefined_color, Qerror_message,
 10628         build_pure_c_string ("Undefined color"));
 10629 
 10630   staticpro (&w32_grabbed_keys);
 10631   w32_grabbed_keys = Qnil;
 10632 
 10633   DEFVAR_LISP ("w32-color-map", Vw32_color_map,
 10634                doc: /* An array of color name mappings for Windows.  */);
 10635   Vw32_color_map = Qnil;
 10636 
 10637   DEFVAR_LISP ("w32-pass-alt-to-system", Vw32_pass_alt_to_system,
 10638                doc: /* Non-nil if Alt key presses are passed on to Windows.
 10639 When non-nil, for example, Alt pressed and released and then space will
 10640 open the System menu.  When nil, Emacs processes the Alt key events, and
 10641 then silently swallows them.  */);
 10642   Vw32_pass_alt_to_system = Qnil;
 10643 
 10644   DEFVAR_LISP ("w32-alt-is-meta", Vw32_alt_is_meta,
 10645                doc: /* Non-nil if the Alt key is to be considered the same as the META key.
 10646 When nil, Emacs will translate the Alt key to the ALT modifier, not to META.  */);
 10647   Vw32_alt_is_meta = Qt;
 10648 
 10649   DEFVAR_INT ("w32-quit-key", w32_quit_key,
 10650                doc: /* If non-zero, the virtual key code for an alternative quit key.  */);
 10651   w32_quit_key = 0;
 10652 
 10653   DEFVAR_LISP ("w32-pass-lwindow-to-system",
 10654                Vw32_pass_lwindow_to_system,
 10655                doc: /* If non-nil, the left \"Windows\" key is passed on to Windows.
 10656 
 10657 When non-nil, the Start menu is opened by tapping the key.
 10658 If you set this to nil, the left \"Windows\" key is processed by Emacs
 10659 according to the value of `w32-lwindow-modifier', which see.
 10660 
 10661 Note that some combinations of the left \"Windows\" key with other
 10662 keys are caught by Windows at low level.  For example, <lwindow>-r
 10663 pops up the Windows Run dialog, <lwindow>-<Pause> pops up the "System
 10664 Properties" dialog, etc.  On Windows 10, no \"Windows\" key
 10665 combinations are normally handed to applications.  To enable Emacs to
 10666 process \"Windows\" key combinations, use the function
 10667 `w32-register-hot-key'.
 10668 
 10669 For Windows 98/ME, see the doc string of `w32-phantom-key-code'.  */);
 10670   Vw32_pass_lwindow_to_system = Qt;
 10671 
 10672   DEFVAR_LISP ("w32-pass-rwindow-to-system",
 10673                Vw32_pass_rwindow_to_system,
 10674                doc: /* If non-nil, the right \"Windows\" key is passed on to Windows.
 10675 
 10676 When non-nil, the Start menu is opened by tapping the key.
 10677 If you set this to nil, the right \"Windows\" key is processed by Emacs
 10678 according to the value of `w32-rwindow-modifier', which see.
 10679 
 10680 Note that some combinations of the right \"Windows\" key with other
 10681 keys are caught by Windows at low level.  For example, <rwindow>-r
 10682 pops up the Windows Run dialog, <rwindow>-<Pause> pops up the "System
 10683 Properties" dialog, etc.  On Windows 10, no \"Windows\" key
 10684 combinations are normally handed to applications.  To enable Emacs to
 10685 process \"Windows\" key combinations, use the function
 10686 `w32-register-hot-key'.
 10687 
 10688 For Windows 98/ME, see the doc string of `w32-phantom-key-code'.  */);
 10689   Vw32_pass_rwindow_to_system = Qt;
 10690 
 10691   DEFVAR_LISP ("w32-phantom-key-code",
 10692                Vw32_phantom_key_code,
 10693                doc: /* Virtual key code used to generate \"phantom\" key presses.
 10694 Value is a number between 0 and 255.
 10695 
 10696 Phantom key presses are generated in order to stop the system from
 10697 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
 10698 `w32-pass-rwindow-to-system' is nil.
 10699 
 10700 This variable is only used on Windows 98 and ME.  For other Windows
 10701 versions, see the documentation of the `w32-register-hot-key'
 10702 function.  */);
 10703   /* Although 255 is technically not a valid key code, it works and
 10704      means that this hack won't interfere with any real key code.  */
 10705   XSETINT (Vw32_phantom_key_code, 255);
 10706 
 10707   DEFVAR_LISP ("w32-enable-num-lock",
 10708                Vw32_enable_num_lock,
 10709                doc: /* If non-nil, the Num Lock key acts normally.
 10710 Set to nil to handle Num Lock as the `kp-numlock' key.  */);
 10711   Vw32_enable_num_lock = Qt;
 10712 
 10713   DEFVAR_LISP ("w32-enable-caps-lock",
 10714                Vw32_enable_caps_lock,
 10715                doc: /* If non-nil, the Caps Lock key acts normally.
 10716 Set to nil to handle Caps Lock as the `capslock' key.  */);
 10717   Vw32_enable_caps_lock = Qt;
 10718 
 10719   DEFVAR_LISP ("w32-scroll-lock-modifier",
 10720                Vw32_scroll_lock_modifier,
 10721                doc: /* Modifier to use for the Scroll Lock ON state.
 10722 The value can be hyper, super, meta, alt, control or shift for the
 10723 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
 10724 Any other value will cause the Scroll Lock key to be ignored by Emacs,
 10725 and it will have the same effect as in other applications.  */);
 10726   Vw32_scroll_lock_modifier = Qnil;
 10727 
 10728   DEFVAR_LISP ("w32-lwindow-modifier",
 10729                Vw32_lwindow_modifier,
 10730                doc: /* Modifier to use for the left \"Windows\" key.
 10731 The value can be hyper, super, meta, alt, control or shift for the
 10732 respective modifier, or nil to appear as the `lwindow' key.
 10733 Any other value will cause the key to be ignored.
 10734 
 10735 Also see the documentation of the `w32-register-hot-key' function.  */);
 10736   Vw32_lwindow_modifier = Qnil;
 10737 
 10738   DEFVAR_LISP ("w32-rwindow-modifier",
 10739                Vw32_rwindow_modifier,
 10740                doc: /* Modifier to use for the right \"Windows\" key.
 10741 The value can be hyper, super, meta, alt, control or shift for the
 10742 respective modifier, or nil to appear as the `rwindow' key.
 10743 Any other value will cause the key to be ignored.
 10744 
 10745 Also see the documentation of the `w32-register-hot-key' function.  */);
 10746   Vw32_rwindow_modifier = Qnil;
 10747 
 10748   DEFVAR_LISP ("w32-apps-modifier",
 10749                Vw32_apps_modifier,
 10750                doc: /* Modifier to use for the \"Apps\" key.
 10751 The value can be hyper, super, meta, alt, control or shift for the
 10752 respective modifier, or nil to appear as the `apps' key.
 10753 Any other value will cause the key to be ignored.  */);
 10754   Vw32_apps_modifier = Qnil;
 10755 
 10756   DEFVAR_BOOL ("w32-enable-synthesized-fonts", w32_enable_synthesized_fonts,
 10757                doc: /* Non-nil enables selection of artificially italicized and bold fonts.  */);
 10758   w32_enable_synthesized_fonts = 0;
 10759 
 10760   DEFVAR_LISP ("w32-enable-palette", Vw32_enable_palette,
 10761                doc: /* Non-nil enables Windows palette management to map colors exactly.  */);
 10762   Vw32_enable_palette = Qt;
 10763 
 10764   DEFVAR_INT ("w32-mouse-button-tolerance",
 10765               w32_mouse_button_tolerance,
 10766               doc: /* Analogue of double click interval for faking middle mouse events.
 10767 The value is the minimum time in milliseconds that must elapse between
 10768 left and right button down events before they are considered distinct events.
 10769 If both mouse buttons are depressed within this interval, a middle mouse
 10770 button down event is generated instead.  */);
 10771   w32_mouse_button_tolerance = GetDoubleClickTime () / 2;
 10772 
 10773   DEFVAR_INT ("w32-mouse-move-interval",
 10774               w32_mouse_move_interval,
 10775               doc: /* Minimum interval between mouse move events.
 10776 The value is the minimum time in milliseconds that must elapse between
 10777 successive mouse move (or scroll bar drag) events before they are
 10778 reported as lisp events.  */);
 10779   w32_mouse_move_interval = 0;
 10780 
 10781   DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
 10782                w32_pass_extra_mouse_buttons_to_system,
 10783                doc: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
 10784 Recent versions of Windows support mice with up to five buttons.
 10785 Since most applications don't support these extra buttons, most mouse
 10786 drivers will allow you to map them to functions at the system level.
 10787 If this variable is non-nil, Emacs will pass them on, allowing the
 10788 system to handle them.  */);
 10789   w32_pass_extra_mouse_buttons_to_system = 0;
 10790 
 10791   DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
 10792                w32_pass_multimedia_buttons_to_system,
 10793                doc: /* If non-nil, media buttons are passed to Windows.
 10794 Some modern keyboards contain buttons for controlling media players, web
 10795 browsers and other applications.  Generally these buttons are handled on a
 10796 system wide basis, but by setting this to nil they are made available
 10797 to Emacs for binding.  Depending on your keyboard, additional keys that
 10798 may be available are:
 10799 
 10800 browser-back, browser-forward, browser-refresh, browser-stop,
 10801 browser-search, browser-favorites, browser-home,
 10802 mail, mail-reply, mail-forward, mail-send,
 10803 app-1, app-2,
 10804 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
 10805 spell-check, correction-list, toggle-dictate-command,
 10806 media-next, media-previous, media-stop, media-play-pause, media-select,
 10807 media-play, media-pause, media-record, media-fast-forward, media-rewind,
 10808 media-channel-up, media-channel-down,
 10809 volume-mute, volume-up, volume-down,
 10810 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
 10811 bass-down, bass-boost, bass-up, treble-down, treble-up  */);
 10812   w32_pass_multimedia_buttons_to_system = 1;
 10813 
 10814 #if 0 /* TODO: Mouse cursor customization.  */
 10815   DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
 10816                doc: /* SKIP: real doc in xfns.c.  */);
 10817   Vx_pointer_shape = Qnil;
 10818 
 10819   Vx_nontext_pointer_shape = Qnil;
 10820 
 10821   Vx_mode_pointer_shape = Qnil;
 10822 
 10823   DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
 10824                doc: /* SKIP: real doc in xfns.c.  */);
 10825   Vx_hourglass_pointer_shape = Qnil;
 10826 
 10827   DEFVAR_LISP ("x-sensitive-text-pointer-shape",
 10828                Vx_sensitive_text_pointer_shape,
 10829                doc: /* SKIP: real doc in xfns.c.  */);
 10830   Vx_sensitive_text_pointer_shape = Qnil;
 10831 
 10832   DEFVAR_LISP ("x-window-horizontal-drag-cursor",
 10833                Vx_window_horizontal_drag_shape,
 10834                doc: /* SKIP: real doc in xfns.c.  */);
 10835   Vx_window_horizontal_drag_shape = Qnil;
 10836 
 10837   DEFVAR_LISP ("x-window-vertical-drag-cursor",
 10838                Vx_window_vertical_drag_shape,
 10839                doc: /* SKIP: real doc in xfns.c.  */);
 10840   Vx_window_vertical_drag_shape = Qnil;
 10841 #endif
 10842 
 10843   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
 10844                doc: /* SKIP: real doc in xfns.c.  */);
 10845   Vx_cursor_fore_pixel = Qnil;
 10846 
 10847   DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
 10848                doc: /* SKIP: real doc in xfns.c.  */);
 10849   Vx_max_tooltip_size = Qnil;
 10850 
 10851   DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
 10852                doc: /* SKIP: real doc in xfns.c.  */);
 10853   /* We don't have any way to find this out, so set it to nil
 10854      and maybe the user would like to set it to t.  */
 10855   Vx_no_window_manager = Qnil;
 10856 
 10857   DEFVAR_LISP ("x-pixel-size-width-font-regexp",
 10858                Vx_pixel_size_width_font_regexp,
 10859                doc: /* SKIP: real doc in xfns.c.  */);
 10860   Vx_pixel_size_width_font_regexp = Qnil;
 10861 
 10862   DEFVAR_BOOL ("w32-strict-painting",
 10863                w32_strict_painting,
 10864                doc: /* Non-nil means use strict rules for repainting frames.
 10865 Set this to nil to get the old behavior for repainting; this should
 10866 only be necessary if the default setting causes problems.  */);
 10867   w32_strict_painting = 1;
 10868 
 10869   DEFVAR_BOOL ("w32-use-fallback-wm-chars-method",
 10870                w32_use_fallback_wm_chars_method,
 10871                doc: /* Non-nil means use old method of processing character keys.
 10872 This is intended only for debugging of the new processing method.
 10873 Default is nil.
 10874 
 10875 This variable has effect only on NT family of systems, not on Windows 9X.  */);
 10876   w32_use_fallback_wm_chars_method = 0;
 10877 
 10878   DEFVAR_BOOL ("w32-disable-new-uniscribe-apis",
 10879                w32_disable_new_uniscribe_apis,
 10880                doc: /* Non-nil means don't use new Uniscribe APIs.
 10881 The new APIs are used to access OTF features supported by fonts.
 10882 This is intended only for debugging of the new Uniscribe-related code.
 10883 Default is nil.
 10884 
 10885 This variable has effect only on Windows Vista and later.  */);
 10886   w32_disable_new_uniscribe_apis = 0;
 10887 
 10888   DEFVAR_LISP ("w32-tooltip-extra-pixels",
 10889                Vw32_tooltip_extra_pixels,
 10890                doc: /* Number of pixels added after tooltip text.
 10891 On Windows some fonts may cause the last character of a tooltip be
 10892 truncated or wrapped around to the next line.  Adding some extra space
 10893 at the end of the toooltip works around this problem.
 10894 
 10895 This variable specifies the number of pixels that shall be added.  The
 10896 default value t means to add the width of one canonical character of the
 10897 tip frame.  */);
 10898   Vw32_tooltip_extra_pixels = Qt;
 10899 
 10900   DEFVAR_BOOL ("w32-disable-abort-dialog",
 10901                w32_disable_abort_dialog,
 10902                doc: /* Non-nil means don't display the abort dialog when aborting.  */);
 10903   w32_disable_abort_dialog = 0;
 10904 
 10905   DEFVAR_BOOL ("w32-ignore-modifiers-on-IME-input",
 10906                w32_ignore_modifiers_on_IME_input,
 10907                doc: /* Whether to ignore modifier keys when processing input with IME.
 10908 Some MS-Windows input methods use modifier keys such as Ctrl or Alt to input
 10909 characters, in which case applying the modifiers will change the input.
 10910 The default value of this variable is therefore t, to ignore modifier
 10911 keys when IME input is received.  */);
 10912   w32_ignore_modifiers_on_IME_input = true;
 10913 
 10914 #if 0 /* TODO: Port to W32 */
 10915   defsubr (&Sx_change_window_property);
 10916   defsubr (&Sx_delete_window_property);
 10917   defsubr (&Sx_window_property);
 10918 #endif
 10919   defsubr (&Sxw_display_color_p);
 10920   defsubr (&Sx_display_grayscale_p);
 10921   defsubr (&Sxw_color_defined_p);
 10922   defsubr (&Sxw_color_values);
 10923   defsubr (&Sx_server_max_request_size);
 10924   defsubr (&Sx_server_vendor);
 10925   defsubr (&Sx_server_version);
 10926   defsubr (&Sx_display_pixel_width);
 10927   defsubr (&Sx_display_pixel_height);
 10928   defsubr (&Sx_display_mm_width);
 10929   defsubr (&Sx_display_mm_height);
 10930   defsubr (&Sx_display_screens);
 10931   defsubr (&Sx_display_planes);
 10932   defsubr (&Sx_display_color_cells);
 10933   defsubr (&Sx_display_visual_class);
 10934   defsubr (&Sx_display_backing_store);
 10935   defsubr (&Sx_display_save_under);
 10936   defsubr (&Sx_create_frame);
 10937   defsubr (&Sx_open_connection);
 10938   defsubr (&Sx_close_connection);
 10939   defsubr (&Sx_display_list);
 10940   defsubr (&Sw32_frame_geometry);
 10941   defsubr (&Sw32_frame_edges);
 10942   defsubr (&Sw32_frame_list_z_order);
 10943   defsubr (&Sw32_frame_restack);
 10944   defsubr (&Sw32_mouse_absolute_pixel_position);
 10945   defsubr (&Sw32_set_mouse_absolute_pixel_position);
 10946   defsubr (&Sx_synchronize);
 10947 
 10948   /* W32 specific functions */
 10949 
 10950   defsubr (&Sw32_define_rgb_color);
 10951   defsubr (&Sw32_display_monitor_attributes_list);
 10952   defsubr (&Sw32_send_sys_command);
 10953   defsubr (&Sw32_shell_execute);
 10954   defsubr (&Sw32_register_hot_key);
 10955   defsubr (&Sw32_unregister_hot_key);
 10956   defsubr (&Sw32_registered_hot_keys);
 10957   defsubr (&Sw32_reconstruct_hot_key);
 10958   defsubr (&Sw32_toggle_lock_key);
 10959   defsubr (&Sw32_window_exists_p);
 10960   defsubr (&Sw32__menu_bar_in_use);
 10961 #if defined WINDOWSNT && !defined HAVE_DBUS
 10962   defsubr (&Sw32_notification_notify);
 10963   defsubr (&Sw32_notification_close);
 10964 #endif
 10965   defsubr (&Sw32_get_ime_open_status);
 10966   defsubr (&Sw32_set_ime_open_status);
 10967 
 10968 #ifdef WINDOWSNT
 10969   defsubr (&Sw32_read_registry);
 10970   defsubr (&Sfile_system_info);
 10971   defsubr (&Sdefault_printer_name);
 10972 #endif
 10973 
 10974   defsubr (&Sset_message_beep);
 10975   defsubr (&Sx_show_tip);
 10976   defsubr (&Sx_hide_tip);
 10977   tip_timer = Qnil;
 10978   staticpro (&tip_timer);
 10979   tip_frame = Qnil;
 10980   staticpro (&tip_frame);
 10981   tip_last_frame = Qnil;
 10982   staticpro (&tip_last_frame);
 10983   tip_last_string = Qnil;
 10984   staticpro (&tip_last_string);
 10985   tip_last_parms = Qnil;
 10986   staticpro (&tip_last_parms);
 10987 
 10988   defsubr (&Sx_file_dialog);
 10989 #ifdef WINDOWSNT
 10990   defsubr (&Ssystem_move_file_to_trash);
 10991   defsubr (&Sw32_set_wallpaper);
 10992 #endif
 10993 }
 10994 
 10995 
 10996 
 10997 /* Crashing and reporting backtrace.  */
 10998 
 10999 #ifndef CYGWIN
 11000 static LONG CALLBACK my_exception_handler (EXCEPTION_POINTERS *);
 11001 static LPTOP_LEVEL_EXCEPTION_FILTER prev_exception_handler;
 11002 #endif
 11003 static DWORD except_code;
 11004 static PVOID except_addr;
 11005 
 11006 #ifndef CYGWIN
 11007 
 11008 /* Stack overflow recovery.  */
 11009 
 11010 /* MinGW headers don't declare this (should be in malloc.h).  Also,
 11011    the function is not present pre-W2K, so make the call through
 11012    a function pointer.  */
 11013 typedef int (__cdecl *_resetstkoflw_proc) (void);
 11014 static _resetstkoflw_proc resetstkoflw;
 11015 
 11016 /* Re-establish the guard page at stack limit.  This is needed because
 11017    when a stack overflow is detected, Windows removes the guard bit
 11018    from the guard page, so if we don't re-establish that protection,
 11019    the next stack overflow will cause a crash.  */
 11020 void
 11021 w32_reset_stack_overflow_guard (void)
 11022 {
 11023   if (resetstkoflw == NULL)
 11024     resetstkoflw = (_resetstkoflw_proc)
 11025       get_proc_addr (GetModuleHandle ("msvcrt.dll"), "_resetstkoflw");
 11026   /* We ignore the return value.  If _resetstkoflw fails, the next
 11027      stack overflow will crash the program.  */
 11028   if (resetstkoflw != NULL)
 11029     (void)resetstkoflw ();
 11030 }
 11031 
 11032 static void
 11033 stack_overflow_handler (void)
 11034 {
 11035   /* Hard GC error may lead to stack overflow caused by
 11036      too nested calls to mark_object.  No way to survive.  */
 11037   if (gc_in_progress)
 11038     terminate_due_to_signal (SIGSEGV, 40);
 11039 #ifdef _WIN64
 11040   /* See ms-w32.h: MinGW64's longjmp crashes if invoked in this context.  */
 11041   __builtin_longjmp (return_to_command_loop, 1);
 11042 #else
 11043   sys_longjmp (return_to_command_loop, 1);
 11044 #endif
 11045 }
 11046 
 11047 /* This handler records the exception code and the address where it
 11048    was triggered so that this info could be included in the backtrace.
 11049    Without that, the backtrace in some cases has no information
 11050    whatsoever about the offending code, and looks as if the top-level
 11051    exception handler in the MinGW startup code was the one that
 11052    crashed.  We also recover from stack overflow, by calling our stack
 11053    overflow handler that jumps back to top level.  */
 11054 static LONG CALLBACK
 11055 my_exception_handler (EXCEPTION_POINTERS * exception_data)
 11056 {
 11057   except_code = exception_data->ExceptionRecord->ExceptionCode;
 11058   except_addr = exception_data->ExceptionRecord->ExceptionAddress;
 11059 
 11060   /* If this is a stack overflow exception, attempt to recover.  */
 11061   if (exception_data->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW
 11062       && exception_data->ExceptionRecord->NumberParameters == 2
 11063       /* We can only longjmp to top level from the main thread.  */
 11064       && GetCurrentThreadId () == dwMainThreadId)
 11065     {
 11066       /* Call stack_overflow_handler ().  */
 11067 #ifdef _WIN64
 11068       exception_data->ContextRecord->Rip = (DWORD_PTR) &stack_overflow_handler;
 11069 #else
 11070       exception_data->ContextRecord->Eip = (DWORD_PTR) &stack_overflow_handler;
 11071 #endif
 11072       /* Zero this out, so the stale address of the stack overflow
 11073          exception we handled is not displayed in some future
 11074          unrelated crash.  */
 11075       except_addr = 0;
 11076       return EXCEPTION_CONTINUE_EXECUTION;
 11077     }
 11078 
 11079   if (prev_exception_handler)
 11080     return prev_exception_handler (exception_data);
 11081   return EXCEPTION_EXECUTE_HANDLER;
 11082 }
 11083 #endif
 11084 
 11085 typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
 11086                                                       PULONG);
 11087 
 11088 #define BACKTRACE_LIMIT_MAX 62
 11089 
 11090 static int
 11091 w32_backtrace (void **buffer, int limit)
 11092 {
 11093   static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace = NULL;
 11094   HMODULE hm_kernel32 = NULL;
 11095 
 11096   if (!s_pfn_CaptureStackBackTrace)
 11097     {
 11098       hm_kernel32 = LoadLibrary ("Kernel32.dll");
 11099       s_pfn_CaptureStackBackTrace = (CaptureStackBackTrace_proc)
 11100         get_proc_addr (hm_kernel32, "RtlCaptureStackBackTrace");
 11101     }
 11102   if (s_pfn_CaptureStackBackTrace)
 11103     return s_pfn_CaptureStackBackTrace (0, min (BACKTRACE_LIMIT_MAX, limit),
 11104                                         buffer, NULL);
 11105   return 0;
 11106 }
 11107 
 11108 void
 11109 emacs_abort (void)
 11110 {
 11111   if (w32_disable_abort_dialog)
 11112     abort ();
 11113 
 11114   int button;
 11115 
 11116   if (noninteractive)
 11117     button = IDNO;
 11118   else
 11119     button = MessageBox (NULL,
 11120                          "A fatal error has occurred!\n\n"
 11121                          "Would you like to attach a debugger?\n\n"
 11122                          "Select:\n"
 11123                          "YES -- to debug Emacs, or\n"
 11124                          "NO  -- to abort Emacs and produce a backtrace\n"
 11125                          "       (emacs_backtrace.txt in current directory)."
 11126 #if __GNUC__
 11127                          "\n\n(Before clicking YES, type\n"
 11128                          "\"gdb -p <emacs-PID>\", then \"continue\" inside GDB.)"
 11129 #endif
 11130                          , "Emacs Abort Dialog",
 11131                          MB_ICONEXCLAMATION | MB_TASKMODAL
 11132                          | MB_SETFOREGROUND | MB_YESNO);
 11133   switch (button)
 11134     {
 11135     case IDYES:
 11136       DebugBreak ();
 11137       exit (2); /* tell the compiler we will never return */
 11138     case IDNO:
 11139     default:
 11140       {
 11141         void *stack[BACKTRACE_LIMIT_MAX + 1];
 11142         int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1);
 11143 
 11144         if (i)
 11145           {
 11146             int errfile_fd = -1;
 11147             int j;
 11148             char buf[sizeof ("\r\nException  at this address:\r\n\r\n")
 11149                      /* The type below should really be 'void *', but
 11150                         INT_BUFSIZE_BOUND cannot handle that without
 11151                         triggering compiler warnings (under certain
 11152                         pedantic warning switches), it wants an
 11153                         integer type.  */
 11154                      + 2 * INT_BUFSIZE_BOUND (intptr_t)];
 11155 #ifdef CYGWIN
 11156             int stderr_fd = 2;
 11157 #else
 11158             HANDLE errout = GetStdHandle (STD_ERROR_HANDLE);
 11159             int stderr_fd = -1;
 11160 
 11161             if (errout && errout != INVALID_HANDLE_VALUE)
 11162               stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY);
 11163 #endif
 11164 
 11165             /* We use %p, not 0x%p, as %p produces a leading "0x" on XP,
 11166                but not on Windows 7.  addr2line doesn't mind a missing
 11167                "0x", but will be confused by an extra one.  */
 11168             if (except_addr)
 11169               sprintf (buf, "\r\nException 0x%x at this address:\r\n%p\r\n",
 11170                        (unsigned int) except_code, except_addr);
 11171             if (stderr_fd >= 0)
 11172               {
 11173                 if (except_addr)
 11174                   write (stderr_fd, buf, strlen (buf));
 11175                 write (stderr_fd, "\r\nBacktrace:\r\n", 14);
 11176               }
 11177 #ifdef CYGWIN
 11178 #define _open open
 11179 #endif
 11180             errfile_fd = _open ("emacs_backtrace.txt", O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
 11181             if (errfile_fd >= 0)
 11182               {
 11183                 lseek (errfile_fd, 0L, SEEK_END);
 11184                 if (except_addr)
 11185                   write (errfile_fd, buf, strlen (buf));
 11186                 write (errfile_fd, "\r\nBacktrace:\r\n", 14);
 11187               }
 11188 
 11189             for (j = 0; j < i; j++)
 11190               {
 11191                 /* stack[] gives the return addresses, whereas we want
 11192                    the address of the call, so decrease each address
 11193                    by approximate size of 1 CALL instruction.  */
 11194                 sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *));
 11195                 if (stderr_fd >= 0)
 11196                   write (stderr_fd, buf, strlen (buf));
 11197                 if (errfile_fd >= 0)
 11198                   write (errfile_fd, buf, strlen (buf));
 11199               }
 11200             if (i == BACKTRACE_LIMIT_MAX)
 11201               {
 11202                 if (stderr_fd >= 0)
 11203                   write (stderr_fd, "...\r\n", 5);
 11204                 if (errfile_fd >= 0)
 11205                   write (errfile_fd, "...\r\n", 5);
 11206               }
 11207             if (errfile_fd >= 0)
 11208               close (errfile_fd);
 11209           }
 11210         abort ();
 11211         break;
 11212       }
 11213     }
 11214 }
 11215 
 11216 
 11217 
 11218 /* Initialization.  */
 11219 
 11220 /*
 11221         globals_of_w32fns is used to initialize those global variables that
 11222         must always be initialized on startup even when the global variable
 11223         initialized is non zero (see the function main in emacs.c).
 11224         globals_of_w32fns is called from syms_of_w32fns when the global
 11225         variable initialized is 0 and directly from main when initialized
 11226         is non zero.
 11227  */
 11228 void
 11229 globals_of_w32fns (void)
 11230 {
 11231   HMODULE user32_lib = GetModuleHandle ("user32.dll");
 11232   /*
 11233     TrackMouseEvent not available in all versions of Windows, so must load
 11234     it dynamically.  Do it once, here, instead of every time it is used.
 11235   */
 11236   track_mouse_event_fn = (TrackMouseEvent_Proc)
 11237     get_proc_addr (user32_lib, "TrackMouseEvent");
 11238 
 11239   monitor_from_point_fn = (MonitorFromPoint_Proc)
 11240     get_proc_addr (user32_lib, "MonitorFromPoint");
 11241   get_monitor_info_fn = (GetMonitorInfo_Proc)
 11242     get_proc_addr (user32_lib, "GetMonitorInfoA");
 11243   monitor_from_window_fn = (MonitorFromWindow_Proc)
 11244     get_proc_addr (user32_lib, "MonitorFromWindow");
 11245   enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
 11246     get_proc_addr (user32_lib, "EnumDisplayMonitors");
 11247   get_title_bar_info_fn = (GetTitleBarInfo_Proc)
 11248     get_proc_addr (user32_lib, "GetTitleBarInfo");
 11249 #ifndef CYGWIN
 11250   system_parameters_info_w_fn = (SystemParametersInfoW_Proc)
 11251     get_proc_addr (user32_lib, "SystemParametersInfoW");
 11252 #endif
 11253 
 11254   {
 11255     HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
 11256     get_composition_string_fn = (ImmGetCompositionString_Proc)
 11257       get_proc_addr (imm32_lib, "ImmGetCompositionStringW");
 11258     get_ime_context_fn = (ImmGetContext_Proc)
 11259       get_proc_addr (imm32_lib, "ImmGetContext");
 11260     release_ime_context_fn = (ImmReleaseContext_Proc)
 11261       get_proc_addr (imm32_lib, "ImmReleaseContext");
 11262     set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
 11263       get_proc_addr (imm32_lib, "ImmSetCompositionWindow");
 11264 
 11265     get_ime_open_status_fn = (ImmGetOpenStatus_Proc)
 11266       get_proc_addr (imm32_lib, "ImmGetOpenStatus");
 11267     set_ime_open_status_fn = (ImmSetOpenStatus_Proc)
 11268       get_proc_addr (imm32_lib, "ImmSetOpenStatus");
 11269   }
 11270 
 11271   HMODULE hm_kernel32 = GetModuleHandle ("kernel32.dll");
 11272   is_debugger_present = (IsDebuggerPresent_Proc)
 11273     get_proc_addr (hm_kernel32, "IsDebuggerPresent");
 11274   set_thread_description = (SetThreadDescription_Proc)
 11275     get_proc_addr (hm_kernel32, "SetThreadDescription");
 11276 
 11277   /* Support OS dark mode on Windows 10 version 1809 and higher.
 11278      See `w32_applytheme' which uses appropriate APIs per version of Windows.
 11279      For future wretches who may need to understand Windows build numbers:
 11280      https://docs.microsoft.com/en-us/windows/release-health/release-information
 11281   */
 11282   if (os_subtype == OS_SUBTYPE_NT
 11283       && w32_major_version >= 10 && w32_build_number >= 17763)
 11284     {
 11285       /* Load dwmapi.dll and uxtheme.dll, which will be needed to set
 11286          window themes.  */
 11287       HMODULE dwmapi_lib = LoadLibrary("dwmapi.dll");
 11288       DwmSetWindowAttribute_fn = (DwmSetWindowAttribute_Proc)
 11289         get_proc_addr (dwmapi_lib, "DwmSetWindowAttribute");
 11290       HMODULE uxtheme_lib = LoadLibrary("uxtheme.dll");
 11291       SetWindowTheme_fn = (SetWindowTheme_Proc)
 11292         get_proc_addr (uxtheme_lib, "SetWindowTheme");
 11293 
 11294       /* Check Windows Registry for system theme and set w32_darkmode.
 11295          TODO: "Nice to have" would be to create a lisp setting (which
 11296          defaults to this Windows Registry value), then read that lisp
 11297          value here instead. This would allow the user to forcibly
 11298          override the system theme (which is also user-configurable in
 11299          Windows settings; see MS-Windows section in Emacs manual). */
 11300       LPBYTE val =
 11301         w32_get_resource ("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
 11302                           "AppsUseLightTheme",
 11303                           NULL);
 11304       if (val && *val == 0)
 11305         w32_darkmode = TRUE;
 11306     }
 11307 
 11308   except_code = 0;
 11309   except_addr = 0;
 11310 #ifndef CYGWIN
 11311   prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler);
 11312   resetstkoflw = NULL;
 11313 #endif
 11314 
 11315   DEFVAR_INT ("w32-ansi-code-page",
 11316               w32_ansi_code_page,
 11317               doc: /* The ANSI code page used by the system.  */);
 11318   w32_ansi_code_page = GetACP ();
 11319 
 11320 #ifndef CYGWIN
 11321   DEFVAR_INT ("w32-multibyte-code-page",
 11322               w32_multibyte_code_page,
 11323               doc: /* The current multibyte code page used by the system.
 11324 A value of zero indicates that the single-byte code page is in use,
 11325 see `w32-ansi-code-page'.  */);
 11326   w32_multibyte_code_page = _getmbcp ();
 11327 #endif
 11328 
 11329   DEFVAR_BOOL ("w32-disable-double-buffering", w32_disable_double_buffering,
 11330                doc: /* Completely disable double buffering.
 11331 This variable is used for debugging, and takes precedence over any
 11332 value of the `inhibit-double-buffering' frame parameter.  */);
 11333   w32_disable_double_buffering = false;
 11334 
 11335   if (os_subtype == OS_SUBTYPE_NT)
 11336     w32_unicode_gui = 1;
 11337   else
 11338     w32_unicode_gui = 0;
 11339 
 11340   after_deadkey = -1;
 11341 
 11342   /* MessageBox does not work without this when linked to comctl32.dll 6.0.  */
 11343   InitCommonControls ();
 11344 
 11345   syms_of_w32uniscribe ();
 11346 }
 11347 
 11348 #ifdef NTGUI_UNICODE
 11349 
 11350 Lisp_Object
 11351 ntgui_encode_system (Lisp_Object str)
 11352 {
 11353   Lisp_Object encoded;
 11354   to_unicode (str, &encoded);
 11355   return encoded;
 11356 }
 11357 
 11358 #endif /* NTGUI_UNICODE */

/* [<][>][^][v][top][bottom][index][help] */