1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
28 #include "blockinput.h"
47 #include "dispextern.h"
49 #include "termhooks.h"
56 #include "intervals.h"
57 #include "composite.h"
60 #define abs(x) ((x) < 0 ? -(x) : (x))
62 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
67 static HBITMAP fringe_bmp
[MAX_FRINGE_BITMAPS
];
69 extern Lisp_Object Qhelp_echo
;
71 /* Non-nil means Emacs uses toolkit scroll bars. */
73 Lisp_Object Vx_toolkit_scroll_bars
;
75 /* If a string, w32_read_socket generates an event to display that string.
76 (The display is done in read_char.) */
78 static Lisp_Object help_echo
;
79 static Lisp_Object help_echo_window
;
80 static Lisp_Object help_echo_object
;
81 static int help_echo_pos
;
83 /* Temporary variables for w32_read_socket. */
85 static Lisp_Object previous_help_echo
;
86 static int last_mousemove_x
= 0;
87 static int last_mousemove_y
= 0;
89 /* Non-zero means that a HELP_EVENT has been generated since Emacs
92 static int any_help_event_p
;
94 /* Non-zero means autoselect window with the mouse cursor. */
96 int mouse_autoselect_window
;
98 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
99 static Lisp_Object last_window
;
101 /* Non-zero means draw block and hollow cursor as wide as the glyph
102 under it. For example, if a block cursor is over a tab, it will be
103 drawn as wide as that tab on the display. */
105 int x_stretch_cursor_p
;
107 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
109 int x_use_underline_position_properties
;
111 extern unsigned int msh_mousewheel
;
113 extern void free_frame_menubar ();
115 extern int w32_codepage_for_font (char *fontname
);
116 extern Cursor
w32_load_cursor (LPCTSTR name
);
118 extern glyph_metric
*w32_BDF_TextMetric(bdffont
*fontp
,
119 unsigned char *text
, int dim
);
120 extern Lisp_Object Vwindow_system
;
122 #define x_any_window_to_frame x_window_to_frame
123 #define x_top_window_to_frame x_window_to_frame
126 /* This is display since w32 does not support multiple ones. */
127 struct w32_display_info one_w32_display_info
;
128 struct w32_display_info
*x_display_list
;
130 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
131 one for each element of w32_display_list and in the same order.
132 NAME is the name of the frame.
133 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
134 Lisp_Object w32_display_name_list
;
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the
138 w32 functions. It is zero while not inside an update.
139 In that case, the w32 functions assume that `SELECTED_FRAME ()'
140 is the frame to apply to. */
141 extern struct frame
*updating_frame
;
143 /* This is a frame waiting to be autoraised, within w32_read_socket. */
144 struct frame
*pending_autoraise_frame
;
146 /* Nominal cursor position -- where to draw output.
147 HPOS and VPOS are window relative glyph matrix coordinates.
148 X and Y are window relative pixel coordinates. */
150 struct cursor_pos output_cursor
;
152 /* The handle of the frame that currently owns the system caret. */
153 HWND w32_system_caret_hwnd
;
154 int w32_system_caret_height
;
155 int w32_system_caret_x
;
156 int w32_system_caret_y
;
157 int w32_use_visible_system_caret
;
159 /* Flag to enable Unicode output in case users wish to use programs
160 like Twinbridge on '95 rather than installed system level support
161 for Far East languages. */
162 int w32_enable_unicode_output
;
164 DWORD dwWindowsThreadId
= 0;
165 HANDLE hWindowsThread
= NULL
;
166 DWORD dwMainThreadId
= 0;
167 HANDLE hMainThread
= NULL
;
170 /* These definitions are new with Windows 95. */
171 #define SIF_RANGE 0x0001
172 #define SIF_PAGE 0x0002
173 #define SIF_POS 0x0004
174 #define SIF_DISABLENOSCROLL 0x0008
175 #define SIF_TRACKPOS 0x0010
176 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
178 typedef struct tagSCROLLINFO
187 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
188 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
191 /* Dynamic linking to new proportional scroll bar functions. */
192 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
193 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
195 int vertical_scroll_bar_min_handle
;
196 int vertical_scroll_bar_top_border
;
197 int vertical_scroll_bar_bottom_border
;
199 int last_scroll_bar_drag_pos
;
201 /* Mouse movement. */
203 /* Where the mouse was last time we reported a mouse event. */
205 FRAME_PTR last_mouse_frame
;
206 static RECT last_mouse_glyph
;
207 static Lisp_Object last_mouse_press_frame
;
209 Lisp_Object Vw32_num_mouse_buttons
;
211 Lisp_Object Vw32_swap_mouse_buttons
;
213 /* Control whether x_raise_frame also sets input focus. */
214 Lisp_Object Vw32_grab_focus_on_raise
;
216 /* Control whether Caps Lock affects non-ascii characters. */
217 Lisp_Object Vw32_capslock_is_shiftlock
;
219 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
220 Lisp_Object Vw32_recognize_altgr
;
222 /* The scroll bar in which the last motion event occurred.
224 If the last motion event occurred in a scroll bar, we set this
225 so w32_mouse_position can know whether to report a scroll bar motion or
228 If the last motion event didn't occur in a scroll bar, we set this
229 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
230 static Lisp_Object last_mouse_scroll_bar
;
231 static int last_mouse_scroll_bar_pos
;
233 /* This is a hack. We would really prefer that w32_mouse_position would
234 return the time associated with the position it returns, but there
235 doesn't seem to be any way to wrest the time-stamp from the server
236 along with the position query. So, we just keep track of the time
237 of the last movement we received, and return that in hopes that
238 it's somewhat accurate. */
240 static Time last_mouse_movement_time
;
242 /* Incremented by w32_read_socket whenever it really tries to read
246 static int volatile input_signal_count
;
248 static int input_signal_count
;
251 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
253 extern Lisp_Object Qface
, Qmouse_face
;
259 /* A mask of extra modifier bits to put into every keyboard char. */
261 extern EMACS_INT extra_keyboard_modifiers
;
263 static void x_update_window_end
P_ ((struct window
*, int, int));
264 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
265 void w32_delete_display
P_ ((struct w32_display_info
*));
266 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
267 int *, int *, Lisp_Object
));
268 static int fast_find_string_pos
P_ ((struct window
*, int, Lisp_Object
,
269 int *, int *, int *, int *, int));
270 static void set_output_cursor
P_ ((struct cursor_pos
*));
271 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
272 int *, int *, int *, int));
273 static void note_mode_line_or_margin_highlight
P_ ((struct window
*, int,
275 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
276 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
277 static void w32_handle_tool_bar_click
P_ ((struct frame
*,
278 struct input_event
*));
279 static void show_mouse_face
P_ ((struct w32_display_info
*,
280 enum draw_glyphs_face
));
281 static int cursor_in_mouse_face_p
P_ ((struct window
*));
282 static int clear_mouse_face
P_ ((struct w32_display_info
*));
283 void w32_define_cursor
P_ ((Window
, Cursor
));
285 void x_lower_frame
P_ ((struct frame
*));
286 void x_scroll_bar_clear
P_ ((struct frame
*));
287 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
288 void x_raise_frame
P_ ((struct frame
*));
289 void x_set_window_size
P_ ((struct frame
*, int, int, int));
290 void x_wm_set_window_state
P_ ((struct frame
*, int));
291 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
292 void w32_initialize
P_ ((void));
293 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
294 int x_compute_min_glyph_bounds
P_ ((struct frame
*));
295 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
297 enum draw_glyphs_face
));
298 static void x_update_end
P_ ((struct frame
*));
299 static void w32_frame_up_to_date
P_ ((struct frame
*));
300 static void w32_set_terminal_modes
P_ ((void));
301 static void w32_reset_terminal_modes
P_ ((void));
302 static void w32_cursor_to
P_ ((int, int, int, int));
303 static void x_write_glyphs
P_ ((struct glyph
*, int));
304 static void x_clear_end_of_line
P_ ((int));
305 static void x_clear_frame
P_ ((void));
306 static void x_clear_cursor
P_ ((struct window
*));
307 static void frame_highlight
P_ ((struct frame
*));
308 static void frame_unhighlight
P_ ((struct frame
*));
309 static void x_new_focus_frame
P_ ((struct w32_display_info
*,
311 static void w32_frame_rehighlight
P_ ((struct frame
*));
312 static void x_frame_rehighlight
P_ ((struct w32_display_info
*));
313 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
314 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
315 enum text_cursor_kinds
));
316 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
317 static int expose_window_tree
P_ ((struct window
*, RECT
*));
318 static void expose_overlaps
P_ ((struct window
*, struct glyph_row
*,
319 struct glyph_row
*));
320 static int expose_window
P_ ((struct window
*, RECT
*));
321 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
322 RECT
*, enum glyph_row_area
));
323 static int expose_line
P_ ((struct window
*, struct glyph_row
*,
325 void x_update_cursor
P_ ((struct frame
*, int));
326 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
327 static void x_update_window_cursor
P_ ((struct window
*, int));
328 static void x_erase_phys_cursor
P_ ((struct window
*));
329 void x_display_cursor
P_ ((struct window
*w
, int, int, int, int, int));
330 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
331 static void w32_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
333 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, RECT
*));
335 static Lisp_Object Qvendor_specific_keysyms
;
338 /***********************************************************************
340 ***********************************************************************/
344 /* This is a function useful for recording debugging information about
345 the sequence of occurrences in this file. */
353 struct record event_record
[100];
355 int event_record_index
;
357 record_event (locus
, type
)
361 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
362 event_record_index
= 0;
364 event_record
[event_record_index
].locus
= locus
;
365 event_record
[event_record_index
].type
= type
;
366 event_record_index
++;
372 void XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
375 if (mask
& GCForeground
)
376 gc
->foreground
= xgcv
->foreground
;
377 if (mask
& GCBackground
)
378 gc
->background
= xgcv
->background
;
380 gc
->font
= xgcv
->font
;
383 XGCValues
*XCreateGC (void * ignore
, Window window
, unsigned long mask
,
386 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
387 bzero (gc
, sizeof (XGCValues
));
389 XChangeGC (ignore
, gc
, mask
, xgcv
);
394 void XGetGCValues (void* ignore
, XGCValues
*gc
,
395 unsigned long mask
, XGCValues
*xgcv
)
397 XChangeGC (ignore
, xgcv
, mask
, gc
);
401 w32_set_clip_rectangle (HDC hdc
, RECT
*rect
)
405 HRGN clip_region
= CreateRectRgnIndirect (rect
);
406 SelectClipRgn (hdc
, clip_region
);
407 DeleteObject (clip_region
);
410 SelectClipRgn (hdc
, NULL
);
414 /* Draw a hollow rectangle at the specified position. */
416 w32_draw_rectangle (HDC hdc
, XGCValues
*gc
, int x
, int y
,
417 int width
, int height
)
422 hb
= CreateSolidBrush (gc
->background
);
423 hp
= CreatePen (PS_SOLID
, 0, gc
->foreground
);
424 oldhb
= SelectObject (hdc
, hb
);
425 oldhp
= SelectObject (hdc
, hp
);
427 Rectangle (hdc
, x
, y
, x
+ width
, y
+ height
);
429 SelectObject (hdc
, oldhb
);
430 SelectObject (hdc
, oldhp
);
435 /* Draw a filled rectangle at the specified position. */
437 w32_fill_rect (f
, hdc
, pix
, lprect
)
445 hb
= CreateSolidBrush (pix
);
446 FillRect (hdc
, lprect
, hb
);
455 HDC hdc
= get_frame_dc (f
);
457 /* Under certain conditions, this can be called at startup with
458 a console frame pointer before the GUI frame is created. An HDC
459 of 0 indicates this. */
462 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
463 w32_clear_rect (f
, hdc
, &rect
);
466 release_frame_dc (f
, hdc
);
470 /***********************************************************************
471 Starting and ending an update
472 ***********************************************************************/
474 /* Start an update of frame F. This function is installed as a hook
475 for update_begin, i.e. it is called when update_begin is called.
476 This function is called prior to calls to x_update_window_begin for
477 each window being updated. */
483 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
485 if (! FRAME_W32_P (f
))
488 /* Regenerate display palette before drawing if list of requested
489 colors has changed. */
490 if (display_info
->regen_palette
)
492 w32_regenerate_palette (f
);
493 display_info
->regen_palette
= FALSE
;
498 /* Start update of window W. Set the global variable updated_window
499 to the window being updated and set output_cursor to the cursor
503 x_update_window_begin (w
)
506 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
507 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
509 /* Hide the system caret during an update. */
510 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
512 SendMessage (w32_system_caret_hwnd
, WM_EMACS_HIDE_CARET
, 0, 0);
516 set_output_cursor (&w
->cursor
);
520 if (f
== display_info
->mouse_face_mouse_frame
)
522 /* Don't do highlighting for mouse motion during the update. */
523 display_info
->mouse_face_defer
= 1;
525 /* If F needs to be redrawn, simply forget about any prior mouse
527 if (FRAME_GARBAGED_P (f
))
528 display_info
->mouse_face_window
= Qnil
;
530 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
531 their mouse_face_p flag set, which means that they are always
532 unequal to rows in a desired matrix which never have that
533 flag set. So, rows containing mouse-face glyphs are never
534 scrolled, and we don't have to switch the mouse highlight off
535 here to prevent it from being scrolled. */
537 /* Can we tell that this update does not affect the window
538 where the mouse highlight is? If so, no need to turn off.
539 Likewise, don't do anything if the frame is garbaged;
540 in that case, the frame's current matrix that we would use
541 is all wrong, and we will redisplay that line anyway. */
542 if (!NILP (display_info
->mouse_face_window
)
543 && w
== XWINDOW (display_info
->mouse_face_window
))
547 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
548 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
551 if (i
< w
->desired_matrix
->nrows
)
552 clear_mouse_face (display_info
);
561 /* Draw a vertical window border to the right of window W if W doesn't
562 have vertical scroll bars. */
565 x_draw_vertical_border (w
)
568 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
570 /* Redraw borders between horizontally adjacent windows. Don't
571 do it for frames with vertical scroll bars because either the
572 right scroll bar of a window, or the left scroll bar of its
573 neighbor will suffice as a border. */
574 if (!WINDOW_RIGHTMOST_P (w
)
575 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
580 window_box_edges (w
, -1, (int *) &r
.left
, (int *) &r
.top
,
581 (int *) &r
.right
, (int *) &r
.bottom
);
582 r
.left
= r
.right
+ FRAME_X_RIGHT_FRINGE_WIDTH (f
);
583 r
.right
= r
.left
+ 1;
586 hdc
= get_frame_dc (f
);
587 w32_fill_rect (f
, hdc
, FRAME_FOREGROUND_PIXEL (f
), &r
);
588 release_frame_dc (f
, hdc
);
593 /* End update of window W (which is equal to updated_window).
595 Draw vertical borders between horizontally adjacent windows, and
596 display W's cursor if CURSOR_ON_P is non-zero.
598 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
599 glyphs in mouse-face were overwritten. In that case we have to
600 make sure that the mouse-highlight is properly redrawn.
602 W may be a menu bar pseudo-window in case we don't have X toolkit
603 support. Such windows don't have a cursor, so don't display it
607 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
609 int cursor_on_p
, mouse_face_overwritten_p
;
611 struct w32_display_info
*dpyinfo
612 = FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
614 if (!w
->pseudo_window_p
)
619 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
621 output_cursor
.x
, output_cursor
.y
);
623 x_draw_vertical_border (w
);
627 /* If a row with mouse-face was overwritten, arrange for
628 XTframe_up_to_date to redisplay the mouse highlight. */
629 if (mouse_face_overwritten_p
)
631 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
632 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
633 dpyinfo
->mouse_face_window
= Qnil
;
636 /* Unhide the caret. This won't actually show the cursor, unless it
637 was visible before the corresponding call to HideCaret in
638 x_update_window_begin. */
639 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
641 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
644 updated_window
= NULL
;
648 /* End update of frame F. This function is installed as a hook in
655 if (! FRAME_W32_P (f
))
658 /* Mouse highlight may be displayed again. */
659 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
663 /* This function is called from various places in xdisp.c whenever a
664 complete update has been performed. The global variable
665 updated_window is not available here. */
668 w32_frame_up_to_date (f
)
673 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
674 if (dpyinfo
->mouse_face_deferred_gc
675 || f
== dpyinfo
->mouse_face_mouse_frame
)
678 if (dpyinfo
->mouse_face_mouse_frame
)
679 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
680 dpyinfo
->mouse_face_mouse_x
,
681 dpyinfo
->mouse_face_mouse_y
);
682 dpyinfo
->mouse_face_deferred_gc
= 0;
689 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
690 arrow bitmaps, or clear the fringes if no bitmaps are required
691 before DESIRED_ROW is made current. The window being updated is
692 found in updated_window. This function is called from
693 update_window_line only if it is known that there are differences
694 between bitmaps to be drawn between current row and DESIRED_ROW. */
697 x_after_update_window_line (desired_row
)
698 struct glyph_row
*desired_row
;
700 struct window
*w
= updated_window
;
706 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
709 draw_row_fringe_bitmaps (w
, desired_row
);
713 /* When a window has disappeared, make sure that no rest of
714 full-width rows stays visible in the internal border. Could
715 check here if updated_window is the leftmost/rightmost window,
716 but I guess it's not worth doing since vertically split windows
717 are almost never used, internal border is rarely set, and the
718 overhead is very small. */
719 if (windows_or_buffers_changed
720 && desired_row
->full_width_p
721 && (f
= XFRAME (w
->frame
),
722 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
724 && (height
= desired_row
->visible_height
,
727 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
728 /* Internal border is drawn below the tool bar. */
729 if (WINDOWP (f
->tool_bar_window
)
730 && w
== XWINDOW (f
->tool_bar_window
))
735 HDC hdc
= get_frame_dc (f
);
736 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
737 w32_clear_area (f
, hdc
, f
->output_data
.w32
->pixel_width
- width
,
739 release_frame_dc (f
, hdc
);
746 /* Draw the bitmap WHICH in one of the left or right fringes of
747 window W. ROW is the glyph row for which to display the bitmap; it
748 determines the vertical position at which the bitmap has to be
752 w32_draw_fringe_bitmap (w
, row
, p
)
754 struct glyph_row
*row
;
755 struct draw_fringe_bitmap_params
*p
;
757 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
759 struct face
*face
= p
->face
;
761 hdc
= get_frame_dc (f
);
763 /* Must clip because of partially visible lines. */
764 w32_clip_to_row (w
, row
, hdc
, 1);
768 w32_fill_area (f
, hdc
, face
->background
,
769 p
->bx
, p
->by
, p
->nx
, p
->ny
);
772 if (p
->which
!= NO_FRINGE_BITMAP
)
774 HBITMAP pixmap
= fringe_bmp
[p
->which
];
778 compat_hdc
= CreateCompatibleDC (hdc
);
781 horig_obj
= SelectObject (compat_hdc
, pixmap
);
782 SetTextColor (hdc
, face
->background
);
783 SetBkColor (hdc
, face
->foreground
);
785 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
786 compat_hdc
, 0, p
->dh
,
789 SelectObject (compat_hdc
, horig_obj
);
790 DeleteDC (compat_hdc
);
794 w32_set_clip_rectangle (hdc
, NULL
);
796 release_frame_dc (f
, hdc
);
800 /* This is called when starting Emacs and when restarting after
801 suspend. When starting Emacs, no window is mapped. And nothing
802 must be done to Emacs's own window if it is suspended (though that
806 w32_set_terminal_modes (void)
810 /* This is called when exiting or suspending Emacs. Exiting will make
811 the W32 windows go away, and suspending requires no action. */
814 w32_reset_terminal_modes (void)
820 /***********************************************************************
822 ***********************************************************************/
824 /* Set the global variable output_cursor to CURSOR. All cursor
825 positions are relative to updated_window. */
828 set_output_cursor (cursor
)
829 struct cursor_pos
*cursor
;
831 output_cursor
.hpos
= cursor
->hpos
;
832 output_cursor
.vpos
= cursor
->vpos
;
833 output_cursor
.x
= cursor
->x
;
834 output_cursor
.y
= cursor
->y
;
838 /* Set a nominal cursor position.
840 HPOS and VPOS are column/row positions in a window glyph matrix. X
841 and Y are window text area relative pixel positions.
843 If this is done during an update, updated_window will contain the
844 window that is being updated and the position is the future output
845 cursor position for that window. If updated_window is null, use
846 selected_window and display the cursor at the given position. */
849 w32_cursor_to (vpos
, hpos
, y
, x
)
850 int vpos
, hpos
, y
, x
;
854 /* If updated_window is not set, work on selected_window. */
858 w
= XWINDOW (selected_window
);
860 /* Set the output cursor. */
861 output_cursor
.hpos
= hpos
;
862 output_cursor
.vpos
= vpos
;
866 /* If not called as part of an update, really display the cursor.
867 This will also set the cursor position of W. */
868 if (updated_window
== NULL
)
871 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
878 /***********************************************************************
880 ***********************************************************************/
882 /* Function prototypes of this page. */
884 static XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*,
886 static int w32_encode_char
P_ ((int, wchar_t *, struct font_info
*, int *));
889 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
890 If CHAR2B is not contained in FONT, the font's default character
891 metric is returned. */
894 w32_bdf_per_char_metric (font
, char2b
, dim
, pcm
)
900 glyph_metric
* bdf_metric
;
904 buf
[0] = (char)(*char2b
);
907 buf
[0] = XCHAR2B_BYTE1 (char2b
);
908 buf
[1] = XCHAR2B_BYTE2 (char2b
);
911 bdf_metric
= w32_BDF_TextMetric (font
->bdf
, buf
, dim
);
915 pcm
->width
= bdf_metric
->dwidth
;
916 pcm
->lbearing
= bdf_metric
->bbox
;
917 pcm
->rbearing
= bdf_metric
->dwidth
918 - (bdf_metric
->bbox
+ bdf_metric
->bbw
);
919 pcm
->ascent
= bdf_metric
->bboy
+ bdf_metric
->bbh
;
920 pcm
->descent
= -bdf_metric
->bboy
;
929 w32_native_per_char_metric (font
, char2b
, font_type
, pcm
)
932 enum w32_char_font_type font_type
;
935 HDC hdc
= GetDC (NULL
);
939 xassert (font
&& char2b
);
940 xassert (font
->hfont
);
941 xassert (font_type
== UNICODE_FONT
|| font_type
== ANSI_FONT
);
943 old_font
= SelectObject (hdc
, font
->hfont
);
945 if ((font
->tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) != 0)
949 if (font_type
== UNICODE_FONT
)
950 retval
= GetCharABCWidthsW (hdc
, *char2b
, *char2b
, &char_widths
);
952 retval
= GetCharABCWidthsA (hdc
, *char2b
, *char2b
, &char_widths
);
957 /* Disabled until we can find a way to get the right results
958 on all versions of Windows. */
960 /* Don't trust the ABC widths. For synthesized fonts they are
961 wrong, and so is the result of GetCharWidth()! */
963 GetCharWidth (hdc
, *char2b
, *char2b
, &real_width
);
965 pcm
->width
= char_widths
.abcA
+ char_widths
.abcB
+ char_widths
.abcC
;
967 /* As far as I can tell, this is the best way to determine what
968 ExtTextOut will do with the broken font. */
969 if (pcm
->width
!= real_width
)
970 pcm
->width
= (pcm
->width
+ real_width
) / 2;
972 pcm
->lbearing
= char_widths
.abcA
;
973 pcm
->rbearing
= char_widths
.abcA
+ char_widths
.abcB
;
974 pcm
->ascent
= FONT_BASE (font
);
975 pcm
->descent
= FONT_DESCENT (font
);
981 /* Either font is not a True-type font, or GetCharABCWidthsW
982 failed (it is not supported on Windows 9x for instance), so we
983 can't determine the full info we would like. All is not lost
984 though - we can call GetTextExtentPoint32 to get rbearing and
985 deduce width based on the font's per-string overhang. lbearing
986 is assumed to be zero. */
988 /* TODO: Some Thai characters (and other composites if Windows
989 supports them) do have lbearing, and report their total width
990 as zero. Need some way of handling them when
991 GetCharABCWidthsW fails. */
994 if (font_type
== UNICODE_FONT
)
995 retval
= GetTextExtentPoint32W (hdc
, char2b
, 1, &sz
);
997 retval
= GetTextExtentPoint32A (hdc
, (char*)char2b
, 1, &sz
);
1001 pcm
->width
= sz
.cx
- font
->tm
.tmOverhang
;
1002 pcm
->rbearing
= sz
.cx
;
1004 pcm
->ascent
= FONT_BASE (font
);
1005 pcm
->descent
= FONT_DESCENT (font
);
1010 if (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0)
1015 SelectObject (hdc
, old_font
);
1016 ReleaseDC (NULL
, hdc
);
1022 static XCharStruct
*
1023 w32_per_char_metric (font
, char2b
, font_type
)
1026 int /* enum w32_char_font_type */ font_type
;
1028 /* The result metric information. */
1032 xassert (font
&& char2b
);
1033 xassert (font_type
!= UNKNOWN_FONT
);
1035 /* Handle the common cases quickly. */
1036 if (!font
->bdf
&& font
->per_char
== NULL
)
1037 /* TODO: determine whether char2b exists in font? */
1038 return &font
->max_bounds
;
1039 else if (!font
->bdf
&& *char2b
< 128)
1040 return &font
->per_char
[*char2b
];
1042 pcm
= &font
->scratch
;
1044 if (font_type
== BDF_1D_FONT
)
1045 retval
= w32_bdf_per_char_metric (font
, char2b
, 1, pcm
);
1046 else if (font_type
== BDF_2D_FONT
)
1047 retval
= w32_bdf_per_char_metric (font
, char2b
, 2, pcm
);
1049 retval
= w32_native_per_char_metric (font
, char2b
, font_type
, pcm
);
1058 w32_cache_char_metrics (font
)
1061 wchar_t char2b
= L
'x';
1063 /* Cache char metrics for the common cases. */
1066 /* TODO: determine whether font is fixed-pitch. */
1067 if (!w32_bdf_per_char_metric (font
, &char2b
, 1, &font
->max_bounds
))
1069 /* Use the font width and height as max bounds, as not all BDF
1070 fonts contain the letter 'x'. */
1071 font
->max_bounds
.width
= FONT_MAX_WIDTH (font
);
1072 font
->max_bounds
.lbearing
= -font
->bdf
->llx
;
1073 font
->max_bounds
.rbearing
= FONT_MAX_WIDTH (font
) - font
->bdf
->urx
;
1074 font
->max_bounds
.ascent
= FONT_BASE (font
);
1075 font
->max_bounds
.descent
= FONT_DESCENT (font
);
1080 if (((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
) != 0)
1081 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1082 though they contain characters of different widths. */
1083 || (font
->tm
.tmMaxCharWidth
!= font
->tm
.tmAveCharWidth
))
1085 /* Font is not fixed pitch, so cache per_char info for the
1086 ASCII characters. It would be much more work, and probably
1087 not worth it, to cache other chars, since we may change
1088 between using Unicode and ANSI text drawing functions at
1092 font
->per_char
= xmalloc (128 * sizeof(XCharStruct
));
1093 for (i
= 0; i
< 128; i
++)
1096 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1097 &font
->per_char
[i
]);
1101 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1107 /* Determine if a font is double byte. */
1108 int w32_font_is_double_byte (XFontStruct
*font
)
1110 return font
->double_byte_p
;
1115 w32_use_unicode_for_codepage (codepage
)
1118 /* If the current codepage is supported, use Unicode for output. */
1119 return (w32_enable_unicode_output
1120 && codepage
!= CP_8BIT
1121 && (codepage
== CP_UNICODE
|| IsValidCodePage (codepage
)));
1124 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1125 the two-byte form of C. Encoding is returned in *CHAR2B. */
1127 static int /* enum w32_char_font_type */
1128 w32_encode_char (c
, char2b
, font_info
, two_byte_p
)
1131 struct font_info
*font_info
;
1134 int charset
= CHAR_CHARSET (c
);
1138 XFontStruct
*font
= font_info
->font
;
1140 xassert (two_byte_p
);
1143 *two_byte_p
= w32_font_is_double_byte (font
);
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 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
;
1156 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1161 ccl
->reg
[0] = charset
;
1162 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1163 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1166 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1168 /* We assume that MSBs are appropriately set/reset by CCL
1170 if (!*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
[charset
])
1177 /* Fixed encoding scheme. See fontset.h for the meaning of the
1178 encoding numbers. */
1179 int enc
= font_info
->encoding
[charset
];
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
1186 || (enc
== 4 && CHARSET_DIMENSION (charset
) == 1))
1187 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
) | 0x80);
1192 ENCODE_SJIS (XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
),
1194 STORE_XCHAR2B (char2b
, sjis1
, sjis2
);
1197 codepage
= font_info
->codepage
;
1199 /* If charset is not ASCII or Latin-1, may need to move it into
1201 if ( font
&& !font
->bdf
&& w32_use_unicode_for_codepage (codepage
)
1202 && charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
1203 && charset
!= CHARSET_8_BIT_CONTROL
&& charset
!= CHARSET_8_BIT_GRAPHIC
)
1206 temp
[0] = XCHAR2B_BYTE1 (char2b
);
1207 temp
[1] = XCHAR2B_BYTE2 (char2b
);
1209 if (codepage
!= CP_UNICODE
)
1212 MultiByteToWideChar (codepage
, 0, temp
, 2, char2b
, 1);
1214 MultiByteToWideChar (codepage
, 0, temp
+1, 1, char2b
, 1);
1220 return UNKNOWN_FONT
;
1221 else if (font
->bdf
&& CHARSET_DIMENSION (charset
) == 1)
1226 return UNICODE_FONT
;
1232 /* Estimate the pixel height of the mode or top line on frame F.
1233 FACE_ID specifies what line's height to estimate. */
1236 x_estimate_mode_line_height (f
, face_id
)
1238 enum face_id face_id
;
1240 int height
= FONT_HEIGHT (FRAME_FONT (f
));
1242 /* This function is called so early when Emacs starts that the face
1243 cache and mode line face are not yet initialized. */
1244 if (FRAME_FACE_CACHE (f
))
1246 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1250 height
= FONT_HEIGHT (face
->font
);
1251 if (face
->box_line_width
> 0)
1252 height
+= 2 * face
->box_line_width
;
1260 /***********************************************************************
1262 ***********************************************************************/
1265 /* Encapsulate the different ways of displaying text under W32. */
1268 w32_text_out (s
, x
, y
,chars
,nchars
)
1269 struct glyph_string
* s
;
1274 int charset_dim
= w32_font_is_double_byte (s
->gc
->font
) ? 2 : 1;
1275 if (s
->gc
->font
->bdf
)
1276 w32_BDF_TextOut (s
->gc
->font
->bdf
, s
->hdc
,
1277 x
, y
, (char *) chars
, charset_dim
,
1278 nchars
* charset_dim
, 0);
1279 else if (s
->first_glyph
->font_type
== UNICODE_FONT
)
1280 ExtTextOutW (s
->hdc
, x
, y
, 0, NULL
, chars
, nchars
, NULL
);
1282 ExtTextOutA (s
->hdc
, x
, y
, 0, NULL
, (char *) chars
,
1283 nchars
* charset_dim
, NULL
);
1288 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1289 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1290 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1292 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1293 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1294 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1295 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1296 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1297 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1298 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1299 static int w32_alloc_lighter_color (struct frame
*, COLORREF
*, double, int);
1300 static void w32_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1301 double, int, COLORREF
));
1302 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1303 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1304 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1305 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1306 static void w32_draw_image_foreground_1
P_ ((struct glyph_string
*, HBITMAP
));
1307 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1309 static void w32_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1310 int, int, int, int, RECT
*));
1311 static void w32_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1312 int, int, int, RECT
*));
1313 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
1314 enum glyph_row_area
));
1317 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1321 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1326 struct glyph_string
*s
;
1328 if (s
->font
== FRAME_FONT (s
->f
)
1329 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1330 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1332 s
->gc
= s
->f
->output_data
.w32
->cursor_gc
;
1335 /* Cursor on non-default face: must merge. */
1339 xgcv
.background
= s
->f
->output_data
.w32
->cursor_pixel
;
1340 xgcv
.foreground
= s
->face
->background
;
1342 /* If the glyph would be invisible, try a different foreground. */
1343 if (xgcv
.foreground
== xgcv
.background
)
1344 xgcv
.foreground
= s
->face
->foreground
;
1345 if (xgcv
.foreground
== xgcv
.background
)
1346 xgcv
.foreground
= s
->f
->output_data
.w32
->cursor_foreground_pixel
;
1347 if (xgcv
.foreground
== xgcv
.background
)
1348 xgcv
.foreground
= s
->face
->foreground
;
1350 /* Make sure the cursor is distinct from text in this face. */
1351 if (xgcv
.background
== s
->face
->background
1352 && xgcv
.foreground
== s
->face
->foreground
)
1354 xgcv
.background
= s
->face
->foreground
;
1355 xgcv
.foreground
= s
->face
->background
;
1358 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1359 xgcv
.font
= s
->font
;
1360 mask
= GCForeground
| GCBackground
| GCFont
;
1362 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1363 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1366 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1367 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1369 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1374 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1377 x_set_mouse_face_gc (s
)
1378 struct glyph_string
*s
;
1383 /* What face has to be used last for the mouse face? */
1384 face_id
= FRAME_W32_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1385 face
= FACE_FROM_ID (s
->f
, face_id
);
1387 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1389 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1390 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1392 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1393 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1394 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1396 /* If font in this face is same as S->font, use it. */
1397 if (s
->font
== s
->face
->font
)
1398 s
->gc
= s
->face
->gc
;
1401 /* Otherwise construct scratch_cursor_gc with values from FACE
1406 xgcv
.background
= s
->face
->background
;
1407 xgcv
.foreground
= s
->face
->foreground
;
1408 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1409 xgcv
.font
= s
->font
;
1410 mask
= GCForeground
| GCBackground
| GCFont
;
1412 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1413 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1416 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1417 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1419 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1422 xassert (s
->gc
!= 0);
1426 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1427 Faces to use in the mode line have already been computed when the
1428 matrix was built, so there isn't much to do, here. */
1431 x_set_mode_line_face_gc (s
)
1432 struct glyph_string
*s
;
1434 s
->gc
= s
->face
->gc
;
1438 /* Set S->gc of glyph string S for drawing that glyph string. Set
1439 S->stippled_p to a non-zero value if the face of S has a stipple
1443 x_set_glyph_string_gc (s
)
1444 struct glyph_string
*s
;
1446 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1448 if (s
->hl
== DRAW_NORMAL_TEXT
)
1450 s
->gc
= s
->face
->gc
;
1451 s
->stippled_p
= s
->face
->stipple
!= 0;
1453 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1455 x_set_mode_line_face_gc (s
);
1456 s
->stippled_p
= s
->face
->stipple
!= 0;
1458 else if (s
->hl
== DRAW_CURSOR
)
1460 x_set_cursor_gc (s
);
1463 else if (s
->hl
== DRAW_MOUSE_FACE
)
1465 x_set_mouse_face_gc (s
);
1466 s
->stippled_p
= s
->face
->stipple
!= 0;
1468 else if (s
->hl
== DRAW_IMAGE_RAISED
1469 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1471 s
->gc
= s
->face
->gc
;
1472 s
->stippled_p
= s
->face
->stipple
!= 0;
1476 s
->gc
= s
->face
->gc
;
1477 s
->stippled_p
= s
->face
->stipple
!= 0;
1480 /* GC must have been set. */
1481 xassert (s
->gc
!= 0);
1485 /* Return in *R the clipping rectangle for glyph string S. */
1488 w32_get_glyph_string_clip_rect (s
, r
)
1489 struct glyph_string
*s
;
1492 int r_height
, r_width
;
1494 if (s
->row
->full_width_p
)
1496 /* Draw full-width. X coordinates are relative to S->w->left. */
1497 int canon_x
= CANON_X_UNIT (s
->f
);
1499 r
->left
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
1500 r_width
= XFASTINT (s
->w
->width
) * canon_x
;
1502 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
1504 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
1505 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
1509 r
->left
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
1511 /* Unless displaying a mode or menu bar line, which are always
1512 fully visible, clip to the visible part of the row. */
1513 if (s
->w
->pseudo_window_p
)
1514 r_height
= s
->row
->visible_height
;
1516 r_height
= s
->height
;
1520 /* This is a text line that may be partially visible. */
1521 r
->left
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
1522 r_width
= window_box_width (s
->w
, s
->area
);
1523 r_height
= s
->row
->visible_height
;
1526 /* If S draws overlapping rows, it's sufficient to use the top and
1527 bottom of the window for clipping because this glyph string
1528 intentionally draws over other lines. */
1529 if (s
->for_overlaps_p
)
1531 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
1532 r_height
= window_text_bottom_y (s
->w
) - r
->top
;
1536 /* Don't use S->y for clipping because it doesn't take partially
1537 visible lines into account. For example, it can be negative for
1538 partially visible lines at the top of a window. */
1539 if (!s
->row
->full_width_p
1540 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
1541 r
->top
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
1543 r
->top
= max (0, s
->row
->y
);
1545 /* If drawing a tool-bar window, draw it over the internal border
1546 at the top of the window. */
1547 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
1548 r
->top
-= s
->f
->output_data
.w32
->internal_border_width
;
1551 r
->top
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->top
);
1553 /* If drawing the cursor, don't let glyph draw outside its
1554 advertised boundaries. Cleartype does this under some circumstances. */
1555 if (s
->hl
== DRAW_CURSOR
)
1559 r_width
-= s
->x
- r
->left
;
1562 r_width
= min (r_width
, s
->first_glyph
->pixel_width
);
1565 r
->bottom
= r
->top
+ r_height
;
1566 r
->right
= r
->left
+ r_width
;
1570 /* Set clipping for output of glyph string S. S may be part of a mode
1571 line or menu if we don't have X toolkit support. */
1574 x_set_glyph_string_clipping (s
)
1575 struct glyph_string
*s
;
1578 w32_get_glyph_string_clip_rect (s
, &r
);
1579 w32_set_clip_rectangle (s
->hdc
, &r
);
1584 Compute left and right overhang of glyph string S. If S is a glyph
1585 string for a composition, assume overhangs don't exist. */
1588 w32_compute_glyph_string_overhangs (s
)
1589 struct glyph_string
*s
;
1591 /* TODO: Windows does not appear to have a method for
1592 getting this info without getting the ABC widths for each
1593 individual character and working it out manually. */
1598 w32_get_glyph_overhangs (glyph
, f
, left
, right
)
1599 struct glyph
*glyph
;
1603 HDC hdc
= get_frame_dc (f
);
1604 /* Convert to unicode! */
1605 x_get_glyph_overhangs (glyph
, f
, left
, right
);
1606 release_frame_dc (f
, hdc
);
1610 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1613 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1614 struct glyph_string
*s
;
1622 /* Take clipping into account. */
1623 if (s
->gc
->clip_mask
== Rect
)
1625 real_x
= max (real_x
, s
->gc
->clip_rectangle
.left
);
1626 real_y
= max (real_y
, s
->gc
->clip_rectangle
.top
);
1627 real_w
= min (real_w
, s
->gc
->clip_rectangle
.right
1628 - s
->gc
->clip_rectangle
.left
);
1629 real_h
= min (real_h
, s
->gc
->clip_rectangle
.bottom
1630 - s
->gc
->clip_rectangle
.top
);
1633 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->background
, real_x
, real_y
,
1638 /* Draw the background of glyph_string S. If S->background_filled_p
1639 is non-zero don't draw it. FORCE_P non-zero means draw the
1640 background even if it wouldn't be drawn normally. This is used
1641 when a string preceding S draws into the background of S, or S
1642 contains the first component of a composition. */
1645 x_draw_glyph_string_background (s
, force_p
)
1646 struct glyph_string
*s
;
1649 /* Nothing to do if background has already been drawn or if it
1650 shouldn't be drawn in the first place. */
1651 if (!s
->background_filled_p
)
1653 int box_line_width
= max (s
->face
->box_line_width
, 0);
1655 #if 0 /* TODO: stipple */
1658 /* Fill background with a stipple pattern. */
1659 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1660 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1661 s
->y
+ box_line_width
,
1662 s
->background_width
,
1663 s
->height
- 2 * box_line_width
);
1664 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1665 s
->background_filled_p
= 1;
1669 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1670 || s
->font_not_found_p
1671 || s
->extends_to_end_of_line_p
1675 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1676 s
->background_width
,
1677 s
->height
- 2 * box_line_width
);
1678 s
->background_filled_p
= 1;
1684 /* Draw the foreground of glyph string S. */
1687 x_draw_glyph_string_foreground (s
)
1688 struct glyph_string
*s
;
1693 /* If first glyph of S has a left box line, start drawing the text
1694 of S to the right of that box line. */
1695 if (s
->face
->box
!= FACE_NO_BOX
1696 && s
->first_glyph
->left_box_line_p
)
1697 x
= s
->x
+ abs (s
->face
->box_line_width
);
1701 if (s
->for_overlaps_p
|| (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1702 SetBkMode (s
->hdc
, TRANSPARENT
);
1704 SetBkMode (s
->hdc
, OPAQUE
);
1706 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1707 SetBkColor (s
->hdc
, s
->gc
->background
);
1708 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1710 if (s
->font
&& s
->font
->hfont
)
1711 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1713 /* Draw characters of S as rectangles if S's font could not be
1715 if (s
->font_not_found_p
)
1717 for (i
= 0; i
< s
->nchars
; ++i
)
1719 struct glyph
*g
= s
->first_glyph
+ i
;
1721 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1723 x
+= g
->pixel_width
;
1728 char *char1b
= (char *) s
->char2b
;
1729 int boff
= s
->font_info
->baseline_offset
;
1731 if (s
->font_info
->vertical_centering
)
1732 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1734 /* If we can use 8-bit functions, condense S->char2b. */
1736 for (i
= 0; i
< s
->nchars
; ++i
)
1737 char1b
[i
] = XCHAR2B_BYTE2 (&s
->char2b
[i
]);
1739 /* Draw text with TextOut and friends. */
1740 w32_text_out (s
, x
, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1742 if (s
->face
->overstrike
)
1744 /* For overstriking (to simulate bold-face), draw the
1745 characters again shifted to the right by one pixel. */
1746 w32_text_out (s
, x
+ 1, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1749 if (s
->font
&& s
->font
->hfont
)
1750 SelectObject (s
->hdc
, old_font
);
1753 /* Draw the foreground of composite glyph string S. */
1756 x_draw_composite_glyph_string_foreground (s
)
1757 struct glyph_string
*s
;
1762 /* If first glyph of S has a left box line, start drawing the text
1763 of S to the right of that box line. */
1764 if (s
->face
->box
!= FACE_NO_BOX
1765 && s
->first_glyph
->left_box_line_p
)
1766 x
= s
->x
+ abs (s
->face
->box_line_width
);
1770 /* S is a glyph string for a composition. S->gidx is the index of
1771 the first character drawn for glyphs of this composition.
1772 S->gidx == 0 means we are drawing the very first character of
1773 this composition. */
1775 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1776 SetBkColor (s
->hdc
, s
->gc
->background
);
1777 SetBkMode (s
->hdc
, TRANSPARENT
);
1778 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1780 if (s
->font
&& s
->font
->hfont
)
1781 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1783 /* Draw a rectangle for the composition if the font for the very
1784 first character of the composition could not be loaded. */
1785 if (s
->font_not_found_p
)
1788 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, s
->width
- 1,
1793 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1795 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1796 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1798 if (s
->face
->overstrike
)
1799 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1800 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1805 if (s
->font
&& s
->font
->hfont
)
1806 SelectObject (s
->hdc
, old_font
);
1810 /* Brightness beyond which a color won't have its highlight brightness
1813 Nominally, highlight colors for `3d' faces are calculated by
1814 brightening an object's color by a constant scale factor, but this
1815 doesn't yield good results for dark colors, so for colors who's
1816 brightness is less than this value (on a scale of 0-255) have to
1817 use an additional additive factor.
1819 The value here is set so that the default menu-bar/mode-line color
1820 (grey75) will not have its highlights changed at all. */
1821 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1824 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1825 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1826 If this produces the same color as COLOR, try a color where all RGB
1827 values have DELTA added. Return the allocated color in *COLOR.
1828 DISPLAY is the X display, CMAP is the colormap to operate on.
1829 Value is non-zero if successful. */
1832 w32_alloc_lighter_color (f
, color
, factor
, delta
)
1841 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1844 /* Change RGB values by specified FACTOR. Avoid overflow! */
1845 xassert (factor
>= 0);
1846 new = PALETTERGB (min (0xff, factor
* GetRValue (*color
)),
1847 min (0xff, factor
* GetGValue (*color
)),
1848 min (0xff, factor
* GetBValue (*color
)));
1850 /* Calculate brightness of COLOR. */
1851 bright
= (2 * GetRValue (*color
) + 3 * GetGValue (*color
)
1852 + GetBValue (*color
)) / 6;
1854 /* We only boost colors that are darker than
1855 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1856 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1857 /* Make an additive adjustment to NEW, because it's dark enough so
1858 that scaling by FACTOR alone isn't enough. */
1860 /* How far below the limit this color is (0 - 1, 1 being darker). */
1861 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1862 /* The additive adjustment. */
1863 int min_delta
= delta
* dimness
* factor
/ 2;
1866 new = PALETTERGB (max (0, min (0xff, min_delta
- GetRValue (*color
))),
1867 max (0, min (0xff, min_delta
- GetGValue (*color
))),
1868 max (0, min (0xff, min_delta
- GetBValue (*color
))));
1870 new = PALETTERGB (max (0, min (0xff, min_delta
+ GetRValue (*color
))),
1871 max (0, min (0xff, min_delta
+ GetGValue (*color
))),
1872 max (0, min (0xff, min_delta
+ GetBValue (*color
))));
1876 new = PALETTERGB (max (0, min (0xff, delta
+ GetRValue (*color
))),
1877 max (0, min (0xff, delta
+ GetGValue (*color
))),
1878 max (0, min (0xff, delta
+ GetBValue (*color
))));
1880 /* TODO: Map to palette and retry with delta if same? */
1881 /* TODO: Free colors (if using palette)? */
1892 /* Set up the foreground color for drawing relief lines of glyph
1893 string S. RELIEF is a pointer to a struct relief containing the GC
1894 with which lines will be drawn. Use a color that is FACTOR or
1895 DELTA lighter or darker than the relief's background which is found
1896 in S->f->output_data.x->relief_background. If such a color cannot
1897 be allocated, use DEFAULT_PIXEL, instead. */
1900 w32_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1902 struct relief
*relief
;
1905 COLORREF default_pixel
;
1908 struct w32_output
*di
= f
->output_data
.w32
;
1909 unsigned long mask
= GCForeground
;
1911 COLORREF background
= di
->relief_background
;
1912 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
1914 /* TODO: Free colors (if using palette)? */
1916 /* Allocate new color. */
1917 xgcv
.foreground
= default_pixel
;
1919 if (w32_alloc_lighter_color (f
, &pixel
, factor
, delta
))
1921 relief
->allocated_p
= 1;
1922 xgcv
.foreground
= relief
->pixel
= pixel
;
1925 if (relief
->gc
== 0)
1927 #if 0 /* TODO: stipple */
1928 xgcv
.stipple
= dpyinfo
->gray
;
1931 relief
->gc
= XCreateGC (NULL
, FRAME_W32_WINDOW (f
), mask
, &xgcv
);
1934 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
1938 /* Set up colors for the relief lines around glyph string S. */
1941 x_setup_relief_colors (s
)
1942 struct glyph_string
*s
;
1944 struct w32_output
*di
= s
->f
->output_data
.w32
;
1947 if (s
->face
->use_box_color_for_shadows_p
)
1948 color
= s
->face
->box_color
;
1949 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1951 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1952 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1954 color
= s
->gc
->background
;
1956 if (di
->white_relief
.gc
== 0
1957 || color
!= di
->relief_background
)
1959 di
->relief_background
= color
;
1960 w32_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1961 WHITE_PIX_DEFAULT (s
->f
));
1962 w32_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1963 BLACK_PIX_DEFAULT (s
->f
));
1968 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1969 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1970 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1971 relief. LEFT_P non-zero means draw a relief on the left side of
1972 the rectangle. RIGHT_P non-zero means draw a relief on the right
1973 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1977 w32_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
1978 raised_p
, left_p
, right_p
, clip_rect
)
1980 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
, raised_p
;
1985 HDC hdc
= get_frame_dc (f
);
1988 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1990 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1992 w32_set_clip_rectangle (hdc
, clip_rect
);
1995 for (i
= 0; i
< width
; ++i
)
1996 w32_fill_area (f
, hdc
, gc
.foreground
,
1997 left_x
+ i
* left_p
, top_y
+ i
,
1998 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
2002 for (i
= 0; i
< width
; ++i
)
2003 w32_fill_area (f
, hdc
, gc
.foreground
,
2004 left_x
+ i
, top_y
+ i
, 1,
2005 bottom_y
- top_y
- 2 * i
+ 1);
2008 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
2010 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
2013 for (i
= 0; i
< width
; ++i
)
2014 w32_fill_area (f
, hdc
, gc
.foreground
,
2015 left_x
+ i
* left_p
, bottom_y
- i
,
2016 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
2020 for (i
= 0; i
< width
; ++i
)
2021 w32_fill_area (f
, hdc
, gc
.foreground
,
2022 right_x
- i
, top_y
+ i
+ 1, 1,
2023 bottom_y
- top_y
- 2 * i
- 1);
2025 w32_set_clip_rectangle (hdc
, NULL
);
2027 release_frame_dc (f
, hdc
);
2031 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2032 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2033 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2034 left side of the rectangle. RIGHT_P non-zero means draw a line
2035 on the right side of the rectangle. CLIP_RECT is the clipping
2036 rectangle to use when drawing. */
2039 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2040 left_p
, right_p
, clip_rect
)
2041 struct glyph_string
*s
;
2042 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2045 w32_set_clip_rectangle (s
->hdc
, clip_rect
);
2048 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2049 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2054 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2055 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2059 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2060 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2065 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2066 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2069 w32_set_clip_rectangle (s
->hdc
, NULL
);
2073 /* Draw a box around glyph string S. */
2076 x_draw_glyph_string_box (s
)
2077 struct glyph_string
*s
;
2079 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2080 int left_p
, right_p
;
2081 struct glyph
*last_glyph
;
2084 last_x
= window_box_right (s
->w
, s
->area
);
2085 if (s
->row
->full_width_p
2086 && !s
->w
->pseudo_window_p
)
2088 last_x
+= FRAME_X_RIGHT_FRINGE_WIDTH (s
->f
);
2089 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
2090 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
2093 /* The glyph that may have a right box line. */
2094 last_glyph
= (s
->cmp
|| s
->img
2096 : s
->first_glyph
+ s
->nchars
- 1);
2098 width
= abs (s
->face
->box_line_width
);
2099 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2101 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2103 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2105 bottom_y
= top_y
+ s
->height
- 1;
2107 left_p
= (s
->first_glyph
->left_box_line_p
2108 || (s
->hl
== DRAW_MOUSE_FACE
2110 || s
->prev
->hl
!= s
->hl
)));
2111 right_p
= (last_glyph
->right_box_line_p
2112 || (s
->hl
== DRAW_MOUSE_FACE
2114 || s
->next
->hl
!= s
->hl
)));
2116 w32_get_glyph_string_clip_rect (s
, &clip_rect
);
2118 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2119 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2120 left_p
, right_p
, &clip_rect
);
2123 x_setup_relief_colors (s
);
2124 w32_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2125 width
, raised_p
, left_p
, right_p
, &clip_rect
);
2130 /* Draw foreground of image glyph string S. */
2133 x_draw_image_foreground (s
)
2134 struct glyph_string
*s
;
2137 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2139 /* If first glyph of S has a left box line, start drawing it to the
2140 right of that line. */
2141 if (s
->face
->box
!= FACE_NO_BOX
2142 && s
->first_glyph
->left_box_line_p
)
2143 x
= s
->x
+ abs (s
->face
->box_line_width
);
2147 /* If there is a margin around the image, adjust x- and y-position
2149 x
+= s
->img
->hmargin
;
2150 y
+= s
->img
->vmargin
;
2156 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2157 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2158 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2159 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2160 SetBkColor (compat_hdc
, RGB (255, 255, 255));
2161 SetTextColor (s
->hdc
, RGB (0, 0, 0));
2162 x_set_glyph_string_clipping (s
);
2166 HDC mask_dc
= CreateCompatibleDC (s
->hdc
);
2167 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2169 SetTextColor (s
->hdc
, RGB (255, 255, 255));
2170 SetBkColor (s
->hdc
, RGB (0, 0, 0));
2172 BitBlt (s
->hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2173 compat_hdc
, 0, 0, SRCINVERT
);
2174 BitBlt (s
->hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2175 mask_dc
, 0, 0, SRCAND
);
2176 BitBlt (s
->hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2177 compat_hdc
, 0, 0, SRCINVERT
);
2179 SelectObject (mask_dc
, mask_orig_obj
);
2184 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2185 SetBkColor (s
->hdc
, s
->gc
->background
);
2187 BitBlt (s
->hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2188 compat_hdc
, 0, 0, SRCCOPY
);
2190 /* When the image has a mask, we can expect that at
2191 least part of a mouse highlight or a block cursor will
2192 be visible. If the image doesn't have a mask, make
2193 a block cursor visible by drawing a rectangle around
2194 the image. I believe it's looking better if we do
2195 nothing here for mouse-face. */
2196 if (s
->hl
== DRAW_CURSOR
)
2198 int r
= s
->img
->relief
;
2200 w32_draw_rectangle (s
->hdc
, s
->gc
, x
- r
, y
- r
,
2201 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2205 w32_set_clip_rectangle (s
->hdc
, NULL
);
2206 SelectObject (s
->hdc
, orig_brush
);
2207 DeleteObject (fg_brush
);
2208 SelectObject (compat_hdc
, orig_obj
);
2209 DeleteDC (compat_hdc
);
2212 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, y
, s
->img
->width
-1,
2213 s
->img
->height
- 1);
2215 RestoreDC (s
->hdc
,-1);
2220 /* Draw a relief around the image glyph string S. */
2223 x_draw_image_relief (s
)
2224 struct glyph_string
*s
;
2226 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2229 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
2231 /* If first glyph of S has a left box line, start drawing it to the
2232 right of that line. */
2233 if (s
->face
->box
!= FACE_NO_BOX
2234 && s
->first_glyph
->left_box_line_p
)
2235 x
= s
->x
+ abs (s
->face
->box_line_width
);
2239 /* If there is a margin around the image, adjust x- and y-position
2241 x
+= s
->img
->hmargin
;
2242 y
+= s
->img
->vmargin
;
2244 if (s
->hl
== DRAW_IMAGE_SUNKEN
2245 || s
->hl
== DRAW_IMAGE_RAISED
)
2247 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2248 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2252 thick
= abs (s
->img
->relief
);
2253 raised_p
= s
->img
->relief
> 0;
2258 x1
= x
+ s
->img
->width
+ thick
- 1;
2259 y1
= y
+ s
->img
->height
+ thick
- 1;
2261 x_setup_relief_colors (s
);
2262 w32_get_glyph_string_clip_rect (s
, &r
);
2263 w32_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
2267 /* Draw the foreground of image glyph string S to PIXMAP. */
2270 w32_draw_image_foreground_1 (s
, pixmap
)
2271 struct glyph_string
*s
;
2274 HDC hdc
= CreateCompatibleDC (s
->hdc
);
2275 HGDIOBJ orig_hdc_obj
= SelectObject (hdc
, pixmap
);
2277 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
2279 /* If first glyph of S has a left box line, start drawing it to the
2280 right of that line. */
2281 if (s
->face
->box
!= FACE_NO_BOX
2282 && s
->first_glyph
->left_box_line_p
)
2283 x
= abs (s
->face
->box_line_width
);
2287 /* If there is a margin around the image, adjust x- and y-position
2289 x
+= s
->img
->hmargin
;
2290 y
+= s
->img
->vmargin
;
2294 HDC compat_hdc
= CreateCompatibleDC (hdc
);
2295 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2296 HBRUSH orig_brush
= SelectObject (hdc
, fg_brush
);
2297 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2301 HDC mask_dc
= CreateCompatibleDC (hdc
);
2302 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2304 SetTextColor (hdc
, RGB (0, 0, 0));
2305 SetBkColor (hdc
, RGB (255, 255, 255));
2306 BitBlt (hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2307 compat_hdc
, 0, 0, SRCINVERT
);
2308 BitBlt (hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2309 mask_dc
, 0, 0, SRCAND
);
2310 BitBlt (hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2311 compat_hdc
, 0, 0, SRCINVERT
);
2313 SelectObject (mask_dc
, mask_orig_obj
);
2318 SetTextColor (hdc
, s
->gc
->foreground
);
2319 SetBkColor (hdc
, s
->gc
->background
);
2321 BitBlt (hdc
, x
, y
, s
->img
->width
, s
->img
->height
,
2322 compat_hdc
, 0, 0, SRCCOPY
);
2324 /* When the image has a mask, we can expect that at
2325 least part of a mouse highlight or a block cursor will
2326 be visible. If the image doesn't have a mask, make
2327 a block cursor visible by drawing a rectangle around
2328 the image. I believe it's looking better if we do
2329 nothing here for mouse-face. */
2330 if (s
->hl
== DRAW_CURSOR
)
2332 int r
= s
->img
->relief
;
2334 w32_draw_rectangle (hdc
, s
->gc
, x
- r
, y
- r
,
2335 s
->img
->width
+ r
*2 - 1, s
->img
->height
+ r
*2 - 1);
2339 SelectObject (hdc
, orig_brush
);
2340 DeleteObject (fg_brush
);
2341 SelectObject (compat_hdc
, orig_obj
);
2342 DeleteDC (compat_hdc
);
2345 w32_draw_rectangle (hdc
, s
->gc
, x
, y
, s
->img
->width
- 1,
2346 s
->img
->height
- 1);
2348 SelectObject (hdc
, orig_hdc_obj
);
2353 /* Draw part of the background of glyph string S. X, Y, W, and H
2354 give the rectangle to draw. */
2357 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2358 struct glyph_string
*s
;
2361 #if 0 /* TODO: stipple */
2364 /* Fill background with a stipple pattern. */
2365 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2366 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2367 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2371 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2375 /* Draw image glyph string S.
2378 s->x +-------------------------
2381 | +-------------------------
2384 | | +-------------------
2390 x_draw_image_glyph_string (s
)
2391 struct glyph_string
*s
;
2394 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2395 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2399 height
= s
->height
- 2 * box_line_vwidth
;
2401 /* Fill background with face under the image. Do it only if row is
2402 taller than image or if image has a clip mask to reduce
2404 s
->stippled_p
= s
->face
->stipple
!= 0;
2405 if (height
> s
->img
->height
2409 || s
->img
->pixmap
== 0
2410 || s
->width
!= s
->background_width
)
2412 if (box_line_hwidth
&& s
->first_glyph
->left_box_line_p
)
2413 x
= s
->x
+ box_line_hwidth
;
2417 y
= s
->y
+ box_line_vwidth
;
2418 #if 0 /* TODO: figure out if we need to do this on Windows. */
2421 /* Create a pixmap as large as the glyph string. Fill it
2422 with the background color. Copy the image to it, using
2423 its mask. Copy the temporary pixmap to the display. */
2424 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2425 int depth
= DefaultDepthOfScreen (screen
);
2427 /* Create a pixmap as large as the glyph string. */
2428 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2429 s
->background_width
,
2432 /* Don't clip in the following because we're working on the
2434 XSetClipMask (s
->display
, s
->gc
, None
);
2436 /* Fill the pixmap with the background color/stipple. */
2439 /* Fill background with a stipple pattern. */
2440 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2441 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2442 0, 0, s
->background_width
, s
->height
);
2443 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2448 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2450 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2451 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2452 0, 0, s
->background_width
, s
->height
);
2453 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2458 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2460 s
->background_filled_p
= 1;
2463 /* Draw the foreground. */
2466 w32_draw_image_foreground_1 (s
, pixmap
);
2467 x_set_glyph_string_clipping (s
);
2469 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2470 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2471 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2472 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, pixmap
);
2474 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2475 SetBkColor (s
->hdc
, s
->gc
->background
);
2476 BitBlt (s
->hdc
, s
->x
, s
->y
, s
->background_width
, s
->height
,
2477 compat_hdc
, 0, 0, SRCCOPY
);
2479 SelectObject (s
->hdc
, orig_brush
);
2480 DeleteObject (fg_brush
);
2481 SelectObject (compat_hdc
, orig_obj
);
2482 DeleteDC (compat_hdc
);
2484 DeleteObject (pixmap
);
2488 x_draw_image_foreground (s
);
2490 /* If we must draw a relief around the image, do it. */
2492 || s
->hl
== DRAW_IMAGE_RAISED
2493 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2494 x_draw_image_relief (s
);
2498 /* Draw stretch glyph string S. */
2501 x_draw_stretch_glyph_string (s
)
2502 struct glyph_string
*s
;
2504 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2505 s
->stippled_p
= s
->face
->stipple
!= 0;
2507 if (s
->hl
== DRAW_CURSOR
2508 && !x_stretch_cursor_p
)
2510 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2511 as wide as the stretch glyph. */
2512 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
2515 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2517 /* Clear rest using the GC of the original non-cursor face. */
2518 if (width
< s
->background_width
)
2520 XGCValues
*gc
= s
->face
->gc
;
2521 int x
= s
->x
+ width
, y
= s
->y
;
2522 int w
= s
->background_width
- width
, h
= s
->height
;
2526 if (s
->row
->mouse_face_p
2527 && cursor_in_mouse_face_p (s
->w
))
2529 x_set_mouse_face_gc (s
);
2535 w32_get_glyph_string_clip_rect (s
, &r
);
2536 w32_set_clip_rectangle (hdc
, &r
);
2538 #if 0 /* TODO: stipple */
2539 if (s
->face
->stipple
)
2541 /* Fill background with a stipple pattern. */
2542 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2543 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2544 XSetFillStyle (s
->display
, gc
, FillSolid
);
2549 w32_fill_area (s
->f
, s
->hdc
, gc
->background
, x
, y
, w
, h
);
2553 else if (!s
->background_filled_p
)
2554 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2557 s
->background_filled_p
= 1;
2561 /* Draw glyph string S. */
2564 x_draw_glyph_string (s
)
2565 struct glyph_string
*s
;
2567 int relief_drawn_p
= 0;
2569 /* If S draws into the background of its successor, draw the
2570 background of the successor first so that S can draw into it.
2571 This makes S->next use XDrawString instead of XDrawImageString. */
2572 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2574 xassert (s
->next
->img
== NULL
);
2575 x_set_glyph_string_gc (s
->next
);
2576 x_set_glyph_string_clipping (s
->next
);
2577 x_draw_glyph_string_background (s
->next
, 1);
2580 /* Set up S->gc, set clipping and draw S. */
2581 x_set_glyph_string_gc (s
);
2583 /* Draw relief (if any) in advance for char/composition so that the
2584 glyph string can be drawn over it. */
2585 if (!s
->for_overlaps_p
2586 && s
->face
->box
!= FACE_NO_BOX
2587 && (s
->first_glyph
->type
== CHAR_GLYPH
2588 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2591 x_set_glyph_string_clipping (s
);
2592 x_draw_glyph_string_background (s
, 1);
2593 x_draw_glyph_string_box (s
);
2594 x_set_glyph_string_clipping (s
);
2598 x_set_glyph_string_clipping (s
);
2600 switch (s
->first_glyph
->type
)
2603 x_draw_image_glyph_string (s
);
2607 x_draw_stretch_glyph_string (s
);
2611 if (s
->for_overlaps_p
)
2612 s
->background_filled_p
= 1;
2614 x_draw_glyph_string_background (s
, 0);
2615 x_draw_glyph_string_foreground (s
);
2618 case COMPOSITE_GLYPH
:
2619 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2620 s
->background_filled_p
= 1;
2622 x_draw_glyph_string_background (s
, 1);
2623 x_draw_composite_glyph_string_foreground (s
);
2630 if (!s
->for_overlaps_p
)
2632 /* Draw underline. */
2633 if (s
->face
->underline_p
2634 && (s
->font
->bdf
|| !s
->font
->tm
.tmUnderlined
))
2636 unsigned long h
= 1;
2637 unsigned long dy
= s
->height
- h
;
2639 /* TODO: Use font information for positioning and thickness
2640 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
2641 if (s
->face
->underline_defaulted_p
)
2643 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2644 s
->y
+ dy
, s
->width
, 1);
2648 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2649 s
->y
+ dy
, s
->width
, 1);
2653 /* Draw overline. */
2654 if (s
->face
->overline_p
)
2656 unsigned long dy
= 0, h
= 1;
2658 if (s
->face
->overline_color_defaulted_p
)
2660 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2661 s
->y
+ dy
, s
->width
, h
);
2665 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2666 s
->y
+ dy
, s
->width
, h
);
2670 /* Draw strike-through. */
2671 if (s
->face
->strike_through_p
2672 && (s
->font
->bdf
|| !s
->font
->tm
.tmStruckOut
))
2674 unsigned long h
= 1;
2675 unsigned long dy
= (s
->height
- h
) / 2;
2677 if (s
->face
->strike_through_color_defaulted_p
)
2679 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
, s
->y
+ dy
,
2684 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2685 s
->y
+ dy
, s
->width
, h
);
2690 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2691 x_draw_glyph_string_box (s
);
2694 /* Reset clipping. */
2695 w32_set_clip_rectangle (s
->hdc
, NULL
);
2699 /* Fix the display of area AREA of overlapping row ROW in window W. */
2702 x_fix_overlapping_area (w
, row
, area
)
2704 struct glyph_row
*row
;
2705 enum glyph_row_area area
;
2711 if (area
== LEFT_MARGIN_AREA
)
2713 else if (area
== TEXT_AREA
)
2714 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
2716 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
2717 + window_box_width (w
, TEXT_AREA
));
2719 for (i
= 0; i
< row
->used
[area
];)
2721 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
2723 int start
= i
, start_x
= x
;
2727 x
+= row
->glyphs
[area
][i
].pixel_width
;
2730 while (i
< row
->used
[area
]
2731 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
2733 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
2734 DRAW_NORMAL_TEXT
, 1);
2738 x
+= row
->glyphs
[area
][i
].pixel_width
;
2747 /* Output LEN glyphs starting at START at the nominal cursor position.
2748 Advance the nominal cursor over the text. The global variable
2749 updated_window contains the window being updated, updated_row is
2750 the glyph row being updated, and updated_area is the area of that
2751 row being updated. */
2754 x_write_glyphs (start
, len
)
2755 struct glyph
*start
;
2760 xassert (updated_window
&& updated_row
);
2765 hpos
= start
- updated_row
->glyphs
[updated_area
];
2766 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
2767 updated_row
, updated_area
,
2769 DRAW_NORMAL_TEXT
, 0);
2771 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
2772 if (updated_area
== TEXT_AREA
2773 && updated_window
->phys_cursor_on_p
2774 && updated_window
->phys_cursor
.vpos
== output_cursor
.vpos
2775 && updated_window
->phys_cursor
.hpos
>= hpos
2776 && updated_window
->phys_cursor
.hpos
< hpos
+ len
)
2777 updated_window
->phys_cursor_on_p
= 0;
2781 /* Advance the output cursor. */
2782 output_cursor
.hpos
+= len
;
2783 output_cursor
.x
= x
;
2787 /* Insert LEN glyphs from START at the nominal cursor position. */
2790 x_insert_glyphs (start
, len
)
2791 struct glyph
*start
;
2796 int line_height
, shift_by_width
, shifted_region_width
;
2797 struct glyph_row
*row
;
2798 struct glyph
*glyph
;
2799 int frame_x
, frame_y
, hpos
;
2802 xassert (updated_window
&& updated_row
);
2805 f
= XFRAME (WINDOW_FRAME (w
));
2806 hdc
= get_frame_dc (f
);
2808 /* Get the height of the line we are in. */
2810 line_height
= row
->height
;
2812 /* Get the width of the glyphs to insert. */
2814 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
2815 shift_by_width
+= glyph
->pixel_width
;
2817 /* Get the width of the region to shift right. */
2818 shifted_region_width
= (window_box_width (w
, updated_area
)
2823 frame_x
= window_box_left (w
, updated_area
) + output_cursor
.x
;
2824 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
2825 BitBlt (hdc
, frame_x
+ shift_by_width
, frame_y
,
2826 shifted_region_width
, line_height
,
2827 hdc
, frame_x
, frame_y
, SRCCOPY
);
2829 /* Write the glyphs. */
2830 hpos
= start
- row
->glyphs
[updated_area
];
2831 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
2832 DRAW_NORMAL_TEXT
, 0);
2834 /* Advance the output cursor. */
2835 output_cursor
.hpos
+= len
;
2836 output_cursor
.x
+= shift_by_width
;
2837 release_frame_dc (f
, hdc
);
2843 /* Delete N glyphs at the nominal cursor position. Not implemented
2855 f
= SELECTED_FRAME ();
2857 if (! FRAME_W32_P (f
))
2864 /* Erase the current text line from the nominal cursor position
2865 (inclusive) to pixel column TO_X (exclusive). The idea is that
2866 everything from TO_X onward is already erased.
2868 TO_X is a pixel position relative to updated_area of
2869 updated_window. TO_X == -1 means clear to the end of this area. */
2872 x_clear_end_of_line (to_x
)
2876 struct window
*w
= updated_window
;
2877 int max_x
, min_y
, max_y
;
2878 int from_x
, from_y
, to_y
;
2880 xassert (updated_window
&& updated_row
);
2881 f
= XFRAME (w
->frame
);
2883 if (updated_row
->full_width_p
)
2885 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
2886 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2887 && !w
->pseudo_window_p
)
2888 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
2891 max_x
= window_box_width (w
, updated_area
);
2892 max_y
= window_text_bottom_y (w
);
2894 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
2895 of window. For TO_X > 0, truncate to end of drawing area. */
2901 to_x
= min (to_x
, max_x
);
2903 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
2905 /* Notice if the cursor will be cleared by this operation. */
2906 if (!updated_row
->full_width_p
)
2907 notice_overwritten_cursor (w
, updated_area
,
2908 output_cursor
.x
, -1,
2910 MATRIX_ROW_BOTTOM_Y (updated_row
));
2912 from_x
= output_cursor
.x
;
2914 /* Translate to frame coordinates. */
2915 if (updated_row
->full_width_p
)
2917 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
2918 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
2922 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
2923 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
2926 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
2927 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
2928 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
2930 /* Prevent inadvertently clearing to end of the X window. */
2931 if (to_x
> from_x
&& to_y
> from_y
)
2935 hdc
= get_frame_dc (f
);
2937 w32_clear_area (f
, hdc
, from_x
, from_y
, to_x
- from_x
, to_y
- from_y
);
2938 release_frame_dc (f
, hdc
);
2944 /* Clear entire frame. If updating_frame is non-null, clear that
2945 frame. Otherwise clear the selected frame. */
2955 f
= SELECTED_FRAME ();
2957 if (! FRAME_W32_P (f
))
2960 /* Clearing the frame will erase any cursor, so mark them all as no
2962 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2963 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2964 output_cursor
.x
= -1;
2966 /* We don't set the output cursor here because there will always
2967 follow an explicit cursor_to. */
2970 w32_clear_window (f
);
2972 /* We have to clear the scroll bars, too. If we have changed
2973 colors or something like that, then they should be notified. */
2974 x_scroll_bar_clear (f
);
2980 /* Make audible bell. */
2983 w32_ring_bell (void)
2987 f
= SELECTED_FRAME ();
2991 if (FRAME_W32_P (f
) && visible_bell
)
2994 HWND hwnd
= FRAME_W32_WINDOW (SELECTED_FRAME ());
2996 for (i
= 0; i
< 5; i
++)
2998 FlashWindow (hwnd
, TRUE
);
3001 FlashWindow (hwnd
, FALSE
);
3004 w32_sys_ring_bell ();
3010 /* Specify how many text lines, from the top of the window,
3011 should be affected by insert-lines and delete-lines operations.
3012 This, and those operations, are used only within an update
3013 that is bounded by calls to x_update_begin and x_update_end. */
3016 w32_set_terminal_window (n
)
3019 /* This function intentionally left blank. */
3023 /***********************************************************************
3025 ***********************************************************************/
3027 /* Perform an insert-lines or delete-lines operation, inserting N
3028 lines or deleting -N lines at vertical position VPOS. */
3031 x_ins_del_lines (vpos
, n
)
3039 f
= SELECTED_FRAME ();
3041 if (! FRAME_W32_P (f
))
3048 /* Scroll part of the display as described by RUN. */
3051 x_scroll_run (w
, run
)
3055 struct frame
*f
= XFRAME (w
->frame
);
3056 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3057 HWND hwnd
= FRAME_W32_WINDOW (f
);
3060 /* Get frame-relative bounding box of the text display area of W,
3061 without mode lines. Include in this box the left and right
3063 window_box (w
, -1, &x
, &y
, &width
, &height
);
3064 width
+= FRAME_X_FRINGE_WIDTH (f
);
3065 x
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
3067 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3068 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3069 bottom_y
= y
+ height
;
3073 /* Scrolling up. Make sure we don't copy part of the mode
3074 line at the bottom. */
3075 if (from_y
+ run
->height
> bottom_y
)
3076 height
= bottom_y
- from_y
;
3078 height
= run
->height
;
3079 expect_dirty
= CreateRectRgn (x
, y
+ height
, x
+ width
, bottom_y
);
3083 /* Scolling down. Make sure we don't copy over the mode line.
3085 if (to_y
+ run
->height
> bottom_y
)
3086 height
= bottom_y
- to_y
;
3088 height
= run
->height
;
3089 expect_dirty
= CreateRectRgn (x
, y
, x
+ width
, to_y
);
3094 /* Cursor off. Will be switched on again in x_update_window_end. */
3101 HRGN dirty
= CreateRectRgn (0, 0, 0, 0);
3102 HRGN combined
= CreateRectRgn (0, 0, 0, 0);
3104 from
.left
= to
.left
= x
;
3105 from
.right
= to
.right
= x
+ width
;
3107 from
.bottom
= from_y
+ height
;
3109 to
.bottom
= bottom_y
;
3111 ScrollWindowEx (hwnd
, 0, to_y
- from_y
, &from
, &to
, dirty
,
3112 NULL
, SW_INVALIDATE
);
3114 /* Combine this with what we expect to be dirty. This covers the
3115 case where not all of the region we expect is actually dirty. */
3116 CombineRgn (combined
, dirty
, expect_dirty
, RGN_OR
);
3118 /* If the dirty region is not what we expected, redraw the entire frame. */
3119 if (!EqualRgn (combined
, expect_dirty
))
3120 SET_FRAME_GARBAGED (f
);
3128 /***********************************************************************
3130 ***********************************************************************/
3132 /* Redisplay an exposed area of frame F. X and Y are the upper-left
3133 corner of the exposed rectangle. W and H are width and height of
3134 the exposed area. All are pixel values. W or H zero means redraw
3135 the entire frame. */
3138 expose_frame (f
, x
, y
, w
, h
)
3143 int mouse_face_overwritten_p
= 0;
3145 TRACE ((stderr
, "expose_frame "));
3147 /* No need to redraw if frame will be redrawn soon. */
3148 if (FRAME_GARBAGED_P (f
))
3150 TRACE ((stderr
, " garbaged\n"));
3154 /* If basic faces haven't been realized yet, there is no point in
3155 trying to redraw anything. This can happen when we get an expose
3156 event while Emacs is starting, e.g. by moving another window. */
3157 if (FRAME_FACE_CACHE (f
) == NULL
3158 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
3160 TRACE ((stderr
, " no faces\n"));
3164 if (w
== 0 || h
== 0)
3167 r
.right
= CANON_X_UNIT (f
) * f
->width
;
3168 r
.bottom
= CANON_Y_UNIT (f
) * f
->height
;
3178 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.left
, r
.top
, r
.right
, r
.bottom
));
3179 mouse_face_overwritten_p
= expose_window_tree (XWINDOW (f
->root_window
), &r
);
3181 if (WINDOWP (f
->tool_bar_window
))
3182 mouse_face_overwritten_p
3183 |= expose_window (XWINDOW (f
->tool_bar_window
), &r
);
3185 /* Some window managers support a focus-follows-mouse style with
3186 delayed raising of frames. Imagine a partially obscured frame,
3187 and moving the mouse into partially obscured mouse-face on that
3188 frame. The visible part of the mouse-face will be highlighted,
3189 then the WM raises the obscured frame. With at least one WM, KDE
3190 2.1, Emacs is not getting any event for the raising of the frame
3191 (even tried with SubstructureRedirectMask), only Expose events.
3192 These expose events will draw text normally, i.e. not
3193 highlighted. Which means we must redo the highlight here.
3194 Subsume it under ``we love X''. --gerd 2001-08-15 */
3195 /* Included in Windows version because Windows most likely does not
3196 do the right thing if any third party tool offers
3197 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
3198 if (mouse_face_overwritten_p
&& !FRAME_GARBAGED_P (f
))
3200 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
3201 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3203 int x
= dpyinfo
->mouse_face_mouse_x
;
3204 int y
= dpyinfo
->mouse_face_mouse_y
;
3205 clear_mouse_face (dpyinfo
);
3206 note_mouse_highlight (f
, x
, y
);
3212 /* Redraw (parts) of all windows in the window tree rooted at W that
3213 intersect R. R contains frame pixel coordinates. */
3216 expose_window_tree (w
, r
)
3220 struct frame
*f
= XFRAME (w
->frame
);
3221 int mouse_face_overwritten_p
= 0;
3223 while (w
&& !FRAME_GARBAGED_P (f
))
3225 if (!NILP (w
->hchild
))
3226 mouse_face_overwritten_p
3227 |= expose_window_tree (XWINDOW (w
->hchild
), r
);
3228 else if (!NILP (w
->vchild
))
3229 mouse_face_overwritten_p
3230 |= expose_window_tree (XWINDOW (w
->vchild
), r
);
3232 mouse_face_overwritten_p
|= expose_window (w
, r
);
3234 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
3237 return mouse_face_overwritten_p
;
3241 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
3242 which intersects rectangle R. R is in window-relative coordinates. */
3245 expose_area (w
, row
, r
, area
)
3247 struct glyph_row
*row
;
3249 enum glyph_row_area area
;
3251 struct glyph
*first
= row
->glyphs
[area
];
3252 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
3254 int first_x
, start_x
, x
;
3256 if (area
== TEXT_AREA
&& row
->fill_line_p
)
3257 /* If row extends face to end of line write the whole line. */
3258 x_draw_glyphs (w
, 0, row
, area
,
3260 DRAW_NORMAL_TEXT
, 0);
3263 /* Set START_X to the window-relative start position for drawing glyphs of
3264 AREA. The first glyph of the text area can be partially visible.
3265 The first glyphs of other areas cannot. */
3266 if (area
== LEFT_MARGIN_AREA
)
3268 else if (area
== TEXT_AREA
)
3269 start_x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
3271 start_x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
3272 + window_box_width (w
, TEXT_AREA
));
3275 /* Find the first glyph that must be redrawn. */
3277 && x
+ first
->pixel_width
< r
->left
)
3279 x
+= first
->pixel_width
;
3283 /* Find the last one. */
3289 x
+= last
->pixel_width
;
3295 x_draw_glyphs (w
, first_x
- start_x
, row
, area
,
3296 first
- row
->glyphs
[area
],
3297 last
- row
->glyphs
[area
],
3298 DRAW_NORMAL_TEXT
, 0);
3303 /* Redraw the parts of the glyph row ROW on window W intersecting
3304 rectangle R. R is in window-relative coordinates. Value is
3305 non-zero if mouse face was overwritten. */
3308 expose_line (w
, row
, r
)
3310 struct glyph_row
*row
;
3313 xassert (row
->enabled_p
);
3315 if (row
->mode_line_p
|| w
->pseudo_window_p
)
3316 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
3317 DRAW_NORMAL_TEXT
, 0);
3320 if (row
->used
[LEFT_MARGIN_AREA
])
3321 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
3322 if (row
->used
[TEXT_AREA
])
3323 expose_area (w
, row
, r
, TEXT_AREA
);
3324 if (row
->used
[RIGHT_MARGIN_AREA
])
3325 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
3326 draw_row_fringe_bitmaps (w
, row
);
3329 return row
->mouse_face_p
;
3333 /* Return non-zero if W's cursor intersects rectangle R. */
3336 x_phys_cursor_in_rect_p (w
, r
)
3341 struct glyph
*cursor_glyph
;
3343 cursor_glyph
= get_phys_cursor_glyph (w
);
3346 cr
.left
= w
->phys_cursor
.x
;
3347 cr
.top
= w
->phys_cursor
.y
;
3348 cr
.right
= cr
.left
+ cursor_glyph
->pixel_width
;
3349 cr
.bottom
= cr
.top
+ w
->phys_cursor_height
;
3350 return IntersectRect (&result
, &cr
, r
);
3357 /* Redraw those parts of glyphs rows during expose event handling that
3358 overlap other rows. Redrawing of an exposed line writes over parts
3359 of lines overlapping that exposed line; this function fixes that.
3361 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
3362 row in W's current matrix that is exposed and overlaps other rows.
3363 LAST_OVERLAPPING_ROW is the last such row. */
3366 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
)
3368 struct glyph_row
*first_overlapping_row
;
3369 struct glyph_row
*last_overlapping_row
;
3371 struct glyph_row
*row
;
3373 for (row
= first_overlapping_row
; row
<= last_overlapping_row
; ++row
)
3374 if (row
->overlapping_p
)
3376 xassert (row
->enabled_p
&& !row
->mode_line_p
);
3378 if (row
->used
[LEFT_MARGIN_AREA
])
3379 x_fix_overlapping_area (w
, row
, LEFT_MARGIN_AREA
);
3381 if (row
->used
[TEXT_AREA
])
3382 x_fix_overlapping_area (w
, row
, TEXT_AREA
);
3384 if (row
->used
[RIGHT_MARGIN_AREA
])
3385 x_fix_overlapping_area (w
, row
, RIGHT_MARGIN_AREA
);
3390 /* Redraw the part of window W intersection rectagle FR. Pixel
3391 coordinates in FR are frame relative. Call this function with
3392 input blocked. Value is non-zero if the exposure overwrites
3396 expose_window (w
, fr
)
3400 struct frame
*f
= XFRAME (w
->frame
);
3402 int mouse_face_overwritten_p
= 0;
3404 /* If window is not yet fully initialized, do nothing. This can
3405 happen when toolkit scroll bars are used and a window is split.
3406 Reconfiguring the scroll bar will generate an expose for a newly
3408 if (w
->current_matrix
== NULL
)
3411 /* When we're currently updating the window, display and current
3412 matrix usually don't agree. Arrange for a thorough display
3414 if (w
== updated_window
)
3416 SET_FRAME_GARBAGED (f
);
3420 /* Frame-relative pixel rectangle of W. */
3421 wr
.left
= XFASTINT (w
->left
) * CANON_X_UNIT (f
);
3422 wr
.top
= XFASTINT (w
->top
) * CANON_Y_UNIT (f
);
3423 wr
.right
= wr
.left
+ XFASTINT (w
->width
) * CANON_X_UNIT (f
);
3424 wr
.bottom
= wr
.top
+ XFASTINT (w
->height
) * CANON_Y_UNIT (f
);
3426 if (IntersectRect(&r
, fr
, &wr
))
3428 int yb
= window_text_bottom_y (w
);
3429 struct glyph_row
*row
;
3430 int cursor_cleared_p
;
3431 struct glyph_row
*first_overlapping_row
, *last_overlapping_row
;
3433 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
3434 r
.left
, r
.top
, r
.right
, r
.bottom
));
3436 /* Convert to window coordinates. */
3437 r
.left
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.left
);
3438 r
.right
= FRAME_TO_WINDOW_PIXEL_X (w
, r
.right
);
3439 r
.top
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.top
);
3440 r
.bottom
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
.bottom
);
3442 /* Turn off the cursor. */
3443 if (!w
->pseudo_window_p
3444 && x_phys_cursor_in_rect_p (w
, &r
))
3447 cursor_cleared_p
= 1;
3450 cursor_cleared_p
= 0;
3452 /* Update lines intersecting rectangle R. */
3453 first_overlapping_row
= last_overlapping_row
= NULL
;
3454 for (row
= w
->current_matrix
->rows
;
3459 int y1
= MATRIX_ROW_BOTTOM_Y (row
);
3461 if ((y0
>= r
.top
&& y0
< r
.bottom
)
3462 || (y1
> r
.top
&& y1
< r
.bottom
)
3463 || (r
.top
>= y0
&& r
.top
< y1
)
3464 || (r
.bottom
> y0
&& r
.bottom
< y1
))
3466 if (row
->overlapping_p
)
3468 if (first_overlapping_row
== NULL
)
3469 first_overlapping_row
= row
;
3470 last_overlapping_row
= row
;
3473 if (expose_line (w
, row
, &r
))
3474 mouse_face_overwritten_p
= 1;
3481 /* Display the mode line if there is one. */
3482 if (WINDOW_WANTS_MODELINE_P (w
)
3483 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
3485 && row
->y
< r
.bottom
)
3487 if (expose_line (w
, row
, &r
))
3488 mouse_face_overwritten_p
= 1;
3491 if (!w
->pseudo_window_p
)
3493 /* Fix the display of overlapping rows. */
3494 if (first_overlapping_row
)
3495 expose_overlaps (w
, first_overlapping_row
, last_overlapping_row
);
3497 /* Draw border between windows. */
3498 x_draw_vertical_border (w
);
3500 /* Turn the cursor on again. */
3501 if (cursor_cleared_p
)
3502 x_update_window_cursor (w
, 1);
3506 return mouse_face_overwritten_p
;
3514 x_update_cursor (f
, 1);
3518 frame_unhighlight (f
)
3521 x_update_cursor (f
, 1);
3524 /* The focus has changed. Update the frames as necessary to reflect
3525 the new situation. Note that we can't change the selected frame
3526 here, because the Lisp code we are interrupting might become confused.
3527 Each event gets marked with the frame in which it occurred, so the
3528 Lisp code can tell when the switch took place by examining the events. */
3531 x_new_focus_frame (dpyinfo
, frame
)
3532 struct w32_display_info
*dpyinfo
;
3533 struct frame
*frame
;
3535 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
3537 if (frame
!= dpyinfo
->w32_focus_frame
)
3539 /* Set this before calling other routines, so that they see
3540 the correct value of w32_focus_frame. */
3541 dpyinfo
->w32_focus_frame
= frame
;
3543 if (old_focus
&& old_focus
->auto_lower
)
3544 x_lower_frame (old_focus
);
3546 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
3547 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
3549 pending_autoraise_frame
= 0;
3552 x_frame_rehighlight (dpyinfo
);
3555 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3558 x_mouse_leave (dpyinfo
)
3559 struct w32_display_info
*dpyinfo
;
3561 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
3564 /* The focus has changed, or we have redirected a frame's focus to
3565 another frame (this happens when a frame uses a surrogate
3566 mini-buffer frame). Shift the highlight as appropriate.
3568 The FRAME argument doesn't necessarily have anything to do with which
3569 frame is being highlighted or un-highlighted; we only use it to find
3570 the appropriate X display info. */
3573 w32_frame_rehighlight (frame
)
3574 struct frame
*frame
;
3576 if (! FRAME_W32_P (frame
))
3578 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
3582 x_frame_rehighlight (dpyinfo
)
3583 struct w32_display_info
*dpyinfo
;
3585 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3587 if (dpyinfo
->w32_focus_frame
)
3589 dpyinfo
->x_highlight_frame
3590 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
3591 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
3592 : dpyinfo
->w32_focus_frame
);
3593 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3595 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
3596 dpyinfo
->x_highlight_frame
= dpyinfo
->w32_focus_frame
;
3600 dpyinfo
->x_highlight_frame
= 0;
3602 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3605 frame_unhighlight (old_highlight
);
3606 if (dpyinfo
->x_highlight_frame
)
3607 frame_highlight (dpyinfo
->x_highlight_frame
);
3611 /* Keyboard processing - modifier keys, etc. */
3613 /* Convert a keysym to its name. */
3616 x_get_keysym_name (keysym
)
3619 /* Make static so we can always return it */
3620 static char value
[100];
3623 GetKeyNameText (keysym
, value
, 100);
3631 /* Mouse clicks and mouse movement. Rah. */
3633 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
3634 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
3635 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
3636 not force the value into range. */
3639 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
3641 register int pix_x
, pix_y
;
3642 register int *x
, *y
;
3646 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
3647 if (NILP (Vwindow_system
))
3654 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
3655 even for negative values. */
3657 pix_x
-= FONT_WIDTH (FRAME_FONT (f
)) - 1;
3659 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
3661 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
3662 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
3666 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
3667 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
3668 bounds
->right
= bounds
->left
+ FONT_WIDTH (FRAME_FONT (f
)) - 1;
3669 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
3676 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
3677 pix_x
= FRAME_WINDOW_WIDTH (f
);
3681 else if (pix_y
> f
->height
)
3690 /* Given HPOS/VPOS in the current matrix of W, return corresponding
3691 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
3692 can't tell the positions because W's display is not up to date,
3696 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
3699 int *frame_x
, *frame_y
;
3703 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
3704 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
3706 if (display_completed
)
3708 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
3709 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
3710 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
3716 *frame_x
+= glyph
->pixel_width
;
3724 *frame_y
= *frame_x
= 0;
3728 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
3729 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
3733 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3734 the state in PUP. XBUTTON provides extra information for extended mouse
3735 button messages. Returns FALSE if unable to parse the message. */
3737 parse_button (message
, xbutton
, pbutton
, pup
)
3748 case WM_LBUTTONDOWN
:
3756 case WM_MBUTTONDOWN
:
3757 if (NILP (Vw32_swap_mouse_buttons
))
3764 if (NILP (Vw32_swap_mouse_buttons
))
3770 case WM_RBUTTONDOWN
:
3771 if (NILP (Vw32_swap_mouse_buttons
))
3778 if (NILP (Vw32_swap_mouse_buttons
))
3784 case WM_XBUTTONDOWN
:
3785 button
= xbutton
+ 2;
3789 button
= xbutton
+ 2;
3797 if (pbutton
) *pbutton
= button
;
3803 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3805 If the event is a button press, then note that we have grabbed
3809 construct_mouse_click (result
, msg
, f
)
3810 struct input_event
*result
;
3817 parse_button (msg
->msg
.message
, HIWORD (msg
->msg
.wParam
),
3820 /* Make the event type NO_EVENT; we'll change that when we decide
3822 result
->kind
= MOUSE_CLICK_EVENT
;
3823 result
->code
= button
;
3824 result
->timestamp
= msg
->msg
.time
;
3825 result
->modifiers
= (msg
->dwModifiers
3830 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
3831 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
3832 XSETFRAME (result
->frame_or_window
, f
);
3838 construct_mouse_wheel (result
, msg
, f
)
3839 struct input_event
*result
;
3844 result
->kind
= MOUSE_WHEEL_EVENT
;
3845 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
3846 result
->timestamp
= msg
->msg
.time
;
3847 result
->modifiers
= msg
->dwModifiers
;
3848 p
.x
= LOWORD (msg
->msg
.lParam
);
3849 p
.y
= HIWORD (msg
->msg
.lParam
);
3850 ScreenToClient (msg
->msg
.hwnd
, &p
);
3851 XSETINT (result
->x
, p
.x
);
3852 XSETINT (result
->y
, p
.y
);
3853 XSETFRAME (result
->frame_or_window
, f
);
3859 construct_drag_n_drop (result
, msg
, f
)
3860 struct input_event
*result
;
3872 result
->kind
= DRAG_N_DROP_EVENT
;
3874 result
->timestamp
= msg
->msg
.time
;
3875 result
->modifiers
= msg
->dwModifiers
;
3877 hdrop
= (HDROP
) msg
->msg
.wParam
;
3878 DragQueryPoint (hdrop
, &p
);
3881 p
.x
= LOWORD (msg
->msg
.lParam
);
3882 p
.y
= HIWORD (msg
->msg
.lParam
);
3883 ScreenToClient (msg
->msg
.hwnd
, &p
);
3886 XSETINT (result
->x
, p
.x
);
3887 XSETINT (result
->y
, p
.y
);
3889 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
3892 for (i
= 0; i
< num_files
; i
++)
3894 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
3897 name
= alloca (len
+ 1);
3898 DragQueryFile (hdrop
, i
, name
, len
+ 1);
3899 files
= Fcons (DECODE_FILE (build_string (name
)), files
);
3904 XSETFRAME (frame
, f
);
3905 result
->frame_or_window
= Fcons (frame
, files
);
3911 /* Function to report a mouse movement to the mainstream Emacs code.
3912 The input handler calls this.
3914 We have received a mouse movement event, which is given in *event.
3915 If the mouse is over a different glyph than it was last time, tell
3916 the mainstream emacs code by setting mouse_moved. If not, ask for
3917 another motion event, so we can check again the next time it moves. */
3919 static MSG last_mouse_motion_event
;
3920 static Lisp_Object last_mouse_motion_frame
;
3922 static void remember_mouse_glyph
P_ ((struct frame
*, int, int));
3925 note_mouse_movement (frame
, msg
)
3929 int mouse_x
= LOWORD (msg
->lParam
);
3930 int mouse_y
= HIWORD (msg
->lParam
);
3932 last_mouse_movement_time
= msg
->time
;
3933 memcpy (&last_mouse_motion_event
, msg
, sizeof (last_mouse_motion_event
));
3934 XSETFRAME (last_mouse_motion_frame
, frame
);
3936 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
3938 frame
->mouse_moved
= 1;
3939 last_mouse_scroll_bar
= Qnil
;
3940 note_mouse_highlight (frame
, -1, -1);
3943 /* Has the mouse moved off the glyph it was on at the last sighting? */
3944 else if (mouse_x
< last_mouse_glyph
.left
3945 || mouse_x
> last_mouse_glyph
.right
3946 || mouse_y
< last_mouse_glyph
.top
3947 || mouse_y
> last_mouse_glyph
.bottom
)
3949 frame
->mouse_moved
= 1;
3950 last_mouse_scroll_bar
= Qnil
;
3951 note_mouse_highlight (frame
, mouse_x
, mouse_y
);
3952 /* Remember the mouse position here, as w32_mouse_position only
3953 gets called when mouse tracking is enabled but we also need
3954 to keep track of the mouse for help_echo and highlighting at
3956 remember_mouse_glyph (frame
, mouse_x
, mouse_y
);
3961 /************************************************************************
3963 ************************************************************************/
3965 /* Find the glyph under window-relative coordinates X/Y in window W.
3966 Consider only glyphs from buffer text, i.e. no glyphs from overlay
3967 strings. Return in *HPOS and *VPOS the row and column number of
3968 the glyph found. Return in *AREA the glyph area containing X.
3969 Value is a pointer to the glyph found or null if X/Y is not on
3970 text, or we can't tell because W's current matrix is not up to
3973 static struct glyph
*
3974 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
, buffer_only_p
)
3977 int *hpos
, *vpos
, *area
;
3980 struct glyph
*glyph
, *end
;
3981 struct glyph_row
*row
= NULL
;
3982 int x0
, i
, left_area_width
;
3984 /* Find row containing Y. Give up if some row is not enabled. */
3985 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
3987 row
= MATRIX_ROW (w
->current_matrix
, i
);
3988 if (!row
->enabled_p
)
3990 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
3997 /* Give up if Y is not in the window. */
3998 if (i
== w
->current_matrix
->nrows
)
4001 /* Get the glyph area containing X. */
4002 if (w
->pseudo_window_p
)
4009 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
4010 if (x
< left_area_width
)
4012 *area
= LEFT_MARGIN_AREA
;
4015 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
4018 x0
= row
->x
+ left_area_width
;
4022 *area
= RIGHT_MARGIN_AREA
;
4023 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
4027 /* Find glyph containing X. */
4028 glyph
= row
->glyphs
[*area
];
4029 end
= glyph
+ row
->used
[*area
];
4032 if (x
< x0
+ glyph
->pixel_width
)
4034 if (w
->pseudo_window_p
)
4036 else if (!buffer_only_p
|| BUFFERP (glyph
->object
))
4040 x0
+= glyph
->pixel_width
;
4047 *hpos
= glyph
- row
->glyphs
[*area
];
4052 /* Convert frame-relative x/y to coordinates relative to window W.
4053 Takes pseudo-windows into account. */
4056 frame_to_window_pixel_xy (w
, x
, y
)
4060 if (w
->pseudo_window_p
)
4062 /* A pseudo-window is always full-width, and starts at the
4063 left edge of the frame, plus a frame border. */
4064 struct frame
*f
= XFRAME (w
->frame
);
4065 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
4066 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
4070 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
4071 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
4076 /* Take proper action when mouse has moved to the mode or header line
4077 or marginal area of window W, x-position X and y-position Y. Area
4078 is 1, 3, 6 or 7 for the mode line, header line, left and right
4079 marginal area respectively. X is relative to the start of the text
4080 display area of W, so the width of bitmap areas and scroll bars
4081 must be subtracted to get a position relative to the start of the
4085 note_mode_line_or_margin_highlight (w
, x
, y
, portion
)
4089 struct frame
*f
= XFRAME (w
->frame
);
4090 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4091 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
4093 Lisp_Object string
, help
, map
, pos
;
4095 if (portion
== 1 || portion
== 3)
4096 string
= mode_line_string (w
, x
, y
, portion
== 1, &charpos
);
4098 string
= marginal_area_string (w
, x
, y
, portion
, &charpos
);
4100 if (STRINGP (string
))
4102 pos
= make_number (charpos
);
4104 /* If we're on a string with `help-echo' text property, arrange
4105 for the help to be displayed. This is done by setting the
4106 global variable help_echo to the help string. */
4107 help
= Fget_text_property (pos
, Qhelp_echo
, string
);
4111 XSETWINDOW (help_echo_window
, w
);
4112 help_echo_object
= string
;
4113 help_echo_pos
= charpos
;
4116 /* Change the mouse pointer according to what is under X/Y. */
4117 map
= Fget_text_property (pos
, Qlocal_map
, string
);
4119 map
= Fget_text_property (pos
, Qkeymap
, string
);
4121 cursor
= f
->output_data
.w32
->nontext_cursor
;
4124 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
4128 /* Take proper action when the mouse has moved to position X, Y on
4129 frame F as regards highlighting characters that have mouse-face
4130 properties. Also de-highlighting chars where the mouse was before.
4131 X and Y can be negative or out of range. */
4134 note_mouse_highlight (f
, x
, y
)
4138 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4145 /* When a menu is active, don't highlight because this looks odd. */
4146 if (popup_activated ())
4149 if (NILP (Vmouse_highlight
)
4150 || !f
->glyphs_initialized_p
)
4153 dpyinfo
->mouse_face_mouse_x
= x
;
4154 dpyinfo
->mouse_face_mouse_y
= y
;
4155 dpyinfo
->mouse_face_mouse_frame
= f
;
4157 if (dpyinfo
->mouse_face_defer
)
4162 dpyinfo
->mouse_face_deferred_gc
= 1;
4166 /* Which window is that in? */
4167 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
4169 /* If we were displaying active text in another window, clear that. */
4170 if (! EQ (window
, dpyinfo
->mouse_face_window
))
4171 clear_mouse_face (dpyinfo
);
4173 /* Not on a window -> return. */
4174 if (!WINDOWP (window
))
4177 /* Reset help_echo. It will get recomputed below. */
4180 /* Convert to window-relative pixel coordinates. */
4181 w
= XWINDOW (window
);
4182 frame_to_window_pixel_xy (w
, &x
, &y
);
4184 /* Handle tool-bar window differently since it doesn't display a
4186 if (EQ (window
, f
->tool_bar_window
))
4188 note_tool_bar_highlight (f
, x
, y
);
4192 /* Mouse is on the mode or header line? */
4193 if (portion
== 1 || portion
== 3 || portion
== 6 || portion
== 7)
4195 note_mode_line_or_margin_highlight (w
, x
, y
, portion
);
4200 cursor
= f
->output_data
.w32
->horizontal_drag_cursor
;
4202 cursor
= f
->output_data
.w32
->text_cursor
;
4204 /* Are we in a window whose display is up to date?
4205 And verify the buffer's text has not changed. */
4206 b
= XBUFFER (w
->buffer
);
4207 if (/* Within text portion of the window. */
4209 && EQ (w
->window_end_valid
, w
->buffer
)
4210 && XFASTINT (w
->last_modified
) == BUF_MODIFF (b
)
4211 && XFASTINT (w
->last_overlay_modified
) == BUF_OVERLAY_MODIFF (b
))
4213 int hpos
, vpos
, pos
, i
, area
;
4214 struct glyph
*glyph
;
4216 Lisp_Object mouse_face
= Qnil
, overlay
= Qnil
, position
;
4217 Lisp_Object
*overlay_vec
= NULL
;
4219 struct buffer
*obuf
;
4220 int obegv
, ozv
, same_region
;
4222 /* Find the glyph under X/Y. */
4223 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
, 0);
4225 /* Clear mouse face if X/Y not over text. */
4227 || area
!= TEXT_AREA
4228 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
4230 clear_mouse_face (dpyinfo
);
4231 cursor
= f
->output_data
.w32
->nontext_cursor
;
4235 pos
= glyph
->charpos
;
4236 object
= glyph
->object
;
4237 if (!STRINGP (object
) && !BUFFERP (object
))
4240 /* If we get an out-of-range value, return now; avoid an error. */
4241 if (BUFFERP (object
) && pos
> BUF_Z (b
))
4244 /* Make the window's buffer temporarily current for
4245 overlays_at and compute_char_face. */
4246 obuf
= current_buffer
;
4253 /* Is this char mouse-active or does it have help-echo? */
4254 position
= make_number (pos
);
4256 if (BUFFERP (object
))
4258 /* Put all the overlays we want in a vector in overlay_vec.
4259 Store the length in len. If there are more than 10, make
4260 enough space for all, and try again. */
4262 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
4263 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
, 0);
4264 if (noverlays
> len
)
4267 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
4268 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
,0);
4271 /* Sort overlays into increasing priority order. */
4272 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
4277 same_region
= (EQ (window
, dpyinfo
->mouse_face_window
)
4278 && vpos
>= dpyinfo
->mouse_face_beg_row
4279 && vpos
<= dpyinfo
->mouse_face_end_row
4280 && (vpos
> dpyinfo
->mouse_face_beg_row
4281 || hpos
>= dpyinfo
->mouse_face_beg_col
)
4282 && (vpos
< dpyinfo
->mouse_face_end_row
4283 || hpos
< dpyinfo
->mouse_face_end_col
4284 || dpyinfo
->mouse_face_past_end
));
4289 /* Check mouse-face highlighting. */
4291 /* If there exists an overlay with mouse-face overlapping
4292 the one we are currently highlighting, we have to
4293 check if we enter the overlapping overlay, and then
4295 || (OVERLAYP (dpyinfo
->mouse_face_overlay
)
4296 && mouse_face_overlay_overlaps (dpyinfo
->mouse_face_overlay
)))
4298 /* Find the highest priority overlay that has a mouse-face
4301 for (i
= noverlays
- 1; i
>= 0 && NILP (overlay
); --i
)
4303 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
4304 if (!NILP (mouse_face
))
4305 overlay
= overlay_vec
[i
];
4308 /* If we're actually highlighting the same overlay as
4309 before, there's no need to do that again. */
4311 && EQ (overlay
, dpyinfo
->mouse_face_overlay
))
4312 goto check_help_echo
;
4314 dpyinfo
->mouse_face_overlay
= overlay
;
4316 /* Clear the display of the old active region, if any. */
4317 if (clear_mouse_face (dpyinfo
))
4320 /* If no overlay applies, get a text property. */
4322 mouse_face
= Fget_text_property (position
, Qmouse_face
, object
);
4324 /* Handle the overlay case. */
4325 if (!NILP (overlay
))
4327 /* Find the range of text around this char that
4328 should be active. */
4329 Lisp_Object before
, after
;
4332 before
= Foverlay_start (overlay
);
4333 after
= Foverlay_end (overlay
);
4334 /* Record this as the current active region. */
4335 fast_find_position (w
, XFASTINT (before
),
4336 &dpyinfo
->mouse_face_beg_col
,
4337 &dpyinfo
->mouse_face_beg_row
,
4338 &dpyinfo
->mouse_face_beg_x
,
4339 &dpyinfo
->mouse_face_beg_y
, Qnil
);
4341 dpyinfo
->mouse_face_past_end
4342 = !fast_find_position (w
, XFASTINT (after
),
4343 &dpyinfo
->mouse_face_end_col
,
4344 &dpyinfo
->mouse_face_end_row
,
4345 &dpyinfo
->mouse_face_end_x
,
4346 &dpyinfo
->mouse_face_end_y
, Qnil
);
4347 dpyinfo
->mouse_face_window
= window
;
4349 dpyinfo
->mouse_face_face_id
4350 = face_at_buffer_position (w
, pos
, 0, 0,
4352 !dpyinfo
->mouse_face_hidden
);
4354 /* Display it as active. */
4355 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
4358 /* Handle the text property case. */
4359 else if (! NILP (mouse_face
) && BUFFERP (object
))
4361 /* Find the range of text around this char that
4362 should be active. */
4363 Lisp_Object before
, after
, beginning
, end
;
4366 beginning
= Fmarker_position (w
->start
);
4367 end
= make_number (BUF_Z (XBUFFER (object
))
4368 - XFASTINT (w
->window_end_pos
));
4370 = Fprevious_single_property_change (make_number (pos
+ 1),
4374 = Fnext_single_property_change (position
, Qmouse_face
,
4377 /* Record this as the current active region. */
4378 fast_find_position (w
, XFASTINT (before
),
4379 &dpyinfo
->mouse_face_beg_col
,
4380 &dpyinfo
->mouse_face_beg_row
,
4381 &dpyinfo
->mouse_face_beg_x
,
4382 &dpyinfo
->mouse_face_beg_y
, Qnil
);
4383 dpyinfo
->mouse_face_past_end
4384 = !fast_find_position (w
, XFASTINT (after
),
4385 &dpyinfo
->mouse_face_end_col
,
4386 &dpyinfo
->mouse_face_end_row
,
4387 &dpyinfo
->mouse_face_end_x
,
4388 &dpyinfo
->mouse_face_end_y
, Qnil
);
4389 dpyinfo
->mouse_face_window
= window
;
4391 if (BUFFERP (object
))
4392 dpyinfo
->mouse_face_face_id
4393 = face_at_buffer_position (w
, pos
, 0, 0,
4395 !dpyinfo
->mouse_face_hidden
);
4397 /* Display it as active. */
4398 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
4401 else if (!NILP (mouse_face
) && STRINGP (object
))
4406 b
= Fprevious_single_property_change (make_number (pos
+ 1),
4409 e
= Fnext_single_property_change (position
, Qmouse_face
,
4412 b
= make_number (0);
4414 e
= make_number (SCHARS (object
) - 1);
4415 fast_find_string_pos (w
, XINT (b
), object
,
4416 &dpyinfo
->mouse_face_beg_col
,
4417 &dpyinfo
->mouse_face_beg_row
,
4418 &dpyinfo
->mouse_face_beg_x
,
4419 &dpyinfo
->mouse_face_beg_y
, 0);
4420 fast_find_string_pos (w
, XINT (e
), object
,
4421 &dpyinfo
->mouse_face_end_col
,
4422 &dpyinfo
->mouse_face_end_row
,
4423 &dpyinfo
->mouse_face_end_x
,
4424 &dpyinfo
->mouse_face_end_y
, 1);
4425 dpyinfo
->mouse_face_past_end
= 0;
4426 dpyinfo
->mouse_face_window
= window
;
4427 dpyinfo
->mouse_face_face_id
4428 = face_at_string_position (w
, object
, pos
, 0, 0, 0, &ignore
,
4430 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
4433 else if (STRINGP (object
) && NILP (mouse_face
))
4435 /* A string which doesn't have mouse-face, but
4436 the text ``under'' it might have. */
4437 struct glyph_row
*r
= MATRIX_ROW (w
->current_matrix
, vpos
);
4438 int start
= MATRIX_ROW_START_CHARPOS (r
);
4440 pos
= string_buffer_position (w
, object
, start
);
4442 mouse_face
= get_char_property_and_overlay (make_number (pos
),
4446 if (!NILP (mouse_face
) && !NILP (overlay
))
4448 Lisp_Object before
= Foverlay_start (overlay
);
4449 Lisp_Object after
= Foverlay_end (overlay
);
4452 /* Note that we might not be able to find position
4453 BEFORE in the glyph matrix if the overlay is
4454 entirely covered by a `display' property. In
4455 this case, we overshoot. So let's stop in
4456 the glyph matrix before glyphs for OBJECT. */
4457 fast_find_position (w
, XFASTINT (before
),
4458 &dpyinfo
->mouse_face_beg_col
,
4459 &dpyinfo
->mouse_face_beg_row
,
4460 &dpyinfo
->mouse_face_beg_x
,
4461 &dpyinfo
->mouse_face_beg_y
,
4464 dpyinfo
->mouse_face_past_end
4465 = !fast_find_position (w
, XFASTINT (after
),
4466 &dpyinfo
->mouse_face_end_col
,
4467 &dpyinfo
->mouse_face_end_row
,
4468 &dpyinfo
->mouse_face_end_x
,
4469 &dpyinfo
->mouse_face_end_y
,
4471 dpyinfo
->mouse_face_window
= window
;
4472 dpyinfo
->mouse_face_face_id
4473 = face_at_buffer_position (w
, pos
, 0, 0,
4475 !dpyinfo
->mouse_face_hidden
);
4477 /* Display it as active. */
4478 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
4486 /* Look for a `help-echo' property. */
4488 Lisp_Object help
, overlay
;
4490 /* Check overlays first. */
4491 help
= overlay
= Qnil
;
4492 for (i
= noverlays
- 1; i
>= 0 && NILP (help
); --i
)
4494 overlay
= overlay_vec
[i
];
4495 help
= Foverlay_get (overlay
, Qhelp_echo
);
4501 help_echo_window
= window
;
4502 help_echo_object
= overlay
;
4503 help_echo_pos
= pos
;
4507 Lisp_Object object
= glyph
->object
;
4508 int charpos
= glyph
->charpos
;
4510 /* Try text properties. */
4511 if (STRINGP (object
)
4513 && charpos
< SCHARS (object
))
4515 help
= Fget_text_property (make_number (charpos
),
4516 Qhelp_echo
, object
);
4519 /* If the string itself doesn't specify a help-echo,
4520 see if the buffer text ``under'' it does. */
4522 = MATRIX_ROW (w
->current_matrix
, vpos
);
4523 int start
= MATRIX_ROW_START_CHARPOS (r
);
4524 int pos
= string_buffer_position (w
, object
, start
);
4527 help
= Fget_char_property (make_number (pos
),
4528 Qhelp_echo
, w
->buffer
);
4537 else if (BUFFERP (object
)
4540 help
= Fget_text_property (make_number (charpos
), Qhelp_echo
,
4546 help_echo_window
= window
;
4547 help_echo_object
= object
;
4548 help_echo_pos
= charpos
;
4555 current_buffer
= obuf
;
4560 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
4564 redo_mouse_highlight ()
4566 if (!NILP (last_mouse_motion_frame
)
4567 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4568 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4569 LOWORD (last_mouse_motion_event
.lParam
),
4570 HIWORD (last_mouse_motion_event
.lParam
));
4574 w32_define_cursor (window
, cursor
)
4578 PostMessage (window
, WM_EMACS_SETCURSOR
, (WPARAM
) cursor
, 0);
4582 /***********************************************************************
4584 ***********************************************************************/
4586 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
4587 struct glyph
**, int *, int *, int *));
4589 /* Tool-bar item index of the item on which a mouse button was pressed
4592 static int last_tool_bar_item
;
4595 /* Get information about the tool-bar item at position X/Y on frame F.
4596 Return in *GLYPH a pointer to the glyph of the tool-bar item in
4597 the current matrix of the tool-bar window of F, or NULL if not
4598 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
4599 item in F->tool_bar_items. Value is
4601 -1 if X/Y is not on a tool-bar item
4602 0 if X/Y is on the same item that was highlighted before.
4606 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
4609 struct glyph
**glyph
;
4610 int *hpos
, *vpos
, *prop_idx
;
4612 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4613 struct window
*w
= XWINDOW (f
->tool_bar_window
);
4616 /* Find the glyph under X/Y. */
4617 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
, 0);
4621 /* Get the start of this tool-bar item's properties in
4622 f->tool_bar_items. */
4623 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
4626 /* Is mouse on the highlighted item? */
4627 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
4628 && *vpos
>= dpyinfo
->mouse_face_beg_row
4629 && *vpos
<= dpyinfo
->mouse_face_end_row
4630 && (*vpos
> dpyinfo
->mouse_face_beg_row
4631 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
4632 && (*vpos
< dpyinfo
->mouse_face_end_row
4633 || *hpos
< dpyinfo
->mouse_face_end_col
4634 || dpyinfo
->mouse_face_past_end
))
4641 /* Handle mouse button event on the tool-bar of frame F, at
4642 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4646 w32_handle_tool_bar_click (f
, button_event
)
4648 struct input_event
*button_event
;
4650 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4651 struct window
*w
= XWINDOW (f
->tool_bar_window
);
4652 int hpos
, vpos
, prop_idx
;
4653 struct glyph
*glyph
;
4654 Lisp_Object enabled_p
;
4655 int x
= XFASTINT (button_event
->x
);
4656 int y
= XFASTINT (button_event
->y
);
4658 /* If not on the highlighted tool-bar item, return. */
4659 frame_to_window_pixel_xy (w
, &x
, &y
);
4660 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
4663 /* If item is disabled, do nothing. */
4664 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
4665 if (NILP (enabled_p
))
4668 if (button_event
->modifiers
& down_modifier
)
4670 /* Show item in pressed state. */
4671 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
4672 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
4673 last_tool_bar_item
= prop_idx
;
4677 Lisp_Object key
, frame
;
4678 struct input_event event
;
4680 /* Show item in released state. */
4681 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
4682 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
4684 key
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_KEY
);
4686 XSETFRAME (frame
, f
);
4687 event
.kind
= TOOL_BAR_EVENT
;
4688 event
.frame_or_window
= frame
;
4690 kbd_buffer_store_event (&event
);
4692 event
.kind
= TOOL_BAR_EVENT
;
4693 event
.frame_or_window
= frame
;
4695 /* The keyboard buffer doesn't like the up modifier being set. */
4696 event
.modifiers
= button_event
->modifiers
& ~up_modifier
;
4697 kbd_buffer_store_event (&event
);
4698 last_tool_bar_item
= -1;
4703 /* Possibly highlight a tool-bar item on frame F when mouse moves to
4704 tool-bar window-relative coordinates X/Y. Called from
4705 note_mouse_highlight. */
4708 note_tool_bar_highlight (f
, x
, y
)
4712 Lisp_Object window
= f
->tool_bar_window
;
4713 struct window
*w
= XWINDOW (window
);
4714 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4716 struct glyph
*glyph
;
4717 struct glyph_row
*row
;
4719 Lisp_Object enabled_p
;
4721 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
4722 int mouse_down_p
, rc
;
4724 /* Function note_mouse_highlight is called with negative x(y
4725 values when mouse moves outside of the frame. */
4726 if (x
<= 0 || y
<= 0)
4728 clear_mouse_face (dpyinfo
);
4732 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
4735 /* Not on tool-bar item. */
4736 clear_mouse_face (dpyinfo
);
4740 /* On same tool-bar item as before. */
4743 clear_mouse_face (dpyinfo
);
4745 /* Mouse is down, but on different tool-bar item? */
4746 mouse_down_p
= (dpyinfo
->grabbed
4747 && f
== last_mouse_frame
4748 && FRAME_LIVE_P (f
));
4750 && last_tool_bar_item
!= prop_idx
)
4753 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
4754 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
4756 /* If tool-bar item is not enabled, don't highlight it. */
4757 enabled_p
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
);
4758 if (!NILP (enabled_p
))
4760 /* Compute the x-position of the glyph. In front and past the
4761 image is a space. We include this is the highlighted area. */
4762 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
4763 for (i
= x
= 0; i
< hpos
; ++i
)
4764 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
4766 /* Record this as the current active region. */
4767 dpyinfo
->mouse_face_beg_col
= hpos
;
4768 dpyinfo
->mouse_face_beg_row
= vpos
;
4769 dpyinfo
->mouse_face_beg_x
= x
;
4770 dpyinfo
->mouse_face_beg_y
= row
->y
;
4771 dpyinfo
->mouse_face_past_end
= 0;
4773 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
4774 dpyinfo
->mouse_face_end_row
= vpos
;
4775 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
4776 dpyinfo
->mouse_face_end_y
= row
->y
;
4777 dpyinfo
->mouse_face_window
= window
;
4778 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
4780 /* Display it as active. */
4781 show_mouse_face (dpyinfo
, draw
);
4782 dpyinfo
->mouse_face_image_state
= draw
;
4787 /* Set help_echo to a help string.to display for this tool-bar item.
4788 w32_read_socket does the rest. */
4789 help_echo_object
= help_echo_window
= Qnil
;
4791 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_HELP
);
4792 if (NILP (help_echo
))
4793 help_echo
= AREF (f
->tool_bar_items
, prop_idx
+ TOOL_BAR_ITEM_CAPTION
);
4798 /* Find the glyph matrix position of buffer position CHARPOS in window
4799 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
4800 current glyphs must be up to date. If CHARPOS is above window
4801 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
4802 of last line in W. In the row containing CHARPOS, stop before glyphs
4803 having STOP as object. */
4805 #if 0 /* This is a version of fast_find_position that's more correct
4806 in the presence of hscrolling, for example. I didn't install
4807 it right away because the problem fixed is minor, it failed
4808 in 20.x as well, and I think it's too risky to install
4809 so near the release of 21.1. 2001-09-25 gerd. */
4812 fast_find_position (w
, charpos
, hpos
, vpos
, x
, y
, stop
)
4815 int *hpos
, *vpos
, *x
, *y
;
4818 struct glyph_row
*row
, *first
;
4819 struct glyph
*glyph
, *end
;
4820 int i
, past_end
= 0;
4822 first
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
4823 row
= row_containing_pos (w
, charpos
, first
, NULL
, 0);
4826 if (charpos
< MATRIX_ROW_START_CHARPOS (first
))
4828 *x
= *y
= *hpos
= *vpos
= 0;
4833 row
= MATRIX_ROW (w
->current_matrix
, XFASTINT (w
->window_end_vpos
));
4840 *vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
4842 glyph
= row
->glyphs
[TEXT_AREA
];
4843 end
= glyph
+ row
->used
[TEXT_AREA
];
4845 /* Skip over glyphs not having an object at the start of the row.
4846 These are special glyphs like truncation marks on terminal
4848 if (row
->displays_text_p
)
4850 && INTEGERP (glyph
->object
)
4851 && !EQ (stop
, glyph
->object
)
4852 && glyph
->charpos
< 0)
4854 *x
+= glyph
->pixel_width
;
4859 && !INTEGERP (glyph
->object
)
4860 && !EQ (stop
, glyph
->object
)
4861 && (!BUFFERP (glyph
->object
)
4862 || glyph
->charpos
< charpos
))
4864 *x
+= glyph
->pixel_width
;
4868 *hpos
= glyph
- row
->glyphs
[TEXT_AREA
];
4875 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
, stop
)
4878 int *hpos
, *vpos
, *x
, *y
;
4883 int maybe_next_line_p
= 0;
4884 int line_start_position
;
4885 int yb
= window_text_bottom_y (w
);
4886 struct glyph_row
*row
, *best_row
;
4887 int row_vpos
, best_row_vpos
;
4890 row
= best_row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
4891 row_vpos
= best_row_vpos
= MATRIX_ROW_VPOS (row
, w
->current_matrix
);
4895 if (row
->used
[TEXT_AREA
])
4896 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
4898 line_start_position
= 0;
4900 if (line_start_position
> pos
)
4902 /* If the position sought is the end of the buffer,
4903 don't include the blank lines at the bottom of the window. */
4904 else if (line_start_position
== pos
4905 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
4907 maybe_next_line_p
= 1;
4910 else if (line_start_position
> 0)
4913 best_row_vpos
= row_vpos
;
4916 if (row
->y
+ row
->height
>= yb
)
4923 /* Find the right column within BEST_ROW. */
4925 current_x
= best_row
->x
;
4926 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
4928 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
4929 int charpos
= glyph
->charpos
;
4931 if (BUFFERP (glyph
->object
))
4936 *vpos
= best_row_vpos
;
4941 else if (charpos
> pos
)
4944 else if (EQ (glyph
->object
, stop
))
4949 current_x
+= glyph
->pixel_width
;
4952 /* If we're looking for the end of the buffer,
4953 and we didn't find it in the line we scanned,
4954 use the start of the following line. */
4955 if (maybe_next_line_p
)
4960 current_x
= best_row
->x
;
4963 *vpos
= best_row_vpos
;
4964 *hpos
= lastcol
+ 1;
4973 /* Find the position of the glyph for position POS in OBJECT in
4974 window W's current matrix, and return in *X/*Y the pixel
4975 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
4977 RIGHT_P non-zero means return the position of the right edge of the
4978 glyph, RIGHT_P zero means return the left edge position.
4980 If no glyph for POS exists in the matrix, return the position of
4981 the glyph with the next smaller position that is in the matrix, if
4982 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
4983 exists in the matrix, return the position of the glyph with the
4984 next larger position in OBJECT.
4986 Value is non-zero if a glyph was found. */
4989 fast_find_string_pos (w
, pos
, object
, hpos
, vpos
, x
, y
, right_p
)
4993 int *hpos
, *vpos
, *x
, *y
;
4996 int yb
= window_text_bottom_y (w
);
4997 struct glyph_row
*r
;
4998 struct glyph
*best_glyph
= NULL
;
4999 struct glyph_row
*best_row
= NULL
;
5002 for (r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5003 r
->enabled_p
&& r
->y
< yb
;
5006 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
5007 struct glyph
*e
= g
+ r
->used
[TEXT_AREA
];
5010 for (gx
= r
->x
; g
< e
; gx
+= g
->pixel_width
, ++g
)
5011 if (EQ (g
->object
, object
))
5013 if (g
->charpos
== pos
)
5020 else if (best_glyph
== NULL
5021 || ((abs (g
->charpos
- pos
)
5022 < abs (best_glyph
->charpos
- pos
))
5025 : g
->charpos
> pos
)))
5039 *hpos
= best_glyph
- best_row
->glyphs
[TEXT_AREA
];
5043 *x
+= best_glyph
->pixel_width
;
5048 *vpos
= best_row
- w
->current_matrix
->rows
;
5051 return best_glyph
!= NULL
;
5055 /* Display the active region described by mouse_face_*
5056 in its mouse-face if HL > 0, in its normal face if HL = 0. */
5059 show_mouse_face (dpyinfo
, draw
)
5060 struct w32_display_info
*dpyinfo
;
5061 enum draw_glyphs_face draw
;
5063 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
5064 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5066 if (/* If window is in the process of being destroyed, don't bother
5068 w
->current_matrix
!= NULL
5069 /* Don't update mouse highlight if hidden */
5070 && (draw
!= DRAW_MOUSE_FACE
|| !dpyinfo
->mouse_face_hidden
)
5071 /* Recognize when we are called to operate on rows that don't exist
5072 anymore. This can happen when a window is split. */
5073 && dpyinfo
->mouse_face_end_row
< w
->current_matrix
->nrows
)
5075 int phys_cursor_on_p
= w
->phys_cursor_on_p
;
5076 struct glyph_row
*row
, *first
, *last
;
5078 first
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_beg_row
);
5079 last
= MATRIX_ROW (w
->current_matrix
, dpyinfo
->mouse_face_end_row
);
5081 for (row
= first
; row
<= last
&& row
->enabled_p
; ++row
)
5083 int start_hpos
, end_hpos
, start_x
;
5085 /* For all but the first row, the highlight starts at column 0. */
5088 start_hpos
= dpyinfo
->mouse_face_beg_col
;
5089 start_x
= dpyinfo
->mouse_face_beg_x
;
5098 end_hpos
= dpyinfo
->mouse_face_end_col
;
5100 end_hpos
= row
->used
[TEXT_AREA
];
5102 if (end_hpos
> start_hpos
)
5104 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
5105 start_hpos
, end_hpos
, draw
, 0);
5108 = draw
== DRAW_MOUSE_FACE
|| draw
== DRAW_IMAGE_RAISED
;
5112 /* When we've written over the cursor, arrange for it to
5113 be displayed again. */
5114 if (phys_cursor_on_p
&& !w
->phys_cursor_on_p
)
5115 x_display_cursor (w
, 1,
5116 w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
5117 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
5120 /* Change the mouse cursor. */
5121 if (draw
== DRAW_NORMAL_TEXT
)
5122 w32_define_cursor (FRAME_W32_WINDOW (f
),
5123 f
->output_data
.w32
->text_cursor
);
5124 else if (draw
== DRAW_MOUSE_FACE
)
5125 w32_define_cursor (FRAME_W32_WINDOW (f
),
5126 f
->output_data
.w32
->hand_cursor
);
5128 w32_define_cursor (FRAME_W32_WINDOW (f
),
5129 f
->output_data
.w32
->nontext_cursor
);
5133 /* Clear out the mouse-highlighted active region.
5134 Redraw it un-highlighted first. */
5137 clear_mouse_face (dpyinfo
)
5138 struct w32_display_info
*dpyinfo
;
5142 if (! NILP (dpyinfo
->mouse_face_window
))
5144 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
5148 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5149 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5150 dpyinfo
->mouse_face_window
= Qnil
;
5151 dpyinfo
->mouse_face_overlay
= Qnil
;
5156 /* Clear any mouse-face on window W. This function is part of the
5157 redisplay interface, and is called from try_window_id and similar
5158 functions to ensure the mouse-highlight is off. */
5161 x_clear_mouse_face (w
)
5164 struct w32_display_info
*dpyinfo
5165 = FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
5169 XSETWINDOW (window
, w
);
5170 if (EQ (window
, dpyinfo
->mouse_face_window
))
5171 clear_mouse_face (dpyinfo
);
5176 /* Just discard the mouse face information for frame F, if any.
5177 This is used when the size of F is changed. */
5180 cancel_mouse_face (f
)
5184 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5186 window
= dpyinfo
->mouse_face_window
;
5187 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
5189 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5190 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5191 dpyinfo
->mouse_face_window
= Qnil
;
5195 static struct scroll_bar
*x_window_to_scroll_bar ();
5196 static void x_scroll_bar_report_motion ();
5197 static void x_check_fullscreen
P_ ((struct frame
*));
5198 static void x_check_fullscreen_move
P_ ((struct frame
*));
5199 static int glyph_rect
P_ ((struct frame
*f
, int, int, RECT
*));
5202 /* Try to determine frame pixel position and size of the glyph under
5203 frame pixel coordinates X/Y on frame F . Return the position and
5204 size in *RECT. Value is non-zero if we could compute these
5208 glyph_rect (f
, x
, y
, rect
)
5216 window
= window_from_coordinates (f
, x
, y
, &part
, 0);
5219 struct window
*w
= XWINDOW (window
);
5220 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
5221 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
5223 frame_to_window_pixel_xy (w
, &x
, &y
);
5225 for (; r
< end
&& r
->enabled_p
; ++r
)
5226 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
5228 /* Found the row at y. */
5229 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
5230 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
5233 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
5234 rect
->bottom
= rect
->top
+ r
->height
;
5238 /* x is to the left of the first glyph in the row. */
5239 rect
->left
= XINT (w
->left
);
5240 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
5244 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
5245 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
5247 /* x is on a glyph. */
5248 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
5249 rect
->right
= rect
->left
+ g
->pixel_width
;
5253 /* x is to the right of the last glyph in the row. */
5254 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
5255 rect
->right
= XINT (w
->left
) + XINT (w
->width
);
5260 /* The y is not on any row. */
5264 /* Record the position of the mouse in last_mouse_glyph. */
5266 remember_mouse_glyph (f1
, gx
, gy
)
5270 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
5272 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
5273 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
5275 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
5276 round down even for negative values. */
5282 /* This was the original code from XTmouse_position, but it seems
5283 to give the position of the glyph diagonally next to the one
5284 the mouse is over. */
5285 gx
= (gx
+ width
- 1) / width
* width
;
5286 gy
= (gy
+ height
- 1) / height
* height
;
5288 gx
= gx
/ width
* width
;
5289 gy
= gy
/ height
* height
;
5292 last_mouse_glyph
.left
= gx
;
5293 last_mouse_glyph
.top
= gy
;
5294 last_mouse_glyph
.right
= gx
+ width
;
5295 last_mouse_glyph
.bottom
= gy
+ height
;
5299 /* Return the current position of the mouse.
5300 *fp should be a frame which indicates which display to ask about.
5302 If the mouse movement started in a scroll bar, set *fp, *bar_window,
5303 and *part to the frame, window, and scroll bar part that the mouse
5304 is over. Set *x and *y to the portion and whole of the mouse's
5305 position on the scroll bar.
5307 If the mouse movement started elsewhere, set *fp to the frame the
5308 mouse is on, *bar_window to nil, and *x and *y to the character cell
5311 Set *time to the server time-stamp for the time at which the mouse
5312 was at this position.
5314 Don't store anything if we don't have a valid set of values to report.
5316 This clears the mouse_moved flag, so we can wait for the next mouse
5320 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
5323 Lisp_Object
*bar_window
;
5324 enum scroll_bar_part
*part
;
5326 unsigned long *time
;
5332 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
5333 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
5338 Lisp_Object frame
, tail
;
5340 /* Clear the mouse-moved flag for every frame on this display. */
5341 FOR_EACH_FRAME (tail
, frame
)
5342 XFRAME (frame
)->mouse_moved
= 0;
5344 last_mouse_scroll_bar
= Qnil
;
5348 /* Now we have a position on the root; find the innermost window
5349 containing the pointer. */
5351 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
5352 && FRAME_LIVE_P (last_mouse_frame
))
5354 /* If mouse was grabbed on a frame, give coords for that frame
5355 even if the mouse is now outside it. */
5356 f1
= last_mouse_frame
;
5360 /* Is window under mouse one of our frames? */
5361 f1
= x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
),
5362 WindowFromPoint (pt
));
5365 /* If not, is it one of our scroll bars? */
5368 struct scroll_bar
*bar
5369 = x_window_to_scroll_bar (WindowFromPoint (pt
));
5373 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5377 if (f1
== 0 && insist
> 0)
5378 f1
= SELECTED_FRAME ();
5382 /* Ok, we found a frame. Store all the values.
5383 last_mouse_glyph is a rectangle used to reduce the
5384 generation of mouse events. To not miss any motion
5385 events, we must divide the frame into rectangles of the
5386 size of the smallest character that could be displayed
5387 on it, i.e. into the same rectangles that matrices on
5388 the frame are divided into. */
5390 #if OLD_REDISPLAY_CODE
5391 int ignore1
, ignore2
;
5393 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
5395 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
5397 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
5400 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
5401 remember_mouse_glyph (f1
, pt
.x
, pt
.y
);
5409 *time
= last_mouse_movement_time
;
5418 /* Scroll bar support. */
5420 /* Given a window ID, find the struct scroll_bar which manages it.
5421 This can be called in GC, so we have to make sure to strip off mark
5424 static struct scroll_bar
*
5425 x_window_to_scroll_bar (window_id
)
5430 for (tail
= Vframe_list
;
5431 XGCTYPE (tail
) == Lisp_Cons
;
5434 Lisp_Object frame
, bar
, condemned
;
5436 frame
= XCAR (tail
);
5437 /* All elements of Vframe_list should be frames. */
5438 if (! GC_FRAMEP (frame
))
5441 /* Scan this frame's scroll bar list for a scroll bar with the
5443 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
5444 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
5445 /* This trick allows us to search both the ordinary and
5446 condemned scroll bar lists with one loop. */
5447 ! GC_NILP (bar
) || (bar
= condemned
,
5450 bar
= XSCROLL_BAR (bar
)->next
)
5451 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
5452 return XSCROLL_BAR (bar
);
5460 /* Set the thumb size and position of scroll bar BAR. We are currently
5461 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5464 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
)
5465 struct scroll_bar
*bar
;
5466 int portion
, position
, whole
;
5468 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
5469 double range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5470 int sb_page
, sb_pos
;
5471 BOOL draggingp
= !NILP (bar
->dragging
) ? TRUE
: FALSE
;
5475 /* Position scroll bar at rock bottom if the bottom of the
5476 buffer is visible. This avoids shinking the thumb away
5477 to nothing if it is held at the bottom of the buffer. */
5478 if (position
+ portion
>= whole
)
5480 sb_page
= range
* (whole
- position
) / whole
5481 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5485 sb_page
= portion
* range
/ whole
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5486 sb_pos
= position
* range
/ whole
;
5496 if (pfnSetScrollInfo
)
5500 si
.cbSize
= sizeof (si
);
5501 /* Only update page size if currently dragging, to reduce
5504 si
.fMask
= SIF_PAGE
;
5506 si
.fMask
= SIF_PAGE
| SIF_POS
;
5510 pfnSetScrollInfo (w
, SB_CTL
, &si
, !draggingp
);
5513 SetScrollPos (w
, SB_CTL
, sb_pos
, !draggingp
);
5519 /************************************************************************
5520 Scroll bars, general
5521 ************************************************************************/
5524 my_create_scrollbar (f
, bar
)
5526 struct scroll_bar
* bar
;
5528 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
5529 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
5533 /*#define ATTACH_THREADS*/
5536 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
5538 #ifndef ATTACH_THREADS
5539 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
5540 (WPARAM
) hwnd
, (LPARAM
) how
);
5542 return ShowWindow (hwnd
, how
);
5547 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
5548 int x
, int y
, int cx
, int cy
, UINT flags
)
5550 #ifndef ATTACH_THREADS
5552 pos
.hwndInsertAfter
= hwndAfter
;
5558 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
5560 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
5565 my_set_focus (f
, hwnd
)
5569 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
5574 my_set_foreground_window (hwnd
)
5577 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
5581 my_destroy_window (f
, hwnd
)
5585 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
5589 /* Create a scroll bar and return the scroll bar vector for it. W is
5590 the Emacs window on which to create the scroll bar. TOP, LEFT,
5591 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
5594 static struct scroll_bar
*
5595 x_scroll_bar_create (w
, top
, left
, width
, height
)
5597 int top
, left
, width
, height
;
5599 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5601 struct scroll_bar
*bar
5602 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
5606 XSETWINDOW (bar
->window
, w
);
5607 XSETINT (bar
->top
, top
);
5608 XSETINT (bar
->left
, left
);
5609 XSETINT (bar
->width
, width
);
5610 XSETINT (bar
->height
, height
);
5611 XSETINT (bar
->start
, 0);
5612 XSETINT (bar
->end
, 0);
5613 bar
->dragging
= Qnil
;
5615 /* Requires geometry to be set before call to create the real window */
5617 hwnd
= my_create_scrollbar (f
, bar
);
5619 if (pfnSetScrollInfo
)
5623 si
.cbSize
= sizeof (si
);
5626 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
5627 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5631 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
5635 SetScrollRange (hwnd
, SB_CTL
, 0,
5636 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
5637 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
5640 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
5642 /* Add bar to its frame's list of scroll bars. */
5643 bar
->next
= FRAME_SCROLL_BARS (f
);
5645 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5646 if (! NILP (bar
->next
))
5647 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5655 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5659 x_scroll_bar_remove (bar
)
5660 struct scroll_bar
*bar
;
5662 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
5666 /* Destroy the window. */
5667 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
5669 /* Disassociate this scroll bar from its window. */
5670 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
5675 /* Set the handle of the vertical scroll bar for WINDOW to indicate
5676 that we are displaying PORTION characters out of a total of WHOLE
5677 characters, starting at POSITION. If WINDOW has no scroll bar,
5680 w32_set_vertical_scroll_bar (w
, portion
, whole
, position
)
5682 int portion
, whole
, position
;
5684 struct frame
*f
= XFRAME (w
->frame
);
5685 struct scroll_bar
*bar
;
5686 int top
, height
, left
, sb_left
, width
, sb_width
;
5687 int window_x
, window_y
, window_width
, window_height
;
5689 /* Get window dimensions. */
5690 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5692 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
5693 height
= window_height
;
5695 /* Compute the left edge of the scroll bar area. */
5696 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5697 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
5699 left
= XFASTINT (w
->left
);
5700 left
*= CANON_X_UNIT (f
);
5701 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
5703 /* Compute the width of the scroll bar which might be less than
5704 the width of the area reserved for the scroll bar. */
5705 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
5706 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
5710 /* Compute the left edge of the scroll bar. */
5711 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
5712 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
5714 sb_left
= left
+ (width
- sb_width
) / 2;
5716 /* Does the scroll bar exist yet? */
5717 if (NILP (w
->vertical_scroll_bar
))
5721 if (width
> 0 && height
> 0)
5723 hdc
= get_frame_dc (f
);
5724 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
5725 release_frame_dc (f
, hdc
);
5729 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
5733 /* It may just need to be moved and resized. */
5736 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
5737 hwnd
= SCROLL_BAR_W32_WINDOW (bar
);
5739 /* If already correctly positioned, do nothing. */
5740 if ( XINT (bar
->left
) == sb_left
5741 && XINT (bar
->top
) == top
5742 && XINT (bar
->width
) == sb_width
5743 && XINT (bar
->height
) == height
)
5745 /* Redraw after clear_frame. */
5746 if (!my_show_window (f
, hwnd
, SW_NORMAL
))
5747 InvalidateRect (hwnd
, NULL
, FALSE
);
5753 if (width
&& height
)
5755 hdc
= get_frame_dc (f
);
5756 /* Since Windows scroll bars are smaller than the space reserved
5757 for them on the frame, we have to clear "under" them. */
5758 w32_clear_area (f
, hdc
,
5763 release_frame_dc (f
, hdc
);
5765 /* Make sure scroll bar is "visible" before moving, to ensure the
5766 area of the parent window now exposed will be refreshed. */
5767 my_show_window (f
, hwnd
, SW_HIDE
);
5768 MoveWindow (hwnd
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
5769 top
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
5770 max (height
, 1), TRUE
);
5771 if (pfnSetScrollInfo
)
5775 si
.cbSize
= sizeof (si
);
5776 si
.fMask
= SIF_RANGE
;
5778 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
5779 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
5781 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
5784 SetScrollRange (hwnd
, SB_CTL
, 0,
5785 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
5786 my_show_window (f
, hwnd
, SW_NORMAL
);
5787 /* InvalidateRect (w, NULL, FALSE); */
5789 /* Remember new settings. */
5790 XSETINT (bar
->left
, sb_left
);
5791 XSETINT (bar
->top
, top
);
5792 XSETINT (bar
->width
, sb_width
);
5793 XSETINT (bar
->height
, height
);
5798 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
5800 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
5804 /* The following three hooks are used when we're doing a thorough
5805 redisplay of the frame. We don't explicitly know which scroll bars
5806 are going to be deleted, because keeping track of when windows go
5807 away is a real pain - "Can you say set-window-configuration, boys
5808 and girls?" Instead, we just assert at the beginning of redisplay
5809 that *all* scroll bars are to be removed, and then save a scroll bar
5810 from the fiery pit when we actually redisplay its window. */
5812 /* Arrange for all scroll bars on FRAME to be removed at the next call
5813 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5814 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5817 w32_condemn_scroll_bars (frame
)
5820 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5821 while (! NILP (FRAME_SCROLL_BARS (frame
)))
5824 bar
= FRAME_SCROLL_BARS (frame
);
5825 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
5826 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
5827 XSCROLL_BAR (bar
)->prev
= Qnil
;
5828 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
5829 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
5830 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
5835 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5836 Note that WINDOW isn't necessarily condemned at all. */
5839 w32_redeem_scroll_bar (window
)
5840 struct window
*window
;
5842 struct scroll_bar
*bar
;
5845 /* We can't redeem this window's scroll bar if it doesn't have one. */
5846 if (NILP (window
->vertical_scroll_bar
))
5849 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5851 /* Unlink it from the condemned list. */
5852 f
= XFRAME (WINDOW_FRAME (window
));
5853 if (NILP (bar
->prev
))
5855 /* If the prev pointer is nil, it must be the first in one of
5857 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5858 /* It's not condemned. Everything's fine. */
5860 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5861 window
->vertical_scroll_bar
))
5862 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5864 /* If its prev pointer is nil, it must be at the front of
5865 one or the other! */
5869 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5871 if (! NILP (bar
->next
))
5872 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5874 bar
->next
= FRAME_SCROLL_BARS (f
);
5876 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5877 if (! NILP (bar
->next
))
5878 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5881 /* Remove all scroll bars on FRAME that haven't been saved since the
5882 last call to `*condemn_scroll_bars_hook'. */
5885 w32_judge_scroll_bars (f
)
5888 Lisp_Object bar
, next
;
5890 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5892 /* Clear out the condemned list now so we won't try to process any
5893 more events on the hapless scroll bars. */
5894 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5896 for (; ! NILP (bar
); bar
= next
)
5898 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5900 x_scroll_bar_remove (b
);
5903 b
->next
= b
->prev
= Qnil
;
5906 /* Now there should be no references to the condemned scroll bars,
5907 and they should get garbage-collected. */
5910 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5911 is set to something other than NO_EVENT, it is enqueued.
5913 This may be called from a signal handler, so we have to ignore GC
5917 w32_scroll_bar_handle_click (bar
, msg
, emacs_event
)
5918 struct scroll_bar
*bar
;
5920 struct input_event
*emacs_event
;
5922 if (! GC_WINDOWP (bar
->window
))
5925 emacs_event
->kind
= W32_SCROLL_BAR_CLICK_EVENT
;
5926 emacs_event
->code
= 0;
5927 /* not really meaningful to distinguish up/down */
5928 emacs_event
->modifiers
= msg
->dwModifiers
;
5929 emacs_event
->frame_or_window
= bar
->window
;
5930 emacs_event
->arg
= Qnil
;
5931 emacs_event
->timestamp
= msg
->msg
.time
;
5934 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5936 int dragging
= !NILP (bar
->dragging
);
5938 if (pfnGetScrollInfo
)
5942 si
.cbSize
= sizeof (si
);
5945 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
5949 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
5951 bar
->dragging
= Qnil
;
5954 last_mouse_scroll_bar_pos
= msg
->msg
.wParam
;
5956 switch (LOWORD (msg
->msg
.wParam
))
5959 emacs_event
->part
= scroll_bar_down_arrow
;
5962 emacs_event
->part
= scroll_bar_up_arrow
;
5965 emacs_event
->part
= scroll_bar_above_handle
;
5968 emacs_event
->part
= scroll_bar_below_handle
;
5971 emacs_event
->part
= scroll_bar_handle
;
5975 emacs_event
->part
= scroll_bar_handle
;
5979 case SB_THUMBPOSITION
:
5980 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
5981 y
= HIWORD (msg
->msg
.wParam
);
5983 emacs_event
->part
= scroll_bar_handle
;
5985 /* "Silently" update current position. */
5986 if (pfnSetScrollInfo
)
5990 si
.cbSize
= sizeof (si
);
5993 /* Remember apparent position (we actually lag behind the real
5994 position, so don't set that directly. */
5995 last_scroll_bar_drag_pos
= y
;
5997 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
6000 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
6003 /* If this is the end of a drag sequence, then reset the scroll
6004 handle size to normal and do a final redraw. Otherwise do
6008 if (pfnSetScrollInfo
)
6011 int start
= XINT (bar
->start
);
6012 int end
= XINT (bar
->end
);
6014 si
.cbSize
= sizeof (si
);
6015 si
.fMask
= SIF_PAGE
| SIF_POS
;
6016 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
6017 si
.nPos
= last_scroll_bar_drag_pos
;
6018 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
6021 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
6025 emacs_event
->kind
= NO_EVENT
;
6029 XSETINT (emacs_event
->x
, y
);
6030 XSETINT (emacs_event
->y
, top_range
);
6036 /* Return information to the user about the current position of the mouse
6037 on the scroll bar. */
6040 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
6042 Lisp_Object
*bar_window
;
6043 enum scroll_bar_part
*part
;
6045 unsigned long *time
;
6047 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
6048 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
6049 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6051 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
6056 *bar_window
= bar
->window
;
6058 if (pfnGetScrollInfo
)
6062 si
.cbSize
= sizeof (si
);
6063 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
6065 pfnGetScrollInfo (w
, SB_CTL
, &si
);
6067 top_range
= si
.nMax
- si
.nPage
+ 1;
6070 pos
= GetScrollPos (w
, SB_CTL
);
6072 switch (LOWORD (last_mouse_scroll_bar_pos
))
6074 case SB_THUMBPOSITION
:
6076 *part
= scroll_bar_handle
;
6077 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
6078 pos
= HIWORD (last_mouse_scroll_bar_pos
);
6081 *part
= scroll_bar_handle
;
6085 *part
= scroll_bar_handle
;
6090 XSETINT (*y
, top_range
);
6093 last_mouse_scroll_bar
= Qnil
;
6095 *time
= last_mouse_movement_time
;
6101 /* The screen has been cleared so we may have changed foreground or
6102 background colors, and the scroll bars may need to be redrawn.
6103 Clear out the scroll bars, and ask for expose events, so we can
6107 x_scroll_bar_clear (f
)
6112 /* We can have scroll bars even if this is 0,
6113 if we just turned off scroll bar mode.
6114 But in that case we should not clear them. */
6115 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
6116 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
6117 bar
= XSCROLL_BAR (bar
)->next
)
6119 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
6120 HDC hdc
= GetDC (window
);
6123 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
6124 arranges to refresh the scroll bar if hidden. */
6125 my_show_window (f
, window
, SW_HIDE
);
6127 GetClientRect (window
, &rect
);
6128 select_palette (f
, hdc
);
6129 w32_clear_rect (f
, hdc
, &rect
);
6130 deselect_palette (f
, hdc
);
6132 ReleaseDC (window
, hdc
);
6137 /* The main W32 event-reading loop - w32_read_socket. */
6139 /* Record the last 100 characters stored
6140 to help debug the loss-of-chars-during-GC problem. */
6142 static int temp_index
;
6143 static short temp_buffer
[100];
6146 /* Read events coming from the W32 shell.
6147 This routine is called by the SIGIO handler.
6148 We return as soon as there are no more events to be read.
6150 Events representing keys are stored in buffer BUFP,
6151 which can hold up to NUMCHARS characters.
6152 We return the number of characters stored into the buffer,
6153 thus pretending to be `read'.
6155 EXPECTED is nonzero if the caller knows input is available.
6157 Some of these messages are reposted back to the message queue since the
6158 system calls the windows proc directly in a context where we cannot return
6159 the data nor can we guarantee the state we are in. So if we dispatch them
6160 we will get into an infinite loop. To prevent this from ever happening we
6161 will set a variable to indicate we are in the read_socket call and indicate
6162 which message we are processing since the windows proc gets called
6163 recursively with different messages by the system.
6167 w32_read_socket (sd
, bufp
, numchars
, expected
)
6169 /* register */ struct input_event
*bufp
;
6170 /* register */ int numchars
;
6174 int check_visibility
= 0;
6177 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6179 if (interrupt_input_blocked
)
6181 interrupt_input_pending
= 1;
6185 interrupt_input_pending
= 0;
6188 /* So people can tell when we have read the available input. */
6189 input_signal_count
++;
6192 abort (); /* Don't think this happens. */
6194 /* TODO: tool-bars, ghostscript integration, mouse
6196 while (get_next_msg (&msg
, FALSE
))
6198 switch (msg
.msg
.message
)
6201 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6205 if (msg
.rect
.right
== msg
.rect
.left
||
6206 msg
.rect
.bottom
== msg
.rect
.top
)
6208 /* We may get paint messages even though the client
6209 area is clipped - these are not expose events. */
6210 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f
,
6213 else if (f
->async_visible
!= 1)
6215 /* Definitely not obscured, so mark as visible. */
6216 f
->async_visible
= 1;
6217 f
->async_iconified
= 0;
6218 SET_FRAME_GARBAGED (f
);
6219 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f
,
6222 /* WM_PAINT serves as MapNotify as well, so report
6223 visibility changes properly. */
6226 bufp
->kind
= DEICONIFY_EVENT
;
6227 XSETFRAME (bufp
->frame_or_window
, f
);
6233 else if (! NILP (Vframe_list
)
6234 && ! NILP (XCDR (Vframe_list
)))
6235 /* Force a redisplay sooner or later to update the
6236 frame titles in case this is the second frame. */
6237 record_asynch_buffer_change ();
6241 HDC hdc
= get_frame_dc (f
);
6243 /* Erase background again for safety. */
6244 w32_clear_rect (f
, hdc
, &msg
.rect
);
6245 release_frame_dc (f
, hdc
);
6249 msg
.rect
.right
- msg
.rect
.left
,
6250 msg
.rect
.bottom
- msg
.rect
.top
);
6255 case WM_INPUTLANGCHANGE
:
6256 /* Generate a language change event. */
6257 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6264 bufp
->kind
= LANGUAGE_CHANGE_EVENT
;
6265 XSETFRAME (bufp
->frame_or_window
, f
);
6267 bufp
->code
= msg
.msg
.wParam
;
6268 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
6277 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6279 if (f
&& !f
->iconified
)
6281 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6283 dpyinfo
->mouse_face_hidden
= 1;
6284 clear_mouse_face (dpyinfo
);
6287 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
6289 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
6290 bufp
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
6291 bufp
->code
= msg
.msg
.wParam
;
6292 bufp
->modifiers
= msg
.dwModifiers
;
6293 XSETFRAME (bufp
->frame_or_window
, f
);
6295 bufp
->timestamp
= msg
.msg
.time
;
6304 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6306 if (f
&& !f
->iconified
)
6308 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
6310 dpyinfo
->mouse_face_hidden
= 1;
6311 clear_mouse_face (dpyinfo
);
6314 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
6316 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
6317 bufp
->kind
= ASCII_KEYSTROKE_EVENT
;
6318 bufp
->code
= msg
.msg
.wParam
;
6319 bufp
->modifiers
= msg
.dwModifiers
;
6320 XSETFRAME (bufp
->frame_or_window
, f
);
6322 bufp
->timestamp
= msg
.msg
.time
;
6330 /* Ignore non-movement. */
6332 int x
= LOWORD (msg
.msg
.lParam
);
6333 int y
= HIWORD (msg
.msg
.lParam
);
6334 if (x
== last_mousemove_x
&& y
== last_mousemove_y
)
6336 last_mousemove_x
= x
;
6337 last_mousemove_y
= y
;
6340 previous_help_echo
= help_echo
;
6342 if (dpyinfo
->grabbed
&& last_mouse_frame
6343 && FRAME_LIVE_P (last_mouse_frame
))
6344 f
= last_mouse_frame
;
6346 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6348 if (dpyinfo
->mouse_face_hidden
)
6350 dpyinfo
->mouse_face_hidden
= 0;
6351 clear_mouse_face (dpyinfo
);
6356 /* Generate SELECT_WINDOW_EVENTs when needed. */
6357 if (mouse_autoselect_window
)
6361 int x
= LOWORD (msg
.msg
.lParam
);
6362 int y
= HIWORD (msg
.msg
.lParam
);
6364 window
= window_from_coordinates (f
,
6368 /* Window will be selected only when it is not
6369 selected now and last mouse movement event was
6370 not in it. Minibuffer window will be selected
6371 iff it is active. */
6373 && !EQ (window
, last_window
)
6374 && !EQ (window
, selected_window
)
6377 bufp
->kind
= SELECT_WINDOW_EVENT
;
6378 bufp
->frame_or_window
= window
;
6380 ++bufp
, ++count
, --numchars
;
6385 note_mouse_movement (f
, &msg
.msg
);
6389 /* If we move outside the frame, then we're
6390 certainly no longer on any text in the frame. */
6391 clear_mouse_face (dpyinfo
);
6394 /* If the contents of the global variable help_echo
6395 has changed, generate a HELP_EVENT. */
6396 if (help_echo
!= previous_help_echo
||
6397 (!NILP (help_echo
) && !STRINGP (help_echo
) && f
->mouse_moved
))
6402 if (help_echo
== Qnil
)
6404 help_echo_object
= help_echo_window
= Qnil
;
6409 XSETFRAME (frame
, f
);
6413 any_help_event_p
= 1;
6414 n
= gen_help_event (bufp
, numchars
, help_echo
, frame
,
6415 help_echo_window
, help_echo_object
,
6417 bufp
+= n
, count
+= n
, numchars
-= n
;
6421 case WM_LBUTTONDOWN
:
6423 case WM_MBUTTONDOWN
:
6425 case WM_RBUTTONDOWN
:
6427 case WM_XBUTTONDOWN
:
6430 /* If we decide we want to generate an event to be seen
6431 by the rest of Emacs, we put it here. */
6432 struct input_event emacs_event
;
6437 emacs_event
.kind
= NO_EVENT
;
6439 if (dpyinfo
->grabbed
&& last_mouse_frame
6440 && FRAME_LIVE_P (last_mouse_frame
))
6441 f
= last_mouse_frame
;
6443 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6447 construct_mouse_click (&emacs_event
, &msg
, f
);
6449 /* Is this in the tool-bar? */
6450 if (WINDOWP (f
->tool_bar_window
)
6451 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
6456 x
= XFASTINT (emacs_event
.x
);
6457 y
= XFASTINT (emacs_event
.y
);
6460 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
6462 if (EQ (window
, f
->tool_bar_window
))
6464 w32_handle_tool_bar_click (f
, &emacs_event
);
6470 if (!dpyinfo
->w32_focus_frame
6471 || f
== dpyinfo
->w32_focus_frame
6474 construct_mouse_click (bufp
, &msg
, f
);
6481 parse_button (msg
.msg
.message
, HIWORD (msg
.msg
.wParam
),
6486 dpyinfo
->grabbed
&= ~ (1 << button
);
6490 dpyinfo
->grabbed
|= (1 << button
);
6491 last_mouse_frame
= f
;
6492 /* Ignore any mouse motion that happened
6493 before this event; any subsequent mouse-movement
6494 Emacs events should reflect only motion after
6500 last_tool_bar_item
= -1;
6506 if (dpyinfo
->grabbed
&& last_mouse_frame
6507 && FRAME_LIVE_P (last_mouse_frame
))
6508 f
= last_mouse_frame
;
6510 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6514 if ((!dpyinfo
->w32_focus_frame
6515 || f
== dpyinfo
->w32_focus_frame
)
6518 construct_mouse_wheel (bufp
, &msg
, f
);
6527 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6531 construct_drag_n_drop (bufp
, &msg
, f
);
6540 struct scroll_bar
*bar
=
6541 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
6543 if (bar
&& numchars
>= 1)
6545 if (w32_scroll_bar_handle_click (bar
, &msg
, bufp
))
6555 case WM_WINDOWPOSCHANGED
:
6556 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6559 x_check_fullscreen_move(f
);
6560 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_WAIT
)
6561 f
->output_data
.w32
->want_fullscreen
&=
6562 ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
6564 check_visibility
= 1;
6568 case WM_ACTIVATEAPP
:
6569 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6571 x_check_fullscreen (f
);
6572 check_visibility
= 1;
6576 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6578 if (f
&& !f
->async_iconified
)
6582 x_real_positions (f
, &x
, &y
);
6583 f
->output_data
.w32
->left_pos
= x
;
6584 f
->output_data
.w32
->top_pos
= y
;
6587 check_visibility
= 1;
6591 /* wParam non-zero means Window is about to be shown, 0 means
6592 about to be hidden. */
6593 /* Redo the mouse-highlight after the tooltip has gone. */
6594 if (!msg
.msg
.wParam
&& msg
.msg
.hwnd
== tip_window
)
6597 redo_mouse_highlight ();
6600 /* If window has been obscured or exposed by another window
6601 being maximised or minimised/restored, then recheck
6602 visibility of all frames. Direct changes to our own
6603 windows get handled by WM_SIZE. */
6605 if (msg
.msg
.lParam
!= 0)
6606 check_visibility
= 1;
6609 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6610 f
->async_visible
= msg
.msg
.wParam
;
6614 check_visibility
= 1;
6618 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6620 /* Inform lisp of whether frame has been iconified etc. */
6623 switch (msg
.msg
.wParam
)
6625 case SIZE_MINIMIZED
:
6626 f
->async_visible
= 0;
6627 f
->async_iconified
= 1;
6629 bufp
->kind
= ICONIFY_EVENT
;
6630 XSETFRAME (bufp
->frame_or_window
, f
);
6637 case SIZE_MAXIMIZED
:
6639 f
->async_visible
= 1;
6640 f
->async_iconified
= 0;
6642 /* wait_reading_process_input will notice this and update
6643 the frame's display structures. */
6644 SET_FRAME_GARBAGED (f
);
6650 /* Reset top and left positions of the Window
6651 here since Windows sends a WM_MOVE message
6652 BEFORE telling us the Window is minimized
6653 when the Window is iconified, with 3000,3000
6655 x_real_positions (f
, &x
, &y
);
6656 f
->output_data
.w32
->left_pos
= x
;
6657 f
->output_data
.w32
->top_pos
= y
;
6659 bufp
->kind
= DEICONIFY_EVENT
;
6660 XSETFRAME (bufp
->frame_or_window
, f
);
6666 else if (! NILP (Vframe_list
)
6667 && ! NILP (XCDR (Vframe_list
)))
6668 /* Force a redisplay sooner or later
6669 to update the frame titles
6670 in case this is the second frame. */
6671 record_asynch_buffer_change ();
6676 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
6684 GetClientRect (msg
.msg
.hwnd
, &rect
);
6686 height
= rect
.bottom
- rect
.top
;
6687 width
= rect
.right
- rect
.left
;
6689 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
6690 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
6692 /* TODO: Clip size to the screen dimensions. */
6694 /* Even if the number of character rows and columns has
6695 not changed, the font size may have changed, so we need
6696 to check the pixel dimensions as well. */
6698 if (columns
!= f
->width
6699 || rows
!= f
->height
6700 || width
!= f
->output_data
.w32
->pixel_width
6701 || height
!= f
->output_data
.w32
->pixel_height
)
6703 change_frame_size (f
, rows
, columns
, 0, 1, 0);
6704 SET_FRAME_GARBAGED (f
);
6705 cancel_mouse_face (f
);
6706 f
->output_data
.w32
->pixel_width
= width
;
6707 f
->output_data
.w32
->pixel_height
= height
;
6708 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
6712 check_visibility
= 1;
6716 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6719 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6721 /* If we move outside the frame, then we're
6722 certainly no longer on any text in the frame. */
6723 clear_mouse_face (dpyinfo
);
6724 dpyinfo
->mouse_face_mouse_frame
= 0;
6727 /* Generate a nil HELP_EVENT to cancel a help-echo.
6728 Do it only if there's something to cancel.
6729 Otherwise, the startup message is cleared when
6730 the mouse leaves the frame. */
6731 if (any_help_event_p
)
6736 XSETFRAME (frame
, f
);
6738 n
= gen_help_event (bufp
, numchars
,
6739 Qnil
, frame
, Qnil
, Qnil
, 0);
6740 bufp
+= n
, count
+= n
, numchars
-= n
;
6746 /* TODO: Port this change:
6747 2002-06-28 Jan D. <jan.h.d@swipnet.se>
6748 * xterm.h (struct x_output): Add focus_state.
6749 * xterm.c (x_focus_changed): New function.
6750 (x_detect_focus_change): New function.
6751 (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
6752 EnterNotify and LeaveNotify to track X focus changes.
6754 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6756 dpyinfo
->w32_focus_event_frame
= f
;
6759 x_new_focus_frame (dpyinfo
, f
);
6762 dpyinfo
->grabbed
= 0;
6763 check_visibility
= 1;
6767 /* TODO: some of this belongs in MOUSE_LEAVE */
6768 f
= x_top_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6772 if (f
== dpyinfo
->w32_focus_event_frame
)
6773 dpyinfo
->w32_focus_event_frame
= 0;
6775 if (f
== dpyinfo
->w32_focus_frame
)
6776 x_new_focus_frame (dpyinfo
, 0);
6778 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6780 /* If we move outside the frame, then we're
6781 certainly no longer on any text in the frame. */
6782 clear_mouse_face (dpyinfo
);
6783 dpyinfo
->mouse_face_mouse_frame
= 0;
6786 /* Generate a nil HELP_EVENT to cancel a help-echo.
6787 Do it only if there's something to cancel.
6788 Otherwise, the startup message is cleared when
6789 the mouse leaves the frame. */
6790 if (any_help_event_p
)
6795 XSETFRAME (frame
, f
);
6797 n
= gen_help_event (bufp
, numchars
,
6798 Qnil
, frame
, Qnil
, Qnil
, 0);
6799 bufp
+= n
, count
+= n
, numchars
-=n
;
6803 dpyinfo
->grabbed
= 0;
6804 check_visibility
= 1;
6808 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6815 bufp
->kind
= DELETE_WINDOW_EVENT
;
6816 XSETFRAME (bufp
->frame_or_window
, f
);
6825 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6832 bufp
->kind
= MENU_BAR_ACTIVATE_EVENT
;
6833 XSETFRAME (bufp
->frame_or_window
, f
);
6842 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6846 extern void menubar_selection_callback
6847 (FRAME_PTR f
, void * client_data
);
6848 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
6851 check_visibility
= 1;
6854 case WM_DISPLAYCHANGE
:
6855 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6859 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
6860 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
6861 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
6862 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
6866 check_visibility
= 1;
6870 /* Check for messages registered at runtime. */
6871 if (msg
.msg
.message
== msh_mousewheel
)
6873 if (dpyinfo
->grabbed
&& last_mouse_frame
6874 && FRAME_LIVE_P (last_mouse_frame
))
6875 f
= last_mouse_frame
;
6877 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
6881 if ((!dpyinfo
->w32_focus_frame
6882 || f
== dpyinfo
->w32_focus_frame
)
6885 construct_mouse_wheel (bufp
, &msg
, f
);
6896 /* If the focus was just given to an autoraising frame,
6898 /* ??? This ought to be able to handle more than one such frame. */
6899 if (pending_autoraise_frame
)
6901 x_raise_frame (pending_autoraise_frame
);
6902 pending_autoraise_frame
= 0;
6905 /* Check which frames are still visisble, if we have enqueued any user
6906 events or been notified of events that may affect visibility. We
6907 do this here because there doesn't seem to be any direct
6908 notification from Windows that the visibility of a window has
6909 changed (at least, not in all cases). */
6910 if (count
> 0 || check_visibility
)
6912 Lisp_Object tail
, frame
;
6914 FOR_EACH_FRAME (tail
, frame
)
6916 FRAME_PTR f
= XFRAME (frame
);
6917 /* The tooltip has been drawn already. Avoid the
6918 SET_FRAME_GARBAGED below. */
6919 if (EQ (frame
, tip_frame
))
6922 /* Check "visible" frames and mark each as obscured or not.
6923 Note that async_visible is nonzero for unobscured and
6924 obscured frames, but zero for hidden and iconified frames. */
6925 if (FRAME_W32_P (f
) && f
->async_visible
)
6931 /* Query clipping rectangle for the entire window area
6932 (GetWindowDC), not just the client portion (GetDC).
6933 Otherwise, the scrollbars and menubar aren't counted as
6934 part of the visible area of the frame, and we may think
6935 the frame is obscured when really a scrollbar is still
6936 visible and gets WM_PAINT messages above. */
6937 hdc
= GetWindowDC (FRAME_W32_WINDOW (f
));
6938 GetClipBox (hdc
, &clipbox
);
6939 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
6942 if (clipbox
.right
== clipbox
.left
6943 || clipbox
.bottom
== clipbox
.top
)
6945 /* Frame has become completely obscured so mark as
6946 such (we do this by setting async_visible to 2 so
6947 that FRAME_VISIBLE_P is still true, but redisplay
6949 f
->async_visible
= 2;
6951 if (!FRAME_OBSCURED_P (f
))
6953 DebPrint (("frame %p (%s) obscured\n", f
,
6959 /* Frame is not obscured, so mark it as such. */
6960 f
->async_visible
= 1;
6962 if (FRAME_OBSCURED_P (f
))
6964 SET_FRAME_GARBAGED (f
);
6965 DebPrint (("obscured frame %p (%s) found to be visible\n", f
,
6968 /* Force a redisplay sooner or later. */
6969 record_asynch_buffer_change ();
6983 /***********************************************************************
6985 ***********************************************************************/
6987 /* Set clipping for output in glyph row ROW. W is the window in which
6988 we operate. GC is the graphics context to set clipping in.
6989 WHOLE_LINE_P non-zero means include the areas used for truncation
6990 mark display and alike in the clipping rectangle.
6992 ROW may be a text row or, e.g., a mode line. Text rows must be
6993 clipped to the interior of the window dedicated to text display,
6994 mode lines must be clipped to the whole window. */
6997 w32_clip_to_row (w
, row
, hdc
, whole_line_p
)
6999 struct glyph_row
*row
;
7003 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7005 int window_x
, window_y
, window_width
, window_height
;
7007 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
7009 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
7010 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
7011 clip_rect
.top
= max (clip_rect
.top
, window_y
);
7012 clip_rect
.right
= clip_rect
.left
+ window_width
;
7013 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
7015 /* If clipping to the whole line, including trunc marks, extend
7016 the rectangle to the left and increase its width. */
7019 clip_rect
.left
-= FRAME_X_LEFT_FRINGE_WIDTH (f
);
7020 clip_rect
.right
+= FRAME_X_FRINGE_WIDTH (f
);
7023 w32_set_clip_rectangle (hdc
, &clip_rect
);
7027 /* Draw a hollow box cursor on window W in glyph row ROW. */
7030 x_draw_hollow_cursor (w
, row
)
7032 struct glyph_row
*row
;
7034 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
7038 struct glyph
*cursor_glyph
;
7039 HBRUSH hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
7041 /* Compute frame-relative coordinates from window-relative
7043 rect
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7044 rect
.top
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
7045 + row
->ascent
- w
->phys_cursor_ascent
);
7046 rect
.bottom
= rect
.top
+ row
->height
;
7048 /* Get the glyph the cursor is on. If we can't tell because
7049 the current matrix is invalid or such, give up. */
7050 cursor_glyph
= get_phys_cursor_glyph (w
);
7051 if (cursor_glyph
== NULL
)
7054 /* Compute the width of the rectangle to draw. If on a stretch
7055 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7056 rectangle as wide as the glyph, but use a canonical character
7058 wd
= cursor_glyph
->pixel_width
;
7059 if (cursor_glyph
->type
== STRETCH_GLYPH
7060 && !x_stretch_cursor_p
)
7061 wd
= min (CANON_X_UNIT (f
), wd
);
7062 w
->phys_cursor_width
= wd
;
7064 rect
.right
= rect
.left
+ wd
;
7065 hdc
= get_frame_dc (f
);
7066 /* Set clipping, draw the rectangle, and reset clipping again. */
7067 w32_clip_to_row (w
, row
, hdc
, 0);
7068 FrameRect (hdc
, &rect
, hb
);
7070 w32_set_clip_rectangle (hdc
, NULL
);
7071 release_frame_dc (f
, hdc
);
7075 /* Draw a bar cursor on window W in glyph row ROW.
7077 Implementation note: One would like to draw a bar cursor with an
7078 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7079 Unfortunately, I didn't find a font yet that has this property set.
7083 x_draw_bar_cursor (w
, row
, width
, kind
)
7085 struct glyph_row
*row
;
7087 enum text_cursor_kinds kind
;
7089 struct frame
*f
= XFRAME (w
->frame
);
7090 struct glyph
*cursor_glyph
;
7094 /* If cursor is out of bounds, don't draw garbage. This can happen
7095 in mini-buffer windows when switching between echo area glyphs
7097 cursor_glyph
= get_phys_cursor_glyph (w
);
7098 if (cursor_glyph
== NULL
)
7101 /* If on an image, draw like a normal cursor. That's usually better
7102 visible than drawing a bar, esp. if the image is large so that
7103 the bar might not be in the window. */
7104 if (cursor_glyph
->type
== IMAGE_GLYPH
)
7106 struct glyph_row
*row
;
7107 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
7108 x_draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
7112 COLORREF cursor_color
= f
->output_data
.w32
->cursor_pixel
;
7113 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
7115 /* If the glyph's background equals the color we normally draw
7116 the bar cursor in, the bar cursor in its normal color is
7117 invisible. Use the glyph's foreground color instead in this
7118 case, on the assumption that the glyph's colors are chosen so
7119 that the glyph is legible. */
7120 if (face
->background
== cursor_color
)
7121 cursor_color
= face
->foreground
;
7123 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7126 width
= FRAME_CURSOR_WIDTH (f
);
7127 width
= min (cursor_glyph
->pixel_width
, width
);
7129 w
->phys_cursor_width
= width
;
7132 hdc
= get_frame_dc (f
);
7133 w32_clip_to_row (w
, row
, hdc
, 0);
7135 if (kind
== BAR_CURSOR
)
7137 w32_fill_area (f
, hdc
, cursor_color
, x
,
7138 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
7139 width
, row
->height
);
7143 w32_fill_area (f
, hdc
, cursor_color
, x
,
7144 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
7145 row
->height
- width
),
7146 cursor_glyph
->pixel_width
, width
);
7149 w32_set_clip_rectangle (hdc
, NULL
);
7150 release_frame_dc (f
, hdc
);
7155 /* Clear the cursor of window W to background color, and mark the
7156 cursor as not shown. This is used when the text where the cursor
7157 is is about to be rewritten. */
7163 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
7164 x_update_window_cursor (w
, 0);
7168 /* Draw the cursor glyph of window W in glyph row ROW. See the
7169 comment of x_draw_glyphs for the meaning of HL. */
7172 x_draw_phys_cursor_glyph (w
, row
, hl
)
7174 struct glyph_row
*row
;
7175 enum draw_glyphs_face hl
;
7177 /* If cursor hpos is out of bounds, don't draw garbage. This can
7178 happen in mini-buffer windows when switching between echo area
7179 glyphs and mini-buffer. */
7180 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
7182 int on_p
= w
->phys_cursor_on_p
;
7184 x1
= x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
7185 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
7187 w
->phys_cursor_on_p
= on_p
;
7189 if (hl
== DRAW_CURSOR
)
7190 w
->phys_cursor_width
= x1
- w
->phys_cursor
.x
;
7192 /* When we erase the cursor, and ROW is overlapped by other
7193 rows, make sure that these overlapping parts of other rows
7195 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
7197 if (row
> w
->current_matrix
->rows
7198 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
7199 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
7201 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
7202 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
7203 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
7209 /* Erase the image of a cursor of window W from the screen. */
7212 x_erase_phys_cursor (w
)
7215 struct frame
*f
= XFRAME (w
->frame
);
7216 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
7217 int hpos
= w
->phys_cursor
.hpos
;
7218 int vpos
= w
->phys_cursor
.vpos
;
7219 int mouse_face_here_p
= 0;
7220 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
7221 struct glyph_row
*cursor_row
;
7222 struct glyph
*cursor_glyph
;
7223 enum draw_glyphs_face hl
;
7225 /* No cursor displayed or row invalidated => nothing to do on the
7227 if (w
->phys_cursor_type
== NO_CURSOR
)
7228 goto mark_cursor_off
;
7230 /* VPOS >= active_glyphs->nrows means that window has been resized.
7231 Don't bother to erase the cursor. */
7232 if (vpos
>= active_glyphs
->nrows
)
7233 goto mark_cursor_off
;
7235 /* If row containing cursor is marked invalid, there is nothing we
7237 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
7238 if (!cursor_row
->enabled_p
)
7239 goto mark_cursor_off
;
7241 /* If row is completely invisible, don't attempt to delete a cursor which
7242 isn't there. This may happen if cursor is at top of window, and
7243 we switch to a buffer with a header line in that window. */
7244 if (cursor_row
->visible_height
<= 0)
7245 goto mark_cursor_off
;
7247 /* This can happen when the new row is shorter than the old one.
7248 In this case, either x_draw_glyphs or clear_end_of_line
7249 should have cleared the cursor. Note that we wouldn't be
7250 able to erase the cursor in this case because we don't have a
7251 cursor glyph at hand. */
7252 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
7253 goto mark_cursor_off
;
7255 /* If the cursor is in the mouse face area, redisplay that when
7256 we clear the cursor. */
7257 if (! NILP (dpyinfo
->mouse_face_window
)
7258 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
7259 && (vpos
> dpyinfo
->mouse_face_beg_row
7260 || (vpos
== dpyinfo
->mouse_face_beg_row
7261 && hpos
>= dpyinfo
->mouse_face_beg_col
))
7262 && (vpos
< dpyinfo
->mouse_face_end_row
7263 || (vpos
== dpyinfo
->mouse_face_end_row
7264 && hpos
< dpyinfo
->mouse_face_end_col
))
7265 /* Don't redraw the cursor's spot in mouse face if it is at the
7266 end of a line (on a newline). The cursor appears there, but
7267 mouse highlighting does not. */
7268 && cursor_row
->used
[TEXT_AREA
] > hpos
)
7269 mouse_face_here_p
= 1;
7271 /* Maybe clear the display under the cursor. */
7272 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
7275 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
7278 cursor_glyph
= get_phys_cursor_glyph (w
);
7279 if (cursor_glyph
== NULL
)
7280 goto mark_cursor_off
;
7282 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7284 hdc
= get_frame_dc (f
);
7285 w32_clear_area (f
, hdc
, x
,
7286 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
7288 cursor_glyph
->pixel_width
,
7289 cursor_row
->visible_height
);
7290 release_frame_dc (f
, hdc
);
7293 /* Erase the cursor by redrawing the character underneath it. */
7294 if (mouse_face_here_p
)
7295 hl
= DRAW_MOUSE_FACE
;
7297 hl
= DRAW_NORMAL_TEXT
;
7298 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
7301 w
->phys_cursor_on_p
= 0;
7302 w
->phys_cursor_type
= NO_CURSOR
;
7306 /* Non-zero if physical cursor of window W is within mouse face. */
7309 cursor_in_mouse_face_p (w
)
7312 struct w32_display_info
*dpyinfo
7313 = FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
7314 int in_mouse_face
= 0;
7316 if (WINDOWP (dpyinfo
->mouse_face_window
)
7317 && XWINDOW (dpyinfo
->mouse_face_window
) == w
)
7319 int hpos
= w
->phys_cursor
.hpos
;
7320 int vpos
= w
->phys_cursor
.vpos
;
7322 if (vpos
>= dpyinfo
->mouse_face_beg_row
7323 && vpos
<= dpyinfo
->mouse_face_end_row
7324 && (vpos
> dpyinfo
->mouse_face_beg_row
7325 || hpos
>= dpyinfo
->mouse_face_beg_col
)
7326 && (vpos
< dpyinfo
->mouse_face_end_row
7327 || hpos
< dpyinfo
->mouse_face_end_col
7328 || dpyinfo
->mouse_face_past_end
))
7332 return in_mouse_face
;
7336 /* Display or clear cursor of window W. If ON is zero, clear the
7337 cursor. If it is non-zero, display the cursor. If ON is nonzero,
7338 where to put the cursor is specified by HPOS, VPOS, X and Y. */
7341 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
7343 int on
, hpos
, vpos
, x
, y
;
7345 struct frame
*f
= XFRAME (w
->frame
);
7346 int new_cursor_type
;
7347 int new_cursor_width
;
7349 struct glyph_matrix
*current_glyphs
;
7350 struct glyph_row
*glyph_row
;
7351 struct glyph
*glyph
;
7353 /* This is pointless on invisible frames, and dangerous on garbaged
7354 windows and frames; in the latter case, the frame or window may
7355 be in the midst of changing its size, and x and y may be off the
7357 if (! FRAME_VISIBLE_P (f
)
7358 || FRAME_GARBAGED_P (f
)
7359 || vpos
>= w
->current_matrix
->nrows
7360 || hpos
>= w
->current_matrix
->matrix_w
)
7363 /* If cursor is off and we want it off, return quickly. */
7364 if (!on
&& !w
->phys_cursor_on_p
)
7367 current_glyphs
= w
->current_matrix
;
7368 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
7369 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
7371 /* If cursor row is not enabled, we don't really know where to
7372 display the cursor. */
7373 if (!glyph_row
->enabled_p
)
7375 w
->phys_cursor_on_p
= 0;
7379 xassert (interrupt_input_blocked
);
7381 /* Set new_cursor_type to the cursor we want to be displayed. */
7382 new_cursor_type
= get_window_cursor_type (w
, &new_cursor_width
, &active_cursor
);
7384 /* If cursor is currently being shown and we don't want it to be or
7385 it is in the wrong place, or the cursor type is not what we want,
7387 if (w
->phys_cursor_on_p
7389 || w
->phys_cursor
.x
!= x
7390 || w
->phys_cursor
.y
!= y
7391 || new_cursor_type
!= w
->phys_cursor_type
7392 || ((new_cursor_type
== BAR_CURSOR
|| new_cursor_type
== HBAR_CURSOR
)
7393 && new_cursor_width
!= w
->phys_cursor_width
)))
7394 x_erase_phys_cursor (w
);
7396 /* Don't check phys_cursor_on_p here because that flag is only set
7397 to zero in some cases where we know that the cursor has been
7398 completely erased, to avoid the extra work of erasing the cursor
7399 twice. In other words, phys_cursor_on_p can be 1 and the cursor
7400 still not be visible, or it has only been partly erased. */
7403 w
->phys_cursor_ascent
= glyph_row
->ascent
;
7404 w
->phys_cursor_height
= glyph_row
->height
;
7406 /* Set phys_cursor_.* before x_draw_.* is called because some
7407 of them may need the information. */
7408 w
->phys_cursor
.x
= x
;
7409 w
->phys_cursor
.y
= glyph_row
->y
;
7410 w
->phys_cursor
.hpos
= hpos
;
7411 w
->phys_cursor
.vpos
= vpos
;
7413 /* If the user wants to use the system caret, make sure our own
7414 cursor remains invisible. */
7415 if (w32_use_visible_system_caret
)
7417 if (w
->phys_cursor_type
!= NO_CURSOR
)
7418 x_erase_phys_cursor (w
);
7420 new_cursor_type
= w
->phys_cursor_type
= NO_CURSOR
;
7421 w
->phys_cursor_width
= -1;
7425 w
->phys_cursor_type
= new_cursor_type
;
7428 w
->phys_cursor_on_p
= 1;
7430 /* If this is the active cursor, we need to track it with the
7431 system caret, so third party software like screen magnifiers
7432 and speech synthesizers can follow the cursor. */
7435 HWND hwnd
= FRAME_W32_WINDOW (f
);
7438 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
7440 = (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
7441 + glyph_row
->ascent
- w
->phys_cursor_ascent
);
7443 /* If the size of the active cursor changed, destroy the old
7445 if (w32_system_caret_hwnd
7446 && (w32_system_caret_height
!= w
->phys_cursor_height
))
7447 PostMessage (hwnd
, WM_EMACS_DESTROY_CARET
, 0, 0);
7449 w32_system_caret_height
= w
->phys_cursor_height
;
7451 /* Move the system caret. */
7452 PostMessage (hwnd
, WM_EMACS_TRACK_CARET
, 0, 0);
7455 switch (new_cursor_type
)
7457 case HOLLOW_BOX_CURSOR
:
7458 x_draw_hollow_cursor (w
, glyph_row
);
7461 case FILLED_BOX_CURSOR
:
7462 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
7466 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
, BAR_CURSOR
);
7470 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
, HBAR_CURSOR
);
7474 w
->phys_cursor_width
= 0;
7484 /* Display the cursor on window W, or clear it. X and Y are window
7485 relative pixel coordinates. HPOS and VPOS are glyph matrix
7486 positions. If W is not the selected window, display a hollow
7487 cursor. ON non-zero means display the cursor at X, Y which
7488 correspond to HPOS, VPOS, otherwise it is cleared. */
7491 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
7493 int on
, hpos
, vpos
, x
, y
;
7496 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
7501 /* Display the cursor on window W, or clear it, according to ON_P.
7502 Don't change the cursor's position. */
7505 x_update_cursor (f
, on_p
)
7509 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
7513 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
7514 in the window tree rooted at W. */
7517 x_update_cursor_in_window_tree (w
, on_p
)
7523 if (!NILP (w
->hchild
))
7524 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
7525 else if (!NILP (w
->vchild
))
7526 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
7528 x_update_window_cursor (w
, on_p
);
7530 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
7535 /* Switch the display of W's cursor on or off, according to the value
7539 x_update_window_cursor (w
, on
)
7543 /* Don't update cursor in windows whose frame is in the process
7544 of being deleted. */
7545 if (w
->current_matrix
)
7548 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
,
7549 w
->phys_cursor
.vpos
, w
->phys_cursor
.x
,
7561 x_bitmap_icon (f
, icon
)
7567 if (FRAME_W32_WINDOW (f
) == 0)
7571 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
7572 else if (STRINGP (icon
))
7573 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
7574 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
7575 else if (SYMBOLP (icon
))
7579 if (EQ (icon
, intern ("application")))
7580 name
= (LPCTSTR
) IDI_APPLICATION
;
7581 else if (EQ (icon
, intern ("hand")))
7582 name
= (LPCTSTR
) IDI_HAND
;
7583 else if (EQ (icon
, intern ("question")))
7584 name
= (LPCTSTR
) IDI_QUESTION
;
7585 else if (EQ (icon
, intern ("exclamation")))
7586 name
= (LPCTSTR
) IDI_EXCLAMATION
;
7587 else if (EQ (icon
, intern ("asterisk")))
7588 name
= (LPCTSTR
) IDI_ASTERISK
;
7589 else if (EQ (icon
, intern ("winlogo")))
7590 name
= (LPCTSTR
) IDI_WINLOGO
;
7594 hicon
= LoadIcon (NULL
, name
);
7602 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
7609 /************************************************************************
7611 ************************************************************************/
7613 /* Display Error Handling functions not used on W32. Listing them here
7614 helps diff stay in step when comparing w32term.c with xterm.c.
7616 x_error_catcher (display, error)
7617 x_catch_errors (dpy)
7618 x_catch_errors_unwind (old_val)
7619 x_check_errors (dpy, format)
7620 x_had_errors_p (dpy)
7621 x_clear_errors (dpy)
7622 x_uncatch_errors (dpy, count)
7624 x_connection_signal (signalnum)
7625 x_connection_closed (dpy, error_message)
7626 x_error_quitter (display, error)
7627 x_error_handler (display, error)
7628 x_io_error_quitter (display)
7633 /* Changing the font of the frame. */
7635 /* Give frame F the font named FONTNAME as its default font, and
7636 return the full name of that font. FONTNAME may be a wildcard
7637 pattern; in that case, we choose some font that fits the pattern.
7638 The return value shows which font we chose. */
7641 x_new_font (f
, fontname
)
7643 register char *fontname
;
7645 struct font_info
*fontp
7646 = FS_LOAD_FONT (f
, 0, fontname
, -1);
7651 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
7652 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
7653 FRAME_FONTSET (f
) = -1;
7655 /* Compute the scroll bar width in character columns. */
7656 if (f
->scroll_bar_pixel_width
> 0)
7658 int wid
= FONT_WIDTH (FRAME_FONT (f
));
7659 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
7663 int wid
= FONT_WIDTH (FRAME_FONT (f
));
7664 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
7667 /* Now make the frame display the given font. */
7668 if (FRAME_W32_WINDOW (f
) != 0)
7670 frame_update_line_height (f
);
7671 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
7672 x_set_window_size (f
, 0, f
->width
, f
->height
);
7675 /* If we are setting a new frame's font for the first time,
7676 there are no faces yet, so this font's height is the line height. */
7677 f
->output_data
.w32
->line_height
= FONT_HEIGHT (FRAME_FONT (f
));
7679 return build_string (fontp
->full_name
);
7682 /* Give frame F the fontset named FONTSETNAME as its default font, and
7683 return the full name of that fontset. FONTSETNAME may be a wildcard
7684 pattern; in that case, we choose some fontset that fits the pattern.
7685 The return value shows which fontset we chose. */
7688 x_new_fontset (f
, fontsetname
)
7692 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
7698 if (FRAME_FONTSET (f
) == fontset
)
7699 /* This fontset is already set in frame F. There's nothing more
7701 return fontset_name (fontset
);
7703 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
7705 if (!STRINGP (result
))
7706 /* Can't load ASCII font. */
7709 /* Since x_new_font doesn't update any fontset information, do it now. */
7710 FRAME_FONTSET(f
) = fontset
;
7712 return build_string (fontsetname
);
7716 /***********************************************************************
7717 TODO: W32 Input Methods
7718 ***********************************************************************/
7719 /* Listing missing functions from xterm.c helps diff stay in step.
7721 xim_destroy_callback (xim, client_data, call_data)
7722 xim_open_dpy (dpyinfo, resource_name)
7724 xim_instantiate_callback (display, client_data, call_data)
7725 xim_initialize (dpyinfo, resource_name)
7726 xim_close_dpy (dpyinfo)
7731 /* Calculate the absolute position in frame F
7732 from its current recorded position values and gravity. */
7735 x_calc_absolute_position (f
)
7739 int flags
= f
->output_data
.w32
->size_hint_flags
;
7743 /* Find the position of the outside upper-left corner of
7744 the inner window, with respect to the outer window.
7745 But do this only if we will need the results. */
7746 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
7749 MapWindowPoints (FRAME_W32_WINDOW (f
),
7750 f
->output_data
.w32
->parent_desc
,
7757 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
7760 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
7761 FRAME_EXTERNAL_MENU_BAR (f
));
7764 pt
.x
+= (rt
.right
- rt
.left
);
7765 pt
.y
+= (rt
.bottom
- rt
.top
);
7768 /* Treat negative positions as relative to the leftmost bottommost
7769 position that fits on the screen. */
7770 if (flags
& XNegative
)
7771 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
7772 - 2 * f
->output_data
.w32
->border_width
- pt
.x
7774 + f
->output_data
.w32
->left_pos
);
7776 if (flags
& YNegative
)
7777 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
7778 - 2 * f
->output_data
.w32
->border_width
- pt
.y
7780 + f
->output_data
.w32
->top_pos
);
7781 /* The left_pos and top_pos
7782 are now relative to the top and left screen edges,
7783 so the flags should correspond. */
7784 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
7787 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
7788 to really change the position, and 0 when calling from
7789 x_make_frame_visible (in that case, XOFF and YOFF are the current
7790 position values). It is -1 when calling from x_set_frame_parameters,
7791 which means, do adjust for borders but don't change the gravity. */
7794 x_set_offset (f
, xoff
, yoff
, change_gravity
)
7796 register int xoff
, yoff
;
7799 int modified_top
, modified_left
;
7801 if (change_gravity
> 0)
7803 f
->output_data
.w32
->top_pos
= yoff
;
7804 f
->output_data
.w32
->left_pos
= xoff
;
7805 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
7807 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
7809 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
7810 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
7812 x_calc_absolute_position (f
);
7815 x_wm_set_size_hint (f
, (long) 0, 0);
7817 modified_left
= f
->output_data
.w32
->left_pos
;
7818 modified_top
= f
->output_data
.w32
->top_pos
;
7820 my_set_window_pos (FRAME_W32_WINDOW (f
),
7822 modified_left
, modified_top
,
7824 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
7829 /* Check if we need to resize the frame due to a fullscreen request.
7830 If so needed, resize the frame. */
7832 x_check_fullscreen (f
)
7835 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_BOTH
)
7837 int width
, height
, ign
;
7839 x_real_positions (f
, &f
->output_data
.w32
->left_pos
,
7840 &f
->output_data
.w32
->top_pos
);
7842 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
7844 /* We do not need to move the window, it shall be taken care of
7845 when setting WM manager hints.
7846 If the frame is visible already, the position is checked by
7847 x_check_fullscreen_move. */
7848 if (f
->width
!= width
|| f
->height
!= height
)
7850 change_frame_size (f
, height
, width
, 0, 1, 0);
7851 SET_FRAME_GARBAGED (f
);
7852 cancel_mouse_face (f
);
7854 /* Wait for the change of frame size to occur */
7855 f
->output_data
.w32
->want_fullscreen
|= FULLSCREEN_WAIT
;
7860 /* If frame parameters are set after the frame is mapped, we need to move
7861 the window. This is done in xfns.c.
7862 Some window managers moves the window to the right position, some
7863 moves the outer window manager window to the specified position.
7864 Here we check that we are in the right spot. If not, make a second
7865 move, assuming we are dealing with the second kind of window manager. */
7867 x_check_fullscreen_move (f
)
7870 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_MOVE_WAIT
)
7872 int expect_top
= f
->output_data
.w32
->top_pos
;
7873 int expect_left
= f
->output_data
.w32
->left_pos
;
7875 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_HEIGHT
)
7877 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_WIDTH
)
7880 if (expect_top
!= f
->output_data
.w32
->top_pos
7881 || expect_left
!= f
->output_data
.w32
->left_pos
)
7882 x_set_offset (f
, expect_left
, expect_top
, 1);
7884 /* Just do this once */
7885 f
->output_data
.w32
->want_fullscreen
&= ~FULLSCREEN_MOVE_WAIT
;
7890 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
7891 wanted positions of the WM window (not emacs window).
7892 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
7893 window (FRAME_X_WINDOW).
7896 x_fullscreen_adjust (f
, width
, height
, top_pos
, left_pos
)
7903 int newwidth
= f
->width
, newheight
= f
->height
;
7905 *top_pos
= f
->output_data
.w32
->top_pos
;
7906 *left_pos
= f
->output_data
.w32
->left_pos
;
7908 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_HEIGHT
)
7912 ph
= FRAME_X_DISPLAY_INFO (f
)->height
;
7913 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
7914 ph
= CHAR_TO_PIXEL_HEIGHT (f
, newheight
)
7915 - f
->output_data
.w32
->y_pixels_diff
;
7916 newheight
= PIXEL_TO_CHAR_HEIGHT (f
, ph
);
7920 if (f
->output_data
.w32
->want_fullscreen
& FULLSCREEN_WIDTH
)
7924 pw
= FRAME_X_DISPLAY_INFO (f
)->width
;
7925 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
7926 pw
= CHAR_TO_PIXEL_WIDTH (f
, newwidth
)
7927 - f
->output_data
.w32
->x_pixels_diff
;
7928 newwidth
= PIXEL_TO_CHAR_WIDTH (f
, pw
);
7933 *height
= newheight
;
7937 /* Call this to change the size of frame F's x-window.
7938 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7939 for this size change and subsequent size changes.
7940 Otherwise we leave the window gravity unchanged. */
7943 x_set_window_size (f
, change_gravity
, cols
, rows
)
7948 int pixelwidth
, pixelheight
;
7952 check_frame_size (f
, &rows
, &cols
);
7953 f
->output_data
.w32
->vertical_scroll_bar_extra
7954 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
7956 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
7958 compute_fringe_widths (f
, 0);
7960 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
7961 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
7963 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
7964 x_wm_set_size_hint (f
, (long) 0, 0);
7969 rect
.left
= rect
.top
= 0;
7970 rect
.right
= pixelwidth
;
7971 rect
.bottom
= pixelheight
;
7973 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
7974 FRAME_EXTERNAL_MENU_BAR (f
));
7976 my_set_window_pos (FRAME_W32_WINDOW (f
),
7979 rect
.right
- rect
.left
,
7980 rect
.bottom
- rect
.top
,
7981 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
7984 /* Now, strictly speaking, we can't be sure that this is accurate,
7985 but the window manager will get around to dealing with the size
7986 change request eventually, and we'll hear how it went when the
7987 ConfigureNotify event gets here.
7989 We could just not bother storing any of this information here,
7990 and let the ConfigureNotify event set everything up, but that
7991 might be kind of confusing to the Lisp code, since size changes
7992 wouldn't be reported in the frame parameters until some random
7993 point in the future when the ConfigureNotify event arrives.
7995 We pass 1 for DELAY since we can't run Lisp code inside of
7997 change_frame_size (f
, rows
, cols
, 0, 1, 0);
7998 PIXEL_WIDTH (f
) = pixelwidth
;
7999 PIXEL_HEIGHT (f
) = pixelheight
;
8001 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8002 receive in the ConfigureNotify event; if we get what we asked
8003 for, then the event won't cause the screen to become garbaged, so
8004 we have to make sure to do it here. */
8005 SET_FRAME_GARBAGED (f
);
8007 /* If cursor was outside the new size, mark it as off. */
8008 mark_window_cursors_off (XWINDOW (f
->root_window
));
8010 /* Clear out any recollection of where the mouse highlighting was,
8011 since it might be in a place that's outside the new frame size.
8012 Actually checking whether it is outside is a pain in the neck,
8013 so don't try--just let the highlighting be done afresh with new size. */
8014 cancel_mouse_face (f
);
8019 /* Mouse warping. */
8021 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
8024 x_set_mouse_position (f
, x
, y
)
8030 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
8031 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
8033 if (pix_x
< 0) pix_x
= 0;
8034 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
8036 if (pix_y
< 0) pix_y
= 0;
8037 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
8039 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
8043 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
8052 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
8053 pt
.x
= rect
.left
+ pix_x
;
8054 pt
.y
= rect
.top
+ pix_y
;
8055 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
8057 SetCursorPos (pt
.x
, pt
.y
);
8063 /* focus shifting, raising and lowering. */
8066 x_focus_on_frame (f
)
8069 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
8071 /* Give input focus to frame. */
8074 /* Try not to change its Z-order if possible. */
8075 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
8076 my_set_focus (f
, FRAME_W32_WINDOW (f
));
8079 my_set_foreground_window (FRAME_W32_WINDOW (f
));
8089 /* Raise frame F. */
8096 /* Strictly speaking, raise-frame should only change the frame's Z
8097 order, leaving input focus unchanged. This is reasonable behaviour
8098 on X where the usual policy is point-to-focus. However, this
8099 behaviour would be very odd on Windows where the usual policy is
8102 On X, if the mouse happens to be over the raised frame, it gets
8103 input focus anyway (so the window with focus will never be
8104 completely obscured) - if not, then just moving the mouse over it
8105 is sufficient to give it focus. On Windows, the user must actually
8106 click on the frame (preferrably the title bar so as not to move
8107 point), which is more awkward. Also, no other Windows program
8108 raises a window to the top but leaves another window (possibly now
8109 completely obscured) with input focus.
8111 Because there is a system setting on Windows that allows the user
8112 to choose the point to focus policy, we make the strict semantics
8113 optional, but by default we grab focus when raising. */
8115 if (NILP (Vw32_grab_focus_on_raise
))
8117 /* The obvious call to my_set_window_pos doesn't work if Emacs is
8118 not already the foreground application: the frame is raised
8119 above all other frames belonging to us, but not above the
8120 current top window. To achieve that, we have to resort to this
8121 more cumbersome method. */
8123 HDWP handle
= BeginDeferWindowPos (2);
8126 DeferWindowPos (handle
,
8127 FRAME_W32_WINDOW (f
),
8130 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
8132 DeferWindowPos (handle
,
8133 GetForegroundWindow (),
8134 FRAME_W32_WINDOW (f
),
8136 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
8138 EndDeferWindowPos (handle
);
8143 my_set_foreground_window (FRAME_W32_WINDOW (f
));
8149 /* Lower frame F. */
8155 my_set_window_pos (FRAME_W32_WINDOW (f
),
8158 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
8163 w32_frame_raise_lower (f
, raise_flag
)
8167 if (! FRAME_W32_P (f
))
8176 /* Change of visibility. */
8178 /* This tries to wait until the frame is really visible.
8179 However, if the window manager asks the user where to position
8180 the frame, this will return before the user finishes doing that.
8181 The frame will not actually be visible at that time,
8182 but it will become visible later when the window manager
8183 finishes with it. */
8186 x_make_frame_visible (f
)
8193 type
= x_icon_type (f
);
8195 x_bitmap_icon (f
, type
);
8197 if (! FRAME_VISIBLE_P (f
))
8199 /* We test FRAME_GARBAGED_P here to make sure we don't
8200 call x_set_offset a second time
8201 if we get to x_make_frame_visible a second time
8202 before the window gets really visible. */
8203 if (! FRAME_ICONIFIED_P (f
)
8204 && ! f
->output_data
.w32
->asked_for_visible
)
8205 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
8207 f
->output_data
.w32
->asked_for_visible
= 1;
8209 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
8210 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
8213 /* Synchronize to ensure Emacs knows the frame is visible
8214 before we do anything else. We do this loop with input not blocked
8215 so that incoming events are handled. */
8220 /* This must come after we set COUNT. */
8223 XSETFRAME (frame
, f
);
8225 /* Wait until the frame is visible. Process X events until a
8226 MapNotify event has been seen, or until we think we won't get a
8227 MapNotify at all.. */
8228 for (count
= input_signal_count
+ 10;
8229 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
8231 /* Force processing of queued events. */
8232 /* TODO: x_sync equivalent? */
8234 /* Machines that do polling rather than SIGIO have been observed
8235 to go into a busy-wait here. So we'll fake an alarm signal
8236 to let the handler know that there's something to be read.
8237 We used to raise a real alarm, but it seems that the handler
8238 isn't always enabled here. This is probably a bug. */
8239 if (input_polling_used ())
8241 /* It could be confusing if a real alarm arrives while processing
8242 the fake one. Turn it off and let the handler reset it. */
8243 int old_poll_suppress_count
= poll_suppress_count
;
8244 poll_suppress_count
= 1;
8245 poll_for_input_1 ();
8246 poll_suppress_count
= old_poll_suppress_count
;
8249 FRAME_SAMPLE_VISIBILITY (f
);
8253 /* Change from mapped state to withdrawn state. */
8255 /* Make the frame visible (mapped and not iconified). */
8257 x_make_frame_invisible (f
)
8260 /* Don't keep the highlight on an invisible frame. */
8261 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8262 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8266 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
8268 /* We can't distinguish this from iconification
8269 just by the event that we get from the server.
8270 So we can't win using the usual strategy of letting
8271 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8272 and synchronize with the server to make sure we agree. */
8274 FRAME_ICONIFIED_P (f
) = 0;
8275 f
->async_visible
= 0;
8276 f
->async_iconified
= 0;
8281 /* Change window state from mapped to iconified. */
8289 /* Don't keep the highlight on an invisible frame. */
8290 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
8291 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
8293 if (f
->async_iconified
)
8298 type
= x_icon_type (f
);
8300 x_bitmap_icon (f
, type
);
8302 /* Simulate the user minimizing the frame. */
8303 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
8309 /* Free X resources of frame F. */
8312 x_free_frame_resources (f
)
8315 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
8319 if (FRAME_W32_WINDOW (f
))
8320 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
8322 free_frame_menubar (f
);
8324 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
8325 unload_color (f
, f
->output_data
.x
->background_pixel
);
8326 unload_color (f
, f
->output_data
.w32
->cursor_pixel
);
8327 unload_color (f
, f
->output_data
.w32
->cursor_foreground_pixel
);
8328 unload_color (f
, f
->output_data
.w32
->border_pixel
);
8329 unload_color (f
, f
->output_data
.w32
->mouse_pixel
);
8330 if (f
->output_data
.w32
->white_relief
.allocated_p
)
8331 unload_color (f
, f
->output_data
.w32
->white_relief
.pixel
);
8332 if (f
->output_data
.w32
->black_relief
.allocated_p
)
8333 unload_color (f
, f
->output_data
.w32
->black_relief
.pixel
);
8335 if (FRAME_FACE_CACHE (f
))
8336 free_frame_faces (f
);
8338 xfree (f
->output_data
.w32
);
8339 f
->output_data
.w32
= NULL
;
8341 if (f
== dpyinfo
->w32_focus_frame
)
8342 dpyinfo
->w32_focus_frame
= 0;
8343 if (f
== dpyinfo
->w32_focus_event_frame
)
8344 dpyinfo
->w32_focus_event_frame
= 0;
8345 if (f
== dpyinfo
->x_highlight_frame
)
8346 dpyinfo
->x_highlight_frame
= 0;
8348 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8350 dpyinfo
->mouse_face_beg_row
8351 = dpyinfo
->mouse_face_beg_col
= -1;
8352 dpyinfo
->mouse_face_end_row
8353 = dpyinfo
->mouse_face_end_col
= -1;
8354 dpyinfo
->mouse_face_window
= Qnil
;
8355 dpyinfo
->mouse_face_deferred_gc
= 0;
8356 dpyinfo
->mouse_face_mouse_frame
= 0;
8363 /* Destroy the window of frame F. */
8365 x_destroy_window (f
)
8368 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
8370 x_free_frame_resources (f
);
8372 dpyinfo
->reference_count
--;
8376 /* Setting window manager hints. */
8378 /* Set the normal size hints for the window manager, for frame F.
8379 FLAGS is the flags word to use--or 0 meaning preserve the flags
8380 that the window now has.
8381 If USER_POSITION is nonzero, we set the USPosition
8382 flag (this is useful when FLAGS is 0). */
8384 x_wm_set_size_hint (f
, flags
, user_position
)
8389 Window window
= FRAME_W32_WINDOW (f
);
8393 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
8394 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
8395 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
8396 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
8401 /* Window manager things */
8402 x_wm_set_icon_position (f
, icon_x
, icon_y
)
8407 Window window
= FRAME_W32_WINDOW (f
);
8409 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
8410 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
8411 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
8413 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
8418 /***********************************************************************
8420 ***********************************************************************/
8422 /* The following functions are listed here to help diff stay in step
8423 with xterm.c. See w32fns.c for definitions.
8425 x_get_font_info (f, font_idx)
8426 x_list_fonts (f, pattern, size, maxnames)
8432 /* Check that FONT is valid on frame F. It is if it can be found in F's
8436 x_check_font (f
, font
)
8441 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
8443 xassert (font
!= NULL
);
8445 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8446 if (dpyinfo
->font_table
[i
].name
8447 && font
== dpyinfo
->font_table
[i
].font
)
8450 xassert (i
< dpyinfo
->n_fonts
);
8453 #endif /* GLYPH_DEBUG != 0 */
8455 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8456 Note: There are (broken) X fonts out there with invalid XFontStruct
8457 min_bounds contents. For example, handa@etl.go.jp reports that
8458 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8459 have font->min_bounds.width == 0. */
8462 x_font_min_bounds (font
, w
, h
)
8467 * TODO: Windows does not appear to offer min bound, only
8468 * average and maximum width, and maximum height.
8470 *h
= FONT_HEIGHT (font
);
8471 *w
= FONT_WIDTH (font
);
8475 /* Compute the smallest character width and smallest font height over
8476 all fonts available on frame F. Set the members smallest_char_width
8477 and smallest_font_height in F's x_display_info structure to
8478 the values computed. Value is non-zero if smallest_font_height or
8479 smallest_char_width become smaller than they were before. */
8482 x_compute_min_glyph_bounds (f
)
8486 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
8488 int old_width
= dpyinfo
->smallest_char_width
;
8489 int old_height
= dpyinfo
->smallest_font_height
;
8491 dpyinfo
->smallest_font_height
= 100000;
8492 dpyinfo
->smallest_char_width
= 100000;
8494 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
8495 if (dpyinfo
->font_table
[i
].name
)
8497 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
8500 font
= (XFontStruct
*) fontp
->font
;
8501 xassert (font
!= (XFontStruct
*) ~0);
8502 x_font_min_bounds (font
, &w
, &h
);
8504 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
8505 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
8508 xassert (dpyinfo
->smallest_char_width
> 0
8509 && dpyinfo
->smallest_font_height
> 0);
8511 return (dpyinfo
->n_fonts
== 1
8512 || dpyinfo
->smallest_char_width
< old_width
8513 || dpyinfo
->smallest_font_height
< old_height
);
8516 /* The following functions are listed here to help diff stay in step
8517 with xterm.c. See w32fns.c for definitions.
8519 x_load_font (f, fontname, size)
8520 x_query_font (f, fontname)
8521 x_find_ccl_program (fontp)
8525 /***********************************************************************
8527 ***********************************************************************/
8529 static int w32_initialized
= 0;
8532 w32_initialize_display_info (display_name
)
8533 Lisp_Object display_name
;
8535 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
8537 bzero (dpyinfo
, sizeof (*dpyinfo
));
8539 /* Put it on w32_display_name_list. */
8540 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
8541 w32_display_name_list
);
8542 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
8544 dpyinfo
->w32_id_name
8545 = (char *) xmalloc (SCHARS (Vinvocation_name
)
8546 + SCHARS (Vsystem_name
)
8548 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
8549 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
8551 /* Default Console mode values - overridden when running in GUI mode
8552 with values obtained from system metrics. */
8555 dpyinfo
->height_in
= 1;
8556 dpyinfo
->width_in
= 1;
8557 dpyinfo
->n_planes
= 1;
8558 dpyinfo
->n_cbits
= 4;
8559 dpyinfo
->n_fonts
= 0;
8560 dpyinfo
->smallest_font_height
= 1;
8561 dpyinfo
->smallest_char_width
= 1;
8563 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8564 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8565 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
8566 dpyinfo
->mouse_face_window
= Qnil
;
8567 dpyinfo
->mouse_face_overlay
= Qnil
;
8568 dpyinfo
->mouse_face_hidden
= 0;
8570 dpyinfo
->vertical_scroll_bar_cursor
= w32_load_cursor (IDC_ARROW
);
8571 /* TODO: dpyinfo->gray */
8575 /* Create an xrdb-style database of resources to supercede registry settings.
8576 The database is just a concatenation of C strings, finished by an additional
8577 \0. The string are submitted to some basic normalization, so
8579 [ *]option[ *]:[ *]value...
8585 but any whitespace following value is not removed. */
8588 w32_make_rdb (xrm_option
)
8591 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
8592 char *current
= buffer
;
8595 int before_value
= 0;
8609 if (in_option
&& (ch
== ':'))
8614 else if (before_value
)
8619 else if (!(in_option
|| before_value
))
8630 struct w32_display_info
*
8631 w32_term_init (display_name
, xrm_option
, resource_name
)
8632 Lisp_Object display_name
;
8634 char *resource_name
;
8636 struct w32_display_info
*dpyinfo
;
8641 if (!w32_initialized
)
8644 w32_initialized
= 1;
8647 w32_initialize_display_info (display_name
);
8649 dpyinfo
= &one_w32_display_info
;
8651 dpyinfo
->xrdb
= xrm_option
? w32_make_rdb (xrm_option
) : NULL
;
8653 /* Put this display on the chain. */
8654 dpyinfo
->next
= x_display_list
;
8655 x_display_list
= dpyinfo
;
8657 hdc
= GetDC (GetDesktopWindow ());
8659 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
8660 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
8661 dpyinfo
->root_window
= GetDesktopWindow ();
8662 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
8663 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
8664 dpyinfo
->resx
= GetDeviceCaps (hdc
, LOGPIXELSX
);
8665 dpyinfo
->resy
= GetDeviceCaps (hdc
, LOGPIXELSY
);
8666 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
8667 dpyinfo
->image_cache
= make_image_cache ();
8668 dpyinfo
->height_in
= dpyinfo
->height
/ dpyinfo
->resx
;
8669 dpyinfo
->width_in
= dpyinfo
->width
/ dpyinfo
->resy
;
8670 ReleaseDC (GetDesktopWindow (), hdc
);
8672 /* initialise palette with white and black */
8675 w32_defined_color (0, "white", &color
, 1);
8676 w32_defined_color (0, "black", &color
, 1);
8679 /* Create Fringe Bitmaps and store them for later use.
8681 On W32, bitmaps are all unsigned short, as Windows requires
8682 bitmap data to be Word aligned. For some reason they are
8683 horizontally reflected compared to how they appear on X, so we
8684 need to bitswap and convert to unsigned shorts before creating
8689 for (i
= NO_FRINGE_BITMAP
+ 1; i
< MAX_FRINGE_BITMAPS
; i
++)
8691 int h
= fringe_bitmaps
[i
].height
;
8692 int wd
= fringe_bitmaps
[i
].width
;
8693 unsigned short *w32bits
8694 = (unsigned short *)alloca (h
* sizeof (unsigned short));
8695 unsigned short *wb
= w32bits
;
8696 unsigned char *bits
= fringe_bitmaps
[i
].bits
;
8697 for (j
= 0; j
< h
; j
++)
8699 static unsigned char swap_nibble
[16]
8700 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
8701 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
8702 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
8703 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
8705 unsigned char b
= *bits
++;
8706 *wb
++ = (unsigned short)((swap_nibble
[b
& 0xf]<<4)
8707 | (swap_nibble
[(b
>>4) & 0xf]));
8709 fringe_bmp
[i
] = CreateBitmap (wd
, h
, 1, 1, w32bits
);
8713 #ifndef F_SETOWN_BUG
8715 #ifdef F_SETOWN_SOCK_NEG
8716 /* stdin is a socket here */
8717 fcntl (connection
, F_SETOWN
, -getpid ());
8718 #else /* ! defined (F_SETOWN_SOCK_NEG) */
8719 fcntl (connection
, F_SETOWN
, getpid ());
8720 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
8721 #endif /* ! defined (F_SETOWN) */
8722 #endif /* F_SETOWN_BUG */
8725 if (interrupt_input
)
8726 init_sigio (connection
);
8727 #endif /* ! defined (SIGIO) */
8734 /* Get rid of display DPYINFO, assuming all frames are already gone. */
8737 x_delete_display (dpyinfo
)
8738 struct w32_display_info
*dpyinfo
;
8740 /* Discard this display from w32_display_name_list and w32_display_list.
8741 We can't use Fdelq because that can quit. */
8742 if (! NILP (w32_display_name_list
)
8743 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
8744 w32_display_name_list
= XCDR (w32_display_name_list
);
8749 tail
= w32_display_name_list
;
8750 while (CONSP (tail
) && CONSP (XCDR (tail
)))
8752 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
8754 XSETCDR (tail
, XCDR (XCDR (tail
)));
8761 /* free palette table */
8763 struct w32_palette_entry
* plist
;
8765 plist
= dpyinfo
->color_list
;
8768 struct w32_palette_entry
* pentry
= plist
;
8769 plist
= plist
->next
;
8772 dpyinfo
->color_list
= NULL
;
8773 if (dpyinfo
->palette
)
8774 DeleteObject(dpyinfo
->palette
);
8776 xfree (dpyinfo
->font_table
);
8777 xfree (dpyinfo
->w32_id_name
);
8779 /* Destroy row bitmaps. */
8783 for (i
= NO_FRINGE_BITMAP
+ 1; i
< MAX_FRINGE_BITMAPS
; i
++)
8784 DeleteObject (fringe_bmp
[i
]);
8788 /* Set up use of W32. */
8790 DWORD
w32_msg_worker ();
8793 x_flush (struct frame
* f
)
8794 { /* Nothing to do */ }
8796 static struct redisplay_interface w32_redisplay_interface
=
8801 x_clear_end_of_line
,
8803 x_after_update_window_line
,
8804 x_update_window_begin
,
8805 x_update_window_end
,
8809 w32_get_glyph_overhangs
,
8810 x_fix_overlapping_area
,
8811 w32_draw_fringe_bitmap
,
8812 w32_per_char_metric
,
8814 NULL
, /* w32_compute_glyph_string_overhangs */
8821 rif
= &w32_redisplay_interface
;
8823 /* MSVC does not type K&R functions with no arguments correctly, and
8824 so we must explicitly cast them. */
8825 clear_frame_hook
= (void (*)(void)) x_clear_frame
;
8826 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
8827 update_begin_hook
= x_update_begin
;
8828 update_end_hook
= x_update_end
;
8830 read_socket_hook
= w32_read_socket
;
8832 frame_up_to_date_hook
= w32_frame_up_to_date
;
8834 mouse_position_hook
= w32_mouse_position
;
8835 frame_rehighlight_hook
= w32_frame_rehighlight
;
8836 frame_raise_lower_hook
= w32_frame_raise_lower
;
8837 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
8838 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
8839 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
8840 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
8841 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
8843 scroll_region_ok
= 1; /* we'll scroll partial frames */
8844 char_ins_del_ok
= 1;
8845 line_ins_del_ok
= 1; /* we'll just blt 'em */
8846 fast_clear_end_of_line
= 1; /* X does this well */
8847 memory_below_frame
= 0; /* we don't remember what scrolls
8851 w32_system_caret_hwnd
= NULL
;
8852 w32_system_caret_height
= 0;
8853 w32_system_caret_x
= 0;
8854 w32_system_caret_y
= 0;
8856 last_tool_bar_item
= -1;
8857 any_help_event_p
= 0;
8859 /* Initialize input mode: interrupt_input off, no flow control, allow
8860 8 bit character input, standard quit char. */
8861 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
8863 /* Create the window thread - it will terminate itself or when the app terminates */
8867 dwMainThreadId
= GetCurrentThreadId ();
8868 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
8869 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
8871 /* Wait for thread to start */
8876 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
8878 hWindowsThread
= CreateThread (NULL
, 0,
8879 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
8880 0, 0, &dwWindowsThreadId
);
8882 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
8885 /* It is desirable that mainThread should have the same notion of
8886 focus window and active window as windowsThread. Unfortunately, the
8887 following call to AttachThreadInput, which should do precisely what
8888 we need, causes major problems when Emacs is linked as a console
8889 program. Unfortunately, we have good reasons for doing that, so
8890 instead we need to send messages to windowsThread to make some API
8891 calls for us (ones that affect, or depend on, the active/focus
8893 #ifdef ATTACH_THREADS
8894 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
8897 /* Dynamically link to optional system components. */
8899 HANDLE user_lib
= LoadLibrary ("user32.dll");
8901 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
8903 /* New proportional scroll bar functions. */
8904 LOAD_PROC (SetScrollInfo
);
8905 LOAD_PROC (GetScrollInfo
);
8909 FreeLibrary (user_lib
);
8911 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
8912 otherwise use the fixed height. */
8913 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
8914 GetSystemMetrics (SM_CYVTHUMB
);
8916 /* For either kind of scroll bar, take account of the arrows; these
8917 effectively form the border of the main scroll bar range. */
8918 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
8919 = GetSystemMetrics (SM_CYVSCROLL
);
8926 staticpro (&w32_display_name_list
);
8927 w32_display_name_list
= Qnil
;
8929 staticpro (&last_mouse_scroll_bar
);
8930 last_mouse_scroll_bar
= Qnil
;
8932 staticpro (&Qvendor_specific_keysyms
);
8933 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
8935 DEFVAR_INT ("w32-num-mouse-buttons",
8936 &Vw32_num_mouse_buttons
,
8937 doc
: /* Number of physical mouse buttons. */);
8938 Vw32_num_mouse_buttons
= Qnil
;
8940 DEFVAR_LISP ("w32-swap-mouse-buttons",
8941 &Vw32_swap_mouse_buttons
,
8942 doc
: /* Swap the mapping of middle and right mouse buttons.
8943 When nil, middle button is mouse-2 and right button is mouse-3. */);
8944 Vw32_swap_mouse_buttons
= Qnil
;
8946 DEFVAR_LISP ("w32-grab-focus-on-raise",
8947 &Vw32_grab_focus_on_raise
,
8948 doc
: /* Raised frame grabs input focus.
8949 When t, `raise-frame' grabs input focus as well. This fits well
8950 with the normal Windows click-to-focus policy, but might not be
8951 desirable when using a point-to-focus policy. */);
8952 Vw32_grab_focus_on_raise
= Qt
;
8954 DEFVAR_LISP ("w32-capslock-is-shiftlock",
8955 &Vw32_capslock_is_shiftlock
,
8956 doc
: /* Apply CapsLock state to non character input keys.
8957 When nil, CapsLock only affects normal character input keys. */);
8958 Vw32_capslock_is_shiftlock
= Qnil
;
8960 DEFVAR_LISP ("w32-recognize-altgr",
8961 &Vw32_recognize_altgr
,
8962 doc
: /* Recognize right-alt and left-ctrl as AltGr.
8963 When nil, the right-alt and left-ctrl key combination is
8964 interpreted normally. */);
8965 Vw32_recognize_altgr
= Qt
;
8967 DEFVAR_BOOL ("w32-enable-unicode-output",
8968 &w32_enable_unicode_output
,
8969 doc
: /* Enable the use of Unicode for text output if non-nil.
8970 Unicode output may prevent some third party applications for displaying
8971 Far-East Languages on Windows 95/98 from working properly.
8972 NT uses Unicode internally anyway, so this flag will probably have no
8973 affect on NT machines. */);
8974 w32_enable_unicode_output
= 1;
8977 staticpro (&help_echo
);
8978 help_echo_object
= Qnil
;
8979 staticpro (&help_echo_object
);
8980 help_echo_window
= Qnil
;
8981 staticpro (&help_echo_window
);
8982 previous_help_echo
= Qnil
;
8983 staticpro (&previous_help_echo
);
8986 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window
,
8987 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
8988 mouse_autoselect_window
= 0;
8990 DEFVAR_BOOL ("w32-use-visible-system-caret",
8991 &w32_use_visible_system_caret
,
8992 doc
: /* Flag to make the system caret visible.
8993 When this is non-nil, Emacs will indicate the position of point by
8994 using the system caret instead of drawing its own cursor. Some screen
8995 reader software does not track the system cursor properly when it is
8996 invisible, and gets confused by Emacs drawing its own cursor, so this
8997 variable is initialized to t when Emacs detects that screen reader
8998 software is running as it starts up.
9000 When this variable is set, other variables affecting the appearance of
9001 the cursor have no effect. */);
9003 /* Initialize w32_use_visible_system_caret based on whether a screen
9004 reader is in use. */
9005 if (!SystemParametersInfo (SPI_GETSCREENREADER
, 0,
9006 &w32_use_visible_system_caret
, 0))
9007 w32_use_visible_system_caret
= 0;
9009 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
9010 doc
: /* *Non-nil means draw block cursor as wide as the glyph under it.
9011 For example, if a block cursor is over a tab, it will be drawn as
9012 wide as that tab on the display. */);
9013 x_stretch_cursor_p
= 0;
9015 DEFVAR_BOOL ("x-use-underline-position-properties",
9016 &x_use_underline_position_properties
,
9017 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9018 nil means ignore them. If you encounter fonts with bogus
9019 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9020 to 4.1, set this to nil. */);
9021 x_use_underline_position_properties
= 1;
9023 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9024 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9025 Vx_toolkit_scroll_bars
= Qt
;
9027 staticpro (&last_mouse_motion_frame
);
9028 last_mouse_motion_frame
= Qnil
;