1 /* Graphical user interface functions for the Microsoft W32 API.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 /* Added by Kevin Gallo */
37 #include "intervals.h"
38 #include "dispextern.h"
40 #include "blockinput.h"
42 #include "character.h"
48 #include "termhooks.h"
52 #include "bitmaps/gray.xbm"
63 #define FILE_NAME_TEXT_FIELD edt1
68 #ifndef FOF_NO_CONNECTED_ELEMENTS
69 #define FOF_NO_CONNECTED_ELEMENTS 0x2000
72 void syms_of_w32fns (void);
73 void globals_of_w32fns (void);
75 extern void free_frame_menubar (struct frame
*);
76 extern double atof (const char *);
77 extern int w32_console_toggle_lock_key (int, Lisp_Object
);
78 extern void w32_menu_display_help (HWND
, HMENU
, UINT
, UINT
);
79 extern void w32_free_menu_strings (HWND
);
80 extern const char *map_w32_filename (const char *, const char **);
84 extern char *lispy_function_keys
[];
86 /* The colormap for converting color names to RGB values */
87 Lisp_Object Vw32_color_map
;
89 /* Non nil if alt key presses are passed on to Windows. */
90 Lisp_Object Vw32_pass_alt_to_system
;
92 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
94 Lisp_Object Vw32_alt_is_meta
;
96 /* If non-zero, the windows virtual key code for an alternative quit key. */
99 /* Non nil if left window key events are passed on to Windows (this only
100 affects whether "tapping" the key opens the Start menu). */
101 Lisp_Object Vw32_pass_lwindow_to_system
;
103 /* Non nil if right window key events are passed on to Windows (this
104 only affects whether "tapping" the key opens the Start menu). */
105 Lisp_Object Vw32_pass_rwindow_to_system
;
107 /* Virtual key code used to generate "phantom" key presses in order
108 to stop system from acting on Windows key events. */
109 Lisp_Object Vw32_phantom_key_code
;
111 /* Modifier associated with the left "Windows" key, or nil to act as a
113 Lisp_Object Vw32_lwindow_modifier
;
115 /* Modifier associated with the right "Windows" key, or nil to act as a
117 Lisp_Object Vw32_rwindow_modifier
;
119 /* Modifier associated with the "Apps" key, or nil to act as a normal
121 Lisp_Object Vw32_apps_modifier
;
123 /* Value is nil if Num Lock acts as a function key. */
124 Lisp_Object Vw32_enable_num_lock
;
126 /* Value is nil if Caps Lock acts as a function key. */
127 Lisp_Object Vw32_enable_caps_lock
;
129 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
130 Lisp_Object Vw32_scroll_lock_modifier
;
132 /* Switch to control whether we inhibit requests for synthesized bold
133 and italic versions of fonts. */
134 int w32_enable_synthesized_fonts
;
136 /* Enable palette management. */
137 Lisp_Object Vw32_enable_palette
;
139 /* Control how close left/right button down events must be to
140 be converted to a middle button down event. */
141 int w32_mouse_button_tolerance
;
143 /* Minimum interval between mouse movement (and scroll bar drag)
144 events that are passed on to the event loop. */
145 int w32_mouse_move_interval
;
147 /* Flag to indicate if XBUTTON events should be passed on to Windows. */
148 static int w32_pass_extra_mouse_buttons_to_system
;
150 /* Flag to indicate if media keys should be passed on to Windows. */
151 static int w32_pass_multimedia_buttons_to_system
;
153 /* Non nil if no window manager is in use. */
154 Lisp_Object Vx_no_window_manager
;
156 /* If non-zero, a w32 timer that, when it expires, displays an
157 hourglass cursor on all frames. */
158 static unsigned hourglass_timer
= 0;
159 static HWND hourglass_hwnd
= NULL
;
161 #if 0 /* TODO: Mouse cursor customization. */
162 /* The background and shape of the mouse pointer, and shape when not
163 over text or in the modeline. */
164 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
165 Lisp_Object Vx_hourglass_pointer_shape
, Vx_window_horizontal_drag_shape
;
167 /* The shape when over mouse-sensitive text. */
169 Lisp_Object Vx_sensitive_text_pointer_shape
;
173 #define IDC_HAND MAKEINTRESOURCE(32649)
176 /* Color of chars displayed in cursor box. */
177 Lisp_Object Vx_cursor_fore_pixel
;
179 /* Nonzero if using Windows. */
181 static int w32_in_use
;
183 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
185 Lisp_Object Vx_pixel_size_width_font_regexp
;
187 /* Alist of bdf fonts and the files that define them. */
188 Lisp_Object Vw32_bdf_filename_alist
;
190 /* A flag to control whether fonts are matched strictly or not. */
191 static int w32_strict_fontnames
;
193 /* A flag to control whether we should only repaint if GetUpdateRect
194 indicates there is an update region. */
195 static int w32_strict_painting
;
198 Lisp_Object Qsuppress_icon
;
199 Lisp_Object Qundefined_color
;
200 Lisp_Object Qcancel_timer
;
201 Lisp_Object Qfont_param
;
207 Lisp_Object Qcontrol
;
211 /* The ANSI codepage. */
212 int w32_ansi_code_page
;
214 /* Prefix for system colors. */
215 #define SYSTEM_COLOR_PREFIX "System"
216 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
218 /* State variables for emulating a three button mouse. */
223 static int button_state
= 0;
224 static W32Msg saved_mouse_button_msg
;
225 static unsigned mouse_button_timer
= 0; /* non-zero when timer is active */
226 static W32Msg saved_mouse_move_msg
;
227 static unsigned mouse_move_timer
= 0;
229 /* Window that is tracking the mouse. */
230 static HWND track_mouse_window
;
232 /* Multi-monitor API definitions that are not pulled from the headers
233 since we are compiling for NT 4. */
234 #ifndef MONITOR_DEFAULT_TO_NEAREST
235 #define MONITOR_DEFAULT_TO_NEAREST 2
237 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
238 To avoid a compile error on one or the other, redefine with a new name. */
247 /* Reportedly, VS 6 does not have this in its headers. */
248 #if defined(_MSC_VER) && _MSC_VER < 1300
249 DECLARE_HANDLE(HMONITOR
);
252 typedef BOOL (WINAPI
* TrackMouseEvent_Proc
)
253 (IN OUT LPTRACKMOUSEEVENT lpEventTrack
);
254 typedef LONG (WINAPI
* ImmGetCompositionString_Proc
)
255 (IN HIMC context
, IN DWORD index
, OUT LPVOID buffer
, IN DWORD bufLen
);
256 typedef HIMC (WINAPI
* ImmGetContext_Proc
) (IN HWND window
);
257 typedef HWND (WINAPI
* ImmReleaseContext_Proc
) (IN HWND wnd
, IN HIMC context
);
258 typedef HWND (WINAPI
* ImmSetCompositionWindow_Proc
) (IN HIMC context
,
259 IN COMPOSITIONFORM
*form
);
260 typedef HMONITOR (WINAPI
* MonitorFromPoint_Proc
) (IN POINT pt
, IN DWORD flags
);
261 typedef BOOL (WINAPI
* GetMonitorInfo_Proc
)
262 (IN HMONITOR monitor
, OUT
struct MONITOR_INFO
* info
);
264 TrackMouseEvent_Proc track_mouse_event_fn
= NULL
;
265 ClipboardSequence_Proc clipboard_sequence_fn
= NULL
;
266 ImmGetCompositionString_Proc get_composition_string_fn
= NULL
;
267 ImmGetContext_Proc get_ime_context_fn
= NULL
;
268 ImmReleaseContext_Proc release_ime_context_fn
= NULL
;
269 ImmSetCompositionWindow_Proc set_ime_composition_window_fn
= NULL
;
270 MonitorFromPoint_Proc monitor_from_point_fn
= NULL
;
271 GetMonitorInfo_Proc get_monitor_info_fn
= NULL
;
273 extern AppendMenuW_Proc unicode_append_menu
;
275 /* Flag to selectively ignore WM_IME_CHAR messages. */
276 static int ignore_ime_char
= 0;
278 /* W95 mousewheel handler */
279 unsigned int msh_mousewheel
= 0;
282 #define MOUSE_BUTTON_ID 1
283 #define MOUSE_MOVE_ID 2
284 #define MENU_FREE_ID 3
285 #define HOURGLASS_ID 4
286 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
288 #define MENU_FREE_DELAY 1000
289 static unsigned menu_free_timer
= 0;
291 /* The below are defined in frame.c. */
293 extern Lisp_Object Vmenu_bar_mode
, Vtool_bar_mode
;
294 extern Lisp_Object Vwindow_system_version
;
297 int image_cache_refcount
, dpyinfo_refcount
;
301 /* From w32term.c. */
302 extern int w32_num_mouse_buttons
;
303 extern Lisp_Object Vw32_recognize_altgr
;
305 extern HWND w32_system_caret_hwnd
;
307 extern int w32_system_caret_height
;
308 extern int w32_system_caret_x
;
309 extern int w32_system_caret_y
;
310 extern int w32_use_visible_system_caret
;
312 static HWND w32_visible_system_caret_hwnd
;
315 extern HMENU current_popup_menu
;
316 static int menubar_in_use
= 0;
318 /* From w32uniscribe.c */
319 extern void syms_of_w32uniscribe (void);
320 extern int uniscribe_available
;
322 /* Function prototypes for hourglass support. */
323 static void w32_show_hourglass (struct frame
*);
324 static void w32_hide_hourglass (void);
328 /* Error if we are not connected to MS-Windows. */
333 error ("MS-Windows not in use or not initialized");
336 /* Nonzero if we can use mouse menus.
337 You should not call this unless HAVE_MENUS is defined. */
345 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
346 and checking validity for W32. */
349 check_x_frame (Lisp_Object frame
)
354 frame
= selected_frame
;
355 CHECK_LIVE_FRAME (frame
);
357 if (! FRAME_W32_P (f
))
358 error ("Non-W32 frame used");
362 /* Let the user specify a display with a frame.
363 nil stands for the selected frame--or, if that is not a w32 frame,
364 the first display on the list. */
366 struct w32_display_info
*
367 check_x_display_info (Lisp_Object frame
)
371 struct frame
*sf
= XFRAME (selected_frame
);
373 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
374 return FRAME_W32_DISPLAY_INFO (sf
);
376 return &one_w32_display_info
;
378 else if (STRINGP (frame
))
379 return x_display_info_for_name (frame
);
384 CHECK_LIVE_FRAME (frame
);
386 if (! FRAME_W32_P (f
))
387 error ("Non-W32 frame used");
388 return FRAME_W32_DISPLAY_INFO (f
);
392 /* Return the Emacs frame-object corresponding to an w32 window.
393 It could be the frame's main window or an icon window. */
395 /* This function can be called during GC, so use GC_xxx type test macros. */
398 x_window_to_frame (struct w32_display_info
*dpyinfo
, HWND wdesc
)
400 Lisp_Object tail
, frame
;
403 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
409 if (!FRAME_W32_P (f
) || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
412 if (FRAME_W32_WINDOW (f
) == wdesc
)
419 static Lisp_Object
unwind_create_frame (Lisp_Object
);
420 static Lisp_Object
unwind_create_tip_frame (Lisp_Object
);
421 static void my_create_window (struct frame
*);
422 static void my_create_tip_window (struct frame
*);
424 /* TODO: Native Input Method support; see x_create_im. */
425 void x_set_foreground_color (struct frame
*, Lisp_Object
, Lisp_Object
);
426 void x_set_background_color (struct frame
*, Lisp_Object
, Lisp_Object
);
427 void x_set_mouse_color (struct frame
*, Lisp_Object
, Lisp_Object
);
428 void x_set_cursor_color (struct frame
*, Lisp_Object
, Lisp_Object
);
429 void x_set_border_color (struct frame
*, Lisp_Object
, Lisp_Object
);
430 void x_set_cursor_type (struct frame
*, Lisp_Object
, Lisp_Object
);
431 void x_set_icon_type (struct frame
*, Lisp_Object
, Lisp_Object
);
432 void x_set_icon_name (struct frame
*, Lisp_Object
, Lisp_Object
);
433 void x_explicitly_set_name (struct frame
*, Lisp_Object
, Lisp_Object
);
434 void x_set_menu_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
435 void x_set_title (struct frame
*, Lisp_Object
, Lisp_Object
);
436 void x_set_tool_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
437 static void x_edge_detection (struct frame
*, struct image
*, Lisp_Object
,
443 /* Store the screen positions of frame F into XPTR and YPTR.
444 These are the positions of the containing window manager window,
445 not Emacs's own window. */
448 x_real_positions (FRAME_PTR f
, int *xptr
, int *yptr
)
453 /* Get the bounds of the WM window. */
454 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
459 /* Convert (0, 0) in the client area to screen co-ordinates. */
460 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
462 /* Remember x_pixels_diff and y_pixels_diff. */
463 f
->x_pixels_diff
= pt
.x
- rect
.left
;
464 f
->y_pixels_diff
= pt
.y
- rect
.top
;
472 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
,
473 Sw32_define_rgb_color
, 4, 4, 0,
474 doc
: /* Convert RGB numbers to a Windows color reference and associate with NAME.
475 This adds or updates a named color to `w32-color-map', making it
476 available for use. The original entry's RGB ref is returned, or nil
477 if the entry is new. */)
478 (Lisp_Object red
, Lisp_Object green
, Lisp_Object blue
, Lisp_Object name
)
481 Lisp_Object oldrgb
= Qnil
;
485 CHECK_NUMBER (green
);
489 XSETINT (rgb
, RGB (XUINT (red
), XUINT (green
), XUINT (blue
)));
493 /* replace existing entry in w32-color-map or add new entry. */
494 entry
= Fassoc (name
, Vw32_color_map
);
497 entry
= Fcons (name
, rgb
);
498 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
502 oldrgb
= Fcdr (entry
);
503 Fsetcdr (entry
, rgb
);
511 /* The default colors for the w32 color map */
512 typedef struct colormap_t
518 colormap_t w32_color_map
[] =
520 {"snow" , PALETTERGB (255,250,250)},
521 {"ghost white" , PALETTERGB (248,248,255)},
522 {"GhostWhite" , PALETTERGB (248,248,255)},
523 {"white smoke" , PALETTERGB (245,245,245)},
524 {"WhiteSmoke" , PALETTERGB (245,245,245)},
525 {"gainsboro" , PALETTERGB (220,220,220)},
526 {"floral white" , PALETTERGB (255,250,240)},
527 {"FloralWhite" , PALETTERGB (255,250,240)},
528 {"old lace" , PALETTERGB (253,245,230)},
529 {"OldLace" , PALETTERGB (253,245,230)},
530 {"linen" , PALETTERGB (250,240,230)},
531 {"antique white" , PALETTERGB (250,235,215)},
532 {"AntiqueWhite" , PALETTERGB (250,235,215)},
533 {"papaya whip" , PALETTERGB (255,239,213)},
534 {"PapayaWhip" , PALETTERGB (255,239,213)},
535 {"blanched almond" , PALETTERGB (255,235,205)},
536 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
537 {"bisque" , PALETTERGB (255,228,196)},
538 {"peach puff" , PALETTERGB (255,218,185)},
539 {"PeachPuff" , PALETTERGB (255,218,185)},
540 {"navajo white" , PALETTERGB (255,222,173)},
541 {"NavajoWhite" , PALETTERGB (255,222,173)},
542 {"moccasin" , PALETTERGB (255,228,181)},
543 {"cornsilk" , PALETTERGB (255,248,220)},
544 {"ivory" , PALETTERGB (255,255,240)},
545 {"lemon chiffon" , PALETTERGB (255,250,205)},
546 {"LemonChiffon" , PALETTERGB (255,250,205)},
547 {"seashell" , PALETTERGB (255,245,238)},
548 {"honeydew" , PALETTERGB (240,255,240)},
549 {"mint cream" , PALETTERGB (245,255,250)},
550 {"MintCream" , PALETTERGB (245,255,250)},
551 {"azure" , PALETTERGB (240,255,255)},
552 {"alice blue" , PALETTERGB (240,248,255)},
553 {"AliceBlue" , PALETTERGB (240,248,255)},
554 {"lavender" , PALETTERGB (230,230,250)},
555 {"lavender blush" , PALETTERGB (255,240,245)},
556 {"LavenderBlush" , PALETTERGB (255,240,245)},
557 {"misty rose" , PALETTERGB (255,228,225)},
558 {"MistyRose" , PALETTERGB (255,228,225)},
559 {"white" , PALETTERGB (255,255,255)},
560 {"black" , PALETTERGB ( 0, 0, 0)},
561 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
562 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
563 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
564 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
565 {"dim gray" , PALETTERGB (105,105,105)},
566 {"DimGray" , PALETTERGB (105,105,105)},
567 {"dim grey" , PALETTERGB (105,105,105)},
568 {"DimGrey" , PALETTERGB (105,105,105)},
569 {"slate gray" , PALETTERGB (112,128,144)},
570 {"SlateGray" , PALETTERGB (112,128,144)},
571 {"slate grey" , PALETTERGB (112,128,144)},
572 {"SlateGrey" , PALETTERGB (112,128,144)},
573 {"light slate gray" , PALETTERGB (119,136,153)},
574 {"LightSlateGray" , PALETTERGB (119,136,153)},
575 {"light slate grey" , PALETTERGB (119,136,153)},
576 {"LightSlateGrey" , PALETTERGB (119,136,153)},
577 {"gray" , PALETTERGB (190,190,190)},
578 {"grey" , PALETTERGB (190,190,190)},
579 {"light grey" , PALETTERGB (211,211,211)},
580 {"LightGrey" , PALETTERGB (211,211,211)},
581 {"light gray" , PALETTERGB (211,211,211)},
582 {"LightGray" , PALETTERGB (211,211,211)},
583 {"midnight blue" , PALETTERGB ( 25, 25,112)},
584 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
585 {"navy" , PALETTERGB ( 0, 0,128)},
586 {"navy blue" , PALETTERGB ( 0, 0,128)},
587 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
588 {"cornflower blue" , PALETTERGB (100,149,237)},
589 {"CornflowerBlue" , PALETTERGB (100,149,237)},
590 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
591 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
592 {"slate blue" , PALETTERGB (106, 90,205)},
593 {"SlateBlue" , PALETTERGB (106, 90,205)},
594 {"medium slate blue" , PALETTERGB (123,104,238)},
595 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
596 {"light slate blue" , PALETTERGB (132,112,255)},
597 {"LightSlateBlue" , PALETTERGB (132,112,255)},
598 {"medium blue" , PALETTERGB ( 0, 0,205)},
599 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
600 {"royal blue" , PALETTERGB ( 65,105,225)},
601 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
602 {"blue" , PALETTERGB ( 0, 0,255)},
603 {"dodger blue" , PALETTERGB ( 30,144,255)},
604 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
605 {"deep sky blue" , PALETTERGB ( 0,191,255)},
606 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
607 {"sky blue" , PALETTERGB (135,206,235)},
608 {"SkyBlue" , PALETTERGB (135,206,235)},
609 {"light sky blue" , PALETTERGB (135,206,250)},
610 {"LightSkyBlue" , PALETTERGB (135,206,250)},
611 {"steel blue" , PALETTERGB ( 70,130,180)},
612 {"SteelBlue" , PALETTERGB ( 70,130,180)},
613 {"light steel blue" , PALETTERGB (176,196,222)},
614 {"LightSteelBlue" , PALETTERGB (176,196,222)},
615 {"light blue" , PALETTERGB (173,216,230)},
616 {"LightBlue" , PALETTERGB (173,216,230)},
617 {"powder blue" , PALETTERGB (176,224,230)},
618 {"PowderBlue" , PALETTERGB (176,224,230)},
619 {"pale turquoise" , PALETTERGB (175,238,238)},
620 {"PaleTurquoise" , PALETTERGB (175,238,238)},
621 {"dark turquoise" , PALETTERGB ( 0,206,209)},
622 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
623 {"medium turquoise" , PALETTERGB ( 72,209,204)},
624 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
625 {"turquoise" , PALETTERGB ( 64,224,208)},
626 {"cyan" , PALETTERGB ( 0,255,255)},
627 {"light cyan" , PALETTERGB (224,255,255)},
628 {"LightCyan" , PALETTERGB (224,255,255)},
629 {"cadet blue" , PALETTERGB ( 95,158,160)},
630 {"CadetBlue" , PALETTERGB ( 95,158,160)},
631 {"medium aquamarine" , PALETTERGB (102,205,170)},
632 {"MediumAquamarine" , PALETTERGB (102,205,170)},
633 {"aquamarine" , PALETTERGB (127,255,212)},
634 {"dark green" , PALETTERGB ( 0,100, 0)},
635 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
636 {"dark olive green" , PALETTERGB ( 85,107, 47)},
637 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
638 {"dark sea green" , PALETTERGB (143,188,143)},
639 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
640 {"sea green" , PALETTERGB ( 46,139, 87)},
641 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
642 {"medium sea green" , PALETTERGB ( 60,179,113)},
643 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
644 {"light sea green" , PALETTERGB ( 32,178,170)},
645 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
646 {"pale green" , PALETTERGB (152,251,152)},
647 {"PaleGreen" , PALETTERGB (152,251,152)},
648 {"spring green" , PALETTERGB ( 0,255,127)},
649 {"SpringGreen" , PALETTERGB ( 0,255,127)},
650 {"lawn green" , PALETTERGB (124,252, 0)},
651 {"LawnGreen" , PALETTERGB (124,252, 0)},
652 {"green" , PALETTERGB ( 0,255, 0)},
653 {"chartreuse" , PALETTERGB (127,255, 0)},
654 {"medium spring green" , PALETTERGB ( 0,250,154)},
655 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
656 {"green yellow" , PALETTERGB (173,255, 47)},
657 {"GreenYellow" , PALETTERGB (173,255, 47)},
658 {"lime green" , PALETTERGB ( 50,205, 50)},
659 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
660 {"yellow green" , PALETTERGB (154,205, 50)},
661 {"YellowGreen" , PALETTERGB (154,205, 50)},
662 {"forest green" , PALETTERGB ( 34,139, 34)},
663 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
664 {"olive drab" , PALETTERGB (107,142, 35)},
665 {"OliveDrab" , PALETTERGB (107,142, 35)},
666 {"dark khaki" , PALETTERGB (189,183,107)},
667 {"DarkKhaki" , PALETTERGB (189,183,107)},
668 {"khaki" , PALETTERGB (240,230,140)},
669 {"pale goldenrod" , PALETTERGB (238,232,170)},
670 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
671 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
672 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
673 {"light yellow" , PALETTERGB (255,255,224)},
674 {"LightYellow" , PALETTERGB (255,255,224)},
675 {"yellow" , PALETTERGB (255,255, 0)},
676 {"gold" , PALETTERGB (255,215, 0)},
677 {"light goldenrod" , PALETTERGB (238,221,130)},
678 {"LightGoldenrod" , PALETTERGB (238,221,130)},
679 {"goldenrod" , PALETTERGB (218,165, 32)},
680 {"dark goldenrod" , PALETTERGB (184,134, 11)},
681 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
682 {"rosy brown" , PALETTERGB (188,143,143)},
683 {"RosyBrown" , PALETTERGB (188,143,143)},
684 {"indian red" , PALETTERGB (205, 92, 92)},
685 {"IndianRed" , PALETTERGB (205, 92, 92)},
686 {"saddle brown" , PALETTERGB (139, 69, 19)},
687 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
688 {"sienna" , PALETTERGB (160, 82, 45)},
689 {"peru" , PALETTERGB (205,133, 63)},
690 {"burlywood" , PALETTERGB (222,184,135)},
691 {"beige" , PALETTERGB (245,245,220)},
692 {"wheat" , PALETTERGB (245,222,179)},
693 {"sandy brown" , PALETTERGB (244,164, 96)},
694 {"SandyBrown" , PALETTERGB (244,164, 96)},
695 {"tan" , PALETTERGB (210,180,140)},
696 {"chocolate" , PALETTERGB (210,105, 30)},
697 {"firebrick" , PALETTERGB (178,34, 34)},
698 {"brown" , PALETTERGB (165,42, 42)},
699 {"dark salmon" , PALETTERGB (233,150,122)},
700 {"DarkSalmon" , PALETTERGB (233,150,122)},
701 {"salmon" , PALETTERGB (250,128,114)},
702 {"light salmon" , PALETTERGB (255,160,122)},
703 {"LightSalmon" , PALETTERGB (255,160,122)},
704 {"orange" , PALETTERGB (255,165, 0)},
705 {"dark orange" , PALETTERGB (255,140, 0)},
706 {"DarkOrange" , PALETTERGB (255,140, 0)},
707 {"coral" , PALETTERGB (255,127, 80)},
708 {"light coral" , PALETTERGB (240,128,128)},
709 {"LightCoral" , PALETTERGB (240,128,128)},
710 {"tomato" , PALETTERGB (255, 99, 71)},
711 {"orange red" , PALETTERGB (255, 69, 0)},
712 {"OrangeRed" , PALETTERGB (255, 69, 0)},
713 {"red" , PALETTERGB (255, 0, 0)},
714 {"hot pink" , PALETTERGB (255,105,180)},
715 {"HotPink" , PALETTERGB (255,105,180)},
716 {"deep pink" , PALETTERGB (255, 20,147)},
717 {"DeepPink" , PALETTERGB (255, 20,147)},
718 {"pink" , PALETTERGB (255,192,203)},
719 {"light pink" , PALETTERGB (255,182,193)},
720 {"LightPink" , PALETTERGB (255,182,193)},
721 {"pale violet red" , PALETTERGB (219,112,147)},
722 {"PaleVioletRed" , PALETTERGB (219,112,147)},
723 {"maroon" , PALETTERGB (176, 48, 96)},
724 {"medium violet red" , PALETTERGB (199, 21,133)},
725 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
726 {"violet red" , PALETTERGB (208, 32,144)},
727 {"VioletRed" , PALETTERGB (208, 32,144)},
728 {"magenta" , PALETTERGB (255, 0,255)},
729 {"violet" , PALETTERGB (238,130,238)},
730 {"plum" , PALETTERGB (221,160,221)},
731 {"orchid" , PALETTERGB (218,112,214)},
732 {"medium orchid" , PALETTERGB (186, 85,211)},
733 {"MediumOrchid" , PALETTERGB (186, 85,211)},
734 {"dark orchid" , PALETTERGB (153, 50,204)},
735 {"DarkOrchid" , PALETTERGB (153, 50,204)},
736 {"dark violet" , PALETTERGB (148, 0,211)},
737 {"DarkViolet" , PALETTERGB (148, 0,211)},
738 {"blue violet" , PALETTERGB (138, 43,226)},
739 {"BlueViolet" , PALETTERGB (138, 43,226)},
740 {"purple" , PALETTERGB (160, 32,240)},
741 {"medium purple" , PALETTERGB (147,112,219)},
742 {"MediumPurple" , PALETTERGB (147,112,219)},
743 {"thistle" , PALETTERGB (216,191,216)},
744 {"gray0" , PALETTERGB ( 0, 0, 0)},
745 {"grey0" , PALETTERGB ( 0, 0, 0)},
746 {"dark grey" , PALETTERGB (169,169,169)},
747 {"DarkGrey" , PALETTERGB (169,169,169)},
748 {"dark gray" , PALETTERGB (169,169,169)},
749 {"DarkGray" , PALETTERGB (169,169,169)},
750 {"dark blue" , PALETTERGB ( 0, 0,139)},
751 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
752 {"dark cyan" , PALETTERGB ( 0,139,139)},
753 {"DarkCyan" , PALETTERGB ( 0,139,139)},
754 {"dark magenta" , PALETTERGB (139, 0,139)},
755 {"DarkMagenta" , PALETTERGB (139, 0,139)},
756 {"dark red" , PALETTERGB (139, 0, 0)},
757 {"DarkRed" , PALETTERGB (139, 0, 0)},
758 {"light green" , PALETTERGB (144,238,144)},
759 {"LightGreen" , PALETTERGB (144,238,144)},
762 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
763 0, 0, 0, doc
: /* Return the default color map. */)
767 colormap_t
*pc
= w32_color_map
;
774 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
776 cmap
= Fcons (Fcons (build_string (pc
->name
),
777 make_number (pc
->colorref
)),
786 w32_to_x_color (Lisp_Object rgb
)
794 color
= Frassq (rgb
, Vw32_color_map
);
799 return (Fcar (color
));
805 w32_color_map_lookup (char *colorname
)
807 Lisp_Object tail
, ret
= Qnil
;
811 for (tail
= Vw32_color_map
; CONSP (tail
); tail
= XCDR (tail
))
813 register Lisp_Object elt
, tem
;
816 if (!CONSP (elt
)) continue;
820 if (lstrcmpi (SDATA (tem
), colorname
) == 0)
837 add_system_logical_colors_to_map (Lisp_Object
*system_colors
)
841 /* Other registry operations are done with input blocked. */
844 /* Look for "Control Panel/Colors" under User and Machine registry
846 if (RegOpenKeyEx (HKEY_CURRENT_USER
, "Control Panel\\Colors", 0,
847 KEY_READ
, &colors_key
) == ERROR_SUCCESS
848 || RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Control Panel\\Colors", 0,
849 KEY_READ
, &colors_key
) == ERROR_SUCCESS
)
852 char color_buffer
[64];
853 char full_name_buffer
[MAX_PATH
+ SYSTEM_COLOR_PREFIX_LEN
];
855 DWORD name_size
, color_size
;
856 char *name_buffer
= full_name_buffer
+ SYSTEM_COLOR_PREFIX_LEN
;
858 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
859 color_size
= sizeof (color_buffer
);
861 strcpy (full_name_buffer
, SYSTEM_COLOR_PREFIX
);
863 while (RegEnumValueA (colors_key
, index
, name_buffer
, &name_size
,
864 NULL
, NULL
, color_buffer
, &color_size
)
868 if (sscanf (color_buffer
, " %u %u %u", &r
, &g
, &b
) == 3)
869 *system_colors
= Fcons (Fcons (build_string (full_name_buffer
),
870 make_number (RGB (r
, g
, b
))),
873 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
874 color_size
= sizeof (color_buffer
);
877 RegCloseKey (colors_key
);
885 x_to_w32_color (char * colorname
)
887 register Lisp_Object ret
= Qnil
;
891 if (colorname
[0] == '#')
893 /* Could be an old-style RGB Device specification. */
896 color
= colorname
+ 1;
898 size
= strlen (color
);
899 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
907 for (i
= 0; i
< 3; i
++)
913 /* The check for 'x' in the following conditional takes into
914 account the fact that strtol allows a "0x" in front of
915 our numbers, and we don't. */
916 if (!isxdigit (color
[0]) || color
[1] == 'x')
920 value
= strtoul (color
, &end
, 16);
922 if (errno
== ERANGE
|| end
- color
!= size
)
927 value
= value
* 0x10;
938 colorval
|= (value
<< pos
);
943 XSETINT (ret
, colorval
);
950 else if (strnicmp (colorname
, "rgb:", 4) == 0)
958 color
= colorname
+ 4;
959 for (i
= 0; i
< 3; i
++)
964 /* The check for 'x' in the following conditional takes into
965 account the fact that strtol allows a "0x" in front of
966 our numbers, and we don't. */
967 if (!isxdigit (color
[0]) || color
[1] == 'x')
969 value
= strtoul (color
, &end
, 16);
975 value
= value
* 0x10 + value
;
988 if (value
== ULONG_MAX
)
990 colorval
|= (value
<< pos
);
997 XSETINT (ret
, colorval
);
1005 else if (strnicmp (colorname
, "rgbi:", 5) == 0)
1007 /* This is an RGB Intensity specification. */
1014 color
= colorname
+ 5;
1015 for (i
= 0; i
< 3; i
++)
1021 value
= strtod (color
, &end
);
1022 if (errno
== ERANGE
)
1024 if (value
< 0.0 || value
> 1.0)
1026 val
= (UINT
)(0x100 * value
);
1027 /* We used 0x100 instead of 0xFF to give a continuous
1028 range between 0.0 and 1.0 inclusive. The next statement
1029 fixes the 1.0 case. */
1032 colorval
|= (val
<< pos
);
1039 XSETINT (ret
, colorval
);
1047 /* I am not going to attempt to handle any of the CIE color schemes
1048 or TekHVC, since I don't know the algorithms for conversion to
1051 /* If we fail to lookup the color name in w32_color_map, then check the
1052 colorname to see if it can be crudely approximated: If the X color
1053 ends in a number (e.g., "darkseagreen2"), strip the number and
1054 return the result of looking up the base color name. */
1055 ret
= w32_color_map_lookup (colorname
);
1058 int len
= strlen (colorname
);
1060 if (isdigit (colorname
[len
- 1]))
1062 char *ptr
, *approx
= alloca (len
+ 1);
1064 strcpy (approx
, colorname
);
1065 ptr
= &approx
[len
- 1];
1066 while (ptr
> approx
&& isdigit (*ptr
))
1069 ret
= w32_color_map_lookup (approx
);
1078 w32_regenerate_palette (FRAME_PTR f
)
1080 struct w32_palette_entry
* list
;
1081 LOGPALETTE
* log_palette
;
1082 HPALETTE new_palette
;
1085 /* don't bother trying to create palette if not supported */
1086 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1089 log_palette
= (LOGPALETTE
*)
1090 alloca (sizeof (LOGPALETTE
) +
1091 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1092 log_palette
->palVersion
= 0x300;
1093 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1095 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1097 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1098 i
++, list
= list
->next
)
1099 log_palette
->palPalEntry
[i
] = list
->entry
;
1101 new_palette
= CreatePalette (log_palette
);
1105 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1106 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1107 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1109 /* Realize display palette and garbage all frames. */
1110 release_frame_dc (f
, get_frame_dc (f
));
1115 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1116 #define SET_W32_COLOR(pe, color) \
1119 pe.peRed = GetRValue (color); \
1120 pe.peGreen = GetGValue (color); \
1121 pe.peBlue = GetBValue (color); \
1126 /* Keep these around in case we ever want to track color usage. */
1128 w32_map_color (FRAME_PTR f
, COLORREF color
)
1130 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1132 if (NILP (Vw32_enable_palette
))
1135 /* check if color is already mapped */
1138 if (W32_COLOR (list
->entry
) == color
)
1146 /* not already mapped, so add to list and recreate Windows palette */
1147 list
= (struct w32_palette_entry
*)
1148 xmalloc (sizeof (struct w32_palette_entry
));
1149 SET_W32_COLOR (list
->entry
, color
);
1151 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1152 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1153 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1155 /* set flag that palette must be regenerated */
1156 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1160 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1162 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1163 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1165 if (NILP (Vw32_enable_palette
))
1168 /* check if color is already mapped */
1171 if (W32_COLOR (list
->entry
) == color
)
1173 if (--list
->refcount
== 0)
1177 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1187 /* set flag that palette must be regenerated */
1188 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1193 /* Gamma-correct COLOR on frame F. */
1196 gamma_correct (struct frame
*f
, COLORREF
*color
)
1200 *color
= PALETTERGB (
1201 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1202 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1203 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1208 /* Decide if color named COLOR is valid for the display associated with
1209 the selected frame; if so, return the rgb values in COLOR_DEF.
1210 If ALLOC is nonzero, allocate a new colormap cell. */
1213 w32_defined_color (FRAME_PTR f
, char *color
, XColor
*color_def
, int alloc
)
1215 register Lisp_Object tem
;
1216 COLORREF w32_color_ref
;
1218 tem
= x_to_w32_color (color
);
1224 /* Apply gamma correction. */
1225 w32_color_ref
= XUINT (tem
);
1226 gamma_correct (f
, &w32_color_ref
);
1227 XSETINT (tem
, w32_color_ref
);
1230 /* Map this color to the palette if it is enabled. */
1231 if (!NILP (Vw32_enable_palette
))
1233 struct w32_palette_entry
* entry
=
1234 one_w32_display_info
.color_list
;
1235 struct w32_palette_entry
** prev
=
1236 &one_w32_display_info
.color_list
;
1238 /* check if color is already mapped */
1241 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1243 prev
= &entry
->next
;
1244 entry
= entry
->next
;
1247 if (entry
== NULL
&& alloc
)
1249 /* not already mapped, so add to list */
1250 entry
= (struct w32_palette_entry
*)
1251 xmalloc (sizeof (struct w32_palette_entry
));
1252 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1255 one_w32_display_info
.num_colors
++;
1257 /* set flag that palette must be regenerated */
1258 one_w32_display_info
.regen_palette
= TRUE
;
1261 /* Ensure COLORREF value is snapped to nearest color in (default)
1262 palette by simulating the PALETTERGB macro. This works whether
1263 or not the display device has a palette. */
1264 w32_color_ref
= XUINT (tem
) | 0x2000000;
1266 color_def
->pixel
= w32_color_ref
;
1267 color_def
->red
= GetRValue (w32_color_ref
) * 256;
1268 color_def
->green
= GetGValue (w32_color_ref
) * 256;
1269 color_def
->blue
= GetBValue (w32_color_ref
) * 256;
1279 /* Given a string ARG naming a color, compute a pixel value from it
1280 suitable for screen F.
1281 If F is not a color screen, return DEF (default) regardless of what
1285 x_decode_color (FRAME_PTR f
, Lisp_Object arg
, int def
)
1291 if (strcmp (SDATA (arg
), "black") == 0)
1292 return BLACK_PIX_DEFAULT (f
);
1293 else if (strcmp (SDATA (arg
), "white") == 0)
1294 return WHITE_PIX_DEFAULT (f
);
1296 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1299 /* w32_defined_color is responsible for coping with failures
1300 by looking for a near-miss. */
1301 if (w32_defined_color (f
, SDATA (arg
), &cdef
, 1))
1304 /* defined_color failed; return an ultimate default. */
1310 /* Functions called only from `x_set_frame_param'
1311 to set individual parameters.
1313 If FRAME_W32_WINDOW (f) is 0,
1314 the frame is being created and its window does not exist yet.
1315 In that case, just record the parameter's new value
1316 in the standard place; do not attempt to change the window. */
1319 x_set_foreground_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1321 struct w32_output
*x
= f
->output_data
.w32
;
1322 PIX_TYPE fg
, old_fg
;
1324 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1325 old_fg
= FRAME_FOREGROUND_PIXEL (f
);
1326 FRAME_FOREGROUND_PIXEL (f
) = fg
;
1328 if (FRAME_W32_WINDOW (f
) != 0)
1330 if (x
->cursor_pixel
== old_fg
)
1331 x
->cursor_pixel
= fg
;
1333 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1334 if (FRAME_VISIBLE_P (f
))
1340 x_set_background_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1342 FRAME_BACKGROUND_PIXEL (f
)
1343 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1345 if (FRAME_W32_WINDOW (f
) != 0)
1347 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
1348 FRAME_BACKGROUND_PIXEL (f
));
1350 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1352 if (FRAME_VISIBLE_P (f
))
1358 x_set_mouse_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1360 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
1364 if (!EQ (Qnil
, arg
))
1365 f
->output_data
.w32
->mouse_pixel
1366 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1367 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
1369 /* Don't let pointers be invisible. */
1370 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1371 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
1372 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
1374 #if 0 /* TODO : Mouse cursor customization. */
1377 /* It's not okay to crash if the user selects a screwy cursor. */
1378 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1380 if (!EQ (Qnil
, Vx_pointer_shape
))
1382 CHECK_NUMBER (Vx_pointer_shape
);
1383 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1386 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1387 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1389 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1391 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1392 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1393 XINT (Vx_nontext_pointer_shape
));
1396 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1397 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1399 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
1401 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1402 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1403 XINT (Vx_hourglass_pointer_shape
));
1406 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
1407 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
1409 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1410 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1412 CHECK_NUMBER (Vx_mode_pointer_shape
);
1413 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1414 XINT (Vx_mode_pointer_shape
));
1417 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1418 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1420 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1422 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1424 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1425 XINT (Vx_sensitive_text_pointer_shape
));
1428 hand_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1430 if (!NILP (Vx_window_horizontal_drag_shape
))
1432 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1433 horizontal_drag_cursor
1434 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1435 XINT (Vx_window_horizontal_drag_shape
));
1438 horizontal_drag_cursor
1439 = XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_sb_h_double_arrow
);
1441 /* Check and report errors with the above calls. */
1442 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1443 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1446 XColor fore_color
, back_color
;
1448 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1449 back_color
.pixel
= mask_color
;
1450 XQueryColor (FRAME_W32_DISPLAY (f
),
1451 DefaultColormap (FRAME_W32_DISPLAY (f
),
1452 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1454 XQueryColor (FRAME_W32_DISPLAY (f
),
1455 DefaultColormap (FRAME_W32_DISPLAY (f
),
1456 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1458 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1459 &fore_color
, &back_color
);
1460 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1461 &fore_color
, &back_color
);
1462 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1463 &fore_color
, &back_color
);
1464 XRecolorCursor (FRAME_W32_DISPLAY (f
), hand_cursor
,
1465 &fore_color
, &back_color
);
1466 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
1467 &fore_color
, &back_color
);
1470 if (FRAME_W32_WINDOW (f
) != 0)
1471 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1473 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1474 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1475 f
->output_data
.w32
->text_cursor
= cursor
;
1477 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1478 && f
->output_data
.w32
->nontext_cursor
!= 0)
1479 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1480 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1482 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
1483 && f
->output_data
.w32
->hourglass_cursor
!= 0)
1484 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
1485 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
1487 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1488 && f
->output_data
.w32
->modeline_cursor
!= 0)
1489 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1490 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1492 if (hand_cursor
!= f
->output_data
.w32
->hand_cursor
1493 && f
->output_data
.w32
->hand_cursor
!= 0)
1494 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hand_cursor
);
1495 f
->output_data
.w32
->hand_cursor
= hand_cursor
;
1497 XFlush (FRAME_W32_DISPLAY (f
));
1500 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1505 x_set_cursor_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1507 unsigned long fore_pixel
, pixel
;
1509 if (!NILP (Vx_cursor_fore_pixel
))
1510 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1511 WHITE_PIX_DEFAULT (f
));
1513 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1515 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1517 /* Make sure that the cursor color differs from the background color. */
1518 if (pixel
== FRAME_BACKGROUND_PIXEL (f
))
1520 pixel
= f
->output_data
.w32
->mouse_pixel
;
1521 if (pixel
== fore_pixel
)
1522 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1525 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1526 f
->output_data
.w32
->cursor_pixel
= pixel
;
1528 if (FRAME_W32_WINDOW (f
) != 0)
1531 /* Update frame's cursor_gc. */
1532 f
->output_data
.w32
->cursor_gc
->foreground
= fore_pixel
;
1533 f
->output_data
.w32
->cursor_gc
->background
= pixel
;
1537 if (FRAME_VISIBLE_P (f
))
1539 x_update_cursor (f
, 0);
1540 x_update_cursor (f
, 1);
1544 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1547 /* Set the border-color of frame F to pixel value PIX.
1548 Note that this does not fully take effect if done before
1552 x_set_border_pixel (struct frame
*f
, int pix
)
1555 f
->output_data
.w32
->border_pixel
= pix
;
1557 if (FRAME_W32_WINDOW (f
) != 0 && f
->border_width
> 0)
1559 if (FRAME_VISIBLE_P (f
))
1564 /* Set the border-color of frame F to value described by ARG.
1565 ARG can be a string naming a color.
1566 The border-color is used for the border that is drawn by the server.
1567 Note that this does not fully take effect if done before
1568 F has a window; it must be redone when the window is created. */
1571 x_set_border_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1576 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1577 x_set_border_pixel (f
, pix
);
1578 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1583 x_set_cursor_type (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1585 set_frame_cursor_types (f
, arg
);
1587 /* Make sure the cursor gets redrawn. */
1588 cursor_type_changed
= 1;
1592 x_set_icon_type (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1596 if (NILP (arg
) && NILP (oldval
))
1599 if (STRINGP (arg
) && STRINGP (oldval
)
1600 && EQ (Fstring_equal (oldval
, arg
), Qt
))
1603 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
1608 result
= x_bitmap_icon (f
, arg
);
1612 error ("No icon window available");
1619 x_set_icon_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1623 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1626 else if (!NILP (arg
) || NILP (oldval
))
1632 if (f
->output_data
.w32
->icon_bitmap
!= 0)
1637 result
= x_text_icon (f
,
1638 (char *) SDATA ((!NILP (f
->icon_name
)
1647 error ("No icon window available");
1650 /* If the window was unmapped (and its icon was mapped),
1651 the new icon is not mapped, so map the window in its stead. */
1652 if (FRAME_VISIBLE_P (f
))
1654 #ifdef USE_X_TOOLKIT
1655 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1657 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1660 XFlush (FRAME_W32_DISPLAY (f
));
1667 x_set_menu_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1670 int olines
= FRAME_MENU_BAR_LINES (f
);
1672 /* Right now, menu bars don't work properly in minibuf-only frames;
1673 most of the commands try to apply themselves to the minibuffer
1674 frame itself, and get an error because you can't switch buffers
1675 in or split the minibuffer window. */
1676 if (FRAME_MINIBUF_ONLY_P (f
))
1679 if (INTEGERP (value
))
1680 nlines
= XINT (value
);
1684 FRAME_MENU_BAR_LINES (f
) = 0;
1686 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1689 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1690 free_frame_menubar (f
);
1691 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1693 /* Adjust the frame size so that the client (text) dimensions
1694 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1696 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1697 do_pending_window_change (0);
1703 /* Set the number of lines used for the tool bar of frame F to VALUE.
1704 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1705 is the old number of tool bar lines. This function changes the
1706 height of all windows on frame F to match the new tool bar height.
1707 The frame's height doesn't change. */
1710 x_set_tool_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1712 int delta
, nlines
, root_height
;
1713 Lisp_Object root_window
;
1715 /* Treat tool bars like menu bars. */
1716 if (FRAME_MINIBUF_ONLY_P (f
))
1719 /* Use VALUE only if an integer >= 0. */
1720 if (INTEGERP (value
) && XINT (value
) >= 0)
1721 nlines
= XFASTINT (value
);
1725 /* Make sure we redisplay all windows in this frame. */
1726 ++windows_or_buffers_changed
;
1728 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
1730 /* Don't resize the tool-bar to more than we have room for. */
1731 root_window
= FRAME_ROOT_WINDOW (f
);
1732 root_height
= WINDOW_TOTAL_LINES (XWINDOW (root_window
));
1733 if (root_height
- delta
< 1)
1735 delta
= root_height
- 1;
1736 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
1739 FRAME_TOOL_BAR_LINES (f
) = nlines
;
1740 change_window_heights (root_window
, delta
);
1743 /* We also have to make sure that the internal border at the top of
1744 the frame, below the menu bar or tool bar, is redrawn when the
1745 tool bar disappears. This is so because the internal border is
1746 below the tool bar if one is displayed, but is below the menu bar
1747 if there isn't a tool bar. The tool bar draws into the area
1748 below the menu bar. */
1749 if (FRAME_W32_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
1752 clear_current_matrices (f
);
1755 /* If the tool bar gets smaller, the internal border below it
1756 has to be cleared. It was formerly part of the display
1757 of the larger tool bar, and updating windows won't clear it. */
1760 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1761 int width
= FRAME_PIXEL_WIDTH (f
);
1762 int y
= nlines
* FRAME_LINE_HEIGHT (f
);
1766 HDC hdc
= get_frame_dc (f
);
1767 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
1768 release_frame_dc (f
, hdc
);
1772 if (WINDOWP (f
->tool_bar_window
))
1773 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
1778 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1781 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1782 name; if NAME is a string, set F's name to NAME and set
1783 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1785 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1786 suggesting a new name, which lisp code should override; if
1787 F->explicit_name is set, ignore the new name; otherwise, set it. */
1790 x_set_name (struct frame
*f
, Lisp_Object name
, int explicit)
1792 /* Make sure that requests from lisp code override requests from
1793 Emacs redisplay code. */
1796 /* If we're switching from explicit to implicit, we had better
1797 update the mode lines and thereby update the title. */
1798 if (f
->explicit_name
&& NILP (name
))
1799 update_mode_lines
= 1;
1801 f
->explicit_name
= ! NILP (name
);
1803 else if (f
->explicit_name
)
1806 /* If NAME is nil, set the name to the w32_id_name. */
1809 /* Check for no change needed in this very common case
1810 before we do any consing. */
1811 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
1814 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
1817 CHECK_STRING (name
);
1819 /* Don't change the name if it's already NAME. */
1820 if (! NILP (Fstring_equal (name
, f
->name
)))
1825 /* For setting the frame title, the title parameter should override
1826 the name parameter. */
1827 if (! NILP (f
->title
))
1830 if (FRAME_W32_WINDOW (f
))
1832 if (STRING_MULTIBYTE (name
))
1833 name
= ENCODE_SYSTEM (name
);
1836 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
1841 /* This function should be called when the user's lisp code has
1842 specified a name for the frame; the name will override any set by the
1845 x_explicitly_set_name (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1847 x_set_name (f
, arg
, 1);
1850 /* This function should be called by Emacs redisplay code to set the
1851 name; names set this way will never override names set by the user's
1854 x_implicitly_set_name (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1856 x_set_name (f
, arg
, 0);
1859 /* Change the title of frame F to NAME.
1860 If NAME is nil, use the frame name as the title. */
1863 x_set_title (struct frame
*f
, Lisp_Object name
, Lisp_Object old_name
)
1865 /* Don't change the title if it's already NAME. */
1866 if (EQ (name
, f
->title
))
1869 update_mode_lines
= 1;
1876 if (FRAME_W32_WINDOW (f
))
1878 if (STRING_MULTIBYTE (name
))
1879 name
= ENCODE_SYSTEM (name
);
1882 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
1889 x_set_scroll_bar_default_width (struct frame
*f
)
1891 int wid
= FRAME_COLUMN_WIDTH (f
);
1893 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
1894 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) +
1899 /* Subroutines for creating a frame. */
1902 w32_load_cursor (LPCTSTR name
)
1904 /* Try first to load cursor from application resource. */
1905 Cursor cursor
= LoadImage ((HINSTANCE
) GetModuleHandle (NULL
),
1906 name
, IMAGE_CURSOR
, 0, 0,
1907 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1910 /* Then try to load a shared predefined cursor. */
1911 cursor
= LoadImage (NULL
, name
, IMAGE_CURSOR
, 0, 0,
1912 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1917 extern LRESULT CALLBACK
w32_wnd_proc (HWND
, UINT
, WPARAM
, LPARAM
);
1920 w32_init_class (HINSTANCE hinst
)
1924 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1925 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
1927 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
1928 wc
.hInstance
= hinst
;
1929 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
1930 wc
.hCursor
= w32_load_cursor (IDC_ARROW
);
1931 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
1932 wc
.lpszMenuName
= NULL
;
1933 wc
.lpszClassName
= EMACS_CLASS
;
1935 return (RegisterClass (&wc
));
1939 w32_createscrollbar (struct frame
*f
, struct scroll_bar
* bar
)
1941 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
1942 /* Position and size of scroll bar. */
1943 XINT (bar
->left
) + VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
1945 XINT (bar
->width
) - VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
1947 FRAME_W32_WINDOW (f
),
1954 w32_createwindow (struct frame
*f
)
1958 Lisp_Object top
= Qunbound
;
1959 Lisp_Object left
= Qunbound
;
1960 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
1962 rect
.left
= rect
.top
= 0;
1963 rect
.right
= FRAME_PIXEL_WIDTH (f
);
1964 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
1966 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
1967 FRAME_EXTERNAL_MENU_BAR (f
));
1969 /* Do first time app init */
1973 w32_init_class (hinst
);
1976 if (f
->size_hint_flags
& USPosition
|| f
->size_hint_flags
& PPosition
)
1978 XSETINT (left
, f
->left_pos
);
1979 XSETINT (top
, f
->top_pos
);
1981 else if (EQ (left
, Qunbound
) && EQ (top
, Qunbound
))
1983 /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
1984 for anything that is not a number and is not Qunbound. */
1985 left
= x_get_arg (dpyinfo
, Qnil
, Qleft
, "left", "Left", RES_TYPE_NUMBER
);
1986 top
= x_get_arg (dpyinfo
, Qnil
, Qtop
, "top", "Top", RES_TYPE_NUMBER
);
1989 FRAME_W32_WINDOW (f
) = hwnd
1990 = CreateWindow (EMACS_CLASS
,
1992 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
1993 EQ (left
, Qunbound
) ? CW_USEDEFAULT
: XINT (left
),
1994 EQ (top
, Qunbound
) ? CW_USEDEFAULT
: XINT (top
),
1995 rect
.right
- rect
.left
,
1996 rect
.bottom
- rect
.top
,
2004 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
2005 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
2006 SetWindowLong (hwnd
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
2007 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
2008 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
2010 /* Enable drag-n-drop. */
2011 DragAcceptFiles (hwnd
, TRUE
);
2013 /* Do this to discard the default setting specified by our parent. */
2014 ShowWindow (hwnd
, SW_HIDE
);
2016 /* Update frame positions. */
2017 GetWindowRect (hwnd
, &rect
);
2018 f
->left_pos
= rect
.left
;
2019 f
->top_pos
= rect
.top
;
2024 my_post_msg (W32Msg
* wmsg
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2026 wmsg
->msg
.hwnd
= hwnd
;
2027 wmsg
->msg
.message
= msg
;
2028 wmsg
->msg
.wParam
= wParam
;
2029 wmsg
->msg
.lParam
= lParam
;
2030 wmsg
->msg
.time
= GetMessageTime ();
2035 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2036 between left and right keys as advertised. We test for this
2037 support dynamically, and set a flag when the support is absent. If
2038 absent, we keep track of the left and right control and alt keys
2039 ourselves. This is particularly necessary on keyboards that rely
2040 upon the AltGr key, which is represented as having the left control
2041 and right alt keys pressed. For these keyboards, we need to know
2042 when the left alt key has been pressed in addition to the AltGr key
2043 so that we can properly support M-AltGr-key sequences (such as M-@
2044 on Swedish keyboards). */
2046 #define EMACS_LCONTROL 0
2047 #define EMACS_RCONTROL 1
2048 #define EMACS_LMENU 2
2049 #define EMACS_RMENU 3
2051 static int modifiers
[4];
2052 static int modifiers_recorded
;
2053 static int modifier_key_support_tested
;
2056 test_modifier_support (unsigned int wparam
)
2060 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
2062 if (wparam
== VK_CONTROL
)
2072 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
2073 modifiers_recorded
= 1;
2075 modifiers_recorded
= 0;
2076 modifier_key_support_tested
= 1;
2080 record_keydown (unsigned int wparam
, unsigned int lparam
)
2084 if (!modifier_key_support_tested
)
2085 test_modifier_support (wparam
);
2087 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2090 if (wparam
== VK_CONTROL
)
2091 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2093 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2099 record_keyup (unsigned int wparam
, unsigned int lparam
)
2103 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2106 if (wparam
== VK_CONTROL
)
2107 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2109 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2114 /* Emacs can lose focus while a modifier key has been pressed. When
2115 it regains focus, be conservative and clear all modifiers since
2116 we cannot reconstruct the left and right modifier state. */
2118 reset_modifiers (void)
2122 if (GetFocus () == NULL
)
2123 /* Emacs doesn't have keyboard focus. Do nothing. */
2126 ctrl
= GetAsyncKeyState (VK_CONTROL
);
2127 alt
= GetAsyncKeyState (VK_MENU
);
2129 if (!(ctrl
& 0x08000))
2130 /* Clear any recorded control modifier state. */
2131 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2133 if (!(alt
& 0x08000))
2134 /* Clear any recorded alt modifier state. */
2135 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2137 /* Update the state of all modifier keys, because modifiers used in
2138 hot-key combinations can get stuck on if Emacs loses focus as a
2139 result of a hot-key being pressed. */
2143 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2145 GetKeyboardState (keystate
);
2146 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
2147 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
2148 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
2149 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
2150 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
2151 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
2152 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
2153 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
2154 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
2155 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
2156 SetKeyboardState (keystate
);
2160 /* Synchronize modifier state with what is reported with the current
2161 keystroke. Even if we cannot distinguish between left and right
2162 modifier keys, we know that, if no modifiers are set, then neither
2163 the left or right modifier should be set. */
2165 sync_modifiers (void)
2167 if (!modifiers_recorded
)
2170 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
2171 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2173 if (!(GetKeyState (VK_MENU
) & 0x8000))
2174 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2178 modifier_set (int vkey
)
2180 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
2181 return (GetKeyState (vkey
) & 0x1);
2182 if (!modifiers_recorded
)
2183 return (GetKeyState (vkey
) & 0x8000);
2188 return modifiers
[EMACS_LCONTROL
];
2190 return modifiers
[EMACS_RCONTROL
];
2192 return modifiers
[EMACS_LMENU
];
2194 return modifiers
[EMACS_RMENU
];
2196 return (GetKeyState (vkey
) & 0x8000);
2199 /* Convert between the modifier bits W32 uses and the modifier bits
2203 w32_key_to_modifier (int key
)
2205 Lisp_Object key_mapping
;
2210 key_mapping
= Vw32_lwindow_modifier
;
2213 key_mapping
= Vw32_rwindow_modifier
;
2216 key_mapping
= Vw32_apps_modifier
;
2219 key_mapping
= Vw32_scroll_lock_modifier
;
2225 /* NB. This code runs in the input thread, asychronously to the lisp
2226 thread, so we must be careful to ensure access to lisp data is
2227 thread-safe. The following code is safe because the modifier
2228 variable values are updated atomically from lisp and symbols are
2229 not relocated by GC. Also, we don't have to worry about seeing GC
2231 if (EQ (key_mapping
, Qhyper
))
2232 return hyper_modifier
;
2233 if (EQ (key_mapping
, Qsuper
))
2234 return super_modifier
;
2235 if (EQ (key_mapping
, Qmeta
))
2236 return meta_modifier
;
2237 if (EQ (key_mapping
, Qalt
))
2238 return alt_modifier
;
2239 if (EQ (key_mapping
, Qctrl
))
2240 return ctrl_modifier
;
2241 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
2242 return ctrl_modifier
;
2243 if (EQ (key_mapping
, Qshift
))
2244 return shift_modifier
;
2246 /* Don't generate any modifier if not explicitly requested. */
2251 w32_get_modifiers (void)
2253 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
2254 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
2255 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
2256 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
2257 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
2258 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
2259 (modifier_set (VK_MENU
) ?
2260 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2263 /* We map the VK_* modifiers into console modifier constants
2264 so that we can use the same routines to handle both console
2265 and window input. */
2268 construct_console_modifiers (void)
2273 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
2274 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
2275 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
2276 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
2277 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
2278 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
2279 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
2280 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
2281 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
2282 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
2283 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
2289 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
2293 /* Convert to emacs modifiers. */
2294 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
2300 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
2302 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
2305 if (virt_key
== VK_RETURN
)
2306 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
2308 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
2309 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
2311 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
2312 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
2314 if (virt_key
== VK_CLEAR
)
2315 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
2320 /* List of special key combinations which w32 would normally capture,
2321 but Emacs should grab instead. Not directly visible to lisp, to
2322 simplify synchronization. Each item is an integer encoding a virtual
2323 key code and modifier combination to capture. */
2324 static Lisp_Object w32_grabbed_keys
;
2326 #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8))
2327 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2328 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2329 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2331 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2332 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2333 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2335 /* Register hot-keys for reserved key combinations when Emacs has
2336 keyboard focus, since this is the only way Emacs can receive key
2337 combinations like Alt-Tab which are used by the system. */
2340 register_hot_keys (HWND hwnd
)
2342 Lisp_Object keylist
;
2344 /* Use CONSP, since we are called asynchronously. */
2345 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2347 Lisp_Object key
= XCAR (keylist
);
2349 /* Deleted entries get set to nil. */
2350 if (!INTEGERP (key
))
2353 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
2354 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
2359 unregister_hot_keys (HWND hwnd
)
2361 Lisp_Object keylist
;
2363 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2365 Lisp_Object key
= XCAR (keylist
);
2367 if (!INTEGERP (key
))
2370 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
2374 /* Main message dispatch loop. */
2377 w32_msg_pump (deferred_msg
* msg_buf
)
2383 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
2385 while (GetMessage (&msg
, NULL
, 0, 0))
2387 if (msg
.hwnd
== NULL
)
2389 switch (msg
.message
)
2392 /* Produced by complete_deferred_msg; just ignore. */
2394 case WM_EMACS_CREATEWINDOW
:
2395 /* Initialize COM for this window. Even though we don't use it,
2396 some third party shell extensions can cause it to be used in
2397 system dialogs, which causes a crash if it is not initialized.
2398 This is a known bug in Windows, which was fixed long ago, but
2399 the patch for XP is not publically available until XP SP3,
2400 and older versions will never be patched. */
2401 CoInitialize (NULL
);
2402 w32_createwindow ((struct frame
*) msg
.wParam
);
2403 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2406 case WM_EMACS_SETLOCALE
:
2407 SetThreadLocale (msg
.wParam
);
2408 /* Reply is not expected. */
2410 case WM_EMACS_SETKEYBOARDLAYOUT
:
2411 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
2412 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2416 case WM_EMACS_REGISTER_HOT_KEY
:
2417 focus_window
= GetFocus ();
2418 if (focus_window
!= NULL
)
2419 RegisterHotKey (focus_window
,
2420 RAW_HOTKEY_ID (msg
.wParam
),
2421 RAW_HOTKEY_MODIFIERS (msg
.wParam
),
2422 RAW_HOTKEY_VK_CODE (msg
.wParam
));
2423 /* Reply is not expected. */
2425 case WM_EMACS_UNREGISTER_HOT_KEY
:
2426 focus_window
= GetFocus ();
2427 if (focus_window
!= NULL
)
2428 UnregisterHotKey (focus_window
, RAW_HOTKEY_ID (msg
.wParam
));
2429 /* Mark item as erased. NB: this code must be
2430 thread-safe. The next line is okay because the cons
2431 cell is never made into garbage and is not relocated by
2433 XSETCAR ((Lisp_Object
) ((EMACS_INT
) msg
.lParam
), Qnil
);
2434 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2437 case WM_EMACS_TOGGLE_LOCK_KEY
:
2439 int vk_code
= (int) msg
.wParam
;
2440 int cur_state
= (GetKeyState (vk_code
) & 1);
2441 Lisp_Object new_state
= (Lisp_Object
) ((EMACS_INT
) msg
.lParam
);
2443 /* NB: This code must be thread-safe. It is safe to
2444 call NILP because symbols are not relocated by GC,
2445 and pointer here is not touched by GC (so the markbit
2446 can't be set). Numbers are safe because they are
2447 immediate values. */
2448 if (NILP (new_state
)
2449 || (NUMBERP (new_state
)
2450 && ((XUINT (new_state
)) & 1) != cur_state
))
2452 one_w32_display_info
.faked_key
= vk_code
;
2454 keybd_event ((BYTE
) vk_code
,
2455 (BYTE
) MapVirtualKey (vk_code
, 0),
2456 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2457 keybd_event ((BYTE
) vk_code
,
2458 (BYTE
) MapVirtualKey (vk_code
, 0),
2459 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2460 keybd_event ((BYTE
) vk_code
,
2461 (BYTE
) MapVirtualKey (vk_code
, 0),
2462 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2463 cur_state
= !cur_state
;
2465 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2471 /* Broadcast messages make it here, so you need to be looking
2472 for something in particular for this to be useful. */
2474 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
2480 DispatchMessage (&msg
);
2483 /* Exit nested loop when our deferred message has completed. */
2484 if (msg_buf
->completed
)
2489 deferred_msg
* deferred_msg_head
;
2491 static deferred_msg
*
2492 find_deferred_msg (HWND hwnd
, UINT msg
)
2494 deferred_msg
* item
;
2496 /* Don't actually need synchronization for read access, since
2497 modification of single pointer is always atomic. */
2498 /* enter_crit (); */
2500 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2501 if (item
->w32msg
.msg
.hwnd
== hwnd
2502 && item
->w32msg
.msg
.message
== msg
)
2505 /* leave_crit (); */
2511 send_deferred_msg (deferred_msg
* msg_buf
,
2517 /* Only input thread can send deferred messages. */
2518 if (GetCurrentThreadId () != dwWindowsThreadId
)
2521 /* It is an error to send a message that is already deferred. */
2522 if (find_deferred_msg (hwnd
, msg
) != NULL
)
2525 /* Enforced synchronization is not needed because this is the only
2526 function that alters deferred_msg_head, and the following critical
2527 section is guaranteed to only be serially reentered (since only the
2528 input thread can call us). */
2530 /* enter_crit (); */
2532 msg_buf
->completed
= 0;
2533 msg_buf
->next
= deferred_msg_head
;
2534 deferred_msg_head
= msg_buf
;
2535 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
2537 /* leave_crit (); */
2539 /* Start a new nested message loop to process other messages until
2540 this one is completed. */
2541 w32_msg_pump (msg_buf
);
2543 deferred_msg_head
= msg_buf
->next
;
2545 return msg_buf
->result
;
2549 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
2551 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
2553 if (msg_buf
== NULL
)
2554 /* Message may have been cancelled, so don't abort. */
2557 msg_buf
->result
= result
;
2558 msg_buf
->completed
= 1;
2560 /* Ensure input thread is woken so it notices the completion. */
2561 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2565 cancel_all_deferred_msgs (void)
2567 deferred_msg
* item
;
2569 /* Don't actually need synchronization for read access, since
2570 modification of single pointer is always atomic. */
2571 /* enter_crit (); */
2573 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2576 item
->completed
= 1;
2579 /* leave_crit (); */
2581 /* Ensure input thread is woken so it notices the completion. */
2582 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2586 w32_msg_worker (void *arg
)
2589 deferred_msg dummy_buf
;
2591 /* Ensure our message queue is created */
2593 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2595 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2598 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
2599 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
2600 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
2602 /* This is the initial message loop which should only exit when the
2603 application quits. */
2604 w32_msg_pump (&dummy_buf
);
2610 signal_user_input (void)
2612 /* Interrupt any lisp that wants to be interrupted by input. */
2613 if (!NILP (Vthrow_on_input
))
2615 Vquit_flag
= Vthrow_on_input
;
2616 /* If we're inside a function that wants immediate quits,
2618 if (immediate_quit
&& NILP (Vinhibit_quit
))
2628 post_character_message (HWND hwnd
, UINT msg
,
2629 WPARAM wParam
, LPARAM lParam
,
2634 wmsg
.dwModifiers
= modifiers
;
2636 /* Detect quit_char and set quit-flag directly. Note that we
2637 still need to post a message to ensure the main thread will be
2638 woken up if blocked in sys_select, but we do NOT want to post
2639 the quit_char message itself (because it will usually be as if
2640 the user had typed quit_char twice). Instead, we post a dummy
2641 message that has no particular effect. */
2644 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
2645 c
= make_ctrl_char (c
) & 0377;
2647 || (wmsg
.dwModifiers
== 0 &&
2648 w32_quit_key
&& wParam
== w32_quit_key
))
2652 /* The choice of message is somewhat arbitrary, as long as
2653 the main thread handler just ignores it. */
2656 /* Interrupt any blocking system calls. */
2659 /* As a safety precaution, forcibly complete any deferred
2660 messages. This is a kludge, but I don't see any particularly
2661 clean way to handle the situation where a deferred message is
2662 "dropped" in the lisp thread, and will thus never be
2663 completed, eg. by the user trying to activate the menubar
2664 when the lisp thread is busy, and then typing C-g when the
2665 menubar doesn't open promptly (with the result that the
2666 menubar never responds at all because the deferred
2667 WM_INITMENU message is never completed). Another problem
2668 situation is when the lisp thread calls SendMessage (to send
2669 a window manager command) when a message has been deferred;
2670 the lisp thread gets blocked indefinitely waiting for the
2671 deferred message to be completed, which itself is waiting for
2672 the lisp thread to respond.
2674 Note that we don't want to block the input thread waiting for
2675 a reponse from the lisp thread (although that would at least
2676 solve the deadlock problem above), because we want to be able
2677 to receive C-g to interrupt the lisp thread. */
2678 cancel_all_deferred_msgs ();
2681 signal_user_input ();
2684 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2687 /* Main window procedure */
2690 w32_wnd_proc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2693 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2695 int windows_translate
;
2698 /* Note that it is okay to call x_window_to_frame, even though we are
2699 not running in the main lisp thread, because frame deletion
2700 requires the lisp thread to synchronize with this thread. Thus, if
2701 a frame struct is returned, it can be used without concern that the
2702 lisp thread might make it disappear while we are using it.
2704 NB. Walking the frame list in this thread is safe (as long as
2705 writes of Lisp_Object slots are atomic, which they are on Windows).
2706 Although delete-frame can destructively modify the frame list while
2707 we are walking it, a garbage collection cannot occur until after
2708 delete-frame has synchronized with this thread.
2710 It is also safe to use functions that make GDI calls, such as
2711 w32_clear_rect, because these functions must obtain a DC handle
2712 from the frame struct using get_frame_dc which is thread-aware. */
2717 f
= x_window_to_frame (dpyinfo
, hwnd
);
2720 HDC hdc
= get_frame_dc (f
);
2721 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
2722 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
2723 release_frame_dc (f
, hdc
);
2725 #if defined (W32_DEBUG_DISPLAY)
2726 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2728 wmsg
.rect
.left
, wmsg
.rect
.top
,
2729 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2730 #endif /* W32_DEBUG_DISPLAY */
2733 case WM_PALETTECHANGED
:
2734 /* ignore our own changes */
2735 if ((HWND
)wParam
!= hwnd
)
2737 f
= x_window_to_frame (dpyinfo
, hwnd
);
2739 /* get_frame_dc will realize our palette and force all
2740 frames to be redrawn if needed. */
2741 release_frame_dc (f
, get_frame_dc (f
));
2746 PAINTSTRUCT paintStruct
;
2748 memset (&update_rect
, 0, sizeof (update_rect
));
2750 f
= x_window_to_frame (dpyinfo
, hwnd
);
2753 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd
));
2757 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2758 fails. Apparently this can happen under some
2760 if (GetUpdateRect (hwnd
, &update_rect
, FALSE
) || !w32_strict_painting
)
2763 BeginPaint (hwnd
, &paintStruct
);
2765 /* The rectangles returned by GetUpdateRect and BeginPaint
2766 do not always match. Play it safe by assuming both areas
2768 UnionRect (&(wmsg
.rect
), &update_rect
, &(paintStruct
.rcPaint
));
2770 #if defined (W32_DEBUG_DISPLAY)
2771 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2773 wmsg
.rect
.left
, wmsg
.rect
.top
,
2774 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2775 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2776 update_rect
.left
, update_rect
.top
,
2777 update_rect
.right
, update_rect
.bottom
));
2779 EndPaint (hwnd
, &paintStruct
);
2782 /* Change the message type to prevent Windows from
2783 combining WM_PAINT messages in the Lisp thread's queue,
2784 since Windows assumes that each message queue is
2785 dedicated to one frame and does not bother checking
2786 that hwnd matches before combining them. */
2787 my_post_msg (&wmsg
, hwnd
, WM_EMACS_PAINT
, wParam
, lParam
);
2792 /* If GetUpdateRect returns 0 (meaning there is no update
2793 region), assume the whole window needs to be repainted. */
2794 GetClientRect (hwnd
, &wmsg
.rect
);
2795 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2799 case WM_INPUTLANGCHANGE
:
2800 /* Inform lisp thread of keyboard layout changes. */
2801 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2803 /* Clear dead keys in the keyboard state; for simplicity only
2804 preserve modifier key states. */
2809 GetKeyboardState (keystate
);
2810 for (i
= 0; i
< 256; i
++)
2827 SetKeyboardState (keystate
);
2832 /* Synchronize hot keys with normal input. */
2833 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
2838 record_keyup (wParam
, lParam
);
2843 /* Ignore keystrokes we fake ourself; see below. */
2844 if (dpyinfo
->faked_key
== wParam
)
2846 dpyinfo
->faked_key
= 0;
2847 /* Make sure TranslateMessage sees them though (as long as
2848 they don't produce WM_CHAR messages). This ensures that
2849 indicator lights are toggled promptly on Windows 9x, for
2851 if (wParam
< 256 && lispy_function_keys
[wParam
])
2853 windows_translate
= 1;
2859 /* Synchronize modifiers with current keystroke. */
2861 record_keydown (wParam
, lParam
);
2862 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
2864 windows_translate
= 0;
2869 if (NILP (Vw32_pass_lwindow_to_system
))
2871 /* Prevent system from acting on keyup (which opens the
2872 Start menu if no other key was pressed) by simulating a
2873 press of Space which we will ignore. */
2874 if (GetAsyncKeyState (wParam
) & 1)
2876 if (NUMBERP (Vw32_phantom_key_code
))
2877 key
= XUINT (Vw32_phantom_key_code
) & 255;
2880 dpyinfo
->faked_key
= key
;
2881 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
2884 if (!NILP (Vw32_lwindow_modifier
))
2888 if (NILP (Vw32_pass_rwindow_to_system
))
2890 if (GetAsyncKeyState (wParam
) & 1)
2892 if (NUMBERP (Vw32_phantom_key_code
))
2893 key
= XUINT (Vw32_phantom_key_code
) & 255;
2896 dpyinfo
->faked_key
= key
;
2897 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
2900 if (!NILP (Vw32_rwindow_modifier
))
2904 if (!NILP (Vw32_apps_modifier
))
2908 if (NILP (Vw32_pass_alt_to_system
))
2909 /* Prevent DefWindowProc from activating the menu bar if an
2910 Alt key is pressed and released by itself. */
2912 windows_translate
= 1;
2915 /* Decide whether to treat as modifier or function key. */
2916 if (NILP (Vw32_enable_caps_lock
))
2917 goto disable_lock_key
;
2918 windows_translate
= 1;
2921 /* Decide whether to treat as modifier or function key. */
2922 if (NILP (Vw32_enable_num_lock
))
2923 goto disable_lock_key
;
2924 windows_translate
= 1;
2927 /* Decide whether to treat as modifier or function key. */
2928 if (NILP (Vw32_scroll_lock_modifier
))
2929 goto disable_lock_key
;
2930 windows_translate
= 1;
2933 /* Ensure the appropriate lock key state (and indicator light)
2934 remains in the same state. We do this by faking another
2935 press of the relevant key. Apparently, this really is the
2936 only way to toggle the state of the indicator lights. */
2937 dpyinfo
->faked_key
= wParam
;
2938 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2939 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2940 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2941 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2942 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2943 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2944 /* Ensure indicator lights are updated promptly on Windows 9x
2945 (TranslateMessage apparently does this), after forwarding
2947 post_character_message (hwnd
, msg
, wParam
, lParam
,
2948 w32_get_key_modifiers (wParam
, lParam
));
2949 windows_translate
= 1;
2953 case VK_PROCESSKEY
: /* Generated by IME. */
2954 windows_translate
= 1;
2957 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
2958 which is confusing for purposes of key binding; convert
2959 VK_CANCEL events into VK_PAUSE events. */
2963 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
2964 for purposes of key binding; convert these back into
2965 VK_NUMLOCK events, at least when we want to see NumLock key
2966 presses. (Note that there is never any possibility that
2967 VK_PAUSE with Ctrl really is C-Pause as per above.) */
2968 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
2969 wParam
= VK_NUMLOCK
;
2972 /* If not defined as a function key, change it to a WM_CHAR message. */
2973 if (wParam
> 255 || !lispy_function_keys
[wParam
])
2975 DWORD modifiers
= construct_console_modifiers ();
2977 if (!NILP (Vw32_recognize_altgr
)
2978 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
2980 /* Always let TranslateMessage handle AltGr key chords;
2981 for some reason, ToAscii doesn't always process AltGr
2982 chords correctly. */
2983 windows_translate
= 1;
2985 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
2987 /* Handle key chords including any modifiers other
2988 than shift directly, in order to preserve as much
2989 modifier information as possible. */
2990 if ('A' <= wParam
&& wParam
<= 'Z')
2992 /* Don't translate modified alphabetic keystrokes,
2993 so the user doesn't need to constantly switch
2994 layout to type control or meta keystrokes when
2995 the normal layout translates alphabetic
2996 characters to non-ascii characters. */
2997 if (!modifier_set (VK_SHIFT
))
2998 wParam
+= ('a' - 'A');
3003 /* Try to handle other keystrokes by determining the
3004 base character (ie. translating the base key plus
3008 KEY_EVENT_RECORD key
;
3010 key
.bKeyDown
= TRUE
;
3011 key
.wRepeatCount
= 1;
3012 key
.wVirtualKeyCode
= wParam
;
3013 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3014 key
.uChar
.AsciiChar
= 0;
3015 key
.dwControlKeyState
= modifiers
;
3017 add
= w32_kbd_patch_key (&key
);
3018 /* 0 means an unrecognised keycode, negative means
3019 dead key. Ignore both. */
3022 /* Forward asciified character sequence. */
3023 post_character_message
3025 (unsigned char) key
.uChar
.AsciiChar
, lParam
,
3026 w32_get_key_modifiers (wParam
, lParam
));
3027 w32_kbd_patch_key (&key
);
3034 /* Let TranslateMessage handle everything else. */
3035 windows_translate
= 1;
3041 if (windows_translate
)
3043 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3044 windows_msg
.time
= GetMessageTime ();
3045 TranslateMessage (&windows_msg
);
3053 post_character_message (hwnd
, msg
, wParam
, lParam
,
3054 w32_get_key_modifiers (wParam
, lParam
));
3058 /* WM_UNICHAR looks promising from the docs, but the exact
3059 circumstances in which TranslateMessage sends it is one of those
3060 Microsoft secret API things that EU and US courts are supposed
3061 to have put a stop to already. Spy++ shows it being sent to Notepad
3062 and other MS apps, but never to Emacs.
3064 Some third party IMEs send it in accordance with the official
3065 documentation though, so handle it here.
3067 UNICODE_NOCHAR is used to test for support for this message.
3068 TRUE indicates that the message is supported. */
3069 if (wParam
== UNICODE_NOCHAR
)
3074 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3075 signal_user_input ();
3076 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3081 /* If we can't get the IME result as unicode, use default processing,
3082 which will at least allow characters decodable in the system locale
3084 if (!get_composition_string_fn
)
3087 else if (!ignore_ime_char
)
3092 HIMC context
= get_ime_context_fn (hwnd
);
3093 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3094 /* Get buffer size. */
3095 size
= get_composition_string_fn (context
, GCS_RESULTSTR
, buffer
, 0);
3096 buffer
= alloca (size
);
3097 size
= get_composition_string_fn (context
, GCS_RESULTSTR
,
3099 release_ime_context_fn (hwnd
, context
);
3101 signal_user_input ();
3102 for (i
= 0; i
< size
/ sizeof (wchar_t); i
++)
3104 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, (WPARAM
) buffer
[i
],
3107 /* Ignore the messages for the rest of the
3108 characters in the string that was output above. */
3109 ignore_ime_char
= (size
/ sizeof (wchar_t)) - 1;
3116 case WM_IME_STARTCOMPOSITION
:
3117 if (!set_ime_composition_window_fn
)
3121 COMPOSITIONFORM form
;
3128 f
= x_window_to_frame (dpyinfo
, hwnd
);
3129 w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
3131 form
.dwStyle
= CFS_RECT
;
3132 form
.ptCurrentPos
.x
= w32_system_caret_x
;
3133 form
.ptCurrentPos
.y
= w32_system_caret_y
;
3135 form
.rcArea
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, 0);
3136 form
.rcArea
.top
= (WINDOW_TOP_EDGE_Y (w
)
3137 + WINDOW_HEADER_LINE_HEIGHT (w
));
3138 form
.rcArea
.right
= (WINDOW_BOX_RIGHT_EDGE_X (w
)
3139 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
3140 - WINDOW_RIGHT_FRINGE_WIDTH (w
));
3141 form
.rcArea
.bottom
= (WINDOW_BOTTOM_EDGE_Y (w
)
3142 - WINDOW_MODE_LINE_HEIGHT (w
));
3144 context
= get_ime_context_fn (hwnd
);
3145 set_ime_composition_window_fn (context
, &form
);
3146 release_ime_context_fn (hwnd
, context
);
3150 case WM_IME_ENDCOMPOSITION
:
3151 ignore_ime_char
= 0;
3154 /* Simulate middle mouse button events when left and right buttons
3155 are used together, but only if user has two button mouse. */
3156 case WM_LBUTTONDOWN
:
3157 case WM_RBUTTONDOWN
:
3158 if (w32_num_mouse_buttons
> 2)
3159 goto handle_plain_button
;
3162 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3163 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3165 if (button_state
& this)
3168 if (button_state
== 0)
3171 button_state
|= this;
3173 if (button_state
& other
)
3175 if (mouse_button_timer
)
3177 KillTimer (hwnd
, mouse_button_timer
);
3178 mouse_button_timer
= 0;
3180 /* Generate middle mouse event instead. */
3181 msg
= WM_MBUTTONDOWN
;
3182 button_state
|= MMOUSE
;
3184 else if (button_state
& MMOUSE
)
3186 /* Ignore button event if we've already generated a
3187 middle mouse down event. This happens if the
3188 user releases and press one of the two buttons
3189 after we've faked a middle mouse event. */
3194 /* Flush out saved message. */
3195 post_msg (&saved_mouse_button_msg
);
3197 wmsg
.dwModifiers
= w32_get_modifiers ();
3198 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3199 signal_user_input ();
3201 /* Clear message buffer. */
3202 saved_mouse_button_msg
.msg
.hwnd
= 0;
3206 /* Hold onto message for now. */
3207 mouse_button_timer
=
3208 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
3209 w32_mouse_button_tolerance
, NULL
);
3210 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3211 saved_mouse_button_msg
.msg
.message
= msg
;
3212 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3213 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3214 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3215 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3222 if (w32_num_mouse_buttons
> 2)
3223 goto handle_plain_button
;
3226 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3227 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3229 if ((button_state
& this) == 0)
3232 button_state
&= ~this;
3234 if (button_state
& MMOUSE
)
3236 /* Only generate event when second button is released. */
3237 if ((button_state
& other
) == 0)
3240 button_state
&= ~MMOUSE
;
3242 if (button_state
) abort ();
3249 /* Flush out saved message if necessary. */
3250 if (saved_mouse_button_msg
.msg
.hwnd
)
3252 post_msg (&saved_mouse_button_msg
);
3255 wmsg
.dwModifiers
= w32_get_modifiers ();
3256 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3257 signal_user_input ();
3259 /* Always clear message buffer and cancel timer. */
3260 saved_mouse_button_msg
.msg
.hwnd
= 0;
3261 KillTimer (hwnd
, mouse_button_timer
);
3262 mouse_button_timer
= 0;
3264 if (button_state
== 0)
3269 case WM_XBUTTONDOWN
:
3271 if (w32_pass_extra_mouse_buttons_to_system
)
3273 /* else fall through and process them. */
3274 case WM_MBUTTONDOWN
:
3276 handle_plain_button
:
3281 /* Ignore middle and extra buttons as long as the menu is active. */
3282 f
= x_window_to_frame (dpyinfo
, hwnd
);
3283 if (f
&& f
->output_data
.w32
->menubar_active
)
3286 if (parse_button (msg
, HIWORD (wParam
), &button
, &up
))
3288 if (up
) ReleaseCapture ();
3289 else SetCapture (hwnd
);
3290 button
= (button
== 0) ? LMOUSE
:
3291 ((button
== 1) ? MMOUSE
: RMOUSE
);
3293 button_state
&= ~button
;
3295 button_state
|= button
;
3299 wmsg
.dwModifiers
= w32_get_modifiers ();
3300 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3301 signal_user_input ();
3303 /* Need to return true for XBUTTON messages, false for others,
3304 to indicate that we processed the message. */
3305 return (msg
== WM_XBUTTONDOWN
|| msg
== WM_XBUTTONUP
);
3308 /* Ignore mouse movements as long as the menu is active. These
3309 movements are processed by the window manager anyway, and
3310 it's wrong to handle them as if they happened on the
3311 underlying frame. */
3312 f
= x_window_to_frame (dpyinfo
, hwnd
);
3313 if (f
&& f
->output_data
.w32
->menubar_active
)
3316 /* If the mouse has just moved into the frame, start tracking
3317 it, so we will be notified when it leaves the frame. Mouse
3318 tracking only works under W98 and NT4 and later. On earlier
3319 versions, there is no way of telling when the mouse leaves the
3320 frame, so we just have to put up with help-echo and mouse
3321 highlighting remaining while the frame is not active. */
3322 if (track_mouse_event_fn
&& !track_mouse_window
)
3324 TRACKMOUSEEVENT tme
;
3325 tme
.cbSize
= sizeof (tme
);
3326 tme
.dwFlags
= TME_LEAVE
;
3327 tme
.hwndTrack
= hwnd
;
3329 track_mouse_event_fn (&tme
);
3330 track_mouse_window
= hwnd
;
3333 if (w32_mouse_move_interval
<= 0
3334 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3336 wmsg
.dwModifiers
= w32_get_modifiers ();
3337 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3341 /* Hang onto mouse move and scroll messages for a bit, to avoid
3342 sending such events to Emacs faster than it can process them.
3343 If we get more events before the timer from the first message
3344 expires, we just replace the first message. */
3346 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3348 SetTimer (hwnd
, MOUSE_MOVE_ID
,
3349 w32_mouse_move_interval
, NULL
);
3351 /* Hold onto message for now. */
3352 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3353 saved_mouse_move_msg
.msg
.message
= msg
;
3354 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3355 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3356 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3357 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3363 wmsg
.dwModifiers
= w32_get_modifiers ();
3364 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3365 signal_user_input ();
3369 if (w32_pass_multimedia_buttons_to_system
)
3371 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
3372 case WM_MOUSEHWHEEL
:
3373 wmsg
.dwModifiers
= w32_get_modifiers ();
3374 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3375 signal_user_input ();
3376 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3377 handled, to prevent the system trying to handle it by faking
3378 scroll bar events. */
3382 /* Flush out saved messages if necessary. */
3383 if (wParam
== mouse_button_timer
)
3385 if (saved_mouse_button_msg
.msg
.hwnd
)
3387 post_msg (&saved_mouse_button_msg
);
3388 signal_user_input ();
3389 saved_mouse_button_msg
.msg
.hwnd
= 0;
3391 KillTimer (hwnd
, mouse_button_timer
);
3392 mouse_button_timer
= 0;
3394 else if (wParam
== mouse_move_timer
)
3396 if (saved_mouse_move_msg
.msg
.hwnd
)
3398 post_msg (&saved_mouse_move_msg
);
3399 saved_mouse_move_msg
.msg
.hwnd
= 0;
3401 KillTimer (hwnd
, mouse_move_timer
);
3402 mouse_move_timer
= 0;
3404 else if (wParam
== menu_free_timer
)
3406 KillTimer (hwnd
, menu_free_timer
);
3407 menu_free_timer
= 0;
3408 f
= x_window_to_frame (dpyinfo
, hwnd
);
3409 /* If a popup menu is active, don't wipe its strings. */
3411 && current_popup_menu
== NULL
)
3413 /* Free memory used by owner-drawn and help-echo strings. */
3414 w32_free_menu_strings (hwnd
);
3415 f
->output_data
.w32
->menubar_active
= 0;
3419 else if (wParam
== hourglass_timer
)
3421 KillTimer (hwnd
, hourglass_timer
);
3422 hourglass_timer
= 0;
3423 w32_show_hourglass (x_window_to_frame (dpyinfo
, hwnd
));
3428 /* Windows doesn't send us focus messages when putting up and
3429 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3430 The only indication we get that something happened is receiving
3431 this message afterwards. So this is a good time to reset our
3432 keyboard modifiers' state. */
3439 /* We must ensure menu bar is fully constructed and up to date
3440 before allowing user interaction with it. To achieve this
3441 we send this message to the lisp thread and wait for a
3442 reply (whose value is not actually needed) to indicate that
3443 the menu bar is now ready for use, so we can now return.
3445 To remain responsive in the meantime, we enter a nested message
3446 loop that can process all other messages.
3448 However, we skip all this if the message results from calling
3449 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3450 thread a message because it is blocked on us at this point. We
3451 set menubar_active before calling TrackPopupMenu to indicate
3452 this (there is no possibility of confusion with real menubar
3455 f
= x_window_to_frame (dpyinfo
, hwnd
);
3457 && (f
->output_data
.w32
->menubar_active
3458 /* We can receive this message even in the absence of a
3459 menubar (ie. when the system menu is activated) - in this
3460 case we do NOT want to forward the message, otherwise it
3461 will cause the menubar to suddenly appear when the user
3462 had requested it to be turned off! */
3463 || f
->output_data
.w32
->menubar_widget
== NULL
))
3467 deferred_msg msg_buf
;
3469 /* Detect if message has already been deferred; in this case
3470 we cannot return any sensible value to ignore this. */
3471 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3476 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3479 case WM_EXITMENULOOP
:
3480 f
= x_window_to_frame (dpyinfo
, hwnd
);
3482 /* If a menu is still active, check again after a short delay,
3483 since Windows often (always?) sends the WM_EXITMENULOOP
3484 before the corresponding WM_COMMAND message.
3485 Don't do this if a popup menu is active, since it is only
3486 menubar menus that require cleaning up in this way.
3488 if (f
&& menubar_in_use
&& current_popup_menu
== NULL
)
3489 menu_free_timer
= SetTimer (hwnd
, MENU_FREE_ID
, MENU_FREE_DELAY
, NULL
);
3491 /* If hourglass cursor should be displayed, display it now. */
3492 if (f
&& f
->output_data
.w32
->hourglass_p
)
3493 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3498 /* Direct handling of help_echo in menus. Should be safe now
3499 that we generate the help_echo by placing a help event in the
3502 HMENU menu
= (HMENU
) lParam
;
3503 UINT menu_item
= (UINT
) LOWORD (wParam
);
3504 UINT flags
= (UINT
) HIWORD (wParam
);
3506 w32_menu_display_help (hwnd
, menu
, menu_item
, flags
);
3510 case WM_MEASUREITEM
:
3511 f
= x_window_to_frame (dpyinfo
, hwnd
);
3514 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3516 if (pMis
->CtlType
== ODT_MENU
)
3518 /* Work out dimensions for popup menu titles. */
3519 char * title
= (char *) pMis
->itemData
;
3520 HDC hdc
= GetDC (hwnd
);
3521 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3522 LOGFONT menu_logfont
;
3526 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3527 menu_logfont
.lfWeight
= FW_BOLD
;
3528 menu_font
= CreateFontIndirect (&menu_logfont
);
3529 old_font
= SelectObject (hdc
, menu_font
);
3531 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3534 if (unicode_append_menu
)
3535 GetTextExtentPoint32W (hdc
, (WCHAR
*) title
,
3536 wcslen ((WCHAR
*) title
),
3539 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3541 pMis
->itemWidth
= size
.cx
;
3542 if (pMis
->itemHeight
< size
.cy
)
3543 pMis
->itemHeight
= size
.cy
;
3546 pMis
->itemWidth
= 0;
3548 SelectObject (hdc
, old_font
);
3549 DeleteObject (menu_font
);
3550 ReleaseDC (hwnd
, hdc
);
3557 f
= x_window_to_frame (dpyinfo
, hwnd
);
3560 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3562 if (pDis
->CtlType
== ODT_MENU
)
3564 /* Draw popup menu title. */
3565 char * title
= (char *) pDis
->itemData
;
3568 HDC hdc
= pDis
->hDC
;
3569 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3570 LOGFONT menu_logfont
;
3573 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3574 menu_logfont
.lfWeight
= FW_BOLD
;
3575 menu_font
= CreateFontIndirect (&menu_logfont
);
3576 old_font
= SelectObject (hdc
, menu_font
);
3578 /* Always draw title as if not selected. */
3579 if (unicode_append_menu
)
3582 + GetSystemMetrics (SM_CXMENUCHECK
),
3584 ETO_OPAQUE
, &pDis
->rcItem
,
3586 wcslen ((WCHAR
*) title
), NULL
);
3590 + GetSystemMetrics (SM_CXMENUCHECK
),
3592 ETO_OPAQUE
, &pDis
->rcItem
,
3593 title
, strlen (title
), NULL
);
3595 SelectObject (hdc
, old_font
);
3596 DeleteObject (menu_font
);
3604 /* Still not right - can't distinguish between clicks in the
3605 client area of the frame from clicks forwarded from the scroll
3606 bars - may have to hook WM_NCHITTEST to remember the mouse
3607 position and then check if it is in the client area ourselves. */
3608 case WM_MOUSEACTIVATE
:
3609 /* Discard the mouse click that activates a frame, allowing the
3610 user to click anywhere without changing point (or worse!).
3611 Don't eat mouse clicks on scrollbars though!! */
3612 if (LOWORD (lParam
) == HTCLIENT
)
3613 return MA_ACTIVATEANDEAT
;
3618 /* No longer tracking mouse. */
3619 track_mouse_window
= NULL
;
3621 case WM_ACTIVATEAPP
:
3623 case WM_WINDOWPOSCHANGED
:
3625 /* Inform lisp thread that a frame might have just been obscured
3626 or exposed, so should recheck visibility of all frames. */
3627 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3631 dpyinfo
->faked_key
= 0;
3633 register_hot_keys (hwnd
);
3636 unregister_hot_keys (hwnd
);
3639 /* Relinquish the system caret. */
3640 if (w32_system_caret_hwnd
)
3642 w32_visible_system_caret_hwnd
= NULL
;
3643 w32_system_caret_hwnd
= NULL
;
3649 f
= x_window_to_frame (dpyinfo
, hwnd
);
3650 if (f
&& HIWORD (wParam
) == 0)
3652 if (menu_free_timer
)
3654 KillTimer (hwnd
, menu_free_timer
);
3655 menu_free_timer
= 0;
3661 wmsg
.dwModifiers
= w32_get_modifiers ();
3662 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3670 wmsg
.dwModifiers
= w32_get_modifiers ();
3671 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3674 case WM_WINDOWPOSCHANGING
:
3675 /* Don't restrict the sizing of tip frames. */
3676 if (hwnd
== tip_window
)
3680 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3682 wp
.length
= sizeof (WINDOWPLACEMENT
);
3683 GetWindowPlacement (hwnd
, &wp
);
3685 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
3692 DWORD internal_border
;
3693 DWORD scrollbar_extra
;
3696 wp
.length
= sizeof (wp
);
3697 GetWindowRect (hwnd
, &wr
);
3701 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3702 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3703 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3704 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
3708 memset (&rect
, 0, sizeof (rect
));
3709 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3710 GetMenu (hwnd
) != NULL
);
3712 /* Force width and height of client area to be exact
3713 multiples of the character cell dimensions. */
3714 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3715 - 2 * internal_border
- scrollbar_extra
)
3717 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3718 - 2 * internal_border
)
3723 /* For right/bottom sizing we can just fix the sizes.
3724 However for top/left sizing we will need to fix the X
3725 and Y positions as well. */
3727 int cx_mintrack
= GetSystemMetrics (SM_CXMINTRACK
);
3728 int cy_mintrack
= GetSystemMetrics (SM_CYMINTRACK
);
3730 lppos
->cx
= max (lppos
->cx
- wdiff
, cx_mintrack
);
3731 lppos
->cy
= max (lppos
->cy
- hdiff
, cy_mintrack
);
3733 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3734 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3736 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3743 lppos
->flags
|= SWP_NOMOVE
;
3754 case WM_GETMINMAXINFO
:
3755 /* Hack to allow resizing the Emacs frame above the screen size.
3756 Note that Windows 9x limits coordinates to 16-bits. */
3757 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.x
= 32767;
3758 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.y
= 32767;
3762 if (LOWORD (lParam
) == HTCLIENT
)
3764 f
= x_window_to_frame (dpyinfo
, hwnd
);
3765 if (f
->output_data
.w32
->hourglass_p
&& !menubar_in_use
3766 && !current_popup_menu
)
3767 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3769 SetCursor (f
->output_data
.w32
->current_cursor
);
3774 case WM_EMACS_SETCURSOR
:
3776 Cursor cursor
= (Cursor
) wParam
;
3777 f
= x_window_to_frame (dpyinfo
, hwnd
);
3780 f
->output_data
.w32
->current_cursor
= cursor
;
3781 if (!f
->output_data
.w32
->hourglass_p
)
3787 case WM_EMACS_CREATESCROLLBAR
:
3788 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
3789 (struct scroll_bar
*) lParam
);
3791 case WM_EMACS_SHOWWINDOW
:
3792 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
3794 case WM_EMACS_SETFOREGROUND
:
3796 HWND foreground_window
;
3797 DWORD foreground_thread
, retval
;
3799 /* On NT 5.0, and apparently Windows 98, it is necessary to
3800 attach to the thread that currently has focus in order to
3801 pull the focus away from it. */
3802 foreground_window
= GetForegroundWindow ();
3803 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
3804 if (!foreground_window
3805 || foreground_thread
== GetCurrentThreadId ()
3806 || !AttachThreadInput (GetCurrentThreadId (),
3807 foreground_thread
, TRUE
))
3808 foreground_thread
= 0;
3810 retval
= SetForegroundWindow ((HWND
) wParam
);
3812 /* Detach from the previous foreground thread. */
3813 if (foreground_thread
)
3814 AttachThreadInput (GetCurrentThreadId (),
3815 foreground_thread
, FALSE
);
3820 case WM_EMACS_SETWINDOWPOS
:
3822 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
3823 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
3824 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
3827 case WM_EMACS_DESTROYWINDOW
:
3828 DragAcceptFiles ((HWND
) wParam
, FALSE
);
3829 return DestroyWindow ((HWND
) wParam
);
3831 case WM_EMACS_HIDE_CARET
:
3832 return HideCaret (hwnd
);
3834 case WM_EMACS_SHOW_CARET
:
3835 return ShowCaret (hwnd
);
3837 case WM_EMACS_DESTROY_CARET
:
3838 w32_system_caret_hwnd
= NULL
;
3839 w32_visible_system_caret_hwnd
= NULL
;
3840 return DestroyCaret ();
3842 case WM_EMACS_TRACK_CARET
:
3843 /* If there is currently no system caret, create one. */
3844 if (w32_system_caret_hwnd
== NULL
)
3846 /* Use the default caret width, and avoid changing it
3847 unneccesarily, as it confuses screen reader software. */
3848 w32_system_caret_hwnd
= hwnd
;
3849 CreateCaret (hwnd
, NULL
, 0,
3850 w32_system_caret_height
);
3853 if (!SetCaretPos (w32_system_caret_x
, w32_system_caret_y
))
3855 /* Ensure visible caret gets turned on when requested. */
3856 else if (w32_use_visible_system_caret
3857 && w32_visible_system_caret_hwnd
!= hwnd
)
3859 w32_visible_system_caret_hwnd
= hwnd
;
3860 return ShowCaret (hwnd
);
3862 /* Ensure visible caret gets turned off when requested. */
3863 else if (!w32_use_visible_system_caret
3864 && w32_visible_system_caret_hwnd
)
3866 w32_visible_system_caret_hwnd
= NULL
;
3867 return HideCaret (hwnd
);
3872 case WM_EMACS_TRACKPOPUPMENU
:
3877 pos
= (POINT
*)lParam
;
3878 flags
= TPM_CENTERALIGN
;
3879 if (button_state
& LMOUSE
)
3880 flags
|= TPM_LEFTBUTTON
;
3881 else if (button_state
& RMOUSE
)
3882 flags
|= TPM_RIGHTBUTTON
;
3884 /* Remember we did a SetCapture on the initial mouse down event,
3885 so for safety, we make sure the capture is cancelled now. */
3889 /* Use menubar_active to indicate that WM_INITMENU is from
3890 TrackPopupMenu below, and should be ignored. */
3891 f
= x_window_to_frame (dpyinfo
, hwnd
);
3893 f
->output_data
.w32
->menubar_active
= 1;
3895 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
3899 /* Eat any mouse messages during popupmenu */
3900 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
3902 /* Get the menu selection, if any */
3903 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
3905 retval
= LOWORD (amsg
.wParam
);
3921 /* Check for messages registered at runtime. */
3922 if (msg
== msh_mousewheel
)
3924 wmsg
.dwModifiers
= w32_get_modifiers ();
3925 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3926 signal_user_input ();
3931 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
3935 /* The most common default return code for handled messages is 0. */
3940 my_create_window (struct frame
* f
)
3944 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
3946 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3950 /* Create a tooltip window. Unlike my_create_window, we do not do this
3951 indirectly via the Window thread, as we do not need to process Window
3952 messages for the tooltip. Creating tooltips indirectly also creates
3953 deadlocks when tooltips are created for menu items. */
3955 my_create_tip_window (struct frame
*f
)
3959 rect
.left
= rect
.top
= 0;
3960 rect
.right
= FRAME_PIXEL_WIDTH (f
);
3961 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
3963 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
3964 FRAME_EXTERNAL_MENU_BAR (f
));
3966 tip_window
= FRAME_W32_WINDOW (f
)
3967 = CreateWindow (EMACS_CLASS
,
3969 f
->output_data
.w32
->dwStyle
,
3972 rect
.right
- rect
.left
,
3973 rect
.bottom
- rect
.top
,
3974 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
3981 SetWindowLong (tip_window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
3982 SetWindowLong (tip_window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
3983 SetWindowLong (tip_window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
3984 SetWindowLong (tip_window
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
3986 /* Tip frames have no scrollbars. */
3987 SetWindowLong (tip_window
, WND_SCROLLBAR_INDEX
, 0);
3989 /* Do this to discard the default setting specified by our parent. */
3990 ShowWindow (tip_window
, SW_HIDE
);
3995 /* Create and set up the w32 window for frame F. */
3998 w32_window (struct frame
*f
, long window_prompting
, int minibuffer_only
)
4002 /* Use the resource name as the top-level window name
4003 for looking up resources. Make a non-Lisp copy
4004 for the window manager, so GC relocation won't bother it.
4006 Elsewhere we specify the window name for the window manager. */
4009 char *str
= (char *) SDATA (Vx_resource_name
);
4010 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4011 strcpy (f
->namebuf
, str
);
4014 my_create_window (f
);
4016 validate_x_resource_name ();
4018 /* x_set_name normally ignores requests to set the name if the
4019 requested name is the same as the current name. This is the one
4020 place where that assumption isn't correct; f->name is set, but
4021 the server hasn't been told. */
4024 int explicit = f
->explicit_name
;
4026 f
->explicit_name
= 0;
4029 x_set_name (f
, name
, explicit);
4034 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4035 initialize_frame_menubar (f
);
4037 if (FRAME_W32_WINDOW (f
) == 0)
4038 error ("Unable to create window");
4041 /* Handle the icon stuff for this window. Perhaps later we might
4042 want an x_set_icon_position which can be called interactively as
4046 x_icon (struct frame
*f
, Lisp_Object parms
)
4048 Lisp_Object icon_x
, icon_y
;
4049 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4051 /* Set the position of the icon. Note that Windows 95 groups all
4052 icons in the tray. */
4053 icon_x
= x_get_arg (dpyinfo
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4054 icon_y
= x_get_arg (dpyinfo
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4055 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4057 CHECK_NUMBER (icon_x
);
4058 CHECK_NUMBER (icon_y
);
4060 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4061 error ("Both left and top icon corners of icon must be specified");
4065 if (! EQ (icon_x
, Qunbound
))
4066 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4069 /* Start up iconic or window? */
4070 x_wm_set_window_state
4071 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4075 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4085 x_make_gc (struct frame
*f
)
4087 XGCValues gc_values
;
4091 /* Create the GC's of this frame.
4092 Note that many default values are used. */
4095 gc_values
.font
= FRAME_FONT (f
);
4097 /* Cursor has cursor-color background, background-color foreground. */
4098 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
4099 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
4100 f
->output_data
.w32
->cursor_gc
4101 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
4102 (GCFont
| GCForeground
| GCBackground
),
4106 f
->output_data
.w32
->white_relief
.gc
= 0;
4107 f
->output_data
.w32
->black_relief
.gc
= 0;
4113 /* Handler for signals raised during x_create_frame and
4114 x_create_top_frame. FRAME is the frame which is partially
4118 unwind_create_frame (Lisp_Object frame
)
4120 struct frame
*f
= XFRAME (frame
);
4122 /* If frame is ``official'', nothing to do. */
4123 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4126 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4129 x_free_frame_resources (f
);
4132 /* Check that reference counts are indeed correct. */
4133 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4134 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4143 x_default_font_parameter (struct frame
*f
, Lisp_Object parms
)
4145 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4146 Lisp_Object font_param
= x_get_arg (dpyinfo
, parms
, Qfont
, NULL
, NULL
,
4149 if (EQ (font_param
, Qunbound
))
4151 font
= !NILP (font_param
) ? font_param
4152 : x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4154 if (!STRINGP (font
))
4157 static char *names
[]
4158 = { "Courier New-10",
4159 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4160 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4164 for (i
= 0; names
[i
]; i
++)
4166 font
= font_open_by_name (f
, names
[i
]);
4171 error ("No suitable font was found");
4173 else if (!NILP (font_param
))
4175 /* Remember the explicit font parameter, so we can re-apply it after
4176 we've applied the `default' face settings. */
4177 x_set_frame_parameters (f
, Fcons (Fcons (Qfont_param
, font_param
), Qnil
));
4179 x_default_parameter (f
, parms
, Qfont
, font
, "font", "Font", RES_TYPE_STRING
);
4182 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4184 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
4185 Return an Emacs frame object.
4186 PARAMETERS is an alist of frame parameters.
4187 If the parameters specify that the frame should not have a minibuffer,
4188 and do not specify a specific minibuffer window to use,
4189 then `default-minibuffer-frame' must be a frame whose minibuffer can
4190 be shared by the new frame.
4192 This function is an internal primitive--use `make-frame' instead. */)
4193 (Lisp_Object parameters
)
4196 Lisp_Object frame
, tem
;
4198 int minibuffer_only
= 0;
4199 long window_prompting
= 0;
4201 int count
= SPECPDL_INDEX ();
4202 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4203 Lisp_Object display
;
4204 struct w32_display_info
*dpyinfo
= NULL
;
4208 /* Make copy of frame parameters because the original is in pure
4210 parameters
= Fcopy_alist (parameters
);
4212 /* Use this general default value to start with
4213 until we know if this frame has a specified name. */
4214 Vx_resource_name
= Vinvocation_name
;
4216 display
= x_get_arg (dpyinfo
, parameters
, Qterminal
, 0, 0, RES_TYPE_NUMBER
);
4217 if (EQ (display
, Qunbound
))
4218 display
= x_get_arg (dpyinfo
, parameters
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4219 if (EQ (display
, Qunbound
))
4221 dpyinfo
= check_x_display_info (display
);
4222 kb
= dpyinfo
->terminal
->kboard
;
4224 if (!dpyinfo
->terminal
->name
)
4225 error ("Terminal is not live, can't create new frames on it");
4227 name
= x_get_arg (dpyinfo
, parameters
, Qname
, "name", "Name", RES_TYPE_STRING
);
4229 && ! EQ (name
, Qunbound
)
4231 error ("Invalid frame name--not a string or nil");
4234 Vx_resource_name
= name
;
4236 /* See if parent window is specified. */
4237 parent
= x_get_arg (dpyinfo
, parameters
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4238 if (EQ (parent
, Qunbound
))
4240 if (! NILP (parent
))
4241 CHECK_NUMBER (parent
);
4243 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4244 /* No need to protect DISPLAY because that's not used after passing
4245 it to make_frame_without_minibuffer. */
4247 GCPRO4 (parameters
, parent
, name
, frame
);
4248 tem
= x_get_arg (dpyinfo
, parameters
, Qminibuffer
, "minibuffer", "Minibuffer",
4250 if (EQ (tem
, Qnone
) || NILP (tem
))
4251 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4252 else if (EQ (tem
, Qonly
))
4254 f
= make_minibuffer_frame ();
4255 minibuffer_only
= 1;
4257 else if (WINDOWP (tem
))
4258 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4262 XSETFRAME (frame
, f
);
4264 /* Note that Windows does support scroll bars. */
4265 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4267 /* By default, make scrollbars the system standard width. */
4268 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
4270 f
->terminal
= dpyinfo
->terminal
;
4271 f
->terminal
->reference_count
++;
4273 f
->output_method
= output_w32
;
4274 f
->output_data
.w32
=
4275 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4276 memset (f
->output_data
.w32
, 0, sizeof (struct w32_output
));
4277 FRAME_FONTSET (f
) = -1;
4280 = x_get_arg (dpyinfo
, parameters
, Qicon_name
, "iconName", "Title",
4282 if (! STRINGP (f
->icon_name
))
4283 f
->icon_name
= Qnil
;
4285 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4287 /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
4288 record_unwind_protect (unwind_create_frame
, frame
);
4290 image_cache_refcount
= FRAME_IMAGE_CACHE (f
)->refcount
;
4291 dpyinfo_refcount
= dpyinfo
->reference_count
;
4292 #endif /* GLYPH_DEBUG */
4294 /* Specify the parent under which to make this window. */
4298 f
->output_data
.w32
->parent_desc
= (Window
) XFASTINT (parent
);
4299 f
->output_data
.w32
->explicit_parent
= 1;
4303 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4304 f
->output_data
.w32
->explicit_parent
= 0;
4307 /* Set the name; the functions to which we pass f expect the name to
4309 if (EQ (name
, Qunbound
) || NILP (name
))
4311 f
->name
= build_string (dpyinfo
->w32_id_name
);
4312 f
->explicit_name
= 0;
4317 f
->explicit_name
= 1;
4318 /* use the frame's title when getting resources for this frame. */
4319 specbind (Qx_resource_name
, name
);
4322 f
->resx
= dpyinfo
->resx
;
4323 f
->resy
= dpyinfo
->resy
;
4325 if (uniscribe_available
)
4326 register_font_driver (&uniscribe_font_driver
, f
);
4327 register_font_driver (&w32font_driver
, f
);
4329 x_default_parameter (f
, parameters
, Qfont_backend
, Qnil
,
4330 "fontBackend", "FontBackend", RES_TYPE_STRING
);
4331 /* Extract the window parameters from the supplied values
4332 that are needed to determine window geometry. */
4333 x_default_font_parameter (f
, parameters
);
4334 x_default_parameter (f
, parameters
, Qborder_width
, make_number (2),
4335 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4337 /* We recognize either internalBorderWidth or internalBorder
4338 (which is what xterm calls it). */
4339 if (NILP (Fassq (Qinternal_border_width
, parameters
)))
4343 value
= x_get_arg (dpyinfo
, parameters
, Qinternal_border_width
,
4344 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
4345 if (! EQ (value
, Qunbound
))
4346 parameters
= Fcons (Fcons (Qinternal_border_width
, value
),
4349 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4350 x_default_parameter (f
, parameters
, Qinternal_border_width
, make_number (0),
4351 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4352 x_default_parameter (f
, parameters
, Qvertical_scroll_bars
, Qright
,
4353 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4355 /* Also do the stuff which must be set before the window exists. */
4356 x_default_parameter (f
, parameters
, Qforeground_color
, build_string ("black"),
4357 "foreground", "Foreground", RES_TYPE_STRING
);
4358 x_default_parameter (f
, parameters
, Qbackground_color
, build_string ("white"),
4359 "background", "Background", RES_TYPE_STRING
);
4360 x_default_parameter (f
, parameters
, Qmouse_color
, build_string ("black"),
4361 "pointerColor", "Foreground", RES_TYPE_STRING
);
4362 x_default_parameter (f
, parameters
, Qcursor_color
, build_string ("black"),
4363 "cursorColor", "Foreground", RES_TYPE_STRING
);
4364 x_default_parameter (f
, parameters
, Qborder_color
, build_string ("black"),
4365 "borderColor", "BorderColor", RES_TYPE_STRING
);
4366 x_default_parameter (f
, parameters
, Qscreen_gamma
, Qnil
,
4367 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4368 x_default_parameter (f
, parameters
, Qline_spacing
, Qnil
,
4369 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4370 x_default_parameter (f
, parameters
, Qleft_fringe
, Qnil
,
4371 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4372 x_default_parameter (f
, parameters
, Qright_fringe
, Qnil
,
4373 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4376 /* Init faces before x_default_parameter is called for scroll-bar
4377 parameters because that function calls x_set_scroll_bar_width,
4378 which calls change_frame_size, which calls Fset_window_buffer,
4379 which runs hooks, which call Fvertical_motion. At the end, we
4380 end up in init_iterator with a null face cache, which should not
4382 init_frame_faces (f
);
4384 /* The X resources controlling the menu-bar and tool-bar are
4385 processed specially at startup, and reflected in the mode
4386 variables; ignore them here. */
4387 x_default_parameter (f
, parameters
, Qmenu_bar_lines
,
4388 NILP (Vmenu_bar_mode
)
4389 ? make_number (0) : make_number (1),
4390 NULL
, NULL
, RES_TYPE_NUMBER
);
4391 x_default_parameter (f
, parameters
, Qtool_bar_lines
,
4392 NILP (Vtool_bar_mode
)
4393 ? make_number (0) : make_number (1),
4394 NULL
, NULL
, RES_TYPE_NUMBER
);
4396 x_default_parameter (f
, parameters
, Qbuffer_predicate
, Qnil
,
4397 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
4398 x_default_parameter (f
, parameters
, Qtitle
, Qnil
,
4399 "title", "Title", RES_TYPE_STRING
);
4400 x_default_parameter (f
, parameters
, Qfullscreen
, Qnil
,
4401 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4403 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4404 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4406 f
->output_data
.w32
->text_cursor
= w32_load_cursor (IDC_IBEAM
);
4407 f
->output_data
.w32
->nontext_cursor
= w32_load_cursor (IDC_ARROW
);
4408 f
->output_data
.w32
->modeline_cursor
= w32_load_cursor (IDC_ARROW
);
4409 f
->output_data
.w32
->hand_cursor
= w32_load_cursor (IDC_HAND
);
4410 f
->output_data
.w32
->hourglass_cursor
= w32_load_cursor (IDC_WAIT
);
4411 f
->output_data
.w32
->horizontal_drag_cursor
= w32_load_cursor (IDC_SIZEWE
);
4413 f
->output_data
.w32
->current_cursor
= f
->output_data
.w32
->nontext_cursor
;
4415 window_prompting
= x_figure_window_size (f
, parameters
, 1);
4417 tem
= x_get_arg (dpyinfo
, parameters
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4418 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4420 w32_window (f
, window_prompting
, minibuffer_only
);
4421 x_icon (f
, parameters
);
4425 /* Now consider the frame official. */
4426 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4427 Vframe_list
= Fcons (frame
, Vframe_list
);
4429 /* We need to do this after creating the window, so that the
4430 icon-creation functions can say whose icon they're describing. */
4431 x_default_parameter (f
, parameters
, Qicon_type
, Qnil
,
4432 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4434 x_default_parameter (f
, parameters
, Qauto_raise
, Qnil
,
4435 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4436 x_default_parameter (f
, parameters
, Qauto_lower
, Qnil
,
4437 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4438 x_default_parameter (f
, parameters
, Qcursor_type
, Qbox
,
4439 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4440 x_default_parameter (f
, parameters
, Qscroll_bar_width
, Qnil
,
4441 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4442 x_default_parameter (f
, parameters
, Qalpha
, Qnil
,
4443 "alpha", "Alpha", RES_TYPE_NUMBER
);
4445 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4446 Change will not be effected unless different from the current
4448 width
= FRAME_COLS (f
);
4449 height
= FRAME_LINES (f
);
4451 FRAME_LINES (f
) = 0;
4452 SET_FRAME_COLS (f
, 0);
4453 change_frame_size (f
, height
, width
, 1, 0, 0);
4455 /* Tell the server what size and position, etc, we want, and how
4456 badly we want them. This should be done after we have the menu
4457 bar so that its size can be taken into account. */
4459 x_wm_set_size_hint (f
, window_prompting
, 0);
4462 /* Make the window appear on the frame and enable display, unless
4463 the caller says not to. However, with explicit parent, Emacs
4464 cannot control visibility, so don't try. */
4465 if (! f
->output_data
.w32
->explicit_parent
)
4467 Lisp_Object visibility
;
4469 visibility
= x_get_arg (dpyinfo
, parameters
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4470 if (EQ (visibility
, Qunbound
))
4473 if (EQ (visibility
, Qicon
))
4474 x_iconify_frame (f
);
4475 else if (! NILP (visibility
))
4476 x_make_frame_visible (f
);
4478 /* Must have been Qnil. */
4482 /* Initialize `default-minibuffer-frame' in case this is the first
4483 frame on this terminal. */
4484 if (FRAME_HAS_MINIBUF_P (f
)
4485 && (!FRAMEP (kb
->Vdefault_minibuffer_frame
)
4486 || !FRAME_LIVE_P (XFRAME (kb
->Vdefault_minibuffer_frame
))))
4487 kb
->Vdefault_minibuffer_frame
= frame
;
4489 /* All remaining specified parameters, which have not been "used"
4490 by x_get_arg and friends, now go in the misc. alist of the frame. */
4491 for (tem
= parameters
; CONSP (tem
); tem
= XCDR (tem
))
4492 if (CONSP (XCAR (tem
)) && !NILP (XCAR (XCAR (tem
))))
4493 f
->param_alist
= Fcons (XCAR (tem
), f
->param_alist
);
4497 /* Make sure windows on this frame appear in calls to next-window
4498 and similar functions. */
4499 Vwindow_list
= Qnil
;
4501 return unbind_to (count
, frame
);
4504 /* FRAME is used only to get a handle on the X display. We don't pass the
4505 display info directly because we're called from frame.c, which doesn't
4506 know about that structure. */
4508 x_get_focus_frame (struct frame
*frame
)
4510 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4512 if (! dpyinfo
->w32_focus_frame
)
4515 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4519 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4520 doc
: /* Give FRAME input focus, raising to foreground if necessary. */)
4523 x_focus_on_frame (check_x_frame (frame
));
4528 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4529 doc
: /* Internal function called by `color-defined-p', which see. */)
4530 (Lisp_Object color
, Lisp_Object frame
)
4533 FRAME_PTR f
= check_x_frame (frame
);
4535 CHECK_STRING (color
);
4537 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
4543 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4544 doc
: /* Internal function called by `color-values', which see. */)
4545 (Lisp_Object color
, Lisp_Object frame
)
4548 FRAME_PTR f
= check_x_frame (frame
);
4550 CHECK_STRING (color
);
4552 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
4553 return list3 (make_number ((GetRValue (foo
.pixel
) << 8)
4554 | GetRValue (foo
.pixel
)),
4555 make_number ((GetGValue (foo
.pixel
) << 8)
4556 | GetGValue (foo
.pixel
)),
4557 make_number ((GetBValue (foo
.pixel
) << 8)
4558 | GetBValue (foo
.pixel
)));
4563 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4564 doc
: /* Internal function called by `display-color-p', which see. */)
4565 (Lisp_Object display
)
4567 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4569 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
4575 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
,
4576 Sx_display_grayscale_p
, 0, 1, 0,
4577 doc
: /* Return t if DISPLAY supports shades of gray.
4578 Note that color displays do support shades of gray.
4579 The optional argument DISPLAY specifies which display to ask about.
4580 DISPLAY should be either a frame or a display name (a string).
4581 If omitted or nil, that stands for the selected frame's display. */)
4582 (Lisp_Object display
)
4584 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4586 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
4592 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
,
4593 Sx_display_pixel_width
, 0, 1, 0,
4594 doc
: /* Return the width in pixels of DISPLAY.
4595 The optional argument DISPLAY specifies which display to ask about.
4596 DISPLAY should be either a frame or a display name (a string).
4597 If omitted or nil, that stands for the selected frame's display. */)
4598 (Lisp_Object display
)
4600 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4602 return make_number (x_display_pixel_width (dpyinfo
));
4605 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4606 Sx_display_pixel_height
, 0, 1, 0,
4607 doc
: /* Return the height in pixels of DISPLAY.
4608 The optional argument DISPLAY specifies which display to ask about.
4609 DISPLAY should be either a frame or a display name (a string).
4610 If omitted or nil, that stands for the selected frame's display. */)
4611 (Lisp_Object display
)
4613 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4615 return make_number (x_display_pixel_height (dpyinfo
));
4618 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4620 doc
: /* Return the number of bitplanes of DISPLAY.
4621 The optional argument DISPLAY specifies which display to ask about.
4622 DISPLAY should be either a frame or a display name (a string).
4623 If omitted or nil, that stands for the selected frame's display. */)
4624 (Lisp_Object display
)
4626 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4628 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
4631 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4633 doc
: /* Return the number of color cells of DISPLAY.
4634 The optional argument DISPLAY specifies which display to ask about.
4635 DISPLAY should be either a frame or a display name (a string).
4636 If omitted or nil, that stands for the selected frame's display. */)
4637 (Lisp_Object display
)
4639 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4643 hdc
= GetDC (dpyinfo
->root_window
);
4644 if (dpyinfo
->has_palette
)
4645 cap
= GetDeviceCaps (hdc
, SIZEPALETTE
);
4647 cap
= GetDeviceCaps (hdc
, NUMCOLORS
);
4649 /* We force 24+ bit depths to 24-bit, both to prevent an overflow
4650 and because probably is more meaningful on Windows anyway */
4652 cap
= 1 << min (dpyinfo
->n_planes
* dpyinfo
->n_cbits
, 24);
4654 ReleaseDC (dpyinfo
->root_window
, hdc
);
4656 return make_number (cap
);
4659 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4660 Sx_server_max_request_size
,
4662 doc
: /* Return the maximum request size of the server of DISPLAY.
4663 The optional argument DISPLAY specifies which display to ask about.
4664 DISPLAY should be either a frame or a display name (a string).
4665 If omitted or nil, that stands for the selected frame's display. */)
4666 (Lisp_Object display
)
4668 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4670 return make_number (1);
4673 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
4674 doc
: /* Return the "vendor ID" string of the W32 system (Microsoft).
4675 The optional argument DISPLAY specifies which display to ask about.
4676 DISPLAY should be either a frame or a display name (a string).
4677 If omitted or nil, that stands for the selected frame's display. */)
4678 (Lisp_Object display
)
4680 return build_string ("Microsoft Corp.");
4683 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
4684 doc
: /* Return the version numbers of the server of DISPLAY.
4685 The value is a list of three integers: the major and minor
4686 version numbers of the X Protocol in use, and the distributor-specific
4687 release number. See also the function `x-server-vendor'.
4689 The optional argument DISPLAY specifies which display to ask about.
4690 DISPLAY should be either a frame or a display name (a string).
4691 If omitted or nil, that stands for the selected frame's display. */)
4692 (Lisp_Object display
)
4694 return Fcons (make_number (w32_major_version
),
4695 Fcons (make_number (w32_minor_version
),
4696 Fcons (make_number (w32_build_number
), Qnil
)));
4699 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
4700 doc
: /* Return the number of screens on the server of DISPLAY.
4701 The optional argument DISPLAY specifies which display to ask about.
4702 DISPLAY should be either a frame or a display name (a string).
4703 If omitted or nil, that stands for the selected frame's display. */)
4704 (Lisp_Object display
)
4706 return make_number (1);
4709 DEFUN ("x-display-mm-height", Fx_display_mm_height
,
4710 Sx_display_mm_height
, 0, 1, 0,
4711 doc
: /* Return the height in millimeters of DISPLAY.
4712 The optional argument DISPLAY specifies which display to ask about.
4713 DISPLAY should be either a frame or a display name (a string).
4714 If omitted or nil, that stands for the selected frame's display. */)
4715 (Lisp_Object display
)
4717 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4721 hdc
= GetDC (dpyinfo
->root_window
);
4723 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
4725 ReleaseDC (dpyinfo
->root_window
, hdc
);
4727 return make_number (cap
);
4730 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
4731 doc
: /* Return the width in millimeters of DISPLAY.
4732 The optional argument DISPLAY specifies which display to ask about.
4733 DISPLAY should be either a frame or a display name (a string).
4734 If omitted or nil, that stands for the selected frame's display. */)
4735 (Lisp_Object display
)
4737 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4742 hdc
= GetDC (dpyinfo
->root_window
);
4744 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
4746 ReleaseDC (dpyinfo
->root_window
, hdc
);
4748 return make_number (cap
);
4751 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
4752 Sx_display_backing_store
, 0, 1, 0,
4753 doc
: /* Return an indication of whether DISPLAY does backing store.
4754 The value may be `always', `when-mapped', or `not-useful'.
4755 The optional argument DISPLAY specifies which display to ask about.
4756 DISPLAY should be either a frame or a display name (a string).
4757 If omitted or nil, that stands for the selected frame's display. */)
4758 (Lisp_Object display
)
4760 return intern ("not-useful");
4763 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
4764 Sx_display_visual_class
, 0, 1, 0,
4765 doc
: /* Return the visual class of DISPLAY.
4766 The value is one of the symbols `static-gray', `gray-scale',
4767 `static-color', `pseudo-color', `true-color', or `direct-color'.
4769 The optional argument DISPLAY specifies which display to ask about.
4770 DISPLAY should be either a frame or a display name (a string).
4771 If omitted or nil, that stands for the selected frame's display. */)
4772 (Lisp_Object display
)
4774 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4775 Lisp_Object result
= Qnil
;
4777 if (dpyinfo
->has_palette
)
4778 result
= intern ("pseudo-color");
4779 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 1)
4780 result
= intern ("static-grey");
4781 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 4)
4782 result
= intern ("static-color");
4783 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
> 8)
4784 result
= intern ("true-color");
4789 DEFUN ("x-display-save-under", Fx_display_save_under
,
4790 Sx_display_save_under
, 0, 1, 0,
4791 doc
: /* Return t if DISPLAY supports the save-under feature.
4792 The optional argument DISPLAY specifies which display to ask about.
4793 DISPLAY should be either a frame or a display name (a string).
4794 If omitted or nil, that stands for the selected frame's display. */)
4795 (Lisp_Object display
)
4801 x_pixel_width (register struct frame
*f
)
4803 return FRAME_PIXEL_WIDTH (f
);
4807 x_pixel_height (register struct frame
*f
)
4809 return FRAME_PIXEL_HEIGHT (f
);
4813 x_char_width (register struct frame
*f
)
4815 return FRAME_COLUMN_WIDTH (f
);
4819 x_char_height (register struct frame
*f
)
4821 return FRAME_LINE_HEIGHT (f
);
4825 x_screen_planes (register struct frame
*f
)
4827 return FRAME_W32_DISPLAY_INFO (f
)->n_planes
;
4830 /* Return the display structure for the display named NAME.
4831 Open a new connection if necessary. */
4833 struct w32_display_info
*
4834 x_display_info_for_name (Lisp_Object name
)
4837 struct w32_display_info
*dpyinfo
;
4839 CHECK_STRING (name
);
4841 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
4843 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4846 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4851 /* Use this general default value to start with. */
4852 Vx_resource_name
= Vinvocation_name
;
4854 validate_x_resource_name ();
4856 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
4857 (char *) SDATA (Vx_resource_name
));
4860 error ("Cannot connect to server %s", SDATA (name
));
4863 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
4868 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4869 1, 3, 0, doc
: /* Open a connection to a server.
4870 DISPLAY is the name of the display to connect to.
4871 Optional second arg XRM-STRING is a string of resources in xrdb format.
4872 If the optional third arg MUST-SUCCEED is non-nil,
4873 terminate Emacs if we can't open the connection. */)
4874 (Lisp_Object display
, Lisp_Object xrm_string
, Lisp_Object must_succeed
)
4876 unsigned char *xrm_option
;
4877 struct w32_display_info
*dpyinfo
;
4879 /* If initialization has already been done, return now to avoid
4880 overwriting critical parts of one_w32_display_info. */
4884 CHECK_STRING (display
);
4885 if (! NILP (xrm_string
))
4886 CHECK_STRING (xrm_string
);
4889 if (! EQ (Vwindow_system
, intern ("w32")))
4890 error ("Not using Microsoft Windows");
4893 /* Allow color mapping to be defined externally; first look in user's
4894 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
4896 Lisp_Object color_file
;
4897 struct gcpro gcpro1
;
4899 color_file
= build_string ("~/rgb.txt");
4901 GCPRO1 (color_file
);
4903 if (NILP (Ffile_readable_p (color_file
)))
4905 Fexpand_file_name (build_string ("rgb.txt"),
4906 Fsymbol_value (intern ("data-directory")));
4908 Vw32_color_map
= Fx_load_color_file (color_file
);
4912 if (NILP (Vw32_color_map
))
4913 Vw32_color_map
= Fw32_default_color_map ();
4915 /* Merge in system logical colors. */
4916 add_system_logical_colors_to_map (&Vw32_color_map
);
4918 if (! NILP (xrm_string
))
4919 xrm_option
= (unsigned char *) SDATA (xrm_string
);
4921 xrm_option
= (unsigned char *) 0;
4923 /* Use this general default value to start with. */
4924 /* First remove .exe suffix from invocation-name - it looks ugly. */
4926 char basename
[ MAX_PATH
], *str
;
4928 strcpy (basename
, SDATA (Vinvocation_name
));
4929 str
= strrchr (basename
, '.');
4931 Vinvocation_name
= build_string (basename
);
4933 Vx_resource_name
= Vinvocation_name
;
4935 validate_x_resource_name ();
4937 /* This is what opens the connection and sets x_current_display.
4938 This also initializes many symbols, such as those used for input. */
4939 dpyinfo
= w32_term_init (display
, xrm_option
,
4940 (char *) SDATA (Vx_resource_name
));
4944 if (!NILP (must_succeed
))
4945 fatal ("Cannot connect to server %s.\n",
4948 error ("Cannot connect to server %s", SDATA (display
));
4953 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
4957 DEFUN ("x-close-connection", Fx_close_connection
,
4958 Sx_close_connection
, 1, 1, 0,
4959 doc
: /* Close the connection to DISPLAY's server.
4960 For DISPLAY, specify either a frame or a display name (a string).
4961 If DISPLAY is nil, that stands for the selected frame's display. */)
4962 (Lisp_Object display
)
4964 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4967 if (dpyinfo
->reference_count
> 0)
4968 error ("Display still has frames on it");
4971 x_destroy_all_bitmaps (dpyinfo
);
4973 x_delete_display (dpyinfo
);
4979 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
4980 doc
: /* Return the list of display names that Emacs has connections to. */)
4983 Lisp_Object tail
, result
;
4986 for (tail
= w32_display_name_list
; CONSP (tail
); tail
= XCDR (tail
))
4987 result
= Fcons (XCAR (XCAR (tail
)), result
);
4992 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
4993 doc
: /* This is a noop on W32 systems. */)
4994 (Lisp_Object on
, Lisp_Object display
)
5001 /***********************************************************************
5003 ***********************************************************************/
5005 DEFUN ("x-change-window-property", Fx_change_window_property
,
5006 Sx_change_window_property
, 2, 6, 0,
5007 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
5008 VALUE may be a string or a list of conses, numbers and/or strings.
5009 If an element in the list is a string, it is converted to
5010 an Atom and the value of the Atom is used. If an element is a cons,
5011 it is converted to a 32 bit number where the car is the 16 top bits and the
5012 cdr is the lower 16 bits.
5013 FRAME nil or omitted means use the selected frame.
5014 If TYPE is given and non-nil, it is the name of the type of VALUE.
5015 If TYPE is not given or nil, the type is STRING.
5016 FORMAT gives the size in bits of each element if VALUE is a list.
5017 It must be one of 8, 16 or 32.
5018 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5019 If OUTER_P is non-nil, the property is changed for the outer X window of
5020 FRAME. Default is to change on the edit X window.
5023 (Lisp_Object prop
, Lisp_Object value
, Lisp_Object frame
, Lisp_Object type
, Lisp_Object format
, Lisp_Object outer_p
)
5025 #if 0 /* TODO : port window properties to W32 */
5026 struct frame
*f
= check_x_frame (frame
);
5029 CHECK_STRING (prop
);
5030 CHECK_STRING (value
);
5033 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5034 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5035 prop_atom
, XA_STRING
, 8, PropModeReplace
,
5036 SDATA (value
), SCHARS (value
));
5038 /* Make sure the property is set when we return. */
5039 XFlush (FRAME_W32_DISPLAY (f
));
5048 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
5049 Sx_delete_window_property
, 1, 2, 0,
5050 doc
: /* Remove window property PROP from X window of FRAME.
5051 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5052 (Lisp_Object prop
, Lisp_Object frame
)
5054 #if 0 /* TODO : port window properties to W32 */
5056 struct frame
*f
= check_x_frame (frame
);
5059 CHECK_STRING (prop
);
5061 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5062 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
5064 /* Make sure the property is removed when we return. */
5065 XFlush (FRAME_W32_DISPLAY (f
));
5073 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
5075 doc
: /* Value is the value of window property PROP on FRAME.
5076 If FRAME is nil or omitted, use the selected frame. Value is nil
5077 if FRAME hasn't a property with name PROP or if PROP has no string
5079 (Lisp_Object prop
, Lisp_Object frame
)
5081 #if 0 /* TODO : port window properties to W32 */
5083 struct frame
*f
= check_x_frame (frame
);
5086 Lisp_Object prop_value
= Qnil
;
5087 char *tmp_data
= NULL
;
5090 unsigned long actual_size
, bytes_remaining
;
5092 CHECK_STRING (prop
);
5094 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5095 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5096 prop_atom
, 0, 0, False
, XA_STRING
,
5097 &actual_type
, &actual_format
, &actual_size
,
5098 &bytes_remaining
, (unsigned char **) &tmp_data
);
5101 int size
= bytes_remaining
;
5106 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5107 prop_atom
, 0, bytes_remaining
,
5109 &actual_type
, &actual_format
,
5110 &actual_size
, &bytes_remaining
,
5111 (unsigned char **) &tmp_data
);
5113 prop_value
= make_string (tmp_data
, size
);
5128 /***********************************************************************
5130 ***********************************************************************/
5132 /* Default number of seconds to wait before displaying an hourglass
5133 cursor. Duplicated from xdisp.c, but cannot use the version there
5134 due to lack of atimers on w32. */
5135 #define DEFAULT_HOURGLASS_DELAY 1
5136 extern Lisp_Object Vhourglass_delay
;
5138 /* Return non-zero if houglass timer has been started or hourglass is shown. */
5139 /* PENDING: if W32 can use atimers (atimer.[hc]) then the common impl in
5140 xdisp.c could be used. */
5143 hourglass_started (void)
5145 return hourglass_shown_p
|| hourglass_timer
;
5148 /* Cancel a currently active hourglass timer, and start a new one. */
5151 start_hourglass (void)
5154 int secs
, msecs
= 0;
5155 struct frame
* f
= SELECTED_FRAME ();
5157 /* No cursors on non GUI frames. */
5158 if (!FRAME_W32_P (f
))
5161 cancel_hourglass ();
5163 if (INTEGERP (Vhourglass_delay
)
5164 && XINT (Vhourglass_delay
) > 0)
5165 secs
= XFASTINT (Vhourglass_delay
);
5166 else if (FLOATP (Vhourglass_delay
)
5167 && XFLOAT_DATA (Vhourglass_delay
) > 0)
5170 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
5171 secs
= XFASTINT (tem
);
5172 msecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000;
5175 secs
= DEFAULT_HOURGLASS_DELAY
;
5177 delay
= secs
* 1000 + msecs
;
5178 hourglass_hwnd
= FRAME_W32_WINDOW (f
);
5179 hourglass_timer
= SetTimer (hourglass_hwnd
, HOURGLASS_ID
, delay
, NULL
);
5183 /* Cancel the hourglass cursor timer if active, hide an hourglass
5187 cancel_hourglass (void)
5189 if (hourglass_timer
)
5191 KillTimer (hourglass_hwnd
, hourglass_timer
);
5192 hourglass_timer
= 0;
5195 if (hourglass_shown_p
)
5196 w32_hide_hourglass ();
5200 /* Timer function of hourglass_timer.
5202 Display an hourglass cursor. Set the hourglass_p flag in display info
5203 to indicate that an hourglass cursor is shown. */
5206 w32_show_hourglass (struct frame
*f
)
5208 if (!hourglass_shown_p
)
5210 f
->output_data
.w32
->hourglass_p
= 1;
5211 if (!menubar_in_use
&& !current_popup_menu
)
5212 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
5213 hourglass_shown_p
= 1;
5218 /* Hide the hourglass cursor on all frames, if it is currently shown. */
5221 w32_hide_hourglass (void)
5223 if (hourglass_shown_p
)
5225 struct frame
*f
= x_window_to_frame (&one_w32_display_info
,
5228 f
->output_data
.w32
->hourglass_p
= 0;
5230 /* If frame was deleted, restore to selected frame's cursor. */
5231 f
= SELECTED_FRAME ();
5233 if (FRAME_W32_P (f
))
5234 SetCursor (f
->output_data
.w32
->current_cursor
);
5236 /* No cursors on non GUI frames - restore to stock arrow cursor. */
5237 SetCursor (w32_load_cursor (IDC_ARROW
));
5239 hourglass_shown_p
= 0;
5245 /***********************************************************************
5247 ***********************************************************************/
5249 static Lisp_Object
x_create_tip_frame (struct w32_display_info
*,
5250 Lisp_Object
, Lisp_Object
);
5251 static void compute_tip_xy (struct frame
*, Lisp_Object
, Lisp_Object
,
5252 Lisp_Object
, int, int, int *, int *);
5254 /* The frame of a currently visible tooltip. */
5256 Lisp_Object tip_frame
;
5258 /* If non-nil, a timer started that hides the last tooltip when it
5261 Lisp_Object tip_timer
;
5264 /* If non-nil, a vector of 3 elements containing the last args
5265 with which x-show-tip was called. See there. */
5267 Lisp_Object last_show_tip_args
;
5269 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
5271 Lisp_Object Vx_max_tooltip_size
;
5275 unwind_create_tip_frame (Lisp_Object frame
)
5277 Lisp_Object deleted
;
5279 deleted
= unwind_create_frame (frame
);
5280 if (EQ (deleted
, Qt
))
5290 /* Create a frame for a tooltip on the display described by DPYINFO.
5291 PARMS is a list of frame parameters. TEXT is the string to
5292 display in the tip frame. Value is the frame.
5294 Note that functions called here, esp. x_default_parameter can
5295 signal errors, for instance when a specified color name is
5296 undefined. We have to make sure that we're in a consistent state
5297 when this happens. */
5300 x_create_tip_frame (struct w32_display_info
*dpyinfo
,
5301 Lisp_Object parms
, Lisp_Object text
)
5304 Lisp_Object frame
, tem
;
5306 long window_prompting
= 0;
5308 int count
= SPECPDL_INDEX ();
5309 struct gcpro gcpro1
, gcpro2
, gcpro3
;
5311 int face_change_count_before
= face_change_count
;
5313 struct buffer
*old_buffer
;
5317 /* Use this general default value to start with until we know if
5318 this frame has a specified name. */
5319 Vx_resource_name
= Vinvocation_name
;
5321 kb
= dpyinfo
->terminal
->kboard
;
5323 /* The calls to x_get_arg remove elements from PARMS, so copy it to
5324 avoid destructive changes behind our caller's back. */
5325 parms
= Fcopy_alist (parms
);
5327 /* Get the name of the frame to use for resource lookup. */
5328 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
5330 && !EQ (name
, Qunbound
)
5332 error ("Invalid frame name--not a string or nil");
5333 Vx_resource_name
= name
;
5336 GCPRO3 (parms
, name
, frame
);
5337 /* Make a frame without minibuffer nor mode-line. */
5339 f
->wants_modeline
= 0;
5340 XSETFRAME (frame
, f
);
5342 buffer
= Fget_buffer_create (build_string (" *tip*"));
5343 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
, Qnil
);
5344 old_buffer
= current_buffer
;
5345 set_buffer_internal_1 (XBUFFER (buffer
));
5346 current_buffer
->truncate_lines
= Qnil
;
5347 specbind (Qinhibit_read_only
, Qt
);
5348 specbind (Qinhibit_modification_hooks
, Qt
);
5351 set_buffer_internal_1 (old_buffer
);
5353 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
5354 record_unwind_protect (unwind_create_tip_frame
, frame
);
5356 /* By setting the output method, we're essentially saying that
5357 the frame is live, as per FRAME_LIVE_P. If we get a signal
5358 from this point on, x_destroy_window might screw up reference
5360 f
->terminal
= dpyinfo
->terminal
;
5361 f
->terminal
->reference_count
++;
5362 f
->output_method
= output_w32
;
5363 f
->output_data
.w32
=
5364 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
5365 memset (f
->output_data
.w32
, 0, sizeof (struct w32_output
));
5367 FRAME_FONTSET (f
) = -1;
5368 f
->icon_name
= Qnil
;
5371 image_cache_refcount
= FRAME_IMAGE_CACHE (f
)->refcount
;
5372 dpyinfo_refcount
= dpyinfo
->reference_count
;
5373 #endif /* GLYPH_DEBUG */
5374 FRAME_KBOARD (f
) = kb
;
5375 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5376 f
->output_data
.w32
->explicit_parent
= 0;
5378 /* Set the name; the functions to which we pass f expect the name to
5380 if (EQ (name
, Qunbound
) || NILP (name
))
5382 f
->name
= build_string (dpyinfo
->w32_id_name
);
5383 f
->explicit_name
= 0;
5388 f
->explicit_name
= 1;
5389 /* use the frame's title when getting resources for this frame. */
5390 specbind (Qx_resource_name
, name
);
5393 f
->resx
= dpyinfo
->resx
;
5394 f
->resy
= dpyinfo
->resy
;
5396 if (uniscribe_available
)
5397 register_font_driver (&uniscribe_font_driver
, f
);
5398 register_font_driver (&w32font_driver
, f
);
5400 x_default_parameter (f
, parms
, Qfont_backend
, Qnil
,
5401 "fontBackend", "FontBackend", RES_TYPE_STRING
);
5403 /* Extract the window parameters from the supplied values
5404 that are needed to determine window geometry. */
5405 x_default_font_parameter (f
, parms
);
5407 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
5408 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
5409 /* This defaults to 2 in order to match xterm. We recognize either
5410 internalBorderWidth or internalBorder (which is what xterm calls
5412 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5416 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
5417 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
5418 if (! EQ (value
, Qunbound
))
5419 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
5422 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
5423 "internalBorderWidth", "internalBorderWidth",
5426 /* Also do the stuff which must be set before the window exists. */
5427 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
5428 "foreground", "Foreground", RES_TYPE_STRING
);
5429 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
5430 "background", "Background", RES_TYPE_STRING
);
5431 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
5432 "pointerColor", "Foreground", RES_TYPE_STRING
);
5433 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
5434 "cursorColor", "Foreground", RES_TYPE_STRING
);
5435 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
5436 "borderColor", "BorderColor", RES_TYPE_STRING
);
5438 /* Init faces before x_default_parameter is called for scroll-bar
5439 parameters because that function calls x_set_scroll_bar_width,
5440 which calls change_frame_size, which calls Fset_window_buffer,
5441 which runs hooks, which call Fvertical_motion. At the end, we
5442 end up in init_iterator with a null face cache, which should not
5444 init_frame_faces (f
);
5446 f
->output_data
.w32
->dwStyle
= WS_BORDER
| WS_POPUP
| WS_DISABLED
;
5447 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5449 window_prompting
= x_figure_window_size (f
, parms
, 0);
5451 /* No fringes on tip frame. */
5453 f
->left_fringe_width
= 0;
5454 f
->right_fringe_width
= 0;
5457 my_create_tip_window (f
);
5462 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
5463 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5464 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
5465 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5466 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
5467 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
5469 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
5470 Change will not be effected unless different from the current
5472 width
= FRAME_COLS (f
);
5473 height
= FRAME_LINES (f
);
5474 FRAME_LINES (f
) = 0;
5475 SET_FRAME_COLS (f
, 0);
5476 change_frame_size (f
, height
, width
, 1, 0, 0);
5478 /* Add `tooltip' frame parameter's default value. */
5479 if (NILP (Fframe_parameter (frame
, intern ("tooltip"))))
5480 Fmodify_frame_parameters (frame
, Fcons (Fcons (intern ("tooltip"), Qt
),
5483 /* Set up faces after all frame parameters are known. This call
5484 also merges in face attributes specified for new frames.
5486 Frame parameters may be changed if .Xdefaults contains
5487 specifications for the default font. For example, if there is an
5488 `Emacs.default.attributeBackground: pink', the `background-color'
5489 attribute of the frame get's set, which let's the internal border
5490 of the tooltip frame appear in pink. Prevent this. */
5492 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
5493 Lisp_Object fg
= Fframe_parameter (frame
, Qforeground_color
);
5494 Lisp_Object colors
= Qnil
;
5496 /* Set tip_frame here, so that */
5498 call2 (Qface_set_after_frame_default
, frame
, Qnil
);
5500 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
5501 colors
= Fcons (Fcons (Qbackground_color
, bg
), colors
);
5502 if (!EQ (fg
, Fframe_parameter (frame
, Qforeground_color
)))
5503 colors
= Fcons (Fcons (Qforeground_color
, fg
), colors
);
5506 Fmodify_frame_parameters (frame
, colors
);
5513 /* It is now ok to make the frame official even if we get an error
5514 below. And the frame needs to be on Vframe_list or making it
5515 visible won't work. */
5516 Vframe_list
= Fcons (frame
, Vframe_list
);
5518 /* Now that the frame is official, it counts as a reference to
5520 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
5522 /* Setting attributes of faces of the tooltip frame from resources
5523 and similar will increment face_change_count, which leads to the
5524 clearing of all current matrices. Since this isn't necessary
5525 here, avoid it by resetting face_change_count to the value it
5526 had before we created the tip frame. */
5527 face_change_count
= face_change_count_before
;
5529 /* Discard the unwind_protect. */
5530 return unbind_to (count
, frame
);
5534 /* Compute where to display tip frame F. PARMS is the list of frame
5535 parameters for F. DX and DY are specified offsets from the current
5536 location of the mouse. WIDTH and HEIGHT are the width and height
5537 of the tooltip. Return coordinates relative to the root window of
5538 the display in *ROOT_X, and *ROOT_Y. */
5541 compute_tip_xy (struct frame
*f
,
5542 Lisp_Object parms
, Lisp_Object dx
, Lisp_Object dy
,
5543 int width
, int height
, int *root_x
, int *root_y
)
5545 Lisp_Object left
, top
;
5546 int min_x
, min_y
, max_x
, max_y
;
5548 /* User-specified position? */
5549 left
= Fcdr (Fassq (Qleft
, parms
));
5550 top
= Fcdr (Fassq (Qtop
, parms
));
5552 /* Move the tooltip window where the mouse pointer is. Resize and
5554 if (!INTEGERP (left
) || !INTEGERP (top
))
5558 /* Default min and max values. */
5561 max_x
= x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f
));
5562 max_y
= x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f
));
5570 /* If multiple monitor support is available, constrain the tip onto
5571 the current monitor. This improves the above by allowing negative
5572 co-ordinates if monitor positions are such that they are valid, and
5573 snaps a tooltip onto a single monitor if we are close to the edge
5574 where it would otherwise flow onto the other monitor (or into
5575 nothingness if there is a gap in the overlap). */
5576 if (monitor_from_point_fn
&& get_monitor_info_fn
)
5578 struct MONITOR_INFO info
;
5580 = monitor_from_point_fn (pt
, MONITOR_DEFAULT_TO_NEAREST
);
5581 info
.cbSize
= sizeof (info
);
5583 if (get_monitor_info_fn (monitor
, &info
))
5585 min_x
= info
.rcWork
.left
;
5586 min_y
= info
.rcWork
.top
;
5587 max_x
= info
.rcWork
.right
;
5588 max_y
= info
.rcWork
.bottom
;
5594 *root_y
= XINT (top
);
5595 else if (*root_y
+ XINT (dy
) <= min_y
)
5596 *root_y
= min_y
; /* Can happen for negative dy */
5597 else if (*root_y
+ XINT (dy
) + height
<= max_y
)
5598 /* It fits below the pointer */
5599 *root_y
+= XINT (dy
);
5600 else if (height
+ XINT (dy
) + min_y
<= *root_y
)
5601 /* It fits above the pointer. */
5602 *root_y
-= height
+ XINT (dy
);
5604 /* Put it on the top. */
5607 if (INTEGERP (left
))
5608 *root_x
= XINT (left
);
5609 else if (*root_x
+ XINT (dx
) <= min_x
)
5610 *root_x
= 0; /* Can happen for negative dx */
5611 else if (*root_x
+ XINT (dx
) + width
<= max_x
)
5612 /* It fits to the right of the pointer. */
5613 *root_x
+= XINT (dx
);
5614 else if (width
+ XINT (dx
) + min_x
<= *root_x
)
5615 /* It fits to the left of the pointer. */
5616 *root_x
-= width
+ XINT (dx
);
5618 /* Put it left justified on the screen -- it ought to fit that way. */
5623 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
5624 doc
: /* Show STRING in a \"tooltip\" window on frame FRAME.
5625 A tooltip window is a small window displaying a string.
5627 This is an internal function; Lisp code should call `tooltip-show'.
5629 FRAME nil or omitted means use the selected frame.
5631 PARMS is an optional list of frame parameters which can be
5632 used to change the tooltip's appearance.
5634 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
5635 means use the default timeout of 5 seconds.
5637 If the list of frame parameters PARMS contains a `left' parameter,
5638 the tooltip is displayed at that x-position. Otherwise it is
5639 displayed at the mouse position, with offset DX added (default is 5 if
5640 DX isn't specified). Likewise for the y-position; if a `top' frame
5641 parameter is specified, it determines the y-position of the tooltip
5642 window, otherwise it is displayed at the mouse position, with offset
5643 DY added (default is -10).
5645 A tooltip's maximum size is specified by `x-max-tooltip-size'.
5646 Text larger than the specified size is clipped. */)
5647 (Lisp_Object string
, Lisp_Object frame
, Lisp_Object parms
, Lisp_Object timeout
, Lisp_Object dx
, Lisp_Object dy
)
5652 struct buffer
*old_buffer
;
5653 struct text_pos pos
;
5654 int i
, width
, height
;
5655 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
5656 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
5657 int count
= SPECPDL_INDEX ();
5659 specbind (Qinhibit_redisplay
, Qt
);
5661 GCPRO4 (string
, parms
, frame
, timeout
);
5663 CHECK_STRING (string
);
5664 f
= check_x_frame (frame
);
5666 timeout
= make_number (5);
5668 CHECK_NATNUM (timeout
);
5671 dx
= make_number (5);
5676 dy
= make_number (-10);
5680 if (NILP (last_show_tip_args
))
5681 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
5683 if (!NILP (tip_frame
))
5685 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
5686 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
5687 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
5689 if (EQ (frame
, last_frame
)
5690 && !NILP (Fequal (last_string
, string
))
5691 && !NILP (Fequal (last_parms
, parms
)))
5693 struct frame
*f
= XFRAME (tip_frame
);
5695 /* Only DX and DY have changed. */
5696 if (!NILP (tip_timer
))
5698 Lisp_Object timer
= tip_timer
;
5700 call1 (Qcancel_timer
, timer
);
5704 compute_tip_xy (f
, parms
, dx
, dy
, FRAME_PIXEL_WIDTH (f
),
5705 FRAME_PIXEL_HEIGHT (f
), &root_x
, &root_y
);
5707 /* Put tooltip in topmost group and in position. */
5708 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
5709 root_x
, root_y
, 0, 0,
5710 SWP_NOSIZE
| SWP_NOACTIVATE
);
5712 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5713 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
5715 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5722 /* Hide a previous tip, if any. */
5725 ASET (last_show_tip_args
, 0, string
);
5726 ASET (last_show_tip_args
, 1, frame
);
5727 ASET (last_show_tip_args
, 2, parms
);
5729 /* Add default values to frame parameters. */
5730 if (NILP (Fassq (Qname
, parms
)))
5731 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
5732 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5733 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
5734 if (NILP (Fassq (Qborder_width
, parms
)))
5735 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
5736 if (NILP (Fassq (Qborder_color
, parms
)))
5737 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
5738 if (NILP (Fassq (Qbackground_color
, parms
)))
5739 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
5742 /* Block input until the tip has been fully drawn, to avoid crashes
5743 when drawing tips in menus. */
5746 /* Create a frame for the tooltip, and record it in the global
5747 variable tip_frame. */
5748 frame
= x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f
), parms
, string
);
5751 /* Set up the frame's root window. */
5752 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
5753 w
->left_col
= w
->top_line
= make_number (0);
5755 if (CONSP (Vx_max_tooltip_size
)
5756 && INTEGERP (XCAR (Vx_max_tooltip_size
))
5757 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
5758 && INTEGERP (XCDR (Vx_max_tooltip_size
))
5759 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
5761 w
->total_cols
= XCAR (Vx_max_tooltip_size
);
5762 w
->total_lines
= XCDR (Vx_max_tooltip_size
);
5766 w
->total_cols
= make_number (80);
5767 w
->total_lines
= make_number (40);
5770 FRAME_TOTAL_COLS (f
) = XINT (w
->total_cols
);
5772 w
->pseudo_window_p
= 1;
5774 /* Display the tooltip text in a temporary buffer. */
5775 old_buffer
= current_buffer
;
5776 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
5777 current_buffer
->truncate_lines
= Qnil
;
5778 clear_glyph_matrix (w
->desired_matrix
);
5779 clear_glyph_matrix (w
->current_matrix
);
5780 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
5781 try_window (FRAME_ROOT_WINDOW (f
), pos
, 0);
5783 /* Compute width and height of the tooltip. */
5785 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
5787 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
5791 /* Stop at the first empty row at the end. */
5792 if (!row
->enabled_p
|| !row
->displays_text_p
)
5795 /* Let the row go over the full width of the frame. */
5796 row
->full_width_p
= 1;
5798 #ifdef TODO /* Investigate why some fonts need more width than is
5799 calculated for some tooltips. */
5800 /* There's a glyph at the end of rows that is use to place
5801 the cursor there. Don't include the width of this glyph. */
5802 if (row
->used
[TEXT_AREA
])
5804 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
5805 row_width
= row
->pixel_width
- last
->pixel_width
;
5809 row_width
= row
->pixel_width
;
5811 /* TODO: find why tips do not draw along baseline as instructed. */
5812 height
+= row
->height
;
5813 width
= max (width
, row_width
);
5816 /* Add the frame's internal border to the width and height the X
5817 window should have. */
5818 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
5819 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
5821 /* Move the tooltip window where the mouse pointer is. Resize and
5823 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
5826 /* Adjust Window size to take border into account. */
5828 rect
.left
= rect
.top
= 0;
5830 rect
.bottom
= height
;
5831 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
5832 FRAME_EXTERNAL_MENU_BAR (f
));
5834 /* Position and size tooltip, and put it in the topmost group.
5835 The add-on of 3 to the 5th argument is a kludge: without it,
5836 some fonts cause the last character of the tip to be truncated,
5837 for some obscure reason. */
5838 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
5839 root_x
, root_y
, rect
.right
- rect
.left
+ 3,
5840 rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
5842 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5843 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
5845 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5847 /* Let redisplay know that we have made the frame visible already. */
5848 f
->async_visible
= 1;
5850 ShowWindow (FRAME_W32_WINDOW (f
), SW_SHOWNOACTIVATE
);
5853 /* Draw into the window. */
5854 w
->must_be_updated_p
= 1;
5855 update_single_window (w
, 1);
5859 /* Restore original current buffer. */
5860 set_buffer_internal_1 (old_buffer
);
5861 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
5864 /* Let the tip disappear after timeout seconds. */
5865 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
5866 intern ("x-hide-tip"));
5869 return unbind_to (count
, Qnil
);
5873 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
5874 doc
: /* Hide the current tooltip window, if there is any.
5875 Value is t if tooltip was open, nil otherwise. */)
5879 Lisp_Object deleted
, frame
, timer
;
5880 struct gcpro gcpro1
, gcpro2
;
5882 /* Return quickly if nothing to do. */
5883 if (NILP (tip_timer
) && NILP (tip_frame
))
5888 GCPRO2 (frame
, timer
);
5889 tip_frame
= tip_timer
= deleted
= Qnil
;
5891 count
= SPECPDL_INDEX ();
5892 specbind (Qinhibit_redisplay
, Qt
);
5893 specbind (Qinhibit_quit
, Qt
);
5896 call1 (Qcancel_timer
, timer
);
5900 delete_frame (frame
, Qnil
);
5905 return unbind_to (count
, deleted
);
5910 /***********************************************************************
5911 File selection dialog
5912 ***********************************************************************/
5913 extern Lisp_Object Qfile_name_history
;
5915 /* Callback for altering the behavior of the Open File dialog.
5916 Makes the Filename text field contain "Current Directory" and be
5917 read-only when "Directories" is selected in the filter. This
5918 allows us to work around the fact that the standard Open File
5919 dialog does not support directories. */
5921 file_dialog_callback (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
5923 if (msg
== WM_NOTIFY
)
5925 OFNOTIFY
* notify
= (OFNOTIFY
*)lParam
;
5926 /* Detect when the Filter dropdown is changed. */
5927 if (notify
->hdr
.code
== CDN_TYPECHANGE
5928 || notify
->hdr
.code
== CDN_INITDONE
)
5930 HWND dialog
= GetParent (hwnd
);
5931 HWND edit_control
= GetDlgItem (dialog
, FILE_NAME_TEXT_FIELD
);
5933 /* Directories is in index 2. */
5934 if (notify
->lpOFN
->nFilterIndex
== 2)
5936 CommDlg_OpenSave_SetControlText (dialog
, FILE_NAME_TEXT_FIELD
,
5937 "Current Directory");
5938 EnableWindow (edit_control
, FALSE
);
5942 /* Don't override default filename on init done. */
5943 if (notify
->hdr
.code
== CDN_TYPECHANGE
)
5944 CommDlg_OpenSave_SetControlText (dialog
,
5945 FILE_NAME_TEXT_FIELD
, "");
5946 EnableWindow (edit_control
, TRUE
);
5953 /* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
5954 we end up with the old file dialogs. Define a big enough struct for the
5955 new dialog to trick GetOpenFileName into giving us the new dialogs on
5956 Windows 2000 and XP. */
5959 OPENFILENAME real_details
;
5966 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 5, 0,
5967 doc
: /* Read file name, prompting with PROMPT in directory DIR.
5968 Use a file selection dialog.
5969 Select DEFAULT-FILENAME in the dialog's file selection box, if
5970 specified. Ensure that file exists if MUSTMATCH is non-nil.
5971 If ONLY-DIR-P is non-nil, the user can only select directories. */)
5972 (Lisp_Object prompt
, Lisp_Object dir
, Lisp_Object default_filename
, Lisp_Object mustmatch
, Lisp_Object only_dir_p
)
5974 struct frame
*f
= SELECTED_FRAME ();
5975 Lisp_Object file
= Qnil
;
5976 int count
= SPECPDL_INDEX ();
5977 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
5978 char filename
[MAX_PATH
+ 1];
5979 char init_dir
[MAX_PATH
+ 1];
5980 int default_filter_index
= 1; /* 1: All Files, 2: Directories only */
5982 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
, file
);
5983 CHECK_STRING (prompt
);
5986 /* Create the dialog with PROMPT as title, using DIR as initial
5987 directory and using "*" as pattern. */
5988 dir
= Fexpand_file_name (dir
, Qnil
);
5989 strncpy (init_dir
, SDATA (ENCODE_FILE (dir
)), MAX_PATH
);
5990 init_dir
[MAX_PATH
] = '\0';
5991 unixtodos_filename (init_dir
);
5993 if (STRINGP (default_filename
))
5995 char *file_name_only
;
5996 char *full_path_name
= SDATA (ENCODE_FILE (default_filename
));
5998 unixtodos_filename (full_path_name
);
6000 file_name_only
= strrchr (full_path_name
, '\\');
6001 if (!file_name_only
)
6002 file_name_only
= full_path_name
;
6006 strncpy (filename
, file_name_only
, MAX_PATH
);
6007 filename
[MAX_PATH
] = '\0';
6013 NEWOPENFILENAME new_file_details
;
6014 BOOL file_opened
= FALSE
;
6015 OPENFILENAME
* file_details
= &new_file_details
.real_details
;
6017 /* Prevent redisplay. */
6018 specbind (Qinhibit_redisplay
, Qt
);
6021 memset (&new_file_details
, 0, sizeof (new_file_details
));
6022 /* Apparently NT4 crashes if you give it an unexpected size.
6023 I'm not sure about Windows 9x, so play it safe. */
6024 if (w32_major_version
> 4 && w32_major_version
< 95)
6025 file_details
->lStructSize
= sizeof (NEWOPENFILENAME
);
6027 file_details
->lStructSize
= sizeof (OPENFILENAME
);
6029 file_details
->hwndOwner
= FRAME_W32_WINDOW (f
);
6030 /* Undocumented Bug in Common File Dialog:
6031 If a filter is not specified, shell links are not resolved. */
6032 file_details
->lpstrFilter
= "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
6033 file_details
->lpstrFile
= filename
;
6034 file_details
->nMaxFile
= sizeof (filename
);
6035 file_details
->lpstrInitialDir
= init_dir
;
6036 file_details
->lpstrTitle
= SDATA (prompt
);
6038 if (! NILP (only_dir_p
))
6039 default_filter_index
= 2;
6041 file_details
->nFilterIndex
= default_filter_index
;
6043 file_details
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
6044 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
6045 if (!NILP (mustmatch
))
6047 /* Require that the path to the parent directory exists. */
6048 file_details
->Flags
|= OFN_PATHMUSTEXIST
;
6049 /* If we are looking for a file, require that it exists. */
6050 if (NILP (only_dir_p
))
6051 file_details
->Flags
|= OFN_FILEMUSTEXIST
;
6054 file_details
->lpfnHook
= (LPOFNHOOKPROC
) file_dialog_callback
;
6056 file_opened
= GetOpenFileName (file_details
);
6062 dostounix_filename (filename
);
6064 if (file_details
->nFilterIndex
== 2)
6066 /* "Directories" selected - strip dummy file name. */
6067 char * last
= strrchr (filename
, '/');
6071 file
= DECODE_FILE (build_string (filename
));
6073 /* User cancelled the dialog without making a selection. */
6074 else if (!CommDlgExtendedError ())
6076 /* An error occurred, fallback on reading from the mini-buffer. */
6078 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
6079 dir
, mustmatch
, dir
, Qfile_name_history
,
6080 default_filename
, Qnil
);
6082 file
= unbind_to (count
, file
);
6087 /* Make "Cancel" equivalent to C-g. */
6089 Fsignal (Qquit
, Qnil
);
6091 return unbind_to (count
, file
);
6095 /* Moving files to the system recycle bin.
6096 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
6097 DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash
,
6098 Ssystem_move_file_to_trash
, 1, 1, 0,
6099 doc
: /* Move file or directory named FILENAME to the recycle bin. */)
6100 (Lisp_Object filename
)
6102 Lisp_Object handler
;
6103 Lisp_Object encoded_file
;
6104 Lisp_Object operation
;
6106 operation
= Qdelete_file
;
6107 if (!NILP (Ffile_directory_p (filename
))
6108 && NILP (Ffile_symlink_p (filename
)))
6110 operation
= intern ("delete-directory");
6111 filename
= Fdirectory_file_name (filename
);
6113 filename
= Fexpand_file_name (filename
, Qnil
);
6115 handler
= Ffind_file_name_handler (filename
, operation
);
6116 if (!NILP (handler
))
6117 return call2 (handler
, operation
, filename
);
6119 encoded_file
= ENCODE_FILE (filename
);
6123 SHFILEOPSTRUCT file_op
;
6124 char tmp_path
[MAX_PATH
+ 1];
6126 path
= map_w32_filename (SDATA (encoded_file
), NULL
);
6128 /* On Windows, write permission is required to delete/move files. */
6129 _chmod (path
, 0666);
6131 memset (tmp_path
, 0, sizeof (tmp_path
));
6132 strcpy (tmp_path
, path
);
6134 memset (&file_op
, 0, sizeof (file_op
));
6135 file_op
.hwnd
= HWND_DESKTOP
;
6136 file_op
.wFunc
= FO_DELETE
;
6137 file_op
.pFrom
= tmp_path
;
6138 file_op
.fFlags
= FOF_SILENT
| FOF_NOCONFIRMATION
| FOF_ALLOWUNDO
6139 | FOF_NOERRORUI
| FOF_NO_CONNECTED_ELEMENTS
;
6140 file_op
.fAnyOperationsAborted
= FALSE
;
6142 if (SHFileOperation (&file_op
) != 0)
6143 report_file_error ("Removing old name", list1 (filename
));
6149 /***********************************************************************
6150 w32 specialized functions
6151 ***********************************************************************/
6153 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
,
6154 Sw32_send_sys_command
, 1, 2, 0,
6155 doc
: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
6156 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
6157 to minimize), #xf120 to restore frame to original size, and #xf100
6158 to activate the menubar for keyboard access. #xf140 activates the
6159 screen saver if defined.
6161 If optional parameter FRAME is not specified, use selected frame. */)
6162 (Lisp_Object command
, Lisp_Object frame
)
6164 FRAME_PTR f
= check_x_frame (frame
);
6166 CHECK_NUMBER (command
);
6168 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
6173 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
6174 doc
: /* Get Windows to perform OPERATION on DOCUMENT.
6175 This is a wrapper around the ShellExecute system function, which
6176 invokes the application registered to handle OPERATION for DOCUMENT.
6178 OPERATION is either nil or a string that names a supported operation.
6179 What operations can be used depends on the particular DOCUMENT and its
6180 handler application, but typically it is one of the following common
6183 \"open\" - open DOCUMENT, which could be a file, a directory, or an
6184 executable program. If it is an application, that
6185 application is launched in the current buffer's default
6186 directory. Otherwise, the application associated with
6187 DOCUMENT is launched in the buffer's default directory.
6188 \"print\" - print DOCUMENT, which must be a file
6189 \"explore\" - start the Windows Explorer on DOCUMENT
6190 \"edit\" - launch an editor and open DOCUMENT for editing; which
6191 editor is launched depends on the association for the
6193 \"find\" - initiate search starting from DOCUMENT which must specify
6195 nil - invoke the default OPERATION, or \"open\" if default is
6196 not defined or unavailable
6198 DOCUMENT is typically the name of a document file or a URL, but can
6199 also be a program executable to run, or a directory to open in the
6202 If DOCUMENT is a program executable, the optional third arg PARAMETERS
6203 can be a string containing command line parameters that will be passed
6204 to the program; otherwise, PARAMETERS should be nil or unspecified.
6206 Optional fourth argument SHOW-FLAG can be used to control how the
6207 application will be displayed when it is invoked. If SHOW-FLAG is nil
6208 or unspecified, the application is displayed normally, otherwise it is
6209 an integer representing a ShowWindow flag:
6214 6 - start minimized */)
6215 (Lisp_Object operation
, Lisp_Object document
, Lisp_Object parameters
, Lisp_Object show_flag
)
6217 Lisp_Object current_dir
;
6220 CHECK_STRING (document
);
6222 /* Encode filename, current directory and parameters. */
6223 current_dir
= ENCODE_FILE (current_buffer
->directory
);
6224 document
= ENCODE_FILE (document
);
6225 if (STRINGP (parameters
))
6226 parameters
= ENCODE_SYSTEM (parameters
);
6228 if ((int) ShellExecute (NULL
,
6229 (STRINGP (operation
) ?
6230 SDATA (operation
) : NULL
),
6232 (STRINGP (parameters
) ?
6233 SDATA (parameters
) : NULL
),
6234 SDATA (current_dir
),
6235 (INTEGERP (show_flag
) ?
6236 XINT (show_flag
) : SW_SHOWDEFAULT
))
6239 errstr
= w32_strerror (0);
6240 /* The error string might be encoded in the locale's encoding. */
6241 if (!NILP (Vlocale_coding_system
))
6243 Lisp_Object decoded
=
6244 code_convert_string_norecord (make_unibyte_string (errstr
,
6246 Vlocale_coding_system
, 0);
6247 errstr
= (char *)SDATA (decoded
);
6249 error ("ShellExecute failed: %s", errstr
);
6252 /* Lookup virtual keycode from string representing the name of a
6253 non-ascii keystroke into the corresponding virtual key, using
6254 lispy_function_keys. */
6256 lookup_vk_code (char *key
)
6260 for (i
= 0; i
< 256; i
++)
6261 if (lispy_function_keys
[i
]
6262 && strcmp (lispy_function_keys
[i
], key
) == 0)
6268 /* Convert a one-element vector style key sequence to a hot key
6271 w32_parse_hot_key (Lisp_Object key
)
6273 /* Copied from Fdefine_key and store_in_keymap. */
6274 register Lisp_Object c
;
6278 struct gcpro gcpro1
;
6282 if (XFASTINT (Flength (key
)) != 1)
6287 c
= Faref (key
, make_number (0));
6289 if (CONSP (c
) && lucid_event_type_list_p (c
))
6290 c
= Fevent_convert_list (c
);
6294 if (! INTEGERP (c
) && ! SYMBOLP (c
))
6295 error ("Key definition is invalid");
6297 /* Work out the base key and the modifiers. */
6300 c
= parse_modifiers (c
);
6301 lisp_modifiers
= XINT (Fcar (Fcdr (c
)));
6305 vk_code
= lookup_vk_code (SDATA (SYMBOL_NAME (c
)));
6307 else if (INTEGERP (c
))
6309 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
6310 /* Many ascii characters are their own virtual key code. */
6311 vk_code
= XINT (c
) & CHARACTERBITS
;
6314 if (vk_code
< 0 || vk_code
> 255)
6317 if ((lisp_modifiers
& meta_modifier
) != 0
6318 && !NILP (Vw32_alt_is_meta
))
6319 lisp_modifiers
|= alt_modifier
;
6321 /* Supply defs missing from mingw32. */
6323 #define MOD_ALT 0x0001
6324 #define MOD_CONTROL 0x0002
6325 #define MOD_SHIFT 0x0004
6326 #define MOD_WIN 0x0008
6329 /* Convert lisp modifiers to Windows hot-key form. */
6330 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
6331 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
6332 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
6333 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
6335 return HOTKEY (vk_code
, w32_modifiers
);
6338 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
,
6339 Sw32_register_hot_key
, 1, 1, 0,
6340 doc
: /* Register KEY as a hot-key combination.
6341 Certain key combinations like Alt-Tab are reserved for system use on
6342 Windows, and therefore are normally intercepted by the system. However,
6343 most of these key combinations can be received by registering them as
6344 hot-keys, overriding their special meaning.
6346 KEY must be a one element key definition in vector form that would be
6347 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
6348 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
6349 is always interpreted as the Windows modifier keys.
6351 The return value is the hotkey-id if registered, otherwise nil. */)
6354 key
= w32_parse_hot_key (key
);
6356 if (!NILP (key
) && NILP (Fmemq (key
, w32_grabbed_keys
)))
6358 /* Reuse an empty slot if possible. */
6359 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
6361 /* Safe to add new key to list, even if we have focus. */
6363 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
6365 XSETCAR (item
, key
);
6367 /* Notify input thread about new hot-key definition, so that it
6368 takes effect without needing to switch focus. */
6369 #ifdef USE_LISP_UNION_TYPE
6370 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
6373 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
6381 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
,
6382 Sw32_unregister_hot_key
, 1, 1, 0,
6383 doc
: /* Unregister KEY as a hot-key combination. */)
6388 if (!INTEGERP (key
))
6389 key
= w32_parse_hot_key (key
);
6391 item
= Fmemq (key
, w32_grabbed_keys
);
6395 /* Notify input thread about hot-key definition being removed, so
6396 that it takes effect without needing focus switch. */
6397 #ifdef USE_LISP_UNION_TYPE
6398 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
6399 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
.i
))
6401 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
6402 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
6406 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6413 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
,
6414 Sw32_registered_hot_keys
, 0, 0, 0,
6415 doc
: /* Return list of registered hot-key IDs. */)
6418 return Fdelq (Qnil
, Fcopy_sequence (w32_grabbed_keys
));
6421 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
,
6422 Sw32_reconstruct_hot_key
, 1, 1, 0,
6423 doc
: /* Convert hot-key ID to a lisp key combination.
6424 usage: (w32-reconstruct-hot-key ID) */)
6425 (Lisp_Object hotkeyid
)
6427 int vk_code
, w32_modifiers
;
6430 CHECK_NUMBER (hotkeyid
);
6432 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
6433 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
6435 if (vk_code
< 256 && lispy_function_keys
[vk_code
])
6436 key
= intern (lispy_function_keys
[vk_code
]);
6438 key
= make_number (vk_code
);
6440 key
= Fcons (key
, Qnil
);
6441 if (w32_modifiers
& MOD_SHIFT
)
6442 key
= Fcons (Qshift
, key
);
6443 if (w32_modifiers
& MOD_CONTROL
)
6444 key
= Fcons (Qctrl
, key
);
6445 if (w32_modifiers
& MOD_ALT
)
6446 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
6447 if (w32_modifiers
& MOD_WIN
)
6448 key
= Fcons (Qhyper
, key
);
6453 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
,
6454 Sw32_toggle_lock_key
, 1, 2, 0,
6455 doc
: /* Toggle the state of the lock key KEY.
6456 KEY can be `capslock', `kp-numlock', or `scroll'.
6457 If the optional parameter NEW-STATE is a number, then the state of KEY
6458 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
6459 (Lisp_Object key
, Lisp_Object new_state
)
6463 if (EQ (key
, intern ("capslock")))
6464 vk_code
= VK_CAPITAL
;
6465 else if (EQ (key
, intern ("kp-numlock")))
6466 vk_code
= VK_NUMLOCK
;
6467 else if (EQ (key
, intern ("scroll")))
6468 vk_code
= VK_SCROLL
;
6472 if (!dwWindowsThreadId
)
6473 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
6475 #ifdef USE_LISP_UNION_TYPE
6476 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
6477 (WPARAM
) vk_code
, (LPARAM
) new_state
.i
))
6479 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
6480 (WPARAM
) vk_code
, (LPARAM
) new_state
))
6484 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6485 return make_number (msg
.wParam
);
6490 DEFUN ("w32-window-exists-p", Fw32_window_exists_p
, Sw32_window_exists_p
,
6492 doc
: /* Return non-nil if a window exists with the specified CLASS and NAME.
6494 This is a direct interface to the Windows API FindWindow function. */)
6495 (Lisp_Object
class, Lisp_Object name
)
6500 CHECK_STRING (class);
6502 CHECK_STRING (name
);
6504 hnd
= FindWindow (STRINGP (class) ? ((LPCTSTR
) SDATA (class)) : NULL
,
6505 STRINGP (name
) ? ((LPCTSTR
) SDATA (name
)) : NULL
);
6511 DEFUN ("w32-battery-status", Fw32_battery_status
, Sw32_battery_status
, 0, 0, 0,
6512 doc
: /* Get power status information from Windows system.
6514 The following %-sequences are provided:
6515 %L AC line status (verbose)
6516 %B Battery status (verbose)
6517 %b Battery status, empty means high, `-' means low,
6518 `!' means critical, and `+' means charging
6519 %p Battery load percentage
6520 %s Remaining time (to charge or discharge) in seconds
6521 %m Remaining time (to charge or discharge) in minutes
6522 %h Remaining time (to charge or discharge) in hours
6523 %t Remaining time (to charge or discharge) in the form `h:min' */)
6526 Lisp_Object status
= Qnil
;
6528 SYSTEM_POWER_STATUS system_status
;
6529 if (GetSystemPowerStatus (&system_status
))
6531 Lisp_Object line_status
, battery_status
, battery_status_symbol
;
6532 Lisp_Object load_percentage
, seconds
, minutes
, hours
, remain
;
6533 Lisp_Object sequences
[8];
6535 long seconds_left
= (long) system_status
.BatteryLifeTime
;
6537 if (system_status
.ACLineStatus
== 0)
6538 line_status
= build_string ("off-line");
6539 else if (system_status
.ACLineStatus
== 1)
6540 line_status
= build_string ("on-line");
6542 line_status
= build_string ("N/A");
6544 if (system_status
.BatteryFlag
& 128)
6546 battery_status
= build_string ("N/A");
6547 battery_status_symbol
= empty_unibyte_string
;
6549 else if (system_status
.BatteryFlag
& 8)
6551 battery_status
= build_string ("charging");
6552 battery_status_symbol
= build_string ("+");
6553 if (system_status
.BatteryFullLifeTime
!= -1L)
6554 seconds_left
= system_status
.BatteryFullLifeTime
- seconds_left
;
6556 else if (system_status
.BatteryFlag
& 4)
6558 battery_status
= build_string ("critical");
6559 battery_status_symbol
= build_string ("!");
6561 else if (system_status
.BatteryFlag
& 2)
6563 battery_status
= build_string ("low");
6564 battery_status_symbol
= build_string ("-");
6566 else if (system_status
.BatteryFlag
& 1)
6568 battery_status
= build_string ("high");
6569 battery_status_symbol
= empty_unibyte_string
;
6573 battery_status
= build_string ("medium");
6574 battery_status_symbol
= empty_unibyte_string
;
6577 if (system_status
.BatteryLifePercent
> 100)
6578 load_percentage
= build_string ("N/A");
6582 _snprintf (buffer
, 16, "%d", system_status
.BatteryLifePercent
);
6583 load_percentage
= build_string (buffer
);
6586 if (seconds_left
< 0)
6587 seconds
= minutes
= hours
= remain
= build_string ("N/A");
6593 _snprintf (buffer
, 16, "%ld", seconds_left
);
6594 seconds
= build_string (buffer
);
6596 m
= seconds_left
/ 60;
6597 _snprintf (buffer
, 16, "%ld", m
);
6598 minutes
= build_string (buffer
);
6600 h
= seconds_left
/ 3600.0;
6601 _snprintf (buffer
, 16, "%3.1f", h
);
6602 hours
= build_string (buffer
);
6604 _snprintf (buffer
, 16, "%ld:%02ld", m
/ 60, m
% 60);
6605 remain
= build_string (buffer
);
6607 sequences
[0] = Fcons (make_number ('L'), line_status
);
6608 sequences
[1] = Fcons (make_number ('B'), battery_status
);
6609 sequences
[2] = Fcons (make_number ('b'), battery_status_symbol
);
6610 sequences
[3] = Fcons (make_number ('p'), load_percentage
);
6611 sequences
[4] = Fcons (make_number ('s'), seconds
);
6612 sequences
[5] = Fcons (make_number ('m'), minutes
);
6613 sequences
[6] = Fcons (make_number ('h'), hours
);
6614 sequences
[7] = Fcons (make_number ('t'), remain
);
6616 status
= Flist (8, sequences
);
6622 DEFUN ("file-system-info", Ffile_system_info
, Sfile_system_info
, 1, 1, 0,
6623 doc
: /* Return storage information about the file system FILENAME is on.
6624 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
6625 storage of the file system, FREE is the free storage, and AVAIL is the
6626 storage available to a non-superuser. All 3 numbers are in bytes.
6627 If the underlying system call fails, value is nil. */)
6628 (Lisp_Object filename
)
6630 Lisp_Object encoded
, value
;
6632 CHECK_STRING (filename
);
6633 filename
= Fexpand_file_name (filename
, Qnil
);
6634 encoded
= ENCODE_FILE (filename
);
6638 /* Determining the required information on Windows turns out, sadly,
6639 to be more involved than one would hope. The original Win32 api
6640 call for this will return bogus information on some systems, but we
6641 must dynamically probe for the replacement api, since that was
6642 added rather late on. */
6644 HMODULE hKernel
= GetModuleHandle ("kernel32");
6645 BOOL (*pfn_GetDiskFreeSpaceEx
)
6646 (char *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
6647 = (void *) GetProcAddress (hKernel
, "GetDiskFreeSpaceEx");
6649 /* On Windows, we may need to specify the root directory of the
6650 volume holding FILENAME. */
6651 char rootname
[MAX_PATH
];
6652 char *name
= SDATA (encoded
);
6654 /* find the root name of the volume if given */
6655 if (isalpha (name
[0]) && name
[1] == ':')
6657 rootname
[0] = name
[0];
6658 rootname
[1] = name
[1];
6662 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
6664 char *str
= rootname
;
6668 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
6678 if (pfn_GetDiskFreeSpaceEx
)
6680 /* Unsigned large integers cannot be cast to double, so
6681 use signed ones instead. */
6682 LARGE_INTEGER availbytes
;
6683 LARGE_INTEGER freebytes
;
6684 LARGE_INTEGER totalbytes
;
6686 if (pfn_GetDiskFreeSpaceEx (rootname
,
6687 (ULARGE_INTEGER
*)&availbytes
,
6688 (ULARGE_INTEGER
*)&totalbytes
,
6689 (ULARGE_INTEGER
*)&freebytes
))
6690 value
= list3 (make_float ((double) totalbytes
.QuadPart
),
6691 make_float ((double) freebytes
.QuadPart
),
6692 make_float ((double) availbytes
.QuadPart
));
6696 DWORD sectors_per_cluster
;
6697 DWORD bytes_per_sector
;
6698 DWORD free_clusters
;
6699 DWORD total_clusters
;
6701 if (GetDiskFreeSpace (rootname
,
6702 §ors_per_cluster
,
6706 value
= list3 (make_float ((double) total_clusters
6707 * sectors_per_cluster
* bytes_per_sector
),
6708 make_float ((double) free_clusters
6709 * sectors_per_cluster
* bytes_per_sector
),
6710 make_float ((double) free_clusters
6711 * sectors_per_cluster
* bytes_per_sector
));
6718 DEFUN ("default-printer-name", Fdefault_printer_name
, Sdefault_printer_name
,
6719 0, 0, 0, doc
: /* Return the name of Windows default printer device. */)
6722 static char pname_buf
[256];
6725 PRINTER_INFO_2
*ppi2
= NULL
;
6726 DWORD dwNeeded
= 0, dwReturned
= 0;
6728 /* Retrieve the default string from Win.ini (the registry).
6729 * String will be in form "printername,drivername,portname".
6730 * This is the most portable way to get the default printer. */
6731 if (GetProfileString ("windows", "device", ",,", pname_buf
, sizeof (pname_buf
)) <= 0)
6733 /* printername precedes first "," character */
6734 strtok (pname_buf
, ",");
6735 /* We want to know more than the printer name */
6736 if (!OpenPrinter (pname_buf
, &hPrn
, NULL
))
6738 GetPrinter (hPrn
, 2, NULL
, 0, &dwNeeded
);
6741 ClosePrinter (hPrn
);
6744 /* Allocate memory for the PRINTER_INFO_2 struct */
6745 ppi2
= (PRINTER_INFO_2
*) xmalloc (dwNeeded
);
6748 ClosePrinter (hPrn
);
6751 /* Call GetPrinter again with big enouth memory block */
6752 err
= GetPrinter (hPrn
, 2, (LPBYTE
)ppi2
, dwNeeded
, &dwReturned
);
6753 ClosePrinter (hPrn
);
6762 if (ppi2
->Attributes
& PRINTER_ATTRIBUTE_SHARED
&& ppi2
->pServerName
)
6764 /* a remote printer */
6765 if (*ppi2
->pServerName
== '\\')
6766 _snprintf (pname_buf
, sizeof (pname_buf
), "%s\\%s", ppi2
->pServerName
,
6769 _snprintf (pname_buf
, sizeof (pname_buf
), "\\\\%s\\%s", ppi2
->pServerName
,
6771 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
6775 /* a local printer */
6776 strncpy (pname_buf
, ppi2
->pPortName
, sizeof (pname_buf
));
6777 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
6778 /* `pPortName' can include several ports, delimited by ','.
6779 * we only use the first one. */
6780 strtok (pname_buf
, ",");
6785 return build_string (pname_buf
);
6788 /***********************************************************************
6790 ***********************************************************************/
6792 /* Keep this list in the same order as frame_parms in frame.c.
6793 Use 0 for unsupported frame parameters. */
6795 frame_parm_handler w32_frame_parm_handlers
[] =
6799 x_set_background_color
,
6805 x_set_foreground_color
,
6808 x_set_internal_border_width
,
6809 x_set_menu_bar_lines
,
6811 x_explicitly_set_name
,
6812 x_set_scroll_bar_width
,
6815 x_set_vertical_scroll_bars
,
6817 x_set_tool_bar_lines
,
6818 0, /* x_set_scroll_bar_foreground, */
6819 0, /* x_set_scroll_bar_background, */
6824 0, /* x_set_wait_for_wm, */
6828 0, /* x_set_sticky */
6832 syms_of_w32fns (void)
6834 globals_of_w32fns ();
6835 /* This is zero if not using MS-Windows. */
6837 track_mouse_window
= NULL
;
6839 w32_visible_system_caret_hwnd
= NULL
;
6841 DEFSYM (Qnone
, "none");
6842 DEFSYM (Qsuppress_icon
, "suppress-icon");
6843 DEFSYM (Qundefined_color
, "undefined-color");
6844 DEFSYM (Qcancel_timer
, "cancel-timer");
6845 DEFSYM (Qhyper
, "hyper");
6846 DEFSYM (Qsuper
, "super");
6847 DEFSYM (Qmeta
, "meta");
6848 DEFSYM (Qalt
, "alt");
6849 DEFSYM (Qctrl
, "ctrl");
6850 DEFSYM (Qcontrol
, "control");
6851 DEFSYM (Qshift
, "shift");
6852 DEFSYM (Qfont_param
, "font-parameter");
6853 /* This is the end of symbol initialization. */
6855 /* Text property `display' should be nonsticky by default. */
6856 Vtext_property_default_nonsticky
6857 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
6860 Fput (Qundefined_color
, Qerror_conditions
,
6861 pure_cons (Qundefined_color
, pure_cons (Qerror
, Qnil
)));
6862 Fput (Qundefined_color
, Qerror_message
,
6863 make_pure_c_string ("Undefined color"));
6865 staticpro (&w32_grabbed_keys
);
6866 w32_grabbed_keys
= Qnil
;
6868 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
6869 doc
: /* An array of color name mappings for Windows. */);
6870 Vw32_color_map
= Qnil
;
6872 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
6873 doc
: /* Non-nil if Alt key presses are passed on to Windows.
6874 When non-nil, for example, Alt pressed and released and then space will
6875 open the System menu. When nil, Emacs processes the Alt key events, and
6876 then silently swallows them. */);
6877 Vw32_pass_alt_to_system
= Qnil
;
6879 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
6880 doc
: /* Non-nil if the Alt key is to be considered the same as the META key.
6881 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
6882 Vw32_alt_is_meta
= Qt
;
6884 DEFVAR_INT ("w32-quit-key", &w32_quit_key
,
6885 doc
: /* If non-zero, the virtual key code for an alternative quit key. */);
6888 DEFVAR_LISP ("w32-pass-lwindow-to-system",
6889 &Vw32_pass_lwindow_to_system
,
6890 doc
: /* If non-nil, the left \"Windows\" key is passed on to Windows.
6892 When non-nil, the Start menu is opened by tapping the key.
6893 If you set this to nil, the left \"Windows\" key is processed by Emacs
6894 according to the value of `w32-lwindow-modifier', which see.
6896 Note that some combinations of the left \"Windows\" key with other keys are
6897 caught by Windows at low level, and so binding them in Emacs will have no
6898 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
6899 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
6900 the doc string of `w32-phantom-key-code'. */);
6901 Vw32_pass_lwindow_to_system
= Qt
;
6903 DEFVAR_LISP ("w32-pass-rwindow-to-system",
6904 &Vw32_pass_rwindow_to_system
,
6905 doc
: /* If non-nil, the right \"Windows\" key is passed on to Windows.
6907 When non-nil, the Start menu is opened by tapping the key.
6908 If you set this to nil, the right \"Windows\" key is processed by Emacs
6909 according to the value of `w32-rwindow-modifier', which see.
6911 Note that some combinations of the right \"Windows\" key with other keys are
6912 caught by Windows at low level, and so binding them in Emacs will have no
6913 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
6914 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
6915 the doc string of `w32-phantom-key-code'. */);
6916 Vw32_pass_rwindow_to_system
= Qt
;
6918 DEFVAR_LISP ("w32-phantom-key-code",
6919 &Vw32_phantom_key_code
,
6920 doc
: /* Virtual key code used to generate \"phantom\" key presses.
6921 Value is a number between 0 and 255.
6923 Phantom key presses are generated in order to stop the system from
6924 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
6925 `w32-pass-rwindow-to-system' is nil. */);
6926 /* Although 255 is technically not a valid key code, it works and
6927 means that this hack won't interfere with any real key code. */
6928 XSETINT (Vw32_phantom_key_code
, 255);
6930 DEFVAR_LISP ("w32-enable-num-lock",
6931 &Vw32_enable_num_lock
,
6932 doc
: /* If non-nil, the Num Lock key acts normally.
6933 Set to nil to handle Num Lock as the `kp-numlock' key. */);
6934 Vw32_enable_num_lock
= Qt
;
6936 DEFVAR_LISP ("w32-enable-caps-lock",
6937 &Vw32_enable_caps_lock
,
6938 doc
: /* If non-nil, the Caps Lock key acts normally.
6939 Set to nil to handle Caps Lock as the `capslock' key. */);
6940 Vw32_enable_caps_lock
= Qt
;
6942 DEFVAR_LISP ("w32-scroll-lock-modifier",
6943 &Vw32_scroll_lock_modifier
,
6944 doc
: /* Modifier to use for the Scroll Lock ON state.
6945 The value can be hyper, super, meta, alt, control or shift for the
6946 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
6947 Any other value will cause the Scroll Lock key to be ignored. */);
6948 Vw32_scroll_lock_modifier
= Qnil
;
6950 DEFVAR_LISP ("w32-lwindow-modifier",
6951 &Vw32_lwindow_modifier
,
6952 doc
: /* Modifier to use for the left \"Windows\" key.
6953 The value can be hyper, super, meta, alt, control or shift for the
6954 respective modifier, or nil to appear as the `lwindow' key.
6955 Any other value will cause the key to be ignored. */);
6956 Vw32_lwindow_modifier
= Qnil
;
6958 DEFVAR_LISP ("w32-rwindow-modifier",
6959 &Vw32_rwindow_modifier
,
6960 doc
: /* Modifier to use for the right \"Windows\" key.
6961 The value can be hyper, super, meta, alt, control or shift for the
6962 respective modifier, or nil to appear as the `rwindow' key.
6963 Any other value will cause the key to be ignored. */);
6964 Vw32_rwindow_modifier
= Qnil
;
6966 DEFVAR_LISP ("w32-apps-modifier",
6967 &Vw32_apps_modifier
,
6968 doc
: /* Modifier to use for the \"Apps\" key.
6969 The value can be hyper, super, meta, alt, control or shift for the
6970 respective modifier, or nil to appear as the `apps' key.
6971 Any other value will cause the key to be ignored. */);
6972 Vw32_apps_modifier
= Qnil
;
6974 DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts
,
6975 doc
: /* Non-nil enables selection of artificially italicized and bold fonts. */);
6976 w32_enable_synthesized_fonts
= 0;
6978 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
6979 doc
: /* Non-nil enables Windows palette management to map colors exactly. */);
6980 Vw32_enable_palette
= Qt
;
6982 DEFVAR_INT ("w32-mouse-button-tolerance",
6983 &w32_mouse_button_tolerance
,
6984 doc
: /* Analogue of double click interval for faking middle mouse events.
6985 The value is the minimum time in milliseconds that must elapse between
6986 left and right button down events before they are considered distinct events.
6987 If both mouse buttons are depressed within this interval, a middle mouse
6988 button down event is generated instead. */);
6989 w32_mouse_button_tolerance
= GetDoubleClickTime () / 2;
6991 DEFVAR_INT ("w32-mouse-move-interval",
6992 &w32_mouse_move_interval
,
6993 doc
: /* Minimum interval between mouse move events.
6994 The value is the minimum time in milliseconds that must elapse between
6995 successive mouse move (or scroll bar drag) events before they are
6996 reported as lisp events. */);
6997 w32_mouse_move_interval
= 0;
6999 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
7000 &w32_pass_extra_mouse_buttons_to_system
,
7001 doc
: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
7002 Recent versions of Windows support mice with up to five buttons.
7003 Since most applications don't support these extra buttons, most mouse
7004 drivers will allow you to map them to functions at the system level.
7005 If this variable is non-nil, Emacs will pass them on, allowing the
7006 system to handle them. */);
7007 w32_pass_extra_mouse_buttons_to_system
= 0;
7009 DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
7010 &w32_pass_multimedia_buttons_to_system
,
7011 doc
: /* If non-nil, media buttons are passed to Windows.
7012 Some modern keyboards contain buttons for controlling media players, web
7013 browsers and other applications. Generally these buttons are handled on a
7014 system wide basis, but by setting this to nil they are made available
7015 to Emacs for binding. Depending on your keyboard, additional keys that
7016 may be available are:
7018 browser-back, browser-forward, browser-refresh, browser-stop,
7019 browser-search, browser-favorites, browser-home,
7020 mail, mail-reply, mail-forward, mail-send,
7022 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
7023 spell-check, correction-list, toggle-dictate-command,
7024 media-next, media-previous, media-stop, media-play-pause, media-select,
7025 media-play, media-pause, media-record, media-fast-forward, media-rewind,
7026 media-channel-up, media-channel-down,
7027 volume-mute, volume-up, volume-down,
7028 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
7029 bass-down, bass-boost, bass-up, treble-down, treble-up */);
7030 w32_pass_multimedia_buttons_to_system
= 1;
7032 #if 0 /* TODO: Mouse cursor customization. */
7033 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
7034 doc
: /* The shape of the pointer when over text.
7035 Changing the value does not affect existing frames
7036 unless you set the mouse color. */);
7037 Vx_pointer_shape
= Qnil
;
7039 Vx_nontext_pointer_shape
= Qnil
;
7041 Vx_mode_pointer_shape
= Qnil
;
7043 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
7044 doc
: /* The shape of the pointer when Emacs is busy.
7045 This variable takes effect when you create a new frame
7046 or when you set the mouse color. */);
7047 Vx_hourglass_pointer_shape
= Qnil
;
7049 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7050 &Vx_sensitive_text_pointer_shape
,
7051 doc
: /* The shape of the pointer when over mouse-sensitive text.
7052 This variable takes effect when you create a new frame
7053 or when you set the mouse color. */);
7054 Vx_sensitive_text_pointer_shape
= Qnil
;
7056 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7057 &Vx_window_horizontal_drag_shape
,
7058 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
7059 This variable takes effect when you create a new frame
7060 or when you set the mouse color. */);
7061 Vx_window_horizontal_drag_shape
= Qnil
;
7064 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
7065 doc
: /* A string indicating the foreground color of the cursor box. */);
7066 Vx_cursor_fore_pixel
= Qnil
;
7068 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
7069 doc
: /* Maximum size for tooltips.
7070 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7071 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
7073 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
7074 doc
: /* Non-nil if no window manager is in use.
7075 Emacs doesn't try to figure this out; this is always nil
7076 unless you set it to something else. */);
7077 /* We don't have any way to find this out, so set it to nil
7078 and maybe the user would like to set it to t. */
7079 Vx_no_window_manager
= Qnil
;
7081 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7082 &Vx_pixel_size_width_font_regexp
,
7083 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7085 Since Emacs gets width of a font matching with this regexp from
7086 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7087 such a font. This is especially effective for such large fonts as
7088 Chinese, Japanese, and Korean. */);
7089 Vx_pixel_size_width_font_regexp
= Qnil
;
7091 DEFVAR_LISP ("w32-bdf-filename-alist",
7092 &Vw32_bdf_filename_alist
,
7093 doc
: /* List of bdf fonts and their corresponding filenames. */);
7094 Vw32_bdf_filename_alist
= Qnil
;
7096 DEFVAR_BOOL ("w32-strict-fontnames",
7097 &w32_strict_fontnames
,
7098 doc
: /* Non-nil means only use fonts that are exact matches for those requested.
7099 Default is nil, which allows old fontnames that are not XLFD compliant,
7100 and allows third-party CJK display to work by specifying false charset
7101 fields to trick Emacs into translating to Big5, SJIS etc.
7102 Setting this to t will prevent wrong fonts being selected when
7103 fontsets are automatically created. */);
7104 w32_strict_fontnames
= 0;
7106 DEFVAR_BOOL ("w32-strict-painting",
7107 &w32_strict_painting
,
7108 doc
: /* Non-nil means use strict rules for repainting frames.
7109 Set this to nil to get the old behavior for repainting; this should
7110 only be necessary if the default setting causes problems. */);
7111 w32_strict_painting
= 1;
7113 #if 0 /* TODO: Port to W32 */
7114 defsubr (&Sx_change_window_property
);
7115 defsubr (&Sx_delete_window_property
);
7116 defsubr (&Sx_window_property
);
7118 defsubr (&Sxw_display_color_p
);
7119 defsubr (&Sx_display_grayscale_p
);
7120 defsubr (&Sxw_color_defined_p
);
7121 defsubr (&Sxw_color_values
);
7122 defsubr (&Sx_server_max_request_size
);
7123 defsubr (&Sx_server_vendor
);
7124 defsubr (&Sx_server_version
);
7125 defsubr (&Sx_display_pixel_width
);
7126 defsubr (&Sx_display_pixel_height
);
7127 defsubr (&Sx_display_mm_width
);
7128 defsubr (&Sx_display_mm_height
);
7129 defsubr (&Sx_display_screens
);
7130 defsubr (&Sx_display_planes
);
7131 defsubr (&Sx_display_color_cells
);
7132 defsubr (&Sx_display_visual_class
);
7133 defsubr (&Sx_display_backing_store
);
7134 defsubr (&Sx_display_save_under
);
7135 defsubr (&Sx_create_frame
);
7136 defsubr (&Sx_open_connection
);
7137 defsubr (&Sx_close_connection
);
7138 defsubr (&Sx_display_list
);
7139 defsubr (&Sx_synchronize
);
7140 defsubr (&Sx_focus_frame
);
7142 /* W32 specific functions */
7144 defsubr (&Sw32_define_rgb_color
);
7145 defsubr (&Sw32_default_color_map
);
7146 defsubr (&Sw32_send_sys_command
);
7147 defsubr (&Sw32_shell_execute
);
7148 defsubr (&Sw32_register_hot_key
);
7149 defsubr (&Sw32_unregister_hot_key
);
7150 defsubr (&Sw32_registered_hot_keys
);
7151 defsubr (&Sw32_reconstruct_hot_key
);
7152 defsubr (&Sw32_toggle_lock_key
);
7153 defsubr (&Sw32_window_exists_p
);
7154 defsubr (&Sw32_battery_status
);
7156 defsubr (&Sfile_system_info
);
7157 defsubr (&Sdefault_printer_name
);
7159 check_window_system_func
= check_w32
;
7162 hourglass_timer
= 0;
7163 hourglass_hwnd
= NULL
;
7165 defsubr (&Sx_show_tip
);
7166 defsubr (&Sx_hide_tip
);
7168 staticpro (&tip_timer
);
7170 staticpro (&tip_frame
);
7172 last_show_tip_args
= Qnil
;
7173 staticpro (&last_show_tip_args
);
7175 defsubr (&Sx_file_dialog
);
7176 defsubr (&Ssystem_move_file_to_trash
);
7181 globals_of_w32fns is used to initialize those global variables that
7182 must always be initialized on startup even when the global variable
7183 initialized is non zero (see the function main in emacs.c).
7184 globals_of_w32fns is called from syms_of_w32fns when the global
7185 variable initialized is 0 and directly from main when initialized
7189 globals_of_w32fns (void)
7191 HMODULE user32_lib
= GetModuleHandle ("user32.dll");
7193 TrackMouseEvent not available in all versions of Windows, so must load
7194 it dynamically. Do it once, here, instead of every time it is used.
7196 track_mouse_event_fn
= (TrackMouseEvent_Proc
)
7197 GetProcAddress (user32_lib
, "TrackMouseEvent");
7198 /* ditto for GetClipboardSequenceNumber. */
7199 clipboard_sequence_fn
= (ClipboardSequence_Proc
)
7200 GetProcAddress (user32_lib
, "GetClipboardSequenceNumber");
7202 monitor_from_point_fn
= (MonitorFromPoint_Proc
)
7203 GetProcAddress (user32_lib
, "MonitorFromPoint");
7204 get_monitor_info_fn
= (GetMonitorInfo_Proc
)
7205 GetProcAddress (user32_lib
, "GetMonitorInfoA");
7208 HMODULE imm32_lib
= GetModuleHandle ("imm32.dll");
7209 get_composition_string_fn
= (ImmGetCompositionString_Proc
)
7210 GetProcAddress (imm32_lib
, "ImmGetCompositionStringW");
7211 get_ime_context_fn
= (ImmGetContext_Proc
)
7212 GetProcAddress (imm32_lib
, "ImmGetContext");
7213 release_ime_context_fn
= (ImmReleaseContext_Proc
)
7214 GetProcAddress (imm32_lib
, "ImmReleaseContext");
7215 set_ime_composition_window_fn
= (ImmSetCompositionWindow_Proc
)
7216 GetProcAddress (imm32_lib
, "ImmSetCompositionWindow");
7218 DEFVAR_INT ("w32-ansi-code-page",
7219 &w32_ansi_code_page
,
7220 doc
: /* The ANSI code page used by the system. */);
7221 w32_ansi_code_page
= GetACP ();
7223 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
7224 InitCommonControls ();
7226 syms_of_w32uniscribe ();
7235 button
= MessageBox (NULL
,
7236 "A fatal error has occurred!\n\n"
7237 "Would you like to attach a debugger?\n\n"
7238 "Select YES to debug, NO to abort Emacs"
7240 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
7241 "\"continue\" inside GDB before clicking YES.)"
7243 , "Emacs Abort Dialog",
7244 MB_ICONEXCLAMATION
| MB_TASKMODAL
7245 | MB_SETFOREGROUND
| MB_YESNO
);
7250 exit (2); /* tell the compiler we will never return */
7258 /* For convenience when debugging. */
7260 w32_last_error (void)
7262 return GetLastError ();
7265 /* arch-tag: 707589ab-b9be-4638-8cdd-74629cc9b446
7266 (do not change this comment) */