1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 #include "blockinput.h"
41 #include "dispextern.h"
42 #include "termhooks.h"
50 #include "intervals.h"
55 #define min(x, y) (((x) < (y)) ? (x) : (y))
56 #define max(x, y) (((x) > (y)) ? (x) : (y))
58 /* Windows libraries do not define codepages other than ANSI and
59 Unicode. We need all the ones for the languages that Emacs supports
60 if languages other than that of the current locale are to be
61 displayed under NT. */
62 #define CP_DEFAULT 1004
68 #define CP_LATIN1 1252
69 #define CP_LATIN2 1250
70 #define CP_LATIN3 1254
71 #define CP_LATIN4 1257
72 #define CP_CYRILLIC5 1251
73 #define CP_ARABIC6 1256
74 #define CP_GREEK7 1253
75 #define CP_HEBREW8 1255
76 #define CP_LATIN9 /*1258?*/
77 #define CP_VIETNAM /*???*/
79 /* ENCODE_SJIS is defined in coding.h, but ENCODE_BIG5 is only in
80 coding.c, so need our own copy here */
81 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
82 #define ENCODE_BIG5(charset, c1, c2, b1, b2) \
84 unsigned int temp = (c1 - 0x21) * (0xFF - 0xA1) + (c2 - 0x21); \
85 if (charset == charset_big5_2) \
86 temp += BIG5_SAME_ROW * (0xC9 - 0xA1); \
87 b1 = temp / BIG5_SAME_ROW + 0xA1; \
88 b2 = temp % BIG5_SAME_ROW; \
89 b2 += b2 < 0x3F ? 0x40 : 0x62; \
92 extern unsigned int msh_mousewheel
;
94 extern void free_frame_menubar ();
96 extern Lisp_Object Vwindow_system
;
98 #define x_any_window_to_frame x_window_to_frame
99 #define x_top_window_to_frame x_window_to_frame
102 /* This is display since w32 does not support multiple ones. */
103 struct w32_display_info one_w32_display_info
;
105 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
106 one for each element of w32_display_list and in the same order.
107 NAME is the name of the frame.
108 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
109 Lisp_Object w32_display_name_list
;
111 /* Frame being updated by update_frame. This is declared in term.c.
112 This is set by update_begin and looked at by all the
113 w32 functions. It is zero while not inside an update.
114 In that case, the w32 functions assume that `selected_frame'
115 is the frame to apply to. */
116 extern struct frame
*updating_frame
;
118 /* This is a frame waiting to be autoraised, within w32_read_socket. */
119 struct frame
*pending_autoraise_frame
;
121 /* During an update, maximum vpos for ins/del line operations to affect. */
123 static int flexlines
;
125 /* During an update, nonzero if chars output now should be highlighted. */
127 static int highlight
;
129 /* Nominal cursor position -- where to draw output.
130 During an update, these are different from the cursor-box position. */
135 /* Flag to enable Unicode output in case users wish to use programs
136 like Twinbridge on '95 rather than installed system level support
137 for Far East languages. */
138 int w32_enable_unicode_output
;
140 DWORD dwWindowsThreadId
= 0;
141 HANDLE hWindowsThread
= NULL
;
142 DWORD dwMainThreadId
= 0;
143 HANDLE hMainThread
= NULL
;
146 /* These definitions are new with Windows 95. */
147 #define SIF_RANGE 0x0001
148 #define SIF_PAGE 0x0002
149 #define SIF_POS 0x0004
150 #define SIF_DISABLENOSCROLL 0x0008
151 #define SIF_TRACKPOS 0x0010
152 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
154 typedef struct tagSCROLLINFO
163 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
164 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
167 /* Dynamic linking to new proportional scroll bar functions. */
168 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
169 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
171 int vertical_scroll_bar_min_handle
;
172 int vertical_scroll_bar_top_border
;
173 int vertical_scroll_bar_bottom_border
;
175 int last_scroll_bar_drag_pos
;
177 /* Mouse movement. */
179 /* Where the mouse was last time we reported a mouse event. */
180 static FRAME_PTR last_mouse_frame
;
181 static RECT last_mouse_glyph
;
183 Lisp_Object Vw32_num_mouse_buttons
;
185 Lisp_Object Vw32_swap_mouse_buttons
;
187 /* Control whether x_raise_frame also sets input focus. */
188 Lisp_Object Vw32_grab_focus_on_raise
;
190 /* Control whether Caps Lock affects non-ascii characters. */
191 Lisp_Object Vw32_capslock_is_shiftlock
;
193 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
194 Lisp_Object Vw32_recognize_altgr
;
196 /* The scroll bar in which the last motion event occurred.
198 If the last motion event occurred in a scroll bar, we set this
199 so w32_mouse_position can know whether to report a scroll bar motion or
202 If the last motion event didn't occur in a scroll bar, we set this
203 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
204 Lisp_Object last_mouse_scroll_bar
;
205 int last_mouse_scroll_bar_pos
;
207 /* This is a hack. We would really prefer that w32_mouse_position would
208 return the time associated with the position it returns, but there
209 doesn't seem to be any way to wrest the timestamp from the server
210 along with the position query. So, we just keep track of the time
211 of the last movement we received, and return that in hopes that
212 it's somewhat accurate. */
213 Time last_mouse_movement_time
;
215 /* Incremented by w32_read_socket whenever it really tries to read events. */
217 static int volatile input_signal_count
;
219 static int input_signal_count
;
222 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
224 extern Lisp_Object Qface
, Qmouse_face
;
228 /* A mask of extra modifier bits to put into every keyboard char. */
229 extern int extra_keyboard_modifiers
;
231 static Lisp_Object Qvendor_specific_keysyms
;
233 void w32_delete_display ();
235 static void redraw_previous_char ();
236 static void redraw_following_char ();
237 static unsigned int w32_get_modifiers ();
239 static int fast_find_position ();
240 static void note_mouse_highlight ();
241 static void clear_mouse_face ();
242 static void show_mouse_face ();
243 static void do_line_dance ();
245 /* Forward declarations for term hooks. Consistency with the rest of Emacs
246 requires the use of K&R functions prototypes. However, MSVC does not
247 pick up the function prototypes correctly with K&R function definitions,
248 and so we declare them first to give a little help to MSVC. */
249 static void w32_clear_frame ();
250 static void w32_clear_end_of_line (int);
251 static void w32_ins_del_lines (int, int);
252 static void w32_change_line_highlight (int, int, int);
253 static void w32_insert_glyphs (GLYPH
*, int);
254 static void w32_write_glyphs (GLYPH
*, int);
255 static void w32_delete_glyphs (int);
256 static void w32_ring_bell ();
257 static void w32_reset_terminal_modes ();
258 static void w32_set_terminal_modes ();
259 static void w32_update_begin (FRAME_PTR
);
260 static void w32_update_end (FRAME_PTR
);
261 static void w32_set_terminal_window (int);
262 extern int w32_read_socket (int, struct input_event
*, int, int);
263 static void w32_frame_up_to_date (FRAME_PTR
);
264 static void w32_cursor_to (int, int);
265 static void w32_reassert_line_highlight (int, int);
266 static void w32_mouse_position (FRAME_PTR
*, int, Lisp_Object
*,
267 enum scroll_bar_part
*, Lisp_Object
*,
268 Lisp_Object
*, unsigned long *);
269 static void w32_frame_rehighlight (FRAME_PTR
);
270 static void w32_frame_raise_lower (FRAME_PTR
, int);
271 static void w32_set_vertical_scroll_bar (struct window
*, int, int, int);
272 static void w32_condemn_scroll_bars (FRAME_PTR
);
273 static void w32_redeem_scroll_bar (struct window
*);
274 static void w32_judge_scroll_bars (FRAME_PTR
);
277 /* This is a function useful for recording debugging information
278 about the sequence of occurrences in this file. */
286 struct record event_record
[100];
288 int event_record_index
;
290 record_event (locus
, type
)
294 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
295 event_record_index
= 0;
297 event_record
[event_record_index
].locus
= locus
;
298 event_record
[event_record_index
].type
= type
;
299 event_record_index
++;
304 /* Return the struct w32_display_info. */
306 struct w32_display_info
*
307 w32_display_info_for_display ()
309 return (&one_w32_display_info
);
313 w32_fill_rect (f
, _hdc
, pix
, lprect
)
328 hdc
= get_frame_dc (f
);
331 hb
= CreateSolidBrush (pix
);
332 FillRect (hdc
, lprect
, hb
);
336 release_frame_dc (f
, hdc
);
345 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
346 w32_clear_rect (f
, NULL
, &rect
);
350 /* Starting and ending updates.
352 These hooks are called by update_frame at the beginning and end
353 of a frame update. We record in `updating_frame' the identity
354 of the frame being updated, so that the w32_... functions do not
355 need to take a frame as argument. Most of the w32_... functions
356 should never be called except during an update, the only exceptions
357 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
366 flexlines
= f
->height
;
371 /* Regenerate display palette before drawing if list of requested
372 colors has changed. */
373 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
375 w32_regenerate_palette (f
);
376 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
379 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
381 /* Don't do highlighting for mouse motion during the update. */
382 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
384 /* If the frame needs to be redrawn,
385 simply forget about any prior mouse highlighting. */
386 if (FRAME_GARBAGED_P (f
))
387 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
389 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
391 int firstline
, lastline
, i
;
392 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
394 /* Find the first, and the last+1, lines affected by redisplay. */
395 for (firstline
= 0; firstline
< f
->height
; firstline
++)
396 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
399 lastline
= f
->height
;
400 for (i
= f
->height
- 1; i
>= 0; i
--)
402 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
408 /* Can we tell that this update does not affect the window
409 where the mouse highlight is? If so, no need to turn off.
410 Likewise, don't do anything if the frame is garbaged;
411 in that case, the FRAME_CURRENT_GLYPHS that we would use
412 are all wrong, and we will redisplay that line anyway. */
413 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
414 || lastline
< XFASTINT (w
->top
)))
415 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
429 x_display_cursor (f
, 1);
431 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
432 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
437 /* This is called after a redisplay on frame F. */
440 w32_frame_up_to_date (f
)
444 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
445 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
447 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
448 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
449 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
450 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
455 /* External interface to control of standout mode.
456 Call this when about to modify line at position VPOS
457 and not change whether it is highlighted. */
460 w32_reassert_line_highlight (new, vpos
)
466 /* Call this when about to modify line at position VPOS
467 and change whether it is highlighted. */
470 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
471 int new_highlight
, vpos
, first_unused_hpos
;
473 highlight
= new_highlight
;
474 w32_cursor_to (vpos
, 0);
475 w32_clear_end_of_line (updating_frame
->width
);
478 /* This is used when starting Emacs and when restarting after suspend.
479 When starting Emacs, no window is mapped. And nothing must be done
480 to Emacs's own window if it is suspended (though that rarely happens). */
483 w32_set_terminal_modes (void)
487 /* This is called when exiting or suspending Emacs.
488 Exiting will make the W32 windows go away, and suspending
489 requires no action. */
492 w32_reset_terminal_modes (void)
496 /* Set the nominal cursor position of the frame.
497 This is where display update commands will take effect.
498 This does not affect the place where the cursor-box is displayed. */
501 w32_cursor_to (row
, col
)
502 register int row
, col
;
509 if (updating_frame
== 0)
512 x_display_cursor (selected_frame
, 1);
518 w32_codepage_for_charset (int charset
)
520 /* The codepage is only used to convert to unicode, so we only need
521 to cover the languages that we may print via unicode. */
522 if (charset
== charset_latin_iso8859_1
)
524 else if (charset
== charset_big5_1
||
525 charset
== charset_big5_2
)
527 else if (charset
== charset_jisx0208
528 || charset
== charset_jisx0208_1978
529 || charset
== charset_katakana_jisx0201
530 || charset
== charset_latin_jisx0201
531 || charset
== charset_id_internal ("japanese-jisx0212"))
533 else if (charset
== charset_id_internal ("chinese-gb2312"))
535 else if (charset
== charset_id_internal ("korean-ksc5601"))
537 else if (charset
== charset_id_internal ("latin-iso8859-2"))
539 else if (charset
== charset_id_internal ("latin-iso8859-3"))
541 else if (charset
== charset_id_internal ("latin-iso8859-4"))
543 else if (charset
== charset_id_internal ("cyrillic-iso8859-5"))
545 else if (charset
== charset_id_internal ("arabic-iso8859-6"))
547 else if (charset
== charset_id_internal ("greek-iso8859-7"))
549 else if (charset
== charset_id_internal ("hebrew-iso8859-8"))
551 else if (charset
== charset_id_internal ("thai-tis620"))
553 else /* Don't care - return system default. */
558 w32_use_unicode_for_codepage (codepage
)
560 /* If the current codepage is supported, use Unicode for output. */
561 return (w32_enable_unicode_output
562 && codepage
!= CP_DEFAULT
&& IsValidCodePage (codepage
));
565 /* Dealing with bits of wchar_t as if they were an XChar2B. */
566 #define BUILD_WCHAR_T(byte1, byte2) \
567 ((wchar_t)(((byte1 & 0x00ff) << 8) | (byte2 & 0x00ff)))
577 /* Display a sequence of N glyphs found at GP.
578 WINDOW is the window to output to. LEFT and TOP are starting coords.
579 HL is 1 if this text is highlighted, 2 if the cursor is on it,
580 3 if should appear in its mouse-face.
581 JUST_FOREGROUND if 1 means draw only the foreground;
582 don't alter the background.
584 FONT is the default font to use (for glyphs whose font-code is 0).
586 Since the display generation code is responsible for calling
587 compute_char_face and compute_glyph_face on everything it puts in
588 the display structure, we can assume that the face code on each
589 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
590 to which we can actually apply intern_face.
591 Call this function with input blocked. */
594 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
597 register GLYPH
*gp
; /* Points to first GLYPH. */
598 register int n
; /* Number of glyphs to display. */
601 struct cmpchar_info
*cmpcharp
;
603 wchar_t *x_2byte_buffer
604 = (wchar_t *) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_2byte_buffer
));
605 register wchar_t *cp
; /* Steps through x_2byte_buffer[]. */
607 /* Allocate double the window width, as this buffer may contain MBCS
608 characters under w32. */
610 = (char *) alloca (2 * FRAME_WINDOW_WIDTH (f
) * sizeof (*x_1byte_buffer
));
611 register char *bp
; /* Steps through x_1byte_buffer[]. */
612 register int tlen
= GLYPH_TABLE_LENGTH
;
613 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
614 Window window
= FRAME_W32_WINDOW (f
);
615 HDC hdc
= get_frame_dc (f
);
616 int orig_left
= left
;
622 /* Get the face-code of the next GLYPH. */
623 int cf
, len
, n_chars
;
626 Lisp_Object first_ch
;
627 /* HIGHEST and LOWEST are used while drawing a composite
628 character. The meanings are described later. */
631 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
632 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
633 ch
= FAST_GLYPH_CHAR (g
);
634 if (unibyte_display_via_language_environment
635 && SINGLE_BYTE_CHAR_P (ch
)
637 ch
= unibyte_char_to_multibyte (ch
);
638 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
639 charset
= CHAR_CHARSET (ch
);
640 if (charset
== CHARSET_COMPOSITION
)
642 /* We must draw components of the composite character on the
644 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
646 /* Set the face in the slot for work. */
647 cmpcharp
->face_work
= cf
;
649 /* We don't need the return value ... */
650 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
651 hl
, just_foreground
, cmpcharp
);
652 /* ... because the width of just drawn text can be
653 calculated as follows. */
654 left
+= FONT_WIDTH (FRAME_FONT (f
)) * cmpcharp
->width
;
657 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
662 /* Find the run of consecutive glyphs which can be drawn with
663 the same DC (i.e. the same charset and the same face-code).
664 Extract their character codes into X_2BYTE_BUFFER.
665 If CMPCHARP is not NULL, face-code is not checked because we
666 use only the face specified in `cmpcharp->face_work'. */
670 int this_charset
, c1
, c2
;
673 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
674 ch
= FAST_GLYPH_CHAR (g
);
675 if (unibyte_display_via_language_environment
676 && SINGLE_BYTE_CHAR_P (ch
)
678 ch
= unibyte_char_to_multibyte (ch
);
679 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
680 if (this_charset
!= charset
681 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
685 *cp
= BUILD_WCHAR_T (c1
, c2
);
687 *cp
= BUILD_WCHAR_T (0, c1
);
690 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
694 /* LEN gets the length of the run. */
695 len
= cp
- x_2byte_buffer
;
696 /* Now output this run of chars, with the font and pixel values
697 determined by the face code CF. */
699 struct face
*face
= FRAME_DEFAULT_FACE (f
);
700 XFontStruct
*font
= NULL
;
704 int line_height
= FRAME_LINE_HEIGHT (f
);
705 /* Pixel width of each glyph in this run. */
707 = (FONT_WIDTH (FRAME_FONT (f
))
708 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
709 /* Overall pixel width of this run. */
711 = (FONT_WIDTH (FRAME_FONT (f
))
712 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
713 /* A flag to tell if we have already filled background. We
714 fill background in advance in the following cases:
715 1) A face has stipple.
716 2) A height of font is shorter than LINE_HEIGHT.
717 3) Drawing a composite character.
718 4) Font has non-zero _MULE_BASELINE_OFFSET property.
719 After filling background, we draw glyphs by XDrawString16. */
720 int background_filled
;
721 /* Baseline position of a character, offset from TOP. */
723 /* The property value of `_MULE_RELATIVE_COMPOSE' and
724 `_MULE_DEFAULT_ASCENT'. */
725 int relative_compose
= 0, default_ascent
= 0;
726 /* 1 if we find no font or a font of inappropriate size. */
727 int require_clipping
;
728 int codepage
= CP_DEFAULT
;
729 BOOL print_via_unicode
= FALSE
;
731 /* HL = 3 means use a mouse face previously chosen. */
733 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
735 /* First look at the face of the text itself. */
738 /* It's possible for the display table to specify
739 a face code that is out of range. Use 0 in that case. */
740 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
741 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
745 face
= FRAME_MODE_LINE_FACE (f
);
747 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
748 if (FACE_STIPPLE (face
))
752 /* Then comes the distinction between modeline and normal text. */
757 face
= FRAME_MODE_LINE_FACE (f
);
758 if (FACE_STIPPLE (face
))
762 /* Setting appropriate font and codepage for this charset. */
763 if (charset
!= CHARSET_ASCII
)
766 int fontset
= FACE_FONTSET (face
);
767 struct font_info
*fontp
;
769 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
770 || !(fontp
= FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
771 charset
, NULL
, fontset
)))
774 font
= (XFontStruct
*) (fontp
->font
);
775 codepage
= w32_codepage_for_charset (charset
);
776 print_via_unicode
= w32_use_unicode_for_codepage (codepage
);
778 /* tmLastChar will only exceed 255 if TEXTMETRICW is used
779 (ie on NT but not on 95). In this case there is no harm
780 in being wrong, so have a go anyway. */
782 (font
->tm
.tmLastChar
> 255
783 ? (line_height
+ font
->tm
.tmAscent
- font
->tm
.tmDescent
) / 2
784 : f
->output_data
.w32
->font_baseline
- fontp
->baseline_offset
);
785 if (FONT_HEIGHT (font
) <= line_height
786 && (font
->tm
.tmAscent
> baseline
787 || font
->tm
.tmDescent
> line_height
- baseline
))
788 /* Adjust baseline for this font to show the whole
790 baseline
= line_height
- font
->tm
.tmDescent
;
792 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
794 relative_compose
= fontp
->relative_compose
;
795 default_ascent
= fontp
->default_ascent
;
798 /* We have to change code points in the following cases. */
799 if (charset
== charset_big5_1
800 || charset
== charset_big5_2
)
802 /* Handle Big5 encoding specially rather than
805 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
807 ENCODE_BIG5 (charset
, BYTE1 (*cp
), BYTE2 (*cp
),
809 *cp
= BUILD_WCHAR_T (big1
, big2
);
812 else if (fontp
->font_encoder
)
814 /* This font requires CCL program to calculate code
815 point of characters. */
816 struct ccl_program
*ccl
= fontp
->font_encoder
;
818 if (CHARSET_DIMENSION (charset
) == 1)
819 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
821 ccl
->reg
[0] = charset
;
822 ccl
->reg
[1] = BYTE2 (*cp
);
823 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
824 /* We assume that MSBs are appropriately
825 set/reset by CCL program. */
826 #if 0 /* this probably works under NT, but not under 95. */
827 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
828 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
830 *cp
= BUILD_WCHAR_T (ccl
->reg
[1], ccl
->reg
[2]);
831 #else /* Assume single dimensional charsets stay so. */
832 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
836 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
838 ccl
->reg
[0] = charset
;
839 ccl
->reg
[1] = BYTE1 (*cp
) , ccl
->reg
[2] = BYTE2 (*cp
);
840 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
841 /* We assume that MSBs are appropriately
842 set/reset by CCL program. */
843 #if 0 /* this probably works under NT, but not under 95. */
844 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
845 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
847 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
848 #else /* Assume multidimensional charsets stay so. */
849 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
853 /* Japanese Kanji are a special case under w32, as they
854 must be printed in SJIS rather than EUC. */
855 else if ((charset
== charset_jisx0208
)
856 || (charset
== charset_jisx0208_1978
)
857 || (charset
== charset_id_internal ("japanese-jisx0212")))
860 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
862 ENCODE_SJIS (BYTE1 (*cp
), BYTE2 (*cp
), sjis1
, sjis2
);
863 *cp
= BUILD_WCHAR_T (sjis1
, sjis2
);
866 else if (fontp
->encoding
[charset
])
868 int enc
= fontp
->encoding
[charset
];
870 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
871 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
872 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
) | 0x80, BYTE2 (*cp
));
873 if (enc
== 1 || enc
== 3)
874 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
875 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
), BYTE2 (*cp
) | 0x80);
881 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
883 font
= FACE_FONT (face
);
884 if (!font
|| font
== (XFontStruct
*) FACE_DEFAULT
)
885 font
= FRAME_FONT (f
);
886 baseline
= FONT_BASE (FRAME_FONT (f
));
887 if (charset
== charset_latin_iso8859_1
)
889 if (font
->tm
.tmLastChar
< 0x80)
890 /* This font can't display Latin1 characters. */
894 for (cp
= x_2byte_buffer
;
895 cp
< x_2byte_buffer
+ len
; cp
++)
896 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
903 /* Convert x_2byte_buffer into a buffer of single byte
904 characters - possibly containing MBCS runs. */
906 for (i
= 0; i
< len
; i
++)
908 if (BYTE1 (*(x_2byte_buffer
+ i
)))
909 *bp
++ = BYTE1 (*(x_2byte_buffer
+ i
));
910 *bp
++ = BYTE2 (*(x_2byte_buffer
+ i
));
912 n_chars
= bp
- x_1byte_buffer
;
914 fg
= face
->foreground
;
915 bg
= face
->background
;
917 /* Now override that if the cursor's on this character. */
920 /* The cursor overrides stippling. */
923 if (font
== FRAME_FONT (f
)
924 && face
->background
== FRAME_BACKGROUND_PIXEL (f
)
925 && face
->foreground
== FRAME_FOREGROUND_PIXEL (f
)
928 bg
= f
->output_data
.w32
->cursor_pixel
;
929 fg
= face
->background
;
931 /* Cursor on non-default face: must merge. */
934 bg
= f
->output_data
.w32
->cursor_pixel
;
935 fg
= face
->background
;
936 /* If the glyph would be invisible,
937 try a different foreground. */
939 fg
= face
->foreground
;
941 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
943 fg
= face
->foreground
;
944 /* Make sure the cursor is distinct from text in this face. */
945 if (bg
== face
->background
946 && fg
== face
->foreground
)
948 bg
= face
->foreground
;
949 fg
= face
->background
;
955 require_clipping
= (!NILP (Vclip_large_size_font
)
956 && (font
->tm
.tmAscent
> baseline
957 || font
->tm
.tmDescent
>
958 line_height
- baseline
960 && FONT_WIDTH (font
) > glyph_width
)));
962 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
963 background_filled
= 1;
965 /* Stippling not supported under w32. */
968 || FONT_HEIGHT (font
) < line_height
969 || FONT_WIDTH (font
) < glyph_width
972 /* Fill in the background for the current run. */
973 w32_fill_area (f
, hdc
, bg
,
978 background_filled
= 1;
980 /* To assure not to fill background while drawing
981 remaining components. */
985 background_filled
= 0;
987 SetBkMode (hdc
, background_filled
? TRANSPARENT
: OPAQUE
);
988 SetTextColor (hdc
, fg
);
989 SetBkColor (hdc
, bg
);
991 if ( print_via_unicode
)
992 n_chars
= MultiByteToWideChar
993 (codepage
, 0, x_1byte_buffer
, n_chars
,
994 x_2byte_buffer
, FRAME_WINDOW_WIDTH (f
));
998 SelectObject (hdc
, font
->hfont
);
1002 int multibyte_pos_offset
= 0;
1003 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
)
1005 RECT clip_rectangle
;
1006 LPRECT clip_region
= NULL
;
1009 for (i
= 0; i
< n_chars
; i
++)
1011 if (require_clipping
)
1013 /* Set up a clipping rectangle for ExtTextOut */
1014 fuOptions
|= ETO_CLIPPED
;
1015 clip_rectangle
.left
= left
+ i
* glyph_width
;
1016 clip_rectangle
.right
1017 = left
+ (i
+ 1) * glyph_width
;
1018 clip_rectangle
.top
= top
;
1019 clip_rectangle
.bottom
= top
+ line_height
;
1020 clip_region
= &clip_rectangle
;
1023 /* baseline works differently on w32 than X,
1024 leave it out for now. */
1025 if (print_via_unicode
)
1026 ExtTextOutW (hdc
, left
+ glyph_width
* i
,
1027 top
/*+ baseline*/, fuOptions
,
1028 clip_region
, x_2byte_buffer
+ i
,
1030 else if (CHARSET_DIMENSION (charset
) > 1)
1032 /* Keep character together */
1033 int n
= CHARSET_DIMENSION (charset
) ;
1034 ExtTextOut (hdc
, left
+ multibyte_pos_offset
,
1035 top
/*+ baseline*/, fuOptions
,
1036 clip_region
, x_1byte_buffer
+ i
,
1040 multibyte_pos_offset
+= glyph_width
;
1043 ExtTextOut (hdc
, left
+ glyph_width
* i
,
1044 top
/*+ baseline*/, fuOptions
,
1045 clip_region
, x_1byte_buffer
+ i
,
1051 /* Print the whole run of characters. */
1052 if (print_via_unicode
)
1053 TextOutW (hdc
, left
, top
/*+ baseline*/,
1054 x_2byte_buffer
, n_chars
);
1056 TextOut (hdc
, left
, top
/*+ baseline*/,
1057 x_1byte_buffer
, n_chars
);
1062 /* Handle composite characters. */
1063 RECT clip_rectangle
;
1064 LPRECT clip_region
= NULL
;
1067 if (require_clipping
)
1069 /* Set up a clipping rectangle for ExtTextOut */
1070 fuOptions
|= ETO_CLIPPED
;
1071 clip_rectangle
.left
= left
;
1072 clip_rectangle
.right
= left
+ glyph_width
;
1073 clip_rectangle
.top
= top
;
1074 clip_rectangle
.bottom
= top
+ line_height
;
1075 clip_region
= &clip_rectangle
;
1077 if ((cmpcharp
->cmp_rule
|| relative_compose
)
1080 /* This is the first character. Initialize variables.
1081 HIGHEST is the highest position of glyphs ever
1082 written, LOWEST the lowest position. */
1086 && CHAR_TABLE_P (Vuse_default_ascent
)
1087 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
1089 highest
= default_ascent
;
1094 /* Per char metrics not supported on w32 - use
1096 highest
= font
->tm
.tmAscent
+ 1;
1097 lowest
= - font
->tm
.tmDescent
;
1100 if (cmpcharp
->cmp_rule
)
1101 x_offset
= (cmpcharp
->col_offset
[0]
1102 * FONT_WIDTH (FRAME_FONT (f
)));
1106 /* Draw the first character at the normal position. */
1107 if (print_via_unicode
)
1108 ExtTextOutW (hdc
, left
+ x_offset
,
1110 fuOptions
, clip_region
,
1111 x_2byte_buffer
, 1, NULL
);
1112 else if (CHARSET_DIMENSION (charset
) > 1)
1114 /* Keep character together */
1115 int n
= CHARSET_DIMENSION (charset
) ;
1116 ExtTextOut (hdc
, left
+ x_offset
,
1118 fuOptions
, clip_region
,
1119 x_1byte_buffer
, n
, NULL
);
1124 ExtTextOut (hdc
, left
+ x_offset
,
1126 fuOptions
, clip_region
,
1127 x_1byte_buffer
, 1, NULL
);
1133 for (; i
< n_chars
; i
++, gidx
++)
1135 int x_offset
= 0, y_offset
= 0;
1137 if (relative_compose
)
1139 /* No per char metrics on w32. */
1140 if (NILP (Vignore_relative_composition
)
1141 || NILP (Faref (Vignore_relative_composition
,
1142 make_number (cmpcharp
->glyph
[gidx
]))))
1144 if (- font
->tm
.tmDescent
>= relative_compose
)
1146 /* Draw above the current glyphs. */
1147 y_offset
= highest
+ font
->tm
.tmDescent
;
1148 highest
+= font
->tm
.tmAscent
1149 + font
->tm
.tmDescent
;
1151 else if (font
->tm
.tmAscent
<= 0)
1153 /* Draw beneath the current glyphs. */
1154 y_offset
= lowest
- font
->tm
.tmAscent
;
1155 lowest
-= font
->tm
.tmAscent
1156 + font
->tm
.tmDescent
;
1161 /* Draw the glyph at normal position. If
1162 it sticks out of HIGHEST or LOWEST,
1163 update them appropriately. */
1164 if (font
->tm
.tmAscent
> highest
)
1165 highest
= font
->tm
.tmAscent
;
1166 else if (- font
->tm
.tmDescent
< lowest
)
1167 lowest
= - font
->tm
.tmDescent
;
1170 else if (cmpcharp
->cmp_rule
)
1172 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1173 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1176 /* Re-encode GREF and NREF so that they specify
1177 only Y-axis information:
1178 0:top, 1:base, 2:bottom, 3:center */
1179 gref
= gref
/ 3 + (gref
== 4) * 2;
1180 nref
= nref
/ 3 + (nref
== 4) * 2;
1182 /* No per char metrics on w32. */
1183 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1184 : gref
== 2 ? lowest
1185 : (highest
+ lowest
) / 2)
1186 - (nref
== 0 ? font
->tm
.tmAscent
1187 + font
->tm
.tmDescent
1188 : nref
== 1 ? font
->tm
.tmDescent
1190 : (font
->tm
.tmAscent
+
1191 font
->tm
.tmDescent
) / 2));
1192 top
= bottom
+ (font
->tm
.tmAscent
+
1193 font
->tm
.tmDescent
);
1196 if (bottom
< lowest
)
1198 y_offset
= bottom
+ font
->tm
.tmDescent
;
1199 x_offset
= (cmpcharp
->col_offset
[gidx
]
1200 * FONT_WIDTH (FRAME_FONT(f
)));
1203 if (print_via_unicode
)
1204 ExtTextOutW (hdc
, left
+ x_offset
,
1205 top
/*+ baseline - y_offset*/,
1206 fuOptions
, clip_region
,
1207 x_2byte_buffer
+ i
, 1, NULL
);
1208 else if (CHARSET_DIMENSION (charset
) > 1)
1210 /* Keep character together */
1211 int n
= CHARSET_DIMENSION (charset
) ;
1212 ExtTextOut (hdc
, left
+ x_offset
,
1213 top
/*+ baseline - y_offset*/,
1214 fuOptions
, clip_region
,
1215 x_1byte_buffer
+ i
, n
, NULL
);
1220 ExtTextOut (hdc
, left
+ x_offset
,
1221 top
/*+ baseline - y_offset*/,
1222 fuOptions
, clip_region
,
1223 x_1byte_buffer
+ i
, 1, NULL
);
1229 /* Show rectangles to indicate that we found no font. */
1230 int limit
= cmpcharp
? 1 : len
;
1232 for (i
= 0; i
< limit
; i
++)
1233 Rectangle (hdc
, left
+ glyph_width
* i
, top
,
1234 left
+ glyph_width
* (i
+ 1) - 1,
1235 top
+ line_height
- 1);
1237 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1239 /* Indicate that we found a font of inappropriate size. */
1240 int limit
= cmpcharp
? 1 : len
;
1242 for (i
= 0; i
< limit
; i
++)
1244 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1245 top
+ line_height
- 1, glyph_width
, 1);
1246 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1247 top
+ line_height
- 3, 1, 2);
1251 /* Setting underline position based on the metric of the
1252 current font results in shaky underline if it strides
1253 over different fonts. So, we set the position based only
1254 on the default font of this frame. */
1255 int underline_position
= 1;
1257 if (FRAME_FONT (f
)->tm
.tmDescent
<= underline_position
)
1258 underline_position
= FRAME_FONT (f
)->tm
.tmDescent
- 1;
1260 if (face
->underline
)
1261 w32_fill_area (f
, hdc
, fg
, left
,
1262 top
+ FONT_BASE (FRAME_FONT (f
))
1263 + underline_position
,
1271 release_frame_dc (f
, hdc
);
1273 return (left
- orig_left
);
1277 /* Output some text at the nominal frame cursor position.
1278 Advance the cursor over the text.
1279 Output LEN glyphs at START.
1281 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
1282 controls the pixel values used for foreground and background. */
1285 w32_write_glyphs (start
, len
)
1286 register GLYPH
*start
;
1289 register int temp_length
;
1299 /* If not within an update,
1300 output at the frame's visible cursor. */
1301 curs_x
= f
->cursor_x
;
1302 curs_y
= f
->cursor_y
;
1306 CHAR_TO_PIXEL_COL (f
, curs_x
),
1307 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1308 start
, len
, highlight
, 0, NULL
);
1310 /* If we drew on top of the cursor, note that it is turned off. */
1311 if (curs_y
== f
->phys_cursor_y
1312 && curs_x
<= f
->phys_cursor_x
1313 && curs_x
+ len
> f
->phys_cursor_x
)
1314 f
->phys_cursor_x
= -1;
1316 if (updating_frame
== 0)
1319 x_display_cursor (f
, 1);
1328 /* Clear to the end of the line.
1329 Erase the current text line from the nominal cursor position (inclusive)
1330 to column FIRST_UNUSED (exclusive). The idea is that everything
1331 from FIRST_UNUSED onward is already erased. */
1334 w32_clear_end_of_line (first_unused
)
1335 register int first_unused
;
1337 struct frame
*f
= updating_frame
;
1342 if (curs_y
< 0 || curs_y
>= f
->height
)
1344 if (first_unused
<= 0)
1347 if (first_unused
>= f
->width
)
1348 first_unused
= f
->width
;
1350 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1356 /* Notice if the cursor will be cleared by this operation. */
1357 if (curs_y
== f
->phys_cursor_y
1358 && curs_x
<= f
->phys_cursor_x
1359 && f
->phys_cursor_x
< first_unused
)
1360 f
->phys_cursor_x
= -1;
1362 w32_clear_area (f
, NULL
,
1363 CHAR_TO_PIXEL_COL (f
, curs_x
),
1364 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1365 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
1366 f
->output_data
.w32
->line_height
);
1374 struct frame
*f
= updating_frame
;
1379 f
->phys_cursor_x
= -1; /* Cursor not visible. */
1380 curs_x
= 0; /* Nominal cursor position is top left. */
1385 w32_clear_window (f
);
1387 /* We have to clear the scroll bars, too. If we have changed
1388 colors or something like that, then they should be notified. */
1389 x_scroll_bar_clear (f
);
1394 /* Make audible bell. */
1397 w32_ring_bell (void)
1404 HWND hwnd
= FRAME_W32_WINDOW (selected_frame
);
1406 for (i
= 0; i
< 5; i
++)
1408 FlashWindow (hwnd
, TRUE
);
1411 FlashWindow (hwnd
, FALSE
);
1414 w32_sys_ring_bell ();
1419 /* Insert and delete character.
1420 These are not supposed to be used because we are supposed to turn
1421 off the feature of using them. */
1424 w32_insert_glyphs (start
, len
)
1425 register GLYPH
*start
;
1432 w32_delete_glyphs (n
)
1438 /* Specify how many text lines, from the top of the window,
1439 should be affected by insert-lines and delete-lines operations.
1440 This, and those operations, are used only within an update
1441 that is bounded by calls to w32_update_begin and w32_update_end. */
1444 w32_set_terminal_window (n
)
1447 if (updating_frame
== 0)
1450 if ((n
<= 0) || (n
> updating_frame
->height
))
1451 flexlines
= updating_frame
->height
;
1456 /* These variables need not be per frame
1457 because redisplay is done on a frame-by-frame basis
1458 and the line dance for one frame is finished before
1459 anything is done for another frame. */
1461 /* Array of line numbers from cached insert/delete operations.
1462 line_dance[i] is the old position of the line that we want
1463 to move to line i, or -1 if we want a blank line there. */
1464 static int *line_dance
;
1466 /* Allocated length of that array. */
1467 static int line_dance_len
;
1469 /* Flag indicating whether we've done any work. */
1470 static int line_dance_in_progress
;
1472 /* Perform an insert-lines or delete-lines operation,
1473 inserting N lines or deleting -N lines at vertical position VPOS. */
1476 w32_ins_del_lines (vpos
, n
)
1479 register int fence
, i
;
1481 if (vpos
>= flexlines
)
1484 if (!line_dance_in_progress
)
1486 int ht
= updating_frame
->height
;
1487 if (ht
> line_dance_len
)
1489 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1490 line_dance_len
= ht
;
1492 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1493 line_dance_in_progress
= 1;
1497 if (n
> flexlines
- vpos
)
1498 n
= flexlines
- vpos
;
1500 for (i
= flexlines
; --i
>= fence
;)
1501 line_dance
[i
] = line_dance
[i
-n
];
1502 for (i
= fence
; --i
>= vpos
;)
1508 if (n
> flexlines
- vpos
)
1509 n
= flexlines
- vpos
;
1510 fence
= flexlines
- n
;
1511 for (i
= vpos
; i
< fence
; ++i
)
1512 line_dance
[i
] = line_dance
[i
+ n
];
1513 for (i
= fence
; i
< flexlines
; ++i
)
1518 /* Here's where we actually move the pixels around.
1519 Must be called with input blocked. */
1523 register int i
, j
, distance
;
1524 register struct frame
*f
;
1529 /* Must check this flag first. If it's not set, then not only is the
1530 array uninitialized, but we might not even have a frame. */
1531 if (!line_dance_in_progress
)
1539 intborder
= f
->output_data
.w32
->internal_border_width
;
1541 x_display_cursor (updating_frame
, 0);
1543 hdc
= get_frame_dc (f
);
1545 for (i
= 0; i
< ht
; ++i
)
1546 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1548 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1549 && line_dance
[j
]-j
== distance
); ++j
);
1550 /* Copy [i,j) upward from [i+distance, j+distance) */
1552 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1553 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1554 (j
-i
) * f
->output_data
.w32
->line_height
,
1556 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1561 for (i
= ht
; --i
>=0; )
1562 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1564 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1565 && line_dance
[j
]-j
== distance
););
1566 /* Copy (j, i] downward from (j+distance, i+distance] */
1568 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1569 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1570 (i
-j
) * f
->output_data
.w32
->line_height
,
1572 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1577 for (i
= 0; i
< ht
; ++i
)
1578 if (line_dance
[i
] == -1)
1580 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1582 w32_clear_area (f
, hdc
,
1584 CHAR_TO_PIXEL_ROW (f
, i
),
1585 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1586 (j
-i
) * f
->output_data
.w32
->line_height
);
1589 line_dance_in_progress
= 0;
1591 release_frame_dc (f
, hdc
);
1594 /* Support routines for exposure events. */
1595 static void clear_cursor ();
1597 /* Output into a rectangle of a window (for frame F)
1598 the characters in f->phys_lines that overlap that rectangle.
1599 TOP and LEFT are the position of the upper left corner of the rectangle.
1600 ROWS and COLS are the size of the rectangle.
1601 Call this function with input blocked. */
1604 dumprectangle (f
, left
, top
, cols
, rows
)
1606 register int left
, top
, cols
, rows
;
1608 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1609 int cursor_cleared
= 0;
1613 if (FRAME_GARBAGED_P (f
))
1616 /* Express rectangle as four edges, instead of position-and-size. */
1617 bottom
= top
+ rows
;
1618 right
= left
+ cols
;
1620 /* Convert rectangle edges in pixels to edges in chars.
1621 Round down for left and top, up for right and bottom. */
1622 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1623 left
= PIXEL_TO_CHAR_COL (f
, left
);
1624 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1625 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1626 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1627 right
= PIXEL_TO_CHAR_COL (f
, right
);
1629 /* Clip the rectangle to what can be visible. */
1634 if (right
> f
->width
)
1636 if (bottom
> f
->height
)
1639 /* Get size in chars of the rectangle. */
1640 cols
= right
- left
;
1641 rows
= bottom
- top
;
1643 /* If rectangle has zero area, return. */
1644 if (rows
<= 0) return;
1645 if (cols
<= 0) return;
1647 /* Turn off the cursor if it is in the rectangle.
1648 We will turn it back on afterward. */
1649 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1650 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1656 /* Display the text in the rectangle, one text line at a time. */
1658 for (y
= top
; y
< bottom
; y
++)
1660 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1662 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1666 CHAR_TO_PIXEL_COL (f
, left
),
1667 CHAR_TO_PIXEL_ROW (f
, y
),
1668 line
, min (cols
, active_frame
->used
[y
] - left
),
1669 active_frame
->highlight
[y
], 0, NULL
);
1672 /* Turn the cursor on if we turned it off. */
1675 x_display_cursor (f
, 1);
1682 x_display_cursor (f
, 1);
1686 frame_unhighlight (f
)
1689 x_display_cursor (f
, 1);
1692 static void x_frame_rehighlight ();
1694 /* The focus has changed. Update the frames as necessary to reflect
1695 the new situation. Note that we can't change the selected frame
1696 here, because the Lisp code we are interrupting might become confused.
1697 Each event gets marked with the frame in which it occurred, so the
1698 Lisp code can tell when the switch took place by examining the events. */
1701 x_new_focus_frame (dpyinfo
, frame
)
1702 struct w32_display_info
*dpyinfo
;
1703 struct frame
*frame
;
1705 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1706 int events_enqueued
= 0;
1708 if (frame
!= dpyinfo
->w32_focus_frame
)
1710 /* Set this before calling other routines, so that they see
1711 the correct value of w32_focus_frame. */
1712 dpyinfo
->w32_focus_frame
= frame
;
1714 if (old_focus
&& old_focus
->auto_lower
)
1715 x_lower_frame (old_focus
);
1717 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1718 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1720 pending_autoraise_frame
= 0;
1723 x_frame_rehighlight (dpyinfo
);
1726 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1729 x_mouse_leave (dpyinfo
)
1730 struct w32_display_info
*dpyinfo
;
1732 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1735 /* The focus has changed, or we have redirected a frame's focus to
1736 another frame (this happens when a frame uses a surrogate
1737 minibuffer frame). Shift the highlight as appropriate.
1739 The FRAME argument doesn't necessarily have anything to do with which
1740 frame is being highlighted or unhighlighted; we only use it to find
1741 the appropriate display info. */
1743 w32_frame_rehighlight (frame
)
1744 struct frame
*frame
;
1746 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1750 x_frame_rehighlight (dpyinfo
)
1751 struct w32_display_info
*dpyinfo
;
1753 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1755 if (dpyinfo
->w32_focus_frame
)
1757 dpyinfo
->w32_highlight_frame
1758 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1759 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1760 : dpyinfo
->w32_focus_frame
);
1761 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1763 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1764 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1768 dpyinfo
->w32_highlight_frame
= 0;
1770 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1773 frame_unhighlight (old_highlight
);
1774 if (dpyinfo
->w32_highlight_frame
)
1775 frame_highlight (dpyinfo
->w32_highlight_frame
);
1779 /* Keyboard processing - modifier keys, etc. */
1781 /* Convert a keysym to its name. */
1784 x_get_keysym_name (keysym
)
1787 /* Make static so we can always return it */
1788 static char value
[100];
1791 GetKeyNameText(keysym
, value
, 100);
1797 /* Mouse clicks and mouse movement. Rah. */
1799 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1800 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1801 that the glyph at X, Y occupies, if BOUNDS != 0.
1802 If NOCLIP is nonzero, do not force the value into range. */
1805 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1807 register int pix_x
, pix_y
;
1808 register int *x
, *y
;
1812 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1813 if (NILP (Vwindow_system
))
1820 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1821 even for negative values. */
1823 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1825 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1827 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1828 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1832 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1833 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1834 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1835 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1842 else if (pix_x
> f
->width
)
1847 else if (pix_y
> f
->height
)
1856 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1859 register int *pix_x
, *pix_y
;
1861 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1862 if (NILP (Vwindow_system
))
1869 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1870 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1874 parse_button (message
, pbutton
, pup
)
1884 case WM_LBUTTONDOWN
:
1892 case WM_MBUTTONDOWN
:
1893 if (NILP (Vw32_swap_mouse_buttons
))
1900 if (NILP (Vw32_swap_mouse_buttons
))
1906 case WM_RBUTTONDOWN
:
1907 if (NILP (Vw32_swap_mouse_buttons
))
1914 if (NILP (Vw32_swap_mouse_buttons
))
1925 if (pbutton
) *pbutton
= button
;
1931 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1933 If the event is a button press, then note that we have grabbed
1937 construct_mouse_click (result
, msg
, f
)
1938 struct input_event
*result
;
1945 parse_button (msg
->msg
.message
, &button
, &up
);
1947 /* Make the event type no_event; we'll change that when we decide
1949 result
->kind
= mouse_click
;
1950 result
->code
= button
;
1951 result
->timestamp
= msg
->msg
.time
;
1952 result
->modifiers
= (msg
->dwModifiers
1960 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1961 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1962 XSETFRAME (result
->frame_or_window
, f
);
1967 construct_mouse_wheel (result
, msg
, f
)
1968 struct input_event
*result
;
1973 result
->kind
= mouse_wheel
;
1974 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1975 result
->timestamp
= msg
->msg
.time
;
1976 result
->modifiers
= msg
->dwModifiers
;
1977 p
.x
= LOWORD (msg
->msg
.lParam
);
1978 p
.y
= HIWORD (msg
->msg
.lParam
);
1979 ScreenToClient(msg
->msg
.hwnd
, &p
);
1980 XSETINT (result
->x
, p
.x
);
1981 XSETINT (result
->y
, p
.y
);
1982 XSETFRAME (result
->frame_or_window
, f
);
1986 construct_drag_n_drop (result
, msg
, f
)
1987 struct input_event
*result
;
1999 result
->kind
= drag_n_drop
;
2001 result
->timestamp
= msg
->msg
.time
;
2002 result
->modifiers
= msg
->dwModifiers
;
2004 p
.x
= LOWORD (msg
->msg
.lParam
);
2005 p
.y
= HIWORD (msg
->msg
.lParam
);
2006 ScreenToClient (msg
->msg
.hwnd
, &p
);
2007 XSETINT (result
->x
, p
.x
);
2008 XSETINT (result
->y
, p
.y
);
2010 hdrop
= (HDROP
) msg
->msg
.wParam
;
2011 DragQueryPoint (hdrop
, &p
);
2012 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
2015 for (i
= 0; i
< num_files
; i
++)
2017 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
2020 name
= alloca (len
+ 1);
2021 DragQueryFile (hdrop
, i
, name
, len
+ 1);
2022 files
= Fcons (build_string (name
), files
);
2027 XSETFRAME (frame
, f
);
2028 result
->frame_or_window
= Fcons (frame
, files
);
2032 /* Function to report a mouse movement to the mainstream Emacs code.
2033 The input handler calls this.
2035 We have received a mouse movement event, which is given in *event.
2036 If the mouse is over a different glyph than it was last time, tell
2037 the mainstream emacs code by setting mouse_moved. If not, ask for
2038 another motion event, so we can check again the next time it moves. */
2041 note_mouse_movement (frame
, msg
)
2045 last_mouse_movement_time
= msg
->time
;
2047 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
2049 frame
->mouse_moved
= 1;
2050 last_mouse_scroll_bar
= Qnil
;
2052 note_mouse_highlight (frame
, -1, -1);
2055 /* Has the mouse moved off the glyph it was on at the last sighting? */
2056 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
2057 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
2058 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
2059 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
2061 frame
->mouse_moved
= 1;
2062 last_mouse_scroll_bar
= Qnil
;
2064 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
2068 /* This is used for debugging, to turn off note_mouse_highlight. */
2069 static int disable_mouse_highlight
;
2071 /* Take proper action when the mouse has moved to position X, Y on frame F
2072 as regards highlighting characters that have mouse-face properties.
2073 Also dehighlighting chars where the mouse was before.
2074 X and Y can be negative or out of range. */
2077 note_mouse_highlight (f
, x
, y
)
2081 int row
, column
, portion
;
2086 if (disable_mouse_highlight
)
2089 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2090 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2091 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2093 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
2098 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2102 /* Find out which glyph the mouse is on. */
2103 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2104 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
2106 /* Which window is that in? */
2107 window
= window_from_coordinates (f
, column
, row
, &portion
);
2108 w
= XWINDOW (window
);
2110 /* If we were displaying active text in another window, clear that. */
2111 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
2112 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2114 /* Are we in a window whose display is up to date?
2115 And verify the buffer's text has not changed. */
2116 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2117 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2118 && EQ (w
->window_end_valid
, w
->buffer
)
2119 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2120 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2122 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2125 /* Find which buffer position the mouse corresponds to. */
2126 for (i
= column
; i
>= 0; i
--)
2130 /* Is it outside the displayed active region (if any)? */
2132 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2133 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
2134 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2135 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2136 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2137 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2138 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2139 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2140 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2142 Lisp_Object mouse_face
, overlay
, position
;
2143 Lisp_Object
*overlay_vec
;
2144 int len
, noverlays
, ignor1
;
2145 struct buffer
*obuf
;
2148 /* If we get an out-of-range value, return now; avoid an error. */
2149 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2152 /* Make the window's buffer temporarily current for
2153 overlays_at and compute_char_face. */
2154 obuf
= current_buffer
;
2155 current_buffer
= XBUFFER (w
->buffer
);
2161 /* Yes. Clear the display of the old active region, if any. */
2162 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2164 /* Is this char mouse-active? */
2165 XSETINT (position
, pos
);
2168 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2170 /* Put all the overlays we want in a vector in overlay_vec.
2171 Store the length in len. */
2172 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2174 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2176 /* Find the highest priority overlay that has a mouse-face prop. */
2178 for (i
= 0; i
< noverlays
; i
++)
2180 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2181 if (!NILP (mouse_face
))
2183 overlay
= overlay_vec
[i
];
2188 /* If no overlay applies, get a text property. */
2190 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2192 /* Handle the overlay case. */
2193 if (! NILP (overlay
))
2195 /* Find the range of text around this char that
2196 should be active. */
2197 Lisp_Object before
, after
;
2200 before
= Foverlay_start (overlay
);
2201 after
= Foverlay_end (overlay
);
2202 /* Record this as the current active region. */
2203 fast_find_position (window
, before
,
2204 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2205 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2206 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2207 = !fast_find_position (window
, after
,
2208 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2209 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2210 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2211 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2212 = compute_char_face (f
, w
, pos
, 0, 0,
2213 &ignore
, pos
+ 1, 1);
2215 /* Display it as active. */
2216 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2218 /* Handle the text property case. */
2219 else if (! NILP (mouse_face
))
2221 /* Find the range of text around this char that
2222 should be active. */
2223 Lisp_Object before
, after
, beginning
, end
;
2226 beginning
= Fmarker_position (w
->start
);
2227 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2228 - XFASTINT (w
->window_end_pos
)));
2230 = Fprevious_single_property_change (make_number (pos
+ 1),
2232 w
->buffer
, beginning
);
2234 = Fnext_single_property_change (position
, Qmouse_face
,
2236 /* Record this as the current active region. */
2237 fast_find_position (window
, before
,
2238 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2239 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2240 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2241 = !fast_find_position (window
, after
,
2242 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2243 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2244 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2245 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2246 = compute_char_face (f
, w
, pos
, 0, 0,
2247 &ignore
, pos
+ 1, 1);
2249 /* Display it as active. */
2250 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2254 current_buffer
= obuf
;
2259 /* Find the row and column of position POS in window WINDOW.
2260 Store them in *COLUMNP and *ROWP.
2261 This assumes display in WINDOW is up to date.
2262 If POS is above start of WINDOW, return coords
2263 of start of first screen line.
2264 If POS is after end of WINDOW, return coords of end of last screen line.
2266 Value is 1 if POS is in range, 0 if it was off screen. */
2269 fast_find_position (window
, pos
, columnp
, rowp
)
2272 int *columnp
, *rowp
;
2274 struct window
*w
= XWINDOW (window
);
2275 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2278 int left
= WINDOW_LEFT_MARGIN (w
);
2280 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2281 int width
= window_internal_width (w
);
2284 int maybe_next_line
= 0;
2286 /* Find the right row. */
2291 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2292 if (linestart
> pos
)
2294 /* If the position sought is the end of the buffer,
2295 don't include the blank lines at the bottom of the window. */
2296 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2298 maybe_next_line
= 1;
2305 /* Find the right column with in it. */
2306 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2308 for (i
= 0; i
< width
; i
++)
2310 if (charstarts
[left
+ i
] == pos
)
2313 *columnp
= i
+ left
;
2316 else if (charstarts
[left
+ i
] > pos
)
2318 else if (charstarts
[left
+ i
] > 0)
2322 /* If we're looking for the end of the buffer,
2323 and we didn't find it in the line we scanned,
2324 use the start of the following line. */
2325 if (maybe_next_line
)
2336 /* Display the active region described by mouse_face_*
2337 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2340 show_mouse_face (dpyinfo
, hl
)
2341 struct w32_display_info
*dpyinfo
;
2344 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2345 int width
= window_internal_width (w
);
2346 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2349 int old_curs_x
= curs_x
;
2350 int old_curs_y
= curs_y
;
2352 /* Set these variables temporarily
2353 so that if we have to turn the cursor off and on again
2354 we will put it back at the same place. */
2355 curs_x
= f
->phys_cursor_x
;
2356 curs_y
= f
->phys_cursor_y
;
2358 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2359 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2361 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2362 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
2363 : WINDOW_LEFT_MARGIN (w
));
2364 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2365 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2366 : WINDOW_LEFT_MARGIN (w
) + width
);
2367 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2369 /* If the cursor's in the text we are about to rewrite,
2370 turn the cursor off. */
2372 && curs_x
>= column
- 1
2373 && curs_x
<= endcolumn
)
2375 x_display_cursor (f
, 0);
2380 CHAR_TO_PIXEL_COL (f
, column
),
2381 CHAR_TO_PIXEL_ROW (f
, i
),
2382 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2384 /* Highlight with mouse face if hl > 0. */
2385 hl
> 0 ? 3 : 0, 0, NULL
);
2388 /* If we turned the cursor off, turn it back on. */
2390 x_display_cursor (f
, 1);
2392 curs_x
= old_curs_x
;
2393 curs_y
= old_curs_y
;
2395 /* Change the mouse cursor according to the value of HL. */
2397 SetCursor (f
->output_data
.w32
->cross_cursor
);
2399 SetCursor (f
->output_data
.w32
->text_cursor
);
2402 /* Clear out the mouse-highlighted active region.
2403 Redraw it unhighlighted first. */
2406 clear_mouse_face (dpyinfo
)
2407 struct w32_display_info
*dpyinfo
;
2409 if (! NILP (dpyinfo
->mouse_face_window
))
2410 show_mouse_face (dpyinfo
, 0);
2412 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2413 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2414 dpyinfo
->mouse_face_window
= Qnil
;
2417 struct scroll_bar
*x_window_to_scroll_bar ();
2418 static void x_scroll_bar_report_motion ();
2420 /* Return the current position of the mouse.
2421 *fp should be a frame which indicates which display to ask about.
2423 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2424 and *part to the frame, window, and scroll bar part that the mouse
2425 is over. Set *x and *y to the portion and whole of the mouse's
2426 position on the scroll bar.
2428 If the mouse movement started elsewhere, set *fp to the frame the
2429 mouse is on, *bar_window to nil, and *x and *y to the character cell
2432 Set *time to the server timestamp for the time at which the mouse
2433 was at this position.
2435 Don't store anything if we don't have a valid set of values to report.
2437 This clears the mouse_moved flag, so we can wait for the next mouse
2438 movement. This also calls XQueryPointer, which will cause the
2439 server to give us another MotionNotify when the mouse moves
2443 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2446 Lisp_Object
*bar_window
;
2447 enum scroll_bar_part
*part
;
2449 unsigned long *time
;
2455 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2456 /* This is never called at the moment. */
2457 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2462 Lisp_Object frame
, tail
;
2464 /* Clear the mouse-moved flag for every frame on this display. */
2465 FOR_EACH_FRAME (tail
, frame
)
2466 XFRAME (frame
)->mouse_moved
= 0;
2468 last_mouse_scroll_bar
= Qnil
;
2472 /* Now we have a position on the root; find the innermost window
2473 containing the pointer. */
2475 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2476 && FRAME_LIVE_P (last_mouse_frame
))
2478 f1
= last_mouse_frame
;
2482 /* Is win one of our frames? */
2483 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
2486 /* If not, is it one of our scroll bars? */
2489 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
2493 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2497 if (f1
== 0 && insist
> 0)
2498 f1
= selected_frame
;
2502 int ignore1
, ignore2
;
2504 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
2506 /* Ok, we found a frame. Store all the values. */
2508 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
2510 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
2518 *time
= last_mouse_movement_time
;
2526 /* Scroll bar support. */
2528 /* Given an window ID, find the struct scroll_bar which manages it.
2529 This can be called in GC, so we have to make sure to strip off mark
2532 x_window_to_scroll_bar (window_id
)
2535 Lisp_Object tail
, frame
;
2537 for (tail
= Vframe_list
;
2538 XGCTYPE (tail
) == Lisp_Cons
;
2539 tail
= XCONS (tail
)->cdr
)
2541 Lisp_Object frame
, bar
, condemned
;
2543 frame
= XCONS (tail
)->car
;
2544 /* All elements of Vframe_list should be frames. */
2545 if (! GC_FRAMEP (frame
))
2548 /* Scan this frame's scroll bar list for a scroll bar with the
2550 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2551 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2552 /* This trick allows us to search both the ordinary and
2553 condemned scroll bar lists with one loop. */
2554 ! GC_NILP (bar
) || (bar
= condemned
,
2557 bar
= XSCROLL_BAR (bar
)->next
)
2558 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2559 return XSCROLL_BAR (bar
);
2566 my_create_scrollbar (f
, bar
)
2568 struct scroll_bar
* bar
;
2570 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2571 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2575 //#define ATTACH_THREADS
2578 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2580 #ifndef ATTACH_THREADS
2581 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2582 (WPARAM
) hwnd
, (LPARAM
) how
);
2584 return ShowWindow (hwnd
, how
);
2589 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2590 int x
, int y
, int cx
, int cy
, UINT flags
)
2592 #ifndef ATTACH_THREADS
2594 pos
.hwndInsertAfter
= hwndAfter
;
2600 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2602 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2607 my_set_focus (f
, hwnd
)
2611 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2616 my_set_foreground_window (hwnd
)
2619 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2623 my_destroy_window (f
, hwnd
)
2627 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2631 /* Open a new window to serve as a scroll bar, and return the
2632 scroll bar vector for it. */
2633 static struct scroll_bar
*
2634 x_scroll_bar_create (window
, top
, left
, width
, height
)
2635 struct window
*window
;
2636 int top
, left
, width
, height
;
2638 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2639 struct scroll_bar
*bar
2640 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2645 XSETWINDOW (bar
->window
, window
);
2646 XSETINT (bar
->top
, top
);
2647 XSETINT (bar
->left
, left
);
2648 XSETINT (bar
->width
, width
);
2649 XSETINT (bar
->height
, height
);
2650 XSETINT (bar
->start
, 0);
2651 XSETINT (bar
->end
, 0);
2652 bar
->dragging
= Qnil
;
2654 /* Requires geometry to be set before call to create the real window */
2656 hwnd
= my_create_scrollbar (f
, bar
);
2658 if (pfnSetScrollInfo
)
2662 si
.cbSize
= sizeof (si
);
2665 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2666 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2670 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2674 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2675 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2678 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2680 /* Add bar to its frame's list of scroll bars. */
2681 bar
->next
= FRAME_SCROLL_BARS (f
);
2683 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2684 if (! NILP (bar
->next
))
2685 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2692 /* Draw BAR's handle in the proper position.
2693 If the handle is already drawn from START to END, don't bother
2694 redrawing it, unless REBUILD is non-zero; in that case, always
2695 redraw it. (REBUILD is handy for drawing the handle after expose
2698 Normally, we want to constrain the start and end of the handle to
2699 fit inside its rectangle, but if the user is dragging the scroll bar
2700 handle, we want to let them drag it down all the way, so that the
2701 bar's top is as far down as it goes; otherwise, there's no way to
2702 move to the very end of the buffer. */
2704 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2705 struct scroll_bar
*bar
;
2709 int dragging
= ! NILP (bar
->dragging
);
2710 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2711 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2713 /* If the display is already accurate, do nothing. */
2715 && start
== XINT (bar
->start
)
2716 && end
== XINT (bar
->end
))
2722 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2724 /* Make sure the values are reasonable, and try to preserve
2725 the distance between start and end. */
2727 int length
= end
- start
;
2731 else if (start
> top_range
)
2733 end
= start
+ length
;
2737 else if (end
> top_range
&& ! dragging
)
2742 /* Store the adjusted setting in the scroll bar. */
2743 XSETINT (bar
->start
, start
);
2744 XSETINT (bar
->end
, end
);
2746 /* If being dragged, let scroll bar update itself. */
2749 if (pfnSetScrollInfo
)
2753 si
.cbSize
= sizeof (si
);
2754 si
.fMask
= SIF_PAGE
| SIF_POS
;
2755 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2758 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2761 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2767 /* Move a scroll bar around on the screen, to accommodate changing
2768 window configurations. */
2770 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2771 struct scroll_bar
*bar
;
2772 int top
, left
, width
, height
;
2774 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2775 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2777 /* If already correctly positioned, do nothing. */
2778 if ( XINT (bar
->left
) == left
2779 && XINT (bar
->top
) == top
2780 && XINT (bar
->width
) == width
2781 && XINT (bar
->height
) == height
)
2783 /* Redraw after clear_frame. */
2784 if (!my_show_window (f
, w
, SW_NORMAL
))
2785 InvalidateRect (w
, NULL
, FALSE
);
2791 /* Make sure scroll bar is "visible" before moving, to ensure the
2792 area of the parent window now exposed will be refreshed. */
2793 my_show_window (f
, w
, SW_HIDE
);
2794 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2795 if (pfnSetScrollInfo
)
2799 si
.cbSize
= sizeof (si
);
2800 si
.fMask
= SIF_RANGE
;
2802 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2803 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2805 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2808 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2809 my_show_window (f
, w
, SW_NORMAL
);
2810 // InvalidateRect (w, NULL, FALSE);
2812 XSETINT (bar
->left
, left
);
2813 XSETINT (bar
->top
, top
);
2814 XSETINT (bar
->width
, width
);
2815 XSETINT (bar
->height
, height
);
2820 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2823 x_scroll_bar_remove (bar
)
2824 struct scroll_bar
*bar
;
2826 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2830 /* Destroy the window. */
2831 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2833 /* Disassociate this scroll bar from its window. */
2834 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2839 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2840 that we are displaying PORTION characters out of a total of WHOLE
2841 characters, starting at POSITION. If WINDOW has no scroll bar,
2844 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2845 struct window
*window
;
2846 int portion
, whole
, position
;
2848 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2849 int top
= XINT (window
->top
);
2850 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2851 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2853 /* Where should this scroll bar be, pixelwise? */
2854 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2855 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2857 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2858 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2859 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2860 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2862 struct scroll_bar
*bar
;
2864 /* Does the scroll bar exist yet? */
2865 if (NILP (window
->vertical_scroll_bar
))
2866 bar
= x_scroll_bar_create (window
,
2867 pixel_top
, pixel_left
,
2868 pixel_width
, pixel_height
);
2871 /* It may just need to be moved and resized. */
2872 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2873 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2876 /* Set the scroll bar's current state. */
2878 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2881 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2884 int start
= (int) (((double) position
* top_range
) / whole
);
2885 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2887 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2891 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2895 /* The following three hooks are used when we're doing a thorough
2896 redisplay of the frame. We don't explicitly know which scroll bars
2897 are going to be deleted, because keeping track of when windows go
2898 away is a real pain - "Can you say set-window-configuration, boys
2899 and girls?" Instead, we just assert at the beginning of redisplay
2900 that *all* scroll bars are to be removed, and then save a scroll bar
2901 from the fiery pit when we actually redisplay its window. */
2903 /* Arrange for all scroll bars on FRAME to be removed at the next call
2904 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2905 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2907 w32_condemn_scroll_bars (frame
)
2910 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2911 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2914 bar
= FRAME_SCROLL_BARS (frame
);
2915 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2916 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2917 XSCROLL_BAR (bar
)->prev
= Qnil
;
2918 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2919 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2920 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2923 /* The condemned list should be empty at this point; if it's not,
2924 then the rest of Emacs isn't using the condemn/redeem/judge
2925 protocol correctly. */
2926 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2929 /* Move them all to the "condemned" list. */
2930 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2931 FRAME_SCROLL_BARS (frame
) = Qnil
;
2935 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2936 Note that WINDOW isn't necessarily condemned at all. */
2938 w32_redeem_scroll_bar (window
)
2939 struct window
*window
;
2941 struct scroll_bar
*bar
;
2943 /* We can't redeem this window's scroll bar if it doesn't have one. */
2944 if (NILP (window
->vertical_scroll_bar
))
2947 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2949 /* Unlink it from the condemned list. */
2951 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2953 if (NILP (bar
->prev
))
2955 /* If the prev pointer is nil, it must be the first in one of
2957 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2958 /* It's not condemned. Everything's fine. */
2960 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2961 window
->vertical_scroll_bar
))
2962 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2964 /* If its prev pointer is nil, it must be at the front of
2965 one or the other! */
2969 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2971 if (! NILP (bar
->next
))
2972 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2974 bar
->next
= FRAME_SCROLL_BARS (f
);
2976 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2977 if (! NILP (bar
->next
))
2978 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2981 struct scroll_bar
*bar
;
2983 /* We can't redeem this window's scroll bar if it doesn't have one. */
2984 if (NILP (window
->vertical_scroll_bar
))
2987 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2989 /* Unlink it from the condemned list. */
2991 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2993 if (NILP (bar
->prev
))
2995 /* If the prev pointer is nil, it must be the first in one of
2997 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2998 /* It's not condemned. Everything's fine. */
3000 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3001 window
->vertical_scroll_bar
))
3002 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3004 /* If its prev pointer is nil, it must be at the front of
3005 one or the other! */
3009 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3011 if (! NILP (bar
->next
))
3012 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3014 bar
->next
= FRAME_SCROLL_BARS (f
);
3016 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3017 if (! NILP (bar
->next
))
3018 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3023 /* Remove all scroll bars on FRAME that haven't been saved since the
3024 last call to `*condemn_scroll_bars_hook'. */
3026 w32_judge_scroll_bars (f
)
3029 Lisp_Object bar
, next
;
3031 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3033 /* Clear out the condemned list now so we won't try to process any
3034 more events on the hapless scroll bars. */
3035 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3037 for (; ! NILP (bar
); bar
= next
)
3039 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3041 x_scroll_bar_remove (b
);
3044 b
->next
= b
->prev
= Qnil
;
3047 /* Now there should be no references to the condemned scroll bars,
3048 and they should get garbage-collected. */
3050 Lisp_Object bar
, next
;
3052 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3054 /* Clear out the condemned list now so we won't try to process any
3055 more events on the hapless scroll bars. */
3056 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3058 for (; ! NILP (bar
); bar
= next
)
3060 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3062 x_scroll_bar_remove (b
);
3065 b
->next
= b
->prev
= Qnil
;
3068 /* Now there should be no references to the condemned scroll bars,
3069 and they should get garbage-collected. */
3073 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3074 is set to something other than no_event, it is enqueued.
3076 This may be called from a signal handler, so we have to ignore GC
3080 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3081 struct scroll_bar
*bar
;
3083 struct input_event
*emacs_event
;
3085 if (! GC_WINDOWP (bar
->window
))
3088 emacs_event
->kind
= w32_scroll_bar_click
;
3089 emacs_event
->code
= 0;
3090 /* not really meaningful to distinguish up/down */
3091 emacs_event
->modifiers
= msg
->dwModifiers
;
3092 emacs_event
->frame_or_window
= bar
->window
;
3093 emacs_event
->timestamp
= msg
->msg
.time
;
3096 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3098 int dragging
= !NILP (bar
->dragging
);
3100 if (pfnGetScrollInfo
)
3104 si
.cbSize
= sizeof (si
);
3107 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3111 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
3113 bar
->dragging
= Qnil
;
3115 switch (LOWORD (msg
->msg
.wParam
))
3118 emacs_event
->part
= scroll_bar_down_arrow
;
3121 emacs_event
->part
= scroll_bar_up_arrow
;
3124 emacs_event
->part
= scroll_bar_above_handle
;
3127 emacs_event
->part
= scroll_bar_below_handle
;
3130 emacs_event
->part
= scroll_bar_handle
;
3134 emacs_event
->part
= scroll_bar_handle
;
3138 case SB_THUMBPOSITION
:
3139 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3140 y
= HIWORD (msg
->msg
.wParam
);
3142 emacs_event
->part
= scroll_bar_handle
;
3144 /* "Silently" update current position. */
3145 if (pfnSetScrollInfo
)
3149 si
.cbSize
= sizeof (si
);
3153 /* Shrink handle if necessary to allow full range for position. */
3155 int start
= XINT (bar
->start
);
3156 int end
= XINT (bar
->end
);
3157 int len
= end
- start
;
3159 /* If new end is nearly hitting bottom, we must shrink
3160 handle. How much we shrink it depends on the relative
3161 sizes of len and top_range. */
3162 if (y
+ len
> top_range
- 2)
3164 len
-= min (top_range
/ 10, (len
/ 3) + 2);
3168 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3169 si
.fMask
|= SIF_PAGE
;
3173 /* Remember apparent position (we actually lag behind the real
3174 position, so don't set that directly. */
3175 last_scroll_bar_drag_pos
= y
;
3177 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3180 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
3183 /* If this is the end of a drag sequence, then reset the scroll
3184 handle size to normal and do a final redraw. Otherwise do
3188 if (pfnSetScrollInfo
)
3191 int start
= XINT (bar
->start
);
3192 int end
= XINT (bar
->end
);
3194 si
.cbSize
= sizeof (si
);
3195 si
.fMask
= SIF_PAGE
| SIF_POS
;
3196 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3197 si
.nPos
= last_scroll_bar_drag_pos
;
3199 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3202 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
3206 emacs_event
->kind
= no_event
;
3210 XSETINT (emacs_event
->x
, y
);
3211 XSETINT (emacs_event
->y
, top_range
);
3217 /* Return information to the user about the current position of the mouse
3218 on the scroll bar. */
3220 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3222 Lisp_Object
*bar_window
;
3223 enum scroll_bar_part
*part
;
3225 unsigned long *time
;
3227 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3228 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3229 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3231 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3236 *bar_window
= bar
->window
;
3238 if (pfnGetScrollInfo
)
3242 si
.cbSize
= sizeof (si
);
3243 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3245 pfnGetScrollInfo (w
, SB_CTL
, &si
);
3247 top_range
= si
.nMax
- si
.nPage
+ 1;
3250 pos
= GetScrollPos (w
, SB_CTL
);
3252 switch (LOWORD (last_mouse_scroll_bar_pos
))
3254 case SB_THUMBPOSITION
:
3256 *part
= scroll_bar_handle
;
3257 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3258 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3261 *part
= scroll_bar_handle
;
3265 *part
= scroll_bar_handle
;
3270 XSETINT(*y
, top_range
);
3273 last_mouse_scroll_bar
= Qnil
;
3275 *time
= last_mouse_movement_time
;
3280 /* The screen has been cleared so we may have changed foreground or
3281 background colors, and the scroll bars may need to be redrawn.
3282 Clear out the scroll bars, and ask for expose events, so we can
3285 x_scroll_bar_clear (f
)
3290 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3291 bar
= XSCROLL_BAR (bar
)->next
)
3293 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3294 HDC hdc
= GetDC (window
);
3297 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3298 arranges to refresh the scroll bar if hidden. */
3299 my_show_window (f
, window
, SW_HIDE
);
3301 GetClientRect (window
, &rect
);
3302 select_palette (f
, hdc
);
3303 w32_clear_rect (f
, hdc
, &rect
);
3304 deselect_palette (f
, hdc
);
3306 ReleaseDC (window
, hdc
);
3310 show_scroll_bars (f
, how
)
3316 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3317 bar
= XSCROLL_BAR (bar
)->next
)
3319 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3320 my_show_window (f
, window
, how
);
3325 /* The main W32 event-reading loop - w32_read_socket. */
3327 /* Timestamp of enter window event. This is only used by w32_read_socket,
3328 but we have to put it out here, since static variables within functions
3329 sometimes don't work. */
3330 static Time enter_timestamp
;
3332 /* Record the last 100 characters stored
3333 to help debug the loss-of-chars-during-GC problem. */
3335 short temp_buffer
[100];
3337 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*, int *isdead
);
3339 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
3340 we can use the same routines to handle input in both console
3341 and window modes. */
3344 convert_to_key_event (W32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
3346 eventp
->bKeyDown
= TRUE
;
3347 eventp
->wRepeatCount
= 1;
3348 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
3349 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
3350 eventp
->uChar
.AsciiChar
= 0;
3351 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
3354 /* Return nonzero if the virtual key is a dead key. */
3357 is_dead_key (int wparam
)
3359 unsigned int code
= MapVirtualKey (wparam
, 2);
3361 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
3362 if ((code
& 0x8000) || (code
& 0x80000000))
3368 /* Read events coming from the W32 shell.
3369 This routine is called by the SIGIO handler.
3370 We return as soon as there are no more events to be read.
3372 Events representing keys are stored in buffer BUFP,
3373 which can hold up to NUMCHARS characters.
3374 We return the number of characters stored into the buffer,
3375 thus pretending to be `read'.
3377 EXPECTED is nonzero if the caller knows input is available.
3379 Some of these messages are reposted back to the message queue since the
3380 system calls the windows proc directly in a context where we cannot return
3381 the data nor can we guarantee the state we are in. So if we dispatch them
3382 we will get into an infinite loop. To prevent this from ever happening we
3383 will set a variable to indicate we are in the read_socket call and indicate
3384 which message we are processing since the windows proc gets called
3385 recursively with different messages by the system.
3389 w32_read_socket (sd
, bufp
, numchars
, expected
)
3391 register struct input_event
*bufp
;
3392 register int numchars
;
3396 int check_visibility
= 0;
3400 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3402 if (interrupt_input_blocked
)
3404 interrupt_input_pending
= 1;
3408 interrupt_input_pending
= 0;
3411 /* So people can tell when we have read the available input. */
3412 input_signal_count
++;
3415 abort (); /* Don't think this happens. */
3417 while (get_next_msg (&msg
, FALSE
))
3419 switch (msg
.msg
.message
)
3422 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3426 if (msg
.rect
.right
== msg
.rect
.left
||
3427 msg
.rect
.bottom
== msg
.rect
.top
)
3429 /* We may get paint messages even though the client
3430 area is clipped - these are not expose events. */
3431 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3432 XSTRING (f
->name
)->data
));
3434 else if (f
->async_visible
!= 1)
3436 /* Definitely not obscured, so mark as visible. */
3437 f
->async_visible
= 1;
3438 f
->async_iconified
= 0;
3439 SET_FRAME_GARBAGED (f
);
3440 DebPrint (("frame %04x (%s) reexposed\n", f
,
3441 XSTRING (f
->name
)->data
));
3443 /* WM_PAINT serves as MapNotify as well, so report
3444 visibility changes properly. */
3447 bufp
->kind
= deiconify_event
;
3448 XSETFRAME (bufp
->frame_or_window
, f
);
3453 else if (! NILP(Vframe_list
)
3454 && ! NILP (XCONS (Vframe_list
)->cdr
))
3455 /* Force a redisplay sooner or later to update the
3456 frame titles in case this is the second frame. */
3457 record_asynch_buffer_change ();
3461 /* Erase background again for safety. */
3462 w32_clear_rect (f
, NULL
, &msg
.rect
);
3466 msg
.rect
.right
- msg
.rect
.left
,
3467 msg
.rect
.bottom
- msg
.rect
.top
);
3474 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3476 if (f
&& !f
->iconified
)
3478 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3480 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3481 bufp
->kind
= non_ascii_keystroke
;
3482 bufp
->code
= msg
.msg
.wParam
;
3483 bufp
->modifiers
= w32_kbd_mods_to_emacs (msg
.dwModifiers
,
3485 XSETFRAME (bufp
->frame_or_window
, f
);
3486 bufp
->timestamp
= msg
.msg
.time
;
3495 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3497 if (f
&& !f
->iconified
)
3503 KEY_EVENT_RECORD key
, *keyp
= &key
;
3505 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3508 convert_to_key_event (&msg
, keyp
);
3509 add
= key_event (keyp
, bufp
, &isdead
);
3510 XSETFRAME (bufp
->frame_or_window
, f
);
3513 /* The key pressed generated two characters, most likely
3514 an accent character and a key that could not be
3515 combined with it. Prepend the message on the queue
3516 again to process the second character (which is
3517 being held internally in key_event), and process
3518 the first character now. */
3538 if (dpyinfo
->grabbed
&& last_mouse_frame
3539 && FRAME_LIVE_P (last_mouse_frame
))
3540 f
= last_mouse_frame
;
3542 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3545 note_mouse_movement (f
, &msg
.msg
);
3547 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3551 case WM_LBUTTONDOWN
:
3553 case WM_MBUTTONDOWN
:
3555 case WM_RBUTTONDOWN
:
3561 if (dpyinfo
->grabbed
&& last_mouse_frame
3562 && FRAME_LIVE_P (last_mouse_frame
))
3563 f
= last_mouse_frame
;
3565 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3569 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3572 construct_mouse_click (bufp
, &msg
, f
);
3579 parse_button (msg
.msg
.message
, &button
, &up
);
3583 dpyinfo
->grabbed
&= ~ (1 << button
);
3587 dpyinfo
->grabbed
|= (1 << button
);
3588 last_mouse_frame
= f
;
3594 if (dpyinfo
->grabbed
&& last_mouse_frame
3595 && FRAME_LIVE_P (last_mouse_frame
))
3596 f
= last_mouse_frame
;
3598 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3602 if ((!dpyinfo
->w32_focus_frame
3603 || f
== dpyinfo
->w32_focus_frame
)
3606 construct_mouse_wheel (bufp
, &msg
, f
);
3615 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3619 construct_drag_n_drop (bufp
, &msg
, f
);
3628 struct scroll_bar
*bar
=
3629 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3631 if (bar
&& numchars
>= 1)
3633 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3643 case WM_WINDOWPOSCHANGED
:
3645 case WM_ACTIVATEAPP
:
3646 check_visibility
= 1;
3650 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3652 if (f
&& !f
->async_iconified
)
3656 x_real_positions (f
, &x
, &y
);
3657 f
->output_data
.w32
->left_pos
= x
;
3658 f
->output_data
.w32
->top_pos
= y
;
3661 check_visibility
= 1;
3665 /* If window has been obscured or exposed by another window
3666 being maximised or minimised/restored, then recheck
3667 visibility of all frames. Direct changes to our own
3668 windows get handled by WM_SIZE. */
3670 if (msg
.msg
.lParam
!= 0)
3671 check_visibility
= 1;
3674 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3675 f
->async_visible
= msg
.msg
.wParam
;
3679 check_visibility
= 1;
3683 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3685 /* Inform lisp of whether frame has been iconified etc. */
3688 switch (msg
.msg
.wParam
)
3690 case SIZE_MINIMIZED
:
3691 f
->async_visible
= 0;
3692 f
->async_iconified
= 1;
3694 bufp
->kind
= iconify_event
;
3695 XSETFRAME (bufp
->frame_or_window
, f
);
3701 case SIZE_MAXIMIZED
:
3703 f
->async_visible
= 1;
3704 f
->async_iconified
= 0;
3706 /* wait_reading_process_input will notice this and update
3707 the frame's display structures. */
3708 SET_FRAME_GARBAGED (f
);
3712 bufp
->kind
= deiconify_event
;
3713 XSETFRAME (bufp
->frame_or_window
, f
);
3719 /* Force a redisplay sooner or later
3720 to update the frame titles
3721 in case this is the second frame. */
3722 record_asynch_buffer_change ();
3727 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3735 GetClientRect(msg
.msg
.hwnd
, &rect
);
3737 height
= rect
.bottom
- rect
.top
;
3738 width
= rect
.right
- rect
.left
;
3740 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3741 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3743 /* TODO: Clip size to the screen dimensions. */
3745 /* Even if the number of character rows and columns has
3746 not changed, the font size may have changed, so we need
3747 to check the pixel dimensions as well. */
3749 if (columns
!= f
->width
3750 || rows
!= f
->height
3751 || width
!= f
->output_data
.w32
->pixel_width
3752 || height
!= f
->output_data
.w32
->pixel_height
)
3754 /* I had set this to 0, 0 - I am not sure why?? */
3756 change_frame_size (f
, rows
, columns
, 0, 1);
3757 SET_FRAME_GARBAGED (f
);
3759 f
->output_data
.w32
->pixel_width
= width
;
3760 f
->output_data
.w32
->pixel_height
= height
;
3761 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3765 check_visibility
= 1;
3770 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3772 if (msg
.msg
.message
== WM_SETFOCUS
)
3774 x_new_focus_frame (dpyinfo
, f
);
3776 else if (f
== dpyinfo
->w32_focus_frame
)
3778 x_new_focus_frame (dpyinfo
, 0);
3781 check_visibility
= 1;
3785 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3792 bufp
->kind
= delete_window_event
;
3793 XSETFRAME (bufp
->frame_or_window
, f
);
3801 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3808 bufp
->kind
= menu_bar_activate_event
;
3809 XSETFRAME (bufp
->frame_or_window
, f
);
3817 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3821 extern void menubar_selection_callback (FRAME_PTR f
, void * client_data
);
3822 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3825 check_visibility
= 1;
3828 case WM_DISPLAYCHANGE
:
3829 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3833 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3834 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3835 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3836 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3840 check_visibility
= 1;
3844 /* Check for messages registered at runtime. */
3845 if (msg
.msg
.message
== msh_mousewheel
)
3847 if (dpyinfo
->grabbed
&& last_mouse_frame
3848 && FRAME_LIVE_P (last_mouse_frame
))
3849 f
= last_mouse_frame
;
3851 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3855 if ((!dpyinfo
->w32_focus_frame
3856 || f
== dpyinfo
->w32_focus_frame
)
3859 construct_mouse_wheel (bufp
, &msg
, f
);
3870 /* If the focus was just given to an autoraising frame,
3872 /* ??? This ought to be able to handle more than one such frame. */
3873 if (pending_autoraise_frame
)
3875 x_raise_frame (pending_autoraise_frame
);
3876 pending_autoraise_frame
= 0;
3879 /* Check which frames are still visisble, if we have enqueued any user
3880 events or been notified of events that may affect visibility. We
3881 do this here because there doesn't seem to be any direct
3882 notification from Windows that the visibility of a window has
3883 changed (at least, not in all cases). */
3884 if (count
> 0 || check_visibility
)
3886 Lisp_Object tail
, frame
;
3888 FOR_EACH_FRAME (tail
, frame
)
3890 FRAME_PTR f
= XFRAME (frame
);
3891 /* Check "visible" frames and mark each as obscured or not.
3892 Note that async_visible is nonzero for unobscured and
3893 obscured frames, but zero for hidden and iconified frames. */
3894 if (FRAME_W32_P (f
) && f
->async_visible
)
3897 HDC hdc
= get_frame_dc (f
);
3898 GetClipBox (hdc
, &clipbox
);
3899 release_frame_dc (f
, hdc
);
3901 if (clipbox
.right
== clipbox
.left
3902 || clipbox
.bottom
== clipbox
.top
)
3904 /* Frame has become completely obscured so mark as
3905 such (we do this by setting async_visible to 2 so
3906 that FRAME_VISIBLE_P is still true, but redisplay
3908 f
->async_visible
= 2;
3910 if (!FRAME_OBSCURED_P (f
))
3912 DebPrint (("frame %04x (%s) obscured\n", f
,
3913 XSTRING (f
->name
)->data
));
3918 /* Frame is not obscured, so mark it as such. */
3919 f
->async_visible
= 1;
3921 if (FRAME_OBSCURED_P (f
))
3923 SET_FRAME_GARBAGED (f
);
3924 DebPrint (("frame %04x (%s) reexposed\n", f
,
3925 XSTRING (f
->name
)->data
));
3927 /* Force a redisplay sooner or later. */
3928 record_asynch_buffer_change ();
3939 /* Drawing the cursor. */
3942 /* Draw a hollow box cursor. Don't change the inside of the box. */
3952 hdc
= get_frame_dc (f
);
3954 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3956 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3957 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3958 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3959 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3961 FrameRect (hdc
, &rect
, hb
);
3964 release_frame_dc (f
, hdc
);
3967 /* Clear the cursor of frame F to background color,
3968 and mark the cursor as not shown.
3969 This is used when the text where the cursor is
3970 is about to be rewritten. */
3976 if (! FRAME_VISIBLE_P (f
)
3977 || f
->phys_cursor_x
< 0)
3980 x_display_cursor (f
, 0);
3981 f
->phys_cursor_x
= -1;
3984 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3985 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3989 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3996 CHAR_TO_PIXEL_COL (f
, column
),
3997 CHAR_TO_PIXEL_ROW (f
, row
),
3998 &glyph
, 1, highlight
, 0, NULL
);
4002 x_display_bar_cursor (f
, on
)
4006 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4008 /* This is pointless on invisible frames, and dangerous on garbaged
4009 frames; in the latter case, the frame may be in the midst of
4010 changing its size, and curs_x and curs_y may be off the frame. */
4011 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4014 if (! on
&& f
->phys_cursor_x
< 0)
4017 /* If there is anything wrong with the current cursor state, remove it. */
4018 if (f
->phys_cursor_x
>= 0
4020 || f
->phys_cursor_x
!= curs_x
4021 || f
->phys_cursor_y
!= curs_y
4022 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
4024 /* Erase the cursor by redrawing the character underneath it. */
4025 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4026 f
->phys_cursor_glyph
,
4027 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4028 f
->phys_cursor_x
= -1;
4031 /* If we now need a cursor in the new place or in the new form, do it so. */
4033 && (f
->phys_cursor_x
< 0
4034 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4036 f
->phys_cursor_glyph
4037 = ((current_glyphs
->enable
[curs_y
]
4038 && curs_x
< current_glyphs
->used
[curs_y
])
4039 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4041 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4042 CHAR_TO_PIXEL_COL (f
, curs_x
),
4043 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4044 max (f
->output_data
.w32
->cursor_width
, 1),
4045 f
->output_data
.w32
->line_height
);
4047 f
->phys_cursor_x
= curs_x
;
4048 f
->phys_cursor_y
= curs_y
;
4050 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4055 /* Turn the displayed cursor of frame F on or off according to ON.
4056 If ON is nonzero, where to put the cursor is specified
4057 by F->cursor_x and F->cursor_y. */
4060 x_display_box_cursor (f
, on
)
4064 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4066 /* This is pointless on invisible frames, and dangerous on garbaged
4067 frames; in the latter case, the frame may be in the midst of
4068 changing its size, and curs_x and curs_y may be off the frame. */
4069 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4072 /* If cursor is off and we want it off, return quickly. */
4073 if (!on
&& f
->phys_cursor_x
< 0)
4076 /* If cursor is currently being shown and we don't want it to be
4077 or it is in the wrong place,
4078 or we want a hollow box and it's not so, (pout!)
4080 if (f
->phys_cursor_x
>= 0
4082 || f
->phys_cursor_x
!= curs_x
4083 || f
->phys_cursor_y
!= curs_y
4084 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4085 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4087 int mouse_face_here
= 0;
4088 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4090 /* If the cursor is in the mouse face area, redisplay that when
4091 we clear the cursor. */
4092 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4093 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4094 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4095 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4096 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4097 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4098 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4099 /* Don't redraw the cursor's spot in mouse face
4100 if it is at the end of a line (on a newline).
4101 The cursor appears there, but mouse highlighting does not. */
4102 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4103 mouse_face_here
= 1;
4105 /* If the font is not as tall as a whole line,
4106 we must explicitly clear the line's whole height. */
4107 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4108 w32_clear_area (f
, NULL
,
4109 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4110 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4111 FONT_WIDTH (f
->output_data
.w32
->font
),
4112 f
->output_data
.w32
->line_height
);
4113 /* Erase the cursor by redrawing the character underneath it. */
4114 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4115 f
->phys_cursor_glyph
,
4118 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4119 f
->phys_cursor_x
= -1;
4122 /* If we want to show a cursor,
4123 or we want a box cursor and it's not so,
4124 write it in the right place. */
4126 && (f
->phys_cursor_x
< 0
4127 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4128 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4130 f
->phys_cursor_glyph
4131 = ((current_glyphs
->enable
[curs_y
]
4132 && curs_x
< current_glyphs
->used
[curs_y
])
4133 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4135 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4138 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4142 x_draw_single_glyph (f
, curs_y
, curs_x
,
4143 f
->phys_cursor_glyph
, 2);
4144 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4147 f
->phys_cursor_x
= curs_x
;
4148 f
->phys_cursor_y
= curs_y
;
4152 /* Display the cursor on frame F, or clear it, according to ON.
4153 Use the position specified by curs_x and curs_y
4154 if we are doing an update of frame F now.
4155 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4158 x_display_cursor (f
, on
)
4164 /* If we're not updating, then we want to use the current frame's
4165 cursor position, not our local idea of where the cursor ought to be. */
4166 if (f
!= updating_frame
)
4168 curs_x
= FRAME_CURSOR_X (f
);
4169 curs_y
= FRAME_CURSOR_Y (f
);
4172 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4173 x_display_box_cursor (f
, on
);
4174 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4175 x_display_bar_cursor (f
, on
);
4177 /* Those are the only two we have implemented! */
4183 /* Changing the font of the frame. */
4185 /* Give frame F the font named FONTNAME as its default font, and
4186 return the full name of that font. FONTNAME may be a wildcard
4187 pattern; in that case, we choose some font that fits the pattern.
4188 The return value shows which font we chose. */
4191 x_new_font (f
, fontname
)
4193 register char *fontname
;
4195 struct font_info
*fontp
4196 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4202 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4203 f
->output_data
.w32
->font_baseline
4204 = FRAME_FONT(f
)->tm
.tmAscent
+ fontp
->baseline_offset
;
4205 FRAME_FONTSET (f
) = -1;
4207 /* Compute the scroll bar width in character columns. */
4208 if (f
->scroll_bar_pixel_width
> 0)
4210 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4211 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4214 f
->scroll_bar_cols
= 2;
4216 /* Now make the frame display the given font. */
4217 if (FRAME_W32_WINDOW (f
) != 0)
4219 frame_update_line_height (f
);
4220 x_set_window_size (f
, 0, f
->width
, f
->height
);
4223 /* If we are setting a new frame's font for the first time,
4224 there are no faces yet, so this font's height is the line height. */
4225 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4228 Lisp_Object lispy_name
;
4230 lispy_name
= build_string (fontname
);
4236 /* Give frame F the fontset named FONTSETNAME as its default font, and
4237 return the full name of that fontset. FONTSETNAME may be a wildcard
4238 pattern; in that case, we choose some fontset that fits the pattern.
4239 The return value shows which fontset we chose. */
4242 x_new_fontset (f
, fontsetname
)
4246 int fontset
= fs_query_fontset (f
, fontsetname
);
4247 struct fontset_info
*fontsetp
;
4253 if (FRAME_FONTSET (f
) == fontset
)
4254 /* This fontset is already set in frame F. There's nothing more
4256 return build_string (fontsetname
);
4258 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4260 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4261 /* This fontset doesn't contain ASCII font. */
4264 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4266 if (!STRINGP (result
))
4267 /* Can't load ASCII font. */
4270 /* Since x_new_font doesn't update any fontset information, do it now. */
4271 FRAME_FONTSET(f
) = fontset
;
4272 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4273 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4275 return build_string (fontsetname
);
4278 /* Calculate the absolute position in frame F
4279 from its current recorded position values and gravity. */
4281 x_calc_absolute_position (f
)
4286 int flags
= f
->output_data
.w32
->size_hint_flags
;
4290 /* Find the position of the outside upper-left corner of
4291 the inner window, with respect to the outer window. */
4292 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4295 MapWindowPoints (FRAME_W32_WINDOW (f
),
4296 f
->output_data
.w32
->parent_desc
,
4303 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4306 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4307 FRAME_EXTERNAL_MENU_BAR (f
));
4310 pt
.x
+= (rt
.right
- rt
.left
);
4311 pt
.y
+= (rt
.bottom
- rt
.top
);
4314 /* Treat negative positions as relative to the leftmost bottommost
4315 position that fits on the screen. */
4316 if (flags
& XNegative
)
4317 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4318 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4320 + f
->output_data
.w32
->left_pos
);
4322 if (flags
& YNegative
)
4323 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4324 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4326 + f
->output_data
.w32
->top_pos
);
4327 /* The left_pos and top_pos
4328 are now relative to the top and left screen edges,
4329 so the flags should correspond. */
4330 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4333 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4334 to really change the position, and 0 when calling from
4335 x_make_frame_visible (in that case, XOFF and YOFF are the current
4336 position values). It is -1 when calling from x_set_frame_parameters,
4337 which means, do adjust for borders but don't change the gravity. */
4339 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4341 register int xoff
, yoff
;
4344 int modified_top
, modified_left
;
4346 if (change_gravity
> 0)
4348 f
->output_data
.w32
->top_pos
= yoff
;
4349 f
->output_data
.w32
->left_pos
= xoff
;
4350 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4352 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4354 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4355 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4357 x_calc_absolute_position (f
);
4360 x_wm_set_size_hint (f
, (long) 0, 0);
4362 /* It is a mystery why we need to add the border_width here
4363 when the frame is already visible, but experiment says we do. */
4364 modified_left
= f
->output_data
.w32
->left_pos
;
4365 modified_top
= f
->output_data
.w32
->top_pos
;
4367 /* Do not add in border widths under W32. */
4368 if (change_gravity
!= 0)
4370 modified_left
+= f
->output_data
.w32
->border_width
;
4371 modified_top
+= f
->output_data
.w32
->border_width
;
4375 my_set_window_pos (FRAME_W32_WINDOW (f
),
4377 modified_left
, modified_top
,
4379 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4383 /* Call this to change the size of frame F's x-window.
4384 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4385 for this size change and subsequent size changes.
4386 Otherwise we leave the window gravity unchanged. */
4388 x_set_window_size (f
, change_gravity
, cols
, rows
)
4393 int pixelwidth
, pixelheight
;
4395 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4399 check_frame_size (f
, &rows
, &cols
);
4400 f
->output_data
.w32
->vertical_scroll_bar_extra
4401 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4403 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4404 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4405 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4406 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4407 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4409 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4410 x_wm_set_size_hint (f
, (long) 0, 0);
4415 rect
.left
= rect
.top
= 0;
4416 rect
.right
= pixelwidth
;
4417 rect
.bottom
= pixelheight
;
4419 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4420 FRAME_EXTERNAL_MENU_BAR (f
));
4422 my_set_window_pos (FRAME_W32_WINDOW (f
),
4425 rect
.right
- rect
.left
,
4426 rect
.bottom
- rect
.top
,
4427 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4430 /* Now, strictly speaking, we can't be sure that this is accurate,
4431 but the window manager will get around to dealing with the size
4432 change request eventually, and we'll hear how it went when the
4433 ConfigureNotify event gets here.
4435 We could just not bother storing any of this information here,
4436 and let the ConfigureNotify event set everything up, but that
4437 might be kind of confusing to the lisp code, since size changes
4438 wouldn't be reported in the frame parameters until some random
4439 point in the future when the ConfigureNotify event arrives. */
4440 change_frame_size (f
, rows
, cols
, 0, 0);
4441 PIXEL_WIDTH (f
) = pixelwidth
;
4442 PIXEL_HEIGHT (f
) = pixelheight
;
4444 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4445 receive in the ConfigureNotify event; if we get what we asked
4446 for, then the event won't cause the screen to become garbaged, so
4447 we have to make sure to do it here. */
4448 SET_FRAME_GARBAGED (f
);
4450 /* If cursor was outside the new size, mark it as off. */
4451 if (f
->phys_cursor_y
>= rows
4452 || f
->phys_cursor_x
>= cols
)
4454 f
->phys_cursor_x
= -1;
4455 f
->phys_cursor_y
= -1;
4458 /* Clear out any recollection of where the mouse highlighting was,
4459 since it might be in a place that's outside the new frame size.
4460 Actually checking whether it is outside is a pain in the neck,
4461 so don't try--just let the highlighting be done afresh with new size. */
4462 window
= dpyinfo
->mouse_face_window
;
4463 if (! NILP (window
) && XFRAME (window
) == f
)
4465 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4466 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4467 dpyinfo
->mouse_face_window
= Qnil
;
4473 /* Mouse warping. */
4476 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4485 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4486 pt
.x
= rect
.left
+ pix_x
;
4487 pt
.y
= rect
.top
+ pix_y
;
4488 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4490 SetCursorPos (pt
.x
, pt
.y
);
4496 x_set_mouse_position (f
, x
, y
)
4502 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4503 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4505 if (pix_x
< 0) pix_x
= 0;
4506 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4508 if (pix_y
< 0) pix_y
= 0;
4509 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4511 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4514 /* focus shifting, raising and lowering. */
4516 x_focus_on_frame (f
)
4519 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4521 /* Give input focus to frame. */
4524 /* Try not to change its Z-order if possible. */
4525 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4526 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4529 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4538 /* Raise frame F. */
4545 /* Strictly speaking, raise-frame should only change the frame's Z
4546 order, leaving input focus unchanged. This is reasonable behaviour
4547 on X where the usual policy is point-to-focus. However, this
4548 behaviour would be very odd on Windows where the usual policy is
4551 On X, if the mouse happens to be over the raised frame, it gets
4552 input focus anyway (so the window with focus will never be
4553 completely obscured) - if not, then just moving the mouse over it
4554 is sufficient to give it focus. On Windows, the user must actually
4555 click on the frame (preferrably the title bar so as not to move
4556 point), which is more awkward. Also, no other Windows program
4557 raises a window to the top but leaves another window (possibly now
4558 completely obscured) with input focus.
4560 Because there is a system setting on Windows that allows the user
4561 to choose the point to focus policy, we make the strict semantics
4562 optional, but by default we grab focus when raising. */
4564 if (NILP (Vw32_grab_focus_on_raise
))
4566 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4567 not already the foreground application: the frame is raised
4568 above all other frames belonging to us, but not above the
4569 current top window. To achieve that, we have to resort to this
4570 more cumbersome method. */
4572 HDWP handle
= BeginDeferWindowPos (2);
4575 DeferWindowPos (handle
,
4576 FRAME_W32_WINDOW (f
),
4579 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4581 DeferWindowPos (handle
,
4582 GetForegroundWindow (),
4583 FRAME_W32_WINDOW (f
),
4585 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4587 EndDeferWindowPos (handle
);
4592 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4598 /* Lower frame F. */
4604 my_set_window_pos (FRAME_W32_WINDOW (f
),
4607 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4612 w32_frame_raise_lower (f
, raise
)
4622 /* Change of visibility. */
4624 /* This tries to wait until the frame is really visible.
4625 However, if the window manager asks the user where to position
4626 the frame, this will return before the user finishes doing that.
4627 The frame will not actually be visible at that time,
4628 but it will become visible later when the window manager
4629 finishes with it. */
4631 x_make_frame_visible (f
)
4636 if (! FRAME_VISIBLE_P (f
))
4638 /* We test FRAME_GARBAGED_P here to make sure we don't
4639 call x_set_offset a second time
4640 if we get to x_make_frame_visible a second time
4641 before the window gets really visible. */
4642 if (! FRAME_ICONIFIED_P (f
)
4643 && ! f
->output_data
.w32
->asked_for_visible
)
4644 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4646 f
->output_data
.w32
->asked_for_visible
= 1;
4648 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4649 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4652 /* Synchronize to ensure Emacs knows the frame is visible
4653 before we do anything else. We do this loop with input not blocked
4654 so that incoming events are handled. */
4657 int count
= input_signal_count
;
4659 /* This must come after we set COUNT. */
4662 XSETFRAME (frame
, f
);
4666 /* Once we have handled input events,
4667 we should have received the MapNotify if one is coming.
4668 So if we have not got it yet, stop looping.
4669 Some window managers make their own decisions
4670 about visibility. */
4671 if (input_signal_count
!= count
)
4673 /* Machines that do polling rather than SIGIO have been observed
4674 to go into a busy-wait here. So we'll fake an alarm signal
4675 to let the handler know that there's something to be read.
4676 We used to raise a real alarm, but it seems that the handler
4677 isn't always enabled here. This is probably a bug. */
4678 if (input_polling_used ())
4680 /* It could be confusing if a real alarm arrives while processing
4681 the fake one. Turn it off and let the handler reset it. */
4683 input_poll_signal (0);
4685 /* Once we have handled input events,
4686 we should have received the MapNotify if one is coming.
4687 So if we have not got it yet, stop looping.
4688 Some window managers make their own decisions
4689 about visibility. */
4690 if (input_signal_count
!= count
)
4693 FRAME_SAMPLE_VISIBILITY (f
);
4697 /* Change from mapped state to withdrawn state. */
4699 /* Make the frame visible (mapped and not iconified). */
4701 x_make_frame_invisible (f
)
4706 /* Don't keep the highlight on an invisible frame. */
4707 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4708 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4712 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4714 /* We can't distinguish this from iconification
4715 just by the event that we get from the server.
4716 So we can't win using the usual strategy of letting
4717 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4718 and synchronize with the server to make sure we agree. */
4720 FRAME_ICONIFIED_P (f
) = 0;
4721 f
->async_visible
= 0;
4722 f
->async_iconified
= 0;
4727 /* Change window state from mapped to iconified. */
4735 /* Don't keep the highlight on an invisible frame. */
4736 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4737 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4739 if (f
->async_iconified
)
4744 /* Simulate the user minimizing the frame. */
4745 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4747 f
->async_iconified
= 1;
4752 /* Destroy the window of frame F. */
4754 x_destroy_window (f
)
4757 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4761 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4762 free_frame_menubar (f
);
4763 free_frame_faces (f
);
4765 xfree (f
->output_data
.w32
);
4766 f
->output_data
.w32
= 0;
4767 if (f
== dpyinfo
->w32_focus_frame
)
4768 dpyinfo
->w32_focus_frame
= 0;
4769 if (f
== dpyinfo
->w32_focus_event_frame
)
4770 dpyinfo
->w32_focus_event_frame
= 0;
4771 if (f
== dpyinfo
->w32_highlight_frame
)
4772 dpyinfo
->w32_highlight_frame
= 0;
4774 dpyinfo
->reference_count
--;
4776 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4778 dpyinfo
->mouse_face_beg_row
4779 = dpyinfo
->mouse_face_beg_col
= -1;
4780 dpyinfo
->mouse_face_end_row
4781 = dpyinfo
->mouse_face_end_col
= -1;
4782 dpyinfo
->mouse_face_window
= Qnil
;
4788 /* Setting window manager hints. */
4790 /* Set the normal size hints for the window manager, for frame F.
4791 FLAGS is the flags word to use--or 0 meaning preserve the flags
4792 that the window now has.
4793 If USER_POSITION is nonzero, we set the USPosition
4794 flag (this is useful when FLAGS is 0). */
4796 x_wm_set_size_hint (f
, flags
, user_position
)
4801 Window window
= FRAME_W32_WINDOW (f
);
4803 flexlines
= f
->height
;
4807 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4808 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4809 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4810 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4815 /* Window manager things */
4816 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4821 Window window
= FRAME_W32_WINDOW (f
);
4823 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4824 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4825 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4827 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4832 /* Initialization. */
4834 #ifdef USE_X_TOOLKIT
4835 static XrmOptionDescRec emacs_options
[] = {
4836 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4837 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4839 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4840 XrmoptionSepArg
, NULL
},
4841 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4843 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4844 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4845 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4846 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4847 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4848 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4849 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4851 #endif /* USE_X_TOOLKIT */
4853 static int w32_initialized
= 0;
4855 struct w32_display_info
*
4856 w32_term_init (display_name
, xrm_option
, resource_name
)
4857 Lisp_Object display_name
;
4859 char *resource_name
;
4863 struct w32_display_info
*dpyinfo
;
4868 if (!w32_initialized
)
4871 w32_initialized
= 1;
4882 argv
[argc
++] = "-xrm";
4883 argv
[argc
++] = xrm_option
;
4887 dpyinfo
= &one_w32_display_info
;
4889 /* Put this display on the chain. */
4890 dpyinfo
->next
= NULL
;
4892 /* Put it on w32_display_name_list as well, to keep them parallel. */
4893 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4894 w32_display_name_list
);
4895 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4897 dpyinfo
->w32_id_name
4898 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4899 + XSTRING (Vsystem_name
)->size
4901 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4902 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4905 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4906 resource_name
, EMACS_CLASS
);
4908 /* Put the rdb where we can find it in a way that works on
4910 dpyinfo
->xrdb
= xrdb
;
4912 hdc
= GetDC (GetDesktopWindow ());
4914 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4915 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4916 dpyinfo
->root_window
= GetDesktopWindow ();
4917 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4918 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4919 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4920 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4921 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4922 dpyinfo
->grabbed
= 0;
4923 dpyinfo
->reference_count
= 0;
4924 dpyinfo
->n_fonts
= 0;
4925 dpyinfo
->font_table_size
= 0;
4926 dpyinfo
->bitmaps
= 0;
4927 dpyinfo
->bitmaps_size
= 0;
4928 dpyinfo
->bitmaps_last
= 0;
4929 dpyinfo
->mouse_face_mouse_frame
= 0;
4930 dpyinfo
->mouse_face_deferred_gc
= 0;
4931 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4932 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4933 dpyinfo
->mouse_face_face_id
= 0;
4934 dpyinfo
->mouse_face_window
= Qnil
;
4935 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4936 dpyinfo
->mouse_face_defer
= 0;
4937 dpyinfo
->w32_focus_frame
= 0;
4938 dpyinfo
->w32_focus_event_frame
= 0;
4939 dpyinfo
->w32_highlight_frame
= 0;
4941 ReleaseDC (GetDesktopWindow (), hdc
);
4943 /* Determine if there is a middle mouse button, to allow parse_button
4944 to decide whether right mouse events should be mouse-2 or
4946 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4948 /* initialise palette with white and black */
4951 defined_color (0, "white", &color
, 1);
4952 defined_color (0, "black", &color
, 1);
4955 #ifndef F_SETOWN_BUG
4957 #ifdef F_SETOWN_SOCK_NEG
4958 /* stdin is a socket here */
4959 fcntl (connection
, F_SETOWN
, -getpid ());
4960 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4961 fcntl (connection
, F_SETOWN
, getpid ());
4962 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4963 #endif /* ! defined (F_SETOWN) */
4964 #endif /* F_SETOWN_BUG */
4967 if (interrupt_input
)
4968 init_sigio (connection
);
4969 #endif /* ! defined (SIGIO) */
4976 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4979 x_delete_display (dpyinfo
)
4980 struct w32_display_info
*dpyinfo
;
4982 /* Discard this display from w32_display_name_list and w32_display_list.
4983 We can't use Fdelq because that can quit. */
4984 if (! NILP (w32_display_name_list
)
4985 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4986 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4991 tail
= w32_display_name_list
;
4992 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4994 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4995 dpyinfo
->name_list_element
))
4997 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5000 tail
= XCONS (tail
)->cdr
;
5004 /* free palette table */
5006 struct w32_palette_entry
* plist
;
5008 plist
= dpyinfo
->color_list
;
5011 struct w32_palette_entry
* pentry
= plist
;
5012 plist
= plist
->next
;
5015 dpyinfo
->color_list
= NULL
;
5016 if (dpyinfo
->palette
)
5017 DeleteObject(dpyinfo
->palette
);
5019 xfree (dpyinfo
->font_table
);
5020 xfree (dpyinfo
->w32_id_name
);
5023 /* Set up use of W32. */
5025 DWORD
w32_msg_worker ();
5029 /* MSVC does not type K&R functions with no arguments correctly, and
5030 so we must explicitly cast them. */
5031 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
5032 clear_end_of_line_hook
= w32_clear_end_of_line
;
5033 ins_del_lines_hook
= w32_ins_del_lines
;
5034 change_line_highlight_hook
= w32_change_line_highlight
;
5035 insert_glyphs_hook
= w32_insert_glyphs
;
5036 write_glyphs_hook
= w32_write_glyphs
;
5037 delete_glyphs_hook
= w32_delete_glyphs
;
5038 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5039 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5040 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5041 update_begin_hook
= w32_update_begin
;
5042 update_end_hook
= w32_update_end
;
5043 set_terminal_window_hook
= w32_set_terminal_window
;
5044 read_socket_hook
= w32_read_socket
;
5045 frame_up_to_date_hook
= w32_frame_up_to_date
;
5046 cursor_to_hook
= w32_cursor_to
;
5047 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5048 mouse_position_hook
= w32_mouse_position
;
5049 frame_rehighlight_hook
= w32_frame_rehighlight
;
5050 frame_raise_lower_hook
= w32_frame_raise_lower
;
5051 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5052 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5053 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5054 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5056 scroll_region_ok
= 1; /* we'll scroll partial frames */
5057 char_ins_del_ok
= 0; /* just as fast to write the line */
5058 line_ins_del_ok
= 1; /* we'll just blt 'em */
5059 fast_clear_end_of_line
= 1; /* X does this well */
5060 memory_below_frame
= 0; /* we don't remember what scrolls
5064 /* Initialize input mode: interrupt_input off, no flow control, allow
5065 8 bit character input, standard quit char. */
5066 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5068 /* Create the window thread - it will terminate itself or when the app terminates */
5072 dwMainThreadId
= GetCurrentThreadId ();
5073 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5074 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5076 /* Wait for thread to start */
5081 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5083 hWindowsThread
= CreateThread (NULL
, 0,
5084 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5085 0, 0, &dwWindowsThreadId
);
5087 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5090 /* It is desirable that mainThread should have the same notion of
5091 focus window and active window as windowsThread. Unfortunately, the
5092 following call to AttachThreadInput, which should do precisely what
5093 we need, causes major problems when Emacs is linked as a console
5094 program. Unfortunately, we have good reasons for doing that, so
5095 instead we need to send messages to windowsThread to make some API
5096 calls for us (ones that affect, or depend on, the active/focus
5098 #ifdef ATTACH_THREADS
5099 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5102 /* Dynamically link to optional system components. */
5104 HANDLE user_lib
= LoadLibrary ("user32.dll");
5106 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5108 /* New proportional scroll bar functions. */
5109 LOAD_PROC( SetScrollInfo
);
5110 LOAD_PROC( GetScrollInfo
);
5114 FreeLibrary (user_lib
);
5116 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5117 otherwise use the fixed height. */
5118 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5119 GetSystemMetrics (SM_CYVTHUMB
);
5121 /* For either kind of scroll bar, take account of the arrows; these
5122 effectively form the border of the main scroll bar range. */
5123 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5124 = GetSystemMetrics (SM_CYVSCROLL
);
5131 staticpro (&w32_display_name_list
);
5132 w32_display_name_list
= Qnil
;
5134 staticpro (&last_mouse_scroll_bar
);
5135 last_mouse_scroll_bar
= Qnil
;
5137 staticpro (&Qvendor_specific_keysyms
);
5138 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5140 DEFVAR_INT ("w32-num-mouse-buttons",
5141 &Vw32_num_mouse_buttons
,
5142 "Number of physical mouse buttons.");
5143 Vw32_num_mouse_buttons
= Qnil
;
5145 DEFVAR_LISP ("w32-swap-mouse-buttons",
5146 &Vw32_swap_mouse_buttons
,
5147 "Swap the mapping of middle and right mouse buttons.\n\
5148 When nil, middle button is mouse-2 and right button is mouse-3.");
5149 Vw32_swap_mouse_buttons
= Qnil
;
5151 DEFVAR_LISP ("w32-grab-focus-on-raise",
5152 &Vw32_grab_focus_on_raise
,
5153 "Raised frame grabs input focus.\n\
5154 When t, `raise-frame' grabs input focus as well. This fits well\n\
5155 with the normal Windows click-to-focus policy, but might not be\n\
5156 desirable when using a point-to-focus policy.");
5157 Vw32_grab_focus_on_raise
= Qt
;
5159 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5160 &Vw32_capslock_is_shiftlock
,
5161 "Apply CapsLock state to non character input keys.\n\
5162 When nil, CapsLock only affects normal character input keys.");
5163 Vw32_capslock_is_shiftlock
= Qnil
;
5165 DEFVAR_LISP ("w32-recognize-altgr",
5166 &Vw32_recognize_altgr
,
5167 "Recognize right-alt and left-ctrl as AltGr.\n\
5168 When nil, the right-alt and left-ctrl key combination is\n\
5169 interpreted normally.");
5170 Vw32_recognize_altgr
= Qt
;
5172 DEFVAR_BOOL ("w32-enable-unicode-output",
5173 &w32_enable_unicode_output
,
5174 "Enable the use of Unicode for text output if non-nil.\n\
5175 Unicode output may prevent some third party applications for displaying\n\
5176 Far-East Languages on Windows 95/98 from working properly.\n\
5177 NT uses Unicode internally anyway, so this flag will probably have no\n\
5178 affect on NT machines.");
5179 w32_enable_unicode_output
= 1;