Merge from trunk
[bpt/emacs.git] / src / w32fns.c
1 /* Graphical user interface functions for the Microsoft Windows API.
2
3 Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* Added by Kevin Gallo */
21
22 #include <config.h>
23
24 #include <signal.h>
25 #include <stdio.h>
26 #include <limits.h>
27 #include <errno.h>
28 #include <math.h>
29
30 #include "lisp.h"
31 #include "w32term.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "character.h"
35 #include "buffer.h"
36 #include "intervals.h"
37 #include "dispextern.h"
38 #include "keyboard.h"
39 #include "blockinput.h"
40 #include "epaths.h"
41 #include "charset.h"
42 #include "coding.h"
43 #include "ccl.h"
44 #include "fontset.h"
45 #include "systime.h"
46 #include "termhooks.h"
47
48 #include "w32heap.h"
49
50 #if CYGWIN
51 #include "cygw32.h"
52 #else
53 #include "w32.h"
54 #endif
55
56 #include "bitmaps/gray.xbm"
57
58 #include <commctrl.h>
59 #include <commdlg.h>
60 #include <shellapi.h>
61 #include <ctype.h>
62 #include <winspool.h>
63 #include <objbase.h>
64
65 #include <dlgs.h>
66 #include <imm.h>
67
68 #include "font.h"
69 #include "w32font.h"
70
71 #ifndef FOF_NO_CONNECTED_ELEMENTS
72 #define FOF_NO_CONNECTED_ELEMENTS 0x2000
73 #endif
74
75 void syms_of_w32fns (void);
76 void globals_of_w32fns (void);
77
78 extern void free_frame_menubar (struct frame *);
79 extern double atof (const char *);
80 extern int w32_console_toggle_lock_key (int, Lisp_Object);
81 extern void w32_menu_display_help (HWND, HMENU, UINT, UINT);
82 extern void w32_free_menu_strings (HWND);
83 extern const char *map_w32_filename (const char *, const char **);
84 extern char * w32_strerror (int error_no);
85
86 /* If non-NULL, a handle to a frame where to display the hourglass cursor. */
87 static HWND hourglass_hwnd = NULL;
88
89 #ifndef IDC_HAND
90 #define IDC_HAND MAKEINTRESOURCE(32649)
91 #endif
92
93 /* Nonzero if using Windows. */
94
95 static int w32_in_use;
96
97 Lisp_Object Qsuppress_icon;
98 Lisp_Object Qundefined_color;
99 Lisp_Object Qcancel_timer;
100 Lisp_Object Qfont_param;
101 Lisp_Object Qhyper;
102 Lisp_Object Qsuper;
103 Lisp_Object Qmeta;
104 Lisp_Object Qalt;
105 Lisp_Object Qctrl;
106 Lisp_Object Qcontrol;
107 Lisp_Object Qshift;
108
109
110 /* Prefix for system colors. */
111 #define SYSTEM_COLOR_PREFIX "System"
112 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
113
114 /* State variables for emulating a three button mouse. */
115 #define LMOUSE 1
116 #define MMOUSE 2
117 #define RMOUSE 4
118
119 static int button_state = 0;
120 static W32Msg saved_mouse_button_msg;
121 static unsigned mouse_button_timer = 0; /* non-zero when timer is active */
122 static W32Msg saved_mouse_move_msg;
123 static unsigned mouse_move_timer = 0;
124
125 /* Window that is tracking the mouse. */
126 static HWND track_mouse_window;
127
128 /* Multi-monitor API definitions that are not pulled from the headers
129 since we are compiling for NT 4. */
130 #ifndef MONITOR_DEFAULT_TO_NEAREST
131 #define MONITOR_DEFAULT_TO_NEAREST 2
132 #endif
133 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
134 To avoid a compile error on one or the other, redefine with a new name. */
135 struct MONITOR_INFO
136 {
137 DWORD cbSize;
138 RECT rcMonitor;
139 RECT rcWork;
140 DWORD dwFlags;
141 };
142
143 /* Reportedly, MSVC does not have this in its headers. */
144 #if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
145 DECLARE_HANDLE(HMONITOR);
146 #endif
147
148 typedef BOOL (WINAPI * TrackMouseEvent_Proc)
149 (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
150 typedef LONG (WINAPI * ImmGetCompositionString_Proc)
151 (IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
152 typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
153 typedef HWND (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
154 typedef HWND (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
155 IN COMPOSITIONFORM *form);
156 typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
157 typedef BOOL (WINAPI * GetMonitorInfo_Proc)
158 (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
159
160 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
161 ImmGetCompositionString_Proc get_composition_string_fn = NULL;
162 ImmGetContext_Proc get_ime_context_fn = NULL;
163 ImmReleaseContext_Proc release_ime_context_fn = NULL;
164 ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
165 MonitorFromPoint_Proc monitor_from_point_fn = NULL;
166 GetMonitorInfo_Proc get_monitor_info_fn = NULL;
167
168 #ifdef NTGUI_UNICODE
169 #define unicode_append_menu AppendMenuW
170 #else /* !NTGUI_UNICODE */
171 extern AppendMenuW_Proc unicode_append_menu;
172 #endif /* NTGUI_UNICODE */
173
174 /* Flag to selectively ignore WM_IME_CHAR messages. */
175 static int ignore_ime_char = 0;
176
177 /* W95 mousewheel handler */
178 unsigned int msh_mousewheel = 0;
179
180 /* Timers */
181 #define MOUSE_BUTTON_ID 1
182 #define MOUSE_MOVE_ID 2
183 #define MENU_FREE_ID 3
184 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
185 is received. */
186 #define MENU_FREE_DELAY 1000
187 static unsigned menu_free_timer = 0;
188
189 #ifdef GLYPH_DEBUG
190 static int image_cache_refcount, dpyinfo_refcount;
191 #endif
192
193 static HWND w32_visible_system_caret_hwnd;
194
195 static int w32_unicode_gui;
196
197 /* From w32menu.c */
198 extern HMENU current_popup_menu;
199 static int menubar_in_use = 0;
200
201 /* From w32uniscribe.c */
202 extern void syms_of_w32uniscribe (void);
203 extern int uniscribe_available;
204
205 /* Function prototypes for hourglass support. */
206 static void w32_show_hourglass (struct frame *);
207 static void w32_hide_hourglass (void);
208
209 #ifdef WINDOWSNT
210 /* From w32inevet.c */
211 extern int faked_key;
212 #endif /* WINDOWSNT */
213
214 /* This gives us the page size and the size of the allocation unit on NT. */
215 SYSTEM_INFO sysinfo_cache;
216
217 /* This gives us version, build, and platform identification. */
218 OSVERSIONINFO osinfo_cache;
219
220 unsigned long syspage_mask = 0;
221
222 /* The major and minor versions of NT. */
223 int w32_major_version;
224 int w32_minor_version;
225 int w32_build_number;
226
227 /* Distinguish between Windows NT and Windows 95. */
228 int os_subtype;
229
230 #ifdef HAVE_NTGUI
231 HINSTANCE hinst = NULL;
232 #endif
233
234 static unsigned int sound_type = 0xFFFFFFFF;
235 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
236
237 \f
238 /* Error if we are not connected to MS-Windows. */
239 void
240 check_w32 (void)
241 {
242 if (! w32_in_use)
243 error ("MS-Windows not in use or not initialized");
244 }
245
246 /* Nonzero if we can use mouse menus.
247 You should not call this unless HAVE_MENUS is defined. */
248
249 int
250 have_menus_p (void)
251 {
252 return w32_in_use;
253 }
254
255 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
256 and checking validity for W32. */
257
258 FRAME_PTR
259 check_x_frame (Lisp_Object frame)
260 {
261 FRAME_PTR f;
262
263 if (NILP (frame))
264 frame = selected_frame;
265 CHECK_LIVE_FRAME (frame);
266 f = XFRAME (frame);
267 if (! FRAME_W32_P (f))
268 error ("Non-W32 frame used");
269 return f;
270 }
271
272 /* Let the user specify a display with a frame.
273 nil stands for the selected frame--or, if that is not a w32 frame,
274 the first display on the list. */
275
276 struct w32_display_info *
277 check_x_display_info (Lisp_Object frame)
278 {
279 if (NILP (frame))
280 {
281 struct frame *sf = XFRAME (selected_frame);
282
283 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
284 return FRAME_W32_DISPLAY_INFO (sf);
285 else
286 return &one_w32_display_info;
287 }
288 else if (STRINGP (frame))
289 return x_display_info_for_name (frame);
290 else
291 {
292 FRAME_PTR f;
293
294 CHECK_LIVE_FRAME (frame);
295 f = XFRAME (frame);
296 if (! FRAME_W32_P (f))
297 error ("Non-W32 frame used");
298 return FRAME_W32_DISPLAY_INFO (f);
299 }
300 }
301 \f
302 /* Return the Emacs frame-object corresponding to an w32 window.
303 It could be the frame's main window or an icon window. */
304
305 /* This function can be called during GC, so use GC_xxx type test macros. */
306
307 struct frame *
308 x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc)
309 {
310 Lisp_Object tail, frame;
311 struct frame *f;
312
313 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
314 {
315 frame = XCAR (tail);
316 if (!FRAMEP (frame))
317 continue;
318 f = XFRAME (frame);
319 if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
320 continue;
321
322 if (FRAME_W32_WINDOW (f) == wdesc)
323 return f;
324 }
325 return 0;
326 }
327
328 \f
329 static Lisp_Object unwind_create_frame (Lisp_Object);
330 static Lisp_Object unwind_create_tip_frame (Lisp_Object);
331 static void my_create_window (struct frame *);
332 static void my_create_tip_window (struct frame *);
333
334 /* TODO: Native Input Method support; see x_create_im. */
335 void x_set_foreground_color (struct frame *, Lisp_Object, Lisp_Object);
336 void x_set_background_color (struct frame *, Lisp_Object, Lisp_Object);
337 void x_set_mouse_color (struct frame *, Lisp_Object, Lisp_Object);
338 void x_set_cursor_color (struct frame *, Lisp_Object, Lisp_Object);
339 void x_set_border_color (struct frame *, Lisp_Object, Lisp_Object);
340 void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
341 void x_set_icon_type (struct frame *, Lisp_Object, Lisp_Object);
342 void x_set_icon_name (struct frame *, Lisp_Object, Lisp_Object);
343 void x_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
344 void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
345 void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
346 void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
347
348
349 \f
350
351 /* Store the screen positions of frame F into XPTR and YPTR.
352 These are the positions of the containing window manager window,
353 not Emacs's own window. */
354
355 void
356 x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
357 {
358 POINT pt;
359 RECT rect;
360
361 /* Get the bounds of the WM window. */
362 GetWindowRect (FRAME_W32_WINDOW (f), &rect);
363
364 pt.x = 0;
365 pt.y = 0;
366
367 /* Convert (0, 0) in the client area to screen co-ordinates. */
368 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
369
370 /* Remember x_pixels_diff and y_pixels_diff. */
371 f->x_pixels_diff = pt.x - rect.left;
372 f->y_pixels_diff = pt.y - rect.top;
373
374 *xptr = rect.left;
375 *yptr = rect.top;
376 }
377
378 \f
379
380 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
381 Sw32_define_rgb_color, 4, 4, 0,
382 doc: /* Convert RGB numbers to a Windows color reference and associate with NAME.
383 This adds or updates a named color to `w32-color-map', making it
384 available for use. The original entry's RGB ref is returned, or nil
385 if the entry is new. */)
386 (Lisp_Object red, Lisp_Object green, Lisp_Object blue, Lisp_Object name)
387 {
388 Lisp_Object rgb;
389 Lisp_Object oldrgb = Qnil;
390 Lisp_Object entry;
391
392 CHECK_NUMBER (red);
393 CHECK_NUMBER (green);
394 CHECK_NUMBER (blue);
395 CHECK_STRING (name);
396
397 XSETINT (rgb, RGB (XUINT (red), XUINT (green), XUINT (blue)));
398
399 block_input ();
400
401 /* replace existing entry in w32-color-map or add new entry. */
402 entry = Fassoc (name, Vw32_color_map);
403 if (NILP (entry))
404 {
405 entry = Fcons (name, rgb);
406 Vw32_color_map = Fcons (entry, Vw32_color_map);
407 }
408 else
409 {
410 oldrgb = Fcdr (entry);
411 Fsetcdr (entry, rgb);
412 }
413
414 unblock_input ();
415
416 return (oldrgb);
417 }
418
419 /* The default colors for the w32 color map */
420 typedef struct colormap_t
421 {
422 char *name;
423 COLORREF colorref;
424 } colormap_t;
425
426 colormap_t w32_color_map[] =
427 {
428 {"snow" , PALETTERGB (255,250,250)},
429 {"ghost white" , PALETTERGB (248,248,255)},
430 {"GhostWhite" , PALETTERGB (248,248,255)},
431 {"white smoke" , PALETTERGB (245,245,245)},
432 {"WhiteSmoke" , PALETTERGB (245,245,245)},
433 {"gainsboro" , PALETTERGB (220,220,220)},
434 {"floral white" , PALETTERGB (255,250,240)},
435 {"FloralWhite" , PALETTERGB (255,250,240)},
436 {"old lace" , PALETTERGB (253,245,230)},
437 {"OldLace" , PALETTERGB (253,245,230)},
438 {"linen" , PALETTERGB (250,240,230)},
439 {"antique white" , PALETTERGB (250,235,215)},
440 {"AntiqueWhite" , PALETTERGB (250,235,215)},
441 {"papaya whip" , PALETTERGB (255,239,213)},
442 {"PapayaWhip" , PALETTERGB (255,239,213)},
443 {"blanched almond" , PALETTERGB (255,235,205)},
444 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
445 {"bisque" , PALETTERGB (255,228,196)},
446 {"peach puff" , PALETTERGB (255,218,185)},
447 {"PeachPuff" , PALETTERGB (255,218,185)},
448 {"navajo white" , PALETTERGB (255,222,173)},
449 {"NavajoWhite" , PALETTERGB (255,222,173)},
450 {"moccasin" , PALETTERGB (255,228,181)},
451 {"cornsilk" , PALETTERGB (255,248,220)},
452 {"ivory" , PALETTERGB (255,255,240)},
453 {"lemon chiffon" , PALETTERGB (255,250,205)},
454 {"LemonChiffon" , PALETTERGB (255,250,205)},
455 {"seashell" , PALETTERGB (255,245,238)},
456 {"honeydew" , PALETTERGB (240,255,240)},
457 {"mint cream" , PALETTERGB (245,255,250)},
458 {"MintCream" , PALETTERGB (245,255,250)},
459 {"azure" , PALETTERGB (240,255,255)},
460 {"alice blue" , PALETTERGB (240,248,255)},
461 {"AliceBlue" , PALETTERGB (240,248,255)},
462 {"lavender" , PALETTERGB (230,230,250)},
463 {"lavender blush" , PALETTERGB (255,240,245)},
464 {"LavenderBlush" , PALETTERGB (255,240,245)},
465 {"misty rose" , PALETTERGB (255,228,225)},
466 {"MistyRose" , PALETTERGB (255,228,225)},
467 {"white" , PALETTERGB (255,255,255)},
468 {"black" , PALETTERGB ( 0, 0, 0)},
469 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
470 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
471 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
472 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
473 {"dim gray" , PALETTERGB (105,105,105)},
474 {"DimGray" , PALETTERGB (105,105,105)},
475 {"dim grey" , PALETTERGB (105,105,105)},
476 {"DimGrey" , PALETTERGB (105,105,105)},
477 {"slate gray" , PALETTERGB (112,128,144)},
478 {"SlateGray" , PALETTERGB (112,128,144)},
479 {"slate grey" , PALETTERGB (112,128,144)},
480 {"SlateGrey" , PALETTERGB (112,128,144)},
481 {"light slate gray" , PALETTERGB (119,136,153)},
482 {"LightSlateGray" , PALETTERGB (119,136,153)},
483 {"light slate grey" , PALETTERGB (119,136,153)},
484 {"LightSlateGrey" , PALETTERGB (119,136,153)},
485 {"gray" , PALETTERGB (190,190,190)},
486 {"grey" , PALETTERGB (190,190,190)},
487 {"light grey" , PALETTERGB (211,211,211)},
488 {"LightGrey" , PALETTERGB (211,211,211)},
489 {"light gray" , PALETTERGB (211,211,211)},
490 {"LightGray" , PALETTERGB (211,211,211)},
491 {"midnight blue" , PALETTERGB ( 25, 25,112)},
492 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
493 {"navy" , PALETTERGB ( 0, 0,128)},
494 {"navy blue" , PALETTERGB ( 0, 0,128)},
495 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
496 {"cornflower blue" , PALETTERGB (100,149,237)},
497 {"CornflowerBlue" , PALETTERGB (100,149,237)},
498 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
499 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
500 {"slate blue" , PALETTERGB (106, 90,205)},
501 {"SlateBlue" , PALETTERGB (106, 90,205)},
502 {"medium slate blue" , PALETTERGB (123,104,238)},
503 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
504 {"light slate blue" , PALETTERGB (132,112,255)},
505 {"LightSlateBlue" , PALETTERGB (132,112,255)},
506 {"medium blue" , PALETTERGB ( 0, 0,205)},
507 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
508 {"royal blue" , PALETTERGB ( 65,105,225)},
509 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
510 {"blue" , PALETTERGB ( 0, 0,255)},
511 {"dodger blue" , PALETTERGB ( 30,144,255)},
512 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
513 {"deep sky blue" , PALETTERGB ( 0,191,255)},
514 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
515 {"sky blue" , PALETTERGB (135,206,235)},
516 {"SkyBlue" , PALETTERGB (135,206,235)},
517 {"light sky blue" , PALETTERGB (135,206,250)},
518 {"LightSkyBlue" , PALETTERGB (135,206,250)},
519 {"steel blue" , PALETTERGB ( 70,130,180)},
520 {"SteelBlue" , PALETTERGB ( 70,130,180)},
521 {"light steel blue" , PALETTERGB (176,196,222)},
522 {"LightSteelBlue" , PALETTERGB (176,196,222)},
523 {"light blue" , PALETTERGB (173,216,230)},
524 {"LightBlue" , PALETTERGB (173,216,230)},
525 {"powder blue" , PALETTERGB (176,224,230)},
526 {"PowderBlue" , PALETTERGB (176,224,230)},
527 {"pale turquoise" , PALETTERGB (175,238,238)},
528 {"PaleTurquoise" , PALETTERGB (175,238,238)},
529 {"dark turquoise" , PALETTERGB ( 0,206,209)},
530 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
531 {"medium turquoise" , PALETTERGB ( 72,209,204)},
532 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
533 {"turquoise" , PALETTERGB ( 64,224,208)},
534 {"cyan" , PALETTERGB ( 0,255,255)},
535 {"light cyan" , PALETTERGB (224,255,255)},
536 {"LightCyan" , PALETTERGB (224,255,255)},
537 {"cadet blue" , PALETTERGB ( 95,158,160)},
538 {"CadetBlue" , PALETTERGB ( 95,158,160)},
539 {"medium aquamarine" , PALETTERGB (102,205,170)},
540 {"MediumAquamarine" , PALETTERGB (102,205,170)},
541 {"aquamarine" , PALETTERGB (127,255,212)},
542 {"dark green" , PALETTERGB ( 0,100, 0)},
543 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
544 {"dark olive green" , PALETTERGB ( 85,107, 47)},
545 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
546 {"dark sea green" , PALETTERGB (143,188,143)},
547 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
548 {"sea green" , PALETTERGB ( 46,139, 87)},
549 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
550 {"medium sea green" , PALETTERGB ( 60,179,113)},
551 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
552 {"light sea green" , PALETTERGB ( 32,178,170)},
553 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
554 {"pale green" , PALETTERGB (152,251,152)},
555 {"PaleGreen" , PALETTERGB (152,251,152)},
556 {"spring green" , PALETTERGB ( 0,255,127)},
557 {"SpringGreen" , PALETTERGB ( 0,255,127)},
558 {"lawn green" , PALETTERGB (124,252, 0)},
559 {"LawnGreen" , PALETTERGB (124,252, 0)},
560 {"green" , PALETTERGB ( 0,255, 0)},
561 {"chartreuse" , PALETTERGB (127,255, 0)},
562 {"medium spring green" , PALETTERGB ( 0,250,154)},
563 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
564 {"green yellow" , PALETTERGB (173,255, 47)},
565 {"GreenYellow" , PALETTERGB (173,255, 47)},
566 {"lime green" , PALETTERGB ( 50,205, 50)},
567 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
568 {"yellow green" , PALETTERGB (154,205, 50)},
569 {"YellowGreen" , PALETTERGB (154,205, 50)},
570 {"forest green" , PALETTERGB ( 34,139, 34)},
571 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
572 {"olive drab" , PALETTERGB (107,142, 35)},
573 {"OliveDrab" , PALETTERGB (107,142, 35)},
574 {"dark khaki" , PALETTERGB (189,183,107)},
575 {"DarkKhaki" , PALETTERGB (189,183,107)},
576 {"khaki" , PALETTERGB (240,230,140)},
577 {"pale goldenrod" , PALETTERGB (238,232,170)},
578 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
579 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
580 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
581 {"light yellow" , PALETTERGB (255,255,224)},
582 {"LightYellow" , PALETTERGB (255,255,224)},
583 {"yellow" , PALETTERGB (255,255, 0)},
584 {"gold" , PALETTERGB (255,215, 0)},
585 {"light goldenrod" , PALETTERGB (238,221,130)},
586 {"LightGoldenrod" , PALETTERGB (238,221,130)},
587 {"goldenrod" , PALETTERGB (218,165, 32)},
588 {"dark goldenrod" , PALETTERGB (184,134, 11)},
589 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
590 {"rosy brown" , PALETTERGB (188,143,143)},
591 {"RosyBrown" , PALETTERGB (188,143,143)},
592 {"indian red" , PALETTERGB (205, 92, 92)},
593 {"IndianRed" , PALETTERGB (205, 92, 92)},
594 {"saddle brown" , PALETTERGB (139, 69, 19)},
595 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
596 {"sienna" , PALETTERGB (160, 82, 45)},
597 {"peru" , PALETTERGB (205,133, 63)},
598 {"burlywood" , PALETTERGB (222,184,135)},
599 {"beige" , PALETTERGB (245,245,220)},
600 {"wheat" , PALETTERGB (245,222,179)},
601 {"sandy brown" , PALETTERGB (244,164, 96)},
602 {"SandyBrown" , PALETTERGB (244,164, 96)},
603 {"tan" , PALETTERGB (210,180,140)},
604 {"chocolate" , PALETTERGB (210,105, 30)},
605 {"firebrick" , PALETTERGB (178,34, 34)},
606 {"brown" , PALETTERGB (165,42, 42)},
607 {"dark salmon" , PALETTERGB (233,150,122)},
608 {"DarkSalmon" , PALETTERGB (233,150,122)},
609 {"salmon" , PALETTERGB (250,128,114)},
610 {"light salmon" , PALETTERGB (255,160,122)},
611 {"LightSalmon" , PALETTERGB (255,160,122)},
612 {"orange" , PALETTERGB (255,165, 0)},
613 {"dark orange" , PALETTERGB (255,140, 0)},
614 {"DarkOrange" , PALETTERGB (255,140, 0)},
615 {"coral" , PALETTERGB (255,127, 80)},
616 {"light coral" , PALETTERGB (240,128,128)},
617 {"LightCoral" , PALETTERGB (240,128,128)},
618 {"tomato" , PALETTERGB (255, 99, 71)},
619 {"orange red" , PALETTERGB (255, 69, 0)},
620 {"OrangeRed" , PALETTERGB (255, 69, 0)},
621 {"red" , PALETTERGB (255, 0, 0)},
622 {"hot pink" , PALETTERGB (255,105,180)},
623 {"HotPink" , PALETTERGB (255,105,180)},
624 {"deep pink" , PALETTERGB (255, 20,147)},
625 {"DeepPink" , PALETTERGB (255, 20,147)},
626 {"pink" , PALETTERGB (255,192,203)},
627 {"light pink" , PALETTERGB (255,182,193)},
628 {"LightPink" , PALETTERGB (255,182,193)},
629 {"pale violet red" , PALETTERGB (219,112,147)},
630 {"PaleVioletRed" , PALETTERGB (219,112,147)},
631 {"maroon" , PALETTERGB (176, 48, 96)},
632 {"medium violet red" , PALETTERGB (199, 21,133)},
633 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
634 {"violet red" , PALETTERGB (208, 32,144)},
635 {"VioletRed" , PALETTERGB (208, 32,144)},
636 {"magenta" , PALETTERGB (255, 0,255)},
637 {"violet" , PALETTERGB (238,130,238)},
638 {"plum" , PALETTERGB (221,160,221)},
639 {"orchid" , PALETTERGB (218,112,214)},
640 {"medium orchid" , PALETTERGB (186, 85,211)},
641 {"MediumOrchid" , PALETTERGB (186, 85,211)},
642 {"dark orchid" , PALETTERGB (153, 50,204)},
643 {"DarkOrchid" , PALETTERGB (153, 50,204)},
644 {"dark violet" , PALETTERGB (148, 0,211)},
645 {"DarkViolet" , PALETTERGB (148, 0,211)},
646 {"blue violet" , PALETTERGB (138, 43,226)},
647 {"BlueViolet" , PALETTERGB (138, 43,226)},
648 {"purple" , PALETTERGB (160, 32,240)},
649 {"medium purple" , PALETTERGB (147,112,219)},
650 {"MediumPurple" , PALETTERGB (147,112,219)},
651 {"thistle" , PALETTERGB (216,191,216)},
652 {"gray0" , PALETTERGB ( 0, 0, 0)},
653 {"grey0" , PALETTERGB ( 0, 0, 0)},
654 {"dark grey" , PALETTERGB (169,169,169)},
655 {"DarkGrey" , PALETTERGB (169,169,169)},
656 {"dark gray" , PALETTERGB (169,169,169)},
657 {"DarkGray" , PALETTERGB (169,169,169)},
658 {"dark blue" , PALETTERGB ( 0, 0,139)},
659 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
660 {"dark cyan" , PALETTERGB ( 0,139,139)},
661 {"DarkCyan" , PALETTERGB ( 0,139,139)},
662 {"dark magenta" , PALETTERGB (139, 0,139)},
663 {"DarkMagenta" , PALETTERGB (139, 0,139)},
664 {"dark red" , PALETTERGB (139, 0, 0)},
665 {"DarkRed" , PALETTERGB (139, 0, 0)},
666 {"light green" , PALETTERGB (144,238,144)},
667 {"LightGreen" , PALETTERGB (144,238,144)},
668 };
669
670 static Lisp_Object
671 w32_default_color_map (void)
672 {
673 int i;
674 colormap_t *pc = w32_color_map;
675 Lisp_Object cmap;
676
677 block_input ();
678
679 cmap = Qnil;
680
681 for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
682 pc++, i++)
683 cmap = Fcons (Fcons (build_string (pc->name),
684 make_number (pc->colorref)),
685 cmap);
686
687 unblock_input ();
688
689 return (cmap);
690 }
691
692 DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
693 0, 0, 0, doc: /* Return the default color map. */)
694 (void)
695 {
696 return w32_default_color_map ();
697 }
698
699 static Lisp_Object
700 w32_color_map_lookup (char *colorname)
701 {
702 Lisp_Object tail, ret = Qnil;
703
704 block_input ();
705
706 for (tail = Vw32_color_map; CONSP (tail); tail = XCDR (tail))
707 {
708 register Lisp_Object elt, tem;
709
710 elt = XCAR (tail);
711 if (!CONSP (elt)) continue;
712
713 tem = XCAR (elt);
714
715 if (lstrcmpi (SDATA (tem), colorname) == 0)
716 {
717 ret = Fcdr (elt);
718 break;
719 }
720
721 QUIT;
722 }
723
724 unblock_input ();
725
726 return ret;
727 }
728
729
730 static void
731 add_system_logical_colors_to_map (Lisp_Object *system_colors)
732 {
733 HKEY colors_key;
734
735 /* Other registry operations are done with input blocked. */
736 block_input ();
737
738 /* Look for "Control Panel/Colors" under User and Machine registry
739 settings. */
740 if (RegOpenKeyEx (HKEY_CURRENT_USER, "Control Panel\\Colors", 0,
741 KEY_READ, &colors_key) == ERROR_SUCCESS
742 || RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Control Panel\\Colors", 0,
743 KEY_READ, &colors_key) == ERROR_SUCCESS)
744 {
745 /* List all keys. */
746 char color_buffer[64];
747 char full_name_buffer[MAX_PATH + SYSTEM_COLOR_PREFIX_LEN];
748 int index = 0;
749 DWORD name_size, color_size;
750 char *name_buffer = full_name_buffer + SYSTEM_COLOR_PREFIX_LEN;
751
752 name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
753 color_size = sizeof (color_buffer);
754
755 strcpy (full_name_buffer, SYSTEM_COLOR_PREFIX);
756
757 while (RegEnumValueA (colors_key, index, name_buffer, &name_size,
758 NULL, NULL, color_buffer, &color_size)
759 == ERROR_SUCCESS)
760 {
761 int r, g, b;
762 if (sscanf (color_buffer, " %u %u %u", &r, &g, &b) == 3)
763 *system_colors = Fcons (Fcons (build_string (full_name_buffer),
764 make_number (RGB (r, g, b))),
765 *system_colors);
766
767 name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
768 color_size = sizeof (color_buffer);
769 index++;
770 }
771 RegCloseKey (colors_key);
772 }
773
774 unblock_input ();
775 }
776
777
778 static Lisp_Object
779 x_to_w32_color (char * colorname)
780 {
781 register Lisp_Object ret = Qnil;
782
783 block_input ();
784
785 if (colorname[0] == '#')
786 {
787 /* Could be an old-style RGB Device specification. */
788 char *color;
789 int size;
790 color = colorname + 1;
791
792 size = strlen (color);
793 if (size == 3 || size == 6 || size == 9 || size == 12)
794 {
795 UINT colorval;
796 int i, pos;
797 pos = 0;
798 size /= 3;
799 colorval = 0;
800
801 for (i = 0; i < 3; i++)
802 {
803 char *end;
804 char t;
805 unsigned long value;
806
807 /* The check for 'x' in the following conditional takes into
808 account the fact that strtol allows a "0x" in front of
809 our numbers, and we don't. */
810 if (!isxdigit (color[0]) || color[1] == 'x')
811 break;
812 t = color[size];
813 color[size] = '\0';
814 value = strtoul (color, &end, 16);
815 color[size] = t;
816 if (errno == ERANGE || end - color != size)
817 break;
818 switch (size)
819 {
820 case 1:
821 value = value * 0x10;
822 break;
823 case 2:
824 break;
825 case 3:
826 value /= 0x10;
827 break;
828 case 4:
829 value /= 0x100;
830 break;
831 }
832 colorval |= (value << pos);
833 pos += 0x8;
834 if (i == 2)
835 {
836 unblock_input ();
837 XSETINT (ret, colorval);
838 return ret;
839 }
840 color = end;
841 }
842 }
843 }
844 else if (strnicmp (colorname, "rgb:", 4) == 0)
845 {
846 char *color;
847 UINT colorval;
848 int i, pos;
849 pos = 0;
850
851 colorval = 0;
852 color = colorname + 4;
853 for (i = 0; i < 3; i++)
854 {
855 char *end;
856 unsigned long value;
857
858 /* The check for 'x' in the following conditional takes into
859 account the fact that strtol allows a "0x" in front of
860 our numbers, and we don't. */
861 if (!isxdigit (color[0]) || color[1] == 'x')
862 break;
863 value = strtoul (color, &end, 16);
864 if (errno == ERANGE)
865 break;
866 switch (end - color)
867 {
868 case 1:
869 value = value * 0x10 + value;
870 break;
871 case 2:
872 break;
873 case 3:
874 value /= 0x10;
875 break;
876 case 4:
877 value /= 0x100;
878 break;
879 default:
880 value = ULONG_MAX;
881 }
882 if (value == ULONG_MAX)
883 break;
884 colorval |= (value << pos);
885 pos += 0x8;
886 if (i == 2)
887 {
888 if (*end != '\0')
889 break;
890 unblock_input ();
891 XSETINT (ret, colorval);
892 return ret;
893 }
894 if (*end != '/')
895 break;
896 color = end + 1;
897 }
898 }
899 else if (strnicmp (colorname, "rgbi:", 5) == 0)
900 {
901 /* This is an RGB Intensity specification. */
902 char *color;
903 UINT colorval;
904 int i, pos;
905 pos = 0;
906
907 colorval = 0;
908 color = colorname + 5;
909 for (i = 0; i < 3; i++)
910 {
911 char *end;
912 double value;
913 UINT val;
914
915 value = strtod (color, &end);
916 if (errno == ERANGE)
917 break;
918 if (value < 0.0 || value > 1.0)
919 break;
920 val = (UINT)(0x100 * value);
921 /* We used 0x100 instead of 0xFF to give a continuous
922 range between 0.0 and 1.0 inclusive. The next statement
923 fixes the 1.0 case. */
924 if (val == 0x100)
925 val = 0xFF;
926 colorval |= (val << pos);
927 pos += 0x8;
928 if (i == 2)
929 {
930 if (*end != '\0')
931 break;
932 unblock_input ();
933 XSETINT (ret, colorval);
934 return ret;
935 }
936 if (*end != '/')
937 break;
938 color = end + 1;
939 }
940 }
941 /* I am not going to attempt to handle any of the CIE color schemes
942 or TekHVC, since I don't know the algorithms for conversion to
943 RGB. */
944
945 /* If we fail to lookup the color name in w32_color_map, then check the
946 colorname to see if it can be crudely approximated: If the X color
947 ends in a number (e.g., "darkseagreen2"), strip the number and
948 return the result of looking up the base color name. */
949 ret = w32_color_map_lookup (colorname);
950 if (NILP (ret))
951 {
952 int len = strlen (colorname);
953
954 if (isdigit (colorname[len - 1]))
955 {
956 char *ptr, *approx = alloca (len + 1);
957
958 strcpy (approx, colorname);
959 ptr = &approx[len - 1];
960 while (ptr > approx && isdigit (*ptr))
961 *ptr-- = '\0';
962
963 ret = w32_color_map_lookup (approx);
964 }
965 }
966
967 unblock_input ();
968 return ret;
969 }
970
971 void
972 w32_regenerate_palette (FRAME_PTR f)
973 {
974 struct w32_palette_entry * list;
975 LOGPALETTE * log_palette;
976 HPALETTE new_palette;
977 int i;
978
979 /* don't bother trying to create palette if not supported */
980 if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
981 return;
982
983 log_palette = (LOGPALETTE *)
984 alloca (sizeof (LOGPALETTE) +
985 FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
986 log_palette->palVersion = 0x300;
987 log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
988
989 list = FRAME_W32_DISPLAY_INFO (f)->color_list;
990 for (i = 0;
991 i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
992 i++, list = list->next)
993 log_palette->palPalEntry[i] = list->entry;
994
995 new_palette = CreatePalette (log_palette);
996
997 enter_crit ();
998
999 if (FRAME_W32_DISPLAY_INFO (f)->palette)
1000 DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1001 FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
1002
1003 /* Realize display palette and garbage all frames. */
1004 release_frame_dc (f, get_frame_dc (f));
1005
1006 leave_crit ();
1007 }
1008
1009 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1010 #define SET_W32_COLOR(pe, color) \
1011 do \
1012 { \
1013 pe.peRed = GetRValue (color); \
1014 pe.peGreen = GetGValue (color); \
1015 pe.peBlue = GetBValue (color); \
1016 pe.peFlags = 0; \
1017 } while (0)
1018
1019 #if 0
1020 /* Keep these around in case we ever want to track color usage. */
1021 void
1022 w32_map_color (FRAME_PTR f, COLORREF color)
1023 {
1024 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1025
1026 if (NILP (Vw32_enable_palette))
1027 return;
1028
1029 /* check if color is already mapped */
1030 while (list)
1031 {
1032 if (W32_COLOR (list->entry) == color)
1033 {
1034 ++list->refcount;
1035 return;
1036 }
1037 list = list->next;
1038 }
1039
1040 /* not already mapped, so add to list and recreate Windows palette */
1041 list = xmalloc (sizeof (struct w32_palette_entry));
1042 SET_W32_COLOR (list->entry, color);
1043 list->refcount = 1;
1044 list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1045 FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1046 FRAME_W32_DISPLAY_INFO (f)->num_colors++;
1047
1048 /* set flag that palette must be regenerated */
1049 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1050 }
1051
1052 void
1053 w32_unmap_color (FRAME_PTR f, COLORREF color)
1054 {
1055 struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1056 struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
1057
1058 if (NILP (Vw32_enable_palette))
1059 return;
1060
1061 /* check if color is already mapped */
1062 while (list)
1063 {
1064 if (W32_COLOR (list->entry) == color)
1065 {
1066 if (--list->refcount == 0)
1067 {
1068 *prev = list->next;
1069 xfree (list);
1070 FRAME_W32_DISPLAY_INFO (f)->num_colors--;
1071 break;
1072 }
1073 else
1074 return;
1075 }
1076 prev = &list->next;
1077 list = list->next;
1078 }
1079
1080 /* set flag that palette must be regenerated */
1081 FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1082 }
1083 #endif
1084
1085
1086 /* Gamma-correct COLOR on frame F. */
1087
1088 void
1089 gamma_correct (struct frame *f, COLORREF *color)
1090 {
1091 if (f->gamma)
1092 {
1093 *color = PALETTERGB (
1094 pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1095 pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1096 pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
1097 }
1098 }
1099
1100
1101 /* Decide if color named COLOR is valid for the display associated with
1102 the selected frame; if so, return the rgb values in COLOR_DEF.
1103 If ALLOC is nonzero, allocate a new colormap cell. */
1104
1105 int
1106 w32_defined_color (FRAME_PTR f, const char *color, XColor *color_def, int alloc)
1107 {
1108 register Lisp_Object tem;
1109 COLORREF w32_color_ref;
1110
1111 tem = x_to_w32_color (color);
1112
1113 if (!NILP (tem))
1114 {
1115 if (f)
1116 {
1117 /* Apply gamma correction. */
1118 w32_color_ref = XUINT (tem);
1119 gamma_correct (f, &w32_color_ref);
1120 XSETINT (tem, w32_color_ref);
1121 }
1122
1123 /* Map this color to the palette if it is enabled. */
1124 if (!NILP (Vw32_enable_palette))
1125 {
1126 struct w32_palette_entry * entry =
1127 one_w32_display_info.color_list;
1128 struct w32_palette_entry ** prev =
1129 &one_w32_display_info.color_list;
1130
1131 /* check if color is already mapped */
1132 while (entry)
1133 {
1134 if (W32_COLOR (entry->entry) == XUINT (tem))
1135 break;
1136 prev = &entry->next;
1137 entry = entry->next;
1138 }
1139
1140 if (entry == NULL && alloc)
1141 {
1142 /* not already mapped, so add to list */
1143 entry = xmalloc (sizeof (struct w32_palette_entry));
1144 SET_W32_COLOR (entry->entry, XUINT (tem));
1145 entry->next = NULL;
1146 *prev = entry;
1147 one_w32_display_info.num_colors++;
1148
1149 /* set flag that palette must be regenerated */
1150 one_w32_display_info.regen_palette = TRUE;
1151 }
1152 }
1153 /* Ensure COLORREF value is snapped to nearest color in (default)
1154 palette by simulating the PALETTERGB macro. This works whether
1155 or not the display device has a palette. */
1156 w32_color_ref = XUINT (tem) | 0x2000000;
1157
1158 color_def->pixel = w32_color_ref;
1159 color_def->red = GetRValue (w32_color_ref) * 256;
1160 color_def->green = GetGValue (w32_color_ref) * 256;
1161 color_def->blue = GetBValue (w32_color_ref) * 256;
1162
1163 return 1;
1164 }
1165 else
1166 {
1167 return 0;
1168 }
1169 }
1170
1171 /* Given a string ARG naming a color, compute a pixel value from it
1172 suitable for screen F.
1173 If F is not a color screen, return DEF (default) regardless of what
1174 ARG says. */
1175
1176 int
1177 x_decode_color (FRAME_PTR f, Lisp_Object arg, int def)
1178 {
1179 XColor cdef;
1180
1181 CHECK_STRING (arg);
1182
1183 if (strcmp (SDATA (arg), "black") == 0)
1184 return BLACK_PIX_DEFAULT (f);
1185 else if (strcmp (SDATA (arg), "white") == 0)
1186 return WHITE_PIX_DEFAULT (f);
1187
1188 if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
1189 return def;
1190
1191 /* w32_defined_color is responsible for coping with failures
1192 by looking for a near-miss. */
1193 if (w32_defined_color (f, SDATA (arg), &cdef, 1))
1194 return cdef.pixel;
1195
1196 /* defined_color failed; return an ultimate default. */
1197 return def;
1198 }
1199 \f
1200
1201
1202 /* Functions called only from `x_set_frame_param'
1203 to set individual parameters.
1204
1205 If FRAME_W32_WINDOW (f) is 0,
1206 the frame is being created and its window does not exist yet.
1207 In that case, just record the parameter's new value
1208 in the standard place; do not attempt to change the window. */
1209
1210 void
1211 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1212 {
1213 struct w32_output *x = f->output_data.w32;
1214 PIX_TYPE fg, old_fg;
1215
1216 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1217 old_fg = FRAME_FOREGROUND_PIXEL (f);
1218 FRAME_FOREGROUND_PIXEL (f) = fg;
1219
1220 if (FRAME_W32_WINDOW (f) != 0)
1221 {
1222 if (x->cursor_pixel == old_fg)
1223 {
1224 x->cursor_pixel = fg;
1225 x->cursor_gc->background = fg;
1226 }
1227
1228 update_face_from_frame_parameter (f, Qforeground_color, arg);
1229 if (FRAME_VISIBLE_P (f))
1230 redraw_frame (f);
1231 }
1232 }
1233
1234 void
1235 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1236 {
1237 FRAME_BACKGROUND_PIXEL (f)
1238 = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1239
1240 if (FRAME_W32_WINDOW (f) != 0)
1241 {
1242 SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
1243 FRAME_BACKGROUND_PIXEL (f));
1244
1245 update_face_from_frame_parameter (f, Qbackground_color, arg);
1246
1247 if (FRAME_VISIBLE_P (f))
1248 redraw_frame (f);
1249 }
1250 }
1251
1252 void
1253 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1254 {
1255 Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1256 int count;
1257 int mask_color;
1258
1259 if (!EQ (Qnil, arg))
1260 f->output_data.w32->mouse_pixel
1261 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1262 mask_color = FRAME_BACKGROUND_PIXEL (f);
1263
1264 /* Don't let pointers be invisible. */
1265 if (mask_color == f->output_data.w32->mouse_pixel
1266 && mask_color == FRAME_BACKGROUND_PIXEL (f))
1267 f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
1268
1269 #if 0 /* TODO : Mouse cursor customization. */
1270 block_input ();
1271
1272 /* It's not okay to crash if the user selects a screwy cursor. */
1273 count = x_catch_errors (FRAME_W32_DISPLAY (f));
1274
1275 if (!EQ (Qnil, Vx_pointer_shape))
1276 {
1277 CHECK_NUMBER (Vx_pointer_shape);
1278 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
1279 }
1280 else
1281 cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1282 x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
1283
1284 if (!EQ (Qnil, Vx_nontext_pointer_shape))
1285 {
1286 CHECK_NUMBER (Vx_nontext_pointer_shape);
1287 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1288 XINT (Vx_nontext_pointer_shape));
1289 }
1290 else
1291 nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
1292 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1293
1294 if (!EQ (Qnil, Vx_hourglass_pointer_shape))
1295 {
1296 CHECK_NUMBER (Vx_hourglass_pointer_shape);
1297 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1298 XINT (Vx_hourglass_pointer_shape));
1299 }
1300 else
1301 hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
1302 x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
1303
1304 x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1305 if (!EQ (Qnil, Vx_mode_pointer_shape))
1306 {
1307 CHECK_NUMBER (Vx_mode_pointer_shape);
1308 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1309 XINT (Vx_mode_pointer_shape));
1310 }
1311 else
1312 mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1313 x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
1314
1315 if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1316 {
1317 CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1318 hand_cursor
1319 = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1320 XINT (Vx_sensitive_text_pointer_shape));
1321 }
1322 else
1323 hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
1324
1325 if (!NILP (Vx_window_horizontal_drag_shape))
1326 {
1327 CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1328 horizontal_drag_cursor
1329 = XCreateFontCursor (FRAME_X_DISPLAY (f),
1330 XINT (Vx_window_horizontal_drag_shape));
1331 }
1332 else
1333 horizontal_drag_cursor
1334 = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
1335
1336 /* Check and report errors with the above calls. */
1337 x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
1338 x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
1339
1340 {
1341 XColor fore_color, back_color;
1342
1343 fore_color.pixel = f->output_data.w32->mouse_pixel;
1344 back_color.pixel = mask_color;
1345 XQueryColor (FRAME_W32_DISPLAY (f),
1346 DefaultColormap (FRAME_W32_DISPLAY (f),
1347 DefaultScreen (FRAME_W32_DISPLAY (f))),
1348 &fore_color);
1349 XQueryColor (FRAME_W32_DISPLAY (f),
1350 DefaultColormap (FRAME_W32_DISPLAY (f),
1351 DefaultScreen (FRAME_W32_DISPLAY (f))),
1352 &back_color);
1353 XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
1354 &fore_color, &back_color);
1355 XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
1356 &fore_color, &back_color);
1357 XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
1358 &fore_color, &back_color);
1359 XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor,
1360 &fore_color, &back_color);
1361 XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
1362 &fore_color, &back_color);
1363 }
1364
1365 if (FRAME_W32_WINDOW (f) != 0)
1366 XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
1367
1368 if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
1369 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
1370 f->output_data.w32->text_cursor = cursor;
1371
1372 if (nontext_cursor != f->output_data.w32->nontext_cursor
1373 && f->output_data.w32->nontext_cursor != 0)
1374 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
1375 f->output_data.w32->nontext_cursor = nontext_cursor;
1376
1377 if (hourglass_cursor != f->output_data.w32->hourglass_cursor
1378 && f->output_data.w32->hourglass_cursor != 0)
1379 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
1380 f->output_data.w32->hourglass_cursor = hourglass_cursor;
1381
1382 if (mode_cursor != f->output_data.w32->modeline_cursor
1383 && f->output_data.w32->modeline_cursor != 0)
1384 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
1385 f->output_data.w32->modeline_cursor = mode_cursor;
1386
1387 if (hand_cursor != f->output_data.w32->hand_cursor
1388 && f->output_data.w32->hand_cursor != 0)
1389 XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor);
1390 f->output_data.w32->hand_cursor = hand_cursor;
1391
1392 XFlush (FRAME_W32_DISPLAY (f));
1393 unblock_input ();
1394
1395 update_face_from_frame_parameter (f, Qmouse_color, arg);
1396 #endif /* TODO */
1397 }
1398
1399 void
1400 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1401 {
1402 unsigned long fore_pixel, pixel;
1403
1404 if (!NILP (Vx_cursor_fore_pixel))
1405 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1406 WHITE_PIX_DEFAULT (f));
1407 else
1408 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1409
1410 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1411
1412 /* Make sure that the cursor color differs from the background color. */
1413 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1414 {
1415 pixel = f->output_data.w32->mouse_pixel;
1416 if (pixel == fore_pixel)
1417 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1418 }
1419
1420 f->output_data.w32->cursor_foreground_pixel = fore_pixel;
1421 f->output_data.w32->cursor_pixel = pixel;
1422
1423 if (FRAME_W32_WINDOW (f) != 0)
1424 {
1425 block_input ();
1426 /* Update frame's cursor_gc. */
1427 f->output_data.w32->cursor_gc->foreground = fore_pixel;
1428 f->output_data.w32->cursor_gc->background = pixel;
1429
1430 unblock_input ();
1431
1432 if (FRAME_VISIBLE_P (f))
1433 {
1434 x_update_cursor (f, 0);
1435 x_update_cursor (f, 1);
1436 }
1437 }
1438
1439 update_face_from_frame_parameter (f, Qcursor_color, arg);
1440 }
1441
1442 /* Set the border-color of frame F to pixel value PIX.
1443 Note that this does not fully take effect if done before
1444 F has a window. */
1445
1446 void
1447 x_set_border_pixel (struct frame *f, int pix)
1448 {
1449
1450 f->output_data.w32->border_pixel = pix;
1451
1452 if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0)
1453 {
1454 if (FRAME_VISIBLE_P (f))
1455 redraw_frame (f);
1456 }
1457 }
1458
1459 /* Set the border-color of frame F to value described by ARG.
1460 ARG can be a string naming a color.
1461 The border-color is used for the border that is drawn by the server.
1462 Note that this does not fully take effect if done before
1463 F has a window; it must be redone when the window is created. */
1464
1465 void
1466 x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1467 {
1468 int pix;
1469
1470 CHECK_STRING (arg);
1471 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1472 x_set_border_pixel (f, pix);
1473 update_face_from_frame_parameter (f, Qborder_color, arg);
1474 }
1475
1476
1477 void
1478 x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
1479 {
1480 set_frame_cursor_types (f, arg);
1481
1482 /* Make sure the cursor gets redrawn. */
1483 cursor_type_changed = 1;
1484 }
1485 \f
1486 void
1487 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1488 {
1489 int result;
1490
1491 if (NILP (arg) && NILP (oldval))
1492 return;
1493
1494 if (STRINGP (arg) && STRINGP (oldval)
1495 && EQ (Fstring_equal (oldval, arg), Qt))
1496 return;
1497
1498 if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
1499 return;
1500
1501 block_input ();
1502
1503 result = x_bitmap_icon (f, arg);
1504 if (result)
1505 {
1506 unblock_input ();
1507 error ("No icon window available");
1508 }
1509
1510 unblock_input ();
1511 }
1512
1513 void
1514 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1515 {
1516 if (STRINGP (arg))
1517 {
1518 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1519 return;
1520 }
1521 else if (!NILP (arg) || NILP (oldval))
1522 return;
1523
1524 fset_icon_name (f, arg);
1525
1526 #if 0
1527 if (f->output_data.w32->icon_bitmap != 0)
1528 return;
1529
1530 block_input ();
1531
1532 result = x_text_icon (f,
1533 SSDATA ((!NILP (f->icon_name)
1534 ? f->icon_name
1535 : !NILP (f->title)
1536 ? f->title
1537 : f->name)));
1538
1539 if (result)
1540 {
1541 unblock_input ();
1542 error ("No icon window available");
1543 }
1544
1545 /* If the window was unmapped (and its icon was mapped),
1546 the new icon is not mapped, so map the window in its stead. */
1547 if (FRAME_VISIBLE_P (f))
1548 {
1549 #ifdef USE_X_TOOLKIT
1550 XtPopup (f->output_data.w32->widget, XtGrabNone);
1551 #endif
1552 XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
1553 }
1554
1555 XFlush (FRAME_W32_DISPLAY (f));
1556 unblock_input ();
1557 #endif
1558 }
1559
1560 \f
1561 void
1562 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1563 {
1564 int nlines;
1565
1566 /* Right now, menu bars don't work properly in minibuf-only frames;
1567 most of the commands try to apply themselves to the minibuffer
1568 frame itself, and get an error because you can't switch buffers
1569 in or split the minibuffer window. */
1570 if (FRAME_MINIBUF_ONLY_P (f))
1571 return;
1572
1573 if (INTEGERP (value))
1574 nlines = XINT (value);
1575 else
1576 nlines = 0;
1577
1578 FRAME_MENU_BAR_LINES (f) = 0;
1579 if (nlines)
1580 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1581 else
1582 {
1583 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1584 free_frame_menubar (f);
1585 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1586
1587 /* Adjust the frame size so that the client (text) dimensions
1588 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1589 set correctly. */
1590 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
1591 do_pending_window_change (0);
1592 }
1593 adjust_glyphs (f);
1594 }
1595
1596
1597 /* Set the number of lines used for the tool bar of frame F to VALUE.
1598 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1599 is the old number of tool bar lines. This function changes the
1600 height of all windows on frame F to match the new tool bar height.
1601 The frame's height doesn't change. */
1602
1603 void
1604 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1605 {
1606 int delta, nlines, root_height;
1607 Lisp_Object root_window;
1608
1609 /* Treat tool bars like menu bars. */
1610 if (FRAME_MINIBUF_ONLY_P (f))
1611 return;
1612
1613 /* Use VALUE only if an integer >= 0. */
1614 if (INTEGERP (value) && XINT (value) >= 0)
1615 nlines = XFASTINT (value);
1616 else
1617 nlines = 0;
1618
1619 /* Make sure we redisplay all windows in this frame. */
1620 ++windows_or_buffers_changed;
1621
1622 delta = nlines - FRAME_TOOL_BAR_LINES (f);
1623
1624 /* Don't resize the tool-bar to more than we have room for. */
1625 root_window = FRAME_ROOT_WINDOW (f);
1626 root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
1627 if (root_height - delta < 1)
1628 {
1629 delta = root_height - 1;
1630 nlines = FRAME_TOOL_BAR_LINES (f) + delta;
1631 }
1632
1633 FRAME_TOOL_BAR_LINES (f) = nlines;
1634 resize_frame_windows (f, FRAME_LINES (f), 0);
1635 adjust_glyphs (f);
1636
1637 /* We also have to make sure that the internal border at the top of
1638 the frame, below the menu bar or tool bar, is redrawn when the
1639 tool bar disappears. This is so because the internal border is
1640 below the tool bar if one is displayed, but is below the menu bar
1641 if there isn't a tool bar. The tool bar draws into the area
1642 below the menu bar. */
1643 if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
1644 {
1645 clear_frame (f);
1646 clear_current_matrices (f);
1647 }
1648
1649 /* If the tool bar gets smaller, the internal border below it
1650 has to be cleared. It was formerly part of the display
1651 of the larger tool bar, and updating windows won't clear it. */
1652 if (delta < 0)
1653 {
1654 int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1655 int width = FRAME_PIXEL_WIDTH (f);
1656 int y = nlines * FRAME_LINE_HEIGHT (f);
1657
1658 block_input ();
1659 {
1660 HDC hdc = get_frame_dc (f);
1661 w32_clear_area (f, hdc, 0, y, width, height);
1662 release_frame_dc (f, hdc);
1663 }
1664 unblock_input ();
1665
1666 if (WINDOWP (f->tool_bar_window))
1667 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1668 }
1669
1670 run_window_configuration_change_hook (f);
1671
1672 }
1673
1674
1675 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1676 w32_id_name.
1677
1678 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1679 name; if NAME is a string, set F's name to NAME and set
1680 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1681
1682 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1683 suggesting a new name, which lisp code should override; if
1684 F->explicit_name is set, ignore the new name; otherwise, set it. */
1685
1686 void
1687 x_set_name (struct frame *f, Lisp_Object name, int explicit)
1688 {
1689 /* Make sure that requests from lisp code override requests from
1690 Emacs redisplay code. */
1691 if (explicit)
1692 {
1693 /* If we're switching from explicit to implicit, we had better
1694 update the mode lines and thereby update the title. */
1695 if (f->explicit_name && NILP (name))
1696 update_mode_lines = 1;
1697
1698 f->explicit_name = ! NILP (name);
1699 }
1700 else if (f->explicit_name)
1701 return;
1702
1703 /* If NAME is nil, set the name to the w32_id_name. */
1704 if (NILP (name))
1705 {
1706 /* Check for no change needed in this very common case
1707 before we do any consing. */
1708 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
1709 SDATA (f->name)))
1710 return;
1711 name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
1712 }
1713 else
1714 CHECK_STRING (name);
1715
1716 /* Don't change the name if it's already NAME. */
1717 if (! NILP (Fstring_equal (name, f->name)))
1718 return;
1719
1720 fset_name (f, name);
1721
1722 /* For setting the frame title, the title parameter should override
1723 the name parameter. */
1724 if (! NILP (f->title))
1725 name = f->title;
1726
1727 if (FRAME_W32_WINDOW (f))
1728 {
1729 if (STRING_MULTIBYTE (name))
1730 name = ENCODE_SYSTEM (name);
1731
1732 block_input ();
1733 SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
1734 unblock_input ();
1735 }
1736 }
1737
1738 /* This function should be called when the user's lisp code has
1739 specified a name for the frame; the name will override any set by the
1740 redisplay code. */
1741 void
1742 x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
1743 {
1744 x_set_name (f, arg, 1);
1745 }
1746
1747 /* This function should be called by Emacs redisplay code to set the
1748 name; names set this way will never override names set by the user's
1749 lisp code. */
1750 void
1751 x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
1752 {
1753 x_set_name (f, arg, 0);
1754 }
1755 \f
1756 /* Change the title of frame F to NAME.
1757 If NAME is nil, use the frame name as the title. */
1758
1759 void
1760 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
1761 {
1762 /* Don't change the title if it's already NAME. */
1763 if (EQ (name, f->title))
1764 return;
1765
1766 update_mode_lines = 1;
1767
1768 fset_title (f, name);
1769
1770 if (NILP (name))
1771 name = f->name;
1772
1773 if (FRAME_W32_WINDOW (f))
1774 {
1775 if (STRING_MULTIBYTE (name))
1776 name = ENCODE_SYSTEM (name);
1777
1778 block_input ();
1779 SetWindowText (FRAME_W32_WINDOW (f), SDATA (name));
1780 unblock_input ();
1781 }
1782 }
1783
1784 void
1785 x_set_scroll_bar_default_width (struct frame *f)
1786 {
1787 int wid = FRAME_COLUMN_WIDTH (f);
1788
1789 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
1790 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
1791 wid - 1) / wid;
1792 }
1793
1794 \f
1795 /* Subroutines for creating a frame. */
1796
1797 Cursor
1798 w32_load_cursor (LPCTSTR name)
1799 {
1800 /* Try first to load cursor from application resource. */
1801 Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle (NULL),
1802 name, IMAGE_CURSOR, 0, 0,
1803 LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
1804 if (!cursor)
1805 {
1806 /* Then try to load a shared predefined cursor. */
1807 cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
1808 LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
1809 }
1810 return cursor;
1811 }
1812
1813 static LRESULT CALLBACK w32_wnd_proc (HWND, UINT, WPARAM, LPARAM);
1814
1815 #define INIT_WINDOW_CLASS(WC) \
1816 (WC).style = CS_HREDRAW | CS_VREDRAW; \
1817 (WC).lpfnWndProc = (WNDPROC) w32_wnd_proc; \
1818 (WC).cbClsExtra = 0; \
1819 (WC).cbWndExtra = WND_EXTRA_BYTES; \
1820 (WC).hInstance = hinst; \
1821 (WC).hIcon = LoadIcon (hinst, EMACS_CLASS); \
1822 (WC).hCursor = w32_load_cursor (IDC_ARROW); \
1823 (WC).hbrBackground = NULL; \
1824 (WC).lpszMenuName = NULL; \
1825
1826 static BOOL
1827 w32_init_class (HINSTANCE hinst)
1828 {
1829
1830 if (w32_unicode_gui)
1831 {
1832 WNDCLASSW uwc;
1833 INIT_WINDOW_CLASS(uwc);
1834 uwc.lpszClassName = L"Emacs";
1835
1836 return RegisterClassW (&uwc);
1837 }
1838 else
1839 {
1840 WNDCLASS wc;
1841 INIT_WINDOW_CLASS(wc);
1842 wc.lpszClassName = EMACS_CLASS;
1843
1844 return RegisterClassA (&wc);
1845 }
1846 }
1847
1848 static HWND
1849 w32_createscrollbar (struct frame *f, struct scroll_bar * bar)
1850 {
1851 return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
1852 /* Position and size of scroll bar. */
1853 XINT (bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
1854 XINT (bar->top),
1855 XINT (bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
1856 XINT (bar->height),
1857 FRAME_W32_WINDOW (f),
1858 NULL,
1859 hinst,
1860 NULL));
1861 }
1862
1863 static void
1864 w32_createwindow (struct frame *f)
1865 {
1866 HWND hwnd;
1867 RECT rect;
1868 Lisp_Object top = Qunbound;
1869 Lisp_Object left = Qunbound;
1870 struct w32_display_info *dpyinfo = &one_w32_display_info;
1871
1872 rect.left = rect.top = 0;
1873 rect.right = FRAME_PIXEL_WIDTH (f);
1874 rect.bottom = FRAME_PIXEL_HEIGHT (f);
1875
1876 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
1877 FRAME_EXTERNAL_MENU_BAR (f));
1878
1879 /* Do first time app init */
1880
1881 w32_init_class (hinst);
1882
1883 if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
1884 {
1885 XSETINT (left, f->left_pos);
1886 XSETINT (top, f->top_pos);
1887 }
1888 else if (EQ (left, Qunbound) && EQ (top, Qunbound))
1889 {
1890 /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
1891 for anything that is not a number and is not Qunbound. */
1892 left = x_get_arg (dpyinfo, Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
1893 top = x_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
1894 }
1895
1896 FRAME_W32_WINDOW (f) = hwnd
1897 = CreateWindow (EMACS_CLASS,
1898 f->namebuf,
1899 f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
1900 EQ (left, Qunbound) ? CW_USEDEFAULT : XINT (left),
1901 EQ (top, Qunbound) ? CW_USEDEFAULT : XINT (top),
1902 rect.right - rect.left,
1903 rect.bottom - rect.top,
1904 NULL,
1905 NULL,
1906 hinst,
1907 NULL);
1908
1909 if (hwnd)
1910 {
1911 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
1912 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
1913 SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
1914 SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
1915 SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
1916
1917 /* Enable drag-n-drop. */
1918 DragAcceptFiles (hwnd, TRUE);
1919
1920 /* Do this to discard the default setting specified by our parent. */
1921 ShowWindow (hwnd, SW_HIDE);
1922
1923 /* Update frame positions. */
1924 GetWindowRect (hwnd, &rect);
1925 f->left_pos = rect.left;
1926 f->top_pos = rect.top;
1927 }
1928 }
1929
1930 static void
1931 my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1932 {
1933 wmsg->msg.hwnd = hwnd;
1934 wmsg->msg.message = msg;
1935 wmsg->msg.wParam = wParam;
1936 wmsg->msg.lParam = lParam;
1937 wmsg->msg.time = GetMessageTime ();
1938
1939 post_msg (wmsg);
1940 }
1941
1942 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
1943 between left and right keys as advertised. We test for this
1944 support dynamically, and set a flag when the support is absent. If
1945 absent, we keep track of the left and right control and alt keys
1946 ourselves. This is particularly necessary on keyboards that rely
1947 upon the AltGr key, which is represented as having the left control
1948 and right alt keys pressed. For these keyboards, we need to know
1949 when the left alt key has been pressed in addition to the AltGr key
1950 so that we can properly support M-AltGr-key sequences (such as M-@
1951 on Swedish keyboards). */
1952
1953 #define EMACS_LCONTROL 0
1954 #define EMACS_RCONTROL 1
1955 #define EMACS_LMENU 2
1956 #define EMACS_RMENU 3
1957
1958 static int modifiers[4];
1959 static int modifiers_recorded;
1960 static int modifier_key_support_tested;
1961
1962 static void
1963 test_modifier_support (unsigned int wparam)
1964 {
1965 unsigned int l, r;
1966
1967 if (wparam != VK_CONTROL && wparam != VK_MENU)
1968 return;
1969 if (wparam == VK_CONTROL)
1970 {
1971 l = VK_LCONTROL;
1972 r = VK_RCONTROL;
1973 }
1974 else
1975 {
1976 l = VK_LMENU;
1977 r = VK_RMENU;
1978 }
1979 if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
1980 modifiers_recorded = 1;
1981 else
1982 modifiers_recorded = 0;
1983 modifier_key_support_tested = 1;
1984 }
1985
1986 static void
1987 record_keydown (unsigned int wparam, unsigned int lparam)
1988 {
1989 int i;
1990
1991 if (!modifier_key_support_tested)
1992 test_modifier_support (wparam);
1993
1994 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
1995 return;
1996
1997 if (wparam == VK_CONTROL)
1998 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
1999 else
2000 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2001
2002 modifiers[i] = 1;
2003 }
2004
2005 static void
2006 record_keyup (unsigned int wparam, unsigned int lparam)
2007 {
2008 int i;
2009
2010 if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
2011 return;
2012
2013 if (wparam == VK_CONTROL)
2014 i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
2015 else
2016 i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2017
2018 modifiers[i] = 0;
2019 }
2020
2021 /* Emacs can lose focus while a modifier key has been pressed. When
2022 it regains focus, be conservative and clear all modifiers since
2023 we cannot reconstruct the left and right modifier state. */
2024 static void
2025 reset_modifiers (void)
2026 {
2027 SHORT ctrl, alt;
2028
2029 if (GetFocus () == NULL)
2030 /* Emacs doesn't have keyboard focus. Do nothing. */
2031 return;
2032
2033 ctrl = GetAsyncKeyState (VK_CONTROL);
2034 alt = GetAsyncKeyState (VK_MENU);
2035
2036 if (!(ctrl & 0x08000))
2037 /* Clear any recorded control modifier state. */
2038 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
2039
2040 if (!(alt & 0x08000))
2041 /* Clear any recorded alt modifier state. */
2042 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
2043
2044 /* Update the state of all modifier keys, because modifiers used in
2045 hot-key combinations can get stuck on if Emacs loses focus as a
2046 result of a hot-key being pressed. */
2047 {
2048 BYTE keystate[256];
2049
2050 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2051
2052 GetKeyboardState (keystate);
2053 keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
2054 keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
2055 keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
2056 keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
2057 keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
2058 keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
2059 keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
2060 keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
2061 keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
2062 keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
2063 SetKeyboardState (keystate);
2064 }
2065 }
2066
2067 /* Synchronize modifier state with what is reported with the current
2068 keystroke. Even if we cannot distinguish between left and right
2069 modifier keys, we know that, if no modifiers are set, then neither
2070 the left or right modifier should be set. */
2071 static void
2072 sync_modifiers (void)
2073 {
2074 if (!modifiers_recorded)
2075 return;
2076
2077 if (!(GetKeyState (VK_CONTROL) & 0x8000))
2078 modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
2079
2080 if (!(GetKeyState (VK_MENU) & 0x8000))
2081 modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
2082 }
2083
2084 static int
2085 modifier_set (int vkey)
2086 {
2087 if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
2088 return (GetKeyState (vkey) & 0x1);
2089 if (!modifiers_recorded)
2090 return (GetKeyState (vkey) & 0x8000);
2091
2092 switch (vkey)
2093 {
2094 case VK_LCONTROL:
2095 return modifiers[EMACS_LCONTROL];
2096 case VK_RCONTROL:
2097 return modifiers[EMACS_RCONTROL];
2098 case VK_LMENU:
2099 return modifiers[EMACS_LMENU];
2100 case VK_RMENU:
2101 return modifiers[EMACS_RMENU];
2102 }
2103 return (GetKeyState (vkey) & 0x8000);
2104 }
2105
2106 /* Convert between the modifier bits W32 uses and the modifier bits
2107 Emacs uses. */
2108
2109 unsigned int
2110 w32_key_to_modifier (int key)
2111 {
2112 Lisp_Object key_mapping;
2113
2114 switch (key)
2115 {
2116 case VK_LWIN:
2117 key_mapping = Vw32_lwindow_modifier;
2118 break;
2119 case VK_RWIN:
2120 key_mapping = Vw32_rwindow_modifier;
2121 break;
2122 case VK_APPS:
2123 key_mapping = Vw32_apps_modifier;
2124 break;
2125 case VK_SCROLL:
2126 key_mapping = Vw32_scroll_lock_modifier;
2127 break;
2128 default:
2129 key_mapping = Qnil;
2130 }
2131
2132 /* NB. This code runs in the input thread, asynchronously to the lisp
2133 thread, so we must be careful to ensure access to lisp data is
2134 thread-safe. The following code is safe because the modifier
2135 variable values are updated atomically from lisp and symbols are
2136 not relocated by GC. Also, we don't have to worry about seeing GC
2137 markbits here. */
2138 if (EQ (key_mapping, Qhyper))
2139 return hyper_modifier;
2140 if (EQ (key_mapping, Qsuper))
2141 return super_modifier;
2142 if (EQ (key_mapping, Qmeta))
2143 return meta_modifier;
2144 if (EQ (key_mapping, Qalt))
2145 return alt_modifier;
2146 if (EQ (key_mapping, Qctrl))
2147 return ctrl_modifier;
2148 if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
2149 return ctrl_modifier;
2150 if (EQ (key_mapping, Qshift))
2151 return shift_modifier;
2152
2153 /* Don't generate any modifier if not explicitly requested. */
2154 return 0;
2155 }
2156
2157 static unsigned int
2158 w32_get_modifiers (void)
2159 {
2160 return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) |
2161 (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) |
2162 (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) |
2163 (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) |
2164 (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) |
2165 (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) |
2166 (modifier_set (VK_MENU) ?
2167 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
2168 }
2169
2170 /* We map the VK_* modifiers into console modifier constants
2171 so that we can use the same routines to handle both console
2172 and window input. */
2173
2174 static int
2175 construct_console_modifiers (void)
2176 {
2177 int mods;
2178
2179 mods = 0;
2180 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
2181 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
2182 mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
2183 mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
2184 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
2185 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
2186 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
2187 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
2188 mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
2189 mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
2190 mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
2191
2192 return mods;
2193 }
2194
2195 static int
2196 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
2197 {
2198 int mods;
2199
2200 /* Convert to emacs modifiers. */
2201 mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
2202
2203 return mods;
2204 }
2205
2206 unsigned int
2207 map_keypad_keys (unsigned int virt_key, unsigned int extended)
2208 {
2209 if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
2210 return virt_key;
2211
2212 if (virt_key == VK_RETURN)
2213 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
2214
2215 if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
2216 return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
2217
2218 if (virt_key == VK_INSERT || virt_key == VK_DELETE)
2219 return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
2220
2221 if (virt_key == VK_CLEAR)
2222 return (!extended ? VK_NUMPAD_CLEAR : virt_key);
2223
2224 return virt_key;
2225 }
2226
2227 /* List of special key combinations which w32 would normally capture,
2228 but Emacs should grab instead. Not directly visible to lisp, to
2229 simplify synchronization. Each item is an integer encoding a virtual
2230 key code and modifier combination to capture. */
2231 static Lisp_Object w32_grabbed_keys;
2232
2233 #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8))
2234 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2235 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2236 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2237
2238 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2239 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2240 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2241
2242 /* Register hot-keys for reserved key combinations when Emacs has
2243 keyboard focus, since this is the only way Emacs can receive key
2244 combinations like Alt-Tab which are used by the system. */
2245
2246 static void
2247 register_hot_keys (HWND hwnd)
2248 {
2249 Lisp_Object keylist;
2250
2251 /* Use CONSP, since we are called asynchronously. */
2252 for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
2253 {
2254 Lisp_Object key = XCAR (keylist);
2255
2256 /* Deleted entries get set to nil. */
2257 if (!INTEGERP (key))
2258 continue;
2259
2260 RegisterHotKey (hwnd, HOTKEY_ID (key),
2261 HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
2262 }
2263 }
2264
2265 static void
2266 unregister_hot_keys (HWND hwnd)
2267 {
2268 Lisp_Object keylist;
2269
2270 for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
2271 {
2272 Lisp_Object key = XCAR (keylist);
2273
2274 if (!INTEGERP (key))
2275 continue;
2276
2277 UnregisterHotKey (hwnd, HOTKEY_ID (key));
2278 }
2279 }
2280
2281 #if EMACSDEBUG
2282 const char*
2283 w32_name_of_message (UINT msg)
2284 {
2285 unsigned i;
2286 static char buf[64];
2287 static const struct {
2288 UINT msg;
2289 const char* name;
2290 } msgnames[] = {
2291 #define M(msg) { msg, # msg }
2292 M (WM_PAINT),
2293 M (WM_TIMER),
2294 M (WM_USER),
2295 M (WM_MOUSEMOVE),
2296 M (WM_LBUTTONUP),
2297 M (WM_KEYDOWN),
2298 M (WM_EMACS_KILL),
2299 M (WM_EMACS_CREATEWINDOW),
2300 M (WM_EMACS_DONE),
2301 M (WM_EMACS_CREATESCROLLBAR),
2302 M (WM_EMACS_SHOWWINDOW),
2303 M (WM_EMACS_SETWINDOWPOS),
2304 M (WM_EMACS_DESTROYWINDOW),
2305 M (WM_EMACS_TRACKPOPUPMENU),
2306 M (WM_EMACS_SETFOCUS),
2307 M (WM_EMACS_SETFOREGROUND),
2308 M (WM_EMACS_SETLOCALE),
2309 M (WM_EMACS_SETKEYBOARDLAYOUT),
2310 M (WM_EMACS_REGISTER_HOT_KEY),
2311 M (WM_EMACS_UNREGISTER_HOT_KEY),
2312 M (WM_EMACS_TOGGLE_LOCK_KEY),
2313 M (WM_EMACS_TRACK_CARET),
2314 M (WM_EMACS_DESTROY_CARET),
2315 M (WM_EMACS_SHOW_CARET),
2316 M (WM_EMACS_HIDE_CARET),
2317 M (WM_EMACS_SETCURSOR),
2318 M (WM_EMACS_PAINT),
2319 M (WM_CHAR),
2320 #undef M
2321 { 0, 0 }
2322 };
2323
2324 for (i = 0; msgnames[i].name; ++i)
2325 if (msgnames[i].msg == msg)
2326 return msgnames[i].name;
2327
2328 sprintf (buf, "message 0x%04x", (unsigned)msg);
2329 return buf;
2330 }
2331 #endif /* EMACSDEBUG */
2332
2333 /* Here's an overview of how Emacs input works on MS-Windows.
2334
2335 System messages are read and processed by w32_msg_pump below. This
2336 function runs in a separate thread. It handles a small number of
2337 custom WM_EMACS_* messages (posted by the main thread, look for
2338 PostMessage calls), and dispatches the rest to w32_wnd_proc, which
2339 is the main window procedure for the entire Emacs application.
2340
2341 w32_wnd_proc also runs in the same separate input thread. It
2342 handles some messages, mostly those that need GDI calls, by itself.
2343 For the others, it calls my_post_msg, which inserts the messages
2344 into the input queue serviced by w32_read_socket.
2345
2346 w32_read_socket runs in the main (a.k.a. "Lisp") thread, and is
2347 called synchronously from keyboard.c when it is known or suspected
2348 that some input is available. w32_read_socket either handles
2349 messages immediately, or converts them into Emacs input events and
2350 stuffs them into kbd_buffer, where kbd_buffer_get_event can get at
2351 them and process them when read_char and its callers require
2352 input.
2353
2354 Under Cygwin with the W32 toolkit, the use of /dev/windows with
2355 select(2) takes the place of w32_read_socket.
2356
2357 */
2358
2359 /* Main message dispatch loop. */
2360
2361 static void
2362 w32_msg_pump (deferred_msg * msg_buf)
2363 {
2364 MSG msg;
2365 WPARAM result;
2366 HWND focus_window;
2367
2368 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
2369
2370 while ((w32_unicode_gui ? GetMessageW : GetMessageA) (&msg, NULL, 0, 0))
2371 {
2372
2373 /* DebPrint (("w32_msg_pump: %s time:%u\n", */
2374 /* w32_name_of_message (msg.message), msg.time)); */
2375
2376 if (msg.hwnd == NULL)
2377 {
2378 switch (msg.message)
2379 {
2380 case WM_NULL:
2381 /* Produced by complete_deferred_msg; just ignore. */
2382 break;
2383 case WM_EMACS_CREATEWINDOW:
2384 /* Initialize COM for this window. Even though we don't use it,
2385 some third party shell extensions can cause it to be used in
2386 system dialogs, which causes a crash if it is not initialized.
2387 This is a known bug in Windows, which was fixed long ago, but
2388 the patch for XP is not publicly available until XP SP3,
2389 and older versions will never be patched. */
2390 CoInitialize (NULL);
2391 w32_createwindow ((struct frame *) msg.wParam);
2392 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2393 emacs_abort ();
2394 break;
2395 case WM_EMACS_SETLOCALE:
2396 SetThreadLocale (msg.wParam);
2397 /* Reply is not expected. */
2398 break;
2399 case WM_EMACS_SETKEYBOARDLAYOUT:
2400 result = (WPARAM) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
2401 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
2402 result, 0))
2403 emacs_abort ();
2404 break;
2405 case WM_EMACS_REGISTER_HOT_KEY:
2406 focus_window = GetFocus ();
2407 if (focus_window != NULL)
2408 RegisterHotKey (focus_window,
2409 RAW_HOTKEY_ID (msg.wParam),
2410 RAW_HOTKEY_MODIFIERS (msg.wParam),
2411 RAW_HOTKEY_VK_CODE (msg.wParam));
2412 /* Reply is not expected. */
2413 break;
2414 case WM_EMACS_UNREGISTER_HOT_KEY:
2415 focus_window = GetFocus ();
2416 if (focus_window != NULL)
2417 UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam));
2418 /* Mark item as erased. NB: this code must be
2419 thread-safe. The next line is okay because the cons
2420 cell is never made into garbage and is not relocated by
2421 GC. */
2422 XSETCAR ((Lisp_Object) ((EMACS_INT) msg.lParam), Qnil);
2423 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2424 emacs_abort ();
2425 break;
2426 case WM_EMACS_TOGGLE_LOCK_KEY:
2427 {
2428 int vk_code = (int) msg.wParam;
2429 int cur_state = (GetKeyState (vk_code) & 1);
2430 Lisp_Object new_state = (Lisp_Object) ((EMACS_INT) msg.lParam);
2431
2432 /* NB: This code must be thread-safe. It is safe to
2433 call NILP because symbols are not relocated by GC,
2434 and pointer here is not touched by GC (so the markbit
2435 can't be set). Numbers are safe because they are
2436 immediate values. */
2437 if (NILP (new_state)
2438 || (NUMBERP (new_state)
2439 && ((XUINT (new_state)) & 1) != cur_state))
2440 {
2441 one_w32_display_info.faked_key = vk_code;
2442
2443 keybd_event ((BYTE) vk_code,
2444 (BYTE) MapVirtualKey (vk_code, 0),
2445 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2446 keybd_event ((BYTE) vk_code,
2447 (BYTE) MapVirtualKey (vk_code, 0),
2448 KEYEVENTF_EXTENDEDKEY | 0, 0);
2449 keybd_event ((BYTE) vk_code,
2450 (BYTE) MapVirtualKey (vk_code, 0),
2451 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2452 cur_state = !cur_state;
2453 }
2454 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
2455 cur_state, 0))
2456 emacs_abort ();
2457 }
2458 break;
2459 #ifdef MSG_DEBUG
2460 /* Broadcast messages make it here, so you need to be looking
2461 for something in particular for this to be useful. */
2462 default:
2463 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
2464 #endif
2465 }
2466 }
2467 else
2468 {
2469 if (w32_unicode_gui)
2470 DispatchMessageW (&msg);
2471 else
2472 DispatchMessageA (&msg);
2473 }
2474
2475 /* Exit nested loop when our deferred message has completed. */
2476 if (msg_buf->completed)
2477 break;
2478 }
2479 }
2480
2481 deferred_msg * deferred_msg_head;
2482
2483 static deferred_msg *
2484 find_deferred_msg (HWND hwnd, UINT msg)
2485 {
2486 deferred_msg * item;
2487
2488 /* Don't actually need synchronization for read access, since
2489 modification of single pointer is always atomic. */
2490 /* enter_crit (); */
2491
2492 for (item = deferred_msg_head; item != NULL; item = item->next)
2493 if (item->w32msg.msg.hwnd == hwnd
2494 && item->w32msg.msg.message == msg)
2495 break;
2496
2497 /* leave_crit (); */
2498
2499 return item;
2500 }
2501
2502 static LRESULT
2503 send_deferred_msg (deferred_msg * msg_buf,
2504 HWND hwnd,
2505 UINT msg,
2506 WPARAM wParam,
2507 LPARAM lParam)
2508 {
2509 /* Only input thread can send deferred messages. */
2510 if (GetCurrentThreadId () != dwWindowsThreadId)
2511 emacs_abort ();
2512
2513 /* It is an error to send a message that is already deferred. */
2514 if (find_deferred_msg (hwnd, msg) != NULL)
2515 emacs_abort ();
2516
2517 /* Enforced synchronization is not needed because this is the only
2518 function that alters deferred_msg_head, and the following critical
2519 section is guaranteed to only be serially reentered (since only the
2520 input thread can call us). */
2521
2522 /* enter_crit (); */
2523
2524 msg_buf->completed = 0;
2525 msg_buf->next = deferred_msg_head;
2526 deferred_msg_head = msg_buf;
2527 my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
2528
2529 /* leave_crit (); */
2530
2531 /* Start a new nested message loop to process other messages until
2532 this one is completed. */
2533 w32_msg_pump (msg_buf);
2534
2535 deferred_msg_head = msg_buf->next;
2536
2537 return msg_buf->result;
2538 }
2539
2540 void
2541 complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
2542 {
2543 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
2544
2545 if (msg_buf == NULL)
2546 /* Message may have been canceled, so don't abort. */
2547 return;
2548
2549 msg_buf->result = result;
2550 msg_buf->completed = 1;
2551
2552 /* Ensure input thread is woken so it notices the completion. */
2553 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
2554 }
2555
2556 static void
2557 cancel_all_deferred_msgs (void)
2558 {
2559 deferred_msg * item;
2560
2561 /* Don't actually need synchronization for read access, since
2562 modification of single pointer is always atomic. */
2563 /* enter_crit (); */
2564
2565 for (item = deferred_msg_head; item != NULL; item = item->next)
2566 {
2567 item->result = 0;
2568 item->completed = 1;
2569 }
2570
2571 /* leave_crit (); */
2572
2573 /* Ensure input thread is woken so it notices the completion. */
2574 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
2575 }
2576
2577 DWORD WINAPI
2578 w32_msg_worker (void *arg)
2579 {
2580 MSG msg;
2581 deferred_msg dummy_buf;
2582
2583 /* Ensure our message queue is created */
2584
2585 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2586
2587 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2588 emacs_abort ();
2589
2590 memset (&dummy_buf, 0, sizeof (dummy_buf));
2591 dummy_buf.w32msg.msg.hwnd = NULL;
2592 dummy_buf.w32msg.msg.message = WM_NULL;
2593
2594 /* This is the initial message loop which should only exit when the
2595 application quits. */
2596 w32_msg_pump (&dummy_buf);
2597
2598 return 0;
2599 }
2600
2601 static void
2602 signal_user_input (void)
2603 {
2604 /* Interrupt any lisp that wants to be interrupted by input. */
2605 if (!NILP (Vthrow_on_input))
2606 {
2607 Vquit_flag = Vthrow_on_input;
2608 /* Doing a QUIT from this thread is a bad idea, since this
2609 unwinds the stack of the Lisp thread, and the Windows runtime
2610 rightfully barfs. Disabled. */
2611 #if 0
2612 /* If we're inside a function that wants immediate quits,
2613 do it now. */
2614 if (immediate_quit && NILP (Vinhibit_quit))
2615 {
2616 immediate_quit = 0;
2617 QUIT;
2618 }
2619 #endif
2620 }
2621 }
2622
2623
2624 static void
2625 post_character_message (HWND hwnd, UINT msg,
2626 WPARAM wParam, LPARAM lParam,
2627 DWORD modifiers)
2628 {
2629 W32Msg wmsg;
2630
2631 wmsg.dwModifiers = modifiers;
2632
2633 /* Detect quit_char and set quit-flag directly. Note that we
2634 still need to post a message to ensure the main thread will be
2635 woken up if blocked in sys_select, but we do NOT want to post
2636 the quit_char message itself (because it will usually be as if
2637 the user had typed quit_char twice). Instead, we post a dummy
2638 message that has no particular effect. */
2639 {
2640 int c = wParam;
2641 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
2642 c = make_ctrl_char (c) & 0377;
2643 if (c == quit_char
2644 || (wmsg.dwModifiers == 0
2645 && w32_quit_key && wParam == w32_quit_key))
2646 {
2647 Vquit_flag = Qt;
2648
2649 /* The choice of message is somewhat arbitrary, as long as
2650 the main thread handler just ignores it. */
2651 msg = WM_NULL;
2652
2653 /* Interrupt any blocking system calls. */
2654 signal_quit ();
2655
2656 /* As a safety precaution, forcibly complete any deferred
2657 messages. This is a kludge, but I don't see any particularly
2658 clean way to handle the situation where a deferred message is
2659 "dropped" in the lisp thread, and will thus never be
2660 completed, eg. by the user trying to activate the menubar
2661 when the lisp thread is busy, and then typing C-g when the
2662 menubar doesn't open promptly (with the result that the
2663 menubar never responds at all because the deferred
2664 WM_INITMENU message is never completed). Another problem
2665 situation is when the lisp thread calls SendMessage (to send
2666 a window manager command) when a message has been deferred;
2667 the lisp thread gets blocked indefinitely waiting for the
2668 deferred message to be completed, which itself is waiting for
2669 the lisp thread to respond.
2670
2671 Note that we don't want to block the input thread waiting for
2672 a response from the lisp thread (although that would at least
2673 solve the deadlock problem above), because we want to be able
2674 to receive C-g to interrupt the lisp thread. */
2675 cancel_all_deferred_msgs ();
2676 }
2677 else
2678 signal_user_input ();
2679 }
2680
2681 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2682 }
2683
2684 /* Main window procedure */
2685
2686 static LRESULT CALLBACK
2687 w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2688 {
2689 struct frame *f;
2690 struct w32_display_info *dpyinfo = &one_w32_display_info;
2691 W32Msg wmsg;
2692 int windows_translate;
2693 int key;
2694
2695 /* Note that it is okay to call x_window_to_frame, even though we are
2696 not running in the main lisp thread, because frame deletion
2697 requires the lisp thread to synchronize with this thread. Thus, if
2698 a frame struct is returned, it can be used without concern that the
2699 lisp thread might make it disappear while we are using it.
2700
2701 NB. Walking the frame list in this thread is safe (as long as
2702 writes of Lisp_Object slots are atomic, which they are on Windows).
2703 Although delete-frame can destructively modify the frame list while
2704 we are walking it, a garbage collection cannot occur until after
2705 delete-frame has synchronized with this thread.
2706
2707 It is also safe to use functions that make GDI calls, such as
2708 w32_clear_rect, because these functions must obtain a DC handle
2709 from the frame struct using get_frame_dc which is thread-aware. */
2710
2711 switch (msg)
2712 {
2713 case WM_ERASEBKGND:
2714 f = x_window_to_frame (dpyinfo, hwnd);
2715 if (f)
2716 {
2717 HDC hdc = get_frame_dc (f);
2718 GetUpdateRect (hwnd, &wmsg.rect, FALSE);
2719 w32_clear_rect (f, hdc, &wmsg.rect);
2720 release_frame_dc (f, hdc);
2721
2722 #if defined (W32_DEBUG_DISPLAY)
2723 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2724 f,
2725 wmsg.rect.left, wmsg.rect.top,
2726 wmsg.rect.right, wmsg.rect.bottom));
2727 #endif /* W32_DEBUG_DISPLAY */
2728 }
2729 return 1;
2730 case WM_PALETTECHANGED:
2731 /* ignore our own changes */
2732 if ((HWND)wParam != hwnd)
2733 {
2734 f = x_window_to_frame (dpyinfo, hwnd);
2735 if (f)
2736 /* get_frame_dc will realize our palette and force all
2737 frames to be redrawn if needed. */
2738 release_frame_dc (f, get_frame_dc (f));
2739 }
2740 return 0;
2741 case WM_PAINT:
2742 {
2743 PAINTSTRUCT paintStruct;
2744 RECT update_rect;
2745 memset (&update_rect, 0, sizeof (update_rect));
2746
2747 f = x_window_to_frame (dpyinfo, hwnd);
2748 if (f == 0)
2749 {
2750 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
2751 return 0;
2752 }
2753
2754 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2755 fails. Apparently this can happen under some
2756 circumstances. */
2757 if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting)
2758 {
2759 enter_crit ();
2760 BeginPaint (hwnd, &paintStruct);
2761
2762 /* The rectangles returned by GetUpdateRect and BeginPaint
2763 do not always match. Play it safe by assuming both areas
2764 are invalid. */
2765 UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint));
2766
2767 #if defined (W32_DEBUG_DISPLAY)
2768 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2769 f,
2770 wmsg.rect.left, wmsg.rect.top,
2771 wmsg.rect.right, wmsg.rect.bottom));
2772 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2773 update_rect.left, update_rect.top,
2774 update_rect.right, update_rect.bottom));
2775 #endif
2776 EndPaint (hwnd, &paintStruct);
2777 leave_crit ();
2778
2779 /* Change the message type to prevent Windows from
2780 combining WM_PAINT messages in the Lisp thread's queue,
2781 since Windows assumes that each message queue is
2782 dedicated to one frame and does not bother checking
2783 that hwnd matches before combining them. */
2784 my_post_msg (&wmsg, hwnd, WM_EMACS_PAINT, wParam, lParam);
2785
2786 return 0;
2787 }
2788
2789 /* If GetUpdateRect returns 0 (meaning there is no update
2790 region), assume the whole window needs to be repainted. */
2791 GetClientRect (hwnd, &wmsg.rect);
2792 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2793 return 0;
2794 }
2795
2796 case WM_INPUTLANGCHANGE:
2797 /* Inform lisp thread of keyboard layout changes. */
2798 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2799
2800 /* Clear dead keys in the keyboard state; for simplicity only
2801 preserve modifier key states. */
2802 {
2803 int i;
2804 BYTE keystate[256];
2805
2806 GetKeyboardState (keystate);
2807 for (i = 0; i < 256; i++)
2808 if (1
2809 && i != VK_SHIFT
2810 && i != VK_LSHIFT
2811 && i != VK_RSHIFT
2812 && i != VK_CAPITAL
2813 && i != VK_NUMLOCK
2814 && i != VK_SCROLL
2815 && i != VK_CONTROL
2816 && i != VK_LCONTROL
2817 && i != VK_RCONTROL
2818 && i != VK_MENU
2819 && i != VK_LMENU
2820 && i != VK_RMENU
2821 && i != VK_LWIN
2822 && i != VK_RWIN)
2823 keystate[i] = 0;
2824 SetKeyboardState (keystate);
2825 }
2826 goto dflt;
2827
2828 case WM_HOTKEY:
2829 /* Synchronize hot keys with normal input. */
2830 PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
2831 return (0);
2832
2833 case WM_KEYUP:
2834 case WM_SYSKEYUP:
2835 record_keyup (wParam, lParam);
2836 goto dflt;
2837
2838 case WM_KEYDOWN:
2839 case WM_SYSKEYDOWN:
2840 /* Ignore keystrokes we fake ourself; see below. */
2841 if (dpyinfo->faked_key == wParam)
2842 {
2843 dpyinfo->faked_key = 0;
2844 /* Make sure TranslateMessage sees them though (as long as
2845 they don't produce WM_CHAR messages). This ensures that
2846 indicator lights are toggled promptly on Windows 9x, for
2847 example. */
2848 if (wParam < 256 && lispy_function_keys[wParam])
2849 {
2850 windows_translate = 1;
2851 goto translate;
2852 }
2853 return 0;
2854 }
2855
2856 /* Synchronize modifiers with current keystroke. */
2857 sync_modifiers ();
2858 record_keydown (wParam, lParam);
2859 wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
2860
2861 windows_translate = 0;
2862
2863 switch (wParam)
2864 {
2865 case VK_LWIN:
2866 if (NILP (Vw32_pass_lwindow_to_system))
2867 {
2868 /* Prevent system from acting on keyup (which opens the
2869 Start menu if no other key was pressed) by simulating a
2870 press of Space which we will ignore. */
2871 if (GetAsyncKeyState (wParam) & 1)
2872 {
2873 if (NUMBERP (Vw32_phantom_key_code))
2874 key = XUINT (Vw32_phantom_key_code) & 255;
2875 else
2876 key = VK_SPACE;
2877 dpyinfo->faked_key = key;
2878 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
2879 }
2880 }
2881 if (!NILP (Vw32_lwindow_modifier))
2882 return 0;
2883 break;
2884 case VK_RWIN:
2885 if (NILP (Vw32_pass_rwindow_to_system))
2886 {
2887 if (GetAsyncKeyState (wParam) & 1)
2888 {
2889 if (NUMBERP (Vw32_phantom_key_code))
2890 key = XUINT (Vw32_phantom_key_code) & 255;
2891 else
2892 key = VK_SPACE;
2893 dpyinfo->faked_key = key;
2894 keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
2895 }
2896 }
2897 if (!NILP (Vw32_rwindow_modifier))
2898 return 0;
2899 break;
2900 case VK_APPS:
2901 if (!NILP (Vw32_apps_modifier))
2902 return 0;
2903 break;
2904 case VK_MENU:
2905 if (NILP (Vw32_pass_alt_to_system))
2906 /* Prevent DefWindowProc from activating the menu bar if an
2907 Alt key is pressed and released by itself. */
2908 return 0;
2909 windows_translate = 1;
2910 break;
2911 case VK_CAPITAL:
2912 /* Decide whether to treat as modifier or function key. */
2913 if (NILP (Vw32_enable_caps_lock))
2914 goto disable_lock_key;
2915 windows_translate = 1;
2916 break;
2917 case VK_NUMLOCK:
2918 /* Decide whether to treat as modifier or function key. */
2919 if (NILP (Vw32_enable_num_lock))
2920 goto disable_lock_key;
2921 windows_translate = 1;
2922 break;
2923 case VK_SCROLL:
2924 /* Decide whether to treat as modifier or function key. */
2925 if (NILP (Vw32_scroll_lock_modifier))
2926 goto disable_lock_key;
2927 windows_translate = 1;
2928 break;
2929 disable_lock_key:
2930 /* Ensure the appropriate lock key state (and indicator light)
2931 remains in the same state. We do this by faking another
2932 press of the relevant key. Apparently, this really is the
2933 only way to toggle the state of the indicator lights. */
2934 dpyinfo->faked_key = wParam;
2935 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
2936 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2937 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
2938 KEYEVENTF_EXTENDEDKEY | 0, 0);
2939 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
2940 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2941 /* Ensure indicator lights are updated promptly on Windows 9x
2942 (TranslateMessage apparently does this), after forwarding
2943 input event. */
2944 post_character_message (hwnd, msg, wParam, lParam,
2945 w32_get_key_modifiers (wParam, lParam));
2946 windows_translate = 1;
2947 break;
2948 case VK_CONTROL:
2949 case VK_SHIFT:
2950 case VK_PROCESSKEY: /* Generated by IME. */
2951 windows_translate = 1;
2952 break;
2953 case VK_CANCEL:
2954 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
2955 which is confusing for purposes of key binding; convert
2956 VK_CANCEL events into VK_PAUSE events. */
2957 wParam = VK_PAUSE;
2958 break;
2959 case VK_PAUSE:
2960 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
2961 for purposes of key binding; convert these back into
2962 VK_NUMLOCK events, at least when we want to see NumLock key
2963 presses. (Note that there is never any possibility that
2964 VK_PAUSE with Ctrl really is C-Pause as per above.) */
2965 if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
2966 wParam = VK_NUMLOCK;
2967 break;
2968 default:
2969 /* If not defined as a function key, change it to a WM_CHAR message. */
2970 if (wParam > 255 || !lispy_function_keys[wParam])
2971 {
2972 DWORD modifiers = construct_console_modifiers ();
2973
2974 if (!NILP (Vw32_recognize_altgr)
2975 && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
2976 {
2977 /* Always let TranslateMessage handle AltGr key chords;
2978 for some reason, ToAscii doesn't always process AltGr
2979 chords correctly. */
2980 windows_translate = 1;
2981 }
2982 else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
2983 {
2984 /* Handle key chords including any modifiers other
2985 than shift directly, in order to preserve as much
2986 modifier information as possible. */
2987 if ('A' <= wParam && wParam <= 'Z')
2988 {
2989 /* Don't translate modified alphabetic keystrokes,
2990 so the user doesn't need to constantly switch
2991 layout to type control or meta keystrokes when
2992 the normal layout translates alphabetic
2993 characters to non-ascii characters. */
2994 if (!modifier_set (VK_SHIFT))
2995 wParam += ('a' - 'A');
2996 msg = WM_CHAR;
2997 }
2998 else
2999 {
3000 /* Try to handle other keystrokes by determining the
3001 base character (ie. translating the base key plus
3002 shift modifier). */
3003 int add;
3004 KEY_EVENT_RECORD key;
3005
3006 key.bKeyDown = TRUE;
3007 key.wRepeatCount = 1;
3008 key.wVirtualKeyCode = wParam;
3009 key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
3010 key.uChar.AsciiChar = 0;
3011 key.dwControlKeyState = modifiers;
3012
3013 add = w32_kbd_patch_key (&key, w32_keyboard_codepage);
3014 /* 0 means an unrecognized keycode, negative means
3015 dead key. Ignore both. */
3016 while (--add >= 0)
3017 {
3018 /* Forward asciified character sequence. */
3019 post_character_message
3020 (hwnd, WM_CHAR,
3021 (unsigned char) key.uChar.AsciiChar, lParam,
3022 w32_get_key_modifiers (wParam, lParam));
3023 w32_kbd_patch_key (&key, w32_keyboard_codepage);
3024 }
3025 return 0;
3026 }
3027 }
3028 else
3029 {
3030 /* Let TranslateMessage handle everything else. */
3031 windows_translate = 1;
3032 }
3033 }
3034 }
3035
3036 translate:
3037 if (windows_translate)
3038 {
3039 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
3040 windows_msg.time = GetMessageTime ();
3041 TranslateMessage (&windows_msg);
3042 goto dflt;
3043 }
3044
3045 /* Fall through */
3046
3047 case WM_SYSCHAR:
3048 case WM_CHAR:
3049 if (wParam > 255 )
3050 {
3051 W32Msg wmsg;
3052
3053 wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
3054 signal_user_input ();
3055 my_post_msg (&wmsg, hwnd, WM_UNICHAR, wParam, lParam);
3056
3057 }
3058 else
3059 post_character_message (hwnd, msg, wParam, lParam,
3060 w32_get_key_modifiers (wParam, lParam));
3061 break;
3062
3063 case WM_UNICHAR:
3064 /* WM_UNICHAR looks promising from the docs, but the exact
3065 circumstances in which TranslateMessage sends it is one of those
3066 Microsoft secret API things that EU and US courts are supposed
3067 to have put a stop to already. Spy++ shows it being sent to Notepad
3068 and other MS apps, but never to Emacs.
3069
3070 Some third party IMEs send it in accordance with the official
3071 documentation though, so handle it here.
3072
3073 UNICODE_NOCHAR is used to test for support for this message.
3074 TRUE indicates that the message is supported. */
3075 if (wParam == UNICODE_NOCHAR)
3076 return TRUE;
3077
3078 {
3079 W32Msg wmsg;
3080 wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
3081 signal_user_input ();
3082 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3083 }
3084 break;
3085
3086 case WM_IME_CHAR:
3087 /* If we can't get the IME result as Unicode, use default processing,
3088 which will at least allow characters decodable in the system locale
3089 get through. */
3090 if (!get_composition_string_fn)
3091 goto dflt;
3092
3093 else if (!ignore_ime_char)
3094 {
3095 wchar_t * buffer;
3096 int size, i;
3097 W32Msg wmsg;
3098 HIMC context = get_ime_context_fn (hwnd);
3099 wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
3100 /* Get buffer size. */
3101 size = get_composition_string_fn (context, GCS_RESULTSTR, NULL, 0);
3102 buffer = alloca (size);
3103 size = get_composition_string_fn (context, GCS_RESULTSTR,
3104 buffer, size);
3105 release_ime_context_fn (hwnd, context);
3106
3107 signal_user_input ();
3108 for (i = 0; i < size / sizeof (wchar_t); i++)
3109 {
3110 my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i],
3111 lParam);
3112 }
3113 /* Ignore the messages for the rest of the
3114 characters in the string that was output above. */
3115 ignore_ime_char = (size / sizeof (wchar_t)) - 1;
3116 }
3117 else
3118 ignore_ime_char--;
3119
3120 break;
3121
3122 case WM_IME_STARTCOMPOSITION:
3123 if (!set_ime_composition_window_fn)
3124 goto dflt;
3125 else
3126 {
3127 COMPOSITIONFORM form;
3128 HIMC context;
3129 struct window *w;
3130
3131 f = x_window_to_frame (dpyinfo, hwnd);
3132 w = XWINDOW (FRAME_SELECTED_WINDOW (f));
3133
3134 form.dwStyle = CFS_RECT;
3135 form.ptCurrentPos.x = w32_system_caret_x;
3136 form.ptCurrentPos.y = w32_system_caret_y;
3137
3138 form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
3139 form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
3140 + WINDOW_HEADER_LINE_HEIGHT (w));
3141 form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
3142 - WINDOW_RIGHT_MARGIN_WIDTH (w)
3143 - WINDOW_RIGHT_FRINGE_WIDTH (w));
3144 form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
3145 - WINDOW_MODE_LINE_HEIGHT (w));
3146
3147 context = get_ime_context_fn (hwnd);
3148
3149 if (!context)
3150 break;
3151
3152 set_ime_composition_window_fn (context, &form);
3153 release_ime_context_fn (hwnd, context);
3154 }
3155 break;
3156
3157 case WM_IME_ENDCOMPOSITION:
3158 ignore_ime_char = 0;
3159 goto dflt;
3160
3161 /* Simulate middle mouse button events when left and right buttons
3162 are used together, but only if user has two button mouse. */
3163 case WM_LBUTTONDOWN:
3164 case WM_RBUTTONDOWN:
3165 if (w32_num_mouse_buttons > 2)
3166 goto handle_plain_button;
3167
3168 {
3169 int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
3170 int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
3171
3172 if (button_state & this)
3173 return 0;
3174
3175 if (button_state == 0)
3176 SetCapture (hwnd);
3177
3178 button_state |= this;
3179
3180 if (button_state & other)
3181 {
3182 if (mouse_button_timer)
3183 {
3184 KillTimer (hwnd, mouse_button_timer);
3185 mouse_button_timer = 0;
3186
3187 /* Generate middle mouse event instead. */
3188 msg = WM_MBUTTONDOWN;
3189 button_state |= MMOUSE;
3190 }
3191 else if (button_state & MMOUSE)
3192 {
3193 /* Ignore button event if we've already generated a
3194 middle mouse down event. This happens if the
3195 user releases and press one of the two buttons
3196 after we've faked a middle mouse event. */
3197 return 0;
3198 }
3199 else
3200 {
3201 /* Flush out saved message. */
3202 post_msg (&saved_mouse_button_msg);
3203 }
3204 wmsg.dwModifiers = w32_get_modifiers ();
3205 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3206 signal_user_input ();
3207
3208 /* Clear message buffer. */
3209 saved_mouse_button_msg.msg.hwnd = 0;
3210 }
3211 else
3212 {
3213 /* Hold onto message for now. */
3214 mouse_button_timer =
3215 SetTimer (hwnd, MOUSE_BUTTON_ID,
3216 w32_mouse_button_tolerance, NULL);
3217 saved_mouse_button_msg.msg.hwnd = hwnd;
3218 saved_mouse_button_msg.msg.message = msg;
3219 saved_mouse_button_msg.msg.wParam = wParam;
3220 saved_mouse_button_msg.msg.lParam = lParam;
3221 saved_mouse_button_msg.msg.time = GetMessageTime ();
3222 saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
3223 }
3224 }
3225 return 0;
3226
3227 case WM_LBUTTONUP:
3228 case WM_RBUTTONUP:
3229 if (w32_num_mouse_buttons > 2)
3230 goto handle_plain_button;
3231
3232 {
3233 int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
3234 int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
3235
3236 if ((button_state & this) == 0)
3237 return 0;
3238
3239 button_state &= ~this;
3240
3241 if (button_state & MMOUSE)
3242 {
3243 /* Only generate event when second button is released. */
3244 if ((button_state & other) == 0)
3245 {
3246 msg = WM_MBUTTONUP;
3247 button_state &= ~MMOUSE;
3248
3249 if (button_state) emacs_abort ();
3250 }
3251 else
3252 return 0;
3253 }
3254 else
3255 {
3256 /* Flush out saved message if necessary. */
3257 if (saved_mouse_button_msg.msg.hwnd)
3258 {
3259 post_msg (&saved_mouse_button_msg);
3260 }
3261 }
3262 wmsg.dwModifiers = w32_get_modifiers ();
3263 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3264 signal_user_input ();
3265
3266 /* Always clear message buffer and cancel timer. */
3267 saved_mouse_button_msg.msg.hwnd = 0;
3268 KillTimer (hwnd, mouse_button_timer);
3269 mouse_button_timer = 0;
3270
3271 if (button_state == 0)
3272 ReleaseCapture ();
3273 }
3274 return 0;
3275
3276 case WM_XBUTTONDOWN:
3277 case WM_XBUTTONUP:
3278 if (w32_pass_extra_mouse_buttons_to_system)
3279 goto dflt;
3280 /* else fall through and process them. */
3281 case WM_MBUTTONDOWN:
3282 case WM_MBUTTONUP:
3283 handle_plain_button:
3284 {
3285 BOOL up;
3286 int button;
3287
3288 /* Ignore middle and extra buttons as long as the menu is active. */
3289 f = x_window_to_frame (dpyinfo, hwnd);
3290 if (f && f->output_data.w32->menubar_active)
3291 return 0;
3292
3293 if (parse_button (msg, HIWORD (wParam), &button, &up))
3294 {
3295 if (up) ReleaseCapture ();
3296 else SetCapture (hwnd);
3297 button = (button == 0) ? LMOUSE :
3298 ((button == 1) ? MMOUSE : RMOUSE);
3299 if (up)
3300 button_state &= ~button;
3301 else
3302 button_state |= button;
3303 }
3304 }
3305
3306 wmsg.dwModifiers = w32_get_modifiers ();
3307 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3308 signal_user_input ();
3309
3310 /* Need to return true for XBUTTON messages, false for others,
3311 to indicate that we processed the message. */
3312 return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
3313
3314 case WM_MOUSEMOVE:
3315 /* Ignore mouse movements as long as the menu is active. These
3316 movements are processed by the window manager anyway, and
3317 it's wrong to handle them as if they happened on the
3318 underlying frame. */
3319 f = x_window_to_frame (dpyinfo, hwnd);
3320 if (f && f->output_data.w32->menubar_active)
3321 return 0;
3322
3323 /* If the mouse has just moved into the frame, start tracking
3324 it, so we will be notified when it leaves the frame. Mouse
3325 tracking only works under W98 and NT4 and later. On earlier
3326 versions, there is no way of telling when the mouse leaves the
3327 frame, so we just have to put up with help-echo and mouse
3328 highlighting remaining while the frame is not active. */
3329 if (track_mouse_event_fn && !track_mouse_window)
3330 {
3331 TRACKMOUSEEVENT tme;
3332 tme.cbSize = sizeof (tme);
3333 tme.dwFlags = TME_LEAVE;
3334 tme.hwndTrack = hwnd;
3335
3336 track_mouse_event_fn (&tme);
3337 track_mouse_window = hwnd;
3338 }
3339 case WM_VSCROLL:
3340 if (w32_mouse_move_interval <= 0
3341 || (msg == WM_MOUSEMOVE && button_state == 0))
3342 {
3343 wmsg.dwModifiers = w32_get_modifiers ();
3344 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3345 return 0;
3346 }
3347
3348 /* Hang onto mouse move and scroll messages for a bit, to avoid
3349 sending such events to Emacs faster than it can process them.
3350 If we get more events before the timer from the first message
3351 expires, we just replace the first message. */
3352
3353 if (saved_mouse_move_msg.msg.hwnd == 0)
3354 mouse_move_timer =
3355 SetTimer (hwnd, MOUSE_MOVE_ID,
3356 w32_mouse_move_interval, NULL);
3357
3358 /* Hold onto message for now. */
3359 saved_mouse_move_msg.msg.hwnd = hwnd;
3360 saved_mouse_move_msg.msg.message = msg;
3361 saved_mouse_move_msg.msg.wParam = wParam;
3362 saved_mouse_move_msg.msg.lParam = lParam;
3363 saved_mouse_move_msg.msg.time = GetMessageTime ();
3364 saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
3365
3366 return 0;
3367
3368 case WM_MOUSEWHEEL:
3369 case WM_DROPFILES:
3370 wmsg.dwModifiers = w32_get_modifiers ();
3371 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3372 signal_user_input ();
3373 return 0;
3374
3375 case WM_APPCOMMAND:
3376 if (w32_pass_multimedia_buttons_to_system)
3377 goto dflt;
3378 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
3379 case WM_MOUSEHWHEEL:
3380 wmsg.dwModifiers = w32_get_modifiers ();
3381 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3382 signal_user_input ();
3383 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3384 handled, to prevent the system trying to handle it by faking
3385 scroll bar events. */
3386 return 1;
3387
3388 case WM_TIMER:
3389 /* Flush out saved messages if necessary. */
3390 if (wParam == mouse_button_timer)
3391 {
3392 if (saved_mouse_button_msg.msg.hwnd)
3393 {
3394 post_msg (&saved_mouse_button_msg);
3395 signal_user_input ();
3396 saved_mouse_button_msg.msg.hwnd = 0;
3397 }
3398 KillTimer (hwnd, mouse_button_timer);
3399 mouse_button_timer = 0;
3400 }
3401 else if (wParam == mouse_move_timer)
3402 {
3403 if (saved_mouse_move_msg.msg.hwnd)
3404 {
3405 post_msg (&saved_mouse_move_msg);
3406 saved_mouse_move_msg.msg.hwnd = 0;
3407 }
3408 KillTimer (hwnd, mouse_move_timer);
3409 mouse_move_timer = 0;
3410 }
3411 else if (wParam == menu_free_timer)
3412 {
3413 KillTimer (hwnd, menu_free_timer);
3414 menu_free_timer = 0;
3415 f = x_window_to_frame (dpyinfo, hwnd);
3416 /* If a popup menu is active, don't wipe its strings. */
3417 if (menubar_in_use
3418 && current_popup_menu == NULL)
3419 {
3420 /* Free memory used by owner-drawn and help-echo strings. */
3421 w32_free_menu_strings (hwnd);
3422 if (f)
3423 f->output_data.w32->menubar_active = 0;
3424 menubar_in_use = 0;
3425 }
3426 }
3427 return 0;
3428
3429 case WM_NCACTIVATE:
3430 /* Windows doesn't send us focus messages when putting up and
3431 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3432 The only indication we get that something happened is receiving
3433 this message afterwards. So this is a good time to reset our
3434 keyboard modifiers' state. */
3435 reset_modifiers ();
3436 goto dflt;
3437
3438 case WM_INITMENU:
3439 button_state = 0;
3440 ReleaseCapture ();
3441 /* We must ensure menu bar is fully constructed and up to date
3442 before allowing user interaction with it. To achieve this
3443 we send this message to the lisp thread and wait for a
3444 reply (whose value is not actually needed) to indicate that
3445 the menu bar is now ready for use, so we can now return.
3446
3447 To remain responsive in the meantime, we enter a nested message
3448 loop that can process all other messages.
3449
3450 However, we skip all this if the message results from calling
3451 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3452 thread a message because it is blocked on us at this point. We
3453 set menubar_active before calling TrackPopupMenu to indicate
3454 this (there is no possibility of confusion with real menubar
3455 being active). */
3456
3457 f = x_window_to_frame (dpyinfo, hwnd);
3458 if (f
3459 && (f->output_data.w32->menubar_active
3460 /* We can receive this message even in the absence of a
3461 menubar (ie. when the system menu is activated) - in this
3462 case we do NOT want to forward the message, otherwise it
3463 will cause the menubar to suddenly appear when the user
3464 had requested it to be turned off! */
3465 || f->output_data.w32->menubar_widget == NULL))
3466 return 0;
3467
3468 {
3469 deferred_msg msg_buf;
3470
3471 /* Detect if message has already been deferred; in this case
3472 we cannot return any sensible value to ignore this. */
3473 if (find_deferred_msg (hwnd, msg) != NULL)
3474 emacs_abort ();
3475
3476 menubar_in_use = 1;
3477
3478 return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
3479 }
3480
3481 case WM_EXITMENULOOP:
3482 f = x_window_to_frame (dpyinfo, hwnd);
3483
3484 /* If a menu is still active, check again after a short delay,
3485 since Windows often (always?) sends the WM_EXITMENULOOP
3486 before the corresponding WM_COMMAND message.
3487 Don't do this if a popup menu is active, since it is only
3488 menubar menus that require cleaning up in this way.
3489 */
3490 if (f && menubar_in_use && current_popup_menu == NULL)
3491 menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
3492
3493 /* If hourglass cursor should be displayed, display it now. */
3494 if (f && f->output_data.w32->hourglass_p)
3495 SetCursor (f->output_data.w32->hourglass_cursor);
3496
3497 goto dflt;
3498
3499 case WM_MENUSELECT:
3500 /* Direct handling of help_echo in menus. Should be safe now
3501 that we generate the help_echo by placing a help event in the
3502 keyboard buffer. */
3503 {
3504 HMENU menu = (HMENU) lParam;
3505 UINT menu_item = (UINT) LOWORD (wParam);
3506 UINT flags = (UINT) HIWORD (wParam);
3507
3508 w32_menu_display_help (hwnd, menu, menu_item, flags);
3509 }
3510 return 0;
3511
3512 case WM_MEASUREITEM:
3513 f = x_window_to_frame (dpyinfo, hwnd);
3514 if (f)
3515 {
3516 MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
3517
3518 if (pMis->CtlType == ODT_MENU)
3519 {
3520 /* Work out dimensions for popup menu titles. */
3521 char * title = (char *) pMis->itemData;
3522 HDC hdc = GetDC (hwnd);
3523 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
3524 LOGFONT menu_logfont;
3525 HFONT old_font;
3526 SIZE size;
3527
3528 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
3529 menu_logfont.lfWeight = FW_BOLD;
3530 menu_font = CreateFontIndirect (&menu_logfont);
3531 old_font = SelectObject (hdc, menu_font);
3532
3533 pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
3534 if (title)
3535 {
3536 if (unicode_append_menu)
3537 GetTextExtentPoint32W (hdc, (WCHAR *) title,
3538 wcslen ((WCHAR *) title),
3539 &size);
3540 else
3541 GetTextExtentPoint32 (hdc, title, strlen (title), &size);
3542
3543 pMis->itemWidth = size.cx;
3544 if (pMis->itemHeight < size.cy)
3545 pMis->itemHeight = size.cy;
3546 }
3547 else
3548 pMis->itemWidth = 0;
3549
3550 SelectObject (hdc, old_font);
3551 DeleteObject (menu_font);
3552 ReleaseDC (hwnd, hdc);
3553 return TRUE;
3554 }
3555 }
3556 return 0;
3557
3558 case WM_DRAWITEM:
3559 f = x_window_to_frame (dpyinfo, hwnd);
3560 if (f)
3561 {
3562 DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
3563
3564 if (pDis->CtlType == ODT_MENU)
3565 {
3566 /* Draw popup menu title. */
3567 char * title = (char *) pDis->itemData;
3568 if (title)
3569 {
3570 HDC hdc = pDis->hDC;
3571 HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
3572 LOGFONT menu_logfont;
3573 HFONT old_font;
3574
3575 GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
3576 menu_logfont.lfWeight = FW_BOLD;
3577 menu_font = CreateFontIndirect (&menu_logfont);
3578 old_font = SelectObject (hdc, menu_font);
3579
3580 /* Always draw title as if not selected. */
3581 if (unicode_append_menu)
3582 ExtTextOutW (hdc,
3583 pDis->rcItem.left
3584 + GetSystemMetrics (SM_CXMENUCHECK),
3585 pDis->rcItem.top,
3586 ETO_OPAQUE, &pDis->rcItem,
3587 (WCHAR *) title,
3588 wcslen ((WCHAR *) title), NULL);
3589 else
3590 ExtTextOut (hdc,
3591 pDis->rcItem.left
3592 + GetSystemMetrics (SM_CXMENUCHECK),
3593 pDis->rcItem.top,
3594 ETO_OPAQUE, &pDis->rcItem,
3595 title, strlen (title), NULL);
3596
3597 SelectObject (hdc, old_font);
3598 DeleteObject (menu_font);
3599 }
3600 return TRUE;
3601 }
3602 }
3603 return 0;
3604
3605 #if 0
3606 /* Still not right - can't distinguish between clicks in the
3607 client area of the frame from clicks forwarded from the scroll
3608 bars - may have to hook WM_NCHITTEST to remember the mouse
3609 position and then check if it is in the client area ourselves. */
3610 case WM_MOUSEACTIVATE:
3611 /* Discard the mouse click that activates a frame, allowing the
3612 user to click anywhere without changing point (or worse!).
3613 Don't eat mouse clicks on scrollbars though!! */
3614 if (LOWORD (lParam) == HTCLIENT )
3615 return MA_ACTIVATEANDEAT;
3616 goto dflt;
3617 #endif
3618
3619 case WM_MOUSELEAVE:
3620 /* No longer tracking mouse. */
3621 track_mouse_window = NULL;
3622
3623 case WM_ACTIVATEAPP:
3624 case WM_ACTIVATE:
3625 case WM_WINDOWPOSCHANGED:
3626 case WM_SHOWWINDOW:
3627 /* Inform lisp thread that a frame might have just been obscured
3628 or exposed, so should recheck visibility of all frames. */
3629 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3630 goto dflt;
3631
3632 case WM_SETFOCUS:
3633 dpyinfo->faked_key = 0;
3634 reset_modifiers ();
3635 register_hot_keys (hwnd);
3636 goto command;
3637 case WM_KILLFOCUS:
3638 unregister_hot_keys (hwnd);
3639 button_state = 0;
3640 ReleaseCapture ();
3641 /* Relinquish the system caret. */
3642 if (w32_system_caret_hwnd)
3643 {
3644 w32_visible_system_caret_hwnd = NULL;
3645 w32_system_caret_hwnd = NULL;
3646 DestroyCaret ();
3647 }
3648 goto command;
3649 case WM_COMMAND:
3650 menubar_in_use = 0;
3651 f = x_window_to_frame (dpyinfo, hwnd);
3652 if (f && HIWORD (wParam) == 0)
3653 {
3654 if (menu_free_timer)
3655 {
3656 KillTimer (hwnd, menu_free_timer);
3657 menu_free_timer = 0;
3658 }
3659 }
3660 case WM_MOVE:
3661 case WM_SIZE:
3662 command:
3663 wmsg.dwModifiers = w32_get_modifiers ();
3664 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3665 goto dflt;
3666
3667 case WM_DESTROY:
3668 CoUninitialize ();
3669 return 0;
3670
3671 case WM_CLOSE:
3672 wmsg.dwModifiers = w32_get_modifiers ();
3673 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3674 return 0;
3675
3676 case WM_WINDOWPOSCHANGING:
3677 /* Don't restrict the sizing of tip frames. */
3678 if (hwnd == tip_window)
3679 return 0;
3680 {
3681 WINDOWPLACEMENT wp;
3682 LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
3683
3684 wp.length = sizeof (WINDOWPLACEMENT);
3685 GetWindowPlacement (hwnd, &wp);
3686
3687 if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
3688 {
3689 RECT rect;
3690 int wdiff;
3691 int hdiff;
3692 DWORD font_width;
3693 DWORD line_height;
3694 DWORD internal_border;
3695 DWORD scrollbar_extra;
3696 RECT wr;
3697
3698 wp.length = sizeof (wp);
3699 GetWindowRect (hwnd, &wr);
3700
3701 enter_crit ();
3702
3703 font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
3704 line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
3705 internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
3706 scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
3707
3708 leave_crit ();
3709
3710 memset (&rect, 0, sizeof (rect));
3711 AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
3712 GetMenu (hwnd) != NULL);
3713
3714 /* Force width and height of client area to be exact
3715 multiples of the character cell dimensions. */
3716 wdiff = (lppos->cx - (rect.right - rect.left)
3717 - 2 * internal_border - scrollbar_extra)
3718 % font_width;
3719 hdiff = (lppos->cy - (rect.bottom - rect.top)
3720 - 2 * internal_border)
3721 % line_height;
3722
3723 if (wdiff || hdiff)
3724 {
3725 /* For right/bottom sizing we can just fix the sizes.
3726 However for top/left sizing we will need to fix the X
3727 and Y positions as well. */
3728
3729 int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK);
3730 int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK);
3731
3732 lppos->cx = max (lppos->cx - wdiff, cx_mintrack);
3733 lppos->cy = max (lppos->cy - hdiff, cy_mintrack);
3734
3735 if (wp.showCmd != SW_SHOWMAXIMIZED
3736 && (lppos->flags & SWP_NOMOVE) == 0)
3737 {
3738 if (lppos->x != wr.left || lppos->y != wr.top)
3739 {
3740 lppos->x += wdiff;
3741 lppos->y += hdiff;
3742 }
3743 else
3744 {
3745 lppos->flags |= SWP_NOMOVE;
3746 }
3747 }
3748
3749 return 0;
3750 }
3751 }
3752 }
3753
3754 goto dflt;
3755
3756 case WM_GETMINMAXINFO:
3757 /* Hack to allow resizing the Emacs frame above the screen size.
3758 Note that Windows 9x limits coordinates to 16-bits. */
3759 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
3760 ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
3761 return 0;
3762
3763 case WM_SETCURSOR:
3764 if (LOWORD (lParam) == HTCLIENT)
3765 {
3766 f = x_window_to_frame (dpyinfo, hwnd);
3767 if (f && f->output_data.w32->hourglass_p
3768 && !menubar_in_use && !current_popup_menu)
3769 SetCursor (f->output_data.w32->hourglass_cursor);
3770 else if (f)
3771 SetCursor (f->output_data.w32->current_cursor);
3772 return 0;
3773 }
3774 goto dflt;
3775
3776 case WM_EMACS_SETCURSOR:
3777 {
3778 Cursor cursor = (Cursor) wParam;
3779 f = x_window_to_frame (dpyinfo, hwnd);
3780 if (f && cursor)
3781 {
3782 f->output_data.w32->current_cursor = cursor;
3783 if (!f->output_data.w32->hourglass_p)
3784 SetCursor (cursor);
3785 }
3786 return 0;
3787 }
3788
3789 case WM_EMACS_CREATESCROLLBAR:
3790 return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
3791 (struct scroll_bar *) lParam);
3792
3793 case WM_EMACS_SHOWWINDOW:
3794 return ShowWindow ((HWND) wParam, (WPARAM) lParam);
3795
3796 case WM_EMACS_BRINGTOTOP:
3797 case WM_EMACS_SETFOREGROUND:
3798 {
3799 HWND foreground_window;
3800 DWORD foreground_thread, retval;
3801
3802 /* On NT 5.0, and apparently Windows 98, it is necessary to
3803 attach to the thread that currently has focus in order to
3804 pull the focus away from it. */
3805 foreground_window = GetForegroundWindow ();
3806 foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
3807 if (!foreground_window
3808 || foreground_thread == GetCurrentThreadId ()
3809 || !AttachThreadInput (GetCurrentThreadId (),
3810 foreground_thread, TRUE))
3811 foreground_thread = 0;
3812
3813 retval = SetForegroundWindow ((HWND) wParam);
3814 if (msg == WM_EMACS_BRINGTOTOP)
3815 retval = BringWindowToTop ((HWND) wParam);
3816
3817 /* Detach from the previous foreground thread. */
3818 if (foreground_thread)
3819 AttachThreadInput (GetCurrentThreadId (),
3820 foreground_thread, FALSE);
3821
3822 return retval;
3823 }
3824
3825 case WM_EMACS_SETWINDOWPOS:
3826 {
3827 WINDOWPOS * pos = (WINDOWPOS *) wParam;
3828 return SetWindowPos (hwnd, pos->hwndInsertAfter,
3829 pos->x, pos->y, pos->cx, pos->cy, pos->flags);
3830 }
3831
3832 case WM_EMACS_DESTROYWINDOW:
3833 DragAcceptFiles ((HWND) wParam, FALSE);
3834 return DestroyWindow ((HWND) wParam);
3835
3836 case WM_EMACS_HIDE_CARET:
3837 return HideCaret (hwnd);
3838
3839 case WM_EMACS_SHOW_CARET:
3840 return ShowCaret (hwnd);
3841
3842 case WM_EMACS_DESTROY_CARET:
3843 w32_system_caret_hwnd = NULL;
3844 w32_visible_system_caret_hwnd = NULL;
3845 return DestroyCaret ();
3846
3847 case WM_EMACS_TRACK_CARET:
3848 /* If there is currently no system caret, create one. */
3849 if (w32_system_caret_hwnd == NULL)
3850 {
3851 /* Use the default caret width, and avoid changing it
3852 unnecessarily, as it confuses screen reader software. */
3853 w32_system_caret_hwnd = hwnd;
3854 CreateCaret (hwnd, NULL, 0,
3855 w32_system_caret_height);
3856 }
3857
3858 if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
3859 return 0;
3860 /* Ensure visible caret gets turned on when requested. */
3861 else if (w32_use_visible_system_caret
3862 && w32_visible_system_caret_hwnd != hwnd)
3863 {
3864 w32_visible_system_caret_hwnd = hwnd;
3865 return ShowCaret (hwnd);
3866 }
3867 /* Ensure visible caret gets turned off when requested. */
3868 else if (!w32_use_visible_system_caret
3869 && w32_visible_system_caret_hwnd)
3870 {
3871 w32_visible_system_caret_hwnd = NULL;
3872 return HideCaret (hwnd);
3873 }
3874 else
3875 return 1;
3876
3877 case WM_EMACS_TRACKPOPUPMENU:
3878 {
3879 UINT flags;
3880 POINT *pos;
3881 int retval;
3882 pos = (POINT *)lParam;
3883 flags = TPM_CENTERALIGN;
3884 if (button_state & LMOUSE)
3885 flags |= TPM_LEFTBUTTON;
3886 else if (button_state & RMOUSE)
3887 flags |= TPM_RIGHTBUTTON;
3888
3889 /* Remember we did a SetCapture on the initial mouse down event,
3890 so for safety, we make sure the capture is canceled now. */
3891 ReleaseCapture ();
3892 button_state = 0;
3893
3894 /* Use menubar_active to indicate that WM_INITMENU is from
3895 TrackPopupMenu below, and should be ignored. */
3896 f = x_window_to_frame (dpyinfo, hwnd);
3897 if (f)
3898 f->output_data.w32->menubar_active = 1;
3899
3900 if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
3901 0, hwnd, NULL))
3902 {
3903 MSG amsg;
3904 /* Eat any mouse messages during popupmenu */
3905 while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
3906 PM_REMOVE));
3907 /* Get the menu selection, if any */
3908 if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
3909 {
3910 retval = LOWORD (amsg.wParam);
3911 }
3912 else
3913 {
3914 retval = 0;
3915 }
3916 }
3917 else
3918 {
3919 retval = -1;
3920 }
3921
3922 return retval;
3923 }
3924
3925 default:
3926 /* Check for messages registered at runtime. */
3927 if (msg == msh_mousewheel)
3928 {
3929 wmsg.dwModifiers = w32_get_modifiers ();
3930 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3931 signal_user_input ();
3932 return 0;
3933 }
3934
3935 dflt:
3936 return (w32_unicode_gui ? DefWindowProcW : DefWindowProcA) (hwnd, msg, wParam, lParam);
3937 }
3938
3939 /* The most common default return code for handled messages is 0. */
3940 return 0;
3941 }
3942
3943 static void
3944 my_create_window (struct frame * f)
3945 {
3946 MSG msg;
3947
3948 if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
3949 emacs_abort ();
3950 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3951 }
3952
3953
3954 /* Create a tooltip window. Unlike my_create_window, we do not do this
3955 indirectly via the Window thread, as we do not need to process Window
3956 messages for the tooltip. Creating tooltips indirectly also creates
3957 deadlocks when tooltips are created for menu items. */
3958 static void
3959 my_create_tip_window (struct frame *f)
3960 {
3961 RECT rect;
3962
3963 rect.left = rect.top = 0;
3964 rect.right = FRAME_PIXEL_WIDTH (f);
3965 rect.bottom = FRAME_PIXEL_HEIGHT (f);
3966
3967 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
3968 FRAME_EXTERNAL_MENU_BAR (f));
3969
3970 tip_window = FRAME_W32_WINDOW (f)
3971 = CreateWindow (EMACS_CLASS,
3972 f->namebuf,
3973 f->output_data.w32->dwStyle,
3974 f->left_pos,
3975 f->top_pos,
3976 rect.right - rect.left,
3977 rect.bottom - rect.top,
3978 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
3979 NULL,
3980 hinst,
3981 NULL);
3982
3983 if (tip_window)
3984 {
3985 SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
3986 SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
3987 SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
3988 SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
3989
3990 /* Tip frames have no scrollbars. */
3991 SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
3992
3993 /* Do this to discard the default setting specified by our parent. */
3994 ShowWindow (tip_window, SW_HIDE);
3995 }
3996 }
3997
3998
3999 /* Create and set up the w32 window for frame F. */
4000
4001 static void
4002 w32_window (struct frame *f, long window_prompting, int minibuffer_only)
4003 {
4004 block_input ();
4005
4006 /* Use the resource name as the top-level window name
4007 for looking up resources. Make a non-Lisp copy
4008 for the window manager, so GC relocation won't bother it.
4009
4010 Elsewhere we specify the window name for the window manager. */
4011
4012 {
4013 char *str = SSDATA (Vx_resource_name);
4014 f->namebuf = xmalloc (strlen (str) + 1);
4015 strcpy (f->namebuf, str);
4016 }
4017
4018 my_create_window (f);
4019
4020 validate_x_resource_name ();
4021
4022 /* x_set_name normally ignores requests to set the name if the
4023 requested name is the same as the current name. This is the one
4024 place where that assumption isn't correct; f->name is set, but
4025 the server hasn't been told. */
4026 {
4027 Lisp_Object name;
4028 int explicit = f->explicit_name;
4029
4030 f->explicit_name = 0;
4031 name = f->name;
4032 fset_name (f, Qnil);
4033 x_set_name (f, name, explicit);
4034 }
4035
4036 unblock_input ();
4037
4038 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4039 initialize_frame_menubar (f);
4040
4041 if (FRAME_W32_WINDOW (f) == 0)
4042 error ("Unable to create window");
4043 }
4044
4045 /* Handle the icon stuff for this window. Perhaps later we might
4046 want an x_set_icon_position which can be called interactively as
4047 well. */
4048
4049 static void
4050 x_icon (struct frame *f, Lisp_Object parms)
4051 {
4052 Lisp_Object icon_x, icon_y;
4053 struct w32_display_info *dpyinfo = &one_w32_display_info;
4054
4055 /* Set the position of the icon. Note that Windows 95 groups all
4056 icons in the tray. */
4057 icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4058 icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4059 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
4060 {
4061 CHECK_NUMBER (icon_x);
4062 CHECK_NUMBER (icon_y);
4063 }
4064 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
4065 error ("Both left and top icon corners of icon must be specified");
4066
4067 block_input ();
4068
4069 if (! EQ (icon_x, Qunbound))
4070 x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
4071
4072 #if 0 /* TODO */
4073 /* Start up iconic or window? */
4074 x_wm_set_window_state
4075 (f, (EQ (x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
4076 ? IconicState
4077 : NormalState));
4078
4079 x_text_icon (f, SSDATA ((!NILP (f->icon_name)
4080 ? f->icon_name
4081 : f->name)));
4082 #endif
4083
4084 unblock_input ();
4085 }
4086
4087
4088 static void
4089 x_make_gc (struct frame *f)
4090 {
4091 XGCValues gc_values;
4092
4093 block_input ();
4094
4095 /* Create the GC's of this frame.
4096 Note that many default values are used. */
4097
4098 /* Normal video */
4099 gc_values.font = FRAME_FONT (f);
4100
4101 /* Cursor has cursor-color background, background-color foreground. */
4102 gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
4103 gc_values.background = f->output_data.w32->cursor_pixel;
4104 f->output_data.w32->cursor_gc
4105 = XCreateGC (NULL, FRAME_W32_WINDOW (f),
4106 (GCFont | GCForeground | GCBackground),
4107 &gc_values);
4108
4109 /* Reliefs. */
4110 f->output_data.w32->white_relief.gc = 0;
4111 f->output_data.w32->black_relief.gc = 0;
4112
4113 unblock_input ();
4114 }
4115
4116
4117 /* Handler for signals raised during x_create_frame and
4118 x_create_tip_frame. FRAME is the frame which is partially
4119 constructed. */
4120
4121 static Lisp_Object
4122 unwind_create_frame (Lisp_Object frame)
4123 {
4124 struct frame *f = XFRAME (frame);
4125
4126 /* If frame is ``official'', nothing to do. */
4127 if (NILP (Fmemq (frame, Vframe_list)))
4128 {
4129 #ifdef GLYPH_DEBUG
4130 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4131 #endif
4132
4133 x_free_frame_resources (f);
4134 free_glyphs (f);
4135
4136 #ifdef GLYPH_DEBUG
4137 /* Check that reference counts are indeed correct. */
4138 eassert (dpyinfo->reference_count == dpyinfo_refcount);
4139 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
4140 #endif
4141 return Qt;
4142 }
4143
4144 return Qnil;
4145 }
4146
4147 static void
4148 x_default_font_parameter (struct frame *f, Lisp_Object parms)
4149 {
4150 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4151 Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
4152 RES_TYPE_STRING);
4153 Lisp_Object font;
4154 if (EQ (font_param, Qunbound))
4155 font_param = Qnil;
4156 font = !NILP (font_param) ? font_param
4157 : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
4158
4159 if (!STRINGP (font))
4160 {
4161 int i;
4162 static char *names[]
4163 = { "Courier New-10",
4164 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4165 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4166 "Fixedsys",
4167 NULL };
4168
4169 for (i = 0; names[i]; i++)
4170 {
4171 font = font_open_by_name (f, build_unibyte_string (names[i]));
4172 if (! NILP (font))
4173 break;
4174 }
4175 if (NILP (font))
4176 error ("No suitable font was found");
4177 }
4178 else if (!NILP (font_param))
4179 {
4180 /* Remember the explicit font parameter, so we can re-apply it after
4181 we've applied the `default' face settings. */
4182 x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
4183 }
4184 x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
4185 }
4186
4187 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4188 1, 1, 0,
4189 doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
4190 Return an Emacs frame object.
4191 PARAMETERS is an alist of frame parameters.
4192 If the parameters specify that the frame should not have a minibuffer,
4193 and do not specify a specific minibuffer window to use,
4194 then `default-minibuffer-frame' must be a frame whose minibuffer can
4195 be shared by the new frame.
4196
4197 This function is an internal primitive--use `make-frame' instead. */)
4198 (Lisp_Object parameters)
4199 {
4200 struct frame *f;
4201 Lisp_Object frame, tem;
4202 Lisp_Object name;
4203 int minibuffer_only = 0;
4204 long window_prompting = 0;
4205 int width, height;
4206 ptrdiff_t count = SPECPDL_INDEX ();
4207 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4208 Lisp_Object display;
4209 struct w32_display_info *dpyinfo = NULL;
4210 Lisp_Object parent;
4211 struct kboard *kb;
4212
4213 /* Make copy of frame parameters because the original is in pure
4214 storage now. */
4215 parameters = Fcopy_alist (parameters);
4216
4217 /* Use this general default value to start with
4218 until we know if this frame has a specified name. */
4219 Vx_resource_name = Vinvocation_name;
4220
4221 display = x_get_arg (dpyinfo, parameters, Qterminal, 0, 0, RES_TYPE_NUMBER);
4222 if (EQ (display, Qunbound))
4223 display = x_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
4224 if (EQ (display, Qunbound))
4225 display = Qnil;
4226 dpyinfo = check_x_display_info (display);
4227 kb = dpyinfo->terminal->kboard;
4228
4229 if (!dpyinfo->terminal->name)
4230 error ("Terminal is not live, can't create new frames on it");
4231
4232 name = x_get_arg (dpyinfo, parameters, Qname, "name", "Name", RES_TYPE_STRING);
4233 if (!STRINGP (name)
4234 && ! EQ (name, Qunbound)
4235 && ! NILP (name))
4236 error ("Invalid frame name--not a string or nil");
4237
4238 if (STRINGP (name))
4239 Vx_resource_name = name;
4240
4241 /* See if parent window is specified. */
4242 parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4243 if (EQ (parent, Qunbound))
4244 parent = Qnil;
4245 if (! NILP (parent))
4246 CHECK_NUMBER (parent);
4247
4248 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4249 /* No need to protect DISPLAY because that's not used after passing
4250 it to make_frame_without_minibuffer. */
4251 frame = Qnil;
4252 GCPRO4 (parameters, parent, name, frame);
4253 tem = x_get_arg (dpyinfo, parameters, Qminibuffer, "minibuffer", "Minibuffer",
4254 RES_TYPE_SYMBOL);
4255 if (EQ (tem, Qnone) || NILP (tem))
4256 f = make_frame_without_minibuffer (Qnil, kb, display);
4257 else if (EQ (tem, Qonly))
4258 {
4259 f = make_minibuffer_frame ();
4260 minibuffer_only = 1;
4261 }
4262 else if (WINDOWP (tem))
4263 f = make_frame_without_minibuffer (tem, kb, display);
4264 else
4265 f = make_frame (1);
4266
4267 XSETFRAME (frame, f);
4268
4269 /* Note that Windows does support scroll bars. */
4270 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4271
4272 /* By default, make scrollbars the system standard width. */
4273 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
4274
4275 f->terminal = dpyinfo->terminal;
4276
4277 f->output_method = output_w32;
4278 f->output_data.w32 = xzalloc (sizeof (struct w32_output));
4279 FRAME_FONTSET (f) = -1;
4280
4281 fset_icon_name
4282 (f, x_get_arg (dpyinfo, parameters, Qicon_name, "iconName", "Title",
4283 RES_TYPE_STRING));
4284 if (! STRINGP (f->icon_name))
4285 fset_icon_name (f, Qnil);
4286
4287 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4288
4289 /* With FRAME_X_DISPLAY_INFO set up, this unwind-protect is safe. */
4290 record_unwind_protect (unwind_create_frame, frame);
4291 #ifdef GLYPH_DEBUG
4292 image_cache_refcount =
4293 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
4294 dpyinfo_refcount = dpyinfo->reference_count;
4295 #endif /* GLYPH_DEBUG */
4296
4297 /* Specify the parent under which to make this window. */
4298
4299 if (!NILP (parent))
4300 {
4301 f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
4302 f->output_data.w32->explicit_parent = 1;
4303 }
4304 else
4305 {
4306 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
4307 f->output_data.w32->explicit_parent = 0;
4308 }
4309
4310 /* Set the name; the functions to which we pass f expect the name to
4311 be set. */
4312 if (EQ (name, Qunbound) || NILP (name))
4313 {
4314 fset_name (f, build_string (dpyinfo->w32_id_name));
4315 f->explicit_name = 0;
4316 }
4317 else
4318 {
4319 fset_name (f, name);
4320 f->explicit_name = 1;
4321 /* use the frame's title when getting resources for this frame. */
4322 specbind (Qx_resource_name, name);
4323 }
4324
4325 f->resx = dpyinfo->resx;
4326 f->resy = dpyinfo->resy;
4327
4328 if (uniscribe_available)
4329 register_font_driver (&uniscribe_font_driver, f);
4330 register_font_driver (&w32font_driver, f);
4331
4332 x_default_parameter (f, parameters, Qfont_backend, Qnil,
4333 "fontBackend", "FontBackend", RES_TYPE_STRING);
4334 /* Extract the window parameters from the supplied values
4335 that are needed to determine window geometry. */
4336 x_default_font_parameter (f, parameters);
4337 x_default_parameter (f, parameters, Qborder_width, make_number (2),
4338 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4339
4340 /* We recognize either internalBorderWidth or internalBorder
4341 (which is what xterm calls it). */
4342 if (NILP (Fassq (Qinternal_border_width, parameters)))
4343 {
4344 Lisp_Object value;
4345
4346 value = x_get_arg (dpyinfo, parameters, Qinternal_border_width,
4347 "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
4348 if (! EQ (value, Qunbound))
4349 parameters = Fcons (Fcons (Qinternal_border_width, value),
4350 parameters);
4351 }
4352 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4353 x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
4354 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
4355 x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
4356 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
4357
4358 /* Also do the stuff which must be set before the window exists. */
4359 x_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
4360 "foreground", "Foreground", RES_TYPE_STRING);
4361 x_default_parameter (f, parameters, Qbackground_color, build_string ("white"),
4362 "background", "Background", RES_TYPE_STRING);
4363 x_default_parameter (f, parameters, Qmouse_color, build_string ("black"),
4364 "pointerColor", "Foreground", RES_TYPE_STRING);
4365 x_default_parameter (f, parameters, Qborder_color, build_string ("black"),
4366 "borderColor", "BorderColor", RES_TYPE_STRING);
4367 x_default_parameter (f, parameters, Qscreen_gamma, Qnil,
4368 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4369 x_default_parameter (f, parameters, Qline_spacing, Qnil,
4370 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4371 x_default_parameter (f, parameters, Qleft_fringe, Qnil,
4372 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4373 x_default_parameter (f, parameters, Qright_fringe, Qnil,
4374 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4375
4376 /* Init faces before x_default_parameter is called for scroll-bar
4377 parameters because that function calls x_set_scroll_bar_width,
4378 which calls change_frame_size, which calls Fset_window_buffer,
4379 which runs hooks, which call Fvertical_motion. At the end, we
4380 end up in init_iterator with a null face cache, which should not
4381 happen. */
4382 init_frame_faces (f);
4383
4384 /* The X resources controlling the menu-bar and tool-bar are
4385 processed specially at startup, and reflected in the mode
4386 variables; ignore them here. */
4387 x_default_parameter (f, parameters, Qmenu_bar_lines,
4388 NILP (Vmenu_bar_mode)
4389 ? make_number (0) : make_number (1),
4390 NULL, NULL, RES_TYPE_NUMBER);
4391 x_default_parameter (f, parameters, Qtool_bar_lines,
4392 NILP (Vtool_bar_mode)
4393 ? make_number (0) : make_number (1),
4394 NULL, NULL, RES_TYPE_NUMBER);
4395
4396 x_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
4397 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
4398 x_default_parameter (f, parameters, Qtitle, Qnil,
4399 "title", "Title", RES_TYPE_STRING);
4400 x_default_parameter (f, parameters, Qfullscreen, Qnil,
4401 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4402
4403 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
4404 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
4405
4406 f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
4407 f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
4408 f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
4409 f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND);
4410 f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
4411 f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
4412
4413 f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
4414
4415 window_prompting = x_figure_window_size (f, parameters, 1);
4416
4417 tem = x_get_arg (dpyinfo, parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4418 f->no_split = minibuffer_only || EQ (tem, Qt);
4419
4420 w32_window (f, window_prompting, minibuffer_only);
4421 x_icon (f, parameters);
4422
4423 x_make_gc (f);
4424
4425 /* Now consider the frame official. */
4426 f->terminal->reference_count++;
4427 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
4428 Vframe_list = Fcons (frame, Vframe_list);
4429
4430 /* We need to do this after creating the window, so that the
4431 icon-creation functions can say whose icon they're describing. */
4432 x_default_parameter (f, parameters, Qicon_type, Qnil,
4433 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4434
4435 x_default_parameter (f, parameters, Qauto_raise, Qnil,
4436 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4437 x_default_parameter (f, parameters, Qauto_lower, Qnil,
4438 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4439 x_default_parameter (f, parameters, Qcursor_type, Qbox,
4440 "cursorType", "CursorType", RES_TYPE_SYMBOL);
4441 x_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
4442 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
4443 x_default_parameter (f, parameters, Qalpha, Qnil,
4444 "alpha", "Alpha", RES_TYPE_NUMBER);
4445
4446 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4447 Change will not be effected unless different from the current
4448 FRAME_LINES (f). */
4449 width = FRAME_COLS (f);
4450 height = FRAME_LINES (f);
4451
4452 FRAME_LINES (f) = 0;
4453 SET_FRAME_COLS (f, 0);
4454 change_frame_size (f, height, width, 1, 0, 0);
4455
4456 /* Tell the server what size and position, etc, we want, and how
4457 badly we want them. This should be done after we have the menu
4458 bar so that its size can be taken into account. */
4459 block_input ();
4460 x_wm_set_size_hint (f, window_prompting, 0);
4461 unblock_input ();
4462
4463 /* Make the window appear on the frame and enable display, unless
4464 the caller says not to. However, with explicit parent, Emacs
4465 cannot control visibility, so don't try. */
4466 if (! f->output_data.w32->explicit_parent)
4467 {
4468 Lisp_Object visibility;
4469
4470 visibility = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
4471 if (EQ (visibility, Qunbound))
4472 visibility = Qt;
4473
4474 if (EQ (visibility, Qicon))
4475 x_iconify_frame (f);
4476 else if (! NILP (visibility))
4477 x_make_frame_visible (f);
4478 else
4479 /* Must have been Qnil. */
4480 ;
4481 }
4482
4483 /* Initialize `default-minibuffer-frame' in case this is the first
4484 frame on this terminal. */
4485 if (FRAME_HAS_MINIBUF_P (f)
4486 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
4487 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
4488 kset_default_minibuffer_frame (kb, frame);
4489
4490 /* All remaining specified parameters, which have not been "used"
4491 by x_get_arg and friends, now go in the misc. alist of the frame. */
4492 for (tem = parameters; CONSP (tem); tem = XCDR (tem))
4493 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
4494 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
4495
4496 UNGCPRO;
4497
4498 /* Make sure windows on this frame appear in calls to next-window
4499 and similar functions. */
4500 Vwindow_list = Qnil;
4501
4502 return unbind_to (count, frame);
4503 }
4504
4505 /* FRAME is used only to get a handle on the X display. We don't pass the
4506 display info directly because we're called from frame.c, which doesn't
4507 know about that structure. */
4508 Lisp_Object
4509 x_get_focus_frame (struct frame *frame)
4510 {
4511 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
4512 Lisp_Object xfocus;
4513 if (! dpyinfo->w32_focus_frame)
4514 return Qnil;
4515
4516 XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
4517 return xfocus;
4518 }
4519
4520 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
4521 doc: /* Give FRAME input focus, raising to foreground if necessary. */)
4522 (Lisp_Object frame)
4523 {
4524 x_focus_on_frame (check_x_frame (frame));
4525 return Qnil;
4526 }
4527
4528 \f
4529 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
4530 doc: /* Internal function called by `color-defined-p', which see.
4531 \(Note that the Nextstep version of this function ignores FRAME.) */)
4532 (Lisp_Object color, Lisp_Object frame)
4533 {
4534 XColor foo;
4535 FRAME_PTR f = check_x_frame (frame);
4536
4537 CHECK_STRING (color);
4538
4539 if (w32_defined_color (f, SDATA (color), &foo, 0))
4540 return Qt;
4541 else
4542 return Qnil;
4543 }
4544
4545 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
4546 doc: /* Internal function called by `color-values', which see. */)
4547 (Lisp_Object color, Lisp_Object frame)
4548 {
4549 XColor foo;
4550 FRAME_PTR f = check_x_frame (frame);
4551
4552 CHECK_STRING (color);
4553
4554 if (w32_defined_color (f, SDATA (color), &foo, 0))
4555 return list3 (make_number ((GetRValue (foo.pixel) << 8)
4556 | GetRValue (foo.pixel)),
4557 make_number ((GetGValue (foo.pixel) << 8)
4558 | GetGValue (foo.pixel)),
4559 make_number ((GetBValue (foo.pixel) << 8)
4560 | GetBValue (foo.pixel)));
4561 else
4562 return Qnil;
4563 }
4564
4565 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
4566 doc: /* Internal function called by `display-color-p', which see. */)
4567 (Lisp_Object display)
4568 {
4569 struct w32_display_info *dpyinfo = check_x_display_info (display);
4570
4571 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
4572 return Qnil;
4573
4574 return Qt;
4575 }
4576
4577 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
4578 Sx_display_grayscale_p, 0, 1, 0,
4579 doc: /* Return t if DISPLAY supports shades of gray.
4580 Note that color displays do support shades of gray.
4581 The optional argument DISPLAY specifies which display to ask about.
4582 DISPLAY should be either a frame or a display name (a string).
4583 If omitted or nil, that stands for the selected frame's display. */)
4584 (Lisp_Object display)
4585 {
4586 struct w32_display_info *dpyinfo = check_x_display_info (display);
4587
4588 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
4589 return Qnil;
4590
4591 return Qt;
4592 }
4593
4594 DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
4595 Sx_display_pixel_width, 0, 1, 0,
4596 doc: /* Return the width in pixels of DISPLAY.
4597 The optional argument DISPLAY specifies which display to ask about.
4598 DISPLAY should be either a frame or a display name (a string).
4599 If omitted or nil, that stands for the selected frame's display. */)
4600 (Lisp_Object display)
4601 {
4602 struct w32_display_info *dpyinfo = check_x_display_info (display);
4603
4604 return make_number (x_display_pixel_width (dpyinfo));
4605 }
4606
4607 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4608 Sx_display_pixel_height, 0, 1, 0,
4609 doc: /* Return the height in pixels of DISPLAY.
4610 The optional argument DISPLAY specifies which display to ask about.
4611 DISPLAY should be either a frame or a display name (a string).
4612 If omitted or nil, that stands for the selected frame's display. */)
4613 (Lisp_Object display)
4614 {
4615 struct w32_display_info *dpyinfo = check_x_display_info (display);
4616
4617 return make_number (x_display_pixel_height (dpyinfo));
4618 }
4619
4620 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
4621 0, 1, 0,
4622 doc: /* Return the number of bitplanes of DISPLAY.
4623 The optional argument DISPLAY specifies which display to ask about.
4624 DISPLAY should be either a frame or a display name (a string).
4625 If omitted or nil, that stands for the selected frame's display. */)
4626 (Lisp_Object display)
4627 {
4628 struct w32_display_info *dpyinfo = check_x_display_info (display);
4629
4630 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
4631 }
4632
4633 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
4634 0, 1, 0,
4635 doc: /* Return the number of color cells of DISPLAY.
4636 The optional argument DISPLAY specifies which display to ask about.
4637 DISPLAY should be either a frame or a display name (a string).
4638 If omitted or nil, that stands for the selected frame's display. */)
4639 (Lisp_Object display)
4640 {
4641 struct w32_display_info *dpyinfo = check_x_display_info (display);
4642 HDC hdc;
4643 int cap;
4644
4645 hdc = GetDC (dpyinfo->root_window);
4646 if (dpyinfo->has_palette)
4647 cap = GetDeviceCaps (hdc, SIZEPALETTE);
4648 else
4649 cap = GetDeviceCaps (hdc, NUMCOLORS);
4650
4651 /* We force 24+ bit depths to 24-bit, both to prevent an overflow
4652 and because probably is more meaningful on Windows anyway */
4653 if (cap < 0)
4654 cap = 1 << min (dpyinfo->n_planes * dpyinfo->n_cbits, 24);
4655
4656 ReleaseDC (dpyinfo->root_window, hdc);
4657
4658 return make_number (cap);
4659 }
4660
4661 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
4662 Sx_server_max_request_size,
4663 0, 1, 0,
4664 doc: /* Return the maximum request size of the server of DISPLAY.
4665 The optional argument DISPLAY specifies which display to ask about.
4666 DISPLAY should be either a frame or a display name (a string).
4667 If omitted or nil, that stands for the selected frame's display. */)
4668 (Lisp_Object display)
4669 {
4670 return make_number (1);
4671 }
4672
4673 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
4674 doc: /* Return the "vendor ID" string of the W32 system (Microsoft).
4675 The optional argument DISPLAY specifies which display to ask about.
4676 DISPLAY should be either a frame or a display name (a string).
4677 If omitted or nil, that stands for the selected frame's display. */)
4678 (Lisp_Object display)
4679 {
4680 return build_string ("Microsoft Corp.");
4681 }
4682
4683 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
4684 doc: /* Return the version numbers of the server of DISPLAY.
4685 The value is a list of three integers: the major and minor
4686 version numbers of the X Protocol in use, and the distributor-specific
4687 release number. See also the function `x-server-vendor'.
4688
4689 The optional argument DISPLAY specifies which display to ask about.
4690 DISPLAY should be either a frame or a display name (a string).
4691 If omitted or nil, that stands for the selected frame's display. */)
4692 (Lisp_Object display)
4693 {
4694 return Fcons (make_number (w32_major_version),
4695 Fcons (make_number (w32_minor_version),
4696 Fcons (make_number (w32_build_number), Qnil)));
4697 }
4698
4699 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
4700 doc: /* Return the number of screens on the server of DISPLAY.
4701 The optional argument DISPLAY specifies which display to ask about.
4702 DISPLAY should be either a frame or a display name (a string).
4703 If omitted or nil, that stands for the selected frame's display. */)
4704 (Lisp_Object display)
4705 {
4706 return make_number (1);
4707 }
4708
4709 DEFUN ("x-display-mm-height", Fx_display_mm_height,
4710 Sx_display_mm_height, 0, 1, 0,
4711 doc: /* Return the height in millimeters of DISPLAY.
4712 The optional argument DISPLAY specifies which display to ask about.
4713 DISPLAY should be either a frame or a display name (a string).
4714 If omitted or nil, that stands for the selected frame's display. */)
4715 (Lisp_Object display)
4716 {
4717 struct w32_display_info *dpyinfo = check_x_display_info (display);
4718 HDC hdc;
4719 int cap;
4720
4721 hdc = GetDC (dpyinfo->root_window);
4722
4723 cap = GetDeviceCaps (hdc, VERTSIZE);
4724
4725 ReleaseDC (dpyinfo->root_window, hdc);
4726
4727 return make_number (cap);
4728 }
4729
4730 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4731 doc: /* Return the width in millimeters of DISPLAY.
4732 The optional argument DISPLAY specifies which display to ask about.
4733 DISPLAY should be either a frame or a display name (a string).
4734 If omitted or nil, that stands for the selected frame's display. */)
4735 (Lisp_Object display)
4736 {
4737 struct w32_display_info *dpyinfo = check_x_display_info (display);
4738
4739 HDC hdc;
4740 int cap;
4741
4742 hdc = GetDC (dpyinfo->root_window);
4743
4744 cap = GetDeviceCaps (hdc, HORZSIZE);
4745
4746 ReleaseDC (dpyinfo->root_window, hdc);
4747
4748 return make_number (cap);
4749 }
4750
4751 DEFUN ("x-display-backing-store", Fx_display_backing_store,
4752 Sx_display_backing_store, 0, 1, 0,
4753 doc: /* Return an indication of whether DISPLAY does backing store.
4754 The value may be `always', `when-mapped', or `not-useful'.
4755 The optional argument DISPLAY specifies which display to ask about.
4756 DISPLAY should be either a frame or a display name (a string).
4757 If omitted or nil, that stands for the selected frame's display. */)
4758 (Lisp_Object display)
4759 {
4760 return intern ("not-useful");
4761 }
4762
4763 DEFUN ("x-display-visual-class", Fx_display_visual_class,
4764 Sx_display_visual_class, 0, 1, 0,
4765 doc: /* Return the visual class of DISPLAY.
4766 The value is one of the symbols `static-gray', `gray-scale',
4767 `static-color', `pseudo-color', `true-color', or `direct-color'.
4768
4769 The optional argument DISPLAY specifies which display to ask about.
4770 DISPLAY should be either a frame or a display name (a string).
4771 If omitted or nil, that stands for the selected frame's display. */)
4772 (Lisp_Object display)
4773 {
4774 struct w32_display_info *dpyinfo = check_x_display_info (display);
4775 Lisp_Object result = Qnil;
4776
4777 if (dpyinfo->has_palette)
4778 result = intern ("pseudo-color");
4779 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
4780 result = intern ("static-grey");
4781 else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
4782 result = intern ("static-color");
4783 else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
4784 result = intern ("true-color");
4785
4786 return result;
4787 }
4788
4789 DEFUN ("x-display-save-under", Fx_display_save_under,
4790 Sx_display_save_under, 0, 1, 0,
4791 doc: /* Return t if DISPLAY supports the save-under feature.
4792 The optional argument DISPLAY specifies which display to ask about.
4793 DISPLAY should be either a frame or a display name (a string).
4794 If omitted or nil, that stands for the selected frame's display. */)
4795 (Lisp_Object display)
4796 {
4797 return Qnil;
4798 }
4799
4800 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
4801 doc: /* Set the sound generated when the bell is rung.
4802 SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
4803 to use the corresponding system sound for the bell. The 'silent sound
4804 prevents Emacs from making any sound at all.
4805 SOUND is nil to use the normal beep. */)
4806 (Lisp_Object sound)
4807 {
4808 CHECK_SYMBOL (sound);
4809
4810 if (NILP (sound))
4811 sound_type = 0xFFFFFFFF;
4812 else if (EQ (sound, intern ("asterisk")))
4813 sound_type = MB_ICONASTERISK;
4814 else if (EQ (sound, intern ("exclamation")))
4815 sound_type = MB_ICONEXCLAMATION;
4816 else if (EQ (sound, intern ("hand")))
4817 sound_type = MB_ICONHAND;
4818 else if (EQ (sound, intern ("question")))
4819 sound_type = MB_ICONQUESTION;
4820 else if (EQ (sound, intern ("ok")))
4821 sound_type = MB_OK;
4822 else if (EQ (sound, intern ("silent")))
4823 sound_type = MB_EMACS_SILENT;
4824 else
4825 sound_type = 0xFFFFFFFF;
4826
4827 return sound;
4828 }
4829
4830 \f
4831 int
4832 x_pixel_width (register struct frame *f)
4833 {
4834 return FRAME_PIXEL_WIDTH (f);
4835 }
4836
4837 int
4838 x_pixel_height (register struct frame *f)
4839 {
4840 return FRAME_PIXEL_HEIGHT (f);
4841 }
4842
4843 int
4844 x_char_width (register struct frame *f)
4845 {
4846 return FRAME_COLUMN_WIDTH (f);
4847 }
4848
4849 int
4850 x_char_height (register struct frame *f)
4851 {
4852 return FRAME_LINE_HEIGHT (f);
4853 }
4854
4855 int
4856 x_screen_planes (register struct frame *f)
4857 {
4858 return FRAME_W32_DISPLAY_INFO (f)->n_planes;
4859 }
4860 \f
4861 /* Return the display structure for the display named NAME.
4862 Open a new connection if necessary. */
4863
4864 struct w32_display_info *
4865 x_display_info_for_name (Lisp_Object name)
4866 {
4867 Lisp_Object names;
4868 struct w32_display_info *dpyinfo;
4869
4870 CHECK_STRING (name);
4871
4872 for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
4873 dpyinfo && !NILP (w32_display_name_list);
4874 dpyinfo = dpyinfo->next, names = XCDR (names))
4875 {
4876 Lisp_Object tem;
4877 tem = Fstring_equal (XCAR (XCAR (names)), name);
4878 if (!NILP (tem))
4879 return dpyinfo;
4880 }
4881
4882 /* Use this general default value to start with. */
4883 Vx_resource_name = Vinvocation_name;
4884
4885 validate_x_resource_name ();
4886
4887 dpyinfo = w32_term_init (name, (unsigned char *)0,
4888 SSDATA (Vx_resource_name));
4889
4890 if (dpyinfo == 0)
4891 error ("Cannot connect to server %s", SDATA (name));
4892
4893 w32_in_use = 1;
4894 XSETFASTINT (Vwindow_system_version, w32_major_version);
4895
4896 return dpyinfo;
4897 }
4898
4899 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
4900 1, 3, 0, doc: /* Open a connection to a display server.
4901 DISPLAY is the name of the display to connect to.
4902 Optional second arg XRM-STRING is a string of resources in xrdb format.
4903 If the optional third arg MUST-SUCCEED is non-nil,
4904 terminate Emacs if we can't open the connection.
4905 \(In the Nextstep version, the last two arguments are currently ignored.) */)
4906 (Lisp_Object display, Lisp_Object xrm_string, Lisp_Object must_succeed)
4907 {
4908 unsigned char *xrm_option;
4909 struct w32_display_info *dpyinfo;
4910
4911 CHECK_STRING (display);
4912
4913 /* Signal an error in order to encourage correct use from callers.
4914 * If we ever support multiple window systems in the same Emacs,
4915 * we'll need callers to be precise about what window system they
4916 * want. */
4917
4918 if (strcmp (SSDATA (display), "w32") != 0)
4919 error ("The name of the display in this Emacs must be \"w32\"");
4920
4921 /* If initialization has already been done, return now to avoid
4922 overwriting critical parts of one_w32_display_info. */
4923 if (w32_in_use)
4924 return Qnil;
4925
4926 if (! NILP (xrm_string))
4927 CHECK_STRING (xrm_string);
4928
4929 #if 0
4930 if (! EQ (Vwindow_system, intern ("w32")))
4931 error ("Not using Microsoft Windows");
4932 #endif
4933
4934 /* Allow color mapping to be defined externally; first look in user's
4935 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
4936 {
4937 Lisp_Object color_file;
4938 struct gcpro gcpro1;
4939
4940 color_file = build_string ("~/rgb.txt");
4941
4942 GCPRO1 (color_file);
4943
4944 if (NILP (Ffile_readable_p (color_file)))
4945 color_file =
4946 Fexpand_file_name (build_string ("rgb.txt"),
4947 Fsymbol_value (intern ("data-directory")));
4948
4949 Vw32_color_map = Fx_load_color_file (color_file);
4950
4951 UNGCPRO;
4952 }
4953 if (NILP (Vw32_color_map))
4954 Vw32_color_map = w32_default_color_map ();
4955
4956 /* Merge in system logical colors. */
4957 add_system_logical_colors_to_map (&Vw32_color_map);
4958
4959 if (! NILP (xrm_string))
4960 xrm_option = SDATA (xrm_string);
4961 else
4962 xrm_option = (unsigned char *) 0;
4963
4964 /* Use this general default value to start with. */
4965 /* First remove .exe suffix from invocation-name - it looks ugly. */
4966 {
4967 char basename[ MAX_PATH ], *str;
4968
4969 strcpy (basename, SDATA (Vinvocation_name));
4970 str = strrchr (basename, '.');
4971 if (str) *str = 0;
4972 Vinvocation_name = build_string (basename);
4973 }
4974 Vx_resource_name = Vinvocation_name;
4975
4976 validate_x_resource_name ();
4977
4978 /* This is what opens the connection and sets x_current_display.
4979 This also initializes many symbols, such as those used for input. */
4980 dpyinfo = w32_term_init (display, xrm_option,
4981 SSDATA (Vx_resource_name));
4982
4983 if (dpyinfo == 0)
4984 {
4985 if (!NILP (must_succeed))
4986 fatal ("Cannot connect to server %s.\n",
4987 SDATA (display));
4988 else
4989 error ("Cannot connect to server %s", SDATA (display));
4990 }
4991
4992 w32_in_use = 1;
4993
4994 XSETFASTINT (Vwindow_system_version, w32_major_version);
4995 return Qnil;
4996 }
4997
4998 DEFUN ("x-close-connection", Fx_close_connection,
4999 Sx_close_connection, 1, 1, 0,
5000 doc: /* Close the connection to DISPLAY's server.
5001 For DISPLAY, specify either a frame or a display name (a string).
5002 If DISPLAY is nil, that stands for the selected frame's display. */)
5003 (Lisp_Object display)
5004 {
5005 struct w32_display_info *dpyinfo = check_x_display_info (display);
5006
5007 if (dpyinfo->reference_count > 0)
5008 error ("Display still has frames on it");
5009
5010 block_input ();
5011 x_destroy_all_bitmaps (dpyinfo);
5012
5013 x_delete_display (dpyinfo);
5014 unblock_input ();
5015
5016 return Qnil;
5017 }
5018
5019 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
5020 doc: /* Return the list of display names that Emacs has connections to. */)
5021 (void)
5022 {
5023 Lisp_Object tail, result;
5024
5025 result = Qnil;
5026 for (tail = w32_display_name_list; CONSP (tail); tail = XCDR (tail))
5027 result = Fcons (XCAR (XCAR (tail)), result);
5028
5029 return result;
5030 }
5031
5032 DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
5033 doc: /* If ON is non-nil, report X errors as soon as the erring request is made.
5034 This function only has an effect on X Windows. With MS Windows, it is
5035 defined but does nothing.
5036
5037 If ON is nil, allow buffering of requests.
5038 Turning on synchronization prohibits the Xlib routines from buffering
5039 requests and seriously degrades performance, but makes debugging much
5040 easier.
5041 The optional second argument TERMINAL specifies which display to act on.
5042 TERMINAL should be a terminal object, a frame or a display name (a string).
5043 If TERMINAL is omitted or nil, that stands for the selected frame's display. */)
5044 (Lisp_Object on, Lisp_Object display)
5045 {
5046 return Qnil;
5047 }
5048
5049
5050 \f
5051 /***********************************************************************
5052 Window properties
5053 ***********************************************************************/
5054
5055 #if 0 /* TODO : port window properties to W32 */
5056
5057 DEFUN ("x-change-window-property", Fx_change_window_property,
5058 Sx_change_window_property, 2, 6, 0,
5059 doc: /* Change window property PROP to VALUE on the X window of FRAME.
5060 PROP must be a string. VALUE may be a string or a list of conses,
5061 numbers and/or strings. If an element in the list is a string, it is
5062 converted to an atom and the value of the Atom is used. If an element
5063 is a cons, it is converted to a 32 bit number where the car is the 16
5064 top bits and the cdr is the lower 16 bits.
5065
5066 FRAME nil or omitted means use the selected frame.
5067 If TYPE is given and non-nil, it is the name of the type of VALUE.
5068 If TYPE is not given or nil, the type is STRING.
5069 FORMAT gives the size in bits of each element if VALUE is a list.
5070 It must be one of 8, 16 or 32.
5071 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
5072 If OUTER-P is non-nil, the property is changed for the outer X window of
5073 FRAME. Default is to change on the edit X window. */)
5074 (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
5075 Lisp_Object type, Lisp_Object format, Lisp_Object outer_p)
5076 {
5077 struct frame *f = check_x_frame (frame);
5078 Atom prop_atom;
5079
5080 CHECK_STRING (prop);
5081 CHECK_STRING (value);
5082
5083 block_input ();
5084 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
5085 XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
5086 prop_atom, XA_STRING, 8, PropModeReplace,
5087 SDATA (value), SCHARS (value));
5088
5089 /* Make sure the property is set when we return. */
5090 XFlush (FRAME_W32_DISPLAY (f));
5091 unblock_input ();
5092
5093 return value;
5094 }
5095
5096
5097 DEFUN ("x-delete-window-property", Fx_delete_window_property,
5098 Sx_delete_window_property, 1, 2, 0,
5099 doc: /* Remove window property PROP from X window of FRAME.
5100 FRAME nil or omitted means use the selected frame. Value is PROP. */)
5101 (Lisp_Object prop, Lisp_Object frame)
5102 {
5103 struct frame *f = check_x_frame (frame);
5104 Atom prop_atom;
5105
5106 CHECK_STRING (prop);
5107 block_input ();
5108 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
5109 XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
5110
5111 /* Make sure the property is removed when we return. */
5112 XFlush (FRAME_W32_DISPLAY (f));
5113 unblock_input ();
5114
5115 return prop;
5116 }
5117
5118
5119 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
5120 1, 6, 0,
5121 doc: /* Value is the value of window property PROP on FRAME.
5122 If FRAME is nil or omitted, use the selected frame.
5123
5124 On X Windows, the following optional arguments are also accepted:
5125 If TYPE is nil or omitted, get the property as a string.
5126 Otherwise TYPE is the name of the atom that denotes the type expected.
5127 If SOURCE is non-nil, get the property on that window instead of from
5128 FRAME. The number 0 denotes the root window.
5129 If DELETE-P is non-nil, delete the property after retrieving it.
5130 If VECTOR-RET-P is non-nil, don't return a string but a vector of values.
5131
5132 On MS Windows, this function accepts but ignores those optional arguments.
5133
5134 Value is nil if FRAME hasn't a property with name PROP or if PROP has
5135 no value of TYPE (always string in the MS Windows case). */)
5136 (Lisp_Object prop, Lisp_Object frame, Lisp_Object type,
5137 Lisp_Object source, Lisp_Object delete_p, Lisp_Object vector_ret_p)
5138 {
5139 struct frame *f = check_x_frame (frame);
5140 Atom prop_atom;
5141 int rc;
5142 Lisp_Object prop_value = Qnil;
5143 char *tmp_data = NULL;
5144 Atom actual_type;
5145 int actual_format;
5146 unsigned long actual_size, bytes_remaining;
5147
5148 CHECK_STRING (prop);
5149 block_input ();
5150 prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
5151 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
5152 prop_atom, 0, 0, False, XA_STRING,
5153 &actual_type, &actual_format, &actual_size,
5154 &bytes_remaining, (unsigned char **) &tmp_data);
5155 if (rc == Success)
5156 {
5157 int size = bytes_remaining;
5158
5159 XFree (tmp_data);
5160 tmp_data = NULL;
5161
5162 rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
5163 prop_atom, 0, bytes_remaining,
5164 False, XA_STRING,
5165 &actual_type, &actual_format,
5166 &actual_size, &bytes_remaining,
5167 (unsigned char **) &tmp_data);
5168 if (rc == Success)
5169 prop_value = make_string (tmp_data, size);
5170
5171 XFree (tmp_data);
5172 }
5173
5174 unblock_input ();
5175
5176 return prop_value;
5177
5178 return Qnil;
5179 }
5180
5181 #endif /* TODO */
5182
5183 \f
5184 /***********************************************************************
5185 Busy cursor
5186 ***********************************************************************/
5187
5188 void
5189 w32_note_current_window (void)
5190 {
5191 struct frame * f = SELECTED_FRAME ();
5192
5193 if (!FRAME_W32_P (f))
5194 return;
5195
5196 hourglass_hwnd = FRAME_W32_WINDOW (f);
5197 }
5198
5199 void
5200 show_hourglass (struct atimer *timer)
5201 {
5202 struct frame *f;
5203
5204 hourglass_atimer = NULL;
5205
5206 block_input ();
5207 f = x_window_to_frame (&one_w32_display_info,
5208 hourglass_hwnd);
5209
5210 if (f)
5211 f->output_data.w32->hourglass_p = 0;
5212 else
5213 f = SELECTED_FRAME ();
5214
5215 if (!FRAME_W32_P (f))
5216 return;
5217
5218 w32_show_hourglass (f);
5219 unblock_input ();
5220 }
5221
5222 void
5223 hide_hourglass (void)
5224 {
5225 block_input ();
5226 w32_hide_hourglass ();
5227 unblock_input ();
5228 }
5229
5230
5231 /* Display an hourglass cursor. Set the hourglass_p flag in display info
5232 to indicate that an hourglass cursor is shown. */
5233
5234 static void
5235 w32_show_hourglass (struct frame *f)
5236 {
5237 if (!hourglass_shown_p)
5238 {
5239 f->output_data.w32->hourglass_p = 1;
5240 if (!menubar_in_use && !current_popup_menu)
5241 SetCursor (f->output_data.w32->hourglass_cursor);
5242 hourglass_shown_p = 1;
5243 }
5244 }
5245
5246
5247 /* Hide the hourglass cursor on all frames, if it is currently shown. */
5248
5249 static void
5250 w32_hide_hourglass (void)
5251 {
5252 if (hourglass_shown_p)
5253 {
5254 struct frame *f = x_window_to_frame (&one_w32_display_info,
5255 hourglass_hwnd);
5256 if (f)
5257 f->output_data.w32->hourglass_p = 0;
5258 else
5259 /* If frame was deleted, restore to selected frame's cursor. */
5260 f = SELECTED_FRAME ();
5261
5262 if (FRAME_W32_P (f))
5263 SetCursor (f->output_data.w32->current_cursor);
5264 else
5265 /* No cursors on non GUI frames - restore to stock arrow cursor. */
5266 SetCursor (w32_load_cursor (IDC_ARROW));
5267
5268 hourglass_shown_p = 0;
5269 }
5270 }
5271
5272
5273 \f
5274 /***********************************************************************
5275 Tool tips
5276 ***********************************************************************/
5277
5278 static Lisp_Object x_create_tip_frame (struct w32_display_info *,
5279 Lisp_Object, Lisp_Object);
5280 static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object,
5281 Lisp_Object, int, int, int *, int *);
5282
5283 /* The frame of a currently visible tooltip. */
5284
5285 Lisp_Object tip_frame;
5286
5287 /* If non-nil, a timer started that hides the last tooltip when it
5288 fires. */
5289
5290 Lisp_Object tip_timer;
5291 Window tip_window;
5292
5293 /* If non-nil, a vector of 3 elements containing the last args
5294 with which x-show-tip was called. See there. */
5295
5296 Lisp_Object last_show_tip_args;
5297
5298
5299 static Lisp_Object
5300 unwind_create_tip_frame (Lisp_Object frame)
5301 {
5302 Lisp_Object deleted;
5303
5304 deleted = unwind_create_frame (frame);
5305 if (EQ (deleted, Qt))
5306 {
5307 tip_window = NULL;
5308 tip_frame = Qnil;
5309 }
5310
5311 return deleted;
5312 }
5313
5314
5315 /* Create a frame for a tooltip on the display described by DPYINFO.
5316 PARMS is a list of frame parameters. TEXT is the string to
5317 display in the tip frame. Value is the frame.
5318
5319 Note that functions called here, esp. x_default_parameter can
5320 signal errors, for instance when a specified color name is
5321 undefined. We have to make sure that we're in a consistent state
5322 when this happens. */
5323
5324 static Lisp_Object
5325 x_create_tip_frame (struct w32_display_info *dpyinfo,
5326 Lisp_Object parms, Lisp_Object text)
5327 {
5328 struct frame *f;
5329 Lisp_Object frame;
5330 Lisp_Object name;
5331 long window_prompting = 0;
5332 int width, height;
5333 ptrdiff_t count = SPECPDL_INDEX ();
5334 struct gcpro gcpro1, gcpro2, gcpro3;
5335 struct kboard *kb;
5336 int face_change_count_before = face_change_count;
5337 Lisp_Object buffer;
5338 struct buffer *old_buffer;
5339
5340 check_w32 ();
5341
5342 /* Use this general default value to start with until we know if
5343 this frame has a specified name. */
5344 Vx_resource_name = Vinvocation_name;
5345
5346 kb = dpyinfo->terminal->kboard;
5347
5348 /* The calls to x_get_arg remove elements from PARMS, so copy it to
5349 avoid destructive changes behind our caller's back. */
5350 parms = Fcopy_alist (parms);
5351
5352 /* Get the name of the frame to use for resource lookup. */
5353 name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
5354 if (!STRINGP (name)
5355 && !EQ (name, Qunbound)
5356 && !NILP (name))
5357 error ("Invalid frame name--not a string or nil");
5358 Vx_resource_name = name;
5359
5360 frame = Qnil;
5361 GCPRO3 (parms, name, frame);
5362 /* Make a frame without minibuffer nor mode-line. */
5363 f = make_frame (0);
5364 f->wants_modeline = 0;
5365 XSETFRAME (frame, f);
5366
5367 buffer = Fget_buffer_create (build_string (" *tip*"));
5368 /* Use set_window_buffer instead of Fset_window_buffer (see
5369 discussion of bug#11984, bug#12025, bug#12026). */
5370 set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, 0, 0);
5371 old_buffer = current_buffer;
5372 set_buffer_internal_1 (XBUFFER (buffer));
5373 bset_truncate_lines (current_buffer, Qnil);
5374 specbind (Qinhibit_read_only, Qt);
5375 specbind (Qinhibit_modification_hooks, Qt);
5376 Ferase_buffer ();
5377 Finsert (1, &text);
5378 set_buffer_internal_1 (old_buffer);
5379
5380 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
5381 record_unwind_protect (unwind_create_tip_frame, frame);
5382
5383 /* By setting the output method, we're essentially saying that
5384 the frame is live, as per FRAME_LIVE_P. If we get a signal
5385 from this point on, x_destroy_window might screw up reference
5386 counts etc. */
5387 f->terminal = dpyinfo->terminal;
5388 f->output_method = output_w32;
5389 f->output_data.w32 = xzalloc (sizeof (struct w32_output));
5390
5391 FRAME_FONTSET (f) = -1;
5392 fset_icon_name (f, Qnil);
5393
5394 #ifdef GLYPH_DEBUG
5395 image_cache_refcount =
5396 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
5397 dpyinfo_refcount = dpyinfo->reference_count;
5398 #endif /* GLYPH_DEBUG */
5399 FRAME_KBOARD (f) = kb;
5400 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5401 f->output_data.w32->explicit_parent = 0;
5402
5403 /* Set the name; the functions to which we pass f expect the name to
5404 be set. */
5405 if (EQ (name, Qunbound) || NILP (name))
5406 {
5407 fset_name (f, build_string (dpyinfo->w32_id_name));
5408 f->explicit_name = 0;
5409 }
5410 else
5411 {
5412 fset_name (f, name);
5413 f->explicit_name = 1;
5414 /* use the frame's title when getting resources for this frame. */
5415 specbind (Qx_resource_name, name);
5416 }
5417
5418 f->resx = dpyinfo->resx;
5419 f->resy = dpyinfo->resy;
5420
5421 if (uniscribe_available)
5422 register_font_driver (&uniscribe_font_driver, f);
5423 register_font_driver (&w32font_driver, f);
5424
5425 x_default_parameter (f, parms, Qfont_backend, Qnil,
5426 "fontBackend", "FontBackend", RES_TYPE_STRING);
5427
5428 /* Extract the window parameters from the supplied values
5429 that are needed to determine window geometry. */
5430 x_default_font_parameter (f, parms);
5431
5432 x_default_parameter (f, parms, Qborder_width, make_number (2),
5433 "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
5434 /* This defaults to 2 in order to match xterm. We recognize either
5435 internalBorderWidth or internalBorder (which is what xterm calls
5436 it). */
5437 if (NILP (Fassq (Qinternal_border_width, parms)))
5438 {
5439 Lisp_Object value;
5440
5441 value = x_get_arg (dpyinfo, parms, Qinternal_border_width,
5442 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
5443 if (! EQ (value, Qunbound))
5444 parms = Fcons (Fcons (Qinternal_border_width, value),
5445 parms);
5446 }
5447 x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
5448 "internalBorderWidth", "internalBorderWidth",
5449 RES_TYPE_NUMBER);
5450
5451 /* Also do the stuff which must be set before the window exists. */
5452 x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
5453 "foreground", "Foreground", RES_TYPE_STRING);
5454 x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
5455 "background", "Background", RES_TYPE_STRING);
5456 x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
5457 "pointerColor", "Foreground", RES_TYPE_STRING);
5458 x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
5459 "cursorColor", "Foreground", RES_TYPE_STRING);
5460 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5461 "borderColor", "BorderColor", RES_TYPE_STRING);
5462
5463 /* Init faces before x_default_parameter is called for scroll-bar
5464 parameters because that function calls x_set_scroll_bar_width,
5465 which calls change_frame_size, which calls Fset_window_buffer,
5466 which runs hooks, which call Fvertical_motion. At the end, we
5467 end up in init_iterator with a null face cache, which should not
5468 happen. */
5469 init_frame_faces (f);
5470
5471 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
5472 f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
5473
5474 window_prompting = x_figure_window_size (f, parms, 0);
5475
5476 /* No fringes on tip frame. */
5477 f->fringe_cols = 0;
5478 f->left_fringe_width = 0;
5479 f->right_fringe_width = 0;
5480
5481 block_input ();
5482 my_create_tip_window (f);
5483 unblock_input ();
5484
5485 x_make_gc (f);
5486
5487 x_default_parameter (f, parms, Qauto_raise, Qnil,
5488 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5489 x_default_parameter (f, parms, Qauto_lower, Qnil,
5490 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
5491 x_default_parameter (f, parms, Qcursor_type, Qbox,
5492 "cursorType", "CursorType", RES_TYPE_SYMBOL);
5493
5494 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
5495 Change will not be effected unless different from the current
5496 FRAME_LINES (f). */
5497 width = FRAME_COLS (f);
5498 height = FRAME_LINES (f);
5499 FRAME_LINES (f) = 0;
5500 SET_FRAME_COLS (f, 0);
5501 change_frame_size (f, height, width, 1, 0, 0);
5502
5503 /* Add `tooltip' frame parameter's default value. */
5504 if (NILP (Fframe_parameter (frame, Qtooltip)))
5505 Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil));
5506
5507 /* Set up faces after all frame parameters are known. This call
5508 also merges in face attributes specified for new frames.
5509
5510 Frame parameters may be changed if .Xdefaults contains
5511 specifications for the default font. For example, if there is an
5512 `Emacs.default.attributeBackground: pink', the `background-color'
5513 attribute of the frame get's set, which let's the internal border
5514 of the tooltip frame appear in pink. Prevent this. */
5515 {
5516 Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
5517 Lisp_Object fg = Fframe_parameter (frame, Qforeground_color);
5518 Lisp_Object colors = Qnil;
5519
5520 /* Set tip_frame here, so that */
5521 tip_frame = frame;
5522 call2 (Qface_set_after_frame_default, frame, Qnil);
5523
5524 if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
5525 colors = Fcons (Fcons (Qbackground_color, bg), colors);
5526 if (!EQ (fg, Fframe_parameter (frame, Qforeground_color)))
5527 colors = Fcons (Fcons (Qforeground_color, fg), colors);
5528
5529 if (!NILP (colors))
5530 Fmodify_frame_parameters (frame, colors);
5531 }
5532
5533 f->no_split = 1;
5534
5535 UNGCPRO;
5536
5537 /* Now that the frame is official, it counts as a reference to
5538 its display. */
5539 FRAME_W32_DISPLAY_INFO (f)->reference_count++;
5540 f->terminal->reference_count++;
5541
5542 /* It is now ok to make the frame official even if we get an error
5543 below. And the frame needs to be on Vframe_list or making it
5544 visible won't work. */
5545 Vframe_list = Fcons (frame, Vframe_list);
5546
5547 /* Setting attributes of faces of the tooltip frame from resources
5548 and similar will increment face_change_count, which leads to the
5549 clearing of all current matrices. Since this isn't necessary
5550 here, avoid it by resetting face_change_count to the value it
5551 had before we created the tip frame. */
5552 face_change_count = face_change_count_before;
5553
5554 /* Discard the unwind_protect. */
5555 return unbind_to (count, frame);
5556 }
5557
5558
5559 /* Compute where to display tip frame F. PARMS is the list of frame
5560 parameters for F. DX and DY are specified offsets from the current
5561 location of the mouse. WIDTH and HEIGHT are the width and height
5562 of the tooltip. Return coordinates relative to the root window of
5563 the display in *ROOT_X, and *ROOT_Y. */
5564
5565 static void
5566 compute_tip_xy (struct frame *f,
5567 Lisp_Object parms, Lisp_Object dx, Lisp_Object dy,
5568 int width, int height, int *root_x, int *root_y)
5569 {
5570 Lisp_Object left, top;
5571 int min_x, min_y, max_x, max_y;
5572
5573 /* User-specified position? */
5574 left = Fcdr (Fassq (Qleft, parms));
5575 top = Fcdr (Fassq (Qtop, parms));
5576
5577 /* Move the tooltip window where the mouse pointer is. Resize and
5578 show it. */
5579 if (!INTEGERP (left) || !INTEGERP (top))
5580 {
5581 POINT pt;
5582
5583 /* Default min and max values. */
5584 min_x = 0;
5585 min_y = 0;
5586 max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f));
5587 max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f));
5588
5589 block_input ();
5590 GetCursorPos (&pt);
5591 *root_x = pt.x;
5592 *root_y = pt.y;
5593 unblock_input ();
5594
5595 /* If multiple monitor support is available, constrain the tip onto
5596 the current monitor. This improves the above by allowing negative
5597 co-ordinates if monitor positions are such that they are valid, and
5598 snaps a tooltip onto a single monitor if we are close to the edge
5599 where it would otherwise flow onto the other monitor (or into
5600 nothingness if there is a gap in the overlap). */
5601 if (monitor_from_point_fn && get_monitor_info_fn)
5602 {
5603 struct MONITOR_INFO info;
5604 HMONITOR monitor
5605 = monitor_from_point_fn (pt, MONITOR_DEFAULT_TO_NEAREST);
5606 info.cbSize = sizeof (info);
5607
5608 if (get_monitor_info_fn (monitor, &info))
5609 {
5610 min_x = info.rcWork.left;
5611 min_y = info.rcWork.top;
5612 max_x = info.rcWork.right;
5613 max_y = info.rcWork.bottom;
5614 }
5615 }
5616 }
5617
5618 if (INTEGERP (top))
5619 *root_y = XINT (top);
5620 else if (*root_y + XINT (dy) <= min_y)
5621 *root_y = min_y; /* Can happen for negative dy */
5622 else if (*root_y + XINT (dy) + height <= max_y)
5623 /* It fits below the pointer */
5624 *root_y += XINT (dy);
5625 else if (height + XINT (dy) + min_y <= *root_y)
5626 /* It fits above the pointer. */
5627 *root_y -= height + XINT (dy);
5628 else
5629 /* Put it on the top. */
5630 *root_y = min_y;
5631
5632 if (INTEGERP (left))
5633 *root_x = XINT (left);
5634 else if (*root_x + XINT (dx) <= min_x)
5635 *root_x = 0; /* Can happen for negative dx */
5636 else if (*root_x + XINT (dx) + width <= max_x)
5637 /* It fits to the right of the pointer. */
5638 *root_x += XINT (dx);
5639 else if (width + XINT (dx) + min_x <= *root_x)
5640 /* It fits to the left of the pointer. */
5641 *root_x -= width + XINT (dx);
5642 else
5643 /* Put it left justified on the screen -- it ought to fit that way. */
5644 *root_x = min_x;
5645 }
5646
5647
5648 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
5649 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
5650 A tooltip window is a small window displaying a string.
5651
5652 This is an internal function; Lisp code should call `tooltip-show'.
5653
5654 FRAME nil or omitted means use the selected frame.
5655
5656 PARMS is an optional list of frame parameters which can be
5657 used to change the tooltip's appearance.
5658
5659 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
5660 means use the default timeout of 5 seconds.
5661
5662 If the list of frame parameters PARMS contains a `left' parameter,
5663 the tooltip is displayed at that x-position. Otherwise it is
5664 displayed at the mouse position, with offset DX added (default is 5 if
5665 DX isn't specified). Likewise for the y-position; if a `top' frame
5666 parameter is specified, it determines the y-position of the tooltip
5667 window, otherwise it is displayed at the mouse position, with offset
5668 DY added (default is -10).
5669
5670 A tooltip's maximum size is specified by `x-max-tooltip-size'.
5671 Text larger than the specified size is clipped. */)
5672 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
5673 {
5674 struct frame *f;
5675 struct window *w;
5676 int root_x, root_y;
5677 struct buffer *old_buffer;
5678 struct text_pos pos;
5679 int i, width, height, seen_reversed_p;
5680 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5681 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5682 ptrdiff_t count = SPECPDL_INDEX ();
5683
5684 specbind (Qinhibit_redisplay, Qt);
5685
5686 GCPRO4 (string, parms, frame, timeout);
5687
5688 CHECK_STRING (string);
5689 f = check_x_frame (frame);
5690 if (NILP (timeout))
5691 timeout = make_number (5);
5692 else
5693 CHECK_NATNUM (timeout);
5694
5695 if (NILP (dx))
5696 dx = make_number (5);
5697 else
5698 CHECK_NUMBER (dx);
5699
5700 if (NILP (dy))
5701 dy = make_number (-10);
5702 else
5703 CHECK_NUMBER (dy);
5704
5705 if (NILP (last_show_tip_args))
5706 last_show_tip_args = Fmake_vector (make_number (3), Qnil);
5707
5708 if (!NILP (tip_frame))
5709 {
5710 Lisp_Object last_string = AREF (last_show_tip_args, 0);
5711 Lisp_Object last_frame = AREF (last_show_tip_args, 1);
5712 Lisp_Object last_parms = AREF (last_show_tip_args, 2);
5713
5714 if (EQ (frame, last_frame)
5715 && !NILP (Fequal (last_string, string))
5716 && !NILP (Fequal (last_parms, parms)))
5717 {
5718 struct frame *f = XFRAME (tip_frame);
5719
5720 /* Only DX and DY have changed. */
5721 if (!NILP (tip_timer))
5722 {
5723 Lisp_Object timer = tip_timer;
5724 tip_timer = Qnil;
5725 call1 (Qcancel_timer, timer);
5726 }
5727
5728 block_input ();
5729 compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
5730 FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
5731
5732 /* Put tooltip in topmost group and in position. */
5733 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
5734 root_x, root_y, 0, 0,
5735 SWP_NOSIZE | SWP_NOACTIVATE);
5736
5737 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5738 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
5739 0, 0, 0, 0,
5740 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
5741
5742 unblock_input ();
5743 goto start_timer;
5744 }
5745 }
5746
5747 /* Hide a previous tip, if any. */
5748 Fx_hide_tip ();
5749
5750 ASET (last_show_tip_args, 0, string);
5751 ASET (last_show_tip_args, 1, frame);
5752 ASET (last_show_tip_args, 2, parms);
5753
5754 /* Add default values to frame parameters. */
5755 if (NILP (Fassq (Qname, parms)))
5756 parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
5757 if (NILP (Fassq (Qinternal_border_width, parms)))
5758 parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
5759 if (NILP (Fassq (Qborder_width, parms)))
5760 parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
5761 if (NILP (Fassq (Qborder_color, parms)))
5762 parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
5763 if (NILP (Fassq (Qbackground_color, parms)))
5764 parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
5765 parms);
5766
5767 /* Block input until the tip has been fully drawn, to avoid crashes
5768 when drawing tips in menus. */
5769 block_input ();
5770
5771 /* Create a frame for the tooltip, and record it in the global
5772 variable tip_frame. */
5773 frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
5774 f = XFRAME (frame);
5775
5776 /* Set up the frame's root window. */
5777 w = XWINDOW (FRAME_ROOT_WINDOW (f));
5778 wset_left_col (w, make_number (0));
5779 wset_top_line (w, make_number (0));
5780
5781 if (CONSP (Vx_max_tooltip_size)
5782 && INTEGERP (XCAR (Vx_max_tooltip_size))
5783 && XINT (XCAR (Vx_max_tooltip_size)) > 0
5784 && INTEGERP (XCDR (Vx_max_tooltip_size))
5785 && XINT (XCDR (Vx_max_tooltip_size)) > 0)
5786 {
5787 wset_total_cols (w, XCAR (Vx_max_tooltip_size));
5788 wset_total_lines (w, XCDR (Vx_max_tooltip_size));
5789 }
5790 else
5791 {
5792 wset_total_cols (w, make_number (80));
5793 wset_total_lines (w, make_number (40));
5794 }
5795
5796 FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
5797 adjust_glyphs (f);
5798 w->pseudo_window_p = 1;
5799
5800 /* Display the tooltip text in a temporary buffer. */
5801 old_buffer = current_buffer;
5802 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
5803 bset_truncate_lines (current_buffer, Qnil);
5804 clear_glyph_matrix (w->desired_matrix);
5805 clear_glyph_matrix (w->current_matrix);
5806 SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
5807 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
5808
5809 /* Compute width and height of the tooltip. */
5810 width = height = seen_reversed_p = 0;
5811 for (i = 0; i < w->desired_matrix->nrows; ++i)
5812 {
5813 struct glyph_row *row = &w->desired_matrix->rows[i];
5814 struct glyph *last;
5815 int row_width;
5816
5817 /* Stop at the first empty row at the end. */
5818 if (!row->enabled_p || !row->displays_text_p)
5819 break;
5820
5821 /* Let the row go over the full width of the frame. */
5822 row->full_width_p = 1;
5823
5824 row_width = row->pixel_width;
5825 if (row->used[TEXT_AREA])
5826 {
5827 if (!row->reversed_p)
5828 {
5829 /* There's a glyph at the end of rows that is used to
5830 place the cursor there. Don't include the width of
5831 this glyph. */
5832 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5833 if (INTEGERP (last->object))
5834 row_width -= last->pixel_width;
5835 }
5836 else
5837 {
5838 /* There could be a stretch glyph at the beginning of R2L
5839 rows that is produced by extend_face_to_end_of_line.
5840 Don't count that glyph. */
5841 struct glyph *g = row->glyphs[TEXT_AREA];
5842
5843 if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
5844 {
5845 row_width -= g->pixel_width;
5846 seen_reversed_p = 1;
5847 }
5848 }
5849 }
5850
5851 height += row->height;
5852 width = max (width, row_width);
5853 }
5854
5855 /* If we've seen partial-length R2L rows, we need to re-adjust the
5856 tool-tip frame width and redisplay it again, to avoid over-wide
5857 tips due to the stretch glyph that extends R2L lines to full
5858 width of the frame. */
5859 if (seen_reversed_p)
5860 {
5861 /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
5862 not in pixels. */
5863 width /= WINDOW_FRAME_COLUMN_WIDTH (w);
5864 wset_total_cols (w, make_number (width));
5865 FRAME_TOTAL_COLS (f) = width;
5866 adjust_glyphs (f);
5867 w->pseudo_window_p = 1;
5868 clear_glyph_matrix (w->desired_matrix);
5869 clear_glyph_matrix (w->current_matrix);
5870 try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
5871 width = height = 0;
5872 /* Recompute width and height of the tooltip. */
5873 for (i = 0; i < w->desired_matrix->nrows; ++i)
5874 {
5875 struct glyph_row *row = &w->desired_matrix->rows[i];
5876 struct glyph *last;
5877 int row_width;
5878
5879 if (!row->enabled_p || !row->displays_text_p)
5880 break;
5881 row->full_width_p = 1;
5882 row_width = row->pixel_width;
5883 if (row->used[TEXT_AREA] && !row->reversed_p)
5884 {
5885 last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
5886 if (INTEGERP (last->object))
5887 row_width -= last->pixel_width;
5888 }
5889
5890 height += row->height;
5891 width = max (width, row_width);
5892 }
5893 }
5894
5895 /* Round up the height to an integral multiple of FRAME_LINE_HEIGHT. */
5896 if (height % FRAME_LINE_HEIGHT (f) != 0)
5897 height += FRAME_LINE_HEIGHT (f) - height % FRAME_LINE_HEIGHT (f);
5898 /* Add the frame's internal border to the width and height the w32
5899 window should have. */
5900 height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5901 width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
5902
5903 /* Move the tooltip window where the mouse pointer is. Resize and
5904 show it. */
5905 compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
5906
5907 {
5908 /* Adjust Window size to take border into account. */
5909 RECT rect;
5910 rect.left = rect.top = 0;
5911 rect.right = width;
5912 rect.bottom = height;
5913 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5914 FRAME_EXTERNAL_MENU_BAR (f));
5915
5916 /* Position and size tooltip, and put it in the topmost group.
5917 The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a
5918 peculiarity of w32 display: without it, some fonts cause the
5919 last character of the tip to be truncated or wrapped around to
5920 the next line. */
5921 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
5922 root_x, root_y,
5923 rect.right - rect.left + FRAME_COLUMN_WIDTH (f),
5924 rect.bottom - rect.top, SWP_NOACTIVATE);
5925
5926 /* Ensure tooltip is on top of other topmost windows (eg menus). */
5927 SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
5928 0, 0, 0, 0,
5929 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
5930
5931 /* Let redisplay know that we have made the frame visible already. */
5932 f->async_visible = 1;
5933
5934 ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
5935 }
5936
5937 /* Draw into the window. */
5938 w->must_be_updated_p = 1;
5939 update_single_window (w, 1);
5940
5941 unblock_input ();
5942
5943 /* Restore original current buffer. */
5944 set_buffer_internal_1 (old_buffer);
5945 windows_or_buffers_changed = old_windows_or_buffers_changed;
5946
5947 start_timer:
5948 /* Let the tip disappear after timeout seconds. */
5949 tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
5950 intern ("x-hide-tip"));
5951
5952 UNGCPRO;
5953 return unbind_to (count, Qnil);
5954 }
5955
5956
5957 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
5958 doc: /* Hide the current tooltip window, if there is any.
5959 Value is t if tooltip was open, nil otherwise. */)
5960 (void)
5961 {
5962 ptrdiff_t count;
5963 Lisp_Object deleted, frame, timer;
5964 struct gcpro gcpro1, gcpro2;
5965
5966 /* Return quickly if nothing to do. */
5967 if (NILP (tip_timer) && NILP (tip_frame))
5968 return Qnil;
5969
5970 frame = tip_frame;
5971 timer = tip_timer;
5972 GCPRO2 (frame, timer);
5973 tip_frame = tip_timer = deleted = Qnil;
5974
5975 count = SPECPDL_INDEX ();
5976 specbind (Qinhibit_redisplay, Qt);
5977 specbind (Qinhibit_quit, Qt);
5978
5979 if (!NILP (timer))
5980 call1 (Qcancel_timer, timer);
5981
5982 if (FRAMEP (frame))
5983 {
5984 delete_frame (frame, Qnil);
5985 deleted = Qt;
5986 }
5987
5988 UNGCPRO;
5989 return unbind_to (count, deleted);
5990 }
5991 \f
5992 /***********************************************************************
5993 File selection dialog
5994 ***********************************************************************/
5995
5996 #define FILE_NAME_TEXT_FIELD edt1
5997 #define FILE_NAME_COMBO_BOX cmb13
5998 #define FILE_NAME_LIST lst1
5999
6000 #ifdef NTGUI_UNICODE
6001 #define GUISTR(x) (L ## x)
6002 typedef wchar_t guichar_t;
6003 #else /* !NTGUI_UNICODE */
6004 #define GUISTR(x) x
6005 typedef char guichar_t;
6006 #endif /* NTGUI_UNICODE */
6007
6008 /* Callback for altering the behavior of the Open File dialog.
6009 Makes the Filename text field contain "Current Directory" and be
6010 read-only when "Directories" is selected in the filter. This
6011 allows us to work around the fact that the standard Open File
6012 dialog does not support directories. */
6013 static UINT CALLBACK
6014 file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
6015 {
6016 if (msg == WM_NOTIFY)
6017 {
6018 #ifdef NTGUI_UNICODE
6019 OFNOTIFYW * notify = (OFNOTIFYW *)lParam;
6020 #else /* !NTGUI_UNICODE */
6021 OFNOTIFYA * notify = (OFNOTIFYA *)lParam;
6022 #endif /* NTGUI_UNICODE */
6023 /* Detect when the Filter dropdown is changed. */
6024 if (notify->hdr.code == CDN_TYPECHANGE
6025 || notify->hdr.code == CDN_INITDONE)
6026 {
6027 HWND dialog = GetParent (hwnd);
6028 HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD);
6029 HWND list = GetDlgItem (dialog, FILE_NAME_LIST);
6030
6031 /* At least on Windows 7, the above attempt to get the window handle
6032 to the File Name Text Field fails. The following code does the
6033 job though. Note that this code is based on my examination of the
6034 window hierarchy using Microsoft Spy++. bk */
6035 if (edit_control == NULL)
6036 {
6037 HWND tmp = GetDlgItem (dialog, FILE_NAME_COMBO_BOX);
6038 if (tmp)
6039 {
6040 tmp = GetWindow (tmp, GW_CHILD);
6041 if (tmp)
6042 edit_control = GetWindow (tmp, GW_CHILD);
6043 }
6044 }
6045
6046 /* Directories is in index 2. */
6047 if (notify->lpOFN->nFilterIndex == 2)
6048 {
6049 CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD,
6050 GUISTR ("Current Directory"));
6051 EnableWindow (edit_control, FALSE);
6052 /* Note that at least on Windows 7, the above call to EnableWindow
6053 disables the window that would ordinarily have focus. If we
6054 do not set focus to some other window here, focus will land in
6055 no man's land and the user will be unable to tab through the
6056 dialog box (pressing tab will only result in a beep).
6057 Avoid that problem by setting focus to the list here. */
6058 if (notify->hdr.code == CDN_INITDONE)
6059 SetFocus (list);
6060 }
6061 else
6062 {
6063 /* Don't override default filename on init done. */
6064 if (notify->hdr.code == CDN_TYPECHANGE)
6065 CommDlg_OpenSave_SetControlText (dialog,
6066 FILE_NAME_TEXT_FIELD,
6067 GUISTR (""));
6068 EnableWindow (edit_control, TRUE);
6069 }
6070 }
6071 }
6072 return 0;
6073 }
6074
6075 DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
6076 doc: /* Read file name, prompting with PROMPT in directory DIR.
6077 Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
6078 selection box, if specified. If MUSTMATCH is non-nil, the returned file
6079 or directory must exist.
6080
6081 This function is only defined on NS, MS Windows, and X Windows with the
6082 Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
6083 Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
6084 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
6085 {
6086 /* Filter index: 1: All Files, 2: Directories only */
6087 static const guichar_t filter[] =
6088 GUISTR ("All Files (*.*)\0*.*\0Directories\0*|*\0");
6089
6090 Lisp_Object filename = default_filename;
6091 struct frame *f = SELECTED_FRAME ();
6092 BOOL file_opened = FALSE;
6093 Lisp_Object orig_dir = dir;
6094 Lisp_Object orig_prompt = prompt;
6095
6096 /* If we compile with _WIN32_WINNT set to 0x0400 (for NT4
6097 compatibility) we end up with the old file dialogs. Define a big
6098 enough struct for the new dialog to trick GetOpenFileName into
6099 giving us the new dialogs on newer versions of Windows. */
6100 struct {
6101 #ifdef NTGUI_UNICODE
6102 OPENFILENAMEW details;
6103 #else /* !NTGUI_UNICODE */
6104 OPENFILENAMEA details;
6105 #endif /* NTGUI_UNICODE */
6106
6107 #if _WIN32_WINNT < 0x500 /* < win2k */
6108 PVOID pvReserved;
6109 DWORD dwReserved;
6110 DWORD FlagsEx;
6111 #endif /* < win2k */
6112 } new_file_details;
6113
6114 #ifdef NTGUI_UNICODE
6115 wchar_t filename_buf[MAX_PATH + 1];
6116 OPENFILENAMEW * file_details = &new_file_details.details;
6117 #else /* not NTGUI_UNICODE */
6118 char filename_buf[MAX_PATH + 1];
6119 OPENFILENAMEA * file_details = &new_file_details.details;
6120 #endif /* NTGUI_UNICODE */
6121
6122 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
6123 GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, filename);
6124
6125 {
6126 struct gcpro gcpro1, gcpro2;
6127 GCPRO2 (orig_dir, orig_prompt); /* There is no GCPRON, N>6. */
6128
6129 /* Note: under NTGUI_UNICODE, we do _NOT_ use ENCODE_FILE: the
6130 system file encoding expected by the platform APIs (e.g. Cygwin's
6131 POSIX implementation) may not the same as the encoding expected
6132 by the Windows API! */
6133
6134 CHECK_STRING (prompt);
6135 CHECK_STRING (dir);
6136
6137 dir = Fexpand_file_name (dir, Qnil);
6138
6139 if (STRINGP (filename))
6140 filename = Ffile_name_nondirectory (filename);
6141 else
6142 filename = empty_unibyte_string;
6143
6144 #ifdef CYGWIN
6145 dir = Fcygwin_convert_path_to_windows (dir, Qt);
6146 if (SCHARS (filename) > 0)
6147 filename = Fcygwin_convert_path_to_windows (filename, Qnil);
6148 #endif
6149
6150 CHECK_STRING (dir);
6151 CHECK_STRING (filename);
6152
6153 /* The code in file_dialog_callback that attempts to set the text
6154 of the file name edit window when handling the CDN_INITDONE
6155 WM_NOTIFY message does not work. Setting filename to "Current
6156 Directory" in the only_dir_p case here does work however. */
6157 if (SCHARS (filename) == 0 && ! NILP (only_dir_p))
6158 filename = build_string ("Current Directory");
6159
6160 /* Convert the values we've computed so far to system form. */
6161 #ifdef NTGUI_UNICODE
6162 to_unicode (prompt, &prompt);
6163 to_unicode (dir, &dir);
6164 to_unicode (filename, &filename);
6165 #else /* !NTGUI_UNICODE */
6166 prompt = ENCODE_FILE (prompt);
6167 dir = ENCODE_FILE (dir);
6168 filename = ENCODE_FILE (filename);
6169
6170 /* We modify these in-place, so make copies for safety. */
6171 dir = Fcopy_sequence (dir);
6172 unixtodos_filename (SDATA (dir));
6173 filename = Fcopy_sequence (filename);
6174 unixtodos_filename (SDATA (filename));
6175 #endif /* NTGUI_UNICODE */
6176
6177 /* Fill in the structure for the call to GetOpenFileName below. For
6178 NTGUI_UNICODE builds (which run only on NT), we just use the
6179 actual size of the structure. For non-NTGUI_UNICODE builds, we
6180 tell the OS we're using an old version of the structure if it's not
6181 new enough to support the newer version. */
6182 memset (&new_file_details, 0, sizeof (new_file_details));
6183
6184 if (w32_major_version > 4 && w32_major_version < 95)
6185 file_details->lStructSize = sizeof (new_file_details);
6186 else
6187 file_details->lStructSize = sizeof (*file_details);
6188
6189 /* Set up the inout parameter for the selected file name. */
6190 if (SBYTES (filename) + 1 > sizeof (filename_buf))
6191 error ("filename too long");
6192
6193 memcpy (filename_buf, SDATA (filename), SBYTES (filename) + 1);
6194 file_details->lpstrFile = filename_buf;
6195 file_details->nMaxFile = sizeof (filename_buf) / sizeof (*filename_buf);
6196
6197 file_details->hwndOwner = FRAME_W32_WINDOW (f);
6198 /* Undocumented Bug in Common File Dialog:
6199 If a filter is not specified, shell links are not resolved. */
6200 file_details->lpstrFilter = filter;
6201 file_details->lpstrInitialDir = (guichar_t*) SDATA (dir);
6202 file_details->lpstrTitle = (guichar_t*) SDATA (prompt);
6203 file_details->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
6204 file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
6205 | OFN_EXPLORER | OFN_ENABLEHOOK);
6206
6207 if (!NILP (mustmatch))
6208 {
6209 /* Require that the path to the parent directory exists. */
6210 file_details->Flags |= OFN_PATHMUSTEXIST;
6211 /* If we are looking for a file, require that it exists. */
6212 if (NILP (only_dir_p))
6213 file_details->Flags |= OFN_FILEMUSTEXIST;
6214 }
6215
6216 {
6217 int count = SPECPDL_INDEX ();
6218 specbind (Qinhibit_redisplay, Qt);
6219 block_input ();
6220 file_details->lpfnHook = file_dialog_callback;
6221
6222 #ifdef NTGUI_UNICODE
6223 file_opened = GetOpenFileNameW (file_details);
6224 #else /* !NTGUI_UNICODE */
6225 file_opened = GetOpenFileNameA (file_details);
6226 #endif /* NTGUI_UNICODE */
6227 unblock_input ();
6228 unbind_to (count, Qnil);
6229 }
6230
6231 if (file_opened)
6232 {
6233 /* Get an Emacs string from the value Windows gave us. */
6234 #ifdef NTGUI_UNICODE
6235 filename = from_unicode (
6236 make_unibyte_string (
6237 (char*) filename_buf,
6238 /* we get one of the two final 0 bytes for free. */
6239 1 + sizeof (wchar_t) * wcslen (filename_buf)));
6240 #else /* !NTGUI_UNICODE */
6241 dostounix_filename (filename_buf);
6242 filename = DECODE_FILE (build_string (filename_buf));
6243 #endif /* NTGUI_UNICODE */
6244
6245 #ifdef CYGWIN
6246 filename = Fcygwin_convert_path_from_windows (filename, Qt);
6247 #endif /* CYGWIN */
6248
6249 /* Strip the dummy filename off the end of the string if we
6250 added it to select a directory. */
6251 if (file_details->nFilterIndex == 2)
6252 {
6253 filename = Ffile_name_directory (filename);
6254 }
6255 }
6256 /* User canceled the dialog without making a selection. */
6257 else if (!CommDlgExtendedError ())
6258 filename = Qnil;
6259 /* An error occurred, fallback on reading from the mini-buffer. */
6260 else
6261 filename = Fcompleting_read (
6262 orig_prompt,
6263 intern ("read-file-name-internal"),
6264 orig_dir,
6265 mustmatch,
6266 orig_dir,
6267 Qfile_name_history,
6268 default_filename,
6269 Qnil);
6270
6271 UNGCPRO;
6272 }
6273
6274 /* Make "Cancel" equivalent to C-g. */
6275 if (NILP (filename))
6276 Fsignal (Qquit, Qnil);
6277
6278 RETURN_UNGCPRO (filename);
6279 }
6280
6281 \f
6282 #ifdef WINDOWSNT
6283 /* Moving files to the system recycle bin.
6284 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
6285 DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
6286 Ssystem_move_file_to_trash, 1, 1, 0,
6287 doc: /* Move file or directory named FILENAME to the recycle bin. */)
6288 (Lisp_Object filename)
6289 {
6290 Lisp_Object handler;
6291 Lisp_Object encoded_file;
6292 Lisp_Object operation;
6293
6294 operation = Qdelete_file;
6295 if (!NILP (Ffile_directory_p (filename))
6296 && NILP (Ffile_symlink_p (filename)))
6297 {
6298 operation = intern ("delete-directory");
6299 filename = Fdirectory_file_name (filename);
6300 }
6301 filename = Fexpand_file_name (filename, Qnil);
6302
6303 handler = Ffind_file_name_handler (filename, operation);
6304 if (!NILP (handler))
6305 return call2 (handler, operation, filename);
6306
6307 encoded_file = ENCODE_FILE (filename);
6308
6309 {
6310 const char * path;
6311 SHFILEOPSTRUCT file_op;
6312 char tmp_path[MAX_PATH + 1];
6313
6314 path = map_w32_filename (SDATA (encoded_file), NULL);
6315
6316 /* On Windows, write permission is required to delete/move files. */
6317 _chmod (path, 0666);
6318
6319 memset (tmp_path, 0, sizeof (tmp_path));
6320 strcpy (tmp_path, path);
6321
6322 memset (&file_op, 0, sizeof (file_op));
6323 file_op.hwnd = HWND_DESKTOP;
6324 file_op.wFunc = FO_DELETE;
6325 file_op.pFrom = tmp_path;
6326 file_op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
6327 | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
6328 file_op.fAnyOperationsAborted = FALSE;
6329
6330 if (SHFileOperation (&file_op) != 0)
6331 report_file_error ("Removing old name", list1 (filename));
6332 }
6333 return Qnil;
6334 }
6335
6336 #endif /* WINDOWSNT */
6337
6338 \f
6339 /***********************************************************************
6340 w32 specialized functions
6341 ***********************************************************************/
6342
6343 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
6344 Sw32_send_sys_command, 1, 2, 0,
6345 doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
6346 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
6347 to minimize), #xf120 to restore frame to original size, and #xf100
6348 to activate the menubar for keyboard access. #xf140 activates the
6349 screen saver if defined.
6350
6351 If optional parameter FRAME is not specified, use selected frame. */)
6352 (Lisp_Object command, Lisp_Object frame)
6353 {
6354 FRAME_PTR f = check_x_frame (frame);
6355
6356 CHECK_NUMBER (command);
6357
6358 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
6359
6360 return Qnil;
6361 }
6362
6363 DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
6364 doc: /* Get Windows to perform OPERATION on DOCUMENT.
6365 This is a wrapper around the ShellExecute system function, which
6366 invokes the application registered to handle OPERATION for DOCUMENT.
6367
6368 OPERATION is either nil or a string that names a supported operation.
6369 What operations can be used depends on the particular DOCUMENT and its
6370 handler application, but typically it is one of the following common
6371 operations:
6372
6373 \"open\" - open DOCUMENT, which could be a file, a directory, or an
6374 executable program. If it is an application, that
6375 application is launched in the current buffer's default
6376 directory. Otherwise, the application associated with
6377 DOCUMENT is launched in the buffer's default directory.
6378 \"print\" - print DOCUMENT, which must be a file
6379 \"explore\" - start the Windows Explorer on DOCUMENT
6380 \"edit\" - launch an editor and open DOCUMENT for editing; which
6381 editor is launched depends on the association for the
6382 specified DOCUMENT
6383 \"find\" - initiate search starting from DOCUMENT which must specify
6384 a directory
6385 nil - invoke the default OPERATION, or \"open\" if default is
6386 not defined or unavailable
6387
6388 DOCUMENT is typically the name of a document file or a URL, but can
6389 also be a program executable to run, or a directory to open in the
6390 Windows Explorer.
6391
6392 If DOCUMENT is a program executable, the optional third arg PARAMETERS
6393 can be a string containing command line parameters that will be passed
6394 to the program; otherwise, PARAMETERS should be nil or unspecified.
6395
6396 Optional fourth argument SHOW-FLAG can be used to control how the
6397 application will be displayed when it is invoked. If SHOW-FLAG is nil
6398 or unspecified, the application is displayed normally, otherwise it is
6399 an integer representing a ShowWindow flag:
6400
6401 0 - start hidden
6402 1 - start normally
6403 3 - start maximized
6404 6 - start minimized */)
6405 (Lisp_Object operation, Lisp_Object document, Lisp_Object parameters, Lisp_Object show_flag)
6406 {
6407 Lisp_Object current_dir;
6408 char *errstr;
6409
6410 CHECK_STRING (document);
6411
6412 /* Encode filename, current directory and parameters. */
6413 current_dir = ENCODE_FILE (BVAR (current_buffer, directory));
6414 document = ENCODE_FILE (document);
6415 if (STRINGP (parameters))
6416 parameters = ENCODE_SYSTEM (parameters);
6417
6418 if ((int) ShellExecute (NULL,
6419 (STRINGP (operation) ?
6420 SDATA (operation) : NULL),
6421 SDATA (document),
6422 (STRINGP (parameters) ?
6423 SDATA (parameters) : NULL),
6424 SDATA (current_dir),
6425 (INTEGERP (show_flag) ?
6426 XINT (show_flag) : SW_SHOWDEFAULT))
6427 > 32)
6428 return Qt;
6429 errstr = w32_strerror (0);
6430 /* The error string might be encoded in the locale's encoding. */
6431 if (!NILP (Vlocale_coding_system))
6432 {
6433 Lisp_Object decoded =
6434 code_convert_string_norecord (build_unibyte_string (errstr),
6435 Vlocale_coding_system, 0);
6436 errstr = SSDATA (decoded);
6437 }
6438 error ("ShellExecute failed: %s", errstr);
6439 }
6440
6441 /* Lookup virtual keycode from string representing the name of a
6442 non-ascii keystroke into the corresponding virtual key, using
6443 lispy_function_keys. */
6444 static int
6445 lookup_vk_code (char *key)
6446 {
6447 int i;
6448
6449 for (i = 0; i < 256; i++)
6450 if (lispy_function_keys[i]
6451 && strcmp (lispy_function_keys[i], key) == 0)
6452 return i;
6453
6454 return -1;
6455 }
6456
6457 /* Convert a one-element vector style key sequence to a hot key
6458 definition. */
6459 static Lisp_Object
6460 w32_parse_hot_key (Lisp_Object key)
6461 {
6462 /* Copied from Fdefine_key and store_in_keymap. */
6463 register Lisp_Object c;
6464 int vk_code;
6465 int lisp_modifiers;
6466 int w32_modifiers;
6467 struct gcpro gcpro1;
6468
6469 CHECK_VECTOR (key);
6470
6471 if (XFASTINT (Flength (key)) != 1)
6472 return Qnil;
6473
6474 GCPRO1 (key);
6475
6476 c = Faref (key, make_number (0));
6477
6478 if (CONSP (c) && lucid_event_type_list_p (c))
6479 c = Fevent_convert_list (c);
6480
6481 UNGCPRO;
6482
6483 if (! INTEGERP (c) && ! SYMBOLP (c))
6484 error ("Key definition is invalid");
6485
6486 /* Work out the base key and the modifiers. */
6487 if (SYMBOLP (c))
6488 {
6489 c = parse_modifiers (c);
6490 lisp_modifiers = XINT (Fcar (Fcdr (c)));
6491 c = Fcar (c);
6492 if (!SYMBOLP (c))
6493 emacs_abort ();
6494 vk_code = lookup_vk_code (SDATA (SYMBOL_NAME (c)));
6495 }
6496 else if (INTEGERP (c))
6497 {
6498 lisp_modifiers = XINT (c) & ~CHARACTERBITS;
6499 /* Many ascii characters are their own virtual key code. */
6500 vk_code = XINT (c) & CHARACTERBITS;
6501 }
6502
6503 if (vk_code < 0 || vk_code > 255)
6504 return Qnil;
6505
6506 if ((lisp_modifiers & meta_modifier) != 0
6507 && !NILP (Vw32_alt_is_meta))
6508 lisp_modifiers |= alt_modifier;
6509
6510 /* Supply defs missing from mingw32. */
6511 #ifndef MOD_ALT
6512 #define MOD_ALT 0x0001
6513 #define MOD_CONTROL 0x0002
6514 #define MOD_SHIFT 0x0004
6515 #define MOD_WIN 0x0008
6516 #endif
6517
6518 /* Convert lisp modifiers to Windows hot-key form. */
6519 w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0;
6520 w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0;
6521 w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0;
6522 w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0;
6523
6524 return HOTKEY (vk_code, w32_modifiers);
6525 }
6526
6527 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
6528 Sw32_register_hot_key, 1, 1, 0,
6529 doc: /* Register KEY as a hot-key combination.
6530 Certain key combinations like Alt-Tab are reserved for system use on
6531 Windows, and therefore are normally intercepted by the system. However,
6532 most of these key combinations can be received by registering them as
6533 hot-keys, overriding their special meaning.
6534
6535 KEY must be a one element key definition in vector form that would be
6536 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
6537 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
6538 is always interpreted as the Windows modifier keys.
6539
6540 The return value is the hotkey-id if registered, otherwise nil. */)
6541 (Lisp_Object key)
6542 {
6543 key = w32_parse_hot_key (key);
6544
6545 if (!NILP (key) && NILP (Fmemq (key, w32_grabbed_keys)))
6546 {
6547 /* Reuse an empty slot if possible. */
6548 Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
6549
6550 /* Safe to add new key to list, even if we have focus. */
6551 if (NILP (item))
6552 w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
6553 else
6554 XSETCAR (item, key);
6555
6556 /* Notify input thread about new hot-key definition, so that it
6557 takes effect without needing to switch focus. */
6558 PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
6559 (WPARAM) XLI (key), 0);
6560 }
6561
6562 return key;
6563 }
6564
6565 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
6566 Sw32_unregister_hot_key, 1, 1, 0,
6567 doc: /* Unregister KEY as a hot-key combination. */)
6568 (Lisp_Object key)
6569 {
6570 Lisp_Object item;
6571
6572 if (!INTEGERP (key))
6573 key = w32_parse_hot_key (key);
6574
6575 item = Fmemq (key, w32_grabbed_keys);
6576
6577 if (!NILP (item))
6578 {
6579 /* Notify input thread about hot-key definition being removed, so
6580 that it takes effect without needing focus switch. */
6581 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
6582 (WPARAM) XINT (XCAR (item)), (LPARAM) XLI (item)))
6583 {
6584 MSG msg;
6585 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6586 }
6587 return Qt;
6588 }
6589 return Qnil;
6590 }
6591
6592 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
6593 Sw32_registered_hot_keys, 0, 0, 0,
6594 doc: /* Return list of registered hot-key IDs. */)
6595 (void)
6596 {
6597 return Fdelq (Qnil, Fcopy_sequence (w32_grabbed_keys));
6598 }
6599
6600 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
6601 Sw32_reconstruct_hot_key, 1, 1, 0,
6602 doc: /* Convert hot-key ID to a lisp key combination.
6603 usage: (w32-reconstruct-hot-key ID) */)
6604 (Lisp_Object hotkeyid)
6605 {
6606 int vk_code, w32_modifiers;
6607 Lisp_Object key;
6608
6609 CHECK_NUMBER (hotkeyid);
6610
6611 vk_code = HOTKEY_VK_CODE (hotkeyid);
6612 w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
6613
6614 if (vk_code < 256 && lispy_function_keys[vk_code])
6615 key = intern (lispy_function_keys[vk_code]);
6616 else
6617 key = make_number (vk_code);
6618
6619 key = Fcons (key, Qnil);
6620 if (w32_modifiers & MOD_SHIFT)
6621 key = Fcons (Qshift, key);
6622 if (w32_modifiers & MOD_CONTROL)
6623 key = Fcons (Qctrl, key);
6624 if (w32_modifiers & MOD_ALT)
6625 key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
6626 if (w32_modifiers & MOD_WIN)
6627 key = Fcons (Qhyper, key);
6628
6629 return key;
6630 }
6631
6632 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
6633 Sw32_toggle_lock_key, 1, 2, 0,
6634 doc: /* Toggle the state of the lock key KEY.
6635 KEY can be `capslock', `kp-numlock', or `scroll'.
6636 If the optional parameter NEW-STATE is a number, then the state of KEY
6637 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
6638 (Lisp_Object key, Lisp_Object new_state)
6639 {
6640 int vk_code;
6641
6642 if (EQ (key, intern ("capslock")))
6643 vk_code = VK_CAPITAL;
6644 else if (EQ (key, intern ("kp-numlock")))
6645 vk_code = VK_NUMLOCK;
6646 else if (EQ (key, intern ("scroll")))
6647 vk_code = VK_SCROLL;
6648 else
6649 return Qnil;
6650
6651 if (!dwWindowsThreadId)
6652 return make_number (w32_console_toggle_lock_key (vk_code, new_state));
6653
6654 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
6655 (WPARAM) vk_code, (LPARAM) XLI (new_state)))
6656 {
6657 MSG msg;
6658 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6659 return make_number (msg.wParam);
6660 }
6661 return Qnil;
6662 }
6663
6664 DEFUN ("w32-window-exists-p", Fw32_window_exists_p, Sw32_window_exists_p,
6665 2, 2, 0,
6666 doc: /* Return non-nil if a window exists with the specified CLASS and NAME.
6667
6668 This is a direct interface to the Windows API FindWindow function. */)
6669 (Lisp_Object class, Lisp_Object name)
6670 {
6671 HWND hnd;
6672
6673 if (!NILP (class))
6674 CHECK_STRING (class);
6675 if (!NILP (name))
6676 CHECK_STRING (name);
6677
6678 hnd = FindWindow (STRINGP (class) ? ((LPCTSTR) SDATA (class)) : NULL,
6679 STRINGP (name) ? ((LPCTSTR) SDATA (name)) : NULL);
6680 if (!hnd)
6681 return Qnil;
6682 return Qt;
6683 }
6684
6685 DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
6686 doc: /* Get power status information from Windows system.
6687
6688 The following %-sequences are provided:
6689 %L AC line status (verbose)
6690 %B Battery status (verbose)
6691 %b Battery status, empty means high, `-' means low,
6692 `!' means critical, and `+' means charging
6693 %p Battery load percentage
6694 %s Remaining time (to charge or discharge) in seconds
6695 %m Remaining time (to charge or discharge) in minutes
6696 %h Remaining time (to charge or discharge) in hours
6697 %t Remaining time (to charge or discharge) in the form `h:min' */)
6698 (void)
6699 {
6700 Lisp_Object status = Qnil;
6701
6702 SYSTEM_POWER_STATUS system_status;
6703 if (GetSystemPowerStatus (&system_status))
6704 {
6705 Lisp_Object line_status, battery_status, battery_status_symbol;
6706 Lisp_Object load_percentage, seconds, minutes, hours, remain;
6707
6708 long seconds_left = (long) system_status.BatteryLifeTime;
6709
6710 if (system_status.ACLineStatus == 0)
6711 line_status = build_string ("off-line");
6712 else if (system_status.ACLineStatus == 1)
6713 line_status = build_string ("on-line");
6714 else
6715 line_status = build_string ("N/A");
6716
6717 if (system_status.BatteryFlag & 128)
6718 {
6719 battery_status = build_string ("N/A");
6720 battery_status_symbol = empty_unibyte_string;
6721 }
6722 else if (system_status.BatteryFlag & 8)
6723 {
6724 battery_status = build_string ("charging");
6725 battery_status_symbol = build_string ("+");
6726 if (system_status.BatteryFullLifeTime != -1L)
6727 seconds_left = system_status.BatteryFullLifeTime - seconds_left;
6728 }
6729 else if (system_status.BatteryFlag & 4)
6730 {
6731 battery_status = build_string ("critical");
6732 battery_status_symbol = build_string ("!");
6733 }
6734 else if (system_status.BatteryFlag & 2)
6735 {
6736 battery_status = build_string ("low");
6737 battery_status_symbol = build_string ("-");
6738 }
6739 else if (system_status.BatteryFlag & 1)
6740 {
6741 battery_status = build_string ("high");
6742 battery_status_symbol = empty_unibyte_string;
6743 }
6744 else
6745 {
6746 battery_status = build_string ("medium");
6747 battery_status_symbol = empty_unibyte_string;
6748 }
6749
6750 if (system_status.BatteryLifePercent > 100)
6751 load_percentage = build_string ("N/A");
6752 else
6753 {
6754 char buffer[16];
6755 snprintf (buffer, 16, "%d", system_status.BatteryLifePercent);
6756 load_percentage = build_string (buffer);
6757 }
6758
6759 if (seconds_left < 0)
6760 seconds = minutes = hours = remain = build_string ("N/A");
6761 else
6762 {
6763 long m;
6764 float h;
6765 char buffer[16];
6766 snprintf (buffer, 16, "%ld", seconds_left);
6767 seconds = build_string (buffer);
6768
6769 m = seconds_left / 60;
6770 snprintf (buffer, 16, "%ld", m);
6771 minutes = build_string (buffer);
6772
6773 h = seconds_left / 3600.0;
6774 snprintf (buffer, 16, "%3.1f", h);
6775 hours = build_string (buffer);
6776
6777 snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60);
6778 remain = build_string (buffer);
6779 }
6780
6781 status = listn (CONSTYPE_HEAP, 8,
6782 Fcons (make_number ('L'), line_status),
6783 Fcons (make_number ('B'), battery_status),
6784 Fcons (make_number ('b'), battery_status_symbol),
6785 Fcons (make_number ('p'), load_percentage),
6786 Fcons (make_number ('s'), seconds),
6787 Fcons (make_number ('m'), minutes),
6788 Fcons (make_number ('h'), hours),
6789 Fcons (make_number ('t'), remain));
6790 }
6791 return status;
6792 }
6793
6794 \f
6795 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
6796 doc: /* Return storage information about the file system FILENAME is on.
6797 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
6798 storage of the file system, FREE is the free storage, and AVAIL is the
6799 storage available to a non-superuser. All 3 numbers are in bytes.
6800 If the underlying system call fails, value is nil. */)
6801 (Lisp_Object filename)
6802 {
6803 Lisp_Object encoded, value;
6804
6805 CHECK_STRING (filename);
6806 filename = Fexpand_file_name (filename, Qnil);
6807 encoded = ENCODE_FILE (filename);
6808
6809 value = Qnil;
6810
6811 /* Determining the required information on Windows turns out, sadly,
6812 to be more involved than one would hope. The original Windows API
6813 call for this will return bogus information on some systems, but we
6814 must dynamically probe for the replacement api, since that was
6815 added rather late on. */
6816 {
6817 HMODULE hKernel = GetModuleHandle ("kernel32");
6818 BOOL (*pfn_GetDiskFreeSpaceEx)
6819 (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
6820 = (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
6821
6822 /* On Windows, we may need to specify the root directory of the
6823 volume holding FILENAME. */
6824 char rootname[MAX_PATH];
6825 char *name = SDATA (encoded);
6826
6827 /* find the root name of the volume if given */
6828 if (isalpha (name[0]) && name[1] == ':')
6829 {
6830 rootname[0] = name[0];
6831 rootname[1] = name[1];
6832 rootname[2] = '\\';
6833 rootname[3] = 0;
6834 }
6835 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
6836 {
6837 char *str = rootname;
6838 int slashes = 4;
6839 do
6840 {
6841 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
6842 break;
6843 *str++ = *name++;
6844 }
6845 while ( *name );
6846
6847 *str++ = '\\';
6848 *str = 0;
6849 }
6850
6851 if (pfn_GetDiskFreeSpaceEx)
6852 {
6853 /* Unsigned large integers cannot be cast to double, so
6854 use signed ones instead. */
6855 LARGE_INTEGER availbytes;
6856 LARGE_INTEGER freebytes;
6857 LARGE_INTEGER totalbytes;
6858
6859 if (pfn_GetDiskFreeSpaceEx (rootname,
6860 (ULARGE_INTEGER *)&availbytes,
6861 (ULARGE_INTEGER *)&totalbytes,
6862 (ULARGE_INTEGER *)&freebytes))
6863 value = list3 (make_float ((double) totalbytes.QuadPart),
6864 make_float ((double) freebytes.QuadPart),
6865 make_float ((double) availbytes.QuadPart));
6866 }
6867 else
6868 {
6869 DWORD sectors_per_cluster;
6870 DWORD bytes_per_sector;
6871 DWORD free_clusters;
6872 DWORD total_clusters;
6873
6874 if (GetDiskFreeSpace (rootname,
6875 &sectors_per_cluster,
6876 &bytes_per_sector,
6877 &free_clusters,
6878 &total_clusters))
6879 value = list3 (make_float ((double) total_clusters
6880 * sectors_per_cluster * bytes_per_sector),
6881 make_float ((double) free_clusters
6882 * sectors_per_cluster * bytes_per_sector),
6883 make_float ((double) free_clusters
6884 * sectors_per_cluster * bytes_per_sector));
6885 }
6886 }
6887
6888 return value;
6889 }
6890 \f
6891 DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
6892 0, 0, 0, doc: /* Return the name of Windows default printer device. */)
6893 (void)
6894 {
6895 static char pname_buf[256];
6896 int err;
6897 HANDLE hPrn;
6898 PRINTER_INFO_2 *ppi2 = NULL;
6899 DWORD dwNeeded = 0, dwReturned = 0;
6900
6901 /* Retrieve the default string from Win.ini (the registry).
6902 * String will be in form "printername,drivername,portname".
6903 * This is the most portable way to get the default printer. */
6904 if (GetProfileString ("windows", "device", ",,", pname_buf, sizeof (pname_buf)) <= 0)
6905 return Qnil;
6906 /* printername precedes first "," character */
6907 strtok (pname_buf, ",");
6908 /* We want to know more than the printer name */
6909 if (!OpenPrinter (pname_buf, &hPrn, NULL))
6910 return Qnil;
6911 GetPrinter (hPrn, 2, NULL, 0, &dwNeeded);
6912 if (dwNeeded == 0)
6913 {
6914 ClosePrinter (hPrn);
6915 return Qnil;
6916 }
6917 /* Allocate memory for the PRINTER_INFO_2 struct */
6918 ppi2 = xmalloc (dwNeeded);
6919 if (!ppi2)
6920 {
6921 ClosePrinter (hPrn);
6922 return Qnil;
6923 }
6924 /* Call GetPrinter again with big enough memory block. */
6925 err = GetPrinter (hPrn, 2, (LPBYTE)ppi2, dwNeeded, &dwReturned);
6926 ClosePrinter (hPrn);
6927 if (!err)
6928 {
6929 xfree (ppi2);
6930 return Qnil;
6931 }
6932
6933 if (ppi2)
6934 {
6935 if (ppi2->Attributes & PRINTER_ATTRIBUTE_SHARED && ppi2->pServerName)
6936 {
6937 /* a remote printer */
6938 if (*ppi2->pServerName == '\\')
6939 snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName,
6940 ppi2->pShareName);
6941 else
6942 snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName,
6943 ppi2->pShareName);
6944 pname_buf[sizeof (pname_buf) - 1] = '\0';
6945 }
6946 else
6947 {
6948 /* a local printer */
6949 strncpy (pname_buf, ppi2->pPortName, sizeof (pname_buf));
6950 pname_buf[sizeof (pname_buf) - 1] = '\0';
6951 /* `pPortName' can include several ports, delimited by ','.
6952 * we only use the first one. */
6953 strtok (pname_buf, ",");
6954 }
6955 xfree (ppi2);
6956 }
6957
6958 return build_string (pname_buf);
6959 }
6960 \f
6961
6962 /* Equivalent of strerror for W32 error codes. */
6963 char *
6964 w32_strerror (int error_no)
6965 {
6966 static char buf[500];
6967 DWORD ret;
6968
6969 if (error_no == 0)
6970 error_no = GetLastError ();
6971
6972 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
6973 FORMAT_MESSAGE_IGNORE_INSERTS,
6974 NULL,
6975 error_no,
6976 0, /* choose most suitable language */
6977 buf, sizeof (buf), NULL);
6978
6979 while (ret > 0 && (buf[ret - 1] == '\n' ||
6980 buf[ret - 1] == '\r' ))
6981 --ret;
6982 buf[ret] = '\0';
6983 if (!ret)
6984 sprintf (buf, "w32 error %u", error_no);
6985
6986 return buf;
6987 }
6988
6989 /* For convenience when debugging. */
6990 int
6991 w32_last_error (void)
6992 {
6993 return GetLastError ();
6994 }
6995
6996 /* Cache information describing the NT system for later use. */
6997 void
6998 cache_system_info (void)
6999 {
7000 union
7001 {
7002 struct info
7003 {
7004 char major;
7005 char minor;
7006 short platform;
7007 } info;
7008 DWORD data;
7009 } version;
7010
7011 /* Cache the version of the operating system. */
7012 version.data = GetVersion ();
7013 w32_major_version = version.info.major;
7014 w32_minor_version = version.info.minor;
7015
7016 if (version.info.platform & 0x8000)
7017 os_subtype = OS_9X;
7018 else
7019 os_subtype = OS_NT;
7020
7021 /* Cache page size, allocation unit, processor type, etc. */
7022 GetSystemInfo (&sysinfo_cache);
7023 syspage_mask = sysinfo_cache.dwPageSize - 1;
7024
7025 /* Cache os info. */
7026 osinfo_cache.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
7027 GetVersionEx (&osinfo_cache);
7028
7029 w32_build_number = osinfo_cache.dwBuildNumber;
7030 if (os_subtype == OS_9X)
7031 w32_build_number &= 0xffff;
7032
7033 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
7034 }
7035
7036 #ifdef EMACSDEBUG
7037 void
7038 _DebPrint (const char *fmt, ...)
7039 {
7040 char buf[1024];
7041 va_list args;
7042
7043 va_start (args, fmt);
7044 vsprintf (buf, fmt, args);
7045 va_end (args);
7046 #if CYGWIN
7047 fprintf (stderr, "%s", buf);
7048 #endif
7049 OutputDebugString (buf);
7050 }
7051 #endif
7052
7053 int
7054 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
7055 {
7056 int cur_state = (GetKeyState (vk_code) & 1);
7057
7058 if (NILP (new_state)
7059 || (NUMBERP (new_state)
7060 && ((XUINT (new_state)) & 1) != cur_state))
7061 {
7062 #ifdef WINDOWSNT
7063 faked_key = vk_code;
7064 #endif /* WINDOWSNT */
7065
7066 keybd_event ((BYTE) vk_code,
7067 (BYTE) MapVirtualKey (vk_code, 0),
7068 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
7069 keybd_event ((BYTE) vk_code,
7070 (BYTE) MapVirtualKey (vk_code, 0),
7071 KEYEVENTF_EXTENDEDKEY | 0, 0);
7072 keybd_event ((BYTE) vk_code,
7073 (BYTE) MapVirtualKey (vk_code, 0),
7074 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
7075 cur_state = !cur_state;
7076 }
7077
7078 return cur_state;
7079 }
7080
7081 /* Translate console modifiers to emacs modifiers.
7082 German keyboard support (Kai Morgan Zeise 2/18/95). */
7083 int
7084 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
7085 {
7086 int retval = 0;
7087
7088 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
7089 pressed, first remove those modifiers. */
7090 if (!NILP (Vw32_recognize_altgr)
7091 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
7092 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
7093 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
7094
7095 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
7096 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
7097
7098 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
7099 {
7100 retval |= ctrl_modifier;
7101 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
7102 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
7103 retval |= meta_modifier;
7104 }
7105
7106 if (mods & LEFT_WIN_PRESSED)
7107 retval |= w32_key_to_modifier (VK_LWIN);
7108 if (mods & RIGHT_WIN_PRESSED)
7109 retval |= w32_key_to_modifier (VK_RWIN);
7110 if (mods & APPS_PRESSED)
7111 retval |= w32_key_to_modifier (VK_APPS);
7112 if (mods & SCROLLLOCK_ON)
7113 retval |= w32_key_to_modifier (VK_SCROLL);
7114
7115 /* Just in case someone wanted the original behavior, make it
7116 optional by setting w32-capslock-is-shiftlock to t. */
7117 if (NILP (Vw32_capslock_is_shiftlock)
7118 /* Keys that should _not_ be affected by CapsLock. */
7119 && ( (key == VK_BACK)
7120 || (key == VK_TAB)
7121 || (key == VK_CLEAR)
7122 || (key == VK_RETURN)
7123 || (key == VK_ESCAPE)
7124 || ((key >= VK_SPACE) && (key <= VK_HELP))
7125 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
7126 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
7127 ))
7128 {
7129 /* Only consider shift state. */
7130 if ((mods & SHIFT_PRESSED) != 0)
7131 retval |= shift_modifier;
7132 }
7133 else
7134 {
7135 /* Ignore CapsLock state if not enabled. */
7136 if (NILP (Vw32_enable_caps_lock))
7137 mods &= ~CAPSLOCK_ON;
7138 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
7139 retval |= shift_modifier;
7140 }
7141
7142 return retval;
7143 }
7144
7145 /* The return code indicates key code size. cpID is the codepage to
7146 use for translation to Unicode; -1 means use the current console
7147 input codepage. */
7148 int
7149 w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
7150 {
7151 unsigned int key_code = event->wVirtualKeyCode;
7152 unsigned int mods = event->dwControlKeyState;
7153 BYTE keystate[256];
7154 static BYTE ansi_code[4];
7155 static int isdead = 0;
7156
7157 if (isdead == 2)
7158 {
7159 event->uChar.AsciiChar = ansi_code[2];
7160 isdead = 0;
7161 return 1;
7162 }
7163 if (event->uChar.AsciiChar != 0)
7164 return 1;
7165
7166 memset (keystate, 0, sizeof (keystate));
7167 keystate[key_code] = 0x80;
7168 if (mods & SHIFT_PRESSED)
7169 keystate[VK_SHIFT] = 0x80;
7170 if (mods & CAPSLOCK_ON)
7171 keystate[VK_CAPITAL] = 1;
7172 /* If we recognize right-alt and left-ctrl as AltGr, set the key
7173 states accordingly before invoking ToAscii. */
7174 if (!NILP (Vw32_recognize_altgr)
7175 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
7176 {
7177 keystate[VK_CONTROL] = 0x80;
7178 keystate[VK_LCONTROL] = 0x80;
7179 keystate[VK_MENU] = 0x80;
7180 keystate[VK_RMENU] = 0x80;
7181 }
7182
7183 #if 0
7184 /* Because of an OS bug, ToAscii corrupts the stack when called to
7185 convert a dead key in console mode on NT4. Unfortunately, trying
7186 to check for dead keys using MapVirtualKey doesn't work either -
7187 these functions apparently use internal information about keyboard
7188 layout which doesn't get properly updated in console programs when
7189 changing layout (though apparently it gets partly updated,
7190 otherwise ToAscii wouldn't crash). */
7191 if (is_dead_key (event->wVirtualKeyCode))
7192 return 0;
7193 #endif
7194
7195 /* On NT, call ToUnicode instead and then convert to the current
7196 console input codepage. */
7197 if (os_subtype == OS_NT)
7198 {
7199 WCHAR buf[128];
7200
7201 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
7202 keystate, buf, 128, 0);
7203 if (isdead > 0)
7204 {
7205 /* When we are called from the GUI message processing code,
7206 we are passed the current keyboard codepage, a positive
7207 number, to use below. */
7208 if (cpId == -1)
7209 cpId = GetConsoleCP ();
7210
7211 event->uChar.UnicodeChar = buf[isdead - 1];
7212 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
7213 ansi_code, 4, NULL, NULL);
7214 }
7215 else
7216 isdead = 0;
7217 }
7218 else
7219 {
7220 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
7221 keystate, (LPWORD) ansi_code, 0);
7222 }
7223
7224 if (isdead == 0)
7225 return 0;
7226 event->uChar.AsciiChar = ansi_code[0];
7227 return isdead;
7228 }
7229
7230
7231 void
7232 w32_sys_ring_bell (struct frame *f)
7233 {
7234 if (sound_type == 0xFFFFFFFF)
7235 {
7236 Beep (666, 100);
7237 }
7238 else if (sound_type == MB_EMACS_SILENT)
7239 {
7240 /* Do nothing. */
7241 }
7242 else
7243 MessageBeep (sound_type);
7244 }
7245
7246 \f
7247 /***********************************************************************
7248 Initialization
7249 ***********************************************************************/
7250
7251 /* Keep this list in the same order as frame_parms in frame.c.
7252 Use 0 for unsupported frame parameters. */
7253
7254 frame_parm_handler w32_frame_parm_handlers[] =
7255 {
7256 x_set_autoraise,
7257 x_set_autolower,
7258 x_set_background_color,
7259 x_set_border_color,
7260 x_set_border_width,
7261 x_set_cursor_color,
7262 x_set_cursor_type,
7263 x_set_font,
7264 x_set_foreground_color,
7265 x_set_icon_name,
7266 x_set_icon_type,
7267 x_set_internal_border_width,
7268 x_set_menu_bar_lines,
7269 x_set_mouse_color,
7270 x_explicitly_set_name,
7271 x_set_scroll_bar_width,
7272 x_set_title,
7273 x_set_unsplittable,
7274 x_set_vertical_scroll_bars,
7275 x_set_visibility,
7276 x_set_tool_bar_lines,
7277 0, /* x_set_scroll_bar_foreground, */
7278 0, /* x_set_scroll_bar_background, */
7279 x_set_screen_gamma,
7280 x_set_line_spacing,
7281 x_set_fringe_width,
7282 x_set_fringe_width,
7283 0, /* x_set_wait_for_wm, */
7284 x_set_fullscreen,
7285 x_set_font_backend,
7286 x_set_alpha,
7287 0, /* x_set_sticky */
7288 0, /* x_set_tool_bar_position */
7289 };
7290
7291 void
7292 syms_of_w32fns (void)
7293 {
7294 globals_of_w32fns ();
7295 /* This is zero if not using MS-Windows. */
7296 w32_in_use = 0;
7297 track_mouse_window = NULL;
7298
7299 w32_visible_system_caret_hwnd = NULL;
7300
7301 DEFSYM (Qsuppress_icon, "suppress-icon");
7302 DEFSYM (Qundefined_color, "undefined-color");
7303 DEFSYM (Qcancel_timer, "cancel-timer");
7304 DEFSYM (Qhyper, "hyper");
7305 DEFSYM (Qsuper, "super");
7306 DEFSYM (Qmeta, "meta");
7307 DEFSYM (Qalt, "alt");
7308 DEFSYM (Qctrl, "ctrl");
7309 DEFSYM (Qcontrol, "control");
7310 DEFSYM (Qshift, "shift");
7311 DEFSYM (Qfont_param, "font-parameter");
7312 /* This is the end of symbol initialization. */
7313
7314
7315 Fput (Qundefined_color, Qerror_conditions,
7316 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
7317 Fput (Qundefined_color, Qerror_message,
7318 build_pure_c_string ("Undefined color"));
7319
7320 staticpro (&w32_grabbed_keys);
7321 w32_grabbed_keys = Qnil;
7322
7323 DEFVAR_LISP ("w32-color-map", Vw32_color_map,
7324 doc: /* An array of color name mappings for Windows. */);
7325 Vw32_color_map = Qnil;
7326
7327 DEFVAR_LISP ("w32-pass-alt-to-system", Vw32_pass_alt_to_system,
7328 doc: /* Non-nil if Alt key presses are passed on to Windows.
7329 When non-nil, for example, Alt pressed and released and then space will
7330 open the System menu. When nil, Emacs processes the Alt key events, and
7331 then silently swallows them. */);
7332 Vw32_pass_alt_to_system = Qnil;
7333
7334 DEFVAR_LISP ("w32-alt-is-meta", Vw32_alt_is_meta,
7335 doc: /* Non-nil if the Alt key is to be considered the same as the META key.
7336 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
7337 Vw32_alt_is_meta = Qt;
7338
7339 DEFVAR_INT ("w32-quit-key", w32_quit_key,
7340 doc: /* If non-zero, the virtual key code for an alternative quit key. */);
7341 w32_quit_key = 0;
7342
7343 DEFVAR_LISP ("w32-pass-lwindow-to-system",
7344 Vw32_pass_lwindow_to_system,
7345 doc: /* If non-nil, the left \"Windows\" key is passed on to Windows.
7346
7347 When non-nil, the Start menu is opened by tapping the key.
7348 If you set this to nil, the left \"Windows\" key is processed by Emacs
7349 according to the value of `w32-lwindow-modifier', which see.
7350
7351 Note that some combinations of the left \"Windows\" key with other keys are
7352 caught by Windows at low level, and so binding them in Emacs will have no
7353 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
7354 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
7355 the doc string of `w32-phantom-key-code'. */);
7356 Vw32_pass_lwindow_to_system = Qt;
7357
7358 DEFVAR_LISP ("w32-pass-rwindow-to-system",
7359 Vw32_pass_rwindow_to_system,
7360 doc: /* If non-nil, the right \"Windows\" key is passed on to Windows.
7361
7362 When non-nil, the Start menu is opened by tapping the key.
7363 If you set this to nil, the right \"Windows\" key is processed by Emacs
7364 according to the value of `w32-rwindow-modifier', which see.
7365
7366 Note that some combinations of the right \"Windows\" key with other keys are
7367 caught by Windows at low level, and so binding them in Emacs will have no
7368 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
7369 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
7370 the doc string of `w32-phantom-key-code'. */);
7371 Vw32_pass_rwindow_to_system = Qt;
7372
7373 DEFVAR_LISP ("w32-phantom-key-code",
7374 Vw32_phantom_key_code,
7375 doc: /* Virtual key code used to generate \"phantom\" key presses.
7376 Value is a number between 0 and 255.
7377
7378 Phantom key presses are generated in order to stop the system from
7379 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
7380 `w32-pass-rwindow-to-system' is nil. */);
7381 /* Although 255 is technically not a valid key code, it works and
7382 means that this hack won't interfere with any real key code. */
7383 XSETINT (Vw32_phantom_key_code, 255);
7384
7385 DEFVAR_LISP ("w32-enable-num-lock",
7386 Vw32_enable_num_lock,
7387 doc: /* If non-nil, the Num Lock key acts normally.
7388 Set to nil to handle Num Lock as the `kp-numlock' key. */);
7389 Vw32_enable_num_lock = Qt;
7390
7391 DEFVAR_LISP ("w32-enable-caps-lock",
7392 Vw32_enable_caps_lock,
7393 doc: /* If non-nil, the Caps Lock key acts normally.
7394 Set to nil to handle Caps Lock as the `capslock' key. */);
7395 Vw32_enable_caps_lock = Qt;
7396
7397 DEFVAR_LISP ("w32-scroll-lock-modifier",
7398 Vw32_scroll_lock_modifier,
7399 doc: /* Modifier to use for the Scroll Lock ON state.
7400 The value can be hyper, super, meta, alt, control or shift for the
7401 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
7402 Any other value will cause the Scroll Lock key to be ignored. */);
7403 Vw32_scroll_lock_modifier = Qnil;
7404
7405 DEFVAR_LISP ("w32-lwindow-modifier",
7406 Vw32_lwindow_modifier,
7407 doc: /* Modifier to use for the left \"Windows\" key.
7408 The value can be hyper, super, meta, alt, control or shift for the
7409 respective modifier, or nil to appear as the `lwindow' key.
7410 Any other value will cause the key to be ignored. */);
7411 Vw32_lwindow_modifier = Qnil;
7412
7413 DEFVAR_LISP ("w32-rwindow-modifier",
7414 Vw32_rwindow_modifier,
7415 doc: /* Modifier to use for the right \"Windows\" key.
7416 The value can be hyper, super, meta, alt, control or shift for the
7417 respective modifier, or nil to appear as the `rwindow' key.
7418 Any other value will cause the key to be ignored. */);
7419 Vw32_rwindow_modifier = Qnil;
7420
7421 DEFVAR_LISP ("w32-apps-modifier",
7422 Vw32_apps_modifier,
7423 doc: /* Modifier to use for the \"Apps\" key.
7424 The value can be hyper, super, meta, alt, control or shift for the
7425 respective modifier, or nil to appear as the `apps' key.
7426 Any other value will cause the key to be ignored. */);
7427 Vw32_apps_modifier = Qnil;
7428
7429 DEFVAR_BOOL ("w32-enable-synthesized-fonts", w32_enable_synthesized_fonts,
7430 doc: /* Non-nil enables selection of artificially italicized and bold fonts. */);
7431 w32_enable_synthesized_fonts = 0;
7432
7433 DEFVAR_LISP ("w32-enable-palette", Vw32_enable_palette,
7434 doc: /* Non-nil enables Windows palette management to map colors exactly. */);
7435 Vw32_enable_palette = Qt;
7436
7437 DEFVAR_INT ("w32-mouse-button-tolerance",
7438 w32_mouse_button_tolerance,
7439 doc: /* Analogue of double click interval for faking middle mouse events.
7440 The value is the minimum time in milliseconds that must elapse between
7441 left and right button down events before they are considered distinct events.
7442 If both mouse buttons are depressed within this interval, a middle mouse
7443 button down event is generated instead. */);
7444 w32_mouse_button_tolerance = GetDoubleClickTime () / 2;
7445
7446 DEFVAR_INT ("w32-mouse-move-interval",
7447 w32_mouse_move_interval,
7448 doc: /* Minimum interval between mouse move events.
7449 The value is the minimum time in milliseconds that must elapse between
7450 successive mouse move (or scroll bar drag) events before they are
7451 reported as lisp events. */);
7452 w32_mouse_move_interval = 0;
7453
7454 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
7455 w32_pass_extra_mouse_buttons_to_system,
7456 doc: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
7457 Recent versions of Windows support mice with up to five buttons.
7458 Since most applications don't support these extra buttons, most mouse
7459 drivers will allow you to map them to functions at the system level.
7460 If this variable is non-nil, Emacs will pass them on, allowing the
7461 system to handle them. */);
7462 w32_pass_extra_mouse_buttons_to_system = 0;
7463
7464 DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
7465 w32_pass_multimedia_buttons_to_system,
7466 doc: /* If non-nil, media buttons are passed to Windows.
7467 Some modern keyboards contain buttons for controlling media players, web
7468 browsers and other applications. Generally these buttons are handled on a
7469 system wide basis, but by setting this to nil they are made available
7470 to Emacs for binding. Depending on your keyboard, additional keys that
7471 may be available are:
7472
7473 browser-back, browser-forward, browser-refresh, browser-stop,
7474 browser-search, browser-favorites, browser-home,
7475 mail, mail-reply, mail-forward, mail-send,
7476 app-1, app-2,
7477 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
7478 spell-check, correction-list, toggle-dictate-command,
7479 media-next, media-previous, media-stop, media-play-pause, media-select,
7480 media-play, media-pause, media-record, media-fast-forward, media-rewind,
7481 media-channel-up, media-channel-down,
7482 volume-mute, volume-up, volume-down,
7483 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
7484 bass-down, bass-boost, bass-up, treble-down, treble-up */);
7485 w32_pass_multimedia_buttons_to_system = 1;
7486
7487 #if 0 /* TODO: Mouse cursor customization. */
7488 DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
7489 doc: /* The shape of the pointer when over text.
7490 Changing the value does not affect existing frames
7491 unless you set the mouse color. */);
7492 Vx_pointer_shape = Qnil;
7493
7494 Vx_nontext_pointer_shape = Qnil;
7495
7496 Vx_mode_pointer_shape = Qnil;
7497
7498 DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
7499 doc: /* The shape of the pointer when Emacs is busy.
7500 This variable takes effect when you create a new frame
7501 or when you set the mouse color. */);
7502 Vx_hourglass_pointer_shape = Qnil;
7503
7504 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
7505 Vx_sensitive_text_pointer_shape,
7506 doc: /* The shape of the pointer when over mouse-sensitive text.
7507 This variable takes effect when you create a new frame
7508 or when you set the mouse color. */);
7509 Vx_sensitive_text_pointer_shape = Qnil;
7510
7511 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
7512 Vx_window_horizontal_drag_shape,
7513 doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
7514 This variable takes effect when you create a new frame
7515 or when you set the mouse color. */);
7516 Vx_window_horizontal_drag_shape = Qnil;
7517 #endif
7518
7519 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7520 doc: /* A string indicating the foreground color of the cursor box. */);
7521 Vx_cursor_fore_pixel = Qnil;
7522
7523 DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
7524 doc: /* Maximum size for tooltips.
7525 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
7526 Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
7527
7528 DEFVAR_LISP ("x-no-window-manager", Vx_no_window_manager,
7529 doc: /* Non-nil if no window manager is in use.
7530 Emacs doesn't try to figure this out; this is always nil
7531 unless you set it to something else. */);
7532 /* We don't have any way to find this out, so set it to nil
7533 and maybe the user would like to set it to t. */
7534 Vx_no_window_manager = Qnil;
7535
7536 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7537 Vx_pixel_size_width_font_regexp,
7538 doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
7539
7540 Since Emacs gets width of a font matching with this regexp from
7541 PIXEL_SIZE field of the name, font finding mechanism gets faster for
7542 such a font. This is especially effective for such large fonts as
7543 Chinese, Japanese, and Korean. */);
7544 Vx_pixel_size_width_font_regexp = Qnil;
7545
7546 DEFVAR_LISP ("w32-bdf-filename-alist",
7547 Vw32_bdf_filename_alist,
7548 doc: /* List of bdf fonts and their corresponding filenames. */);
7549 Vw32_bdf_filename_alist = Qnil;
7550
7551 DEFVAR_BOOL ("w32-strict-fontnames",
7552 w32_strict_fontnames,
7553 doc: /* Non-nil means only use fonts that are exact matches for those requested.
7554 Default is nil, which allows old fontnames that are not XLFD compliant,
7555 and allows third-party CJK display to work by specifying false charset
7556 fields to trick Emacs into translating to Big5, SJIS etc.
7557 Setting this to t will prevent wrong fonts being selected when
7558 fontsets are automatically created. */);
7559 w32_strict_fontnames = 0;
7560
7561 DEFVAR_BOOL ("w32-strict-painting",
7562 w32_strict_painting,
7563 doc: /* Non-nil means use strict rules for repainting frames.
7564 Set this to nil to get the old behavior for repainting; this should
7565 only be necessary if the default setting causes problems. */);
7566 w32_strict_painting = 1;
7567
7568 #if 0 /* TODO: Port to W32 */
7569 defsubr (&Sx_change_window_property);
7570 defsubr (&Sx_delete_window_property);
7571 defsubr (&Sx_window_property);
7572 #endif
7573 defsubr (&Sxw_display_color_p);
7574 defsubr (&Sx_display_grayscale_p);
7575 defsubr (&Sxw_color_defined_p);
7576 defsubr (&Sxw_color_values);
7577 defsubr (&Sx_server_max_request_size);
7578 defsubr (&Sx_server_vendor);
7579 defsubr (&Sx_server_version);
7580 defsubr (&Sx_display_pixel_width);
7581 defsubr (&Sx_display_pixel_height);
7582 defsubr (&Sx_display_mm_width);
7583 defsubr (&Sx_display_mm_height);
7584 defsubr (&Sx_display_screens);
7585 defsubr (&Sx_display_planes);
7586 defsubr (&Sx_display_color_cells);
7587 defsubr (&Sx_display_visual_class);
7588 defsubr (&Sx_display_backing_store);
7589 defsubr (&Sx_display_save_under);
7590 defsubr (&Sx_create_frame);
7591 defsubr (&Sx_open_connection);
7592 defsubr (&Sx_close_connection);
7593 defsubr (&Sx_display_list);
7594 defsubr (&Sx_synchronize);
7595 defsubr (&Sx_focus_frame);
7596
7597 /* W32 specific functions */
7598
7599 defsubr (&Sw32_define_rgb_color);
7600 defsubr (&Sw32_default_color_map);
7601 defsubr (&Sw32_send_sys_command);
7602 defsubr (&Sw32_shell_execute);
7603 defsubr (&Sw32_register_hot_key);
7604 defsubr (&Sw32_unregister_hot_key);
7605 defsubr (&Sw32_registered_hot_keys);
7606 defsubr (&Sw32_reconstruct_hot_key);
7607 defsubr (&Sw32_toggle_lock_key);
7608 defsubr (&Sw32_window_exists_p);
7609 defsubr (&Sw32_battery_status);
7610
7611 defsubr (&Sfile_system_info);
7612 defsubr (&Sdefault_printer_name);
7613 defsubr (&Sset_message_beep);
7614
7615 check_window_system_func = check_w32;
7616
7617 hourglass_hwnd = NULL;
7618
7619 defsubr (&Sx_show_tip);
7620 defsubr (&Sx_hide_tip);
7621 tip_timer = Qnil;
7622 staticpro (&tip_timer);
7623 tip_frame = Qnil;
7624 staticpro (&tip_frame);
7625
7626 last_show_tip_args = Qnil;
7627 staticpro (&last_show_tip_args);
7628
7629 defsubr (&Sx_file_dialog);
7630 #ifdef WINDOWSNT
7631 defsubr (&Ssystem_move_file_to_trash);
7632 #endif
7633 }
7634
7635
7636 /*
7637 globals_of_w32fns is used to initialize those global variables that
7638 must always be initialized on startup even when the global variable
7639 initialized is non zero (see the function main in emacs.c).
7640 globals_of_w32fns is called from syms_of_w32fns when the global
7641 variable initialized is 0 and directly from main when initialized
7642 is non zero.
7643 */
7644 void
7645 globals_of_w32fns (void)
7646 {
7647 HMODULE user32_lib = GetModuleHandle ("user32.dll");
7648 /*
7649 TrackMouseEvent not available in all versions of Windows, so must load
7650 it dynamically. Do it once, here, instead of every time it is used.
7651 */
7652 track_mouse_event_fn = (TrackMouseEvent_Proc)
7653 GetProcAddress (user32_lib, "TrackMouseEvent");
7654
7655 monitor_from_point_fn = (MonitorFromPoint_Proc)
7656 GetProcAddress (user32_lib, "MonitorFromPoint");
7657 get_monitor_info_fn = (GetMonitorInfo_Proc)
7658 GetProcAddress (user32_lib, "GetMonitorInfoA");
7659
7660 {
7661 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
7662 get_composition_string_fn = (ImmGetCompositionString_Proc)
7663 GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
7664 get_ime_context_fn = (ImmGetContext_Proc)
7665 GetProcAddress (imm32_lib, "ImmGetContext");
7666 release_ime_context_fn = (ImmReleaseContext_Proc)
7667 GetProcAddress (imm32_lib, "ImmReleaseContext");
7668 set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
7669 GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
7670 }
7671 DEFVAR_INT ("w32-ansi-code-page",
7672 w32_ansi_code_page,
7673 doc: /* The ANSI code page used by the system. */);
7674 w32_ansi_code_page = GetACP ();
7675
7676 if (os_subtype == OS_NT)
7677 w32_unicode_gui = 1;
7678 else
7679 w32_unicode_gui = 0;
7680
7681 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
7682 InitCommonControls ();
7683
7684 syms_of_w32uniscribe ();
7685 }
7686
7687 void
7688 emacs_abort (void)
7689 {
7690 int button;
7691 button = MessageBox (NULL,
7692 "A fatal error has occurred!\n\n"
7693 "Would you like to attach a debugger?\n\n"
7694 "Select YES to debug, NO to abort Emacs"
7695 #if __GNUC__
7696 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
7697 "\"continue\" inside GDB before clicking YES.)"
7698 #endif
7699 , "Emacs Abort Dialog",
7700 MB_ICONEXCLAMATION | MB_TASKMODAL
7701 | MB_SETFOREGROUND | MB_YESNO);
7702 switch (button)
7703 {
7704 case IDYES:
7705 DebugBreak ();
7706 exit (2); /* tell the compiler we will never return */
7707 case IDNO:
7708 default:
7709 abort ();
7710 break;
7711 }
7712 }
7713