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"
49 extern void free_frame_menubar ();
50 extern struct scroll_bar
*x_window_to_scroll_bar ();
51 extern int w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
);
54 extern char *lispy_function_keys
[];
56 /* The colormap for converting color names to RGB values */
57 Lisp_Object Vw32_color_map
;
59 /* Non nil if alt key presses are passed on to Windows. */
60 Lisp_Object Vw32_pass_alt_to_system
;
62 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
64 Lisp_Object Vw32_alt_is_meta
;
66 /* Non nil if left window key events are passed on to Windows (this only
67 affects whether "tapping" the key opens the Start menu). */
68 Lisp_Object Vw32_pass_lwindow_to_system
;
70 /* Non nil if right window key events are passed on to Windows (this
71 only affects whether "tapping" the key opens the Start menu). */
72 Lisp_Object Vw32_pass_rwindow_to_system
;
74 /* Virtual key code used to generate "phantom" key presses in order
75 to stop system from acting on Windows key events. */
76 Lisp_Object Vw32_phantom_key_code
;
78 /* Modifier associated with the left "Windows" key, or nil to act as a
80 Lisp_Object Vw32_lwindow_modifier
;
82 /* Modifier associated with the right "Windows" key, or nil to act as a
84 Lisp_Object Vw32_rwindow_modifier
;
86 /* Modifier associated with the "Apps" key, or nil to act as a normal
88 Lisp_Object Vw32_apps_modifier
;
90 /* Value is nil if Num Lock acts as a function key. */
91 Lisp_Object Vw32_enable_num_lock
;
93 /* Value is nil if Caps Lock acts as a function key. */
94 Lisp_Object Vw32_enable_caps_lock
;
96 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
97 Lisp_Object Vw32_scroll_lock_modifier
;
99 /* Switch to control whether we inhibit requests for italicised fonts (which
100 are synthesized, look ugly, and are trashed by cursor movement under NT). */
101 Lisp_Object Vw32_enable_italics
;
103 /* Enable palette management. */
104 Lisp_Object Vw32_enable_palette
;
106 /* Control how close left/right button down events must be to
107 be converted to a middle button down event. */
108 Lisp_Object Vw32_mouse_button_tolerance
;
110 /* Minimum interval between mouse movement (and scroll bar drag)
111 events that are passed on to the event loop. */
112 Lisp_Object Vw32_mouse_move_interval
;
114 /* The name we're using in resource queries. */
115 Lisp_Object Vx_resource_name
;
117 /* Non nil if no window manager is in use. */
118 Lisp_Object Vx_no_window_manager
;
120 /* The background and shape of the mouse pointer, and shape when not
121 over text or in the modeline. */
122 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
123 /* The shape when over mouse-sensitive text. */
124 Lisp_Object Vx_sensitive_text_pointer_shape
;
126 /* Color of chars displayed in cursor box. */
127 Lisp_Object Vx_cursor_fore_pixel
;
129 /* Nonzero if using Windows. */
130 static int w32_in_use
;
132 /* Search path for bitmap files. */
133 Lisp_Object Vx_bitmap_file_path
;
135 /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
136 Lisp_Object Vx_pixel_size_width_font_regexp
;
138 /* Alist of bdf fonts and the files that define them. */
139 Lisp_Object Vw32_bdf_filename_alist
;
141 /* A flag to control how to display unibyte 8-bit character. */
142 int unibyte_display_via_language_environment
;
144 /* Evaluate this expression to rebuild the section of syms_of_w32fns
145 that initializes and staticpros the symbols declared below. Note
146 that Emacs 18 has a bug that keeps C-x C-e from being able to
147 evaluate this expression.
150 ;; Accumulate a list of the symbols we want to initialize from the
151 ;; declarations at the top of the file.
152 (goto-char (point-min))
153 (search-forward "/\*&&& symbols declared here &&&*\/\n")
155 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
157 (cons (buffer-substring (match-beginning 1) (match-end 1))
160 (setq symbol-list (nreverse symbol-list))
161 ;; Delete the section of syms_of_... where we initialize the symbols.
162 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
163 (let ((start (point)))
164 (while (looking-at "^ Q")
166 (kill-region start (point)))
167 ;; Write a new symbol initialization section.
169 (insert (format " %s = intern (\"" (car symbol-list)))
170 (let ((start (point)))
171 (insert (substring (car symbol-list) 1))
172 (subst-char-in-region start (point) ?_ ?-))
173 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
174 (setq symbol-list (cdr symbol-list)))))
178 /*&&& symbols declared here &&&*/
179 Lisp_Object Qauto_raise
;
180 Lisp_Object Qauto_lower
;
181 Lisp_Object Qbackground_color
;
183 Lisp_Object Qborder_color
;
184 Lisp_Object Qborder_width
;
186 Lisp_Object Qcursor_color
;
187 Lisp_Object Qcursor_type
;
188 Lisp_Object Qforeground_color
;
189 Lisp_Object Qgeometry
;
190 Lisp_Object Qicon_left
;
191 Lisp_Object Qicon_top
;
192 Lisp_Object Qicon_type
;
193 Lisp_Object Qicon_name
;
194 Lisp_Object Qinternal_border_width
;
197 Lisp_Object Qmouse_color
;
199 Lisp_Object Qparent_id
;
200 Lisp_Object Qscroll_bar_width
;
201 Lisp_Object Qsuppress_icon
;
203 Lisp_Object Qundefined_color
;
204 Lisp_Object Qvertical_scroll_bars
;
205 Lisp_Object Qvisibility
;
206 Lisp_Object Qwindow_id
;
207 Lisp_Object Qx_frame_parameter
;
208 Lisp_Object Qx_resource_name
;
209 Lisp_Object Quser_position
;
210 Lisp_Object Quser_size
;
211 Lisp_Object Qdisplay
;
218 Lisp_Object Qcontrol
;
221 /* State variables for emulating a three button mouse. */
226 static int button_state
= 0;
227 static W32Msg saved_mouse_button_msg
;
228 static unsigned mouse_button_timer
; /* non-zero when timer is active */
229 static W32Msg saved_mouse_move_msg
;
230 static unsigned mouse_move_timer
;
232 /* W95 mousewheel handler */
233 unsigned int msh_mousewheel
= 0;
235 #define MOUSE_BUTTON_ID 1
236 #define MOUSE_MOVE_ID 2
238 /* The below are defined in frame.c. */
239 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
240 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
242 extern Lisp_Object Vwindow_system_version
;
244 Lisp_Object Qface_set_after_frame_default
;
246 extern Lisp_Object last_mouse_scroll_bar
;
247 extern int last_mouse_scroll_bar_pos
;
249 /* From w32term.c. */
250 extern Lisp_Object Vw32_num_mouse_buttons
;
251 extern Lisp_Object Vw32_recognize_altgr
;
254 /* Error if we are not connected to MS-Windows. */
259 error ("MS-Windows not in use or not initialized");
262 /* Nonzero if we can use mouse menus.
263 You should not call this unless HAVE_MENUS is defined. */
271 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
272 and checking validity for W32. */
275 check_x_frame (frame
)
284 CHECK_LIVE_FRAME (frame
, 0);
287 if (! FRAME_W32_P (f
))
288 error ("non-w32 frame used");
292 /* Let the user specify an display with a frame.
293 nil stands for the selected frame--or, if that is not a w32 frame,
294 the first display on the list. */
296 static struct w32_display_info
*
297 check_x_display_info (frame
)
302 if (FRAME_W32_P (selected_frame
))
303 return FRAME_W32_DISPLAY_INFO (selected_frame
);
305 return &one_w32_display_info
;
307 else if (STRINGP (frame
))
308 return x_display_info_for_name (frame
);
313 CHECK_LIVE_FRAME (frame
, 0);
315 if (! FRAME_W32_P (f
))
316 error ("non-w32 frame used");
317 return FRAME_W32_DISPLAY_INFO (f
);
321 /* Return the Emacs frame-object corresponding to an w32 window.
322 It could be the frame's main window or an icon window. */
324 /* This function can be called during GC, so use GC_xxx type test macros. */
327 x_window_to_frame (dpyinfo
, wdesc
)
328 struct w32_display_info
*dpyinfo
;
331 Lisp_Object tail
, frame
;
334 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
336 frame
= XCONS (tail
)->car
;
337 if (!GC_FRAMEP (frame
))
340 if (f
->output_data
.nothing
== 1
341 || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
343 if (FRAME_W32_WINDOW (f
) == wdesc
)
351 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
352 id, which is just an int that this section returns. Bitmaps are
353 reference counted so they can be shared among frames.
355 Bitmap indices are guaranteed to be > 0, so a negative number can
356 be used to indicate no bitmap.
358 If you use x_create_bitmap_from_data, then you must keep track of
359 the bitmaps yourself. That is, creating a bitmap from the same
360 data more than once will not be caught. */
363 /* Functions to access the contents of a bitmap, given an id. */
366 x_bitmap_height (f
, id
)
370 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
374 x_bitmap_width (f
, id
)
378 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
382 x_bitmap_pixmap (f
, id
)
386 return (int) FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
390 /* Allocate a new bitmap record. Returns index of new record. */
393 x_allocate_bitmap_record (f
)
396 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
399 if (dpyinfo
->bitmaps
== NULL
)
401 dpyinfo
->bitmaps_size
= 10;
403 = (struct w32_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
404 dpyinfo
->bitmaps_last
= 1;
408 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
409 return ++dpyinfo
->bitmaps_last
;
411 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
412 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
415 dpyinfo
->bitmaps_size
*= 2;
417 = (struct w32_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
418 dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
419 return ++dpyinfo
->bitmaps_last
;
422 /* Add one reference to the reference count of the bitmap with id ID. */
425 x_reference_bitmap (f
, id
)
429 ++FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
432 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
435 x_create_bitmap_from_data (f
, bits
, width
, height
)
438 unsigned int width
, height
;
440 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
444 bitmap
= CreateBitmap (width
, height
,
445 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
446 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
452 id
= x_allocate_bitmap_record (f
);
453 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
454 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
455 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
456 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
457 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
458 dpyinfo
->bitmaps
[id
- 1].height
= height
;
459 dpyinfo
->bitmaps
[id
- 1].width
= width
;
464 /* Create bitmap from file FILE for frame F. */
467 x_create_bitmap_from_file (f
, file
)
473 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
474 unsigned int width
, height
;
476 int xhot
, yhot
, result
, id
;
482 /* Look for an existing bitmap with the same name. */
483 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
485 if (dpyinfo
->bitmaps
[id
].refcount
486 && dpyinfo
->bitmaps
[id
].file
487 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
489 ++dpyinfo
->bitmaps
[id
].refcount
;
494 /* Search bitmap-file-path for the file, if appropriate. */
495 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
498 /* LoadLibraryEx won't handle special files handled by Emacs handler. */
503 filename
= (char *) XSTRING (found
)->data
;
505 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
511 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
512 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
513 if (result
!= BitmapSuccess
)
516 id
= x_allocate_bitmap_record (f
);
517 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
518 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
519 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (XSTRING (file
)->size
+ 1);
520 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
521 dpyinfo
->bitmaps
[id
- 1].height
= height
;
522 dpyinfo
->bitmaps
[id
- 1].width
= width
;
523 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
529 /* Remove reference to bitmap with id number ID. */
532 x_destroy_bitmap (f
, id
)
536 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
540 --dpyinfo
->bitmaps
[id
- 1].refcount
;
541 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
544 DeleteObject (dpyinfo
->bitmaps
[id
- 1].pixmap
);
545 if (dpyinfo
->bitmaps
[id
- 1].file
)
547 free (dpyinfo
->bitmaps
[id
- 1].file
);
548 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
555 /* Free all the bitmaps for the display specified by DPYINFO. */
558 x_destroy_all_bitmaps (dpyinfo
)
559 struct w32_display_info
*dpyinfo
;
562 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
563 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
565 DeleteObject (dpyinfo
->bitmaps
[i
].pixmap
);
566 if (dpyinfo
->bitmaps
[i
].file
)
567 free (dpyinfo
->bitmaps
[i
].file
);
569 dpyinfo
->bitmaps_last
= 0;
572 /* Connect the frame-parameter names for W32 frames
573 to the ways of passing the parameter values to the window system.
575 The name of a parameter, as a Lisp symbol,
576 has an `x-frame-parameter' property which is an integer in Lisp
577 but can be interpreted as an `enum x_frame_parm' in C. */
581 X_PARM_FOREGROUND_COLOR
,
582 X_PARM_BACKGROUND_COLOR
,
589 X_PARM_INTERNAL_BORDER_WIDTH
,
593 X_PARM_VERT_SCROLL_BAR
,
595 X_PARM_MENU_BAR_LINES
599 struct x_frame_parm_table
602 void (*setter
)( /* struct frame *frame, Lisp_Object val, oldval */ );
605 void x_set_foreground_color ();
606 void x_set_background_color ();
607 void x_set_mouse_color ();
608 void x_set_cursor_color ();
609 void x_set_border_color ();
610 void x_set_cursor_type ();
611 void x_set_icon_type ();
612 void x_set_icon_name ();
614 void x_set_border_width ();
615 void x_set_internal_border_width ();
616 void x_explicitly_set_name ();
617 void x_set_autoraise ();
618 void x_set_autolower ();
619 void x_set_vertical_scroll_bars ();
620 void x_set_visibility ();
621 void x_set_menu_bar_lines ();
622 void x_set_scroll_bar_width ();
624 void x_set_unsplittable ();
626 static struct x_frame_parm_table x_frame_parms
[] =
628 "auto-raise", x_set_autoraise
,
629 "auto-lower", x_set_autolower
,
630 "background-color", x_set_background_color
,
631 "border-color", x_set_border_color
,
632 "border-width", x_set_border_width
,
633 "cursor-color", x_set_cursor_color
,
634 "cursor-type", x_set_cursor_type
,
636 "foreground-color", x_set_foreground_color
,
637 "icon-name", x_set_icon_name
,
638 "icon-type", x_set_icon_type
,
639 "internal-border-width", x_set_internal_border_width
,
640 "menu-bar-lines", x_set_menu_bar_lines
,
641 "mouse-color", x_set_mouse_color
,
642 "name", x_explicitly_set_name
,
643 "scroll-bar-width", x_set_scroll_bar_width
,
644 "title", x_set_title
,
645 "unsplittable", x_set_unsplittable
,
646 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
647 "visibility", x_set_visibility
,
650 /* Attach the `x-frame-parameter' properties to
651 the Lisp symbol names of parameters relevant to W32. */
653 init_x_parm_symbols ()
657 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
658 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
662 /* Change the parameters of FRAME as specified by ALIST.
663 If a parameter is not specially recognized, do nothing;
664 otherwise call the `x_set_...' function for that parameter. */
667 x_set_frame_parameters (f
, alist
)
673 /* If both of these parameters are present, it's more efficient to
674 set them both at once. So we wait until we've looked at the
675 entire list before we set them. */
679 Lisp_Object left
, top
;
681 /* Same with these. */
682 Lisp_Object icon_left
, icon_top
;
684 /* Record in these vectors all the parms specified. */
688 int left_no_change
= 0, top_no_change
= 0;
689 int icon_left_no_change
= 0, icon_top_no_change
= 0;
692 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
695 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
696 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
698 /* Extract parm names and values into those vectors. */
701 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
703 Lisp_Object elt
, prop
, val
;
706 parms
[i
] = Fcar (elt
);
707 values
[i
] = Fcdr (elt
);
711 top
= left
= Qunbound
;
712 icon_left
= icon_top
= Qunbound
;
714 /* Provide default values for HEIGHT and WIDTH. */
715 width
= FRAME_WIDTH (f
);
716 height
= FRAME_HEIGHT (f
);
718 /* Now process them in reverse of specified order. */
719 for (i
--; i
>= 0; i
--)
721 Lisp_Object prop
, val
;
726 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
727 width
= XFASTINT (val
);
728 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
729 height
= XFASTINT (val
);
730 else if (EQ (prop
, Qtop
))
732 else if (EQ (prop
, Qleft
))
734 else if (EQ (prop
, Qicon_top
))
736 else if (EQ (prop
, Qicon_left
))
740 register Lisp_Object param_index
, old_value
;
742 param_index
= Fget (prop
, Qx_frame_parameter
);
743 old_value
= get_frame_param (f
, prop
);
744 store_frame_param (f
, prop
, val
);
745 if (NATNUMP (param_index
)
746 && (XFASTINT (param_index
)
747 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
748 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
752 /* Don't die if just one of these was set. */
753 if (EQ (left
, Qunbound
))
756 if (f
->output_data
.w32
->left_pos
< 0)
757 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->left_pos
), Qnil
));
759 XSETINT (left
, f
->output_data
.w32
->left_pos
);
761 if (EQ (top
, Qunbound
))
764 if (f
->output_data
.w32
->top_pos
< 0)
765 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->top_pos
), Qnil
));
767 XSETINT (top
, f
->output_data
.w32
->top_pos
);
770 /* If one of the icon positions was not set, preserve or default it. */
771 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
773 icon_left_no_change
= 1;
774 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
775 if (NILP (icon_left
))
776 XSETINT (icon_left
, 0);
778 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
780 icon_top_no_change
= 1;
781 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
783 XSETINT (icon_top
, 0);
786 /* Don't set these parameters unless they've been explicitly
787 specified. The window might be mapped or resized while we're in
788 this function, and we don't want to override that unless the lisp
789 code has asked for it.
791 Don't set these parameters unless they actually differ from the
792 window's current parameters; the window may not actually exist
797 check_frame_size (f
, &height
, &width
);
799 XSETFRAME (frame
, f
);
801 if (XINT (width
) != FRAME_WIDTH (f
)
802 || XINT (height
) != FRAME_HEIGHT (f
))
803 Fset_frame_size (frame
, make_number (width
), make_number (height
));
805 if ((!NILP (left
) || !NILP (top
))
806 && ! (left_no_change
&& top_no_change
)
807 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.w32
->left_pos
808 && NUMBERP (top
) && XINT (top
) == f
->output_data
.w32
->top_pos
))
813 /* Record the signs. */
814 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
815 if (EQ (left
, Qminus
))
816 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
817 else if (INTEGERP (left
))
819 leftpos
= XINT (left
);
821 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
823 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
824 && CONSP (XCONS (left
)->cdr
)
825 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
827 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
828 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
830 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
831 && CONSP (XCONS (left
)->cdr
)
832 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
834 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
837 if (EQ (top
, Qminus
))
838 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
839 else if (INTEGERP (top
))
843 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
845 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
846 && CONSP (XCONS (top
)->cdr
)
847 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
849 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
850 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
852 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
853 && CONSP (XCONS (top
)->cdr
)
854 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
856 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
860 /* Store the numeric value of the position. */
861 f
->output_data
.w32
->top_pos
= toppos
;
862 f
->output_data
.w32
->left_pos
= leftpos
;
864 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
866 /* Actually set that position, and convert to absolute. */
867 x_set_offset (f
, leftpos
, toppos
, -1);
870 if ((!NILP (icon_left
) || !NILP (icon_top
))
871 && ! (icon_left_no_change
&& icon_top_no_change
))
872 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
876 /* Store the screen positions of frame F into XPTR and YPTR.
877 These are the positions of the containing window manager window,
878 not Emacs's own window. */
881 x_real_positions (f
, xptr
, yptr
)
890 GetClientRect(FRAME_W32_WINDOW(f
), &rect
);
891 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
, FRAME_EXTERNAL_MENU_BAR(f
));
897 ClientToScreen (FRAME_W32_WINDOW(f
), &pt
);
903 /* Insert a description of internally-recorded parameters of frame X
904 into the parameter alist *ALISTPTR that is to be given to the user.
905 Only parameters that are specific to W32
906 and whose values are not correctly recorded in the frame's
907 param_alist need to be considered here. */
909 x_report_frame_params (f
, alistptr
)
911 Lisp_Object
*alistptr
;
916 /* Represent negative positions (off the top or left screen edge)
917 in a way that Fmodify_frame_parameters will understand correctly. */
918 XSETINT (tem
, f
->output_data
.w32
->left_pos
);
919 if (f
->output_data
.w32
->left_pos
>= 0)
920 store_in_alist (alistptr
, Qleft
, tem
);
922 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
924 XSETINT (tem
, f
->output_data
.w32
->top_pos
);
925 if (f
->output_data
.w32
->top_pos
>= 0)
926 store_in_alist (alistptr
, Qtop
, tem
);
928 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
930 store_in_alist (alistptr
, Qborder_width
,
931 make_number (f
->output_data
.w32
->border_width
));
932 store_in_alist (alistptr
, Qinternal_border_width
,
933 make_number (f
->output_data
.w32
->internal_border_width
));
934 sprintf (buf
, "%ld", (long) FRAME_W32_WINDOW (f
));
935 store_in_alist (alistptr
, Qwindow_id
,
937 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
938 FRAME_SAMPLE_VISIBILITY (f
);
939 store_in_alist (alistptr
, Qvisibility
,
940 (FRAME_VISIBLE_P (f
) ? Qt
941 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
942 store_in_alist (alistptr
, Qdisplay
,
943 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->car
);
947 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
, Sw32_define_rgb_color
, 4, 4, 0,
948 "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
949 This adds or updates a named color to w32-color-map, making it available for use.\n\
950 The original entry's RGB ref is returned, or nil if the entry is new.")
951 (red
, green
, blue
, name
)
952 Lisp_Object red
, green
, blue
, name
;
955 Lisp_Object oldrgb
= Qnil
;
958 CHECK_NUMBER (red
, 0);
959 CHECK_NUMBER (green
, 0);
960 CHECK_NUMBER (blue
, 0);
961 CHECK_STRING (name
, 0);
963 XSET (rgb
, Lisp_Int
, RGB(XUINT (red
), XUINT (green
), XUINT (blue
)));
967 /* replace existing entry in w32-color-map or add new entry. */
968 entry
= Fassoc (name
, Vw32_color_map
);
971 entry
= Fcons (name
, rgb
);
972 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
976 oldrgb
= Fcdr (entry
);
977 Fsetcdr (entry
, rgb
);
985 DEFUN ("w32-load-color-file", Fw32_load_color_file
, Sw32_load_color_file
, 1, 1, 0,
986 "Create an alist of color entries from an external file (ie. rgb.txt).\n\
987 Assign this value to w32-color-map to replace the existing color map.\n\
989 The file should define one named RGB color per line like so:\
991 where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
993 Lisp_Object filename
;
996 Lisp_Object cmap
= Qnil
;
999 CHECK_STRING (filename
, 0);
1000 abspath
= Fexpand_file_name (filename
, Qnil
);
1002 fp
= fopen (XSTRING (filename
)->data
, "rt");
1006 int red
, green
, blue
;
1011 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
1012 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
1014 char *name
= buf
+ num
;
1015 num
= strlen (name
) - 1;
1016 if (name
[num
] == '\n')
1018 cmap
= Fcons (Fcons (build_string (name
),
1019 make_number (RGB (red
, green
, blue
))),
1031 /* The default colors for the w32 color map */
1032 typedef struct colormap_t
1038 colormap_t w32_color_map
[] =
1040 {"snow" , PALETTERGB (255,250,250)},
1041 {"ghost white" , PALETTERGB (248,248,255)},
1042 {"GhostWhite" , PALETTERGB (248,248,255)},
1043 {"white smoke" , PALETTERGB (245,245,245)},
1044 {"WhiteSmoke" , PALETTERGB (245,245,245)},
1045 {"gainsboro" , PALETTERGB (220,220,220)},
1046 {"floral white" , PALETTERGB (255,250,240)},
1047 {"FloralWhite" , PALETTERGB (255,250,240)},
1048 {"old lace" , PALETTERGB (253,245,230)},
1049 {"OldLace" , PALETTERGB (253,245,230)},
1050 {"linen" , PALETTERGB (250,240,230)},
1051 {"antique white" , PALETTERGB (250,235,215)},
1052 {"AntiqueWhite" , PALETTERGB (250,235,215)},
1053 {"papaya whip" , PALETTERGB (255,239,213)},
1054 {"PapayaWhip" , PALETTERGB (255,239,213)},
1055 {"blanched almond" , PALETTERGB (255,235,205)},
1056 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
1057 {"bisque" , PALETTERGB (255,228,196)},
1058 {"peach puff" , PALETTERGB (255,218,185)},
1059 {"PeachPuff" , PALETTERGB (255,218,185)},
1060 {"navajo white" , PALETTERGB (255,222,173)},
1061 {"NavajoWhite" , PALETTERGB (255,222,173)},
1062 {"moccasin" , PALETTERGB (255,228,181)},
1063 {"cornsilk" , PALETTERGB (255,248,220)},
1064 {"ivory" , PALETTERGB (255,255,240)},
1065 {"lemon chiffon" , PALETTERGB (255,250,205)},
1066 {"LemonChiffon" , PALETTERGB (255,250,205)},
1067 {"seashell" , PALETTERGB (255,245,238)},
1068 {"honeydew" , PALETTERGB (240,255,240)},
1069 {"mint cream" , PALETTERGB (245,255,250)},
1070 {"MintCream" , PALETTERGB (245,255,250)},
1071 {"azure" , PALETTERGB (240,255,255)},
1072 {"alice blue" , PALETTERGB (240,248,255)},
1073 {"AliceBlue" , PALETTERGB (240,248,255)},
1074 {"lavender" , PALETTERGB (230,230,250)},
1075 {"lavender blush" , PALETTERGB (255,240,245)},
1076 {"LavenderBlush" , PALETTERGB (255,240,245)},
1077 {"misty rose" , PALETTERGB (255,228,225)},
1078 {"MistyRose" , PALETTERGB (255,228,225)},
1079 {"white" , PALETTERGB (255,255,255)},
1080 {"black" , PALETTERGB ( 0, 0, 0)},
1081 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1082 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1083 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1084 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1085 {"dim gray" , PALETTERGB (105,105,105)},
1086 {"DimGray" , PALETTERGB (105,105,105)},
1087 {"dim grey" , PALETTERGB (105,105,105)},
1088 {"DimGrey" , PALETTERGB (105,105,105)},
1089 {"slate gray" , PALETTERGB (112,128,144)},
1090 {"SlateGray" , PALETTERGB (112,128,144)},
1091 {"slate grey" , PALETTERGB (112,128,144)},
1092 {"SlateGrey" , PALETTERGB (112,128,144)},
1093 {"light slate gray" , PALETTERGB (119,136,153)},
1094 {"LightSlateGray" , PALETTERGB (119,136,153)},
1095 {"light slate grey" , PALETTERGB (119,136,153)},
1096 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1097 {"gray" , PALETTERGB (190,190,190)},
1098 {"grey" , PALETTERGB (190,190,190)},
1099 {"light grey" , PALETTERGB (211,211,211)},
1100 {"LightGrey" , PALETTERGB (211,211,211)},
1101 {"light gray" , PALETTERGB (211,211,211)},
1102 {"LightGray" , PALETTERGB (211,211,211)},
1103 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1104 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1105 {"navy" , PALETTERGB ( 0, 0,128)},
1106 {"navy blue" , PALETTERGB ( 0, 0,128)},
1107 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1108 {"cornflower blue" , PALETTERGB (100,149,237)},
1109 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1110 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1111 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1112 {"slate blue" , PALETTERGB (106, 90,205)},
1113 {"SlateBlue" , PALETTERGB (106, 90,205)},
1114 {"medium slate blue" , PALETTERGB (123,104,238)},
1115 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1116 {"light slate blue" , PALETTERGB (132,112,255)},
1117 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1118 {"medium blue" , PALETTERGB ( 0, 0,205)},
1119 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1120 {"royal blue" , PALETTERGB ( 65,105,225)},
1121 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1122 {"blue" , PALETTERGB ( 0, 0,255)},
1123 {"dodger blue" , PALETTERGB ( 30,144,255)},
1124 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1125 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1126 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1127 {"sky blue" , PALETTERGB (135,206,235)},
1128 {"SkyBlue" , PALETTERGB (135,206,235)},
1129 {"light sky blue" , PALETTERGB (135,206,250)},
1130 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1131 {"steel blue" , PALETTERGB ( 70,130,180)},
1132 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1133 {"light steel blue" , PALETTERGB (176,196,222)},
1134 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1135 {"light blue" , PALETTERGB (173,216,230)},
1136 {"LightBlue" , PALETTERGB (173,216,230)},
1137 {"powder blue" , PALETTERGB (176,224,230)},
1138 {"PowderBlue" , PALETTERGB (176,224,230)},
1139 {"pale turquoise" , PALETTERGB (175,238,238)},
1140 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1141 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1142 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1143 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1144 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1145 {"turquoise" , PALETTERGB ( 64,224,208)},
1146 {"cyan" , PALETTERGB ( 0,255,255)},
1147 {"light cyan" , PALETTERGB (224,255,255)},
1148 {"LightCyan" , PALETTERGB (224,255,255)},
1149 {"cadet blue" , PALETTERGB ( 95,158,160)},
1150 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1151 {"medium aquamarine" , PALETTERGB (102,205,170)},
1152 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1153 {"aquamarine" , PALETTERGB (127,255,212)},
1154 {"dark green" , PALETTERGB ( 0,100, 0)},
1155 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1156 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1157 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1158 {"dark sea green" , PALETTERGB (143,188,143)},
1159 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1160 {"sea green" , PALETTERGB ( 46,139, 87)},
1161 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1162 {"medium sea green" , PALETTERGB ( 60,179,113)},
1163 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1164 {"light sea green" , PALETTERGB ( 32,178,170)},
1165 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1166 {"pale green" , PALETTERGB (152,251,152)},
1167 {"PaleGreen" , PALETTERGB (152,251,152)},
1168 {"spring green" , PALETTERGB ( 0,255,127)},
1169 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1170 {"lawn green" , PALETTERGB (124,252, 0)},
1171 {"LawnGreen" , PALETTERGB (124,252, 0)},
1172 {"green" , PALETTERGB ( 0,255, 0)},
1173 {"chartreuse" , PALETTERGB (127,255, 0)},
1174 {"medium spring green" , PALETTERGB ( 0,250,154)},
1175 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1176 {"green yellow" , PALETTERGB (173,255, 47)},
1177 {"GreenYellow" , PALETTERGB (173,255, 47)},
1178 {"lime green" , PALETTERGB ( 50,205, 50)},
1179 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1180 {"yellow green" , PALETTERGB (154,205, 50)},
1181 {"YellowGreen" , PALETTERGB (154,205, 50)},
1182 {"forest green" , PALETTERGB ( 34,139, 34)},
1183 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1184 {"olive drab" , PALETTERGB (107,142, 35)},
1185 {"OliveDrab" , PALETTERGB (107,142, 35)},
1186 {"dark khaki" , PALETTERGB (189,183,107)},
1187 {"DarkKhaki" , PALETTERGB (189,183,107)},
1188 {"khaki" , PALETTERGB (240,230,140)},
1189 {"pale goldenrod" , PALETTERGB (238,232,170)},
1190 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1191 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1192 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1193 {"light yellow" , PALETTERGB (255,255,224)},
1194 {"LightYellow" , PALETTERGB (255,255,224)},
1195 {"yellow" , PALETTERGB (255,255, 0)},
1196 {"gold" , PALETTERGB (255,215, 0)},
1197 {"light goldenrod" , PALETTERGB (238,221,130)},
1198 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1199 {"goldenrod" , PALETTERGB (218,165, 32)},
1200 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1201 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1202 {"rosy brown" , PALETTERGB (188,143,143)},
1203 {"RosyBrown" , PALETTERGB (188,143,143)},
1204 {"indian red" , PALETTERGB (205, 92, 92)},
1205 {"IndianRed" , PALETTERGB (205, 92, 92)},
1206 {"saddle brown" , PALETTERGB (139, 69, 19)},
1207 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1208 {"sienna" , PALETTERGB (160, 82, 45)},
1209 {"peru" , PALETTERGB (205,133, 63)},
1210 {"burlywood" , PALETTERGB (222,184,135)},
1211 {"beige" , PALETTERGB (245,245,220)},
1212 {"wheat" , PALETTERGB (245,222,179)},
1213 {"sandy brown" , PALETTERGB (244,164, 96)},
1214 {"SandyBrown" , PALETTERGB (244,164, 96)},
1215 {"tan" , PALETTERGB (210,180,140)},
1216 {"chocolate" , PALETTERGB (210,105, 30)},
1217 {"firebrick" , PALETTERGB (178,34, 34)},
1218 {"brown" , PALETTERGB (165,42, 42)},
1219 {"dark salmon" , PALETTERGB (233,150,122)},
1220 {"DarkSalmon" , PALETTERGB (233,150,122)},
1221 {"salmon" , PALETTERGB (250,128,114)},
1222 {"light salmon" , PALETTERGB (255,160,122)},
1223 {"LightSalmon" , PALETTERGB (255,160,122)},
1224 {"orange" , PALETTERGB (255,165, 0)},
1225 {"dark orange" , PALETTERGB (255,140, 0)},
1226 {"DarkOrange" , PALETTERGB (255,140, 0)},
1227 {"coral" , PALETTERGB (255,127, 80)},
1228 {"light coral" , PALETTERGB (240,128,128)},
1229 {"LightCoral" , PALETTERGB (240,128,128)},
1230 {"tomato" , PALETTERGB (255, 99, 71)},
1231 {"orange red" , PALETTERGB (255, 69, 0)},
1232 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1233 {"red" , PALETTERGB (255, 0, 0)},
1234 {"hot pink" , PALETTERGB (255,105,180)},
1235 {"HotPink" , PALETTERGB (255,105,180)},
1236 {"deep pink" , PALETTERGB (255, 20,147)},
1237 {"DeepPink" , PALETTERGB (255, 20,147)},
1238 {"pink" , PALETTERGB (255,192,203)},
1239 {"light pink" , PALETTERGB (255,182,193)},
1240 {"LightPink" , PALETTERGB (255,182,193)},
1241 {"pale violet red" , PALETTERGB (219,112,147)},
1242 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1243 {"maroon" , PALETTERGB (176, 48, 96)},
1244 {"medium violet red" , PALETTERGB (199, 21,133)},
1245 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1246 {"violet red" , PALETTERGB (208, 32,144)},
1247 {"VioletRed" , PALETTERGB (208, 32,144)},
1248 {"magenta" , PALETTERGB (255, 0,255)},
1249 {"violet" , PALETTERGB (238,130,238)},
1250 {"plum" , PALETTERGB (221,160,221)},
1251 {"orchid" , PALETTERGB (218,112,214)},
1252 {"medium orchid" , PALETTERGB (186, 85,211)},
1253 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1254 {"dark orchid" , PALETTERGB (153, 50,204)},
1255 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1256 {"dark violet" , PALETTERGB (148, 0,211)},
1257 {"DarkViolet" , PALETTERGB (148, 0,211)},
1258 {"blue violet" , PALETTERGB (138, 43,226)},
1259 {"BlueViolet" , PALETTERGB (138, 43,226)},
1260 {"purple" , PALETTERGB (160, 32,240)},
1261 {"medium purple" , PALETTERGB (147,112,219)},
1262 {"MediumPurple" , PALETTERGB (147,112,219)},
1263 {"thistle" , PALETTERGB (216,191,216)},
1264 {"gray0" , PALETTERGB ( 0, 0, 0)},
1265 {"grey0" , PALETTERGB ( 0, 0, 0)},
1266 {"dark grey" , PALETTERGB (169,169,169)},
1267 {"DarkGrey" , PALETTERGB (169,169,169)},
1268 {"dark gray" , PALETTERGB (169,169,169)},
1269 {"DarkGray" , PALETTERGB (169,169,169)},
1270 {"dark blue" , PALETTERGB ( 0, 0,139)},
1271 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1272 {"dark cyan" , PALETTERGB ( 0,139,139)},
1273 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1274 {"dark magenta" , PALETTERGB (139, 0,139)},
1275 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1276 {"dark red" , PALETTERGB (139, 0, 0)},
1277 {"DarkRed" , PALETTERGB (139, 0, 0)},
1278 {"light green" , PALETTERGB (144,238,144)},
1279 {"LightGreen" , PALETTERGB (144,238,144)},
1282 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
1283 0, 0, 0, "Return the default color map.")
1287 colormap_t
*pc
= w32_color_map
;
1294 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
1296 cmap
= Fcons (Fcons (build_string (pc
->name
),
1297 make_number (pc
->colorref
)),
1306 w32_to_x_color (rgb
)
1311 CHECK_NUMBER (rgb
, 0);
1315 color
= Frassq (rgb
, Vw32_color_map
);
1320 return (Fcar (color
));
1326 w32_color_map_lookup (colorname
)
1329 Lisp_Object tail
, ret
= Qnil
;
1333 for (tail
= Vw32_color_map
; !NILP (tail
); tail
= Fcdr (tail
))
1335 register Lisp_Object elt
, tem
;
1338 if (!CONSP (elt
)) continue;
1342 if (lstrcmpi (XSTRING (tem
)->data
, colorname
) == 0)
1344 ret
= XUINT (Fcdr (elt
));
1358 x_to_w32_color (colorname
)
1361 register Lisp_Object tail
, ret
= Qnil
;
1365 if (colorname
[0] == '#')
1367 /* Could be an old-style RGB Device specification. */
1370 color
= colorname
+ 1;
1372 size
= strlen(color
);
1373 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1381 for (i
= 0; i
< 3; i
++)
1385 unsigned long value
;
1387 /* The check for 'x' in the following conditional takes into
1388 account the fact that strtol allows a "0x" in front of
1389 our numbers, and we don't. */
1390 if (!isxdigit(color
[0]) || color
[1] == 'x')
1394 value
= strtoul(color
, &end
, 16);
1396 if (errno
== ERANGE
|| end
- color
!= size
)
1401 value
= value
* 0x10;
1412 colorval
|= (value
<< pos
);
1423 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1431 color
= colorname
+ 4;
1432 for (i
= 0; i
< 3; i
++)
1435 unsigned long value
;
1437 /* The check for 'x' in the following conditional takes into
1438 account the fact that strtol allows a "0x" in front of
1439 our numbers, and we don't. */
1440 if (!isxdigit(color
[0]) || color
[1] == 'x')
1442 value
= strtoul(color
, &end
, 16);
1443 if (errno
== ERANGE
)
1445 switch (end
- color
)
1448 value
= value
* 0x10 + value
;
1461 if (value
== ULONG_MAX
)
1463 colorval
|= (value
<< pos
);
1477 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1479 /* This is an RGB Intensity specification. */
1486 color
= colorname
+ 5;
1487 for (i
= 0; i
< 3; i
++)
1493 value
= strtod(color
, &end
);
1494 if (errno
== ERANGE
)
1496 if (value
< 0.0 || value
> 1.0)
1498 val
= (UINT
)(0x100 * value
);
1499 /* We used 0x100 instead of 0xFF to give an continuous
1500 range between 0.0 and 1.0 inclusive. The next statement
1501 fixes the 1.0 case. */
1504 colorval
|= (val
<< pos
);
1518 /* I am not going to attempt to handle any of the CIE color schemes
1519 or TekHVC, since I don't know the algorithms for conversion to
1522 /* If we fail to lookup the color name in w32_color_map, then check the
1523 colorname to see if it can be crudely approximated: If the X color
1524 ends in a number (e.g., "darkseagreen2"), strip the number and
1525 return the result of looking up the base color name. */
1526 ret
= w32_color_map_lookup (colorname
);
1529 int len
= strlen (colorname
);
1531 if (isdigit (colorname
[len
- 1]))
1533 char *ptr
, *approx
= alloca (len
);
1535 strcpy (approx
, colorname
);
1536 ptr
= &approx
[len
- 1];
1537 while (ptr
> approx
&& isdigit (*ptr
))
1540 ret
= w32_color_map_lookup (approx
);
1550 w32_regenerate_palette (FRAME_PTR f
)
1552 struct w32_palette_entry
* list
;
1553 LOGPALETTE
* log_palette
;
1554 HPALETTE new_palette
;
1557 /* don't bother trying to create palette if not supported */
1558 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1561 log_palette
= (LOGPALETTE
*)
1562 alloca (sizeof (LOGPALETTE
) +
1563 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1564 log_palette
->palVersion
= 0x300;
1565 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1567 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1569 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1570 i
++, list
= list
->next
)
1571 log_palette
->palPalEntry
[i
] = list
->entry
;
1573 new_palette
= CreatePalette (log_palette
);
1577 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1578 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1579 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1581 /* Realize display palette and garbage all frames. */
1582 release_frame_dc (f
, get_frame_dc (f
));
1587 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1588 #define SET_W32_COLOR(pe, color) \
1591 pe.peRed = GetRValue (color); \
1592 pe.peGreen = GetGValue (color); \
1593 pe.peBlue = GetBValue (color); \
1598 /* Keep these around in case we ever want to track color usage. */
1600 w32_map_color (FRAME_PTR f
, COLORREF color
)
1602 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1604 if (NILP (Vw32_enable_palette
))
1607 /* check if color is already mapped */
1610 if (W32_COLOR (list
->entry
) == color
)
1618 /* not already mapped, so add to list and recreate Windows palette */
1619 list
= (struct w32_palette_entry
*)
1620 xmalloc (sizeof (struct w32_palette_entry
));
1621 SET_W32_COLOR (list
->entry
, color
);
1623 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1624 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1625 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1627 /* set flag that palette must be regenerated */
1628 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1632 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1634 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1635 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1637 if (NILP (Vw32_enable_palette
))
1640 /* check if color is already mapped */
1643 if (W32_COLOR (list
->entry
) == color
)
1645 if (--list
->refcount
== 0)
1649 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1659 /* set flag that palette must be regenerated */
1660 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1664 /* Decide if color named COLOR is valid for the display associated with
1665 the selected frame; if so, return the rgb values in COLOR_DEF.
1666 If ALLOC is nonzero, allocate a new colormap cell. */
1669 defined_color (f
, color
, color_def
, alloc
)
1672 COLORREF
*color_def
;
1675 register Lisp_Object tem
;
1677 tem
= x_to_w32_color (color
);
1681 if (!NILP (Vw32_enable_palette
))
1683 struct w32_palette_entry
* entry
=
1684 FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1685 struct w32_palette_entry
** prev
=
1686 &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1688 /* check if color is already mapped */
1691 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1693 prev
= &entry
->next
;
1694 entry
= entry
->next
;
1697 if (entry
== NULL
&& alloc
)
1699 /* not already mapped, so add to list */
1700 entry
= (struct w32_palette_entry
*)
1701 xmalloc (sizeof (struct w32_palette_entry
));
1702 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1705 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1707 /* set flag that palette must be regenerated */
1708 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1711 /* Ensure COLORREF value is snapped to nearest color in (default)
1712 palette by simulating the PALETTERGB macro. This works whether
1713 or not the display device has a palette. */
1714 *color_def
= XUINT (tem
) | 0x2000000;
1723 /* Given a string ARG naming a color, compute a pixel value from it
1724 suitable for screen F.
1725 If F is not a color screen, return DEF (default) regardless of what
1729 x_decode_color (f
, arg
, def
)
1736 CHECK_STRING (arg
, 0);
1738 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1739 return BLACK_PIX_DEFAULT (f
);
1740 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1741 return WHITE_PIX_DEFAULT (f
);
1743 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1746 /* defined_color is responsible for coping with failures
1747 by looking for a near-miss. */
1748 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1751 /* defined_color failed; return an ultimate default. */
1755 /* Functions called only from `x_set_frame_param'
1756 to set individual parameters.
1758 If FRAME_W32_WINDOW (f) is 0,
1759 the frame is being created and its window does not exist yet.
1760 In that case, just record the parameter's new value
1761 in the standard place; do not attempt to change the window. */
1764 x_set_foreground_color (f
, arg
, oldval
)
1766 Lisp_Object arg
, oldval
;
1768 f
->output_data
.w32
->foreground_pixel
1769 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1771 if (FRAME_W32_WINDOW (f
) != 0)
1773 recompute_basic_faces (f
);
1774 if (FRAME_VISIBLE_P (f
))
1780 x_set_background_color (f
, arg
, oldval
)
1782 Lisp_Object arg
, oldval
;
1787 f
->output_data
.w32
->background_pixel
1788 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1790 if (FRAME_W32_WINDOW (f
) != 0)
1792 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
1794 recompute_basic_faces (f
);
1796 if (FRAME_VISIBLE_P (f
))
1802 x_set_mouse_color (f
, arg
, oldval
)
1804 Lisp_Object arg
, oldval
;
1807 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1812 if (!EQ (Qnil
, arg
))
1813 f
->output_data
.w32
->mouse_pixel
1814 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1815 mask_color
= f
->output_data
.w32
->background_pixel
;
1816 /* No invisible pointers. */
1817 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1818 && mask_color
== f
->output_data
.w32
->background_pixel
)
1819 f
->output_data
.w32
->mouse_pixel
= f
->output_data
.w32
->foreground_pixel
;
1824 /* It's not okay to crash if the user selects a screwy cursor. */
1825 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1827 if (!EQ (Qnil
, Vx_pointer_shape
))
1829 CHECK_NUMBER (Vx_pointer_shape
, 0);
1830 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1833 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1834 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1836 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1838 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1839 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1840 XINT (Vx_nontext_pointer_shape
));
1843 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1844 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1846 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1848 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1849 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1850 XINT (Vx_mode_pointer_shape
));
1853 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1854 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1856 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1858 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1860 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1861 XINT (Vx_sensitive_text_pointer_shape
));
1864 cross_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1866 /* Check and report errors with the above calls. */
1867 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1868 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1871 XColor fore_color
, back_color
;
1873 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1874 back_color
.pixel
= mask_color
;
1875 XQueryColor (FRAME_W32_DISPLAY (f
),
1876 DefaultColormap (FRAME_W32_DISPLAY (f
),
1877 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1879 XQueryColor (FRAME_W32_DISPLAY (f
),
1880 DefaultColormap (FRAME_W32_DISPLAY (f
),
1881 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1883 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1884 &fore_color
, &back_color
);
1885 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1886 &fore_color
, &back_color
);
1887 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1888 &fore_color
, &back_color
);
1889 XRecolorCursor (FRAME_W32_DISPLAY (f
), cross_cursor
,
1890 &fore_color
, &back_color
);
1893 if (FRAME_W32_WINDOW (f
) != 0)
1895 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1898 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1899 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1900 f
->output_data
.w32
->text_cursor
= cursor
;
1902 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1903 && f
->output_data
.w32
->nontext_cursor
!= 0)
1904 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1905 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1907 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1908 && f
->output_data
.w32
->modeline_cursor
!= 0)
1909 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1910 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1911 if (cross_cursor
!= f
->output_data
.w32
->cross_cursor
1912 && f
->output_data
.w32
->cross_cursor
!= 0)
1913 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->cross_cursor
);
1914 f
->output_data
.w32
->cross_cursor
= cross_cursor
;
1916 XFlush (FRAME_W32_DISPLAY (f
));
1922 x_set_cursor_color (f
, arg
, oldval
)
1924 Lisp_Object arg
, oldval
;
1926 unsigned long fore_pixel
;
1928 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1929 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1930 WHITE_PIX_DEFAULT (f
));
1932 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1933 f
->output_data
.w32
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1935 /* Make sure that the cursor color differs from the background color. */
1936 if (f
->output_data
.w32
->cursor_pixel
== f
->output_data
.w32
->background_pixel
)
1938 f
->output_data
.w32
->cursor_pixel
= f
->output_data
.w32
->mouse_pixel
;
1939 if (f
->output_data
.w32
->cursor_pixel
== fore_pixel
)
1940 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1942 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1944 if (FRAME_W32_WINDOW (f
) != 0)
1946 if (FRAME_VISIBLE_P (f
))
1948 x_display_cursor (f
, 0);
1949 x_display_cursor (f
, 1);
1954 /* Set the border-color of frame F to pixel value PIX.
1955 Note that this does not fully take effect if done before
1958 x_set_border_pixel (f
, pix
)
1962 f
->output_data
.w32
->border_pixel
= pix
;
1964 if (FRAME_W32_WINDOW (f
) != 0 && f
->output_data
.w32
->border_width
> 0)
1966 if (FRAME_VISIBLE_P (f
))
1971 /* Set the border-color of frame F to value described by ARG.
1972 ARG can be a string naming a color.
1973 The border-color is used for the border that is drawn by the server.
1974 Note that this does not fully take effect if done before
1975 F has a window; it must be redone when the window is created. */
1978 x_set_border_color (f
, arg
, oldval
)
1980 Lisp_Object arg
, oldval
;
1985 CHECK_STRING (arg
, 0);
1986 str
= XSTRING (arg
)->data
;
1988 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1990 x_set_border_pixel (f
, pix
);
1994 x_set_cursor_type (f
, arg
, oldval
)
1996 Lisp_Object arg
, oldval
;
2000 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
2001 f
->output_data
.w32
->cursor_width
= 2;
2003 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
2004 && INTEGERP (XCONS (arg
)->cdr
))
2006 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
2007 f
->output_data
.w32
->cursor_width
= XINT (XCONS (arg
)->cdr
);
2010 /* Treat anything unknown as "box cursor".
2011 It was bad to signal an error; people have trouble fixing
2012 .Xdefaults with Emacs, when it has something bad in it. */
2013 FRAME_DESIRED_CURSOR (f
) = filled_box_cursor
;
2015 /* Make sure the cursor gets redrawn. This is overkill, but how
2016 often do people change cursor types? */
2017 update_mode_lines
++;
2021 x_set_icon_type (f
, arg
, oldval
)
2023 Lisp_Object arg
, oldval
;
2031 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2034 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2039 result
= x_text_icon (f
,
2040 (char *) XSTRING ((!NILP (f
->icon_name
)
2044 result
= x_bitmap_icon (f
, arg
);
2049 error ("No icon window available");
2052 /* If the window was unmapped (and its icon was mapped),
2053 the new icon is not mapped, so map the window in its stead. */
2054 if (FRAME_VISIBLE_P (f
))
2056 #ifdef USE_X_TOOLKIT
2057 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2059 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2062 XFlush (FRAME_W32_DISPLAY (f
));
2067 /* Return non-nil if frame F wants a bitmap icon. */
2075 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
2077 return XCONS (tem
)->cdr
;
2083 x_set_icon_name (f
, arg
, oldval
)
2085 Lisp_Object arg
, oldval
;
2092 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2095 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2101 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2106 result
= x_text_icon (f
,
2107 (char *) XSTRING ((!NILP (f
->icon_name
)
2116 error ("No icon window available");
2119 /* If the window was unmapped (and its icon was mapped),
2120 the new icon is not mapped, so map the window in its stead. */
2121 if (FRAME_VISIBLE_P (f
))
2123 #ifdef USE_X_TOOLKIT
2124 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2126 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2129 XFlush (FRAME_W32_DISPLAY (f
));
2134 extern Lisp_Object
x_new_font ();
2135 extern Lisp_Object
x_new_fontset();
2138 x_set_font (f
, arg
, oldval
)
2140 Lisp_Object arg
, oldval
;
2143 Lisp_Object fontset_name
;
2146 CHECK_STRING (arg
, 1);
2148 fontset_name
= Fquery_fontset (arg
, Qnil
);
2151 result
= (STRINGP (fontset_name
)
2152 ? x_new_fontset (f
, XSTRING (fontset_name
)->data
)
2153 : x_new_font (f
, XSTRING (arg
)->data
));
2156 if (EQ (result
, Qnil
))
2157 error ("Font \"%s\" is not defined", XSTRING (arg
)->data
);
2158 else if (EQ (result
, Qt
))
2159 error ("the characters of the given font have varying widths");
2160 else if (STRINGP (result
))
2162 recompute_basic_faces (f
);
2163 store_frame_param (f
, Qfont
, result
);
2168 XSETFRAME (frame
, f
);
2169 call1 (Qface_set_after_frame_default
, frame
);
2173 x_set_border_width (f
, arg
, oldval
)
2175 Lisp_Object arg
, oldval
;
2177 CHECK_NUMBER (arg
, 0);
2179 if (XINT (arg
) == f
->output_data
.w32
->border_width
)
2182 if (FRAME_W32_WINDOW (f
) != 0)
2183 error ("Cannot change the border width of a window");
2185 f
->output_data
.w32
->border_width
= XINT (arg
);
2189 x_set_internal_border_width (f
, arg
, oldval
)
2191 Lisp_Object arg
, oldval
;
2194 int old
= f
->output_data
.w32
->internal_border_width
;
2196 CHECK_NUMBER (arg
, 0);
2197 f
->output_data
.w32
->internal_border_width
= XINT (arg
);
2198 if (f
->output_data
.w32
->internal_border_width
< 0)
2199 f
->output_data
.w32
->internal_border_width
= 0;
2201 if (f
->output_data
.w32
->internal_border_width
== old
)
2204 if (FRAME_W32_WINDOW (f
) != 0)
2207 x_set_window_size (f
, 0, f
->width
, f
->height
);
2209 SET_FRAME_GARBAGED (f
);
2214 x_set_visibility (f
, value
, oldval
)
2216 Lisp_Object value
, oldval
;
2219 XSETFRAME (frame
, f
);
2222 Fmake_frame_invisible (frame
, Qt
);
2223 else if (EQ (value
, Qicon
))
2224 Ficonify_frame (frame
);
2226 Fmake_frame_visible (frame
);
2230 x_set_menu_bar_lines (f
, value
, oldval
)
2232 Lisp_Object value
, oldval
;
2235 int olines
= FRAME_MENU_BAR_LINES (f
);
2237 /* Right now, menu bars don't work properly in minibuf-only frames;
2238 most of the commands try to apply themselves to the minibuffer
2239 frame itslef, and get an error because you can't switch buffers
2240 in or split the minibuffer window. */
2241 if (FRAME_MINIBUF_ONLY_P (f
))
2244 if (INTEGERP (value
))
2245 nlines
= XINT (value
);
2249 FRAME_MENU_BAR_LINES (f
) = 0;
2251 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2254 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2255 free_frame_menubar (f
);
2256 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2258 /* Adjust the frame size so that the client (text) dimensions
2259 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2261 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2265 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2268 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2269 name; if NAME is a string, set F's name to NAME and set
2270 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2272 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2273 suggesting a new name, which lisp code should override; if
2274 F->explicit_name is set, ignore the new name; otherwise, set it. */
2277 x_set_name (f
, name
, explicit)
2282 /* Make sure that requests from lisp code override requests from
2283 Emacs redisplay code. */
2286 /* If we're switching from explicit to implicit, we had better
2287 update the mode lines and thereby update the title. */
2288 if (f
->explicit_name
&& NILP (name
))
2289 update_mode_lines
= 1;
2291 f
->explicit_name
= ! NILP (name
);
2293 else if (f
->explicit_name
)
2296 /* If NAME is nil, set the name to the w32_id_name. */
2299 /* Check for no change needed in this very common case
2300 before we do any consing. */
2301 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
2302 XSTRING (f
->name
)->data
))
2304 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
2307 CHECK_STRING (name
, 0);
2309 /* Don't change the name if it's already NAME. */
2310 if (! NILP (Fstring_equal (name
, f
->name
)))
2315 /* For setting the frame title, the title parameter should override
2316 the name parameter. */
2317 if (! NILP (f
->title
))
2320 if (FRAME_W32_WINDOW (f
))
2323 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2328 /* This function should be called when the user's lisp code has
2329 specified a name for the frame; the name will override any set by the
2332 x_explicitly_set_name (f
, arg
, oldval
)
2334 Lisp_Object arg
, oldval
;
2336 x_set_name (f
, arg
, 1);
2339 /* This function should be called by Emacs redisplay code to set the
2340 name; names set this way will never override names set by the user's
2343 x_implicitly_set_name (f
, arg
, oldval
)
2345 Lisp_Object arg
, oldval
;
2347 x_set_name (f
, arg
, 0);
2350 /* Change the title of frame F to NAME.
2351 If NAME is nil, use the frame name as the title.
2353 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2354 name; if NAME is a string, set F's name to NAME and set
2355 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2357 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2358 suggesting a new name, which lisp code should override; if
2359 F->explicit_name is set, ignore the new name; otherwise, set it. */
2362 x_set_title (f
, name
)
2366 /* Don't change the title if it's already NAME. */
2367 if (EQ (name
, f
->title
))
2370 update_mode_lines
= 1;
2377 if (FRAME_W32_WINDOW (f
))
2380 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2386 x_set_autoraise (f
, arg
, oldval
)
2388 Lisp_Object arg
, oldval
;
2390 f
->auto_raise
= !EQ (Qnil
, arg
);
2394 x_set_autolower (f
, arg
, oldval
)
2396 Lisp_Object arg
, oldval
;
2398 f
->auto_lower
= !EQ (Qnil
, arg
);
2402 x_set_unsplittable (f
, arg
, oldval
)
2404 Lisp_Object arg
, oldval
;
2406 f
->no_split
= !NILP (arg
);
2410 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2412 Lisp_Object arg
, oldval
;
2414 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2415 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2416 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2417 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2419 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = NILP (arg
) ?
2420 vertical_scroll_bar_none
:
2421 /* Put scroll bars on the right by default, as is conventional
2424 ? vertical_scroll_bar_left
2425 : vertical_scroll_bar_right
;
2427 /* We set this parameter before creating the window for the
2428 frame, so we can get the geometry right from the start.
2429 However, if the window hasn't been created yet, we shouldn't
2430 call x_set_window_size. */
2431 if (FRAME_W32_WINDOW (f
))
2432 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2437 x_set_scroll_bar_width (f
, arg
, oldval
)
2439 Lisp_Object arg
, oldval
;
2443 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2444 FRAME_SCROLL_BAR_COLS (f
) = 2;
2446 else if (INTEGERP (arg
) && XINT (arg
) > 0
2447 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2449 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
2450 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2451 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2452 if (FRAME_W32_WINDOW (f
))
2453 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2457 /* Subroutines of creating an frame. */
2459 /* Make sure that Vx_resource_name is set to a reasonable value.
2460 Fix it up, or set it to `emacs' if it is too hopeless. */
2463 validate_x_resource_name ()
2466 /* Number of valid characters in the resource name. */
2468 /* Number of invalid characters in the resource name. */
2473 if (STRINGP (Vx_resource_name
))
2475 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2478 len
= XSTRING (Vx_resource_name
)->size
;
2480 /* Only letters, digits, - and _ are valid in resource names.
2481 Count the valid characters and count the invalid ones. */
2482 for (i
= 0; i
< len
; i
++)
2485 if (! ((c
>= 'a' && c
<= 'z')
2486 || (c
>= 'A' && c
<= 'Z')
2487 || (c
>= '0' && c
<= '9')
2488 || c
== '-' || c
== '_'))
2495 /* Not a string => completely invalid. */
2496 bad_count
= 5, good_count
= 0;
2498 /* If name is valid already, return. */
2502 /* If name is entirely invalid, or nearly so, use `emacs'. */
2504 || (good_count
== 1 && bad_count
> 0))
2506 Vx_resource_name
= build_string ("emacs");
2510 /* Name is partly valid. Copy it and replace the invalid characters
2511 with underscores. */
2513 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2515 for (i
= 0; i
< len
; i
++)
2517 int c
= XSTRING (new)->data
[i
];
2518 if (! ((c
>= 'a' && c
<= 'z')
2519 || (c
>= 'A' && c
<= 'Z')
2520 || (c
>= '0' && c
<= '9')
2521 || c
== '-' || c
== '_'))
2522 XSTRING (new)->data
[i
] = '_';
2527 extern char *x_get_string_resource ();
2529 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2530 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2531 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2532 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2533 the name specified by the `-name' or `-rn' command-line arguments.\n\
2535 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2536 class, respectively. You must specify both of them or neither.\n\
2537 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2538 and the class is `Emacs.CLASS.SUBCLASS'.")
2539 (attribute
, class, component
, subclass
)
2540 Lisp_Object attribute
, class, component
, subclass
;
2542 register char *value
;
2546 CHECK_STRING (attribute
, 0);
2547 CHECK_STRING (class, 0);
2549 if (!NILP (component
))
2550 CHECK_STRING (component
, 1);
2551 if (!NILP (subclass
))
2552 CHECK_STRING (subclass
, 2);
2553 if (NILP (component
) != NILP (subclass
))
2554 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2556 validate_x_resource_name ();
2558 /* Allocate space for the components, the dots which separate them,
2559 and the final '\0'. Make them big enough for the worst case. */
2560 name_key
= (char *) alloca (XSTRING (Vx_resource_name
)->size
2561 + (STRINGP (component
)
2562 ? XSTRING (component
)->size
: 0)
2563 + XSTRING (attribute
)->size
2566 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2567 + XSTRING (class)->size
2568 + (STRINGP (subclass
)
2569 ? XSTRING (subclass
)->size
: 0)
2572 /* Start with emacs.FRAMENAME for the name (the specific one)
2573 and with `Emacs' for the class key (the general one). */
2574 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2575 strcpy (class_key
, EMACS_CLASS
);
2577 strcat (class_key
, ".");
2578 strcat (class_key
, XSTRING (class)->data
);
2580 if (!NILP (component
))
2582 strcat (class_key
, ".");
2583 strcat (class_key
, XSTRING (subclass
)->data
);
2585 strcat (name_key
, ".");
2586 strcat (name_key
, XSTRING (component
)->data
);
2589 strcat (name_key
, ".");
2590 strcat (name_key
, XSTRING (attribute
)->data
);
2592 value
= x_get_string_resource (Qnil
,
2593 name_key
, class_key
);
2595 if (value
!= (char *) 0)
2596 return build_string (value
);
2601 /* Used when C code wants a resource value. */
2604 x_get_resource_string (attribute
, class)
2605 char *attribute
, *class;
2607 register char *value
;
2611 /* Allocate space for the components, the dots which separate them,
2612 and the final '\0'. */
2613 name_key
= (char *) alloca (XSTRING (Vinvocation_name
)->size
2614 + strlen (attribute
) + 2);
2615 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2616 + strlen (class) + 2);
2618 sprintf (name_key
, "%s.%s",
2619 XSTRING (Vinvocation_name
)->data
,
2621 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2623 return x_get_string_resource (selected_frame
,
2624 name_key
, class_key
);
2627 /* Types we might convert a resource string into. */
2630 number
, boolean
, string
, symbol
2633 /* Return the value of parameter PARAM.
2635 First search ALIST, then Vdefault_frame_alist, then the X defaults
2636 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2638 Convert the resource to the type specified by desired_type.
2640 If no default is specified, return Qunbound. If you call
2641 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2642 and don't let it get stored in any Lisp-visible variables! */
2645 x_get_arg (alist
, param
, attribute
, class, type
)
2646 Lisp_Object alist
, param
;
2649 enum resource_types type
;
2651 register Lisp_Object tem
;
2653 tem
= Fassq (param
, alist
);
2655 tem
= Fassq (param
, Vdefault_frame_alist
);
2661 tem
= Fx_get_resource (build_string (attribute
),
2662 build_string (class),
2671 return make_number (atoi (XSTRING (tem
)->data
));
2674 tem
= Fdowncase (tem
);
2675 if (!strcmp (XSTRING (tem
)->data
, "on")
2676 || !strcmp (XSTRING (tem
)->data
, "true"))
2685 /* As a special case, we map the values `true' and `on'
2686 to Qt, and `false' and `off' to Qnil. */
2689 lower
= Fdowncase (tem
);
2690 if (!strcmp (XSTRING (lower
)->data
, "on")
2691 || !strcmp (XSTRING (lower
)->data
, "true"))
2693 else if (!strcmp (XSTRING (lower
)->data
, "off")
2694 || !strcmp (XSTRING (lower
)->data
, "false"))
2697 return Fintern (tem
, Qnil
);
2710 /* Record in frame F the specified or default value according to ALIST
2711 of the parameter named PARAM (a Lisp symbol).
2712 If no value is specified for PARAM, look for an X default for XPROP
2713 on the frame named NAME.
2714 If that is not found either, use the value DEFLT. */
2717 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2724 enum resource_types type
;
2728 tem
= x_get_arg (alist
, prop
, xprop
, xclass
, type
);
2729 if (EQ (tem
, Qunbound
))
2731 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2735 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2736 "Parse an X-style geometry string STRING.\n\
2737 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2738 The properties returned may include `top', `left', `height', and `width'.\n\
2739 The value of `left' or `top' may be an integer,\n\
2740 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2741 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2746 unsigned int width
, height
;
2749 CHECK_STRING (string
, 0);
2751 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2752 &x
, &y
, &width
, &height
);
2755 if (geometry
& XValue
)
2757 Lisp_Object element
;
2759 if (x
>= 0 && (geometry
& XNegative
))
2760 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2761 else if (x
< 0 && ! (geometry
& XNegative
))
2762 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2764 element
= Fcons (Qleft
, make_number (x
));
2765 result
= Fcons (element
, result
);
2768 if (geometry
& YValue
)
2770 Lisp_Object element
;
2772 if (y
>= 0 && (geometry
& YNegative
))
2773 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2774 else if (y
< 0 && ! (geometry
& YNegative
))
2775 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2777 element
= Fcons (Qtop
, make_number (y
));
2778 result
= Fcons (element
, result
);
2781 if (geometry
& WidthValue
)
2782 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2783 if (geometry
& HeightValue
)
2784 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2789 /* Calculate the desired size and position of this window,
2790 and return the flags saying which aspects were specified.
2792 This function does not make the coordinates positive. */
2794 #define DEFAULT_ROWS 40
2795 #define DEFAULT_COLS 80
2798 x_figure_window_size (f
, parms
)
2802 register Lisp_Object tem0
, tem1
, tem2
;
2803 int height
, width
, left
, top
;
2804 register int geometry
;
2805 long window_prompting
= 0;
2807 /* Default values if we fall through.
2808 Actually, if that happens we should get
2809 window manager prompting. */
2810 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2811 f
->height
= DEFAULT_ROWS
;
2812 /* Window managers expect that if program-specified
2813 positions are not (0,0), they're intentional, not defaults. */
2814 f
->output_data
.w32
->top_pos
= 0;
2815 f
->output_data
.w32
->left_pos
= 0;
2817 tem0
= x_get_arg (parms
, Qheight
, 0, 0, number
);
2818 tem1
= x_get_arg (parms
, Qwidth
, 0, 0, number
);
2819 tem2
= x_get_arg (parms
, Quser_size
, 0, 0, number
);
2820 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2822 if (!EQ (tem0
, Qunbound
))
2824 CHECK_NUMBER (tem0
, 0);
2825 f
->height
= XINT (tem0
);
2827 if (!EQ (tem1
, Qunbound
))
2829 CHECK_NUMBER (tem1
, 0);
2830 SET_FRAME_WIDTH (f
, XINT (tem1
));
2832 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2833 window_prompting
|= USSize
;
2835 window_prompting
|= PSize
;
2838 f
->output_data
.w32
->vertical_scroll_bar_extra
2839 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2841 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2842 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2843 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2844 f
->output_data
.w32
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2845 f
->output_data
.w32
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2847 tem0
= x_get_arg (parms
, Qtop
, 0, 0, number
);
2848 tem1
= x_get_arg (parms
, Qleft
, 0, 0, number
);
2849 tem2
= x_get_arg (parms
, Quser_position
, 0, 0, number
);
2850 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2852 if (EQ (tem0
, Qminus
))
2854 f
->output_data
.w32
->top_pos
= 0;
2855 window_prompting
|= YNegative
;
2857 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2858 && CONSP (XCONS (tem0
)->cdr
)
2859 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2861 f
->output_data
.w32
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2862 window_prompting
|= YNegative
;
2864 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2865 && CONSP (XCONS (tem0
)->cdr
)
2866 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2868 f
->output_data
.w32
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2870 else if (EQ (tem0
, Qunbound
))
2871 f
->output_data
.w32
->top_pos
= 0;
2874 CHECK_NUMBER (tem0
, 0);
2875 f
->output_data
.w32
->top_pos
= XINT (tem0
);
2876 if (f
->output_data
.w32
->top_pos
< 0)
2877 window_prompting
|= YNegative
;
2880 if (EQ (tem1
, Qminus
))
2882 f
->output_data
.w32
->left_pos
= 0;
2883 window_prompting
|= XNegative
;
2885 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2886 && CONSP (XCONS (tem1
)->cdr
)
2887 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2889 f
->output_data
.w32
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2890 window_prompting
|= XNegative
;
2892 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2893 && CONSP (XCONS (tem1
)->cdr
)
2894 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2896 f
->output_data
.w32
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2898 else if (EQ (tem1
, Qunbound
))
2899 f
->output_data
.w32
->left_pos
= 0;
2902 CHECK_NUMBER (tem1
, 0);
2903 f
->output_data
.w32
->left_pos
= XINT (tem1
);
2904 if (f
->output_data
.w32
->left_pos
< 0)
2905 window_prompting
|= XNegative
;
2908 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2909 window_prompting
|= USPosition
;
2911 window_prompting
|= PPosition
;
2914 return window_prompting
;
2919 extern LRESULT CALLBACK
w32_wnd_proc ();
2922 w32_init_class (hinst
)
2927 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2928 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
2930 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
2931 wc
.hInstance
= hinst
;
2932 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
2933 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
2934 wc
.hbrBackground
= NULL
; /* GetStockObject (WHITE_BRUSH); */
2935 wc
.lpszMenuName
= NULL
;
2936 wc
.lpszClassName
= EMACS_CLASS
;
2938 return (RegisterClass (&wc
));
2942 w32_createscrollbar (f
, bar
)
2944 struct scroll_bar
* bar
;
2946 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
2947 /* Position and size of scroll bar. */
2948 XINT(bar
->left
), XINT(bar
->top
),
2949 XINT(bar
->width
), XINT(bar
->height
),
2950 FRAME_W32_WINDOW (f
),
2957 w32_createwindow (f
)
2963 rect
.left
= rect
.top
= 0;
2964 rect
.right
= PIXEL_WIDTH (f
);
2965 rect
.bottom
= PIXEL_HEIGHT (f
);
2967 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2968 FRAME_EXTERNAL_MENU_BAR (f
));
2970 /* Do first time app init */
2974 w32_init_class (hinst
);
2977 FRAME_W32_WINDOW (f
) = hwnd
2978 = CreateWindow (EMACS_CLASS
,
2980 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2981 f
->output_data
.w32
->left_pos
,
2982 f
->output_data
.w32
->top_pos
,
2983 rect
.right
- rect
.left
,
2984 rect
.bottom
- rect
.top
,
2992 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
2993 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
2994 SetWindowLong (hwnd
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
2995 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
2996 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
2998 /* Enable drag-n-drop. */
2999 DragAcceptFiles (hwnd
, TRUE
);
3001 /* Do this to discard the default setting specified by our parent. */
3002 ShowWindow (hwnd
, SW_HIDE
);
3007 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
3014 wmsg
->msg
.hwnd
= hwnd
;
3015 wmsg
->msg
.message
= msg
;
3016 wmsg
->msg
.wParam
= wParam
;
3017 wmsg
->msg
.lParam
= lParam
;
3018 wmsg
->msg
.time
= GetMessageTime ();
3023 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
3024 between left and right keys as advertised. We test for this
3025 support dynamically, and set a flag when the support is absent. If
3026 absent, we keep track of the left and right control and alt keys
3027 ourselves. This is particularly necessary on keyboards that rely
3028 upon the AltGr key, which is represented as having the left control
3029 and right alt keys pressed. For these keyboards, we need to know
3030 when the left alt key has been pressed in addition to the AltGr key
3031 so that we can properly support M-AltGr-key sequences (such as M-@
3032 on Swedish keyboards). */
3034 #define EMACS_LCONTROL 0
3035 #define EMACS_RCONTROL 1
3036 #define EMACS_LMENU 2
3037 #define EMACS_RMENU 3
3039 static int modifiers
[4];
3040 static int modifiers_recorded
;
3041 static int modifier_key_support_tested
;
3044 test_modifier_support (unsigned int wparam
)
3048 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
3050 if (wparam
== VK_CONTROL
)
3060 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
3061 modifiers_recorded
= 1;
3063 modifiers_recorded
= 0;
3064 modifier_key_support_tested
= 1;
3068 record_keydown (unsigned int wparam
, unsigned int lparam
)
3072 if (!modifier_key_support_tested
)
3073 test_modifier_support (wparam
);
3075 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3078 if (wparam
== VK_CONTROL
)
3079 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3081 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3087 record_keyup (unsigned int wparam
, unsigned int lparam
)
3091 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
3094 if (wparam
== VK_CONTROL
)
3095 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3097 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3102 /* Emacs can lose focus while a modifier key has been pressed. When
3103 it regains focus, be conservative and clear all modifiers since
3104 we cannot reconstruct the left and right modifier state. */
3110 if (GetFocus () == NULL
)
3111 /* Emacs doesn't have keyboard focus. Do nothing. */
3114 ctrl
= GetAsyncKeyState (VK_CONTROL
);
3115 alt
= GetAsyncKeyState (VK_MENU
);
3117 if (!(ctrl
& 0x08000))
3118 /* Clear any recorded control modifier state. */
3119 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3121 if (!(alt
& 0x08000))
3122 /* Clear any recorded alt modifier state. */
3123 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3125 /* Update the state of all modifier keys, because modifiers used in
3126 hot-key combinations can get stuck on if Emacs loses focus as a
3127 result of a hot-key being pressed. */
3131 #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
3133 GetKeyboardState (keystate
);
3134 keystate
[VK_SHIFT
] = CURRENT_STATE (VK_SHIFT
);
3135 keystate
[VK_CONTROL
] = CURRENT_STATE (VK_CONTROL
);
3136 keystate
[VK_LCONTROL
] = CURRENT_STATE (VK_LCONTROL
);
3137 keystate
[VK_RCONTROL
] = CURRENT_STATE (VK_RCONTROL
);
3138 keystate
[VK_MENU
] = CURRENT_STATE (VK_MENU
);
3139 keystate
[VK_LMENU
] = CURRENT_STATE (VK_LMENU
);
3140 keystate
[VK_RMENU
] = CURRENT_STATE (VK_RMENU
);
3141 keystate
[VK_LWIN
] = CURRENT_STATE (VK_LWIN
);
3142 keystate
[VK_RWIN
] = CURRENT_STATE (VK_RWIN
);
3143 keystate
[VK_APPS
] = CURRENT_STATE (VK_APPS
);
3144 SetKeyboardState (keystate
);
3148 /* Synchronize modifier state with what is reported with the current
3149 keystroke. Even if we cannot distinguish between left and right
3150 modifier keys, we know that, if no modifiers are set, then neither
3151 the left or right modifier should be set. */
3155 if (!modifiers_recorded
)
3158 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
3159 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3161 if (!(GetKeyState (VK_MENU
) & 0x8000))
3162 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3166 modifier_set (int vkey
)
3168 if (vkey
== VK_CAPITAL
|| vkey
== VK_SCROLL
)
3169 return (GetKeyState (vkey
) & 0x1);
3170 if (!modifiers_recorded
)
3171 return (GetKeyState (vkey
) & 0x8000);
3176 return modifiers
[EMACS_LCONTROL
];
3178 return modifiers
[EMACS_RCONTROL
];
3180 return modifiers
[EMACS_LMENU
];
3182 return modifiers
[EMACS_RMENU
];
3184 return (GetKeyState (vkey
) & 0x8000);
3187 /* Convert between the modifier bits W32 uses and the modifier bits
3191 w32_key_to_modifier (int key
)
3193 Lisp_Object key_mapping
;
3198 key_mapping
= Vw32_lwindow_modifier
;
3201 key_mapping
= Vw32_rwindow_modifier
;
3204 key_mapping
= Vw32_apps_modifier
;
3207 key_mapping
= Vw32_scroll_lock_modifier
;
3213 /* NB. This code runs in the input thread, asychronously to the lisp
3214 thread, so we must be careful to ensure access to lisp data is
3215 thread-safe. The following code is safe because the modifier
3216 variable values are updated atomically from lisp and symbols are
3217 not relocated by GC. Also, we don't have to worry about seeing GC
3219 if (EQ (key_mapping
, Qhyper
))
3220 return hyper_modifier
;
3221 if (EQ (key_mapping
, Qsuper
))
3222 return super_modifier
;
3223 if (EQ (key_mapping
, Qmeta
))
3224 return meta_modifier
;
3225 if (EQ (key_mapping
, Qalt
))
3226 return alt_modifier
;
3227 if (EQ (key_mapping
, Qctrl
))
3228 return ctrl_modifier
;
3229 if (EQ (key_mapping
, Qcontrol
)) /* synonym for ctrl */
3230 return ctrl_modifier
;
3231 if (EQ (key_mapping
, Qshift
))
3232 return shift_modifier
;
3234 /* Don't generate any modifier if not explicitly requested. */
3239 w32_get_modifiers ()
3241 return ((modifier_set (VK_SHIFT
) ? shift_modifier
: 0) |
3242 (modifier_set (VK_CONTROL
) ? ctrl_modifier
: 0) |
3243 (modifier_set (VK_LWIN
) ? w32_key_to_modifier (VK_LWIN
) : 0) |
3244 (modifier_set (VK_RWIN
) ? w32_key_to_modifier (VK_RWIN
) : 0) |
3245 (modifier_set (VK_APPS
) ? w32_key_to_modifier (VK_APPS
) : 0) |
3246 (modifier_set (VK_SCROLL
) ? w32_key_to_modifier (VK_SCROLL
) : 0) |
3247 (modifier_set (VK_MENU
) ?
3248 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
3251 /* We map the VK_* modifiers into console modifier constants
3252 so that we can use the same routines to handle both console
3253 and window input. */
3256 construct_console_modifiers ()
3261 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
3262 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
3263 mods
|= (modifier_set (VK_SCROLL
)) ? SCROLLLOCK_ON
: 0;
3264 mods
|= (modifier_set (VK_NUMLOCK
)) ? NUMLOCK_ON
: 0;
3265 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
3266 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
3267 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
3268 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
3269 mods
|= (modifier_set (VK_LWIN
)) ? LEFT_WIN_PRESSED
: 0;
3270 mods
|= (modifier_set (VK_RWIN
)) ? RIGHT_WIN_PRESSED
: 0;
3271 mods
|= (modifier_set (VK_APPS
)) ? APPS_PRESSED
: 0;
3277 w32_get_key_modifiers (unsigned int wparam
, unsigned int lparam
)
3281 /* Convert to emacs modifiers. */
3282 mods
= w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam
);
3288 map_keypad_keys (unsigned int virt_key
, unsigned int extended
)
3290 if (virt_key
< VK_CLEAR
|| virt_key
> VK_DELETE
)
3293 if (virt_key
== VK_RETURN
)
3294 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
3296 if (virt_key
>= VK_PRIOR
&& virt_key
<= VK_DOWN
)
3297 return (!extended
? (VK_NUMPAD_PRIOR
+ (virt_key
- VK_PRIOR
)) : virt_key
);
3299 if (virt_key
== VK_INSERT
|| virt_key
== VK_DELETE
)
3300 return (!extended
? (VK_NUMPAD_INSERT
+ (virt_key
- VK_INSERT
)) : virt_key
);
3302 if (virt_key
== VK_CLEAR
)
3303 return (!extended
? VK_NUMPAD_CLEAR
: virt_key
);
3308 /* List of special key combinations which w32 would normally capture,
3309 but emacs should grab instead. Not directly visible to lisp, to
3310 simplify synchronization. Each item is an integer encoding a virtual
3311 key code and modifier combination to capture. */
3312 Lisp_Object w32_grabbed_keys
;
3314 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3315 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3316 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3317 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3319 /* Register hot-keys for reserved key combinations when Emacs has
3320 keyboard focus, since this is the only way Emacs can receive key
3321 combinations like Alt-Tab which are used by the system. */
3324 register_hot_keys (hwnd
)
3327 Lisp_Object keylist
;
3329 /* Use GC_CONSP, since we are called asynchronously. */
3330 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3332 Lisp_Object key
= XCAR (keylist
);
3334 /* Deleted entries get set to nil. */
3335 if (!INTEGERP (key
))
3338 RegisterHotKey (hwnd
, HOTKEY_ID (key
),
3339 HOTKEY_MODIFIERS (key
), HOTKEY_VK_CODE (key
));
3344 unregister_hot_keys (hwnd
)
3347 Lisp_Object keylist
;
3349 /* Use GC_CONSP, since we are called asynchronously. */
3350 for (keylist
= w32_grabbed_keys
; GC_CONSP (keylist
); keylist
= XCDR (keylist
))
3352 Lisp_Object key
= XCAR (keylist
);
3354 if (!INTEGERP (key
))
3357 UnregisterHotKey (hwnd
, HOTKEY_ID (key
));
3361 /* Main message dispatch loop. */
3364 w32_msg_pump (deferred_msg
* msg_buf
)
3370 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
3372 while (GetMessage (&msg
, NULL
, 0, 0))
3374 if (msg
.hwnd
== NULL
)
3376 switch (msg
.message
)
3379 /* Produced by complete_deferred_msg; just ignore. */
3381 case WM_EMACS_CREATEWINDOW
:
3382 w32_createwindow ((struct frame
*) msg
.wParam
);
3383 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3386 case WM_EMACS_SETLOCALE
:
3387 SetThreadLocale (msg
.wParam
);
3388 /* Reply is not expected. */
3390 case WM_EMACS_SETKEYBOARDLAYOUT
:
3391 result
= (int) ActivateKeyboardLayout ((HKL
) msg
.wParam
, 0);
3392 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3396 case WM_EMACS_REGISTER_HOT_KEY
:
3397 focus_window
= GetFocus ();
3398 if (focus_window
!= NULL
)
3399 RegisterHotKey (focus_window
,
3400 HOTKEY_ID (msg
.wParam
),
3401 HOTKEY_MODIFIERS (msg
.wParam
),
3402 HOTKEY_VK_CODE (msg
.wParam
));
3403 /* Reply is not expected. */
3405 case WM_EMACS_UNREGISTER_HOT_KEY
:
3406 focus_window
= GetFocus ();
3407 if (focus_window
!= NULL
)
3408 UnregisterHotKey (focus_window
, HOTKEY_ID (msg
.wParam
));
3409 /* Mark item as erased. NB: this code must be
3410 thread-safe. The next line is okay because the cons
3411 cell is never made into garbage and is not relocated by
3413 XCAR ((Lisp_Object
) msg
.lParam
) = Qnil
;
3414 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3417 case WM_EMACS_TOGGLE_LOCK_KEY
:
3419 int vk_code
= (int) msg
.wParam
;
3420 int cur_state
= (GetKeyState (vk_code
) & 1);
3421 Lisp_Object new_state
= (Lisp_Object
) msg
.lParam
;
3423 /* NB: This code must be thread-safe. It is safe to
3424 call NILP because symbols are not relocated by GC,
3425 and pointer here is not touched by GC (so the markbit
3426 can't be set). Numbers are safe because they are
3427 immediate values. */
3428 if (NILP (new_state
)
3429 || (NUMBERP (new_state
)
3430 && (XUINT (new_state
)) & 1 != cur_state
))
3432 one_w32_display_info
.faked_key
= vk_code
;
3434 keybd_event ((BYTE
) vk_code
,
3435 (BYTE
) MapVirtualKey (vk_code
, 0),
3436 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3437 keybd_event ((BYTE
) vk_code
,
3438 (BYTE
) MapVirtualKey (vk_code
, 0),
3439 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3440 keybd_event ((BYTE
) vk_code
,
3441 (BYTE
) MapVirtualKey (vk_code
, 0),
3442 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3443 cur_state
= !cur_state
;
3445 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
,
3451 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
3456 DispatchMessage (&msg
);
3459 /* Exit nested loop when our deferred message has completed. */
3460 if (msg_buf
->completed
)
3465 deferred_msg
* deferred_msg_head
;
3467 static deferred_msg
*
3468 find_deferred_msg (HWND hwnd
, UINT msg
)
3470 deferred_msg
* item
;
3472 /* Don't actually need synchronization for read access, since
3473 modification of single pointer is always atomic. */
3474 /* enter_crit (); */
3476 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3477 if (item
->w32msg
.msg
.hwnd
== hwnd
3478 && item
->w32msg
.msg
.message
== msg
)
3481 /* leave_crit (); */
3487 send_deferred_msg (deferred_msg
* msg_buf
,
3493 /* Only input thread can send deferred messages. */
3494 if (GetCurrentThreadId () != dwWindowsThreadId
)
3497 /* It is an error to send a message that is already deferred. */
3498 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3501 /* Enforced synchronization is not needed because this is the only
3502 function that alters deferred_msg_head, and the following critical
3503 section is guaranteed to only be serially reentered (since only the
3504 input thread can call us). */
3506 /* enter_crit (); */
3508 msg_buf
->completed
= 0;
3509 msg_buf
->next
= deferred_msg_head
;
3510 deferred_msg_head
= msg_buf
;
3511 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
3513 /* leave_crit (); */
3515 /* Start a new nested message loop to process other messages until
3516 this one is completed. */
3517 w32_msg_pump (msg_buf
);
3519 deferred_msg_head
= msg_buf
->next
;
3521 return msg_buf
->result
;
3525 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
3527 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
3529 if (msg_buf
== NULL
)
3530 /* Message may have been cancelled, so don't abort(). */
3533 msg_buf
->result
= result
;
3534 msg_buf
->completed
= 1;
3536 /* Ensure input thread is woken so it notices the completion. */
3537 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3541 cancel_all_deferred_msgs ()
3543 deferred_msg
* item
;
3545 /* Don't actually need synchronization for read access, since
3546 modification of single pointer is always atomic. */
3547 /* enter_crit (); */
3549 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3552 item
->completed
= 1;
3555 /* leave_crit (); */
3557 /* Ensure input thread is woken so it notices the completion. */
3558 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3566 deferred_msg dummy_buf
;
3568 /* Ensure our message queue is created */
3570 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3572 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3575 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
3576 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
3577 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
3579 /* This is the inital message loop which should only exit when the
3580 application quits. */
3581 w32_msg_pump (&dummy_buf
);
3587 post_character_message (hwnd
, msg
, wParam
, lParam
, modifiers
)
3597 wmsg
.dwModifiers
= modifiers
;
3599 /* Detect quit_char and set quit-flag directly. Note that we
3600 still need to post a message to ensure the main thread will be
3601 woken up if blocked in sys_select(), but we do NOT want to post
3602 the quit_char message itself (because it will usually be as if
3603 the user had typed quit_char twice). Instead, we post a dummy
3604 message that has no particular effect. */
3607 if (isalpha (c
) && wmsg
.dwModifiers
== ctrl_modifier
)
3608 c
= make_ctrl_char (c
) & 0377;
3613 /* The choice of message is somewhat arbitrary, as long as
3614 the main thread handler just ignores it. */
3617 /* Interrupt any blocking system calls. */
3620 /* As a safety precaution, forcibly complete any deferred
3621 messages. This is a kludge, but I don't see any particularly
3622 clean way to handle the situation where a deferred message is
3623 "dropped" in the lisp thread, and will thus never be
3624 completed, eg. by the user trying to activate the menubar
3625 when the lisp thread is busy, and then typing C-g when the
3626 menubar doesn't open promptly (with the result that the
3627 menubar never responds at all because the deferred
3628 WM_INITMENU message is never completed). Another problem
3629 situation is when the lisp thread calls SendMessage (to send
3630 a window manager command) when a message has been deferred;
3631 the lisp thread gets blocked indefinitely waiting for the
3632 deferred message to be completed, which itself is waiting for
3633 the lisp thread to respond.
3635 Note that we don't want to block the input thread waiting for
3636 a reponse from the lisp thread (although that would at least
3637 solve the deadlock problem above), because we want to be able
3638 to receive C-g to interrupt the lisp thread. */
3639 cancel_all_deferred_msgs ();
3643 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3646 /* Main window procedure */
3649 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
3656 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3658 int windows_translate
;
3661 /* Note that it is okay to call x_window_to_frame, even though we are
3662 not running in the main lisp thread, because frame deletion
3663 requires the lisp thread to synchronize with this thread. Thus, if
3664 a frame struct is returned, it can be used without concern that the
3665 lisp thread might make it disappear while we are using it.
3667 NB. Walking the frame list in this thread is safe (as long as
3668 writes of Lisp_Object slots are atomic, which they are on Windows).
3669 Although delete-frame can destructively modify the frame list while
3670 we are walking it, a garbage collection cannot occur until after
3671 delete-frame has synchronized with this thread.
3673 It is also safe to use functions that make GDI calls, such as
3674 w32_clear_rect, because these functions must obtain a DC handle
3675 from the frame struct using get_frame_dc which is thread-aware. */
3680 f
= x_window_to_frame (dpyinfo
, hwnd
);
3683 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
3684 w32_clear_rect (f
, NULL
, &wmsg
.rect
);
3687 case WM_PALETTECHANGED
:
3688 /* ignore our own changes */
3689 if ((HWND
)wParam
!= hwnd
)
3691 f
= x_window_to_frame (dpyinfo
, hwnd
);
3693 /* get_frame_dc will realize our palette and force all
3694 frames to be redrawn if needed. */
3695 release_frame_dc (f
, get_frame_dc (f
));
3700 PAINTSTRUCT paintStruct
;
3703 BeginPaint (hwnd
, &paintStruct
);
3704 wmsg
.rect
= paintStruct
.rcPaint
;
3705 EndPaint (hwnd
, &paintStruct
);
3708 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3713 case WM_INPUTLANGCHANGE
:
3714 /* Inform lisp thread of keyboard layout changes. */
3715 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3717 /* Clear dead keys in the keyboard state; for simplicity only
3718 preserve modifier key states. */
3723 GetKeyboardState (keystate
);
3724 for (i
= 0; i
< 256; i
++)
3741 SetKeyboardState (keystate
);
3746 /* Synchronize hot keys with normal input. */
3747 PostMessage (hwnd
, WM_KEYDOWN
, HIWORD (lParam
), 0);
3752 record_keyup (wParam
, lParam
);
3757 /* Ignore keystrokes we fake ourself; see below. */
3758 if (dpyinfo
->faked_key
== wParam
)
3760 dpyinfo
->faked_key
= 0;
3761 /* Make sure TranslateMessage sees them though (as long as
3762 they don't produce WM_CHAR messages). This ensures that
3763 indicator lights are toggled promptly on Windows 9x, for
3765 if (lispy_function_keys
[wParam
] != 0)
3767 windows_translate
= 1;
3773 /* Synchronize modifiers with current keystroke. */
3775 record_keydown (wParam
, lParam
);
3776 wParam
= map_keypad_keys (wParam
, (lParam
& 0x1000000L
) != 0);
3778 windows_translate
= 0;
3783 if (NILP (Vw32_pass_lwindow_to_system
))
3785 /* Prevent system from acting on keyup (which opens the
3786 Start menu if no other key was pressed) by simulating a
3787 press of Space which we will ignore. */
3788 if (GetAsyncKeyState (wParam
) & 1)
3790 if (NUMBERP (Vw32_phantom_key_code
))
3791 key
= XUINT (Vw32_phantom_key_code
) & 255;
3794 dpyinfo
->faked_key
= key
;
3795 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3798 if (!NILP (Vw32_lwindow_modifier
))
3802 if (NILP (Vw32_pass_rwindow_to_system
))
3804 if (GetAsyncKeyState (wParam
) & 1)
3806 if (NUMBERP (Vw32_phantom_key_code
))
3807 key
= XUINT (Vw32_phantom_key_code
) & 255;
3810 dpyinfo
->faked_key
= key
;
3811 keybd_event (key
, (BYTE
) MapVirtualKey (key
, 0), 0, 0);
3814 if (!NILP (Vw32_rwindow_modifier
))
3818 if (!NILP (Vw32_apps_modifier
))
3822 if (NILP (Vw32_pass_alt_to_system
))
3823 /* Prevent DefWindowProc from activating the menu bar if an
3824 Alt key is pressed and released by itself. */
3826 windows_translate
= 1;
3829 /* Decide whether to treat as modifier or function key. */
3830 if (NILP (Vw32_enable_caps_lock
))
3831 goto disable_lock_key
;
3832 windows_translate
= 1;
3835 /* Decide whether to treat as modifier or function key. */
3836 if (NILP (Vw32_enable_num_lock
))
3837 goto disable_lock_key
;
3838 windows_translate
= 1;
3841 /* Decide whether to treat as modifier or function key. */
3842 if (NILP (Vw32_scroll_lock_modifier
))
3843 goto disable_lock_key
;
3844 windows_translate
= 1;
3847 /* Ensure the appropriate lock key state (and indicator light)
3848 remains in the same state. We do this by faking another
3849 press of the relevant key. Apparently, this really is the
3850 only way to toggle the state of the indicator lights. */
3851 dpyinfo
->faked_key
= wParam
;
3852 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3853 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3854 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3855 KEYEVENTF_EXTENDEDKEY
| 0, 0);
3856 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
3857 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
3858 /* Ensure indicator lights are updated promptly on Windows 9x
3859 (TranslateMessage apparently does this), after forwarding
3861 post_character_message (hwnd
, msg
, wParam
, lParam
,
3862 w32_get_key_modifiers (wParam
, lParam
));
3863 windows_translate
= 1;
3867 case VK_PROCESSKEY
: /* Generated by IME. */
3868 windows_translate
= 1;
3871 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3872 which is confusing for purposes of key binding; convert
3873 VK_CANCEL events into VK_PAUSE events. */
3877 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3878 for purposes of key binding; convert these back into
3879 VK_NUMLOCK events, at least when we want to see NumLock key
3880 presses. (Note that there is never any possibility that
3881 VK_PAUSE with Ctrl really is C-Pause as per above.) */
3882 if (NILP (Vw32_enable_num_lock
) && modifier_set (VK_CONTROL
))
3883 wParam
= VK_NUMLOCK
;
3886 /* If not defined as a function key, change it to a WM_CHAR message. */
3887 if (lispy_function_keys
[wParam
] == 0)
3889 DWORD modifiers
= construct_console_modifiers ();
3891 if (!NILP (Vw32_recognize_altgr
)
3892 && modifier_set (VK_LCONTROL
) && modifier_set (VK_RMENU
))
3894 /* Always let TranslateMessage handle AltGr key chords;
3895 for some reason, ToAscii doesn't always process AltGr
3896 chords correctly. */
3897 windows_translate
= 1;
3899 else if ((modifiers
& (~SHIFT_PRESSED
& ~CAPSLOCK_ON
)) != 0)
3901 /* Handle key chords including any modifiers other
3902 than shift directly, in order to preserve as much
3903 modifier information as possible. */
3904 if ('A' <= wParam
&& wParam
<= 'Z')
3906 /* Don't translate modified alphabetic keystrokes,
3907 so the user doesn't need to constantly switch
3908 layout to type control or meta keystrokes when
3909 the normal layout translates alphabetic
3910 characters to non-ascii characters. */
3911 if (!modifier_set (VK_SHIFT
))
3912 wParam
+= ('a' - 'A');
3917 /* Try to handle other keystrokes by determining the
3918 base character (ie. translating the base key plus
3922 KEY_EVENT_RECORD key
;
3924 key
.bKeyDown
= TRUE
;
3925 key
.wRepeatCount
= 1;
3926 key
.wVirtualKeyCode
= wParam
;
3927 key
.wVirtualScanCode
= (lParam
& 0xFF0000) >> 16;
3928 key
.uChar
.AsciiChar
= 0;
3929 key
.dwControlKeyState
= modifiers
;
3931 add
= w32_kbd_patch_key (&key
);
3932 /* 0 means an unrecognised keycode, negative means
3933 dead key. Ignore both. */
3936 /* Forward asciified character sequence. */
3937 post_character_message
3938 (hwnd
, WM_CHAR
, key
.uChar
.AsciiChar
, lParam
,
3939 w32_get_key_modifiers (wParam
, lParam
));
3940 w32_kbd_patch_key (&key
);
3947 /* Let TranslateMessage handle everything else. */
3948 windows_translate
= 1;
3954 if (windows_translate
)
3956 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3958 windows_msg
.time
= GetMessageTime ();
3959 TranslateMessage (&windows_msg
);
3967 post_character_message (hwnd
, msg
, wParam
, lParam
,
3968 w32_get_key_modifiers (wParam
, lParam
));
3971 /* Simulate middle mouse button events when left and right buttons
3972 are used together, but only if user has two button mouse. */
3973 case WM_LBUTTONDOWN
:
3974 case WM_RBUTTONDOWN
:
3975 if (XINT (Vw32_num_mouse_buttons
) == 3)
3976 goto handle_plain_button
;
3979 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3980 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3982 if (button_state
& this)
3985 if (button_state
== 0)
3988 button_state
|= this;
3990 if (button_state
& other
)
3992 if (mouse_button_timer
)
3994 KillTimer (hwnd
, mouse_button_timer
);
3995 mouse_button_timer
= 0;
3997 /* Generate middle mouse event instead. */
3998 msg
= WM_MBUTTONDOWN
;
3999 button_state
|= MMOUSE
;
4001 else if (button_state
& MMOUSE
)
4003 /* Ignore button event if we've already generated a
4004 middle mouse down event. This happens if the
4005 user releases and press one of the two buttons
4006 after we've faked a middle mouse event. */
4011 /* Flush out saved message. */
4012 post_msg (&saved_mouse_button_msg
);
4014 wmsg
.dwModifiers
= w32_get_modifiers ();
4015 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4017 /* Clear message buffer. */
4018 saved_mouse_button_msg
.msg
.hwnd
= 0;
4022 /* Hold onto message for now. */
4023 mouse_button_timer
=
4024 SetTimer (hwnd
, MOUSE_BUTTON_ID
,
4025 XINT (Vw32_mouse_button_tolerance
), NULL
);
4026 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
4027 saved_mouse_button_msg
.msg
.message
= msg
;
4028 saved_mouse_button_msg
.msg
.wParam
= wParam
;
4029 saved_mouse_button_msg
.msg
.lParam
= lParam
;
4030 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
4031 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
4038 if (XINT (Vw32_num_mouse_buttons
) == 3)
4039 goto handle_plain_button
;
4042 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
4043 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
4045 if ((button_state
& this) == 0)
4048 button_state
&= ~this;
4050 if (button_state
& MMOUSE
)
4052 /* Only generate event when second button is released. */
4053 if ((button_state
& other
) == 0)
4056 button_state
&= ~MMOUSE
;
4058 if (button_state
) abort ();
4065 /* Flush out saved message if necessary. */
4066 if (saved_mouse_button_msg
.msg
.hwnd
)
4068 post_msg (&saved_mouse_button_msg
);
4071 wmsg
.dwModifiers
= w32_get_modifiers ();
4072 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4074 /* Always clear message buffer and cancel timer. */
4075 saved_mouse_button_msg
.msg
.hwnd
= 0;
4076 KillTimer (hwnd
, mouse_button_timer
);
4077 mouse_button_timer
= 0;
4079 if (button_state
== 0)
4084 case WM_MBUTTONDOWN
:
4086 handle_plain_button
:
4091 if (parse_button (msg
, &button
, &up
))
4093 if (up
) ReleaseCapture ();
4094 else SetCapture (hwnd
);
4095 button
= (button
== 0) ? LMOUSE
:
4096 ((button
== 1) ? MMOUSE
: RMOUSE
);
4098 button_state
&= ~button
;
4100 button_state
|= button
;
4104 wmsg
.dwModifiers
= w32_get_modifiers ();
4105 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4110 if (XINT (Vw32_mouse_move_interval
) <= 0
4111 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
4113 wmsg
.dwModifiers
= w32_get_modifiers ();
4114 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4118 /* Hang onto mouse move and scroll messages for a bit, to avoid
4119 sending such events to Emacs faster than it can process them.
4120 If we get more events before the timer from the first message
4121 expires, we just replace the first message. */
4123 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
4125 SetTimer (hwnd
, MOUSE_MOVE_ID
,
4126 XINT (Vw32_mouse_move_interval
), NULL
);
4128 /* Hold onto message for now. */
4129 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
4130 saved_mouse_move_msg
.msg
.message
= msg
;
4131 saved_mouse_move_msg
.msg
.wParam
= wParam
;
4132 saved_mouse_move_msg
.msg
.lParam
= lParam
;
4133 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
4134 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
4139 wmsg
.dwModifiers
= w32_get_modifiers ();
4140 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4144 wmsg
.dwModifiers
= w32_get_modifiers ();
4145 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4149 /* Flush out saved messages if necessary. */
4150 if (wParam
== mouse_button_timer
)
4152 if (saved_mouse_button_msg
.msg
.hwnd
)
4154 post_msg (&saved_mouse_button_msg
);
4155 saved_mouse_button_msg
.msg
.hwnd
= 0;
4157 KillTimer (hwnd
, mouse_button_timer
);
4158 mouse_button_timer
= 0;
4160 else if (wParam
== mouse_move_timer
)
4162 if (saved_mouse_move_msg
.msg
.hwnd
)
4164 post_msg (&saved_mouse_move_msg
);
4165 saved_mouse_move_msg
.msg
.hwnd
= 0;
4167 KillTimer (hwnd
, mouse_move_timer
);
4168 mouse_move_timer
= 0;
4173 /* Windows doesn't send us focus messages when putting up and
4174 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
4175 The only indication we get that something happened is receiving
4176 this message afterwards. So this is a good time to reset our
4177 keyboard modifiers' state. */
4182 /* We must ensure menu bar is fully constructed and up to date
4183 before allowing user interaction with it. To achieve this
4184 we send this message to the lisp thread and wait for a
4185 reply (whose value is not actually needed) to indicate that
4186 the menu bar is now ready for use, so we can now return.
4188 To remain responsive in the meantime, we enter a nested message
4189 loop that can process all other messages.
4191 However, we skip all this if the message results from calling
4192 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
4193 thread a message because it is blocked on us at this point. We
4194 set menubar_active before calling TrackPopupMenu to indicate
4195 this (there is no possibility of confusion with real menubar
4198 f
= x_window_to_frame (dpyinfo
, hwnd
);
4200 && (f
->output_data
.w32
->menubar_active
4201 /* We can receive this message even in the absence of a
4202 menubar (ie. when the system menu is activated) - in this
4203 case we do NOT want to forward the message, otherwise it
4204 will cause the menubar to suddenly appear when the user
4205 had requested it to be turned off! */
4206 || f
->output_data
.w32
->menubar_widget
== NULL
))
4210 deferred_msg msg_buf
;
4212 /* Detect if message has already been deferred; in this case
4213 we cannot return any sensible value to ignore this. */
4214 if (find_deferred_msg (hwnd
, msg
) != NULL
)
4217 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
4220 case WM_EXITMENULOOP
:
4221 f
= x_window_to_frame (dpyinfo
, hwnd
);
4223 /* Indicate that menubar can be modified again. */
4225 f
->output_data
.w32
->menubar_active
= 0;
4228 case WM_MEASUREITEM
:
4229 f
= x_window_to_frame (dpyinfo
, hwnd
);
4232 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
4234 if (pMis
->CtlType
== ODT_MENU
)
4236 /* Work out dimensions for popup menu titles. */
4237 char * title
= (char *) pMis
->itemData
;
4238 HDC hdc
= GetDC (hwnd
);
4239 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4240 LOGFONT menu_logfont
;
4244 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4245 menu_logfont
.lfWeight
= FW_BOLD
;
4246 menu_font
= CreateFontIndirect (&menu_logfont
);
4247 old_font
= SelectObject (hdc
, menu_font
);
4249 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
4250 pMis
->itemWidth
= size
.cx
;
4251 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
4252 if (pMis
->itemHeight
< size
.cy
)
4253 pMis
->itemHeight
= size
.cy
;
4255 SelectObject (hdc
, old_font
);
4256 DeleteObject (menu_font
);
4257 ReleaseDC (hwnd
, hdc
);
4264 f
= x_window_to_frame (dpyinfo
, hwnd
);
4267 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
4269 if (pDis
->CtlType
== ODT_MENU
)
4271 /* Draw popup menu title. */
4272 char * title
= (char *) pDis
->itemData
;
4273 HDC hdc
= pDis
->hDC
;
4274 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
4275 LOGFONT menu_logfont
;
4278 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
4279 menu_logfont
.lfWeight
= FW_BOLD
;
4280 menu_font
= CreateFontIndirect (&menu_logfont
);
4281 old_font
= SelectObject (hdc
, menu_font
);
4283 /* Always draw title as if not selected. */
4285 pDis
->rcItem
.left
+ GetSystemMetrics (SM_CXMENUCHECK
),
4287 ETO_OPAQUE
, &pDis
->rcItem
,
4288 title
, strlen (title
), NULL
);
4290 SelectObject (hdc
, old_font
);
4291 DeleteObject (menu_font
);
4298 /* Still not right - can't distinguish between clicks in the
4299 client area of the frame from clicks forwarded from the scroll
4300 bars - may have to hook WM_NCHITTEST to remember the mouse
4301 position and then check if it is in the client area ourselves. */
4302 case WM_MOUSEACTIVATE
:
4303 /* Discard the mouse click that activates a frame, allowing the
4304 user to click anywhere without changing point (or worse!).
4305 Don't eat mouse clicks on scrollbars though!! */
4306 if (LOWORD (lParam
) == HTCLIENT
)
4307 return MA_ACTIVATEANDEAT
;
4311 case WM_ACTIVATEAPP
:
4313 case WM_WINDOWPOSCHANGED
:
4315 /* Inform lisp thread that a frame might have just been obscured
4316 or exposed, so should recheck visibility of all frames. */
4317 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4321 dpyinfo
->faked_key
= 0;
4323 register_hot_keys (hwnd
);
4326 unregister_hot_keys (hwnd
);
4331 wmsg
.dwModifiers
= w32_get_modifiers ();
4332 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4336 wmsg
.dwModifiers
= w32_get_modifiers ();
4337 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4340 case WM_WINDOWPOSCHANGING
:
4343 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
4345 wp
.length
= sizeof (WINDOWPLACEMENT
);
4346 GetWindowPlacement (hwnd
, &wp
);
4348 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
4355 DWORD internal_border
;
4356 DWORD scrollbar_extra
;
4359 wp
.length
= sizeof(wp
);
4360 GetWindowRect (hwnd
, &wr
);
4364 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
4365 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
4366 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
4367 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
4371 memset (&rect
, 0, sizeof (rect
));
4372 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
4373 GetMenu (hwnd
) != NULL
);
4375 /* Force width and height of client area to be exact
4376 multiples of the character cell dimensions. */
4377 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
4378 - 2 * internal_border
- scrollbar_extra
)
4380 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
4381 - 2 * internal_border
)
4386 /* For right/bottom sizing we can just fix the sizes.
4387 However for top/left sizing we will need to fix the X
4388 and Y positions as well. */
4393 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
4394 && (lppos
->flags
& SWP_NOMOVE
) == 0)
4396 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
4403 lppos
->flags
|= SWP_NOMOVE
;
4414 case WM_EMACS_CREATESCROLLBAR
:
4415 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
4416 (struct scroll_bar
*) lParam
);
4418 case WM_EMACS_SHOWWINDOW
:
4419 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
4421 case WM_EMACS_SETFOREGROUND
:
4422 return SetForegroundWindow ((HWND
) wParam
);
4424 case WM_EMACS_SETWINDOWPOS
:
4426 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
4427 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
4428 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
4431 case WM_EMACS_DESTROYWINDOW
:
4432 DragAcceptFiles ((HWND
) wParam
, FALSE
);
4433 return DestroyWindow ((HWND
) wParam
);
4435 case WM_EMACS_TRACKPOPUPMENU
:
4440 pos
= (POINT
*)lParam
;
4441 flags
= TPM_CENTERALIGN
;
4442 if (button_state
& LMOUSE
)
4443 flags
|= TPM_LEFTBUTTON
;
4444 else if (button_state
& RMOUSE
)
4445 flags
|= TPM_RIGHTBUTTON
;
4447 /* Remember we did a SetCapture on the initial mouse down event,
4448 so for safety, we make sure the capture is cancelled now. */
4452 /* Use menubar_active to indicate that WM_INITMENU is from
4453 TrackPopupMenu below, and should be ignored. */
4454 f
= x_window_to_frame (dpyinfo
, hwnd
);
4456 f
->output_data
.w32
->menubar_active
= 1;
4458 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
4462 /* Eat any mouse messages during popupmenu */
4463 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
4465 /* Get the menu selection, if any */
4466 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
4468 retval
= LOWORD (amsg
.wParam
);
4484 /* Check for messages registered at runtime. */
4485 if (msg
== msh_mousewheel
)
4487 wmsg
.dwModifiers
= w32_get_modifiers ();
4488 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
4493 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
4497 /* The most common default return code for handled messages is 0. */
4502 my_create_window (f
)
4507 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
4509 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4512 /* Create and set up the w32 window for frame F. */
4515 w32_window (f
, window_prompting
, minibuffer_only
)
4517 long window_prompting
;
4518 int minibuffer_only
;
4522 /* Use the resource name as the top-level window name
4523 for looking up resources. Make a non-Lisp copy
4524 for the window manager, so GC relocation won't bother it.
4526 Elsewhere we specify the window name for the window manager. */
4529 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
4530 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
4531 strcpy (f
->namebuf
, str
);
4534 my_create_window (f
);
4536 validate_x_resource_name ();
4538 /* x_set_name normally ignores requests to set the name if the
4539 requested name is the same as the current name. This is the one
4540 place where that assumption isn't correct; f->name is set, but
4541 the server hasn't been told. */
4544 int explicit = f
->explicit_name
;
4546 f
->explicit_name
= 0;
4549 x_set_name (f
, name
, explicit);
4554 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
4555 initialize_frame_menubar (f
);
4557 if (FRAME_W32_WINDOW (f
) == 0)
4558 error ("Unable to create window");
4561 /* Handle the icon stuff for this window. Perhaps later we might
4562 want an x_set_icon_position which can be called interactively as
4570 Lisp_Object icon_x
, icon_y
;
4572 /* Set the position of the icon. Note that Windows 95 groups all
4573 icons in the tray. */
4574 icon_x
= x_get_arg (parms
, Qicon_left
, 0, 0, number
);
4575 icon_y
= x_get_arg (parms
, Qicon_top
, 0, 0, number
);
4576 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4578 CHECK_NUMBER (icon_x
, 0);
4579 CHECK_NUMBER (icon_y
, 0);
4581 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4582 error ("Both left and top icon corners of icon must be specified");
4586 if (! EQ (icon_x
, Qunbound
))
4587 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4590 /* Start up iconic or window? */
4591 x_wm_set_window_state
4592 (f
, (EQ (x_get_arg (parms
, Qvisibility
, 0, 0, symbol
), Qicon
)
4596 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4604 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4606 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
4607 Returns an Emacs frame object.\n\
4608 ALIST is an alist of frame parameters.\n\
4609 If the parameters specify that the frame should not have a minibuffer,\n\
4610 and do not specify a specific minibuffer window to use,\n\
4611 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4612 be shared by the new frame.\n\
4614 This function is an internal primitive--use `make-frame' instead.")
4619 Lisp_Object frame
, tem
;
4621 int minibuffer_only
= 0;
4622 long window_prompting
= 0;
4624 int count
= specpdl_ptr
- specpdl
;
4625 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4626 Lisp_Object display
;
4627 struct w32_display_info
*dpyinfo
;
4633 /* Use this general default value to start with
4634 until we know if this frame has a specified name. */
4635 Vx_resource_name
= Vinvocation_name
;
4637 display
= x_get_arg (parms
, Qdisplay
, 0, 0, string
);
4638 if (EQ (display
, Qunbound
))
4640 dpyinfo
= check_x_display_info (display
);
4642 kb
= dpyinfo
->kboard
;
4644 kb
= &the_only_kboard
;
4647 name
= x_get_arg (parms
, Qname
, "name", "Name", string
);
4649 && ! EQ (name
, Qunbound
)
4651 error ("Invalid frame name--not a string or nil");
4654 Vx_resource_name
= name
;
4656 /* See if parent window is specified. */
4657 parent
= x_get_arg (parms
, Qparent_id
, NULL
, NULL
, number
);
4658 if (EQ (parent
, Qunbound
))
4660 if (! NILP (parent
))
4661 CHECK_NUMBER (parent
, 0);
4663 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4664 /* No need to protect DISPLAY because that's not used after passing
4665 it to make_frame_without_minibuffer. */
4667 GCPRO4 (parms
, parent
, name
, frame
);
4668 tem
= x_get_arg (parms
, Qminibuffer
, 0, 0, symbol
);
4669 if (EQ (tem
, Qnone
) || NILP (tem
))
4670 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4671 else if (EQ (tem
, Qonly
))
4673 f
= make_minibuffer_frame ();
4674 minibuffer_only
= 1;
4676 else if (WINDOWP (tem
))
4677 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4681 XSETFRAME (frame
, f
);
4683 /* Note that Windows does support scroll bars. */
4684 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4685 /* By default, make scrollbars the system standard width. */
4686 f
->scroll_bar_pixel_width
= GetSystemMetrics (SM_CXVSCROLL
);
4688 f
->output_method
= output_w32
;
4689 f
->output_data
.w32
= (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4690 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
4692 FRAME_FONTSET (f
) = -1;
4695 = x_get_arg (parms
, Qicon_name
, "iconName", "Title", string
);
4696 if (! STRINGP (f
->icon_name
))
4697 f
->icon_name
= Qnil
;
4699 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4701 FRAME_KBOARD (f
) = kb
;
4704 /* Specify the parent under which to make this window. */
4708 f
->output_data
.w32
->parent_desc
= (Window
) parent
;
4709 f
->output_data
.w32
->explicit_parent
= 1;
4713 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4714 f
->output_data
.w32
->explicit_parent
= 0;
4717 /* Note that the frame has no physical cursor right now. */
4718 f
->phys_cursor_x
= -1;
4720 /* Set the name; the functions to which we pass f expect the name to
4722 if (EQ (name
, Qunbound
) || NILP (name
))
4724 f
->name
= build_string (dpyinfo
->w32_id_name
);
4725 f
->explicit_name
= 0;
4730 f
->explicit_name
= 1;
4731 /* use the frame's title when getting resources for this frame. */
4732 specbind (Qx_resource_name
, name
);
4735 /* Create fontsets from `global_fontset_alist' before handling fonts. */
4736 for (tem
= Vglobal_fontset_alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
4737 fs_register_fontset (f
, XCONS (tem
)->car
);
4739 /* Extract the window parameters from the supplied values
4740 that are needed to determine window geometry. */
4744 font
= x_get_arg (parms
, Qfont
, "font", "Font", string
);
4746 /* First, try whatever font the caller has specified. */
4749 tem
= Fquery_fontset (font
, Qnil
);
4751 font
= x_new_fontset (f
, XSTRING (tem
)->data
);
4753 font
= x_new_font (f
, XSTRING (font
)->data
);
4755 /* Try out a font which we hope has bold and italic variations. */
4756 if (!STRINGP (font
))
4757 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
4758 if (! STRINGP (font
))
4759 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-*-97-*-*-c-*-iso8859-1");
4760 /* If those didn't work, look for something which will at least work. */
4761 if (! STRINGP (font
))
4762 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-*-*-90-*-c-*-iso8859-1");
4764 if (! STRINGP (font
))
4765 font
= build_string ("Fixedsys");
4767 x_default_parameter (f
, parms
, Qfont
, font
,
4768 "font", "Font", string
);
4771 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4772 "borderwidth", "BorderWidth", number
);
4773 /* This defaults to 2 in order to match xterm. We recognize either
4774 internalBorderWidth or internalBorder (which is what xterm calls
4776 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4780 value
= x_get_arg (parms
, Qinternal_border_width
,
4781 "internalBorder", "BorderWidth", number
);
4782 if (! EQ (value
, Qunbound
))
4783 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4786 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4787 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (0),
4788 "internalBorderWidth", "BorderWidth", number
);
4789 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qt
,
4790 "verticalScrollBars", "ScrollBars", boolean
);
4792 /* Also do the stuff which must be set before the window exists. */
4793 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4794 "foreground", "Foreground", string
);
4795 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4796 "background", "Background", string
);
4797 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4798 "pointerColor", "Foreground", string
);
4799 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4800 "cursorColor", "Foreground", string
);
4801 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4802 "borderColor", "BorderColor", string
);
4804 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4805 "menuBar", "MenuBar", number
);
4806 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4807 "scrollBarWidth", "ScrollBarWidth", number
);
4808 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4809 "bufferPredicate", "BufferPredicate", symbol
);
4810 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4811 "title", "Title", string
);
4813 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4814 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4815 window_prompting
= x_figure_window_size (f
, parms
);
4817 if (window_prompting
& XNegative
)
4819 if (window_prompting
& YNegative
)
4820 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
4822 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
4826 if (window_prompting
& YNegative
)
4827 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
4829 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4832 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
4834 w32_window (f
, window_prompting
, minibuffer_only
);
4836 init_frame_faces (f
);
4838 /* We need to do this after creating the window, so that the
4839 icon-creation functions can say whose icon they're describing. */
4840 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4841 "bitmapIcon", "BitmapIcon", symbol
);
4843 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4844 "autoRaise", "AutoRaiseLower", boolean
);
4845 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4846 "autoLower", "AutoRaiseLower", boolean
);
4847 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4848 "cursorType", "CursorType", symbol
);
4850 /* Dimensions, especially f->height, must be done via change_frame_size.
4851 Change will not be effected unless different from the current
4856 SET_FRAME_WIDTH (f
, 0);
4857 change_frame_size (f
, height
, width
, 1, 0);
4859 /* Tell the server what size and position, etc, we want,
4860 and how badly we want them. */
4862 x_wm_set_size_hint (f
, window_prompting
, 0);
4865 tem
= x_get_arg (parms
, Qunsplittable
, 0, 0, boolean
);
4866 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4870 /* It is now ok to make the frame official
4871 even if we get an error below.
4872 And the frame needs to be on Vframe_list
4873 or making it visible won't work. */
4874 Vframe_list
= Fcons (frame
, Vframe_list
);
4876 /* Now that the frame is official, it counts as a reference to
4878 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4880 /* Make the window appear on the frame and enable display,
4881 unless the caller says not to. However, with explicit parent,
4882 Emacs cannot control visibility, so don't try. */
4883 if (! f
->output_data
.w32
->explicit_parent
)
4885 Lisp_Object visibility
;
4887 visibility
= x_get_arg (parms
, Qvisibility
, 0, 0, symbol
);
4888 if (EQ (visibility
, Qunbound
))
4891 if (EQ (visibility
, Qicon
))
4892 x_iconify_frame (f
);
4893 else if (! NILP (visibility
))
4894 x_make_frame_visible (f
);
4896 /* Must have been Qnil. */
4900 return unbind_to (count
, frame
);
4903 /* FRAME is used only to get a handle on the X display. We don't pass the
4904 display info directly because we're called from frame.c, which doesn't
4905 know about that structure. */
4907 x_get_focus_frame (frame
)
4908 struct frame
*frame
;
4910 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4912 if (! dpyinfo
->w32_focus_frame
)
4915 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4919 DEFUN ("w32-focus-frame", Fw32_focus_frame
, Sw32_focus_frame
, 1, 1, 0,
4920 "Give FRAME input focus, raising to foreground if necessary.")
4924 x_focus_on_frame (check_x_frame (frame
));
4929 struct font_info
*w32_load_bdf_font (struct frame
*f
, char *fontname
,
4930 int size
, char* filename
);
4933 w32_load_system_font (f
,fontname
,size
)
4938 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4939 Lisp_Object font_names
;
4941 /* Get a list of all the fonts that match this name. Once we
4942 have a list of matching fonts, we compare them against the fonts
4943 we already have loaded by comparing names. */
4944 font_names
= w32_list_fonts (f
, build_string (fontname
), size
, 100);
4946 if (!NILP (font_names
))
4950 #if 0 /* This code has nasty side effects that cause Emacs to crash. */
4952 /* First check if any are already loaded, as that is cheaper
4953 than loading another one. */
4954 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
4955 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4956 if (!strcmp (dpyinfo
->font_table
[i
].name
,
4957 XSTRING (XCONS (tail
)->car
)->data
)
4958 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
4959 XSTRING (XCONS (tail
)->car
)->data
))
4960 return (dpyinfo
->font_table
+ i
);
4962 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
4964 /* Because we need to support NT 3.x, we can't use EnumFontFamiliesEx
4965 so if fonts of the same name are available with several
4966 alternative character sets, the w32_list_fonts can fail to find a
4967 match even if the font exists. Try loading it anyway.
4974 /* Load the font and add it to the table. */
4976 char *full_name
, *encoding
;
4978 struct font_info
*fontp
;
4982 if (!fontname
|| !x_to_w32_font (fontname
, &lf
))
4985 if (!*lf
.lfFaceName
)
4986 /* If no name was specified for the font, we get a random font
4987 from CreateFontIndirect - this is not particularly
4988 desirable, especially since CreateFontIndirect does not
4989 fill out the missing name in lf, so we never know what we
4993 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
4995 /* Set bdf to NULL to indicate that this is a Windows font. */
5000 font
->hfont
= CreateFontIndirect (&lf
);
5002 if (font
->hfont
== NULL
)
5011 hdc
= GetDC (dpyinfo
->root_window
);
5012 oldobj
= SelectObject (hdc
, font
->hfont
);
5013 ok
= GetTextMetrics (hdc
, &font
->tm
);
5014 SelectObject (hdc
, oldobj
);
5015 ReleaseDC (dpyinfo
->root_window
, hdc
);
5022 w32_unload_font (dpyinfo
, font
);
5026 /* Do we need to create the table? */
5027 if (dpyinfo
->font_table_size
== 0)
5029 dpyinfo
->font_table_size
= 16;
5031 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
5032 * sizeof (struct font_info
));
5034 /* Do we need to grow the table? */
5035 else if (dpyinfo
->n_fonts
5036 >= dpyinfo
->font_table_size
)
5038 dpyinfo
->font_table_size
*= 2;
5040 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
5041 (dpyinfo
->font_table_size
5042 * sizeof (struct font_info
)));
5045 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
5047 /* Now fill in the slots of *FONTP. */
5050 fontp
->font_idx
= dpyinfo
->n_fonts
;
5051 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
5052 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
5054 /* Work out the font's full name. */
5055 full_name
= (char *)xmalloc (100);
5056 if (full_name
&& w32_to_x_font (&lf
, full_name
, 100))
5057 fontp
->full_name
= full_name
;
5060 /* If all else fails - just use the name we used to load it. */
5062 fontp
->full_name
= fontp
->name
;
5065 fontp
->size
= FONT_WIDTH (font
);
5066 fontp
->height
= FONT_HEIGHT (font
);
5068 /* The slot `encoding' specifies how to map a character
5069 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
5070 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
5071 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
5072 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
5073 2:0xA020..0xFF7F). For the moment, we don't know which charset
5074 uses this font. So, we set informatoin in fontp->encoding[1]
5075 which is never used by any charset. If mapping can't be
5076 decided, set FONT_ENCODING_NOT_DECIDED. */
5078 /* SJIS fonts need to be set to type 4, all others seem to work as
5079 type FONT_ENCODING_NOT_DECIDED. */
5080 encoding
= strrchr (fontp
->name
, '-');
5081 if (encoding
&& stricmp (encoding
+1, "sjis") == 0)
5082 fontp
->encoding
[1] = 4;
5084 fontp
->encoding
[1] = FONT_ENCODING_NOT_DECIDED
;
5086 /* The following three values are set to 0 under W32, which is
5087 what they get set to if XGetFontProperty fails under X. */
5088 fontp
->baseline_offset
= 0;
5089 fontp
->relative_compose
= 0;
5090 fontp
->default_ascent
= 0;
5099 /* Load font named FONTNAME of size SIZE for frame F, and return a
5100 pointer to the structure font_info while allocating it dynamically.
5101 If loading fails, return NULL. */
5103 w32_load_font (f
,fontname
,size
)
5108 Lisp_Object bdf_fonts
;
5109 struct font_info
*retval
= NULL
;
5111 bdf_fonts
= w32_list_bdf_fonts (build_string (fontname
));
5113 while (!retval
&& CONSP (bdf_fonts
))
5115 char *bdf_name
, *bdf_file
;
5116 Lisp_Object bdf_pair
;
5118 bdf_name
= XSTRING (XCONS (bdf_fonts
)->car
)->data
;
5119 bdf_pair
= Fassoc (XCONS (bdf_fonts
)->car
, Vw32_bdf_filename_alist
);
5120 bdf_file
= XSTRING (XCONS (bdf_pair
)->cdr
)->data
;
5122 retval
= w32_load_bdf_font (f
, bdf_name
, size
, bdf_file
);
5124 bdf_fonts
= XCONS (bdf_fonts
)->cdr
;
5130 return w32_load_system_font(f
, fontname
, size
);
5135 w32_unload_font (dpyinfo
, font
)
5136 struct w32_display_info
*dpyinfo
;
5141 if (font
->bdf
) w32_free_bdf_font (font
->bdf
);
5143 if (font
->hfont
) DeleteObject(font
->hfont
);
5148 /* The font conversion stuff between x and w32 */
5150 /* X font string is as follows (from faces.el)
5154 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
5155 * (weight\? "\\([^-]*\\)") ; 1
5156 * (slant "\\([ior]\\)") ; 2
5157 * (slant\? "\\([^-]?\\)") ; 2
5158 * (swidth "\\([^-]*\\)") ; 3
5159 * (adstyle "[^-]*") ; 4
5160 * (pixelsize "[0-9]+")
5161 * (pointsize "[0-9][0-9]+")
5162 * (resx "[0-9][0-9]+")
5163 * (resy "[0-9][0-9]+")
5164 * (spacing "[cmp?*]")
5165 * (avgwidth "[0-9]+")
5166 * (registry "[^-]+")
5167 * (encoding "[^-]+")
5169 * (setq x-font-regexp
5170 * (concat "\\`\\*?[-?*]"
5171 * foundry - family - weight\? - slant\? - swidth - adstyle -
5172 * pixelsize - pointsize - resx - resy - spacing - registry -
5173 * encoding "[-?*]\\*?\\'"
5175 * (setq x-font-regexp-head
5176 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
5177 * "\\([-*?]\\|\\'\\)"))
5178 * (setq x-font-regexp-slant (concat - slant -))
5179 * (setq x-font-regexp-weight (concat - weight -))
5183 #define FONT_START "[-?]"
5184 #define FONT_FOUNDRY "[^-]+"
5185 #define FONT_FAMILY "\\([^-]+\\)" /* 1 */
5186 #define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
5187 #define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
5188 #define FONT_SLANT "\\([ior]\\)" /* 3 */
5189 #define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
5190 #define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
5191 #define FONT_ADSTYLE "[^-]*"
5192 #define FONT_PIXELSIZE "[^-]*"
5193 #define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
5194 #define FONT_RESX "[0-9][0-9]+"
5195 #define FONT_RESY "[0-9][0-9]+"
5196 #define FONT_SPACING "[cmp?*]"
5197 #define FONT_AVGWIDTH "[0-9]+"
5198 #define FONT_REGISTRY "[^-]+"
5199 #define FONT_ENCODING "[^-]+"
5201 #define FONT_REGEXP ("\\`\\*?[-?*]" \
5208 FONT_PIXELSIZE "-" \
5209 FONT_POINTSIZE "-" \
5212 #define FONT_REGEXP_HEAD ("\\`[-?*]" \
5217 "\\([-*?]\\|\\'\\)")
5219 #define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
5220 #define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
5223 x_to_w32_weight (lpw
)
5226 if (!lpw
) return (FW_DONTCARE
);
5228 if (stricmp (lpw
,"heavy") == 0) return FW_HEAVY
;
5229 else if (stricmp (lpw
,"extrabold") == 0) return FW_EXTRABOLD
;
5230 else if (stricmp (lpw
,"bold") == 0) return FW_BOLD
;
5231 else if (stricmp (lpw
,"demibold") == 0) return FW_SEMIBOLD
;
5232 else if (stricmp (lpw
,"semibold") == 0) return FW_SEMIBOLD
;
5233 else if (stricmp (lpw
,"medium") == 0) return FW_MEDIUM
;
5234 else if (stricmp (lpw
,"normal") == 0) return FW_NORMAL
;
5235 else if (stricmp (lpw
,"light") == 0) return FW_LIGHT
;
5236 else if (stricmp (lpw
,"extralight") == 0) return FW_EXTRALIGHT
;
5237 else if (stricmp (lpw
,"thin") == 0) return FW_THIN
;
5244 w32_to_x_weight (fnweight
)
5247 if (fnweight
>= FW_HEAVY
) return "heavy";
5248 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
5249 if (fnweight
>= FW_BOLD
) return "bold";
5250 if (fnweight
>= FW_SEMIBOLD
) return "semibold";
5251 if (fnweight
>= FW_MEDIUM
) return "medium";
5252 if (fnweight
>= FW_NORMAL
) return "normal";
5253 if (fnweight
>= FW_LIGHT
) return "light";
5254 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
5255 if (fnweight
>= FW_THIN
) return "thin";
5261 x_to_w32_charset (lpcs
)
5264 if (!lpcs
) return (0);
5266 if (stricmp (lpcs
,"ansi") == 0) return ANSI_CHARSET
;
5267 else if (stricmp (lpcs
,"iso8859-1") == 0) return ANSI_CHARSET
;
5268 else if (stricmp (lpcs
, "ms-symbol") == 0) return SYMBOL_CHARSET
;
5269 else if (stricmp (lpcs
, "jis") == 0) return SHIFTJIS_CHARSET
;
5270 else if (stricmp (lpcs
, "ksc5601.1987") == 0) return HANGEUL_CHARSET
;
5271 else if (stricmp (lpcs
, "gb2312") == 0) return GB2312_CHARSET
;
5272 else if (stricmp (lpcs
, "big5") == 0) return CHINESEBIG5_CHARSET
;
5273 else if (stricmp (lpcs
, "ms-oem") == 0) return OEM_CHARSET
;
5275 #ifdef EASTEUROPE_CHARSET
5276 else if (stricmp (lpcs
, "iso8859-2") == 0) return EASTEUROPE_CHARSET
;
5277 else if (stricmp (lpcs
, "iso8859-3") == 0) return TURKISH_CHARSET
;
5278 else if (stricmp (lpcs
, "iso8859-4") == 0) return BALTIC_CHARSET
;
5279 else if (stricmp (lpcs
, "iso8859-5") == 0) return RUSSIAN_CHARSET
;
5280 else if (stricmp (lpcs
, "koi8") == 0) return RUSSIAN_CHARSET
;
5281 else if (stricmp (lpcs
, "iso8859-6") == 0) return ARABIC_CHARSET
;
5282 else if (stricmp (lpcs
, "iso8859-7") == 0) return GREEK_CHARSET
;
5283 else if (stricmp (lpcs
, "iso8859-8") == 0) return HEBREW_CHARSET
;
5284 else if (stricmp (lpcs
, "iso8859-9") == 0) return TURKISH_CHARSET
;
5285 else if (stricmp (lpcs
, "viscii") == 0) return VIETNAMESE_CHARSET
;
5286 else if (stricmp (lpcs
, "vscii") == 0) return VIETNAMESE_CHARSET
;
5287 else if (stricmp (lpcs
, "tis620") == 0) return THAI_CHARSET
;
5288 else if (stricmp (lpcs
, "mac") == 0) return MAC_CHARSET
;
5289 else if (stricmp (lpcs
, "ksc5601.1992") == 0) return JOHAB_CHARSET
;
5290 /* For backwards compatibility with previous 20.4 pretests. */
5291 else if (stricmp (lpcs
, "ksc5601") == 0) return HANGEUL_CHARSET
;
5292 else if (stricmp (lpcs
, "johab") == 0) return JOHAB_CHARSET
;
5295 #ifdef UNICODE_CHARSET
5296 else if (stricmp (lpcs
,"iso10646") == 0) return UNICODE_CHARSET
;
5297 else if (stricmp (lpcs
, "unicode") == 0) return UNICODE_CHARSET
;
5299 else if (lpcs
[0] == '#') return atoi (lpcs
+ 1);
5301 return DEFAULT_CHARSET
;
5305 w32_to_x_charset (fncharset
)
5308 static char buf
[16];
5312 /* ansi is considered iso8859-1, as most modern ansi fonts are. */
5313 case ANSI_CHARSET
: return "iso8859-1";
5314 case DEFAULT_CHARSET
: return "ascii-*";
5315 case SYMBOL_CHARSET
: return "ms-symbol";
5316 case SHIFTJIS_CHARSET
: return "jisx0208-sjis";
5317 case HANGEUL_CHARSET
: return "ksc5601.1987-*";
5318 case GB2312_CHARSET
: return "gb2312-*";
5319 case CHINESEBIG5_CHARSET
: return "big5-*";
5320 case OEM_CHARSET
: return "ms-oem";
5322 /* More recent versions of Windows (95 and NT4.0) define more
5324 #ifdef EASTEUROPE_CHARSET
5325 case EASTEUROPE_CHARSET
: return "iso8859-2";
5326 case TURKISH_CHARSET
: return "iso8859-9";
5327 case BALTIC_CHARSET
: return "iso8859-4";
5329 /* W95 with international support but not IE4 often has the
5330 KOI8-R codepage but not ISO8859-5. */
5331 case RUSSIAN_CHARSET
:
5332 if (!IsValidCodePage(28595) && IsValidCodePage(20886))
5336 case ARABIC_CHARSET
: return "iso8859-6";
5337 case GREEK_CHARSET
: return "iso8859-7";
5338 case HEBREW_CHARSET
: return "iso8859-8";
5339 case VIETNAMESE_CHARSET
: return "viscii1.1-*";
5340 case THAI_CHARSET
: return "tis620-*";
5341 case MAC_CHARSET
: return "mac-*";
5342 case JOHAB_CHARSET
: return "ksc5601.1992-*";
5346 #ifdef UNICODE_CHARSET
5347 case UNICODE_CHARSET
: return "iso10646-unicode";
5350 /* Encode numerical value of unknown charset. */
5351 sprintf (buf
, "*-#%u", fncharset
);
5356 w32_to_x_font (lplogfont
, lpxstr
, len
)
5357 LOGFONT
* lplogfont
;
5362 char height_pixels
[8];
5364 char width_pixels
[8];
5365 char *fontname_dash
;
5366 int display_resy
= one_w32_display_info
.height_in
;
5367 int display_resx
= one_w32_display_info
.width_in
;
5369 if (!lpxstr
) abort ();
5374 strncpy (fontname
, lplogfont
->lfFaceName
, 50);
5375 fontname
[49] = '\0'; /* Just in case */
5377 /* Replace dashes with underscores so the dashes are not
5379 fontname_dash
= fontname
;
5380 while (fontname_dash
= strchr (fontname_dash
, '-'))
5381 *fontname_dash
= '_';
5383 if (lplogfont
->lfHeight
)
5385 sprintf (height_pixels
, "%u", abs (lplogfont
->lfHeight
));
5386 sprintf (height_dpi
, "%u",
5387 abs (lplogfont
->lfHeight
) * 720 / display_resy
);
5391 strcpy (height_pixels
, "*");
5392 strcpy (height_dpi
, "*");
5394 if (lplogfont
->lfWidth
)
5395 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
5397 strcpy (width_pixels
, "*");
5399 _snprintf (lpxstr
, len
- 1,
5400 "-*-%s-%s-%c-*-*-%s-%s-%d-%d-%c-%s-%s",
5402 fontname
, /* family */
5403 w32_to_x_weight (lplogfont
->lfWeight
), /* weight */
5404 lplogfont
->lfItalic
?'i':'r', /* slant */
5406 /* add style name */
5407 height_pixels
, /* pixel size */
5408 height_dpi
, /* point size */
5409 display_resx
, /* resx */
5410 display_resy
, /* resy */
5411 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
)
5412 ? 'p' : 'c', /* spacing */
5413 width_pixels
, /* avg width */
5414 w32_to_x_charset (lplogfont
->lfCharSet
) /* charset registry
5418 lpxstr
[len
- 1] = 0; /* just to be sure */
5423 x_to_w32_font (lpxstr
, lplogfont
)
5425 LOGFONT
* lplogfont
;
5427 if (!lplogfont
) return (FALSE
);
5429 memset (lplogfont
, 0, sizeof (*lplogfont
));
5431 /* Set default value for each field. */
5433 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5434 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5435 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
5437 /* go for maximum quality */
5438 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
5439 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
5440 lplogfont
->lfQuality
= PROOF_QUALITY
;
5443 lplogfont
->lfCharSet
= DEFAULT_CHARSET
;
5444 lplogfont
->lfWeight
= FW_DONTCARE
;
5445 lplogfont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
5450 /* Provide a simple escape mechanism for specifying Windows font names
5451 * directly -- if font spec does not beginning with '-', assume this
5453 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
5459 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10],
5460 width
[10], resy
[10], remainder
[20];
5462 int dpi
= one_w32_display_info
.height_in
;
5464 fields
= sscanf (lpxstr
,
5465 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%19s",
5466 name
, weight
, &slant
, pixels
, height
, resy
, &pitch
, width
, remainder
);
5467 if (fields
== EOF
) return (FALSE
);
5469 if (fields
> 0 && name
[0] != '*')
5471 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
5472 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
5476 lplogfont
->lfFaceName
[0] = 0;
5481 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5485 if (!NILP (Vw32_enable_italics
))
5486 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
5490 if (fields
> 0 && pixels
[0] != '*')
5491 lplogfont
->lfHeight
= atoi (pixels
);
5495 if (fields
> 0 && resy
[0] != '*')
5497 tem
= atoi (pixels
);
5498 if (tem
> 0) dpi
= tem
;
5501 if (fields
> -1 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
5502 lplogfont
->lfHeight
= atoi (height
) * dpi
/ 720;
5505 lplogfont
->lfPitchAndFamily
=
5506 (fields
> 0 && pitch
== 'p') ? VARIABLE_PITCH
: FIXED_PITCH
;
5510 if (fields
> 0 && width
[0] != '*')
5511 lplogfont
->lfWidth
= atoi (width
) / 10;
5515 /* Strip the trailing '-' if present. (it shouldn't be, as it
5516 fails the test against xlfn-tight-regexp in fontset.el). */
5518 int len
= strlen (remainder
);
5519 if (len
> 0 && remainder
[len
-1] == '-')
5520 remainder
[len
-1] = 0;
5522 encoding
= remainder
;
5523 if (strncmp (encoding
, "*-", 2) == 0)
5525 lplogfont
->lfCharSet
= x_to_w32_charset (fields
> 0 ? encoding
: "");
5530 char name
[100], height
[10], width
[10], weight
[20];
5532 fields
= sscanf (lpxstr
,
5533 "%99[^:]:%9[^:]:%9[^:]:%19s",
5534 name
, height
, width
, weight
);
5536 if (fields
== EOF
) return (FALSE
);
5540 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
5541 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
5545 lplogfont
->lfFaceName
[0] = 0;
5551 lplogfont
->lfHeight
= atoi (height
);
5556 lplogfont
->lfWidth
= atoi (width
);
5560 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
5563 /* This makes TrueType fonts work better. */
5564 lplogfont
->lfHeight
= - abs (lplogfont
->lfHeight
);
5570 w32_font_match (lpszfont1
, lpszfont2
)
5574 char * s1
= lpszfont1
, *e1
, *w1
;
5575 char * s2
= lpszfont2
, *e2
, *w2
;
5577 if (s1
== NULL
|| s2
== NULL
) return (FALSE
);
5579 if (*s1
== '-') s1
++;
5580 if (*s2
== '-') s2
++;
5584 int len1
, len2
, len3
=0;
5586 e1
= strchr (s1
, '-');
5587 e2
= strchr (s2
, '-');
5588 w1
= strchr (s1
, '*');
5589 w2
= strchr (s2
, '*');
5602 if (w2
&& w2
< e2
&& ( len3
== 0 || (w2
- s2
) < len3
))
5605 /* Whole field is not a wildcard, and ...*/
5606 if (*s1
!= '*' && *s2
!= '*' && *s1
!= '-' && *s2
!= '-'
5607 /* Lengths are different and there are no wildcards, or ... */
5608 && ((len1
!= len2
&& len3
== 0) ||
5609 /* strings don't match up until first wildcard or end. */
5610 strnicmp (s1
, s2
, len3
> 0 ? len3
: len1
) != 0))
5613 if (e1
== NULL
|| e2
== NULL
)
5621 typedef struct enumfont_t
5626 XFontStruct
*size_ref
;
5627 Lisp_Object
*pattern
;
5632 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
5634 NEWTEXTMETRIC
* lptm
;
5638 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
5641 /* Check that the character set matches if it was specified */
5642 if (lpef
->logfont
.lfCharSet
!= DEFAULT_CHARSET
&&
5643 lplf
->elfLogFont
.lfCharSet
!= lpef
->logfont
.lfCharSet
)
5646 /* We want all fonts cached, so don't compare sizes just yet */
5647 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
5650 Lisp_Object width
= Qnil
;
5652 if (!NILP (*(lpef
->pattern
)) && FontType
!= RASTER_FONTTYPE
)
5654 /* Scalable fonts are as big as you want them to be. */
5655 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
5656 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
5659 /* The MaxCharWidth is not valid at this stage for scalable fonts. */
5660 if (FontType
== RASTER_FONTTYPE
)
5661 width
= make_number (lptm
->tmMaxCharWidth
);
5663 if (!w32_to_x_font (&(lplf
->elfLogFont
), buf
, 100))
5666 if (NILP (*(lpef
->pattern
)) ||
5667 w32_font_match (buf
, XSTRING (*(lpef
->pattern
))->data
))
5669 *lpef
->tail
= Fcons (Fcons (build_string (buf
), width
), Qnil
);
5670 lpef
->tail
= &(XCONS (*lpef
->tail
)->cdr
);
5679 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
5681 NEWTEXTMETRIC
* lptm
;
5685 return EnumFontFamilies (lpef
->hdc
,
5686 lplf
->elfLogFont
.lfFaceName
,
5687 (FONTENUMPROC
) enum_font_cb2
,
5692 /* Interface to fontset handler. (adapted from mw32font.c in Meadow
5693 and xterm.c in Emacs 20.3) */
5695 Lisp_Object
w32_list_bdf_fonts (Lisp_Object pattern
)
5697 char *fontname
, *ptnstr
;
5698 Lisp_Object list
, tem
, newlist
= Qnil
;
5700 list
= Vw32_bdf_filename_alist
;
5701 ptnstr
= XSTRING (pattern
)->data
;
5703 for ( ; CONSP (list
); list
= XCONS (list
)->cdr
)
5705 tem
= XCONS (list
)->car
;
5707 fontname
= XSTRING (XCONS (tem
)->car
)->data
;
5708 else if (STRINGP (tem
))
5709 fontname
= XSTRING (tem
)->data
;
5713 if (w32_font_match (fontname
, ptnstr
))
5714 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
5720 /* Return a list of names of available fonts matching PATTERN on frame
5721 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
5722 to be listed. Frame F NULL means we have not yet created any
5723 frame, which means we can't get proper size info, as we don't have
5724 a device context to use for GetTextMetrics.
5725 MAXNAMES sets a limit on how many fonts to match. */
5728 w32_list_fonts (FRAME_PTR f
, Lisp_Object pattern
, int size
, int maxnames
)
5730 Lisp_Object patterns
, key
, tem
, tpat
;
5731 Lisp_Object list
= Qnil
, newlist
= Qnil
, second_best
= Qnil
;
5732 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
5734 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
5735 if (NILP (patterns
))
5736 patterns
= Fcons (pattern
, Qnil
);
5738 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
5742 tpat
= XCONS (patterns
)->car
;
5744 /* See if we cached the result for this particular query.
5745 The cache is an alist of the form:
5746 ((PATTERN (FONTNAME . WIDTH) ...) ...)
5748 if (tem
= XCONS (dpyinfo
->name_list_element
)->cdr
,
5749 !NILP (list
= Fassoc (tpat
, tem
)))
5751 list
= Fcdr_safe (list
);
5752 /* We have a cached list. Don't have to get the list again. */
5757 /* At first, put PATTERN in the cache. */
5763 x_to_w32_font (STRINGP (tpat
) ? XSTRING (tpat
)->data
:
5766 ef
.hdc
= GetDC (dpyinfo
->root_window
);
5768 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
,
5771 ReleaseDC (dpyinfo
->root_window
, ef
.hdc
);
5776 /* Make a list of the fonts we got back.
5777 Store that in the font cache for the display. */
5778 XCONS (dpyinfo
->name_list_element
)->cdr
5779 = Fcons (Fcons (tpat
, list
),
5780 XCONS (dpyinfo
->name_list_element
)->cdr
);
5783 if (NILP (list
)) continue; /* Try the remaining alternatives. */
5785 newlist
= second_best
= Qnil
;
5787 /* Make a list of the fonts that have the right width. */
5788 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
5791 tem
= XCONS (list
)->car
;
5795 if (NILP (XCONS (tem
)->car
))
5799 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
5802 if (!INTEGERP (XCONS (tem
)->cdr
))
5804 /* Since we don't yet know the size of the font, we must
5805 load it and try GetTextMetrics. */
5806 W32FontStruct thisinfo
;
5811 if (!x_to_w32_font (XSTRING (XCONS (tem
)->car
)->data
, &lf
))
5815 thisinfo
.bdf
= NULL
;
5816 thisinfo
.hfont
= CreateFontIndirect (&lf
);
5817 if (thisinfo
.hfont
== NULL
)
5820 hdc
= GetDC (dpyinfo
->root_window
);
5821 oldobj
= SelectObject (hdc
, thisinfo
.hfont
);
5822 if (GetTextMetrics (hdc
, &thisinfo
.tm
))
5823 XCONS (tem
)->cdr
= make_number (FONT_WIDTH (&thisinfo
));
5825 XCONS (tem
)->cdr
= make_number (0);
5826 SelectObject (hdc
, oldobj
);
5827 ReleaseDC (dpyinfo
->root_window
, hdc
);
5828 DeleteObject(thisinfo
.hfont
);
5831 found_size
= XINT (XCONS (tem
)->cdr
);
5832 if (found_size
== size
)
5833 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
5835 /* keep track of the closest matching size in case
5836 no exact match is found. */
5837 else if (found_size
> 0)
5839 if (NILP (second_best
))
5841 else if (found_size
< size
)
5843 if (XINT (XCONS (second_best
)->cdr
) > size
5844 || XINT (XCONS (second_best
)->cdr
) < found_size
)
5849 if (XINT (XCONS (second_best
)->cdr
) > size
5850 && XINT (XCONS (second_best
)->cdr
) >
5857 if (!NILP (newlist
))
5859 else if (!NILP (second_best
))
5861 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
5866 /* Include any bdf fonts. */
5868 Lisp_Object combined
[2];
5869 combined
[0] = w32_list_bdf_fonts (pattern
);
5870 combined
[1] = newlist
;
5871 newlist
= Fnconc(2, combined
);
5877 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5879 w32_get_font_info (f
, font_idx
)
5883 return (FRAME_W32_FONT_TABLE (f
) + font_idx
);
5888 w32_query_font (struct frame
*f
, char *fontname
)
5891 struct font_info
*pfi
;
5893 pfi
= FRAME_W32_FONT_TABLE (f
);
5895 for (i
= 0; i
< one_w32_display_info
.n_fonts
;i
++, pfi
++)
5897 if (strcmp(pfi
->name
, fontname
) == 0) return pfi
;
5903 /* Find a CCL program for a font specified by FONTP, and set the member
5904 `encoder' of the structure. */
5907 w32_find_ccl_program (fontp
)
5908 struct font_info
*fontp
;
5910 extern Lisp_Object Vfont_ccl_encoder_alist
, Vccl_program_table
;
5911 extern Lisp_Object Qccl_program_idx
;
5912 extern Lisp_Object
resolve_symbol_ccl_program ();
5913 Lisp_Object list
, elt
, ccl_prog
, ccl_id
;
5915 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCONS (list
)->cdr
)
5917 elt
= XCONS (list
)->car
;
5919 && STRINGP (XCONS (elt
)->car
)
5920 && (fast_c_string_match_ignore_case (XCONS (elt
)->car
, fontp
->name
)
5923 if (SYMBOLP (XCONS (elt
)->cdr
) &&
5924 (!NILP (ccl_id
= Fget (XCONS (elt
)->cdr
, Qccl_program_idx
))))
5926 ccl_prog
= XVECTOR (Vccl_program_table
)->contents
[XUINT (ccl_id
)];
5927 if (!CONSP (ccl_prog
)) continue;
5928 ccl_prog
= XCONS (ccl_prog
)->cdr
;
5932 ccl_prog
= XCONS (elt
)->cdr
;
5933 if (!VECTORP (ccl_prog
)) continue;
5937 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
5938 setup_ccl_program (fontp
->font_encoder
,
5939 resolve_symbol_ccl_program (ccl_prog
));
5947 #include "x-list-font.c"
5949 DEFUN ("x-list-fonts", Fx_list_fonts
, Sx_list_fonts
, 1, 4, 0,
5950 "Return a list of the names of available fonts matching PATTERN.\n\
5951 If optional arguments FACE and FRAME are specified, return only fonts\n\
5952 the same size as FACE on FRAME.\n\
5954 PATTERN is a string, perhaps with wildcard characters;\n\
5955 the * character matches any substring, and\n\
5956 the ? character matches any single character.\n\
5957 PATTERN is case-insensitive.\n\
5958 FACE is a face name--a symbol.\n\
5960 The return value is a list of strings, suitable as arguments to\n\
5963 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
5964 even if they match PATTERN and FACE.\n\
5966 The optional fourth argument MAXIMUM sets a limit on how many\n\
5967 fonts to match. The first MAXIMUM fonts are reported.")
5968 (pattern
, face
, frame
, maximum
)
5969 Lisp_Object pattern
, face
, frame
, maximum
;
5974 XFontStruct
*size_ref
;
5975 Lisp_Object namelist
;
5980 CHECK_STRING (pattern
, 0);
5982 CHECK_SYMBOL (face
, 1);
5984 f
= check_x_frame (frame
);
5986 /* Determine the width standard for comparison with the fonts we find. */
5994 /* Don't die if we get called with a terminal frame. */
5995 if (! FRAME_W32_P (f
))
5996 error ("non-w32 frame used in `x-list-fonts'");
5998 face_id
= face_name_id_number (f
, face
);
6000 if (face_id
< 0 || face_id
>= FRAME_N_PARAM_FACES (f
)
6001 || FRAME_PARAM_FACES (f
) [face_id
] == 0)
6002 size_ref
= f
->output_data
.w32
->font
;
6005 size_ref
= FRAME_PARAM_FACES (f
) [face_id
]->font
;
6006 if (size_ref
== (XFontStruct
*) (~0))
6007 size_ref
= f
->output_data
.w32
->font
;
6011 /* See if we cached the result for this particular query. */
6012 list
= Fassoc (pattern
,
6013 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6015 /* We have info in the cache for this PATTERN. */
6018 Lisp_Object tem
, newlist
;
6020 /* We have info about this pattern. */
6021 list
= XCONS (list
)->cdr
;
6028 /* Filter the cached info and return just the fonts that match FACE. */
6030 for (tem
= list
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
6032 struct font_info
*fontinf
;
6033 XFontStruct
*thisinfo
= NULL
;
6035 fontinf
= w32_load_font (f
, XSTRING (XCONS (tem
)->car
)->data
, 0);
6037 thisinfo
= (XFontStruct
*)fontinf
->font
;
6038 if (thisinfo
&& same_size_fonts (thisinfo
, size_ref
))
6039 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6041 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
6052 ef
.pattern
= &pattern
;
6055 x_to_w32_font (STRINGP (pattern
) ? XSTRING (pattern
)->data
: NULL
, &ef
.logfont
);
6058 ef
.hdc
= GetDC (FRAME_W32_WINDOW (f
));
6060 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
, (LPARAM
)&ef
);
6062 ReleaseDC (FRAME_W32_WINDOW (f
), ef
.hdc
);
6072 /* Make a list of all the fonts we got back.
6073 Store that in the font cache for the display. */
6074 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
6075 = Fcons (Fcons (pattern
, namelist
),
6076 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6078 /* Make a list of the fonts that have the right width. */
6081 for (i
= 0; i
< ef
.numFonts
; i
++)
6089 struct font_info
*fontinf
;
6090 XFontStruct
*thisinfo
= NULL
;
6093 fontinf
= w32_load_font (f
, XSTRING (Fcar (cur
))->data
, 0);
6095 thisinfo
= (XFontStruct
*)fontinf
->font
;
6097 keeper
= thisinfo
&& same_size_fonts (thisinfo
, size_ref
);
6099 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
6104 list
= Fcons (build_string (XSTRING (Fcar (cur
))->data
), list
);
6108 list
= Fnreverse (list
);
6115 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts
, Sw32_find_bdf_fonts
,
6117 "Return a list of BDF fonts in DIR, suitable for appending to\n\
6118 w32-bdf-filename-alist. Fonts which do not contain an xfld description\n\
6119 will not be included in the list. DIR may be a list of directories.")
6121 Lisp_Object directory
;
6123 Lisp_Object list
= Qnil
;
6124 struct gcpro gcpro1
, gcpro2
;
6126 if (!CONSP (directory
))
6127 return w32_find_bdf_fonts_in_dir (directory
);
6129 for ( ; CONSP (directory
); directory
= XCONS (directory
)->cdr
)
6131 Lisp_Object pair
[2];
6134 GCPRO2 (directory
, list
);
6135 pair
[1] = w32_find_bdf_fonts_in_dir( XCONS (directory
)->car
);
6136 list
= Fnconc( 2, pair
);
6142 /* Find BDF files in a specified directory. (use GCPRO when calling,
6143 as this calls lisp to get a directory listing). */
6144 Lisp_Object
w32_find_bdf_fonts_in_dir( Lisp_Object directory
)
6146 Lisp_Object filelist
, list
= Qnil
;
6149 if (!STRINGP(directory
))
6152 filelist
= Fdirectory_files (directory
, Qt
,
6153 build_string (".*\\.[bB][dD][fF]"), Qt
);
6155 for ( ; CONSP(filelist
); filelist
= XCONS (filelist
)->cdr
)
6157 Lisp_Object filename
= XCONS (filelist
)->car
;
6158 if (w32_BDF_to_x_font (XSTRING (filename
)->data
, fontname
, 100))
6159 store_in_alist (&list
, build_string (fontname
), filename
);
6165 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
6166 "Return non-nil if color COLOR is supported on frame FRAME.\n\
6167 If FRAME is omitted or nil, use the selected frame.")
6169 Lisp_Object color
, frame
;
6172 FRAME_PTR f
= check_x_frame (frame
);
6174 CHECK_STRING (color
, 1);
6176 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6182 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
6183 "Return a description of the color named COLOR on frame FRAME.\n\
6184 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
6185 These values appear to range from 0 to 65280 or 65535, depending\n\
6186 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
6187 If FRAME is omitted or nil, use the selected frame.")
6189 Lisp_Object color
, frame
;
6192 FRAME_PTR f
= check_x_frame (frame
);
6194 CHECK_STRING (color
, 1);
6196 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
6200 rgb
[0] = make_number ((GetRValue (foo
) << 8) | GetRValue (foo
));
6201 rgb
[1] = make_number ((GetGValue (foo
) << 8) | GetGValue (foo
));
6202 rgb
[2] = make_number ((GetBValue (foo
) << 8) | GetBValue (foo
));
6203 return Flist (3, rgb
);
6209 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
6210 "Return t if the X display supports color.\n\
6211 The optional argument DISPLAY specifies which display to ask about.\n\
6212 DISPLAY should be either a frame or a display name (a string).\n\
6213 If omitted or nil, that stands for the selected frame's display.")
6215 Lisp_Object display
;
6217 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6219 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
6225 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
6227 "Return t if the X display supports shades of gray.\n\
6228 Note that color displays do support shades of gray.\n\
6229 The optional argument DISPLAY specifies which display to ask about.\n\
6230 DISPLAY should be either a frame or a display name (a string).\n\
6231 If omitted or nil, that stands for the selected frame's display.")
6233 Lisp_Object display
;
6235 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6237 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
6243 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
6245 "Returns the width in pixels of the X display DISPLAY.\n\
6246 The optional argument DISPLAY specifies which display to ask about.\n\
6247 DISPLAY should be either a frame or a display name (a string).\n\
6248 If omitted or nil, that stands for the selected frame's display.")
6250 Lisp_Object display
;
6252 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6254 return make_number (dpyinfo
->width
);
6257 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
6258 Sx_display_pixel_height
, 0, 1, 0,
6259 "Returns the height in pixels of the X display DISPLAY.\n\
6260 The optional argument DISPLAY specifies which display to ask about.\n\
6261 DISPLAY should be either a frame or a display name (a string).\n\
6262 If omitted or nil, that stands for the selected frame's display.")
6264 Lisp_Object display
;
6266 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6268 return make_number (dpyinfo
->height
);
6271 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
6273 "Returns the number of bitplanes of the display DISPLAY.\n\
6274 The optional argument DISPLAY specifies which display to ask about.\n\
6275 DISPLAY should be either a frame or a display name (a string).\n\
6276 If omitted or nil, that stands for the selected frame's display.")
6278 Lisp_Object display
;
6280 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6282 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
6285 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
6287 "Returns the number of color cells of the display DISPLAY.\n\
6288 The optional argument DISPLAY specifies which display to ask about.\n\
6289 DISPLAY should be either a frame or a display name (a string).\n\
6290 If omitted or nil, that stands for the selected frame's display.")
6292 Lisp_Object display
;
6294 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6298 hdc
= GetDC (dpyinfo
->root_window
);
6299 if (dpyinfo
->has_palette
)
6300 cap
= GetDeviceCaps (hdc
,SIZEPALETTE
);
6302 cap
= GetDeviceCaps (hdc
,NUMCOLORS
);
6304 ReleaseDC (dpyinfo
->root_window
, hdc
);
6306 return make_number (cap
);
6309 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
6310 Sx_server_max_request_size
,
6312 "Returns the maximum request size of the server of display DISPLAY.\n\
6313 The optional argument DISPLAY specifies which display to ask about.\n\
6314 DISPLAY should be either a frame or a display name (a string).\n\
6315 If omitted or nil, that stands for the selected frame's display.")
6317 Lisp_Object display
;
6319 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6321 return make_number (1);
6324 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
6325 "Returns the vendor ID string of the W32 system (Microsoft).\n\
6326 The optional argument DISPLAY specifies which display to ask about.\n\
6327 DISPLAY should be either a frame or a display name (a string).\n\
6328 If omitted or nil, that stands for the selected frame's display.")
6330 Lisp_Object display
;
6332 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6333 char *vendor
= "Microsoft Corp.";
6335 if (! vendor
) vendor
= "";
6336 return build_string (vendor
);
6339 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
6340 "Returns the version numbers of the server of display DISPLAY.\n\
6341 The value is a list of three integers: the major and minor\n\
6342 version numbers, and the vendor-specific release\n\
6343 number. See also the function `x-server-vendor'.\n\n\
6344 The optional argument DISPLAY specifies which display to ask about.\n\
6345 DISPLAY should be either a frame or a display name (a string).\n\
6346 If omitted or nil, that stands for the selected frame's display.")
6348 Lisp_Object display
;
6350 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6352 return Fcons (make_number (w32_major_version
),
6353 Fcons (make_number (w32_minor_version
), Qnil
));
6356 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
6357 "Returns the number of screens on the server of display DISPLAY.\n\
6358 The optional argument DISPLAY specifies which display to ask about.\n\
6359 DISPLAY should be either a frame or a display name (a string).\n\
6360 If omitted or nil, that stands for the selected frame's display.")
6362 Lisp_Object display
;
6364 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6366 return make_number (1);
6369 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
6370 "Returns the height in millimeters of the X display DISPLAY.\n\
6371 The optional argument DISPLAY specifies which display to ask about.\n\
6372 DISPLAY should be either a frame or a display name (a string).\n\
6373 If omitted or nil, that stands for the selected frame's display.")
6375 Lisp_Object display
;
6377 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6381 hdc
= GetDC (dpyinfo
->root_window
);
6383 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
6385 ReleaseDC (dpyinfo
->root_window
, hdc
);
6387 return make_number (cap
);
6390 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
6391 "Returns the width in millimeters of the X display DISPLAY.\n\
6392 The optional argument DISPLAY specifies which display to ask about.\n\
6393 DISPLAY should be either a frame or a display name (a string).\n\
6394 If omitted or nil, that stands for the selected frame's display.")
6396 Lisp_Object display
;
6398 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6403 hdc
= GetDC (dpyinfo
->root_window
);
6405 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
6407 ReleaseDC (dpyinfo
->root_window
, hdc
);
6409 return make_number (cap
);
6412 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
6413 Sx_display_backing_store
, 0, 1, 0,
6414 "Returns an indication of whether display DISPLAY does backing store.\n\
6415 The value may be `always', `when-mapped', or `not-useful'.\n\
6416 The optional argument DISPLAY specifies which display to ask about.\n\
6417 DISPLAY should be either a frame or a display name (a string).\n\
6418 If omitted or nil, that stands for the selected frame's display.")
6420 Lisp_Object display
;
6422 return intern ("not-useful");
6425 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
6426 Sx_display_visual_class
, 0, 1, 0,
6427 "Returns the visual class of the display DISPLAY.\n\
6428 The value is one of the symbols `static-gray', `gray-scale',\n\
6429 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
6430 The optional argument DISPLAY specifies which display to ask about.\n\
6431 DISPLAY should be either a frame or a display name (a string).\n\
6432 If omitted or nil, that stands for the selected frame's display.")
6434 Lisp_Object display
;
6436 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6439 switch (dpyinfo
->visual
->class)
6441 case StaticGray
: return (intern ("static-gray"));
6442 case GrayScale
: return (intern ("gray-scale"));
6443 case StaticColor
: return (intern ("static-color"));
6444 case PseudoColor
: return (intern ("pseudo-color"));
6445 case TrueColor
: return (intern ("true-color"));
6446 case DirectColor
: return (intern ("direct-color"));
6448 error ("Display has an unknown visual class");
6452 error ("Display has an unknown visual class");
6455 DEFUN ("x-display-save-under", Fx_display_save_under
,
6456 Sx_display_save_under
, 0, 1, 0,
6457 "Returns t if the display DISPLAY supports the save-under feature.\n\
6458 The optional argument DISPLAY specifies which display to ask about.\n\
6459 DISPLAY should be either a frame or a display name (a string).\n\
6460 If omitted or nil, that stands for the selected frame's display.")
6462 Lisp_Object display
;
6464 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6471 register struct frame
*f
;
6473 return PIXEL_WIDTH (f
);
6478 register struct frame
*f
;
6480 return PIXEL_HEIGHT (f
);
6485 register struct frame
*f
;
6487 return FONT_WIDTH (f
->output_data
.w32
->font
);
6492 register struct frame
*f
;
6494 return f
->output_data
.w32
->line_height
;
6498 x_screen_planes (frame
)
6501 return (FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
*
6502 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
);
6505 /* Return the display structure for the display named NAME.
6506 Open a new connection if necessary. */
6508 struct w32_display_info
*
6509 x_display_info_for_name (name
)
6513 struct w32_display_info
*dpyinfo
;
6515 CHECK_STRING (name
, 0);
6517 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
6519 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
6522 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
6527 /* Use this general default value to start with. */
6528 Vx_resource_name
= Vinvocation_name
;
6530 validate_x_resource_name ();
6532 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
6533 (char *) XSTRING (Vx_resource_name
)->data
);
6536 error ("Cannot connect to server %s", XSTRING (name
)->data
);
6539 XSETFASTINT (Vwindow_system_version
, 3);
6544 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
6545 1, 3, 0, "Open a connection to a server.\n\
6546 DISPLAY is the name of the display to connect to.\n\
6547 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
6548 If the optional third arg MUST-SUCCEED is non-nil,\n\
6549 terminate Emacs if we can't open the connection.")
6550 (display
, xrm_string
, must_succeed
)
6551 Lisp_Object display
, xrm_string
, must_succeed
;
6553 unsigned int n_planes
;
6554 unsigned char *xrm_option
;
6555 struct w32_display_info
*dpyinfo
;
6557 CHECK_STRING (display
, 0);
6558 if (! NILP (xrm_string
))
6559 CHECK_STRING (xrm_string
, 1);
6561 if (! EQ (Vwindow_system
, intern ("w32")))
6562 error ("Not using Microsoft Windows");
6564 /* Allow color mapping to be defined externally; first look in user's
6565 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
6567 Lisp_Object color_file
;
6568 struct gcpro gcpro1
;
6570 color_file
= build_string("~/rgb.txt");
6572 GCPRO1 (color_file
);
6574 if (NILP (Ffile_readable_p (color_file
)))
6576 Fexpand_file_name (build_string ("rgb.txt"),
6577 Fsymbol_value (intern ("data-directory")));
6579 Vw32_color_map
= Fw32_load_color_file (color_file
);
6583 if (NILP (Vw32_color_map
))
6584 Vw32_color_map
= Fw32_default_color_map ();
6586 if (! NILP (xrm_string
))
6587 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
6589 xrm_option
= (unsigned char *) 0;
6591 /* Use this general default value to start with. */
6592 /* First remove .exe suffix from invocation-name - it looks ugly. */
6594 char basename
[ MAX_PATH
], *str
;
6596 strcpy (basename
, XSTRING (Vinvocation_name
)->data
);
6597 str
= strrchr (basename
, '.');
6599 Vinvocation_name
= build_string (basename
);
6601 Vx_resource_name
= Vinvocation_name
;
6603 validate_x_resource_name ();
6605 /* This is what opens the connection and sets x_current_display.
6606 This also initializes many symbols, such as those used for input. */
6607 dpyinfo
= w32_term_init (display
, xrm_option
,
6608 (char *) XSTRING (Vx_resource_name
)->data
);
6612 if (!NILP (must_succeed
))
6613 fatal ("Cannot connect to server %s.\n",
6614 XSTRING (display
)->data
);
6616 error ("Cannot connect to server %s", XSTRING (display
)->data
);
6621 XSETFASTINT (Vwindow_system_version
, 3);
6625 DEFUN ("x-close-connection", Fx_close_connection
,
6626 Sx_close_connection
, 1, 1, 0,
6627 "Close the connection to DISPLAY's server.\n\
6628 For DISPLAY, specify either a frame or a display name (a string).\n\
6629 If DISPLAY is nil, that stands for the selected frame's display.")
6631 Lisp_Object display
;
6633 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6634 struct w32_display_info
*tail
;
6637 if (dpyinfo
->reference_count
> 0)
6638 error ("Display still has frames on it");
6641 /* Free the fonts in the font table. */
6642 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6644 if (dpyinfo
->font_table
[i
].name
)
6645 free (dpyinfo
->font_table
[i
].name
);
6646 /* Don't free the full_name string;
6647 it is always shared with something else. */
6648 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
6650 x_destroy_all_bitmaps (dpyinfo
);
6652 x_delete_display (dpyinfo
);
6658 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
6659 "Return the list of display names that Emacs has connections to.")
6662 Lisp_Object tail
, result
;
6665 for (tail
= w32_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
6666 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
6671 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
6672 "If ON is non-nil, report errors as soon as the erring request is made.\n\
6673 If ON is nil, allow buffering of requests.\n\
6674 This is a noop on W32 systems.\n\
6675 The optional second argument DISPLAY specifies which display to act on.\n\
6676 DISPLAY should be either a frame or a display name (a string).\n\
6677 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
6679 Lisp_Object display
, on
;
6681 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
6687 /* These are the w32 specialized functions */
6689 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 1, 0,
6690 "This will display the W32 font dialog and return an X font string corresponding to the selection.")
6694 FRAME_PTR f
= check_x_frame (frame
);
6699 bzero (&cf
, sizeof (cf
));
6701 cf
.lStructSize
= sizeof (cf
);
6702 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
6703 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
| CF_SCREENFONTS
;
6706 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100))
6709 return build_string (buf
);
6712 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
, Sw32_send_sys_command
, 1, 2, 0,
6713 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\
6714 Some useful values for command are 0xf030 to maximise frame (0xf020\n\
6715 to minimize), 0xf120 to restore frame to original size, and 0xf100\n\
6716 to activate the menubar for keyboard access. 0xf140 activates the\n\
6717 screen saver if defined.\n\
6719 If optional parameter FRAME is not specified, use selected frame.")
6721 Lisp_Object command
, frame
;
6724 FRAME_PTR f
= check_x_frame (frame
);
6726 CHECK_NUMBER (command
, 0);
6728 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
6733 /* Lookup virtual keycode from string representing the name of a
6734 non-ascii keystroke into the corresponding virtual key, using
6735 lispy_function_keys. */
6737 lookup_vk_code (char *key
)
6741 for (i
= 0; i
< 256; i
++)
6742 if (lispy_function_keys
[i
] != 0
6743 && strcmp (lispy_function_keys
[i
], key
) == 0)
6749 /* Convert a one-element vector style key sequence to a hot key
6752 w32_parse_hot_key (key
)
6755 /* Copied from Fdefine_key and store_in_keymap. */
6756 register Lisp_Object c
;
6760 struct gcpro gcpro1
;
6762 CHECK_VECTOR (key
, 0);
6764 if (XFASTINT (Flength (key
)) != 1)
6769 c
= Faref (key
, make_number (0));
6771 if (CONSP (c
) && lucid_event_type_list_p (c
))
6772 c
= Fevent_convert_list (c
);
6776 if (! INTEGERP (c
) && ! SYMBOLP (c
))
6777 error ("Key definition is invalid");
6779 /* Work out the base key and the modifiers. */
6782 c
= parse_modifiers (c
);
6783 lisp_modifiers
= Fcar (Fcdr (c
));
6787 vk_code
= lookup_vk_code (XSYMBOL (c
)->name
->data
);
6789 else if (INTEGERP (c
))
6791 lisp_modifiers
= XINT (c
) & ~CHARACTERBITS
;
6792 /* Many ascii characters are their own virtual key code. */
6793 vk_code
= XINT (c
) & CHARACTERBITS
;
6796 if (vk_code
< 0 || vk_code
> 255)
6799 if ((lisp_modifiers
& meta_modifier
) != 0
6800 && !NILP (Vw32_alt_is_meta
))
6801 lisp_modifiers
|= alt_modifier
;
6803 /* Convert lisp modifiers to Windows hot-key form. */
6804 w32_modifiers
= (lisp_modifiers
& hyper_modifier
) ? MOD_WIN
: 0;
6805 w32_modifiers
|= (lisp_modifiers
& alt_modifier
) ? MOD_ALT
: 0;
6806 w32_modifiers
|= (lisp_modifiers
& ctrl_modifier
) ? MOD_CONTROL
: 0;
6807 w32_modifiers
|= (lisp_modifiers
& shift_modifier
) ? MOD_SHIFT
: 0;
6809 return HOTKEY (vk_code
, w32_modifiers
);
6812 DEFUN ("w32-register-hot-key", Fw32_register_hot_key
, Sw32_register_hot_key
, 1, 1, 0,
6813 "Register KEY as a hot-key combination.\n\
6814 Certain key combinations like Alt-Tab are reserved for system use on\n\
6815 Windows, and therefore are normally intercepted by the system. However,\n\
6816 most of these key combinations can be received by registering them as\n\
6817 hot-keys, overriding their special meaning.\n\
6819 KEY must be a one element key definition in vector form that would be\n\
6820 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta\n\
6821 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper\n\
6822 is always interpreted as the Windows modifier keys.\n\
6824 The return value is the hotkey-id if registered, otherwise nil.")
6828 key
= w32_parse_hot_key (key
);
6830 if (NILP (Fmemq (key
, w32_grabbed_keys
)))
6832 /* Reuse an empty slot if possible. */
6833 Lisp_Object item
= Fmemq (Qnil
, w32_grabbed_keys
);
6835 /* Safe to add new key to list, even if we have focus. */
6837 w32_grabbed_keys
= Fcons (key
, w32_grabbed_keys
);
6841 /* Notify input thread about new hot-key definition, so that it
6842 takes effect without needing to switch focus. */
6843 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_REGISTER_HOT_KEY
,
6850 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key
, Sw32_unregister_hot_key
, 1, 1, 0,
6851 "Unregister HOTKEY as a hot-key combination.")
6857 if (!INTEGERP (key
))
6858 key
= w32_parse_hot_key (key
);
6860 item
= Fmemq (key
, w32_grabbed_keys
);
6864 /* Notify input thread about hot-key definition being removed, so
6865 that it takes effect without needing focus switch. */
6866 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_UNREGISTER_HOT_KEY
,
6867 (WPARAM
) XINT (XCAR (item
)), (LPARAM
) item
))
6870 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6877 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys
, Sw32_registered_hot_keys
, 0, 0, 0,
6878 "Return list of registered hot-key IDs.")
6881 return Fcopy_sequence (w32_grabbed_keys
);
6884 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key
, Sw32_reconstruct_hot_key
, 1, 1, 0,
6885 "Convert hot-key ID to a lisp key combination.")
6887 Lisp_Object hotkeyid
;
6889 int vk_code
, w32_modifiers
;
6892 CHECK_NUMBER (hotkeyid
, 0);
6894 vk_code
= HOTKEY_VK_CODE (hotkeyid
);
6895 w32_modifiers
= HOTKEY_MODIFIERS (hotkeyid
);
6897 if (lispy_function_keys
[vk_code
])
6898 key
= intern (lispy_function_keys
[vk_code
]);
6900 key
= make_number (vk_code
);
6902 key
= Fcons (key
, Qnil
);
6903 if (w32_modifiers
& MOD_SHIFT
)
6904 key
= Fcons (Qshift
, key
);
6905 if (w32_modifiers
& MOD_CONTROL
)
6906 key
= Fcons (Qctrl
, key
);
6907 if (w32_modifiers
& MOD_ALT
)
6908 key
= Fcons (NILP (Vw32_alt_is_meta
) ? Qalt
: Qmeta
, key
);
6909 if (w32_modifiers
& MOD_WIN
)
6910 key
= Fcons (Qhyper
, key
);
6915 DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key
, Sw32_toggle_lock_key
, 1, 2, 0,
6916 "Toggle the state of the lock key KEY.\n\
6917 KEY can be `capslock', `kp-numlock', or `scroll'.\n\
6918 If the optional parameter NEW-STATE is a number, then the state of KEY\n\
6919 is set to off if the low bit of NEW-STATE is zero, otherwise on.")
6921 Lisp_Object key
, new_state
;
6926 if (EQ (key
, intern ("capslock")))
6927 vk_code
= VK_CAPITAL
;
6928 else if (EQ (key
, intern ("kp-numlock")))
6929 vk_code
= VK_NUMLOCK
;
6930 else if (EQ (key
, intern ("scroll")))
6931 vk_code
= VK_SCROLL
;
6935 if (!dwWindowsThreadId
)
6936 return make_number (w32_console_toggle_lock_key (vk_code
, new_state
));
6938 if (PostThreadMessage (dwWindowsThreadId
, WM_EMACS_TOGGLE_LOCK_KEY
,
6939 (WPARAM
) vk_code
, (LPARAM
) new_state
))
6942 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6943 return make_number (msg
.wParam
);
6950 /* This is zero if not using MS-Windows. */
6953 /* The section below is built by the lisp expression at the top of the file,
6954 just above where these variables are declared. */
6955 /*&&& init symbols here &&&*/
6956 Qauto_raise
= intern ("auto-raise");
6957 staticpro (&Qauto_raise
);
6958 Qauto_lower
= intern ("auto-lower");
6959 staticpro (&Qauto_lower
);
6960 Qbackground_color
= intern ("background-color");
6961 staticpro (&Qbackground_color
);
6962 Qbar
= intern ("bar");
6964 Qborder_color
= intern ("border-color");
6965 staticpro (&Qborder_color
);
6966 Qborder_width
= intern ("border-width");
6967 staticpro (&Qborder_width
);
6968 Qbox
= intern ("box");
6970 Qcursor_color
= intern ("cursor-color");
6971 staticpro (&Qcursor_color
);
6972 Qcursor_type
= intern ("cursor-type");
6973 staticpro (&Qcursor_type
);
6974 Qforeground_color
= intern ("foreground-color");
6975 staticpro (&Qforeground_color
);
6976 Qgeometry
= intern ("geometry");
6977 staticpro (&Qgeometry
);
6978 Qicon_left
= intern ("icon-left");
6979 staticpro (&Qicon_left
);
6980 Qicon_top
= intern ("icon-top");
6981 staticpro (&Qicon_top
);
6982 Qicon_type
= intern ("icon-type");
6983 staticpro (&Qicon_type
);
6984 Qicon_name
= intern ("icon-name");
6985 staticpro (&Qicon_name
);
6986 Qinternal_border_width
= intern ("internal-border-width");
6987 staticpro (&Qinternal_border_width
);
6988 Qleft
= intern ("left");
6990 Qright
= intern ("right");
6991 staticpro (&Qright
);
6992 Qmouse_color
= intern ("mouse-color");
6993 staticpro (&Qmouse_color
);
6994 Qnone
= intern ("none");
6996 Qparent_id
= intern ("parent-id");
6997 staticpro (&Qparent_id
);
6998 Qscroll_bar_width
= intern ("scroll-bar-width");
6999 staticpro (&Qscroll_bar_width
);
7000 Qsuppress_icon
= intern ("suppress-icon");
7001 staticpro (&Qsuppress_icon
);
7002 Qtop
= intern ("top");
7004 Qundefined_color
= intern ("undefined-color");
7005 staticpro (&Qundefined_color
);
7006 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
7007 staticpro (&Qvertical_scroll_bars
);
7008 Qvisibility
= intern ("visibility");
7009 staticpro (&Qvisibility
);
7010 Qwindow_id
= intern ("window-id");
7011 staticpro (&Qwindow_id
);
7012 Qx_frame_parameter
= intern ("x-frame-parameter");
7013 staticpro (&Qx_frame_parameter
);
7014 Qx_resource_name
= intern ("x-resource-name");
7015 staticpro (&Qx_resource_name
);
7016 Quser_position
= intern ("user-position");
7017 staticpro (&Quser_position
);
7018 Quser_size
= intern ("user-size");
7019 staticpro (&Quser_size
);
7020 Qdisplay
= intern ("display");
7021 staticpro (&Qdisplay
);
7022 /* This is the end of symbol initialization. */
7024 Qhyper
= intern ("hyper");
7025 staticpro (&Qhyper
);
7026 Qsuper
= intern ("super");
7027 staticpro (&Qsuper
);
7028 Qmeta
= intern ("meta");
7030 Qalt
= intern ("alt");
7032 Qctrl
= intern ("ctrl");
7034 Qcontrol
= intern ("control");
7035 staticpro (&Qcontrol
);
7036 Qshift
= intern ("shift");
7037 staticpro (&Qshift
);
7039 Qface_set_after_frame_default
= intern ("face-set-after-frame-default");
7040 staticpro (&Qface_set_after_frame_default
);
7042 Fput (Qundefined_color
, Qerror_conditions
,
7043 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
7044 Fput (Qundefined_color
, Qerror_message
,
7045 build_string ("Undefined color"));
7047 staticpro (&w32_grabbed_keys
);
7048 w32_grabbed_keys
= Qnil
;
7050 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
7051 "An array of color name mappings for windows.");
7052 Vw32_color_map
= Qnil
;
7054 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
7055 "Non-nil if alt key presses are passed on to Windows.\n\
7056 When non-nil, for example, alt pressed and released and then space will\n\
7057 open the System menu. When nil, Emacs silently swallows alt key events.");
7058 Vw32_pass_alt_to_system
= Qnil
;
7060 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
7061 "Non-nil if the alt key is to be considered the same as the meta key.\n\
7062 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
7063 Vw32_alt_is_meta
= Qt
;
7065 DEFVAR_LISP ("w32-pass-lwindow-to-system",
7066 &Vw32_pass_lwindow_to_system
,
7067 "Non-nil if the left \"Windows\" key is passed on to Windows.\n\
7068 When non-nil, the Start menu is opened by tapping the key.");
7069 Vw32_pass_lwindow_to_system
= Qt
;
7071 DEFVAR_LISP ("w32-pass-rwindow-to-system",
7072 &Vw32_pass_rwindow_to_system
,
7073 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\
7074 When non-nil, the Start menu is opened by tapping the key.");
7075 Vw32_pass_rwindow_to_system
= Qt
;
7077 DEFVAR_INT ("w32-phantom-key-code",
7078 &Vw32_phantom_key_code
,
7079 "Virtual key code used to generate \"phantom\" key presses.\n\
7080 Value is a number between 0 and 255.\n\
7082 Phantom key presses are generated in order to stop the system from\n\
7083 acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or\n\
7084 `w32-pass-rwindow-to-system' is nil.");
7085 Vw32_phantom_key_code
= VK_SPACE
;
7087 DEFVAR_LISP ("w32-enable-num-lock",
7088 &Vw32_enable_num_lock
,
7089 "Non-nil if Num Lock should act normally.\n\
7090 Set to nil to see Num Lock as the key `kp-numlock'.");
7091 Vw32_enable_num_lock
= Qt
;
7093 DEFVAR_LISP ("w32-enable-caps-lock",
7094 &Vw32_enable_caps_lock
,
7095 "Non-nil if Caps Lock should act normally.\n\
7096 Set to nil to see Caps Lock as the key `capslock'.");
7097 Vw32_enable_caps_lock
= Qt
;
7099 DEFVAR_LISP ("w32-scroll-lock-modifier",
7100 &Vw32_scroll_lock_modifier
,
7101 "Modifier to use for the Scroll Lock on state.\n\
7102 The value can be hyper, super, meta, alt, control or shift for the\n\
7103 respective modifier, or nil to see Scroll Lock as the key `scroll'.\n\
7104 Any other value will cause the key to be ignored.");
7105 Vw32_scroll_lock_modifier
= Qt
;
7107 DEFVAR_LISP ("w32-lwindow-modifier",
7108 &Vw32_lwindow_modifier
,
7109 "Modifier to use for the left \"Windows\" key.\n\
7110 The value can be hyper, super, meta, alt, control or shift for the\n\
7111 respective modifier, or nil to appear as the key `lwindow'.\n\
7112 Any other value will cause the key to be ignored.");
7113 Vw32_lwindow_modifier
= Qnil
;
7115 DEFVAR_LISP ("w32-rwindow-modifier",
7116 &Vw32_rwindow_modifier
,
7117 "Modifier to use for the right \"Windows\" key.\n\
7118 The value can be hyper, super, meta, alt, control or shift for the\n\
7119 respective modifier, or nil to appear as the key `rwindow'.\n\
7120 Any other value will cause the key to be ignored.");
7121 Vw32_rwindow_modifier
= Qnil
;
7123 DEFVAR_LISP ("w32-apps-modifier",
7124 &Vw32_apps_modifier
,
7125 "Modifier to use for the \"Apps\" key.\n\
7126 The value can be hyper, super, meta, alt, control or shift for the\n\
7127 respective modifier, or nil to appear as the key `apps'.\n\
7128 Any other value will cause the key to be ignored.");
7129 Vw32_apps_modifier
= Qnil
;
7131 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics
,
7132 "Non-nil enables selection of artificially italicized fonts.");
7133 Vw32_enable_italics
= Qnil
;
7135 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
7136 "Non-nil enables Windows palette management to map colors exactly.");
7137 Vw32_enable_palette
= Qt
;
7139 DEFVAR_INT ("w32-mouse-button-tolerance",
7140 &Vw32_mouse_button_tolerance
,
7141 "Analogue of double click interval for faking middle mouse events.\n\
7142 The value is the minimum time in milliseconds that must elapse between\n\
7143 left/right button down events before they are considered distinct events.\n\
7144 If both mouse buttons are depressed within this interval, a middle mouse\n\
7145 button down event is generated instead.");
7146 XSETINT (Vw32_mouse_button_tolerance
, GetDoubleClickTime () / 2);
7148 DEFVAR_INT ("w32-mouse-move-interval",
7149 &Vw32_mouse_move_interval
,
7150 "Minimum interval between mouse move events.\n\
7151 The value is the minimum time in milliseconds that must elapse between\n\
7152 successive mouse move (or scroll bar drag) events before they are\n\
7153 reported as lisp events.");
7154 XSETINT (Vw32_mouse_move_interval
, 50);
7156 init_x_parm_symbols ();
7158 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7159 "List of directories to search for bitmap files for w32.");
7160 Vx_bitmap_file_path
= decode_env_path ((char *) 0, "PATH");
7162 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
7163 "The shape of the pointer when over text.\n\
7164 Changing the value does not affect existing frames\n\
7165 unless you set the mouse color.");
7166 Vx_pointer_shape
= Qnil
;
7168 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
7169 "The name Emacs uses to look up resources; for internal use only.\n\
7170 `x-get-resource' uses this as the first component of the instance name\n\
7171 when requesting resource values.\n\
7172 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
7173 was invoked, or to the value specified with the `-name' or `-rn'\n\
7174 switches, if present.");
7175 Vx_resource_name
= Qnil
;
7177 Vx_nontext_pointer_shape
= Qnil
;
7179 Vx_mode_pointer_shape
= Qnil
;
7181 DEFVAR_INT ("x-sensitive-text-pointer-shape",
7182 &Vx_sensitive_text_pointer_shape
,
7183 "The shape of the pointer when over mouse-sensitive text.\n\
7184 This variable takes effect when you create a new frame\n\
7185 or when you set the mouse color.");
7186 Vx_sensitive_text_pointer_shape
= Qnil
;
7188 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
7189 "A string indicating the foreground color of the cursor box.");
7190 Vx_cursor_fore_pixel
= Qnil
;
7192 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
7193 "Non-nil if no window manager is in use.\n\
7194 Emacs doesn't try to figure this out; this is always nil\n\
7195 unless you set it to something else.");
7196 /* We don't have any way to find this out, so set it to nil
7197 and maybe the user would like to set it to t. */
7198 Vx_no_window_manager
= Qnil
;
7200 DEFVAR_LISP ("x-pixel-size-width-font-regexp",
7201 &Vx_pixel_size_width_font_regexp
,
7202 "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
7204 Since Emacs gets width of a font matching with this regexp from\n\
7205 PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
7206 such a font. This is especially effective for such large fonts as\n\
7207 Chinese, Japanese, and Korean.");
7208 Vx_pixel_size_width_font_regexp
= Qnil
;
7210 DEFVAR_BOOL ("unibyte-display-via-language-environment",
7211 &unibyte_display_via_language_environment
,
7212 "*Non-nil means display unibyte text according to language environment.\n\
7213 Specifically this means that unibyte non-ASCII characters\n\
7214 are displayed by converting them to the equivalent multibyte characters\n\
7215 according to the current language environment. As a result, they are\n\
7216 displayed according to the current fontset.");
7217 unibyte_display_via_language_environment
= 0;
7219 DEFVAR_LISP ("w32-bdf-filename-alist",
7220 &Vw32_bdf_filename_alist
,
7221 "List of bdf fonts and their corresponding filenames.");
7222 Vw32_bdf_filename_alist
= Qnil
;
7224 defsubr (&Sx_get_resource
);
7225 defsubr (&Sx_list_fonts
);
7226 defsubr (&Sx_display_color_p
);
7227 defsubr (&Sx_display_grayscale_p
);
7228 defsubr (&Sx_color_defined_p
);
7229 defsubr (&Sx_color_values
);
7230 defsubr (&Sx_server_max_request_size
);
7231 defsubr (&Sx_server_vendor
);
7232 defsubr (&Sx_server_version
);
7233 defsubr (&Sx_display_pixel_width
);
7234 defsubr (&Sx_display_pixel_height
);
7235 defsubr (&Sx_display_mm_width
);
7236 defsubr (&Sx_display_mm_height
);
7237 defsubr (&Sx_display_screens
);
7238 defsubr (&Sx_display_planes
);
7239 defsubr (&Sx_display_color_cells
);
7240 defsubr (&Sx_display_visual_class
);
7241 defsubr (&Sx_display_backing_store
);
7242 defsubr (&Sx_display_save_under
);
7243 defsubr (&Sx_parse_geometry
);
7244 defsubr (&Sx_create_frame
);
7245 defsubr (&Sx_open_connection
);
7246 defsubr (&Sx_close_connection
);
7247 defsubr (&Sx_display_list
);
7248 defsubr (&Sx_synchronize
);
7250 /* W32 specific functions */
7252 defsubr (&Sw32_focus_frame
);
7253 defsubr (&Sw32_select_font
);
7254 defsubr (&Sw32_define_rgb_color
);
7255 defsubr (&Sw32_default_color_map
);
7256 defsubr (&Sw32_load_color_file
);
7257 defsubr (&Sw32_send_sys_command
);
7258 defsubr (&Sw32_register_hot_key
);
7259 defsubr (&Sw32_unregister_hot_key
);
7260 defsubr (&Sw32_registered_hot_keys
);
7261 defsubr (&Sw32_reconstruct_hot_key
);
7262 defsubr (&Sw32_toggle_lock_key
);
7263 defsubr (&Sw32_find_bdf_fonts
);
7265 /* Setting callback functions for fontset handler. */
7266 get_font_info_func
= w32_get_font_info
;
7267 list_fonts_func
= w32_list_fonts
;
7268 load_font_func
= w32_load_font
;
7269 find_ccl_program_func
= w32_find_ccl_program
;
7270 query_font_func
= w32_query_font
;
7271 set_frame_fontset_func
= x_set_font
;
7272 check_window_system_func
= check_w32
;
7281 button
= MessageBox (NULL
,
7282 "A fatal error has occurred!\n\n"
7283 "Select Abort to exit, Retry to debug, Ignore to continue",
7284 "Emacs Abort Dialog",
7285 MB_ICONEXCLAMATION
| MB_TASKMODAL
7286 | MB_SETFOREGROUND
| MB_ABORTRETRYIGNORE
);
7301 /* For convenience when debugging. */
7305 return GetLastError ();