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