1 /* Graphical user interface functions for the Microsoft Windows API.
3 Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* Added by Kevin Gallo */
34 #include "character.h"
36 #include "intervals.h"
37 #include "dispextern.h"
39 #include "blockinput.h"
46 #include "termhooks.h"
56 #include "bitmaps/gray.xbm"
71 #ifndef FOF_NO_CONNECTED_ELEMENTS
72 #define FOF_NO_CONNECTED_ELEMENTS 0x2000
75 void syms_of_w32fns (void);
76 void globals_of_w32fns (void);
78 extern void free_frame_menubar (struct frame
*);
79 extern double atof (const char *);
80 extern int w32_console_toggle_lock_key (int, Lisp_Object
);
81 extern void w32_menu_display_help (HWND
, HMENU
, UINT
, UINT
);
82 extern void w32_free_menu_strings (HWND
);
83 extern const char *map_w32_filename (const char *, const char **);
84 extern char * w32_strerror (int error_no
);
86 /* If non-NULL, a handle to a frame where to display the hourglass cursor. */
87 static HWND hourglass_hwnd
= NULL
;
90 #define IDC_HAND MAKEINTRESOURCE(32649)
93 /* Nonzero if using Windows. */
95 static int w32_in_use
;
97 Lisp_Object Qsuppress_icon
;
98 Lisp_Object Qundefined_color
;
99 Lisp_Object Qcancel_timer
;
100 Lisp_Object Qfont_param
;
106 Lisp_Object Qcontrol
;
110 /* Prefix for system colors. */
111 #define SYSTEM_COLOR_PREFIX "System"
112 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
114 /* State variables for emulating a three button mouse. */
119 static int button_state
= 0;
120 static W32Msg saved_mouse_button_msg
;
121 static unsigned mouse_button_timer
= 0; /* non-zero when timer is active */
122 static W32Msg saved_mouse_move_msg
;
123 static unsigned mouse_move_timer
= 0;
125 /* Window that is tracking the mouse. */
126 static HWND track_mouse_window
;
128 /* Multi-monitor API definitions that are not pulled from the headers
129 since we are compiling for NT 4. */
130 #ifndef MONITOR_DEFAULT_TO_NEAREST
131 #define MONITOR_DEFAULT_TO_NEAREST 2
133 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
134 To avoid a compile error on one or the other, redefine with a new name. */
143 /* Reportedly, MSVC does not have this in its headers. */
144 #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
145 DECLARE_HANDLE(HMONITOR
);
148 typedef BOOL (WINAPI
* TrackMouseEvent_Proc
)
149 (IN OUT LPTRACKMOUSEEVENT lpEventTrack
);
150 typedef LONG (WINAPI
* ImmGetCompositionString_Proc
)
151 (IN HIMC context
, IN DWORD index
, OUT LPVOID buffer
, IN DWORD bufLen
);
152 typedef HIMC (WINAPI
* ImmGetContext_Proc
) (IN HWND window
);
153 typedef HWND (WINAPI
* ImmReleaseContext_Proc
) (IN HWND wnd
, IN HIMC context
);
154 typedef HWND (WINAPI
* ImmSetCompositionWindow_Proc
) (IN HIMC context
,
155 IN COMPOSITIONFORM
*form
);
156 typedef HMONITOR (WINAPI
* MonitorFromPoint_Proc
) (IN POINT pt
, IN DWORD flags
);
157 typedef BOOL (WINAPI
* GetMonitorInfo_Proc
)
158 (IN HMONITOR monitor
, OUT
struct MONITOR_INFO
* info
);
160 TrackMouseEvent_Proc track_mouse_event_fn
= NULL
;
161 ImmGetCompositionString_Proc get_composition_string_fn
= NULL
;
162 ImmGetContext_Proc get_ime_context_fn
= NULL
;
163 ImmReleaseContext_Proc release_ime_context_fn
= NULL
;
164 ImmSetCompositionWindow_Proc set_ime_composition_window_fn
= NULL
;
165 MonitorFromPoint_Proc monitor_from_point_fn
= NULL
;
166 GetMonitorInfo_Proc get_monitor_info_fn
= NULL
;
169 #define unicode_append_menu AppendMenuW
170 #else /* !NTGUI_UNICODE */
171 extern AppendMenuW_Proc unicode_append_menu
;
172 #endif /* NTGUI_UNICODE */
174 /* Flag to selectively ignore WM_IME_CHAR messages. */
175 static int ignore_ime_char
= 0;
177 /* W95 mousewheel handler */
178 unsigned int msh_mousewheel
= 0;
181 #define MOUSE_BUTTON_ID 1
182 #define MOUSE_MOVE_ID 2
183 #define MENU_FREE_ID 3
184 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
186 #define MENU_FREE_DELAY 1000
187 static unsigned menu_free_timer
= 0;
190 static int image_cache_refcount
, dpyinfo_refcount
;
193 static HWND w32_visible_system_caret_hwnd
;
195 static int w32_unicode_gui
;
198 extern HMENU current_popup_menu
;
199 static int menubar_in_use
= 0;
201 /* From w32uniscribe.c */
202 extern void syms_of_w32uniscribe (void);
203 extern int uniscribe_available
;
205 /* Function prototypes for hourglass support. */
206 static void w32_show_hourglass (struct frame
*);
207 static void w32_hide_hourglass (void);
210 /* From w32inevet.c */
211 extern int faked_key
;
212 #endif /* WINDOWSNT */
214 /* This gives us the page size and the size of the allocation unit on NT. */
215 SYSTEM_INFO sysinfo_cache
;
217 /* This gives us version, build, and platform identification. */
218 OSVERSIONINFO osinfo_cache
;
220 unsigned long syspage_mask
= 0;
222 /* The major and minor versions of NT. */
223 int w32_major_version
;
224 int w32_minor_version
;
225 int w32_build_number
;
227 /* Distinguish between Windows NT and Windows 95. */
231 HINSTANCE hinst
= NULL
;
234 static unsigned int sound_type
= 0xFFFFFFFF;
235 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
238 /* Error if we are not connected to MS-Windows. */
243 error ("MS-Windows not in use or not initialized");
246 /* Nonzero if we can use mouse menus.
247 You should not call this unless HAVE_MENUS is defined. */
255 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
256 and checking validity for W32. */
259 check_x_frame (Lisp_Object frame
)
264 frame
= selected_frame
;
265 CHECK_LIVE_FRAME (frame
);
267 if (! FRAME_W32_P (f
))
268 error ("Non-W32 frame used");
272 /* Let the user specify a display with a frame.
273 nil stands for the selected frame--or, if that is not a w32 frame,
274 the first display on the list. */
276 struct w32_display_info
*
277 check_x_display_info (Lisp_Object frame
)
281 struct frame
*sf
= XFRAME (selected_frame
);
283 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
284 return FRAME_W32_DISPLAY_INFO (sf
);
286 return &one_w32_display_info
;
288 else if (STRINGP (frame
))
289 return x_display_info_for_name (frame
);
294 CHECK_LIVE_FRAME (frame
);
296 if (! FRAME_W32_P (f
))
297 error ("Non-W32 frame used");
298 return FRAME_W32_DISPLAY_INFO (f
);
302 /* Return the Emacs frame-object corresponding to an w32 window.
303 It could be the frame's main window or an icon window. */
305 /* This function can be called during GC, so use GC_xxx type test macros. */
308 x_window_to_frame (struct w32_display_info
*dpyinfo
, HWND wdesc
)
310 Lisp_Object tail
, frame
;
313 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
319 if (!FRAME_W32_P (f
) || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
322 if (FRAME_W32_WINDOW (f
) == wdesc
)
329 static Lisp_Object
unwind_create_frame (Lisp_Object
);
330 static Lisp_Object
unwind_create_tip_frame (Lisp_Object
);
331 static void my_create_window (struct frame
*);
332 static void my_create_tip_window (struct frame
*);
334 /* TODO: Native Input Method support; see x_create_im. */
335 void x_set_foreground_color (struct frame
*, Lisp_Object
, Lisp_Object
);
336 void x_set_background_color (struct frame
*, Lisp_Object
, Lisp_Object
);
337 void x_set_mouse_color (struct frame
*, Lisp_Object
, Lisp_Object
);
338 void x_set_cursor_color (struct frame
*, Lisp_Object
, Lisp_Object
);
339 void x_set_border_color (struct frame
*, Lisp_Object
, Lisp_Object
);
340 void x_set_cursor_type (struct frame
*, Lisp_Object
, Lisp_Object
);
341 void x_set_icon_type (struct frame
*, Lisp_Object
, Lisp_Object
);
342 void x_set_icon_name (struct frame
*, Lisp_Object
, Lisp_Object
);
343 void x_explicitly_set_name (struct frame
*, Lisp_Object
, Lisp_Object
);
344 void x_set_menu_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
345 void x_set_title (struct frame
*, Lisp_Object
, Lisp_Object
);
346 void x_set_tool_bar_lines (struct frame
*, Lisp_Object
, Lisp_Object
);
351 /* Store the screen positions of frame F into XPTR and YPTR.
352 These are the positions of the containing window manager window,
353 not Emacs's own window. */
356 x_real_positions (FRAME_PTR f
, int *xptr
, int *yptr
)
361 /* Get the bounds of the WM window. */
362 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
367 /* Convert (0, 0) in the client area to screen co-ordinates. */
368 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
370 /* Remember x_pixels_diff and y_pixels_diff. */
371 f
->x_pixels_diff
= pt
.x
- rect
.left
;
372 f
->y_pixels_diff
= pt
.y
- rect
.top
;
380 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
,
381 Sw32_define_rgb_color
, 4, 4, 0,
382 doc
: /* Convert RGB numbers to a Windows color reference and associate with NAME.
383 This adds or updates a named color to `w32-color-map', making it
384 available for use. The original entry's RGB ref is returned, or nil
385 if the entry is new. */)
386 (Lisp_Object red
, Lisp_Object green
, Lisp_Object blue
, Lisp_Object name
)
389 Lisp_Object oldrgb
= Qnil
;
393 CHECK_NUMBER (green
);
397 XSETINT (rgb
, RGB (XUINT (red
), XUINT (green
), XUINT (blue
)));
401 /* replace existing entry in w32-color-map or add new entry. */
402 entry
= Fassoc (name
, Vw32_color_map
);
405 entry
= Fcons (name
, rgb
);
406 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
410 oldrgb
= Fcdr (entry
);
411 Fsetcdr (entry
, rgb
);
419 /* The default colors for the w32 color map */
420 typedef struct colormap_t
426 colormap_t w32_color_map
[] =
428 {"snow" , PALETTERGB (255,250,250)},
429 {"ghost white" , PALETTERGB (248,248,255)},
430 {"GhostWhite" , PALETTERGB (248,248,255)},
431 {"white smoke" , PALETTERGB (245,245,245)},
432 {"WhiteSmoke" , PALETTERGB (245,245,245)},
433 {"gainsboro" , PALETTERGB (220,220,220)},
434 {"floral white" , PALETTERGB (255,250,240)},
435 {"FloralWhite" , PALETTERGB (255,250,240)},
436 {"old lace" , PALETTERGB (253,245,230)},
437 {"OldLace" , PALETTERGB (253,245,230)},
438 {"linen" , PALETTERGB (250,240,230)},
439 {"antique white" , PALETTERGB (250,235,215)},
440 {"AntiqueWhite" , PALETTERGB (250,235,215)},
441 {"papaya whip" , PALETTERGB (255,239,213)},
442 {"PapayaWhip" , PALETTERGB (255,239,213)},
443 {"blanched almond" , PALETTERGB (255,235,205)},
444 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
445 {"bisque" , PALETTERGB (255,228,196)},
446 {"peach puff" , PALETTERGB (255,218,185)},
447 {"PeachPuff" , PALETTERGB (255,218,185)},
448 {"navajo white" , PALETTERGB (255,222,173)},
449 {"NavajoWhite" , PALETTERGB (255,222,173)},
450 {"moccasin" , PALETTERGB (255,228,181)},
451 {"cornsilk" , PALETTERGB (255,248,220)},
452 {"ivory" , PALETTERGB (255,255,240)},
453 {"lemon chiffon" , PALETTERGB (255,250,205)},
454 {"LemonChiffon" , PALETTERGB (255,250,205)},
455 {"seashell" , PALETTERGB (255,245,238)},
456 {"honeydew" , PALETTERGB (240,255,240)},
457 {"mint cream" , PALETTERGB (245,255,250)},
458 {"MintCream" , PALETTERGB (245,255,250)},
459 {"azure" , PALETTERGB (240,255,255)},
460 {"alice blue" , PALETTERGB (240,248,255)},
461 {"AliceBlue" , PALETTERGB (240,248,255)},
462 {"lavender" , PALETTERGB (230,230,250)},
463 {"lavender blush" , PALETTERGB (255,240,245)},
464 {"LavenderBlush" , PALETTERGB (255,240,245)},
465 {"misty rose" , PALETTERGB (255,228,225)},
466 {"MistyRose" , PALETTERGB (255,228,225)},
467 {"white" , PALETTERGB (255,255,255)},
468 {"black" , PALETTERGB ( 0, 0, 0)},
469 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
470 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
471 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
472 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
473 {"dim gray" , PALETTERGB (105,105,105)},
474 {"DimGray" , PALETTERGB (105,105,105)},
475 {"dim grey" , PALETTERGB (105,105,105)},
476 {"DimGrey" , PALETTERGB (105,105,105)},
477 {"slate gray" , PALETTERGB (112,128,144)},
478 {"SlateGray" , PALETTERGB (112,128,144)},
479 {"slate grey" , PALETTERGB (112,128,144)},
480 {"SlateGrey" , PALETTERGB (112,128,144)},
481 {"light slate gray" , PALETTERGB (119,136,153)},
482 {"LightSlateGray" , PALETTERGB (119,136,153)},
483 {"light slate grey" , PALETTERGB (119,136,153)},
484 {"LightSlateGrey" , PALETTERGB (119,136,153)},
485 {"gray" , PALETTERGB (190,190,190)},
486 {"grey" , PALETTERGB (190,190,190)},
487 {"light grey" , PALETTERGB (211,211,211)},
488 {"LightGrey" , PALETTERGB (211,211,211)},
489 {"light gray" , PALETTERGB (211,211,211)},
490 {"LightGray" , PALETTERGB (211,211,211)},
491 {"midnight blue" , PALETTERGB ( 25, 25,112)},
492 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
493 {"navy" , PALETTERGB ( 0, 0,128)},
494 {"navy blue" , PALETTERGB ( 0, 0,128)},
495 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
496 {"cornflower blue" , PALETTERGB (100,149,237)},
497 {"CornflowerBlue" , PALETTERGB (100,149,237)},
498 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
499 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
500 {"slate blue" , PALETTERGB (106, 90,205)},
501 {"SlateBlue" , PALETTERGB (106, 90,205)},
502 {"medium slate blue" , PALETTERGB (123,104,238)},
503 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
504 {"light slate blue" , PALETTERGB (132,112,255)},
505 {"LightSlateBlue" , PALETTERGB (132,112,255)},
506 {"medium blue" , PALETTERGB ( 0, 0,205)},
507 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
508 {"royal blue" , PALETTERGB ( 65,105,225)},
509 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
510 {"blue" , PALETTERGB ( 0, 0,255)},
511 {"dodger blue" , PALETTERGB ( 30,144,255)},
512 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
513 {"deep sky blue" , PALETTERGB ( 0,191,255)},
514 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
515 {"sky blue" , PALETTERGB (135,206,235)},
516 {"SkyBlue" , PALETTERGB (135,206,235)},
517 {"light sky blue" , PALETTERGB (135,206,250)},
518 {"LightSkyBlue" , PALETTERGB (135,206,250)},
519 {"steel blue" , PALETTERGB ( 70,130,180)},
520 {"SteelBlue" , PALETTERGB ( 70,130,180)},
521 {"light steel blue" , PALETTERGB (176,196,222)},
522 {"LightSteelBlue" , PALETTERGB (176,196,222)},
523 {"light blue" , PALETTERGB (173,216,230)},
524 {"LightBlue" , PALETTERGB (173,216,230)},
525 {"powder blue" , PALETTERGB (176,224,230)},
526 {"PowderBlue" , PALETTERGB (176,224,230)},
527 {"pale turquoise" , PALETTERGB (175,238,238)},
528 {"PaleTurquoise" , PALETTERGB (175,238,238)},
529 {"dark turquoise" , PALETTERGB ( 0,206,209)},
530 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
531 {"medium turquoise" , PALETTERGB ( 72,209,204)},
532 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
533 {"turquoise" , PALETTERGB ( 64,224,208)},
534 {"cyan" , PALETTERGB ( 0,255,255)},
535 {"light cyan" , PALETTERGB (224,255,255)},
536 {"LightCyan" , PALETTERGB (224,255,255)},
537 {"cadet blue" , PALETTERGB ( 95,158,160)},
538 {"CadetBlue" , PALETTERGB ( 95,158,160)},
539 {"medium aquamarine" , PALETTERGB (102,205,170)},
540 {"MediumAquamarine" , PALETTERGB (102,205,170)},
541 {"aquamarine" , PALETTERGB (127,255,212)},
542 {"dark green" , PALETTERGB ( 0,100, 0)},
543 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
544 {"dark olive green" , PALETTERGB ( 85,107, 47)},
545 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
546 {"dark sea green" , PALETTERGB (143,188,143)},
547 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
548 {"sea green" , PALETTERGB ( 46,139, 87)},
549 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
550 {"medium sea green" , PALETTERGB ( 60,179,113)},
551 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
552 {"light sea green" , PALETTERGB ( 32,178,170)},
553 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
554 {"pale green" , PALETTERGB (152,251,152)},
555 {"PaleGreen" , PALETTERGB (152,251,152)},
556 {"spring green" , PALETTERGB ( 0,255,127)},
557 {"SpringGreen" , PALETTERGB ( 0,255,127)},
558 {"lawn green" , PALETTERGB (124,252, 0)},
559 {"LawnGreen" , PALETTERGB (124,252, 0)},
560 {"green" , PALETTERGB ( 0,255, 0)},
561 {"chartreuse" , PALETTERGB (127,255, 0)},
562 {"medium spring green" , PALETTERGB ( 0,250,154)},
563 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
564 {"green yellow" , PALETTERGB (173,255, 47)},
565 {"GreenYellow" , PALETTERGB (173,255, 47)},
566 {"lime green" , PALETTERGB ( 50,205, 50)},
567 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
568 {"yellow green" , PALETTERGB (154,205, 50)},
569 {"YellowGreen" , PALETTERGB (154,205, 50)},
570 {"forest green" , PALETTERGB ( 34,139, 34)},
571 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
572 {"olive drab" , PALETTERGB (107,142, 35)},
573 {"OliveDrab" , PALETTERGB (107,142, 35)},
574 {"dark khaki" , PALETTERGB (189,183,107)},
575 {"DarkKhaki" , PALETTERGB (189,183,107)},
576 {"khaki" , PALETTERGB (240,230,140)},
577 {"pale goldenrod" , PALETTERGB (238,232,170)},
578 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
579 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
580 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
581 {"light yellow" , PALETTERGB (255,255,224)},
582 {"LightYellow" , PALETTERGB (255,255,224)},
583 {"yellow" , PALETTERGB (255,255, 0)},
584 {"gold" , PALETTERGB (255,215, 0)},
585 {"light goldenrod" , PALETTERGB (238,221,130)},
586 {"LightGoldenrod" , PALETTERGB (238,221,130)},
587 {"goldenrod" , PALETTERGB (218,165, 32)},
588 {"dark goldenrod" , PALETTERGB (184,134, 11)},
589 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
590 {"rosy brown" , PALETTERGB (188,143,143)},
591 {"RosyBrown" , PALETTERGB (188,143,143)},
592 {"indian red" , PALETTERGB (205, 92, 92)},
593 {"IndianRed" , PALETTERGB (205, 92, 92)},
594 {"saddle brown" , PALETTERGB (139, 69, 19)},
595 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
596 {"sienna" , PALETTERGB (160, 82, 45)},
597 {"peru" , PALETTERGB (205,133, 63)},
598 {"burlywood" , PALETTERGB (222,184,135)},
599 {"beige" , PALETTERGB (245,245,220)},
600 {"wheat" , PALETTERGB (245,222,179)},
601 {"sandy brown" , PALETTERGB (244,164, 96)},
602 {"SandyBrown" , PALETTERGB (244,164, 96)},
603 {"tan" , PALETTERGB (210,180,140)},
604 {"chocolate" , PALETTERGB (210,105, 30)},
605 {"firebrick" , PALETTERGB (178,34, 34)},
606 {"brown" , PALETTERGB (165,42, 42)},
607 {"dark salmon" , PALETTERGB (233,150,122)},
608 {"DarkSalmon" , PALETTERGB (233,150,122)},
609 {"salmon" , PALETTERGB (250,128,114)},
610 {"light salmon" , PALETTERGB (255,160,122)},
611 {"LightSalmon" , PALETTERGB (255,160,122)},
612 {"orange" , PALETTERGB (255,165, 0)},
613 {"dark orange" , PALETTERGB (255,140, 0)},
614 {"DarkOrange" , PALETTERGB (255,140, 0)},
615 {"coral" , PALETTERGB (255,127, 80)},
616 {"light coral" , PALETTERGB (240,128,128)},
617 {"LightCoral" , PALETTERGB (240,128,128)},
618 {"tomato" , PALETTERGB (255, 99, 71)},
619 {"orange red" , PALETTERGB (255, 69, 0)},
620 {"OrangeRed" , PALETTERGB (255, 69, 0)},
621 {"red" , PALETTERGB (255, 0, 0)},
622 {"hot pink" , PALETTERGB (255,105,180)},
623 {"HotPink" , PALETTERGB (255,105,180)},
624 {"deep pink" , PALETTERGB (255, 20,147)},
625 {"DeepPink" , PALETTERGB (255, 20,147)},
626 {"pink" , PALETTERGB (255,192,203)},
627 {"light pink" , PALETTERGB (255,182,193)},
628 {"LightPink" , PALETTERGB (255,182,193)},
629 {"pale violet red" , PALETTERGB (219,112,147)},
630 {"PaleVioletRed" , PALETTERGB (219,112,147)},
631 {"maroon" , PALETTERGB (176, 48, 96)},
632 {"medium violet red" , PALETTERGB (199, 21,133)},
633 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
634 {"violet red" , PALETTERGB (208, 32,144)},
635 {"VioletRed" , PALETTERGB (208, 32,144)},
636 {"magenta" , PALETTERGB (255, 0,255)},
637 {"violet" , PALETTERGB (238,130,238)},
638 {"plum" , PALETTERGB (221,160,221)},
639 {"orchid" , PALETTERGB (218,112,214)},
640 {"medium orchid" , PALETTERGB (186, 85,211)},
641 {"MediumOrchid" , PALETTERGB (186, 85,211)},
642 {"dark orchid" , PALETTERGB (153, 50,204)},
643 {"DarkOrchid" , PALETTERGB (153, 50,204)},
644 {"dark violet" , PALETTERGB (148, 0,211)},
645 {"DarkViolet" , PALETTERGB (148, 0,211)},
646 {"blue violet" , PALETTERGB (138, 43,226)},
647 {"BlueViolet" , PALETTERGB (138, 43,226)},
648 {"purple" , PALETTERGB (160, 32,240)},
649 {"medium purple" , PALETTERGB (147,112,219)},
650 {"MediumPurple" , PALETTERGB (147,112,219)},
651 {"thistle" , PALETTERGB (216,191,216)},
652 {"gray0" , PALETTERGB ( 0, 0, 0)},
653 {"grey0" , PALETTERGB ( 0, 0, 0)},
654 {"dark grey" , PALETTERGB (169,169,169)},
655 {"DarkGrey" , PALETTERGB (169,169,169)},
656 {"dark gray" , PALETTERGB (169,169,169)},
657 {"DarkGray" , PALETTERGB (169,169,169)},
658 {"dark blue" , PALETTERGB ( 0, 0,139)},
659 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
660 {"dark cyan" , PALETTERGB ( 0,139,139)},
661 {"DarkCyan" , PALETTERGB ( 0,139,139)},
662 {"dark magenta" , PALETTERGB (139, 0,139)},
663 {"DarkMagenta" , PALETTERGB (139, 0,139)},
664 {"dark red" , PALETTERGB (139, 0, 0)},
665 {"DarkRed" , PALETTERGB (139, 0, 0)},
666 {"light green" , PALETTERGB (144,238,144)},
667 {"LightGreen" , PALETTERGB (144,238,144)},
671 w32_default_color_map (void)
674 colormap_t
*pc
= w32_color_map
;
681 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
683 cmap
= Fcons (Fcons (build_string (pc
->name
),
684 make_number (pc
->colorref
)),
692 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
693 0, 0, 0, doc
: /* Return the default color map. */)
696 return w32_default_color_map ();
700 w32_color_map_lookup (char *colorname
)
702 Lisp_Object tail
, ret
= Qnil
;
706 for (tail
= Vw32_color_map
; CONSP (tail
); tail
= XCDR (tail
))
708 register Lisp_Object elt
, tem
;
711 if (!CONSP (elt
)) continue;
715 if (lstrcmpi (SDATA (tem
), colorname
) == 0)
731 add_system_logical_colors_to_map (Lisp_Object
*system_colors
)
735 /* Other registry operations are done with input blocked. */
738 /* Look for "Control Panel/Colors" under User and Machine registry
740 if (RegOpenKeyEx (HKEY_CURRENT_USER
, "Control Panel\\Colors", 0,
741 KEY_READ
, &colors_key
) == ERROR_SUCCESS
742 || RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Control Panel\\Colors", 0,
743 KEY_READ
, &colors_key
) == ERROR_SUCCESS
)
746 char color_buffer
[64];
747 char full_name_buffer
[MAX_PATH
+ SYSTEM_COLOR_PREFIX_LEN
];
749 DWORD name_size
, color_size
;
750 char *name_buffer
= full_name_buffer
+ SYSTEM_COLOR_PREFIX_LEN
;
752 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
753 color_size
= sizeof (color_buffer
);
755 strcpy (full_name_buffer
, SYSTEM_COLOR_PREFIX
);
757 while (RegEnumValueA (colors_key
, index
, name_buffer
, &name_size
,
758 NULL
, NULL
, color_buffer
, &color_size
)
762 if (sscanf (color_buffer
, " %u %u %u", &r
, &g
, &b
) == 3)
763 *system_colors
= Fcons (Fcons (build_string (full_name_buffer
),
764 make_number (RGB (r
, g
, b
))),
767 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
768 color_size
= sizeof (color_buffer
);
771 RegCloseKey (colors_key
);
779 x_to_w32_color (char * colorname
)
781 register Lisp_Object ret
= Qnil
;
785 if (colorname
[0] == '#')
787 /* Could be an old-style RGB Device specification. */
790 color
= colorname
+ 1;
792 size
= strlen (color
);
793 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
801 for (i
= 0; i
< 3; i
++)
807 /* The check for 'x' in the following conditional takes into
808 account the fact that strtol allows a "0x" in front of
809 our numbers, and we don't. */
810 if (!isxdigit (color
[0]) || color
[1] == 'x')
814 value
= strtoul (color
, &end
, 16);
816 if (errno
== ERANGE
|| end
- color
!= size
)
821 value
= value
* 0x10;
832 colorval
|= (value
<< pos
);
837 XSETINT (ret
, colorval
);
844 else if (strnicmp (colorname
, "rgb:", 4) == 0)
852 color
= colorname
+ 4;
853 for (i
= 0; i
< 3; i
++)
858 /* The check for 'x' in the following conditional takes into
859 account the fact that strtol allows a "0x" in front of
860 our numbers, and we don't. */
861 if (!isxdigit (color
[0]) || color
[1] == 'x')
863 value
= strtoul (color
, &end
, 16);
869 value
= value
* 0x10 + value
;
882 if (value
== ULONG_MAX
)
884 colorval
|= (value
<< pos
);
891 XSETINT (ret
, colorval
);
899 else if (strnicmp (colorname
, "rgbi:", 5) == 0)
901 /* This is an RGB Intensity specification. */
908 color
= colorname
+ 5;
909 for (i
= 0; i
< 3; i
++)
915 value
= strtod (color
, &end
);
918 if (value
< 0.0 || value
> 1.0)
920 val
= (UINT
)(0x100 * value
);
921 /* We used 0x100 instead of 0xFF to give a continuous
922 range between 0.0 and 1.0 inclusive. The next statement
923 fixes the 1.0 case. */
926 colorval
|= (val
<< pos
);
933 XSETINT (ret
, colorval
);
941 /* I am not going to attempt to handle any of the CIE color schemes
942 or TekHVC, since I don't know the algorithms for conversion to
945 /* If we fail to lookup the color name in w32_color_map, then check the
946 colorname to see if it can be crudely approximated: If the X color
947 ends in a number (e.g., "darkseagreen2"), strip the number and
948 return the result of looking up the base color name. */
949 ret
= w32_color_map_lookup (colorname
);
952 int len
= strlen (colorname
);
954 if (isdigit (colorname
[len
- 1]))
956 char *ptr
, *approx
= alloca (len
+ 1);
958 strcpy (approx
, colorname
);
959 ptr
= &approx
[len
- 1];
960 while (ptr
> approx
&& isdigit (*ptr
))
963 ret
= w32_color_map_lookup (approx
);
972 w32_regenerate_palette (FRAME_PTR f
)
974 struct w32_palette_entry
* list
;
975 LOGPALETTE
* log_palette
;
976 HPALETTE new_palette
;
979 /* don't bother trying to create palette if not supported */
980 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
983 log_palette
= (LOGPALETTE
*)
984 alloca (sizeof (LOGPALETTE
) +
985 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
986 log_palette
->palVersion
= 0x300;
987 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
989 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
991 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
992 i
++, list
= list
->next
)
993 log_palette
->palPalEntry
[i
] = list
->entry
;
995 new_palette
= CreatePalette (log_palette
);
999 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1000 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1001 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1003 /* Realize display palette and garbage all frames. */
1004 release_frame_dc (f
, get_frame_dc (f
));
1009 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1010 #define SET_W32_COLOR(pe, color) \
1013 pe.peRed = GetRValue (color); \
1014 pe.peGreen = GetGValue (color); \
1015 pe.peBlue = GetBValue (color); \
1020 /* Keep these around in case we ever want to track color usage. */
1022 w32_map_color (FRAME_PTR f
, COLORREF color
)
1024 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1026 if (NILP (Vw32_enable_palette
))
1029 /* check if color is already mapped */
1032 if (W32_COLOR (list
->entry
) == color
)
1040 /* not already mapped, so add to list and recreate Windows palette */
1041 list
= xmalloc (sizeof (struct w32_palette_entry
));
1042 SET_W32_COLOR (list
->entry
, color
);
1044 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1045 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1046 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1048 /* set flag that palette must be regenerated */
1049 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1053 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1055 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1056 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1058 if (NILP (Vw32_enable_palette
))
1061 /* check if color is already mapped */
1064 if (W32_COLOR (list
->entry
) == color
)
1066 if (--list
->refcount
== 0)
1070 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1080 /* set flag that palette must be regenerated */
1081 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1086 /* Gamma-correct COLOR on frame F. */
1089 gamma_correct (struct frame
*f
, COLORREF
*color
)
1093 *color
= PALETTERGB (
1094 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1095 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1096 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1101 /* Decide if color named COLOR is valid for the display associated with
1102 the selected frame; if so, return the rgb values in COLOR_DEF.
1103 If ALLOC is nonzero, allocate a new colormap cell. */
1106 w32_defined_color (FRAME_PTR f
, const char *color
, XColor
*color_def
, int alloc
)
1108 register Lisp_Object tem
;
1109 COLORREF w32_color_ref
;
1111 tem
= x_to_w32_color (color
);
1117 /* Apply gamma correction. */
1118 w32_color_ref
= XUINT (tem
);
1119 gamma_correct (f
, &w32_color_ref
);
1120 XSETINT (tem
, w32_color_ref
);
1123 /* Map this color to the palette if it is enabled. */
1124 if (!NILP (Vw32_enable_palette
))
1126 struct w32_palette_entry
* entry
=
1127 one_w32_display_info
.color_list
;
1128 struct w32_palette_entry
** prev
=
1129 &one_w32_display_info
.color_list
;
1131 /* check if color is already mapped */
1134 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1136 prev
= &entry
->next
;
1137 entry
= entry
->next
;
1140 if (entry
== NULL
&& alloc
)
1142 /* not already mapped, so add to list */
1143 entry
= xmalloc (sizeof (struct w32_palette_entry
));
1144 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1147 one_w32_display_info
.num_colors
++;
1149 /* set flag that palette must be regenerated */
1150 one_w32_display_info
.regen_palette
= TRUE
;
1153 /* Ensure COLORREF value is snapped to nearest color in (default)
1154 palette by simulating the PALETTERGB macro. This works whether
1155 or not the display device has a palette. */
1156 w32_color_ref
= XUINT (tem
) | 0x2000000;
1158 color_def
->pixel
= w32_color_ref
;
1159 color_def
->red
= GetRValue (w32_color_ref
) * 256;
1160 color_def
->green
= GetGValue (w32_color_ref
) * 256;
1161 color_def
->blue
= GetBValue (w32_color_ref
) * 256;
1171 /* Given a string ARG naming a color, compute a pixel value from it
1172 suitable for screen F.
1173 If F is not a color screen, return DEF (default) regardless of what
1177 x_decode_color (FRAME_PTR f
, Lisp_Object arg
, int def
)
1183 if (strcmp (SDATA (arg
), "black") == 0)
1184 return BLACK_PIX_DEFAULT (f
);
1185 else if (strcmp (SDATA (arg
), "white") == 0)
1186 return WHITE_PIX_DEFAULT (f
);
1188 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1191 /* w32_defined_color is responsible for coping with failures
1192 by looking for a near-miss. */
1193 if (w32_defined_color (f
, SDATA (arg
), &cdef
, 1))
1196 /* defined_color failed; return an ultimate default. */
1202 /* Functions called only from `x_set_frame_param'
1203 to set individual parameters.
1205 If FRAME_W32_WINDOW (f) is 0,
1206 the frame is being created and its window does not exist yet.
1207 In that case, just record the parameter's new value
1208 in the standard place; do not attempt to change the window. */
1211 x_set_foreground_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1213 struct w32_output
*x
= f
->output_data
.w32
;
1214 PIX_TYPE fg
, old_fg
;
1216 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1217 old_fg
= FRAME_FOREGROUND_PIXEL (f
);
1218 FRAME_FOREGROUND_PIXEL (f
) = fg
;
1220 if (FRAME_W32_WINDOW (f
) != 0)
1222 if (x
->cursor_pixel
== old_fg
)
1224 x
->cursor_pixel
= fg
;
1225 x
->cursor_gc
->background
= fg
;
1228 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1229 if (FRAME_VISIBLE_P (f
))
1235 x_set_background_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1237 FRAME_BACKGROUND_PIXEL (f
)
1238 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1240 if (FRAME_W32_WINDOW (f
) != 0)
1242 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
1243 FRAME_BACKGROUND_PIXEL (f
));
1245 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1247 if (FRAME_VISIBLE_P (f
))
1253 x_set_mouse_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1255 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
1259 if (!EQ (Qnil
, arg
))
1260 f
->output_data
.w32
->mouse_pixel
1261 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1262 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
1264 /* Don't let pointers be invisible. */
1265 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1266 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
1267 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
1269 #if 0 /* TODO : Mouse cursor customization. */
1272 /* It's not okay to crash if the user selects a screwy cursor. */
1273 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1275 if (!EQ (Qnil
, Vx_pointer_shape
))
1277 CHECK_NUMBER (Vx_pointer_shape
);
1278 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1281 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1282 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1284 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1286 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1287 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1288 XINT (Vx_nontext_pointer_shape
));
1291 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1292 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1294 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
1296 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1297 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1298 XINT (Vx_hourglass_pointer_shape
));
1301 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
1302 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
1304 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1305 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1307 CHECK_NUMBER (Vx_mode_pointer_shape
);
1308 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1309 XINT (Vx_mode_pointer_shape
));
1312 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1313 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1315 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1317 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1319 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1320 XINT (Vx_sensitive_text_pointer_shape
));
1323 hand_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1325 if (!NILP (Vx_window_horizontal_drag_shape
))
1327 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1328 horizontal_drag_cursor
1329 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1330 XINT (Vx_window_horizontal_drag_shape
));
1333 horizontal_drag_cursor
1334 = XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_sb_h_double_arrow
);
1336 /* Check and report errors with the above calls. */
1337 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1338 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1341 XColor fore_color
, back_color
;
1343 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1344 back_color
.pixel
= mask_color
;
1345 XQueryColor (FRAME_W32_DISPLAY (f
),
1346 DefaultColormap (FRAME_W32_DISPLAY (f
),
1347 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1349 XQueryColor (FRAME_W32_DISPLAY (f
),
1350 DefaultColormap (FRAME_W32_DISPLAY (f
),
1351 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1353 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1354 &fore_color
, &back_color
);
1355 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1356 &fore_color
, &back_color
);
1357 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1358 &fore_color
, &back_color
);
1359 XRecolorCursor (FRAME_W32_DISPLAY (f
), hand_cursor
,
1360 &fore_color
, &back_color
);
1361 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
1362 &fore_color
, &back_color
);
1365 if (FRAME_W32_WINDOW (f
) != 0)
1366 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1368 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1369 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1370 f
->output_data
.w32
->text_cursor
= cursor
;
1372 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1373 && f
->output_data
.w32
->nontext_cursor
!= 0)
1374 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1375 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1377 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
1378 && f
->output_data
.w32
->hourglass_cursor
!= 0)
1379 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
1380 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
1382 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1383 && f
->output_data
.w32
->modeline_cursor
!= 0)
1384 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1385 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1387 if (hand_cursor
!= f
->output_data
.w32
->hand_cursor
1388 && f
->output_data
.w32
->hand_cursor
!= 0)
1389 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hand_cursor
);
1390 f
->output_data
.w32
->hand_cursor
= hand_cursor
;
1392 XFlush (FRAME_W32_DISPLAY (f
));
1395 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1400 x_set_cursor_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1402 unsigned long fore_pixel
, pixel
;
1404 if (!NILP (Vx_cursor_fore_pixel
))
1405 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1406 WHITE_PIX_DEFAULT (f
));
1408 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1410 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1412 /* Make sure that the cursor color differs from the background color. */
1413 if (pixel
== FRAME_BACKGROUND_PIXEL (f
))
1415 pixel
= f
->output_data
.w32
->mouse_pixel
;
1416 if (pixel
== fore_pixel
)
1417 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1420 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1421 f
->output_data
.w32
->cursor_pixel
= pixel
;
1423 if (FRAME_W32_WINDOW (f
) != 0)
1426 /* Update frame's cursor_gc. */
1427 f
->output_data
.w32
->cursor_gc
->foreground
= fore_pixel
;
1428 f
->output_data
.w32
->cursor_gc
->background
= pixel
;
1432 if (FRAME_VISIBLE_P (f
))
1434 x_update_cursor (f
, 0);
1435 x_update_cursor (f
, 1);
1439 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1442 /* Set the border-color of frame F to pixel value PIX.
1443 Note that this does not fully take effect if done before
1447 x_set_border_pixel (struct frame
*f
, int pix
)
1450 f
->output_data
.w32
->border_pixel
= pix
;
1452 if (FRAME_W32_WINDOW (f
) != 0 && f
->border_width
> 0)
1454 if (FRAME_VISIBLE_P (f
))
1459 /* Set the border-color of frame F to value described by ARG.
1460 ARG can be a string naming a color.
1461 The border-color is used for the border that is drawn by the server.
1462 Note that this does not fully take effect if done before
1463 F has a window; it must be redone when the window is created. */
1466 x_set_border_color (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1471 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1472 x_set_border_pixel (f
, pix
);
1473 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1478 x_set_cursor_type (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1480 set_frame_cursor_types (f
, arg
);
1482 /* Make sure the cursor gets redrawn. */
1483 cursor_type_changed
= 1;
1487 x_set_icon_type (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1491 if (NILP (arg
) && NILP (oldval
))
1494 if (STRINGP (arg
) && STRINGP (oldval
)
1495 && EQ (Fstring_equal (oldval
, arg
), Qt
))
1498 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
1503 result
= x_bitmap_icon (f
, arg
);
1507 error ("No icon window available");
1514 x_set_icon_name (struct frame
*f
, Lisp_Object arg
, Lisp_Object oldval
)
1518 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1521 else if (!NILP (arg
) || NILP (oldval
))
1524 fset_icon_name (f
, arg
);
1527 if (f
->output_data
.w32
->icon_bitmap
!= 0)
1532 result
= x_text_icon (f
,
1533 SSDATA ((!NILP (f
->icon_name
)
1542 error ("No icon window available");
1545 /* If the window was unmapped (and its icon was mapped),
1546 the new icon is not mapped, so map the window in its stead. */
1547 if (FRAME_VISIBLE_P (f
))
1549 #ifdef USE_X_TOOLKIT
1550 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1552 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1555 XFlush (FRAME_W32_DISPLAY (f
));
1562 x_set_menu_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1566 /* Right now, menu bars don't work properly in minibuf-only frames;
1567 most of the commands try to apply themselves to the minibuffer
1568 frame itself, and get an error because you can't switch buffers
1569 in or split the minibuffer window. */
1570 if (FRAME_MINIBUF_ONLY_P (f
))
1573 if (INTEGERP (value
))
1574 nlines
= XINT (value
);
1578 FRAME_MENU_BAR_LINES (f
) = 0;
1580 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1583 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1584 free_frame_menubar (f
);
1585 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1587 /* Adjust the frame size so that the client (text) dimensions
1588 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1590 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1591 do_pending_window_change (0);
1597 /* Set the number of lines used for the tool bar of frame F to VALUE.
1598 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1599 is the old number of tool bar lines. This function changes the
1600 height of all windows on frame F to match the new tool bar height.
1601 The frame's height doesn't change. */
1604 x_set_tool_bar_lines (struct frame
*f
, Lisp_Object value
, Lisp_Object oldval
)
1606 int delta
, nlines
, root_height
;
1607 Lisp_Object root_window
;
1609 /* Treat tool bars like menu bars. */
1610 if (FRAME_MINIBUF_ONLY_P (f
))
1613 /* Use VALUE only if an integer >= 0. */
1614 if (INTEGERP (value
) && XINT (value
) >= 0)
1615 nlines
= XFASTINT (value
);
1619 /* Make sure we redisplay all windows in this frame. */
1620 ++windows_or_buffers_changed
;
1622 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
1624 /* Don't resize the tool-bar to more than we have room for. */
1625 root_window
= FRAME_ROOT_WINDOW (f
);
1626 root_height
= WINDOW_TOTAL_LINES (XWINDOW (root_window
));
1627 if (root_height
- delta
< 1)
1629 delta
= root_height
- 1;
1630 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
1633 FRAME_TOOL_BAR_LINES (f
) = nlines
;
1634 resize_frame_windows (f
, FRAME_LINES (f
), 0);
1637 /* We also have to make sure that the internal border at the top of
1638 the frame, below the menu bar or tool bar, is redrawn when the
1639 tool bar disappears. This is so because the internal border is
1640 below the tool bar if one is displayed, but is below the menu bar
1641 if there isn't a tool bar. The tool bar draws into the area
1642 below the menu bar. */
1643 if (FRAME_W32_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
1646 clear_current_matrices (f
);
1649 /* If the tool bar gets smaller, the internal border below it
1650 has to be cleared. It was formerly part of the display
1651 of the larger tool bar, and updating windows won't clear it. */
1654 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1655 int width
= FRAME_PIXEL_WIDTH (f
);
1656 int y
= nlines
* FRAME_LINE_HEIGHT (f
);
1660 HDC hdc
= get_frame_dc (f
);
1661 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
1662 release_frame_dc (f
, hdc
);
1666 if (WINDOWP (f
->tool_bar_window
))
1667 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
1670 run_window_configuration_change_hook (f
);
1675 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1678 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1679 name; if NAME is a string, set F's name to NAME and set
1680 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1682 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1683 suggesting a new name, which lisp code should override; if
1684 F->explicit_name is set, ignore the new name; otherwise, set it. */
1687 x_set_name (struct frame
*f
, Lisp_Object name
, int explicit)
1689 /* Make sure that requests from lisp code override requests from
1690 Emacs redisplay code. */
1693 /* If we're switching from explicit to implicit, we had better
1694 update the mode lines and thereby update the title. */
1695 if (f
->explicit_name
&& NILP (name
))
1696 update_mode_lines
= 1;
1698 f
->explicit_name
= ! NILP (name
);
1700 else if (f
->explicit_name
)
1703 /* If NAME is nil, set the name to the w32_id_name. */
1706 /* Check for no change needed in this very common case
1707 before we do any consing. */
1708 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
1711 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
1714 CHECK_STRING (name
);
1716 /* Don't change the name if it's already NAME. */
1717 if (! NILP (Fstring_equal (name
, f
->name
)))
1720 fset_name (f
, name
);
1722 /* For setting the frame title, the title parameter should override
1723 the name parameter. */
1724 if (! NILP (f
->title
))
1727 if (FRAME_W32_WINDOW (f
))
1729 if (STRING_MULTIBYTE (name
))
1730 name
= ENCODE_SYSTEM (name
);
1733 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
1738 /* This function should be called when the user's lisp code has
1739 specified a name for the frame; the name will override any set by the
1742 x_explicitly_set_name (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1744 x_set_name (f
, arg
, 1);
1747 /* This function should be called by Emacs redisplay code to set the
1748 name; names set this way will never override names set by the user's
1751 x_implicitly_set_name (FRAME_PTR f
, Lisp_Object arg
, Lisp_Object oldval
)
1753 x_set_name (f
, arg
, 0);
1756 /* Change the title of frame F to NAME.
1757 If NAME is nil, use the frame name as the title. */
1760 x_set_title (struct frame
*f
, Lisp_Object name
, Lisp_Object old_name
)
1762 /* Don't change the title if it's already NAME. */
1763 if (EQ (name
, f
->title
))
1766 update_mode_lines
= 1;
1768 fset_title (f
, name
);
1773 if (FRAME_W32_WINDOW (f
))
1775 if (STRING_MULTIBYTE (name
))
1776 name
= ENCODE_SYSTEM (name
);
1779 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
1785 x_set_scroll_bar_default_width (struct frame
*f
)
1787 int wid
= FRAME_COLUMN_WIDTH (f
);
1789 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
1790 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) +
1795 /* Subroutines for creating a frame. */
1798 w32_load_cursor (LPCTSTR name
)
1800 /* Try first to load cursor from application resource. */
1801 Cursor cursor
= LoadImage ((HINSTANCE
) GetModuleHandle (NULL
),
1802 name
, IMAGE_CURSOR
, 0, 0,
1803 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1806 /* Then try to load a shared predefined cursor. */
1807 cursor
= LoadImage (NULL
, name
, IMAGE_CURSOR
, 0, 0,
1808 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
1813 static LRESULT CALLBACK
w32_wnd_proc (HWND
, UINT
, WPARAM
, LPARAM
);
1815 #define INIT_WINDOW_CLASS(WC) \
1816 (WC).style = CS_HREDRAW | CS_VREDRAW; \
1817 (WC).lpfnWndProc = (WNDPROC) w32_wnd_proc; \
1818 (WC).cbClsExtra = 0; \
1819 (WC).cbWndExtra = WND_EXTRA_BYTES; \
1820 (WC).hInstance = hinst; \
1821 (WC).hIcon = LoadIcon (hinst, EMACS_CLASS); \
1822 (WC).hCursor = w32_load_cursor (IDC_ARROW); \
1823 (WC).hbrBackground = NULL; \
1824 (WC).lpszMenuName = NULL; \
1827 w32_init_class (HINSTANCE hinst
)
1830 if (w32_unicode_gui
)
1833 INIT_WINDOW_CLASS(uwc
);
1834 uwc
.lpszClassName
= L
"Emacs";
1836 return RegisterClassW (&uwc
);
1841 INIT_WINDOW_CLASS(wc
);
1842 wc
.lpszClassName
= EMACS_CLASS
;
1844 return RegisterClassA (&wc
);
1849 w32_createscrollbar (struct frame
*f
, struct scroll_bar
* bar
)
1851 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
1852 /* Position and size of scroll bar. */
1853 XINT (bar
->left
) + VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
1855 XINT (bar
->width
) - VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
1857 FRAME_W32_WINDOW (f
),
1864 w32_createwindow (struct frame
*f
)
1868 Lisp_Object top
= Qunbound
;
1869 Lisp_Object left
= Qunbound
;
1870 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
1872 rect
.left
= rect
.top
= 0;
1873 rect
.right
= FRAME_PIXEL_WIDTH (f
);
1874 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
1876 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
1877 FRAME_EXTERNAL_MENU_BAR (f
));
1879 /* Do first time app init */
1881 w32_init_class (hinst
);
1883 if (f
->size_hint_flags
& USPosition
|| f
->size_hint_flags
& PPosition
)
1885 XSETINT (left
, f
->left_pos
);
1886 XSETINT (top
, f
->top_pos
);
1888 else if (EQ (left
, Qunbound
) && EQ (top
, Qunbound
))
1890 /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
1891 for anything that is not a number and is not Qunbound. */
1892 left
= x_get_arg (dpyinfo
, Qnil
, Qleft
, "left", "Left", RES_TYPE_NUMBER
);
1893 top
= x_get_arg (dpyinfo
, Qnil
, Qtop
, "top", "Top", RES_TYPE_NUMBER
);
1896 FRAME_W32_WINDOW (f
) = hwnd
1897 = CreateWindow (EMACS_CLASS
,
1899 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
1900 EQ (left
, Qunbound
) ? CW_USEDEFAULT
: XINT (left
),
1901 EQ (top
, Qunbound
) ? CW_USEDEFAULT
: XINT (top
),
1902 rect
.right
- rect
.left
,
1903 rect
.bottom
- rect
.top
,
1911 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
1912 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
1913 SetWindowLong (hwnd
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
1914 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
1915 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
1917 /* Enable drag-n-drop. */
1918 DragAcceptFiles (hwnd
, TRUE
);
1920 /* Do this to discard the default setting specified by our parent. */
1921 ShowWindow (hwnd
, SW_HIDE
);
1923 /* Update frame positions. */
1924 GetWindowRect (hwnd
, &rect
);
1925 f
->left_pos
= rect
.left
;
1926 f
->top_pos
= rect
.top
;
1931 my_post_msg (W32Msg
* wmsg
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1933 wmsg
->msg
.hwnd
= hwnd
;
1934 wmsg
->msg
.message
= msg
;
1935 wmsg
->msg
.wParam
= wParam
;
1936 wmsg
->msg
.lParam
= lParam
;
1937 wmsg
->msg
.time
= GetMessageTime ();
1942 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
1943 between left and right keys as advertised. We test for this
1944 support dynamically, and set a flag when the support is absent. If
1945 absent, we keep track of the left and right control and alt keys
1946 ourselves. This is particularly necessary on keyboards that rely
1947 upon the AltGr key, which is represented as having the left control
1948 and right alt keys pressed. For these keyboards, we need to know
1949 when the left alt key has been pressed in addition to the AltGr key
1950 so that we can properly support M-AltGr-key sequences (such as M-@
1951 on Swedish keyboards). */
1953 #define EMACS_LCONTROL 0
1954 #define EMACS_RCONTROL 1
1955 #define EMACS_LMENU 2
1956 #define EMACS_RMENU 3
1958 static int modifiers
[4];
1959 static int modifiers_recorded
;
1960 static int modifier_key_support_tested
;
1963 test_modifier_support (unsigned int wparam
)
1967 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
1969 if (wparam
== VK_CONTROL
)
1979 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
1980 modifiers_recorded
= 1;
1982 modifiers_recorded
= 0;
1983 modifier_key_support_tested
= 1;
1987 record_keydown (unsigned int wparam
, unsigned int lparam
)
1991 if (!modifier_key_support_tested
)
1992 test_modifier_support (wparam
);
1994 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
1997 if (wparam
== VK_CONTROL
)
1998 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2000 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2006 record_keyup (unsigned int wparam
, unsigned int lparam
)
2010 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2013 if (wparam
== VK_CONTROL
)
2014 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2016 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2021 /* Emacs can lose focus while a modifier key has been pressed. When
2022 it regains focus, be conservative and clear all modifiers since
2023 we cannot reconstruct the left and right modifier state. */
2025 reset_modifiers (void)
2029 if (GetFocus () == NULL
)
2030 /* Emacs doesn't have keyboard focus. Do nothing. */
2033 ctrl
= GetAsyncKeyState (VK_CONTROL
);
2034 alt
= GetAsyncKeyState (VK_MENU
);
2036 if (!(ctrl
& 0x08000))
2037 /* Clear any recorded control modifier state. */
2038 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2040 if (!(alt
& 0x08000))
2041 /* Clear any recorded alt modifier state. */
2042 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2044 /* Update the state of all modifier keys, because modifiers used in
2045 hot-key combinations can get stuck on if Emacs loses focus as a
2046 result of a hot-key being pressed. */
2050 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2052 GetKeyboardState (keystate
);
2053 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
2054 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
2055 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
2056 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
2057 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
2058 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
2059 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
2060 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
2061 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
2062 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
2063 SetKeyboardState (keystate
);
2067 /* Synchronize modifier state with what is reported with the current
2068 keystroke. Even if we cannot distinguish between left and right
2069 modifier keys, we know that, if no modifiers are set, then neither
2070 the left or right modifier should be set. */
2072 sync_modifiers (void)
2074 if (!modifiers_recorded
)
2077 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
2078 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2080 if (!(GetKeyState (VK_MENU
) & 0x8000))
2081 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2085 modifier_set (int vkey
)
2087 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
2088 return (GetKeyState (vkey
) & 0x1);
2089 if (!modifiers_recorded
)
2090 return (GetKeyState (vkey
) & 0x8000);
2095 return modifiers
[EMACS_LCONTROL
];
2097 return modifiers
[EMACS_RCONTROL
];
2099 return modifiers
[EMACS_LMENU
];
2101 return modifiers
[EMACS_RMENU
];
2103 return (GetKeyState (vkey
) & 0x8000);
2106 /* Convert between the modifier bits W32 uses and the modifier bits
2110 w32_key_to_modifier (int key
)
2112 Lisp_Object key_mapping
;
2117 key_mapping
= Vw32_lwindow_modifier
;
2120 key_mapping
= Vw32_rwindow_modifier
;
2123 key_mapping
= Vw32_apps_modifier
;
2126 key_mapping
= Vw32_scroll_lock_modifier
;
2132 /* NB. This code runs in the input thread, asynchronously to the lisp
2133 thread, so we must be careful to ensure access to lisp data is
2134 thread-safe. The following code is safe because the modifier
2135 variable values are updated atomically from lisp and symbols are
2136 not relocated by GC. Also, we don't have to worry about seeing GC
2138 if (EQ (key_mapping
, Qhyper
))
2139 return hyper_modifier
;
2140 if (EQ (key_mapping
, Qsuper
))
2141 return super_modifier
;
2142 if (EQ (key_mapping
, Qmeta
))
2143 return meta_modifier
;
2144 if (EQ (key_mapping
, Qalt
))
2145 return alt_modifier
;
2146 if (EQ (key_mapping
, Qctrl
))
2147 return ctrl_modifier
;
2148 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
2149 return ctrl_modifier
;
2150 if (EQ (key_mapping
, Qshift
))
2151 return shift_modifier
;
2153 /* Don't generate any modifier if not explicitly requested. */
2158 w32_get_modifiers (void)
2160 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
2161 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
2162 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
2163 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
2164 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
2165 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
2166 (modifier_set (VK_MENU
) ?
2167 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2170 /* We map the VK_* modifiers into console modifier constants
2171 so that we can use the same routines to handle both console
2172 and window input. */
2175 construct_console_modifiers (void)
2180 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
2181 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
2182 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
2183 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
2184 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
2185 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
2186 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
2187 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
2188 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
2189 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
2190 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
2196 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
2200 /* Convert to emacs modifiers. */
2201 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
2207 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
2209 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
2212 if (virt_key
== VK_RETURN
)
2213 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
2215 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
2216 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
2218 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
2219 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
2221 if (virt_key
== VK_CLEAR
)
2222 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
2227 /* List of special key combinations which w32 would normally capture,
2228 but Emacs should grab instead. Not directly visible to lisp, to
2229 simplify synchronization. Each item is an integer encoding a virtual
2230 key code and modifier combination to capture. */
2231 static Lisp_Object w32_grabbed_keys
;
2233 #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8))
2234 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2235 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2236 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2238 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2239 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2240 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2242 /* Register hot-keys for reserved key combinations when Emacs has
2243 keyboard focus, since this is the only way Emacs can receive key
2244 combinations like Alt-Tab which are used by the system. */
2247 register_hot_keys (HWND hwnd
)
2249 Lisp_Object keylist
;
2251 /* Use CONSP, since we are called asynchronously. */
2252 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2254 Lisp_Object key
= XCAR (keylist
);
2256 /* Deleted entries get set to nil. */
2257 if (!INTEGERP (key
))
2260 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
2261 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
2266 unregister_hot_keys (HWND hwnd
)
2268 Lisp_Object keylist
;
2270 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2272 Lisp_Object key
= XCAR (keylist
);
2274 if (!INTEGERP (key
))
2277 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
2283 w32_name_of_message (UINT msg
)
2286 static char buf
[64];
2287 static const struct {
2291 #define M(msg) { msg, # msg }
2299 M (WM_EMACS_CREATEWINDOW
),
2301 M (WM_EMACS_CREATESCROLLBAR
),
2302 M (WM_EMACS_SHOWWINDOW
),
2303 M (WM_EMACS_SETWINDOWPOS
),
2304 M (WM_EMACS_DESTROYWINDOW
),
2305 M (WM_EMACS_TRACKPOPUPMENU
),
2306 M (WM_EMACS_SETFOCUS
),
2307 M (WM_EMACS_SETFOREGROUND
),
2308 M (WM_EMACS_SETLOCALE
),
2309 M (WM_EMACS_SETKEYBOARDLAYOUT
),
2310 M (WM_EMACS_REGISTER_HOT_KEY
),
2311 M (WM_EMACS_UNREGISTER_HOT_KEY
),
2312 M (WM_EMACS_TOGGLE_LOCK_KEY
),
2313 M (WM_EMACS_TRACK_CARET
),
2314 M (WM_EMACS_DESTROY_CARET
),
2315 M (WM_EMACS_SHOW_CARET
),
2316 M (WM_EMACS_HIDE_CARET
),
2317 M (WM_EMACS_SETCURSOR
),
2324 for (i
= 0; msgnames
[i
].name
; ++i
)
2325 if (msgnames
[i
].msg
== msg
)
2326 return msgnames
[i
].name
;
2328 sprintf (buf
, "message 0x%04x", (unsigned)msg
);
2331 #endif /* EMACSDEBUG */
2333 /* Here's an overview of how Emacs input works on MS-Windows.
2335 System messages are read and processed by w32_msg_pump below. This
2336 function runs in a separate thread. It handles a small number of
2337 custom WM_EMACS_* messages (posted by the main thread, look for
2338 PostMessage calls), and dispatches the rest to w32_wnd_proc, which
2339 is the main window procedure for the entire Emacs application.
2341 w32_wnd_proc also runs in the same separate input thread. It
2342 handles some messages, mostly those that need GDI calls, by itself.
2343 For the others, it calls my_post_msg, which inserts the messages
2344 into the input queue serviced by w32_read_socket.
2346 w32_read_socket runs in the main (a.k.a. "Lisp") thread, and is
2347 called synchronously from keyboard.c when it is known or suspected
2348 that some input is available. w32_read_socket either handles
2349 messages immediately, or converts them into Emacs input events and
2350 stuffs them into kbd_buffer, where kbd_buffer_get_event can get at
2351 them and process them when read_char and its callers require
2354 Under Cygwin with the W32 toolkit, the use of /dev/windows with
2355 select(2) takes the place of w32_read_socket.
2359 /* Main message dispatch loop. */
2362 w32_msg_pump (deferred_msg
* msg_buf
)
2368 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
2370 while ((w32_unicode_gui
? GetMessageW
: GetMessageA
) (&msg
, NULL
, 0, 0))
2373 /* DebPrint (("w32_msg_pump: %s time:%u\n", */
2374 /* w32_name_of_message (msg.message), msg.time)); */
2376 if (msg
.hwnd
== NULL
)
2378 switch (msg
.message
)
2381 /* Produced by complete_deferred_msg; just ignore. */
2383 case WM_EMACS_CREATEWINDOW
:
2384 /* Initialize COM for this window. Even though we don't use it,
2385 some third party shell extensions can cause it to be used in
2386 system dialogs, which causes a crash if it is not initialized.
2387 This is a known bug in Windows, which was fixed long ago, but
2388 the patch for XP is not publicly available until XP SP3,
2389 and older versions will never be patched. */
2390 CoInitialize (NULL
);
2391 w32_createwindow ((struct frame
*) msg
.wParam
);
2392 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2395 case WM_EMACS_SETLOCALE
:
2396 SetThreadLocale (msg
.wParam
);
2397 /* Reply is not expected. */
2399 case WM_EMACS_SETKEYBOARDLAYOUT
:
2400 result
= (WPARAM
) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
2401 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2405 case WM_EMACS_REGISTER_HOT_KEY
:
2406 focus_window
= GetFocus ();
2407 if (focus_window
!= NULL
)
2408 RegisterHotKey (focus_window
,
2409 RAW_HOTKEY_ID (msg
.wParam
),
2410 RAW_HOTKEY_MODIFIERS (msg
.wParam
),
2411 RAW_HOTKEY_VK_CODE (msg
.wParam
));
2412 /* Reply is not expected. */
2414 case WM_EMACS_UNREGISTER_HOT_KEY
:
2415 focus_window
= GetFocus ();
2416 if (focus_window
!= NULL
)
2417 UnregisterHotKey (focus_window
, RAW_HOTKEY_ID (msg
.wParam
));
2418 /* Mark item as erased. NB: this code must be
2419 thread-safe. The next line is okay because the cons
2420 cell is never made into garbage and is not relocated by
2422 XSETCAR ((Lisp_Object
) ((EMACS_INT
) msg
.lParam
), Qnil
);
2423 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2426 case WM_EMACS_TOGGLE_LOCK_KEY
:
2428 int vk_code
= (int) msg
.wParam
;
2429 int cur_state
= (GetKeyState (vk_code
) & 1);
2430 Lisp_Object new_state
= (Lisp_Object
) ((EMACS_INT
) msg
.lParam
);
2432 /* NB: This code must be thread-safe. It is safe to
2433 call NILP because symbols are not relocated by GC,
2434 and pointer here is not touched by GC (so the markbit
2435 can't be set). Numbers are safe because they are
2436 immediate values. */
2437 if (NILP (new_state
)
2438 || (NUMBERP (new_state
)
2439 && ((XUINT (new_state
)) & 1) != cur_state
))
2441 one_w32_display_info
.faked_key
= vk_code
;
2443 keybd_event ((BYTE
) vk_code
,
2444 (BYTE
) MapVirtualKey (vk_code
, 0),
2445 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2446 keybd_event ((BYTE
) vk_code
,
2447 (BYTE
) MapVirtualKey (vk_code
, 0),
2448 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2449 keybd_event ((BYTE
) vk_code
,
2450 (BYTE
) MapVirtualKey (vk_code
, 0),
2451 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2452 cur_state
= !cur_state
;
2454 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2460 /* Broadcast messages make it here, so you need to be looking
2461 for something in particular for this to be useful. */
2463 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
2469 if (w32_unicode_gui
)
2470 DispatchMessageW (&msg
);
2472 DispatchMessageA (&msg
);
2475 /* Exit nested loop when our deferred message has completed. */
2476 if (msg_buf
->completed
)
2481 deferred_msg
* deferred_msg_head
;
2483 static deferred_msg
*
2484 find_deferred_msg (HWND hwnd
, UINT msg
)
2486 deferred_msg
* item
;
2488 /* Don't actually need synchronization for read access, since
2489 modification of single pointer is always atomic. */
2490 /* enter_crit (); */
2492 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2493 if (item
->w32msg
.msg
.hwnd
== hwnd
2494 && item
->w32msg
.msg
.message
== msg
)
2497 /* leave_crit (); */
2503 send_deferred_msg (deferred_msg
* msg_buf
,
2509 /* Only input thread can send deferred messages. */
2510 if (GetCurrentThreadId () != dwWindowsThreadId
)
2513 /* It is an error to send a message that is already deferred. */
2514 if (find_deferred_msg (hwnd
, msg
) != NULL
)
2517 /* Enforced synchronization is not needed because this is the only
2518 function that alters deferred_msg_head, and the following critical
2519 section is guaranteed to only be serially reentered (since only the
2520 input thread can call us). */
2522 /* enter_crit (); */
2524 msg_buf
->completed
= 0;
2525 msg_buf
->next
= deferred_msg_head
;
2526 deferred_msg_head
= msg_buf
;
2527 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
2529 /* leave_crit (); */
2531 /* Start a new nested message loop to process other messages until
2532 this one is completed. */
2533 w32_msg_pump (msg_buf
);
2535 deferred_msg_head
= msg_buf
->next
;
2537 return msg_buf
->result
;
2541 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
2543 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
2545 if (msg_buf
== NULL
)
2546 /* Message may have been canceled, so don't abort. */
2549 msg_buf
->result
= result
;
2550 msg_buf
->completed
= 1;
2552 /* Ensure input thread is woken so it notices the completion. */
2553 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2557 cancel_all_deferred_msgs (void)
2559 deferred_msg
* item
;
2561 /* Don't actually need synchronization for read access, since
2562 modification of single pointer is always atomic. */
2563 /* enter_crit (); */
2565 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2568 item
->completed
= 1;
2571 /* leave_crit (); */
2573 /* Ensure input thread is woken so it notices the completion. */
2574 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2578 w32_msg_worker (void *arg
)
2581 deferred_msg dummy_buf
;
2583 /* Ensure our message queue is created */
2585 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2587 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2590 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
2591 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
2592 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
2594 /* This is the initial message loop which should only exit when the
2595 application quits. */
2596 w32_msg_pump (&dummy_buf
);
2602 signal_user_input (void)
2604 /* Interrupt any lisp that wants to be interrupted by input. */
2605 if (!NILP (Vthrow_on_input
))
2607 Vquit_flag
= Vthrow_on_input
;
2608 /* Doing a QUIT from this thread is a bad idea, since this
2609 unwinds the stack of the Lisp thread, and the Windows runtime
2610 rightfully barfs. Disabled. */
2612 /* If we're inside a function that wants immediate quits,
2614 if (immediate_quit
&& NILP (Vinhibit_quit
))
2625 post_character_message (HWND hwnd
, UINT msg
,
2626 WPARAM wParam
, LPARAM lParam
,
2631 wmsg
.dwModifiers
= modifiers
;
2633 /* Detect quit_char and set quit-flag directly. Note that we
2634 still need to post a message to ensure the main thread will be
2635 woken up if blocked in sys_select, but we do NOT want to post
2636 the quit_char message itself (because it will usually be as if
2637 the user had typed quit_char twice). Instead, we post a dummy
2638 message that has no particular effect. */
2641 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
2642 c
= make_ctrl_char (c
) & 0377;
2644 || (wmsg
.dwModifiers
== 0
2645 && w32_quit_key
&& wParam
== w32_quit_key
))
2649 /* The choice of message is somewhat arbitrary, as long as
2650 the main thread handler just ignores it. */
2653 /* Interrupt any blocking system calls. */
2656 /* As a safety precaution, forcibly complete any deferred
2657 messages. This is a kludge, but I don't see any particularly
2658 clean way to handle the situation where a deferred message is
2659 "dropped" in the lisp thread, and will thus never be
2660 completed, eg. by the user trying to activate the menubar
2661 when the lisp thread is busy, and then typing C-g when the
2662 menubar doesn't open promptly (with the result that the
2663 menubar never responds at all because the deferred
2664 WM_INITMENU message is never completed). Another problem
2665 situation is when the lisp thread calls SendMessage (to send
2666 a window manager command) when a message has been deferred;
2667 the lisp thread gets blocked indefinitely waiting for the
2668 deferred message to be completed, which itself is waiting for
2669 the lisp thread to respond.
2671 Note that we don't want to block the input thread waiting for
2672 a response from the lisp thread (although that would at least
2673 solve the deadlock problem above), because we want to be able
2674 to receive C-g to interrupt the lisp thread. */
2675 cancel_all_deferred_msgs ();
2678 signal_user_input ();
2681 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2684 /* Main window procedure */
2686 static LRESULT CALLBACK
2687 w32_wnd_proc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2690 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2692 int windows_translate
;
2695 /* Note that it is okay to call x_window_to_frame, even though we are
2696 not running in the main lisp thread, because frame deletion
2697 requires the lisp thread to synchronize with this thread. Thus, if
2698 a frame struct is returned, it can be used without concern that the
2699 lisp thread might make it disappear while we are using it.
2701 NB. Walking the frame list in this thread is safe (as long as
2702 writes of Lisp_Object slots are atomic, which they are on Windows).
2703 Although delete-frame can destructively modify the frame list while
2704 we are walking it, a garbage collection cannot occur until after
2705 delete-frame has synchronized with this thread.
2707 It is also safe to use functions that make GDI calls, such as
2708 w32_clear_rect, because these functions must obtain a DC handle
2709 from the frame struct using get_frame_dc which is thread-aware. */
2714 f
= x_window_to_frame (dpyinfo
, hwnd
);
2717 HDC hdc
= get_frame_dc (f
);
2718 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
2719 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
2720 release_frame_dc (f
, hdc
);
2722 #if defined (W32_DEBUG_DISPLAY)
2723 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2725 wmsg
.rect
.left
, wmsg
.rect
.top
,
2726 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2727 #endif /* W32_DEBUG_DISPLAY */
2730 case WM_PALETTECHANGED
:
2731 /* ignore our own changes */
2732 if ((HWND
)wParam
!= hwnd
)
2734 f
= x_window_to_frame (dpyinfo
, hwnd
);
2736 /* get_frame_dc will realize our palette and force all
2737 frames to be redrawn if needed. */
2738 release_frame_dc (f
, get_frame_dc (f
));
2743 PAINTSTRUCT paintStruct
;
2745 memset (&update_rect
, 0, sizeof (update_rect
));
2747 f
= x_window_to_frame (dpyinfo
, hwnd
);
2750 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd
));
2754 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2755 fails. Apparently this can happen under some
2757 if (GetUpdateRect (hwnd
, &update_rect
, FALSE
) || !w32_strict_painting
)
2760 BeginPaint (hwnd
, &paintStruct
);
2762 /* The rectangles returned by GetUpdateRect and BeginPaint
2763 do not always match. Play it safe by assuming both areas
2765 UnionRect (&(wmsg
.rect
), &update_rect
, &(paintStruct
.rcPaint
));
2767 #if defined (W32_DEBUG_DISPLAY)
2768 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2770 wmsg
.rect
.left
, wmsg
.rect
.top
,
2771 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2772 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2773 update_rect
.left
, update_rect
.top
,
2774 update_rect
.right
, update_rect
.bottom
));
2776 EndPaint (hwnd
, &paintStruct
);
2779 /* Change the message type to prevent Windows from
2780 combining WM_PAINT messages in the Lisp thread's queue,
2781 since Windows assumes that each message queue is
2782 dedicated to one frame and does not bother checking
2783 that hwnd matches before combining them. */
2784 my_post_msg (&wmsg
, hwnd
, WM_EMACS_PAINT
, wParam
, lParam
);
2789 /* If GetUpdateRect returns 0 (meaning there is no update
2790 region), assume the whole window needs to be repainted. */
2791 GetClientRect (hwnd
, &wmsg
.rect
);
2792 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2796 case WM_INPUTLANGCHANGE
:
2797 /* Inform lisp thread of keyboard layout changes. */
2798 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2800 /* Clear dead keys in the keyboard state; for simplicity only
2801 preserve modifier key states. */
2806 GetKeyboardState (keystate
);
2807 for (i
= 0; i
< 256; i
++)
2824 SetKeyboardState (keystate
);
2829 /* Synchronize hot keys with normal input. */
2830 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
2835 record_keyup (wParam
, lParam
);
2840 /* Ignore keystrokes we fake ourself; see below. */
2841 if (dpyinfo
->faked_key
== wParam
)
2843 dpyinfo
->faked_key
= 0;
2844 /* Make sure TranslateMessage sees them though (as long as
2845 they don't produce WM_CHAR messages). This ensures that
2846 indicator lights are toggled promptly on Windows 9x, for
2848 if (wParam
< 256 && lispy_function_keys
[wParam
])
2850 windows_translate
= 1;
2856 /* Synchronize modifiers with current keystroke. */
2858 record_keydown (wParam
, lParam
);
2859 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
2861 windows_translate
= 0;
2866 if (NILP (Vw32_pass_lwindow_to_system
))
2868 /* Prevent system from acting on keyup (which opens the
2869 Start menu if no other key was pressed) by simulating a
2870 press of Space which we will ignore. */
2871 if (GetAsyncKeyState (wParam
) & 1)
2873 if (NUMBERP (Vw32_phantom_key_code
))
2874 key
= XUINT (Vw32_phantom_key_code
) & 255;
2877 dpyinfo
->faked_key
= key
;
2878 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
2881 if (!NILP (Vw32_lwindow_modifier
))
2885 if (NILP (Vw32_pass_rwindow_to_system
))
2887 if (GetAsyncKeyState (wParam
) & 1)
2889 if (NUMBERP (Vw32_phantom_key_code
))
2890 key
= XUINT (Vw32_phantom_key_code
) & 255;
2893 dpyinfo
->faked_key
= key
;
2894 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
2897 if (!NILP (Vw32_rwindow_modifier
))
2901 if (!NILP (Vw32_apps_modifier
))
2905 if (NILP (Vw32_pass_alt_to_system
))
2906 /* Prevent DefWindowProc from activating the menu bar if an
2907 Alt key is pressed and released by itself. */
2909 windows_translate
= 1;
2912 /* Decide whether to treat as modifier or function key. */
2913 if (NILP (Vw32_enable_caps_lock
))
2914 goto disable_lock_key
;
2915 windows_translate
= 1;
2918 /* Decide whether to treat as modifier or function key. */
2919 if (NILP (Vw32_enable_num_lock
))
2920 goto disable_lock_key
;
2921 windows_translate
= 1;
2924 /* Decide whether to treat as modifier or function key. */
2925 if (NILP (Vw32_scroll_lock_modifier
))
2926 goto disable_lock_key
;
2927 windows_translate
= 1;
2930 /* Ensure the appropriate lock key state (and indicator light)
2931 remains in the same state. We do this by faking another
2932 press of the relevant key. Apparently, this really is the
2933 only way to toggle the state of the indicator lights. */
2934 dpyinfo
->faked_key
= wParam
;
2935 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2936 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2937 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2938 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2939 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
2940 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2941 /* Ensure indicator lights are updated promptly on Windows 9x
2942 (TranslateMessage apparently does this), after forwarding
2944 post_character_message (hwnd
, msg
, wParam
, lParam
,
2945 w32_get_key_modifiers (wParam
, lParam
));
2946 windows_translate
= 1;
2950 case VK_PROCESSKEY
: /* Generated by IME. */
2951 windows_translate
= 1;
2954 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
2955 which is confusing for purposes of key binding; convert
2956 VK_CANCEL events into VK_PAUSE events. */
2960 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
2961 for purposes of key binding; convert these back into
2962 VK_NUMLOCK events, at least when we want to see NumLock key
2963 presses. (Note that there is never any possibility that
2964 VK_PAUSE with Ctrl really is C-Pause as per above.) */
2965 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
2966 wParam
= VK_NUMLOCK
;
2969 /* If not defined as a function key, change it to a WM_CHAR message. */
2970 if (wParam
> 255 || !lispy_function_keys
[wParam
])
2972 DWORD modifiers
= construct_console_modifiers ();
2974 if (!NILP (Vw32_recognize_altgr
)
2975 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
2977 /* Always let TranslateMessage handle AltGr key chords;
2978 for some reason, ToAscii doesn't always process AltGr
2979 chords correctly. */
2980 windows_translate
= 1;
2982 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
2984 /* Handle key chords including any modifiers other
2985 than shift directly, in order to preserve as much
2986 modifier information as possible. */
2987 if ('A' <= wParam
&& wParam
<= 'Z')
2989 /* Don't translate modified alphabetic keystrokes,
2990 so the user doesn't need to constantly switch
2991 layout to type control or meta keystrokes when
2992 the normal layout translates alphabetic
2993 characters to non-ascii characters. */
2994 if (!modifier_set (VK_SHIFT
))
2995 wParam
+= ('a' - 'A');
3000 /* Try to handle other keystrokes by determining the
3001 base character (ie. translating the base key plus
3004 KEY_EVENT_RECORD key
;
3006 key
.bKeyDown
= TRUE
;
3007 key
.wRepeatCount
= 1;
3008 key
.wVirtualKeyCode
= wParam
;
3009 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3010 key
.uChar
.AsciiChar
= 0;
3011 key
.dwControlKeyState
= modifiers
;
3013 add
= w32_kbd_patch_key (&key
, w32_keyboard_codepage
);
3014 /* 0 means an unrecognized keycode, negative means
3015 dead key. Ignore both. */
3018 /* Forward asciified character sequence. */
3019 post_character_message
3021 (unsigned char) key
.uChar
.AsciiChar
, lParam
,
3022 w32_get_key_modifiers (wParam
, lParam
));
3023 w32_kbd_patch_key (&key
, w32_keyboard_codepage
);
3030 /* Let TranslateMessage handle everything else. */
3031 windows_translate
= 1;
3037 if (windows_translate
)
3039 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3040 windows_msg
.time
= GetMessageTime ();
3041 TranslateMessage (&windows_msg
);
3053 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3054 signal_user_input ();
3055 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, wParam
, lParam
);
3059 post_character_message (hwnd
, msg
, wParam
, lParam
,
3060 w32_get_key_modifiers (wParam
, lParam
));
3064 /* WM_UNICHAR looks promising from the docs, but the exact
3065 circumstances in which TranslateMessage sends it is one of those
3066 Microsoft secret API things that EU and US courts are supposed
3067 to have put a stop to already. Spy++ shows it being sent to Notepad
3068 and other MS apps, but never to Emacs.
3070 Some third party IMEs send it in accordance with the official
3071 documentation though, so handle it here.
3073 UNICODE_NOCHAR is used to test for support for this message.
3074 TRUE indicates that the message is supported. */
3075 if (wParam
== UNICODE_NOCHAR
)
3080 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3081 signal_user_input ();
3082 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3087 /* If we can't get the IME result as Unicode, use default processing,
3088 which will at least allow characters decodable in the system locale
3090 if (!get_composition_string_fn
)
3093 else if (!ignore_ime_char
)
3098 HIMC context
= get_ime_context_fn (hwnd
);
3099 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3100 /* Get buffer size. */
3101 size
= get_composition_string_fn (context
, GCS_RESULTSTR
, NULL
, 0);
3102 buffer
= alloca (size
);
3103 size
= get_composition_string_fn (context
, GCS_RESULTSTR
,
3105 release_ime_context_fn (hwnd
, context
);
3107 signal_user_input ();
3108 for (i
= 0; i
< size
/ sizeof (wchar_t); i
++)
3110 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, (WPARAM
) buffer
[i
],
3113 /* Ignore the messages for the rest of the
3114 characters in the string that was output above. */
3115 ignore_ime_char
= (size
/ sizeof (wchar_t)) - 1;
3122 case WM_IME_STARTCOMPOSITION
:
3123 if (!set_ime_composition_window_fn
)
3127 COMPOSITIONFORM form
;
3131 f
= x_window_to_frame (dpyinfo
, hwnd
);
3132 w
= XWINDOW (FRAME_SELECTED_WINDOW (f
));
3134 form
.dwStyle
= CFS_RECT
;
3135 form
.ptCurrentPos
.x
= w32_system_caret_x
;
3136 form
.ptCurrentPos
.y
= w32_system_caret_y
;
3138 form
.rcArea
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, 0);
3139 form
.rcArea
.top
= (WINDOW_TOP_EDGE_Y (w
)
3140 + WINDOW_HEADER_LINE_HEIGHT (w
));
3141 form
.rcArea
.right
= (WINDOW_BOX_RIGHT_EDGE_X (w
)
3142 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
3143 - WINDOW_RIGHT_FRINGE_WIDTH (w
));
3144 form
.rcArea
.bottom
= (WINDOW_BOTTOM_EDGE_Y (w
)
3145 - WINDOW_MODE_LINE_HEIGHT (w
));
3147 context
= get_ime_context_fn (hwnd
);
3152 set_ime_composition_window_fn (context
, &form
);
3153 release_ime_context_fn (hwnd
, context
);
3157 case WM_IME_ENDCOMPOSITION
:
3158 ignore_ime_char
= 0;
3161 /* Simulate middle mouse button events when left and right buttons
3162 are used together, but only if user has two button mouse. */
3163 case WM_LBUTTONDOWN
:
3164 case WM_RBUTTONDOWN
:
3165 if (w32_num_mouse_buttons
> 2)
3166 goto handle_plain_button
;
3169 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3170 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3172 if (button_state
& this)
3175 if (button_state
== 0)
3178 button_state
|= this;
3180 if (button_state
& other
)
3182 if (mouse_button_timer
)
3184 KillTimer (hwnd
, mouse_button_timer
);
3185 mouse_button_timer
= 0;
3187 /* Generate middle mouse event instead. */
3188 msg
= WM_MBUTTONDOWN
;
3189 button_state
|= MMOUSE
;
3191 else if (button_state
& MMOUSE
)
3193 /* Ignore button event if we've already generated a
3194 middle mouse down event. This happens if the
3195 user releases and press one of the two buttons
3196 after we've faked a middle mouse event. */
3201 /* Flush out saved message. */
3202 post_msg (&saved_mouse_button_msg
);
3204 wmsg
.dwModifiers
= w32_get_modifiers ();
3205 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3206 signal_user_input ();
3208 /* Clear message buffer. */
3209 saved_mouse_button_msg
.msg
.hwnd
= 0;
3213 /* Hold onto message for now. */
3214 mouse_button_timer
=
3215 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
3216 w32_mouse_button_tolerance
, NULL
);
3217 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3218 saved_mouse_button_msg
.msg
.message
= msg
;
3219 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3220 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3221 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3222 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3229 if (w32_num_mouse_buttons
> 2)
3230 goto handle_plain_button
;
3233 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3234 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3236 if ((button_state
& this) == 0)
3239 button_state
&= ~this;
3241 if (button_state
& MMOUSE
)
3243 /* Only generate event when second button is released. */
3244 if ((button_state
& other
) == 0)
3247 button_state
&= ~MMOUSE
;
3249 if (button_state
) emacs_abort ();
3256 /* Flush out saved message if necessary. */
3257 if (saved_mouse_button_msg
.msg
.hwnd
)
3259 post_msg (&saved_mouse_button_msg
);
3262 wmsg
.dwModifiers
= w32_get_modifiers ();
3263 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3264 signal_user_input ();
3266 /* Always clear message buffer and cancel timer. */
3267 saved_mouse_button_msg
.msg
.hwnd
= 0;
3268 KillTimer (hwnd
, mouse_button_timer
);
3269 mouse_button_timer
= 0;
3271 if (button_state
== 0)
3276 case WM_XBUTTONDOWN
:
3278 if (w32_pass_extra_mouse_buttons_to_system
)
3280 /* else fall through and process them. */
3281 case WM_MBUTTONDOWN
:
3283 handle_plain_button
:
3288 /* Ignore middle and extra buttons as long as the menu is active. */
3289 f
= x_window_to_frame (dpyinfo
, hwnd
);
3290 if (f
&& f
->output_data
.w32
->menubar_active
)
3293 if (parse_button (msg
, HIWORD (wParam
), &button
, &up
))
3295 if (up
) ReleaseCapture ();
3296 else SetCapture (hwnd
);
3297 button
= (button
== 0) ? LMOUSE
:
3298 ((button
== 1) ? MMOUSE
: RMOUSE
);
3300 button_state
&= ~button
;
3302 button_state
|= button
;
3306 wmsg
.dwModifiers
= w32_get_modifiers ();
3307 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3308 signal_user_input ();
3310 /* Need to return true for XBUTTON messages, false for others,
3311 to indicate that we processed the message. */
3312 return (msg
== WM_XBUTTONDOWN
|| msg
== WM_XBUTTONUP
);
3315 /* Ignore mouse movements as long as the menu is active. These
3316 movements are processed by the window manager anyway, and
3317 it's wrong to handle them as if they happened on the
3318 underlying frame. */
3319 f
= x_window_to_frame (dpyinfo
, hwnd
);
3320 if (f
&& f
->output_data
.w32
->menubar_active
)
3323 /* If the mouse has just moved into the frame, start tracking
3324 it, so we will be notified when it leaves the frame. Mouse
3325 tracking only works under W98 and NT4 and later. On earlier
3326 versions, there is no way of telling when the mouse leaves the
3327 frame, so we just have to put up with help-echo and mouse
3328 highlighting remaining while the frame is not active. */
3329 if (track_mouse_event_fn
&& !track_mouse_window
)
3331 TRACKMOUSEEVENT tme
;
3332 tme
.cbSize
= sizeof (tme
);
3333 tme
.dwFlags
= TME_LEAVE
;
3334 tme
.hwndTrack
= hwnd
;
3336 track_mouse_event_fn (&tme
);
3337 track_mouse_window
= hwnd
;
3340 if (w32_mouse_move_interval
<= 0
3341 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3343 wmsg
.dwModifiers
= w32_get_modifiers ();
3344 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3348 /* Hang onto mouse move and scroll messages for a bit, to avoid
3349 sending such events to Emacs faster than it can process them.
3350 If we get more events before the timer from the first message
3351 expires, we just replace the first message. */
3353 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3355 SetTimer (hwnd
, MOUSE_MOVE_ID
,
3356 w32_mouse_move_interval
, NULL
);
3358 /* Hold onto message for now. */
3359 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3360 saved_mouse_move_msg
.msg
.message
= msg
;
3361 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3362 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3363 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3364 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3370 wmsg
.dwModifiers
= w32_get_modifiers ();
3371 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3372 signal_user_input ();
3376 if (w32_pass_multimedia_buttons_to_system
)
3378 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
3379 case WM_MOUSEHWHEEL
:
3380 wmsg
.dwModifiers
= w32_get_modifiers ();
3381 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3382 signal_user_input ();
3383 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3384 handled, to prevent the system trying to handle it by faking
3385 scroll bar events. */
3389 /* Flush out saved messages if necessary. */
3390 if (wParam
== mouse_button_timer
)
3392 if (saved_mouse_button_msg
.msg
.hwnd
)
3394 post_msg (&saved_mouse_button_msg
);
3395 signal_user_input ();
3396 saved_mouse_button_msg
.msg
.hwnd
= 0;
3398 KillTimer (hwnd
, mouse_button_timer
);
3399 mouse_button_timer
= 0;
3401 else if (wParam
== mouse_move_timer
)
3403 if (saved_mouse_move_msg
.msg
.hwnd
)
3405 post_msg (&saved_mouse_move_msg
);
3406 saved_mouse_move_msg
.msg
.hwnd
= 0;
3408 KillTimer (hwnd
, mouse_move_timer
);
3409 mouse_move_timer
= 0;
3411 else if (wParam
== menu_free_timer
)
3413 KillTimer (hwnd
, menu_free_timer
);
3414 menu_free_timer
= 0;
3415 f
= x_window_to_frame (dpyinfo
, hwnd
);
3416 /* If a popup menu is active, don't wipe its strings. */
3418 && current_popup_menu
== NULL
)
3420 /* Free memory used by owner-drawn and help-echo strings. */
3421 w32_free_menu_strings (hwnd
);
3423 f
->output_data
.w32
->menubar_active
= 0;
3430 /* Windows doesn't send us focus messages when putting up and
3431 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3432 The only indication we get that something happened is receiving
3433 this message afterwards. So this is a good time to reset our
3434 keyboard modifiers' state. */
3441 /* We must ensure menu bar is fully constructed and up to date
3442 before allowing user interaction with it. To achieve this
3443 we send this message to the lisp thread and wait for a
3444 reply (whose value is not actually needed) to indicate that
3445 the menu bar is now ready for use, so we can now return.
3447 To remain responsive in the meantime, we enter a nested message
3448 loop that can process all other messages.
3450 However, we skip all this if the message results from calling
3451 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3452 thread a message because it is blocked on us at this point. We
3453 set menubar_active before calling TrackPopupMenu to indicate
3454 this (there is no possibility of confusion with real menubar
3457 f
= x_window_to_frame (dpyinfo
, hwnd
);
3459 && (f
->output_data
.w32
->menubar_active
3460 /* We can receive this message even in the absence of a
3461 menubar (ie. when the system menu is activated) - in this
3462 case we do NOT want to forward the message, otherwise it
3463 will cause the menubar to suddenly appear when the user
3464 had requested it to be turned off! */
3465 || f
->output_data
.w32
->menubar_widget
== NULL
))
3469 deferred_msg msg_buf
;
3471 /* Detect if message has already been deferred; in this case
3472 we cannot return any sensible value to ignore this. */
3473 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3478 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3481 case WM_EXITMENULOOP
:
3482 f
= x_window_to_frame (dpyinfo
, hwnd
);
3484 /* If a menu is still active, check again after a short delay,
3485 since Windows often (always?) sends the WM_EXITMENULOOP
3486 before the corresponding WM_COMMAND message.
3487 Don't do this if a popup menu is active, since it is only
3488 menubar menus that require cleaning up in this way.
3490 if (f
&& menubar_in_use
&& current_popup_menu
== NULL
)
3491 menu_free_timer
= SetTimer (hwnd
, MENU_FREE_ID
, MENU_FREE_DELAY
, NULL
);
3493 /* If hourglass cursor should be displayed, display it now. */
3494 if (f
&& f
->output_data
.w32
->hourglass_p
)
3495 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3500 /* Direct handling of help_echo in menus. Should be safe now
3501 that we generate the help_echo by placing a help event in the
3504 HMENU menu
= (HMENU
) lParam
;
3505 UINT menu_item
= (UINT
) LOWORD (wParam
);
3506 UINT flags
= (UINT
) HIWORD (wParam
);
3508 w32_menu_display_help (hwnd
, menu
, menu_item
, flags
);
3512 case WM_MEASUREITEM
:
3513 f
= x_window_to_frame (dpyinfo
, hwnd
);
3516 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3518 if (pMis
->CtlType
== ODT_MENU
)
3520 /* Work out dimensions for popup menu titles. */
3521 char * title
= (char *) pMis
->itemData
;
3522 HDC hdc
= GetDC (hwnd
);
3523 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3524 LOGFONT menu_logfont
;
3528 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3529 menu_logfont
.lfWeight
= FW_BOLD
;
3530 menu_font
= CreateFontIndirect (&menu_logfont
);
3531 old_font
= SelectObject (hdc
, menu_font
);
3533 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3536 if (unicode_append_menu
)
3537 GetTextExtentPoint32W (hdc
, (WCHAR
*) title
,
3538 wcslen ((WCHAR
*) title
),
3541 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3543 pMis
->itemWidth
= size
.cx
;
3544 if (pMis
->itemHeight
< size
.cy
)
3545 pMis
->itemHeight
= size
.cy
;
3548 pMis
->itemWidth
= 0;
3550 SelectObject (hdc
, old_font
);
3551 DeleteObject (menu_font
);
3552 ReleaseDC (hwnd
, hdc
);
3559 f
= x_window_to_frame (dpyinfo
, hwnd
);
3562 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3564 if (pDis
->CtlType
== ODT_MENU
)
3566 /* Draw popup menu title. */
3567 char * title
= (char *) pDis
->itemData
;
3570 HDC hdc
= pDis
->hDC
;
3571 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3572 LOGFONT menu_logfont
;
3575 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3576 menu_logfont
.lfWeight
= FW_BOLD
;
3577 menu_font
= CreateFontIndirect (&menu_logfont
);
3578 old_font
= SelectObject (hdc
, menu_font
);
3580 /* Always draw title as if not selected. */
3581 if (unicode_append_menu
)
3584 + GetSystemMetrics (SM_CXMENUCHECK
),
3586 ETO_OPAQUE
, &pDis
->rcItem
,
3588 wcslen ((WCHAR
*) title
), NULL
);
3592 + GetSystemMetrics (SM_CXMENUCHECK
),
3594 ETO_OPAQUE
, &pDis
->rcItem
,
3595 title
, strlen (title
), NULL
);
3597 SelectObject (hdc
, old_font
);
3598 DeleteObject (menu_font
);
3606 /* Still not right - can't distinguish between clicks in the
3607 client area of the frame from clicks forwarded from the scroll
3608 bars - may have to hook WM_NCHITTEST to remember the mouse
3609 position and then check if it is in the client area ourselves. */
3610 case WM_MOUSEACTIVATE
:
3611 /* Discard the mouse click that activates a frame, allowing the
3612 user to click anywhere without changing point (or worse!).
3613 Don't eat mouse clicks on scrollbars though!! */
3614 if (LOWORD (lParam
) == HTCLIENT
)
3615 return MA_ACTIVATEANDEAT
;
3620 /* No longer tracking mouse. */
3621 track_mouse_window
= NULL
;
3623 case WM_ACTIVATEAPP
:
3625 case WM_WINDOWPOSCHANGED
:
3627 /* Inform lisp thread that a frame might have just been obscured
3628 or exposed, so should recheck visibility of all frames. */
3629 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3633 dpyinfo
->faked_key
= 0;
3635 register_hot_keys (hwnd
);
3638 unregister_hot_keys (hwnd
);
3641 /* Relinquish the system caret. */
3642 if (w32_system_caret_hwnd
)
3644 w32_visible_system_caret_hwnd
= NULL
;
3645 w32_system_caret_hwnd
= NULL
;
3651 f
= x_window_to_frame (dpyinfo
, hwnd
);
3652 if (f
&& HIWORD (wParam
) == 0)
3654 if (menu_free_timer
)
3656 KillTimer (hwnd
, menu_free_timer
);
3657 menu_free_timer
= 0;
3663 wmsg
.dwModifiers
= w32_get_modifiers ();
3664 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3672 wmsg
.dwModifiers
= w32_get_modifiers ();
3673 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3676 case WM_WINDOWPOSCHANGING
:
3677 /* Don't restrict the sizing of tip frames. */
3678 if (hwnd
== tip_window
)
3682 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3684 wp
.length
= sizeof (WINDOWPLACEMENT
);
3685 GetWindowPlacement (hwnd
, &wp
);
3687 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
3694 DWORD internal_border
;
3695 DWORD scrollbar_extra
;
3698 wp
.length
= sizeof (wp
);
3699 GetWindowRect (hwnd
, &wr
);
3703 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3704 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3705 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3706 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
3710 memset (&rect
, 0, sizeof (rect
));
3711 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3712 GetMenu (hwnd
) != NULL
);
3714 /* Force width and height of client area to be exact
3715 multiples of the character cell dimensions. */
3716 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3717 - 2 * internal_border
- scrollbar_extra
)
3719 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3720 - 2 * internal_border
)
3725 /* For right/bottom sizing we can just fix the sizes.
3726 However for top/left sizing we will need to fix the X
3727 and Y positions as well. */
3729 int cx_mintrack
= GetSystemMetrics (SM_CXMINTRACK
);
3730 int cy_mintrack
= GetSystemMetrics (SM_CYMINTRACK
);
3732 lppos
->cx
= max (lppos
->cx
- wdiff
, cx_mintrack
);
3733 lppos
->cy
= max (lppos
->cy
- hdiff
, cy_mintrack
);
3735 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3736 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3738 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3745 lppos
->flags
|= SWP_NOMOVE
;
3756 case WM_GETMINMAXINFO
:
3757 /* Hack to allow resizing the Emacs frame above the screen size.
3758 Note that Windows 9x limits coordinates to 16-bits. */
3759 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.x
= 32767;
3760 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.y
= 32767;
3764 if (LOWORD (lParam
) == HTCLIENT
)
3766 f
= x_window_to_frame (dpyinfo
, hwnd
);
3767 if (f
&& f
->output_data
.w32
->hourglass_p
3768 && !menubar_in_use
&& !current_popup_menu
)
3769 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3771 SetCursor (f
->output_data
.w32
->current_cursor
);
3776 case WM_EMACS_SETCURSOR
:
3778 Cursor cursor
= (Cursor
) wParam
;
3779 f
= x_window_to_frame (dpyinfo
, hwnd
);
3782 f
->output_data
.w32
->current_cursor
= cursor
;
3783 if (!f
->output_data
.w32
->hourglass_p
)
3789 case WM_EMACS_CREATESCROLLBAR
:
3790 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
3791 (struct scroll_bar
*) lParam
);
3793 case WM_EMACS_SHOWWINDOW
:
3794 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
3796 case WM_EMACS_BRINGTOTOP
:
3797 case WM_EMACS_SETFOREGROUND
:
3799 HWND foreground_window
;
3800 DWORD foreground_thread
, retval
;
3802 /* On NT 5.0, and apparently Windows 98, it is necessary to
3803 attach to the thread that currently has focus in order to
3804 pull the focus away from it. */
3805 foreground_window
= GetForegroundWindow ();
3806 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
3807 if (!foreground_window
3808 || foreground_thread
== GetCurrentThreadId ()
3809 || !AttachThreadInput (GetCurrentThreadId (),
3810 foreground_thread
, TRUE
))
3811 foreground_thread
= 0;
3813 retval
= SetForegroundWindow ((HWND
) wParam
);
3814 if (msg
== WM_EMACS_BRINGTOTOP
)
3815 retval
= BringWindowToTop ((HWND
) wParam
);
3817 /* Detach from the previous foreground thread. */
3818 if (foreground_thread
)
3819 AttachThreadInput (GetCurrentThreadId (),
3820 foreground_thread
, FALSE
);
3825 case WM_EMACS_SETWINDOWPOS
:
3827 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
3828 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
3829 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
3832 case WM_EMACS_DESTROYWINDOW
:
3833 DragAcceptFiles ((HWND
) wParam
, FALSE
);
3834 return DestroyWindow ((HWND
) wParam
);
3836 case WM_EMACS_HIDE_CARET
:
3837 return HideCaret (hwnd
);
3839 case WM_EMACS_SHOW_CARET
:
3840 return ShowCaret (hwnd
);
3842 case WM_EMACS_DESTROY_CARET
:
3843 w32_system_caret_hwnd
= NULL
;
3844 w32_visible_system_caret_hwnd
= NULL
;
3845 return DestroyCaret ();
3847 case WM_EMACS_TRACK_CARET
:
3848 /* If there is currently no system caret, create one. */
3849 if (w32_system_caret_hwnd
== NULL
)
3851 /* Use the default caret width, and avoid changing it
3852 unnecessarily, as it confuses screen reader software. */
3853 w32_system_caret_hwnd
= hwnd
;
3854 CreateCaret (hwnd
, NULL
, 0,
3855 w32_system_caret_height
);
3858 if (!SetCaretPos (w32_system_caret_x
, w32_system_caret_y
))
3860 /* Ensure visible caret gets turned on when requested. */
3861 else if (w32_use_visible_system_caret
3862 && w32_visible_system_caret_hwnd
!= hwnd
)
3864 w32_visible_system_caret_hwnd
= hwnd
;
3865 return ShowCaret (hwnd
);
3867 /* Ensure visible caret gets turned off when requested. */
3868 else if (!w32_use_visible_system_caret
3869 && w32_visible_system_caret_hwnd
)
3871 w32_visible_system_caret_hwnd
= NULL
;
3872 return HideCaret (hwnd
);
3877 case WM_EMACS_TRACKPOPUPMENU
:
3882 pos
= (POINT
*)lParam
;
3883 flags
= TPM_CENTERALIGN
;
3884 if (button_state
& LMOUSE
)
3885 flags
|= TPM_LEFTBUTTON
;
3886 else if (button_state
& RMOUSE
)
3887 flags
|= TPM_RIGHTBUTTON
;
3889 /* Remember we did a SetCapture on the initial mouse down event,
3890 so for safety, we make sure the capture is canceled now. */
3894 /* Use menubar_active to indicate that WM_INITMENU is from
3895 TrackPopupMenu below, and should be ignored. */
3896 f
= x_window_to_frame (dpyinfo
, hwnd
);
3898 f
->output_data
.w32
->menubar_active
= 1;
3900 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
3904 /* Eat any mouse messages during popupmenu */
3905 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
3907 /* Get the menu selection, if any */
3908 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
3910 retval
= LOWORD (amsg
.wParam
);
3926 /* Check for messages registered at runtime. */
3927 if (msg
== msh_mousewheel
)
3929 wmsg
.dwModifiers
= w32_get_modifiers ();
3930 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3931 signal_user_input ();
3936 return (w32_unicode_gui
? DefWindowProcW
: DefWindowProcA
) (hwnd
, msg
, wParam
, lParam
);
3939 /* The most common default return code for handled messages is 0. */
3944 my_create_window (struct frame
* f
)
3948 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
3950 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3954 /* Create a tooltip window. Unlike my_create_window, we do not do this
3955 indirectly via the Window thread, as we do not need to process Window
3956 messages for the tooltip. Creating tooltips indirectly also creates
3957 deadlocks when tooltips are created for menu items. */
3959 my_create_tip_window (struct frame
*f
)
3963 rect
.left
= rect
.top
= 0;
3964 rect
.right
= FRAME_PIXEL_WIDTH (f
);
3965 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
3967 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
3968 FRAME_EXTERNAL_MENU_BAR (f
));
3970 tip_window
= FRAME_W32_WINDOW (f
)
3971 = CreateWindow (EMACS_CLASS
,
3973 f
->output_data
.w32
->dwStyle
,
3976 rect
.right
- rect
.left
,
3977 rect
.bottom
- rect
.top
,
3978 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
3985 SetWindowLong (tip_window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
3986 SetWindowLong (tip_window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
3987 SetWindowLong (tip_window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
3988 SetWindowLong (tip_window
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
3990 /* Tip frames have no scrollbars. */
3991 SetWindowLong (tip_window
, WND_SCROLLBAR_INDEX
, 0);
3993 /* Do this to discard the default setting specified by our parent. */
3994 ShowWindow (tip_window
, SW_HIDE
);
3999 /* Create and set up the w32 window for frame F. */
4002 w32_window (struct frame
*f
, long window_prompting
, int minibuffer_only
)
4006 /* Use the resource name as the top-level window name
4007 for looking up resources. Make a non-Lisp copy
4008 for the window manager, so GC relocation won't bother it.
4010 Elsewhere we specify the window name for the window manager. */
4013 char *str
= SSDATA (Vx_resource_name
);
4014 f
->namebuf
= xmalloc (strlen (str
) + 1);
4015 strcpy (f
->namebuf
, str
);
4018 my_create_window (f
);
4020 validate_x_resource_name ();
4022 /* x_set_name normally ignores requests to set the name if the
4023 requested name is the same as the current name. This is the one
4024 place where that assumption isn't correct; f->name is set, but
4025 the server hasn't been told. */
4028 int explicit = f
->explicit_name
;
4030 f
->explicit_name
= 0;
4032 fset_name (f
, Qnil
);
4033 x_set_name (f
, name
, explicit);
4038 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4039 initialize_frame_menubar (f
);
4041 if (FRAME_W32_WINDOW (f
) == 0)
4042 error ("Unable to create window");
4045 /* Handle the icon stuff for this window. Perhaps later we might
4046 want an x_set_icon_position which can be called interactively as
4050 x_icon (struct frame
*f
, Lisp_Object parms
)
4052 Lisp_Object icon_x
, icon_y
;
4053 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4055 /* Set the position of the icon. Note that Windows 95 groups all
4056 icons in the tray. */
4057 icon_x
= x_get_arg (dpyinfo
, parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4058 icon_y
= x_get_arg (dpyinfo
, parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4059 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4061 CHECK_NUMBER (icon_x
);
4062 CHECK_NUMBER (icon_y
);
4064 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4065 error ("Both left and top icon corners of icon must be specified");
4069 if (! EQ (icon_x
, Qunbound
))
4070 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4073 /* Start up iconic or window? */
4074 x_wm_set_window_state
4075 (f
, (EQ (x_get_arg (dpyinfo
, parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4079 x_text_icon (f
, SSDATA ((!NILP (f
->icon_name
)
4089 x_make_gc (struct frame
*f
)
4091 XGCValues gc_values
;
4095 /* Create the GC's of this frame.
4096 Note that many default values are used. */
4099 gc_values
.font
= FRAME_FONT (f
);
4101 /* Cursor has cursor-color background, background-color foreground. */
4102 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
4103 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
4104 f
->output_data
.w32
->cursor_gc
4105 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
4106 (GCFont
| GCForeground
| GCBackground
),
4110 f
->output_data
.w32
->white_relief
.gc
= 0;
4111 f
->output_data
.w32
->black_relief
.gc
= 0;
4117 /* Handler for signals raised during x_create_frame and
4118 x_create_tip_frame. FRAME is the frame which is partially
4122 unwind_create_frame (Lisp_Object frame
)
4124 struct frame
*f
= XFRAME (frame
);
4126 /* If frame is ``official'', nothing to do. */
4127 if (NILP (Fmemq (frame
, Vframe_list
)))
4130 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4133 x_free_frame_resources (f
);
4137 /* Check that reference counts are indeed correct. */
4138 eassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4139 eassert (dpyinfo
->terminal
->image_cache
->refcount
== image_cache_refcount
);
4148 x_default_font_parameter (struct frame
*f
, Lisp_Object parms
)
4150 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4151 Lisp_Object font_param
= x_get_arg (dpyinfo
, parms
, Qfont
, NULL
, NULL
,
4154 if (EQ (font_param
, Qunbound
))
4156 font
= !NILP (font_param
) ? font_param
4157 : x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4159 if (!STRINGP (font
))
4162 static char *names
[]
4163 = { "Courier New-10",
4164 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4165 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4169 for (i
= 0; names
[i
]; i
++)
4171 font
= font_open_by_name (f
, build_unibyte_string (names
[i
]));
4176 error ("No suitable font was found");
4178 else if (!NILP (font_param
))
4180 /* Remember the explicit font parameter, so we can re-apply it after
4181 we've applied the `default' face settings. */
4182 x_set_frame_parameters (f
, Fcons (Fcons (Qfont_param
, font_param
), Qnil
));
4184 x_default_parameter (f
, parms
, Qfont
, font
, "font", "Font", RES_TYPE_STRING
);
4187 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4189 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
4190 Return an Emacs frame object.
4191 PARAMETERS is an alist of frame parameters.
4192 If the parameters specify that the frame should not have a minibuffer,
4193 and do not specify a specific minibuffer window to use,
4194 then `default-minibuffer-frame' must be a frame whose minibuffer can
4195 be shared by the new frame.
4197 This function is an internal primitive--use `make-frame' instead. */)
4198 (Lisp_Object parameters
)
4201 Lisp_Object frame
, tem
;
4203 int minibuffer_only
= 0;
4204 long window_prompting
= 0;
4206 ptrdiff_t count
= SPECPDL_INDEX ();
4207 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4208 Lisp_Object display
;
4209 struct w32_display_info
*dpyinfo
= NULL
;
4213 /* Make copy of frame parameters because the original is in pure
4215 parameters
= Fcopy_alist (parameters
);
4217 /* Use this general default value to start with
4218 until we know if this frame has a specified name. */
4219 Vx_resource_name
= Vinvocation_name
;
4221 display
= x_get_arg (dpyinfo
, parameters
, Qterminal
, 0, 0, RES_TYPE_NUMBER
);
4222 if (EQ (display
, Qunbound
))
4223 display
= x_get_arg (dpyinfo
, parameters
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4224 if (EQ (display
, Qunbound
))
4226 dpyinfo
= check_x_display_info (display
);
4227 kb
= dpyinfo
->terminal
->kboard
;
4229 if (!dpyinfo
->terminal
->name
)
4230 error ("Terminal is not live, can't create new frames on it");
4232 name
= x_get_arg (dpyinfo
, parameters
, Qname
, "name", "Name", RES_TYPE_STRING
);
4234 && ! EQ (name
, Qunbound
)
4236 error ("Invalid frame name--not a string or nil");
4239 Vx_resource_name
= name
;
4241 /* See if parent window is specified. */
4242 parent
= x_get_arg (dpyinfo
, parameters
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4243 if (EQ (parent
, Qunbound
))
4245 if (! NILP (parent
))
4246 CHECK_NUMBER (parent
);
4248 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4249 /* No need to protect DISPLAY because that's not used after passing
4250 it to make_frame_without_minibuffer. */
4252 GCPRO4 (parameters
, parent
, name
, frame
);
4253 tem
= x_get_arg (dpyinfo
, parameters
, Qminibuffer
, "minibuffer", "Minibuffer",
4255 if (EQ (tem
, Qnone
) || NILP (tem
))
4256 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4257 else if (EQ (tem
, Qonly
))
4259 f
= make_minibuffer_frame ();
4260 minibuffer_only
= 1;
4262 else if (WINDOWP (tem
))
4263 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4267 XSETFRAME (frame
, f
);
4269 /* Note that Windows does support scroll bars. */
4270 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4272 /* By default, make scrollbars the system standard width. */
4273 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
4275 f
->terminal
= dpyinfo
->terminal
;
4277 f
->output_method
= output_w32
;
4278 f
->output_data
.w32
= xzalloc (sizeof (struct w32_output
));
4279 FRAME_FONTSET (f
) = -1;
4282 (f
, x_get_arg (dpyinfo
, parameters
, Qicon_name
, "iconName", "Title",
4284 if (! STRINGP (f
->icon_name
))
4285 fset_icon_name (f
, Qnil
);
4287 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4289 /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
4290 record_unwind_protect (unwind_create_frame
, frame
);
4292 image_cache_refcount
=
4293 FRAME_IMAGE_CACHE (f
) ? FRAME_IMAGE_CACHE (f
)->refcount
: 0;
4294 dpyinfo_refcount
= dpyinfo
->reference_count
;
4295 #endif /* GLYPH_DEBUG */
4297 /* Specify the parent under which to make this window. */
4301 f
->output_data
.w32
->parent_desc
= (Window
) XFASTINT (parent
);
4302 f
->output_data
.w32
->explicit_parent
= 1;
4306 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4307 f
->output_data
.w32
->explicit_parent
= 0;
4310 /* Set the name; the functions to which we pass f expect the name to
4312 if (EQ (name
, Qunbound
) || NILP (name
))
4314 fset_name (f
, build_string (dpyinfo
->w32_id_name
));
4315 f
->explicit_name
= 0;
4319 fset_name (f
, name
);
4320 f
->explicit_name
= 1;
4321 /* use the frame's title when getting resources for this frame. */
4322 specbind (Qx_resource_name
, name
);
4325 f
->resx
= dpyinfo
->resx
;
4326 f
->resy
= dpyinfo
->resy
;
4328 if (uniscribe_available
)
4329 register_font_driver (&uniscribe_font_driver
, f
);
4330 register_font_driver (&w32font_driver
, f
);
4332 x_default_parameter (f
, parameters
, Qfont_backend
, Qnil
,
4333 "fontBackend", "FontBackend", RES_TYPE_STRING
);
4334 /* Extract the window parameters from the supplied values
4335 that are needed to determine window geometry. */
4336 x_default_font_parameter (f
, parameters
);
4337 x_default_parameter (f
, parameters
, Qborder_width
, make_number (2),
4338 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4340 /* We recognize either internalBorderWidth or internalBorder
4341 (which is what xterm calls it). */
4342 if (NILP (Fassq (Qinternal_border_width
, parameters
)))
4346 value
= x_get_arg (dpyinfo
, parameters
, Qinternal_border_width
,
4347 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
4348 if (! EQ (value
, Qunbound
))
4349 parameters
= Fcons (Fcons (Qinternal_border_width
, value
),
4352 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4353 x_default_parameter (f
, parameters
, Qinternal_border_width
, make_number (0),
4354 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4355 x_default_parameter (f
, parameters
, Qvertical_scroll_bars
, Qright
,
4356 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4358 /* Also do the stuff which must be set before the window exists. */
4359 x_default_parameter (f
, parameters
, Qforeground_color
, build_string ("black"),
4360 "foreground", "Foreground", RES_TYPE_STRING
);
4361 x_default_parameter (f
, parameters
, Qbackground_color
, build_string ("white"),
4362 "background", "Background", RES_TYPE_STRING
);
4363 x_default_parameter (f
, parameters
, Qmouse_color
, build_string ("black"),
4364 "pointerColor", "Foreground", RES_TYPE_STRING
);
4365 x_default_parameter (f
, parameters
, Qborder_color
, build_string ("black"),
4366 "borderColor", "BorderColor", RES_TYPE_STRING
);
4367 x_default_parameter (f
, parameters
, Qscreen_gamma
, Qnil
,
4368 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4369 x_default_parameter (f
, parameters
, Qline_spacing
, Qnil
,
4370 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4371 x_default_parameter (f
, parameters
, Qleft_fringe
, Qnil
,
4372 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4373 x_default_parameter (f
, parameters
, Qright_fringe
, Qnil
,
4374 "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 f
->terminal
->reference_count
++;
4427 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4428 Vframe_list
= Fcons (frame
, Vframe_list
);
4430 /* We need to do this after creating the window, so that the
4431 icon-creation functions can say whose icon they're describing. */
4432 x_default_parameter (f
, parameters
, Qicon_type
, Qnil
,
4433 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4435 x_default_parameter (f
, parameters
, Qauto_raise
, Qnil
,
4436 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4437 x_default_parameter (f
, parameters
, Qauto_lower
, Qnil
,
4438 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4439 x_default_parameter (f
, parameters
, Qcursor_type
, Qbox
,
4440 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4441 x_default_parameter (f
, parameters
, Qscroll_bar_width
, Qnil
,
4442 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4443 x_default_parameter (f
, parameters
, Qalpha
, Qnil
,
4444 "alpha", "Alpha", RES_TYPE_NUMBER
);
4446 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4447 Change will not be effected unless different from the current
4449 width
= FRAME_COLS (f
);
4450 height
= FRAME_LINES (f
);
4452 FRAME_LINES (f
) = 0;
4453 SET_FRAME_COLS (f
, 0);
4454 change_frame_size (f
, height
, width
, 1, 0, 0);
4456 /* Tell the server what size and position, etc, we want, and how
4457 badly we want them. This should be done after we have the menu
4458 bar so that its size can be taken into account. */
4460 x_wm_set_size_hint (f
, window_prompting
, 0);
4463 /* Make the window appear on the frame and enable display, unless
4464 the caller says not to. However, with explicit parent, Emacs
4465 cannot control visibility, so don't try. */
4466 if (! f
->output_data
.w32
->explicit_parent
)
4468 Lisp_Object visibility
;
4470 visibility
= x_get_arg (dpyinfo
, parameters
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4471 if (EQ (visibility
, Qunbound
))
4474 if (EQ (visibility
, Qicon
))
4475 x_iconify_frame (f
);
4476 else if (! NILP (visibility
))
4477 x_make_frame_visible (f
);
4479 /* Must have been Qnil. */
4483 /* Initialize `default-minibuffer-frame' in case this is the first
4484 frame on this terminal. */
4485 if (FRAME_HAS_MINIBUF_P (f
)
4486 && (!FRAMEP (KVAR (kb
, Vdefault_minibuffer_frame
))
4487 || !FRAME_LIVE_P (XFRAME (KVAR (kb
, Vdefault_minibuffer_frame
)))))
4488 kset_default_minibuffer_frame (kb
, frame
);
4490 /* All remaining specified parameters, which have not been "used"
4491 by x_get_arg and friends, now go in the misc. alist of the frame. */
4492 for (tem
= parameters
; CONSP (tem
); tem
= XCDR (tem
))
4493 if (CONSP (XCAR (tem
)) && !NILP (XCAR (XCAR (tem
))))
4494 fset_param_alist (f
, Fcons (XCAR (tem
), f
->param_alist
));
4498 /* Make sure windows on this frame appear in calls to next-window
4499 and similar functions. */
4500 Vwindow_list
= Qnil
;
4502 return unbind_to (count
, frame
);
4505 /* FRAME is used only to get a handle on the X display. We don't pass the
4506 display info directly because we're called from frame.c, which doesn't
4507 know about that structure. */
4509 x_get_focus_frame (struct frame
*frame
)
4511 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4513 if (! dpyinfo
->w32_focus_frame
)
4516 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4520 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4521 doc
: /* Give FRAME input focus, raising to foreground if necessary. */)
4524 x_focus_on_frame (check_x_frame (frame
));
4529 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
4530 doc
: /* Internal function called by `color-defined-p', which see.
4531 \(Note that the Nextstep version of this function ignores FRAME.) */)
4532 (Lisp_Object color
, Lisp_Object frame
)
4535 FRAME_PTR f
= check_x_frame (frame
);
4537 CHECK_STRING (color
);
4539 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
4545 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
4546 doc
: /* Internal function called by `color-values', which see. */)
4547 (Lisp_Object color
, Lisp_Object frame
)
4550 FRAME_PTR f
= check_x_frame (frame
);
4552 CHECK_STRING (color
);
4554 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
4555 return list3 (make_number ((GetRValue (foo
.pixel
) << 8)
4556 | GetRValue (foo
.pixel
)),
4557 make_number ((GetGValue (foo
.pixel
) << 8)
4558 | GetGValue (foo
.pixel
)),
4559 make_number ((GetBValue (foo
.pixel
) << 8)
4560 | GetBValue (foo
.pixel
)));
4565 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
4566 doc
: /* Internal function called by `display-color-p', which see. */)
4567 (Lisp_Object display
)
4569 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4571 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
4577 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
,
4578 Sx_display_grayscale_p
, 0, 1, 0,
4579 doc
: /* Return t if DISPLAY supports shades of gray.
4580 Note that color displays do support shades of gray.
4581 The optional argument DISPLAY specifies which display to ask about.
4582 DISPLAY should be either a frame or a display name (a string).
4583 If omitted or nil, that stands for the selected frame's display. */)
4584 (Lisp_Object display
)
4586 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4588 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
4594 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
,
4595 Sx_display_pixel_width
, 0, 1, 0,
4596 doc
: /* Return the width in pixels of DISPLAY.
4597 The optional argument DISPLAY specifies which display to ask about.
4598 DISPLAY should be either a frame or a display name (a string).
4599 If omitted or nil, that stands for the selected frame's display. */)
4600 (Lisp_Object display
)
4602 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4604 return make_number (x_display_pixel_width (dpyinfo
));
4607 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
4608 Sx_display_pixel_height
, 0, 1, 0,
4609 doc
: /* Return the height in pixels of DISPLAY.
4610 The optional argument DISPLAY specifies which display to ask about.
4611 DISPLAY should be either a frame or a display name (a string).
4612 If omitted or nil, that stands for the selected frame's display. */)
4613 (Lisp_Object display
)
4615 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4617 return make_number (x_display_pixel_height (dpyinfo
));
4620 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
4622 doc
: /* Return the number of bitplanes of DISPLAY.
4623 The optional argument DISPLAY specifies which display to ask about.
4624 DISPLAY should be either a frame or a display name (a string).
4625 If omitted or nil, that stands for the selected frame's display. */)
4626 (Lisp_Object display
)
4628 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4630 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
4633 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
4635 doc
: /* Return the number of color cells of DISPLAY.
4636 The optional argument DISPLAY specifies which display to ask about.
4637 DISPLAY should be either a frame or a display name (a string).
4638 If omitted or nil, that stands for the selected frame's display. */)
4639 (Lisp_Object display
)
4641 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
4645 hdc
= GetDC (dpyinfo
->root_window
);
4646 if (dpyinfo
->has_palette
)
4647 cap
= GetDeviceCaps (hdc
, SIZEPALETTE
);
4649 cap
= GetDeviceCaps (hdc
, NUMCOLORS
);
4651 /* We force 24+ bit depths to 24-bit, both to prevent an overflow
4652 and because probably is more meaningful on Windows anyway */
4654 cap
= 1 << min (dpyinfo
->n_planes
* dpyinfo
->n_cbits
, 24);
4656 ReleaseDC (dpyinfo
->root_window
, hdc
);
4658 return make_number (cap
);
4661 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
4662 Sx_server_max_request_size
,
4664 doc
: /* Return the maximum request size of the server of DISPLAY.
4665 The optional argument DISPLAY specifies which display to ask about.
4666 DISPLAY should be either a frame or a display name (a string).
4667 If omitted or nil, that stands for the selected frame's display. */)
4668 (Lisp_Object 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
)
4800 DEFUN ("set-message-beep", Fset_message_beep
, Sset_message_beep
, 1, 1, 0,
4801 doc
: /* Set the sound generated when the bell is rung.
4802 SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
4803 to use the corresponding system sound for the bell. The 'silent sound
4804 prevents Emacs from making any sound at all.
4805 SOUND is nil to use the normal beep. */)
4808 CHECK_SYMBOL (sound
);
4811 sound_type
= 0xFFFFFFFF;
4812 else if (EQ (sound
, intern ("asterisk")))
4813 sound_type
= MB_ICONASTERISK
;
4814 else if (EQ (sound
, intern ("exclamation")))
4815 sound_type
= MB_ICONEXCLAMATION
;
4816 else if (EQ (sound
, intern ("hand")))
4817 sound_type
= MB_ICONHAND
;
4818 else if (EQ (sound
, intern ("question")))
4819 sound_type
= MB_ICONQUESTION
;
4820 else if (EQ (sound
, intern ("ok")))
4822 else if (EQ (sound
, intern ("silent")))
4823 sound_type
= MB_EMACS_SILENT
;
4825 sound_type
= 0xFFFFFFFF;
4832 x_pixel_width (register struct frame
*f
)
4834 return FRAME_PIXEL_WIDTH (f
);
4838 x_pixel_height (register struct frame
*f
)
4840 return FRAME_PIXEL_HEIGHT (f
);
4844 x_char_width (register struct frame
*f
)
4846 return FRAME_COLUMN_WIDTH (f
);
4850 x_char_height (register struct frame
*f
)
4852 return FRAME_LINE_HEIGHT (f
);
4856 x_screen_planes (register struct frame
*f
)
4858 return FRAME_W32_DISPLAY_INFO (f
)->n_planes
;
4861 /* Return the display structure for the display named NAME.
4862 Open a new connection if necessary. */
4864 struct w32_display_info
*
4865 x_display_info_for_name (Lisp_Object name
)
4868 struct w32_display_info
*dpyinfo
;
4870 CHECK_STRING (name
);
4872 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
4873 dpyinfo
&& !NILP (w32_display_name_list
);
4874 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
4877 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
4882 /* Use this general default value to start with. */
4883 Vx_resource_name
= Vinvocation_name
;
4885 validate_x_resource_name ();
4887 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
4888 SSDATA (Vx_resource_name
));
4891 error ("Cannot connect to server %s", SDATA (name
));
4894 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
4899 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
4900 1, 3, 0, doc
: /* Open a connection to a display server.
4901 DISPLAY is the name of the display to connect to.
4902 Optional second arg XRM-STRING is a string of resources in xrdb format.
4903 If the optional third arg MUST-SUCCEED is non-nil,
4904 terminate Emacs if we can't open the connection.
4905 \(In the Nextstep version, the last two arguments are currently ignored.) */)
4906 (Lisp_Object display
, Lisp_Object xrm_string
, Lisp_Object must_succeed
)
4908 unsigned char *xrm_option
;
4909 struct w32_display_info
*dpyinfo
;
4911 CHECK_STRING (display
);
4913 /* Signal an error in order to encourage correct use from callers.
4914 * If we ever support multiple window systems in the same Emacs,
4915 * we'll need callers to be precise about what window system they
4918 if (strcmp (SSDATA (display
), "w32") != 0)
4919 error ("The name of the display in this Emacs must be \"w32\"");
4921 /* If initialization has already been done, return now to avoid
4922 overwriting critical parts of one_w32_display_info. */
4926 if (! NILP (xrm_string
))
4927 CHECK_STRING (xrm_string
);
4930 if (! EQ (Vwindow_system
, intern ("w32")))
4931 error ("Not using Microsoft Windows");
4934 /* Allow color mapping to be defined externally; first look in user's
4935 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
4937 Lisp_Object color_file
;
4938 struct gcpro gcpro1
;
4940 color_file
= build_string ("~/rgb.txt");
4942 GCPRO1 (color_file
);
4944 if (NILP (Ffile_readable_p (color_file
)))
4946 Fexpand_file_name (build_string ("rgb.txt"),
4947 Fsymbol_value (intern ("data-directory")));
4949 Vw32_color_map
= Fx_load_color_file (color_file
);
4953 if (NILP (Vw32_color_map
))
4954 Vw32_color_map
= w32_default_color_map ();
4956 /* Merge in system logical colors. */
4957 add_system_logical_colors_to_map (&Vw32_color_map
);
4959 if (! NILP (xrm_string
))
4960 xrm_option
= SDATA (xrm_string
);
4962 xrm_option
= (unsigned char *) 0;
4964 /* Use this general default value to start with. */
4965 /* First remove .exe suffix from invocation-name - it looks ugly. */
4967 char basename
[ MAX_PATH
], *str
;
4969 strcpy (basename
, SDATA (Vinvocation_name
));
4970 str
= strrchr (basename
, '.');
4972 Vinvocation_name
= build_string (basename
);
4974 Vx_resource_name
= Vinvocation_name
;
4976 validate_x_resource_name ();
4978 /* This is what opens the connection and sets x_current_display.
4979 This also initializes many symbols, such as those used for input. */
4980 dpyinfo
= w32_term_init (display
, xrm_option
,
4981 SSDATA (Vx_resource_name
));
4985 if (!NILP (must_succeed
))
4986 fatal ("Cannot connect to server %s.\n",
4989 error ("Cannot connect to server %s", SDATA (display
));
4994 XSETFASTINT (Vwindow_system_version
, w32_major_version
);
4998 DEFUN ("x-close-connection", Fx_close_connection
,
4999 Sx_close_connection
, 1, 1, 0,
5000 doc
: /* Close the connection to DISPLAY's server.
5001 For DISPLAY, specify either a frame or a display name (a string).
5002 If DISPLAY is nil, that stands for the selected frame's display. */)
5003 (Lisp_Object display
)
5005 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5007 if (dpyinfo
->reference_count
> 0)
5008 error ("Display still has frames on it");
5011 x_destroy_all_bitmaps (dpyinfo
);
5013 x_delete_display (dpyinfo
);
5019 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5020 doc
: /* Return the list of display names that Emacs has connections to. */)
5023 Lisp_Object tail
, result
;
5026 for (tail
= w32_display_name_list
; CONSP (tail
); tail
= XCDR (tail
))
5027 result
= Fcons (XCAR (XCAR (tail
)), result
);
5032 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5033 doc
: /* If ON is non-nil, report X errors as soon as the erring request is made.
5034 This function only has an effect on X Windows. With MS Windows, it is
5035 defined but does nothing.
5037 If ON is nil, allow buffering of requests.
5038 Turning on synchronization prohibits the Xlib routines from buffering
5039 requests and seriously degrades performance, but makes debugging much
5041 The optional second argument TERMINAL specifies which display to act on.
5042 TERMINAL should be a terminal object, a frame or a display name (a string).
5043 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5044 (Lisp_Object on
, Lisp_Object display
)
5051 /***********************************************************************
5053 ***********************************************************************/
5055 #if 0 /* TODO : port window properties to W32 */
5057 DEFUN ("x-change-window-property", Fx_change_window_property
,
5058 Sx_change_window_property
, 2, 6, 0,
5059 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
5060 PROP must be a string. VALUE may be a string or a list of conses,
5061 numbers and/or strings. If an element in the list is a string, it is
5062 converted to an atom and the value of the Atom is used. If an element
5063 is a cons, it is converted to a 32 bit number where the car is the 16
5064 top bits and the cdr is the lower 16 bits.
5066 FRAME nil or omitted means use the selected frame.
5067 If TYPE is given and non-nil, it is the name of the type of VALUE.
5068 If TYPE is not given or nil, the type is STRING.
5069 FORMAT gives the size in bits of each element if VALUE is a list.
5070 It must be one of 8, 16 or 32.
5071 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5072 If OUTER-P is non-nil, the property is changed for the outer X window of
5073 FRAME. Default is to change on the edit X window. */)
5074 (Lisp_Object prop
, Lisp_Object value
, Lisp_Object frame
,
5075 Lisp_Object type
, Lisp_Object format
, Lisp_Object outer_p
)
5077 struct frame
*f
= check_x_frame (frame
);
5080 CHECK_STRING (prop
);
5081 CHECK_STRING (value
);
5084 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5085 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5086 prop_atom
, XA_STRING
, 8, PropModeReplace
,
5087 SDATA (value
), SCHARS (value
));
5089 /* Make sure the property is set when we return. */
5090 XFlush (FRAME_W32_DISPLAY (f
));
5097 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
5098 Sx_delete_window_property
, 1, 2, 0,
5099 doc
: /* Remove window property PROP from X window of FRAME.
5100 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5101 (Lisp_Object prop
, Lisp_Object frame
)
5103 struct frame
*f
= check_x_frame (frame
);
5106 CHECK_STRING (prop
);
5108 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5109 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
5111 /* Make sure the property is removed when we return. */
5112 XFlush (FRAME_W32_DISPLAY (f
));
5119 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
5121 doc
: /* Value is the value of window property PROP on FRAME.
5122 If FRAME is nil or omitted, use the selected frame.
5124 On X Windows, the following optional arguments are also accepted:
5125 If TYPE is nil or omitted, get the property as a string.
5126 Otherwise TYPE is the name of the atom that denotes the type expected.
5127 If SOURCE is non-nil, get the property on that window instead of from
5128 FRAME. The number 0 denotes the root window.
5129 If DELETE-P is non-nil, delete the property after retrieving it.
5130 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5132 On MS Windows, this function accepts but ignores those optional arguments.
5134 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5135 no value of TYPE (always string in the MS Windows case). */)
5136 (Lisp_Object prop
, Lisp_Object frame
, Lisp_Object type
,
5137 Lisp_Object source
, Lisp_Object delete_p
, Lisp_Object vector_ret_p
)
5139 struct frame
*f
= check_x_frame (frame
);
5142 Lisp_Object prop_value
= Qnil
;
5143 char *tmp_data
= NULL
;
5146 unsigned long actual_size
, bytes_remaining
;
5148 CHECK_STRING (prop
);
5150 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
5151 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5152 prop_atom
, 0, 0, False
, XA_STRING
,
5153 &actual_type
, &actual_format
, &actual_size
,
5154 &bytes_remaining
, (unsigned char **) &tmp_data
);
5157 int size
= bytes_remaining
;
5162 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
5163 prop_atom
, 0, bytes_remaining
,
5165 &actual_type
, &actual_format
,
5166 &actual_size
, &bytes_remaining
,
5167 (unsigned char **) &tmp_data
);
5169 prop_value
= make_string (tmp_data
, size
);
5184 /***********************************************************************
5186 ***********************************************************************/
5189 w32_note_current_window (void)
5191 struct frame
* f
= SELECTED_FRAME ();
5193 if (!FRAME_W32_P (f
))
5196 hourglass_hwnd
= FRAME_W32_WINDOW (f
);
5200 show_hourglass (struct atimer
*timer
)
5204 hourglass_atimer
= NULL
;
5207 f
= x_window_to_frame (&one_w32_display_info
,
5211 f
->output_data
.w32
->hourglass_p
= 0;
5213 f
= SELECTED_FRAME ();
5215 if (!FRAME_W32_P (f
))
5218 w32_show_hourglass (f
);
5223 hide_hourglass (void)
5226 w32_hide_hourglass ();
5231 /* Display an hourglass cursor. Set the hourglass_p flag in display info
5232 to indicate that an hourglass cursor is shown. */
5235 w32_show_hourglass (struct frame
*f
)
5237 if (!hourglass_shown_p
)
5239 f
->output_data
.w32
->hourglass_p
= 1;
5240 if (!menubar_in_use
&& !current_popup_menu
)
5241 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
5242 hourglass_shown_p
= 1;
5247 /* Hide the hourglass cursor on all frames, if it is currently shown. */
5250 w32_hide_hourglass (void)
5252 if (hourglass_shown_p
)
5254 struct frame
*f
= x_window_to_frame (&one_w32_display_info
,
5257 f
->output_data
.w32
->hourglass_p
= 0;
5259 /* If frame was deleted, restore to selected frame's cursor. */
5260 f
= SELECTED_FRAME ();
5262 if (FRAME_W32_P (f
))
5263 SetCursor (f
->output_data
.w32
->current_cursor
);
5265 /* No cursors on non GUI frames - restore to stock arrow cursor. */
5266 SetCursor (w32_load_cursor (IDC_ARROW
));
5268 hourglass_shown_p
= 0;
5274 /***********************************************************************
5276 ***********************************************************************/
5278 static Lisp_Object
x_create_tip_frame (struct w32_display_info
*,
5279 Lisp_Object
, Lisp_Object
);
5280 static void compute_tip_xy (struct frame
*, Lisp_Object
, Lisp_Object
,
5281 Lisp_Object
, int, int, int *, int *);
5283 /* The frame of a currently visible tooltip. */
5285 Lisp_Object tip_frame
;
5287 /* If non-nil, a timer started that hides the last tooltip when it
5290 Lisp_Object tip_timer
;
5293 /* If non-nil, a vector of 3 elements containing the last args
5294 with which x-show-tip was called. See there. */
5296 Lisp_Object last_show_tip_args
;
5300 unwind_create_tip_frame (Lisp_Object frame
)
5302 Lisp_Object deleted
;
5304 deleted
= unwind_create_frame (frame
);
5305 if (EQ (deleted
, Qt
))
5315 /* Create a frame for a tooltip on the display described by DPYINFO.
5316 PARMS is a list of frame parameters. TEXT is the string to
5317 display in the tip frame. Value is the frame.
5319 Note that functions called here, esp. x_default_parameter can
5320 signal errors, for instance when a specified color name is
5321 undefined. We have to make sure that we're in a consistent state
5322 when this happens. */
5325 x_create_tip_frame (struct w32_display_info
*dpyinfo
,
5326 Lisp_Object parms
, Lisp_Object text
)
5331 long window_prompting
= 0;
5333 ptrdiff_t count
= SPECPDL_INDEX ();
5334 struct gcpro gcpro1
, gcpro2
, gcpro3
;
5336 int face_change_count_before
= face_change_count
;
5338 struct buffer
*old_buffer
;
5342 /* Use this general default value to start with until we know if
5343 this frame has a specified name. */
5344 Vx_resource_name
= Vinvocation_name
;
5346 kb
= dpyinfo
->terminal
->kboard
;
5348 /* The calls to x_get_arg remove elements from PARMS, so copy it to
5349 avoid destructive changes behind our caller's back. */
5350 parms
= Fcopy_alist (parms
);
5352 /* Get the name of the frame to use for resource lookup. */
5353 name
= x_get_arg (dpyinfo
, parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
5355 && !EQ (name
, Qunbound
)
5357 error ("Invalid frame name--not a string or nil");
5358 Vx_resource_name
= name
;
5361 GCPRO3 (parms
, name
, frame
);
5362 /* Make a frame without minibuffer nor mode-line. */
5364 f
->wants_modeline
= 0;
5365 XSETFRAME (frame
, f
);
5367 buffer
= Fget_buffer_create (build_string (" *tip*"));
5368 /* Use set_window_buffer instead of Fset_window_buffer (see
5369 discussion of bug#11984, bug#12025, bug#12026). */
5370 set_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
, 0, 0);
5371 old_buffer
= current_buffer
;
5372 set_buffer_internal_1 (XBUFFER (buffer
));
5373 bset_truncate_lines (current_buffer
, Qnil
);
5374 specbind (Qinhibit_read_only
, Qt
);
5375 specbind (Qinhibit_modification_hooks
, Qt
);
5378 set_buffer_internal_1 (old_buffer
);
5380 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
5381 record_unwind_protect (unwind_create_tip_frame
, frame
);
5383 /* By setting the output method, we're essentially saying that
5384 the frame is live, as per FRAME_LIVE_P. If we get a signal
5385 from this point on, x_destroy_window might screw up reference
5387 f
->terminal
= dpyinfo
->terminal
;
5388 f
->output_method
= output_w32
;
5389 f
->output_data
.w32
= xzalloc (sizeof (struct w32_output
));
5391 FRAME_FONTSET (f
) = -1;
5392 fset_icon_name (f
, Qnil
);
5395 image_cache_refcount
=
5396 FRAME_IMAGE_CACHE (f
) ? FRAME_IMAGE_CACHE (f
)->refcount
: 0;
5397 dpyinfo_refcount
= dpyinfo
->reference_count
;
5398 #endif /* GLYPH_DEBUG */
5399 FRAME_KBOARD (f
) = kb
;
5400 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5401 f
->output_data
.w32
->explicit_parent
= 0;
5403 /* Set the name; the functions to which we pass f expect the name to
5405 if (EQ (name
, Qunbound
) || NILP (name
))
5407 fset_name (f
, build_string (dpyinfo
->w32_id_name
));
5408 f
->explicit_name
= 0;
5412 fset_name (f
, name
);
5413 f
->explicit_name
= 1;
5414 /* use the frame's title when getting resources for this frame. */
5415 specbind (Qx_resource_name
, name
);
5418 f
->resx
= dpyinfo
->resx
;
5419 f
->resy
= dpyinfo
->resy
;
5421 if (uniscribe_available
)
5422 register_font_driver (&uniscribe_font_driver
, f
);
5423 register_font_driver (&w32font_driver
, f
);
5425 x_default_parameter (f
, parms
, Qfont_backend
, Qnil
,
5426 "fontBackend", "FontBackend", RES_TYPE_STRING
);
5428 /* Extract the window parameters from the supplied values
5429 that are needed to determine window geometry. */
5430 x_default_font_parameter (f
, parms
);
5432 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
5433 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
5434 /* This defaults to 2 in order to match xterm. We recognize either
5435 internalBorderWidth or internalBorder (which is what xterm calls
5437 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5441 value
= x_get_arg (dpyinfo
, parms
, Qinternal_border_width
,
5442 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
5443 if (! EQ (value
, Qunbound
))
5444 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
5447 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
5448 "internalBorderWidth", "internalBorderWidth",
5451 /* Also do the stuff which must be set before the window exists. */
5452 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
5453 "foreground", "Foreground", RES_TYPE_STRING
);
5454 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
5455 "background", "Background", RES_TYPE_STRING
);
5456 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
5457 "pointerColor", "Foreground", RES_TYPE_STRING
);
5458 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
5459 "cursorColor", "Foreground", RES_TYPE_STRING
);
5460 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
5461 "borderColor", "BorderColor", RES_TYPE_STRING
);
5463 /* Init faces before x_default_parameter is called for scroll-bar
5464 parameters because that function calls x_set_scroll_bar_width,
5465 which calls change_frame_size, which calls Fset_window_buffer,
5466 which runs hooks, which call Fvertical_motion. At the end, we
5467 end up in init_iterator with a null face cache, which should not
5469 init_frame_faces (f
);
5471 f
->output_data
.w32
->dwStyle
= WS_BORDER
| WS_POPUP
| WS_DISABLED
;
5472 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
5474 window_prompting
= x_figure_window_size (f
, parms
, 0);
5476 /* No fringes on tip frame. */
5478 f
->left_fringe_width
= 0;
5479 f
->right_fringe_width
= 0;
5482 my_create_tip_window (f
);
5487 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
5488 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5489 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
5490 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
5491 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
5492 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
5494 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
5495 Change will not be effected unless different from the current
5497 width
= FRAME_COLS (f
);
5498 height
= FRAME_LINES (f
);
5499 FRAME_LINES (f
) = 0;
5500 SET_FRAME_COLS (f
, 0);
5501 change_frame_size (f
, height
, width
, 1, 0, 0);
5503 /* Add `tooltip' frame parameter's default value. */
5504 if (NILP (Fframe_parameter (frame
, Qtooltip
)))
5505 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qtooltip
, Qt
), Qnil
));
5507 /* Set up faces after all frame parameters are known. This call
5508 also merges in face attributes specified for new frames.
5510 Frame parameters may be changed if .Xdefaults contains
5511 specifications for the default font. For example, if there is an
5512 `Emacs.default.attributeBackground: pink', the `background-color'
5513 attribute of the frame get's set, which let's the internal border
5514 of the tooltip frame appear in pink. Prevent this. */
5516 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
5517 Lisp_Object fg
= Fframe_parameter (frame
, Qforeground_color
);
5518 Lisp_Object colors
= Qnil
;
5520 /* Set tip_frame here, so that */
5522 call2 (Qface_set_after_frame_default
, frame
, Qnil
);
5524 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
5525 colors
= Fcons (Fcons (Qbackground_color
, bg
), colors
);
5526 if (!EQ (fg
, Fframe_parameter (frame
, Qforeground_color
)))
5527 colors
= Fcons (Fcons (Qforeground_color
, fg
), colors
);
5530 Fmodify_frame_parameters (frame
, colors
);
5537 /* Now that the frame is official, it counts as a reference to
5539 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
5540 f
->terminal
->reference_count
++;
5542 /* It is now ok to make the frame official even if we get an error
5543 below. And the frame needs to be on Vframe_list or making it
5544 visible won't work. */
5545 Vframe_list
= Fcons (frame
, Vframe_list
);
5547 /* Setting attributes of faces of the tooltip frame from resources
5548 and similar will increment face_change_count, which leads to the
5549 clearing of all current matrices. Since this isn't necessary
5550 here, avoid it by resetting face_change_count to the value it
5551 had before we created the tip frame. */
5552 face_change_count
= face_change_count_before
;
5554 /* Discard the unwind_protect. */
5555 return unbind_to (count
, frame
);
5559 /* Compute where to display tip frame F. PARMS is the list of frame
5560 parameters for F. DX and DY are specified offsets from the current
5561 location of the mouse. WIDTH and HEIGHT are the width and height
5562 of the tooltip. Return coordinates relative to the root window of
5563 the display in *ROOT_X, and *ROOT_Y. */
5566 compute_tip_xy (struct frame
*f
,
5567 Lisp_Object parms
, Lisp_Object dx
, Lisp_Object dy
,
5568 int width
, int height
, int *root_x
, int *root_y
)
5570 Lisp_Object left
, top
;
5571 int min_x
, min_y
, max_x
, max_y
;
5573 /* User-specified position? */
5574 left
= Fcdr (Fassq (Qleft
, parms
));
5575 top
= Fcdr (Fassq (Qtop
, parms
));
5577 /* Move the tooltip window where the mouse pointer is. Resize and
5579 if (!INTEGERP (left
) || !INTEGERP (top
))
5583 /* Default min and max values. */
5586 max_x
= x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f
));
5587 max_y
= x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f
));
5595 /* If multiple monitor support is available, constrain the tip onto
5596 the current monitor. This improves the above by allowing negative
5597 co-ordinates if monitor positions are such that they are valid, and
5598 snaps a tooltip onto a single monitor if we are close to the edge
5599 where it would otherwise flow onto the other monitor (or into
5600 nothingness if there is a gap in the overlap). */
5601 if (monitor_from_point_fn
&& get_monitor_info_fn
)
5603 struct MONITOR_INFO info
;
5605 = monitor_from_point_fn (pt
, MONITOR_DEFAULT_TO_NEAREST
);
5606 info
.cbSize
= sizeof (info
);
5608 if (get_monitor_info_fn (monitor
, &info
))
5610 min_x
= info
.rcWork
.left
;
5611 min_y
= info
.rcWork
.top
;
5612 max_x
= info
.rcWork
.right
;
5613 max_y
= info
.rcWork
.bottom
;
5619 *root_y
= XINT (top
);
5620 else if (*root_y
+ XINT (dy
) <= min_y
)
5621 *root_y
= min_y
; /* Can happen for negative dy */
5622 else if (*root_y
+ XINT (dy
) + height
<= max_y
)
5623 /* It fits below the pointer */
5624 *root_y
+= XINT (dy
);
5625 else if (height
+ XINT (dy
) + min_y
<= *root_y
)
5626 /* It fits above the pointer. */
5627 *root_y
-= height
+ XINT (dy
);
5629 /* Put it on the top. */
5632 if (INTEGERP (left
))
5633 *root_x
= XINT (left
);
5634 else if (*root_x
+ XINT (dx
) <= min_x
)
5635 *root_x
= 0; /* Can happen for negative dx */
5636 else if (*root_x
+ XINT (dx
) + width
<= max_x
)
5637 /* It fits to the right of the pointer. */
5638 *root_x
+= XINT (dx
);
5639 else if (width
+ XINT (dx
) + min_x
<= *root_x
)
5640 /* It fits to the left of the pointer. */
5641 *root_x
-= width
+ XINT (dx
);
5643 /* Put it left justified on the screen -- it ought to fit that way. */
5648 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
5649 doc
: /* Show STRING in a \"tooltip\" window on frame FRAME.
5650 A tooltip window is a small window displaying a string.
5652 This is an internal function; Lisp code should call `tooltip-show'.
5654 FRAME nil or omitted means use the selected frame.
5656 PARMS is an optional list of frame parameters which can be
5657 used to change the tooltip's appearance.
5659 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
5660 means use the default timeout of 5 seconds.
5662 If the list of frame parameters PARMS contains a `left' parameter,
5663 the tooltip is displayed at that x-position. Otherwise it is
5664 displayed at the mouse position, with offset DX added (default is 5 if
5665 DX isn't specified). Likewise for the y-position; if a `top' frame
5666 parameter is specified, it determines the y-position of the tooltip
5667 window, otherwise it is displayed at the mouse position, with offset
5668 DY added (default is -10).
5670 A tooltip's maximum size is specified by `x-max-tooltip-size'.
5671 Text larger than the specified size is clipped. */)
5672 (Lisp_Object string
, Lisp_Object frame
, Lisp_Object parms
, Lisp_Object timeout
, Lisp_Object dx
, Lisp_Object dy
)
5677 struct buffer
*old_buffer
;
5678 struct text_pos pos
;
5679 int i
, width
, height
, seen_reversed_p
;
5680 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
5681 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
5682 ptrdiff_t count
= SPECPDL_INDEX ();
5684 specbind (Qinhibit_redisplay
, Qt
);
5686 GCPRO4 (string
, parms
, frame
, timeout
);
5688 CHECK_STRING (string
);
5689 f
= check_x_frame (frame
);
5691 timeout
= make_number (5);
5693 CHECK_NATNUM (timeout
);
5696 dx
= make_number (5);
5701 dy
= make_number (-10);
5705 if (NILP (last_show_tip_args
))
5706 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
5708 if (!NILP (tip_frame
))
5710 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
5711 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
5712 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
5714 if (EQ (frame
, last_frame
)
5715 && !NILP (Fequal (last_string
, string
))
5716 && !NILP (Fequal (last_parms
, parms
)))
5718 struct frame
*f
= XFRAME (tip_frame
);
5720 /* Only DX and DY have changed. */
5721 if (!NILP (tip_timer
))
5723 Lisp_Object timer
= tip_timer
;
5725 call1 (Qcancel_timer
, timer
);
5729 compute_tip_xy (f
, parms
, dx
, dy
, FRAME_PIXEL_WIDTH (f
),
5730 FRAME_PIXEL_HEIGHT (f
), &root_x
, &root_y
);
5732 /* Put tooltip in topmost group and in position. */
5733 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
5734 root_x
, root_y
, 0, 0,
5735 SWP_NOSIZE
| SWP_NOACTIVATE
);
5737 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5738 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
5740 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5747 /* Hide a previous tip, if any. */
5750 ASET (last_show_tip_args
, 0, string
);
5751 ASET (last_show_tip_args
, 1, frame
);
5752 ASET (last_show_tip_args
, 2, parms
);
5754 /* Add default values to frame parameters. */
5755 if (NILP (Fassq (Qname
, parms
)))
5756 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
5757 if (NILP (Fassq (Qinternal_border_width
, parms
)))
5758 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
5759 if (NILP (Fassq (Qborder_width
, parms
)))
5760 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
5761 if (NILP (Fassq (Qborder_color
, parms
)))
5762 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
5763 if (NILP (Fassq (Qbackground_color
, parms
)))
5764 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
5767 /* Block input until the tip has been fully drawn, to avoid crashes
5768 when drawing tips in menus. */
5771 /* Create a frame for the tooltip, and record it in the global
5772 variable tip_frame. */
5773 frame
= x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f
), parms
, string
);
5776 /* Set up the frame's root window. */
5777 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
5778 wset_left_col (w
, make_number (0));
5779 wset_top_line (w
, make_number (0));
5781 if (CONSP (Vx_max_tooltip_size
)
5782 && INTEGERP (XCAR (Vx_max_tooltip_size
))
5783 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
5784 && INTEGERP (XCDR (Vx_max_tooltip_size
))
5785 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
5787 wset_total_cols (w
, XCAR (Vx_max_tooltip_size
));
5788 wset_total_lines (w
, XCDR (Vx_max_tooltip_size
));
5792 wset_total_cols (w
, make_number (80));
5793 wset_total_lines (w
, make_number (40));
5796 FRAME_TOTAL_COLS (f
) = XINT (w
->total_cols
);
5798 w
->pseudo_window_p
= 1;
5800 /* Display the tooltip text in a temporary buffer. */
5801 old_buffer
= current_buffer
;
5802 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
5803 bset_truncate_lines (current_buffer
, Qnil
);
5804 clear_glyph_matrix (w
->desired_matrix
);
5805 clear_glyph_matrix (w
->current_matrix
);
5806 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
5807 try_window (FRAME_ROOT_WINDOW (f
), pos
, TRY_WINDOW_IGNORE_FONTS_CHANGE
);
5809 /* Compute width and height of the tooltip. */
5810 width
= height
= seen_reversed_p
= 0;
5811 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
5813 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
5817 /* Stop at the first empty row at the end. */
5818 if (!row
->enabled_p
|| !row
->displays_text_p
)
5821 /* Let the row go over the full width of the frame. */
5822 row
->full_width_p
= 1;
5824 row_width
= row
->pixel_width
;
5825 if (row
->used
[TEXT_AREA
])
5827 if (!row
->reversed_p
)
5829 /* There's a glyph at the end of rows that is used to
5830 place the cursor there. Don't include the width of
5832 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
5833 if (INTEGERP (last
->object
))
5834 row_width
-= last
->pixel_width
;
5838 /* There could be a stretch glyph at the beginning of R2L
5839 rows that is produced by extend_face_to_end_of_line.
5840 Don't count that glyph. */
5841 struct glyph
*g
= row
->glyphs
[TEXT_AREA
];
5843 if (g
->type
== STRETCH_GLYPH
&& INTEGERP (g
->object
))
5845 row_width
-= g
->pixel_width
;
5846 seen_reversed_p
= 1;
5851 height
+= row
->height
;
5852 width
= max (width
, row_width
);
5855 /* If we've seen partial-length R2L rows, we need to re-adjust the
5856 tool-tip frame width and redisplay it again, to avoid over-wide
5857 tips due to the stretch glyph that extends R2L lines to full
5858 width of the frame. */
5859 if (seen_reversed_p
)
5861 /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
5863 width
/= WINDOW_FRAME_COLUMN_WIDTH (w
);
5864 wset_total_cols (w
, make_number (width
));
5865 FRAME_TOTAL_COLS (f
) = width
;
5867 w
->pseudo_window_p
= 1;
5868 clear_glyph_matrix (w
->desired_matrix
);
5869 clear_glyph_matrix (w
->current_matrix
);
5870 try_window (FRAME_ROOT_WINDOW (f
), pos
, TRY_WINDOW_IGNORE_FONTS_CHANGE
);
5872 /* Recompute width and height of the tooltip. */
5873 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
5875 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
5879 if (!row
->enabled_p
|| !row
->displays_text_p
)
5881 row
->full_width_p
= 1;
5882 row_width
= row
->pixel_width
;
5883 if (row
->used
[TEXT_AREA
] && !row
->reversed_p
)
5885 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
5886 if (INTEGERP (last
->object
))
5887 row_width
-= last
->pixel_width
;
5890 height
+= row
->height
;
5891 width
= max (width
, row_width
);
5895 /* Round up the height to an integral multiple of FRAME_LINE_HEIGHT. */
5896 if (height
% FRAME_LINE_HEIGHT (f
) != 0)
5897 height
+= FRAME_LINE_HEIGHT (f
) - height
% FRAME_LINE_HEIGHT (f
);
5898 /* Add the frame's internal border to the width and height the w32
5899 window should have. */
5900 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
5901 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
5903 /* Move the tooltip window where the mouse pointer is. Resize and
5905 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
5908 /* Adjust Window size to take border into account. */
5910 rect
.left
= rect
.top
= 0;
5912 rect
.bottom
= height
;
5913 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
5914 FRAME_EXTERNAL_MENU_BAR (f
));
5916 /* Position and size tooltip, and put it in the topmost group.
5917 The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a
5918 peculiarity of w32 display: without it, some fonts cause the
5919 last character of the tip to be truncated or wrapped around to
5921 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
5923 rect
.right
- rect
.left
+ FRAME_COLUMN_WIDTH (f
),
5924 rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
5926 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5927 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
5929 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5931 /* Let redisplay know that we have made the frame visible already. */
5932 f
->async_visible
= 1;
5934 ShowWindow (FRAME_W32_WINDOW (f
), SW_SHOWNOACTIVATE
);
5937 /* Draw into the window. */
5938 w
->must_be_updated_p
= 1;
5939 update_single_window (w
, 1);
5943 /* Restore original current buffer. */
5944 set_buffer_internal_1 (old_buffer
);
5945 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
5948 /* Let the tip disappear after timeout seconds. */
5949 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
5950 intern ("x-hide-tip"));
5953 return unbind_to (count
, Qnil
);
5957 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
5958 doc
: /* Hide the current tooltip window, if there is any.
5959 Value is t if tooltip was open, nil otherwise. */)
5963 Lisp_Object deleted
, frame
, timer
;
5964 struct gcpro gcpro1
, gcpro2
;
5966 /* Return quickly if nothing to do. */
5967 if (NILP (tip_timer
) && NILP (tip_frame
))
5972 GCPRO2 (frame
, timer
);
5973 tip_frame
= tip_timer
= deleted
= Qnil
;
5975 count
= SPECPDL_INDEX ();
5976 specbind (Qinhibit_redisplay
, Qt
);
5977 specbind (Qinhibit_quit
, Qt
);
5980 call1 (Qcancel_timer
, timer
);
5984 delete_frame (frame
, Qnil
);
5989 return unbind_to (count
, deleted
);
5992 /***********************************************************************
5993 File selection dialog
5994 ***********************************************************************/
5996 #define FILE_NAME_TEXT_FIELD edt1
5997 #define FILE_NAME_COMBO_BOX cmb13
5998 #define FILE_NAME_LIST lst1
6000 #ifdef NTGUI_UNICODE
6001 #define GUISTR(x) (L ## x)
6002 typedef wchar_t guichar_t
;
6003 #else /* !NTGUI_UNICODE */
6005 typedef char guichar_t
;
6006 #endif /* NTGUI_UNICODE */
6008 /* Callback for altering the behavior of the Open File dialog.
6009 Makes the Filename text field contain "Current Directory" and be
6010 read-only when "Directories" is selected in the filter. This
6011 allows us to work around the fact that the standard Open File
6012 dialog does not support directories. */
6013 static UINT CALLBACK
6014 file_dialog_callback (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
6016 if (msg
== WM_NOTIFY
)
6018 #ifdef NTGUI_UNICODE
6019 OFNOTIFYW
* notify
= (OFNOTIFYW
*)lParam
;
6020 #else /* !NTGUI_UNICODE */
6021 OFNOTIFYA
* notify
= (OFNOTIFYA
*)lParam
;
6022 #endif /* NTGUI_UNICODE */
6023 /* Detect when the Filter dropdown is changed. */
6024 if (notify
->hdr
.code
== CDN_TYPECHANGE
6025 || notify
->hdr
.code
== CDN_INITDONE
)
6027 HWND dialog
= GetParent (hwnd
);
6028 HWND edit_control
= GetDlgItem (dialog
, FILE_NAME_TEXT_FIELD
);
6029 HWND list
= GetDlgItem (dialog
, FILE_NAME_LIST
);
6031 /* At least on Windows 7, the above attempt to get the window handle
6032 to the File Name Text Field fails. The following code does the
6033 job though. Note that this code is based on my examination of the
6034 window hierarchy using Microsoft Spy++. bk */
6035 if (edit_control
== NULL
)
6037 HWND tmp
= GetDlgItem (dialog
, FILE_NAME_COMBO_BOX
);
6040 tmp
= GetWindow (tmp
, GW_CHILD
);
6042 edit_control
= GetWindow (tmp
, GW_CHILD
);
6046 /* Directories is in index 2. */
6047 if (notify
->lpOFN
->nFilterIndex
== 2)
6049 CommDlg_OpenSave_SetControlText (dialog
, FILE_NAME_TEXT_FIELD
,
6050 GUISTR ("Current Directory"));
6051 EnableWindow (edit_control
, FALSE
);
6052 /* Note that at least on Windows 7, the above call to EnableWindow
6053 disables the window that would ordinarily have focus. If we
6054 do not set focus to some other window here, focus will land in
6055 no man's land and the user will be unable to tab through the
6056 dialog box (pressing tab will only result in a beep).
6057 Avoid that problem by setting focus to the list here. */
6058 if (notify
->hdr
.code
== CDN_INITDONE
)
6063 /* Don't override default filename on init done. */
6064 if (notify
->hdr
.code
== CDN_TYPECHANGE
)
6065 CommDlg_OpenSave_SetControlText (dialog
,
6066 FILE_NAME_TEXT_FIELD
,
6068 EnableWindow (edit_control
, TRUE
);
6075 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 5, 0,
6076 doc
: /* Read file name, prompting with PROMPT in directory DIR.
6077 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6078 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6079 or directory must exist.
6081 This function is only defined on NS, MS Windows, and X Windows with the
6082 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6083 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
6084 (Lisp_Object prompt
, Lisp_Object dir
, Lisp_Object default_filename
, Lisp_Object mustmatch
, Lisp_Object only_dir_p
)
6086 /* Filter index: 1: All Files, 2: Directories only */
6087 static const guichar_t filter
[] =
6088 GUISTR ("All Files (*.*)\0*.*\0Directories\0*|*\0");
6090 Lisp_Object filename
= default_filename
;
6091 struct frame
*f
= SELECTED_FRAME ();
6092 BOOL file_opened
= FALSE
;
6093 Lisp_Object orig_dir
= dir
;
6094 Lisp_Object orig_prompt
= prompt
;
6096 /* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
6097 compatibility) we end up with the old file dialogs. Define a big
6098 enough struct for the new dialog to trick GetOpenFileName into
6099 giving us the new dialogs on newer versions of Windows. */
6101 #ifdef NTGUI_UNICODE
6102 OPENFILENAMEW details
;
6103 #else /* !NTGUI_UNICODE */
6104 OPENFILENAMEA details
;
6105 #endif /* NTGUI_UNICODE */
6107 #if _WIN32_WINNT < 0x500 /* < win2k */
6111 #endif /* < win2k */
6114 #ifdef NTGUI_UNICODE
6115 wchar_t filename_buf
[MAX_PATH
+ 1];
6116 OPENFILENAMEW
* file_details
= &new_file_details
.details
;
6117 #else /* not NTGUI_UNICODE */
6118 char filename_buf
[MAX_PATH
+ 1];
6119 OPENFILENAMEA
* file_details
= &new_file_details
.details
;
6120 #endif /* NTGUI_UNICODE */
6122 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
6123 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
, filename
);
6126 struct gcpro gcpro1
, gcpro2
;
6127 GCPRO2 (orig_dir
, orig_prompt
); /* There is no GCPRON, N>6. */
6129 /* Note: under NTGUI_UNICODE, we do _NOT_ use ENCODE_FILE: the
6130 system file encoding expected by the platform APIs (e.g. Cygwin's
6131 POSIX implementation) may not the same as the encoding expected
6132 by the Windows API! */
6134 CHECK_STRING (prompt
);
6137 dir
= Fexpand_file_name (dir
, Qnil
);
6139 if (STRINGP (filename
))
6140 filename
= Ffile_name_nondirectory (filename
);
6142 filename
= empty_unibyte_string
;
6145 dir
= Fcygwin_convert_path_to_windows (dir
, Qt
);
6146 if (SCHARS (filename
) > 0)
6147 filename
= Fcygwin_convert_path_to_windows (filename
, Qnil
);
6151 CHECK_STRING (filename
);
6153 /* The code in file_dialog_callback that attempts to set the text
6154 of the file name edit window when handling the CDN_INITDONE
6155 WM_NOTIFY message does not work. Setting filename to "Current
6156 Directory" in the only_dir_p case here does work however. */
6157 if (SCHARS (filename
) == 0 && ! NILP (only_dir_p
))
6158 filename
= build_string ("Current Directory");
6160 /* Convert the values we've computed so far to system form. */
6161 #ifdef NTGUI_UNICODE
6162 to_unicode (prompt
, &prompt
);
6163 to_unicode (dir
, &dir
);
6164 to_unicode (filename
, &filename
);
6165 #else /* !NTGUI_UNICODE */
6166 prompt
= ENCODE_FILE (prompt
);
6167 dir
= ENCODE_FILE (dir
);
6168 filename
= ENCODE_FILE (filename
);
6170 /* We modify these in-place, so make copies for safety. */
6171 dir
= Fcopy_sequence (dir
);
6172 unixtodos_filename (SDATA (dir
));
6173 filename
= Fcopy_sequence (filename
);
6174 unixtodos_filename (SDATA (filename
));
6175 #endif /* NTGUI_UNICODE */
6177 /* Fill in the structure for the call to GetOpenFileName below. For
6178 NTGUI_UNICODE builds (which run only on NT), we just use the
6179 actual size of the structure. For non-NTGUI_UNICODE builds, we
6180 tell the OS we're using an old version of the structure if it's not
6181 new enough to support the newer version. */
6182 memset (&new_file_details
, 0, sizeof (new_file_details
));
6184 if (w32_major_version
> 4 && w32_major_version
< 95)
6185 file_details
->lStructSize
= sizeof (new_file_details
);
6187 file_details
->lStructSize
= sizeof (*file_details
);
6189 /* Set up the inout parameter for the selected file name. */
6190 if (SBYTES (filename
) + 1 > sizeof (filename_buf
))
6191 error ("filename too long");
6193 memcpy (filename_buf
, SDATA (filename
), SBYTES (filename
) + 1);
6194 file_details
->lpstrFile
= filename_buf
;
6195 file_details
->nMaxFile
= sizeof (filename_buf
) / sizeof (*filename_buf
);
6197 file_details
->hwndOwner
= FRAME_W32_WINDOW (f
);
6198 /* Undocumented Bug in Common File Dialog:
6199 If a filter is not specified, shell links are not resolved. */
6200 file_details
->lpstrFilter
= filter
;
6201 file_details
->lpstrInitialDir
= (guichar_t
*) SDATA (dir
);
6202 file_details
->lpstrTitle
= (guichar_t
*) SDATA (prompt
);
6203 file_details
->nFilterIndex
= NILP (only_dir_p
) ? 1 : 2;
6204 file_details
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
6205 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
6207 if (!NILP (mustmatch
))
6209 /* Require that the path to the parent directory exists. */
6210 file_details
->Flags
|= OFN_PATHMUSTEXIST
;
6211 /* If we are looking for a file, require that it exists. */
6212 if (NILP (only_dir_p
))
6213 file_details
->Flags
|= OFN_FILEMUSTEXIST
;
6217 int count
= SPECPDL_INDEX ();
6218 specbind (Qinhibit_redisplay
, Qt
);
6220 file_details
->lpfnHook
= file_dialog_callback
;
6222 #ifdef NTGUI_UNICODE
6223 file_opened
= GetOpenFileNameW (file_details
);
6224 #else /* !NTGUI_UNICODE */
6225 file_opened
= GetOpenFileNameA (file_details
);
6226 #endif /* NTGUI_UNICODE */
6228 unbind_to (count
, Qnil
);
6233 /* Get an Emacs string from the value Windows gave us. */
6234 #ifdef NTGUI_UNICODE
6235 filename
= from_unicode (
6236 make_unibyte_string (
6237 (char*) filename_buf
,
6238 /* we get one of the two final 0 bytes for free. */
6239 1 + sizeof (wchar_t) * wcslen (filename_buf
)));
6240 #else /* !NTGUI_UNICODE */
6241 dostounix_filename (filename_buf
);
6242 filename
= DECODE_FILE (build_string (filename_buf
));
6243 #endif /* NTGUI_UNICODE */
6246 filename
= Fcygwin_convert_path_from_windows (filename
, Qt
);
6249 /* Strip the dummy filename off the end of the string if we
6250 added it to select a directory. */
6251 if (file_details
->nFilterIndex
== 2)
6253 filename
= Ffile_name_directory (filename
);
6256 /* User canceled the dialog without making a selection. */
6257 else if (!CommDlgExtendedError ())
6259 /* An error occurred, fallback on reading from the mini-buffer. */
6261 filename
= Fcompleting_read (
6263 intern ("read-file-name-internal"),
6274 /* Make "Cancel" equivalent to C-g. */
6275 if (NILP (filename
))
6276 Fsignal (Qquit
, Qnil
);
6278 RETURN_UNGCPRO (filename
);
6283 /* Moving files to the system recycle bin.
6284 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
6285 DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash
,
6286 Ssystem_move_file_to_trash
, 1, 1, 0,
6287 doc
: /* Move file or directory named FILENAME to the recycle bin. */)
6288 (Lisp_Object filename
)
6290 Lisp_Object handler
;
6291 Lisp_Object encoded_file
;
6292 Lisp_Object operation
;
6294 operation
= Qdelete_file
;
6295 if (!NILP (Ffile_directory_p (filename
))
6296 && NILP (Ffile_symlink_p (filename
)))
6298 operation
= intern ("delete-directory");
6299 filename
= Fdirectory_file_name (filename
);
6301 filename
= Fexpand_file_name (filename
, Qnil
);
6303 handler
= Ffind_file_name_handler (filename
, operation
);
6304 if (!NILP (handler
))
6305 return call2 (handler
, operation
, filename
);
6307 encoded_file
= ENCODE_FILE (filename
);
6311 SHFILEOPSTRUCT file_op
;
6312 char tmp_path
[MAX_PATH
+ 1];
6314 path
= map_w32_filename (SDATA (encoded_file
), NULL
);
6316 /* On Windows, write permission is required to delete/move files. */
6317 _chmod (path
, 0666);
6319 memset (tmp_path
, 0, sizeof (tmp_path
));
6320 strcpy (tmp_path
, path
);
6322 memset (&file_op
, 0, sizeof (file_op
));
6323 file_op
.hwnd
= HWND_DESKTOP
;
6324 file_op
.wFunc
= FO_DELETE
;
6325 file_op
.pFrom
= tmp_path
;
6326 file_op
.fFlags
= FOF_SILENT
| FOF_NOCONFIRMATION
| FOF_ALLOWUNDO
6327 | FOF_NOERRORUI
| FOF_NO_CONNECTED_ELEMENTS
;
6328 file_op
.fAnyOperationsAborted
= FALSE
;
6330 if (SHFileOperation (&file_op
) != 0)
6331 report_file_error ("Removing old name", list1 (filename
));
6336 #endif /* WINDOWSNT */
6339 /***********************************************************************
6340 w32 specialized functions
6341 ***********************************************************************/
6343 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
,
6344 Sw32_send_sys_command
, 1, 2, 0,
6345 doc
: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
6346 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
6347 to minimize), #xf120 to restore frame to original size, and #xf100
6348 to activate the menubar for keyboard access. #xf140 activates the
6349 screen saver if defined.
6351 If optional parameter FRAME is not specified, use selected frame. */)
6352 (Lisp_Object command
, Lisp_Object frame
)
6354 FRAME_PTR f
= check_x_frame (frame
);
6356 CHECK_NUMBER (command
);
6358 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
6363 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
6364 doc
: /* Get Windows to perform OPERATION on DOCUMENT.
6365 This is a wrapper around the ShellExecute system function, which
6366 invokes the application registered to handle OPERATION for DOCUMENT.
6368 OPERATION is either nil or a string that names a supported operation.
6369 What operations can be used depends on the particular DOCUMENT and its
6370 handler application, but typically it is one of the following common
6373 \"open\" - open DOCUMENT, which could be a file, a directory, or an
6374 executable program. If it is an application, that
6375 application is launched in the current buffer's default
6376 directory. Otherwise, the application associated with
6377 DOCUMENT is launched in the buffer's default directory.
6378 \"print\" - print DOCUMENT, which must be a file
6379 \"explore\" - start the Windows Explorer on DOCUMENT
6380 \"edit\" - launch an editor and open DOCUMENT for editing; which
6381 editor is launched depends on the association for the
6383 \"find\" - initiate search starting from DOCUMENT which must specify
6385 nil - invoke the default OPERATION, or \"open\" if default is
6386 not defined or unavailable
6388 DOCUMENT is typically the name of a document file or a URL, but can
6389 also be a program executable to run, or a directory to open in the
6392 If DOCUMENT is a program executable, the optional third arg PARAMETERS
6393 can be a string containing command line parameters that will be passed
6394 to the program; otherwise, PARAMETERS should be nil or unspecified.
6396 Optional fourth argument SHOW-FLAG can be used to control how the
6397 application will be displayed when it is invoked. If SHOW-FLAG is nil
6398 or unspecified, the application is displayed normally, otherwise it is
6399 an integer representing a ShowWindow flag:
6404 6 - start minimized */)
6405 (Lisp_Object operation
, Lisp_Object document
, Lisp_Object parameters
, Lisp_Object show_flag
)
6407 Lisp_Object current_dir
;
6410 CHECK_STRING (document
);
6412 /* Encode filename, current directory and parameters. */
6413 current_dir
= ENCODE_FILE (BVAR (current_buffer
, directory
));
6414 document
= ENCODE_FILE (document
);
6415 if (STRINGP (parameters
))
6416 parameters
= ENCODE_SYSTEM (parameters
);
6418 if ((int) ShellExecute (NULL
,
6419 (STRINGP (operation
) ?
6420 SDATA (operation
) : NULL
),
6422 (STRINGP (parameters
) ?
6423 SDATA (parameters
) : NULL
),
6424 SDATA (current_dir
),
6425 (INTEGERP (show_flag
) ?
6426 XINT (show_flag
) : SW_SHOWDEFAULT
))
6429 errstr
= w32_strerror (0);
6430 /* The error string might be encoded in the locale's encoding. */
6431 if (!NILP (Vlocale_coding_system
))
6433 Lisp_Object decoded
=
6434 code_convert_string_norecord (build_unibyte_string (errstr
),
6435 Vlocale_coding_system
, 0);
6436 errstr
= SSDATA (decoded
);
6438 error ("ShellExecute failed: %s", errstr
);
6441 /* Lookup virtual keycode from string representing the name of a
6442 non-ascii keystroke into the corresponding virtual key, using
6443 lispy_function_keys. */
6445 lookup_vk_code (char *key
)
6449 for (i
= 0; i
< 256; i
++)
6450 if (lispy_function_keys
[i
]
6451 && strcmp (lispy_function_keys
[i
], key
) == 0)
6457 /* Convert a one-element vector style key sequence to a hot key
6460 w32_parse_hot_key (Lisp_Object key
)
6462 /* Copied from Fdefine_key and store_in_keymap. */
6463 register Lisp_Object c
;
6467 struct gcpro gcpro1
;
6471 if (XFASTINT (Flength (key
)) != 1)
6476 c
= Faref (key
, make_number (0));
6478 if (CONSP (c
) && lucid_event_type_list_p (c
))
6479 c
= Fevent_convert_list (c
);
6483 if (! INTEGERP (c
) && ! SYMBOLP (c
))
6484 error ("Key definition is invalid");
6486 /* Work out the base key and the modifiers. */
6489 c
= parse_modifiers (c
);
6490 lisp_modifiers
= XINT (Fcar (Fcdr (c
)));
6494 vk_code
= lookup_vk_code (SDATA (SYMBOL_NAME (c
)));
6496 else if (INTEGERP (c
))
6498 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
6499 /* Many ascii characters are their own virtual key code. */
6500 vk_code
= XINT (c
) & CHARACTERBITS
;
6503 if (vk_code
< 0 || vk_code
> 255)
6506 if ((lisp_modifiers
& meta_modifier
) != 0
6507 && !NILP (Vw32_alt_is_meta
))
6508 lisp_modifiers
|= alt_modifier
;
6510 /* Supply defs missing from mingw32. */
6512 #define MOD_ALT 0x0001
6513 #define MOD_CONTROL 0x0002
6514 #define MOD_SHIFT 0x0004
6515 #define MOD_WIN 0x0008
6518 /* Convert lisp modifiers to Windows hot-key form. */
6519 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
6520 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
6521 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
6522 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
6524 return HOTKEY (vk_code
, w32_modifiers
);
6527 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
,
6528 Sw32_register_hot_key
, 1, 1, 0,
6529 doc
: /* Register KEY as a hot-key combination.
6530 Certain key combinations like Alt-Tab are reserved for system use on
6531 Windows, and therefore are normally intercepted by the system. However,
6532 most of these key combinations can be received by registering them as
6533 hot-keys, overriding their special meaning.
6535 KEY must be a one element key definition in vector form that would be
6536 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
6537 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
6538 is always interpreted as the Windows modifier keys.
6540 The return value is the hotkey-id if registered, otherwise nil. */)
6543 key
= w32_parse_hot_key (key
);
6545 if (!NILP (key
) && NILP (Fmemq (key
, w32_grabbed_keys
)))
6547 /* Reuse an empty slot if possible. */
6548 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
6550 /* Safe to add new key to list, even if we have focus. */
6552 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
6554 XSETCAR (item
, key
);
6556 /* Notify input thread about new hot-key definition, so that it
6557 takes effect without needing to switch focus. */
6558 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
6559 (WPARAM
) XLI (key
), 0);
6565 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
,
6566 Sw32_unregister_hot_key
, 1, 1, 0,
6567 doc
: /* Unregister KEY as a hot-key combination. */)
6572 if (!INTEGERP (key
))
6573 key
= w32_parse_hot_key (key
);
6575 item
= Fmemq (key
, w32_grabbed_keys
);
6579 /* Notify input thread about hot-key definition being removed, so
6580 that it takes effect without needing focus switch. */
6581 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
6582 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) XLI (item
)))
6585 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6592 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
,
6593 Sw32_registered_hot_keys
, 0, 0, 0,
6594 doc
: /* Return list of registered hot-key IDs. */)
6597 return Fdelq (Qnil
, Fcopy_sequence (w32_grabbed_keys
));
6600 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
,
6601 Sw32_reconstruct_hot_key
, 1, 1, 0,
6602 doc
: /* Convert hot-key ID to a lisp key combination.
6603 usage: (w32-reconstruct-hot-key ID) */)
6604 (Lisp_Object hotkeyid
)
6606 int vk_code
, w32_modifiers
;
6609 CHECK_NUMBER (hotkeyid
);
6611 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
6612 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
6614 if (vk_code
< 256 && lispy_function_keys
[vk_code
])
6615 key
= intern (lispy_function_keys
[vk_code
]);
6617 key
= make_number (vk_code
);
6619 key
= Fcons (key
, Qnil
);
6620 if (w32_modifiers
& MOD_SHIFT
)
6621 key
= Fcons (Qshift
, key
);
6622 if (w32_modifiers
& MOD_CONTROL
)
6623 key
= Fcons (Qctrl
, key
);
6624 if (w32_modifiers
& MOD_ALT
)
6625 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
6626 if (w32_modifiers
& MOD_WIN
)
6627 key
= Fcons (Qhyper
, key
);
6632 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
,
6633 Sw32_toggle_lock_key
, 1, 2, 0,
6634 doc
: /* Toggle the state of the lock key KEY.
6635 KEY can be `capslock', `kp-numlock', or `scroll'.
6636 If the optional parameter NEW-STATE is a number, then the state of KEY
6637 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
6638 (Lisp_Object key
, Lisp_Object new_state
)
6642 if (EQ (key
, intern ("capslock")))
6643 vk_code
= VK_CAPITAL
;
6644 else if (EQ (key
, intern ("kp-numlock")))
6645 vk_code
= VK_NUMLOCK
;
6646 else if (EQ (key
, intern ("scroll")))
6647 vk_code
= VK_SCROLL
;
6651 if (!dwWindowsThreadId
)
6652 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
6654 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
6655 (WPARAM
) vk_code
, (LPARAM
) XLI (new_state
)))
6658 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6659 return make_number (msg
.wParam
);
6664 DEFUN ("w32-window-exists-p", Fw32_window_exists_p
, Sw32_window_exists_p
,
6666 doc
: /* Return non-nil if a window exists with the specified CLASS and NAME.
6668 This is a direct interface to the Windows API FindWindow function. */)
6669 (Lisp_Object
class, Lisp_Object name
)
6674 CHECK_STRING (class);
6676 CHECK_STRING (name
);
6678 hnd
= FindWindow (STRINGP (class) ? ((LPCTSTR
) SDATA (class)) : NULL
,
6679 STRINGP (name
) ? ((LPCTSTR
) SDATA (name
)) : NULL
);
6685 DEFUN ("w32-battery-status", Fw32_battery_status
, Sw32_battery_status
, 0, 0, 0,
6686 doc
: /* Get power status information from Windows system.
6688 The following %-sequences are provided:
6689 %L AC line status (verbose)
6690 %B Battery status (verbose)
6691 %b Battery status, empty means high, `-' means low,
6692 `!' means critical, and `+' means charging
6693 %p Battery load percentage
6694 %s Remaining time (to charge or discharge) in seconds
6695 %m Remaining time (to charge or discharge) in minutes
6696 %h Remaining time (to charge or discharge) in hours
6697 %t Remaining time (to charge or discharge) in the form `h:min' */)
6700 Lisp_Object status
= Qnil
;
6702 SYSTEM_POWER_STATUS system_status
;
6703 if (GetSystemPowerStatus (&system_status
))
6705 Lisp_Object line_status
, battery_status
, battery_status_symbol
;
6706 Lisp_Object load_percentage
, seconds
, minutes
, hours
, remain
;
6708 long seconds_left
= (long) system_status
.BatteryLifeTime
;
6710 if (system_status
.ACLineStatus
== 0)
6711 line_status
= build_string ("off-line");
6712 else if (system_status
.ACLineStatus
== 1)
6713 line_status
= build_string ("on-line");
6715 line_status
= build_string ("N/A");
6717 if (system_status
.BatteryFlag
& 128)
6719 battery_status
= build_string ("N/A");
6720 battery_status_symbol
= empty_unibyte_string
;
6722 else if (system_status
.BatteryFlag
& 8)
6724 battery_status
= build_string ("charging");
6725 battery_status_symbol
= build_string ("+");
6726 if (system_status
.BatteryFullLifeTime
!= -1L)
6727 seconds_left
= system_status
.BatteryFullLifeTime
- seconds_left
;
6729 else if (system_status
.BatteryFlag
& 4)
6731 battery_status
= build_string ("critical");
6732 battery_status_symbol
= build_string ("!");
6734 else if (system_status
.BatteryFlag
& 2)
6736 battery_status
= build_string ("low");
6737 battery_status_symbol
= build_string ("-");
6739 else if (system_status
.BatteryFlag
& 1)
6741 battery_status
= build_string ("high");
6742 battery_status_symbol
= empty_unibyte_string
;
6746 battery_status
= build_string ("medium");
6747 battery_status_symbol
= empty_unibyte_string
;
6750 if (system_status
.BatteryLifePercent
> 100)
6751 load_percentage
= build_string ("N/A");
6755 snprintf (buffer
, 16, "%d", system_status
.BatteryLifePercent
);
6756 load_percentage
= build_string (buffer
);
6759 if (seconds_left
< 0)
6760 seconds
= minutes
= hours
= remain
= build_string ("N/A");
6766 snprintf (buffer
, 16, "%ld", seconds_left
);
6767 seconds
= build_string (buffer
);
6769 m
= seconds_left
/ 60;
6770 snprintf (buffer
, 16, "%ld", m
);
6771 minutes
= build_string (buffer
);
6773 h
= seconds_left
/ 3600.0;
6774 snprintf (buffer
, 16, "%3.1f", h
);
6775 hours
= build_string (buffer
);
6777 snprintf (buffer
, 16, "%ld:%02ld", m
/ 60, m
% 60);
6778 remain
= build_string (buffer
);
6781 status
= listn (CONSTYPE_HEAP
, 8,
6782 Fcons (make_number ('L'), line_status
),
6783 Fcons (make_number ('B'), battery_status
),
6784 Fcons (make_number ('b'), battery_status_symbol
),
6785 Fcons (make_number ('p'), load_percentage
),
6786 Fcons (make_number ('s'), seconds
),
6787 Fcons (make_number ('m'), minutes
),
6788 Fcons (make_number ('h'), hours
),
6789 Fcons (make_number ('t'), remain
));
6795 DEFUN ("file-system-info", Ffile_system_info
, Sfile_system_info
, 1, 1, 0,
6796 doc
: /* Return storage information about the file system FILENAME is on.
6797 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
6798 storage of the file system, FREE is the free storage, and AVAIL is the
6799 storage available to a non-superuser. All 3 numbers are in bytes.
6800 If the underlying system call fails, value is nil. */)
6801 (Lisp_Object filename
)
6803 Lisp_Object encoded
, value
;
6805 CHECK_STRING (filename
);
6806 filename
= Fexpand_file_name (filename
, Qnil
);
6807 encoded
= ENCODE_FILE (filename
);
6811 /* Determining the required information on Windows turns out, sadly,
6812 to be more involved than one would hope. The original Windows API
6813 call for this will return bogus information on some systems, but we
6814 must dynamically probe for the replacement api, since that was
6815 added rather late on. */
6817 HMODULE hKernel
= GetModuleHandle ("kernel32");
6818 BOOL (*pfn_GetDiskFreeSpaceEx
)
6819 (char *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
6820 = (void *) GetProcAddress (hKernel
, "GetDiskFreeSpaceEx");
6822 /* On Windows, we may need to specify the root directory of the
6823 volume holding FILENAME. */
6824 char rootname
[MAX_PATH
];
6825 char *name
= SDATA (encoded
);
6827 /* find the root name of the volume if given */
6828 if (isalpha (name
[0]) && name
[1] == ':')
6830 rootname
[0] = name
[0];
6831 rootname
[1] = name
[1];
6835 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
6837 char *str
= rootname
;
6841 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
6851 if (pfn_GetDiskFreeSpaceEx
)
6853 /* Unsigned large integers cannot be cast to double, so
6854 use signed ones instead. */
6855 LARGE_INTEGER availbytes
;
6856 LARGE_INTEGER freebytes
;
6857 LARGE_INTEGER totalbytes
;
6859 if (pfn_GetDiskFreeSpaceEx (rootname
,
6860 (ULARGE_INTEGER
*)&availbytes
,
6861 (ULARGE_INTEGER
*)&totalbytes
,
6862 (ULARGE_INTEGER
*)&freebytes
))
6863 value
= list3 (make_float ((double) totalbytes
.QuadPart
),
6864 make_float ((double) freebytes
.QuadPart
),
6865 make_float ((double) availbytes
.QuadPart
));
6869 DWORD sectors_per_cluster
;
6870 DWORD bytes_per_sector
;
6871 DWORD free_clusters
;
6872 DWORD total_clusters
;
6874 if (GetDiskFreeSpace (rootname
,
6875 §ors_per_cluster
,
6879 value
= list3 (make_float ((double) total_clusters
6880 * sectors_per_cluster
* bytes_per_sector
),
6881 make_float ((double) free_clusters
6882 * sectors_per_cluster
* bytes_per_sector
),
6883 make_float ((double) free_clusters
6884 * sectors_per_cluster
* bytes_per_sector
));
6891 DEFUN ("default-printer-name", Fdefault_printer_name
, Sdefault_printer_name
,
6892 0, 0, 0, doc
: /* Return the name of Windows default printer device. */)
6895 static char pname_buf
[256];
6898 PRINTER_INFO_2
*ppi2
= NULL
;
6899 DWORD dwNeeded
= 0, dwReturned
= 0;
6901 /* Retrieve the default string from Win.ini (the registry).
6902 * String will be in form "printername,drivername,portname".
6903 * This is the most portable way to get the default printer. */
6904 if (GetProfileString ("windows", "device", ",,", pname_buf
, sizeof (pname_buf
)) <= 0)
6906 /* printername precedes first "," character */
6907 strtok (pname_buf
, ",");
6908 /* We want to know more than the printer name */
6909 if (!OpenPrinter (pname_buf
, &hPrn
, NULL
))
6911 GetPrinter (hPrn
, 2, NULL
, 0, &dwNeeded
);
6914 ClosePrinter (hPrn
);
6917 /* Allocate memory for the PRINTER_INFO_2 struct */
6918 ppi2
= xmalloc (dwNeeded
);
6921 ClosePrinter (hPrn
);
6924 /* Call GetPrinter again with big enough memory block. */
6925 err
= GetPrinter (hPrn
, 2, (LPBYTE
)ppi2
, dwNeeded
, &dwReturned
);
6926 ClosePrinter (hPrn
);
6935 if (ppi2
->Attributes
& PRINTER_ATTRIBUTE_SHARED
&& ppi2
->pServerName
)
6937 /* a remote printer */
6938 if (*ppi2
->pServerName
== '\\')
6939 snprintf (pname_buf
, sizeof (pname_buf
), "%s\\%s", ppi2
->pServerName
,
6942 snprintf (pname_buf
, sizeof (pname_buf
), "\\\\%s\\%s", ppi2
->pServerName
,
6944 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
6948 /* a local printer */
6949 strncpy (pname_buf
, ppi2
->pPortName
, sizeof (pname_buf
));
6950 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
6951 /* `pPortName' can include several ports, delimited by ','.
6952 * we only use the first one. */
6953 strtok (pname_buf
, ",");
6958 return build_string (pname_buf
);
6962 /* Equivalent of strerror for W32 error codes. */
6964 w32_strerror (int error_no
)
6966 static char buf
[500];
6970 error_no
= GetLastError ();
6972 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
6973 FORMAT_MESSAGE_IGNORE_INSERTS
,
6976 0, /* choose most suitable language */
6977 buf
, sizeof (buf
), NULL
);
6979 while (ret
> 0 && (buf
[ret
- 1] == '\n' ||
6980 buf
[ret
- 1] == '\r' ))
6984 sprintf (buf
, "w32 error %u", error_no
);
6989 /* For convenience when debugging. */
6991 w32_last_error (void)
6993 return GetLastError ();
6996 /* Cache information describing the NT system for later use. */
6998 cache_system_info (void)
7011 /* Cache the version of the operating system. */
7012 version
.data
= GetVersion ();
7013 w32_major_version
= version
.info
.major
;
7014 w32_minor_version
= version
.info
.minor
;
7016 if (version
.info
.platform
& 0x8000)
7021 /* Cache page size, allocation unit, processor type, etc. */
7022 GetSystemInfo (&sysinfo_cache
);
7023 syspage_mask
= sysinfo_cache
.dwPageSize
- 1;
7025 /* Cache os info. */
7026 osinfo_cache
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
7027 GetVersionEx (&osinfo_cache
);
7029 w32_build_number
= osinfo_cache
.dwBuildNumber
;
7030 if (os_subtype
== OS_9X
)
7031 w32_build_number
&= 0xffff;
7033 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
7038 _DebPrint (const char *fmt
, ...)
7043 va_start (args
, fmt
);
7044 vsprintf (buf
, fmt
, args
);
7047 fprintf (stderr
, "%s", buf
);
7049 OutputDebugString (buf
);
7054 w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
)
7056 int cur_state
= (GetKeyState (vk_code
) & 1);
7058 if (NILP (new_state
)
7059 || (NUMBERP (new_state
)
7060 && ((XUINT (new_state
)) & 1) != cur_state
))
7063 faked_key
= vk_code
;
7064 #endif /* WINDOWSNT */
7066 keybd_event ((BYTE
) vk_code
,
7067 (BYTE
) MapVirtualKey (vk_code
, 0),
7068 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
7069 keybd_event ((BYTE
) vk_code
,
7070 (BYTE
) MapVirtualKey (vk_code
, 0),
7071 KEYEVENTF_EXTENDEDKEY
| 0, 0);
7072 keybd_event ((BYTE
) vk_code
,
7073 (BYTE
) MapVirtualKey (vk_code
, 0),
7074 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
7075 cur_state
= !cur_state
;
7081 /* Translate console modifiers to emacs modifiers.
7082 German keyboard support (Kai Morgan Zeise 2/18/95). */
7084 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
7088 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
7089 pressed, first remove those modifiers. */
7090 if (!NILP (Vw32_recognize_altgr
)
7091 && (mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
7092 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
7093 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
7095 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
7096 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
7098 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
7100 retval
|= ctrl_modifier
;
7101 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
7102 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
7103 retval
|= meta_modifier
;
7106 if (mods
& LEFT_WIN_PRESSED
)
7107 retval
|= w32_key_to_modifier (VK_LWIN
);
7108 if (mods
& RIGHT_WIN_PRESSED
)
7109 retval
|= w32_key_to_modifier (VK_RWIN
);
7110 if (mods
& APPS_PRESSED
)
7111 retval
|= w32_key_to_modifier (VK_APPS
);
7112 if (mods
& SCROLLLOCK_ON
)
7113 retval
|= w32_key_to_modifier (VK_SCROLL
);
7115 /* Just in case someone wanted the original behavior, make it
7116 optional by setting w32-capslock-is-shiftlock to t. */
7117 if (NILP (Vw32_capslock_is_shiftlock
)
7118 /* Keys that should _not_ be affected by CapsLock. */
7119 && ( (key
== VK_BACK
)
7121 || (key
== VK_CLEAR
)
7122 || (key
== VK_RETURN
)
7123 || (key
== VK_ESCAPE
)
7124 || ((key
>= VK_SPACE
) && (key
<= VK_HELP
))
7125 || ((key
>= VK_NUMPAD0
) && (key
<= VK_F24
))
7126 || ((key
>= VK_NUMPAD_CLEAR
) && (key
<= VK_NUMPAD_DELETE
))
7129 /* Only consider shift state. */
7130 if ((mods
& SHIFT_PRESSED
) != 0)
7131 retval
|= shift_modifier
;
7135 /* Ignore CapsLock state if not enabled. */
7136 if (NILP (Vw32_enable_caps_lock
))
7137 mods
&= ~CAPSLOCK_ON
;
7138 if ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) != 0)
7139 retval
|= shift_modifier
;
7145 /* The return code indicates key code size. cpID is the codepage to
7146 use for translation to Unicode; -1 means use the current console
7149 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
, int cpId
)
7151 unsigned int key_code
= event
->wVirtualKeyCode
;
7152 unsigned int mods
= event
->dwControlKeyState
;
7154 static BYTE ansi_code
[4];
7155 static int isdead
= 0;
7159 event
->uChar
.AsciiChar
= ansi_code
[2];
7163 if (event
->uChar
.AsciiChar
!= 0)
7166 memset (keystate
, 0, sizeof (keystate
));
7167 keystate
[key_code
] = 0x80;
7168 if (mods
& SHIFT_PRESSED
)
7169 keystate
[VK_SHIFT
] = 0x80;
7170 if (mods
& CAPSLOCK_ON
)
7171 keystate
[VK_CAPITAL
] = 1;
7172 /* If we recognize right-alt and left-ctrl as AltGr, set the key
7173 states accordingly before invoking ToAscii. */
7174 if (!NILP (Vw32_recognize_altgr
)
7175 && (mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
7177 keystate
[VK_CONTROL
] = 0x80;
7178 keystate
[VK_LCONTROL
] = 0x80;
7179 keystate
[VK_MENU
] = 0x80;
7180 keystate
[VK_RMENU
] = 0x80;
7184 /* Because of an OS bug, ToAscii corrupts the stack when called to
7185 convert a dead key in console mode on NT4. Unfortunately, trying
7186 to check for dead keys using MapVirtualKey doesn't work either -
7187 these functions apparently use internal information about keyboard
7188 layout which doesn't get properly updated in console programs when
7189 changing layout (though apparently it gets partly updated,
7190 otherwise ToAscii wouldn't crash). */
7191 if (is_dead_key (event
->wVirtualKeyCode
))
7195 /* On NT, call ToUnicode instead and then convert to the current
7196 console input codepage. */
7197 if (os_subtype
== OS_NT
)
7201 isdead
= ToUnicode (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
7202 keystate
, buf
, 128, 0);
7205 /* When we are called from the GUI message processing code,
7206 we are passed the current keyboard codepage, a positive
7207 number, to use below. */
7209 cpId
= GetConsoleCP ();
7211 event
->uChar
.UnicodeChar
= buf
[isdead
- 1];
7212 isdead
= WideCharToMultiByte (cpId
, 0, buf
, isdead
,
7213 ansi_code
, 4, NULL
, NULL
);
7220 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
7221 keystate
, (LPWORD
) ansi_code
, 0);
7226 event
->uChar
.AsciiChar
= ansi_code
[0];
7232 w32_sys_ring_bell (struct frame
*f
)
7234 if (sound_type
== 0xFFFFFFFF)
7238 else if (sound_type
== MB_EMACS_SILENT
)
7243 MessageBeep (sound_type
);
7247 /***********************************************************************
7249 ***********************************************************************/
7251 /* Keep this list in the same order as frame_parms in frame.c.
7252 Use 0 for unsupported frame parameters. */
7254 frame_parm_handler w32_frame_parm_handlers
[] =
7258 x_set_background_color
,
7264 x_set_foreground_color
,
7267 x_set_internal_border_width
,
7268 x_set_menu_bar_lines
,
7270 x_explicitly_set_name
,
7271 x_set_scroll_bar_width
,
7274 x_set_vertical_scroll_bars
,
7276 x_set_tool_bar_lines
,
7277 0, /* x_set_scroll_bar_foreground, */
7278 0, /* x_set_scroll_bar_background, */
7283 0, /* x_set_wait_for_wm, */
7287 0, /* x_set_sticky */
7288 0, /* x_set_tool_bar_position */
7292 syms_of_w32fns (void)
7294 globals_of_w32fns ();
7295 /* This is zero if not using MS-Windows. */
7297 track_mouse_window
= NULL
;
7299 w32_visible_system_caret_hwnd
= NULL
;
7301 DEFSYM (Qsuppress_icon
, "suppress-icon");
7302 DEFSYM (Qundefined_color
, "undefined-color");
7303 DEFSYM (Qcancel_timer
, "cancel-timer");
7304 DEFSYM (Qhyper
, "hyper");
7305 DEFSYM (Qsuper
, "super");
7306 DEFSYM (Qmeta
, "meta");
7307 DEFSYM (Qalt
, "alt");
7308 DEFSYM (Qctrl
, "ctrl");
7309 DEFSYM (Qcontrol
, "control");
7310 DEFSYM (Qshift
, "shift");
7311 DEFSYM (Qfont_param
, "font-parameter");
7312 /* This is the end of symbol initialization. */
7315 Fput (Qundefined_color
, Qerror_conditions
,
7316 listn (CONSTYPE_PURE
, 2, Qundefined_color
, Qerror
));
7317 Fput (Qundefined_color
, Qerror_message
,
7318 build_pure_c_string ("Undefined color"));
7320 staticpro (&w32_grabbed_keys
);
7321 w32_grabbed_keys
= Qnil
;
7323 DEFVAR_LISP ("w32-color-map", Vw32_color_map
,
7324 doc
: /* An array of color name mappings for Windows. */);
7325 Vw32_color_map
= Qnil
;
7327 DEFVAR_LISP ("w32-pass-alt-to-system", Vw32_pass_alt_to_system
,
7328 doc
: /* Non-nil if Alt key presses are passed on to Windows.
7329 When non-nil, for example, Alt pressed and released and then space will
7330 open the System menu. When nil, Emacs processes the Alt key events, and
7331 then silently swallows them. */);
7332 Vw32_pass_alt_to_system
= Qnil
;
7334 DEFVAR_LISP ("w32-alt-is-meta", Vw32_alt_is_meta
,
7335 doc
: /* Non-nil if the Alt key is to be considered the same as the META key.
7336 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
7337 Vw32_alt_is_meta
= Qt
;
7339 DEFVAR_INT ("w32-quit-key", w32_quit_key
,
7340 doc
: /* If non-zero, the virtual key code for an alternative quit key. */);
7343 DEFVAR_LISP ("w32-pass-lwindow-to-system",
7344 Vw32_pass_lwindow_to_system
,
7345 doc
: /* If non-nil, the left \"Windows\" key is passed on to Windows.
7347 When non-nil, the Start menu is opened by tapping the key.
7348 If you set this to nil, the left \"Windows\" key is processed by Emacs
7349 according to the value of `w32-lwindow-modifier', which see.
7351 Note that some combinations of the left \"Windows\" key with other keys are
7352 caught by Windows at low level, and so binding them in Emacs will have no
7353 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
7354 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
7355 the doc string of `w32-phantom-key-code'. */);
7356 Vw32_pass_lwindow_to_system
= Qt
;
7358 DEFVAR_LISP ("w32-pass-rwindow-to-system",
7359 Vw32_pass_rwindow_to_system
,
7360 doc
: /* If non-nil, the right \"Windows\" key is passed on to Windows.
7362 When non-nil, the Start menu is opened by tapping the key.
7363 If you set this to nil, the right \"Windows\" key is processed by Emacs
7364 according to the value of `w32-rwindow-modifier', which see.
7366 Note that some combinations of the right \"Windows\" key with other keys are
7367 caught by Windows at low level, and so binding them in Emacs will have no
7368 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
7369 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
7370 the doc string of `w32-phantom-key-code'. */);
7371 Vw32_pass_rwindow_to_system
= Qt
;
7373 DEFVAR_LISP ("w32-phantom-key-code",
7374 Vw32_phantom_key_code
,
7375 doc
: /* Virtual key code used to generate \"phantom\" key presses.
7376 Value is a number between 0 and 255.
7378 Phantom key presses are generated in order to stop the system from
7379 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
7380 `w32-pass-rwindow-to-system' is nil. */);
7381 /* Although 255 is technically not a valid key code, it works and
7382 means that this hack won't interfere with any real key code. */
7383 XSETINT (Vw32_phantom_key_code
, 255);
7385 DEFVAR_LISP ("w32-enable-num-lock",
7386 Vw32_enable_num_lock
,
7387 doc
: /* If non-nil, the Num Lock key acts normally.
7388 Set to nil to handle Num Lock as the `kp-numlock' key. */);
7389 Vw32_enable_num_lock
= Qt
;
7391 DEFVAR_LISP ("w32-enable-caps-lock",
7392 Vw32_enable_caps_lock
,
7393 doc
: /* If non-nil, the Caps Lock key acts normally.
7394 Set to nil to handle Caps Lock as the `capslock' key. */);
7395 Vw32_enable_caps_lock
= Qt
;
7397 DEFVAR_LISP ("w32-scroll-lock-modifier",
7398 Vw32_scroll_lock_modifier
,
7399 doc
: /* Modifier to use for the Scroll Lock ON state.
7400 The value can be hyper, super, meta, alt, control or shift for the
7401 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
7402 Any other value will cause the Scroll Lock key to be ignored. */);
7403 Vw32_scroll_lock_modifier
= Qnil
;
7405 DEFVAR_LISP ("w32-lwindow-modifier",
7406 Vw32_lwindow_modifier
,
7407 doc
: /* Modifier to use for the left \"Windows\" key.
7408 The value can be hyper, super, meta, alt, control or shift for the
7409 respective modifier, or nil to appear as the `lwindow' key.
7410 Any other value will cause the key to be ignored. */);
7411 Vw32_lwindow_modifier
= Qnil
;
7413 DEFVAR_LISP ("w32-rwindow-modifier",
7414 Vw32_rwindow_modifier
,
7415 doc
: /* Modifier to use for the right \"Windows\" key.
7416 The value can be hyper, super, meta, alt, control or shift for the
7417 respective modifier, or nil to appear as the `rwindow' key.
7418 Any other value will cause the key to be ignored. */);
7419 Vw32_rwindow_modifier
= Qnil
;
7421 DEFVAR_LISP ("w32-apps-modifier",
7423 doc
: /* Modifier to use for the \"Apps\" key.
7424 The value can be hyper, super, meta, alt, control or shift for the
7425 respective modifier, or nil to appear as the `apps' key.
7426 Any other value will cause the key to be ignored. */);
7427 Vw32_apps_modifier
= Qnil
;
7429 DEFVAR_BOOL ("w32-enable-synthesized-fonts", w32_enable_synthesized_fonts
,
7430 doc
: /* Non-nil enables selection of artificially italicized and bold fonts. */);
7431 w32_enable_synthesized_fonts
= 0;
7433 DEFVAR_LISP ("w32-enable-palette", Vw32_enable_palette
,
7434 doc
: /* Non-nil enables Windows palette management to map colors exactly. */);
7435 Vw32_enable_palette
= Qt
;
7437 DEFVAR_INT ("w32-mouse-button-tolerance",
7438 w32_mouse_button_tolerance
,
7439 doc
: /* Analogue of double click interval for faking middle mouse events.
7440 The value is the minimum time in milliseconds that must elapse between
7441 left and right button down events before they are considered distinct events.
7442 If both mouse buttons are depressed within this interval, a middle mouse
7443 button down event is generated instead. */);
7444 w32_mouse_button_tolerance
= GetDoubleClickTime () / 2;
7446 DEFVAR_INT ("w32-mouse-move-interval",
7447 w32_mouse_move_interval
,
7448 doc
: /* Minimum interval between mouse move events.
7449 The value is the minimum time in milliseconds that must elapse between
7450 successive mouse move (or scroll bar drag) events before they are
7451 reported as lisp events. */);
7452 w32_mouse_move_interval
= 0;
7454 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
7455 w32_pass_extra_mouse_buttons_to_system
,
7456 doc
: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
7457 Recent versions of Windows support mice with up to five buttons.
7458 Since most applications don't support these extra buttons, most mouse
7459 drivers will allow you to map them to functions at the system level.
7460 If this variable is non-nil, Emacs will pass them on, allowing the
7461 system to handle them. */);
7462 w32_pass_extra_mouse_buttons_to_system
= 0;
7464 DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
7465 w32_pass_multimedia_buttons_to_system
,
7466 doc
: /* If non-nil, media buttons are passed to Windows.
7467 Some modern keyboards contain buttons for controlling media players, web
7468 browsers and other applications. Generally these buttons are handled on a
7469 system wide basis, but by setting this to nil they are made available
7470 to Emacs for binding. Depending on your keyboard, additional keys that
7471 may be available are:
7473 browser-back, browser-forward, browser-refresh, browser-stop,
7474 browser-search, browser-favorites, browser-home,
7475 mail, mail-reply, mail-forward, mail-send,
7477 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
7478 spell-check, correction-list, toggle-dictate-command,
7479 media-next, media-previous, media-stop, media-play-pause, media-select,
7480 media-play, media-pause, media-record, media-fast-forward, media-rewind,
7481 media-channel-up, media-channel-down,
7482 volume-mute, volume-up, volume-down,
7483 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
7484 bass-down, bass-boost, bass-up, treble-down, treble-up */);
7485 w32_pass_multimedia_buttons_to_system
= 1;
7487 #if 0 /* TODO: Mouse cursor customization. */
7488 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape
,
7489 doc
: /* The shape of the pointer when over text.
7490 Changing the value does not affect existing frames
7491 unless you set the mouse color. */);
7492 Vx_pointer_shape
= Qnil
;
7494 Vx_nontext_pointer_shape
= Qnil
;
7496 Vx_mode_pointer_shape
= Qnil
;
7498 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape
,
7499 doc
: /* The shape of the pointer when Emacs is busy.
7500 This variable takes effect when you create a new frame
7501 or when you set the mouse color. */);
7502 Vx_hourglass_pointer_shape
= Qnil
;
7504 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7505 Vx_sensitive_text_pointer_shape
,
7506 doc
: /* The shape of the pointer when over mouse-sensitive text.
7507 This variable takes effect when you create a new frame
7508 or when you set the mouse color. */);
7509 Vx_sensitive_text_pointer_shape
= Qnil
;
7511 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7512 Vx_window_horizontal_drag_shape
,
7513 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
7514 This variable takes effect when you create a new frame
7515 or when you set the mouse color. */);
7516 Vx_window_horizontal_drag_shape
= Qnil
;
7519 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel
,
7520 doc
: /* A string indicating the foreground color of the cursor box. */);
7521 Vx_cursor_fore_pixel
= Qnil
;
7523 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size
,
7524 doc
: /* Maximum size for tooltips.
7525 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7526 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
7528 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager
,
7529 doc
: /* Non-nil if no window manager is in use.
7530 Emacs doesn't try to figure this out; this is always nil
7531 unless you set it to something else. */);
7532 /* We don't have any way to find this out, so set it to nil
7533 and maybe the user would like to set it to t. */
7534 Vx_no_window_manager
= Qnil
;
7536 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7537 Vx_pixel_size_width_font_regexp
,
7538 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7540 Since Emacs gets width of a font matching with this regexp from
7541 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7542 such a font. This is especially effective for such large fonts as
7543 Chinese, Japanese, and Korean. */);
7544 Vx_pixel_size_width_font_regexp
= Qnil
;
7546 DEFVAR_LISP ("w32-bdf-filename-alist",
7547 Vw32_bdf_filename_alist
,
7548 doc
: /* List of bdf fonts and their corresponding filenames. */);
7549 Vw32_bdf_filename_alist
= Qnil
;
7551 DEFVAR_BOOL ("w32-strict-fontnames",
7552 w32_strict_fontnames
,
7553 doc
: /* Non-nil means only use fonts that are exact matches for those requested.
7554 Default is nil, which allows old fontnames that are not XLFD compliant,
7555 and allows third-party CJK display to work by specifying false charset
7556 fields to trick Emacs into translating to Big5, SJIS etc.
7557 Setting this to t will prevent wrong fonts being selected when
7558 fontsets are automatically created. */);
7559 w32_strict_fontnames
= 0;
7561 DEFVAR_BOOL ("w32-strict-painting",
7562 w32_strict_painting
,
7563 doc
: /* Non-nil means use strict rules for repainting frames.
7564 Set this to nil to get the old behavior for repainting; this should
7565 only be necessary if the default setting causes problems. */);
7566 w32_strict_painting
= 1;
7568 #if 0 /* TODO: Port to W32 */
7569 defsubr (&Sx_change_window_property
);
7570 defsubr (&Sx_delete_window_property
);
7571 defsubr (&Sx_window_property
);
7573 defsubr (&Sxw_display_color_p
);
7574 defsubr (&Sx_display_grayscale_p
);
7575 defsubr (&Sxw_color_defined_p
);
7576 defsubr (&Sxw_color_values
);
7577 defsubr (&Sx_server_max_request_size
);
7578 defsubr (&Sx_server_vendor
);
7579 defsubr (&Sx_server_version
);
7580 defsubr (&Sx_display_pixel_width
);
7581 defsubr (&Sx_display_pixel_height
);
7582 defsubr (&Sx_display_mm_width
);
7583 defsubr (&Sx_display_mm_height
);
7584 defsubr (&Sx_display_screens
);
7585 defsubr (&Sx_display_planes
);
7586 defsubr (&Sx_display_color_cells
);
7587 defsubr (&Sx_display_visual_class
);
7588 defsubr (&Sx_display_backing_store
);
7589 defsubr (&Sx_display_save_under
);
7590 defsubr (&Sx_create_frame
);
7591 defsubr (&Sx_open_connection
);
7592 defsubr (&Sx_close_connection
);
7593 defsubr (&Sx_display_list
);
7594 defsubr (&Sx_synchronize
);
7595 defsubr (&Sx_focus_frame
);
7597 /* W32 specific functions */
7599 defsubr (&Sw32_define_rgb_color
);
7600 defsubr (&Sw32_default_color_map
);
7601 defsubr (&Sw32_send_sys_command
);
7602 defsubr (&Sw32_shell_execute
);
7603 defsubr (&Sw32_register_hot_key
);
7604 defsubr (&Sw32_unregister_hot_key
);
7605 defsubr (&Sw32_registered_hot_keys
);
7606 defsubr (&Sw32_reconstruct_hot_key
);
7607 defsubr (&Sw32_toggle_lock_key
);
7608 defsubr (&Sw32_window_exists_p
);
7609 defsubr (&Sw32_battery_status
);
7611 defsubr (&Sfile_system_info
);
7612 defsubr (&Sdefault_printer_name
);
7613 defsubr (&Sset_message_beep
);
7615 check_window_system_func
= check_w32
;
7617 hourglass_hwnd
= NULL
;
7619 defsubr (&Sx_show_tip
);
7620 defsubr (&Sx_hide_tip
);
7622 staticpro (&tip_timer
);
7624 staticpro (&tip_frame
);
7626 last_show_tip_args
= Qnil
;
7627 staticpro (&last_show_tip_args
);
7629 defsubr (&Sx_file_dialog
);
7631 defsubr (&Ssystem_move_file_to_trash
);
7637 globals_of_w32fns is used to initialize those global variables that
7638 must always be initialized on startup even when the global variable
7639 initialized is non zero (see the function main in emacs.c).
7640 globals_of_w32fns is called from syms_of_w32fns when the global
7641 variable initialized is 0 and directly from main when initialized
7645 globals_of_w32fns (void)
7647 HMODULE user32_lib
= GetModuleHandle ("user32.dll");
7649 TrackMouseEvent not available in all versions of Windows, so must load
7650 it dynamically. Do it once, here, instead of every time it is used.
7652 track_mouse_event_fn
= (TrackMouseEvent_Proc
)
7653 GetProcAddress (user32_lib
, "TrackMouseEvent");
7655 monitor_from_point_fn
= (MonitorFromPoint_Proc
)
7656 GetProcAddress (user32_lib
, "MonitorFromPoint");
7657 get_monitor_info_fn
= (GetMonitorInfo_Proc
)
7658 GetProcAddress (user32_lib
, "GetMonitorInfoA");
7661 HMODULE imm32_lib
= GetModuleHandle ("imm32.dll");
7662 get_composition_string_fn
= (ImmGetCompositionString_Proc
)
7663 GetProcAddress (imm32_lib
, "ImmGetCompositionStringW");
7664 get_ime_context_fn
= (ImmGetContext_Proc
)
7665 GetProcAddress (imm32_lib
, "ImmGetContext");
7666 release_ime_context_fn
= (ImmReleaseContext_Proc
)
7667 GetProcAddress (imm32_lib
, "ImmReleaseContext");
7668 set_ime_composition_window_fn
= (ImmSetCompositionWindow_Proc
)
7669 GetProcAddress (imm32_lib
, "ImmSetCompositionWindow");
7671 DEFVAR_INT ("w32-ansi-code-page",
7673 doc
: /* The ANSI code page used by the system. */);
7674 w32_ansi_code_page
= GetACP ();
7676 if (os_subtype
== OS_NT
)
7677 w32_unicode_gui
= 1;
7679 w32_unicode_gui
= 0;
7681 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
7682 InitCommonControls ();
7684 syms_of_w32uniscribe ();
7691 button
= MessageBox (NULL
,
7692 "A fatal error has occurred!\n\n"
7693 "Would you like to attach a debugger?\n\n"
7694 "Select YES to debug, NO to abort Emacs"
7696 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
7697 "\"continue\" inside GDB before clicking YES.)"
7699 , "Emacs Abort Dialog",
7700 MB_ICONEXCLAMATION
| MB_TASKMODAL
7701 | MB_SETFOREGROUND
| MB_YESNO
);
7706 exit (2); /* tell the compiler we will never return */