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];
3338 /* Read events coming from the W32 shell.
3339 This routine is called by the SIGIO handler.
3340 We return as soon as there are no more events to be read.
3342 Events representing keys are stored in buffer BUFP,
3343 which can hold up to NUMCHARS characters.
3344 We return the number of characters stored into the buffer,
3345 thus pretending to be `read'.
3347 EXPECTED is nonzero if the caller knows input is available.
3349 Some of these messages are reposted back to the message queue since the
3350 system calls the windows proc directly in a context where we cannot return
3351 the data nor can we guarantee the state we are in. So if we dispatch them
3352 we will get into an infinite loop. To prevent this from ever happening we
3353 will set a variable to indicate we are in the read_socket call and indicate
3354 which message we are processing since the windows proc gets called
3355 recursively with different messages by the system.
3359 w32_read_socket (sd
, bufp
, numchars
, expected
)
3361 register struct input_event
*bufp
;
3362 register int numchars
;
3366 int check_visibility
= 0;
3370 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3372 if (interrupt_input_blocked
)
3374 interrupt_input_pending
= 1;
3378 interrupt_input_pending
= 0;
3381 /* So people can tell when we have read the available input. */
3382 input_signal_count
++;
3385 abort (); /* Don't think this happens. */
3387 while (get_next_msg (&msg
, FALSE
))
3389 switch (msg
.msg
.message
)
3392 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3396 if (msg
.rect
.right
== msg
.rect
.left
||
3397 msg
.rect
.bottom
== msg
.rect
.top
)
3399 /* We may get paint messages even though the client
3400 area is clipped - these are not expose events. */
3401 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3402 XSTRING (f
->name
)->data
));
3404 else if (f
->async_visible
!= 1)
3406 /* Definitely not obscured, so mark as visible. */
3407 f
->async_visible
= 1;
3408 f
->async_iconified
= 0;
3409 SET_FRAME_GARBAGED (f
);
3410 DebPrint (("frame %04x (%s) reexposed\n", f
,
3411 XSTRING (f
->name
)->data
));
3413 /* WM_PAINT serves as MapNotify as well, so report
3414 visibility changes properly. */
3417 bufp
->kind
= deiconify_event
;
3418 XSETFRAME (bufp
->frame_or_window
, f
);
3423 else if (! NILP(Vframe_list
)
3424 && ! NILP (XCONS (Vframe_list
)->cdr
))
3425 /* Force a redisplay sooner or later to update the
3426 frame titles in case this is the second frame. */
3427 record_asynch_buffer_change ();
3431 /* Erase background again for safety. */
3432 w32_clear_rect (f
, NULL
, &msg
.rect
);
3436 msg
.rect
.right
- msg
.rect
.left
,
3437 msg
.rect
.bottom
- msg
.rect
.top
);
3442 case WM_INPUTLANGCHANGE
:
3443 /* Generate a language change event. */
3444 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3451 bufp
->kind
= language_change_event
;
3452 XSETFRAME (bufp
->frame_or_window
, f
);
3453 bufp
->code
= msg
.msg
.wParam
;
3454 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
3463 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3465 if (f
&& !f
->iconified
)
3467 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3469 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3470 bufp
->kind
= non_ascii_keystroke
;
3471 bufp
->code
= msg
.msg
.wParam
;
3472 bufp
->modifiers
= msg
.dwModifiers
;
3473 XSETFRAME (bufp
->frame_or_window
, f
);
3474 bufp
->timestamp
= msg
.msg
.time
;
3483 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3485 if (f
&& !f
->iconified
)
3487 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3489 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3490 bufp
->kind
= ascii_keystroke
;
3491 bufp
->code
= msg
.msg
.wParam
;
3492 bufp
->modifiers
= msg
.dwModifiers
;
3493 XSETFRAME (bufp
->frame_or_window
, f
);
3494 bufp
->timestamp
= msg
.msg
.time
;
3502 if (dpyinfo
->grabbed
&& last_mouse_frame
3503 && FRAME_LIVE_P (last_mouse_frame
))
3504 f
= last_mouse_frame
;
3506 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3509 note_mouse_movement (f
, &msg
.msg
);
3511 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3515 case WM_LBUTTONDOWN
:
3517 case WM_MBUTTONDOWN
:
3519 case WM_RBUTTONDOWN
:
3525 if (dpyinfo
->grabbed
&& last_mouse_frame
3526 && FRAME_LIVE_P (last_mouse_frame
))
3527 f
= last_mouse_frame
;
3529 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3533 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3536 construct_mouse_click (bufp
, &msg
, f
);
3543 parse_button (msg
.msg
.message
, &button
, &up
);
3547 dpyinfo
->grabbed
&= ~ (1 << button
);
3551 dpyinfo
->grabbed
|= (1 << button
);
3552 last_mouse_frame
= f
;
3558 if (dpyinfo
->grabbed
&& last_mouse_frame
3559 && FRAME_LIVE_P (last_mouse_frame
))
3560 f
= last_mouse_frame
;
3562 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3566 if ((!dpyinfo
->w32_focus_frame
3567 || f
== dpyinfo
->w32_focus_frame
)
3570 construct_mouse_wheel (bufp
, &msg
, f
);
3579 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3583 construct_drag_n_drop (bufp
, &msg
, f
);
3592 struct scroll_bar
*bar
=
3593 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3595 if (bar
&& numchars
>= 1)
3597 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3607 case WM_WINDOWPOSCHANGED
:
3609 case WM_ACTIVATEAPP
:
3610 check_visibility
= 1;
3614 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3616 if (f
&& !f
->async_iconified
)
3620 x_real_positions (f
, &x
, &y
);
3621 f
->output_data
.w32
->left_pos
= x
;
3622 f
->output_data
.w32
->top_pos
= y
;
3625 check_visibility
= 1;
3629 /* If window has been obscured or exposed by another window
3630 being maximised or minimised/restored, then recheck
3631 visibility of all frames. Direct changes to our own
3632 windows get handled by WM_SIZE. */
3634 if (msg
.msg
.lParam
!= 0)
3635 check_visibility
= 1;
3638 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3639 f
->async_visible
= msg
.msg
.wParam
;
3643 check_visibility
= 1;
3647 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3649 /* Inform lisp of whether frame has been iconified etc. */
3652 switch (msg
.msg
.wParam
)
3654 case SIZE_MINIMIZED
:
3655 f
->async_visible
= 0;
3656 f
->async_iconified
= 1;
3658 bufp
->kind
= iconify_event
;
3659 XSETFRAME (bufp
->frame_or_window
, f
);
3665 case SIZE_MAXIMIZED
:
3667 f
->async_visible
= 1;
3668 f
->async_iconified
= 0;
3670 /* wait_reading_process_input will notice this and update
3671 the frame's display structures. */
3672 SET_FRAME_GARBAGED (f
);
3676 bufp
->kind
= deiconify_event
;
3677 XSETFRAME (bufp
->frame_or_window
, f
);
3683 /* Force a redisplay sooner or later
3684 to update the frame titles
3685 in case this is the second frame. */
3686 record_asynch_buffer_change ();
3691 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3699 GetClientRect(msg
.msg
.hwnd
, &rect
);
3701 height
= rect
.bottom
- rect
.top
;
3702 width
= rect
.right
- rect
.left
;
3704 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3705 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3707 /* TODO: Clip size to the screen dimensions. */
3709 /* Even if the number of character rows and columns has
3710 not changed, the font size may have changed, so we need
3711 to check the pixel dimensions as well. */
3713 if (columns
!= f
->width
3714 || rows
!= f
->height
3715 || width
!= f
->output_data
.w32
->pixel_width
3716 || height
!= f
->output_data
.w32
->pixel_height
)
3718 /* I had set this to 0, 0 - I am not sure why?? */
3720 change_frame_size (f
, rows
, columns
, 0, 1);
3721 SET_FRAME_GARBAGED (f
);
3723 f
->output_data
.w32
->pixel_width
= width
;
3724 f
->output_data
.w32
->pixel_height
= height
;
3725 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3729 check_visibility
= 1;
3734 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3736 if (msg
.msg
.message
== WM_SETFOCUS
)
3738 x_new_focus_frame (dpyinfo
, f
);
3740 else if (f
== dpyinfo
->w32_focus_frame
)
3742 x_new_focus_frame (dpyinfo
, 0);
3745 check_visibility
= 1;
3749 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3756 bufp
->kind
= delete_window_event
;
3757 XSETFRAME (bufp
->frame_or_window
, f
);
3765 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3772 bufp
->kind
= menu_bar_activate_event
;
3773 XSETFRAME (bufp
->frame_or_window
, f
);
3781 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3785 extern void menubar_selection_callback
3786 (FRAME_PTR f
, void * client_data
);
3787 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3790 check_visibility
= 1;
3793 case WM_DISPLAYCHANGE
:
3794 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3798 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3799 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3800 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3801 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3805 check_visibility
= 1;
3809 /* Check for messages registered at runtime. */
3810 if (msg
.msg
.message
== msh_mousewheel
)
3812 if (dpyinfo
->grabbed
&& last_mouse_frame
3813 && FRAME_LIVE_P (last_mouse_frame
))
3814 f
= last_mouse_frame
;
3816 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3820 if ((!dpyinfo
->w32_focus_frame
3821 || f
== dpyinfo
->w32_focus_frame
)
3824 construct_mouse_wheel (bufp
, &msg
, f
);
3835 /* If the focus was just given to an autoraising frame,
3837 /* ??? This ought to be able to handle more than one such frame. */
3838 if (pending_autoraise_frame
)
3840 x_raise_frame (pending_autoraise_frame
);
3841 pending_autoraise_frame
= 0;
3844 /* Check which frames are still visisble, if we have enqueued any user
3845 events or been notified of events that may affect visibility. We
3846 do this here because there doesn't seem to be any direct
3847 notification from Windows that the visibility of a window has
3848 changed (at least, not in all cases). */
3849 if (count
> 0 || check_visibility
)
3851 Lisp_Object tail
, frame
;
3853 FOR_EACH_FRAME (tail
, frame
)
3855 FRAME_PTR f
= XFRAME (frame
);
3856 /* Check "visible" frames and mark each as obscured or not.
3857 Note that async_visible is nonzero for unobscured and
3858 obscured frames, but zero for hidden and iconified frames. */
3859 if (FRAME_W32_P (f
) && f
->async_visible
)
3862 HDC hdc
= get_frame_dc (f
);
3863 GetClipBox (hdc
, &clipbox
);
3864 release_frame_dc (f
, hdc
);
3866 if (clipbox
.right
== clipbox
.left
3867 || clipbox
.bottom
== clipbox
.top
)
3869 /* Frame has become completely obscured so mark as
3870 such (we do this by setting async_visible to 2 so
3871 that FRAME_VISIBLE_P is still true, but redisplay
3873 f
->async_visible
= 2;
3875 if (!FRAME_OBSCURED_P (f
))
3877 DebPrint (("frame %04x (%s) obscured\n", f
,
3878 XSTRING (f
->name
)->data
));
3883 /* Frame is not obscured, so mark it as such. */
3884 f
->async_visible
= 1;
3886 if (FRAME_OBSCURED_P (f
))
3888 SET_FRAME_GARBAGED (f
);
3889 DebPrint (("frame %04x (%s) reexposed\n", f
,
3890 XSTRING (f
->name
)->data
));
3892 /* Force a redisplay sooner or later. */
3893 record_asynch_buffer_change ();
3904 /* Drawing the cursor. */
3907 /* Draw a hollow box cursor. Don't change the inside of the box. */
3917 hdc
= get_frame_dc (f
);
3919 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3921 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3922 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3923 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3924 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3926 FrameRect (hdc
, &rect
, hb
);
3929 release_frame_dc (f
, hdc
);
3932 /* Clear the cursor of frame F to background color,
3933 and mark the cursor as not shown.
3934 This is used when the text where the cursor is
3935 is about to be rewritten. */
3941 if (! FRAME_VISIBLE_P (f
)
3942 || f
->phys_cursor_x
< 0)
3945 x_display_cursor (f
, 0);
3946 f
->phys_cursor_x
= -1;
3949 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3950 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3954 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3961 CHAR_TO_PIXEL_COL (f
, column
),
3962 CHAR_TO_PIXEL_ROW (f
, row
),
3963 &glyph
, 1, highlight
, 0, NULL
);
3967 x_display_bar_cursor (f
, on
)
3971 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3973 /* This is pointless on invisible frames, and dangerous on garbaged
3974 frames; in the latter case, the frame may be in the midst of
3975 changing its size, and curs_x and curs_y may be off the frame. */
3976 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3979 if (! on
&& f
->phys_cursor_x
< 0)
3982 /* If there is anything wrong with the current cursor state, remove it. */
3983 if (f
->phys_cursor_x
>= 0
3985 || f
->phys_cursor_x
!= curs_x
3986 || f
->phys_cursor_y
!= curs_y
3987 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
3989 /* Erase the cursor by redrawing the character underneath it. */
3990 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3991 f
->phys_cursor_glyph
,
3992 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3993 f
->phys_cursor_x
= -1;
3996 /* If we now need a cursor in the new place or in the new form, do it so. */
3998 && (f
->phys_cursor_x
< 0
3999 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4001 f
->phys_cursor_glyph
4002 = ((current_glyphs
->enable
[curs_y
]
4003 && curs_x
< current_glyphs
->used
[curs_y
])
4004 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4006 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4007 CHAR_TO_PIXEL_COL (f
, curs_x
),
4008 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4009 max (f
->output_data
.w32
->cursor_width
, 1),
4010 f
->output_data
.w32
->line_height
);
4012 f
->phys_cursor_x
= curs_x
;
4013 f
->phys_cursor_y
= curs_y
;
4015 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4020 /* Turn the displayed cursor of frame F on or off according to ON.
4021 If ON is nonzero, where to put the cursor is specified
4022 by F->cursor_x and F->cursor_y. */
4025 x_display_box_cursor (f
, on
)
4029 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4031 /* This is pointless on invisible frames, and dangerous on garbaged
4032 frames; in the latter case, the frame may be in the midst of
4033 changing its size, and curs_x and curs_y may be off the frame. */
4034 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4037 /* If cursor is off and we want it off, return quickly. */
4038 if (!on
&& f
->phys_cursor_x
< 0)
4041 /* If cursor is currently being shown and we don't want it to be
4042 or it is in the wrong place,
4043 or we want a hollow box and it's not so, (pout!)
4045 if (f
->phys_cursor_x
>= 0
4047 || f
->phys_cursor_x
!= curs_x
4048 || f
->phys_cursor_y
!= curs_y
4049 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4050 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4052 int mouse_face_here
= 0;
4053 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4055 /* If the cursor is in the mouse face area, redisplay that when
4056 we clear the cursor. */
4057 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4058 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4059 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4060 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4061 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4062 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4063 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4064 /* Don't redraw the cursor's spot in mouse face
4065 if it is at the end of a line (on a newline).
4066 The cursor appears there, but mouse highlighting does not. */
4067 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4068 mouse_face_here
= 1;
4070 /* If the font is not as tall as a whole line,
4071 we must explicitly clear the line's whole height. */
4072 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4073 w32_clear_area (f
, NULL
,
4074 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4075 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4076 FONT_WIDTH (f
->output_data
.w32
->font
),
4077 f
->output_data
.w32
->line_height
);
4078 /* Erase the cursor by redrawing the character underneath it. */
4079 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4080 f
->phys_cursor_glyph
,
4083 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4084 f
->phys_cursor_x
= -1;
4087 /* If we want to show a cursor,
4088 or we want a box cursor and it's not so,
4089 write it in the right place. */
4091 && (f
->phys_cursor_x
< 0
4092 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4093 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4095 f
->phys_cursor_glyph
4096 = ((current_glyphs
->enable
[curs_y
]
4097 && curs_x
< current_glyphs
->used
[curs_y
])
4098 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4100 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4103 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4107 x_draw_single_glyph (f
, curs_y
, curs_x
,
4108 f
->phys_cursor_glyph
, 2);
4109 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4112 f
->phys_cursor_x
= curs_x
;
4113 f
->phys_cursor_y
= curs_y
;
4117 /* Display the cursor on frame F, or clear it, according to ON.
4118 Use the position specified by curs_x and curs_y
4119 if we are doing an update of frame F now.
4120 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4123 x_display_cursor (f
, on
)
4129 /* If we're not updating, then we want to use the current frame's
4130 cursor position, not our local idea of where the cursor ought to be. */
4131 if (f
!= updating_frame
)
4133 curs_x
= FRAME_CURSOR_X (f
);
4134 curs_y
= FRAME_CURSOR_Y (f
);
4137 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4138 x_display_box_cursor (f
, on
);
4139 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4140 x_display_bar_cursor (f
, on
);
4142 /* Those are the only two we have implemented! */
4148 /* Changing the font of the frame. */
4150 /* Give frame F the font named FONTNAME as its default font, and
4151 return the full name of that font. FONTNAME may be a wildcard
4152 pattern; in that case, we choose some font that fits the pattern.
4153 The return value shows which font we chose. */
4156 x_new_font (f
, fontname
)
4158 register char *fontname
;
4160 struct font_info
*fontp
4161 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4167 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4168 f
->output_data
.w32
->font_baseline
4169 = FRAME_FONT(f
)->tm
.tmAscent
+ fontp
->baseline_offset
;
4170 FRAME_FONTSET (f
) = -1;
4172 /* Compute the scroll bar width in character columns. */
4173 if (f
->scroll_bar_pixel_width
> 0)
4175 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4176 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4179 f
->scroll_bar_cols
= 2;
4181 /* Now make the frame display the given font. */
4182 if (FRAME_W32_WINDOW (f
) != 0)
4184 frame_update_line_height (f
);
4185 x_set_window_size (f
, 0, f
->width
, f
->height
);
4188 /* If we are setting a new frame's font for the first time,
4189 there are no faces yet, so this font's height is the line height. */
4190 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4193 Lisp_Object lispy_name
;
4195 lispy_name
= build_string (fontname
);
4201 /* Give frame F the fontset named FONTSETNAME as its default font, and
4202 return the full name of that fontset. FONTSETNAME may be a wildcard
4203 pattern; in that case, we choose some fontset that fits the pattern.
4204 The return value shows which fontset we chose. */
4207 x_new_fontset (f
, fontsetname
)
4211 int fontset
= fs_query_fontset (f
, fontsetname
);
4212 struct fontset_info
*fontsetp
;
4218 if (FRAME_FONTSET (f
) == fontset
)
4219 /* This fontset is already set in frame F. There's nothing more
4221 return build_string (fontsetname
);
4223 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4225 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4226 /* This fontset doesn't contain ASCII font. */
4229 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4231 if (!STRINGP (result
))
4232 /* Can't load ASCII font. */
4235 /* Since x_new_font doesn't update any fontset information, do it now. */
4236 FRAME_FONTSET(f
) = fontset
;
4237 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4238 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4240 return build_string (fontsetname
);
4243 /* Calculate the absolute position in frame F
4244 from its current recorded position values and gravity. */
4246 x_calc_absolute_position (f
)
4251 int flags
= f
->output_data
.w32
->size_hint_flags
;
4255 /* Find the position of the outside upper-left corner of
4256 the inner window, with respect to the outer window. */
4257 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4260 MapWindowPoints (FRAME_W32_WINDOW (f
),
4261 f
->output_data
.w32
->parent_desc
,
4268 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4271 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4272 FRAME_EXTERNAL_MENU_BAR (f
));
4275 pt
.x
+= (rt
.right
- rt
.left
);
4276 pt
.y
+= (rt
.bottom
- rt
.top
);
4279 /* Treat negative positions as relative to the leftmost bottommost
4280 position that fits on the screen. */
4281 if (flags
& XNegative
)
4282 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4283 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4285 + f
->output_data
.w32
->left_pos
);
4287 if (flags
& YNegative
)
4288 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4289 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4291 + f
->output_data
.w32
->top_pos
);
4292 /* The left_pos and top_pos
4293 are now relative to the top and left screen edges,
4294 so the flags should correspond. */
4295 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4298 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4299 to really change the position, and 0 when calling from
4300 x_make_frame_visible (in that case, XOFF and YOFF are the current
4301 position values). It is -1 when calling from x_set_frame_parameters,
4302 which means, do adjust for borders but don't change the gravity. */
4304 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4306 register int xoff
, yoff
;
4309 int modified_top
, modified_left
;
4311 if (change_gravity
> 0)
4313 f
->output_data
.w32
->top_pos
= yoff
;
4314 f
->output_data
.w32
->left_pos
= xoff
;
4315 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4317 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4319 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4320 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4322 x_calc_absolute_position (f
);
4325 x_wm_set_size_hint (f
, (long) 0, 0);
4327 /* It is a mystery why we need to add the border_width here
4328 when the frame is already visible, but experiment says we do. */
4329 modified_left
= f
->output_data
.w32
->left_pos
;
4330 modified_top
= f
->output_data
.w32
->top_pos
;
4332 /* Do not add in border widths under W32. */
4333 if (change_gravity
!= 0)
4335 modified_left
+= f
->output_data
.w32
->border_width
;
4336 modified_top
+= f
->output_data
.w32
->border_width
;
4340 my_set_window_pos (FRAME_W32_WINDOW (f
),
4342 modified_left
, modified_top
,
4344 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4348 /* Call this to change the size of frame F's x-window.
4349 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4350 for this size change and subsequent size changes.
4351 Otherwise we leave the window gravity unchanged. */
4353 x_set_window_size (f
, change_gravity
, cols
, rows
)
4358 int pixelwidth
, pixelheight
;
4360 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4364 check_frame_size (f
, &rows
, &cols
);
4365 f
->output_data
.w32
->vertical_scroll_bar_extra
4366 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4368 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4369 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4370 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4371 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4372 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4374 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4375 x_wm_set_size_hint (f
, (long) 0, 0);
4380 rect
.left
= rect
.top
= 0;
4381 rect
.right
= pixelwidth
;
4382 rect
.bottom
= pixelheight
;
4384 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4385 FRAME_EXTERNAL_MENU_BAR (f
));
4387 my_set_window_pos (FRAME_W32_WINDOW (f
),
4390 rect
.right
- rect
.left
,
4391 rect
.bottom
- rect
.top
,
4392 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4395 /* Now, strictly speaking, we can't be sure that this is accurate,
4396 but the window manager will get around to dealing with the size
4397 change request eventually, and we'll hear how it went when the
4398 ConfigureNotify event gets here.
4400 We could just not bother storing any of this information here,
4401 and let the ConfigureNotify event set everything up, but that
4402 might be kind of confusing to the lisp code, since size changes
4403 wouldn't be reported in the frame parameters until some random
4404 point in the future when the ConfigureNotify event arrives. */
4405 change_frame_size (f
, rows
, cols
, 0, 0);
4406 PIXEL_WIDTH (f
) = pixelwidth
;
4407 PIXEL_HEIGHT (f
) = pixelheight
;
4409 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4410 receive in the ConfigureNotify event; if we get what we asked
4411 for, then the event won't cause the screen to become garbaged, so
4412 we have to make sure to do it here. */
4413 SET_FRAME_GARBAGED (f
);
4415 /* If cursor was outside the new size, mark it as off. */
4416 if (f
->phys_cursor_y
>= rows
4417 || f
->phys_cursor_x
>= cols
)
4419 f
->phys_cursor_x
= -1;
4420 f
->phys_cursor_y
= -1;
4423 /* Clear out any recollection of where the mouse highlighting was,
4424 since it might be in a place that's outside the new frame size.
4425 Actually checking whether it is outside is a pain in the neck,
4426 so don't try--just let the highlighting be done afresh with new size. */
4427 window
= dpyinfo
->mouse_face_window
;
4428 if (! NILP (window
) && XFRAME (window
) == f
)
4430 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4431 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4432 dpyinfo
->mouse_face_window
= Qnil
;
4438 /* Mouse warping. */
4441 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4450 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4451 pt
.x
= rect
.left
+ pix_x
;
4452 pt
.y
= rect
.top
+ pix_y
;
4453 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4455 SetCursorPos (pt
.x
, pt
.y
);
4461 x_set_mouse_position (f
, x
, y
)
4467 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4468 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4470 if (pix_x
< 0) pix_x
= 0;
4471 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4473 if (pix_y
< 0) pix_y
= 0;
4474 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4476 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4479 /* focus shifting, raising and lowering. */
4481 x_focus_on_frame (f
)
4484 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4486 /* Give input focus to frame. */
4489 /* Try not to change its Z-order if possible. */
4490 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4491 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4494 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4503 /* Raise frame F. */
4510 /* Strictly speaking, raise-frame should only change the frame's Z
4511 order, leaving input focus unchanged. This is reasonable behaviour
4512 on X where the usual policy is point-to-focus. However, this
4513 behaviour would be very odd on Windows where the usual policy is
4516 On X, if the mouse happens to be over the raised frame, it gets
4517 input focus anyway (so the window with focus will never be
4518 completely obscured) - if not, then just moving the mouse over it
4519 is sufficient to give it focus. On Windows, the user must actually
4520 click on the frame (preferrably the title bar so as not to move
4521 point), which is more awkward. Also, no other Windows program
4522 raises a window to the top but leaves another window (possibly now
4523 completely obscured) with input focus.
4525 Because there is a system setting on Windows that allows the user
4526 to choose the point to focus policy, we make the strict semantics
4527 optional, but by default we grab focus when raising. */
4529 if (NILP (Vw32_grab_focus_on_raise
))
4531 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4532 not already the foreground application: the frame is raised
4533 above all other frames belonging to us, but not above the
4534 current top window. To achieve that, we have to resort to this
4535 more cumbersome method. */
4537 HDWP handle
= BeginDeferWindowPos (2);
4540 DeferWindowPos (handle
,
4541 FRAME_W32_WINDOW (f
),
4544 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4546 DeferWindowPos (handle
,
4547 GetForegroundWindow (),
4548 FRAME_W32_WINDOW (f
),
4550 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4552 EndDeferWindowPos (handle
);
4557 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4563 /* Lower frame F. */
4569 my_set_window_pos (FRAME_W32_WINDOW (f
),
4572 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4577 w32_frame_raise_lower (f
, raise
)
4587 /* Change of visibility. */
4589 /* This tries to wait until the frame is really visible.
4590 However, if the window manager asks the user where to position
4591 the frame, this will return before the user finishes doing that.
4592 The frame will not actually be visible at that time,
4593 but it will become visible later when the window manager
4594 finishes with it. */
4596 x_make_frame_visible (f
)
4601 if (! FRAME_VISIBLE_P (f
))
4603 /* We test FRAME_GARBAGED_P here to make sure we don't
4604 call x_set_offset a second time
4605 if we get to x_make_frame_visible a second time
4606 before the window gets really visible. */
4607 if (! FRAME_ICONIFIED_P (f
)
4608 && ! f
->output_data
.w32
->asked_for_visible
)
4609 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4611 f
->output_data
.w32
->asked_for_visible
= 1;
4613 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4614 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4617 /* Synchronize to ensure Emacs knows the frame is visible
4618 before we do anything else. We do this loop with input not blocked
4619 so that incoming events are handled. */
4622 int count
= input_signal_count
;
4624 /* This must come after we set COUNT. */
4627 XSETFRAME (frame
, f
);
4631 /* Once we have handled input events,
4632 we should have received the MapNotify if one is coming.
4633 So if we have not got it yet, stop looping.
4634 Some window managers make their own decisions
4635 about visibility. */
4636 if (input_signal_count
!= count
)
4638 /* Machines that do polling rather than SIGIO have been observed
4639 to go into a busy-wait here. So we'll fake an alarm signal
4640 to let the handler know that there's something to be read.
4641 We used to raise a real alarm, but it seems that the handler
4642 isn't always enabled here. This is probably a bug. */
4643 if (input_polling_used ())
4645 /* It could be confusing if a real alarm arrives while processing
4646 the fake one. Turn it off and let the handler reset it. */
4648 input_poll_signal (0);
4650 /* Once we have handled input events,
4651 we should have received the MapNotify if one is coming.
4652 So if we have not got it yet, stop looping.
4653 Some window managers make their own decisions
4654 about visibility. */
4655 if (input_signal_count
!= count
)
4658 FRAME_SAMPLE_VISIBILITY (f
);
4662 /* Change from mapped state to withdrawn state. */
4664 /* Make the frame visible (mapped and not iconified). */
4666 x_make_frame_invisible (f
)
4671 /* Don't keep the highlight on an invisible frame. */
4672 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4673 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4677 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4679 /* We can't distinguish this from iconification
4680 just by the event that we get from the server.
4681 So we can't win using the usual strategy of letting
4682 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4683 and synchronize with the server to make sure we agree. */
4685 FRAME_ICONIFIED_P (f
) = 0;
4686 f
->async_visible
= 0;
4687 f
->async_iconified
= 0;
4692 /* Change window state from mapped to iconified. */
4700 /* Don't keep the highlight on an invisible frame. */
4701 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4702 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4704 if (f
->async_iconified
)
4709 /* Simulate the user minimizing the frame. */
4710 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4712 f
->async_iconified
= 1;
4717 /* Destroy the window of frame F. */
4719 x_destroy_window (f
)
4722 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4726 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4727 free_frame_menubar (f
);
4728 free_frame_faces (f
);
4730 xfree (f
->output_data
.w32
);
4731 f
->output_data
.w32
= 0;
4732 if (f
== dpyinfo
->w32_focus_frame
)
4733 dpyinfo
->w32_focus_frame
= 0;
4734 if (f
== dpyinfo
->w32_focus_event_frame
)
4735 dpyinfo
->w32_focus_event_frame
= 0;
4736 if (f
== dpyinfo
->w32_highlight_frame
)
4737 dpyinfo
->w32_highlight_frame
= 0;
4739 dpyinfo
->reference_count
--;
4741 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4743 dpyinfo
->mouse_face_beg_row
4744 = dpyinfo
->mouse_face_beg_col
= -1;
4745 dpyinfo
->mouse_face_end_row
4746 = dpyinfo
->mouse_face_end_col
= -1;
4747 dpyinfo
->mouse_face_window
= Qnil
;
4753 /* Setting window manager hints. */
4755 /* Set the normal size hints for the window manager, for frame F.
4756 FLAGS is the flags word to use--or 0 meaning preserve the flags
4757 that the window now has.
4758 If USER_POSITION is nonzero, we set the USPosition
4759 flag (this is useful when FLAGS is 0). */
4761 x_wm_set_size_hint (f
, flags
, user_position
)
4766 Window window
= FRAME_W32_WINDOW (f
);
4768 flexlines
= f
->height
;
4772 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4773 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4774 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4775 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4780 /* Window manager things */
4781 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4786 Window window
= FRAME_W32_WINDOW (f
);
4788 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4789 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4790 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4792 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4797 /* Initialization. */
4799 #ifdef USE_X_TOOLKIT
4800 static XrmOptionDescRec emacs_options
[] = {
4801 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4802 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4804 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4805 XrmoptionSepArg
, NULL
},
4806 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4808 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4809 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4810 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4811 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4812 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4813 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4814 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4816 #endif /* USE_X_TOOLKIT */
4818 static int w32_initialized
= 0;
4820 struct w32_display_info
*
4821 w32_term_init (display_name
, xrm_option
, resource_name
)
4822 Lisp_Object display_name
;
4824 char *resource_name
;
4828 struct w32_display_info
*dpyinfo
;
4833 if (!w32_initialized
)
4836 w32_initialized
= 1;
4847 argv
[argc
++] = "-xrm";
4848 argv
[argc
++] = xrm_option
;
4852 dpyinfo
= &one_w32_display_info
;
4854 /* Put this display on the chain. */
4855 dpyinfo
->next
= NULL
;
4857 /* Put it on w32_display_name_list as well, to keep them parallel. */
4858 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4859 w32_display_name_list
);
4860 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4862 dpyinfo
->w32_id_name
4863 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4864 + XSTRING (Vsystem_name
)->size
4866 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4867 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4870 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4871 resource_name
, EMACS_CLASS
);
4873 /* Put the rdb where we can find it in a way that works on
4875 dpyinfo
->xrdb
= xrdb
;
4877 hdc
= GetDC (GetDesktopWindow ());
4879 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4880 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4881 dpyinfo
->root_window
= GetDesktopWindow ();
4882 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4883 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4884 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4885 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4886 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4887 dpyinfo
->grabbed
= 0;
4888 dpyinfo
->reference_count
= 0;
4889 dpyinfo
->n_fonts
= 0;
4890 dpyinfo
->font_table_size
= 0;
4891 dpyinfo
->bitmaps
= 0;
4892 dpyinfo
->bitmaps_size
= 0;
4893 dpyinfo
->bitmaps_last
= 0;
4894 dpyinfo
->mouse_face_mouse_frame
= 0;
4895 dpyinfo
->mouse_face_deferred_gc
= 0;
4896 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4897 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4898 dpyinfo
->mouse_face_face_id
= 0;
4899 dpyinfo
->mouse_face_window
= Qnil
;
4900 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4901 dpyinfo
->mouse_face_defer
= 0;
4902 dpyinfo
->w32_focus_frame
= 0;
4903 dpyinfo
->w32_focus_event_frame
= 0;
4904 dpyinfo
->w32_highlight_frame
= 0;
4906 ReleaseDC (GetDesktopWindow (), hdc
);
4908 /* Determine if there is a middle mouse button, to allow parse_button
4909 to decide whether right mouse events should be mouse-2 or
4911 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4913 /* initialise palette with white and black */
4916 defined_color (0, "white", &color
, 1);
4917 defined_color (0, "black", &color
, 1);
4920 #ifndef F_SETOWN_BUG
4922 #ifdef F_SETOWN_SOCK_NEG
4923 /* stdin is a socket here */
4924 fcntl (connection
, F_SETOWN
, -getpid ());
4925 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4926 fcntl (connection
, F_SETOWN
, getpid ());
4927 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4928 #endif /* ! defined (F_SETOWN) */
4929 #endif /* F_SETOWN_BUG */
4932 if (interrupt_input
)
4933 init_sigio (connection
);
4934 #endif /* ! defined (SIGIO) */
4941 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4944 x_delete_display (dpyinfo
)
4945 struct w32_display_info
*dpyinfo
;
4947 /* Discard this display from w32_display_name_list and w32_display_list.
4948 We can't use Fdelq because that can quit. */
4949 if (! NILP (w32_display_name_list
)
4950 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4951 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4956 tail
= w32_display_name_list
;
4957 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4959 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4960 dpyinfo
->name_list_element
))
4962 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4965 tail
= XCONS (tail
)->cdr
;
4969 /* free palette table */
4971 struct w32_palette_entry
* plist
;
4973 plist
= dpyinfo
->color_list
;
4976 struct w32_palette_entry
* pentry
= plist
;
4977 plist
= plist
->next
;
4980 dpyinfo
->color_list
= NULL
;
4981 if (dpyinfo
->palette
)
4982 DeleteObject(dpyinfo
->palette
);
4984 xfree (dpyinfo
->font_table
);
4985 xfree (dpyinfo
->w32_id_name
);
4988 /* Set up use of W32. */
4990 DWORD
w32_msg_worker ();
4994 /* MSVC does not type K&R functions with no arguments correctly, and
4995 so we must explicitly cast them. */
4996 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
4997 clear_end_of_line_hook
= w32_clear_end_of_line
;
4998 ins_del_lines_hook
= w32_ins_del_lines
;
4999 change_line_highlight_hook
= w32_change_line_highlight
;
5000 insert_glyphs_hook
= w32_insert_glyphs
;
5001 write_glyphs_hook
= w32_write_glyphs
;
5002 delete_glyphs_hook
= w32_delete_glyphs
;
5003 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5004 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5005 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5006 update_begin_hook
= w32_update_begin
;
5007 update_end_hook
= w32_update_end
;
5008 set_terminal_window_hook
= w32_set_terminal_window
;
5009 read_socket_hook
= w32_read_socket
;
5010 frame_up_to_date_hook
= w32_frame_up_to_date
;
5011 cursor_to_hook
= w32_cursor_to
;
5012 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5013 mouse_position_hook
= w32_mouse_position
;
5014 frame_rehighlight_hook
= w32_frame_rehighlight
;
5015 frame_raise_lower_hook
= w32_frame_raise_lower
;
5016 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5017 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5018 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5019 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5021 scroll_region_ok
= 1; /* we'll scroll partial frames */
5022 char_ins_del_ok
= 0; /* just as fast to write the line */
5023 line_ins_del_ok
= 1; /* we'll just blt 'em */
5024 fast_clear_end_of_line
= 1; /* X does this well */
5025 memory_below_frame
= 0; /* we don't remember what scrolls
5029 /* Initialize input mode: interrupt_input off, no flow control, allow
5030 8 bit character input, standard quit char. */
5031 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5033 /* Create the window thread - it will terminate itself or when the app terminates */
5037 dwMainThreadId
= GetCurrentThreadId ();
5038 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5039 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5041 /* Wait for thread to start */
5046 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5048 hWindowsThread
= CreateThread (NULL
, 0,
5049 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5050 0, 0, &dwWindowsThreadId
);
5052 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5055 /* It is desirable that mainThread should have the same notion of
5056 focus window and active window as windowsThread. Unfortunately, the
5057 following call to AttachThreadInput, which should do precisely what
5058 we need, causes major problems when Emacs is linked as a console
5059 program. Unfortunately, we have good reasons for doing that, so
5060 instead we need to send messages to windowsThread to make some API
5061 calls for us (ones that affect, or depend on, the active/focus
5063 #ifdef ATTACH_THREADS
5064 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5067 /* Dynamically link to optional system components. */
5069 HANDLE user_lib
= LoadLibrary ("user32.dll");
5071 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5073 /* New proportional scroll bar functions. */
5074 LOAD_PROC( SetScrollInfo
);
5075 LOAD_PROC( GetScrollInfo
);
5079 FreeLibrary (user_lib
);
5081 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5082 otherwise use the fixed height. */
5083 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5084 GetSystemMetrics (SM_CYVTHUMB
);
5086 /* For either kind of scroll bar, take account of the arrows; these
5087 effectively form the border of the main scroll bar range. */
5088 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5089 = GetSystemMetrics (SM_CYVSCROLL
);
5096 staticpro (&w32_display_name_list
);
5097 w32_display_name_list
= Qnil
;
5099 staticpro (&last_mouse_scroll_bar
);
5100 last_mouse_scroll_bar
= Qnil
;
5102 staticpro (&Qvendor_specific_keysyms
);
5103 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5105 DEFVAR_INT ("w32-num-mouse-buttons",
5106 &Vw32_num_mouse_buttons
,
5107 "Number of physical mouse buttons.");
5108 Vw32_num_mouse_buttons
= Qnil
;
5110 DEFVAR_LISP ("w32-swap-mouse-buttons",
5111 &Vw32_swap_mouse_buttons
,
5112 "Swap the mapping of middle and right mouse buttons.\n\
5113 When nil, middle button is mouse-2 and right button is mouse-3.");
5114 Vw32_swap_mouse_buttons
= Qnil
;
5116 DEFVAR_LISP ("w32-grab-focus-on-raise",
5117 &Vw32_grab_focus_on_raise
,
5118 "Raised frame grabs input focus.\n\
5119 When t, `raise-frame' grabs input focus as well. This fits well\n\
5120 with the normal Windows click-to-focus policy, but might not be\n\
5121 desirable when using a point-to-focus policy.");
5122 Vw32_grab_focus_on_raise
= Qt
;
5124 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5125 &Vw32_capslock_is_shiftlock
,
5126 "Apply CapsLock state to non character input keys.\n\
5127 When nil, CapsLock only affects normal character input keys.");
5128 Vw32_capslock_is_shiftlock
= Qnil
;
5130 DEFVAR_LISP ("w32-recognize-altgr",
5131 &Vw32_recognize_altgr
,
5132 "Recognize right-alt and left-ctrl as AltGr.\n\
5133 When nil, the right-alt and left-ctrl key combination is\n\
5134 interpreted normally.");
5135 Vw32_recognize_altgr
= Qt
;
5137 DEFVAR_BOOL ("w32-enable-unicode-output",
5138 &w32_enable_unicode_output
,
5139 "Enable the use of Unicode for text output if non-nil.\n\
5140 Unicode output may prevent some third party applications for displaying\n\
5141 Far-East Languages on Windows 95/98 from working properly.\n\
5142 NT uses Unicode internally anyway, so this flag will probably have no\n\
5143 affect on NT machines.");
5144 w32_enable_unicode_output
= 1;