1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
28 #include "blockinput.h"
40 #include "character.h"
44 #include "dispextern.h"
46 #include "termhooks.h"
54 #include "intervals.h"
63 #ifdef USE_FONT_BACKEND
65 #endif /* USE_FONT_BACKEND */
67 #define abs(x) ((x) < 0 ? -(x) : (x))
72 static int max_fringe_bmp
= 0;
73 static HBITMAP
*fringe_bmp
= 0;
75 /* Non-nil means Emacs uses toolkit scroll bars. */
77 Lisp_Object Vx_toolkit_scroll_bars
;
79 /* Temporary variables for w32_read_socket. */
81 static int last_mousemove_x
= 0;
82 static int last_mousemove_y
= 0;
84 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
85 #ifndef GET_WHEEL_DELTA_WPARAM
86 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
89 /* Non-zero means that a HELP_EVENT has been generated since Emacs
92 static int any_help_event_p
;
94 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
95 static Lisp_Object last_window
;
97 /* Non-zero means make use of UNDERLINE_POSITION font properties.
98 (Not yet supported, see TODO in x_draw_glyph_string.) */
99 int x_use_underline_position_properties
;
101 /* Non-zero means to draw the underline at the same place as the descent line. */
103 int x_underline_at_descent_line
;
105 extern unsigned int msh_mousewheel
;
107 extern void free_frame_menubar ();
109 extern int w32_codepage_for_font (char *fontname
);
110 extern Cursor
w32_load_cursor (LPCTSTR name
);
112 extern glyph_metric
*w32_BDF_TextMetric(bdffont
*fontp
,
113 unsigned char *text
, int dim
);
114 extern Lisp_Object Vwindow_system
;
116 #define x_any_window_to_frame x_window_to_frame
117 #define x_top_window_to_frame x_window_to_frame
120 /* This is display since w32 does not support multiple ones. */
121 struct w32_display_info one_w32_display_info
;
122 struct w32_display_info
*x_display_list
;
124 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
125 one for each element of w32_display_list and in the same order.
126 NAME is the name of the frame.
127 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
128 Lisp_Object w32_display_name_list
;
132 /* Pre Windows 2000, this was not available, but define it here so
133 that Emacs compiled on such a platform will run on newer versions. */
135 typedef struct tagWCRANGE
141 typedef struct tagGLYPHSET
145 DWORD cGlyphsSupported
;
152 /* Dynamic linking to GetFontUnicodeRanges (not available on 95, 98, ME). */
153 DWORD (PASCAL
*pfnGetFontUnicodeRanges
) (HDC device
, GLYPHSET
*ranges
);
155 /* Frame being updated by update_frame. This is declared in term.c.
156 This is set by update_begin and looked at by all the
157 w32 functions. It is zero while not inside an update.
158 In that case, the w32 functions assume that `SELECTED_FRAME ()'
159 is the frame to apply to. */
160 extern struct frame
*updating_frame
;
162 /* This is a frame waiting to be autoraised, within w32_read_socket. */
163 struct frame
*pending_autoraise_frame
;
165 /* The handle of the frame that currently owns the system caret. */
166 HWND w32_system_caret_hwnd
;
167 int w32_system_caret_height
;
168 int w32_system_caret_x
;
169 int w32_system_caret_y
;
170 int w32_use_visible_system_caret
;
172 /* Flag to enable Unicode output in case users wish to use programs
173 like Twinbridge on '95 rather than installed system level support
174 for Far East languages. */
175 int w32_enable_unicode_output
;
177 /* Flag to enable Cleartype hack for font metrics. */
178 static int cleartype_active
;
180 DWORD dwWindowsThreadId
= 0;
181 HANDLE hWindowsThread
= NULL
;
182 DWORD dwMainThreadId
= 0;
183 HANDLE hMainThread
= NULL
;
185 int vertical_scroll_bar_min_handle
;
186 int vertical_scroll_bar_top_border
;
187 int vertical_scroll_bar_bottom_border
;
189 int last_scroll_bar_drag_pos
;
191 /* Mouse movement. */
193 /* Where the mouse was last time we reported a mouse event. */
195 static RECT last_mouse_glyph
;
196 static FRAME_PTR last_mouse_glyph_frame
;
197 static Lisp_Object last_mouse_press_frame
;
199 int w32_num_mouse_buttons
;
201 Lisp_Object Vw32_swap_mouse_buttons
;
203 /* Control whether x_raise_frame also sets input focus. */
204 Lisp_Object Vw32_grab_focus_on_raise
;
206 /* Control whether Caps Lock affects non-ascii characters. */
207 Lisp_Object Vw32_capslock_is_shiftlock
;
209 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
210 Lisp_Object Vw32_recognize_altgr
;
212 /* The scroll bar in which the last motion event occurred.
214 If the last motion event occurred in a scroll bar, we set this
215 so w32_mouse_position can know whether to report a scroll bar motion or
218 If the last motion event didn't occur in a scroll bar, we set this
219 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
220 static Lisp_Object last_mouse_scroll_bar
;
221 static int last_mouse_scroll_bar_pos
;
223 /* This is a hack. We would really prefer that w32_mouse_position would
224 return the time associated with the position it returns, but there
225 doesn't seem to be any way to wrest the time-stamp from the server
226 along with the position query. So, we just keep track of the time
227 of the last movement we received, and return that in hopes that
228 it's somewhat accurate. */
230 static Time last_mouse_movement_time
;
232 /* Incremented by w32_read_socket whenever it really tries to read
236 static int volatile input_signal_count
;
238 static int input_signal_count
;
241 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
247 /* A mask of extra modifier bits to put into every keyboard char. */
249 extern EMACS_INT extra_keyboard_modifiers
;
251 static void x_update_window_end
P_ ((struct window
*, int, int));
252 static void w32_handle_tool_bar_click
P_ ((struct frame
*,
253 struct input_event
*));
254 static void w32_define_cursor
P_ ((Window
, Cursor
));
256 void x_lower_frame
P_ ((struct frame
*));
257 void x_scroll_bar_clear
P_ ((struct frame
*));
258 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
259 void x_raise_frame
P_ ((struct frame
*));
260 void x_set_window_size
P_ ((struct frame
*, int, int, int));
261 void x_wm_set_window_state
P_ ((struct frame
*, int));
262 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
263 static void w32_initialize
P_ ((void));
264 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
265 int x_compute_min_glyph_bounds
P_ ((struct frame
*));
266 static void x_update_end
P_ ((struct frame
*));
267 static void w32_frame_up_to_date
P_ ((struct frame
*));
268 static void w32_set_terminal_modes
P_ ((void));
269 static void w32_reset_terminal_modes
P_ ((void));
270 static void x_clear_frame
P_ ((void));
271 static void frame_highlight
P_ ((struct frame
*));
272 static void frame_unhighlight
P_ ((struct frame
*));
273 static void x_new_focus_frame
P_ ((struct w32_display_info
*,
275 static void x_focus_changed
P_ ((int, int, struct w32_display_info
*,
276 struct frame
*, struct input_event
*));
277 static void w32_detect_focus_change
P_ ((struct w32_display_info
*,
278 W32Msg
*, struct input_event
*));
279 static void w32_frame_rehighlight
P_ ((struct frame
*));
280 static void x_frame_rehighlight
P_ ((struct w32_display_info
*));
281 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
282 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
283 enum text_cursor_kinds
));
284 static void w32_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, HDC
));
285 static BOOL my_show_window
P_ ((struct frame
*, HWND
, int));
286 static void my_set_window_pos
P_ ((HWND
, HWND
, int, int, int, int, UINT
));
287 static void my_set_focus
P_ ((struct frame
*, HWND
));
288 static void my_set_foreground_window
P_ ((HWND
));
289 static void my_destroy_window
P_ ((struct frame
*, HWND
));
291 static Lisp_Object Qvendor_specific_keysyms
;
294 /***********************************************************************
296 ***********************************************************************/
300 /* This is a function useful for recording debugging information about
301 the sequence of occurrences in this file. */
309 struct record event_record
[100];
311 int event_record_index
;
313 record_event (locus
, type
)
317 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
318 event_record_index
= 0;
320 event_record
[event_record_index
].locus
= locus
;
321 event_record
[event_record_index
].type
= type
;
322 event_record_index
++;
329 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
332 if (mask
& GCForeground
)
333 gc
->foreground
= xgcv
->foreground
;
334 if (mask
& GCBackground
)
335 gc
->background
= xgcv
->background
;
337 gc
->font
= xgcv
->font
;
340 XGCValues
*XCreateGC (void * ignore
, Window window
, unsigned long mask
,
343 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
344 bzero (gc
, sizeof (XGCValues
));
346 XChangeGC (ignore
, gc
, mask
, xgcv
);
352 XGetGCValues (void* ignore
, XGCValues
*gc
,
353 unsigned long mask
, XGCValues
*xgcv
)
355 XChangeGC (ignore
, xgcv
, mask
, gc
);
359 w32_set_clip_rectangle (HDC hdc
, RECT
*rect
)
363 HRGN clip_region
= CreateRectRgnIndirect (rect
);
364 SelectClipRgn (hdc
, clip_region
);
365 DeleteObject (clip_region
);
368 SelectClipRgn (hdc
, NULL
);
372 /* Draw a hollow rectangle at the specified position. */
374 w32_draw_rectangle (HDC hdc
, XGCValues
*gc
, int x
, int y
,
375 int width
, int height
)
380 hb
= CreateSolidBrush (gc
->background
);
381 hp
= CreatePen (PS_SOLID
, 0, gc
->foreground
);
382 oldhb
= SelectObject (hdc
, hb
);
383 oldhp
= SelectObject (hdc
, hp
);
385 Rectangle (hdc
, x
, y
, x
+ width
, y
+ height
);
387 SelectObject (hdc
, oldhb
);
388 SelectObject (hdc
, oldhp
);
393 /* Draw a filled rectangle at the specified position. */
395 w32_fill_rect (f
, hdc
, pix
, lprect
)
403 hb
= CreateSolidBrush (pix
);
404 FillRect (hdc
, lprect
, hb
);
413 HDC hdc
= get_frame_dc (f
);
415 /* Under certain conditions, this can be called at startup with
416 a console frame pointer before the GUI frame is created. An HDC
417 of 0 indicates this. */
420 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
421 w32_clear_rect (f
, hdc
, &rect
);
424 release_frame_dc (f
, hdc
);
428 /***********************************************************************
429 Starting and ending an update
430 ***********************************************************************/
432 /* Start an update of frame F. This function is installed as a hook
433 for update_begin, i.e. it is called when update_begin is called.
434 This function is called prior to calls to x_update_window_begin for
435 each window being updated. */
441 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
443 if (! FRAME_W32_P (f
))
446 /* Regenerate display palette before drawing if list of requested
447 colors has changed. */
448 if (display_info
->regen_palette
)
450 w32_regenerate_palette (f
);
451 display_info
->regen_palette
= FALSE
;
456 /* Start update of window W. Set the global variable updated_window
457 to the window being updated and set output_cursor to the cursor
461 x_update_window_begin (w
)
464 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
465 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
467 /* Hide the system caret during an update. */
468 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
470 SendMessage (w32_system_caret_hwnd
, WM_EMACS_HIDE_CARET
, 0, 0);
474 set_output_cursor (&w
->cursor
);
478 if (f
== display_info
->mouse_face_mouse_frame
)
480 /* Don't do highlighting for mouse motion during the update. */
481 display_info
->mouse_face_defer
= 1;
483 /* If F needs to be redrawn, simply forget about any prior mouse
485 if (FRAME_GARBAGED_P (f
))
486 display_info
->mouse_face_window
= Qnil
;
488 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
489 their mouse_face_p flag set, which means that they are always
490 unequal to rows in a desired matrix which never have that
491 flag set. So, rows containing mouse-face glyphs are never
492 scrolled, and we don't have to switch the mouse highlight off
493 here to prevent it from being scrolled. */
495 /* Can we tell that this update does not affect the window
496 where the mouse highlight is? If so, no need to turn off.
497 Likewise, don't do anything if the frame is garbaged;
498 in that case, the frame's current matrix that we would use
499 is all wrong, and we will redisplay that line anyway. */
500 if (!NILP (display_info
->mouse_face_window
)
501 && w
== XWINDOW (display_info
->mouse_face_window
))
505 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
506 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
509 if (i
< w
->desired_matrix
->nrows
)
510 clear_mouse_face (display_info
);
518 /* Draw a vertical window border from (x,y0) to (x,y1) */
521 w32_draw_vertical_window_border (w
, x
, y0
, y1
)
525 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
535 hdc
= get_frame_dc (f
);
536 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
538 w32_fill_rect (f
, hdc
, face
->foreground
, &r
);
540 w32_fill_rect (f
, hdc
, FRAME_FOREGROUND_PIXEL (f
), &r
);
542 release_frame_dc (f
, hdc
);
546 /* End update of window W (which is equal to updated_window).
548 Draw vertical borders between horizontally adjacent windows, and
549 display W's cursor if CURSOR_ON_P is non-zero.
551 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
552 glyphs in mouse-face were overwritten. In that case we have to
553 make sure that the mouse-highlight is properly redrawn.
555 W may be a menu bar pseudo-window in case we don't have X toolkit
556 support. Such windows don't have a cursor, so don't display it
560 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
562 int cursor_on_p
, mouse_face_overwritten_p
;
564 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
566 if (!w
->pseudo_window_p
)
571 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
573 output_cursor
.x
, output_cursor
.y
);
575 if (draw_window_fringes (w
, 1))
576 x_draw_vertical_border (w
);
581 /* If a row with mouse-face was overwritten, arrange for
582 XTframe_up_to_date to redisplay the mouse highlight. */
583 if (mouse_face_overwritten_p
)
585 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
586 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
587 dpyinfo
->mouse_face_window
= Qnil
;
590 /* Unhide the caret. This won't actually show the cursor, unless it
591 was visible before the corresponding call to HideCaret in
592 x_update_window_begin. */
593 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
595 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
598 updated_window
= NULL
;
602 /* End update of frame F. This function is installed as a hook in
609 if (! FRAME_W32_P (f
))
612 /* Mouse highlight may be displayed again. */
613 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
617 /* This function is called from various places in xdisp.c whenever a
618 complete update has been performed. The global variable
619 updated_window is not available here. */
622 w32_frame_up_to_date (f
)
627 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
629 if (dpyinfo
->mouse_face_deferred_gc
630 || f
== dpyinfo
->mouse_face_mouse_frame
)
633 if (dpyinfo
->mouse_face_mouse_frame
)
634 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
635 dpyinfo
->mouse_face_mouse_x
,
636 dpyinfo
->mouse_face_mouse_y
);
637 dpyinfo
->mouse_face_deferred_gc
= 0;
644 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
645 arrow bitmaps, or clear the fringes if no bitmaps are required
646 before DESIRED_ROW is made current. The window being updated is
647 found in updated_window. This function is called from
648 update_window_line only if it is known that there are differences
649 between bitmaps to be drawn between current row and DESIRED_ROW. */
652 x_after_update_window_line (desired_row
)
653 struct glyph_row
*desired_row
;
655 struct window
*w
= updated_window
;
661 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
662 desired_row
->redraw_fringe_bitmaps_p
= 1;
664 /* When a window has disappeared, make sure that no rest of
665 full-width rows stays visible in the internal border. Could
666 check here if updated_window is the leftmost/rightmost window,
667 but I guess it's not worth doing since vertically split windows
668 are almost never used, internal border is rarely set, and the
669 overhead is very small. */
670 if (windows_or_buffers_changed
671 && desired_row
->full_width_p
672 && (f
= XFRAME (w
->frame
),
673 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
675 && (height
= desired_row
->visible_height
,
678 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
680 /* Internal border is drawn below the tool bar. */
681 if (WINDOWP (f
->tool_bar_window
)
682 && w
== XWINDOW (f
->tool_bar_window
))
687 HDC hdc
= get_frame_dc (f
);
688 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
689 w32_clear_area (f
, hdc
, FRAME_PIXEL_WIDTH (f
) - width
,
691 release_frame_dc (f
, hdc
);
698 /* Draw the bitmap WHICH in one of the left or right fringes of
699 window W. ROW is the glyph row for which to display the bitmap; it
700 determines the vertical position at which the bitmap has to be
704 w32_draw_fringe_bitmap (w
, row
, p
)
706 struct glyph_row
*row
;
707 struct draw_fringe_bitmap_params
*p
;
709 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
711 struct face
*face
= p
->face
;
714 hdc
= get_frame_dc (f
);
716 /* Must clip because of partially visible lines. */
717 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
720 /* Adjust position of "bottom aligned" bitmap on partially
723 int oldVH
= row
->visible_height
;
724 row
->visible_height
= p
->h
;
725 row
->y
-= rowY
- p
->y
;
726 w32_clip_to_row (w
, row
, -1, hdc
);
728 row
->visible_height
= oldVH
;
731 w32_clip_to_row (w
, row
, -1, hdc
);
733 if (p
->bx
>= 0 && !p
->overlay_p
)
735 w32_fill_area (f
, hdc
, face
->background
,
736 p
->bx
, p
->by
, p
->nx
, p
->ny
);
739 if (p
->which
&& p
->which
< max_fringe_bmp
)
741 HBITMAP pixmap
= fringe_bmp
[p
->which
];
745 compat_hdc
= CreateCompatibleDC (hdc
);
749 horig_obj
= SelectObject (compat_hdc
, pixmap
);
751 /* Paint overlays transparently. */
754 HBRUSH h_brush
, h_orig_brush
;
756 SetTextColor (hdc
, BLACK_PIX_DEFAULT (f
));
757 SetBkColor (hdc
, WHITE_PIX_DEFAULT (f
));
758 h_brush
= CreateSolidBrush (face
->foreground
);
759 h_orig_brush
= SelectObject (hdc
, h_brush
);
761 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
762 compat_hdc
, 0, p
->dh
,
764 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
765 compat_hdc
, 0, p
->dh
,
767 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
768 compat_hdc
, 0, p
->dh
,
771 SelectObject (hdc
, h_orig_brush
);
772 DeleteObject (h_brush
);
776 SetTextColor (hdc
, face
->background
);
777 SetBkColor (hdc
, (p
->cursor_p
778 ? f
->output_data
.w32
->cursor_pixel
779 : face
->foreground
));
781 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
782 compat_hdc
, 0, p
->dh
,
786 SelectObject (compat_hdc
, horig_obj
);
787 DeleteDC (compat_hdc
);
791 w32_set_clip_rectangle (hdc
, NULL
);
793 release_frame_dc (f
, hdc
);
797 w32_define_fringe_bitmap (which
, bits
, h
, wd
)
799 unsigned short *bits
;
802 if (which
>= max_fringe_bmp
)
804 int i
= max_fringe_bmp
;
805 max_fringe_bmp
= which
+ 20;
806 fringe_bmp
= (HBITMAP
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (HBITMAP
));
807 while (i
< max_fringe_bmp
)
811 fringe_bmp
[which
] = CreateBitmap (wd
, h
, 1, 1, bits
);
815 w32_destroy_fringe_bitmap (which
)
818 if (which
>= max_fringe_bmp
)
821 if (fringe_bmp
[which
])
822 DeleteObject (fringe_bmp
[which
]);
823 fringe_bmp
[which
] = 0;
828 /* This is called when starting Emacs and when restarting after
829 suspend. When starting Emacs, no window is mapped. And nothing
830 must be done to Emacs's own window if it is suspended (though that
834 w32_set_terminal_modes (void)
838 /* This is called when exiting or suspending Emacs. Exiting will make
839 the W32 windows go away, and suspending requires no action. */
842 w32_reset_terminal_modes (void)
848 /***********************************************************************
850 ***********************************************************************/
852 /* Function prototypes of this page. */
854 XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*, wchar_t *, int));
855 static int w32_encode_char
P_ ((int, wchar_t *, struct font_info
*,
856 struct charset
*, int *));
859 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
860 If CHAR2B is not contained in FONT, the font's default character
861 metric is returned. */
864 w32_bdf_per_char_metric (font
, char2b
, dim
, pcm
)
870 glyph_metric
* bdf_metric
;
874 buf
[0] = (char)(*char2b
);
877 buf
[0] = XCHAR2B_BYTE1 (char2b
);
878 buf
[1] = XCHAR2B_BYTE2 (char2b
);
881 bdf_metric
= w32_BDF_TextMetric (font
->bdf
, buf
, dim
);
885 pcm
->width
= bdf_metric
->dwidth
;
886 pcm
->lbearing
= bdf_metric
->bbox
;
887 pcm
->rbearing
= bdf_metric
->dwidth
888 - (bdf_metric
->bbox
+ bdf_metric
->bbw
);
889 pcm
->ascent
= bdf_metric
->bboy
+ bdf_metric
->bbh
;
890 pcm
->descent
= -bdf_metric
->bboy
;
899 w32_native_per_char_metric (font
, char2b
, font_type
, pcm
)
902 enum w32_char_font_type font_type
;
905 HDC hdc
= GetDC (NULL
);
909 xassert (font
&& char2b
);
910 xassert (font
->hfont
);
911 xassert (font_type
== UNICODE_FONT
|| font_type
== ANSI_FONT
);
913 old_font
= SelectObject (hdc
, font
->hfont
);
915 if ((font
->tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) != 0)
919 if (font_type
== UNICODE_FONT
)
920 retval
= GetCharABCWidthsW (hdc
, *char2b
, *char2b
, &char_widths
);
922 retval
= GetCharABCWidthsA (hdc
, *char2b
, *char2b
, &char_widths
);
927 /* Disabled until we can find a way to get the right results
928 on all versions of Windows. */
930 /* Don't trust the ABC widths. For synthesized fonts they are
931 wrong, and so is the result of GetCharWidth()! */
933 GetCharWidth (hdc
, *char2b
, *char2b
, &real_width
);
935 if (cleartype_active
)
937 /* Cleartype antialiasing causes characters to overhang
938 by a pixel on each side compared with what GetCharABCWidths
940 char_widths
.abcA
-= 1;
941 char_widths
.abcC
-= 1;
942 char_widths
.abcB
+= 2;
945 pcm
->width
= char_widths
.abcA
+ char_widths
.abcB
+ char_widths
.abcC
;
947 /* As far as I can tell, this is the best way to determine what
948 ExtTextOut will do with the broken font. */
949 if (pcm
->width
!= real_width
)
950 pcm
->width
= (pcm
->width
+ real_width
) / 2;
952 pcm
->lbearing
= char_widths
.abcA
;
953 pcm
->rbearing
= char_widths
.abcA
+ char_widths
.abcB
;
954 pcm
->ascent
= FONT_BASE (font
);
955 pcm
->descent
= FONT_DESCENT (font
);
961 /* Either font is not a True-type font, or GetCharABCWidthsW
962 failed (it is not supported on Windows 9x for instance), so we
963 can't determine the full info we would like. All is not lost
964 though - we can call GetTextExtentPoint32 to get rbearing and
965 deduce width based on the font's per-string overhang. lbearing
966 is assumed to be zero. */
968 /* TODO: Some Thai characters (and other composites if Windows
969 supports them) do have lbearing, and report their total width
970 as zero. Need some way of handling them when
971 GetCharABCWidthsW fails. */
974 if (font_type
== UNICODE_FONT
)
975 retval
= GetTextExtentPoint32W (hdc
, char2b
, 1, &sz
);
977 retval
= GetTextExtentPoint32A (hdc
, (char*)char2b
, 1, &sz
);
982 pcm
->rbearing
= sz
.cx
+ font
->tm
.tmOverhang
;
984 pcm
->ascent
= FONT_BASE (font
);
985 pcm
->descent
= FONT_DESCENT (font
);
990 if (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0)
995 SelectObject (hdc
, old_font
);
996 ReleaseDC (NULL
, hdc
);
1003 w32_per_char_metric (font
, char2b
, font_type
)
1006 int /* enum w32_char_font_type */ font_type
;
1008 /* The result metric information. */
1012 xassert (font
&& char2b
);
1014 /* TODO: This function is currently called through the RIF, and in
1015 some cases font_type is UNKNOWN_FONT. We currently allow the
1016 cached metrics to be used, which seems to work, but in cases
1017 where font_type is UNKNOWN_FONT, we probably haven't encoded
1018 char2b appropriately. All callers need checking to see what they
1019 are passing. This is most likely to affect variable width fonts
1020 outside the Latin-1 range, particularly in languages like Thai
1021 that rely on rbearing and lbearing to provide composition. I
1022 don't think that is working currently anyway, but we don't seem
1023 to have anyone testing such languages on Windows. */
1025 /* Handle the common cases quickly. */
1026 if (!font
->bdf
&& font
->per_char
== NULL
)
1027 /* TODO: determine whether char2b exists in font? */
1028 return &font
->max_bounds
;
1029 else if (!font
->bdf
&& *char2b
< 128)
1030 return &font
->per_char
[*char2b
];
1032 xassert (font_type
!= UNKNOWN_FONT
);
1034 pcm
= &font
->scratch
;
1036 if (font_type
== BDF_1D_FONT
)
1037 retval
= w32_bdf_per_char_metric (font
, char2b
, 1, pcm
);
1038 else if (font_type
== BDF_2D_FONT
)
1039 retval
= w32_bdf_per_char_metric (font
, char2b
, 2, pcm
);
1041 retval
= w32_native_per_char_metric (font
, char2b
, font_type
, pcm
);
1050 w32_cache_char_metrics (font
)
1053 wchar_t char2b
= L
'x';
1055 /* Cache char metrics for the common cases. */
1058 /* TODO: determine whether font is fixed-pitch. */
1059 if (!w32_bdf_per_char_metric (font
, &char2b
, 1, &font
->max_bounds
))
1061 /* Use the font width and height as max bounds, as not all BDF
1062 fonts contain the letter 'x'. */
1063 font
->max_bounds
.width
= FONT_WIDTH (font
);
1064 font
->max_bounds
.lbearing
= -font
->bdf
->llx
;
1065 font
->max_bounds
.rbearing
= FONT_WIDTH (font
) - font
->bdf
->urx
;
1066 font
->max_bounds
.ascent
= FONT_BASE (font
);
1067 font
->max_bounds
.descent
= FONT_DESCENT (font
);
1072 if (((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
) != 0)
1073 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1074 though they contain characters of different widths. */
1075 || (font
->tm
.tmMaxCharWidth
!= font
->tm
.tmAveCharWidth
))
1077 /* Font is not fixed pitch, so cache per_char info for the
1078 ASCII characters. It would be much more work, and probably
1079 not worth it, to cache other chars, since we may change
1080 between using Unicode and ANSI text drawing functions at
1084 font
->per_char
= xmalloc (128 * sizeof(XCharStruct
));
1085 for (i
= 0; i
< 128; i
++)
1088 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1089 &font
->per_char
[i
]);
1093 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1099 /* Determine if a font is double byte. */
1100 int w32_font_is_double_byte (XFontStruct
*font
)
1102 return font
->double_byte_p
;
1107 w32_use_unicode_for_codepage (codepage
)
1110 /* If the current codepage is supported, use Unicode for output. */
1111 return (w32_enable_unicode_output
1112 && codepage
!= CP_8BIT
1113 && (codepage
== CP_UNICODE
|| IsValidCodePage (codepage
)));
1116 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1117 the two-byte form of C. Encoding is returned in *CHAR2B. */
1119 static int /* enum w32_char_font_type */
1120 w32_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1123 struct font_info
*font_info
;
1124 struct charset
*charset
;
1129 int internal_two_byte_p
= 0;
1131 XFontStruct
*font
= font_info
->font
;
1133 internal_two_byte_p
= w32_font_is_double_byte (font
);
1134 codepage
= font_info
->codepage
;
1136 /* If font can output unicode, use the original unicode character. */
1137 if ( font
&& !font
->bdf
&& w32_use_unicode_for_codepage (codepage
)
1142 internal_two_byte_p
= 1;
1145 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1146 This may be either a program in a special encoder language or a
1148 else if (font_info
->font_encoder
)
1150 /* It's a program. */
1151 struct ccl_program
*ccl
= font_info
->font_encoder
;
1153 if (CHARSET_DIMENSION (charset
) == 1)
1155 ccl
->reg
[0] = CHARSET_ID (charset
);
1156 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1161 ccl
->reg
[0] = CHARSET_ID (charset
);
1162 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1163 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1166 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
1168 /* We assume that MSBs are appropriately set/reset by CCL
1170 if (!internal_two_byte_p
) /* 1-byte font */
1171 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
1173 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
1175 else if (font_info
->encoding_type
)
1177 /* Fixed encoding scheme. See fontset.h for the meaning of the
1178 encoding numbers. */
1179 unsigned char enc
= font_info
->encoding_type
;
1181 if ((enc
== 1 || enc
== 2)
1182 && CHARSET_DIMENSION (charset
) == 2)
1183 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
) | 0x80, XCHAR2B_BYTE2 (char2b
));
1185 if (enc
== 1 || enc
== 3 || (enc
== 4 && CHARSET_DIMENSION (charset
) == 1))
1186 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
) | 0x80);
1189 int code
= (int) (*char2b
);
1192 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
1197 *two_byte_p
= internal_two_byte_p
;
1200 return UNKNOWN_FONT
;
1201 else if (font
->bdf
&& CHARSET_DIMENSION (charset
) == 1)
1206 return UNICODE_FONT
;
1212 /* Return a char-table whose elements are t if the font FONT_INFO
1213 contains a glyph for the corresponding character, and nil if not.
1215 Fixme: For the moment, this function works only for fonts whose
1216 glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts). */
1219 x_get_font_repertory (f
, font_info
)
1221 struct font_info
*font_info
;
1223 XFontStruct
*font
= (XFontStruct
*) font_info
->font
;
1225 int min_byte1
, max_byte1
, min_byte2
, max_byte2
;
1227 struct charset
*charset
= CHARSET_FROM_ID (font_info
->charset
);
1228 int offset
= CHARSET_OFFSET (charset
);
1230 table
= Fmake_char_table (Qnil
, Qnil
);
1232 if (!font
->bdf
&& pfnGetFontUnicodeRanges
)
1235 DWORD glyphset_size
;
1236 HDC display
= get_frame_dc (f
);
1240 prev_font
= SelectObject (display
, font
->hfont
);
1242 /* First call GetFontUnicodeRanges to find out how big a structure
1244 glyphset_size
= pfnGetFontUnicodeRanges (display
, NULL
);
1247 glyphset
= (GLYPHSET
*) alloca (glyphset_size
);
1248 glyphset
->cbThis
= glyphset_size
;
1250 /* Now call it again to get the ranges. */
1251 glyphset_size
= pfnGetFontUnicodeRanges (display
, glyphset
);
1255 /* Store the ranges in TABLE. */
1256 for (i
= 0; i
< glyphset
->cRanges
; i
++)
1258 int from
= glyphset
->ranges
[i
].wcLow
;
1259 int to
= from
+ glyphset
->ranges
[i
].cGlyphs
- 1;
1260 char_table_set_range (table
, from
, to
, Qt
);
1265 SelectObject (display
, prev_font
);
1266 release_frame_dc (f
, display
);
1268 /* If we got the information we wanted above, then return it. */
1273 #if 0 /* TODO: Convert to work on Windows so BDF and older platforms work. */
1274 /* When GetFontUnicodeRanges is not available or does not work,
1275 work it out manually. */
1276 min_byte1
= font
->min_byte1
;
1277 max_byte1
= font
->max_byte1
;
1278 min_byte2
= font
->min_char_or_byte2
;
1279 max_byte2
= font
->max_char_or_byte2
;
1280 if (min_byte1
== 0 && max_byte1
== 0)
1282 if (! font
->per_char
|| font
->all_chars_exist
== True
)
1285 char_table_set_range (table
, offset
+ min_byte2
,
1286 offset
+ max_byte2
, Qt
);
1288 for (; min_byte2
<= max_byte2
; min_byte2
++)
1290 c
= DECODE_CHAR (charset
, min_byte2
);
1291 CHAR_TABLE_SET (table
, c
, Qt
);
1296 XCharStruct
*pcm
= font
->per_char
;
1300 for (i
= min_byte2
; i
<= max_byte2
; i
++, pcm
++)
1302 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
1307 char_table_set_range (table
, offset
+ from
,
1308 offset
+ i
- 1, Qt
);
1310 for (; from
< i
; from
++)
1312 c
= DECODE_CHAR (charset
, from
);
1313 CHAR_TABLE_SET (table
, c
, Qt
);
1324 char_table_set_range (table
, offset
+ from
, offset
+ i
- 1,
1327 for (; from
< i
; from
++)
1329 c
= DECODE_CHAR (charset
, from
);
1330 CHAR_TABLE_SET (table
, c
, Qt
);
1337 if (! font
->per_char
|| font
->all_chars_exist
== True
)
1342 for (i
= min_byte1
; i
<= max_byte1
; i
++)
1343 char_table_set_range
1344 (table
, offset
+ ((i
<< 8) | min_byte2
),
1345 offset
+ ((i
<< 8) | max_byte2
), Qt
);
1347 for (i
= min_byte1
; i
<= max_byte1
; i
++)
1348 for (j
= min_byte2
; j
<= max_byte2
; j
++)
1350 unsiged code
= (i
<< 8) | j
;
1351 c
= DECODE_CHAR (charset
, code
);
1352 CHAR_TABLE_SET (table
, c
, Qt
);
1357 XCharStruct
*pcm
= font
->per_char
;
1360 for (i
= min_byte1
; i
<= max_byte1
; i
++)
1365 for (j
= min_byte2
; j
<= max_byte2
; j
++, pcm
++)
1367 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
1372 char_table_set_range
1373 (table
, offset
+ ((i
<< 8) | from
),
1374 offset
+ ((i
<< 8) | (j
- 1)), Qt
);
1377 for (; from
< j
; from
++)
1379 unsigned code
= (i
<< 8) | from
;
1380 c
= ENCODE_CHAR (charset
, code
);
1381 CHAR_TABLE_SET (table
, c
, Qt
);
1393 char_table_set_range
1394 (table
, offset
+ ((i
<< 8) | from
),
1395 offset
+ ((i
<< 8) | (j
- 1)), Qt
);
1398 for (; from
< j
; from
++)
1400 unsigned code
= (i
<< 8) | from
;
1401 c
= DECODE_CHAR (charset
, code
);
1402 CHAR_TABLE_SET (table
, c
, Qt
);
1414 /***********************************************************************
1416 ***********************************************************************/
1419 /* Encapsulate the different ways of displaying text under W32. */
1422 w32_text_out (s
, x
, y
,chars
,nchars
)
1423 struct glyph_string
* s
;
1428 int charset_dim
= w32_font_is_double_byte (s
->font
) ? 2 : 1;
1430 w32_BDF_TextOut (s
->font
->bdf
, s
->hdc
,
1431 x
, y
, (char *) chars
, charset_dim
,
1432 nchars
* charset_dim
, 0);
1433 else if (s
->first_glyph
->font_type
== UNICODE_FONT
)
1434 ExtTextOutW (s
->hdc
, x
, y
, 0, NULL
, chars
, nchars
, NULL
);
1436 ExtTextOutA (s
->hdc
, x
, y
, 0, NULL
, (char *) chars
,
1437 nchars
* charset_dim
, NULL
);
1441 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1442 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1443 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1445 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1446 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1447 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1448 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1449 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1450 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1451 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1452 static int w32_alloc_lighter_color (struct frame
*, COLORREF
*, double, int);
1453 static void w32_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1454 double, int, COLORREF
));
1455 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1456 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1457 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1458 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1459 static void w32_draw_image_foreground_1
P_ ((struct glyph_string
*, HBITMAP
));
1460 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1462 static void w32_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1463 int, int, int, int, int, int,
1465 static void w32_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1466 int, int, int, RECT
*));
1469 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1473 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1478 struct glyph_string
*s
;
1480 if (s
->font
== FRAME_FONT (s
->f
)
1481 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1482 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1484 s
->gc
= s
->f
->output_data
.w32
->cursor_gc
;
1487 /* Cursor on non-default face: must merge. */
1491 xgcv
.background
= s
->f
->output_data
.w32
->cursor_pixel
;
1492 xgcv
.foreground
= s
->face
->background
;
1494 /* If the glyph would be invisible, try a different foreground. */
1495 if (xgcv
.foreground
== xgcv
.background
)
1496 xgcv
.foreground
= s
->face
->foreground
;
1497 if (xgcv
.foreground
== xgcv
.background
)
1498 xgcv
.foreground
= s
->f
->output_data
.w32
->cursor_foreground_pixel
;
1499 if (xgcv
.foreground
== xgcv
.background
)
1500 xgcv
.foreground
= s
->face
->foreground
;
1502 /* Make sure the cursor is distinct from text in this face. */
1503 if (xgcv
.background
== s
->face
->background
1504 && xgcv
.foreground
== s
->face
->foreground
)
1506 xgcv
.background
= s
->face
->foreground
;
1507 xgcv
.foreground
= s
->face
->background
;
1510 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1511 xgcv
.font
= s
->font
;
1512 mask
= GCForeground
| GCBackground
| GCFont
;
1514 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1515 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1518 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1519 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1521 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1526 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1529 x_set_mouse_face_gc (s
)
1530 struct glyph_string
*s
;
1535 /* What face has to be used last for the mouse face? */
1536 face_id
= FRAME_W32_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1537 face
= FACE_FROM_ID (s
->f
, face_id
);
1539 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1541 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1542 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1544 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1545 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1546 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1548 /* If font in this face is same as S->font, use it. */
1549 if (s
->font
== s
->face
->font
)
1550 s
->gc
= s
->face
->gc
;
1551 #ifdef USE_FONT_BACKEND
1552 else if (enable_font_backend
)
1553 /* No need of setting a font for s->gc. */
1554 s
->gc
= s
->face
->gc
;
1555 #endif /* USE_FONT_BACKEND */
1558 /* Otherwise construct scratch_cursor_gc with values from FACE
1563 xgcv
.background
= s
->face
->background
;
1564 xgcv
.foreground
= s
->face
->foreground
;
1565 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1566 xgcv
.font
= s
->font
;
1567 mask
= GCForeground
| GCBackground
| GCFont
;
1569 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1570 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1573 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1574 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1576 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1579 xassert (s
->gc
!= 0);
1583 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1584 Faces to use in the mode line have already been computed when the
1585 matrix was built, so there isn't much to do, here. */
1588 x_set_mode_line_face_gc (s
)
1589 struct glyph_string
*s
;
1591 s
->gc
= s
->face
->gc
;
1595 /* Set S->gc of glyph string S for drawing that glyph string. Set
1596 S->stippled_p to a non-zero value if the face of S has a stipple
1600 x_set_glyph_string_gc (s
)
1601 struct glyph_string
*s
;
1603 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1605 if (s
->hl
== DRAW_NORMAL_TEXT
)
1607 s
->gc
= s
->face
->gc
;
1608 s
->stippled_p
= s
->face
->stipple
!= 0;
1610 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1612 x_set_mode_line_face_gc (s
);
1613 s
->stippled_p
= s
->face
->stipple
!= 0;
1615 else if (s
->hl
== DRAW_CURSOR
)
1617 x_set_cursor_gc (s
);
1620 else if (s
->hl
== DRAW_MOUSE_FACE
)
1622 x_set_mouse_face_gc (s
);
1623 s
->stippled_p
= s
->face
->stipple
!= 0;
1625 else if (s
->hl
== DRAW_IMAGE_RAISED
1626 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1628 s
->gc
= s
->face
->gc
;
1629 s
->stippled_p
= s
->face
->stipple
!= 0;
1633 s
->gc
= s
->face
->gc
;
1634 s
->stippled_p
= s
->face
->stipple
!= 0;
1637 /* GC must have been set. */
1638 xassert (s
->gc
!= 0);
1642 /* Set clipping for output of glyph string S. S may be part of a mode
1643 line or menu if we don't have X toolkit support. */
1646 x_set_glyph_string_clipping (s
)
1647 struct glyph_string
*s
;
1650 get_glyph_string_clip_rect (s
, &r
);
1651 w32_set_clip_rectangle (s
->hdc
, &r
);
1652 #ifdef USE_FONT_BACKEND
1653 s
->clip_x
= r
.left
, s
->clip_y
= r
.top
;
1654 s
->clip_width
= r
.right
- r
.left
, s
->clip_height
= r
.bottom
- r
.top
;
1655 #endif /* USE_FONT_BACKEND */
1658 /* Set SRC's clipping for output of glyph string DST. This is called
1659 when we are drawing DST's left_overhang or right_overhang only in
1663 x_set_glyph_string_clipping_exactly (src
, dst
)
1664 struct glyph_string
*src
, *dst
;
1668 #ifdef USE_FONT_BACKEND
1669 if (enable_font_backend
)
1671 r
.left
= dst
->clip_x
= src
->x
;
1672 r
.right
= r
.left
+ (dst
->clip_width
= src
->width
);
1673 r
.top
= dst
->clip_y
= src
->y
;
1674 r
.bottom
= r
.top
+ (dst
->clip_height
= src
->height
);
1678 #endif /* USE_FONT_BACKEND */
1679 struct glyph_string
*clip_head
= src
->clip_head
;
1680 struct glyph_string
*clip_tail
= src
->clip_tail
;
1682 /* This foces clipping just this glyph string. */
1683 src
->clip_head
= src
->clip_tail
= src
;
1684 get_glyph_string_clip_rect (src
, &r
);
1685 src
->clip_head
= clip_head
, src
->clip_tail
= clip_tail
;
1686 #ifdef USE_FONT_BACKEND
1688 #endif /* USE_FONT_BACKEND */
1689 w32_set_clip_rectangle (dst
->hdc
, &r
);
1693 Compute left and right overhang of glyph string S. If S is a glyph
1694 string for a composition, assume overhangs don't exist. */
1697 w32_compute_glyph_string_overhangs (s
)
1698 struct glyph_string
*s
;
1700 /* TODO: Windows does not appear to have a method for
1701 getting this info without getting the ABC widths for each
1702 individual character and working it out manually. */
1707 w32_get_glyph_overhangs (glyph
, f
, left
, right
)
1708 struct glyph
*glyph
;
1712 HDC hdc
= get_frame_dc (f
);
1713 /* Convert to unicode! */
1714 x_get_glyph_overhangs (glyph
, f
, left
, right
);
1715 release_frame_dc (f
, hdc
);
1719 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1722 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1723 struct glyph_string
*s
;
1731 /* Take clipping into account. */
1732 if (s
->gc
->clip_mask
== Rect
)
1734 real_x
= max (real_x
, s
->gc
->clip_rectangle
.left
);
1735 real_y
= max (real_y
, s
->gc
->clip_rectangle
.top
);
1736 real_w
= min (real_w
, s
->gc
->clip_rectangle
.right
1737 - s
->gc
->clip_rectangle
.left
);
1738 real_h
= min (real_h
, s
->gc
->clip_rectangle
.bottom
1739 - s
->gc
->clip_rectangle
.top
);
1742 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->background
, real_x
, real_y
,
1747 /* Draw the background of glyph_string S. If S->background_filled_p
1748 is non-zero don't draw it. FORCE_P non-zero means draw the
1749 background even if it wouldn't be drawn normally. This is used
1750 when a string preceding S draws into the background of S, or S
1751 contains the first component of a composition. */
1754 x_draw_glyph_string_background (s
, force_p
)
1755 struct glyph_string
*s
;
1758 /* Nothing to do if background has already been drawn or if it
1759 shouldn't be drawn in the first place. */
1760 if (!s
->background_filled_p
)
1762 int box_line_width
= max (s
->face
->box_line_width
, 0);
1764 #if 0 /* TODO: stipple */
1767 /* Fill background with a stipple pattern. */
1768 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1769 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1770 s
->y
+ box_line_width
,
1771 s
->background_width
,
1772 s
->height
- 2 * box_line_width
);
1773 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1774 s
->background_filled_p
= 1;
1778 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1779 || s
->font_not_found_p
1780 || s
->extends_to_end_of_line_p
1784 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1785 s
->background_width
,
1786 s
->height
- 2 * box_line_width
);
1787 s
->background_filled_p
= 1;
1793 /* Draw the foreground of glyph string S. */
1796 x_draw_glyph_string_foreground (s
)
1797 struct glyph_string
*s
;
1802 /* If first glyph of S has a left box line, start drawing the text
1803 of S to the right of that box line. */
1804 if (s
->face
->box
!= FACE_NO_BOX
1805 && s
->first_glyph
->left_box_line_p
)
1806 x
= s
->x
+ abs (s
->face
->box_line_width
);
1810 if (s
->for_overlaps
|| (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1811 SetBkMode (s
->hdc
, TRANSPARENT
);
1813 SetBkMode (s
->hdc
, OPAQUE
);
1815 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1816 SetBkColor (s
->hdc
, s
->gc
->background
);
1817 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1819 if (s
->font
&& s
->font
->hfont
)
1820 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1822 /* Draw characters of S as rectangles if S's font could not be
1824 if (s
->font_not_found_p
)
1826 for (i
= 0; i
< s
->nchars
; ++i
)
1828 struct glyph
*g
= s
->first_glyph
+ i
;
1830 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1832 x
+= g
->pixel_width
;
1835 #ifdef USE_FONT_BACKEND
1836 else if (enable_font_backend
)
1838 int boff
= s
->font_info
->baseline_offset
;
1839 struct font
*font
= (struct font
*) s
->font_info
;
1842 if (s
->font_info
->vertical_centering
)
1843 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1845 y
= s
->ybase
- boff
;
1847 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1848 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 0);
1850 font
->driver
->draw (s
, 0, s
->nchars
, x
, y
, 1);
1851 if (s
->face
->overstrike
)
1852 font
->driver
->draw (s
, 0, s
->nchars
, x
+ 1, y
, 0);
1854 #endif /* USE_FONT_BACKEND */
1857 char *char1b
= (char *) s
->char2b
;
1858 int boff
= s
->font_info
->baseline_offset
;
1860 if (s
->font_info
->vertical_centering
)
1861 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1863 /* If we can use 8-bit functions, condense S->char2b. */
1865 for (i
= 0; i
< s
->nchars
; ++i
)
1866 char1b
[i
] = XCHAR2B_BYTE2 (&s
->char2b
[i
]);
1868 /* Draw text with TextOut and friends. */
1869 w32_text_out (s
, x
, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1871 if (s
->face
->overstrike
)
1873 /* For overstriking (to simulate bold-face), draw the
1874 characters again shifted to the right by one pixel. */
1875 int old_BkMode
= SetBkMode (s
->hdc
, TRANSPARENT
);
1876 w32_text_out (s
, x
+ 1, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1877 if (old_BkMode
&& old_BkMode
!= TRANSPARENT
)
1878 SetBkMode (s
->hdc
, old_BkMode
);
1881 if (s
->font
&& s
->font
->hfont
)
1882 SelectObject (s
->hdc
, old_font
);
1885 /* Draw the foreground of composite glyph string S. */
1888 x_draw_composite_glyph_string_foreground (s
)
1889 struct glyph_string
*s
;
1894 /* If first glyph of S has a left box line, start drawing the text
1895 of S to the right of that box line. */
1896 if (s
->face
&& s
->face
->box
!= FACE_NO_BOX
1897 && s
->first_glyph
->left_box_line_p
)
1898 x
= s
->x
+ abs (s
->face
->box_line_width
);
1902 /* S is a glyph string for a composition. S->gidx is the index of
1903 the first character drawn for glyphs of this composition.
1904 S->gidx == 0 means we are drawing the very first character of
1905 this composition. */
1907 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1908 SetBkColor (s
->hdc
, s
->gc
->background
);
1909 SetBkMode (s
->hdc
, TRANSPARENT
);
1910 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1912 if (s
->font
&& s
->font
->hfont
)
1913 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1915 /* Draw a rectangle for the composition if the font for the very
1916 first character of the composition could not be loaded. */
1917 if (s
->font_not_found_p
)
1920 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, s
->width
- 1,
1923 #ifdef USE_FONT_BACKEND
1924 else if (enable_font_backend
)
1926 struct font
*font
= (struct font
*) s
->font_info
;
1930 if (s
->cmp
->method
== COMPOSITION_WITH_GLYPH_STRING
)
1932 Lisp_Object gstring
= AREF (XHASH_TABLE (composition_hash_table
)
1934 s
->cmp
->hash_index
* 2);
1937 for (i
= from
= 0; i
< s
->nchars
; i
++)
1939 Lisp_Object g
= LGSTRING_GLYPH (gstring
, i
);
1940 Lisp_Object adjustment
= LGLYPH_ADJUSTMENT (g
);
1941 int xoff
, yoff
, wadjust
;
1943 if (! VECTORP (adjustment
))
1945 width
+= XINT (LGLYPH_WIDTH (g
));
1950 font
->driver
->draw (s
, from
, i
, x
, y
, 0);
1953 xoff
= XINT (AREF (adjustment
, 0));
1954 yoff
= XINT (AREF (adjustment
, 1));
1955 wadjust
= XINT (AREF (adjustment
, 2));
1957 font
->driver
->draw (s
, i
, i
+ 1, x
+ xoff
, y
+ yoff
, 0);
1958 x
+= XINT (LGLYPH_WIDTH (g
)) + wadjust
;
1963 font
->driver
->draw (s
, from
, i
, x
, y
, 0);
1967 for (i
= 0, j
= s
->gidx
; i
< s
->nchars
; i
++, j
++)
1968 if (COMPOSITION_GLYPH (s
->cmp
, j
) != '\t')
1970 int xx
= x
+ s
->cmp
->offsets
[j
* 2];
1971 int yy
= y
- s
->cmp
->offsets
[j
* 2 + 1];
1973 font
->driver
->draw (s
, j
, j
+ 1, xx
, yy
, 0);
1974 if (s
->face
->overstrike
)
1975 font
->driver
->draw (s
, j
, j
+ 1, xx
+ 1, yy
, 0);
1979 #endif /* USE_FONT_BACKEND */
1982 for (i
= 0, j
= s
->gidx
; i
< s
->nchars
; i
++, j
++)
1985 w32_text_out (s
, x
+ s
->cmp
->offsets
[j
* 2],
1986 s
->ybase
- s
->cmp
->offsets
[j
* 2 + 1],
1988 if (s
->face
->overstrike
)
1989 w32_text_out (s
, x
+ s
->cmp
->offsets
[j
* 2] + 1,
1990 s
->ybase
- s
->cmp
->offsets
[j
+ 1],
1995 if (s
->font
&& s
->font
->hfont
)
1996 SelectObject (s
->hdc
, old_font
);
2000 /* Brightness beyond which a color won't have its highlight brightness
2003 Nominally, highlight colors for `3d' faces are calculated by
2004 brightening an object's color by a constant scale factor, but this
2005 doesn't yield good results for dark colors, so for colors who's
2006 brightness is less than this value (on a scale of 0-255) have to
2007 use an additional additive factor.
2009 The value here is set so that the default menu-bar/mode-line color
2010 (grey75) will not have its highlights changed at all. */
2011 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2014 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2015 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2016 If this produces the same color as COLOR, try a color where all RGB
2017 values have DELTA added. Return the allocated color in *COLOR.
2018 DISPLAY is the X display, CMAP is the colormap to operate on.
2019 Value is non-zero if successful. */
2022 w32_alloc_lighter_color (f
, color
, factor
, delta
)
2031 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
2034 /* Change RGB values by specified FACTOR. Avoid overflow! */
2035 xassert (factor
>= 0);
2036 new = PALETTERGB (min (0xff, factor
* GetRValue (*color
)),
2037 min (0xff, factor
* GetGValue (*color
)),
2038 min (0xff, factor
* GetBValue (*color
)));
2040 /* Calculate brightness of COLOR. */
2041 bright
= (2 * GetRValue (*color
) + 3 * GetGValue (*color
)
2042 + GetBValue (*color
)) / 6;
2044 /* We only boost colors that are darker than
2045 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2046 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2047 /* Make an additive adjustment to NEW, because it's dark enough so
2048 that scaling by FACTOR alone isn't enough. */
2050 /* How far below the limit this color is (0 - 1, 1 being darker). */
2051 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2052 /* The additive adjustment. */
2053 int min_delta
= delta
* dimness
* factor
/ 2;
2056 new = PALETTERGB (max (0, min (0xff, min_delta
- GetRValue (*color
))),
2057 max (0, min (0xff, min_delta
- GetGValue (*color
))),
2058 max (0, min (0xff, min_delta
- GetBValue (*color
))));
2060 new = PALETTERGB (max (0, min (0xff, min_delta
+ GetRValue (*color
))),
2061 max (0, min (0xff, min_delta
+ GetGValue (*color
))),
2062 max (0, min (0xff, min_delta
+ GetBValue (*color
))));
2066 new = PALETTERGB (max (0, min (0xff, delta
+ GetRValue (*color
))),
2067 max (0, min (0xff, delta
+ GetGValue (*color
))),
2068 max (0, min (0xff, delta
+ GetBValue (*color
))));
2070 /* TODO: Map to palette and retry with delta if same? */
2071 /* TODO: Free colors (if using palette)? */
2082 /* Set up the foreground color for drawing relief lines of glyph
2083 string S. RELIEF is a pointer to a struct relief containing the GC
2084 with which lines will be drawn. Use a color that is FACTOR or
2085 DELTA lighter or darker than the relief's background which is found
2086 in S->f->output_data.x->relief_background. If such a color cannot
2087 be allocated, use DEFAULT_PIXEL, instead. */
2090 w32_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2092 struct relief
*relief
;
2095 COLORREF default_pixel
;
2098 struct w32_output
*di
= f
->output_data
.w32
;
2099 unsigned long mask
= GCForeground
;
2101 COLORREF background
= di
->relief_background
;
2102 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
2104 /* TODO: Free colors (if using palette)? */
2106 /* Allocate new color. */
2107 xgcv
.foreground
= default_pixel
;
2109 if (w32_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2111 relief
->allocated_p
= 1;
2112 xgcv
.foreground
= relief
->pixel
= pixel
;
2115 if (relief
->gc
== 0)
2117 #if 0 /* TODO: stipple */
2118 xgcv
.stipple
= dpyinfo
->gray
;
2121 relief
->gc
= XCreateGC (NULL
, FRAME_W32_WINDOW (f
), mask
, &xgcv
);
2124 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2128 /* Set up colors for the relief lines around glyph string S. */
2131 x_setup_relief_colors (s
)
2132 struct glyph_string
*s
;
2134 struct w32_output
*di
= s
->f
->output_data
.w32
;
2137 if (s
->face
->use_box_color_for_shadows_p
)
2138 color
= s
->face
->box_color
;
2139 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2141 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2142 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2144 color
= s
->gc
->background
;
2146 if (di
->white_relief
.gc
== 0
2147 || color
!= di
->relief_background
)
2149 di
->relief_background
= color
;
2150 w32_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2151 WHITE_PIX_DEFAULT (s
->f
));
2152 w32_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2153 BLACK_PIX_DEFAULT (s
->f
));
2158 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2159 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2160 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2161 relief. LEFT_P non-zero means draw a relief on the left side of
2162 the rectangle. RIGHT_P non-zero means draw a relief on the right
2163 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2167 w32_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2168 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2170 int left_x
, top_y
, right_x
, bottom_y
, width
;
2171 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2176 HDC hdc
= get_frame_dc (f
);
2179 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
2181 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
2183 w32_set_clip_rectangle (hdc
, clip_rect
);
2187 for (i
= 0; i
< width
; ++i
)
2188 w32_fill_area (f
, hdc
, gc
.foreground
,
2189 left_x
+ i
* left_p
, top_y
+ i
,
2190 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
2194 for (i
= 0; i
< width
; ++i
)
2195 w32_fill_area (f
, hdc
, gc
.foreground
,
2196 left_x
+ i
, top_y
+ i
, 1,
2197 bottom_y
- top_y
- 2 * i
+ 1);
2200 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
2202 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
2206 for (i
= 0; i
< width
; ++i
)
2207 w32_fill_area (f
, hdc
, gc
.foreground
,
2208 left_x
+ i
* left_p
, bottom_y
- i
,
2209 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
2213 for (i
= 0; i
< width
; ++i
)
2214 w32_fill_area (f
, hdc
, gc
.foreground
,
2215 right_x
- i
, top_y
+ i
+ 1, 1,
2216 bottom_y
- top_y
- 2 * i
- 1);
2218 w32_set_clip_rectangle (hdc
, NULL
);
2220 release_frame_dc (f
, hdc
);
2224 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2225 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2226 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2227 left side of the rectangle. RIGHT_P non-zero means draw a line
2228 on the right side of the rectangle. CLIP_RECT is the clipping
2229 rectangle to use when drawing. */
2232 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2233 left_p
, right_p
, clip_rect
)
2234 struct glyph_string
*s
;
2235 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2238 w32_set_clip_rectangle (s
->hdc
, clip_rect
);
2241 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2242 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2247 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2248 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2252 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2253 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2258 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2259 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2262 w32_set_clip_rectangle (s
->hdc
, NULL
);
2266 /* Draw a box around glyph string S. */
2269 x_draw_glyph_string_box (s
)
2270 struct glyph_string
*s
;
2272 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2273 int left_p
, right_p
;
2274 struct glyph
*last_glyph
;
2277 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2278 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2279 : window_box_right (s
->w
, s
->area
));
2281 /* The glyph that may have a right box line. */
2282 last_glyph
= (s
->cmp
|| s
->img
2284 : s
->first_glyph
+ s
->nchars
- 1);
2286 width
= abs (s
->face
->box_line_width
);
2287 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2289 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2291 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2293 bottom_y
= top_y
+ s
->height
- 1;
2295 left_p
= (s
->first_glyph
->left_box_line_p
2296 || (s
->hl
== DRAW_MOUSE_FACE
2298 || s
->prev
->hl
!= s
->hl
)));
2299 right_p
= (last_glyph
->right_box_line_p
2300 || (s
->hl
== DRAW_MOUSE_FACE
2302 || s
->next
->hl
!= s
->hl
)));
2304 get_glyph_string_clip_rect (s
, &clip_rect
);
2306 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2307 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2308 left_p
, right_p
, &clip_rect
);
2311 x_setup_relief_colors (s
);
2312 w32_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2313 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2318 /* Draw foreground of image glyph string S. */
2321 x_draw_image_foreground (s
)
2322 struct glyph_string
*s
;
2325 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2327 /* If first glyph of S has a left box line, start drawing it to the
2328 right of that line. */
2329 if (s
->face
->box
!= FACE_NO_BOX
2330 && s
->first_glyph
->left_box_line_p
2332 x
+= abs (s
->face
->box_line_width
);
2334 /* If there is a margin around the image, adjust x- and y-position
2336 if (s
->slice
.x
== 0)
2337 x
+= s
->img
->hmargin
;
2338 if (s
->slice
.y
== 0)
2339 y
+= s
->img
->vmargin
;
2345 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2346 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2347 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2348 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2349 SetBkColor (compat_hdc
, RGB (255, 255, 255));
2350 SetTextColor (s
->hdc
, RGB (0, 0, 0));
2351 x_set_glyph_string_clipping (s
);
2355 HDC mask_dc
= CreateCompatibleDC (s
->hdc
);
2356 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2358 SetTextColor (s
->hdc
, RGB (255, 255, 255));
2359 SetBkColor (s
->hdc
, RGB (0, 0, 0));
2361 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2362 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2363 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2364 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2365 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2366 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2368 SelectObject (mask_dc
, mask_orig_obj
);
2373 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2374 SetBkColor (s
->hdc
, s
->gc
->background
);
2376 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2377 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2379 /* When the image has a mask, we can expect that at
2380 least part of a mouse highlight or a block cursor will
2381 be visible. If the image doesn't have a mask, make
2382 a block cursor visible by drawing a rectangle around
2383 the image. I believe it's looking better if we do
2384 nothing here for mouse-face. */
2385 if (s
->hl
== DRAW_CURSOR
)
2387 int r
= s
->img
->relief
;
2389 w32_draw_rectangle (s
->hdc
, s
->gc
, x
- r
, y
- r
,
2390 s
->slice
.width
+ r
*2 - 1,
2391 s
->slice
.height
+ r
*2 - 1);
2395 w32_set_clip_rectangle (s
->hdc
, NULL
);
2396 SelectObject (s
->hdc
, orig_brush
);
2397 DeleteObject (fg_brush
);
2398 SelectObject (compat_hdc
, orig_obj
);
2399 DeleteDC (compat_hdc
);
2402 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, y
,
2403 s
->slice
.width
- 1, s
->slice
.height
- 1);
2405 RestoreDC (s
->hdc
,-1);
2409 /* Draw a relief around the image glyph string S. */
2412 x_draw_image_relief (s
)
2413 struct glyph_string
*s
;
2415 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2418 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2420 /* If first glyph of S has a left box line, start drawing it to the
2421 right of that line. */
2422 if (s
->face
->box
!= FACE_NO_BOX
2423 && s
->first_glyph
->left_box_line_p
2425 x
+= abs (s
->face
->box_line_width
);
2427 /* If there is a margin around the image, adjust x- and y-position
2429 if (s
->slice
.x
== 0)
2430 x
+= s
->img
->hmargin
;
2431 if (s
->slice
.y
== 0)
2432 y
+= s
->img
->vmargin
;
2434 if (s
->hl
== DRAW_IMAGE_SUNKEN
2435 || s
->hl
== DRAW_IMAGE_RAISED
)
2437 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2438 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2442 thick
= abs (s
->img
->relief
);
2443 raised_p
= s
->img
->relief
> 0;
2448 x1
= x
+ s
->slice
.width
+ thick
- 1;
2449 y1
= y
+ s
->slice
.height
+ thick
- 1;
2451 x_setup_relief_colors (s
);
2452 get_glyph_string_clip_rect (s
, &r
);
2453 w32_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2455 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2457 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2462 /* Draw the foreground of image glyph string S to PIXMAP. */
2465 w32_draw_image_foreground_1 (s
, pixmap
)
2466 struct glyph_string
*s
;
2469 HDC hdc
= CreateCompatibleDC (s
->hdc
);
2470 HGDIOBJ orig_hdc_obj
= SelectObject (hdc
, pixmap
);
2472 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2474 /* If first glyph of S has a left box line, start drawing it to the
2475 right of that line. */
2476 if (s
->face
->box
!= FACE_NO_BOX
2477 && s
->first_glyph
->left_box_line_p
2479 x
+= abs (s
->face
->box_line_width
);
2481 /* If there is a margin around the image, adjust x- and y-position
2483 if (s
->slice
.x
== 0)
2484 x
+= s
->img
->hmargin
;
2485 if (s
->slice
.y
== 0)
2486 y
+= s
->img
->vmargin
;
2490 HDC compat_hdc
= CreateCompatibleDC (hdc
);
2491 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2492 HBRUSH orig_brush
= SelectObject (hdc
, fg_brush
);
2493 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2497 HDC mask_dc
= CreateCompatibleDC (hdc
);
2498 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2500 SetTextColor (hdc
, RGB (0, 0, 0));
2501 SetBkColor (hdc
, RGB (255, 255, 255));
2502 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2503 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2504 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2505 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2506 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2507 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2509 SelectObject (mask_dc
, mask_orig_obj
);
2514 SetTextColor (hdc
, s
->gc
->foreground
);
2515 SetBkColor (hdc
, s
->gc
->background
);
2517 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2518 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2520 /* When the image has a mask, we can expect that at
2521 least part of a mouse highlight or a block cursor will
2522 be visible. If the image doesn't have a mask, make
2523 a block cursor visible by drawing a rectangle around
2524 the image. I believe it's looking better if we do
2525 nothing here for mouse-face. */
2526 if (s
->hl
== DRAW_CURSOR
)
2528 int r
= s
->img
->relief
;
2530 w32_draw_rectangle (hdc
, s
->gc
, x
- r
, y
- r
,
2531 s
->slice
.width
+ r
*2 - 1,
2532 s
->slice
.height
+ r
*2 - 1);
2536 SelectObject (hdc
, orig_brush
);
2537 DeleteObject (fg_brush
);
2538 SelectObject (compat_hdc
, orig_obj
);
2539 DeleteDC (compat_hdc
);
2542 w32_draw_rectangle (hdc
, s
->gc
, x
, y
,
2543 s
->slice
.width
- 1, s
->slice
.height
- 1);
2545 SelectObject (hdc
, orig_hdc_obj
);
2550 /* Draw part of the background of glyph string S. X, Y, W, and H
2551 give the rectangle to draw. */
2554 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2555 struct glyph_string
*s
;
2558 #if 0 /* TODO: stipple */
2561 /* Fill background with a stipple pattern. */
2562 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2563 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2564 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2568 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2572 /* Draw image glyph string S.
2575 s->x +-------------------------
2578 | +-------------------------
2581 | | +-------------------
2587 x_draw_image_glyph_string (s
)
2588 struct glyph_string
*s
;
2591 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2592 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2596 height
= s
->height
- 2 * box_line_vwidth
;
2598 /* Fill background with face under the image. Do it only if row is
2599 taller than image or if image has a clip mask to reduce
2601 s
->stippled_p
= s
->face
->stipple
!= 0;
2602 if (height
> s
->slice
.height
2606 || s
->img
->pixmap
== 0
2607 || s
->width
!= s
->background_width
)
2610 if (s
->first_glyph
->left_box_line_p
2612 x
+= box_line_hwidth
;
2615 if (s
->slice
.y
== 0)
2616 y
+= box_line_vwidth
;
2618 #if 0 /* TODO: figure out if we need to do this on Windows. */
2621 /* Create a pixmap as large as the glyph string. Fill it
2622 with the background color. Copy the image to it, using
2623 its mask. Copy the temporary pixmap to the display. */
2624 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2625 int depth
= DefaultDepthOfScreen (screen
);
2627 /* Create a pixmap as large as the glyph string. */
2628 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2629 s
->background_width
,
2632 /* Don't clip in the following because we're working on the
2634 XSetClipMask (s
->display
, s
->gc
, None
);
2636 /* Fill the pixmap with the background color/stipple. */
2639 /* Fill background with a stipple pattern. */
2640 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2641 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2642 0, 0, s
->background_width
, s
->height
);
2643 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2648 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2650 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2651 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2652 0, 0, s
->background_width
, s
->height
);
2653 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2658 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2660 s
->background_filled_p
= 1;
2663 /* Draw the foreground. */
2666 w32_draw_image_foreground_1 (s
, pixmap
);
2667 x_set_glyph_string_clipping (s
);
2669 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2670 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2671 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2672 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, pixmap
);
2674 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2675 SetBkColor (s
->hdc
, s
->gc
->background
);
2676 BitBlt (s
->hdc
, s
->x
, s
->y
, s
->background_width
, s
->height
,
2677 compat_hdc
, 0, 0, SRCCOPY
);
2679 SelectObject (s
->hdc
, orig_brush
);
2680 DeleteObject (fg_brush
);
2681 SelectObject (compat_hdc
, orig_obj
);
2682 DeleteDC (compat_hdc
);
2684 DeleteObject (pixmap
);
2688 x_draw_image_foreground (s
);
2690 /* If we must draw a relief around the image, do it. */
2692 || s
->hl
== DRAW_IMAGE_RAISED
2693 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2694 x_draw_image_relief (s
);
2698 /* Draw stretch glyph string S. */
2701 x_draw_stretch_glyph_string (s
)
2702 struct glyph_string
*s
;
2704 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2705 s
->stippled_p
= s
->face
->stipple
!= 0;
2707 if (s
->hl
== DRAW_CURSOR
2708 && !x_stretch_cursor_p
)
2710 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2711 as wide as the stretch glyph. */
2712 int width
, background_width
= s
->background_width
;
2713 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2717 background_width
-= left_x
- x
;
2720 width
= min (FRAME_COLUMN_WIDTH (s
->f
), background_width
);
2723 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, width
, s
->height
);
2725 /* Clear rest using the GC of the original non-cursor face. */
2726 if (width
< background_width
)
2728 XGCValues
*gc
= s
->face
->gc
;
2730 int w
= background_width
- width
, h
= s
->height
;
2735 if (s
->row
->mouse_face_p
2736 && cursor_in_mouse_face_p (s
->w
))
2738 x_set_mouse_face_gc (s
);
2744 get_glyph_string_clip_rect (s
, &r
);
2745 w32_set_clip_rectangle (hdc
, &r
);
2747 #if 0 /* TODO: stipple */
2748 if (s
->face
->stipple
)
2750 /* Fill background with a stipple pattern. */
2751 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2752 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2753 XSetFillStyle (s
->display
, gc
, FillSolid
);
2758 w32_fill_area (s
->f
, s
->hdc
, gc
->background
, x
, y
, w
, h
);
2762 else if (!s
->background_filled_p
)
2764 int background_width
= s
->background_width
;
2765 int x
= s
->x
, left_x
= window_box_left_offset (s
->w
, TEXT_AREA
);
2767 /* Don't draw into left margin, fringe or scrollbar area
2768 except for header line and mode line. */
2769 if (x
< left_x
&& !s
->row
->mode_line_p
)
2771 background_width
-= left_x
- x
;
2774 if (background_width
> 0)
2775 x_draw_glyph_string_bg_rect (s
, x
, s
->y
, background_width
, s
->height
);
2778 s
->background_filled_p
= 1;
2782 /* Draw glyph string S. */
2785 x_draw_glyph_string (s
)
2786 struct glyph_string
*s
;
2788 int relief_drawn_p
= 0;
2790 /* If S draws into the background of its successor, draw the
2791 background of the successor first so that S can draw into it.
2792 This makes S->next use XDrawString instead of XDrawImageString. */
2793 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
)
2796 struct glyph_string
*next
;
2797 for (width
= 0, next
= s
->next
; next
;
2798 width
+= next
->width
, next
= next
->next
)
2799 if (next
->first_glyph
->type
!= IMAGE_GLYPH
)
2801 x_set_glyph_string_gc (next
);
2802 x_set_glyph_string_clipping (next
);
2803 x_draw_glyph_string_background (next
, 1);
2804 #ifdef USE_FONT_BACKEND
2805 next
->clip_width
= 0;
2806 #endif /* USE_FONT_BACKEND */
2810 /* Set up S->gc, set clipping and draw S. */
2811 x_set_glyph_string_gc (s
);
2813 /* Draw relief (if any) in advance for char/composition so that the
2814 glyph string can be drawn over it. */
2815 if (!s
->for_overlaps
2816 && s
->face
->box
!= FACE_NO_BOX
2817 && (s
->first_glyph
->type
== CHAR_GLYPH
2818 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2821 x_set_glyph_string_clipping (s
);
2822 x_draw_glyph_string_background (s
, 1);
2823 x_draw_glyph_string_box (s
);
2824 x_set_glyph_string_clipping (s
);
2827 else if ((s
->prev
&& s
->prev
->hl
!= s
->hl
&& s
->left_overhang
)
2828 || (s
->next
&& s
->next
->hl
!= s
->hl
&& s
->right_overhang
))
2829 /* We must clip just this glyph. left_overhang part has already
2830 drawn when s->prev was drawn, and right_overhang part will be
2831 drawn later when s->next is drawn. */
2832 x_set_glyph_string_clipping_exactly (s
, s
);
2834 x_set_glyph_string_clipping (s
);
2836 switch (s
->first_glyph
->type
)
2839 x_draw_image_glyph_string (s
);
2843 x_draw_stretch_glyph_string (s
);
2847 if (s
->for_overlaps
)
2848 s
->background_filled_p
= 1;
2850 x_draw_glyph_string_background (s
, 0);
2851 x_draw_glyph_string_foreground (s
);
2854 case COMPOSITE_GLYPH
:
2855 if (s
->for_overlaps
|| s
->gidx
> 0)
2856 s
->background_filled_p
= 1;
2858 x_draw_glyph_string_background (s
, 1);
2859 x_draw_composite_glyph_string_foreground (s
);
2866 if (!s
->for_overlaps
)
2868 /* Draw underline. */
2869 if (s
->face
->underline_p
2870 && (s
->font
->bdf
|| !s
->font
->tm
.tmUnderlined
))
2874 /* Get the underline thickness. Default is 1 pixel. */
2875 #ifdef USE_FONT_BACKEND
2876 if (enable_font_backend
)
2877 /* In the future, we must use information of font. */
2880 #endif /* USE_FONT_BACKEND */
2883 #ifdef USE_FONT_BACKEND
2884 if (enable_font_backend
)
2887 /* In the future, we must use information of font. */
2888 y
= s
->ybase
+ (s
->face
->font
->max_bounds
.descent
+ 1) / 2;
2890 y
= s
->y
+ s
->height
- h
;
2895 y
= s
->y
+ s
->height
- h
;
2896 /* TODO: Use font information for positioning and
2897 thickness of underline. See OUTLINETEXTMETRIC,
2898 and xterm.c. Note: If you make this work,
2899 don't forget to change the doc string of
2900 x-use-underline_color-position-properties
2903 if (!x_underline_at_descent_line
)
2909 if (s
->face
->underline_defaulted_p
)
2911 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2912 y
, s
->background_width
, 1);
2916 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2917 y
, s
->background_width
, 1);
2920 /* Draw overline. */
2921 if (s
->face
->overline_p
)
2923 unsigned long dy
= 0, h
= 1;
2925 if (s
->face
->overline_color_defaulted_p
)
2927 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2928 s
->y
+ dy
, s
->background_width
, h
);
2932 w32_fill_area (s
->f
, s
->hdc
, s
->face
->overline_color
, s
->x
,
2933 s
->y
+ dy
, s
->background_width
, h
);
2937 /* Draw strike-through. */
2938 if (s
->face
->strike_through_p
2939 && (s
->font
->bdf
|| !s
->font
->tm
.tmStruckOut
))
2941 unsigned long h
= 1;
2942 unsigned long dy
= (s
->height
- h
) / 2;
2944 if (s
->face
->strike_through_color_defaulted_p
)
2946 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
, s
->y
+ dy
,
2951 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2952 s
->y
+ dy
, s
->width
, h
);
2956 /* Draw relief if not yet drawn. */
2957 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2958 x_draw_glyph_string_box (s
);
2962 struct glyph_string
*prev
;
2964 for (prev
= s
->prev
; prev
; prev
= prev
->prev
)
2965 if (prev
->hl
!= s
->hl
2966 && prev
->x
+ prev
->width
+ prev
->right_overhang
> s
->x
)
2968 /* As prev was drawn while clipped to its own area, we
2969 must draw the right_overhang part using s->hl now. */
2970 enum draw_glyphs_face save
= prev
->hl
;
2973 x_set_glyph_string_gc (prev
);
2974 x_set_glyph_string_clipping_exactly (s
, prev
);
2975 if (prev
->first_glyph
->type
== CHAR_GLYPH
)
2976 x_draw_glyph_string_foreground (prev
);
2978 x_draw_composite_glyph_string_foreground (prev
);
2979 w32_set_clip_rectangle (prev
->hdc
, NULL
);
2981 #ifdef USE_FONT_BACKEND
2982 prev
->clip_width
= 0;
2983 #endif /* USE_FONT_BACKEND */
2989 struct glyph_string
*next
;
2991 for (next
= s
->next
; next
; next
= next
->next
)
2992 if (next
->hl
!= s
->hl
2993 && next
->x
- next
->left_overhang
< s
->x
+ s
->width
)
2995 /* As next will be drawn while clipped to its own area,
2996 we must draw the left_overhang part using s->hl now. */
2997 enum draw_glyphs_face save
= next
->hl
;
3000 x_set_glyph_string_gc (next
);
3001 x_set_glyph_string_clipping_exactly (s
, next
);
3002 if (next
->first_glyph
->type
== CHAR_GLYPH
)
3003 x_draw_glyph_string_foreground (next
);
3005 x_draw_composite_glyph_string_foreground (next
);
3006 w32_set_clip_rectangle (next
->hdc
, NULL
);
3008 #ifdef USE_FONT_BACKEND
3009 next
->clip_width
= 0;
3010 #endif /* USE_FONT_BACKEND */
3015 /* Reset clipping. */
3016 w32_set_clip_rectangle (s
->hdc
, NULL
);
3017 #ifdef USE_FONT_BACKEND
3019 #endif /* USE_FONT_BACKEND */
3023 /* Shift display to make room for inserted glyphs. */
3026 w32_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3028 int x
, y
, width
, height
, shift_by
;
3032 hdc
= get_frame_dc (f
);
3033 BitBlt (hdc
, x
+ shift_by
, y
, width
, height
,
3034 hdc
, x
, y
, SRCCOPY
);
3036 release_frame_dc (f
, hdc
);
3040 /* Delete N glyphs at the nominal cursor position. Not implemented
3052 f
= SELECTED_FRAME ();
3054 if (! FRAME_W32_P (f
))
3061 /* Clear entire frame. If updating_frame is non-null, clear that
3062 frame. Otherwise clear the selected frame. */
3072 f
= SELECTED_FRAME ();
3074 if (! FRAME_W32_P (f
))
3077 /* Clearing the frame will erase any cursor, so mark them all as no
3079 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3080 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3081 output_cursor
.x
= -1;
3083 /* We don't set the output cursor here because there will always
3084 follow an explicit cursor_to. */
3087 w32_clear_window (f
);
3089 /* We have to clear the scroll bars, too. If we have changed
3090 colors or something like that, then they should be notified. */
3091 x_scroll_bar_clear (f
);
3097 /* Make audible bell. */
3100 w32_ring_bell (void)
3104 f
= SELECTED_FRAME ();
3108 if (FRAME_W32_P (f
) && visible_bell
)
3111 HWND hwnd
= FRAME_W32_WINDOW (SELECTED_FRAME ());
3113 for (i
= 0; i
< 5; i
++)
3115 FlashWindow (hwnd
, TRUE
);
3118 FlashWindow (hwnd
, FALSE
);
3121 w32_sys_ring_bell ();
3127 /* Specify how many text lines, from the top of the window,
3128 should be affected by insert-lines and delete-lines operations.
3129 This, and those operations, are used only within an update
3130 that is bounded by calls to x_update_begin and x_update_end. */
3133 w32_set_terminal_window (n
)
3136 /* This function intentionally left blank. */
3140 /***********************************************************************
3142 ***********************************************************************/
3144 /* Perform an insert-lines or delete-lines operation, inserting N
3145 lines or deleting -N lines at vertical position VPOS. */
3148 x_ins_del_lines (vpos
, n
)
3156 f
= SELECTED_FRAME ();
3158 if (! FRAME_W32_P (f
))
3165 /* Scroll part of the display as described by RUN. */
3168 x_scroll_run (w
, run
)
3172 struct frame
*f
= XFRAME (w
->frame
);
3173 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3174 HWND hwnd
= FRAME_W32_WINDOW (f
);
3177 /* Get frame-relative bounding box of the text display area of W,
3178 without mode lines. Include in this box the left and right
3180 window_box (w
, -1, &x
, &y
, &width
, &height
);
3182 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3183 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3184 bottom_y
= y
+ height
;
3188 /* Scrolling up. Make sure we don't copy part of the mode
3189 line at the bottom. */
3190 if (from_y
+ run
->height
> bottom_y
)
3191 height
= bottom_y
- from_y
;
3193 height
= run
->height
;
3194 expect_dirty
= CreateRectRgn (x
, y
+ height
, x
+ width
, bottom_y
);
3198 /* Scolling down. Make sure we don't copy over the mode line.
3200 if (to_y
+ run
->height
> bottom_y
)
3201 height
= bottom_y
- to_y
;
3203 height
= run
->height
;
3204 expect_dirty
= CreateRectRgn (x
, y
, x
+ width
, to_y
);
3209 /* Cursor off. Will be switched on again in x_update_window_end. */
3216 HRGN dirty
= CreateRectRgn (0, 0, 0, 0);
3217 HRGN combined
= CreateRectRgn (0, 0, 0, 0);
3219 from
.left
= to
.left
= x
;
3220 from
.right
= to
.right
= x
+ width
;
3222 from
.bottom
= from_y
+ height
;
3224 to
.bottom
= bottom_y
;
3226 ScrollWindowEx (hwnd
, 0, to_y
- from_y
, &from
, &to
, dirty
,
3227 NULL
, SW_INVALIDATE
);
3229 /* Combine this with what we expect to be dirty. This covers the
3230 case where not all of the region we expect is actually dirty. */
3231 CombineRgn (combined
, dirty
, expect_dirty
, RGN_OR
);
3233 /* If the dirty region is not what we expected, redraw the entire frame. */
3234 if (!EqualRgn (combined
, expect_dirty
))
3235 SET_FRAME_GARBAGED (f
);
3237 DeleteObject (dirty
);
3238 DeleteObject (combined
);
3242 DeleteObject (expect_dirty
);
3247 /***********************************************************************
3249 ***********************************************************************/
3255 x_update_cursor (f
, 1);
3259 frame_unhighlight (f
)
3262 x_update_cursor (f
, 1);
3265 /* The focus has changed. Update the frames as necessary to reflect
3266 the new situation. Note that we can't change the selected frame
3267 here, because the Lisp code we are interrupting might become confused.
3268 Each event gets marked with the frame in which it occurred, so the
3269 Lisp code can tell when the switch took place by examining the events. */
3272 x_new_focus_frame (dpyinfo
, frame
)
3273 struct w32_display_info
*dpyinfo
;
3274 struct frame
*frame
;
3276 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
3278 if (frame
!= dpyinfo
->w32_focus_frame
)
3280 /* Set this before calling other routines, so that they see
3281 the correct value of w32_focus_frame. */
3282 dpyinfo
->w32_focus_frame
= frame
;
3284 if (old_focus
&& old_focus
->auto_lower
)
3285 x_lower_frame (old_focus
);
3287 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
3288 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
3290 pending_autoraise_frame
= 0;
3293 x_frame_rehighlight (dpyinfo
);
3297 /* Handle FocusIn and FocusOut state changes for FRAME.
3298 If FRAME has focus and there exists more than one frame, puts
3299 a FOCUS_IN_EVENT into *BUFP. */
3302 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
3305 struct w32_display_info
*dpyinfo
;
3306 struct frame
*frame
;
3307 struct input_event
*bufp
;
3309 if (type
== WM_SETFOCUS
)
3311 if (dpyinfo
->w32_focus_event_frame
!= frame
)
3313 x_new_focus_frame (dpyinfo
, frame
);
3314 dpyinfo
->w32_focus_event_frame
= frame
;
3316 /* Don't stop displaying the initial startup message
3317 for a switch-frame event we don't need. */
3318 if (NILP (Vterminal_frame
)
3319 && CONSP (Vframe_list
)
3320 && !NILP (XCDR (Vframe_list
)))
3322 bufp
->kind
= FOCUS_IN_EVENT
;
3323 XSETFRAME (bufp
->frame_or_window
, frame
);
3327 frame
->output_data
.x
->focus_state
|= state
;
3329 /* TODO: IME focus? */
3331 else if (type
== WM_KILLFOCUS
)
3333 frame
->output_data
.x
->focus_state
&= ~state
;
3335 if (dpyinfo
->w32_focus_event_frame
== frame
)
3337 dpyinfo
->w32_focus_event_frame
= 0;
3338 x_new_focus_frame (dpyinfo
, 0);
3341 /* TODO: IME focus? */
3346 /* The focus may have changed. Figure out if it is a real focus change,
3347 by checking both FocusIn/Out and Enter/LeaveNotify events.
3349 Returns FOCUS_IN_EVENT event in *BUFP. */
3352 w32_detect_focus_change (dpyinfo
, event
, bufp
)
3353 struct w32_display_info
*dpyinfo
;
3355 struct input_event
*bufp
;
3357 struct frame
*frame
;
3359 frame
= x_any_window_to_frame (dpyinfo
, event
->msg
.hwnd
);
3363 /* On w32, this is only called from focus events, so no switch needed. */
3364 x_focus_changed (event
->msg
.message
,
3365 (event
->msg
.message
== WM_KILLFOCUS
?
3366 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
3367 dpyinfo
, frame
, bufp
);
3371 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3374 x_mouse_leave (dpyinfo
)
3375 struct w32_display_info
*dpyinfo
;
3377 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
3380 /* The focus has changed, or we have redirected a frame's focus to
3381 another frame (this happens when a frame uses a surrogate
3382 mini-buffer frame). Shift the highlight as appropriate.
3384 The FRAME argument doesn't necessarily have anything to do with which
3385 frame is being highlighted or un-highlighted; we only use it to find
3386 the appropriate X display info. */
3389 w32_frame_rehighlight (frame
)
3390 struct frame
*frame
;
3392 if (! FRAME_W32_P (frame
))
3394 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
3398 x_frame_rehighlight (dpyinfo
)
3399 struct w32_display_info
*dpyinfo
;
3401 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3403 if (dpyinfo
->w32_focus_frame
)
3405 dpyinfo
->x_highlight_frame
3406 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
3407 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
3408 : dpyinfo
->w32_focus_frame
);
3409 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3411 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
3412 dpyinfo
->x_highlight_frame
= dpyinfo
->w32_focus_frame
;
3416 dpyinfo
->x_highlight_frame
= 0;
3418 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3421 frame_unhighlight (old_highlight
);
3422 if (dpyinfo
->x_highlight_frame
)
3423 frame_highlight (dpyinfo
->x_highlight_frame
);
3427 /* Keyboard processing - modifier keys, etc. */
3429 /* Convert a keysym to its name. */
3432 x_get_keysym_name (keysym
)
3435 /* Make static so we can always return it */
3436 static char value
[100];
3439 GetKeyNameText (keysym
, value
, 100);
3447 /* Mouse clicks and mouse movement. Rah. */
3449 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3450 the state in PUP. XBUTTON provides extra information for extended mouse
3451 button messages. Returns FALSE if unable to parse the message. */
3453 parse_button (message
, xbutton
, pbutton
, pup
)
3464 case WM_LBUTTONDOWN
:
3472 case WM_MBUTTONDOWN
:
3473 if (NILP (Vw32_swap_mouse_buttons
))
3480 if (NILP (Vw32_swap_mouse_buttons
))
3486 case WM_RBUTTONDOWN
:
3487 if (NILP (Vw32_swap_mouse_buttons
))
3494 if (NILP (Vw32_swap_mouse_buttons
))
3500 case WM_XBUTTONDOWN
:
3501 button
= xbutton
+ 2;
3505 button
= xbutton
+ 2;
3513 if (pbutton
) *pbutton
= button
;
3519 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3521 If the event is a button press, then note that we have grabbed
3525 construct_mouse_click (result
, msg
, f
)
3526 struct input_event
*result
;
3533 parse_button (msg
->msg
.message
, HIWORD (msg
->msg
.wParam
),
3536 /* Make the event type NO_EVENT; we'll change that when we decide
3538 result
->kind
= MOUSE_CLICK_EVENT
;
3539 result
->code
= button
;
3540 result
->timestamp
= msg
->msg
.time
;
3541 result
->modifiers
= (msg
->dwModifiers
3546 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
3547 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
3548 XSETFRAME (result
->frame_or_window
, f
);
3554 construct_mouse_wheel (result
, msg
, f
)
3555 struct input_event
*result
;
3562 result
->kind
= WHEEL_EVENT
;
3564 result
->timestamp
= msg
->msg
.time
;
3566 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3567 forward, away from the user (up); a negative value indicates that
3568 the wheel was rotated backward, toward the user (down). */
3569 delta
= GET_WHEEL_DELTA_WPARAM (msg
->msg
.wParam
);
3571 /* The up and down modifiers indicate if the wheel was rotated up or
3572 down based on WHEEL_DELTA value. */
3573 result
->modifiers
= (msg
->dwModifiers
3574 | ((delta
< 0 ) ? down_modifier
: up_modifier
));
3576 /* With multiple monitors, we can legitimately get negative
3577 coordinates, so cast to short to interpret them correctly. */
3578 p
.x
= (short) LOWORD (msg
->msg
.lParam
);
3579 p
.y
= (short) HIWORD (msg
->msg
.lParam
);
3580 ScreenToClient (msg
->msg
.hwnd
, &p
);
3581 XSETINT (result
->x
, p
.x
);
3582 XSETINT (result
->y
, p
.y
);
3583 XSETFRAME (result
->frame_or_window
, f
);
3589 construct_drag_n_drop (result
, msg
, f
)
3590 struct input_event
*result
;
3602 result
->kind
= DRAG_N_DROP_EVENT
;
3604 result
->timestamp
= msg
->msg
.time
;
3605 result
->modifiers
= msg
->dwModifiers
;
3607 hdrop
= (HDROP
) msg
->msg
.wParam
;
3608 DragQueryPoint (hdrop
, &p
);
3611 p
.x
= LOWORD (msg
->msg
.lParam
);
3612 p
.y
= HIWORD (msg
->msg
.lParam
);
3613 ScreenToClient (msg
->msg
.hwnd
, &p
);
3616 XSETINT (result
->x
, p
.x
);
3617 XSETINT (result
->y
, p
.y
);
3619 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
3622 for (i
= 0; i
< num_files
; i
++)
3624 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
3627 name
= alloca (len
+ 1);
3628 DragQueryFile (hdrop
, i
, name
, len
+ 1);
3629 files
= Fcons (DECODE_FILE (build_string (name
)), files
);
3634 XSETFRAME (frame
, f
);
3635 result
->frame_or_window
= frame
;
3636 result
->arg
= files
;
3641 /* Function to report a mouse movement to the mainstream Emacs code.
3642 The input handler calls this.
3644 We have received a mouse movement event, which is given in *event.
3645 If the mouse is over a different glyph than it was last time, tell
3646 the mainstream emacs code by setting mouse_moved. If not, ask for
3647 another motion event, so we can check again the next time it moves. */
3649 static MSG last_mouse_motion_event
;
3650 static Lisp_Object last_mouse_motion_frame
;
3653 note_mouse_movement (frame
, msg
)
3657 int mouse_x
= LOWORD (msg
->lParam
);
3658 int mouse_y
= HIWORD (msg
->lParam
);
3660 last_mouse_movement_time
= msg
->time
;
3661 memcpy (&last_mouse_motion_event
, msg
, sizeof (last_mouse_motion_event
));
3662 XSETFRAME (last_mouse_motion_frame
, frame
);
3664 if (!FRAME_X_OUTPUT (frame
))
3667 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
3669 frame
->mouse_moved
= 1;
3670 last_mouse_scroll_bar
= Qnil
;
3671 note_mouse_highlight (frame
, -1, -1);
3672 last_mouse_glyph_frame
= 0;
3676 /* Has the mouse moved off the glyph it was on at the last sighting? */
3677 if (frame
!= last_mouse_glyph_frame
3678 || mouse_x
< last_mouse_glyph
.left
3679 || mouse_x
>= last_mouse_glyph
.right
3680 || mouse_y
< last_mouse_glyph
.top
3681 || mouse_y
>= last_mouse_glyph
.bottom
)
3683 frame
->mouse_moved
= 1;
3684 last_mouse_scroll_bar
= Qnil
;
3685 note_mouse_highlight (frame
, mouse_x
, mouse_y
);
3686 /* Remember the mouse position here, as w32_mouse_position only
3687 gets called when mouse tracking is enabled but we also need
3688 to keep track of the mouse for help_echo and highlighting at
3690 remember_mouse_glyph (frame
, mouse_x
, mouse_y
, &last_mouse_glyph
);
3691 last_mouse_glyph_frame
= frame
;
3699 /************************************************************************
3701 ************************************************************************/
3703 static struct scroll_bar
*x_window_to_scroll_bar ();
3704 static void x_scroll_bar_report_motion ();
3705 static void x_check_fullscreen
P_ ((struct frame
*));
3708 redo_mouse_highlight ()
3710 if (!NILP (last_mouse_motion_frame
)
3711 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3712 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3713 LOWORD (last_mouse_motion_event
.lParam
),
3714 HIWORD (last_mouse_motion_event
.lParam
));
3718 w32_define_cursor (window
, cursor
)
3722 PostMessage (window
, WM_EMACS_SETCURSOR
, (WPARAM
) cursor
, 0);
3724 /* Return the current position of the mouse.
3725 *fp should be a frame which indicates which display to ask about.
3727 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3728 and *part to the frame, window, and scroll bar part that the mouse
3729 is over. Set *x and *y to the portion and whole of the mouse's
3730 position on the scroll bar.
3732 If the mouse movement started elsewhere, set *fp to the frame the
3733 mouse is on, *bar_window to nil, and *x and *y to the character cell
3736 Set *time to the server time-stamp for the time at which the mouse
3737 was at this position.
3739 Don't store anything if we don't have a valid set of values to report.
3741 This clears the mouse_moved flag, so we can wait for the next mouse
3745 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3748 Lisp_Object
*bar_window
;
3749 enum scroll_bar_part
*part
;
3751 unsigned long *time
;
3757 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3758 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3763 Lisp_Object frame
, tail
;
3765 /* Clear the mouse-moved flag for every frame on this display. */
3766 FOR_EACH_FRAME (tail
, frame
)
3767 XFRAME (frame
)->mouse_moved
= 0;
3769 last_mouse_scroll_bar
= Qnil
;
3773 /* Now we have a position on the root; find the innermost window
3774 containing the pointer. */
3776 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3777 && FRAME_LIVE_P (last_mouse_frame
))
3779 /* If mouse was grabbed on a frame, give coords for that frame
3780 even if the mouse is now outside it. */
3781 f1
= last_mouse_frame
;
3785 /* Is window under mouse one of our frames? */
3786 f1
= x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
),
3787 WindowFromPoint (pt
));
3790 /* If not, is it one of our scroll bars? */
3793 struct scroll_bar
*bar
3794 = x_window_to_scroll_bar (WindowFromPoint (pt
));
3798 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3802 if (f1
== 0 && insist
> 0)
3803 f1
= SELECTED_FRAME ();
3807 /* Ok, we found a frame. Store all the values.
3808 last_mouse_glyph is a rectangle used to reduce the
3809 generation of mouse events. To not miss any motion
3810 events, we must divide the frame into rectangles of the
3811 size of the smallest character that could be displayed
3812 on it, i.e. into the same rectangles that matrices on
3813 the frame are divided into. */
3815 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3816 remember_mouse_glyph (f1
, pt
.x
, pt
.y
, &last_mouse_glyph
);
3817 last_mouse_glyph_frame
= f1
;
3824 *time
= last_mouse_movement_time
;
3833 /***********************************************************************
3835 ***********************************************************************/
3837 /* Handle mouse button event on the tool-bar of frame F, at
3838 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3842 w32_handle_tool_bar_click (f
, button_event
)
3844 struct input_event
*button_event
;
3846 int x
= XFASTINT (button_event
->x
);
3847 int y
= XFASTINT (button_event
->y
);
3849 if (button_event
->modifiers
& down_modifier
)
3850 handle_tool_bar_click (f
, x
, y
, 1, 0);
3852 handle_tool_bar_click (f
, x
, y
, 0,
3853 button_event
->modifiers
& ~up_modifier
);
3858 /***********************************************************************
3860 ***********************************************************************/
3862 /* Scroll bar support. */
3864 /* Given a window ID, find the struct scroll_bar which manages it.
3865 This can be called in GC, so we have to make sure to strip off mark
3868 static struct scroll_bar
*
3869 x_window_to_scroll_bar (window_id
)
3874 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
3876 Lisp_Object frame
, bar
, condemned
;
3878 frame
= XCAR (tail
);
3879 /* All elements of Vframe_list should be frames. */
3880 if (! FRAMEP (frame
))
3883 /* Scan this frame's scroll bar list for a scroll bar with the
3885 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3886 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3887 /* This trick allows us to search both the ordinary and
3888 condemned scroll bar lists with one loop. */
3889 ! NILP (bar
) || (bar
= condemned
,
3892 bar
= XSCROLL_BAR (bar
)->next
)
3893 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
3894 return XSCROLL_BAR (bar
);
3902 /* Set the thumb size and position of scroll bar BAR. We are currently
3903 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3906 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
)
3907 struct scroll_bar
*bar
;
3908 int portion
, position
, whole
;
3910 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3911 /* We use the whole scroll-bar height in the calculations below, to
3912 avoid strange effects like scrolling backwards when just clicking
3913 on the handle (without moving it). */
3914 double range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
))
3915 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3916 int sb_page
, sb_pos
;
3917 BOOL draggingp
= !NILP (bar
->dragging
) ? TRUE
: FALSE
;
3920 /* We used to change the nPage setting while dragging the handle,
3921 but that had very strange effects (such as scrolling backwards
3922 while dragging downwards).
3924 Now, we don't change the nPage setting while dragging unless we
3925 get near to the end of the buffer, in which case we often have to
3926 resize the handle to "go all the way". */
3932 si
.cbSize
= sizeof (si
);
3933 si
.fMask
= SIF_POS
| SIF_PAGE
;
3934 GetScrollInfo(w
, SB_CTL
, &si
);
3935 near_bottom_p
= si
.nPos
+ si
.nPage
>= range
;
3943 /* Position scroll bar at rock bottom if the bottom of the
3944 buffer is visible. This avoids shinking the thumb away
3945 to nothing if it is held at the bottom of the buffer. */
3946 if (position
+ portion
>= whole
&& !draggingp
)
3948 sb_page
= range
* (whole
- position
) / whole
;
3953 sb_pos
= position
* range
/ whole
;
3954 sb_page
= (min (portion
, (whole
- position
)) * range
) / whole
;
3963 sb_page
= max (sb_page
, VERTICAL_SCROLL_BAR_MIN_HANDLE
);
3967 si
.cbSize
= sizeof (si
);
3968 si
.fMask
= SIF_PAGE
| SIF_POS
;
3972 SetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
3978 /************************************************************************
3979 Scroll bars, general
3980 ************************************************************************/
3983 my_create_scrollbar (f
, bar
)
3985 struct scroll_bar
* bar
;
3987 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
3988 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
3992 /*#define ATTACH_THREADS*/
3995 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
3997 #ifndef ATTACH_THREADS
3998 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
3999 (WPARAM
) hwnd
, (LPARAM
) how
);
4001 return ShowWindow (hwnd
, how
);
4006 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
4007 int x
, int y
, int cx
, int cy
, UINT flags
)
4009 #ifndef ATTACH_THREADS
4011 pos
.hwndInsertAfter
= hwndAfter
;
4017 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
4019 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
4024 my_set_focus (f
, hwnd
)
4028 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
4033 my_set_foreground_window (hwnd
)
4036 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
4041 my_destroy_window (f
, hwnd
)
4045 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
4049 /* Create a scroll bar and return the scroll bar vector for it. W is
4050 the Emacs window on which to create the scroll bar. TOP, LEFT,
4051 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
4054 static struct scroll_bar
*
4055 x_scroll_bar_create (w
, top
, left
, width
, height
)
4057 int top
, left
, width
, height
;
4059 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4062 struct scroll_bar
*bar
4063 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4067 XSETWINDOW (bar
->window
, w
);
4068 XSETINT (bar
->top
, top
);
4069 XSETINT (bar
->left
, left
);
4070 XSETINT (bar
->width
, width
);
4071 XSETINT (bar
->height
, height
);
4072 XSETINT (bar
->start
, 0);
4073 XSETINT (bar
->end
, 0);
4074 bar
->dragging
= Qnil
;
4076 /* Requires geometry to be set before call to create the real window */
4078 hwnd
= my_create_scrollbar (f
, bar
);
4080 si
.cbSize
= sizeof (si
);
4083 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
4084 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4088 SetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
4090 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
4092 /* Add bar to its frame's list of scroll bars. */
4093 bar
->next
= FRAME_SCROLL_BARS (f
);
4095 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4096 if (! NILP (bar
->next
))
4097 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4105 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4109 x_scroll_bar_remove (bar
)
4110 struct scroll_bar
*bar
;
4112 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4116 /* Destroy the window. */
4117 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
4119 /* Disassociate this scroll bar from its window. */
4120 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4125 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4126 that we are displaying PORTION characters out of a total of WHOLE
4127 characters, starting at POSITION. If WINDOW has no scroll bar,
4130 w32_set_vertical_scroll_bar (w
, portion
, whole
, position
)
4132 int portion
, whole
, position
;
4134 struct frame
*f
= XFRAME (w
->frame
);
4135 struct scroll_bar
*bar
;
4136 int top
, height
, left
, sb_left
, width
, sb_width
;
4137 int window_y
, window_height
;
4139 /* Get window dimensions. */
4140 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4142 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4143 height
= window_height
;
4145 /* Compute the left edge of the scroll bar area. */
4146 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4148 /* Compute the width of the scroll bar which might be less than
4149 the width of the area reserved for the scroll bar. */
4150 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4151 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4155 /* Compute the left edge of the scroll bar. */
4156 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4157 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4159 sb_left
= left
+ (width
- sb_width
) / 2;
4161 /* Does the scroll bar exist yet? */
4162 if (NILP (w
->vertical_scroll_bar
))
4166 if (width
> 0 && height
> 0)
4168 hdc
= get_frame_dc (f
);
4169 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
4170 release_frame_dc (f
, hdc
);
4174 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
4178 /* It may just need to be moved and resized. */
4181 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4182 hwnd
= SCROLL_BAR_W32_WINDOW (bar
);
4184 /* If already correctly positioned, do nothing. */
4185 if ( XINT (bar
->left
) == sb_left
4186 && XINT (bar
->top
) == top
4187 && XINT (bar
->width
) == sb_width
4188 && XINT (bar
->height
) == height
)
4190 /* Redraw after clear_frame. */
4191 if (!my_show_window (f
, hwnd
, SW_NORMAL
))
4192 InvalidateRect (hwnd
, NULL
, FALSE
);
4200 if (width
&& height
)
4202 hdc
= get_frame_dc (f
);
4203 /* Since Windows scroll bars are smaller than the space reserved
4204 for them on the frame, we have to clear "under" them. */
4205 w32_clear_area (f
, hdc
,
4210 release_frame_dc (f
, hdc
);
4212 /* Make sure scroll bar is "visible" before moving, to ensure the
4213 area of the parent window now exposed will be refreshed. */
4214 my_show_window (f
, hwnd
, SW_HIDE
);
4215 MoveWindow (hwnd
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
4216 top
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4217 max (height
, 1), TRUE
);
4219 si
.cbSize
= sizeof (si
);
4220 si
.fMask
= SIF_RANGE
;
4222 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
4223 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4225 SetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
4227 my_show_window (f
, hwnd
, SW_NORMAL
);
4228 /* InvalidateRect (w, NULL, FALSE); */
4230 /* Remember new settings. */
4231 XSETINT (bar
->left
, sb_left
);
4232 XSETINT (bar
->top
, top
);
4233 XSETINT (bar
->width
, sb_width
);
4234 XSETINT (bar
->height
, height
);
4239 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
4241 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4245 /* The following three hooks are used when we're doing a thorough
4246 redisplay of the frame. We don't explicitly know which scroll bars
4247 are going to be deleted, because keeping track of when windows go
4248 away is a real pain - "Can you say set-window-configuration, boys
4249 and girls?" Instead, we just assert at the beginning of redisplay
4250 that *all* scroll bars are to be removed, and then save a scroll bar
4251 from the fiery pit when we actually redisplay its window. */
4253 /* Arrange for all scroll bars on FRAME to be removed at the next call
4254 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4255 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4258 w32_condemn_scroll_bars (frame
)
4261 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4262 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4265 bar
= FRAME_SCROLL_BARS (frame
);
4266 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4267 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4268 XSCROLL_BAR (bar
)->prev
= Qnil
;
4269 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4270 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4271 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4276 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4277 Note that WINDOW isn't necessarily condemned at all. */
4280 w32_redeem_scroll_bar (window
)
4281 struct window
*window
;
4283 struct scroll_bar
*bar
;
4286 /* We can't redeem this window's scroll bar if it doesn't have one. */
4287 if (NILP (window
->vertical_scroll_bar
))
4290 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4292 /* Unlink it from the condemned list. */
4293 f
= XFRAME (WINDOW_FRAME (window
));
4294 if (NILP (bar
->prev
))
4296 /* If the prev pointer is nil, it must be the first in one of
4298 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4299 /* It's not condemned. Everything's fine. */
4301 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4302 window
->vertical_scroll_bar
))
4303 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4305 /* If its prev pointer is nil, it must be at the front of
4306 one or the other! */
4310 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4312 if (! NILP (bar
->next
))
4313 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4315 bar
->next
= FRAME_SCROLL_BARS (f
);
4317 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4318 if (! NILP (bar
->next
))
4319 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4322 /* Remove all scroll bars on FRAME that haven't been saved since the
4323 last call to `*condemn_scroll_bars_hook'. */
4326 w32_judge_scroll_bars (f
)
4329 Lisp_Object bar
, next
;
4331 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4333 /* Clear out the condemned list now so we won't try to process any
4334 more events on the hapless scroll bars. */
4335 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4337 for (; ! NILP (bar
); bar
= next
)
4339 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4341 x_scroll_bar_remove (b
);
4344 b
->next
= b
->prev
= Qnil
;
4347 /* Now there should be no references to the condemned scroll bars,
4348 and they should get garbage-collected. */
4351 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4352 is set to something other than NO_EVENT, it is enqueued.
4354 This may be called from a signal handler, so we have to ignore GC
4358 w32_scroll_bar_handle_click (bar
, msg
, emacs_event
)
4359 struct scroll_bar
*bar
;
4361 struct input_event
*emacs_event
;
4363 if (! WINDOWP (bar
->window
))
4366 emacs_event
->kind
= W32_SCROLL_BAR_CLICK_EVENT
;
4367 emacs_event
->code
= 0;
4368 /* not really meaningful to distinguish up/down */
4369 emacs_event
->modifiers
= msg
->dwModifiers
;
4370 emacs_event
->frame_or_window
= bar
->window
;
4371 emacs_event
->arg
= Qnil
;
4372 emacs_event
->timestamp
= msg
->msg
.time
;
4375 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4377 int dragging
= !NILP (bar
->dragging
);
4380 si
.cbSize
= sizeof (si
);
4383 GetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
4386 bar
->dragging
= Qnil
;
4389 last_mouse_scroll_bar_pos
= msg
->msg
.wParam
;
4391 switch (LOWORD (msg
->msg
.wParam
))
4394 emacs_event
->part
= scroll_bar_down_arrow
;
4397 emacs_event
->part
= scroll_bar_up_arrow
;
4400 emacs_event
->part
= scroll_bar_above_handle
;
4403 emacs_event
->part
= scroll_bar_below_handle
;
4406 emacs_event
->part
= scroll_bar_handle
;
4410 emacs_event
->part
= scroll_bar_handle
;
4414 case SB_THUMBPOSITION
:
4415 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4416 y
= HIWORD (msg
->msg
.wParam
);
4418 emacs_event
->part
= scroll_bar_handle
;
4420 /* "Silently" update current position. */
4424 si
.cbSize
= sizeof (si
);
4427 /* Remember apparent position (we actually lag behind the real
4428 position, so don't set that directly. */
4429 last_scroll_bar_drag_pos
= y
;
4431 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
4435 /* If this is the end of a drag sequence, then reset the scroll
4436 handle size to normal and do a final redraw. Otherwise do
4441 int start
= XINT (bar
->start
);
4442 int end
= XINT (bar
->end
);
4444 si
.cbSize
= sizeof (si
);
4445 si
.fMask
= SIF_PAGE
| SIF_POS
;
4446 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4447 si
.nPos
= last_scroll_bar_drag_pos
;
4448 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
4452 emacs_event
->kind
= NO_EVENT
;
4456 XSETINT (emacs_event
->x
, y
);
4457 XSETINT (emacs_event
->y
, top_range
);
4463 /* Return information to the user about the current position of the mouse
4464 on the scroll bar. */
4467 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4469 Lisp_Object
*bar_window
;
4470 enum scroll_bar_part
*part
;
4472 unsigned long *time
;
4474 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4475 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
4476 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4478 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4484 *bar_window
= bar
->window
;
4486 si
.cbSize
= sizeof (si
);
4487 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
4489 GetScrollInfo (w
, SB_CTL
, &si
);
4491 top_range
= si
.nMax
- si
.nPage
+ 1;
4493 switch (LOWORD (last_mouse_scroll_bar_pos
))
4495 case SB_THUMBPOSITION
:
4497 *part
= scroll_bar_handle
;
4498 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4499 pos
= HIWORD (last_mouse_scroll_bar_pos
);
4502 *part
= scroll_bar_handle
;
4506 *part
= scroll_bar_handle
;
4511 XSETINT (*y
, top_range
);
4514 last_mouse_scroll_bar
= Qnil
;
4516 *time
= last_mouse_movement_time
;
4522 /* The screen has been cleared so we may have changed foreground or
4523 background colors, and the scroll bars may need to be redrawn.
4524 Clear out the scroll bars, and ask for expose events, so we can
4528 x_scroll_bar_clear (f
)
4533 /* We can have scroll bars even if this is 0,
4534 if we just turned off scroll bar mode.
4535 But in that case we should not clear them. */
4536 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4537 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
4538 bar
= XSCROLL_BAR (bar
)->next
)
4540 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
4541 HDC hdc
= GetDC (window
);
4544 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4545 arranges to refresh the scroll bar if hidden. */
4546 my_show_window (f
, window
, SW_HIDE
);
4548 GetClientRect (window
, &rect
);
4549 select_palette (f
, hdc
);
4550 w32_clear_rect (f
, hdc
, &rect
);
4551 deselect_palette (f
, hdc
);
4553 ReleaseDC (window
, hdc
);
4558 /* The main W32 event-reading loop - w32_read_socket. */
4560 /* Record the last 100 characters stored
4561 to help debug the loss-of-chars-during-GC problem. */
4563 static int temp_index
;
4564 static short temp_buffer
[100];
4567 /* Read events coming from the W32 shell.
4568 This routine is called by the SIGIO handler.
4569 We return as soon as there are no more events to be read.
4571 We return the number of characters stored into the buffer,
4572 thus pretending to be `read'.
4574 EXPECTED is nonzero if the caller knows input is available.
4576 Some of these messages are reposted back to the message queue since the
4577 system calls the windows proc directly in a context where we cannot return
4578 the data nor can we guarantee the state we are in. So if we dispatch them
4579 we will get into an infinite loop. To prevent this from ever happening we
4580 will set a variable to indicate we are in the read_socket call and indicate
4581 which message we are processing since the windows proc gets called
4582 recursively with different messages by the system.
4586 w32_read_socket (sd
, expected
, hold_quit
)
4589 struct input_event
*hold_quit
;
4592 int check_visibility
= 0;
4595 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4597 if (interrupt_input_blocked
)
4599 interrupt_input_pending
= 1;
4603 interrupt_input_pending
= 0;
4606 /* So people can tell when we have read the available input. */
4607 input_signal_count
++;
4609 /* TODO: ghostscript integration. */
4610 while (get_next_msg (&msg
, FALSE
))
4612 struct input_event inev
;
4616 inev
.kind
= NO_EVENT
;
4619 switch (msg
.msg
.message
)
4622 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4626 if (msg
.rect
.right
== msg
.rect
.left
||
4627 msg
.rect
.bottom
== msg
.rect
.top
)
4629 /* We may get paint messages even though the client
4630 area is clipped - these are not expose events. */
4631 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f
,
4634 else if (f
->async_visible
!= 1)
4636 /* Definitely not obscured, so mark as visible. */
4637 f
->async_visible
= 1;
4638 f
->async_iconified
= 0;
4639 SET_FRAME_GARBAGED (f
);
4640 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f
,
4643 /* WM_PAINT serves as MapNotify as well, so report
4644 visibility changes properly. */
4647 inev
.kind
= DEICONIFY_EVENT
;
4648 XSETFRAME (inev
.frame_or_window
, f
);
4650 else if (! NILP (Vframe_list
)
4651 && ! NILP (XCDR (Vframe_list
)))
4652 /* Force a redisplay sooner or later to update the
4653 frame titles in case this is the second frame. */
4654 record_asynch_buffer_change ();
4658 HDC hdc
= get_frame_dc (f
);
4660 /* Erase background again for safety. */
4661 w32_clear_rect (f
, hdc
, &msg
.rect
);
4662 release_frame_dc (f
, hdc
);
4666 msg
.rect
.right
- msg
.rect
.left
,
4667 msg
.rect
.bottom
- msg
.rect
.top
);
4672 case WM_INPUTLANGCHANGE
:
4673 /* Generate a language change event. */
4674 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4678 inev
.kind
= LANGUAGE_CHANGE_EVENT
;
4679 XSETFRAME (inev
.frame_or_window
, f
);
4680 inev
.code
= msg
.msg
.wParam
;
4681 inev
.modifiers
= msg
.msg
.lParam
& 0xffff;
4687 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4689 if (f
&& !f
->iconified
)
4691 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
4692 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
4694 clear_mouse_face (dpyinfo
);
4695 dpyinfo
->mouse_face_hidden
= 1;
4698 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4700 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4701 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
4702 inev
.code
= msg
.msg
.wParam
;
4703 inev
.modifiers
= msg
.dwModifiers
;
4704 XSETFRAME (inev
.frame_or_window
, f
);
4705 inev
.timestamp
= msg
.msg
.time
;
4711 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4713 if (f
&& !f
->iconified
)
4715 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
4716 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
4718 clear_mouse_face (dpyinfo
);
4719 dpyinfo
->mouse_face_hidden
= 1;
4722 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4724 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4725 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
4726 inev
.code
= msg
.msg
.wParam
;
4727 inev
.modifiers
= msg
.dwModifiers
;
4728 XSETFRAME (inev
.frame_or_window
, f
);
4729 inev
.timestamp
= msg
.msg
.time
;
4734 /* Ignore non-movement. */
4736 int x
= LOWORD (msg
.msg
.lParam
);
4737 int y
= HIWORD (msg
.msg
.lParam
);
4738 if (x
== last_mousemove_x
&& y
== last_mousemove_y
)
4740 last_mousemove_x
= x
;
4741 last_mousemove_y
= y
;
4744 previous_help_echo_string
= help_echo_string
;
4745 help_echo_string
= Qnil
;
4747 if (dpyinfo
->grabbed
&& last_mouse_frame
4748 && FRAME_LIVE_P (last_mouse_frame
))
4749 f
= last_mouse_frame
;
4751 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4753 if (dpyinfo
->mouse_face_hidden
)
4755 dpyinfo
->mouse_face_hidden
= 0;
4756 clear_mouse_face (dpyinfo
);
4761 /* Generate SELECT_WINDOW_EVENTs when needed. */
4762 if (!NILP (Vmouse_autoselect_window
))
4765 int x
= LOWORD (msg
.msg
.lParam
);
4766 int y
= HIWORD (msg
.msg
.lParam
);
4768 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 0);
4770 /* Window will be selected only when it is not
4771 selected now and last mouse movement event was
4772 not in it. Minibuffer window will be selected
4773 iff it is active. */
4775 && !EQ (window
, last_window
)
4776 && !EQ (window
, selected_window
))
4778 inev
.kind
= SELECT_WINDOW_EVENT
;
4779 inev
.frame_or_window
= window
;
4784 if (!note_mouse_movement (f
, &msg
.msg
))
4785 help_echo_string
= previous_help_echo_string
;
4789 /* If we move outside the frame, then we're
4790 certainly no longer on any text in the frame. */
4791 clear_mouse_face (dpyinfo
);
4794 /* If the contents of the global variable help_echo_string
4795 has changed, generate a HELP_EVENT. */
4796 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4797 But it was originally changed to this to fix a bug, so I have
4798 not removed it completely in case the bug is still there. */
4799 if (help_echo_string
!= previous_help_echo_string
||
4800 (!NILP (help_echo_string
) && !STRINGP (help_echo_string
) && f
->mouse_moved
))
4801 #else /* This is what xterm.c does. */
4802 if (!NILP (help_echo_string
)
4803 || !NILP (previous_help_echo_string
))
4808 case WM_LBUTTONDOWN
:
4810 case WM_MBUTTONDOWN
:
4812 case WM_RBUTTONDOWN
:
4814 case WM_XBUTTONDOWN
:
4817 /* If we decide we want to generate an event to be seen
4818 by the rest of Emacs, we put it here. */
4823 if (dpyinfo
->grabbed
&& last_mouse_frame
4824 && FRAME_LIVE_P (last_mouse_frame
))
4825 f
= last_mouse_frame
;
4827 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4831 construct_mouse_click (&inev
, &msg
, f
);
4833 /* Is this in the tool-bar? */
4834 if (WINDOWP (f
->tool_bar_window
)
4835 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
4838 int x
= XFASTINT (inev
.x
);
4839 int y
= XFASTINT (inev
.y
);
4841 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
4843 if (EQ (window
, f
->tool_bar_window
))
4845 w32_handle_tool_bar_click (f
, &inev
);
4851 || (dpyinfo
->w32_focus_frame
4852 && f
!= dpyinfo
->w32_focus_frame
))
4853 inev
.kind
= NO_EVENT
;
4856 parse_button (msg
.msg
.message
, HIWORD (msg
.msg
.wParam
),
4861 dpyinfo
->grabbed
&= ~ (1 << button
);
4865 dpyinfo
->grabbed
|= (1 << button
);
4866 last_mouse_frame
= f
;
4867 /* Ignore any mouse motion that happened
4868 before this event; any subsequent mouse-movement
4869 Emacs events should reflect only motion after
4875 last_tool_bar_item
= -1;
4882 if (dpyinfo
->grabbed
&& last_mouse_frame
4883 && FRAME_LIVE_P (last_mouse_frame
))
4884 f
= last_mouse_frame
;
4886 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4891 if (!dpyinfo
->w32_focus_frame
4892 || f
== dpyinfo
->w32_focus_frame
)
4894 /* Emit an Emacs wheel-up/down event. */
4895 construct_mouse_wheel (&inev
, &msg
, f
);
4897 /* Ignore any mouse motion that happened before this
4898 event; any subsequent mouse-movement Emacs events
4899 should reflect only motion after the
4903 last_mouse_frame
= f
;
4904 last_tool_bar_item
= -1;
4909 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4912 construct_drag_n_drop (&inev
, &msg
, f
);
4917 struct scroll_bar
*bar
=
4918 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
4921 w32_scroll_bar_handle_click (bar
, &msg
, &inev
);
4925 case WM_WINDOWPOSCHANGED
:
4926 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4929 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
4930 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
4932 check_visibility
= 1;
4936 case WM_ACTIVATEAPP
:
4937 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4939 x_check_fullscreen (f
);
4940 check_visibility
= 1;
4944 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4946 if (f
&& !f
->async_iconified
)
4950 x_real_positions (f
, &x
, &y
);
4955 check_visibility
= 1;
4959 /* wParam non-zero means Window is about to be shown, 0 means
4960 about to be hidden. */
4961 /* Redo the mouse-highlight after the tooltip has gone. */
4962 if (!msg
.msg
.wParam
&& msg
.msg
.hwnd
== tip_window
)
4965 redo_mouse_highlight ();
4968 /* If window has been obscured or exposed by another window
4969 being maximised or minimised/restored, then recheck
4970 visibility of all frames. Direct changes to our own
4971 windows get handled by WM_SIZE. */
4973 if (msg
.msg
.lParam
!= 0)
4974 check_visibility
= 1;
4977 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4978 f
->async_visible
= msg
.msg
.wParam
;
4982 check_visibility
= 1;
4986 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4988 /* Inform lisp of whether frame has been iconified etc. */
4991 switch (msg
.msg
.wParam
)
4993 case SIZE_MINIMIZED
:
4994 f
->async_visible
= 0;
4995 f
->async_iconified
= 1;
4997 inev
.kind
= ICONIFY_EVENT
;
4998 XSETFRAME (inev
.frame_or_window
, f
);
5001 case SIZE_MAXIMIZED
:
5003 f
->async_visible
= 1;
5004 f
->async_iconified
= 0;
5006 /* wait_reading_process_output will notice this and update
5007 the frame's display structures. */
5008 SET_FRAME_GARBAGED (f
);
5014 /* Reset top and left positions of the Window
5015 here since Windows sends a WM_MOVE message
5016 BEFORE telling us the Window is minimized
5017 when the Window is iconified, with 3000,3000
5019 x_real_positions (f
, &x
, &y
);
5023 inev
.kind
= DEICONIFY_EVENT
;
5024 XSETFRAME (inev
.frame_or_window
, f
);
5026 else if (! NILP (Vframe_list
)
5027 && ! NILP (XCDR (Vframe_list
)))
5028 /* Force a redisplay sooner or later
5029 to update the frame titles
5030 in case this is the second frame. */
5031 record_asynch_buffer_change ();
5036 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
5044 GetClientRect (msg
.msg
.hwnd
, &rect
);
5046 height
= rect
.bottom
- rect
.top
;
5047 width
= rect
.right
- rect
.left
;
5049 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
5050 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
5052 /* TODO: Clip size to the screen dimensions. */
5054 /* Even if the number of character rows and columns has
5055 not changed, the font size may have changed, so we need
5056 to check the pixel dimensions as well. */
5058 if (columns
!= FRAME_COLS (f
)
5059 || rows
!= FRAME_LINES (f
)
5060 || width
!= FRAME_PIXEL_WIDTH (f
)
5061 || height
!= FRAME_PIXEL_HEIGHT (f
))
5063 change_frame_size (f
, rows
, columns
, 0, 1, 0);
5064 SET_FRAME_GARBAGED (f
);
5065 cancel_mouse_face (f
);
5066 FRAME_PIXEL_WIDTH (f
) = width
;
5067 FRAME_PIXEL_HEIGHT (f
) = height
;
5068 f
->win_gravity
= NorthWestGravity
;
5072 check_visibility
= 1;
5076 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5079 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5081 /* If we move outside the frame, then we're
5082 certainly no longer on any text in the frame. */
5083 clear_mouse_face (dpyinfo
);
5084 dpyinfo
->mouse_face_mouse_frame
= 0;
5087 /* Generate a nil HELP_EVENT to cancel a help-echo.
5088 Do it only if there's something to cancel.
5089 Otherwise, the startup message is cleared when
5090 the mouse leaves the frame. */
5091 if (any_help_event_p
)
5097 w32_detect_focus_change (dpyinfo
, &msg
, &inev
);
5099 dpyinfo
->grabbed
= 0;
5100 check_visibility
= 1;
5104 f
= x_top_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5108 if (f
== dpyinfo
->w32_focus_event_frame
)
5109 dpyinfo
->w32_focus_event_frame
= 0;
5111 if (f
== dpyinfo
->w32_focus_frame
)
5112 x_new_focus_frame (dpyinfo
, 0);
5114 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5116 /* If we move outside the frame, then we're
5117 certainly no longer on any text in the frame. */
5118 clear_mouse_face (dpyinfo
);
5119 dpyinfo
->mouse_face_mouse_frame
= 0;
5122 /* Generate a nil HELP_EVENT to cancel a help-echo.
5123 Do it only if there's something to cancel.
5124 Otherwise, the startup message is cleared when
5125 the mouse leaves the frame. */
5126 if (any_help_event_p
)
5130 dpyinfo
->grabbed
= 0;
5131 check_visibility
= 1;
5135 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5139 inev
.kind
= DELETE_WINDOW_EVENT
;
5140 XSETFRAME (inev
.frame_or_window
, f
);
5145 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5149 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
5150 XSETFRAME (inev
.frame_or_window
, f
);
5155 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5159 extern void menubar_selection_callback
5160 (FRAME_PTR f
, void * client_data
);
5161 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
5164 check_visibility
= 1;
5167 case WM_DISPLAYCHANGE
:
5168 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
5172 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
5173 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
5174 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
5175 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
5179 check_visibility
= 1;
5183 /* Check for messages registered at runtime. */
5184 if (msg
.msg
.message
== msh_mousewheel
)
5186 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
5187 msg
.msg
.message
= WM_MOUSEWHEEL
;
5193 if (inev
.kind
!= NO_EVENT
)
5195 kbd_buffer_store_event_hold (&inev
, hold_quit
);
5200 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
5205 XSETFRAME (frame
, f
);
5211 if (NILP (help_echo_string
))
5213 help_echo_object
= help_echo_window
= Qnil
;
5217 any_help_event_p
= 1;
5218 gen_help_event (help_echo_string
, frame
, help_echo_window
,
5219 help_echo_object
, help_echo_pos
);
5223 help_echo_string
= Qnil
;
5224 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
5230 /* If the focus was just given to an autoraising frame,
5232 /* ??? This ought to be able to handle more than one such frame. */
5233 if (pending_autoraise_frame
)
5235 x_raise_frame (pending_autoraise_frame
);
5236 pending_autoraise_frame
= 0;
5239 /* Check which frames are still visisble, if we have enqueued any user
5240 events or been notified of events that may affect visibility. We
5241 do this here because there doesn't seem to be any direct
5242 notification from Windows that the visibility of a window has
5243 changed (at least, not in all cases). */
5244 if (count
> 0 || check_visibility
)
5246 Lisp_Object tail
, frame
;
5248 FOR_EACH_FRAME (tail
, frame
)
5250 FRAME_PTR f
= XFRAME (frame
);
5251 /* The tooltip has been drawn already. Avoid the
5252 SET_FRAME_GARBAGED below. */
5253 if (EQ (frame
, tip_frame
))
5256 /* Check "visible" frames and mark each as obscured or not.
5257 Note that async_visible is nonzero for unobscured and
5258 obscured frames, but zero for hidden and iconified frames. */
5259 if (FRAME_W32_P (f
) && f
->async_visible
)
5265 /* Query clipping rectangle for the entire window area
5266 (GetWindowDC), not just the client portion (GetDC).
5267 Otherwise, the scrollbars and menubar aren't counted as
5268 part of the visible area of the frame, and we may think
5269 the frame is obscured when really a scrollbar is still
5270 visible and gets WM_PAINT messages above. */
5271 hdc
= GetWindowDC (FRAME_W32_WINDOW (f
));
5272 GetClipBox (hdc
, &clipbox
);
5273 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
5276 if (clipbox
.right
== clipbox
.left
5277 || clipbox
.bottom
== clipbox
.top
)
5279 /* Frame has become completely obscured so mark as
5280 such (we do this by setting async_visible to 2 so
5281 that FRAME_VISIBLE_P is still true, but redisplay
5283 f
->async_visible
= 2;
5285 if (!FRAME_OBSCURED_P (f
))
5287 DebPrint (("frame %p (%s) obscured\n", f
,
5293 /* Frame is not obscured, so mark it as such. */
5294 f
->async_visible
= 1;
5296 if (FRAME_OBSCURED_P (f
))
5298 SET_FRAME_GARBAGED (f
);
5299 DebPrint (("obscured frame %p (%s) found to be visible\n", f
,
5302 /* Force a redisplay sooner or later. */
5303 record_asynch_buffer_change ();
5316 /***********************************************************************
5318 ***********************************************************************/
5320 /* Set clipping for output in glyph row ROW. W is the window in which
5321 we operate. GC is the graphics context to set clipping in.
5323 ROW may be a text row or, e.g., a mode line. Text rows must be
5324 clipped to the interior of the window dedicated to text display,
5325 mode lines must be clipped to the whole window. */
5328 w32_clip_to_row (w
, row
, area
, hdc
)
5330 struct glyph_row
*row
;
5334 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5336 int window_x
, window_y
, window_width
;
5338 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5340 clip_rect
.left
= window_x
;
5341 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5342 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5343 clip_rect
.right
= clip_rect
.left
+ window_width
;
5344 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5346 w32_set_clip_rectangle (hdc
, &clip_rect
);
5350 /* Draw a hollow box cursor on window W in glyph row ROW. */
5353 x_draw_hollow_cursor (w
, row
)
5355 struct glyph_row
*row
;
5357 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5361 struct glyph
*cursor_glyph
;
5362 HBRUSH hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
5364 /* Get the glyph the cursor is on. If we can't tell because
5365 the current matrix is invalid or such, give up. */
5366 cursor_glyph
= get_phys_cursor_glyph (w
);
5367 if (cursor_glyph
== NULL
)
5370 /* Compute frame-relative coordinates for phys cursor. */
5371 get_phys_cursor_geometry (w
, row
, cursor_glyph
, &left
, &top
, &h
);
5374 rect
.bottom
= rect
.top
+ h
;
5375 rect
.right
= rect
.left
+ w
->phys_cursor_width
;
5377 hdc
= get_frame_dc (f
);
5378 /* Set clipping, draw the rectangle, and reset clipping again. */
5379 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
5380 FrameRect (hdc
, &rect
, hb
);
5382 w32_set_clip_rectangle (hdc
, NULL
);
5383 release_frame_dc (f
, hdc
);
5387 /* Draw a bar cursor on window W in glyph row ROW.
5389 Implementation note: One would like to draw a bar cursor with an
5390 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5391 Unfortunately, I didn't find a font yet that has this property set.
5395 x_draw_bar_cursor (w
, row
, width
, kind
)
5397 struct glyph_row
*row
;
5399 enum text_cursor_kinds kind
;
5401 struct frame
*f
= XFRAME (w
->frame
);
5402 struct glyph
*cursor_glyph
;
5406 /* If cursor is out of bounds, don't draw garbage. This can happen
5407 in mini-buffer windows when switching between echo area glyphs
5409 cursor_glyph
= get_phys_cursor_glyph (w
);
5410 if (cursor_glyph
== NULL
)
5413 /* If on an image, draw like a normal cursor. That's usually better
5414 visible than drawing a bar, esp. if the image is large so that
5415 the bar might not be in the window. */
5416 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5418 struct glyph_row
*row
;
5419 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5420 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5424 COLORREF cursor_color
= f
->output_data
.w32
->cursor_pixel
;
5425 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5427 /* If the glyph's background equals the color we normally draw
5428 the bar cursor in, the bar cursor in its normal color is
5429 invisible. Use the glyph's foreground color instead in this
5430 case, on the assumption that the glyph's colors are chosen so
5431 that the glyph is legible. */
5432 if (face
->background
== cursor_color
)
5433 cursor_color
= face
->foreground
;
5435 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5438 width
= FRAME_CURSOR_WIDTH (f
);
5439 width
= min (cursor_glyph
->pixel_width
, width
);
5441 w
->phys_cursor_width
= width
;
5444 hdc
= get_frame_dc (f
);
5445 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
5447 if (kind
== BAR_CURSOR
)
5449 w32_fill_area (f
, hdc
, cursor_color
, x
,
5450 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5451 width
, row
->height
);
5455 w32_fill_area (f
, hdc
, cursor_color
, x
,
5456 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5457 row
->height
- width
),
5458 cursor_glyph
->pixel_width
, width
);
5461 w32_set_clip_rectangle (hdc
, NULL
);
5462 release_frame_dc (f
, hdc
);
5467 /* RIF: Define cursor CURSOR on frame F. */
5470 w32_define_frame_cursor (f
, cursor
)
5474 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
5478 /* RIF: Clear area on frame F. */
5481 w32_clear_frame_area (f
, x
, y
, width
, height
)
5483 int x
, y
, width
, height
;
5487 hdc
= get_frame_dc (f
);
5488 w32_clear_area (f
, hdc
, x
, y
, width
, height
);
5489 release_frame_dc (f
, hdc
);
5492 /* RIF: Draw or clear cursor on window W. */
5495 w32_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5497 struct glyph_row
*glyph_row
;
5499 int cursor_type
, cursor_width
;
5504 /* If the user wants to use the system caret, make sure our own
5505 cursor remains invisible. */
5506 if (w32_use_visible_system_caret
)
5508 /* Call to erase_phys_cursor here seems to use the
5509 wrong values of w->phys_cursor, as they have been
5510 overwritten before this function was called. */
5511 if (w
->phys_cursor_type
!= NO_CURSOR
)
5512 erase_phys_cursor (w
);
5514 cursor_type
= w
->phys_cursor_type
= NO_CURSOR
;
5515 w
->phys_cursor_width
= -1;
5519 w
->phys_cursor_type
= cursor_type
;
5522 w
->phys_cursor_on_p
= 1;
5524 /* If this is the active cursor, we need to track it with the
5525 system caret, so third party software like screen magnifiers
5526 and speech synthesizers can follow the cursor. */
5529 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5530 HWND hwnd
= FRAME_W32_WINDOW (f
);
5533 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5535 = (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
5536 + glyph_row
->ascent
- w
->phys_cursor_ascent
);
5538 /* If the size of the active cursor changed, destroy the old
5540 if (w32_system_caret_hwnd
5541 && (w32_system_caret_height
!= w
->phys_cursor_height
))
5542 PostMessage (hwnd
, WM_EMACS_DESTROY_CARET
, 0, 0);
5544 w32_system_caret_height
= w
->phys_cursor_height
;
5546 /* Move the system caret. */
5547 PostMessage (hwnd
, WM_EMACS_TRACK_CARET
, 0, 0);
5550 if (glyph_row
->exact_window_width_line_p
5551 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5553 glyph_row
->cursor_in_fringe_p
= 1;
5554 draw_fringe_bitmap (w
, glyph_row
, 0);
5558 switch (cursor_type
)
5560 case HOLLOW_BOX_CURSOR
:
5561 x_draw_hollow_cursor (w
, glyph_row
);
5564 case FILLED_BOX_CURSOR
:
5565 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5569 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5573 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5577 w
->phys_cursor_width
= 0;
5591 x_bitmap_icon (f
, icon
)
5596 HANDLE small_icon
= NULL
;
5598 if (FRAME_W32_WINDOW (f
) == 0)
5602 main_icon
= LoadIcon (hinst
, EMACS_CLASS
);
5603 else if (STRINGP (icon
))
5605 /* Load the main icon from the named file. */
5606 main_icon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5607 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5608 /* Try to load a small icon to go with it. */
5609 small_icon
= LoadImage (NULL
, (LPCSTR
) SDATA (icon
), IMAGE_ICON
,
5610 GetSystemMetrics (SM_CXSMICON
),
5611 GetSystemMetrics (SM_CYSMICON
),
5614 else if (SYMBOLP (icon
))
5618 if (EQ (icon
, intern ("application")))
5619 name
= (LPCTSTR
) IDI_APPLICATION
;
5620 else if (EQ (icon
, intern ("hand")))
5621 name
= (LPCTSTR
) IDI_HAND
;
5622 else if (EQ (icon
, intern ("question")))
5623 name
= (LPCTSTR
) IDI_QUESTION
;
5624 else if (EQ (icon
, intern ("exclamation")))
5625 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5626 else if (EQ (icon
, intern ("asterisk")))
5627 name
= (LPCTSTR
) IDI_ASTERISK
;
5628 else if (EQ (icon
, intern ("winlogo")))
5629 name
= (LPCTSTR
) IDI_WINLOGO
;
5633 main_icon
= LoadIcon (NULL
, name
);
5638 if (main_icon
== NULL
)
5641 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5642 (LPARAM
) main_icon
);
5644 /* If there is a small icon that goes with it, set that too. */
5646 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_SMALL
,
5647 (LPARAM
) small_icon
);
5653 /************************************************************************
5655 ************************************************************************/
5657 /* Display Error Handling functions not used on W32. Listing them here
5658 helps diff stay in step when comparing w32term.c with xterm.c.
5660 x_error_catcher (display, error)
5661 x_catch_errors (dpy)
5662 x_catch_errors_unwind (old_val)
5663 x_check_errors (dpy, format)
5664 x_fully_uncatch_errors ()
5665 x_catching_errors ()
5666 x_had_errors_p (dpy)
5667 x_clear_errors (dpy)
5668 x_uncatch_errors (dpy, count)
5670 x_connection_signal (signalnum)
5671 x_connection_closed (dpy, error_message)
5672 x_error_quitter (display, error)
5673 x_error_handler (display, error)
5674 x_io_error_quitter (display)
5679 /* Changing the font of the frame. */
5681 /* Give frame F the font named FONTNAME as its default font, and
5682 return the full name of that font. FONTNAME may be a wildcard
5683 pattern; in that case, we choose some font that fits the pattern.
5684 The return value shows which font we chose. */
5687 x_new_font (f
, fontname
)
5689 register char *fontname
;
5691 struct font_info
*fontp
5692 = FS_LOAD_FONT (f
, fontname
);
5697 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5698 /* This font is already set in frame F. There's nothing more to
5700 return build_string (fontp
->full_name
);
5702 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5703 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5704 FRAME_FONTSET (f
) = -1;
5706 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5707 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5708 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5710 compute_fringe_widths (f
, 1);
5712 /* Compute the scroll bar width in character columns. */
5713 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5715 int wid
= FRAME_COLUMN_WIDTH (f
);
5716 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5717 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5721 int wid
= FRAME_COLUMN_WIDTH (f
);
5722 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5725 /* Now make the frame display the given font. */
5726 if (FRAME_W32_WINDOW (f
) != 0)
5728 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5729 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5732 return build_string (fontp
->full_name
);
5735 /* Give frame F the fontset named FONTSETNAME as its default fontset,
5736 and return the full name of that fontset. FONTSETNAME may be a
5737 wildcard pattern; in that case, we choose some fontset that fits
5738 the pattern. FONTSETNAME may be a font name for ASCII characters;
5739 in that case, we create a fontset from that font name.
5741 The return value shows which fontset we chose.
5742 If FONTSETNAME specifies the default fontset, return Qt.
5743 If an ASCII font in the specified fontset can't be loaded, return
5747 x_new_fontset (f
, fontsetname
)
5749 Lisp_Object fontsetname
;
5751 int fontset
= fs_query_fontset (fontsetname
, 0);
5754 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5755 /* This fontset is already set in frame F. There's nothing more
5757 return fontset_name (fontset
);
5758 else if (fontset
== 0)
5759 /* The default fontset can't be the default font. */
5763 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5765 result
= x_new_font (f
, SDATA (fontsetname
));
5767 if (!STRINGP (result
))
5768 /* Can't load ASCII font. */
5772 fontset
= new_fontset_from_font_name (result
);
5774 /* Since x_new_font doesn't update any fontset information, do it now. */
5775 FRAME_FONTSET(f
) = fontset
;
5777 return fontset_name (fontset
);
5780 #ifdef USE_FONT_BACKEND
5782 x_new_fontset2 (f
, fontset
, font_object
)
5785 Lisp_Object font_object
;
5787 struct font
*font
= XSAVE_VALUE (font_object
)->pointer
;
5789 if (FRAME_FONT_OBJECT (f
) == font
)
5790 /* This font is already set in frame F. There's nothing more to
5792 return fontset_name (fontset
);
5796 FRAME_FONT_OBJECT (f
) = font
;
5797 FRAME_FONT (f
) = font
->font
.font
;
5798 FRAME_BASELINE_OFFSET (f
) = font
->font
.baseline_offset
;
5799 FRAME_FONTSET (f
) = fontset
;
5801 FRAME_COLUMN_WIDTH (f
) = font
->font
.average_width
;
5802 FRAME_SPACE_WIDTH (f
) = font
->font
.space_width
;
5803 FRAME_LINE_HEIGHT (f
) = font
->font
.height
;
5805 compute_fringe_widths (f
, 1);
5807 /* Compute the scroll bar width in character columns. */
5808 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5810 int wid
= FRAME_COLUMN_WIDTH (f
);
5811 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5812 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
- 1) / wid
;
5816 int wid
= FRAME_COLUMN_WIDTH (f
);
5817 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5820 /* Now make the frame display the given font. */
5821 if (FRAME_X_WINDOW (f
) != 0)
5823 /* Don't change the size of a tip frame; there's no point in
5824 doing it because it's done in Fx_show_tip, and it leads to
5825 problems because the tip frame has no widget. */
5826 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5827 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5832 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
5833 xic_set_xfontset (f
, SDATA (fontset_ascii (fontset
)));
5838 return fontset_name (fontset
);
5840 #endif /* USE_FONT_BACKEND */
5843 /***********************************************************************
5844 TODO: W32 Input Methods
5845 ***********************************************************************/
5846 /* Listing missing functions from xterm.c helps diff stay in step.
5848 xim_destroy_callback (xim, client_data, call_data)
5849 xim_open_dpy (dpyinfo, resource_name)
5851 xim_instantiate_callback (display, client_data, call_data)
5852 xim_initialize (dpyinfo, resource_name)
5853 xim_close_dpy (dpyinfo)
5858 /* Calculate the absolute position in frame F
5859 from its current recorded position values and gravity. */
5862 x_calc_absolute_position (f
)
5865 int flags
= f
->size_hint_flags
;
5867 /* The sum of the widths of the frame's left and right borders, and
5868 the sum of the heights of the frame's top and bottom borders (in
5869 pixels) drawn by Windows. */
5870 unsigned int left_right_borders_width
, top_bottom_borders_height
;
5872 /* Try to get the actual values of these two variables. We compute
5873 the border width (height) by subtracting the width (height) of
5874 the frame's client area from the width (height) of the frame's
5876 WINDOWPLACEMENT wp
= { 0 };
5877 RECT client_rect
= { 0 };
5879 if (GetWindowPlacement (FRAME_W32_WINDOW (f
), &wp
)
5880 && GetClientRect (FRAME_W32_WINDOW (f
), &client_rect
))
5882 left_right_borders_width
=
5883 (wp
.rcNormalPosition
.right
- wp
.rcNormalPosition
.left
) -
5884 (client_rect
.right
- client_rect
.left
);
5886 top_bottom_borders_height
=
5887 (wp
.rcNormalPosition
.bottom
- wp
.rcNormalPosition
.top
) -
5888 (client_rect
.bottom
- client_rect
.top
);
5892 /* Use sensible default values. */
5893 left_right_borders_width
= 8;
5894 top_bottom_borders_height
= 32;
5897 /* Treat negative positions as relative to the rightmost bottommost
5898 position that fits on the screen. */
5899 if (flags
& XNegative
)
5900 f
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
5901 - FRAME_PIXEL_WIDTH (f
)
5903 - (left_right_borders_width
- 1));
5905 if (flags
& YNegative
)
5906 f
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
5907 - FRAME_PIXEL_HEIGHT (f
)
5909 - (top_bottom_borders_height
- 1));
5911 /* The left_pos and top_pos are now relative to the top and left
5912 screen edges, so the flags should correspond. */
5913 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5916 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5917 to really change the position, and 0 when calling from
5918 x_make_frame_visible (in that case, XOFF and YOFF are the current
5919 position values). It is -1 when calling from x_set_frame_parameters,
5920 which means, do adjust for borders but don't change the gravity. */
5923 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5925 register int xoff
, yoff
;
5928 int modified_top
, modified_left
;
5930 if (change_gravity
> 0)
5934 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5936 f
->size_hint_flags
|= XNegative
;
5938 f
->size_hint_flags
|= YNegative
;
5939 f
->win_gravity
= NorthWestGravity
;
5941 x_calc_absolute_position (f
);
5944 x_wm_set_size_hint (f
, (long) 0, 0);
5946 modified_left
= f
->left_pos
;
5947 modified_top
= f
->top_pos
;
5949 my_set_window_pos (FRAME_W32_WINDOW (f
),
5951 modified_left
, modified_top
,
5953 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5958 /* Check if we need to resize the frame due to a fullscreen request.
5959 If so needed, resize the frame. */
5961 x_check_fullscreen (f
)
5964 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
5966 int width
, height
, ign
;
5968 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5970 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
5972 /* We do not need to move the window, it shall be taken care of
5973 when setting WM manager hints. */
5974 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
5976 change_frame_size (f
, height
, width
, 0, 1, 0);
5977 SET_FRAME_GARBAGED (f
);
5978 cancel_mouse_face (f
);
5980 /* Wait for the change of frame size to occur */
5981 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
5986 /* Call this to change the size of frame F's x-window.
5987 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5988 for this size change and subsequent size changes.
5989 Otherwise we leave the window gravity unchanged. */
5992 x_set_window_size (f
, change_gravity
, cols
, rows
)
5997 int pixelwidth
, pixelheight
;
6001 check_frame_size (f
, &rows
, &cols
);
6002 f
->scroll_bar_actual_width
6003 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
6005 compute_fringe_widths (f
, 0);
6007 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
6008 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
6010 f
->win_gravity
= NorthWestGravity
;
6011 x_wm_set_size_hint (f
, (long) 0, 0);
6016 rect
.left
= rect
.top
= 0;
6017 rect
.right
= pixelwidth
;
6018 rect
.bottom
= pixelheight
;
6020 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
6021 FRAME_EXTERNAL_MENU_BAR (f
));
6023 my_set_window_pos (FRAME_W32_WINDOW (f
),
6026 rect
.right
- rect
.left
,
6027 rect
.bottom
- rect
.top
,
6028 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
6031 /* Now, strictly speaking, we can't be sure that this is accurate,
6032 but the window manager will get around to dealing with the size
6033 change request eventually, and we'll hear how it went when the
6034 ConfigureNotify event gets here.
6036 We could just not bother storing any of this information here,
6037 and let the ConfigureNotify event set everything up, but that
6038 might be kind of confusing to the Lisp code, since size changes
6039 wouldn't be reported in the frame parameters until some random
6040 point in the future when the ConfigureNotify event arrives.
6042 We pass 1 for DELAY since we can't run Lisp code inside of
6044 change_frame_size (f
, rows
, cols
, 0, 1, 0);
6045 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
6046 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
6048 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
6049 receive in the ConfigureNotify event; if we get what we asked
6050 for, then the event won't cause the screen to become garbaged, so
6051 we have to make sure to do it here. */
6052 SET_FRAME_GARBAGED (f
);
6054 /* If cursor was outside the new size, mark it as off. */
6055 mark_window_cursors_off (XWINDOW (f
->root_window
));
6057 /* Clear out any recollection of where the mouse highlighting was,
6058 since it might be in a place that's outside the new frame size.
6059 Actually checking whether it is outside is a pain in the neck,
6060 so don't try--just let the highlighting be done afresh with new size. */
6061 cancel_mouse_face (f
);
6066 /* Mouse warping. */
6068 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
6071 x_set_mouse_position (f
, x
, y
)
6077 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
6078 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
6080 if (pix_x
< 0) pix_x
= 0;
6081 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
6083 if (pix_y
< 0) pix_y
= 0;
6084 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
6086 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
6090 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
6099 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
6100 pt
.x
= rect
.left
+ pix_x
;
6101 pt
.y
= rect
.top
+ pix_y
;
6102 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
6104 SetCursorPos (pt
.x
, pt
.y
);
6110 /* focus shifting, raising and lowering. */
6113 x_focus_on_frame (f
)
6116 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6118 /* Give input focus to frame. */
6121 /* Try not to change its Z-order if possible. */
6122 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
6123 my_set_focus (f
, FRAME_W32_WINDOW (f
));
6126 my_set_foreground_window (FRAME_W32_WINDOW (f
));
6136 /* Raise frame F. */
6143 /* Strictly speaking, raise-frame should only change the frame's Z
6144 order, leaving input focus unchanged. This is reasonable behaviour
6145 on X where the usual policy is point-to-focus. However, this
6146 behaviour would be very odd on Windows where the usual policy is
6149 On X, if the mouse happens to be over the raised frame, it gets
6150 input focus anyway (so the window with focus will never be
6151 completely obscured) - if not, then just moving the mouse over it
6152 is sufficient to give it focus. On Windows, the user must actually
6153 click on the frame (preferrably the title bar so as not to move
6154 point), which is more awkward. Also, no other Windows program
6155 raises a window to the top but leaves another window (possibly now
6156 completely obscured) with input focus.
6158 Because there is a system setting on Windows that allows the user
6159 to choose the point to focus policy, we make the strict semantics
6160 optional, but by default we grab focus when raising. */
6162 if (NILP (Vw32_grab_focus_on_raise
))
6164 /* The obvious call to my_set_window_pos doesn't work if Emacs is
6165 not already the foreground application: the frame is raised
6166 above all other frames belonging to us, but not above the
6167 current top window. To achieve that, we have to resort to this
6168 more cumbersome method. */
6170 HDWP handle
= BeginDeferWindowPos (2);
6173 DeferWindowPos (handle
,
6174 FRAME_W32_WINDOW (f
),
6177 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
6179 DeferWindowPos (handle
,
6180 GetForegroundWindow (),
6181 FRAME_W32_WINDOW (f
),
6183 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
6185 EndDeferWindowPos (handle
);
6190 my_set_foreground_window (FRAME_W32_WINDOW (f
));
6196 /* Lower frame F. */
6202 my_set_window_pos (FRAME_W32_WINDOW (f
),
6205 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
6210 w32_frame_raise_lower (f
, raise_flag
)
6214 if (! FRAME_W32_P (f
))
6223 /* Change of visibility. */
6225 /* This tries to wait until the frame is really visible.
6226 However, if the window manager asks the user where to position
6227 the frame, this will return before the user finishes doing that.
6228 The frame will not actually be visible at that time,
6229 but it will become visible later when the window manager
6230 finishes with it. */
6233 x_make_frame_visible (f
)
6240 type
= x_icon_type (f
);
6242 x_bitmap_icon (f
, type
);
6244 if (! FRAME_VISIBLE_P (f
))
6246 /* We test FRAME_GARBAGED_P here to make sure we don't
6247 call x_set_offset a second time
6248 if we get to x_make_frame_visible a second time
6249 before the window gets really visible. */
6250 if (! FRAME_ICONIFIED_P (f
)
6251 && ! f
->output_data
.w32
->asked_for_visible
)
6256 /* Adjust vertical window position in order to avoid being
6257 covered by a task bar placed at the bottom of the desktop. */
6258 SystemParametersInfo(SPI_GETWORKAREA
, 0, &workarea_rect
, 0);
6259 GetWindowRect(FRAME_W32_WINDOW(f
), &window_rect
);
6260 if (window_rect
.bottom
> workarea_rect
.bottom
6261 && window_rect
.top
> workarea_rect
.top
)
6262 f
->top_pos
= max (window_rect
.top
6263 - window_rect
.bottom
+ workarea_rect
.bottom
,
6266 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6269 f
->output_data
.w32
->asked_for_visible
= 1;
6271 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
6272 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
6275 /* Synchronize to ensure Emacs knows the frame is visible
6276 before we do anything else. We do this loop with input not blocked
6277 so that incoming events are handled. */
6282 /* This must come after we set COUNT. */
6285 XSETFRAME (frame
, f
);
6287 /* Wait until the frame is visible. Process X events until a
6288 MapNotify event has been seen, or until we think we won't get a
6289 MapNotify at all.. */
6290 for (count
= input_signal_count
+ 10;
6291 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6293 /* Force processing of queued events. */
6294 /* TODO: x_sync equivalent? */
6296 /* Machines that do polling rather than SIGIO have been observed
6297 to go into a busy-wait here. So we'll fake an alarm signal
6298 to let the handler know that there's something to be read.
6299 We used to raise a real alarm, but it seems that the handler
6300 isn't always enabled here. This is probably a bug. */
6301 if (input_polling_used ())
6303 /* It could be confusing if a real alarm arrives while processing
6304 the fake one. Turn it off and let the handler reset it. */
6305 int old_poll_suppress_count
= poll_suppress_count
;
6306 poll_suppress_count
= 1;
6307 poll_for_input_1 ();
6308 poll_suppress_count
= old_poll_suppress_count
;
6311 FRAME_SAMPLE_VISIBILITY (f
);
6315 /* Change from mapped state to withdrawn state. */
6317 /* Make the frame visible (mapped and not iconified). */
6319 x_make_frame_invisible (f
)
6322 /* Don't keep the highlight on an invisible frame. */
6323 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6324 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6328 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
6330 /* We can't distinguish this from iconification
6331 just by the event that we get from the server.
6332 So we can't win using the usual strategy of letting
6333 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6334 and synchronize with the server to make sure we agree. */
6336 FRAME_ICONIFIED_P (f
) = 0;
6337 f
->async_visible
= 0;
6338 f
->async_iconified
= 0;
6343 /* Change window state from mapped to iconified. */
6351 /* Don't keep the highlight on an invisible frame. */
6352 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6353 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6355 if (f
->async_iconified
)
6360 type
= x_icon_type (f
);
6362 x_bitmap_icon (f
, type
);
6364 /* Simulate the user minimizing the frame. */
6365 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
6371 /* Free X resources of frame F. */
6374 x_free_frame_resources (f
)
6377 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6381 #ifdef USE_FONT_BACKEND
6382 /* We must free faces before destroying windows because some
6383 font-driver (e.g. xft) access a window while finishing a
6385 if (enable_font_backend
6386 && FRAME_FACE_CACHE (f
))
6387 free_frame_faces (f
);
6388 #endif /* USE_FONT_BACKEND */
6390 if (FRAME_W32_WINDOW (f
))
6391 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
6393 free_frame_menubar (f
);
6395 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
6396 unload_color (f
, f
->output_data
.x
->background_pixel
);
6397 unload_color (f
, f
->output_data
.w32
->cursor_pixel
);
6398 unload_color (f
, f
->output_data
.w32
->cursor_foreground_pixel
);
6399 unload_color (f
, f
->output_data
.w32
->border_pixel
);
6400 unload_color (f
, f
->output_data
.w32
->mouse_pixel
);
6401 if (f
->output_data
.w32
->white_relief
.allocated_p
)
6402 unload_color (f
, f
->output_data
.w32
->white_relief
.pixel
);
6403 if (f
->output_data
.w32
->black_relief
.allocated_p
)
6404 unload_color (f
, f
->output_data
.w32
->black_relief
.pixel
);
6406 if (FRAME_FACE_CACHE (f
))
6407 free_frame_faces (f
);
6409 xfree (f
->output_data
.w32
);
6410 f
->output_data
.w32
= NULL
;
6412 if (f
== dpyinfo
->w32_focus_frame
)
6413 dpyinfo
->w32_focus_frame
= 0;
6414 if (f
== dpyinfo
->w32_focus_event_frame
)
6415 dpyinfo
->w32_focus_event_frame
= 0;
6416 if (f
== dpyinfo
->x_highlight_frame
)
6417 dpyinfo
->x_highlight_frame
= 0;
6419 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6421 dpyinfo
->mouse_face_beg_row
6422 = dpyinfo
->mouse_face_beg_col
= -1;
6423 dpyinfo
->mouse_face_end_row
6424 = dpyinfo
->mouse_face_end_col
= -1;
6425 dpyinfo
->mouse_face_window
= Qnil
;
6426 dpyinfo
->mouse_face_deferred_gc
= 0;
6427 dpyinfo
->mouse_face_mouse_frame
= 0;
6434 /* Destroy the window of frame F. */
6436 x_destroy_window (f
)
6439 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6441 x_free_frame_resources (f
);
6443 dpyinfo
->reference_count
--;
6447 /* Setting window manager hints. */
6449 /* Set the normal size hints for the window manager, for frame F.
6450 FLAGS is the flags word to use--or 0 meaning preserve the flags
6451 that the window now has.
6452 If USER_POSITION is nonzero, we set the USPosition
6453 flag (this is useful when FLAGS is 0). */
6455 x_wm_set_size_hint (f
, flags
, user_position
)
6460 Window window
= FRAME_W32_WINDOW (f
);
6464 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
6465 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
6466 SetWindowLong (window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
6467 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
6472 /* Window manager things */
6474 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6479 Window window
= FRAME_W32_WINDOW (f
);
6481 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6482 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6483 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6485 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
6490 /***********************************************************************
6492 ***********************************************************************/
6494 /* The following functions are listed here to help diff stay in step
6495 with xterm.c. See w32fns.c for definitions.
6497 x_get_font_info (f, font_idx)
6498 x_list_fonts (f, pattern, size, maxnames)
6504 /* Check that FONT is valid on frame F. It is if it can be found in F's
6508 x_check_font (f
, font
)
6513 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6515 xassert (font
!= NULL
);
6517 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6518 if (dpyinfo
->font_table
[i
].name
6519 && font
== dpyinfo
->font_table
[i
].font
)
6522 xassert (i
< dpyinfo
->n_fonts
);
6525 #endif /* GLYPH_DEBUG != 0 */
6527 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6528 Note: There are (broken) X fonts out there with invalid XFontStruct
6529 min_bounds contents. For example, handa@etl.go.jp reports that
6530 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6531 have font->min_bounds.width == 0. */
6534 x_font_min_bounds (font
, w
, h
)
6539 * TODO: Windows does not appear to offer min bound, only
6540 * average and maximum width, and maximum height.
6542 *h
= FONT_HEIGHT (font
);
6543 *w
= FONT_AVG_WIDTH (font
);
6547 /* Compute the smallest character width and smallest font height over
6548 all fonts available on frame F. Set the members smallest_char_width
6549 and smallest_font_height in F's x_display_info structure to
6550 the values computed. Value is non-zero if smallest_font_height or
6551 smallest_char_width become smaller than they were before. */
6554 x_compute_min_glyph_bounds (f
)
6558 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6560 int old_width
= dpyinfo
->smallest_char_width
;
6561 int old_height
= dpyinfo
->smallest_font_height
;
6563 dpyinfo
->smallest_font_height
= 100000;
6564 dpyinfo
->smallest_char_width
= 100000;
6566 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6567 if (dpyinfo
->font_table
[i
].name
)
6569 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6572 font
= (XFontStruct
*) fontp
->font
;
6573 xassert (font
!= (XFontStruct
*) ~0);
6574 x_font_min_bounds (font
, &w
, &h
);
6576 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6577 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6580 xassert (dpyinfo
->smallest_char_width
> 0
6581 && dpyinfo
->smallest_font_height
> 0);
6583 return (dpyinfo
->n_fonts
== 1
6584 || dpyinfo
->smallest_char_width
< old_width
6585 || dpyinfo
->smallest_font_height
< old_height
);
6588 /* The following functions are listed here to help diff stay in step
6589 with xterm.c. See w32fns.c for definitions.
6591 x_load_font (f, fontname, size)
6592 x_query_font (f, fontname)
6593 x_find_ccl_program (fontp)
6597 /***********************************************************************
6599 ***********************************************************************/
6601 static int w32_initialized
= 0;
6604 w32_initialize_display_info (display_name
)
6605 Lisp_Object display_name
;
6607 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6609 bzero (dpyinfo
, sizeof (*dpyinfo
));
6611 /* Put it on w32_display_name_list. */
6612 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6613 w32_display_name_list
);
6614 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
6616 dpyinfo
->w32_id_name
6617 = (char *) xmalloc (SCHARS (Vinvocation_name
)
6618 + SCHARS (Vsystem_name
)
6620 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
6621 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
6623 /* Default Console mode values - overridden when running in GUI mode
6624 with values obtained from system metrics. */
6627 dpyinfo
->height_in
= 1;
6628 dpyinfo
->width_in
= 1;
6629 dpyinfo
->n_planes
= 1;
6630 dpyinfo
->n_cbits
= 4;
6631 dpyinfo
->n_fonts
= 0;
6632 dpyinfo
->smallest_font_height
= 1;
6633 dpyinfo
->smallest_char_width
= 1;
6635 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6636 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6637 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
6638 dpyinfo
->mouse_face_window
= Qnil
;
6639 dpyinfo
->mouse_face_overlay
= Qnil
;
6640 dpyinfo
->mouse_face_hidden
= 0;
6642 dpyinfo
->vertical_scroll_bar_cursor
= w32_load_cursor (IDC_ARROW
);
6643 /* TODO: dpyinfo->gray */
6647 /* Create an xrdb-style database of resources to supercede registry settings.
6648 The database is just a concatenation of C strings, finished by an additional
6649 \0. The string are submitted to some basic normalization, so
6651 [ *]option[ *]:[ *]value...
6657 but any whitespace following value is not removed. */
6660 w32_make_rdb (xrm_option
)
6663 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
6664 char *current
= buffer
;
6667 int before_value
= 0;
6681 if (in_option
&& (ch
== ':'))
6686 else if (before_value
)
6691 else if (!(in_option
|| before_value
))
6702 struct w32_display_info
*
6703 w32_term_init (display_name
, xrm_option
, resource_name
)
6704 Lisp_Object display_name
;
6706 char *resource_name
;
6708 struct w32_display_info
*dpyinfo
;
6713 if (!w32_initialized
)
6716 w32_initialized
= 1;
6719 w32_initialize_display_info (display_name
);
6721 dpyinfo
= &one_w32_display_info
;
6723 dpyinfo
->xrdb
= xrm_option
? w32_make_rdb (xrm_option
) : NULL
;
6725 /* Put this display on the chain. */
6726 dpyinfo
->next
= x_display_list
;
6727 x_display_list
= dpyinfo
;
6729 hdc
= GetDC (GetDesktopWindow ());
6731 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
6732 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
6733 dpyinfo
->root_window
= GetDesktopWindow ();
6734 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
6735 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
6736 dpyinfo
->resx
= GetDeviceCaps (hdc
, LOGPIXELSX
);
6737 dpyinfo
->resy
= GetDeviceCaps (hdc
, LOGPIXELSY
);
6738 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
6739 dpyinfo
->image_cache
= make_image_cache ();
6740 dpyinfo
->height_in
= dpyinfo
->height
/ dpyinfo
->resx
;
6741 dpyinfo
->width_in
= dpyinfo
->width
/ dpyinfo
->resy
;
6742 ReleaseDC (GetDesktopWindow (), hdc
);
6744 /* initialise palette with white and black */
6747 w32_defined_color (0, "white", &color
, 1);
6748 w32_defined_color (0, "black", &color
, 1);
6751 /* Create Fringe Bitmaps and store them for later use.
6753 On W32, bitmaps are all unsigned short, as Windows requires
6754 bitmap data to be Word aligned. For some reason they are
6755 horizontally reflected compared to how they appear on X, so we
6756 need to bitswap and convert to unsigned shorts before creating
6760 #ifndef F_SETOWN_BUG
6762 #ifdef F_SETOWN_SOCK_NEG
6763 /* stdin is a socket here */
6764 fcntl (connection
, F_SETOWN
, -getpid ());
6765 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6766 fcntl (connection
, F_SETOWN
, getpid ());
6767 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6768 #endif /* ! defined (F_SETOWN) */
6769 #endif /* F_SETOWN_BUG */
6772 if (interrupt_input
)
6773 init_sigio (connection
);
6774 #endif /* ! defined (SIGIO) */
6781 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6784 x_delete_display (dpyinfo
)
6785 struct w32_display_info
*dpyinfo
;
6787 /* Discard this display from w32_display_name_list and w32_display_list.
6788 We can't use Fdelq because that can quit. */
6789 if (! NILP (w32_display_name_list
)
6790 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
6791 w32_display_name_list
= XCDR (w32_display_name_list
);
6796 tail
= w32_display_name_list
;
6797 while (CONSP (tail
) && CONSP (XCDR (tail
)))
6799 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
6801 XSETCDR (tail
, XCDR (XCDR (tail
)));
6808 /* free palette table */
6810 struct w32_palette_entry
* plist
;
6812 plist
= dpyinfo
->color_list
;
6815 struct w32_palette_entry
* pentry
= plist
;
6816 plist
= plist
->next
;
6819 dpyinfo
->color_list
= NULL
;
6820 if (dpyinfo
->palette
)
6821 DeleteObject(dpyinfo
->palette
);
6823 xfree (dpyinfo
->font_table
);
6824 xfree (dpyinfo
->w32_id_name
);
6826 w32_reset_fringes ();
6829 /* Set up use of W32. */
6831 DWORD WINAPI
w32_msg_worker (void * arg
);
6834 x_flush (struct frame
* f
)
6835 { /* Nothing to do */ }
6837 extern frame_parm_handler w32_frame_parm_handlers
[];
6839 static struct redisplay_interface w32_redisplay_interface
=
6841 w32_frame_parm_handlers
,
6845 x_clear_end_of_line
,
6847 x_after_update_window_line
,
6848 x_update_window_begin
,
6849 x_update_window_end
,
6852 0, /* flush_display_optional */
6853 x_clear_window_mouse_face
,
6854 w32_get_glyph_overhangs
,
6855 x_fix_overlapping_area
,
6856 w32_draw_fringe_bitmap
,
6857 w32_define_fringe_bitmap
,
6858 w32_destroy_fringe_bitmap
,
6859 w32_per_char_metric
,
6861 NULL
, /* w32_compute_glyph_string_overhangs */
6862 x_draw_glyph_string
,
6863 w32_define_frame_cursor
,
6864 w32_clear_frame_area
,
6865 w32_draw_window_cursor
,
6866 w32_draw_vertical_window_border
,
6867 w32_shift_glyphs_for_insert
6873 rif
= &w32_redisplay_interface
;
6875 /* MSVC does not type K&R functions with no arguments correctly, and
6876 so we must explicitly cast them. */
6877 clear_frame_hook
= (void (*)(void)) x_clear_frame
;
6878 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
6879 update_begin_hook
= x_update_begin
;
6880 update_end_hook
= x_update_end
;
6882 read_socket_hook
= w32_read_socket
;
6884 frame_up_to_date_hook
= w32_frame_up_to_date
;
6886 mouse_position_hook
= w32_mouse_position
;
6887 frame_rehighlight_hook
= w32_frame_rehighlight
;
6888 frame_raise_lower_hook
= w32_frame_raise_lower
;
6889 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
6890 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
6891 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
6892 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
6894 scroll_region_ok
= 1; /* we'll scroll partial frames */
6895 char_ins_del_ok
= 1;
6896 line_ins_del_ok
= 1; /* we'll just blt 'em */
6897 fast_clear_end_of_line
= 1; /* X does this well */
6898 memory_below_frame
= 0; /* we don't remember what scrolls
6902 w32_system_caret_hwnd
= NULL
;
6903 w32_system_caret_height
= 0;
6904 w32_system_caret_x
= 0;
6905 w32_system_caret_y
= 0;
6907 /* Initialize w32_use_visible_system_caret based on whether a screen
6908 reader is in use. */
6909 if (!SystemParametersInfo (SPI_GETSCREENREADER
, 0,
6910 &w32_use_visible_system_caret
, 0))
6911 w32_use_visible_system_caret
= 0;
6913 last_tool_bar_item
= -1;
6914 any_help_event_p
= 0;
6916 /* Initialize input mode: interrupt_input off, no flow control, allow
6917 8 bit character input, standard quit char. */
6918 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
6920 /* Create the window thread - it will terminate itself or when the app terminates */
6924 dwMainThreadId
= GetCurrentThreadId ();
6925 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6926 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
6928 /* Wait for thread to start */
6933 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
6935 hWindowsThread
= CreateThread (NULL
, 0,
6937 0, 0, &dwWindowsThreadId
);
6939 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6942 /* It is desirable that mainThread should have the same notion of
6943 focus window and active window as windowsThread. Unfortunately, the
6944 following call to AttachThreadInput, which should do precisely what
6945 we need, causes major problems when Emacs is linked as a console
6946 program. Unfortunately, we have good reasons for doing that, so
6947 instead we need to send messages to windowsThread to make some API
6948 calls for us (ones that affect, or depend on, the active/focus
6950 #ifdef ATTACH_THREADS
6951 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
6954 /* Dynamically link to optional system components. */
6956 UINT smoothing_type
;
6957 BOOL smoothing_enabled
;
6959 HANDLE gdi_lib
= LoadLibrary ("gdi32.dll");
6961 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6963 LOAD_PROC (gdi_lib
, GetFontUnicodeRanges
);
6967 FreeLibrary (gdi_lib
);
6969 /* Ensure scrollbar handle is at least 5 pixels. */
6970 vertical_scroll_bar_min_handle
= 5;
6972 /* For either kind of scroll bar, take account of the arrows; these
6973 effectively form the border of the main scroll bar range. */
6974 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
6975 = GetSystemMetrics (SM_CYVSCROLL
);
6977 /* Constants that are not always defined by the system headers
6978 since they only exist on certain versions of Windows. */
6979 #ifndef SPI_GETFONTSMOOTHING
6980 #define SPI_GETFONTSMOOTHING 0x4A
6982 #ifndef SPI_GETFONTSMOOTHINGTYPE
6983 #define SPI_GETFONTSMOOTHINGTYPE 0x0200A
6985 #ifndef FE_FONTSMOOTHINGCLEARTYPE
6986 #define FE_FONTSMOOTHINGCLEARTYPE 0x2
6989 /* Determine if Cleartype is in use. Used to enable a hack in
6990 the char metric calculations which adds extra pixels to
6991 compensate for the "sub-pixels" that are not counted by the
6994 SystemParametersInfo (SPI_GETFONTSMOOTHING
, 0, &smoothing_enabled
, 0)
6995 && smoothing_enabled
6996 && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE
, 0, &smoothing_type
, 0)
6997 && smoothing_type
== FE_FONTSMOOTHINGCLEARTYPE
;
7004 staticpro (&w32_display_name_list
);
7005 w32_display_name_list
= Qnil
;
7007 staticpro (&last_mouse_scroll_bar
);
7008 last_mouse_scroll_bar
= Qnil
;
7010 DEFSYM (Qvendor_specific_keysyms
, "vendor-specific-keysyms");
7012 DEFVAR_INT ("w32-num-mouse-buttons",
7013 &w32_num_mouse_buttons
,
7014 doc
: /* Number of physical mouse buttons. */);
7015 w32_num_mouse_buttons
= 2;
7017 DEFVAR_LISP ("w32-swap-mouse-buttons",
7018 &Vw32_swap_mouse_buttons
,
7019 doc
: /* Swap the mapping of middle and right mouse buttons.
7020 When nil, middle button is mouse-2 and right button is mouse-3. */);
7021 Vw32_swap_mouse_buttons
= Qnil
;
7023 DEFVAR_LISP ("w32-grab-focus-on-raise",
7024 &Vw32_grab_focus_on_raise
,
7025 doc
: /* Raised frame grabs input focus.
7026 When t, `raise-frame' grabs input focus as well. This fits well
7027 with the normal Windows click-to-focus policy, but might not be
7028 desirable when using a point-to-focus policy. */);
7029 Vw32_grab_focus_on_raise
= Qt
;
7031 DEFVAR_LISP ("w32-capslock-is-shiftlock",
7032 &Vw32_capslock_is_shiftlock
,
7033 doc
: /* Apply CapsLock state to non character input keys.
7034 When nil, CapsLock only affects normal character input keys. */);
7035 Vw32_capslock_is_shiftlock
= Qnil
;
7037 DEFVAR_LISP ("w32-recognize-altgr",
7038 &Vw32_recognize_altgr
,
7039 doc
: /* Recognize right-alt and left-ctrl as AltGr.
7040 When nil, the right-alt and left-ctrl key combination is
7041 interpreted normally. */);
7042 Vw32_recognize_altgr
= Qt
;
7044 DEFVAR_BOOL ("w32-enable-unicode-output",
7045 &w32_enable_unicode_output
,
7046 doc
: /* Enable the use of Unicode for text output if non-nil.
7047 Unicode output may prevent some third party applications for displaying
7048 Far-East Languages on Windows 95/98 from working properly.
7049 NT uses Unicode internally anyway, so this flag will probably have no
7050 affect on NT machines. */);
7051 w32_enable_unicode_output
= 1;
7053 DEFVAR_BOOL ("w32-use-visible-system-caret",
7054 &w32_use_visible_system_caret
,
7055 doc
: /* Flag to make the system caret visible.
7056 When this is non-nil, Emacs will indicate the position of point by
7057 using the system caret instead of drawing its own cursor. Some screen
7058 reader software does not track the system cursor properly when it is
7059 invisible, and gets confused by Emacs drawing its own cursor, so this
7060 variable is initialized to t when Emacs detects that screen reader
7061 software is running as it starts up.
7063 When this variable is set, other variables affecting the appearance of
7064 the cursor have no effect. */);
7066 w32_use_visible_system_caret
= 0;
7068 /* We don't yet support this, but defining this here avoids whining
7069 from cus-start.el and other places, like "M-x set-variable". */
7070 DEFVAR_BOOL ("x-use-underline-position-properties",
7071 &x_use_underline_position_properties
,
7072 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
7073 A value of nil means ignore them. If you encounter fonts with bogus
7074 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
7075 to 4.1, set this to nil.
7077 NOTE: Not supported on MS-Windows yet. */);
7078 x_use_underline_position_properties
= 0;
7080 DEFVAR_BOOL ("x-underline-at-descent-line",
7081 &x_underline_at_descent_line
,
7082 doc
: /* *Non-nil means to draw the underline at the same place as the descent line.
7083 A value of nil means to draw the underline according to the value of the
7084 variable `x-use-underline-position-properties', which is usually at the
7085 baseline level. The default value is nil. */);
7086 x_underline_at_descent_line
= 0;
7088 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
7089 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
7090 Vx_toolkit_scroll_bars
= Qt
;
7092 staticpro (&last_mouse_motion_frame
);
7093 last_mouse_motion_frame
= Qnil
;
7096 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
7097 (do not change this comment) */