1 /* Graphical user interface functions for the Microsoft W32 API.
2 Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Added by Kevin Gallo */
37 #include "dispextern.h"
39 #include "blockinput.h"
42 #include "termhooks.h"
50 extern void free_frame_menubar ();
51 extern struct scroll_bar
*x_window_to_scroll_bar ();
52 extern int w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
);
55 extern char *lispy_function_keys
[];
57 /* The colormap for converting color names to RGB values */
58 Lisp_Object Vw32_color_map
;
60 /* Non nil if alt key presses are passed on to Windows. */
61 Lisp_Object Vw32_pass_alt_to_system
;
63 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
65 Lisp_Object Vw32_alt_is_meta
;
67 /* If non-zero, the windows virtual key code for an alternative quit key. */
68 Lisp_Object Vw32_quit_key
;
70 /* Non nil if left window key events are passed on to Windows (this only
71 affects whether "tapping" the key opens the Start menu). */
72 Lisp_Object Vw32_pass_lwindow_to_system
;
74 /* Non nil if right window key events are passed on to Windows (this
75 only affects whether "tapping" the key opens the Start menu). */
76 Lisp_Object Vw32_pass_rwindow_to_system
;
78 /* Virtual key code used to generate "phantom" key presses in order
79 to stop system from acting on Windows key events. */
80 Lisp_Object Vw32_phantom_key_code
;
82 /* Modifier associated with the left "Windows" key, or nil to act as a
84 Lisp_Object Vw32_lwindow_modifier
;
86 /* Modifier associated with the right "Windows" key, or nil to act as a
88 Lisp_Object Vw32_rwindow_modifier
;
90 /* Modifier associated with the "Apps" key, or nil to act as a normal
92 Lisp_Object Vw32_apps_modifier
;
94 /* Value is nil if Num Lock acts as a function key. */
95 Lisp_Object Vw32_enable_num_lock
;
97 /* Value is nil if Caps Lock acts as a function key. */
98 Lisp_Object Vw32_enable_caps_lock
;
100 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
101 Lisp_Object Vw32_scroll_lock_modifier
;
103 /* Switch to control whether we inhibit requests for italicised fonts (which
104 are synthesized, look ugly, and are trashed by cursor movement under NT). */
105 Lisp_Object Vw32_enable_italics
;
107 /* Enable palette management. */
108 Lisp_Object Vw32_enable_palette
;
110 /* Control how close left/right button down events must be to
111 be converted to a middle button down event. */
112 Lisp_Object Vw32_mouse_button_tolerance
;
114 /* Minimum interval between mouse movement (and scroll bar drag)
115 events that are passed on to the event loop. */
116 Lisp_Object Vw32_mouse_move_interval
;
118 /* The name we're using in resource queries. */
119 Lisp_Object Vx_resource_name
;
121 /* Non nil if no window manager is in use. */
122 Lisp_Object Vx_no_window_manager
;
124 /* The background and shape of the mouse pointer, and shape when not
125 over text or in the modeline. */
126 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
127 /* The shape when over mouse-sensitive text. */
128 Lisp_Object Vx_sensitive_text_pointer_shape
;
130 /* Color of chars displayed in cursor box. */
131 Lisp_Object Vx_cursor_fore_pixel
;
133 /* Nonzero if using Windows. */
134 static int w32_in_use
;
136 /* Search path for bitmap files. */
137 Lisp_Object Vx_bitmap_file_path
;
139 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
140 Lisp_Object Vx_pixel_size_width_font_regexp
;
142 /* Alist of bdf fonts and the files that define them. */
143 Lisp_Object Vw32_bdf_filename_alist
;
145 Lisp_Object Vw32_system_coding_system
;
147 /* A flag to control whether fonts are matched strictly or not. */
148 int w32_strict_fontnames
;
150 /* A flag to control whether we should only repaint if GetUpdateRect
151 indicates there is an update region. */
152 int w32_strict_painting
;
154 /* Evaluate this expression to rebuild the section of syms_of_w32fns
155 that initializes and staticpros the symbols declared below. Note
156 that Emacs 18 has a bug that keeps C-x C-e from being able to
157 evaluate this expression.
160 ;; Accumulate a list of the symbols we want to initialize from the
161 ;; declarations at the top of the file.
162 (goto-char (point-min))
163 (search-forward "/\*&&& symbols declared here &&&*\/\n")
165 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
167 (cons (buffer-substring (match-beginning 1) (match-end 1))
170 (setq symbol-list (nreverse symbol-list))
171 ;; Delete the section of syms_of_... where we initialize the symbols.
172 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
173 (let ((start (point)))
174 (while (looking-at "^ Q")
176 (kill-region start (point)))
177 ;; Write a new symbol initialization section.
179 (insert (format " %s = intern (\"" (car symbol-list)))
180 (let ((start (point)))
181 (insert (substring (car symbol-list) 1))
182 (subst-char-in-region start (point) ?_ ?-))
183 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
184 (setq symbol-list (cdr symbol-list)))))
188 /*&&& symbols declared here &&&*/
189 Lisp_Object Qauto_raise
;
190 Lisp_Object Qauto_lower
;
191 Lisp_Object Qbackground_color
;
193 Lisp_Object Qborder_color
;
194 Lisp_Object Qborder_width
;
196 Lisp_Object Qcursor_color
;
197 Lisp_Object Qcursor_type
;
198 Lisp_Object Qforeground_color
;
199 Lisp_Object Qgeometry
;
200 Lisp_Object Qicon_left
;
201 Lisp_Object Qicon_top
;
202 Lisp_Object Qicon_type
;
203 Lisp_Object Qicon_name
;
204 Lisp_Object Qinternal_border_width
;
207 Lisp_Object Qmouse_color
;
209 Lisp_Object Qparent_id
;
210 Lisp_Object Qscroll_bar_width
;
211 Lisp_Object Qsuppress_icon
;
213 Lisp_Object Qundefined_color
;
214 Lisp_Object Qvertical_scroll_bars
;
215 Lisp_Object Qvisibility
;
216 Lisp_Object Qwindow_id
;
217 Lisp_Object Qx_frame_parameter
;
218 Lisp_Object Qx_resource_name
;
219 Lisp_Object Quser_position
;
220 Lisp_Object Quser_size
;
221 Lisp_Object Qdisplay
;
228 Lisp_Object Qcontrol
;
231 /* State variables for emulating a three button mouse. */
236 static int button_state
= 0;
237 static W32Msg saved_mouse_button_msg
;
238 static unsigned mouse_button_timer
; /* non-zero when timer is active */
239 static W32Msg saved_mouse_move_msg
;
240 static unsigned mouse_move_timer
;
242 /* W95 mousewheel handler */
243 unsigned int msh_mousewheel
= 0;
245 #define MOUSE_BUTTON_ID 1
246 #define MOUSE_MOVE_ID 2
248 /* The below are defined in frame.c. */
249 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
250 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
252 extern Lisp_Object Vwindow_system_version
;
254 Lisp_Object Qface_set_after_frame_default
;
256 extern Lisp_Object last_mouse_scroll_bar
;
257 extern int last_mouse_scroll_bar_pos
;
259 /* From w32term.c. */
260 extern Lisp_Object Vw32_num_mouse_buttons
;
261 extern Lisp_Object Vw32_recognize_altgr
;
264 /* Error if we are not connected to MS-Windows. */
269 error ("MS-Windows not in use or not initialized");
272 /* Nonzero if we can use mouse menus.
273 You should not call this unless HAVE_MENUS is defined. */
281 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
282 and checking validity for W32. */
285 check_x_frame (frame
)
294 CHECK_LIVE_FRAME (frame
, 0);
297 if (! FRAME_W32_P (f
))
298 error ("non-w32 frame used");
302 /* Let the user specify an display with a frame.
303 nil stands for the selected frame--or, if that is not a w32 frame,
304 the first display on the list. */
306 static struct w32_display_info
*
307 check_x_display_info (frame
)
312 if (FRAME_W32_P (selected_frame
))
313 return FRAME_W32_DISPLAY_INFO (selected_frame
);
315 return &one_w32_display_info
;
317 else if (STRINGP (frame
))
318 return x_display_info_for_name (frame
);
323 CHECK_LIVE_FRAME (frame
, 0);
325 if (! FRAME_W32_P (f
))
326 error ("non-w32 frame used");
327 return FRAME_W32_DISPLAY_INFO (f
);
331 /* Return the Emacs frame-object corresponding to an w32 window.
332 It could be the frame's main window or an icon window. */
334 /* This function can be called during GC, so use GC_xxx type test macros. */
337 x_window_to_frame (dpyinfo
, wdesc
)
338 struct w32_display_info
*dpyinfo
;
341 Lisp_Object tail
, frame
;
344 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
346 frame
= XCONS (tail
)->car
;
347 if (!GC_FRAMEP (frame
))
350 if (f
->output_data
.nothing
== 1
351 || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
353 if (FRAME_W32_WINDOW (f
) == wdesc
)
361 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
362 id, which is just an int that this section returns. Bitmaps are
363 reference counted so they can be shared among frames.
365 Bitmap indices are guaranteed to be > 0, so a negative number can
366 be used to indicate no bitmap.
368 If you use x_create_bitmap_from_data, then you must keep track of
369 the bitmaps yourself. That is, creating a bitmap from the same
370 data more than once will not be caught. */
373 /* Functions to access the contents of a bitmap, given an id. */
376 x_bitmap_height (f
, id
)
380 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
384 x_bitmap_width (f
, id
)
388 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
392 x_bitmap_pixmap (f
, id
)
396 return (int) FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
400 /* Allocate a new bitmap record. Returns index of new record. */
403 x_allocate_bitmap_record (f
)
406 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
409 if (dpyinfo
->bitmaps
== NULL
)
411 dpyinfo
->bitmaps_size
= 10;
413 = (struct w32_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
414 dpyinfo
->bitmaps_last
= 1;
418 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
419 return ++dpyinfo
->bitmaps_last
;
421 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
422 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
425 dpyinfo
->bitmaps_size
*= 2;
427 = (struct w32_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
428 dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
429 return ++dpyinfo
->bitmaps_last
;
432 /* Add one reference to the reference count of the bitmap with id ID. */
435 x_reference_bitmap (f
, id
)
439 ++FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
442 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
445 x_create_bitmap_from_data (f
, bits
, width
, height
)
448 unsigned int width
, height
;
450 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
454 bitmap
= CreateBitmap (width
, height
,
455 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
456 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
462 id
= x_allocate_bitmap_record (f
);
463 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
464 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
465 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
466 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
467 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
468 dpyinfo
->bitmaps
[id
- 1].height
= height
;
469 dpyinfo
->bitmaps
[id
- 1].width
= width
;
474 /* Create bitmap from file FILE for frame F. */
477 x_create_bitmap_from_file (f
, file
)
483 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
484 unsigned int width
, height
;
486 int xhot
, yhot
, result
, id
;
492 /* Look for an existing bitmap with the same name. */
493 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
495 if (dpyinfo
->bitmaps
[id
].refcount
496 && dpyinfo
->bitmaps
[id
].file
497 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
499 ++dpyinfo
->bitmaps
[id
].refcount
;
504 /* Search bitmap-file-path for the file, if appropriate. */
505 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
508 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
513 filename
= (char *) XSTRING (found
)->data
;
515 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
521 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
522 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
523 if (result
!= BitmapSuccess
)
526 id
= x_allocate_bitmap_record (f
);
527 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
528 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
529 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (XSTRING (file
)->size
+ 1);
530 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
531 dpyinfo
->bitmaps
[id
- 1].height
= height
;
532 dpyinfo
->bitmaps
[id
- 1].width
= width
;
533 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
539 /* Remove reference to bitmap with id number ID. */
542 x_destroy_bitmap (f
, id
)
546 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
550 --dpyinfo
->bitmaps
[id
- 1].refcount
;
551 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
554 DeleteObject (dpyinfo
->bitmaps
[id
- 1].pixmap
);
555 if (dpyinfo
->bitmaps
[id
- 1].file
)
557 free (dpyinfo
->bitmaps
[id
- 1].file
);
558 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
565 /* Free all the bitmaps for the display specified by DPYINFO. */
568 x_destroy_all_bitmaps (dpyinfo
)
569 struct w32_display_info
*dpyinfo
;
572 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
573 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
575 DeleteObject (dpyinfo
->bitmaps
[i
].pixmap
);
576 if (dpyinfo
->bitmaps
[i
].file
)
577 free (dpyinfo
->bitmaps
[i
].file
);
579 dpyinfo
->bitmaps_last
= 0;
582 /* Connect the frame-parameter names for W32 frames
583 to the ways of passing the parameter values to the window system.
585 The name of a parameter, as a Lisp symbol,
586 has an `x-frame-parameter' property which is an integer in Lisp
587 but can be interpreted as an `enum x_frame_parm' in C. */
591 X_PARM_FOREGROUND_COLOR
,
592 X_PARM_BACKGROUND_COLOR
,
599 X_PARM_INTERNAL_BORDER_WIDTH
,
603 X_PARM_VERT_SCROLL_BAR
,
605 X_PARM_MENU_BAR_LINES
609 struct x_frame_parm_table
612 void (*setter
)( /* struct frame *frame, Lisp_Object val, oldval */ );
615 void x_set_foreground_color ();
616 void x_set_background_color ();
617 void x_set_mouse_color ();
618 void x_set_cursor_color ();
619 void x_set_border_color ();
620 void x_set_cursor_type ();
621 void x_set_icon_type ();
622 void x_set_icon_name ();
624 void x_set_border_width ();
625 void x_set_internal_border_width ();
626 void x_explicitly_set_name ();
627 void x_set_autoraise ();
628 void x_set_autolower ();
629 void x_set_vertical_scroll_bars ();
630 void x_set_visibility ();
631 void x_set_menu_bar_lines ();
632 void x_set_scroll_bar_width ();
634 void x_set_unsplittable ();
636 static struct x_frame_parm_table x_frame_parms
[] =
638 "auto-raise", x_set_autoraise
,
639 "auto-lower", x_set_autolower
,
640 "background-color", x_set_background_color
,
641 "border-color", x_set_border_color
,
642 "border-width", x_set_border_width
,
643 "cursor-color", x_set_cursor_color
,
644 "cursor-type", x_set_cursor_type
,
646 "foreground-color", x_set_foreground_color
,
647 "icon-name", x_set_icon_name
,
648 "icon-type", x_set_icon_type
,
649 "internal-border-width", x_set_internal_border_width
,
650 "menu-bar-lines", x_set_menu_bar_lines
,
651 "mouse-color", x_set_mouse_color
,
652 "name", x_explicitly_set_name
,
653 "scroll-bar-width", x_set_scroll_bar_width
,
654 "title", x_set_title
,
655 "unsplittable", x_set_unsplittable
,
656 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
657 "visibility", x_set_visibility
,
660 /* Attach the `x-frame-parameter' properties to
661 the Lisp symbol names of parameters relevant to W32. */
663 init_x_parm_symbols ()
667 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
668 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
672 /* Change the parameters of FRAME as specified by ALIST.
673 If a parameter is not specially recognized, do nothing;
674 otherwise call the `x_set_...' function for that parameter. */
677 x_set_frame_parameters (f
, alist
)
683 /* If both of these parameters are present, it's more efficient to
684 set them both at once. So we wait until we've looked at the
685 entire list before we set them. */
689 Lisp_Object left
, top
;
691 /* Same with these. */
692 Lisp_Object icon_left
, icon_top
;
694 /* Record in these vectors all the parms specified. */
698 int left_no_change
= 0, top_no_change
= 0;
699 int icon_left_no_change
= 0, icon_top_no_change
= 0;
701 struct gcpro gcpro1
, gcpro2
;
704 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
707 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
708 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
710 /* Extract parm names and values into those vectors. */
713 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
715 Lisp_Object elt
, prop
, val
;
718 parms
[i
] = Fcar (elt
);
719 values
[i
] = Fcdr (elt
);
723 /* TAIL and ALIST are not used again below here. */
726 GCPRO2 (*parms
, *values
);
730 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
731 because their values appear in VALUES and strings are not valid. */
732 top
= left
= Qunbound
;
733 icon_left
= icon_top
= Qunbound
;
735 /* Provide default values for HEIGHT and WIDTH. */
736 width
= FRAME_WIDTH (f
);
737 height
= FRAME_HEIGHT (f
);
739 /* Now process them in reverse of specified order. */
740 for (i
--; i
>= 0; i
--)
742 Lisp_Object prop
, val
;
747 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
748 width
= XFASTINT (val
);
749 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
750 height
= XFASTINT (val
);
751 else if (EQ (prop
, Qtop
))
753 else if (EQ (prop
, Qleft
))
755 else if (EQ (prop
, Qicon_top
))
757 else if (EQ (prop
, Qicon_left
))
761 register Lisp_Object param_index
, old_value
;
763 param_index
= Fget (prop
, Qx_frame_parameter
);
764 old_value
= get_frame_param (f
, prop
);
765 store_frame_param (f
, prop
, val
);
766 if (NATNUMP (param_index
)
767 && (XFASTINT (param_index
)
768 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
769 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
773 /* Don't die if just one of these was set. */
774 if (EQ (left
, Qunbound
))
777 if (f
->output_data
.w32
->left_pos
< 0)
778 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->left_pos
), Qnil
));
780 XSETINT (left
, f
->output_data
.w32
->left_pos
);
782 if (EQ (top
, Qunbound
))
785 if (f
->output_data
.w32
->top_pos
< 0)
786 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->top_pos
), Qnil
));
788 XSETINT (top
, f
->output_data
.w32
->top_pos
);
791 /* If one of the icon positions was not set, preserve or default it. */
792 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
794 icon_left_no_change
= 1;
795 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
796 if (NILP (icon_left
))
797 XSETINT (icon_left
, 0);
799 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
801 icon_top_no_change
= 1;
802 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
804 XSETINT (icon_top
, 0);
807 /* Don't set these parameters unless they've been explicitly
808 specified. The window might be mapped or resized while we're in
809 this function, and we don't want to override that unless the lisp
810 code has asked for it.
812 Don't set these parameters unless they actually differ from the
813 window's current parameters; the window may not actually exist
818 check_frame_size (f
, &height
, &width
);
820 XSETFRAME (frame
, f
);
822 if (XINT (width
) != FRAME_WIDTH (f
)
823 || XINT (height
) != FRAME_HEIGHT (f
))
824 Fset_frame_size (frame
, make_number (width
), make_number (height
));
826 if ((!NILP (left
) || !NILP (top
))
827 && ! (left_no_change
&& top_no_change
)
828 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.w32
->left_pos
829 && NUMBERP (top
) && XINT (top
) == f
->output_data
.w32
->top_pos
))
834 /* Record the signs. */
835 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
836 if (EQ (left
, Qminus
))
837 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
838 else if (INTEGERP (left
))
840 leftpos
= XINT (left
);
842 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
844 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
845 && CONSP (XCONS (left
)->cdr
)
846 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
848 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
849 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
851 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
852 && CONSP (XCONS (left
)->cdr
)
853 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
855 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
858 if (EQ (top
, Qminus
))
859 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
860 else if (INTEGERP (top
))
864 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
866 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
867 && CONSP (XCONS (top
)->cdr
)
868 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
870 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
871 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
873 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
874 && CONSP (XCONS (top
)->cdr
)
875 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
877 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
881 /* Store the numeric value of the position. */
882 f
->output_data
.w32
->top_pos
= toppos
;
883 f
->output_data
.w32
->left_pos
= leftpos
;
885 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
887 /* Actually set that position, and convert to absolute. */
888 x_set_offset (f
, leftpos
, toppos
, -1);
891 if ((!NILP (icon_left
) || !NILP (icon_top
))
892 && ! (icon_left_no_change
&& icon_top_no_change
))
893 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
899 /* Store the screen positions of frame F into XPTR and YPTR.
900 These are the positions of the containing window manager window,
901 not Emacs's own window. */
904 x_real_positions (f
, xptr
, yptr
)
913 GetClientRect(FRAME_W32_WINDOW(f
), &rect
);
914 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
, FRAME_EXTERNAL_MENU_BAR(f
));
920 ClientToScreen (FRAME_W32_WINDOW(f
), &pt
);
926 /* Insert a description of internally-recorded parameters of frame X
927 into the parameter alist *ALISTPTR that is to be given to the user.
928 Only parameters that are specific to W32
929 and whose values are not correctly recorded in the frame's
930 param_alist need to be considered here. */
932 x_report_frame_params (f
, alistptr
)
934 Lisp_Object
*alistptr
;
939 /* Represent negative positions (off the top or left screen edge)
940 in a way that Fmodify_frame_parameters will understand correctly. */
941 XSETINT (tem
, f
->output_data
.w32
->left_pos
);
942 if (f
->output_data
.w32
->left_pos
>= 0)
943 store_in_alist (alistptr
, Qleft
, tem
);
945 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
947 XSETINT (tem
, f
->output_data
.w32
->top_pos
);
948 if (f
->output_data
.w32
->top_pos
>= 0)
949 store_in_alist (alistptr
, Qtop
, tem
);
951 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
953 store_in_alist (alistptr
, Qborder_width
,
954 make_number (f
->output_data
.w32
->border_width
));
955 store_in_alist (alistptr
, Qinternal_border_width
,
956 make_number (f
->output_data
.w32
->internal_border_width
));
957 sprintf (buf
, "%ld", (long) FRAME_W32_WINDOW (f
));
958 store_in_alist (alistptr
, Qwindow_id
,
960 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
961 FRAME_SAMPLE_VISIBILITY (f
);
962 store_in_alist (alistptr
, Qvisibility
,
963 (FRAME_VISIBLE_P (f
) ? Qt
964 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
965 store_in_alist (alistptr
, Qdisplay
,
966 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->car
);
970 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
, Sw32_define_rgb_color
, 4, 4, 0,
971 "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
972 This adds or updates a named color to w32-color-map, making it available for use.\n\
973 The original entry's RGB ref is returned, or nil if the entry is new.")
974 (red
, green
, blue
, name
)
975 Lisp_Object red
, green
, blue
, name
;
978 Lisp_Object oldrgb
= Qnil
;
981 CHECK_NUMBER (red
, 0);
982 CHECK_NUMBER (green
, 0);
983 CHECK_NUMBER (blue
, 0);
984 CHECK_STRING (name
, 0);
986 XSET (rgb
, Lisp_Int
, RGB(XUINT (red
), XUINT (green
), XUINT (blue
)));
990 /* replace existing entry in w32-color-map or add new entry. */
991 entry
= Fassoc (name
, Vw32_color_map
);
994 entry
= Fcons (name
, rgb
);
995 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
999 oldrgb
= Fcdr (entry
);
1000 Fsetcdr (entry
, rgb
);
1008 DEFUN ("w32-load-color-file", Fw32_load_color_file
, Sw32_load_color_file
, 1, 1, 0,
1009 "Create an alist of color entries from an external file (ie. rgb.txt).\n\
1010 Assign this value to w32-color-map to replace the existing color map.\n\
1012 The file should define one named RGB color per line like so:\
1014 where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
1016 Lisp_Object filename
;
1019 Lisp_Object cmap
= Qnil
;
1020 Lisp_Object abspath
;
1022 CHECK_STRING (filename
, 0);
1023 abspath
= Fexpand_file_name (filename
, Qnil
);
1025 fp
= fopen (XSTRING (filename
)->data
, "rt");
1029 int red
, green
, blue
;
1034 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
1035 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
1037 char *name
= buf
+ num
;
1038 num
= strlen (name
) - 1;
1039 if (name
[num
] == '\n')
1041 cmap
= Fcons (Fcons (build_string (name
),
1042 make_number (RGB (red
, green
, blue
))),
1054 /* The default colors for the w32 color map */
1055 typedef struct colormap_t
1061 colormap_t w32_color_map
[] =
1063 {"snow" , PALETTERGB (255,250,250)},
1064 {"ghost white" , PALETTERGB (248,248,255)},
1065 {"GhostWhite" , PALETTERGB (248,248,255)},
1066 {"white smoke" , PALETTERGB (245,245,245)},
1067 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1068 {"gainsboro" , PALETTERGB (220,220,220)},
1069 {"floral white" , PALETTERGB (255,250,240)},
1070 {"FloralWhite" , PALETTERGB (255,250,240)},
1071 {"old lace" , PALETTERGB (253,245,230)},
1072 {"OldLace" , PALETTERGB (253,245,230)},
1073 {"linen" , PALETTERGB (250,240,230)},
1074 {"antique white" , PALETTERGB (250,235,215)},
1075 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1076 {"papaya whip" , PALETTERGB (255,239,213)},
1077 {"PapayaWhip" , PALETTERGB (255,239,213)},
1078 {"blanched almond" , PALETTERGB (255,235,205)},
1079 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1080 {"bisque" , PALETTERGB (255,228,196)},
1081 {"peach puff" , PALETTERGB (255,218,185)},
1082 {"PeachPuff" , PALETTERGB (255,218,185)},
1083 {"navajo white" , PALETTERGB (255,222,173)},
1084 {"NavajoWhite" , PALETTERGB (255,222,173)},
1085 {"moccasin" , PALETTERGB (255,228,181)},
1086 {"cornsilk" , PALETTERGB (255,248,220)},
1087 {"ivory" , PALETTERGB (255,255,240)},
1088 {"lemon chiffon" , PALETTERGB (255,250,205)},
1089 {"LemonChiffon" , PALETTERGB (255,250,205)},
1090 {"seashell" , PALETTERGB (255,245,238)},
1091 {"honeydew" , PALETTERGB (240,255,240)},
1092 {"mint cream" , PALETTERGB (245,255,250)},
1093 {"MintCream" , PALETTERGB (245,255,250)},
1094 {"azure" , PALETTERGB (240,255,255)},
1095 {"alice blue" , PALETTERGB (240,248,255)},
1096 {"AliceBlue" , PALETTERGB (240,248,255)},
1097 {"lavender" , PALETTERGB (230,230,250)},
1098 {"lavender blush" , PALETTERGB (255,240,245)},
1099 {"LavenderBlush" , PALETTERGB (255,240,245)},
1100 {"misty rose" , PALETTERGB (255,228,225)},
1101 {"MistyRose" , PALETTERGB (255,228,225)},
1102 {"white" , PALETTERGB (255,255,255)},
1103 {"black" , PALETTERGB ( 0, 0, 0)},
1104 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1105 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1106 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1107 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1108 {"dim gray" , PALETTERGB (105,105,105)},
1109 {"DimGray" , PALETTERGB (105,105,105)},
1110 {"dim grey" , PALETTERGB (105,105,105)},
1111 {"DimGrey" , PALETTERGB (105,105,105)},
1112 {"slate gray" , PALETTERGB (112,128,144)},
1113 {"SlateGray" , PALETTERGB (112,128,144)},
1114 {"slate grey" , PALETTERGB (112,128,144)},
1115 {"SlateGrey" , PALETTERGB (112,128,144)},
1116 {"light slate gray" , PALETTERGB (119,136,153)},
1117 {"LightSlateGray" , PALETTERGB (119,136,153)},
1118 {"light slate grey" , PALETTERGB (119,136,153)},
1119 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1120 {"gray" , PALETTERGB (190,190,190)},
1121 {"grey" , PALETTERGB (190,190,190)},
1122 {"light grey" , PALETTERGB (211,211,211)},
1123 {"LightGrey" , PALETTERGB (211,211,211)},
1124 {"light gray" , PALETTERGB (211,211,211)},
1125 {"LightGray" , PALETTERGB (211,211,211)},
1126 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1127 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1128 {"navy" , PALETTERGB ( 0, 0,128)},
1129 {"navy blue" , PALETTERGB ( 0, 0,128)},
1130 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1131 {"cornflower blue" , PALETTERGB (100,149,237)},
1132 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1133 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1134 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1135 {"slate blue" , PALETTERGB (106, 90,205)},
1136 {"SlateBlue" , PALETTERGB (106, 90,205)},
1137 {"medium slate blue" , PALETTERGB (123,104,238)},
1138 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1139 {"light slate blue" , PALETTERGB (132,112,255)},
1140 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1141 {"medium blue" , PALETTERGB ( 0, 0,205)},
1142 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1143 {"royal blue" , PALETTERGB ( 65,105,225)},
1144 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1145 {"blue" , PALETTERGB ( 0, 0,255)},
1146 {"dodger blue" , PALETTERGB ( 30,144,255)},
1147 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1148 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1149 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1150 {"sky blue" , PALETTERGB (135,206,235)},
1151 {"SkyBlue" , PALETTERGB (135,206,235)},
1152 {"light sky blue" , PALETTERGB (135,206,250)},
1153 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1154 {"steel blue" , PALETTERGB ( 70,130,180)},
1155 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1156 {"light steel blue" , PALETTERGB (176,196,222)},
1157 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1158 {"light blue" , PALETTERGB (173,216,230)},
1159 {"LightBlue" , PALETTERGB (173,216,230)},
1160 {"powder blue" , PALETTERGB (176,224,230)},
1161 {"PowderBlue" , PALETTERGB (176,224,230)},
1162 {"pale turquoise" , PALETTERGB (175,238,238)},
1163 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1164 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1165 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1166 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1167 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1168 {"turquoise" , PALETTERGB ( 64,224,208)},
1169 {"cyan" , PALETTERGB ( 0,255,255)},
1170 {"light cyan" , PALETTERGB (224,255,255)},
1171 {"LightCyan" , PALETTERGB (224,255,255)},
1172 {"cadet blue" , PALETTERGB ( 95,158,160)},
1173 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1174 {"medium aquamarine" , PALETTERGB (102,205,170)},
1175 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1176 {"aquamarine" , PALETTERGB (127,255,212)},
1177 {"dark green" , PALETTERGB ( 0,100, 0)},
1178 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1179 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1180 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1181 {"dark sea green" , PALETTERGB (143,188,143)},
1182 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1183 {"sea green" , PALETTERGB ( 46,139, 87)},
1184 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1185 {"medium sea green" , PALETTERGB ( 60,179,113)},
1186 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1187 {"light sea green" , PALETTERGB ( 32,178,170)},
1188 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1189 {"pale green" , PALETTERGB (152,251,152)},
1190 {"PaleGreen" , PALETTERGB (152,251,152)},
1191 {"spring green" , PALETTERGB ( 0,255,127)},
1192 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1193 {"lawn green" , PALETTERGB (124,252, 0)},
1194 {"LawnGreen" , PALETTERGB (124,252, 0)},
1195 {"green" , PALETTERGB ( 0,255, 0)},
1196 {"chartreuse" , PALETTERGB (127,255, 0)},
1197 {"medium spring green" , PALETTERGB ( 0,250,154)},
1198 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1199 {"green yellow" , PALETTERGB (173,255, 47)},
1200 {"GreenYellow" , PALETTERGB (173,255, 47)},
1201 {"lime green" , PALETTERGB ( 50,205, 50)},
1202 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1203 {"yellow green" , PALETTERGB (154,205, 50)},
1204 {"YellowGreen" , PALETTERGB (154,205, 50)},
1205 {"forest green" , PALETTERGB ( 34,139, 34)},
1206 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1207 {"olive drab" , PALETTERGB (107,142, 35)},
1208 {"OliveDrab" , PALETTERGB (107,142, 35)},
1209 {"dark khaki" , PALETTERGB (189,183,107)},
1210 {"DarkKhaki" , PALETTERGB (189,183,107)},
1211 {"khaki" , PALETTERGB (240,230,140)},
1212 {"pale goldenrod" , PALETTERGB (238,232,170)},
1213 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1214 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1215 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1216 {"light yellow" , PALETTERGB (255,255,224)},
1217 {"LightYellow" , PALETTERGB (255,255,224)},
1218 {"yellow" , PALETTERGB (255,255, 0)},
1219 {"gold" , PALETTERGB (255,215, 0)},
1220 {"light goldenrod" , PALETTERGB (238,221,130)},
1221 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1222 {"goldenrod" , PALETTERGB (218,165, 32)},
1223 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1224 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1225 {"rosy brown" , PALETTERGB (188,143,143)},
1226 {"RosyBrown" , PALETTERGB (188,143,143)},
1227 {"indian red" , PALETTERGB (205, 92, 92)},
1228 {"IndianRed" , PALETTERGB (205, 92, 92)},
1229 {"saddle brown" , PALETTERGB (139, 69, 19)},
1230 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1231 {"sienna" , PALETTERGB (160, 82, 45)},
1232 {"peru" , PALETTERGB (205,133, 63)},
1233 {"burlywood" , PALETTERGB (222,184,135)},
1234 {"beige" , PALETTERGB (245,245,220)},
1235 {"wheat" , PALETTERGB (245,222,179)},
1236 {"sandy brown" , PALETTERGB (244,164, 96)},
1237 {"SandyBrown" , PALETTERGB (244,164, 96)},
1238 {"tan" , PALETTERGB (210,180,140)},
1239 {"chocolate" , PALETTERGB (210,105, 30)},
1240 {"firebrick" , PALETTERGB (178,34, 34)},
1241 {"brown" , PALETTERGB (165,42, 42)},
1242 {"dark salmon" , PALETTERGB (233,150,122)},
1243 {"DarkSalmon" , PALETTERGB (233,150,122)},
1244 {"salmon" , PALETTERGB (250,128,114)},
1245 {"light salmon" , PALETTERGB (255,160,122)},
1246 {"LightSalmon" , PALETTERGB (255,160,122)},
1247 {"orange" , PALETTERGB (255,165, 0)},
1248 {"dark orange" , PALETTERGB (255,140, 0)},
1249 {"DarkOrange" , PALETTERGB (255,140, 0)},
1250 {"coral" , PALETTERGB (255,127, 80)},
1251 {"light coral" , PALETTERGB (240,128,128)},
1252 {"LightCoral" , PALETTERGB (240,128,128)},
1253 {"tomato" , PALETTERGB (255, 99, 71)},
1254 {"orange red" , PALETTERGB (255, 69, 0)},
1255 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1256 {"red" , PALETTERGB (255, 0, 0)},
1257 {"hot pink" , PALETTERGB (255,105,180)},
1258 {"HotPink" , PALETTERGB (255,105,180)},
1259 {"deep pink" , PALETTERGB (255, 20,147)},
1260 {"DeepPink" , PALETTERGB (255, 20,147)},
1261 {"pink" , PALETTERGB (255,192,203)},
1262 {"light pink" , PALETTERGB (255,182,193)},
1263 {"LightPink" , PALETTERGB (255,182,193)},
1264 {"pale violet red" , PALETTERGB (219,112,147)},
1265 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1266 {"maroon" , PALETTERGB (176, 48, 96)},
1267 {"medium violet red" , PALETTERGB (199, 21,133)},
1268 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1269 {"violet red" , PALETTERGB (208, 32,144)},
1270 {"VioletRed" , PALETTERGB (208, 32,144)},
1271 {"magenta" , PALETTERGB (255, 0,255)},
1272 {"violet" , PALETTERGB (238,130,238)},
1273 {"plum" , PALETTERGB (221,160,221)},
1274 {"orchid" , PALETTERGB (218,112,214)},
1275 {"medium orchid" , PALETTERGB (186, 85,211)},
1276 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1277 {"dark orchid" , PALETTERGB (153, 50,204)},
1278 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1279 {"dark violet" , PALETTERGB (148, 0,211)},
1280 {"DarkViolet" , PALETTERGB (148, 0,211)},
1281 {"blue violet" , PALETTERGB (138, 43,226)},
1282 {"BlueViolet" , PALETTERGB (138, 43,226)},
1283 {"purple" , PALETTERGB (160, 32,240)},
1284 {"medium purple" , PALETTERGB (147,112,219)},
1285 {"MediumPurple" , PALETTERGB (147,112,219)},
1286 {"thistle" , PALETTERGB (216,191,216)},
1287 {"gray0" , PALETTERGB ( 0, 0, 0)},
1288 {"grey0" , PALETTERGB ( 0, 0, 0)},
1289 {"dark grey" , PALETTERGB (169,169,169)},
1290 {"DarkGrey" , PALETTERGB (169,169,169)},
1291 {"dark gray" , PALETTERGB (169,169,169)},
1292 {"DarkGray" , PALETTERGB (169,169,169)},
1293 {"dark blue" , PALETTERGB ( 0, 0,139)},
1294 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1295 {"dark cyan" , PALETTERGB ( 0,139,139)},
1296 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1297 {"dark magenta" , PALETTERGB (139, 0,139)},
1298 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1299 {"dark red" , PALETTERGB (139, 0, 0)},
1300 {"DarkRed" , PALETTERGB (139, 0, 0)},
1301 {"light green" , PALETTERGB (144,238,144)},
1302 {"LightGreen" , PALETTERGB (144,238,144)},
1305 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
1306 0, 0, 0, "Return the default color map.")
1310 colormap_t
*pc
= w32_color_map
;
1317 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
1319 cmap
= Fcons (Fcons (build_string (pc
->name
),
1320 make_number (pc
->colorref
)),
1329 w32_to_x_color (rgb
)
1334 CHECK_NUMBER (rgb
, 0);
1338 color
= Frassq (rgb
, Vw32_color_map
);
1343 return (Fcar (color
));
1349 w32_color_map_lookup (colorname
)
1352 Lisp_Object tail
, ret
= Qnil
;
1356 for (tail
= Vw32_color_map
; !NILP (tail
); tail
= Fcdr (tail
))
1358 register Lisp_Object elt
, tem
;
1361 if (!CONSP (elt
)) continue;
1365 if (lstrcmpi (XSTRING (tem
)->data
, colorname
) == 0)
1367 ret
= XUINT (Fcdr (elt
));
1381 x_to_w32_color (colorname
)
1384 register Lisp_Object tail
, ret
= Qnil
;
1388 if (colorname
[0] == '#')
1390 /* Could be an old-style RGB Device specification. */
1393 color
= colorname
+ 1;
1395 size
= strlen(color
);
1396 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1404 for (i
= 0; i
< 3; i
++)
1408 unsigned long value
;
1410 /* The check for 'x' in the following conditional takes into
1411 account the fact that strtol allows a "0x" in front of
1412 our numbers, and we don't. */
1413 if (!isxdigit(color
[0]) || color
[1] == 'x')
1417 value
= strtoul(color
, &end
, 16);
1419 if (errno
== ERANGE
|| end
- color
!= size
)
1424 value
= value
* 0x10;
1435 colorval
|= (value
<< pos
);
1446 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1454 color
= colorname
+ 4;
1455 for (i
= 0; i
< 3; i
++)
1458 unsigned long value
;
1460 /* The check for 'x' in the following conditional takes into
1461 account the fact that strtol allows a "0x" in front of
1462 our numbers, and we don't. */
1463 if (!isxdigit(color
[0]) || color
[1] == 'x')
1465 value
= strtoul(color
, &end
, 16);
1466 if (errno
== ERANGE
)
1468 switch (end
- color
)
1471 value
= value
* 0x10 + value
;
1484 if (value
== ULONG_MAX
)
1486 colorval
|= (value
<< pos
);
1500 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1502 /* This is an RGB Intensity specification. */
1509 color
= colorname
+ 5;
1510 for (i
= 0; i
< 3; i
++)
1516 value
= strtod(color
, &end
);
1517 if (errno
== ERANGE
)
1519 if (value
< 0.0 || value
> 1.0)
1521 val
= (UINT
)(0x100 * value
);
1522 /* We used 0x100 instead of 0xFF to give an continuous
1523 range between 0.0 and 1.0 inclusive. The next statement
1524 fixes the 1.0 case. */
1527 colorval
|= (val
<< pos
);
1541 /* I am not going to attempt to handle any of the CIE color schemes
1542 or TekHVC, since I don't know the algorithms for conversion to
1545 /* If we fail to lookup the color name in w32_color_map, then check the
1546 colorname to see if it can be crudely approximated: If the X color
1547 ends in a number (e.g., "darkseagreen2"), strip the number and
1548 return the result of looking up the base color name. */
1549 ret
= w32_color_map_lookup (colorname
);
1552 int len
= strlen (colorname
);
1554 if (isdigit (colorname
[len
- 1]))
1556 char *ptr
, *approx
= alloca (len
);
1558 strcpy (approx
, colorname
);
1559 ptr
= &approx
[len
- 1];
1560 while (ptr
> approx
&& isdigit (*ptr
))
1563 ret
= w32_color_map_lookup (approx
);
1573 w32_regenerate_palette (FRAME_PTR f
)
1575 struct w32_palette_entry
* list
;
1576 LOGPALETTE
* log_palette
;
1577 HPALETTE new_palette
;
1580 /* don't bother trying to create palette if not supported */
1581 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1584 log_palette
= (LOGPALETTE
*)
1585 alloca (sizeof (LOGPALETTE
) +
1586 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1587 log_palette
->palVersion
= 0x300;
1588 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1590 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1592 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1593 i
++, list
= list
->next
)
1594 log_palette
->palPalEntry
[i
] = list
->entry
;
1596 new_palette
= CreatePalette (log_palette
);
1600 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1601 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1602 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1604 /* Realize display palette and garbage all frames. */
1605 release_frame_dc (f
, get_frame_dc (f
));
1610 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1611 #define SET_W32_COLOR(pe, color) \
1614 pe.peRed = GetRValue (color); \
1615 pe.peGreen = GetGValue (color); \
1616 pe.peBlue = GetBValue (color); \
1621 /* Keep these around in case we ever want to track color usage. */
1623 w32_map_color (FRAME_PTR f
, COLORREF color
)
1625 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1627 if (NILP (Vw32_enable_palette
))
1630 /* check if color is already mapped */
1633 if (W32_COLOR (list
->entry
) == color
)
1641 /* not already mapped, so add to list and recreate Windows palette */
1642 list
= (struct w32_palette_entry
*)
1643 xmalloc (sizeof (struct w32_palette_entry
));
1644 SET_W32_COLOR (list
->entry
, color
);
1646 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1647 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1648 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1650 /* set flag that palette must be regenerated */
1651 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1655 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1657 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1658 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1660 if (NILP (Vw32_enable_palette
))
1663 /* check if color is already mapped */
1666 if (W32_COLOR (list
->entry
) == color
)
1668 if (--list
->refcount
== 0)
1672 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1682 /* set flag that palette must be regenerated */
1683 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1687 /* Decide if color named COLOR is valid for the display associated with
1688 the selected frame; if so, return the rgb values in COLOR_DEF.
1689 If ALLOC is nonzero, allocate a new colormap cell. */
1692 defined_color (f
, color
, color_def
, alloc
)
1695 COLORREF
*color_def
;
1698 register Lisp_Object tem
;
1700 tem
= x_to_w32_color (color
);
1704 if (!NILP (Vw32_enable_palette
))
1706 struct w32_palette_entry
* entry
=
1707 FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1708 struct w32_palette_entry
** prev
=
1709 &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1711 /* check if color is already mapped */
1714 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1716 prev
= &entry
->next
;
1717 entry
= entry
->next
;
1720 if (entry
== NULL
&& alloc
)
1722 /* not already mapped, so add to list */
1723 entry
= (struct w32_palette_entry
*)
1724 xmalloc (sizeof (struct w32_palette_entry
));
1725 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1728 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1730 /* set flag that palette must be regenerated */
1731 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1734 /* Ensure COLORREF value is snapped to nearest color in (default)
1735 palette by simulating the PALETTERGB macro. This works whether
1736 or not the display device has a palette. */
1737 *color_def
= XUINT (tem
) | 0x2000000;
1746 /* Given a string ARG naming a color, compute a pixel value from it
1747 suitable for screen F.
1748 If F is not a color screen, return DEF (default) regardless of what
1752 x_decode_color (f
, arg
, def
)
1759 CHECK_STRING (arg
, 0);
1761 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1762 return BLACK_PIX_DEFAULT (f
);
1763 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1764 return WHITE_PIX_DEFAULT (f
);
1766 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1769 /* defined_color is responsible for coping with failures
1770 by looking for a near-miss. */
1771 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1774 /* defined_color failed; return an ultimate default. */
1778 /* Functions called only from `x_set_frame_param'
1779 to set individual parameters.
1781 If FRAME_W32_WINDOW (f) is 0,
1782 the frame is being created and its window does not exist yet.
1783 In that case, just record the parameter's new value
1784 in the standard place; do not attempt to change the window. */
1787 x_set_foreground_color (f
, arg
, oldval
)
1789 Lisp_Object arg
, oldval
;
1791 f
->output_data
.w32
->foreground_pixel
1792 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1794 if (FRAME_W32_WINDOW (f
) != 0)
1796 recompute_basic_faces (f
);
1797 if (FRAME_VISIBLE_P (f
))
1803 x_set_background_color (f
, arg
, oldval
)
1805 Lisp_Object arg
, oldval
;
1810 f
->output_data
.w32
->background_pixel
1811 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1813 if (FRAME_W32_WINDOW (f
) != 0)
1815 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
1817 recompute_basic_faces (f
);
1819 if (FRAME_VISIBLE_P (f
))
1825 x_set_mouse_color (f
, arg
, oldval
)
1827 Lisp_Object arg
, oldval
;
1830 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1835 if (!EQ (Qnil
, arg
))
1836 f
->output_data
.w32
->mouse_pixel
1837 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1838 mask_color
= f
->output_data
.w32
->background_pixel
;
1839 /* No invisible pointers. */
1840 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1841 && mask_color
== f
->output_data
.w32
->background_pixel
)
1842 f
->output_data
.w32
->mouse_pixel
= f
->output_data
.w32
->foreground_pixel
;
1847 /* It's not okay to crash if the user selects a screwy cursor. */
1848 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1850 if (!EQ (Qnil
, Vx_pointer_shape
))
1852 CHECK_NUMBER (Vx_pointer_shape
, 0);
1853 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1856 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1857 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1859 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1861 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1862 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1863 XINT (Vx_nontext_pointer_shape
));
1866 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1867 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1869 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1871 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1872 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1873 XINT (Vx_mode_pointer_shape
));
1876 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1877 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1879 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1881 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1883 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1884 XINT (Vx_sensitive_text_pointer_shape
));
1887 cross_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1889 /* Check and report errors with the above calls. */
1890 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1891 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1894 XColor fore_color
, back_color
;
1896 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1897 back_color
.pixel
= mask_color
;
1898 XQueryColor (FRAME_W32_DISPLAY (f
),
1899 DefaultColormap (FRAME_W32_DISPLAY (f
),
1900 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1902 XQueryColor (FRAME_W32_DISPLAY (f
),
1903 DefaultColormap (FRAME_W32_DISPLAY (f
),
1904 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1906 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1907 &fore_color
, &back_color
);
1908 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1909 &fore_color
, &back_color
);
1910 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1911 &fore_color
, &back_color
);
1912 XRecolorCursor (FRAME_W32_DISPLAY (f
), cross_cursor
,
1913 &fore_color
, &back_color
);
1916 if (FRAME_W32_WINDOW (f
) != 0)
1918 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1921 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1922 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1923 f
->output_data
.w32
->text_cursor
= cursor
;
1925 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1926 && f
->output_data
.w32
->nontext_cursor
!= 0)
1927 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1928 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1930 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1931 && f
->output_data
.w32
->modeline_cursor
!= 0)
1932 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1933 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1934 if (cross_cursor
!= f
->output_data
.w32
->cross_cursor
1935 && f
->output_data
.w32
->cross_cursor
!= 0)
1936 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->cross_cursor
);
1937 f
->output_data
.w32
->cross_cursor
= cross_cursor
;
1939 XFlush (FRAME_W32_DISPLAY (f
));
1945 x_set_cursor_color (f
, arg
, oldval
)
1947 Lisp_Object arg
, oldval
;
1949 unsigned long fore_pixel
;
1951 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1952 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1953 WHITE_PIX_DEFAULT (f
));
1955 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1956 f
->output_data
.w32
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1958 /* Make sure that the cursor color differs from the background color. */
1959 if (f
->output_data
.w32
->cursor_pixel
== f
->output_data
.w32
->background_pixel
)
1961 f
->output_data
.w32
->cursor_pixel
= f
->output_data
.w32
->mouse_pixel
;
1962 if (f
->output_data
.w32
->cursor_pixel
== fore_pixel
)
1963 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1965 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1967 if (FRAME_W32_WINDOW (f
) != 0)
1969 if (FRAME_VISIBLE_P (f
))
1971 x_display_cursor (f
, 0);
1972 x_display_cursor (f
, 1);
1977 /* Set the border-color of frame F to pixel value PIX.
1978 Note that this does not fully take effect if done before
1981 x_set_border_pixel (f
, pix
)
1985 f
->output_data
.w32
->border_pixel
= pix
;
1987 if (FRAME_W32_WINDOW (f
) != 0 && f
->output_data
.w32
->border_width
> 0)
1989 if (FRAME_VISIBLE_P (f
))
1994 /* Set the border-color of frame F to value described by ARG.
1995 ARG can be a string naming a color.
1996 The border-color is used for the border that is drawn by the server.
1997 Note that this does not fully take effect if done before
1998 F has a window; it must be redone when the window is created. */
2001 x_set_border_color (f
, arg
, oldval
)
2003 Lisp_Object arg
, oldval
;
2008 CHECK_STRING (arg
, 0);
2009 str
= XSTRING (arg
)->data
;
2011 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
2013 x_set_border_pixel (f
, pix
);
2017 x_set_cursor_type (f
, arg
, oldval
)
2019 Lisp_Object arg
, oldval
;
2023 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
2024 f
->output_data
.w32
->cursor_width
= 2;
2026 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
2027 && INTEGERP (XCONS (arg
)->cdr
))
2029 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
2030 f
->output_data
.w32
->cursor_width
= XINT (XCONS (arg
)->cdr
);
2033 /* Treat anything unknown as "box cursor".
2034 It was bad to signal an error; people have trouble fixing
2035 .Xdefaults with Emacs, when it has something bad in it. */
2036 FRAME_DESIRED_CURSOR (f
) = filled_box_cursor
;
2038 /* Make sure the cursor gets redrawn. This is overkill, but how
2039 often do people change cursor types? */
2040 update_mode_lines
++;
2044 x_set_icon_type (f
, arg
, oldval
)
2046 Lisp_Object arg
, oldval
;
2050 if (NILP (arg
) && NILP (oldval
))
2053 if (STRINGP (arg
) && STRINGP (oldval
)
2054 && EQ (Fstring_equal (oldval
, arg
), Qt
))
2057 if (SYMBOLP (arg
) && SYMBOLP (oldval
) && EQ (arg
, oldval
))
2062 result
= x_bitmap_icon (f
, arg
);
2066 error ("No icon window available");
2072 /* Return non-nil if frame F wants a bitmap icon. */
2080 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
2082 return XCONS (tem
)->cdr
;
2088 x_set_icon_name (f
, arg
, oldval
)
2090 Lisp_Object arg
, oldval
;
2097 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2100 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2106 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2111 result
= x_text_icon (f
,
2112 (char *) XSTRING ((!NILP (f
->icon_name
)
2121 error ("No icon window available");
2124 /* If the window was unmapped (and its icon was mapped),
2125 the new icon is not mapped, so map the window in its stead. */
2126 if (FRAME_VISIBLE_P (f
))
2128 #ifdef USE_X_TOOLKIT
2129 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2131 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2134 XFlush (FRAME_W32_DISPLAY (f
));
2139 extern Lisp_Object
x_new_font ();
2140 extern Lisp_Object
x_new_fontset();
2143 x_set_font (f
, arg
, oldval
)
2145 Lisp_Object arg
, oldval
;
2148 Lisp_Object fontset_name
;
2151 CHECK_STRING (arg
, 1);
2153 fontset_name
= Fquery_fontset (arg
, Qnil
);
2156 result
= (STRINGP (fontset_name
)
2157 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
2158 : x_new_font (f
, XSTRING (arg
)->data
));
2161 if (EQ (result
, Qnil
))
2162 error ("Font \"%s\" is not defined", XSTRING (arg
)->data
);
2163 else if (EQ (result
, Qt
))
2164 error ("the characters of the given font have varying widths");
2165 else if (STRINGP (result
))
2167 recompute_basic_faces (f
);
2168 store_frame_param (f
, Qfont
, result
);
2173 XSETFRAME (frame
, f
);
2174 call1 (Qface_set_after_frame_default
, frame
);
2178 x_set_border_width (f
, arg
, oldval
)
2180 Lisp_Object arg
, oldval
;
2182 CHECK_NUMBER (arg
, 0);
2184 if (XINT (arg
) == f
->output_data
.w32
->border_width
)
2187 if (FRAME_W32_WINDOW (f
) != 0)
2188 error ("Cannot change the border width of a window");
2190 f
->output_data
.w32
->border_width
= XINT (arg
);
2194 x_set_internal_border_width (f
, arg
, oldval
)
2196 Lisp_Object arg
, oldval
;
2199 int old
= f
->output_data
.w32
->internal_border_width
;
2201 CHECK_NUMBER (arg
, 0);
2202 f
->output_data
.w32
->internal_border_width
= XINT (arg
);
2203 if (f
->output_data
.w32
->internal_border_width
< 0)
2204 f
->output_data
.w32
->internal_border_width
= 0;
2206 if (f
->output_data
.w32
->internal_border_width
== old
)
2209 if (FRAME_W32_WINDOW (f
) != 0)
2212 x_set_window_size (f
, 0, f
->width
, f
->height
);
2214 SET_FRAME_GARBAGED (f
);
2219 x_set_visibility (f
, value
, oldval
)
2221 Lisp_Object value
, oldval
;
2224 XSETFRAME (frame
, f
);
2227 Fmake_frame_invisible (frame
, Qt
);
2228 else if (EQ (value
, Qicon
))
2229 Ficonify_frame (frame
);
2231 Fmake_frame_visible (frame
);
2235 x_set_menu_bar_lines (f
, value
, oldval
)
2237 Lisp_Object value
, oldval
;
2240 int olines
= FRAME_MENU_BAR_LINES (f
);
2242 /* Right now, menu bars don't work properly in minibuf-only frames;
2243 most of the commands try to apply themselves to the minibuffer
2244 frame itslef, and get an error because you can't switch buffers
2245 in or split the minibuffer window. */
2246 if (FRAME_MINIBUF_ONLY_P (f
))
2249 if (INTEGERP (value
))
2250 nlines
= XINT (value
);
2254 FRAME_MENU_BAR_LINES (f
) = 0;
2256 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2259 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2260 free_frame_menubar (f
);
2261 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2263 /* Adjust the frame size so that the client (text) dimensions
2264 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2266 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2270 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2273 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2274 name; if NAME is a string, set F's name to NAME and set
2275 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2277 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2278 suggesting a new name, which lisp code should override; if
2279 F->explicit_name is set, ignore the new name; otherwise, set it. */
2282 x_set_name (f
, name
, explicit)
2287 /* Make sure that requests from lisp code override requests from
2288 Emacs redisplay code. */
2291 /* If we're switching from explicit to implicit, we had better
2292 update the mode lines and thereby update the title. */
2293 if (f
->explicit_name
&& NILP (name
))
2294 update_mode_lines
= 1;
2296 f
->explicit_name
= ! NILP (name
);
2298 else if (f
->explicit_name
)
2301 /* If NAME is nil, set the name to the w32_id_name. */
2304 /* Check for no change needed in this very common case
2305 before we do any consing. */
2306 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
2307 XSTRING (f
->name
)->data
))
2309 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
2312 CHECK_STRING (name
, 0);
2314 /* Don't change the name if it's already NAME. */
2315 if (! NILP (Fstring_equal (name
, f
->name
)))
2320 /* For setting the frame title, the title parameter should override
2321 the name parameter. */
2322 if (! NILP (f
->title
))
2325 if (FRAME_W32_WINDOW (f
))
2328 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2333 /* This function should be called when the user's lisp code has
2334 specified a name for the frame; the name will override any set by the
2337 x_explicitly_set_name (f
, arg
, oldval
)
2339 Lisp_Object arg
, oldval
;
2341 x_set_name (f
, arg
, 1);
2344 /* This function should be called by Emacs redisplay code to set the
2345 name; names set this way will never override names set by the user's
2348 x_implicitly_set_name (f
, arg
, oldval
)
2350 Lisp_Object arg
, oldval
;
2352 x_set_name (f
, arg
, 0);
2355 /* Change the title of frame F to NAME.
2356 If NAME is nil, use the frame name as the title.
2358 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2359 name; if NAME is a string, set F's name to NAME and set
2360 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2362 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2363 suggesting a new name, which lisp code should override; if
2364 F->explicit_name is set, ignore the new name; otherwise, set it. */
2367 x_set_title (f
, name
)
2371 /* Don't change the title if it's already NAME. */
2372 if (EQ (name
, f
->title
))
2375 update_mode_lines
= 1;
2382 if (FRAME_W32_WINDOW (f
))
2385 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2391 x_set_autoraise (f
, arg
, oldval
)
2393 Lisp_Object arg
, oldval
;
2395 f
->auto_raise
= !EQ (Qnil
, arg
);
2399 x_set_autolower (f
, arg
, oldval
)
2401 Lisp_Object arg
, oldval
;
2403 f
->auto_lower
= !EQ (Qnil
, arg
);
2407 x_set_unsplittable (f
, arg
, oldval
)
2409 Lisp_Object arg
, oldval
;
2411 f
->no_split
= !NILP (arg
);
2415 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2417 Lisp_Object arg
, oldval
;
2419 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2420 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2421 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2422 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2424 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = NILP (arg
) ?
2425 vertical_scroll_bar_none
:
2426 /* Put scroll bars on the right by default, as is conventional
2429 ? vertical_scroll_bar_left
2430 : vertical_scroll_bar_right
;
2432 /* We set this parameter before creating the window for the
2433 frame, so we can get the geometry right from the start.
2434 However, if the window hasn't been created yet, we shouldn't
2435 call x_set_window_size. */
2436 if (FRAME_W32_WINDOW (f
))
2437 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2442 x_set_scroll_bar_width (f
, arg
, oldval
)
2444 Lisp_Object arg
, oldval
;
2448 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2449 FRAME_SCROLL_BAR_COLS (f
) = 2;
2451 else if (INTEGERP (arg
) && XINT (arg
) > 0
2452 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2454 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
2455 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2456 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2457 if (FRAME_W32_WINDOW (f
))
2458 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2462 /* Subroutines of creating an frame. */
2464 /* Make sure that Vx_resource_name is set to a reasonable value.
2465 Fix it up, or set it to `emacs' if it is too hopeless. */
2468 validate_x_resource_name ()
2471 /* Number of valid characters in the resource name. */
2473 /* Number of invalid characters in the resource name. */
2478 if (STRINGP (Vx_resource_name
))
2480 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2483 len
= XSTRING (Vx_resource_name
)->size
;
2485 /* Only letters, digits, - and _ are valid in resource names.
2486 Count the valid characters and count the invalid ones. */
2487 for (i
= 0; i
< len
; i
++)
2490 if (! ((c
>= 'a' && c
<= 'z')
2491 || (c
>= 'A' && c
<= 'Z')
2492 || (c
>= '0' && c
<= '9')
2493 || c
== '-' || c
== '_'))
2500 /* Not a string => completely invalid. */
2501 bad_count
= 5, good_count
= 0;
2503 /* If name is valid already, return. */
2507 /* If name is entirely invalid, or nearly so, use `emacs'. */
2509 || (good_count
== 1 && bad_count
> 0))
2511 Vx_resource_name
= build_string ("emacs");
2515 /* Name is partly valid. Copy it and replace the invalid characters
2516 with underscores. */
2518 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2520 for (i
= 0; i
< len
; i
++)
2522 int c
= XSTRING (new)->data
[i
];
2523 if (! ((c
>= 'a' && c
<= 'z')
2524 || (c
>= 'A' && c
<= 'Z')
2525 || (c
>= '0' && c
<= '9')
2526 || c
== '-' || c
== '_'))
2527 XSTRING (new)->data
[i
] = '_';
2532 extern char *x_get_string_resource ();
2534 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2535 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2536 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2537 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2538 the name specified by the `-name' or `-rn' command-line arguments.\n\
2540 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2541 class, respectively. You must specify both of them or neither.\n\
2542 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2543 and the class is `Emacs.CLASS.SUBCLASS'.")
2544 (attribute
, class, component
, subclass
)
2545 Lisp_Object attribute
, class, component
, subclass
;
2547 register char *value
;
2551 CHECK_STRING (attribute
, 0);
2552 CHECK_STRING (class, 0);
2554 if (!NILP (component
))
2555 CHECK_STRING (component
, 1);
2556 if (!NILP (subclass
))
2557 CHECK_STRING (subclass
, 2);
2558 if (NILP (component
) != NILP (subclass
))
2559 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2561 validate_x_resource_name ();
2563 /* Allocate space for the components, the dots which separate them,
2564 and the final '\0'. Make them big enough for the worst case. */
2565 name_key
= (char *) alloca (XSTRING (Vx_resource_name
)->size
2566 + (STRINGP (component
)
2567 ? XSTRING (component
)->size
: 0)
2568 + XSTRING (attribute
)->size
2571 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2572 + XSTRING (class)->size
2573 + (STRINGP (subclass
)
2574 ? XSTRING (subclass
)->size
: 0)
2577 /* Start with emacs.FRAMENAME for the name (the specific one)
2578 and with `Emacs' for the class key (the general one). */
2579 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2580 strcpy (class_key
, EMACS_CLASS
);
2582 strcat (class_key
, ".");
2583 strcat (class_key
, XSTRING (class)->data
);
2585 if (!NILP (component
))
2587 strcat (class_key
, ".");
2588 strcat (class_key
, XSTRING (subclass
)->data
);
2590 strcat (name_key
, ".");
2591 strcat (name_key
, XSTRING (component
)->data
);
2594 strcat (name_key
, ".");
2595 strcat (name_key
, XSTRING (attribute
)->data
);
2597 value
= x_get_string_resource (Qnil
,
2598 name_key
, class_key
);
2600 if (value
!= (char *) 0)
2601 return build_string (value
);
2606 /* Used when C code wants a resource value. */
2609 x_get_resource_string (attribute
, class)
2610 char *attribute
, *class;
2612 register char *value
;
2616 /* Allocate space for the components, the dots which separate them,
2617 and the final '\0'. */
2618 name_key
= (char *) alloca (XSTRING (Vinvocation_name
)->size
2619 + strlen (attribute
) + 2);
2620 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2621 + strlen (class) + 2);
2623 sprintf (name_key
, "%s.%s",
2624 XSTRING (Vinvocation_name
)->data
,
2626 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2628 return x_get_string_resource (selected_frame
,
2629 name_key
, class_key
);
2632 /* Types we might convert a resource string into. */
2635 number
, boolean
, string
, symbol
2638 /* Return the value of parameter PARAM.
2640 First search ALIST, then Vdefault_frame_alist, then the X defaults
2641 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2643 Convert the resource to the type specified by desired_type.
2645 If no default is specified, return Qunbound. If you call
2646 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2647 and don't let it get stored in any Lisp-visible variables! */
2650 x_get_arg (alist
, param
, attribute
, class, type
)
2651 Lisp_Object alist
, param
;
2654 enum resource_types type
;
2656 register Lisp_Object tem
;
2658 tem
= Fassq (param
, alist
);
2660 tem
= Fassq (param
, Vdefault_frame_alist
);
2666 tem
= Fx_get_resource (build_string (attribute
),
2667 build_string (class),
2676 return make_number (atoi (XSTRING (tem
)->data
));
2679 tem
= Fdowncase (tem
);
2680 if (!strcmp (XSTRING (tem
)->data
, "on")
2681 || !strcmp (XSTRING (tem
)->data
, "true"))
2690 /* As a special case, we map the values `true' and `on'
2691 to Qt, and `false' and `off' to Qnil. */
2694 lower
= Fdowncase (tem
);
2695 if (!strcmp (XSTRING (lower
)->data
, "on")
2696 || !strcmp (XSTRING (lower
)->data
, "true"))
2698 else if (!strcmp (XSTRING (lower
)->data
, "off")
2699 || !strcmp (XSTRING (lower
)->data
, "false"))
2702 return Fintern (tem
, Qnil
);
2715 /* Record in frame F the specified or default value according to ALIST
2716 of the parameter named PARAM (a Lisp symbol).
2717 If no value is specified for PARAM, look for an X default for XPROP
2718 on the frame named NAME.
2719 If that is not found either, use the value DEFLT. */
2722 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2729 enum resource_types type
;
2733 tem
= x_get_arg (alist
, prop
, xprop
, xclass
, type
);
2734 if (EQ (tem
, Qunbound
))
2736 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2740 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2741 "Parse an X-style geometry string STRING.\n\
2742 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2743 The properties returned may include `top', `left', `height', and `width'.\n\
2744 The value of `left' or `top' may be an integer,\n\
2745 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2746 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2751 unsigned int width
, height
;
2754 CHECK_STRING (string
, 0);
2756 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2757 &x
, &y
, &width
, &height
);
2760 if (geometry
& XValue
)
2762 Lisp_Object element
;
2764 if (x
>= 0 && (geometry
& XNegative
))
2765 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2766 else if (x
< 0 && ! (geometry
& XNegative
))
2767 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2769 element
= Fcons (Qleft
, make_number (x
));
2770 result
= Fcons (element
, result
);
2773 if (geometry
& YValue
)
2775 Lisp_Object element
;
2777 if (y
>= 0 && (geometry
& YNegative
))
2778 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2779 else if (y
< 0 && ! (geometry
& YNegative
))
2780 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2782 element
= Fcons (Qtop
, make_number (y
));
2783 result
= Fcons (element
, result
);
2786 if (geometry
& WidthValue
)
2787 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2788 if (geometry
& HeightValue
)
2789 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2794 /* Calculate the desired size and position of this window,
2795 and return the flags saying which aspects were specified.
2797 This function does not make the coordinates positive. */
2799 #define DEFAULT_ROWS 40
2800 #define DEFAULT_COLS 80
2803 x_figure_window_size (f
, parms
)
2807 register Lisp_Object tem0
, tem1
, tem2
;
2808 int height
, width
, left
, top
;
2809 register int geometry
;
2810 long window_prompting
= 0;
2812 /* Default values if we fall through.
2813 Actually, if that happens we should get
2814 window manager prompting. */
2815 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2816 f
->height
= DEFAULT_ROWS
;
2817 /* Window managers expect that if program-specified
2818 positions are not (0,0), they're intentional, not defaults. */
2819 f
->output_data
.w32
->top_pos
= 0;
2820 f
->output_data
.w32
->left_pos
= 0;
2822 tem0
= x_get_arg (parms
, Qheight
, 0, 0, number
);
2823 tem1
= x_get_arg (parms
, Qwidth
, 0, 0, number
);
2824 tem2
= x_get_arg (parms
, Quser_size
, 0, 0, number
);
2825 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2827 if (!EQ (tem0
, Qunbound
))
2829 CHECK_NUMBER (tem0
, 0);
2830 f
->height
= XINT (tem0
);
2832 if (!EQ (tem1
, Qunbound
))
2834 CHECK_NUMBER (tem1
, 0);
2835 SET_FRAME_WIDTH (f
, XINT (tem1
));
2837 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2838 window_prompting
|= USSize
;
2840 window_prompting
|= PSize
;
2843 f
->output_data
.w32
->vertical_scroll_bar_extra
2844 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2846 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2847 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2848 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2849 f
->output_data
.w32
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2850 f
->output_data
.w32
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2852 tem0
= x_get_arg (parms
, Qtop
, 0, 0, number
);
2853 tem1
= x_get_arg (parms
, Qleft
, 0, 0, number
);
2854 tem2
= x_get_arg (parms
, Quser_position
, 0, 0, number
);
2855 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2857 if (EQ (tem0
, Qminus
))
2859 f
->output_data
.w32
->top_pos
= 0;
2860 window_prompting
|= YNegative
;
2862 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2863 && CONSP (XCONS (tem0
)->cdr
)
2864 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2866 f
->output_data
.w32
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2867 window_prompting
|= YNegative
;
2869 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2870 && CONSP (XCONS (tem0
)->cdr
)
2871 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2873 f
->output_data
.w32
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2875 else if (EQ (tem0
, Qunbound
))
2876 f
->output_data
.w32
->top_pos
= 0;
2879 CHECK_NUMBER (tem0
, 0);
2880 f
->output_data
.w32
->top_pos
= XINT (tem0
);
2881 if (f
->output_data
.w32
->top_pos
< 0)
2882 window_prompting
|= YNegative
;
2885 if (EQ (tem1
, Qminus
))
2887 f
->output_data
.w32
->left_pos
= 0;
2888 window_prompting
|= XNegative
;
2890 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2891 && CONSP (XCONS (tem1
)->cdr
)
2892 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2894 f
->output_data
.w32
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2895 window_prompting
|= XNegative
;
2897 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2898 && CONSP (XCONS (tem1
)->cdr
)
2899 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2901 f
->output_data
.w32
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2903 else if (EQ (tem1
, Qunbound
))
2904 f
->output_data
.w32
->left_pos
= 0;
2907 CHECK_NUMBER (tem1
, 0);
2908 f
->output_data
.w32
->left_pos
= XINT (tem1
);
2909 if (f
->output_data
.w32
->left_pos
< 0)
2910 window_prompting
|= XNegative
;
2913 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2914 window_prompting
|= USPosition
;
2916 window_prompting
|= PPosition
;
2919 return window_prompting
;
2924 extern LRESULT CALLBACK
w32_wnd_proc ();
2927 w32_init_class (hinst
)
2932 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2933 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
2935 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
2936 wc
.hInstance
= hinst
;
2937 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
2938 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
2939 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
2940 wc
.lpszMenuName
= NULL
;
2941 wc
.lpszClassName
= EMACS_CLASS
;
2943 return (RegisterClass (&wc
));
2947 w32_createscrollbar (f
, bar
)
2949 struct scroll_bar
* bar
;
2951 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
2952 /* Position and size of scroll bar. */
2953 XINT(bar
->left
), XINT(bar
->top
),
2954 XINT(bar
->width
), XINT(bar
->height
),
2955 FRAME_W32_WINDOW (f
),
2962 w32_createwindow (f
)
2968 rect
.left
= rect
.top
= 0;
2969 rect
.right
= PIXEL_WIDTH (f
);
2970 rect
.bottom
= PIXEL_HEIGHT (f
);
2972 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2973 FRAME_EXTERNAL_MENU_BAR (f
));
2975 /* Do first time app init */
2979 w32_init_class (hinst
);
2982 FRAME_W32_WINDOW (f
) = hwnd
2983 = CreateWindow (EMACS_CLASS
,
2985 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2986 f
->output_data
.w32
->left_pos
,
2987 f
->output_data
.w32
->top_pos
,
2988 rect
.right
- rect
.left
,
2989 rect
.bottom
- rect
.top
,
2997 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
2998 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
2999 SetWindowLong (hwnd
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
3000 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
3001 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
3003 /* Enable drag-n-drop. */
3004 DragAcceptFiles (hwnd
, TRUE
);
3006 /* Do this to discard the default setting specified by our parent. */
3007 ShowWindow (hwnd
, SW_HIDE
);
3012 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
3019 wmsg
->msg
.hwnd
= hwnd
;
3020 wmsg
->msg
.message
= msg
;
3021 wmsg
->msg
.wParam
= wParam
;
3022 wmsg
->msg
.lParam
= lParam
;
3023 wmsg
->msg
.time
= GetMessageTime ();
3028 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3029 between left and right keys as advertised. We test for this
3030 support dynamically, and set a flag when the support is absent. If
3031 absent, we keep track of the left and right control and alt keys
3032 ourselves. This is particularly necessary on keyboards that rely
3033 upon the AltGr key, which is represented as having the left control
3034 and right alt keys pressed. For these keyboards, we need to know
3035 when the left alt key has been pressed in addition to the AltGr key
3036 so that we can properly support M-AltGr-key sequences (such as M-@
3037 on Swedish keyboards). */
3039 #define EMACS_LCONTROL 0
3040 #define EMACS_RCONTROL 1
3041 #define EMACS_LMENU 2
3042 #define EMACS_RMENU 3
3044 static int modifiers
[4];
3045 static int modifiers_recorded
;
3046 static int modifier_key_support_tested
;
3049 test_modifier_support (unsigned int wparam
)
3053 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
3055 if (wparam
== VK_CONTROL
)
3065 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
3066 modifiers_recorded
= 1;
3068 modifiers_recorded
= 0;
3069 modifier_key_support_tested
= 1;
3073 record_keydown (unsigned int wparam
, unsigned int lparam
)
3077 if (!modifier_key_support_tested
)
3078 test_modifier_support (wparam
);
3080 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3083 if (wparam
== VK_CONTROL
)
3084 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3086 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3092 record_keyup (unsigned int wparam
, unsigned int lparam
)
3096 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3099 if (wparam
== VK_CONTROL
)
3100 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3102 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3107 /* Emacs can lose focus while a modifier key has been pressed. When
3108 it regains focus, be conservative and clear all modifiers since
3109 we cannot reconstruct the left and right modifier state. */
3115 if (GetFocus () == NULL
)
3116 /* Emacs doesn't have keyboard focus. Do nothing. */
3119 ctrl
= GetAsyncKeyState (VK_CONTROL
);
3120 alt
= GetAsyncKeyState (VK_MENU
);
3122 if (!(ctrl
& 0x08000))
3123 /* Clear any recorded control modifier state. */
3124 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3126 if (!(alt
& 0x08000))
3127 /* Clear any recorded alt modifier state. */
3128 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3130 /* Update the state of all modifier keys, because modifiers used in
3131 hot-key combinations can get stuck on if Emacs loses focus as a
3132 result of a hot-key being pressed. */
3136 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3138 GetKeyboardState (keystate
);
3139 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
3140 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
3141 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
3142 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
3143 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
3144 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
3145 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
3146 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
3147 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
3148 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
3149 SetKeyboardState (keystate
);
3153 /* Synchronize modifier state with what is reported with the current
3154 keystroke. Even if we cannot distinguish between left and right
3155 modifier keys, we know that, if no modifiers are set, then neither
3156 the left or right modifier should be set. */
3160 if (!modifiers_recorded
)
3163 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
3164 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3166 if (!(GetKeyState (VK_MENU
) & 0x8000))
3167 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3171 modifier_set (int vkey
)
3173 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
3174 return (GetKeyState (vkey
) & 0x1);
3175 if (!modifiers_recorded
)
3176 return (GetKeyState (vkey
) & 0x8000);
3181 return modifiers
[EMACS_LCONTROL
];
3183 return modifiers
[EMACS_RCONTROL
];
3185 return modifiers
[EMACS_LMENU
];
3187 return modifiers
[EMACS_RMENU
];
3189 return (GetKeyState (vkey
) & 0x8000);
3192 /* Convert between the modifier bits W32 uses and the modifier bits
3196 w32_key_to_modifier (int key
)
3198 Lisp_Object key_mapping
;
3203 key_mapping
= Vw32_lwindow_modifier
;
3206 key_mapping
= Vw32_rwindow_modifier
;
3209 key_mapping
= Vw32_apps_modifier
;
3212 key_mapping
= Vw32_scroll_lock_modifier
;
3218 /* NB. This code runs in the input thread, asychronously to the lisp
3219 thread, so we must be careful to ensure access to lisp data is
3220 thread-safe. The following code is safe because the modifier
3221 variable values are updated atomically from lisp and symbols are
3222 not relocated by GC. Also, we don't have to worry about seeing GC
3224 if (EQ (key_mapping
, Qhyper
))
3225 return hyper_modifier
;
3226 if (EQ (key_mapping
, Qsuper
))
3227 return super_modifier
;
3228 if (EQ (key_mapping
, Qmeta
))
3229 return meta_modifier
;
3230 if (EQ (key_mapping
, Qalt
))
3231 return alt_modifier
;
3232 if (EQ (key_mapping
, Qctrl
))
3233 return ctrl_modifier
;
3234 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
3235 return ctrl_modifier
;
3236 if (EQ (key_mapping
, Qshift
))
3237 return shift_modifier
;
3239 /* Don't generate any modifier if not explicitly requested. */
3244 w32_get_modifiers ()
3246 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
3247 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
3248 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
3249 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
3250 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
3251 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
3252 (modifier_set (VK_MENU
) ?
3253 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
3256 /* We map the VK_* modifiers into console modifier constants
3257 so that we can use the same routines to handle both console
3258 and window input. */
3261 construct_console_modifiers ()
3266 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
3267 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
3268 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
3269 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
3270 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
3271 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
3272 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
3273 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
3274 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
3275 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
3276 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
3282 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
3286 /* Convert to emacs modifiers. */
3287 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
3293 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
3295 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
3298 if (virt_key
== VK_RETURN
)
3299 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
3301 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
3302 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
3304 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
3305 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
3307 if (virt_key
== VK_CLEAR
)
3308 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
3313 /* List of special key combinations which w32 would normally capture,
3314 but emacs should grab instead. Not directly visible to lisp, to
3315 simplify synchronization. Each item is an integer encoding a virtual
3316 key code and modifier combination to capture. */
3317 Lisp_Object w32_grabbed_keys
;
3319 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3320 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3321 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3322 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3324 /* Register hot-keys for reserved key combinations when Emacs has
3325 keyboard focus, since this is the only way Emacs can receive key
3326 combinations like Alt-Tab which are used by the system. */
3329 register_hot_keys (hwnd
)
3332 Lisp_Object keylist
;
3334 /* Use GC_CONSP, since we are called asynchronously. */
3335 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3337 Lisp_Object key
= XCAR (keylist
);
3339 /* Deleted entries get set to nil. */
3340 if (!INTEGERP (key
))
3343 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
3344 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
3349 unregister_hot_keys (hwnd
)
3352 Lisp_Object keylist
;
3354 /* Use GC_CONSP, since we are called asynchronously. */
3355 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3357 Lisp_Object key
= XCAR (keylist
);
3359 if (!INTEGERP (key
))
3362 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
3366 /* Main message dispatch loop. */
3369 w32_msg_pump (deferred_msg
* msg_buf
)
3375 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
3377 while (GetMessage (&msg
, NULL
, 0, 0))
3379 if (msg
.hwnd
== NULL
)
3381 switch (msg
.message
)
3384 /* Produced by complete_deferred_msg; just ignore. */
3386 case WM_EMACS_CREATEWINDOW
:
3387 w32_createwindow ((struct frame
*) msg
.wParam
);
3388 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3391 case WM_EMACS_SETLOCALE
:
3392 SetThreadLocale (msg
.wParam
);
3393 /* Reply is not expected. */
3395 case WM_EMACS_SETKEYBOARDLAYOUT
:
3396 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
3397 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3401 case WM_EMACS_REGISTER_HOT_KEY
:
3402 focus_window
= GetFocus ();
3403 if (focus_window
!= NULL
)
3404 RegisterHotKey (focus_window
,
3405 HOTKEY_ID (msg
.wParam
),
3406 HOTKEY_MODIFIERS (msg
.wParam
),
3407 HOTKEY_VK_CODE (msg
.wParam
));
3408 /* Reply is not expected. */
3410 case WM_EMACS_UNREGISTER_HOT_KEY
:
3411 focus_window
= GetFocus ();
3412 if (focus_window
!= NULL
)
3413 UnregisterHotKey (focus_window
, HOTKEY_ID (msg
.wParam
));
3414 /* Mark item as erased. NB: this code must be
3415 thread-safe. The next line is okay because the cons
3416 cell is never made into garbage and is not relocated by
3418 XCAR ((Lisp_Object
) msg
.lParam
) = Qnil
;
3419 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3422 case WM_EMACS_TOGGLE_LOCK_KEY
:
3424 int vk_code
= (int) msg
.wParam
;
3425 int cur_state
= (GetKeyState (vk_code
) & 1);
3426 Lisp_Object new_state
= (Lisp_Object
) msg
.lParam
;
3428 /* NB: This code must be thread-safe. It is safe to
3429 call NILP because symbols are not relocated by GC,
3430 and pointer here is not touched by GC (so the markbit
3431 can't be set). Numbers are safe because they are
3432 immediate values. */
3433 if (NILP (new_state
)
3434 || (NUMBERP (new_state
)
3435 && (XUINT (new_state
)) & 1 != cur_state
))
3437 one_w32_display_info
.faked_key
= vk_code
;
3439 keybd_event ((BYTE
) vk_code
,
3440 (BYTE
) MapVirtualKey (vk_code
, 0),
3441 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3442 keybd_event ((BYTE
) vk_code
,
3443 (BYTE
) MapVirtualKey (vk_code
, 0),
3444 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3445 keybd_event ((BYTE
) vk_code
,
3446 (BYTE
) MapVirtualKey (vk_code
, 0),
3447 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3448 cur_state
= !cur_state
;
3450 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3456 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
3461 DispatchMessage (&msg
);
3464 /* Exit nested loop when our deferred message has completed. */
3465 if (msg_buf
->completed
)
3470 deferred_msg
* deferred_msg_head
;
3472 static deferred_msg
*
3473 find_deferred_msg (HWND hwnd
, UINT msg
)
3475 deferred_msg
* item
;
3477 /* Don't actually need synchronization for read access, since
3478 modification of single pointer is always atomic. */
3479 /* enter_crit (); */
3481 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3482 if (item
->w32msg
.msg
.hwnd
== hwnd
3483 && item
->w32msg
.msg
.message
== msg
)
3486 /* leave_crit (); */
3492 send_deferred_msg (deferred_msg
* msg_buf
,
3498 /* Only input thread can send deferred messages. */
3499 if (GetCurrentThreadId () != dwWindowsThreadId
)
3502 /* It is an error to send a message that is already deferred. */
3503 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3506 /* Enforced synchronization is not needed because this is the only
3507 function that alters deferred_msg_head, and the following critical
3508 section is guaranteed to only be serially reentered (since only the
3509 input thread can call us). */
3511 /* enter_crit (); */
3513 msg_buf
->completed
= 0;
3514 msg_buf
->next
= deferred_msg_head
;
3515 deferred_msg_head
= msg_buf
;
3516 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
3518 /* leave_crit (); */
3520 /* Start a new nested message loop to process other messages until
3521 this one is completed. */
3522 w32_msg_pump (msg_buf
);
3524 deferred_msg_head
= msg_buf
->next
;
3526 return msg_buf
->result
;
3530 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
3532 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
3534 if (msg_buf
== NULL
)
3535 /* Message may have been cancelled, so don't abort(). */
3538 msg_buf
->result
= result
;
3539 msg_buf
->completed
= 1;
3541 /* Ensure input thread is woken so it notices the completion. */
3542 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3546 cancel_all_deferred_msgs ()
3548 deferred_msg
* item
;
3550 /* Don't actually need synchronization for read access, since
3551 modification of single pointer is always atomic. */
3552 /* enter_crit (); */
3554 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3557 item
->completed
= 1;
3560 /* leave_crit (); */
3562 /* Ensure input thread is woken so it notices the completion. */
3563 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3571 deferred_msg dummy_buf
;
3573 /* Ensure our message queue is created */
3575 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3577 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3580 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
3581 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
3582 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
3584 /* This is the inital message loop which should only exit when the
3585 application quits. */
3586 w32_msg_pump (&dummy_buf
);
3592 post_character_message (hwnd
, msg
, wParam
, lParam
, modifiers
)
3602 wmsg
.dwModifiers
= modifiers
;
3604 /* Detect quit_char and set quit-flag directly. Note that we
3605 still need to post a message to ensure the main thread will be
3606 woken up if blocked in sys_select(), but we do NOT want to post
3607 the quit_char message itself (because it will usually be as if
3608 the user had typed quit_char twice). Instead, we post a dummy
3609 message that has no particular effect. */
3612 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
3613 c
= make_ctrl_char (c
) & 0377;
3615 || (wmsg
.dwModifiers
== 0 &&
3616 XFASTINT (Vw32_quit_key
) && wParam
== XFASTINT (Vw32_quit_key
)))
3620 /* The choice of message is somewhat arbitrary, as long as
3621 the main thread handler just ignores it. */
3624 /* Interrupt any blocking system calls. */
3627 /* As a safety precaution, forcibly complete any deferred
3628 messages. This is a kludge, but I don't see any particularly
3629 clean way to handle the situation where a deferred message is
3630 "dropped" in the lisp thread, and will thus never be
3631 completed, eg. by the user trying to activate the menubar
3632 when the lisp thread is busy, and then typing C-g when the
3633 menubar doesn't open promptly (with the result that the
3634 menubar never responds at all because the deferred
3635 WM_INITMENU message is never completed). Another problem
3636 situation is when the lisp thread calls SendMessage (to send
3637 a window manager command) when a message has been deferred;
3638 the lisp thread gets blocked indefinitely waiting for the
3639 deferred message to be completed, which itself is waiting for
3640 the lisp thread to respond.
3642 Note that we don't want to block the input thread waiting for
3643 a reponse from the lisp thread (although that would at least
3644 solve the deadlock problem above), because we want to be able
3645 to receive C-g to interrupt the lisp thread. */
3646 cancel_all_deferred_msgs ();
3650 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3653 /* Main window procedure */
3656 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
3663 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3665 int windows_translate
;
3668 /* Note that it is okay to call x_window_to_frame, even though we are
3669 not running in the main lisp thread, because frame deletion
3670 requires the lisp thread to synchronize with this thread. Thus, if
3671 a frame struct is returned, it can be used without concern that the
3672 lisp thread might make it disappear while we are using it.
3674 NB. Walking the frame list in this thread is safe (as long as
3675 writes of Lisp_Object slots are atomic, which they are on Windows).
3676 Although delete-frame can destructively modify the frame list while
3677 we are walking it, a garbage collection cannot occur until after
3678 delete-frame has synchronized with this thread.
3680 It is also safe to use functions that make GDI calls, such as
3681 w32_clear_rect, because these functions must obtain a DC handle
3682 from the frame struct using get_frame_dc which is thread-aware. */
3687 f
= x_window_to_frame (dpyinfo
, hwnd
);
3690 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
3691 w32_clear_rect (f
, NULL
, &wmsg
.rect
);
3693 #if defined (W32_DEBUG_DISPLAY)
3694 DebPrint (("WM_ERASEBKGND: erasing %d,%d-%d,%d\n",
3695 wmsg
.rect
.left
, wmsg
.rect
.top
, wmsg
.rect
.right
,
3697 #endif /* W32_DEBUG_DISPLAY */
3700 case WM_PALETTECHANGED
:
3701 /* ignore our own changes */
3702 if ((HWND
)wParam
!= hwnd
)
3704 f
= x_window_to_frame (dpyinfo
, hwnd
);
3706 /* get_frame_dc will realize our palette and force all
3707 frames to be redrawn if needed. */
3708 release_frame_dc (f
, get_frame_dc (f
));
3713 PAINTSTRUCT paintStruct
;
3716 /* MSDN Docs say not to call BeginPaint if GetUpdateRect
3717 fails. Apparently this can happen under some
3719 if (!w32_strict_painting
|| GetUpdateRect (hwnd
, &update_rect
, FALSE
))
3722 BeginPaint (hwnd
, &paintStruct
);
3724 if (w32_strict_painting
)
3725 /* The rectangles returned by GetUpdateRect and BeginPaint
3726 do not always match. GetUpdateRect seems to be the
3727 more reliable of the two. */
3728 wmsg
.rect
= update_rect
;
3730 wmsg
.rect
= paintStruct
.rcPaint
;
3732 #if defined (W32_DEBUG_DISPLAY)
3733 DebPrint (("WM_PAINT: painting %d,%d-%d,%d\n", wmsg
.rect
.left
,
3734 wmsg
.rect
.top
, wmsg
.rect
.right
, wmsg
.rect
.bottom
));
3735 DebPrint (("WM_PAINT: update region is %d,%d-%d,%d\n",
3736 update_rect
.left
, update_rect
.top
,
3737 update_rect
.right
, update_rect
.bottom
));
3739 EndPaint (hwnd
, &paintStruct
);
3742 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3747 /* If GetUpdateRect returns 0 (meaning there is no update
3748 region), assume the whole window needs to be repainted. */
3749 GetClientRect(hwnd
, &wmsg
.rect
);
3750 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3754 case WM_INPUTLANGCHANGE
:
3755 /* Inform lisp thread of keyboard layout changes. */
3756 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3758 /* Clear dead keys in the keyboard state; for simplicity only
3759 preserve modifier key states. */
3764 GetKeyboardState (keystate
);
3765 for (i
= 0; i
< 256; i
++)
3782 SetKeyboardState (keystate
);
3787 /* Synchronize hot keys with normal input. */
3788 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
3793 record_keyup (wParam
, lParam
);
3798 /* Ignore keystrokes we fake ourself; see below. */
3799 if (dpyinfo
->faked_key
== wParam
)
3801 dpyinfo
->faked_key
= 0;
3802 /* Make sure TranslateMessage sees them though (as long as
3803 they don't produce WM_CHAR messages). This ensures that
3804 indicator lights are toggled promptly on Windows 9x, for
3806 if (lispy_function_keys
[wParam
] != 0)
3808 windows_translate
= 1;
3814 /* Synchronize modifiers with current keystroke. */
3816 record_keydown (wParam
, lParam
);
3817 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
3819 windows_translate
= 0;
3824 if (NILP (Vw32_pass_lwindow_to_system
))
3826 /* Prevent system from acting on keyup (which opens the
3827 Start menu if no other key was pressed) by simulating a
3828 press of Space which we will ignore. */
3829 if (GetAsyncKeyState (wParam
) & 1)
3831 if (NUMBERP (Vw32_phantom_key_code
))
3832 key
= XUINT (Vw32_phantom_key_code
) & 255;
3835 dpyinfo
->faked_key
= key
;
3836 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3839 if (!NILP (Vw32_lwindow_modifier
))
3843 if (NILP (Vw32_pass_rwindow_to_system
))
3845 if (GetAsyncKeyState (wParam
) & 1)
3847 if (NUMBERP (Vw32_phantom_key_code
))
3848 key
= XUINT (Vw32_phantom_key_code
) & 255;
3851 dpyinfo
->faked_key
= key
;
3852 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3855 if (!NILP (Vw32_rwindow_modifier
))
3859 if (!NILP (Vw32_apps_modifier
))
3863 if (NILP (Vw32_pass_alt_to_system
))
3864 /* Prevent DefWindowProc from activating the menu bar if an
3865 Alt key is pressed and released by itself. */
3867 windows_translate
= 1;
3870 /* Decide whether to treat as modifier or function key. */
3871 if (NILP (Vw32_enable_caps_lock
))
3872 goto disable_lock_key
;
3873 windows_translate
= 1;
3876 /* Decide whether to treat as modifier or function key. */
3877 if (NILP (Vw32_enable_num_lock
))
3878 goto disable_lock_key
;
3879 windows_translate
= 1;
3882 /* Decide whether to treat as modifier or function key. */
3883 if (NILP (Vw32_scroll_lock_modifier
))
3884 goto disable_lock_key
;
3885 windows_translate
= 1;
3888 /* Ensure the appropriate lock key state (and indicator light)
3889 remains in the same state. We do this by faking another
3890 press of the relevant key. Apparently, this really is the
3891 only way to toggle the state of the indicator lights. */
3892 dpyinfo
->faked_key
= wParam
;
3893 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3894 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3895 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3896 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3897 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3898 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3899 /* Ensure indicator lights are updated promptly on Windows 9x
3900 (TranslateMessage apparently does this), after forwarding
3902 post_character_message (hwnd
, msg
, wParam
, lParam
,
3903 w32_get_key_modifiers (wParam
, lParam
));
3904 windows_translate
= 1;
3908 case VK_PROCESSKEY
: /* Generated by IME. */
3909 windows_translate
= 1;
3912 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3913 which is confusing for purposes of key binding; convert
3914 VK_CANCEL events into VK_PAUSE events. */
3918 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3919 for purposes of key binding; convert these back into
3920 VK_NUMLOCK events, at least when we want to see NumLock key
3921 presses. (Note that there is never any possibility that
3922 VK_PAUSE with Ctrl really is C-Pause as per above.) */
3923 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
3924 wParam
= VK_NUMLOCK
;
3927 /* If not defined as a function key, change it to a WM_CHAR message. */
3928 if (lispy_function_keys
[wParam
] == 0)
3930 DWORD modifiers
= construct_console_modifiers ();
3932 if (!NILP (Vw32_recognize_altgr
)
3933 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
3935 /* Always let TranslateMessage handle AltGr key chords;
3936 for some reason, ToAscii doesn't always process AltGr
3937 chords correctly. */
3938 windows_translate
= 1;
3940 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
3942 /* Handle key chords including any modifiers other
3943 than shift directly, in order to preserve as much
3944 modifier information as possible. */
3945 if ('A' <= wParam
&& wParam
<= 'Z')
3947 /* Don't translate modified alphabetic keystrokes,
3948 so the user doesn't need to constantly switch
3949 layout to type control or meta keystrokes when
3950 the normal layout translates alphabetic
3951 characters to non-ascii characters. */
3952 if (!modifier_set (VK_SHIFT
))
3953 wParam
+= ('a' - 'A');
3958 /* Try to handle other keystrokes by determining the
3959 base character (ie. translating the base key plus
3963 KEY_EVENT_RECORD key
;
3965 key
.bKeyDown
= TRUE
;
3966 key
.wRepeatCount
= 1;
3967 key
.wVirtualKeyCode
= wParam
;
3968 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3969 key
.uChar
.AsciiChar
= 0;
3970 key
.dwControlKeyState
= modifiers
;
3972 add
= w32_kbd_patch_key (&key
);
3973 /* 0 means an unrecognised keycode, negative means
3974 dead key. Ignore both. */
3977 /* Forward asciified character sequence. */
3978 post_character_message
3979 (hwnd
, WM_CHAR
, key
.uChar
.AsciiChar
, lParam
,
3980 w32_get_key_modifiers (wParam
, lParam
));
3981 w32_kbd_patch_key (&key
);
3988 /* Let TranslateMessage handle everything else. */
3989 windows_translate
= 1;
3995 if (windows_translate
)
3997 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3999 windows_msg
.time
= GetMessageTime ();
4000 TranslateMessage (&windows_msg
);
4008 post_character_message (hwnd
, msg
, wParam
, lParam
,
4009 w32_get_key_modifiers (wParam
, lParam
));
4012 /* Simulate middle mouse button events when left and right buttons
4013 are used together, but only if user has two button mouse. */
4014 case WM_LBUTTONDOWN
:
4015 case WM_RBUTTONDOWN
:
4016 if (XINT (Vw32_num_mouse_buttons
) == 3)
4017 goto handle_plain_button
;
4020 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
4021 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
4023 if (button_state
& this)
4026 if (button_state
== 0)
4029 button_state
|= this;
4031 if (button_state
& other
)
4033 if (mouse_button_timer
)
4035 KillTimer (hwnd
, mouse_button_timer
);
4036 mouse_button_timer
= 0;
4038 /* Generate middle mouse event instead. */
4039 msg
= WM_MBUTTONDOWN
;
4040 button_state
|= MMOUSE
;
4042 else if (button_state
& MMOUSE
)
4044 /* Ignore button event if we've already generated a
4045 middle mouse down event. This happens if the
4046 user releases and press one of the two buttons
4047 after we've faked a middle mouse event. */
4052 /* Flush out saved message. */
4053 post_msg (&saved_mouse_button_msg
);
4055 wmsg
.dwModifiers
= w32_get_modifiers ();
4056 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4058 /* Clear message buffer. */
4059 saved_mouse_button_msg
.msg
.hwnd
= 0;
4063 /* Hold onto message for now. */
4064 mouse_button_timer
=
4065 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
4066 XINT (Vw32_mouse_button_tolerance
), NULL
);
4067 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
4068 saved_mouse_button_msg
.msg
.message
= msg
;
4069 saved_mouse_button_msg
.msg
.wParam
= wParam
;
4070 saved_mouse_button_msg
.msg
.lParam
= lParam
;
4071 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
4072 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
4079 if (XINT (Vw32_num_mouse_buttons
) == 3)
4080 goto handle_plain_button
;
4083 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
4084 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
4086 if ((button_state
& this) == 0)
4089 button_state
&= ~this;
4091 if (button_state
& MMOUSE
)
4093 /* Only generate event when second button is released. */
4094 if ((button_state
& other
) == 0)
4097 button_state
&= ~MMOUSE
;
4099 if (button_state
) abort ();
4106 /* Flush out saved message if necessary. */
4107 if (saved_mouse_button_msg
.msg
.hwnd
)
4109 post_msg (&saved_mouse_button_msg
);
4112 wmsg
.dwModifiers
= w32_get_modifiers ();
4113 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4115 /* Always clear message buffer and cancel timer. */
4116 saved_mouse_button_msg
.msg
.hwnd
= 0;
4117 KillTimer (hwnd
, mouse_button_timer
);
4118 mouse_button_timer
= 0;
4120 if (button_state
== 0)
4125 case WM_MBUTTONDOWN
:
4127 handle_plain_button
:
4132 if (parse_button (msg
, &button
, &up
))
4134 if (up
) ReleaseCapture ();
4135 else SetCapture (hwnd
);
4136 button
= (button
== 0) ? LMOUSE
:
4137 ((button
== 1) ? MMOUSE
: RMOUSE
);
4139 button_state
&= ~button
;
4141 button_state
|= button
;
4145 wmsg
.dwModifiers
= w32_get_modifiers ();
4146 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4151 if (XINT (Vw32_mouse_move_interval
) <= 0
4152 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
4154 wmsg
.dwModifiers
= w32_get_modifiers ();
4155 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4159 /* Hang onto mouse move and scroll messages for a bit, to avoid
4160 sending such events to Emacs faster than it can process them.
4161 If we get more events before the timer from the first message
4162 expires, we just replace the first message. */
4164 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
4166 SetTimer (hwnd
, MOUSE_MOVE_ID
,
4167 XINT (Vw32_mouse_move_interval
), NULL
);
4169 /* Hold onto message for now. */
4170 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
4171 saved_mouse_move_msg
.msg
.message
= msg
;
4172 saved_mouse_move_msg
.msg
.wParam
= wParam
;
4173 saved_mouse_move_msg
.msg
.lParam
= lParam
;
4174 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
4175 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
4180 wmsg
.dwModifiers
= w32_get_modifiers ();
4181 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4185 wmsg
.dwModifiers
= w32_get_modifiers ();
4186 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4190 /* Flush out saved messages if necessary. */
4191 if (wParam
== mouse_button_timer
)
4193 if (saved_mouse_button_msg
.msg
.hwnd
)
4195 post_msg (&saved_mouse_button_msg
);
4196 saved_mouse_button_msg
.msg
.hwnd
= 0;
4198 KillTimer (hwnd
, mouse_button_timer
);
4199 mouse_button_timer
= 0;
4201 else if (wParam
== mouse_move_timer
)
4203 if (saved_mouse_move_msg
.msg
.hwnd
)
4205 post_msg (&saved_mouse_move_msg
);
4206 saved_mouse_move_msg
.msg
.hwnd
= 0;
4208 KillTimer (hwnd
, mouse_move_timer
);
4209 mouse_move_timer
= 0;
4214 /* Windows doesn't send us focus messages when putting up and
4215 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4216 The only indication we get that something happened is receiving
4217 this message afterwards. So this is a good time to reset our
4218 keyboard modifiers' state. */
4225 /* We must ensure menu bar is fully constructed and up to date
4226 before allowing user interaction with it. To achieve this
4227 we send this message to the lisp thread and wait for a
4228 reply (whose value is not actually needed) to indicate that
4229 the menu bar is now ready for use, so we can now return.
4231 To remain responsive in the meantime, we enter a nested message
4232 loop that can process all other messages.
4234 However, we skip all this if the message results from calling
4235 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4236 thread a message because it is blocked on us at this point. We
4237 set menubar_active before calling TrackPopupMenu to indicate
4238 this (there is no possibility of confusion with real menubar
4241 f
= x_window_to_frame (dpyinfo
, hwnd
);
4243 && (f
->output_data
.w32
->menubar_active
4244 /* We can receive this message even in the absence of a
4245 menubar (ie. when the system menu is activated) - in this
4246 case we do NOT want to forward the message, otherwise it
4247 will cause the menubar to suddenly appear when the user
4248 had requested it to be turned off! */
4249 || f
->output_data
.w32
->menubar_widget
== NULL
))
4253 deferred_msg msg_buf
;
4255 /* Detect if message has already been deferred; in this case
4256 we cannot return any sensible value to ignore this. */
4257 if (find_deferred_msg (hwnd
, msg
) != NULL
)
4260 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
4263 case WM_EXITMENULOOP
:
4264 f
= x_window_to_frame (dpyinfo
, hwnd
);
4266 /* Indicate that menubar can be modified again. */
4268 f
->output_data
.w32
->menubar_active
= 0;
4271 case WM_MEASUREITEM
:
4272 f
= x_window_to_frame (dpyinfo
, hwnd
);
4275 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
4277 if (pMis
->CtlType
== ODT_MENU
)
4279 /* Work out dimensions for popup menu titles. */
4280 char * title
= (char *) pMis
->itemData
;
4281 HDC hdc
= GetDC (hwnd
);
4282 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4283 LOGFONT menu_logfont
;
4287 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4288 menu_logfont
.lfWeight
= FW_BOLD
;
4289 menu_font
= CreateFontIndirect (&menu_logfont
);
4290 old_font
= SelectObject (hdc
, menu_font
);
4292 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
4293 pMis
->itemWidth
= size
.cx
;
4294 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
4295 if (pMis
->itemHeight
< size
.cy
)
4296 pMis
->itemHeight
= size
.cy
;
4298 SelectObject (hdc
, old_font
);
4299 DeleteObject (menu_font
);
4300 ReleaseDC (hwnd
, hdc
);
4307 f
= x_window_to_frame (dpyinfo
, hwnd
);
4310 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
4312 if (pDis
->CtlType
== ODT_MENU
)
4314 /* Draw popup menu title. */
4315 char * title
= (char *) pDis
->itemData
;
4316 HDC hdc
= pDis
->hDC
;
4317 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4318 LOGFONT menu_logfont
;
4321 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4322 menu_logfont
.lfWeight
= FW_BOLD
;
4323 menu_font
= CreateFontIndirect (&menu_logfont
);
4324 old_font
= SelectObject (hdc
, menu_font
);
4326 /* Always draw title as if not selected. */
4328 pDis
->rcItem
.left
+ GetSystemMetrics (SM_CXMENUCHECK
),
4330 ETO_OPAQUE
, &pDis
->rcItem
,
4331 title
, strlen (title
), NULL
);
4333 SelectObject (hdc
, old_font
);
4334 DeleteObject (menu_font
);
4341 /* Still not right - can't distinguish between clicks in the
4342 client area of the frame from clicks forwarded from the scroll
4343 bars - may have to hook WM_NCHITTEST to remember the mouse
4344 position and then check if it is in the client area ourselves. */
4345 case WM_MOUSEACTIVATE
:
4346 /* Discard the mouse click that activates a frame, allowing the
4347 user to click anywhere without changing point (or worse!).
4348 Don't eat mouse clicks on scrollbars though!! */
4349 if (LOWORD (lParam
) == HTCLIENT
)
4350 return MA_ACTIVATEANDEAT
;
4354 case WM_ACTIVATEAPP
:
4356 case WM_WINDOWPOSCHANGED
:
4358 /* Inform lisp thread that a frame might have just been obscured
4359 or exposed, so should recheck visibility of all frames. */
4360 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4364 dpyinfo
->faked_key
= 0;
4366 register_hot_keys (hwnd
);
4369 unregister_hot_keys (hwnd
);
4376 wmsg
.dwModifiers
= w32_get_modifiers ();
4377 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4381 wmsg
.dwModifiers
= w32_get_modifiers ();
4382 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4385 case WM_WINDOWPOSCHANGING
:
4388 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
4390 wp
.length
= sizeof (WINDOWPLACEMENT
);
4391 GetWindowPlacement (hwnd
, &wp
);
4393 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
4400 DWORD internal_border
;
4401 DWORD scrollbar_extra
;
4404 wp
.length
= sizeof(wp
);
4405 GetWindowRect (hwnd
, &wr
);
4409 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
4410 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
4411 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
4412 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
4416 memset (&rect
, 0, sizeof (rect
));
4417 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
4418 GetMenu (hwnd
) != NULL
);
4420 /* Force width and height of client area to be exact
4421 multiples of the character cell dimensions. */
4422 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
4423 - 2 * internal_border
- scrollbar_extra
)
4425 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
4426 - 2 * internal_border
)
4431 /* For right/bottom sizing we can just fix the sizes.
4432 However for top/left sizing we will need to fix the X
4433 and Y positions as well. */
4438 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
4439 && (lppos
->flags
& SWP_NOMOVE
) == 0)
4441 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
4448 lppos
->flags
|= SWP_NOMOVE
;
4459 case WM_GETMINMAXINFO
:
4460 /* Hack to correct bug that allows Emacs frames to be resized
4461 below the Minimum Tracking Size. */
4462 ((LPMINMAXINFO
) lParam
)->ptMinTrackSize
.y
++;
4465 case WM_EMACS_CREATESCROLLBAR
:
4466 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
4467 (struct scroll_bar
*) lParam
);
4469 case WM_EMACS_SHOWWINDOW
:
4470 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
4472 case WM_EMACS_SETFOREGROUND
:
4474 HWND foreground_window
;
4475 DWORD foreground_thread
, retval
;
4477 /* On NT 5.0, and apparently Windows 98, it is necessary to
4478 attach to the thread that currently has focus in order to
4479 pull the focus away from it. */
4480 foreground_window
= GetForegroundWindow ();
4481 foreground_thread
= GetWindowThreadProcessId (foreground_window
, NULL
);
4482 if (!foreground_window
4483 || foreground_thread
== GetCurrentThreadId ()
4484 || !AttachThreadInput (GetCurrentThreadId (),
4485 foreground_thread
, TRUE
))
4486 foreground_thread
= 0;
4488 retval
= SetForegroundWindow ((HWND
) wParam
);
4490 /* Detach from the previous foreground thread. */
4491 if (foreground_thread
)
4492 AttachThreadInput (GetCurrentThreadId (),
4493 foreground_thread
, FALSE
);
4498 case WM_EMACS_SETWINDOWPOS
:
4500 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
4501 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
4502 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
4505 case WM_EMACS_DESTROYWINDOW
:
4506 DragAcceptFiles ((HWND
) wParam
, FALSE
);
4507 return DestroyWindow ((HWND
) wParam
);
4509 case WM_EMACS_TRACKPOPUPMENU
:
4514 pos
= (POINT
*)lParam
;
4515 flags
= TPM_CENTERALIGN
;
4516 if (button_state
& LMOUSE
)
4517 flags
|= TPM_LEFTBUTTON
;
4518 else if (button_state
& RMOUSE
)
4519 flags
|= TPM_RIGHTBUTTON
;
4521 /* Remember we did a SetCapture on the initial mouse down event,
4522 so for safety, we make sure the capture is cancelled now. */
4526 /* Use menubar_active to indicate that WM_INITMENU is from
4527 TrackPopupMenu below, and should be ignored. */
4528 f
= x_window_to_frame (dpyinfo
, hwnd
);
4530 f
->output_data
.w32
->menubar_active
= 1;
4532 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
4536 /* Eat any mouse messages during popupmenu */
4537 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
4539 /* Get the menu selection, if any */
4540 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
4542 retval
= LOWORD (amsg
.wParam
);
4558 /* Check for messages registered at runtime. */
4559 if (msg
== msh_mousewheel
)
4561 wmsg
.dwModifiers
= w32_get_modifiers ();
4562 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4567 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
4571 /* The most common default return code for handled messages is 0. */
4576 my_create_window (f
)
4581 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
4583 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4586 /* Create and set up the w32 window for frame F. */
4589 w32_window (f
, window_prompting
, minibuffer_only
)
4591 long window_prompting
;
4592 int minibuffer_only
;
4596 /* Use the resource name as the top-level window name
4597 for looking up resources. Make a non-Lisp copy
4598 for the window manager, so GC relocation won't bother it.
4600 Elsewhere we specify the window name for the window manager. */
4603 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
4604 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4605 strcpy (f
->namebuf
, str
);
4608 my_create_window (f
);
4610 validate_x_resource_name ();
4612 /* x_set_name normally ignores requests to set the name if the
4613 requested name is the same as the current name. This is the one
4614 place where that assumption isn't correct; f->name is set, but
4615 the server hasn't been told. */
4618 int explicit = f
->explicit_name
;
4620 f
->explicit_name
= 0;
4623 x_set_name (f
, name
, explicit);
4628 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4629 initialize_frame_menubar (f
);
4631 if (FRAME_W32_WINDOW (f
) == 0)
4632 error ("Unable to create window");
4635 /* Handle the icon stuff for this window. Perhaps later we might
4636 want an x_set_icon_position which can be called interactively as
4644 Lisp_Object icon_x
, icon_y
;
4646 /* Set the position of the icon. Note that Windows 95 groups all
4647 icons in the tray. */
4648 icon_x
= x_get_arg (parms
, Qicon_left
, 0, 0, number
);
4649 icon_y
= x_get_arg (parms
, Qicon_top
, 0, 0, number
);
4650 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4652 CHECK_NUMBER (icon_x
, 0);
4653 CHECK_NUMBER (icon_y
, 0);
4655 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4656 error ("Both left and top icon corners of icon must be specified");
4660 if (! EQ (icon_x
, Qunbound
))
4661 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4664 /* Start up iconic or window? */
4665 x_wm_set_window_state
4666 (f
, (EQ (x_get_arg (parms
, Qvisibility
, 0, 0, symbol
), Qicon
)
4670 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4678 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4680 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
4681 Returns an Emacs frame object.\n\
4682 ALIST is an alist of frame parameters.\n\
4683 If the parameters specify that the frame should not have a minibuffer,\n\
4684 and do not specify a specific minibuffer window to use,\n\
4685 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4686 be shared by the new frame.\n\
4688 This function is an internal primitive--use `make-frame' instead.")
4693 Lisp_Object frame
, tem
;
4695 int minibuffer_only
= 0;
4696 long window_prompting
= 0;
4698 int count
= specpdl_ptr
- specpdl
;
4699 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4700 Lisp_Object display
;
4701 struct w32_display_info
*dpyinfo
;
4707 /* Use this general default value to start with
4708 until we know if this frame has a specified name. */
4709 Vx_resource_name
= Vinvocation_name
;
4711 display
= x_get_arg (parms
, Qdisplay
, 0, 0, string
);
4712 if (EQ (display
, Qunbound
))
4714 dpyinfo
= check_x_display_info (display
);
4716 kb
= dpyinfo
->kboard
;
4718 kb
= &the_only_kboard
;
4721 name
= x_get_arg (parms
, Qname
, "name", "Name", string
);
4723 && ! EQ (name
, Qunbound
)
4725 error ("Invalid frame name--not a string or nil");
4728 Vx_resource_name
= name
;
4730 /* See if parent window is specified. */
4731 parent
= x_get_arg (parms
, Qparent_id
, NULL
, NULL
, number
);
4732 if (EQ (parent
, Qunbound
))
4734 if (! NILP (parent
))
4735 CHECK_NUMBER (parent
, 0);
4737 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4738 /* No need to protect DISPLAY because that's not used after passing
4739 it to make_frame_without_minibuffer. */
4741 GCPRO4 (parms
, parent
, name
, frame
);
4742 tem
= x_get_arg (parms
, Qminibuffer
, 0, 0, symbol
);
4743 if (EQ (tem
, Qnone
) || NILP (tem
))
4744 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4745 else if (EQ (tem
, Qonly
))
4747 f
= make_minibuffer_frame ();
4748 minibuffer_only
= 1;
4750 else if (WINDOWP (tem
))
4751 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4755 XSETFRAME (frame
, f
);
4757 /* Note that Windows does support scroll bars. */
4758 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4759 /* By default, make scrollbars the system standard width. */
4760 f
->scroll_bar_pixel_width
= GetSystemMetrics (SM_CXVSCROLL
);
4762 f
->output_method
= output_w32
;
4763 f
->output_data
.w32
= (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4764 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
4766 FRAME_FONTSET (f
) = -1;
4769 = x_get_arg (parms
, Qicon_name
, "iconName", "Title", string
);
4770 if (! STRINGP (f
->icon_name
))
4771 f
->icon_name
= Qnil
;
4773 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4775 FRAME_KBOARD (f
) = kb
;
4778 /* Specify the parent under which to make this window. */
4782 f
->output_data
.w32
->parent_desc
= (Window
) parent
;
4783 f
->output_data
.w32
->explicit_parent
= 1;
4787 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4788 f
->output_data
.w32
->explicit_parent
= 0;
4791 /* Note that the frame has no physical cursor right now. */
4792 f
->phys_cursor_x
= -1;
4794 /* Set the name; the functions to which we pass f expect the name to
4796 if (EQ (name
, Qunbound
) || NILP (name
))
4798 f
->name
= build_string (dpyinfo
->w32_id_name
);
4799 f
->explicit_name
= 0;
4804 f
->explicit_name
= 1;
4805 /* use the frame's title when getting resources for this frame. */
4806 specbind (Qx_resource_name
, name
);
4809 /* Create fontsets from `global_fontset_alist' before handling fonts. */
4810 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
4811 fs_register_fontset (f
, XCONS (tem
)->car
);
4813 /* Extract the window parameters from the supplied values
4814 that are needed to determine window geometry. */
4818 font
= x_get_arg (parms
, Qfont
, "font", "Font", string
);
4820 /* First, try whatever font the caller has specified. */
4823 tem
= Fquery_fontset (font
, Qnil
);
4825 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4827 font
= x_new_font (f
, XSTRING (font
)->data
);
4829 /* Try out a font which we hope has bold and italic variations. */
4830 if (!STRINGP (font
))
4831 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
4832 if (! STRINGP (font
))
4833 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-*-97-*-*-c-*-iso8859-1");
4834 /* If those didn't work, look for something which will at least work. */
4835 if (! STRINGP (font
))
4836 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-*-*-90-*-c-*-iso8859-1");
4838 if (! STRINGP (font
))
4839 font
= build_string ("Fixedsys");
4841 x_default_parameter (f
, parms
, Qfont
, font
,
4842 "font", "Font", string
);
4845 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4846 "borderwidth", "BorderWidth", number
);
4847 /* This defaults to 2 in order to match xterm. We recognize either
4848 internalBorderWidth or internalBorder (which is what xterm calls
4850 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4854 value
= x_get_arg (parms
, Qinternal_border_width
,
4855 "internalBorder", "BorderWidth", number
);
4856 if (! EQ (value
, Qunbound
))
4857 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4860 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4861 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (0),
4862 "internalBorderWidth", "BorderWidth", number
);
4863 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qt
,
4864 "verticalScrollBars", "ScrollBars", boolean
);
4866 /* Also do the stuff which must be set before the window exists. */
4867 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4868 "foreground", "Foreground", string
);
4869 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4870 "background", "Background", string
);
4871 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4872 "pointerColor", "Foreground", string
);
4873 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4874 "cursorColor", "Foreground", string
);
4875 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4876 "borderColor", "BorderColor", string
);
4878 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4879 "menuBar", "MenuBar", number
);
4880 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4881 "scrollBarWidth", "ScrollBarWidth", number
);
4882 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4883 "bufferPredicate", "BufferPredicate", symbol
);
4884 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4885 "title", "Title", string
);
4887 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4888 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4889 window_prompting
= x_figure_window_size (f
, parms
);
4891 if (window_prompting
& XNegative
)
4893 if (window_prompting
& YNegative
)
4894 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
4896 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
4900 if (window_prompting
& YNegative
)
4901 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
4903 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4906 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
4908 w32_window (f
, window_prompting
, minibuffer_only
);
4910 init_frame_faces (f
);
4912 /* We need to do this after creating the window, so that the
4913 icon-creation functions can say whose icon they're describing. */
4914 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4915 "bitmapIcon", "BitmapIcon", symbol
);
4917 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4918 "autoRaise", "AutoRaiseLower", boolean
);
4919 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4920 "autoLower", "AutoRaiseLower", boolean
);
4921 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4922 "cursorType", "CursorType", symbol
);
4924 /* Dimensions, especially f->height, must be done via change_frame_size.
4925 Change will not be effected unless different from the current
4930 SET_FRAME_WIDTH (f
, 0);
4931 change_frame_size (f
, height
, width
, 1, 0);
4933 /* Tell the server what size and position, etc, we want,
4934 and how badly we want them. */
4936 x_wm_set_size_hint (f
, window_prompting
, 0);
4939 tem
= x_get_arg (parms
, Qunsplittable
, 0, 0, boolean
);
4940 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4944 /* It is now ok to make the frame official
4945 even if we get an error below.
4946 And the frame needs to be on Vframe_list
4947 or making it visible won't work. */
4948 Vframe_list
= Fcons (frame
, Vframe_list
);
4950 /* Now that the frame is official, it counts as a reference to
4952 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4954 /* Make the window appear on the frame and enable display,
4955 unless the caller says not to. However, with explicit parent,
4956 Emacs cannot control visibility, so don't try. */
4957 if (! f
->output_data
.w32
->explicit_parent
)
4959 Lisp_Object visibility
;
4961 visibility
= x_get_arg (parms
, Qvisibility
, 0, 0, symbol
);
4962 if (EQ (visibility
, Qunbound
))
4965 if (EQ (visibility
, Qicon
))
4966 x_iconify_frame (f
);
4967 else if (! NILP (visibility
))
4968 x_make_frame_visible (f
);
4970 /* Must have been Qnil. */
4974 return unbind_to (count
, frame
);
4977 /* FRAME is used only to get a handle on the X display. We don't pass the
4978 display info directly because we're called from frame.c, which doesn't
4979 know about that structure. */
4981 x_get_focus_frame (frame
)
4982 struct frame
*frame
;
4984 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4986 if (! dpyinfo
->w32_focus_frame
)
4989 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4993 DEFUN ("w32-focus-frame", Fw32_focus_frame
, Sw32_focus_frame
, 1, 1, 0,
4994 "Give FRAME input focus, raising to foreground if necessary.")
4998 x_focus_on_frame (check_x_frame (frame
));
5003 struct font_info
*w32_load_bdf_font (struct frame
*f
, char *fontname
,
5004 int size
, char* filename
);
5007 w32_load_system_font (f
,fontname
,size
)
5012 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5013 Lisp_Object font_names
;
5015 /* Get a list of all the fonts that match this name. Once we
5016 have a list of matching fonts, we compare them against the fonts
5017 we already have loaded by comparing names. */
5018 font_names
= w32_list_fonts (f
, build_string (fontname
), size
, 100);
5020 if (!NILP (font_names
))
5024 #if 0 /* This code has nasty side effects that cause Emacs to crash. */
5026 /* First check if any are already loaded, as that is cheaper
5027 than loading another one. */
5028 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5029 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
5030 if (!strcmp (dpyinfo
->font_table
[i
].name
,
5031 XSTRING (XCONS (tail
)->car
)->data
)
5032 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
5033 XSTRING (XCONS (tail
)->car
)->data
))
5034 return (dpyinfo
->font_table
+ i
);
5036 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
5038 else if (w32_strict_fontnames
)
5040 /* If EnumFontFamiliesEx was available, we got a full list of
5041 fonts back so stop now to avoid the possibility of loading a
5042 random font. If we had to fall back to EnumFontFamilies, the
5043 list is incomplete, so continue whether the font we want was
5045 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
5046 FARPROC enum_font_families_ex
5047 = GetProcAddress (gdi32
, "EnumFontFamiliesExA");
5048 if (enum_font_families_ex
)
5052 /* Load the font and add it to the table. */
5054 char *full_name
, *encoding
;
5056 struct font_info
*fontp
;
5060 if (!fontname
|| !x_to_w32_font (fontname
, &lf
))
5063 if (!*lf
.lfFaceName
)
5064 /* If no name was specified for the font, we get a random font
5065 from CreateFontIndirect - this is not particularly
5066 desirable, especially since CreateFontIndirect does not
5067 fill out the missing name in lf, so we never know what we
5071 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
5073 /* Set bdf to NULL to indicate that this is a Windows font. */
5078 font
->hfont
= CreateFontIndirect (&lf
);
5080 if (font
->hfont
== NULL
)
5089 hdc
= GetDC (dpyinfo
->root_window
);
5090 oldobj
= SelectObject (hdc
, font
->hfont
);
5091 ok
= GetTextMetrics (hdc
, &font
->tm
);
5092 SelectObject (hdc
, oldobj
);
5093 ReleaseDC (dpyinfo
->root_window
, hdc
);
5095 /* [andrewi, 25-Apr-99] A number of fixed pitch fonts,
5096 eg. Courier New and perhaps others, report a max width which
5097 is larger than the average character width, at least on some
5098 NT systems (I don't understand why - my best guess is that it
5099 results from installing the CJK language packs for NT4).
5100 Unfortunately, this forces the redisplay code in dumpglyphs
5101 to draw text character by character.
5103 I don't like this hack, but it seems better to force the max
5104 width to match the average width if the font is marked as
5105 fixed pitch, for the sake of redisplay performance. */
5107 if ((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
) == 0)
5108 font
->tm
.tmMaxCharWidth
= font
->tm
.tmAveCharWidth
;
5115 w32_unload_font (dpyinfo
, font
);
5119 /* Do we need to create the table? */
5120 if (dpyinfo
->font_table_size
== 0)
5122 dpyinfo
->font_table_size
= 16;
5124 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
5125 * sizeof (struct font_info
));
5127 /* Do we need to grow the table? */
5128 else if (dpyinfo
->n_fonts
5129 >= dpyinfo
->font_table_size
)
5131 dpyinfo
->font_table_size
*= 2;
5133 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
5134 (dpyinfo
->font_table_size
5135 * sizeof (struct font_info
)));
5138 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
5140 /* Now fill in the slots of *FONTP. */
5143 fontp
->font_idx
= dpyinfo
->n_fonts
;
5144 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
5145 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
5147 /* Work out the font's full name. */
5148 full_name
= (char *)xmalloc (100);
5149 if (full_name
&& w32_to_x_font (&lf
, full_name
, 100))
5150 fontp
->full_name
= full_name
;
5153 /* If all else fails - just use the name we used to load it. */
5155 fontp
->full_name
= fontp
->name
;
5158 fontp
->size
= FONT_WIDTH (font
);
5159 fontp
->height
= FONT_HEIGHT (font
);
5161 /* The slot `encoding' specifies how to map a character
5162 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5163 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
5164 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
5165 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
5166 2:0xA020..0xFF7F). For the moment, we don't know which charset
5167 uses this font. So, we set informatoin in fontp->encoding[1]
5168 which is never used by any charset. If mapping can't be
5169 decided, set FONT_ENCODING_NOT_DECIDED. */
5171 /* SJIS fonts need to be set to type 4, all others seem to work as
5172 type FONT_ENCODING_NOT_DECIDED. */
5173 encoding
= strrchr (fontp
->name
, '-');
5174 if (encoding
&& stricmp (encoding
+1, "sjis") == 0)
5175 fontp
->encoding
[1] = 4;
5177 fontp
->encoding
[1] = FONT_ENCODING_NOT_DECIDED
;
5179 /* The following three values are set to 0 under W32, which is
5180 what they get set to if XGetFontProperty fails under X. */
5181 fontp
->baseline_offset
= 0;
5182 fontp
->relative_compose
= 0;
5183 fontp
->default_ascent
= 0;
5192 /* Load font named FONTNAME of size SIZE for frame F, and return a
5193 pointer to the structure font_info while allocating it dynamically.
5194 If loading fails, return NULL. */
5196 w32_load_font (f
,fontname
,size
)
5201 Lisp_Object bdf_fonts
;
5202 struct font_info
*retval
= NULL
;
5204 bdf_fonts
= w32_list_bdf_fonts (build_string (fontname
));
5206 while (!retval
&& CONSP (bdf_fonts
))
5208 char *bdf_name
, *bdf_file
;
5209 Lisp_Object bdf_pair
;
5211 bdf_name
= XSTRING (XCONS (bdf_fonts
)->car
)->data
;
5212 bdf_pair
= Fassoc (XCONS (bdf_fonts
)->car
, Vw32_bdf_filename_alist
);
5213 bdf_file
= XSTRING (XCONS (bdf_pair
)->cdr
)->data
;
5215 retval
= w32_load_bdf_font (f
, bdf_name
, size
, bdf_file
);
5217 bdf_fonts
= XCONS (bdf_fonts
)->cdr
;
5223 return w32_load_system_font(f
, fontname
, size
);
5228 w32_unload_font (dpyinfo
, font
)
5229 struct w32_display_info
*dpyinfo
;
5234 if (font
->bdf
) w32_free_bdf_font (font
->bdf
);
5236 if (font
->hfont
) DeleteObject(font
->hfont
);
5241 /* The font conversion stuff between x and w32 */
5243 /* X font string is as follows (from faces.el)
5247 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5248 * (weight\? "\\([^-]*\\)") ; 1
5249 * (slant "\\([ior]\\)") ; 2
5250 * (slant\? "\\([^-]?\\)") ; 2
5251 * (swidth "\\([^-]*\\)") ; 3
5252 * (adstyle "[^-]*") ; 4
5253 * (pixelsize "[0-9]+")
5254 * (pointsize "[0-9][0-9]+")
5255 * (resx "[0-9][0-9]+")
5256 * (resy "[0-9][0-9]+")
5257 * (spacing "[cmp?*]")
5258 * (avgwidth "[0-9]+")
5259 * (registry "[^-]+")
5260 * (encoding "[^-]+")
5262 * (setq x-font-regexp
5263 * (concat "\\`\\*?[-?*]"
5264 * foundry - family - weight\? - slant\? - swidth - adstyle -
5265 * pixelsize - pointsize - resx - resy - spacing - registry -
5266 * encoding "[-?*]\\*?\\'"
5268 * (setq x-font-regexp-head
5269 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
5270 * "\\([-*?]\\|\\'\\)"))
5271 * (setq x-font-regexp-slant (concat - slant -))
5272 * (setq x-font-regexp-weight (concat - weight -))
5276 #define FONT_START "[-?]"
5277 #define FONT_FOUNDRY "[^-]+"
5278 #define FONT_FAMILY "\\([^-]+\\)" /* 1 */
5279 #define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
5280 #define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
5281 #define FONT_SLANT "\\([ior]\\)" /* 3 */
5282 #define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
5283 #define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
5284 #define FONT_ADSTYLE "[^-]*"
5285 #define FONT_PIXELSIZE "[^-]*"
5286 #define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
5287 #define FONT_RESX "[0-9][0-9]+"
5288 #define FONT_RESY "[0-9][0-9]+"
5289 #define FONT_SPACING "[cmp?*]"
5290 #define FONT_AVGWIDTH "[0-9]+"
5291 #define FONT_REGISTRY "[^-]+"
5292 #define FONT_ENCODING "[^-]+"
5294 #define FONT_REGEXP ("\\`\\*?[-?*]" \
5301 FONT_PIXELSIZE "-" \
5302 FONT_POINTSIZE "-" \
5305 #define FONT_REGEXP_HEAD ("\\`[-?*]" \
5310 "\\([-*?]\\|\\'\\)")
5312 #define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
5313 #define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
5316 x_to_w32_weight (lpw
)
5319 if (!lpw
) return (FW_DONTCARE
);
5321 if (stricmp (lpw
,"heavy") == 0) return FW_HEAVY
;
5322 else if (stricmp (lpw
,"extrabold") == 0) return FW_EXTRABOLD
;
5323 else if (stricmp (lpw
,"bold") == 0) return FW_BOLD
;
5324 else if (stricmp (lpw
,"demibold") == 0) return FW_SEMIBOLD
;
5325 else if (stricmp (lpw
,"semibold") == 0) return FW_SEMIBOLD
;
5326 else if (stricmp (lpw
,"medium") == 0) return FW_MEDIUM
;
5327 else if (stricmp (lpw
,"normal") == 0) return FW_NORMAL
;
5328 else if (stricmp (lpw
,"light") == 0) return FW_LIGHT
;
5329 else if (stricmp (lpw
,"extralight") == 0) return FW_EXTRALIGHT
;
5330 else if (stricmp (lpw
,"thin") == 0) return FW_THIN
;
5337 w32_to_x_weight (fnweight
)
5340 if (fnweight
>= FW_HEAVY
) return "heavy";
5341 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
5342 if (fnweight
>= FW_BOLD
) return "bold";
5343 if (fnweight
>= FW_SEMIBOLD
) return "demibold";
5344 if (fnweight
>= FW_MEDIUM
) return "medium";
5345 if (fnweight
>= FW_NORMAL
) return "normal";
5346 if (fnweight
>= FW_LIGHT
) return "light";
5347 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
5348 if (fnweight
>= FW_THIN
) return "thin";
5354 x_to_w32_charset (lpcs
)
5357 if (!lpcs
) return (0);
5359 if (stricmp (lpcs
,"ansi") == 0) return ANSI_CHARSET
;
5360 else if (stricmp (lpcs
,"iso8859-1") == 0) return ANSI_CHARSET
;
5361 else if (stricmp (lpcs
, "ms-symbol") == 0) return SYMBOL_CHARSET
;
5362 /* Map all Japanese charsets to the Windows Shift-JIS charset. */
5363 else if (strnicmp (lpcs
, "jis", 3) == 0) return SHIFTJIS_CHARSET
;
5364 /* Map all GB charsets to the Windows GB2312 charset. */
5365 else if (strnicmp (lpcs
, "gb2312", 6) == 0) return GB2312_CHARSET
;
5366 /* Map all Big5 charsets to the Windows Big5 charset. */
5367 else if (strnicmp (lpcs
, "big5", 4) == 0) return CHINESEBIG5_CHARSET
;
5368 else if (stricmp (lpcs
, "ksc5601.1987") == 0) return HANGEUL_CHARSET
;
5369 else if (stricmp (lpcs
, "ms-oem") == 0) return OEM_CHARSET
;
5371 #ifdef EASTEUROPE_CHARSET
5372 else if (stricmp (lpcs
, "iso8859-2") == 0) return EASTEUROPE_CHARSET
;
5373 else if (stricmp (lpcs
, "iso8859-3") == 0) return TURKISH_CHARSET
;
5374 else if (stricmp (lpcs
, "iso8859-4") == 0) return BALTIC_CHARSET
;
5375 else if (stricmp (lpcs
, "iso8859-5") == 0) return RUSSIAN_CHARSET
;
5376 else if (stricmp (lpcs
, "koi8") == 0) return RUSSIAN_CHARSET
;
5377 else if (stricmp (lpcs
, "iso8859-6") == 0) return ARABIC_CHARSET
;
5378 else if (stricmp (lpcs
, "iso8859-7") == 0) return GREEK_CHARSET
;
5379 else if (stricmp (lpcs
, "iso8859-8") == 0) return HEBREW_CHARSET
;
5380 else if (stricmp (lpcs
, "iso8859-9") == 0) return TURKISH_CHARSET
;
5381 #ifndef VIETNAMESE_CHARSET
5382 #define VIETNAMESE_CHARSET 163
5384 /* Map all Viscii charsets to the Windows Vietnamese charset. */
5385 else if (strnicmp (lpcs
, "viscii", 6) == 0) return VIETNAMESE_CHARSET
;
5386 else if (strnicmp (lpcs
, "vscii", 5) == 0) return VIETNAMESE_CHARSET
;
5387 /* Map all TIS charsets to the Windows Thai charset. */
5388 else if (strnicmp (lpcs
, "tis620", 6) == 0) return THAI_CHARSET
;
5389 else if (stricmp (lpcs
, "mac") == 0) return MAC_CHARSET
;
5390 else if (stricmp (lpcs
, "ksc5601.1992") == 0) return JOHAB_CHARSET
;
5391 /* For backwards compatibility with previous 20.4 pretests, map
5392 non-specific KSC charsets to the Windows Hangeul charset. */
5393 else if (strnicmp (lpcs
, "ksc5601", 7) == 0) return HANGEUL_CHARSET
;
5394 else if (stricmp (lpcs
, "johab") == 0) return JOHAB_CHARSET
;
5397 #ifdef UNICODE_CHARSET
5398 else if (stricmp (lpcs
,"iso10646") == 0) return UNICODE_CHARSET
;
5399 else if (stricmp (lpcs
, "unicode") == 0) return UNICODE_CHARSET
;
5401 else if (lpcs
[0] == '#') return atoi (lpcs
+ 1);
5403 return DEFAULT_CHARSET
;
5407 w32_to_x_charset (fncharset
)
5410 static char buf
[16];
5414 /* ansi is considered iso8859-1, as most modern ansi fonts are. */
5415 case ANSI_CHARSET
: return "iso8859-1";
5416 case DEFAULT_CHARSET
: return "ascii-*";
5417 case SYMBOL_CHARSET
: return "ms-symbol";
5418 case SHIFTJIS_CHARSET
: return "jisx0208-sjis";
5419 case HANGEUL_CHARSET
: return "ksc5601.1987-*";
5420 case GB2312_CHARSET
: return "gb2312-*";
5421 case CHINESEBIG5_CHARSET
: return "big5-*";
5422 case OEM_CHARSET
: return "ms-oem";
5424 /* More recent versions of Windows (95 and NT4.0) define more
5426 #ifdef EASTEUROPE_CHARSET
5427 case EASTEUROPE_CHARSET
: return "iso8859-2";
5428 case TURKISH_CHARSET
: return "iso8859-9";
5429 case BALTIC_CHARSET
: return "iso8859-4";
5431 /* W95 with international support but not IE4 often has the
5432 KOI8-R codepage but not ISO8859-5. */
5433 case RUSSIAN_CHARSET
:
5434 if (!IsValidCodePage(28595) && IsValidCodePage(20886))
5438 case ARABIC_CHARSET
: return "iso8859-6";
5439 case GREEK_CHARSET
: return "iso8859-7";
5440 case HEBREW_CHARSET
: return "iso8859-8";
5441 case VIETNAMESE_CHARSET
: return "viscii1.1-*";
5442 case THAI_CHARSET
: return "tis620-*";
5443 case MAC_CHARSET
: return "mac-*";
5444 case JOHAB_CHARSET
: return "ksc5601.1992-*";
5448 #ifdef UNICODE_CHARSET
5449 case UNICODE_CHARSET
: return "iso10646-unicode";
5452 /* Encode numerical value of unknown charset. */
5453 sprintf (buf
, "*-#%u", fncharset
);
5458 w32_to_x_font (lplogfont
, lpxstr
, len
)
5459 LOGFONT
* lplogfont
;
5464 char height_pixels
[8];
5466 char width_pixels
[8];
5467 char *fontname_dash
;
5468 int display_resy
= one_w32_display_info
.height_in
;
5469 int display_resx
= one_w32_display_info
.width_in
;
5471 struct coding_system coding
;
5473 if (!lpxstr
) abort ();
5478 setup_coding_system (Fcheck_coding_system (Vw32_system_coding_system
),
5480 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5481 bufsz
= decoding_buffer_size (&coding
, LF_FACESIZE
);
5483 fontname
= alloca(sizeof(*fontname
) * bufsz
);
5484 decode_coding (&coding
, lplogfont
->lfFaceName
, fontname
,
5485 strlen(lplogfont
->lfFaceName
), bufsz
- 1);
5486 *(fontname
+ coding
.produced
) = '\0';
5488 /* Replace dashes with underscores so the dashes are not
5490 fontname_dash
= fontname
;
5491 while (fontname_dash
= strchr (fontname_dash
, '-'))
5492 *fontname_dash
= '_';
5494 if (lplogfont
->lfHeight
)
5496 sprintf (height_pixels
, "%u", abs (lplogfont
->lfHeight
));
5497 sprintf (height_dpi
, "%u",
5498 abs (lplogfont
->lfHeight
) * 720 / display_resy
);
5502 strcpy (height_pixels
, "*");
5503 strcpy (height_dpi
, "*");
5505 if (lplogfont
->lfWidth
)
5506 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
5508 strcpy (width_pixels
, "*");
5510 _snprintf (lpxstr
, len
- 1,
5511 "-*-%s-%s-%c-*-*-%s-%s-%d-%d-%c-%s-%s",
5513 fontname
, /* family */
5514 w32_to_x_weight (lplogfont
->lfWeight
), /* weight */
5515 lplogfont
->lfItalic
?'i':'r', /* slant */
5517 /* add style name */
5518 height_pixels
, /* pixel size */
5519 height_dpi
, /* point size */
5520 display_resx
, /* resx */
5521 display_resy
, /* resy */
5522 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
)
5523 ? 'p' : 'c', /* spacing */
5524 width_pixels
, /* avg width */
5525 w32_to_x_charset (lplogfont
->lfCharSet
) /* charset registry
5529 lpxstr
[len
- 1] = 0; /* just to be sure */
5534 x_to_w32_font (lpxstr
, lplogfont
)
5536 LOGFONT
* lplogfont
;
5538 struct coding_system coding
;
5540 if (!lplogfont
) return (FALSE
);
5542 memset (lplogfont
, 0, sizeof (*lplogfont
));
5544 /* Set default value for each field. */
5546 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5547 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5548 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
5550 /* go for maximum quality */
5551 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
5552 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
5553 lplogfont
->lfQuality
= PROOF_QUALITY
;
5556 lplogfont
->lfCharSet
= DEFAULT_CHARSET
;
5557 lplogfont
->lfWeight
= FW_DONTCARE
;
5558 lplogfont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
5563 /* Provide a simple escape mechanism for specifying Windows font names
5564 * directly -- if font spec does not beginning with '-', assume this
5566 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
5572 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10],
5573 width
[10], resy
[10], remainder
[20];
5575 int dpi
= one_w32_display_info
.height_in
;
5577 fields
= sscanf (lpxstr
,
5578 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%19s",
5579 name
, weight
, &slant
, pixels
, height
, resy
, &pitch
, width
, remainder
);
5580 if (fields
== EOF
) return (FALSE
);
5582 if (fields
> 0 && name
[0] != '*')
5588 (Fcheck_coding_system (Vw32_system_coding_system
), &coding
);
5589 bufsize
= encoding_buffer_size (&coding
, strlen (name
));
5590 buf
= (unsigned char *) alloca (bufsize
);
5591 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5592 encode_coding (&coding
, name
, buf
, strlen (name
), bufsize
);
5593 if (coding
.produced
>= LF_FACESIZE
)
5594 coding
.produced
= LF_FACESIZE
- 1;
5595 buf
[coding
.produced
] = 0;
5596 strcpy (lplogfont
->lfFaceName
, buf
);
5600 lplogfont
->lfFaceName
[0] = 0;
5605 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5609 if (!NILP (Vw32_enable_italics
))
5610 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
5614 if (fields
> 0 && pixels
[0] != '*')
5615 lplogfont
->lfHeight
= atoi (pixels
);
5619 if (fields
> 0 && resy
[0] != '*')
5621 tem
= atoi (pixels
);
5622 if (tem
> 0) dpi
= tem
;
5625 if (fields
> -1 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
5626 lplogfont
->lfHeight
= atoi (height
) * dpi
/ 720;
5629 lplogfont
->lfPitchAndFamily
=
5630 (fields
> 0 && pitch
== 'p') ? VARIABLE_PITCH
: FIXED_PITCH
;
5634 if (fields
> 0 && width
[0] != '*')
5635 lplogfont
->lfWidth
= atoi (width
) / 10;
5639 /* Strip the trailing '-' if present. (it shouldn't be, as it
5640 fails the test against xlfn-tight-regexp in fontset.el). */
5642 int len
= strlen (remainder
);
5643 if (len
> 0 && remainder
[len
-1] == '-')
5644 remainder
[len
-1] = 0;
5646 encoding
= remainder
;
5647 if (strncmp (encoding
, "*-", 2) == 0)
5649 lplogfont
->lfCharSet
= x_to_w32_charset (fields
> 0 ? encoding
: "");
5654 char name
[100], height
[10], width
[10], weight
[20];
5656 fields
= sscanf (lpxstr
,
5657 "%99[^:]:%9[^:]:%9[^:]:%19s",
5658 name
, height
, width
, weight
);
5660 if (fields
== EOF
) return (FALSE
);
5664 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
5665 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
5669 lplogfont
->lfFaceName
[0] = 0;
5675 lplogfont
->lfHeight
= atoi (height
);
5680 lplogfont
->lfWidth
= atoi (width
);
5684 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5687 /* This makes TrueType fonts work better. */
5688 lplogfont
->lfHeight
= - abs (lplogfont
->lfHeight
);
5694 w32_font_match (lpszfont1
, lpszfont2
)
5698 char * s1
= lpszfont1
, *e1
, *w1
;
5699 char * s2
= lpszfont2
, *e2
, *w2
;
5701 if (s1
== NULL
|| s2
== NULL
) return (FALSE
);
5703 if (*s1
== '-') s1
++;
5704 if (*s2
== '-') s2
++;
5708 int len1
, len2
, len3
=0;
5710 e1
= strchr (s1
, '-');
5711 e2
= strchr (s2
, '-');
5712 w1
= strchr (s1
, '*');
5713 w2
= strchr (s2
, '*');
5726 if (w2
&& w2
< e2
&& ( len3
== 0 || (w2
- s2
) < len3
))
5729 /* Whole field is not a wildcard, and ...*/
5730 if (*s1
!= '*' && *s2
!= '*' && *s1
!= '-' && *s2
!= '-'
5731 /* Lengths are different and there are no wildcards, or ... */
5732 && ((len1
!= len2
&& len3
== 0) ||
5733 /* strings don't match up until first wildcard or end. */
5734 strnicmp (s1
, s2
, len3
> 0 ? len3
: len1
) != 0))
5737 if (e1
== NULL
|| e2
== NULL
)
5745 /* Callback functions, and a structure holding info they need, for
5746 listing system fonts on W32. We need one set of functions to do the
5747 job properly, but these don't work on NT 3.51 and earlier, so we
5748 have a second set which don't handle character sets properly to
5751 In both cases, there are two passes made. The first pass gets one
5752 font from each family, the second pass lists all the fonts from
5755 typedef struct enumfont_t
5760 XFontStruct
*size_ref
;
5761 Lisp_Object
*pattern
;
5766 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
5768 NEWTEXTMETRIC
* lptm
;
5772 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
5775 /* Check that the character set matches if it was specified */
5776 if (lpef
->logfont
.lfCharSet
!= DEFAULT_CHARSET
&&
5777 lplf
->elfLogFont
.lfCharSet
!= lpef
->logfont
.lfCharSet
)
5780 /* We want all fonts cached, so don't compare sizes just yet */
5781 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
5784 Lisp_Object width
= Qnil
;
5786 if (!NILP (*(lpef
->pattern
)) && FontType
!= RASTER_FONTTYPE
)
5788 /* Scalable fonts are as big as you want them to be. */
5789 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
5790 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
5792 /* Make sure the height used here is the same as everywhere
5793 else (ie character height, not cell height). */
5794 else if (lplf
->elfLogFont
.lfHeight
> 0)
5795 lplf
->elfLogFont
.lfHeight
= lptm
->tmInternalLeading
- lptm
->tmHeight
;
5797 /* The MaxCharWidth is not valid at this stage for scalable fonts. */
5798 if (FontType
== RASTER_FONTTYPE
)
5799 width
= make_number (lptm
->tmMaxCharWidth
);
5801 if (!w32_to_x_font (&(lplf
->elfLogFont
), buf
, 100))
5804 if (NILP (*(lpef
->pattern
))
5805 || w32_font_match (buf
, XSTRING (*(lpef
->pattern
))->data
))
5807 *lpef
->tail
= Fcons (Fcons (build_string (buf
), width
), Qnil
);
5808 lpef
->tail
= &(XCONS (*lpef
->tail
)->cdr
);
5817 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
5819 NEWTEXTMETRIC
* lptm
;
5823 return EnumFontFamilies (lpef
->hdc
,
5824 lplf
->elfLogFont
.lfFaceName
,
5825 (FONTENUMPROC
) enum_font_cb2
,
5831 enum_fontex_cb2 (lplf
, lptm
, font_type
, lpef
)
5832 ENUMLOGFONTEX
* lplf
;
5833 NEWTEXTMETRICEX
* lptm
;
5837 /* We are not interested in the extra info we get back from the 'Ex
5838 version - only the fact that we get character set variations
5839 enumerated seperately. */
5840 return enum_font_cb2 ((ENUMLOGFONT
*) lplf
, (NEWTEXTMETRIC
*) lptm
,
5845 enum_fontex_cb1 (lplf
, lptm
, font_type
, lpef
)
5846 ENUMLOGFONTEX
* lplf
;
5847 NEWTEXTMETRICEX
* lptm
;
5851 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
5852 FARPROC enum_font_families_ex
5853 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
5854 /* We don't really expect EnumFontFamiliesEx to disappear once we
5855 get here, so don't bother handling it gracefully. */
5856 if (enum_font_families_ex
== NULL
)
5857 error ("gdi32.dll has disappeared!");
5858 return enum_font_families_ex (lpef
->hdc
,
5860 (FONTENUMPROC
) enum_fontex_cb2
,
5864 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
5865 and xterm.c in Emacs 20.3) */
5867 Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
, int max_names
)
5869 char *fontname
, *ptnstr
;
5870 Lisp_Object list
, tem
, newlist
= Qnil
;
5873 list
= Vw32_bdf_filename_alist
;
5874 ptnstr
= XSTRING (pattern
)->data
;
5876 for ( ; CONSP (list
); list
= XCONS (list
)->cdr
)
5878 tem
= XCONS (list
)->car
;
5880 fontname
= XSTRING (XCONS (tem
)->car
)->data
;
5881 else if (STRINGP (tem
))
5882 fontname
= XSTRING (tem
)->data
;
5886 if (w32_font_match (fontname
, ptnstr
))
5888 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
5890 if (n_fonts
>= max_names
)
5898 Lisp_Object
w32_list_synthesized_fonts (FRAME_PTR f
, Lisp_Object pattern
,
5899 int size
, int max_names
);
5901 /* Return a list of names of available fonts matching PATTERN on frame
5902 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
5903 to be listed. Frame F NULL means we have not yet created any
5904 frame, which means we can't get proper size info, as we don't have
5905 a device context to use for GetTextMetrics.
5906 MAXNAMES sets a limit on how many fonts to match. */
5909 w32_list_fonts (FRAME_PTR f
, Lisp_Object pattern
, int size
, int maxnames
)
5911 Lisp_Object patterns
, key
, tem
, tpat
;
5912 Lisp_Object list
= Qnil
, newlist
= Qnil
, second_best
= Qnil
;
5913 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
5916 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
5917 if (NILP (patterns
))
5918 patterns
= Fcons (pattern
, Qnil
);
5920 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
5924 tpat
= XCONS (patterns
)->car
;
5926 /* See if we cached the result for this particular query.
5927 The cache is an alist of the form:
5928 ((PATTERN (FONTNAME . WIDTH) ...) ...)
5930 if (tem
= XCONS (dpyinfo
->name_list_element
)->cdr
,
5931 !NILP (list
= Fassoc (tpat
, tem
)))
5933 list
= Fcdr_safe (list
);
5934 /* We have a cached list. Don't have to get the list again. */
5939 /* At first, put PATTERN in the cache. */
5945 /* Use EnumFontFamiliesEx where it is available, as it knows
5946 about character sets. Fall back to EnumFontFamilies for
5947 older versions of NT that don't support the 'Ex function. */
5948 x_to_w32_font (STRINGP (tpat
) ? XSTRING (tpat
)->data
:
5951 LOGFONT font_match_pattern
;
5952 HMODULE gdi32
= GetModuleHandle ("gdi32.dll");
5953 FARPROC enum_font_families_ex
5954 = GetProcAddress ( gdi32
, "EnumFontFamiliesExA");
5956 /* We do our own pattern matching so we can handle wildcards. */
5957 font_match_pattern
.lfFaceName
[0] = 0;
5958 font_match_pattern
.lfPitchAndFamily
= 0;
5959 /* We can use the charset, because if it is a wildcard it will
5960 be DEFAULT_CHARSET anyway. */
5961 font_match_pattern
.lfCharSet
= ef
.logfont
.lfCharSet
;
5963 ef
.hdc
= GetDC (dpyinfo
->root_window
);
5965 if (enum_font_families_ex
)
5966 enum_font_families_ex (ef
.hdc
,
5967 &font_match_pattern
,
5968 (FONTENUMPROC
) enum_fontex_cb1
,
5971 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
,
5974 ReleaseDC (dpyinfo
->root_window
, ef
.hdc
);
5979 /* Make a list of the fonts we got back.
5980 Store that in the font cache for the display. */
5981 XCONS (dpyinfo
->name_list_element
)->cdr
5982 = Fcons (Fcons (tpat
, list
),
5983 XCONS (dpyinfo
->name_list_element
)->cdr
);
5986 if (NILP (list
)) continue; /* Try the remaining alternatives. */
5988 newlist
= second_best
= Qnil
;
5990 /* Make a list of the fonts that have the right width. */
5991 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
5994 tem
= XCONS (list
)->car
;
5998 if (NILP (XCONS (tem
)->car
))
6002 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6004 if (n_fonts
>= maxnames
)
6009 if (!INTEGERP (XCONS (tem
)->cdr
))
6011 /* Since we don't yet know the size of the font, we must
6012 load it and try GetTextMetrics. */
6013 W32FontStruct thisinfo
;
6018 if (!x_to_w32_font (XSTRING (XCONS (tem
)->car
)->data
, &lf
))
6022 thisinfo
.bdf
= NULL
;
6023 thisinfo
.hfont
= CreateFontIndirect (&lf
);
6024 if (thisinfo
.hfont
== NULL
)
6027 hdc
= GetDC (dpyinfo
->root_window
);
6028 oldobj
= SelectObject (hdc
, thisinfo
.hfont
);
6029 if (GetTextMetrics (hdc
, &thisinfo
.tm
))
6030 XCONS (tem
)->cdr
= make_number (FONT_WIDTH (&thisinfo
));
6032 XCONS (tem
)->cdr
= make_number (0);
6033 SelectObject (hdc
, oldobj
);
6034 ReleaseDC (dpyinfo
->root_window
, hdc
);
6035 DeleteObject(thisinfo
.hfont
);
6038 found_size
= XINT (XCONS (tem
)->cdr
);
6039 if (found_size
== size
)
6041 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6043 if (n_fonts
>= maxnames
)
6046 /* keep track of the closest matching size in case
6047 no exact match is found. */
6048 else if (found_size
> 0)
6050 if (NILP (second_best
))
6053 else if (found_size
< size
)
6055 if (XINT (XCONS (second_best
)->cdr
) > size
6056 || XINT (XCONS (second_best
)->cdr
) < found_size
)
6061 if (XINT (XCONS (second_best
)->cdr
) > size
6062 && XINT (XCONS (second_best
)->cdr
) >
6069 if (!NILP (newlist
))
6071 else if (!NILP (second_best
))
6073 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6078 /* Include any bdf fonts. */
6079 if (n_fonts
< maxnames
)
6081 Lisp_Object combined
[2];
6082 combined
[0] = w32_list_bdf_fonts (pattern
, maxnames
- n_fonts
);
6083 combined
[1] = newlist
;
6084 newlist
= Fnconc(2, combined
);
6087 /* If we can't find a font that matches, check if Windows would be
6088 able to synthesize it from a different style. */
6089 if (NILP (newlist
) && !NILP (Vw32_enable_italics
))
6090 newlist
= w32_list_synthesized_fonts (f
, pattern
, size
, maxnames
);
6096 w32_list_synthesized_fonts (f
, pattern
, size
, max_names
)
6098 Lisp_Object pattern
;
6103 char *full_pattn
, *new_pattn
, foundary
[50], family
[50], *pattn_part2
;
6104 char style
[20], slant
;
6105 Lisp_Object matches
, match
, tem
, synthed_matches
= Qnil
;
6107 full_pattn
= XSTRING (pattern
)->data
;
6109 pattn_part2
= alloca (XSTRING (pattern
)->size
);
6110 /* Allow some space for wildcard expansion. */
6111 new_pattn
= alloca (XSTRING (pattern
)->size
+ 100);
6113 fields
= sscanf (full_pattn
, "-%49[^-]-%49[^-]-%19[^-]-%c-%s",
6114 foundary
, family
, style
, &slant
, pattn_part2
);
6115 if (fields
== EOF
|| fields
< 5)
6118 /* If the style and slant are wildcards already there is no point
6119 checking again (and we don't want to keep recursing). */
6120 if (*style
== '*' && slant
== '*')
6123 sprintf (new_pattn
, "-%s-%s-*-*-%s", foundary
, family
, pattn_part2
);
6125 matches
= w32_list_fonts (f
, build_string (new_pattn
), size
, max_names
);
6127 for ( ; CONSP (matches
); matches
= XCONS (matches
)->cdr
)
6129 tem
= XCONS (matches
)->car
;
6133 full_pattn
= XSTRING (tem
)->data
;
6134 fields
= sscanf (full_pattn
, "-%49[^-]-%49[^-]-%*[^-]-%*c-%s",
6135 foundary
, family
, pattn_part2
);
6136 if (fields
== EOF
|| fields
< 3)
6139 sprintf (new_pattn
, "-%s-%s-%s-%c-%s", foundary
, family
, style
,
6140 slant
, pattn_part2
);
6142 synthed_matches
= Fcons (build_string (new_pattn
),
6146 return synthed_matches
;
6150 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6152 w32_get_font_info (f
, font_idx
)
6156 return (FRAME_W32_FONT_TABLE (f
) + font_idx
);
6161 w32_query_font (struct frame
*f
, char *fontname
)
6164 struct font_info
*pfi
;
6166 pfi
= FRAME_W32_FONT_TABLE (f
);
6168 for (i
= 0; i
< one_w32_display_info
.n_fonts
;i
++, pfi
++)
6170 if (strcmp(pfi
->name
, fontname
) == 0) return pfi
;
6176 /* Find a CCL program for a font specified by FONTP, and set the member
6177 `encoder' of the structure. */
6180 w32_find_ccl_program (fontp
)
6181 struct font_info
*fontp
;
6183 Lisp_Object list
, elt
;
6185 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCONS (list
)->cdr
)
6187 elt
= XCONS (list
)->car
;
6189 && STRINGP (XCONS (elt
)->car
)
6190 && (fast_c_string_match_ignore_case (XCONS (elt
)->car
, fontp
->name
)
6196 struct ccl_program
*ccl
6197 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6199 if (setup_ccl_program (ccl
, XCONS (elt
)->cdr
) < 0)
6202 fontp
->font_encoder
= ccl
;
6208 #include "x-list-font.c"
6210 DEFUN ("x-list-fonts", Fx_list_fonts
, Sx_list_fonts
, 1, 4, 0,
6211 "Return a list of the names of available fonts matching PATTERN.\n\
6212 If optional arguments FACE and FRAME are specified, return only fonts\n\
6213 the same size as FACE on FRAME.\n\
6215 PATTERN is a string, perhaps with wildcard characters;\n\
6216 the * character matches any substring, and\n\
6217 the ? character matches any single character.\n\
6218 PATTERN is case-insensitive.\n\
6219 FACE is a face name--a symbol.\n\
6221 The return value is a list of strings, suitable as arguments to\n\
6224 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
6225 even if they match PATTERN and FACE.\n\
6227 The optional fourth argument MAXIMUM sets a limit on how many\n\
6228 fonts to match. The first MAXIMUM fonts are reported.")
6229 (pattern
, face
, frame
, maximum
)
6230 Lisp_Object pattern
, face
, frame
, maximum
;
6235 XFontStruct
*size_ref
;
6236 Lisp_Object namelist
;
6241 CHECK_STRING (pattern
, 0);
6243 CHECK_SYMBOL (face
, 1);
6245 f
= check_x_frame (frame
);
6247 /* Determine the width standard for comparison with the fonts we find. */
6255 /* Don't die if we get called with a terminal frame. */
6256 if (! FRAME_W32_P (f
))
6257 error ("non-w32 frame used in `x-list-fonts'");
6259 face_id
= face_name_id_number (f
, face
);
6261 if (face_id
< 0 || face_id
>= FRAME_N_PARAM_FACES (f
)
6262 || FRAME_PARAM_FACES (f
) [face_id
] == 0)
6263 size_ref
= f
->output_data
.w32
->font
;
6266 size_ref
= FRAME_PARAM_FACES (f
) [face_id
]->font
;
6267 if (size_ref
== (XFontStruct
*) (~0))
6268 size_ref
= f
->output_data
.w32
->font
;
6272 /* See if we cached the result for this particular query. */
6273 list
= Fassoc (pattern
,
6274 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6276 /* We have info in the cache for this PATTERN. */
6279 Lisp_Object tem
, newlist
;
6281 /* We have info about this pattern. */
6282 list
= XCONS (list
)->cdr
;
6289 /* Filter the cached info and return just the fonts that match FACE. */
6291 for (tem
= list
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
6293 struct font_info
*fontinf
;
6294 XFontStruct
*thisinfo
= NULL
;
6296 fontinf
= w32_load_font (f
, XSTRING (XCONS (tem
)->car
)->data
, 0);
6298 thisinfo
= (XFontStruct
*)fontinf
->font
;
6299 if (thisinfo
&& same_size_fonts (thisinfo
, size_ref
))
6300 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6302 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
6313 ef
.pattern
= &pattern
;
6316 x_to_w32_font (STRINGP (pattern
) ? XSTRING (pattern
)->data
: NULL
, &ef
.logfont
);
6319 ef
.hdc
= GetDC (FRAME_W32_WINDOW (f
));
6321 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
, (LPARAM
)&ef
);
6323 ReleaseDC (FRAME_W32_WINDOW (f
), ef
.hdc
);
6333 /* Make a list of all the fonts we got back.
6334 Store that in the font cache for the display. */
6335 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
6336 = Fcons (Fcons (pattern
, namelist
),
6337 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6339 /* Make a list of the fonts that have the right width. */
6342 for (i
= 0; i
< ef
.numFonts
; i
++)
6350 struct font_info
*fontinf
;
6351 XFontStruct
*thisinfo
= NULL
;
6354 fontinf
= w32_load_font (f
, XSTRING (Fcar (cur
))->data
, 0);
6356 thisinfo
= (XFontStruct
*)fontinf
->font
;
6358 keeper
= thisinfo
&& same_size_fonts (thisinfo
, size_ref
);
6360 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
6365 list
= Fcons (build_string (XSTRING (Fcar (cur
))->data
), list
);
6369 list
= Fnreverse (list
);
6376 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts
, Sw32_find_bdf_fonts
,
6378 "Return a list of BDF fonts in DIR, suitable for appending to\n\
6379 w32-bdf-filename-alist. Fonts which do not contain an xfld description\n\
6380 will not be included in the list. DIR may be a list of directories.")
6382 Lisp_Object directory
;
6384 Lisp_Object list
= Qnil
;
6385 struct gcpro gcpro1
, gcpro2
;
6387 if (!CONSP (directory
))
6388 return w32_find_bdf_fonts_in_dir (directory
);
6390 for ( ; CONSP (directory
); directory
= XCONS (directory
)->cdr
)
6392 Lisp_Object pair
[2];
6395 GCPRO2 (directory
, list
);
6396 pair
[1] = w32_find_bdf_fonts_in_dir( XCONS (directory
)->car
);
6397 list
= Fnconc( 2, pair
);
6403 /* Find BDF files in a specified directory. (use GCPRO when calling,
6404 as this calls lisp to get a directory listing). */
6405 Lisp_Object
w32_find_bdf_fonts_in_dir( Lisp_Object directory
)
6407 Lisp_Object filelist
, list
= Qnil
;
6410 if (!STRINGP(directory
))
6413 filelist
= Fdirectory_files (directory
, Qt
,
6414 build_string (".*\\.[bB][dD][fF]"), Qt
);
6416 for ( ; CONSP(filelist
); filelist
= XCONS (filelist
)->cdr
)
6418 Lisp_Object filename
= XCONS (filelist
)->car
;
6419 if (w32_BDF_to_x_font (XSTRING (filename
)->data
, fontname
, 100))
6420 store_in_alist (&list
, build_string (fontname
), filename
);
6426 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
6427 "Return non-nil if color COLOR is supported on frame FRAME.\n\
6428 If FRAME is omitted or nil, use the selected frame.")
6430 Lisp_Object color
, frame
;
6433 FRAME_PTR f
= check_x_frame (frame
);
6435 CHECK_STRING (color
, 1);
6437 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6443 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
6444 "Return a description of the color named COLOR on frame FRAME.\n\
6445 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
6446 These values appear to range from 0 to 65280 or 65535, depending\n\
6447 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
6448 If FRAME is omitted or nil, use the selected frame.")
6450 Lisp_Object color
, frame
;
6453 FRAME_PTR f
= check_x_frame (frame
);
6455 CHECK_STRING (color
, 1);
6457 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6461 rgb
[0] = make_number ((GetRValue (foo
) << 8) | GetRValue (foo
));
6462 rgb
[1] = make_number ((GetGValue (foo
) << 8) | GetGValue (foo
));
6463 rgb
[2] = make_number ((GetBValue (foo
) << 8) | GetBValue (foo
));
6464 return Flist (3, rgb
);
6470 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
6471 "Return t if the X display supports color.\n\
6472 The optional argument DISPLAY specifies which display to ask about.\n\
6473 DISPLAY should be either a frame or a display name (a string).\n\
6474 If omitted or nil, that stands for the selected frame's display.")
6476 Lisp_Object display
;
6478 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6480 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
6486 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
6488 "Return t if the X display supports shades of gray.\n\
6489 Note that color displays do support shades of gray.\n\
6490 The optional argument DISPLAY specifies which display to ask about.\n\
6491 DISPLAY should be either a frame or a display name (a string).\n\
6492 If omitted or nil, that stands for the selected frame's display.")
6494 Lisp_Object display
;
6496 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6498 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
6504 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
6506 "Returns the width in pixels of the X display DISPLAY.\n\
6507 The optional argument DISPLAY specifies which display to ask about.\n\
6508 DISPLAY should be either a frame or a display name (a string).\n\
6509 If omitted or nil, that stands for the selected frame's display.")
6511 Lisp_Object display
;
6513 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6515 return make_number (dpyinfo
->width
);
6518 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
6519 Sx_display_pixel_height
, 0, 1, 0,
6520 "Returns the height in pixels of the X display DISPLAY.\n\
6521 The optional argument DISPLAY specifies which display to ask about.\n\
6522 DISPLAY should be either a frame or a display name (a string).\n\
6523 If omitted or nil, that stands for the selected frame's display.")
6525 Lisp_Object display
;
6527 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6529 return make_number (dpyinfo
->height
);
6532 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
6534 "Returns the number of bitplanes of the display DISPLAY.\n\
6535 The optional argument DISPLAY specifies which display to ask about.\n\
6536 DISPLAY should be either a frame or a display name (a string).\n\
6537 If omitted or nil, that stands for the selected frame's display.")
6539 Lisp_Object display
;
6541 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6543 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
6546 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
6548 "Returns the number of color cells of the display DISPLAY.\n\
6549 The optional argument DISPLAY specifies which display to ask about.\n\
6550 DISPLAY should be either a frame or a display name (a string).\n\
6551 If omitted or nil, that stands for the selected frame's display.")
6553 Lisp_Object display
;
6555 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6559 hdc
= GetDC (dpyinfo
->root_window
);
6560 if (dpyinfo
->has_palette
)
6561 cap
= GetDeviceCaps (hdc
,SIZEPALETTE
);
6563 cap
= GetDeviceCaps (hdc
,NUMCOLORS
);
6565 ReleaseDC (dpyinfo
->root_window
, hdc
);
6567 return make_number (cap
);
6570 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
6571 Sx_server_max_request_size
,
6573 "Returns the maximum request size of the server of display DISPLAY.\n\
6574 The optional argument DISPLAY specifies which display to ask about.\n\
6575 DISPLAY should be either a frame or a display name (a string).\n\
6576 If omitted or nil, that stands for the selected frame's display.")
6578 Lisp_Object display
;
6580 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6582 return make_number (1);
6585 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
6586 "Returns the vendor ID string of the W32 system (Microsoft).\n\
6587 The optional argument DISPLAY specifies which display to ask about.\n\
6588 DISPLAY should be either a frame or a display name (a string).\n\
6589 If omitted or nil, that stands for the selected frame's display.")
6591 Lisp_Object display
;
6593 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6594 char *vendor
= "Microsoft Corp.";
6596 if (! vendor
) vendor
= "";
6597 return build_string (vendor
);
6600 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
6601 "Returns the version numbers of the server of display DISPLAY.\n\
6602 The value is a list of three integers: the major and minor\n\
6603 version numbers, and the vendor-specific release\n\
6604 number. See also the function `x-server-vendor'.\n\n\
6605 The optional argument DISPLAY specifies which display to ask about.\n\
6606 DISPLAY should be either a frame or a display name (a string).\n\
6607 If omitted or nil, that stands for the selected frame's display.")
6609 Lisp_Object display
;
6611 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6613 return Fcons (make_number (w32_major_version
),
6614 Fcons (make_number (w32_minor_version
), Qnil
));
6617 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
6618 "Returns the number of screens on the server of display DISPLAY.\n\
6619 The optional argument DISPLAY specifies which display to ask about.\n\
6620 DISPLAY should be either a frame or a display name (a string).\n\
6621 If omitted or nil, that stands for the selected frame's display.")
6623 Lisp_Object display
;
6625 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6627 return make_number (1);
6630 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
6631 "Returns the height in millimeters of the X display DISPLAY.\n\
6632 The optional argument DISPLAY specifies which display to ask about.\n\
6633 DISPLAY should be either a frame or a display name (a string).\n\
6634 If omitted or nil, that stands for the selected frame's display.")
6636 Lisp_Object display
;
6638 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6642 hdc
= GetDC (dpyinfo
->root_window
);
6644 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
6646 ReleaseDC (dpyinfo
->root_window
, hdc
);
6648 return make_number (cap
);
6651 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
6652 "Returns the width in millimeters of the X display DISPLAY.\n\
6653 The optional argument DISPLAY specifies which display to ask about.\n\
6654 DISPLAY should be either a frame or a display name (a string).\n\
6655 If omitted or nil, that stands for the selected frame's display.")
6657 Lisp_Object display
;
6659 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6664 hdc
= GetDC (dpyinfo
->root_window
);
6666 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
6668 ReleaseDC (dpyinfo
->root_window
, hdc
);
6670 return make_number (cap
);
6673 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
6674 Sx_display_backing_store
, 0, 1, 0,
6675 "Returns an indication of whether display DISPLAY does backing store.\n\
6676 The value may be `always', `when-mapped', or `not-useful'.\n\
6677 The optional argument DISPLAY specifies which display to ask about.\n\
6678 DISPLAY should be either a frame or a display name (a string).\n\
6679 If omitted or nil, that stands for the selected frame's display.")
6681 Lisp_Object display
;
6683 return intern ("not-useful");
6686 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
6687 Sx_display_visual_class
, 0, 1, 0,
6688 "Returns the visual class of the display DISPLAY.\n\
6689 The value is one of the symbols `static-gray', `gray-scale',\n\
6690 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
6691 The optional argument DISPLAY specifies which display to ask about.\n\
6692 DISPLAY should be either a frame or a display name (a string).\n\
6693 If omitted or nil, that stands for the selected frame's display.")
6695 Lisp_Object display
;
6697 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6700 switch (dpyinfo
->visual
->class)
6702 case StaticGray
: return (intern ("static-gray"));
6703 case GrayScale
: return (intern ("gray-scale"));
6704 case StaticColor
: return (intern ("static-color"));
6705 case PseudoColor
: return (intern ("pseudo-color"));
6706 case TrueColor
: return (intern ("true-color"));
6707 case DirectColor
: return (intern ("direct-color"));
6709 error ("Display has an unknown visual class");
6713 error ("Display has an unknown visual class");
6716 DEFUN ("x-display-save-under", Fx_display_save_under
,
6717 Sx_display_save_under
, 0, 1, 0,
6718 "Returns t if the display DISPLAY supports the save-under feature.\n\
6719 The optional argument DISPLAY specifies which display to ask about.\n\
6720 DISPLAY should be either a frame or a display name (a string).\n\
6721 If omitted or nil, that stands for the selected frame's display.")
6723 Lisp_Object display
;
6725 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6732 register struct frame
*f
;
6734 return PIXEL_WIDTH (f
);
6739 register struct frame
*f
;
6741 return PIXEL_HEIGHT (f
);
6746 register struct frame
*f
;
6748 return FONT_WIDTH (f
->output_data
.w32
->font
);
6753 register struct frame
*f
;
6755 return f
->output_data
.w32
->line_height
;
6759 x_screen_planes (frame
)
6762 return (FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
*
6763 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
);
6766 /* Return the display structure for the display named NAME.
6767 Open a new connection if necessary. */
6769 struct w32_display_info
*
6770 x_display_info_for_name (name
)
6774 struct w32_display_info
*dpyinfo
;
6776 CHECK_STRING (name
, 0);
6778 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
6780 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
6783 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
6788 /* Use this general default value to start with. */
6789 Vx_resource_name
= Vinvocation_name
;
6791 validate_x_resource_name ();
6793 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
6794 (char *) XSTRING (Vx_resource_name
)->data
);
6797 error ("Cannot connect to server %s", XSTRING (name
)->data
);
6800 XSETFASTINT (Vwindow_system_version
, 3);
6805 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
6806 1, 3, 0, "Open a connection to a server.\n\
6807 DISPLAY is the name of the display to connect to.\n\
6808 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
6809 If the optional third arg MUST-SUCCEED is non-nil,\n\
6810 terminate Emacs if we can't open the connection.")
6811 (display
, xrm_string
, must_succeed
)
6812 Lisp_Object display
, xrm_string
, must_succeed
;
6814 unsigned int n_planes
;
6815 unsigned char *xrm_option
;
6816 struct w32_display_info
*dpyinfo
;
6818 CHECK_STRING (display
, 0);
6819 if (! NILP (xrm_string
))
6820 CHECK_STRING (xrm_string
, 1);
6822 if (! EQ (Vwindow_system
, intern ("w32")))
6823 error ("Not using Microsoft Windows");
6825 /* Allow color mapping to be defined externally; first look in user's
6826 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
6828 Lisp_Object color_file
;
6829 struct gcpro gcpro1
;
6831 color_file
= build_string("~/rgb.txt");
6833 GCPRO1 (color_file
);
6835 if (NILP (Ffile_readable_p (color_file
)))
6837 Fexpand_file_name (build_string ("rgb.txt"),
6838 Fsymbol_value (intern ("data-directory")));
6840 Vw32_color_map
= Fw32_load_color_file (color_file
);
6844 if (NILP (Vw32_color_map
))
6845 Vw32_color_map
= Fw32_default_color_map ();
6847 if (! NILP (xrm_string
))
6848 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
6850 xrm_option
= (unsigned char *) 0;
6852 /* Use this general default value to start with. */
6853 /* First remove .exe suffix from invocation-name - it looks ugly. */
6855 char basename
[ MAX_PATH
], *str
;
6857 strcpy (basename
, XSTRING (Vinvocation_name
)->data
);
6858 str
= strrchr (basename
, '.');
6860 Vinvocation_name
= build_string (basename
);
6862 Vx_resource_name
= Vinvocation_name
;
6864 validate_x_resource_name ();
6866 /* This is what opens the connection and sets x_current_display.
6867 This also initializes many symbols, such as those used for input. */
6868 dpyinfo
= w32_term_init (display
, xrm_option
,
6869 (char *) XSTRING (Vx_resource_name
)->data
);
6873 if (!NILP (must_succeed
))
6874 fatal ("Cannot connect to server %s.\n",
6875 XSTRING (display
)->data
);
6877 error ("Cannot connect to server %s", XSTRING (display
)->data
);
6882 XSETFASTINT (Vwindow_system_version
, 3);
6886 DEFUN ("x-close-connection", Fx_close_connection
,
6887 Sx_close_connection
, 1, 1, 0,
6888 "Close the connection to DISPLAY's server.\n\
6889 For DISPLAY, specify either a frame or a display name (a string).\n\
6890 If DISPLAY is nil, that stands for the selected frame's display.")
6892 Lisp_Object display
;
6894 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6895 struct w32_display_info
*tail
;
6898 if (dpyinfo
->reference_count
> 0)
6899 error ("Display still has frames on it");
6902 /* Free the fonts in the font table. */
6903 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6905 if (dpyinfo
->font_table
[i
].name
)
6906 free (dpyinfo
->font_table
[i
].name
);
6907 /* Don't free the full_name string;
6908 it is always shared with something else. */
6909 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
6911 x_destroy_all_bitmaps (dpyinfo
);
6913 x_delete_display (dpyinfo
);
6919 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
6920 "Return the list of display names that Emacs has connections to.")
6923 Lisp_Object tail
, result
;
6926 for (tail
= w32_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
6927 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
6932 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
6933 "If ON is non-nil, report errors as soon as the erring request is made.\n\
6934 If ON is nil, allow buffering of requests.\n\
6935 This is a noop on W32 systems.\n\
6936 The optional second argument DISPLAY specifies which display to act on.\n\
6937 DISPLAY should be either a frame or a display name (a string).\n\
6938 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
6940 Lisp_Object display
, on
;
6942 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6948 /* These are the w32 specialized functions */
6950 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 1, 0,
6951 "This will display the W32 font dialog and return an X font string corresponding to the selection.")
6955 FRAME_PTR f
= check_x_frame (frame
);
6963 bzero (&cf
, sizeof (cf
));
6964 bzero (&lf
, sizeof (lf
));
6966 cf
.lStructSize
= sizeof (cf
);
6967 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
6968 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
| CF_SCREENFONTS
;
6971 /* Initialize as much of the font details as we can from the current
6973 hdc
= GetDC (FRAME_W32_WINDOW (f
));
6974 oldobj
= SelectObject (hdc
, FRAME_FONT (f
)->hfont
);
6975 GetTextFace (hdc
, LF_FACESIZE
, lf
.lfFaceName
);
6976 if (GetTextMetrics (hdc
, &tm
))
6978 lf
.lfHeight
= tm
.tmInternalLeading
- tm
.tmHeight
;
6979 lf
.lfWeight
= tm
.tmWeight
;
6980 lf
.lfItalic
= tm
.tmItalic
;
6981 lf
.lfUnderline
= tm
.tmUnderlined
;
6982 lf
.lfStrikeOut
= tm
.tmStruckOut
;
6983 lf
.lfPitchAndFamily
= tm
.tmPitchAndFamily
;
6984 lf
.lfCharSet
= tm
.tmCharSet
;
6985 cf
.Flags
|= CF_INITTOLOGFONTSTRUCT
;
6987 SelectObject (hdc
, oldobj
);
6988 ReleaseDC (FRAME_W32_WINDOW(f
), hdc
);
6990 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100))
6993 return build_string (buf
);
6996 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
, Sw32_send_sys_command
, 1, 2, 0,
6997 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\
6998 Some useful values for command are 0xf030 to maximise frame (0xf020\n\
6999 to minimize), 0xf120 to restore frame to original size, and 0xf100\n\
7000 to activate the menubar for keyboard access. 0xf140 activates the\n\
7001 screen saver if defined.\n\
7003 If optional parameter FRAME is not specified, use selected frame.")
7005 Lisp_Object command
, frame
;
7008 FRAME_PTR f
= check_x_frame (frame
);
7010 CHECK_NUMBER (command
, 0);
7012 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
7017 DEFUN ("w32-shell-execute", Fw32_shell_execute
, Sw32_shell_execute
, 2, 4, 0,
7018 "Get Windows to perform OPERATION on DOCUMENT.\n\
7019 This is a wrapper around the ShellExecute system function, which\n\
7020 invokes the application registered to handle OPERATION for DOCUMENT.\n\
7021 OPERATION is typically \"open\", \"print\" or \"explore\", and DOCUMENT\n\
7022 is typically the name of a document file or URL, but can also be a\n\
7023 program executable to run or a directory to open in the Windows Explorer.\n\
7025 If DOCUMENT is a program executable, PARAMETERS can be a list of command\n\
7026 line parameters, but otherwise should be nil.\n\
7028 SHOW-FLAG can be used to control whether the invoked application is hidden\n\
7029 or minimized. If SHOw-FLAG is nil, the application is displayed normally,\n\
7030 otherwise it is an integer representing a ShowWindow flag:\n\
7033 1 - start normally\n\
7034 3 - start maximized\n\
7035 6 - start minimized")
7036 (operation
, document
, parameters
, show_flag
)
7037 Lisp_Object operation
, document
, parameters
, show_flag
;
7039 Lisp_Object current_dir
;
7041 CHECK_STRING (operation
, 0);
7042 CHECK_STRING (document
, 0);
7044 /* Encode filename and current directory. */
7045 current_dir
= ENCODE_FILE (current_buffer
->directory
);
7046 document
= ENCODE_FILE (document
);
7047 if ((int) ShellExecute (NULL
,
7048 XSTRING (operation
)->data
,
7049 XSTRING (document
)->data
,
7050 (STRINGP (parameters
) ?
7051 XSTRING (parameters
)->data
: NULL
),
7052 XSTRING (current_dir
)->data
,
7053 (INTEGERP (show_flag
) ?
7054 XINT (show_flag
) : SW_SHOWDEFAULT
))
7057 error ("ShellExecute failed");
7060 /* Lookup virtual keycode from string representing the name of a
7061 non-ascii keystroke into the corresponding virtual key, using
7062 lispy_function_keys. */
7064 lookup_vk_code (char *key
)
7068 for (i
= 0; i
< 256; i
++)
7069 if (lispy_function_keys
[i
] != 0
7070 && strcmp (lispy_function_keys
[i
], key
) == 0)
7076 /* Convert a one-element vector style key sequence to a hot key
7079 w32_parse_hot_key (key
)
7082 /* Copied from Fdefine_key and store_in_keymap. */
7083 register Lisp_Object c
;
7087 struct gcpro gcpro1
;
7089 CHECK_VECTOR (key
, 0);
7091 if (XFASTINT (Flength (key
)) != 1)
7096 c
= Faref (key
, make_number (0));
7098 if (CONSP (c
) && lucid_event_type_list_p (c
))
7099 c
= Fevent_convert_list (c
);
7103 if (! INTEGERP (c
) && ! SYMBOLP (c
))
7104 error ("Key definition is invalid");
7106 /* Work out the base key and the modifiers. */
7109 c
= parse_modifiers (c
);
7110 lisp_modifiers
= Fcar (Fcdr (c
));
7114 vk_code
= lookup_vk_code (XSYMBOL (c
)->name
->data
);
7116 else if (INTEGERP (c
))
7118 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
7119 /* Many ascii characters are their own virtual key code. */
7120 vk_code
= XINT (c
) & CHARACTERBITS
;
7123 if (vk_code
< 0 || vk_code
> 255)
7126 if ((lisp_modifiers
& meta_modifier
) != 0
7127 && !NILP (Vw32_alt_is_meta
))
7128 lisp_modifiers
|= alt_modifier
;
7130 /* Convert lisp modifiers to Windows hot-key form. */
7131 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
7132 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
7133 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
7134 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
7136 return HOTKEY (vk_code
, w32_modifiers
);
7139 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
, Sw32_register_hot_key
, 1, 1, 0,
7140 "Register KEY as a hot-key combination.\n\
7141 Certain key combinations like Alt-Tab are reserved for system use on\n\
7142 Windows, and therefore are normally intercepted by the system. However,\n\
7143 most of these key combinations can be received by registering them as\n\
7144 hot-keys, overriding their special meaning.\n\
7146 KEY must be a one element key definition in vector form that would be\n\
7147 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta\n\
7148 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper\n\
7149 is always interpreted as the Windows modifier keys.\n\
7151 The return value is the hotkey-id if registered, otherwise nil.")
7155 key
= w32_parse_hot_key (key
);
7157 if (NILP (Fmemq (key
, w32_grabbed_keys
)))
7159 /* Reuse an empty slot if possible. */
7160 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
7162 /* Safe to add new key to list, even if we have focus. */
7164 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
7168 /* Notify input thread about new hot-key definition, so that it
7169 takes effect without needing to switch focus. */
7170 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
7177 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
, Sw32_unregister_hot_key
, 1, 1, 0,
7178 "Unregister HOTKEY as a hot-key combination.")
7184 if (!INTEGERP (key
))
7185 key
= w32_parse_hot_key (key
);
7187 item
= Fmemq (key
, w32_grabbed_keys
);
7191 /* Notify input thread about hot-key definition being removed, so
7192 that it takes effect without needing focus switch. */
7193 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
7194 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
7197 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
7204 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
, Sw32_registered_hot_keys
, 0, 0, 0,
7205 "Return list of registered hot-key IDs.")
7208 return Fcopy_sequence (w32_grabbed_keys
);
7211 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
, Sw32_reconstruct_hot_key
, 1, 1, 0,
7212 "Convert hot-key ID to a lisp key combination.")
7214 Lisp_Object hotkeyid
;
7216 int vk_code
, w32_modifiers
;
7219 CHECK_NUMBER (hotkeyid
, 0);
7221 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
7222 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
7224 if (lispy_function_keys
[vk_code
])
7225 key
= intern (lispy_function_keys
[vk_code
]);
7227 key
= make_number (vk_code
);
7229 key
= Fcons (key
, Qnil
);
7230 if (w32_modifiers
& MOD_SHIFT
)
7231 key
= Fcons (Qshift
, key
);
7232 if (w32_modifiers
& MOD_CONTROL
)
7233 key
= Fcons (Qctrl
, key
);
7234 if (w32_modifiers
& MOD_ALT
)
7235 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
7236 if (w32_modifiers
& MOD_WIN
)
7237 key
= Fcons (Qhyper
, key
);
7242 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
, Sw32_toggle_lock_key
, 1, 2, 0,
7243 "Toggle the state of the lock key KEY.\n\
7244 KEY can be `capslock', `kp-numlock', or `scroll'.\n\
7245 If the optional parameter NEW-STATE is a number, then the state of KEY\n\
7246 is set to off if the low bit of NEW-STATE is zero, otherwise on.")
7248 Lisp_Object key
, new_state
;
7253 if (EQ (key
, intern ("capslock")))
7254 vk_code
= VK_CAPITAL
;
7255 else if (EQ (key
, intern ("kp-numlock")))
7256 vk_code
= VK_NUMLOCK
;
7257 else if (EQ (key
, intern ("scroll")))
7258 vk_code
= VK_SCROLL
;
7262 if (!dwWindowsThreadId
)
7263 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
7265 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
7266 (WPARAM
) vk_code
, (LPARAM
) new_state
))
7269 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
7270 return make_number (msg
.wParam
);
7277 /* This is zero if not using MS-Windows. */
7280 /* The section below is built by the lisp expression at the top of the file,
7281 just above where these variables are declared. */
7282 /*&&& init symbols here &&&*/
7283 Qauto_raise
= intern ("auto-raise");
7284 staticpro (&Qauto_raise
);
7285 Qauto_lower
= intern ("auto-lower");
7286 staticpro (&Qauto_lower
);
7287 Qbackground_color
= intern ("background-color");
7288 staticpro (&Qbackground_color
);
7289 Qbar
= intern ("bar");
7291 Qborder_color
= intern ("border-color");
7292 staticpro (&Qborder_color
);
7293 Qborder_width
= intern ("border-width");
7294 staticpro (&Qborder_width
);
7295 Qbox
= intern ("box");
7297 Qcursor_color
= intern ("cursor-color");
7298 staticpro (&Qcursor_color
);
7299 Qcursor_type
= intern ("cursor-type");
7300 staticpro (&Qcursor_type
);
7301 Qforeground_color
= intern ("foreground-color");
7302 staticpro (&Qforeground_color
);
7303 Qgeometry
= intern ("geometry");
7304 staticpro (&Qgeometry
);
7305 Qicon_left
= intern ("icon-left");
7306 staticpro (&Qicon_left
);
7307 Qicon_top
= intern ("icon-top");
7308 staticpro (&Qicon_top
);
7309 Qicon_type
= intern ("icon-type");
7310 staticpro (&Qicon_type
);
7311 Qicon_name
= intern ("icon-name");
7312 staticpro (&Qicon_name
);
7313 Qinternal_border_width
= intern ("internal-border-width");
7314 staticpro (&Qinternal_border_width
);
7315 Qleft
= intern ("left");
7317 Qright
= intern ("right");
7318 staticpro (&Qright
);
7319 Qmouse_color
= intern ("mouse-color");
7320 staticpro (&Qmouse_color
);
7321 Qnone
= intern ("none");
7323 Qparent_id
= intern ("parent-id");
7324 staticpro (&Qparent_id
);
7325 Qscroll_bar_width
= intern ("scroll-bar-width");
7326 staticpro (&Qscroll_bar_width
);
7327 Qsuppress_icon
= intern ("suppress-icon");
7328 staticpro (&Qsuppress_icon
);
7329 Qtop
= intern ("top");
7331 Qundefined_color
= intern ("undefined-color");
7332 staticpro (&Qundefined_color
);
7333 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
7334 staticpro (&Qvertical_scroll_bars
);
7335 Qvisibility
= intern ("visibility");
7336 staticpro (&Qvisibility
);
7337 Qwindow_id
= intern ("window-id");
7338 staticpro (&Qwindow_id
);
7339 Qx_frame_parameter
= intern ("x-frame-parameter");
7340 staticpro (&Qx_frame_parameter
);
7341 Qx_resource_name
= intern ("x-resource-name");
7342 staticpro (&Qx_resource_name
);
7343 Quser_position
= intern ("user-position");
7344 staticpro (&Quser_position
);
7345 Quser_size
= intern ("user-size");
7346 staticpro (&Quser_size
);
7347 Qdisplay
= intern ("display");
7348 staticpro (&Qdisplay
);
7349 /* This is the end of symbol initialization. */
7351 Qhyper
= intern ("hyper");
7352 staticpro (&Qhyper
);
7353 Qsuper
= intern ("super");
7354 staticpro (&Qsuper
);
7355 Qmeta
= intern ("meta");
7357 Qalt
= intern ("alt");
7359 Qctrl
= intern ("ctrl");
7361 Qcontrol
= intern ("control");
7362 staticpro (&Qcontrol
);
7363 Qshift
= intern ("shift");
7364 staticpro (&Qshift
);
7366 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
7367 staticpro (&Qface_set_after_frame_default
);
7369 Fput (Qundefined_color
, Qerror_conditions
,
7370 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
7371 Fput (Qundefined_color
, Qerror_message
,
7372 build_string ("Undefined color"));
7374 staticpro (&w32_grabbed_keys
);
7375 w32_grabbed_keys
= Qnil
;
7377 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
7378 "An array of color name mappings for windows.");
7379 Vw32_color_map
= Qnil
;
7381 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
7382 "Non-nil if alt key presses are passed on to Windows.\n\
7383 When non-nil, for example, alt pressed and released and then space will\n\
7384 open the System menu. When nil, Emacs silently swallows alt key events.");
7385 Vw32_pass_alt_to_system
= Qnil
;
7387 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
7388 "Non-nil if the alt key is to be considered the same as the meta key.\n\
7389 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
7390 Vw32_alt_is_meta
= Qt
;
7392 DEFVAR_INT ("w32-quit-key", &Vw32_quit_key
,
7393 "If non-zero, the virtual key code for an alternative quit key.");
7394 XSETINT (Vw32_quit_key
, 0);
7396 DEFVAR_LISP ("w32-pass-lwindow-to-system",
7397 &Vw32_pass_lwindow_to_system
,
7398 "Non-nil if the left \"Windows\" key is passed on to Windows.\n\
7399 When non-nil, the Start menu is opened by tapping the key.");
7400 Vw32_pass_lwindow_to_system
= Qt
;
7402 DEFVAR_LISP ("w32-pass-rwindow-to-system",
7403 &Vw32_pass_rwindow_to_system
,
7404 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\
7405 When non-nil, the Start menu is opened by tapping the key.");
7406 Vw32_pass_rwindow_to_system
= Qt
;
7408 DEFVAR_INT ("w32-phantom-key-code",
7409 &Vw32_phantom_key_code
,
7410 "Virtual key code used to generate \"phantom\" key presses.\n\
7411 Value is a number between 0 and 255.\n\
7413 Phantom key presses are generated in order to stop the system from\n\
7414 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or\n\
7415 `w32-pass-rwindow-to-system' is nil.");
7416 /* Although 255 is technically not a valid key code, it works and
7417 means that this hack won't interfere with any real key code. */
7418 Vw32_phantom_key_code
= 255;
7420 DEFVAR_LISP ("w32-enable-num-lock",
7421 &Vw32_enable_num_lock
,
7422 "Non-nil if Num Lock should act normally.\n\
7423 Set to nil to see Num Lock as the key `kp-numlock'.");
7424 Vw32_enable_num_lock
= Qt
;
7426 DEFVAR_LISP ("w32-enable-caps-lock",
7427 &Vw32_enable_caps_lock
,
7428 "Non-nil if Caps Lock should act normally.\n\
7429 Set to nil to see Caps Lock as the key `capslock'.");
7430 Vw32_enable_caps_lock
= Qt
;
7432 DEFVAR_LISP ("w32-scroll-lock-modifier",
7433 &Vw32_scroll_lock_modifier
,
7434 "Modifier to use for the Scroll Lock on state.\n\
7435 The value can be hyper, super, meta, alt, control or shift for the\n\
7436 respective modifier, or nil to see Scroll Lock as the key `scroll'.\n\
7437 Any other value will cause the key to be ignored.");
7438 Vw32_scroll_lock_modifier
= Qt
;
7440 DEFVAR_LISP ("w32-lwindow-modifier",
7441 &Vw32_lwindow_modifier
,
7442 "Modifier to use for the left \"Windows\" key.\n\
7443 The value can be hyper, super, meta, alt, control or shift for the\n\
7444 respective modifier, or nil to appear as the key `lwindow'.\n\
7445 Any other value will cause the key to be ignored.");
7446 Vw32_lwindow_modifier
= Qnil
;
7448 DEFVAR_LISP ("w32-rwindow-modifier",
7449 &Vw32_rwindow_modifier
,
7450 "Modifier to use for the right \"Windows\" key.\n\
7451 The value can be hyper, super, meta, alt, control or shift for the\n\
7452 respective modifier, or nil to appear as the key `rwindow'.\n\
7453 Any other value will cause the key to be ignored.");
7454 Vw32_rwindow_modifier
= Qnil
;
7456 DEFVAR_LISP ("w32-apps-modifier",
7457 &Vw32_apps_modifier
,
7458 "Modifier to use for the \"Apps\" key.\n\
7459 The value can be hyper, super, meta, alt, control or shift for the\n\
7460 respective modifier, or nil to appear as the key `apps'.\n\
7461 Any other value will cause the key to be ignored.");
7462 Vw32_apps_modifier
= Qnil
;
7464 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics
,
7465 "Non-nil enables selection of artificially italicized fonts.");
7466 Vw32_enable_italics
= Qnil
;
7468 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
7469 "Non-nil enables Windows palette management to map colors exactly.");
7470 Vw32_enable_palette
= Qt
;
7472 DEFVAR_INT ("w32-mouse-button-tolerance",
7473 &Vw32_mouse_button_tolerance
,
7474 "Analogue of double click interval for faking middle mouse events.\n\
7475 The value is the minimum time in milliseconds that must elapse between\n\
7476 left/right button down events before they are considered distinct events.\n\
7477 If both mouse buttons are depressed within this interval, a middle mouse\n\
7478 button down event is generated instead.");
7479 XSETINT (Vw32_mouse_button_tolerance
, GetDoubleClickTime () / 2);
7481 DEFVAR_INT ("w32-mouse-move-interval",
7482 &Vw32_mouse_move_interval
,
7483 "Minimum interval between mouse move events.\n\
7484 The value is the minimum time in milliseconds that must elapse between\n\
7485 successive mouse move (or scroll bar drag) events before they are\n\
7486 reported as lisp events.");
7487 XSETINT (Vw32_mouse_move_interval
, 0);
7489 init_x_parm_symbols ();
7491 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7492 "List of directories to search for bitmap files for w32.");
7493 Vx_bitmap_file_path
= decode_env_path ((char *) 0, "PATH");
7495 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
7496 "The shape of the pointer when over text.\n\
7497 Changing the value does not affect existing frames\n\
7498 unless you set the mouse color.");
7499 Vx_pointer_shape
= Qnil
;
7501 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
7502 "The name Emacs uses to look up resources; for internal use only.\n\
7503 `x-get-resource' uses this as the first component of the instance name\n\
7504 when requesting resource values.\n\
7505 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
7506 was invoked, or to the value specified with the `-name' or `-rn'\n\
7507 switches, if present.");
7508 Vx_resource_name
= Qnil
;
7510 Vx_nontext_pointer_shape
= Qnil
;
7512 Vx_mode_pointer_shape
= Qnil
;
7514 DEFVAR_INT ("x-sensitive-text-pointer-shape",
7515 &Vx_sensitive_text_pointer_shape
,
7516 "The shape of the pointer when over mouse-sensitive text.\n\
7517 This variable takes effect when you create a new frame\n\
7518 or when you set the mouse color.");
7519 Vx_sensitive_text_pointer_shape
= Qnil
;
7521 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
7522 "A string indicating the foreground color of the cursor box.");
7523 Vx_cursor_fore_pixel
= Qnil
;
7525 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
7526 "Non-nil if no window manager is in use.\n\
7527 Emacs doesn't try to figure this out; this is always nil\n\
7528 unless you set it to something else.");
7529 /* We don't have any way to find this out, so set it to nil
7530 and maybe the user would like to set it to t. */
7531 Vx_no_window_manager
= Qnil
;
7533 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7534 &Vx_pixel_size_width_font_regexp
,
7535 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
7537 Since Emacs gets width of a font matching with this regexp from\n\
7538 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
7539 such a font. This is especially effective for such large fonts as\n\
7540 Chinese, Japanese, and Korean.");
7541 Vx_pixel_size_width_font_regexp
= Qnil
;
7543 DEFVAR_LISP ("w32-bdf-filename-alist",
7544 &Vw32_bdf_filename_alist
,
7545 "List of bdf fonts and their corresponding filenames.");
7546 Vw32_bdf_filename_alist
= Qnil
;
7548 DEFVAR_BOOL ("w32-strict-fontnames",
7549 &w32_strict_fontnames
,
7550 "Non-nil means only use fonts that are exact matches for those requested.\n\
7551 Default is nil, which allows old fontnames that are not XLFD compliant,\n\
7552 and allows third-party CJK display to work by specifying false charset\n\
7553 fields to trick Emacs into translating to Big5, SJIS etc.\n\
7554 Setting this to t will prevent wrong fonts being selected when\n\
7555 fontsets are automatically created.");
7556 w32_strict_fontnames
= 0;
7558 DEFVAR_BOOL ("w32-strict-painting",
7559 &w32_strict_painting
,
7560 "Non-nil means use strict rules for repainting frames.\n\
7561 Set this to nil to get the old behaviour for repainting; this should\n\
7562 only be necessary if the default setting causes problems.");
7563 w32_strict_painting
= 1;
7565 DEFVAR_LISP ("w32-system-coding-system",
7566 &Vw32_system_coding_system
,
7567 "Coding system used by Windows system functions, such as for font names.");
7568 Vw32_system_coding_system
= Qnil
;
7570 defsubr (&Sx_get_resource
);
7571 defsubr (&Sx_list_fonts
);
7572 defsubr (&Sx_display_color_p
);
7573 defsubr (&Sx_display_grayscale_p
);
7574 defsubr (&Sx_color_defined_p
);
7575 defsubr (&Sx_color_values
);
7576 defsubr (&Sx_server_max_request_size
);
7577 defsubr (&Sx_server_vendor
);
7578 defsubr (&Sx_server_version
);
7579 defsubr (&Sx_display_pixel_width
);
7580 defsubr (&Sx_display_pixel_height
);
7581 defsubr (&Sx_display_mm_width
);
7582 defsubr (&Sx_display_mm_height
);
7583 defsubr (&Sx_display_screens
);
7584 defsubr (&Sx_display_planes
);
7585 defsubr (&Sx_display_color_cells
);
7586 defsubr (&Sx_display_visual_class
);
7587 defsubr (&Sx_display_backing_store
);
7588 defsubr (&Sx_display_save_under
);
7589 defsubr (&Sx_parse_geometry
);
7590 defsubr (&Sx_create_frame
);
7591 defsubr (&Sx_open_connection
);
7592 defsubr (&Sx_close_connection
);
7593 defsubr (&Sx_display_list
);
7594 defsubr (&Sx_synchronize
);
7596 /* W32 specific functions */
7598 defsubr (&Sw32_focus_frame
);
7599 defsubr (&Sw32_select_font
);
7600 defsubr (&Sw32_define_rgb_color
);
7601 defsubr (&Sw32_default_color_map
);
7602 defsubr (&Sw32_load_color_file
);
7603 defsubr (&Sw32_send_sys_command
);
7604 defsubr (&Sw32_shell_execute
);
7605 defsubr (&Sw32_register_hot_key
);
7606 defsubr (&Sw32_unregister_hot_key
);
7607 defsubr (&Sw32_registered_hot_keys
);
7608 defsubr (&Sw32_reconstruct_hot_key
);
7609 defsubr (&Sw32_toggle_lock_key
);
7610 defsubr (&Sw32_find_bdf_fonts
);
7612 /* Setting callback functions for fontset handler. */
7613 get_font_info_func
= w32_get_font_info
;
7614 list_fonts_func
= w32_list_fonts
;
7615 load_font_func
= w32_load_font
;
7616 find_ccl_program_func
= w32_find_ccl_program
;
7617 query_font_func
= w32_query_font
;
7618 set_frame_fontset_func
= x_set_font
;
7619 check_window_system_func
= check_w32
;
7628 button
= MessageBox (NULL
,
7629 "A fatal error has occurred!\n\n"
7630 "Select Abort to exit, Retry to debug, Ignore to continue",
7631 "Emacs Abort Dialog",
7632 MB_ICONEXCLAMATION
| MB_TASKMODAL
7633 | MB_SETFOREGROUND
| MB_ABORTRETRYIGNORE
);
7648 /* For convenience when debugging. */
7652 return GetLastError ();