1 /* Graphical user interface functions for the Microsoft W32 API.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 /* Added by Kevin Gallo */
38 #include "intervals.h"
39 #include "dispextern.h"
41 #include "blockinput.h"
43 #include "character.h"
49 #include "termhooks.h"
52 #include "bitmaps/gray.xbm"
63 #define FILE_NAME_TEXT_FIELD edt1
65 #ifdef USE_FONT_BACKEND
69 void syms_of_w32fns ();
70 void globals_of_w32fns ();
72 extern void free_frame_menubar ();
73 extern double atof ();
74 extern int w32_console_toggle_lock_key
P_ ((int, Lisp_Object
));
75 extern void w32_menu_display_help
P_ ((HWND
, HMENU
, UINT
, UINT
));
76 extern void w32_free_menu_strings
P_ ((HWND
));
77 extern XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*, wchar_t *, int));
81 extern char *lispy_function_keys
[];
83 /* The colormap for converting color names to RGB values */
84 Lisp_Object Vw32_color_map
;
86 /* Non nil if alt key presses are passed on to Windows. */
87 Lisp_Object Vw32_pass_alt_to_system
;
89 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
91 Lisp_Object Vw32_alt_is_meta
;
93 /* If non-zero, the windows virtual key code for an alternative quit key. */
96 /* Non nil if left window key events are passed on to Windows (this only
97 affects whether "tapping" the key opens the Start menu). */
98 Lisp_Object Vw32_pass_lwindow_to_system
;
100 /* Non nil if right window key events are passed on to Windows (this
101 only affects whether "tapping" the key opens the Start menu). */
102 Lisp_Object Vw32_pass_rwindow_to_system
;
104 /* Virtual key code used to generate "phantom" key presses in order
105 to stop system from acting on Windows key events. */
106 Lisp_Object Vw32_phantom_key_code
;
108 /* Modifier associated with the left "Windows" key, or nil to act as a
110 Lisp_Object Vw32_lwindow_modifier
;
112 /* Modifier associated with the right "Windows" key, or nil to act as a
114 Lisp_Object Vw32_rwindow_modifier
;
116 /* Modifier associated with the "Apps" key, or nil to act as a normal
118 Lisp_Object Vw32_apps_modifier
;
120 /* Value is nil if Num Lock acts as a function key. */
121 Lisp_Object Vw32_enable_num_lock
;
123 /* Value is nil if Caps Lock acts as a function key. */
124 Lisp_Object Vw32_enable_caps_lock
;
126 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
127 Lisp_Object Vw32_scroll_lock_modifier
;
129 /* Switch to control whether we inhibit requests for synthesized bold
130 and italic versions of fonts. */
131 int w32_enable_synthesized_fonts
;
133 /* Enable palette management. */
134 Lisp_Object Vw32_enable_palette
;
136 /* Control how close left/right button down events must be to
137 be converted to a middle button down event. */
138 int w32_mouse_button_tolerance
;
140 /* Minimum interval between mouse movement (and scroll bar drag)
141 events that are passed on to the event loop. */
142 int w32_mouse_move_interval
;
144 /* Flag to indicate if XBUTTON events should be passed on to Windows. */
145 static int w32_pass_extra_mouse_buttons_to_system
;
147 /* Flag to indicate if media keys should be passed on to Windows. */
148 static int w32_pass_multimedia_buttons_to_system
;
150 /* Non nil if no window manager is in use. */
151 Lisp_Object Vx_no_window_manager
;
153 /* Non-zero means we're allowed to display a hourglass pointer. */
155 int display_hourglass_p
;
157 /* If non-zero, a w32 timer that, when it expires, displays an
158 hourglass cursor on all frames. */
159 static unsigned hourglass_timer
= 0;
160 static HWND hourglass_hwnd
= NULL
;
162 /* The background and shape of the mouse pointer, and shape when not
163 over text or in the modeline. */
165 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
166 Lisp_Object Vx_hourglass_pointer_shape
, Vx_window_horizontal_drag_shape
;
168 /* The shape when over mouse-sensitive text. */
170 Lisp_Object Vx_sensitive_text_pointer_shape
;
173 #define IDC_HAND MAKEINTRESOURCE(32649)
176 /* Color of chars displayed in cursor box. */
178 Lisp_Object Vx_cursor_fore_pixel
;
180 /* Nonzero if using Windows. */
182 static int w32_in_use
;
184 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
186 Lisp_Object Vx_pixel_size_width_font_regexp
;
188 /* Alist of bdf fonts and the files that define them. */
189 Lisp_Object Vw32_bdf_filename_alist
;
191 /* A flag to control whether fonts are matched strictly or not. */
192 static int w32_strict_fontnames
;
194 /* A flag to control whether we should only repaint if GetUpdateRect
195 indicates there is an update region. */
196 static int w32_strict_painting
;
198 /* Associative list linking character set strings to Windows codepages. */
199 static Lisp_Object Vw32_charset_info_alist
;
201 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
202 #ifndef VIETNAMESE_CHARSET
203 #define VIETNAMESE_CHARSET 163
207 Lisp_Object Qsuppress_icon
;
208 Lisp_Object Qundefined_color
;
209 Lisp_Object Qcancel_timer
;
215 Lisp_Object Qcontrol
;
218 Lisp_Object Qw32_charset_ansi
;
219 Lisp_Object Qw32_charset_default
;
220 Lisp_Object Qw32_charset_symbol
;
221 Lisp_Object Qw32_charset_shiftjis
;
222 Lisp_Object Qw32_charset_hangeul
;
223 Lisp_Object Qw32_charset_gb2312
;
224 Lisp_Object Qw32_charset_chinesebig5
;
225 Lisp_Object Qw32_charset_oem
;
227 #ifndef JOHAB_CHARSET
228 #define JOHAB_CHARSET 130
231 Lisp_Object Qw32_charset_easteurope
;
232 Lisp_Object Qw32_charset_turkish
;
233 Lisp_Object Qw32_charset_baltic
;
234 Lisp_Object Qw32_charset_russian
;
235 Lisp_Object Qw32_charset_arabic
;
236 Lisp_Object Qw32_charset_greek
;
237 Lisp_Object Qw32_charset_hebrew
;
238 Lisp_Object Qw32_charset_vietnamese
;
239 Lisp_Object Qw32_charset_thai
;
240 Lisp_Object Qw32_charset_johab
;
241 Lisp_Object Qw32_charset_mac
;
244 #ifdef UNICODE_CHARSET
245 Lisp_Object Qw32_charset_unicode
;
248 /* The ANSI codepage. */
249 int w32_ansi_code_page
;
251 /* Prefix for system colors. */
252 #define SYSTEM_COLOR_PREFIX "System"
253 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
255 /* State variables for emulating a three button mouse. */
260 static int button_state
= 0;
261 static W32Msg saved_mouse_button_msg
;
262 static unsigned mouse_button_timer
= 0; /* non-zero when timer is active */
263 static W32Msg saved_mouse_move_msg
;
264 static unsigned mouse_move_timer
= 0;
266 /* Window that is tracking the mouse. */
267 static HWND track_mouse_window
;
269 /* Multi-monitor API definitions that are not pulled from the headers
270 since we are compiling for NT 4. */
271 #ifndef MONITOR_DEFAULT_TO_NEAREST
272 #define MONITOR_DEFAULT_TO_NEAREST 2
274 /* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
275 To avoid a compile error on one or the other, redefine with a new name. */
284 typedef BOOL (WINAPI
* TrackMouseEvent_Proc
)
285 (IN OUT LPTRACKMOUSEEVENT lpEventTrack
);
286 typedef LONG (WINAPI
* ImmGetCompositionString_Proc
)
287 (IN HIMC context
, IN DWORD index
, OUT LPVOID buffer
, IN DWORD bufLen
);
288 typedef HIMC (WINAPI
* ImmGetContext_Proc
) (IN HWND window
);
289 typedef HMONITOR (WINAPI
* MonitorFromPoint_Proc
) (IN POINT pt
, IN DWORD flags
);
290 typedef BOOL (WINAPI
* GetMonitorInfo_Proc
)
291 (IN HMONITOR monitor
, OUT
struct MONITOR_INFO
* info
);
293 TrackMouseEvent_Proc track_mouse_event_fn
= NULL
;
294 ClipboardSequence_Proc clipboard_sequence_fn
= NULL
;
295 ImmGetCompositionString_Proc get_composition_string_fn
= NULL
;
296 ImmGetContext_Proc get_ime_context_fn
= NULL
;
297 MonitorFromPoint_Proc monitor_from_point_fn
= NULL
;
298 GetMonitorInfo_Proc get_monitor_info_fn
= NULL
;
300 extern AppendMenuW_Proc unicode_append_menu
;
302 /* Flag to selectively ignore WM_IME_CHAR messages. */
303 static int ignore_ime_char
= 0;
305 /* W95 mousewheel handler */
306 unsigned int msh_mousewheel
= 0;
309 #define MOUSE_BUTTON_ID 1
310 #define MOUSE_MOVE_ID 2
311 #define MENU_FREE_ID 3
312 #define HOURGLASS_ID 4
313 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
315 #define MENU_FREE_DELAY 1000
316 static unsigned menu_free_timer
= 0;
318 /* The below are defined in frame.c. */
320 extern Lisp_Object Vwindow_system_version
;
323 int image_cache_refcount
, dpyinfo_refcount
;
327 /* From w32term.c. */
328 extern int w32_num_mouse_buttons
;
329 extern Lisp_Object Vw32_recognize_altgr
;
331 extern HWND w32_system_caret_hwnd
;
333 extern int w32_system_caret_height
;
334 extern int w32_system_caret_x
;
335 extern int w32_system_caret_y
;
336 extern int w32_use_visible_system_caret
;
338 static HWND w32_visible_system_caret_hwnd
;
341 extern HMENU current_popup_menu
;
342 static int menubar_in_use
= 0;
344 /* From w32uniscribe.c */
345 #ifdef USE_FONT_BACKEND
346 extern void syms_of_w32uniscribe ();
347 extern int uniscribe_available
;
350 /* Function prototypes for hourglass support. */
351 static void show_hourglass
P_ ((struct frame
*));
352 static void hide_hourglass
P_ ((void));
356 /* Error if we are not connected to MS-Windows. */
361 error ("MS-Windows not in use or not initialized");
364 /* Nonzero if we can use mouse menus.
365 You should not call this unless HAVE_MENUS is defined. */
373 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
374 and checking validity for W32. */
377 check_x_frame (frame
)
383 frame
= selected_frame
;
384 CHECK_LIVE_FRAME (frame
);
386 if (! FRAME_W32_P (f
))
387 error ("Non-W32 frame used");
391 /* Let the user specify a display with a frame.
392 nil stands for the selected frame--or, if that is not a w32 frame,
393 the first display on the list. */
395 struct w32_display_info
*
396 check_x_display_info (frame
)
401 struct frame
*sf
= XFRAME (selected_frame
);
403 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
404 return FRAME_W32_DISPLAY_INFO (sf
);
406 return &one_w32_display_info
;
408 else if (STRINGP (frame
))
409 return x_display_info_for_name (frame
);
414 CHECK_LIVE_FRAME (frame
);
416 if (! FRAME_W32_P (f
))
417 error ("Non-W32 frame used");
418 return FRAME_W32_DISPLAY_INFO (f
);
422 /* Return the Emacs frame-object corresponding to an w32 window.
423 It could be the frame's main window or an icon window. */
425 /* This function can be called during GC, so use GC_xxx type test macros. */
428 x_window_to_frame (dpyinfo
, wdesc
)
429 struct w32_display_info
*dpyinfo
;
432 Lisp_Object tail
, frame
;
435 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
441 if (!FRAME_W32_P (f
) || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
444 if (FRAME_W32_WINDOW (f
) == wdesc
)
451 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
452 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
453 static void my_create_window
P_ ((struct frame
*));
454 static void my_create_tip_window
P_ ((struct frame
*));
456 /* TODO: Native Input Method support; see x_create_im. */
457 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
458 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
459 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
460 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
461 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
462 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
463 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
464 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
465 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
466 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
467 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
468 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
469 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
475 /* Store the screen positions of frame F into XPTR and YPTR.
476 These are the positions of the containing window manager window,
477 not Emacs's own window. */
480 x_real_positions (f
, xptr
, yptr
)
487 /* Get the bounds of the WM window. */
488 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
493 /* Convert (0, 0) in the client area to screen co-ordinates. */
494 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
496 /* Remember x_pixels_diff and y_pixels_diff. */
497 f
->x_pixels_diff
= pt
.x
- rect
.left
;
498 f
->y_pixels_diff
= pt
.y
- rect
.top
;
506 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
,
507 Sw32_define_rgb_color
, 4, 4, 0,
508 doc
: /* Convert RGB numbers to a Windows color reference and associate with NAME.
509 This adds or updates a named color to `w32-color-map', making it
510 available for use. The original entry's RGB ref is returned, or nil
511 if the entry is new. */)
512 (red
, green
, blue
, name
)
513 Lisp_Object red
, green
, blue
, name
;
516 Lisp_Object oldrgb
= Qnil
;
520 CHECK_NUMBER (green
);
524 XSETINT (rgb
, RGB (XUINT (red
), XUINT (green
), XUINT (blue
)));
528 /* replace existing entry in w32-color-map or add new entry. */
529 entry
= Fassoc (name
, Vw32_color_map
);
532 entry
= Fcons (name
, rgb
);
533 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
537 oldrgb
= Fcdr (entry
);
538 Fsetcdr (entry
, rgb
);
546 DEFUN ("w32-load-color-file", Fw32_load_color_file
,
547 Sw32_load_color_file
, 1, 1, 0,
548 doc
: /* Create an alist of color entries from an external file.
549 Assign this value to `w32-color-map' to replace the existing color map.
551 The file should define one named RGB color per line like so:
553 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
555 Lisp_Object filename
;
558 Lisp_Object cmap
= Qnil
;
561 CHECK_STRING (filename
);
562 abspath
= Fexpand_file_name (filename
, Qnil
);
564 fp
= fopen (SDATA (filename
), "rt");
568 int red
, green
, blue
;
573 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
574 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
576 char *name
= buf
+ num
;
577 num
= strlen (name
) - 1;
578 if (name
[num
] == '\n')
580 cmap
= Fcons (Fcons (build_string (name
),
581 make_number (RGB (red
, green
, blue
))),
593 /* The default colors for the w32 color map */
594 typedef struct colormap_t
600 colormap_t w32_color_map
[] =
602 {"snow" , PALETTERGB (255,250,250)},
603 {"ghost white" , PALETTERGB (248,248,255)},
604 {"GhostWhite" , PALETTERGB (248,248,255)},
605 {"white smoke" , PALETTERGB (245,245,245)},
606 {"WhiteSmoke" , PALETTERGB (245,245,245)},
607 {"gainsboro" , PALETTERGB (220,220,220)},
608 {"floral white" , PALETTERGB (255,250,240)},
609 {"FloralWhite" , PALETTERGB (255,250,240)},
610 {"old lace" , PALETTERGB (253,245,230)},
611 {"OldLace" , PALETTERGB (253,245,230)},
612 {"linen" , PALETTERGB (250,240,230)},
613 {"antique white" , PALETTERGB (250,235,215)},
614 {"AntiqueWhite" , PALETTERGB (250,235,215)},
615 {"papaya whip" , PALETTERGB (255,239,213)},
616 {"PapayaWhip" , PALETTERGB (255,239,213)},
617 {"blanched almond" , PALETTERGB (255,235,205)},
618 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
619 {"bisque" , PALETTERGB (255,228,196)},
620 {"peach puff" , PALETTERGB (255,218,185)},
621 {"PeachPuff" , PALETTERGB (255,218,185)},
622 {"navajo white" , PALETTERGB (255,222,173)},
623 {"NavajoWhite" , PALETTERGB (255,222,173)},
624 {"moccasin" , PALETTERGB (255,228,181)},
625 {"cornsilk" , PALETTERGB (255,248,220)},
626 {"ivory" , PALETTERGB (255,255,240)},
627 {"lemon chiffon" , PALETTERGB (255,250,205)},
628 {"LemonChiffon" , PALETTERGB (255,250,205)},
629 {"seashell" , PALETTERGB (255,245,238)},
630 {"honeydew" , PALETTERGB (240,255,240)},
631 {"mint cream" , PALETTERGB (245,255,250)},
632 {"MintCream" , PALETTERGB (245,255,250)},
633 {"azure" , PALETTERGB (240,255,255)},
634 {"alice blue" , PALETTERGB (240,248,255)},
635 {"AliceBlue" , PALETTERGB (240,248,255)},
636 {"lavender" , PALETTERGB (230,230,250)},
637 {"lavender blush" , PALETTERGB (255,240,245)},
638 {"LavenderBlush" , PALETTERGB (255,240,245)},
639 {"misty rose" , PALETTERGB (255,228,225)},
640 {"MistyRose" , PALETTERGB (255,228,225)},
641 {"white" , PALETTERGB (255,255,255)},
642 {"black" , PALETTERGB ( 0, 0, 0)},
643 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
644 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
645 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
646 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
647 {"dim gray" , PALETTERGB (105,105,105)},
648 {"DimGray" , PALETTERGB (105,105,105)},
649 {"dim grey" , PALETTERGB (105,105,105)},
650 {"DimGrey" , PALETTERGB (105,105,105)},
651 {"slate gray" , PALETTERGB (112,128,144)},
652 {"SlateGray" , PALETTERGB (112,128,144)},
653 {"slate grey" , PALETTERGB (112,128,144)},
654 {"SlateGrey" , PALETTERGB (112,128,144)},
655 {"light slate gray" , PALETTERGB (119,136,153)},
656 {"LightSlateGray" , PALETTERGB (119,136,153)},
657 {"light slate grey" , PALETTERGB (119,136,153)},
658 {"LightSlateGrey" , PALETTERGB (119,136,153)},
659 {"gray" , PALETTERGB (190,190,190)},
660 {"grey" , PALETTERGB (190,190,190)},
661 {"light grey" , PALETTERGB (211,211,211)},
662 {"LightGrey" , PALETTERGB (211,211,211)},
663 {"light gray" , PALETTERGB (211,211,211)},
664 {"LightGray" , PALETTERGB (211,211,211)},
665 {"midnight blue" , PALETTERGB ( 25, 25,112)},
666 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
667 {"navy" , PALETTERGB ( 0, 0,128)},
668 {"navy blue" , PALETTERGB ( 0, 0,128)},
669 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
670 {"cornflower blue" , PALETTERGB (100,149,237)},
671 {"CornflowerBlue" , PALETTERGB (100,149,237)},
672 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
673 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
674 {"slate blue" , PALETTERGB (106, 90,205)},
675 {"SlateBlue" , PALETTERGB (106, 90,205)},
676 {"medium slate blue" , PALETTERGB (123,104,238)},
677 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
678 {"light slate blue" , PALETTERGB (132,112,255)},
679 {"LightSlateBlue" , PALETTERGB (132,112,255)},
680 {"medium blue" , PALETTERGB ( 0, 0,205)},
681 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
682 {"royal blue" , PALETTERGB ( 65,105,225)},
683 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
684 {"blue" , PALETTERGB ( 0, 0,255)},
685 {"dodger blue" , PALETTERGB ( 30,144,255)},
686 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
687 {"deep sky blue" , PALETTERGB ( 0,191,255)},
688 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
689 {"sky blue" , PALETTERGB (135,206,235)},
690 {"SkyBlue" , PALETTERGB (135,206,235)},
691 {"light sky blue" , PALETTERGB (135,206,250)},
692 {"LightSkyBlue" , PALETTERGB (135,206,250)},
693 {"steel blue" , PALETTERGB ( 70,130,180)},
694 {"SteelBlue" , PALETTERGB ( 70,130,180)},
695 {"light steel blue" , PALETTERGB (176,196,222)},
696 {"LightSteelBlue" , PALETTERGB (176,196,222)},
697 {"light blue" , PALETTERGB (173,216,230)},
698 {"LightBlue" , PALETTERGB (173,216,230)},
699 {"powder blue" , PALETTERGB (176,224,230)},
700 {"PowderBlue" , PALETTERGB (176,224,230)},
701 {"pale turquoise" , PALETTERGB (175,238,238)},
702 {"PaleTurquoise" , PALETTERGB (175,238,238)},
703 {"dark turquoise" , PALETTERGB ( 0,206,209)},
704 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
705 {"medium turquoise" , PALETTERGB ( 72,209,204)},
706 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
707 {"turquoise" , PALETTERGB ( 64,224,208)},
708 {"cyan" , PALETTERGB ( 0,255,255)},
709 {"light cyan" , PALETTERGB (224,255,255)},
710 {"LightCyan" , PALETTERGB (224,255,255)},
711 {"cadet blue" , PALETTERGB ( 95,158,160)},
712 {"CadetBlue" , PALETTERGB ( 95,158,160)},
713 {"medium aquamarine" , PALETTERGB (102,205,170)},
714 {"MediumAquamarine" , PALETTERGB (102,205,170)},
715 {"aquamarine" , PALETTERGB (127,255,212)},
716 {"dark green" , PALETTERGB ( 0,100, 0)},
717 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
718 {"dark olive green" , PALETTERGB ( 85,107, 47)},
719 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
720 {"dark sea green" , PALETTERGB (143,188,143)},
721 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
722 {"sea green" , PALETTERGB ( 46,139, 87)},
723 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
724 {"medium sea green" , PALETTERGB ( 60,179,113)},
725 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
726 {"light sea green" , PALETTERGB ( 32,178,170)},
727 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
728 {"pale green" , PALETTERGB (152,251,152)},
729 {"PaleGreen" , PALETTERGB (152,251,152)},
730 {"spring green" , PALETTERGB ( 0,255,127)},
731 {"SpringGreen" , PALETTERGB ( 0,255,127)},
732 {"lawn green" , PALETTERGB (124,252, 0)},
733 {"LawnGreen" , PALETTERGB (124,252, 0)},
734 {"green" , PALETTERGB ( 0,255, 0)},
735 {"chartreuse" , PALETTERGB (127,255, 0)},
736 {"medium spring green" , PALETTERGB ( 0,250,154)},
737 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
738 {"green yellow" , PALETTERGB (173,255, 47)},
739 {"GreenYellow" , PALETTERGB (173,255, 47)},
740 {"lime green" , PALETTERGB ( 50,205, 50)},
741 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
742 {"yellow green" , PALETTERGB (154,205, 50)},
743 {"YellowGreen" , PALETTERGB (154,205, 50)},
744 {"forest green" , PALETTERGB ( 34,139, 34)},
745 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
746 {"olive drab" , PALETTERGB (107,142, 35)},
747 {"OliveDrab" , PALETTERGB (107,142, 35)},
748 {"dark khaki" , PALETTERGB (189,183,107)},
749 {"DarkKhaki" , PALETTERGB (189,183,107)},
750 {"khaki" , PALETTERGB (240,230,140)},
751 {"pale goldenrod" , PALETTERGB (238,232,170)},
752 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
753 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
754 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
755 {"light yellow" , PALETTERGB (255,255,224)},
756 {"LightYellow" , PALETTERGB (255,255,224)},
757 {"yellow" , PALETTERGB (255,255, 0)},
758 {"gold" , PALETTERGB (255,215, 0)},
759 {"light goldenrod" , PALETTERGB (238,221,130)},
760 {"LightGoldenrod" , PALETTERGB (238,221,130)},
761 {"goldenrod" , PALETTERGB (218,165, 32)},
762 {"dark goldenrod" , PALETTERGB (184,134, 11)},
763 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
764 {"rosy brown" , PALETTERGB (188,143,143)},
765 {"RosyBrown" , PALETTERGB (188,143,143)},
766 {"indian red" , PALETTERGB (205, 92, 92)},
767 {"IndianRed" , PALETTERGB (205, 92, 92)},
768 {"saddle brown" , PALETTERGB (139, 69, 19)},
769 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
770 {"sienna" , PALETTERGB (160, 82, 45)},
771 {"peru" , PALETTERGB (205,133, 63)},
772 {"burlywood" , PALETTERGB (222,184,135)},
773 {"beige" , PALETTERGB (245,245,220)},
774 {"wheat" , PALETTERGB (245,222,179)},
775 {"sandy brown" , PALETTERGB (244,164, 96)},
776 {"SandyBrown" , PALETTERGB (244,164, 96)},
777 {"tan" , PALETTERGB (210,180,140)},
778 {"chocolate" , PALETTERGB (210,105, 30)},
779 {"firebrick" , PALETTERGB (178,34, 34)},
780 {"brown" , PALETTERGB (165,42, 42)},
781 {"dark salmon" , PALETTERGB (233,150,122)},
782 {"DarkSalmon" , PALETTERGB (233,150,122)},
783 {"salmon" , PALETTERGB (250,128,114)},
784 {"light salmon" , PALETTERGB (255,160,122)},
785 {"LightSalmon" , PALETTERGB (255,160,122)},
786 {"orange" , PALETTERGB (255,165, 0)},
787 {"dark orange" , PALETTERGB (255,140, 0)},
788 {"DarkOrange" , PALETTERGB (255,140, 0)},
789 {"coral" , PALETTERGB (255,127, 80)},
790 {"light coral" , PALETTERGB (240,128,128)},
791 {"LightCoral" , PALETTERGB (240,128,128)},
792 {"tomato" , PALETTERGB (255, 99, 71)},
793 {"orange red" , PALETTERGB (255, 69, 0)},
794 {"OrangeRed" , PALETTERGB (255, 69, 0)},
795 {"red" , PALETTERGB (255, 0, 0)},
796 {"hot pink" , PALETTERGB (255,105,180)},
797 {"HotPink" , PALETTERGB (255,105,180)},
798 {"deep pink" , PALETTERGB (255, 20,147)},
799 {"DeepPink" , PALETTERGB (255, 20,147)},
800 {"pink" , PALETTERGB (255,192,203)},
801 {"light pink" , PALETTERGB (255,182,193)},
802 {"LightPink" , PALETTERGB (255,182,193)},
803 {"pale violet red" , PALETTERGB (219,112,147)},
804 {"PaleVioletRed" , PALETTERGB (219,112,147)},
805 {"maroon" , PALETTERGB (176, 48, 96)},
806 {"medium violet red" , PALETTERGB (199, 21,133)},
807 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
808 {"violet red" , PALETTERGB (208, 32,144)},
809 {"VioletRed" , PALETTERGB (208, 32,144)},
810 {"magenta" , PALETTERGB (255, 0,255)},
811 {"violet" , PALETTERGB (238,130,238)},
812 {"plum" , PALETTERGB (221,160,221)},
813 {"orchid" , PALETTERGB (218,112,214)},
814 {"medium orchid" , PALETTERGB (186, 85,211)},
815 {"MediumOrchid" , PALETTERGB (186, 85,211)},
816 {"dark orchid" , PALETTERGB (153, 50,204)},
817 {"DarkOrchid" , PALETTERGB (153, 50,204)},
818 {"dark violet" , PALETTERGB (148, 0,211)},
819 {"DarkViolet" , PALETTERGB (148, 0,211)},
820 {"blue violet" , PALETTERGB (138, 43,226)},
821 {"BlueViolet" , PALETTERGB (138, 43,226)},
822 {"purple" , PALETTERGB (160, 32,240)},
823 {"medium purple" , PALETTERGB (147,112,219)},
824 {"MediumPurple" , PALETTERGB (147,112,219)},
825 {"thistle" , PALETTERGB (216,191,216)},
826 {"gray0" , PALETTERGB ( 0, 0, 0)},
827 {"grey0" , PALETTERGB ( 0, 0, 0)},
828 {"dark grey" , PALETTERGB (169,169,169)},
829 {"DarkGrey" , PALETTERGB (169,169,169)},
830 {"dark gray" , PALETTERGB (169,169,169)},
831 {"DarkGray" , PALETTERGB (169,169,169)},
832 {"dark blue" , PALETTERGB ( 0, 0,139)},
833 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
834 {"dark cyan" , PALETTERGB ( 0,139,139)},
835 {"DarkCyan" , PALETTERGB ( 0,139,139)},
836 {"dark magenta" , PALETTERGB (139, 0,139)},
837 {"DarkMagenta" , PALETTERGB (139, 0,139)},
838 {"dark red" , PALETTERGB (139, 0, 0)},
839 {"DarkRed" , PALETTERGB (139, 0, 0)},
840 {"light green" , PALETTERGB (144,238,144)},
841 {"LightGreen" , PALETTERGB (144,238,144)},
844 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
845 0, 0, 0, doc
: /* Return the default color map. */)
849 colormap_t
*pc
= w32_color_map
;
856 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
858 cmap
= Fcons (Fcons (build_string (pc
->name
),
859 make_number (pc
->colorref
)),
877 color
= Frassq (rgb
, Vw32_color_map
);
882 return (Fcar (color
));
888 w32_color_map_lookup (colorname
)
891 Lisp_Object tail
, ret
= Qnil
;
895 for (tail
= Vw32_color_map
; CONSP (tail
); tail
= XCDR (tail
))
897 register Lisp_Object elt
, tem
;
900 if (!CONSP (elt
)) continue;
904 if (lstrcmpi (SDATA (tem
), colorname
) == 0)
921 add_system_logical_colors_to_map (system_colors
)
922 Lisp_Object
*system_colors
;
926 /* Other registry operations are done with input blocked. */
929 /* Look for "Control Panel/Colors" under User and Machine registry
931 if (RegOpenKeyEx (HKEY_CURRENT_USER
, "Control Panel\\Colors", 0,
932 KEY_READ
, &colors_key
) == ERROR_SUCCESS
933 || RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Control Panel\\Colors", 0,
934 KEY_READ
, &colors_key
) == ERROR_SUCCESS
)
937 char color_buffer
[64];
938 char full_name_buffer
[MAX_PATH
+ SYSTEM_COLOR_PREFIX_LEN
];
940 DWORD name_size
, color_size
;
941 char *name_buffer
= full_name_buffer
+ SYSTEM_COLOR_PREFIX_LEN
;
943 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
944 color_size
= sizeof (color_buffer
);
946 strcpy (full_name_buffer
, SYSTEM_COLOR_PREFIX
);
948 while (RegEnumValueA (colors_key
, index
, name_buffer
, &name_size
,
949 NULL
, NULL
, color_buffer
, &color_size
)
953 if (sscanf (color_buffer
, " %u %u %u", &r
, &g
, &b
) == 3)
954 *system_colors
= Fcons (Fcons (build_string (full_name_buffer
),
955 make_number (RGB (r
, g
, b
))),
958 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
959 color_size
= sizeof (color_buffer
);
962 RegCloseKey (colors_key
);
970 x_to_w32_color (colorname
)
973 register Lisp_Object ret
= Qnil
;
977 if (colorname
[0] == '#')
979 /* Could be an old-style RGB Device specification. */
982 color
= colorname
+ 1;
984 size
= strlen (color
);
985 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
993 for (i
= 0; i
< 3; i
++)
999 /* The check for 'x' in the following conditional takes into
1000 account the fact that strtol allows a "0x" in front of
1001 our numbers, and we don't. */
1002 if (!isxdigit (color
[0]) || color
[1] == 'x')
1006 value
= strtoul (color
, &end
, 16);
1008 if (errno
== ERANGE
|| end
- color
!= size
)
1013 value
= value
* 0x10;
1024 colorval
|= (value
<< pos
);
1029 XSETINT (ret
, colorval
);
1036 else if (strnicmp (colorname
, "rgb:", 4) == 0)
1044 color
= colorname
+ 4;
1045 for (i
= 0; i
< 3; i
++)
1048 unsigned long value
;
1050 /* The check for 'x' in the following conditional takes into
1051 account the fact that strtol allows a "0x" in front of
1052 our numbers, and we don't. */
1053 if (!isxdigit (color
[0]) || color
[1] == 'x')
1055 value
= strtoul (color
, &end
, 16);
1056 if (errno
== ERANGE
)
1058 switch (end
- color
)
1061 value
= value
* 0x10 + value
;
1074 if (value
== ULONG_MAX
)
1076 colorval
|= (value
<< pos
);
1083 XSETINT (ret
, colorval
);
1091 else if (strnicmp (colorname
, "rgbi:", 5) == 0)
1093 /* This is an RGB Intensity specification. */
1100 color
= colorname
+ 5;
1101 for (i
= 0; i
< 3; i
++)
1107 value
= strtod (color
, &end
);
1108 if (errno
== ERANGE
)
1110 if (value
< 0.0 || value
> 1.0)
1112 val
= (UINT
)(0x100 * value
);
1113 /* We used 0x100 instead of 0xFF to give a continuous
1114 range between 0.0 and 1.0 inclusive. The next statement
1115 fixes the 1.0 case. */
1118 colorval
|= (val
<< pos
);
1125 XSETINT (ret
, colorval
);
1133 /* I am not going to attempt to handle any of the CIE color schemes
1134 or TekHVC, since I don't know the algorithms for conversion to
1137 /* If we fail to lookup the color name in w32_color_map, then check the
1138 colorname to see if it can be crudely approximated: If the X color
1139 ends in a number (e.g., "darkseagreen2"), strip the number and
1140 return the result of looking up the base color name. */
1141 ret
= w32_color_map_lookup (colorname
);
1144 int len
= strlen (colorname
);
1146 if (isdigit (colorname
[len
- 1]))
1148 char *ptr
, *approx
= alloca (len
+ 1);
1150 strcpy (approx
, colorname
);
1151 ptr
= &approx
[len
- 1];
1152 while (ptr
> approx
&& isdigit (*ptr
))
1155 ret
= w32_color_map_lookup (approx
);
1164 w32_regenerate_palette (FRAME_PTR f
)
1166 struct w32_palette_entry
* list
;
1167 LOGPALETTE
* log_palette
;
1168 HPALETTE new_palette
;
1171 /* don't bother trying to create palette if not supported */
1172 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1175 log_palette
= (LOGPALETTE
*)
1176 alloca (sizeof (LOGPALETTE
) +
1177 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1178 log_palette
->palVersion
= 0x300;
1179 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1181 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1183 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1184 i
++, list
= list
->next
)
1185 log_palette
->palPalEntry
[i
] = list
->entry
;
1187 new_palette
= CreatePalette (log_palette
);
1191 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1192 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1193 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1195 /* Realize display palette and garbage all frames. */
1196 release_frame_dc (f
, get_frame_dc (f
));
1201 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1202 #define SET_W32_COLOR(pe, color) \
1205 pe.peRed = GetRValue (color); \
1206 pe.peGreen = GetGValue (color); \
1207 pe.peBlue = GetBValue (color); \
1212 /* Keep these around in case we ever want to track color usage. */
1214 w32_map_color (FRAME_PTR f
, COLORREF color
)
1216 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1218 if (NILP (Vw32_enable_palette
))
1221 /* check if color is already mapped */
1224 if (W32_COLOR (list
->entry
) == color
)
1232 /* not already mapped, so add to list and recreate Windows palette */
1233 list
= (struct w32_palette_entry
*)
1234 xmalloc (sizeof (struct w32_palette_entry
));
1235 SET_W32_COLOR (list
->entry
, color
);
1237 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1238 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1239 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1241 /* set flag that palette must be regenerated */
1242 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1246 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1248 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1249 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1251 if (NILP (Vw32_enable_palette
))
1254 /* check if color is already mapped */
1257 if (W32_COLOR (list
->entry
) == color
)
1259 if (--list
->refcount
== 0)
1263 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1273 /* set flag that palette must be regenerated */
1274 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1279 /* Gamma-correct COLOR on frame F. */
1282 gamma_correct (f
, color
)
1288 *color
= PALETTERGB (
1289 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1290 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1291 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1296 /* Decide if color named COLOR is valid for the display associated with
1297 the selected frame; if so, return the rgb values in COLOR_DEF.
1298 If ALLOC is nonzero, allocate a new colormap cell. */
1301 w32_defined_color (f
, color
, color_def
, alloc
)
1307 register Lisp_Object tem
;
1308 COLORREF w32_color_ref
;
1310 tem
= x_to_w32_color (color
);
1316 /* Apply gamma correction. */
1317 w32_color_ref
= XUINT (tem
);
1318 gamma_correct (f
, &w32_color_ref
);
1319 XSETINT (tem
, w32_color_ref
);
1322 /* Map this color to the palette if it is enabled. */
1323 if (!NILP (Vw32_enable_palette
))
1325 struct w32_palette_entry
* entry
=
1326 one_w32_display_info
.color_list
;
1327 struct w32_palette_entry
** prev
=
1328 &one_w32_display_info
.color_list
;
1330 /* check if color is already mapped */
1333 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1335 prev
= &entry
->next
;
1336 entry
= entry
->next
;
1339 if (entry
== NULL
&& alloc
)
1341 /* not already mapped, so add to list */
1342 entry
= (struct w32_palette_entry
*)
1343 xmalloc (sizeof (struct w32_palette_entry
));
1344 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1347 one_w32_display_info
.num_colors
++;
1349 /* set flag that palette must be regenerated */
1350 one_w32_display_info
.regen_palette
= TRUE
;
1353 /* Ensure COLORREF value is snapped to nearest color in (default)
1354 palette by simulating the PALETTERGB macro. This works whether
1355 or not the display device has a palette. */
1356 w32_color_ref
= XUINT (tem
) | 0x2000000;
1358 color_def
->pixel
= w32_color_ref
;
1359 color_def
->red
= GetRValue (w32_color_ref
) * 256;
1360 color_def
->green
= GetGValue (w32_color_ref
) * 256;
1361 color_def
->blue
= GetBValue (w32_color_ref
) * 256;
1371 /* Given a string ARG naming a color, compute a pixel value from it
1372 suitable for screen F.
1373 If F is not a color screen, return DEF (default) regardless of what
1377 x_decode_color (f
, arg
, def
)
1386 if (strcmp (SDATA (arg
), "black") == 0)
1387 return BLACK_PIX_DEFAULT (f
);
1388 else if (strcmp (SDATA (arg
), "white") == 0)
1389 return WHITE_PIX_DEFAULT (f
);
1391 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1394 /* w32_defined_color is responsible for coping with failures
1395 by looking for a near-miss. */
1396 if (w32_defined_color (f
, SDATA (arg
), &cdef
, 1))
1399 /* defined_color failed; return an ultimate default. */
1405 /* Functions called only from `x_set_frame_param'
1406 to set individual parameters.
1408 If FRAME_W32_WINDOW (f) is 0,
1409 the frame is being created and its window does not exist yet.
1410 In that case, just record the parameter's new value
1411 in the standard place; do not attempt to change the window. */
1414 x_set_foreground_color (f
, arg
, oldval
)
1416 Lisp_Object arg
, oldval
;
1418 struct w32_output
*x
= f
->output_data
.w32
;
1419 PIX_TYPE fg
, old_fg
;
1421 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1422 old_fg
= FRAME_FOREGROUND_PIXEL (f
);
1423 FRAME_FOREGROUND_PIXEL (f
) = fg
;
1425 if (FRAME_W32_WINDOW (f
) != 0)
1427 if (x
->cursor_pixel
== old_fg
)
1428 x
->cursor_pixel
= fg
;
1430 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1431 if (FRAME_VISIBLE_P (f
))
1437 x_set_background_color (f
, arg
, oldval
)
1439 Lisp_Object arg
, oldval
;
1441 FRAME_BACKGROUND_PIXEL (f
)
1442 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1444 if (FRAME_W32_WINDOW (f
) != 0)
1446 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
1447 FRAME_BACKGROUND_PIXEL (f
));
1449 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1451 if (FRAME_VISIBLE_P (f
))
1457 x_set_mouse_color (f
, arg
, oldval
)
1459 Lisp_Object arg
, oldval
;
1461 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
1465 if (!EQ (Qnil
, arg
))
1466 f
->output_data
.w32
->mouse_pixel
1467 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1468 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
1470 /* Don't let pointers be invisible. */
1471 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1472 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
1473 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
1475 #if 0 /* TODO : cursor changes */
1478 /* It's not okay to crash if the user selects a screwy cursor. */
1479 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1481 if (!EQ (Qnil
, Vx_pointer_shape
))
1483 CHECK_NUMBER (Vx_pointer_shape
);
1484 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1487 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1488 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1490 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1492 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1493 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1494 XINT (Vx_nontext_pointer_shape
));
1497 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1498 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1500 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
1502 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1503 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1504 XINT (Vx_hourglass_pointer_shape
));
1507 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
1508 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
1510 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1511 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1513 CHECK_NUMBER (Vx_mode_pointer_shape
);
1514 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1515 XINT (Vx_mode_pointer_shape
));
1518 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1519 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1521 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1523 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1525 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1526 XINT (Vx_sensitive_text_pointer_shape
));
1529 hand_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1531 if (!NILP (Vx_window_horizontal_drag_shape
))
1533 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1534 horizontal_drag_cursor
1535 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1536 XINT (Vx_window_horizontal_drag_shape
));
1539 horizontal_drag_cursor
1540 = XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_sb_h_double_arrow
);
1542 /* Check and report errors with the above calls. */
1543 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1544 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1547 XColor fore_color
, back_color
;
1549 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1550 back_color
.pixel
= mask_color
;
1551 XQueryColor (FRAME_W32_DISPLAY (f
),
1552 DefaultColormap (FRAME_W32_DISPLAY (f
),
1553 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1555 XQueryColor (FRAME_W32_DISPLAY (f
),
1556 DefaultColormap (FRAME_W32_DISPLAY (f
),
1557 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1559 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1560 &fore_color
, &back_color
);
1561 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1562 &fore_color
, &back_color
);
1563 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1564 &fore_color
, &back_color
);
1565 XRecolorCursor (FRAME_W32_DISPLAY (f
), hand_cursor
,
1566 &fore_color
, &back_color
);
1567 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
1568 &fore_color
, &back_color
);
1571 if (FRAME_W32_WINDOW (f
) != 0)
1572 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1574 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1575 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1576 f
->output_data
.w32
->text_cursor
= cursor
;
1578 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1579 && f
->output_data
.w32
->nontext_cursor
!= 0)
1580 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1581 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1583 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
1584 && f
->output_data
.w32
->hourglass_cursor
!= 0)
1585 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
1586 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
1588 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1589 && f
->output_data
.w32
->modeline_cursor
!= 0)
1590 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1591 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1593 if (hand_cursor
!= f
->output_data
.w32
->hand_cursor
1594 && f
->output_data
.w32
->hand_cursor
!= 0)
1595 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hand_cursor
);
1596 f
->output_data
.w32
->hand_cursor
= hand_cursor
;
1598 XFlush (FRAME_W32_DISPLAY (f
));
1601 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1606 x_set_cursor_color (f
, arg
, oldval
)
1608 Lisp_Object arg
, oldval
;
1610 unsigned long fore_pixel
, pixel
;
1612 if (!NILP (Vx_cursor_fore_pixel
))
1613 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1614 WHITE_PIX_DEFAULT (f
));
1616 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1618 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1620 /* Make sure that the cursor color differs from the background color. */
1621 if (pixel
== FRAME_BACKGROUND_PIXEL (f
))
1623 pixel
= f
->output_data
.w32
->mouse_pixel
;
1624 if (pixel
== fore_pixel
)
1625 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1628 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1629 f
->output_data
.w32
->cursor_pixel
= pixel
;
1631 if (FRAME_W32_WINDOW (f
) != 0)
1634 /* Update frame's cursor_gc. */
1635 f
->output_data
.w32
->cursor_gc
->foreground
= fore_pixel
;
1636 f
->output_data
.w32
->cursor_gc
->background
= pixel
;
1640 if (FRAME_VISIBLE_P (f
))
1642 x_update_cursor (f
, 0);
1643 x_update_cursor (f
, 1);
1647 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1650 /* Set the border-color of frame F to pixel value PIX.
1651 Note that this does not fully take effect if done before
1655 x_set_border_pixel (f
, pix
)
1660 f
->output_data
.w32
->border_pixel
= pix
;
1662 if (FRAME_W32_WINDOW (f
) != 0 && f
->border_width
> 0)
1664 if (FRAME_VISIBLE_P (f
))
1669 /* Set the border-color of frame F to value described by ARG.
1670 ARG can be a string naming a color.
1671 The border-color is used for the border that is drawn by the server.
1672 Note that this does not fully take effect if done before
1673 F has a window; it must be redone when the window is created. */
1676 x_set_border_color (f
, arg
, oldval
)
1678 Lisp_Object arg
, oldval
;
1683 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1684 x_set_border_pixel (f
, pix
);
1685 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1690 x_set_cursor_type (f
, arg
, oldval
)
1692 Lisp_Object arg
, oldval
;
1694 set_frame_cursor_types (f
, arg
);
1696 /* Make sure the cursor gets redrawn. */
1697 cursor_type_changed
= 1;
1701 x_set_icon_type (f
, arg
, oldval
)
1703 Lisp_Object arg
, oldval
;
1707 if (NILP (arg
) && NILP (oldval
))
1710 if (STRINGP (arg
) && STRINGP (oldval
)
1711 && EQ (Fstring_equal (oldval
, arg
), Qt
))
1714 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
1719 result
= x_bitmap_icon (f
, arg
);
1723 error ("No icon window available");
1730 x_set_icon_name (f
, arg
, oldval
)
1732 Lisp_Object arg
, oldval
;
1736 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1739 else if (!NILP (arg
) || NILP (oldval
))
1745 if (f
->output_data
.w32
->icon_bitmap
!= 0)
1750 result
= x_text_icon (f
,
1751 (char *) SDATA ((!NILP (f
->icon_name
)
1760 error ("No icon window available");
1763 /* If the window was unmapped (and its icon was mapped),
1764 the new icon is not mapped, so map the window in its stead. */
1765 if (FRAME_VISIBLE_P (f
))
1767 #ifdef USE_X_TOOLKIT
1768 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1770 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1773 XFlush (FRAME_W32_DISPLAY (f
));
1780 x_set_menu_bar_lines (f
, value
, oldval
)
1782 Lisp_Object value
, oldval
;
1785 int olines
= FRAME_MENU_BAR_LINES (f
);
1787 /* Right now, menu bars don't work properly in minibuf-only frames;
1788 most of the commands try to apply themselves to the minibuffer
1789 frame itself, and get an error because you can't switch buffers
1790 in or split the minibuffer window. */
1791 if (FRAME_MINIBUF_ONLY_P (f
))
1794 if (INTEGERP (value
))
1795 nlines
= XINT (value
);
1799 FRAME_MENU_BAR_LINES (f
) = 0;
1801 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1804 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1805 free_frame_menubar (f
);
1806 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1808 /* Adjust the frame size so that the client (text) dimensions
1809 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1811 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1812 do_pending_window_change (0);
1818 /* Set the number of lines used for the tool bar of frame F to VALUE.
1819 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1820 is the old number of tool bar lines. This function changes the
1821 height of all windows on frame F to match the new tool bar height.
1822 The frame's height doesn't change. */
1825 x_set_tool_bar_lines (f
, value
, oldval
)
1827 Lisp_Object value
, oldval
;
1829 int delta
, nlines
, root_height
;
1830 Lisp_Object root_window
;
1832 /* Treat tool bars like menu bars. */
1833 if (FRAME_MINIBUF_ONLY_P (f
))
1836 /* Use VALUE only if an integer >= 0. */
1837 if (INTEGERP (value
) && XINT (value
) >= 0)
1838 nlines
= XFASTINT (value
);
1842 /* Make sure we redisplay all windows in this frame. */
1843 ++windows_or_buffers_changed
;
1845 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
1847 /* Don't resize the tool-bar to more than we have room for. */
1848 root_window
= FRAME_ROOT_WINDOW (f
);
1849 root_height
= WINDOW_TOTAL_LINES (XWINDOW (root_window
));
1850 if (root_height
- delta
< 1)
1852 delta
= root_height
- 1;
1853 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
1856 FRAME_TOOL_BAR_LINES (f
) = nlines
;
1857 change_window_heights (root_window
, delta
);
1860 /* We also have to make sure that the internal border at the top of
1861 the frame, below the menu bar or tool bar, is redrawn when the
1862 tool bar disappears. This is so because the internal border is
1863 below the tool bar if one is displayed, but is below the menu bar
1864 if there isn't a tool bar. The tool bar draws into the area
1865 below the menu bar. */
1866 if (FRAME_W32_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
1869 clear_current_matrices (f
);
1872 /* If the tool bar gets smaller, the internal border below it
1873 has to be cleared. It was formerly part of the display
1874 of the larger tool bar, and updating windows won't clear it. */
1877 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1878 int width
= FRAME_PIXEL_WIDTH (f
);
1879 int y
= nlines
* FRAME_LINE_HEIGHT (f
);
1883 HDC hdc
= get_frame_dc (f
);
1884 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
1885 release_frame_dc (f
, hdc
);
1889 if (WINDOWP (f
->tool_bar_window
))
1890 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
1895 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1898 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1899 name; if NAME is a string, set F's name to NAME and set
1900 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1902 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1903 suggesting a new name, which lisp code should override; if
1904 F->explicit_name is set, ignore the new name; otherwise, set it. */
1907 x_set_name (f
, name
, explicit)
1912 /* Make sure that requests from lisp code override requests from
1913 Emacs redisplay code. */
1916 /* If we're switching from explicit to implicit, we had better
1917 update the mode lines and thereby update the title. */
1918 if (f
->explicit_name
&& NILP (name
))
1919 update_mode_lines
= 1;
1921 f
->explicit_name
= ! NILP (name
);
1923 else if (f
->explicit_name
)
1926 /* If NAME is nil, set the name to the w32_id_name. */
1929 /* Check for no change needed in this very common case
1930 before we do any consing. */
1931 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
1934 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
1937 CHECK_STRING (name
);
1939 /* Don't change the name if it's already NAME. */
1940 if (! NILP (Fstring_equal (name
, f
->name
)))
1945 /* For setting the frame title, the title parameter should override
1946 the name parameter. */
1947 if (! NILP (f
->title
))
1950 if (FRAME_W32_WINDOW (f
))
1952 if (STRING_MULTIBYTE (name
))
1953 name
= ENCODE_SYSTEM (name
);
1956 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
1961 /* This function should be called when the user's lisp code has
1962 specified a name for the frame; the name will override any set by the
1965 x_explicitly_set_name (f
, arg
, oldval
)
1967 Lisp_Object arg
, oldval
;
1969 x_set_name (f
, arg
, 1);
1972 /* This function should be called by Emacs redisplay code to set the
1973 name; names set this way will never override names set by the user's
1976 x_implicitly_set_name (f
, arg
, oldval
)
1978 Lisp_Object arg
, oldval
;
1980 x_set_name (f
, arg
, 0);
1983 /* Change the title of frame F to NAME.
1984 If NAME is nil, use the frame name as the title. */
1987 x_set_title (f
, name
, old_name
)
1989 Lisp_Object name
, old_name
;
1991 /* Don't change the title if it's already NAME. */
1992 if (EQ (name
, f
->title
))
1995 update_mode_lines
= 1;
2002 if (FRAME_W32_WINDOW (f
))
2004 if (STRING_MULTIBYTE (name
))
2005 name
= ENCODE_SYSTEM (name
);
2008 SetWindowText (FRAME_W32_WINDOW (f
), SDATA (name
));
2014 void x_set_scroll_bar_default_width (f
)
2017 int wid
= FRAME_COLUMN_WIDTH (f
);
2019 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
2020 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) +
2025 /* Subroutines of creating a frame. */
2028 /* Return the value of parameter PARAM.
2030 First search ALIST, then Vdefault_frame_alist, then the X defaults
2031 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2033 Convert the resource to the type specified by desired_type.
2035 If no default is specified, return Qunbound. If you call
2036 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
2037 and don't let it get stored in any Lisp-visible variables! */
2040 w32_get_arg (alist
, param
, attribute
, class, type
)
2041 Lisp_Object alist
, param
;
2044 enum resource_types type
;
2046 return x_get_arg (check_x_display_info (Qnil
),
2047 alist
, param
, attribute
, class, type
);
2052 w32_load_cursor (LPCTSTR name
)
2054 /* Try first to load cursor from application resource. */
2055 Cursor cursor
= LoadImage ((HINSTANCE
) GetModuleHandle (NULL
),
2056 name
, IMAGE_CURSOR
, 0, 0,
2057 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
2060 /* Then try to load a shared predefined cursor. */
2061 cursor
= LoadImage (NULL
, name
, IMAGE_CURSOR
, 0, 0,
2062 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
2067 extern LRESULT CALLBACK
w32_wnd_proc ();
2070 w32_init_class (hinst
)
2075 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2076 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
2078 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
2079 wc
.hInstance
= hinst
;
2080 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
2081 wc
.hCursor
= w32_load_cursor (IDC_ARROW
);
2082 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
2083 wc
.lpszMenuName
= NULL
;
2084 wc
.lpszClassName
= EMACS_CLASS
;
2086 return (RegisterClass (&wc
));
2090 w32_createscrollbar (f
, bar
)
2092 struct scroll_bar
* bar
;
2094 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
2095 /* Position and size of scroll bar. */
2096 XINT (bar
->left
) + VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
2098 XINT (bar
->width
) - VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
2100 FRAME_W32_WINDOW (f
),
2107 w32_createwindow (f
)
2112 Lisp_Object top
= Qunbound
;
2113 Lisp_Object left
= Qunbound
;
2115 rect
.left
= rect
.top
= 0;
2116 rect
.right
= FRAME_PIXEL_WIDTH (f
);
2117 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
2119 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2120 FRAME_EXTERNAL_MENU_BAR (f
));
2122 /* Do first time app init */
2126 w32_init_class (hinst
);
2129 if (f
->size_hint_flags
& USPosition
|| f
->size_hint_flags
& PPosition
)
2131 XSETINT (left
, f
->left_pos
);
2132 XSETINT (top
, f
->top_pos
);
2134 else if (EQ (left
, Qunbound
) && EQ (top
, Qunbound
))
2136 /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
2137 for anything that is not a number and is not Qunbound. */
2138 left
= w32_get_arg (Qnil
, Qleft
, "left", "Left", RES_TYPE_NUMBER
);
2139 top
= w32_get_arg (Qnil
, Qtop
, "top", "Top", RES_TYPE_NUMBER
);
2142 FRAME_W32_WINDOW (f
) = hwnd
2143 = CreateWindow (EMACS_CLASS
,
2145 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2146 EQ (left
, Qunbound
) ? CW_USEDEFAULT
: XINT (left
),
2147 EQ (top
, Qunbound
) ? CW_USEDEFAULT
: XINT (top
),
2148 rect
.right
- rect
.left
,
2149 rect
.bottom
- rect
.top
,
2157 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
2158 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
2159 SetWindowLong (hwnd
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
2160 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
2161 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
2163 /* Enable drag-n-drop. */
2164 DragAcceptFiles (hwnd
, TRUE
);
2166 /* Do this to discard the default setting specified by our parent. */
2167 ShowWindow (hwnd
, SW_HIDE
);
2169 /* Update frame positions. */
2170 GetWindowRect (hwnd
, &rect
);
2171 f
->left_pos
= rect
.left
;
2172 f
->top_pos
= rect
.top
;
2177 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
2184 wmsg
->msg
.hwnd
= hwnd
;
2185 wmsg
->msg
.message
= msg
;
2186 wmsg
->msg
.wParam
= wParam
;
2187 wmsg
->msg
.lParam
= lParam
;
2188 wmsg
->msg
.time
= GetMessageTime ();
2193 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2194 between left and right keys as advertised. We test for this
2195 support dynamically, and set a flag when the support is absent. If
2196 absent, we keep track of the left and right control and alt keys
2197 ourselves. This is particularly necessary on keyboards that rely
2198 upon the AltGr key, which is represented as having the left control
2199 and right alt keys pressed. For these keyboards, we need to know
2200 when the left alt key has been pressed in addition to the AltGr key
2201 so that we can properly support M-AltGr-key sequences (such as M-@
2202 on Swedish keyboards). */
2204 #define EMACS_LCONTROL 0
2205 #define EMACS_RCONTROL 1
2206 #define EMACS_LMENU 2
2207 #define EMACS_RMENU 3
2209 static int modifiers
[4];
2210 static int modifiers_recorded
;
2211 static int modifier_key_support_tested
;
2214 test_modifier_support (unsigned int wparam
)
2218 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
2220 if (wparam
== VK_CONTROL
)
2230 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
2231 modifiers_recorded
= 1;
2233 modifiers_recorded
= 0;
2234 modifier_key_support_tested
= 1;
2238 record_keydown (unsigned int wparam
, unsigned int lparam
)
2242 if (!modifier_key_support_tested
)
2243 test_modifier_support (wparam
);
2245 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2248 if (wparam
== VK_CONTROL
)
2249 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2251 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2257 record_keyup (unsigned int wparam
, unsigned int lparam
)
2261 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2264 if (wparam
== VK_CONTROL
)
2265 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2267 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2272 /* Emacs can lose focus while a modifier key has been pressed. When
2273 it regains focus, be conservative and clear all modifiers since
2274 we cannot reconstruct the left and right modifier state. */
2280 if (GetFocus () == NULL
)
2281 /* Emacs doesn't have keyboard focus. Do nothing. */
2284 ctrl
= GetAsyncKeyState (VK_CONTROL
);
2285 alt
= GetAsyncKeyState (VK_MENU
);
2287 if (!(ctrl
& 0x08000))
2288 /* Clear any recorded control modifier state. */
2289 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2291 if (!(alt
& 0x08000))
2292 /* Clear any recorded alt modifier state. */
2293 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2295 /* Update the state of all modifier keys, because modifiers used in
2296 hot-key combinations can get stuck on if Emacs loses focus as a
2297 result of a hot-key being pressed. */
2301 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2303 GetKeyboardState (keystate
);
2304 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
2305 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
2306 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
2307 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
2308 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
2309 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
2310 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
2311 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
2312 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
2313 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
2314 SetKeyboardState (keystate
);
2318 /* Synchronize modifier state with what is reported with the current
2319 keystroke. Even if we cannot distinguish between left and right
2320 modifier keys, we know that, if no modifiers are set, then neither
2321 the left or right modifier should be set. */
2325 if (!modifiers_recorded
)
2328 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
2329 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2331 if (!(GetKeyState (VK_MENU
) & 0x8000))
2332 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2336 modifier_set (int vkey
)
2338 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
2339 return (GetKeyState (vkey
) & 0x1);
2340 if (!modifiers_recorded
)
2341 return (GetKeyState (vkey
) & 0x8000);
2346 return modifiers
[EMACS_LCONTROL
];
2348 return modifiers
[EMACS_RCONTROL
];
2350 return modifiers
[EMACS_LMENU
];
2352 return modifiers
[EMACS_RMENU
];
2354 return (GetKeyState (vkey
) & 0x8000);
2357 /* Convert between the modifier bits W32 uses and the modifier bits
2361 w32_key_to_modifier (int key
)
2363 Lisp_Object key_mapping
;
2368 key_mapping
= Vw32_lwindow_modifier
;
2371 key_mapping
= Vw32_rwindow_modifier
;
2374 key_mapping
= Vw32_apps_modifier
;
2377 key_mapping
= Vw32_scroll_lock_modifier
;
2383 /* NB. This code runs in the input thread, asychronously to the lisp
2384 thread, so we must be careful to ensure access to lisp data is
2385 thread-safe. The following code is safe because the modifier
2386 variable values are updated atomically from lisp and symbols are
2387 not relocated by GC. Also, we don't have to worry about seeing GC
2389 if (EQ (key_mapping
, Qhyper
))
2390 return hyper_modifier
;
2391 if (EQ (key_mapping
, Qsuper
))
2392 return super_modifier
;
2393 if (EQ (key_mapping
, Qmeta
))
2394 return meta_modifier
;
2395 if (EQ (key_mapping
, Qalt
))
2396 return alt_modifier
;
2397 if (EQ (key_mapping
, Qctrl
))
2398 return ctrl_modifier
;
2399 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
2400 return ctrl_modifier
;
2401 if (EQ (key_mapping
, Qshift
))
2402 return shift_modifier
;
2404 /* Don't generate any modifier if not explicitly requested. */
2409 w32_get_modifiers ()
2411 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
2412 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
2413 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
2414 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
2415 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
2416 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
2417 (modifier_set (VK_MENU
) ?
2418 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2421 /* We map the VK_* modifiers into console modifier constants
2422 so that we can use the same routines to handle both console
2423 and window input. */
2426 construct_console_modifiers ()
2431 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
2432 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
2433 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
2434 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
2435 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
2436 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
2437 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
2438 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
2439 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
2440 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
2441 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
2447 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
2451 /* Convert to emacs modifiers. */
2452 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
2458 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
2460 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
2463 if (virt_key
== VK_RETURN
)
2464 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
2466 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
2467 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
2469 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
2470 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
2472 if (virt_key
== VK_CLEAR
)
2473 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
2478 /* List of special key combinations which w32 would normally capture,
2479 but Emacs should grab instead. Not directly visible to lisp, to
2480 simplify synchronization. Each item is an integer encoding a virtual
2481 key code and modifier combination to capture. */
2482 static Lisp_Object w32_grabbed_keys
;
2484 #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8))
2485 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2486 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2487 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2489 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2490 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2491 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2493 /* Register hot-keys for reserved key combinations when Emacs has
2494 keyboard focus, since this is the only way Emacs can receive key
2495 combinations like Alt-Tab which are used by the system. */
2498 register_hot_keys (hwnd
)
2501 Lisp_Object keylist
;
2503 /* Use CONSP, since we are called asynchronously. */
2504 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2506 Lisp_Object key
= XCAR (keylist
);
2508 /* Deleted entries get set to nil. */
2509 if (!INTEGERP (key
))
2512 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
2513 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
2518 unregister_hot_keys (hwnd
)
2521 Lisp_Object keylist
;
2523 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2525 Lisp_Object key
= XCAR (keylist
);
2527 if (!INTEGERP (key
))
2530 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
2534 /* Main message dispatch loop. */
2537 w32_msg_pump (deferred_msg
* msg_buf
)
2543 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
2545 while (GetMessage (&msg
, NULL
, 0, 0))
2547 if (msg
.hwnd
== NULL
)
2549 switch (msg
.message
)
2552 /* Produced by complete_deferred_msg; just ignore. */
2554 case WM_EMACS_CREATEWINDOW
:
2555 /* Initialize COM for this window. Even though we don't use it,
2556 some third party shell extensions can cause it to be used in
2557 system dialogs, which causes a crash if it is not initialized.
2558 This is a known bug in Windows, which was fixed long ago, but
2559 the patch for XP is not publically available until XP SP3,
2560 and older versions will never be patched. */
2561 CoInitialize (NULL
);
2562 w32_createwindow ((struct frame
*) msg
.wParam
);
2563 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2566 case WM_EMACS_SETLOCALE
:
2567 SetThreadLocale (msg
.wParam
);
2568 /* Reply is not expected. */
2570 case WM_EMACS_SETKEYBOARDLAYOUT
:
2571 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
2572 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2576 case WM_EMACS_REGISTER_HOT_KEY
:
2577 focus_window
= GetFocus ();
2578 if (focus_window
!= NULL
)
2579 RegisterHotKey (focus_window
,
2580 RAW_HOTKEY_ID (msg
.wParam
),
2581 RAW_HOTKEY_MODIFIERS (msg
.wParam
),
2582 RAW_HOTKEY_VK_CODE (msg
.wParam
));
2583 /* Reply is not expected. */
2585 case WM_EMACS_UNREGISTER_HOT_KEY
:
2586 focus_window
= GetFocus ();
2587 if (focus_window
!= NULL
)
2588 UnregisterHotKey (focus_window
, RAW_HOTKEY_ID (msg
.wParam
));
2589 /* Mark item as erased. NB: this code must be
2590 thread-safe. The next line is okay because the cons
2591 cell is never made into garbage and is not relocated by
2593 XSETCAR ((Lisp_Object
) ((EMACS_INT
) msg
.lParam
), Qnil
);
2594 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2597 case WM_EMACS_TOGGLE_LOCK_KEY
:
2599 int vk_code
= (int) msg
.wParam
;
2600 int cur_state
= (GetKeyState (vk_code
) & 1);
2601 Lisp_Object new_state
= (Lisp_Object
) ((EMACS_INT
) msg
.lParam
);
2603 /* NB: This code must be thread-safe. It is safe to
2604 call NILP because symbols are not relocated by GC,
2605 and pointer here is not touched by GC (so the markbit
2606 can't be set). Numbers are safe because they are
2607 immediate values. */
2608 if (NILP (new_state
)
2609 || (NUMBERP (new_state
)
2610 && ((XUINT (new_state
)) & 1) != cur_state
))
2612 one_w32_display_info
.faked_key
= vk_code
;
2614 keybd_event ((BYTE
) vk_code
,
2615 (BYTE
) MapVirtualKey (vk_code
, 0),
2616 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2617 keybd_event ((BYTE
) vk_code
,
2618 (BYTE
) MapVirtualKey (vk_code
, 0),
2619 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2620 keybd_event ((BYTE
) vk_code
,
2621 (BYTE
) MapVirtualKey (vk_code
, 0),
2622 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2623 cur_state
= !cur_state
;
2625 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2631 /* Broadcast messages make it here, so you need to be looking
2632 for something in particular for this to be useful. */
2634 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
2640 DispatchMessage (&msg
);
2643 /* Exit nested loop when our deferred message has completed. */
2644 if (msg_buf
->completed
)
2649 deferred_msg
* deferred_msg_head
;
2651 static deferred_msg
*
2652 find_deferred_msg (HWND hwnd
, UINT msg
)
2654 deferred_msg
* item
;
2656 /* Don't actually need synchronization for read access, since
2657 modification of single pointer is always atomic. */
2658 /* enter_crit (); */
2660 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2661 if (item
->w32msg
.msg
.hwnd
== hwnd
2662 && item
->w32msg
.msg
.message
== msg
)
2665 /* leave_crit (); */
2671 send_deferred_msg (deferred_msg
* msg_buf
,
2677 /* Only input thread can send deferred messages. */
2678 if (GetCurrentThreadId () != dwWindowsThreadId
)
2681 /* It is an error to send a message that is already deferred. */
2682 if (find_deferred_msg (hwnd
, msg
) != NULL
)
2685 /* Enforced synchronization is not needed because this is the only
2686 function that alters deferred_msg_head, and the following critical
2687 section is guaranteed to only be serially reentered (since only the
2688 input thread can call us). */
2690 /* enter_crit (); */
2692 msg_buf
->completed
= 0;
2693 msg_buf
->next
= deferred_msg_head
;
2694 deferred_msg_head
= msg_buf
;
2695 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
2697 /* leave_crit (); */
2699 /* Start a new nested message loop to process other messages until
2700 this one is completed. */
2701 w32_msg_pump (msg_buf
);
2703 deferred_msg_head
= msg_buf
->next
;
2705 return msg_buf
->result
;
2709 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
2711 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
2713 if (msg_buf
== NULL
)
2714 /* Message may have been cancelled, so don't abort. */
2717 msg_buf
->result
= result
;
2718 msg_buf
->completed
= 1;
2720 /* Ensure input thread is woken so it notices the completion. */
2721 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2725 cancel_all_deferred_msgs ()
2727 deferred_msg
* item
;
2729 /* Don't actually need synchronization for read access, since
2730 modification of single pointer is always atomic. */
2731 /* enter_crit (); */
2733 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2736 item
->completed
= 1;
2739 /* leave_crit (); */
2741 /* Ensure input thread is woken so it notices the completion. */
2742 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2746 w32_msg_worker (void *arg
)
2749 deferred_msg dummy_buf
;
2751 /* Ensure our message queue is created */
2753 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2755 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2758 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
2759 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
2760 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
2762 /* This is the initial message loop which should only exit when the
2763 application quits. */
2764 w32_msg_pump (&dummy_buf
);
2770 signal_user_input ()
2772 /* Interrupt any lisp that wants to be interrupted by input. */
2773 if (!NILP (Vthrow_on_input
))
2775 Vquit_flag
= Vthrow_on_input
;
2776 /* If we're inside a function that wants immediate quits,
2778 if (immediate_quit
&& NILP (Vinhibit_quit
))
2788 post_character_message (hwnd
, msg
, wParam
, lParam
, modifiers
)
2798 wmsg
.dwModifiers
= modifiers
;
2800 /* Detect quit_char and set quit-flag directly. Note that we
2801 still need to post a message to ensure the main thread will be
2802 woken up if blocked in sys_select, but we do NOT want to post
2803 the quit_char message itself (because it will usually be as if
2804 the user had typed quit_char twice). Instead, we post a dummy
2805 message that has no particular effect. */
2808 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
2809 c
= make_ctrl_char (c
) & 0377;
2811 || (wmsg
.dwModifiers
== 0 &&
2812 w32_quit_key
&& wParam
== w32_quit_key
))
2816 /* The choice of message is somewhat arbitrary, as long as
2817 the main thread handler just ignores it. */
2820 /* Interrupt any blocking system calls. */
2823 /* As a safety precaution, forcibly complete any deferred
2824 messages. This is a kludge, but I don't see any particularly
2825 clean way to handle the situation where a deferred message is
2826 "dropped" in the lisp thread, and will thus never be
2827 completed, eg. by the user trying to activate the menubar
2828 when the lisp thread is busy, and then typing C-g when the
2829 menubar doesn't open promptly (with the result that the
2830 menubar never responds at all because the deferred
2831 WM_INITMENU message is never completed). Another problem
2832 situation is when the lisp thread calls SendMessage (to send
2833 a window manager command) when a message has been deferred;
2834 the lisp thread gets blocked indefinitely waiting for the
2835 deferred message to be completed, which itself is waiting for
2836 the lisp thread to respond.
2838 Note that we don't want to block the input thread waiting for
2839 a reponse from the lisp thread (although that would at least
2840 solve the deadlock problem above), because we want to be able
2841 to receive C-g to interrupt the lisp thread. */
2842 cancel_all_deferred_msgs ();
2845 signal_user_input ();
2848 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2851 /* Main window procedure */
2854 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
2861 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2863 int windows_translate
;
2866 /* Note that it is okay to call x_window_to_frame, even though we are
2867 not running in the main lisp thread, because frame deletion
2868 requires the lisp thread to synchronize with this thread. Thus, if
2869 a frame struct is returned, it can be used without concern that the
2870 lisp thread might make it disappear while we are using it.
2872 NB. Walking the frame list in this thread is safe (as long as
2873 writes of Lisp_Object slots are atomic, which they are on Windows).
2874 Although delete-frame can destructively modify the frame list while
2875 we are walking it, a garbage collection cannot occur until after
2876 delete-frame has synchronized with this thread.
2878 It is also safe to use functions that make GDI calls, such as
2879 w32_clear_rect, because these functions must obtain a DC handle
2880 from the frame struct using get_frame_dc which is thread-aware. */
2885 f
= x_window_to_frame (dpyinfo
, hwnd
);
2888 HDC hdc
= get_frame_dc (f
);
2889 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
2890 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
2891 release_frame_dc (f
, hdc
);
2893 #if defined (W32_DEBUG_DISPLAY)
2894 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2896 wmsg
.rect
.left
, wmsg
.rect
.top
,
2897 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2898 #endif /* W32_DEBUG_DISPLAY */
2901 case WM_PALETTECHANGED
:
2902 /* ignore our own changes */
2903 if ((HWND
)wParam
!= hwnd
)
2905 f
= x_window_to_frame (dpyinfo
, hwnd
);
2907 /* get_frame_dc will realize our palette and force all
2908 frames to be redrawn if needed. */
2909 release_frame_dc (f
, get_frame_dc (f
));
2914 PAINTSTRUCT paintStruct
;
2916 bzero (&update_rect
, sizeof (update_rect
));
2918 f
= x_window_to_frame (dpyinfo
, hwnd
);
2921 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd
));
2925 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2926 fails. Apparently this can happen under some
2928 if (GetUpdateRect (hwnd
, &update_rect
, FALSE
) || !w32_strict_painting
)
2931 BeginPaint (hwnd
, &paintStruct
);
2933 /* The rectangles returned by GetUpdateRect and BeginPaint
2934 do not always match. Play it safe by assuming both areas
2936 UnionRect (&(wmsg
.rect
), &update_rect
, &(paintStruct
.rcPaint
));
2938 #if defined (W32_DEBUG_DISPLAY)
2939 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2941 wmsg
.rect
.left
, wmsg
.rect
.top
,
2942 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2943 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2944 update_rect
.left
, update_rect
.top
,
2945 update_rect
.right
, update_rect
.bottom
));
2947 EndPaint (hwnd
, &paintStruct
);
2950 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2955 /* If GetUpdateRect returns 0 (meaning there is no update
2956 region), assume the whole window needs to be repainted. */
2957 GetClientRect (hwnd
, &wmsg
.rect
);
2958 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2962 case WM_INPUTLANGCHANGE
:
2963 /* Inform lisp thread of keyboard layout changes. */
2964 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2966 /* Clear dead keys in the keyboard state; for simplicity only
2967 preserve modifier key states. */
2972 GetKeyboardState (keystate
);
2973 for (i
= 0; i
< 256; i
++)
2990 SetKeyboardState (keystate
);
2995 /* Synchronize hot keys with normal input. */
2996 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
3001 record_keyup (wParam
, lParam
);
3006 /* Ignore keystrokes we fake ourself; see below. */
3007 if (dpyinfo
->faked_key
== wParam
)
3009 dpyinfo
->faked_key
= 0;
3010 /* Make sure TranslateMessage sees them though (as long as
3011 they don't produce WM_CHAR messages). This ensures that
3012 indicator lights are toggled promptly on Windows 9x, for
3014 if (wParam
< 256 && lispy_function_keys
[wParam
])
3016 windows_translate
= 1;
3022 /* Synchronize modifiers with current keystroke. */
3024 record_keydown (wParam
, lParam
);
3025 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
3027 windows_translate
= 0;
3032 if (NILP (Vw32_pass_lwindow_to_system
))
3034 /* Prevent system from acting on keyup (which opens the
3035 Start menu if no other key was pressed) by simulating a
3036 press of Space which we will ignore. */
3037 if (GetAsyncKeyState (wParam
) & 1)
3039 if (NUMBERP (Vw32_phantom_key_code
))
3040 key
= XUINT (Vw32_phantom_key_code
) & 255;
3043 dpyinfo
->faked_key
= key
;
3044 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3047 if (!NILP (Vw32_lwindow_modifier
))
3051 if (NILP (Vw32_pass_rwindow_to_system
))
3053 if (GetAsyncKeyState (wParam
) & 1)
3055 if (NUMBERP (Vw32_phantom_key_code
))
3056 key
= XUINT (Vw32_phantom_key_code
) & 255;
3059 dpyinfo
->faked_key
= key
;
3060 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3063 if (!NILP (Vw32_rwindow_modifier
))
3067 if (!NILP (Vw32_apps_modifier
))
3071 if (NILP (Vw32_pass_alt_to_system
))
3072 /* Prevent DefWindowProc from activating the menu bar if an
3073 Alt key is pressed and released by itself. */
3075 windows_translate
= 1;
3078 /* Decide whether to treat as modifier or function key. */
3079 if (NILP (Vw32_enable_caps_lock
))
3080 goto disable_lock_key
;
3081 windows_translate
= 1;
3084 /* Decide whether to treat as modifier or function key. */
3085 if (NILP (Vw32_enable_num_lock
))
3086 goto disable_lock_key
;
3087 windows_translate
= 1;
3090 /* Decide whether to treat as modifier or function key. */
3091 if (NILP (Vw32_scroll_lock_modifier
))
3092 goto disable_lock_key
;
3093 windows_translate
= 1;
3096 /* Ensure the appropriate lock key state (and indicator light)
3097 remains in the same state. We do this by faking another
3098 press of the relevant key. Apparently, this really is the
3099 only way to toggle the state of the indicator lights. */
3100 dpyinfo
->faked_key
= wParam
;
3101 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3102 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3103 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3104 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3105 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3106 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3107 /* Ensure indicator lights are updated promptly on Windows 9x
3108 (TranslateMessage apparently does this), after forwarding
3110 post_character_message (hwnd
, msg
, wParam
, lParam
,
3111 w32_get_key_modifiers (wParam
, lParam
));
3112 windows_translate
= 1;
3116 case VK_PROCESSKEY
: /* Generated by IME. */
3117 windows_translate
= 1;
3120 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3121 which is confusing for purposes of key binding; convert
3122 VK_CANCEL events into VK_PAUSE events. */
3126 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3127 for purposes of key binding; convert these back into
3128 VK_NUMLOCK events, at least when we want to see NumLock key
3129 presses. (Note that there is never any possibility that
3130 VK_PAUSE with Ctrl really is C-Pause as per above.) */
3131 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
3132 wParam
= VK_NUMLOCK
;
3135 /* If not defined as a function key, change it to a WM_CHAR message. */
3136 if (wParam
> 255 || !lispy_function_keys
[wParam
])
3138 DWORD modifiers
= construct_console_modifiers ();
3140 if (!NILP (Vw32_recognize_altgr
)
3141 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
3143 /* Always let TranslateMessage handle AltGr key chords;
3144 for some reason, ToAscii doesn't always process AltGr
3145 chords correctly. */
3146 windows_translate
= 1;
3148 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
3150 /* Handle key chords including any modifiers other
3151 than shift directly, in order to preserve as much
3152 modifier information as possible. */
3153 if ('A' <= wParam
&& wParam
<= 'Z')
3155 /* Don't translate modified alphabetic keystrokes,
3156 so the user doesn't need to constantly switch
3157 layout to type control or meta keystrokes when
3158 the normal layout translates alphabetic
3159 characters to non-ascii characters. */
3160 if (!modifier_set (VK_SHIFT
))
3161 wParam
+= ('a' - 'A');
3166 /* Try to handle other keystrokes by determining the
3167 base character (ie. translating the base key plus
3171 KEY_EVENT_RECORD key
;
3173 key
.bKeyDown
= TRUE
;
3174 key
.wRepeatCount
= 1;
3175 key
.wVirtualKeyCode
= wParam
;
3176 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3177 key
.uChar
.AsciiChar
= 0;
3178 key
.dwControlKeyState
= modifiers
;
3180 add
= w32_kbd_patch_key (&key
);
3181 /* 0 means an unrecognised keycode, negative means
3182 dead key. Ignore both. */
3185 /* Forward asciified character sequence. */
3186 post_character_message
3188 (unsigned char) key
.uChar
.AsciiChar
, lParam
,
3189 w32_get_key_modifiers (wParam
, lParam
));
3190 w32_kbd_patch_key (&key
);
3197 /* Let TranslateMessage handle everything else. */
3198 windows_translate
= 1;
3204 if (windows_translate
)
3206 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3207 windows_msg
.time
= GetMessageTime ();
3208 TranslateMessage (&windows_msg
);
3216 post_character_message (hwnd
, msg
, wParam
, lParam
,
3217 w32_get_key_modifiers (wParam
, lParam
));
3221 /* WM_UNICHAR looks promising from the docs, but the exact
3222 circumstances in which TranslateMessage sends it is one of those
3223 Microsoft secret API things that EU and US courts are supposed
3224 to have put a stop to already. Spy++ shows it being sent to Notepad
3225 and other MS apps, but never to Emacs.
3227 Some third party IMEs send it in accordance with the official
3228 documentation though, so handle it here.
3230 UNICODE_NOCHAR is used to test for support for this message.
3231 TRUE indicates that the message is supported. */
3232 if (wParam
== UNICODE_NOCHAR
)
3237 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3238 signal_user_input ();
3239 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3244 /* If we can't get the IME result as unicode, use default processing,
3245 which will at least allow characters decodable in the system locale
3247 if (!get_composition_string_fn
)
3250 else if (!ignore_ime_char
)
3255 HIMC context
= get_ime_context_fn (hwnd
);
3256 wmsg
.dwModifiers
= w32_get_key_modifiers (wParam
, lParam
);
3257 /* Get buffer size. */
3258 size
= get_composition_string_fn (context
, GCS_RESULTSTR
, buffer
, 0);
3259 buffer
= alloca(size
);
3260 size
= get_composition_string_fn (context
, GCS_RESULTSTR
,
3262 signal_user_input ();
3263 for (i
= 0; i
< size
/ sizeof (wchar_t); i
++)
3265 my_post_msg (&wmsg
, hwnd
, WM_UNICHAR
, (WPARAM
) buffer
[i
],
3268 /* We output the whole string above, so ignore following ones
3269 until we are notified of the end of composition. */
3270 ignore_ime_char
= 1;
3274 case WM_IME_ENDCOMPOSITION
:
3275 ignore_ime_char
= 0;
3278 /* Simulate middle mouse button events when left and right buttons
3279 are used together, but only if user has two button mouse. */
3280 case WM_LBUTTONDOWN
:
3281 case WM_RBUTTONDOWN
:
3282 if (w32_num_mouse_buttons
> 2)
3283 goto handle_plain_button
;
3286 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3287 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3289 if (button_state
& this)
3292 if (button_state
== 0)
3295 button_state
|= this;
3297 if (button_state
& other
)
3299 if (mouse_button_timer
)
3301 KillTimer (hwnd
, mouse_button_timer
);
3302 mouse_button_timer
= 0;
3304 /* Generate middle mouse event instead. */
3305 msg
= WM_MBUTTONDOWN
;
3306 button_state
|= MMOUSE
;
3308 else if (button_state
& MMOUSE
)
3310 /* Ignore button event if we've already generated a
3311 middle mouse down event. This happens if the
3312 user releases and press one of the two buttons
3313 after we've faked a middle mouse event. */
3318 /* Flush out saved message. */
3319 post_msg (&saved_mouse_button_msg
);
3321 wmsg
.dwModifiers
= w32_get_modifiers ();
3322 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3323 signal_user_input ();
3325 /* Clear message buffer. */
3326 saved_mouse_button_msg
.msg
.hwnd
= 0;
3330 /* Hold onto message for now. */
3331 mouse_button_timer
=
3332 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
3333 w32_mouse_button_tolerance
, NULL
);
3334 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3335 saved_mouse_button_msg
.msg
.message
= msg
;
3336 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3337 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3338 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3339 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3346 if (w32_num_mouse_buttons
> 2)
3347 goto handle_plain_button
;
3350 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3351 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3353 if ((button_state
& this) == 0)
3356 button_state
&= ~this;
3358 if (button_state
& MMOUSE
)
3360 /* Only generate event when second button is released. */
3361 if ((button_state
& other
) == 0)
3364 button_state
&= ~MMOUSE
;
3366 if (button_state
) abort ();
3373 /* Flush out saved message if necessary. */
3374 if (saved_mouse_button_msg
.msg
.hwnd
)
3376 post_msg (&saved_mouse_button_msg
);
3379 wmsg
.dwModifiers
= w32_get_modifiers ();
3380 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3381 signal_user_input ();
3383 /* Always clear message buffer and cancel timer. */
3384 saved_mouse_button_msg
.msg
.hwnd
= 0;
3385 KillTimer (hwnd
, mouse_button_timer
);
3386 mouse_button_timer
= 0;
3388 if (button_state
== 0)
3393 case WM_XBUTTONDOWN
:
3395 if (w32_pass_extra_mouse_buttons_to_system
)
3397 /* else fall through and process them. */
3398 case WM_MBUTTONDOWN
:
3400 handle_plain_button
:
3405 /* Ignore middle and extra buttons as long as the menu is active. */
3406 f
= x_window_to_frame (dpyinfo
, hwnd
);
3407 if (f
&& f
->output_data
.w32
->menubar_active
)
3410 if (parse_button (msg
, HIWORD (wParam
), &button
, &up
))
3412 if (up
) ReleaseCapture ();
3413 else SetCapture (hwnd
);
3414 button
= (button
== 0) ? LMOUSE
:
3415 ((button
== 1) ? MMOUSE
: RMOUSE
);
3417 button_state
&= ~button
;
3419 button_state
|= button
;
3423 wmsg
.dwModifiers
= w32_get_modifiers ();
3424 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3425 signal_user_input ();
3427 /* Need to return true for XBUTTON messages, false for others,
3428 to indicate that we processed the message. */
3429 return (msg
== WM_XBUTTONDOWN
|| msg
== WM_XBUTTONUP
);
3432 /* Ignore mouse movements as long as the menu is active. These
3433 movements are processed by the window manager anyway, and
3434 it's wrong to handle them as if they happened on the
3435 underlying frame. */
3436 f
= x_window_to_frame (dpyinfo
, hwnd
);
3437 if (f
&& f
->output_data
.w32
->menubar_active
)
3440 /* If the mouse has just moved into the frame, start tracking
3441 it, so we will be notified when it leaves the frame. Mouse
3442 tracking only works under W98 and NT4 and later. On earlier
3443 versions, there is no way of telling when the mouse leaves the
3444 frame, so we just have to put up with help-echo and mouse
3445 highlighting remaining while the frame is not active. */
3446 if (track_mouse_event_fn
&& !track_mouse_window
)
3448 TRACKMOUSEEVENT tme
;
3449 tme
.cbSize
= sizeof (tme
);
3450 tme
.dwFlags
= TME_LEAVE
;
3451 tme
.hwndTrack
= hwnd
;
3453 track_mouse_event_fn (&tme
);
3454 track_mouse_window
= hwnd
;
3457 if (w32_mouse_move_interval
<= 0
3458 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3460 wmsg
.dwModifiers
= w32_get_modifiers ();
3461 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3465 /* Hang onto mouse move and scroll messages for a bit, to avoid
3466 sending such events to Emacs faster than it can process them.
3467 If we get more events before the timer from the first message
3468 expires, we just replace the first message. */
3470 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3472 SetTimer (hwnd
, MOUSE_MOVE_ID
,
3473 w32_mouse_move_interval
, NULL
);
3475 /* Hold onto message for now. */
3476 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3477 saved_mouse_move_msg
.msg
.message
= msg
;
3478 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3479 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3480 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3481 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3487 wmsg
.dwModifiers
= w32_get_modifiers ();
3488 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3489 signal_user_input ();
3493 if (w32_pass_multimedia_buttons_to_system
)
3495 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
3496 case WM_MOUSEHWHEEL
:
3497 wmsg
.dwModifiers
= w32_get_modifiers ();
3498 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3499 signal_user_input ();
3500 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3501 handled, to prevent the system trying to handle it by faking
3502 scroll bar events. */
3506 /* Flush out saved messages if necessary. */
3507 if (wParam
== mouse_button_timer
)
3509 if (saved_mouse_button_msg
.msg
.hwnd
)
3511 post_msg (&saved_mouse_button_msg
);
3512 signal_user_input ();
3513 saved_mouse_button_msg
.msg
.hwnd
= 0;
3515 KillTimer (hwnd
, mouse_button_timer
);
3516 mouse_button_timer
= 0;
3518 else if (wParam
== mouse_move_timer
)
3520 if (saved_mouse_move_msg
.msg
.hwnd
)
3522 post_msg (&saved_mouse_move_msg
);
3523 saved_mouse_move_msg
.msg
.hwnd
= 0;
3525 KillTimer (hwnd
, mouse_move_timer
);
3526 mouse_move_timer
= 0;
3528 else if (wParam
== menu_free_timer
)
3530 KillTimer (hwnd
, menu_free_timer
);
3531 menu_free_timer
= 0;
3532 f
= x_window_to_frame (dpyinfo
, hwnd
);
3533 /* If a popup menu is active, don't wipe its strings. */
3535 && current_popup_menu
== NULL
)
3537 /* Free memory used by owner-drawn and help-echo strings. */
3538 w32_free_menu_strings (hwnd
);
3539 f
->output_data
.w32
->menubar_active
= 0;
3543 else if (wParam
== hourglass_timer
)
3545 KillTimer (hwnd
, hourglass_timer
);
3546 hourglass_timer
= 0;
3547 show_hourglass (x_window_to_frame (dpyinfo
, hwnd
));
3552 /* Windows doesn't send us focus messages when putting up and
3553 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3554 The only indication we get that something happened is receiving
3555 this message afterwards. So this is a good time to reset our
3556 keyboard modifiers' state. */
3563 /* We must ensure menu bar is fully constructed and up to date
3564 before allowing user interaction with it. To achieve this
3565 we send this message to the lisp thread and wait for a
3566 reply (whose value is not actually needed) to indicate that
3567 the menu bar is now ready for use, so we can now return.
3569 To remain responsive in the meantime, we enter a nested message
3570 loop that can process all other messages.
3572 However, we skip all this if the message results from calling
3573 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3574 thread a message because it is blocked on us at this point. We
3575 set menubar_active before calling TrackPopupMenu to indicate
3576 this (there is no possibility of confusion with real menubar
3579 f
= x_window_to_frame (dpyinfo
, hwnd
);
3581 && (f
->output_data
.w32
->menubar_active
3582 /* We can receive this message even in the absence of a
3583 menubar (ie. when the system menu is activated) - in this
3584 case we do NOT want to forward the message, otherwise it
3585 will cause the menubar to suddenly appear when the user
3586 had requested it to be turned off! */
3587 || f
->output_data
.w32
->menubar_widget
== NULL
))
3591 deferred_msg msg_buf
;
3593 /* Detect if message has already been deferred; in this case
3594 we cannot return any sensible value to ignore this. */
3595 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3600 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3603 case WM_EXITMENULOOP
:
3604 f
= x_window_to_frame (dpyinfo
, hwnd
);
3606 /* If a menu is still active, check again after a short delay,
3607 since Windows often (always?) sends the WM_EXITMENULOOP
3608 before the corresponding WM_COMMAND message.
3609 Don't do this if a popup menu is active, since it is only
3610 menubar menus that require cleaning up in this way.
3612 if (f
&& menubar_in_use
&& current_popup_menu
== NULL
)
3613 menu_free_timer
= SetTimer (hwnd
, MENU_FREE_ID
, MENU_FREE_DELAY
, NULL
);
3615 /* If hourglass cursor should be displayed, display it now. */
3616 if (f
&& f
->output_data
.w32
->hourglass_p
)
3617 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3622 /* Direct handling of help_echo in menus. Should be safe now
3623 that we generate the help_echo by placing a help event in the
3626 HMENU menu
= (HMENU
) lParam
;
3627 UINT menu_item
= (UINT
) LOWORD (wParam
);
3628 UINT flags
= (UINT
) HIWORD (wParam
);
3630 w32_menu_display_help (hwnd
, menu
, menu_item
, flags
);
3634 case WM_MEASUREITEM
:
3635 f
= x_window_to_frame (dpyinfo
, hwnd
);
3638 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3640 if (pMis
->CtlType
== ODT_MENU
)
3642 /* Work out dimensions for popup menu titles. */
3643 char * title
= (char *) pMis
->itemData
;
3644 HDC hdc
= GetDC (hwnd
);
3645 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3646 LOGFONT menu_logfont
;
3650 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3651 menu_logfont
.lfWeight
= FW_BOLD
;
3652 menu_font
= CreateFontIndirect (&menu_logfont
);
3653 old_font
= SelectObject (hdc
, menu_font
);
3655 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3658 if (unicode_append_menu
)
3659 GetTextExtentPoint32W (hdc
, (WCHAR
*) title
,
3660 wcslen ((WCHAR
*) title
),
3663 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3665 pMis
->itemWidth
= size
.cx
;
3666 if (pMis
->itemHeight
< size
.cy
)
3667 pMis
->itemHeight
= size
.cy
;
3670 pMis
->itemWidth
= 0;
3672 SelectObject (hdc
, old_font
);
3673 DeleteObject (menu_font
);
3674 ReleaseDC (hwnd
, hdc
);
3681 f
= x_window_to_frame (dpyinfo
, hwnd
);
3684 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3686 if (pDis
->CtlType
== ODT_MENU
)
3688 /* Draw popup menu title. */
3689 char * title
= (char *) pDis
->itemData
;
3692 HDC hdc
= pDis
->hDC
;
3693 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3694 LOGFONT menu_logfont
;
3697 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3698 menu_logfont
.lfWeight
= FW_BOLD
;
3699 menu_font
= CreateFontIndirect (&menu_logfont
);
3700 old_font
= SelectObject (hdc
, menu_font
);
3702 /* Always draw title as if not selected. */
3703 if (unicode_append_menu
)
3706 + GetSystemMetrics (SM_CXMENUCHECK
),
3708 ETO_OPAQUE
, &pDis
->rcItem
,
3710 wcslen ((WCHAR
*) title
), NULL
);
3714 + GetSystemMetrics (SM_CXMENUCHECK
),
3716 ETO_OPAQUE
, &pDis
->rcItem
,
3717 title
, strlen (title
), NULL
);
3719 SelectObject (hdc
, old_font
);
3720 DeleteObject (menu_font
);
3728 /* Still not right - can't distinguish between clicks in the
3729 client area of the frame from clicks forwarded from the scroll
3730 bars - may have to hook WM_NCHITTEST to remember the mouse
3731 position and then check if it is in the client area ourselves. */
3732 case WM_MOUSEACTIVATE
:
3733 /* Discard the mouse click that activates a frame, allowing the
3734 user to click anywhere without changing point (or worse!).
3735 Don't eat mouse clicks on scrollbars though!! */
3736 if (LOWORD (lParam
) == HTCLIENT
)
3737 return MA_ACTIVATEANDEAT
;
3742 /* No longer tracking mouse. */
3743 track_mouse_window
= NULL
;
3745 case WM_ACTIVATEAPP
:
3747 case WM_WINDOWPOSCHANGED
:
3749 /* Inform lisp thread that a frame might have just been obscured
3750 or exposed, so should recheck visibility of all frames. */
3751 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3755 dpyinfo
->faked_key
= 0;
3757 register_hot_keys (hwnd
);
3760 unregister_hot_keys (hwnd
);
3763 /* Relinquish the system caret. */
3764 if (w32_system_caret_hwnd
)
3766 w32_visible_system_caret_hwnd
= NULL
;
3767 w32_system_caret_hwnd
= NULL
;
3773 f
= x_window_to_frame (dpyinfo
, hwnd
);
3774 if (f
&& HIWORD (wParam
) == 0)
3776 if (menu_free_timer
)
3778 KillTimer (hwnd
, menu_free_timer
);
3779 menu_free_timer
= 0;
3785 wmsg
.dwModifiers
= w32_get_modifiers ();
3786 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3794 wmsg
.dwModifiers
= w32_get_modifiers ();
3795 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3798 case WM_WINDOWPOSCHANGING
:
3799 /* Don't restrict the sizing of tip frames. */
3800 if (hwnd
== tip_window
)
3804 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3806 wp
.length
= sizeof (WINDOWPLACEMENT
);
3807 GetWindowPlacement (hwnd
, &wp
);
3809 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
3816 DWORD internal_border
;
3817 DWORD scrollbar_extra
;
3820 wp
.length
= sizeof (wp
);
3821 GetWindowRect (hwnd
, &wr
);
3825 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3826 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3827 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3828 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
3832 memset (&rect
, 0, sizeof (rect
));
3833 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3834 GetMenu (hwnd
) != NULL
);
3836 /* Force width and height of client area to be exact
3837 multiples of the character cell dimensions. */
3838 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3839 - 2 * internal_border
- scrollbar_extra
)
3841 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3842 - 2 * internal_border
)
3847 /* For right/bottom sizing we can just fix the sizes.
3848 However for top/left sizing we will need to fix the X
3849 and Y positions as well. */
3851 int cx_mintrack
= GetSystemMetrics (SM_CXMINTRACK
);
3852 int cy_mintrack
= GetSystemMetrics (SM_CYMINTRACK
);
3854 lppos
->cx
= max (lppos
->cx
- wdiff
, cx_mintrack
);
3855 lppos
->cy
= max (lppos
->cy
- hdiff
, cy_mintrack
);
3857 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3858 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3860 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3867 lppos
->flags
|= SWP_NOMOVE
;
3878 case WM_GETMINMAXINFO
:
3879 /* Hack to allow resizing the Emacs frame above the screen size.
3880 Note that Windows 9x limits coordinates to 16-bits. */
3881 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.x
= 32767;
3882 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.y
= 32767;
3886 if (LOWORD (lParam
) == HTCLIENT
)
3888 f
= x_window_to_frame (dpyinfo
, hwnd
);
3889 if (f
->output_data
.w32
->hourglass_p
&& !menubar_in_use
3890 && !current_popup_menu
)
3891 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
3893 SetCursor (f
->output_data
.w32
->current_cursor
);
3898 case WM_EMACS_SETCURSOR
:
3900 Cursor cursor
= (Cursor
) wParam
;
3901 f
= x_window_to_frame (dpyinfo
, hwnd
);
3904 f
->output_data
.w32
->current_cursor
= cursor
;
3905 if (!f
->output_data
.w32
->hourglass_p
)
3911 case WM_EMACS_CREATESCROLLBAR
:
3912 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
3913 (struct scroll_bar
*) lParam
);
3915 case WM_EMACS_SHOWWINDOW
:
3916 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
3918 case WM_EMACS_SETFOREGROUND
:
3920 HWND foreground_window
;
3921 DWORD foreground_thread
, retval
;
3923 /* On NT 5.0, and apparently Windows 98, it is necessary to
3924 attach to the thread that currently has focus in order to
3925 pull the focus away from it. */
3926 foreground_window
= GetForegroundWindow ();
3927 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
3928 if (!foreground_window
3929 || foreground_thread
== GetCurrentThreadId ()
3930 || !AttachThreadInput (GetCurrentThreadId (),
3931 foreground_thread
, TRUE
))
3932 foreground_thread
= 0;
3934 retval
= SetForegroundWindow ((HWND
) wParam
);
3936 /* Detach from the previous foreground thread. */
3937 if (foreground_thread
)
3938 AttachThreadInput (GetCurrentThreadId (),
3939 foreground_thread
, FALSE
);
3944 case WM_EMACS_SETWINDOWPOS
:
3946 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
3947 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
3948 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
3951 case WM_EMACS_DESTROYWINDOW
:
3952 DragAcceptFiles ((HWND
) wParam
, FALSE
);
3953 return DestroyWindow ((HWND
) wParam
);
3955 case WM_EMACS_HIDE_CARET
:
3956 return HideCaret (hwnd
);
3958 case WM_EMACS_SHOW_CARET
:
3959 return ShowCaret (hwnd
);
3961 case WM_EMACS_DESTROY_CARET
:
3962 w32_system_caret_hwnd
= NULL
;
3963 w32_visible_system_caret_hwnd
= NULL
;
3964 return DestroyCaret ();
3966 case WM_EMACS_TRACK_CARET
:
3967 /* If there is currently no system caret, create one. */
3968 if (w32_system_caret_hwnd
== NULL
)
3970 /* Use the default caret width, and avoid changing it
3971 unneccesarily, as it confuses screen reader software. */
3972 w32_system_caret_hwnd
= hwnd
;
3973 CreateCaret (hwnd
, NULL
, 0,
3974 w32_system_caret_height
);
3977 if (!SetCaretPos (w32_system_caret_x
, w32_system_caret_y
))
3979 /* Ensure visible caret gets turned on when requested. */
3980 else if (w32_use_visible_system_caret
3981 && w32_visible_system_caret_hwnd
!= hwnd
)
3983 w32_visible_system_caret_hwnd
= hwnd
;
3984 return ShowCaret (hwnd
);
3986 /* Ensure visible caret gets turned off when requested. */
3987 else if (!w32_use_visible_system_caret
3988 && w32_visible_system_caret_hwnd
)
3990 w32_visible_system_caret_hwnd
= NULL
;
3991 return HideCaret (hwnd
);
3996 case WM_EMACS_TRACKPOPUPMENU
:
4001 pos
= (POINT
*)lParam
;
4002 flags
= TPM_CENTERALIGN
;
4003 if (button_state
& LMOUSE
)
4004 flags
|= TPM_LEFTBUTTON
;
4005 else if (button_state
& RMOUSE
)
4006 flags
|= TPM_RIGHTBUTTON
;
4008 /* Remember we did a SetCapture on the initial mouse down event,
4009 so for safety, we make sure the capture is cancelled now. */
4013 /* Use menubar_active to indicate that WM_INITMENU is from
4014 TrackPopupMenu below, and should be ignored. */
4015 f
= x_window_to_frame (dpyinfo
, hwnd
);
4017 f
->output_data
.w32
->menubar_active
= 1;
4019 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
4023 /* Eat any mouse messages during popupmenu */
4024 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
4026 /* Get the menu selection, if any */
4027 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
4029 retval
= LOWORD (amsg
.wParam
);
4045 /* Check for messages registered at runtime. */
4046 if (msg
== msh_mousewheel
)
4048 wmsg
.dwModifiers
= w32_get_modifiers ();
4049 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4050 signal_user_input ();
4055 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
4059 /* The most common default return code for handled messages is 0. */
4064 my_create_window (f
)
4069 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
4071 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4075 /* Create a tooltip window. Unlike my_create_window, we do not do this
4076 indirectly via the Window thread, as we do not need to process Window
4077 messages for the tooltip. Creating tooltips indirectly also creates
4078 deadlocks when tooltips are created for menu items. */
4080 my_create_tip_window (f
)
4085 rect
.left
= rect
.top
= 0;
4086 rect
.right
= FRAME_PIXEL_WIDTH (f
);
4087 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
4089 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
4090 FRAME_EXTERNAL_MENU_BAR (f
));
4092 tip_window
= FRAME_W32_WINDOW (f
)
4093 = CreateWindow (EMACS_CLASS
,
4095 f
->output_data
.w32
->dwStyle
,
4098 rect
.right
- rect
.left
,
4099 rect
.bottom
- rect
.top
,
4100 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
4107 SetWindowLong (tip_window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
4108 SetWindowLong (tip_window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
4109 SetWindowLong (tip_window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
4110 SetWindowLong (tip_window
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
4112 /* Tip frames have no scrollbars. */
4113 SetWindowLong (tip_window
, WND_SCROLLBAR_INDEX
, 0);
4115 /* Do this to discard the default setting specified by our parent. */
4116 ShowWindow (tip_window
, SW_HIDE
);
4121 /* Create and set up the w32 window for frame F. */
4124 w32_window (f
, window_prompting
, minibuffer_only
)
4126 long window_prompting
;
4127 int minibuffer_only
;
4131 /* Use the resource name as the top-level window name
4132 for looking up resources. Make a non-Lisp copy
4133 for the window manager, so GC relocation won't bother it.
4135 Elsewhere we specify the window name for the window manager. */
4138 char *str
= (char *) SDATA (Vx_resource_name
);
4139 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4140 strcpy (f
->namebuf
, str
);
4143 my_create_window (f
);
4145 validate_x_resource_name ();
4147 /* x_set_name normally ignores requests to set the name if the
4148 requested name is the same as the current name. This is the one
4149 place where that assumption isn't correct; f->name is set, but
4150 the server hasn't been told. */
4153 int explicit = f
->explicit_name
;
4155 f
->explicit_name
= 0;
4158 x_set_name (f
, name
, explicit);
4163 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4164 initialize_frame_menubar (f
);
4166 if (FRAME_W32_WINDOW (f
) == 0)
4167 error ("Unable to create window");
4170 /* Handle the icon stuff for this window. Perhaps later we might
4171 want an x_set_icon_position which can be called interactively as
4179 Lisp_Object icon_x
, icon_y
;
4181 /* Set the position of the icon. Note that Windows 95 groups all
4182 icons in the tray. */
4183 icon_x
= w32_get_arg (parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4184 icon_y
= w32_get_arg (parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4185 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4187 CHECK_NUMBER (icon_x
);
4188 CHECK_NUMBER (icon_y
);
4190 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4191 error ("Both left and top icon corners of icon must be specified");
4195 if (! EQ (icon_x
, Qunbound
))
4196 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4199 /* Start up iconic or window? */
4200 x_wm_set_window_state
4201 (f
, (EQ (w32_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4205 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4218 XGCValues gc_values
;
4222 /* Create the GC's of this frame.
4223 Note that many default values are used. */
4226 gc_values
.font
= FRAME_FONT (f
);
4228 /* Cursor has cursor-color background, background-color foreground. */
4229 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
4230 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
4231 f
->output_data
.w32
->cursor_gc
4232 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
4233 (GCFont
| GCForeground
| GCBackground
),
4237 f
->output_data
.w32
->white_relief
.gc
= 0;
4238 f
->output_data
.w32
->black_relief
.gc
= 0;
4244 /* Handler for signals raised during x_create_frame and
4245 x_create_top_frame. FRAME is the frame which is partially
4249 unwind_create_frame (frame
)
4252 struct frame
*f
= XFRAME (frame
);
4254 /* If frame is ``official'', nothing to do. */
4255 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4258 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4261 x_free_frame_resources (f
);
4263 /* Check that reference counts are indeed correct. */
4264 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4265 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4273 #ifdef USE_FONT_BACKEND
4275 x_default_font_parameter (f
, parms
)
4279 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4280 Lisp_Object font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font",
4283 if (!STRINGP (font
))
4286 static char *names
[]
4287 = { "Courier New-10",
4288 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4289 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4293 for (i
= 0; names
[i
]; i
++)
4295 font
= font_open_by_name (f
, names
[i
]);
4300 error ("No suitable font was found");
4302 x_default_parameter (f
, parms
, Qfont
, font
, "font", "Font", RES_TYPE_STRING
);
4306 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4308 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
4309 Return an Emacs frame object.
4310 PARAMETERS is an alist of frame parameters.
4311 If the parameters specify that the frame should not have a minibuffer,
4312 and do not specify a specific minibuffer window to use,
4313 then `default-minibuffer-frame' must be a frame whose minibuffer can
4314 be shared by the new frame.
4316 This function is an internal primitive--use `make-frame' instead. */)
4318 Lisp_Object parameters
;
4321 Lisp_Object frame
, tem
;
4323 int minibuffer_only
= 0;
4324 long window_prompting
= 0;
4326 int count
= SPECPDL_INDEX ();
4327 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4328 Lisp_Object display
;
4329 struct w32_display_info
*dpyinfo
= NULL
;
4335 /* Make copy of frame parameters because the original is in pure
4337 parameters
= Fcopy_alist (parameters
);
4339 /* Use this general default value to start with
4340 until we know if this frame has a specified name. */
4341 Vx_resource_name
= Vinvocation_name
;
4343 display
= w32_get_arg (parameters
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4344 if (EQ (display
, Qunbound
))
4346 dpyinfo
= check_x_display_info (display
);
4348 kb
= dpyinfo
->terminal
->kboard
;
4350 kb
= &the_only_kboard
;
4353 name
= w32_get_arg (parameters
, Qname
, "name", "Name", RES_TYPE_STRING
);
4355 && ! EQ (name
, Qunbound
)
4357 error ("Invalid frame name--not a string or nil");
4360 Vx_resource_name
= name
;
4362 /* See if parent window is specified. */
4363 parent
= w32_get_arg (parameters
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4364 if (EQ (parent
, Qunbound
))
4366 if (! NILP (parent
))
4367 CHECK_NUMBER (parent
);
4369 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4370 /* No need to protect DISPLAY because that's not used after passing
4371 it to make_frame_without_minibuffer. */
4373 GCPRO4 (parameters
, parent
, name
, frame
);
4374 tem
= w32_get_arg (parameters
, Qminibuffer
, "minibuffer", "Minibuffer",
4376 if (EQ (tem
, Qnone
) || NILP (tem
))
4377 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4378 else if (EQ (tem
, Qonly
))
4380 f
= make_minibuffer_frame ();
4381 minibuffer_only
= 1;
4383 else if (WINDOWP (tem
))
4384 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4388 XSETFRAME (frame
, f
);
4390 /* Note that Windows does support scroll bars. */
4391 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4393 /* By default, make scrollbars the system standard width. */
4394 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
4396 f
->terminal
= dpyinfo
->terminal
;
4397 f
->terminal
->reference_count
++;
4399 f
->output_method
= output_w32
;
4400 f
->output_data
.w32
=
4401 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4402 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
4403 FRAME_FONTSET (f
) = -1;
4404 record_unwind_protect (unwind_create_frame
, frame
);
4407 = w32_get_arg (parameters
, Qicon_name
, "iconName", "Title", RES_TYPE_STRING
);
4408 if (! STRINGP (f
->icon_name
))
4409 f
->icon_name
= Qnil
;
4411 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4413 FRAME_KBOARD (f
) = kb
;
4416 /* Specify the parent under which to make this window. */
4420 f
->output_data
.w32
->parent_desc
= (Window
) XFASTINT (parent
);
4421 f
->output_data
.w32
->explicit_parent
= 1;
4425 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4426 f
->output_data
.w32
->explicit_parent
= 0;
4429 /* Set the name; the functions to which we pass f expect the name to
4431 if (EQ (name
, Qunbound
) || NILP (name
))
4433 f
->name
= build_string (dpyinfo
->w32_id_name
);
4434 f
->explicit_name
= 0;
4439 f
->explicit_name
= 1;
4440 /* use the frame's title when getting resources for this frame. */
4441 specbind (Qx_resource_name
, name
);
4444 f
->resx
= dpyinfo
->resx
;
4445 f
->resy
= dpyinfo
->resy
;
4447 #ifdef USE_FONT_BACKEND
4448 if (enable_font_backend
)
4450 /* Perhaps, we must allow frame parameter, say `font-backend',
4451 to specify which font backends to use. */
4452 if (uniscribe_available
)
4453 register_font_driver (&uniscribe_font_driver
, f
);
4454 register_font_driver (&w32font_driver
, f
);
4456 x_default_parameter (f
, parameters
, Qfont_backend
, Qnil
,
4457 "fontBackend", "FontBackend", RES_TYPE_STRING
);
4459 #endif /* USE_FONT_BACKEND */
4461 /* Extract the window parameters from the supplied values
4462 that are needed to determine window geometry. */
4463 #ifdef USE_FONT_BACKEND
4464 if (enable_font_backend
)
4465 x_default_font_parameter (f
, parameters
);
4471 font
= w32_get_arg (parameters
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4474 /* First, try whatever font the caller has specified. */
4477 tem
= Fquery_fontset (font
, Qnil
);
4479 font
= x_new_fontset (f
, tem
);
4481 font
= x_new_font (f
, SDATA (font
));
4483 /* Try out a font which we hope has bold and italic variations. */
4484 if (!STRINGP (font
))
4485 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
4486 if (! STRINGP (font
))
4487 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
4488 /* If those didn't work, look for something which will at least work. */
4489 if (! STRINGP (font
))
4490 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
4492 if (! STRINGP (font
))
4493 font
= build_string ("Fixedsys");
4495 x_default_parameter (f
, parameters
, Qfont
, font
,
4496 "font", "Font", RES_TYPE_STRING
);
4499 x_default_parameter (f
, parameters
, Qborder_width
, make_number (2),
4500 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4501 /* This defaults to 2 in order to match xterm. We recognize either
4502 internalBorderWidth or internalBorder (which is what xterm calls
4504 if (NILP (Fassq (Qinternal_border_width
, parameters
)))
4508 value
= w32_get_arg (parameters
, Qinternal_border_width
,
4509 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
4510 if (! EQ (value
, Qunbound
))
4511 parameters
= Fcons (Fcons (Qinternal_border_width
, value
),
4514 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4515 x_default_parameter (f
, parameters
, Qinternal_border_width
, make_number (0),
4516 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4517 x_default_parameter (f
, parameters
, Qvertical_scroll_bars
, Qright
,
4518 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4520 /* Also do the stuff which must be set before the window exists. */
4521 x_default_parameter (f
, parameters
, Qforeground_color
, build_string ("black"),
4522 "foreground", "Foreground", RES_TYPE_STRING
);
4523 x_default_parameter (f
, parameters
, Qbackground_color
, build_string ("white"),
4524 "background", "Background", RES_TYPE_STRING
);
4525 x_default_parameter (f
, parameters
, Qmouse_color
, build_string ("black"),
4526 "pointerColor", "Foreground", RES_TYPE_STRING
);
4527 x_default_parameter (f
, parameters
, Qcursor_color
, build_string ("black"),
4528 "cursorColor", "Foreground", RES_TYPE_STRING
);
4529 x_default_parameter (f
, parameters
, Qborder_color
, build_string ("black"),
4530 "borderColor", "BorderColor", RES_TYPE_STRING
);
4531 x_default_parameter (f
, parameters
, Qscreen_gamma
, Qnil
,
4532 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4533 x_default_parameter (f
, parameters
, Qline_spacing
, Qnil
,
4534 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4535 x_default_parameter (f
, parameters
, Qleft_fringe
, Qnil
,
4536 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4537 x_default_parameter (f
, parameters
, Qright_fringe
, Qnil
,
4538 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4541 /* Init faces before x_default_parameter is called for scroll-bar
4542 parameters because that function calls x_set_scroll_bar_width,
4543 which calls change_frame_size, which calls Fset_window_buffer,
4544 which runs hooks, which call Fvertical_motion. At the end, we
4545 end up in init_iterator with a null face cache, which should not
4547 init_frame_faces (f
);
4549 x_default_parameter (f
, parameters
, Qmenu_bar_lines
, make_number (1),
4550 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4551 x_default_parameter (f
, parameters
, Qtool_bar_lines
, make_number (1),
4552 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4554 x_default_parameter (f
, parameters
, Qbuffer_predicate
, Qnil
,
4555 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
4556 x_default_parameter (f
, parameters
, Qtitle
, Qnil
,
4557 "title", "Title", RES_TYPE_STRING
);
4558 x_default_parameter (f
, parameters
, Qfullscreen
, Qnil
,
4559 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4561 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4562 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4564 f
->output_data
.w32
->text_cursor
= w32_load_cursor (IDC_IBEAM
);
4565 f
->output_data
.w32
->nontext_cursor
= w32_load_cursor (IDC_ARROW
);
4566 f
->output_data
.w32
->modeline_cursor
= w32_load_cursor (IDC_ARROW
);
4567 f
->output_data
.w32
->hand_cursor
= w32_load_cursor (IDC_HAND
);
4568 f
->output_data
.w32
->hourglass_cursor
= w32_load_cursor (IDC_WAIT
);
4569 f
->output_data
.w32
->horizontal_drag_cursor
= w32_load_cursor (IDC_SIZEWE
);
4571 f
->output_data
.w32
->current_cursor
= f
->output_data
.w32
->nontext_cursor
;
4573 window_prompting
= x_figure_window_size (f
, parameters
, 1);
4575 tem
= w32_get_arg (parameters
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4576 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4578 w32_window (f
, window_prompting
, minibuffer_only
);
4579 x_icon (f
, parameters
);
4583 /* Now consider the frame official. */
4584 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4585 Vframe_list
= Fcons (frame
, Vframe_list
);
4587 /* We need to do this after creating the window, so that the
4588 icon-creation functions can say whose icon they're describing. */
4589 x_default_parameter (f
, parameters
, Qicon_type
, Qnil
,
4590 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4592 x_default_parameter (f
, parameters
, Qauto_raise
, Qnil
,
4593 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4594 x_default_parameter (f
, parameters
, Qauto_lower
, Qnil
,
4595 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4596 x_default_parameter (f
, parameters
, Qcursor_type
, Qbox
,
4597 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4598 x_default_parameter (f
, parameters
, Qscroll_bar_width
, Qnil
,
4599 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4601 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4602 Change will not be effected unless different from the current
4604 width
= FRAME_COLS (f
);
4605 height
= FRAME_LINES (f
);
4607 FRAME_LINES (f
) = 0;
4608 SET_FRAME_COLS (f
, 0);
4609 change_frame_size (f
, height
, width
, 1, 0, 0);
4611 /* Tell the server what size and position, etc, we want, and how
4612 badly we want them. This should be done after we have the menu
4613 bar so that its size can be taken into account. */
4615 x_wm_set_size_hint (f
, window_prompting
, 0);
4618 /* Make the window appear on the frame and enable display, unless
4619 the caller says not to. However, with explicit parent, Emacs
4620 cannot control visibility, so don't try. */
4621 if (! f
->output_data
.w32
->explicit_parent
)
4623 Lisp_Object visibility
;
4625 visibility
= w32_get_arg (parameters
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4626 if (EQ (visibility
, Qunbound
))
4629 if (EQ (visibility
, Qicon
))
4630 x_iconify_frame (f
);
4631 else if (! NILP (visibility
))
4632 x_make_frame_visible (f
);
4634 /* Must have been Qnil. */
4638 /* Initialize `default-minibuffer-frame' in case this is the first
4639 frame on this terminal. */
4640 if (FRAME_HAS_MINIBUF_P (f
)
4641 && (!FRAMEP (kb
->Vdefault_minibuffer_frame
)
4642 || !FRAME_LIVE_P (XFRAME (kb
->Vdefault_minibuffer_frame
))))
4643 kb
->Vdefault_minibuffer_frame
= frame
;
4645 /* All remaining specified parameters, which have not been "used"
4646 by x_get_arg and friends, now go in the misc. alist of the frame. */
4647 for (tem
= parameters
; CONSP (tem
); tem
= XCDR (tem
))
4648 if (CONSP (XCAR (tem
)) && !NILP (XCAR (XCAR (tem
))))
4649 f
->param_alist
= Fcons (XCAR (tem
), f
->param_alist
);
4653 /* Make sure windows on this frame appear in calls to next-window
4654 and similar functions. */
4655 Vwindow_list
= Qnil
;
4657 return unbind_to (count
, frame
);
4660 /* FRAME is used only to get a handle on the X display. We don't pass the
4661 display info directly because we're called from frame.c, which doesn't
4662 know about that structure. */
4664 x_get_focus_frame (frame
)
4665 struct frame
*frame
;
4667 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4669 if (! dpyinfo
->w32_focus_frame
)
4672 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4676 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4677 doc
: /* Give FRAME input focus, raising to foreground if necessary. */)
4681 x_focus_on_frame (check_x_frame (frame
));
4686 /* Return the charset portion of a font name. */
4688 xlfd_charset_of_font (char * fontname
)
4690 char *charset
, *encoding
;
4692 encoding
= strrchr (fontname
, '-');
4693 if (!encoding
|| encoding
== fontname
)
4696 for (charset
= encoding
- 1; charset
>= fontname
; charset
--)
4697 if (*charset
== '-')
4700 if (charset
== fontname
|| strcmp (charset
, "-*-*") == 0)
4706 struct font_info
*w32_load_bdf_font (struct frame
*f
, char *fontname
,
4707 int size
, char* filename
);
4708 static Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
);
4709 static BOOL
w32_to_x_font (LOGFONT
* lplf
, char * lpxstr
, int len
,
4711 static BOOL
x_to_w32_font (char *lpxstr
, LOGFONT
*lplogfont
);
4713 static struct font_info
*
4714 w32_load_system_font (f
, fontname
, size
)
4719 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4720 Lisp_Object font_names
;
4722 /* Get a list of all the fonts that match this name. Once we
4723 have a list of matching fonts, we compare them against the fonts
4724 we already have loaded by comparing names. */
4725 font_names
= w32_list_fonts (f
, build_string (fontname
), size
, 100);
4727 if (!NILP (font_names
))
4732 /* First check if any are already loaded, as that is cheaper
4733 than loading another one. */
4734 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4735 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
4736 if (dpyinfo
->font_table
[i
].name
4737 && (!strcmp (dpyinfo
->font_table
[i
].name
,
4738 SDATA (XCAR (tail
)))
4739 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
4740 SDATA (XCAR (tail
)))))
4741 return (dpyinfo
->font_table
+ i
);
4743 fontname
= (char *) SDATA (XCAR (font_names
));
4745 else if (w32_strict_fontnames
)
4747 /* If EnumFontFamiliesEx was available, we got a full list of
4748 fonts back so stop now to avoid the possibility of loading a
4749 random font. If we had to fall back to EnumFontFamilies, the
4750 list is incomplete, so continue whether the font we want was
4752 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
4753 FARPROC enum_font_families_ex
4754 = GetProcAddress (gdi32
, "EnumFontFamiliesExA");
4755 if (enum_font_families_ex
)
4759 /* Load the font and add it to the table. */
4761 char *full_name
, *encoding
, *charset
;
4763 struct font_info
*fontp
;
4769 if (!fontname
|| !x_to_w32_font (fontname
, &lf
))
4772 if (!*lf
.lfFaceName
)
4773 /* If no name was specified for the font, we get a random font
4774 from CreateFontIndirect - this is not particularly
4775 desirable, especially since CreateFontIndirect does not
4776 fill out the missing name in lf, so we never know what we
4780 lf
.lfQuality
= DEFAULT_QUALITY
;
4782 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
4783 bzero (font
, sizeof (*font
));
4785 /* Set bdf to NULL to indicate that this is a Windows font. */
4790 font
->hfont
= CreateFontIndirect (&lf
);
4792 if (font
->hfont
== NULL
)
4801 codepage
= w32_codepage_for_font (fontname
);
4803 hdc
= GetDC (dpyinfo
->root_window
);
4804 oldobj
= SelectObject (hdc
, font
->hfont
);
4806 ok
= GetTextMetrics (hdc
, &font
->tm
);
4807 if (codepage
== CP_UNICODE
)
4808 font
->double_byte_p
= 1;
4811 /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
4812 don't report themselves as double byte fonts, when
4813 patently they are. So instead of trusting
4814 GetFontLanguageInfo, we check the properties of the
4815 codepage directly, since that is ultimately what we are
4816 working from anyway. */
4817 /* font->double_byte_p = GetFontLanguageInfo (hdc) & GCP_DBCS; */
4819 GetCPInfo (codepage
, &cpi
);
4820 font
->double_byte_p
= cpi
.MaxCharSize
> 1;
4823 SelectObject (hdc
, oldobj
);
4824 ReleaseDC (dpyinfo
->root_window
, hdc
);
4825 /* Fill out details in lf according to the font that was
4827 lf
.lfHeight
= font
->tm
.tmInternalLeading
- font
->tm
.tmHeight
;
4828 lf
.lfWidth
= font
->tm
.tmMaxCharWidth
;
4829 lf
.lfWeight
= font
->tm
.tmWeight
;
4830 lf
.lfItalic
= font
->tm
.tmItalic
;
4831 lf
.lfCharSet
= font
->tm
.tmCharSet
;
4832 lf
.lfPitchAndFamily
= ((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
)
4833 ? VARIABLE_PITCH
: FIXED_PITCH
);
4834 lf
.lfOutPrecision
= ((font
->tm
.tmPitchAndFamily
& TMPF_VECTOR
)
4835 ? OUT_STROKE_PRECIS
: OUT_STRING_PRECIS
);
4837 w32_cache_char_metrics (font
);
4844 w32_unload_font (dpyinfo
, font
);
4848 /* Find a free slot in the font table. */
4849 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
4850 if (dpyinfo
->font_table
[i
].name
== NULL
)
4853 /* If no free slot found, maybe enlarge the font table. */
4854 if (i
== dpyinfo
->n_fonts
4855 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
4858 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
4859 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
4861 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
4864 fontp
= dpyinfo
->font_table
+ i
;
4865 if (i
== dpyinfo
->n_fonts
)
4868 /* Now fill in the slots of *FONTP. */
4870 bzero (fontp
, sizeof (*fontp
));
4872 fontp
->font_idx
= i
;
4873 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
4874 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
4876 if ((lf
.lfPitchAndFamily
& 0x03) == FIXED_PITCH
)
4878 /* Fixed width font. */
4879 fontp
->average_width
= fontp
->space_width
= FONT_AVG_WIDTH (font
);
4885 pcm
= w32_per_char_metric (font
, &space
, ANSI_FONT
);
4887 fontp
->space_width
= pcm
->width
;
4889 fontp
->space_width
= FONT_AVG_WIDTH (font
);
4891 fontp
->average_width
= font
->tm
.tmAveCharWidth
;
4894 fontp
->charset
= -1;
4895 charset
= xlfd_charset_of_font (fontname
);
4897 /* Cache the W32 codepage for a font. This makes w32_encode_char
4898 (called for every glyph during redisplay) much faster. */
4899 fontp
->codepage
= codepage
;
4901 /* Work out the font's full name. */
4902 full_name
= (char *)xmalloc (100);
4903 if (full_name
&& w32_to_x_font (&lf
, full_name
, 100, charset
))
4904 fontp
->full_name
= full_name
;
4907 /* If all else fails - just use the name we used to load it. */
4909 fontp
->full_name
= fontp
->name
;
4912 fontp
->size
= FONT_WIDTH (font
);
4913 fontp
->height
= FONT_HEIGHT (font
);
4915 /* The slot `encoding' specifies how to map a character
4916 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
4917 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
4918 (0:0x20..0x7F, 1:0xA0..0xFF,
4919 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
4920 2:0xA020..0xFF7F). For the moment, we don't know which charset
4921 uses this font. So, we set information in fontp->encoding_type
4922 which is never used by any charset. If mapping can't be
4923 decided, set FONT_ENCODING_NOT_DECIDED. */
4925 /* SJIS fonts need to be set to type 4, all others seem to work as
4926 type FONT_ENCODING_NOT_DECIDED. */
4927 encoding
= strrchr (fontp
->name
, '-');
4928 if (encoding
&& strnicmp (encoding
+1, "sjis", 4) == 0)
4929 fontp
->encoding_type
= 4;
4931 fontp
->encoding_type
= FONT_ENCODING_NOT_DECIDED
;
4933 /* The following three values are set to 0 under W32, which is
4934 what they get set to if XGetFontProperty fails under X. */
4935 fontp
->baseline_offset
= 0;
4936 fontp
->relative_compose
= 0;
4937 fontp
->default_ascent
= 0;
4939 /* Set global flag fonts_changed_p to non-zero if the font loaded
4940 has a character with a smaller width than any other character
4941 before, or if the font loaded has a smaller height than any
4942 other font loaded before. If this happens, it will make a
4943 glyph matrix reallocation necessary. */
4944 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
4950 /* Load font named FONTNAME of size SIZE for frame F, and return a
4951 pointer to the structure font_info while allocating it dynamically.
4952 If loading fails, return NULL. */
4954 w32_load_font (f
, fontname
, size
)
4959 Lisp_Object bdf_fonts
;
4960 struct font_info
*retval
= NULL
;
4961 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4963 bdf_fonts
= w32_list_bdf_fonts (build_string (fontname
), 1);
4965 while (!retval
&& CONSP (bdf_fonts
))
4967 char *bdf_name
, *bdf_file
;
4968 Lisp_Object bdf_pair
;
4971 bdf_name
= SDATA (XCAR (bdf_fonts
));
4972 bdf_pair
= Fassoc (XCAR (bdf_fonts
), Vw32_bdf_filename_alist
);
4973 bdf_file
= SDATA (XCDR (bdf_pair
));
4975 /* If the font is already loaded, do not load it again. */
4976 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4978 if ((dpyinfo
->font_table
[i
].name
4979 && !strcmp (dpyinfo
->font_table
[i
].name
, bdf_name
))
4980 || (dpyinfo
->font_table
[i
].full_name
4981 && !strcmp (dpyinfo
->font_table
[i
].full_name
, bdf_name
)))
4982 return dpyinfo
->font_table
+ i
;
4985 retval
= w32_load_bdf_font (f
, bdf_name
, size
, bdf_file
);
4987 bdf_fonts
= XCDR (bdf_fonts
);
4993 return w32_load_system_font (f
, fontname
, size
);
4998 w32_unload_font (dpyinfo
, font
)
4999 struct w32_display_info
*dpyinfo
;
5004 if (font
->per_char
) xfree (font
->per_char
);
5005 if (font
->bdf
) w32_free_bdf_font (font
->bdf
);
5007 if (font
->hfont
) DeleteObject (font
->hfont
);
5012 /* The font conversion stuff between x and w32 */
5014 /* X font string is as follows (from faces.el)
5018 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5019 * (weight\? "\\([^-]*\\)") ; 1
5020 * (slant "\\([ior]\\)") ; 2
5021 * (slant\? "\\([^-]?\\)") ; 2
5022 * (swidth "\\([^-]*\\)") ; 3
5023 * (adstyle "[^-]*") ; 4
5024 * (pixelsize "[0-9]+")
5025 * (pointsize "[0-9][0-9]+")
5026 * (resx "[0-9][0-9]+")
5027 * (resy "[0-9][0-9]+")
5028 * (spacing "[cmp?*]")
5029 * (avgwidth "[0-9]+")
5030 * (registry "[^-]+")
5031 * (encoding "[^-]+")
5036 x_to_w32_weight (lpw
)
5039 if (!lpw
) return (FW_DONTCARE
);
5041 if (stricmp (lpw
, "heavy") == 0) return FW_HEAVY
;
5042 else if (stricmp (lpw
, "extrabold") == 0) return FW_EXTRABOLD
;
5043 else if (stricmp (lpw
, "bold") == 0) return FW_BOLD
;
5044 else if (stricmp (lpw
, "demibold") == 0) return FW_SEMIBOLD
;
5045 else if (stricmp (lpw
, "semibold") == 0) return FW_SEMIBOLD
;
5046 else if (stricmp (lpw
, "medium") == 0) return FW_MEDIUM
;
5047 else if (stricmp (lpw
, "normal") == 0) return FW_NORMAL
;
5048 else if (stricmp (lpw
, "light") == 0) return FW_LIGHT
;
5049 else if (stricmp (lpw
, "extralight") == 0) return FW_EXTRALIGHT
;
5050 else if (stricmp (lpw
, "thin") == 0) return FW_THIN
;
5057 w32_to_x_weight (fnweight
)
5060 if (fnweight
>= FW_HEAVY
) return "heavy";
5061 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
5062 if (fnweight
>= FW_BOLD
) return "bold";
5063 if (fnweight
>= FW_SEMIBOLD
) return "demibold";
5064 if (fnweight
>= FW_MEDIUM
) return "medium";
5065 if (fnweight
>= FW_NORMAL
) return "normal";
5066 if (fnweight
>= FW_LIGHT
) return "light";
5067 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
5068 if (fnweight
>= FW_THIN
) return "thin";
5074 x_to_w32_charset (lpcs
)
5077 Lisp_Object this_entry
, w32_charset
;
5079 int len
= strlen (lpcs
);
5081 /* Support "*-#nnn" format for unknown charsets. */
5082 if (strncmp (lpcs
, "*-#", 3) == 0)
5083 return atoi (lpcs
+ 3);
5085 /* All Windows fonts qualify as unicode. */
5086 if (!strncmp (lpcs
, "iso10646", 8))
5087 return DEFAULT_CHARSET
;
5089 /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5". */
5090 charset
= alloca (len
+ 1);
5091 strcpy (charset
, lpcs
);
5092 lpcs
= strchr (charset
, '*');
5096 /* Look through w32-charset-info-alist for the character set.
5097 Format of each entry is
5098 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5100 this_entry
= Fassoc (build_string (charset
), Vw32_charset_info_alist
);
5102 if (NILP (this_entry
))
5104 /* At startup, we want iso8859-1 fonts to come up properly. */
5105 if (stricmp (charset
, "iso8859-1") == 0)
5106 return ANSI_CHARSET
;
5108 return DEFAULT_CHARSET
;
5111 w32_charset
= Fcar (Fcdr (this_entry
));
5113 /* Translate Lisp symbol to number. */
5114 if (EQ (w32_charset
, Qw32_charset_ansi
))
5115 return ANSI_CHARSET
;
5116 if (EQ (w32_charset
, Qw32_charset_symbol
))
5117 return SYMBOL_CHARSET
;
5118 if (EQ (w32_charset
, Qw32_charset_shiftjis
))
5119 return SHIFTJIS_CHARSET
;
5120 if (EQ (w32_charset
, Qw32_charset_hangeul
))
5121 return HANGEUL_CHARSET
;
5122 if (EQ (w32_charset
, Qw32_charset_chinesebig5
))
5123 return CHINESEBIG5_CHARSET
;
5124 if (EQ (w32_charset
, Qw32_charset_gb2312
))
5125 return GB2312_CHARSET
;
5126 if (EQ (w32_charset
, Qw32_charset_oem
))
5128 #ifdef JOHAB_CHARSET
5129 if (EQ (w32_charset
, Qw32_charset_johab
))
5130 return JOHAB_CHARSET
;
5131 if (EQ (w32_charset
, Qw32_charset_easteurope
))
5132 return EASTEUROPE_CHARSET
;
5133 if (EQ (w32_charset
, Qw32_charset_turkish
))
5134 return TURKISH_CHARSET
;
5135 if (EQ (w32_charset
, Qw32_charset_baltic
))
5136 return BALTIC_CHARSET
;
5137 if (EQ (w32_charset
, Qw32_charset_russian
))
5138 return RUSSIAN_CHARSET
;
5139 if (EQ (w32_charset
, Qw32_charset_arabic
))
5140 return ARABIC_CHARSET
;
5141 if (EQ (w32_charset
, Qw32_charset_greek
))
5142 return GREEK_CHARSET
;
5143 if (EQ (w32_charset
, Qw32_charset_hebrew
))
5144 return HEBREW_CHARSET
;
5145 if (EQ (w32_charset
, Qw32_charset_vietnamese
))
5146 return VIETNAMESE_CHARSET
;
5147 if (EQ (w32_charset
, Qw32_charset_thai
))
5148 return THAI_CHARSET
;
5149 if (EQ (w32_charset
, Qw32_charset_mac
))
5151 #endif /* JOHAB_CHARSET */
5152 #ifdef UNICODE_CHARSET
5153 if (EQ (w32_charset
, Qw32_charset_unicode
))
5154 return UNICODE_CHARSET
;
5157 return DEFAULT_CHARSET
;
5162 w32_to_x_charset (fncharset
, matching
)
5166 static char buf
[32];
5167 Lisp_Object charset_type
;
5172 /* If fully specified, accept it as it is. Otherwise use a
5174 char *wildcard
= strchr (matching
, '*');
5177 else if (strchr (matching
, '-'))
5180 match_len
= strlen (matching
);
5186 /* Handle startup case of w32-charset-info-alist not
5187 being set up yet. */
5188 if (NILP (Vw32_charset_info_alist
))
5190 charset_type
= Qw32_charset_ansi
;
5192 case DEFAULT_CHARSET
:
5193 charset_type
= Qw32_charset_default
;
5195 case SYMBOL_CHARSET
:
5196 charset_type
= Qw32_charset_symbol
;
5198 case SHIFTJIS_CHARSET
:
5199 charset_type
= Qw32_charset_shiftjis
;
5201 case HANGEUL_CHARSET
:
5202 charset_type
= Qw32_charset_hangeul
;
5204 case GB2312_CHARSET
:
5205 charset_type
= Qw32_charset_gb2312
;
5207 case CHINESEBIG5_CHARSET
:
5208 charset_type
= Qw32_charset_chinesebig5
;
5211 charset_type
= Qw32_charset_oem
;
5214 /* More recent versions of Windows (95 and NT4.0) define more
5216 #ifdef EASTEUROPE_CHARSET
5217 case EASTEUROPE_CHARSET
:
5218 charset_type
= Qw32_charset_easteurope
;
5220 case TURKISH_CHARSET
:
5221 charset_type
= Qw32_charset_turkish
;
5223 case BALTIC_CHARSET
:
5224 charset_type
= Qw32_charset_baltic
;
5226 case RUSSIAN_CHARSET
:
5227 charset_type
= Qw32_charset_russian
;
5229 case ARABIC_CHARSET
:
5230 charset_type
= Qw32_charset_arabic
;
5233 charset_type
= Qw32_charset_greek
;
5235 case HEBREW_CHARSET
:
5236 charset_type
= Qw32_charset_hebrew
;
5238 case VIETNAMESE_CHARSET
:
5239 charset_type
= Qw32_charset_vietnamese
;
5242 charset_type
= Qw32_charset_thai
;
5245 charset_type
= Qw32_charset_mac
;
5248 charset_type
= Qw32_charset_johab
;
5252 #ifdef UNICODE_CHARSET
5253 case UNICODE_CHARSET
:
5254 charset_type
= Qw32_charset_unicode
;
5258 /* Encode numerical value of unknown charset. */
5259 sprintf (buf
, "*-#%u", fncharset
);
5265 char * best_match
= NULL
;
5266 int matching_found
= 0;
5268 /* Look through w32-charset-info-alist for the character set.
5269 Prefer ISO codepages, and prefer lower numbers in the ISO
5270 range. Only return charsets for codepages which are installed.
5272 Format of each entry is
5273 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5275 for (rest
= Vw32_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
5278 Lisp_Object w32_charset
;
5279 Lisp_Object codepage
;
5281 Lisp_Object this_entry
= XCAR (rest
);
5283 /* Skip invalid entries in alist. */
5284 if (!CONSP (this_entry
) || !STRINGP (XCAR (this_entry
))
5285 || !CONSP (XCDR (this_entry
))
5286 || !SYMBOLP (XCAR (XCDR (this_entry
))))
5289 x_charset
= SDATA (XCAR (this_entry
));
5290 w32_charset
= XCAR (XCDR (this_entry
));
5291 codepage
= XCDR (XCDR (this_entry
));
5293 /* Look for Same charset and a valid codepage (or non-int
5294 which means ignore). */
5295 if (EQ (w32_charset
, charset_type
)
5296 && (!INTEGERP (codepage
) || XINT (codepage
) == CP_DEFAULT
5297 || IsValidCodePage (XINT (codepage
))))
5299 /* If we don't have a match already, then this is the
5303 best_match
= x_charset
;
5304 if (matching
&& !strnicmp (x_charset
, matching
, match_len
))
5307 /* If we already found a match for MATCHING, then
5308 only consider other matches. */
5309 else if (matching_found
5310 && strnicmp (x_charset
, matching
, match_len
))
5312 /* If this matches what we want, and the best so far doesn't,
5313 then this is better. */
5314 else if (!matching_found
&& matching
5315 && !strnicmp (x_charset
, matching
, match_len
))
5317 best_match
= x_charset
;
5320 /* If this is fully specified, and the best so far isn't,
5321 then this is better. */
5322 else if ((!strchr (best_match
, '-') && strchr (x_charset
, '-'))
5323 /* If this is an ISO codepage, and the best so far isn't,
5324 then this is better, but only if it fully specifies the
5326 || (strnicmp (best_match
, "iso", 3) != 0
5327 && strnicmp (x_charset
, "iso", 3) == 0
5328 && strchr (x_charset
, '-')))
5329 best_match
= x_charset
;
5330 /* If both are ISO8859 codepages, choose the one with the
5331 lowest number in the encoding field. */
5332 else if (strnicmp (best_match
, "iso8859-", 8) == 0
5333 && strnicmp (x_charset
, "iso8859-", 8) == 0)
5335 int best_enc
= atoi (best_match
+ 8);
5336 int this_enc
= atoi (x_charset
+ 8);
5337 if (this_enc
> 0 && this_enc
< best_enc
)
5338 best_match
= x_charset
;
5343 /* If no match, encode the numeric value. */
5346 sprintf (buf
, "*-#%u", fncharset
);
5350 strncpy (buf
, best_match
, 31);
5351 /* If the charset is not fully specified, put -0 on the end. */
5352 if (!strchr (best_match
, '-'))
5354 int pos
= strlen (best_match
);
5355 /* Charset specifiers shouldn't be very long. If it is a made
5356 up one, truncating it should not do any harm since it isn't
5357 recognized anyway. */
5360 strcpy (buf
+ pos
, "-0");
5368 /* Return all the X charsets that map to a font. */
5370 w32_to_all_x_charsets (fncharset
)
5373 static char buf
[32];
5374 Lisp_Object charset_type
;
5375 Lisp_Object retval
= Qnil
;
5380 /* Handle startup case of w32-charset-info-alist not
5381 being set up yet. */
5382 if (NILP (Vw32_charset_info_alist
))
5383 return Fcons (build_string ("iso8859-1"), Qnil
);
5385 charset_type
= Qw32_charset_ansi
;
5387 case DEFAULT_CHARSET
:
5388 charset_type
= Qw32_charset_default
;
5390 case SYMBOL_CHARSET
:
5391 charset_type
= Qw32_charset_symbol
;
5393 case SHIFTJIS_CHARSET
:
5394 charset_type
= Qw32_charset_shiftjis
;
5396 case HANGEUL_CHARSET
:
5397 charset_type
= Qw32_charset_hangeul
;
5399 case GB2312_CHARSET
:
5400 charset_type
= Qw32_charset_gb2312
;
5402 case CHINESEBIG5_CHARSET
:
5403 charset_type
= Qw32_charset_chinesebig5
;
5406 charset_type
= Qw32_charset_oem
;
5409 /* More recent versions of Windows (95 and NT4.0) define more
5411 #ifdef EASTEUROPE_CHARSET
5412 case EASTEUROPE_CHARSET
:
5413 charset_type
= Qw32_charset_easteurope
;
5415 case TURKISH_CHARSET
:
5416 charset_type
= Qw32_charset_turkish
;
5418 case BALTIC_CHARSET
:
5419 charset_type
= Qw32_charset_baltic
;
5421 case RUSSIAN_CHARSET
:
5422 charset_type
= Qw32_charset_russian
;
5424 case ARABIC_CHARSET
:
5425 charset_type
= Qw32_charset_arabic
;
5428 charset_type
= Qw32_charset_greek
;
5430 case HEBREW_CHARSET
:
5431 charset_type
= Qw32_charset_hebrew
;
5433 case VIETNAMESE_CHARSET
:
5434 charset_type
= Qw32_charset_vietnamese
;
5437 charset_type
= Qw32_charset_thai
;
5440 charset_type
= Qw32_charset_mac
;
5443 charset_type
= Qw32_charset_johab
;
5447 #ifdef UNICODE_CHARSET
5448 case UNICODE_CHARSET
:
5449 charset_type
= Qw32_charset_unicode
;
5453 /* Encode numerical value of unknown charset. */
5454 sprintf (buf
, "*-#%u", fncharset
);
5455 return Fcons (build_string (buf
), Qnil
);
5460 /* Look through w32-charset-info-alist for the character set.
5461 Only return fully specified charsets for codepages which are
5464 Format of each entry in Vw32_charset_info_alist is
5465 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5467 for (rest
= Vw32_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
5469 Lisp_Object x_charset
;
5470 Lisp_Object w32_charset
;
5471 Lisp_Object codepage
;
5473 Lisp_Object this_entry
= XCAR (rest
);
5475 /* Skip invalid entries in alist. */
5476 if (!CONSP (this_entry
) || !STRINGP (XCAR (this_entry
))
5477 || !CONSP (XCDR (this_entry
))
5478 || !SYMBOLP (XCAR (XCDR (this_entry
))))
5481 x_charset
= XCAR (this_entry
);
5482 w32_charset
= XCAR (XCDR (this_entry
));
5483 codepage
= XCDR (XCDR (this_entry
));
5485 if (!strchr (SDATA (x_charset
), '-'))
5488 /* Look for Same charset and a valid codepage (or non-int
5489 which means ignore). */
5490 if (EQ (w32_charset
, charset_type
)
5491 && (!INTEGERP (codepage
) || XINT (codepage
) == CP_DEFAULT
5492 || IsValidCodePage (XINT (codepage
))))
5494 retval
= Fcons (x_charset
, retval
);
5498 /* If no match, encode the numeric value. */
5501 sprintf (buf
, "*-#%u", fncharset
);
5502 return Fcons (build_string (buf
), Qnil
);
5509 /* Get the Windows codepage corresponding to the specified font. The
5510 charset info in the font name is used to look up
5511 w32-charset-to-codepage-alist. */
5513 w32_codepage_for_font (char *fontname
)
5515 Lisp_Object codepage
, entry
;
5516 char *charset_str
, *charset
, *end
;
5518 /* Extract charset part of font string. */
5519 charset
= xlfd_charset_of_font (fontname
);
5524 charset_str
= (char *) alloca (strlen (charset
) + 1);
5525 strcpy (charset_str
, charset
);
5528 /* Remove leading "*-". */
5529 if (strncmp ("*-", charset_str
, 2) == 0)
5530 charset
= charset_str
+ 2;
5533 charset
= charset_str
;
5535 /* Stop match at wildcard (including preceding '-'). */
5536 if (end
= strchr (charset
, '*'))
5538 if (end
> charset
&& *(end
-1) == '-')
5543 if (!strcmp (charset
, "iso10646"))
5546 if (NILP (Vw32_charset_info_alist
))
5549 entry
= Fassoc (build_string(charset
), Vw32_charset_info_alist
);
5553 codepage
= Fcdr (Fcdr (entry
));
5555 if (NILP (codepage
))
5557 else if (XFASTINT (codepage
) == XFASTINT (Qt
))
5559 else if (INTEGERP (codepage
))
5560 return XINT (codepage
);
5567 w32_to_x_font (lplogfont
, lpxstr
, len
, specific_charset
)
5568 LOGFONT
* lplogfont
;
5571 char * specific_charset
;
5575 char height_pixels
[8];
5577 char width_pixels
[8];
5578 char *fontname_dash
;
5579 int display_resy
= (int) one_w32_display_info
.resy
;
5580 int display_resx
= (int) one_w32_display_info
.resx
;
5581 struct coding_system coding
;
5583 if (!lpxstr
) abort ();
5588 if (lplogfont
->lfOutPrecision
== OUT_STRING_PRECIS
)
5589 fonttype
= "raster";
5590 else if (lplogfont
->lfOutPrecision
== OUT_STROKE_PRECIS
)
5591 fonttype
= "outline";
5593 fonttype
= "unknown";
5595 setup_coding_system (Fcheck_coding_system (Vlocale_coding_system
),
5597 coding
.src_multibyte
= 0;
5598 coding
.dst_multibyte
= 1;
5599 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5600 /* We explicitely disable composition handling because selection
5601 data should not contain any composition sequence. */
5602 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
5604 coding
.dst_bytes
= LF_FACESIZE
* 2;
5605 coding
.destination
= (unsigned char *) xmalloc (coding
.dst_bytes
+ 1);
5606 decode_coding_c_string (&coding
, lplogfont
->lfFaceName
,
5607 strlen(lplogfont
->lfFaceName
), Qnil
);
5608 fontname
= coding
.destination
;
5610 *(fontname
+ coding
.produced
) = '\0';
5612 /* Replace dashes with underscores so the dashes are not
5614 fontname_dash
= fontname
;
5615 while (fontname_dash
= strchr (fontname_dash
, '-'))
5616 *fontname_dash
= '_';
5618 if (lplogfont
->lfHeight
)
5620 sprintf (height_pixels
, "%u", eabs (lplogfont
->lfHeight
));
5621 sprintf (height_dpi
, "%u",
5622 eabs (lplogfont
->lfHeight
) * 720 / display_resy
);
5626 strcpy (height_pixels
, "*");
5627 strcpy (height_dpi
, "*");
5630 #if 0 /* Never put the width in the xfld. It fails on fonts with
5631 double-width characters. */
5632 if (lplogfont
->lfWidth
)
5633 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
5636 strcpy (width_pixels
, "*");
5638 _snprintf (lpxstr
, len
- 1,
5639 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
5640 fonttype
, /* foundry */
5641 fontname
, /* family */
5642 w32_to_x_weight (lplogfont
->lfWeight
), /* weight */
5643 lplogfont
->lfItalic
?'i':'r', /* slant */
5645 /* add style name */
5646 height_pixels
, /* pixel size */
5647 height_dpi
, /* point size */
5648 display_resx
, /* resx */
5649 display_resy
, /* resy */
5650 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
)
5651 ? 'p' : 'c', /* spacing */
5652 width_pixels
, /* avg width */
5653 w32_to_x_charset (lplogfont
->lfCharSet
, specific_charset
)
5654 /* charset registry and encoding */
5657 lpxstr
[len
- 1] = 0; /* just to be sure */
5662 x_to_w32_font (lpxstr
, lplogfont
)
5664 LOGFONT
* lplogfont
;
5666 struct coding_system coding
;
5668 if (!lplogfont
) return (FALSE
);
5670 memset (lplogfont
, 0, sizeof (*lplogfont
));
5672 /* Set default value for each field. */
5674 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5675 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5676 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
5678 /* go for maximum quality */
5679 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
5680 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
5681 lplogfont
->lfQuality
= PROOF_QUALITY
;
5684 lplogfont
->lfCharSet
= DEFAULT_CHARSET
;
5685 lplogfont
->lfWeight
= FW_DONTCARE
;
5686 lplogfont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
5691 /* Provide a simple escape mechanism for specifying Windows font names
5692 * directly -- if font spec does not beginning with '-', assume this
5694 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
5700 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10],
5701 width
[10], resy
[10], remainder
[50];
5703 int dpi
= (int) one_w32_display_info
.resy
;
5705 fields
= sscanf (lpxstr
,
5706 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
5707 name
, weight
, &slant
, pixels
, height
, resy
, &pitch
, width
, remainder
);
5711 /* In the general case when wildcards cover more than one field,
5712 we don't know which field is which, so don't fill any in.
5713 However, we need to cope with this particular form, which is
5714 generated by font_list_1 (invoked by try_font_list):
5715 "-raster-6x10-*-gb2312*-*"
5716 and make sure to correctly parse the charset field. */
5719 fields
= sscanf (lpxstr
,
5720 "-%*[^-]-%49[^-]-*-%49s",
5723 else if (fields
< 9)
5729 if (fields
> 0 && name
[0] != '*')
5731 Lisp_Object string
= build_string (name
);
5733 (Fcheck_coding_system (Vlocale_coding_system
), &coding
);
5734 coding
.mode
|= (CODING_MODE_SAFE_ENCODING
| CODING_MODE_LAST_BLOCK
);
5735 /* Disable composition/charset annotation. */
5736 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
5737 coding
.dst_bytes
= SCHARS (string
) * 2;
5739 coding
.destination
= (unsigned char *) xmalloc (coding
.dst_bytes
);
5740 encode_coding_object (&coding
, string
, 0, 0,
5741 SCHARS (string
), SBYTES (string
), Qnil
);
5742 if (coding
.produced
>= LF_FACESIZE
)
5743 coding
.produced
= LF_FACESIZE
- 1;
5745 coding
.destination
[coding
.produced
] = '\0';
5747 strcpy (lplogfont
->lfFaceName
, coding
.destination
);
5748 xfree (coding
.destination
);
5752 lplogfont
->lfFaceName
[0] = '\0';
5757 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5761 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
5765 if (fields
> 0 && pixels
[0] != '*')
5766 lplogfont
->lfHeight
= atoi (pixels
);
5770 if (fields
> 0 && resy
[0] != '*')
5773 if (tem
> 0) dpi
= tem
;
5776 if (fields
> -1 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
5777 lplogfont
->lfHeight
= atoi (height
) * dpi
/ 720;
5782 lplogfont
->lfPitchAndFamily
= VARIABLE_PITCH
| FF_DONTCARE
;
5783 else if (pitch
== 'c')
5784 lplogfont
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
5789 if (fields
> 0 && width
[0] != '*')
5790 lplogfont
->lfWidth
= atoi (width
) / 10;
5794 /* Strip the trailing '-' if present. (it shouldn't be, as it
5795 fails the test against xlfd-tight-regexp in fontset.el). */
5797 int len
= strlen (remainder
);
5798 if (len
> 0 && remainder
[len
-1] == '-')
5799 remainder
[len
-1] = 0;
5801 encoding
= remainder
;
5803 if (strncmp (encoding
, "*-", 2) == 0)
5806 lplogfont
->lfCharSet
= x_to_w32_charset (encoding
);
5811 char name
[100], height
[10], width
[10], weight
[20];
5813 fields
= sscanf (lpxstr
,
5814 "%99[^:]:%9[^:]:%9[^:]:%19s",
5815 name
, height
, width
, weight
);
5817 if (fields
== EOF
) return (FALSE
);
5821 strncpy (lplogfont
->lfFaceName
, name
, LF_FACESIZE
);
5822 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
5826 lplogfont
->lfFaceName
[0] = 0;
5832 lplogfont
->lfHeight
= atoi (height
);
5837 lplogfont
->lfWidth
= atoi (width
);
5841 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5844 /* This makes TrueType fonts work better. */
5845 lplogfont
->lfHeight
= - eabs (lplogfont
->lfHeight
);
5850 /* Strip the pixel height and point height from the given xlfd, and
5851 return the pixel height. If no pixel height is specified, calculate
5852 one from the point height, or if that isn't defined either, return
5853 0 (which usually signifies a scalable font).
5856 xlfd_strip_height (char *fontname
)
5858 int pixel_height
, field_number
;
5859 char *read_from
, *write_to
;
5863 pixel_height
= field_number
= 0;
5866 /* Look for height fields. */
5867 for (read_from
= fontname
; *read_from
; read_from
++)
5869 if (*read_from
== '-')
5872 if (field_number
== 7) /* Pixel height. */
5875 write_to
= read_from
;
5877 /* Find end of field. */
5878 for (;*read_from
&& *read_from
!= '-'; read_from
++)
5881 /* Split the fontname at end of field. */
5887 pixel_height
= atoi (write_to
);
5888 /* Blank out field. */
5889 if (read_from
> write_to
)
5894 /* If the pixel height field is at the end (partial xlfd),
5897 return pixel_height
;
5899 /* If we got a pixel height, the point height can be
5900 ignored. Just blank it out and break now. */
5903 /* Find end of point size field. */
5904 for (; *read_from
&& *read_from
!= '-'; read_from
++)
5910 /* Blank out the point size field. */
5911 if (read_from
> write_to
)
5917 return pixel_height
;
5921 /* If the point height is already blank, break now. */
5922 if (*read_from
== '-')
5928 else if (field_number
== 8)
5930 /* If we didn't get a pixel height, try to get the point
5931 height and convert that. */
5933 char *point_size_start
= read_from
++;
5935 /* Find end of field. */
5936 for (; *read_from
&& *read_from
!= '-'; read_from
++)
5945 point_size
= atoi (point_size_start
);
5947 /* Convert to pixel height. */
5948 pixel_height
= point_size
5949 * one_w32_display_info
.height_in
/ 720;
5951 /* Blank out this field and break. */
5959 /* Shift the rest of the font spec into place. */
5960 if (write_to
&& read_from
> write_to
)
5962 for (; *read_from
; read_from
++, write_to
++)
5963 *write_to
= *read_from
;
5967 return pixel_height
;
5970 /* Assume parameter 1 is fully qualified, no wildcards. */
5972 w32_font_match (fontname
, pattern
)
5977 char *font_name_copy
;
5978 char *regex
= alloca (strlen (pattern
) * 2 + 3);
5980 font_name_copy
= alloca (strlen (fontname
) + 1);
5981 strcpy (font_name_copy
, fontname
);
5986 /* Turn pattern into a regexp and do a regexp match. */
5987 for (; *pattern
; pattern
++)
5989 if (*pattern
== '?')
5991 else if (*pattern
== '*')
6002 /* Strip out font heights and compare them seperately, since
6003 rounding error can cause mismatches. This also allows a
6004 comparison between a font that declares only a pixel height and a
6005 pattern that declares the point height.
6008 int font_height
, pattern_height
;
6010 font_height
= xlfd_strip_height (font_name_copy
);
6011 pattern_height
= xlfd_strip_height (regex
);
6013 /* Compare now, and don't bother doing expensive regexp matching
6014 if the heights differ. */
6015 if (font_height
&& pattern_height
&& (font_height
!= pattern_height
))
6019 return (fast_string_match_ignore_case (build_string (regex
),
6020 build_string (font_name_copy
)) >= 0);
6023 /* Callback functions, and a structure holding info they need, for
6024 listing system fonts on W32. We need one set of functions to do the
6025 job properly, but these don't work on NT 3.51 and earlier, so we
6026 have a second set which don't handle character sets properly to
6029 In both cases, there are two passes made. The first pass gets one
6030 font from each family, the second pass lists all the fonts from
6033 typedef struct enumfont_t
6038 XFontStruct
*size_ref
;
6039 Lisp_Object pattern
;
6045 enum_font_maybe_add_to_list (enumfont_t
*, LOGFONT
*, char *, Lisp_Object
);
6049 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
6051 NEWTEXTMETRIC
* lptm
;
6055 /* Ignore struck out and underlined versions of fonts. */
6056 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
6059 /* Only return fonts with names starting with @ if they were
6060 explicitly specified, since Microsoft uses an initial @ to
6061 denote fonts for vertical writing, without providing a more
6062 convenient way of identifying them. */
6063 if (lplf
->elfLogFont
.lfFaceName
[0] == '@'
6064 && lpef
->logfont
.lfFaceName
[0] != '@')
6067 /* Check that the character set matches if it was specified */
6068 if (lpef
->logfont
.lfCharSet
!= DEFAULT_CHARSET
&&
6069 lplf
->elfLogFont
.lfCharSet
!= lpef
->logfont
.lfCharSet
)
6072 if (FontType
== RASTER_FONTTYPE
)
6074 /* DBCS raster fonts have problems displaying, so skip them. */
6075 int charset
= lplf
->elfLogFont
.lfCharSet
;
6076 if (charset
== SHIFTJIS_CHARSET
6077 || charset
== HANGEUL_CHARSET
6078 || charset
== CHINESEBIG5_CHARSET
6079 || charset
== GB2312_CHARSET
6080 #ifdef JOHAB_CHARSET
6081 || charset
== JOHAB_CHARSET
6089 Lisp_Object width
= Qnil
;
6090 Lisp_Object charset_list
= Qnil
;
6091 char *charset
= NULL
;
6093 /* Truetype fonts do not report their true metrics until loaded */
6094 if (FontType
!= RASTER_FONTTYPE
)
6096 if (!NILP (lpef
->pattern
))
6098 /* Scalable fonts are as big as you want them to be. */
6099 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
6100 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
6101 width
= make_number (lpef
->logfont
.lfWidth
);
6105 lplf
->elfLogFont
.lfHeight
= 0;
6106 lplf
->elfLogFont
.lfWidth
= 0;
6110 /* Make sure the height used here is the same as everywhere
6111 else (ie character height, not cell height). */
6112 if (lplf
->elfLogFont
.lfHeight
> 0)
6114 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
6115 if (FontType
== RASTER_FONTTYPE
)
6116 lplf
->elfLogFont
.lfHeight
= lptm
->tmInternalLeading
- lptm
->tmHeight
;
6118 lplf
->elfLogFont
.lfHeight
= -lplf
->elfLogFont
.lfHeight
;
6121 if (!NILP (lpef
->pattern
))
6123 charset
= xlfd_charset_of_font (SDATA (lpef
->pattern
));
6125 /* We already checked charsets above, but DEFAULT_CHARSET
6126 slipped through. So only allow exact matches for DEFAULT_CHARSET. */
6128 && strncmp (charset
, "*-*", 3) != 0
6129 && lpef
->logfont
.lfCharSet
== DEFAULT_CHARSET
6130 && strcmp (charset
, w32_to_x_charset (DEFAULT_CHARSET
, NULL
)) != 0)
6133 /* Reject raster fonts if we are looking for a unicode font. */
6135 && FontType
== RASTER_FONTTYPE
6136 && strncmp (charset
, "iso10646", 8) == 0)
6141 charset_list
= Fcons (build_string (charset
), Qnil
);
6143 /* Always prefer unicode. */
6145 = Fcons (build_string ("iso10646-1"),
6146 w32_to_all_x_charsets (lplf
->elfLogFont
.lfCharSet
));
6148 /* Loop through the charsets. */
6149 for ( ; CONSP (charset_list
); charset_list
= Fcdr (charset_list
))
6151 Lisp_Object this_charset
= Fcar (charset_list
);
6152 charset
= SDATA (this_charset
);
6154 /* Don't list raster fonts as unicode. */
6156 && FontType
== RASTER_FONTTYPE
6157 && strncmp (charset
, "iso10646", 8) == 0)
6160 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6163 /* List bold and italic variations if w32-enable-synthesized-fonts
6164 is non-nil and this is a plain font. */
6165 if (w32_enable_synthesized_fonts
6166 && lplf
->elfLogFont
.lfWeight
== FW_NORMAL
6167 && lplf
->elfLogFont
.lfItalic
== FALSE
)
6170 lplf
->elfLogFont
.lfWeight
= FW_BOLD
;
6171 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6174 lplf
->elfLogFont
.lfItalic
= TRUE
;
6175 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6178 lplf
->elfLogFont
.lfWeight
= FW_NORMAL
;
6179 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6189 enum_font_maybe_add_to_list (lpef
, logfont
, match_charset
, width
)
6192 char * match_charset
;
6197 if (!w32_to_x_font (logfont
, buf
, 100, match_charset
))
6200 if (NILP (lpef
->pattern
)
6201 || w32_font_match (buf
, SDATA (lpef
->pattern
)))
6203 /* Check if we already listed this font. This may happen if
6204 w32_enable_synthesized_fonts is non-nil, and there are real
6205 bold and italic versions of the font. */
6206 Lisp_Object font_name
= build_string (buf
);
6207 if (NILP (Fmember (font_name
, lpef
->list
)))
6209 Lisp_Object entry
= Fcons (font_name
, width
);
6210 lpef
->list
= Fcons (entry
, lpef
->list
);
6218 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
6220 NEWTEXTMETRIC
* lptm
;
6224 return EnumFontFamilies (lpef
->hdc
,
6225 lplf
->elfLogFont
.lfFaceName
,
6226 (FONTENUMPROC
) enum_font_cb2
,
6232 enum_fontex_cb2 (lplf
, lptm
, font_type
, lpef
)
6233 ENUMLOGFONTEX
* lplf
;
6234 NEWTEXTMETRICEX
* lptm
;
6238 /* We are not interested in the extra info we get back from the 'Ex
6239 version - only the fact that we get character set variations
6240 enumerated seperately. */
6241 return enum_font_cb2 ((ENUMLOGFONT
*) lplf
, (NEWTEXTMETRIC
*) lptm
,
6246 enum_fontex_cb1 (lplf
, lptm
, font_type
, lpef
)
6247 ENUMLOGFONTEX
* lplf
;
6248 NEWTEXTMETRICEX
* lptm
;
6252 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6253 FARPROC enum_font_families_ex
6254 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6255 /* We don't really expect EnumFontFamiliesEx to disappear once we
6256 get here, so don't bother handling it gracefully. */
6257 if (enum_font_families_ex
== NULL
)
6258 error ("gdi32.dll has disappeared!");
6259 return enum_font_families_ex (lpef
->hdc
,
6261 (FONTENUMPROC
) enum_fontex_cb2
,
6265 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
6266 and xterm.c in Emacs 20.3) */
6269 w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
)
6271 char *fontname
, *ptnstr
;
6272 Lisp_Object list
, tem
, newlist
= Qnil
;
6275 list
= Vw32_bdf_filename_alist
;
6276 ptnstr
= SDATA (pattern
);
6278 for ( ; CONSP (list
); list
= XCDR (list
))
6282 fontname
= SDATA (XCAR (tem
));
6283 else if (STRINGP (tem
))
6284 fontname
= SDATA (tem
);
6288 if (w32_font_match (fontname
, ptnstr
))
6290 newlist
= Fcons (XCAR (tem
), newlist
);
6292 if (max_names
>= 0 && n_fonts
>= max_names
)
6301 /* Return a list of names of available fonts matching PATTERN on frame
6302 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6303 to be listed. Frame F NULL means we have not yet created any
6304 frame, which means we can't get proper size info, as we don't have
6305 a device context to use for GetTextMetrics.
6306 MAXNAMES sets a limit on how many fonts to match. If MAXNAMES is
6307 negative, then all matching fonts are returned. */
6310 w32_list_fonts (f
, pattern
, size
, maxnames
)
6312 Lisp_Object pattern
;
6316 Lisp_Object patterns
, key
= Qnil
, tem
, tpat
;
6317 Lisp_Object list
= Qnil
, newlist
= Qnil
, second_best
= Qnil
;
6318 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6321 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6322 if (NILP (patterns
))
6323 patterns
= Fcons (pattern
, Qnil
);
6325 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6330 tpat
= XCAR (patterns
);
6332 if (!STRINGP (tpat
))
6335 /* Avoid expensive EnumFontFamilies functions if we are not
6336 going to be able to output one of these anyway. */
6337 codepage
= w32_codepage_for_font (SDATA (tpat
));
6338 if (codepage
!= CP_8BIT
&& codepage
!= CP_UNICODE
6339 && codepage
!= CP_DEFAULT
&& codepage
!= CP_UNKNOWN
6340 && !IsValidCodePage (codepage
))
6343 /* See if we cached the result for this particular query.
6344 The cache is an alist of the form:
6345 ((PATTERN (FONTNAME . WIDTH) ...) ...)
6347 if (tem
= XCDR (dpyinfo
->name_list_element
),
6348 !NILP (list
= Fassoc (tpat
, tem
)))
6350 list
= Fcdr_safe (list
);
6351 /* We have a cached list. Don't have to get the list again. */
6356 /* At first, put PATTERN in the cache. */
6361 /* Use EnumFontFamiliesEx where it is available, as it knows
6362 about character sets. Fall back to EnumFontFamilies for
6363 older versions of NT that don't support the 'Ex function. */
6364 x_to_w32_font (SDATA (tpat
), &ef
.logfont
);
6366 LOGFONT font_match_pattern
;
6367 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6368 FARPROC enum_font_families_ex
6369 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6371 /* We do our own pattern matching so we can handle wildcards. */
6372 font_match_pattern
.lfFaceName
[0] = 0;
6373 font_match_pattern
.lfPitchAndFamily
= 0;
6374 /* We can use the charset, because if it is a wildcard it will
6375 be DEFAULT_CHARSET anyway. */
6376 font_match_pattern
.lfCharSet
= ef
.logfont
.lfCharSet
;
6378 ef
.hdc
= GetDC (dpyinfo
->root_window
);
6380 if (enum_font_families_ex
)
6381 enum_font_families_ex (ef
.hdc
,
6382 &font_match_pattern
,
6383 (FONTENUMPROC
) enum_fontex_cb1
,
6386 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
,
6389 ReleaseDC (dpyinfo
->root_window
, ef
.hdc
);
6395 /* Make a list of the fonts we got back.
6396 Store that in the font cache for the display. */
6397 XSETCDR (dpyinfo
->name_list_element
,
6398 Fcons (Fcons (tpat
, list
),
6399 XCDR (dpyinfo
->name_list_element
)));
6402 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6404 newlist
= second_best
= Qnil
;
6406 /* Make a list of the fonts that have the right width. */
6407 for (; CONSP (list
); list
= XCDR (list
))
6414 if (NILP (XCAR (tem
)))
6418 newlist
= Fcons (XCAR (tem
), newlist
);
6420 if (maxnames
>= 0 && n_fonts
>= maxnames
)
6425 if (!INTEGERP (XCDR (tem
)))
6427 /* Since we don't yet know the size of the font, we must
6428 load it and try GetTextMetrics. */
6429 W32FontStruct thisinfo
;
6434 if (!x_to_w32_font (SDATA (XCAR (tem
)), &lf
))
6438 thisinfo
.bdf
= NULL
;
6439 thisinfo
.hfont
= CreateFontIndirect (&lf
);
6440 if (thisinfo
.hfont
== NULL
)
6443 hdc
= GetDC (dpyinfo
->root_window
);
6444 oldobj
= SelectObject (hdc
, thisinfo
.hfont
);
6445 if (GetTextMetrics (hdc
, &thisinfo
.tm
))
6446 XSETCDR (tem
, make_number (FONT_AVG_WIDTH (&thisinfo
)));
6448 XSETCDR (tem
, make_number (0));
6449 SelectObject (hdc
, oldobj
);
6450 ReleaseDC (dpyinfo
->root_window
, hdc
);
6451 DeleteObject (thisinfo
.hfont
);
6454 found_size
= XINT (XCDR (tem
));
6455 if (found_size
== size
)
6457 newlist
= Fcons (XCAR (tem
), newlist
);
6459 if (maxnames
>= 0 && n_fonts
>= maxnames
)
6462 /* keep track of the closest matching size in case
6463 no exact match is found. */
6464 else if (found_size
> 0)
6466 if (NILP (second_best
))
6469 else if (found_size
< size
)
6471 if (XINT (XCDR (second_best
)) > size
6472 || XINT (XCDR (second_best
)) < found_size
)
6477 if (XINT (XCDR (second_best
)) > size
6478 && XINT (XCDR (second_best
)) >
6485 if (!NILP (newlist
))
6487 else if (!NILP (second_best
))
6489 newlist
= Fcons (XCAR (second_best
), Qnil
);
6494 /* Include any bdf fonts. */
6495 if (n_fonts
< maxnames
|| maxnames
< 0)
6497 Lisp_Object combined
[2];
6498 combined
[0] = w32_list_bdf_fonts (pattern
, maxnames
- n_fonts
);
6499 combined
[1] = newlist
;
6500 newlist
= Fnconc (2, combined
);
6507 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6509 w32_get_font_info (f
, font_idx
)
6513 return (FRAME_W32_FONT_TABLE (f
) + font_idx
);
6518 w32_query_font (struct frame
*f
, char *fontname
)
6521 struct font_info
*pfi
;
6523 pfi
= FRAME_W32_FONT_TABLE (f
);
6525 for (i
= 0; i
< one_w32_display_info
.n_fonts
;i
++, pfi
++)
6527 if (stricmp (pfi
->name
, fontname
) == 0) return pfi
;
6533 /* Find a CCL program for a font specified by FONTP, and set the member
6534 `encoder' of the structure. */
6537 w32_find_ccl_program (fontp
)
6538 struct font_info
*fontp
;
6540 Lisp_Object list
, elt
;
6542 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
6546 && STRINGP (XCAR (elt
))
6547 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
6553 struct ccl_program
*ccl
6554 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6556 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
6559 fontp
->font_encoder
= ccl
;
6563 /* directory-files from dired.c. */
6564 Lisp_Object Fdirectory_files
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
, Lisp_Object
));
6567 /* Find BDF files in a specified directory. (use GCPRO when calling,
6568 as this calls lisp to get a directory listing). */
6570 w32_find_bdf_fonts_in_dir (Lisp_Object directory
)
6572 Lisp_Object filelist
, list
= Qnil
;
6575 if (!STRINGP (directory
))
6578 filelist
= Fdirectory_files (directory
, Qt
,
6579 build_string (".*\\.[bB][dD][fF]"), Qt
);
6581 for ( ; CONSP (filelist
); filelist
= XCDR (filelist
))
6583 Lisp_Object filename
= XCAR (filelist
);
6584 if (w32_BDF_to_x_font (SDATA (filename
), fontname
, 100))
6585 store_in_alist (&list
, build_string (fontname
), filename
);
6590 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts
, Sw32_find_bdf_fonts
,
6592 doc
: /* Return a list of BDF fonts in DIRECTORY.
6593 The list is suitable for appending to `w32-bdf-filename-alist'.
6594 Fonts which do not contain an xlfd description will not be included
6595 in the list. DIRECTORY may be a list of directories. */)
6597 Lisp_Object directory
;
6599 Lisp_Object list
= Qnil
;
6600 struct gcpro gcpro1
, gcpro2
;
6602 if (!CONSP (directory
))
6603 return w32_find_bdf_fonts_in_dir (directory
);
6605 for ( ; CONSP (directory
); directory
= XCDR (directory
))
6607 Lisp_Object pair
[2];
6610 GCPRO2 (directory
, list
);
6611 pair
[1] = w32_find_bdf_fonts_in_dir ( XCAR (directory
) );
6612 list
= Fnconc ( 2, pair
);
6619 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
6620 doc
: /* Internal function called by `color-defined-p', which see. */)
6622 Lisp_Object color
, frame
;
6625 FRAME_PTR f
= check_x_frame (frame
);
6627 CHECK_STRING (color
);
6629 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
6635 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
6636 doc
: /* Internal function called by `color-values', which see. */)
6638 Lisp_Object color
, frame
;
6641 FRAME_PTR f
= check_x_frame (frame
);
6643 CHECK_STRING (color
);
6645 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
6646 return list3 (make_number ((GetRValue (foo
.pixel
) << 8)
6647 | GetRValue (foo
.pixel
)),
6648 make_number ((GetGValue (foo
.pixel
) << 8)
6649 | GetGValue (foo
.pixel
)),
6650 make_number ((GetBValue (foo
.pixel
) << 8)
6651 | GetBValue (foo
.pixel
)));
6656 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
6657 doc
: /* Internal function called by `display-color-p', which see. */)
6659 Lisp_Object display
;
6661 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6663 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
6669 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
,
6670 Sx_display_grayscale_p
, 0, 1, 0,
6671 doc
: /* Return t if DISPLAY supports shades of gray.
6672 Note that color displays do support shades of gray.
6673 The optional argument DISPLAY specifies which display to ask about.
6674 DISPLAY should be either a frame or a display name (a string).
6675 If omitted or nil, that stands for the selected frame's display. */)
6677 Lisp_Object display
;
6679 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6681 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
6687 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
,
6688 Sx_display_pixel_width
, 0, 1, 0,
6689 doc
: /* Return the width in pixels of DISPLAY.
6690 The optional argument DISPLAY specifies which display to ask about.
6691 DISPLAY should be either a frame or a display name (a string).
6692 If omitted or nil, that stands for the selected frame's display. */)
6694 Lisp_Object display
;
6696 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6698 return make_number (dpyinfo
->width
);
6701 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
6702 Sx_display_pixel_height
, 0, 1, 0,
6703 doc
: /* Return the height in pixels of DISPLAY.
6704 The optional argument DISPLAY specifies which display to ask about.
6705 DISPLAY should be either a frame or a display name (a string).
6706 If omitted or nil, that stands for the selected frame's display. */)
6708 Lisp_Object display
;
6710 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6712 return make_number (dpyinfo
->height
);
6715 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
6717 doc
: /* Return the number of bitplanes of DISPLAY.
6718 The optional argument DISPLAY specifies which display to ask about.
6719 DISPLAY should be either a frame or a display name (a string).
6720 If omitted or nil, that stands for the selected frame's display. */)
6722 Lisp_Object display
;
6724 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6726 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
6729 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
6731 doc
: /* Return the number of color cells of DISPLAY.
6732 The optional argument DISPLAY specifies which display to ask about.
6733 DISPLAY should be either a frame or a display name (a string).
6734 If omitted or nil, that stands for the selected frame's display. */)
6736 Lisp_Object display
;
6738 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6742 hdc
= GetDC (dpyinfo
->root_window
);
6743 if (dpyinfo
->has_palette
)
6744 cap
= GetDeviceCaps (hdc
, SIZEPALETTE
);
6746 cap
= GetDeviceCaps (hdc
, NUMCOLORS
);
6748 /* We force 24+ bit depths to 24-bit, both to prevent an overflow
6749 and because probably is more meaningful on Windows anyway */
6751 cap
= 1 << min (dpyinfo
->n_planes
* dpyinfo
->n_cbits
, 24);
6753 ReleaseDC (dpyinfo
->root_window
, hdc
);
6755 return make_number (cap
);
6758 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
6759 Sx_server_max_request_size
,
6761 doc
: /* Return the maximum request size of the server of DISPLAY.
6762 The optional argument DISPLAY specifies which display to ask about.
6763 DISPLAY should be either a frame or a display name (a string).
6764 If omitted or nil, that stands for the selected frame's display. */)
6766 Lisp_Object display
;
6768 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6770 return make_number (1);
6773 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
6774 doc
: /* Return the "vendor ID" string of the W32 system (Microsoft).
6775 The optional argument DISPLAY specifies which display to ask about.
6776 DISPLAY should be either a frame or a display name (a string).
6777 If omitted or nil, that stands for the selected frame's display. */)
6779 Lisp_Object display
;
6781 return build_string ("Microsoft Corp.");
6784 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
6785 doc
: /* Return the version numbers of the server of DISPLAY.
6786 The value is a list of three integers: the major and minor
6787 version numbers of the X Protocol in use, and the distributor-specific
6788 release number. See also the function `x-server-vendor'.
6790 The optional argument DISPLAY specifies which display to ask about.
6791 DISPLAY should be either a frame or a display name (a string).
6792 If omitted or nil, that stands for the selected frame's display. */)
6794 Lisp_Object display
;
6796 return Fcons (make_number (w32_major_version
),
6797 Fcons (make_number (w32_minor_version
),
6798 Fcons (make_number (w32_build_number
), Qnil
)));
6801 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
6802 doc
: /* Return the number of screens on the server of DISPLAY.
6803 The optional argument DISPLAY specifies which display to ask about.
6804 DISPLAY should be either a frame or a display name (a string).
6805 If omitted or nil, that stands for the selected frame's display. */)
6807 Lisp_Object display
;
6809 return make_number (1);
6812 DEFUN ("x-display-mm-height", Fx_display_mm_height
,
6813 Sx_display_mm_height
, 0, 1, 0,
6814 doc
: /* Return the height in millimeters of DISPLAY.
6815 The optional argument DISPLAY specifies which display to ask about.
6816 DISPLAY should be either a frame or a display name (a string).
6817 If omitted or nil, that stands for the selected frame's display. */)
6819 Lisp_Object display
;
6821 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6825 hdc
= GetDC (dpyinfo
->root_window
);
6827 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
6829 ReleaseDC (dpyinfo
->root_window
, hdc
);
6831 return make_number (cap
);
6834 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
6835 doc
: /* Return the width in millimeters of DISPLAY.
6836 The optional argument DISPLAY specifies which display to ask about.
6837 DISPLAY should be either a frame or a display name (a string).
6838 If omitted or nil, that stands for the selected frame's display. */)
6840 Lisp_Object display
;
6842 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6847 hdc
= GetDC (dpyinfo
->root_window
);
6849 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
6851 ReleaseDC (dpyinfo
->root_window
, hdc
);
6853 return make_number (cap
);
6856 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
6857 Sx_display_backing_store
, 0, 1, 0,
6858 doc
: /* Return an indication of whether DISPLAY does backing store.
6859 The value may be `always', `when-mapped', or `not-useful'.
6860 The optional argument DISPLAY specifies which display to ask about.
6861 DISPLAY should be either a frame or a display name (a string).
6862 If omitted or nil, that stands for the selected frame's display. */)
6864 Lisp_Object display
;
6866 return intern ("not-useful");
6869 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
6870 Sx_display_visual_class
, 0, 1, 0,
6871 doc
: /* Return the visual class of DISPLAY.
6872 The value is one of the symbols `static-gray', `gray-scale',
6873 `static-color', `pseudo-color', `true-color', or `direct-color'.
6875 The optional argument DISPLAY specifies which display to ask about.
6876 DISPLAY should be either a frame or a display name (a string).
6877 If omitted or nil, that stands for the selected frame's display. */)
6879 Lisp_Object display
;
6881 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6882 Lisp_Object result
= Qnil
;
6884 if (dpyinfo
->has_palette
)
6885 result
= intern ("pseudo-color");
6886 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 1)
6887 result
= intern ("static-grey");
6888 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 4)
6889 result
= intern ("static-color");
6890 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
> 8)
6891 result
= intern ("true-color");
6896 DEFUN ("x-display-save-under", Fx_display_save_under
,
6897 Sx_display_save_under
, 0, 1, 0,
6898 doc
: /* Return t if DISPLAY supports the save-under feature.
6899 The optional argument DISPLAY specifies which display to ask about.
6900 DISPLAY should be either a frame or a display name (a string).
6901 If omitted or nil, that stands for the selected frame's display. */)
6903 Lisp_Object display
;
6910 register struct frame
*f
;
6912 return FRAME_PIXEL_WIDTH (f
);
6917 register struct frame
*f
;
6919 return FRAME_PIXEL_HEIGHT (f
);
6924 register struct frame
*f
;
6926 return FRAME_COLUMN_WIDTH (f
);
6931 register struct frame
*f
;
6933 return FRAME_LINE_HEIGHT (f
);
6938 register struct frame
*f
;
6940 return FRAME_W32_DISPLAY_INFO (f
)->n_planes
;
6943 /* Return the display structure for the display named NAME.
6944 Open a new connection if necessary. */
6946 struct w32_display_info
*
6947 x_display_info_for_name (name
)
6951 struct w32_display_info
*dpyinfo
;
6953 CHECK_STRING (name
);
6955 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
6957 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
6960 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
6965 /* Use this general default value to start with. */
6966 Vx_resource_name
= Vinvocation_name
;
6968 validate_x_resource_name ();
6970 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
6971 (char *) SDATA (Vx_resource_name
));
6974 error ("Cannot connect to server %s", SDATA (name
));
6977 XSETFASTINT (Vwindow_system_version
, 3);
6982 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
6983 1, 3, 0, doc
: /* Open a connection to a server.
6984 DISPLAY is the name of the display to connect to.
6985 Optional second arg XRM-STRING is a string of resources in xrdb format.
6986 If the optional third arg MUST-SUCCEED is non-nil,
6987 terminate Emacs if we can't open the connection. */)
6988 (display
, xrm_string
, must_succeed
)
6989 Lisp_Object display
, xrm_string
, must_succeed
;
6991 unsigned char *xrm_option
;
6992 struct w32_display_info
*dpyinfo
;
6994 /* If initialization has already been done, return now to avoid
6995 overwriting critical parts of one_w32_display_info. */
6999 CHECK_STRING (display
);
7000 if (! NILP (xrm_string
))
7001 CHECK_STRING (xrm_string
);
7004 if (! EQ (Vwindow_system
, intern ("w32")))
7005 error ("Not using Microsoft Windows");
7008 /* Allow color mapping to be defined externally; first look in user's
7009 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
7011 Lisp_Object color_file
;
7012 struct gcpro gcpro1
;
7014 color_file
= build_string ("~/rgb.txt");
7016 GCPRO1 (color_file
);
7018 if (NILP (Ffile_readable_p (color_file
)))
7020 Fexpand_file_name (build_string ("rgb.txt"),
7021 Fsymbol_value (intern ("data-directory")));
7023 Vw32_color_map
= Fw32_load_color_file (color_file
);
7027 if (NILP (Vw32_color_map
))
7028 Vw32_color_map
= Fw32_default_color_map ();
7030 /* Merge in system logical colors. */
7031 add_system_logical_colors_to_map (&Vw32_color_map
);
7033 if (! NILP (xrm_string
))
7034 xrm_option
= (unsigned char *) SDATA (xrm_string
);
7036 xrm_option
= (unsigned char *) 0;
7038 /* Use this general default value to start with. */
7039 /* First remove .exe suffix from invocation-name - it looks ugly. */
7041 char basename
[ MAX_PATH
], *str
;
7043 strcpy (basename
, SDATA (Vinvocation_name
));
7044 str
= strrchr (basename
, '.');
7046 Vinvocation_name
= build_string (basename
);
7048 Vx_resource_name
= Vinvocation_name
;
7050 validate_x_resource_name ();
7052 /* This is what opens the connection and sets x_current_display.
7053 This also initializes many symbols, such as those used for input. */
7054 dpyinfo
= w32_term_init (display
, xrm_option
,
7055 (char *) SDATA (Vx_resource_name
));
7059 if (!NILP (must_succeed
))
7060 fatal ("Cannot connect to server %s.\n",
7063 error ("Cannot connect to server %s", SDATA (display
));
7068 XSETFASTINT (Vwindow_system_version
, 3);
7072 DEFUN ("x-close-connection", Fx_close_connection
,
7073 Sx_close_connection
, 1, 1, 0,
7074 doc
: /* Close the connection to DISPLAY's server.
7075 For DISPLAY, specify either a frame or a display name (a string).
7076 If DISPLAY is nil, that stands for the selected frame's display. */)
7078 Lisp_Object display
;
7080 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
7083 if (dpyinfo
->reference_count
> 0)
7084 error ("Display still has frames on it");
7087 /* Free the fonts in the font table. */
7088 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7089 if (dpyinfo
->font_table
[i
].name
)
7091 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
7092 xfree (dpyinfo
->font_table
[i
].full_name
);
7093 xfree (dpyinfo
->font_table
[i
].name
);
7094 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
7096 x_destroy_all_bitmaps (dpyinfo
);
7098 x_delete_display (dpyinfo
);
7104 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
7105 doc
: /* Return the list of display names that Emacs has connections to. */)
7108 Lisp_Object tail
, result
;
7111 for (tail
= w32_display_name_list
; CONSP (tail
); tail
= XCDR (tail
))
7112 result
= Fcons (XCAR (XCAR (tail
)), result
);
7117 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
7118 doc
: /* This is a noop on W32 systems. */)
7120 Lisp_Object display
, on
;
7127 /***********************************************************************
7129 ***********************************************************************/
7131 DEFUN ("x-change-window-property", Fx_change_window_property
,
7132 Sx_change_window_property
, 2, 6, 0,
7133 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
7134 VALUE may be a string or a list of conses, numbers and/or strings.
7135 If an element in the list is a string, it is converted to
7136 an Atom and the value of the Atom is used. If an element is a cons,
7137 it is converted to a 32 bit number where the car is the 16 top bits and the
7138 cdr is the lower 16 bits.
7139 FRAME nil or omitted means use the selected frame.
7140 If TYPE is given and non-nil, it is the name of the type of VALUE.
7141 If TYPE is not given or nil, the type is STRING.
7142 FORMAT gives the size in bits of each element if VALUE is a list.
7143 It must be one of 8, 16 or 32.
7144 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
7145 If OUTER_P is non-nil, the property is changed for the outer X window of
7146 FRAME. Default is to change on the edit X window.
7149 (prop
, value
, frame
, type
, format
, outer_p
)
7150 Lisp_Object prop
, value
, frame
, type
, format
, outer_p
;
7152 #if 0 /* TODO : port window properties to W32 */
7153 struct frame
*f
= check_x_frame (frame
);
7156 CHECK_STRING (prop
);
7157 CHECK_STRING (value
);
7160 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7161 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7162 prop_atom
, XA_STRING
, 8, PropModeReplace
,
7163 SDATA (value
), SCHARS (value
));
7165 /* Make sure the property is set when we return. */
7166 XFlush (FRAME_W32_DISPLAY (f
));
7175 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
7176 Sx_delete_window_property
, 1, 2, 0,
7177 doc
: /* Remove window property PROP from X window of FRAME.
7178 FRAME nil or omitted means use the selected frame. Value is PROP. */)
7180 Lisp_Object prop
, frame
;
7182 #if 0 /* TODO : port window properties to W32 */
7184 struct frame
*f
= check_x_frame (frame
);
7187 CHECK_STRING (prop
);
7189 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7190 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
7192 /* Make sure the property is removed when we return. */
7193 XFlush (FRAME_W32_DISPLAY (f
));
7201 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
7203 doc
: /* Value is the value of window property PROP on FRAME.
7204 If FRAME is nil or omitted, use the selected frame. Value is nil
7205 if FRAME hasn't a property with name PROP or if PROP has no string
7208 Lisp_Object prop
, frame
;
7210 #if 0 /* TODO : port window properties to W32 */
7212 struct frame
*f
= check_x_frame (frame
);
7215 Lisp_Object prop_value
= Qnil
;
7216 char *tmp_data
= NULL
;
7219 unsigned long actual_size
, bytes_remaining
;
7221 CHECK_STRING (prop
);
7223 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7224 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7225 prop_atom
, 0, 0, False
, XA_STRING
,
7226 &actual_type
, &actual_format
, &actual_size
,
7227 &bytes_remaining
, (unsigned char **) &tmp_data
);
7230 int size
= bytes_remaining
;
7235 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7236 prop_atom
, 0, bytes_remaining
,
7238 &actual_type
, &actual_format
,
7239 &actual_size
, &bytes_remaining
,
7240 (unsigned char **) &tmp_data
);
7242 prop_value
= make_string (tmp_data
, size
);
7257 /***********************************************************************
7259 ***********************************************************************/
7261 /* Non-zero means an hourglass cursor is currently shown. */
7263 static int hourglass_shown_p
;
7265 /* Number of seconds to wait before displaying an hourglass cursor. */
7267 static Lisp_Object Vhourglass_delay
;
7269 /* Default number of seconds to wait before displaying an hourglass
7272 #define DEFAULT_HOURGLASS_DELAY 1
7274 /* Return non-zero if houglass timer has been started or hourglass is shown. */
7277 hourglass_started ()
7279 return hourglass_shown_p
|| hourglass_timer
;
7282 /* Cancel a currently active hourglass timer, and start a new one. */
7288 int secs
, msecs
= 0;
7289 struct frame
* f
= SELECTED_FRAME ();
7291 /* No cursors on non GUI frames. */
7292 if (!FRAME_W32_P (f
))
7295 cancel_hourglass ();
7297 if (INTEGERP (Vhourglass_delay
)
7298 && XINT (Vhourglass_delay
) > 0)
7299 secs
= XFASTINT (Vhourglass_delay
);
7300 else if (FLOATP (Vhourglass_delay
)
7301 && XFLOAT_DATA (Vhourglass_delay
) > 0)
7304 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
7305 secs
= XFASTINT (tem
);
7306 msecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000;
7309 secs
= DEFAULT_HOURGLASS_DELAY
;
7311 delay
= secs
* 1000 + msecs
;
7312 hourglass_hwnd
= FRAME_W32_WINDOW (f
);
7313 hourglass_timer
= SetTimer (hourglass_hwnd
, HOURGLASS_ID
, delay
, NULL
);
7317 /* Cancel the hourglass cursor timer if active, hide an hourglass
7323 if (hourglass_timer
)
7325 KillTimer (hourglass_hwnd
, hourglass_timer
);
7326 hourglass_timer
= 0;
7329 if (hourglass_shown_p
)
7334 /* Timer function of hourglass_timer.
7336 Display an hourglass cursor. Set the hourglass_p flag in display info
7337 to indicate that an hourglass cursor is shown. */
7343 if (!hourglass_shown_p
)
7345 f
->output_data
.w32
->hourglass_p
= 1;
7346 if (!menubar_in_use
&& !current_popup_menu
)
7347 SetCursor (f
->output_data
.w32
->hourglass_cursor
);
7348 hourglass_shown_p
= 1;
7353 /* Hide the hourglass cursor on all frames, if it is currently shown. */
7358 if (hourglass_shown_p
)
7360 struct frame
*f
= x_window_to_frame (&one_w32_display_info
,
7363 f
->output_data
.w32
->hourglass_p
= 0;
7364 SetCursor (f
->output_data
.w32
->current_cursor
);
7365 hourglass_shown_p
= 0;
7371 /***********************************************************************
7373 ***********************************************************************/
7375 static Lisp_Object x_create_tip_frame
P_ ((struct w32_display_info
*,
7376 Lisp_Object
, Lisp_Object
));
7377 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
7378 Lisp_Object
, int, int, int *, int *));
7380 /* The frame of a currently visible tooltip. */
7382 Lisp_Object tip_frame
;
7384 /* If non-nil, a timer started that hides the last tooltip when it
7387 Lisp_Object tip_timer
;
7390 /* If non-nil, a vector of 3 elements containing the last args
7391 with which x-show-tip was called. See there. */
7393 Lisp_Object last_show_tip_args
;
7395 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
7397 Lisp_Object Vx_max_tooltip_size
;
7401 unwind_create_tip_frame (frame
)
7404 Lisp_Object deleted
;
7406 deleted
= unwind_create_frame (frame
);
7407 if (EQ (deleted
, Qt
))
7417 /* Create a frame for a tooltip on the display described by DPYINFO.
7418 PARMS is a list of frame parameters. TEXT is the string to
7419 display in the tip frame. Value is the frame.
7421 Note that functions called here, esp. x_default_parameter can
7422 signal errors, for instance when a specified color name is
7423 undefined. We have to make sure that we're in a consistent state
7424 when this happens. */
7427 x_create_tip_frame (dpyinfo
, parms
, text
)
7428 struct w32_display_info
*dpyinfo
;
7429 Lisp_Object parms
, text
;
7432 Lisp_Object frame
, tem
;
7434 long window_prompting
= 0;
7436 int count
= SPECPDL_INDEX ();
7437 struct gcpro gcpro1
, gcpro2
, gcpro3
;
7439 int face_change_count_before
= face_change_count
;
7441 struct buffer
*old_buffer
;
7445 /* Use this general default value to start with until we know if
7446 this frame has a specified name. */
7447 Vx_resource_name
= Vinvocation_name
;
7450 kb
= dpyinfo
->terminal
->kboard
;
7452 kb
= &the_only_kboard
;
7455 /* Get the name of the frame to use for resource lookup. */
7456 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
7458 && !EQ (name
, Qunbound
)
7460 error ("Invalid frame name--not a string or nil");
7461 Vx_resource_name
= name
;
7464 GCPRO3 (parms
, name
, frame
);
7465 /* Make a frame without minibuffer nor mode-line. */
7467 f
->wants_modeline
= 0;
7468 XSETFRAME (frame
, f
);
7470 buffer
= Fget_buffer_create (build_string (" *tip*"));
7471 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
, Qnil
);
7472 old_buffer
= current_buffer
;
7473 set_buffer_internal_1 (XBUFFER (buffer
));
7474 current_buffer
->truncate_lines
= Qnil
;
7475 specbind (Qinhibit_read_only
, Qt
);
7476 specbind (Qinhibit_modification_hooks
, Qt
);
7479 set_buffer_internal_1 (old_buffer
);
7481 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
7482 record_unwind_protect (unwind_create_tip_frame
, frame
);
7484 /* By setting the output method, we're essentially saying that
7485 the frame is live, as per FRAME_LIVE_P. If we get a signal
7486 from this point on, x_destroy_window might screw up reference
7488 f
->terminal
= dpyinfo
->terminal
;
7489 f
->terminal
->reference_count
++;
7490 f
->output_method
= output_w32
;
7491 f
->output_data
.w32
=
7492 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
7493 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
7495 FRAME_FONTSET (f
) = -1;
7496 f
->icon_name
= Qnil
;
7498 #if 0 /* GLYPH_DEBUG TODO: image support. */
7499 image_cache_refcount
= FRAME_IMAGE_CACHE (f
)->refcount
;
7500 dpyinfo_refcount
= dpyinfo
->reference_count
;
7501 #endif /* GLYPH_DEBUG */
7503 FRAME_KBOARD (f
) = kb
;
7505 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
7506 f
->output_data
.w32
->explicit_parent
= 0;
7508 /* Set the name; the functions to which we pass f expect the name to
7510 if (EQ (name
, Qunbound
) || NILP (name
))
7512 f
->name
= build_string (dpyinfo
->w32_id_name
);
7513 f
->explicit_name
= 0;
7518 f
->explicit_name
= 1;
7519 /* use the frame's title when getting resources for this frame. */
7520 specbind (Qx_resource_name
, name
);
7523 f
->resx
= dpyinfo
->resx
;
7524 f
->resy
= dpyinfo
->resy
;
7526 #ifdef USE_FONT_BACKEND
7527 if (enable_font_backend
)
7529 /* Perhaps, we must allow frame parameter, say `font-backend',
7530 to specify which font backends to use. */
7531 register_font_driver (&w32font_driver
, f
);
7533 x_default_parameter (f
, parms
, Qfont_backend
, Qnil
,
7534 "fontBackend", "FontBackend", RES_TYPE_STRING
);
7536 #endif /* USE_FONT_BACKEND */
7538 /* Extract the window parameters from the supplied values
7539 that are needed to determine window geometry. */
7540 #ifdef USE_FONT_BACKEND
7541 if (enable_font_backend
)
7542 x_default_font_parameter (f
, parms
);
7544 #endif /* USE_FONT_BACKEND */
7548 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
7551 /* First, try whatever font the caller has specified. */
7554 tem
= Fquery_fontset (font
, Qnil
);
7556 font
= x_new_fontset (f
, tem
);
7558 font
= x_new_font (f
, SDATA (font
));
7561 /* Try out a font which we hope has bold and italic variations. */
7562 if (!STRINGP (font
))
7563 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
7564 if (! STRINGP (font
))
7565 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
7566 /* If those didn't work, look for something which will at least work. */
7567 if (! STRINGP (font
))
7568 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
7570 if (! STRINGP (font
))
7571 font
= build_string ("Fixedsys");
7573 x_default_parameter (f
, parms
, Qfont
, font
,
7574 "font", "Font", RES_TYPE_STRING
);
7577 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
7578 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
7579 /* This defaults to 2 in order to match xterm. We recognize either
7580 internalBorderWidth or internalBorder (which is what xterm calls
7582 if (NILP (Fassq (Qinternal_border_width
, parms
)))
7586 value
= w32_get_arg (parms
, Qinternal_border_width
,
7587 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
7588 if (! EQ (value
, Qunbound
))
7589 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
7592 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
7593 "internalBorderWidth", "internalBorderWidth",
7596 /* Also do the stuff which must be set before the window exists. */
7597 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
7598 "foreground", "Foreground", RES_TYPE_STRING
);
7599 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
7600 "background", "Background", RES_TYPE_STRING
);
7601 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
7602 "pointerColor", "Foreground", RES_TYPE_STRING
);
7603 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
7604 "cursorColor", "Foreground", RES_TYPE_STRING
);
7605 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
7606 "borderColor", "BorderColor", RES_TYPE_STRING
);
7608 /* Init faces before x_default_parameter is called for scroll-bar
7609 parameters because that function calls x_set_scroll_bar_width,
7610 which calls change_frame_size, which calls Fset_window_buffer,
7611 which runs hooks, which call Fvertical_motion. At the end, we
7612 end up in init_iterator with a null face cache, which should not
7614 init_frame_faces (f
);
7616 f
->output_data
.w32
->dwStyle
= WS_BORDER
| WS_POPUP
| WS_DISABLED
;
7617 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
7619 window_prompting
= x_figure_window_size (f
, parms
, 0);
7621 /* No fringes on tip frame. */
7623 f
->left_fringe_width
= 0;
7624 f
->right_fringe_width
= 0;
7627 my_create_tip_window (f
);
7632 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
7633 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
7634 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
7635 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
7636 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
7637 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
7639 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
7640 Change will not be effected unless different from the current
7642 width
= FRAME_COLS (f
);
7643 height
= FRAME_LINES (f
);
7644 FRAME_LINES (f
) = 0;
7645 SET_FRAME_COLS (f
, 0);
7646 change_frame_size (f
, height
, width
, 1, 0, 0);
7648 /* Add `tooltip' frame parameter's default value. */
7649 if (NILP (Fframe_parameter (frame
, intern ("tooltip"))))
7650 Fmodify_frame_parameters (frame
, Fcons (Fcons (intern ("tooltip"), Qt
),
7653 /* Set up faces after all frame parameters are known. This call
7654 also merges in face attributes specified for new frames.
7656 Frame parameters may be changed if .Xdefaults contains
7657 specifications for the default font. For example, if there is an
7658 `Emacs.default.attributeBackground: pink', the `background-color'
7659 attribute of the frame get's set, which let's the internal border
7660 of the tooltip frame appear in pink. Prevent this. */
7662 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
7664 /* Set tip_frame here, so that */
7666 call1 (Qface_set_after_frame_default
, frame
);
7668 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
7669 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
7677 /* It is now ok to make the frame official even if we get an error
7678 below. And the frame needs to be on Vframe_list or making it
7679 visible won't work. */
7680 Vframe_list
= Fcons (frame
, Vframe_list
);
7682 /* Now that the frame is official, it counts as a reference to
7684 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
7686 /* Setting attributes of faces of the tooltip frame from resources
7687 and similar will increment face_change_count, which leads to the
7688 clearing of all current matrices. Since this isn't necessary
7689 here, avoid it by resetting face_change_count to the value it
7690 had before we created the tip frame. */
7691 face_change_count
= face_change_count_before
;
7693 /* Discard the unwind_protect. */
7694 return unbind_to (count
, frame
);
7698 /* Compute where to display tip frame F. PARMS is the list of frame
7699 parameters for F. DX and DY are specified offsets from the current
7700 location of the mouse. WIDTH and HEIGHT are the width and height
7701 of the tooltip. Return coordinates relative to the root window of
7702 the display in *ROOT_X, and *ROOT_Y. */
7705 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
7707 Lisp_Object parms
, dx
, dy
;
7709 int *root_x
, *root_y
;
7711 Lisp_Object left
, top
;
7712 int min_x
, min_y
, max_x
, max_y
;
7714 /* User-specified position? */
7715 left
= Fcdr (Fassq (Qleft
, parms
));
7716 top
= Fcdr (Fassq (Qtop
, parms
));
7718 /* Move the tooltip window where the mouse pointer is. Resize and
7720 if (!INTEGERP (left
) || !INTEGERP (top
))
7724 /* Default min and max values. */
7727 max_x
= FRAME_W32_DISPLAY_INFO (f
)->width
;
7728 max_y
= FRAME_W32_DISPLAY_INFO (f
)->height
;
7736 /* If multiple monitor support is available, constrain the tip onto
7737 the current monitor. This improves the above by allowing negative
7738 co-ordinates if monitor positions are such that they are valid, and
7739 snaps a tooltip onto a single monitor if we are close to the edge
7740 where it would otherwise flow onto the other monitor (or into
7741 nothingness if there is a gap in the overlap). */
7742 if (monitor_from_point_fn
&& get_monitor_info_fn
)
7744 struct MONITOR_INFO info
;
7746 = monitor_from_point_fn (pt
, MONITOR_DEFAULT_TO_NEAREST
);
7747 info
.cbSize
= sizeof (info
);
7749 if (get_monitor_info_fn (monitor
, &info
))
7751 min_x
= info
.rcWork
.left
;
7752 min_y
= info
.rcWork
.top
;
7753 max_x
= info
.rcWork
.right
;
7754 max_y
= info
.rcWork
.bottom
;
7760 *root_y
= XINT (top
);
7761 else if (*root_y
+ XINT (dy
) <= min_y
)
7762 *root_y
= min_y
; /* Can happen for negative dy */
7763 else if (*root_y
+ XINT (dy
) + height
<= max_y
)
7764 /* It fits below the pointer */
7765 *root_y
+= XINT (dy
);
7766 else if (height
+ XINT (dy
) + min_y
<= *root_y
)
7767 /* It fits above the pointer. */
7768 *root_y
-= height
+ XINT (dy
);
7770 /* Put it on the top. */
7773 if (INTEGERP (left
))
7774 *root_x
= XINT (left
);
7775 else if (*root_x
+ XINT (dx
) <= min_x
)
7776 *root_x
= 0; /* Can happen for negative dx */
7777 else if (*root_x
+ XINT (dx
) + width
<= max_x
)
7778 /* It fits to the right of the pointer. */
7779 *root_x
+= XINT (dx
);
7780 else if (width
+ XINT (dx
) + min_x
<= *root_x
)
7781 /* It fits to the left of the pointer. */
7782 *root_x
-= width
+ XINT (dx
);
7784 /* Put it left justified on the screen -- it ought to fit that way. */
7789 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
7790 doc
: /* Show STRING in a \"tooltip\" window on frame FRAME.
7791 A tooltip window is a small window displaying a string.
7793 This is an internal function; Lisp code should call `tooltip-show'.
7795 FRAME nil or omitted means use the selected frame.
7797 PARMS is an optional list of frame parameters which can be
7798 used to change the tooltip's appearance.
7800 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
7801 means use the default timeout of 5 seconds.
7803 If the list of frame parameters PARMS contains a `left' parameter,
7804 the tooltip is displayed at that x-position. Otherwise it is
7805 displayed at the mouse position, with offset DX added (default is 5 if
7806 DX isn't specified). Likewise for the y-position; if a `top' frame
7807 parameter is specified, it determines the y-position of the tooltip
7808 window, otherwise it is displayed at the mouse position, with offset
7809 DY added (default is -10).
7811 A tooltip's maximum size is specified by `x-max-tooltip-size'.
7812 Text larger than the specified size is clipped. */)
7813 (string
, frame
, parms
, timeout
, dx
, dy
)
7814 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
7819 struct buffer
*old_buffer
;
7820 struct text_pos pos
;
7821 int i
, width
, height
;
7822 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
7823 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
7824 int count
= SPECPDL_INDEX ();
7826 specbind (Qinhibit_redisplay
, Qt
);
7828 GCPRO4 (string
, parms
, frame
, timeout
);
7830 CHECK_STRING (string
);
7831 f
= check_x_frame (frame
);
7833 timeout
= make_number (5);
7835 CHECK_NATNUM (timeout
);
7838 dx
= make_number (5);
7843 dy
= make_number (-10);
7847 if (NILP (last_show_tip_args
))
7848 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
7850 if (!NILP (tip_frame
))
7852 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
7853 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
7854 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
7856 if (EQ (frame
, last_frame
)
7857 && !NILP (Fequal (last_string
, string
))
7858 && !NILP (Fequal (last_parms
, parms
)))
7860 struct frame
*f
= XFRAME (tip_frame
);
7862 /* Only DX and DY have changed. */
7863 if (!NILP (tip_timer
))
7865 Lisp_Object timer
= tip_timer
;
7867 call1 (Qcancel_timer
, timer
);
7871 compute_tip_xy (f
, parms
, dx
, dy
, FRAME_PIXEL_WIDTH (f
),
7872 FRAME_PIXEL_HEIGHT (f
), &root_x
, &root_y
);
7874 /* Put tooltip in topmost group and in position. */
7875 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
7876 root_x
, root_y
, 0, 0,
7877 SWP_NOSIZE
| SWP_NOACTIVATE
);
7879 /* Ensure tooltip is on top of other topmost windows (eg menus). */
7880 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
7882 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
7889 /* Hide a previous tip, if any. */
7892 ASET (last_show_tip_args
, 0, string
);
7893 ASET (last_show_tip_args
, 1, frame
);
7894 ASET (last_show_tip_args
, 2, parms
);
7896 /* Add default values to frame parameters. */
7897 if (NILP (Fassq (Qname
, parms
)))
7898 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
7899 if (NILP (Fassq (Qinternal_border_width
, parms
)))
7900 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
7901 if (NILP (Fassq (Qborder_width
, parms
)))
7902 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
7903 if (NILP (Fassq (Qborder_color
, parms
)))
7904 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
7905 if (NILP (Fassq (Qbackground_color
, parms
)))
7906 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
7909 /* Block input until the tip has been fully drawn, to avoid crashes
7910 when drawing tips in menus. */
7913 /* Create a frame for the tooltip, and record it in the global
7914 variable tip_frame. */
7915 frame
= x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f
), parms
, string
);
7918 /* Set up the frame's root window. */
7919 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
7920 w
->left_col
= w
->top_line
= make_number (0);
7922 if (CONSP (Vx_max_tooltip_size
)
7923 && INTEGERP (XCAR (Vx_max_tooltip_size
))
7924 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
7925 && INTEGERP (XCDR (Vx_max_tooltip_size
))
7926 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
7928 w
->total_cols
= XCAR (Vx_max_tooltip_size
);
7929 w
->total_lines
= XCDR (Vx_max_tooltip_size
);
7933 w
->total_cols
= make_number (80);
7934 w
->total_lines
= make_number (40);
7937 FRAME_TOTAL_COLS (f
) = XINT (w
->total_cols
);
7939 w
->pseudo_window_p
= 1;
7941 /* Display the tooltip text in a temporary buffer. */
7942 old_buffer
= current_buffer
;
7943 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
7944 current_buffer
->truncate_lines
= Qnil
;
7945 clear_glyph_matrix (w
->desired_matrix
);
7946 clear_glyph_matrix (w
->current_matrix
);
7947 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
7948 try_window (FRAME_ROOT_WINDOW (f
), pos
, 0);
7950 /* Compute width and height of the tooltip. */
7952 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
7954 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
7958 /* Stop at the first empty row at the end. */
7959 if (!row
->enabled_p
|| !row
->displays_text_p
)
7962 /* Let the row go over the full width of the frame. */
7963 row
->full_width_p
= 1;
7965 #ifdef TODO /* Investigate why some fonts need more width than is
7966 calculated for some tooltips. */
7967 /* There's a glyph at the end of rows that is use to place
7968 the cursor there. Don't include the width of this glyph. */
7969 if (row
->used
[TEXT_AREA
])
7971 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
7972 row_width
= row
->pixel_width
- last
->pixel_width
;
7976 row_width
= row
->pixel_width
;
7978 /* TODO: find why tips do not draw along baseline as instructed. */
7979 height
+= row
->height
;
7980 width
= max (width
, row_width
);
7983 /* Add the frame's internal border to the width and height the X
7984 window should have. */
7985 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
7986 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
7988 /* Move the tooltip window where the mouse pointer is. Resize and
7990 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
7993 /* Adjust Window size to take border into account. */
7995 rect
.left
= rect
.top
= 0;
7997 rect
.bottom
= height
;
7998 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
7999 FRAME_EXTERNAL_MENU_BAR (f
));
8001 /* Position and size tooltip, and put it in the topmost group.
8002 The add-on of 3 to the 5th argument is a kludge: without it,
8003 some fonts cause the last character of the tip to be truncated,
8004 for some obscure reason. */
8005 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
8006 root_x
, root_y
, rect
.right
- rect
.left
+ 3,
8007 rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
8009 /* Ensure tooltip is on top of other topmost windows (eg menus). */
8010 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
8012 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
8014 /* Let redisplay know that we have made the frame visible already. */
8015 f
->async_visible
= 1;
8017 ShowWindow (FRAME_W32_WINDOW (f
), SW_SHOWNOACTIVATE
);
8020 /* Draw into the window. */
8021 w
->must_be_updated_p
= 1;
8022 update_single_window (w
, 1);
8026 /* Restore original current buffer. */
8027 set_buffer_internal_1 (old_buffer
);
8028 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
8031 /* Let the tip disappear after timeout seconds. */
8032 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
8033 intern ("x-hide-tip"));
8036 return unbind_to (count
, Qnil
);
8040 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
8041 doc
: /* Hide the current tooltip window, if there is any.
8042 Value is t if tooltip was open, nil otherwise. */)
8046 Lisp_Object deleted
, frame
, timer
;
8047 struct gcpro gcpro1
, gcpro2
;
8049 /* Return quickly if nothing to do. */
8050 if (NILP (tip_timer
) && NILP (tip_frame
))
8055 GCPRO2 (frame
, timer
);
8056 tip_frame
= tip_timer
= deleted
= Qnil
;
8058 count
= SPECPDL_INDEX ();
8059 specbind (Qinhibit_redisplay
, Qt
);
8060 specbind (Qinhibit_quit
, Qt
);
8063 call1 (Qcancel_timer
, timer
);
8067 Fdelete_frame (frame
, Qnil
);
8072 return unbind_to (count
, deleted
);
8077 /***********************************************************************
8078 File selection dialog
8079 ***********************************************************************/
8080 extern Lisp_Object Qfile_name_history
;
8082 /* Callback for altering the behaviour of the Open File dialog.
8083 Makes the Filename text field contain "Current Directory" and be
8084 read-only when "Directories" is selected in the filter. This
8085 allows us to work around the fact that the standard Open File
8086 dialog does not support directories. */
8088 file_dialog_callback (hwnd
, msg
, wParam
, lParam
)
8094 if (msg
== WM_NOTIFY
)
8096 OFNOTIFY
* notify
= (OFNOTIFY
*)lParam
;
8097 /* Detect when the Filter dropdown is changed. */
8098 if (notify
->hdr
.code
== CDN_TYPECHANGE
8099 || notify
->hdr
.code
== CDN_INITDONE
)
8101 HWND dialog
= GetParent (hwnd
);
8102 HWND edit_control
= GetDlgItem (dialog
, FILE_NAME_TEXT_FIELD
);
8104 /* Directories is in index 2. */
8105 if (notify
->lpOFN
->nFilterIndex
== 2)
8107 CommDlg_OpenSave_SetControlText (dialog
, FILE_NAME_TEXT_FIELD
,
8108 "Current Directory");
8109 EnableWindow (edit_control
, FALSE
);
8113 /* Don't override default filename on init done. */
8114 if (notify
->hdr
.code
== CDN_TYPECHANGE
)
8115 CommDlg_OpenSave_SetControlText (dialog
,
8116 FILE_NAME_TEXT_FIELD
, "");
8117 EnableWindow (edit_control
, TRUE
);
8124 /* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
8125 we end up with the old file dialogs. Define a big enough struct for the
8126 new dialog to trick GetOpenFileName into giving us the new dialogs on
8127 Windows 2000 and XP. */
8130 OPENFILENAME real_details
;
8137 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 5, 0,
8138 doc
: /* Read file name, prompting with PROMPT in directory DIR.
8139 Use a file selection dialog.
8140 Select DEFAULT-FILENAME in the dialog's file selection box, if
8141 specified. Ensure that file exists if MUSTMATCH is non-nil.
8142 If ONLY-DIR-P is non-nil, the user can only select directories. */)
8143 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
)
8144 Lisp_Object prompt
, dir
, default_filename
, mustmatch
, only_dir_p
;
8146 struct frame
*f
= SELECTED_FRAME ();
8147 Lisp_Object file
= Qnil
;
8148 int count
= SPECPDL_INDEX ();
8149 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
8150 char filename
[MAX_PATH
+ 1];
8151 char init_dir
[MAX_PATH
+ 1];
8152 int default_filter_index
= 1; /* 1: All Files, 2: Directories only */
8154 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
, file
);
8155 CHECK_STRING (prompt
);
8158 /* Create the dialog with PROMPT as title, using DIR as initial
8159 directory and using "*" as pattern. */
8160 dir
= Fexpand_file_name (dir
, Qnil
);
8161 strncpy (init_dir
, SDATA (ENCODE_FILE (dir
)), MAX_PATH
);
8162 init_dir
[MAX_PATH
] = '\0';
8163 unixtodos_filename (init_dir
);
8165 if (STRINGP (default_filename
))
8167 char *file_name_only
;
8168 char *full_path_name
= SDATA (ENCODE_FILE (default_filename
));
8170 unixtodos_filename (full_path_name
);
8172 file_name_only
= strrchr (full_path_name
, '\\');
8173 if (!file_name_only
)
8174 file_name_only
= full_path_name
;
8178 strncpy (filename
, file_name_only
, MAX_PATH
);
8179 filename
[MAX_PATH
] = '\0';
8185 NEWOPENFILENAME new_file_details
;
8186 BOOL file_opened
= FALSE
;
8187 OPENFILENAME
* file_details
= &new_file_details
.real_details
;
8189 /* Prevent redisplay. */
8190 specbind (Qinhibit_redisplay
, Qt
);
8193 bzero (&new_file_details
, sizeof (new_file_details
));
8194 /* Apparently NT4 crashes if you give it an unexpected size.
8195 I'm not sure about Windows 9x, so play it safe. */
8196 if (w32_major_version
> 4 && w32_major_version
< 95)
8197 file_details
->lStructSize
= sizeof (NEWOPENFILENAME
);
8199 file_details
->lStructSize
= sizeof (OPENFILENAME
);
8201 file_details
->hwndOwner
= FRAME_W32_WINDOW (f
);
8202 /* Undocumented Bug in Common File Dialog:
8203 If a filter is not specified, shell links are not resolved. */
8204 file_details
->lpstrFilter
= "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
8205 file_details
->lpstrFile
= filename
;
8206 file_details
->nMaxFile
= sizeof (filename
);
8207 file_details
->lpstrInitialDir
= init_dir
;
8208 file_details
->lpstrTitle
= SDATA (prompt
);
8210 if (! NILP (only_dir_p
))
8211 default_filter_index
= 2;
8213 file_details
->nFilterIndex
= default_filter_index
;
8215 file_details
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
8216 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
8217 if (!NILP (mustmatch
))
8219 /* Require that the path to the parent directory exists. */
8220 file_details
->Flags
|= OFN_PATHMUSTEXIST
;
8221 /* If we are looking for a file, require that it exists. */
8222 if (NILP (only_dir_p
))
8223 file_details
->Flags
|= OFN_FILEMUSTEXIST
;
8226 file_details
->lpfnHook
= (LPOFNHOOKPROC
) file_dialog_callback
;
8228 file_opened
= GetOpenFileName (file_details
);
8234 dostounix_filename (filename
);
8236 if (file_details
->nFilterIndex
== 2)
8238 /* "Directories" selected - strip dummy file name. */
8239 char * last
= strrchr (filename
, '/');
8243 file
= DECODE_FILE (build_string (filename
));
8245 /* User cancelled the dialog without making a selection. */
8246 else if (!CommDlgExtendedError ())
8248 /* An error occurred, fallback on reading from the mini-buffer. */
8250 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
8251 dir
, mustmatch
, dir
, Qfile_name_history
,
8252 default_filename
, Qnil
);
8254 file
= unbind_to (count
, file
);
8259 /* Make "Cancel" equivalent to C-g. */
8261 Fsignal (Qquit
, Qnil
);
8263 return unbind_to (count
, file
);
8268 /***********************************************************************
8269 w32 specialized functions
8270 ***********************************************************************/
8272 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 2, 0,
8273 doc
: /* Select a font for the named FRAME using the W32 font dialog.
8274 Return an X-style font string corresponding to the selection.
8276 If FRAME is omitted or nil, it defaults to the selected frame.
8277 If INCLUDE-PROPORTIONAL is non-nil, include proportional fonts
8278 in the font selection dialog. */)
8279 (frame
, include_proportional
)
8280 Lisp_Object frame
, include_proportional
;
8282 FRAME_PTR f
= check_x_frame (frame
);
8290 bzero (&cf
, sizeof (cf
));
8291 bzero (&lf
, sizeof (lf
));
8293 cf
.lStructSize
= sizeof (cf
);
8294 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
8295 cf
.Flags
= CF_FORCEFONTEXIST
| CF_SCREENFONTS
| CF_NOVERTFONTS
;
8297 /* Unless include_proportional is non-nil, limit the selection to
8298 monospaced fonts. */
8299 if (NILP (include_proportional
))
8300 cf
.Flags
|= CF_FIXEDPITCHONLY
;
8304 /* Initialize as much of the font details as we can from the current
8306 hdc
= GetDC (FRAME_W32_WINDOW (f
));
8307 oldobj
= SelectObject (hdc
, FRAME_FONT (f
)->hfont
);
8308 GetTextFace (hdc
, LF_FACESIZE
, lf
.lfFaceName
);
8309 if (GetTextMetrics (hdc
, &tm
))
8311 lf
.lfHeight
= tm
.tmInternalLeading
- tm
.tmHeight
;
8312 lf
.lfWeight
= tm
.tmWeight
;
8313 lf
.lfItalic
= tm
.tmItalic
;
8314 lf
.lfUnderline
= tm
.tmUnderlined
;
8315 lf
.lfStrikeOut
= tm
.tmStruckOut
;
8316 lf
.lfCharSet
= tm
.tmCharSet
;
8317 cf
.Flags
|= CF_INITTOLOGFONTSTRUCT
;
8319 SelectObject (hdc
, oldobj
);
8320 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
8322 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100, NULL
))
8325 return build_string (buf
);
8328 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
,
8329 Sw32_send_sys_command
, 1, 2, 0,
8330 doc
: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
8331 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
8332 to minimize), #xf120 to restore frame to original size, and #xf100
8333 to activate the menubar for keyboard access. #xf140 activates the
8334 screen saver if defined.
8336 If optional parameter FRAME is not specified, use selected frame. */)
8338 Lisp_Object command
, frame
;
8340 FRAME_PTR f
= check_x_frame (frame
);
8342 CHECK_NUMBER (command
);
8344 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
8349 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
8350 doc
: /* Get Windows to perform OPERATION on DOCUMENT.
8351 This is a wrapper around the ShellExecute system function, which
8352 invokes the application registered to handle OPERATION for DOCUMENT.
8354 OPERATION is either nil or a string that names a supported operation.
8355 What operations can be used depends on the particular DOCUMENT and its
8356 handler application, but typically it is one of the following common
8359 \"open\" - open DOCUMENT, which could be a file, a directory, or an
8360 executable program. If it is an application, that
8361 application is launched in the current buffer's default
8362 directory. Otherwise, the application associated with
8363 DOCUMENT is launched in the buffer's default directory.
8364 \"print\" - print DOCUMENT, which must be a file
8365 \"explore\" - start the Windows Explorer on DOCUMENT
8366 \"edit\" - launch an editor and open DOCUMENT for editing; which
8367 editor is launched depends on the association for the
8369 \"find\" - initiate search starting from DOCUMENT which must specify
8371 nil - invoke the default OPERATION, or \"open\" if default is
8372 not defined or unavailable
8374 DOCUMENT is typically the name of a document file or a URL, but can
8375 also be a program executable to run, or a directory to open in the
8378 If DOCUMENT is a program executable, the optional third arg PARAMETERS
8379 can be a string containing command line parameters that will be passed
8380 to the program; otherwise, PARAMETERS should be nil or unspecified.
8382 Optional fourth argument SHOW-FLAG can be used to control how the
8383 application will be displayed when it is invoked. If SHOW-FLAG is nil
8384 or unspecified, the application is displayed normally, otherwise it is
8385 an integer representing a ShowWindow flag:
8390 6 - start minimized */)
8391 (operation
, document
, parameters
, show_flag
)
8392 Lisp_Object operation
, document
, parameters
, show_flag
;
8394 Lisp_Object current_dir
;
8396 CHECK_STRING (document
);
8398 /* Encode filename, current directory and parameters. */
8399 current_dir
= ENCODE_FILE (current_buffer
->directory
);
8400 document
= ENCODE_FILE (document
);
8401 if (STRINGP (parameters
))
8402 parameters
= ENCODE_SYSTEM (parameters
);
8404 if ((int) ShellExecute (NULL
,
8405 (STRINGP (operation
) ?
8406 SDATA (operation
) : NULL
),
8408 (STRINGP (parameters
) ?
8409 SDATA (parameters
) : NULL
),
8410 SDATA (current_dir
),
8411 (INTEGERP (show_flag
) ?
8412 XINT (show_flag
) : SW_SHOWDEFAULT
))
8415 error ("ShellExecute failed: %s", w32_strerror (0));
8418 /* Lookup virtual keycode from string representing the name of a
8419 non-ascii keystroke into the corresponding virtual key, using
8420 lispy_function_keys. */
8422 lookup_vk_code (char *key
)
8426 for (i
= 0; i
< 256; i
++)
8427 if (lispy_function_keys
[i
]
8428 && strcmp (lispy_function_keys
[i
], key
) == 0)
8434 /* Convert a one-element vector style key sequence to a hot key
8437 w32_parse_hot_key (key
)
8440 /* Copied from Fdefine_key and store_in_keymap. */
8441 register Lisp_Object c
;
8445 struct gcpro gcpro1
;
8449 if (XFASTINT (Flength (key
)) != 1)
8454 c
= Faref (key
, make_number (0));
8456 if (CONSP (c
) && lucid_event_type_list_p (c
))
8457 c
= Fevent_convert_list (c
);
8461 if (! INTEGERP (c
) && ! SYMBOLP (c
))
8462 error ("Key definition is invalid");
8464 /* Work out the base key and the modifiers. */
8467 c
= parse_modifiers (c
);
8468 lisp_modifiers
= XINT (Fcar (Fcdr (c
)));
8472 vk_code
= lookup_vk_code (SDATA (SYMBOL_NAME (c
)));
8474 else if (INTEGERP (c
))
8476 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
8477 /* Many ascii characters are their own virtual key code. */
8478 vk_code
= XINT (c
) & CHARACTERBITS
;
8481 if (vk_code
< 0 || vk_code
> 255)
8484 if ((lisp_modifiers
& meta_modifier
) != 0
8485 && !NILP (Vw32_alt_is_meta
))
8486 lisp_modifiers
|= alt_modifier
;
8488 /* Supply defs missing from mingw32. */
8490 #define MOD_ALT 0x0001
8491 #define MOD_CONTROL 0x0002
8492 #define MOD_SHIFT 0x0004
8493 #define MOD_WIN 0x0008
8496 /* Convert lisp modifiers to Windows hot-key form. */
8497 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
8498 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
8499 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
8500 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
8502 return HOTKEY (vk_code
, w32_modifiers
);
8505 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
,
8506 Sw32_register_hot_key
, 1, 1, 0,
8507 doc
: /* Register KEY as a hot-key combination.
8508 Certain key combinations like Alt-Tab are reserved for system use on
8509 Windows, and therefore are normally intercepted by the system. However,
8510 most of these key combinations can be received by registering them as
8511 hot-keys, overriding their special meaning.
8513 KEY must be a one element key definition in vector form that would be
8514 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
8515 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
8516 is always interpreted as the Windows modifier keys.
8518 The return value is the hotkey-id if registered, otherwise nil. */)
8522 key
= w32_parse_hot_key (key
);
8524 if (!NILP (key
) && NILP (Fmemq (key
, w32_grabbed_keys
)))
8526 /* Reuse an empty slot if possible. */
8527 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
8529 /* Safe to add new key to list, even if we have focus. */
8531 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
8533 XSETCAR (item
, key
);
8535 /* Notify input thread about new hot-key definition, so that it
8536 takes effect without needing to switch focus. */
8537 #ifdef USE_LISP_UNION_TYPE
8538 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
8541 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
8549 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
,
8550 Sw32_unregister_hot_key
, 1, 1, 0,
8551 doc
: /* Unregister KEY as a hot-key combination. */)
8557 if (!INTEGERP (key
))
8558 key
= w32_parse_hot_key (key
);
8560 item
= Fmemq (key
, w32_grabbed_keys
);
8564 /* Notify input thread about hot-key definition being removed, so
8565 that it takes effect without needing focus switch. */
8566 #ifdef USE_LISP_UNION_TYPE
8567 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
8568 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
.i
))
8570 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
8571 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
8575 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
8582 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
,
8583 Sw32_registered_hot_keys
, 0, 0, 0,
8584 doc
: /* Return list of registered hot-key IDs. */)
8587 return Fdelq (Qnil
, Fcopy_sequence (w32_grabbed_keys
));
8590 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
,
8591 Sw32_reconstruct_hot_key
, 1, 1, 0,
8592 doc
: /* Convert hot-key ID to a lisp key combination.
8593 usage: (w32-reconstruct-hot-key ID) */)
8595 Lisp_Object hotkeyid
;
8597 int vk_code
, w32_modifiers
;
8600 CHECK_NUMBER (hotkeyid
);
8602 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
8603 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
8605 if (vk_code
< 256 && lispy_function_keys
[vk_code
])
8606 key
= intern (lispy_function_keys
[vk_code
]);
8608 key
= make_number (vk_code
);
8610 key
= Fcons (key
, Qnil
);
8611 if (w32_modifiers
& MOD_SHIFT
)
8612 key
= Fcons (Qshift
, key
);
8613 if (w32_modifiers
& MOD_CONTROL
)
8614 key
= Fcons (Qctrl
, key
);
8615 if (w32_modifiers
& MOD_ALT
)
8616 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
8617 if (w32_modifiers
& MOD_WIN
)
8618 key
= Fcons (Qhyper
, key
);
8623 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
,
8624 Sw32_toggle_lock_key
, 1, 2, 0,
8625 doc
: /* Toggle the state of the lock key KEY.
8626 KEY can be `capslock', `kp-numlock', or `scroll'.
8627 If the optional parameter NEW-STATE is a number, then the state of KEY
8628 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
8630 Lisp_Object key
, new_state
;
8634 if (EQ (key
, intern ("capslock")))
8635 vk_code
= VK_CAPITAL
;
8636 else if (EQ (key
, intern ("kp-numlock")))
8637 vk_code
= VK_NUMLOCK
;
8638 else if (EQ (key
, intern ("scroll")))
8639 vk_code
= VK_SCROLL
;
8643 if (!dwWindowsThreadId
)
8644 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
8646 #ifdef USE_LISP_UNION_TYPE
8647 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
8648 (WPARAM
) vk_code
, (LPARAM
) new_state
.i
))
8650 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
8651 (WPARAM
) vk_code
, (LPARAM
) new_state
))
8655 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
8656 return make_number (msg
.wParam
);
8661 DEFUN ("w32-window-exists-p", Fw32_window_exists_p
, Sw32_window_exists_p
,
8663 doc
: /* Return non-nil if a window exists with the specified CLASS and NAME.
8665 This is a direct interface to the Windows API FindWindow function. */)
8667 Lisp_Object
class, name
;
8672 CHECK_STRING (class);
8674 CHECK_STRING (name
);
8676 hnd
= FindWindow (STRINGP (class) ? ((LPCTSTR
) SDATA (class)) : NULL
,
8677 STRINGP (name
) ? ((LPCTSTR
) SDATA (name
)) : NULL
);
8683 DEFUN ("w32-battery-status", Fw32_battery_status
, Sw32_battery_status
, 0, 0, 0,
8684 doc
: /* Get power status information from Windows system.
8686 The following %-sequences are provided:
8687 %L AC line status (verbose)
8688 %B Battery status (verbose)
8689 %b Battery status, empty means high, `-' means low,
8690 `!' means critical, and `+' means charging
8691 %p Battery load percentage
8692 %s Remaining time (to charge or discharge) in seconds
8693 %m Remaining time (to charge or discharge) in minutes
8694 %h Remaining time (to charge or discharge) in hours
8695 %t Remaining time (to charge or discharge) in the form `h:min' */)
8698 Lisp_Object status
= Qnil
;
8700 SYSTEM_POWER_STATUS system_status
;
8701 if (GetSystemPowerStatus (&system_status
))
8703 Lisp_Object line_status
, battery_status
, battery_status_symbol
;
8704 Lisp_Object load_percentage
, seconds
, minutes
, hours
, remain
;
8705 Lisp_Object sequences
[8];
8707 long seconds_left
= (long) system_status
.BatteryLifeTime
;
8709 if (system_status
.ACLineStatus
== 0)
8710 line_status
= build_string ("off-line");
8711 else if (system_status
.ACLineStatus
== 1)
8712 line_status
= build_string ("on-line");
8714 line_status
= build_string ("N/A");
8716 if (system_status
.BatteryFlag
& 128)
8718 battery_status
= build_string ("N/A");
8719 battery_status_symbol
= build_string ("");
8721 else if (system_status
.BatteryFlag
& 8)
8723 battery_status
= build_string ("charging");
8724 battery_status_symbol
= build_string ("+");
8725 if (system_status
.BatteryFullLifeTime
!= -1L)
8726 seconds_left
= system_status
.BatteryFullLifeTime
- seconds_left
;
8728 else if (system_status
.BatteryFlag
& 4)
8730 battery_status
= build_string ("critical");
8731 battery_status_symbol
= build_string ("!");
8733 else if (system_status
.BatteryFlag
& 2)
8735 battery_status
= build_string ("low");
8736 battery_status_symbol
= build_string ("-");
8738 else if (system_status
.BatteryFlag
& 1)
8740 battery_status
= build_string ("high");
8741 battery_status_symbol
= build_string ("");
8745 battery_status
= build_string ("medium");
8746 battery_status_symbol
= build_string ("");
8749 if (system_status
.BatteryLifePercent
> 100)
8750 load_percentage
= build_string ("N/A");
8754 _snprintf (buffer
, 16, "%d", system_status
.BatteryLifePercent
);
8755 load_percentage
= build_string (buffer
);
8758 if (seconds_left
< 0)
8759 seconds
= minutes
= hours
= remain
= build_string ("N/A");
8765 _snprintf (buffer
, 16, "%ld", seconds_left
);
8766 seconds
= build_string (buffer
);
8768 m
= seconds_left
/ 60;
8769 _snprintf (buffer
, 16, "%d", m
);
8770 minutes
= build_string (buffer
);
8772 h
= seconds_left
/ 3600.0;
8773 _snprintf (buffer
, 16, "%3.1f", h
);
8774 hours
= build_string (buffer
);
8776 _snprintf (buffer
, 16, "%1.0f:%d", h
, m
);
8777 remain
= build_string (buffer
);
8779 sequences
[0] = Fcons (make_number ('L'), line_status
);
8780 sequences
[1] = Fcons (make_number ('B'), battery_status
);
8781 sequences
[2] = Fcons (make_number ('b'), battery_status_symbol
);
8782 sequences
[3] = Fcons (make_number ('p'), load_percentage
);
8783 sequences
[4] = Fcons (make_number ('s'), seconds
);
8784 sequences
[5] = Fcons (make_number ('m'), minutes
);
8785 sequences
[6] = Fcons (make_number ('h'), hours
);
8786 sequences
[7] = Fcons (make_number ('t'), remain
);
8788 status
= Flist (8, sequences
);
8794 DEFUN ("file-system-info", Ffile_system_info
, Sfile_system_info
, 1, 1, 0,
8795 doc
: /* Return storage information about the file system FILENAME is on.
8796 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
8797 storage of the file system, FREE is the free storage, and AVAIL is the
8798 storage available to a non-superuser. All 3 numbers are in bytes.
8799 If the underlying system call fails, value is nil. */)
8801 Lisp_Object filename
;
8803 Lisp_Object encoded
, value
;
8805 CHECK_STRING (filename
);
8806 filename
= Fexpand_file_name (filename
, Qnil
);
8807 encoded
= ENCODE_FILE (filename
);
8811 /* Determining the required information on Windows turns out, sadly,
8812 to be more involved than one would hope. The original Win32 api
8813 call for this will return bogus information on some systems, but we
8814 must dynamically probe for the replacement api, since that was
8815 added rather late on. */
8817 HMODULE hKernel
= GetModuleHandle ("kernel32");
8818 BOOL (*pfn_GetDiskFreeSpaceEx
)
8819 (char *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
8820 = (void *) GetProcAddress (hKernel
, "GetDiskFreeSpaceEx");
8822 /* On Windows, we may need to specify the root directory of the
8823 volume holding FILENAME. */
8824 char rootname
[MAX_PATH
];
8825 char *name
= SDATA (encoded
);
8827 /* find the root name of the volume if given */
8828 if (isalpha (name
[0]) && name
[1] == ':')
8830 rootname
[0] = name
[0];
8831 rootname
[1] = name
[1];
8835 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
8837 char *str
= rootname
;
8841 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
8851 if (pfn_GetDiskFreeSpaceEx
)
8853 /* Unsigned large integers cannot be cast to double, so
8854 use signed ones instead. */
8855 LARGE_INTEGER availbytes
;
8856 LARGE_INTEGER freebytes
;
8857 LARGE_INTEGER totalbytes
;
8859 if (pfn_GetDiskFreeSpaceEx (rootname
,
8860 (ULARGE_INTEGER
*)&availbytes
,
8861 (ULARGE_INTEGER
*)&totalbytes
,
8862 (ULARGE_INTEGER
*)&freebytes
))
8863 value
= list3 (make_float ((double) totalbytes
.QuadPart
),
8864 make_float ((double) freebytes
.QuadPart
),
8865 make_float ((double) availbytes
.QuadPart
));
8869 DWORD sectors_per_cluster
;
8870 DWORD bytes_per_sector
;
8871 DWORD free_clusters
;
8872 DWORD total_clusters
;
8874 if (GetDiskFreeSpace (rootname
,
8875 §ors_per_cluster
,
8879 value
= list3 (make_float ((double) total_clusters
8880 * sectors_per_cluster
* bytes_per_sector
),
8881 make_float ((double) free_clusters
8882 * sectors_per_cluster
* bytes_per_sector
),
8883 make_float ((double) free_clusters
8884 * sectors_per_cluster
* bytes_per_sector
));
8891 DEFUN ("default-printer-name", Fdefault_printer_name
, Sdefault_printer_name
,
8892 0, 0, 0, doc
: /* Return the name of Windows default printer device. */)
8895 static char pname_buf
[256];
8898 PRINTER_INFO_2
*ppi2
= NULL
;
8899 DWORD dwNeeded
= 0, dwReturned
= 0;
8901 /* Retrieve the default string from Win.ini (the registry).
8902 * String will be in form "printername,drivername,portname".
8903 * This is the most portable way to get the default printer. */
8904 if (GetProfileString ("windows", "device", ",,", pname_buf
, sizeof (pname_buf
)) <= 0)
8906 /* printername precedes first "," character */
8907 strtok (pname_buf
, ",");
8908 /* We want to know more than the printer name */
8909 if (!OpenPrinter (pname_buf
, &hPrn
, NULL
))
8911 GetPrinter (hPrn
, 2, NULL
, 0, &dwNeeded
);
8914 ClosePrinter (hPrn
);
8917 /* Allocate memory for the PRINTER_INFO_2 struct */
8918 ppi2
= (PRINTER_INFO_2
*) xmalloc (dwNeeded
);
8921 ClosePrinter (hPrn
);
8924 /* Call GetPrinter again with big enouth memory block */
8925 err
= GetPrinter (hPrn
, 2, (LPBYTE
)ppi2
, dwNeeded
, &dwReturned
);
8926 ClosePrinter (hPrn
);
8935 if (ppi2
->Attributes
& PRINTER_ATTRIBUTE_SHARED
&& ppi2
->pServerName
)
8937 /* a remote printer */
8938 if (*ppi2
->pServerName
== '\\')
8939 _snprintf (pname_buf
, sizeof (pname_buf
), "%s\\%s", ppi2
->pServerName
,
8942 _snprintf (pname_buf
, sizeof (pname_buf
), "\\\\%s\\%s", ppi2
->pServerName
,
8944 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
8948 /* a local printer */
8949 strncpy (pname_buf
, ppi2
->pPortName
, sizeof (pname_buf
));
8950 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
8951 /* `pPortName' can include several ports, delimited by ','.
8952 * we only use the first one. */
8953 strtok (pname_buf
, ",");
8958 return build_string (pname_buf
);
8961 /***********************************************************************
8963 ***********************************************************************/
8965 /* Keep this list in the same order as frame_parms in frame.c.
8966 Use 0 for unsupported frame parameters. */
8968 frame_parm_handler w32_frame_parm_handlers
[] =
8972 x_set_background_color
,
8978 x_set_foreground_color
,
8981 x_set_internal_border_width
,
8982 x_set_menu_bar_lines
,
8984 x_explicitly_set_name
,
8985 x_set_scroll_bar_width
,
8988 x_set_vertical_scroll_bars
,
8990 x_set_tool_bar_lines
,
8991 0, /* x_set_scroll_bar_foreground, */
8992 0, /* x_set_scroll_bar_background, */
8997 0, /* x_set_wait_for_wm, */
8999 #ifdef USE_FONT_BACKEND
9007 globals_of_w32fns ();
9008 /* This is zero if not using MS-Windows. */
9010 track_mouse_window
= NULL
;
9012 w32_visible_system_caret_hwnd
= NULL
;
9014 DEFSYM (Qnone
, "none");
9015 DEFSYM (Qsuppress_icon
, "suppress-icon");
9016 DEFSYM (Qundefined_color
, "undefined-color");
9017 DEFSYM (Qcancel_timer
, "cancel-timer");
9018 DEFSYM (Qhyper
, "hyper");
9019 DEFSYM (Qsuper
, "super");
9020 DEFSYM (Qmeta
, "meta");
9021 DEFSYM (Qalt
, "alt");
9022 DEFSYM (Qctrl
, "ctrl");
9023 DEFSYM (Qcontrol
, "control");
9024 DEFSYM (Qshift
, "shift");
9025 /* This is the end of symbol initialization. */
9027 /* Text property `display' should be nonsticky by default. */
9028 Vtext_property_default_nonsticky
9029 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
9032 Fput (Qundefined_color
, Qerror_conditions
,
9033 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
9034 Fput (Qundefined_color
, Qerror_message
,
9035 build_string ("Undefined color"));
9037 staticpro (&w32_grabbed_keys
);
9038 w32_grabbed_keys
= Qnil
;
9040 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
9041 doc
: /* An array of color name mappings for Windows. */);
9042 Vw32_color_map
= Qnil
;
9044 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
9045 doc
: /* Non-nil if Alt key presses are passed on to Windows.
9046 When non-nil, for example, Alt pressed and released and then space will
9047 open the System menu. When nil, Emacs processes the Alt key events, and
9048 then silently swallows them. */);
9049 Vw32_pass_alt_to_system
= Qnil
;
9051 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
9052 doc
: /* Non-nil if the Alt key is to be considered the same as the META key.
9053 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
9054 Vw32_alt_is_meta
= Qt
;
9056 DEFVAR_INT ("w32-quit-key", &w32_quit_key
,
9057 doc
: /* If non-zero, the virtual key code for an alternative quit key. */);
9060 DEFVAR_LISP ("w32-pass-lwindow-to-system",
9061 &Vw32_pass_lwindow_to_system
,
9062 doc
: /* If non-nil, the left \"Windows\" key is passed on to Windows.
9064 When non-nil, the Start menu is opened by tapping the key.
9065 If you set this to nil, the left \"Windows\" key is processed by Emacs
9066 according to the value of `w32-lwindow-modifier', which see.
9068 Note that some combinations of the left \"Windows\" key with other keys are
9069 caught by Windows at low level, and so binding them in Emacs will have no
9070 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
9071 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
9072 the doc string of `w32-phantom-key-code'. */);
9073 Vw32_pass_lwindow_to_system
= Qt
;
9075 DEFVAR_LISP ("w32-pass-rwindow-to-system",
9076 &Vw32_pass_rwindow_to_system
,
9077 doc
: /* If non-nil, the right \"Windows\" key is passed on to Windows.
9079 When non-nil, the Start menu is opened by tapping the key.
9080 If you set this to nil, the right \"Windows\" key is processed by Emacs
9081 according to the value of `w32-rwindow-modifier', which see.
9083 Note that some combinations of the right \"Windows\" key with other keys are
9084 caught by Windows at low level, and so binding them in Emacs will have no
9085 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
9086 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
9087 the doc string of `w32-phantom-key-code'. */);
9088 Vw32_pass_rwindow_to_system
= Qt
;
9090 DEFVAR_LISP ("w32-phantom-key-code",
9091 &Vw32_phantom_key_code
,
9092 doc
: /* Virtual key code used to generate \"phantom\" key presses.
9093 Value is a number between 0 and 255.
9095 Phantom key presses are generated in order to stop the system from
9096 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
9097 `w32-pass-rwindow-to-system' is nil. */);
9098 /* Although 255 is technically not a valid key code, it works and
9099 means that this hack won't interfere with any real key code. */
9100 XSETINT (Vw32_phantom_key_code
, 255);
9102 DEFVAR_LISP ("w32-enable-num-lock",
9103 &Vw32_enable_num_lock
,
9104 doc
: /* If non-nil, the Num Lock key acts normally.
9105 Set to nil to handle Num Lock as the `kp-numlock' key. */);
9106 Vw32_enable_num_lock
= Qt
;
9108 DEFVAR_LISP ("w32-enable-caps-lock",
9109 &Vw32_enable_caps_lock
,
9110 doc
: /* If non-nil, the Caps Lock key acts normally.
9111 Set to nil to handle Caps Lock as the `capslock' key. */);
9112 Vw32_enable_caps_lock
= Qt
;
9114 DEFVAR_LISP ("w32-scroll-lock-modifier",
9115 &Vw32_scroll_lock_modifier
,
9116 doc
: /* Modifier to use for the Scroll Lock ON state.
9117 The value can be hyper, super, meta, alt, control or shift for the
9118 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
9119 Any other value will cause the Scroll Lock key to be ignored. */);
9120 Vw32_scroll_lock_modifier
= Qt
;
9122 DEFVAR_LISP ("w32-lwindow-modifier",
9123 &Vw32_lwindow_modifier
,
9124 doc
: /* Modifier to use for the left \"Windows\" key.
9125 The value can be hyper, super, meta, alt, control or shift for the
9126 respective modifier, or nil to appear as the `lwindow' key.
9127 Any other value will cause the key to be ignored. */);
9128 Vw32_lwindow_modifier
= Qnil
;
9130 DEFVAR_LISP ("w32-rwindow-modifier",
9131 &Vw32_rwindow_modifier
,
9132 doc
: /* Modifier to use for the right \"Windows\" key.
9133 The value can be hyper, super, meta, alt, control or shift for the
9134 respective modifier, or nil to appear as the `rwindow' key.
9135 Any other value will cause the key to be ignored. */);
9136 Vw32_rwindow_modifier
= Qnil
;
9138 DEFVAR_LISP ("w32-apps-modifier",
9139 &Vw32_apps_modifier
,
9140 doc
: /* Modifier to use for the \"Apps\" key.
9141 The value can be hyper, super, meta, alt, control or shift for the
9142 respective modifier, or nil to appear as the `apps' key.
9143 Any other value will cause the key to be ignored. */);
9144 Vw32_apps_modifier
= Qnil
;
9146 DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts
,
9147 doc
: /* Non-nil enables selection of artificially italicized and bold fonts. */);
9148 w32_enable_synthesized_fonts
= 0;
9150 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
9151 doc
: /* Non-nil enables Windows palette management to map colors exactly. */);
9152 Vw32_enable_palette
= Qt
;
9154 DEFVAR_INT ("w32-mouse-button-tolerance",
9155 &w32_mouse_button_tolerance
,
9156 doc
: /* Analogue of double click interval for faking middle mouse events.
9157 The value is the minimum time in milliseconds that must elapse between
9158 left and right button down events before they are considered distinct events.
9159 If both mouse buttons are depressed within this interval, a middle mouse
9160 button down event is generated instead. */);
9161 w32_mouse_button_tolerance
= GetDoubleClickTime () / 2;
9163 DEFVAR_INT ("w32-mouse-move-interval",
9164 &w32_mouse_move_interval
,
9165 doc
: /* Minimum interval between mouse move events.
9166 The value is the minimum time in milliseconds that must elapse between
9167 successive mouse move (or scroll bar drag) events before they are
9168 reported as lisp events. */);
9169 w32_mouse_move_interval
= 0;
9171 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
9172 &w32_pass_extra_mouse_buttons_to_system
,
9173 doc
: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
9174 Recent versions of Windows support mice with up to five buttons.
9175 Since most applications don't support these extra buttons, most mouse
9176 drivers will allow you to map them to functions at the system level.
9177 If this variable is non-nil, Emacs will pass them on, allowing the
9178 system to handle them. */);
9179 w32_pass_extra_mouse_buttons_to_system
= 0;
9181 DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system",
9182 &w32_pass_multimedia_buttons_to_system
,
9183 doc
: /* If non-nil, media buttons are passed to Windows.
9184 Some modern keyboards contain buttons for controlling media players, web
9185 browsers and other applications. Generally these buttons are handled on a
9186 system wide basis, but by setting this to nil they are made available
9187 to Emacs for binding. Depending on your keyboard, additional keys that
9188 may be available are:
9190 browser-back, browser-forward, browser-refresh, browser-stop,
9191 browser-search, browser-favorites, browser-home,
9192 mail, mail-reply, mail-forward, mail-send,
9194 help, find, new, open, close, save, print, undo, redo, copy, cut, paste,
9195 spell-check, correction-list, toggle-dictate-command,
9196 media-next, media-previous, media-stop, media-play-pause, media-select,
9197 media-play, media-pause, media-record, media-fast-forward, media-rewind,
9198 media-channel-up, media-channel-down,
9199 volume-mute, volume-up, volume-down,
9200 mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
9201 bass-down, bass-boost, bass-up, treble-down, treble-up */);
9202 w32_pass_multimedia_buttons_to_system
= 1;
9204 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
9205 doc
: /* The shape of the pointer when over text.
9206 Changing the value does not affect existing frames
9207 unless you set the mouse color. */);
9208 Vx_pointer_shape
= Qnil
;
9210 Vx_nontext_pointer_shape
= Qnil
;
9212 Vx_mode_pointer_shape
= Qnil
;
9214 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
9215 doc
: /* The shape of the pointer when Emacs is busy.
9216 This variable takes effect when you create a new frame
9217 or when you set the mouse color. */);
9218 Vx_hourglass_pointer_shape
= Qnil
;
9220 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
9221 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
9222 display_hourglass_p
= 1;
9224 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
9225 doc
: /* *Seconds to wait before displaying an hourglass pointer.
9226 Value must be an integer or float. */);
9227 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
9229 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
9230 &Vx_sensitive_text_pointer_shape
,
9231 doc
: /* The shape of the pointer when over mouse-sensitive text.
9232 This variable takes effect when you create a new frame
9233 or when you set the mouse color. */);
9234 Vx_sensitive_text_pointer_shape
= Qnil
;
9236 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
9237 &Vx_window_horizontal_drag_shape
,
9238 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
9239 This variable takes effect when you create a new frame
9240 or when you set the mouse color. */);
9241 Vx_window_horizontal_drag_shape
= Qnil
;
9243 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
9244 doc
: /* A string indicating the foreground color of the cursor box. */);
9245 Vx_cursor_fore_pixel
= Qnil
;
9247 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
9248 doc
: /* Maximum size for tooltips.
9249 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
9250 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
9252 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
9253 doc
: /* Non-nil if no window manager is in use.
9254 Emacs doesn't try to figure this out; this is always nil
9255 unless you set it to something else. */);
9256 /* We don't have any way to find this out, so set it to nil
9257 and maybe the user would like to set it to t. */
9258 Vx_no_window_manager
= Qnil
;
9260 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
9261 &Vx_pixel_size_width_font_regexp
,
9262 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
9264 Since Emacs gets width of a font matching with this regexp from
9265 PIXEL_SIZE field of the name, font finding mechanism gets faster for
9266 such a font. This is especially effective for such large fonts as
9267 Chinese, Japanese, and Korean. */);
9268 Vx_pixel_size_width_font_regexp
= Qnil
;
9270 DEFVAR_LISP ("w32-bdf-filename-alist",
9271 &Vw32_bdf_filename_alist
,
9272 doc
: /* List of bdf fonts and their corresponding filenames. */);
9273 Vw32_bdf_filename_alist
= Qnil
;
9275 DEFVAR_BOOL ("w32-strict-fontnames",
9276 &w32_strict_fontnames
,
9277 doc
: /* Non-nil means only use fonts that are exact matches for those requested.
9278 Default is nil, which allows old fontnames that are not XLFD compliant,
9279 and allows third-party CJK display to work by specifying false charset
9280 fields to trick Emacs into translating to Big5, SJIS etc.
9281 Setting this to t will prevent wrong fonts being selected when
9282 fontsets are automatically created. */);
9283 w32_strict_fontnames
= 0;
9285 DEFVAR_BOOL ("w32-strict-painting",
9286 &w32_strict_painting
,
9287 doc
: /* Non-nil means use strict rules for repainting frames.
9288 Set this to nil to get the old behavior for repainting; this should
9289 only be necessary if the default setting causes problems. */);
9290 w32_strict_painting
= 1;
9292 DEFVAR_LISP ("w32-charset-info-alist",
9293 &Vw32_charset_info_alist
,
9294 doc
: /* Alist linking Emacs character sets to Windows fonts and codepages.
9295 Each entry should be of the form:
9297 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
9299 where CHARSET_NAME is a string used in font names to identify the charset,
9300 WINDOWS_CHARSET is a symbol that can be one of:
9301 w32-charset-ansi, w32-charset-default, w32-charset-symbol,
9302 w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
9303 w32-charset-chinesebig5,
9304 w32-charset-johab, w32-charset-hebrew,
9305 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
9306 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
9307 w32-charset-russian, w32-charset-mac, w32-charset-baltic,
9308 w32-charset-unicode,
9310 CODEPAGE should be an integer specifying the codepage that should be used
9311 to display the character set, t to do no translation and output as Unicode,
9312 or nil to do no translation and output as 8 bit (or multibyte on far-east
9313 versions of Windows) characters. */);
9314 Vw32_charset_info_alist
= Qnil
;
9316 DEFSYM (Qw32_charset_ansi
, "w32-charset-ansi");
9317 DEFSYM (Qw32_charset_symbol
, "w32-charset-symbol");
9318 DEFSYM (Qw32_charset_default
, "w32-charset-default");
9319 DEFSYM (Qw32_charset_shiftjis
, "w32-charset-shiftjis");
9320 DEFSYM (Qw32_charset_hangeul
, "w32-charset-hangeul");
9321 DEFSYM (Qw32_charset_chinesebig5
, "w32-charset-chinesebig5");
9322 DEFSYM (Qw32_charset_gb2312
, "w32-charset-gb2312");
9323 DEFSYM (Qw32_charset_oem
, "w32-charset-oem");
9325 #ifdef JOHAB_CHARSET
9327 static int w32_extra_charsets_defined
= 1;
9328 DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined
,
9329 doc
: /* Internal variable. */);
9331 DEFSYM (Qw32_charset_johab
, "w32-charset-johab");
9332 DEFSYM (Qw32_charset_easteurope
, "w32-charset-easteurope");
9333 DEFSYM (Qw32_charset_turkish
, "w32-charset-turkish");
9334 DEFSYM (Qw32_charset_baltic
, "w32-charset-baltic");
9335 DEFSYM (Qw32_charset_russian
, "w32-charset-russian");
9336 DEFSYM (Qw32_charset_arabic
, "w32-charset-arabic");
9337 DEFSYM (Qw32_charset_greek
, "w32-charset-greek");
9338 DEFSYM (Qw32_charset_hebrew
, "w32-charset-hebrew");
9339 DEFSYM (Qw32_charset_vietnamese
, "w32-charset-vietnamese");
9340 DEFSYM (Qw32_charset_thai
, "w32-charset-thai");
9341 DEFSYM (Qw32_charset_mac
, "w32-charset-mac");
9345 #ifdef UNICODE_CHARSET
9347 static int w32_unicode_charset_defined
= 1;
9348 DEFVAR_BOOL ("w32-unicode-charset-defined",
9349 &w32_unicode_charset_defined
,
9350 doc
: /* Internal variable. */);
9351 DEFSYM (Qw32_charset_unicode
, "w32-charset-unicode");
9355 #if 0 /* TODO: Port to W32 */
9356 defsubr (&Sx_change_window_property
);
9357 defsubr (&Sx_delete_window_property
);
9358 defsubr (&Sx_window_property
);
9360 defsubr (&Sxw_display_color_p
);
9361 defsubr (&Sx_display_grayscale_p
);
9362 defsubr (&Sxw_color_defined_p
);
9363 defsubr (&Sxw_color_values
);
9364 defsubr (&Sx_server_max_request_size
);
9365 defsubr (&Sx_server_vendor
);
9366 defsubr (&Sx_server_version
);
9367 defsubr (&Sx_display_pixel_width
);
9368 defsubr (&Sx_display_pixel_height
);
9369 defsubr (&Sx_display_mm_width
);
9370 defsubr (&Sx_display_mm_height
);
9371 defsubr (&Sx_display_screens
);
9372 defsubr (&Sx_display_planes
);
9373 defsubr (&Sx_display_color_cells
);
9374 defsubr (&Sx_display_visual_class
);
9375 defsubr (&Sx_display_backing_store
);
9376 defsubr (&Sx_display_save_under
);
9377 defsubr (&Sx_create_frame
);
9378 defsubr (&Sx_open_connection
);
9379 defsubr (&Sx_close_connection
);
9380 defsubr (&Sx_display_list
);
9381 defsubr (&Sx_synchronize
);
9382 defsubr (&Sx_focus_frame
);
9384 /* W32 specific functions */
9386 defsubr (&Sw32_select_font
);
9387 defsubr (&Sw32_define_rgb_color
);
9388 defsubr (&Sw32_default_color_map
);
9389 defsubr (&Sw32_load_color_file
);
9390 defsubr (&Sw32_send_sys_command
);
9391 defsubr (&Sw32_shell_execute
);
9392 defsubr (&Sw32_register_hot_key
);
9393 defsubr (&Sw32_unregister_hot_key
);
9394 defsubr (&Sw32_registered_hot_keys
);
9395 defsubr (&Sw32_reconstruct_hot_key
);
9396 defsubr (&Sw32_toggle_lock_key
);
9397 defsubr (&Sw32_window_exists_p
);
9398 defsubr (&Sw32_find_bdf_fonts
);
9399 defsubr (&Sw32_battery_status
);
9401 defsubr (&Sfile_system_info
);
9402 defsubr (&Sdefault_printer_name
);
9404 /* Setting callback functions for fontset handler. */
9405 get_font_info_func
= w32_get_font_info
;
9407 #if 0 /* This function pointer doesn't seem to be used anywhere.
9408 And the pointer assigned has the wrong type, anyway. */
9409 list_fonts_func
= w32_list_fonts
;
9412 load_font_func
= w32_load_font
;
9413 find_ccl_program_func
= w32_find_ccl_program
;
9414 query_font_func
= w32_query_font
;
9415 set_frame_fontset_func
= x_set_font
;
9416 get_font_repertory_func
= x_get_font_repertory
;
9417 check_window_system_func
= check_w32
;
9420 hourglass_timer
= 0;
9421 hourglass_hwnd
= NULL
;
9422 hourglass_shown_p
= 0;
9423 defsubr (&Sx_show_tip
);
9424 defsubr (&Sx_hide_tip
);
9426 staticpro (&tip_timer
);
9428 staticpro (&tip_frame
);
9430 last_show_tip_args
= Qnil
;
9431 staticpro (&last_show_tip_args
);
9433 defsubr (&Sx_file_dialog
);
9438 globals_of_w32fns is used to initialize those global variables that
9439 must always be initialized on startup even when the global variable
9440 initialized is non zero (see the function main in emacs.c).
9441 globals_of_w32fns is called from syms_of_w32fns when the global
9442 variable initialized is 0 and directly from main when initialized
9446 globals_of_w32fns ()
9448 HMODULE user32_lib
= GetModuleHandle ("user32.dll");
9450 TrackMouseEvent not available in all versions of Windows, so must load
9451 it dynamically. Do it once, here, instead of every time it is used.
9453 track_mouse_event_fn
= (TrackMouseEvent_Proc
)
9454 GetProcAddress (user32_lib
, "TrackMouseEvent");
9455 /* ditto for GetClipboardSequenceNumber. */
9456 clipboard_sequence_fn
= (ClipboardSequence_Proc
)
9457 GetProcAddress (user32_lib
, "GetClipboardSequenceNumber");
9459 monitor_from_point_fn
= (MonitorFromPoint_Proc
)
9460 GetProcAddress (user32_lib
, "MonitorFromPoint");
9461 get_monitor_info_fn
= (GetMonitorInfo_Proc
)
9462 GetProcAddress (user32_lib
, "GetMonitorInfoA");
9465 HMODULE imm32_lib
= GetModuleHandle ("imm32.dll");
9466 get_composition_string_fn
= (ImmGetCompositionString_Proc
)
9467 GetProcAddress (imm32_lib
, "ImmGetCompositionStringW");
9468 get_ime_context_fn
= (ImmGetContext_Proc
)
9469 GetProcAddress (imm32_lib
, "ImmGetContext");
9471 DEFVAR_INT ("w32-ansi-code-page",
9472 &w32_ansi_code_page
,
9473 doc
: /* The ANSI code page used by the system. */);
9474 w32_ansi_code_page
= GetACP ();
9476 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
9477 InitCommonControls ();
9479 #ifdef USE_FONT_BACKEND
9480 syms_of_w32uniscribe ();
9490 button
= MessageBox (NULL
,
9491 "A fatal error has occurred!\n\n"
9492 "Would you like to attach a debugger?\n\n"
9493 "Select YES to debug, NO to abort Emacs"
9495 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
9496 "\"continue\" inside GDB before clicking YES.)"
9498 , "Emacs Abort Dialog",
9499 MB_ICONEXCLAMATION
| MB_TASKMODAL
9500 | MB_SETFOREGROUND
| MB_YESNO
);
9505 exit (2); /* tell the compiler we will never return */
9513 /* For convenience when debugging. */
9517 return GetLastError ();
9520 /* arch-tag: 707589ab-b9be-4638-8cdd-74629cc9b446
9521 (do not change this comment) */