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. */
27 #include "blockinput.h"
39 #include "character.h"
43 #include "dispextern.h"
45 #include "termhooks.h"
53 #include "intervals.h"
62 #define abs(x) ((x) < 0 ? -(x) : (x))
67 static int max_fringe_bmp
= 0;
68 static HBITMAP
*fringe_bmp
= 0;
70 /* Non-nil means Emacs uses toolkit scroll bars. */
72 Lisp_Object Vx_toolkit_scroll_bars
;
74 /* Temporary variables for w32_read_socket. */
76 static int last_mousemove_x
= 0;
77 static int last_mousemove_y
= 0;
79 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
80 #ifndef GET_WHEEL_DELTA_WPARAM
81 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
84 /* Non-zero means that a HELP_EVENT has been generated since Emacs
87 static int any_help_event_p
;
89 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
90 static Lisp_Object last_window
;
92 extern unsigned int msh_mousewheel
;
94 extern void free_frame_menubar ();
96 extern int w32_codepage_for_font (char *fontname
);
97 extern Cursor
w32_load_cursor (LPCTSTR name
);
99 extern glyph_metric
*w32_BDF_TextMetric(bdffont
*fontp
,
100 unsigned char *text
, int dim
);
101 extern Lisp_Object Vwindow_system
;
103 #define x_any_window_to_frame x_window_to_frame
104 #define x_top_window_to_frame x_window_to_frame
107 /* This is display since w32 does not support multiple ones. */
108 struct w32_display_info one_w32_display_info
;
109 struct w32_display_info
*x_display_list
;
111 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
112 one for each element of w32_display_list and in the same order.
113 NAME is the name of the frame.
114 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
115 Lisp_Object w32_display_name_list
;
119 /* Pre Windows 2000, this was not available, but define it here so
120 that Emacs compiled on such a platform will run on newer versions. */
122 typedef struct tagWCRANGE
128 typedef struct tagGLYPHSET
132 DWORD cGlyphsSupported
;
139 /* Dynamic linking to GetFontUnicodeRanges (not available on 95, 98, ME). */
140 DWORD (PASCAL
*pfnGetFontUnicodeRanges
) (HDC device
, GLYPHSET
*ranges
);
142 /* Frame being updated by update_frame. This is declared in term.c.
143 This is set by update_begin and looked at by all the
144 w32 functions. It is zero while not inside an update.
145 In that case, the w32 functions assume that `SELECTED_FRAME ()'
146 is the frame to apply to. */
147 extern struct frame
*updating_frame
;
149 /* This is a frame waiting to be autoraised, within w32_read_socket. */
150 struct frame
*pending_autoraise_frame
;
152 /* The handle of the frame that currently owns the system caret. */
153 HWND w32_system_caret_hwnd
;
154 int w32_system_caret_height
;
155 int w32_system_caret_x
;
156 int w32_system_caret_y
;
157 int w32_use_visible_system_caret
;
159 /* Flag to enable Unicode output in case users wish to use programs
160 like Twinbridge on '95 rather than installed system level support
161 for Far East languages. */
162 int w32_enable_unicode_output
;
164 DWORD dwWindowsThreadId
= 0;
165 HANDLE hWindowsThread
= NULL
;
166 DWORD dwMainThreadId
= 0;
167 HANDLE hMainThread
= NULL
;
170 /* These definitions are new with Windows 95. */
171 #define SIF_RANGE 0x0001
172 #define SIF_PAGE 0x0002
173 #define SIF_POS 0x0004
174 #define SIF_DISABLENOSCROLL 0x0008
175 #define SIF_TRACKPOS 0x0010
176 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
178 typedef struct tagSCROLLINFO
187 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
188 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
191 /* Dynamic linking to new proportional scroll bar functions. */
192 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
193 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
195 int vertical_scroll_bar_min_handle
;
196 int vertical_scroll_bar_top_border
;
197 int vertical_scroll_bar_bottom_border
;
199 int last_scroll_bar_drag_pos
;
201 /* Mouse movement. */
203 /* Where the mouse was last time we reported a mouse event. */
205 static RECT last_mouse_glyph
;
206 static Lisp_Object last_mouse_press_frame
;
208 int w32_num_mouse_buttons
;
210 Lisp_Object Vw32_swap_mouse_buttons
;
212 /* Control whether x_raise_frame also sets input focus. */
213 Lisp_Object Vw32_grab_focus_on_raise
;
215 /* Control whether Caps Lock affects non-ascii characters. */
216 Lisp_Object Vw32_capslock_is_shiftlock
;
218 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
219 Lisp_Object Vw32_recognize_altgr
;
221 /* The scroll bar in which the last motion event occurred.
223 If the last motion event occurred in a scroll bar, we set this
224 so w32_mouse_position can know whether to report a scroll bar motion or
227 If the last motion event didn't occur in a scroll bar, we set this
228 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
229 static Lisp_Object last_mouse_scroll_bar
;
230 static int last_mouse_scroll_bar_pos
;
232 /* This is a hack. We would really prefer that w32_mouse_position would
233 return the time associated with the position it returns, but there
234 doesn't seem to be any way to wrest the time-stamp from the server
235 along with the position query. So, we just keep track of the time
236 of the last movement we received, and return that in hopes that
237 it's somewhat accurate. */
239 static Time last_mouse_movement_time
;
241 /* Incremented by w32_read_socket whenever it really tries to read
245 static int volatile input_signal_count
;
247 static int input_signal_count
;
250 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
256 /* A mask of extra modifier bits to put into every keyboard char. */
258 extern EMACS_INT extra_keyboard_modifiers
;
260 static void x_update_window_end
P_ ((struct window
*, int, int));
261 void w32_delete_display
P_ ((struct w32_display_info
*));
262 static void w32_handle_tool_bar_click
P_ ((struct frame
*,
263 struct input_event
*));
264 void w32_define_cursor
P_ ((Window
, Cursor
));
266 void x_lower_frame
P_ ((struct frame
*));
267 void x_scroll_bar_clear
P_ ((struct frame
*));
268 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
269 void x_raise_frame
P_ ((struct frame
*));
270 void x_set_window_size
P_ ((struct frame
*, int, int, int));
271 void x_wm_set_window_state
P_ ((struct frame
*, int));
272 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
273 void w32_initialize
P_ ((void));
274 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
275 int x_compute_min_glyph_bounds
P_ ((struct frame
*));
276 static void x_update_end
P_ ((struct frame
*));
277 static void w32_frame_up_to_date
P_ ((struct frame
*));
278 static void w32_set_terminal_modes
P_ ((void));
279 static void w32_reset_terminal_modes
P_ ((void));
280 static void x_clear_frame
P_ ((void));
281 static void frame_highlight
P_ ((struct frame
*));
282 static void frame_unhighlight
P_ ((struct frame
*));
283 static void x_new_focus_frame
P_ ((struct w32_display_info
*,
285 static void w32_frame_rehighlight
P_ ((struct frame
*));
286 static void x_frame_rehighlight
P_ ((struct w32_display_info
*));
287 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
288 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
289 enum text_cursor_kinds
));
290 static void w32_clip_to_row
P_ ((struct window
*, struct glyph_row
*, HDC
));
292 static Lisp_Object Qvendor_specific_keysyms
;
295 /***********************************************************************
297 ***********************************************************************/
301 /* This is a function useful for recording debugging information about
302 the sequence of occurrences in this file. */
310 struct record event_record
[100];
312 int event_record_index
;
314 record_event (locus
, type
)
318 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
319 event_record_index
= 0;
321 event_record
[event_record_index
].locus
= locus
;
322 event_record
[event_record_index
].type
= type
;
323 event_record_index
++;
330 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
333 if (mask
& GCForeground
)
334 gc
->foreground
= xgcv
->foreground
;
335 if (mask
& GCBackground
)
336 gc
->background
= xgcv
->background
;
338 gc
->font
= xgcv
->font
;
341 XGCValues
*XCreateGC (void * ignore
, Window window
, unsigned long mask
,
344 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
345 bzero (gc
, sizeof (XGCValues
));
347 XChangeGC (ignore
, gc
, mask
, xgcv
);
353 XGetGCValues (void* ignore
, XGCValues
*gc
,
354 unsigned long mask
, XGCValues
*xgcv
)
356 XChangeGC (ignore
, xgcv
, mask
, gc
);
360 w32_set_clip_rectangle (HDC hdc
, RECT
*rect
)
364 HRGN clip_region
= CreateRectRgnIndirect (rect
);
365 SelectClipRgn (hdc
, clip_region
);
366 DeleteObject (clip_region
);
369 SelectClipRgn (hdc
, NULL
);
373 /* Draw a hollow rectangle at the specified position. */
375 w32_draw_rectangle (HDC hdc
, XGCValues
*gc
, int x
, int y
,
376 int width
, int height
)
381 hb
= CreateSolidBrush (gc
->background
);
382 hp
= CreatePen (PS_SOLID
, 0, gc
->foreground
);
383 oldhb
= SelectObject (hdc
, hb
);
384 oldhp
= SelectObject (hdc
, hp
);
386 Rectangle (hdc
, x
, y
, x
+ width
, y
+ height
);
388 SelectObject (hdc
, oldhb
);
389 SelectObject (hdc
, oldhp
);
394 /* Draw a filled rectangle at the specified position. */
396 w32_fill_rect (f
, hdc
, pix
, lprect
)
404 hb
= CreateSolidBrush (pix
);
405 FillRect (hdc
, lprect
, hb
);
414 HDC hdc
= get_frame_dc (f
);
416 /* Under certain conditions, this can be called at startup with
417 a console frame pointer before the GUI frame is created. An HDC
418 of 0 indicates this. */
421 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
422 w32_clear_rect (f
, hdc
, &rect
);
425 release_frame_dc (f
, hdc
);
429 /***********************************************************************
430 Starting and ending an update
431 ***********************************************************************/
433 /* Start an update of frame F. This function is installed as a hook
434 for update_begin, i.e. it is called when update_begin is called.
435 This function is called prior to calls to x_update_window_begin for
436 each window being updated. */
442 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
444 if (! FRAME_W32_P (f
))
447 /* Regenerate display palette before drawing if list of requested
448 colors has changed. */
449 if (display_info
->regen_palette
)
451 w32_regenerate_palette (f
);
452 display_info
->regen_palette
= FALSE
;
457 /* Start update of window W. Set the global variable updated_window
458 to the window being updated and set output_cursor to the cursor
462 x_update_window_begin (w
)
465 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
466 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
468 /* Hide the system caret during an update. */
469 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
471 SendMessage (w32_system_caret_hwnd
, WM_EMACS_HIDE_CARET
, 0, 0);
475 set_output_cursor (&w
->cursor
);
479 if (f
== display_info
->mouse_face_mouse_frame
)
481 /* Don't do highlighting for mouse motion during the update. */
482 display_info
->mouse_face_defer
= 1;
484 /* If F needs to be redrawn, simply forget about any prior mouse
486 if (FRAME_GARBAGED_P (f
))
487 display_info
->mouse_face_window
= Qnil
;
489 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
490 their mouse_face_p flag set, which means that they are always
491 unequal to rows in a desired matrix which never have that
492 flag set. So, rows containing mouse-face glyphs are never
493 scrolled, and we don't have to switch the mouse highlight off
494 here to prevent it from being scrolled. */
496 /* Can we tell that this update does not affect the window
497 where the mouse highlight is? If so, no need to turn off.
498 Likewise, don't do anything if the frame is garbaged;
499 in that case, the frame's current matrix that we would use
500 is all wrong, and we will redisplay that line anyway. */
501 if (!NILP (display_info
->mouse_face_window
)
502 && w
== XWINDOW (display_info
->mouse_face_window
))
506 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
507 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
510 if (i
< w
->desired_matrix
->nrows
)
511 clear_mouse_face (display_info
);
519 /* Draw a vertical window border from (x,y0) to (x,y1) */
522 w32_draw_vertical_window_border (w
, x
, y0
, y1
)
526 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
535 hdc
= get_frame_dc (f
);
536 w32_fill_rect (f
, hdc
, FRAME_FOREGROUND_PIXEL (f
), &r
);
537 release_frame_dc (f
, hdc
);
541 /* End update of window W (which is equal to updated_window).
543 Draw vertical borders between horizontally adjacent windows, and
544 display W's cursor if CURSOR_ON_P is non-zero.
546 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
547 glyphs in mouse-face were overwritten. In that case we have to
548 make sure that the mouse-highlight is properly redrawn.
550 W may be a menu bar pseudo-window in case we don't have X toolkit
551 support. Such windows don't have a cursor, so don't display it
555 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
557 int cursor_on_p
, mouse_face_overwritten_p
;
559 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (XFRAME (w
->frame
));
561 if (!w
->pseudo_window_p
)
566 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
568 output_cursor
.x
, output_cursor
.y
);
570 if (draw_window_fringes (w
, 1))
571 x_draw_vertical_border (w
);
576 /* If a row with mouse-face was overwritten, arrange for
577 XTframe_up_to_date to redisplay the mouse highlight. */
578 if (mouse_face_overwritten_p
)
580 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
581 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
582 dpyinfo
->mouse_face_window
= Qnil
;
585 /* Unhide the caret. This won't actually show the cursor, unless it
586 was visible before the corresponding call to HideCaret in
587 x_update_window_begin. */
588 if (w32_use_visible_system_caret
&& w32_system_caret_hwnd
)
590 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
593 updated_window
= NULL
;
597 /* End update of frame F. This function is installed as a hook in
604 if (! FRAME_W32_P (f
))
607 /* Mouse highlight may be displayed again. */
608 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
612 /* This function is called from various places in xdisp.c whenever a
613 complete update has been performed. The global variable
614 updated_window is not available here. */
617 w32_frame_up_to_date (f
)
622 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
624 if (dpyinfo
->mouse_face_deferred_gc
625 || f
== dpyinfo
->mouse_face_mouse_frame
)
628 if (dpyinfo
->mouse_face_mouse_frame
)
629 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
630 dpyinfo
->mouse_face_mouse_x
,
631 dpyinfo
->mouse_face_mouse_y
);
632 dpyinfo
->mouse_face_deferred_gc
= 0;
639 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
640 arrow bitmaps, or clear the fringes if no bitmaps are required
641 before DESIRED_ROW is made current. The window being updated is
642 found in updated_window. This function is called from
643 update_window_line only if it is known that there are differences
644 between bitmaps to be drawn between current row and DESIRED_ROW. */
647 x_after_update_window_line (desired_row
)
648 struct glyph_row
*desired_row
;
650 struct window
*w
= updated_window
;
656 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
657 desired_row
->redraw_fringe_bitmaps_p
= 1;
659 /* When a window has disappeared, make sure that no rest of
660 full-width rows stays visible in the internal border. Could
661 check here if updated_window is the leftmost/rightmost window,
662 but I guess it's not worth doing since vertically split windows
663 are almost never used, internal border is rarely set, and the
664 overhead is very small. */
665 if (windows_or_buffers_changed
666 && desired_row
->full_width_p
667 && (f
= XFRAME (w
->frame
),
668 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
670 && (height
= desired_row
->visible_height
,
673 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
675 /* Internal border is drawn below the tool bar. */
676 if (WINDOWP (f
->tool_bar_window
)
677 && w
== XWINDOW (f
->tool_bar_window
))
682 HDC hdc
= get_frame_dc (f
);
683 w32_clear_area (f
, hdc
, 0, y
, width
, height
);
684 w32_clear_area (f
, hdc
, FRAME_PIXEL_WIDTH (f
) - width
,
686 release_frame_dc (f
, hdc
);
693 /* Draw the bitmap WHICH in one of the left or right fringes of
694 window W. ROW is the glyph row for which to display the bitmap; it
695 determines the vertical position at which the bitmap has to be
699 w32_draw_fringe_bitmap (w
, row
, p
)
701 struct glyph_row
*row
;
702 struct draw_fringe_bitmap_params
*p
;
704 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
706 struct face
*face
= p
->face
;
709 hdc
= get_frame_dc (f
);
711 /* Must clip because of partially visible lines. */
712 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
715 /* Adjust position of "bottom aligned" bitmap on partially
718 int oldVH
= row
->visible_height
;
719 row
->visible_height
= p
->h
;
720 row
->y
-= rowY
- p
->y
;
721 w32_clip_to_row (w
, row
, hdc
);
723 row
->visible_height
= oldVH
;
726 w32_clip_to_row (w
, row
, hdc
);
728 if (p
->bx
>= 0 && !p
->overlay_p
)
730 w32_fill_area (f
, hdc
, face
->background
,
731 p
->bx
, p
->by
, p
->nx
, p
->ny
);
734 if (p
->which
&& p
->which
< max_fringe_bmp
)
736 HBITMAP pixmap
= fringe_bmp
[p
->which
];
740 compat_hdc
= CreateCompatibleDC (hdc
);
744 horig_obj
= SelectObject (compat_hdc
, pixmap
);
746 /* Paint overlays transparently. */
749 HBRUSH h_brush
, h_orig_brush
;
751 SetTextColor (hdc
, BLACK_PIX_DEFAULT (f
));
752 SetBkColor (hdc
, WHITE_PIX_DEFAULT (f
));
753 h_brush
= CreateSolidBrush (face
->foreground
);
754 h_orig_brush
= SelectObject (hdc
, h_brush
);
756 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
757 compat_hdc
, 0, p
->dh
,
759 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
760 compat_hdc
, 0, p
->dh
,
762 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
763 compat_hdc
, 0, p
->dh
,
766 SelectObject (hdc
, h_orig_brush
);
767 DeleteObject (h_brush
);
771 SetTextColor (hdc
, face
->background
);
772 SetBkColor (hdc
, (p
->cursor_p
773 ? f
->output_data
.w32
->cursor_pixel
774 : face
->foreground
));
776 BitBlt (hdc
, p
->x
, p
->y
, p
->wd
, p
->h
,
777 compat_hdc
, 0, p
->dh
,
781 SelectObject (compat_hdc
, horig_obj
);
782 DeleteDC (compat_hdc
);
786 w32_set_clip_rectangle (hdc
, NULL
);
788 release_frame_dc (f
, hdc
);
792 w32_define_fringe_bitmap (which
, bits
, h
, wd
)
794 unsigned short *bits
;
797 if (which
>= max_fringe_bmp
)
799 int i
= max_fringe_bmp
;
800 max_fringe_bmp
= which
+ 20;
801 fringe_bmp
= (HBITMAP
*) xrealloc (fringe_bmp
, max_fringe_bmp
* sizeof (HBITMAP
));
802 while (i
< max_fringe_bmp
)
806 fringe_bmp
[which
] = CreateBitmap (wd
, h
, 1, 1, bits
);
810 w32_destroy_fringe_bitmap (which
)
813 if (which
>= max_fringe_bmp
)
816 if (fringe_bmp
[which
])
817 DeleteObject (fringe_bmp
[which
]);
818 fringe_bmp
[which
] = 0;
823 /* This is called when starting Emacs and when restarting after
824 suspend. When starting Emacs, no window is mapped. And nothing
825 must be done to Emacs's own window if it is suspended (though that
829 w32_set_terminal_modes (void)
833 /* This is called when exiting or suspending Emacs. Exiting will make
834 the W32 windows go away, and suspending requires no action. */
837 w32_reset_terminal_modes (void)
843 /***********************************************************************
845 ***********************************************************************/
847 /* Function prototypes of this page. */
849 static XCharStruct
*w32_per_char_metric
P_ ((XFontStruct
*,
851 static int w32_encode_char
P_ ((int, wchar_t *, struct font_info
*,
852 struct charset
*, int *));
855 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
856 If CHAR2B is not contained in FONT, the font's default character
857 metric is returned. */
860 w32_bdf_per_char_metric (font
, char2b
, dim
, pcm
)
866 glyph_metric
* bdf_metric
;
870 buf
[0] = (char)(*char2b
);
873 buf
[0] = XCHAR2B_BYTE1 (char2b
);
874 buf
[1] = XCHAR2B_BYTE2 (char2b
);
877 bdf_metric
= w32_BDF_TextMetric (font
->bdf
, buf
, dim
);
881 pcm
->width
= bdf_metric
->dwidth
;
882 pcm
->lbearing
= bdf_metric
->bbox
;
883 pcm
->rbearing
= bdf_metric
->dwidth
884 - (bdf_metric
->bbox
+ bdf_metric
->bbw
);
885 pcm
->ascent
= bdf_metric
->bboy
+ bdf_metric
->bbh
;
886 pcm
->descent
= -bdf_metric
->bboy
;
895 w32_native_per_char_metric (font
, char2b
, font_type
, pcm
)
898 enum w32_char_font_type font_type
;
901 HDC hdc
= GetDC (NULL
);
905 xassert (font
&& char2b
);
906 xassert (font
->hfont
);
907 xassert (font_type
== UNICODE_FONT
|| font_type
== ANSI_FONT
);
909 old_font
= SelectObject (hdc
, font
->hfont
);
911 if ((font
->tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) != 0)
915 if (font_type
== UNICODE_FONT
)
916 retval
= GetCharABCWidthsW (hdc
, *char2b
, *char2b
, &char_widths
);
918 retval
= GetCharABCWidthsA (hdc
, *char2b
, *char2b
, &char_widths
);
923 /* Disabled until we can find a way to get the right results
924 on all versions of Windows. */
926 /* Don't trust the ABC widths. For synthesized fonts they are
927 wrong, and so is the result of GetCharWidth()! */
929 GetCharWidth (hdc
, *char2b
, *char2b
, &real_width
);
931 pcm
->width
= char_widths
.abcA
+ char_widths
.abcB
+ char_widths
.abcC
;
933 /* As far as I can tell, this is the best way to determine what
934 ExtTextOut will do with the broken font. */
935 if (pcm
->width
!= real_width
)
936 pcm
->width
= (pcm
->width
+ real_width
) / 2;
938 pcm
->lbearing
= char_widths
.abcA
;
939 pcm
->rbearing
= char_widths
.abcA
+ char_widths
.abcB
;
940 pcm
->ascent
= FONT_BASE (font
);
941 pcm
->descent
= FONT_DESCENT (font
);
947 /* Either font is not a True-type font, or GetCharABCWidthsW
948 failed (it is not supported on Windows 9x for instance), so we
949 can't determine the full info we would like. All is not lost
950 though - we can call GetTextExtentPoint32 to get rbearing and
951 deduce width based on the font's per-string overhang. lbearing
952 is assumed to be zero. */
954 /* TODO: Some Thai characters (and other composites if Windows
955 supports them) do have lbearing, and report their total width
956 as zero. Need some way of handling them when
957 GetCharABCWidthsW fails. */
960 if (font_type
== UNICODE_FONT
)
961 retval
= GetTextExtentPoint32W (hdc
, char2b
, 1, &sz
);
963 retval
= GetTextExtentPoint32A (hdc
, (char*)char2b
, 1, &sz
);
967 pcm
->width
= sz
.cx
- font
->tm
.tmOverhang
;
968 pcm
->rbearing
= sz
.cx
;
970 pcm
->ascent
= FONT_BASE (font
);
971 pcm
->descent
= FONT_DESCENT (font
);
976 if (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0)
981 SelectObject (hdc
, old_font
);
982 ReleaseDC (NULL
, hdc
);
989 w32_per_char_metric (font
, char2b
, font_type
)
992 int /* enum w32_char_font_type */ font_type
;
994 /* The result metric information. */
998 xassert (font
&& char2b
);
1000 /* TODO: This function is currently called through the RIF, and in
1001 some cases font_type is UNKNOWN_FONT. We currently allow the
1002 cached metrics to be used, which seems to work, but in cases
1003 where font_type is UNKNOWN_FONT, we probably haven't encoded
1004 char2b appropriately. All callers need checking to see what they
1005 are passing. This is most likely to affect variable width fonts
1006 outside the Latin-1 range, particularly in languages like Thai
1007 that rely on rbearing and lbearing to provide composition. I
1008 don't think that is working currently anyway, but we don't seem
1009 to have anyone testing such languages on Windows. */
1011 /* Handle the common cases quickly. */
1012 if (!font
->bdf
&& font
->per_char
== NULL
)
1013 /* TODO: determine whether char2b exists in font? */
1014 return &font
->max_bounds
;
1015 else if (!font
->bdf
&& *char2b
< 128)
1016 return &font
->per_char
[*char2b
];
1018 xassert (font_type
!= UNKNOWN_FONT
);
1020 pcm
= &font
->scratch
;
1022 if (font_type
== BDF_1D_FONT
)
1023 retval
= w32_bdf_per_char_metric (font
, char2b
, 1, pcm
);
1024 else if (font_type
== BDF_2D_FONT
)
1025 retval
= w32_bdf_per_char_metric (font
, char2b
, 2, pcm
);
1027 retval
= w32_native_per_char_metric (font
, char2b
, font_type
, pcm
);
1036 w32_cache_char_metrics (font
)
1039 wchar_t char2b
= L
'x';
1041 /* Cache char metrics for the common cases. */
1044 /* TODO: determine whether font is fixed-pitch. */
1045 if (!w32_bdf_per_char_metric (font
, &char2b
, 1, &font
->max_bounds
))
1047 /* Use the font width and height as max bounds, as not all BDF
1048 fonts contain the letter 'x'. */
1049 font
->max_bounds
.width
= FONT_MAX_WIDTH (font
);
1050 font
->max_bounds
.lbearing
= -font
->bdf
->llx
;
1051 font
->max_bounds
.rbearing
= FONT_MAX_WIDTH (font
) - font
->bdf
->urx
;
1052 font
->max_bounds
.ascent
= FONT_BASE (font
);
1053 font
->max_bounds
.descent
= FONT_DESCENT (font
);
1058 if (((font
->tm
.tmPitchAndFamily
& TMPF_FIXED_PITCH
) != 0)
1059 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1060 though they contain characters of different widths. */
1061 || (font
->tm
.tmMaxCharWidth
!= font
->tm
.tmAveCharWidth
))
1063 /* Font is not fixed pitch, so cache per_char info for the
1064 ASCII characters. It would be much more work, and probably
1065 not worth it, to cache other chars, since we may change
1066 between using Unicode and ANSI text drawing functions at
1070 font
->per_char
= xmalloc (128 * sizeof(XCharStruct
));
1071 for (i
= 0; i
< 128; i
++)
1074 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1075 &font
->per_char
[i
]);
1079 w32_native_per_char_metric (font
, &char2b
, ANSI_FONT
,
1085 /* Determine if a font is double byte. */
1086 int w32_font_is_double_byte (XFontStruct
*font
)
1088 return font
->double_byte_p
;
1093 w32_use_unicode_for_codepage (codepage
)
1096 /* If the current codepage is supported, use Unicode for output. */
1097 return (w32_enable_unicode_output
1098 && codepage
!= CP_8BIT
1099 && (codepage
== CP_UNICODE
|| IsValidCodePage (codepage
)));
1102 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1103 the two-byte form of C. Encoding is returned in *CHAR2B. */
1105 static int /* enum w32_char_font_type */
1106 w32_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1109 struct font_info
*font_info
;
1110 struct charset
*charset
;
1115 int internal_two_byte_p
= 0;
1117 XFontStruct
*font
= font_info
->font
;
1119 internal_two_byte_p
= w32_font_is_double_byte (font
);
1120 codepage
= font_info
->codepage
;
1122 /* If font can output unicode, use the original unicode character. */
1123 if ( font
&& !font
->bdf
&& w32_use_unicode_for_codepage (codepage
)
1128 internal_two_byte_p
= 1;
1131 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1132 This may be either a program in a special encoder language or a
1134 else if (font_info
->font_encoder
)
1136 /* It's a program. */
1137 struct ccl_program
*ccl
= font_info
->font_encoder
;
1139 if (CHARSET_DIMENSION (charset
) == 1)
1141 ccl
->reg
[0] = CHARSET_ID (charset
);
1142 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1147 ccl
->reg
[0] = CHARSET_ID (charset
);
1148 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1149 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1152 ccl_driver (ccl
, NULL
, NULL
, 0, 0, Qnil
);
1154 /* We assume that MSBs are appropriately set/reset by CCL
1156 if (!internal_two_byte_p
) /* 1-byte font */
1157 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
1159 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
1161 else if (font_info
->encoding_type
)
1163 /* Fixed encoding scheme. See fontset.h for the meaning of the
1164 encoding numbers. */
1165 unsigned char enc
= font_info
->encoding_type
;
1167 if ((enc
== 1 || enc
== 2)
1168 && CHARSET_DIMENSION (charset
) == 2)
1169 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
) | 0x80, XCHAR2B_BYTE2 (char2b
));
1171 if (enc
== 1 || enc
== 3 || (enc
== 4 && CHARSET_DIMENSION (charset
) == 1))
1172 STORE_XCHAR2B (char2b
, XCHAR2B_BYTE1 (char2b
), XCHAR2B_BYTE2 (char2b
) | 0x80);
1175 int code
= (int) (*char2b
);
1178 STORE_XCHAR2B (char2b
, (code
>> 8), (code
& 0xFF));
1183 *two_byte_p
= internal_two_byte_p
;
1186 return UNKNOWN_FONT
;
1187 else if (font
->bdf
&& CHARSET_DIMENSION (charset
) == 1)
1192 return UNICODE_FONT
;
1198 /* Return a char-table whose elements are t if the font FONT_INFO
1199 contains a glyph for the corresponding character, and nil if not.
1201 Fixme: For the moment, this function works only for fonts whose
1202 glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts). */
1205 x_get_font_repertory (f
, font_info
)
1207 struct font_info
*font_info
;
1209 XFontStruct
*font
= (XFontStruct
*) font_info
->font
;
1211 int min_byte1
, max_byte1
, min_byte2
, max_byte2
;
1213 table
= Fmake_char_table (Qnil
, Qnil
);
1215 if (!font
->bdf
&& pfnGetFontUnicodeRanges
)
1218 DWORD glyphset_size
;
1219 HDC display
= get_frame_dc (f
);
1223 prev_font
= SelectObject (display
, font
->hfont
);
1225 /* First call GetFontUnicodeRanges to find out how big a structure
1227 glyphset_size
= pfnGetFontUnicodeRanges (display
, NULL
);
1230 glyphset
= (GLYPHSET
*) alloca (glyphset_size
);
1231 glyphset
->cbThis
= glyphset_size
;
1233 /* Now call it again to get the ranges. */
1234 glyphset_size
= pfnGetFontUnicodeRanges (display
, glyphset
);
1238 /* Store the ranges in TABLE. */
1239 for (i
= 0; i
< glyphset
->cRanges
; i
++)
1241 int from
= glyphset
->ranges
[i
].wcLow
;
1242 int to
= from
+ glyphset
->ranges
[i
].cGlyphs
- 1;
1243 char_table_set_range (table
, from
, to
, Qt
);
1248 SelectObject (display
, prev_font
);
1249 release_frame_dc (f
, display
);
1251 /* If we got the information we wanted above, then return it. */
1256 #if 0 /* TODO: Convert to work on Windows so BDF and older platforms work. */
1257 /* When GetFontUnicodeRanges is not available or does not work,
1258 work it out manually. */
1259 min_byte1
= font
->min_byte1
;
1260 max_byte1
= font
->max_byte1
;
1261 min_byte2
= font
->min_char_or_byte2
;
1262 max_byte2
= font
->max_char_or_byte2
;
1263 if (min_byte1
== 0 && max_byte1
== 0)
1265 if (! font
->per_char
|| font
->all_chars_exist
== True
)
1266 char_table_set_range (table
, min_byte2
, max_byte2
, Qt
);
1269 XCharStruct
*pcm
= font
->per_char
;
1273 for (i
= min_byte2
; i
<= max_byte2
; i
++, pcm
++)
1275 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
1279 char_table_set_range (table
, from
, i
- 1, Qt
);
1287 char_table_set_range (table
, from
, i
- 1, Qt
);
1292 if (! font
->per_char
|| font
->all_chars_exist
== True
)
1296 for (i
= min_byte1
; i
<= max_byte1
; i
++)
1297 char_table_set_range (table
,
1298 (i
<< 8) | min_byte2
, (i
<< 8) | max_byte2
,
1303 XCharStruct
*pcm
= font
->per_char
;
1306 for (i
= min_byte1
; i
<= max_byte1
; i
++)
1311 for (j
= min_byte2
; j
<= max_byte2
; j
++, pcm
++)
1313 if (pcm
->width
== 0 && pcm
->rbearing
== pcm
->lbearing
)
1317 char_table_set_range (table
, (i
<< 8) | from
,
1318 (i
<< 8) | (j
- 1), Qt
);
1326 char_table_set_range (table
, (i
<< 8) | from
,
1327 (i
<< 8) | (j
- 1), Qt
);
1336 /***********************************************************************
1338 ***********************************************************************/
1341 /* Encapsulate the different ways of displaying text under W32. */
1344 w32_text_out (s
, x
, y
,chars
,nchars
)
1345 struct glyph_string
* s
;
1350 int charset_dim
= w32_font_is_double_byte (s
->font
) ? 2 : 1;
1352 w32_BDF_TextOut (s
->font
->bdf
, s
->hdc
,
1353 x
, y
, (char *) chars
, charset_dim
,
1354 nchars
* charset_dim
, 0);
1355 else if (s
->first_glyph
->font_type
== UNICODE_FONT
)
1356 ExtTextOutW (s
->hdc
, x
, y
, 0, NULL
, chars
, nchars
, NULL
);
1358 ExtTextOutA (s
->hdc
, x
, y
, 0, NULL
, (char *) chars
,
1359 nchars
* charset_dim
, NULL
);
1363 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1364 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1365 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1367 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1368 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1369 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1370 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1371 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1372 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1373 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1374 static int w32_alloc_lighter_color (struct frame
*, COLORREF
*, double, int);
1375 static void w32_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1376 double, int, COLORREF
));
1377 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1378 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1379 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1380 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1381 static void w32_draw_image_foreground_1
P_ ((struct glyph_string
*, HBITMAP
));
1382 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1384 static void w32_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1385 int, int, int, int, int, int,
1387 static void w32_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1388 int, int, int, RECT
*));
1391 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1395 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1400 struct glyph_string
*s
;
1402 if (s
->font
== FRAME_FONT (s
->f
)
1403 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1404 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1406 s
->gc
= s
->f
->output_data
.w32
->cursor_gc
;
1409 /* Cursor on non-default face: must merge. */
1413 xgcv
.background
= s
->f
->output_data
.w32
->cursor_pixel
;
1414 xgcv
.foreground
= s
->face
->background
;
1416 /* If the glyph would be invisible, try a different foreground. */
1417 if (xgcv
.foreground
== xgcv
.background
)
1418 xgcv
.foreground
= s
->face
->foreground
;
1419 if (xgcv
.foreground
== xgcv
.background
)
1420 xgcv
.foreground
= s
->f
->output_data
.w32
->cursor_foreground_pixel
;
1421 if (xgcv
.foreground
== xgcv
.background
)
1422 xgcv
.foreground
= s
->face
->foreground
;
1424 /* Make sure the cursor is distinct from text in this face. */
1425 if (xgcv
.background
== s
->face
->background
1426 && xgcv
.foreground
== s
->face
->foreground
)
1428 xgcv
.background
= s
->face
->foreground
;
1429 xgcv
.foreground
= s
->face
->background
;
1432 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1433 xgcv
.font
= s
->font
;
1434 mask
= GCForeground
| GCBackground
| GCFont
;
1436 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1437 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1440 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1441 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1443 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1448 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1451 x_set_mouse_face_gc (s
)
1452 struct glyph_string
*s
;
1457 /* What face has to be used last for the mouse face? */
1458 face_id
= FRAME_W32_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1459 face
= FACE_FROM_ID (s
->f
, face_id
);
1461 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1463 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1464 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1466 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1467 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1468 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1470 /* If font in this face is same as S->font, use it. */
1471 if (s
->font
== s
->face
->font
)
1472 s
->gc
= s
->face
->gc
;
1475 /* Otherwise construct scratch_cursor_gc with values from FACE
1480 xgcv
.background
= s
->face
->background
;
1481 xgcv
.foreground
= s
->face
->foreground
;
1482 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1483 xgcv
.font
= s
->font
;
1484 mask
= GCForeground
| GCBackground
| GCFont
;
1486 if (FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1487 XChangeGC (NULL
, FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1490 FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1491 = XCreateGC (NULL
, s
->window
, mask
, &xgcv
);
1493 s
->gc
= FRAME_W32_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1496 xassert (s
->gc
!= 0);
1500 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1501 Faces to use in the mode line have already been computed when the
1502 matrix was built, so there isn't much to do, here. */
1505 x_set_mode_line_face_gc (s
)
1506 struct glyph_string
*s
;
1508 s
->gc
= s
->face
->gc
;
1512 /* Set S->gc of glyph string S for drawing that glyph string. Set
1513 S->stippled_p to a non-zero value if the face of S has a stipple
1517 x_set_glyph_string_gc (s
)
1518 struct glyph_string
*s
;
1520 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1522 if (s
->hl
== DRAW_NORMAL_TEXT
)
1524 s
->gc
= s
->face
->gc
;
1525 s
->stippled_p
= s
->face
->stipple
!= 0;
1527 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1529 x_set_mode_line_face_gc (s
);
1530 s
->stippled_p
= s
->face
->stipple
!= 0;
1532 else if (s
->hl
== DRAW_CURSOR
)
1534 x_set_cursor_gc (s
);
1537 else if (s
->hl
== DRAW_MOUSE_FACE
)
1539 x_set_mouse_face_gc (s
);
1540 s
->stippled_p
= s
->face
->stipple
!= 0;
1542 else if (s
->hl
== DRAW_IMAGE_RAISED
1543 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1545 s
->gc
= s
->face
->gc
;
1546 s
->stippled_p
= s
->face
->stipple
!= 0;
1550 s
->gc
= s
->face
->gc
;
1551 s
->stippled_p
= s
->face
->stipple
!= 0;
1554 /* GC must have been set. */
1555 xassert (s
->gc
!= 0);
1559 /* Set clipping for output of glyph string S. S may be part of a mode
1560 line or menu if we don't have X toolkit support. */
1563 x_set_glyph_string_clipping (s
)
1564 struct glyph_string
*s
;
1567 get_glyph_string_clip_rect (s
, &r
);
1568 w32_set_clip_rectangle (s
->hdc
, &r
);
1573 Compute left and right overhang of glyph string S. If S is a glyph
1574 string for a composition, assume overhangs don't exist. */
1577 w32_compute_glyph_string_overhangs (s
)
1578 struct glyph_string
*s
;
1580 /* TODO: Windows does not appear to have a method for
1581 getting this info without getting the ABC widths for each
1582 individual character and working it out manually. */
1587 w32_get_glyph_overhangs (glyph
, f
, left
, right
)
1588 struct glyph
*glyph
;
1592 HDC hdc
= get_frame_dc (f
);
1593 /* Convert to unicode! */
1594 x_get_glyph_overhangs (glyph
, f
, left
, right
);
1595 release_frame_dc (f
, hdc
);
1599 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1602 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1603 struct glyph_string
*s
;
1611 /* Take clipping into account. */
1612 if (s
->gc
->clip_mask
== Rect
)
1614 real_x
= max (real_x
, s
->gc
->clip_rectangle
.left
);
1615 real_y
= max (real_y
, s
->gc
->clip_rectangle
.top
);
1616 real_w
= min (real_w
, s
->gc
->clip_rectangle
.right
1617 - s
->gc
->clip_rectangle
.left
);
1618 real_h
= min (real_h
, s
->gc
->clip_rectangle
.bottom
1619 - s
->gc
->clip_rectangle
.top
);
1622 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->background
, real_x
, real_y
,
1627 /* Draw the background of glyph_string S. If S->background_filled_p
1628 is non-zero don't draw it. FORCE_P non-zero means draw the
1629 background even if it wouldn't be drawn normally. This is used
1630 when a string preceding S draws into the background of S, or S
1631 contains the first component of a composition. */
1634 x_draw_glyph_string_background (s
, force_p
)
1635 struct glyph_string
*s
;
1638 /* Nothing to do if background has already been drawn or if it
1639 shouldn't be drawn in the first place. */
1640 if (!s
->background_filled_p
)
1642 int box_line_width
= max (s
->face
->box_line_width
, 0);
1644 #if 0 /* TODO: stipple */
1647 /* Fill background with a stipple pattern. */
1648 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1649 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1650 s
->y
+ box_line_width
,
1651 s
->background_width
,
1652 s
->height
- 2 * box_line_width
);
1653 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1654 s
->background_filled_p
= 1;
1658 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1659 || s
->font_not_found_p
1660 || s
->extends_to_end_of_line_p
1664 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1665 s
->background_width
,
1666 s
->height
- 2 * box_line_width
);
1667 s
->background_filled_p
= 1;
1673 /* Draw the foreground of glyph string S. */
1676 x_draw_glyph_string_foreground (s
)
1677 struct glyph_string
*s
;
1682 /* If first glyph of S has a left box line, start drawing the text
1683 of S to the right of that box line. */
1684 if (s
->face
->box
!= FACE_NO_BOX
1685 && s
->first_glyph
->left_box_line_p
)
1686 x
= s
->x
+ abs (s
->face
->box_line_width
);
1690 if (s
->for_overlaps_p
|| (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
1691 SetBkMode (s
->hdc
, TRANSPARENT
);
1693 SetBkMode (s
->hdc
, OPAQUE
);
1695 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1696 SetBkColor (s
->hdc
, s
->gc
->background
);
1697 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1699 if (s
->font
&& s
->font
->hfont
)
1700 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1702 /* Draw characters of S as rectangles if S's font could not be
1704 if (s
->font_not_found_p
)
1706 for (i
= 0; i
< s
->nchars
; ++i
)
1708 struct glyph
*g
= s
->first_glyph
+ i
;
1710 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
1712 x
+= g
->pixel_width
;
1717 char *char1b
= (char *) s
->char2b
;
1718 int boff
= s
->font_info
->baseline_offset
;
1720 if (s
->font_info
->vertical_centering
)
1721 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
1723 /* If we can use 8-bit functions, condense S->char2b. */
1725 for (i
= 0; i
< s
->nchars
; ++i
)
1726 char1b
[i
] = XCHAR2B_BYTE2 (&s
->char2b
[i
]);
1728 /* Draw text with TextOut and friends. */
1729 w32_text_out (s
, x
, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1731 if (s
->face
->overstrike
)
1733 /* For overstriking (to simulate bold-face), draw the
1734 characters again shifted to the right by one pixel. */
1735 w32_text_out (s
, x
+ 1, s
->ybase
- boff
, s
->char2b
, s
->nchars
);
1738 if (s
->font
&& s
->font
->hfont
)
1739 SelectObject (s
->hdc
, old_font
);
1742 /* Draw the foreground of composite glyph string S. */
1745 x_draw_composite_glyph_string_foreground (s
)
1746 struct glyph_string
*s
;
1751 /* If first glyph of S has a left box line, start drawing the text
1752 of S to the right of that box line. */
1753 if (s
->face
->box
!= FACE_NO_BOX
1754 && s
->first_glyph
->left_box_line_p
)
1755 x
= s
->x
+ abs (s
->face
->box_line_width
);
1759 /* S is a glyph string for a composition. S->gidx is the index of
1760 the first character drawn for glyphs of this composition.
1761 S->gidx == 0 means we are drawing the very first character of
1762 this composition. */
1764 SetTextColor (s
->hdc
, s
->gc
->foreground
);
1765 SetBkColor (s
->hdc
, s
->gc
->background
);
1766 SetBkMode (s
->hdc
, TRANSPARENT
);
1767 SetTextAlign (s
->hdc
, TA_BASELINE
| TA_LEFT
);
1769 if (s
->font
&& s
->font
->hfont
)
1770 old_font
= SelectObject (s
->hdc
, s
->font
->hfont
);
1772 /* Draw a rectangle for the composition if the font for the very
1773 first character of the composition could not be loaded. */
1774 if (s
->font_not_found_p
)
1777 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, s
->y
, s
->width
- 1,
1782 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
1784 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2],
1785 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1787 if (s
->face
->overstrike
)
1788 w32_text_out (s
, x
+ s
->cmp
->offsets
[s
->gidx
* 2] + 1,
1789 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
1794 if (s
->font
&& s
->font
->hfont
)
1795 SelectObject (s
->hdc
, old_font
);
1799 /* Brightness beyond which a color won't have its highlight brightness
1802 Nominally, highlight colors for `3d' faces are calculated by
1803 brightening an object's color by a constant scale factor, but this
1804 doesn't yield good results for dark colors, so for colors who's
1805 brightness is less than this value (on a scale of 0-255) have to
1806 use an additional additive factor.
1808 The value here is set so that the default menu-bar/mode-line color
1809 (grey75) will not have its highlights changed at all. */
1810 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1813 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1814 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1815 If this produces the same color as COLOR, try a color where all RGB
1816 values have DELTA added. Return the allocated color in *COLOR.
1817 DISPLAY is the X display, CMAP is the colormap to operate on.
1818 Value is non-zero if successful. */
1821 w32_alloc_lighter_color (f
, color
, factor
, delta
)
1830 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1833 /* Change RGB values by specified FACTOR. Avoid overflow! */
1834 xassert (factor
>= 0);
1835 new = PALETTERGB (min (0xff, factor
* GetRValue (*color
)),
1836 min (0xff, factor
* GetGValue (*color
)),
1837 min (0xff, factor
* GetBValue (*color
)));
1839 /* Calculate brightness of COLOR. */
1840 bright
= (2 * GetRValue (*color
) + 3 * GetGValue (*color
)
1841 + GetBValue (*color
)) / 6;
1843 /* We only boost colors that are darker than
1844 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1845 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
1846 /* Make an additive adjustment to NEW, because it's dark enough so
1847 that scaling by FACTOR alone isn't enough. */
1849 /* How far below the limit this color is (0 - 1, 1 being darker). */
1850 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
1851 /* The additive adjustment. */
1852 int min_delta
= delta
* dimness
* factor
/ 2;
1855 new = PALETTERGB (max (0, min (0xff, min_delta
- GetRValue (*color
))),
1856 max (0, min (0xff, min_delta
- GetGValue (*color
))),
1857 max (0, min (0xff, min_delta
- GetBValue (*color
))));
1859 new = PALETTERGB (max (0, min (0xff, min_delta
+ GetRValue (*color
))),
1860 max (0, min (0xff, min_delta
+ GetGValue (*color
))),
1861 max (0, min (0xff, min_delta
+ GetBValue (*color
))));
1865 new = PALETTERGB (max (0, min (0xff, delta
+ GetRValue (*color
))),
1866 max (0, min (0xff, delta
+ GetGValue (*color
))),
1867 max (0, min (0xff, delta
+ GetBValue (*color
))));
1869 /* TODO: Map to palette and retry with delta if same? */
1870 /* TODO: Free colors (if using palette)? */
1881 /* Set up the foreground color for drawing relief lines of glyph
1882 string S. RELIEF is a pointer to a struct relief containing the GC
1883 with which lines will be drawn. Use a color that is FACTOR or
1884 DELTA lighter or darker than the relief's background which is found
1885 in S->f->output_data.x->relief_background. If such a color cannot
1886 be allocated, use DEFAULT_PIXEL, instead. */
1889 w32_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
1891 struct relief
*relief
;
1894 COLORREF default_pixel
;
1897 struct w32_output
*di
= f
->output_data
.w32
;
1898 unsigned long mask
= GCForeground
;
1900 COLORREF background
= di
->relief_background
;
1901 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
1903 /* TODO: Free colors (if using palette)? */
1905 /* Allocate new color. */
1906 xgcv
.foreground
= default_pixel
;
1908 if (w32_alloc_lighter_color (f
, &pixel
, factor
, delta
))
1910 relief
->allocated_p
= 1;
1911 xgcv
.foreground
= relief
->pixel
= pixel
;
1914 if (relief
->gc
== 0)
1916 #if 0 /* TODO: stipple */
1917 xgcv
.stipple
= dpyinfo
->gray
;
1920 relief
->gc
= XCreateGC (NULL
, FRAME_W32_WINDOW (f
), mask
, &xgcv
);
1923 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
1927 /* Set up colors for the relief lines around glyph string S. */
1930 x_setup_relief_colors (s
)
1931 struct glyph_string
*s
;
1933 struct w32_output
*di
= s
->f
->output_data
.w32
;
1936 if (s
->face
->use_box_color_for_shadows_p
)
1937 color
= s
->face
->box_color
;
1938 else if (s
->first_glyph
->type
== IMAGE_GLYPH
1940 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
1941 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
1943 color
= s
->gc
->background
;
1945 if (di
->white_relief
.gc
== 0
1946 || color
!= di
->relief_background
)
1948 di
->relief_background
= color
;
1949 w32_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
1950 WHITE_PIX_DEFAULT (s
->f
));
1951 w32_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
1952 BLACK_PIX_DEFAULT (s
->f
));
1957 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1958 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1959 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1960 relief. LEFT_P non-zero means draw a relief on the left side of
1961 the rectangle. RIGHT_P non-zero means draw a relief on the right
1962 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1966 w32_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
1967 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
1969 int left_x
, top_y
, right_x
, bottom_y
, width
;
1970 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
1975 HDC hdc
= get_frame_dc (f
);
1978 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
1980 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
1982 w32_set_clip_rectangle (hdc
, clip_rect
);
1986 for (i
= 0; i
< width
; ++i
)
1987 w32_fill_area (f
, hdc
, gc
.foreground
,
1988 left_x
+ i
* left_p
, top_y
+ i
,
1989 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
1993 for (i
= 0; i
< width
; ++i
)
1994 w32_fill_area (f
, hdc
, gc
.foreground
,
1995 left_x
+ i
, top_y
+ i
, 1,
1996 bottom_y
- top_y
- 2 * i
+ 1);
1999 gc
.foreground
= f
->output_data
.w32
->black_relief
.gc
->foreground
;
2001 gc
.foreground
= f
->output_data
.w32
->white_relief
.gc
->foreground
;
2005 for (i
= 0; i
< width
; ++i
)
2006 w32_fill_area (f
, hdc
, gc
.foreground
,
2007 left_x
+ i
* left_p
, bottom_y
- i
,
2008 right_x
- left_x
- i
* (left_p
+ right_p
) + 1, 1);
2012 for (i
= 0; i
< width
; ++i
)
2013 w32_fill_area (f
, hdc
, gc
.foreground
,
2014 right_x
- i
, top_y
+ i
+ 1, 1,
2015 bottom_y
- top_y
- 2 * i
- 1);
2017 w32_set_clip_rectangle (hdc
, NULL
);
2019 release_frame_dc (f
, hdc
);
2023 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2024 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2025 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2026 left side of the rectangle. RIGHT_P non-zero means draw a line
2027 on the right side of the rectangle. CLIP_RECT is the clipping
2028 rectangle to use when drawing. */
2031 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2032 left_p
, right_p
, clip_rect
)
2033 struct glyph_string
*s
;
2034 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2037 w32_set_clip_rectangle (s
->hdc
, clip_rect
);
2040 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2041 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2046 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2047 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2051 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2052 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2057 w32_fill_area (s
->f
, s
->hdc
, s
->face
->box_color
,
2058 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2061 w32_set_clip_rectangle (s
->hdc
, NULL
);
2065 /* Draw a box around glyph string S. */
2068 x_draw_glyph_string_box (s
)
2069 struct glyph_string
*s
;
2071 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2072 int left_p
, right_p
;
2073 struct glyph
*last_glyph
;
2076 last_x
= window_box_right (s
->w
, s
->area
);
2077 if (s
->row
->full_width_p
2078 && !s
->w
->pseudo_window_p
)
2080 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2081 if (s
->area
!= RIGHT_MARGIN_AREA
2082 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2083 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2086 /* The glyph that may have a right box line. */
2087 last_glyph
= (s
->cmp
|| s
->img
2089 : s
->first_glyph
+ s
->nchars
- 1);
2091 width
= abs (s
->face
->box_line_width
);
2092 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2094 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2096 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2098 bottom_y
= top_y
+ s
->height
- 1;
2100 left_p
= (s
->first_glyph
->left_box_line_p
2101 || (s
->hl
== DRAW_MOUSE_FACE
2103 || s
->prev
->hl
!= s
->hl
)));
2104 right_p
= (last_glyph
->right_box_line_p
2105 || (s
->hl
== DRAW_MOUSE_FACE
2107 || s
->next
->hl
!= s
->hl
)));
2109 get_glyph_string_clip_rect (s
, &clip_rect
);
2111 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2112 w32_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2113 left_p
, right_p
, &clip_rect
);
2116 x_setup_relief_colors (s
);
2117 w32_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2118 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2123 /* Draw foreground of image glyph string S. */
2126 x_draw_image_foreground (s
)
2127 struct glyph_string
*s
;
2130 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2132 /* If first glyph of S has a left box line, start drawing it to the
2133 right of that line. */
2134 if (s
->face
->box
!= FACE_NO_BOX
2135 && s
->first_glyph
->left_box_line_p
2137 x
+= abs (s
->face
->box_line_width
);
2139 /* If there is a margin around the image, adjust x- and y-position
2141 if (s
->slice
.x
== 0)
2142 x
+= s
->img
->hmargin
;
2143 if (s
->slice
.y
== 0)
2144 y
+= s
->img
->vmargin
;
2150 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2151 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2152 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2153 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2154 SetBkColor (compat_hdc
, RGB (255, 255, 255));
2155 SetTextColor (s
->hdc
, RGB (0, 0, 0));
2156 x_set_glyph_string_clipping (s
);
2160 HDC mask_dc
= CreateCompatibleDC (s
->hdc
);
2161 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2163 SetTextColor (s
->hdc
, RGB (255, 255, 255));
2164 SetBkColor (s
->hdc
, RGB (0, 0, 0));
2166 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2167 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2168 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2169 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2170 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2171 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2173 SelectObject (mask_dc
, mask_orig_obj
);
2178 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2179 SetBkColor (s
->hdc
, s
->gc
->background
);
2181 BitBlt (s
->hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2182 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2184 /* When the image has a mask, we can expect that at
2185 least part of a mouse highlight or a block cursor will
2186 be visible. If the image doesn't have a mask, make
2187 a block cursor visible by drawing a rectangle around
2188 the image. I believe it's looking better if we do
2189 nothing here for mouse-face. */
2190 if (s
->hl
== DRAW_CURSOR
)
2192 int r
= s
->img
->relief
;
2194 w32_draw_rectangle (s
->hdc
, s
->gc
, x
- r
, y
- r
,
2195 s
->slice
.width
+ r
*2 - 1,
2196 s
->slice
.height
+ r
*2 - 1);
2200 w32_set_clip_rectangle (s
->hdc
, NULL
);
2201 SelectObject (s
->hdc
, orig_brush
);
2202 DeleteObject (fg_brush
);
2203 SelectObject (compat_hdc
, orig_obj
);
2204 DeleteDC (compat_hdc
);
2207 w32_draw_rectangle (s
->hdc
, s
->gc
, x
, y
,
2208 s
->slice
.width
- 1, s
->slice
.height
- 1);
2210 RestoreDC (s
->hdc
,-1);
2214 /* Draw a relief around the image glyph string S. */
2217 x_draw_image_relief (s
)
2218 struct glyph_string
*s
;
2220 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2223 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2225 /* If first glyph of S has a left box line, start drawing it to the
2226 right of that line. */
2227 if (s
->face
->box
!= FACE_NO_BOX
2228 && s
->first_glyph
->left_box_line_p
2230 x
+= abs (s
->face
->box_line_width
);
2232 /* If there is a margin around the image, adjust x- and y-position
2234 if (s
->slice
.x
== 0)
2235 x
+= s
->img
->hmargin
;
2236 if (s
->slice
.y
== 0)
2237 y
+= s
->img
->vmargin
;
2239 if (s
->hl
== DRAW_IMAGE_SUNKEN
2240 || s
->hl
== DRAW_IMAGE_RAISED
)
2242 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2243 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2247 thick
= abs (s
->img
->relief
);
2248 raised_p
= s
->img
->relief
> 0;
2253 x1
= x
+ s
->slice
.width
+ thick
- 1;
2254 y1
= y
+ s
->slice
.height
+ thick
- 1;
2256 x_setup_relief_colors (s
);
2257 get_glyph_string_clip_rect (s
, &r
);
2258 w32_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2260 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2262 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2267 /* Draw the foreground of image glyph string S to PIXMAP. */
2270 w32_draw_image_foreground_1 (s
, pixmap
)
2271 struct glyph_string
*s
;
2274 HDC hdc
= CreateCompatibleDC (s
->hdc
);
2275 HGDIOBJ orig_hdc_obj
= SelectObject (hdc
, pixmap
);
2277 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2279 /* If first glyph of S has a left box line, start drawing it to the
2280 right of that line. */
2281 if (s
->face
->box
!= FACE_NO_BOX
2282 && s
->first_glyph
->left_box_line_p
2284 x
+= abs (s
->face
->box_line_width
);
2286 /* If there is a margin around the image, adjust x- and y-position
2288 if (s
->slice
.x
== 0)
2289 x
+= s
->img
->hmargin
;
2290 if (s
->slice
.y
== 0)
2291 y
+= s
->img
->vmargin
;
2295 HDC compat_hdc
= CreateCompatibleDC (hdc
);
2296 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2297 HBRUSH orig_brush
= SelectObject (hdc
, fg_brush
);
2298 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, s
->img
->pixmap
);
2302 HDC mask_dc
= CreateCompatibleDC (hdc
);
2303 HGDIOBJ mask_orig_obj
= SelectObject (mask_dc
, s
->img
->mask
);
2305 SetTextColor (hdc
, RGB (0, 0, 0));
2306 SetBkColor (hdc
, RGB (255, 255, 255));
2307 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2308 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2309 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2310 mask_dc
, s
->slice
.x
, s
->slice
.y
, SRCAND
);
2311 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2312 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCINVERT
);
2314 SelectObject (mask_dc
, mask_orig_obj
);
2319 SetTextColor (hdc
, s
->gc
->foreground
);
2320 SetBkColor (hdc
, s
->gc
->background
);
2322 BitBlt (hdc
, x
, y
, s
->slice
.width
, s
->slice
.height
,
2323 compat_hdc
, s
->slice
.x
, s
->slice
.y
, SRCCOPY
);
2325 /* When the image has a mask, we can expect that at
2326 least part of a mouse highlight or a block cursor will
2327 be visible. If the image doesn't have a mask, make
2328 a block cursor visible by drawing a rectangle around
2329 the image. I believe it's looking better if we do
2330 nothing here for mouse-face. */
2331 if (s
->hl
== DRAW_CURSOR
)
2333 int r
= s
->img
->relief
;
2335 w32_draw_rectangle (hdc
, s
->gc
, x
- r
, y
- r
,
2336 s
->slice
.width
+ r
*2 - 1,
2337 s
->slice
.height
+ r
*2 - 1);
2341 SelectObject (hdc
, orig_brush
);
2342 DeleteObject (fg_brush
);
2343 SelectObject (compat_hdc
, orig_obj
);
2344 DeleteDC (compat_hdc
);
2347 w32_draw_rectangle (hdc
, s
->gc
, x
, y
,
2348 s
->slice
.width
- 1, s
->slice
.height
- 1);
2350 SelectObject (hdc
, orig_hdc_obj
);
2355 /* Draw part of the background of glyph string S. X, Y, W, and H
2356 give the rectangle to draw. */
2359 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2360 struct glyph_string
*s
;
2363 #if 0 /* TODO: stipple */
2366 /* Fill background with a stipple pattern. */
2367 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2368 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2369 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2373 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2377 /* Draw image glyph string S.
2380 s->x +-------------------------
2383 | +-------------------------
2386 | | +-------------------
2392 x_draw_image_glyph_string (s
)
2393 struct glyph_string
*s
;
2396 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2397 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2401 height
= s
->height
- 2 * box_line_vwidth
;
2403 /* Fill background with face under the image. Do it only if row is
2404 taller than image or if image has a clip mask to reduce
2406 s
->stippled_p
= s
->face
->stipple
!= 0;
2407 if (height
> s
->slice
.height
2411 || s
->img
->pixmap
== 0
2412 || s
->width
!= s
->background_width
)
2415 if (s
->first_glyph
->left_box_line_p
2417 x
+= box_line_hwidth
;
2420 if (s
->slice
.y
== 0)
2421 y
+= box_line_vwidth
;
2423 #if 0 /* TODO: figure out if we need to do this on Windows. */
2426 /* Create a pixmap as large as the glyph string. Fill it
2427 with the background color. Copy the image to it, using
2428 its mask. Copy the temporary pixmap to the display. */
2429 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
2430 int depth
= DefaultDepthOfScreen (screen
);
2432 /* Create a pixmap as large as the glyph string. */
2433 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2434 s
->background_width
,
2437 /* Don't clip in the following because we're working on the
2439 XSetClipMask (s
->display
, s
->gc
, None
);
2441 /* Fill the pixmap with the background color/stipple. */
2444 /* Fill background with a stipple pattern. */
2445 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2446 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2447 0, 0, s
->background_width
, s
->height
);
2448 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2453 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2455 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2456 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2457 0, 0, s
->background_width
, s
->height
);
2458 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2463 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2465 s
->background_filled_p
= 1;
2468 /* Draw the foreground. */
2471 w32_draw_image_foreground_1 (s
, pixmap
);
2472 x_set_glyph_string_clipping (s
);
2474 HDC compat_hdc
= CreateCompatibleDC (s
->hdc
);
2475 HBRUSH fg_brush
= CreateSolidBrush (s
->gc
->foreground
);
2476 HBRUSH orig_brush
= SelectObject (s
->hdc
, fg_brush
);
2477 HGDIOBJ orig_obj
= SelectObject (compat_hdc
, pixmap
);
2479 SetTextColor (s
->hdc
, s
->gc
->foreground
);
2480 SetBkColor (s
->hdc
, s
->gc
->background
);
2481 BitBlt (s
->hdc
, s
->x
, s
->y
, s
->background_width
, s
->height
,
2482 compat_hdc
, 0, 0, SRCCOPY
);
2484 SelectObject (s
->hdc
, orig_brush
);
2485 DeleteObject (fg_brush
);
2486 SelectObject (compat_hdc
, orig_obj
);
2487 DeleteDC (compat_hdc
);
2489 DeleteObject (pixmap
);
2493 x_draw_image_foreground (s
);
2495 /* If we must draw a relief around the image, do it. */
2497 || s
->hl
== DRAW_IMAGE_RAISED
2498 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2499 x_draw_image_relief (s
);
2503 /* Draw stretch glyph string S. */
2506 x_draw_stretch_glyph_string (s
)
2507 struct glyph_string
*s
;
2509 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2510 s
->stippled_p
= s
->face
->stipple
!= 0;
2512 if (s
->hl
== DRAW_CURSOR
2513 && !x_stretch_cursor_p
)
2515 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2516 as wide as the stretch glyph. */
2517 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2520 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2522 /* Clear rest using the GC of the original non-cursor face. */
2523 if (width
< s
->background_width
)
2525 XGCValues
*gc
= s
->face
->gc
;
2526 int x
= s
->x
+ width
, y
= s
->y
;
2527 int w
= s
->background_width
- width
, h
= s
->height
;
2531 if (s
->row
->mouse_face_p
2532 && cursor_in_mouse_face_p (s
->w
))
2534 x_set_mouse_face_gc (s
);
2540 get_glyph_string_clip_rect (s
, &r
);
2541 w32_set_clip_rectangle (hdc
, &r
);
2543 #if 0 /* TODO: stipple */
2544 if (s
->face
->stipple
)
2546 /* Fill background with a stipple pattern. */
2547 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2548 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2549 XSetFillStyle (s
->display
, gc
, FillSolid
);
2554 w32_fill_area (s
->f
, s
->hdc
, gc
->background
, x
, y
, w
, h
);
2558 else if (!s
->background_filled_p
)
2559 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
2562 s
->background_filled_p
= 1;
2566 /* Draw glyph string S. */
2569 x_draw_glyph_string (s
)
2570 struct glyph_string
*s
;
2572 int relief_drawn_p
= 0;
2574 /* If S draws into the background of its successor, draw the
2575 background of the successor first so that S can draw into it.
2576 This makes S->next use XDrawString instead of XDrawImageString. */
2577 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
2579 xassert (s
->next
->img
== NULL
);
2580 x_set_glyph_string_gc (s
->next
);
2581 x_set_glyph_string_clipping (s
->next
);
2582 x_draw_glyph_string_background (s
->next
, 1);
2585 /* Set up S->gc, set clipping and draw S. */
2586 x_set_glyph_string_gc (s
);
2588 /* Draw relief (if any) in advance for char/composition so that the
2589 glyph string can be drawn over it. */
2590 if (!s
->for_overlaps_p
2591 && s
->face
->box
!= FACE_NO_BOX
2592 && (s
->first_glyph
->type
== CHAR_GLYPH
2593 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
2596 x_set_glyph_string_clipping (s
);
2597 x_draw_glyph_string_background (s
, 1);
2598 x_draw_glyph_string_box (s
);
2599 x_set_glyph_string_clipping (s
);
2603 x_set_glyph_string_clipping (s
);
2605 switch (s
->first_glyph
->type
)
2608 x_draw_image_glyph_string (s
);
2612 x_draw_stretch_glyph_string (s
);
2616 if (s
->for_overlaps_p
)
2617 s
->background_filled_p
= 1;
2619 x_draw_glyph_string_background (s
, 0);
2620 x_draw_glyph_string_foreground (s
);
2623 case COMPOSITE_GLYPH
:
2624 if (s
->for_overlaps_p
|| s
->gidx
> 0)
2625 s
->background_filled_p
= 1;
2627 x_draw_glyph_string_background (s
, 1);
2628 x_draw_composite_glyph_string_foreground (s
);
2635 if (!s
->for_overlaps_p
)
2637 /* Draw underline. */
2638 if (s
->face
->underline_p
2639 && (s
->font
->bdf
|| !s
->font
->tm
.tmUnderlined
))
2641 unsigned long h
= 1;
2642 unsigned long dy
= s
->height
- h
;
2644 /* TODO: Use font information for positioning and thickness
2645 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
2646 if (s
->face
->underline_defaulted_p
)
2648 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2649 s
->y
+ dy
, s
->width
, 1);
2653 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2654 s
->y
+ dy
, s
->width
, 1);
2658 /* Draw overline. */
2659 if (s
->face
->overline_p
)
2661 unsigned long dy
= 0, h
= 1;
2663 if (s
->face
->overline_color_defaulted_p
)
2665 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
,
2666 s
->y
+ dy
, s
->width
, h
);
2670 w32_fill_area (s
->f
, s
->hdc
, s
->face
->overline_color
, s
->x
,
2671 s
->y
+ dy
, s
->width
, h
);
2675 /* Draw strike-through. */
2676 if (s
->face
->strike_through_p
2677 && (s
->font
->bdf
|| !s
->font
->tm
.tmStruckOut
))
2679 unsigned long h
= 1;
2680 unsigned long dy
= (s
->height
- h
) / 2;
2682 if (s
->face
->strike_through_color_defaulted_p
)
2684 w32_fill_area (s
->f
, s
->hdc
, s
->gc
->foreground
, s
->x
, s
->y
+ dy
,
2689 w32_fill_area (s
->f
, s
->hdc
, s
->face
->underline_color
, s
->x
,
2690 s
->y
+ dy
, s
->width
, h
);
2695 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
2696 x_draw_glyph_string_box (s
);
2699 /* Reset clipping. */
2700 w32_set_clip_rectangle (s
->hdc
, NULL
);
2704 /* Shift display to make room for inserted glyphs. */
2707 w32_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
2709 int x
, y
, width
, height
, shift_by
;
2713 hdc
= get_frame_dc (f
);
2714 BitBlt (hdc
, x
+ shift_by
, y
, width
, height
,
2715 hdc
, x
, y
, SRCCOPY
);
2717 release_frame_dc (f
, hdc
);
2721 /* Delete N glyphs at the nominal cursor position. Not implemented
2733 f
= SELECTED_FRAME ();
2735 if (! FRAME_W32_P (f
))
2742 /* Clear entire frame. If updating_frame is non-null, clear that
2743 frame. Otherwise clear the selected frame. */
2753 f
= SELECTED_FRAME ();
2755 if (! FRAME_W32_P (f
))
2758 /* Clearing the frame will erase any cursor, so mark them all as no
2760 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2761 output_cursor
.hpos
= output_cursor
.vpos
= 0;
2762 output_cursor
.x
= -1;
2764 /* We don't set the output cursor here because there will always
2765 follow an explicit cursor_to. */
2768 w32_clear_window (f
);
2770 /* We have to clear the scroll bars, too. If we have changed
2771 colors or something like that, then they should be notified. */
2772 x_scroll_bar_clear (f
);
2778 /* Make audible bell. */
2781 w32_ring_bell (void)
2785 f
= SELECTED_FRAME ();
2789 if (FRAME_W32_P (f
) && visible_bell
)
2792 HWND hwnd
= FRAME_W32_WINDOW (SELECTED_FRAME ());
2794 for (i
= 0; i
< 5; i
++)
2796 FlashWindow (hwnd
, TRUE
);
2799 FlashWindow (hwnd
, FALSE
);
2802 w32_sys_ring_bell ();
2808 /* Specify how many text lines, from the top of the window,
2809 should be affected by insert-lines and delete-lines operations.
2810 This, and those operations, are used only within an update
2811 that is bounded by calls to x_update_begin and x_update_end. */
2814 w32_set_terminal_window (n
)
2817 /* This function intentionally left blank. */
2821 /***********************************************************************
2823 ***********************************************************************/
2825 /* Perform an insert-lines or delete-lines operation, inserting N
2826 lines or deleting -N lines at vertical position VPOS. */
2829 x_ins_del_lines (vpos
, n
)
2837 f
= SELECTED_FRAME ();
2839 if (! FRAME_W32_P (f
))
2846 /* Scroll part of the display as described by RUN. */
2849 x_scroll_run (w
, run
)
2853 struct frame
*f
= XFRAME (w
->frame
);
2854 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
2855 HWND hwnd
= FRAME_W32_WINDOW (f
);
2858 /* Get frame-relative bounding box of the text display area of W,
2859 without mode lines. Include in this box the left and right
2861 window_box (w
, -1, &x
, &y
, &width
, &height
);
2863 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
2864 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
2865 bottom_y
= y
+ height
;
2869 /* Scrolling up. Make sure we don't copy part of the mode
2870 line at the bottom. */
2871 if (from_y
+ run
->height
> bottom_y
)
2872 height
= bottom_y
- from_y
;
2874 height
= run
->height
;
2875 expect_dirty
= CreateRectRgn (x
, y
+ height
, x
+ width
, bottom_y
);
2879 /* Scolling down. Make sure we don't copy over the mode line.
2881 if (to_y
+ run
->height
> bottom_y
)
2882 height
= bottom_y
- to_y
;
2884 height
= run
->height
;
2885 expect_dirty
= CreateRectRgn (x
, y
, x
+ width
, to_y
);
2890 /* Cursor off. Will be switched on again in x_update_window_end. */
2897 HRGN dirty
= CreateRectRgn (0, 0, 0, 0);
2898 HRGN combined
= CreateRectRgn (0, 0, 0, 0);
2900 from
.left
= to
.left
= x
;
2901 from
.right
= to
.right
= x
+ width
;
2903 from
.bottom
= from_y
+ height
;
2905 to
.bottom
= bottom_y
;
2907 ScrollWindowEx (hwnd
, 0, to_y
- from_y
, &from
, &to
, dirty
,
2908 NULL
, SW_INVALIDATE
);
2910 /* Combine this with what we expect to be dirty. This covers the
2911 case where not all of the region we expect is actually dirty. */
2912 CombineRgn (combined
, dirty
, expect_dirty
, RGN_OR
);
2914 /* If the dirty region is not what we expected, redraw the entire frame. */
2915 if (!EqualRgn (combined
, expect_dirty
))
2916 SET_FRAME_GARBAGED (f
);
2918 DeleteObject (dirty
);
2919 DeleteObject (combined
);
2923 DeleteObject (expect_dirty
);
2928 /***********************************************************************
2930 ***********************************************************************/
2936 x_update_cursor (f
, 1);
2940 frame_unhighlight (f
)
2943 x_update_cursor (f
, 1);
2946 /* The focus has changed. Update the frames as necessary to reflect
2947 the new situation. Note that we can't change the selected frame
2948 here, because the Lisp code we are interrupting might become confused.
2949 Each event gets marked with the frame in which it occurred, so the
2950 Lisp code can tell when the switch took place by examining the events. */
2953 x_new_focus_frame (dpyinfo
, frame
)
2954 struct w32_display_info
*dpyinfo
;
2955 struct frame
*frame
;
2957 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
2959 if (frame
!= dpyinfo
->w32_focus_frame
)
2961 /* Set this before calling other routines, so that they see
2962 the correct value of w32_focus_frame. */
2963 dpyinfo
->w32_focus_frame
= frame
;
2965 if (old_focus
&& old_focus
->auto_lower
)
2966 x_lower_frame (old_focus
);
2968 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
2969 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
2971 pending_autoraise_frame
= 0;
2974 x_frame_rehighlight (dpyinfo
);
2977 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2980 x_mouse_leave (dpyinfo
)
2981 struct w32_display_info
*dpyinfo
;
2983 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
2986 /* The focus has changed, or we have redirected a frame's focus to
2987 another frame (this happens when a frame uses a surrogate
2988 mini-buffer frame). Shift the highlight as appropriate.
2990 The FRAME argument doesn't necessarily have anything to do with which
2991 frame is being highlighted or un-highlighted; we only use it to find
2992 the appropriate X display info. */
2995 w32_frame_rehighlight (frame
)
2996 struct frame
*frame
;
2998 if (! FRAME_W32_P (frame
))
3000 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
3004 x_frame_rehighlight (dpyinfo
)
3005 struct w32_display_info
*dpyinfo
;
3007 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3009 if (dpyinfo
->w32_focus_frame
)
3011 dpyinfo
->x_highlight_frame
3012 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
3013 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
3014 : dpyinfo
->w32_focus_frame
);
3015 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3017 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
3018 dpyinfo
->x_highlight_frame
= dpyinfo
->w32_focus_frame
;
3022 dpyinfo
->x_highlight_frame
= 0;
3024 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3027 frame_unhighlight (old_highlight
);
3028 if (dpyinfo
->x_highlight_frame
)
3029 frame_highlight (dpyinfo
->x_highlight_frame
);
3033 /* Keyboard processing - modifier keys, etc. */
3035 /* Convert a keysym to its name. */
3038 x_get_keysym_name (keysym
)
3041 /* Make static so we can always return it */
3042 static char value
[100];
3045 GetKeyNameText (keysym
, value
, 100);
3053 /* Mouse clicks and mouse movement. Rah. */
3055 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3056 the state in PUP. XBUTTON provides extra information for extended mouse
3057 button messages. Returns FALSE if unable to parse the message. */
3059 parse_button (message
, xbutton
, pbutton
, pup
)
3070 case WM_LBUTTONDOWN
:
3078 case WM_MBUTTONDOWN
:
3079 if (NILP (Vw32_swap_mouse_buttons
))
3086 if (NILP (Vw32_swap_mouse_buttons
))
3092 case WM_RBUTTONDOWN
:
3093 if (NILP (Vw32_swap_mouse_buttons
))
3100 if (NILP (Vw32_swap_mouse_buttons
))
3106 case WM_XBUTTONDOWN
:
3107 button
= xbutton
+ 2;
3111 button
= xbutton
+ 2;
3119 if (pbutton
) *pbutton
= button
;
3125 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3127 If the event is a button press, then note that we have grabbed
3131 construct_mouse_click (result
, msg
, f
)
3132 struct input_event
*result
;
3139 parse_button (msg
->msg
.message
, HIWORD (msg
->msg
.wParam
),
3142 /* Make the event type NO_EVENT; we'll change that when we decide
3144 result
->kind
= MOUSE_CLICK_EVENT
;
3145 result
->code
= button
;
3146 result
->timestamp
= msg
->msg
.time
;
3147 result
->modifiers
= (msg
->dwModifiers
3152 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
3153 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
3154 XSETFRAME (result
->frame_or_window
, f
);
3160 construct_mouse_wheel (result
, msg
, f
)
3161 struct input_event
*result
;
3168 result
->kind
= WHEEL_EVENT
;
3170 result
->timestamp
= msg
->msg
.time
;
3172 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3173 forward, away from the user (up); a negative value indicates that
3174 the wheel was rotated backward, toward the user (down). */
3175 delta
= GET_WHEEL_DELTA_WPARAM (msg
->msg
.wParam
);
3177 /* The up and down modifiers indicate if the wheel was rotated up or
3178 down based on WHEEL_DELTA value. */
3179 result
->modifiers
= (msg
->dwModifiers
3180 | ((delta
< 0 ) ? down_modifier
: up_modifier
));
3182 p
.x
= LOWORD (msg
->msg
.lParam
);
3183 p
.y
= HIWORD (msg
->msg
.lParam
);
3184 ScreenToClient (msg
->msg
.hwnd
, &p
);
3185 XSETINT (result
->x
, p
.x
);
3186 XSETINT (result
->y
, p
.y
);
3187 XSETFRAME (result
->frame_or_window
, f
);
3193 construct_drag_n_drop (result
, msg
, f
)
3194 struct input_event
*result
;
3206 result
->kind
= DRAG_N_DROP_EVENT
;
3208 result
->timestamp
= msg
->msg
.time
;
3209 result
->modifiers
= msg
->dwModifiers
;
3211 hdrop
= (HDROP
) msg
->msg
.wParam
;
3212 DragQueryPoint (hdrop
, &p
);
3215 p
.x
= LOWORD (msg
->msg
.lParam
);
3216 p
.y
= HIWORD (msg
->msg
.lParam
);
3217 ScreenToClient (msg
->msg
.hwnd
, &p
);
3220 XSETINT (result
->x
, p
.x
);
3221 XSETINT (result
->y
, p
.y
);
3223 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
3226 for (i
= 0; i
< num_files
; i
++)
3228 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
3231 name
= alloca (len
+ 1);
3232 DragQueryFile (hdrop
, i
, name
, len
+ 1);
3233 files
= Fcons (DECODE_FILE (build_string (name
)), files
);
3238 XSETFRAME (frame
, f
);
3239 result
->frame_or_window
= Fcons (frame
, files
);
3245 /* Function to report a mouse movement to the mainstream Emacs code.
3246 The input handler calls this.
3248 We have received a mouse movement event, which is given in *event.
3249 If the mouse is over a different glyph than it was last time, tell
3250 the mainstream emacs code by setting mouse_moved. If not, ask for
3251 another motion event, so we can check again the next time it moves. */
3253 static MSG last_mouse_motion_event
;
3254 static Lisp_Object last_mouse_motion_frame
;
3256 static void remember_mouse_glyph
P_ ((struct frame
*, int, int));
3259 note_mouse_movement (frame
, msg
)
3263 int mouse_x
= LOWORD (msg
->lParam
);
3264 int mouse_y
= HIWORD (msg
->lParam
);
3266 last_mouse_movement_time
= msg
->time
;
3267 memcpy (&last_mouse_motion_event
, msg
, sizeof (last_mouse_motion_event
));
3268 XSETFRAME (last_mouse_motion_frame
, frame
);
3270 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
3272 frame
->mouse_moved
= 1;
3273 last_mouse_scroll_bar
= Qnil
;
3274 note_mouse_highlight (frame
, -1, -1);
3277 /* Has the mouse moved off the glyph it was on at the last sighting? */
3278 else if (mouse_x
< last_mouse_glyph
.left
3279 || mouse_x
> last_mouse_glyph
.right
3280 || mouse_y
< last_mouse_glyph
.top
3281 || mouse_y
> last_mouse_glyph
.bottom
)
3283 frame
->mouse_moved
= 1;
3284 last_mouse_scroll_bar
= Qnil
;
3285 note_mouse_highlight (frame
, mouse_x
, mouse_y
);
3286 /* Remember the mouse position here, as w32_mouse_position only
3287 gets called when mouse tracking is enabled but we also need
3288 to keep track of the mouse for help_echo and highlighting at
3290 remember_mouse_glyph (frame
, mouse_x
, mouse_y
);
3295 /************************************************************************
3297 ************************************************************************/
3299 static struct scroll_bar
*x_window_to_scroll_bar ();
3300 static void x_scroll_bar_report_motion ();
3301 static void x_check_fullscreen
P_ ((struct frame
*));
3302 static int glyph_rect
P_ ((struct frame
*f
, int, int, RECT
*));
3306 redo_mouse_highlight ()
3308 if (!NILP (last_mouse_motion_frame
)
3309 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3310 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3311 LOWORD (last_mouse_motion_event
.lParam
),
3312 HIWORD (last_mouse_motion_event
.lParam
));
3316 w32_define_cursor (window
, cursor
)
3320 PostMessage (window
, WM_EMACS_SETCURSOR
, (WPARAM
) cursor
, 0);
3323 /* Try to determine frame pixel position and size of the glyph under
3324 frame pixel coordinates X/Y on frame F . Return the position and
3325 size in *RECT. Value is non-zero if we could compute these
3329 glyph_rect (f
, x
, y
, rect
)
3336 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3340 struct window
*w
= XWINDOW (window
);
3341 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3342 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3344 for (; r
< end
&& r
->enabled_p
; ++r
)
3345 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3347 /* Found the row at y. */
3348 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3349 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3352 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3353 rect
->bottom
= rect
->top
+ r
->height
;
3357 /* x is to the left of the first glyph in the row. */
3358 /* Shouldn't this be a pixel value?
3359 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3361 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3362 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3366 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3367 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3369 /* x is on a glyph. */
3370 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3371 rect
->right
= rect
->left
+ g
->pixel_width
;
3375 /* x is to the right of the last glyph in the row. */
3376 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3377 /* Shouldn't this be a pixel value?
3378 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3380 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3385 /* The y is not on any row. */
3389 /* Record the position of the mouse in last_mouse_glyph. */
3391 remember_mouse_glyph (f1
, gx
, gy
)
3395 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3397 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3398 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3400 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3401 round down even for negative values. */
3407 /* This was the original code from XTmouse_position, but it seems
3408 to give the position of the glyph diagonally next to the one
3409 the mouse is over. */
3410 gx
= (gx
+ width
- 1) / width
* width
;
3411 gy
= (gy
+ height
- 1) / height
* height
;
3413 gx
= gx
/ width
* width
;
3414 gy
= gy
/ height
* height
;
3417 last_mouse_glyph
.left
= gx
;
3418 last_mouse_glyph
.top
= gy
;
3419 last_mouse_glyph
.right
= gx
+ width
;
3420 last_mouse_glyph
.bottom
= gy
+ height
;
3424 /* Return the current position of the mouse.
3425 *fp should be a frame which indicates which display to ask about.
3427 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3428 and *part to the frame, window, and scroll bar part that the mouse
3429 is over. Set *x and *y to the portion and whole of the mouse's
3430 position on the scroll bar.
3432 If the mouse movement started elsewhere, set *fp to the frame the
3433 mouse is on, *bar_window to nil, and *x and *y to the character cell
3436 Set *time to the server time-stamp for the time at which the mouse
3437 was at this position.
3439 Don't store anything if we don't have a valid set of values to report.
3441 This clears the mouse_moved flag, so we can wait for the next mouse
3445 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3448 Lisp_Object
*bar_window
;
3449 enum scroll_bar_part
*part
;
3451 unsigned long *time
;
3457 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3458 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3463 Lisp_Object frame
, tail
;
3465 /* Clear the mouse-moved flag for every frame on this display. */
3466 FOR_EACH_FRAME (tail
, frame
)
3467 XFRAME (frame
)->mouse_moved
= 0;
3469 last_mouse_scroll_bar
= Qnil
;
3473 /* Now we have a position on the root; find the innermost window
3474 containing the pointer. */
3476 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
3477 && FRAME_LIVE_P (last_mouse_frame
))
3479 /* If mouse was grabbed on a frame, give coords for that frame
3480 even if the mouse is now outside it. */
3481 f1
= last_mouse_frame
;
3485 /* Is window under mouse one of our frames? */
3486 f1
= x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
),
3487 WindowFromPoint (pt
));
3490 /* If not, is it one of our scroll bars? */
3493 struct scroll_bar
*bar
3494 = x_window_to_scroll_bar (WindowFromPoint (pt
));
3498 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3502 if (f1
== 0 && insist
> 0)
3503 f1
= SELECTED_FRAME ();
3507 /* Ok, we found a frame. Store all the values.
3508 last_mouse_glyph is a rectangle used to reduce the
3509 generation of mouse events. To not miss any motion
3510 events, we must divide the frame into rectangles of the
3511 size of the smallest character that could be displayed
3512 on it, i.e. into the same rectangles that matrices on
3513 the frame are divided into. */
3515 #if OLD_REDISPLAY_CODE
3516 int ignore1
, ignore2
;
3518 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3520 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
3522 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
3525 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
3526 remember_mouse_glyph (f1
, pt
.x
, pt
.y
);
3534 *time
= last_mouse_movement_time
;
3543 /***********************************************************************
3545 ***********************************************************************/
3547 /* Handle mouse button event on the tool-bar of frame F, at
3548 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3552 w32_handle_tool_bar_click (f
, button_event
)
3554 struct input_event
*button_event
;
3556 int x
= XFASTINT (button_event
->x
);
3557 int y
= XFASTINT (button_event
->y
);
3559 if (button_event
->modifiers
& down_modifier
)
3560 handle_tool_bar_click (f
, x
, y
, 1, 0);
3562 handle_tool_bar_click (f
, x
, y
, 0,
3563 button_event
->modifiers
& ~up_modifier
);
3568 /***********************************************************************
3570 ***********************************************************************/
3572 /* Scroll bar support. */
3574 /* Given a window ID, find the struct scroll_bar which manages it.
3575 This can be called in GC, so we have to make sure to strip off mark
3578 static struct scroll_bar
*
3579 x_window_to_scroll_bar (window_id
)
3584 for (tail
= Vframe_list
;
3585 XGCTYPE (tail
) == Lisp_Cons
;
3588 Lisp_Object frame
, bar
, condemned
;
3590 frame
= XCAR (tail
);
3591 /* All elements of Vframe_list should be frames. */
3592 if (! GC_FRAMEP (frame
))
3595 /* Scan this frame's scroll bar list for a scroll bar with the
3597 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
3598 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
3599 /* This trick allows us to search both the ordinary and
3600 condemned scroll bar lists with one loop. */
3601 ! GC_NILP (bar
) || (bar
= condemned
,
3604 bar
= XSCROLL_BAR (bar
)->next
)
3605 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
3606 return XSCROLL_BAR (bar
);
3614 /* Set the thumb size and position of scroll bar BAR. We are currently
3615 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3618 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
)
3619 struct scroll_bar
*bar
;
3620 int portion
, position
, whole
;
3622 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3623 double range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3624 int sb_page
, sb_pos
;
3625 BOOL draggingp
= !NILP (bar
->dragging
) ? TRUE
: FALSE
;
3629 /* Position scroll bar at rock bottom if the bottom of the
3630 buffer is visible. This avoids shinking the thumb away
3631 to nothing if it is held at the bottom of the buffer. */
3632 if (position
+ portion
>= whole
)
3634 sb_page
= range
* (whole
- position
) / whole
3635 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3639 sb_page
= portion
* range
/ whole
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3640 sb_pos
= position
* range
/ whole
;
3650 if (pfnSetScrollInfo
)
3654 si
.cbSize
= sizeof (si
);
3655 /* Only update page size if currently dragging, to reduce
3658 si
.fMask
= SIF_PAGE
;
3660 si
.fMask
= SIF_PAGE
| SIF_POS
;
3664 pfnSetScrollInfo (w
, SB_CTL
, &si
, !draggingp
);
3667 SetScrollPos (w
, SB_CTL
, sb_pos
, !draggingp
);
3673 /************************************************************************
3674 Scroll bars, general
3675 ************************************************************************/
3678 my_create_scrollbar (f
, bar
)
3680 struct scroll_bar
* bar
;
3682 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
3683 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
3687 /*#define ATTACH_THREADS*/
3690 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
3692 #ifndef ATTACH_THREADS
3693 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
3694 (WPARAM
) hwnd
, (LPARAM
) how
);
3696 return ShowWindow (hwnd
, how
);
3701 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
3702 int x
, int y
, int cx
, int cy
, UINT flags
)
3704 #ifndef ATTACH_THREADS
3706 pos
.hwndInsertAfter
= hwndAfter
;
3712 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
3714 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
3719 my_set_focus (f
, hwnd
)
3723 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
3728 my_set_foreground_window (hwnd
)
3731 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
3735 my_destroy_window (f
, hwnd
)
3739 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
3743 /* Create a scroll bar and return the scroll bar vector for it. W is
3744 the Emacs window on which to create the scroll bar. TOP, LEFT,
3745 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3748 static struct scroll_bar
*
3749 x_scroll_bar_create (w
, top
, left
, width
, height
)
3751 int top
, left
, width
, height
;
3753 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3755 struct scroll_bar
*bar
3756 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
3760 XSETWINDOW (bar
->window
, w
);
3761 XSETINT (bar
->top
, top
);
3762 XSETINT (bar
->left
, left
);
3763 XSETINT (bar
->width
, width
);
3764 XSETINT (bar
->height
, height
);
3765 XSETINT (bar
->start
, 0);
3766 XSETINT (bar
->end
, 0);
3767 bar
->dragging
= Qnil
;
3769 /* Requires geometry to be set before call to create the real window */
3771 hwnd
= my_create_scrollbar (f
, bar
);
3773 if (pfnSetScrollInfo
)
3777 si
.cbSize
= sizeof (si
);
3780 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3781 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3785 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3789 SetScrollRange (hwnd
, SB_CTL
, 0,
3790 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
3791 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
3794 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
3796 /* Add bar to its frame's list of scroll bars. */
3797 bar
->next
= FRAME_SCROLL_BARS (f
);
3799 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3800 if (! NILP (bar
->next
))
3801 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3809 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3813 x_scroll_bar_remove (bar
)
3814 struct scroll_bar
*bar
;
3816 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3820 /* Destroy the window. */
3821 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
3823 /* Disassociate this scroll bar from its window. */
3824 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3829 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3830 that we are displaying PORTION characters out of a total of WHOLE
3831 characters, starting at POSITION. If WINDOW has no scroll bar,
3834 w32_set_vertical_scroll_bar (w
, portion
, whole
, position
)
3836 int portion
, whole
, position
;
3838 struct frame
*f
= XFRAME (w
->frame
);
3839 struct scroll_bar
*bar
;
3840 int top
, height
, left
, sb_left
, width
, sb_width
;
3841 int window_y
, window_height
;
3843 /* Get window dimensions. */
3844 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
3846 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
3847 height
= window_height
;
3849 /* Compute the left edge of the scroll bar area. */
3850 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
3852 /* Compute the width of the scroll bar which might be less than
3853 the width of the area reserved for the scroll bar. */
3854 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
3855 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
3859 /* Compute the left edge of the scroll bar. */
3860 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
3861 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
3863 sb_left
= left
+ (width
- sb_width
) / 2;
3865 /* Does the scroll bar exist yet? */
3866 if (NILP (w
->vertical_scroll_bar
))
3870 if (width
> 0 && height
> 0)
3872 hdc
= get_frame_dc (f
);
3873 w32_clear_area (f
, hdc
, left
, top
, width
, height
);
3874 release_frame_dc (f
, hdc
);
3878 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
3882 /* It may just need to be moved and resized. */
3885 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
3886 hwnd
= SCROLL_BAR_W32_WINDOW (bar
);
3888 /* If already correctly positioned, do nothing. */
3889 if ( XINT (bar
->left
) == sb_left
3890 && XINT (bar
->top
) == top
3891 && XINT (bar
->width
) == sb_width
3892 && XINT (bar
->height
) == height
)
3894 /* Redraw after clear_frame. */
3895 if (!my_show_window (f
, hwnd
, SW_NORMAL
))
3896 InvalidateRect (hwnd
, NULL
, FALSE
);
3902 if (width
&& height
)
3904 hdc
= get_frame_dc (f
);
3905 /* Since Windows scroll bars are smaller than the space reserved
3906 for them on the frame, we have to clear "under" them. */
3907 w32_clear_area (f
, hdc
,
3912 release_frame_dc (f
, hdc
);
3914 /* Make sure scroll bar is "visible" before moving, to ensure the
3915 area of the parent window now exposed will be refreshed. */
3916 my_show_window (f
, hwnd
, SW_HIDE
);
3917 MoveWindow (hwnd
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
3918 top
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
3919 max (height
, 1), TRUE
);
3920 if (pfnSetScrollInfo
)
3924 si
.cbSize
= sizeof (si
);
3925 si
.fMask
= SIF_RANGE
;
3927 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
)
3928 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3930 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
3933 SetScrollRange (hwnd
, SB_CTL
, 0,
3934 VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
), FALSE
);
3935 my_show_window (f
, hwnd
, SW_NORMAL
);
3936 /* InvalidateRect (w, NULL, FALSE); */
3938 /* Remember new settings. */
3939 XSETINT (bar
->left
, sb_left
);
3940 XSETINT (bar
->top
, top
);
3941 XSETINT (bar
->width
, sb_width
);
3942 XSETINT (bar
->height
, height
);
3947 w32_set_scroll_bar_thumb (bar
, portion
, position
, whole
);
3949 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
3953 /* The following three hooks are used when we're doing a thorough
3954 redisplay of the frame. We don't explicitly know which scroll bars
3955 are going to be deleted, because keeping track of when windows go
3956 away is a real pain - "Can you say set-window-configuration, boys
3957 and girls?" Instead, we just assert at the beginning of redisplay
3958 that *all* scroll bars are to be removed, and then save a scroll bar
3959 from the fiery pit when we actually redisplay its window. */
3961 /* Arrange for all scroll bars on FRAME to be removed at the next call
3962 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3963 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3966 w32_condemn_scroll_bars (frame
)
3969 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3970 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3973 bar
= FRAME_SCROLL_BARS (frame
);
3974 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3975 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3976 XSCROLL_BAR (bar
)->prev
= Qnil
;
3977 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3978 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3979 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3984 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3985 Note that WINDOW isn't necessarily condemned at all. */
3988 w32_redeem_scroll_bar (window
)
3989 struct window
*window
;
3991 struct scroll_bar
*bar
;
3994 /* We can't redeem this window's scroll bar if it doesn't have one. */
3995 if (NILP (window
->vertical_scroll_bar
))
3998 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4000 /* Unlink it from the condemned list. */
4001 f
= XFRAME (WINDOW_FRAME (window
));
4002 if (NILP (bar
->prev
))
4004 /* If the prev pointer is nil, it must be the first in one of
4006 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4007 /* It's not condemned. Everything's fine. */
4009 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4010 window
->vertical_scroll_bar
))
4011 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4013 /* If its prev pointer is nil, it must be at the front of
4014 one or the other! */
4018 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4020 if (! NILP (bar
->next
))
4021 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4023 bar
->next
= FRAME_SCROLL_BARS (f
);
4025 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4026 if (! NILP (bar
->next
))
4027 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4030 /* Remove all scroll bars on FRAME that haven't been saved since the
4031 last call to `*condemn_scroll_bars_hook'. */
4034 w32_judge_scroll_bars (f
)
4037 Lisp_Object bar
, next
;
4039 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4041 /* Clear out the condemned list now so we won't try to process any
4042 more events on the hapless scroll bars. */
4043 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4045 for (; ! NILP (bar
); bar
= next
)
4047 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4049 x_scroll_bar_remove (b
);
4052 b
->next
= b
->prev
= Qnil
;
4055 /* Now there should be no references to the condemned scroll bars,
4056 and they should get garbage-collected. */
4059 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4060 is set to something other than NO_EVENT, it is enqueued.
4062 This may be called from a signal handler, so we have to ignore GC
4066 w32_scroll_bar_handle_click (bar
, msg
, emacs_event
)
4067 struct scroll_bar
*bar
;
4069 struct input_event
*emacs_event
;
4071 if (! GC_WINDOWP (bar
->window
))
4074 emacs_event
->kind
= W32_SCROLL_BAR_CLICK_EVENT
;
4075 emacs_event
->code
= 0;
4076 /* not really meaningful to distinguish up/down */
4077 emacs_event
->modifiers
= msg
->dwModifiers
;
4078 emacs_event
->frame_or_window
= bar
->window
;
4079 emacs_event
->arg
= Qnil
;
4080 emacs_event
->timestamp
= msg
->msg
.time
;
4083 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4085 int dragging
= !NILP (bar
->dragging
);
4087 if (pfnGetScrollInfo
)
4091 si
.cbSize
= sizeof (si
);
4094 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
4098 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
4100 bar
->dragging
= Qnil
;
4103 last_mouse_scroll_bar_pos
= msg
->msg
.wParam
;
4105 switch (LOWORD (msg
->msg
.wParam
))
4108 emacs_event
->part
= scroll_bar_down_arrow
;
4111 emacs_event
->part
= scroll_bar_up_arrow
;
4114 emacs_event
->part
= scroll_bar_above_handle
;
4117 emacs_event
->part
= scroll_bar_below_handle
;
4120 emacs_event
->part
= scroll_bar_handle
;
4124 emacs_event
->part
= scroll_bar_handle
;
4128 case SB_THUMBPOSITION
:
4129 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4130 y
= HIWORD (msg
->msg
.wParam
);
4132 emacs_event
->part
= scroll_bar_handle
;
4134 /* "Silently" update current position. */
4135 if (pfnSetScrollInfo
)
4139 si
.cbSize
= sizeof (si
);
4142 /* Remember apparent position (we actually lag behind the real
4143 position, so don't set that directly. */
4144 last_scroll_bar_drag_pos
= y
;
4146 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
4149 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
4152 /* If this is the end of a drag sequence, then reset the scroll
4153 handle size to normal and do a final redraw. Otherwise do
4157 if (pfnSetScrollInfo
)
4160 int start
= XINT (bar
->start
);
4161 int end
= XINT (bar
->end
);
4163 si
.cbSize
= sizeof (si
);
4164 si
.fMask
= SIF_PAGE
| SIF_POS
;
4165 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4166 si
.nPos
= last_scroll_bar_drag_pos
;
4167 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
4170 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
4174 emacs_event
->kind
= NO_EVENT
;
4178 XSETINT (emacs_event
->x
, y
);
4179 XSETINT (emacs_event
->y
, top_range
);
4185 /* Return information to the user about the current position of the mouse
4186 on the scroll bar. */
4189 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4191 Lisp_Object
*bar_window
;
4192 enum scroll_bar_part
*part
;
4194 unsigned long *time
;
4196 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4197 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
4198 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4200 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4205 *bar_window
= bar
->window
;
4207 if (pfnGetScrollInfo
)
4211 si
.cbSize
= sizeof (si
);
4212 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
4214 pfnGetScrollInfo (w
, SB_CTL
, &si
);
4216 top_range
= si
.nMax
- si
.nPage
+ 1;
4219 pos
= GetScrollPos (w
, SB_CTL
);
4221 switch (LOWORD (last_mouse_scroll_bar_pos
))
4223 case SB_THUMBPOSITION
:
4225 *part
= scroll_bar_handle
;
4226 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
)) <= 0xffff)
4227 pos
= HIWORD (last_mouse_scroll_bar_pos
);
4230 *part
= scroll_bar_handle
;
4234 *part
= scroll_bar_handle
;
4239 XSETINT (*y
, top_range
);
4242 last_mouse_scroll_bar
= Qnil
;
4244 *time
= last_mouse_movement_time
;
4250 /* The screen has been cleared so we may have changed foreground or
4251 background colors, and the scroll bars may need to be redrawn.
4252 Clear out the scroll bars, and ask for expose events, so we can
4256 x_scroll_bar_clear (f
)
4261 /* We can have scroll bars even if this is 0,
4262 if we just turned off scroll bar mode.
4263 But in that case we should not clear them. */
4264 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4265 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
4266 bar
= XSCROLL_BAR (bar
)->next
)
4268 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
4269 HDC hdc
= GetDC (window
);
4272 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4273 arranges to refresh the scroll bar if hidden. */
4274 my_show_window (f
, window
, SW_HIDE
);
4276 GetClientRect (window
, &rect
);
4277 select_palette (f
, hdc
);
4278 w32_clear_rect (f
, hdc
, &rect
);
4279 deselect_palette (f
, hdc
);
4281 ReleaseDC (window
, hdc
);
4286 /* The main W32 event-reading loop - w32_read_socket. */
4288 /* Record the last 100 characters stored
4289 to help debug the loss-of-chars-during-GC problem. */
4291 static int temp_index
;
4292 static short temp_buffer
[100];
4295 /* Read events coming from the W32 shell.
4296 This routine is called by the SIGIO handler.
4297 We return as soon as there are no more events to be read.
4299 We return the number of characters stored into the buffer,
4300 thus pretending to be `read'.
4302 EXPECTED is nonzero if the caller knows input is available.
4304 Some of these messages are reposted back to the message queue since the
4305 system calls the windows proc directly in a context where we cannot return
4306 the data nor can we guarantee the state we are in. So if we dispatch them
4307 we will get into an infinite loop. To prevent this from ever happening we
4308 will set a variable to indicate we are in the read_socket call and indicate
4309 which message we are processing since the windows proc gets called
4310 recursively with different messages by the system.
4314 w32_read_socket (sd
, expected
, hold_quit
)
4317 struct input_event
*hold_quit
;
4320 int check_visibility
= 0;
4323 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4325 if (interrupt_input_blocked
)
4327 interrupt_input_pending
= 1;
4331 interrupt_input_pending
= 0;
4334 /* So people can tell when we have read the available input. */
4335 input_signal_count
++;
4337 /* TODO: ghostscript integration. */
4338 while (get_next_msg (&msg
, FALSE
))
4340 struct input_event inev
;
4344 inev
.kind
= NO_EVENT
;
4347 switch (msg
.msg
.message
)
4350 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4354 if (msg
.rect
.right
== msg
.rect
.left
||
4355 msg
.rect
.bottom
== msg
.rect
.top
)
4357 /* We may get paint messages even though the client
4358 area is clipped - these are not expose events. */
4359 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f
,
4362 else if (f
->async_visible
!= 1)
4364 /* Definitely not obscured, so mark as visible. */
4365 f
->async_visible
= 1;
4366 f
->async_iconified
= 0;
4367 SET_FRAME_GARBAGED (f
);
4368 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f
,
4371 /* WM_PAINT serves as MapNotify as well, so report
4372 visibility changes properly. */
4375 inev
.kind
= DEICONIFY_EVENT
;
4376 XSETFRAME (inev
.frame_or_window
, f
);
4378 else if (! NILP (Vframe_list
)
4379 && ! NILP (XCDR (Vframe_list
)))
4380 /* Force a redisplay sooner or later to update the
4381 frame titles in case this is the second frame. */
4382 record_asynch_buffer_change ();
4386 HDC hdc
= get_frame_dc (f
);
4388 /* Erase background again for safety. */
4389 w32_clear_rect (f
, hdc
, &msg
.rect
);
4390 release_frame_dc (f
, hdc
);
4394 msg
.rect
.right
- msg
.rect
.left
,
4395 msg
.rect
.bottom
- msg
.rect
.top
);
4400 case WM_INPUTLANGCHANGE
:
4401 /* Generate a language change event. */
4402 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4406 inev
.kind
= LANGUAGE_CHANGE_EVENT
;
4407 XSETFRAME (inev
.frame_or_window
, f
);
4408 inev
.code
= msg
.msg
.wParam
;
4409 inev
.modifiers
= msg
.msg
.lParam
& 0xffff;
4415 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4417 if (f
&& !f
->iconified
)
4419 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
4421 clear_mouse_face (dpyinfo
);
4422 dpyinfo
->mouse_face_hidden
= 1;
4425 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4427 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4428 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
4429 inev
.code
= msg
.msg
.wParam
;
4430 inev
.modifiers
= msg
.dwModifiers
;
4431 XSETFRAME (inev
.frame_or_window
, f
);
4432 inev
.timestamp
= msg
.msg
.time
;
4438 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4440 if (f
&& !f
->iconified
)
4442 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
4444 clear_mouse_face (dpyinfo
);
4445 dpyinfo
->mouse_face_hidden
= 1;
4448 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4450 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
4451 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
4452 inev
.code
= msg
.msg
.wParam
;
4453 inev
.modifiers
= msg
.dwModifiers
;
4454 XSETFRAME (inev
.frame_or_window
, f
);
4455 inev
.timestamp
= msg
.msg
.time
;
4460 /* Ignore non-movement. */
4462 int x
= LOWORD (msg
.msg
.lParam
);
4463 int y
= HIWORD (msg
.msg
.lParam
);
4464 if (x
== last_mousemove_x
&& y
== last_mousemove_y
)
4466 last_mousemove_x
= x
;
4467 last_mousemove_y
= y
;
4470 previous_help_echo_string
= help_echo_string
;
4472 if (dpyinfo
->grabbed
&& last_mouse_frame
4473 && FRAME_LIVE_P (last_mouse_frame
))
4474 f
= last_mouse_frame
;
4476 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4478 if (dpyinfo
->mouse_face_hidden
)
4480 dpyinfo
->mouse_face_hidden
= 0;
4481 clear_mouse_face (dpyinfo
);
4486 /* Generate SELECT_WINDOW_EVENTs when needed. */
4487 if (mouse_autoselect_window
)
4490 int x
= LOWORD (msg
.msg
.lParam
);
4491 int y
= HIWORD (msg
.msg
.lParam
);
4493 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 0);
4495 /* Window will be selected only when it is not
4496 selected now and last mouse movement event was
4497 not in it. Minibuffer window will be selected
4498 iff it is active. */
4500 && !EQ (window
, last_window
)
4501 && !EQ (window
, selected_window
))
4503 inev
.kind
= SELECT_WINDOW_EVENT
;
4504 inev
.frame_or_window
= window
;
4509 note_mouse_movement (f
, &msg
.msg
);
4513 /* If we move outside the frame, then we're
4514 certainly no longer on any text in the frame. */
4515 clear_mouse_face (dpyinfo
);
4518 /* If the contents of the global variable help_echo_string
4519 has changed, generate a HELP_EVENT. */
4520 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4521 But it was originally changed to this to fix a bug, so I have
4522 not removed it completely in case the bug is still there. */
4523 if (help_echo_string
!= previous_help_echo_string
||
4524 (!NILP (help_echo_string
) && !STRINGP (help_echo_string
) && f
->mouse_moved
))
4525 #else /* This is what xterm.c does. */
4526 if (!NILP (help_echo_string
)
4527 || !NILP (previous_help_echo_string
))
4532 case WM_LBUTTONDOWN
:
4534 case WM_MBUTTONDOWN
:
4536 case WM_RBUTTONDOWN
:
4538 case WM_XBUTTONDOWN
:
4541 /* If we decide we want to generate an event to be seen
4542 by the rest of Emacs, we put it here. */
4547 if (dpyinfo
->grabbed
&& last_mouse_frame
4548 && FRAME_LIVE_P (last_mouse_frame
))
4549 f
= last_mouse_frame
;
4551 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4555 construct_mouse_click (&inev
, &msg
, f
);
4557 /* Is this in the tool-bar? */
4558 if (WINDOWP (f
->tool_bar_window
)
4559 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)))
4562 int x
= XFASTINT (inev
.x
);
4563 int y
= XFASTINT (inev
.y
);
4565 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
4567 if (EQ (window
, f
->tool_bar_window
))
4569 w32_handle_tool_bar_click (f
, &inev
);
4575 || (dpyinfo
->w32_focus_frame
4576 && f
!= dpyinfo
->w32_focus_frame
))
4577 inev
.kind
= NO_EVENT
;
4580 parse_button (msg
.msg
.message
, HIWORD (msg
.msg
.wParam
),
4585 dpyinfo
->grabbed
&= ~ (1 << button
);
4589 dpyinfo
->grabbed
|= (1 << button
);
4590 last_mouse_frame
= f
;
4591 /* Ignore any mouse motion that happened
4592 before this event; any subsequent mouse-movement
4593 Emacs events should reflect only motion after
4599 last_tool_bar_item
= -1;
4606 if (dpyinfo
->grabbed
&& last_mouse_frame
4607 && FRAME_LIVE_P (last_mouse_frame
))
4608 f
= last_mouse_frame
;
4610 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4615 if (!dpyinfo
->w32_focus_frame
4616 || f
== dpyinfo
->w32_focus_frame
)
4618 /* Emit an Emacs wheel-up/down event. */
4619 construct_mouse_wheel (&inev
, &msg
, f
);
4621 /* Ignore any mouse motion that happened before this
4622 event; any subsequent mouse-movement Emacs events
4623 should reflect only motion after the
4627 last_mouse_frame
= f
;
4628 last_tool_bar_item
= -1;
4633 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4636 construct_drag_n_drop (&inev
, &msg
, f
);
4641 struct scroll_bar
*bar
=
4642 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
4645 w32_scroll_bar_handle_click (bar
, &msg
, &inev
);
4649 case WM_WINDOWPOSCHANGED
:
4650 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4653 if (f
->want_fullscreen
& FULLSCREEN_WAIT
)
4654 f
->want_fullscreen
&= ~(FULLSCREEN_WAIT
|FULLSCREEN_BOTH
);
4656 check_visibility
= 1;
4660 case WM_ACTIVATEAPP
:
4661 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4663 x_check_fullscreen (f
);
4664 check_visibility
= 1;
4668 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4670 if (f
&& !f
->async_iconified
)
4674 x_real_positions (f
, &x
, &y
);
4679 check_visibility
= 1;
4683 /* wParam non-zero means Window is about to be shown, 0 means
4684 about to be hidden. */
4685 /* Redo the mouse-highlight after the tooltip has gone. */
4686 if (!msg
.msg
.wParam
&& msg
.msg
.hwnd
== tip_window
)
4689 redo_mouse_highlight ();
4692 /* If window has been obscured or exposed by another window
4693 being maximised or minimised/restored, then recheck
4694 visibility of all frames. Direct changes to our own
4695 windows get handled by WM_SIZE. */
4697 if (msg
.msg
.lParam
!= 0)
4698 check_visibility
= 1;
4701 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4702 f
->async_visible
= msg
.msg
.wParam
;
4706 check_visibility
= 1;
4710 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4712 /* Inform lisp of whether frame has been iconified etc. */
4715 switch (msg
.msg
.wParam
)
4717 case SIZE_MINIMIZED
:
4718 f
->async_visible
= 0;
4719 f
->async_iconified
= 1;
4721 inev
.kind
= ICONIFY_EVENT
;
4722 XSETFRAME (inev
.frame_or_window
, f
);
4725 case SIZE_MAXIMIZED
:
4727 f
->async_visible
= 1;
4728 f
->async_iconified
= 0;
4730 /* wait_reading_process_output will notice this and update
4731 the frame's display structures. */
4732 SET_FRAME_GARBAGED (f
);
4738 /* Reset top and left positions of the Window
4739 here since Windows sends a WM_MOVE message
4740 BEFORE telling us the Window is minimized
4741 when the Window is iconified, with 3000,3000
4743 x_real_positions (f
, &x
, &y
);
4747 inev
.kind
= DEICONIFY_EVENT
;
4748 XSETFRAME (inev
.frame_or_window
, f
);
4750 else if (! NILP (Vframe_list
)
4751 && ! NILP (XCDR (Vframe_list
)))
4752 /* Force a redisplay sooner or later
4753 to update the frame titles
4754 in case this is the second frame. */
4755 record_asynch_buffer_change ();
4760 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
4768 GetClientRect (msg
.msg
.hwnd
, &rect
);
4770 height
= rect
.bottom
- rect
.top
;
4771 width
= rect
.right
- rect
.left
;
4773 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
4774 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
4776 /* TODO: Clip size to the screen dimensions. */
4778 /* Even if the number of character rows and columns has
4779 not changed, the font size may have changed, so we need
4780 to check the pixel dimensions as well. */
4782 if (columns
!= FRAME_COLS (f
)
4783 || rows
!= FRAME_LINES (f
)
4784 || width
!= FRAME_PIXEL_WIDTH (f
)
4785 || height
!= FRAME_PIXEL_HEIGHT (f
))
4787 change_frame_size (f
, rows
, columns
, 0, 1, 0);
4788 SET_FRAME_GARBAGED (f
);
4789 cancel_mouse_face (f
);
4790 FRAME_PIXEL_WIDTH (f
) = width
;
4791 FRAME_PIXEL_HEIGHT (f
) = height
;
4792 f
->win_gravity
= NorthWestGravity
;
4796 check_visibility
= 1;
4800 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4803 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4805 /* If we move outside the frame, then we're
4806 certainly no longer on any text in the frame. */
4807 clear_mouse_face (dpyinfo
);
4808 dpyinfo
->mouse_face_mouse_frame
= 0;
4811 /* Generate a nil HELP_EVENT to cancel a help-echo.
4812 Do it only if there's something to cancel.
4813 Otherwise, the startup message is cleared when
4814 the mouse leaves the frame. */
4815 if (any_help_event_p
)
4821 /* TODO: Port this change:
4822 2002-06-28 Jan D. <jan.h.d@swipnet.se>
4823 * xterm.h (struct x_output): Add focus_state.
4824 * xterm.c (x_focus_changed): New function.
4825 (x_detect_focus_change): New function.
4826 (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
4827 EnterNotify and LeaveNotify to track X focus changes.
4829 f
= x_any_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4831 dpyinfo
->w32_focus_event_frame
= f
;
4834 x_new_focus_frame (dpyinfo
, f
);
4836 dpyinfo
->grabbed
= 0;
4837 check_visibility
= 1;
4841 /* TODO: some of this belongs in MOUSE_LEAVE */
4842 f
= x_top_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4846 if (f
== dpyinfo
->w32_focus_event_frame
)
4847 dpyinfo
->w32_focus_event_frame
= 0;
4849 if (f
== dpyinfo
->w32_focus_frame
)
4850 x_new_focus_frame (dpyinfo
, 0);
4852 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4854 /* If we move outside the frame, then we're
4855 certainly no longer on any text in the frame. */
4856 clear_mouse_face (dpyinfo
);
4857 dpyinfo
->mouse_face_mouse_frame
= 0;
4860 /* Generate a nil HELP_EVENT to cancel a help-echo.
4861 Do it only if there's something to cancel.
4862 Otherwise, the startup message is cleared when
4863 the mouse leaves the frame. */
4864 if (any_help_event_p
)
4868 dpyinfo
->grabbed
= 0;
4869 check_visibility
= 1;
4873 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4877 inev
.kind
= DELETE_WINDOW_EVENT
;
4878 XSETFRAME (inev
.frame_or_window
, f
);
4883 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4887 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
4888 XSETFRAME (inev
.frame_or_window
, f
);
4893 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4897 extern void menubar_selection_callback
4898 (FRAME_PTR f
, void * client_data
);
4899 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
4902 check_visibility
= 1;
4905 case WM_DISPLAYCHANGE
:
4906 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
4910 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
4911 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
4912 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
4913 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
4917 check_visibility
= 1;
4921 /* Check for messages registered at runtime. */
4922 if (msg
.msg
.message
== msh_mousewheel
)
4924 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4925 msg
.msg
.message
= WM_MOUSEWHEEL
;
4931 if (inev
.kind
!= NO_EVENT
)
4933 kbd_buffer_store_event_hold (&inev
, hold_quit
);
4938 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
4943 XSETFRAME (frame
, f
);
4949 if (NILP (help_echo_string
))
4951 help_echo_object
= help_echo_window
= Qnil
;
4955 any_help_event_p
= 1;
4956 gen_help_event (help_echo_string
, frame
, help_echo_window
,
4957 help_echo_object
, help_echo_pos
);
4961 help_echo_string
= Qnil
;
4962 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
4968 /* If the focus was just given to an autoraising frame,
4970 /* ??? This ought to be able to handle more than one such frame. */
4971 if (pending_autoraise_frame
)
4973 x_raise_frame (pending_autoraise_frame
);
4974 pending_autoraise_frame
= 0;
4977 /* Check which frames are still visisble, if we have enqueued any user
4978 events or been notified of events that may affect visibility. We
4979 do this here because there doesn't seem to be any direct
4980 notification from Windows that the visibility of a window has
4981 changed (at least, not in all cases). */
4982 if (count
> 0 || check_visibility
)
4984 Lisp_Object tail
, frame
;
4986 FOR_EACH_FRAME (tail
, frame
)
4988 FRAME_PTR f
= XFRAME (frame
);
4989 /* The tooltip has been drawn already. Avoid the
4990 SET_FRAME_GARBAGED below. */
4991 if (EQ (frame
, tip_frame
))
4994 /* Check "visible" frames and mark each as obscured or not.
4995 Note that async_visible is nonzero for unobscured and
4996 obscured frames, but zero for hidden and iconified frames. */
4997 if (FRAME_W32_P (f
) && f
->async_visible
)
5003 /* Query clipping rectangle for the entire window area
5004 (GetWindowDC), not just the client portion (GetDC).
5005 Otherwise, the scrollbars and menubar aren't counted as
5006 part of the visible area of the frame, and we may think
5007 the frame is obscured when really a scrollbar is still
5008 visible and gets WM_PAINT messages above. */
5009 hdc
= GetWindowDC (FRAME_W32_WINDOW (f
));
5010 GetClipBox (hdc
, &clipbox
);
5011 ReleaseDC (FRAME_W32_WINDOW (f
), hdc
);
5014 if (clipbox
.right
== clipbox
.left
5015 || clipbox
.bottom
== clipbox
.top
)
5017 /* Frame has become completely obscured so mark as
5018 such (we do this by setting async_visible to 2 so
5019 that FRAME_VISIBLE_P is still true, but redisplay
5021 f
->async_visible
= 2;
5023 if (!FRAME_OBSCURED_P (f
))
5025 DebPrint (("frame %p (%s) obscured\n", f
,
5031 /* Frame is not obscured, so mark it as such. */
5032 f
->async_visible
= 1;
5034 if (FRAME_OBSCURED_P (f
))
5036 SET_FRAME_GARBAGED (f
);
5037 DebPrint (("obscured frame %p (%s) found to be visible\n", f
,
5040 /* Force a redisplay sooner or later. */
5041 record_asynch_buffer_change ();
5054 /***********************************************************************
5056 ***********************************************************************/
5058 /* Set clipping for output in glyph row ROW. W is the window in which
5059 we operate. GC is the graphics context to set clipping in.
5061 ROW may be a text row or, e.g., a mode line. Text rows must be
5062 clipped to the interior of the window dedicated to text display,
5063 mode lines must be clipped to the whole window. */
5066 w32_clip_to_row (w
, row
, hdc
)
5068 struct glyph_row
*row
;
5071 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5073 int window_y
, window_width
;
5075 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
5077 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
5078 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5079 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5080 clip_rect
.right
= clip_rect
.left
+ window_width
;
5081 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5083 w32_set_clip_rectangle (hdc
, &clip_rect
);
5087 /* Draw a hollow box cursor on window W in glyph row ROW. */
5090 x_draw_hollow_cursor (w
, row
)
5092 struct glyph_row
*row
;
5094 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5098 struct glyph
*cursor_glyph
;
5099 HBRUSH hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
5101 /* Get the glyph the cursor is on. If we can't tell because
5102 the current matrix is invalid or such, give up. */
5103 cursor_glyph
= get_phys_cursor_glyph (w
);
5104 if (cursor_glyph
== NULL
)
5107 /* Compute frame-relative coordinates from window-relative
5109 rect
.left
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5110 rect
.top
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
5111 + row
->ascent
- w
->phys_cursor_ascent
);
5113 /* Compute the proper height and ascent of the rectangle, based
5114 on the actual glyph. Using the full height of the row looks
5115 bad when there are tall images on that row. */
5116 h
= max (min (FRAME_LINE_HEIGHT (f
), row
->height
),
5117 cursor_glyph
->ascent
+ cursor_glyph
->descent
);
5118 if (h
< row
->height
)
5119 rect
.top
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
5122 rect
.bottom
= rect
.top
+ h
;
5124 /* Compute the width of the rectangle to draw. If on a stretch
5125 glyph, and `x-stretch-block-cursor' is nil, don't draw a
5126 rectangle as wide as the glyph, but use a canonical character
5128 wd
= cursor_glyph
->pixel_width
; /* TODO: Why off by one compared with X? */
5129 if (cursor_glyph
->type
== STRETCH_GLYPH
5130 && !x_stretch_cursor_p
)
5131 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
5132 w
->phys_cursor_width
= wd
;
5134 rect
.right
= rect
.left
+ wd
;
5135 hdc
= get_frame_dc (f
);
5136 /* Set clipping, draw the rectangle, and reset clipping again. */
5137 w32_clip_to_row (w
, row
, hdc
);
5138 FrameRect (hdc
, &rect
, hb
);
5140 w32_set_clip_rectangle (hdc
, NULL
);
5141 release_frame_dc (f
, hdc
);
5145 /* Draw a bar cursor on window W in glyph row ROW.
5147 Implementation note: One would like to draw a bar cursor with an
5148 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5149 Unfortunately, I didn't find a font yet that has this property set.
5153 x_draw_bar_cursor (w
, row
, width
, kind
)
5155 struct glyph_row
*row
;
5157 enum text_cursor_kinds kind
;
5159 struct frame
*f
= XFRAME (w
->frame
);
5160 struct glyph
*cursor_glyph
;
5164 /* If cursor is out of bounds, don't draw garbage. This can happen
5165 in mini-buffer windows when switching between echo area glyphs
5167 cursor_glyph
= get_phys_cursor_glyph (w
);
5168 if (cursor_glyph
== NULL
)
5171 /* If on an image, draw like a normal cursor. That's usually better
5172 visible than drawing a bar, esp. if the image is large so that
5173 the bar might not be in the window. */
5174 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5176 struct glyph_row
*row
;
5177 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5178 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5182 COLORREF cursor_color
= f
->output_data
.w32
->cursor_pixel
;
5183 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5185 /* If the glyph's background equals the color we normally draw
5186 the bar cursor in, the bar cursor in its normal color is
5187 invisible. Use the glyph's foreground color instead in this
5188 case, on the assumption that the glyph's colors are chosen so
5189 that the glyph is legible. */
5190 if (face
->background
== cursor_color
)
5191 cursor_color
= face
->foreground
;
5193 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5196 width
= FRAME_CURSOR_WIDTH (f
);
5197 width
= min (cursor_glyph
->pixel_width
, width
);
5199 w
->phys_cursor_width
= width
;
5202 hdc
= get_frame_dc (f
);
5203 w32_clip_to_row (w
, row
, hdc
);
5205 if (kind
== BAR_CURSOR
)
5207 w32_fill_area (f
, hdc
, cursor_color
, x
,
5208 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5209 width
, row
->height
);
5213 w32_fill_area (f
, hdc
, cursor_color
, x
,
5214 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5215 row
->height
- width
),
5216 cursor_glyph
->pixel_width
, width
);
5219 w32_set_clip_rectangle (hdc
, NULL
);
5220 release_frame_dc (f
, hdc
);
5225 /* RIF: Define cursor CURSOR on frame F. */
5228 w32_define_frame_cursor (f
, cursor
)
5232 w32_define_cursor (FRAME_W32_WINDOW (f
), cursor
);
5236 /* RIF: Clear area on frame F. */
5239 w32_clear_frame_area (f
, x
, y
, width
, height
)
5241 int x
, y
, width
, height
;
5245 hdc
= get_frame_dc (f
);
5246 w32_clear_area (f
, hdc
, x
, y
, width
, height
);
5247 release_frame_dc (f
, hdc
);
5250 /* RIF: Draw or clear cursor on window W. */
5253 w32_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5255 struct glyph_row
*glyph_row
;
5257 int cursor_type
, cursor_width
;
5262 /* If the user wants to use the system caret, make sure our own
5263 cursor remains invisible. */
5264 if (w32_use_visible_system_caret
)
5266 /* Call to erase_phys_cursor here seems to use the
5267 wrong values of w->phys_cursor, as they have been
5268 overwritten before this function was called. */
5269 if (w
->phys_cursor_type
!= NO_CURSOR
)
5270 erase_phys_cursor (w
);
5272 cursor_type
= w
->phys_cursor_type
= NO_CURSOR
;
5273 w
->phys_cursor_width
= -1;
5277 w
->phys_cursor_type
= cursor_type
;
5280 w
->phys_cursor_on_p
= 1;
5282 /* If this is the active cursor, we need to track it with the
5283 system caret, so third party software like screen magnifiers
5284 and speech synthesizers can follow the cursor. */
5287 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5288 HWND hwnd
= FRAME_W32_WINDOW (f
);
5291 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5293 = (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
5294 + glyph_row
->ascent
- w
->phys_cursor_ascent
);
5296 /* If the size of the active cursor changed, destroy the old
5298 if (w32_system_caret_hwnd
5299 && (w32_system_caret_height
!= w
->phys_cursor_height
))
5300 PostMessage (hwnd
, WM_EMACS_DESTROY_CARET
, 0, 0);
5302 w32_system_caret_height
= w
->phys_cursor_height
;
5304 /* Move the system caret. */
5305 PostMessage (hwnd
, WM_EMACS_TRACK_CARET
, 0, 0);
5308 if (glyph_row
->exact_window_width_line_p
5309 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5311 glyph_row
->cursor_in_fringe_p
= 1;
5312 draw_fringe_bitmap (w
, glyph_row
, 0);
5316 switch (cursor_type
)
5318 case HOLLOW_BOX_CURSOR
:
5319 x_draw_hollow_cursor (w
, glyph_row
);
5322 case FILLED_BOX_CURSOR
:
5323 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5327 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5331 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5335 w
->phys_cursor_width
= 0;
5349 x_bitmap_icon (f
, icon
)
5355 if (FRAME_W32_WINDOW (f
) == 0)
5359 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5360 else if (STRINGP (icon
))
5361 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5362 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5363 else if (SYMBOLP (icon
))
5367 if (EQ (icon
, intern ("application")))
5368 name
= (LPCTSTR
) IDI_APPLICATION
;
5369 else if (EQ (icon
, intern ("hand")))
5370 name
= (LPCTSTR
) IDI_HAND
;
5371 else if (EQ (icon
, intern ("question")))
5372 name
= (LPCTSTR
) IDI_QUESTION
;
5373 else if (EQ (icon
, intern ("exclamation")))
5374 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5375 else if (EQ (icon
, intern ("asterisk")))
5376 name
= (LPCTSTR
) IDI_ASTERISK
;
5377 else if (EQ (icon
, intern ("winlogo")))
5378 name
= (LPCTSTR
) IDI_WINLOGO
;
5382 hicon
= LoadIcon (NULL
, name
);
5390 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5397 /************************************************************************
5399 ************************************************************************/
5401 /* Display Error Handling functions not used on W32. Listing them here
5402 helps diff stay in step when comparing w32term.c with xterm.c.
5404 x_error_catcher (display, error)
5405 x_catch_errors (dpy)
5406 x_catch_errors_unwind (old_val)
5407 x_check_errors (dpy, format)
5408 x_had_errors_p (dpy)
5409 x_clear_errors (dpy)
5410 x_uncatch_errors (dpy, count)
5412 x_connection_signal (signalnum)
5413 x_connection_closed (dpy, error_message)
5414 x_error_quitter (display, error)
5415 x_error_handler (display, error)
5416 x_io_error_quitter (display)
5421 /* Changing the font of the frame. */
5423 /* Give frame F the font named FONTNAME as its default font, and
5424 return the full name of that font. FONTNAME may be a wildcard
5425 pattern; in that case, we choose some font that fits the pattern.
5426 The return value shows which font we chose. */
5429 x_new_font (f
, fontname
)
5431 register char *fontname
;
5433 struct font_info
*fontp
5434 = FS_LOAD_FONT (f
, fontname
);
5439 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5440 /* This font is already set in frame F. There's nothing more to
5442 return build_string (fontp
->full_name
);
5444 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5445 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5446 FRAME_FONTSET (f
) = -1;
5448 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
5449 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5451 compute_fringe_widths (f
, 1);
5453 /* Compute the scroll bar width in character columns. */
5454 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5456 int wid
= FRAME_COLUMN_WIDTH (f
);
5457 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5458 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5462 int wid
= FRAME_COLUMN_WIDTH (f
);
5463 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5466 /* Now make the frame display the given font. */
5467 if (FRAME_W32_WINDOW (f
) != 0)
5469 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5470 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5473 return build_string (fontp
->full_name
);
5476 /* Give frame F the fontset named FONTSETNAME as its default fontset,
5477 and return the full name of that fontset. FONTSETNAME may be a
5478 wildcard pattern; in that case, we choose some fontset that fits
5479 the pattern. FONTSETNAME may be a font name for ASCII characters;
5480 in that case, we create a fontset from that font name.
5482 The return value shows which fontset we chose.
5483 If FONTSETNAME specifies the default fontset, return Qt.
5484 If an ASCII font in the specified fontset can't be loaded, return
5488 x_new_fontset (f
, fontsetname
)
5490 Lisp_Object fontsetname
;
5492 int fontset
= fs_query_fontset (fontsetname
, 0);
5495 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5496 /* This fontset is already set in frame F. There's nothing more
5498 return fontset_name (fontset
);
5499 else if (fontset
== 0)
5500 /* The default fontset can't be the default font. */
5504 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5506 result
= x_new_font (f
, SDATA (fontsetname
));
5508 if (!STRINGP (result
))
5509 /* Can't load ASCII font. */
5513 fontset
= new_fontset_from_font_name (result
);
5515 /* Since x_new_font doesn't update any fontset information, do it now. */
5516 FRAME_FONTSET(f
) = fontset
;
5518 return fontset_name (fontset
);
5522 /***********************************************************************
5523 TODO: W32 Input Methods
5524 ***********************************************************************/
5525 /* Listing missing functions from xterm.c helps diff stay in step.
5527 xim_destroy_callback (xim, client_data, call_data)
5528 xim_open_dpy (dpyinfo, resource_name)
5530 xim_instantiate_callback (display, client_data, call_data)
5531 xim_initialize (dpyinfo, resource_name)
5532 xim_close_dpy (dpyinfo)
5537 /* Calculate the absolute position in frame F
5538 from its current recorded position values and gravity. */
5541 x_calc_absolute_position (f
)
5545 int flags
= f
->size_hint_flags
;
5549 /* Find the position of the outside upper-left corner of
5550 the inner window, with respect to the outer window.
5551 But do this only if we will need the results. */
5552 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
5555 MapWindowPoints (FRAME_W32_WINDOW (f
),
5556 f
->output_data
.w32
->parent_desc
,
5563 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
5566 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
5567 FRAME_EXTERNAL_MENU_BAR (f
));
5570 pt
.x
+= (rt
.right
- rt
.left
);
5571 pt
.y
+= (rt
.bottom
- rt
.top
);
5574 /* Treat negative positions as relative to the leftmost bottommost
5575 position that fits on the screen. */
5576 if (flags
& XNegative
)
5577 f
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
5578 - 2 * f
->border_width
- pt
.x
5579 - FRAME_PIXEL_WIDTH (f
)
5582 if (flags
& YNegative
)
5583 f
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
5584 - 2 * f
->border_width
- pt
.y
5585 - FRAME_PIXEL_HEIGHT (f
)
5587 /* The left_pos and top_pos
5588 are now relative to the top and left screen edges,
5589 so the flags should correspond. */
5590 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5593 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5594 to really change the position, and 0 when calling from
5595 x_make_frame_visible (in that case, XOFF and YOFF are the current
5596 position values). It is -1 when calling from x_set_frame_parameters,
5597 which means, do adjust for borders but don't change the gravity. */
5600 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5602 register int xoff
, yoff
;
5605 int modified_top
, modified_left
;
5607 if (change_gravity
> 0)
5611 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5613 f
->size_hint_flags
|= XNegative
;
5615 f
->size_hint_flags
|= YNegative
;
5616 f
->win_gravity
= NorthWestGravity
;
5618 x_calc_absolute_position (f
);
5621 x_wm_set_size_hint (f
, (long) 0, 0);
5623 modified_left
= f
->left_pos
;
5624 modified_top
= f
->top_pos
;
5626 my_set_window_pos (FRAME_W32_WINDOW (f
),
5628 modified_left
, modified_top
,
5630 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
5635 /* Check if we need to resize the frame due to a fullscreen request.
5636 If so needed, resize the frame. */
5638 x_check_fullscreen (f
)
5641 if (f
->want_fullscreen
& FULLSCREEN_BOTH
)
5643 int width
, height
, ign
;
5645 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5647 x_fullscreen_adjust (f
, &width
, &height
, &ign
, &ign
);
5649 /* We do not need to move the window, it shall be taken care of
5650 when setting WM manager hints. */
5651 if (FRAME_COLS (f
) != width
|| FRAME_LINES (f
) != height
)
5653 change_frame_size (f
, height
, width
, 0, 1, 0);
5654 SET_FRAME_GARBAGED (f
);
5655 cancel_mouse_face (f
);
5657 /* Wait for the change of frame size to occur */
5658 f
->want_fullscreen
|= FULLSCREEN_WAIT
;
5663 /* Call this to change the size of frame F's x-window.
5664 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5665 for this size change and subsequent size changes.
5666 Otherwise we leave the window gravity unchanged. */
5669 x_set_window_size (f
, change_gravity
, cols
, rows
)
5674 int pixelwidth
, pixelheight
;
5678 check_frame_size (f
, &rows
, &cols
);
5679 f
->scroll_bar_actual_width
5680 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5682 compute_fringe_widths (f
, 0);
5684 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5685 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5687 f
->win_gravity
= NorthWestGravity
;
5688 x_wm_set_size_hint (f
, (long) 0, 0);
5693 rect
.left
= rect
.top
= 0;
5694 rect
.right
= pixelwidth
;
5695 rect
.bottom
= pixelheight
;
5697 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
5698 FRAME_EXTERNAL_MENU_BAR (f
));
5700 my_set_window_pos (FRAME_W32_WINDOW (f
),
5703 rect
.right
- rect
.left
,
5704 rect
.bottom
- rect
.top
,
5705 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5708 /* Now, strictly speaking, we can't be sure that this is accurate,
5709 but the window manager will get around to dealing with the size
5710 change request eventually, and we'll hear how it went when the
5711 ConfigureNotify event gets here.
5713 We could just not bother storing any of this information here,
5714 and let the ConfigureNotify event set everything up, but that
5715 might be kind of confusing to the Lisp code, since size changes
5716 wouldn't be reported in the frame parameters until some random
5717 point in the future when the ConfigureNotify event arrives.
5719 We pass 1 for DELAY since we can't run Lisp code inside of
5721 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5722 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5723 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5725 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5726 receive in the ConfigureNotify event; if we get what we asked
5727 for, then the event won't cause the screen to become garbaged, so
5728 we have to make sure to do it here. */
5729 SET_FRAME_GARBAGED (f
);
5731 /* If cursor was outside the new size, mark it as off. */
5732 mark_window_cursors_off (XWINDOW (f
->root_window
));
5734 /* Clear out any recollection of where the mouse highlighting was,
5735 since it might be in a place that's outside the new frame size.
5736 Actually checking whether it is outside is a pain in the neck,
5737 so don't try--just let the highlighting be done afresh with new size. */
5738 cancel_mouse_face (f
);
5743 /* Mouse warping. */
5745 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5748 x_set_mouse_position (f
, x
, y
)
5754 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5755 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5757 if (pix_x
< 0) pix_x
= 0;
5758 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5760 if (pix_y
< 0) pix_y
= 0;
5761 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5763 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5767 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5776 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
5777 pt
.x
= rect
.left
+ pix_x
;
5778 pt
.y
= rect
.top
+ pix_y
;
5779 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
5781 SetCursorPos (pt
.x
, pt
.y
);
5787 /* focus shifting, raising and lowering. */
5790 x_focus_on_frame (f
)
5793 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
5795 /* Give input focus to frame. */
5798 /* Try not to change its Z-order if possible. */
5799 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
5800 my_set_focus (f
, FRAME_W32_WINDOW (f
));
5803 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5813 /* Raise frame F. */
5820 /* Strictly speaking, raise-frame should only change the frame's Z
5821 order, leaving input focus unchanged. This is reasonable behaviour
5822 on X where the usual policy is point-to-focus. However, this
5823 behaviour would be very odd on Windows where the usual policy is
5826 On X, if the mouse happens to be over the raised frame, it gets
5827 input focus anyway (so the window with focus will never be
5828 completely obscured) - if not, then just moving the mouse over it
5829 is sufficient to give it focus. On Windows, the user must actually
5830 click on the frame (preferrably the title bar so as not to move
5831 point), which is more awkward. Also, no other Windows program
5832 raises a window to the top but leaves another window (possibly now
5833 completely obscured) with input focus.
5835 Because there is a system setting on Windows that allows the user
5836 to choose the point to focus policy, we make the strict semantics
5837 optional, but by default we grab focus when raising. */
5839 if (NILP (Vw32_grab_focus_on_raise
))
5841 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5842 not already the foreground application: the frame is raised
5843 above all other frames belonging to us, but not above the
5844 current top window. To achieve that, we have to resort to this
5845 more cumbersome method. */
5847 HDWP handle
= BeginDeferWindowPos (2);
5850 DeferWindowPos (handle
,
5851 FRAME_W32_WINDOW (f
),
5854 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5856 DeferWindowPos (handle
,
5857 GetForegroundWindow (),
5858 FRAME_W32_WINDOW (f
),
5860 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5862 EndDeferWindowPos (handle
);
5867 my_set_foreground_window (FRAME_W32_WINDOW (f
));
5873 /* Lower frame F. */
5879 my_set_window_pos (FRAME_W32_WINDOW (f
),
5882 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
5887 w32_frame_raise_lower (f
, raise_flag
)
5891 if (! FRAME_W32_P (f
))
5900 /* Change of visibility. */
5902 /* This tries to wait until the frame is really visible.
5903 However, if the window manager asks the user where to position
5904 the frame, this will return before the user finishes doing that.
5905 The frame will not actually be visible at that time,
5906 but it will become visible later when the window manager
5907 finishes with it. */
5910 x_make_frame_visible (f
)
5917 type
= x_icon_type (f
);
5919 x_bitmap_icon (f
, type
);
5921 if (! FRAME_VISIBLE_P (f
))
5923 /* We test FRAME_GARBAGED_P here to make sure we don't
5924 call x_set_offset a second time
5925 if we get to x_make_frame_visible a second time
5926 before the window gets really visible. */
5927 if (! FRAME_ICONIFIED_P (f
)
5928 && ! f
->output_data
.w32
->asked_for_visible
)
5929 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5931 f
->output_data
.w32
->asked_for_visible
= 1;
5933 /* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
5934 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
5937 /* Synchronize to ensure Emacs knows the frame is visible
5938 before we do anything else. We do this loop with input not blocked
5939 so that incoming events are handled. */
5944 /* This must come after we set COUNT. */
5947 XSETFRAME (frame
, f
);
5949 /* Wait until the frame is visible. Process X events until a
5950 MapNotify event has been seen, or until we think we won't get a
5951 MapNotify at all.. */
5952 for (count
= input_signal_count
+ 10;
5953 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5955 /* Force processing of queued events. */
5956 /* TODO: x_sync equivalent? */
5958 /* Machines that do polling rather than SIGIO have been observed
5959 to go into a busy-wait here. So we'll fake an alarm signal
5960 to let the handler know that there's something to be read.
5961 We used to raise a real alarm, but it seems that the handler
5962 isn't always enabled here. This is probably a bug. */
5963 if (input_polling_used ())
5965 /* It could be confusing if a real alarm arrives while processing
5966 the fake one. Turn it off and let the handler reset it. */
5967 int old_poll_suppress_count
= poll_suppress_count
;
5968 poll_suppress_count
= 1;
5969 poll_for_input_1 ();
5970 poll_suppress_count
= old_poll_suppress_count
;
5973 FRAME_SAMPLE_VISIBILITY (f
);
5977 /* Change from mapped state to withdrawn state. */
5979 /* Make the frame visible (mapped and not iconified). */
5981 x_make_frame_invisible (f
)
5984 /* Don't keep the highlight on an invisible frame. */
5985 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5986 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5990 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
5992 /* We can't distinguish this from iconification
5993 just by the event that we get from the server.
5994 So we can't win using the usual strategy of letting
5995 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5996 and synchronize with the server to make sure we agree. */
5998 FRAME_ICONIFIED_P (f
) = 0;
5999 f
->async_visible
= 0;
6000 f
->async_iconified
= 0;
6005 /* Change window state from mapped to iconified. */
6013 /* Don't keep the highlight on an invisible frame. */
6014 if (FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6015 FRAME_W32_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6017 if (f
->async_iconified
)
6022 type
= x_icon_type (f
);
6024 x_bitmap_icon (f
, type
);
6026 /* Simulate the user minimizing the frame. */
6027 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
6033 /* Free X resources of frame F. */
6036 x_free_frame_resources (f
)
6039 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6043 if (FRAME_W32_WINDOW (f
))
6044 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
6046 free_frame_menubar (f
);
6048 unload_color (f
, f
->output_data
.x
->foreground_pixel
);
6049 unload_color (f
, f
->output_data
.x
->background_pixel
);
6050 unload_color (f
, f
->output_data
.w32
->cursor_pixel
);
6051 unload_color (f
, f
->output_data
.w32
->cursor_foreground_pixel
);
6052 unload_color (f
, f
->output_data
.w32
->border_pixel
);
6053 unload_color (f
, f
->output_data
.w32
->mouse_pixel
);
6054 if (f
->output_data
.w32
->white_relief
.allocated_p
)
6055 unload_color (f
, f
->output_data
.w32
->white_relief
.pixel
);
6056 if (f
->output_data
.w32
->black_relief
.allocated_p
)
6057 unload_color (f
, f
->output_data
.w32
->black_relief
.pixel
);
6059 if (FRAME_FACE_CACHE (f
))
6060 free_frame_faces (f
);
6062 xfree (f
->output_data
.w32
);
6063 f
->output_data
.w32
= NULL
;
6065 if (f
== dpyinfo
->w32_focus_frame
)
6066 dpyinfo
->w32_focus_frame
= 0;
6067 if (f
== dpyinfo
->w32_focus_event_frame
)
6068 dpyinfo
->w32_focus_event_frame
= 0;
6069 if (f
== dpyinfo
->x_highlight_frame
)
6070 dpyinfo
->x_highlight_frame
= 0;
6072 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6074 dpyinfo
->mouse_face_beg_row
6075 = dpyinfo
->mouse_face_beg_col
= -1;
6076 dpyinfo
->mouse_face_end_row
6077 = dpyinfo
->mouse_face_end_col
= -1;
6078 dpyinfo
->mouse_face_window
= Qnil
;
6079 dpyinfo
->mouse_face_deferred_gc
= 0;
6080 dpyinfo
->mouse_face_mouse_frame
= 0;
6087 /* Destroy the window of frame F. */
6089 x_destroy_window (f
)
6092 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6094 x_free_frame_resources (f
);
6096 dpyinfo
->reference_count
--;
6100 /* Setting window manager hints. */
6102 /* Set the normal size hints for the window manager, for frame F.
6103 FLAGS is the flags word to use--or 0 meaning preserve the flags
6104 that the window now has.
6105 If USER_POSITION is nonzero, we set the USPosition
6106 flag (this is useful when FLAGS is 0). */
6108 x_wm_set_size_hint (f
, flags
, user_position
)
6113 Window window
= FRAME_W32_WINDOW (f
);
6117 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FRAME_COLUMN_WIDTH (f
));
6118 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, FRAME_LINE_HEIGHT (f
));
6119 SetWindowLong (window
, WND_BORDER_INDEX
, FRAME_INTERNAL_BORDER_WIDTH (f
));
6120 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->scroll_bar_actual_width
);
6125 /* Window manager things */
6127 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6132 Window window
= FRAME_W32_WINDOW (f
);
6134 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
6135 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
6136 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
6138 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
6143 /***********************************************************************
6145 ***********************************************************************/
6147 /* The following functions are listed here to help diff stay in step
6148 with xterm.c. See w32fns.c for definitions.
6150 x_get_font_info (f, font_idx)
6151 x_list_fonts (f, pattern, size, maxnames)
6157 /* Check that FONT is valid on frame F. It is if it can be found in F's
6161 x_check_font (f
, font
)
6166 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6168 xassert (font
!= NULL
);
6170 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6171 if (dpyinfo
->font_table
[i
].name
6172 && font
== dpyinfo
->font_table
[i
].font
)
6175 xassert (i
< dpyinfo
->n_fonts
);
6178 #endif /* GLYPH_DEBUG != 0 */
6180 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6181 Note: There are (broken) X fonts out there with invalid XFontStruct
6182 min_bounds contents. For example, handa@etl.go.jp reports that
6183 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6184 have font->min_bounds.width == 0. */
6187 x_font_min_bounds (font
, w
, h
)
6192 * TODO: Windows does not appear to offer min bound, only
6193 * average and maximum width, and maximum height.
6195 *h
= FONT_HEIGHT (font
);
6196 *w
= FONT_WIDTH (font
);
6200 /* Compute the smallest character width and smallest font height over
6201 all fonts available on frame F. Set the members smallest_char_width
6202 and smallest_font_height in F's x_display_info structure to
6203 the values computed. Value is non-zero if smallest_font_height or
6204 smallest_char_width become smaller than they were before. */
6207 x_compute_min_glyph_bounds (f
)
6211 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
6213 int old_width
= dpyinfo
->smallest_char_width
;
6214 int old_height
= dpyinfo
->smallest_font_height
;
6216 dpyinfo
->smallest_font_height
= 100000;
6217 dpyinfo
->smallest_char_width
= 100000;
6219 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6220 if (dpyinfo
->font_table
[i
].name
)
6222 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6225 font
= (XFontStruct
*) fontp
->font
;
6226 xassert (font
!= (XFontStruct
*) ~0);
6227 x_font_min_bounds (font
, &w
, &h
);
6229 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6230 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6233 xassert (dpyinfo
->smallest_char_width
> 0
6234 && dpyinfo
->smallest_font_height
> 0);
6236 return (dpyinfo
->n_fonts
== 1
6237 || dpyinfo
->smallest_char_width
< old_width
6238 || dpyinfo
->smallest_font_height
< old_height
);
6241 /* The following functions are listed here to help diff stay in step
6242 with xterm.c. See w32fns.c for definitions.
6244 x_load_font (f, fontname, size)
6245 x_query_font (f, fontname)
6246 x_find_ccl_program (fontp)
6250 /***********************************************************************
6252 ***********************************************************************/
6254 static int w32_initialized
= 0;
6257 w32_initialize_display_info (display_name
)
6258 Lisp_Object display_name
;
6260 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
6262 bzero (dpyinfo
, sizeof (*dpyinfo
));
6264 /* Put it on w32_display_name_list. */
6265 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6266 w32_display_name_list
);
6267 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
6269 dpyinfo
->w32_id_name
6270 = (char *) xmalloc (SCHARS (Vinvocation_name
)
6271 + SCHARS (Vsystem_name
)
6273 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
6274 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
6276 /* Default Console mode values - overridden when running in GUI mode
6277 with values obtained from system metrics. */
6280 dpyinfo
->height_in
= 1;
6281 dpyinfo
->width_in
= 1;
6282 dpyinfo
->n_planes
= 1;
6283 dpyinfo
->n_cbits
= 4;
6284 dpyinfo
->n_fonts
= 0;
6285 dpyinfo
->smallest_font_height
= 1;
6286 dpyinfo
->smallest_char_width
= 1;
6288 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6289 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6290 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
6291 dpyinfo
->mouse_face_window
= Qnil
;
6292 dpyinfo
->mouse_face_overlay
= Qnil
;
6293 dpyinfo
->mouse_face_hidden
= 0;
6295 dpyinfo
->vertical_scroll_bar_cursor
= w32_load_cursor (IDC_ARROW
);
6296 /* TODO: dpyinfo->gray */
6300 /* Create an xrdb-style database of resources to supercede registry settings.
6301 The database is just a concatenation of C strings, finished by an additional
6302 \0. The string are submitted to some basic normalization, so
6304 [ *]option[ *]:[ *]value...
6310 but any whitespace following value is not removed. */
6313 w32_make_rdb (xrm_option
)
6316 char *buffer
= xmalloc (strlen (xrm_option
) + 2);
6317 char *current
= buffer
;
6320 int before_value
= 0;
6334 if (in_option
&& (ch
== ':'))
6339 else if (before_value
)
6344 else if (!(in_option
|| before_value
))
6355 struct w32_display_info
*
6356 w32_term_init (display_name
, xrm_option
, resource_name
)
6357 Lisp_Object display_name
;
6359 char *resource_name
;
6361 struct w32_display_info
*dpyinfo
;
6366 if (!w32_initialized
)
6369 w32_initialized
= 1;
6372 w32_initialize_display_info (display_name
);
6374 dpyinfo
= &one_w32_display_info
;
6376 dpyinfo
->xrdb
= xrm_option
? w32_make_rdb (xrm_option
) : NULL
;
6378 /* Put this display on the chain. */
6379 dpyinfo
->next
= x_display_list
;
6380 x_display_list
= dpyinfo
;
6382 hdc
= GetDC (GetDesktopWindow ());
6384 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
6385 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
6386 dpyinfo
->root_window
= GetDesktopWindow ();
6387 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
6388 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
6389 dpyinfo
->resx
= GetDeviceCaps (hdc
, LOGPIXELSX
);
6390 dpyinfo
->resy
= GetDeviceCaps (hdc
, LOGPIXELSY
);
6391 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
6392 dpyinfo
->image_cache
= make_image_cache ();
6393 dpyinfo
->height_in
= dpyinfo
->height
/ dpyinfo
->resx
;
6394 dpyinfo
->width_in
= dpyinfo
->width
/ dpyinfo
->resy
;
6395 ReleaseDC (GetDesktopWindow (), hdc
);
6397 /* initialise palette with white and black */
6400 w32_defined_color (0, "white", &color
, 1);
6401 w32_defined_color (0, "black", &color
, 1);
6404 /* Create Fringe Bitmaps and store them for later use.
6406 On W32, bitmaps are all unsigned short, as Windows requires
6407 bitmap data to be Word aligned. For some reason they are
6408 horizontally reflected compared to how they appear on X, so we
6409 need to bitswap and convert to unsigned shorts before creating
6413 #ifndef F_SETOWN_BUG
6415 #ifdef F_SETOWN_SOCK_NEG
6416 /* stdin is a socket here */
6417 fcntl (connection
, F_SETOWN
, -getpid ());
6418 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6419 fcntl (connection
, F_SETOWN
, getpid ());
6420 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6421 #endif /* ! defined (F_SETOWN) */
6422 #endif /* F_SETOWN_BUG */
6425 if (interrupt_input
)
6426 init_sigio (connection
);
6427 #endif /* ! defined (SIGIO) */
6434 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6437 x_delete_display (dpyinfo
)
6438 struct w32_display_info
*dpyinfo
;
6440 /* Discard this display from w32_display_name_list and w32_display_list.
6441 We can't use Fdelq because that can quit. */
6442 if (! NILP (w32_display_name_list
)
6443 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
6444 w32_display_name_list
= XCDR (w32_display_name_list
);
6449 tail
= w32_display_name_list
;
6450 while (CONSP (tail
) && CONSP (XCDR (tail
)))
6452 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
6454 XSETCDR (tail
, XCDR (XCDR (tail
)));
6461 /* free palette table */
6463 struct w32_palette_entry
* plist
;
6465 plist
= dpyinfo
->color_list
;
6468 struct w32_palette_entry
* pentry
= plist
;
6469 plist
= plist
->next
;
6472 dpyinfo
->color_list
= NULL
;
6473 if (dpyinfo
->palette
)
6474 DeleteObject(dpyinfo
->palette
);
6476 xfree (dpyinfo
->font_table
);
6477 xfree (dpyinfo
->w32_id_name
);
6479 w32_reset_fringes ();
6482 /* Set up use of W32. */
6484 DWORD
w32_msg_worker ();
6487 x_flush (struct frame
* f
)
6488 { /* Nothing to do */ }
6490 extern frame_parm_handler w32_frame_parm_handlers
[];
6492 static struct redisplay_interface w32_redisplay_interface
=
6494 w32_frame_parm_handlers
,
6498 x_clear_end_of_line
,
6500 x_after_update_window_line
,
6501 x_update_window_begin
,
6502 x_update_window_end
,
6505 0, /* flush_display_optional */
6506 x_clear_window_mouse_face
,
6507 w32_get_glyph_overhangs
,
6508 x_fix_overlapping_area
,
6509 w32_draw_fringe_bitmap
,
6510 w32_define_fringe_bitmap
,
6511 w32_destroy_fringe_bitmap
,
6512 w32_per_char_metric
,
6514 NULL
, /* w32_compute_glyph_string_overhangs */
6515 x_draw_glyph_string
,
6516 w32_define_frame_cursor
,
6517 w32_clear_frame_area
,
6518 w32_draw_window_cursor
,
6519 w32_draw_vertical_window_border
,
6520 w32_shift_glyphs_for_insert
6526 rif
= &w32_redisplay_interface
;
6528 /* MSVC does not type K&R functions with no arguments correctly, and
6529 so we must explicitly cast them. */
6530 clear_frame_hook
= (void (*)(void)) x_clear_frame
;
6531 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
6532 update_begin_hook
= x_update_begin
;
6533 update_end_hook
= x_update_end
;
6535 read_socket_hook
= w32_read_socket
;
6537 frame_up_to_date_hook
= w32_frame_up_to_date
;
6539 mouse_position_hook
= w32_mouse_position
;
6540 frame_rehighlight_hook
= w32_frame_rehighlight
;
6541 frame_raise_lower_hook
= w32_frame_raise_lower
;
6542 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
6543 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
6544 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
6545 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
6547 scroll_region_ok
= 1; /* we'll scroll partial frames */
6548 char_ins_del_ok
= 1;
6549 line_ins_del_ok
= 1; /* we'll just blt 'em */
6550 fast_clear_end_of_line
= 1; /* X does this well */
6551 memory_below_frame
= 0; /* we don't remember what scrolls
6555 w32_system_caret_hwnd
= NULL
;
6556 w32_system_caret_height
= 0;
6557 w32_system_caret_x
= 0;
6558 w32_system_caret_y
= 0;
6560 last_tool_bar_item
= -1;
6561 any_help_event_p
= 0;
6563 /* Initialize input mode: interrupt_input off, no flow control, allow
6564 8 bit character input, standard quit char. */
6565 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
6567 /* Create the window thread - it will terminate itself or when the app terminates */
6571 dwMainThreadId
= GetCurrentThreadId ();
6572 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6573 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
6575 /* Wait for thread to start */
6580 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
6582 hWindowsThread
= CreateThread (NULL
, 0,
6583 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
6584 0, 0, &dwWindowsThreadId
);
6586 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
6589 /* It is desirable that mainThread should have the same notion of
6590 focus window and active window as windowsThread. Unfortunately, the
6591 following call to AttachThreadInput, which should do precisely what
6592 we need, causes major problems when Emacs is linked as a console
6593 program. Unfortunately, we have good reasons for doing that, so
6594 instead we need to send messages to windowsThread to make some API
6595 calls for us (ones that affect, or depend on, the active/focus
6597 #ifdef ATTACH_THREADS
6598 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
6601 /* Dynamically link to optional system components. */
6603 HANDLE user_lib
= LoadLibrary ("user32.dll");
6604 HANDLE gdi_lib
= LoadLibrary ("gdi32.dll");
6606 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6608 /* New proportional scroll bar functions. */
6609 LOAD_PROC (user_lib
, SetScrollInfo
);
6610 LOAD_PROC (user_lib
, GetScrollInfo
);
6611 LOAD_PROC (gdi_lib
, GetFontUnicodeRanges
);
6615 FreeLibrary (user_lib
);
6616 FreeLibrary (gdi_lib
);
6618 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
6619 otherwise use the fixed height. */
6620 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
6621 GetSystemMetrics (SM_CYVTHUMB
);
6623 /* For either kind of scroll bar, take account of the arrows; these
6624 effectively form the border of the main scroll bar range. */
6625 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
6626 = GetSystemMetrics (SM_CYVSCROLL
);
6633 staticpro (&w32_display_name_list
);
6634 w32_display_name_list
= Qnil
;
6636 staticpro (&last_mouse_scroll_bar
);
6637 last_mouse_scroll_bar
= Qnil
;
6639 staticpro (&Qvendor_specific_keysyms
);
6640 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6642 DEFVAR_INT ("w32-num-mouse-buttons",
6643 &w32_num_mouse_buttons
,
6644 doc
: /* Number of physical mouse buttons. */);
6645 w32_num_mouse_buttons
= 2;
6647 DEFVAR_LISP ("w32-swap-mouse-buttons",
6648 &Vw32_swap_mouse_buttons
,
6649 doc
: /* Swap the mapping of middle and right mouse buttons.
6650 When nil, middle button is mouse-2 and right button is mouse-3. */);
6651 Vw32_swap_mouse_buttons
= Qnil
;
6653 DEFVAR_LISP ("w32-grab-focus-on-raise",
6654 &Vw32_grab_focus_on_raise
,
6655 doc
: /* Raised frame grabs input focus.
6656 When t, `raise-frame' grabs input focus as well. This fits well
6657 with the normal Windows click-to-focus policy, but might not be
6658 desirable when using a point-to-focus policy. */);
6659 Vw32_grab_focus_on_raise
= Qt
;
6661 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6662 &Vw32_capslock_is_shiftlock
,
6663 doc
: /* Apply CapsLock state to non character input keys.
6664 When nil, CapsLock only affects normal character input keys. */);
6665 Vw32_capslock_is_shiftlock
= Qnil
;
6667 DEFVAR_LISP ("w32-recognize-altgr",
6668 &Vw32_recognize_altgr
,
6669 doc
: /* Recognize right-alt and left-ctrl as AltGr.
6670 When nil, the right-alt and left-ctrl key combination is
6671 interpreted normally. */);
6672 Vw32_recognize_altgr
= Qt
;
6674 DEFVAR_BOOL ("w32-enable-unicode-output",
6675 &w32_enable_unicode_output
,
6676 doc
: /* Enable the use of Unicode for text output if non-nil.
6677 Unicode output may prevent some third party applications for displaying
6678 Far-East Languages on Windows 95/98 from working properly.
6679 NT uses Unicode internally anyway, so this flag will probably have no
6680 affect on NT machines. */);
6681 w32_enable_unicode_output
= 1;
6683 DEFVAR_BOOL ("w32-use-visible-system-caret",
6684 &w32_use_visible_system_caret
,
6685 doc
: /* Flag to make the system caret visible.
6686 When this is non-nil, Emacs will indicate the position of point by
6687 using the system caret instead of drawing its own cursor. Some screen
6688 reader software does not track the system cursor properly when it is
6689 invisible, and gets confused by Emacs drawing its own cursor, so this
6690 variable is initialized to t when Emacs detects that screen reader
6691 software is running as it starts up.
6693 When this variable is set, other variables affecting the appearance of
6694 the cursor have no effect. */);
6696 /* Initialize w32_use_visible_system_caret based on whether a screen
6697 reader is in use. */
6698 if (!SystemParametersInfo (SPI_GETSCREENREADER
, 0,
6699 &w32_use_visible_system_caret
, 0))
6700 w32_use_visible_system_caret
= 0;
6702 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
6703 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
6704 Vx_toolkit_scroll_bars
= Qt
;
6706 staticpro (&last_mouse_motion_frame
);
6707 last_mouse_motion_frame
= Qnil
;
6710 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6711 (do not change this comment) */