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 */
35 #include "dispextern.h"
37 #include "blockinput.h"
40 #include "termhooks.h"
45 extern void free_frame_menubar ();
46 extern struct scroll_bar
*x_window_to_scroll_bar ();
49 /* The colormap for converting color names to RGB values */
50 Lisp_Object Vw32_color_map
;
52 /* Non nil if alt key presses are passed on to Windows. */
53 Lisp_Object Vw32_pass_alt_to_system
;
55 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
57 Lisp_Object Vw32_alt_is_meta
;
59 /* Non nil if left window, right window, and application key events
60 are passed on to Windows. */
61 Lisp_Object Vw32_pass_optional_keys_to_system
;
63 /* Switch to control whether we inhibit requests for italicised fonts (which
64 are synthesized, look ugly, and are trashed by cursor movement under NT). */
65 Lisp_Object Vw32_enable_italics
;
67 /* Enable palette management. */
68 Lisp_Object Vw32_enable_palette
;
70 /* Control how close left/right button down events must be to
71 be converted to a middle button down event. */
72 Lisp_Object Vw32_mouse_button_tolerance
;
74 /* Minimum interval between mouse movement (and scroll bar drag)
75 events that are passed on to the event loop. */
76 Lisp_Object Vw32_mouse_move_interval
;
78 /* The name we're using in resource queries. */
79 Lisp_Object Vx_resource_name
;
81 /* Non nil if no window manager is in use. */
82 Lisp_Object Vx_no_window_manager
;
84 /* The background and shape of the mouse pointer, and shape when not
85 over text or in the modeline. */
86 Lisp_Object Vx_pointer_shape
, Vx_nontext_pointer_shape
, Vx_mode_pointer_shape
;
87 /* The shape when over mouse-sensitive text. */
88 Lisp_Object Vx_sensitive_text_pointer_shape
;
90 /* Color of chars displayed in cursor box. */
91 Lisp_Object Vx_cursor_fore_pixel
;
93 /* Nonzero if using Windows. */
94 static int w32_in_use
;
96 /* Search path for bitmap files. */
97 Lisp_Object Vx_bitmap_file_path
;
99 /* Evaluate this expression to rebuild the section of syms_of_w32fns
100 that initializes and staticpros the symbols declared below. Note
101 that Emacs 18 has a bug that keeps C-x C-e from being able to
102 evaluate this expression.
105 ;; Accumulate a list of the symbols we want to initialize from the
106 ;; declarations at the top of the file.
107 (goto-char (point-min))
108 (search-forward "/\*&&& symbols declared here &&&*\/\n")
110 (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
112 (cons (buffer-substring (match-beginning 1) (match-end 1))
115 (setq symbol-list (nreverse symbol-list))
116 ;; Delete the section of syms_of_... where we initialize the symbols.
117 (search-forward "\n /\*&&& init symbols here &&&*\/\n")
118 (let ((start (point)))
119 (while (looking-at "^ Q")
121 (kill-region start (point)))
122 ;; Write a new symbol initialization section.
124 (insert (format " %s = intern (\"" (car symbol-list)))
125 (let ((start (point)))
126 (insert (substring (car symbol-list) 1))
127 (subst-char-in-region start (point) ?_ ?-))
128 (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
129 (setq symbol-list (cdr symbol-list)))))
133 /*&&& symbols declared here &&&*/
134 Lisp_Object Qauto_raise
;
135 Lisp_Object Qauto_lower
;
136 Lisp_Object Qbackground_color
;
138 Lisp_Object Qborder_color
;
139 Lisp_Object Qborder_width
;
141 Lisp_Object Qcursor_color
;
142 Lisp_Object Qcursor_type
;
143 Lisp_Object Qforeground_color
;
144 Lisp_Object Qgeometry
;
145 Lisp_Object Qicon_left
;
146 Lisp_Object Qicon_top
;
147 Lisp_Object Qicon_type
;
148 Lisp_Object Qicon_name
;
149 Lisp_Object Qinternal_border_width
;
152 Lisp_Object Qmouse_color
;
154 Lisp_Object Qparent_id
;
155 Lisp_Object Qscroll_bar_width
;
156 Lisp_Object Qsuppress_icon
;
158 Lisp_Object Qundefined_color
;
159 Lisp_Object Qvertical_scroll_bars
;
160 Lisp_Object Qvisibility
;
161 Lisp_Object Qwindow_id
;
162 Lisp_Object Qx_frame_parameter
;
163 Lisp_Object Qx_resource_name
;
164 Lisp_Object Quser_position
;
165 Lisp_Object Quser_size
;
166 Lisp_Object Qdisplay
;
168 /* State variables for emulating a three button mouse. */
173 static int button_state
= 0;
174 static W32Msg saved_mouse_button_msg
;
175 static unsigned mouse_button_timer
; /* non-zero when timer is active */
176 static W32Msg saved_mouse_move_msg
;
177 static unsigned mouse_move_timer
;
179 /* W95 mousewheel handler */
180 unsigned int msh_mousewheel
= 0;
182 #define MOUSE_BUTTON_ID 1
183 #define MOUSE_MOVE_ID 2
185 /* The below are defined in frame.c. */
186 extern Lisp_Object Qheight
, Qminibuffer
, Qname
, Qonly
, Qwidth
;
187 extern Lisp_Object Qunsplittable
, Qmenu_bar_lines
, Qbuffer_predicate
, Qtitle
;
189 extern Lisp_Object Vwindow_system_version
;
191 extern Lisp_Object last_mouse_scroll_bar
;
192 extern int last_mouse_scroll_bar_pos
;
194 /* From w32term.c. */
195 extern Lisp_Object Vw32_num_mouse_buttons
;
198 /* Error if we are not connected to MS-Windows. */
203 error ("MS-Windows not in use or not initialized");
206 /* Nonzero if we can use mouse menus.
207 You should not call this unless HAVE_MENUS is defined. */
215 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
216 and checking validity for W32. */
219 check_x_frame (frame
)
228 CHECK_LIVE_FRAME (frame
, 0);
231 if (! FRAME_W32_P (f
))
232 error ("non-w32 frame used");
236 /* Let the user specify an display with a frame.
237 nil stands for the selected frame--or, if that is not a w32 frame,
238 the first display on the list. */
240 static struct w32_display_info
*
241 check_x_display_info (frame
)
246 if (FRAME_W32_P (selected_frame
))
247 return FRAME_W32_DISPLAY_INFO (selected_frame
);
249 return &one_w32_display_info
;
251 else if (STRINGP (frame
))
252 return x_display_info_for_name (frame
);
257 CHECK_LIVE_FRAME (frame
, 0);
259 if (! FRAME_W32_P (f
))
260 error ("non-w32 frame used");
261 return FRAME_W32_DISPLAY_INFO (f
);
265 /* Return the Emacs frame-object corresponding to an w32 window.
266 It could be the frame's main window or an icon window. */
268 /* This function can be called during GC, so use GC_xxx type test macros. */
271 x_window_to_frame (dpyinfo
, wdesc
)
272 struct w32_display_info
*dpyinfo
;
275 Lisp_Object tail
, frame
;
278 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCONS (tail
)->cdr
)
280 frame
= XCONS (tail
)->car
;
281 if (!GC_FRAMEP (frame
))
284 if (f
->output_data
.nothing
== 1
285 || FRAME_W32_DISPLAY_INFO (f
) != dpyinfo
)
287 if (FRAME_W32_WINDOW (f
) == wdesc
)
295 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
296 id, which is just an int that this section returns. Bitmaps are
297 reference counted so they can be shared among frames.
299 Bitmap indices are guaranteed to be > 0, so a negative number can
300 be used to indicate no bitmap.
302 If you use x_create_bitmap_from_data, then you must keep track of
303 the bitmaps yourself. That is, creating a bitmap from the same
304 data more than once will not be caught. */
307 /* Functions to access the contents of a bitmap, given an id. */
310 x_bitmap_height (f
, id
)
314 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
318 x_bitmap_width (f
, id
)
322 return FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
326 x_bitmap_pixmap (f
, id
)
330 return (int) FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
334 /* Allocate a new bitmap record. Returns index of new record. */
337 x_allocate_bitmap_record (f
)
340 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
343 if (dpyinfo
->bitmaps
== NULL
)
345 dpyinfo
->bitmaps_size
= 10;
347 = (struct w32_bitmap_record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
348 dpyinfo
->bitmaps_last
= 1;
352 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
353 return ++dpyinfo
->bitmaps_last
;
355 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
356 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
359 dpyinfo
->bitmaps_size
*= 2;
361 = (struct w32_bitmap_record
*) xrealloc (dpyinfo
->bitmaps
,
362 dpyinfo
->bitmaps_size
* sizeof (struct w32_bitmap_record
));
363 return ++dpyinfo
->bitmaps_last
;
366 /* Add one reference to the reference count of the bitmap with id ID. */
369 x_reference_bitmap (f
, id
)
373 ++FRAME_W32_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
376 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
379 x_create_bitmap_from_data (f
, bits
, width
, height
)
382 unsigned int width
, height
;
384 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
388 bitmap
= CreateBitmap (width
, height
,
389 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
390 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
396 id
= x_allocate_bitmap_record (f
);
397 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
398 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
399 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
400 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
401 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
402 dpyinfo
->bitmaps
[id
- 1].height
= height
;
403 dpyinfo
->bitmaps
[id
- 1].width
= width
;
408 /* Create bitmap from file FILE for frame F. */
411 x_create_bitmap_from_file (f
, file
)
417 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
418 unsigned int width
, height
;
420 int xhot
, yhot
, result
, id
;
426 /* Look for an existing bitmap with the same name. */
427 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
429 if (dpyinfo
->bitmaps
[id
].refcount
430 && dpyinfo
->bitmaps
[id
].file
431 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) XSTRING (file
)->data
))
433 ++dpyinfo
->bitmaps
[id
].refcount
;
438 /* Search bitmap-file-path for the file, if appropriate. */
439 fd
= openp (Vx_bitmap_file_path
, file
, "", &found
, 0);
444 filename
= (char *) XSTRING (found
)->data
;
446 hinst
= LoadLibraryEx (filename
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
452 result
= XReadBitmapFile (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
),
453 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
454 if (result
!= BitmapSuccess
)
457 id
= x_allocate_bitmap_record (f
);
458 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
459 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
460 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (XSTRING (file
)->size
+ 1);
461 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
462 dpyinfo
->bitmaps
[id
- 1].height
= height
;
463 dpyinfo
->bitmaps
[id
- 1].width
= width
;
464 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, XSTRING (file
)->data
);
470 /* Remove reference to bitmap with id number ID. */
473 x_destroy_bitmap (f
, id
)
477 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
481 --dpyinfo
->bitmaps
[id
- 1].refcount
;
482 if (dpyinfo
->bitmaps
[id
- 1].refcount
== 0)
485 DeleteObject (dpyinfo
->bitmaps
[id
- 1].pixmap
);
486 if (dpyinfo
->bitmaps
[id
- 1].file
)
488 free (dpyinfo
->bitmaps
[id
- 1].file
);
489 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
496 /* Free all the bitmaps for the display specified by DPYINFO. */
499 x_destroy_all_bitmaps (dpyinfo
)
500 struct w32_display_info
*dpyinfo
;
503 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++)
504 if (dpyinfo
->bitmaps
[i
].refcount
> 0)
506 DeleteObject (dpyinfo
->bitmaps
[i
].pixmap
);
507 if (dpyinfo
->bitmaps
[i
].file
)
508 free (dpyinfo
->bitmaps
[i
].file
);
510 dpyinfo
->bitmaps_last
= 0;
513 /* Connect the frame-parameter names for W32 frames
514 to the ways of passing the parameter values to the window system.
516 The name of a parameter, as a Lisp symbol,
517 has an `x-frame-parameter' property which is an integer in Lisp
518 but can be interpreted as an `enum x_frame_parm' in C. */
522 X_PARM_FOREGROUND_COLOR
,
523 X_PARM_BACKGROUND_COLOR
,
530 X_PARM_INTERNAL_BORDER_WIDTH
,
534 X_PARM_VERT_SCROLL_BAR
,
536 X_PARM_MENU_BAR_LINES
540 struct x_frame_parm_table
543 void (*setter
)( /* struct frame *frame, Lisp_Object val, oldval */ );
546 void x_set_foreground_color ();
547 void x_set_background_color ();
548 void x_set_mouse_color ();
549 void x_set_cursor_color ();
550 void x_set_border_color ();
551 void x_set_cursor_type ();
552 void x_set_icon_type ();
553 void x_set_icon_name ();
555 void x_set_border_width ();
556 void x_set_internal_border_width ();
557 void x_explicitly_set_name ();
558 void x_set_autoraise ();
559 void x_set_autolower ();
560 void x_set_vertical_scroll_bars ();
561 void x_set_visibility ();
562 void x_set_menu_bar_lines ();
563 void x_set_scroll_bar_width ();
565 void x_set_unsplittable ();
567 static struct x_frame_parm_table x_frame_parms
[] =
569 "auto-raise", x_set_autoraise
,
570 "auto-lower", x_set_autolower
,
571 "background-color", x_set_background_color
,
572 "border-color", x_set_border_color
,
573 "border-width", x_set_border_width
,
574 "cursor-color", x_set_cursor_color
,
575 "cursor-type", x_set_cursor_type
,
577 "foreground-color", x_set_foreground_color
,
578 "icon-name", x_set_icon_name
,
579 "icon-type", x_set_icon_type
,
580 "internal-border-width", x_set_internal_border_width
,
581 "menu-bar-lines", x_set_menu_bar_lines
,
582 "mouse-color", x_set_mouse_color
,
583 "name", x_explicitly_set_name
,
584 "scroll-bar-width", x_set_scroll_bar_width
,
585 "title", x_set_title
,
586 "unsplittable", x_set_unsplittable
,
587 "vertical-scroll-bars", x_set_vertical_scroll_bars
,
588 "visibility", x_set_visibility
,
591 /* Attach the `x-frame-parameter' properties to
592 the Lisp symbol names of parameters relevant to W32. */
594 init_x_parm_symbols ()
598 for (i
= 0; i
< sizeof (x_frame_parms
) / sizeof (x_frame_parms
[0]); i
++)
599 Fput (intern (x_frame_parms
[i
].name
), Qx_frame_parameter
,
603 /* Change the parameters of FRAME as specified by ALIST.
604 If a parameter is not specially recognized, do nothing;
605 otherwise call the `x_set_...' function for that parameter. */
608 x_set_frame_parameters (f
, alist
)
614 /* If both of these parameters are present, it's more efficient to
615 set them both at once. So we wait until we've looked at the
616 entire list before we set them. */
620 Lisp_Object left
, top
;
622 /* Same with these. */
623 Lisp_Object icon_left
, icon_top
;
625 /* Record in these vectors all the parms specified. */
629 int left_no_change
= 0, top_no_change
= 0;
630 int icon_left_no_change
= 0, icon_top_no_change
= 0;
633 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
636 parms
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
637 values
= (Lisp_Object
*) alloca (i
* sizeof (Lisp_Object
));
639 /* Extract parm names and values into those vectors. */
642 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
644 Lisp_Object elt
, prop
, val
;
647 parms
[i
] = Fcar (elt
);
648 values
[i
] = Fcdr (elt
);
652 top
= left
= Qunbound
;
653 icon_left
= icon_top
= Qunbound
;
655 /* Provide default values for HEIGHT and WIDTH. */
656 width
= FRAME_WIDTH (f
);
657 height
= FRAME_HEIGHT (f
);
659 /* Now process them in reverse of specified order. */
660 for (i
--; i
>= 0; i
--)
662 Lisp_Object prop
, val
;
667 if (EQ (prop
, Qwidth
) && NUMBERP (val
))
668 width
= XFASTINT (val
);
669 else if (EQ (prop
, Qheight
) && NUMBERP (val
))
670 height
= XFASTINT (val
);
671 else if (EQ (prop
, Qtop
))
673 else if (EQ (prop
, Qleft
))
675 else if (EQ (prop
, Qicon_top
))
677 else if (EQ (prop
, Qicon_left
))
681 register Lisp_Object param_index
, old_value
;
683 param_index
= Fget (prop
, Qx_frame_parameter
);
684 old_value
= get_frame_param (f
, prop
);
685 store_frame_param (f
, prop
, val
);
686 if (NATNUMP (param_index
)
687 && (XFASTINT (param_index
)
688 < sizeof (x_frame_parms
)/sizeof (x_frame_parms
[0])))
689 (*x_frame_parms
[XINT (param_index
)].setter
)(f
, val
, old_value
);
693 /* Don't die if just one of these was set. */
694 if (EQ (left
, Qunbound
))
697 if (f
->output_data
.w32
->left_pos
< 0)
698 left
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->left_pos
), Qnil
));
700 XSETINT (left
, f
->output_data
.w32
->left_pos
);
702 if (EQ (top
, Qunbound
))
705 if (f
->output_data
.w32
->top_pos
< 0)
706 top
= Fcons (Qplus
, Fcons (make_number (f
->output_data
.w32
->top_pos
), Qnil
));
708 XSETINT (top
, f
->output_data
.w32
->top_pos
);
711 /* If one of the icon positions was not set, preserve or default it. */
712 if (EQ (icon_left
, Qunbound
) || ! INTEGERP (icon_left
))
714 icon_left_no_change
= 1;
715 icon_left
= Fcdr (Fassq (Qicon_left
, f
->param_alist
));
716 if (NILP (icon_left
))
717 XSETINT (icon_left
, 0);
719 if (EQ (icon_top
, Qunbound
) || ! INTEGERP (icon_top
))
721 icon_top_no_change
= 1;
722 icon_top
= Fcdr (Fassq (Qicon_top
, f
->param_alist
));
724 XSETINT (icon_top
, 0);
727 /* Don't set these parameters unless they've been explicitly
728 specified. The window might be mapped or resized while we're in
729 this function, and we don't want to override that unless the lisp
730 code has asked for it.
732 Don't set these parameters unless they actually differ from the
733 window's current parameters; the window may not actually exist
738 check_frame_size (f
, &height
, &width
);
740 XSETFRAME (frame
, f
);
742 if (XINT (width
) != FRAME_WIDTH (f
)
743 || XINT (height
) != FRAME_HEIGHT (f
))
744 Fset_frame_size (frame
, make_number (width
), make_number (height
));
746 if ((!NILP (left
) || !NILP (top
))
747 && ! (left_no_change
&& top_no_change
)
748 && ! (NUMBERP (left
) && XINT (left
) == f
->output_data
.w32
->left_pos
749 && NUMBERP (top
) && XINT (top
) == f
->output_data
.w32
->top_pos
))
754 /* Record the signs. */
755 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
756 if (EQ (left
, Qminus
))
757 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
758 else if (INTEGERP (left
))
760 leftpos
= XINT (left
);
762 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
764 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qminus
)
765 && CONSP (XCONS (left
)->cdr
)
766 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
768 leftpos
= - XINT (XCONS (XCONS (left
)->cdr
)->car
);
769 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
771 else if (CONSP (left
) && EQ (XCONS (left
)->car
, Qplus
)
772 && CONSP (XCONS (left
)->cdr
)
773 && INTEGERP (XCONS (XCONS (left
)->cdr
)->car
))
775 leftpos
= XINT (XCONS (XCONS (left
)->cdr
)->car
);
778 if (EQ (top
, Qminus
))
779 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
780 else if (INTEGERP (top
))
784 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
786 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qminus
)
787 && CONSP (XCONS (top
)->cdr
)
788 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
790 toppos
= - XINT (XCONS (XCONS (top
)->cdr
)->car
);
791 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
793 else if (CONSP (top
) && EQ (XCONS (top
)->car
, Qplus
)
794 && CONSP (XCONS (top
)->cdr
)
795 && INTEGERP (XCONS (XCONS (top
)->cdr
)->car
))
797 toppos
= XINT (XCONS (XCONS (top
)->cdr
)->car
);
801 /* Store the numeric value of the position. */
802 f
->output_data
.w32
->top_pos
= toppos
;
803 f
->output_data
.w32
->left_pos
= leftpos
;
805 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
807 /* Actually set that position, and convert to absolute. */
808 x_set_offset (f
, leftpos
, toppos
, -1);
811 if ((!NILP (icon_left
) || !NILP (icon_top
))
812 && ! (icon_left_no_change
&& icon_top_no_change
))
813 x_wm_set_icon_position (f
, XINT (icon_left
), XINT (icon_top
));
817 /* Store the screen positions of frame F into XPTR and YPTR.
818 These are the positions of the containing window manager window,
819 not Emacs's own window. */
822 x_real_positions (f
, xptr
, yptr
)
831 GetClientRect(FRAME_W32_WINDOW(f
), &rect
);
832 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
, FRAME_EXTERNAL_MENU_BAR(f
));
838 ClientToScreen (FRAME_W32_WINDOW(f
), &pt
);
844 /* Insert a description of internally-recorded parameters of frame X
845 into the parameter alist *ALISTPTR that is to be given to the user.
846 Only parameters that are specific to W32
847 and whose values are not correctly recorded in the frame's
848 param_alist need to be considered here. */
850 x_report_frame_params (f
, alistptr
)
852 Lisp_Object
*alistptr
;
857 /* Represent negative positions (off the top or left screen edge)
858 in a way that Fmodify_frame_parameters will understand correctly. */
859 XSETINT (tem
, f
->output_data
.w32
->left_pos
);
860 if (f
->output_data
.w32
->left_pos
>= 0)
861 store_in_alist (alistptr
, Qleft
, tem
);
863 store_in_alist (alistptr
, Qleft
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
865 XSETINT (tem
, f
->output_data
.w32
->top_pos
);
866 if (f
->output_data
.w32
->top_pos
>= 0)
867 store_in_alist (alistptr
, Qtop
, tem
);
869 store_in_alist (alistptr
, Qtop
, Fcons (Qplus
, Fcons (tem
, Qnil
)));
871 store_in_alist (alistptr
, Qborder_width
,
872 make_number (f
->output_data
.w32
->border_width
));
873 store_in_alist (alistptr
, Qinternal_border_width
,
874 make_number (f
->output_data
.w32
->internal_border_width
));
875 sprintf (buf
, "%ld", (long) FRAME_W32_WINDOW (f
));
876 store_in_alist (alistptr
, Qwindow_id
,
878 store_in_alist (alistptr
, Qicon_name
, f
->icon_name
);
879 FRAME_SAMPLE_VISIBILITY (f
);
880 store_in_alist (alistptr
, Qvisibility
,
881 (FRAME_VISIBLE_P (f
) ? Qt
882 : FRAME_ICONIFIED_P (f
) ? Qicon
: Qnil
));
883 store_in_alist (alistptr
, Qdisplay
,
884 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->car
);
888 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color
, Sw32_define_rgb_color
, 4, 4, 0,
889 "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
890 This adds or updates a named color to w32-color-map, making it available for use.\n\
891 The original entry's RGB ref is returned, or nil if the entry is new.")
892 (red
, green
, blue
, name
)
893 Lisp_Object red
, green
, blue
, name
;
896 Lisp_Object oldrgb
= Qnil
;
899 CHECK_NUMBER (red
, 0);
900 CHECK_NUMBER (green
, 0);
901 CHECK_NUMBER (blue
, 0);
902 CHECK_STRING (name
, 0);
904 XSET (rgb
, Lisp_Int
, RGB(XUINT (red
), XUINT (green
), XUINT (blue
)));
908 /* replace existing entry in w32-color-map or add new entry. */
909 entry
= Fassoc (name
, Vw32_color_map
);
912 entry
= Fcons (name
, rgb
);
913 Vw32_color_map
= Fcons (entry
, Vw32_color_map
);
917 oldrgb
= Fcdr (entry
);
918 Fsetcdr (entry
, rgb
);
926 DEFUN ("w32-load-color-file", Fw32_load_color_file
, Sw32_load_color_file
, 1, 1, 0,
927 "Create an alist of color entries from an external file (ie. rgb.txt).\n\
928 Assign this value to w32-color-map to replace the existing color map.\n\
930 The file should define one named RGB color per line like so:\
932 where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
934 Lisp_Object filename
;
937 Lisp_Object cmap
= Qnil
;
940 CHECK_STRING (filename
, 0);
941 abspath
= Fexpand_file_name (filename
, Qnil
);
943 fp
= fopen (XSTRING (filename
)->data
, "rt");
947 int red
, green
, blue
;
952 while (fgets (buf
, sizeof (buf
), fp
) != NULL
) {
953 if (sscanf (buf
, "%u %u %u %n", &red
, &green
, &blue
, &num
) == 3)
955 char *name
= buf
+ num
;
956 num
= strlen (name
) - 1;
957 if (name
[num
] == '\n')
959 cmap
= Fcons (Fcons (build_string (name
),
960 make_number (RGB (red
, green
, blue
))),
972 /* The default colors for the w32 color map */
973 typedef struct colormap_t
979 colormap_t w32_color_map
[] =
981 {"snow" , PALETTERGB (255,250,250)},
982 {"ghost white" , PALETTERGB (248,248,255)},
983 {"GhostWhite" , PALETTERGB (248,248,255)},
984 {"white smoke" , PALETTERGB (245,245,245)},
985 {"WhiteSmoke" , PALETTERGB (245,245,245)},
986 {"gainsboro" , PALETTERGB (220,220,220)},
987 {"floral white" , PALETTERGB (255,250,240)},
988 {"FloralWhite" , PALETTERGB (255,250,240)},
989 {"old lace" , PALETTERGB (253,245,230)},
990 {"OldLace" , PALETTERGB (253,245,230)},
991 {"linen" , PALETTERGB (250,240,230)},
992 {"antique white" , PALETTERGB (250,235,215)},
993 {"AntiqueWhite" , PALETTERGB (250,235,215)},
994 {"papaya whip" , PALETTERGB (255,239,213)},
995 {"PapayaWhip" , PALETTERGB (255,239,213)},
996 {"blanched almond" , PALETTERGB (255,235,205)},
997 {"BlanchedAlmond" , PALETTERGB (255,235,205)},
998 {"bisque" , PALETTERGB (255,228,196)},
999 {"peach puff" , PALETTERGB (255,218,185)},
1000 {"PeachPuff" , PALETTERGB (255,218,185)},
1001 {"navajo white" , PALETTERGB (255,222,173)},
1002 {"NavajoWhite" , PALETTERGB (255,222,173)},
1003 {"moccasin" , PALETTERGB (255,228,181)},
1004 {"cornsilk" , PALETTERGB (255,248,220)},
1005 {"ivory" , PALETTERGB (255,255,240)},
1006 {"lemon chiffon" , PALETTERGB (255,250,205)},
1007 {"LemonChiffon" , PALETTERGB (255,250,205)},
1008 {"seashell" , PALETTERGB (255,245,238)},
1009 {"honeydew" , PALETTERGB (240,255,240)},
1010 {"mint cream" , PALETTERGB (245,255,250)},
1011 {"MintCream" , PALETTERGB (245,255,250)},
1012 {"azure" , PALETTERGB (240,255,255)},
1013 {"alice blue" , PALETTERGB (240,248,255)},
1014 {"AliceBlue" , PALETTERGB (240,248,255)},
1015 {"lavender" , PALETTERGB (230,230,250)},
1016 {"lavender blush" , PALETTERGB (255,240,245)},
1017 {"LavenderBlush" , PALETTERGB (255,240,245)},
1018 {"misty rose" , PALETTERGB (255,228,225)},
1019 {"MistyRose" , PALETTERGB (255,228,225)},
1020 {"white" , PALETTERGB (255,255,255)},
1021 {"black" , PALETTERGB ( 0, 0, 0)},
1022 {"dark slate gray" , PALETTERGB ( 47, 79, 79)},
1023 {"DarkSlateGray" , PALETTERGB ( 47, 79, 79)},
1024 {"dark slate grey" , PALETTERGB ( 47, 79, 79)},
1025 {"DarkSlateGrey" , PALETTERGB ( 47, 79, 79)},
1026 {"dim gray" , PALETTERGB (105,105,105)},
1027 {"DimGray" , PALETTERGB (105,105,105)},
1028 {"dim grey" , PALETTERGB (105,105,105)},
1029 {"DimGrey" , PALETTERGB (105,105,105)},
1030 {"slate gray" , PALETTERGB (112,128,144)},
1031 {"SlateGray" , PALETTERGB (112,128,144)},
1032 {"slate grey" , PALETTERGB (112,128,144)},
1033 {"SlateGrey" , PALETTERGB (112,128,144)},
1034 {"light slate gray" , PALETTERGB (119,136,153)},
1035 {"LightSlateGray" , PALETTERGB (119,136,153)},
1036 {"light slate grey" , PALETTERGB (119,136,153)},
1037 {"LightSlateGrey" , PALETTERGB (119,136,153)},
1038 {"gray" , PALETTERGB (190,190,190)},
1039 {"grey" , PALETTERGB (190,190,190)},
1040 {"light grey" , PALETTERGB (211,211,211)},
1041 {"LightGrey" , PALETTERGB (211,211,211)},
1042 {"light gray" , PALETTERGB (211,211,211)},
1043 {"LightGray" , PALETTERGB (211,211,211)},
1044 {"midnight blue" , PALETTERGB ( 25, 25,112)},
1045 {"MidnightBlue" , PALETTERGB ( 25, 25,112)},
1046 {"navy" , PALETTERGB ( 0, 0,128)},
1047 {"navy blue" , PALETTERGB ( 0, 0,128)},
1048 {"NavyBlue" , PALETTERGB ( 0, 0,128)},
1049 {"cornflower blue" , PALETTERGB (100,149,237)},
1050 {"CornflowerBlue" , PALETTERGB (100,149,237)},
1051 {"dark slate blue" , PALETTERGB ( 72, 61,139)},
1052 {"DarkSlateBlue" , PALETTERGB ( 72, 61,139)},
1053 {"slate blue" , PALETTERGB (106, 90,205)},
1054 {"SlateBlue" , PALETTERGB (106, 90,205)},
1055 {"medium slate blue" , PALETTERGB (123,104,238)},
1056 {"MediumSlateBlue" , PALETTERGB (123,104,238)},
1057 {"light slate blue" , PALETTERGB (132,112,255)},
1058 {"LightSlateBlue" , PALETTERGB (132,112,255)},
1059 {"medium blue" , PALETTERGB ( 0, 0,205)},
1060 {"MediumBlue" , PALETTERGB ( 0, 0,205)},
1061 {"royal blue" , PALETTERGB ( 65,105,225)},
1062 {"RoyalBlue" , PALETTERGB ( 65,105,225)},
1063 {"blue" , PALETTERGB ( 0, 0,255)},
1064 {"dodger blue" , PALETTERGB ( 30,144,255)},
1065 {"DodgerBlue" , PALETTERGB ( 30,144,255)},
1066 {"deep sky blue" , PALETTERGB ( 0,191,255)},
1067 {"DeepSkyBlue" , PALETTERGB ( 0,191,255)},
1068 {"sky blue" , PALETTERGB (135,206,235)},
1069 {"SkyBlue" , PALETTERGB (135,206,235)},
1070 {"light sky blue" , PALETTERGB (135,206,250)},
1071 {"LightSkyBlue" , PALETTERGB (135,206,250)},
1072 {"steel blue" , PALETTERGB ( 70,130,180)},
1073 {"SteelBlue" , PALETTERGB ( 70,130,180)},
1074 {"light steel blue" , PALETTERGB (176,196,222)},
1075 {"LightSteelBlue" , PALETTERGB (176,196,222)},
1076 {"light blue" , PALETTERGB (173,216,230)},
1077 {"LightBlue" , PALETTERGB (173,216,230)},
1078 {"powder blue" , PALETTERGB (176,224,230)},
1079 {"PowderBlue" , PALETTERGB (176,224,230)},
1080 {"pale turquoise" , PALETTERGB (175,238,238)},
1081 {"PaleTurquoise" , PALETTERGB (175,238,238)},
1082 {"dark turquoise" , PALETTERGB ( 0,206,209)},
1083 {"DarkTurquoise" , PALETTERGB ( 0,206,209)},
1084 {"medium turquoise" , PALETTERGB ( 72,209,204)},
1085 {"MediumTurquoise" , PALETTERGB ( 72,209,204)},
1086 {"turquoise" , PALETTERGB ( 64,224,208)},
1087 {"cyan" , PALETTERGB ( 0,255,255)},
1088 {"light cyan" , PALETTERGB (224,255,255)},
1089 {"LightCyan" , PALETTERGB (224,255,255)},
1090 {"cadet blue" , PALETTERGB ( 95,158,160)},
1091 {"CadetBlue" , PALETTERGB ( 95,158,160)},
1092 {"medium aquamarine" , PALETTERGB (102,205,170)},
1093 {"MediumAquamarine" , PALETTERGB (102,205,170)},
1094 {"aquamarine" , PALETTERGB (127,255,212)},
1095 {"dark green" , PALETTERGB ( 0,100, 0)},
1096 {"DarkGreen" , PALETTERGB ( 0,100, 0)},
1097 {"dark olive green" , PALETTERGB ( 85,107, 47)},
1098 {"DarkOliveGreen" , PALETTERGB ( 85,107, 47)},
1099 {"dark sea green" , PALETTERGB (143,188,143)},
1100 {"DarkSeaGreen" , PALETTERGB (143,188,143)},
1101 {"sea green" , PALETTERGB ( 46,139, 87)},
1102 {"SeaGreen" , PALETTERGB ( 46,139, 87)},
1103 {"medium sea green" , PALETTERGB ( 60,179,113)},
1104 {"MediumSeaGreen" , PALETTERGB ( 60,179,113)},
1105 {"light sea green" , PALETTERGB ( 32,178,170)},
1106 {"LightSeaGreen" , PALETTERGB ( 32,178,170)},
1107 {"pale green" , PALETTERGB (152,251,152)},
1108 {"PaleGreen" , PALETTERGB (152,251,152)},
1109 {"spring green" , PALETTERGB ( 0,255,127)},
1110 {"SpringGreen" , PALETTERGB ( 0,255,127)},
1111 {"lawn green" , PALETTERGB (124,252, 0)},
1112 {"LawnGreen" , PALETTERGB (124,252, 0)},
1113 {"green" , PALETTERGB ( 0,255, 0)},
1114 {"chartreuse" , PALETTERGB (127,255, 0)},
1115 {"medium spring green" , PALETTERGB ( 0,250,154)},
1116 {"MediumSpringGreen" , PALETTERGB ( 0,250,154)},
1117 {"green yellow" , PALETTERGB (173,255, 47)},
1118 {"GreenYellow" , PALETTERGB (173,255, 47)},
1119 {"lime green" , PALETTERGB ( 50,205, 50)},
1120 {"LimeGreen" , PALETTERGB ( 50,205, 50)},
1121 {"yellow green" , PALETTERGB (154,205, 50)},
1122 {"YellowGreen" , PALETTERGB (154,205, 50)},
1123 {"forest green" , PALETTERGB ( 34,139, 34)},
1124 {"ForestGreen" , PALETTERGB ( 34,139, 34)},
1125 {"olive drab" , PALETTERGB (107,142, 35)},
1126 {"OliveDrab" , PALETTERGB (107,142, 35)},
1127 {"dark khaki" , PALETTERGB (189,183,107)},
1128 {"DarkKhaki" , PALETTERGB (189,183,107)},
1129 {"khaki" , PALETTERGB (240,230,140)},
1130 {"pale goldenrod" , PALETTERGB (238,232,170)},
1131 {"PaleGoldenrod" , PALETTERGB (238,232,170)},
1132 {"light goldenrod yellow" , PALETTERGB (250,250,210)},
1133 {"LightGoldenrodYellow" , PALETTERGB (250,250,210)},
1134 {"light yellow" , PALETTERGB (255,255,224)},
1135 {"LightYellow" , PALETTERGB (255,255,224)},
1136 {"yellow" , PALETTERGB (255,255, 0)},
1137 {"gold" , PALETTERGB (255,215, 0)},
1138 {"light goldenrod" , PALETTERGB (238,221,130)},
1139 {"LightGoldenrod" , PALETTERGB (238,221,130)},
1140 {"goldenrod" , PALETTERGB (218,165, 32)},
1141 {"dark goldenrod" , PALETTERGB (184,134, 11)},
1142 {"DarkGoldenrod" , PALETTERGB (184,134, 11)},
1143 {"rosy brown" , PALETTERGB (188,143,143)},
1144 {"RosyBrown" , PALETTERGB (188,143,143)},
1145 {"indian red" , PALETTERGB (205, 92, 92)},
1146 {"IndianRed" , PALETTERGB (205, 92, 92)},
1147 {"saddle brown" , PALETTERGB (139, 69, 19)},
1148 {"SaddleBrown" , PALETTERGB (139, 69, 19)},
1149 {"sienna" , PALETTERGB (160, 82, 45)},
1150 {"peru" , PALETTERGB (205,133, 63)},
1151 {"burlywood" , PALETTERGB (222,184,135)},
1152 {"beige" , PALETTERGB (245,245,220)},
1153 {"wheat" , PALETTERGB (245,222,179)},
1154 {"sandy brown" , PALETTERGB (244,164, 96)},
1155 {"SandyBrown" , PALETTERGB (244,164, 96)},
1156 {"tan" , PALETTERGB (210,180,140)},
1157 {"chocolate" , PALETTERGB (210,105, 30)},
1158 {"firebrick" , PALETTERGB (178,34, 34)},
1159 {"brown" , PALETTERGB (165,42, 42)},
1160 {"dark salmon" , PALETTERGB (233,150,122)},
1161 {"DarkSalmon" , PALETTERGB (233,150,122)},
1162 {"salmon" , PALETTERGB (250,128,114)},
1163 {"light salmon" , PALETTERGB (255,160,122)},
1164 {"LightSalmon" , PALETTERGB (255,160,122)},
1165 {"orange" , PALETTERGB (255,165, 0)},
1166 {"dark orange" , PALETTERGB (255,140, 0)},
1167 {"DarkOrange" , PALETTERGB (255,140, 0)},
1168 {"coral" , PALETTERGB (255,127, 80)},
1169 {"light coral" , PALETTERGB (240,128,128)},
1170 {"LightCoral" , PALETTERGB (240,128,128)},
1171 {"tomato" , PALETTERGB (255, 99, 71)},
1172 {"orange red" , PALETTERGB (255, 69, 0)},
1173 {"OrangeRed" , PALETTERGB (255, 69, 0)},
1174 {"red" , PALETTERGB (255, 0, 0)},
1175 {"hot pink" , PALETTERGB (255,105,180)},
1176 {"HotPink" , PALETTERGB (255,105,180)},
1177 {"deep pink" , PALETTERGB (255, 20,147)},
1178 {"DeepPink" , PALETTERGB (255, 20,147)},
1179 {"pink" , PALETTERGB (255,192,203)},
1180 {"light pink" , PALETTERGB (255,182,193)},
1181 {"LightPink" , PALETTERGB (255,182,193)},
1182 {"pale violet red" , PALETTERGB (219,112,147)},
1183 {"PaleVioletRed" , PALETTERGB (219,112,147)},
1184 {"maroon" , PALETTERGB (176, 48, 96)},
1185 {"medium violet red" , PALETTERGB (199, 21,133)},
1186 {"MediumVioletRed" , PALETTERGB (199, 21,133)},
1187 {"violet red" , PALETTERGB (208, 32,144)},
1188 {"VioletRed" , PALETTERGB (208, 32,144)},
1189 {"magenta" , PALETTERGB (255, 0,255)},
1190 {"violet" , PALETTERGB (238,130,238)},
1191 {"plum" , PALETTERGB (221,160,221)},
1192 {"orchid" , PALETTERGB (218,112,214)},
1193 {"medium orchid" , PALETTERGB (186, 85,211)},
1194 {"MediumOrchid" , PALETTERGB (186, 85,211)},
1195 {"dark orchid" , PALETTERGB (153, 50,204)},
1196 {"DarkOrchid" , PALETTERGB (153, 50,204)},
1197 {"dark violet" , PALETTERGB (148, 0,211)},
1198 {"DarkViolet" , PALETTERGB (148, 0,211)},
1199 {"blue violet" , PALETTERGB (138, 43,226)},
1200 {"BlueViolet" , PALETTERGB (138, 43,226)},
1201 {"purple" , PALETTERGB (160, 32,240)},
1202 {"medium purple" , PALETTERGB (147,112,219)},
1203 {"MediumPurple" , PALETTERGB (147,112,219)},
1204 {"thistle" , PALETTERGB (216,191,216)},
1205 {"gray0" , PALETTERGB ( 0, 0, 0)},
1206 {"grey0" , PALETTERGB ( 0, 0, 0)},
1207 {"dark grey" , PALETTERGB (169,169,169)},
1208 {"DarkGrey" , PALETTERGB (169,169,169)},
1209 {"dark gray" , PALETTERGB (169,169,169)},
1210 {"DarkGray" , PALETTERGB (169,169,169)},
1211 {"dark blue" , PALETTERGB ( 0, 0,139)},
1212 {"DarkBlue" , PALETTERGB ( 0, 0,139)},
1213 {"dark cyan" , PALETTERGB ( 0,139,139)},
1214 {"DarkCyan" , PALETTERGB ( 0,139,139)},
1215 {"dark magenta" , PALETTERGB (139, 0,139)},
1216 {"DarkMagenta" , PALETTERGB (139, 0,139)},
1217 {"dark red" , PALETTERGB (139, 0, 0)},
1218 {"DarkRed" , PALETTERGB (139, 0, 0)},
1219 {"light green" , PALETTERGB (144,238,144)},
1220 {"LightGreen" , PALETTERGB (144,238,144)},
1223 DEFUN ("w32-default-color-map", Fw32_default_color_map
, Sw32_default_color_map
,
1224 0, 0, 0, "Return the default color map.")
1228 colormap_t
*pc
= w32_color_map
;
1235 for (i
= 0; i
< sizeof (w32_color_map
) / sizeof (w32_color_map
[0]);
1237 cmap
= Fcons (Fcons (build_string (pc
->name
),
1238 make_number (pc
->colorref
)),
1247 w32_to_x_color (rgb
)
1252 CHECK_NUMBER (rgb
, 0);
1256 color
= Frassq (rgb
, Vw32_color_map
);
1261 return (Fcar (color
));
1267 x_to_w32_color (colorname
)
1270 register Lisp_Object tail
, ret
= Qnil
;
1274 if (colorname
[0] == '#')
1276 /* Could be an old-style RGB Device specification. */
1279 color
= colorname
+ 1;
1281 size
= strlen(color
);
1282 if (size
== 3 || size
== 6 || size
== 9 || size
== 12)
1290 for (i
= 0; i
< 3; i
++)
1294 unsigned long value
;
1296 /* The check for 'x' in the following conditional takes into
1297 account the fact that strtol allows a "0x" in front of
1298 our numbers, and we don't. */
1299 if (!isxdigit(color
[0]) || color
[1] == 'x')
1303 value
= strtoul(color
, &end
, 16);
1305 if (errno
== ERANGE
|| end
- color
!= size
)
1310 value
= value
* 0x10;
1321 colorval
|= (value
<< pos
);
1332 else if (strnicmp(colorname
, "rgb:", 4) == 0)
1340 color
= colorname
+ 4;
1341 for (i
= 0; i
< 3; i
++)
1344 unsigned long value
;
1346 /* The check for 'x' in the following conditional takes into
1347 account the fact that strtol allows a "0x" in front of
1348 our numbers, and we don't. */
1349 if (!isxdigit(color
[0]) || color
[1] == 'x')
1351 value
= strtoul(color
, &end
, 16);
1352 if (errno
== ERANGE
)
1354 switch (end
- color
)
1357 value
= value
* 0x10 + value
;
1370 if (value
== ULONG_MAX
)
1372 colorval
|= (value
<< pos
);
1386 else if (strnicmp(colorname
, "rgbi:", 5) == 0)
1388 /* This is an RGB Intensity specification. */
1395 color
= colorname
+ 5;
1396 for (i
= 0; i
< 3; i
++)
1402 value
= strtod(color
, &end
);
1403 if (errno
== ERANGE
)
1405 if (value
< 0.0 || value
> 1.0)
1407 val
= (UINT
)(0x100 * value
);
1408 /* We used 0x100 instead of 0xFF to give an continuous
1409 range between 0.0 and 1.0 inclusive. The next statement
1410 fixes the 1.0 case. */
1413 colorval
|= (val
<< pos
);
1427 /* I am not going to attempt to handle any of the CIE color schemes
1428 or TekHVC, since I don't know the algorithms for conversion to
1431 for (tail
= Vw32_color_map
; !NILP (tail
); tail
= Fcdr (tail
))
1433 register Lisp_Object elt
, tem
;
1436 if (!CONSP (elt
)) continue;
1440 if (lstrcmpi (XSTRING (tem
)->data
, colorname
) == 0)
1442 ret
= XUINT(Fcdr (elt
));
1456 w32_regenerate_palette (FRAME_PTR f
)
1458 struct w32_palette_entry
* list
;
1459 LOGPALETTE
* log_palette
;
1460 HPALETTE new_palette
;
1463 /* don't bother trying to create palette if not supported */
1464 if (! FRAME_W32_DISPLAY_INFO (f
)->has_palette
)
1467 log_palette
= (LOGPALETTE
*)
1468 alloca (sizeof (LOGPALETTE
) +
1469 FRAME_W32_DISPLAY_INFO (f
)->num_colors
* sizeof (PALETTEENTRY
));
1470 log_palette
->palVersion
= 0x300;
1471 log_palette
->palNumEntries
= FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1473 list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1475 i
< FRAME_W32_DISPLAY_INFO (f
)->num_colors
;
1476 i
++, list
= list
->next
)
1477 log_palette
->palPalEntry
[i
] = list
->entry
;
1479 new_palette
= CreatePalette (log_palette
);
1483 if (FRAME_W32_DISPLAY_INFO (f
)->palette
)
1484 DeleteObject (FRAME_W32_DISPLAY_INFO (f
)->palette
);
1485 FRAME_W32_DISPLAY_INFO (f
)->palette
= new_palette
;
1487 /* Realize display palette and garbage all frames. */
1488 release_frame_dc (f
, get_frame_dc (f
));
1493 #define W32_COLOR(pe) RGB (pe.peRed, pe.peGreen, pe.peBlue)
1494 #define SET_W32_COLOR(pe, color) \
1497 pe.peRed = GetRValue (color); \
1498 pe.peGreen = GetGValue (color); \
1499 pe.peBlue = GetBValue (color); \
1504 /* Keep these around in case we ever want to track color usage. */
1506 w32_map_color (FRAME_PTR f
, COLORREF color
)
1508 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1510 if (NILP (Vw32_enable_palette
))
1513 /* check if color is already mapped */
1516 if (W32_COLOR (list
->entry
) == color
)
1524 /* not already mapped, so add to list and recreate Windows palette */
1525 list
= (struct w32_palette_entry
*)
1526 xmalloc (sizeof (struct w32_palette_entry
));
1527 SET_W32_COLOR (list
->entry
, color
);
1529 list
->next
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1530 FRAME_W32_DISPLAY_INFO (f
)->color_list
= list
;
1531 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1533 /* set flag that palette must be regenerated */
1534 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1538 w32_unmap_color (FRAME_PTR f
, COLORREF color
)
1540 struct w32_palette_entry
* list
= FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1541 struct w32_palette_entry
**prev
= &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1543 if (NILP (Vw32_enable_palette
))
1546 /* check if color is already mapped */
1549 if (W32_COLOR (list
->entry
) == color
)
1551 if (--list
->refcount
== 0)
1555 FRAME_W32_DISPLAY_INFO (f
)->num_colors
--;
1565 /* set flag that palette must be regenerated */
1566 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1570 /* Decide if color named COLOR is valid for the display associated with
1571 the selected frame; if so, return the rgb values in COLOR_DEF.
1572 If ALLOC is nonzero, allocate a new colormap cell. */
1575 defined_color (f
, color
, color_def
, alloc
)
1578 COLORREF
*color_def
;
1581 register Lisp_Object tem
;
1583 tem
= x_to_w32_color (color
);
1587 if (!NILP (Vw32_enable_palette
))
1589 struct w32_palette_entry
* entry
=
1590 FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1591 struct w32_palette_entry
** prev
=
1592 &FRAME_W32_DISPLAY_INFO (f
)->color_list
;
1594 /* check if color is already mapped */
1597 if (W32_COLOR (entry
->entry
) == XUINT (tem
))
1599 prev
= &entry
->next
;
1600 entry
= entry
->next
;
1603 if (entry
== NULL
&& alloc
)
1605 /* not already mapped, so add to list */
1606 entry
= (struct w32_palette_entry
*)
1607 xmalloc (sizeof (struct w32_palette_entry
));
1608 SET_W32_COLOR (entry
->entry
, XUINT (tem
));
1611 FRAME_W32_DISPLAY_INFO (f
)->num_colors
++;
1613 /* set flag that palette must be regenerated */
1614 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= TRUE
;
1617 /* Ensure COLORREF value is snapped to nearest color in (default)
1618 palette by simulating the PALETTERGB macro. This works whether
1619 or not the display device has a palette. */
1620 *color_def
= XUINT (tem
) | 0x2000000;
1629 /* Given a string ARG naming a color, compute a pixel value from it
1630 suitable for screen F.
1631 If F is not a color screen, return DEF (default) regardless of what
1635 x_decode_color (f
, arg
, def
)
1642 CHECK_STRING (arg
, 0);
1644 if (strcmp (XSTRING (arg
)->data
, "black") == 0)
1645 return BLACK_PIX_DEFAULT (f
);
1646 else if (strcmp (XSTRING (arg
)->data
, "white") == 0)
1647 return WHITE_PIX_DEFAULT (f
);
1649 if ((FRAME_W32_DISPLAY_INFO (f
)->n_planes
* FRAME_W32_DISPLAY_INFO (f
)->n_cbits
) == 1)
1652 /* defined_color is responsible for coping with failures
1653 by looking for a near-miss. */
1654 if (defined_color (f
, XSTRING (arg
)->data
, &cdef
, 1))
1657 /* defined_color failed; return an ultimate default. */
1661 /* Functions called only from `x_set_frame_param'
1662 to set individual parameters.
1664 If FRAME_W32_WINDOW (f) is 0,
1665 the frame is being created and its window does not exist yet.
1666 In that case, just record the parameter's new value
1667 in the standard place; do not attempt to change the window. */
1670 x_set_foreground_color (f
, arg
, oldval
)
1672 Lisp_Object arg
, oldval
;
1674 f
->output_data
.w32
->foreground_pixel
1675 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1677 if (FRAME_W32_WINDOW (f
) != 0)
1679 recompute_basic_faces (f
);
1680 if (FRAME_VISIBLE_P (f
))
1686 x_set_background_color (f
, arg
, oldval
)
1688 Lisp_Object arg
, oldval
;
1693 f
->output_data
.w32
->background_pixel
1694 = x_decode_color (f
, arg
, WHITE_PIX_DEFAULT (f
));
1696 if (FRAME_W32_WINDOW (f
) != 0)
1698 SetWindowLong (FRAME_W32_WINDOW (f
), WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
1700 recompute_basic_faces (f
);
1702 if (FRAME_VISIBLE_P (f
))
1708 x_set_mouse_color (f
, arg
, oldval
)
1710 Lisp_Object arg
, oldval
;
1713 Cursor cursor
, nontext_cursor
, mode_cursor
, cross_cursor
;
1718 if (!EQ (Qnil
, arg
))
1719 f
->output_data
.w32
->mouse_pixel
1720 = x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1721 mask_color
= f
->output_data
.w32
->background_pixel
;
1722 /* No invisible pointers. */
1723 if (mask_color
== f
->output_data
.w32
->mouse_pixel
1724 && mask_color
== f
->output_data
.w32
->background_pixel
)
1725 f
->output_data
.w32
->mouse_pixel
= f
->output_data
.w32
->foreground_pixel
;
1730 /* It's not okay to crash if the user selects a screwy cursor. */
1731 count
= x_catch_errors (FRAME_W32_DISPLAY (f
));
1733 if (!EQ (Qnil
, Vx_pointer_shape
))
1735 CHECK_NUMBER (Vx_pointer_shape
, 0);
1736 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XINT (Vx_pointer_shape
));
1739 cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1740 x_check_errors (FRAME_W32_DISPLAY (f
), "bad text pointer cursor: %s");
1742 if (!EQ (Qnil
, Vx_nontext_pointer_shape
))
1744 CHECK_NUMBER (Vx_nontext_pointer_shape
, 0);
1745 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1746 XINT (Vx_nontext_pointer_shape
));
1749 nontext_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_left_ptr
);
1750 x_check_errors (FRAME_W32_DISPLAY (f
), "bad nontext pointer cursor: %s");
1752 if (!EQ (Qnil
, Vx_mode_pointer_shape
))
1754 CHECK_NUMBER (Vx_mode_pointer_shape
, 0);
1755 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1756 XINT (Vx_mode_pointer_shape
));
1759 mode_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_xterm
);
1760 x_check_errors (FRAME_W32_DISPLAY (f
), "bad modeline pointer cursor: %s");
1762 if (!EQ (Qnil
, Vx_sensitive_text_pointer_shape
))
1764 CHECK_NUMBER (Vx_sensitive_text_pointer_shape
, 0);
1766 = XCreateFontCursor (FRAME_W32_DISPLAY (f
),
1767 XINT (Vx_sensitive_text_pointer_shape
));
1770 cross_cursor
= XCreateFontCursor (FRAME_W32_DISPLAY (f
), XC_crosshair
);
1772 /* Check and report errors with the above calls. */
1773 x_check_errors (FRAME_W32_DISPLAY (f
), "can't set cursor shape: %s");
1774 x_uncatch_errors (FRAME_W32_DISPLAY (f
), count
);
1777 XColor fore_color
, back_color
;
1779 fore_color
.pixel
= f
->output_data
.w32
->mouse_pixel
;
1780 back_color
.pixel
= mask_color
;
1781 XQueryColor (FRAME_W32_DISPLAY (f
),
1782 DefaultColormap (FRAME_W32_DISPLAY (f
),
1783 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1785 XQueryColor (FRAME_W32_DISPLAY (f
),
1786 DefaultColormap (FRAME_W32_DISPLAY (f
),
1787 DefaultScreen (FRAME_W32_DISPLAY (f
))),
1789 XRecolorCursor (FRAME_W32_DISPLAY (f
), cursor
,
1790 &fore_color
, &back_color
);
1791 XRecolorCursor (FRAME_W32_DISPLAY (f
), nontext_cursor
,
1792 &fore_color
, &back_color
);
1793 XRecolorCursor (FRAME_W32_DISPLAY (f
), mode_cursor
,
1794 &fore_color
, &back_color
);
1795 XRecolorCursor (FRAME_W32_DISPLAY (f
), cross_cursor
,
1796 &fore_color
, &back_color
);
1799 if (FRAME_W32_WINDOW (f
) != 0)
1801 XDefineCursor (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
), cursor
);
1804 if (cursor
!= f
->output_data
.w32
->text_cursor
&& f
->output_data
.w32
->text_cursor
!= 0)
1805 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->text_cursor
);
1806 f
->output_data
.w32
->text_cursor
= cursor
;
1808 if (nontext_cursor
!= f
->output_data
.w32
->nontext_cursor
1809 && f
->output_data
.w32
->nontext_cursor
!= 0)
1810 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->nontext_cursor
);
1811 f
->output_data
.w32
->nontext_cursor
= nontext_cursor
;
1813 if (mode_cursor
!= f
->output_data
.w32
->modeline_cursor
1814 && f
->output_data
.w32
->modeline_cursor
!= 0)
1815 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->modeline_cursor
);
1816 f
->output_data
.w32
->modeline_cursor
= mode_cursor
;
1817 if (cross_cursor
!= f
->output_data
.w32
->cross_cursor
1818 && f
->output_data
.w32
->cross_cursor
!= 0)
1819 XFreeCursor (FRAME_W32_DISPLAY (f
), f
->output_data
.w32
->cross_cursor
);
1820 f
->output_data
.w32
->cross_cursor
= cross_cursor
;
1822 XFlush (FRAME_W32_DISPLAY (f
));
1828 x_set_cursor_color (f
, arg
, oldval
)
1830 Lisp_Object arg
, oldval
;
1832 unsigned long fore_pixel
;
1834 if (!EQ (Vx_cursor_fore_pixel
, Qnil
))
1835 fore_pixel
= x_decode_color (f
, Vx_cursor_fore_pixel
,
1836 WHITE_PIX_DEFAULT (f
));
1838 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1839 f
->output_data
.w32
->cursor_pixel
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1841 /* Make sure that the cursor color differs from the background color. */
1842 if (f
->output_data
.w32
->cursor_pixel
== f
->output_data
.w32
->background_pixel
)
1844 f
->output_data
.w32
->cursor_pixel
= f
->output_data
.w32
->mouse_pixel
;
1845 if (f
->output_data
.w32
->cursor_pixel
== fore_pixel
)
1846 fore_pixel
= f
->output_data
.w32
->background_pixel
;
1848 f
->output_data
.w32
->cursor_foreground_pixel
= fore_pixel
;
1850 if (FRAME_W32_WINDOW (f
) != 0)
1852 if (FRAME_VISIBLE_P (f
))
1854 x_display_cursor (f
, 0);
1855 x_display_cursor (f
, 1);
1860 /* Set the border-color of frame F to value described by ARG.
1861 ARG can be a string naming a color.
1862 The border-color is used for the border that is drawn by the server.
1863 Note that this does not fully take effect if done before
1864 F has a window; it must be redone when the window is created. */
1867 x_set_border_color (f
, arg
, oldval
)
1869 Lisp_Object arg
, oldval
;
1874 CHECK_STRING (arg
, 0);
1875 str
= XSTRING (arg
)->data
;
1877 pix
= x_decode_color (f
, arg
, BLACK_PIX_DEFAULT (f
));
1879 x_set_border_pixel (f
, pix
);
1882 /* Set the border-color of frame F to pixel value PIX.
1883 Note that this does not fully take effect if done before
1886 x_set_border_pixel (f
, pix
)
1890 f
->output_data
.w32
->border_pixel
= pix
;
1892 if (FRAME_W32_WINDOW (f
) != 0 && f
->output_data
.w32
->border_width
> 0)
1894 if (FRAME_VISIBLE_P (f
))
1900 x_set_cursor_type (f
, arg
, oldval
)
1902 Lisp_Object arg
, oldval
;
1906 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
1907 f
->output_data
.w32
->cursor_width
= 2;
1909 else if (CONSP (arg
) && EQ (XCONS (arg
)->car
, Qbar
)
1910 && INTEGERP (XCONS (arg
)->cdr
))
1912 FRAME_DESIRED_CURSOR (f
) = bar_cursor
;
1913 f
->output_data
.w32
->cursor_width
= XINT (XCONS (arg
)->cdr
);
1916 /* Treat anything unknown as "box cursor".
1917 It was bad to signal an error; people have trouble fixing
1918 .Xdefaults with Emacs, when it has something bad in it. */
1919 FRAME_DESIRED_CURSOR (f
) = filled_box_cursor
;
1921 /* Make sure the cursor gets redrawn. This is overkill, but how
1922 often do people change cursor types? */
1923 update_mode_lines
++;
1927 x_set_icon_type (f
, arg
, oldval
)
1929 Lisp_Object arg
, oldval
;
1937 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
1940 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
1945 result
= x_text_icon (f
,
1946 (char *) XSTRING ((!NILP (f
->icon_name
)
1950 result
= x_bitmap_icon (f
, arg
);
1955 error ("No icon window available");
1958 /* If the window was unmapped (and its icon was mapped),
1959 the new icon is not mapped, so map the window in its stead. */
1960 if (FRAME_VISIBLE_P (f
))
1962 #ifdef USE_X_TOOLKIT
1963 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
1965 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
1968 XFlush (FRAME_W32_DISPLAY (f
));
1973 /* Return non-nil if frame F wants a bitmap icon. */
1981 tem
= assq_no_quit (Qicon_type
, f
->param_alist
);
1983 return XCONS (tem
)->cdr
;
1989 x_set_icon_name (f
, arg
, oldval
)
1991 Lisp_Object arg
, oldval
;
1998 if (STRINGP (oldval
) && EQ (Fstring_equal (oldval
, arg
), Qt
))
2001 else if (!STRINGP (oldval
) && EQ (oldval
, Qnil
) == EQ (arg
, Qnil
))
2007 if (f
->output_data
.w32
->icon_bitmap
!= 0)
2012 result
= x_text_icon (f
,
2013 (char *) XSTRING ((!NILP (f
->icon_name
)
2022 error ("No icon window available");
2025 /* If the window was unmapped (and its icon was mapped),
2026 the new icon is not mapped, so map the window in its stead. */
2027 if (FRAME_VISIBLE_P (f
))
2029 #ifdef USE_X_TOOLKIT
2030 XtPopup (f
->output_data
.w32
->widget
, XtGrabNone
);
2032 XMapWindow (FRAME_W32_DISPLAY (f
), FRAME_W32_WINDOW (f
));
2035 XFlush (FRAME_W32_DISPLAY (f
));
2040 extern Lisp_Object
x_new_font ();
2043 x_set_font (f
, arg
, oldval
)
2045 Lisp_Object arg
, oldval
;
2049 CHECK_STRING (arg
, 1);
2052 result
= x_new_font (f
, XSTRING (arg
)->data
);
2055 if (EQ (result
, Qnil
))
2056 error ("Font \"%s\" is not defined", XSTRING (arg
)->data
);
2057 else if (EQ (result
, Qt
))
2058 error ("the characters of the given font have varying widths");
2059 else if (STRINGP (result
))
2061 recompute_basic_faces (f
);
2062 store_frame_param (f
, Qfont
, result
);
2069 x_set_border_width (f
, arg
, oldval
)
2071 Lisp_Object arg
, oldval
;
2073 CHECK_NUMBER (arg
, 0);
2075 if (XINT (arg
) == f
->output_data
.w32
->border_width
)
2078 if (FRAME_W32_WINDOW (f
) != 0)
2079 error ("Cannot change the border width of a window");
2081 f
->output_data
.w32
->border_width
= XINT (arg
);
2085 x_set_internal_border_width (f
, arg
, oldval
)
2087 Lisp_Object arg
, oldval
;
2090 int old
= f
->output_data
.w32
->internal_border_width
;
2092 CHECK_NUMBER (arg
, 0);
2093 f
->output_data
.w32
->internal_border_width
= XINT (arg
);
2094 if (f
->output_data
.w32
->internal_border_width
< 0)
2095 f
->output_data
.w32
->internal_border_width
= 0;
2097 if (f
->output_data
.w32
->internal_border_width
== old
)
2100 if (FRAME_W32_WINDOW (f
) != 0)
2103 x_set_window_size (f
, 0, f
->width
, f
->height
);
2105 SET_FRAME_GARBAGED (f
);
2110 x_set_visibility (f
, value
, oldval
)
2112 Lisp_Object value
, oldval
;
2115 XSETFRAME (frame
, f
);
2118 Fmake_frame_invisible (frame
, Qt
);
2119 else if (EQ (value
, Qicon
))
2120 Ficonify_frame (frame
);
2122 Fmake_frame_visible (frame
);
2126 x_set_menu_bar_lines (f
, value
, oldval
)
2128 Lisp_Object value
, oldval
;
2131 int olines
= FRAME_MENU_BAR_LINES (f
);
2133 /* Right now, menu bars don't work properly in minibuf-only frames;
2134 most of the commands try to apply themselves to the minibuffer
2135 frame itslef, and get an error because you can't switch buffers
2136 in or split the minibuffer window. */
2137 if (FRAME_MINIBUF_ONLY_P (f
))
2140 if (INTEGERP (value
))
2141 nlines
= XINT (value
);
2145 FRAME_MENU_BAR_LINES (f
) = 0;
2147 FRAME_EXTERNAL_MENU_BAR (f
) = 1;
2150 if (FRAME_EXTERNAL_MENU_BAR (f
) == 1)
2151 free_frame_menubar (f
);
2152 FRAME_EXTERNAL_MENU_BAR (f
) = 0;
2154 /* Adjust the frame size so that the client (text) dimensions
2155 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
2157 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2161 /* Change the name of frame F to NAME. If NAME is nil, set F's name to
2164 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2165 name; if NAME is a string, set F's name to NAME and set
2166 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2168 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2169 suggesting a new name, which lisp code should override; if
2170 F->explicit_name is set, ignore the new name; otherwise, set it. */
2173 x_set_name (f
, name
, explicit)
2178 /* Make sure that requests from lisp code override requests from
2179 Emacs redisplay code. */
2182 /* If we're switching from explicit to implicit, we had better
2183 update the mode lines and thereby update the title. */
2184 if (f
->explicit_name
&& NILP (name
))
2185 update_mode_lines
= 1;
2187 f
->explicit_name
= ! NILP (name
);
2189 else if (f
->explicit_name
)
2192 /* If NAME is nil, set the name to the w32_id_name. */
2195 /* Check for no change needed in this very common case
2196 before we do any consing. */
2197 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
,
2198 XSTRING (f
->name
)->data
))
2200 name
= build_string (FRAME_W32_DISPLAY_INFO (f
)->w32_id_name
);
2203 CHECK_STRING (name
, 0);
2205 /* Don't change the name if it's already NAME. */
2206 if (! NILP (Fstring_equal (name
, f
->name
)))
2211 /* For setting the frame title, the title parameter should override
2212 the name parameter. */
2213 if (! NILP (f
->title
))
2216 if (FRAME_W32_WINDOW (f
))
2219 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2224 /* This function should be called when the user's lisp code has
2225 specified a name for the frame; the name will override any set by the
2228 x_explicitly_set_name (f
, arg
, oldval
)
2230 Lisp_Object arg
, oldval
;
2232 x_set_name (f
, arg
, 1);
2235 /* This function should be called by Emacs redisplay code to set the
2236 name; names set this way will never override names set by the user's
2239 x_implicitly_set_name (f
, arg
, oldval
)
2241 Lisp_Object arg
, oldval
;
2243 x_set_name (f
, arg
, 0);
2246 /* Change the title of frame F to NAME.
2247 If NAME is nil, use the frame name as the title.
2249 If EXPLICIT is non-zero, that indicates that lisp code is setting the
2250 name; if NAME is a string, set F's name to NAME and set
2251 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
2253 If EXPLICIT is zero, that indicates that Emacs redisplay code is
2254 suggesting a new name, which lisp code should override; if
2255 F->explicit_name is set, ignore the new name; otherwise, set it. */
2258 x_set_title (f
, name
)
2262 /* Don't change the title if it's already NAME. */
2263 if (EQ (name
, f
->title
))
2266 update_mode_lines
= 1;
2273 if (FRAME_W32_WINDOW (f
))
2276 SetWindowText(FRAME_W32_WINDOW (f
), XSTRING (name
)->data
);
2282 x_set_autoraise (f
, arg
, oldval
)
2284 Lisp_Object arg
, oldval
;
2286 f
->auto_raise
= !EQ (Qnil
, arg
);
2290 x_set_autolower (f
, arg
, oldval
)
2292 Lisp_Object arg
, oldval
;
2294 f
->auto_lower
= !EQ (Qnil
, arg
);
2298 x_set_unsplittable (f
, arg
, oldval
)
2300 Lisp_Object arg
, oldval
;
2302 f
->no_split
= !NILP (arg
);
2306 x_set_vertical_scroll_bars (f
, arg
, oldval
)
2308 Lisp_Object arg
, oldval
;
2310 if ((EQ (arg
, Qleft
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
2311 || (EQ (arg
, Qright
) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
2312 || (NILP (arg
) && FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2313 || (!NILP (arg
) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f
)))
2315 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = NILP (arg
) ?
2316 vertical_scroll_bar_none
:
2317 /* Put scroll bars on the right by default, as is conventional
2320 ? vertical_scroll_bar_left
2321 : vertical_scroll_bar_right
;
2323 /* We set this parameter before creating the window for the
2324 frame, so we can get the geometry right from the start.
2325 However, if the window hasn't been created yet, we shouldn't
2326 call x_set_window_size. */
2327 if (FRAME_W32_WINDOW (f
))
2328 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2333 x_set_scroll_bar_width (f
, arg
, oldval
)
2335 Lisp_Object arg
, oldval
;
2339 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = 0;
2340 FRAME_SCROLL_BAR_COLS (f
) = 2;
2342 else if (INTEGERP (arg
) && XINT (arg
) > 0
2343 && XFASTINT (arg
) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f
))
2345 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
2346 FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) = XFASTINT (arg
);
2347 FRAME_SCROLL_BAR_COLS (f
) = (XFASTINT (arg
) + wid
-1) / wid
;
2348 if (FRAME_W32_WINDOW (f
))
2349 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
2353 /* Subroutines of creating an frame. */
2355 /* Make sure that Vx_resource_name is set to a reasonable value.
2356 Fix it up, or set it to `emacs' if it is too hopeless. */
2359 validate_x_resource_name ()
2362 /* Number of valid characters in the resource name. */
2364 /* Number of invalid characters in the resource name. */
2369 if (STRINGP (Vx_resource_name
))
2371 unsigned char *p
= XSTRING (Vx_resource_name
)->data
;
2374 len
= XSTRING (Vx_resource_name
)->size
;
2376 /* Only letters, digits, - and _ are valid in resource names.
2377 Count the valid characters and count the invalid ones. */
2378 for (i
= 0; i
< len
; i
++)
2381 if (! ((c
>= 'a' && c
<= 'z')
2382 || (c
>= 'A' && c
<= 'Z')
2383 || (c
>= '0' && c
<= '9')
2384 || c
== '-' || c
== '_'))
2391 /* Not a string => completely invalid. */
2392 bad_count
= 5, good_count
= 0;
2394 /* If name is valid already, return. */
2398 /* If name is entirely invalid, or nearly so, use `emacs'. */
2400 || (good_count
== 1 && bad_count
> 0))
2402 Vx_resource_name
= build_string ("emacs");
2406 /* Name is partly valid. Copy it and replace the invalid characters
2407 with underscores. */
2409 Vx_resource_name
= new = Fcopy_sequence (Vx_resource_name
);
2411 for (i
= 0; i
< len
; i
++)
2413 int c
= XSTRING (new)->data
[i
];
2414 if (! ((c
>= 'a' && c
<= 'z')
2415 || (c
>= 'A' && c
<= 'Z')
2416 || (c
>= '0' && c
<= '9')
2417 || c
== '-' || c
== '_'))
2418 XSTRING (new)->data
[i
] = '_';
2423 extern char *x_get_string_resource ();
2425 DEFUN ("x-get-resource", Fx_get_resource
, Sx_get_resource
, 2, 4, 0,
2426 "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
2427 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
2428 class, where INSTANCE is the name under which Emacs was invoked, or\n\
2429 the name specified by the `-name' or `-rn' command-line arguments.\n\
2431 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
2432 class, respectively. You must specify both of them or neither.\n\
2433 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
2434 and the class is `Emacs.CLASS.SUBCLASS'.")
2435 (attribute
, class, component
, subclass
)
2436 Lisp_Object attribute
, class, component
, subclass
;
2438 register char *value
;
2442 CHECK_STRING (attribute
, 0);
2443 CHECK_STRING (class, 0);
2445 if (!NILP (component
))
2446 CHECK_STRING (component
, 1);
2447 if (!NILP (subclass
))
2448 CHECK_STRING (subclass
, 2);
2449 if (NILP (component
) != NILP (subclass
))
2450 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
2452 validate_x_resource_name ();
2454 /* Allocate space for the components, the dots which separate them,
2455 and the final '\0'. Make them big enough for the worst case. */
2456 name_key
= (char *) alloca (XSTRING (Vx_resource_name
)->size
2457 + (STRINGP (component
)
2458 ? XSTRING (component
)->size
: 0)
2459 + XSTRING (attribute
)->size
2462 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2463 + XSTRING (class)->size
2464 + (STRINGP (subclass
)
2465 ? XSTRING (subclass
)->size
: 0)
2468 /* Start with emacs.FRAMENAME for the name (the specific one)
2469 and with `Emacs' for the class key (the general one). */
2470 strcpy (name_key
, XSTRING (Vx_resource_name
)->data
);
2471 strcpy (class_key
, EMACS_CLASS
);
2473 strcat (class_key
, ".");
2474 strcat (class_key
, XSTRING (class)->data
);
2476 if (!NILP (component
))
2478 strcat (class_key
, ".");
2479 strcat (class_key
, XSTRING (subclass
)->data
);
2481 strcat (name_key
, ".");
2482 strcat (name_key
, XSTRING (component
)->data
);
2485 strcat (name_key
, ".");
2486 strcat (name_key
, XSTRING (attribute
)->data
);
2488 value
= x_get_string_resource (Qnil
,
2489 name_key
, class_key
);
2491 if (value
!= (char *) 0)
2492 return build_string (value
);
2497 /* Used when C code wants a resource value. */
2500 x_get_resource_string (attribute
, class)
2501 char *attribute
, *class;
2503 register char *value
;
2507 /* Allocate space for the components, the dots which separate them,
2508 and the final '\0'. */
2509 name_key
= (char *) alloca (XSTRING (Vinvocation_name
)->size
2510 + strlen (attribute
) + 2);
2511 class_key
= (char *) alloca ((sizeof (EMACS_CLASS
) - 1)
2512 + strlen (class) + 2);
2514 sprintf (name_key
, "%s.%s",
2515 XSTRING (Vinvocation_name
)->data
,
2517 sprintf (class_key
, "%s.%s", EMACS_CLASS
, class);
2519 return x_get_string_resource (selected_frame
,
2520 name_key
, class_key
);
2523 /* Types we might convert a resource string into. */
2526 number
, boolean
, string
, symbol
2529 /* Return the value of parameter PARAM.
2531 First search ALIST, then Vdefault_frame_alist, then the X defaults
2532 database, using ATTRIBUTE as the attribute name and CLASS as its class.
2534 Convert the resource to the type specified by desired_type.
2536 If no default is specified, return Qunbound. If you call
2537 x_get_arg, make sure you deal with Qunbound in a reasonable way,
2538 and don't let it get stored in any Lisp-visible variables! */
2541 x_get_arg (alist
, param
, attribute
, class, type
)
2542 Lisp_Object alist
, param
;
2545 enum resource_types type
;
2547 register Lisp_Object tem
;
2549 tem
= Fassq (param
, alist
);
2551 tem
= Fassq (param
, Vdefault_frame_alist
);
2557 tem
= Fx_get_resource (build_string (attribute
),
2558 build_string (class),
2567 return make_number (atoi (XSTRING (tem
)->data
));
2570 tem
= Fdowncase (tem
);
2571 if (!strcmp (XSTRING (tem
)->data
, "on")
2572 || !strcmp (XSTRING (tem
)->data
, "true"))
2581 /* As a special case, we map the values `true' and `on'
2582 to Qt, and `false' and `off' to Qnil. */
2585 lower
= Fdowncase (tem
);
2586 if (!strcmp (XSTRING (lower
)->data
, "on")
2587 || !strcmp (XSTRING (lower
)->data
, "true"))
2589 else if (!strcmp (XSTRING (lower
)->data
, "off")
2590 || !strcmp (XSTRING (lower
)->data
, "false"))
2593 return Fintern (tem
, Qnil
);
2606 /* Record in frame F the specified or default value according to ALIST
2607 of the parameter named PARAM (a Lisp symbol).
2608 If no value is specified for PARAM, look for an X default for XPROP
2609 on the frame named NAME.
2610 If that is not found either, use the value DEFLT. */
2613 x_default_parameter (f
, alist
, prop
, deflt
, xprop
, xclass
, type
)
2620 enum resource_types type
;
2624 tem
= x_get_arg (alist
, prop
, xprop
, xclass
, type
);
2625 if (EQ (tem
, Qunbound
))
2627 x_set_frame_parameters (f
, Fcons (Fcons (prop
, tem
), Qnil
));
2631 DEFUN ("x-parse-geometry", Fx_parse_geometry
, Sx_parse_geometry
, 1, 1, 0,
2632 "Parse an X-style geometry string STRING.\n\
2633 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
2634 The properties returned may include `top', `left', `height', and `width'.\n\
2635 The value of `left' or `top' may be an integer,\n\
2636 or a list (+ N) meaning N pixels relative to top/left corner,\n\
2637 or a list (- N) meaning -N pixels relative to bottom/right corner.")
2642 unsigned int width
, height
;
2645 CHECK_STRING (string
, 0);
2647 geometry
= XParseGeometry ((char *) XSTRING (string
)->data
,
2648 &x
, &y
, &width
, &height
);
2651 if (geometry
& XValue
)
2653 Lisp_Object element
;
2655 if (x
>= 0 && (geometry
& XNegative
))
2656 element
= Fcons (Qleft
, Fcons (Qminus
, Fcons (make_number (-x
), Qnil
)));
2657 else if (x
< 0 && ! (geometry
& XNegative
))
2658 element
= Fcons (Qleft
, Fcons (Qplus
, Fcons (make_number (x
), Qnil
)));
2660 element
= Fcons (Qleft
, make_number (x
));
2661 result
= Fcons (element
, result
);
2664 if (geometry
& YValue
)
2666 Lisp_Object element
;
2668 if (y
>= 0 && (geometry
& YNegative
))
2669 element
= Fcons (Qtop
, Fcons (Qminus
, Fcons (make_number (-y
), Qnil
)));
2670 else if (y
< 0 && ! (geometry
& YNegative
))
2671 element
= Fcons (Qtop
, Fcons (Qplus
, Fcons (make_number (y
), Qnil
)));
2673 element
= Fcons (Qtop
, make_number (y
));
2674 result
= Fcons (element
, result
);
2677 if (geometry
& WidthValue
)
2678 result
= Fcons (Fcons (Qwidth
, make_number (width
)), result
);
2679 if (geometry
& HeightValue
)
2680 result
= Fcons (Fcons (Qheight
, make_number (height
)), result
);
2685 /* Calculate the desired size and position of this window,
2686 and return the flags saying which aspects were specified.
2688 This function does not make the coordinates positive. */
2690 #define DEFAULT_ROWS 40
2691 #define DEFAULT_COLS 80
2694 x_figure_window_size (f
, parms
)
2698 register Lisp_Object tem0
, tem1
, tem2
;
2699 int height
, width
, left
, top
;
2700 register int geometry
;
2701 long window_prompting
= 0;
2703 /* Default values if we fall through.
2704 Actually, if that happens we should get
2705 window manager prompting. */
2706 SET_FRAME_WIDTH (f
, DEFAULT_COLS
);
2707 f
->height
= DEFAULT_ROWS
;
2708 /* Window managers expect that if program-specified
2709 positions are not (0,0), they're intentional, not defaults. */
2710 f
->output_data
.w32
->top_pos
= 0;
2711 f
->output_data
.w32
->left_pos
= 0;
2713 tem0
= x_get_arg (parms
, Qheight
, 0, 0, number
);
2714 tem1
= x_get_arg (parms
, Qwidth
, 0, 0, number
);
2715 tem2
= x_get_arg (parms
, Quser_size
, 0, 0, number
);
2716 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2718 if (!EQ (tem0
, Qunbound
))
2720 CHECK_NUMBER (tem0
, 0);
2721 f
->height
= XINT (tem0
);
2723 if (!EQ (tem1
, Qunbound
))
2725 CHECK_NUMBER (tem1
, 0);
2726 SET_FRAME_WIDTH (f
, XINT (tem1
));
2728 if (!NILP (tem2
) && !EQ (tem2
, Qunbound
))
2729 window_prompting
|= USSize
;
2731 window_prompting
|= PSize
;
2734 f
->output_data
.w32
->vertical_scroll_bar_extra
2735 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2737 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2738 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2739 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2740 f
->output_data
.w32
->pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, f
->width
);
2741 f
->output_data
.w32
->pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, f
->height
);
2743 tem0
= x_get_arg (parms
, Qtop
, 0, 0, number
);
2744 tem1
= x_get_arg (parms
, Qleft
, 0, 0, number
);
2745 tem2
= x_get_arg (parms
, Quser_position
, 0, 0, number
);
2746 if (! EQ (tem0
, Qunbound
) || ! EQ (tem1
, Qunbound
))
2748 if (EQ (tem0
, Qminus
))
2750 f
->output_data
.w32
->top_pos
= 0;
2751 window_prompting
|= YNegative
;
2753 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qminus
)
2754 && CONSP (XCONS (tem0
)->cdr
)
2755 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2757 f
->output_data
.w32
->top_pos
= - XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2758 window_prompting
|= YNegative
;
2760 else if (CONSP (tem0
) && EQ (XCONS (tem0
)->car
, Qplus
)
2761 && CONSP (XCONS (tem0
)->cdr
)
2762 && INTEGERP (XCONS (XCONS (tem0
)->cdr
)->car
))
2764 f
->output_data
.w32
->top_pos
= XINT (XCONS (XCONS (tem0
)->cdr
)->car
);
2766 else if (EQ (tem0
, Qunbound
))
2767 f
->output_data
.w32
->top_pos
= 0;
2770 CHECK_NUMBER (tem0
, 0);
2771 f
->output_data
.w32
->top_pos
= XINT (tem0
);
2772 if (f
->output_data
.w32
->top_pos
< 0)
2773 window_prompting
|= YNegative
;
2776 if (EQ (tem1
, Qminus
))
2778 f
->output_data
.w32
->left_pos
= 0;
2779 window_prompting
|= XNegative
;
2781 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qminus
)
2782 && CONSP (XCONS (tem1
)->cdr
)
2783 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2785 f
->output_data
.w32
->left_pos
= - XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2786 window_prompting
|= XNegative
;
2788 else if (CONSP (tem1
) && EQ (XCONS (tem1
)->car
, Qplus
)
2789 && CONSP (XCONS (tem1
)->cdr
)
2790 && INTEGERP (XCONS (XCONS (tem1
)->cdr
)->car
))
2792 f
->output_data
.w32
->left_pos
= XINT (XCONS (XCONS (tem1
)->cdr
)->car
);
2794 else if (EQ (tem1
, Qunbound
))
2795 f
->output_data
.w32
->left_pos
= 0;
2798 CHECK_NUMBER (tem1
, 0);
2799 f
->output_data
.w32
->left_pos
= XINT (tem1
);
2800 if (f
->output_data
.w32
->left_pos
< 0)
2801 window_prompting
|= XNegative
;
2804 if (!NILP (tem2
) && ! EQ (tem2
, Qunbound
))
2805 window_prompting
|= USPosition
;
2807 window_prompting
|= PPosition
;
2810 return window_prompting
;
2815 extern LRESULT CALLBACK
w32_wnd_proc ();
2818 w32_init_class (hinst
)
2823 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2824 wc
.lpfnWndProc
= (WNDPROC
) w32_wnd_proc
;
2826 wc
.cbWndExtra
= WND_EXTRA_BYTES
;
2827 wc
.hInstance
= hinst
;
2828 wc
.hIcon
= LoadIcon (hinst
, EMACS_CLASS
);
2829 wc
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
2830 wc
.hbrBackground
= NULL
; // GetStockObject (WHITE_BRUSH);
2831 wc
.lpszMenuName
= NULL
;
2832 wc
.lpszClassName
= EMACS_CLASS
;
2834 return (RegisterClass (&wc
));
2838 w32_createscrollbar (f
, bar
)
2840 struct scroll_bar
* bar
;
2842 return (CreateWindow ("SCROLLBAR", "", SBS_VERT
| WS_CHILD
| WS_VISIBLE
,
2843 /* Position and size of scroll bar. */
2844 XINT(bar
->left
), XINT(bar
->top
),
2845 XINT(bar
->width
), XINT(bar
->height
),
2846 FRAME_W32_WINDOW (f
),
2853 w32_createwindow (f
)
2859 rect
.left
= rect
.top
= 0;
2860 rect
.right
= PIXEL_WIDTH (f
);
2861 rect
.bottom
= PIXEL_HEIGHT (f
);
2863 AdjustWindowRect (&rect
, f
->output_data
.w32
->dwStyle
,
2864 FRAME_EXTERNAL_MENU_BAR (f
));
2866 /* Do first time app init */
2870 w32_init_class (hinst
);
2873 FRAME_W32_WINDOW (f
) = hwnd
2874 = CreateWindow (EMACS_CLASS
,
2876 f
->output_data
.w32
->dwStyle
| WS_CLIPCHILDREN
,
2877 f
->output_data
.w32
->left_pos
,
2878 f
->output_data
.w32
->top_pos
,
2879 rect
.right
- rect
.left
,
2880 rect
.bottom
- rect
.top
,
2888 SetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
2889 SetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
2890 SetWindowLong (hwnd
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
2891 SetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
2892 SetWindowLong (hwnd
, WND_BACKGROUND_INDEX
, f
->output_data
.w32
->background_pixel
);
2894 /* Do this to discard the default setting specified by our parent. */
2895 ShowWindow (hwnd
, SW_HIDE
);
2899 /* Convert between the modifier bits W32 uses and the modifier bits
2902 w32_get_modifiers ()
2904 return (((GetKeyState (VK_SHIFT
)&0x8000) ? shift_modifier
: 0) |
2905 ((GetKeyState (VK_CONTROL
)&0x8000) ? ctrl_modifier
: 0) |
2906 ((GetKeyState (VK_MENU
)&0x8000) ?
2907 ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
) : 0));
2911 my_post_msg (wmsg
, hwnd
, msg
, wParam
, lParam
)
2918 wmsg
->msg
.hwnd
= hwnd
;
2919 wmsg
->msg
.message
= msg
;
2920 wmsg
->msg
.wParam
= wParam
;
2921 wmsg
->msg
.lParam
= lParam
;
2922 wmsg
->msg
.time
= GetMessageTime ();
2927 /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2928 between left and right keys as advertised. We test for this
2929 support dynamically, and set a flag when the support is absent. If
2930 absent, we keep track of the left and right control and alt keys
2931 ourselves. This is particularly necessary on keyboards that rely
2932 upon the AltGr key, which is represented as having the left control
2933 and right alt keys pressed. For these keyboards, we need to know
2934 when the left alt key has been pressed in addition to the AltGr key
2935 so that we can properly support M-AltGr-key sequences (such as M-@
2936 on Swedish keyboards). */
2938 #define EMACS_LCONTROL 0
2939 #define EMACS_RCONTROL 1
2940 #define EMACS_LMENU 2
2941 #define EMACS_RMENU 3
2943 static int modifiers
[4];
2944 static int modifiers_recorded
;
2945 static int modifier_key_support_tested
;
2948 test_modifier_support (unsigned int wparam
)
2952 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
2954 if (wparam
== VK_CONTROL
)
2964 if (!(GetKeyState (l
) & 0x8000) && !(GetKeyState (r
) & 0x8000))
2965 modifiers_recorded
= 1;
2967 modifiers_recorded
= 0;
2968 modifier_key_support_tested
= 1;
2972 record_keydown (unsigned int wparam
, unsigned int lparam
)
2976 if (!modifier_key_support_tested
)
2977 test_modifier_support (wparam
);
2979 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2982 if (wparam
== VK_CONTROL
)
2983 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
2985 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
2991 record_keyup (unsigned int wparam
, unsigned int lparam
)
2995 if ((wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
) || !modifiers_recorded
)
2998 if (wparam
== VK_CONTROL
)
2999 i
= (lparam
& 0x1000000) ? EMACS_RCONTROL
: EMACS_LCONTROL
;
3001 i
= (lparam
& 0x1000000) ? EMACS_RMENU
: EMACS_LMENU
;
3006 /* Emacs can lose focus while a modifier key has been pressed. When
3007 it regains focus, be conservative and clear all modifiers since
3008 we cannot reconstruct the left and right modifier state. */
3014 if (!modifiers_recorded
)
3017 ctrl
= GetAsyncKeyState (VK_CONTROL
);
3018 alt
= GetAsyncKeyState (VK_MENU
);
3020 if (ctrl
== 0 || alt
== 0)
3021 /* Emacs doesn't have keyboard focus. Do nothing. */
3024 if (!(ctrl
& 0x08000))
3025 /* Clear any recorded control modifier state. */
3026 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3028 if (!(alt
& 0x08000))
3029 /* Clear any recorded alt modifier state. */
3030 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3032 /* Otherwise, leave the modifier state as it was when Emacs lost
3036 /* Synchronize modifier state with what is reported with the current
3037 keystroke. Even if we cannot distinguish between left and right
3038 modifier keys, we know that, if no modifiers are set, then neither
3039 the left or right modifier should be set. */
3043 if (!modifiers_recorded
)
3046 if (!(GetKeyState (VK_CONTROL
) & 0x8000))
3047 modifiers
[EMACS_RCONTROL
] = modifiers
[EMACS_LCONTROL
] = 0;
3049 if (!(GetKeyState (VK_MENU
) & 0x8000))
3050 modifiers
[EMACS_RMENU
] = modifiers
[EMACS_LMENU
] = 0;
3054 modifier_set (int vkey
)
3056 if (vkey
== VK_CAPITAL
)
3057 return (GetKeyState (vkey
) & 0x1);
3058 if (!modifiers_recorded
)
3059 return (GetKeyState (vkey
) & 0x8000);
3064 return modifiers
[EMACS_LCONTROL
];
3066 return modifiers
[EMACS_RCONTROL
];
3068 return modifiers
[EMACS_LMENU
];
3070 return modifiers
[EMACS_RMENU
];
3074 return (GetKeyState (vkey
) & 0x8000);
3077 /* We map the VK_* modifiers into console modifier constants
3078 so that we can use the same routines to handle both console
3079 and window input. */
3082 construct_modifiers (unsigned int wparam
, unsigned int lparam
)
3086 if (wparam
!= VK_CONTROL
&& wparam
!= VK_MENU
)
3087 mods
= GetLastError ();
3090 mods
|= (modifier_set (VK_SHIFT
)) ? SHIFT_PRESSED
: 0;
3091 mods
|= (modifier_set (VK_CAPITAL
)) ? CAPSLOCK_ON
: 0;
3092 mods
|= (modifier_set (VK_LCONTROL
)) ? LEFT_CTRL_PRESSED
: 0;
3093 mods
|= (modifier_set (VK_RCONTROL
)) ? RIGHT_CTRL_PRESSED
: 0;
3094 mods
|= (modifier_set (VK_LMENU
)) ? LEFT_ALT_PRESSED
: 0;
3095 mods
|= (modifier_set (VK_RMENU
)) ? RIGHT_ALT_PRESSED
: 0;
3101 map_keypad_keys (unsigned int wparam
, unsigned int lparam
)
3103 unsigned int extended
= (lparam
& 0x1000000L
);
3105 if (wparam
< VK_CLEAR
|| wparam
> VK_DELETE
)
3108 if (wparam
== VK_RETURN
)
3109 return (extended
? VK_NUMPAD_ENTER
: VK_RETURN
);
3111 if (wparam
>= VK_PRIOR
&& wparam
<= VK_DOWN
)
3112 return (!extended
? (VK_NUMPAD_PRIOR
+ (wparam
- VK_PRIOR
)) : wparam
);
3114 if (wparam
== VK_INSERT
|| wparam
== VK_DELETE
)
3115 return (!extended
? (VK_NUMPAD_INSERT
+ (wparam
- VK_INSERT
)) : wparam
);
3117 if (wparam
== VK_CLEAR
)
3118 return (!extended
? VK_NUMPAD_CLEAR
: wparam
);
3123 /* Main message dispatch loop. */
3126 w32_msg_pump (deferred_msg
* msg_buf
)
3130 msh_mousewheel
= RegisterWindowMessage (MSH_MOUSEWHEEL
);
3132 while (GetMessage (&msg
, NULL
, 0, 0))
3134 if (msg
.hwnd
== NULL
)
3136 switch (msg
.message
)
3138 case WM_EMACS_CREATEWINDOW
:
3139 w32_createwindow ((struct frame
*) msg
.wParam
);
3140 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3143 case WM_EMACS_SETLOCALE
:
3144 SetThreadLocale (msg
.wParam
);
3145 /* Reply is not expected. */
3148 /* No need to be so draconian! */
3150 DebPrint (("msg %x not expected by w32_msg_pump\n", msg
.message
));
3155 DispatchMessage (&msg
);
3158 /* Exit nested loop when our deferred message has completed. */
3159 if (msg_buf
->completed
)
3164 deferred_msg
* deferred_msg_head
;
3166 static deferred_msg
*
3167 find_deferred_msg (HWND hwnd
, UINT msg
)
3169 deferred_msg
* item
;
3171 /* Don't actually need synchronization for read access, since
3172 modification of single pointer is always atomic. */
3173 /* enter_crit (); */
3175 for (item
= deferred_msg_head
; item
!= NULL
; item
= item
->next
)
3176 if (item
->w32msg
.msg
.hwnd
== hwnd
3177 && item
->w32msg
.msg
.message
== msg
)
3180 /* leave_crit (); */
3186 send_deferred_msg (deferred_msg
* msg_buf
,
3192 /* Only input thread can send deferred messages. */
3193 if (GetCurrentThreadId () != dwWindowsThreadId
)
3196 /* It is an error to send a message that is already deferred. */
3197 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3200 /* Enforced synchronization is not needed because this is the only
3201 function that alters deferred_msg_head, and the following critical
3202 section is guaranteed to only be serially reentered (since only the
3203 input thread can call us). */
3205 /* enter_crit (); */
3207 msg_buf
->completed
= 0;
3208 msg_buf
->next
= deferred_msg_head
;
3209 deferred_msg_head
= msg_buf
;
3210 my_post_msg (&msg_buf
->w32msg
, hwnd
, msg
, wParam
, lParam
);
3212 /* leave_crit (); */
3214 /* Start a new nested message loop to process other messages until
3215 this one is completed. */
3216 w32_msg_pump (msg_buf
);
3218 deferred_msg_head
= msg_buf
->next
;
3220 return msg_buf
->result
;
3224 complete_deferred_msg (HWND hwnd
, UINT msg
, LRESULT result
)
3226 deferred_msg
* msg_buf
= find_deferred_msg (hwnd
, msg
);
3228 if (msg_buf
== NULL
)
3231 msg_buf
->result
= result
;
3232 msg_buf
->completed
= 1;
3234 /* Ensure input thread is woken so it notices the completion. */
3235 PostThreadMessage (dwWindowsThreadId
, WM_NULL
, 0, 0);
3244 deferred_msg dummy_buf
;
3246 /* Ensure our message queue is created */
3248 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3250 if (!PostThreadMessage (dwMainThreadId
, WM_EMACS_DONE
, 0, 0))
3253 memset (&dummy_buf
, 0, sizeof (dummy_buf
));
3254 dummy_buf
.w32msg
.msg
.hwnd
= NULL
;
3255 dummy_buf
.w32msg
.msg
.message
= WM_NULL
;
3257 /* This is the inital message loop which should only exit when the
3258 application quits. */
3259 w32_msg_pump (&dummy_buf
);
3264 /* Main window procedure */
3266 extern char *lispy_function_keys
[];
3269 w32_wnd_proc (hwnd
, msg
, wParam
, lParam
)
3276 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3278 int windows_translate
;
3280 /* Note that it is okay to call x_window_to_frame, even though we are
3281 not running in the main lisp thread, because frame deletion
3282 requires the lisp thread to synchronize with this thread. Thus, if
3283 a frame struct is returned, it can be used without concern that the
3284 lisp thread might make it disappear while we are using it.
3286 NB. Walking the frame list in this thread is safe (as long as
3287 writes of Lisp_Object slots are atomic, which they are on Windows).
3288 Although delete-frame can destructively modify the frame list while
3289 we are walking it, a garbage collection cannot occur until after
3290 delete-frame has synchronized with this thread.
3292 It is also safe to use functions that make GDI calls, such as
3293 w32_clear_rect, because these functions must obtain a DC handle
3294 from the frame struct using get_frame_dc which is thread-aware. */
3299 f
= x_window_to_frame (dpyinfo
, hwnd
);
3302 GetUpdateRect (hwnd
, &wmsg
.rect
, FALSE
);
3303 w32_clear_rect (f
, NULL
, &wmsg
.rect
);
3306 case WM_PALETTECHANGED
:
3307 /* ignore our own changes */
3308 if ((HWND
)wParam
!= hwnd
)
3310 f
= x_window_to_frame (dpyinfo
, hwnd
);
3312 /* get_frame_dc will realize our palette and force all
3313 frames to be redrawn if needed. */
3314 release_frame_dc (f
, get_frame_dc (f
));
3319 PAINTSTRUCT paintStruct
;
3322 BeginPaint (hwnd
, &paintStruct
);
3323 wmsg
.rect
= paintStruct
.rcPaint
;
3324 EndPaint (hwnd
, &paintStruct
);
3327 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3334 record_keyup (wParam
, lParam
);
3339 /* Synchronize modifiers with current keystroke. */
3342 record_keydown (wParam
, lParam
);
3344 wParam
= map_keypad_keys (wParam
, lParam
);
3346 windows_translate
= 0;
3351 /* More support for these keys will likely be necessary. */
3352 if (!NILP (Vw32_pass_optional_keys_to_system
))
3353 windows_translate
= 1;
3356 if (NILP (Vw32_pass_alt_to_system
))
3358 windows_translate
= 1;
3365 windows_translate
= 1;
3368 /* If not defined as a function key, change it to a WM_CHAR message. */
3369 if (lispy_function_keys
[wParam
] == 0)
3374 if (windows_translate
)
3376 MSG windows_msg
= { hwnd
, msg
, wParam
, lParam
, 0, {0,0} };
3378 windows_msg
.time
= GetMessageTime ();
3379 TranslateMessage (&windows_msg
);
3387 wmsg
.dwModifiers
= construct_modifiers (wParam
, lParam
);
3390 /* Detect quit_char and set quit-flag directly. Note that we
3391 still need to post a message to ensure the main thread will be
3392 woken up if blocked in sys_select(), but we do NOT want to post
3393 the quit_char message itself (because it will usually be as if
3394 the user had typed quit_char twice). Instead, we post a dummy
3395 message that has no particular effect. */
3398 if (isalpha (c
) && (wmsg
.dwModifiers
== LEFT_CTRL_PRESSED
3399 || wmsg
.dwModifiers
== RIGHT_CTRL_PRESSED
))
3400 c
= make_ctrl_char (c
) & 0377;
3405 /* The choice of message is somewhat arbitrary, as long as
3406 the main thread handler just ignores it. */
3412 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3416 /* Simulate middle mouse button events when left and right buttons
3417 are used together, but only if user has two button mouse. */
3418 case WM_LBUTTONDOWN
:
3419 case WM_RBUTTONDOWN
:
3420 if (XINT (Vw32_num_mouse_buttons
) == 3)
3421 goto handle_plain_button
;
3424 int this = (msg
== WM_LBUTTONDOWN
) ? LMOUSE
: RMOUSE
;
3425 int other
= (msg
== WM_LBUTTONDOWN
) ? RMOUSE
: LMOUSE
;
3427 if (button_state
& this)
3430 if (button_state
== 0)
3433 button_state
|= this;
3435 if (button_state
& other
)
3437 if (mouse_button_timer
)
3439 KillTimer (hwnd
, mouse_button_timer
);
3440 mouse_button_timer
= 0;
3442 /* Generate middle mouse event instead. */
3443 msg
= WM_MBUTTONDOWN
;
3444 button_state
|= MMOUSE
;
3446 else if (button_state
& MMOUSE
)
3448 /* Ignore button event if we've already generated a
3449 middle mouse down event. This happens if the
3450 user releases and press one of the two buttons
3451 after we've faked a middle mouse event. */
3456 /* Flush out saved message. */
3457 post_msg (&saved_mouse_button_msg
);
3459 wmsg
.dwModifiers
= w32_get_modifiers ();
3460 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3462 /* Clear message buffer. */
3463 saved_mouse_button_msg
.msg
.hwnd
= 0;
3467 /* Hold onto message for now. */
3468 mouse_button_timer
=
3469 SetTimer (hwnd
, MOUSE_BUTTON_ID
, XINT (Vw32_mouse_button_tolerance
), NULL
);
3470 saved_mouse_button_msg
.msg
.hwnd
= hwnd
;
3471 saved_mouse_button_msg
.msg
.message
= msg
;
3472 saved_mouse_button_msg
.msg
.wParam
= wParam
;
3473 saved_mouse_button_msg
.msg
.lParam
= lParam
;
3474 saved_mouse_button_msg
.msg
.time
= GetMessageTime ();
3475 saved_mouse_button_msg
.dwModifiers
= w32_get_modifiers ();
3482 if (XINT (Vw32_num_mouse_buttons
) == 3)
3483 goto handle_plain_button
;
3486 int this = (msg
== WM_LBUTTONUP
) ? LMOUSE
: RMOUSE
;
3487 int other
= (msg
== WM_LBUTTONUP
) ? RMOUSE
: LMOUSE
;
3489 if ((button_state
& this) == 0)
3492 button_state
&= ~this;
3494 if (button_state
& MMOUSE
)
3496 /* Only generate event when second button is released. */
3497 if ((button_state
& other
) == 0)
3500 button_state
&= ~MMOUSE
;
3502 if (button_state
) abort ();
3509 /* Flush out saved message if necessary. */
3510 if (saved_mouse_button_msg
.msg
.hwnd
)
3512 post_msg (&saved_mouse_button_msg
);
3515 wmsg
.dwModifiers
= w32_get_modifiers ();
3516 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3518 /* Always clear message buffer and cancel timer. */
3519 saved_mouse_button_msg
.msg
.hwnd
= 0;
3520 KillTimer (hwnd
, mouse_button_timer
);
3521 mouse_button_timer
= 0;
3523 if (button_state
== 0)
3528 case WM_MBUTTONDOWN
:
3530 handle_plain_button
:
3535 if (parse_button (msg
, &button
, &up
))
3537 if (up
) ReleaseCapture ();
3538 else SetCapture (hwnd
);
3539 button
= (button
== 0) ? LMOUSE
:
3540 ((button
== 1) ? MMOUSE
: RMOUSE
);
3542 button_state
&= ~button
;
3544 button_state
|= button
;
3548 wmsg
.dwModifiers
= w32_get_modifiers ();
3549 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3554 if (XINT (Vw32_mouse_move_interval
) <= 0
3555 || (msg
== WM_MOUSEMOVE
&& button_state
== 0))
3557 wmsg
.dwModifiers
= w32_get_modifiers ();
3558 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3562 /* Hang onto mouse move and scroll messages for a bit, to avoid
3563 sending such events to Emacs faster than it can process them.
3564 If we get more events before the timer from the first message
3565 expires, we just replace the first message. */
3567 if (saved_mouse_move_msg
.msg
.hwnd
== 0)
3569 SetTimer (hwnd
, MOUSE_MOVE_ID
, XINT (Vw32_mouse_move_interval
), NULL
);
3571 /* Hold onto message for now. */
3572 saved_mouse_move_msg
.msg
.hwnd
= hwnd
;
3573 saved_mouse_move_msg
.msg
.message
= msg
;
3574 saved_mouse_move_msg
.msg
.wParam
= wParam
;
3575 saved_mouse_move_msg
.msg
.lParam
= lParam
;
3576 saved_mouse_move_msg
.msg
.time
= GetMessageTime ();
3577 saved_mouse_move_msg
.dwModifiers
= w32_get_modifiers ();
3582 wmsg
.dwModifiers
= w32_get_modifiers ();
3583 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3587 /* Flush out saved messages if necessary. */
3588 if (wParam
== mouse_button_timer
)
3590 if (saved_mouse_button_msg
.msg
.hwnd
)
3592 post_msg (&saved_mouse_button_msg
);
3593 saved_mouse_button_msg
.msg
.hwnd
= 0;
3595 KillTimer (hwnd
, mouse_button_timer
);
3596 mouse_button_timer
= 0;
3598 else if (wParam
== mouse_move_timer
)
3600 if (saved_mouse_move_msg
.msg
.hwnd
)
3602 post_msg (&saved_mouse_move_msg
);
3603 saved_mouse_move_msg
.msg
.hwnd
= 0;
3605 KillTimer (hwnd
, mouse_move_timer
);
3606 mouse_move_timer
= 0;
3611 /* Windows doesn't send us focus messages when putting up and
3612 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3613 The only indication we get that something happened is receiving
3614 this message afterwards. So this is a good time to reset our
3615 keyboard modifiers' state. */
3620 /* We must ensure menu bar is fully constructed and up to date
3621 before allowing user interaction with it. To achieve this
3622 we send this message to the lisp thread and wait for a
3623 reply (whose value is not actually needed) to indicate that
3624 the menu bar is now ready for use, so we can now return.
3626 To remain responsive in the meantime, we enter a nested message
3627 loop that can process all other messages.
3629 However, we skip all this if the message results from calling
3630 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3631 thread a message because it is blocked on us at this point. We
3632 set menubar_active before calling TrackPopupMenu to indicate
3633 this (there is no possibility of confusion with real menubar
3636 f
= x_window_to_frame (dpyinfo
, hwnd
);
3638 && (f
->output_data
.w32
->menubar_active
3639 /* We can receive this message even in the absence of a
3640 menubar (ie. when the system menu is activated) - in this
3641 case we do NOT want to forward the message, otherwise it
3642 will cause the menubar to suddenly appear when the user
3643 had requested it to be turned off! */
3644 || f
->output_data
.w32
->menubar_widget
== NULL
))
3648 deferred_msg msg_buf
;
3650 /* Detect if message has already been deferred; in this case
3651 we cannot return any sensible value to ignore this. */
3652 if (find_deferred_msg (hwnd
, msg
) != NULL
)
3655 return send_deferred_msg (&msg_buf
, hwnd
, msg
, wParam
, lParam
);
3658 case WM_EXITMENULOOP
:
3659 f
= x_window_to_frame (dpyinfo
, hwnd
);
3661 /* Indicate that menubar can be modified again. */
3663 f
->output_data
.w32
->menubar_active
= 0;
3666 case WM_MEASUREITEM
:
3667 f
= x_window_to_frame (dpyinfo
, hwnd
);
3670 MEASUREITEMSTRUCT
* pMis
= (MEASUREITEMSTRUCT
*) lParam
;
3672 if (pMis
->CtlType
== ODT_MENU
)
3674 /* Work out dimensions for popup menu titles. */
3675 char * title
= (char *) pMis
->itemData
;
3676 HDC hdc
= GetDC (hwnd
);
3677 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3678 LOGFONT menu_logfont
;
3682 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3683 menu_logfont
.lfWeight
= FW_BOLD
;
3684 menu_font
= CreateFontIndirect (&menu_logfont
);
3685 old_font
= SelectObject (hdc
, menu_font
);
3687 GetTextExtentPoint32 (hdc
, title
, strlen (title
), &size
);
3688 pMis
->itemWidth
= size
.cx
;
3689 pMis
->itemHeight
= GetSystemMetrics (SM_CYMENUSIZE
);
3690 if (pMis
->itemHeight
< size
.cy
)
3691 pMis
->itemHeight
= size
.cy
;
3693 SelectObject (hdc
, old_font
);
3694 DeleteObject (menu_font
);
3695 ReleaseDC (hwnd
, hdc
);
3702 f
= x_window_to_frame (dpyinfo
, hwnd
);
3705 DRAWITEMSTRUCT
* pDis
= (DRAWITEMSTRUCT
*) lParam
;
3707 if (pDis
->CtlType
== ODT_MENU
)
3709 /* Draw popup menu title. */
3710 char * title
= (char *) pDis
->itemData
;
3711 HDC hdc
= pDis
->hDC
;
3712 HFONT menu_font
= GetCurrentObject (hdc
, OBJ_FONT
);
3713 LOGFONT menu_logfont
;
3716 GetObject (menu_font
, sizeof (menu_logfont
), &menu_logfont
);
3717 menu_logfont
.lfWeight
= FW_BOLD
;
3718 menu_font
= CreateFontIndirect (&menu_logfont
);
3719 old_font
= SelectObject (hdc
, menu_font
);
3721 /* Always draw title as if not selected. */
3723 pDis
->rcItem
.left
+ GetSystemMetrics (SM_CXMENUCHECK
),
3725 ETO_OPAQUE
, &pDis
->rcItem
,
3726 title
, strlen (title
), NULL
);
3728 SelectObject (hdc
, old_font
);
3729 DeleteObject (menu_font
);
3736 /* Still not right - can't distinguish between clicks in the
3737 client area of the frame from clicks forwarded from the scroll
3738 bars - may have to hook WM_NCHITTEST to remember the mouse
3739 position and then check if it is in the client area ourselves. */
3740 case WM_MOUSEACTIVATE
:
3741 /* Discard the mouse click that activates a frame, allowing the
3742 user to click anywhere without changing point (or worse!).
3743 Don't eat mouse clicks on scrollbars though!! */
3744 if (LOWORD (lParam
) == HTCLIENT
)
3745 return MA_ACTIVATEANDEAT
;
3750 case WM_ACTIVATEAPP
:
3751 case WM_WINDOWPOSCHANGED
:
3753 /* Inform lisp thread that a frame might have just been obscured
3754 or exposed, so should recheck visibility of all frames. */
3755 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3764 wmsg
.dwModifiers
= w32_get_modifiers ();
3765 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3769 wmsg
.dwModifiers
= w32_get_modifiers ();
3770 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3773 case WM_WINDOWPOSCHANGING
:
3776 LPWINDOWPOS lppos
= (WINDOWPOS
*) lParam
;
3778 wp
.length
= sizeof (WINDOWPLACEMENT
);
3779 GetWindowPlacement (hwnd
, &wp
);
3781 if (wp
.showCmd
!= SW_SHOWMINIMIZED
&& (lppos
->flags
& SWP_NOSIZE
) == 0)
3788 DWORD internal_border
;
3789 DWORD scrollbar_extra
;
3792 wp
.length
= sizeof(wp
);
3793 GetWindowRect (hwnd
, &wr
);
3797 font_width
= GetWindowLong (hwnd
, WND_FONTWIDTH_INDEX
);
3798 line_height
= GetWindowLong (hwnd
, WND_LINEHEIGHT_INDEX
);
3799 internal_border
= GetWindowLong (hwnd
, WND_BORDER_INDEX
);
3800 scrollbar_extra
= GetWindowLong (hwnd
, WND_SCROLLBAR_INDEX
);
3804 memset (&rect
, 0, sizeof (rect
));
3805 AdjustWindowRect (&rect
, GetWindowLong (hwnd
, GWL_STYLE
),
3806 GetMenu (hwnd
) != NULL
);
3808 /* Force width and height of client area to be exact
3809 multiples of the character cell dimensions. */
3810 wdiff
= (lppos
->cx
- (rect
.right
- rect
.left
)
3811 - 2 * internal_border
- scrollbar_extra
)
3813 hdiff
= (lppos
->cy
- (rect
.bottom
- rect
.top
)
3814 - 2 * internal_border
)
3819 /* For right/bottom sizing we can just fix the sizes.
3820 However for top/left sizing we will need to fix the X
3821 and Y positions as well. */
3826 if (wp
.showCmd
!= SW_SHOWMAXIMIZED
3827 && (lppos
->flags
& SWP_NOMOVE
) == 0)
3829 if (lppos
->x
!= wr
.left
|| lppos
->y
!= wr
.top
)
3836 lppos
->flags
|= SWP_NOMOVE
;
3847 case WM_EMACS_CREATESCROLLBAR
:
3848 return (LRESULT
) w32_createscrollbar ((struct frame
*) wParam
,
3849 (struct scroll_bar
*) lParam
);
3851 case WM_EMACS_SHOWWINDOW
:
3852 return ShowWindow ((HWND
) wParam
, (WPARAM
) lParam
);
3854 case WM_EMACS_SETFOREGROUND
:
3855 return SetForegroundWindow ((HWND
) wParam
);
3857 case WM_EMACS_SETWINDOWPOS
:
3859 WINDOWPOS
* pos
= (WINDOWPOS
*) wParam
;
3860 return SetWindowPos (hwnd
, pos
->hwndInsertAfter
,
3861 pos
->x
, pos
->y
, pos
->cx
, pos
->cy
, pos
->flags
);
3864 case WM_EMACS_DESTROYWINDOW
:
3865 return DestroyWindow ((HWND
) wParam
);
3867 case WM_EMACS_TRACKPOPUPMENU
:
3872 pos
= (POINT
*)lParam
;
3873 flags
= TPM_CENTERALIGN
;
3874 if (button_state
& LMOUSE
)
3875 flags
|= TPM_LEFTBUTTON
;
3876 else if (button_state
& RMOUSE
)
3877 flags
|= TPM_RIGHTBUTTON
;
3879 /* Remember we did a SetCapture on the initial mouse down event,
3880 so for safety, we make sure the capture is cancelled now. */
3883 /* Use menubar_active to indicate that WM_INITMENU is from
3884 TrackPopupMenu below, and should be ignored. */
3885 f
= x_window_to_frame (dpyinfo
, hwnd
);
3887 f
->output_data
.w32
->menubar_active
= 1;
3889 if (TrackPopupMenu ((HMENU
)wParam
, flags
, pos
->x
, pos
->y
,
3893 /* Eat any mouse messages during popupmenu */
3894 while (PeekMessage (&amsg
, hwnd
, WM_MOUSEFIRST
, WM_MOUSELAST
,
3896 /* Get the menu selection, if any */
3897 if (PeekMessage (&amsg
, hwnd
, WM_COMMAND
, WM_COMMAND
, PM_REMOVE
))
3899 retval
= LOWORD (amsg
.wParam
);
3916 /* Check for messages registered at runtime. */
3917 if (msg
== msh_mousewheel
)
3919 wmsg
.dwModifiers
= w32_get_modifiers ();
3920 my_post_msg (&wmsg
, hwnd
, msg
, wParam
, lParam
);
3925 return DefWindowProc (hwnd
, msg
, wParam
, lParam
);
3929 /* The most common default return code for handled messages is 0. */
3934 my_create_window (f
)
3939 if (!PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATEWINDOW
, (WPARAM
)f
, 0))
3941 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3944 /* Create and set up the w32 window for frame F. */
3947 w32_window (f
, window_prompting
, minibuffer_only
)
3949 long window_prompting
;
3950 int minibuffer_only
;
3954 /* Use the resource name as the top-level window name
3955 for looking up resources. Make a non-Lisp copy
3956 for the window manager, so GC relocation won't bother it.
3958 Elsewhere we specify the window name for the window manager. */
3961 char *str
= (char *) XSTRING (Vx_resource_name
)->data
;
3962 f
->namebuf
= (char *) xmalloc (strlen (str
) + 1);
3963 strcpy (f
->namebuf
, str
);
3966 my_create_window (f
);
3968 validate_x_resource_name ();
3970 /* x_set_name normally ignores requests to set the name if the
3971 requested name is the same as the current name. This is the one
3972 place where that assumption isn't correct; f->name is set, but
3973 the server hasn't been told. */
3976 int explicit = f
->explicit_name
;
3978 f
->explicit_name
= 0;
3981 x_set_name (f
, name
, explicit);
3986 if (!minibuffer_only
&& FRAME_EXTERNAL_MENU_BAR (f
))
3987 initialize_frame_menubar (f
);
3989 if (FRAME_W32_WINDOW (f
) == 0)
3990 error ("Unable to create window");
3993 /* Handle the icon stuff for this window. Perhaps later we might
3994 want an x_set_icon_position which can be called interactively as
4002 Lisp_Object icon_x
, icon_y
;
4004 /* Set the position of the icon. Note that Windows 95 groups all
4005 icons in the tray. */
4006 icon_x
= x_get_arg (parms
, Qicon_left
, 0, 0, number
);
4007 icon_y
= x_get_arg (parms
, Qicon_top
, 0, 0, number
);
4008 if (!EQ (icon_x
, Qunbound
) && !EQ (icon_y
, Qunbound
))
4010 CHECK_NUMBER (icon_x
, 0);
4011 CHECK_NUMBER (icon_y
, 0);
4013 else if (!EQ (icon_x
, Qunbound
) || !EQ (icon_y
, Qunbound
))
4014 error ("Both left and top icon corners of icon must be specified");
4018 if (! EQ (icon_x
, Qunbound
))
4019 x_wm_set_icon_position (f
, XINT (icon_x
), XINT (icon_y
));
4022 /* Start up iconic or window? */
4023 x_wm_set_window_state
4024 (f
, (EQ (x_get_arg (parms
, Qvisibility
, 0, 0, symbol
), Qicon
)
4028 x_text_icon (f
, (char *) XSTRING ((!NILP (f
->icon_name
)
4036 DEFUN ("x-create-frame", Fx_create_frame
, Sx_create_frame
,
4038 "Make a new window, which is called a \"frame\" in Emacs terms.\n\
4039 Returns an Emacs frame object.\n\
4040 ALIST is an alist of frame parameters.\n\
4041 If the parameters specify that the frame should not have a minibuffer,\n\
4042 and do not specify a specific minibuffer window to use,\n\
4043 then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
4044 be shared by the new frame.\n\
4046 This function is an internal primitive--use `make-frame' instead.")
4051 Lisp_Object frame
, tem
;
4053 int minibuffer_only
= 0;
4054 long window_prompting
= 0;
4056 int count
= specpdl_ptr
- specpdl
;
4057 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
4058 Lisp_Object display
;
4059 struct w32_display_info
*dpyinfo
;
4063 /* Use this general default value to start with
4064 until we know if this frame has a specified name. */
4065 Vx_resource_name
= Vinvocation_name
;
4067 display
= x_get_arg (parms
, Qdisplay
, 0, 0, string
);
4068 if (EQ (display
, Qunbound
))
4070 dpyinfo
= check_x_display_info (display
);
4072 kb
= dpyinfo
->kboard
;
4074 kb
= &the_only_kboard
;
4077 name
= x_get_arg (parms
, Qname
, "name", "Name", string
);
4079 && ! EQ (name
, Qunbound
)
4081 error ("Invalid frame name--not a string or nil");
4084 Vx_resource_name
= name
;
4086 /* See if parent window is specified. */
4087 parent
= x_get_arg (parms
, Qparent_id
, NULL
, NULL
, number
);
4088 if (EQ (parent
, Qunbound
))
4090 if (! NILP (parent
))
4091 CHECK_NUMBER (parent
, 0);
4093 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
4094 /* No need to protect DISPLAY because that's not used after passing
4095 it to make_frame_without_minibuffer. */
4097 GCPRO4 (parms
, parent
, name
, frame
);
4098 tem
= x_get_arg (parms
, Qminibuffer
, 0, 0, symbol
);
4099 if (EQ (tem
, Qnone
) || NILP (tem
))
4100 f
= make_frame_without_minibuffer (Qnil
, kb
, display
);
4101 else if (EQ (tem
, Qonly
))
4103 f
= make_minibuffer_frame ();
4104 minibuffer_only
= 1;
4106 else if (WINDOWP (tem
))
4107 f
= make_frame_without_minibuffer (tem
, kb
, display
);
4111 XSETFRAME (frame
, f
);
4113 /* Note that Windows does support scroll bars. */
4114 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
4115 /* By default, make scrollbars the system standard width. */
4116 f
->scroll_bar_pixel_width
= GetSystemMetrics (SM_CXVSCROLL
);
4118 f
->output_method
= output_w32
;
4119 f
->output_data
.w32
= (struct w32_output
*) xmalloc (sizeof (struct w32_output
));
4120 bzero (f
->output_data
.w32
, sizeof (struct w32_output
));
4123 = x_get_arg (parms
, Qicon_name
, "iconName", "Title", string
);
4124 if (! STRINGP (f
->icon_name
))
4125 f
->icon_name
= Qnil
;
4127 /* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4129 FRAME_KBOARD (f
) = kb
;
4132 /* Specify the parent under which to make this window. */
4136 f
->output_data
.w32
->parent_desc
= (Window
) parent
;
4137 f
->output_data
.w32
->explicit_parent
= 1;
4141 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4142 f
->output_data
.w32
->explicit_parent
= 0;
4145 /* Note that the frame has no physical cursor right now. */
4146 f
->phys_cursor_x
= -1;
4148 /* Set the name; the functions to which we pass f expect the name to
4150 if (EQ (name
, Qunbound
) || NILP (name
))
4152 f
->name
= build_string (dpyinfo
->w32_id_name
);
4153 f
->explicit_name
= 0;
4158 f
->explicit_name
= 1;
4159 /* use the frame's title when getting resources for this frame. */
4160 specbind (Qx_resource_name
, name
);
4163 /* Extract the window parameters from the supplied values
4164 that are needed to determine window geometry. */
4168 font
= x_get_arg (parms
, Qfont
, "font", "Font", string
);
4170 /* First, try whatever font the caller has specified. */
4172 font
= x_new_font (f
, XSTRING (font
)->data
);
4173 /* Try out a font which we hope has bold and italic variations. */
4174 if (!STRINGP (font
))
4175 font
= x_new_font (f
, "-*-Courier New-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
4176 if (! STRINGP (font
))
4177 font
= x_new_font (f
, "-*-Courier-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
4178 /* If those didn't work, look for something which will at least work. */
4179 if (! STRINGP (font
))
4180 font
= x_new_font (f
, "-*-Fixedsys-normal-r-*-*-13-97-*-*-c-*-*-ansi-");
4182 if (! STRINGP (font
))
4183 font
= build_string ("Fixedsys");
4185 x_default_parameter (f
, parms
, Qfont
, font
,
4186 "font", "Font", string
);
4189 x_default_parameter (f
, parms
, Qborder_width
, make_number (2),
4190 "borderwidth", "BorderWidth", number
);
4191 /* This defaults to 2 in order to match xterm. We recognize either
4192 internalBorderWidth or internalBorder (which is what xterm calls
4194 if (NILP (Fassq (Qinternal_border_width
, parms
)))
4198 value
= x_get_arg (parms
, Qinternal_border_width
,
4199 "internalBorder", "BorderWidth", number
);
4200 if (! EQ (value
, Qunbound
))
4201 parms
= Fcons (Fcons (Qinternal_border_width
, value
),
4204 /* Default internalBorderWidth to 0 on Windows to match other programs. */
4205 x_default_parameter (f
, parms
, Qinternal_border_width
, make_number (0),
4206 "internalBorderWidth", "BorderWidth", number
);
4207 x_default_parameter (f
, parms
, Qvertical_scroll_bars
, Qt
,
4208 "verticalScrollBars", "ScrollBars", boolean
);
4210 /* Also do the stuff which must be set before the window exists. */
4211 x_default_parameter (f
, parms
, Qforeground_color
, build_string ("black"),
4212 "foreground", "Foreground", string
);
4213 x_default_parameter (f
, parms
, Qbackground_color
, build_string ("white"),
4214 "background", "Background", string
);
4215 x_default_parameter (f
, parms
, Qmouse_color
, build_string ("black"),
4216 "pointerColor", "Foreground", string
);
4217 x_default_parameter (f
, parms
, Qcursor_color
, build_string ("black"),
4218 "cursorColor", "Foreground", string
);
4219 x_default_parameter (f
, parms
, Qborder_color
, build_string ("black"),
4220 "borderColor", "BorderColor", string
);
4222 x_default_parameter (f
, parms
, Qmenu_bar_lines
, make_number (1),
4223 "menuBar", "MenuBar", number
);
4224 x_default_parameter (f
, parms
, Qscroll_bar_width
, Qnil
,
4225 "scrollBarWidth", "ScrollBarWidth", number
);
4226 x_default_parameter (f
, parms
, Qbuffer_predicate
, Qnil
,
4227 "bufferPredicate", "BufferPredicate", symbol
);
4228 x_default_parameter (f
, parms
, Qtitle
, Qnil
,
4229 "title", "Title", string
);
4231 f
->output_data
.w32
->dwStyle
= WS_OVERLAPPEDWINDOW
;
4232 f
->output_data
.w32
->parent_desc
= FRAME_W32_DISPLAY_INFO (f
)->root_window
;
4233 window_prompting
= x_figure_window_size (f
, parms
);
4235 if (window_prompting
& XNegative
)
4237 if (window_prompting
& YNegative
)
4238 f
->output_data
.w32
->win_gravity
= SouthEastGravity
;
4240 f
->output_data
.w32
->win_gravity
= NorthEastGravity
;
4244 if (window_prompting
& YNegative
)
4245 f
->output_data
.w32
->win_gravity
= SouthWestGravity
;
4247 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4250 f
->output_data
.w32
->size_hint_flags
= window_prompting
;
4252 w32_window (f
, window_prompting
, minibuffer_only
);
4254 init_frame_faces (f
);
4256 /* We need to do this after creating the window, so that the
4257 icon-creation functions can say whose icon they're describing. */
4258 x_default_parameter (f
, parms
, Qicon_type
, Qnil
,
4259 "bitmapIcon", "BitmapIcon", symbol
);
4261 x_default_parameter (f
, parms
, Qauto_raise
, Qnil
,
4262 "autoRaise", "AutoRaiseLower", boolean
);
4263 x_default_parameter (f
, parms
, Qauto_lower
, Qnil
,
4264 "autoLower", "AutoRaiseLower", boolean
);
4265 x_default_parameter (f
, parms
, Qcursor_type
, Qbox
,
4266 "cursorType", "CursorType", symbol
);
4268 /* Dimensions, especially f->height, must be done via change_frame_size.
4269 Change will not be effected unless different from the current
4274 SET_FRAME_WIDTH (f
, 0);
4275 change_frame_size (f
, height
, width
, 1, 0);
4277 /* Tell the server what size and position, etc, we want,
4278 and how badly we want them. */
4280 x_wm_set_size_hint (f
, window_prompting
, 0);
4283 tem
= x_get_arg (parms
, Qunsplittable
, 0, 0, boolean
);
4284 f
->no_split
= minibuffer_only
|| EQ (tem
, Qt
);
4288 /* It is now ok to make the frame official
4289 even if we get an error below.
4290 And the frame needs to be on Vframe_list
4291 or making it visible won't work. */
4292 Vframe_list
= Fcons (frame
, Vframe_list
);
4294 /* Now that the frame is official, it counts as a reference to
4296 FRAME_W32_DISPLAY_INFO (f
)->reference_count
++;
4298 /* Make the window appear on the frame and enable display,
4299 unless the caller says not to. However, with explicit parent,
4300 Emacs cannot control visibility, so don't try. */
4301 if (! f
->output_data
.w32
->explicit_parent
)
4303 Lisp_Object visibility
;
4305 visibility
= x_get_arg (parms
, Qvisibility
, 0, 0, symbol
);
4306 if (EQ (visibility
, Qunbound
))
4309 if (EQ (visibility
, Qicon
))
4310 x_iconify_frame (f
);
4311 else if (! NILP (visibility
))
4312 x_make_frame_visible (f
);
4314 /* Must have been Qnil. */
4318 return unbind_to (count
, frame
);
4321 /* FRAME is used only to get a handle on the X display. We don't pass the
4322 display info directly because we're called from frame.c, which doesn't
4323 know about that structure. */
4325 x_get_focus_frame (frame
)
4326 struct frame
*frame
;
4328 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (frame
);
4330 if (! dpyinfo
->w32_focus_frame
)
4333 XSETFRAME (xfocus
, dpyinfo
->w32_focus_frame
);
4337 DEFUN ("w32-focus-frame", Fw32_focus_frame
, Sw32_focus_frame
, 1, 1, 0,
4338 "Give FRAME input focus, raising to foreground if necessary.")
4342 x_focus_on_frame (check_x_frame (frame
));
4348 w32_load_font (dpyinfo
,name
)
4349 struct w32_display_info
*dpyinfo
;
4352 XFontStruct
* font
= NULL
;
4358 if (!name
|| !x_to_w32_font (name
, &lf
))
4361 font
= (XFontStruct
*) xmalloc (sizeof (XFontStruct
));
4363 if (!font
) return (NULL
);
4367 font
->hfont
= CreateFontIndirect (&lf
);
4370 if (font
->hfont
== NULL
)
4379 hdc
= GetDC (dpyinfo
->root_window
);
4380 oldobj
= SelectObject (hdc
, font
->hfont
);
4381 ok
= GetTextMetrics (hdc
, &font
->tm
);
4382 SelectObject (hdc
, oldobj
);
4383 ReleaseDC (dpyinfo
->root_window
, hdc
);
4388 if (ok
) return (font
);
4390 w32_unload_font (dpyinfo
, font
);
4395 w32_unload_font (dpyinfo
, font
)
4396 struct w32_display_info
*dpyinfo
;
4401 if (font
->hfont
) DeleteObject(font
->hfont
);
4406 /* The font conversion stuff between x and w32 */
4408 /* X font string is as follows (from faces.el)
4412 * (weight "\\(bold\\|demibold\\|medium\\)") ; 1
4413 * (weight\? "\\([^-]*\\)") ; 1
4414 * (slant "\\([ior]\\)") ; 2
4415 * (slant\? "\\([^-]?\\)") ; 2
4416 * (swidth "\\([^-]*\\)") ; 3
4417 * (adstyle "[^-]*") ; 4
4418 * (pixelsize "[0-9]+")
4419 * (pointsize "[0-9][0-9]+")
4420 * (resx "[0-9][0-9]+")
4421 * (resy "[0-9][0-9]+")
4422 * (spacing "[cmp?*]")
4423 * (avgwidth "[0-9]+")
4424 * (registry "[^-]+")
4425 * (encoding "[^-]+")
4427 * (setq x-font-regexp
4428 * (concat "\\`\\*?[-?*]"
4429 * foundry - family - weight\? - slant\? - swidth - adstyle -
4430 * pixelsize - pointsize - resx - resy - spacing - registry -
4431 * encoding "[-?*]\\*?\\'"
4433 * (setq x-font-regexp-head
4434 * (concat "\\`[-?*]" foundry - family - weight\? - slant\?
4435 * "\\([-*?]\\|\\'\\)"))
4436 * (setq x-font-regexp-slant (concat - slant -))
4437 * (setq x-font-regexp-weight (concat - weight -))
4441 #define FONT_START "[-?]"
4442 #define FONT_FOUNDRY "[^-]+"
4443 #define FONT_FAMILY "\\([^-]+\\)" /* 1 */
4444 #define FONT_WEIGHT "\\(bold\\|demibold\\|medium\\)" /* 2 */
4445 #define FONT_WEIGHT_Q "\\([^-]*\\)" /* 2 */
4446 #define FONT_SLANT "\\([ior]\\)" /* 3 */
4447 #define FONT_SLANT_Q "\\([^-]?\\)" /* 3 */
4448 #define FONT_SWIDTH "\\([^-]*\\)" /* 4 */
4449 #define FONT_ADSTYLE "[^-]*"
4450 #define FONT_PIXELSIZE "[^-]*"
4451 #define FONT_POINTSIZE "\\([0-9][0-9]+\\|\\*\\)" /* 5 */
4452 #define FONT_RESX "[0-9][0-9]+"
4453 #define FONT_RESY "[0-9][0-9]+"
4454 #define FONT_SPACING "[cmp?*]"
4455 #define FONT_AVGWIDTH "[0-9]+"
4456 #define FONT_REGISTRY "[^-]+"
4457 #define FONT_ENCODING "[^-]+"
4459 #define FONT_REGEXP ("\\`\\*?[-?*]" \
4466 FONT_PIXELSIZE "-" \
4467 FONT_POINTSIZE "-" \
4470 #define FONT_REGEXP_HEAD ("\\`[-?*]" \
4475 "\\([-*?]\\|\\'\\)")
4477 #define FONT_REGEXP_SLANT "-" FONT_SLANT "-"
4478 #define FONT_REGEXP_WEIGHT "-" FONT_WEIGHT "-"
4481 x_to_w32_weight (lpw
)
4484 if (!lpw
) return (FW_DONTCARE
);
4486 if (stricmp (lpw
,"heavy") == 0) return FW_HEAVY
;
4487 else if (stricmp (lpw
,"extrabold") == 0) return FW_EXTRABOLD
;
4488 else if (stricmp (lpw
,"bold") == 0) return FW_BOLD
;
4489 else if (stricmp (lpw
,"demibold") == 0) return FW_SEMIBOLD
;
4490 else if (stricmp (lpw
,"semibold") == 0) return FW_SEMIBOLD
;
4491 else if (stricmp (lpw
,"medium") == 0) return FW_MEDIUM
;
4492 else if (stricmp (lpw
,"normal") == 0) return FW_NORMAL
;
4493 else if (stricmp (lpw
,"light") == 0) return FW_LIGHT
;
4494 else if (stricmp (lpw
,"extralight") == 0) return FW_EXTRALIGHT
;
4495 else if (stricmp (lpw
,"thin") == 0) return FW_THIN
;
4502 w32_to_x_weight (fnweight
)
4505 if (fnweight
>= FW_HEAVY
) return "heavy";
4506 if (fnweight
>= FW_EXTRABOLD
) return "extrabold";
4507 if (fnweight
>= FW_BOLD
) return "bold";
4508 if (fnweight
>= FW_SEMIBOLD
) return "semibold";
4509 if (fnweight
>= FW_MEDIUM
) return "medium";
4510 if (fnweight
>= FW_NORMAL
) return "normal";
4511 if (fnweight
>= FW_LIGHT
) return "light";
4512 if (fnweight
>= FW_EXTRALIGHT
) return "extralight";
4513 if (fnweight
>= FW_THIN
) return "thin";
4519 x_to_w32_charset (lpcs
)
4522 if (!lpcs
) return (0);
4524 if (stricmp (lpcs
,"ansi") == 0) return ANSI_CHARSET
;
4525 else if (stricmp (lpcs
,"iso8859-1") == 0) return ANSI_CHARSET
;
4526 else if (stricmp (lpcs
,"iso8859") == 0) return ANSI_CHARSET
;
4527 else if (stricmp (lpcs
,"oem") == 0) return OEM_CHARSET
;
4528 #ifdef UNICODE_CHARSET
4529 else if (stricmp (lpcs
,"unicode") == 0) return UNICODE_CHARSET
;
4530 else if (stricmp (lpcs
,"iso10646") == 0) return UNICODE_CHARSET
;
4532 else if (lpcs
[0] == '#') return atoi (lpcs
+ 1);
4534 return DEFAULT_CHARSET
;
4538 w32_to_x_charset (fncharset
)
4541 static char buf
[16];
4545 case ANSI_CHARSET
: return "ansi";
4546 case OEM_CHARSET
: return "oem";
4547 case SYMBOL_CHARSET
: return "symbol";
4548 #ifdef UNICODE_CHARSET
4549 case UNICODE_CHARSET
: return "unicode";
4552 /* Encode numerical value of unknown charset. */
4553 sprintf (buf
, "#%u", fncharset
);
4558 w32_to_x_font (lplogfont
, lpxstr
, len
)
4559 LOGFONT
* lplogfont
;
4563 char height_pixels
[8];
4565 char width_pixels
[8];
4567 if (!lpxstr
) abort ();
4572 if (lplogfont
->lfHeight
)
4574 sprintf (height_pixels
, "%u", abs (lplogfont
->lfHeight
));
4575 sprintf (height_dpi
, "%u",
4576 (abs (lplogfont
->lfHeight
) * 720) / one_w32_display_info
.height_in
);
4580 strcpy (height_pixels
, "*");
4581 strcpy (height_dpi
, "*");
4583 if (lplogfont
->lfWidth
)
4584 sprintf (width_pixels
, "%u", lplogfont
->lfWidth
* 10);
4586 strcpy (width_pixels
, "*");
4588 _snprintf (lpxstr
, len
- 1,
4589 "-*-%s-%s-%c-*-*-%s-%s-*-*-%c-%s-*-%s-",
4590 lplogfont
->lfFaceName
,
4591 w32_to_x_weight (lplogfont
->lfWeight
),
4592 lplogfont
->lfItalic
?'i':'r',
4595 ((lplogfont
->lfPitchAndFamily
& 0x3) == VARIABLE_PITCH
) ? 'p' : 'c',
4597 w32_to_x_charset (lplogfont
->lfCharSet
)
4600 lpxstr
[len
- 1] = 0; /* just to be sure */
4605 x_to_w32_font (lpxstr
, lplogfont
)
4607 LOGFONT
* lplogfont
;
4609 if (!lplogfont
) return (FALSE
);
4611 memset (lplogfont
, 0, sizeof (*lplogfont
));
4614 lplogfont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
4615 lplogfont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
4616 lplogfont
->lfQuality
= DEFAULT_QUALITY
;
4618 /* go for maximum quality */
4619 lplogfont
->lfOutPrecision
= OUT_STROKE_PRECIS
;
4620 lplogfont
->lfClipPrecision
= CLIP_STROKE_PRECIS
;
4621 lplogfont
->lfQuality
= PROOF_QUALITY
;
4627 /* Provide a simple escape mechanism for specifying Windows font names
4628 * directly -- if font spec does not beginning with '-', assume this
4630 * "<font name>[:height in pixels[:width in pixels[:weight]]]"
4636 char name
[50], weight
[20], slant
, pitch
, pixels
[10], height
[10], width
[10], remainder
[20];
4639 fields
= sscanf (lpxstr
,
4640 "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%*[^-]-%c-%9[^-]-%19s",
4641 name
, weight
, &slant
, pixels
, height
, &pitch
, width
, remainder
);
4643 if (fields
== EOF
) return (FALSE
);
4645 if (fields
> 0 && name
[0] != '*')
4647 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
4648 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
4652 lplogfont
->lfFaceName
[0] = 0;
4657 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
4661 if (!NILP (Vw32_enable_italics
))
4662 lplogfont
->lfItalic
= (fields
> 0 && slant
== 'i');
4666 if (fields
> 0 && pixels
[0] != '*')
4667 lplogfont
->lfHeight
= atoi (pixels
);
4671 if (fields
> 0 && lplogfont
->lfHeight
== 0 && height
[0] != '*')
4672 lplogfont
->lfHeight
= (atoi (height
)
4673 * one_w32_display_info
.height_in
) / 720;
4677 lplogfont
->lfPitchAndFamily
=
4678 (fields
> 0 && pitch
== 'p') ? VARIABLE_PITCH
: FIXED_PITCH
;
4682 if (fields
> 0 && width
[0] != '*')
4683 lplogfont
->lfWidth
= atoi (width
) / 10;
4687 /* Not all font specs include the registry field, so we allow for an
4688 optional registry field before the encoding when parsing
4689 remainder. Also we strip the trailing '-' if present. */
4691 int len
= strlen (remainder
);
4692 if (len
> 0 && remainder
[len
-1] == '-')
4693 remainder
[len
-1] = 0;
4695 encoding
= remainder
;
4696 if (strncmp (encoding
, "*-", 2) == 0)
4698 lplogfont
->lfCharSet
= x_to_w32_charset (fields
> 0 ? encoding
: "");
4703 char name
[100], height
[10], width
[10], weight
[20];
4705 fields
= sscanf (lpxstr
,
4706 "%99[^:]:%9[^:]:%9[^:]:%19s",
4707 name
, height
, width
, weight
);
4709 if (fields
== EOF
) return (FALSE
);
4713 strncpy (lplogfont
->lfFaceName
,name
, LF_FACESIZE
);
4714 lplogfont
->lfFaceName
[LF_FACESIZE
-1] = 0;
4718 lplogfont
->lfFaceName
[0] = 0;
4724 lplogfont
->lfHeight
= atoi (height
);
4729 lplogfont
->lfWidth
= atoi (width
);
4733 lplogfont
->lfWeight
= x_to_w32_weight ((fields
> 0 ? weight
: ""));
4736 /* This makes TrueType fonts work better. */
4737 lplogfont
->lfHeight
= - abs (lplogfont
->lfHeight
);
4743 w32_font_match (lpszfont1
, lpszfont2
)
4747 char * s1
= lpszfont1
, *e1
;
4748 char * s2
= lpszfont2
, *e2
;
4750 if (s1
== NULL
|| s2
== NULL
) return (FALSE
);
4752 if (*s1
== '-') s1
++;
4753 if (*s2
== '-') s2
++;
4759 e1
= strchr (s1
, '-');
4760 e2
= strchr (s2
, '-');
4762 if (e1
== NULL
|| e2
== NULL
) return (TRUE
);
4767 if (*s1
!= '*' && *s2
!= '*'
4768 && (len1
!= len2
|| strnicmp (s1
, s2
, len1
) != 0))
4776 typedef struct enumfont_t
4781 XFontStruct
*size_ref
;
4782 Lisp_Object
*pattern
;
4788 enum_font_cb2 (lplf
, lptm
, FontType
, lpef
)
4790 NEWTEXTMETRIC
* lptm
;
4794 if (lplf
->elfLogFont
.lfStrikeOut
|| lplf
->elfLogFont
.lfUnderline
)
4797 /* if (!lpef->size_ref || lptm->tmMaxCharWidth == FONT_WIDTH (lpef->size_ref)) */
4801 if (!NILP (*(lpef
->pattern
)) && FontType
== TRUETYPE_FONTTYPE
)
4803 lplf
->elfLogFont
.lfHeight
= lpef
->logfont
.lfHeight
;
4804 lplf
->elfLogFont
.lfWidth
= lpef
->logfont
.lfWidth
;
4807 if (!w32_to_x_font (lplf
, buf
, 100)) return (0);
4809 if (NILP (*(lpef
->pattern
)) || w32_font_match (buf
, XSTRING (*(lpef
->pattern
))->data
))
4811 *lpef
->tail
= Fcons (build_string (buf
), Qnil
);
4812 lpef
->tail
= &XCONS (*lpef
->tail
)->cdr
;
4821 enum_font_cb1 (lplf
, lptm
, FontType
, lpef
)
4823 NEWTEXTMETRIC
* lptm
;
4827 return EnumFontFamilies (lpef
->hdc
,
4828 lplf
->elfLogFont
.lfFaceName
,
4829 (FONTENUMPROC
) enum_font_cb2
,
4834 DEFUN ("x-list-fonts", Fx_list_fonts
, Sx_list_fonts
, 1, 3, 0,
4835 "Return a list of the names of available fonts matching PATTERN.\n\
4836 If optional arguments FACE and FRAME are specified, return only fonts\n\
4837 the same size as FACE on FRAME.\n\
4839 PATTERN is a string, perhaps with wildcard characters;\n\
4840 the * character matches any substring, and\n\
4841 the ? character matches any single character.\n\
4842 PATTERN is case-insensitive.\n\
4843 FACE is a face name--a symbol.\n\
4845 The return value is a list of strings, suitable as arguments to\n\
4848 Fonts Emacs can't use (i.e. proportional fonts) may or may not be excluded\n\
4849 even if they match PATTERN and FACE.")
4850 (pattern
, face
, frame
)
4851 Lisp_Object pattern
, face
, frame
;
4856 XFontStruct
*size_ref
;
4857 Lisp_Object namelist
;
4862 CHECK_STRING (pattern
, 0);
4864 CHECK_SYMBOL (face
, 1);
4866 f
= check_x_frame (frame
);
4868 /* Determine the width standard for comparison with the fonts we find. */
4876 /* Don't die if we get called with a terminal frame. */
4877 if (! FRAME_W32_P (f
))
4878 error ("non-w32 frame used in `x-list-fonts'");
4880 face_id
= face_name_id_number (f
, face
);
4882 if (face_id
< 0 || face_id
>= FRAME_N_PARAM_FACES (f
)
4883 || FRAME_PARAM_FACES (f
) [face_id
] == 0)
4884 size_ref
= f
->output_data
.w32
->font
;
4887 size_ref
= FRAME_PARAM_FACES (f
) [face_id
]->font
;
4888 if (size_ref
== (XFontStruct
*) (~0))
4889 size_ref
= f
->output_data
.w32
->font
;
4893 /* See if we cached the result for this particular query. */
4894 list
= Fassoc (pattern
,
4895 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
4897 /* We have info in the cache for this PATTERN. */
4900 Lisp_Object tem
, newlist
;
4902 /* We have info about this pattern. */
4903 list
= XCONS (list
)->cdr
;
4910 /* Filter the cached info and return just the fonts that match FACE. */
4912 for (tem
= list
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
4914 XFontStruct
*thisinfo
;
4916 thisinfo
= w32_load_font (FRAME_W32_DISPLAY_INFO (f
), XSTRING (XCONS (tem
)->car
)->data
);
4918 if (thisinfo
&& same_size_fonts (thisinfo
, size_ref
))
4919 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
4921 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
4932 ef
.pattern
= &pattern
;
4933 ef
.tail
= ef
.head
= &namelist
;
4935 x_to_w32_font (STRINGP (pattern
) ? XSTRING (pattern
)->data
: NULL
, &ef
.logfont
);
4938 ef
.hdc
= GetDC (FRAME_W32_WINDOW (f
));
4940 EnumFontFamilies (ef
.hdc
, NULL
, (FONTENUMPROC
) enum_font_cb1
, (LPARAM
)&ef
);
4942 ReleaseDC (FRAME_W32_WINDOW (f
), ef
.hdc
);
4952 /* Make a list of all the fonts we got back.
4953 Store that in the font cache for the display. */
4954 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
4955 = Fcons (Fcons (pattern
, namelist
),
4956 XCONS (FRAME_W32_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
4958 /* Make a list of the fonts that have the right width. */
4961 for (i
= 0; i
< ef
.numFonts
; i
++)
4969 XFontStruct
*thisinfo
;
4972 thisinfo
= w32_load_font (FRAME_W32_DISPLAY_INFO (f
), XSTRING (Fcar (cur
))->data
);
4974 keeper
= thisinfo
&& same_size_fonts (thisinfo
, size_ref
);
4976 w32_unload_font (FRAME_W32_DISPLAY_INFO (f
), thisinfo
);
4981 list
= Fcons (build_string (XSTRING (Fcar (cur
))->data
), list
);
4985 list
= Fnreverse (list
);
4991 DEFUN ("x-color-defined-p", Fx_color_defined_p
, Sx_color_defined_p
, 1, 2, 0,
4992 "Return non-nil if color COLOR is supported on frame FRAME.\n\
4993 If FRAME is omitted or nil, use the selected frame.")
4995 Lisp_Object color
, frame
;
4998 FRAME_PTR f
= check_x_frame (frame
);
5000 CHECK_STRING (color
, 1);
5002 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
5008 DEFUN ("x-color-values", Fx_color_values
, Sx_color_values
, 1, 2, 0,
5009 "Return a description of the color named COLOR on frame FRAME.\n\
5010 The value is a list of integer RGB values--(RED GREEN BLUE).\n\
5011 These values appear to range from 0 to 65280 or 65535, depending\n\
5012 on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
5013 If FRAME is omitted or nil, use the selected frame.")
5015 Lisp_Object color
, frame
;
5018 FRAME_PTR f
= check_x_frame (frame
);
5020 CHECK_STRING (color
, 1);
5022 if (defined_color (f
, XSTRING (color
)->data
, &foo
, 0))
5026 rgb
[0] = make_number ((GetRValue (foo
) << 8) | GetRValue (foo
));
5027 rgb
[1] = make_number ((GetGValue (foo
) << 8) | GetGValue (foo
));
5028 rgb
[2] = make_number ((GetBValue (foo
) << 8) | GetBValue (foo
));
5029 return Flist (3, rgb
);
5035 DEFUN ("x-display-color-p", Fx_display_color_p
, Sx_display_color_p
, 0, 1, 0,
5036 "Return t if the X display supports color.\n\
5037 The optional argument DISPLAY specifies which display to ask about.\n\
5038 DISPLAY should be either a frame or a display name (a string).\n\
5039 If omitted or nil, that stands for the selected frame's display.")
5041 Lisp_Object display
;
5043 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5045 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 2)
5051 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p
, Sx_display_grayscale_p
,
5053 "Return t if the X display supports shades of gray.\n\
5054 Note that color displays do support shades of gray.\n\
5055 The optional argument DISPLAY specifies which display to ask about.\n\
5056 DISPLAY should be either a frame or a display name (a string).\n\
5057 If omitted or nil, that stands for the selected frame's display.")
5059 Lisp_Object display
;
5061 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5063 if ((dpyinfo
->n_planes
* dpyinfo
->n_cbits
) <= 1)
5069 DEFUN ("x-display-pixel-width", Fx_display_pixel_width
, Sx_display_pixel_width
,
5071 "Returns the width in pixels of the X display DISPLAY.\n\
5072 The optional argument DISPLAY specifies which display to ask about.\n\
5073 DISPLAY should be either a frame or a display name (a string).\n\
5074 If omitted or nil, that stands for the selected frame's display.")
5076 Lisp_Object display
;
5078 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5080 return make_number (dpyinfo
->width
);
5083 DEFUN ("x-display-pixel-height", Fx_display_pixel_height
,
5084 Sx_display_pixel_height
, 0, 1, 0,
5085 "Returns the height in pixels of the X display DISPLAY.\n\
5086 The optional argument DISPLAY specifies which display to ask about.\n\
5087 DISPLAY should be either a frame or a display name (a string).\n\
5088 If omitted or nil, that stands for the selected frame's display.")
5090 Lisp_Object display
;
5092 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5094 return make_number (dpyinfo
->height
);
5097 DEFUN ("x-display-planes", Fx_display_planes
, Sx_display_planes
,
5099 "Returns the number of bitplanes of the display DISPLAY.\n\
5100 The optional argument DISPLAY specifies which display to ask about.\n\
5101 DISPLAY should be either a frame or a display name (a string).\n\
5102 If omitted or nil, that stands for the selected frame's display.")
5104 Lisp_Object display
;
5106 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5108 return make_number (dpyinfo
->n_planes
* dpyinfo
->n_cbits
);
5111 DEFUN ("x-display-color-cells", Fx_display_color_cells
, Sx_display_color_cells
,
5113 "Returns the number of color cells of the display DISPLAY.\n\
5114 The optional argument DISPLAY specifies which display to ask about.\n\
5115 DISPLAY should be either a frame or a display name (a string).\n\
5116 If omitted or nil, that stands for the selected frame's display.")
5118 Lisp_Object display
;
5120 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5124 hdc
= GetDC (dpyinfo
->root_window
);
5125 if (dpyinfo
->has_palette
)
5126 cap
= GetDeviceCaps (hdc
,SIZEPALETTE
);
5128 cap
= GetDeviceCaps (hdc
,NUMCOLORS
);
5130 ReleaseDC (dpyinfo
->root_window
, hdc
);
5132 return make_number (cap
);
5135 DEFUN ("x-server-max-request-size", Fx_server_max_request_size
,
5136 Sx_server_max_request_size
,
5138 "Returns the maximum request size of the server of display DISPLAY.\n\
5139 The optional argument DISPLAY specifies which display to ask about.\n\
5140 DISPLAY should be either a frame or a display name (a string).\n\
5141 If omitted or nil, that stands for the selected frame's display.")
5143 Lisp_Object display
;
5145 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5147 return make_number (1);
5150 DEFUN ("x-server-vendor", Fx_server_vendor
, Sx_server_vendor
, 0, 1, 0,
5151 "Returns the vendor ID string of the W32 system (Microsoft).\n\
5152 The optional argument DISPLAY specifies which display to ask about.\n\
5153 DISPLAY should be either a frame or a display name (a string).\n\
5154 If omitted or nil, that stands for the selected frame's display.")
5156 Lisp_Object display
;
5158 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5159 char *vendor
= "Microsoft Corp.";
5161 if (! vendor
) vendor
= "";
5162 return build_string (vendor
);
5165 DEFUN ("x-server-version", Fx_server_version
, Sx_server_version
, 0, 1, 0,
5166 "Returns the version numbers of the server of display DISPLAY.\n\
5167 The value is a list of three integers: the major and minor\n\
5168 version numbers, and the vendor-specific release\n\
5169 number. See also the function `x-server-vendor'.\n\n\
5170 The optional argument DISPLAY specifies which display to ask about.\n\
5171 DISPLAY should be either a frame or a display name (a string).\n\
5172 If omitted or nil, that stands for the selected frame's display.")
5174 Lisp_Object display
;
5176 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5178 return Fcons (make_number (w32_major_version
),
5179 Fcons (make_number (w32_minor_version
), Qnil
));
5182 DEFUN ("x-display-screens", Fx_display_screens
, Sx_display_screens
, 0, 1, 0,
5183 "Returns the number of screens on the server of display DISPLAY.\n\
5184 The optional argument DISPLAY specifies which display to ask about.\n\
5185 DISPLAY should be either a frame or a display name (a string).\n\
5186 If omitted or nil, that stands for the selected frame's display.")
5188 Lisp_Object display
;
5190 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5192 return make_number (1);
5195 DEFUN ("x-display-mm-height", Fx_display_mm_height
, Sx_display_mm_height
, 0, 1, 0,
5196 "Returns the height in millimeters of the X display DISPLAY.\n\
5197 The optional argument DISPLAY specifies which display to ask about.\n\
5198 DISPLAY should be either a frame or a display name (a string).\n\
5199 If omitted or nil, that stands for the selected frame's display.")
5201 Lisp_Object display
;
5203 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5207 hdc
= GetDC (dpyinfo
->root_window
);
5209 cap
= GetDeviceCaps (hdc
, VERTSIZE
);
5211 ReleaseDC (dpyinfo
->root_window
, hdc
);
5213 return make_number (cap
);
5216 DEFUN ("x-display-mm-width", Fx_display_mm_width
, Sx_display_mm_width
, 0, 1, 0,
5217 "Returns the width in millimeters of the X display DISPLAY.\n\
5218 The optional argument DISPLAY specifies which display to ask about.\n\
5219 DISPLAY should be either a frame or a display name (a string).\n\
5220 If omitted or nil, that stands for the selected frame's display.")
5222 Lisp_Object display
;
5224 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5229 hdc
= GetDC (dpyinfo
->root_window
);
5231 cap
= GetDeviceCaps (hdc
, HORZSIZE
);
5233 ReleaseDC (dpyinfo
->root_window
, hdc
);
5235 return make_number (cap
);
5238 DEFUN ("x-display-backing-store", Fx_display_backing_store
,
5239 Sx_display_backing_store
, 0, 1, 0,
5240 "Returns an indication of whether display DISPLAY does backing store.\n\
5241 The value may be `always', `when-mapped', or `not-useful'.\n\
5242 The optional argument DISPLAY specifies which display to ask about.\n\
5243 DISPLAY should be either a frame or a display name (a string).\n\
5244 If omitted or nil, that stands for the selected frame's display.")
5246 Lisp_Object display
;
5248 return intern ("not-useful");
5251 DEFUN ("x-display-visual-class", Fx_display_visual_class
,
5252 Sx_display_visual_class
, 0, 1, 0,
5253 "Returns the visual class of the display DISPLAY.\n\
5254 The value is one of the symbols `static-gray', `gray-scale',\n\
5255 `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
5256 The optional argument DISPLAY specifies which display to ask about.\n\
5257 DISPLAY should be either a frame or a display name (a string).\n\
5258 If omitted or nil, that stands for the selected frame's display.")
5260 Lisp_Object display
;
5262 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5265 switch (dpyinfo
->visual
->class)
5267 case StaticGray
: return (intern ("static-gray"));
5268 case GrayScale
: return (intern ("gray-scale"));
5269 case StaticColor
: return (intern ("static-color"));
5270 case PseudoColor
: return (intern ("pseudo-color"));
5271 case TrueColor
: return (intern ("true-color"));
5272 case DirectColor
: return (intern ("direct-color"));
5274 error ("Display has an unknown visual class");
5278 error ("Display has an unknown visual class");
5281 DEFUN ("x-display-save-under", Fx_display_save_under
,
5282 Sx_display_save_under
, 0, 1, 0,
5283 "Returns t if the display DISPLAY supports the save-under feature.\n\
5284 The optional argument DISPLAY specifies which display to ask about.\n\
5285 DISPLAY should be either a frame or a display name (a string).\n\
5286 If omitted or nil, that stands for the selected frame's display.")
5288 Lisp_Object display
;
5290 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5297 register struct frame
*f
;
5299 return PIXEL_WIDTH (f
);
5304 register struct frame
*f
;
5306 return PIXEL_HEIGHT (f
);
5311 register struct frame
*f
;
5313 return FONT_WIDTH (f
->output_data
.w32
->font
);
5318 register struct frame
*f
;
5320 return f
->output_data
.w32
->line_height
;
5324 x_screen_planes (frame
)
5327 return (FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_planes
*
5328 FRAME_W32_DISPLAY_INFO (XFRAME (frame
))->n_cbits
);
5331 /* Return the display structure for the display named NAME.
5332 Open a new connection if necessary. */
5334 struct w32_display_info
*
5335 x_display_info_for_name (name
)
5339 struct w32_display_info
*dpyinfo
;
5341 CHECK_STRING (name
, 0);
5343 for (dpyinfo
= &one_w32_display_info
, names
= w32_display_name_list
;
5345 dpyinfo
= dpyinfo
->next
, names
= XCONS (names
)->cdr
)
5348 tem
= Fstring_equal (XCONS (XCONS (names
)->car
)->car
, name
);
5353 /* Use this general default value to start with. */
5354 Vx_resource_name
= Vinvocation_name
;
5356 validate_x_resource_name ();
5358 dpyinfo
= w32_term_init (name
, (unsigned char *)0,
5359 (char *) XSTRING (Vx_resource_name
)->data
);
5362 error ("Cannot connect to server %s", XSTRING (name
)->data
);
5365 XSETFASTINT (Vwindow_system_version
, 3);
5370 DEFUN ("x-open-connection", Fx_open_connection
, Sx_open_connection
,
5371 1, 3, 0, "Open a connection to a server.\n\
5372 DISPLAY is the name of the display to connect to.\n\
5373 Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
5374 If the optional third arg MUST-SUCCEED is non-nil,\n\
5375 terminate Emacs if we can't open the connection.")
5376 (display
, xrm_string
, must_succeed
)
5377 Lisp_Object display
, xrm_string
, must_succeed
;
5379 unsigned int n_planes
;
5380 unsigned char *xrm_option
;
5381 struct w32_display_info
*dpyinfo
;
5383 CHECK_STRING (display
, 0);
5384 if (! NILP (xrm_string
))
5385 CHECK_STRING (xrm_string
, 1);
5387 if (! EQ (Vwindow_system
, intern ("w32")))
5388 error ("Not using Microsoft Windows");
5390 /* Allow color mapping to be defined externally; first look in user's
5391 HOME directory, then in Emacs etc dir for a file called rgb.txt. */
5393 Lisp_Object color_file
;
5394 struct gcpro gcpro1
;
5396 color_file
= build_string("~/rgb.txt");
5398 GCPRO1 (color_file
);
5400 if (NILP (Ffile_readable_p (color_file
)))
5402 Fexpand_file_name (build_string ("rgb.txt"),
5403 Fsymbol_value (intern ("data-directory")));
5405 Vw32_color_map
= Fw32_load_color_file (color_file
);
5409 if (NILP (Vw32_color_map
))
5410 Vw32_color_map
= Fw32_default_color_map ();
5412 if (! NILP (xrm_string
))
5413 xrm_option
= (unsigned char *) XSTRING (xrm_string
)->data
;
5415 xrm_option
= (unsigned char *) 0;
5417 /* Use this general default value to start with. */
5418 /* First remove .exe suffix from invocation-name - it looks ugly. */
5420 char basename
[ MAX_PATH
], *str
;
5422 strcpy (basename
, XSTRING (Vinvocation_name
)->data
);
5423 str
= strrchr (basename
, '.');
5425 Vinvocation_name
= build_string (basename
);
5427 Vx_resource_name
= Vinvocation_name
;
5429 validate_x_resource_name ();
5431 /* This is what opens the connection and sets x_current_display.
5432 This also initializes many symbols, such as those used for input. */
5433 dpyinfo
= w32_term_init (display
, xrm_option
,
5434 (char *) XSTRING (Vx_resource_name
)->data
);
5438 if (!NILP (must_succeed
))
5439 fatal ("Cannot connect to server %s.\n",
5440 XSTRING (display
)->data
);
5442 error ("Cannot connect to server %s", XSTRING (display
)->data
);
5447 XSETFASTINT (Vwindow_system_version
, 3);
5451 DEFUN ("x-close-connection", Fx_close_connection
,
5452 Sx_close_connection
, 1, 1, 0,
5453 "Close the connection to DISPLAY's server.\n\
5454 For DISPLAY, specify either a frame or a display name (a string).\n\
5455 If DISPLAY is nil, that stands for the selected frame's display.")
5457 Lisp_Object display
;
5459 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5460 struct w32_display_info
*tail
;
5463 if (dpyinfo
->reference_count
> 0)
5464 error ("Display still has frames on it");
5467 /* Free the fonts in the font table. */
5468 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
5470 if (dpyinfo
->font_table
[i
].name
)
5471 free (dpyinfo
->font_table
[i
].name
);
5472 /* Don't free the full_name string;
5473 it is always shared with something else. */
5474 w32_unload_font (dpyinfo
, dpyinfo
->font_table
[i
].font
);
5476 x_destroy_all_bitmaps (dpyinfo
);
5478 x_delete_display (dpyinfo
);
5484 DEFUN ("x-display-list", Fx_display_list
, Sx_display_list
, 0, 0, 0,
5485 "Return the list of display names that Emacs has connections to.")
5488 Lisp_Object tail
, result
;
5491 for (tail
= w32_display_name_list
; ! NILP (tail
); tail
= XCONS (tail
)->cdr
)
5492 result
= Fcons (XCONS (XCONS (tail
)->car
)->car
, result
);
5497 DEFUN ("x-synchronize", Fx_synchronize
, Sx_synchronize
, 1, 2, 0,
5498 "If ON is non-nil, report errors as soon as the erring request is made.\n\
5499 If ON is nil, allow buffering of requests.\n\
5500 This is a noop on W32 systems.\n\
5501 The optional second argument DISPLAY specifies which display to act on.\n\
5502 DISPLAY should be either a frame or a display name (a string).\n\
5503 If DISPLAY is omitted or nil, that stands for the selected frame's display.")
5505 Lisp_Object display
, on
;
5507 struct w32_display_info
*dpyinfo
= check_x_display_info (display
);
5513 /* These are the w32 specialized functions */
5515 DEFUN ("w32-select-font", Fw32_select_font
, Sw32_select_font
, 0, 1, 0,
5516 "This will display the W32 font dialog and return an X font string corresponding to the selection.")
5520 FRAME_PTR f
= check_x_frame (frame
);
5525 bzero (&cf
, sizeof (cf
));
5527 cf
.lStructSize
= sizeof (cf
);
5528 cf
.hwndOwner
= FRAME_W32_WINDOW (f
);
5529 cf
.Flags
= CF_FIXEDPITCHONLY
| CF_FORCEFONTEXIST
| CF_SCREENFONTS
;
5532 if (!ChooseFont (&cf
) || !w32_to_x_font (&lf
, buf
, 100))
5535 return build_string (buf
);
5538 DEFUN ("w32-send-sys-command", Fw32_send_sys_command
, Sw32_send_sys_command
, 1, 2, 0,
5539 "Send frame a Windows WM_SYSCOMMAND message of type COMMAND.\n\
5540 Some useful values for command are 0xf030 to maximise frame (0xf020\n\
5541 to minimize), 0xf120 to restore frame to original size, and 0xf100\n\
5542 to activate the menubar for keyboard access. 0xf140 activates the\n\
5543 screen saver if defined.\n\
5545 If optional parameter FRAME is not specified, use selected frame.")
5547 Lisp_Object command
, frame
;
5550 FRAME_PTR f
= check_x_frame (frame
);
5552 CHECK_NUMBER (command
, 0);
5554 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, XINT (command
), 0);
5562 /* This is zero if not using MS-Windows. */
5565 /* The section below is built by the lisp expression at the top of the file,
5566 just above where these variables are declared. */
5567 /*&&& init symbols here &&&*/
5568 Qauto_raise
= intern ("auto-raise");
5569 staticpro (&Qauto_raise
);
5570 Qauto_lower
= intern ("auto-lower");
5571 staticpro (&Qauto_lower
);
5572 Qbackground_color
= intern ("background-color");
5573 staticpro (&Qbackground_color
);
5574 Qbar
= intern ("bar");
5576 Qborder_color
= intern ("border-color");
5577 staticpro (&Qborder_color
);
5578 Qborder_width
= intern ("border-width");
5579 staticpro (&Qborder_width
);
5580 Qbox
= intern ("box");
5582 Qcursor_color
= intern ("cursor-color");
5583 staticpro (&Qcursor_color
);
5584 Qcursor_type
= intern ("cursor-type");
5585 staticpro (&Qcursor_type
);
5586 Qforeground_color
= intern ("foreground-color");
5587 staticpro (&Qforeground_color
);
5588 Qgeometry
= intern ("geometry");
5589 staticpro (&Qgeometry
);
5590 Qicon_left
= intern ("icon-left");
5591 staticpro (&Qicon_left
);
5592 Qicon_top
= intern ("icon-top");
5593 staticpro (&Qicon_top
);
5594 Qicon_type
= intern ("icon-type");
5595 staticpro (&Qicon_type
);
5596 Qicon_name
= intern ("icon-name");
5597 staticpro (&Qicon_name
);
5598 Qinternal_border_width
= intern ("internal-border-width");
5599 staticpro (&Qinternal_border_width
);
5600 Qleft
= intern ("left");
5602 Qright
= intern ("right");
5603 staticpro (&Qright
);
5604 Qmouse_color
= intern ("mouse-color");
5605 staticpro (&Qmouse_color
);
5606 Qnone
= intern ("none");
5608 Qparent_id
= intern ("parent-id");
5609 staticpro (&Qparent_id
);
5610 Qscroll_bar_width
= intern ("scroll-bar-width");
5611 staticpro (&Qscroll_bar_width
);
5612 Qsuppress_icon
= intern ("suppress-icon");
5613 staticpro (&Qsuppress_icon
);
5614 Qtop
= intern ("top");
5616 Qundefined_color
= intern ("undefined-color");
5617 staticpro (&Qundefined_color
);
5618 Qvertical_scroll_bars
= intern ("vertical-scroll-bars");
5619 staticpro (&Qvertical_scroll_bars
);
5620 Qvisibility
= intern ("visibility");
5621 staticpro (&Qvisibility
);
5622 Qwindow_id
= intern ("window-id");
5623 staticpro (&Qwindow_id
);
5624 Qx_frame_parameter
= intern ("x-frame-parameter");
5625 staticpro (&Qx_frame_parameter
);
5626 Qx_resource_name
= intern ("x-resource-name");
5627 staticpro (&Qx_resource_name
);
5628 Quser_position
= intern ("user-position");
5629 staticpro (&Quser_position
);
5630 Quser_size
= intern ("user-size");
5631 staticpro (&Quser_size
);
5632 Qdisplay
= intern ("display");
5633 staticpro (&Qdisplay
);
5634 /* This is the end of symbol initialization. */
5636 Fput (Qundefined_color
, Qerror_conditions
,
5637 Fcons (Qundefined_color
, Fcons (Qerror
, Qnil
)));
5638 Fput (Qundefined_color
, Qerror_message
,
5639 build_string ("Undefined color"));
5641 DEFVAR_LISP ("w32-color-map", &Vw32_color_map
,
5642 "A array of color name mappings for windows.");
5643 Vw32_color_map
= Qnil
;
5645 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system
,
5646 "Non-nil if alt key presses are passed on to Windows.\n\
5647 When non-nil, for example, alt pressed and released and then space will\n\
5648 open the System menu. When nil, Emacs silently swallows alt key events.");
5649 Vw32_pass_alt_to_system
= Qnil
;
5651 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta
,
5652 "Non-nil if the alt key is to be considered the same as the meta key.\n\
5653 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
5654 Vw32_alt_is_meta
= Qt
;
5656 DEFVAR_LISP ("w32-pass-optional-keys-to-system",
5657 &Vw32_pass_optional_keys_to_system
,
5658 "Non-nil if the 'optional' keys (left window, right window,\n\
5659 and application keys) are passed on to Windows.");
5660 Vw32_pass_optional_keys_to_system
= Qnil
;
5662 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics
,
5663 "Non-nil enables selection of artificially italicized fonts.");
5664 Vw32_enable_italics
= Qnil
;
5666 DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette
,
5667 "Non-nil enables Windows palette management to map colors exactly.");
5668 Vw32_enable_palette
= Qt
;
5670 DEFVAR_INT ("w32-mouse-button-tolerance",
5671 &Vw32_mouse_button_tolerance
,
5672 "Analogue of double click interval for faking middle mouse events.\n\
5673 The value is the minimum time in milliseconds that must elapse between\n\
5674 left/right button down events before they are considered distinct events.\n\
5675 If both mouse buttons are depressed within this interval, a middle mouse\n\
5676 button down event is generated instead.");
5677 XSETINT (Vw32_mouse_button_tolerance
, GetDoubleClickTime () / 2);
5679 DEFVAR_INT ("w32-mouse-move-interval",
5680 &Vw32_mouse_move_interval
,
5681 "Minimum interval between mouse move events.\n\
5682 The value is the minimum time in milliseconds that must elapse between\n\
5683 successive mouse move (or scroll bar drag) events before they are\n\
5684 reported as lisp events.");
5685 XSETINT (Vw32_mouse_move_interval
, 50);
5687 init_x_parm_symbols ();
5689 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
5690 "List of directories to search for bitmap files for w32.");
5691 Vx_bitmap_file_path
= decode_env_path ((char *) 0, "PATH");
5693 DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape
,
5694 "The shape of the pointer when over text.\n\
5695 Changing the value does not affect existing frames\n\
5696 unless you set the mouse color.");
5697 Vx_pointer_shape
= Qnil
;
5699 DEFVAR_LISP ("x-resource-name", &Vx_resource_name
,
5700 "The name Emacs uses to look up resources; for internal use only.\n\
5701 `x-get-resource' uses this as the first component of the instance name\n\
5702 when requesting resource values.\n\
5703 Emacs initially sets `x-resource-name' to the name under which Emacs\n\
5704 was invoked, or to the value specified with the `-name' or `-rn'\n\
5705 switches, if present.");
5706 Vx_resource_name
= Qnil
;
5708 Vx_nontext_pointer_shape
= Qnil
;
5710 Vx_mode_pointer_shape
= Qnil
;
5712 DEFVAR_INT ("x-sensitive-text-pointer-shape",
5713 &Vx_sensitive_text_pointer_shape
,
5714 "The shape of the pointer when over mouse-sensitive text.\n\
5715 This variable takes effect when you create a new frame\n\
5716 or when you set the mouse color.");
5717 Vx_sensitive_text_pointer_shape
= Qnil
;
5719 DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel
,
5720 "A string indicating the foreground color of the cursor box.");
5721 Vx_cursor_fore_pixel
= Qnil
;
5723 DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager
,
5724 "Non-nil if no window manager is in use.\n\
5725 Emacs doesn't try to figure this out; this is always nil\n\
5726 unless you set it to something else.");
5727 /* We don't have any way to find this out, so set it to nil
5728 and maybe the user would like to set it to t. */
5729 Vx_no_window_manager
= Qnil
;
5731 defsubr (&Sx_get_resource
);
5732 defsubr (&Sx_list_fonts
);
5733 defsubr (&Sx_display_color_p
);
5734 defsubr (&Sx_display_grayscale_p
);
5735 defsubr (&Sx_color_defined_p
);
5736 defsubr (&Sx_color_values
);
5737 defsubr (&Sx_server_max_request_size
);
5738 defsubr (&Sx_server_vendor
);
5739 defsubr (&Sx_server_version
);
5740 defsubr (&Sx_display_pixel_width
);
5741 defsubr (&Sx_display_pixel_height
);
5742 defsubr (&Sx_display_mm_width
);
5743 defsubr (&Sx_display_mm_height
);
5744 defsubr (&Sx_display_screens
);
5745 defsubr (&Sx_display_planes
);
5746 defsubr (&Sx_display_color_cells
);
5747 defsubr (&Sx_display_visual_class
);
5748 defsubr (&Sx_display_backing_store
);
5749 defsubr (&Sx_display_save_under
);
5750 defsubr (&Sx_parse_geometry
);
5751 defsubr (&Sx_create_frame
);
5752 defsubr (&Sx_open_connection
);
5753 defsubr (&Sx_close_connection
);
5754 defsubr (&Sx_display_list
);
5755 defsubr (&Sx_synchronize
);
5757 /* W32 specific functions */
5759 defsubr (&Sw32_focus_frame
);
5760 defsubr (&Sw32_select_font
);
5761 defsubr (&Sw32_define_rgb_color
);
5762 defsubr (&Sw32_default_color_map
);
5763 defsubr (&Sw32_load_color_file
);
5764 defsubr (&Sw32_send_sys_command
);
5773 button
= MessageBox (NULL
,
5774 "A fatal error has occurred!\n\n"
5775 "Select Abort to exit, Retry to debug, Ignore to continue",
5776 "Emacs Abort Dialog",
5777 MB_ICONEXCLAMATION
| MB_TASKMODAL
5778 | MB_SETFOREGROUND
| MB_ABORTRETRYIGNORE
);