1 /* Graphical user interface functions for the Microsoft Windows API.
3 Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* Added by Kevin Gallo */
38 #include "character.h"
40 #include "intervals.h"
41 #include "dispextern.h"
43 #include "blockinput.h"
50 #include "termhooks.h"
52 #include "w32common.h"
57 #endif /* WINDOWSNT */
65 #include "bitmaps/gray.xbm"
80 #ifndef FOF_NO_CONNECTED_ELEMENTS
81 #define FOF_NO_CONNECTED_ELEMENTS 0x2000
84 void syms_of_w32fns (void);
85 void globals_of_w32fns (void);
87 extern void free_frame_menubar (struct frame
*);
88 extern int w32_console_toggle_lock_key (int, Lisp_Object
);
89 extern void w32_menu_display_help (HWND
, HMENU
, UINT
, UINT
);
90 extern void w32_free_menu_strings (HWND
);
91 extern const char *map_w32_filename (const char *, const char **);
92 extern char * w32_strerror (int error_no
);
95 #define IDC_HAND MAKEINTRESOURCE(32649)
98 /* Prefix for system colors. */
99 #define SYSTEM_COLOR_PREFIX "System"
100 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
102 /* State variables for emulating a three button mouse. */
107 static int button_state
= 0;
108 static W32Msg saved_mouse_button_msg
;
109 static unsigned mouse_button_timer
= 0; /* non-zero when timer is active */
110 static W32Msg saved_mouse_move_msg
;
111 static unsigned mouse_move_timer
= 0;
113 /* Window that is tracking the mouse. */
114 static HWND track_mouse_window
;
116 /* Multi-monitor API definitions that are not pulled from the headers
117 since we are compiling for NT 4. */
118 #ifndef MONITOR_DEFAULT_TO_NEAREST
119 #define MONITOR_DEFAULT_TO_NEAREST 2
121 #ifndef MONITORINFOF_PRIMARY
122 #define MONITORINFOF_PRIMARY 1
124 #ifndef SM_XVIRTUALSCREEN
125 #define SM_XVIRTUALSCREEN 76
127 #ifndef SM_YVIRTUALSCREEN
128 #define SM_YVIRTUALSCREEN 77
130 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
131 To avoid a compile error on one or the other, redefine with a new name. */
140 #ifndef CCHDEVICENAME
141 #define CCHDEVICENAME 32
143 struct MONITOR_INFO_EX
149 char szDevice
[CCHDEVICENAME
];
152 /* Reportedly, MSVC does not have this in its headers. */
153 #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
154 DECLARE_HANDLE(HMONITOR
);
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
);
175 TrackMouseEvent_Proc track_mouse_event_fn
= NULL
;
176 ImmGetCompositionString_Proc get_composition_string_fn
= NULL
;
177 ImmGetContext_Proc get_ime_context_fn
= NULL
;
178 ImmReleaseContext_Proc release_ime_context_fn
= NULL
;
179 ImmSetCompositionWindow_Proc set_ime_composition_window_fn
= NULL
;
180 MonitorFromPoint_Proc monitor_from_point_fn
= NULL
;
181 GetMonitorInfo_Proc get_monitor_info_fn
= NULL
;
182 MonitorFromWindow_Proc monitor_from_window_fn
= NULL
;
183 EnumDisplayMonitors_Proc enum_display_monitors_fn
= NULL
;
186 #define unicode_append_menu AppendMenuW
187 #else /* !NTGUI_UNICODE */
188 extern AppendMenuW_Proc unicode_append_menu
;
189 #endif /* NTGUI_UNICODE */
191 /* Flag to selectively ignore WM_IME_CHAR messages. */
192 static int ignore_ime_char
= 0;
194 /* W95 mousewheel handler */
195 unsigned int msh_mousewheel
= 0;
198 #define MOUSE_BUTTON_ID 1
199 #define MOUSE_MOVE_ID 2
200 #define MENU_FREE_ID 3
201 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
203 #define MENU_FREE_DELAY 1000
204 static unsigned menu_free_timer
= 0;
207 static int image_cache_refcount
, dpyinfo_refcount
;
210 static HWND w32_visible_system_caret_hwnd
;
212 static int w32_unicode_gui
;
215 extern HMENU current_popup_menu
;
216 int menubar_in_use
= 0;
218 /* From w32uniscribe.c */
219 extern void syms_of_w32uniscribe (void);
220 extern int uniscribe_available
;
223 /* From w32inevt.c */
224 extern int faked_key
;
225 #endif /* WINDOWSNT */
227 /* This gives us the page size and the size of the allocation unit on NT. */
228 SYSTEM_INFO sysinfo_cache
;
230 /* This gives us version, build, and platform identification. */
231 OSVERSIONINFO osinfo_cache
;
233 DWORD_PTR syspage_mask
= 0;
235 /* The major and minor versions of NT. */
236 int w32_major_version
;
237 int w32_minor_version
;
238 int w32_build_number
;
240 /* Distinguish between Windows NT and Windows 95. */
244 HINSTANCE hinst
= NULL
;
247 static unsigned int sound_type
= 0xFFFFFFFF;
248 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
250 /* Let the user specify a display with a frame.
251 nil stands for the selected frame--or, if that is not a w32 frame,
252 the first display on the list. */
254 struct w32_display_info
*
255 check_x_display_info (Lisp_Object object
)
259 struct frame
*sf
= XFRAME (selected_frame
);
261 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
262 return FRAME_DISPLAY_INFO (sf
);
264 return &one_w32_display_info
;
266 else if (TERMINALP (object
))
268 struct terminal
*t
= decode_live_terminal (object
);
270 if (t
->type
!= output_w32
)
271 error ("Terminal %d is not a W32 display", t
->id
);
273 return t
->display_info
.w32
;
275 else if (STRINGP (object
))
276 return x_display_info_for_name (object
);
281 CHECK_LIVE_FRAME (object
);
283 if (! FRAME_W32_P (f
))
284 error ("Non-W32 frame used");
285 return FRAME_DISPLAY_INFO (f
);
289 /* Return the Emacs frame-object corresponding to an w32 window.
290 It could be the frame's main window or an icon window. */
293 x_window_to_frame (struct w32_display_info
*dpyinfo
, HWND wdesc
)
295 Lisp_Object tail
, frame
;
298 FOR_EACH_FRAME (tail
, frame
)
301 if (!FRAME_W32_P (f
) || FRAME_DISPLAY_INFO (f
) != dpyinfo
)
304 if (FRAME_W32_WINDOW (f
) == wdesc
)
311 static Lisp_Object
unwind_create_frame (Lisp_Object
);
312 static void unwind_create_tip_frame (Lisp_Object
);
313 static void my_create_window (struct frame
*);
314 static void my_create_tip_window (struct frame
*);
316 /* TODO: Native Input Method support; see x_create_im. */
317 void x_set_foreground_color (struct frame
*, Lisp_Object
, Lisp_Object
);
318 void x_set_background_color (struct frame
*, Lisp_Object
, Lisp_Object
);
319 void x_set_mouse_color (struct frame
*, Lisp_Object
, Lisp_Object
);
320 void x_set_cursor_color (struct frame
*, Lisp_Object
, Lisp_Object
);
321 void x_set_border_color (struct frame
*, Lisp_Object
, Lisp_Object
);
322 void x_set_cursor_type (struct frame
*, Lisp_Object
, Lisp_Object
);
323 void x_set_icon_type (struct frame
*, Lisp_Object
, Lisp_Object
);
324 void x_set_icon_name (struct frame
*, Lisp_Object
, Lisp_Object
);
325 void x_explicitly_set_name (struct frame
*, Lisp_Object
, Lisp_Object
);
326 void x_set_menu_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
327 void x_set_title (struct frame
*, Lisp_Object
, Lisp_Object
);
328 void x_set_tool_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
329 void x_set_internal_border_width (struct frame
*f
, Lisp_Object
, Lisp_Object
);
332 /* Store the screen positions of frame F into XPTR and YPTR.
333 These are the positions of the containing window manager window,
334 not Emacs's own window. */
337 x_real_positions (struct frame
*f
, int *xptr
, int *yptr
)
342 /* Get the bounds of the WM window. */
343 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
348 /* Convert (0, 0) in the client area to screen co-ordinates. */
349 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
355 /* Returns the window rectangle appropriate for the given fullscreen mode.
356 The normal rect parameter was the window's rectangle prior to entering
357 fullscreen mode. If multiple monitor support is available, the nearest
358 monitor to the window is chosen. */
361 w32_fullscreen_rect (HWND hwnd
, int fsmode
, RECT normal
, RECT
*rect
)
363 struct MONITOR_INFO mi
= { sizeof(mi
) };
364 if (monitor_from_window_fn
&& get_monitor_info_fn
)
367 monitor_from_window_fn (hwnd
, MONITOR_DEFAULT_TO_NEAREST
);
368 get_monitor_info_fn (monitor
, &mi
);
372 mi
.rcMonitor
.left
= 0;
373 mi
.rcMonitor
.top
= 0;
374 mi
.rcMonitor
.right
= GetSystemMetrics (SM_CXSCREEN
);
375 mi
.rcMonitor
.bottom
= GetSystemMetrics (SM_CYSCREEN
);
378 mi
.rcWork
.right
= GetSystemMetrics (SM_CXMAXIMIZED
);
379 mi
.rcWork
.bottom
= GetSystemMetrics (SM_CYMAXIMIZED
);
384 case FULLSCREEN_BOTH
:
385 rect
->left
= mi
.rcMonitor
.left
;
386 rect
->top
= mi
.rcMonitor
.top
;
387 rect
->right
= mi
.rcMonitor
.right
;
388 rect
->bottom
= mi
.rcMonitor
.bottom
;
390 case FULLSCREEN_WIDTH
:
391 rect
->left
= mi
.rcWork
.left
;
392 rect
->top
= normal
.top
;
393 rect
->right
= mi
.rcWork
.right
;
394 rect
->bottom
= normal
.bottom
;
396 case FULLSCREEN_HEIGHT
:
397 rect
->left
= normal
.left
;
398 rect
->top
= mi
.rcWork
.top
;
399 rect
->right
= normal
.right
;
400 rect
->bottom
= mi
.rcWork
.bottom
;
410 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
,
411 Sw32_define_rgb_color
, 4, 4, 0,
412 doc
: /* Convert RGB numbers to a Windows color reference and associate with NAME.
413 This adds or updates a named color to `w32-color-map', making it
414 available for use. The original entry's RGB ref is returned, or nil
415 if the entry is new. */)
416 (Lisp_Object red
, Lisp_Object green
, Lisp_Object blue
, Lisp_Object name
)
419 Lisp_Object oldrgb
= Qnil
;
423 CHECK_NUMBER (green
);
427 XSETINT (rgb
, RGB (XUINT (red
), XUINT (green
), XUINT (blue
)));
431 /* replace existing entry in w32-color-map or add new entry. */
432 entry
= Fassoc (name
, Vw32_color_map
);
435 entry
= Fcons (name
, rgb
);
436 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
440 oldrgb
= Fcdr (entry
);
441 Fsetcdr (entry
, rgb
);
449 /* The default colors for the w32 color map */
450 typedef struct colormap_t
456 colormap_t w32_color_map
[] =
458 {"snow" , PALETTERGB (255,250,250)},
459 {"ghost white" , PALETTERGB (248,248,255)},
460 {"GhostWhite" , PALETTERGB (248,248,255)},
461 {"white smoke" , PALETTERGB (245,245,245)},
462 {"WhiteSmoke" , PALETTERGB (245,245,245)},
463 {"gainsboro" , PALETTERGB (220,220,220)},
464 {"floral white" , PALETTERGB (255,250,240)},
465 {"FloralWhite" , PALETTERGB (255,250,240)},
466 {"old lace" , PALETTERGB (253,245,230)},
467 {"OldLace" , PALETTERGB (253,245,230)},
468 {"linen" , PALETTERGB (250,240,230)},
469 {"antique white" , PALETTERGB (250,235,215)},
470 {"AntiqueWhite" , PALETTERGB (250,235,215)},
471 {"papaya whip" , PALETTERGB (255,239,213)},
472 {"PapayaWhip" , PALETTERGB (255,239,213)},
473 {"blanched almond" , PALETTERGB (255,235,205)},
474 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
475 {"bisque" , PALETTERGB (255,228,196)},
476 {"peach puff" , PALETTERGB (255,218,185)},
477 {"PeachPuff" , PALETTERGB (255,218,185)},
478 {"navajo white" , PALETTERGB (255,222,173)},
479 {"NavajoWhite" , PALETTERGB (255,222,173)},
480 {"moccasin" , PALETTERGB (255,228,181)},
481 {"cornsilk" , PALETTERGB (255,248,220)},
482 {"ivory" , PALETTERGB (255,255,240)},
483 {"lemon chiffon" , PALETTERGB (255,250,205)},
484 {"LemonChiffon" , PALETTERGB (255,250,205)},
485 {"seashell" , PALETTERGB (255,245,238)},
486 {"honeydew" , PALETTERGB (240,255,240)},
487 {"mint cream" , PALETTERGB (245,255,250)},
488 {"MintCream" , PALETTERGB (245,255,250)},
489 {"azure" , PALETTERGB (240,255,255)},
490 {"alice blue" , PALETTERGB (240,248,255)},
491 {"AliceBlue" , PALETTERGB (240,248,255)},
492 {"lavender" , PALETTERGB (230,230,250)},
493 {"lavender blush" , PALETTERGB (255,240,245)},
494 {"LavenderBlush" , PALETTERGB (255,240,245)},
495 {"misty rose" , PALETTERGB (255,228,225)},
496 {"MistyRose" , PALETTERGB (255,228,225)},
497 {"white" , PALETTERGB (255,255,255)},
498 {"black" , PALETTERGB ( 0, 0, 0)},
499 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
500 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
501 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
502 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
503 {"dim gray" , PALETTERGB (105,105,105)},
504 {"DimGray" , PALETTERGB (105,105,105)},
505 {"dim grey" , PALETTERGB (105,105,105)},
506 {"DimGrey" , PALETTERGB (105,105,105)},
507 {"slate gray" , PALETTERGB (112,128,144)},
508 {"SlateGray" , PALETTERGB (112,128,144)},
509 {"slate grey" , PALETTERGB (112,128,144)},
510 {"SlateGrey" , PALETTERGB (112,128,144)},
511 {"light slate gray" , PALETTERGB (119,136,153)},
512 {"LightSlateGray" , PALETTERGB (119,136,153)},
513 {"light slate grey" , PALETTERGB (119,136,153)},
514 {"LightSlateGrey" , PALETTERGB (119,136,153)},
515 {"gray" , PALETTERGB (190,190,190)},
516 {"grey" , PALETTERGB (190,190,190)},
517 {"light grey" , PALETTERGB (211,211,211)},
518 {"LightGrey" , PALETTERGB (211,211,211)},
519 {"light gray" , PALETTERGB (211,211,211)},
520 {"LightGray" , PALETTERGB (211,211,211)},
521 {"midnight blue" , PALETTERGB ( 25, 25,112)},
522 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
523 {"navy" , PALETTERGB ( 0, 0,128)},
524 {"navy blue" , PALETTERGB ( 0, 0,128)},
525 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
526 {"cornflower blue" , PALETTERGB (100,149,237)},
527 {"CornflowerBlue" , PALETTERGB (100,149,237)},
528 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
529 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
530 {"slate blue" , PALETTERGB (106, 90,205)},
531 {"SlateBlue" , PALETTERGB (106, 90,205)},
532 {"medium slate blue" , PALETTERGB (123,104,238)},
533 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
534 {"light slate blue" , PALETTERGB (132,112,255)},
535 {"LightSlateBlue" , PALETTERGB (132,112,255)},
536 {"medium blue" , PALETTERGB ( 0, 0,205)},
537 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
538 {"royal blue" , PALETTERGB ( 65,105,225)},
539 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
540 {"blue" , PALETTERGB ( 0, 0,255)},
541 {"dodger blue" , PALETTERGB ( 30,144,255)},
542 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
543 {"deep sky blue" , PALETTERGB ( 0,191,255)},
544 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
545 {"sky blue" , PALETTERGB (135,206,235)},
546 {"SkyBlue" , PALETTERGB (135,206,235)},
547 {"light sky blue" , PALETTERGB (135,206,250)},
548 {"LightSkyBlue" , PALETTERGB (135,206,250)},
549 {"steel blue" , PALETTERGB ( 70,130,180)},
550 {"SteelBlue" , PALETTERGB ( 70,130,180)},
551 {"light steel blue" , PALETTERGB (176,196,222)},
552 {"LightSteelBlue" , PALETTERGB (176,196,222)},
553 {"light blue" , PALETTERGB (173,216,230)},
554 {"LightBlue" , PALETTERGB (173,216,230)},
555 {"powder blue" , PALETTERGB (176,224,230)},
556 {"PowderBlue" , PALETTERGB (176,224,230)},
557 {"pale turquoise" , PALETTERGB (175,238,238)},
558 {"PaleTurquoise" , PALETTERGB (175,238,238)},
559 {"dark turquoise" , PALETTERGB ( 0,206,209)},
560 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
561 {"medium turquoise" , PALETTERGB ( 72,209,204)},
562 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
563 {"turquoise" , PALETTERGB ( 64,224,208)},
564 {"cyan" , PALETTERGB ( 0,255,255)},
565 {"light cyan" , PALETTERGB (224,255,255)},
566 {"LightCyan" , PALETTERGB (224,255,255)},
567 {"cadet blue" , PALETTERGB ( 95,158,160)},
568 {"CadetBlue" , PALETTERGB ( 95,158,160)},
569 {"medium aquamarine" , PALETTERGB (102,205,170)},
570 {"MediumAquamarine" , PALETTERGB (102,205,170)},
571 {"aquamarine" , PALETTERGB (127,255,212)},
572 {"dark green" , PALETTERGB ( 0,100, 0)},
573 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
574 {"dark olive green" , PALETTERGB ( 85,107, 47)},
575 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
576 {"dark sea green" , PALETTERGB (143,188,143)},
577 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
578 {"sea green" , PALETTERGB ( 46,139, 87)},
579 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
580 {"medium sea green" , PALETTERGB ( 60,179,113)},
581 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
582 {"light sea green" , PALETTERGB ( 32,178,170)},
583 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
584 {"pale green" , PALETTERGB (152,251,152)},
585 {"PaleGreen" , PALETTERGB (152,251,152)},
586 {"spring green" , PALETTERGB ( 0,255,127)},
587 {"SpringGreen" , PALETTERGB ( 0,255,127)},
588 {"lawn green" , PALETTERGB (124,252, 0)},
589 {"LawnGreen" , PALETTERGB (124,252, 0)},
590 {"green" , PALETTERGB ( 0,255, 0)},
591 {"chartreuse" , PALETTERGB (127,255, 0)},
592 {"medium spring green" , PALETTERGB ( 0,250,154)},
593 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
594 {"green yellow" , PALETTERGB (173,255, 47)},
595 {"GreenYellow" , PALETTERGB (173,255, 47)},
596 {"lime green" , PALETTERGB ( 50,205, 50)},
597 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
598 {"yellow green" , PALETTERGB (154,205, 50)},
599 {"YellowGreen" , PALETTERGB (154,205, 50)},
600 {"forest green" , PALETTERGB ( 34,139, 34)},
601 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
602 {"olive drab" , PALETTERGB (107,142, 35)},
603 {"OliveDrab" , PALETTERGB (107,142, 35)},
604 {"dark khaki" , PALETTERGB (189,183,107)},
605 {"DarkKhaki" , PALETTERGB (189,183,107)},
606 {"khaki" , PALETTERGB (240,230,140)},
607 {"pale goldenrod" , PALETTERGB (238,232,170)},
608 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
609 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
610 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
611 {"light yellow" , PALETTERGB (255,255,224)},
612 {"LightYellow" , PALETTERGB (255,255,224)},
613 {"yellow" , PALETTERGB (255,255, 0)},
614 {"gold" , PALETTERGB (255,215, 0)},
615 {"light goldenrod" , PALETTERGB (238,221,130)},
616 {"LightGoldenrod" , PALETTERGB (238,221,130)},
617 {"goldenrod" , PALETTERGB (218,165, 32)},
618 {"dark goldenrod" , PALETTERGB (184,134, 11)},
619 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
620 {"rosy brown" , PALETTERGB (188,143,143)},
621 {"RosyBrown" , PALETTERGB (188,143,143)},
622 {"indian red" , PALETTERGB (205, 92, 92)},
623 {"IndianRed" , PALETTERGB (205, 92, 92)},
624 {"saddle brown" , PALETTERGB (139, 69, 19)},
625 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
626 {"sienna" , PALETTERGB (160, 82, 45)},
627 {"peru" , PALETTERGB (205,133, 63)},
628 {"burlywood" , PALETTERGB (222,184,135)},
629 {"beige" , PALETTERGB (245,245,220)},
630 {"wheat" , PALETTERGB (245,222,179)},
631 {"sandy brown" , PALETTERGB (244,164, 96)},
632 {"SandyBrown" , PALETTERGB (244,164, 96)},
633 {"tan" , PALETTERGB (210,180,140)},
634 {"chocolate" , PALETTERGB (210,105, 30)},
635 {"firebrick" , PALETTERGB (178,34, 34)},
636 {"brown" , PALETTERGB (165,42, 42)},
637 {"dark salmon" , PALETTERGB (233,150,122)},
638 {"DarkSalmon" , PALETTERGB (233,150,122)},
639 {"salmon" , PALETTERGB (250,128,114)},
640 {"light salmon" , PALETTERGB (255,160,122)},
641 {"LightSalmon" , PALETTERGB (255,160,122)},
642 {"orange" , PALETTERGB (255,165, 0)},
643 {"dark orange" , PALETTERGB (255,140, 0)},
644 {"DarkOrange" , PALETTERGB (255,140, 0)},
645 {"coral" , PALETTERGB (255,127, 80)},
646 {"light coral" , PALETTERGB (240,128,128)},
647 {"LightCoral" , PALETTERGB (240,128,128)},
648 {"tomato" , PALETTERGB (255, 99, 71)},
649 {"orange red" , PALETTERGB (255, 69, 0)},
650 {"OrangeRed" , PALETTERGB (255, 69, 0)},
651 {"red" , PALETTERGB (255, 0, 0)},
652 {"hot pink" , PALETTERGB (255,105,180)},
653 {"HotPink" , PALETTERGB (255,105,180)},
654 {"deep pink" , PALETTERGB (255, 20,147)},
655 {"DeepPink" , PALETTERGB (255, 20,147)},
656 {"pink" , PALETTERGB (255,192,203)},
657 {"light pink" , PALETTERGB (255,182,193)},
658 {"LightPink" , PALETTERGB (255,182,193)},
659 {"pale violet red" , PALETTERGB (219,112,147)},
660 {"PaleVioletRed" , PALETTERGB (219,112,147)},
661 {"maroon" , PALETTERGB (176, 48, 96)},
662 {"medium violet red" , PALETTERGB (199, 21,133)},
663 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
664 {"violet red" , PALETTERGB (208, 32,144)},
665 {"VioletRed" , PALETTERGB (208, 32,144)},
666 {"magenta" , PALETTERGB (255, 0,255)},
667 {"violet" , PALETTERGB (238,130,238)},
668 {"plum" , PALETTERGB (221,160,221)},
669 {"orchid" , PALETTERGB (218,112,214)},
670 {"medium orchid" , PALETTERGB (186, 85,211)},
671 {"MediumOrchid" , PALETTERGB (186, 85,211)},
672 {"dark orchid" , PALETTERGB (153, 50,204)},
673 {"DarkOrchid" , PALETTERGB (153, 50,204)},
674 {"dark violet" , PALETTERGB (148, 0,211)},
675 {"DarkViolet" , PALETTERGB (148, 0,211)},
676 {"blue violet" , PALETTERGB (138, 43,226)},
677 {"BlueViolet" , PALETTERGB (138, 43,226)},
678 {"purple" , PALETTERGB (160, 32,240)},
679 {"medium purple" , PALETTERGB (147,112,219)},
680 {"MediumPurple" , PALETTERGB (147,112,219)},
681 {"thistle" , PALETTERGB (216,191,216)},
682 {"gray0" , PALETTERGB ( 0, 0, 0)},
683 {"grey0" , PALETTERGB ( 0, 0, 0)},
684 {"dark grey" , PALETTERGB (169,169,169)},
685 {"DarkGrey" , PALETTERGB (169,169,169)},
686 {"dark gray" , PALETTERGB (169,169,169)},
687 {"DarkGray" , PALETTERGB (169,169,169)},
688 {"dark blue" , PALETTERGB ( 0, 0,139)},
689 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
690 {"dark cyan" , PALETTERGB ( 0,139,139)},
691 {"DarkCyan" , PALETTERGB ( 0,139,139)},
692 {"dark magenta" , PALETTERGB (139, 0,139)},
693 {"DarkMagenta" , PALETTERGB (139, 0,139)},
694 {"dark red" , PALETTERGB (139, 0, 0)},
695 {"DarkRed" , PALETTERGB (139, 0, 0)},
696 {"light green" , PALETTERGB (144,238,144)},
697 {"LightGreen" , PALETTERGB (144,238,144)},
701 w32_default_color_map (void)
704 colormap_t
*pc
= w32_color_map
;
711 for (i
= 0; i
< ARRAYELTS (w32_color_map
); pc
++, i
++)
712 cmap
= Fcons (Fcons (build_string (pc
->name
),
713 make_number (pc
->colorref
)),
721 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
722 0, 0, 0, doc
: /* Return the default color map. */)
725 return w32_default_color_map ();
729 w32_color_map_lookup (const char *colorname
)
731 Lisp_Object tail
, ret
= Qnil
;
735 for (tail
= Vw32_color_map
; CONSP (tail
); tail
= XCDR (tail
))
737 register Lisp_Object elt
, tem
;
740 if (!CONSP (elt
)) continue;
744 if (lstrcmpi (SDATA (tem
), colorname
) == 0)
760 add_system_logical_colors_to_map (Lisp_Object
*system_colors
)
764 /* Other registry operations are done with input blocked. */
767 /* Look for "Control Panel/Colors" under User and Machine registry
769 if (RegOpenKeyEx (HKEY_CURRENT_USER
, "Control Panel\\Colors", 0,
770 KEY_READ
, &colors_key
) == ERROR_SUCCESS
771 || RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Control Panel\\Colors", 0,
772 KEY_READ
, &colors_key
) == ERROR_SUCCESS
)
775 char color_buffer
[64];
776 char full_name_buffer
[MAX_PATH
+ SYSTEM_COLOR_PREFIX_LEN
];
778 DWORD name_size
, color_size
;
779 char *name_buffer
= full_name_buffer
+ SYSTEM_COLOR_PREFIX_LEN
;
781 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
782 color_size
= sizeof (color_buffer
);
784 strcpy (full_name_buffer
, SYSTEM_COLOR_PREFIX
);
786 while (RegEnumValueA (colors_key
, index
, name_buffer
, &name_size
,
787 NULL
, NULL
, color_buffer
, &color_size
)
791 if (sscanf (color_buffer
, " %u %u %u", &r
, &g
, &b
) == 3)
792 *system_colors
= Fcons (Fcons (build_string (full_name_buffer
),
793 make_number (RGB (r
, g
, b
))),
796 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
797 color_size
= sizeof (color_buffer
);
800 RegCloseKey (colors_key
);
808 x_to_w32_color (const char * colorname
)
810 register Lisp_Object ret
= Qnil
;
814 if (colorname
[0] == '#')
816 /* Could be an old-style RGB Device specification. */
817 int size
= strlen (colorname
+ 1);
818 char *color
= alloca (size
+ 1);
820 strcpy (color
, colorname
+ 1);
821 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
829 for (i
= 0; i
< 3; i
++)
835 /* The check for 'x' in the following conditional takes into
836 account the fact that strtol allows a "0x" in front of
837 our numbers, and we don't. */
838 if (!isxdigit (color
[0]) || color
[1] == 'x')
842 value
= strtoul (color
, &end
, 16);
844 if (errno
== ERANGE
|| end
- color
!= size
)
849 value
= value
* 0x10;
860 colorval
|= (value
<< pos
);
865 XSETINT (ret
, colorval
);
872 else if (strnicmp (colorname
, "rgb:", 4) == 0)
880 color
= colorname
+ 4;
881 for (i
= 0; i
< 3; i
++)
886 /* The check for 'x' in the following conditional takes into
887 account the fact that strtol allows a "0x" in front of
888 our numbers, and we don't. */
889 if (!isxdigit (color
[0]) || color
[1] == 'x')
891 value
= strtoul (color
, &end
, 16);
897 value
= value
* 0x10 + value
;
910 if (value
== ULONG_MAX
)
912 colorval
|= (value
<< pos
);
919 XSETINT (ret
, colorval
);
927 else if (strnicmp (colorname
, "rgbi:", 5) == 0)
929 /* This is an RGB Intensity specification. */
936 color
= colorname
+ 5;
937 for (i
= 0; i
< 3; i
++)
943 value
= strtod (color
, &end
);
946 if (value
< 0.0 || value
> 1.0)
948 val
= (UINT
)(0x100 * value
);
949 /* We used 0x100 instead of 0xFF to give a continuous
950 range between 0.0 and 1.0 inclusive. The next statement
951 fixes the 1.0 case. */
954 colorval
|= (val
<< pos
);
961 XSETINT (ret
, colorval
);
969 /* I am not going to attempt to handle any of the CIE color schemes
970 or TekHVC, since I don't know the algorithms for conversion to
973 /* If we fail to lookup the color name in w32_color_map, then check the
974 colorname to see if it can be crudely approximated: If the X color
975 ends in a number (e.g., "darkseagreen2"), strip the number and
976 return the result of looking up the base color name. */
977 ret
= w32_color_map_lookup (colorname
);
980 int len
= strlen (colorname
);
982 if (isdigit (colorname
[len
- 1]))
984 char *ptr
, *approx
= alloca (len
+ 1);
986 strcpy (approx
, colorname
);
987 ptr
= &approx
[len
- 1];
988 while (ptr
> approx
&& isdigit (*ptr
))
991 ret
= w32_color_map_lookup (approx
);
1000 w32_regenerate_palette (struct frame
*f
)
1002 struct w32_palette_entry
* list
;
1003 LOGPALETTE
* log_palette
;
1004 HPALETTE new_palette
;
1007 /* don't bother trying to create palette if not supported */
1008 if (! FRAME_DISPLAY_INFO (f
)->has_palette
)
1011 log_palette
= (LOGPALETTE
*)
1012 alloca (sizeof (LOGPALETTE
) +
1013 FRAME_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1014 log_palette
->palVersion
= 0x300;
1015 log_palette
->palNumEntries
= FRAME_DISPLAY_INFO (f
)->num_colors
;
1017 list
= FRAME_DISPLAY_INFO (f
)->color_list
;
1019 i
< FRAME_DISPLAY_INFO (f
)->num_colors
;
1020 i
++, list
= list
->next
)
1021 log_palette
->palPalEntry
[i
] = list
->entry
;
1023 new_palette
= CreatePalette (log_palette
);
1027 if (FRAME_DISPLAY_INFO (f
)->palette
)
1028 DeleteObject (FRAME_DISPLAY_INFO (f
)->palette
);
1029 FRAME_DISPLAY_INFO (f
)->palette
= new_palette
;
1031 /* Realize display palette and garbage all frames. */
1032 release_frame_dc (f
, get_frame_dc (f
));
1037 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1038 #define SET_W32_COLOR(pe, color) \
1041 pe.peRed = GetRValue (color); \
1042 pe.peGreen = GetGValue (color); \
1043 pe.peBlue = GetBValue (color); \
1048 /* Keep these around in case we ever want to track color usage. */
1050 w32_map_color (struct frame
*f
, COLORREF color
)
1052 struct w32_palette_entry
* list
= FRAME_DISPLAY_INFO (f
)->color_list
;
1054 if (NILP (Vw32_enable_palette
))
1057 /* check if color is already mapped */
1060 if (W32_COLOR (list
->entry
) == color
)
1068 /* not already mapped, so add to list and recreate Windows palette */
1069 list
= xmalloc (sizeof (struct w32_palette_entry
));
1070 SET_W32_COLOR (list
->entry
, color
);
1072 list
->next
= FRAME_DISPLAY_INFO (f
)->color_list
;
1073 FRAME_DISPLAY_INFO (f
)->color_list
= list
;
1074 FRAME_DISPLAY_INFO (f
)->num_colors
++;
1076 /* set flag that palette must be regenerated */
1077 FRAME_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1081 w32_unmap_color (struct frame
*f
, COLORREF color
)
1083 struct w32_palette_entry
* list
= FRAME_DISPLAY_INFO (f
)->color_list
;
1084 struct w32_palette_entry
**prev
= &FRAME_DISPLAY_INFO (f
)->color_list
;
1086 if (NILP (Vw32_enable_palette
))
1089 /* check if color is already mapped */
1092 if (W32_COLOR (list
->entry
) == color
)
1094 if (--list
->refcount
== 0)
1098 FRAME_DISPLAY_INFO (f
)->num_colors
--;
1108 /* set flag that palette must be regenerated */
1109 FRAME_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1114 /* Gamma-correct COLOR on frame F. */
1117 gamma_correct (struct frame
*f
, COLORREF
*color
)
1121 *color
= PALETTERGB (
1122 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1123 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1124 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1129 /* Decide if color named COLOR is valid for the display associated with
1130 the selected frame; if so, return the rgb values in COLOR_DEF.
1131 If ALLOC is nonzero, allocate a new colormap cell. */
1134 w32_defined_color (struct frame
*f
, const char *color
, XColor
*color_def
,
1137 register Lisp_Object tem
;
1138 COLORREF w32_color_ref
;
1140 tem
= x_to_w32_color (color
);
1146 /* Apply gamma correction. */
1147 w32_color_ref
= XUINT (tem
);
1148 gamma_correct (f
, &w32_color_ref
);
1149 XSETINT (tem
, w32_color_ref
);
1152 /* Map this color to the palette if it is enabled. */
1153 if (!NILP (Vw32_enable_palette
))
1155 struct w32_palette_entry
* entry
=
1156 one_w32_display_info
.color_list
;
1157 struct w32_palette_entry
** prev
=
1158 &one_w32_display_info
.color_list
;
1160 /* check if color is already mapped */
1163 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1165 prev
= &entry
->next
;
1166 entry
= entry
->next
;
1169 if (entry
== NULL
&& alloc_p
)
1171 /* not already mapped, so add to list */
1172 entry
= xmalloc (sizeof (struct w32_palette_entry
));
1173 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1176 one_w32_display_info
.num_colors
++;
1178 /* set flag that palette must be regenerated */
1179 one_w32_display_info
.regen_palette
= TRUE
;
1182 /* Ensure COLORREF value is snapped to nearest color in (default)
1183 palette by simulating the PALETTERGB macro. This works whether
1184 or not the display device has a palette. */
1185 w32_color_ref
= XUINT (tem
) | 0x2000000;
1187 color_def
->pixel
= w32_color_ref
;
1188 color_def
->red
= GetRValue (w32_color_ref
) * 256;
1189 color_def
->green
= GetGValue (w32_color_ref
) * 256;
1190 color_def
->blue
= GetBValue (w32_color_ref
) * 256;
1200 /* Given a string ARG naming a color, compute a pixel value from it
1201 suitable for screen F.
1202 If F is not a color screen, return DEF (default) regardless of what
1206 x_decode_color (struct frame
*f
, Lisp_Object arg
, int def
)
1212 if (strcmp (SDATA (arg
), "black") == 0)
1213 return BLACK_PIX_DEFAULT (f
);
1214 else if (strcmp (SDATA (arg
), "white") == 0)
1215 return WHITE_PIX_DEFAULT (f
);
1217 if ((FRAME_DISPLAY_INFO (f
)->n_planes
* FRAME_DISPLAY_INFO (f
)->n_cbits
) == 1)
1220 /* w32_defined_color is responsible for coping with failures
1221 by looking for a near-miss. */
1222 if (w32_defined_color (f
, SDATA (arg
), &cdef
, true))
1225 /* defined_color failed; return an ultimate default. */
1231 /* Functions called only from `x_set_frame_param'
1232 to set individual parameters.
1234 If FRAME_W32_WINDOW (f) is 0,
1235 the frame is being created and its window does not exist yet.
1236 In that case, just record the parameter's new value
1237 in the standard place; do not attempt to change the window. */
1240 x_set_foreground_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1242 struct w32_output
*x
= f
->output_data
.w32
;
1243 PIX_TYPE fg
, old_fg
;
1245 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1246 old_fg
= FRAME_FOREGROUND_PIXEL (f
);
1247 FRAME_FOREGROUND_PIXEL (f
) = fg
;
1249 if (FRAME_W32_WINDOW (f
) != 0)
1251 if (x
->cursor_pixel
== old_fg
)
1253 x
->cursor_pixel
= fg
;
1254 x
->cursor_gc
->background
= fg
;
1257 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1258 if (FRAME_VISIBLE_P (f
))
1264 x_set_background_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1266 FRAME_BACKGROUND_PIXEL (f
)
1267 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1269 if (FRAME_W32_WINDOW (f
) != 0)
1271 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
1272 FRAME_BACKGROUND_PIXEL (f
));
1274 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1276 if (FRAME_VISIBLE_P (f
))
1282 x_set_mouse_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1284 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
1288 if (!EQ (Qnil
, arg
))
1289 f
->output_data
.w32
->mouse_pixel
1290 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1291 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
1293 /* Don't let pointers be invisible. */
1294 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1295 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
1296 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
1298 #if 0 /* TODO : Mouse cursor customization. */
1301 /* It's not okay to crash if the user selects a screwy cursor. */
1302 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1304 if (!EQ (Qnil
, Vx_pointer_shape
))
1306 CHECK_NUMBER (Vx_pointer_shape
);
1307 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1310 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1311 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1313 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1315 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1316 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1317 XINT (Vx_nontext_pointer_shape
));
1320 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1321 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1323 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
1325 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1326 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1327 XINT (Vx_hourglass_pointer_shape
));
1330 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
1331 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
1333 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1334 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1336 CHECK_NUMBER (Vx_mode_pointer_shape
);
1337 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1338 XINT (Vx_mode_pointer_shape
));
1341 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1342 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1344 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1346 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1348 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1349 XINT (Vx_sensitive_text_pointer_shape
));
1352 hand_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1354 if (!NILP (Vx_window_horizontal_drag_shape
))
1356 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1357 horizontal_drag_cursor
1358 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1359 XINT (Vx_window_horizontal_drag_shape
));
1362 horizontal_drag_cursor
1363 = XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_sb_h_double_arrow
);
1365 if (!NILP (Vx_window_vertical_drag_shape
))
1367 CHECK_NUMBER (Vx_window_vertical_drag_shape
);
1368 vertical_drag_cursor
1369 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1370 XINT (Vx_window_vertical_drag_shape
));
1373 vertical_drag_cursor
1374 = XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_sb_v_double_arrow
);
1376 /* Check and report errors with the above calls. */
1377 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1378 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1381 XColor fore_color
, back_color
;
1383 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1384 back_color
.pixel
= mask_color
;
1385 XQueryColor (FRAME_W32_DISPLAY (f
),
1386 DefaultColormap (FRAME_W32_DISPLAY (f
),
1387 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1389 XQueryColor (FRAME_W32_DISPLAY (f
),
1390 DefaultColormap (FRAME_W32_DISPLAY (f
),
1391 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1393 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1394 &fore_color
, &back_color
);
1395 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1396 &fore_color
, &back_color
);
1397 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1398 &fore_color
, &back_color
);
1399 XRecolorCursor (FRAME_W32_DISPLAY (f
), hand_cursor
,
1400 &fore_color
, &back_color
);
1401 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
1402 &fore_color
, &back_color
);
1405 if (FRAME_W32_WINDOW (f
) != 0)
1406 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1408 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1409 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1410 f
->output_data
.w32
->text_cursor
= cursor
;
1412 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1413 && f
->output_data
.w32
->nontext_cursor
!= 0)
1414 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1415 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1417 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
1418 && f
->output_data
.w32
->hourglass_cursor
!= 0)
1419 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
1420 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
1422 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1423 && f
->output_data
.w32
->modeline_cursor
!= 0)
1424 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1425 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1427 if (hand_cursor
!= f
->output_data
.w32
->hand_cursor
1428 && f
->output_data
.w32
->hand_cursor
!= 0)
1429 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hand_cursor
);
1430 f
->output_data
.w32
->hand_cursor
= hand_cursor
;
1432 XFlush (FRAME_W32_DISPLAY (f
));
1435 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1440 x_set_cursor_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1442 unsigned long fore_pixel
, pixel
;
1444 if (!NILP (Vx_cursor_fore_pixel
))
1445 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1446 WHITE_PIX_DEFAULT (f
));
1448 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1450 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1452 /* Make sure that the cursor color differs from the background color. */
1453 if (pixel
== FRAME_BACKGROUND_PIXEL (f
))
1455 pixel
= f
->output_data
.w32
->mouse_pixel
;
1456 if (pixel
== fore_pixel
)
1457 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1460 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1461 f
->output_data
.w32
->cursor_pixel
= pixel
;
1463 if (FRAME_W32_WINDOW (f
) != 0)
1466 /* Update frame's cursor_gc. */
1467 f
->output_data
.w32
->cursor_gc
->foreground
= fore_pixel
;
1468 f
->output_data
.w32
->cursor_gc
->background
= pixel
;
1472 if (FRAME_VISIBLE_P (f
))
1474 x_update_cursor (f
, 0);
1475 x_update_cursor (f
, 1);
1479 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1482 /* Set the border-color of frame F to pixel value PIX.
1483 Note that this does not fully take effect if done before
1487 x_set_border_pixel (struct frame
*f
, int pix
)
1490 f
->output_data
.w32
->border_pixel
= pix
;
1492 if (FRAME_W32_WINDOW (f
) != 0 && f
->border_width
> 0)
1494 if (FRAME_VISIBLE_P (f
))
1499 /* Set the border-color of frame F to value described by ARG.
1500 ARG can be a string naming a color.
1501 The border-color is used for the border that is drawn by the server.
1502 Note that this does not fully take effect if done before
1503 F has a window; it must be redone when the window is created. */
1506 x_set_border_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1511 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1512 x_set_border_pixel (f
, pix
);
1513 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1518 x_set_cursor_type (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1520 set_frame_cursor_types (f
, arg
);
1524 x_set_icon_type (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1528 if (NILP (arg
) && NILP (oldval
))
1531 if (STRINGP (arg
) && STRINGP (oldval
)
1532 && EQ (Fstring_equal (oldval
, arg
), Qt
))
1535 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
1540 result
= x_bitmap_icon (f
, arg
);
1544 error ("No icon window available");
1551 x_set_icon_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1555 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1558 else if (!NILP (arg
) || NILP (oldval
))
1561 fset_icon_name (f
, arg
);
1564 if (f
->output_data
.w32
->icon_bitmap
!= 0)
1569 result
= x_text_icon (f
,
1570 SSDATA ((!NILP (f
->icon_name
)
1579 error ("No icon window available");
1582 /* If the window was unmapped (and its icon was mapped),
1583 the new icon is not mapped, so map the window in its stead. */
1584 if (FRAME_VISIBLE_P (f
))
1586 #ifdef USE_X_TOOLKIT
1587 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1589 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1592 XFlush (FRAME_W32_DISPLAY (f
));
1598 x_clear_under_internal_border (struct frame
*f
)
1600 int border
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1602 /* Clear border if it's larger than before. */
1605 HDC hdc
= get_frame_dc (f
);
1606 int width
= FRAME_PIXEL_WIDTH (f
);
1607 int height
= FRAME_PIXEL_HEIGHT (f
);
1610 w32_clear_area (f
, hdc
, 0, FRAME_TOP_MARGIN_HEIGHT (f
), width
, border
);
1611 w32_clear_area (f
, hdc
, 0, 0, border
, height
);
1612 w32_clear_area (f
, hdc
, width
- border
, 0, border
, height
);
1613 w32_clear_area (f
, hdc
, 0, height
- border
, width
, border
);
1614 release_frame_dc (f
, hdc
);
1621 x_set_internal_border_width (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1625 CHECK_TYPE_RANGED_INTEGER (int, arg
);
1626 border
= max (XINT (arg
), 0);
1628 if (border
!= FRAME_INTERNAL_BORDER_WIDTH (f
))
1630 FRAME_INTERNAL_BORDER_WIDTH (f
) = border
;
1632 if (FRAME_X_WINDOW (f
) != 0)
1634 adjust_frame_size (f
, -1, -1, 3, false, Qinternal_border_width
);
1636 if (FRAME_VISIBLE_P (f
))
1637 x_clear_under_internal_border (f
);
1644 x_set_menu_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1648 /* Right now, menu bars don't work properly in minibuf-only frames;
1649 most of the commands try to apply themselves to the minibuffer
1650 frame itself, and get an error because you can't switch buffers
1651 in or split the minibuffer window. */
1652 if (FRAME_MINIBUF_ONLY_P (f
))
1655 if (INTEGERP (value
))
1656 nlines
= XINT (value
);
1660 FRAME_MENU_BAR_LINES (f
) = 0;
1661 FRAME_MENU_BAR_HEIGHT (f
) = 0;
1664 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1665 windows_or_buffers_changed
= 23;
1669 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1670 free_frame_menubar (f
);
1671 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1673 /* Adjust the frame size so that the client (text) dimensions
1674 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1675 set correctly. Note that we resize twice: The first time upon
1676 a request from the window manager who wants to keep the height
1677 of the outer rectangle (including decorations) unchanged, and a
1678 second time because we want to keep the height of the inner
1679 rectangle (without the decorations unchanged). */
1680 adjust_frame_size (f
, -1, -1, 2, true, Qmenu_bar_lines
);
1682 /* Not sure whether this is needed. */
1683 x_clear_under_internal_border (f
);
1688 /* Set the number of lines used for the tool bar of frame F to VALUE.
1689 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL is
1690 the old number of tool bar lines (and is unused). This function may
1691 change the height of all windows on frame F to match the new tool bar
1692 height. By design, the frame's height doesn't change (but maybe it
1693 should if we don't get enough space otherwise). */
1696 x_set_tool_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1700 /* Treat tool bars like menu bars. */
1701 if (FRAME_MINIBUF_ONLY_P (f
))
1704 /* Use VALUE only if an integer >= 0. */
1705 if (INTEGERP (value
) && XINT (value
) >= 0)
1706 nlines
= XFASTINT (value
);
1710 x_change_tool_bar_height (f
, nlines
* FRAME_LINE_HEIGHT (f
));
1714 /* Set the pixel height of the tool bar of frame F to HEIGHT. */
1716 x_change_tool_bar_height (struct frame
*f
, int height
)
1719 int unit
= FRAME_LINE_HEIGHT (f
);
1720 int old_height
= FRAME_TOOL_BAR_HEIGHT (f
);
1721 int lines
= (height
+ unit
- 1) / unit
;
1722 int old_text_height
= FRAME_TEXT_HEIGHT (f
);
1723 Lisp_Object fullscreen
;
1725 /* Make sure we redisplay all windows in this frame. */
1726 windows_or_buffers_changed
= 23;
1728 /* Recalculate tool bar and frame text sizes. */
1729 FRAME_TOOL_BAR_HEIGHT (f
) = height
;
1730 FRAME_TOOL_BAR_LINES (f
) = lines
;
1731 /* Store `tool-bar-lines' and `height' frame parameters. */
1732 store_frame_param (f
, Qtool_bar_lines
, make_number (lines
));
1733 store_frame_param (f
, Qheight
, make_number (FRAME_LINES (f
)));
1735 if (FRAME_W32_WINDOW (f
) && FRAME_TOOL_BAR_HEIGHT (f
) == 0)
1738 clear_current_matrices (f
);
1741 if ((height
< old_height
) && WINDOWP (f
->tool_bar_window
))
1742 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
1744 /* Recalculate toolbar height. */
1745 f
->n_tool_bar_rows
= 0;
1747 adjust_frame_size (f
, -1, -1,
1748 ((!f
->tool_bar_redisplayed_once
1749 && (NILP (fullscreen
=
1750 get_frame_param (f
, Qfullscreen
))
1751 || EQ (fullscreen
, Qfullwidth
))) ? 1
1752 : (old_height
== 0 || height
== 0) ? 2
1754 false, Qtool_bar_lines
);
1756 /* adjust_frame_size might not have done anything, garbage frame
1758 adjust_frame_glyphs (f
);
1759 SET_FRAME_GARBAGED (f
);
1760 if (FRAME_X_WINDOW (f
))
1761 x_clear_under_internal_border (f
);
1765 w32_set_title_bar_text (struct frame
*f
, Lisp_Object name
)
1767 if (FRAME_W32_WINDOW (f
))
1771 GUI_FN (SetWindowText
) (FRAME_W32_WINDOW (f
),
1772 GUI_SDATA (GUI_ENCODE_SYSTEM (name
)));
1774 /* The frame's title many times shows the name of the file
1775 visited in the selected window's buffer, so it makes sense to
1776 support non-ASCII characters outside of the current system
1777 codepage in the title. */
1778 if (w32_unicode_filenames
)
1780 Lisp_Object encoded_title
= ENCODE_UTF_8 (name
);
1782 int tlen
= pMultiByteToWideChar (CP_UTF8
, 0, SSDATA (encoded_title
),
1787 /* Windows truncates the title text beyond what fits on
1788 a single line, so we can limit the length to some
1789 reasonably large value, and use alloca. */
1792 title_w
= alloca ((tlen
+ 1) * sizeof (wchar_t));
1793 pMultiByteToWideChar (CP_UTF8
, 0, SSDATA (encoded_title
), -1,
1795 title_w
[tlen
] = L
'\0';
1796 SetWindowTextW (FRAME_W32_WINDOW (f
), title_w
);
1798 else /* Conversion to UTF-16 failed, so we punt. */
1799 SetWindowTextA (FRAME_W32_WINDOW (f
),
1800 SSDATA (ENCODE_SYSTEM (name
)));
1803 SetWindowTextA (FRAME_W32_WINDOW (f
), SSDATA (ENCODE_SYSTEM (name
)));
1809 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1812 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1813 name; if NAME is a string, set F's name to NAME and set
1814 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1816 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1817 suggesting a new name, which lisp code should override; if
1818 F->explicit_name is set, ignore the new name; otherwise, set it. */
1821 x_set_name (struct frame
*f
, Lisp_Object name
, bool explicit)
1823 /* Make sure that requests from lisp code override requests from
1824 Emacs redisplay code. */
1827 /* If we're switching from explicit to implicit, we had better
1828 update the mode lines and thereby update the title. */
1829 if (f
->explicit_name
&& NILP (name
))
1830 update_mode_lines
= 25;
1832 f
->explicit_name
= ! NILP (name
);
1834 else if (f
->explicit_name
)
1837 /* If NAME is nil, set the name to the w32_id_name. */
1840 /* Check for no change needed in this very common case
1841 before we do any consing. */
1842 if (!strcmp (FRAME_DISPLAY_INFO (f
)->w32_id_name
,
1845 name
= build_string (FRAME_DISPLAY_INFO (f
)->w32_id_name
);
1848 CHECK_STRING (name
);
1850 /* Don't change the name if it's already NAME. */
1851 if (! NILP (Fstring_equal (name
, f
->name
)))
1854 fset_name (f
, name
);
1856 /* For setting the frame title, the title parameter should override
1857 the name parameter. */
1858 if (! NILP (f
->title
))
1861 w32_set_title_bar_text (f
, name
);
1864 /* This function should be called when the user's lisp code has
1865 specified a name for the frame; the name will override any set by the
1868 x_explicitly_set_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1870 x_set_name (f
, arg
, true);
1873 /* This function should be called by Emacs redisplay code to set the
1874 name; names set this way will never override names set by the user's
1877 x_implicitly_set_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1879 x_set_name (f
, arg
, false);
1882 /* Change the title of frame F to NAME.
1883 If NAME is nil, use the frame name as the title. */
1886 x_set_title (struct frame
*f
, Lisp_Object name
, Lisp_Object old_name
)
1888 /* Don't change the title if it's already NAME. */
1889 if (EQ (name
, f
->title
))
1892 update_mode_lines
= 26;
1894 fset_title (f
, name
);
1899 w32_set_title_bar_text (f
, name
);
1903 x_set_scroll_bar_default_width (struct frame
*f
)
1905 int unit
= FRAME_COLUMN_WIDTH (f
);
1907 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
1908 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
1909 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + unit
- 1) / unit
;
1914 x_set_scroll_bar_default_height (struct frame
*f
)
1916 int unit
= FRAME_LINE_HEIGHT (f
);
1918 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f
) = GetSystemMetrics (SM_CXHSCROLL
);
1919 FRAME_CONFIG_SCROLL_BAR_LINES (f
)
1920 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f
) + unit
- 1) / unit
;
1923 /* Subroutines for creating a frame. */
1926 w32_load_cursor (LPCTSTR name
)
1928 /* Try first to load cursor from application resource. */
1929 Cursor cursor
= LoadImage ((HINSTANCE
) GetModuleHandle (NULL
),
1930 name
, IMAGE_CURSOR
, 0, 0,
1931 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1934 /* Then try to load a shared predefined cursor. */
1935 cursor
= LoadImage (NULL
, name
, IMAGE_CURSOR
, 0, 0,
1936 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1941 static LRESULT CALLBACK
w32_wnd_proc (HWND
, UINT
, WPARAM
, LPARAM
);
1943 #define INIT_WINDOW_CLASS(WC) \
1944 (WC).style = CS_HREDRAW | CS_VREDRAW; \
1945 (WC).lpfnWndProc = (WNDPROC) w32_wnd_proc; \
1946 (WC).cbClsExtra = 0; \
1947 (WC).cbWndExtra = WND_EXTRA_BYTES; \
1948 (WC).hInstance = hinst; \
1949 (WC).hIcon = LoadIcon (hinst, EMACS_CLASS); \
1950 (WC).hCursor = w32_load_cursor (IDC_ARROW); \
1951 (WC).hbrBackground = NULL; \
1952 (WC).lpszMenuName = NULL; \
1955 w32_init_class (HINSTANCE hinst
)
1957 if (w32_unicode_gui
)
1960 INIT_WINDOW_CLASS(uwc
);
1961 uwc
.lpszClassName
= L
"Emacs";
1963 return RegisterClassW (&uwc
);
1968 INIT_WINDOW_CLASS(wc
);
1969 wc
.lpszClassName
= EMACS_CLASS
;
1971 return RegisterClassA (&wc
);
1976 w32_createvscrollbar (struct frame
*f
, struct scroll_bar
* bar
)
1978 return CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
1979 /* Position and size of scroll bar. */
1980 bar
->left
, bar
->top
, bar
->width
, bar
->height
,
1981 FRAME_W32_WINDOW (f
), NULL
, hinst
, NULL
);
1985 w32_createhscrollbar (struct frame
*f
, struct scroll_bar
* bar
)
1987 return CreateWindow ("SCROLLBAR", "", SBS_HORZ
| WS_CHILD
| WS_VISIBLE
,
1988 /* Position and size of scroll bar. */
1989 bar
->left
, bar
->top
, bar
->width
, bar
->height
,
1990 FRAME_W32_WINDOW (f
), NULL
, hinst
, NULL
);
1994 w32_createwindow (struct frame
*f
, int *coords
)
2001 rect
.left
= rect
.top
= 0;
2002 rect
.right
= FRAME_PIXEL_WIDTH (f
);
2003 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
2005 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2006 FRAME_EXTERNAL_MENU_BAR (f
));
2008 /* Do first time app init */
2010 w32_init_class (hinst
);
2012 if (f
->size_hint_flags
& USPosition
|| f
->size_hint_flags
& PPosition
)
2023 FRAME_W32_WINDOW (f
) = hwnd
2024 = CreateWindow (EMACS_CLASS
,
2026 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2028 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
2036 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
2037 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
2038 SetWindowLong (hwnd
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
2039 SetWindowLong (hwnd
, WND_VSCROLLBAR_INDEX
, FRAME_SCROLL_BAR_AREA_WIDTH (f
));
2040 SetWindowLong (hwnd
, WND_HSCROLLBAR_INDEX
, FRAME_SCROLL_BAR_AREA_HEIGHT (f
));
2041 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
2043 /* Enable drag-n-drop. */
2044 DragAcceptFiles (hwnd
, TRUE
);
2046 /* Do this to discard the default setting specified by our parent. */
2047 ShowWindow (hwnd
, SW_HIDE
);
2049 /* Update frame positions. */
2050 GetWindowRect (hwnd
, &rect
);
2051 f
->left_pos
= rect
.left
;
2052 f
->top_pos
= rect
.top
;
2057 my_post_msg (W32Msg
* wmsg
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2059 wmsg
->msg
.hwnd
= hwnd
;
2060 wmsg
->msg
.message
= msg
;
2061 wmsg
->msg
.wParam
= wParam
;
2062 wmsg
->msg
.lParam
= lParam
;
2063 wmsg
->msg
.time
= GetMessageTime ();
2068 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2069 between left and right keys as advertised. We test for this
2070 support dynamically, and set a flag when the support is absent. If
2071 absent, we keep track of the left and right control and alt keys
2072 ourselves. This is particularly necessary on keyboards that rely
2073 upon the AltGr key, which is represented as having the left control
2074 and right alt keys pressed. For these keyboards, we need to know
2075 when the left alt key has been pressed in addition to the AltGr key
2076 so that we can properly support M-AltGr-key sequences (such as M-@
2077 on Swedish keyboards). */
2079 #define EMACS_LCONTROL 0
2080 #define EMACS_RCONTROL 1
2081 #define EMACS_LMENU 2
2082 #define EMACS_RMENU 3
2084 static int modifiers
[4];
2085 static int modifiers_recorded
;
2086 static int modifier_key_support_tested
;
2089 test_modifier_support (unsigned int wparam
)
2093 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
2095 if (wparam
== VK_CONTROL
)
2105 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
2106 modifiers_recorded
= 1;
2108 modifiers_recorded
= 0;
2109 modifier_key_support_tested
= 1;
2113 record_keydown (unsigned int wparam
, unsigned int lparam
)
2117 if (!modifier_key_support_tested
)
2118 test_modifier_support (wparam
);
2120 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2123 if (wparam
== VK_CONTROL
)
2124 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2126 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2132 record_keyup (unsigned int wparam
, unsigned int lparam
)
2136 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2139 if (wparam
== VK_CONTROL
)
2140 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2142 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2147 /* Emacs can lose focus while a modifier key has been pressed. When
2148 it regains focus, be conservative and clear all modifiers since
2149 we cannot reconstruct the left and right modifier state. */
2151 reset_modifiers (void)
2155 if (GetFocus () == NULL
)
2156 /* Emacs doesn't have keyboard focus. Do nothing. */
2159 ctrl
= GetAsyncKeyState (VK_CONTROL
);
2160 alt
= GetAsyncKeyState (VK_MENU
);
2162 if (!(ctrl
& 0x08000))
2163 /* Clear any recorded control modifier state. */
2164 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2166 if (!(alt
& 0x08000))
2167 /* Clear any recorded alt modifier state. */
2168 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2170 /* Update the state of all modifier keys, because modifiers used in
2171 hot-key combinations can get stuck on if Emacs loses focus as a
2172 result of a hot-key being pressed. */
2176 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2178 memset (keystate
, 0, sizeof (keystate
));
2179 GetKeyboardState (keystate
);
2180 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
2181 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
2182 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
2183 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
2184 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
2185 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
2186 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
2187 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
2188 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
2189 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
2190 SetKeyboardState (keystate
);
2194 /* Synchronize modifier state with what is reported with the current
2195 keystroke. Even if we cannot distinguish between left and right
2196 modifier keys, we know that, if no modifiers are set, then neither
2197 the left or right modifier should be set. */
2199 sync_modifiers (void)
2201 if (!modifiers_recorded
)
2204 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
2205 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2207 if (!(GetKeyState (VK_MENU
) & 0x8000))
2208 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2212 modifier_set (int vkey
)
2214 /* Warning: The fact that VK_NUMLOCK is not treated as the other 2
2215 toggle keys is not an omission! If you want to add it, you will
2216 have to make changes in the default sub-case of the WM_KEYDOWN
2217 switch, because if the NUMLOCK modifier is set, the code there
2218 will directly convert any key that looks like an ASCII letter,
2219 and also downcase those that look like upper-case ASCII. */
2220 if (vkey
== VK_CAPITAL
)
2222 if (NILP (Vw32_enable_caps_lock
))
2225 return (GetKeyState (vkey
) & 0x1);
2227 if (vkey
== VK_SCROLL
)
2229 if (NILP (Vw32_scroll_lock_modifier
)
2230 /* w32-scroll-lock-modifier can be any non-nil value that is
2231 not one of the modifiers, in which case it shall be ignored. */
2232 || !( EQ (Vw32_scroll_lock_modifier
, Qhyper
)
2233 || EQ (Vw32_scroll_lock_modifier
, Qsuper
)
2234 || EQ (Vw32_scroll_lock_modifier
, Qmeta
)
2235 || EQ (Vw32_scroll_lock_modifier
, Qalt
)
2236 || EQ (Vw32_scroll_lock_modifier
, Qcontrol
)
2237 || EQ (Vw32_scroll_lock_modifier
, Qshift
)))
2240 return (GetKeyState (vkey
) & 0x1);
2243 if (!modifiers_recorded
)
2244 return (GetKeyState (vkey
) & 0x8000);
2249 return modifiers
[EMACS_LCONTROL
];
2251 return modifiers
[EMACS_RCONTROL
];
2253 return modifiers
[EMACS_LMENU
];
2255 return modifiers
[EMACS_RMENU
];
2257 return (GetKeyState (vkey
) & 0x8000);
2260 /* Convert between the modifier bits W32 uses and the modifier bits
2264 w32_key_to_modifier (int key
)
2266 Lisp_Object key_mapping
;
2271 key_mapping
= Vw32_lwindow_modifier
;
2274 key_mapping
= Vw32_rwindow_modifier
;
2277 key_mapping
= Vw32_apps_modifier
;
2280 key_mapping
= Vw32_scroll_lock_modifier
;
2286 /* NB. This code runs in the input thread, asynchronously to the lisp
2287 thread, so we must be careful to ensure access to lisp data is
2288 thread-safe. The following code is safe because the modifier
2289 variable values are updated atomically from lisp and symbols are
2290 not relocated by GC. Also, we don't have to worry about seeing GC
2292 if (EQ (key_mapping
, Qhyper
))
2293 return hyper_modifier
;
2294 if (EQ (key_mapping
, Qsuper
))
2295 return super_modifier
;
2296 if (EQ (key_mapping
, Qmeta
))
2297 return meta_modifier
;
2298 if (EQ (key_mapping
, Qalt
))
2299 return alt_modifier
;
2300 if (EQ (key_mapping
, Qctrl
))
2301 return ctrl_modifier
;
2302 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
2303 return ctrl_modifier
;
2304 if (EQ (key_mapping
, Qshift
))
2305 return shift_modifier
;
2307 /* Don't generate any modifier if not explicitly requested. */
2312 w32_get_modifiers (void)
2314 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
2315 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
2316 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
2317 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
2318 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
2319 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
2320 (modifier_set (VK_MENU
) ?
2321 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2324 /* We map the VK_* modifiers into console modifier constants
2325 so that we can use the same routines to handle both console
2326 and window input. */
2329 construct_console_modifiers (void)
2334 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
2335 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
2336 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
2337 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
2338 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
2339 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
2340 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
2341 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
2342 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
2343 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
2344 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
2350 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
2354 /* Convert to emacs modifiers. */
2355 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
2361 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
2363 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
2366 if (virt_key
== VK_RETURN
)
2367 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
2369 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
2370 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
2372 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
2373 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
2375 if (virt_key
== VK_CLEAR
)
2376 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
2381 /* List of special key combinations which w32 would normally capture,
2382 but Emacs should grab instead. Not directly visible to lisp, to
2383 simplify synchronization. Each item is an integer encoding a virtual
2384 key code and modifier combination to capture. */
2385 static Lisp_Object w32_grabbed_keys
;
2387 #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8))
2388 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2389 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2390 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2392 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2393 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2394 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2396 /* Register hot-keys for reserved key combinations when Emacs has
2397 keyboard focus, since this is the only way Emacs can receive key
2398 combinations like Alt-Tab which are used by the system. */
2401 register_hot_keys (HWND hwnd
)
2403 Lisp_Object keylist
;
2405 /* Use CONSP, since we are called asynchronously. */
2406 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2408 Lisp_Object key
= XCAR (keylist
);
2410 /* Deleted entries get set to nil. */
2411 if (!INTEGERP (key
))
2414 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
2415 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
2420 unregister_hot_keys (HWND hwnd
)
2422 Lisp_Object keylist
;
2424 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2426 Lisp_Object key
= XCAR (keylist
);
2428 if (!INTEGERP (key
))
2431 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
2437 w32_name_of_message (UINT msg
)
2440 static char buf
[64];
2441 static const struct {
2445 #define M(msg) { msg, # msg }
2453 M (WM_EMACS_CREATEWINDOW
),
2455 M (WM_EMACS_CREATEVSCROLLBAR
),
2456 M (WM_EMACS_CREATEHSCROLLBAR
),
2457 M (WM_EMACS_SHOWWINDOW
),
2458 M (WM_EMACS_SETWINDOWPOS
),
2459 M (WM_EMACS_DESTROYWINDOW
),
2460 M (WM_EMACS_TRACKPOPUPMENU
),
2461 M (WM_EMACS_SETFOCUS
),
2462 M (WM_EMACS_SETFOREGROUND
),
2463 M (WM_EMACS_SETLOCALE
),
2464 M (WM_EMACS_SETKEYBOARDLAYOUT
),
2465 M (WM_EMACS_REGISTER_HOT_KEY
),
2466 M (WM_EMACS_UNREGISTER_HOT_KEY
),
2467 M (WM_EMACS_TOGGLE_LOCK_KEY
),
2468 M (WM_EMACS_TRACK_CARET
),
2469 M (WM_EMACS_DESTROY_CARET
),
2470 M (WM_EMACS_SHOW_CARET
),
2471 M (WM_EMACS_HIDE_CARET
),
2472 M (WM_EMACS_SETCURSOR
),
2473 M (WM_EMACS_SHOWCURSOR
),
2480 for (i
= 0; msgnames
[i
].name
; ++i
)
2481 if (msgnames
[i
].msg
== msg
)
2482 return msgnames
[i
].name
;
2484 sprintf (buf
, "message 0x%04x", (unsigned)msg
);
2487 #endif /* EMACSDEBUG */
2489 /* Here's an overview of how Emacs input works in GUI sessions on
2490 MS-Windows. (For description of non-GUI input, see the commentary
2491 before w32_console_read_socket in w32inevt.c.)
2493 System messages are read and processed by w32_msg_pump below. This
2494 function runs in a separate thread. It handles a small number of
2495 custom WM_EMACS_* messages (posted by the main thread, look for
2496 PostMessage calls), and dispatches the rest to w32_wnd_proc, which
2497 is the main window procedure for the entire Emacs application.
2499 w32_wnd_proc also runs in the same separate input thread. It
2500 handles some messages, mostly those that need GDI calls, by itself.
2501 For the others, it calls my_post_msg, which inserts the messages
2502 into the input queue serviced by w32_read_socket.
2504 w32_read_socket runs in the main (a.k.a. "Lisp") thread, and is
2505 called synchronously from keyboard.c when it is known or suspected
2506 that some input is available. w32_read_socket either handles
2507 messages immediately, or converts them into Emacs input events and
2508 stuffs them into kbd_buffer, where kbd_buffer_get_event can get at
2509 them and process them when read_char and its callers require
2512 Under Cygwin with the W32 toolkit, the use of /dev/windows with
2513 select(2) takes the place of w32_read_socket.
2517 /* Main message dispatch loop. */
2520 w32_msg_pump (deferred_msg
* msg_buf
)
2526 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
2528 while ((w32_unicode_gui
? GetMessageW
: GetMessageA
) (&msg
, NULL
, 0, 0))
2531 /* DebPrint (("w32_msg_pump: %s time:%u\n", */
2532 /* w32_name_of_message (msg.message), msg.time)); */
2534 if (msg
.hwnd
== NULL
)
2536 switch (msg
.message
)
2539 /* Produced by complete_deferred_msg; just ignore. */
2541 case WM_EMACS_CREATEWINDOW
:
2542 /* Initialize COM for this window. Even though we don't use it,
2543 some third party shell extensions can cause it to be used in
2544 system dialogs, which causes a crash if it is not initialized.
2545 This is a known bug in Windows, which was fixed long ago, but
2546 the patch for XP is not publicly available until XP SP3,
2547 and older versions will never be patched. */
2548 CoInitialize (NULL
);
2549 w32_createwindow ((struct frame
*) msg
.wParam
,
2550 (int *) msg
.lParam
);
2551 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2554 case WM_EMACS_SETLOCALE
:
2555 SetThreadLocale (msg
.wParam
);
2556 /* Reply is not expected. */
2558 case WM_EMACS_SETKEYBOARDLAYOUT
:
2559 result
= (WPARAM
) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
2560 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2564 case WM_EMACS_REGISTER_HOT_KEY
:
2565 focus_window
= GetFocus ();
2566 if (focus_window
!= NULL
)
2567 RegisterHotKey (focus_window
,
2568 RAW_HOTKEY_ID (msg
.wParam
),
2569 RAW_HOTKEY_MODIFIERS (msg
.wParam
),
2570 RAW_HOTKEY_VK_CODE (msg
.wParam
));
2571 /* Reply is not expected. */
2573 case WM_EMACS_UNREGISTER_HOT_KEY
:
2574 focus_window
= GetFocus ();
2575 if (focus_window
!= NULL
)
2576 UnregisterHotKey (focus_window
, RAW_HOTKEY_ID (msg
.wParam
));
2577 /* Mark item as erased. NB: this code must be
2578 thread-safe. The next line is okay because the cons
2579 cell is never made into garbage and is not relocated by
2581 XSETCAR (make_lisp_ptr ((void *)msg
.lParam
, Lisp_Cons
), Qnil
);
2582 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2585 case WM_EMACS_TOGGLE_LOCK_KEY
:
2587 int vk_code
= (int) msg
.wParam
;
2588 int cur_state
= (GetKeyState (vk_code
) & 1);
2589 int new_state
= msg
.lParam
;
2592 || ((new_state
& 1) != cur_state
))
2594 one_w32_display_info
.faked_key
= vk_code
;
2596 keybd_event ((BYTE
) vk_code
,
2597 (BYTE
) MapVirtualKey (vk_code
, 0),
2598 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2599 keybd_event ((BYTE
) vk_code
,
2600 (BYTE
) MapVirtualKey (vk_code
, 0),
2601 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2602 keybd_event ((BYTE
) vk_code
,
2603 (BYTE
) MapVirtualKey (vk_code
, 0),
2604 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2605 cur_state
= !cur_state
;
2607 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2613 /* Broadcast messages make it here, so you need to be looking
2614 for something in particular for this to be useful. */
2616 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
2622 if (w32_unicode_gui
)
2623 DispatchMessageW (&msg
);
2625 DispatchMessageA (&msg
);
2628 /* Exit nested loop when our deferred message has completed. */
2629 if (msg_buf
->completed
)
2634 deferred_msg
* deferred_msg_head
;
2636 static deferred_msg
*
2637 find_deferred_msg (HWND hwnd
, UINT msg
)
2639 deferred_msg
* item
;
2641 /* Don't actually need synchronization for read access, since
2642 modification of single pointer is always atomic. */
2643 /* enter_crit (); */
2645 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2646 if (item
->w32msg
.msg
.hwnd
== hwnd
2647 && item
->w32msg
.msg
.message
== msg
)
2650 /* leave_crit (); */
2656 send_deferred_msg (deferred_msg
* msg_buf
,
2662 /* Only input thread can send deferred messages. */
2663 if (GetCurrentThreadId () != dwWindowsThreadId
)
2666 /* It is an error to send a message that is already deferred. */
2667 if (find_deferred_msg (hwnd
, msg
) != NULL
)
2670 /* Enforced synchronization is not needed because this is the only
2671 function that alters deferred_msg_head, and the following critical
2672 section is guaranteed to only be serially reentered (since only the
2673 input thread can call us). */
2675 /* enter_crit (); */
2677 msg_buf
->completed
= 0;
2678 msg_buf
->next
= deferred_msg_head
;
2679 deferred_msg_head
= msg_buf
;
2680 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
2682 /* leave_crit (); */
2684 /* Start a new nested message loop to process other messages until
2685 this one is completed. */
2686 w32_msg_pump (msg_buf
);
2688 deferred_msg_head
= msg_buf
->next
;
2690 return msg_buf
->result
;
2694 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
2696 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
2698 if (msg_buf
== NULL
)
2699 /* Message may have been canceled, so don't abort. */
2702 msg_buf
->result
= result
;
2703 msg_buf
->completed
= 1;
2705 /* Ensure input thread is woken so it notices the completion. */
2706 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2710 cancel_all_deferred_msgs (void)
2712 deferred_msg
* item
;
2714 /* Don't actually need synchronization for read access, since
2715 modification of single pointer is always atomic. */
2716 /* enter_crit (); */
2718 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2721 item
->completed
= 1;
2724 /* leave_crit (); */
2726 /* Ensure input thread is woken so it notices the completion. */
2727 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2731 w32_msg_worker (void *arg
)
2734 deferred_msg dummy_buf
;
2736 /* Ensure our message queue is created */
2738 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2740 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2743 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
2744 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
2745 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
2747 /* This is the initial message loop which should only exit when the
2748 application quits. */
2749 w32_msg_pump (&dummy_buf
);
2755 signal_user_input (void)
2757 /* Interrupt any lisp that wants to be interrupted by input. */
2758 if (!NILP (Vthrow_on_input
))
2760 Vquit_flag
= Vthrow_on_input
;
2761 /* Doing a QUIT from this thread is a bad idea, since this
2762 unwinds the stack of the Lisp thread, and the Windows runtime
2763 rightfully barfs. Disabled. */
2765 /* If we're inside a function that wants immediate quits,
2767 if (immediate_quit
&& NILP (Vinhibit_quit
))
2778 post_character_message (HWND hwnd
, UINT msg
,
2779 WPARAM wParam
, LPARAM lParam
,
2784 wmsg
.dwModifiers
= modifiers
;
2786 /* Detect quit_char and set quit-flag directly. Note that we
2787 still need to post a message to ensure the main thread will be
2788 woken up if blocked in sys_select, but we do NOT want to post
2789 the quit_char message itself (because it will usually be as if
2790 the user had typed quit_char twice). Instead, we post a dummy
2791 message that has no particular effect. */
2794 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
2795 c
= make_ctrl_char (c
) & 0377;
2797 || (wmsg
.dwModifiers
== 0
2798 && w32_quit_key
&& wParam
== w32_quit_key
))
2802 /* The choice of message is somewhat arbitrary, as long as
2803 the main thread handler just ignores it. */
2806 /* Interrupt any blocking system calls. */
2809 /* As a safety precaution, forcibly complete any deferred
2810 messages. This is a kludge, but I don't see any particularly
2811 clean way to handle the situation where a deferred message is
2812 "dropped" in the lisp thread, and will thus never be
2813 completed, eg. by the user trying to activate the menubar
2814 when the lisp thread is busy, and then typing C-g when the
2815 menubar doesn't open promptly (with the result that the
2816 menubar never responds at all because the deferred
2817 WM_INITMENU message is never completed). Another problem
2818 situation is when the lisp thread calls SendMessage (to send
2819 a window manager command) when a message has been deferred;
2820 the lisp thread gets blocked indefinitely waiting for the
2821 deferred message to be completed, which itself is waiting for
2822 the lisp thread to respond.
2824 Note that we don't want to block the input thread waiting for
2825 a response from the lisp thread (although that would at least
2826 solve the deadlock problem above), because we want to be able
2827 to receive C-g to interrupt the lisp thread. */
2828 cancel_all_deferred_msgs ();
2831 signal_user_input ();
2834 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2837 /* Main window procedure */
2839 static LRESULT CALLBACK
2840 w32_wnd_proc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2843 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2845 int windows_translate
;
2848 /* Note that it is okay to call x_window_to_frame, even though we are
2849 not running in the main lisp thread, because frame deletion
2850 requires the lisp thread to synchronize with this thread. Thus, if
2851 a frame struct is returned, it can be used without concern that the
2852 lisp thread might make it disappear while we are using it.
2854 NB. Walking the frame list in this thread is safe (as long as
2855 writes of Lisp_Object slots are atomic, which they are on Windows).
2856 Although delete-frame can destructively modify the frame list while
2857 we are walking it, a garbage collection cannot occur until after
2858 delete-frame has synchronized with this thread.
2860 It is also safe to use functions that make GDI calls, such as
2861 w32_clear_rect, because these functions must obtain a DC handle
2862 from the frame struct using get_frame_dc which is thread-aware. */
2867 f
= x_window_to_frame (dpyinfo
, hwnd
);
2870 HDC hdc
= get_frame_dc (f
);
2871 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
2872 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
2873 release_frame_dc (f
, hdc
);
2875 #if defined (W32_DEBUG_DISPLAY)
2876 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2878 wmsg
.rect
.left
, wmsg
.rect
.top
,
2879 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2880 #endif /* W32_DEBUG_DISPLAY */
2883 case WM_PALETTECHANGED
:
2884 /* ignore our own changes */
2885 if ((HWND
)wParam
!= hwnd
)
2887 f
= x_window_to_frame (dpyinfo
, hwnd
);
2889 /* get_frame_dc will realize our palette and force all
2890 frames to be redrawn if needed. */
2891 release_frame_dc (f
, get_frame_dc (f
));
2896 PAINTSTRUCT paintStruct
;
2898 memset (&update_rect
, 0, sizeof (update_rect
));
2900 f
= x_window_to_frame (dpyinfo
, hwnd
);
2903 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd
));
2907 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2908 fails. Apparently this can happen under some
2910 if (GetUpdateRect (hwnd
, &update_rect
, FALSE
) || !w32_strict_painting
)
2913 BeginPaint (hwnd
, &paintStruct
);
2915 /* The rectangles returned by GetUpdateRect and BeginPaint
2916 do not always match. Play it safe by assuming both areas
2918 UnionRect (&(wmsg
.rect
), &update_rect
, &(paintStruct
.rcPaint
));
2920 #if defined (W32_DEBUG_DISPLAY)
2921 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2923 wmsg
.rect
.left
, wmsg
.rect
.top
,
2924 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2925 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2926 update_rect
.left
, update_rect
.top
,
2927 update_rect
.right
, update_rect
.bottom
));
2929 EndPaint (hwnd
, &paintStruct
);
2932 /* Change the message type to prevent Windows from
2933 combining WM_PAINT messages in the Lisp thread's queue,
2934 since Windows assumes that each message queue is
2935 dedicated to one frame and does not bother checking
2936 that hwnd matches before combining them. */
2937 my_post_msg (&wmsg
, hwnd
, WM_EMACS_PAINT
, wParam
, lParam
);
2942 /* If GetUpdateRect returns 0 (meaning there is no update
2943 region), assume the whole window needs to be repainted. */
2944 GetClientRect (hwnd
, &wmsg
.rect
);
2945 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2949 case WM_INPUTLANGCHANGE
:
2950 /* Inform lisp thread of keyboard layout changes. */
2951 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2953 /* Clear dead keys in the keyboard state; for simplicity only
2954 preserve modifier key states. */
2959 GetKeyboardState (keystate
);
2960 for (i
= 0; i
< 256; i
++)
2977 SetKeyboardState (keystate
);
2982 /* Synchronize hot keys with normal input. */
2983 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
2988 record_keyup (wParam
, lParam
);
2993 /* Ignore keystrokes we fake ourself; see below. */
2994 if (dpyinfo
->faked_key
== wParam
)
2996 dpyinfo
->faked_key
= 0;
2997 /* Make sure TranslateMessage sees them though (as long as
2998 they don't produce WM_CHAR messages). This ensures that
2999 indicator lights are toggled promptly on Windows 9x, for
3001 if (wParam
< 256 && lispy_function_keys
[wParam
])
3003 windows_translate
= 1;
3009 /* Synchronize modifiers with current keystroke. */
3011 record_keydown (wParam
, lParam
);
3012 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
3014 windows_translate
= 0;
3019 if (NILP (Vw32_pass_lwindow_to_system
))
3021 /* Prevent system from acting on keyup (which opens the
3022 Start menu if no other key was pressed) by simulating a
3023 press of Space which we will ignore. */
3024 if (GetAsyncKeyState (wParam
) & 1)
3026 if (NUMBERP (Vw32_phantom_key_code
))
3027 key
= XUINT (Vw32_phantom_key_code
) & 255;
3030 dpyinfo
->faked_key
= key
;
3031 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3034 if (!NILP (Vw32_lwindow_modifier
))
3038 if (NILP (Vw32_pass_rwindow_to_system
))
3040 if (GetAsyncKeyState (wParam
) & 1)
3042 if (NUMBERP (Vw32_phantom_key_code
))
3043 key
= XUINT (Vw32_phantom_key_code
) & 255;
3046 dpyinfo
->faked_key
= key
;
3047 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3050 if (!NILP (Vw32_rwindow_modifier
))
3054 if (!NILP (Vw32_apps_modifier
))
3058 if (NILP (Vw32_pass_alt_to_system
))
3059 /* Prevent DefWindowProc from activating the menu bar if an
3060 Alt key is pressed and released by itself. */
3062 windows_translate
= 1;
3065 /* Decide whether to treat as modifier or function key. */
3066 if (NILP (Vw32_enable_caps_lock
))
3067 goto disable_lock_key
;
3068 windows_translate
= 1;
3071 /* Decide whether to treat as modifier or function key. */
3072 if (NILP (Vw32_enable_num_lock
))
3073 goto disable_lock_key
;
3074 windows_translate
= 1;
3077 /* Decide whether to treat as modifier or function key. */
3078 if (NILP (Vw32_scroll_lock_modifier
))
3079 goto disable_lock_key
;
3080 windows_translate
= 1;
3083 /* Ensure the appropriate lock key state (and indicator light)
3084 remains in the same state. We do this by faking another
3085 press of the relevant key. Apparently, this really is the
3086 only way to toggle the state of the indicator lights. */
3087 dpyinfo
->faked_key
= wParam
;
3088 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3089 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3090 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3091 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3092 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3093 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3094 /* Ensure indicator lights are updated promptly on Windows 9x
3095 (TranslateMessage apparently does this), after forwarding
3097 post_character_message (hwnd
, msg
, wParam
, lParam
,
3098 w32_get_key_modifiers (wParam
, lParam
));
3099 windows_translate
= 1;
3103 case VK_PROCESSKEY
: /* Generated by IME. */
3104 windows_translate
= 1;
3107 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3108 which is confusing for purposes of key binding; convert
3109 VK_CANCEL events into VK_PAUSE events. */
3113 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3114 for purposes of key binding; convert these back into
3115 VK_NUMLOCK events, at least when we want to see NumLock key
3116 presses. (Note that there is never any possibility that
3117 VK_PAUSE with Ctrl really is C-Pause as per above.) */
3118 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
3119 wParam
= VK_NUMLOCK
;
3122 /* If not defined as a function key, change it to a WM_CHAR message. */
3123 if (wParam
> 255 || !lispy_function_keys
[wParam
])
3125 DWORD modifiers
= construct_console_modifiers ();
3127 if (!NILP (Vw32_recognize_altgr
)
3128 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
3130 /* Always let TranslateMessage handle AltGr key chords;
3131 for some reason, ToAscii doesn't always process AltGr
3132 chords correctly. */
3133 windows_translate
= 1;
3135 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
3137 /* Handle key chords including any modifiers other
3138 than shift directly, in order to preserve as much
3139 modifier information as possible. */
3140 if ('A' <= wParam
&& wParam
<= 'Z')
3142 /* Don't translate modified alphabetic keystrokes,
3143 so the user doesn't need to constantly switch
3144 layout to type control or meta keystrokes when
3145 the normal layout translates alphabetic
3146 characters to non-ascii characters. */
3147 if (!modifier_set (VK_SHIFT
))
3148 wParam
+= ('a' - 'A');
3153 /* Try to handle other keystrokes by determining the
3154 base character (ie. translating the base key plus
3157 KEY_EVENT_RECORD key
;
3159 key
.bKeyDown
= TRUE
;
3160 key
.wRepeatCount
= 1;
3161 key
.wVirtualKeyCode
= wParam
;
3162 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3163 key
.uChar
.AsciiChar
= 0;
3164 key
.dwControlKeyState
= modifiers
;
3166 add
= w32_kbd_patch_key (&key
, w32_keyboard_codepage
);
3167 /* 0 means an unrecognized keycode, negative means
3168 dead key. Ignore both. */
3171 /* Forward asciified character sequence. */
3172 post_character_message
3174 (unsigned char) key
.uChar
.AsciiChar
, lParam
,
3175 w32_get_key_modifiers (wParam
, lParam
));
3176 w32_kbd_patch_key (&key
, w32_keyboard_codepage
);
3183 /* Let TranslateMessage handle everything else. */
3184 windows_translate
= 1;
3190 if (windows_translate
)
3192 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3193 windows_msg
.time
= GetMessageTime ();
3194 TranslateMessage (&windows_msg
);
3206 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3207 signal_user_input ();
3208 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, wParam
, lParam
);
3212 post_character_message (hwnd
, msg
, wParam
, lParam
,
3213 w32_get_key_modifiers (wParam
, lParam
));
3217 /* WM_UNICHAR looks promising from the docs, but the exact
3218 circumstances in which TranslateMessage sends it is one of those
3219 Microsoft secret API things that EU and US courts are supposed
3220 to have put a stop to already. Spy++ shows it being sent to Notepad
3221 and other MS apps, but never to Emacs.
3223 Some third party IMEs send it in accordance with the official
3224 documentation though, so handle it here.
3226 UNICODE_NOCHAR is used to test for support for this message.
3227 TRUE indicates that the message is supported. */
3228 if (wParam
== UNICODE_NOCHAR
)
3233 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3234 signal_user_input ();
3235 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3240 /* If we can't get the IME result as Unicode, use default processing,
3241 which will at least allow characters decodable in the system locale
3243 if (!get_composition_string_fn
)
3246 else if (!ignore_ime_char
)
3251 HIMC context
= get_ime_context_fn (hwnd
);
3252 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3253 /* Get buffer size. */
3254 size
= get_composition_string_fn (context
, GCS_RESULTSTR
, NULL
, 0);
3255 buffer
= alloca (size
);
3256 size
= get_composition_string_fn (context
, GCS_RESULTSTR
,
3258 release_ime_context_fn (hwnd
, context
);
3260 signal_user_input ();
3261 for (i
= 0; i
< size
/ sizeof (wchar_t); i
++)
3263 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, (WPARAM
) buffer
[i
],
3266 /* Ignore the messages for the rest of the
3267 characters in the string that was output above. */
3268 ignore_ime_char
= (size
/ sizeof (wchar_t)) - 1;
3275 case WM_IME_STARTCOMPOSITION
:
3276 if (!set_ime_composition_window_fn
)
3280 COMPOSITIONFORM form
;
3284 /* Implementation note: The code below does something that
3285 one shouldn't do: it accesses the window object from a
3286 separate thread, while the main (a.k.a. "Lisp") thread
3287 runs and can legitimately delete and even GC it. That is
3288 why we are extra careful not to futz with a window that
3289 is different from the one recorded when the system caret
3290 coordinates were last modified. That is also why we are
3291 careful not to move the IME window if the window
3292 described by W was deleted, as indicated by its buffer
3293 field being reset to nil. */
3294 f
= x_window_to_frame (dpyinfo
, hwnd
);
3295 if (!(f
&& FRAME_LIVE_P (f
)))
3297 w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
3298 /* Punt if someone changed the frame's selected window
3300 if (w
!= w32_system_caret_window
)
3303 form
.dwStyle
= CFS_RECT
;
3304 form
.ptCurrentPos
.x
= w32_system_caret_x
;
3305 form
.ptCurrentPos
.y
= w32_system_caret_y
;
3307 form
.rcArea
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, 0);
3308 form
.rcArea
.top
= (WINDOW_TOP_EDGE_Y (w
)
3309 + w32_system_caret_hdr_height
);
3310 form
.rcArea
.right
= (WINDOW_BOX_RIGHT_EDGE_X (w
)
3311 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
3312 - WINDOW_RIGHT_FRINGE_WIDTH (w
));
3313 form
.rcArea
.bottom
= (WINDOW_BOTTOM_EDGE_Y (w
)
3314 - WINDOW_BOTTOM_DIVIDER_WIDTH (w
)
3315 - w32_system_caret_mode_height
);
3317 /* Punt if the window was deleted behind our back. */
3318 if (!BUFFERP (w
->contents
))
3321 context
= get_ime_context_fn (hwnd
);
3326 set_ime_composition_window_fn (context
, &form
);
3327 release_ime_context_fn (hwnd
, context
);
3329 /* We should "goto dflt" here to pass WM_IME_STARTCOMPOSITION to
3330 DefWindowProc, so that the composition window will actually
3331 be displayed. But doing so causes trouble with displaying
3332 dialog boxes, such as the file selection dialog or font
3333 selection dialog. So something else is needed to fix the
3334 former without breaking the latter. See bug#11732. */
3337 case WM_IME_ENDCOMPOSITION
:
3338 ignore_ime_char
= 0;
3341 /* Simulate middle mouse button events when left and right buttons
3342 are used together, but only if user has two button mouse. */
3343 case WM_LBUTTONDOWN
:
3344 case WM_RBUTTONDOWN
:
3345 if (w32_num_mouse_buttons
> 2)
3346 goto handle_plain_button
;
3349 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3350 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3352 if (button_state
& this)
3355 if (button_state
== 0)
3358 button_state
|= this;
3360 if (button_state
& other
)
3362 if (mouse_button_timer
)
3364 KillTimer (hwnd
, mouse_button_timer
);
3365 mouse_button_timer
= 0;
3367 /* Generate middle mouse event instead. */
3368 msg
= WM_MBUTTONDOWN
;
3369 button_state
|= MMOUSE
;
3371 else if (button_state
& MMOUSE
)
3373 /* Ignore button event if we've already generated a
3374 middle mouse down event. This happens if the
3375 user releases and press one of the two buttons
3376 after we've faked a middle mouse event. */
3381 /* Flush out saved message. */
3382 post_msg (&saved_mouse_button_msg
);
3384 wmsg
.dwModifiers
= w32_get_modifiers ();
3385 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3386 signal_user_input ();
3388 /* Clear message buffer. */
3389 saved_mouse_button_msg
.msg
.hwnd
= 0;
3393 /* Hold onto message for now. */
3394 mouse_button_timer
=
3395 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
3396 w32_mouse_button_tolerance
, NULL
);
3397 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3398 saved_mouse_button_msg
.msg
.message
= msg
;
3399 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3400 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3401 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3402 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3409 if (w32_num_mouse_buttons
> 2)
3410 goto handle_plain_button
;
3413 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3414 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3416 if ((button_state
& this) == 0)
3419 button_state
&= ~this;
3421 if (button_state
& MMOUSE
)
3423 /* Only generate event when second button is released. */
3424 if ((button_state
& other
) == 0)
3427 button_state
&= ~MMOUSE
;
3429 if (button_state
) emacs_abort ();
3436 /* Flush out saved message if necessary. */
3437 if (saved_mouse_button_msg
.msg
.hwnd
)
3439 post_msg (&saved_mouse_button_msg
);
3442 wmsg
.dwModifiers
= w32_get_modifiers ();
3443 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3444 signal_user_input ();
3446 /* Always clear message buffer and cancel timer. */
3447 saved_mouse_button_msg
.msg
.hwnd
= 0;
3448 KillTimer (hwnd
, mouse_button_timer
);
3449 mouse_button_timer
= 0;
3451 if (button_state
== 0)
3456 case WM_XBUTTONDOWN
:
3458 if (w32_pass_extra_mouse_buttons_to_system
)
3460 /* else fall through and process them. */
3461 case WM_MBUTTONDOWN
:
3463 handle_plain_button
:
3468 /* Ignore middle and extra buttons as long as the menu is active. */
3469 f
= x_window_to_frame (dpyinfo
, hwnd
);
3470 if (f
&& f
->output_data
.w32
->menubar_active
)
3473 if (parse_button (msg
, HIWORD (wParam
), &button
, &up
))
3475 if (up
) ReleaseCapture ();
3476 else SetCapture (hwnd
);
3477 button
= (button
== 0) ? LMOUSE
:
3478 ((button
== 1) ? MMOUSE
: RMOUSE
);
3480 button_state
&= ~button
;
3482 button_state
|= button
;
3486 wmsg
.dwModifiers
= w32_get_modifiers ();
3487 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3488 signal_user_input ();
3490 /* Need to return true for XBUTTON messages, false for others,
3491 to indicate that we processed the message. */
3492 return (msg
== WM_XBUTTONDOWN
|| msg
== WM_XBUTTONUP
);
3495 /* Ignore mouse movements as long as the menu is active. These
3496 movements are processed by the window manager anyway, and
3497 it's wrong to handle them as if they happened on the
3498 underlying frame. */
3499 f
= x_window_to_frame (dpyinfo
, hwnd
);
3500 if (f
&& f
->output_data
.w32
->menubar_active
)
3503 /* If the mouse has just moved into the frame, start tracking
3504 it, so we will be notified when it leaves the frame. Mouse
3505 tracking only works under W98 and NT4 and later. On earlier
3506 versions, there is no way of telling when the mouse leaves the
3507 frame, so we just have to put up with help-echo and mouse
3508 highlighting remaining while the frame is not active. */
3509 if (track_mouse_event_fn
&& !track_mouse_window
3510 /* If the menu bar is active, turning on tracking of mouse
3511 movement events might send these events to the tooltip
3512 frame, if the user happens to move the mouse pointer over
3513 the tooltip. But since we don't process events for
3514 tooltip frames, this causes Windows to present a
3515 hourglass cursor, which is ugly and unexpected. So don't
3516 enable tracking mouse events in this case; they will be
3517 restarted when the menu pops down. (Confusingly, the
3518 menubar_active member of f->output_data.w32, tested
3519 above, is only set when a menu was popped up _not_ from
3520 the frame's menu bar, but via x-popup-menu.) */
3523 TRACKMOUSEEVENT tme
;
3524 tme
.cbSize
= sizeof (tme
);
3525 tme
.dwFlags
= TME_LEAVE
;
3526 tme
.hwndTrack
= hwnd
;
3527 tme
.dwHoverTime
= HOVER_DEFAULT
;
3529 track_mouse_event_fn (&tme
);
3530 track_mouse_window
= hwnd
;
3534 if (w32_mouse_move_interval
<= 0
3535 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3537 wmsg
.dwModifiers
= w32_get_modifiers ();
3538 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3542 /* Hang onto mouse move and scroll messages for a bit, to avoid
3543 sending such events to Emacs faster than it can process them.
3544 If we get more events before the timer from the first message
3545 expires, we just replace the first message. */
3547 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3549 SetTimer (hwnd
, MOUSE_MOVE_ID
,
3550 w32_mouse_move_interval
, NULL
);
3552 /* Hold onto message for now. */
3553 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3554 saved_mouse_move_msg
.msg
.message
= msg
;
3555 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3556 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3557 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3558 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3564 wmsg
.dwModifiers
= w32_get_modifiers ();
3565 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3566 signal_user_input ();
3570 if (w32_pass_multimedia_buttons_to_system
)
3572 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
3573 case WM_MOUSEHWHEEL
:
3574 wmsg
.dwModifiers
= w32_get_modifiers ();
3575 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3576 signal_user_input ();
3577 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3578 handled, to prevent the system trying to handle it by faking
3579 scroll bar events. */
3583 /* Flush out saved messages if necessary. */
3584 if (wParam
== mouse_button_timer
)
3586 if (saved_mouse_button_msg
.msg
.hwnd
)
3588 post_msg (&saved_mouse_button_msg
);
3589 signal_user_input ();
3590 saved_mouse_button_msg
.msg
.hwnd
= 0;
3592 KillTimer (hwnd
, mouse_button_timer
);
3593 mouse_button_timer
= 0;
3595 else if (wParam
== mouse_move_timer
)
3597 if (saved_mouse_move_msg
.msg
.hwnd
)
3599 post_msg (&saved_mouse_move_msg
);
3600 saved_mouse_move_msg
.msg
.hwnd
= 0;
3602 KillTimer (hwnd
, mouse_move_timer
);
3603 mouse_move_timer
= 0;
3605 else if (wParam
== menu_free_timer
)
3607 KillTimer (hwnd
, menu_free_timer
);
3608 menu_free_timer
= 0;
3609 f
= x_window_to_frame (dpyinfo
, hwnd
);
3610 /* If a popup menu is active, don't wipe its strings. */
3612 && current_popup_menu
== NULL
)
3614 /* Free memory used by owner-drawn and help-echo strings. */
3615 w32_free_menu_strings (hwnd
);
3617 f
->output_data
.w32
->menubar_active
= 0;
3624 /* Windows doesn't send us focus messages when putting up and
3625 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3626 The only indication we get that something happened is receiving
3627 this message afterwards. So this is a good time to reset our
3628 keyboard modifiers' state. */
3635 /* We must ensure menu bar is fully constructed and up to date
3636 before allowing user interaction with it. To achieve this
3637 we send this message to the lisp thread and wait for a
3638 reply (whose value is not actually needed) to indicate that
3639 the menu bar is now ready for use, so we can now return.
3641 To remain responsive in the meantime, we enter a nested message
3642 loop that can process all other messages.
3644 However, we skip all this if the message results from calling
3645 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3646 thread a message because it is blocked on us at this point. We
3647 set menubar_active before calling TrackPopupMenu to indicate
3648 this (there is no possibility of confusion with real menubar
3651 f
= x_window_to_frame (dpyinfo
, hwnd
);
3653 && (f
->output_data
.w32
->menubar_active
3654 /* We can receive this message even in the absence of a
3655 menubar (ie. when the system menu is activated) - in this
3656 case we do NOT want to forward the message, otherwise it
3657 will cause the menubar to suddenly appear when the user
3658 had requested it to be turned off! */
3659 || f
->output_data
.w32
->menubar_widget
== NULL
))
3663 deferred_msg msg_buf
;
3665 /* Detect if message has already been deferred; in this case
3666 we cannot return any sensible value to ignore this. */
3667 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3672 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3675 case WM_EXITMENULOOP
:
3676 f
= x_window_to_frame (dpyinfo
, hwnd
);
3678 /* If a menu is still active, check again after a short delay,
3679 since Windows often (always?) sends the WM_EXITMENULOOP
3680 before the corresponding WM_COMMAND message.
3681 Don't do this if a popup menu is active, since it is only
3682 menubar menus that require cleaning up in this way.
3684 if (f
&& menubar_in_use
&& current_popup_menu
== NULL
)
3685 menu_free_timer
= SetTimer (hwnd
, MENU_FREE_ID
, MENU_FREE_DELAY
, NULL
);
3687 /* If hourglass cursor should be displayed, display it now. */
3688 if (f
&& f
->output_data
.w32
->hourglass_p
)
3689 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3694 /* Direct handling of help_echo in menus. Should be safe now
3695 that we generate the help_echo by placing a help event in the
3698 HMENU menu
= (HMENU
) lParam
;
3699 UINT menu_item
= (UINT
) LOWORD (wParam
);
3700 UINT flags
= (UINT
) HIWORD (wParam
);
3702 w32_menu_display_help (hwnd
, menu
, menu_item
, flags
);
3706 case WM_MEASUREITEM
:
3707 f
= x_window_to_frame (dpyinfo
, hwnd
);
3710 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3712 if (pMis
->CtlType
== ODT_MENU
)
3714 /* Work out dimensions for popup menu titles. */
3715 char * title
= (char *) pMis
->itemData
;
3716 HDC hdc
= GetDC (hwnd
);
3717 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3718 LOGFONT menu_logfont
;
3722 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3723 menu_logfont
.lfWeight
= FW_BOLD
;
3724 menu_font
= CreateFontIndirect (&menu_logfont
);
3725 old_font
= SelectObject (hdc
, menu_font
);
3727 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3730 if (unicode_append_menu
)
3731 GetTextExtentPoint32W (hdc
, (WCHAR
*) title
,
3732 wcslen ((WCHAR
*) title
),
3735 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3737 pMis
->itemWidth
= size
.cx
;
3738 if (pMis
->itemHeight
< size
.cy
)
3739 pMis
->itemHeight
= size
.cy
;
3742 pMis
->itemWidth
= 0;
3744 SelectObject (hdc
, old_font
);
3745 DeleteObject (menu_font
);
3746 ReleaseDC (hwnd
, hdc
);
3753 f
= x_window_to_frame (dpyinfo
, hwnd
);
3756 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3758 if (pDis
->CtlType
== ODT_MENU
)
3760 /* Draw popup menu title. */
3761 char * title
= (char *) pDis
->itemData
;
3764 HDC hdc
= pDis
->hDC
;
3765 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3766 LOGFONT menu_logfont
;
3769 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3770 menu_logfont
.lfWeight
= FW_BOLD
;
3771 menu_font
= CreateFontIndirect (&menu_logfont
);
3772 old_font
= SelectObject (hdc
, menu_font
);
3774 /* Always draw title as if not selected. */
3775 if (unicode_append_menu
)
3778 + GetSystemMetrics (SM_CXMENUCHECK
),
3780 ETO_OPAQUE
, &pDis
->rcItem
,
3782 wcslen ((WCHAR
*) title
), NULL
);
3786 + GetSystemMetrics (SM_CXMENUCHECK
),
3788 ETO_OPAQUE
, &pDis
->rcItem
,
3789 title
, strlen (title
), NULL
);
3791 SelectObject (hdc
, old_font
);
3792 DeleteObject (menu_font
);
3800 /* Still not right - can't distinguish between clicks in the
3801 client area of the frame from clicks forwarded from the scroll
3802 bars - may have to hook WM_NCHITTEST to remember the mouse
3803 position and then check if it is in the client area ourselves. */
3804 case WM_MOUSEACTIVATE
:
3805 /* Discard the mouse click that activates a frame, allowing the
3806 user to click anywhere without changing point (or worse!).
3807 Don't eat mouse clicks on scrollbars though!! */
3808 if (LOWORD (lParam
) == HTCLIENT
)
3809 return MA_ACTIVATEANDEAT
;
3814 /* No longer tracking mouse. */
3815 track_mouse_window
= NULL
;
3817 case WM_ACTIVATEAPP
:
3819 case WM_WINDOWPOSCHANGED
:
3821 /* Inform lisp thread that a frame might have just been obscured
3822 or exposed, so should recheck visibility of all frames. */
3823 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3827 dpyinfo
->faked_key
= 0;
3829 register_hot_keys (hwnd
);
3832 unregister_hot_keys (hwnd
);
3835 /* Relinquish the system caret. */
3836 if (w32_system_caret_hwnd
)
3838 w32_visible_system_caret_hwnd
= NULL
;
3839 w32_system_caret_hwnd
= NULL
;
3845 f
= x_window_to_frame (dpyinfo
, hwnd
);
3846 if (f
&& HIWORD (wParam
) == 0)
3848 if (menu_free_timer
)
3850 KillTimer (hwnd
, menu_free_timer
);
3851 menu_free_timer
= 0;
3857 wmsg
.dwModifiers
= w32_get_modifiers ();
3858 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3866 wmsg
.dwModifiers
= w32_get_modifiers ();
3867 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3870 case WM_WINDOWPOSCHANGING
:
3871 /* Don't restrict the sizing of any kind of frames. If the window
3872 manager doesn't, there's no reason to do it ourselves. */
3874 if (frame_resize_pixelwise
|| hwnd
== tip_window
)
3879 /* Don't restrict the sizing of fullscreened frames, allowing them to be
3880 flush with the sides of the screen. */
3881 f
= x_window_to_frame (dpyinfo
, hwnd
);
3882 if (f
&& FRAME_PREV_FSMODE (f
) != FULLSCREEN_NONE
)
3887 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3889 wp
.length
= sizeof (WINDOWPLACEMENT
);
3890 GetWindowPlacement (hwnd
, &wp
);
3892 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
&& wp
.showCmd
!= SW_SHOWMINIMIZED
3893 && (lppos
->flags
& SWP_NOSIZE
) == 0)
3900 DWORD internal_border
;
3901 DWORD vscrollbar_extra
;
3902 DWORD hscrollbar_extra
;
3905 wp
.length
= sizeof (wp
);
3906 GetWindowRect (hwnd
, &wr
);
3910 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3911 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3912 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3913 vscrollbar_extra
= GetWindowLong (hwnd
, WND_VSCROLLBAR_INDEX
);
3914 hscrollbar_extra
= GetWindowLong (hwnd
, WND_HSCROLLBAR_INDEX
);
3918 memset (&rect
, 0, sizeof (rect
));
3919 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3920 GetMenu (hwnd
) != NULL
);
3922 /* Force width and height of client area to be exact
3923 multiples of the character cell dimensions. */
3924 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3925 - 2 * internal_border
- vscrollbar_extra
)
3927 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3928 - 2 * internal_border
- hscrollbar_extra
)
3933 /* For right/bottom sizing we can just fix the sizes.
3934 However for top/left sizing we will need to fix the X
3935 and Y positions as well. */
3937 int cx_mintrack
= GetSystemMetrics (SM_CXMINTRACK
);
3938 int cy_mintrack
= GetSystemMetrics (SM_CYMINTRACK
);
3940 lppos
->cx
= max (lppos
->cx
- wdiff
, cx_mintrack
);
3941 lppos
->cy
= max (lppos
->cy
- hdiff
, cy_mintrack
);
3943 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3944 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3946 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3953 lppos
->flags
|= SWP_NOMOVE
;
3965 case WM_GETMINMAXINFO
:
3966 /* Hack to allow resizing the Emacs frame above the screen size.
3967 Note that Windows 9x limits coordinates to 16-bits. */
3968 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.x
= 32767;
3969 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.y
= 32767;
3973 if (LOWORD (lParam
) == HTCLIENT
)
3975 f
= x_window_to_frame (dpyinfo
, hwnd
);
3976 if (f
&& f
->output_data
.w32
->hourglass_p
3977 && !menubar_in_use
&& !current_popup_menu
)
3978 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3980 SetCursor (f
->output_data
.w32
->current_cursor
);
3985 case WM_EMACS_SETCURSOR
:
3987 Cursor cursor
= (Cursor
) wParam
;
3988 f
= x_window_to_frame (dpyinfo
, hwnd
);
3991 f
->output_data
.w32
->current_cursor
= cursor
;
3992 if (!f
->output_data
.w32
->hourglass_p
)
3998 case WM_EMACS_SHOWCURSOR
:
4000 ShowCursor ((BOOL
) wParam
);
4005 case WM_EMACS_CREATEVSCROLLBAR
:
4006 return (LRESULT
) w32_createvscrollbar ((struct frame
*) wParam
,
4007 (struct scroll_bar
*) lParam
);
4009 case WM_EMACS_CREATEHSCROLLBAR
:
4010 return (LRESULT
) w32_createhscrollbar ((struct frame
*) wParam
,
4011 (struct scroll_bar
*) lParam
);
4013 case WM_EMACS_SHOWWINDOW
:
4014 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
4016 case WM_EMACS_BRINGTOTOP
:
4017 case WM_EMACS_SETFOREGROUND
:
4019 HWND foreground_window
;
4020 DWORD foreground_thread
, retval
;
4022 /* On NT 5.0, and apparently Windows 98, it is necessary to
4023 attach to the thread that currently has focus in order to
4024 pull the focus away from it. */
4025 foreground_window
= GetForegroundWindow ();
4026 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
4027 if (!foreground_window
4028 || foreground_thread
== GetCurrentThreadId ()
4029 || !AttachThreadInput (GetCurrentThreadId (),
4030 foreground_thread
, TRUE
))
4031 foreground_thread
= 0;
4033 retval
= SetForegroundWindow ((HWND
) wParam
);
4034 if (msg
== WM_EMACS_BRINGTOTOP
)
4035 retval
= BringWindowToTop ((HWND
) wParam
);
4037 /* Detach from the previous foreground thread. */
4038 if (foreground_thread
)
4039 AttachThreadInput (GetCurrentThreadId (),
4040 foreground_thread
, FALSE
);
4045 case WM_EMACS_SETWINDOWPOS
:
4047 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
4048 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
4049 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
4052 case WM_EMACS_DESTROYWINDOW
:
4053 DragAcceptFiles ((HWND
) wParam
, FALSE
);
4054 return DestroyWindow ((HWND
) wParam
);
4056 case WM_EMACS_HIDE_CARET
:
4057 return HideCaret (hwnd
);
4059 case WM_EMACS_SHOW_CARET
:
4060 return ShowCaret (hwnd
);
4062 case WM_EMACS_DESTROY_CARET
:
4063 w32_system_caret_hwnd
= NULL
;
4064 w32_visible_system_caret_hwnd
= NULL
;
4065 return DestroyCaret ();
4067 case WM_EMACS_TRACK_CARET
:
4068 /* If there is currently no system caret, create one. */
4069 if (w32_system_caret_hwnd
== NULL
)
4071 /* Use the default caret width, and avoid changing it
4072 unnecessarily, as it confuses screen reader software. */
4073 w32_system_caret_hwnd
= hwnd
;
4074 CreateCaret (hwnd
, NULL
, 0,
4075 w32_system_caret_height
);
4078 if (!SetCaretPos (w32_system_caret_x
, w32_system_caret_y
))
4080 /* Ensure visible caret gets turned on when requested. */
4081 else if (w32_use_visible_system_caret
4082 && w32_visible_system_caret_hwnd
!= hwnd
)
4084 w32_visible_system_caret_hwnd
= hwnd
;
4085 return ShowCaret (hwnd
);
4087 /* Ensure visible caret gets turned off when requested. */
4088 else if (!w32_use_visible_system_caret
4089 && w32_visible_system_caret_hwnd
)
4091 w32_visible_system_caret_hwnd
= NULL
;
4092 return HideCaret (hwnd
);
4097 case WM_EMACS_TRACKPOPUPMENU
:
4102 pos
= (POINT
*)lParam
;
4103 flags
= TPM_CENTERALIGN
;
4104 if (button_state
& LMOUSE
)
4105 flags
|= TPM_LEFTBUTTON
;
4106 else if (button_state
& RMOUSE
)
4107 flags
|= TPM_RIGHTBUTTON
;
4109 /* Remember we did a SetCapture on the initial mouse down event,
4110 so for safety, we make sure the capture is canceled now. */
4114 /* Use menubar_active to indicate that WM_INITMENU is from
4115 TrackPopupMenu below, and should be ignored. */
4116 f
= x_window_to_frame (dpyinfo
, hwnd
);
4118 f
->output_data
.w32
->menubar_active
= 1;
4120 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
4124 /* Eat any mouse messages during popupmenu */
4125 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
4127 /* Get the menu selection, if any */
4128 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
4130 retval
= LOWORD (amsg
.wParam
);
4144 case WM_EMACS_FILENOTIFY
:
4145 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4149 /* Check for messages registered at runtime. */
4150 if (msg
== msh_mousewheel
)
4152 wmsg
.dwModifiers
= w32_get_modifiers ();
4153 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4154 signal_user_input ();
4159 return (w32_unicode_gui
? DefWindowProcW
: DefWindowProcA
) (hwnd
, msg
, wParam
, lParam
);
4162 /* The most common default return code for handled messages is 0. */
4167 my_create_window (struct frame
* f
)
4170 static int coords
[2];
4171 Lisp_Object left
, top
;
4172 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4174 /* When called with RES_TYPE_NUMBER, x_get_arg will return zero for
4175 anything that is not a number and is not Qunbound. */
4176 left
= x_get_arg (dpyinfo
, Qnil
, Qleft
, "left", "Left", RES_TYPE_NUMBER
);
4177 top
= x_get_arg (dpyinfo
, Qnil
, Qtop
, "top", "Top", RES_TYPE_NUMBER
);
4178 if (EQ (left
, Qunbound
))
4179 coords
[0] = CW_USEDEFAULT
;
4181 coords
[0] = XINT (left
);
4182 if (EQ (top
, Qunbound
))
4183 coords
[1] = CW_USEDEFAULT
;
4185 coords
[1] = XINT (top
);
4187 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
,
4188 (WPARAM
)f
, (LPARAM
)coords
))
4190 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4194 /* Create a tooltip window. Unlike my_create_window, we do not do this
4195 indirectly via the Window thread, as we do not need to process Window
4196 messages for the tooltip. Creating tooltips indirectly also creates
4197 deadlocks when tooltips are created for menu items. */
4199 my_create_tip_window (struct frame
*f
)
4203 rect
.left
= rect
.top
= 0;
4204 rect
.right
= FRAME_PIXEL_WIDTH (f
);
4205 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
4207 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
4208 FRAME_EXTERNAL_MENU_BAR (f
));
4210 tip_window
= FRAME_W32_WINDOW (f
)
4211 = CreateWindow (EMACS_CLASS
,
4213 f
->output_data
.w32
->dwStyle
,
4216 rect
.right
- rect
.left
,
4217 rect
.bottom
- rect
.top
,
4218 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
4225 SetWindowLong (tip_window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
4226 SetWindowLong (tip_window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
4227 SetWindowLong (tip_window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
4228 SetWindowLong (tip_window
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
4230 /* Tip frames have no scrollbars. */
4231 SetWindowLong (tip_window
, WND_VSCROLLBAR_INDEX
, 0);
4232 SetWindowLong (tip_window
, WND_HSCROLLBAR_INDEX
, 0);
4234 /* Do this to discard the default setting specified by our parent. */
4235 ShowWindow (tip_window
, SW_HIDE
);
4240 /* Create and set up the w32 window for frame F. */
4243 w32_window (struct frame
*f
, long window_prompting
, bool minibuffer_only
)
4247 /* Use the resource name as the top-level window name
4248 for looking up resources. Make a non-Lisp copy
4249 for the window manager, so GC relocation won't bother it.
4251 Elsewhere we specify the window name for the window manager. */
4252 f
->namebuf
= xlispstrdup (Vx_resource_name
);
4254 my_create_window (f
);
4256 validate_x_resource_name ();
4258 /* x_set_name normally ignores requests to set the name if the
4259 requested name is the same as the current name. This is the one
4260 place where that assumption isn't correct; f->name is set, but
4261 the server hasn't been told. */
4264 int explicit = f
->explicit_name
;
4266 f
->explicit_name
= 0;
4268 fset_name (f
, Qnil
);
4269 x_set_name (f
, name
, explicit);
4274 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4275 initialize_frame_menubar (f
);
4277 if (FRAME_W32_WINDOW (f
) == 0)
4278 error ("Unable to create window");
4281 /* Handle the icon stuff for this window. Perhaps later we might
4282 want an x_set_icon_position which can be called interactively as
4286 x_icon (struct frame
*f
, Lisp_Object parms
)
4288 Lisp_Object icon_x
, icon_y
;
4289 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4291 /* Set the position of the icon. Note that Windows 95 groups all
4292 icons in the tray. */
4293 icon_x
= x_get_arg (dpyinfo
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4294 icon_y
= x_get_arg (dpyinfo
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4295 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4297 CHECK_NUMBER (icon_x
);
4298 CHECK_NUMBER (icon_y
);
4300 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4301 error ("Both left and top icon corners of icon must be specified");
4306 /* Start up iconic or window? */
4307 x_wm_set_window_state
4308 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4312 x_text_icon (f
, SSDATA ((!NILP (f
->icon_name
)
4322 x_make_gc (struct frame
*f
)
4324 XGCValues gc_values
;
4328 /* Create the GC's of this frame.
4329 Note that many default values are used. */
4332 gc_values
.font
= FRAME_FONT (f
);
4334 /* Cursor has cursor-color background, background-color foreground. */
4335 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
4336 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
4337 f
->output_data
.w32
->cursor_gc
4338 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
4339 (GCFont
| GCForeground
| GCBackground
),
4343 f
->output_data
.w32
->white_relief
.gc
= 0;
4344 f
->output_data
.w32
->black_relief
.gc
= 0;
4350 /* Handler for signals raised during x_create_frame and
4351 x_create_tip_frame. FRAME is the frame which is partially
4355 unwind_create_frame (Lisp_Object frame
)
4357 struct frame
*f
= XFRAME (frame
);
4359 /* If frame is ``official'', nothing to do. */
4360 if (NILP (Fmemq (frame
, Vframe_list
)))
4363 struct w32_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
4365 /* If the frame's image cache refcount is still the same as our
4366 private shadow variable, it means we are unwinding a frame
4367 for which we didn't yet call init_frame_faces, where the
4368 refcount is incremented. Therefore, we increment it here, so
4369 that free_frame_faces, called in x_free_frame_resources
4370 below, will not mistakenly decrement the counter that was not
4371 incremented yet to account for this new frame. */
4372 if (FRAME_IMAGE_CACHE (f
) != NULL
4373 && FRAME_IMAGE_CACHE (f
)->refcount
== image_cache_refcount
)
4374 FRAME_IMAGE_CACHE (f
)->refcount
++;
4377 x_free_frame_resources (f
);
4381 /* Check that reference counts are indeed correct. */
4382 eassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4383 eassert ((dpyinfo
->terminal
->image_cache
== NULL
4384 && image_cache_refcount
== 0)
4385 || (dpyinfo
->terminal
->image_cache
!= NULL
4386 && dpyinfo
->terminal
->image_cache
->refcount
== image_cache_refcount
));
4395 do_unwind_create_frame (Lisp_Object frame
)
4397 unwind_create_frame (frame
);
4401 unwind_create_frame_1 (Lisp_Object val
)
4403 inhibit_lisp_code
= val
;
4407 x_default_font_parameter (struct frame
*f
, Lisp_Object parms
)
4409 struct w32_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (f
);
4410 Lisp_Object font_param
= x_get_arg (dpyinfo
, parms
, Qfont
, NULL
, NULL
,
4413 if (EQ (font_param
, Qunbound
))
4415 font
= !NILP (font_param
) ? font_param
4416 : x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4418 if (!STRINGP (font
))
4421 static char *names
[]
4422 = { "Courier New-10",
4423 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4424 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4428 for (i
= 0; names
[i
]; i
++)
4430 font
= font_open_by_name (f
, build_unibyte_string (names
[i
]));
4435 error ("No suitable font was found");
4437 else if (!NILP (font_param
))
4439 /* Remember the explicit font parameter, so we can re-apply it after
4440 we've applied the `default' face settings. */
4441 x_set_frame_parameters (f
, Fcons (Fcons (Qfont_param
, font_param
), Qnil
));
4443 x_default_parameter (f
, parms
, Qfont
, font
, "font", "Font", RES_TYPE_STRING
);
4446 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4448 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
4449 Return an Emacs frame object.
4450 PARAMETERS is an alist of frame parameters.
4451 If the parameters specify that the frame should not have a minibuffer,
4452 and do not specify a specific minibuffer window to use,
4453 then `default-minibuffer-frame' must be a frame whose minibuffer can
4454 be shared by the new frame.
4456 This function is an internal primitive--use `make-frame' instead. */)
4457 (Lisp_Object parameters
)
4460 Lisp_Object frame
, tem
;
4462 bool minibuffer_only
= false;
4463 long window_prompting
= 0;
4464 ptrdiff_t count
= SPECPDL_INDEX ();
4465 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4466 Lisp_Object display
;
4467 struct w32_display_info
*dpyinfo
= NULL
;
4471 if (!FRAME_W32_P (SELECTED_FRAME ())
4472 && !FRAME_INITIAL_P (SELECTED_FRAME ()))
4473 error ("Cannot create a GUI frame in a -nw session");
4475 /* Make copy of frame parameters because the original is in pure
4477 parameters
= Fcopy_alist (parameters
);
4479 /* Use this general default value to start with
4480 until we know if this frame has a specified name. */
4481 Vx_resource_name
= Vinvocation_name
;
4483 display
= x_get_arg (dpyinfo
, parameters
, Qterminal
, 0, 0, RES_TYPE_NUMBER
);
4484 if (EQ (display
, Qunbound
))
4485 display
= x_get_arg (dpyinfo
, parameters
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4486 if (EQ (display
, Qunbound
))
4488 dpyinfo
= check_x_display_info (display
);
4489 kb
= dpyinfo
->terminal
->kboard
;
4491 if (!dpyinfo
->terminal
->name
)
4492 error ("Terminal is not live, can't create new frames on it");
4494 name
= x_get_arg (dpyinfo
, parameters
, Qname
, "name", "Name", RES_TYPE_STRING
);
4496 && ! EQ (name
, Qunbound
)
4498 error ("Invalid frame name--not a string or nil");
4501 Vx_resource_name
= name
;
4503 /* See if parent window is specified. */
4504 parent
= x_get_arg (dpyinfo
, parameters
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4505 if (EQ (parent
, Qunbound
))
4507 if (! NILP (parent
))
4508 CHECK_NUMBER (parent
);
4510 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4511 /* No need to protect DISPLAY because that's not used after passing
4512 it to make_frame_without_minibuffer. */
4514 GCPRO4 (parameters
, parent
, name
, frame
);
4515 tem
= x_get_arg (dpyinfo
, parameters
, Qminibuffer
, "minibuffer", "Minibuffer",
4517 if (EQ (tem
, Qnone
) || NILP (tem
))
4518 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4519 else if (EQ (tem
, Qonly
))
4521 f
= make_minibuffer_frame ();
4522 minibuffer_only
= true;
4524 else if (WINDOWP (tem
))
4525 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4527 f
= make_frame (true);
4529 XSETFRAME (frame
, f
);
4531 /* By default, make scrollbars the system standard width and height. */
4532 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
4533 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f
) = GetSystemMetrics (SM_CXHSCROLL
);
4535 f
->terminal
= dpyinfo
->terminal
;
4537 f
->output_method
= output_w32
;
4538 f
->output_data
.w32
= xzalloc (sizeof (struct w32_output
));
4539 FRAME_FONTSET (f
) = -1;
4542 (f
, x_get_arg (dpyinfo
, parameters
, Qicon_name
, "iconName", "Title",
4544 if (! STRINGP (f
->icon_name
))
4545 fset_icon_name (f
, Qnil
);
4547 /* FRAME_DISPLAY_INFO (f) = dpyinfo; */
4549 /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
4550 record_unwind_protect (do_unwind_create_frame
, frame
);
4553 image_cache_refcount
=
4554 FRAME_IMAGE_CACHE (f
) ? FRAME_IMAGE_CACHE (f
)->refcount
: 0;
4555 dpyinfo_refcount
= dpyinfo
->reference_count
;
4556 #endif /* GLYPH_DEBUG */
4558 /* Specify the parent under which to make this window. */
4561 /* Cast to UINT_PTR shuts up compiler warnings about cast to
4562 pointer from integer of different size. */
4563 f
->output_data
.w32
->parent_desc
= (Window
) (UINT_PTR
) XFASTINT (parent
);
4564 f
->output_data
.w32
->explicit_parent
= true;
4568 f
->output_data
.w32
->parent_desc
= FRAME_DISPLAY_INFO (f
)->root_window
;
4569 f
->output_data
.w32
->explicit_parent
= false;
4572 /* Set the name; the functions to which we pass f expect the name to
4574 if (EQ (name
, Qunbound
) || NILP (name
))
4576 fset_name (f
, build_string (dpyinfo
->w32_id_name
));
4577 f
->explicit_name
= false;
4581 fset_name (f
, name
);
4582 f
->explicit_name
= true;
4583 /* Use the frame's title when getting resources for this frame. */
4584 specbind (Qx_resource_name
, name
);
4587 if (uniscribe_available
)
4588 register_font_driver (&uniscribe_font_driver
, f
);
4589 register_font_driver (&w32font_driver
, f
);
4591 x_default_parameter (f
, parameters
, Qfont_backend
, Qnil
,
4592 "fontBackend", "FontBackend", RES_TYPE_STRING
);
4594 /* Extract the window parameters from the supplied values
4595 that are needed to determine window geometry. */
4596 x_default_font_parameter (f
, parameters
);
4598 x_default_parameter (f
, parameters
, Qborder_width
, make_number (2),
4599 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4601 /* We recognize either internalBorderWidth or internalBorder
4602 (which is what xterm calls it). */
4603 if (NILP (Fassq (Qinternal_border_width
, parameters
)))
4607 value
= x_get_arg (dpyinfo
, parameters
, Qinternal_border_width
,
4608 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
4609 if (! EQ (value
, Qunbound
))
4610 parameters
= Fcons (Fcons (Qinternal_border_width
, value
),
4613 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4614 x_default_parameter (f
, parameters
, Qinternal_border_width
, make_number (0),
4615 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4616 x_default_parameter (f
, parameters
, Qright_divider_width
, make_number (0),
4617 NULL
, NULL
, RES_TYPE_NUMBER
);
4618 x_default_parameter (f
, parameters
, Qbottom_divider_width
, make_number (0),
4619 NULL
, NULL
, RES_TYPE_NUMBER
);
4620 x_default_parameter (f
, parameters
, Qvertical_scroll_bars
, Qright
,
4621 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4622 x_default_parameter (f
, parameters
, Qhorizontal_scroll_bars
, Qnil
,
4623 "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4625 /* Also do the stuff which must be set before the window exists. */
4626 x_default_parameter (f
, parameters
, Qforeground_color
, build_string ("black"),
4627 "foreground", "Foreground", RES_TYPE_STRING
);
4628 x_default_parameter (f
, parameters
, Qbackground_color
, build_string ("white"),
4629 "background", "Background", RES_TYPE_STRING
);
4630 x_default_parameter (f
, parameters
, Qmouse_color
, build_string ("black"),
4631 "pointerColor", "Foreground", RES_TYPE_STRING
);
4632 x_default_parameter (f
, parameters
, Qborder_color
, build_string ("black"),
4633 "borderColor", "BorderColor", RES_TYPE_STRING
);
4634 x_default_parameter (f
, parameters
, Qscreen_gamma
, Qnil
,
4635 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4636 x_default_parameter (f
, parameters
, Qline_spacing
, Qnil
,
4637 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4638 x_default_parameter (f
, parameters
, Qleft_fringe
, Qnil
,
4639 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4640 x_default_parameter (f
, parameters
, Qright_fringe
, Qnil
,
4641 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4642 /* Process alpha here (Bug#16619). */
4643 x_default_parameter (f
, parameters
, Qalpha
, Qnil
,
4644 "alpha", "Alpha", RES_TYPE_NUMBER
);
4646 /* Init faces first since we need the frame's column width/line
4647 height in various occasions. */
4648 init_frame_faces (f
);
4650 /* The following call of change_frame_size is needed since otherwise
4651 x_set_tool_bar_lines will already work with the character sizes
4652 installed by init_frame_faces while the frame's pixel size is
4653 still calculated from a character size of 1 and we subsequently
4654 hit the (height >= 0) assertion in window_box_height.
4656 The non-pixelwise code apparently worked around this because it
4657 had one frame line vs one toolbar line which left us with a zero
4658 root window height which was obviously wrong as well ... */
4659 adjust_frame_size (f
, FRAME_COLS (f
) * FRAME_COLUMN_WIDTH (f
),
4660 FRAME_LINES (f
) * FRAME_LINE_HEIGHT (f
), 5, true,
4663 /* The X resources controlling the menu-bar and tool-bar are
4664 processed specially at startup, and reflected in the mode
4665 variables; ignore them here. */
4666 x_default_parameter (f
, parameters
, Qmenu_bar_lines
,
4667 NILP (Vmenu_bar_mode
)
4668 ? make_number (0) : make_number (1),
4669 NULL
, NULL
, RES_TYPE_NUMBER
);
4670 x_default_parameter (f
, parameters
, Qtool_bar_lines
,
4671 NILP (Vtool_bar_mode
)
4672 ? make_number (0) : make_number (1),
4673 NULL
, NULL
, RES_TYPE_NUMBER
);
4675 x_default_parameter (f
, parameters
, Qbuffer_predicate
, Qnil
,
4676 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
4677 x_default_parameter (f
, parameters
, Qtitle
, Qnil
,
4678 "title", "Title", RES_TYPE_STRING
);
4680 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4681 f
->output_data
.w32
->parent_desc
= FRAME_DISPLAY_INFO (f
)->root_window
;
4683 f
->output_data
.w32
->text_cursor
= w32_load_cursor (IDC_IBEAM
);
4684 f
->output_data
.w32
->nontext_cursor
= w32_load_cursor (IDC_ARROW
);
4685 f
->output_data
.w32
->modeline_cursor
= w32_load_cursor (IDC_ARROW
);
4686 f
->output_data
.w32
->hand_cursor
= w32_load_cursor (IDC_HAND
);
4687 f
->output_data
.w32
->hourglass_cursor
= w32_load_cursor (IDC_WAIT
);
4688 f
->output_data
.w32
->horizontal_drag_cursor
= w32_load_cursor (IDC_SIZEWE
);
4689 f
->output_data
.w32
->vertical_drag_cursor
= w32_load_cursor (IDC_SIZENS
);
4691 f
->output_data
.w32
->current_cursor
= f
->output_data
.w32
->nontext_cursor
;
4693 window_prompting
= x_figure_window_size (f
, parameters
, true);
4695 tem
= x_get_arg (dpyinfo
, parameters
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4696 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4698 w32_window (f
, window_prompting
, minibuffer_only
);
4699 x_icon (f
, parameters
);
4703 /* Now consider the frame official. */
4704 f
->terminal
->reference_count
++;
4705 FRAME_DISPLAY_INFO (f
)->reference_count
++;
4706 Vframe_list
= Fcons (frame
, Vframe_list
);
4708 /* We need to do this after creating the window, so that the
4709 icon-creation functions can say whose icon they're describing. */
4710 x_default_parameter (f
, parameters
, Qicon_type
, Qnil
,
4711 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4713 x_default_parameter (f
, parameters
, Qauto_raise
, Qnil
,
4714 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4715 x_default_parameter (f
, parameters
, Qauto_lower
, Qnil
,
4716 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4717 x_default_parameter (f
, parameters
, Qcursor_type
, Qbox
,
4718 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4719 x_default_parameter (f
, parameters
, Qscroll_bar_width
, Qnil
,
4720 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4721 x_default_parameter (f
, parameters
, Qscroll_bar_height
, Qnil
,
4722 "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER
);
4724 /* Allow x_set_window_size, now. */
4725 f
->can_x_set_window_size
= true;
4727 adjust_frame_size (f
, FRAME_TEXT_WIDTH (f
), FRAME_TEXT_HEIGHT (f
), 0, true,
4730 /* Tell the server what size and position, etc, we want, and how
4731 badly we want them. This should be done after we have the menu
4732 bar so that its size can be taken into account. */
4734 x_wm_set_size_hint (f
, window_prompting
, false);
4737 /* Process fullscreen parameter here in the hope that normalizing a
4738 fullheight/fullwidth frame will produce the size set by the last
4739 adjust_frame_size call. */
4740 x_default_parameter (f
, parameters
, Qfullscreen
, Qnil
,
4741 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4743 /* Make the window appear on the frame and enable display, unless
4744 the caller says not to. However, with explicit parent, Emacs
4745 cannot control visibility, so don't try. */
4746 if (! f
->output_data
.w32
->explicit_parent
)
4748 Lisp_Object visibility
;
4750 visibility
= x_get_arg (dpyinfo
, parameters
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4751 if (EQ (visibility
, Qunbound
))
4754 if (EQ (visibility
, Qicon
))
4755 x_iconify_frame (f
);
4756 else if (! NILP (visibility
))
4757 x_make_frame_visible (f
);
4759 /* Must have been Qnil. */
4763 /* Initialize `default-minibuffer-frame' in case this is the first
4764 frame on this terminal. */
4765 if (FRAME_HAS_MINIBUF_P (f
)
4766 && (!FRAMEP (KVAR (kb
, Vdefault_minibuffer_frame
))
4767 || !FRAME_LIVE_P (XFRAME (KVAR (kb
, Vdefault_minibuffer_frame
)))))
4768 kset_default_minibuffer_frame (kb
, frame
);
4770 /* All remaining specified parameters, which have not been "used"
4771 by x_get_arg and friends, now go in the misc. alist of the frame. */
4772 for (tem
= parameters
; CONSP (tem
); tem
= XCDR (tem
))
4773 if (CONSP (XCAR (tem
)) && !NILP (XCAR (XCAR (tem
))))
4774 fset_param_alist (f
, Fcons (XCAR (tem
), f
->param_alist
));
4778 /* Make sure windows on this frame appear in calls to next-window
4779 and similar functions. */
4780 Vwindow_list
= Qnil
;
4782 return unbind_to (count
, frame
);
4785 /* FRAME is used only to get a handle on the X display. We don't pass the
4786 display info directly because we're called from frame.c, which doesn't
4787 know about that structure. */
4789 x_get_focus_frame (struct frame
*frame
)
4791 struct w32_display_info
*dpyinfo
= FRAME_DISPLAY_INFO (frame
);
4793 if (! dpyinfo
->w32_focus_frame
)
4796 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4800 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4801 doc
: /* Internal function called by `color-defined-p', which see.
4802 \(Note that the Nextstep version of this function ignores FRAME.) */)
4803 (Lisp_Object color
, Lisp_Object frame
)
4806 struct frame
*f
= decode_window_system_frame (frame
);
4808 CHECK_STRING (color
);
4810 if (w32_defined_color (f
, SDATA (color
), &foo
, false))
4816 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4817 doc
: /* Internal function called by `color-values', which see. */)
4818 (Lisp_Object color
, Lisp_Object frame
)
4821 struct frame
*f
= decode_window_system_frame (frame
);
4823 CHECK_STRING (color
);
4825 if (w32_defined_color (f
, SDATA (color
), &foo
, false))
4826 return list3i ((GetRValue (foo
.pixel
) << 8) | GetRValue (foo
.pixel
),
4827 (GetGValue (foo
.pixel
) << 8) | GetGValue (foo
.pixel
),
4828 (GetBValue (foo
.pixel
) << 8) | GetBValue (foo
.pixel
));
4833 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4834 doc
: /* Internal function called by `display-color-p', which see. */)
4835 (Lisp_Object display
)
4837 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4839 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
4845 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
,
4846 Sx_display_grayscale_p
, 0, 1, 0,
4847 doc
: /* Return t if DISPLAY supports shades of gray.
4848 Note that color displays do support shades of gray.
4849 The optional argument DISPLAY specifies which display to ask about.
4850 DISPLAY should be either a frame or a display name (a string).
4851 If omitted or nil, that stands for the selected frame's display. */)
4852 (Lisp_Object display
)
4854 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4856 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
4862 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
,
4863 Sx_display_pixel_width
, 0, 1, 0,
4864 doc
: /* Return the width in pixels of DISPLAY.
4865 The optional argument DISPLAY specifies which display to ask about.
4866 DISPLAY should be either a frame or a display name (a string).
4867 If omitted or nil, that stands for the selected frame's display.
4869 On \"multi-monitor\" setups this refers to the pixel width for all
4870 physical monitors associated with DISPLAY. To get information for
4871 each physical monitor, use `display-monitor-attributes-list'. */)
4872 (Lisp_Object display
)
4874 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4876 return make_number (x_display_pixel_width (dpyinfo
));
4879 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4880 Sx_display_pixel_height
, 0, 1, 0,
4881 doc
: /* Return the height in pixels of DISPLAY.
4882 The optional argument DISPLAY specifies which display to ask about.
4883 DISPLAY should be either a frame or a display name (a string).
4884 If omitted or nil, that stands for the selected frame's display.
4886 On \"multi-monitor\" setups this refers to the pixel height for all
4887 physical monitors associated with DISPLAY. To get information for
4888 each physical monitor, use `display-monitor-attributes-list'. */)
4889 (Lisp_Object display
)
4891 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4893 return make_number (x_display_pixel_height (dpyinfo
));
4896 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4898 doc
: /* Return the number of bitplanes of DISPLAY.
4899 The optional argument DISPLAY specifies which display to ask about.
4900 DISPLAY should be either a frame or a display name (a string).
4901 If omitted or nil, that stands for the selected frame's display. */)
4902 (Lisp_Object display
)
4904 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4906 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
4909 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4911 doc
: /* Return the number of color cells of DISPLAY.
4912 The optional argument DISPLAY specifies which display to ask about.
4913 DISPLAY should be either a frame or a display name (a string).
4914 If omitted or nil, that stands for the selected frame's display. */)
4915 (Lisp_Object display
)
4917 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4920 /* Don't use NCOLORS: it returns incorrect results under remote
4921 * desktop. We force 24+ bit depths to 24-bit, both to prevent an
4922 * overflow and because probably is more meaningful on Windows
4925 cap
= 1 << min (dpyinfo
->n_planes
* dpyinfo
->n_cbits
, 24);
4926 return make_number (cap
);
4929 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4930 Sx_server_max_request_size
,
4932 doc
: /* Return the maximum request size of the server of DISPLAY.
4933 The optional argument DISPLAY specifies which display to ask about.
4934 DISPLAY should be either a frame or a display name (a string).
4935 If omitted or nil, that stands for the selected frame's display. */)
4936 (Lisp_Object display
)
4938 return make_number (1);
4941 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4942 doc
: /* Return the "vendor ID" string of the GUI software on TERMINAL.
4944 \(Labeling every distributor as a "vendor" embodies the false assumption
4945 that operating systems cannot be developed and distributed noncommercially.)
4947 For GNU and Unix systems, this queries the X server software; for
4948 MS-Windows, this queries the OS.
4950 The optional argument TERMINAL specifies which display to ask about.
4951 TERMINAL should be a terminal object, a frame or a display name (a string).
4952 If omitted or nil, that stands for the selected frame's display. */)
4953 (Lisp_Object terminal
)
4955 return build_string ("Microsoft Corp.");
4958 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4959 doc
: /* Return the version numbers of the GUI software on TERMINAL.
4960 The value is a list of three integers specifying the version of the GUI
4963 For GNU and Unix system, the first 2 numbers are the version of the X
4964 Protocol used on TERMINAL and the 3rd number is the distributor-specific
4965 release number. For MS-Windows, the 3 numbers report the version and
4966 the build number of the OS.
4968 See also the function `x-server-vendor'.
4970 The optional argument TERMINAL specifies which display to ask about.
4971 TERMINAL should be a terminal object, a frame or a display name (a string).
4972 If omitted or nil, that stands for the selected frame's display. */)
4973 (Lisp_Object terminal
)
4975 return list3i (w32_major_version
, w32_minor_version
, w32_build_number
);
4978 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4979 doc
: /* Return the number of screens on the server of DISPLAY.
4980 The optional argument DISPLAY specifies which display to ask about.
4981 DISPLAY should be either a frame or a display name (a string).
4982 If omitted or nil, that stands for the selected frame's display. */)
4983 (Lisp_Object display
)
4985 return make_number (1);
4988 DEFUN ("x-display-mm-height", Fx_display_mm_height
,
4989 Sx_display_mm_height
, 0, 1, 0,
4990 doc
: /* Return the height in millimeters of DISPLAY.
4991 The optional argument DISPLAY specifies which display to ask about.
4992 DISPLAY should be either a frame or a display name (a string).
4993 If omitted or nil, that stands for the selected frame's display.
4995 On \"multi-monitor\" setups this refers to the height in millimeters for
4996 all physical monitors associated with DISPLAY. To get information
4997 for each physical monitor, use `display-monitor-attributes-list'. */)
4998 (Lisp_Object display
)
5000 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5002 double mm_per_pixel
;
5005 mm_per_pixel
= ((double) GetDeviceCaps (hdc
, VERTSIZE
)
5006 / GetDeviceCaps (hdc
, VERTRES
));
5007 ReleaseDC (NULL
, hdc
);
5009 return make_number (x_display_pixel_height (dpyinfo
) * mm_per_pixel
+ 0.5);
5012 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
5013 doc
: /* Return the width in millimeters of DISPLAY.
5014 The optional argument DISPLAY specifies which display to ask about.
5015 DISPLAY should be either a frame or a display name (a string).
5016 If omitted or nil, that stands for the selected frame's display.
5018 On \"multi-monitor\" setups this refers to the width in millimeters for
5019 all physical monitors associated with TERMINAL. To get information
5020 for each physical monitor, use `display-monitor-attributes-list'. */)
5021 (Lisp_Object display
)
5023 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5025 double mm_per_pixel
;
5028 mm_per_pixel
= ((double) GetDeviceCaps (hdc
, HORZSIZE
)
5029 / GetDeviceCaps (hdc
, HORZRES
));
5030 ReleaseDC (NULL
, hdc
);
5032 return make_number (x_display_pixel_width (dpyinfo
) * mm_per_pixel
+ 0.5);
5035 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
5036 Sx_display_backing_store
, 0, 1, 0,
5037 doc
: /* Return an indication of whether DISPLAY does backing store.
5038 The value may be `always', `when-mapped', or `not-useful'.
5039 The optional argument DISPLAY specifies which display to ask about.
5040 DISPLAY should be either a frame or a display name (a string).
5041 If omitted or nil, that stands for the selected frame's display. */)
5042 (Lisp_Object display
)
5044 return intern ("not-useful");
5047 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5048 Sx_display_visual_class
, 0, 1, 0,
5049 doc
: /* Return the visual class of DISPLAY.
5050 The value is one of the symbols `static-gray', `gray-scale',
5051 `static-color', `pseudo-color', `true-color', or `direct-color'.
5053 The optional argument DISPLAY specifies which display to ask about.
5054 DISPLAY should be either a frame or a display name (a string).
5055 If omitted or nil, that stands for the selected frame's display. */)
5056 (Lisp_Object display
)
5058 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5059 Lisp_Object result
= Qnil
;
5061 if (dpyinfo
->has_palette
)
5062 result
= intern ("pseudo-color");
5063 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 1)
5064 result
= intern ("static-grey");
5065 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 4)
5066 result
= intern ("static-color");
5067 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
> 8)
5068 result
= intern ("true-color");
5073 DEFUN ("x-display-save-under", Fx_display_save_under
,
5074 Sx_display_save_under
, 0, 1, 0,
5075 doc
: /* Return t if DISPLAY supports the save-under feature.
5076 The optional argument DISPLAY specifies which display to ask about.
5077 DISPLAY should be either a frame or a display name (a string).
5078 If omitted or nil, that stands for the selected frame's display. */)
5079 (Lisp_Object display
)
5084 static BOOL CALLBACK ALIGN_STACK
5085 w32_monitor_enum (HMONITOR monitor
, HDC hdc
, RECT
*rcMonitor
, LPARAM dwData
)
5087 Lisp_Object
*monitor_list
= (Lisp_Object
*) dwData
;
5089 *monitor_list
= Fcons (make_save_ptr (monitor
), *monitor_list
);
5095 w32_display_monitor_attributes_list (void)
5097 Lisp_Object attributes_list
= Qnil
, primary_monitor_attributes
= Qnil
;
5098 Lisp_Object monitor_list
= Qnil
, monitor_frames
, rest
, frame
;
5101 struct gcpro gcpro1
, gcpro2
, gcpro3
;
5103 if (!(enum_display_monitors_fn
&& get_monitor_info_fn
5104 && monitor_from_window_fn
))
5107 if (!enum_display_monitors_fn (NULL
, NULL
, w32_monitor_enum
,
5108 (LPARAM
) &monitor_list
)
5109 || NILP (monitor_list
))
5113 for (rest
= monitor_list
; CONSP (rest
); rest
= XCDR (rest
))
5116 monitors
= xmalloc (n_monitors
* sizeof (*monitors
));
5117 for (i
= 0; i
< n_monitors
; i
++)
5119 monitors
[i
] = XSAVE_POINTER (XCAR (monitor_list
), 0);
5120 monitor_list
= XCDR (monitor_list
);
5123 monitor_frames
= Fmake_vector (make_number (n_monitors
), Qnil
);
5124 FOR_EACH_FRAME (rest
, frame
)
5126 struct frame
*f
= XFRAME (frame
);
5128 if (FRAME_W32_P (f
) && !EQ (frame
, tip_frame
))
5131 monitor_from_window_fn (FRAME_W32_WINDOW (f
),
5132 MONITOR_DEFAULT_TO_NEAREST
);
5134 for (i
= 0; i
< n_monitors
; i
++)
5135 if (monitors
[i
] == monitor
)
5139 ASET (monitor_frames
, i
, Fcons (frame
, AREF (monitor_frames
, i
)));
5143 GCPRO3 (attributes_list
, primary_monitor_attributes
, monitor_frames
);
5145 for (i
= 0; i
< n_monitors
; i
++)
5147 Lisp_Object geometry
, workarea
, name
, attributes
= Qnil
;
5149 int width_mm
, height_mm
;
5150 struct MONITOR_INFO_EX mi
;
5152 mi
.cbSize
= sizeof (mi
);
5153 if (!get_monitor_info_fn (monitors
[i
], (struct MONITOR_INFO
*) &mi
))
5156 hdc
= CreateDCA ("DISPLAY", mi
.szDevice
, NULL
, NULL
);
5159 width_mm
= GetDeviceCaps (hdc
, HORZSIZE
);
5160 height_mm
= GetDeviceCaps (hdc
, VERTSIZE
);
5163 attributes
= Fcons (Fcons (Qframes
, AREF (monitor_frames
, i
)),
5166 name
= DECODE_SYSTEM (build_unibyte_string (mi
.szDevice
));
5168 attributes
= Fcons (Fcons (Qname
, name
), attributes
);
5170 attributes
= Fcons (Fcons (Qmm_size
, list2i (width_mm
, height_mm
)),
5173 workarea
= list4i (mi
.rcWork
.left
, mi
.rcWork
.top
,
5174 mi
.rcWork
.right
- mi
.rcWork
.left
,
5175 mi
.rcWork
.bottom
- mi
.rcWork
.top
);
5176 attributes
= Fcons (Fcons (Qworkarea
, workarea
), attributes
);
5178 geometry
= list4i (mi
.rcMonitor
.left
, mi
.rcMonitor
.top
,
5179 mi
.rcMonitor
.right
- mi
.rcMonitor
.left
,
5180 mi
.rcMonitor
.bottom
- mi
.rcMonitor
.top
);
5181 attributes
= Fcons (Fcons (Qgeometry
, geometry
), attributes
);
5183 if (mi
.dwFlags
& MONITORINFOF_PRIMARY
)
5184 primary_monitor_attributes
= attributes
;
5186 attributes_list
= Fcons (attributes
, attributes_list
);
5189 if (!NILP (primary_monitor_attributes
))
5190 attributes_list
= Fcons (primary_monitor_attributes
, attributes_list
);
5196 return attributes_list
;
5200 w32_display_monitor_attributes_list_fallback (struct w32_display_info
*dpyinfo
)
5202 Lisp_Object geometry
, workarea
, frames
, rest
, frame
, attributes
= Qnil
;
5204 double mm_per_pixel
;
5205 int pixel_width
, pixel_height
, width_mm
, height_mm
;
5208 /* Fallback: treat (possibly) multiple physical monitors as if they
5209 formed a single monitor as a whole. This should provide a
5210 consistent result at least on single monitor environments. */
5211 attributes
= Fcons (Fcons (Qname
, build_string ("combined screen")),
5215 FOR_EACH_FRAME (rest
, frame
)
5217 struct frame
*f
= XFRAME (frame
);
5219 if (FRAME_W32_P (f
) && !EQ (frame
, tip_frame
))
5220 frames
= Fcons (frame
, frames
);
5222 attributes
= Fcons (Fcons (Qframes
, frames
), attributes
);
5224 pixel_width
= x_display_pixel_width (dpyinfo
);
5225 pixel_height
= x_display_pixel_height (dpyinfo
);
5228 mm_per_pixel
= ((double) GetDeviceCaps (hdc
, HORZSIZE
)
5229 / GetDeviceCaps (hdc
, HORZRES
));
5230 width_mm
= pixel_width
* mm_per_pixel
+ 0.5;
5231 mm_per_pixel
= ((double) GetDeviceCaps (hdc
, VERTSIZE
)
5232 / GetDeviceCaps (hdc
, VERTRES
));
5233 height_mm
= pixel_height
* mm_per_pixel
+ 0.5;
5234 ReleaseDC (NULL
, hdc
);
5235 attributes
= Fcons (Fcons (Qmm_size
, list2i (width_mm
, height_mm
)),
5238 /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but
5240 geometry
= list4i (GetSystemMetrics (SM_XVIRTUALSCREEN
),
5241 GetSystemMetrics (SM_YVIRTUALSCREEN
),
5242 pixel_width
, pixel_height
);
5243 if (SystemParametersInfo (SPI_GETWORKAREA
, 0, &workarea_rect
, 0))
5244 workarea
= list4i (workarea_rect
.left
, workarea_rect
.top
,
5245 workarea_rect
.right
- workarea_rect
.left
,
5246 workarea_rect
.bottom
- workarea_rect
.top
);
5248 workarea
= geometry
;
5249 attributes
= Fcons (Fcons (Qworkarea
, workarea
), attributes
);
5251 attributes
= Fcons (Fcons (Qgeometry
, geometry
), attributes
);
5253 return list1 (attributes
);
5256 DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list
,
5257 Sw32_display_monitor_attributes_list
,
5259 doc
: /* Return a list of physical monitor attributes on the W32 display DISPLAY.
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.
5265 Internal use only, use `display-monitor-attributes-list' instead. */)
5266 (Lisp_Object display
)
5268 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5269 Lisp_Object attributes_list
;
5272 attributes_list
= w32_display_monitor_attributes_list ();
5273 if (NILP (attributes_list
))
5274 attributes_list
= w32_display_monitor_attributes_list_fallback (dpyinfo
);
5277 return attributes_list
;
5280 DEFUN ("set-message-beep", Fset_message_beep
, Sset_message_beep
, 1, 1, 0,
5281 doc
: /* Set the sound generated when the bell is rung.
5282 SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
5283 to use the corresponding system sound for the bell. The 'silent sound
5284 prevents Emacs from making any sound at all.
5285 SOUND is nil to use the normal beep. */)
5288 CHECK_SYMBOL (sound
);
5291 sound_type
= 0xFFFFFFFF;
5292 else if (EQ (sound
, intern ("asterisk")))
5293 sound_type
= MB_ICONASTERISK
;
5294 else if (EQ (sound
, intern ("exclamation")))
5295 sound_type
= MB_ICONEXCLAMATION
;
5296 else if (EQ (sound
, intern ("hand")))
5297 sound_type
= MB_ICONHAND
;
5298 else if (EQ (sound
, intern ("question")))
5299 sound_type
= MB_ICONQUESTION
;
5300 else if (EQ (sound
, intern ("ok")))
5302 else if (EQ (sound
, intern ("silent")))
5303 sound_type
= MB_EMACS_SILENT
;
5305 sound_type
= 0xFFFFFFFF;
5311 x_screen_planes (register struct frame
*f
)
5313 return FRAME_DISPLAY_INFO (f
)->n_planes
;
5316 /* Return the display structure for the display named NAME.
5317 Open a new connection if necessary. */
5319 struct w32_display_info
*
5320 x_display_info_for_name (Lisp_Object name
)
5322 struct w32_display_info
*dpyinfo
;
5324 CHECK_STRING (name
);
5326 for (dpyinfo
= &one_w32_display_info
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
5327 if (!NILP (Fstring_equal (XCAR (dpyinfo
->name_list_element
), name
)))
5330 /* Use this general default value to start with. */
5331 Vx_resource_name
= Vinvocation_name
;
5333 validate_x_resource_name ();
5335 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
5336 SSDATA (Vx_resource_name
));
5339 error ("Cannot connect to server %s", SDATA (name
));
5341 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
5346 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5347 1, 3, 0, doc
: /* Open a connection to a display server.
5348 DISPLAY is the name of the display to connect to.
5349 Optional second arg XRM-STRING is a string of resources in xrdb format.
5350 If the optional third arg MUST-SUCCEED is non-nil,
5351 terminate Emacs if we can't open the connection.
5352 \(In the Nextstep version, the last two arguments are currently ignored.) */)
5353 (Lisp_Object display
, Lisp_Object xrm_string
, Lisp_Object must_succeed
)
5355 unsigned char *xrm_option
;
5356 struct w32_display_info
*dpyinfo
;
5358 CHECK_STRING (display
);
5360 /* Signal an error in order to encourage correct use from callers.
5361 * If we ever support multiple window systems in the same Emacs,
5362 * we'll need callers to be precise about what window system they
5365 if (strcmp (SSDATA (display
), "w32") != 0)
5366 error ("The name of the display in this Emacs must be \"w32\"");
5368 /* If initialization has already been done, return now to avoid
5369 overwriting critical parts of one_w32_display_info. */
5370 if (window_system_available (NULL
))
5373 if (! NILP (xrm_string
))
5374 CHECK_STRING (xrm_string
);
5376 /* Allow color mapping to be defined externally; first look in user's
5377 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
5379 Lisp_Object color_file
;
5380 struct gcpro gcpro1
;
5382 color_file
= build_string ("~/rgb.txt");
5384 GCPRO1 (color_file
);
5386 if (NILP (Ffile_readable_p (color_file
)))
5388 Fexpand_file_name (build_string ("rgb.txt"),
5389 Fsymbol_value (intern ("data-directory")));
5391 Vw32_color_map
= Fx_load_color_file (color_file
);
5395 if (NILP (Vw32_color_map
))
5396 Vw32_color_map
= w32_default_color_map ();
5398 /* Merge in system logical colors. */
5399 add_system_logical_colors_to_map (&Vw32_color_map
);
5401 if (! NILP (xrm_string
))
5402 xrm_option
= SDATA (xrm_string
);
5404 xrm_option
= (unsigned char *) 0;
5406 /* Use this general default value to start with. */
5407 /* First remove .exe suffix from invocation-name - it looks ugly. */
5409 char basename
[ MAX_PATH
], *str
;
5411 lispstpcpy (basename
, Vinvocation_name
);
5412 str
= strrchr (basename
, '.');
5414 Vinvocation_name
= build_string (basename
);
5416 Vx_resource_name
= Vinvocation_name
;
5418 validate_x_resource_name ();
5420 /* This is what opens the connection and sets x_current_display.
5421 This also initializes many symbols, such as those used for input. */
5422 dpyinfo
= w32_term_init (display
, xrm_option
,
5423 SSDATA (Vx_resource_name
));
5427 if (!NILP (must_succeed
))
5428 fatal ("Cannot connect to server %s.\n",
5431 error ("Cannot connect to server %s", SDATA (display
));
5434 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
5438 DEFUN ("x-close-connection", Fx_close_connection
,
5439 Sx_close_connection
, 1, 1, 0,
5440 doc
: /* Close the connection to DISPLAY's server.
5441 For DISPLAY, specify either a frame or a display name (a string).
5442 If DISPLAY is nil, that stands for the selected frame's display. */)
5443 (Lisp_Object display
)
5445 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5447 if (dpyinfo
->reference_count
> 0)
5448 error ("Display still has frames on it");
5451 x_destroy_all_bitmaps (dpyinfo
);
5453 x_delete_display (dpyinfo
);
5459 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5460 doc
: /* Return the list of display names that Emacs has connections to. */)
5463 Lisp_Object result
= Qnil
;
5464 struct w32_display_info
*wdi
;
5466 for (wdi
= x_display_list
; wdi
; wdi
= wdi
->next
)
5467 result
= Fcons (XCAR (wdi
->name_list_element
), result
);
5472 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5473 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5474 This function only has an effect on X Windows. With MS Windows, it is
5475 defined but does nothing.
5477 If ON is nil, allow buffering of requests.
5478 Turning on synchronization prohibits the Xlib routines from buffering
5479 requests and seriously degrades performance, but makes debugging much
5481 The optional second argument TERMINAL specifies which display to act on.
5482 TERMINAL should be a terminal object, a frame or a display name (a string).
5483 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5484 (Lisp_Object on
, Lisp_Object display
)
5491 /***********************************************************************
5493 ***********************************************************************/
5495 #if 0 /* TODO : port window properties to W32 */
5497 DEFUN ("x-change-window-property", Fx_change_window_property
,
5498 Sx_change_window_property
, 2, 6, 0,
5499 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
5500 PROP must be a string. VALUE may be a string or a list of conses,
5501 numbers and/or strings. If an element in the list is a string, it is
5502 converted to an atom and the value of the Atom is used. If an element
5503 is a cons, it is converted to a 32 bit number where the car is the 16
5504 top bits and the cdr is the lower 16 bits.
5506 FRAME nil or omitted means use the selected frame.
5507 If TYPE is given and non-nil, it is the name of the type of VALUE.
5508 If TYPE is not given or nil, the type is STRING.
5509 FORMAT gives the size in bits of each element if VALUE is a list.
5510 It must be one of 8, 16 or 32.
5511 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5512 If OUTER-P is non-nil, the property is changed for the outer X window of
5513 FRAME. Default is to change on the edit X window. */)
5514 (Lisp_Object prop
, Lisp_Object value
, Lisp_Object frame
,
5515 Lisp_Object type
, Lisp_Object format
, Lisp_Object outer_p
)
5517 struct frame
*f
= decode_window_system_frame (frame
);
5520 CHECK_STRING (prop
);
5521 CHECK_STRING (value
);
5524 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5525 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5526 prop_atom
, XA_STRING
, 8, PropModeReplace
,
5527 SDATA (value
), SCHARS (value
));
5529 /* Make sure the property is set when we return. */
5530 XFlush (FRAME_W32_DISPLAY (f
));
5537 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
5538 Sx_delete_window_property
, 1, 2, 0,
5539 doc
: /* Remove window property PROP from X window of FRAME.
5540 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5541 (Lisp_Object prop
, Lisp_Object frame
)
5543 struct frame
*f
= decode_window_system_frame (frame
);
5546 CHECK_STRING (prop
);
5548 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5549 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
5551 /* Make sure the property is removed when we return. */
5552 XFlush (FRAME_W32_DISPLAY (f
));
5559 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
5561 doc
: /* Value is the value of window property PROP on FRAME.
5562 If FRAME is nil or omitted, use the selected frame.
5564 On X Windows, the following optional arguments are also accepted:
5565 If TYPE is nil or omitted, get the property as a string.
5566 Otherwise TYPE is the name of the atom that denotes the type expected.
5567 If SOURCE is non-nil, get the property on that window instead of from
5568 FRAME. The number 0 denotes the root window.
5569 If DELETE-P is non-nil, delete the property after retrieving it.
5570 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5572 On MS Windows, this function accepts but ignores those optional arguments.
5574 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5575 no value of TYPE (always string in the MS Windows case). */)
5576 (Lisp_Object prop
, Lisp_Object frame
, Lisp_Object type
,
5577 Lisp_Object source
, Lisp_Object delete_p
, Lisp_Object vector_ret_p
)
5579 struct frame
*f
= decode_window_system_frame (frame
);
5582 Lisp_Object prop_value
= Qnil
;
5583 char *tmp_data
= NULL
;
5586 unsigned long actual_size
, bytes_remaining
;
5588 CHECK_STRING (prop
);
5590 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5591 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5592 prop_atom
, 0, 0, False
, XA_STRING
,
5593 &actual_type
, &actual_format
, &actual_size
,
5594 &bytes_remaining
, (unsigned char **) &tmp_data
);
5597 int size
= bytes_remaining
;
5602 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5603 prop_atom
, 0, bytes_remaining
,
5605 &actual_type
, &actual_format
,
5606 &actual_size
, &bytes_remaining
,
5607 (unsigned char **) &tmp_data
);
5609 prop_value
= make_string (tmp_data
, size
);
5623 /***********************************************************************
5625 ***********************************************************************/
5627 static Lisp_Object
x_create_tip_frame (struct w32_display_info
*,
5628 Lisp_Object
, Lisp_Object
);
5629 static void compute_tip_xy (struct frame
*, Lisp_Object
, Lisp_Object
,
5630 Lisp_Object
, int, int, int *, int *);
5632 /* The frame of a currently visible tooltip. */
5634 Lisp_Object tip_frame
;
5636 /* If non-nil, a timer started that hides the last tooltip when it
5639 Lisp_Object tip_timer
;
5642 /* If non-nil, a vector of 3 elements containing the last args
5643 with which x-show-tip was called. See there. */
5645 Lisp_Object last_show_tip_args
;
5649 unwind_create_tip_frame (Lisp_Object frame
)
5651 Lisp_Object deleted
;
5653 deleted
= unwind_create_frame (frame
);
5654 if (EQ (deleted
, Qt
))
5662 /* Create a frame for a tooltip on the display described by DPYINFO.
5663 PARMS is a list of frame parameters. TEXT is the string to
5664 display in the tip frame. Value is the frame.
5666 Note that functions called here, esp. x_default_parameter can
5667 signal errors, for instance when a specified color name is
5668 undefined. We have to make sure that we're in a consistent state
5669 when this happens. */
5672 x_create_tip_frame (struct w32_display_info
*dpyinfo
,
5673 Lisp_Object parms
, Lisp_Object text
)
5678 long window_prompting
= 0;
5680 ptrdiff_t count
= SPECPDL_INDEX ();
5681 struct gcpro gcpro1
, gcpro2
, gcpro3
;
5683 bool face_change_before
= face_change
;
5685 struct buffer
*old_buffer
;
5687 /* Use this general default value to start with until we know if
5688 this frame has a specified name. */
5689 Vx_resource_name
= Vinvocation_name
;
5691 kb
= dpyinfo
->terminal
->kboard
;
5693 /* The calls to x_get_arg remove elements from PARMS, so copy it to
5694 avoid destructive changes behind our caller's back. */
5695 parms
= Fcopy_alist (parms
);
5697 /* Get the name of the frame to use for resource lookup. */
5698 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
5700 && !EQ (name
, Qunbound
)
5702 error ("Invalid frame name--not a string or nil");
5703 Vx_resource_name
= name
;
5706 GCPRO3 (parms
, name
, frame
);
5707 /* Make a frame without minibuffer nor mode-line. */
5708 f
= make_frame (false);
5709 f
->wants_modeline
= 0;
5710 XSETFRAME (frame
, f
);
5712 AUTO_STRING (tip
, " *tip*");
5713 buffer
= Fget_buffer_create (tip
);
5714 /* Use set_window_buffer instead of Fset_window_buffer (see
5715 discussion of bug#11984, bug#12025, bug#12026). */
5716 set_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
, false, false);
5717 old_buffer
= current_buffer
;
5718 set_buffer_internal_1 (XBUFFER (buffer
));
5719 bset_truncate_lines (current_buffer
, Qnil
);
5720 specbind (Qinhibit_read_only
, Qt
);
5721 specbind (Qinhibit_modification_hooks
, Qt
);
5724 set_buffer_internal_1 (old_buffer
);
5726 record_unwind_protect (unwind_create_tip_frame
, frame
);
5728 /* By setting the output method, we're essentially saying that
5729 the frame is live, as per FRAME_LIVE_P. If we get a signal
5730 from this point on, x_destroy_window might screw up reference
5732 f
->terminal
= dpyinfo
->terminal
;
5733 f
->output_method
= output_w32
;
5734 f
->output_data
.w32
= xzalloc (sizeof (struct w32_output
));
5736 FRAME_FONTSET (f
) = -1;
5737 fset_icon_name (f
, Qnil
);
5740 image_cache_refcount
=
5741 FRAME_IMAGE_CACHE (f
) ? FRAME_IMAGE_CACHE (f
)->refcount
: 0;
5742 dpyinfo_refcount
= dpyinfo
->reference_count
;
5743 #endif /* GLYPH_DEBUG */
5744 FRAME_KBOARD (f
) = kb
;
5745 f
->output_data
.w32
->parent_desc
= FRAME_DISPLAY_INFO (f
)->root_window
;
5746 f
->output_data
.w32
->explicit_parent
= false;
5748 /* Set the name; the functions to which we pass f expect the name to
5750 if (EQ (name
, Qunbound
) || NILP (name
))
5752 fset_name (f
, build_string (dpyinfo
->w32_id_name
));
5753 f
->explicit_name
= false;
5757 fset_name (f
, name
);
5758 f
->explicit_name
= true;
5759 /* use the frame's title when getting resources for this frame. */
5760 specbind (Qx_resource_name
, name
);
5763 if (uniscribe_available
)
5764 register_font_driver (&uniscribe_font_driver
, f
);
5765 register_font_driver (&w32font_driver
, f
);
5767 x_default_parameter (f
, parms
, Qfont_backend
, Qnil
,
5768 "fontBackend", "FontBackend", RES_TYPE_STRING
);
5770 /* Extract the window parameters from the supplied values
5771 that are needed to determine window geometry. */
5772 x_default_font_parameter (f
, parms
);
5774 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
5775 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
5776 /* This defaults to 2 in order to match xterm. We recognize either
5777 internalBorderWidth or internalBorder (which is what xterm calls
5779 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5783 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
5784 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
5785 if (! EQ (value
, Qunbound
))
5786 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
5789 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
5790 "internalBorderWidth", "internalBorderWidth",
5792 x_default_parameter (f
, parms
, Qright_divider_width
, make_number (0),
5793 NULL
, NULL
, RES_TYPE_NUMBER
);
5794 x_default_parameter (f
, parms
, Qbottom_divider_width
, make_number (0),
5795 NULL
, NULL
, RES_TYPE_NUMBER
);
5797 /* Also do the stuff which must be set before the window exists. */
5798 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
5799 "foreground", "Foreground", RES_TYPE_STRING
);
5800 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
5801 "background", "Background", RES_TYPE_STRING
);
5802 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
5803 "pointerColor", "Foreground", RES_TYPE_STRING
);
5804 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
5805 "cursorColor", "Foreground", RES_TYPE_STRING
);
5806 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
5807 "borderColor", "BorderColor", RES_TYPE_STRING
);
5808 x_default_parameter (f
, parms
, Qalpha
, Qnil
,
5809 "alpha", "Alpha", RES_TYPE_NUMBER
);
5811 /* Init faces before x_default_parameter is called for the
5812 scroll-bar-width parameter because otherwise we end up in
5813 init_iterator with a null face cache, which should not happen. */
5814 init_frame_faces (f
);
5816 f
->output_data
.w32
->dwStyle
= WS_BORDER
| WS_POPUP
| WS_DISABLED
;
5817 f
->output_data
.w32
->parent_desc
= FRAME_DISPLAY_INFO (f
)->root_window
;
5819 window_prompting
= x_figure_window_size (f
, parms
, false);
5821 /* No fringes on tip frame. */
5823 f
->left_fringe_width
= 0;
5824 f
->right_fringe_width
= 0;
5827 my_create_tip_window (f
);
5832 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
5833 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5834 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
5835 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5836 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
5837 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
5839 /* Dimensions, especially FRAME_LINES (f), must be done via
5840 change_frame_size. Change will not be effected unless different
5841 from the current FRAME_LINES (f). */
5842 width
= FRAME_COLS (f
);
5843 height
= FRAME_LINES (f
);
5844 SET_FRAME_COLS (f
, 0);
5845 SET_FRAME_LINES (f
, 0);
5846 adjust_frame_size (f
, width
* FRAME_COLUMN_WIDTH (f
),
5847 height
* FRAME_LINE_HEIGHT (f
), 0, true, Qtip_frame
);
5849 /* Add `tooltip' frame parameter's default value. */
5850 if (NILP (Fframe_parameter (frame
, Qtooltip
)))
5851 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qtooltip
, Qt
), Qnil
));
5853 /* Set up faces after all frame parameters are known. This call
5854 also merges in face attributes specified for new frames.
5856 Frame parameters may be changed if .Xdefaults contains
5857 specifications for the default font. For example, if there is an
5858 `Emacs.default.attributeBackground: pink', the `background-color'
5859 attribute of the frame get's set, which let's the internal border
5860 of the tooltip frame appear in pink. Prevent this. */
5862 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
5863 Lisp_Object fg
= Fframe_parameter (frame
, Qforeground_color
);
5864 Lisp_Object colors
= Qnil
;
5866 /* Set tip_frame here, so that */
5868 call2 (Qface_set_after_frame_default
, frame
, Qnil
);
5870 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
5871 colors
= Fcons (Fcons (Qbackground_color
, bg
), colors
);
5872 if (!EQ (fg
, Fframe_parameter (frame
, Qforeground_color
)))
5873 colors
= Fcons (Fcons (Qforeground_color
, fg
), colors
);
5876 Fmodify_frame_parameters (frame
, colors
);
5883 /* Now that the frame is official, it counts as a reference to
5885 FRAME_DISPLAY_INFO (f
)->reference_count
++;
5886 f
->terminal
->reference_count
++;
5888 /* It is now ok to make the frame official even if we get an error
5889 below. And the frame needs to be on Vframe_list or making it
5890 visible won't work. */
5891 Vframe_list
= Fcons (frame
, Vframe_list
);
5892 f
->can_x_set_window_size
= true;
5894 /* Setting attributes of faces of the tooltip frame from resources
5895 and similar will set face_change, which leads to the
5896 clearing of all current matrices. Since this isn't necessary
5897 here, avoid it by resetting face_change to the value it
5898 had before we created the tip frame. */
5899 face_change
= face_change_before
;
5901 /* Discard the unwind_protect. */
5902 return unbind_to (count
, frame
);
5906 /* Compute where to display tip frame F. PARMS is the list of frame
5907 parameters for F. DX and DY are specified offsets from the current
5908 location of the mouse. WIDTH and HEIGHT are the width and height
5909 of the tooltip. Return coordinates relative to the root window of
5910 the display in *ROOT_X, and *ROOT_Y. */
5913 compute_tip_xy (struct frame
*f
,
5914 Lisp_Object parms
, Lisp_Object dx
, Lisp_Object dy
,
5915 int width
, int height
, int *root_x
, int *root_y
)
5917 Lisp_Object left
, top
;
5918 int min_x
, min_y
, max_x
, max_y
;
5920 /* User-specified position? */
5921 left
= Fcdr (Fassq (Qleft
, parms
));
5922 top
= Fcdr (Fassq (Qtop
, parms
));
5924 /* Move the tooltip window where the mouse pointer is. Resize and
5926 if (!INTEGERP (left
) || !INTEGERP (top
))
5930 /* Default min and max values. */
5933 max_x
= x_display_pixel_width (FRAME_DISPLAY_INFO (f
));
5934 max_y
= x_display_pixel_height (FRAME_DISPLAY_INFO (f
));
5942 /* If multiple monitor support is available, constrain the tip onto
5943 the current monitor. This improves the above by allowing negative
5944 co-ordinates if monitor positions are such that they are valid, and
5945 snaps a tooltip onto a single monitor if we are close to the edge
5946 where it would otherwise flow onto the other monitor (or into
5947 nothingness if there is a gap in the overlap). */
5948 if (monitor_from_point_fn
&& get_monitor_info_fn
)
5950 struct MONITOR_INFO info
;
5952 = monitor_from_point_fn (pt
, MONITOR_DEFAULT_TO_NEAREST
);
5953 info
.cbSize
= sizeof (info
);
5955 if (get_monitor_info_fn (monitor
, &info
))
5957 min_x
= info
.rcWork
.left
;
5958 min_y
= info
.rcWork
.top
;
5959 max_x
= info
.rcWork
.right
;
5960 max_y
= info
.rcWork
.bottom
;
5966 *root_y
= XINT (top
);
5967 else if (*root_y
+ XINT (dy
) <= min_y
)
5968 *root_y
= min_y
; /* Can happen for negative dy */
5969 else if (*root_y
+ XINT (dy
) + height
<= max_y
)
5970 /* It fits below the pointer */
5971 *root_y
+= XINT (dy
);
5972 else if (height
+ XINT (dy
) + min_y
<= *root_y
)
5973 /* It fits above the pointer. */
5974 *root_y
-= height
+ XINT (dy
);
5976 /* Put it on the top. */
5979 if (INTEGERP (left
))
5980 *root_x
= XINT (left
);
5981 else if (*root_x
+ XINT (dx
) <= min_x
)
5982 *root_x
= 0; /* Can happen for negative dx */
5983 else if (*root_x
+ XINT (dx
) + width
<= max_x
)
5984 /* It fits to the right of the pointer. */
5985 *root_x
+= XINT (dx
);
5986 else if (width
+ XINT (dx
) + min_x
<= *root_x
)
5987 /* It fits to the left of the pointer. */
5988 *root_x
-= width
+ XINT (dx
);
5990 /* Put it left justified on the screen -- it ought to fit that way. */
5995 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
5996 doc
: /* Show STRING in a \"tooltip\" window on frame FRAME.
5997 A tooltip window is a small window displaying a string.
5999 This is an internal function; Lisp code should call `tooltip-show'.
6001 FRAME nil or omitted means use the selected frame.
6003 PARMS is an optional list of frame parameters which can be
6004 used to change the tooltip's appearance.
6006 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
6007 means use the default timeout of 5 seconds.
6009 If the list of frame parameters PARMS contains a `left' parameter,
6010 the tooltip is displayed at that x-position. Otherwise it is
6011 displayed at the mouse position, with offset DX added (default is 5 if
6012 DX isn't specified). Likewise for the y-position; if a `top' frame
6013 parameter is specified, it determines the y-position of the tooltip
6014 window, otherwise it is displayed at the mouse position, with offset
6015 DY added (default is -10).
6017 A tooltip's maximum size is specified by `x-max-tooltip-size'.
6018 Text larger than the specified size is clipped. */)
6019 (Lisp_Object string
, Lisp_Object frame
, Lisp_Object parms
, Lisp_Object timeout
, Lisp_Object dx
, Lisp_Object dy
)
6024 struct buffer
*old_buffer
;
6025 struct text_pos pos
;
6026 int i
, width
, height
;
6027 bool seen_reversed_p
;
6028 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
6029 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
6030 ptrdiff_t count
= SPECPDL_INDEX ();
6032 specbind (Qinhibit_redisplay
, Qt
);
6034 GCPRO4 (string
, parms
, frame
, timeout
);
6036 CHECK_STRING (string
);
6037 f
= decode_window_system_frame (frame
);
6039 timeout
= make_number (5);
6041 CHECK_NATNUM (timeout
);
6044 dx
= make_number (5);
6049 dy
= make_number (-10);
6053 if (NILP (last_show_tip_args
))
6054 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
6056 if (!NILP (tip_frame
))
6058 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
6059 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
6060 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
6062 if (EQ (frame
, last_frame
)
6063 && !NILP (Fequal (last_string
, string
))
6064 && !NILP (Fequal (last_parms
, parms
)))
6066 struct frame
*f
= XFRAME (tip_frame
);
6068 /* Only DX and DY have changed. */
6069 if (!NILP (tip_timer
))
6071 Lisp_Object timer
= tip_timer
;
6073 call1 (Qcancel_timer
, timer
);
6077 compute_tip_xy (f
, parms
, dx
, dy
, FRAME_PIXEL_WIDTH (f
),
6078 FRAME_PIXEL_HEIGHT (f
), &root_x
, &root_y
);
6080 /* Put tooltip in topmost group and in position. */
6081 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
6082 root_x
, root_y
, 0, 0,
6083 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOOWNERZORDER
);
6085 /* Ensure tooltip is on top of other topmost windows (eg menus). */
6086 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
6088 SWP_NOMOVE
| SWP_NOSIZE
6089 | SWP_NOACTIVATE
| SWP_NOOWNERZORDER
);
6096 /* Hide a previous tip, if any. */
6099 ASET (last_show_tip_args
, 0, string
);
6100 ASET (last_show_tip_args
, 1, frame
);
6101 ASET (last_show_tip_args
, 2, parms
);
6103 /* Add default values to frame parameters. */
6104 if (NILP (Fassq (Qname
, parms
)))
6105 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
6106 if (NILP (Fassq (Qinternal_border_width
, parms
)))
6107 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
6108 if (NILP (Fassq (Qright_divider_width
, parms
)))
6109 parms
= Fcons (Fcons (Qright_divider_width
, make_number (0)), parms
);
6110 if (NILP (Fassq (Qbottom_divider_width
, parms
)))
6111 parms
= Fcons (Fcons (Qbottom_divider_width
, make_number (0)), parms
);
6112 if (NILP (Fassq (Qborder_width
, parms
)))
6113 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
6114 if (NILP (Fassq (Qborder_color
, parms
)))
6115 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
6116 if (NILP (Fassq (Qbackground_color
, parms
)))
6117 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
6120 /* Block input until the tip has been fully drawn, to avoid crashes
6121 when drawing tips in menus. */
6124 /* Create a frame for the tooltip, and record it in the global
6125 variable tip_frame. */
6126 frame
= x_create_tip_frame (FRAME_DISPLAY_INFO (f
), parms
, string
);
6129 /* Set up the frame's root window. */
6130 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6136 if (CONSP (Vx_max_tooltip_size
)
6137 && INTEGERP (XCAR (Vx_max_tooltip_size
))
6138 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
6139 && INTEGERP (XCDR (Vx_max_tooltip_size
))
6140 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
6142 w
->total_cols
= XFASTINT (XCAR (Vx_max_tooltip_size
));
6143 w
->total_lines
= XFASTINT (XCDR (Vx_max_tooltip_size
));
6148 w
->total_lines
= 40;
6151 w
->pixel_width
= w
->total_cols
* FRAME_COLUMN_WIDTH (f
);
6152 w
->pixel_height
= w
->total_lines
* FRAME_LINE_HEIGHT (f
);
6154 FRAME_TOTAL_COLS (f
) = WINDOW_TOTAL_COLS (w
);
6155 adjust_frame_glyphs (f
);
6156 w
->pseudo_window_p
= true;
6158 /* Display the tooltip text in a temporary buffer. */
6159 old_buffer
= current_buffer
;
6160 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->contents
));
6161 bset_truncate_lines (current_buffer
, Qnil
);
6162 clear_glyph_matrix (w
->desired_matrix
);
6163 clear_glyph_matrix (w
->current_matrix
);
6164 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
6165 try_window (FRAME_ROOT_WINDOW (f
), pos
, TRY_WINDOW_IGNORE_FONTS_CHANGE
);
6167 /* Compute width and height of the tooltip. */
6169 seen_reversed_p
= false;
6170 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
6172 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
6176 /* Stop at the first empty row at the end. */
6177 if (!row
->enabled_p
|| !MATRIX_ROW_DISPLAYS_TEXT_P (row
))
6180 /* Let the row go over the full width of the frame. */
6181 row
->full_width_p
= true;
6183 row_width
= row
->pixel_width
;
6184 if (row
->used
[TEXT_AREA
])
6186 if (!row
->reversed_p
)
6188 /* There's a glyph at the end of rows that is used to
6189 place the cursor there. Don't include the width of
6191 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
6192 if (NILP (last
->object
))
6193 row_width
-= last
->pixel_width
;
6197 /* There could be a stretch glyph at the beginning of R2L
6198 rows that is produced by extend_face_to_end_of_line.
6199 Don't count that glyph. */
6200 struct glyph
*g
= row
->glyphs
[TEXT_AREA
];
6202 if (g
->type
== STRETCH_GLYPH
&& NILP (g
->object
))
6204 row_width
-= g
->pixel_width
;
6205 seen_reversed_p
= true;
6210 height
+= row
->height
;
6211 width
= max (width
, row_width
);
6214 /* If we've seen partial-length R2L rows, we need to re-adjust the
6215 tool-tip frame width and redisplay it again, to avoid over-wide
6216 tips due to the stretch glyph that extends R2L lines to full
6217 width of the frame. */
6218 if (seen_reversed_p
)
6220 /* PXW: Why do we do the pixel-to-cols conversion only if
6221 seen_reversed_p holds? Don't we have to set other fields of
6222 the window/frame structure?
6224 w->total_cols and FRAME_TOTAL_COLS want the width in columns,
6226 w
->pixel_width
= width
;
6227 width
/= WINDOW_FRAME_COLUMN_WIDTH (w
);
6228 w
->total_cols
= width
;
6229 FRAME_TOTAL_COLS (f
) = width
;
6230 SET_FRAME_WIDTH (f
, width
);
6231 adjust_frame_glyphs (f
);
6232 w
->pseudo_window_p
= 1;
6233 clear_glyph_matrix (w
->desired_matrix
);
6234 clear_glyph_matrix (w
->current_matrix
);
6235 try_window (FRAME_ROOT_WINDOW (f
), pos
, TRY_WINDOW_IGNORE_FONTS_CHANGE
);
6237 /* Recompute width and height of the tooltip. */
6238 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
6240 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
6244 if (!row
->enabled_p
|| !MATRIX_ROW_DISPLAYS_TEXT_P (row
))
6246 row
->full_width_p
= true;
6247 row_width
= row
->pixel_width
;
6248 if (row
->used
[TEXT_AREA
] && !row
->reversed_p
)
6250 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
6251 if (NILP (last
->object
))
6252 row_width
-= last
->pixel_width
;
6255 height
+= row
->height
;
6256 width
= max (width
, row_width
);
6260 /* Add the frame's internal border to the width and height the w32
6261 window should have. */
6262 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
6263 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
6265 /* Move the tooltip window where the mouse pointer is. Resize and
6268 PXW: This should use the frame's pixel coordinates. */
6269 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
6272 /* Adjust Window size to take border into account. */
6274 rect
.left
= rect
.top
= 0;
6276 rect
.bottom
= height
;
6277 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
6278 FRAME_EXTERNAL_MENU_BAR (f
));
6280 /* Position and size tooltip, and put it in the topmost group.
6281 The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a
6282 peculiarity of w32 display: without it, some fonts cause the
6283 last character of the tip to be truncated or wrapped around to
6285 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
6287 rect
.right
- rect
.left
+ FRAME_COLUMN_WIDTH (f
),
6288 rect
.bottom
- rect
.top
, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
);
6290 /* Ensure tooltip is on top of other topmost windows (eg menus). */
6291 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
6293 SWP_NOMOVE
| SWP_NOSIZE
6294 | SWP_NOACTIVATE
| SWP_NOOWNERZORDER
);
6296 /* Let redisplay know that we have made the frame visible already. */
6297 SET_FRAME_VISIBLE (f
, 1);
6299 ShowWindow (FRAME_W32_WINDOW (f
), SW_SHOWNOACTIVATE
);
6302 /* Draw into the window. */
6303 w
->must_be_updated_p
= true;
6304 update_single_window (w
);
6308 /* Restore original current buffer. */
6309 set_buffer_internal_1 (old_buffer
);
6310 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
6313 /* Let the tip disappear after timeout seconds. */
6314 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
6315 intern ("x-hide-tip"));
6318 return unbind_to (count
, Qnil
);
6322 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
6323 doc
: /* Hide the current tooltip window, if there is any.
6324 Value is t if tooltip was open, nil otherwise. */)
6328 Lisp_Object deleted
, frame
, timer
;
6329 struct gcpro gcpro1
, gcpro2
;
6331 /* Return quickly if nothing to do. */
6332 if (NILP (tip_timer
) && NILP (tip_frame
))
6337 GCPRO2 (frame
, timer
);
6338 tip_frame
= tip_timer
= deleted
= Qnil
;
6340 count
= SPECPDL_INDEX ();
6341 specbind (Qinhibit_redisplay
, Qt
);
6342 specbind (Qinhibit_quit
, Qt
);
6345 call1 (Qcancel_timer
, timer
);
6349 delete_frame (frame
, Qnil
);
6354 return unbind_to (count
, deleted
);
6357 /***********************************************************************
6358 File selection dialog
6359 ***********************************************************************/
6361 #define FILE_NAME_TEXT_FIELD edt1
6362 #define FILE_NAME_COMBO_BOX cmb13
6363 #define FILE_NAME_LIST lst1
6365 /* Callback for altering the behavior of the Open File dialog.
6366 Makes the Filename text field contain "Current Directory" and be
6367 read-only when "Directories" is selected in the filter. This
6368 allows us to work around the fact that the standard Open File
6369 dialog does not support directories. */
6370 static UINT_PTR CALLBACK
6371 file_dialog_callback (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
6373 if (msg
== WM_NOTIFY
)
6375 OFNOTIFYW
* notify_w
= (OFNOTIFYW
*)lParam
;
6376 OFNOTIFYA
* notify_a
= (OFNOTIFYA
*)lParam
;
6377 int dropdown_changed
;
6379 #ifdef NTGUI_UNICODE
6380 const int use_unicode
= 1;
6381 #else /* !NTGUI_UNICODE */
6382 int use_unicode
= w32_unicode_filenames
;
6383 #endif /* NTGUI_UNICODE */
6385 /* Detect when the Filter dropdown is changed. */
6388 notify_w
->hdr
.code
== CDN_TYPECHANGE
6389 || notify_w
->hdr
.code
== CDN_INITDONE
;
6392 notify_a
->hdr
.code
== CDN_TYPECHANGE
6393 || notify_a
->hdr
.code
== CDN_INITDONE
;
6394 if (dropdown_changed
)
6396 HWND dialog
= GetParent (hwnd
);
6397 HWND edit_control
= GetDlgItem (dialog
, FILE_NAME_TEXT_FIELD
);
6398 HWND list
= GetDlgItem (dialog
, FILE_NAME_LIST
);
6401 /* At least on Windows 7, the above attempt to get the window handle
6402 to the File Name Text Field fails. The following code does the
6403 job though. Note that this code is based on my examination of the
6404 window hierarchy using Microsoft Spy++. bk */
6405 if (edit_control
== NULL
)
6407 HWND tmp
= GetDlgItem (dialog
, FILE_NAME_COMBO_BOX
);
6410 tmp
= GetWindow (tmp
, GW_CHILD
);
6412 edit_control
= GetWindow (tmp
, GW_CHILD
);
6416 /* Directories is in index 2. */
6419 dir_index
= notify_w
->lpOFN
->nFilterIndex
;
6420 hdr_code
= notify_w
->hdr
.code
;
6424 dir_index
= notify_a
->lpOFN
->nFilterIndex
;
6425 hdr_code
= notify_a
->hdr
.code
;
6430 SendMessageW (dialog
, CDM_SETCONTROLTEXT
, FILE_NAME_TEXT_FIELD
,
6431 (LPARAM
)L
"Current Directory");
6433 SendMessageA (dialog
, CDM_SETCONTROLTEXT
, FILE_NAME_TEXT_FIELD
,
6434 (LPARAM
)"Current Directory");
6435 EnableWindow (edit_control
, FALSE
);
6436 /* Note that at least on Windows 7, the above call to EnableWindow
6437 disables the window that would ordinarily have focus. If we
6438 do not set focus to some other window here, focus will land in
6439 no man's land and the user will be unable to tab through the
6440 dialog box (pressing tab will only result in a beep).
6441 Avoid that problem by setting focus to the list here. */
6442 if (hdr_code
== CDN_INITDONE
)
6447 /* Don't override default filename on init done. */
6448 if (hdr_code
== CDN_TYPECHANGE
)
6451 SendMessageW (dialog
, CDM_SETCONTROLTEXT
,
6452 FILE_NAME_TEXT_FIELD
, (LPARAM
)L
"");
6454 SendMessageA (dialog
, CDM_SETCONTROLTEXT
,
6455 FILE_NAME_TEXT_FIELD
, (LPARAM
)"");
6457 EnableWindow (edit_control
, TRUE
);
6464 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 5, 0,
6465 doc
: /* Read file name, prompting with PROMPT in directory DIR.
6466 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6467 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6468 or directory must exist.
6470 This function is only defined on NS, MS Windows, and X Windows with the
6471 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6472 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories.
6473 On Windows 7 and later, the file selection dialog "remembers" the last
6474 directory where the user selected a file, and will open that directory
6475 instead of DIR on subsequent invocations of this function with the same
6476 value of DIR as in previous invocations; this is standard Windows behavior. */)
6477 (Lisp_Object prompt
, Lisp_Object dir
, Lisp_Object default_filename
, Lisp_Object mustmatch
, Lisp_Object only_dir_p
)
6479 /* Filter index: 1: All Files, 2: Directories only */
6480 static const wchar_t filter_w
[] = L
"All Files (*.*)\0*.*\0Directories\0*|*\0";
6481 static const char filter_a
[] = "All Files (*.*)\0*.*\0Directories\0*|*\0";
6483 Lisp_Object filename
= default_filename
;
6484 struct frame
*f
= SELECTED_FRAME ();
6485 BOOL file_opened
= FALSE
;
6486 Lisp_Object orig_dir
= dir
;
6487 Lisp_Object orig_prompt
= prompt
;
6489 /* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
6490 compatibility) we end up with the old file dialogs. Define a big
6491 enough struct for the new dialog to trick GetOpenFileName into
6492 giving us the new dialogs on newer versions of Windows. */
6494 OPENFILENAMEW details
;
6495 #if _WIN32_WINNT < 0x500 /* < win2k */
6499 #endif /* < win2k */
6500 } new_file_details_w
;
6502 #ifdef NTGUI_UNICODE
6503 wchar_t filename_buf_w
[32*1024 + 1]; // NT kernel maximum
6504 OPENFILENAMEW
* file_details_w
= &new_file_details_w
.details
;
6505 const int use_unicode
= 1;
6506 #else /* not NTGUI_UNICODE */
6508 OPENFILENAMEA details
;
6509 #if _WIN32_WINNT < 0x500 /* < win2k */
6513 #endif /* < win2k */
6514 } new_file_details_a
;
6515 wchar_t filename_buf_w
[MAX_PATH
+ 1], dir_w
[MAX_PATH
];
6516 char filename_buf_a
[MAX_PATH
+ 1], dir_a
[MAX_PATH
];
6517 OPENFILENAMEW
* file_details_w
= &new_file_details_w
.details
;
6518 OPENFILENAMEA
* file_details_a
= &new_file_details_a
.details
;
6519 int use_unicode
= w32_unicode_filenames
;
6523 char fname_ret
[MAX_UTF8_PATH
];
6524 #endif /* NTGUI_UNICODE */
6526 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
6527 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
, filename
);
6530 struct gcpro gcpro1
, gcpro2
;
6531 GCPRO2 (orig_dir
, orig_prompt
); /* There is no GCPRON, N>6. */
6533 /* Note: under NTGUI_UNICODE, we do _NOT_ use ENCODE_FILE: the
6534 system file encoding expected by the platform APIs (e.g. Cygwin's
6535 POSIX implementation) may not be the same as the encoding expected
6536 by the Windows "ANSI" APIs! */
6538 CHECK_STRING (prompt
);
6541 dir
= Fexpand_file_name (dir
, Qnil
);
6543 if (STRINGP (filename
))
6544 filename
= Ffile_name_nondirectory (filename
);
6546 filename
= empty_unibyte_string
;
6549 dir
= Fcygwin_convert_file_name_to_windows (dir
, Qt
);
6550 if (SCHARS (filename
) > 0)
6551 filename
= Fcygwin_convert_file_name_to_windows (filename
, Qnil
);
6555 CHECK_STRING (filename
);
6557 /* The code in file_dialog_callback that attempts to set the text
6558 of the file name edit window when handling the CDN_INITDONE
6559 WM_NOTIFY message does not work. Setting filename to "Current
6560 Directory" in the only_dir_p case here does work however. */
6561 if (SCHARS (filename
) == 0 && ! NILP (only_dir_p
))
6562 filename
= build_string ("Current Directory");
6564 /* Convert the values we've computed so far to system form. */
6565 #ifdef NTGUI_UNICODE
6566 to_unicode (prompt
, &prompt
);
6567 to_unicode (dir
, &dir
);
6568 to_unicode (filename
, &filename
);
6569 if (SBYTES (filename
) + 1 > sizeof (filename_buf_w
))
6570 report_file_error ("filename too long", default_filename
);
6572 memcpy (filename_buf_w
, SDATA (filename
), SBYTES (filename
) + 1);
6573 #else /* !NTGUI_UNICODE */
6574 prompt
= ENCODE_FILE (prompt
);
6575 dir
= ENCODE_FILE (dir
);
6576 filename
= ENCODE_FILE (filename
);
6578 /* We modify these in-place, so make copies for safety. */
6579 dir
= Fcopy_sequence (dir
);
6580 unixtodos_filename (SDATA (dir
));
6581 filename
= Fcopy_sequence (filename
);
6582 unixtodos_filename (SDATA (filename
));
6583 if (SBYTES (filename
) >= MAX_UTF8_PATH
)
6584 report_file_error ("filename too long", default_filename
);
6585 if (w32_unicode_filenames
)
6587 filename_to_utf16 (SSDATA (dir
), dir_w
);
6588 if (filename_to_utf16 (SSDATA (filename
), filename_buf_w
) != 0)
6590 /* filename_to_utf16 sets errno to ENOENT when the file
6591 name is too long or cannot be converted to UTF-16. */
6592 if (errno
== ENOENT
&& filename_buf_w
[MAX_PATH
- 1] != 0)
6593 report_file_error ("filename too long", default_filename
);
6595 len
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
,
6596 SSDATA (prompt
), -1, NULL
, 0);
6599 prompt_w
= alloca (len
* sizeof (wchar_t));
6600 pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
,
6601 SSDATA (prompt
), -1, prompt_w
, len
);
6605 filename_to_ansi (SSDATA (dir
), dir_a
);
6606 if (filename_to_ansi (SSDATA (filename
), filename_buf_a
) != '\0')
6608 /* filename_to_ansi sets errno to ENOENT when the file
6609 name is too long or cannot be converted to UTF-16. */
6610 if (errno
== ENOENT
&& filename_buf_a
[MAX_PATH
- 1] != 0)
6611 report_file_error ("filename too long", default_filename
);
6613 len
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
,
6614 SSDATA (prompt
), -1, NULL
, 0);
6617 prompt_w
= alloca (len
* sizeof (wchar_t));
6618 pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
,
6619 SSDATA (prompt
), -1, prompt_w
, len
);
6620 len
= pWideCharToMultiByte (CP_ACP
, 0, prompt_w
, -1, NULL
, 0, NULL
, NULL
);
6623 prompt_a
= alloca (len
);
6624 pWideCharToMultiByte (CP_ACP
, 0, prompt_w
, -1, prompt_a
, len
, NULL
, NULL
);
6626 #endif /* NTGUI_UNICODE */
6628 /* Fill in the structure for the call to GetOpenFileName below.
6629 For NTGUI_UNICODE builds (which run only on NT), we just use
6630 the actual size of the structure. For non-NTGUI_UNICODE
6631 builds, we tell the OS we're using an old version of the
6632 structure if the OS isn't new enough to support the newer
6636 memset (&new_file_details_w
, 0, sizeof (new_file_details_w
));
6637 if (w32_major_version
> 4 && w32_major_version
< 95)
6638 file_details_w
->lStructSize
= sizeof (new_file_details_w
);
6640 file_details_w
->lStructSize
= sizeof (*file_details_w
);
6641 /* Set up the inout parameter for the selected file name. */
6642 file_details_w
->lpstrFile
= filename_buf_w
;
6643 file_details_w
->nMaxFile
=
6644 sizeof (filename_buf_w
) / sizeof (*filename_buf_w
);
6645 file_details_w
->hwndOwner
= FRAME_W32_WINDOW (f
);
6646 /* Undocumented Bug in Common File Dialog:
6647 If a filter is not specified, shell links are not resolved. */
6648 file_details_w
->lpstrFilter
= filter_w
;
6649 #ifdef NTGUI_UNICODE
6650 file_details_w
->lpstrInitialDir
= (wchar_t*) SDATA (dir
);
6651 file_details_w
->lpstrTitle
= (guichar_t
*) SDATA (prompt
);
6653 file_details_w
->lpstrInitialDir
= dir_w
;
6654 file_details_w
->lpstrTitle
= prompt_w
;
6656 file_details_w
->nFilterIndex
= NILP (only_dir_p
) ? 1 : 2;
6657 file_details_w
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
6658 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
6659 if (!NILP (mustmatch
))
6661 /* Require that the path to the parent directory exists. */
6662 file_details_w
->Flags
|= OFN_PATHMUSTEXIST
;
6663 /* If we are looking for a file, require that it exists. */
6664 if (NILP (only_dir_p
))
6665 file_details_w
->Flags
|= OFN_FILEMUSTEXIST
;
6668 #ifndef NTGUI_UNICODE
6671 memset (&new_file_details_a
, 0, sizeof (new_file_details_a
));
6672 if (w32_major_version
> 4 && w32_major_version
< 95)
6673 file_details_a
->lStructSize
= sizeof (new_file_details_a
);
6675 file_details_a
->lStructSize
= sizeof (*file_details_a
);
6676 file_details_a
->lpstrFile
= filename_buf_a
;
6677 file_details_a
->nMaxFile
=
6678 sizeof (filename_buf_a
) / sizeof (*filename_buf_a
);
6679 file_details_a
->hwndOwner
= FRAME_W32_WINDOW (f
);
6680 file_details_a
->lpstrFilter
= filter_a
;
6681 file_details_a
->lpstrInitialDir
= dir_a
;
6682 file_details_a
->lpstrTitle
= prompt_a
;
6683 file_details_a
->nFilterIndex
= NILP (only_dir_p
) ? 1 : 2;
6684 file_details_a
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
6685 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
6686 if (!NILP (mustmatch
))
6688 /* Require that the path to the parent directory exists. */
6689 file_details_a
->Flags
|= OFN_PATHMUSTEXIST
;
6690 /* If we are looking for a file, require that it exists. */
6691 if (NILP (only_dir_p
))
6692 file_details_a
->Flags
|= OFN_FILEMUSTEXIST
;
6695 #endif /* !NTGUI_UNICODE */
6698 int count
= SPECPDL_INDEX ();
6699 /* Prevent redisplay. */
6700 specbind (Qinhibit_redisplay
, Qt
);
6704 file_details_w
->lpfnHook
= file_dialog_callback
;
6706 file_opened
= GetOpenFileNameW (file_details_w
);
6708 #ifndef NTGUI_UNICODE
6711 file_details_a
->lpfnHook
= file_dialog_callback
;
6713 file_opened
= GetOpenFileNameA (file_details_a
);
6715 #endif /* !NTGUI_UNICODE */
6717 unbind_to (count
, Qnil
);
6722 /* Get an Emacs string from the value Windows gave us. */
6723 #ifdef NTGUI_UNICODE
6724 filename
= from_unicode_buffer (filename_buf_w
);
6725 #else /* !NTGUI_UNICODE */
6727 filename_from_utf16 (filename_buf_w
, fname_ret
);
6729 filename_from_ansi (filename_buf_a
, fname_ret
);
6730 dostounix_filename (fname_ret
);
6731 filename
= DECODE_FILE (build_unibyte_string (fname_ret
));
6732 #endif /* NTGUI_UNICODE */
6735 filename
= Fcygwin_convert_file_name_from_windows (filename
, Qt
);
6738 /* Strip the dummy filename off the end of the string if we
6739 added it to select a directory. */
6740 if ((use_unicode
&& file_details_w
->nFilterIndex
== 2)
6741 #ifndef NTGUI_UNICODE
6742 || (!use_unicode
&& file_details_a
->nFilterIndex
== 2)
6745 filename
= Ffile_name_directory (filename
);
6747 /* User canceled the dialog without making a selection. */
6748 else if (!CommDlgExtendedError ())
6750 /* An error occurred, fallback on reading from the mini-buffer. */
6752 filename
= Fcompleting_read (
6754 intern ("read-file-name-internal"),
6765 /* Make "Cancel" equivalent to C-g. */
6766 if (NILP (filename
))
6767 Fsignal (Qquit
, Qnil
);
6769 RETURN_UNGCPRO (filename
);
6774 /* Moving files to the system recycle bin.
6775 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
6776 DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash
,
6777 Ssystem_move_file_to_trash
, 1, 1, 0,
6778 doc
: /* Move file or directory named FILENAME to the recycle bin. */)
6779 (Lisp_Object filename
)
6781 Lisp_Object handler
;
6782 Lisp_Object encoded_file
;
6783 Lisp_Object operation
;
6785 operation
= Qdelete_file
;
6786 if (!NILP (Ffile_directory_p (filename
))
6787 && NILP (Ffile_symlink_p (filename
)))
6789 operation
= intern ("delete-directory");
6790 filename
= Fdirectory_file_name (filename
);
6793 /* Must have fully qualified file names for moving files to Recycle
6795 filename
= Fexpand_file_name (filename
, Qnil
);
6797 handler
= Ffind_file_name_handler (filename
, operation
);
6798 if (!NILP (handler
))
6799 return call2 (handler
, operation
, filename
);
6805 encoded_file
= ENCODE_FILE (filename
);
6807 path
= map_w32_filename (SDATA (encoded_file
), NULL
);
6809 /* The Unicode version of SHFileOperation is not supported on
6811 if (w32_unicode_filenames
&& os_subtype
!= OS_9X
)
6813 SHFILEOPSTRUCTW file_op_w
;
6814 /* We need one more element beyond MAX_PATH because this is
6815 a list of file names, with the last element double-null
6817 wchar_t tmp_path_w
[MAX_PATH
+ 1];
6819 memset (tmp_path_w
, 0, sizeof (tmp_path_w
));
6820 filename_to_utf16 (path
, tmp_path_w
);
6822 /* On Windows, write permission is required to delete/move files. */
6823 _wchmod (tmp_path_w
, 0666);
6825 memset (&file_op_w
, 0, sizeof (file_op_w
));
6826 file_op_w
.hwnd
= HWND_DESKTOP
;
6827 file_op_w
.wFunc
= FO_DELETE
;
6828 file_op_w
.pFrom
= tmp_path_w
;
6829 file_op_w
.fFlags
= FOF_SILENT
| FOF_NOCONFIRMATION
| FOF_ALLOWUNDO
6830 | FOF_NOERRORUI
| FOF_NO_CONNECTED_ELEMENTS
;
6831 file_op_w
.fAnyOperationsAborted
= FALSE
;
6833 result
= SHFileOperationW (&file_op_w
);
6837 SHFILEOPSTRUCTA file_op_a
;
6838 char tmp_path_a
[MAX_PATH
+ 1];
6840 memset (tmp_path_a
, 0, sizeof (tmp_path_a
));
6841 filename_to_ansi (path
, tmp_path_a
);
6843 /* If a file cannot be represented in ANSI codepage, don't
6844 let them inadvertently delete other files because some
6845 characters are interpreted as a wildcards. */
6846 if (_mbspbrk (tmp_path_a
, "?*"))
6847 result
= ERROR_FILE_NOT_FOUND
;
6850 _chmod (tmp_path_a
, 0666);
6852 memset (&file_op_a
, 0, sizeof (file_op_a
));
6853 file_op_a
.hwnd
= HWND_DESKTOP
;
6854 file_op_a
.wFunc
= FO_DELETE
;
6855 file_op_a
.pFrom
= tmp_path_a
;
6856 file_op_a
.fFlags
= FOF_SILENT
| FOF_NOCONFIRMATION
| FOF_ALLOWUNDO
6857 | FOF_NOERRORUI
| FOF_NO_CONNECTED_ELEMENTS
;
6858 file_op_a
.fAnyOperationsAborted
= FALSE
;
6860 result
= SHFileOperationA (&file_op_a
);
6864 report_file_error ("Removing old name", list1 (filename
));
6869 #endif /* WINDOWSNT */
6872 /***********************************************************************
6873 w32 specialized functions
6874 ***********************************************************************/
6876 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
,
6877 Sw32_send_sys_command
, 1, 2, 0,
6878 doc
: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
6879 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
6880 to minimize), #xf120 to restore frame to original size, and #xf100
6881 to activate the menubar for keyboard access. #xf140 activates the
6882 screen saver if defined.
6884 If optional parameter FRAME is not specified, use selected frame. */)
6885 (Lisp_Object command
, Lisp_Object frame
)
6887 struct frame
*f
= decode_window_system_frame (frame
);
6889 CHECK_NUMBER (command
);
6891 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
6896 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
6897 doc
: /* Get Windows to perform OPERATION on DOCUMENT.
6898 This is a wrapper around the ShellExecute system function, which
6899 invokes the application registered to handle OPERATION for DOCUMENT.
6901 OPERATION is either nil or a string that names a supported operation.
6902 What operations can be used depends on the particular DOCUMENT and its
6903 handler application, but typically it is one of the following common
6906 \"open\" - open DOCUMENT, which could be a file, a directory, or an
6907 executable program (application). If it is an application,
6908 that application is launched in the current buffer's default
6909 directory. Otherwise, the application associated with
6910 DOCUMENT is launched in the buffer's default directory.
6911 \"opennew\" - like \"open\", but instruct the application to open
6912 DOCUMENT in a new window.
6913 \"openas\" - open the \"Open With\" dialog for DOCUMENT.
6914 \"print\" - print DOCUMENT, which must be a file.
6915 \"printto\" - print DOCUMENT, which must be a file, to a specified printer.
6916 The printer should be provided in PARAMETERS, see below.
6917 \"explore\" - start the Windows Explorer on DOCUMENT.
6918 \"edit\" - launch an editor and open DOCUMENT for editing; which
6919 editor is launched depends on the association for the
6921 \"find\" - initiate search starting from DOCUMENT, which must specify
6923 \"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin.
6924 \"copy\" - copy DOCUMENT, which must be a file or a directory, into
6926 \"cut\" - move DOCUMENT, a file or a directory, into the clipboard.
6927 \"paste\" - paste the file whose name is in the clipboard into DOCUMENT,
6928 which must be a directory.
6930 - create a shortcut in DOCUMENT (which must be a directory)
6931 the file or directory whose name is in the clipboard.
6932 \"runas\" - run DOCUMENT, which must be an excutable file, with
6933 elevated privileges (a.k.a. \"as Administrator\").
6935 - open the property sheet dialog for DOCUMENT.
6936 nil - invoke the default OPERATION, or \"open\" if default is
6937 not defined or unavailable.
6939 DOCUMENT is typically the name of a document file or a URL, but can
6940 also be an executable program to run, or a directory to open in the
6941 Windows Explorer. If it is a file or a directory, it must be a local
6942 one; this function does not support remote file names.
6944 If DOCUMENT is an executable program, the optional third arg PARAMETERS
6945 can be a string containing command line parameters, separated by blanks,
6946 that will be passed to the program. Some values of OPERATION also require
6947 parameters (e.g., \"printto\" requires the printer address). Otherwise,
6948 PARAMETERS should be nil or unspecified. Note that double quote characters
6949 in PARAMETERS must each be enclosed in 2 additional quotes, as in \"\"\".
6951 Optional fourth argument SHOW-FLAG can be used to control how the
6952 application will be displayed when it is invoked. If SHOW-FLAG is nil
6953 or unspecified, the application is displayed as if SHOW-FLAG of 10 was
6954 specified, otherwise it is an integer between 0 and 11 representing
6958 1 - start as normal-size window
6959 3 - start in a maximized window
6960 6 - start in a minimized window
6961 10 - start as the application itself specifies; this is the default. */)
6962 (Lisp_Object operation
, Lisp_Object document
, Lisp_Object parameters
, Lisp_Object show_flag
)
6965 Lisp_Object current_dir
= BVAR (current_buffer
, directory
);;
6966 wchar_t *doc_w
= NULL
, *params_w
= NULL
, *ops_w
= NULL
;
6970 int use_unicode
= w32_unicode_filenames
;
6971 char *doc_a
= NULL
, *params_a
= NULL
, *ops_a
= NULL
;
6972 Lisp_Object absdoc
, handler
;
6974 struct gcpro gcpro1
;
6977 CHECK_STRING (document
);
6980 current_dir
= Fcygwin_convert_file_name_to_windows (current_dir
, Qt
);
6981 document
= Fcygwin_convert_file_name_to_windows (document
, Qt
);
6983 /* Encode filename, current directory and parameters. */
6984 current_dir
= GUI_ENCODE_FILE (current_dir
);
6985 document
= GUI_ENCODE_FILE (document
);
6986 doc_w
= GUI_SDATA (document
);
6987 if (STRINGP (parameters
))
6989 parameters
= GUI_ENCODE_SYSTEM (parameters
);
6990 params_w
= GUI_SDATA (parameters
);
6992 if (STRINGP (operation
))
6994 operation
= GUI_ENCODE_SYSTEM (operation
);
6995 ops_w
= GUI_SDATA (operation
);
6997 result
= (intptr_t) ShellExecuteW (NULL
, ops_w
, doc_w
, params_w
,
6998 GUI_SDATA (current_dir
),
6999 (INTEGERP (show_flag
)
7000 ? XINT (show_flag
) : SW_SHOWDEFAULT
));
7007 case SE_ERR_ACCESSDENIED
:
7008 errstr
= w32_strerror (ERROR_ACCESS_DENIED
);
7010 case SE_ERR_ASSOCINCOMPLETE
:
7011 case SE_ERR_NOASSOC
:
7012 errstr
= w32_strerror (ERROR_NO_ASSOCIATION
);
7014 case SE_ERR_DDEBUSY
:
7015 case SE_ERR_DDEFAIL
:
7016 errstr
= w32_strerror (ERROR_DDE_FAIL
);
7018 case SE_ERR_DDETIMEOUT
:
7019 errstr
= w32_strerror (ERROR_TIMEOUT
);
7021 case SE_ERR_DLLNOTFOUND
:
7022 errstr
= w32_strerror (ERROR_DLL_NOT_FOUND
);
7025 errstr
= w32_strerror (ERROR_FILE_NOT_FOUND
);
7028 errstr
= w32_strerror (ERROR_NOT_ENOUGH_MEMORY
);
7031 errstr
= w32_strerror (ERROR_PATH_NOT_FOUND
);
7034 errstr
= w32_strerror (ERROR_SHARING_VIOLATION
);
7037 errstr
= w32_strerror (0);
7043 const char file_url_str
[] = "file:///";
7044 const int file_url_len
= sizeof (file_url_str
) - 1;
7045 if (strncmp (SSDATA (document
), file_url_str
, file_url_len
) == 0)
7047 /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
7048 start a thread in some rare system configurations, for
7049 unknown reasons. That thread is started in the context of
7050 the Emacs process, but out of control of our code, and seems
7051 to never exit afterwards. Each such thread reserves 8MB of
7052 stack space (because that's the value recorded in the Emacs
7053 executable at link time: Emacs needs a large stack). So a
7054 large enough number of invocations of w32-shell-execute can
7055 potentially cause the Emacs process to run out of available
7056 address space, which is nasty. To work around this, we
7057 convert such URLs to local file names, which seems to prevent
7058 those threads from starting. See bug #20220. */
7059 char *p
= SSDATA (document
) + file_url_len
;
7061 if (c_isalpha (*p
) && p
[1] == ':' && IS_DIRECTORY_SEP (p
[2]))
7062 document
= Fsubstring_no_properties (document
,
7063 make_number (file_url_len
), Qnil
);
7065 /* We have a situation here. If DOCUMENT is a relative file name,
7066 but its name includes leading directories, i.e. it lives not in
7067 CURRENT_DIR, but in its subdirectory, then ShellExecute below
7068 will fail to find it. So we need to make the file name is
7069 absolute. But DOCUMENT does not have to be a file, it can be a
7070 URL, for example. So we make it absolute only if it is an
7071 existing file; if it is a file that does not exist, tough. */
7073 absdoc
= Fexpand_file_name (document
, Qnil
);
7074 /* Don't call file handlers for file-exists-p, since they might
7075 attempt to access the file, which could fail or produce undesired
7076 consequences, see bug#16558 for an example. */
7077 handler
= Ffind_file_name_handler (absdoc
, Qfile_exists_p
);
7080 Lisp_Object absdoc_encoded
= ENCODE_FILE (absdoc
);
7082 if (faccessat (AT_FDCWD
, SSDATA (absdoc_encoded
), F_OK
, AT_EACCESS
) == 0)
7084 /* ShellExecute fails if DOCUMENT is a UNC with forward
7085 slashes (expand-file-name above converts all backslashes
7086 to forward slashes). Now that we know DOCUMENT is a
7087 file, we can mirror all forward slashes into backslashes. */
7088 unixtodos_filename (SSDATA (absdoc_encoded
));
7089 document
= absdoc_encoded
;
7092 document
= ENCODE_FILE (document
);
7095 document
= ENCODE_FILE (document
);
7098 current_dir
= ENCODE_FILE (current_dir
);
7101 wchar_t document_w
[MAX_PATH
], current_dir_w
[MAX_PATH
];
7102 SHELLEXECUTEINFOW shexinfo_w
;
7104 /* Encode filename, current directory and parameters, and
7105 convert operation to UTF-16. */
7106 filename_to_utf16 (SSDATA (current_dir
), current_dir_w
);
7107 filename_to_utf16 (SSDATA (document
), document_w
);
7109 if (STRINGP (parameters
))
7113 parameters
= ENCODE_SYSTEM (parameters
);
7114 len
= pMultiByteToWideChar (CP_ACP
, MB_ERR_INVALID_CHARS
,
7115 SSDATA (parameters
), -1, NULL
, 0);
7118 params_w
= alloca (len
* sizeof (wchar_t));
7119 pMultiByteToWideChar (CP_ACP
, MB_ERR_INVALID_CHARS
,
7120 SSDATA (parameters
), -1, params_w
, len
);
7122 if (STRINGP (operation
))
7124 /* Assume OPERATION is pure ASCII. */
7125 const char *s
= SSDATA (operation
);
7127 int len
= SBYTES (operation
) + 1;
7131 d
= ops_w
= alloca (len
* sizeof (wchar_t));
7132 while (d
< ops_w
+ len
- 1)
7137 /* Using ShellExecuteEx and setting the SEE_MASK_INVOKEIDLIST
7138 flag succeeds with more OPERATIONs (a.k.a. "verbs"), as it is
7139 able to invoke verbs from shortcut menu extensions, not just
7140 static verbs listed in the Registry. */
7141 memset (&shexinfo_w
, 0, sizeof (shexinfo_w
));
7142 shexinfo_w
.cbSize
= sizeof (shexinfo_w
);
7144 SEE_MASK_INVOKEIDLIST
| SEE_MASK_FLAG_DDEWAIT
| SEE_MASK_FLAG_NO_UI
;
7145 shexinfo_w
.hwnd
= NULL
;
7146 shexinfo_w
.lpVerb
= ops_w
;
7147 shexinfo_w
.lpFile
= doc_w
;
7148 shexinfo_w
.lpParameters
= params_w
;
7149 shexinfo_w
.lpDirectory
= current_dir_w
;
7151 (INTEGERP (show_flag
) ? XINT (show_flag
) : SW_SHOWDEFAULT
);
7152 success
= ShellExecuteExW (&shexinfo_w
);
7156 char document_a
[MAX_PATH
], current_dir_a
[MAX_PATH
];
7157 SHELLEXECUTEINFOA shexinfo_a
;
7159 filename_to_ansi (SSDATA (current_dir
), current_dir_a
);
7160 filename_to_ansi (SSDATA (document
), document_a
);
7162 if (STRINGP (parameters
))
7164 parameters
= ENCODE_SYSTEM (parameters
);
7165 params_a
= SSDATA (parameters
);
7167 if (STRINGP (operation
))
7169 /* Assume OPERATION is pure ASCII. */
7170 ops_a
= SSDATA (operation
);
7172 memset (&shexinfo_a
, 0, sizeof (shexinfo_a
));
7173 shexinfo_a
.cbSize
= sizeof (shexinfo_a
);
7175 SEE_MASK_INVOKEIDLIST
| SEE_MASK_FLAG_DDEWAIT
| SEE_MASK_FLAG_NO_UI
;
7176 shexinfo_a
.hwnd
= NULL
;
7177 shexinfo_a
.lpVerb
= ops_a
;
7178 shexinfo_a
.lpFile
= doc_a
;
7179 shexinfo_a
.lpParameters
= params_a
;
7180 shexinfo_a
.lpDirectory
= current_dir_a
;
7182 (INTEGERP (show_flag
) ? XINT (show_flag
) : SW_SHOWDEFAULT
);
7183 success
= ShellExecuteExA (&shexinfo_a
);
7189 errstr
= w32_strerror (0);
7191 #endif /* !CYGWIN */
7193 /* The error string might be encoded in the locale's encoding. */
7194 if (!NILP (Vlocale_coding_system
))
7196 Lisp_Object decoded
=
7197 code_convert_string_norecord (build_unibyte_string (errstr
),
7198 Vlocale_coding_system
, 0);
7199 errstr
= SSDATA (decoded
);
7201 error ("ShellExecute failed: %s", errstr
);
7204 /* Lookup virtual keycode from string representing the name of a
7205 non-ascii keystroke into the corresponding virtual key, using
7206 lispy_function_keys. */
7208 lookup_vk_code (char *key
)
7212 for (i
= 0; i
< 256; i
++)
7213 if (lispy_function_keys
[i
]
7214 && strcmp (lispy_function_keys
[i
], key
) == 0)
7220 /* Convert a one-element vector style key sequence to a hot key
7223 w32_parse_hot_key (Lisp_Object key
)
7225 /* Copied from Fdefine_key and store_in_keymap. */
7226 register Lisp_Object c
;
7230 struct gcpro gcpro1
;
7234 if (ASIZE (key
) != 1)
7241 if (CONSP (c
) && lucid_event_type_list_p (c
))
7242 c
= Fevent_convert_list (c
);
7246 if (! INTEGERP (c
) && ! SYMBOLP (c
))
7247 error ("Key definition is invalid");
7249 /* Work out the base key and the modifiers. */
7252 c
= parse_modifiers (c
);
7253 lisp_modifiers
= XINT (Fcar (Fcdr (c
)));
7257 vk_code
= lookup_vk_code (SDATA (SYMBOL_NAME (c
)));
7259 else if (INTEGERP (c
))
7261 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
7262 /* Many ascii characters are their own virtual key code. */
7263 vk_code
= XINT (c
) & CHARACTERBITS
;
7266 if (vk_code
< 0 || vk_code
> 255)
7269 if ((lisp_modifiers
& meta_modifier
) != 0
7270 && !NILP (Vw32_alt_is_meta
))
7271 lisp_modifiers
|= alt_modifier
;
7273 /* Supply defs missing from mingw32. */
7275 #define MOD_ALT 0x0001
7276 #define MOD_CONTROL 0x0002
7277 #define MOD_SHIFT 0x0004
7278 #define MOD_WIN 0x0008
7281 /* Convert lisp modifiers to Windows hot-key form. */
7282 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
7283 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
7284 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
7285 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
7287 return HOTKEY (vk_code
, w32_modifiers
);
7290 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
,
7291 Sw32_register_hot_key
, 1, 1, 0,
7292 doc
: /* Register KEY as a hot-key combination.
7293 Certain key combinations like Alt-Tab are reserved for system use on
7294 Windows, and therefore are normally intercepted by the system. However,
7295 most of these key combinations can be received by registering them as
7296 hot-keys, overriding their special meaning.
7298 KEY must be a one element key definition in vector form that would be
7299 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
7300 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
7301 is always interpreted as the Windows modifier keys.
7303 The return value is the hotkey-id if registered, otherwise nil. */)
7306 key
= w32_parse_hot_key (key
);
7308 if (!NILP (key
) && NILP (Fmemq (key
, w32_grabbed_keys
)))
7310 /* Reuse an empty slot if possible. */
7311 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
7313 /* Safe to add new key to list, even if we have focus. */
7315 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
7317 XSETCAR (item
, key
);
7319 /* Notify input thread about new hot-key definition, so that it
7320 takes effect without needing to switch focus. */
7321 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
7322 (WPARAM
) XINT (key
), 0);
7328 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
,
7329 Sw32_unregister_hot_key
, 1, 1, 0,
7330 doc
: /* Unregister KEY as a hot-key combination. */)
7335 if (!INTEGERP (key
))
7336 key
= w32_parse_hot_key (key
);
7338 item
= Fmemq (key
, w32_grabbed_keys
);
7344 eassert (CONSP (item
));
7345 /* Pass the tail of the list as a pointer to a Lisp_Cons cell,
7346 so that it works in a --with-wide-int build as well. */
7347 lparam
= (LPARAM
) XUNTAG (item
, Lisp_Cons
);
7349 /* Notify input thread about hot-key definition being removed, so
7350 that it takes effect without needing focus switch. */
7351 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
7352 (WPARAM
) XINT (XCAR (item
)), lparam
))
7355 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
7362 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
,
7363 Sw32_registered_hot_keys
, 0, 0, 0,
7364 doc
: /* Return list of registered hot-key IDs. */)
7367 return Fdelq (Qnil
, Fcopy_sequence (w32_grabbed_keys
));
7370 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
,
7371 Sw32_reconstruct_hot_key
, 1, 1, 0,
7372 doc
: /* Convert hot-key ID to a lisp key combination.
7373 usage: (w32-reconstruct-hot-key ID) */)
7374 (Lisp_Object hotkeyid
)
7376 int vk_code
, w32_modifiers
;
7379 CHECK_NUMBER (hotkeyid
);
7381 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
7382 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
7384 if (vk_code
< 256 && lispy_function_keys
[vk_code
])
7385 key
= intern (lispy_function_keys
[vk_code
]);
7387 key
= make_number (vk_code
);
7389 key
= Fcons (key
, Qnil
);
7390 if (w32_modifiers
& MOD_SHIFT
)
7391 key
= Fcons (Qshift
, key
);
7392 if (w32_modifiers
& MOD_CONTROL
)
7393 key
= Fcons (Qctrl
, key
);
7394 if (w32_modifiers
& MOD_ALT
)
7395 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
7396 if (w32_modifiers
& MOD_WIN
)
7397 key
= Fcons (Qhyper
, key
);
7402 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
,
7403 Sw32_toggle_lock_key
, 1, 2, 0,
7404 doc
: /* Toggle the state of the lock key KEY.
7405 KEY can be `capslock', `kp-numlock', or `scroll'.
7406 If the optional parameter NEW-STATE is a number, then the state of KEY
7407 is set to off if the low bit of NEW-STATE is zero, otherwise on.
7408 If NEW-STATE is omitted or nil, the function toggles the state,
7410 Value is the new state of the key, or nil if the function failed
7411 to change the state. */)
7412 (Lisp_Object key
, Lisp_Object new_state
)
7417 if (EQ (key
, intern ("capslock")))
7418 vk_code
= VK_CAPITAL
;
7419 else if (EQ (key
, intern ("kp-numlock")))
7420 vk_code
= VK_NUMLOCK
;
7421 else if (EQ (key
, intern ("scroll")))
7422 vk_code
= VK_SCROLL
;
7426 if (!dwWindowsThreadId
)
7427 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
7429 if (NILP (new_state
))
7432 lparam
= (XUINT (new_state
)) & 1;
7433 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
7434 (WPARAM
) vk_code
, lparam
))
7437 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
7438 return make_number (msg
.wParam
);
7443 DEFUN ("w32-window-exists-p", Fw32_window_exists_p
, Sw32_window_exists_p
,
7445 doc
: /* Return non-nil if a window exists with the specified CLASS and NAME.
7447 This is a direct interface to the Windows API FindWindow function. */)
7448 (Lisp_Object
class, Lisp_Object name
)
7453 CHECK_STRING (class);
7455 CHECK_STRING (name
);
7457 hnd
= FindWindow (STRINGP (class) ? ((LPCTSTR
) SDATA (class)) : NULL
,
7458 STRINGP (name
) ? ((LPCTSTR
) SDATA (name
)) : NULL
);
7464 DEFUN ("w32-frame-menu-bar-size", Fw32_frame_menu_bar_size
, Sw32_frame_menu_bar_size
, 0, 1, 0,
7465 doc
: /* Return sizes of menu bar on frame FRAME.
7466 The return value is a list of four elements: The current width and
7467 height of FRAME's menu bar in pixels, the height of one menu bar line in
7468 a wrapped menu bar in pixels, and the height of a single line menu bar
7471 If FRAME is omitted or nil, the selected frame is used. */)
7474 struct frame
*f
= decode_any_frame (frame
);
7475 MENUBARINFO menu_bar
;
7476 int width
, height
, single_height
, wrapped_height
;
7480 single_height
= GetSystemMetrics (SM_CYMENU
);
7481 wrapped_height
= GetSystemMetrics (SM_CYMENUSIZE
);
7482 menu_bar
.cbSize
= sizeof (menu_bar
);
7483 menu_bar
.rcBar
.right
= menu_bar
.rcBar
.left
= 0;
7484 menu_bar
.rcBar
.top
= menu_bar
.rcBar
.bottom
= 0;
7485 GetMenuBarInfo (FRAME_W32_WINDOW (f
), 0xFFFFFFFD, 0, &menu_bar
);
7486 width
= menu_bar
.rcBar
.right
- menu_bar
.rcBar
.left
;
7487 height
= menu_bar
.rcBar
.bottom
- menu_bar
.rcBar
.top
;
7491 return list4 (make_number (width
), make_number (height
),
7492 make_number (wrapped_height
), make_number (single_height
));
7495 DEFUN ("w32-frame-rect", Fw32_frame_rect
, Sw32_frame_rect
, 0, 2, 0,
7496 doc
: /* Return boundary rectangle of FRAME in screen coordinates.
7497 FRAME must be a live frame and defaults to the selected one.
7499 The boundary rectangle is a list of four elements, specifying the left,
7500 top, right and bottom screen coordinates of FRAME including menu and
7501 title bar and decorations. Optional argument CLIENT non-nil means to
7502 return the boundaries of the client rectangle which excludes menu and
7503 title bar and decorations. */)
7504 (Lisp_Object frame
, Lisp_Object client
)
7506 struct frame
*f
= decode_live_frame (frame
);
7512 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
7514 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
7518 return list4 (make_number (rect
.left
), make_number (rect
.top
),
7519 make_number (rect
.right
), make_number (rect
.bottom
));
7522 DEFUN ("x-frame-geometry", Fx_frame_geometry
, Sx_frame_geometry
, 0, 1, 0,
7523 doc
: /* Return geometric attributes of frame FRAME.
7524 FRAME must be a live frame and defaults to the selected one.
7526 The return value is an association list containing the following
7527 elements (all size values are in pixels).
7529 - `frame-outer-size' is a cons of the outer width and height of FRAME.
7530 The outer size includes the title bar and the external borders as well
7531 as any menu and/or tool bar of frame.
7533 - `border' is a cons of the horizontal and vertical width of FRAME's
7536 - `title-bar-height' is the height of the title bar of FRAME.
7538 - `menu-bar-external' if t means the menu bar is by default external
7539 (not included in the inner size of FRAME).
7541 - `menu-bar-size' is a cons of the width and height of the menu bar of
7544 - `tool-bar-external' if t means the tool bar is by default external
7545 (not included in the inner size of FRAME).
7547 - `tool-bar-side' tells tells on which side the tool bar on FRAME is by
7548 default and can be one of `left', `top', `right' or `bottom'.
7550 - `tool-bar-size' is a cons of the width and height of the tool bar of
7553 - `frame-inner-size' is a cons of the inner width and height of FRAME.
7554 This excludes FRAME's title bar and external border as well as any
7555 external menu and/or tool bar. */)
7558 struct frame
*f
= decode_live_frame (frame
);
7559 Lisp_Object geometry
= Qnil
;
7560 RECT frame_outer_edges
, frame_inner_edges
;
7561 MENUBARINFO menu_bar
;
7562 int border_width
, border_height
, title_height
;
7563 int single_bar_height
, wrapped_bar_height
, menu_bar_height
;
7564 Lisp_Object fullscreen
= Fframe_parameter (frame
, Qfullscreen
);
7568 /* Outer frame rectangle, including outer borders and title bar. */
7569 GetWindowRect (FRAME_W32_WINDOW (f
), &frame_outer_edges
);
7570 /* Inner frame rectangle, excluding borders and title bar. */
7571 GetClientRect (FRAME_W32_WINDOW (f
), &frame_inner_edges
);
7573 border_width
= GetSystemMetrics (SM_CXFRAME
);
7574 border_height
= GetSystemMetrics (SM_CYFRAME
);
7576 title_height
= GetSystemMetrics (SM_CYCAPTION
);
7578 menu_bar
.cbSize
= sizeof (menu_bar
);
7579 menu_bar
.rcBar
.right
= menu_bar
.rcBar
.left
= 0;
7580 menu_bar
.rcBar
.top
= menu_bar
.rcBar
.bottom
= 0;
7581 GetMenuBarInfo (FRAME_W32_WINDOW (f
), 0xFFFFFFFD, 0, &menu_bar
);
7582 single_bar_height
= GetSystemMetrics (SM_CYMENU
);
7583 wrapped_bar_height
= GetSystemMetrics (SM_CYMENUSIZE
);
7586 menu_bar_height
= menu_bar
.rcBar
.bottom
- menu_bar
.rcBar
.top
;
7587 /* Fix menu bar height reported by GetMenuBarInfo. */
7588 if (menu_bar_height
> single_bar_height
)
7589 /* A wrapped menu bar. */
7590 menu_bar_height
+= single_bar_height
- wrapped_bar_height
;
7591 else if (menu_bar_height
> 0)
7592 /* A single line menu bar. */
7593 menu_bar_height
= single_bar_height
;
7596 listn (CONSTYPE_HEAP
, 10,
7597 Fcons (Qframe_position
,
7598 Fcons (make_number (frame_outer_edges
.left
),
7599 make_number (frame_outer_edges
.top
))),
7600 Fcons (Qframe_outer_size
,
7602 (frame_outer_edges
.right
- frame_outer_edges
.left
),
7604 (frame_outer_edges
.bottom
- frame_outer_edges
.top
))),
7605 Fcons (Qexternal_border_size
,
7606 ((EQ (fullscreen
, Qfullboth
) || EQ (fullscreen
, Qfullscreen
))
7607 ? Fcons (make_number (0), make_number (0))
7608 : Fcons (make_number (border_width
),
7609 make_number (border_height
)))),
7610 Fcons (Qtitle_height
,
7611 ((EQ (fullscreen
, Qfullboth
) || EQ (fullscreen
, Qfullscreen
))
7613 : make_number (title_height
))),
7614 Fcons (Qmenu_bar_external
, Qt
),
7615 Fcons (Qmenu_bar_size
,
7617 (menu_bar
.rcBar
.right
- menu_bar
.rcBar
.left
),
7618 make_number (menu_bar_height
))),
7619 Fcons (Qtool_bar_external
, Qnil
),
7620 Fcons (Qtool_bar_position
, Qtop
),
7621 Fcons (Qtool_bar_size
,
7622 Fcons (make_number (FRAME_TOOL_BAR_LINES (f
)
7623 ? (FRAME_PIXEL_WIDTH (f
)
7624 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f
))
7626 make_number (FRAME_TOOL_BAR_HEIGHT (f
)))),
7627 Fcons (Qframe_inner_size
,
7629 (frame_inner_edges
.right
- frame_inner_edges
.left
),
7631 (frame_inner_edges
.bottom
- frame_inner_edges
.top
))));
7634 DEFUN ("w32-battery-status", Fw32_battery_status
, Sw32_battery_status
, 0, 0, 0,
7635 doc
: /* Get power status information from Windows system.
7637 The following %-sequences are provided:
7638 %L AC line status (verbose)
7639 %B Battery status (verbose)
7640 %b Battery status, empty means high, `-' means low,
7641 `!' means critical, and `+' means charging
7642 %p Battery load percentage
7643 %s Remaining time (to charge or discharge) in seconds
7644 %m Remaining time (to charge or discharge) in minutes
7645 %h Remaining time (to charge or discharge) in hours
7646 %t Remaining time (to charge or discharge) in the form `h:min' */)
7649 Lisp_Object status
= Qnil
;
7651 SYSTEM_POWER_STATUS system_status
;
7652 if (GetSystemPowerStatus (&system_status
))
7654 Lisp_Object line_status
, battery_status
, battery_status_symbol
;
7655 Lisp_Object load_percentage
, seconds
, minutes
, hours
, remain
;
7657 long seconds_left
= (long) system_status
.BatteryLifeTime
;
7659 if (system_status
.ACLineStatus
== 0)
7660 line_status
= build_string ("off-line");
7661 else if (system_status
.ACLineStatus
== 1)
7662 line_status
= build_string ("on-line");
7664 line_status
= build_string ("N/A");
7666 if (system_status
.BatteryFlag
& 128)
7668 battery_status
= build_string ("N/A");
7669 battery_status_symbol
= empty_unibyte_string
;
7671 else if (system_status
.BatteryFlag
& 8)
7673 battery_status
= build_string ("charging");
7674 battery_status_symbol
= build_string ("+");
7675 if (system_status
.BatteryFullLifeTime
!= -1L)
7676 seconds_left
= system_status
.BatteryFullLifeTime
- seconds_left
;
7678 else if (system_status
.BatteryFlag
& 4)
7680 battery_status
= build_string ("critical");
7681 battery_status_symbol
= build_string ("!");
7683 else if (system_status
.BatteryFlag
& 2)
7685 battery_status
= build_string ("low");
7686 battery_status_symbol
= build_string ("-");
7688 else if (system_status
.BatteryFlag
& 1)
7690 battery_status
= build_string ("high");
7691 battery_status_symbol
= empty_unibyte_string
;
7695 battery_status
= build_string ("medium");
7696 battery_status_symbol
= empty_unibyte_string
;
7699 if (system_status
.BatteryLifePercent
> 100)
7700 load_percentage
= build_string ("N/A");
7704 snprintf (buffer
, 16, "%d", system_status
.BatteryLifePercent
);
7705 load_percentage
= build_string (buffer
);
7708 if (seconds_left
< 0)
7709 seconds
= minutes
= hours
= remain
= build_string ("N/A");
7715 snprintf (buffer
, 16, "%ld", seconds_left
);
7716 seconds
= build_string (buffer
);
7718 m
= seconds_left
/ 60;
7719 snprintf (buffer
, 16, "%ld", m
);
7720 minutes
= build_string (buffer
);
7722 h
= seconds_left
/ 3600.0;
7723 snprintf (buffer
, 16, "%3.1f", h
);
7724 hours
= build_string (buffer
);
7726 snprintf (buffer
, 16, "%ld:%02ld", m
/ 60, m
% 60);
7727 remain
= build_string (buffer
);
7730 status
= listn (CONSTYPE_HEAP
, 8,
7731 Fcons (make_number ('L'), line_status
),
7732 Fcons (make_number ('B'), battery_status
),
7733 Fcons (make_number ('b'), battery_status_symbol
),
7734 Fcons (make_number ('p'), load_percentage
),
7735 Fcons (make_number ('s'), seconds
),
7736 Fcons (make_number ('m'), minutes
),
7737 Fcons (make_number ('h'), hours
),
7738 Fcons (make_number ('t'), remain
));
7745 DEFUN ("file-system-info", Ffile_system_info
, Sfile_system_info
, 1, 1, 0,
7746 doc
: /* Return storage information about the file system FILENAME is on.
7747 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
7748 storage of the file system, FREE is the free storage, and AVAIL is the
7749 storage available to a non-superuser. All 3 numbers are in bytes.
7750 If the underlying system call fails, value is nil. */)
7751 (Lisp_Object filename
)
7753 Lisp_Object encoded
, value
;
7755 CHECK_STRING (filename
);
7756 filename
= Fexpand_file_name (filename
, Qnil
);
7757 encoded
= ENCODE_FILE (filename
);
7761 /* Determining the required information on Windows turns out, sadly,
7762 to be more involved than one would hope. The original Windows API
7763 call for this will return bogus information on some systems, but we
7764 must dynamically probe for the replacement api, since that was
7765 added rather late on. */
7767 HMODULE hKernel
= GetModuleHandle ("kernel32");
7768 BOOL (WINAPI
*pfn_GetDiskFreeSpaceExW
)
7769 (wchar_t *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
7770 = GetProcAddress (hKernel
, "GetDiskFreeSpaceExW");
7771 BOOL (WINAPI
*pfn_GetDiskFreeSpaceExA
)
7772 (char *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
7773 = GetProcAddress (hKernel
, "GetDiskFreeSpaceExA");
7774 bool have_pfn_GetDiskFreeSpaceEx
=
7775 ((w32_unicode_filenames
&& pfn_GetDiskFreeSpaceExW
)
7776 || (!w32_unicode_filenames
&& pfn_GetDiskFreeSpaceExA
));
7778 /* On Windows, we may need to specify the root directory of the
7779 volume holding FILENAME. */
7780 char rootname
[MAX_UTF8_PATH
];
7781 wchar_t rootname_w
[MAX_PATH
];
7782 char rootname_a
[MAX_PATH
];
7783 char *name
= SDATA (encoded
);
7786 /* find the root name of the volume if given */
7787 if (isalpha (name
[0]) && name
[1] == ':')
7789 rootname
[0] = name
[0];
7790 rootname
[1] = name
[1];
7794 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
7796 char *str
= rootname
;
7800 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
7810 if (w32_unicode_filenames
)
7811 filename_to_utf16 (rootname
, rootname_w
);
7813 filename_to_ansi (rootname
, rootname_a
);
7815 if (have_pfn_GetDiskFreeSpaceEx
)
7817 /* Unsigned large integers cannot be cast to double, so
7818 use signed ones instead. */
7819 LARGE_INTEGER availbytes
;
7820 LARGE_INTEGER freebytes
;
7821 LARGE_INTEGER totalbytes
;
7823 if (w32_unicode_filenames
)
7824 result
= pfn_GetDiskFreeSpaceExW (rootname_w
,
7825 (ULARGE_INTEGER
*)&availbytes
,
7826 (ULARGE_INTEGER
*)&totalbytes
,
7827 (ULARGE_INTEGER
*)&freebytes
);
7829 result
= pfn_GetDiskFreeSpaceExA (rootname_a
,
7830 (ULARGE_INTEGER
*)&availbytes
,
7831 (ULARGE_INTEGER
*)&totalbytes
,
7832 (ULARGE_INTEGER
*)&freebytes
);
7834 value
= list3 (make_float ((double) totalbytes
.QuadPart
),
7835 make_float ((double) freebytes
.QuadPart
),
7836 make_float ((double) availbytes
.QuadPart
));
7840 DWORD sectors_per_cluster
;
7841 DWORD bytes_per_sector
;
7842 DWORD free_clusters
;
7843 DWORD total_clusters
;
7845 if (w32_unicode_filenames
)
7846 result
= GetDiskFreeSpaceW (rootname_w
,
7847 §ors_per_cluster
,
7852 result
= GetDiskFreeSpaceA (rootname_a
,
7853 §ors_per_cluster
,
7858 value
= list3 (make_float ((double) total_clusters
7859 * sectors_per_cluster
* bytes_per_sector
),
7860 make_float ((double) free_clusters
7861 * sectors_per_cluster
* bytes_per_sector
),
7862 make_float ((double) free_clusters
7863 * sectors_per_cluster
* bytes_per_sector
));
7869 #endif /* WINDOWSNT */
7873 DEFUN ("default-printer-name", Fdefault_printer_name
, Sdefault_printer_name
,
7874 0, 0, 0, doc
: /* Return the name of Windows default printer device. */)
7877 static char pname_buf
[256];
7880 PRINTER_INFO_2W
*ppi2w
= NULL
;
7881 PRINTER_INFO_2A
*ppi2a
= NULL
;
7882 DWORD dwNeeded
= 0, dwReturned
= 0;
7883 char server_name
[MAX_UTF8_PATH
], share_name
[MAX_UTF8_PATH
];
7884 char port_name
[MAX_UTF8_PATH
];
7886 /* Retrieve the default string from Win.ini (the registry).
7887 * String will be in form "printername,drivername,portname".
7888 * This is the most portable way to get the default printer. */
7889 if (GetProfileString ("windows", "device", ",,", pname_buf
, sizeof (pname_buf
)) <= 0)
7891 /* printername precedes first "," character */
7892 strtok (pname_buf
, ",");
7893 /* We want to know more than the printer name */
7894 if (!OpenPrinter (pname_buf
, &hPrn
, NULL
))
7896 /* GetPrinterW is not supported by unicows.dll. */
7897 if (w32_unicode_filenames
&& os_subtype
!= OS_9X
)
7898 GetPrinterW (hPrn
, 2, NULL
, 0, &dwNeeded
);
7900 GetPrinterA (hPrn
, 2, NULL
, 0, &dwNeeded
);
7903 ClosePrinter (hPrn
);
7906 /* Call GetPrinter again with big enough memory block. */
7907 if (w32_unicode_filenames
&& os_subtype
!= OS_9X
)
7909 /* Allocate memory for the PRINTER_INFO_2 struct. */
7910 ppi2w
= xmalloc (dwNeeded
);
7911 err
= GetPrinterW (hPrn
, 2, (LPBYTE
)ppi2w
, dwNeeded
, &dwReturned
);
7912 ClosePrinter (hPrn
);
7919 if ((ppi2w
->Attributes
& PRINTER_ATTRIBUTE_SHARED
)
7920 && ppi2w
->pServerName
)
7922 filename_from_utf16 (ppi2w
->pServerName
, server_name
);
7923 filename_from_utf16 (ppi2w
->pShareName
, share_name
);
7927 server_name
[0] = '\0';
7928 filename_from_utf16 (ppi2w
->pPortName
, port_name
);
7933 ppi2a
= xmalloc (dwNeeded
);
7934 err
= GetPrinterA (hPrn
, 2, (LPBYTE
)ppi2a
, dwNeeded
, &dwReturned
);
7935 ClosePrinter (hPrn
);
7942 if ((ppi2a
->Attributes
& PRINTER_ATTRIBUTE_SHARED
)
7943 && ppi2a
->pServerName
)
7945 filename_from_ansi (ppi2a
->pServerName
, server_name
);
7946 filename_from_ansi (ppi2a
->pShareName
, share_name
);
7950 server_name
[0] = '\0';
7951 filename_from_ansi (ppi2a
->pPortName
, port_name
);
7957 /* a remote printer */
7958 if (server_name
[0] == '\\')
7959 snprintf (pname_buf
, sizeof (pname_buf
), "%s\\%s", server_name
,
7962 snprintf (pname_buf
, sizeof (pname_buf
), "\\\\%s\\%s", server_name
,
7964 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
7968 /* a local printer */
7969 strncpy (pname_buf
, port_name
, sizeof (pname_buf
));
7970 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
7971 /* `pPortName' can include several ports, delimited by ','.
7972 * we only use the first one. */
7973 strtok (pname_buf
, ",");
7976 return DECODE_FILE (build_unibyte_string (pname_buf
));
7978 #endif /* WINDOWSNT */
7981 /* Equivalent of strerror for W32 error codes. */
7983 w32_strerror (int error_no
)
7985 static char buf
[500];
7989 error_no
= GetLastError ();
7991 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
7992 FORMAT_MESSAGE_IGNORE_INSERTS
,
7995 0, /* choose most suitable language */
7996 buf
, sizeof (buf
), NULL
);
7998 while (ret
> 0 && (buf
[ret
- 1] == '\n' ||
7999 buf
[ret
- 1] == '\r' ))
8003 sprintf (buf
, "w32 error %u", error_no
);
8008 /* For convenience when debugging. (You cannot call GetLastError
8009 directly from GDB: it will crash, because it uses the __stdcall
8010 calling convention, not the _cdecl convention assumed by GDB.) */
8012 w32_last_error (void)
8014 return GetLastError ();
8017 /* Cache information describing the NT system for later use. */
8019 cache_system_info (void)
8032 /* Cache the module handle of Emacs itself. */
8033 hinst
= GetModuleHandle (NULL
);
8035 /* Cache the version of the operating system. */
8036 version
.data
= GetVersion ();
8037 w32_major_version
= version
.info
.major
;
8038 w32_minor_version
= version
.info
.minor
;
8040 if (version
.info
.platform
& 0x8000)
8045 /* Cache page size, allocation unit, processor type, etc. */
8046 GetSystemInfo (&sysinfo_cache
);
8047 syspage_mask
= (DWORD_PTR
)sysinfo_cache
.dwPageSize
- 1;
8049 /* Cache os info. */
8050 osinfo_cache
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
8051 GetVersionEx (&osinfo_cache
);
8053 w32_build_number
= osinfo_cache
.dwBuildNumber
;
8054 if (os_subtype
== OS_9X
)
8055 w32_build_number
&= 0xffff;
8057 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
8062 _DebPrint (const char *fmt
, ...)
8067 va_start (args
, fmt
);
8068 vsprintf (buf
, fmt
, args
);
8071 fprintf (stderr
, "%s", buf
);
8073 OutputDebugString (buf
);
8078 w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
)
8080 int cur_state
= (GetKeyState (vk_code
) & 1);
8082 if (NILP (new_state
)
8083 || (NUMBERP (new_state
)
8084 && ((XUINT (new_state
)) & 1) != cur_state
))
8087 faked_key
= vk_code
;
8088 #endif /* WINDOWSNT */
8090 keybd_event ((BYTE
) vk_code
,
8091 (BYTE
) MapVirtualKey (vk_code
, 0),
8092 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
8093 keybd_event ((BYTE
) vk_code
,
8094 (BYTE
) MapVirtualKey (vk_code
, 0),
8095 KEYEVENTF_EXTENDEDKEY
| 0, 0);
8096 keybd_event ((BYTE
) vk_code
,
8097 (BYTE
) MapVirtualKey (vk_code
, 0),
8098 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
8099 cur_state
= !cur_state
;
8105 /* Translate console modifiers to emacs modifiers.
8106 German keyboard support (Kai Morgan Zeise 2/18/95). */
8108 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
8112 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
8113 pressed, first remove those modifiers. */
8114 if (!NILP (Vw32_recognize_altgr
)
8115 && (mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
8116 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
8117 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
8119 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
8120 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
8122 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
8124 retval
|= ctrl_modifier
;
8125 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
8126 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
8127 retval
|= meta_modifier
;
8130 if (mods
& LEFT_WIN_PRESSED
)
8131 retval
|= w32_key_to_modifier (VK_LWIN
);
8132 if (mods
& RIGHT_WIN_PRESSED
)
8133 retval
|= w32_key_to_modifier (VK_RWIN
);
8134 if (mods
& APPS_PRESSED
)
8135 retval
|= w32_key_to_modifier (VK_APPS
);
8136 if (mods
& SCROLLLOCK_ON
)
8137 retval
|= w32_key_to_modifier (VK_SCROLL
);
8139 /* Just in case someone wanted the original behavior, make it
8140 optional by setting w32-capslock-is-shiftlock to t. */
8141 if (NILP (Vw32_capslock_is_shiftlock
)
8142 /* Keys that should _not_ be affected by CapsLock. */
8143 && ( (key
== VK_BACK
)
8145 || (key
== VK_CLEAR
)
8146 || (key
== VK_RETURN
)
8147 || (key
== VK_ESCAPE
)
8148 || ((key
>= VK_SPACE
) && (key
<= VK_HELP
))
8149 || ((key
>= VK_NUMPAD0
) && (key
<= VK_F24
))
8150 || ((key
>= VK_NUMPAD_CLEAR
) && (key
<= VK_NUMPAD_DELETE
))
8153 /* Only consider shift state. */
8154 if ((mods
& SHIFT_PRESSED
) != 0)
8155 retval
|= shift_modifier
;
8159 /* Ignore CapsLock state if not enabled. */
8160 if (NILP (Vw32_enable_caps_lock
))
8161 mods
&= ~CAPSLOCK_ON
;
8162 if ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) != 0)
8163 retval
|= shift_modifier
;
8169 /* The return code indicates key code size. cpID is the codepage to
8170 use for translation to Unicode; -1 means use the current console
8173 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
, int cpId
)
8175 unsigned int key_code
= event
->wVirtualKeyCode
;
8176 unsigned int mods
= event
->dwControlKeyState
;
8178 static BYTE ansi_code
[4];
8179 static int isdead
= 0;
8183 event
->uChar
.AsciiChar
= ansi_code
[2];
8187 if (event
->uChar
.AsciiChar
!= 0)
8190 memset (keystate
, 0, sizeof (keystate
));
8191 keystate
[key_code
] = 0x80;
8192 if (mods
& SHIFT_PRESSED
)
8193 keystate
[VK_SHIFT
] = 0x80;
8194 if (mods
& CAPSLOCK_ON
)
8195 keystate
[VK_CAPITAL
] = 1;
8196 /* If we recognize right-alt and left-ctrl as AltGr, set the key
8197 states accordingly before invoking ToAscii. */
8198 if (!NILP (Vw32_recognize_altgr
)
8199 && (mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
8201 keystate
[VK_CONTROL
] = 0x80;
8202 keystate
[VK_LCONTROL
] = 0x80;
8203 keystate
[VK_MENU
] = 0x80;
8204 keystate
[VK_RMENU
] = 0x80;
8208 /* Because of an OS bug, ToAscii corrupts the stack when called to
8209 convert a dead key in console mode on NT4. Unfortunately, trying
8210 to check for dead keys using MapVirtualKey doesn't work either -
8211 these functions apparently use internal information about keyboard
8212 layout which doesn't get properly updated in console programs when
8213 changing layout (though apparently it gets partly updated,
8214 otherwise ToAscii wouldn't crash). */
8215 if (is_dead_key (event
->wVirtualKeyCode
))
8219 /* On NT, call ToUnicode instead and then convert to the current
8220 console input codepage. */
8221 if (os_subtype
== OS_NT
)
8225 isdead
= ToUnicode (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
8226 keystate
, buf
, 128, 0);
8229 /* When we are called from the GUI message processing code,
8230 we are passed the current keyboard codepage, a positive
8231 number, to use below. */
8233 cpId
= GetConsoleCP ();
8235 event
->uChar
.UnicodeChar
= buf
[isdead
- 1];
8236 isdead
= WideCharToMultiByte (cpId
, 0, buf
, isdead
,
8237 ansi_code
, 4, NULL
, NULL
);
8244 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
8245 keystate
, (LPWORD
) ansi_code
, 0);
8250 event
->uChar
.AsciiChar
= ansi_code
[0];
8256 w32_sys_ring_bell (struct frame
*f
)
8258 if (sound_type
== 0xFFFFFFFF)
8262 else if (sound_type
== MB_EMACS_SILENT
)
8267 MessageBeep (sound_type
);
8270 DEFUN ("w32--menu-bar-in-use", Fw32__menu_bar_in_use
, Sw32__menu_bar_in_use
,
8272 doc
: /* Return non-nil when a menu-bar menu is being used.
8273 Internal use only. */)
8276 return menubar_in_use
? Qt
: Qnil
;
8280 /***********************************************************************
8282 ***********************************************************************/
8284 /* Keep this list in the same order as frame_parms in frame.c.
8285 Use 0 for unsupported frame parameters. */
8287 frame_parm_handler w32_frame_parm_handlers
[] =
8291 x_set_background_color
,
8297 x_set_foreground_color
,
8300 x_set_internal_border_width
,
8301 x_set_right_divider_width
,
8302 x_set_bottom_divider_width
,
8303 x_set_menu_bar_lines
,
8305 x_explicitly_set_name
,
8306 x_set_scroll_bar_width
,
8307 x_set_scroll_bar_height
,
8310 x_set_vertical_scroll_bars
,
8311 x_set_horizontal_scroll_bars
,
8313 x_set_tool_bar_lines
,
8314 0, /* x_set_scroll_bar_foreground, */
8315 0, /* x_set_scroll_bar_background, */
8320 0, /* x_set_wait_for_wm, */
8324 0, /* x_set_sticky */
8325 0, /* x_set_tool_bar_position */
8329 syms_of_w32fns (void)
8331 globals_of_w32fns ();
8332 track_mouse_window
= NULL
;
8334 w32_visible_system_caret_hwnd
= NULL
;
8336 DEFSYM (Qundefined_color
, "undefined-color");
8337 DEFSYM (Qcancel_timer
, "cancel-timer");
8338 DEFSYM (Qhyper
, "hyper");
8339 DEFSYM (Qsuper
, "super");
8340 DEFSYM (Qmeta
, "meta");
8341 DEFSYM (Qalt
, "alt");
8342 DEFSYM (Qctrl
, "ctrl");
8343 DEFSYM (Qcontrol
, "control");
8344 DEFSYM (Qshift
, "shift");
8345 DEFSYM (Qfont_param
, "font-parameter");
8346 DEFSYM (Qgeometry
, "geometry");
8347 DEFSYM (Qworkarea
, "workarea");
8348 DEFSYM (Qmm_size
, "mm-size");
8349 DEFSYM (Qframes
, "frames");
8351 Fput (Qundefined_color
, Qerror_conditions
,
8352 listn (CONSTYPE_PURE
, 2, Qundefined_color
, Qerror
));
8353 Fput (Qundefined_color
, Qerror_message
,
8354 build_pure_c_string ("Undefined color"));
8356 staticpro (&w32_grabbed_keys
);
8357 w32_grabbed_keys
= Qnil
;
8359 DEFVAR_LISP ("w32-color-map", Vw32_color_map
,
8360 doc
: /* An array of color name mappings for Windows. */);
8361 Vw32_color_map
= Qnil
;
8363 DEFVAR_LISP ("w32-pass-alt-to-system", Vw32_pass_alt_to_system
,
8364 doc
: /* Non-nil if Alt key presses are passed on to Windows.
8365 When non-nil, for example, Alt pressed and released and then space will
8366 open the System menu. When nil, Emacs processes the Alt key events, and
8367 then silently swallows them. */);
8368 Vw32_pass_alt_to_system
= Qnil
;
8370 DEFVAR_LISP ("w32-alt-is-meta", Vw32_alt_is_meta
,
8371 doc
: /* Non-nil if the Alt key is to be considered the same as the META key.
8372 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
8373 Vw32_alt_is_meta
= Qt
;
8375 DEFVAR_INT ("w32-quit-key", w32_quit_key
,
8376 doc
: /* If non-zero, the virtual key code for an alternative quit key. */);
8379 DEFVAR_LISP ("w32-pass-lwindow-to-system",
8380 Vw32_pass_lwindow_to_system
,
8381 doc
: /* If non-nil, the left \"Windows\" key is passed on to Windows.
8383 When non-nil, the Start menu is opened by tapping the key.
8384 If you set this to nil, the left \"Windows\" key is processed by Emacs
8385 according to the value of `w32-lwindow-modifier', which see.
8387 Note that some combinations of the left \"Windows\" key with other keys are
8388 caught by Windows at low level, and so binding them in Emacs will have no
8389 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
8390 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
8391 the doc string of `w32-phantom-key-code'. */);
8392 Vw32_pass_lwindow_to_system
= Qt
;
8394 DEFVAR_LISP ("w32-pass-rwindow-to-system",
8395 Vw32_pass_rwindow_to_system
,
8396 doc
: /* If non-nil, the right \"Windows\" key is passed on to Windows.
8398 When non-nil, the Start menu is opened by tapping the key.
8399 If you set this to nil, the right \"Windows\" key is processed by Emacs
8400 according to the value of `w32-rwindow-modifier', which see.
8402 Note that some combinations of the right \"Windows\" key with other keys are
8403 caught by Windows at low level, and so binding them in Emacs will have no
8404 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
8405 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
8406 the doc string of `w32-phantom-key-code'. */);
8407 Vw32_pass_rwindow_to_system
= Qt
;
8409 DEFVAR_LISP ("w32-phantom-key-code",
8410 Vw32_phantom_key_code
,
8411 doc
: /* Virtual key code used to generate \"phantom\" key presses.
8412 Value is a number between 0 and 255.
8414 Phantom key presses are generated in order to stop the system from
8415 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
8416 `w32-pass-rwindow-to-system' is nil. */);
8417 /* Although 255 is technically not a valid key code, it works and
8418 means that this hack won't interfere with any real key code. */
8419 XSETINT (Vw32_phantom_key_code
, 255);
8421 DEFVAR_LISP ("w32-enable-num-lock",
8422 Vw32_enable_num_lock
,
8423 doc
: /* If non-nil, the Num Lock key acts normally.
8424 Set to nil to handle Num Lock as the `kp-numlock' key. */);
8425 Vw32_enable_num_lock
= Qt
;
8427 DEFVAR_LISP ("w32-enable-caps-lock",
8428 Vw32_enable_caps_lock
,
8429 doc
: /* If non-nil, the Caps Lock key acts normally.
8430 Set to nil to handle Caps Lock as the `capslock' key. */);
8431 Vw32_enable_caps_lock
= Qt
;
8433 DEFVAR_LISP ("w32-scroll-lock-modifier",
8434 Vw32_scroll_lock_modifier
,
8435 doc
: /* Modifier to use for the Scroll Lock ON state.
8436 The value can be hyper, super, meta, alt, control or shift for the
8437 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
8438 Any other value will cause the Scroll Lock key to be ignored. */);
8439 Vw32_scroll_lock_modifier
= Qnil
;
8441 DEFVAR_LISP ("w32-lwindow-modifier",
8442 Vw32_lwindow_modifier
,
8443 doc
: /* Modifier to use for the left \"Windows\" key.
8444 The value can be hyper, super, meta, alt, control or shift for the
8445 respective modifier, or nil to appear as the `lwindow' key.
8446 Any other value will cause the key to be ignored. */);
8447 Vw32_lwindow_modifier
= Qnil
;
8449 DEFVAR_LISP ("w32-rwindow-modifier",
8450 Vw32_rwindow_modifier
,
8451 doc
: /* Modifier to use for the right \"Windows\" key.
8452 The value can be hyper, super, meta, alt, control or shift for the
8453 respective modifier, or nil to appear as the `rwindow' key.
8454 Any other value will cause the key to be ignored. */);
8455 Vw32_rwindow_modifier
= Qnil
;
8457 DEFVAR_LISP ("w32-apps-modifier",
8459 doc
: /* Modifier to use for the \"Apps\" key.
8460 The value can be hyper, super, meta, alt, control or shift for the
8461 respective modifier, or nil to appear as the `apps' key.
8462 Any other value will cause the key to be ignored. */);
8463 Vw32_apps_modifier
= Qnil
;
8465 DEFVAR_BOOL ("w32-enable-synthesized-fonts", w32_enable_synthesized_fonts
,
8466 doc
: /* Non-nil enables selection of artificially italicized and bold fonts. */);
8467 w32_enable_synthesized_fonts
= 0;
8469 DEFVAR_LISP ("w32-enable-palette", Vw32_enable_palette
,
8470 doc
: /* Non-nil enables Windows palette management to map colors exactly. */);
8471 Vw32_enable_palette
= Qt
;
8473 DEFVAR_INT ("w32-mouse-button-tolerance",
8474 w32_mouse_button_tolerance
,
8475 doc
: /* Analogue of double click interval for faking middle mouse events.
8476 The value is the minimum time in milliseconds that must elapse between
8477 left and right button down events before they are considered distinct events.
8478 If both mouse buttons are depressed within this interval, a middle mouse
8479 button down event is generated instead. */);
8480 w32_mouse_button_tolerance
= GetDoubleClickTime () / 2;
8482 DEFVAR_INT ("w32-mouse-move-interval",
8483 w32_mouse_move_interval
,
8484 doc
: /* Minimum interval between mouse move events.
8485 The value is the minimum time in milliseconds that must elapse between
8486 successive mouse move (or scroll bar drag) events before they are
8487 reported as lisp events. */);
8488 w32_mouse_move_interval
= 0;
8490 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
8491 w32_pass_extra_mouse_buttons_to_system
,
8492 doc
: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
8493 Recent versions of Windows support mice with up to five buttons.
8494 Since most applications don't support these extra buttons, most mouse
8495 drivers will allow you to map them to functions at the system level.
8496 If this variable is non-nil, Emacs will pass them on, allowing the
8497 system to handle them. */);
8498 w32_pass_extra_mouse_buttons_to_system
= 0;
8500 DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
8501 w32_pass_multimedia_buttons_to_system
,
8502 doc
: /* If non-nil, media buttons are passed to Windows.
8503 Some modern keyboards contain buttons for controlling media players, web
8504 browsers and other applications. Generally these buttons are handled on a
8505 system wide basis, but by setting this to nil they are made available
8506 to Emacs for binding. Depending on your keyboard, additional keys that
8507 may be available are:
8509 browser-back, browser-forward, browser-refresh, browser-stop,
8510 browser-search, browser-favorites, browser-home,
8511 mail, mail-reply, mail-forward, mail-send,
8513 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
8514 spell-check, correction-list, toggle-dictate-command,
8515 media-next, media-previous, media-stop, media-play-pause, media-select,
8516 media-play, media-pause, media-record, media-fast-forward, media-rewind,
8517 media-channel-up, media-channel-down,
8518 volume-mute, volume-up, volume-down,
8519 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
8520 bass-down, bass-boost, bass-up, treble-down, treble-up */);
8521 w32_pass_multimedia_buttons_to_system
= 1;
8523 #if 0 /* TODO: Mouse cursor customization. */
8524 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape
,
8525 doc
: /* The shape of the pointer when over text.
8526 Changing the value does not affect existing frames
8527 unless you set the mouse color. */);
8528 Vx_pointer_shape
= Qnil
;
8530 Vx_nontext_pointer_shape
= Qnil
;
8532 Vx_mode_pointer_shape
= Qnil
;
8534 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape
,
8535 doc
: /* The shape of the pointer when Emacs is busy.
8536 This variable takes effect when you create a new frame
8537 or when you set the mouse color. */);
8538 Vx_hourglass_pointer_shape
= Qnil
;
8540 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
8541 Vx_sensitive_text_pointer_shape
,
8542 doc
: /* The shape of the pointer when over mouse-sensitive text.
8543 This variable takes effect when you create a new frame
8544 or when you set the mouse color. */);
8545 Vx_sensitive_text_pointer_shape
= Qnil
;
8547 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
8548 Vx_window_horizontal_drag_shape
,
8549 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
8550 This variable takes effect when you create a new frame
8551 or when you set the mouse color. */);
8552 Vx_window_horizontal_drag_shape
= Qnil
;
8554 DEFVAR_LISP ("x-window-vertical-drag-cursor",
8555 Vx_window_vertical_drag_shape
,
8556 doc
: /* Pointer shape to use for indicating a window can be dragged vertically.
8557 This variable takes effect when you create a new frame
8558 or when you set the mouse color. */);
8559 Vx_window_vertical_drag_shape
= Qnil
;
8562 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel
,
8563 doc
: /* A string indicating the foreground color of the cursor box. */);
8564 Vx_cursor_fore_pixel
= Qnil
;
8566 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size
,
8567 doc
: /* Maximum size for tooltips.
8568 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
8569 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
8571 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager
,
8572 doc
: /* Non-nil if no window manager is in use.
8573 Emacs doesn't try to figure this out; this is always nil
8574 unless you set it to something else. */);
8575 /* We don't have any way to find this out, so set it to nil
8576 and maybe the user would like to set it to t. */
8577 Vx_no_window_manager
= Qnil
;
8579 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
8580 Vx_pixel_size_width_font_regexp
,
8581 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
8583 Since Emacs gets width of a font matching with this regexp from
8584 PIXEL_SIZE field of the name, font finding mechanism gets faster for
8585 such a font. This is especially effective for such large fonts as
8586 Chinese, Japanese, and Korean. */);
8587 Vx_pixel_size_width_font_regexp
= Qnil
;
8589 DEFVAR_LISP ("w32-bdf-filename-alist",
8590 Vw32_bdf_filename_alist
,
8591 doc
: /* List of bdf fonts and their corresponding filenames. */);
8592 Vw32_bdf_filename_alist
= Qnil
;
8594 DEFVAR_BOOL ("w32-strict-fontnames",
8595 w32_strict_fontnames
,
8596 doc
: /* Non-nil means only use fonts that are exact matches for those requested.
8597 Default is nil, which allows old fontnames that are not XLFD compliant,
8598 and allows third-party CJK display to work by specifying false charset
8599 fields to trick Emacs into translating to Big5, SJIS etc.
8600 Setting this to t will prevent wrong fonts being selected when
8601 fontsets are automatically created. */);
8602 w32_strict_fontnames
= 0;
8604 DEFVAR_BOOL ("w32-strict-painting",
8605 w32_strict_painting
,
8606 doc
: /* Non-nil means use strict rules for repainting frames.
8607 Set this to nil to get the old behavior for repainting; this should
8608 only be necessary if the default setting causes problems. */);
8609 w32_strict_painting
= 1;
8611 #if 0 /* TODO: Port to W32 */
8612 defsubr (&Sx_change_window_property
);
8613 defsubr (&Sx_delete_window_property
);
8614 defsubr (&Sx_window_property
);
8616 defsubr (&Sxw_display_color_p
);
8617 defsubr (&Sx_display_grayscale_p
);
8618 defsubr (&Sxw_color_defined_p
);
8619 defsubr (&Sxw_color_values
);
8620 defsubr (&Sx_server_max_request_size
);
8621 defsubr (&Sx_server_vendor
);
8622 defsubr (&Sx_server_version
);
8623 defsubr (&Sx_display_pixel_width
);
8624 defsubr (&Sx_display_pixel_height
);
8625 defsubr (&Sx_display_mm_width
);
8626 defsubr (&Sx_display_mm_height
);
8627 defsubr (&Sx_display_screens
);
8628 defsubr (&Sx_display_planes
);
8629 defsubr (&Sx_display_color_cells
);
8630 defsubr (&Sx_display_visual_class
);
8631 defsubr (&Sx_display_backing_store
);
8632 defsubr (&Sx_display_save_under
);
8633 defsubr (&Sx_create_frame
);
8634 defsubr (&Sx_open_connection
);
8635 defsubr (&Sx_close_connection
);
8636 defsubr (&Sx_display_list
);
8637 defsubr (&Sx_frame_geometry
);
8638 defsubr (&Sx_synchronize
);
8640 /* W32 specific functions */
8642 defsubr (&Sw32_define_rgb_color
);
8643 defsubr (&Sw32_default_color_map
);
8644 defsubr (&Sw32_display_monitor_attributes_list
);
8645 defsubr (&Sw32_send_sys_command
);
8646 defsubr (&Sw32_shell_execute
);
8647 defsubr (&Sw32_register_hot_key
);
8648 defsubr (&Sw32_unregister_hot_key
);
8649 defsubr (&Sw32_registered_hot_keys
);
8650 defsubr (&Sw32_reconstruct_hot_key
);
8651 defsubr (&Sw32_toggle_lock_key
);
8652 defsubr (&Sw32_window_exists_p
);
8653 defsubr (&Sw32_frame_rect
);
8654 defsubr (&Sw32_frame_menu_bar_size
);
8655 defsubr (&Sw32_battery_status
);
8656 defsubr (&Sw32__menu_bar_in_use
);
8659 defsubr (&Sfile_system_info
);
8660 defsubr (&Sdefault_printer_name
);
8663 defsubr (&Sset_message_beep
);
8664 defsubr (&Sx_show_tip
);
8665 defsubr (&Sx_hide_tip
);
8667 staticpro (&tip_timer
);
8669 staticpro (&tip_frame
);
8671 last_show_tip_args
= Qnil
;
8672 staticpro (&last_show_tip_args
);
8674 defsubr (&Sx_file_dialog
);
8676 defsubr (&Ssystem_move_file_to_trash
);
8682 /* Crashing and reporting backtrace. */
8685 static LONG CALLBACK
my_exception_handler (EXCEPTION_POINTERS
*);
8686 static LPTOP_LEVEL_EXCEPTION_FILTER prev_exception_handler
;
8688 static DWORD except_code
;
8689 static PVOID except_addr
;
8692 /* This handler records the exception code and the address where it
8693 was triggered so that this info could be included in the backtrace.
8694 Without that, the backtrace in some cases has no information
8695 whatsoever about the offending code, and looks as if the top-level
8696 exception handler in the MinGW startup code di the one that
8698 static LONG CALLBACK
8699 my_exception_handler (EXCEPTION_POINTERS
* exception_data
)
8701 except_code
= exception_data
->ExceptionRecord
->ExceptionCode
;
8702 except_addr
= exception_data
->ExceptionRecord
->ExceptionAddress
;
8704 if (prev_exception_handler
)
8705 return prev_exception_handler (exception_data
);
8706 return EXCEPTION_EXECUTE_HANDLER
;
8710 typedef USHORT (WINAPI
* CaptureStackBackTrace_proc
) (ULONG
, ULONG
, PVOID
*,
8713 #define BACKTRACE_LIMIT_MAX 62
8716 w32_backtrace (void **buffer
, int limit
)
8718 static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace
= NULL
;
8719 HMODULE hm_kernel32
= NULL
;
8721 if (!s_pfn_CaptureStackBackTrace
)
8723 hm_kernel32
= LoadLibrary ("Kernel32.dll");
8724 s_pfn_CaptureStackBackTrace
=
8725 (CaptureStackBackTrace_proc
) GetProcAddress (hm_kernel32
,
8726 "RtlCaptureStackBackTrace");
8728 if (s_pfn_CaptureStackBackTrace
)
8729 return s_pfn_CaptureStackBackTrace (0, min (BACKTRACE_LIMIT_MAX
, limit
),
8738 button
= MessageBox (NULL
,
8739 "A fatal error has occurred!\n\n"
8740 "Would you like to attach a debugger?\n\n"
8742 "YES -- to debug Emacs, or\n"
8743 "NO -- to abort Emacs and produce a backtrace\n"
8744 " (emacs_backtrace.txt in current directory)."
8746 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
8747 "\"continue\" inside GDB before clicking YES.)"
8749 , "Emacs Abort Dialog",
8750 MB_ICONEXCLAMATION
| MB_TASKMODAL
8751 | MB_SETFOREGROUND
| MB_YESNO
);
8756 exit (2); /* tell the compiler we will never return */
8760 void *stack
[BACKTRACE_LIMIT_MAX
+ 1];
8761 int i
= w32_backtrace (stack
, BACKTRACE_LIMIT_MAX
+ 1);
8765 int errfile_fd
= -1;
8767 char buf
[sizeof ("\r\nException at this address:\r\n\r\n")
8768 /* The type below should really be 'void *', but
8769 INT_BUFSIZE_BOUND cannot handle that without
8770 triggering compiler warnings (under certain
8771 pedantic warning switches), it wants an
8773 + 2 * INT_BUFSIZE_BOUND (intptr_t)];
8777 HANDLE errout
= GetStdHandle (STD_ERROR_HANDLE
);
8780 if (errout
&& errout
!= INVALID_HANDLE_VALUE
)
8781 stderr_fd
= _open_osfhandle ((intptr_t)errout
, O_APPEND
| O_BINARY
);
8784 /* We use %p, not 0x%p, as %p produces a leading "0x" on XP,
8785 but not on Windows 7. addr2line doesn't mind a missing
8786 "0x", but will be confused by an extra one. */
8788 sprintf (buf
, "\r\nException 0x%lx at this address:\r\n%p\r\n",
8789 except_code
, except_addr
);
8793 write (stderr_fd
, buf
, strlen (buf
));
8794 write (stderr_fd
, "\r\nBacktrace:\r\n", 14);
8799 errfile_fd
= _open ("emacs_backtrace.txt", O_RDWR
| O_CREAT
| O_BINARY
, S_IREAD
| S_IWRITE
);
8800 if (errfile_fd
>= 0)
8802 lseek (errfile_fd
, 0L, SEEK_END
);
8804 write (errfile_fd
, buf
, strlen (buf
));
8805 write (errfile_fd
, "\r\nBacktrace:\r\n", 14);
8808 for (j
= 0; j
< i
; j
++)
8810 /* stack[] gives the return addresses, whereas we want
8811 the address of the call, so decrease each address
8812 by approximate size of 1 CALL instruction. */
8813 sprintf (buf
, "%p\r\n", (char *)stack
[j
] - sizeof(void *));
8815 write (stderr_fd
, buf
, strlen (buf
));
8816 if (errfile_fd
>= 0)
8817 write (errfile_fd
, buf
, strlen (buf
));
8819 if (i
== BACKTRACE_LIMIT_MAX
)
8822 write (stderr_fd
, "...\r\n", 5);
8823 if (errfile_fd
>= 0)
8824 write (errfile_fd
, "...\r\n", 5);
8826 if (errfile_fd
>= 0)
8837 /* Initialization. */
8840 globals_of_w32fns is used to initialize those global variables that
8841 must always be initialized on startup even when the global variable
8842 initialized is non zero (see the function main in emacs.c).
8843 globals_of_w32fns is called from syms_of_w32fns when the global
8844 variable initialized is 0 and directly from main when initialized
8848 globals_of_w32fns (void)
8850 HMODULE user32_lib
= GetModuleHandle ("user32.dll");
8852 TrackMouseEvent not available in all versions of Windows, so must load
8853 it dynamically. Do it once, here, instead of every time it is used.
8855 track_mouse_event_fn
= (TrackMouseEvent_Proc
)
8856 GetProcAddress (user32_lib
, "TrackMouseEvent");
8858 monitor_from_point_fn
= (MonitorFromPoint_Proc
)
8859 GetProcAddress (user32_lib
, "MonitorFromPoint");
8860 get_monitor_info_fn
= (GetMonitorInfo_Proc
)
8861 GetProcAddress (user32_lib
, "GetMonitorInfoA");
8862 monitor_from_window_fn
= (MonitorFromWindow_Proc
)
8863 GetProcAddress (user32_lib
, "MonitorFromWindow");
8864 enum_display_monitors_fn
= (EnumDisplayMonitors_Proc
)
8865 GetProcAddress (user32_lib
, "EnumDisplayMonitors");
8868 HMODULE imm32_lib
= GetModuleHandle ("imm32.dll");
8869 get_composition_string_fn
= (ImmGetCompositionString_Proc
)
8870 GetProcAddress (imm32_lib
, "ImmGetCompositionStringW");
8871 get_ime_context_fn
= (ImmGetContext_Proc
)
8872 GetProcAddress (imm32_lib
, "ImmGetContext");
8873 release_ime_context_fn
= (ImmReleaseContext_Proc
)
8874 GetProcAddress (imm32_lib
, "ImmReleaseContext");
8875 set_ime_composition_window_fn
= (ImmSetCompositionWindow_Proc
)
8876 GetProcAddress (imm32_lib
, "ImmSetCompositionWindow");
8882 prev_exception_handler
= SetUnhandledExceptionFilter (my_exception_handler
);
8885 DEFVAR_INT ("w32-ansi-code-page",
8887 doc
: /* The ANSI code page used by the system. */);
8888 w32_ansi_code_page
= GetACP ();
8890 if (os_subtype
== OS_NT
)
8891 w32_unicode_gui
= 1;
8893 w32_unicode_gui
= 0;
8895 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
8896 InitCommonControls ();
8898 syms_of_w32uniscribe ();
8901 #ifdef NTGUI_UNICODE
8904 ntgui_encode_system (Lisp_Object str
)
8906 Lisp_Object encoded
;
8907 to_unicode (str
, &encoded
);
8911 #endif /* NTGUI_UNICODE */