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