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