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. Unsigned to let GetCharABCWidths work. */
609 unsigned char *x_1byte_buffer
610 = (unsigned char *) alloca (2 * FRAME_WINDOW_WIDTH (f
)
611 * sizeof (*x_1byte_buffer
));
612 register unsigned char *bp
; /* Steps through x_1byte_buffer[]. */
613 register int tlen
= GLYPH_TABLE_LENGTH
;
614 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
615 Window window
= FRAME_W32_WINDOW (f
);
616 HDC hdc
= get_frame_dc (f
);
617 int orig_left
= left
;
623 /* Get the face-code of the next GLYPH. */
624 int cf
, len
, n_chars
;
627 Lisp_Object first_ch
;
628 /* HIGHEST and LOWEST are used while drawing a composite
629 character. The meanings are described later. */
632 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
633 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
634 ch
= FAST_GLYPH_CHAR (g
);
635 if (unibyte_display_via_language_environment
636 && SINGLE_BYTE_CHAR_P (ch
)
638 ch
= unibyte_char_to_multibyte (ch
);
639 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
640 charset
= CHAR_CHARSET (ch
);
641 if (charset
== CHARSET_COMPOSITION
)
643 /* We must draw components of the composite character on the
645 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
647 /* Set the face in the slot for work. */
648 cmpcharp
->face_work
= cf
;
650 /* We don't need the return value ... */
651 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
652 hl
, just_foreground
, cmpcharp
);
653 /* ... because the width of just drawn text can be
654 calculated as follows. */
655 left
+= FONT_WIDTH (FRAME_FONT (f
)) * cmpcharp
->width
;
658 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
663 /* Find the run of consecutive glyphs which can be drawn with
664 the same DC (i.e. the same charset and the same face-code).
665 Extract their character codes into X_2BYTE_BUFFER.
666 If CMPCHARP is not NULL, face-code is not checked because we
667 use only the face specified in `cmpcharp->face_work'. */
671 int this_charset
, c1
, c2
;
674 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
675 ch
= FAST_GLYPH_CHAR (g
);
676 if (unibyte_display_via_language_environment
677 && SINGLE_BYTE_CHAR_P (ch
)
679 ch
= unibyte_char_to_multibyte (ch
);
680 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
681 if (this_charset
!= charset
682 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
686 *cp
= BUILD_WCHAR_T (c1
, c2
);
688 *cp
= BUILD_WCHAR_T (0, c1
);
691 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
695 /* LEN gets the length of the run. */
696 len
= cp
- x_2byte_buffer
;
697 /* Now output this run of chars, with the font and pixel values
698 determined by the face code CF. */
700 struct face
*face
= FRAME_DEFAULT_FACE (f
);
701 XFontStruct
*font
= NULL
;
705 int line_height
= FRAME_LINE_HEIGHT (f
);
706 /* Pixel width of each glyph in this run. */
708 = (FONT_WIDTH (FRAME_FONT (f
))
709 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
710 /* Overall pixel width of this run. */
712 = (FONT_WIDTH (FRAME_FONT (f
))
713 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
714 /* A flag to tell if we have already filled background. We
715 fill background in advance in the following cases:
716 1) A face has stipple.
717 2) A height of font is shorter than LINE_HEIGHT.
718 3) Drawing a composite character.
719 4) Font has non-zero _MULE_BASELINE_OFFSET property.
720 After filling background, we draw glyphs by XDrawString16. */
721 int background_filled
;
722 /* Baseline position of a character, offset from TOP. */
724 /* The property value of `_MULE_RELATIVE_COMPOSE' and
725 `_MULE_DEFAULT_ASCENT'. */
726 int relative_compose
= 0, default_ascent
= 0;
727 /* 1 if we find no font or a font of inappropriate size. */
728 int require_clipping
;
729 int codepage
= CP_DEFAULT
;
730 BOOL print_via_unicode
= FALSE
;
732 /* HL = 3 means use a mouse face previously chosen. */
734 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
736 /* First look at the face of the text itself. */
739 /* It's possible for the display table to specify
740 a face code that is out of range. Use 0 in that case. */
741 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
742 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
746 face
= FRAME_MODE_LINE_FACE (f
);
748 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
749 if (FACE_STIPPLE (face
))
753 /* Then comes the distinction between modeline and normal text. */
758 face
= FRAME_MODE_LINE_FACE (f
);
759 if (FACE_STIPPLE (face
))
763 /* Setting appropriate font and codepage for this charset. */
764 if (charset
!= CHARSET_ASCII
)
767 int fontset
= FACE_FONTSET (face
);
768 struct font_info
*fontp
;
770 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
771 || !(fontp
= FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
772 charset
, NULL
, fontset
)))
775 font
= (XFontStruct
*) (fontp
->font
);
776 codepage
= w32_codepage_for_charset (charset
);
777 print_via_unicode
= w32_use_unicode_for_codepage (codepage
);
779 /* tmLastChar will only exceed 255 if TEXTMETRICW is used
780 (ie on NT but not on 95). In this case there is no harm
781 in being wrong, so have a go anyway. */
783 (font
->tm
.tmLastChar
> 255
784 ? (line_height
+ font
->tm
.tmAscent
- font
->tm
.tmDescent
) / 2
785 : f
->output_data
.w32
->font_baseline
- fontp
->baseline_offset
);
786 if (FONT_HEIGHT (font
) <= line_height
787 && (font
->tm
.tmAscent
> baseline
788 || font
->tm
.tmDescent
> line_height
- baseline
))
789 /* Adjust baseline for this font to show the whole
791 baseline
= line_height
- font
->tm
.tmDescent
;
793 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
795 relative_compose
= fontp
->relative_compose
;
796 default_ascent
= fontp
->default_ascent
;
799 /* We have to change code points in the following cases. */
800 if (charset
== charset_big5_1
801 || charset
== charset_big5_2
)
803 /* Handle Big5 encoding specially rather than
806 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
808 ENCODE_BIG5 (charset
, BYTE1 (*cp
), BYTE2 (*cp
),
810 *cp
= BUILD_WCHAR_T (big1
, big2
);
813 else if (fontp
->font_encoder
)
815 /* This font requires CCL program to calculate code
816 point of characters. */
817 struct ccl_program
*ccl
= fontp
->font_encoder
;
819 if (CHARSET_DIMENSION (charset
) == 1)
820 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
822 ccl
->reg
[0] = charset
;
823 ccl
->reg
[1] = BYTE2 (*cp
);
824 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
825 /* We assume that MSBs are appropriately
826 set/reset by CCL program. */
827 #if 0 /* this probably works under NT, but not under 95. */
828 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
829 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
831 *cp
= BUILD_WCHAR_T (ccl
->reg
[1], ccl
->reg
[2]);
832 #else /* Assume single dimensional charsets stay so. */
833 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
837 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
839 ccl
->reg
[0] = charset
;
840 ccl
->reg
[1] = BYTE1 (*cp
) , ccl
->reg
[2] = BYTE2 (*cp
);
841 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
842 /* We assume that MSBs are appropriately
843 set/reset by CCL program. */
844 #if 0 /* this probably works under NT, but not under 95. */
845 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
846 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
848 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
849 #else /* Assume multidimensional charsets stay so. */
850 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
854 /* Japanese Kanji are a special case under w32, as they
855 must be printed in SJIS rather than EUC. */
856 else if ((charset
== charset_jisx0208
)
857 || (charset
== charset_jisx0208_1978
)
858 || (charset
== charset_id_internal ("japanese-jisx0212")))
861 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
863 ENCODE_SJIS (BYTE1 (*cp
), BYTE2 (*cp
), sjis1
, sjis2
);
864 *cp
= BUILD_WCHAR_T (sjis1
, sjis2
);
867 else if (fontp
->encoding
[charset
])
869 int enc
= fontp
->encoding
[charset
];
871 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
872 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
873 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
) | 0x80, BYTE2 (*cp
));
874 if (enc
== 1 || enc
== 3)
875 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
876 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
), BYTE2 (*cp
) | 0x80);
882 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
884 font
= FACE_FONT (face
);
885 if (!font
|| font
== (XFontStruct
*) FACE_DEFAULT
)
886 font
= FRAME_FONT (f
);
887 baseline
= FONT_BASE (FRAME_FONT (f
));
888 if (charset
== charset_latin_iso8859_1
)
890 if (font
->tm
.tmLastChar
< 0x80)
891 /* This font can't display Latin1 characters. */
895 for (cp
= x_2byte_buffer
;
896 cp
< x_2byte_buffer
+ len
; cp
++)
897 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
904 /* Convert x_2byte_buffer into a buffer of single byte
905 characters - possibly containing MBCS runs. */
907 for (i
= 0; i
< len
; i
++)
909 if (BYTE1 (*(x_2byte_buffer
+ i
)))
910 *bp
++ = BYTE1 (*(x_2byte_buffer
+ i
));
911 *bp
++ = BYTE2 (*(x_2byte_buffer
+ i
));
913 n_chars
= bp
- x_1byte_buffer
;
915 fg
= face
->foreground
;
916 bg
= face
->background
;
918 /* Now override that if the cursor's on this character. */
921 /* The cursor overrides stippling. */
924 if (font
== FRAME_FONT (f
)
925 && face
->background
== FRAME_BACKGROUND_PIXEL (f
)
926 && face
->foreground
== FRAME_FOREGROUND_PIXEL (f
)
929 bg
= f
->output_data
.w32
->cursor_pixel
;
930 fg
= face
->background
;
932 /* Cursor on non-default face: must merge. */
935 bg
= f
->output_data
.w32
->cursor_pixel
;
936 fg
= face
->background
;
937 /* If the glyph would be invisible,
938 try a different foreground. */
940 fg
= face
->foreground
;
942 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
944 fg
= face
->foreground
;
945 /* Make sure the cursor is distinct from text in this face. */
946 if (bg
== face
->background
947 && fg
== face
->foreground
)
949 bg
= face
->foreground
;
950 fg
= face
->background
;
956 require_clipping
= (!NILP (Vclip_large_size_font
)
957 && (font
->tm
.tmAscent
> baseline
958 || font
->tm
.tmDescent
>
959 line_height
- baseline
961 && FONT_MAX_WIDTH (font
) > glyph_width
)));
963 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
964 background_filled
= 1;
966 /* Stippling not supported under w32. */
969 || FONT_HEIGHT (font
) < line_height
970 || FONT_WIDTH (font
) < glyph_width
971 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
)
974 /* Fill in the background for the current run. */
975 w32_fill_area (f
, hdc
, bg
,
980 background_filled
= 1;
982 /* To assure not to fill background while drawing
983 remaining components. */
987 background_filled
= 0;
989 SetBkMode (hdc
, background_filled
? TRANSPARENT
: OPAQUE
);
990 SetTextColor (hdc
, fg
);
991 SetBkColor (hdc
, bg
);
993 if ( print_via_unicode
)
994 n_chars
= MultiByteToWideChar
995 (codepage
, 0, x_1byte_buffer
, n_chars
,
996 x_2byte_buffer
, FRAME_WINDOW_WIDTH (f
));
1000 SelectObject (hdc
, font
->hfont
);
1004 int multibyte_pos_offset
= 0;
1005 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
1006 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
))
1008 RECT clip_rectangle
;
1009 LPRECT clip_region
= NULL
;
1012 for (i
= 0; i
< n_chars
; i
++)
1014 if (require_clipping
)
1016 /* Set up a clipping rectangle for ExtTextOut */
1017 fuOptions
|= ETO_CLIPPED
;
1018 clip_rectangle
.left
= left
+ i
* glyph_width
;
1019 clip_rectangle
.right
1020 = left
+ (i
+ 1) * glyph_width
;
1021 clip_rectangle
.top
= top
;
1022 clip_rectangle
.bottom
= top
+ line_height
;
1023 clip_region
= &clip_rectangle
;
1026 /* baseline works differently on w32 than X,
1027 leave it out for now. */
1028 if (print_via_unicode
)
1029 ExtTextOutW (hdc
, left
+ glyph_width
* i
,
1030 top
/*+ baseline*/, fuOptions
,
1031 clip_region
, x_2byte_buffer
+ i
,
1033 else if (CHARSET_DIMENSION (charset
) > 1)
1035 /* Keep character together */
1036 int n
= CHARSET_DIMENSION (charset
) ;
1037 ExtTextOut (hdc
, left
+ multibyte_pos_offset
,
1038 top
/*+ baseline*/, fuOptions
,
1039 clip_region
, x_1byte_buffer
+ i
,
1043 multibyte_pos_offset
+= glyph_width
;
1046 ExtTextOut (hdc
, left
+ glyph_width
* i
,
1047 top
/*+ baseline*/, fuOptions
,
1048 clip_region
, x_1byte_buffer
+ i
,
1054 /* Print the whole run of characters. */
1055 if (print_via_unicode
)
1056 TextOutW (hdc
, left
, top
/*+ baseline*/,
1057 x_2byte_buffer
, n_chars
);
1059 TextOut (hdc
, left
, top
/*+ baseline*/,
1060 x_1byte_buffer
, n_chars
);
1065 /* Handle composite characters. */
1066 RECT clip_rectangle
;
1067 LPRECT clip_region
= NULL
;
1072 if (require_clipping
)
1074 /* Set up a clipping rectangle for ExtTextOut */
1075 fuOptions
|= ETO_CLIPPED
;
1076 clip_rectangle
.left
= left
;
1077 clip_rectangle
.right
= left
+ glyph_width
;
1078 clip_rectangle
.top
= top
;
1079 clip_rectangle
.bottom
= top
+ line_height
;
1080 clip_region
= &clip_rectangle
;
1082 if ((cmpcharp
->cmp_rule
|| relative_compose
)
1085 /* This is the first character. Initialize variables.
1086 HIGHEST is the highest position of glyphs ever
1087 written, LOWEST the lowest position. */
1091 && CHAR_TABLE_P (Vuse_default_ascent
)
1092 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
1094 highest
= default_ascent
;
1099 /* Per char metrics not supported on w32 - use
1101 highest
= font
->tm
.tmAscent
+ 1;
1102 lowest
= - font
->tm
.tmDescent
;
1105 if (cmpcharp
->cmp_rule
)
1106 x_offset
= (cmpcharp
->col_offset
[0]
1107 * FONT_WIDTH (FRAME_FONT (f
)));
1111 /* Truetype fonts often contain underhangs to
1112 handle composition characters. This works
1113 against our attempts to position the characters
1114 manually, so we need to compensate for this.
1116 if (print_via_unicode
?
1117 GetCharABCWidthsW (hdc
, *x_2byte_buffer
,
1120 : GetCharABCWidths (hdc
, *x_1byte_buffer
,
1124 char_width
= char_placement
.abcA
1125 + char_placement
.abcB
+ char_placement
.abcC
;
1126 x_offset
+= FONT_WIDTH (font
) - char_width
;
1128 /* Don't let characters go beyond the glyph
1129 boundary whatever their over/underhangs. */
1130 if (x_offset
> glyph_width
- char_width
)
1131 x_offset
= glyph_width
- char_width
;
1136 /* Draw the first character at the normal position. */
1137 if (print_via_unicode
)
1138 ExtTextOutW (hdc
, left
+ x_offset
,
1140 fuOptions
, clip_region
,
1141 x_2byte_buffer
, 1, NULL
);
1142 else if (CHARSET_DIMENSION (charset
) > 1)
1144 /* Keep character together */
1145 int n
= CHARSET_DIMENSION (charset
) ;
1146 ExtTextOut (hdc
, left
+ x_offset
,
1148 fuOptions
, clip_region
,
1149 x_1byte_buffer
, n
, NULL
);
1154 ExtTextOut (hdc
, left
+ x_offset
,
1156 fuOptions
, clip_region
,
1157 x_1byte_buffer
, 1, NULL
);
1163 for (; i
< n_chars
; i
++, gidx
++)
1165 int x_offset
= 0, y_offset
= 0;
1167 if (relative_compose
)
1169 /* No per char metrics on w32. */
1170 if (NILP (Vignore_relative_composition
)
1171 || NILP (Faref (Vignore_relative_composition
,
1172 make_number (cmpcharp
->glyph
[gidx
]))))
1174 if (- font
->tm
.tmDescent
>= relative_compose
)
1176 /* Draw above the current glyphs. */
1177 y_offset
= highest
+ font
->tm
.tmDescent
;
1178 highest
+= font
->tm
.tmAscent
1179 + font
->tm
.tmDescent
;
1181 else if (font
->tm
.tmAscent
<= 0)
1183 /* Draw beneath the current glyphs. */
1184 y_offset
= lowest
- font
->tm
.tmAscent
;
1185 lowest
-= font
->tm
.tmAscent
1186 + font
->tm
.tmDescent
;
1191 /* Draw the glyph at normal position. If
1192 it sticks out of HIGHEST or LOWEST,
1193 update them appropriately. */
1194 if (font
->tm
.tmAscent
> highest
)
1195 highest
= font
->tm
.tmAscent
;
1196 else if (- font
->tm
.tmDescent
< lowest
)
1197 lowest
= - font
->tm
.tmDescent
;
1200 else if (cmpcharp
->cmp_rule
)
1202 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1203 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1206 /* Re-encode GREF and NREF so that they specify
1207 only Y-axis information:
1208 0:top, 1:base, 2:bottom, 3:center */
1209 gref
= gref
/ 3 + (gref
== 4) * 2;
1210 nref
= nref
/ 3 + (nref
== 4) * 2;
1212 /* No per char metrics on w32. */
1213 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1214 : gref
== 2 ? lowest
1215 : (highest
+ lowest
) / 2)
1216 - (nref
== 0 ? font
->tm
.tmAscent
1217 + font
->tm
.tmDescent
1218 : nref
== 1 ? font
->tm
.tmDescent
1220 : (font
->tm
.tmAscent
+
1221 font
->tm
.tmDescent
) / 2));
1222 top
= bottom
+ (font
->tm
.tmAscent
+
1223 font
->tm
.tmDescent
);
1226 if (bottom
< lowest
)
1228 y_offset
= bottom
+ font
->tm
.tmDescent
;
1229 x_offset
= (cmpcharp
->col_offset
[gidx
]
1230 * FONT_WIDTH (FRAME_FONT(f
)));
1233 /* Truetype fonts often contain underhangs to
1234 handle composition characters. This works
1235 against our attempts to position the characters
1236 manually, so we need to compensate for this.
1238 if (print_via_unicode
?
1239 GetCharABCWidthsW (hdc
, *(x_2byte_buffer
+ i
),
1240 *(x_2byte_buffer
+ i
),
1242 : GetCharABCWidths (hdc
, *(x_1byte_buffer
+ i
),
1243 *(x_1byte_buffer
+ i
),
1246 char_width
= char_placement
.abcA
1247 + char_placement
.abcB
+ char_placement
.abcC
;
1248 x_offset
+= FONT_WIDTH (font
) - char_width
;
1250 /* Don't let characters go beyond the glyph
1251 boundary whatever their over/underhangs. */
1252 if (x_offset
> glyph_width
- char_width
)
1253 x_offset
= glyph_width
- char_width
;
1258 if (print_via_unicode
)
1259 ExtTextOutW (hdc
, left
+ x_offset
,
1260 top
/*+ baseline - y_offset*/,
1261 fuOptions
, clip_region
,
1262 x_2byte_buffer
+ i
, 1, NULL
);
1263 else if (CHARSET_DIMENSION (charset
) > 1)
1265 /* Keep character together */
1266 int n
= CHARSET_DIMENSION (charset
) ;
1267 ExtTextOut (hdc
, left
+ x_offset
,
1268 top
/*+ baseline - y_offset*/,
1269 fuOptions
, clip_region
,
1270 x_1byte_buffer
+ i
, n
, NULL
);
1275 ExtTextOut (hdc
, left
+ x_offset
,
1276 top
/*+ baseline - y_offset*/,
1277 fuOptions
, clip_region
,
1278 x_1byte_buffer
+ i
, 1, NULL
);
1284 /* Show rectangles to indicate that we found no font. */
1285 int limit
= cmpcharp
? 1 : len
;
1287 for (i
= 0; i
< limit
; i
++)
1288 Rectangle (hdc
, left
+ glyph_width
* i
, top
,
1289 left
+ glyph_width
* (i
+ 1) - 1,
1290 top
+ line_height
- 1);
1292 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1294 /* Indicate that we found a font of inappropriate size. */
1295 int limit
= cmpcharp
? 1 : len
;
1297 for (i
= 0; i
< limit
; i
++)
1299 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1300 top
+ line_height
- 1, glyph_width
, 1);
1301 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1302 top
+ line_height
- 3, 1, 2);
1306 /* Setting underline position based on the metric of the
1307 current font results in shaky underline if it strides
1308 over different fonts. So, we set the position based only
1309 on the default font of this frame. */
1310 int underline_position
= 1;
1312 if (FRAME_FONT (f
)->tm
.tmDescent
<= underline_position
)
1313 underline_position
= FRAME_FONT (f
)->tm
.tmDescent
- 1;
1315 if (face
->underline
)
1316 w32_fill_area (f
, hdc
, fg
, left
,
1317 top
+ FONT_BASE (FRAME_FONT (f
))
1318 + underline_position
,
1326 release_frame_dc (f
, hdc
);
1328 return (left
- orig_left
);
1332 /* Output some text at the nominal frame cursor position.
1333 Advance the cursor over the text.
1334 Output LEN glyphs at START.
1336 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
1337 controls the pixel values used for foreground and background. */
1340 w32_write_glyphs (start
, len
)
1341 register GLYPH
*start
;
1344 register int temp_length
;
1354 /* If not within an update,
1355 output at the frame's visible cursor. */
1356 curs_x
= f
->cursor_x
;
1357 curs_y
= f
->cursor_y
;
1361 CHAR_TO_PIXEL_COL (f
, curs_x
),
1362 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1363 start
, len
, highlight
, 0, NULL
);
1365 /* If we drew on top of the cursor, note that it is turned off. */
1366 if (curs_y
== f
->phys_cursor_y
1367 && curs_x
<= f
->phys_cursor_x
1368 && curs_x
+ len
> f
->phys_cursor_x
)
1369 f
->phys_cursor_x
= -1;
1371 if (updating_frame
== 0)
1374 x_display_cursor (f
, 1);
1383 /* Clear to the end of the line.
1384 Erase the current text line from the nominal cursor position (inclusive)
1385 to column FIRST_UNUSED (exclusive). The idea is that everything
1386 from FIRST_UNUSED onward is already erased. */
1389 w32_clear_end_of_line (first_unused
)
1390 register int first_unused
;
1392 struct frame
*f
= updating_frame
;
1397 if (curs_y
< 0 || curs_y
>= f
->height
)
1399 if (first_unused
<= 0)
1402 if (first_unused
>= f
->width
)
1403 first_unused
= f
->width
;
1405 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1411 /* Notice if the cursor will be cleared by this operation. */
1412 if (curs_y
== f
->phys_cursor_y
1413 && curs_x
<= f
->phys_cursor_x
1414 && f
->phys_cursor_x
< first_unused
)
1415 f
->phys_cursor_x
= -1;
1417 w32_clear_area (f
, NULL
,
1418 CHAR_TO_PIXEL_COL (f
, curs_x
),
1419 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1420 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
1421 f
->output_data
.w32
->line_height
);
1429 struct frame
*f
= updating_frame
;
1434 f
->phys_cursor_x
= -1; /* Cursor not visible. */
1435 curs_x
= 0; /* Nominal cursor position is top left. */
1440 w32_clear_window (f
);
1442 /* We have to clear the scroll bars, too. If we have changed
1443 colors or something like that, then they should be notified. */
1444 x_scroll_bar_clear (f
);
1449 /* Make audible bell. */
1452 w32_ring_bell (void)
1459 HWND hwnd
= FRAME_W32_WINDOW (selected_frame
);
1461 for (i
= 0; i
< 5; i
++)
1463 FlashWindow (hwnd
, TRUE
);
1466 FlashWindow (hwnd
, FALSE
);
1469 w32_sys_ring_bell ();
1474 /* Insert and delete character.
1475 These are not supposed to be used because we are supposed to turn
1476 off the feature of using them. */
1479 w32_insert_glyphs (start
, len
)
1480 register GLYPH
*start
;
1487 w32_delete_glyphs (n
)
1493 /* Specify how many text lines, from the top of the window,
1494 should be affected by insert-lines and delete-lines operations.
1495 This, and those operations, are used only within an update
1496 that is bounded by calls to w32_update_begin and w32_update_end. */
1499 w32_set_terminal_window (n
)
1502 if (updating_frame
== 0)
1505 if ((n
<= 0) || (n
> updating_frame
->height
))
1506 flexlines
= updating_frame
->height
;
1511 /* These variables need not be per frame
1512 because redisplay is done on a frame-by-frame basis
1513 and the line dance for one frame is finished before
1514 anything is done for another frame. */
1516 /* Array of line numbers from cached insert/delete operations.
1517 line_dance[i] is the old position of the line that we want
1518 to move to line i, or -1 if we want a blank line there. */
1519 static int *line_dance
;
1521 /* Allocated length of that array. */
1522 static int line_dance_len
;
1524 /* Flag indicating whether we've done any work. */
1525 static int line_dance_in_progress
;
1527 /* Perform an insert-lines or delete-lines operation,
1528 inserting N lines or deleting -N lines at vertical position VPOS. */
1531 w32_ins_del_lines (vpos
, n
)
1534 register int fence
, i
;
1536 if (vpos
>= flexlines
)
1539 if (!line_dance_in_progress
)
1541 int ht
= updating_frame
->height
;
1542 if (ht
> line_dance_len
)
1544 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1545 line_dance_len
= ht
;
1547 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1548 line_dance_in_progress
= 1;
1552 if (n
> flexlines
- vpos
)
1553 n
= flexlines
- vpos
;
1555 for (i
= flexlines
; --i
>= fence
;)
1556 line_dance
[i
] = line_dance
[i
-n
];
1557 for (i
= fence
; --i
>= vpos
;)
1563 if (n
> flexlines
- vpos
)
1564 n
= flexlines
- vpos
;
1565 fence
= flexlines
- n
;
1566 for (i
= vpos
; i
< fence
; ++i
)
1567 line_dance
[i
] = line_dance
[i
+ n
];
1568 for (i
= fence
; i
< flexlines
; ++i
)
1573 /* Here's where we actually move the pixels around.
1574 Must be called with input blocked. */
1578 register int i
, j
, distance
;
1579 register struct frame
*f
;
1584 /* Must check this flag first. If it's not set, then not only is the
1585 array uninitialized, but we might not even have a frame. */
1586 if (!line_dance_in_progress
)
1594 intborder
= f
->output_data
.w32
->internal_border_width
;
1596 x_display_cursor (updating_frame
, 0);
1598 hdc
= get_frame_dc (f
);
1600 for (i
= 0; i
< ht
; ++i
)
1601 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1603 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1604 && line_dance
[j
]-j
== distance
); ++j
);
1605 /* Copy [i,j) upward from [i+distance, j+distance) */
1607 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1608 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1609 (j
-i
) * f
->output_data
.w32
->line_height
,
1611 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1616 for (i
= ht
; --i
>=0; )
1617 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1619 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1620 && line_dance
[j
]-j
== distance
););
1621 /* Copy (j, i] downward from (j+distance, i+distance] */
1623 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1624 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1625 (i
-j
) * f
->output_data
.w32
->line_height
,
1627 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1632 for (i
= 0; i
< ht
; ++i
)
1633 if (line_dance
[i
] == -1)
1635 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1637 w32_clear_area (f
, hdc
,
1639 CHAR_TO_PIXEL_ROW (f
, i
),
1640 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1641 (j
-i
) * f
->output_data
.w32
->line_height
);
1644 line_dance_in_progress
= 0;
1646 release_frame_dc (f
, hdc
);
1649 /* Support routines for exposure events. */
1650 static void clear_cursor ();
1652 /* Output into a rectangle of a window (for frame F)
1653 the characters in f->phys_lines that overlap that rectangle.
1654 TOP and LEFT are the position of the upper left corner of the rectangle.
1655 ROWS and COLS are the size of the rectangle.
1656 Call this function with input blocked. */
1659 dumprectangle (f
, left
, top
, cols
, rows
)
1661 register int left
, top
, cols
, rows
;
1663 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1664 int cursor_cleared
= 0;
1668 if (FRAME_GARBAGED_P (f
))
1671 /* Express rectangle as four edges, instead of position-and-size. */
1672 bottom
= top
+ rows
;
1673 right
= left
+ cols
;
1675 /* Convert rectangle edges in pixels to edges in chars.
1676 Round down for left and top, up for right and bottom. */
1677 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1678 left
= PIXEL_TO_CHAR_COL (f
, left
);
1679 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1680 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1681 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1682 right
= PIXEL_TO_CHAR_COL (f
, right
);
1684 /* Clip the rectangle to what can be visible. */
1689 if (right
> f
->width
)
1691 if (bottom
> f
->height
)
1694 /* Get size in chars of the rectangle. */
1695 cols
= right
- left
;
1696 rows
= bottom
- top
;
1698 /* If rectangle has zero area, return. */
1699 if (rows
<= 0) return;
1700 if (cols
<= 0) return;
1702 /* Turn off the cursor if it is in the rectangle.
1703 We will turn it back on afterward. */
1704 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1705 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1711 /* Display the text in the rectangle, one text line at a time. */
1713 for (y
= top
; y
< bottom
; y
++)
1715 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1717 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1721 CHAR_TO_PIXEL_COL (f
, left
),
1722 CHAR_TO_PIXEL_ROW (f
, y
),
1723 line
, min (cols
, active_frame
->used
[y
] - left
),
1724 active_frame
->highlight
[y
], 0, NULL
);
1727 /* Turn the cursor on if we turned it off. */
1730 x_display_cursor (f
, 1);
1737 x_display_cursor (f
, 1);
1741 frame_unhighlight (f
)
1744 x_display_cursor (f
, 1);
1747 static void x_frame_rehighlight ();
1749 /* The focus has changed. Update the frames as necessary to reflect
1750 the new situation. Note that we can't change the selected frame
1751 here, because the Lisp code we are interrupting might become confused.
1752 Each event gets marked with the frame in which it occurred, so the
1753 Lisp code can tell when the switch took place by examining the events. */
1756 x_new_focus_frame (dpyinfo
, frame
)
1757 struct w32_display_info
*dpyinfo
;
1758 struct frame
*frame
;
1760 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1761 int events_enqueued
= 0;
1763 if (frame
!= dpyinfo
->w32_focus_frame
)
1765 /* Set this before calling other routines, so that they see
1766 the correct value of w32_focus_frame. */
1767 dpyinfo
->w32_focus_frame
= frame
;
1769 if (old_focus
&& old_focus
->auto_lower
)
1770 x_lower_frame (old_focus
);
1772 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1773 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1775 pending_autoraise_frame
= 0;
1778 x_frame_rehighlight (dpyinfo
);
1781 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1784 x_mouse_leave (dpyinfo
)
1785 struct w32_display_info
*dpyinfo
;
1787 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1790 /* The focus has changed, or we have redirected a frame's focus to
1791 another frame (this happens when a frame uses a surrogate
1792 minibuffer frame). Shift the highlight as appropriate.
1794 The FRAME argument doesn't necessarily have anything to do with which
1795 frame is being highlighted or unhighlighted; we only use it to find
1796 the appropriate display info. */
1798 w32_frame_rehighlight (frame
)
1799 struct frame
*frame
;
1801 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1805 x_frame_rehighlight (dpyinfo
)
1806 struct w32_display_info
*dpyinfo
;
1808 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1810 if (dpyinfo
->w32_focus_frame
)
1812 dpyinfo
->w32_highlight_frame
1813 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1814 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1815 : dpyinfo
->w32_focus_frame
);
1816 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1818 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1819 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1823 dpyinfo
->w32_highlight_frame
= 0;
1825 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1828 frame_unhighlight (old_highlight
);
1829 if (dpyinfo
->w32_highlight_frame
)
1830 frame_highlight (dpyinfo
->w32_highlight_frame
);
1834 /* Keyboard processing - modifier keys, etc. */
1836 /* Convert a keysym to its name. */
1839 x_get_keysym_name (keysym
)
1842 /* Make static so we can always return it */
1843 static char value
[100];
1846 GetKeyNameText(keysym
, value
, 100);
1852 /* Mouse clicks and mouse movement. Rah. */
1854 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1855 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1856 that the glyph at X, Y occupies, if BOUNDS != 0.
1857 If NOCLIP is nonzero, do not force the value into range. */
1860 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1862 register int pix_x
, pix_y
;
1863 register int *x
, *y
;
1867 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1868 if (NILP (Vwindow_system
))
1875 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1876 even for negative values. */
1878 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1880 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1882 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1883 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1887 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1888 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1889 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1890 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1897 else if (pix_x
> f
->width
)
1902 else if (pix_y
> f
->height
)
1911 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1914 register int *pix_x
, *pix_y
;
1916 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1917 if (NILP (Vwindow_system
))
1924 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1925 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1929 parse_button (message
, pbutton
, pup
)
1939 case WM_LBUTTONDOWN
:
1947 case WM_MBUTTONDOWN
:
1948 if (NILP (Vw32_swap_mouse_buttons
))
1955 if (NILP (Vw32_swap_mouse_buttons
))
1961 case WM_RBUTTONDOWN
:
1962 if (NILP (Vw32_swap_mouse_buttons
))
1969 if (NILP (Vw32_swap_mouse_buttons
))
1980 if (pbutton
) *pbutton
= button
;
1986 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1988 If the event is a button press, then note that we have grabbed
1992 construct_mouse_click (result
, msg
, f
)
1993 struct input_event
*result
;
2000 parse_button (msg
->msg
.message
, &button
, &up
);
2002 /* Make the event type no_event; we'll change that when we decide
2004 result
->kind
= mouse_click
;
2005 result
->code
= button
;
2006 result
->timestamp
= msg
->msg
.time
;
2007 result
->modifiers
= (msg
->dwModifiers
2015 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
2016 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
2017 XSETFRAME (result
->frame_or_window
, f
);
2022 construct_mouse_wheel (result
, msg
, f
)
2023 struct input_event
*result
;
2028 result
->kind
= mouse_wheel
;
2029 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
2030 result
->timestamp
= msg
->msg
.time
;
2031 result
->modifiers
= msg
->dwModifiers
;
2032 p
.x
= LOWORD (msg
->msg
.lParam
);
2033 p
.y
= HIWORD (msg
->msg
.lParam
);
2034 ScreenToClient(msg
->msg
.hwnd
, &p
);
2035 XSETINT (result
->x
, p
.x
);
2036 XSETINT (result
->y
, p
.y
);
2037 XSETFRAME (result
->frame_or_window
, f
);
2041 construct_drag_n_drop (result
, msg
, f
)
2042 struct input_event
*result
;
2054 result
->kind
= drag_n_drop
;
2056 result
->timestamp
= msg
->msg
.time
;
2057 result
->modifiers
= msg
->dwModifiers
;
2059 p
.x
= LOWORD (msg
->msg
.lParam
);
2060 p
.y
= HIWORD (msg
->msg
.lParam
);
2061 ScreenToClient (msg
->msg
.hwnd
, &p
);
2062 XSETINT (result
->x
, p
.x
);
2063 XSETINT (result
->y
, p
.y
);
2065 hdrop
= (HDROP
) msg
->msg
.wParam
;
2066 DragQueryPoint (hdrop
, &p
);
2067 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
2070 for (i
= 0; i
< num_files
; i
++)
2072 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
2075 name
= alloca (len
+ 1);
2076 DragQueryFile (hdrop
, i
, name
, len
+ 1);
2077 files
= Fcons (build_string (name
), files
);
2082 XSETFRAME (frame
, f
);
2083 result
->frame_or_window
= Fcons (frame
, files
);
2087 /* Function to report a mouse movement to the mainstream Emacs code.
2088 The input handler calls this.
2090 We have received a mouse movement event, which is given in *event.
2091 If the mouse is over a different glyph than it was last time, tell
2092 the mainstream emacs code by setting mouse_moved. If not, ask for
2093 another motion event, so we can check again the next time it moves. */
2096 note_mouse_movement (frame
, msg
)
2100 last_mouse_movement_time
= msg
->time
;
2102 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
2104 frame
->mouse_moved
= 1;
2105 last_mouse_scroll_bar
= Qnil
;
2107 note_mouse_highlight (frame
, -1, -1);
2110 /* Has the mouse moved off the glyph it was on at the last sighting? */
2111 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
2112 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
2113 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
2114 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
2116 frame
->mouse_moved
= 1;
2117 last_mouse_scroll_bar
= Qnil
;
2119 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
2123 /* This is used for debugging, to turn off note_mouse_highlight. */
2124 static int disable_mouse_highlight
;
2126 /* Take proper action when the mouse has moved to position X, Y on frame F
2127 as regards highlighting characters that have mouse-face properties.
2128 Also dehighlighting chars where the mouse was before.
2129 X and Y can be negative or out of range. */
2132 note_mouse_highlight (f
, x
, y
)
2136 int row
, column
, portion
;
2141 if (disable_mouse_highlight
)
2144 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2145 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2146 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2148 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
2153 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2157 /* Find out which glyph the mouse is on. */
2158 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2159 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
2161 /* Which window is that in? */
2162 window
= window_from_coordinates (f
, column
, row
, &portion
);
2163 w
= XWINDOW (window
);
2165 /* If we were displaying active text in another window, clear that. */
2166 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
2167 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2169 /* Are we in a window whose display is up to date?
2170 And verify the buffer's text has not changed. */
2171 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2172 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2173 && EQ (w
->window_end_valid
, w
->buffer
)
2174 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2175 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2177 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2180 /* Find which buffer position the mouse corresponds to. */
2181 for (i
= column
; i
>= 0; i
--)
2185 /* Is it outside the displayed active region (if any)? */
2187 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2188 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
2189 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2190 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2191 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2192 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2193 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2194 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2195 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2197 Lisp_Object mouse_face
, overlay
, position
;
2198 Lisp_Object
*overlay_vec
;
2199 int len
, noverlays
, ignor1
;
2200 struct buffer
*obuf
;
2203 /* If we get an out-of-range value, return now; avoid an error. */
2204 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2207 /* Make the window's buffer temporarily current for
2208 overlays_at and compute_char_face. */
2209 obuf
= current_buffer
;
2210 current_buffer
= XBUFFER (w
->buffer
);
2216 /* Yes. Clear the display of the old active region, if any. */
2217 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2219 /* Is this char mouse-active? */
2220 XSETINT (position
, pos
);
2223 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2225 /* Put all the overlays we want in a vector in overlay_vec.
2226 Store the length in len. */
2227 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2229 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2231 /* Find the highest priority overlay that has a mouse-face prop. */
2233 for (i
= 0; i
< noverlays
; i
++)
2235 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2236 if (!NILP (mouse_face
))
2238 overlay
= overlay_vec
[i
];
2243 /* If no overlay applies, get a text property. */
2245 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2247 /* Handle the overlay case. */
2248 if (! NILP (overlay
))
2250 /* Find the range of text around this char that
2251 should be active. */
2252 Lisp_Object before
, after
;
2255 before
= Foverlay_start (overlay
);
2256 after
= Foverlay_end (overlay
);
2257 /* Record this as the current active region. */
2258 fast_find_position (window
, before
,
2259 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2260 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2261 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2262 = !fast_find_position (window
, after
,
2263 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2264 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2265 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2266 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2267 = compute_char_face (f
, w
, pos
, 0, 0,
2268 &ignore
, pos
+ 1, 1);
2270 /* Display it as active. */
2271 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2273 /* Handle the text property case. */
2274 else if (! NILP (mouse_face
))
2276 /* Find the range of text around this char that
2277 should be active. */
2278 Lisp_Object before
, after
, beginning
, end
;
2281 beginning
= Fmarker_position (w
->start
);
2282 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2283 - XFASTINT (w
->window_end_pos
)));
2285 = Fprevious_single_property_change (make_number (pos
+ 1),
2287 w
->buffer
, beginning
);
2289 = Fnext_single_property_change (position
, Qmouse_face
,
2291 /* Record this as the current active region. */
2292 fast_find_position (window
, before
,
2293 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2294 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2295 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2296 = !fast_find_position (window
, after
,
2297 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2298 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2299 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2300 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2301 = compute_char_face (f
, w
, pos
, 0, 0,
2302 &ignore
, pos
+ 1, 1);
2304 /* Display it as active. */
2305 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2309 current_buffer
= obuf
;
2314 /* Find the row and column of position POS in window WINDOW.
2315 Store them in *COLUMNP and *ROWP.
2316 This assumes display in WINDOW is up to date.
2317 If POS is above start of WINDOW, return coords
2318 of start of first screen line.
2319 If POS is after end of WINDOW, return coords of end of last screen line.
2321 Value is 1 if POS is in range, 0 if it was off screen. */
2324 fast_find_position (window
, pos
, columnp
, rowp
)
2327 int *columnp
, *rowp
;
2329 struct window
*w
= XWINDOW (window
);
2330 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2333 int left
= WINDOW_LEFT_MARGIN (w
);
2335 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2336 int width
= window_internal_width (w
);
2339 int maybe_next_line
= 0;
2341 /* Find the right row. */
2346 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2347 if (linestart
> pos
)
2349 /* If the position sought is the end of the buffer,
2350 don't include the blank lines at the bottom of the window. */
2351 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2353 maybe_next_line
= 1;
2360 /* Find the right column with in it. */
2361 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2363 for (i
= 0; i
< width
; i
++)
2365 if (charstarts
[left
+ i
] == pos
)
2368 *columnp
= i
+ left
;
2371 else if (charstarts
[left
+ i
] > pos
)
2373 else if (charstarts
[left
+ i
] > 0)
2377 /* If we're looking for the end of the buffer,
2378 and we didn't find it in the line we scanned,
2379 use the start of the following line. */
2380 if (maybe_next_line
)
2391 /* Display the active region described by mouse_face_*
2392 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2395 show_mouse_face (dpyinfo
, hl
)
2396 struct w32_display_info
*dpyinfo
;
2399 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2400 int width
= window_internal_width (w
);
2401 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2404 int old_curs_x
= curs_x
;
2405 int old_curs_y
= curs_y
;
2407 /* Set these variables temporarily
2408 so that if we have to turn the cursor off and on again
2409 we will put it back at the same place. */
2410 curs_x
= f
->phys_cursor_x
;
2411 curs_y
= f
->phys_cursor_y
;
2413 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2414 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2416 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2417 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
2418 : WINDOW_LEFT_MARGIN (w
));
2419 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2420 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2421 : WINDOW_LEFT_MARGIN (w
) + width
);
2422 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2424 /* If the cursor's in the text we are about to rewrite,
2425 turn the cursor off. */
2427 && curs_x
>= column
- 1
2428 && curs_x
<= endcolumn
)
2430 x_display_cursor (f
, 0);
2435 CHAR_TO_PIXEL_COL (f
, column
),
2436 CHAR_TO_PIXEL_ROW (f
, i
),
2437 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2439 /* Highlight with mouse face if hl > 0. */
2440 hl
> 0 ? 3 : 0, 0, NULL
);
2443 /* If we turned the cursor off, turn it back on. */
2445 x_display_cursor (f
, 1);
2447 curs_x
= old_curs_x
;
2448 curs_y
= old_curs_y
;
2450 /* Change the mouse cursor according to the value of HL. */
2452 SetCursor (f
->output_data
.w32
->cross_cursor
);
2454 SetCursor (f
->output_data
.w32
->text_cursor
);
2457 /* Clear out the mouse-highlighted active region.
2458 Redraw it unhighlighted first. */
2461 clear_mouse_face (dpyinfo
)
2462 struct w32_display_info
*dpyinfo
;
2464 if (! NILP (dpyinfo
->mouse_face_window
))
2465 show_mouse_face (dpyinfo
, 0);
2467 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2468 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2469 dpyinfo
->mouse_face_window
= Qnil
;
2472 struct scroll_bar
*x_window_to_scroll_bar ();
2473 static void x_scroll_bar_report_motion ();
2475 /* Return the current position of the mouse.
2476 *fp should be a frame which indicates which display to ask about.
2478 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2479 and *part to the frame, window, and scroll bar part that the mouse
2480 is over. Set *x and *y to the portion and whole of the mouse's
2481 position on the scroll bar.
2483 If the mouse movement started elsewhere, set *fp to the frame the
2484 mouse is on, *bar_window to nil, and *x and *y to the character cell
2487 Set *time to the server timestamp for the time at which the mouse
2488 was at this position.
2490 Don't store anything if we don't have a valid set of values to report.
2492 This clears the mouse_moved flag, so we can wait for the next mouse
2493 movement. This also calls XQueryPointer, which will cause the
2494 server to give us another MotionNotify when the mouse moves
2498 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2501 Lisp_Object
*bar_window
;
2502 enum scroll_bar_part
*part
;
2504 unsigned long *time
;
2510 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2511 /* This is never called at the moment. */
2512 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2517 Lisp_Object frame
, tail
;
2519 /* Clear the mouse-moved flag for every frame on this display. */
2520 FOR_EACH_FRAME (tail
, frame
)
2521 XFRAME (frame
)->mouse_moved
= 0;
2523 last_mouse_scroll_bar
= Qnil
;
2527 /* Now we have a position on the root; find the innermost window
2528 containing the pointer. */
2530 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2531 && FRAME_LIVE_P (last_mouse_frame
))
2533 f1
= last_mouse_frame
;
2537 /* Is win one of our frames? */
2538 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
2541 /* If not, is it one of our scroll bars? */
2544 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
2548 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2552 if (f1
== 0 && insist
> 0)
2553 f1
= selected_frame
;
2557 int ignore1
, ignore2
;
2559 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
2561 /* Ok, we found a frame. Store all the values. */
2563 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
2565 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
2573 *time
= last_mouse_movement_time
;
2581 /* Scroll bar support. */
2583 /* Given an window ID, find the struct scroll_bar which manages it.
2584 This can be called in GC, so we have to make sure to strip off mark
2587 x_window_to_scroll_bar (window_id
)
2590 Lisp_Object tail
, frame
;
2592 for (tail
= Vframe_list
;
2593 XGCTYPE (tail
) == Lisp_Cons
;
2594 tail
= XCONS (tail
)->cdr
)
2596 Lisp_Object frame
, bar
, condemned
;
2598 frame
= XCONS (tail
)->car
;
2599 /* All elements of Vframe_list should be frames. */
2600 if (! GC_FRAMEP (frame
))
2603 /* Scan this frame's scroll bar list for a scroll bar with the
2605 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2606 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2607 /* This trick allows us to search both the ordinary and
2608 condemned scroll bar lists with one loop. */
2609 ! GC_NILP (bar
) || (bar
= condemned
,
2612 bar
= XSCROLL_BAR (bar
)->next
)
2613 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2614 return XSCROLL_BAR (bar
);
2621 my_create_scrollbar (f
, bar
)
2623 struct scroll_bar
* bar
;
2625 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2626 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2630 //#define ATTACH_THREADS
2633 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2635 #ifndef ATTACH_THREADS
2636 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2637 (WPARAM
) hwnd
, (LPARAM
) how
);
2639 return ShowWindow (hwnd
, how
);
2644 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2645 int x
, int y
, int cx
, int cy
, UINT flags
)
2647 #ifndef ATTACH_THREADS
2649 pos
.hwndInsertAfter
= hwndAfter
;
2655 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2657 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2662 my_set_focus (f
, hwnd
)
2666 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2671 my_set_foreground_window (hwnd
)
2674 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2678 my_destroy_window (f
, hwnd
)
2682 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2686 /* Open a new window to serve as a scroll bar, and return the
2687 scroll bar vector for it. */
2688 static struct scroll_bar
*
2689 x_scroll_bar_create (window
, top
, left
, width
, height
)
2690 struct window
*window
;
2691 int top
, left
, width
, height
;
2693 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2694 struct scroll_bar
*bar
2695 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2700 XSETWINDOW (bar
->window
, window
);
2701 XSETINT (bar
->top
, top
);
2702 XSETINT (bar
->left
, left
);
2703 XSETINT (bar
->width
, width
);
2704 XSETINT (bar
->height
, height
);
2705 XSETINT (bar
->start
, 0);
2706 XSETINT (bar
->end
, 0);
2707 bar
->dragging
= Qnil
;
2709 /* Requires geometry to be set before call to create the real window */
2711 hwnd
= my_create_scrollbar (f
, bar
);
2713 if (pfnSetScrollInfo
)
2717 si
.cbSize
= sizeof (si
);
2720 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2721 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2725 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2729 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2730 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2733 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2735 /* Add bar to its frame's list of scroll bars. */
2736 bar
->next
= FRAME_SCROLL_BARS (f
);
2738 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2739 if (! NILP (bar
->next
))
2740 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2747 /* Draw BAR's handle in the proper position.
2748 If the handle is already drawn from START to END, don't bother
2749 redrawing it, unless REBUILD is non-zero; in that case, always
2750 redraw it. (REBUILD is handy for drawing the handle after expose
2753 Normally, we want to constrain the start and end of the handle to
2754 fit inside its rectangle, but if the user is dragging the scroll bar
2755 handle, we want to let them drag it down all the way, so that the
2756 bar's top is as far down as it goes; otherwise, there's no way to
2757 move to the very end of the buffer. */
2759 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2760 struct scroll_bar
*bar
;
2764 int dragging
= ! NILP (bar
->dragging
);
2765 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2766 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2768 /* If the display is already accurate, do nothing. */
2770 && start
== XINT (bar
->start
)
2771 && end
== XINT (bar
->end
))
2777 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2779 /* Make sure the values are reasonable, and try to preserve
2780 the distance between start and end. */
2782 int length
= end
- start
;
2786 else if (start
> top_range
)
2788 end
= start
+ length
;
2792 else if (end
> top_range
&& ! dragging
)
2797 /* Store the adjusted setting in the scroll bar. */
2798 XSETINT (bar
->start
, start
);
2799 XSETINT (bar
->end
, end
);
2801 /* If being dragged, let scroll bar update itself. */
2804 if (pfnSetScrollInfo
)
2808 si
.cbSize
= sizeof (si
);
2809 si
.fMask
= SIF_PAGE
| SIF_POS
;
2810 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2813 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2816 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2822 /* Move a scroll bar around on the screen, to accommodate changing
2823 window configurations. */
2825 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2826 struct scroll_bar
*bar
;
2827 int top
, left
, width
, height
;
2829 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2830 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2832 /* If already correctly positioned, do nothing. */
2833 if ( XINT (bar
->left
) == left
2834 && XINT (bar
->top
) == top
2835 && XINT (bar
->width
) == width
2836 && XINT (bar
->height
) == height
)
2838 /* Redraw after clear_frame. */
2839 if (!my_show_window (f
, w
, SW_NORMAL
))
2840 InvalidateRect (w
, NULL
, FALSE
);
2846 /* Make sure scroll bar is "visible" before moving, to ensure the
2847 area of the parent window now exposed will be refreshed. */
2848 my_show_window (f
, w
, SW_HIDE
);
2849 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2850 if (pfnSetScrollInfo
)
2854 si
.cbSize
= sizeof (si
);
2855 si
.fMask
= SIF_RANGE
;
2857 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2858 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2860 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2863 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2864 my_show_window (f
, w
, SW_NORMAL
);
2865 // InvalidateRect (w, NULL, FALSE);
2867 XSETINT (bar
->left
, left
);
2868 XSETINT (bar
->top
, top
);
2869 XSETINT (bar
->width
, width
);
2870 XSETINT (bar
->height
, height
);
2875 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2878 x_scroll_bar_remove (bar
)
2879 struct scroll_bar
*bar
;
2881 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2885 /* Destroy the window. */
2886 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2888 /* Disassociate this scroll bar from its window. */
2889 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2894 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2895 that we are displaying PORTION characters out of a total of WHOLE
2896 characters, starting at POSITION. If WINDOW has no scroll bar,
2899 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2900 struct window
*window
;
2901 int portion
, whole
, position
;
2903 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2904 int top
= XINT (window
->top
);
2905 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2906 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2908 /* Where should this scroll bar be, pixelwise? */
2909 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2910 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2912 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2913 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2914 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2915 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2917 struct scroll_bar
*bar
;
2919 /* Does the scroll bar exist yet? */
2920 if (NILP (window
->vertical_scroll_bar
))
2921 bar
= x_scroll_bar_create (window
,
2922 pixel_top
, pixel_left
,
2923 pixel_width
, pixel_height
);
2926 /* It may just need to be moved and resized. */
2927 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2928 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2931 /* Set the scroll bar's current state. */
2933 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2936 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2939 int start
= (int) (((double) position
* top_range
) / whole
);
2940 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2942 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2946 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2950 /* The following three hooks are used when we're doing a thorough
2951 redisplay of the frame. We don't explicitly know which scroll bars
2952 are going to be deleted, because keeping track of when windows go
2953 away is a real pain - "Can you say set-window-configuration, boys
2954 and girls?" Instead, we just assert at the beginning of redisplay
2955 that *all* scroll bars are to be removed, and then save a scroll bar
2956 from the fiery pit when we actually redisplay its window. */
2958 /* Arrange for all scroll bars on FRAME to be removed at the next call
2959 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2960 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2962 w32_condemn_scroll_bars (frame
)
2965 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2966 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2969 bar
= FRAME_SCROLL_BARS (frame
);
2970 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2971 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2972 XSCROLL_BAR (bar
)->prev
= Qnil
;
2973 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2974 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2975 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2978 /* The condemned list should be empty at this point; if it's not,
2979 then the rest of Emacs isn't using the condemn/redeem/judge
2980 protocol correctly. */
2981 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2984 /* Move them all to the "condemned" list. */
2985 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2986 FRAME_SCROLL_BARS (frame
) = Qnil
;
2990 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2991 Note that WINDOW isn't necessarily condemned at all. */
2993 w32_redeem_scroll_bar (window
)
2994 struct window
*window
;
2996 struct scroll_bar
*bar
;
2998 /* We can't redeem this window's scroll bar if it doesn't have one. */
2999 if (NILP (window
->vertical_scroll_bar
))
3002 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3004 /* Unlink it from the condemned list. */
3006 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3008 if (NILP (bar
->prev
))
3010 /* If the prev pointer is nil, it must be the first in one of
3012 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3013 /* It's not condemned. Everything's fine. */
3015 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3016 window
->vertical_scroll_bar
))
3017 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3019 /* If its prev pointer is nil, it must be at the front of
3020 one or the other! */
3024 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3026 if (! NILP (bar
->next
))
3027 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3029 bar
->next
= FRAME_SCROLL_BARS (f
);
3031 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3032 if (! NILP (bar
->next
))
3033 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3036 struct scroll_bar
*bar
;
3038 /* We can't redeem this window's scroll bar if it doesn't have one. */
3039 if (NILP (window
->vertical_scroll_bar
))
3042 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3044 /* Unlink it from the condemned list. */
3046 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3048 if (NILP (bar
->prev
))
3050 /* If the prev pointer is nil, it must be the first in one of
3052 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3053 /* It's not condemned. Everything's fine. */
3055 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3056 window
->vertical_scroll_bar
))
3057 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3059 /* If its prev pointer is nil, it must be at the front of
3060 one or the other! */
3064 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3066 if (! NILP (bar
->next
))
3067 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3069 bar
->next
= FRAME_SCROLL_BARS (f
);
3071 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3072 if (! NILP (bar
->next
))
3073 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3078 /* Remove all scroll bars on FRAME that haven't been saved since the
3079 last call to `*condemn_scroll_bars_hook'. */
3081 w32_judge_scroll_bars (f
)
3084 Lisp_Object bar
, next
;
3086 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3088 /* Clear out the condemned list now so we won't try to process any
3089 more events on the hapless scroll bars. */
3090 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3092 for (; ! NILP (bar
); bar
= next
)
3094 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3096 x_scroll_bar_remove (b
);
3099 b
->next
= b
->prev
= Qnil
;
3102 /* Now there should be no references to the condemned scroll bars,
3103 and they should get garbage-collected. */
3105 Lisp_Object bar
, next
;
3107 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3109 /* Clear out the condemned list now so we won't try to process any
3110 more events on the hapless scroll bars. */
3111 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3113 for (; ! NILP (bar
); bar
= next
)
3115 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3117 x_scroll_bar_remove (b
);
3120 b
->next
= b
->prev
= Qnil
;
3123 /* Now there should be no references to the condemned scroll bars,
3124 and they should get garbage-collected. */
3128 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3129 is set to something other than no_event, it is enqueued.
3131 This may be called from a signal handler, so we have to ignore GC
3135 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3136 struct scroll_bar
*bar
;
3138 struct input_event
*emacs_event
;
3140 if (! GC_WINDOWP (bar
->window
))
3143 emacs_event
->kind
= w32_scroll_bar_click
;
3144 emacs_event
->code
= 0;
3145 /* not really meaningful to distinguish up/down */
3146 emacs_event
->modifiers
= msg
->dwModifiers
;
3147 emacs_event
->frame_or_window
= bar
->window
;
3148 emacs_event
->timestamp
= msg
->msg
.time
;
3151 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3153 int dragging
= !NILP (bar
->dragging
);
3155 if (pfnGetScrollInfo
)
3159 si
.cbSize
= sizeof (si
);
3162 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3166 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
3168 bar
->dragging
= Qnil
;
3170 switch (LOWORD (msg
->msg
.wParam
))
3173 emacs_event
->part
= scroll_bar_down_arrow
;
3176 emacs_event
->part
= scroll_bar_up_arrow
;
3179 emacs_event
->part
= scroll_bar_above_handle
;
3182 emacs_event
->part
= scroll_bar_below_handle
;
3185 emacs_event
->part
= scroll_bar_handle
;
3189 emacs_event
->part
= scroll_bar_handle
;
3193 case SB_THUMBPOSITION
:
3194 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3195 y
= HIWORD (msg
->msg
.wParam
);
3197 emacs_event
->part
= scroll_bar_handle
;
3199 /* "Silently" update current position. */
3200 if (pfnSetScrollInfo
)
3204 si
.cbSize
= sizeof (si
);
3208 /* Shrink handle if necessary to allow full range for position. */
3210 int start
= XINT (bar
->start
);
3211 int end
= XINT (bar
->end
);
3212 int len
= end
- start
;
3214 /* If new end is nearly hitting bottom, we must shrink
3215 handle. How much we shrink it depends on the relative
3216 sizes of len and top_range. */
3217 if (y
+ len
> top_range
- 2)
3219 len
-= min (top_range
/ 10, (len
/ 3) + 2);
3223 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3224 si
.fMask
|= SIF_PAGE
;
3228 /* Remember apparent position (we actually lag behind the real
3229 position, so don't set that directly. */
3230 last_scroll_bar_drag_pos
= y
;
3232 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3235 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
3238 /* If this is the end of a drag sequence, then reset the scroll
3239 handle size to normal and do a final redraw. Otherwise do
3243 if (pfnSetScrollInfo
)
3246 int start
= XINT (bar
->start
);
3247 int end
= XINT (bar
->end
);
3249 si
.cbSize
= sizeof (si
);
3250 si
.fMask
= SIF_PAGE
| SIF_POS
;
3251 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3252 si
.nPos
= last_scroll_bar_drag_pos
;
3254 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3257 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
3261 emacs_event
->kind
= no_event
;
3265 XSETINT (emacs_event
->x
, y
);
3266 XSETINT (emacs_event
->y
, top_range
);
3272 /* Return information to the user about the current position of the mouse
3273 on the scroll bar. */
3275 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3277 Lisp_Object
*bar_window
;
3278 enum scroll_bar_part
*part
;
3280 unsigned long *time
;
3282 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3283 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3284 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3286 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3291 *bar_window
= bar
->window
;
3293 if (pfnGetScrollInfo
)
3297 si
.cbSize
= sizeof (si
);
3298 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3300 pfnGetScrollInfo (w
, SB_CTL
, &si
);
3302 top_range
= si
.nMax
- si
.nPage
+ 1;
3305 pos
= GetScrollPos (w
, SB_CTL
);
3307 switch (LOWORD (last_mouse_scroll_bar_pos
))
3309 case SB_THUMBPOSITION
:
3311 *part
= scroll_bar_handle
;
3312 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3313 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3316 *part
= scroll_bar_handle
;
3320 *part
= scroll_bar_handle
;
3325 XSETINT(*y
, top_range
);
3328 last_mouse_scroll_bar
= Qnil
;
3330 *time
= last_mouse_movement_time
;
3335 /* The screen has been cleared so we may have changed foreground or
3336 background colors, and the scroll bars may need to be redrawn.
3337 Clear out the scroll bars, and ask for expose events, so we can
3340 x_scroll_bar_clear (f
)
3345 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3346 bar
= XSCROLL_BAR (bar
)->next
)
3348 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3349 HDC hdc
= GetDC (window
);
3352 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3353 arranges to refresh the scroll bar if hidden. */
3354 my_show_window (f
, window
, SW_HIDE
);
3356 GetClientRect (window
, &rect
);
3357 select_palette (f
, hdc
);
3358 w32_clear_rect (f
, hdc
, &rect
);
3359 deselect_palette (f
, hdc
);
3361 ReleaseDC (window
, hdc
);
3365 show_scroll_bars (f
, how
)
3371 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3372 bar
= XSCROLL_BAR (bar
)->next
)
3374 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3375 my_show_window (f
, window
, how
);
3380 /* The main W32 event-reading loop - w32_read_socket. */
3382 /* Timestamp of enter window event. This is only used by w32_read_socket,
3383 but we have to put it out here, since static variables within functions
3384 sometimes don't work. */
3385 static Time enter_timestamp
;
3387 /* Record the last 100 characters stored
3388 to help debug the loss-of-chars-during-GC problem. */
3390 short temp_buffer
[100];
3393 /* Read events coming from the W32 shell.
3394 This routine is called by the SIGIO handler.
3395 We return as soon as there are no more events to be read.
3397 Events representing keys are stored in buffer BUFP,
3398 which can hold up to NUMCHARS characters.
3399 We return the number of characters stored into the buffer,
3400 thus pretending to be `read'.
3402 EXPECTED is nonzero if the caller knows input is available.
3404 Some of these messages are reposted back to the message queue since the
3405 system calls the windows proc directly in a context where we cannot return
3406 the data nor can we guarantee the state we are in. So if we dispatch them
3407 we will get into an infinite loop. To prevent this from ever happening we
3408 will set a variable to indicate we are in the read_socket call and indicate
3409 which message we are processing since the windows proc gets called
3410 recursively with different messages by the system.
3414 w32_read_socket (sd
, bufp
, numchars
, expected
)
3416 register struct input_event
*bufp
;
3417 register int numchars
;
3421 int check_visibility
= 0;
3425 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3427 if (interrupt_input_blocked
)
3429 interrupt_input_pending
= 1;
3433 interrupt_input_pending
= 0;
3436 /* So people can tell when we have read the available input. */
3437 input_signal_count
++;
3440 abort (); /* Don't think this happens. */
3442 while (get_next_msg (&msg
, FALSE
))
3444 switch (msg
.msg
.message
)
3447 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3451 if (msg
.rect
.right
== msg
.rect
.left
||
3452 msg
.rect
.bottom
== msg
.rect
.top
)
3454 /* We may get paint messages even though the client
3455 area is clipped - these are not expose events. */
3456 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3457 XSTRING (f
->name
)->data
));
3459 else if (f
->async_visible
!= 1)
3461 /* Definitely not obscured, so mark as visible. */
3462 f
->async_visible
= 1;
3463 f
->async_iconified
= 0;
3464 SET_FRAME_GARBAGED (f
);
3465 DebPrint (("frame %04x (%s) reexposed\n", f
,
3466 XSTRING (f
->name
)->data
));
3468 /* WM_PAINT serves as MapNotify as well, so report
3469 visibility changes properly. */
3472 bufp
->kind
= deiconify_event
;
3473 XSETFRAME (bufp
->frame_or_window
, f
);
3478 else if (! NILP(Vframe_list
)
3479 && ! NILP (XCONS (Vframe_list
)->cdr
))
3480 /* Force a redisplay sooner or later to update the
3481 frame titles in case this is the second frame. */
3482 record_asynch_buffer_change ();
3486 /* Erase background again for safety. */
3487 w32_clear_rect (f
, NULL
, &msg
.rect
);
3491 msg
.rect
.right
- msg
.rect
.left
,
3492 msg
.rect
.bottom
- msg
.rect
.top
);
3497 case WM_INPUTLANGCHANGE
:
3498 /* Generate a language change event. */
3499 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3506 bufp
->kind
= language_change_event
;
3507 XSETFRAME (bufp
->frame_or_window
, f
);
3508 bufp
->code
= msg
.msg
.wParam
;
3509 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
3518 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3520 if (f
&& !f
->iconified
)
3522 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3524 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3525 bufp
->kind
= non_ascii_keystroke
;
3526 bufp
->code
= msg
.msg
.wParam
;
3527 bufp
->modifiers
= msg
.dwModifiers
;
3528 XSETFRAME (bufp
->frame_or_window
, f
);
3529 bufp
->timestamp
= msg
.msg
.time
;
3538 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3540 if (f
&& !f
->iconified
)
3542 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3544 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3545 bufp
->kind
= ascii_keystroke
;
3546 bufp
->code
= msg
.msg
.wParam
;
3547 bufp
->modifiers
= msg
.dwModifiers
;
3548 XSETFRAME (bufp
->frame_or_window
, f
);
3549 bufp
->timestamp
= msg
.msg
.time
;
3557 if (dpyinfo
->grabbed
&& last_mouse_frame
3558 && FRAME_LIVE_P (last_mouse_frame
))
3559 f
= last_mouse_frame
;
3561 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3564 note_mouse_movement (f
, &msg
.msg
);
3566 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3570 case WM_LBUTTONDOWN
:
3572 case WM_MBUTTONDOWN
:
3574 case WM_RBUTTONDOWN
:
3580 if (dpyinfo
->grabbed
&& last_mouse_frame
3581 && FRAME_LIVE_P (last_mouse_frame
))
3582 f
= last_mouse_frame
;
3584 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3588 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3591 construct_mouse_click (bufp
, &msg
, f
);
3598 parse_button (msg
.msg
.message
, &button
, &up
);
3602 dpyinfo
->grabbed
&= ~ (1 << button
);
3606 dpyinfo
->grabbed
|= (1 << button
);
3607 last_mouse_frame
= f
;
3613 if (dpyinfo
->grabbed
&& last_mouse_frame
3614 && FRAME_LIVE_P (last_mouse_frame
))
3615 f
= last_mouse_frame
;
3617 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3621 if ((!dpyinfo
->w32_focus_frame
3622 || f
== dpyinfo
->w32_focus_frame
)
3625 construct_mouse_wheel (bufp
, &msg
, f
);
3634 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3638 construct_drag_n_drop (bufp
, &msg
, f
);
3647 struct scroll_bar
*bar
=
3648 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3650 if (bar
&& numchars
>= 1)
3652 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3662 case WM_WINDOWPOSCHANGED
:
3664 case WM_ACTIVATEAPP
:
3665 check_visibility
= 1;
3669 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3671 if (f
&& !f
->async_iconified
)
3675 x_real_positions (f
, &x
, &y
);
3676 f
->output_data
.w32
->left_pos
= x
;
3677 f
->output_data
.w32
->top_pos
= y
;
3680 check_visibility
= 1;
3684 /* If window has been obscured or exposed by another window
3685 being maximised or minimised/restored, then recheck
3686 visibility of all frames. Direct changes to our own
3687 windows get handled by WM_SIZE. */
3689 if (msg
.msg
.lParam
!= 0)
3690 check_visibility
= 1;
3693 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3694 f
->async_visible
= msg
.msg
.wParam
;
3698 check_visibility
= 1;
3702 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3704 /* Inform lisp of whether frame has been iconified etc. */
3707 switch (msg
.msg
.wParam
)
3709 case SIZE_MINIMIZED
:
3710 f
->async_visible
= 0;
3711 f
->async_iconified
= 1;
3713 bufp
->kind
= iconify_event
;
3714 XSETFRAME (bufp
->frame_or_window
, f
);
3720 case SIZE_MAXIMIZED
:
3722 f
->async_visible
= 1;
3723 f
->async_iconified
= 0;
3725 /* wait_reading_process_input will notice this and update
3726 the frame's display structures. */
3727 SET_FRAME_GARBAGED (f
);
3731 bufp
->kind
= deiconify_event
;
3732 XSETFRAME (bufp
->frame_or_window
, f
);
3738 /* Force a redisplay sooner or later
3739 to update the frame titles
3740 in case this is the second frame. */
3741 record_asynch_buffer_change ();
3746 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3754 GetClientRect(msg
.msg
.hwnd
, &rect
);
3756 height
= rect
.bottom
- rect
.top
;
3757 width
= rect
.right
- rect
.left
;
3759 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3760 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3762 /* TODO: Clip size to the screen dimensions. */
3764 /* Even if the number of character rows and columns has
3765 not changed, the font size may have changed, so we need
3766 to check the pixel dimensions as well. */
3768 if (columns
!= f
->width
3769 || rows
!= f
->height
3770 || width
!= f
->output_data
.w32
->pixel_width
3771 || height
!= f
->output_data
.w32
->pixel_height
)
3773 /* I had set this to 0, 0 - I am not sure why?? */
3775 change_frame_size (f
, rows
, columns
, 0, 1);
3776 SET_FRAME_GARBAGED (f
);
3778 f
->output_data
.w32
->pixel_width
= width
;
3779 f
->output_data
.w32
->pixel_height
= height
;
3780 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3784 check_visibility
= 1;
3789 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3791 if (msg
.msg
.message
== WM_SETFOCUS
)
3793 x_new_focus_frame (dpyinfo
, f
);
3795 else if (f
== dpyinfo
->w32_focus_frame
)
3797 x_new_focus_frame (dpyinfo
, 0);
3800 check_visibility
= 1;
3804 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3811 bufp
->kind
= delete_window_event
;
3812 XSETFRAME (bufp
->frame_or_window
, f
);
3820 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3827 bufp
->kind
= menu_bar_activate_event
;
3828 XSETFRAME (bufp
->frame_or_window
, f
);
3836 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3840 extern void menubar_selection_callback
3841 (FRAME_PTR f
, void * client_data
);
3842 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3845 check_visibility
= 1;
3848 case WM_DISPLAYCHANGE
:
3849 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3853 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3854 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3855 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3856 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3860 check_visibility
= 1;
3864 /* Check for messages registered at runtime. */
3865 if (msg
.msg
.message
== msh_mousewheel
)
3867 if (dpyinfo
->grabbed
&& last_mouse_frame
3868 && FRAME_LIVE_P (last_mouse_frame
))
3869 f
= last_mouse_frame
;
3871 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3875 if ((!dpyinfo
->w32_focus_frame
3876 || f
== dpyinfo
->w32_focus_frame
)
3879 construct_mouse_wheel (bufp
, &msg
, f
);
3890 /* If the focus was just given to an autoraising frame,
3892 /* ??? This ought to be able to handle more than one such frame. */
3893 if (pending_autoraise_frame
)
3895 x_raise_frame (pending_autoraise_frame
);
3896 pending_autoraise_frame
= 0;
3899 /* Check which frames are still visisble, if we have enqueued any user
3900 events or been notified of events that may affect visibility. We
3901 do this here because there doesn't seem to be any direct
3902 notification from Windows that the visibility of a window has
3903 changed (at least, not in all cases). */
3904 if (count
> 0 || check_visibility
)
3906 Lisp_Object tail
, frame
;
3908 FOR_EACH_FRAME (tail
, frame
)
3910 FRAME_PTR f
= XFRAME (frame
);
3911 /* Check "visible" frames and mark each as obscured or not.
3912 Note that async_visible is nonzero for unobscured and
3913 obscured frames, but zero for hidden and iconified frames. */
3914 if (FRAME_W32_P (f
) && f
->async_visible
)
3917 HDC hdc
= get_frame_dc (f
);
3918 GetClipBox (hdc
, &clipbox
);
3919 release_frame_dc (f
, hdc
);
3921 if (clipbox
.right
== clipbox
.left
3922 || clipbox
.bottom
== clipbox
.top
)
3924 /* Frame has become completely obscured so mark as
3925 such (we do this by setting async_visible to 2 so
3926 that FRAME_VISIBLE_P is still true, but redisplay
3928 f
->async_visible
= 2;
3930 if (!FRAME_OBSCURED_P (f
))
3932 DebPrint (("frame %04x (%s) obscured\n", f
,
3933 XSTRING (f
->name
)->data
));
3938 /* Frame is not obscured, so mark it as such. */
3939 f
->async_visible
= 1;
3941 if (FRAME_OBSCURED_P (f
))
3943 SET_FRAME_GARBAGED (f
);
3944 DebPrint (("frame %04x (%s) reexposed\n", f
,
3945 XSTRING (f
->name
)->data
));
3947 /* Force a redisplay sooner or later. */
3948 record_asynch_buffer_change ();
3959 /* Drawing the cursor. */
3962 /* Draw a hollow box cursor. Don't change the inside of the box. */
3972 hdc
= get_frame_dc (f
);
3974 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3976 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3977 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3978 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3979 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3981 FrameRect (hdc
, &rect
, hb
);
3984 release_frame_dc (f
, hdc
);
3987 /* Clear the cursor of frame F to background color,
3988 and mark the cursor as not shown.
3989 This is used when the text where the cursor is
3990 is about to be rewritten. */
3996 if (! FRAME_VISIBLE_P (f
)
3997 || f
->phys_cursor_x
< 0)
4000 x_display_cursor (f
, 0);
4001 f
->phys_cursor_x
= -1;
4004 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4005 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4009 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4016 CHAR_TO_PIXEL_COL (f
, column
),
4017 CHAR_TO_PIXEL_ROW (f
, row
),
4018 &glyph
, 1, highlight
, 0, NULL
);
4022 x_display_bar_cursor (f
, on
)
4026 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4028 /* This is pointless on invisible frames, and dangerous on garbaged
4029 frames; in the latter case, the frame may be in the midst of
4030 changing its size, and curs_x and curs_y may be off the frame. */
4031 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4034 if (! on
&& f
->phys_cursor_x
< 0)
4037 /* If there is anything wrong with the current cursor state, remove it. */
4038 if (f
->phys_cursor_x
>= 0
4040 || f
->phys_cursor_x
!= curs_x
4041 || f
->phys_cursor_y
!= curs_y
4042 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
4044 /* Erase the cursor by redrawing the character underneath it. */
4045 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4046 f
->phys_cursor_glyph
,
4047 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4048 f
->phys_cursor_x
= -1;
4051 /* If we now need a cursor in the new place or in the new form, do it so. */
4053 && (f
->phys_cursor_x
< 0
4054 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4056 f
->phys_cursor_glyph
4057 = ((current_glyphs
->enable
[curs_y
]
4058 && curs_x
< current_glyphs
->used
[curs_y
])
4059 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4061 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4062 CHAR_TO_PIXEL_COL (f
, curs_x
),
4063 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4064 max (f
->output_data
.w32
->cursor_width
, 1),
4065 f
->output_data
.w32
->line_height
);
4067 f
->phys_cursor_x
= curs_x
;
4068 f
->phys_cursor_y
= curs_y
;
4070 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4075 /* Turn the displayed cursor of frame F on or off according to ON.
4076 If ON is nonzero, where to put the cursor is specified
4077 by F->cursor_x and F->cursor_y. */
4080 x_display_box_cursor (f
, on
)
4084 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4086 /* This is pointless on invisible frames, and dangerous on garbaged
4087 frames; in the latter case, the frame may be in the midst of
4088 changing its size, and curs_x and curs_y may be off the frame. */
4089 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4092 /* If cursor is off and we want it off, return quickly. */
4093 if (!on
&& f
->phys_cursor_x
< 0)
4096 /* If cursor is currently being shown and we don't want it to be
4097 or it is in the wrong place,
4098 or we want a hollow box and it's not so, (pout!)
4100 if (f
->phys_cursor_x
>= 0
4102 || f
->phys_cursor_x
!= curs_x
4103 || f
->phys_cursor_y
!= curs_y
4104 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4105 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4107 int mouse_face_here
= 0;
4108 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4110 /* If the cursor is in the mouse face area, redisplay that when
4111 we clear the cursor. */
4112 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4113 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4114 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4115 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4116 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4117 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4118 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4119 /* Don't redraw the cursor's spot in mouse face
4120 if it is at the end of a line (on a newline).
4121 The cursor appears there, but mouse highlighting does not. */
4122 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4123 mouse_face_here
= 1;
4125 /* If the font is not as tall as a whole line,
4126 we must explicitly clear the line's whole height. */
4127 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4128 w32_clear_area (f
, NULL
,
4129 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4130 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4131 FONT_WIDTH (f
->output_data
.w32
->font
),
4132 f
->output_data
.w32
->line_height
);
4133 /* Erase the cursor by redrawing the character underneath it. */
4134 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4135 f
->phys_cursor_glyph
,
4138 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4139 f
->phys_cursor_x
= -1;
4142 /* If we want to show a cursor,
4143 or we want a box cursor and it's not so,
4144 write it in the right place. */
4146 && (f
->phys_cursor_x
< 0
4147 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4148 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4150 f
->phys_cursor_glyph
4151 = ((current_glyphs
->enable
[curs_y
]
4152 && curs_x
< current_glyphs
->used
[curs_y
])
4153 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4155 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4158 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4162 x_draw_single_glyph (f
, curs_y
, curs_x
,
4163 f
->phys_cursor_glyph
, 2);
4164 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4167 f
->phys_cursor_x
= curs_x
;
4168 f
->phys_cursor_y
= curs_y
;
4172 /* Display the cursor on frame F, or clear it, according to ON.
4173 Use the position specified by curs_x and curs_y
4174 if we are doing an update of frame F now.
4175 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4178 x_display_cursor (f
, on
)
4184 /* If we're not updating, then we want to use the current frame's
4185 cursor position, not our local idea of where the cursor ought to be. */
4186 if (f
!= updating_frame
)
4188 curs_x
= FRAME_CURSOR_X (f
);
4189 curs_y
= FRAME_CURSOR_Y (f
);
4192 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4193 x_display_box_cursor (f
, on
);
4194 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4195 x_display_bar_cursor (f
, on
);
4197 /* Those are the only two we have implemented! */
4203 /* Changing the font of the frame. */
4205 /* Give frame F the font named FONTNAME as its default font, and
4206 return the full name of that font. FONTNAME may be a wildcard
4207 pattern; in that case, we choose some font that fits the pattern.
4208 The return value shows which font we chose. */
4211 x_new_font (f
, fontname
)
4213 register char *fontname
;
4215 struct font_info
*fontp
4216 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4222 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4223 f
->output_data
.w32
->font_baseline
4224 = FRAME_FONT(f
)->tm
.tmAscent
+ fontp
->baseline_offset
;
4225 FRAME_FONTSET (f
) = -1;
4227 /* Compute the scroll bar width in character columns. */
4228 if (f
->scroll_bar_pixel_width
> 0)
4230 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4231 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4234 f
->scroll_bar_cols
= 2;
4236 /* Now make the frame display the given font. */
4237 if (FRAME_W32_WINDOW (f
) != 0)
4239 frame_update_line_height (f
);
4240 x_set_window_size (f
, 0, f
->width
, f
->height
);
4243 /* If we are setting a new frame's font for the first time,
4244 there are no faces yet, so this font's height is the line height. */
4245 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4248 Lisp_Object lispy_name
;
4250 lispy_name
= build_string (fontname
);
4256 /* Give frame F the fontset named FONTSETNAME as its default font, and
4257 return the full name of that fontset. FONTSETNAME may be a wildcard
4258 pattern; in that case, we choose some fontset that fits the pattern.
4259 The return value shows which fontset we chose. */
4262 x_new_fontset (f
, fontsetname
)
4266 int fontset
= fs_query_fontset (f
, fontsetname
);
4267 struct fontset_info
*fontsetp
;
4273 if (FRAME_FONTSET (f
) == fontset
)
4274 /* This fontset is already set in frame F. There's nothing more
4276 return build_string (fontsetname
);
4278 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4280 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4281 /* This fontset doesn't contain ASCII font. */
4284 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4286 if (!STRINGP (result
))
4287 /* Can't load ASCII font. */
4290 /* Since x_new_font doesn't update any fontset information, do it now. */
4291 FRAME_FONTSET(f
) = fontset
;
4292 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4293 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4295 return build_string (fontsetname
);
4298 /* Calculate the absolute position in frame F
4299 from its current recorded position values and gravity. */
4301 x_calc_absolute_position (f
)
4306 int flags
= f
->output_data
.w32
->size_hint_flags
;
4310 /* Find the position of the outside upper-left corner of
4311 the inner window, with respect to the outer window. */
4312 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4315 MapWindowPoints (FRAME_W32_WINDOW (f
),
4316 f
->output_data
.w32
->parent_desc
,
4323 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4326 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4327 FRAME_EXTERNAL_MENU_BAR (f
));
4330 pt
.x
+= (rt
.right
- rt
.left
);
4331 pt
.y
+= (rt
.bottom
- rt
.top
);
4334 /* Treat negative positions as relative to the leftmost bottommost
4335 position that fits on the screen. */
4336 if (flags
& XNegative
)
4337 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4338 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4340 + f
->output_data
.w32
->left_pos
);
4342 if (flags
& YNegative
)
4343 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4344 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4346 + f
->output_data
.w32
->top_pos
);
4347 /* The left_pos and top_pos
4348 are now relative to the top and left screen edges,
4349 so the flags should correspond. */
4350 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4353 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4354 to really change the position, and 0 when calling from
4355 x_make_frame_visible (in that case, XOFF and YOFF are the current
4356 position values). It is -1 when calling from x_set_frame_parameters,
4357 which means, do adjust for borders but don't change the gravity. */
4359 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4361 register int xoff
, yoff
;
4364 int modified_top
, modified_left
;
4366 if (change_gravity
> 0)
4368 f
->output_data
.w32
->top_pos
= yoff
;
4369 f
->output_data
.w32
->left_pos
= xoff
;
4370 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4372 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4374 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4375 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4377 x_calc_absolute_position (f
);
4380 x_wm_set_size_hint (f
, (long) 0, 0);
4382 /* It is a mystery why we need to add the border_width here
4383 when the frame is already visible, but experiment says we do. */
4384 modified_left
= f
->output_data
.w32
->left_pos
;
4385 modified_top
= f
->output_data
.w32
->top_pos
;
4387 /* Do not add in border widths under W32. */
4388 if (change_gravity
!= 0)
4390 modified_left
+= f
->output_data
.w32
->border_width
;
4391 modified_top
+= f
->output_data
.w32
->border_width
;
4395 my_set_window_pos (FRAME_W32_WINDOW (f
),
4397 modified_left
, modified_top
,
4399 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4403 /* Call this to change the size of frame F's x-window.
4404 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4405 for this size change and subsequent size changes.
4406 Otherwise we leave the window gravity unchanged. */
4408 x_set_window_size (f
, change_gravity
, cols
, rows
)
4413 int pixelwidth
, pixelheight
;
4415 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4419 check_frame_size (f
, &rows
, &cols
);
4420 f
->output_data
.w32
->vertical_scroll_bar_extra
4421 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4423 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4424 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4425 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4426 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4427 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4429 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4430 x_wm_set_size_hint (f
, (long) 0, 0);
4435 rect
.left
= rect
.top
= 0;
4436 rect
.right
= pixelwidth
;
4437 rect
.bottom
= pixelheight
;
4439 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4440 FRAME_EXTERNAL_MENU_BAR (f
));
4442 my_set_window_pos (FRAME_W32_WINDOW (f
),
4445 rect
.right
- rect
.left
,
4446 rect
.bottom
- rect
.top
,
4447 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4450 /* Now, strictly speaking, we can't be sure that this is accurate,
4451 but the window manager will get around to dealing with the size
4452 change request eventually, and we'll hear how it went when the
4453 ConfigureNotify event gets here.
4455 We could just not bother storing any of this information here,
4456 and let the ConfigureNotify event set everything up, but that
4457 might be kind of confusing to the lisp code, since size changes
4458 wouldn't be reported in the frame parameters until some random
4459 point in the future when the ConfigureNotify event arrives. */
4460 change_frame_size (f
, rows
, cols
, 0, 0);
4461 PIXEL_WIDTH (f
) = pixelwidth
;
4462 PIXEL_HEIGHT (f
) = pixelheight
;
4464 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4465 receive in the ConfigureNotify event; if we get what we asked
4466 for, then the event won't cause the screen to become garbaged, so
4467 we have to make sure to do it here. */
4468 SET_FRAME_GARBAGED (f
);
4470 /* If cursor was outside the new size, mark it as off. */
4471 if (f
->phys_cursor_y
>= rows
4472 || f
->phys_cursor_x
>= cols
)
4474 f
->phys_cursor_x
= -1;
4475 f
->phys_cursor_y
= -1;
4478 /* Clear out any recollection of where the mouse highlighting was,
4479 since it might be in a place that's outside the new frame size.
4480 Actually checking whether it is outside is a pain in the neck,
4481 so don't try--just let the highlighting be done afresh with new size. */
4482 window
= dpyinfo
->mouse_face_window
;
4483 if (! NILP (window
) && XFRAME (window
) == f
)
4485 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4486 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4487 dpyinfo
->mouse_face_window
= Qnil
;
4493 /* Mouse warping. */
4496 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4505 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4506 pt
.x
= rect
.left
+ pix_x
;
4507 pt
.y
= rect
.top
+ pix_y
;
4508 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4510 SetCursorPos (pt
.x
, pt
.y
);
4516 x_set_mouse_position (f
, x
, y
)
4522 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4523 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4525 if (pix_x
< 0) pix_x
= 0;
4526 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4528 if (pix_y
< 0) pix_y
= 0;
4529 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4531 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4534 /* focus shifting, raising and lowering. */
4536 x_focus_on_frame (f
)
4539 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4541 /* Give input focus to frame. */
4544 /* Try not to change its Z-order if possible. */
4545 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4546 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4549 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4558 /* Raise frame F. */
4565 /* Strictly speaking, raise-frame should only change the frame's Z
4566 order, leaving input focus unchanged. This is reasonable behaviour
4567 on X where the usual policy is point-to-focus. However, this
4568 behaviour would be very odd on Windows where the usual policy is
4571 On X, if the mouse happens to be over the raised frame, it gets
4572 input focus anyway (so the window with focus will never be
4573 completely obscured) - if not, then just moving the mouse over it
4574 is sufficient to give it focus. On Windows, the user must actually
4575 click on the frame (preferrably the title bar so as not to move
4576 point), which is more awkward. Also, no other Windows program
4577 raises a window to the top but leaves another window (possibly now
4578 completely obscured) with input focus.
4580 Because there is a system setting on Windows that allows the user
4581 to choose the point to focus policy, we make the strict semantics
4582 optional, but by default we grab focus when raising. */
4584 if (NILP (Vw32_grab_focus_on_raise
))
4586 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4587 not already the foreground application: the frame is raised
4588 above all other frames belonging to us, but not above the
4589 current top window. To achieve that, we have to resort to this
4590 more cumbersome method. */
4592 HDWP handle
= BeginDeferWindowPos (2);
4595 DeferWindowPos (handle
,
4596 FRAME_W32_WINDOW (f
),
4599 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4601 DeferWindowPos (handle
,
4602 GetForegroundWindow (),
4603 FRAME_W32_WINDOW (f
),
4605 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4607 EndDeferWindowPos (handle
);
4612 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4618 /* Lower frame F. */
4624 my_set_window_pos (FRAME_W32_WINDOW (f
),
4627 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4632 w32_frame_raise_lower (f
, raise
)
4642 /* Change of visibility. */
4644 /* This tries to wait until the frame is really visible.
4645 However, if the window manager asks the user where to position
4646 the frame, this will return before the user finishes doing that.
4647 The frame will not actually be visible at that time,
4648 but it will become visible later when the window manager
4649 finishes with it. */
4651 x_make_frame_visible (f
)
4656 if (! FRAME_VISIBLE_P (f
))
4658 /* We test FRAME_GARBAGED_P here to make sure we don't
4659 call x_set_offset a second time
4660 if we get to x_make_frame_visible a second time
4661 before the window gets really visible. */
4662 if (! FRAME_ICONIFIED_P (f
)
4663 && ! f
->output_data
.w32
->asked_for_visible
)
4664 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4666 f
->output_data
.w32
->asked_for_visible
= 1;
4668 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4669 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4672 /* Synchronize to ensure Emacs knows the frame is visible
4673 before we do anything else. We do this loop with input not blocked
4674 so that incoming events are handled. */
4677 int count
= input_signal_count
;
4679 /* This must come after we set COUNT. */
4682 XSETFRAME (frame
, f
);
4686 /* Once we have handled input events,
4687 we should have received the MapNotify if one is coming.
4688 So if we have not got it yet, stop looping.
4689 Some window managers make their own decisions
4690 about visibility. */
4691 if (input_signal_count
!= count
)
4693 /* Machines that do polling rather than SIGIO have been observed
4694 to go into a busy-wait here. So we'll fake an alarm signal
4695 to let the handler know that there's something to be read.
4696 We used to raise a real alarm, but it seems that the handler
4697 isn't always enabled here. This is probably a bug. */
4698 if (input_polling_used ())
4700 /* It could be confusing if a real alarm arrives while processing
4701 the fake one. Turn it off and let the handler reset it. */
4703 input_poll_signal (0);
4705 /* Once we have handled input events,
4706 we should have received the MapNotify if one is coming.
4707 So if we have not got it yet, stop looping.
4708 Some window managers make their own decisions
4709 about visibility. */
4710 if (input_signal_count
!= count
)
4713 FRAME_SAMPLE_VISIBILITY (f
);
4717 /* Change from mapped state to withdrawn state. */
4719 /* Make the frame visible (mapped and not iconified). */
4721 x_make_frame_invisible (f
)
4726 /* Don't keep the highlight on an invisible frame. */
4727 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4728 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4732 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4734 /* We can't distinguish this from iconification
4735 just by the event that we get from the server.
4736 So we can't win using the usual strategy of letting
4737 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4738 and synchronize with the server to make sure we agree. */
4740 FRAME_ICONIFIED_P (f
) = 0;
4741 f
->async_visible
= 0;
4742 f
->async_iconified
= 0;
4747 /* Change window state from mapped to iconified. */
4755 /* Don't keep the highlight on an invisible frame. */
4756 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4757 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4759 if (f
->async_iconified
)
4764 /* Simulate the user minimizing the frame. */
4765 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4767 f
->async_iconified
= 1;
4772 /* Destroy the window of frame F. */
4774 x_destroy_window (f
)
4777 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4781 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4782 free_frame_menubar (f
);
4783 free_frame_faces (f
);
4785 xfree (f
->output_data
.w32
);
4786 f
->output_data
.w32
= 0;
4787 if (f
== dpyinfo
->w32_focus_frame
)
4788 dpyinfo
->w32_focus_frame
= 0;
4789 if (f
== dpyinfo
->w32_focus_event_frame
)
4790 dpyinfo
->w32_focus_event_frame
= 0;
4791 if (f
== dpyinfo
->w32_highlight_frame
)
4792 dpyinfo
->w32_highlight_frame
= 0;
4794 dpyinfo
->reference_count
--;
4796 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4798 dpyinfo
->mouse_face_beg_row
4799 = dpyinfo
->mouse_face_beg_col
= -1;
4800 dpyinfo
->mouse_face_end_row
4801 = dpyinfo
->mouse_face_end_col
= -1;
4802 dpyinfo
->mouse_face_window
= Qnil
;
4808 /* Setting window manager hints. */
4810 /* Set the normal size hints for the window manager, for frame F.
4811 FLAGS is the flags word to use--or 0 meaning preserve the flags
4812 that the window now has.
4813 If USER_POSITION is nonzero, we set the USPosition
4814 flag (this is useful when FLAGS is 0). */
4816 x_wm_set_size_hint (f
, flags
, user_position
)
4821 Window window
= FRAME_W32_WINDOW (f
);
4823 flexlines
= f
->height
;
4827 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4828 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4829 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4830 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4835 /* Window manager things */
4836 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4841 Window window
= FRAME_W32_WINDOW (f
);
4843 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4844 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4845 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4847 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4852 /* Initialization. */
4854 #ifdef USE_X_TOOLKIT
4855 static XrmOptionDescRec emacs_options
[] = {
4856 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4857 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4859 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4860 XrmoptionSepArg
, NULL
},
4861 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4863 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4864 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4865 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4866 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4867 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4868 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4869 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4871 #endif /* USE_X_TOOLKIT */
4873 static int w32_initialized
= 0;
4875 struct w32_display_info
*
4876 w32_term_init (display_name
, xrm_option
, resource_name
)
4877 Lisp_Object display_name
;
4879 char *resource_name
;
4883 struct w32_display_info
*dpyinfo
;
4888 if (!w32_initialized
)
4891 w32_initialized
= 1;
4902 argv
[argc
++] = "-xrm";
4903 argv
[argc
++] = xrm_option
;
4907 dpyinfo
= &one_w32_display_info
;
4909 /* Put this display on the chain. */
4910 dpyinfo
->next
= NULL
;
4912 /* Put it on w32_display_name_list as well, to keep them parallel. */
4913 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4914 w32_display_name_list
);
4915 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4917 dpyinfo
->w32_id_name
4918 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4919 + XSTRING (Vsystem_name
)->size
4921 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4922 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4925 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4926 resource_name
, EMACS_CLASS
);
4928 /* Put the rdb where we can find it in a way that works on
4930 dpyinfo
->xrdb
= xrdb
;
4932 hdc
= GetDC (GetDesktopWindow ());
4934 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4935 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4936 dpyinfo
->root_window
= GetDesktopWindow ();
4937 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4938 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4939 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4940 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4941 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4942 dpyinfo
->grabbed
= 0;
4943 dpyinfo
->reference_count
= 0;
4944 dpyinfo
->n_fonts
= 0;
4945 dpyinfo
->font_table_size
= 0;
4946 dpyinfo
->bitmaps
= 0;
4947 dpyinfo
->bitmaps_size
= 0;
4948 dpyinfo
->bitmaps_last
= 0;
4949 dpyinfo
->mouse_face_mouse_frame
= 0;
4950 dpyinfo
->mouse_face_deferred_gc
= 0;
4951 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4952 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4953 dpyinfo
->mouse_face_face_id
= 0;
4954 dpyinfo
->mouse_face_window
= Qnil
;
4955 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4956 dpyinfo
->mouse_face_defer
= 0;
4957 dpyinfo
->w32_focus_frame
= 0;
4958 dpyinfo
->w32_focus_event_frame
= 0;
4959 dpyinfo
->w32_highlight_frame
= 0;
4961 ReleaseDC (GetDesktopWindow (), hdc
);
4963 /* Determine if there is a middle mouse button, to allow parse_button
4964 to decide whether right mouse events should be mouse-2 or
4966 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4968 /* initialise palette with white and black */
4971 defined_color (0, "white", &color
, 1);
4972 defined_color (0, "black", &color
, 1);
4975 #ifndef F_SETOWN_BUG
4977 #ifdef F_SETOWN_SOCK_NEG
4978 /* stdin is a socket here */
4979 fcntl (connection
, F_SETOWN
, -getpid ());
4980 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4981 fcntl (connection
, F_SETOWN
, getpid ());
4982 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4983 #endif /* ! defined (F_SETOWN) */
4984 #endif /* F_SETOWN_BUG */
4987 if (interrupt_input
)
4988 init_sigio (connection
);
4989 #endif /* ! defined (SIGIO) */
4996 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4999 x_delete_display (dpyinfo
)
5000 struct w32_display_info
*dpyinfo
;
5002 /* Discard this display from w32_display_name_list and w32_display_list.
5003 We can't use Fdelq because that can quit. */
5004 if (! NILP (w32_display_name_list
)
5005 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
5006 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
5011 tail
= w32_display_name_list
;
5012 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
5014 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
5015 dpyinfo
->name_list_element
))
5017 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
5020 tail
= XCONS (tail
)->cdr
;
5024 /* free palette table */
5026 struct w32_palette_entry
* plist
;
5028 plist
= dpyinfo
->color_list
;
5031 struct w32_palette_entry
* pentry
= plist
;
5032 plist
= plist
->next
;
5035 dpyinfo
->color_list
= NULL
;
5036 if (dpyinfo
->palette
)
5037 DeleteObject(dpyinfo
->palette
);
5039 xfree (dpyinfo
->font_table
);
5040 xfree (dpyinfo
->w32_id_name
);
5043 /* Set up use of W32. */
5045 DWORD
w32_msg_worker ();
5049 /* MSVC does not type K&R functions with no arguments correctly, and
5050 so we must explicitly cast them. */
5051 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
5052 clear_end_of_line_hook
= w32_clear_end_of_line
;
5053 ins_del_lines_hook
= w32_ins_del_lines
;
5054 change_line_highlight_hook
= w32_change_line_highlight
;
5055 insert_glyphs_hook
= w32_insert_glyphs
;
5056 write_glyphs_hook
= w32_write_glyphs
;
5057 delete_glyphs_hook
= w32_delete_glyphs
;
5058 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5059 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5060 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5061 update_begin_hook
= w32_update_begin
;
5062 update_end_hook
= w32_update_end
;
5063 set_terminal_window_hook
= w32_set_terminal_window
;
5064 read_socket_hook
= w32_read_socket
;
5065 frame_up_to_date_hook
= w32_frame_up_to_date
;
5066 cursor_to_hook
= w32_cursor_to
;
5067 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5068 mouse_position_hook
= w32_mouse_position
;
5069 frame_rehighlight_hook
= w32_frame_rehighlight
;
5070 frame_raise_lower_hook
= w32_frame_raise_lower
;
5071 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5072 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5073 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5074 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5076 scroll_region_ok
= 1; /* we'll scroll partial frames */
5077 char_ins_del_ok
= 0; /* just as fast to write the line */
5078 line_ins_del_ok
= 1; /* we'll just blt 'em */
5079 fast_clear_end_of_line
= 1; /* X does this well */
5080 memory_below_frame
= 0; /* we don't remember what scrolls
5084 /* Initialize input mode: interrupt_input off, no flow control, allow
5085 8 bit character input, standard quit char. */
5086 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5088 /* Create the window thread - it will terminate itself or when the app terminates */
5092 dwMainThreadId
= GetCurrentThreadId ();
5093 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5094 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5096 /* Wait for thread to start */
5101 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5103 hWindowsThread
= CreateThread (NULL
, 0,
5104 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5105 0, 0, &dwWindowsThreadId
);
5107 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5110 /* It is desirable that mainThread should have the same notion of
5111 focus window and active window as windowsThread. Unfortunately, the
5112 following call to AttachThreadInput, which should do precisely what
5113 we need, causes major problems when Emacs is linked as a console
5114 program. Unfortunately, we have good reasons for doing that, so
5115 instead we need to send messages to windowsThread to make some API
5116 calls for us (ones that affect, or depend on, the active/focus
5118 #ifdef ATTACH_THREADS
5119 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5122 /* Dynamically link to optional system components. */
5124 HANDLE user_lib
= LoadLibrary ("user32.dll");
5126 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5128 /* New proportional scroll bar functions. */
5129 LOAD_PROC( SetScrollInfo
);
5130 LOAD_PROC( GetScrollInfo
);
5134 FreeLibrary (user_lib
);
5136 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5137 otherwise use the fixed height. */
5138 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5139 GetSystemMetrics (SM_CYVTHUMB
);
5141 /* For either kind of scroll bar, take account of the arrows; these
5142 effectively form the border of the main scroll bar range. */
5143 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5144 = GetSystemMetrics (SM_CYVSCROLL
);
5151 staticpro (&w32_display_name_list
);
5152 w32_display_name_list
= Qnil
;
5154 staticpro (&last_mouse_scroll_bar
);
5155 last_mouse_scroll_bar
= Qnil
;
5157 staticpro (&Qvendor_specific_keysyms
);
5158 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5160 DEFVAR_INT ("w32-num-mouse-buttons",
5161 &Vw32_num_mouse_buttons
,
5162 "Number of physical mouse buttons.");
5163 Vw32_num_mouse_buttons
= Qnil
;
5165 DEFVAR_LISP ("w32-swap-mouse-buttons",
5166 &Vw32_swap_mouse_buttons
,
5167 "Swap the mapping of middle and right mouse buttons.\n\
5168 When nil, middle button is mouse-2 and right button is mouse-3.");
5169 Vw32_swap_mouse_buttons
= Qnil
;
5171 DEFVAR_LISP ("w32-grab-focus-on-raise",
5172 &Vw32_grab_focus_on_raise
,
5173 "Raised frame grabs input focus.\n\
5174 When t, `raise-frame' grabs input focus as well. This fits well\n\
5175 with the normal Windows click-to-focus policy, but might not be\n\
5176 desirable when using a point-to-focus policy.");
5177 Vw32_grab_focus_on_raise
= Qt
;
5179 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5180 &Vw32_capslock_is_shiftlock
,
5181 "Apply CapsLock state to non character input keys.\n\
5182 When nil, CapsLock only affects normal character input keys.");
5183 Vw32_capslock_is_shiftlock
= Qnil
;
5185 DEFVAR_LISP ("w32-recognize-altgr",
5186 &Vw32_recognize_altgr
,
5187 "Recognize right-alt and left-ctrl as AltGr.\n\
5188 When nil, the right-alt and left-ctrl key combination is\n\
5189 interpreted normally.");
5190 Vw32_recognize_altgr
= Qt
;
5192 DEFVAR_BOOL ("w32-enable-unicode-output",
5193 &w32_enable_unicode_output
,
5194 "Enable the use of Unicode for text output if non-nil.\n\
5195 Unicode output may prevent some third party applications for displaying\n\
5196 Far-East Languages on Windows 95/98 from working properly.\n\
5197 NT uses Unicode internally anyway, so this flag will probably have no\n\
5198 affect on NT machines.");
5199 w32_enable_unicode_output
= 1;