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