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