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