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