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