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))
65 static int max_fringe_bmp
= 0;
66 static HBITMAP
*fringe_bmp
= 0;
68 /* Non-nil means Emacs uses toolkit scroll bars. */
70 Lisp_Object Vx_toolkit_scroll_bars
;
72 /* Temporary variables for w32_read_socket. */
74 static int last_mousemove_x
= 0;
75 static int last_mousemove_y
= 0;
77 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
78 #ifndef GET_WHEEL_DELTA_WPARAM
79 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
82 /* Non-zero means that a HELP_EVENT has been generated since Emacs
85 static int any_help_event_p
;
87 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88 static Lisp_Object last_window
;
90 extern unsigned int msh_mousewheel
;
92 extern void free_frame_menubar ();
94 extern int w32_codepage_for_font (char *fontname
);
95 extern Cursor
w32_load_cursor (LPCTSTR name
);
97 extern glyph_metric
*w32_BDF_TextMetric(bdffont
*fontp
,
98 unsigned char *text
, int dim
);
99 extern Lisp_Object Vwindow_system
;
101 #define x_any_window_to_frame x_window_to_frame
102 #define x_top_window_to_frame x_window_to_frame
105 /* This is display since w32 does not support multiple ones. */
106 struct w32_display_info one_w32_display_info
;
107 struct w32_display_info
*x_display_list
;
109 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
110 one for each element of w32_display_list and in the same order.
111 NAME is the name of the frame.
112 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
113 Lisp_Object w32_display_name_list
;
115 /* Frame being updated by update_frame. This is declared in term.c.
116 This is set by update_begin and looked at by all the
117 w32 functions. It is zero while not inside an update.
118 In that case, the w32 functions assume that `SELECTED_FRAME ()'
119 is the frame to apply to. */
120 extern struct frame
*updating_frame
;
122 /* This is a frame waiting to be autoraised, within w32_read_socket. */
123 struct frame
*pending_autoraise_frame
;
125 /* The handle of the frame that currently owns the system caret. */
126 HWND w32_system_caret_hwnd
;
127 int w32_system_caret_height
;
128 int w32_system_caret_x
;
129 int w32_system_caret_y
;
130 int w32_use_visible_system_caret
;
132 /* Flag to enable Unicode output in case users wish to use programs
133 like Twinbridge on '95 rather than installed system level support
134 for Far East languages. */
135 int w32_enable_unicode_output
;
137 DWORD dwWindowsThreadId
= 0;
138 HANDLE hWindowsThread
= NULL
;
139 DWORD dwMainThreadId
= 0;
140 HANDLE hMainThread
= NULL
;
143 /* These definitions are new with Windows 95. */
144 #define SIF_RANGE 0x0001
145 #define SIF_PAGE 0x0002
146 #define SIF_POS 0x0004
147 #define SIF_DISABLENOSCROLL 0x0008
148 #define SIF_TRACKPOS 0x0010
149 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
151 typedef struct tagSCROLLINFO
160 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
161 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
164 /* Dynamic linking to new proportional scroll bar functions. */
165 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
166 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
168 int vertical_scroll_bar_min_handle
;
169 int vertical_scroll_bar_top_border
;
170 int vertical_scroll_bar_bottom_border
;
172 int last_scroll_bar_drag_pos
;
174 /* Mouse movement. */
176 /* Where the mouse was last time we reported a mouse event. */
178 static RECT last_mouse_glyph
;
179 static Lisp_Object last_mouse_press_frame
;
181 int w32_num_mouse_buttons
;
183 Lisp_Object Vw32_swap_mouse_buttons
;
185 /* Control whether x_raise_frame also sets input focus. */
186 Lisp_Object Vw32_grab_focus_on_raise
;
188 /* Control whether Caps Lock affects non-ascii characters. */
189 Lisp_Object Vw32_capslock_is_shiftlock
;
191 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
192 Lisp_Object Vw32_recognize_altgr
;
194 /* The scroll bar in which the last motion event occurred.
196 If the last motion event occurred in a scroll bar, we set this
197 so w32_mouse_position can know whether to report a scroll bar motion or
200 If the last motion event didn't occur in a scroll bar, we set this
201 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
202 static Lisp_Object last_mouse_scroll_bar
;
203 static int last_mouse_scroll_bar_pos
;
205 /* This is a hack. We would really prefer that w32_mouse_position would
206 return the time associated with the position it returns, but there
207 doesn't seem to be any way to wrest the time-stamp from the server
208 along with the position query. So, we just keep track of the time
209 of the last movement we received, and return that in hopes that
210 it's somewhat accurate. */
212 static Time last_mouse_movement_time
;
214 /* Incremented by w32_read_socket whenever it really tries to read
218 static int volatile input_signal_count
;
220 static int input_signal_count
;
223 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
229 /* A mask of extra modifier bits to put into every keyboard char. */
231 extern EMACS_INT extra_keyboard_modifiers
;
233 static void x_update_window_end
P_ ((struct window
*, int, int));
234 void w32_delete_display
P_ ((struct w32_display_info
*));
235 static void w32_handle_tool_bar_click
P_ ((struct frame
*,
236 struct input_event
*));
237 void w32_define_cursor
P_ ((Window
, Cursor
));
239 void x_lower_frame
P_ ((struct frame
*));
240 void x_scroll_bar_clear
P_ ((struct frame
*));
241 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
242 void x_raise_frame
P_ ((struct frame
*));
243 void x_set_window_size
P_ ((struct frame
*, int, int, int));
244 void x_wm_set_window_state
P_ ((struct frame
*, int));
245 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
246 void w32_initialize
P_ ((void));
247 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
248 int x_compute_min_glyph_bounds
P_ ((struct frame
*));
249 static void x_update_end
P_ ((struct frame
*));
250 static void w32_frame_up_to_date
P_ ((struct frame
*));
251 static void w32_set_terminal_modes
P_ ((void));
252 static void w32_reset_terminal_modes
P_ ((void));
253 static void x_clear_frame
P_ ((void));
254 static void frame_highlight
P_ ((struct frame
*));
255 static void frame_unhighlight
P_ ((struct frame
*));
256 static void x_new_focus_frame
P_ ((struct w32_display_info
*,
258 static void x_focus_changed
P_ ((int, int, struct w32_display_info
*,
259 struct frame
*, struct input_event
*));
260 static void w32_detect_focus_change
P_ ((struct w32_display_info
*,
261 W32Msg
*, struct input_event
*));
262 static void w32_frame_rehighlight
P_ ((struct frame
*));
263 static void x_frame_rehighlight
P_ ((struct w32_display_info
*));
264 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
265 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
266 enum text_cursor_kinds
));
267 static void w32_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, HDC
));
269 static Lisp_Object Qvendor_specific_keysyms
;
272 /***********************************************************************
274 ***********************************************************************/
278 /* This is a function useful for recording debugging information about
279 the sequence of occurrences in this file. */
287 struct record event_record
[100];
289 int event_record_index
;
291 record_event (locus
, type
)
295 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
296 event_record_index
= 0;
298 event_record
[event_record_index
].locus
= locus
;
299 event_record
[event_record_index
].type
= type
;
300 event_record_index
++;
307 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
310 if (mask
& GCForeground
)
311 gc
->foreground
= xgcv
->foreground
;
312 if (mask
& GCBackground
)
313 gc
->background
= xgcv
->background
;
315 gc
->font
= xgcv
->font
;
318 XGCValues
*XCreateGC (void * ignore
, Window window
, unsigned long mask
,
321 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
322 bzero (gc
, sizeof (XGCValues
));
324 XChangeGC (ignore
, gc
, mask
, xgcv
);
330 XGetGCValues (void* ignore
, XGCValues
*gc
,
331 unsigned long mask
, XGCValues
*xgcv
)
333 XChangeGC (ignore
, xgcv
, mask
, gc
);
337 w32_set_clip_rectangle (HDC hdc
, RECT
*rect
)
341 HRGN clip_region
= CreateRectRgnIndirect (rect
);
342 SelectClipRgn (hdc
, clip_region
);
343 DeleteObject (clip_region
);
346 SelectClipRgn (hdc
, NULL
);
350 /* Draw a hollow rectangle at the specified position. */
352 w32_draw_rectangle (HDC hdc
, XGCValues
*gc
, int x
, int y
,
353 int width
, int height
)
358 hb
= CreateSolidBrush (gc
->background
);
359 hp
= CreatePen (PS_SOLID
, 0, gc
->foreground
);
360 oldhb
= SelectObject (hdc
, hb
);
361 oldhp
= SelectObject (hdc
, hp
);
363 Rectangle (hdc
, x
, y
, x
+ width
, y
+ height
);
365 SelectObject (hdc
, oldhb
);
366 SelectObject (hdc
, oldhp
);
371 /* Draw a filled rectangle at the specified position. */
373 w32_fill_rect (f
, hdc
, pix
, lprect
)
381 hb
= CreateSolidBrush (pix
);
382 FillRect (hdc
, lprect
, hb
);
391 HDC hdc
= get_frame_dc (f
);
393 /* Under certain conditions, this can be called at startup with
394 a console frame pointer before the GUI frame is created. An HDC
395 of 0 indicates this. */
398 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
399 w32_clear_rect (f
, hdc
, &rect
);
402 release_frame_dc (f
, hdc
);
406 /***********************************************************************
407 Starting and ending an update
408 ***********************************************************************/
410 /* Start an update of frame F. This function is installed as a hook
411 for update_begin, i.e. it is called when update_begin is called.
412 This function is called prior to calls to x_update_window_begin for
413 each window being updated. */
419 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
421 if (! FRAME_W32_P (f
))
424 /* Regenerate display palette before drawing if list of requested
425 colors has changed. */
426 if (display_info
->regen_palette
)
428 w32_regenerate_palette (f
);
429 display_info
->regen_palette
= FALSE
;
434 /* Start update of window W. Set the global variable updated_window
435 to the window being updated and set output_cursor to the cursor
439 x_update_window_begin (w
)
442 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
443 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
445 /* Hide the system caret during an update. */
446 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
448 SendMessage (w32_system_caret_hwnd
, WM_EMACS_HIDE_CARET
, 0, 0);
452 set_output_cursor (&w
->cursor
);
456 if (f
== display_info
->mouse_face_mouse_frame
)
458 /* Don't do highlighting for mouse motion during the update. */
459 display_info
->mouse_face_defer
= 1;
461 /* If F needs to be redrawn, simply forget about any prior mouse
463 if (FRAME_GARBAGED_P (f
))
464 display_info
->mouse_face_window
= Qnil
;
466 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
467 their mouse_face_p flag set, which means that they are always
468 unequal to rows in a desired matrix which never have that
469 flag set. So, rows containing mouse-face glyphs are never
470 scrolled, and we don't have to switch the mouse highlight off
471 here to prevent it from being scrolled. */
473 /* Can we tell that this update does not affect the window
474 where the mouse highlight is? If so, no need to turn off.
475 Likewise, don't do anything if the frame is garbaged;
476 in that case, the frame's current matrix that we would use
477 is all wrong, and we will redisplay that line anyway. */
478 if (!NILP (display_info
->mouse_face_window
)
479 && w
== XWINDOW (display_info
->mouse_face_window
))
483 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
484 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
487 if (i
< w
->desired_matrix
->nrows
)
488 clear_mouse_face (display_info
);
496 /* Draw a vertical window border from (x,y0) to (x,y1) */
499 w32_draw_vertical_window_border (w
, x
, y0
, y1
)
503 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
512 hdc
= get_frame_dc (f
);
513 w32_fill_rect (f
, hdc
, FRAME_FOREGROUND_PIXEL (f
), &r
);
514 release_frame_dc (f
, hdc
);
518 /* End update of window W (which is equal to updated_window).
520 Draw vertical borders between horizontally adjacent windows, and
521 display W's cursor if CURSOR_ON_P is non-zero.
523 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
524 glyphs in mouse-face were overwritten. In that case we have to
525 make sure that the mouse-highlight is properly redrawn.
527 W may be a menu bar pseudo-window in case we don't have X toolkit
528 support. Such windows don't have a cursor, so don't display it
532 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
534 int cursor_on_p
, mouse_face_overwritten_p
;
536 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
538 if (!w
->pseudo_window_p
)
543 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
545 output_cursor
.x
, output_cursor
.y
);
547 if (draw_window_fringes (w
, 1))
548 x_draw_vertical_border (w
);
553 /* If a row with mouse-face was overwritten, arrange for
554 XTframe_up_to_date to redisplay the mouse highlight. */
555 if (mouse_face_overwritten_p
)
557 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
558 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
559 dpyinfo
->mouse_face_window
= Qnil
;
562 /* Unhide the caret. This won't actually show the cursor, unless it
563 was visible before the corresponding call to HideCaret in
564 x_update_window_begin. */
565 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
567 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
570 updated_window
= NULL
;
574 /* End update of frame F. This function is installed as a hook in
581 if (! FRAME_W32_P (f
))
584 /* Mouse highlight may be displayed again. */
585 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
589 /* This function is called from various places in xdisp.c whenever a
590 complete update has been performed. The global variable
591 updated_window is not available here. */
594 w32_frame_up_to_date (f
)
599 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
601 if (dpyinfo
->mouse_face_deferred_gc
602 || f
== dpyinfo
->mouse_face_mouse_frame
)
605 if (dpyinfo
->mouse_face_mouse_frame
)
606 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
607 dpyinfo
->mouse_face_mouse_x
,
608 dpyinfo
->mouse_face_mouse_y
);
609 dpyinfo
->mouse_face_deferred_gc
= 0;
616 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
617 arrow bitmaps, or clear the fringes if no bitmaps are required
618 before DESIRED_ROW is made current. The window being updated is
619 found in updated_window. This function is called from
620 update_window_line only if it is known that there are differences
621 between bitmaps to be drawn between current row and DESIRED_ROW. */
624 x_after_update_window_line (desired_row
)
625 struct glyph_row
*desired_row
;
627 struct window
*w
= updated_window
;
633 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
634 desired_row
->redraw_fringe_bitmaps_p
= 1;
636 /* When a window has disappeared, make sure that no rest of
637 full-width rows stays visible in the internal border. Could
638 check here if updated_window is the leftmost/rightmost window,
639 but I guess it's not worth doing since vertically split windows
640 are almost never used, internal border is rarely set, and the
641 overhead is very small. */
642 if (windows_or_buffers_changed
643 && desired_row
->full_width_p
644 && (f
= XFRAME (w
->frame
),
645 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
647 && (height
= desired_row
->visible_height
,
650 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
652 /* Internal border is drawn below the tool bar. */
653 if (WINDOWP (f
->tool_bar_window
)
654 && w
== XWINDOW (f
->tool_bar_window
))
659 HDC hdc
= get_frame_dc (f
);
660 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
661 w32_clear_area (f
, hdc
, FRAME_PIXEL_WIDTH (f
) - width
,
663 release_frame_dc (f
, hdc
);
670 /* Draw the bitmap WHICH in one of the left or right fringes of
671 window W. ROW is the glyph row for which to display the bitmap; it
672 determines the vertical position at which the bitmap has to be
676 w32_draw_fringe_bitmap (w
, row
, p
)
678 struct glyph_row
*row
;
679 struct draw_fringe_bitmap_params
*p
;
681 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
683 struct face
*face
= p
->face
;
686 hdc
= get_frame_dc (f
);
688 /* Must clip because of partially visible lines. */
689 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
692 /* Adjust position of "bottom aligned" bitmap on partially
695 int oldVH
= row
->visible_height
;
696 row
->visible_height
= p
->h
;
697 row
->y
-= rowY
- p
->y
;
698 w32_clip_to_row (w
, row
, -1, hdc
);
700 row
->visible_height
= oldVH
;
703 w32_clip_to_row (w
, row
, -1, hdc
);
705 if (p
->bx
>= 0 && !p
->overlay_p
)
707 w32_fill_area (f
, hdc
, face
->background
,
708 p
->bx
, p
->by
, p
->nx
, p
->ny
);
711 if (p
->which
&& p
->which
< max_fringe_bmp
)
713 HBITMAP pixmap
= fringe_bmp
[p
->which
];
717 compat_hdc
= CreateCompatibleDC (hdc
);
721 horig_obj
= SelectObject (compat_hdc
, pixmap
);
723 /* Paint overlays transparently. */
726 HBRUSH h_brush
, h_orig_brush
;
728 SetTextColor (hdc
, BLACK_PIX_DEFAULT (f
));
729 SetBkColor (hdc
, WHITE_PIX_DEFAULT (f
));
730 h_brush
= CreateSolidBrush (face
->foreground
);
731 h_orig_brush
= SelectObject (hdc
, h_brush
);
733 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
734 compat_hdc
, 0, p
->dh
,
736 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
737 compat_hdc
, 0, p
->dh
,
739 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
740 compat_hdc
, 0, p
->dh
,
743 SelectObject (hdc
, h_orig_brush
);
744 DeleteObject (h_brush
);
748 SetTextColor (hdc
, face
->background
);
749 SetBkColor (hdc
, (p
->cursor_p
750 ? f
->output_data
.w32
->cursor_pixel
751 : face
->foreground
));
753 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
754 compat_hdc
, 0, p
->dh
,
758 SelectObject (compat_hdc
, horig_obj
);
759 DeleteDC (compat_hdc
);
763 w32_set_clip_rectangle (hdc
, NULL
);
765 release_frame_dc (f
, hdc
);
769 w32_define_fringe_bitmap (which
, bits
, h
, wd
)
771 unsigned short *bits
;
774 if (which
>= max_fringe_bmp
)
776 int i
= max_fringe_bmp
;
777 max_fringe_bmp
= which
+ 20;
778 fringe_bmp
= (HBITMAP
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (HBITMAP
));
779 while (i
< max_fringe_bmp
)
783 fringe_bmp
[which
] = CreateBitmap (wd
, h
, 1, 1, bits
);
787 w32_destroy_fringe_bitmap (which
)
790 if (which
>= max_fringe_bmp
)
793 if (fringe_bmp
[which
])
794 DeleteObject (fringe_bmp
[which
]);
795 fringe_bmp
[which
] = 0;
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 /* Function prototypes of this page. */
826 XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*, wchar_t *, int));
827 static int w32_encode_char
P_ ((int, wchar_t *, struct font_info
*, int *));
830 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
831 If CHAR2B is not contained in FONT, the font's default character
832 metric is returned. */
835 w32_bdf_per_char_metric (font
, char2b
, dim
, pcm
)
841 glyph_metric
* bdf_metric
;
845 buf
[0] = (char)(*char2b
);
848 buf
[0] = XCHAR2B_BYTE1 (char2b
);
849 buf
[1] = XCHAR2B_BYTE2 (char2b
);
852 bdf_metric
= w32_BDF_TextMetric (font
->bdf
, buf
, dim
);
856 pcm
->width
= bdf_metric
->dwidth
;
857 pcm
->lbearing
= bdf_metric
->bbox
;
858 pcm
->rbearing
= bdf_metric
->dwidth
859 - (bdf_metric
->bbox
+ bdf_metric
->bbw
);
860 pcm
->ascent
= bdf_metric
->bboy
+ bdf_metric
->bbh
;
861 pcm
->descent
= -bdf_metric
->bboy
;
870 w32_native_per_char_metric (font
, char2b
, font_type
, pcm
)
873 enum w32_char_font_type font_type
;
876 HDC hdc
= GetDC (NULL
);
880 xassert (font
&& char2b
);
881 xassert (font
->hfont
);
882 xassert (font_type
== UNICODE_FONT
|| font_type
== ANSI_FONT
);
884 old_font
= SelectObject (hdc
, font
->hfont
);
886 if ((font
->tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) != 0)
890 if (font_type
== UNICODE_FONT
)
891 retval
= GetCharABCWidthsW (hdc
, *char2b
, *char2b
, &char_widths
);
893 retval
= GetCharABCWidthsA (hdc
, *char2b
, *char2b
, &char_widths
);
898 /* Disabled until we can find a way to get the right results
899 on all versions of Windows. */
901 /* Don't trust the ABC widths. For synthesized fonts they are
902 wrong, and so is the result of GetCharWidth()! */
904 GetCharWidth (hdc
, *char2b
, *char2b
, &real_width
);
906 pcm
->width
= char_widths
.abcA
+ char_widths
.abcB
+ char_widths
.abcC
;
908 /* As far as I can tell, this is the best way to determine what
909 ExtTextOut will do with the broken font. */
910 if (pcm
->width
!= real_width
)
911 pcm
->width
= (pcm
->width
+ real_width
) / 2;
913 pcm
->lbearing
= char_widths
.abcA
;
914 pcm
->rbearing
= char_widths
.abcA
+ char_widths
.abcB
;
915 pcm
->ascent
= FONT_BASE (font
);
916 pcm
->descent
= FONT_DESCENT (font
);
922 /* Either font is not a True-type font, or GetCharABCWidthsW
923 failed (it is not supported on Windows 9x for instance), so we
924 can't determine the full info we would like. All is not lost
925 though - we can call GetTextExtentPoint32 to get rbearing and
926 deduce width based on the font's per-string overhang. lbearing
927 is assumed to be zero. */
929 /* TODO: Some Thai characters (and other composites if Windows
930 supports them) do have lbearing, and report their total width
931 as zero. Need some way of handling them when
932 GetCharABCWidthsW fails. */
935 if (font_type
== UNICODE_FONT
)
936 retval
= GetTextExtentPoint32W (hdc
, char2b
, 1, &sz
);
938 retval
= GetTextExtentPoint32A (hdc
, (char*)char2b
, 1, &sz
);
942 pcm
->width
= sz
.cx
- font
->tm
.tmOverhang
;
943 pcm
->rbearing
= sz
.cx
;
945 pcm
->ascent
= FONT_BASE (font
);
946 pcm
->descent
= FONT_DESCENT (font
);
951 if (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0)
956 SelectObject (hdc
, old_font
);
957 ReleaseDC (NULL
, hdc
);
964 w32_per_char_metric (font
, char2b
, font_type
)
967 int /* enum w32_char_font_type */ font_type
;
969 /* The result metric information. */
973 xassert (font
&& char2b
);
975 /* TODO: This function is currently called through the RIF, and in
976 some cases font_type is UNKNOWN_FONT. We currently allow the
977 cached metrics to be used, which seems to work, but in cases
978 where font_type is UNKNOWN_FONT, we probably haven't encoded
979 char2b appropriately. All callers need checking to see what they
980 are passing. This is most likely to affect variable width fonts
981 outside the Latin-1 range, particularly in languages like Thai
982 that rely on rbearing and lbearing to provide composition. I
983 don't think that is working currently anyway, but we don't seem
984 to have anyone testing such languages on Windows. */
986 /* Handle the common cases quickly. */
987 if (!font
->bdf
&& font
->per_char
== NULL
)
988 /* TODO: determine whether char2b exists in font? */
989 return &font
->max_bounds
;
990 else if (!font
->bdf
&& *char2b
< 128)
991 return &font
->per_char
[*char2b
];
993 xassert (font_type
!= UNKNOWN_FONT
);
995 pcm
= &font
->scratch
;
997 if (font_type
== BDF_1D_FONT
)
998 retval
= w32_bdf_per_char_metric (font
, char2b
, 1, pcm
);
999 else if (font_type
== BDF_2D_FONT
)
1000 retval
= w32_bdf_per_char_metric (font
, char2b
, 2, pcm
);
1002 retval
= w32_native_per_char_metric (font
, char2b
, font_type
, pcm
);
1011 w32_cache_char_metrics (font
)
1014 wchar_t char2b
= L
'x';
1016 /* Cache char metrics for the common cases. */
1019 /* TODO: determine whether font is fixed-pitch. */
1020 if (!w32_bdf_per_char_metric (font
, &char2b
, 1, &font
->max_bounds
))
1022 /* Use the font width and height as max bounds, as not all BDF
1023 fonts contain the letter 'x'. */
1024 font
->max_bounds
.width
= FONT_MAX_WIDTH (font
);
1025 font
->max_bounds
.lbearing
= -font
->bdf
->llx
;
1026 font
->max_bounds
.rbearing
= FONT_MAX_WIDTH (font
) - font
->bdf
->urx
;
1027 font
->max_bounds
.ascent
= FONT_BASE (font
);
1028 font
->max_bounds
.descent
= FONT_DESCENT (font
);
1033 if (((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
) != 0)
1034 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1035 though they contain characters of different widths. */
1036 || (font
->tm
.tmMaxCharWidth
!= font
->tm
.tmAveCharWidth
))
1038 /* Font is not fixed pitch, so cache per_char info for the
1039 ASCII characters. It would be much more work, and probably
1040 not worth it, to cache other chars, since we may change
1041 between using Unicode and ANSI text drawing functions at
1045 font
->per_char
= xmalloc (128 * sizeof(XCharStruct
));
1046 for (i
= 0; i
< 128; i
++)
1049 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1050 &font
->per_char
[i
]);
1054 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1060 /* Determine if a font is double byte. */
1061 int w32_font_is_double_byte (XFontStruct
*font
)
1063 return font
->double_byte_p
;
1068 w32_use_unicode_for_codepage (codepage
)
1071 /* If the current codepage is supported, use Unicode for output. */
1072 return (w32_enable_unicode_output
1073 && codepage
!= CP_8BIT
1074 && (codepage
== CP_UNICODE
|| IsValidCodePage (codepage
)));
1077 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1078 the two-byte form of C. Encoding is returned in *CHAR2B. */
1080 static int /* enum w32_char_font_type */
1081 w32_encode_char (c
, char2b
, font_info
, two_byte_p
)
1084 struct font_info
*font_info
;
1087 int charset
= CHAR_CHARSET (c
);
1090 int internal_two_byte_p
= 0;
1092 XFontStruct
*font
= font_info
->font
;
1094 internal_two_byte_p
= w32_font_is_double_byte (font
);
1096 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1097 This may be either a program in a special encoder language or a
1099 if (font_info
->font_encoder
)
1101 /* It's a program. */
1102 struct ccl_program
*ccl
= font_info
->font_encoder
;
1104 if (CHARSET_DIMENSION (charset
) == 1)
1106 ccl
->reg
[0] = charset
;
1107 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1112 ccl
->reg
[0] = charset
;
1113 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1114 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1117 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1119 /* We assume that MSBs are appropriately set/reset by CCL
1121 if (!internal_two_byte_p
) /* 1-byte font */
1122 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
1124 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
1126 else if (font_info
->encoding
[charset
])
1128 /* Fixed encoding scheme. See fontset.h for the meaning of the
1129 encoding numbers. */
1130 int enc
= font_info
->encoding
[charset
];
1132 if ((enc
== 1 || enc
== 2)
1133 && CHARSET_DIMENSION (charset
) == 2)
1134 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
) | 0x80, XCHAR2B_BYTE2 (char2b
));
1136 if (enc
== 1 || enc
== 3
1137 || (enc
== 4 && CHARSET_DIMENSION (charset
) == 1))
1138 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
) | 0x80);
1143 ENCODE_SJIS (XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
),
1145 STORE_XCHAR2B (char2b
, sjis1
, sjis2
);
1148 codepage
= font_info
->codepage
;
1150 /* If charset is not ASCII or Latin-1, may need to move it into
1152 if ( font
&& !font
->bdf
&& w32_use_unicode_for_codepage (codepage
)
1153 && charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
1154 && charset
!= CHARSET_8_BIT_CONTROL
&& charset
!= CHARSET_8_BIT_GRAPHIC
)
1157 temp
[0] = XCHAR2B_BYTE1 (char2b
);
1158 temp
[1] = XCHAR2B_BYTE2 (char2b
);
1160 if (codepage
!= CP_UNICODE
)
1163 MultiByteToWideChar (codepage
, 0, temp
, 2, char2b
, 1);
1165 MultiByteToWideChar (codepage
, 0, temp
+1, 1, char2b
, 1);
1168 internal_two_byte_p
= 1;
1172 *two_byte_p
= internal_two_byte_p
;
1175 return UNKNOWN_FONT
;
1176 else if (font
->bdf
&& CHARSET_DIMENSION (charset
) == 1)
1181 return UNICODE_FONT
;
1188 /***********************************************************************
1190 ***********************************************************************/
1193 /* Encapsulate the different ways of displaying text under W32. */
1196 w32_text_out (s
, x
, y
,chars
,nchars
)
1197 struct glyph_string
* s
;
1202 int charset_dim
= w32_font_is_double_byte (s
->font
) ? 2 : 1;
1204 w32_BDF_TextOut (s
->font
->bdf
, s
->hdc
,
1205 x
, y
, (char *) chars
, charset_dim
,
1206 nchars
* charset_dim
, 0);
1207 else if (s
->first_glyph
->font_type
== UNICODE_FONT
)
1208 ExtTextOutW (s
->hdc
, x
, y
, 0, NULL
, chars
, nchars
, NULL
);
1210 ExtTextOutA (s
->hdc
, x
, y
, 0, NULL
, (char *) chars
,
1211 nchars
* charset_dim
, NULL
);
1215 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1216 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1217 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1219 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1220 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1221 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1222 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1223 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1224 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1225 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1226 static int w32_alloc_lighter_color (struct frame
*, COLORREF
*, double, int);
1227 static void w32_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1228 double, int, COLORREF
));
1229 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1230 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1231 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1232 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1233 static void w32_draw_image_foreground_1
P_ ((struct glyph_string
*, HBITMAP
));
1234 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1236 static void w32_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1237 int, int, int, int, int, int,
1239 static void w32_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1240 int, int, int, RECT
*));
1243 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1247 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1252 struct glyph_string
*s
;
1254 if (s
->font
== FRAME_FONT (s
->f
)
1255 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1256 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1258 s
->gc
= s
->f
->output_data
.w32
->cursor_gc
;
1261 /* Cursor on non-default face: must merge. */
1265 xgcv
.background
= s
->f
->output_data
.w32
->cursor_pixel
;
1266 xgcv
.foreground
= s
->face
->background
;
1268 /* If the glyph would be invisible, try a different foreground. */
1269 if (xgcv
.foreground
== xgcv
.background
)
1270 xgcv
.foreground
= s
->face
->foreground
;
1271 if (xgcv
.foreground
== xgcv
.background
)
1272 xgcv
.foreground
= s
->f
->output_data
.w32
->cursor_foreground_pixel
;
1273 if (xgcv
.foreground
== xgcv
.background
)
1274 xgcv
.foreground
= s
->face
->foreground
;
1276 /* Make sure the cursor is distinct from text in this face. */
1277 if (xgcv
.background
== s
->face
->background
1278 && xgcv
.foreground
== s
->face
->foreground
)
1280 xgcv
.background
= s
->face
->foreground
;
1281 xgcv
.foreground
= s
->face
->background
;
1284 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1285 xgcv
.font
= s
->font
;
1286 mask
= GCForeground
| GCBackground
| GCFont
;
1288 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1289 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1292 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1293 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1295 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1300 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1303 x_set_mouse_face_gc (s
)
1304 struct glyph_string
*s
;
1309 /* What face has to be used last for the mouse face? */
1310 face_id
= FRAME_W32_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1311 face
= FACE_FROM_ID (s
->f
, face_id
);
1313 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1315 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1316 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1318 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1319 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1320 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1322 /* If font in this face is same as S->font, use it. */
1323 if (s
->font
== s
->face
->font
)
1324 s
->gc
= s
->face
->gc
;
1327 /* Otherwise construct scratch_cursor_gc with values from FACE
1332 xgcv
.background
= s
->face
->background
;
1333 xgcv
.foreground
= s
->face
->foreground
;
1334 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1335 xgcv
.font
= s
->font
;
1336 mask
= GCForeground
| GCBackground
| GCFont
;
1338 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1339 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1342 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1343 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1345 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1348 xassert (s
->gc
!= 0);
1352 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1353 Faces to use in the mode line have already been computed when the
1354 matrix was built, so there isn't much to do, here. */
1357 x_set_mode_line_face_gc (s
)
1358 struct glyph_string
*s
;
1360 s
->gc
= s
->face
->gc
;
1364 /* Set S->gc of glyph string S for drawing that glyph string. Set
1365 S->stippled_p to a non-zero value if the face of S has a stipple
1369 x_set_glyph_string_gc (s
)
1370 struct glyph_string
*s
;
1372 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1374 if (s
->hl
== DRAW_NORMAL_TEXT
)
1376 s
->gc
= s
->face
->gc
;
1377 s
->stippled_p
= s
->face
->stipple
!= 0;
1379 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1381 x_set_mode_line_face_gc (s
);
1382 s
->stippled_p
= s
->face
->stipple
!= 0;
1384 else if (s
->hl
== DRAW_CURSOR
)
1386 x_set_cursor_gc (s
);
1389 else if (s
->hl
== DRAW_MOUSE_FACE
)
1391 x_set_mouse_face_gc (s
);
1392 s
->stippled_p
= s
->face
->stipple
!= 0;
1394 else if (s
->hl
== DRAW_IMAGE_RAISED
1395 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1397 s
->gc
= s
->face
->gc
;
1398 s
->stippled_p
= s
->face
->stipple
!= 0;
1402 s
->gc
= s
->face
->gc
;
1403 s
->stippled_p
= s
->face
->stipple
!= 0;
1406 /* GC must have been set. */
1407 xassert (s
->gc
!= 0);
1411 /* Set clipping for output of glyph string S. S may be part of a mode
1412 line or menu if we don't have X toolkit support. */
1415 x_set_glyph_string_clipping (s
)
1416 struct glyph_string
*s
;
1419 get_glyph_string_clip_rect (s
, &r
);
1420 w32_set_clip_rectangle (s
->hdc
, &r
);
1425 Compute left and right overhang of glyph string S. If S is a glyph
1426 string for a composition, assume overhangs don't exist. */
1429 w32_compute_glyph_string_overhangs (s
)
1430 struct glyph_string
*s
;
1432 /* TODO: Windows does not appear to have a method for
1433 getting this info without getting the ABC widths for each
1434 individual character and working it out manually. */
1439 w32_get_glyph_overhangs (glyph
, f
, left
, right
)
1440 struct glyph
*glyph
;
1444 HDC hdc
= get_frame_dc (f
);
1445 /* Convert to unicode! */
1446 x_get_glyph_overhangs (glyph
, f
, left
, right
);
1447 release_frame_dc (f
, hdc
);
1451 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1454 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1455 struct glyph_string
*s
;
1463 /* Take clipping into account. */
1464 if (s
->gc
->clip_mask
== Rect
)
1466 real_x
= max (real_x
, s
->gc
->clip_rectangle
.left
);
1467 real_y
= max (real_y
, s
->gc
->clip_rectangle
.top
);
1468 real_w
= min (real_w
, s
->gc
->clip_rectangle
.right
1469 - s
->gc
->clip_rectangle
.left
);
1470 real_h
= min (real_h
, s
->gc
->clip_rectangle
.bottom
1471 - s
->gc
->clip_rectangle
.top
);
1474 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->background
, real_x
, real_y
,
1479 /* Draw the background of glyph_string S. If S->background_filled_p
1480 is non-zero don't draw it. FORCE_P non-zero means draw the
1481 background even if it wouldn't be drawn normally. This is used
1482 when a string preceding S draws into the background of S, or S
1483 contains the first component of a composition. */
1486 x_draw_glyph_string_background (s
, force_p
)
1487 struct glyph_string
*s
;
1490 /* Nothing to do if background has already been drawn or if it
1491 shouldn't be drawn in the first place. */
1492 if (!s
->background_filled_p
)
1494 int box_line_width
= max (s
->face
->box_line_width
, 0);
1496 #if 0 /* TODO: stipple */
1499 /* Fill background with a stipple pattern. */
1500 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1501 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1502 s
->y
+ box_line_width
,
1503 s
->background_width
,
1504 s
->height
- 2 * box_line_width
);
1505 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1506 s
->background_filled_p
= 1;
1510 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1511 || s
->font_not_found_p
1512 || s
->extends_to_end_of_line_p
1516 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1517 s
->background_width
,
1518 s
->height
- 2 * box_line_width
);
1519 s
->background_filled_p
= 1;
1525 /* Draw the foreground of glyph string S. */
1528 x_draw_glyph_string_foreground (s
)
1529 struct glyph_string
*s
;
1534 /* If first glyph of S has a left box line, start drawing the text
1535 of S to the right of that box line. */
1536 if (s
->face
->box
!= FACE_NO_BOX
1537 && s
->first_glyph
->left_box_line_p
)
1538 x
= s
->x
+ abs (s
->face
->box_line_width
);
1542 if (s
->for_overlaps_p
|| (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1543 SetBkMode (s
->hdc
, TRANSPARENT
);
1545 SetBkMode (s
->hdc
, OPAQUE
);
1547 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1548 SetBkColor (s
->hdc
, s
->gc
->background
);
1549 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1551 if (s
->font
&& s
->font
->hfont
)
1552 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1554 /* Draw characters of S as rectangles if S's font could not be
1556 if (s
->font_not_found_p
)
1558 for (i
= 0; i
< s
->nchars
; ++i
)
1560 struct glyph
*g
= s
->first_glyph
+ i
;
1562 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1564 x
+= g
->pixel_width
;
1569 char *char1b
= (char *) s
->char2b
;
1570 int boff
= s
->font_info
->baseline_offset
;
1572 if (s
->font_info
->vertical_centering
)
1573 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1575 /* If we can use 8-bit functions, condense S->char2b. */
1577 for (i
= 0; i
< s
->nchars
; ++i
)
1578 char1b
[i
] = XCHAR2B_BYTE2 (&s
->char2b
[i
]);
1580 /* Draw text with TextOut and friends. */
1581 w32_text_out (s
, x
, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1583 if (s
->face
->overstrike
)
1585 /* For overstriking (to simulate bold-face), draw the
1586 characters again shifted to the right by one pixel. */
1587 w32_text_out (s
, x
+ 1, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1590 if (s
->font
&& s
->font
->hfont
)
1591 SelectObject (s
->hdc
, old_font
);
1594 /* Draw the foreground of composite glyph string S. */
1597 x_draw_composite_glyph_string_foreground (s
)
1598 struct glyph_string
*s
;
1603 /* If first glyph of S has a left box line, start drawing the text
1604 of S to the right of that box line. */
1605 if (s
->face
->box
!= FACE_NO_BOX
1606 && s
->first_glyph
->left_box_line_p
)
1607 x
= s
->x
+ abs (s
->face
->box_line_width
);
1611 /* S is a glyph string for a composition. S->gidx is the index of
1612 the first character drawn for glyphs of this composition.
1613 S->gidx == 0 means we are drawing the very first character of
1614 this composition. */
1616 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1617 SetBkColor (s
->hdc
, s
->gc
->background
);
1618 SetBkMode (s
->hdc
, TRANSPARENT
);
1619 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1621 if (s
->font
&& s
->font
->hfont
)
1622 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1624 /* Draw a rectangle for the composition if the font for the very
1625 first character of the composition could not be loaded. */
1626 if (s
->font_not_found_p
)
1629 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, s
->width
- 1,
1634 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1636 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1637 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1639 if (s
->face
->overstrike
)
1640 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1641 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1646 if (s
->font
&& s
->font
->hfont
)
1647 SelectObject (s
->hdc
, old_font
);
1651 /* Brightness beyond which a color won't have its highlight brightness
1654 Nominally, highlight colors for `3d' faces are calculated by
1655 brightening an object's color by a constant scale factor, but this
1656 doesn't yield good results for dark colors, so for colors who's
1657 brightness is less than this value (on a scale of 0-255) have to
1658 use an additional additive factor.
1660 The value here is set so that the default menu-bar/mode-line color
1661 (grey75) will not have its highlights changed at all. */
1662 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1665 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1666 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1667 If this produces the same color as COLOR, try a color where all RGB
1668 values have DELTA added. Return the allocated color in *COLOR.
1669 DISPLAY is the X display, CMAP is the colormap to operate on.
1670 Value is non-zero if successful. */
1673 w32_alloc_lighter_color (f
, color
, factor
, delta
)
1682 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1685 /* Change RGB values by specified FACTOR. Avoid overflow! */
1686 xassert (factor
>= 0);
1687 new = PALETTERGB (min (0xff, factor
* GetRValue (*color
)),
1688 min (0xff, factor
* GetGValue (*color
)),
1689 min (0xff, factor
* GetBValue (*color
)));
1691 /* Calculate brightness of COLOR. */
1692 bright
= (2 * GetRValue (*color
) + 3 * GetGValue (*color
)
1693 + GetBValue (*color
)) / 6;
1695 /* We only boost colors that are darker than
1696 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1697 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1698 /* Make an additive adjustment to NEW, because it's dark enough so
1699 that scaling by FACTOR alone isn't enough. */
1701 /* How far below the limit this color is (0 - 1, 1 being darker). */
1702 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1703 /* The additive adjustment. */
1704 int min_delta
= delta
* dimness
* factor
/ 2;
1707 new = PALETTERGB (max (0, min (0xff, min_delta
- GetRValue (*color
))),
1708 max (0, min (0xff, min_delta
- GetGValue (*color
))),
1709 max (0, min (0xff, min_delta
- GetBValue (*color
))));
1711 new = PALETTERGB (max (0, min (0xff, min_delta
+ GetRValue (*color
))),
1712 max (0, min (0xff, min_delta
+ GetGValue (*color
))),
1713 max (0, min (0xff, min_delta
+ GetBValue (*color
))));
1717 new = PALETTERGB (max (0, min (0xff, delta
+ GetRValue (*color
))),
1718 max (0, min (0xff, delta
+ GetGValue (*color
))),
1719 max (0, min (0xff, delta
+ GetBValue (*color
))));
1721 /* TODO: Map to palette and retry with delta if same? */
1722 /* TODO: Free colors (if using palette)? */
1733 /* Set up the foreground color for drawing relief lines of glyph
1734 string S. RELIEF is a pointer to a struct relief containing the GC
1735 with which lines will be drawn. Use a color that is FACTOR or
1736 DELTA lighter or darker than the relief's background which is found
1737 in S->f->output_data.x->relief_background. If such a color cannot
1738 be allocated, use DEFAULT_PIXEL, instead. */
1741 w32_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1743 struct relief
*relief
;
1746 COLORREF default_pixel
;
1749 struct w32_output
*di
= f
->output_data
.w32
;
1750 unsigned long mask
= GCForeground
;
1752 COLORREF background
= di
->relief_background
;
1753 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
1755 /* TODO: Free colors (if using palette)? */
1757 /* Allocate new color. */
1758 xgcv
.foreground
= default_pixel
;
1760 if (w32_alloc_lighter_color (f
, &pixel
, factor
, delta
))
1762 relief
->allocated_p
= 1;
1763 xgcv
.foreground
= relief
->pixel
= pixel
;
1766 if (relief
->gc
== 0)
1768 #if 0 /* TODO: stipple */
1769 xgcv
.stipple
= dpyinfo
->gray
;
1772 relief
->gc
= XCreateGC (NULL
, FRAME_W32_WINDOW (f
), mask
, &xgcv
);
1775 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
1779 /* Set up colors for the relief lines around glyph string S. */
1782 x_setup_relief_colors (s
)
1783 struct glyph_string
*s
;
1785 struct w32_output
*di
= s
->f
->output_data
.w32
;
1788 if (s
->face
->use_box_color_for_shadows_p
)
1789 color
= s
->face
->box_color
;
1790 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1792 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1793 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1795 color
= s
->gc
->background
;
1797 if (di
->white_relief
.gc
== 0
1798 || color
!= di
->relief_background
)
1800 di
->relief_background
= color
;
1801 w32_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1802 WHITE_PIX_DEFAULT (s
->f
));
1803 w32_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1804 BLACK_PIX_DEFAULT (s
->f
));
1809 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1810 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1811 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1812 relief. LEFT_P non-zero means draw a relief on the left side of
1813 the rectangle. RIGHT_P non-zero means draw a relief on the right
1814 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1818 w32_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
1819 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
1821 int left_x
, top_y
, right_x
, bottom_y
, width
;
1822 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
1827 HDC hdc
= get_frame_dc (f
);
1830 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1832 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1834 w32_set_clip_rectangle (hdc
, clip_rect
);
1838 for (i
= 0; i
< width
; ++i
)
1839 w32_fill_area (f
, hdc
, gc
.foreground
,
1840 left_x
+ i
* left_p
, top_y
+ i
,
1841 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
1845 for (i
= 0; i
< width
; ++i
)
1846 w32_fill_area (f
, hdc
, gc
.foreground
,
1847 left_x
+ i
, top_y
+ i
, 1,
1848 bottom_y
- top_y
- 2 * i
+ 1);
1851 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1853 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1857 for (i
= 0; i
< width
; ++i
)
1858 w32_fill_area (f
, hdc
, gc
.foreground
,
1859 left_x
+ i
* left_p
, bottom_y
- i
,
1860 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
1864 for (i
= 0; i
< width
; ++i
)
1865 w32_fill_area (f
, hdc
, gc
.foreground
,
1866 right_x
- i
, top_y
+ i
+ 1, 1,
1867 bottom_y
- top_y
- 2 * i
- 1);
1869 w32_set_clip_rectangle (hdc
, NULL
);
1871 release_frame_dc (f
, hdc
);
1875 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1876 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1877 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1878 left side of the rectangle. RIGHT_P non-zero means draw a line
1879 on the right side of the rectangle. CLIP_RECT is the clipping
1880 rectangle to use when drawing. */
1883 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
1884 left_p
, right_p
, clip_rect
)
1885 struct glyph_string
*s
;
1886 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
1889 w32_set_clip_rectangle (s
->hdc
, clip_rect
);
1892 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1893 left_x
, top_y
, right_x
- left_x
+ 1, width
);
1898 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1899 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
1903 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1904 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
1909 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
1910 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
1913 w32_set_clip_rectangle (s
->hdc
, NULL
);
1917 /* Draw a box around glyph string S. */
1920 x_draw_glyph_string_box (s
)
1921 struct glyph_string
*s
;
1923 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
1924 int left_p
, right_p
;
1925 struct glyph
*last_glyph
;
1928 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
1929 ? WINDOW_RIGHT_EDGE_X (s
->w
)
1930 : window_box_right (s
->w
, s
->area
));
1932 /* The glyph that may have a right box line. */
1933 last_glyph
= (s
->cmp
|| s
->img
1935 : s
->first_glyph
+ s
->nchars
- 1);
1937 width
= abs (s
->face
->box_line_width
);
1938 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
1940 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
1942 : min (last_x
, s
->x
+ s
->background_width
) - 1));
1944 bottom_y
= top_y
+ s
->height
- 1;
1946 left_p
= (s
->first_glyph
->left_box_line_p
1947 || (s
->hl
== DRAW_MOUSE_FACE
1949 || s
->prev
->hl
!= s
->hl
)));
1950 right_p
= (last_glyph
->right_box_line_p
1951 || (s
->hl
== DRAW_MOUSE_FACE
1953 || s
->next
->hl
!= s
->hl
)));
1955 get_glyph_string_clip_rect (s
, &clip_rect
);
1957 if (s
->face
->box
== FACE_SIMPLE_BOX
)
1958 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
1959 left_p
, right_p
, &clip_rect
);
1962 x_setup_relief_colors (s
);
1963 w32_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
1964 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
1969 /* Draw foreground of image glyph string S. */
1972 x_draw_image_foreground (s
)
1973 struct glyph_string
*s
;
1976 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
1978 /* If first glyph of S has a left box line, start drawing it to the
1979 right of that line. */
1980 if (s
->face
->box
!= FACE_NO_BOX
1981 && s
->first_glyph
->left_box_line_p
1983 x
+= abs (s
->face
->box_line_width
);
1985 /* If there is a margin around the image, adjust x- and y-position
1987 if (s
->slice
.x
== 0)
1988 x
+= s
->img
->hmargin
;
1989 if (s
->slice
.y
== 0)
1990 y
+= s
->img
->vmargin
;
1996 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
1997 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
1998 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
1999 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2000 SetBkColor (compat_hdc
, RGB (255, 255, 255));
2001 SetTextColor (s
->hdc
, RGB (0, 0, 0));
2002 x_set_glyph_string_clipping (s
);
2006 HDC mask_dc
= CreateCompatibleDC (s
->hdc
);
2007 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2009 SetTextColor (s
->hdc
, RGB (255, 255, 255));
2010 SetBkColor (s
->hdc
, RGB (0, 0, 0));
2012 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2013 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2014 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2015 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2016 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2017 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2019 SelectObject (mask_dc
, mask_orig_obj
);
2024 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2025 SetBkColor (s
->hdc
, s
->gc
->background
);
2027 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2028 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2030 /* When the image has a mask, we can expect that at
2031 least part of a mouse highlight or a block cursor will
2032 be visible. If the image doesn't have a mask, make
2033 a block cursor visible by drawing a rectangle around
2034 the image. I believe it's looking better if we do
2035 nothing here for mouse-face. */
2036 if (s
->hl
== DRAW_CURSOR
)
2038 int r
= s
->img
->relief
;
2040 w32_draw_rectangle (s
->hdc
, s
->gc
, x
- r
, y
- r
,
2041 s
->slice
.width
+ r
*2 - 1,
2042 s
->slice
.height
+ r
*2 - 1);
2046 w32_set_clip_rectangle (s
->hdc
, NULL
);
2047 SelectObject (s
->hdc
, orig_brush
);
2048 DeleteObject (fg_brush
);
2049 SelectObject (compat_hdc
, orig_obj
);
2050 DeleteDC (compat_hdc
);
2053 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, y
,
2054 s
->slice
.width
- 1, s
->slice
.height
- 1);
2056 RestoreDC (s
->hdc
,-1);
2060 /* Draw a relief around the image glyph string S. */
2063 x_draw_image_relief (s
)
2064 struct glyph_string
*s
;
2066 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2069 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2071 /* If first glyph of S has a left box line, start drawing it to the
2072 right of that line. */
2073 if (s
->face
->box
!= FACE_NO_BOX
2074 && s
->first_glyph
->left_box_line_p
2076 x
+= abs (s
->face
->box_line_width
);
2078 /* If there is a margin around the image, adjust x- and y-position
2080 if (s
->slice
.x
== 0)
2081 x
+= s
->img
->hmargin
;
2082 if (s
->slice
.y
== 0)
2083 y
+= s
->img
->vmargin
;
2085 if (s
->hl
== DRAW_IMAGE_SUNKEN
2086 || s
->hl
== DRAW_IMAGE_RAISED
)
2088 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2089 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2093 thick
= abs (s
->img
->relief
);
2094 raised_p
= s
->img
->relief
> 0;
2099 x1
= x
+ s
->slice
.width
+ thick
- 1;
2100 y1
= y
+ s
->slice
.height
+ thick
- 1;
2102 x_setup_relief_colors (s
);
2103 get_glyph_string_clip_rect (s
, &r
);
2104 w32_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2106 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2108 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2113 /* Draw the foreground of image glyph string S to PIXMAP. */
2116 w32_draw_image_foreground_1 (s
, pixmap
)
2117 struct glyph_string
*s
;
2120 HDC hdc
= CreateCompatibleDC (s
->hdc
);
2121 HGDIOBJ orig_hdc_obj
= SelectObject (hdc
, pixmap
);
2123 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2125 /* If first glyph of S has a left box line, start drawing it to the
2126 right of that line. */
2127 if (s
->face
->box
!= FACE_NO_BOX
2128 && s
->first_glyph
->left_box_line_p
2130 x
+= abs (s
->face
->box_line_width
);
2132 /* If there is a margin around the image, adjust x- and y-position
2134 if (s
->slice
.x
== 0)
2135 x
+= s
->img
->hmargin
;
2136 if (s
->slice
.y
== 0)
2137 y
+= s
->img
->vmargin
;
2141 HDC compat_hdc
= CreateCompatibleDC (hdc
);
2142 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2143 HBRUSH orig_brush
= SelectObject (hdc
, fg_brush
);
2144 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2148 HDC mask_dc
= CreateCompatibleDC (hdc
);
2149 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2151 SetTextColor (hdc
, RGB (0, 0, 0));
2152 SetBkColor (hdc
, RGB (255, 255, 255));
2153 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2154 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2155 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2156 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2157 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2158 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2160 SelectObject (mask_dc
, mask_orig_obj
);
2165 SetTextColor (hdc
, s
->gc
->foreground
);
2166 SetBkColor (hdc
, s
->gc
->background
);
2168 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2169 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2171 /* When the image has a mask, we can expect that at
2172 least part of a mouse highlight or a block cursor will
2173 be visible. If the image doesn't have a mask, make
2174 a block cursor visible by drawing a rectangle around
2175 the image. I believe it's looking better if we do
2176 nothing here for mouse-face. */
2177 if (s
->hl
== DRAW_CURSOR
)
2179 int r
= s
->img
->relief
;
2181 w32_draw_rectangle (hdc
, s
->gc
, x
- r
, y
- r
,
2182 s
->slice
.width
+ r
*2 - 1,
2183 s
->slice
.height
+ r
*2 - 1);
2187 SelectObject (hdc
, orig_brush
);
2188 DeleteObject (fg_brush
);
2189 SelectObject (compat_hdc
, orig_obj
);
2190 DeleteDC (compat_hdc
);
2193 w32_draw_rectangle (hdc
, s
->gc
, x
, y
,
2194 s
->slice
.width
- 1, s
->slice
.height
- 1);
2196 SelectObject (hdc
, orig_hdc_obj
);
2201 /* Draw part of the background of glyph string S. X, Y, W, and H
2202 give the rectangle to draw. */
2205 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2206 struct glyph_string
*s
;
2209 #if 0 /* TODO: stipple */
2212 /* Fill background with a stipple pattern. */
2213 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2214 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2215 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2219 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2223 /* Draw image glyph string S.
2226 s->x +-------------------------
2229 | +-------------------------
2232 | | +-------------------
2238 x_draw_image_glyph_string (s
)
2239 struct glyph_string
*s
;
2242 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2243 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2247 height
= s
->height
- 2 * box_line_vwidth
;
2249 /* Fill background with face under the image. Do it only if row is
2250 taller than image or if image has a clip mask to reduce
2252 s
->stippled_p
= s
->face
->stipple
!= 0;
2253 if (height
> s
->slice
.height
2257 || s
->img
->pixmap
== 0
2258 || s
->width
!= s
->background_width
)
2261 if (s
->first_glyph
->left_box_line_p
2263 x
+= box_line_hwidth
;
2266 if (s
->slice
.y
== 0)
2267 y
+= box_line_vwidth
;
2269 #if 0 /* TODO: figure out if we need to do this on Windows. */
2272 /* Create a pixmap as large as the glyph string. Fill it
2273 with the background color. Copy the image to it, using
2274 its mask. Copy the temporary pixmap to the display. */
2275 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2276 int depth
= DefaultDepthOfScreen (screen
);
2278 /* Create a pixmap as large as the glyph string. */
2279 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2280 s
->background_width
,
2283 /* Don't clip in the following because we're working on the
2285 XSetClipMask (s
->display
, s
->gc
, None
);
2287 /* Fill the pixmap with the background color/stipple. */
2290 /* Fill background with a stipple pattern. */
2291 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2292 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2293 0, 0, s
->background_width
, s
->height
);
2294 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2299 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2301 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2302 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2303 0, 0, s
->background_width
, s
->height
);
2304 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2309 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2311 s
->background_filled_p
= 1;
2314 /* Draw the foreground. */
2317 w32_draw_image_foreground_1 (s
, pixmap
);
2318 x_set_glyph_string_clipping (s
);
2320 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2321 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2322 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2323 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, pixmap
);
2325 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2326 SetBkColor (s
->hdc
, s
->gc
->background
);
2327 BitBlt (s
->hdc
, s
->x
, s
->y
, s
->background_width
, s
->height
,
2328 compat_hdc
, 0, 0, SRCCOPY
);
2330 SelectObject (s
->hdc
, orig_brush
);
2331 DeleteObject (fg_brush
);
2332 SelectObject (compat_hdc
, orig_obj
);
2333 DeleteDC (compat_hdc
);
2335 DeleteObject (pixmap
);
2339 x_draw_image_foreground (s
);
2341 /* If we must draw a relief around the image, do it. */
2343 || s
->hl
== DRAW_IMAGE_RAISED
2344 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2345 x_draw_image_relief (s
);
2349 /* Draw stretch glyph string S. */
2352 x_draw_stretch_glyph_string (s
)
2353 struct glyph_string
*s
;
2355 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2356 s
->stippled_p
= s
->face
->stipple
!= 0;
2358 if (s
->hl
== DRAW_CURSOR
2359 && !x_stretch_cursor_p
)
2361 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2362 as wide as the stretch glyph. */
2363 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2366 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2368 /* Clear rest using the GC of the original non-cursor face. */
2369 if (width
< s
->background_width
)
2371 XGCValues
*gc
= s
->face
->gc
;
2372 int x
= s
->x
+ width
, y
= s
->y
;
2373 int w
= s
->background_width
- width
, h
= s
->height
;
2377 if (s
->row
->mouse_face_p
2378 && cursor_in_mouse_face_p (s
->w
))
2380 x_set_mouse_face_gc (s
);
2386 get_glyph_string_clip_rect (s
, &r
);
2387 w32_set_clip_rectangle (hdc
, &r
);
2389 #if 0 /* TODO: stipple */
2390 if (s
->face
->stipple
)
2392 /* Fill background with a stipple pattern. */
2393 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2394 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2395 XSetFillStyle (s
->display
, gc
, FillSolid
);
2400 w32_fill_area (s
->f
, s
->hdc
, gc
->background
, x
, y
, w
, h
);
2404 else if (!s
->background_filled_p
)
2405 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2408 s
->background_filled_p
= 1;
2412 /* Draw glyph string S. */
2415 x_draw_glyph_string (s
)
2416 struct glyph_string
*s
;
2418 int relief_drawn_p
= 0;
2420 /* If S draws into the background of its successor, draw the
2421 background of the successor first so that S can draw into it.
2422 This makes S->next use XDrawString instead of XDrawImageString. */
2423 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2425 xassert (s
->next
->img
== NULL
);
2426 x_set_glyph_string_gc (s
->next
);
2427 x_set_glyph_string_clipping (s
->next
);
2428 x_draw_glyph_string_background (s
->next
, 1);
2431 /* Set up S->gc, set clipping and draw S. */
2432 x_set_glyph_string_gc (s
);
2434 /* Draw relief (if any) in advance for char/composition so that the
2435 glyph string can be drawn over it. */
2436 if (!s
->for_overlaps_p
2437 && s
->face
->box
!= FACE_NO_BOX
2438 && (s
->first_glyph
->type
== CHAR_GLYPH
2439 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2442 x_set_glyph_string_clipping (s
);
2443 x_draw_glyph_string_background (s
, 1);
2444 x_draw_glyph_string_box (s
);
2445 x_set_glyph_string_clipping (s
);
2449 x_set_glyph_string_clipping (s
);
2451 switch (s
->first_glyph
->type
)
2454 x_draw_image_glyph_string (s
);
2458 x_draw_stretch_glyph_string (s
);
2462 if (s
->for_overlaps_p
)
2463 s
->background_filled_p
= 1;
2465 x_draw_glyph_string_background (s
, 0);
2466 x_draw_glyph_string_foreground (s
);
2469 case COMPOSITE_GLYPH
:
2470 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2471 s
->background_filled_p
= 1;
2473 x_draw_glyph_string_background (s
, 1);
2474 x_draw_composite_glyph_string_foreground (s
);
2481 if (!s
->for_overlaps_p
)
2483 /* Draw underline. */
2484 if (s
->face
->underline_p
2485 && (s
->font
->bdf
|| !s
->font
->tm
.tmUnderlined
))
2487 unsigned long h
= 1;
2488 unsigned long dy
= s
->height
- h
;
2490 /* TODO: Use font information for positioning and thickness
2491 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
2492 if (s
->face
->underline_defaulted_p
)
2494 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2495 s
->y
+ dy
, s
->width
, 1);
2499 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2500 s
->y
+ dy
, s
->width
, 1);
2504 /* Draw overline. */
2505 if (s
->face
->overline_p
)
2507 unsigned long dy
= 0, h
= 1;
2509 if (s
->face
->overline_color_defaulted_p
)
2511 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2512 s
->y
+ dy
, s
->width
, h
);
2516 w32_fill_area (s
->f
, s
->hdc
, s
->face
->overline_color
, s
->x
,
2517 s
->y
+ dy
, s
->width
, h
);
2521 /* Draw strike-through. */
2522 if (s
->face
->strike_through_p
2523 && (s
->font
->bdf
|| !s
->font
->tm
.tmStruckOut
))
2525 unsigned long h
= 1;
2526 unsigned long dy
= (s
->height
- h
) / 2;
2528 if (s
->face
->strike_through_color_defaulted_p
)
2530 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
, s
->y
+ dy
,
2535 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2536 s
->y
+ dy
, s
->width
, h
);
2541 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2542 x_draw_glyph_string_box (s
);
2545 /* Reset clipping. */
2546 w32_set_clip_rectangle (s
->hdc
, NULL
);
2550 /* Shift display to make room for inserted glyphs. */
2553 w32_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2555 int x
, y
, width
, height
, shift_by
;
2559 hdc
= get_frame_dc (f
);
2560 BitBlt (hdc
, x
+ shift_by
, y
, width
, height
,
2561 hdc
, x
, y
, SRCCOPY
);
2563 release_frame_dc (f
, hdc
);
2567 /* Delete N glyphs at the nominal cursor position. Not implemented
2579 f
= SELECTED_FRAME ();
2581 if (! FRAME_W32_P (f
))
2588 /* Clear entire frame. If updating_frame is non-null, clear that
2589 frame. Otherwise clear the selected frame. */
2599 f
= SELECTED_FRAME ();
2601 if (! FRAME_W32_P (f
))
2604 /* Clearing the frame will erase any cursor, so mark them all as no
2606 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2607 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2608 output_cursor
.x
= -1;
2610 /* We don't set the output cursor here because there will always
2611 follow an explicit cursor_to. */
2614 w32_clear_window (f
);
2616 /* We have to clear the scroll bars, too. If we have changed
2617 colors or something like that, then they should be notified. */
2618 x_scroll_bar_clear (f
);
2624 /* Make audible bell. */
2627 w32_ring_bell (void)
2631 f
= SELECTED_FRAME ();
2635 if (FRAME_W32_P (f
) && visible_bell
)
2638 HWND hwnd
= FRAME_W32_WINDOW (SELECTED_FRAME ());
2640 for (i
= 0; i
< 5; i
++)
2642 FlashWindow (hwnd
, TRUE
);
2645 FlashWindow (hwnd
, FALSE
);
2648 w32_sys_ring_bell ();
2654 /* Specify how many text lines, from the top of the window,
2655 should be affected by insert-lines and delete-lines operations.
2656 This, and those operations, are used only within an update
2657 that is bounded by calls to x_update_begin and x_update_end. */
2660 w32_set_terminal_window (n
)
2663 /* This function intentionally left blank. */
2667 /***********************************************************************
2669 ***********************************************************************/
2671 /* Perform an insert-lines or delete-lines operation, inserting N
2672 lines or deleting -N lines at vertical position VPOS. */
2675 x_ins_del_lines (vpos
, n
)
2683 f
= SELECTED_FRAME ();
2685 if (! FRAME_W32_P (f
))
2692 /* Scroll part of the display as described by RUN. */
2695 x_scroll_run (w
, run
)
2699 struct frame
*f
= XFRAME (w
->frame
);
2700 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
2701 HWND hwnd
= FRAME_W32_WINDOW (f
);
2704 /* Get frame-relative bounding box of the text display area of W,
2705 without mode lines. Include in this box the left and right
2707 window_box (w
, -1, &x
, &y
, &width
, &height
);
2709 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
2710 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
2711 bottom_y
= y
+ height
;
2715 /* Scrolling up. Make sure we don't copy part of the mode
2716 line at the bottom. */
2717 if (from_y
+ run
->height
> bottom_y
)
2718 height
= bottom_y
- from_y
;
2720 height
= run
->height
;
2721 expect_dirty
= CreateRectRgn (x
, y
+ height
, x
+ width
, bottom_y
);
2725 /* Scolling down. Make sure we don't copy over the mode line.
2727 if (to_y
+ run
->height
> bottom_y
)
2728 height
= bottom_y
- to_y
;
2730 height
= run
->height
;
2731 expect_dirty
= CreateRectRgn (x
, y
, x
+ width
, to_y
);
2736 /* Cursor off. Will be switched on again in x_update_window_end. */
2743 HRGN dirty
= CreateRectRgn (0, 0, 0, 0);
2744 HRGN combined
= CreateRectRgn (0, 0, 0, 0);
2746 from
.left
= to
.left
= x
;
2747 from
.right
= to
.right
= x
+ width
;
2749 from
.bottom
= from_y
+ height
;
2751 to
.bottom
= bottom_y
;
2753 ScrollWindowEx (hwnd
, 0, to_y
- from_y
, &from
, &to
, dirty
,
2754 NULL
, SW_INVALIDATE
);
2756 /* Combine this with what we expect to be dirty. This covers the
2757 case where not all of the region we expect is actually dirty. */
2758 CombineRgn (combined
, dirty
, expect_dirty
, RGN_OR
);
2760 /* If the dirty region is not what we expected, redraw the entire frame. */
2761 if (!EqualRgn (combined
, expect_dirty
))
2762 SET_FRAME_GARBAGED (f
);
2764 DeleteObject (dirty
);
2765 DeleteObject (combined
);
2769 DeleteObject (expect_dirty
);
2774 /***********************************************************************
2776 ***********************************************************************/
2782 x_update_cursor (f
, 1);
2786 frame_unhighlight (f
)
2789 x_update_cursor (f
, 1);
2792 /* The focus has changed. Update the frames as necessary to reflect
2793 the new situation. Note that we can't change the selected frame
2794 here, because the Lisp code we are interrupting might become confused.
2795 Each event gets marked with the frame in which it occurred, so the
2796 Lisp code can tell when the switch took place by examining the events. */
2799 x_new_focus_frame (dpyinfo
, frame
)
2800 struct w32_display_info
*dpyinfo
;
2801 struct frame
*frame
;
2803 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
2805 if (frame
!= dpyinfo
->w32_focus_frame
)
2807 /* Set this before calling other routines, so that they see
2808 the correct value of w32_focus_frame. */
2809 dpyinfo
->w32_focus_frame
= frame
;
2811 if (old_focus
&& old_focus
->auto_lower
)
2812 x_lower_frame (old_focus
);
2814 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
2815 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
2817 pending_autoraise_frame
= 0;
2820 x_frame_rehighlight (dpyinfo
);
2824 /* Handle FocusIn and FocusOut state changes for FRAME.
2825 If FRAME has focus and there exists more than one frame, puts
2826 a FOCUS_IN_EVENT into *BUFP. */
2829 x_focus_changed (type
, state
, dpyinfo
, frame
, bufp
)
2832 struct w32_display_info
*dpyinfo
;
2833 struct frame
*frame
;
2834 struct input_event
*bufp
;
2836 if (type
== WM_SETFOCUS
)
2838 if (dpyinfo
->w32_focus_event_frame
!= frame
)
2840 x_new_focus_frame (dpyinfo
, frame
);
2841 dpyinfo
->w32_focus_event_frame
= frame
;
2843 /* Don't stop displaying the initial startup message
2844 for a switch-frame event we don't need. */
2845 if (GC_NILP (Vterminal_frame
)
2846 && GC_CONSP (Vframe_list
)
2847 && !GC_NILP (XCDR (Vframe_list
)))
2849 bufp
->kind
= FOCUS_IN_EVENT
;
2850 XSETFRAME (bufp
->frame_or_window
, frame
);
2854 frame
->output_data
.x
->focus_state
|= state
;
2856 /* TODO: IME focus? */
2858 else if (type
== WM_KILLFOCUS
)
2860 frame
->output_data
.x
->focus_state
&= ~state
;
2862 if (dpyinfo
->w32_focus_event_frame
== frame
)
2864 dpyinfo
->w32_focus_event_frame
= 0;
2865 x_new_focus_frame (dpyinfo
, 0);
2868 /* TODO: IME focus? */
2873 /* The focus may have changed. Figure out if it is a real focus change,
2874 by checking both FocusIn/Out and Enter/LeaveNotify events.
2876 Returns FOCUS_IN_EVENT event in *BUFP. */
2879 w32_detect_focus_change (dpyinfo
, event
, bufp
)
2880 struct w32_display_info
*dpyinfo
;
2882 struct input_event
*bufp
;
2884 struct frame
*frame
;
2886 frame
= x_any_window_to_frame (dpyinfo
, event
->msg
.hwnd
);
2890 /* On w32, this is only called from focus events, so no switch needed. */
2891 x_focus_changed (event
->msg
.message
,
2892 (event
->msg
.message
== WM_KILLFOCUS
?
2893 FOCUS_IMPLICIT
: FOCUS_EXPLICIT
),
2894 dpyinfo
, frame
, bufp
);
2898 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2901 x_mouse_leave (dpyinfo
)
2902 struct w32_display_info
*dpyinfo
;
2904 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
2907 /* The focus has changed, or we have redirected a frame's focus to
2908 another frame (this happens when a frame uses a surrogate
2909 mini-buffer frame). Shift the highlight as appropriate.
2911 The FRAME argument doesn't necessarily have anything to do with which
2912 frame is being highlighted or un-highlighted; we only use it to find
2913 the appropriate X display info. */
2916 w32_frame_rehighlight (frame
)
2917 struct frame
*frame
;
2919 if (! FRAME_W32_P (frame
))
2921 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
2925 x_frame_rehighlight (dpyinfo
)
2926 struct w32_display_info
*dpyinfo
;
2928 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
2930 if (dpyinfo
->w32_focus_frame
)
2932 dpyinfo
->x_highlight_frame
2933 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
2934 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
2935 : dpyinfo
->w32_focus_frame
);
2936 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
2938 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
2939 dpyinfo
->x_highlight_frame
= dpyinfo
->w32_focus_frame
;
2943 dpyinfo
->x_highlight_frame
= 0;
2945 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
2948 frame_unhighlight (old_highlight
);
2949 if (dpyinfo
->x_highlight_frame
)
2950 frame_highlight (dpyinfo
->x_highlight_frame
);
2954 /* Keyboard processing - modifier keys, etc. */
2956 /* Convert a keysym to its name. */
2959 x_get_keysym_name (keysym
)
2962 /* Make static so we can always return it */
2963 static char value
[100];
2966 GetKeyNameText (keysym
, value
, 100);
2974 /* Mouse clicks and mouse movement. Rah. */
2976 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2977 the state in PUP. XBUTTON provides extra information for extended mouse
2978 button messages. Returns FALSE if unable to parse the message. */
2980 parse_button (message
, xbutton
, pbutton
, pup
)
2991 case WM_LBUTTONDOWN
:
2999 case WM_MBUTTONDOWN
:
3000 if (NILP (Vw32_swap_mouse_buttons
))
3007 if (NILP (Vw32_swap_mouse_buttons
))
3013 case WM_RBUTTONDOWN
:
3014 if (NILP (Vw32_swap_mouse_buttons
))
3021 if (NILP (Vw32_swap_mouse_buttons
))
3027 case WM_XBUTTONDOWN
:
3028 button
= xbutton
+ 2;
3032 button
= xbutton
+ 2;
3040 if (pbutton
) *pbutton
= button
;
3046 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3048 If the event is a button press, then note that we have grabbed
3052 construct_mouse_click (result
, msg
, f
)
3053 struct input_event
*result
;
3060 parse_button (msg
->msg
.message
, HIWORD (msg
->msg
.wParam
),
3063 /* Make the event type NO_EVENT; we'll change that when we decide
3065 result
->kind
= MOUSE_CLICK_EVENT
;
3066 result
->code
= button
;
3067 result
->timestamp
= msg
->msg
.time
;
3068 result
->modifiers
= (msg
->dwModifiers
3073 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
3074 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
3075 XSETFRAME (result
->frame_or_window
, f
);
3081 construct_mouse_wheel (result
, msg
, f
)
3082 struct input_event
*result
;
3089 result
->kind
= WHEEL_EVENT
;
3091 result
->timestamp
= msg
->msg
.time
;
3093 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3094 forward, away from the user (up); a negative value indicates that
3095 the wheel was rotated backward, toward the user (down). */
3096 delta
= GET_WHEEL_DELTA_WPARAM (msg
->msg
.wParam
);
3098 /* The up and down modifiers indicate if the wheel was rotated up or
3099 down based on WHEEL_DELTA value. */
3100 result
->modifiers
= (msg
->dwModifiers
3101 | ((delta
< 0 ) ? down_modifier
: up_modifier
));
3103 p
.x
= LOWORD (msg
->msg
.lParam
);
3104 p
.y
= HIWORD (msg
->msg
.lParam
);
3105 ScreenToClient (msg
->msg
.hwnd
, &p
);
3106 XSETINT (result
->x
, p
.x
);
3107 XSETINT (result
->y
, p
.y
);
3108 XSETFRAME (result
->frame_or_window
, f
);
3114 construct_drag_n_drop (result
, msg
, f
)
3115 struct input_event
*result
;
3127 result
->kind
= DRAG_N_DROP_EVENT
;
3129 result
->timestamp
= msg
->msg
.time
;
3130 result
->modifiers
= msg
->dwModifiers
;
3132 hdrop
= (HDROP
) msg
->msg
.wParam
;
3133 DragQueryPoint (hdrop
, &p
);
3136 p
.x
= LOWORD (msg
->msg
.lParam
);
3137 p
.y
= HIWORD (msg
->msg
.lParam
);
3138 ScreenToClient (msg
->msg
.hwnd
, &p
);
3141 XSETINT (result
->x
, p
.x
);
3142 XSETINT (result
->y
, p
.y
);
3144 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
3147 for (i
= 0; i
< num_files
; i
++)
3149 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
3152 name
= alloca (len
+ 1);
3153 DragQueryFile (hdrop
, i
, name
, len
+ 1);
3154 files
= Fcons (DECODE_FILE (build_string (name
)), files
);
3159 XSETFRAME (frame
, f
);
3160 result
->frame_or_window
= Fcons (frame
, files
);
3166 /* Function to report a mouse movement to the mainstream Emacs code.
3167 The input handler calls this.
3169 We have received a mouse movement event, which is given in *event.
3170 If the mouse is over a different glyph than it was last time, tell
3171 the mainstream emacs code by setting mouse_moved. If not, ask for
3172 another motion event, so we can check again the next time it moves. */
3174 static MSG last_mouse_motion_event
;
3175 static Lisp_Object last_mouse_motion_frame
;
3177 static void remember_mouse_glyph
P_ ((struct frame
*, int, int));
3180 note_mouse_movement (frame
, msg
)
3184 int mouse_x
= LOWORD (msg
->lParam
);
3185 int mouse_y
= HIWORD (msg
->lParam
);
3187 last_mouse_movement_time
= msg
->time
;
3188 memcpy (&last_mouse_motion_event
, msg
, sizeof (last_mouse_motion_event
));
3189 XSETFRAME (last_mouse_motion_frame
, frame
);
3191 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
3193 frame
->mouse_moved
= 1;
3194 last_mouse_scroll_bar
= Qnil
;
3195 note_mouse_highlight (frame
, -1, -1);
3198 /* Has the mouse moved off the glyph it was on at the last sighting? */
3199 else if (mouse_x
< last_mouse_glyph
.left
3200 || mouse_x
> last_mouse_glyph
.right
3201 || mouse_y
< last_mouse_glyph
.top
3202 || mouse_y
> last_mouse_glyph
.bottom
)
3204 frame
->mouse_moved
= 1;
3205 last_mouse_scroll_bar
= Qnil
;
3206 note_mouse_highlight (frame
, mouse_x
, mouse_y
);
3207 /* Remember the mouse position here, as w32_mouse_position only
3208 gets called when mouse tracking is enabled but we also need
3209 to keep track of the mouse for help_echo and highlighting at
3211 remember_mouse_glyph (frame
, mouse_x
, mouse_y
);
3216 /************************************************************************
3218 ************************************************************************/
3220 static struct scroll_bar
*x_window_to_scroll_bar ();
3221 static void x_scroll_bar_report_motion ();
3222 static void x_check_fullscreen
P_ ((struct frame
*));
3223 static int glyph_rect
P_ ((struct frame
*f
, int, int, RECT
*));
3227 redo_mouse_highlight ()
3229 if (!NILP (last_mouse_motion_frame
)
3230 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3231 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3232 LOWORD (last_mouse_motion_event
.lParam
),
3233 HIWORD (last_mouse_motion_event
.lParam
));
3237 w32_define_cursor (window
, cursor
)
3241 PostMessage (window
, WM_EMACS_SETCURSOR
, (WPARAM
) cursor
, 0);
3244 /* Try to determine frame pixel position and size of the glyph under
3245 frame pixel coordinates X/Y on frame F . Return the position and
3246 size in *RECT. Value is non-zero if we could compute these
3250 glyph_rect (f
, x
, y
, rect
)
3257 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3261 struct window
*w
= XWINDOW (window
);
3262 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3263 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3265 for (; r
< end
&& r
->enabled_p
; ++r
)
3266 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3268 /* Found the row at y. */
3269 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3270 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3273 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3274 rect
->bottom
= rect
->top
+ r
->height
;
3278 /* x is to the left of the first glyph in the row. */
3279 /* Shouldn't this be a pixel value?
3280 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3282 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3283 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3287 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3288 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3290 /* x is on a glyph. */
3291 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3292 rect
->right
= rect
->left
+ g
->pixel_width
;
3296 /* x is to the right of the last glyph in the row. */
3297 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3298 /* Shouldn't this be a pixel value?
3299 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3301 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3306 /* The y is not on any row. */
3310 /* Record the position of the mouse in last_mouse_glyph. */
3312 remember_mouse_glyph (f1
, gx
, gy
)
3316 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3318 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3319 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3321 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3322 round down even for negative values. */
3328 /* This was the original code from XTmouse_position, but it seems
3329 to give the position of the glyph diagonally next to the one
3330 the mouse is over. */
3331 gx
= (gx
+ width
- 1) / width
* width
;
3332 gy
= (gy
+ height
- 1) / height
* height
;
3334 gx
= gx
/ width
* width
;
3335 gy
= gy
/ height
* height
;
3338 last_mouse_glyph
.left
= gx
;
3339 last_mouse_glyph
.top
= gy
;
3340 last_mouse_glyph
.right
= gx
+ width
;
3341 last_mouse_glyph
.bottom
= gy
+ height
;
3345 /* Return the current position of the mouse.
3346 *fp should be a frame which indicates which display to ask about.
3348 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3349 and *part to the frame, window, and scroll bar part that the mouse
3350 is over. Set *x and *y to the portion and whole of the mouse's
3351 position on the scroll bar.
3353 If the mouse movement started elsewhere, set *fp to the frame the
3354 mouse is on, *bar_window to nil, and *x and *y to the character cell
3357 Set *time to the server time-stamp for the time at which the mouse
3358 was at this position.
3360 Don't store anything if we don't have a valid set of values to report.
3362 This clears the mouse_moved flag, so we can wait for the next mouse
3366 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3369 Lisp_Object
*bar_window
;
3370 enum scroll_bar_part
*part
;
3372 unsigned long *time
;
3378 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3379 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3384 Lisp_Object frame
, tail
;
3386 /* Clear the mouse-moved flag for every frame on this display. */
3387 FOR_EACH_FRAME (tail
, frame
)
3388 XFRAME (frame
)->mouse_moved
= 0;
3390 last_mouse_scroll_bar
= Qnil
;
3394 /* Now we have a position on the root; find the innermost window
3395 containing the pointer. */
3397 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3398 && FRAME_LIVE_P (last_mouse_frame
))
3400 /* If mouse was grabbed on a frame, give coords for that frame
3401 even if the mouse is now outside it. */
3402 f1
= last_mouse_frame
;
3406 /* Is window under mouse one of our frames? */
3407 f1
= x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
),
3408 WindowFromPoint (pt
));
3411 /* If not, is it one of our scroll bars? */
3414 struct scroll_bar
*bar
3415 = x_window_to_scroll_bar (WindowFromPoint (pt
));
3419 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3423 if (f1
== 0 && insist
> 0)
3424 f1
= SELECTED_FRAME ();
3428 /* Ok, we found a frame. Store all the values.
3429 last_mouse_glyph is a rectangle used to reduce the
3430 generation of mouse events. To not miss any motion
3431 events, we must divide the frame into rectangles of the
3432 size of the smallest character that could be displayed
3433 on it, i.e. into the same rectangles that matrices on
3434 the frame are divided into. */
3436 #if OLD_REDISPLAY_CODE
3437 int ignore1
, ignore2
;
3439 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3441 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
3443 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
3446 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3447 remember_mouse_glyph (f1
, pt
.x
, pt
.y
);
3455 *time
= last_mouse_movement_time
;
3464 /***********************************************************************
3466 ***********************************************************************/
3468 /* Handle mouse button event on the tool-bar of frame F, at
3469 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3473 w32_handle_tool_bar_click (f
, button_event
)
3475 struct input_event
*button_event
;
3477 int x
= XFASTINT (button_event
->x
);
3478 int y
= XFASTINT (button_event
->y
);
3480 if (button_event
->modifiers
& down_modifier
)
3481 handle_tool_bar_click (f
, x
, y
, 1, 0);
3483 handle_tool_bar_click (f
, x
, y
, 0,
3484 button_event
->modifiers
& ~up_modifier
);
3489 /***********************************************************************
3491 ***********************************************************************/
3493 /* Scroll bar support. */
3495 /* Given a window ID, find the struct scroll_bar which manages it.
3496 This can be called in GC, so we have to make sure to strip off mark
3499 static struct scroll_bar
*
3500 x_window_to_scroll_bar (window_id
)
3505 for (tail
= Vframe_list
;
3506 XGCTYPE (tail
) == Lisp_Cons
;
3509 Lisp_Object frame
, bar
, condemned
;
3511 frame
= XCAR (tail
);
3512 /* All elements of Vframe_list should be frames. */
3513 if (! GC_FRAMEP (frame
))
3516 /* Scan this frame's scroll bar list for a scroll bar with the
3518 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3519 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3520 /* This trick allows us to search both the ordinary and
3521 condemned scroll bar lists with one loop. */
3522 ! GC_NILP (bar
) || (bar
= condemned
,
3525 bar
= XSCROLL_BAR (bar
)->next
)
3526 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
3527 return XSCROLL_BAR (bar
);
3535 /* Set the thumb size and position of scroll bar BAR. We are currently
3536 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3539 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
)
3540 struct scroll_bar
*bar
;
3541 int portion
, position
, whole
;
3543 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3544 double range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3545 int sb_page
, sb_pos
;
3546 BOOL draggingp
= !NILP (bar
->dragging
) ? TRUE
: FALSE
;
3550 /* Position scroll bar at rock bottom if the bottom of the
3551 buffer is visible. This avoids shinking the thumb away
3552 to nothing if it is held at the bottom of the buffer. */
3553 if (position
+ portion
>= whole
)
3555 sb_page
= range
* (whole
- position
) / whole
3556 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3560 sb_page
= portion
* range
/ whole
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3561 sb_pos
= position
* range
/ whole
;
3571 if (pfnSetScrollInfo
)
3575 si
.cbSize
= sizeof (si
);
3576 /* Only update page size if currently dragging, to reduce
3579 si
.fMask
= SIF_PAGE
;
3581 si
.fMask
= SIF_PAGE
| SIF_POS
;
3585 pfnSetScrollInfo (w
, SB_CTL
, &si
, !draggingp
);
3588 SetScrollPos (w
, SB_CTL
, sb_pos
, !draggingp
);
3594 /************************************************************************
3595 Scroll bars, general
3596 ************************************************************************/
3599 my_create_scrollbar (f
, bar
)
3601 struct scroll_bar
* bar
;
3603 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
3604 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
3608 /*#define ATTACH_THREADS*/
3611 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
3613 #ifndef ATTACH_THREADS
3614 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
3615 (WPARAM
) hwnd
, (LPARAM
) how
);
3617 return ShowWindow (hwnd
, how
);
3622 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
3623 int x
, int y
, int cx
, int cy
, UINT flags
)
3625 #ifndef ATTACH_THREADS
3627 pos
.hwndInsertAfter
= hwndAfter
;
3633 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
3635 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
3640 my_set_focus (f
, hwnd
)
3644 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
3649 my_set_foreground_window (hwnd
)
3652 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
3656 my_destroy_window (f
, hwnd
)
3660 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
3664 /* Create a scroll bar and return the scroll bar vector for it. W is
3665 the Emacs window on which to create the scroll bar. TOP, LEFT,
3666 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3669 static struct scroll_bar
*
3670 x_scroll_bar_create (w
, top
, left
, width
, height
)
3672 int top
, left
, width
, height
;
3674 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3676 struct scroll_bar
*bar
3677 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
3681 XSETWINDOW (bar
->window
, w
);
3682 XSETINT (bar
->top
, top
);
3683 XSETINT (bar
->left
, left
);
3684 XSETINT (bar
->width
, width
);
3685 XSETINT (bar
->height
, height
);
3686 XSETINT (bar
->start
, 0);
3687 XSETINT (bar
->end
, 0);
3688 bar
->dragging
= Qnil
;
3690 /* Requires geometry to be set before call to create the real window */
3692 hwnd
= my_create_scrollbar (f
, bar
);
3694 if (pfnSetScrollInfo
)
3698 si
.cbSize
= sizeof (si
);
3701 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3702 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3706 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3710 SetScrollRange (hwnd
, SB_CTL
, 0,
3711 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
3712 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
3715 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
3717 /* Add bar to its frame's list of scroll bars. */
3718 bar
->next
= FRAME_SCROLL_BARS (f
);
3720 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3721 if (! NILP (bar
->next
))
3722 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3730 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3734 x_scroll_bar_remove (bar
)
3735 struct scroll_bar
*bar
;
3737 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3741 /* Destroy the window. */
3742 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
3744 /* Disassociate this scroll bar from its window. */
3745 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3750 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3751 that we are displaying PORTION characters out of a total of WHOLE
3752 characters, starting at POSITION. If WINDOW has no scroll bar,
3755 w32_set_vertical_scroll_bar (w
, portion
, whole
, position
)
3757 int portion
, whole
, position
;
3759 struct frame
*f
= XFRAME (w
->frame
);
3760 struct scroll_bar
*bar
;
3761 int top
, height
, left
, sb_left
, width
, sb_width
;
3762 int window_y
, window_height
;
3764 /* Get window dimensions. */
3765 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
3767 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
3768 height
= window_height
;
3770 /* Compute the left edge of the scroll bar area. */
3771 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
3773 /* Compute the width of the scroll bar which might be less than
3774 the width of the area reserved for the scroll bar. */
3775 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
3776 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
3780 /* Compute the left edge of the scroll bar. */
3781 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
3782 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
3784 sb_left
= left
+ (width
- sb_width
) / 2;
3786 /* Does the scroll bar exist yet? */
3787 if (NILP (w
->vertical_scroll_bar
))
3791 if (width
> 0 && height
> 0)
3793 hdc
= get_frame_dc (f
);
3794 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
3795 release_frame_dc (f
, hdc
);
3799 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
3803 /* It may just need to be moved and resized. */
3806 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
3807 hwnd
= SCROLL_BAR_W32_WINDOW (bar
);
3809 /* If already correctly positioned, do nothing. */
3810 if ( XINT (bar
->left
) == sb_left
3811 && XINT (bar
->top
) == top
3812 && XINT (bar
->width
) == sb_width
3813 && XINT (bar
->height
) == height
)
3815 /* Redraw after clear_frame. */
3816 if (!my_show_window (f
, hwnd
, SW_NORMAL
))
3817 InvalidateRect (hwnd
, NULL
, FALSE
);
3823 if (width
&& height
)
3825 hdc
= get_frame_dc (f
);
3826 /* Since Windows scroll bars are smaller than the space reserved
3827 for them on the frame, we have to clear "under" them. */
3828 w32_clear_area (f
, hdc
,
3833 release_frame_dc (f
, hdc
);
3835 /* Make sure scroll bar is "visible" before moving, to ensure the
3836 area of the parent window now exposed will be refreshed. */
3837 my_show_window (f
, hwnd
, SW_HIDE
);
3838 MoveWindow (hwnd
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
3839 top
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
3840 max (height
, 1), TRUE
);
3841 if (pfnSetScrollInfo
)
3845 si
.cbSize
= sizeof (si
);
3846 si
.fMask
= SIF_RANGE
;
3848 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3849 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3851 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3854 SetScrollRange (hwnd
, SB_CTL
, 0,
3855 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
3856 my_show_window (f
, hwnd
, SW_NORMAL
);
3857 /* InvalidateRect (w, NULL, FALSE); */
3859 /* Remember new settings. */
3860 XSETINT (bar
->left
, sb_left
);
3861 XSETINT (bar
->top
, top
);
3862 XSETINT (bar
->width
, sb_width
);
3863 XSETINT (bar
->height
, height
);
3868 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
3870 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
3874 /* The following three hooks are used when we're doing a thorough
3875 redisplay of the frame. We don't explicitly know which scroll bars
3876 are going to be deleted, because keeping track of when windows go
3877 away is a real pain - "Can you say set-window-configuration, boys
3878 and girls?" Instead, we just assert at the beginning of redisplay
3879 that *all* scroll bars are to be removed, and then save a scroll bar
3880 from the fiery pit when we actually redisplay its window. */
3882 /* Arrange for all scroll bars on FRAME to be removed at the next call
3883 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3884 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3887 w32_condemn_scroll_bars (frame
)
3890 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3891 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3894 bar
= FRAME_SCROLL_BARS (frame
);
3895 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3896 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3897 XSCROLL_BAR (bar
)->prev
= Qnil
;
3898 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3899 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3900 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3905 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3906 Note that WINDOW isn't necessarily condemned at all. */
3909 w32_redeem_scroll_bar (window
)
3910 struct window
*window
;
3912 struct scroll_bar
*bar
;
3915 /* We can't redeem this window's scroll bar if it doesn't have one. */
3916 if (NILP (window
->vertical_scroll_bar
))
3919 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3921 /* Unlink it from the condemned list. */
3922 f
= XFRAME (WINDOW_FRAME (window
));
3923 if (NILP (bar
->prev
))
3925 /* If the prev pointer is nil, it must be the first in one of
3927 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3928 /* It's not condemned. Everything's fine. */
3930 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3931 window
->vertical_scroll_bar
))
3932 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3934 /* If its prev pointer is nil, it must be at the front of
3935 one or the other! */
3939 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3941 if (! NILP (bar
->next
))
3942 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3944 bar
->next
= FRAME_SCROLL_BARS (f
);
3946 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3947 if (! NILP (bar
->next
))
3948 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3951 /* Remove all scroll bars on FRAME that haven't been saved since the
3952 last call to `*condemn_scroll_bars_hook'. */
3955 w32_judge_scroll_bars (f
)
3958 Lisp_Object bar
, next
;
3960 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3962 /* Clear out the condemned list now so we won't try to process any
3963 more events on the hapless scroll bars. */
3964 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3966 for (; ! NILP (bar
); bar
= next
)
3968 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3970 x_scroll_bar_remove (b
);
3973 b
->next
= b
->prev
= Qnil
;
3976 /* Now there should be no references to the condemned scroll bars,
3977 and they should get garbage-collected. */
3980 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3981 is set to something other than NO_EVENT, it is enqueued.
3983 This may be called from a signal handler, so we have to ignore GC
3987 w32_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3988 struct scroll_bar
*bar
;
3990 struct input_event
*emacs_event
;
3992 if (! GC_WINDOWP (bar
->window
))
3995 emacs_event
->kind
= W32_SCROLL_BAR_CLICK_EVENT
;
3996 emacs_event
->code
= 0;
3997 /* not really meaningful to distinguish up/down */
3998 emacs_event
->modifiers
= msg
->dwModifiers
;
3999 emacs_event
->frame_or_window
= bar
->window
;
4000 emacs_event
->arg
= Qnil
;
4001 emacs_event
->timestamp
= msg
->msg
.time
;
4004 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4006 int dragging
= !NILP (bar
->dragging
);
4008 if (pfnGetScrollInfo
)
4012 si
.cbSize
= sizeof (si
);
4015 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
4019 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
4021 bar
->dragging
= Qnil
;
4024 last_mouse_scroll_bar_pos
= msg
->msg
.wParam
;
4026 switch (LOWORD (msg
->msg
.wParam
))
4029 emacs_event
->part
= scroll_bar_down_arrow
;
4032 emacs_event
->part
= scroll_bar_up_arrow
;
4035 emacs_event
->part
= scroll_bar_above_handle
;
4038 emacs_event
->part
= scroll_bar_below_handle
;
4041 emacs_event
->part
= scroll_bar_handle
;
4045 emacs_event
->part
= scroll_bar_handle
;
4049 case SB_THUMBPOSITION
:
4050 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4051 y
= HIWORD (msg
->msg
.wParam
);
4053 emacs_event
->part
= scroll_bar_handle
;
4055 /* "Silently" update current position. */
4056 if (pfnSetScrollInfo
)
4060 si
.cbSize
= sizeof (si
);
4063 /* Remember apparent position (we actually lag behind the real
4064 position, so don't set that directly. */
4065 last_scroll_bar_drag_pos
= y
;
4067 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
4070 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
4073 /* If this is the end of a drag sequence, then reset the scroll
4074 handle size to normal and do a final redraw. Otherwise do
4078 if (pfnSetScrollInfo
)
4081 int start
= XINT (bar
->start
);
4082 int end
= XINT (bar
->end
);
4084 si
.cbSize
= sizeof (si
);
4085 si
.fMask
= SIF_PAGE
| SIF_POS
;
4086 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4087 si
.nPos
= last_scroll_bar_drag_pos
;
4088 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
4091 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
4095 emacs_event
->kind
= NO_EVENT
;
4099 XSETINT (emacs_event
->x
, y
);
4100 XSETINT (emacs_event
->y
, top_range
);
4106 /* Return information to the user about the current position of the mouse
4107 on the scroll bar. */
4110 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4112 Lisp_Object
*bar_window
;
4113 enum scroll_bar_part
*part
;
4115 unsigned long *time
;
4117 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4118 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
4119 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4121 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4126 *bar_window
= bar
->window
;
4128 if (pfnGetScrollInfo
)
4132 si
.cbSize
= sizeof (si
);
4133 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
4135 pfnGetScrollInfo (w
, SB_CTL
, &si
);
4137 top_range
= si
.nMax
- si
.nPage
+ 1;
4140 pos
= GetScrollPos (w
, SB_CTL
);
4142 switch (LOWORD (last_mouse_scroll_bar_pos
))
4144 case SB_THUMBPOSITION
:
4146 *part
= scroll_bar_handle
;
4147 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4148 pos
= HIWORD (last_mouse_scroll_bar_pos
);
4151 *part
= scroll_bar_handle
;
4155 *part
= scroll_bar_handle
;
4160 XSETINT (*y
, top_range
);
4163 last_mouse_scroll_bar
= Qnil
;
4165 *time
= last_mouse_movement_time
;
4171 /* The screen has been cleared so we may have changed foreground or
4172 background colors, and the scroll bars may need to be redrawn.
4173 Clear out the scroll bars, and ask for expose events, so we can
4177 x_scroll_bar_clear (f
)
4182 /* We can have scroll bars even if this is 0,
4183 if we just turned off scroll bar mode.
4184 But in that case we should not clear them. */
4185 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4186 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
4187 bar
= XSCROLL_BAR (bar
)->next
)
4189 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
4190 HDC hdc
= GetDC (window
);
4193 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4194 arranges to refresh the scroll bar if hidden. */
4195 my_show_window (f
, window
, SW_HIDE
);
4197 GetClientRect (window
, &rect
);
4198 select_palette (f
, hdc
);
4199 w32_clear_rect (f
, hdc
, &rect
);
4200 deselect_palette (f
, hdc
);
4202 ReleaseDC (window
, hdc
);
4207 /* The main W32 event-reading loop - w32_read_socket. */
4209 /* Record the last 100 characters stored
4210 to help debug the loss-of-chars-during-GC problem. */
4212 static int temp_index
;
4213 static short temp_buffer
[100];
4216 /* Read events coming from the W32 shell.
4217 This routine is called by the SIGIO handler.
4218 We return as soon as there are no more events to be read.
4220 We return the number of characters stored into the buffer,
4221 thus pretending to be `read'.
4223 EXPECTED is nonzero if the caller knows input is available.
4225 Some of these messages are reposted back to the message queue since the
4226 system calls the windows proc directly in a context where we cannot return
4227 the data nor can we guarantee the state we are in. So if we dispatch them
4228 we will get into an infinite loop. To prevent this from ever happening we
4229 will set a variable to indicate we are in the read_socket call and indicate
4230 which message we are processing since the windows proc gets called
4231 recursively with different messages by the system.
4235 w32_read_socket (sd
, expected
, hold_quit
)
4238 struct input_event
*hold_quit
;
4241 int check_visibility
= 0;
4244 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4246 if (interrupt_input_blocked
)
4248 interrupt_input_pending
= 1;
4252 interrupt_input_pending
= 0;
4255 /* So people can tell when we have read the available input. */
4256 input_signal_count
++;
4258 /* TODO: ghostscript integration. */
4259 while (get_next_msg (&msg
, FALSE
))
4261 struct input_event inev
;
4265 inev
.kind
= NO_EVENT
;
4268 switch (msg
.msg
.message
)
4271 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4275 if (msg
.rect
.right
== msg
.rect
.left
||
4276 msg
.rect
.bottom
== msg
.rect
.top
)
4278 /* We may get paint messages even though the client
4279 area is clipped - these are not expose events. */
4280 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f
,
4283 else if (f
->async_visible
!= 1)
4285 /* Definitely not obscured, so mark as visible. */
4286 f
->async_visible
= 1;
4287 f
->async_iconified
= 0;
4288 SET_FRAME_GARBAGED (f
);
4289 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f
,
4292 /* WM_PAINT serves as MapNotify as well, so report
4293 visibility changes properly. */
4296 inev
.kind
= DEICONIFY_EVENT
;
4297 XSETFRAME (inev
.frame_or_window
, f
);
4299 else if (! NILP (Vframe_list
)
4300 && ! NILP (XCDR (Vframe_list
)))
4301 /* Force a redisplay sooner or later to update the
4302 frame titles in case this is the second frame. */
4303 record_asynch_buffer_change ();
4307 HDC hdc
= get_frame_dc (f
);
4309 /* Erase background again for safety. */
4310 w32_clear_rect (f
, hdc
, &msg
.rect
);
4311 release_frame_dc (f
, hdc
);
4315 msg
.rect
.right
- msg
.rect
.left
,
4316 msg
.rect
.bottom
- msg
.rect
.top
);
4321 case WM_INPUTLANGCHANGE
:
4322 /* Generate a language change event. */
4323 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4327 inev
.kind
= LANGUAGE_CHANGE_EVENT
;
4328 XSETFRAME (inev
.frame_or_window
, f
);
4329 inev
.code
= msg
.msg
.wParam
;
4330 inev
.modifiers
= msg
.msg
.lParam
& 0xffff;
4336 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4338 if (f
&& !f
->iconified
)
4340 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
4342 clear_mouse_face (dpyinfo
);
4343 dpyinfo
->mouse_face_hidden
= 1;
4346 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4348 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4349 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
4350 inev
.code
= msg
.msg
.wParam
;
4351 inev
.modifiers
= msg
.dwModifiers
;
4352 XSETFRAME (inev
.frame_or_window
, f
);
4353 inev
.timestamp
= msg
.msg
.time
;
4359 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4361 if (f
&& !f
->iconified
)
4363 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
4365 clear_mouse_face (dpyinfo
);
4366 dpyinfo
->mouse_face_hidden
= 1;
4369 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4371 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4372 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
4373 inev
.code
= msg
.msg
.wParam
;
4374 inev
.modifiers
= msg
.dwModifiers
;
4375 XSETFRAME (inev
.frame_or_window
, f
);
4376 inev
.timestamp
= msg
.msg
.time
;
4381 /* Ignore non-movement. */
4383 int x
= LOWORD (msg
.msg
.lParam
);
4384 int y
= HIWORD (msg
.msg
.lParam
);
4385 if (x
== last_mousemove_x
&& y
== last_mousemove_y
)
4387 last_mousemove_x
= x
;
4388 last_mousemove_y
= y
;
4391 previous_help_echo_string
= help_echo_string
;
4393 if (dpyinfo
->grabbed
&& last_mouse_frame
4394 && FRAME_LIVE_P (last_mouse_frame
))
4395 f
= last_mouse_frame
;
4397 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4399 if (dpyinfo
->mouse_face_hidden
)
4401 dpyinfo
->mouse_face_hidden
= 0;
4402 clear_mouse_face (dpyinfo
);
4407 /* Generate SELECT_WINDOW_EVENTs when needed. */
4408 if (mouse_autoselect_window
)
4411 int x
= LOWORD (msg
.msg
.lParam
);
4412 int y
= HIWORD (msg
.msg
.lParam
);
4414 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 0);
4416 /* Window will be selected only when it is not
4417 selected now and last mouse movement event was
4418 not in it. Minibuffer window will be selected
4419 iff it is active. */
4421 && !EQ (window
, last_window
)
4422 && !EQ (window
, selected_window
))
4424 inev
.kind
= SELECT_WINDOW_EVENT
;
4425 inev
.frame_or_window
= window
;
4430 note_mouse_movement (f
, &msg
.msg
);
4434 /* If we move outside the frame, then we're
4435 certainly no longer on any text in the frame. */
4436 clear_mouse_face (dpyinfo
);
4439 /* If the contents of the global variable help_echo_string
4440 has changed, generate a HELP_EVENT. */
4441 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4442 But it was originally changed to this to fix a bug, so I have
4443 not removed it completely in case the bug is still there. */
4444 if (help_echo_string
!= previous_help_echo_string
||
4445 (!NILP (help_echo_string
) && !STRINGP (help_echo_string
) && f
->mouse_moved
))
4446 #else /* This is what xterm.c does. */
4447 if (!NILP (help_echo_string
)
4448 || !NILP (previous_help_echo_string
))
4453 case WM_LBUTTONDOWN
:
4455 case WM_MBUTTONDOWN
:
4457 case WM_RBUTTONDOWN
:
4459 case WM_XBUTTONDOWN
:
4462 /* If we decide we want to generate an event to be seen
4463 by the rest of Emacs, we put it here. */
4468 if (dpyinfo
->grabbed
&& last_mouse_frame
4469 && FRAME_LIVE_P (last_mouse_frame
))
4470 f
= last_mouse_frame
;
4472 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4476 construct_mouse_click (&inev
, &msg
, f
);
4478 /* Is this in the tool-bar? */
4479 if (WINDOWP (f
->tool_bar_window
)
4480 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
4483 int x
= XFASTINT (inev
.x
);
4484 int y
= XFASTINT (inev
.y
);
4486 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
4488 if (EQ (window
, f
->tool_bar_window
))
4490 w32_handle_tool_bar_click (f
, &inev
);
4496 || (dpyinfo
->w32_focus_frame
4497 && f
!= dpyinfo
->w32_focus_frame
))
4498 inev
.kind
= NO_EVENT
;
4501 parse_button (msg
.msg
.message
, HIWORD (msg
.msg
.wParam
),
4506 dpyinfo
->grabbed
&= ~ (1 << button
);
4510 dpyinfo
->grabbed
|= (1 << button
);
4511 last_mouse_frame
= f
;
4512 /* Ignore any mouse motion that happened
4513 before this event; any subsequent mouse-movement
4514 Emacs events should reflect only motion after
4520 last_tool_bar_item
= -1;
4527 if (dpyinfo
->grabbed
&& last_mouse_frame
4528 && FRAME_LIVE_P (last_mouse_frame
))
4529 f
= last_mouse_frame
;
4531 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4536 if (!dpyinfo
->w32_focus_frame
4537 || f
== dpyinfo
->w32_focus_frame
)
4539 /* Emit an Emacs wheel-up/down event. */
4540 construct_mouse_wheel (&inev
, &msg
, f
);
4542 /* Ignore any mouse motion that happened before this
4543 event; any subsequent mouse-movement Emacs events
4544 should reflect only motion after the
4548 last_mouse_frame
= f
;
4549 last_tool_bar_item
= -1;
4554 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4557 construct_drag_n_drop (&inev
, &msg
, f
);
4562 struct scroll_bar
*bar
=
4563 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
4566 w32_scroll_bar_handle_click (bar
, &msg
, &inev
);
4570 case WM_WINDOWPOSCHANGED
:
4571 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4574 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
4575 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
4577 check_visibility
= 1;
4581 case WM_ACTIVATEAPP
:
4582 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4584 x_check_fullscreen (f
);
4585 check_visibility
= 1;
4589 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4591 if (f
&& !f
->async_iconified
)
4595 x_real_positions (f
, &x
, &y
);
4600 check_visibility
= 1;
4604 /* wParam non-zero means Window is about to be shown, 0 means
4605 about to be hidden. */
4606 /* Redo the mouse-highlight after the tooltip has gone. */
4607 if (!msg
.msg
.wParam
&& msg
.msg
.hwnd
== tip_window
)
4610 redo_mouse_highlight ();
4613 /* If window has been obscured or exposed by another window
4614 being maximised or minimised/restored, then recheck
4615 visibility of all frames. Direct changes to our own
4616 windows get handled by WM_SIZE. */
4618 if (msg
.msg
.lParam
!= 0)
4619 check_visibility
= 1;
4622 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4623 f
->async_visible
= msg
.msg
.wParam
;
4627 check_visibility
= 1;
4631 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4633 /* Inform lisp of whether frame has been iconified etc. */
4636 switch (msg
.msg
.wParam
)
4638 case SIZE_MINIMIZED
:
4639 f
->async_visible
= 0;
4640 f
->async_iconified
= 1;
4642 inev
.kind
= ICONIFY_EVENT
;
4643 XSETFRAME (inev
.frame_or_window
, f
);
4646 case SIZE_MAXIMIZED
:
4648 f
->async_visible
= 1;
4649 f
->async_iconified
= 0;
4651 /* wait_reading_process_output will notice this and update
4652 the frame's display structures. */
4653 SET_FRAME_GARBAGED (f
);
4659 /* Reset top and left positions of the Window
4660 here since Windows sends a WM_MOVE message
4661 BEFORE telling us the Window is minimized
4662 when the Window is iconified, with 3000,3000
4664 x_real_positions (f
, &x
, &y
);
4668 inev
.kind
= DEICONIFY_EVENT
;
4669 XSETFRAME (inev
.frame_or_window
, f
);
4671 else if (! NILP (Vframe_list
)
4672 && ! NILP (XCDR (Vframe_list
)))
4673 /* Force a redisplay sooner or later
4674 to update the frame titles
4675 in case this is the second frame. */
4676 record_asynch_buffer_change ();
4681 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
4689 GetClientRect (msg
.msg
.hwnd
, &rect
);
4691 height
= rect
.bottom
- rect
.top
;
4692 width
= rect
.right
- rect
.left
;
4694 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
4695 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
4697 /* TODO: Clip size to the screen dimensions. */
4699 /* Even if the number of character rows and columns has
4700 not changed, the font size may have changed, so we need
4701 to check the pixel dimensions as well. */
4703 if (columns
!= FRAME_COLS (f
)
4704 || rows
!= FRAME_LINES (f
)
4705 || width
!= FRAME_PIXEL_WIDTH (f
)
4706 || height
!= FRAME_PIXEL_HEIGHT (f
))
4708 change_frame_size (f
, rows
, columns
, 0, 1, 0);
4709 SET_FRAME_GARBAGED (f
);
4710 cancel_mouse_face (f
);
4711 FRAME_PIXEL_WIDTH (f
) = width
;
4712 FRAME_PIXEL_HEIGHT (f
) = height
;
4713 f
->win_gravity
= NorthWestGravity
;
4717 check_visibility
= 1;
4721 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4724 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4726 /* If we move outside the frame, then we're
4727 certainly no longer on any text in the frame. */
4728 clear_mouse_face (dpyinfo
);
4729 dpyinfo
->mouse_face_mouse_frame
= 0;
4732 /* Generate a nil HELP_EVENT to cancel a help-echo.
4733 Do it only if there's something to cancel.
4734 Otherwise, the startup message is cleared when
4735 the mouse leaves the frame. */
4736 if (any_help_event_p
)
4742 w32_detect_focus_change (dpyinfo
, &msg
, &inev
);
4744 dpyinfo
->grabbed
= 0;
4745 check_visibility
= 1;
4749 f
= x_top_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4753 if (f
== dpyinfo
->w32_focus_event_frame
)
4754 dpyinfo
->w32_focus_event_frame
= 0;
4756 if (f
== dpyinfo
->w32_focus_frame
)
4757 x_new_focus_frame (dpyinfo
, 0);
4759 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4761 /* If we move outside the frame, then we're
4762 certainly no longer on any text in the frame. */
4763 clear_mouse_face (dpyinfo
);
4764 dpyinfo
->mouse_face_mouse_frame
= 0;
4767 /* Generate a nil HELP_EVENT to cancel a help-echo.
4768 Do it only if there's something to cancel.
4769 Otherwise, the startup message is cleared when
4770 the mouse leaves the frame. */
4771 if (any_help_event_p
)
4775 dpyinfo
->grabbed
= 0;
4776 check_visibility
= 1;
4780 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4784 inev
.kind
= DELETE_WINDOW_EVENT
;
4785 XSETFRAME (inev
.frame_or_window
, f
);
4790 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4794 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
4795 XSETFRAME (inev
.frame_or_window
, f
);
4800 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4804 extern void menubar_selection_callback
4805 (FRAME_PTR f
, void * client_data
);
4806 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
4809 check_visibility
= 1;
4812 case WM_DISPLAYCHANGE
:
4813 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4817 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
4818 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
4819 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
4820 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
4824 check_visibility
= 1;
4828 /* Check for messages registered at runtime. */
4829 if (msg
.msg
.message
== msh_mousewheel
)
4831 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4832 msg
.msg
.message
= WM_MOUSEWHEEL
;
4838 if (inev
.kind
!= NO_EVENT
)
4840 kbd_buffer_store_event_hold (&inev
, hold_quit
);
4845 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
4850 XSETFRAME (frame
, f
);
4856 if (NILP (help_echo_string
))
4858 help_echo_object
= help_echo_window
= Qnil
;
4862 any_help_event_p
= 1;
4863 gen_help_event (help_echo_string
, frame
, help_echo_window
,
4864 help_echo_object
, help_echo_pos
);
4868 help_echo_string
= Qnil
;
4869 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
4875 /* If the focus was just given to an autoraising frame,
4877 /* ??? This ought to be able to handle more than one such frame. */
4878 if (pending_autoraise_frame
)
4880 x_raise_frame (pending_autoraise_frame
);
4881 pending_autoraise_frame
= 0;
4884 /* Check which frames are still visisble, if we have enqueued any user
4885 events or been notified of events that may affect visibility. We
4886 do this here because there doesn't seem to be any direct
4887 notification from Windows that the visibility of a window has
4888 changed (at least, not in all cases). */
4889 if (count
> 0 || check_visibility
)
4891 Lisp_Object tail
, frame
;
4893 FOR_EACH_FRAME (tail
, frame
)
4895 FRAME_PTR f
= XFRAME (frame
);
4896 /* The tooltip has been drawn already. Avoid the
4897 SET_FRAME_GARBAGED below. */
4898 if (EQ (frame
, tip_frame
))
4901 /* Check "visible" frames and mark each as obscured or not.
4902 Note that async_visible is nonzero for unobscured and
4903 obscured frames, but zero for hidden and iconified frames. */
4904 if (FRAME_W32_P (f
) && f
->async_visible
)
4910 /* Query clipping rectangle for the entire window area
4911 (GetWindowDC), not just the client portion (GetDC).
4912 Otherwise, the scrollbars and menubar aren't counted as
4913 part of the visible area of the frame, and we may think
4914 the frame is obscured when really a scrollbar is still
4915 visible and gets WM_PAINT messages above. */
4916 hdc
= GetWindowDC (FRAME_W32_WINDOW (f
));
4917 GetClipBox (hdc
, &clipbox
);
4918 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
4921 if (clipbox
.right
== clipbox
.left
4922 || clipbox
.bottom
== clipbox
.top
)
4924 /* Frame has become completely obscured so mark as
4925 such (we do this by setting async_visible to 2 so
4926 that FRAME_VISIBLE_P is still true, but redisplay
4928 f
->async_visible
= 2;
4930 if (!FRAME_OBSCURED_P (f
))
4932 DebPrint (("frame %p (%s) obscured\n", f
,
4938 /* Frame is not obscured, so mark it as such. */
4939 f
->async_visible
= 1;
4941 if (FRAME_OBSCURED_P (f
))
4943 SET_FRAME_GARBAGED (f
);
4944 DebPrint (("obscured frame %p (%s) found to be visible\n", f
,
4947 /* Force a redisplay sooner or later. */
4948 record_asynch_buffer_change ();
4961 /***********************************************************************
4963 ***********************************************************************/
4965 /* Set clipping for output in glyph row ROW. W is the window in which
4966 we operate. GC is the graphics context to set clipping in.
4968 ROW may be a text row or, e.g., a mode line. Text rows must be
4969 clipped to the interior of the window dedicated to text display,
4970 mode lines must be clipped to the whole window. */
4973 w32_clip_to_row (w
, row
, area
, hdc
)
4975 struct glyph_row
*row
;
4979 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4981 int window_x
, window_y
, window_width
;
4983 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4985 clip_rect
.left
= window_x
;
4986 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4987 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4988 clip_rect
.right
= clip_rect
.left
+ window_width
;
4989 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4991 w32_set_clip_rectangle (hdc
, &clip_rect
);
4995 /* Draw a hollow box cursor on window W in glyph row ROW. */
4998 x_draw_hollow_cursor (w
, row
)
5000 struct glyph_row
*row
;
5002 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5006 struct glyph
*cursor_glyph
;
5007 HBRUSH hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
5009 /* Get the glyph the cursor is on. If we can't tell because
5010 the current matrix is invalid or such, give up. */
5011 cursor_glyph
= get_phys_cursor_glyph (w
);
5012 if (cursor_glyph
== NULL
)
5015 /* Compute frame-relative coordinates for phys cursor. */
5016 rect
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5017 rect
.top
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5018 rect
.bottom
= rect
.top
+ h
;
5019 rect
.right
= rect
.left
+ w
->phys_cursor_width
;
5021 hdc
= get_frame_dc (f
);
5022 /* Set clipping, draw the rectangle, and reset clipping again. */
5023 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
5024 FrameRect (hdc
, &rect
, hb
);
5026 w32_set_clip_rectangle (hdc
, NULL
);
5027 release_frame_dc (f
, hdc
);
5031 /* Draw a bar cursor on window W in glyph row ROW.
5033 Implementation note: One would like to draw a bar cursor with an
5034 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5035 Unfortunately, I didn't find a font yet that has this property set.
5039 x_draw_bar_cursor (w
, row
, width
, kind
)
5041 struct glyph_row
*row
;
5043 enum text_cursor_kinds kind
;
5045 struct frame
*f
= XFRAME (w
->frame
);
5046 struct glyph
*cursor_glyph
;
5050 /* If cursor is out of bounds, don't draw garbage. This can happen
5051 in mini-buffer windows when switching between echo area glyphs
5053 cursor_glyph
= get_phys_cursor_glyph (w
);
5054 if (cursor_glyph
== NULL
)
5057 /* If on an image, draw like a normal cursor. That's usually better
5058 visible than drawing a bar, esp. if the image is large so that
5059 the bar might not be in the window. */
5060 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5062 struct glyph_row
*row
;
5063 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5064 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5068 COLORREF cursor_color
= f
->output_data
.w32
->cursor_pixel
;
5069 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5071 /* If the glyph's background equals the color we normally draw
5072 the bar cursor in, the bar cursor in its normal color is
5073 invisible. Use the glyph's foreground color instead in this
5074 case, on the assumption that the glyph's colors are chosen so
5075 that the glyph is legible. */
5076 if (face
->background
== cursor_color
)
5077 cursor_color
= face
->foreground
;
5079 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5082 width
= FRAME_CURSOR_WIDTH (f
);
5083 width
= min (cursor_glyph
->pixel_width
, width
);
5085 w
->phys_cursor_width
= width
;
5088 hdc
= get_frame_dc (f
);
5089 w32_clip_to_row (w
, row
, TEXT_AREA
, hdc
);
5091 if (kind
== BAR_CURSOR
)
5093 w32_fill_area (f
, hdc
, cursor_color
, x
,
5094 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5095 width
, row
->height
);
5099 w32_fill_area (f
, hdc
, cursor_color
, x
,
5100 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5101 row
->height
- width
),
5102 cursor_glyph
->pixel_width
, width
);
5105 w32_set_clip_rectangle (hdc
, NULL
);
5106 release_frame_dc (f
, hdc
);
5111 /* RIF: Define cursor CURSOR on frame F. */
5114 w32_define_frame_cursor (f
, cursor
)
5118 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
5122 /* RIF: Clear area on frame F. */
5125 w32_clear_frame_area (f
, x
, y
, width
, height
)
5127 int x
, y
, width
, height
;
5131 hdc
= get_frame_dc (f
);
5132 w32_clear_area (f
, hdc
, x
, y
, width
, height
);
5133 release_frame_dc (f
, hdc
);
5136 /* RIF: Draw or clear cursor on window W. */
5139 w32_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5141 struct glyph_row
*glyph_row
;
5143 int cursor_type
, cursor_width
;
5148 /* If the user wants to use the system caret, make sure our own
5149 cursor remains invisible. */
5150 if (w32_use_visible_system_caret
)
5152 /* Call to erase_phys_cursor here seems to use the
5153 wrong values of w->phys_cursor, as they have been
5154 overwritten before this function was called. */
5155 if (w
->phys_cursor_type
!= NO_CURSOR
)
5156 erase_phys_cursor (w
);
5158 cursor_type
= w
->phys_cursor_type
= NO_CURSOR
;
5159 w
->phys_cursor_width
= -1;
5163 w
->phys_cursor_type
= cursor_type
;
5166 w
->phys_cursor_on_p
= 1;
5168 /* If this is the active cursor, we need to track it with the
5169 system caret, so third party software like screen magnifiers
5170 and speech synthesizers can follow the cursor. */
5173 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5174 HWND hwnd
= FRAME_W32_WINDOW (f
);
5177 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5179 = (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
5180 + glyph_row
->ascent
- w
->phys_cursor_ascent
);
5182 /* If the size of the active cursor changed, destroy the old
5184 if (w32_system_caret_hwnd
5185 && (w32_system_caret_height
!= w
->phys_cursor_height
))
5186 PostMessage (hwnd
, WM_EMACS_DESTROY_CARET
, 0, 0);
5188 w32_system_caret_height
= w
->phys_cursor_height
;
5190 /* Move the system caret. */
5191 PostMessage (hwnd
, WM_EMACS_TRACK_CARET
, 0, 0);
5194 if (glyph_row
->exact_window_width_line_p
5195 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5197 glyph_row
->cursor_in_fringe_p
= 1;
5198 draw_fringe_bitmap (w
, glyph_row
, 0);
5202 switch (cursor_type
)
5204 case HOLLOW_BOX_CURSOR
:
5205 x_draw_hollow_cursor (w
, glyph_row
);
5208 case FILLED_BOX_CURSOR
:
5209 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5213 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5217 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5221 w
->phys_cursor_width
= 0;
5235 x_bitmap_icon (f
, icon
)
5241 if (FRAME_W32_WINDOW (f
) == 0)
5245 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5246 else if (STRINGP (icon
))
5247 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5248 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5249 else if (SYMBOLP (icon
))
5253 if (EQ (icon
, intern ("application")))
5254 name
= (LPCTSTR
) IDI_APPLICATION
;
5255 else if (EQ (icon
, intern ("hand")))
5256 name
= (LPCTSTR
) IDI_HAND
;
5257 else if (EQ (icon
, intern ("question")))
5258 name
= (LPCTSTR
) IDI_QUESTION
;
5259 else if (EQ (icon
, intern ("exclamation")))
5260 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5261 else if (EQ (icon
, intern ("asterisk")))
5262 name
= (LPCTSTR
) IDI_ASTERISK
;
5263 else if (EQ (icon
, intern ("winlogo")))
5264 name
= (LPCTSTR
) IDI_WINLOGO
;
5268 hicon
= LoadIcon (NULL
, name
);
5276 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5283 /************************************************************************
5285 ************************************************************************/
5287 /* Display Error Handling functions not used on W32. Listing them here
5288 helps diff stay in step when comparing w32term.c with xterm.c.
5290 x_error_catcher (display, error)
5291 x_catch_errors (dpy)
5292 x_catch_errors_unwind (old_val)
5293 x_check_errors (dpy, format)
5294 x_had_errors_p (dpy)
5295 x_clear_errors (dpy)
5296 x_uncatch_errors (dpy, count)
5298 x_connection_signal (signalnum)
5299 x_connection_closed (dpy, error_message)
5300 x_error_quitter (display, error)
5301 x_error_handler (display, error)
5302 x_io_error_quitter (display)
5307 /* Changing the font of the frame. */
5309 /* Give frame F the font named FONTNAME as its default font, and
5310 return the full name of that font. FONTNAME may be a wildcard
5311 pattern; in that case, we choose some font that fits the pattern.
5312 The return value shows which font we chose. */
5315 x_new_font (f
, fontname
)
5317 register char *fontname
;
5319 struct font_info
*fontp
5320 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5325 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5326 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5327 FRAME_FONTSET (f
) = -1;
5329 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5330 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5331 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5333 compute_fringe_widths (f
, 1);
5335 /* Compute the scroll bar width in character columns. */
5336 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5338 int wid
= FRAME_COLUMN_WIDTH (f
);
5339 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5340 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5344 int wid
= FRAME_COLUMN_WIDTH (f
);
5345 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5348 /* Now make the frame display the given font. */
5349 if (FRAME_W32_WINDOW (f
) != 0)
5351 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5352 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5355 return build_string (fontp
->full_name
);
5358 /* Give frame F the fontset named FONTSETNAME as its default font, and
5359 return the full name of that fontset. FONTSETNAME may be a wildcard
5360 pattern; in that case, we choose some fontset that fits the pattern.
5361 The return value shows which fontset we chose. */
5364 x_new_fontset (f
, fontsetname
)
5368 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5374 if (FRAME_FONTSET (f
) == fontset
)
5375 /* This fontset is already set in frame F. There's nothing more
5377 return fontset_name (fontset
);
5379 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5381 if (!STRINGP (result
))
5382 /* Can't load ASCII font. */
5385 /* Since x_new_font doesn't update any fontset information, do it now. */
5386 FRAME_FONTSET(f
) = fontset
;
5388 return build_string (fontsetname
);
5392 /***********************************************************************
5393 TODO: W32 Input Methods
5394 ***********************************************************************/
5395 /* Listing missing functions from xterm.c helps diff stay in step.
5397 xim_destroy_callback (xim, client_data, call_data)
5398 xim_open_dpy (dpyinfo, resource_name)
5400 xim_instantiate_callback (display, client_data, call_data)
5401 xim_initialize (dpyinfo, resource_name)
5402 xim_close_dpy (dpyinfo)
5407 /* Calculate the absolute position in frame F
5408 from its current recorded position values and gravity. */
5411 x_calc_absolute_position (f
)
5414 int flags
= f
->size_hint_flags
;
5416 /* Treat negative positions as relative to the leftmost bottommost
5417 position that fits on the screen. */
5418 if (flags
& XNegative
)
5419 f
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
5420 - FRAME_PIXEL_WIDTH (f
)
5423 if (flags
& YNegative
)
5424 f
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
5425 - FRAME_PIXEL_HEIGHT (f
)
5427 /* The left_pos and top_pos
5428 are now relative to the top and left screen edges,
5429 so the flags should correspond. */
5430 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5433 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5434 to really change the position, and 0 when calling from
5435 x_make_frame_visible (in that case, XOFF and YOFF are the current
5436 position values). It is -1 when calling from x_set_frame_parameters,
5437 which means, do adjust for borders but don't change the gravity. */
5440 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5442 register int xoff
, yoff
;
5445 int modified_top
, modified_left
;
5447 if (change_gravity
> 0)
5451 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5453 f
->size_hint_flags
|= XNegative
;
5455 f
->size_hint_flags
|= YNegative
;
5456 f
->win_gravity
= NorthWestGravity
;
5458 x_calc_absolute_position (f
);
5461 x_wm_set_size_hint (f
, (long) 0, 0);
5463 modified_left
= f
->left_pos
;
5464 modified_top
= f
->top_pos
;
5466 my_set_window_pos (FRAME_W32_WINDOW (f
),
5468 modified_left
, modified_top
,
5470 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5475 /* Check if we need to resize the frame due to a fullscreen request.
5476 If so needed, resize the frame. */
5478 x_check_fullscreen (f
)
5481 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
5483 int width
, height
, ign
;
5485 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5487 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
5489 /* We do not need to move the window, it shall be taken care of
5490 when setting WM manager hints. */
5491 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
5493 change_frame_size (f
, height
, width
, 0, 1, 0);
5494 SET_FRAME_GARBAGED (f
);
5495 cancel_mouse_face (f
);
5497 /* Wait for the change of frame size to occur */
5498 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
5503 /* Call this to change the size of frame F's x-window.
5504 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5505 for this size change and subsequent size changes.
5506 Otherwise we leave the window gravity unchanged. */
5509 x_set_window_size (f
, change_gravity
, cols
, rows
)
5514 int pixelwidth
, pixelheight
;
5518 check_frame_size (f
, &rows
, &cols
);
5519 f
->scroll_bar_actual_width
5520 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5522 compute_fringe_widths (f
, 0);
5524 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5525 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5527 f
->win_gravity
= NorthWestGravity
;
5528 x_wm_set_size_hint (f
, (long) 0, 0);
5533 rect
.left
= rect
.top
= 0;
5534 rect
.right
= pixelwidth
;
5535 rect
.bottom
= pixelheight
;
5537 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
5538 FRAME_EXTERNAL_MENU_BAR (f
));
5540 my_set_window_pos (FRAME_W32_WINDOW (f
),
5543 rect
.right
- rect
.left
,
5544 rect
.bottom
- rect
.top
,
5545 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5548 /* Now, strictly speaking, we can't be sure that this is accurate,
5549 but the window manager will get around to dealing with the size
5550 change request eventually, and we'll hear how it went when the
5551 ConfigureNotify event gets here.
5553 We could just not bother storing any of this information here,
5554 and let the ConfigureNotify event set everything up, but that
5555 might be kind of confusing to the Lisp code, since size changes
5556 wouldn't be reported in the frame parameters until some random
5557 point in the future when the ConfigureNotify event arrives.
5559 We pass 1 for DELAY since we can't run Lisp code inside of
5561 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5562 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5563 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5565 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5566 receive in the ConfigureNotify event; if we get what we asked
5567 for, then the event won't cause the screen to become garbaged, so
5568 we have to make sure to do it here. */
5569 SET_FRAME_GARBAGED (f
);
5571 /* If cursor was outside the new size, mark it as off. */
5572 mark_window_cursors_off (XWINDOW (f
->root_window
));
5574 /* Clear out any recollection of where the mouse highlighting was,
5575 since it might be in a place that's outside the new frame size.
5576 Actually checking whether it is outside is a pain in the neck,
5577 so don't try--just let the highlighting be done afresh with new size. */
5578 cancel_mouse_face (f
);
5583 /* Mouse warping. */
5585 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5588 x_set_mouse_position (f
, x
, y
)
5594 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5595 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5597 if (pix_x
< 0) pix_x
= 0;
5598 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5600 if (pix_y
< 0) pix_y
= 0;
5601 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5603 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5607 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5616 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
5617 pt
.x
= rect
.left
+ pix_x
;
5618 pt
.y
= rect
.top
+ pix_y
;
5619 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
5621 SetCursorPos (pt
.x
, pt
.y
);
5627 /* focus shifting, raising and lowering. */
5630 x_focus_on_frame (f
)
5633 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
5635 /* Give input focus to frame. */
5638 /* Try not to change its Z-order if possible. */
5639 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
5640 my_set_focus (f
, FRAME_W32_WINDOW (f
));
5643 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5653 /* Raise frame F. */
5660 /* Strictly speaking, raise-frame should only change the frame's Z
5661 order, leaving input focus unchanged. This is reasonable behaviour
5662 on X where the usual policy is point-to-focus. However, this
5663 behaviour would be very odd on Windows where the usual policy is
5666 On X, if the mouse happens to be over the raised frame, it gets
5667 input focus anyway (so the window with focus will never be
5668 completely obscured) - if not, then just moving the mouse over it
5669 is sufficient to give it focus. On Windows, the user must actually
5670 click on the frame (preferrably the title bar so as not to move
5671 point), which is more awkward. Also, no other Windows program
5672 raises a window to the top but leaves another window (possibly now
5673 completely obscured) with input focus.
5675 Because there is a system setting on Windows that allows the user
5676 to choose the point to focus policy, we make the strict semantics
5677 optional, but by default we grab focus when raising. */
5679 if (NILP (Vw32_grab_focus_on_raise
))
5681 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5682 not already the foreground application: the frame is raised
5683 above all other frames belonging to us, but not above the
5684 current top window. To achieve that, we have to resort to this
5685 more cumbersome method. */
5687 HDWP handle
= BeginDeferWindowPos (2);
5690 DeferWindowPos (handle
,
5691 FRAME_W32_WINDOW (f
),
5694 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5696 DeferWindowPos (handle
,
5697 GetForegroundWindow (),
5698 FRAME_W32_WINDOW (f
),
5700 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5702 EndDeferWindowPos (handle
);
5707 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5713 /* Lower frame F. */
5719 my_set_window_pos (FRAME_W32_WINDOW (f
),
5722 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5727 w32_frame_raise_lower (f
, raise_flag
)
5731 if (! FRAME_W32_P (f
))
5740 /* Change of visibility. */
5742 /* This tries to wait until the frame is really visible.
5743 However, if the window manager asks the user where to position
5744 the frame, this will return before the user finishes doing that.
5745 The frame will not actually be visible at that time,
5746 but it will become visible later when the window manager
5747 finishes with it. */
5750 x_make_frame_visible (f
)
5757 type
= x_icon_type (f
);
5759 x_bitmap_icon (f
, type
);
5761 if (! FRAME_VISIBLE_P (f
))
5763 /* We test FRAME_GARBAGED_P here to make sure we don't
5764 call x_set_offset a second time
5765 if we get to x_make_frame_visible a second time
5766 before the window gets really visible. */
5767 if (! FRAME_ICONIFIED_P (f
)
5768 && ! f
->output_data
.w32
->asked_for_visible
)
5769 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5771 f
->output_data
.w32
->asked_for_visible
= 1;
5773 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
5774 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
5777 /* Synchronize to ensure Emacs knows the frame is visible
5778 before we do anything else. We do this loop with input not blocked
5779 so that incoming events are handled. */
5784 /* This must come after we set COUNT. */
5787 XSETFRAME (frame
, f
);
5789 /* Wait until the frame is visible. Process X events until a
5790 MapNotify event has been seen, or until we think we won't get a
5791 MapNotify at all.. */
5792 for (count
= input_signal_count
+ 10;
5793 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5795 /* Force processing of queued events. */
5796 /* TODO: x_sync equivalent? */
5798 /* Machines that do polling rather than SIGIO have been observed
5799 to go into a busy-wait here. So we'll fake an alarm signal
5800 to let the handler know that there's something to be read.
5801 We used to raise a real alarm, but it seems that the handler
5802 isn't always enabled here. This is probably a bug. */
5803 if (input_polling_used ())
5805 /* It could be confusing if a real alarm arrives while processing
5806 the fake one. Turn it off and let the handler reset it. */
5807 int old_poll_suppress_count
= poll_suppress_count
;
5808 poll_suppress_count
= 1;
5809 poll_for_input_1 ();
5810 poll_suppress_count
= old_poll_suppress_count
;
5813 FRAME_SAMPLE_VISIBILITY (f
);
5817 /* Change from mapped state to withdrawn state. */
5819 /* Make the frame visible (mapped and not iconified). */
5821 x_make_frame_invisible (f
)
5824 /* Don't keep the highlight on an invisible frame. */
5825 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5826 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5830 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
5832 /* We can't distinguish this from iconification
5833 just by the event that we get from the server.
5834 So we can't win using the usual strategy of letting
5835 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5836 and synchronize with the server to make sure we agree. */
5838 FRAME_ICONIFIED_P (f
) = 0;
5839 f
->async_visible
= 0;
5840 f
->async_iconified
= 0;
5845 /* Change window state from mapped to iconified. */
5853 /* Don't keep the highlight on an invisible frame. */
5854 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5855 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5857 if (f
->async_iconified
)
5862 type
= x_icon_type (f
);
5864 x_bitmap_icon (f
, type
);
5866 /* Simulate the user minimizing the frame. */
5867 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
5873 /* Free X resources of frame F. */
5876 x_free_frame_resources (f
)
5879 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5883 if (FRAME_W32_WINDOW (f
))
5884 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
5886 free_frame_menubar (f
);
5888 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
5889 unload_color (f
, f
->output_data
.x
->background_pixel
);
5890 unload_color (f
, f
->output_data
.w32
->cursor_pixel
);
5891 unload_color (f
, f
->output_data
.w32
->cursor_foreground_pixel
);
5892 unload_color (f
, f
->output_data
.w32
->border_pixel
);
5893 unload_color (f
, f
->output_data
.w32
->mouse_pixel
);
5894 if (f
->output_data
.w32
->white_relief
.allocated_p
)
5895 unload_color (f
, f
->output_data
.w32
->white_relief
.pixel
);
5896 if (f
->output_data
.w32
->black_relief
.allocated_p
)
5897 unload_color (f
, f
->output_data
.w32
->black_relief
.pixel
);
5899 if (FRAME_FACE_CACHE (f
))
5900 free_frame_faces (f
);
5902 xfree (f
->output_data
.w32
);
5903 f
->output_data
.w32
= NULL
;
5905 if (f
== dpyinfo
->w32_focus_frame
)
5906 dpyinfo
->w32_focus_frame
= 0;
5907 if (f
== dpyinfo
->w32_focus_event_frame
)
5908 dpyinfo
->w32_focus_event_frame
= 0;
5909 if (f
== dpyinfo
->x_highlight_frame
)
5910 dpyinfo
->x_highlight_frame
= 0;
5912 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5914 dpyinfo
->mouse_face_beg_row
5915 = dpyinfo
->mouse_face_beg_col
= -1;
5916 dpyinfo
->mouse_face_end_row
5917 = dpyinfo
->mouse_face_end_col
= -1;
5918 dpyinfo
->mouse_face_window
= Qnil
;
5919 dpyinfo
->mouse_face_deferred_gc
= 0;
5920 dpyinfo
->mouse_face_mouse_frame
= 0;
5927 /* Destroy the window of frame F. */
5929 x_destroy_window (f
)
5932 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
5934 x_free_frame_resources (f
);
5936 dpyinfo
->reference_count
--;
5940 /* Setting window manager hints. */
5942 /* Set the normal size hints for the window manager, for frame F.
5943 FLAGS is the flags word to use--or 0 meaning preserve the flags
5944 that the window now has.
5945 If USER_POSITION is nonzero, we set the USPosition
5946 flag (this is useful when FLAGS is 0). */
5948 x_wm_set_size_hint (f
, flags
, user_position
)
5953 Window window
= FRAME_W32_WINDOW (f
);
5957 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
5958 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
5959 SetWindowLong (window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
5960 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
5965 /* Window manager things */
5967 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5972 Window window
= FRAME_W32_WINDOW (f
);
5974 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
5975 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
5976 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
5978 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
5983 /***********************************************************************
5985 ***********************************************************************/
5987 /* The following functions are listed here to help diff stay in step
5988 with xterm.c. See w32fns.c for definitions.
5990 x_get_font_info (f, font_idx)
5991 x_list_fonts (f, pattern, size, maxnames)
5997 /* Check that FONT is valid on frame F. It is if it can be found in F's
6001 x_check_font (f
, font
)
6006 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6008 xassert (font
!= NULL
);
6010 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6011 if (dpyinfo
->font_table
[i
].name
6012 && font
== dpyinfo
->font_table
[i
].font
)
6015 xassert (i
< dpyinfo
->n_fonts
);
6018 #endif /* GLYPH_DEBUG != 0 */
6020 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6021 Note: There are (broken) X fonts out there with invalid XFontStruct
6022 min_bounds contents. For example, handa@etl.go.jp reports that
6023 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6024 have font->min_bounds.width == 0. */
6027 x_font_min_bounds (font
, w
, h
)
6032 * TODO: Windows does not appear to offer min bound, only
6033 * average and maximum width, and maximum height.
6035 *h
= FONT_HEIGHT (font
);
6036 *w
= FONT_WIDTH (font
);
6040 /* Compute the smallest character width and smallest font height over
6041 all fonts available on frame F. Set the members smallest_char_width
6042 and smallest_font_height in F's x_display_info structure to
6043 the values computed. Value is non-zero if smallest_font_height or
6044 smallest_char_width become smaller than they were before. */
6047 x_compute_min_glyph_bounds (f
)
6051 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6053 int old_width
= dpyinfo
->smallest_char_width
;
6054 int old_height
= dpyinfo
->smallest_font_height
;
6056 dpyinfo
->smallest_font_height
= 100000;
6057 dpyinfo
->smallest_char_width
= 100000;
6059 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6060 if (dpyinfo
->font_table
[i
].name
)
6062 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6065 font
= (XFontStruct
*) fontp
->font
;
6066 xassert (font
!= (XFontStruct
*) ~0);
6067 x_font_min_bounds (font
, &w
, &h
);
6069 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6070 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6073 xassert (dpyinfo
->smallest_char_width
> 0
6074 && dpyinfo
->smallest_font_height
> 0);
6076 return (dpyinfo
->n_fonts
== 1
6077 || dpyinfo
->smallest_char_width
< old_width
6078 || dpyinfo
->smallest_font_height
< old_height
);
6081 /* The following functions are listed here to help diff stay in step
6082 with xterm.c. See w32fns.c for definitions.
6084 x_load_font (f, fontname, size)
6085 x_query_font (f, fontname)
6086 x_find_ccl_program (fontp)
6090 /***********************************************************************
6092 ***********************************************************************/
6094 static int w32_initialized
= 0;
6097 w32_initialize_display_info (display_name
)
6098 Lisp_Object display_name
;
6100 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6102 bzero (dpyinfo
, sizeof (*dpyinfo
));
6104 /* Put it on w32_display_name_list. */
6105 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6106 w32_display_name_list
);
6107 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
6109 dpyinfo
->w32_id_name
6110 = (char *) xmalloc (SCHARS (Vinvocation_name
)
6111 + SCHARS (Vsystem_name
)
6113 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
6114 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
6116 /* Default Console mode values - overridden when running in GUI mode
6117 with values obtained from system metrics. */
6120 dpyinfo
->height_in
= 1;
6121 dpyinfo
->width_in
= 1;
6122 dpyinfo
->n_planes
= 1;
6123 dpyinfo
->n_cbits
= 4;
6124 dpyinfo
->n_fonts
= 0;
6125 dpyinfo
->smallest_font_height
= 1;
6126 dpyinfo
->smallest_char_width
= 1;
6128 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6129 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6130 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
6131 dpyinfo
->mouse_face_window
= Qnil
;
6132 dpyinfo
->mouse_face_overlay
= Qnil
;
6133 dpyinfo
->mouse_face_hidden
= 0;
6135 dpyinfo
->vertical_scroll_bar_cursor
= w32_load_cursor (IDC_ARROW
);
6136 /* TODO: dpyinfo->gray */
6140 /* Create an xrdb-style database of resources to supercede registry settings.
6141 The database is just a concatenation of C strings, finished by an additional
6142 \0. The string are submitted to some basic normalization, so
6144 [ *]option[ *]:[ *]value...
6150 but any whitespace following value is not removed. */
6153 w32_make_rdb (xrm_option
)
6156 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
6157 char *current
= buffer
;
6160 int before_value
= 0;
6174 if (in_option
&& (ch
== ':'))
6179 else if (before_value
)
6184 else if (!(in_option
|| before_value
))
6195 struct w32_display_info
*
6196 w32_term_init (display_name
, xrm_option
, resource_name
)
6197 Lisp_Object display_name
;
6199 char *resource_name
;
6201 struct w32_display_info
*dpyinfo
;
6206 if (!w32_initialized
)
6209 w32_initialized
= 1;
6212 w32_initialize_display_info (display_name
);
6214 dpyinfo
= &one_w32_display_info
;
6216 dpyinfo
->xrdb
= xrm_option
? w32_make_rdb (xrm_option
) : NULL
;
6218 /* Put this display on the chain. */
6219 dpyinfo
->next
= x_display_list
;
6220 x_display_list
= dpyinfo
;
6222 hdc
= GetDC (GetDesktopWindow ());
6224 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
6225 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
6226 dpyinfo
->root_window
= GetDesktopWindow ();
6227 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
6228 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
6229 dpyinfo
->resx
= GetDeviceCaps (hdc
, LOGPIXELSX
);
6230 dpyinfo
->resy
= GetDeviceCaps (hdc
, LOGPIXELSY
);
6231 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
6232 dpyinfo
->image_cache
= make_image_cache ();
6233 dpyinfo
->height_in
= dpyinfo
->height
/ dpyinfo
->resx
;
6234 dpyinfo
->width_in
= dpyinfo
->width
/ dpyinfo
->resy
;
6235 ReleaseDC (GetDesktopWindow (), hdc
);
6237 /* initialise palette with white and black */
6240 w32_defined_color (0, "white", &color
, 1);
6241 w32_defined_color (0, "black", &color
, 1);
6244 /* Create Fringe Bitmaps and store them for later use.
6246 On W32, bitmaps are all unsigned short, as Windows requires
6247 bitmap data to be Word aligned. For some reason they are
6248 horizontally reflected compared to how they appear on X, so we
6249 need to bitswap and convert to unsigned shorts before creating
6253 #ifndef F_SETOWN_BUG
6255 #ifdef F_SETOWN_SOCK_NEG
6256 /* stdin is a socket here */
6257 fcntl (connection
, F_SETOWN
, -getpid ());
6258 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6259 fcntl (connection
, F_SETOWN
, getpid ());
6260 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6261 #endif /* ! defined (F_SETOWN) */
6262 #endif /* F_SETOWN_BUG */
6265 if (interrupt_input
)
6266 init_sigio (connection
);
6267 #endif /* ! defined (SIGIO) */
6274 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6277 x_delete_display (dpyinfo
)
6278 struct w32_display_info
*dpyinfo
;
6280 /* Discard this display from w32_display_name_list and w32_display_list.
6281 We can't use Fdelq because that can quit. */
6282 if (! NILP (w32_display_name_list
)
6283 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
6284 w32_display_name_list
= XCDR (w32_display_name_list
);
6289 tail
= w32_display_name_list
;
6290 while (CONSP (tail
) && CONSP (XCDR (tail
)))
6292 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
6294 XSETCDR (tail
, XCDR (XCDR (tail
)));
6301 /* free palette table */
6303 struct w32_palette_entry
* plist
;
6305 plist
= dpyinfo
->color_list
;
6308 struct w32_palette_entry
* pentry
= plist
;
6309 plist
= plist
->next
;
6312 dpyinfo
->color_list
= NULL
;
6313 if (dpyinfo
->palette
)
6314 DeleteObject(dpyinfo
->palette
);
6316 xfree (dpyinfo
->font_table
);
6317 xfree (dpyinfo
->w32_id_name
);
6319 w32_reset_fringes ();
6322 /* Set up use of W32. */
6324 DWORD
w32_msg_worker ();
6327 x_flush (struct frame
* f
)
6328 { /* Nothing to do */ }
6330 extern frame_parm_handler w32_frame_parm_handlers
[];
6332 static struct redisplay_interface w32_redisplay_interface
=
6334 w32_frame_parm_handlers
,
6338 x_clear_end_of_line
,
6340 x_after_update_window_line
,
6341 x_update_window_begin
,
6342 x_update_window_end
,
6345 0, /* flush_display_optional */
6346 x_clear_window_mouse_face
,
6347 w32_get_glyph_overhangs
,
6348 x_fix_overlapping_area
,
6349 w32_draw_fringe_bitmap
,
6350 w32_define_fringe_bitmap
,
6351 w32_destroy_fringe_bitmap
,
6352 w32_per_char_metric
,
6354 NULL
, /* w32_compute_glyph_string_overhangs */
6355 x_draw_glyph_string
,
6356 w32_define_frame_cursor
,
6357 w32_clear_frame_area
,
6358 w32_draw_window_cursor
,
6359 w32_draw_vertical_window_border
,
6360 w32_shift_glyphs_for_insert
6366 rif
= &w32_redisplay_interface
;
6368 /* MSVC does not type K&R functions with no arguments correctly, and
6369 so we must explicitly cast them. */
6370 clear_frame_hook
= (void (*)(void)) x_clear_frame
;
6371 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
6372 update_begin_hook
= x_update_begin
;
6373 update_end_hook
= x_update_end
;
6375 read_socket_hook
= w32_read_socket
;
6377 frame_up_to_date_hook
= w32_frame_up_to_date
;
6379 mouse_position_hook
= w32_mouse_position
;
6380 frame_rehighlight_hook
= w32_frame_rehighlight
;
6381 frame_raise_lower_hook
= w32_frame_raise_lower
;
6382 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
6383 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
6384 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
6385 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
6387 scroll_region_ok
= 1; /* we'll scroll partial frames */
6388 char_ins_del_ok
= 1;
6389 line_ins_del_ok
= 1; /* we'll just blt 'em */
6390 fast_clear_end_of_line
= 1; /* X does this well */
6391 memory_below_frame
= 0; /* we don't remember what scrolls
6395 w32_system_caret_hwnd
= NULL
;
6396 w32_system_caret_height
= 0;
6397 w32_system_caret_x
= 0;
6398 w32_system_caret_y
= 0;
6400 last_tool_bar_item
= -1;
6401 any_help_event_p
= 0;
6403 /* Initialize input mode: interrupt_input off, no flow control, allow
6404 8 bit character input, standard quit char. */
6405 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
6407 /* Create the window thread - it will terminate itself or when the app terminates */
6411 dwMainThreadId
= GetCurrentThreadId ();
6412 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6413 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
6415 /* Wait for thread to start */
6420 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
6422 hWindowsThread
= CreateThread (NULL
, 0,
6423 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
6424 0, 0, &dwWindowsThreadId
);
6426 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6429 /* It is desirable that mainThread should have the same notion of
6430 focus window and active window as windowsThread. Unfortunately, the
6431 following call to AttachThreadInput, which should do precisely what
6432 we need, causes major problems when Emacs is linked as a console
6433 program. Unfortunately, we have good reasons for doing that, so
6434 instead we need to send messages to windowsThread to make some API
6435 calls for us (ones that affect, or depend on, the active/focus
6437 #ifdef ATTACH_THREADS
6438 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
6441 /* Dynamically link to optional system components. */
6443 HANDLE user_lib
= LoadLibrary ("user32.dll");
6445 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
6447 /* New proportional scroll bar functions. */
6448 LOAD_PROC (SetScrollInfo
);
6449 LOAD_PROC (GetScrollInfo
);
6453 FreeLibrary (user_lib
);
6455 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
6456 otherwise use the fixed height. */
6457 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
6458 GetSystemMetrics (SM_CYVTHUMB
);
6460 /* For either kind of scroll bar, take account of the arrows; these
6461 effectively form the border of the main scroll bar range. */
6462 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
6463 = GetSystemMetrics (SM_CYVSCROLL
);
6470 staticpro (&w32_display_name_list
);
6471 w32_display_name_list
= Qnil
;
6473 staticpro (&last_mouse_scroll_bar
);
6474 last_mouse_scroll_bar
= Qnil
;
6476 staticpro (&Qvendor_specific_keysyms
);
6477 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6479 DEFVAR_INT ("w32-num-mouse-buttons",
6480 &w32_num_mouse_buttons
,
6481 doc
: /* Number of physical mouse buttons. */);
6482 w32_num_mouse_buttons
= 2;
6484 DEFVAR_LISP ("w32-swap-mouse-buttons",
6485 &Vw32_swap_mouse_buttons
,
6486 doc
: /* Swap the mapping of middle and right mouse buttons.
6487 When nil, middle button is mouse-2 and right button is mouse-3. */);
6488 Vw32_swap_mouse_buttons
= Qnil
;
6490 DEFVAR_LISP ("w32-grab-focus-on-raise",
6491 &Vw32_grab_focus_on_raise
,
6492 doc
: /* Raised frame grabs input focus.
6493 When t, `raise-frame' grabs input focus as well. This fits well
6494 with the normal Windows click-to-focus policy, but might not be
6495 desirable when using a point-to-focus policy. */);
6496 Vw32_grab_focus_on_raise
= Qt
;
6498 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6499 &Vw32_capslock_is_shiftlock
,
6500 doc
: /* Apply CapsLock state to non character input keys.
6501 When nil, CapsLock only affects normal character input keys. */);
6502 Vw32_capslock_is_shiftlock
= Qnil
;
6504 DEFVAR_LISP ("w32-recognize-altgr",
6505 &Vw32_recognize_altgr
,
6506 doc
: /* Recognize right-alt and left-ctrl as AltGr.
6507 When nil, the right-alt and left-ctrl key combination is
6508 interpreted normally. */);
6509 Vw32_recognize_altgr
= Qt
;
6511 DEFVAR_BOOL ("w32-enable-unicode-output",
6512 &w32_enable_unicode_output
,
6513 doc
: /* Enable the use of Unicode for text output if non-nil.
6514 Unicode output may prevent some third party applications for displaying
6515 Far-East Languages on Windows 95/98 from working properly.
6516 NT uses Unicode internally anyway, so this flag will probably have no
6517 affect on NT machines. */);
6518 w32_enable_unicode_output
= 1;
6520 DEFVAR_BOOL ("w32-use-visible-system-caret",
6521 &w32_use_visible_system_caret
,
6522 doc
: /* Flag to make the system caret visible.
6523 When this is non-nil, Emacs will indicate the position of point by
6524 using the system caret instead of drawing its own cursor. Some screen
6525 reader software does not track the system cursor properly when it is
6526 invisible, and gets confused by Emacs drawing its own cursor, so this
6527 variable is initialized to t when Emacs detects that screen reader
6528 software is running as it starts up.
6530 When this variable is set, other variables affecting the appearance of
6531 the cursor have no effect. */);
6533 /* Initialize w32_use_visible_system_caret based on whether a screen
6534 reader is in use. */
6535 if (!SystemParametersInfo (SPI_GETSCREENREADER
, 0,
6536 &w32_use_visible_system_caret
, 0))
6537 w32_use_visible_system_caret
= 0;
6539 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
6540 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
6541 Vx_toolkit_scroll_bars
= Qt
;
6543 staticpro (&last_mouse_motion_frame
);
6544 last_mouse_motion_frame
= Qnil
;
6547 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6548 (do not change this comment) */