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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Added by Kevin Gallo */
36 #include "intervals.h"
37 #include "dispextern.h"
39 #include "blockinput.h"
41 #include "character.h"
47 #include "termhooks.h"
50 #include "bitmaps/gray.xbm"
60 #define FILE_NAME_TEXT_FIELD edt1
62 #ifdef USE_FONT_BACKEND
66 void syms_of_w32fns ();
67 void globals_of_w32fns ();
69 extern void free_frame_menubar ();
70 extern double atof ();
71 extern int w32_console_toggle_lock_key
P_ ((int, Lisp_Object
));
72 extern void w32_menu_display_help
P_ ((HWND
, HMENU
, UINT
, UINT
));
73 extern void w32_free_menu_strings
P_ ((HWND
));
74 extern XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*, wchar_t *, int));
78 extern char *lispy_function_keys
[];
80 /* The gray bitmap `bitmaps/gray'. This is done because w32term.c uses
81 it, and including `bitmaps/gray' more than once is a problem when
82 config.h defines `static' as an empty replacement string. */
84 int gray_bitmap_width
= gray_width
;
85 int gray_bitmap_height
= gray_height
;
86 unsigned char *gray_bitmap_bits
= gray_bits
;
88 /* The colormap for converting color names to RGB values */
89 Lisp_Object Vw32_color_map
;
91 /* Non nil if alt key presses are passed on to Windows. */
92 Lisp_Object Vw32_pass_alt_to_system
;
94 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
96 Lisp_Object Vw32_alt_is_meta
;
98 /* If non-zero, the windows virtual key code for an alternative quit key. */
101 /* Non nil if left window key events are passed on to Windows (this only
102 affects whether "tapping" the key opens the Start menu). */
103 Lisp_Object Vw32_pass_lwindow_to_system
;
105 /* Non nil if right window key events are passed on to Windows (this
106 only affects whether "tapping" the key opens the Start menu). */
107 Lisp_Object Vw32_pass_rwindow_to_system
;
109 /* Virtual key code used to generate "phantom" key presses in order
110 to stop system from acting on Windows key events. */
111 Lisp_Object Vw32_phantom_key_code
;
113 /* Modifier associated with the left "Windows" key, or nil to act as a
115 Lisp_Object Vw32_lwindow_modifier
;
117 /* Modifier associated with the right "Windows" key, or nil to act as a
119 Lisp_Object Vw32_rwindow_modifier
;
121 /* Modifier associated with the "Apps" key, or nil to act as a normal
123 Lisp_Object Vw32_apps_modifier
;
125 /* Value is nil if Num Lock acts as a function key. */
126 Lisp_Object Vw32_enable_num_lock
;
128 /* Value is nil if Caps Lock acts as a function key. */
129 Lisp_Object Vw32_enable_caps_lock
;
131 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
132 Lisp_Object Vw32_scroll_lock_modifier
;
134 /* Switch to control whether we inhibit requests for synthesized bold
135 and italic versions of fonts. */
136 int w32_enable_synthesized_fonts
;
138 /* Enable palette management. */
139 Lisp_Object Vw32_enable_palette
;
141 /* Control how close left/right button down events must be to
142 be converted to a middle button down event. */
143 int w32_mouse_button_tolerance
;
145 /* Minimum interval between mouse movement (and scroll bar drag)
146 events that are passed on to the event loop. */
147 int w32_mouse_move_interval
;
149 /* Flag to indicate if XBUTTON events should be passed on to Windows. */
150 int w32_pass_extra_mouse_buttons_to_system
;
152 /* Non nil if no window manager is in use. */
153 Lisp_Object Vx_no_window_manager
;
155 /* Non-zero means we're allowed to display a hourglass pointer. */
157 int display_hourglass_p
;
159 /* The background and shape of the mouse pointer, and shape when not
160 over text or in the modeline. */
162 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
163 Lisp_Object Vx_hourglass_pointer_shape
, Vx_window_horizontal_drag_shape
;
165 /* The shape when over mouse-sensitive text. */
167 Lisp_Object Vx_sensitive_text_pointer_shape
;
170 #define IDC_HAND MAKEINTRESOURCE(32649)
173 /* Color of chars displayed in cursor box. */
175 Lisp_Object Vx_cursor_fore_pixel
;
177 /* Nonzero if using Windows. */
179 static int w32_in_use
;
181 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
183 Lisp_Object Vx_pixel_size_width_font_regexp
;
185 /* Alist of bdf fonts and the files that define them. */
186 Lisp_Object Vw32_bdf_filename_alist
;
188 /* A flag to control whether fonts are matched strictly or not. */
189 int w32_strict_fontnames
;
191 /* A flag to control whether we should only repaint if GetUpdateRect
192 indicates there is an update region. */
193 int w32_strict_painting
;
195 /* Associative list linking character set strings to Windows codepages. */
196 Lisp_Object Vw32_charset_info_alist
;
198 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
199 #ifndef VIETNAMESE_CHARSET
200 #define VIETNAMESE_CHARSET 163
204 Lisp_Object Qsuppress_icon
;
205 Lisp_Object Qundefined_color
;
206 Lisp_Object Qcancel_timer
;
212 Lisp_Object Qcontrol
;
215 Lisp_Object Qw32_charset_ansi
;
216 Lisp_Object Qw32_charset_default
;
217 Lisp_Object Qw32_charset_symbol
;
218 Lisp_Object Qw32_charset_shiftjis
;
219 Lisp_Object Qw32_charset_hangeul
;
220 Lisp_Object Qw32_charset_gb2312
;
221 Lisp_Object Qw32_charset_chinesebig5
;
222 Lisp_Object Qw32_charset_oem
;
224 #ifndef JOHAB_CHARSET
225 #define JOHAB_CHARSET 130
228 Lisp_Object Qw32_charset_easteurope
;
229 Lisp_Object Qw32_charset_turkish
;
230 Lisp_Object Qw32_charset_baltic
;
231 Lisp_Object Qw32_charset_russian
;
232 Lisp_Object Qw32_charset_arabic
;
233 Lisp_Object Qw32_charset_greek
;
234 Lisp_Object Qw32_charset_hebrew
;
235 Lisp_Object Qw32_charset_vietnamese
;
236 Lisp_Object Qw32_charset_thai
;
237 Lisp_Object Qw32_charset_johab
;
238 Lisp_Object Qw32_charset_mac
;
241 #ifdef UNICODE_CHARSET
242 Lisp_Object Qw32_charset_unicode
;
245 /* The ANSI codepage. */
246 int w32_ansi_code_page
;
248 /* Prefix for system colors. */
249 #define SYSTEM_COLOR_PREFIX "System"
250 #define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
252 /* State variables for emulating a three button mouse. */
257 static int button_state
= 0;
258 static W32Msg saved_mouse_button_msg
;
259 static unsigned mouse_button_timer
= 0; /* non-zero when timer is active */
260 static W32Msg saved_mouse_move_msg
;
261 static unsigned mouse_move_timer
= 0;
263 /* Window that is tracking the mouse. */
264 static HWND track_mouse_window
;
266 typedef BOOL (WINAPI
* TrackMouseEvent_Proc
)
267 (IN OUT LPTRACKMOUSEEVENT lpEventTrack
);
269 TrackMouseEvent_Proc track_mouse_event_fn
= NULL
;
270 ClipboardSequence_Proc clipboard_sequence_fn
= NULL
;
271 extern AppendMenuW_Proc unicode_append_menu
;
273 /* W95 mousewheel handler */
274 unsigned int msh_mousewheel
= 0;
277 #define MOUSE_BUTTON_ID 1
278 #define MOUSE_MOVE_ID 2
279 #define MENU_FREE_ID 3
280 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
282 #define MENU_FREE_DELAY 1000
283 static unsigned menu_free_timer
= 0;
285 /* The below are defined in frame.c. */
287 extern Lisp_Object Vwindow_system_version
;
290 int image_cache_refcount
, dpyinfo_refcount
;
294 /* From w32term.c. */
295 extern int w32_num_mouse_buttons
;
296 extern Lisp_Object Vw32_recognize_altgr
;
298 extern HWND w32_system_caret_hwnd
;
300 extern int w32_system_caret_height
;
301 extern int w32_system_caret_x
;
302 extern int w32_system_caret_y
;
303 extern int w32_use_visible_system_caret
;
305 static HWND w32_visible_system_caret_hwnd
;
308 extern HMENU current_popup_menu
;
309 static int menubar_in_use
= 0;
312 /* Error if we are not connected to MS-Windows. */
317 error ("MS-Windows not in use or not initialized");
320 /* Nonzero if we can use mouse menus.
321 You should not call this unless HAVE_MENUS is defined. */
329 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
330 and checking validity for W32. */
333 check_x_frame (frame
)
339 frame
= selected_frame
;
340 CHECK_LIVE_FRAME (frame
);
342 if (! FRAME_W32_P (f
))
343 error ("Non-W32 frame used");
347 /* Let the user specify a display with a frame.
348 nil stands for the selected frame--or, if that is not a w32 frame,
349 the first display on the list. */
351 struct w32_display_info
*
352 check_x_display_info (frame
)
357 struct frame
*sf
= XFRAME (selected_frame
);
359 if (FRAME_W32_P (sf
) && FRAME_LIVE_P (sf
))
360 return FRAME_W32_DISPLAY_INFO (sf
);
362 return &one_w32_display_info
;
364 else if (STRINGP (frame
))
365 return x_display_info_for_name (frame
);
370 CHECK_LIVE_FRAME (frame
);
372 if (! FRAME_W32_P (f
))
373 error ("Non-W32 frame used");
374 return FRAME_W32_DISPLAY_INFO (f
);
378 /* Return the Emacs frame-object corresponding to an w32 window.
379 It could be the frame's main window or an icon window. */
381 /* This function can be called during GC, so use GC_xxx type test macros. */
384 x_window_to_frame (dpyinfo
, wdesc
)
385 struct w32_display_info
*dpyinfo
;
388 Lisp_Object tail
, frame
;
391 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
397 if (!FRAME_W32_P (f
) || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
399 if (f
->output_data
.w32
->hourglass_window
== wdesc
)
402 if (FRAME_W32_WINDOW (f
) == wdesc
)
409 static Lisp_Object unwind_create_frame
P_ ((Lisp_Object
));
410 static Lisp_Object unwind_create_tip_frame
P_ ((Lisp_Object
));
411 static void my_create_window
P_ ((struct frame
*));
412 static void my_create_tip_window
P_ ((struct frame
*));
414 /* TODO: Native Input Method support; see x_create_im. */
415 void x_set_foreground_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
416 void x_set_background_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
417 void x_set_mouse_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
418 void x_set_cursor_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
419 void x_set_border_color
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
420 void x_set_cursor_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
421 void x_set_icon_type
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
422 void x_set_icon_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
423 void x_explicitly_set_name
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
424 void x_set_menu_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
425 void x_set_title
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
426 void x_set_tool_bar_lines
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
));
427 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
433 /* Store the screen positions of frame F into XPTR and YPTR.
434 These are the positions of the containing window manager window,
435 not Emacs's own window. */
438 x_real_positions (f
, xptr
, yptr
)
445 /* Get the bounds of the WM window. */
446 GetWindowRect (FRAME_W32_WINDOW (f
), &rect
);
451 /* Convert (0, 0) in the client area to screen co-ordinates. */
452 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
454 /* Remember x_pixels_diff and y_pixels_diff. */
455 f
->x_pixels_diff
= pt
.x
- rect
.left
;
456 f
->y_pixels_diff
= pt
.y
- rect
.top
;
464 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
,
465 Sw32_define_rgb_color
, 4, 4, 0,
466 doc
: /* Convert RGB numbers to a windows color reference and associate with NAME.
467 This adds or updates a named color to w32-color-map, making it
468 available for use. The original entry's RGB ref is returned, or nil
469 if the entry is new. */)
470 (red
, green
, blue
, name
)
471 Lisp_Object red
, green
, blue
, name
;
474 Lisp_Object oldrgb
= Qnil
;
478 CHECK_NUMBER (green
);
482 XSETINT (rgb
, RGB(XUINT (red
), XUINT (green
), XUINT (blue
)));
486 /* replace existing entry in w32-color-map or add new entry. */
487 entry
= Fassoc (name
, Vw32_color_map
);
490 entry
= Fcons (name
, rgb
);
491 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
495 oldrgb
= Fcdr (entry
);
496 Fsetcdr (entry
, rgb
);
504 DEFUN ("w32-load-color-file", Fw32_load_color_file
,
505 Sw32_load_color_file
, 1, 1, 0,
506 doc
: /* Create an alist of color entries from an external file.
507 Assign this value to w32-color-map to replace the existing color map.
509 The file should define one named RGB color per line like so:
511 where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
513 Lisp_Object filename
;
516 Lisp_Object cmap
= Qnil
;
519 CHECK_STRING (filename
);
520 abspath
= Fexpand_file_name (filename
, Qnil
);
522 fp
= fopen (SDATA (filename
), "rt");
526 int red
, green
, blue
;
531 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
532 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
534 char *name
= buf
+ num
;
535 num
= strlen (name
) - 1;
536 if (name
[num
] == '\n')
538 cmap
= Fcons (Fcons (build_string (name
),
539 make_number (RGB (red
, green
, blue
))),
551 /* The default colors for the w32 color map */
552 typedef struct colormap_t
558 colormap_t w32_color_map
[] =
560 {"snow" , PALETTERGB (255,250,250)},
561 {"ghost white" , PALETTERGB (248,248,255)},
562 {"GhostWhite" , PALETTERGB (248,248,255)},
563 {"white smoke" , PALETTERGB (245,245,245)},
564 {"WhiteSmoke" , PALETTERGB (245,245,245)},
565 {"gainsboro" , PALETTERGB (220,220,220)},
566 {"floral white" , PALETTERGB (255,250,240)},
567 {"FloralWhite" , PALETTERGB (255,250,240)},
568 {"old lace" , PALETTERGB (253,245,230)},
569 {"OldLace" , PALETTERGB (253,245,230)},
570 {"linen" , PALETTERGB (250,240,230)},
571 {"antique white" , PALETTERGB (250,235,215)},
572 {"AntiqueWhite" , PALETTERGB (250,235,215)},
573 {"papaya whip" , PALETTERGB (255,239,213)},
574 {"PapayaWhip" , PALETTERGB (255,239,213)},
575 {"blanched almond" , PALETTERGB (255,235,205)},
576 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
577 {"bisque" , PALETTERGB (255,228,196)},
578 {"peach puff" , PALETTERGB (255,218,185)},
579 {"PeachPuff" , PALETTERGB (255,218,185)},
580 {"navajo white" , PALETTERGB (255,222,173)},
581 {"NavajoWhite" , PALETTERGB (255,222,173)},
582 {"moccasin" , PALETTERGB (255,228,181)},
583 {"cornsilk" , PALETTERGB (255,248,220)},
584 {"ivory" , PALETTERGB (255,255,240)},
585 {"lemon chiffon" , PALETTERGB (255,250,205)},
586 {"LemonChiffon" , PALETTERGB (255,250,205)},
587 {"seashell" , PALETTERGB (255,245,238)},
588 {"honeydew" , PALETTERGB (240,255,240)},
589 {"mint cream" , PALETTERGB (245,255,250)},
590 {"MintCream" , PALETTERGB (245,255,250)},
591 {"azure" , PALETTERGB (240,255,255)},
592 {"alice blue" , PALETTERGB (240,248,255)},
593 {"AliceBlue" , PALETTERGB (240,248,255)},
594 {"lavender" , PALETTERGB (230,230,250)},
595 {"lavender blush" , PALETTERGB (255,240,245)},
596 {"LavenderBlush" , PALETTERGB (255,240,245)},
597 {"misty rose" , PALETTERGB (255,228,225)},
598 {"MistyRose" , PALETTERGB (255,228,225)},
599 {"white" , PALETTERGB (255,255,255)},
600 {"black" , PALETTERGB ( 0, 0, 0)},
601 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
602 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
603 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
604 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
605 {"dim gray" , PALETTERGB (105,105,105)},
606 {"DimGray" , PALETTERGB (105,105,105)},
607 {"dim grey" , PALETTERGB (105,105,105)},
608 {"DimGrey" , PALETTERGB (105,105,105)},
609 {"slate gray" , PALETTERGB (112,128,144)},
610 {"SlateGray" , PALETTERGB (112,128,144)},
611 {"slate grey" , PALETTERGB (112,128,144)},
612 {"SlateGrey" , PALETTERGB (112,128,144)},
613 {"light slate gray" , PALETTERGB (119,136,153)},
614 {"LightSlateGray" , PALETTERGB (119,136,153)},
615 {"light slate grey" , PALETTERGB (119,136,153)},
616 {"LightSlateGrey" , PALETTERGB (119,136,153)},
617 {"gray" , PALETTERGB (190,190,190)},
618 {"grey" , PALETTERGB (190,190,190)},
619 {"light grey" , PALETTERGB (211,211,211)},
620 {"LightGrey" , PALETTERGB (211,211,211)},
621 {"light gray" , PALETTERGB (211,211,211)},
622 {"LightGray" , PALETTERGB (211,211,211)},
623 {"midnight blue" , PALETTERGB ( 25, 25,112)},
624 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
625 {"navy" , PALETTERGB ( 0, 0,128)},
626 {"navy blue" , PALETTERGB ( 0, 0,128)},
627 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
628 {"cornflower blue" , PALETTERGB (100,149,237)},
629 {"CornflowerBlue" , PALETTERGB (100,149,237)},
630 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
631 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
632 {"slate blue" , PALETTERGB (106, 90,205)},
633 {"SlateBlue" , PALETTERGB (106, 90,205)},
634 {"medium slate blue" , PALETTERGB (123,104,238)},
635 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
636 {"light slate blue" , PALETTERGB (132,112,255)},
637 {"LightSlateBlue" , PALETTERGB (132,112,255)},
638 {"medium blue" , PALETTERGB ( 0, 0,205)},
639 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
640 {"royal blue" , PALETTERGB ( 65,105,225)},
641 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
642 {"blue" , PALETTERGB ( 0, 0,255)},
643 {"dodger blue" , PALETTERGB ( 30,144,255)},
644 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
645 {"deep sky blue" , PALETTERGB ( 0,191,255)},
646 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
647 {"sky blue" , PALETTERGB (135,206,235)},
648 {"SkyBlue" , PALETTERGB (135,206,235)},
649 {"light sky blue" , PALETTERGB (135,206,250)},
650 {"LightSkyBlue" , PALETTERGB (135,206,250)},
651 {"steel blue" , PALETTERGB ( 70,130,180)},
652 {"SteelBlue" , PALETTERGB ( 70,130,180)},
653 {"light steel blue" , PALETTERGB (176,196,222)},
654 {"LightSteelBlue" , PALETTERGB (176,196,222)},
655 {"light blue" , PALETTERGB (173,216,230)},
656 {"LightBlue" , PALETTERGB (173,216,230)},
657 {"powder blue" , PALETTERGB (176,224,230)},
658 {"PowderBlue" , PALETTERGB (176,224,230)},
659 {"pale turquoise" , PALETTERGB (175,238,238)},
660 {"PaleTurquoise" , PALETTERGB (175,238,238)},
661 {"dark turquoise" , PALETTERGB ( 0,206,209)},
662 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
663 {"medium turquoise" , PALETTERGB ( 72,209,204)},
664 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
665 {"turquoise" , PALETTERGB ( 64,224,208)},
666 {"cyan" , PALETTERGB ( 0,255,255)},
667 {"light cyan" , PALETTERGB (224,255,255)},
668 {"LightCyan" , PALETTERGB (224,255,255)},
669 {"cadet blue" , PALETTERGB ( 95,158,160)},
670 {"CadetBlue" , PALETTERGB ( 95,158,160)},
671 {"medium aquamarine" , PALETTERGB (102,205,170)},
672 {"MediumAquamarine" , PALETTERGB (102,205,170)},
673 {"aquamarine" , PALETTERGB (127,255,212)},
674 {"dark green" , PALETTERGB ( 0,100, 0)},
675 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
676 {"dark olive green" , PALETTERGB ( 85,107, 47)},
677 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
678 {"dark sea green" , PALETTERGB (143,188,143)},
679 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
680 {"sea green" , PALETTERGB ( 46,139, 87)},
681 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
682 {"medium sea green" , PALETTERGB ( 60,179,113)},
683 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
684 {"light sea green" , PALETTERGB ( 32,178,170)},
685 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
686 {"pale green" , PALETTERGB (152,251,152)},
687 {"PaleGreen" , PALETTERGB (152,251,152)},
688 {"spring green" , PALETTERGB ( 0,255,127)},
689 {"SpringGreen" , PALETTERGB ( 0,255,127)},
690 {"lawn green" , PALETTERGB (124,252, 0)},
691 {"LawnGreen" , PALETTERGB (124,252, 0)},
692 {"green" , PALETTERGB ( 0,255, 0)},
693 {"chartreuse" , PALETTERGB (127,255, 0)},
694 {"medium spring green" , PALETTERGB ( 0,250,154)},
695 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
696 {"green yellow" , PALETTERGB (173,255, 47)},
697 {"GreenYellow" , PALETTERGB (173,255, 47)},
698 {"lime green" , PALETTERGB ( 50,205, 50)},
699 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
700 {"yellow green" , PALETTERGB (154,205, 50)},
701 {"YellowGreen" , PALETTERGB (154,205, 50)},
702 {"forest green" , PALETTERGB ( 34,139, 34)},
703 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
704 {"olive drab" , PALETTERGB (107,142, 35)},
705 {"OliveDrab" , PALETTERGB (107,142, 35)},
706 {"dark khaki" , PALETTERGB (189,183,107)},
707 {"DarkKhaki" , PALETTERGB (189,183,107)},
708 {"khaki" , PALETTERGB (240,230,140)},
709 {"pale goldenrod" , PALETTERGB (238,232,170)},
710 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
711 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
712 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
713 {"light yellow" , PALETTERGB (255,255,224)},
714 {"LightYellow" , PALETTERGB (255,255,224)},
715 {"yellow" , PALETTERGB (255,255, 0)},
716 {"gold" , PALETTERGB (255,215, 0)},
717 {"light goldenrod" , PALETTERGB (238,221,130)},
718 {"LightGoldenrod" , PALETTERGB (238,221,130)},
719 {"goldenrod" , PALETTERGB (218,165, 32)},
720 {"dark goldenrod" , PALETTERGB (184,134, 11)},
721 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
722 {"rosy brown" , PALETTERGB (188,143,143)},
723 {"RosyBrown" , PALETTERGB (188,143,143)},
724 {"indian red" , PALETTERGB (205, 92, 92)},
725 {"IndianRed" , PALETTERGB (205, 92, 92)},
726 {"saddle brown" , PALETTERGB (139, 69, 19)},
727 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
728 {"sienna" , PALETTERGB (160, 82, 45)},
729 {"peru" , PALETTERGB (205,133, 63)},
730 {"burlywood" , PALETTERGB (222,184,135)},
731 {"beige" , PALETTERGB (245,245,220)},
732 {"wheat" , PALETTERGB (245,222,179)},
733 {"sandy brown" , PALETTERGB (244,164, 96)},
734 {"SandyBrown" , PALETTERGB (244,164, 96)},
735 {"tan" , PALETTERGB (210,180,140)},
736 {"chocolate" , PALETTERGB (210,105, 30)},
737 {"firebrick" , PALETTERGB (178,34, 34)},
738 {"brown" , PALETTERGB (165,42, 42)},
739 {"dark salmon" , PALETTERGB (233,150,122)},
740 {"DarkSalmon" , PALETTERGB (233,150,122)},
741 {"salmon" , PALETTERGB (250,128,114)},
742 {"light salmon" , PALETTERGB (255,160,122)},
743 {"LightSalmon" , PALETTERGB (255,160,122)},
744 {"orange" , PALETTERGB (255,165, 0)},
745 {"dark orange" , PALETTERGB (255,140, 0)},
746 {"DarkOrange" , PALETTERGB (255,140, 0)},
747 {"coral" , PALETTERGB (255,127, 80)},
748 {"light coral" , PALETTERGB (240,128,128)},
749 {"LightCoral" , PALETTERGB (240,128,128)},
750 {"tomato" , PALETTERGB (255, 99, 71)},
751 {"orange red" , PALETTERGB (255, 69, 0)},
752 {"OrangeRed" , PALETTERGB (255, 69, 0)},
753 {"red" , PALETTERGB (255, 0, 0)},
754 {"hot pink" , PALETTERGB (255,105,180)},
755 {"HotPink" , PALETTERGB (255,105,180)},
756 {"deep pink" , PALETTERGB (255, 20,147)},
757 {"DeepPink" , PALETTERGB (255, 20,147)},
758 {"pink" , PALETTERGB (255,192,203)},
759 {"light pink" , PALETTERGB (255,182,193)},
760 {"LightPink" , PALETTERGB (255,182,193)},
761 {"pale violet red" , PALETTERGB (219,112,147)},
762 {"PaleVioletRed" , PALETTERGB (219,112,147)},
763 {"maroon" , PALETTERGB (176, 48, 96)},
764 {"medium violet red" , PALETTERGB (199, 21,133)},
765 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
766 {"violet red" , PALETTERGB (208, 32,144)},
767 {"VioletRed" , PALETTERGB (208, 32,144)},
768 {"magenta" , PALETTERGB (255, 0,255)},
769 {"violet" , PALETTERGB (238,130,238)},
770 {"plum" , PALETTERGB (221,160,221)},
771 {"orchid" , PALETTERGB (218,112,214)},
772 {"medium orchid" , PALETTERGB (186, 85,211)},
773 {"MediumOrchid" , PALETTERGB (186, 85,211)},
774 {"dark orchid" , PALETTERGB (153, 50,204)},
775 {"DarkOrchid" , PALETTERGB (153, 50,204)},
776 {"dark violet" , PALETTERGB (148, 0,211)},
777 {"DarkViolet" , PALETTERGB (148, 0,211)},
778 {"blue violet" , PALETTERGB (138, 43,226)},
779 {"BlueViolet" , PALETTERGB (138, 43,226)},
780 {"purple" , PALETTERGB (160, 32,240)},
781 {"medium purple" , PALETTERGB (147,112,219)},
782 {"MediumPurple" , PALETTERGB (147,112,219)},
783 {"thistle" , PALETTERGB (216,191,216)},
784 {"gray0" , PALETTERGB ( 0, 0, 0)},
785 {"grey0" , PALETTERGB ( 0, 0, 0)},
786 {"dark grey" , PALETTERGB (169,169,169)},
787 {"DarkGrey" , PALETTERGB (169,169,169)},
788 {"dark gray" , PALETTERGB (169,169,169)},
789 {"DarkGray" , PALETTERGB (169,169,169)},
790 {"dark blue" , PALETTERGB ( 0, 0,139)},
791 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
792 {"dark cyan" , PALETTERGB ( 0,139,139)},
793 {"DarkCyan" , PALETTERGB ( 0,139,139)},
794 {"dark magenta" , PALETTERGB (139, 0,139)},
795 {"DarkMagenta" , PALETTERGB (139, 0,139)},
796 {"dark red" , PALETTERGB (139, 0, 0)},
797 {"DarkRed" , PALETTERGB (139, 0, 0)},
798 {"light green" , PALETTERGB (144,238,144)},
799 {"LightGreen" , PALETTERGB (144,238,144)},
802 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
803 0, 0, 0, doc
: /* Return the default color map. */)
807 colormap_t
*pc
= w32_color_map
;
814 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
816 cmap
= Fcons (Fcons (build_string (pc
->name
),
817 make_number (pc
->colorref
)),
835 color
= Frassq (rgb
, Vw32_color_map
);
840 return (Fcar (color
));
846 w32_color_map_lookup (colorname
)
849 Lisp_Object tail
, ret
= Qnil
;
853 for (tail
= Vw32_color_map
; !NILP (tail
); tail
= Fcdr (tail
))
855 register Lisp_Object elt
, tem
;
858 if (!CONSP (elt
)) continue;
862 if (lstrcmpi (SDATA (tem
), colorname
) == 0)
879 add_system_logical_colors_to_map (system_colors
)
880 Lisp_Object
*system_colors
;
884 /* Other registry operations are done with input blocked. */
887 /* Look for "Control Panel/Colors" under User and Machine registry
889 if (RegOpenKeyEx (HKEY_CURRENT_USER
, "Control Panel\\Colors", 0,
890 KEY_READ
, &colors_key
) == ERROR_SUCCESS
891 || RegOpenKeyEx (HKEY_LOCAL_MACHINE
, "Control Panel\\Colors", 0,
892 KEY_READ
, &colors_key
) == ERROR_SUCCESS
)
895 char color_buffer
[64];
896 char full_name_buffer
[MAX_PATH
+ SYSTEM_COLOR_PREFIX_LEN
];
898 DWORD name_size
, color_size
;
899 char *name_buffer
= full_name_buffer
+ SYSTEM_COLOR_PREFIX_LEN
;
901 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
902 color_size
= sizeof (color_buffer
);
904 strcpy (full_name_buffer
, SYSTEM_COLOR_PREFIX
);
906 while (RegEnumValueA (colors_key
, index
, name_buffer
, &name_size
,
907 NULL
, NULL
, color_buffer
, &color_size
)
911 if (sscanf (color_buffer
, " %u %u %u", &r
, &g
, &b
) == 3)
912 *system_colors
= Fcons (Fcons (build_string (full_name_buffer
),
913 make_number (RGB (r
, g
, b
))),
916 name_size
= sizeof (full_name_buffer
) - SYSTEM_COLOR_PREFIX_LEN
;
917 color_size
= sizeof (color_buffer
);
920 RegCloseKey (colors_key
);
928 x_to_w32_color (colorname
)
931 register Lisp_Object ret
= Qnil
;
935 if (colorname
[0] == '#')
937 /* Could be an old-style RGB Device specification. */
940 color
= colorname
+ 1;
942 size
= strlen(color
);
943 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
951 for (i
= 0; i
< 3; i
++)
957 /* The check for 'x' in the following conditional takes into
958 account the fact that strtol allows a "0x" in front of
959 our numbers, and we don't. */
960 if (!isxdigit(color
[0]) || color
[1] == 'x')
964 value
= strtoul(color
, &end
, 16);
966 if (errno
== ERANGE
|| end
- color
!= size
)
971 value
= value
* 0x10;
982 colorval
|= (value
<< pos
);
987 XSETINT (ret
, colorval
);
994 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1002 color
= colorname
+ 4;
1003 for (i
= 0; i
< 3; i
++)
1006 unsigned long value
;
1008 /* The check for 'x' in the following conditional takes into
1009 account the fact that strtol allows a "0x" in front of
1010 our numbers, and we don't. */
1011 if (!isxdigit(color
[0]) || color
[1] == 'x')
1013 value
= strtoul(color
, &end
, 16);
1014 if (errno
== ERANGE
)
1016 switch (end
- color
)
1019 value
= value
* 0x10 + value
;
1032 if (value
== ULONG_MAX
)
1034 colorval
|= (value
<< pos
);
1041 XSETINT (ret
, colorval
);
1049 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1051 /* This is an RGB Intensity specification. */
1058 color
= colorname
+ 5;
1059 for (i
= 0; i
< 3; i
++)
1065 value
= strtod(color
, &end
);
1066 if (errno
== ERANGE
)
1068 if (value
< 0.0 || value
> 1.0)
1070 val
= (UINT
)(0x100 * value
);
1071 /* We used 0x100 instead of 0xFF to give a continuous
1072 range between 0.0 and 1.0 inclusive. The next statement
1073 fixes the 1.0 case. */
1076 colorval
|= (val
<< pos
);
1083 XSETINT (ret
, colorval
);
1091 /* I am not going to attempt to handle any of the CIE color schemes
1092 or TekHVC, since I don't know the algorithms for conversion to
1095 /* If we fail to lookup the color name in w32_color_map, then check the
1096 colorname to see if it can be crudely approximated: If the X color
1097 ends in a number (e.g., "darkseagreen2"), strip the number and
1098 return the result of looking up the base color name. */
1099 ret
= w32_color_map_lookup (colorname
);
1102 int len
= strlen (colorname
);
1104 if (isdigit (colorname
[len
- 1]))
1106 char *ptr
, *approx
= alloca (len
+ 1);
1108 strcpy (approx
, colorname
);
1109 ptr
= &approx
[len
- 1];
1110 while (ptr
> approx
&& isdigit (*ptr
))
1113 ret
= w32_color_map_lookup (approx
);
1122 w32_regenerate_palette (FRAME_PTR f
)
1124 struct w32_palette_entry
* list
;
1125 LOGPALETTE
* log_palette
;
1126 HPALETTE new_palette
;
1129 /* don't bother trying to create palette if not supported */
1130 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1133 log_palette
= (LOGPALETTE
*)
1134 alloca (sizeof (LOGPALETTE
) +
1135 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1136 log_palette
->palVersion
= 0x300;
1137 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1139 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1141 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1142 i
++, list
= list
->next
)
1143 log_palette
->palPalEntry
[i
] = list
->entry
;
1145 new_palette
= CreatePalette (log_palette
);
1149 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1150 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1151 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1153 /* Realize display palette and garbage all frames. */
1154 release_frame_dc (f
, get_frame_dc (f
));
1159 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1160 #define SET_W32_COLOR(pe, color) \
1163 pe.peRed = GetRValue (color); \
1164 pe.peGreen = GetGValue (color); \
1165 pe.peBlue = GetBValue (color); \
1170 /* Keep these around in case we ever want to track color usage. */
1172 w32_map_color (FRAME_PTR f
, COLORREF color
)
1174 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1176 if (NILP (Vw32_enable_palette
))
1179 /* check if color is already mapped */
1182 if (W32_COLOR (list
->entry
) == color
)
1190 /* not already mapped, so add to list and recreate Windows palette */
1191 list
= (struct w32_palette_entry
*)
1192 xmalloc (sizeof (struct w32_palette_entry
));
1193 SET_W32_COLOR (list
->entry
, color
);
1195 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1196 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1197 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1199 /* set flag that palette must be regenerated */
1200 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1204 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1206 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1207 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1209 if (NILP (Vw32_enable_palette
))
1212 /* check if color is already mapped */
1215 if (W32_COLOR (list
->entry
) == color
)
1217 if (--list
->refcount
== 0)
1221 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1231 /* set flag that palette must be regenerated */
1232 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1237 /* Gamma-correct COLOR on frame F. */
1240 gamma_correct (f
, color
)
1246 *color
= PALETTERGB (
1247 pow (GetRValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1248 pow (GetGValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5,
1249 pow (GetBValue (*color
) / 255.0, f
->gamma
) * 255.0 + 0.5);
1254 /* Decide if color named COLOR is valid for the display associated with
1255 the selected frame; if so, return the rgb values in COLOR_DEF.
1256 If ALLOC is nonzero, allocate a new colormap cell. */
1259 w32_defined_color (f
, color
, color_def
, alloc
)
1265 register Lisp_Object tem
;
1266 COLORREF w32_color_ref
;
1268 tem
= x_to_w32_color (color
);
1274 /* Apply gamma correction. */
1275 w32_color_ref
= XUINT (tem
);
1276 gamma_correct (f
, &w32_color_ref
);
1277 XSETINT (tem
, w32_color_ref
);
1280 /* Map this color to the palette if it is enabled. */
1281 if (!NILP (Vw32_enable_palette
))
1283 struct w32_palette_entry
* entry
=
1284 one_w32_display_info
.color_list
;
1285 struct w32_palette_entry
** prev
=
1286 &one_w32_display_info
.color_list
;
1288 /* check if color is already mapped */
1291 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1293 prev
= &entry
->next
;
1294 entry
= entry
->next
;
1297 if (entry
== NULL
&& alloc
)
1299 /* not already mapped, so add to list */
1300 entry
= (struct w32_palette_entry
*)
1301 xmalloc (sizeof (struct w32_palette_entry
));
1302 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1305 one_w32_display_info
.num_colors
++;
1307 /* set flag that palette must be regenerated */
1308 one_w32_display_info
.regen_palette
= TRUE
;
1311 /* Ensure COLORREF value is snapped to nearest color in (default)
1312 palette by simulating the PALETTERGB macro. This works whether
1313 or not the display device has a palette. */
1314 w32_color_ref
= XUINT (tem
) | 0x2000000;
1316 color_def
->pixel
= w32_color_ref
;
1317 color_def
->red
= GetRValue (w32_color_ref
) * 256;
1318 color_def
->green
= GetGValue (w32_color_ref
) * 256;
1319 color_def
->blue
= GetBValue (w32_color_ref
) * 256;
1329 /* Given a string ARG naming a color, compute a pixel value from it
1330 suitable for screen F.
1331 If F is not a color screen, return DEF (default) regardless of what
1335 x_decode_color (f
, arg
, def
)
1344 if (strcmp (SDATA (arg
), "black") == 0)
1345 return BLACK_PIX_DEFAULT (f
);
1346 else if (strcmp (SDATA (arg
), "white") == 0)
1347 return WHITE_PIX_DEFAULT (f
);
1349 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1352 /* w32_defined_color is responsible for coping with failures
1353 by looking for a near-miss. */
1354 if (w32_defined_color (f
, SDATA (arg
), &cdef
, 1))
1357 /* defined_color failed; return an ultimate default. */
1363 /* Functions called only from `x_set_frame_param'
1364 to set individual parameters.
1366 If FRAME_W32_WINDOW (f) is 0,
1367 the frame is being created and its window does not exist yet.
1368 In that case, just record the parameter's new value
1369 in the standard place; do not attempt to change the window. */
1372 x_set_foreground_color (f
, arg
, oldval
)
1374 Lisp_Object arg
, oldval
;
1376 struct w32_output
*x
= f
->output_data
.w32
;
1377 PIX_TYPE fg
, old_fg
;
1379 fg
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1380 old_fg
= FRAME_FOREGROUND_PIXEL (f
);
1381 FRAME_FOREGROUND_PIXEL (f
) = fg
;
1383 if (FRAME_W32_WINDOW (f
) != 0)
1385 if (x
->cursor_pixel
== old_fg
)
1386 x
->cursor_pixel
= fg
;
1388 update_face_from_frame_parameter (f
, Qforeground_color
, arg
);
1389 if (FRAME_VISIBLE_P (f
))
1395 x_set_background_color (f
, arg
, oldval
)
1397 Lisp_Object arg
, oldval
;
1399 FRAME_BACKGROUND_PIXEL (f
)
1400 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1402 if (FRAME_W32_WINDOW (f
) != 0)
1404 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
,
1405 FRAME_BACKGROUND_PIXEL (f
));
1407 update_face_from_frame_parameter (f
, Qbackground_color
, arg
);
1409 if (FRAME_VISIBLE_P (f
))
1415 x_set_mouse_color (f
, arg
, oldval
)
1417 Lisp_Object arg
, oldval
;
1419 Cursor cursor
, nontext_cursor
, mode_cursor
, hand_cursor
;
1423 if (!EQ (Qnil
, arg
))
1424 f
->output_data
.w32
->mouse_pixel
1425 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1426 mask_color
= FRAME_BACKGROUND_PIXEL (f
);
1428 /* Don't let pointers be invisible. */
1429 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1430 && mask_color
== FRAME_BACKGROUND_PIXEL (f
))
1431 f
->output_data
.w32
->mouse_pixel
= FRAME_FOREGROUND_PIXEL (f
);
1433 #if 0 /* TODO : cursor changes */
1436 /* It's not okay to crash if the user selects a screwy cursor. */
1437 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1439 if (!EQ (Qnil
, Vx_pointer_shape
))
1441 CHECK_NUMBER (Vx_pointer_shape
);
1442 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1445 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1446 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1448 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1450 CHECK_NUMBER (Vx_nontext_pointer_shape
);
1451 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1452 XINT (Vx_nontext_pointer_shape
));
1455 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1456 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1458 if (!EQ (Qnil
, Vx_hourglass_pointer_shape
))
1460 CHECK_NUMBER (Vx_hourglass_pointer_shape
);
1461 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1462 XINT (Vx_hourglass_pointer_shape
));
1465 hourglass_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_watch
);
1466 x_check_errors (FRAME_W32_DISPLAY (f
), "bad busy pointer cursor: %s");
1468 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1469 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1471 CHECK_NUMBER (Vx_mode_pointer_shape
);
1472 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1473 XINT (Vx_mode_pointer_shape
));
1476 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1477 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1479 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1481 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
);
1483 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1484 XINT (Vx_sensitive_text_pointer_shape
));
1487 hand_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1489 if (!NILP (Vx_window_horizontal_drag_shape
))
1491 CHECK_NUMBER (Vx_window_horizontal_drag_shape
);
1492 horizontal_drag_cursor
1493 = XCreateFontCursor (FRAME_X_DISPLAY (f
),
1494 XINT (Vx_window_horizontal_drag_shape
));
1497 horizontal_drag_cursor
1498 = XCreateFontCursor (FRAME_X_DISPLAY (f
), XC_sb_h_double_arrow
);
1500 /* Check and report errors with the above calls. */
1501 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1502 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1505 XColor fore_color
, back_color
;
1507 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1508 back_color
.pixel
= mask_color
;
1509 XQueryColor (FRAME_W32_DISPLAY (f
),
1510 DefaultColormap (FRAME_W32_DISPLAY (f
),
1511 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1513 XQueryColor (FRAME_W32_DISPLAY (f
),
1514 DefaultColormap (FRAME_W32_DISPLAY (f
),
1515 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1517 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1518 &fore_color
, &back_color
);
1519 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1520 &fore_color
, &back_color
);
1521 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1522 &fore_color
, &back_color
);
1523 XRecolorCursor (FRAME_W32_DISPLAY (f
), hand_cursor
,
1524 &fore_color
, &back_color
);
1525 XRecolorCursor (FRAME_W32_DISPLAY (f
), hourglass_cursor
,
1526 &fore_color
, &back_color
);
1529 if (FRAME_W32_WINDOW (f
) != 0)
1530 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1532 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1533 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1534 f
->output_data
.w32
->text_cursor
= cursor
;
1536 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1537 && f
->output_data
.w32
->nontext_cursor
!= 0)
1538 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1539 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1541 if (hourglass_cursor
!= f
->output_data
.w32
->hourglass_cursor
1542 && f
->output_data
.w32
->hourglass_cursor
!= 0)
1543 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hourglass_cursor
);
1544 f
->output_data
.w32
->hourglass_cursor
= hourglass_cursor
;
1546 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1547 && f
->output_data
.w32
->modeline_cursor
!= 0)
1548 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1549 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1551 if (hand_cursor
!= f
->output_data
.w32
->hand_cursor
1552 && f
->output_data
.w32
->hand_cursor
!= 0)
1553 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->hand_cursor
);
1554 f
->output_data
.w32
->hand_cursor
= hand_cursor
;
1556 XFlush (FRAME_W32_DISPLAY (f
));
1559 update_face_from_frame_parameter (f
, Qmouse_color
, arg
);
1563 /* Defined in w32term.c. */
1565 x_set_cursor_color (f
, arg
, oldval
)
1567 Lisp_Object arg
, oldval
;
1569 unsigned long fore_pixel
, pixel
;
1571 if (!NILP (Vx_cursor_fore_pixel
))
1572 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1573 WHITE_PIX_DEFAULT (f
));
1575 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1577 pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1579 /* Make sure that the cursor color differs from the background color. */
1580 if (pixel
== FRAME_BACKGROUND_PIXEL (f
))
1582 pixel
= f
->output_data
.w32
->mouse_pixel
;
1583 if (pixel
== fore_pixel
)
1584 fore_pixel
= FRAME_BACKGROUND_PIXEL (f
);
1587 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1588 f
->output_data
.w32
->cursor_pixel
= pixel
;
1590 if (FRAME_W32_WINDOW (f
) != 0)
1593 /* Update frame's cursor_gc. */
1594 f
->output_data
.w32
->cursor_gc
->foreground
= fore_pixel
;
1595 f
->output_data
.w32
->cursor_gc
->background
= pixel
;
1599 if (FRAME_VISIBLE_P (f
))
1601 x_update_cursor (f
, 0);
1602 x_update_cursor (f
, 1);
1606 update_face_from_frame_parameter (f
, Qcursor_color
, arg
);
1609 /* Set the border-color of frame F to pixel value PIX.
1610 Note that this does not fully take effect if done before
1614 x_set_border_pixel (f
, pix
)
1619 f
->output_data
.w32
->border_pixel
= pix
;
1621 if (FRAME_W32_WINDOW (f
) != 0 && f
->border_width
> 0)
1623 if (FRAME_VISIBLE_P (f
))
1628 /* Set the border-color of frame F to value described by ARG.
1629 ARG can be a string naming a color.
1630 The border-color is used for the border that is drawn by the server.
1631 Note that this does not fully take effect if done before
1632 F has a window; it must be redone when the window is created. */
1635 x_set_border_color (f
, arg
, oldval
)
1637 Lisp_Object arg
, oldval
;
1642 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1643 x_set_border_pixel (f
, pix
);
1644 update_face_from_frame_parameter (f
, Qborder_color
, arg
);
1649 x_set_cursor_type (f
, arg
, oldval
)
1651 Lisp_Object arg
, oldval
;
1653 set_frame_cursor_types (f
, arg
);
1655 /* Make sure the cursor gets redrawn. */
1656 cursor_type_changed
= 1;
1660 x_set_icon_type (f
, arg
, oldval
)
1662 Lisp_Object arg
, oldval
;
1666 if (NILP (arg
) && NILP (oldval
))
1669 if (STRINGP (arg
) && STRINGP (oldval
)
1670 && EQ (Fstring_equal (oldval
, arg
), Qt
))
1673 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
1678 result
= x_bitmap_icon (f
, arg
);
1682 error ("No icon window available");
1689 x_set_icon_name (f
, arg
, oldval
)
1691 Lisp_Object arg
, oldval
;
1695 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1698 else if (!NILP (arg
) || NILP (oldval
))
1704 if (f
->output_data
.w32
->icon_bitmap
!= 0)
1709 result
= x_text_icon (f
,
1710 (char *) SDATA ((!NILP (f
->icon_name
)
1719 error ("No icon window available");
1722 /* If the window was unmapped (and its icon was mapped),
1723 the new icon is not mapped, so map the window in its stead. */
1724 if (FRAME_VISIBLE_P (f
))
1726 #ifdef USE_X_TOOLKIT
1727 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1729 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1732 XFlush (FRAME_W32_DISPLAY (f
));
1739 x_set_menu_bar_lines (f
, value
, oldval
)
1741 Lisp_Object value
, oldval
;
1744 int olines
= FRAME_MENU_BAR_LINES (f
);
1746 /* Right now, menu bars don't work properly in minibuf-only frames;
1747 most of the commands try to apply themselves to the minibuffer
1748 frame itself, and get an error because you can't switch buffers
1749 in or split the minibuffer window. */
1750 if (FRAME_MINIBUF_ONLY_P (f
))
1753 if (INTEGERP (value
))
1754 nlines
= XINT (value
);
1758 FRAME_MENU_BAR_LINES (f
) = 0;
1760 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
1763 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
1764 free_frame_menubar (f
);
1765 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
1767 /* Adjust the frame size so that the client (text) dimensions
1768 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
1770 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1771 do_pending_window_change (0);
1777 /* Set the number of lines used for the tool bar of frame F to VALUE.
1778 VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
1779 is the old number of tool bar lines. This function changes the
1780 height of all windows on frame F to match the new tool bar height.
1781 The frame's height doesn't change. */
1784 x_set_tool_bar_lines (f
, value
, oldval
)
1786 Lisp_Object value
, oldval
;
1788 int delta
, nlines
, root_height
;
1789 Lisp_Object root_window
;
1791 /* Treat tool bars like menu bars. */
1792 if (FRAME_MINIBUF_ONLY_P (f
))
1795 /* Use VALUE only if an integer >= 0. */
1796 if (INTEGERP (value
) && XINT (value
) >= 0)
1797 nlines
= XFASTINT (value
);
1801 /* Make sure we redisplay all windows in this frame. */
1802 ++windows_or_buffers_changed
;
1804 delta
= nlines
- FRAME_TOOL_BAR_LINES (f
);
1806 /* Don't resize the tool-bar to more than we have room for. */
1807 root_window
= FRAME_ROOT_WINDOW (f
);
1808 root_height
= WINDOW_TOTAL_LINES (XWINDOW (root_window
));
1809 if (root_height
- delta
< 1)
1811 delta
= root_height
- 1;
1812 nlines
= FRAME_TOOL_BAR_LINES (f
) + delta
;
1815 FRAME_TOOL_BAR_LINES (f
) = nlines
;
1816 change_window_heights (root_window
, delta
);
1819 /* We also have to make sure that the internal border at the top of
1820 the frame, below the menu bar or tool bar, is redrawn when the
1821 tool bar disappears. This is so because the internal border is
1822 below the tool bar if one is displayed, but is below the menu bar
1823 if there isn't a tool bar. The tool bar draws into the area
1824 below the menu bar. */
1825 if (FRAME_W32_WINDOW (f
) && FRAME_TOOL_BAR_LINES (f
) == 0)
1828 clear_current_matrices (f
);
1831 /* If the tool bar gets smaller, the internal border below it
1832 has to be cleared. It was formerly part of the display
1833 of the larger tool bar, and updating windows won't clear it. */
1836 int height
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1837 int width
= FRAME_PIXEL_WIDTH (f
);
1838 int y
= nlines
* FRAME_LINE_HEIGHT (f
);
1842 HDC hdc
= get_frame_dc (f
);
1843 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
1844 release_frame_dc (f
, hdc
);
1848 if (WINDOWP (f
->tool_bar_window
))
1849 clear_glyph_matrix (XWINDOW (f
->tool_bar_window
)->current_matrix
);
1854 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
1857 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1858 name; if NAME is a string, set F's name to NAME and set
1859 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1861 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1862 suggesting a new name, which lisp code should override; if
1863 F->explicit_name is set, ignore the new name; otherwise, set it. */
1866 x_set_name (f
, name
, explicit)
1871 /* Make sure that requests from lisp code override requests from
1872 Emacs redisplay code. */
1875 /* If we're switching from explicit to implicit, we had better
1876 update the mode lines and thereby update the title. */
1877 if (f
->explicit_name
&& NILP (name
))
1878 update_mode_lines
= 1;
1880 f
->explicit_name
= ! NILP (name
);
1882 else if (f
->explicit_name
)
1885 /* If NAME is nil, set the name to the w32_id_name. */
1888 /* Check for no change needed in this very common case
1889 before we do any consing. */
1890 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
1893 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
1896 CHECK_STRING (name
);
1898 /* Don't change the name if it's already NAME. */
1899 if (! NILP (Fstring_equal (name
, f
->name
)))
1904 /* For setting the frame title, the title parameter should override
1905 the name parameter. */
1906 if (! NILP (f
->title
))
1909 if (FRAME_W32_WINDOW (f
))
1911 if (STRING_MULTIBYTE (name
))
1912 name
= ENCODE_SYSTEM (name
);
1915 SetWindowText(FRAME_W32_WINDOW (f
), SDATA (name
));
1920 /* This function should be called when the user's lisp code has
1921 specified a name for the frame; the name will override any set by the
1924 x_explicitly_set_name (f
, arg
, oldval
)
1926 Lisp_Object arg
, oldval
;
1928 x_set_name (f
, arg
, 1);
1931 /* This function should be called by Emacs redisplay code to set the
1932 name; names set this way will never override names set by the user's
1935 x_implicitly_set_name (f
, arg
, oldval
)
1937 Lisp_Object arg
, oldval
;
1939 x_set_name (f
, arg
, 0);
1942 /* Change the title of frame F to NAME.
1943 If NAME is nil, use the frame name as the title.
1945 If EXPLICIT is non-zero, that indicates that lisp code is setting the
1946 name; if NAME is a string, set F's name to NAME and set
1947 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1949 If EXPLICIT is zero, that indicates that Emacs redisplay code is
1950 suggesting a new name, which lisp code should override; if
1951 F->explicit_name is set, ignore the new name; otherwise, set it. */
1954 x_set_title (f
, name
, old_name
)
1956 Lisp_Object name
, old_name
;
1958 /* Don't change the title if it's already NAME. */
1959 if (EQ (name
, f
->title
))
1962 update_mode_lines
= 1;
1969 if (FRAME_W32_WINDOW (f
))
1971 if (STRING_MULTIBYTE (name
))
1972 name
= ENCODE_SYSTEM (name
);
1975 SetWindowText(FRAME_W32_WINDOW (f
), SDATA (name
));
1981 void x_set_scroll_bar_default_width (f
)
1984 int wid
= FRAME_COLUMN_WIDTH (f
);
1986 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
1987 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) +
1992 /* Subroutines of creating a frame. */
1995 /* Return the value of parameter PARAM.
1997 First search ALIST, then Vdefault_frame_alist, then the X defaults
1998 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2000 Convert the resource to the type specified by desired_type.
2002 If no default is specified, return Qunbound. If you call
2003 w32_get_arg, make sure you deal with Qunbound in a reasonable way,
2004 and don't let it get stored in any Lisp-visible variables! */
2007 w32_get_arg (alist
, param
, attribute
, class, type
)
2008 Lisp_Object alist
, param
;
2011 enum resource_types type
;
2013 return x_get_arg (check_x_display_info (Qnil
),
2014 alist
, param
, attribute
, class, type
);
2019 w32_load_cursor (LPCTSTR name
)
2021 /* Try first to load cursor from application resource. */
2022 Cursor cursor
= LoadImage ((HINSTANCE
) GetModuleHandle(NULL
),
2023 name
, IMAGE_CURSOR
, 0, 0,
2024 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
2027 /* Then try to load a shared predefined cursor. */
2028 cursor
= LoadImage (NULL
, name
, IMAGE_CURSOR
, 0, 0,
2029 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
2034 extern LRESULT CALLBACK
w32_wnd_proc ();
2037 w32_init_class (hinst
)
2042 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2043 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
2045 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
2046 wc
.hInstance
= hinst
;
2047 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
2048 wc
.hCursor
= w32_load_cursor (IDC_ARROW
);
2049 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
2050 wc
.lpszMenuName
= NULL
;
2051 wc
.lpszClassName
= EMACS_CLASS
;
2053 return (RegisterClass (&wc
));
2057 w32_createscrollbar (f
, bar
)
2059 struct scroll_bar
* bar
;
2061 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
2062 /* Position and size of scroll bar. */
2063 XINT(bar
->left
) + VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
2065 XINT(bar
->width
) - VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
2067 FRAME_W32_WINDOW (f
),
2074 w32_createwindow (f
)
2079 Lisp_Object top
= Qunbound
;
2080 Lisp_Object left
= Qunbound
;
2082 rect
.left
= rect
.top
= 0;
2083 rect
.right
= FRAME_PIXEL_WIDTH (f
);
2084 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
2086 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2087 FRAME_EXTERNAL_MENU_BAR (f
));
2089 /* Do first time app init */
2093 w32_init_class (hinst
);
2096 if (f
->size_hint_flags
& USPosition
|| f
->size_hint_flags
& PPosition
)
2098 XSETINT (left
, f
->left_pos
);
2099 XSETINT (top
, f
->top_pos
);
2101 else if (EQ (left
, Qunbound
) && EQ (top
, Qunbound
))
2103 /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
2104 for anything that is not a number and is not Qunbound. */
2105 left
= w32_get_arg (Qnil
, Qleft
, "left", "Left", RES_TYPE_NUMBER
);
2106 top
= w32_get_arg (Qnil
, Qtop
, "top", "Top", RES_TYPE_NUMBER
);
2109 FRAME_W32_WINDOW (f
) = hwnd
2110 = CreateWindow (EMACS_CLASS
,
2112 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2113 EQ (left
, Qunbound
) ? CW_USEDEFAULT
: XINT (left
),
2114 EQ (top
, Qunbound
) ? CW_USEDEFAULT
: XINT (top
),
2115 rect
.right
- rect
.left
,
2116 rect
.bottom
- rect
.top
,
2124 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
2125 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
2126 SetWindowLong (hwnd
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
2127 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
2128 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
2130 /* Enable drag-n-drop. */
2131 DragAcceptFiles (hwnd
, TRUE
);
2133 /* Do this to discard the default setting specified by our parent. */
2134 ShowWindow (hwnd
, SW_HIDE
);
2136 /* Update frame positions. */
2137 GetWindowRect (hwnd
, &rect
);
2138 f
->left_pos
= rect
.left
;
2139 f
->top_pos
= rect
.top
;
2144 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
2151 wmsg
->msg
.hwnd
= hwnd
;
2152 wmsg
->msg
.message
= msg
;
2153 wmsg
->msg
.wParam
= wParam
;
2154 wmsg
->msg
.lParam
= lParam
;
2155 wmsg
->msg
.time
= GetMessageTime ();
2160 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2161 between left and right keys as advertised. We test for this
2162 support dynamically, and set a flag when the support is absent. If
2163 absent, we keep track of the left and right control and alt keys
2164 ourselves. This is particularly necessary on keyboards that rely
2165 upon the AltGr key, which is represented as having the left control
2166 and right alt keys pressed. For these keyboards, we need to know
2167 when the left alt key has been pressed in addition to the AltGr key
2168 so that we can properly support M-AltGr-key sequences (such as M-@
2169 on Swedish keyboards). */
2171 #define EMACS_LCONTROL 0
2172 #define EMACS_RCONTROL 1
2173 #define EMACS_LMENU 2
2174 #define EMACS_RMENU 3
2176 static int modifiers
[4];
2177 static int modifiers_recorded
;
2178 static int modifier_key_support_tested
;
2181 test_modifier_support (unsigned int wparam
)
2185 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
2187 if (wparam
== VK_CONTROL
)
2197 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
2198 modifiers_recorded
= 1;
2200 modifiers_recorded
= 0;
2201 modifier_key_support_tested
= 1;
2205 record_keydown (unsigned int wparam
, unsigned int lparam
)
2209 if (!modifier_key_support_tested
)
2210 test_modifier_support (wparam
);
2212 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2215 if (wparam
== VK_CONTROL
)
2216 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2218 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2224 record_keyup (unsigned int wparam
, unsigned int lparam
)
2228 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2231 if (wparam
== VK_CONTROL
)
2232 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2234 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2239 /* Emacs can lose focus while a modifier key has been pressed. When
2240 it regains focus, be conservative and clear all modifiers since
2241 we cannot reconstruct the left and right modifier state. */
2247 if (GetFocus () == NULL
)
2248 /* Emacs doesn't have keyboard focus. Do nothing. */
2251 ctrl
= GetAsyncKeyState (VK_CONTROL
);
2252 alt
= GetAsyncKeyState (VK_MENU
);
2254 if (!(ctrl
& 0x08000))
2255 /* Clear any recorded control modifier state. */
2256 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2258 if (!(alt
& 0x08000))
2259 /* Clear any recorded alt modifier state. */
2260 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2262 /* Update the state of all modifier keys, because modifiers used in
2263 hot-key combinations can get stuck on if Emacs loses focus as a
2264 result of a hot-key being pressed. */
2268 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2270 GetKeyboardState (keystate
);
2271 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
2272 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
2273 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
2274 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
2275 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
2276 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
2277 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
2278 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
2279 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
2280 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
2281 SetKeyboardState (keystate
);
2285 /* Synchronize modifier state with what is reported with the current
2286 keystroke. Even if we cannot distinguish between left and right
2287 modifier keys, we know that, if no modifiers are set, then neither
2288 the left or right modifier should be set. */
2292 if (!modifiers_recorded
)
2295 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
2296 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
2298 if (!(GetKeyState (VK_MENU
) & 0x8000))
2299 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
2303 modifier_set (int vkey
)
2305 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
2306 return (GetKeyState (vkey
) & 0x1);
2307 if (!modifiers_recorded
)
2308 return (GetKeyState (vkey
) & 0x8000);
2313 return modifiers
[EMACS_LCONTROL
];
2315 return modifiers
[EMACS_RCONTROL
];
2317 return modifiers
[EMACS_LMENU
];
2319 return modifiers
[EMACS_RMENU
];
2321 return (GetKeyState (vkey
) & 0x8000);
2324 /* Convert between the modifier bits W32 uses and the modifier bits
2328 w32_key_to_modifier (int key
)
2330 Lisp_Object key_mapping
;
2335 key_mapping
= Vw32_lwindow_modifier
;
2338 key_mapping
= Vw32_rwindow_modifier
;
2341 key_mapping
= Vw32_apps_modifier
;
2344 key_mapping
= Vw32_scroll_lock_modifier
;
2350 /* NB. This code runs in the input thread, asychronously to the lisp
2351 thread, so we must be careful to ensure access to lisp data is
2352 thread-safe. The following code is safe because the modifier
2353 variable values are updated atomically from lisp and symbols are
2354 not relocated by GC. Also, we don't have to worry about seeing GC
2356 if (EQ (key_mapping
, Qhyper
))
2357 return hyper_modifier
;
2358 if (EQ (key_mapping
, Qsuper
))
2359 return super_modifier
;
2360 if (EQ (key_mapping
, Qmeta
))
2361 return meta_modifier
;
2362 if (EQ (key_mapping
, Qalt
))
2363 return alt_modifier
;
2364 if (EQ (key_mapping
, Qctrl
))
2365 return ctrl_modifier
;
2366 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
2367 return ctrl_modifier
;
2368 if (EQ (key_mapping
, Qshift
))
2369 return shift_modifier
;
2371 /* Don't generate any modifier if not explicitly requested. */
2376 w32_get_modifiers ()
2378 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
2379 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
2380 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
2381 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
2382 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
2383 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
2384 (modifier_set (VK_MENU
) ?
2385 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2388 /* We map the VK_* modifiers into console modifier constants
2389 so that we can use the same routines to handle both console
2390 and window input. */
2393 construct_console_modifiers ()
2398 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
2399 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
2400 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
2401 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
2402 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
2403 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
2404 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
2405 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
2406 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
2407 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
2408 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
2414 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
2418 /* Convert to emacs modifiers. */
2419 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
2425 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
2427 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
2430 if (virt_key
== VK_RETURN
)
2431 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
2433 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
2434 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
2436 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
2437 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
2439 if (virt_key
== VK_CLEAR
)
2440 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
2445 /* List of special key combinations which w32 would normally capture,
2446 but emacs should grab instead. Not directly visible to lisp, to
2447 simplify synchronization. Each item is an integer encoding a virtual
2448 key code and modifier combination to capture. */
2449 Lisp_Object w32_grabbed_keys
;
2451 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
2452 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
2453 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
2454 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
2456 #define RAW_HOTKEY_ID(k) ((k) & 0xbfff)
2457 #define RAW_HOTKEY_VK_CODE(k) ((k) & 255)
2458 #define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2460 /* Register hot-keys for reserved key combinations when Emacs has
2461 keyboard focus, since this is the only way Emacs can receive key
2462 combinations like Alt-Tab which are used by the system. */
2465 register_hot_keys (hwnd
)
2468 Lisp_Object keylist
;
2470 /* Use CONSP, since we are called asynchronously. */
2471 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2473 Lisp_Object key
= XCAR (keylist
);
2475 /* Deleted entries get set to nil. */
2476 if (!INTEGERP (key
))
2479 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
2480 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
2485 unregister_hot_keys (hwnd
)
2488 Lisp_Object keylist
;
2490 for (keylist
= w32_grabbed_keys
; CONSP (keylist
); keylist
= XCDR (keylist
))
2492 Lisp_Object key
= XCAR (keylist
);
2494 if (!INTEGERP (key
))
2497 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
2501 /* Main message dispatch loop. */
2504 w32_msg_pump (deferred_msg
* msg_buf
)
2510 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
2512 while (GetMessage (&msg
, NULL
, 0, 0))
2514 if (msg
.hwnd
== NULL
)
2516 switch (msg
.message
)
2519 /* Produced by complete_deferred_msg; just ignore. */
2521 case WM_EMACS_CREATEWINDOW
:
2522 /* Initialize COM for this window. Even though we don't use it,
2523 some third party shell extensions can cause it to be used in
2524 system dialogs, which causes a crash if it is not initialized.
2525 This is a known bug in Windows, which was fixed long ago, but
2526 the patch for XP is not publically available until XP SP3,
2527 and older versions will never be patched. */
2528 CoInitialize (NULL
);
2529 w32_createwindow ((struct frame
*) msg
.wParam
);
2530 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2533 case WM_EMACS_SETLOCALE
:
2534 SetThreadLocale (msg
.wParam
);
2535 /* Reply is not expected. */
2537 case WM_EMACS_SETKEYBOARDLAYOUT
:
2538 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
2539 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2543 case WM_EMACS_REGISTER_HOT_KEY
:
2544 focus_window
= GetFocus ();
2545 if (focus_window
!= NULL
)
2546 RegisterHotKey (focus_window
,
2547 RAW_HOTKEY_ID (msg
.wParam
),
2548 RAW_HOTKEY_MODIFIERS (msg
.wParam
),
2549 RAW_HOTKEY_VK_CODE (msg
.wParam
));
2550 /* Reply is not expected. */
2552 case WM_EMACS_UNREGISTER_HOT_KEY
:
2553 focus_window
= GetFocus ();
2554 if (focus_window
!= NULL
)
2555 UnregisterHotKey (focus_window
, RAW_HOTKEY_ID (msg
.wParam
));
2556 /* Mark item as erased. NB: this code must be
2557 thread-safe. The next line is okay because the cons
2558 cell is never made into garbage and is not relocated by
2560 XSETCAR ((Lisp_Object
) ((EMACS_INT
) msg
.lParam
), Qnil
);
2561 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2564 case WM_EMACS_TOGGLE_LOCK_KEY
:
2566 int vk_code
= (int) msg
.wParam
;
2567 int cur_state
= (GetKeyState (vk_code
) & 1);
2568 Lisp_Object new_state
= (Lisp_Object
) ((EMACS_INT
) msg
.lParam
);
2570 /* NB: This code must be thread-safe. It is safe to
2571 call NILP because symbols are not relocated by GC,
2572 and pointer here is not touched by GC (so the markbit
2573 can't be set). Numbers are safe because they are
2574 immediate values. */
2575 if (NILP (new_state
)
2576 || (NUMBERP (new_state
)
2577 && ((XUINT (new_state
)) & 1) != cur_state
))
2579 one_w32_display_info
.faked_key
= vk_code
;
2581 keybd_event ((BYTE
) vk_code
,
2582 (BYTE
) MapVirtualKey (vk_code
, 0),
2583 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2584 keybd_event ((BYTE
) vk_code
,
2585 (BYTE
) MapVirtualKey (vk_code
, 0),
2586 KEYEVENTF_EXTENDEDKEY
| 0, 0);
2587 keybd_event ((BYTE
) vk_code
,
2588 (BYTE
) MapVirtualKey (vk_code
, 0),
2589 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
2590 cur_state
= !cur_state
;
2592 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
2598 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
2603 DispatchMessage (&msg
);
2606 /* Exit nested loop when our deferred message has completed. */
2607 if (msg_buf
->completed
)
2612 deferred_msg
* deferred_msg_head
;
2614 static deferred_msg
*
2615 find_deferred_msg (HWND hwnd
, UINT msg
)
2617 deferred_msg
* item
;
2619 /* Don't actually need synchronization for read access, since
2620 modification of single pointer is always atomic. */
2621 /* enter_crit (); */
2623 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2624 if (item
->w32msg
.msg
.hwnd
== hwnd
2625 && item
->w32msg
.msg
.message
== msg
)
2628 /* leave_crit (); */
2634 send_deferred_msg (deferred_msg
* msg_buf
,
2640 /* Only input thread can send deferred messages. */
2641 if (GetCurrentThreadId () != dwWindowsThreadId
)
2644 /* It is an error to send a message that is already deferred. */
2645 if (find_deferred_msg (hwnd
, msg
) != NULL
)
2648 /* Enforced synchronization is not needed because this is the only
2649 function that alters deferred_msg_head, and the following critical
2650 section is guaranteed to only be serially reentered (since only the
2651 input thread can call us). */
2653 /* enter_crit (); */
2655 msg_buf
->completed
= 0;
2656 msg_buf
->next
= deferred_msg_head
;
2657 deferred_msg_head
= msg_buf
;
2658 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
2660 /* leave_crit (); */
2662 /* Start a new nested message loop to process other messages until
2663 this one is completed. */
2664 w32_msg_pump (msg_buf
);
2666 deferred_msg_head
= msg_buf
->next
;
2668 return msg_buf
->result
;
2672 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
2674 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
2676 if (msg_buf
== NULL
)
2677 /* Message may have been cancelled, so don't abort(). */
2680 msg_buf
->result
= result
;
2681 msg_buf
->completed
= 1;
2683 /* Ensure input thread is woken so it notices the completion. */
2684 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2688 cancel_all_deferred_msgs ()
2690 deferred_msg
* item
;
2692 /* Don't actually need synchronization for read access, since
2693 modification of single pointer is always atomic. */
2694 /* enter_crit (); */
2696 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
2699 item
->completed
= 1;
2702 /* leave_crit (); */
2704 /* Ensure input thread is woken so it notices the completion. */
2705 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
2709 w32_msg_worker (void *arg
)
2712 deferred_msg dummy_buf
;
2714 /* Ensure our message queue is created */
2716 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2718 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
2721 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
2722 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
2723 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
2725 /* This is the inital message loop which should only exit when the
2726 application quits. */
2727 w32_msg_pump (&dummy_buf
);
2733 signal_user_input ()
2735 /* Interrupt any lisp that wants to be interrupted by input. */
2736 if (!NILP (Vthrow_on_input
))
2738 Vquit_flag
= Vthrow_on_input
;
2739 /* If we're inside a function that wants immediate quits,
2741 if (immediate_quit
&& NILP (Vinhibit_quit
))
2751 post_character_message (hwnd
, msg
, wParam
, lParam
, modifiers
)
2761 wmsg
.dwModifiers
= modifiers
;
2763 /* Detect quit_char and set quit-flag directly. Note that we
2764 still need to post a message to ensure the main thread will be
2765 woken up if blocked in sys_select(), but we do NOT want to post
2766 the quit_char message itself (because it will usually be as if
2767 the user had typed quit_char twice). Instead, we post a dummy
2768 message that has no particular effect. */
2771 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
2772 c
= make_ctrl_char (c
) & 0377;
2774 || (wmsg
.dwModifiers
== 0 &&
2775 w32_quit_key
&& wParam
== w32_quit_key
))
2779 /* The choice of message is somewhat arbitrary, as long as
2780 the main thread handler just ignores it. */
2783 /* Interrupt any blocking system calls. */
2786 /* As a safety precaution, forcibly complete any deferred
2787 messages. This is a kludge, but I don't see any particularly
2788 clean way to handle the situation where a deferred message is
2789 "dropped" in the lisp thread, and will thus never be
2790 completed, eg. by the user trying to activate the menubar
2791 when the lisp thread is busy, and then typing C-g when the
2792 menubar doesn't open promptly (with the result that the
2793 menubar never responds at all because the deferred
2794 WM_INITMENU message is never completed). Another problem
2795 situation is when the lisp thread calls SendMessage (to send
2796 a window manager command) when a message has been deferred;
2797 the lisp thread gets blocked indefinitely waiting for the
2798 deferred message to be completed, which itself is waiting for
2799 the lisp thread to respond.
2801 Note that we don't want to block the input thread waiting for
2802 a reponse from the lisp thread (although that would at least
2803 solve the deadlock problem above), because we want to be able
2804 to receive C-g to interrupt the lisp thread. */
2805 cancel_all_deferred_msgs ();
2808 signal_user_input ();
2811 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2814 /* Main window procedure */
2817 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
2824 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2826 int windows_translate
;
2829 /* Note that it is okay to call x_window_to_frame, even though we are
2830 not running in the main lisp thread, because frame deletion
2831 requires the lisp thread to synchronize with this thread. Thus, if
2832 a frame struct is returned, it can be used without concern that the
2833 lisp thread might make it disappear while we are using it.
2835 NB. Walking the frame list in this thread is safe (as long as
2836 writes of Lisp_Object slots are atomic, which they are on Windows).
2837 Although delete-frame can destructively modify the frame list while
2838 we are walking it, a garbage collection cannot occur until after
2839 delete-frame has synchronized with this thread.
2841 It is also safe to use functions that make GDI calls, such as
2842 w32_clear_rect, because these functions must obtain a DC handle
2843 from the frame struct using get_frame_dc which is thread-aware. */
2848 f
= x_window_to_frame (dpyinfo
, hwnd
);
2851 HDC hdc
= get_frame_dc (f
);
2852 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
2853 w32_clear_rect (f
, hdc
, &wmsg
.rect
);
2854 release_frame_dc (f
, hdc
);
2856 #if defined (W32_DEBUG_DISPLAY)
2857 DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2859 wmsg
.rect
.left
, wmsg
.rect
.top
,
2860 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2861 #endif /* W32_DEBUG_DISPLAY */
2864 case WM_PALETTECHANGED
:
2865 /* ignore our own changes */
2866 if ((HWND
)wParam
!= hwnd
)
2868 f
= x_window_to_frame (dpyinfo
, hwnd
);
2870 /* get_frame_dc will realize our palette and force all
2871 frames to be redrawn if needed. */
2872 release_frame_dc (f
, get_frame_dc (f
));
2877 PAINTSTRUCT paintStruct
;
2879 bzero (&update_rect
, sizeof (update_rect
));
2881 f
= x_window_to_frame (dpyinfo
, hwnd
);
2884 DebPrint (("WM_PAINT received for unknown window %p\n", hwnd
));
2888 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2889 fails. Apparently this can happen under some
2891 if (GetUpdateRect (hwnd
, &update_rect
, FALSE
) || !w32_strict_painting
)
2894 BeginPaint (hwnd
, &paintStruct
);
2896 /* The rectangles returned by GetUpdateRect and BeginPaint
2897 do not always match. Play it safe by assuming both areas
2899 UnionRect (&(wmsg
.rect
), &update_rect
, &(paintStruct
.rcPaint
));
2901 #if defined (W32_DEBUG_DISPLAY)
2902 DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2904 wmsg
.rect
.left
, wmsg
.rect
.top
,
2905 wmsg
.rect
.right
, wmsg
.rect
.bottom
));
2906 DebPrint ((" [update region is %d,%d-%d,%d]\n",
2907 update_rect
.left
, update_rect
.top
,
2908 update_rect
.right
, update_rect
.bottom
));
2910 EndPaint (hwnd
, &paintStruct
);
2913 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2918 /* If GetUpdateRect returns 0 (meaning there is no update
2919 region), assume the whole window needs to be repainted. */
2920 GetClientRect(hwnd
, &wmsg
.rect
);
2921 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2925 case WM_INPUTLANGCHANGE
:
2926 /* Inform lisp thread of keyboard layout changes. */
2927 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
2929 /* Clear dead keys in the keyboard state; for simplicity only
2930 preserve modifier key states. */
2935 GetKeyboardState (keystate
);
2936 for (i
= 0; i
< 256; i
++)
2953 SetKeyboardState (keystate
);
2958 /* Synchronize hot keys with normal input. */
2959 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
2964 record_keyup (wParam
, lParam
);
2969 /* Ignore keystrokes we fake ourself; see below. */
2970 if (dpyinfo
->faked_key
== wParam
)
2972 dpyinfo
->faked_key
= 0;
2973 /* Make sure TranslateMessage sees them though (as long as
2974 they don't produce WM_CHAR messages). This ensures that
2975 indicator lights are toggled promptly on Windows 9x, for
2977 if (lispy_function_keys
[wParam
] != 0)
2979 windows_translate
= 1;
2985 /* Synchronize modifiers with current keystroke. */
2987 record_keydown (wParam
, lParam
);
2988 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
2990 windows_translate
= 0;
2995 if (NILP (Vw32_pass_lwindow_to_system
))
2997 /* Prevent system from acting on keyup (which opens the
2998 Start menu if no other key was pressed) by simulating a
2999 press of Space which we will ignore. */
3000 if (GetAsyncKeyState (wParam
) & 1)
3002 if (NUMBERP (Vw32_phantom_key_code
))
3003 key
= XUINT (Vw32_phantom_key_code
) & 255;
3006 dpyinfo
->faked_key
= key
;
3007 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3010 if (!NILP (Vw32_lwindow_modifier
))
3014 if (NILP (Vw32_pass_rwindow_to_system
))
3016 if (GetAsyncKeyState (wParam
) & 1)
3018 if (NUMBERP (Vw32_phantom_key_code
))
3019 key
= XUINT (Vw32_phantom_key_code
) & 255;
3022 dpyinfo
->faked_key
= key
;
3023 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3026 if (!NILP (Vw32_rwindow_modifier
))
3030 if (!NILP (Vw32_apps_modifier
))
3034 if (NILP (Vw32_pass_alt_to_system
))
3035 /* Prevent DefWindowProc from activating the menu bar if an
3036 Alt key is pressed and released by itself. */
3038 windows_translate
= 1;
3041 /* Decide whether to treat as modifier or function key. */
3042 if (NILP (Vw32_enable_caps_lock
))
3043 goto disable_lock_key
;
3044 windows_translate
= 1;
3047 /* Decide whether to treat as modifier or function key. */
3048 if (NILP (Vw32_enable_num_lock
))
3049 goto disable_lock_key
;
3050 windows_translate
= 1;
3053 /* Decide whether to treat as modifier or function key. */
3054 if (NILP (Vw32_scroll_lock_modifier
))
3055 goto disable_lock_key
;
3056 windows_translate
= 1;
3059 /* Ensure the appropriate lock key state (and indicator light)
3060 remains in the same state. We do this by faking another
3061 press of the relevant key. Apparently, this really is the
3062 only way to toggle the state of the indicator lights. */
3063 dpyinfo
->faked_key
= wParam
;
3064 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3065 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3066 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3067 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3068 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3069 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3070 /* Ensure indicator lights are updated promptly on Windows 9x
3071 (TranslateMessage apparently does this), after forwarding
3073 post_character_message (hwnd
, msg
, wParam
, lParam
,
3074 w32_get_key_modifiers (wParam
, lParam
));
3075 windows_translate
= 1;
3079 case VK_PROCESSKEY
: /* Generated by IME. */
3080 windows_translate
= 1;
3083 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3084 which is confusing for purposes of key binding; convert
3085 VK_CANCEL events into VK_PAUSE events. */
3089 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3090 for purposes of key binding; convert these back into
3091 VK_NUMLOCK events, at least when we want to see NumLock key
3092 presses. (Note that there is never any possibility that
3093 VK_PAUSE with Ctrl really is C-Pause as per above.) */
3094 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
3095 wParam
= VK_NUMLOCK
;
3098 /* If not defined as a function key, change it to a WM_CHAR message. */
3099 if (lispy_function_keys
[wParam
] == 0)
3101 DWORD modifiers
= construct_console_modifiers ();
3103 if (!NILP (Vw32_recognize_altgr
)
3104 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
3106 /* Always let TranslateMessage handle AltGr key chords;
3107 for some reason, ToAscii doesn't always process AltGr
3108 chords correctly. */
3109 windows_translate
= 1;
3111 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
3113 /* Handle key chords including any modifiers other
3114 than shift directly, in order to preserve as much
3115 modifier information as possible. */
3116 if ('A' <= wParam
&& wParam
<= 'Z')
3118 /* Don't translate modified alphabetic keystrokes,
3119 so the user doesn't need to constantly switch
3120 layout to type control or meta keystrokes when
3121 the normal layout translates alphabetic
3122 characters to non-ascii characters. */
3123 if (!modifier_set (VK_SHIFT
))
3124 wParam
+= ('a' - 'A');
3129 /* Try to handle other keystrokes by determining the
3130 base character (ie. translating the base key plus
3134 KEY_EVENT_RECORD key
;
3136 key
.bKeyDown
= TRUE
;
3137 key
.wRepeatCount
= 1;
3138 key
.wVirtualKeyCode
= wParam
;
3139 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3140 key
.uChar
.AsciiChar
= 0;
3141 key
.dwControlKeyState
= modifiers
;
3143 add
= w32_kbd_patch_key (&key
);
3144 /* 0 means an unrecognised keycode, negative means
3145 dead key. Ignore both. */
3148 /* Forward asciified character sequence. */
3149 post_character_message
3150 (hwnd
, WM_CHAR
, key
.uChar
.AsciiChar
, lParam
,
3151 w32_get_key_modifiers (wParam
, lParam
));
3152 w32_kbd_patch_key (&key
);
3159 /* Let TranslateMessage handle everything else. */
3160 windows_translate
= 1;
3166 if (windows_translate
)
3168 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3170 windows_msg
.time
= GetMessageTime ();
3171 TranslateMessage (&windows_msg
);
3179 post_character_message (hwnd
, msg
, wParam
, lParam
,
3180 w32_get_key_modifiers (wParam
, lParam
));
3183 /* Simulate middle mouse button events when left and right buttons
3184 are used together, but only if user has two button mouse. */
3185 case WM_LBUTTONDOWN
:
3186 case WM_RBUTTONDOWN
:
3187 if (w32_num_mouse_buttons
> 2)
3188 goto handle_plain_button
;
3191 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3192 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3194 if (button_state
& this)
3197 if (button_state
== 0)
3200 button_state
|= this;
3202 if (button_state
& other
)
3204 if (mouse_button_timer
)
3206 KillTimer (hwnd
, mouse_button_timer
);
3207 mouse_button_timer
= 0;
3209 /* Generate middle mouse event instead. */
3210 msg
= WM_MBUTTONDOWN
;
3211 button_state
|= MMOUSE
;
3213 else if (button_state
& MMOUSE
)
3215 /* Ignore button event if we've already generated a
3216 middle mouse down event. This happens if the
3217 user releases and press one of the two buttons
3218 after we've faked a middle mouse event. */
3223 /* Flush out saved message. */
3224 post_msg (&saved_mouse_button_msg
);
3226 wmsg
.dwModifiers
= w32_get_modifiers ();
3227 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3228 signal_user_input ();
3230 /* Clear message buffer. */
3231 saved_mouse_button_msg
.msg
.hwnd
= 0;
3235 /* Hold onto message for now. */
3236 mouse_button_timer
=
3237 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
3238 w32_mouse_button_tolerance
, NULL
);
3239 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3240 saved_mouse_button_msg
.msg
.message
= msg
;
3241 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3242 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3243 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3244 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3251 if (w32_num_mouse_buttons
> 2)
3252 goto handle_plain_button
;
3255 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3256 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3258 if ((button_state
& this) == 0)
3261 button_state
&= ~this;
3263 if (button_state
& MMOUSE
)
3265 /* Only generate event when second button is released. */
3266 if ((button_state
& other
) == 0)
3269 button_state
&= ~MMOUSE
;
3271 if (button_state
) abort ();
3278 /* Flush out saved message if necessary. */
3279 if (saved_mouse_button_msg
.msg
.hwnd
)
3281 post_msg (&saved_mouse_button_msg
);
3284 wmsg
.dwModifiers
= w32_get_modifiers ();
3285 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3286 signal_user_input ();
3288 /* Always clear message buffer and cancel timer. */
3289 saved_mouse_button_msg
.msg
.hwnd
= 0;
3290 KillTimer (hwnd
, mouse_button_timer
);
3291 mouse_button_timer
= 0;
3293 if (button_state
== 0)
3298 case WM_XBUTTONDOWN
:
3300 if (w32_pass_extra_mouse_buttons_to_system
)
3302 /* else fall through and process them. */
3303 case WM_MBUTTONDOWN
:
3305 handle_plain_button
:
3310 /* Ignore middle and extra buttons as long as the menu is active. */
3311 f
= x_window_to_frame (dpyinfo
, hwnd
);
3312 if (f
&& f
->output_data
.w32
->menubar_active
)
3315 if (parse_button (msg
, HIWORD (wParam
), &button
, &up
))
3317 if (up
) ReleaseCapture ();
3318 else SetCapture (hwnd
);
3319 button
= (button
== 0) ? LMOUSE
:
3320 ((button
== 1) ? MMOUSE
: RMOUSE
);
3322 button_state
&= ~button
;
3324 button_state
|= button
;
3328 wmsg
.dwModifiers
= w32_get_modifiers ();
3329 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3330 signal_user_input ();
3332 /* Need to return true for XBUTTON messages, false for others,
3333 to indicate that we processed the message. */
3334 return (msg
== WM_XBUTTONDOWN
|| msg
== WM_XBUTTONUP
);
3337 /* Ignore mouse movements as long as the menu is active. These
3338 movements are processed by the window manager anyway, and
3339 it's wrong to handle them as if they happened on the
3340 underlying frame. */
3341 f
= x_window_to_frame (dpyinfo
, hwnd
);
3342 if (f
&& f
->output_data
.w32
->menubar_active
)
3345 /* If the mouse has just moved into the frame, start tracking
3346 it, so we will be notified when it leaves the frame. Mouse
3347 tracking only works under W98 and NT4 and later. On earlier
3348 versions, there is no way of telling when the mouse leaves the
3349 frame, so we just have to put up with help-echo and mouse
3350 highlighting remaining while the frame is not active. */
3351 if (track_mouse_event_fn
&& !track_mouse_window
)
3353 TRACKMOUSEEVENT tme
;
3354 tme
.cbSize
= sizeof (tme
);
3355 tme
.dwFlags
= TME_LEAVE
;
3356 tme
.hwndTrack
= hwnd
;
3358 track_mouse_event_fn (&tme
);
3359 track_mouse_window
= hwnd
;
3362 if (w32_mouse_move_interval
<= 0
3363 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3365 wmsg
.dwModifiers
= w32_get_modifiers ();
3366 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3370 /* Hang onto mouse move and scroll messages for a bit, to avoid
3371 sending such events to Emacs faster than it can process them.
3372 If we get more events before the timer from the first message
3373 expires, we just replace the first message. */
3375 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3377 SetTimer (hwnd
, MOUSE_MOVE_ID
,
3378 w32_mouse_move_interval
, NULL
);
3380 /* Hold onto message for now. */
3381 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3382 saved_mouse_move_msg
.msg
.message
= msg
;
3383 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3384 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3385 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3386 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3392 wmsg
.dwModifiers
= w32_get_modifiers ();
3393 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3394 signal_user_input ();
3397 case WM_MOUSEHWHEEL
:
3398 wmsg
.dwModifiers
= w32_get_modifiers ();
3399 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3400 signal_user_input ();
3401 /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
3402 handled, to prevent the system trying to handle it by faking
3403 scroll bar events. */
3407 /* Flush out saved messages if necessary. */
3408 if (wParam
== mouse_button_timer
)
3410 if (saved_mouse_button_msg
.msg
.hwnd
)
3412 post_msg (&saved_mouse_button_msg
);
3413 signal_user_input ();
3414 saved_mouse_button_msg
.msg
.hwnd
= 0;
3416 KillTimer (hwnd
, mouse_button_timer
);
3417 mouse_button_timer
= 0;
3419 else if (wParam
== mouse_move_timer
)
3421 if (saved_mouse_move_msg
.msg
.hwnd
)
3423 post_msg (&saved_mouse_move_msg
);
3424 saved_mouse_move_msg
.msg
.hwnd
= 0;
3426 KillTimer (hwnd
, mouse_move_timer
);
3427 mouse_move_timer
= 0;
3429 else if (wParam
== menu_free_timer
)
3431 KillTimer (hwnd
, menu_free_timer
);
3432 menu_free_timer
= 0;
3433 f
= x_window_to_frame (dpyinfo
, hwnd
);
3434 /* If a popup menu is active, don't wipe its strings. */
3436 && current_popup_menu
== NULL
)
3438 /* Free memory used by owner-drawn and help-echo strings. */
3439 w32_free_menu_strings (hwnd
);
3440 f
->output_data
.w32
->menubar_active
= 0;
3447 /* Windows doesn't send us focus messages when putting up and
3448 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3449 The only indication we get that something happened is receiving
3450 this message afterwards. So this is a good time to reset our
3451 keyboard modifiers' state. */
3458 /* We must ensure menu bar is fully constructed and up to date
3459 before allowing user interaction with it. To achieve this
3460 we send this message to the lisp thread and wait for a
3461 reply (whose value is not actually needed) to indicate that
3462 the menu bar is now ready for use, so we can now return.
3464 To remain responsive in the meantime, we enter a nested message
3465 loop that can process all other messages.
3467 However, we skip all this if the message results from calling
3468 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3469 thread a message because it is blocked on us at this point. We
3470 set menubar_active before calling TrackPopupMenu to indicate
3471 this (there is no possibility of confusion with real menubar
3474 f
= x_window_to_frame (dpyinfo
, hwnd
);
3476 && (f
->output_data
.w32
->menubar_active
3477 /* We can receive this message even in the absence of a
3478 menubar (ie. when the system menu is activated) - in this
3479 case we do NOT want to forward the message, otherwise it
3480 will cause the menubar to suddenly appear when the user
3481 had requested it to be turned off! */
3482 || f
->output_data
.w32
->menubar_widget
== NULL
))
3486 deferred_msg msg_buf
;
3488 /* Detect if message has already been deferred; in this case
3489 we cannot return any sensible value to ignore this. */
3490 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3495 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3498 case WM_EXITMENULOOP
:
3499 f
= x_window_to_frame (dpyinfo
, hwnd
);
3501 /* If a menu is still active, check again after a short delay,
3502 since Windows often (always?) sends the WM_EXITMENULOOP
3503 before the corresponding WM_COMMAND message.
3504 Don't do this if a popup menu is active, since it is only
3505 menubar menus that require cleaning up in this way.
3507 if (f
&& menubar_in_use
&& current_popup_menu
== NULL
)
3508 menu_free_timer
= SetTimer (hwnd
, MENU_FREE_ID
, MENU_FREE_DELAY
, NULL
);
3512 /* Direct handling of help_echo in menus. Should be safe now
3513 that we generate the help_echo by placing a help event in the
3516 HMENU menu
= (HMENU
) lParam
;
3517 UINT menu_item
= (UINT
) LOWORD (wParam
);
3518 UINT flags
= (UINT
) HIWORD (wParam
);
3520 w32_menu_display_help (hwnd
, menu
, menu_item
, flags
);
3524 case WM_MEASUREITEM
:
3525 f
= x_window_to_frame (dpyinfo
, hwnd
);
3528 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3530 if (pMis
->CtlType
== ODT_MENU
)
3532 /* Work out dimensions for popup menu titles. */
3533 char * title
= (char *) pMis
->itemData
;
3534 HDC hdc
= GetDC (hwnd
);
3535 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3536 LOGFONT menu_logfont
;
3540 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3541 menu_logfont
.lfWeight
= FW_BOLD
;
3542 menu_font
= CreateFontIndirect (&menu_logfont
);
3543 old_font
= SelectObject (hdc
, menu_font
);
3545 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3548 if (unicode_append_menu
)
3549 GetTextExtentPoint32W (hdc
, (WCHAR
*) title
,
3550 wcslen ((WCHAR
*) title
),
3553 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3555 pMis
->itemWidth
= size
.cx
;
3556 if (pMis
->itemHeight
< size
.cy
)
3557 pMis
->itemHeight
= size
.cy
;
3560 pMis
->itemWidth
= 0;
3562 SelectObject (hdc
, old_font
);
3563 DeleteObject (menu_font
);
3564 ReleaseDC (hwnd
, hdc
);
3571 f
= x_window_to_frame (dpyinfo
, hwnd
);
3574 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3576 if (pDis
->CtlType
== ODT_MENU
)
3578 /* Draw popup menu title. */
3579 char * title
= (char *) pDis
->itemData
;
3582 HDC hdc
= pDis
->hDC
;
3583 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3584 LOGFONT menu_logfont
;
3587 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3588 menu_logfont
.lfWeight
= FW_BOLD
;
3589 menu_font
= CreateFontIndirect (&menu_logfont
);
3590 old_font
= SelectObject (hdc
, menu_font
);
3592 /* Always draw title as if not selected. */
3593 if (unicode_append_menu
)
3596 + GetSystemMetrics (SM_CXMENUCHECK
),
3598 ETO_OPAQUE
, &pDis
->rcItem
,
3600 wcslen ((WCHAR
*) title
), NULL
);
3604 + GetSystemMetrics (SM_CXMENUCHECK
),
3606 ETO_OPAQUE
, &pDis
->rcItem
,
3607 title
, strlen (title
), NULL
);
3609 SelectObject (hdc
, old_font
);
3610 DeleteObject (menu_font
);
3618 /* Still not right - can't distinguish between clicks in the
3619 client area of the frame from clicks forwarded from the scroll
3620 bars - may have to hook WM_NCHITTEST to remember the mouse
3621 position and then check if it is in the client area ourselves. */
3622 case WM_MOUSEACTIVATE
:
3623 /* Discard the mouse click that activates a frame, allowing the
3624 user to click anywhere without changing point (or worse!).
3625 Don't eat mouse clicks on scrollbars though!! */
3626 if (LOWORD (lParam
) == HTCLIENT
)
3627 return MA_ACTIVATEANDEAT
;
3632 /* No longer tracking mouse. */
3633 track_mouse_window
= NULL
;
3635 case WM_ACTIVATEAPP
:
3637 case WM_WINDOWPOSCHANGED
:
3639 /* Inform lisp thread that a frame might have just been obscured
3640 or exposed, so should recheck visibility of all frames. */
3641 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3645 dpyinfo
->faked_key
= 0;
3647 register_hot_keys (hwnd
);
3650 unregister_hot_keys (hwnd
);
3653 /* Relinquish the system caret. */
3654 if (w32_system_caret_hwnd
)
3656 w32_visible_system_caret_hwnd
= NULL
;
3657 w32_system_caret_hwnd
= NULL
;
3663 f
= x_window_to_frame (dpyinfo
, hwnd
);
3664 if (f
&& HIWORD (wParam
) == 0)
3666 if (menu_free_timer
)
3668 KillTimer (hwnd
, menu_free_timer
);
3669 menu_free_timer
= 0;
3675 wmsg
.dwModifiers
= w32_get_modifiers ();
3676 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3684 wmsg
.dwModifiers
= w32_get_modifiers ();
3685 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3688 case WM_WINDOWPOSCHANGING
:
3689 /* Don't restrict the sizing of tip frames. */
3690 if (hwnd
== tip_window
)
3694 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3696 wp
.length
= sizeof (WINDOWPLACEMENT
);
3697 GetWindowPlacement (hwnd
, &wp
);
3699 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
3706 DWORD internal_border
;
3707 DWORD scrollbar_extra
;
3710 wp
.length
= sizeof(wp
);
3711 GetWindowRect (hwnd
, &wr
);
3715 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3716 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3717 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3718 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
3722 memset (&rect
, 0, sizeof (rect
));
3723 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3724 GetMenu (hwnd
) != NULL
);
3726 /* Force width and height of client area to be exact
3727 multiples of the character cell dimensions. */
3728 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3729 - 2 * internal_border
- scrollbar_extra
)
3731 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3732 - 2 * internal_border
)
3737 /* For right/bottom sizing we can just fix the sizes.
3738 However for top/left sizing we will need to fix the X
3739 and Y positions as well. */
3741 int cx_mintrack
= GetSystemMetrics (SM_CXMINTRACK
);
3742 int cy_mintrack
= GetSystemMetrics (SM_CYMINTRACK
);
3744 lppos
->cx
= max (lppos
->cx
- wdiff
, cx_mintrack
);
3745 lppos
->cy
= max (lppos
->cy
- hdiff
, cy_mintrack
);
3747 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3748 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3750 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3757 lppos
->flags
|= SWP_NOMOVE
;
3768 case WM_GETMINMAXINFO
:
3769 /* Hack to allow resizing the Emacs frame above the screen size.
3770 Note that Windows 9x limits coordinates to 16-bits. */
3771 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.x
= 32767;
3772 ((LPMINMAXINFO
) lParam
)->ptMaxTrackSize
.y
= 32767;
3776 if (LOWORD (lParam
) == HTCLIENT
)
3781 case WM_EMACS_SETCURSOR
:
3783 Cursor cursor
= (Cursor
) wParam
;
3789 case WM_EMACS_CREATESCROLLBAR
:
3790 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
3791 (struct scroll_bar
*) lParam
);
3793 case WM_EMACS_SHOWWINDOW
:
3794 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
3796 case WM_EMACS_SETFOREGROUND
:
3798 HWND foreground_window
;
3799 DWORD foreground_thread
, retval
;
3801 /* On NT 5.0, and apparently Windows 98, it is necessary to
3802 attach to the thread that currently has focus in order to
3803 pull the focus away from it. */
3804 foreground_window
= GetForegroundWindow ();
3805 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
3806 if (!foreground_window
3807 || foreground_thread
== GetCurrentThreadId ()
3808 || !AttachThreadInput (GetCurrentThreadId (),
3809 foreground_thread
, TRUE
))
3810 foreground_thread
= 0;
3812 retval
= SetForegroundWindow ((HWND
) wParam
);
3814 /* Detach from the previous foreground thread. */
3815 if (foreground_thread
)
3816 AttachThreadInput (GetCurrentThreadId (),
3817 foreground_thread
, FALSE
);
3822 case WM_EMACS_SETWINDOWPOS
:
3824 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
3825 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
3826 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
3829 case WM_EMACS_DESTROYWINDOW
:
3830 DragAcceptFiles ((HWND
) wParam
, FALSE
);
3831 return DestroyWindow ((HWND
) wParam
);
3833 case WM_EMACS_HIDE_CARET
:
3834 return HideCaret (hwnd
);
3836 case WM_EMACS_SHOW_CARET
:
3837 return ShowCaret (hwnd
);
3839 case WM_EMACS_DESTROY_CARET
:
3840 w32_system_caret_hwnd
= NULL
;
3841 w32_visible_system_caret_hwnd
= NULL
;
3842 return DestroyCaret ();
3844 case WM_EMACS_TRACK_CARET
:
3845 /* If there is currently no system caret, create one. */
3846 if (w32_system_caret_hwnd
== NULL
)
3848 /* Use the default caret width, and avoid changing it
3849 unneccesarily, as it confuses screen reader software. */
3850 w32_system_caret_hwnd
= hwnd
;
3851 CreateCaret (hwnd
, NULL
, 0,
3852 w32_system_caret_height
);
3855 if (!SetCaretPos (w32_system_caret_x
, w32_system_caret_y
))
3857 /* Ensure visible caret gets turned on when requested. */
3858 else if (w32_use_visible_system_caret
3859 && w32_visible_system_caret_hwnd
!= hwnd
)
3861 w32_visible_system_caret_hwnd
= hwnd
;
3862 return ShowCaret (hwnd
);
3864 /* Ensure visible caret gets turned off when requested. */
3865 else if (!w32_use_visible_system_caret
3866 && w32_visible_system_caret_hwnd
)
3868 w32_visible_system_caret_hwnd
= NULL
;
3869 return HideCaret (hwnd
);
3874 case WM_EMACS_TRACKPOPUPMENU
:
3879 pos
= (POINT
*)lParam
;
3880 flags
= TPM_CENTERALIGN
;
3881 if (button_state
& LMOUSE
)
3882 flags
|= TPM_LEFTBUTTON
;
3883 else if (button_state
& RMOUSE
)
3884 flags
|= TPM_RIGHTBUTTON
;
3886 /* Remember we did a SetCapture on the initial mouse down event,
3887 so for safety, we make sure the capture is cancelled now. */
3891 /* Use menubar_active to indicate that WM_INITMENU is from
3892 TrackPopupMenu below, and should be ignored. */
3893 f
= x_window_to_frame (dpyinfo
, hwnd
);
3895 f
->output_data
.w32
->menubar_active
= 1;
3897 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
3901 /* Eat any mouse messages during popupmenu */
3902 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
3904 /* Get the menu selection, if any */
3905 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
3907 retval
= LOWORD (amsg
.wParam
);
3923 /* Check for messages registered at runtime. */
3924 if (msg
== msh_mousewheel
)
3926 wmsg
.dwModifiers
= w32_get_modifiers ();
3927 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3928 signal_user_input ();
3933 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
3937 /* The most common default return code for handled messages is 0. */
3942 my_create_window (f
)
3947 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
3949 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3953 /* Create a tooltip window. Unlike my_create_window, we do not do this
3954 indirectly via the Window thread, as we do not need to process Window
3955 messages for the tooltip. Creating tooltips indirectly also creates
3956 deadlocks when tooltips are created for menu items. */
3958 my_create_tip_window (f
)
3963 rect
.left
= rect
.top
= 0;
3964 rect
.right
= FRAME_PIXEL_WIDTH (f
);
3965 rect
.bottom
= FRAME_PIXEL_HEIGHT (f
);
3967 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
3968 FRAME_EXTERNAL_MENU_BAR (f
));
3970 tip_window
= FRAME_W32_WINDOW (f
)
3971 = CreateWindow (EMACS_CLASS
,
3973 f
->output_data
.w32
->dwStyle
,
3976 rect
.right
- rect
.left
,
3977 rect
.bottom
- rect
.top
,
3978 FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
3985 SetWindowLong (tip_window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
3986 SetWindowLong (tip_window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
3987 SetWindowLong (tip_window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
3988 SetWindowLong (tip_window
, WND_BACKGROUND_INDEX
, FRAME_BACKGROUND_PIXEL (f
));
3990 /* Tip frames have no scrollbars. */
3991 SetWindowLong (tip_window
, WND_SCROLLBAR_INDEX
, 0);
3993 /* Do this to discard the default setting specified by our parent. */
3994 ShowWindow (tip_window
, SW_HIDE
);
3999 /* Create and set up the w32 window for frame F. */
4002 w32_window (f
, window_prompting
, minibuffer_only
)
4004 long window_prompting
;
4005 int minibuffer_only
;
4009 /* Use the resource name as the top-level window name
4010 for looking up resources. Make a non-Lisp copy
4011 for the window manager, so GC relocation won't bother it.
4013 Elsewhere we specify the window name for the window manager. */
4016 char *str
= (char *) SDATA (Vx_resource_name
);
4017 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4018 strcpy (f
->namebuf
, str
);
4021 my_create_window (f
);
4023 validate_x_resource_name ();
4025 /* x_set_name normally ignores requests to set the name if the
4026 requested name is the same as the current name. This is the one
4027 place where that assumption isn't correct; f->name is set, but
4028 the server hasn't been told. */
4031 int explicit = f
->explicit_name
;
4033 f
->explicit_name
= 0;
4036 x_set_name (f
, name
, explicit);
4041 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4042 initialize_frame_menubar (f
);
4044 if (FRAME_W32_WINDOW (f
) == 0)
4045 error ("Unable to create window");
4048 /* Handle the icon stuff for this window. Perhaps later we might
4049 want an x_set_icon_position which can be called interactively as
4057 Lisp_Object icon_x
, icon_y
;
4059 /* Set the position of the icon. Note that Windows 95 groups all
4060 icons in the tray. */
4061 icon_x
= w32_get_arg (parms
, Qicon_left
, 0, 0, RES_TYPE_NUMBER
);
4062 icon_y
= w32_get_arg (parms
, Qicon_top
, 0, 0, RES_TYPE_NUMBER
);
4063 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4065 CHECK_NUMBER (icon_x
);
4066 CHECK_NUMBER (icon_y
);
4068 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4069 error ("Both left and top icon corners of icon must be specified");
4073 if (! EQ (icon_x
, Qunbound
))
4074 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4077 /* Start up iconic or window? */
4078 x_wm_set_window_state
4079 (f
, (EQ (w32_get_arg (parms
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
), Qicon
)
4083 x_text_icon (f
, (char *) SDATA ((!NILP (f
->icon_name
)
4096 XGCValues gc_values
;
4100 /* Create the GC's of this frame.
4101 Note that many default values are used. */
4104 gc_values
.font
= FRAME_FONT (f
);
4106 /* Cursor has cursor-color background, background-color foreground. */
4107 gc_values
.foreground
= FRAME_BACKGROUND_PIXEL (f
);
4108 gc_values
.background
= f
->output_data
.w32
->cursor_pixel
;
4109 f
->output_data
.w32
->cursor_gc
4110 = XCreateGC (NULL
, FRAME_W32_WINDOW (f
),
4111 (GCFont
| GCForeground
| GCBackground
),
4115 f
->output_data
.w32
->white_relief
.gc
= 0;
4116 f
->output_data
.w32
->black_relief
.gc
= 0;
4122 /* Handler for signals raised during x_create_frame and
4123 x_create_top_frame. FRAME is the frame which is partially
4127 unwind_create_frame (frame
)
4130 struct frame
*f
= XFRAME (frame
);
4132 /* If frame is ``official'', nothing to do. */
4133 if (!CONSP (Vframe_list
) || !EQ (XCAR (Vframe_list
), frame
))
4136 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4139 x_free_frame_resources (f
);
4141 /* Check that reference counts are indeed correct. */
4142 xassert (dpyinfo
->reference_count
== dpyinfo_refcount
);
4143 xassert (dpyinfo
->image_cache
->refcount
== image_cache_refcount
);
4151 #ifdef USE_FONT_BACKEND
4153 x_default_font_parameter (f
, parms
)
4157 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4158 Lisp_Object font
= x_get_arg (dpyinfo
, parms
, Qfont
, "font", "Font",
4161 if (!STRINGP (font
))
4164 static char *names
[]
4165 = { "Courier New-10",
4166 "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
4167 "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
4171 for (i
= 0; names
[i
]; i
++)
4173 font
= font_open_by_name (f
, names
[i
]);
4178 error ("No suitable font was found");
4180 x_default_parameter (f
, parms
, Qfont
, font
, "font", "Font", RES_TYPE_STRING
);
4184 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4186 doc
: /* Make a new window, which is called a \"frame\" in Emacs terms.
4187 Returns an Emacs frame object.
4188 PARAMETERS is an alist of frame parameters.
4189 If the parameters specify that the frame should not have a minibuffer,
4190 and do not specify a specific minibuffer window to use,
4191 then `default-minibuffer-frame' must be a frame whose minibuffer can
4192 be shared by the new frame.
4194 This function is an internal primitive--use `make-frame' instead. */)
4196 Lisp_Object parameters
;
4199 Lisp_Object frame
, tem
;
4201 int minibuffer_only
= 0;
4202 long window_prompting
= 0;
4204 int count
= SPECPDL_INDEX ();
4205 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4206 Lisp_Object display
;
4207 struct w32_display_info
*dpyinfo
= NULL
;
4213 /* Use this general default value to start with
4214 until we know if this frame has a specified name. */
4215 Vx_resource_name
= Vinvocation_name
;
4217 display
= w32_get_arg (parameters
, Qdisplay
, 0, 0, RES_TYPE_STRING
);
4218 if (EQ (display
, Qunbound
))
4220 dpyinfo
= check_x_display_info (display
);
4222 kb
= dpyinfo
->terminal
->kboard
;
4224 kb
= &the_only_kboard
;
4227 name
= w32_get_arg (parameters
, Qname
, "name", "Name", RES_TYPE_STRING
);
4229 && ! EQ (name
, Qunbound
)
4231 error ("Invalid frame name--not a string or nil");
4234 Vx_resource_name
= name
;
4236 /* See if parent window is specified. */
4237 parent
= w32_get_arg (parameters
, Qparent_id
, NULL
, NULL
, RES_TYPE_NUMBER
);
4238 if (EQ (parent
, Qunbound
))
4240 if (! NILP (parent
))
4241 CHECK_NUMBER (parent
);
4243 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4244 /* No need to protect DISPLAY because that's not used after passing
4245 it to make_frame_without_minibuffer. */
4247 GCPRO4 (parameters
, parent
, name
, frame
);
4248 tem
= w32_get_arg (parameters
, Qminibuffer
, "minibuffer", "Minibuffer",
4250 if (EQ (tem
, Qnone
) || NILP (tem
))
4251 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4252 else if (EQ (tem
, Qonly
))
4254 f
= make_minibuffer_frame ();
4255 minibuffer_only
= 1;
4257 else if (WINDOWP (tem
))
4258 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4262 XSETFRAME (frame
, f
);
4264 /* Note that Windows does support scroll bars. */
4265 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4267 /* By default, make scrollbars the system standard width. */
4268 FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) = GetSystemMetrics (SM_CXVSCROLL
);
4270 f
->terminal
= dpyinfo
->terminal
;
4271 f
->terminal
->reference_count
++;
4273 f
->output_method
= output_w32
;
4274 f
->output_data
.w32
=
4275 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4276 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
4277 FRAME_FONTSET (f
) = -1;
4278 record_unwind_protect (unwind_create_frame
, frame
);
4281 = w32_get_arg (parameters
, Qicon_name
, "iconName", "Title", RES_TYPE_STRING
);
4282 if (! STRINGP (f
->icon_name
))
4283 f
->icon_name
= Qnil
;
4285 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4287 FRAME_KBOARD (f
) = kb
;
4290 /* Specify the parent under which to make this window. */
4294 f
->output_data
.w32
->parent_desc
= (Window
) XFASTINT (parent
);
4295 f
->output_data
.w32
->explicit_parent
= 1;
4299 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4300 f
->output_data
.w32
->explicit_parent
= 0;
4303 /* Set the name; the functions to which we pass f expect the name to
4305 if (EQ (name
, Qunbound
) || NILP (name
))
4307 f
->name
= build_string (dpyinfo
->w32_id_name
);
4308 f
->explicit_name
= 0;
4313 f
->explicit_name
= 1;
4314 /* use the frame's title when getting resources for this frame. */
4315 specbind (Qx_resource_name
, name
);
4318 f
->resx
= dpyinfo
->resx
;
4319 f
->resy
= dpyinfo
->resy
;
4321 #ifdef USE_FONT_BACKEND
4322 if (enable_font_backend
)
4324 /* Perhaps, we must allow frame parameter, say `font-backend',
4325 to specify which font backends to use. */
4326 register_font_driver (&w32font_driver
, f
);
4328 x_default_parameter (f
, parameters
, Qfont_backend
, Qnil
,
4329 "fontBackend", "FontBackend", RES_TYPE_STRING
);
4331 #endif /* USE_FONT_BACKEND */
4333 /* Extract the window parameters from the supplied values
4334 that are needed to determine window geometry. */
4335 #ifdef USE_FONT_BACKEND
4336 if (enable_font_backend
)
4337 x_default_font_parameter (f
, parameters
);
4343 font
= w32_get_arg (parameters
, Qfont
, "font", "Font", RES_TYPE_STRING
);
4346 /* First, try whatever font the caller has specified. */
4349 tem
= Fquery_fontset (font
, Qnil
);
4351 font
= x_new_fontset (f
, tem
);
4353 font
= x_new_font (f
, SDATA (font
));
4355 /* Try out a font which we hope has bold and italic variations. */
4356 if (!STRINGP (font
))
4357 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
4358 if (! STRINGP (font
))
4359 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
4360 /* If those didn't work, look for something which will at least work. */
4361 if (! STRINGP (font
))
4362 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
4364 if (! STRINGP (font
))
4365 font
= build_string ("Fixedsys");
4367 x_default_parameter (f
, parameters
, Qfont
, font
,
4368 "font", "Font", RES_TYPE_STRING
);
4371 x_default_parameter (f
, parameters
, Qborder_width
, make_number (2),
4372 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
4373 /* This defaults to 2 in order to match xterm. We recognize either
4374 internalBorderWidth or internalBorder (which is what xterm calls
4376 if (NILP (Fassq (Qinternal_border_width
, parameters
)))
4380 value
= w32_get_arg (parameters
, Qinternal_border_width
,
4381 "internalBorder", "InternalBorder", RES_TYPE_NUMBER
);
4382 if (! EQ (value
, Qunbound
))
4383 parameters
= Fcons (Fcons (Qinternal_border_width
, value
),
4386 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4387 x_default_parameter (f
, parameters
, Qinternal_border_width
, make_number (0),
4388 "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER
);
4389 x_default_parameter (f
, parameters
, Qvertical_scroll_bars
, Qright
,
4390 "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL
);
4392 /* Also do the stuff which must be set before the window exists. */
4393 x_default_parameter (f
, parameters
, Qforeground_color
, build_string ("black"),
4394 "foreground", "Foreground", RES_TYPE_STRING
);
4395 x_default_parameter (f
, parameters
, Qbackground_color
, build_string ("white"),
4396 "background", "Background", RES_TYPE_STRING
);
4397 x_default_parameter (f
, parameters
, Qmouse_color
, build_string ("black"),
4398 "pointerColor", "Foreground", RES_TYPE_STRING
);
4399 x_default_parameter (f
, parameters
, Qcursor_color
, build_string ("black"),
4400 "cursorColor", "Foreground", RES_TYPE_STRING
);
4401 x_default_parameter (f
, parameters
, Qborder_color
, build_string ("black"),
4402 "borderColor", "BorderColor", RES_TYPE_STRING
);
4403 x_default_parameter (f
, parameters
, Qscreen_gamma
, Qnil
,
4404 "screenGamma", "ScreenGamma", RES_TYPE_FLOAT
);
4405 x_default_parameter (f
, parameters
, Qline_spacing
, Qnil
,
4406 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER
);
4407 x_default_parameter (f
, parameters
, Qleft_fringe
, Qnil
,
4408 "leftFringe", "LeftFringe", RES_TYPE_NUMBER
);
4409 x_default_parameter (f
, parameters
, Qright_fringe
, Qnil
,
4410 "rightFringe", "RightFringe", RES_TYPE_NUMBER
);
4413 /* Init faces before x_default_parameter is called for scroll-bar
4414 parameters because that function calls x_set_scroll_bar_width,
4415 which calls change_frame_size, which calls Fset_window_buffer,
4416 which runs hooks, which call Fvertical_motion. At the end, we
4417 end up in init_iterator with a null face cache, which should not
4419 init_frame_faces (f
);
4421 x_default_parameter (f
, parameters
, Qmenu_bar_lines
, make_number (1),
4422 "menuBar", "MenuBar", RES_TYPE_NUMBER
);
4423 x_default_parameter (f
, parameters
, Qtool_bar_lines
, make_number (1),
4424 "toolBar", "ToolBar", RES_TYPE_NUMBER
);
4426 x_default_parameter (f
, parameters
, Qbuffer_predicate
, Qnil
,
4427 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL
);
4428 x_default_parameter (f
, parameters
, Qtitle
, Qnil
,
4429 "title", "Title", RES_TYPE_STRING
);
4430 x_default_parameter (f
, parameters
, Qfullscreen
, Qnil
,
4431 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL
);
4433 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4434 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4436 f
->output_data
.w32
->text_cursor
= w32_load_cursor (IDC_IBEAM
);
4437 f
->output_data
.w32
->nontext_cursor
= w32_load_cursor (IDC_ARROW
);
4438 f
->output_data
.w32
->modeline_cursor
= w32_load_cursor (IDC_ARROW
);
4439 f
->output_data
.w32
->hand_cursor
= w32_load_cursor (IDC_HAND
);
4440 f
->output_data
.w32
->hourglass_cursor
= w32_load_cursor (IDC_WAIT
);
4441 f
->output_data
.w32
->horizontal_drag_cursor
= w32_load_cursor (IDC_SIZEWE
);
4443 window_prompting
= x_figure_window_size (f
, parameters
, 1);
4445 tem
= w32_get_arg (parameters
, Qunsplittable
, 0, 0, RES_TYPE_BOOLEAN
);
4446 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4448 w32_window (f
, window_prompting
, minibuffer_only
);
4449 x_icon (f
, parameters
);
4453 /* Now consider the frame official. */
4454 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4455 Vframe_list
= Fcons (frame
, Vframe_list
);
4457 /* We need to do this after creating the window, so that the
4458 icon-creation functions can say whose icon they're describing. */
4459 x_default_parameter (f
, parameters
, Qicon_type
, Qnil
,
4460 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL
);
4462 x_default_parameter (f
, parameters
, Qauto_raise
, Qnil
,
4463 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4464 x_default_parameter (f
, parameters
, Qauto_lower
, Qnil
,
4465 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
4466 x_default_parameter (f
, parameters
, Qcursor_type
, Qbox
,
4467 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
4468 x_default_parameter (f
, parameters
, Qscroll_bar_width
, Qnil
,
4469 "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER
);
4471 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4472 Change will not be effected unless different from the current
4474 width
= FRAME_COLS (f
);
4475 height
= FRAME_LINES (f
);
4477 FRAME_LINES (f
) = 0;
4478 SET_FRAME_COLS (f
, 0);
4479 change_frame_size (f
, height
, width
, 1, 0, 0);
4481 /* Tell the server what size and position, etc, we want, and how
4482 badly we want them. This should be done after we have the menu
4483 bar so that its size can be taken into account. */
4485 x_wm_set_size_hint (f
, window_prompting
, 0);
4488 /* Make the window appear on the frame and enable display, unless
4489 the caller says not to. However, with explicit parent, Emacs
4490 cannot control visibility, so don't try. */
4491 if (! f
->output_data
.w32
->explicit_parent
)
4493 Lisp_Object visibility
;
4495 visibility
= w32_get_arg (parameters
, Qvisibility
, 0, 0, RES_TYPE_SYMBOL
);
4496 if (EQ (visibility
, Qunbound
))
4499 if (EQ (visibility
, Qicon
))
4500 x_iconify_frame (f
);
4501 else if (! NILP (visibility
))
4502 x_make_frame_visible (f
);
4504 /* Must have been Qnil. */
4508 /* Initialize `default-minibuffer-frame' in case this is the first
4509 frame on this terminal. */
4510 if (FRAME_HAS_MINIBUF_P (f
)
4511 && (!FRAMEP (kb
->Vdefault_minibuffer_frame
)
4512 || !FRAME_LIVE_P (XFRAME (kb
->Vdefault_minibuffer_frame
))))
4513 kb
->Vdefault_minibuffer_frame
= frame
;
4515 /* All remaining specified parameters, which have not been "used"
4516 by x_get_arg and friends, now go in the misc. alist of the frame. */
4517 for (tem
= parameters
; !NILP (tem
); tem
= XCDR (tem
))
4518 if (CONSP (XCAR (tem
)) && !NILP (XCAR (XCAR (tem
))))
4519 f
->param_alist
= Fcons (XCAR (tem
), f
->param_alist
);
4521 store_frame_param (f
, Qwindow_system
, Qw32
);
4525 /* Make sure windows on this frame appear in calls to next-window
4526 and similar functions. */
4527 Vwindow_list
= Qnil
;
4529 return unbind_to (count
, frame
);
4532 /* FRAME is used only to get a handle on the X display. We don't pass the
4533 display info directly because we're called from frame.c, which doesn't
4534 know about that structure. */
4536 x_get_focus_frame (frame
)
4537 struct frame
*frame
;
4539 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4541 if (! dpyinfo
->w32_focus_frame
)
4544 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4548 DEFUN ("x-focus-frame", Fx_focus_frame
, Sx_focus_frame
, 1, 1, 0,
4549 doc
: /* Give FRAME input focus, raising to foreground if necessary. */)
4553 x_focus_on_frame (check_x_frame (frame
));
4558 /* Return the charset portion of a font name. */
4559 char * xlfd_charset_of_font (char * fontname
)
4561 char *charset
, *encoding
;
4563 encoding
= strrchr(fontname
, '-');
4564 if (!encoding
|| encoding
== fontname
)
4567 for (charset
= encoding
- 1; charset
>= fontname
; charset
--)
4568 if (*charset
== '-')
4571 if (charset
== fontname
|| strcmp(charset
, "-*-*") == 0)
4577 struct font_info
*w32_load_bdf_font (struct frame
*f
, char *fontname
,
4578 int size
, char* filename
);
4579 static Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
);
4580 static BOOL
w32_to_x_font (LOGFONT
* lplf
, char * lpxstr
, int len
,
4582 static BOOL
x_to_w32_font (char *lpxstr
, LOGFONT
*lplogfont
);
4584 static struct font_info
*
4585 w32_load_system_font (f
,fontname
,size
)
4590 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4591 Lisp_Object font_names
;
4593 /* Get a list of all the fonts that match this name. Once we
4594 have a list of matching fonts, we compare them against the fonts
4595 we already have loaded by comparing names. */
4596 font_names
= w32_list_fonts (f
, build_string (fontname
), size
, 100);
4598 if (!NILP (font_names
))
4603 /* First check if any are already loaded, as that is cheaper
4604 than loading another one. */
4605 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4606 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
4607 if (dpyinfo
->font_table
[i
].name
4608 && (!strcmp (dpyinfo
->font_table
[i
].name
,
4609 SDATA (XCAR (tail
)))
4610 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
4611 SDATA (XCAR (tail
)))))
4612 return (dpyinfo
->font_table
+ i
);
4614 fontname
= (char *) SDATA (XCAR (font_names
));
4616 else if (w32_strict_fontnames
)
4618 /* If EnumFontFamiliesEx was available, we got a full list of
4619 fonts back so stop now to avoid the possibility of loading a
4620 random font. If we had to fall back to EnumFontFamilies, the
4621 list is incomplete, so continue whether the font we want was
4623 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
4624 FARPROC enum_font_families_ex
4625 = GetProcAddress (gdi32
, "EnumFontFamiliesExA");
4626 if (enum_font_families_ex
)
4630 /* Load the font and add it to the table. */
4632 char *full_name
, *encoding
, *charset
;
4634 struct font_info
*fontp
;
4640 if (!fontname
|| !x_to_w32_font (fontname
, &lf
))
4643 if (!*lf
.lfFaceName
)
4644 /* If no name was specified for the font, we get a random font
4645 from CreateFontIndirect - this is not particularly
4646 desirable, especially since CreateFontIndirect does not
4647 fill out the missing name in lf, so we never know what we
4651 lf
.lfQuality
= DEFAULT_QUALITY
;
4653 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
4654 bzero (font
, sizeof (*font
));
4656 /* Set bdf to NULL to indicate that this is a Windows font. */
4661 font
->hfont
= CreateFontIndirect (&lf
);
4663 if (font
->hfont
== NULL
)
4672 codepage
= w32_codepage_for_font (fontname
);
4674 hdc
= GetDC (dpyinfo
->root_window
);
4675 oldobj
= SelectObject (hdc
, font
->hfont
);
4677 ok
= GetTextMetrics (hdc
, &font
->tm
);
4678 if (codepage
== CP_UNICODE
)
4679 font
->double_byte_p
= 1;
4682 /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
4683 don't report themselves as double byte fonts, when
4684 patently they are. So instead of trusting
4685 GetFontLanguageInfo, we check the properties of the
4686 codepage directly, since that is ultimately what we are
4687 working from anyway. */
4688 /* font->double_byte_p = GetFontLanguageInfo(hdc) & GCP_DBCS; */
4690 GetCPInfo (codepage
, &cpi
);
4691 font
->double_byte_p
= cpi
.MaxCharSize
> 1;
4694 SelectObject (hdc
, oldobj
);
4695 ReleaseDC (dpyinfo
->root_window
, hdc
);
4696 /* Fill out details in lf according to the font that was
4698 lf
.lfHeight
= font
->tm
.tmInternalLeading
- font
->tm
.tmHeight
;
4699 lf
.lfWidth
= font
->tm
.tmMaxCharWidth
;
4700 lf
.lfWeight
= font
->tm
.tmWeight
;
4701 lf
.lfItalic
= font
->tm
.tmItalic
;
4702 lf
.lfCharSet
= font
->tm
.tmCharSet
;
4703 lf
.lfPitchAndFamily
= ((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
)
4704 ? VARIABLE_PITCH
: FIXED_PITCH
);
4705 lf
.lfOutPrecision
= ((font
->tm
.tmPitchAndFamily
& TMPF_VECTOR
)
4706 ? OUT_STROKE_PRECIS
: OUT_STRING_PRECIS
);
4708 w32_cache_char_metrics (font
);
4715 w32_unload_font (dpyinfo
, font
);
4719 /* Find a free slot in the font table. */
4720 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
4721 if (dpyinfo
->font_table
[i
].name
== NULL
)
4724 /* If no free slot found, maybe enlarge the font table. */
4725 if (i
== dpyinfo
->n_fonts
4726 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
4729 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
4730 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
4732 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
4735 fontp
= dpyinfo
->font_table
+ i
;
4736 if (i
== dpyinfo
->n_fonts
)
4739 /* Now fill in the slots of *FONTP. */
4741 bzero (fontp
, sizeof (*fontp
));
4743 fontp
->font_idx
= i
;
4744 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
4745 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
4747 if ((lf
.lfPitchAndFamily
& 0x03) == FIXED_PITCH
)
4749 /* Fixed width font. */
4750 fontp
->average_width
= fontp
->space_width
= FONT_AVG_WIDTH (font
);
4756 pcm
= w32_per_char_metric (font
, &space
, ANSI_FONT
);
4758 fontp
->space_width
= pcm
->width
;
4760 fontp
->space_width
= FONT_AVG_WIDTH (font
);
4762 fontp
->average_width
= font
->tm
.tmAveCharWidth
;
4765 fontp
->charset
= -1;
4766 charset
= xlfd_charset_of_font (fontname
);
4768 /* Cache the W32 codepage for a font. This makes w32_encode_char
4769 (called for every glyph during redisplay) much faster. */
4770 fontp
->codepage
= codepage
;
4772 /* Work out the font's full name. */
4773 full_name
= (char *)xmalloc (100);
4774 if (full_name
&& w32_to_x_font (&lf
, full_name
, 100, charset
))
4775 fontp
->full_name
= full_name
;
4778 /* If all else fails - just use the name we used to load it. */
4780 fontp
->full_name
= fontp
->name
;
4783 fontp
->size
= FONT_WIDTH (font
);
4784 fontp
->height
= FONT_HEIGHT (font
);
4786 /* The slot `encoding' specifies how to map a character
4787 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
4788 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
4789 (0:0x20..0x7F, 1:0xA0..0xFF,
4790 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
4791 2:0xA020..0xFF7F). For the moment, we don't know which charset
4792 uses this font. So, we set information in fontp->encoding_type
4793 which is never used by any charset. If mapping can't be
4794 decided, set FONT_ENCODING_NOT_DECIDED. */
4796 /* SJIS fonts need to be set to type 4, all others seem to work as
4797 type FONT_ENCODING_NOT_DECIDED. */
4798 encoding
= strrchr (fontp
->name
, '-');
4799 if (encoding
&& strnicmp (encoding
+1, "sjis", 4) == 0)
4800 fontp
->encoding_type
= 4;
4802 fontp
->encoding_type
= FONT_ENCODING_NOT_DECIDED
;
4804 /* The following three values are set to 0 under W32, which is
4805 what they get set to if XGetFontProperty fails under X. */
4806 fontp
->baseline_offset
= 0;
4807 fontp
->relative_compose
= 0;
4808 fontp
->default_ascent
= 0;
4810 /* Set global flag fonts_changed_p to non-zero if the font loaded
4811 has a character with a smaller width than any other character
4812 before, or if the font loaded has a smaller height than any
4813 other font loaded before. If this happens, it will make a
4814 glyph matrix reallocation necessary. */
4815 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
4821 /* Load font named FONTNAME of size SIZE for frame F, and return a
4822 pointer to the structure font_info while allocating it dynamically.
4823 If loading fails, return NULL. */
4825 w32_load_font (f
,fontname
,size
)
4830 Lisp_Object bdf_fonts
;
4831 struct font_info
*retval
= NULL
;
4832 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4834 bdf_fonts
= w32_list_bdf_fonts (build_string (fontname
), 1);
4836 while (!retval
&& CONSP (bdf_fonts
))
4838 char *bdf_name
, *bdf_file
;
4839 Lisp_Object bdf_pair
;
4842 bdf_name
= SDATA (XCAR (bdf_fonts
));
4843 bdf_pair
= Fassoc (XCAR (bdf_fonts
), Vw32_bdf_filename_alist
);
4844 bdf_file
= SDATA (XCDR (bdf_pair
));
4846 // If the font is already loaded, do not load it again.
4847 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4849 if ((dpyinfo
->font_table
[i
].name
4850 && !strcmp (dpyinfo
->font_table
[i
].name
, bdf_name
))
4851 || (dpyinfo
->font_table
[i
].full_name
4852 && !strcmp (dpyinfo
->font_table
[i
].full_name
, bdf_name
)))
4853 return dpyinfo
->font_table
+ i
;
4856 retval
= w32_load_bdf_font (f
, bdf_name
, size
, bdf_file
);
4858 bdf_fonts
= XCDR (bdf_fonts
);
4864 return w32_load_system_font(f
, fontname
, size
);
4869 w32_unload_font (dpyinfo
, font
)
4870 struct w32_display_info
*dpyinfo
;
4875 if (font
->per_char
) xfree (font
->per_char
);
4876 if (font
->bdf
) w32_free_bdf_font (font
->bdf
);
4878 if (font
->hfont
) DeleteObject(font
->hfont
);
4883 /* The font conversion stuff between x and w32 */
4885 /* X font string is as follows (from faces.el)
4889 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
4890 * (weight\? "\\([^-]*\\)") ; 1
4891 * (slant "\\([ior]\\)") ; 2
4892 * (slant\? "\\([^-]?\\)") ; 2
4893 * (swidth "\\([^-]*\\)") ; 3
4894 * (adstyle "[^-]*") ; 4
4895 * (pixelsize "[0-9]+")
4896 * (pointsize "[0-9][0-9]+")
4897 * (resx "[0-9][0-9]+")
4898 * (resy "[0-9][0-9]+")
4899 * (spacing "[cmp?*]")
4900 * (avgwidth "[0-9]+")
4901 * (registry "[^-]+")
4902 * (encoding "[^-]+")
4907 x_to_w32_weight (lpw
)
4910 if (!lpw
) return (FW_DONTCARE
);
4912 if (stricmp (lpw
,"heavy") == 0) return FW_HEAVY
;
4913 else if (stricmp (lpw
,"extrabold") == 0) return FW_EXTRABOLD
;
4914 else if (stricmp (lpw
,"bold") == 0) return FW_BOLD
;
4915 else if (stricmp (lpw
,"demibold") == 0) return FW_SEMIBOLD
;
4916 else if (stricmp (lpw
,"semibold") == 0) return FW_SEMIBOLD
;
4917 else if (stricmp (lpw
,"medium") == 0) return FW_MEDIUM
;
4918 else if (stricmp (lpw
,"normal") == 0) return FW_NORMAL
;
4919 else if (stricmp (lpw
,"light") == 0) return FW_LIGHT
;
4920 else if (stricmp (lpw
,"extralight") == 0) return FW_EXTRALIGHT
;
4921 else if (stricmp (lpw
,"thin") == 0) return FW_THIN
;
4928 w32_to_x_weight (fnweight
)
4931 if (fnweight
>= FW_HEAVY
) return "heavy";
4932 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
4933 if (fnweight
>= FW_BOLD
) return "bold";
4934 if (fnweight
>= FW_SEMIBOLD
) return "demibold";
4935 if (fnweight
>= FW_MEDIUM
) return "medium";
4936 if (fnweight
>= FW_NORMAL
) return "normal";
4937 if (fnweight
>= FW_LIGHT
) return "light";
4938 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
4939 if (fnweight
>= FW_THIN
) return "thin";
4945 x_to_w32_charset (lpcs
)
4948 Lisp_Object this_entry
, w32_charset
;
4950 int len
= strlen (lpcs
);
4952 /* Support "*-#nnn" format for unknown charsets. */
4953 if (strncmp (lpcs
, "*-#", 3) == 0)
4954 return atoi (lpcs
+ 3);
4956 /* All Windows fonts qualify as unicode. */
4957 if (!strncmp (lpcs
, "iso10646", 8))
4958 return DEFAULT_CHARSET
;
4960 /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5". */
4961 charset
= alloca (len
+ 1);
4962 strcpy (charset
, lpcs
);
4963 lpcs
= strchr (charset
, '*');
4967 /* Look through w32-charset-info-alist for the character set.
4968 Format of each entry is
4969 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
4971 this_entry
= Fassoc (build_string(charset
), Vw32_charset_info_alist
);
4973 if (NILP(this_entry
))
4975 /* At startup, we want iso8859-1 fonts to come up properly. */
4976 if (stricmp(charset
, "iso8859-1") == 0)
4977 return ANSI_CHARSET
;
4979 return DEFAULT_CHARSET
;
4982 w32_charset
= Fcar (Fcdr (this_entry
));
4984 /* Translate Lisp symbol to number. */
4985 if (EQ (w32_charset
, Qw32_charset_ansi
))
4986 return ANSI_CHARSET
;
4987 if (EQ (w32_charset
, Qw32_charset_symbol
))
4988 return SYMBOL_CHARSET
;
4989 if (EQ (w32_charset
, Qw32_charset_shiftjis
))
4990 return SHIFTJIS_CHARSET
;
4991 if (EQ (w32_charset
, Qw32_charset_hangeul
))
4992 return HANGEUL_CHARSET
;
4993 if (EQ (w32_charset
, Qw32_charset_chinesebig5
))
4994 return CHINESEBIG5_CHARSET
;
4995 if (EQ (w32_charset
, Qw32_charset_gb2312
))
4996 return GB2312_CHARSET
;
4997 if (EQ (w32_charset
, Qw32_charset_oem
))
4999 #ifdef JOHAB_CHARSET
5000 if (EQ (w32_charset
, Qw32_charset_johab
))
5001 return JOHAB_CHARSET
;
5002 if (EQ (w32_charset
, Qw32_charset_easteurope
))
5003 return EASTEUROPE_CHARSET
;
5004 if (EQ (w32_charset
, Qw32_charset_turkish
))
5005 return TURKISH_CHARSET
;
5006 if (EQ (w32_charset
, Qw32_charset_baltic
))
5007 return BALTIC_CHARSET
;
5008 if (EQ (w32_charset
, Qw32_charset_russian
))
5009 return RUSSIAN_CHARSET
;
5010 if (EQ (w32_charset
, Qw32_charset_arabic
))
5011 return ARABIC_CHARSET
;
5012 if (EQ (w32_charset
, Qw32_charset_greek
))
5013 return GREEK_CHARSET
;
5014 if (EQ (w32_charset
, Qw32_charset_hebrew
))
5015 return HEBREW_CHARSET
;
5016 if (EQ (w32_charset
, Qw32_charset_vietnamese
))
5017 return VIETNAMESE_CHARSET
;
5018 if (EQ (w32_charset
, Qw32_charset_thai
))
5019 return THAI_CHARSET
;
5020 if (EQ (w32_charset
, Qw32_charset_mac
))
5022 #endif /* JOHAB_CHARSET */
5023 #ifdef UNICODE_CHARSET
5024 if (EQ (w32_charset
, Qw32_charset_unicode
))
5025 return UNICODE_CHARSET
;
5028 return DEFAULT_CHARSET
;
5033 w32_to_x_charset (fncharset
, matching
)
5037 static char buf
[32];
5038 Lisp_Object charset_type
;
5043 /* If fully specified, accept it as it is. Otherwise use a
5045 char *wildcard
= strchr (matching
, '*');
5048 else if (strchr (matching
, '-'))
5051 match_len
= strlen (matching
);
5057 /* Handle startup case of w32-charset-info-alist not
5058 being set up yet. */
5059 if (NILP(Vw32_charset_info_alist
))
5061 charset_type
= Qw32_charset_ansi
;
5063 case DEFAULT_CHARSET
:
5064 charset_type
= Qw32_charset_default
;
5066 case SYMBOL_CHARSET
:
5067 charset_type
= Qw32_charset_symbol
;
5069 case SHIFTJIS_CHARSET
:
5070 charset_type
= Qw32_charset_shiftjis
;
5072 case HANGEUL_CHARSET
:
5073 charset_type
= Qw32_charset_hangeul
;
5075 case GB2312_CHARSET
:
5076 charset_type
= Qw32_charset_gb2312
;
5078 case CHINESEBIG5_CHARSET
:
5079 charset_type
= Qw32_charset_chinesebig5
;
5082 charset_type
= Qw32_charset_oem
;
5085 /* More recent versions of Windows (95 and NT4.0) define more
5087 #ifdef EASTEUROPE_CHARSET
5088 case EASTEUROPE_CHARSET
:
5089 charset_type
= Qw32_charset_easteurope
;
5091 case TURKISH_CHARSET
:
5092 charset_type
= Qw32_charset_turkish
;
5094 case BALTIC_CHARSET
:
5095 charset_type
= Qw32_charset_baltic
;
5097 case RUSSIAN_CHARSET
:
5098 charset_type
= Qw32_charset_russian
;
5100 case ARABIC_CHARSET
:
5101 charset_type
= Qw32_charset_arabic
;
5104 charset_type
= Qw32_charset_greek
;
5106 case HEBREW_CHARSET
:
5107 charset_type
= Qw32_charset_hebrew
;
5109 case VIETNAMESE_CHARSET
:
5110 charset_type
= Qw32_charset_vietnamese
;
5113 charset_type
= Qw32_charset_thai
;
5116 charset_type
= Qw32_charset_mac
;
5119 charset_type
= Qw32_charset_johab
;
5123 #ifdef UNICODE_CHARSET
5124 case UNICODE_CHARSET
:
5125 charset_type
= Qw32_charset_unicode
;
5129 /* Encode numerical value of unknown charset. */
5130 sprintf (buf
, "*-#%u", fncharset
);
5136 char * best_match
= NULL
;
5137 int matching_found
= 0;
5139 /* Look through w32-charset-info-alist for the character set.
5140 Prefer ISO codepages, and prefer lower numbers in the ISO
5141 range. Only return charsets for codepages which are installed.
5143 Format of each entry is
5144 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5146 for (rest
= Vw32_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
5149 Lisp_Object w32_charset
;
5150 Lisp_Object codepage
;
5152 Lisp_Object this_entry
= XCAR (rest
);
5154 /* Skip invalid entries in alist. */
5155 if (!CONSP (this_entry
) || !STRINGP (XCAR (this_entry
))
5156 || !CONSP (XCDR (this_entry
))
5157 || !SYMBOLP (XCAR (XCDR (this_entry
))))
5160 x_charset
= SDATA (XCAR (this_entry
));
5161 w32_charset
= XCAR (XCDR (this_entry
));
5162 codepage
= XCDR (XCDR (this_entry
));
5164 /* Look for Same charset and a valid codepage (or non-int
5165 which means ignore). */
5166 if (EQ (w32_charset
, charset_type
)
5167 && (!INTEGERP (codepage
) || XINT (codepage
) == CP_DEFAULT
5168 || IsValidCodePage (XINT (codepage
))))
5170 /* If we don't have a match already, then this is the
5174 best_match
= x_charset
;
5175 if (matching
&& !strnicmp (x_charset
, matching
, match_len
))
5178 /* If we already found a match for MATCHING, then
5179 only consider other matches. */
5180 else if (matching_found
5181 && strnicmp (x_charset
, matching
, match_len
))
5183 /* If this matches what we want, and the best so far doesn't,
5184 then this is better. */
5185 else if (!matching_found
&& matching
5186 && !strnicmp (x_charset
, matching
, match_len
))
5188 best_match
= x_charset
;
5191 /* If this is fully specified, and the best so far isn't,
5192 then this is better. */
5193 else if ((!strchr (best_match
, '-') && strchr (x_charset
, '-'))
5194 /* If this is an ISO codepage, and the best so far isn't,
5195 then this is better, but only if it fully specifies the
5197 || (strnicmp (best_match
, "iso", 3) != 0
5198 && strnicmp (x_charset
, "iso", 3) == 0
5199 && strchr (x_charset
, '-')))
5200 best_match
= x_charset
;
5201 /* If both are ISO8859 codepages, choose the one with the
5202 lowest number in the encoding field. */
5203 else if (strnicmp (best_match
, "iso8859-", 8) == 0
5204 && strnicmp (x_charset
, "iso8859-", 8) == 0)
5206 int best_enc
= atoi (best_match
+ 8);
5207 int this_enc
= atoi (x_charset
+ 8);
5208 if (this_enc
> 0 && this_enc
< best_enc
)
5209 best_match
= x_charset
;
5214 /* If no match, encode the numeric value. */
5217 sprintf (buf
, "*-#%u", fncharset
);
5221 strncpy (buf
, best_match
, 31);
5222 /* If the charset is not fully specified, put -0 on the end. */
5223 if (!strchr (best_match
, '-'))
5225 int pos
= strlen (best_match
);
5226 /* Charset specifiers shouldn't be very long. If it is a made
5227 up one, truncating it should not do any harm since it isn't
5228 recognized anyway. */
5231 strcpy (buf
+ pos
, "-0");
5239 /* Return all the X charsets that map to a font. */
5241 w32_to_all_x_charsets (fncharset
)
5244 static char buf
[32];
5245 Lisp_Object charset_type
;
5246 Lisp_Object retval
= Qnil
;
5251 /* Handle startup case of w32-charset-info-alist not
5252 being set up yet. */
5253 if (NILP(Vw32_charset_info_alist
))
5254 return Fcons (build_string ("iso8859-1"), Qnil
);
5256 charset_type
= Qw32_charset_ansi
;
5258 case DEFAULT_CHARSET
:
5259 charset_type
= Qw32_charset_default
;
5261 case SYMBOL_CHARSET
:
5262 charset_type
= Qw32_charset_symbol
;
5264 case SHIFTJIS_CHARSET
:
5265 charset_type
= Qw32_charset_shiftjis
;
5267 case HANGEUL_CHARSET
:
5268 charset_type
= Qw32_charset_hangeul
;
5270 case GB2312_CHARSET
:
5271 charset_type
= Qw32_charset_gb2312
;
5273 case CHINESEBIG5_CHARSET
:
5274 charset_type
= Qw32_charset_chinesebig5
;
5277 charset_type
= Qw32_charset_oem
;
5280 /* More recent versions of Windows (95 and NT4.0) define more
5282 #ifdef EASTEUROPE_CHARSET
5283 case EASTEUROPE_CHARSET
:
5284 charset_type
= Qw32_charset_easteurope
;
5286 case TURKISH_CHARSET
:
5287 charset_type
= Qw32_charset_turkish
;
5289 case BALTIC_CHARSET
:
5290 charset_type
= Qw32_charset_baltic
;
5292 case RUSSIAN_CHARSET
:
5293 charset_type
= Qw32_charset_russian
;
5295 case ARABIC_CHARSET
:
5296 charset_type
= Qw32_charset_arabic
;
5299 charset_type
= Qw32_charset_greek
;
5301 case HEBREW_CHARSET
:
5302 charset_type
= Qw32_charset_hebrew
;
5304 case VIETNAMESE_CHARSET
:
5305 charset_type
= Qw32_charset_vietnamese
;
5308 charset_type
= Qw32_charset_thai
;
5311 charset_type
= Qw32_charset_mac
;
5314 charset_type
= Qw32_charset_johab
;
5318 #ifdef UNICODE_CHARSET
5319 case UNICODE_CHARSET
:
5320 charset_type
= Qw32_charset_unicode
;
5324 /* Encode numerical value of unknown charset. */
5325 sprintf (buf
, "*-#%u", fncharset
);
5326 return Fcons (build_string (buf
), Qnil
);
5331 /* Look through w32-charset-info-alist for the character set.
5332 Only return fully specified charsets for codepages which are
5335 Format of each entry in Vw32_charset_info_alist is
5336 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5338 for (rest
= Vw32_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
5340 Lisp_Object x_charset
;
5341 Lisp_Object w32_charset
;
5342 Lisp_Object codepage
;
5344 Lisp_Object this_entry
= XCAR (rest
);
5346 /* Skip invalid entries in alist. */
5347 if (!CONSP (this_entry
) || !STRINGP (XCAR (this_entry
))
5348 || !CONSP (XCDR (this_entry
))
5349 || !SYMBOLP (XCAR (XCDR (this_entry
))))
5352 x_charset
= XCAR (this_entry
);
5353 w32_charset
= XCAR (XCDR (this_entry
));
5354 codepage
= XCDR (XCDR (this_entry
));
5356 if (!strchr (SDATA (x_charset
), '-'))
5359 /* Look for Same charset and a valid codepage (or non-int
5360 which means ignore). */
5361 if (EQ (w32_charset
, charset_type
)
5362 && (!INTEGERP (codepage
) || XINT (codepage
) == CP_DEFAULT
5363 || IsValidCodePage (XINT (codepage
))))
5365 retval
= Fcons (x_charset
, retval
);
5369 /* If no match, encode the numeric value. */
5372 sprintf (buf
, "*-#%u", fncharset
);
5373 return Fcons (build_string (buf
), Qnil
);
5380 /* Get the Windows codepage corresponding to the specified font. The
5381 charset info in the font name is used to look up
5382 w32-charset-to-codepage-alist. */
5384 w32_codepage_for_font (char *fontname
)
5386 Lisp_Object codepage
, entry
;
5387 char *charset_str
, *charset
, *end
;
5389 /* Extract charset part of font string. */
5390 charset
= xlfd_charset_of_font (fontname
);
5395 charset_str
= (char *) alloca (strlen (charset
) + 1);
5396 strcpy (charset_str
, charset
);
5399 /* Remove leading "*-". */
5400 if (strncmp ("*-", charset_str
, 2) == 0)
5401 charset
= charset_str
+ 2;
5404 charset
= charset_str
;
5406 /* Stop match at wildcard (including preceding '-'). */
5407 if (end
= strchr (charset
, '*'))
5409 if (end
> charset
&& *(end
-1) == '-')
5414 if (!strcmp (charset
, "iso10646"))
5417 if (NILP (Vw32_charset_info_alist
))
5420 entry
= Fassoc (build_string(charset
), Vw32_charset_info_alist
);
5424 codepage
= Fcdr (Fcdr (entry
));
5426 if (NILP (codepage
))
5428 else if (XFASTINT (codepage
) == XFASTINT (Qt
))
5430 else if (INTEGERP (codepage
))
5431 return XINT (codepage
);
5438 w32_to_x_font (lplogfont
, lpxstr
, len
, specific_charset
)
5439 LOGFONT
* lplogfont
;
5442 char * specific_charset
;
5446 char height_pixels
[8];
5448 char width_pixels
[8];
5449 char *fontname_dash
;
5450 int display_resy
= (int) one_w32_display_info
.resy
;
5451 int display_resx
= (int) one_w32_display_info
.resx
;
5452 struct coding_system coding
;
5454 if (!lpxstr
) abort ();
5459 if (lplogfont
->lfOutPrecision
== OUT_STRING_PRECIS
)
5460 fonttype
= "raster";
5461 else if (lplogfont
->lfOutPrecision
== OUT_STROKE_PRECIS
)
5462 fonttype
= "outline";
5464 fonttype
= "unknown";
5466 setup_coding_system (Fcheck_coding_system (Vlocale_coding_system
),
5468 coding
.src_multibyte
= 0;
5469 coding
.dst_multibyte
= 1;
5470 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5471 /* We explicitely disable composition handling because selection
5472 data should not contain any composition sequence. */
5473 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
5475 coding
.dst_bytes
= LF_FACESIZE
* 2;
5476 coding
.destination
= (unsigned char *) xmalloc (coding
.dst_bytes
+ 1);
5477 decode_coding_c_string (&coding
, lplogfont
->lfFaceName
,
5478 strlen(lplogfont
->lfFaceName
), Qnil
);
5479 fontname
= coding
.destination
;
5481 *(fontname
+ coding
.produced
) = '\0';
5483 /* Replace dashes with underscores so the dashes are not
5485 fontname_dash
= fontname
;
5486 while (fontname_dash
= strchr (fontname_dash
, '-'))
5487 *fontname_dash
= '_';
5489 if (lplogfont
->lfHeight
)
5491 sprintf (height_pixels
, "%u", abs (lplogfont
->lfHeight
));
5492 sprintf (height_dpi
, "%u",
5493 abs (lplogfont
->lfHeight
) * 720 / display_resy
);
5497 strcpy (height_pixels
, "*");
5498 strcpy (height_dpi
, "*");
5501 #if 0 /* Never put the width in the xfld. It fails on fonts with
5502 double-width characters. */
5503 if (lplogfont
->lfWidth
)
5504 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
5507 strcpy (width_pixels
, "*");
5509 _snprintf (lpxstr
, len
- 1,
5510 "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
5511 fonttype
, /* foundry */
5512 fontname
, /* family */
5513 w32_to_x_weight (lplogfont
->lfWeight
), /* weight */
5514 lplogfont
->lfItalic
?'i':'r', /* slant */
5516 /* add style name */
5517 height_pixels
, /* pixel size */
5518 height_dpi
, /* point size */
5519 display_resx
, /* resx */
5520 display_resy
, /* resy */
5521 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
)
5522 ? 'p' : 'c', /* spacing */
5523 width_pixels
, /* avg width */
5524 w32_to_x_charset (lplogfont
->lfCharSet
, specific_charset
)
5525 /* charset registry and encoding */
5528 lpxstr
[len
- 1] = 0; /* just to be sure */
5533 x_to_w32_font (lpxstr
, lplogfont
)
5535 LOGFONT
* lplogfont
;
5537 struct coding_system coding
;
5539 if (!lplogfont
) return (FALSE
);
5541 memset (lplogfont
, 0, sizeof (*lplogfont
));
5543 /* Set default value for each field. */
5545 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5546 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5547 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
5549 /* go for maximum quality */
5550 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
5551 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
5552 lplogfont
->lfQuality
= PROOF_QUALITY
;
5555 lplogfont
->lfCharSet
= DEFAULT_CHARSET
;
5556 lplogfont
->lfWeight
= FW_DONTCARE
;
5557 lplogfont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
5562 /* Provide a simple escape mechanism for specifying Windows font names
5563 * directly -- if font spec does not beginning with '-', assume this
5565 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
5571 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10],
5572 width
[10], resy
[10], remainder
[50];
5574 int dpi
= (int) one_w32_display_info
.resy
;
5576 fields
= sscanf (lpxstr
,
5577 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
5578 name
, weight
, &slant
, pixels
, height
, resy
, &pitch
, width
, remainder
);
5582 /* In the general case when wildcards cover more than one field,
5583 we don't know which field is which, so don't fill any in.
5584 However, we need to cope with this particular form, which is
5585 generated by font_list_1 (invoked by try_font_list):
5586 "-raster-6x10-*-gb2312*-*"
5587 and make sure to correctly parse the charset field. */
5590 fields
= sscanf (lpxstr
,
5591 "-%*[^-]-%49[^-]-*-%49s",
5594 else if (fields
< 9)
5600 if (fields
> 0 && name
[0] != '*')
5602 Lisp_Object string
= build_string (name
);
5604 (Fcheck_coding_system (Vlocale_coding_system
), &coding
);
5605 coding
.mode
|= (CODING_MODE_SAFE_ENCODING
| CODING_MODE_LAST_BLOCK
);
5606 /* Disable composition/charset annotation. */
5607 coding
.common_flags
&= ~CODING_ANNOTATION_MASK
;
5608 coding
.dst_bytes
= SCHARS (string
) * 2;
5610 coding
.destination
= (unsigned char *) xmalloc (coding
.dst_bytes
);
5611 encode_coding_object (&coding
, string
, 0, 0,
5612 SCHARS (string
), SBYTES (string
), Qnil
);
5613 if (coding
.produced
>= LF_FACESIZE
)
5614 coding
.produced
= LF_FACESIZE
- 1;
5616 coding
.destination
[coding
.produced
] = '\0';
5618 strcpy (lplogfont
->lfFaceName
, coding
.destination
);
5619 xfree (coding
.destination
);
5623 lplogfont
->lfFaceName
[0] = '\0';
5628 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5632 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
5636 if (fields
> 0 && pixels
[0] != '*')
5637 lplogfont
->lfHeight
= atoi (pixels
);
5641 if (fields
> 0 && resy
[0] != '*')
5644 if (tem
> 0) dpi
= tem
;
5647 if (fields
> -1 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
5648 lplogfont
->lfHeight
= atoi (height
) * dpi
/ 720;
5653 lplogfont
->lfPitchAndFamily
= VARIABLE_PITCH
| FF_DONTCARE
;
5654 else if (pitch
== 'c')
5655 lplogfont
->lfPitchAndFamily
= FIXED_PITCH
| FF_DONTCARE
;
5660 if (fields
> 0 && width
[0] != '*')
5661 lplogfont
->lfWidth
= atoi (width
) / 10;
5665 /* Strip the trailing '-' if present. (it shouldn't be, as it
5666 fails the test against xlfd-tight-regexp in fontset.el). */
5668 int len
= strlen (remainder
);
5669 if (len
> 0 && remainder
[len
-1] == '-')
5670 remainder
[len
-1] = 0;
5672 encoding
= remainder
;
5674 if (strncmp (encoding
, "*-", 2) == 0)
5677 lplogfont
->lfCharSet
= x_to_w32_charset (encoding
);
5682 char name
[100], height
[10], width
[10], weight
[20];
5684 fields
= sscanf (lpxstr
,
5685 "%99[^:]:%9[^:]:%9[^:]:%19s",
5686 name
, height
, width
, weight
);
5688 if (fields
== EOF
) return (FALSE
);
5692 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
5693 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
5697 lplogfont
->lfFaceName
[0] = 0;
5703 lplogfont
->lfHeight
= atoi (height
);
5708 lplogfont
->lfWidth
= atoi (width
);
5712 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5715 /* This makes TrueType fonts work better. */
5716 lplogfont
->lfHeight
= - abs (lplogfont
->lfHeight
);
5721 /* Strip the pixel height and point height from the given xlfd, and
5722 return the pixel height. If no pixel height is specified, calculate
5723 one from the point height, or if that isn't defined either, return
5724 0 (which usually signifies a scalable font).
5727 xlfd_strip_height (char *fontname
)
5729 int pixel_height
, field_number
;
5730 char *read_from
, *write_to
;
5734 pixel_height
= field_number
= 0;
5737 /* Look for height fields. */
5738 for (read_from
= fontname
; *read_from
; read_from
++)
5740 if (*read_from
== '-')
5743 if (field_number
== 7) /* Pixel height. */
5746 write_to
= read_from
;
5748 /* Find end of field. */
5749 for (;*read_from
&& *read_from
!= '-'; read_from
++)
5752 /* Split the fontname at end of field. */
5758 pixel_height
= atoi (write_to
);
5759 /* Blank out field. */
5760 if (read_from
> write_to
)
5765 /* If the pixel height field is at the end (partial xlfd),
5768 return pixel_height
;
5770 /* If we got a pixel height, the point height can be
5771 ignored. Just blank it out and break now. */
5774 /* Find end of point size field. */
5775 for (; *read_from
&& *read_from
!= '-'; read_from
++)
5781 /* Blank out the point size field. */
5782 if (read_from
> write_to
)
5788 return pixel_height
;
5792 /* If the point height is already blank, break now. */
5793 if (*read_from
== '-')
5799 else if (field_number
== 8)
5801 /* If we didn't get a pixel height, try to get the point
5802 height and convert that. */
5804 char *point_size_start
= read_from
++;
5806 /* Find end of field. */
5807 for (; *read_from
&& *read_from
!= '-'; read_from
++)
5816 point_size
= atoi (point_size_start
);
5818 /* Convert to pixel height. */
5819 pixel_height
= point_size
5820 * one_w32_display_info
.height_in
/ 720;
5822 /* Blank out this field and break. */
5830 /* Shift the rest of the font spec into place. */
5831 if (write_to
&& read_from
> write_to
)
5833 for (; *read_from
; read_from
++, write_to
++)
5834 *write_to
= *read_from
;
5838 return pixel_height
;
5841 /* Assume parameter 1 is fully qualified, no wildcards. */
5843 w32_font_match (fontname
, pattern
)
5848 char *font_name_copy
;
5849 char *regex
= alloca (strlen (pattern
) * 2 + 3);
5851 font_name_copy
= alloca (strlen (fontname
) + 1);
5852 strcpy (font_name_copy
, fontname
);
5857 /* Turn pattern into a regexp and do a regexp match. */
5858 for (; *pattern
; pattern
++)
5860 if (*pattern
== '?')
5862 else if (*pattern
== '*')
5873 /* Strip out font heights and compare them seperately, since
5874 rounding error can cause mismatches. This also allows a
5875 comparison between a font that declares only a pixel height and a
5876 pattern that declares the point height.
5879 int font_height
, pattern_height
;
5881 font_height
= xlfd_strip_height (font_name_copy
);
5882 pattern_height
= xlfd_strip_height (regex
);
5884 /* Compare now, and don't bother doing expensive regexp matching
5885 if the heights differ. */
5886 if (font_height
&& pattern_height
&& (font_height
!= pattern_height
))
5890 return (fast_string_match_ignore_case (build_string (regex
),
5891 build_string(font_name_copy
)) >= 0);
5894 /* Callback functions, and a structure holding info they need, for
5895 listing system fonts on W32. We need one set of functions to do the
5896 job properly, but these don't work on NT 3.51 and earlier, so we
5897 have a second set which don't handle character sets properly to
5900 In both cases, there are two passes made. The first pass gets one
5901 font from each family, the second pass lists all the fonts from
5904 typedef struct enumfont_t
5909 XFontStruct
*size_ref
;
5910 Lisp_Object pattern
;
5916 enum_font_maybe_add_to_list (enumfont_t
*, LOGFONT
*, char *, Lisp_Object
);
5920 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
5922 NEWTEXTMETRIC
* lptm
;
5926 /* Ignore struck out and underlined versions of fonts. */
5927 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
5930 /* Only return fonts with names starting with @ if they were
5931 explicitly specified, since Microsoft uses an initial @ to
5932 denote fonts for vertical writing, without providing a more
5933 convenient way of identifying them. */
5934 if (lplf
->elfLogFont
.lfFaceName
[0] == '@'
5935 && lpef
->logfont
.lfFaceName
[0] != '@')
5938 /* Check that the character set matches if it was specified */
5939 if (lpef
->logfont
.lfCharSet
!= DEFAULT_CHARSET
&&
5940 lplf
->elfLogFont
.lfCharSet
!= lpef
->logfont
.lfCharSet
)
5943 if (FontType
== RASTER_FONTTYPE
)
5945 /* DBCS raster fonts have problems displaying, so skip them. */
5946 int charset
= lplf
->elfLogFont
.lfCharSet
;
5947 if (charset
== SHIFTJIS_CHARSET
5948 || charset
== HANGEUL_CHARSET
5949 || charset
== CHINESEBIG5_CHARSET
5950 || charset
== GB2312_CHARSET
5951 #ifdef JOHAB_CHARSET
5952 || charset
== JOHAB_CHARSET
5960 Lisp_Object width
= Qnil
;
5961 Lisp_Object charset_list
= Qnil
;
5962 char *charset
= NULL
;
5964 /* Truetype fonts do not report their true metrics until loaded */
5965 if (FontType
!= RASTER_FONTTYPE
)
5967 if (!NILP (lpef
->pattern
))
5969 /* Scalable fonts are as big as you want them to be. */
5970 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
5971 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
5972 width
= make_number (lpef
->logfont
.lfWidth
);
5976 lplf
->elfLogFont
.lfHeight
= 0;
5977 lplf
->elfLogFont
.lfWidth
= 0;
5981 /* Make sure the height used here is the same as everywhere
5982 else (ie character height, not cell height). */
5983 if (lplf
->elfLogFont
.lfHeight
> 0)
5985 /* lptm can be trusted for RASTER fonts, but not scalable ones. */
5986 if (FontType
== RASTER_FONTTYPE
)
5987 lplf
->elfLogFont
.lfHeight
= lptm
->tmInternalLeading
- lptm
->tmHeight
;
5989 lplf
->elfLogFont
.lfHeight
= -lplf
->elfLogFont
.lfHeight
;
5992 if (!NILP (lpef
->pattern
))
5994 charset
= xlfd_charset_of_font (SDATA (lpef
->pattern
));
5996 /* We already checked charsets above, but DEFAULT_CHARSET
5997 slipped through. So only allow exact matches for DEFAULT_CHARSET. */
5999 && strncmp (charset
, "*-*", 3) != 0
6000 && lpef
->logfont
.lfCharSet
== DEFAULT_CHARSET
6001 && strcmp (charset
, w32_to_x_charset (DEFAULT_CHARSET
, NULL
)) != 0)
6006 charset_list
= Fcons (build_string (charset
), Qnil
);
6008 /* Always prefer unicode. */
6010 = Fcons (build_string ("iso10646-1"),
6011 w32_to_all_x_charsets (lplf
->elfLogFont
.lfCharSet
));
6013 /* Loop through the charsets. */
6014 for ( ; CONSP (charset_list
); charset_list
= Fcdr (charset_list
))
6016 Lisp_Object this_charset
= Fcar (charset_list
);
6017 charset
= SDATA (this_charset
);
6019 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6022 /* List bold and italic variations if w32-enable-synthesized-fonts
6023 is non-nil and this is a plain font. */
6024 if (w32_enable_synthesized_fonts
6025 && lplf
->elfLogFont
.lfWeight
== FW_NORMAL
6026 && lplf
->elfLogFont
.lfItalic
== FALSE
)
6029 lplf
->elfLogFont
.lfWeight
= FW_BOLD
;
6030 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6033 lplf
->elfLogFont
.lfItalic
= TRUE
;
6034 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6037 lplf
->elfLogFont
.lfWeight
= FW_NORMAL
;
6038 enum_font_maybe_add_to_list (lpef
, &(lplf
->elfLogFont
),
6048 enum_font_maybe_add_to_list (lpef
, logfont
, match_charset
, width
)
6051 char * match_charset
;
6056 if (!w32_to_x_font (logfont
, buf
, 100, match_charset
))
6059 if (NILP (lpef
->pattern
)
6060 || w32_font_match (buf
, SDATA (lpef
->pattern
)))
6062 /* Check if we already listed this font. This may happen if
6063 w32_enable_synthesized_fonts is non-nil, and there are real
6064 bold and italic versions of the font. */
6065 Lisp_Object font_name
= build_string (buf
);
6066 if (NILP (Fmember (font_name
, lpef
->list
)))
6068 Lisp_Object entry
= Fcons (font_name
, width
);
6069 lpef
->list
= Fcons (entry
, lpef
->list
);
6077 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
6079 NEWTEXTMETRIC
* lptm
;
6083 return EnumFontFamilies (lpef
->hdc
,
6084 lplf
->elfLogFont
.lfFaceName
,
6085 (FONTENUMPROC
) enum_font_cb2
,
6091 enum_fontex_cb2 (lplf
, lptm
, font_type
, lpef
)
6092 ENUMLOGFONTEX
* lplf
;
6093 NEWTEXTMETRICEX
* lptm
;
6097 /* We are not interested in the extra info we get back from the 'Ex
6098 version - only the fact that we get character set variations
6099 enumerated seperately. */
6100 return enum_font_cb2 ((ENUMLOGFONT
*) lplf
, (NEWTEXTMETRIC
*) lptm
,
6105 enum_fontex_cb1 (lplf
, lptm
, font_type
, lpef
)
6106 ENUMLOGFONTEX
* lplf
;
6107 NEWTEXTMETRICEX
* lptm
;
6111 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6112 FARPROC enum_font_families_ex
6113 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6114 /* We don't really expect EnumFontFamiliesEx to disappear once we
6115 get here, so don't bother handling it gracefully. */
6116 if (enum_font_families_ex
== NULL
)
6117 error ("gdi32.dll has disappeared!");
6118 return enum_font_families_ex (lpef
->hdc
,
6120 (FONTENUMPROC
) enum_fontex_cb2
,
6124 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
6125 and xterm.c in Emacs 20.3) */
6127 static Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
)
6129 char *fontname
, *ptnstr
;
6130 Lisp_Object list
, tem
, newlist
= Qnil
;
6133 list
= Vw32_bdf_filename_alist
;
6134 ptnstr
= SDATA (pattern
);
6136 for ( ; CONSP (list
); list
= XCDR (list
))
6140 fontname
= SDATA (XCAR (tem
));
6141 else if (STRINGP (tem
))
6142 fontname
= SDATA (tem
);
6146 if (w32_font_match (fontname
, ptnstr
))
6148 newlist
= Fcons (XCAR (tem
), newlist
);
6150 if (max_names
>= 0 && n_fonts
>= max_names
)
6159 /* Return a list of names of available fonts matching PATTERN on frame
6160 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6161 to be listed. Frame F NULL means we have not yet created any
6162 frame, which means we can't get proper size info, as we don't have
6163 a device context to use for GetTextMetrics.
6164 MAXNAMES sets a limit on how many fonts to match. If MAXNAMES is
6165 negative, then all matching fonts are returned. */
6168 w32_list_fonts (f
, pattern
, size
, maxnames
)
6170 Lisp_Object pattern
;
6174 Lisp_Object patterns
, key
= Qnil
, tem
, tpat
;
6175 Lisp_Object list
= Qnil
, newlist
= Qnil
, second_best
= Qnil
;
6176 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6179 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6180 if (NILP (patterns
))
6181 patterns
= Fcons (pattern
, Qnil
);
6183 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6188 tpat
= XCAR (patterns
);
6190 if (!STRINGP (tpat
))
6193 /* Avoid expensive EnumFontFamilies functions if we are not
6194 going to be able to output one of these anyway. */
6195 codepage
= w32_codepage_for_font (SDATA (tpat
));
6196 if (codepage
!= CP_8BIT
&& codepage
!= CP_UNICODE
6197 && codepage
!= CP_DEFAULT
&& codepage
!= CP_UNKNOWN
6198 && !IsValidCodePage(codepage
))
6201 /* See if we cached the result for this particular query.
6202 The cache is an alist of the form:
6203 ((PATTERN (FONTNAME . WIDTH) ...) ...)
6205 if (tem
= XCDR (dpyinfo
->name_list_element
),
6206 !NILP (list
= Fassoc (tpat
, tem
)))
6208 list
= Fcdr_safe (list
);
6209 /* We have a cached list. Don't have to get the list again. */
6214 /* At first, put PATTERN in the cache. */
6219 /* Use EnumFontFamiliesEx where it is available, as it knows
6220 about character sets. Fall back to EnumFontFamilies for
6221 older versions of NT that don't support the 'Ex function. */
6222 x_to_w32_font (SDATA (tpat
), &ef
.logfont
);
6224 LOGFONT font_match_pattern
;
6225 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
6226 FARPROC enum_font_families_ex
6227 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
6229 /* We do our own pattern matching so we can handle wildcards. */
6230 font_match_pattern
.lfFaceName
[0] = 0;
6231 font_match_pattern
.lfPitchAndFamily
= 0;
6232 /* We can use the charset, because if it is a wildcard it will
6233 be DEFAULT_CHARSET anyway. */
6234 font_match_pattern
.lfCharSet
= ef
.logfont
.lfCharSet
;
6236 ef
.hdc
= GetDC (dpyinfo
->root_window
);
6238 if (enum_font_families_ex
)
6239 enum_font_families_ex (ef
.hdc
,
6240 &font_match_pattern
,
6241 (FONTENUMPROC
) enum_fontex_cb1
,
6244 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
,
6247 ReleaseDC (dpyinfo
->root_window
, ef
.hdc
);
6253 /* Make a list of the fonts we got back.
6254 Store that in the font cache for the display. */
6255 XSETCDR (dpyinfo
->name_list_element
,
6256 Fcons (Fcons (tpat
, list
),
6257 XCDR (dpyinfo
->name_list_element
)));
6260 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6262 newlist
= second_best
= Qnil
;
6264 /* Make a list of the fonts that have the right width. */
6265 for (; CONSP (list
); list
= XCDR (list
))
6272 if (NILP (XCAR (tem
)))
6276 newlist
= Fcons (XCAR (tem
), newlist
);
6278 if (maxnames
>= 0 && n_fonts
>= maxnames
)
6283 if (!INTEGERP (XCDR (tem
)))
6285 /* Since we don't yet know the size of the font, we must
6286 load it and try GetTextMetrics. */
6287 W32FontStruct thisinfo
;
6292 if (!x_to_w32_font (SDATA (XCAR (tem
)), &lf
))
6296 thisinfo
.bdf
= NULL
;
6297 thisinfo
.hfont
= CreateFontIndirect (&lf
);
6298 if (thisinfo
.hfont
== NULL
)
6301 hdc
= GetDC (dpyinfo
->root_window
);
6302 oldobj
= SelectObject (hdc
, thisinfo
.hfont
);
6303 if (GetTextMetrics (hdc
, &thisinfo
.tm
))
6304 XSETCDR (tem
, make_number (FONT_AVG_WIDTH (&thisinfo
)));
6306 XSETCDR (tem
, make_number (0));
6307 SelectObject (hdc
, oldobj
);
6308 ReleaseDC (dpyinfo
->root_window
, hdc
);
6309 DeleteObject(thisinfo
.hfont
);
6312 found_size
= XINT (XCDR (tem
));
6313 if (found_size
== size
)
6315 newlist
= Fcons (XCAR (tem
), newlist
);
6317 if (maxnames
>= 0 && n_fonts
>= maxnames
)
6320 /* keep track of the closest matching size in case
6321 no exact match is found. */
6322 else if (found_size
> 0)
6324 if (NILP (second_best
))
6327 else if (found_size
< size
)
6329 if (XINT (XCDR (second_best
)) > size
6330 || XINT (XCDR (second_best
)) < found_size
)
6335 if (XINT (XCDR (second_best
)) > size
6336 && XINT (XCDR (second_best
)) >
6343 if (!NILP (newlist
))
6345 else if (!NILP (second_best
))
6347 newlist
= Fcons (XCAR (second_best
), Qnil
);
6352 /* Include any bdf fonts. */
6353 if (n_fonts
< maxnames
|| maxnames
< 0)
6355 Lisp_Object combined
[2];
6356 combined
[0] = w32_list_bdf_fonts (pattern
, maxnames
- n_fonts
);
6357 combined
[1] = newlist
;
6358 newlist
= Fnconc(2, combined
);
6365 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6367 w32_get_font_info (f
, font_idx
)
6371 return (FRAME_W32_FONT_TABLE (f
) + font_idx
);
6376 w32_query_font (struct frame
*f
, char *fontname
)
6379 struct font_info
*pfi
;
6381 pfi
= FRAME_W32_FONT_TABLE (f
);
6383 for (i
= 0; i
< one_w32_display_info
.n_fonts
;i
++, pfi
++)
6385 if (stricmp(pfi
->name
, fontname
) == 0) return pfi
;
6391 /* Find a CCL program for a font specified by FONTP, and set the member
6392 `encoder' of the structure. */
6395 w32_find_ccl_program (fontp
)
6396 struct font_info
*fontp
;
6398 Lisp_Object list
, elt
;
6400 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
6404 && STRINGP (XCAR (elt
))
6405 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
6411 struct ccl_program
*ccl
6412 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6414 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
6417 fontp
->font_encoder
= ccl
;
6421 /* directory-files from dired.c. */
6422 Lisp_Object Fdirectory_files
P_((Lisp_Object
, Lisp_Object
, Lisp_Object
, Lisp_Object
));
6425 /* Find BDF files in a specified directory. (use GCPRO when calling,
6426 as this calls lisp to get a directory listing). */
6428 w32_find_bdf_fonts_in_dir (Lisp_Object directory
)
6430 Lisp_Object filelist
, list
= Qnil
;
6433 if (!STRINGP(directory
))
6436 filelist
= Fdirectory_files (directory
, Qt
,
6437 build_string (".*\\.[bB][dD][fF]"), Qt
);
6439 for ( ; CONSP(filelist
); filelist
= XCDR (filelist
))
6441 Lisp_Object filename
= XCAR (filelist
);
6442 if (w32_BDF_to_x_font (SDATA (filename
), fontname
, 100))
6443 store_in_alist (&list
, build_string (fontname
), filename
);
6448 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts
, Sw32_find_bdf_fonts
,
6450 doc
: /* Return a list of BDF fonts in DIRECTORY.
6451 The list is suitable for appending to `w32-bdf-filename-alist'.
6452 Fonts which do not contain an xlfd description will not be included
6453 in the list. DIRECTORY may be a list of directories. */)
6455 Lisp_Object directory
;
6457 Lisp_Object list
= Qnil
;
6458 struct gcpro gcpro1
, gcpro2
;
6460 if (!CONSP (directory
))
6461 return w32_find_bdf_fonts_in_dir (directory
);
6463 for ( ; CONSP (directory
); directory
= XCDR (directory
))
6465 Lisp_Object pair
[2];
6468 GCPRO2 (directory
, list
);
6469 pair
[1] = w32_find_bdf_fonts_in_dir( XCAR (directory
) );
6470 list
= Fnconc( 2, pair
);
6477 DEFUN ("xw-color-defined-p", Fxw_color_defined_p
, Sxw_color_defined_p
, 1, 2, 0,
6478 doc
: /* Internal function called by `color-defined-p', which see. */)
6480 Lisp_Object color
, frame
;
6483 FRAME_PTR f
= check_x_frame (frame
);
6485 CHECK_STRING (color
);
6487 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
6493 DEFUN ("xw-color-values", Fxw_color_values
, Sxw_color_values
, 1, 2, 0,
6494 doc
: /* Internal function called by `color-values', which see. */)
6496 Lisp_Object color
, frame
;
6499 FRAME_PTR f
= check_x_frame (frame
);
6501 CHECK_STRING (color
);
6503 if (w32_defined_color (f
, SDATA (color
), &foo
, 0))
6504 return list3 (make_number ((GetRValue (foo
.pixel
) << 8)
6505 | GetRValue (foo
.pixel
)),
6506 make_number ((GetGValue (foo
.pixel
) << 8)
6507 | GetGValue (foo
.pixel
)),
6508 make_number ((GetBValue (foo
.pixel
) << 8)
6509 | GetBValue (foo
.pixel
)));
6514 DEFUN ("xw-display-color-p", Fxw_display_color_p
, Sxw_display_color_p
, 0, 1, 0,
6515 doc
: /* Internal function called by `display-color-p', which see. */)
6517 Lisp_Object display
;
6519 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6521 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
6527 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
,
6528 Sx_display_grayscale_p
, 0, 1, 0,
6529 doc
: /* Return t if DISPLAY supports shades of gray.
6530 Note that color displays do support shades of gray.
6531 The optional argument DISPLAY specifies which display to ask about.
6532 DISPLAY should be either a frame or a display name (a string).
6533 If omitted or nil, that stands for the selected frame's display. */)
6535 Lisp_Object display
;
6537 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6539 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
6545 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
,
6546 Sx_display_pixel_width
, 0, 1, 0,
6547 doc
: /* Returns the width in pixels of DISPLAY.
6548 The optional argument DISPLAY specifies which display to ask about.
6549 DISPLAY should be either a frame or a display name (a string).
6550 If omitted or nil, that stands for the selected frame's display. */)
6552 Lisp_Object display
;
6554 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6556 return make_number (dpyinfo
->width
);
6559 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
6560 Sx_display_pixel_height
, 0, 1, 0,
6561 doc
: /* Returns the height in pixels of DISPLAY.
6562 The optional argument DISPLAY specifies which display to ask about.
6563 DISPLAY should be either a frame or a display name (a string).
6564 If omitted or nil, that stands for the selected frame's display. */)
6566 Lisp_Object display
;
6568 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6570 return make_number (dpyinfo
->height
);
6573 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
6575 doc
: /* Returns the number of bitplanes of DISPLAY.
6576 The optional argument DISPLAY specifies which display to ask about.
6577 DISPLAY should be either a frame or a display name (a string).
6578 If omitted or nil, that stands for the selected frame's display. */)
6580 Lisp_Object display
;
6582 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6584 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
6587 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
6589 doc
: /* Returns the number of color cells of DISPLAY.
6590 The optional argument DISPLAY specifies which display to ask about.
6591 DISPLAY should be either a frame or a display name (a string).
6592 If omitted or nil, that stands for the selected frame's display. */)
6594 Lisp_Object display
;
6596 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6600 hdc
= GetDC (dpyinfo
->root_window
);
6601 if (dpyinfo
->has_palette
)
6602 cap
= GetDeviceCaps (hdc
, SIZEPALETTE
);
6604 cap
= GetDeviceCaps (hdc
, NUMCOLORS
);
6606 /* We force 24+ bit depths to 24-bit, both to prevent an overflow
6607 and because probably is more meaningful on Windows anyway */
6609 cap
= 1 << min(dpyinfo
->n_planes
* dpyinfo
->n_cbits
, 24);
6611 ReleaseDC (dpyinfo
->root_window
, hdc
);
6613 return make_number (cap
);
6616 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
6617 Sx_server_max_request_size
,
6619 doc
: /* Returns the maximum request size of the server of DISPLAY.
6620 The optional argument DISPLAY specifies which display to ask about.
6621 DISPLAY should be either a frame or a display name (a string).
6622 If omitted or nil, that stands for the selected frame's display. */)
6624 Lisp_Object display
;
6626 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6628 return make_number (1);
6631 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
6632 doc
: /* Returns the "vendor ID" string of the W32 system (Microsoft).
6633 The optional argument DISPLAY specifies which display to ask about.
6634 DISPLAY should be either a frame or a display name (a string).
6635 If omitted or nil, that stands for the selected frame's display. */)
6637 Lisp_Object display
;
6639 return build_string ("Microsoft Corp.");
6642 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
6643 doc
: /* Returns the version numbers of the server of DISPLAY.
6644 The value is a list of three integers: the major and minor
6645 version numbers of the X Protocol in use, and the distributor-specific release
6646 number. See also the function `x-server-vendor'.
6648 The optional argument DISPLAY specifies which display to ask about.
6649 DISPLAY should be either a frame or a display name (a string).
6650 If omitted or nil, that stands for the selected frame's display. */)
6652 Lisp_Object display
;
6654 return Fcons (make_number (w32_major_version
),
6655 Fcons (make_number (w32_minor_version
),
6656 Fcons (make_number (w32_build_number
), Qnil
)));
6659 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
6660 doc
: /* Returns the number of screens on the server of DISPLAY.
6661 The optional argument DISPLAY specifies which display to ask about.
6662 DISPLAY should be either a frame or a display name (a string).
6663 If omitted or nil, that stands for the selected frame's display. */)
6665 Lisp_Object display
;
6667 return make_number (1);
6670 DEFUN ("x-display-mm-height", Fx_display_mm_height
,
6671 Sx_display_mm_height
, 0, 1, 0,
6672 doc
: /* Returns the height in millimeters of DISPLAY.
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
);
6683 hdc
= GetDC (dpyinfo
->root_window
);
6685 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
6687 ReleaseDC (dpyinfo
->root_window
, hdc
);
6689 return make_number (cap
);
6692 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
6693 doc
: /* Returns the width in millimeters of DISPLAY.
6694 The optional argument DISPLAY specifies which display to ask about.
6695 DISPLAY should be either a frame or a display name (a string).
6696 If omitted or nil, that stands for the selected frame's display. */)
6698 Lisp_Object display
;
6700 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6705 hdc
= GetDC (dpyinfo
->root_window
);
6707 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
6709 ReleaseDC (dpyinfo
->root_window
, hdc
);
6711 return make_number (cap
);
6714 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
6715 Sx_display_backing_store
, 0, 1, 0,
6716 doc
: /* Returns an indication of whether DISPLAY does backing store.
6717 The value may be `always', `when-mapped', or `not-useful'.
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 return intern ("not-useful");
6727 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
6728 Sx_display_visual_class
, 0, 1, 0,
6729 doc
: /* Returns the visual class of DISPLAY.
6730 The value is one of the symbols `static-gray', `gray-scale',
6731 `static-color', `pseudo-color', `true-color', or `direct-color'.
6733 The optional argument DISPLAY specifies which display to ask about.
6734 DISPLAY should be either a frame or a display name (a string).
6735 If omitted or nil, that stands for the selected frame's display. */)
6737 Lisp_Object display
;
6739 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6740 Lisp_Object result
= Qnil
;
6742 if (dpyinfo
->has_palette
)
6743 result
= intern ("pseudo-color");
6744 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 1)
6745 result
= intern ("static-grey");
6746 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
== 4)
6747 result
= intern ("static-color");
6748 else if (dpyinfo
->n_planes
* dpyinfo
->n_cbits
> 8)
6749 result
= intern ("true-color");
6754 DEFUN ("x-display-save-under", Fx_display_save_under
,
6755 Sx_display_save_under
, 0, 1, 0,
6756 doc
: /* Returns t if DISPLAY supports the save-under feature.
6757 The optional argument DISPLAY specifies which display to ask about.
6758 DISPLAY should be either a frame or a display name (a string).
6759 If omitted or nil, that stands for the selected frame's display. */)
6761 Lisp_Object display
;
6768 register struct frame
*f
;
6770 return FRAME_PIXEL_WIDTH (f
);
6775 register struct frame
*f
;
6777 return FRAME_PIXEL_HEIGHT (f
);
6782 register struct frame
*f
;
6784 return FRAME_COLUMN_WIDTH (f
);
6789 register struct frame
*f
;
6791 return FRAME_LINE_HEIGHT (f
);
6796 register struct frame
*f
;
6798 return FRAME_W32_DISPLAY_INFO (f
)->n_planes
;
6801 /* Return the display structure for the display named NAME.
6802 Open a new connection if necessary. */
6804 struct w32_display_info
*
6805 x_display_info_for_name (name
)
6809 struct w32_display_info
*dpyinfo
;
6811 CHECK_STRING (name
);
6813 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
6815 dpyinfo
= dpyinfo
->next
, names
= XCDR (names
))
6818 tem
= Fstring_equal (XCAR (XCAR (names
)), name
);
6823 /* Use this general default value to start with. */
6824 Vx_resource_name
= Vinvocation_name
;
6826 validate_x_resource_name ();
6828 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
6829 (char *) SDATA (Vx_resource_name
));
6832 error ("Cannot connect to server %s", SDATA (name
));
6835 XSETFASTINT (Vwindow_system_version
, 3);
6840 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
6841 1, 3, 0, doc
: /* Open a connection to a server.
6842 DISPLAY is the name of the display to connect to.
6843 Optional second arg XRM-STRING is a string of resources in xrdb format.
6844 If the optional third arg MUST-SUCCEED is non-nil,
6845 terminate Emacs if we can't open the connection. */)
6846 (display
, xrm_string
, must_succeed
)
6847 Lisp_Object display
, xrm_string
, must_succeed
;
6849 unsigned char *xrm_option
;
6850 struct w32_display_info
*dpyinfo
;
6852 /* If initialization has already been done, return now to avoid
6853 overwriting critical parts of one_w32_display_info. */
6857 CHECK_STRING (display
);
6858 if (! NILP (xrm_string
))
6859 CHECK_STRING (xrm_string
);
6862 if (! EQ (Vwindow_system
, intern ("w32")))
6863 error ("Not using Microsoft Windows");
6866 /* Allow color mapping to be defined externally; first look in user's
6867 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
6869 Lisp_Object color_file
;
6870 struct gcpro gcpro1
;
6872 color_file
= build_string("~/rgb.txt");
6874 GCPRO1 (color_file
);
6876 if (NILP (Ffile_readable_p (color_file
)))
6878 Fexpand_file_name (build_string ("rgb.txt"),
6879 Fsymbol_value (intern ("data-directory")));
6881 Vw32_color_map
= Fw32_load_color_file (color_file
);
6885 if (NILP (Vw32_color_map
))
6886 Vw32_color_map
= Fw32_default_color_map ();
6888 /* Merge in system logical colors. */
6889 add_system_logical_colors_to_map (&Vw32_color_map
);
6891 if (! NILP (xrm_string
))
6892 xrm_option
= (unsigned char *) SDATA (xrm_string
);
6894 xrm_option
= (unsigned char *) 0;
6896 /* Use this general default value to start with. */
6897 /* First remove .exe suffix from invocation-name - it looks ugly. */
6899 char basename
[ MAX_PATH
], *str
;
6901 strcpy (basename
, SDATA (Vinvocation_name
));
6902 str
= strrchr (basename
, '.');
6904 Vinvocation_name
= build_string (basename
);
6906 Vx_resource_name
= Vinvocation_name
;
6908 validate_x_resource_name ();
6910 /* This is what opens the connection and sets x_current_display.
6911 This also initializes many symbols, such as those used for input. */
6912 dpyinfo
= w32_term_init (display
, xrm_option
,
6913 (char *) SDATA (Vx_resource_name
));
6917 if (!NILP (must_succeed
))
6918 fatal ("Cannot connect to server %s.\n",
6921 error ("Cannot connect to server %s", SDATA (display
));
6926 XSETFASTINT (Vwindow_system_version
, 3);
6930 DEFUN ("x-close-connection", Fx_close_connection
,
6931 Sx_close_connection
, 1, 1, 0,
6932 doc
: /* Close the connection to DISPLAY's server.
6933 For DISPLAY, specify either a frame or a display name (a string).
6934 If DISPLAY is nil, that stands for the selected frame's display. */)
6936 Lisp_Object display
;
6938 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6941 if (dpyinfo
->reference_count
> 0)
6942 error ("Display still has frames on it");
6945 /* Free the fonts in the font table. */
6946 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6947 if (dpyinfo
->font_table
[i
].name
)
6949 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
6950 xfree (dpyinfo
->font_table
[i
].full_name
);
6951 xfree (dpyinfo
->font_table
[i
].name
);
6952 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
6954 x_destroy_all_bitmaps (dpyinfo
);
6956 x_delete_display (dpyinfo
);
6962 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
6963 doc
: /* Return the list of display names that Emacs has connections to. */)
6966 Lisp_Object tail
, result
;
6969 for (tail
= w32_display_name_list
; ! NILP (tail
); tail
= XCDR (tail
))
6970 result
= Fcons (XCAR (XCAR (tail
)), result
);
6975 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
6976 doc
: /* This is a noop on W32 systems. */)
6978 Lisp_Object display
, on
;
6985 /***********************************************************************
6987 ***********************************************************************/
6989 DEFUN ("x-change-window-property", Fx_change_window_property
,
6990 Sx_change_window_property
, 2, 6, 0,
6991 doc
: /* Change window property PROP to VALUE on the X window of FRAME.
6992 VALUE may be a string or a list of conses, numbers and/or strings.
6993 If an element in the list is a string, it is converted to
6994 an Atom and the value of the Atom is used. If an element is a cons,
6995 it is converted to a 32 bit number where the car is the 16 top bits and the
6996 cdr is the lower 16 bits.
6997 FRAME nil or omitted means use the selected frame.
6998 If TYPE is given and non-nil, it is the name of the type of VALUE.
6999 If TYPE is not given or nil, the type is STRING.
7000 FORMAT gives the size in bits of each element if VALUE is a list.
7001 It must be one of 8, 16 or 32.
7002 If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
7003 If OUTER_P is non-nil, the property is changed for the outer X window of
7004 FRAME. Default is to change on the edit X window.
7007 (prop
, value
, frame
, type
, format
, outer_p
)
7008 Lisp_Object prop
, value
, frame
, type
, format
, outer_p
;
7010 #if 0 /* TODO : port window properties to W32 */
7011 struct frame
*f
= check_x_frame (frame
);
7014 CHECK_STRING (prop
);
7015 CHECK_STRING (value
);
7018 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7019 XChangeProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7020 prop_atom
, XA_STRING
, 8, PropModeReplace
,
7021 SDATA (value
), SCHARS (value
));
7023 /* Make sure the property is set when we return. */
7024 XFlush (FRAME_W32_DISPLAY (f
));
7033 DEFUN ("x-delete-window-property", Fx_delete_window_property
,
7034 Sx_delete_window_property
, 1, 2, 0,
7035 doc
: /* Remove window property PROP from X window of FRAME.
7036 FRAME nil or omitted means use the selected frame. Value is PROP. */)
7038 Lisp_Object prop
, frame
;
7040 #if 0 /* TODO : port window properties to W32 */
7042 struct frame
*f
= check_x_frame (frame
);
7045 CHECK_STRING (prop
);
7047 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7048 XDeleteProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), prop_atom
);
7050 /* Make sure the property is removed when we return. */
7051 XFlush (FRAME_W32_DISPLAY (f
));
7059 DEFUN ("x-window-property", Fx_window_property
, Sx_window_property
,
7061 doc
: /* Value is the value of window property PROP on FRAME.
7062 If FRAME is nil or omitted, use the selected frame. Value is nil
7063 if FRAME hasn't a property with name PROP or if PROP has no string
7066 Lisp_Object prop
, frame
;
7068 #if 0 /* TODO : port window properties to W32 */
7070 struct frame
*f
= check_x_frame (frame
);
7073 Lisp_Object prop_value
= Qnil
;
7074 char *tmp_data
= NULL
;
7077 unsigned long actual_size
, bytes_remaining
;
7079 CHECK_STRING (prop
);
7081 prop_atom
= XInternAtom (FRAME_W32_DISPLAY (f
), SDATA (prop
), False
);
7082 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7083 prop_atom
, 0, 0, False
, XA_STRING
,
7084 &actual_type
, &actual_format
, &actual_size
,
7085 &bytes_remaining
, (unsigned char **) &tmp_data
);
7088 int size
= bytes_remaining
;
7093 rc
= XGetWindowProperty (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
7094 prop_atom
, 0, bytes_remaining
,
7096 &actual_type
, &actual_format
,
7097 &actual_size
, &bytes_remaining
,
7098 (unsigned char **) &tmp_data
);
7100 prop_value
= make_string (tmp_data
, size
);
7115 /***********************************************************************
7117 ***********************************************************************/
7119 /* If non-null, an asynchronous timer that, when it expires, displays
7120 an hourglass cursor on all frames. */
7122 static struct atimer
*hourglass_atimer
;
7124 /* Non-zero means an hourglass cursor is currently shown. */
7126 static int hourglass_shown_p
;
7128 /* Number of seconds to wait before displaying an hourglass cursor. */
7130 static Lisp_Object Vhourglass_delay
;
7132 /* Default number of seconds to wait before displaying an hourglass
7135 #define DEFAULT_HOURGLASS_DELAY 1
7137 /* Function prototypes. */
7139 static void show_hourglass
P_ ((struct atimer
*));
7140 static void hide_hourglass
P_ ((void));
7143 /* Cancel a currently active hourglass timer, and start a new one. */
7148 #if 0 /* TODO: cursor shape changes. */
7150 int secs
, usecs
= 0;
7152 cancel_hourglass ();
7154 if (INTEGERP (Vhourglass_delay
)
7155 && XINT (Vhourglass_delay
) > 0)
7156 secs
= XFASTINT (Vhourglass_delay
);
7157 else if (FLOATP (Vhourglass_delay
)
7158 && XFLOAT_DATA (Vhourglass_delay
) > 0)
7161 tem
= Ftruncate (Vhourglass_delay
, Qnil
);
7162 secs
= XFASTINT (tem
);
7163 usecs
= (XFLOAT_DATA (Vhourglass_delay
) - secs
) * 1000000;
7166 secs
= DEFAULT_HOURGLASS_DELAY
;
7168 EMACS_SET_SECS_USECS (delay
, secs
, usecs
);
7169 hourglass_atimer
= start_atimer (ATIMER_RELATIVE
, delay
,
7170 show_hourglass
, NULL
);
7175 /* Cancel the hourglass cursor timer if active, hide an hourglass
7181 if (hourglass_atimer
)
7183 cancel_atimer (hourglass_atimer
);
7184 hourglass_atimer
= NULL
;
7187 if (hourglass_shown_p
)
7192 /* Timer function of hourglass_atimer. TIMER is equal to
7195 Display an hourglass cursor on all frames by mapping the frames'
7196 hourglass_window. Set the hourglass_p flag in the frames'
7197 output_data.x structure to indicate that an hourglass cursor is
7198 shown on the frames. */
7201 show_hourglass (timer
)
7202 struct atimer
*timer
;
7204 #if 0 /* TODO: cursor shape changes. */
7205 /* The timer implementation will cancel this timer automatically
7206 after this function has run. Set hourglass_atimer to null
7207 so that we know the timer doesn't have to be canceled. */
7208 hourglass_atimer
= NULL
;
7210 if (!hourglass_shown_p
)
7212 Lisp_Object rest
, frame
;
7216 FOR_EACH_FRAME (rest
, frame
)
7217 if (FRAME_W32_P (XFRAME (frame
)))
7219 struct frame
*f
= XFRAME (frame
);
7221 f
->output_data
.w32
->hourglass_p
= 1;
7223 if (!f
->output_data
.w32
->hourglass_window
)
7225 unsigned long mask
= CWCursor
;
7226 XSetWindowAttributes attrs
;
7228 attrs
.cursor
= f
->output_data
.w32
->hourglass_cursor
;
7230 f
->output_data
.w32
->hourglass_window
7231 = XCreateWindow (FRAME_X_DISPLAY (f
),
7232 FRAME_OUTER_WINDOW (f
),
7233 0, 0, 32000, 32000, 0, 0,
7239 XMapRaised (FRAME_X_DISPLAY (f
),
7240 f
->output_data
.w32
->hourglass_window
);
7241 XFlush (FRAME_X_DISPLAY (f
));
7244 hourglass_shown_p
= 1;
7251 /* Hide the hourglass cursor on all frames, if it is currently shown. */
7256 #if 0 /* TODO: cursor shape changes. */
7257 if (hourglass_shown_p
)
7259 Lisp_Object rest
, frame
;
7262 FOR_EACH_FRAME (rest
, frame
)
7264 struct frame
*f
= XFRAME (frame
);
7267 /* Watch out for newly created frames. */
7268 && f
->output_data
.x
->hourglass_window
)
7270 XUnmapWindow (FRAME_X_DISPLAY (f
),
7271 f
->output_data
.x
->hourglass_window
);
7272 /* Sync here because XTread_socket looks at the
7273 hourglass_p flag that is reset to zero below. */
7274 XSync (FRAME_X_DISPLAY (f
), False
);
7275 f
->output_data
.x
->hourglass_p
= 0;
7279 hourglass_shown_p
= 0;
7287 /***********************************************************************
7289 ***********************************************************************/
7291 static Lisp_Object x_create_tip_frame
P_ ((struct w32_display_info
*,
7292 Lisp_Object
, Lisp_Object
));
7293 static void compute_tip_xy
P_ ((struct frame
*, Lisp_Object
, Lisp_Object
,
7294 Lisp_Object
, int, int, int *, int *));
7296 /* The frame of a currently visible tooltip. */
7298 Lisp_Object tip_frame
;
7300 /* If non-nil, a timer started that hides the last tooltip when it
7303 Lisp_Object tip_timer
;
7306 /* If non-nil, a vector of 3 elements containing the last args
7307 with which x-show-tip was called. See there. */
7309 Lisp_Object last_show_tip_args
;
7311 /* Maximum size for tooltips; a cons (COLUMNS . ROWS). */
7313 Lisp_Object Vx_max_tooltip_size
;
7317 unwind_create_tip_frame (frame
)
7320 Lisp_Object deleted
;
7322 deleted
= unwind_create_frame (frame
);
7323 if (EQ (deleted
, Qt
))
7333 /* Create a frame for a tooltip on the display described by DPYINFO.
7334 PARMS is a list of frame parameters. TEXT is the string to
7335 display in the tip frame. Value is the frame.
7337 Note that functions called here, esp. x_default_parameter can
7338 signal errors, for instance when a specified color name is
7339 undefined. We have to make sure that we're in a consistent state
7340 when this happens. */
7343 x_create_tip_frame (dpyinfo
, parms
, text
)
7344 struct w32_display_info
*dpyinfo
;
7345 Lisp_Object parms
, text
;
7348 Lisp_Object frame
, tem
;
7350 long window_prompting
= 0;
7352 int count
= SPECPDL_INDEX ();
7353 struct gcpro gcpro1
, gcpro2
, gcpro3
;
7355 int face_change_count_before
= face_change_count
;
7357 struct buffer
*old_buffer
;
7361 /* Use this general default value to start with until we know if
7362 this frame has a specified name. */
7363 Vx_resource_name
= Vinvocation_name
;
7366 kb
= dpyinfo
->terminal
->kboard
;
7368 kb
= &the_only_kboard
;
7371 /* Get the name of the frame to use for resource lookup. */
7372 name
= w32_get_arg (parms
, Qname
, "name", "Name", RES_TYPE_STRING
);
7374 && !EQ (name
, Qunbound
)
7376 error ("Invalid frame name--not a string or nil");
7377 Vx_resource_name
= name
;
7380 GCPRO3 (parms
, name
, frame
);
7381 /* Make a frame without minibuffer nor mode-line. */
7383 f
->wants_modeline
= 0;
7384 XSETFRAME (frame
, f
);
7386 buffer
= Fget_buffer_create (build_string (" *tip*"));
7387 Fset_window_buffer (FRAME_ROOT_WINDOW (f
), buffer
, Qnil
);
7388 old_buffer
= current_buffer
;
7389 set_buffer_internal_1 (XBUFFER (buffer
));
7390 current_buffer
->truncate_lines
= Qnil
;
7391 specbind (Qinhibit_read_only
, Qt
);
7392 specbind (Qinhibit_modification_hooks
, Qt
);
7395 set_buffer_internal_1 (old_buffer
);
7397 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 0;
7398 record_unwind_protect (unwind_create_tip_frame
, frame
);
7400 /* By setting the output method, we're essentially saying that
7401 the frame is live, as per FRAME_LIVE_P. If we get a signal
7402 from this point on, x_destroy_window might screw up reference
7404 f
->terminal
= dpyinfo
->terminal
;
7405 f
->terminal
->reference_count
++;
7406 f
->output_method
= output_w32
;
7407 f
->output_data
.w32
=
7408 (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
7409 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
7411 FRAME_FONTSET (f
) = -1;
7412 f
->icon_name
= Qnil
;
7414 #if 0 /* GLYPH_DEBUG TODO: image support. */
7415 image_cache_refcount
= FRAME_X_IMAGE_CACHE (f
)->refcount
;
7416 dpyinfo_refcount
= dpyinfo
->reference_count
;
7417 #endif /* GLYPH_DEBUG */
7419 FRAME_KBOARD (f
) = kb
;
7421 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
7422 f
->output_data
.w32
->explicit_parent
= 0;
7424 /* Set the name; the functions to which we pass f expect the name to
7426 if (EQ (name
, Qunbound
) || NILP (name
))
7428 f
->name
= build_string (dpyinfo
->w32_id_name
);
7429 f
->explicit_name
= 0;
7434 f
->explicit_name
= 1;
7435 /* use the frame's title when getting resources for this frame. */
7436 specbind (Qx_resource_name
, name
);
7439 f
->resx
= dpyinfo
->resx
;
7440 f
->resy
= dpyinfo
->resy
;
7442 #ifdef USE_FONT_BACKEND
7443 if (enable_font_backend
)
7445 /* Perhaps, we must allow frame parameter, say `font-backend',
7446 to specify which font backends to use. */
7447 register_font_driver (&w32font_driver
, f
);
7449 x_default_parameter (f
, parms
, Qfont_backend
, Qnil
,
7450 "fontBackend", "FontBackend", RES_TYPE_STRING
);
7452 #endif /* USE_FONT_BACKEND */
7454 /* Extract the window parameters from the supplied values
7455 that are needed to determine window geometry. */
7456 #ifdef USE_FONT_BACKEND
7457 if (enable_font_backend
)
7458 x_default_font_parameter (f
, parms
);
7460 #endif /* USE_FONT_BACKEND */
7464 font
= w32_get_arg (parms
, Qfont
, "font", "Font", RES_TYPE_STRING
);
7467 /* First, try whatever font the caller has specified. */
7470 tem
= Fquery_fontset (font
, Qnil
);
7472 font
= x_new_fontset (f
, tem
);
7474 font
= x_new_font (f
, SDATA (font
));
7477 /* Try out a font which we hope has bold and italic variations. */
7478 if (!STRINGP (font
))
7479 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
7480 if (! STRINGP (font
))
7481 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
7482 /* If those didn't work, look for something which will at least work. */
7483 if (! STRINGP (font
))
7484 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
7486 if (! STRINGP (font
))
7487 font
= build_string ("Fixedsys");
7489 x_default_parameter (f
, parms
, Qfont
, font
,
7490 "font", "Font", RES_TYPE_STRING
);
7493 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
7494 "borderWidth", "BorderWidth", RES_TYPE_NUMBER
);
7495 /* This defaults to 2 in order to match xterm. We recognize either
7496 internalBorderWidth or internalBorder (which is what xterm calls
7498 if (NILP (Fassq (Qinternal_border_width
, parms
)))
7502 value
= w32_get_arg (parms
, Qinternal_border_width
,
7503 "internalBorder", "internalBorder", RES_TYPE_NUMBER
);
7504 if (! EQ (value
, Qunbound
))
7505 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
7508 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (1),
7509 "internalBorderWidth", "internalBorderWidth",
7512 /* Also do the stuff which must be set before the window exists. */
7513 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
7514 "foreground", "Foreground", RES_TYPE_STRING
);
7515 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
7516 "background", "Background", RES_TYPE_STRING
);
7517 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
7518 "pointerColor", "Foreground", RES_TYPE_STRING
);
7519 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
7520 "cursorColor", "Foreground", RES_TYPE_STRING
);
7521 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
7522 "borderColor", "BorderColor", RES_TYPE_STRING
);
7524 /* Init faces before x_default_parameter is called for scroll-bar
7525 parameters because that function calls x_set_scroll_bar_width,
7526 which calls change_frame_size, which calls Fset_window_buffer,
7527 which runs hooks, which call Fvertical_motion. At the end, we
7528 end up in init_iterator with a null face cache, which should not
7530 init_frame_faces (f
);
7532 f
->output_data
.w32
->dwStyle
= WS_BORDER
| WS_POPUP
| WS_DISABLED
;
7533 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
7535 window_prompting
= x_figure_window_size (f
, parms
, 0);
7537 /* No fringes on tip frame. */
7539 f
->left_fringe_width
= 0;
7540 f
->right_fringe_width
= 0;
7543 my_create_tip_window (f
);
7548 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
7549 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
7550 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
7551 "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN
);
7552 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
7553 "cursorType", "CursorType", RES_TYPE_SYMBOL
);
7555 /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
7556 Change will not be effected unless different from the current
7558 width
= FRAME_COLS (f
);
7559 height
= FRAME_LINES (f
);
7560 FRAME_LINES (f
) = 0;
7561 SET_FRAME_COLS (f
, 0);
7562 change_frame_size (f
, height
, width
, 1, 0, 0);
7564 /* Add `tooltip' frame parameter's default value. */
7565 if (NILP (Fframe_parameter (frame
, intern ("tooltip"))))
7566 Fmodify_frame_parameters (frame
, Fcons (Fcons (intern ("tooltip"), Qt
),
7569 /* Set up faces after all frame parameters are known. This call
7570 also merges in face attributes specified for new frames.
7572 Frame parameters may be changed if .Xdefaults contains
7573 specifications for the default font. For example, if there is an
7574 `Emacs.default.attributeBackground: pink', the `background-color'
7575 attribute of the frame get's set, which let's the internal border
7576 of the tooltip frame appear in pink. Prevent this. */
7578 Lisp_Object bg
= Fframe_parameter (frame
, Qbackground_color
);
7580 /* Set tip_frame here, so that */
7582 call1 (Qface_set_after_frame_default
, frame
);
7584 if (!EQ (bg
, Fframe_parameter (frame
, Qbackground_color
)))
7585 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qbackground_color
, bg
),
7589 Fmodify_frame_parameters (frame
, Fcons (Fcons (Qwindow_system
, Qw32
), Qnil
));
7595 /* It is now ok to make the frame official even if we get an error
7596 below. And the frame needs to be on Vframe_list or making it
7597 visible won't work. */
7598 Vframe_list
= Fcons (frame
, Vframe_list
);
7600 /* Now that the frame is official, it counts as a reference to
7602 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
7604 /* Setting attributes of faces of the tooltip frame from resources
7605 and similar will increment face_change_count, which leads to the
7606 clearing of all current matrices. Since this isn't necessary
7607 here, avoid it by resetting face_change_count to the value it
7608 had before we created the tip frame. */
7609 face_change_count
= face_change_count_before
;
7611 /* Discard the unwind_protect. */
7612 return unbind_to (count
, frame
);
7616 /* Compute where to display tip frame F. PARMS is the list of frame
7617 parameters for F. DX and DY are specified offsets from the current
7618 location of the mouse. WIDTH and HEIGHT are the width and height
7619 of the tooltip. Return coordinates relative to the root window of
7620 the display in *ROOT_X, and *ROOT_Y. */
7623 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, root_x
, root_y
)
7625 Lisp_Object parms
, dx
, dy
;
7627 int *root_x
, *root_y
;
7629 Lisp_Object left
, top
;
7631 /* User-specified position? */
7632 left
= Fcdr (Fassq (Qleft
, parms
));
7633 top
= Fcdr (Fassq (Qtop
, parms
));
7635 /* Move the tooltip window where the mouse pointer is. Resize and
7637 if (!INTEGERP (left
) || !INTEGERP (top
))
7649 *root_y
= XINT (top
);
7650 else if (*root_y
+ XINT (dy
) <= 0)
7651 *root_y
= 0; /* Can happen for negative dy */
7652 else if (*root_y
+ XINT (dy
) + height
<= FRAME_W32_DISPLAY_INFO (f
)->height
)
7653 /* It fits below the pointer */
7654 *root_y
+= XINT (dy
);
7655 else if (height
+ XINT (dy
) <= *root_y
)
7656 /* It fits above the pointer. */
7657 *root_y
-= height
+ XINT (dy
);
7659 /* Put it on the top. */
7662 if (INTEGERP (left
))
7663 *root_x
= XINT (left
);
7664 else if (*root_x
+ XINT (dx
) <= 0)
7665 *root_x
= 0; /* Can happen for negative dx */
7666 else if (*root_x
+ XINT (dx
) + width
<= FRAME_W32_DISPLAY_INFO (f
)->width
)
7667 /* It fits to the right of the pointer. */
7668 *root_x
+= XINT (dx
);
7669 else if (width
+ XINT (dx
) <= *root_x
)
7670 /* It fits to the left of the pointer. */
7671 *root_x
-= width
+ XINT (dx
);
7673 /* Put it left justified on the screen -- it ought to fit that way. */
7678 DEFUN ("x-show-tip", Fx_show_tip
, Sx_show_tip
, 1, 6, 0,
7679 doc
: /* Show STRING in a \"tooltip\" window on frame FRAME.
7680 A tooltip window is a small window displaying a string.
7682 This is an internal function; Lisp code should call `tooltip-show'.
7684 FRAME nil or omitted means use the selected frame.
7686 PARMS is an optional list of frame parameters which can be
7687 used to change the tooltip's appearance.
7689 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
7690 means use the default timeout of 5 seconds.
7692 If the list of frame parameters PARMS contains a `left' parameter,
7693 the tooltip is displayed at that x-position. Otherwise it is
7694 displayed at the mouse position, with offset DX added (default is 5 if
7695 DX isn't specified). Likewise for the y-position; if a `top' frame
7696 parameter is specified, it determines the y-position of the tooltip
7697 window, otherwise it is displayed at the mouse position, with offset
7698 DY added (default is -10).
7700 A tooltip's maximum size is specified by `x-max-tooltip-size'.
7701 Text larger than the specified size is clipped. */)
7702 (string
, frame
, parms
, timeout
, dx
, dy
)
7703 Lisp_Object string
, frame
, parms
, timeout
, dx
, dy
;
7708 struct buffer
*old_buffer
;
7709 struct text_pos pos
;
7710 int i
, width
, height
;
7711 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
7712 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
7713 int count
= SPECPDL_INDEX ();
7715 specbind (Qinhibit_redisplay
, Qt
);
7717 GCPRO4 (string
, parms
, frame
, timeout
);
7719 CHECK_STRING (string
);
7720 f
= check_x_frame (frame
);
7722 timeout
= make_number (5);
7724 CHECK_NATNUM (timeout
);
7727 dx
= make_number (5);
7732 dy
= make_number (-10);
7736 if (NILP (last_show_tip_args
))
7737 last_show_tip_args
= Fmake_vector (make_number (3), Qnil
);
7739 if (!NILP (tip_frame
))
7741 Lisp_Object last_string
= AREF (last_show_tip_args
, 0);
7742 Lisp_Object last_frame
= AREF (last_show_tip_args
, 1);
7743 Lisp_Object last_parms
= AREF (last_show_tip_args
, 2);
7745 if (EQ (frame
, last_frame
)
7746 && !NILP (Fequal (last_string
, string
))
7747 && !NILP (Fequal (last_parms
, parms
)))
7749 struct frame
*f
= XFRAME (tip_frame
);
7751 /* Only DX and DY have changed. */
7752 if (!NILP (tip_timer
))
7754 Lisp_Object timer
= tip_timer
;
7756 call1 (Qcancel_timer
, timer
);
7760 compute_tip_xy (f
, parms
, dx
, dy
, FRAME_PIXEL_WIDTH (f
),
7761 FRAME_PIXEL_HEIGHT (f
), &root_x
, &root_y
);
7763 /* Put tooltip in topmost group and in position. */
7764 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
7765 root_x
, root_y
, 0, 0,
7766 SWP_NOSIZE
| SWP_NOACTIVATE
);
7768 /* Ensure tooltip is on top of other topmost windows (eg menus). */
7769 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
7771 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
7778 /* Hide a previous tip, if any. */
7781 ASET (last_show_tip_args
, 0, string
);
7782 ASET (last_show_tip_args
, 1, frame
);
7783 ASET (last_show_tip_args
, 2, parms
);
7785 /* Add default values to frame parameters. */
7786 if (NILP (Fassq (Qname
, parms
)))
7787 parms
= Fcons (Fcons (Qname
, build_string ("tooltip")), parms
);
7788 if (NILP (Fassq (Qinternal_border_width
, parms
)))
7789 parms
= Fcons (Fcons (Qinternal_border_width
, make_number (3)), parms
);
7790 if (NILP (Fassq (Qborder_width
, parms
)))
7791 parms
= Fcons (Fcons (Qborder_width
, make_number (1)), parms
);
7792 if (NILP (Fassq (Qborder_color
, parms
)))
7793 parms
= Fcons (Fcons (Qborder_color
, build_string ("lightyellow")), parms
);
7794 if (NILP (Fassq (Qbackground_color
, parms
)))
7795 parms
= Fcons (Fcons (Qbackground_color
, build_string ("lightyellow")),
7798 /* Block input until the tip has been fully drawn, to avoid crashes
7799 when drawing tips in menus. */
7802 /* Create a frame for the tooltip, and record it in the global
7803 variable tip_frame. */
7804 frame
= x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f
), parms
, string
);
7807 /* Set up the frame's root window. */
7808 w
= XWINDOW (FRAME_ROOT_WINDOW (f
));
7809 w
->left_col
= w
->top_line
= make_number (0);
7811 if (CONSP (Vx_max_tooltip_size
)
7812 && INTEGERP (XCAR (Vx_max_tooltip_size
))
7813 && XINT (XCAR (Vx_max_tooltip_size
)) > 0
7814 && INTEGERP (XCDR (Vx_max_tooltip_size
))
7815 && XINT (XCDR (Vx_max_tooltip_size
)) > 0)
7817 w
->total_cols
= XCAR (Vx_max_tooltip_size
);
7818 w
->total_lines
= XCDR (Vx_max_tooltip_size
);
7822 w
->total_cols
= make_number (80);
7823 w
->total_lines
= make_number (40);
7826 FRAME_TOTAL_COLS (f
) = XINT (w
->total_cols
);
7828 w
->pseudo_window_p
= 1;
7830 /* Display the tooltip text in a temporary buffer. */
7831 old_buffer
= current_buffer
;
7832 set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f
))->buffer
));
7833 current_buffer
->truncate_lines
= Qnil
;
7834 clear_glyph_matrix (w
->desired_matrix
);
7835 clear_glyph_matrix (w
->current_matrix
);
7836 SET_TEXT_POS (pos
, BEGV
, BEGV_BYTE
);
7837 try_window (FRAME_ROOT_WINDOW (f
), pos
, 0);
7839 /* Compute width and height of the tooltip. */
7841 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
7843 struct glyph_row
*row
= &w
->desired_matrix
->rows
[i
];
7847 /* Stop at the first empty row at the end. */
7848 if (!row
->enabled_p
|| !row
->displays_text_p
)
7851 /* Let the row go over the full width of the frame. */
7852 row
->full_width_p
= 1;
7854 #ifdef TODO /* Investigate why some fonts need more width than is
7855 calculated for some tooltips. */
7856 /* There's a glyph at the end of rows that is use to place
7857 the cursor there. Don't include the width of this glyph. */
7858 if (row
->used
[TEXT_AREA
])
7860 last
= &row
->glyphs
[TEXT_AREA
][row
->used
[TEXT_AREA
] - 1];
7861 row_width
= row
->pixel_width
- last
->pixel_width
;
7865 row_width
= row
->pixel_width
;
7867 /* TODO: find why tips do not draw along baseline as instructed. */
7868 height
+= row
->height
;
7869 width
= max (width
, row_width
);
7872 /* Add the frame's internal border to the width and height the X
7873 window should have. */
7874 height
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
7875 width
+= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
7877 /* Move the tooltip window where the mouse pointer is. Resize and
7879 compute_tip_xy (f
, parms
, dx
, dy
, width
, height
, &root_x
, &root_y
);
7882 /* Adjust Window size to take border into account. */
7884 rect
.left
= rect
.top
= 0;
7886 rect
.bottom
= height
;
7887 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
7888 FRAME_EXTERNAL_MENU_BAR (f
));
7890 /* Position and size tooltip, and put it in the topmost group.
7891 The add-on of 3 to the 5th argument is a kludge: without it,
7892 some fonts cause the last character of the tip to be truncated,
7893 for some obscure reason. */
7894 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOPMOST
,
7895 root_x
, root_y
, rect
.right
- rect
.left
+ 3,
7896 rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
7898 /* Ensure tooltip is on top of other topmost windows (eg menus). */
7899 SetWindowPos (FRAME_W32_WINDOW (f
), HWND_TOP
,
7901 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
7903 /* Let redisplay know that we have made the frame visible already. */
7904 f
->async_visible
= 1;
7906 ShowWindow (FRAME_W32_WINDOW (f
), SW_SHOWNOACTIVATE
);
7909 /* Draw into the window. */
7910 w
->must_be_updated_p
= 1;
7911 update_single_window (w
, 1);
7915 /* Restore original current buffer. */
7916 set_buffer_internal_1 (old_buffer
);
7917 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
7920 /* Let the tip disappear after timeout seconds. */
7921 tip_timer
= call3 (intern ("run-at-time"), timeout
, Qnil
,
7922 intern ("x-hide-tip"));
7925 return unbind_to (count
, Qnil
);
7929 DEFUN ("x-hide-tip", Fx_hide_tip
, Sx_hide_tip
, 0, 0, 0,
7930 doc
: /* Hide the current tooltip window, if there is any.
7931 Value is t if tooltip was open, nil otherwise. */)
7935 Lisp_Object deleted
, frame
, timer
;
7936 struct gcpro gcpro1
, gcpro2
;
7938 /* Return quickly if nothing to do. */
7939 if (NILP (tip_timer
) && NILP (tip_frame
))
7944 GCPRO2 (frame
, timer
);
7945 tip_frame
= tip_timer
= deleted
= Qnil
;
7947 count
= SPECPDL_INDEX ();
7948 specbind (Qinhibit_redisplay
, Qt
);
7949 specbind (Qinhibit_quit
, Qt
);
7952 call1 (Qcancel_timer
, timer
);
7956 Fdelete_frame (frame
, Qnil
);
7961 return unbind_to (count
, deleted
);
7966 /***********************************************************************
7967 File selection dialog
7968 ***********************************************************************/
7969 extern Lisp_Object Qfile_name_history
;
7971 /* Callback for altering the behaviour of the Open File dialog.
7972 Makes the Filename text field contain "Current Directory" and be
7973 read-only when "Directories" is selected in the filter. This
7974 allows us to work around the fact that the standard Open File
7975 dialog does not support directories. */
7977 file_dialog_callback (hwnd
, msg
, wParam
, lParam
)
7983 if (msg
== WM_NOTIFY
)
7985 OFNOTIFY
* notify
= (OFNOTIFY
*)lParam
;
7986 /* Detect when the Filter dropdown is changed. */
7987 if (notify
->hdr
.code
== CDN_TYPECHANGE
7988 || notify
->hdr
.code
== CDN_INITDONE
)
7990 HWND dialog
= GetParent (hwnd
);
7991 HWND edit_control
= GetDlgItem (dialog
, FILE_NAME_TEXT_FIELD
);
7993 /* Directories is in index 2. */
7994 if (notify
->lpOFN
->nFilterIndex
== 2)
7996 CommDlg_OpenSave_SetControlText (dialog
, FILE_NAME_TEXT_FIELD
,
7997 "Current Directory");
7998 EnableWindow (edit_control
, FALSE
);
8002 /* Don't override default filename on init done. */
8003 if (notify
->hdr
.code
== CDN_TYPECHANGE
)
8004 CommDlg_OpenSave_SetControlText (dialog
,
8005 FILE_NAME_TEXT_FIELD
, "");
8006 EnableWindow (edit_control
, TRUE
);
8013 /* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
8014 we end up with the old file dialogs. Define a big enough struct for the
8015 new dialog to trick GetOpenFileName into giving us the new dialogs on
8016 Windows 2000 and XP. */
8019 OPENFILENAME real_details
;
8026 DEFUN ("x-file-dialog", Fx_file_dialog
, Sx_file_dialog
, 2, 5, 0,
8027 doc
: /* Read file name, prompting with PROMPT in directory DIR.
8028 Use a file selection dialog.
8029 Select DEFAULT-FILENAME in the dialog's file selection box, if
8030 specified. Ensure that file exists if MUSTMATCH is non-nil.
8031 If ONLY-DIR-P is non-nil, the user can only select directories. */)
8032 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
)
8033 Lisp_Object prompt
, dir
, default_filename
, mustmatch
, only_dir_p
;
8035 struct frame
*f
= SELECTED_FRAME ();
8036 Lisp_Object file
= Qnil
;
8037 int count
= SPECPDL_INDEX ();
8038 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
8039 char filename
[MAX_PATH
+ 1];
8040 char init_dir
[MAX_PATH
+ 1];
8041 int default_filter_index
= 1; /* 1: All Files, 2: Directories only */
8043 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
, file
);
8044 CHECK_STRING (prompt
);
8047 /* Create the dialog with PROMPT as title, using DIR as initial
8048 directory and using "*" as pattern. */
8049 dir
= Fexpand_file_name (dir
, Qnil
);
8050 strncpy (init_dir
, SDATA (ENCODE_FILE (dir
)), MAX_PATH
);
8051 init_dir
[MAX_PATH
] = '\0';
8052 unixtodos_filename (init_dir
);
8054 if (STRINGP (default_filename
))
8056 char *file_name_only
;
8057 char *full_path_name
= SDATA (ENCODE_FILE (default_filename
));
8059 unixtodos_filename (full_path_name
);
8061 file_name_only
= strrchr (full_path_name
, '\\');
8062 if (!file_name_only
)
8063 file_name_only
= full_path_name
;
8067 strncpy (filename
, file_name_only
, MAX_PATH
);
8068 filename
[MAX_PATH
] = '\0';
8074 NEWOPENFILENAME new_file_details
;
8075 BOOL file_opened
= FALSE
;
8076 OPENFILENAME
* file_details
= &new_file_details
.real_details
;
8078 /* Prevent redisplay. */
8079 specbind (Qinhibit_redisplay
, Qt
);
8082 bzero (&new_file_details
, sizeof (new_file_details
));
8083 /* Apparently NT4 crashes if you give it an unexpected size.
8084 I'm not sure about Windows 9x, so play it safe. */
8085 if (w32_major_version
> 4 && w32_major_version
< 95)
8086 file_details
->lStructSize
= sizeof (NEWOPENFILENAME
);
8088 file_details
->lStructSize
= sizeof (OPENFILENAME
);
8090 file_details
->hwndOwner
= FRAME_W32_WINDOW (f
);
8091 /* Undocumented Bug in Common File Dialog:
8092 If a filter is not specified, shell links are not resolved. */
8093 file_details
->lpstrFilter
= "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
8094 file_details
->lpstrFile
= filename
;
8095 file_details
->nMaxFile
= sizeof (filename
);
8096 file_details
->lpstrInitialDir
= init_dir
;
8097 file_details
->lpstrTitle
= SDATA (prompt
);
8099 if (! NILP (only_dir_p
))
8100 default_filter_index
= 2;
8102 file_details
->nFilterIndex
= default_filter_index
;
8104 file_details
->Flags
= (OFN_HIDEREADONLY
| OFN_NOCHANGEDIR
8105 | OFN_EXPLORER
| OFN_ENABLEHOOK
);
8106 if (!NILP (mustmatch
))
8108 /* Require that the path to the parent directory exists. */
8109 file_details
->Flags
|= OFN_PATHMUSTEXIST
;
8110 /* If we are looking for a file, require that it exists. */
8111 if (NILP (only_dir_p
))
8112 file_details
->Flags
|= OFN_FILEMUSTEXIST
;
8115 file_details
->lpfnHook
= (LPOFNHOOKPROC
) file_dialog_callback
;
8117 file_opened
= GetOpenFileName (file_details
);
8123 dostounix_filename (filename
);
8125 if (file_details
->nFilterIndex
== 2)
8127 /* "Directories" selected - strip dummy file name. */
8128 char * last
= strrchr (filename
, '/');
8132 file
= DECODE_FILE(build_string (filename
));
8134 /* User cancelled the dialog without making a selection. */
8135 else if (!CommDlgExtendedError ())
8137 /* An error occurred, fallback on reading from the mini-buffer. */
8139 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
8140 dir
, mustmatch
, dir
, Qfile_name_history
,
8141 default_filename
, Qnil
);
8143 file
= unbind_to (count
, file
);
8148 /* Make "Cancel" equivalent to C-g. */
8150 Fsignal (Qquit
, Qnil
);
8152 return unbind_to (count
, file
);
8157 /***********************************************************************
8158 w32 specialized functions
8159 ***********************************************************************/
8161 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 2, 0,
8162 doc
: /* Select a font for the named FRAME using the W32 font dialog.
8163 Returns an X-style font string corresponding to the selection.
8165 If FRAME is omitted or nil, it defaults to the selected frame.
8166 If INCLUDE-PROPORTIONAL is non-nil, include proportional fonts
8167 in the font selection dialog. */)
8168 (frame
, include_proportional
)
8169 Lisp_Object frame
, include_proportional
;
8171 FRAME_PTR f
= check_x_frame (frame
);
8179 bzero (&cf
, sizeof (cf
));
8180 bzero (&lf
, sizeof (lf
));
8182 cf
.lStructSize
= sizeof (cf
);
8183 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
8184 cf
.Flags
= CF_FORCEFONTEXIST
| CF_SCREENFONTS
| CF_NOVERTFONTS
;
8186 /* Unless include_proportional is non-nil, limit the selection to
8187 monospaced fonts. */
8188 if (NILP (include_proportional
))
8189 cf
.Flags
|= CF_FIXEDPITCHONLY
;
8193 /* Initialize as much of the font details as we can from the current
8195 hdc
= GetDC (FRAME_W32_WINDOW (f
));
8196 oldobj
= SelectObject (hdc
, FRAME_FONT (f
)->hfont
);
8197 GetTextFace (hdc
, LF_FACESIZE
, lf
.lfFaceName
);
8198 if (GetTextMetrics (hdc
, &tm
))
8200 lf
.lfHeight
= tm
.tmInternalLeading
- tm
.tmHeight
;
8201 lf
.lfWeight
= tm
.tmWeight
;
8202 lf
.lfItalic
= tm
.tmItalic
;
8203 lf
.lfUnderline
= tm
.tmUnderlined
;
8204 lf
.lfStrikeOut
= tm
.tmStruckOut
;
8205 lf
.lfCharSet
= tm
.tmCharSet
;
8206 cf
.Flags
|= CF_INITTOLOGFONTSTRUCT
;
8208 SelectObject (hdc
, oldobj
);
8209 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
8211 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100, NULL
))
8214 return build_string (buf
);
8217 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
,
8218 Sw32_send_sys_command
, 1, 2, 0,
8219 doc
: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
8220 Some useful values for COMMAND are #xf030 to maximize frame (#xf020
8221 to minimize), #xf120 to restore frame to original size, and #xf100
8222 to activate the menubar for keyboard access. #xf140 activates the
8223 screen saver if defined.
8225 If optional parameter FRAME is not specified, use selected frame. */)
8227 Lisp_Object command
, frame
;
8229 FRAME_PTR f
= check_x_frame (frame
);
8231 CHECK_NUMBER (command
);
8233 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
8238 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
8239 doc
: /* Get Windows to perform OPERATION on DOCUMENT.
8240 This is a wrapper around the ShellExecute system function, which
8241 invokes the application registered to handle OPERATION for DOCUMENT.
8243 OPERATION is either nil or a string that names a supported operation.
8244 What operations can be used depends on the particular DOCUMENT and its
8245 handler application, but typically it is one of the following common
8248 \"open\" - open DOCUMENT, which could be a file, a directory, or an
8249 executable program. If it is an application, that
8250 application is launched in the current buffer's default
8251 directory. Otherwise, the application associated with
8252 DOCUMENT is launched in the buffer's default directory.
8253 \"print\" - print DOCUMENT, which must be a file
8254 \"explore\" - start the Windows Explorer on DOCUMENT
8255 \"edit\" - launch an editor and open DOCUMENT for editing; which
8256 editor is launched depends on the association for the
8258 \"find\" - initiate search starting from DOCUMENT which must specify
8260 nil - invoke the default OPERATION, or \"open\" if default is
8261 not defined or unavailable
8263 DOCUMENT is typically the name of a document file or a URL, but can
8264 also be a program executable to run, or a directory to open in the
8267 If DOCUMENT is a program executable, the optional arg PARAMETERS can
8268 be a string containing command line parameters that will be passed to
8269 the program; otherwise, PARAMETERS should be nil or unspecified.
8271 Second optional argument SHOW-FLAG can be used to control how the
8272 application will be displayed when it is invoked. If SHOW-FLAG is nil
8273 or unspceified, the application is displayed normally, otherwise it is
8274 an integer representing a ShowWindow flag:
8279 6 - start minimized */)
8280 (operation
, document
, parameters
, show_flag
)
8281 Lisp_Object operation
, document
, parameters
, show_flag
;
8283 Lisp_Object current_dir
;
8285 CHECK_STRING (document
);
8287 /* Encode filename and current directory. */
8288 current_dir
= ENCODE_FILE (current_buffer
->directory
);
8289 document
= ENCODE_FILE (document
);
8290 if ((int) ShellExecute (NULL
,
8291 (STRINGP (operation
) ?
8292 SDATA (operation
) : NULL
),
8294 (STRINGP (parameters
) ?
8295 SDATA (parameters
) : NULL
),
8296 SDATA (current_dir
),
8297 (INTEGERP (show_flag
) ?
8298 XINT (show_flag
) : SW_SHOWDEFAULT
))
8301 error ("ShellExecute failed: %s", w32_strerror (0));
8304 /* Lookup virtual keycode from string representing the name of a
8305 non-ascii keystroke into the corresponding virtual key, using
8306 lispy_function_keys. */
8308 lookup_vk_code (char *key
)
8312 for (i
= 0; i
< 256; i
++)
8313 if (lispy_function_keys
[i
] != 0
8314 && strcmp (lispy_function_keys
[i
], key
) == 0)
8320 /* Convert a one-element vector style key sequence to a hot key
8323 w32_parse_hot_key (key
)
8326 /* Copied from Fdefine_key and store_in_keymap. */
8327 register Lisp_Object c
;
8331 struct gcpro gcpro1
;
8335 if (XFASTINT (Flength (key
)) != 1)
8340 c
= Faref (key
, make_number (0));
8342 if (CONSP (c
) && lucid_event_type_list_p (c
))
8343 c
= Fevent_convert_list (c
);
8347 if (! INTEGERP (c
) && ! SYMBOLP (c
))
8348 error ("Key definition is invalid");
8350 /* Work out the base key and the modifiers. */
8353 c
= parse_modifiers (c
);
8354 lisp_modifiers
= XINT (Fcar (Fcdr (c
)));
8358 vk_code
= lookup_vk_code (SDATA (SYMBOL_NAME (c
)));
8360 else if (INTEGERP (c
))
8362 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
8363 /* Many ascii characters are their own virtual key code. */
8364 vk_code
= XINT (c
) & CHARACTERBITS
;
8367 if (vk_code
< 0 || vk_code
> 255)
8370 if ((lisp_modifiers
& meta_modifier
) != 0
8371 && !NILP (Vw32_alt_is_meta
))
8372 lisp_modifiers
|= alt_modifier
;
8374 /* Supply defs missing from mingw32. */
8376 #define MOD_ALT 0x0001
8377 #define MOD_CONTROL 0x0002
8378 #define MOD_SHIFT 0x0004
8379 #define MOD_WIN 0x0008
8382 /* Convert lisp modifiers to Windows hot-key form. */
8383 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
8384 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
8385 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
8386 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
8388 return HOTKEY (vk_code
, w32_modifiers
);
8391 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
,
8392 Sw32_register_hot_key
, 1, 1, 0,
8393 doc
: /* Register KEY as a hot-key combination.
8394 Certain key combinations like Alt-Tab are reserved for system use on
8395 Windows, and therefore are normally intercepted by the system. However,
8396 most of these key combinations can be received by registering them as
8397 hot-keys, overriding their special meaning.
8399 KEY must be a one element key definition in vector form that would be
8400 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta
8401 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
8402 is always interpreted as the Windows modifier keys.
8404 The return value is the hotkey-id if registered, otherwise nil. */)
8408 key
= w32_parse_hot_key (key
);
8410 if (NILP (Fmemq (key
, w32_grabbed_keys
)))
8412 /* Reuse an empty slot if possible. */
8413 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
8415 /* Safe to add new key to list, even if we have focus. */
8417 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
8419 XSETCAR (item
, key
);
8421 /* Notify input thread about new hot-key definition, so that it
8422 takes effect without needing to switch focus. */
8423 #ifdef USE_LISP_UNION_TYPE
8424 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
8427 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
8435 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
,
8436 Sw32_unregister_hot_key
, 1, 1, 0,
8437 doc
: /* Unregister KEY as a hot-key combination. */)
8443 if (!INTEGERP (key
))
8444 key
= w32_parse_hot_key (key
);
8446 item
= Fmemq (key
, w32_grabbed_keys
);
8450 /* Notify input thread about hot-key definition being removed, so
8451 that it takes effect without needing focus switch. */
8452 #ifdef USE_LISP_UNION_TYPE
8453 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
8454 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
.i
))
8456 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
8457 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
8462 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
8469 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
,
8470 Sw32_registered_hot_keys
, 0, 0, 0,
8471 doc
: /* Return list of registered hot-key IDs. */)
8474 return Fcopy_sequence (w32_grabbed_keys
);
8477 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
,
8478 Sw32_reconstruct_hot_key
, 1, 1, 0,
8479 doc
: /* Convert hot-key ID to a lisp key combination.
8480 usage: (w32-reconstruct-hot-key ID) */)
8482 Lisp_Object hotkeyid
;
8484 int vk_code
, w32_modifiers
;
8487 CHECK_NUMBER (hotkeyid
);
8489 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
8490 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
8492 if (lispy_function_keys
[vk_code
])
8493 key
= intern (lispy_function_keys
[vk_code
]);
8495 key
= make_number (vk_code
);
8497 key
= Fcons (key
, Qnil
);
8498 if (w32_modifiers
& MOD_SHIFT
)
8499 key
= Fcons (Qshift
, key
);
8500 if (w32_modifiers
& MOD_CONTROL
)
8501 key
= Fcons (Qctrl
, key
);
8502 if (w32_modifiers
& MOD_ALT
)
8503 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
8504 if (w32_modifiers
& MOD_WIN
)
8505 key
= Fcons (Qhyper
, key
);
8510 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
,
8511 Sw32_toggle_lock_key
, 1, 2, 0,
8512 doc
: /* Toggle the state of the lock key KEY.
8513 KEY can be `capslock', `kp-numlock', or `scroll'.
8514 If the optional parameter NEW-STATE is a number, then the state of KEY
8515 is set to off if the low bit of NEW-STATE is zero, otherwise on. */)
8517 Lisp_Object key
, new_state
;
8521 if (EQ (key
, intern ("capslock")))
8522 vk_code
= VK_CAPITAL
;
8523 else if (EQ (key
, intern ("kp-numlock")))
8524 vk_code
= VK_NUMLOCK
;
8525 else if (EQ (key
, intern ("scroll")))
8526 vk_code
= VK_SCROLL
;
8530 if (!dwWindowsThreadId
)
8531 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
8533 #ifdef USE_LISP_UNION_TYPE
8534 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
8535 (WPARAM
) vk_code
, (LPARAM
) new_state
.i
))
8537 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
8538 (WPARAM
) vk_code
, (LPARAM
) new_state
))
8542 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
8543 return make_number (msg
.wParam
);
8548 DEFUN ("w32-window-exists-p", Fw32_window_exists_p
, Sw32_window_exists_p
,
8550 doc
: /* Return non-nil if a window exists with the specified CLASS and NAME.
8552 This is a direct interface to the Windows API FindWindow function. */)
8554 Lisp_Object
class, name
;
8559 CHECK_STRING (class);
8561 CHECK_STRING (name
);
8563 hnd
= FindWindow (STRINGP (class) ? ((LPCTSTR
) SDATA (class)) : NULL
,
8564 STRINGP (name
) ? ((LPCTSTR
) SDATA (name
)) : NULL
);
8572 DEFUN ("file-system-info", Ffile_system_info
, Sfile_system_info
, 1, 1, 0,
8573 doc
: /* Return storage information about the file system FILENAME is on.
8574 Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
8575 storage of the file system, FREE is the free storage, and AVAIL is the
8576 storage available to a non-superuser. All 3 numbers are in bytes.
8577 If the underlying system call fails, value is nil. */)
8579 Lisp_Object filename
;
8581 Lisp_Object encoded
, value
;
8583 CHECK_STRING (filename
);
8584 filename
= Fexpand_file_name (filename
, Qnil
);
8585 encoded
= ENCODE_FILE (filename
);
8589 /* Determining the required information on Windows turns out, sadly,
8590 to be more involved than one would hope. The original Win32 api
8591 call for this will return bogus information on some systems, but we
8592 must dynamically probe for the replacement api, since that was
8593 added rather late on. */
8595 HMODULE hKernel
= GetModuleHandle ("kernel32");
8596 BOOL (*pfn_GetDiskFreeSpaceEx
)
8597 (char *, PULARGE_INTEGER
, PULARGE_INTEGER
, PULARGE_INTEGER
)
8598 = (void *) GetProcAddress (hKernel
, "GetDiskFreeSpaceEx");
8600 /* On Windows, we may need to specify the root directory of the
8601 volume holding FILENAME. */
8602 char rootname
[MAX_PATH
];
8603 char *name
= SDATA (encoded
);
8605 /* find the root name of the volume if given */
8606 if (isalpha (name
[0]) && name
[1] == ':')
8608 rootname
[0] = name
[0];
8609 rootname
[1] = name
[1];
8613 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
8615 char *str
= rootname
;
8619 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
8629 if (pfn_GetDiskFreeSpaceEx
)
8631 /* Unsigned large integers cannot be cast to double, so
8632 use signed ones instead. */
8633 LARGE_INTEGER availbytes
;
8634 LARGE_INTEGER freebytes
;
8635 LARGE_INTEGER totalbytes
;
8637 if (pfn_GetDiskFreeSpaceEx(rootname
,
8638 (ULARGE_INTEGER
*)&availbytes
,
8639 (ULARGE_INTEGER
*)&totalbytes
,
8640 (ULARGE_INTEGER
*)&freebytes
))
8641 value
= list3 (make_float ((double) totalbytes
.QuadPart
),
8642 make_float ((double) freebytes
.QuadPart
),
8643 make_float ((double) availbytes
.QuadPart
));
8647 DWORD sectors_per_cluster
;
8648 DWORD bytes_per_sector
;
8649 DWORD free_clusters
;
8650 DWORD total_clusters
;
8652 if (GetDiskFreeSpace(rootname
,
8653 §ors_per_cluster
,
8657 value
= list3 (make_float ((double) total_clusters
8658 * sectors_per_cluster
* bytes_per_sector
),
8659 make_float ((double) free_clusters
8660 * sectors_per_cluster
* bytes_per_sector
),
8661 make_float ((double) free_clusters
8662 * sectors_per_cluster
* bytes_per_sector
));
8669 DEFUN ("default-printer-name", Fdefault_printer_name
, Sdefault_printer_name
,
8670 0, 0, 0, doc
: /* Return the name of Windows default printer device. */)
8673 static char pname_buf
[256];
8676 PRINTER_INFO_2
*ppi2
= NULL
;
8677 DWORD dwNeeded
= 0, dwReturned
= 0;
8679 /* Retrieve the default string from Win.ini (the registry).
8680 * String will be in form "printername,drivername,portname".
8681 * This is the most portable way to get the default printer. */
8682 if (GetProfileString ("windows", "device", ",,", pname_buf
, sizeof (pname_buf
)) <= 0)
8684 /* printername precedes first "," character */
8685 strtok (pname_buf
, ",");
8686 /* We want to know more than the printer name */
8687 if (!OpenPrinter (pname_buf
, &hPrn
, NULL
))
8689 GetPrinter (hPrn
, 2, NULL
, 0, &dwNeeded
);
8692 ClosePrinter (hPrn
);
8695 /* Allocate memory for the PRINTER_INFO_2 struct */
8696 ppi2
= (PRINTER_INFO_2
*) xmalloc (dwNeeded
);
8699 ClosePrinter (hPrn
);
8702 /* Call GetPrinter() again with big enouth memory block */
8703 err
= GetPrinter (hPrn
, 2, (LPBYTE
)ppi2
, dwNeeded
, &dwReturned
);
8704 ClosePrinter (hPrn
);
8713 if (ppi2
->Attributes
& PRINTER_ATTRIBUTE_SHARED
&& ppi2
->pServerName
)
8715 /* a remote printer */
8716 if (*ppi2
->pServerName
== '\\')
8717 _snprintf(pname_buf
, sizeof (pname_buf
), "%s\\%s", ppi2
->pServerName
,
8720 _snprintf(pname_buf
, sizeof (pname_buf
), "\\\\%s\\%s", ppi2
->pServerName
,
8722 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
8726 /* a local printer */
8727 strncpy(pname_buf
, ppi2
->pPortName
, sizeof (pname_buf
));
8728 pname_buf
[sizeof (pname_buf
) - 1] = '\0';
8729 /* `pPortName' can include several ports, delimited by ','.
8730 * we only use the first one. */
8731 strtok(pname_buf
, ",");
8736 return build_string (pname_buf
);
8739 /***********************************************************************
8741 ***********************************************************************/
8743 /* Keep this list in the same order as frame_parms in frame.c.
8744 Use 0 for unsupported frame parameters. */
8746 frame_parm_handler w32_frame_parm_handlers
[] =
8750 x_set_background_color
,
8756 x_set_foreground_color
,
8759 x_set_internal_border_width
,
8760 x_set_menu_bar_lines
,
8762 x_explicitly_set_name
,
8763 x_set_scroll_bar_width
,
8766 x_set_vertical_scroll_bars
,
8768 x_set_tool_bar_lines
,
8769 0, /* x_set_scroll_bar_foreground, */
8770 0, /* x_set_scroll_bar_background, */
8775 0, /* x_set_wait_for_wm, */
8777 #ifdef USE_FONT_BACKEND
8785 globals_of_w32fns ();
8786 /* This is zero if not using MS-Windows. */
8788 track_mouse_window
= NULL
;
8790 w32_visible_system_caret_hwnd
= NULL
;
8792 DEFSYM (Qnone
, "none");
8793 DEFSYM (Qsuppress_icon
, "suppress-icon");
8794 DEFSYM (Qundefined_color
, "undefined-color");
8795 DEFSYM (Qcancel_timer
, "cancel-timer");
8796 DEFSYM (Qhyper
, "hyper");
8797 DEFSYM (Qsuper
, "super");
8798 DEFSYM (Qmeta
, "meta");
8799 DEFSYM (Qalt
, "alt");
8800 DEFSYM (Qctrl
, "ctrl");
8801 DEFSYM (Qcontrol
, "control");
8802 DEFSYM (Qshift
, "shift");
8803 /* This is the end of symbol initialization. */
8805 /* Text property `display' should be nonsticky by default. */
8806 Vtext_property_default_nonsticky
8807 = Fcons (Fcons (Qdisplay
, Qt
), Vtext_property_default_nonsticky
);
8810 Fput (Qundefined_color
, Qerror_conditions
,
8811 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
8812 Fput (Qundefined_color
, Qerror_message
,
8813 build_string ("Undefined color"));
8815 staticpro (&w32_grabbed_keys
);
8816 w32_grabbed_keys
= Qnil
;
8818 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
8819 doc
: /* An array of color name mappings for Windows. */);
8820 Vw32_color_map
= Qnil
;
8822 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
8823 doc
: /* Non-nil if Alt key presses are passed on to Windows.
8824 When non-nil, for example, Alt pressed and released and then space will
8825 open the System menu. When nil, Emacs processes the Alt key events, and
8826 then silently swallows them. */);
8827 Vw32_pass_alt_to_system
= Qnil
;
8829 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
8830 doc
: /* Non-nil if the Alt key is to be considered the same as the META key.
8831 When nil, Emacs will translate the Alt key to the ALT modifier, not to META. */);
8832 Vw32_alt_is_meta
= Qt
;
8834 DEFVAR_INT ("w32-quit-key", &w32_quit_key
,
8835 doc
: /* If non-zero, the virtual key code for an alternative quit key. */);
8838 DEFVAR_LISP ("w32-pass-lwindow-to-system",
8839 &Vw32_pass_lwindow_to_system
,
8840 doc
: /* If non-nil, the left \"Windows\" key is passed on to Windows.
8842 When non-nil, the Start menu is opened by tapping the key.
8843 If you set this to nil, the left \"Windows\" key is processed by Emacs
8844 according to the value of `w32-lwindow-modifier', which see.
8846 Note that some combinations of the left \"Windows\" key with other keys are
8847 caught by Windows at low level, and so binding them in Emacs will have no
8848 effect. For example, <lwindow>-r always pops up the Windows Run dialog,
8849 <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
8850 the doc string of `w32-phantom-key-code'. */);
8851 Vw32_pass_lwindow_to_system
= Qt
;
8853 DEFVAR_LISP ("w32-pass-rwindow-to-system",
8854 &Vw32_pass_rwindow_to_system
,
8855 doc
: /* If non-nil, the right \"Windows\" key is passed on to Windows.
8857 When non-nil, the Start menu is opened by tapping the key.
8858 If you set this to nil, the right \"Windows\" key is processed by Emacs
8859 according to the value of `w32-rwindow-modifier', which see.
8861 Note that some combinations of the right \"Windows\" key with other keys are
8862 caught by Windows at low level, and so binding them in Emacs will have no
8863 effect. For example, <rwindow>-r always pops up the Windows Run dialog,
8864 <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see
8865 the doc string of `w32-phantom-key-code'. */);
8866 Vw32_pass_rwindow_to_system
= Qt
;
8868 DEFVAR_LISP ("w32-phantom-key-code",
8869 &Vw32_phantom_key_code
,
8870 doc
: /* Virtual key code used to generate \"phantom\" key presses.
8871 Value is a number between 0 and 255.
8873 Phantom key presses are generated in order to stop the system from
8874 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
8875 `w32-pass-rwindow-to-system' is nil. */);
8876 /* Although 255 is technically not a valid key code, it works and
8877 means that this hack won't interfere with any real key code. */
8878 XSETINT (Vw32_phantom_key_code
, 255);
8880 DEFVAR_LISP ("w32-enable-num-lock",
8881 &Vw32_enable_num_lock
,
8882 doc
: /* If non-nil, the Num Lock key acts normally.
8883 Set to nil to handle Num Lock as the `kp-numlock' key. */);
8884 Vw32_enable_num_lock
= Qt
;
8886 DEFVAR_LISP ("w32-enable-caps-lock",
8887 &Vw32_enable_caps_lock
,
8888 doc
: /* If non-nil, the Caps Lock key acts normally.
8889 Set to nil to handle Caps Lock as the `capslock' key. */);
8890 Vw32_enable_caps_lock
= Qt
;
8892 DEFVAR_LISP ("w32-scroll-lock-modifier",
8893 &Vw32_scroll_lock_modifier
,
8894 doc
: /* Modifier to use for the Scroll Lock ON state.
8895 The value can be hyper, super, meta, alt, control or shift for the
8896 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
8897 Any other value will cause the Scroll Lock key to be ignored. */);
8898 Vw32_scroll_lock_modifier
= Qt
;
8900 DEFVAR_LISP ("w32-lwindow-modifier",
8901 &Vw32_lwindow_modifier
,
8902 doc
: /* Modifier to use for the left \"Windows\" key.
8903 The value can be hyper, super, meta, alt, control or shift for the
8904 respective modifier, or nil to appear as the `lwindow' key.
8905 Any other value will cause the key to be ignored. */);
8906 Vw32_lwindow_modifier
= Qnil
;
8908 DEFVAR_LISP ("w32-rwindow-modifier",
8909 &Vw32_rwindow_modifier
,
8910 doc
: /* Modifier to use for the right \"Windows\" key.
8911 The value can be hyper, super, meta, alt, control or shift for the
8912 respective modifier, or nil to appear as the `rwindow' key.
8913 Any other value will cause the key to be ignored. */);
8914 Vw32_rwindow_modifier
= Qnil
;
8916 DEFVAR_LISP ("w32-apps-modifier",
8917 &Vw32_apps_modifier
,
8918 doc
: /* Modifier to use for the \"Apps\" key.
8919 The value can be hyper, super, meta, alt, control or shift for the
8920 respective modifier, or nil to appear as the `apps' key.
8921 Any other value will cause the key to be ignored. */);
8922 Vw32_apps_modifier
= Qnil
;
8924 DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts
,
8925 doc
: /* Non-nil enables selection of artificially italicized and bold fonts. */);
8926 w32_enable_synthesized_fonts
= 0;
8928 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
8929 doc
: /* Non-nil enables Windows palette management to map colors exactly. */);
8930 Vw32_enable_palette
= Qt
;
8932 DEFVAR_INT ("w32-mouse-button-tolerance",
8933 &w32_mouse_button_tolerance
,
8934 doc
: /* Analogue of double click interval for faking middle mouse events.
8935 The value is the minimum time in milliseconds that must elapse between
8936 left and right button down events before they are considered distinct events.
8937 If both mouse buttons are depressed within this interval, a middle mouse
8938 button down event is generated instead. */);
8939 w32_mouse_button_tolerance
= GetDoubleClickTime () / 2;
8941 DEFVAR_INT ("w32-mouse-move-interval",
8942 &w32_mouse_move_interval
,
8943 doc
: /* Minimum interval between mouse move events.
8944 The value is the minimum time in milliseconds that must elapse between
8945 successive mouse move (or scroll bar drag) events before they are
8946 reported as lisp events. */);
8947 w32_mouse_move_interval
= 0;
8949 DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
8950 &w32_pass_extra_mouse_buttons_to_system
,
8951 doc
: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
8952 Recent versions of Windows support mice with up to five buttons.
8953 Since most applications don't support these extra buttons, most mouse
8954 drivers will allow you to map them to functions at the system level.
8955 If this variable is non-nil, Emacs will pass them on, allowing the
8956 system to handle them. */);
8957 w32_pass_extra_mouse_buttons_to_system
= 0;
8959 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
8960 doc
: /* The shape of the pointer when over text.
8961 Changing the value does not affect existing frames
8962 unless you set the mouse color. */);
8963 Vx_pointer_shape
= Qnil
;
8965 Vx_nontext_pointer_shape
= Qnil
;
8967 Vx_mode_pointer_shape
= Qnil
;
8969 DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape
,
8970 doc
: /* The shape of the pointer when Emacs is busy.
8971 This variable takes effect when you create a new frame
8972 or when you set the mouse color. */);
8973 Vx_hourglass_pointer_shape
= Qnil
;
8975 DEFVAR_BOOL ("display-hourglass", &display_hourglass_p
,
8976 doc
: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
8977 display_hourglass_p
= 1;
8979 DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay
,
8980 doc
: /* *Seconds to wait before displaying an hourglass pointer.
8981 Value must be an integer or float. */);
8982 Vhourglass_delay
= make_number (DEFAULT_HOURGLASS_DELAY
);
8984 DEFVAR_LISP ("x-sensitive-text-pointer-shape",
8985 &Vx_sensitive_text_pointer_shape
,
8986 doc
: /* The shape of the pointer when over mouse-sensitive text.
8987 This variable takes effect when you create a new frame
8988 or when you set the mouse color. */);
8989 Vx_sensitive_text_pointer_shape
= Qnil
;
8991 DEFVAR_LISP ("x-window-horizontal-drag-cursor",
8992 &Vx_window_horizontal_drag_shape
,
8993 doc
: /* Pointer shape to use for indicating a window can be dragged horizontally.
8994 This variable takes effect when you create a new frame
8995 or when you set the mouse color. */);
8996 Vx_window_horizontal_drag_shape
= Qnil
;
8998 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
8999 doc
: /* A string indicating the foreground color of the cursor box. */);
9000 Vx_cursor_fore_pixel
= Qnil
;
9002 DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size
,
9003 doc
: /* Maximum size for tooltips.
9004 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */);
9005 Vx_max_tooltip_size
= Fcons (make_number (80), make_number (40));
9007 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
9008 doc
: /* Non-nil if no window manager is in use.
9009 Emacs doesn't try to figure this out; this is always nil
9010 unless you set it to something else. */);
9011 /* We don't have any way to find this out, so set it to nil
9012 and maybe the user would like to set it to t. */
9013 Vx_no_window_manager
= Qnil
;
9015 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
9016 &Vx_pixel_size_width_font_regexp
,
9017 doc
: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
9019 Since Emacs gets width of a font matching with this regexp from
9020 PIXEL_SIZE field of the name, font finding mechanism gets faster for
9021 such a font. This is especially effective for such large fonts as
9022 Chinese, Japanese, and Korean. */);
9023 Vx_pixel_size_width_font_regexp
= Qnil
;
9025 DEFVAR_LISP ("w32-bdf-filename-alist",
9026 &Vw32_bdf_filename_alist
,
9027 doc
: /* List of bdf fonts and their corresponding filenames. */);
9028 Vw32_bdf_filename_alist
= Qnil
;
9030 DEFVAR_BOOL ("w32-strict-fontnames",
9031 &w32_strict_fontnames
,
9032 doc
: /* Non-nil means only use fonts that are exact matches for those requested.
9033 Default is nil, which allows old fontnames that are not XLFD compliant,
9034 and allows third-party CJK display to work by specifying false charset
9035 fields to trick Emacs into translating to Big5, SJIS etc.
9036 Setting this to t will prevent wrong fonts being selected when
9037 fontsets are automatically created. */);
9038 w32_strict_fontnames
= 0;
9040 DEFVAR_BOOL ("w32-strict-painting",
9041 &w32_strict_painting
,
9042 doc
: /* Non-nil means use strict rules for repainting frames.
9043 Set this to nil to get the old behavior for repainting; this should
9044 only be necessary if the default setting causes problems. */);
9045 w32_strict_painting
= 1;
9047 DEFVAR_LISP ("w32-charset-info-alist",
9048 &Vw32_charset_info_alist
,
9049 doc
: /* Alist linking Emacs character sets to Windows fonts and codepages.
9050 Each entry should be of the form:
9052 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
9054 where CHARSET_NAME is a string used in font names to identify the charset,
9055 WINDOWS_CHARSET is a symbol that can be one of:
9056 w32-charset-ansi, w32-charset-default, w32-charset-symbol,
9057 w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
9058 w32-charset-chinesebig5,
9059 w32-charset-johab, w32-charset-hebrew,
9060 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
9061 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
9062 w32-charset-russian, w32-charset-mac, w32-charset-baltic,
9063 w32-charset-unicode,
9065 CODEPAGE should be an integer specifying the codepage that should be used
9066 to display the character set, t to do no translation and output as Unicode,
9067 or nil to do no translation and output as 8 bit (or multibyte on far-east
9068 versions of Windows) characters. */);
9069 Vw32_charset_info_alist
= Qnil
;
9071 DEFSYM (Qw32_charset_ansi
, "w32-charset-ansi");
9072 DEFSYM (Qw32_charset_symbol
, "w32-charset-symbol");
9073 DEFSYM (Qw32_charset_default
, "w32-charset-default");
9074 DEFSYM (Qw32_charset_shiftjis
, "w32-charset-shiftjis");
9075 DEFSYM (Qw32_charset_hangeul
, "w32-charset-hangeul");
9076 DEFSYM (Qw32_charset_chinesebig5
, "w32-charset-chinesebig5");
9077 DEFSYM (Qw32_charset_gb2312
, "w32-charset-gb2312");
9078 DEFSYM (Qw32_charset_oem
, "w32-charset-oem");
9080 #ifdef JOHAB_CHARSET
9082 static int w32_extra_charsets_defined
= 1;
9083 DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined
,
9084 doc
: /* Internal variable. */);
9086 DEFSYM (Qw32_charset_johab
, "w32-charset-johab");
9087 DEFSYM (Qw32_charset_easteurope
, "w32-charset-easteurope");
9088 DEFSYM (Qw32_charset_turkish
, "w32-charset-turkish");
9089 DEFSYM (Qw32_charset_baltic
, "w32-charset-baltic");
9090 DEFSYM (Qw32_charset_russian
, "w32-charset-russian");
9091 DEFSYM (Qw32_charset_arabic
, "w32-charset-arabic");
9092 DEFSYM (Qw32_charset_greek
, "w32-charset-greek");
9093 DEFSYM (Qw32_charset_hebrew
, "w32-charset-hebrew");
9094 DEFSYM (Qw32_charset_vietnamese
, "w32-charset-vietnamese");
9095 DEFSYM (Qw32_charset_thai
, "w32-charset-thai");
9096 DEFSYM (Qw32_charset_mac
, "w32-charset-mac");
9100 #ifdef UNICODE_CHARSET
9102 static int w32_unicode_charset_defined
= 1;
9103 DEFVAR_BOOL ("w32-unicode-charset-defined",
9104 &w32_unicode_charset_defined
,
9105 doc
: /* Internal variable. */);
9106 DEFSYM (Qw32_charset_unicode
, "w32-charset-unicode");
9110 #if 0 /* TODO: Port to W32 */
9111 defsubr (&Sx_change_window_property
);
9112 defsubr (&Sx_delete_window_property
);
9113 defsubr (&Sx_window_property
);
9115 defsubr (&Sxw_display_color_p
);
9116 defsubr (&Sx_display_grayscale_p
);
9117 defsubr (&Sxw_color_defined_p
);
9118 defsubr (&Sxw_color_values
);
9119 defsubr (&Sx_server_max_request_size
);
9120 defsubr (&Sx_server_vendor
);
9121 defsubr (&Sx_server_version
);
9122 defsubr (&Sx_display_pixel_width
);
9123 defsubr (&Sx_display_pixel_height
);
9124 defsubr (&Sx_display_mm_width
);
9125 defsubr (&Sx_display_mm_height
);
9126 defsubr (&Sx_display_screens
);
9127 defsubr (&Sx_display_planes
);
9128 defsubr (&Sx_display_color_cells
);
9129 defsubr (&Sx_display_visual_class
);
9130 defsubr (&Sx_display_backing_store
);
9131 defsubr (&Sx_display_save_under
);
9132 defsubr (&Sx_create_frame
);
9133 defsubr (&Sx_open_connection
);
9134 defsubr (&Sx_close_connection
);
9135 defsubr (&Sx_display_list
);
9136 defsubr (&Sx_synchronize
);
9137 defsubr (&Sx_focus_frame
);
9139 /* W32 specific functions */
9141 defsubr (&Sw32_select_font
);
9142 defsubr (&Sw32_define_rgb_color
);
9143 defsubr (&Sw32_default_color_map
);
9144 defsubr (&Sw32_load_color_file
);
9145 defsubr (&Sw32_send_sys_command
);
9146 defsubr (&Sw32_shell_execute
);
9147 defsubr (&Sw32_register_hot_key
);
9148 defsubr (&Sw32_unregister_hot_key
);
9149 defsubr (&Sw32_registered_hot_keys
);
9150 defsubr (&Sw32_reconstruct_hot_key
);
9151 defsubr (&Sw32_toggle_lock_key
);
9152 defsubr (&Sw32_window_exists_p
);
9153 defsubr (&Sw32_find_bdf_fonts
);
9155 defsubr (&Sfile_system_info
);
9156 defsubr (&Sdefault_printer_name
);
9158 /* Setting callback functions for fontset handler. */
9159 get_font_info_func
= w32_get_font_info
;
9161 #if 0 /* This function pointer doesn't seem to be used anywhere.
9162 And the pointer assigned has the wrong type, anyway. */
9163 list_fonts_func
= w32_list_fonts
;
9166 load_font_func
= w32_load_font
;
9167 find_ccl_program_func
= w32_find_ccl_program
;
9168 query_font_func
= w32_query_font
;
9169 set_frame_fontset_func
= x_set_font
;
9170 get_font_repertory_func
= x_get_font_repertory
;
9171 check_window_system_func
= check_w32
;
9174 hourglass_atimer
= NULL
;
9175 hourglass_shown_p
= 0;
9176 defsubr (&Sx_show_tip
);
9177 defsubr (&Sx_hide_tip
);
9179 staticpro (&tip_timer
);
9181 staticpro (&tip_frame
);
9183 last_show_tip_args
= Qnil
;
9184 staticpro (&last_show_tip_args
);
9186 defsubr (&Sx_file_dialog
);
9191 globals_of_w32fns is used to initialize those global variables that
9192 must always be initialized on startup even when the global variable
9193 initialized is non zero (see the function main in emacs.c).
9194 globals_of_w32fns is called from syms_of_w32fns when the global
9195 variable initialized is 0 and directly from main when initialized
9198 void globals_of_w32fns ()
9200 HMODULE user32_lib
= GetModuleHandle ("user32.dll");
9202 TrackMouseEvent not available in all versions of Windows, so must load
9203 it dynamically. Do it once, here, instead of every time it is used.
9205 track_mouse_event_fn
= (TrackMouseEvent_Proc
)
9206 GetProcAddress (user32_lib
, "TrackMouseEvent");
9207 /* ditto for GetClipboardSequenceNumber. */
9208 clipboard_sequence_fn
= (ClipboardSequence_Proc
)
9209 GetProcAddress (user32_lib
, "GetClipboardSequenceNumber");
9211 DEFVAR_INT ("w32-ansi-code-page",
9212 &w32_ansi_code_page
,
9213 doc
: /* The ANSI code page used by the system. */);
9214 w32_ansi_code_page
= GetACP ();
9216 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
9217 InitCommonControls ();
9222 void w32_abort (void) NO_RETURN
;
9228 button
= MessageBox (NULL
,
9229 "A fatal error has occurred!\n\n"
9230 "Would you like to attach a debugger?\n\n"
9231 "Select YES to debug, NO to abort Emacs"
9233 "\n\n(type \"gdb -p <emacs-PID>\" and\n"
9234 "\"continue\" inside GDB before clicking YES.)"
9236 , "Emacs Abort Dialog",
9237 MB_ICONEXCLAMATION
| MB_TASKMODAL
9238 | MB_SETFOREGROUND
| MB_YESNO
);
9243 exit (2); /* tell the compiler we will never return */
9251 /* For convenience when debugging. */
9255 return GetLastError ();
9258 /* arch-tag: 707589ab-b9be-4638-8cdd-74629cc9b446
9259 (do not change this comment) */