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

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