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"
42 #include "dispextern.h"
43 #include "termhooks.h"
51 #include "intervals.h"
56 #define min(x, y) (((x) < (y)) ? (x) : (y))
57 #define max(x, y) (((x) > (y)) ? (x) : (y))
59 #define CP_DEFAULT 1004
61 extern unsigned int msh_mousewheel
;
63 extern void free_frame_menubar ();
65 extern Lisp_Object Vwindow_system
;
67 #define x_any_window_to_frame x_window_to_frame
68 #define x_top_window_to_frame x_window_to_frame
71 /* This is display since w32 does not support multiple ones. */
72 struct w32_display_info one_w32_display_info
;
74 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
75 one for each element of w32_display_list and in the same order.
76 NAME is the name of the frame.
77 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
78 Lisp_Object w32_display_name_list
;
80 /* Frame being updated by update_frame. This is declared in term.c.
81 This is set by update_begin and looked at by all the
82 w32 functions. It is zero while not inside an update.
83 In that case, the w32 functions assume that `selected_frame'
84 is the frame to apply to. */
85 extern struct frame
*updating_frame
;
87 /* This is a frame waiting to be autoraised, within w32_read_socket. */
88 struct frame
*pending_autoraise_frame
;
90 /* During an update, maximum vpos for ins/del line operations to affect. */
94 /* During an update, nonzero if chars output now should be highlighted. */
98 /* Nominal cursor position -- where to draw output.
99 During an update, these are different from the cursor-box position. */
104 /* Flag to enable Unicode output in case users wish to use programs
105 like Twinbridge on '95 rather than installed system level support
106 for Far East languages. */
107 int w32_enable_unicode_output
;
109 DWORD dwWindowsThreadId
= 0;
110 HANDLE hWindowsThread
= NULL
;
111 DWORD dwMainThreadId
= 0;
112 HANDLE hMainThread
= NULL
;
115 /* These definitions are new with Windows 95. */
116 #define SIF_RANGE 0x0001
117 #define SIF_PAGE 0x0002
118 #define SIF_POS 0x0004
119 #define SIF_DISABLENOSCROLL 0x0008
120 #define SIF_TRACKPOS 0x0010
121 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
123 typedef struct tagSCROLLINFO
132 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
133 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
136 /* Dynamic linking to new proportional scroll bar functions. */
137 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
138 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
140 int vertical_scroll_bar_min_handle
;
141 int vertical_scroll_bar_top_border
;
142 int vertical_scroll_bar_bottom_border
;
144 int last_scroll_bar_drag_pos
;
146 /* Mouse movement. */
148 /* Where the mouse was last time we reported a mouse event. */
149 static FRAME_PTR last_mouse_frame
;
150 static RECT last_mouse_glyph
;
152 Lisp_Object Vw32_num_mouse_buttons
;
154 Lisp_Object Vw32_swap_mouse_buttons
;
156 /* Control whether x_raise_frame also sets input focus. */
157 Lisp_Object Vw32_grab_focus_on_raise
;
159 /* Control whether Caps Lock affects non-ascii characters. */
160 Lisp_Object Vw32_capslock_is_shiftlock
;
162 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
163 Lisp_Object Vw32_recognize_altgr
;
165 /* The scroll bar in which the last motion event occurred.
167 If the last motion event occurred in a scroll bar, we set this
168 so w32_mouse_position can know whether to report a scroll bar motion or
171 If the last motion event didn't occur in a scroll bar, we set this
172 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
173 Lisp_Object last_mouse_scroll_bar
;
174 int last_mouse_scroll_bar_pos
;
176 /* This is a hack. We would really prefer that w32_mouse_position would
177 return the time associated with the position it returns, but there
178 doesn't seem to be any way to wrest the timestamp from the server
179 along with the position query. So, we just keep track of the time
180 of the last movement we received, and return that in hopes that
181 it's somewhat accurate. */
182 Time last_mouse_movement_time
;
184 /* Associative list linking character set strings to Windows codepages. */
185 Lisp_Object Vw32_charset_to_codepage_alist
;
187 /* Incremented by w32_read_socket whenever it really tries to read events. */
189 static int volatile input_signal_count
;
191 static int input_signal_count
;
194 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
196 extern Lisp_Object Qface
, Qmouse_face
;
200 /* A mask of extra modifier bits to put into every keyboard char. */
201 extern int extra_keyboard_modifiers
;
203 static Lisp_Object Qvendor_specific_keysyms
;
205 void w32_delete_display ();
207 static void redraw_previous_char ();
208 static void redraw_following_char ();
209 static unsigned int w32_get_modifiers ();
211 static int fast_find_position ();
212 static void note_mouse_highlight ();
213 static void clear_mouse_face ();
214 static void show_mouse_face ();
215 static void do_line_dance ();
217 /* Forward declarations for term hooks. Consistency with the rest of Emacs
218 requires the use of K&R functions prototypes. However, MSVC does not
219 pick up the function prototypes correctly with K&R function definitions,
220 and so we declare them first to give a little help to MSVC. */
221 static void w32_clear_frame ();
222 static void w32_clear_end_of_line (int);
223 static void w32_ins_del_lines (int, int);
224 static void w32_change_line_highlight (int, int, int);
225 static void w32_insert_glyphs (GLYPH
*, int);
226 static void w32_write_glyphs (GLYPH
*, int);
227 static void w32_delete_glyphs (int);
228 static void w32_ring_bell ();
229 static void w32_reset_terminal_modes ();
230 static void w32_set_terminal_modes ();
231 static void w32_update_begin (FRAME_PTR
);
232 static void w32_update_end (FRAME_PTR
);
233 static void w32_set_terminal_window (int);
234 extern int w32_read_socket (int, struct input_event
*, int, int);
235 static void w32_frame_up_to_date (FRAME_PTR
);
236 static void w32_cursor_to (int, int);
237 static void w32_reassert_line_highlight (int, int);
238 static void w32_mouse_position (FRAME_PTR
*, int, Lisp_Object
*,
239 enum scroll_bar_part
*, Lisp_Object
*,
240 Lisp_Object
*, unsigned long *);
241 static void w32_frame_rehighlight (FRAME_PTR
);
242 static void w32_frame_raise_lower (FRAME_PTR
, int);
243 static void w32_set_vertical_scroll_bar (struct window
*, int, int, int);
244 static void w32_condemn_scroll_bars (FRAME_PTR
);
245 static void w32_redeem_scroll_bar (struct window
*);
246 static void w32_judge_scroll_bars (FRAME_PTR
);
249 /* This is a function useful for recording debugging information
250 about the sequence of occurrences in this file. */
258 struct record event_record
[100];
260 int event_record_index
;
262 record_event (locus
, type
)
266 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
267 event_record_index
= 0;
269 event_record
[event_record_index
].locus
= locus
;
270 event_record
[event_record_index
].type
= type
;
271 event_record_index
++;
276 /* Return the struct w32_display_info. */
278 struct w32_display_info
*
279 w32_display_info_for_display ()
281 return (&one_w32_display_info
);
285 w32_fill_rect (f
, _hdc
, pix
, lprect
)
300 hdc
= get_frame_dc (f
);
303 hb
= CreateSolidBrush (pix
);
304 FillRect (hdc
, lprect
, hb
);
308 release_frame_dc (f
, hdc
);
317 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
318 w32_clear_rect (f
, NULL
, &rect
);
322 /* Starting and ending updates.
324 These hooks are called by update_frame at the beginning and end
325 of a frame update. We record in `updating_frame' the identity
326 of the frame being updated, so that the w32_... functions do not
327 need to take a frame as argument. Most of the w32_... functions
328 should never be called except during an update, the only exceptions
329 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
338 flexlines
= f
->height
;
343 /* Regenerate display palette before drawing if list of requested
344 colors has changed. */
345 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
347 w32_regenerate_palette (f
);
348 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
351 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
353 /* Don't do highlighting for mouse motion during the update. */
354 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
356 /* If the frame needs to be redrawn,
357 simply forget about any prior mouse highlighting. */
358 if (FRAME_GARBAGED_P (f
))
359 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
361 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
363 int firstline
, lastline
, i
;
364 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
366 /* Find the first, and the last+1, lines affected by redisplay. */
367 for (firstline
= 0; firstline
< f
->height
; firstline
++)
368 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
371 lastline
= f
->height
;
372 for (i
= f
->height
- 1; i
>= 0; i
--)
374 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
380 /* Can we tell that this update does not affect the window
381 where the mouse highlight is? If so, no need to turn off.
382 Likewise, don't do anything if the frame is garbaged;
383 in that case, the FRAME_CURRENT_GLYPHS that we would use
384 are all wrong, and we will redisplay that line anyway. */
385 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
386 || lastline
< XFASTINT (w
->top
)))
387 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
401 x_display_cursor (f
, 1);
403 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
404 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
409 /* This is called after a redisplay on frame F. */
412 w32_frame_up_to_date (f
)
416 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
417 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
419 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
420 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
421 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
422 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
427 /* External interface to control of standout mode.
428 Call this when about to modify line at position VPOS
429 and not change whether it is highlighted. */
432 w32_reassert_line_highlight (new, vpos
)
438 /* Call this when about to modify line at position VPOS
439 and change whether it is highlighted. */
442 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
443 int new_highlight
, vpos
, first_unused_hpos
;
445 highlight
= new_highlight
;
446 w32_cursor_to (vpos
, 0);
447 w32_clear_end_of_line (updating_frame
->width
);
450 /* This is used when starting Emacs and when restarting after suspend.
451 When starting Emacs, no window is mapped. And nothing must be done
452 to Emacs's own window if it is suspended (though that rarely happens). */
455 w32_set_terminal_modes (void)
459 /* This is called when exiting or suspending Emacs.
460 Exiting will make the W32 windows go away, and suspending
461 requires no action. */
464 w32_reset_terminal_modes (void)
468 /* Set the nominal cursor position of the frame.
469 This is where display update commands will take effect.
470 This does not affect the place where the cursor-box is displayed. */
473 w32_cursor_to (row
, col
)
474 register int row
, col
;
481 if (updating_frame
== 0)
484 x_display_cursor (selected_frame
, 1);
489 /* Get the Windows codepage corresponding to the specified font. The
490 charset info in the font name is used to look up
491 w32-charset-to-codepage-alist. */
493 w32_codepage_for_font (char *fontname
)
495 Lisp_Object codepage
;
496 char charset_str
[20], *charset
, *end
;
498 /* Extract charset part of font string. */
499 if (sscanf (fontname
,
500 "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
504 /* Remove leading "*-". */
505 if (strncmp ("*-", charset_str
, 2) == 0)
506 charset
= charset_str
+ 2;
508 charset
= charset_str
;
510 /* Stop match at wildcard (including preceding '-'). */
511 if (end
= strchr (charset
, '*'))
513 if (end
> charset
&& *(end
-1) == '-')
518 codepage
= Fcdr (Fassoc (build_string(charset
),
519 Vw32_charset_to_codepage_alist
));
521 if (INTEGERP (codepage
))
522 return XINT (codepage
);
528 w32_use_unicode_for_codepage (codepage
)
530 /* If the current codepage is supported, use Unicode for output. */
531 return (w32_enable_unicode_output
532 && codepage
!= CP_DEFAULT
&& IsValidCodePage (codepage
));
535 /* Dealing with bits of wchar_t as if they were an XChar2B. */
536 #define BUILD_WCHAR_T(byte1, byte2) \
537 ((wchar_t)(((byte1 & 0x00ff) << 8) | (byte2 & 0x00ff)))
546 #define W32_TEXTOUT(start_offset,nchars) \
548 int charset_dim = CHARSET_DIMENSION(charset); \
550 w32_BDF_TextOut (font->bdf, hdc, left + xoffset, \
552 x_1byte_buffer + start_offset, \
553 charset_dim, nchars, 0); \
554 else if (print_via_unicode) \
555 ExtTextOutW (hdc, left + xoffset, top + yoffset, \
556 fuOptions, clip_region, \
557 x_2byte_buffer + start_offset, nchars, NULL); \
559 ExtTextOut (hdc, left + xoffset, top + yoffset, \
560 fuOptions, clip_region, \
561 x_1byte_buffer + start_offset, \
562 nchars * charset_dim, NULL); \
563 start_offset += nchars * (print_via_unicode ? 1 : charset_dim ); \
564 xoffset += nchars * glyph_width; \
567 /* Display a sequence of N glyphs found at GP.
568 WINDOW is the window to output to. LEFT and TOP are starting coords.
569 HL is 1 if this text is highlighted, 2 if the cursor is on it,
570 3 if should appear in its mouse-face.
571 JUST_FOREGROUND if 1 means draw only the foreground;
572 don't alter the background.
574 FONT is the default font to use (for glyphs whose font-code is 0).
576 Since the display generation code is responsible for calling
577 compute_char_face and compute_glyph_face on everything it puts in
578 the display structure, we can assume that the face code on each
579 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
580 to which we can actually apply intern_face.
581 Call this function with input blocked. */
584 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
587 register GLYPH
*gp
; /* Points to first GLYPH. */
588 register int n
; /* Number of glyphs to display. */
591 struct cmpchar_info
*cmpcharp
;
593 wchar_t *x_2byte_buffer
594 = (wchar_t *) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_2byte_buffer
));
595 register wchar_t *cp
; /* Steps through x_2byte_buffer[]. */
597 /* Allocate double the window width, as this buffer may contain MBCS
598 characters under w32. Unsigned to let GetCharABCWidths work. */
599 unsigned char *x_1byte_buffer
600 = (unsigned char *) alloca (2 * FRAME_WINDOW_WIDTH (f
)
601 * sizeof (*x_1byte_buffer
));
602 register unsigned char *bp
; /* Steps through x_1byte_buffer[]. */
603 register int tlen
= GLYPH_TABLE_LENGTH
;
604 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
605 Window window
= FRAME_W32_WINDOW (f
);
606 HDC hdc
= get_frame_dc (f
);
607 int orig_left
= left
;
613 /* Get the face-code of the next GLYPH. */
614 int cf
, len
, n_chars
;
617 Lisp_Object first_ch
;
618 /* HIGHEST and LOWEST are used while drawing a composite
619 character. The meanings are described later. */
622 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
623 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
624 ch
= FAST_GLYPH_CHAR (g
);
625 if (unibyte_display_via_language_environment
626 && SINGLE_BYTE_CHAR_P (ch
)
628 ch
= unibyte_char_to_multibyte (ch
);
629 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
630 charset
= CHAR_CHARSET (ch
);
631 if (charset
== CHARSET_COMPOSITION
)
633 /* We must draw components of the composite character on the
635 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
637 /* Set the face in the slot for work. */
638 cmpcharp
->face_work
= cf
;
640 /* We don't need the return value ... */
641 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
642 hl
, just_foreground
, cmpcharp
);
643 /* ... because the width of just drawn text can be
644 calculated as follows. */
645 left
+= FONT_WIDTH (FRAME_FONT (f
)) * cmpcharp
->width
;
648 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
653 /* Find the run of consecutive glyphs which can be drawn with
654 the same DC (i.e. the same charset and the same face-code).
655 Extract their character codes into X_2BYTE_BUFFER.
656 If CMPCHARP is not NULL, face-code is not checked because we
657 use only the face specified in `cmpcharp->face_work'. */
661 int this_charset
, c1
, c2
;
664 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
665 ch
= FAST_GLYPH_CHAR (g
);
666 if (unibyte_display_via_language_environment
667 && SINGLE_BYTE_CHAR_P (ch
)
669 ch
= unibyte_char_to_multibyte (ch
);
670 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
671 if (this_charset
!= charset
672 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
676 *cp
= BUILD_WCHAR_T (c1
, c2
);
678 *cp
= BUILD_WCHAR_T (0, c1
);
681 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
685 /* LEN gets the length of the run. */
686 len
= cp
- x_2byte_buffer
;
687 /* Now output this run of chars, with the font and pixel values
688 determined by the face code CF. */
690 struct face
*face
= FRAME_DEFAULT_FACE (f
);
691 XFontStruct
*font
= NULL
;
693 struct font_info
*fontp
;
698 int line_height
= FRAME_LINE_HEIGHT (f
);
699 /* Pixel width of each glyph in this run. */
701 = (FONT_WIDTH (FRAME_FONT (f
))
702 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
703 /* Overall pixel width of this run. */
705 = (FONT_WIDTH (FRAME_FONT (f
))
706 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
707 /* A flag to tell if we have already filled background. We
708 fill background in advance in the following cases:
709 1) A face has stipple.
710 2) A height of font is shorter than LINE_HEIGHT.
711 3) Drawing a composite character.
712 4) Font has non-zero _MULE_BASELINE_OFFSET property.
713 5) Font is a bdf font.
714 6) Font is italic (italic fonts falsely report their height).
715 After filling background, we draw glyphs by XDrawString16. */
716 int background_filled
;
717 /* Baseline position of a character, offset from TOP. */
719 /* The property value of `_MULE_RELATIVE_COMPOSE' and
720 `_MULE_DEFAULT_ASCENT'. */
721 int relative_compose
= 0, default_ascent
= 0;
722 /* 1 if we find no font or a font of inappropriate size. */
723 int require_clipping
;
725 LPRECT clip_region
= NULL
;
728 int codepage
= CP_DEFAULT
;
729 BOOL print_via_unicode
= FALSE
;
731 /* HL = 3 means use a mouse face previously chosen. */
733 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
735 /* First look at the face of the text itself. */
738 /* It's possible for the display table to specify
739 a face code that is out of range. Use 0 in that case. */
740 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
741 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
745 face
= FRAME_MODE_LINE_FACE (f
);
747 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
748 if (FACE_STIPPLE (face
))
752 /* Then comes the distinction between modeline and normal text. */
757 face
= FRAME_MODE_LINE_FACE (f
);
758 if (FACE_STIPPLE (face
))
762 /* Setting appropriate font and codepage for this charset. */
763 if (charset
!= CHARSET_ASCII
)
765 fontset
= FACE_FONTSET (face
);
767 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
768 || !(fontp
= FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
769 charset
, NULL
, fontset
)))
772 font
= (XFontStruct
*) (fontp
->font
);
773 codepage
= w32_codepage_for_font (fontp
->name
);
775 if ( font
&& !font
->bdf
)
776 print_via_unicode
= w32_use_unicode_for_codepage (codepage
);
778 baseline
= FONT_BASE (font
) + fontp
->baseline_offset
;
780 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
782 relative_compose
= fontp
->relative_compose
;
783 default_ascent
= fontp
->default_ascent
;
786 /* We have to change code points in the following cases. */
787 if (fontp
->font_encoder
)
789 /* This font requires CCL program to calculate code
790 point of characters. */
791 struct ccl_program
*ccl
= fontp
->font_encoder
;
793 if (CHARSET_DIMENSION (charset
) == 1)
794 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
796 ccl
->reg
[0] = charset
;
797 ccl
->reg
[1] = BYTE2 (*cp
);
798 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
799 /* We assume that MSBs are appropriately
800 set/reset by CCL program. */
801 #if 0 /* this probably works under NT, but not under 95. */
802 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
803 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
805 *cp
= BUILD_WCHAR_T (ccl
->reg
[1], ccl
->reg
[2]);
806 #else /* Assume single dimensional charsets stay so. */
807 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
811 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
813 ccl
->reg
[0] = charset
;
814 ccl
->reg
[1] = BYTE1 (*cp
) , ccl
->reg
[2] = BYTE2 (*cp
);
815 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
816 /* We assume that MSBs are appropriately
817 set/reset by CCL program. */
818 #if 0 /* this probably works under NT, but not under 95. */
819 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
820 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
822 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
823 #else /* Assume multidimensional charsets stay so. */
824 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
828 else if (fontp
->encoding
[charset
])
830 int enc
= fontp
->encoding
[charset
];
832 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
833 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
834 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
) | 0x80, BYTE2 (*cp
));
835 if (enc
== 1 || enc
== 3)
836 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
837 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
), BYTE2 (*cp
) | 0x80);
838 /* Special encoding for SJIS Kanji. */
841 if (CHARSET_DIMENSION (charset
) == 2)
844 for (cp
= x_2byte_buffer
;
845 cp
< x_2byte_buffer
+ len
; cp
++)
847 ENCODE_SJIS (BYTE1 (*cp
), BYTE2 (*cp
),
849 *cp
= BUILD_WCHAR_T (sjis1
, sjis2
);
853 for (cp
= x_2byte_buffer
;
854 cp
< x_2byte_buffer
+ len
; cp
++)
855 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
863 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
865 font
= FACE_FONT (face
);
866 if (!font
|| font
== (XFontStruct
*) FACE_DEFAULT
)
867 font
= FRAME_FONT (f
);
868 baseline
= FONT_BASE (FRAME_FONT (f
));
869 if (charset
== charset_latin_iso8859_1
)
871 if (!font
->bdf
&& font
->tm
.tmLastChar
< 0x80)
872 /* This font can't display Latin1 characters. */
876 for (cp
= x_2byte_buffer
;
877 cp
< x_2byte_buffer
+ len
; cp
++)
878 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
885 fg
= face
->foreground
;
886 bg
= face
->background
;
888 /* Now override that if the cursor's on this character. */
891 /* The cursor overrides stippling. */
894 if (font
== FRAME_FONT (f
)
895 && face
->background
== FRAME_BACKGROUND_PIXEL (f
)
896 && face
->foreground
== FRAME_FOREGROUND_PIXEL (f
)
899 bg
= f
->output_data
.w32
->cursor_pixel
;
900 fg
= face
->background
;
902 /* Cursor on non-default face: must merge. */
905 bg
= f
->output_data
.w32
->cursor_pixel
;
906 fg
= face
->background
;
907 /* If the glyph would be invisible,
908 try a different foreground. */
910 fg
= face
->foreground
;
912 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
914 fg
= face
->foreground
;
915 /* Make sure the cursor is distinct from text in this face. */
916 if (bg
== face
->background
917 && fg
== face
->foreground
)
919 bg
= face
->foreground
;
920 fg
= face
->background
;
926 require_clipping
= (!NILP (Vclip_large_size_font
)
928 ? (font
->bdf
->ury
> baseline
929 || font
->bdf
->lly
> line_height
- baseline
)
930 : (font
->tm
.tmAscent
> baseline
931 || font
->tm
.tmDescent
> line_height
- baseline
))
932 || (!cmpcharp
&& FONT_MAX_WIDTH (font
) > glyph_width
)));
934 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
935 background_filled
= 1;
937 /* Stippling not supported under w32. */
941 || FONT_HEIGHT (font
) < line_height
942 || FONT_WIDTH (font
) < glyph_width
943 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
)
947 /* Fill in the background for the current run. */
948 w32_fill_area (f
, hdc
, bg
,
953 background_filled
= 1;
955 /* To assure not to fill background while drawing
956 remaining components. */
960 background_filled
= 0;
962 SetBkMode (hdc
, background_filled
? TRANSPARENT
: OPAQUE
);
963 SetTextColor (hdc
, fg
);
964 SetBkColor (hdc
, bg
);
965 SetTextAlign (hdc
, TA_BASELINE
| TA_LEFT
);
967 /* On NT, where conversion to Unicode has to happen sometime
968 when using the normal ExtTextOut facility, we might as well
969 take advantage of x_2byte_buffer which is already allocated,
970 to avoid the allocation overhead for implicit conversion. */
972 if (!print_via_unicode
973 && codepage
== CP_DEFAULT
974 && w32_enable_unicode_output
975 && os_subtype
== OS_NT
976 && font
&& !font
->bdf
)
978 print_via_unicode
= TRUE
;
981 /* Note that we can special-case the conversion to Unicode when
982 the charset is CHARSET_ASCII (an important case) or Latin-1,
983 because x_2byte_buffer in fact already contains the unicode
984 characters. So avoid setting up x_1byte_buffer in that case. */
985 if (!print_via_unicode
986 || (charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
))
988 /* Convert x_2byte_buffer into a buffer of single byte
989 characters - possibly containing MBCS runs. */
991 for (i
= 0; i
< len
; i
++)
993 if (BYTE1 (*(x_2byte_buffer
+ i
)))
994 *bp
++ = BYTE1 (*(x_2byte_buffer
+ i
));
995 *bp
++ = BYTE2 (*(x_2byte_buffer
+ i
));
997 n_chars
= bp
- x_1byte_buffer
;
1002 if (print_via_unicode
1003 && charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
)
1005 i
= MultiByteToWideChar
1006 (codepage
, 0, x_1byte_buffer
, n_chars
,
1007 x_2byte_buffer
, FRAME_WINDOW_WIDTH (f
));
1009 /* Make sure we don't display nothing if conversion fails. */
1011 print_via_unicode
= FALSE
;
1019 SelectObject (hdc
, font
->hfont
);
1023 int xoffset
= 0, yoffset
= baseline
;
1024 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
1025 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
))
1027 /* The incrementing of i in this loop is done
1028 inside the W32_CHAROUT macro. */
1029 for (i
= 0; i
< n_chars
; )
1031 if (require_clipping
)
1033 /* Set up a clipping rectangle for ExtTextOut */
1034 fuOptions
|= ETO_CLIPPED
;
1035 clip_rectangle
.left
= left
+ i
* glyph_width
;
1036 clip_rectangle
.right
1037 = left
+ (i
+ 1) * glyph_width
;
1038 clip_rectangle
.top
= top
;
1039 clip_rectangle
.bottom
= top
+ line_height
;
1040 clip_region
= &clip_rectangle
;
1048 W32_TEXTOUT (i
, n_chars
);
1053 /* Handle composite characters. */
1054 RECT clip_rectangle
;
1055 LPRECT clip_region
= NULL
;
1060 if (require_clipping
)
1062 /* Set up a clipping rectangle for ExtTextOut */
1063 fuOptions
|= ETO_CLIPPED
;
1064 clip_rectangle
.left
= left
;
1065 clip_rectangle
.right
= left
+ glyph_width
;
1066 clip_rectangle
.top
= top
;
1067 clip_rectangle
.bottom
= top
+ line_height
;
1068 clip_region
= &clip_rectangle
;
1070 if ((cmpcharp
->cmp_rule
|| relative_compose
)
1073 /* This is the first character. Initialize variables.
1074 HIGHEST is the highest position of glyphs ever
1075 written, LOWEST the lowest position. */
1077 int yoffset
= baseline
;
1081 && CHAR_TABLE_P (Vuse_default_ascent
)
1082 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
1084 highest
= default_ascent
;
1087 /* TODO: per char metrics for Truetype and BDF
1090 highest
= FONT_BASE (font
) + 1;
1091 lowest
= - (FONT_HEIGHT (font
) - FONT_BASE (font
));
1094 if (cmpcharp
->cmp_rule
)
1095 xoffset
= (int)(cmpcharp
->col_offset
[0]
1096 * FONT_WIDTH (FRAME_FONT (f
)));
1100 /* Truetype fonts often contain underhangs to
1101 handle composition characters. This works
1102 against our attempts to position the characters
1103 manually, so we need to compensate for this.
1105 if (print_via_unicode
?
1106 GetCharABCWidthsW (hdc
, *x_2byte_buffer
,
1109 : GetCharABCWidths (hdc
, *x_1byte_buffer
,
1113 char_width
= char_placement
.abcA
1114 + char_placement
.abcB
+ char_placement
.abcC
;
1115 xoffset
+= FONT_WIDTH (font
) - char_width
;
1117 /* Don't let characters go beyond the glyph
1118 boundary whatever their over/underhangs. */
1119 if (xoffset
> glyph_width
- char_width
)
1120 xoffset
= glyph_width
- char_width
;
1125 /* Draw the first character at the normal
1127 W32_TEXTOUT (start
, 1);
1133 for (; i
< n_chars
; gidx
++)
1135 int xoffset
= 0, yoffset
= FONT_BASE (font
);
1137 if (relative_compose
)
1139 /* No per char metrics on w32. */
1140 if (NILP (Vignore_relative_composition
)
1141 || NILP (Faref (Vignore_relative_composition
,
1142 make_number (cmpcharp
->glyph
[gidx
]))))
1144 if (- (FONT_HEIGHT (font
) - FONT_BASE (font
))
1145 >= relative_compose
)
1147 /* Draw above the current glyphs. */
1148 yoffset
= highest
+ FONT_HEIGHT (font
);
1149 highest
+= FONT_HEIGHT (font
);
1151 else if (FONT_BASE (font
) <= 0)
1153 /* Draw beneath the current glyphs. */
1155 lowest
-= FONT_HEIGHT (font
);
1160 /* Draw the glyph at normal position. If
1161 it sticks out of HIGHEST or LOWEST,
1162 update them appropriately. */
1163 if (FONT_BASE (font
) > highest
)
1164 highest
= FONT_BASE (font
);
1165 else if (- (FONT_HEIGHT (font
) - FONT_BASE (font
))
1167 lowest
= - (FONT_HEIGHT (font
) -
1171 else if (cmpcharp
->cmp_rule
)
1173 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1174 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1177 /* Re-encode GREF and NREF so that they specify
1178 only Y-axis information:
1179 0:top, 1:base, 2:bottom, 3:center */
1180 gref
= gref
/ 3 + (gref
== 4) * 2;
1181 nref
= nref
/ 3 + (nref
== 4) * 2;
1183 /* No per char metrics on w32. */
1184 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1185 : gref
== 2 ? lowest
1186 : (highest
+ lowest
) / 2)
1187 - (nref
== 0 ? FONT_HEIGHT (font
)
1188 : nref
== 1 ? (FONT_HEIGHT (font
) -
1191 : (FONT_HEIGHT (font
) / 2)));
1192 top
= bottom
+ FONT_HEIGHT (font
);
1196 if (bottom
< lowest
)
1198 yoffset
= bottom
+ FONT_HEIGHT (font
);
1199 xoffset
= (int)(cmpcharp
->col_offset
[gidx
]
1200 * FONT_WIDTH (FRAME_FONT(f
)));
1203 /* Truetype fonts often contain underhangs to
1204 handle composition characters. This works
1205 against our attempts to position the characters
1206 manually, so we need to compensate for this.
1208 if (print_via_unicode
?
1209 GetCharABCWidthsW (hdc
, *(x_2byte_buffer
+ i
),
1210 *(x_2byte_buffer
+ i
),
1212 : GetCharABCWidths (hdc
, *(x_1byte_buffer
+ i
),
1213 *(x_1byte_buffer
+ i
),
1216 char_width
= char_placement
.abcA
1217 + char_placement
.abcB
+ char_placement
.abcC
;
1218 xoffset
+= FONT_WIDTH (font
) - char_width
;
1220 /* Don't let characters go beyond the glyph
1221 boundary whatever their over/underhangs. */
1222 if (xoffset
> glyph_width
- char_width
)
1223 xoffset
= glyph_width
- char_width
;
1234 /* Show rectangles to indicate that we found no font. */
1235 int limit
= cmpcharp
? 1 : len
;
1237 for (i
= 0; i
< limit
; i
++)
1238 Rectangle (hdc
, left
+ glyph_width
* i
, top
,
1239 left
+ glyph_width
* (i
+ 1) - 1,
1240 top
+ line_height
- 1);
1242 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1244 /* Indicate that we found a font of inappropriate size. */
1245 int limit
= cmpcharp
? 1 : len
;
1247 for (i
= 0; i
< limit
; i
++)
1249 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1250 top
+ line_height
- 1, glyph_width
, 1);
1251 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1252 top
+ line_height
- 3, 1, 2);
1256 /* Setting underline position based on the metric of the
1257 current font results in shaky underline if it strides
1258 over different fonts. So, we set the position based only
1259 on the default font of this frame. */
1260 int underline_position
= 1;
1262 if (FONT_HEIGHT (FRAME_FONT (f
)) - FONT_BASE(FRAME_FONT (f
))
1263 <= underline_position
)
1264 underline_position
= (FONT_HEIGHT (FRAME_FONT (f
)) -
1265 FONT_BASE(FRAME_FONT (f
))) - 1;
1267 if (face
->underline
)
1268 w32_fill_area (f
, hdc
, fg
, left
,
1269 top
+ FONT_BASE (FRAME_FONT (f
))
1270 + underline_position
,
1278 release_frame_dc (f
, hdc
);
1280 return (left
- orig_left
);
1284 /* Output some text at the nominal frame cursor position.
1285 Advance the cursor over the text.
1286 Output LEN glyphs at START.
1288 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
1289 controls the pixel values used for foreground and background. */
1292 w32_write_glyphs (start
, len
)
1293 register GLYPH
*start
;
1296 register int temp_length
;
1306 /* If not within an update,
1307 output at the frame's visible cursor. */
1308 curs_x
= f
->cursor_x
;
1309 curs_y
= f
->cursor_y
;
1313 CHAR_TO_PIXEL_COL (f
, curs_x
),
1314 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1315 start
, len
, highlight
, 0, NULL
);
1317 /* If we drew on top of the cursor, note that it is turned off. */
1318 if (curs_y
== f
->phys_cursor_y
1319 && curs_x
<= f
->phys_cursor_x
1320 && curs_x
+ len
> f
->phys_cursor_x
)
1321 f
->phys_cursor_on
= 0;
1323 if (updating_frame
== 0)
1326 x_display_cursor (f
, 1);
1335 /* Clear to the end of the line.
1336 Erase the current text line from the nominal cursor position (inclusive)
1337 to column FIRST_UNUSED (exclusive). The idea is that everything
1338 from FIRST_UNUSED onward is already erased. */
1341 w32_clear_end_of_line (first_unused
)
1342 register int first_unused
;
1344 struct frame
*f
= updating_frame
;
1349 if (curs_y
< 0 || curs_y
>= f
->height
)
1351 if (first_unused
<= 0)
1354 if (first_unused
>= f
->width
)
1355 first_unused
= f
->width
;
1357 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1363 /* Notice if the cursor will be cleared by this operation. */
1364 if (curs_y
== f
->phys_cursor_y
1365 && curs_x
<= f
->phys_cursor_x
1366 && f
->phys_cursor_x
< first_unused
)
1367 f
->phys_cursor_on
= 0;
1369 w32_clear_area (f
, NULL
,
1370 CHAR_TO_PIXEL_COL (f
, curs_x
),
1371 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1372 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
1373 f
->output_data
.w32
->line_height
);
1381 struct frame
*f
= updating_frame
;
1386 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1387 curs_x
= 0; /* Nominal cursor position is top left. */
1392 w32_clear_window (f
);
1394 /* We have to clear the scroll bars, too. If we have changed
1395 colors or something like that, then they should be notified. */
1396 x_scroll_bar_clear (f
);
1401 /* Make audible bell. */
1404 w32_ring_bell (void)
1411 HWND hwnd
= FRAME_W32_WINDOW (selected_frame
);
1413 for (i
= 0; i
< 5; i
++)
1415 FlashWindow (hwnd
, TRUE
);
1418 FlashWindow (hwnd
, FALSE
);
1421 w32_sys_ring_bell ();
1426 /* Insert and delete character.
1427 These are not supposed to be used because we are supposed to turn
1428 off the feature of using them. */
1431 w32_insert_glyphs (start
, len
)
1432 register GLYPH
*start
;
1439 w32_delete_glyphs (n
)
1445 /* Specify how many text lines, from the top of the window,
1446 should be affected by insert-lines and delete-lines operations.
1447 This, and those operations, are used only within an update
1448 that is bounded by calls to w32_update_begin and w32_update_end. */
1451 w32_set_terminal_window (n
)
1454 if (updating_frame
== 0)
1457 if ((n
<= 0) || (n
> updating_frame
->height
))
1458 flexlines
= updating_frame
->height
;
1463 /* These variables need not be per frame
1464 because redisplay is done on a frame-by-frame basis
1465 and the line dance for one frame is finished before
1466 anything is done for another frame. */
1468 /* Array of line numbers from cached insert/delete operations.
1469 line_dance[i] is the old position of the line that we want
1470 to move to line i, or -1 if we want a blank line there. */
1471 static int *line_dance
;
1473 /* Allocated length of that array. */
1474 static int line_dance_len
;
1476 /* Flag indicating whether we've done any work. */
1477 static int line_dance_in_progress
;
1479 /* Perform an insert-lines or delete-lines operation,
1480 inserting N lines or deleting -N lines at vertical position VPOS. */
1483 w32_ins_del_lines (vpos
, n
)
1486 register int fence
, i
;
1488 if (vpos
>= flexlines
)
1491 if (!line_dance_in_progress
)
1493 int ht
= updating_frame
->height
;
1494 if (ht
> line_dance_len
)
1496 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1497 line_dance_len
= ht
;
1499 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1500 line_dance_in_progress
= 1;
1504 if (n
> flexlines
- vpos
)
1505 n
= flexlines
- vpos
;
1507 for (i
= flexlines
; --i
>= fence
;)
1508 line_dance
[i
] = line_dance
[i
-n
];
1509 for (i
= fence
; --i
>= vpos
;)
1515 if (n
> flexlines
- vpos
)
1516 n
= flexlines
- vpos
;
1517 fence
= flexlines
- n
;
1518 for (i
= vpos
; i
< fence
; ++i
)
1519 line_dance
[i
] = line_dance
[i
+ n
];
1520 for (i
= fence
; i
< flexlines
; ++i
)
1525 /* Here's where we actually move the pixels around.
1526 Must be called with input blocked. */
1530 register int i
, j
, distance
;
1531 register struct frame
*f
;
1536 /* Must check this flag first. If it's not set, then not only is the
1537 array uninitialized, but we might not even have a frame. */
1538 if (!line_dance_in_progress
)
1546 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1548 x_display_cursor (updating_frame
, 0);
1550 hdc
= get_frame_dc (f
);
1552 for (i
= 0; i
< ht
; ++i
)
1553 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1555 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1556 && line_dance
[j
]-j
== distance
); ++j
);
1557 /* Copy [i,j) upward from [i+distance, j+distance) */
1559 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1560 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1561 (j
-i
) * FRAME_LINE_HEIGHT (f
),
1563 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1568 for (i
= ht
; --i
>=0; )
1569 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1571 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1572 && line_dance
[j
]-j
== distance
););
1573 /* Copy (j, i] downward from (j+distance, i+distance] */
1575 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1576 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1577 (i
-j
) * FRAME_LINE_HEIGHT (f
),
1579 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1584 for (i
= 0; i
< ht
; ++i
)
1585 if (line_dance
[i
] == -1)
1587 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1589 w32_clear_area (f
, hdc
,
1591 CHAR_TO_PIXEL_ROW (f
, i
),
1592 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1593 (j
-i
) * FRAME_LINE_HEIGHT (f
));
1596 line_dance_in_progress
= 0;
1598 release_frame_dc (f
, hdc
);
1601 /* Support routines for exposure events. */
1602 static void clear_cursor ();
1604 /* Output into a rectangle of a window (for frame F)
1605 the characters in f->phys_lines that overlap that rectangle.
1606 TOP and LEFT are the position of the upper left corner of the rectangle.
1607 ROWS and COLS are the size of the rectangle.
1608 Call this function with input blocked. */
1611 dumprectangle (f
, left
, top
, cols
, rows
)
1613 register int left
, top
, cols
, rows
;
1615 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1616 int cursor_cleared
= 0;
1620 if (FRAME_GARBAGED_P (f
))
1623 /* Express rectangle as four edges, instead of position-and-size. */
1624 bottom
= top
+ rows
;
1625 right
= left
+ cols
;
1627 /* Convert rectangle edges in pixels to edges in chars.
1628 Round down for left and top, up for right and bottom. */
1629 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1630 left
= PIXEL_TO_CHAR_COL (f
, left
);
1631 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1632 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1633 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1634 right
= PIXEL_TO_CHAR_COL (f
, right
);
1636 /* Clip the rectangle to what can be visible. */
1637 if (left
< FRAME_LEFT_SCROLL_BAR_WIDTH (f
))
1638 left
= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1641 if (right
> f
->width
+ FRAME_LEFT_SCROLL_BAR_WIDTH (f
))
1642 right
= f
->width
+ FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1643 if (bottom
> f
->height
)
1646 /* Get size in chars of the rectangle. */
1647 cols
= right
- left
;
1648 rows
= bottom
- top
;
1650 /* If rectangle has zero area, return. */
1651 if (rows
<= 0) return;
1652 if (cols
<= 0) return;
1654 /* Turn off the cursor if it is in the rectangle.
1655 We will turn it back on afterward. */
1656 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1657 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1663 /* Display the text in the rectangle, one text line at a time. */
1665 for (y
= top
; y
< bottom
; y
++)
1667 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1669 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1673 CHAR_TO_PIXEL_COL (f
, left
),
1674 CHAR_TO_PIXEL_ROW (f
, y
),
1675 line
, min (cols
, active_frame
->used
[y
] - left
),
1676 active_frame
->highlight
[y
], 0, NULL
);
1679 /* Turn the cursor on if we turned it off. */
1682 x_display_cursor (f
, 1);
1689 x_display_cursor (f
, 1);
1693 frame_unhighlight (f
)
1696 x_display_cursor (f
, 1);
1699 static void x_frame_rehighlight ();
1701 /* The focus has changed. Update the frames as necessary to reflect
1702 the new situation. Note that we can't change the selected frame
1703 here, because the Lisp code we are interrupting might become confused.
1704 Each event gets marked with the frame in which it occurred, so the
1705 Lisp code can tell when the switch took place by examining the events. */
1708 x_new_focus_frame (dpyinfo
, frame
)
1709 struct w32_display_info
*dpyinfo
;
1710 struct frame
*frame
;
1712 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1713 int events_enqueued
= 0;
1715 if (frame
!= dpyinfo
->w32_focus_frame
)
1717 /* Set this before calling other routines, so that they see
1718 the correct value of w32_focus_frame. */
1719 dpyinfo
->w32_focus_frame
= frame
;
1721 if (old_focus
&& old_focus
->auto_lower
)
1722 x_lower_frame (old_focus
);
1724 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1725 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1727 pending_autoraise_frame
= 0;
1730 x_frame_rehighlight (dpyinfo
);
1733 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1736 x_mouse_leave (dpyinfo
)
1737 struct w32_display_info
*dpyinfo
;
1739 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1742 /* The focus has changed, or we have redirected a frame's focus to
1743 another frame (this happens when a frame uses a surrogate
1744 minibuffer frame). Shift the highlight as appropriate.
1746 The FRAME argument doesn't necessarily have anything to do with which
1747 frame is being highlighted or unhighlighted; we only use it to find
1748 the appropriate display info. */
1750 w32_frame_rehighlight (frame
)
1751 struct frame
*frame
;
1753 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1757 x_frame_rehighlight (dpyinfo
)
1758 struct w32_display_info
*dpyinfo
;
1760 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1762 if (dpyinfo
->w32_focus_frame
)
1764 dpyinfo
->w32_highlight_frame
1765 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1766 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1767 : dpyinfo
->w32_focus_frame
);
1768 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1770 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1771 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1775 dpyinfo
->w32_highlight_frame
= 0;
1777 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1780 frame_unhighlight (old_highlight
);
1781 if (dpyinfo
->w32_highlight_frame
)
1782 frame_highlight (dpyinfo
->w32_highlight_frame
);
1786 /* Keyboard processing - modifier keys, etc. */
1788 /* Convert a keysym to its name. */
1791 x_get_keysym_name (keysym
)
1794 /* Make static so we can always return it */
1795 static char value
[100];
1798 GetKeyNameText(keysym
, value
, 100);
1804 /* Mouse clicks and mouse movement. Rah. */
1806 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1807 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1808 that the glyph at X, Y occupies, if BOUNDS != 0.
1809 If NOCLIP is nonzero, do not force the value into range. */
1812 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1814 register int pix_x
, pix_y
;
1815 register int *x
, *y
;
1819 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1820 if (NILP (Vwindow_system
))
1827 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1828 even for negative values. */
1830 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1832 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1834 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1835 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1839 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1840 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1841 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1842 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1849 else if (pix_x
> f
->width
)
1854 else if (pix_y
> f
->height
)
1863 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1866 register int *pix_x
, *pix_y
;
1868 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1869 if (NILP (Vwindow_system
))
1876 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1877 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1881 parse_button (message
, pbutton
, pup
)
1891 case WM_LBUTTONDOWN
:
1899 case WM_MBUTTONDOWN
:
1900 if (NILP (Vw32_swap_mouse_buttons
))
1907 if (NILP (Vw32_swap_mouse_buttons
))
1913 case WM_RBUTTONDOWN
:
1914 if (NILP (Vw32_swap_mouse_buttons
))
1921 if (NILP (Vw32_swap_mouse_buttons
))
1932 if (pbutton
) *pbutton
= button
;
1938 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1940 If the event is a button press, then note that we have grabbed
1944 construct_mouse_click (result
, msg
, f
)
1945 struct input_event
*result
;
1952 parse_button (msg
->msg
.message
, &button
, &up
);
1954 /* Make the event type no_event; we'll change that when we decide
1956 result
->kind
= mouse_click
;
1957 result
->code
= button
;
1958 result
->timestamp
= msg
->msg
.time
;
1959 result
->modifiers
= (msg
->dwModifiers
1967 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1968 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1969 XSETFRAME (result
->frame_or_window
, f
);
1974 construct_mouse_wheel (result
, msg
, f
)
1975 struct input_event
*result
;
1980 result
->kind
= mouse_wheel
;
1981 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1982 result
->timestamp
= msg
->msg
.time
;
1983 result
->modifiers
= msg
->dwModifiers
;
1984 p
.x
= LOWORD (msg
->msg
.lParam
);
1985 p
.y
= HIWORD (msg
->msg
.lParam
);
1986 ScreenToClient(msg
->msg
.hwnd
, &p
);
1987 XSETINT (result
->x
, p
.x
);
1988 XSETINT (result
->y
, p
.y
);
1989 XSETFRAME (result
->frame_or_window
, f
);
1993 construct_drag_n_drop (result
, msg
, f
)
1994 struct input_event
*result
;
2006 result
->kind
= drag_n_drop
;
2008 result
->timestamp
= msg
->msg
.time
;
2009 result
->modifiers
= msg
->dwModifiers
;
2011 hdrop
= (HDROP
) msg
->msg
.wParam
;
2012 DragQueryPoint (hdrop
, &p
);
2015 p
.x
= LOWORD (msg
->msg
.lParam
);
2016 p
.y
= HIWORD (msg
->msg
.lParam
);
2017 ScreenToClient (msg
->msg
.hwnd
, &p
);
2020 XSETINT (result
->x
, p
.x
);
2021 XSETINT (result
->y
, p
.y
);
2023 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
2026 for (i
= 0; i
< num_files
; i
++)
2028 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
2031 name
= alloca (len
+ 1);
2032 DragQueryFile (hdrop
, i
, name
, len
+ 1);
2033 files
= Fcons (build_string (name
), files
);
2038 XSETFRAME (frame
, f
);
2039 result
->frame_or_window
= Fcons (frame
, files
);
2043 /* Function to report a mouse movement to the mainstream Emacs code.
2044 The input handler calls this.
2046 We have received a mouse movement event, which is given in *event.
2047 If the mouse is over a different glyph than it was last time, tell
2048 the mainstream emacs code by setting mouse_moved. If not, ask for
2049 another motion event, so we can check again the next time it moves. */
2052 note_mouse_movement (frame
, msg
)
2056 last_mouse_movement_time
= msg
->time
;
2058 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
2060 frame
->mouse_moved
= 1;
2061 last_mouse_scroll_bar
= Qnil
;
2063 note_mouse_highlight (frame
, -1, -1);
2066 /* Has the mouse moved off the glyph it was on at the last sighting? */
2067 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
2068 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
2069 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
2070 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
2072 frame
->mouse_moved
= 1;
2073 last_mouse_scroll_bar
= Qnil
;
2075 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
2079 /* This is used for debugging, to turn off note_mouse_highlight. */
2080 static int disable_mouse_highlight
;
2082 /* Take proper action when the mouse has moved to position X, Y on frame F
2083 as regards highlighting characters that have mouse-face properties.
2084 Also dehighlighting chars where the mouse was before.
2085 X and Y can be negative or out of range. */
2088 note_mouse_highlight (f
, x
, y
)
2092 int row
, column
, portion
;
2097 if (disable_mouse_highlight
)
2100 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2101 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2102 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2104 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
2109 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2113 /* Find out which glyph the mouse is on. */
2114 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2115 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
2117 /* Which window is that in? */
2118 window
= window_from_coordinates (f
, column
, row
, &portion
);
2119 w
= XWINDOW (window
);
2121 /* If we were displaying active text in another window, clear that. */
2122 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
2123 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2125 /* Are we in a window whose display is up to date?
2126 And verify the buffer's text has not changed. */
2127 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2128 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2129 && EQ (w
->window_end_valid
, w
->buffer
)
2130 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2131 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2133 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2136 /* Find which buffer position the mouse corresponds to. */
2137 for (i
= column
; i
>= 0; i
--)
2141 /* Is it outside the displayed active region (if any)? */
2143 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2144 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
2145 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2146 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2147 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2148 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2149 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2150 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2151 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2153 Lisp_Object mouse_face
, overlay
, position
;
2154 Lisp_Object
*overlay_vec
;
2155 int len
, noverlays
, ignor1
;
2156 struct buffer
*obuf
;
2159 /* If we get an out-of-range value, return now; avoid an error. */
2160 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2163 /* Make the window's buffer temporarily current for
2164 overlays_at and compute_char_face. */
2165 obuf
= current_buffer
;
2166 current_buffer
= XBUFFER (w
->buffer
);
2172 /* Yes. Clear the display of the old active region, if any. */
2173 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2175 /* Is this char mouse-active? */
2176 XSETINT (position
, pos
);
2179 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2181 /* Put all the overlays we want in a vector in overlay_vec.
2182 Store the length in len. */
2183 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2185 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2187 /* Find the highest priority overlay that has a mouse-face prop. */
2189 for (i
= 0; i
< noverlays
; i
++)
2191 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2192 if (!NILP (mouse_face
))
2194 overlay
= overlay_vec
[i
];
2199 /* If no overlay applies, get a text property. */
2201 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2203 /* Handle the overlay case. */
2204 if (! NILP (overlay
))
2206 /* Find the range of text around this char that
2207 should be active. */
2208 Lisp_Object before
, after
;
2211 before
= Foverlay_start (overlay
);
2212 after
= Foverlay_end (overlay
);
2213 /* Record this as the current active region. */
2214 fast_find_position (window
, before
,
2215 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2216 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2217 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2218 = !fast_find_position (window
, after
,
2219 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2220 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2221 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2222 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2223 = compute_char_face (f
, w
, pos
, 0, 0,
2224 &ignore
, pos
+ 1, 1);
2226 /* Display it as active. */
2227 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2229 /* Handle the text property case. */
2230 else if (! NILP (mouse_face
))
2232 /* Find the range of text around this char that
2233 should be active. */
2234 Lisp_Object before
, after
, beginning
, end
;
2237 beginning
= Fmarker_position (w
->start
);
2238 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2239 - XFASTINT (w
->window_end_pos
)));
2241 = Fprevious_single_property_change (make_number (pos
+ 1),
2243 w
->buffer
, beginning
);
2245 = Fnext_single_property_change (position
, Qmouse_face
,
2247 /* Record this as the current active region. */
2248 fast_find_position (window
, before
,
2249 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2250 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2251 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2252 = !fast_find_position (window
, after
,
2253 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2254 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2255 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2256 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2257 = compute_char_face (f
, w
, pos
, 0, 0,
2258 &ignore
, pos
+ 1, 1);
2260 /* Display it as active. */
2261 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2265 current_buffer
= obuf
;
2270 /* Find the row and column of position POS in window WINDOW.
2271 Store them in *COLUMNP and *ROWP.
2272 This assumes display in WINDOW is up to date.
2273 If POS is above start of WINDOW, return coords
2274 of start of first screen line.
2275 If POS is after end of WINDOW, return coords of end of last screen line.
2277 Value is 1 if POS is in range, 0 if it was off screen. */
2280 fast_find_position (window
, pos
, columnp
, rowp
)
2283 int *columnp
, *rowp
;
2285 struct window
*w
= XWINDOW (window
);
2286 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2289 int left
= WINDOW_LEFT_MARGIN (w
);
2291 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2292 int width
= window_internal_width (w
);
2295 int maybe_next_line
= 0;
2297 /* Find the right row. */
2302 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2303 if (linestart
> pos
)
2305 /* If the position sought is the end of the buffer,
2306 don't include the blank lines at the bottom of the window. */
2307 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2309 maybe_next_line
= 1;
2316 /* Find the right column with in it. */
2317 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2319 for (i
= 0; i
< width
; i
++)
2321 if (charstarts
[left
+ i
] == pos
)
2324 *columnp
= i
+ left
;
2327 else if (charstarts
[left
+ i
] > pos
)
2329 else if (charstarts
[left
+ i
] > 0)
2333 /* If we're looking for the end of the buffer,
2334 and we didn't find it in the line we scanned,
2335 use the start of the following line. */
2336 if (maybe_next_line
)
2347 /* Display the active region described by mouse_face_*
2348 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2351 show_mouse_face (dpyinfo
, hl
)
2352 struct w32_display_info
*dpyinfo
;
2355 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2356 int width
= window_internal_width (w
);
2357 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2360 int old_curs_x
= curs_x
;
2361 int old_curs_y
= curs_y
;
2363 /* Set these variables temporarily
2364 so that if we have to turn the cursor off and on again
2365 we will put it back at the same place. */
2366 curs_x
= f
->phys_cursor_x
;
2367 curs_y
= f
->phys_cursor_y
;
2369 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2370 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2372 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2373 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
2374 : WINDOW_LEFT_MARGIN (w
));
2375 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2376 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2377 : WINDOW_LEFT_MARGIN (w
) + width
);
2378 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2380 /* If the cursor's in the text we are about to rewrite,
2381 turn the cursor off. */
2383 && curs_x
>= column
- 1
2384 && curs_x
<= endcolumn
)
2386 x_display_cursor (f
, 0);
2391 CHAR_TO_PIXEL_COL (f
, column
),
2392 CHAR_TO_PIXEL_ROW (f
, i
),
2393 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2395 /* Highlight with mouse face if hl > 0. */
2396 hl
> 0 ? 3 : 0, 0, NULL
);
2399 /* If we turned the cursor off, turn it back on. */
2401 x_display_cursor (f
, 1);
2403 curs_x
= old_curs_x
;
2404 curs_y
= old_curs_y
;
2406 /* Change the mouse cursor according to the value of HL. */
2408 SetCursor (f
->output_data
.w32
->cross_cursor
);
2410 SetCursor (f
->output_data
.w32
->text_cursor
);
2413 /* Clear out the mouse-highlighted active region.
2414 Redraw it unhighlighted first. */
2417 clear_mouse_face (dpyinfo
)
2418 struct w32_display_info
*dpyinfo
;
2420 if (! NILP (dpyinfo
->mouse_face_window
))
2421 show_mouse_face (dpyinfo
, 0);
2423 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2424 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2425 dpyinfo
->mouse_face_window
= Qnil
;
2428 struct scroll_bar
*x_window_to_scroll_bar ();
2429 static void x_scroll_bar_report_motion ();
2431 /* Return the current position of the mouse.
2432 *fp should be a frame which indicates which display to ask about.
2434 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2435 and *part to the frame, window, and scroll bar part that the mouse
2436 is over. Set *x and *y to the portion and whole of the mouse's
2437 position on the scroll bar.
2439 If the mouse movement started elsewhere, set *fp to the frame the
2440 mouse is on, *bar_window to nil, and *x and *y to the character cell
2443 Set *time to the server timestamp for the time at which the mouse
2444 was at this position.
2446 Don't store anything if we don't have a valid set of values to report.
2448 This clears the mouse_moved flag, so we can wait for the next mouse
2449 movement. This also calls XQueryPointer, which will cause the
2450 server to give us another MotionNotify when the mouse moves
2454 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2457 Lisp_Object
*bar_window
;
2458 enum scroll_bar_part
*part
;
2460 unsigned long *time
;
2466 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2467 /* This is never called at the moment. */
2468 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2473 Lisp_Object frame
, tail
;
2475 /* Clear the mouse-moved flag for every frame on this display. */
2476 FOR_EACH_FRAME (tail
, frame
)
2477 XFRAME (frame
)->mouse_moved
= 0;
2479 last_mouse_scroll_bar
= Qnil
;
2483 /* Now we have a position on the root; find the innermost window
2484 containing the pointer. */
2486 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2487 && FRAME_LIVE_P (last_mouse_frame
))
2489 f1
= last_mouse_frame
;
2493 /* Is win one of our frames? */
2494 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
2497 /* If not, is it one of our scroll bars? */
2500 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
2504 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2508 if (f1
== 0 && insist
> 0)
2509 f1
= selected_frame
;
2513 int ignore1
, ignore2
;
2515 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
2517 /* Ok, we found a frame. Store all the values. */
2519 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
2521 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
2529 *time
= last_mouse_movement_time
;
2537 /* Scroll bar support. */
2539 /* Given an window ID, find the struct scroll_bar which manages it.
2540 This can be called in GC, so we have to make sure to strip off mark
2543 x_window_to_scroll_bar (window_id
)
2546 Lisp_Object tail
, frame
;
2548 for (tail
= Vframe_list
;
2549 XGCTYPE (tail
) == Lisp_Cons
;
2550 tail
= XCONS (tail
)->cdr
)
2552 Lisp_Object frame
, bar
, condemned
;
2554 frame
= XCONS (tail
)->car
;
2555 /* All elements of Vframe_list should be frames. */
2556 if (! GC_FRAMEP (frame
))
2559 /* Scan this frame's scroll bar list for a scroll bar with the
2561 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2562 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2563 /* This trick allows us to search both the ordinary and
2564 condemned scroll bar lists with one loop. */
2565 ! GC_NILP (bar
) || (bar
= condemned
,
2568 bar
= XSCROLL_BAR (bar
)->next
)
2569 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2570 return XSCROLL_BAR (bar
);
2577 my_create_scrollbar (f
, bar
)
2579 struct scroll_bar
* bar
;
2581 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2582 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2586 //#define ATTACH_THREADS
2589 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2591 #ifndef ATTACH_THREADS
2592 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2593 (WPARAM
) hwnd
, (LPARAM
) how
);
2595 return ShowWindow (hwnd
, how
);
2600 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2601 int x
, int y
, int cx
, int cy
, UINT flags
)
2603 #ifndef ATTACH_THREADS
2605 pos
.hwndInsertAfter
= hwndAfter
;
2611 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2613 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2618 my_set_focus (f
, hwnd
)
2622 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2627 my_set_foreground_window (hwnd
)
2630 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2634 my_destroy_window (f
, hwnd
)
2638 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2642 /* Open a new window to serve as a scroll bar, and return the
2643 scroll bar vector for it. */
2644 static struct scroll_bar
*
2645 x_scroll_bar_create (window
, top
, left
, width
, height
)
2646 struct window
*window
;
2647 int top
, left
, width
, height
;
2649 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2650 struct scroll_bar
*bar
2651 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2656 XSETWINDOW (bar
->window
, window
);
2657 XSETINT (bar
->top
, top
);
2658 XSETINT (bar
->left
, left
);
2659 XSETINT (bar
->width
, width
);
2660 XSETINT (bar
->height
, height
);
2661 XSETINT (bar
->start
, 0);
2662 XSETINT (bar
->end
, 0);
2663 bar
->dragging
= Qnil
;
2665 /* Requires geometry to be set before call to create the real window */
2667 hwnd
= my_create_scrollbar (f
, bar
);
2669 if (pfnSetScrollInfo
)
2673 si
.cbSize
= sizeof (si
);
2676 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2677 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2681 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2685 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2686 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2689 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2691 /* Add bar to its frame's list of scroll bars. */
2692 bar
->next
= FRAME_SCROLL_BARS (f
);
2694 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2695 if (! NILP (bar
->next
))
2696 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2703 /* Draw BAR's handle in the proper position.
2704 If the handle is already drawn from START to END, don't bother
2705 redrawing it, unless REBUILD is non-zero; in that case, always
2706 redraw it. (REBUILD is handy for drawing the handle after expose
2709 Normally, we want to constrain the start and end of the handle to
2710 fit inside its rectangle, but if the user is dragging the scroll bar
2711 handle, we want to let them drag it down all the way, so that the
2712 bar's top is as far down as it goes; otherwise, there's no way to
2713 move to the very end of the buffer. */
2715 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2716 struct scroll_bar
*bar
;
2720 int dragging
= ! NILP (bar
->dragging
);
2721 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2722 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2724 /* If the display is already accurate, do nothing. */
2726 && start
== XINT (bar
->start
)
2727 && end
== XINT (bar
->end
))
2733 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2735 /* Make sure the values are reasonable, and try to preserve
2736 the distance between start and end. */
2738 int length
= end
- start
;
2742 else if (start
> top_range
)
2744 end
= start
+ length
;
2748 else if (end
> top_range
&& ! dragging
)
2753 /* Store the adjusted setting in the scroll bar. */
2754 XSETINT (bar
->start
, start
);
2755 XSETINT (bar
->end
, end
);
2757 /* If being dragged, let scroll bar update itself. */
2760 if (pfnSetScrollInfo
)
2764 si
.cbSize
= sizeof (si
);
2765 si
.fMask
= SIF_PAGE
| SIF_POS
;
2766 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2769 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2772 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2778 /* Move a scroll bar around on the screen, to accommodate changing
2779 window configurations. */
2781 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2782 struct scroll_bar
*bar
;
2783 int top
, left
, width
, height
;
2785 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2786 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2788 /* If already correctly positioned, do nothing. */
2789 if ( XINT (bar
->left
) == left
2790 && XINT (bar
->top
) == top
2791 && XINT (bar
->width
) == width
2792 && XINT (bar
->height
) == height
)
2794 /* Redraw after clear_frame. */
2795 if (!my_show_window (f
, w
, SW_NORMAL
))
2796 InvalidateRect (w
, NULL
, FALSE
);
2802 /* Make sure scroll bar is "visible" before moving, to ensure the
2803 area of the parent window now exposed will be refreshed. */
2804 my_show_window (f
, w
, SW_HIDE
);
2805 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2806 if (pfnSetScrollInfo
)
2810 si
.cbSize
= sizeof (si
);
2811 si
.fMask
= SIF_RANGE
;
2813 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2814 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2816 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2819 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2820 my_show_window (f
, w
, SW_NORMAL
);
2821 // InvalidateRect (w, NULL, FALSE);
2823 XSETINT (bar
->left
, left
);
2824 XSETINT (bar
->top
, top
);
2825 XSETINT (bar
->width
, width
);
2826 XSETINT (bar
->height
, height
);
2831 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2834 x_scroll_bar_remove (bar
)
2835 struct scroll_bar
*bar
;
2837 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2841 /* Destroy the window. */
2842 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2844 /* Disassociate this scroll bar from its window. */
2845 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2850 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2851 that we are displaying PORTION characters out of a total of WHOLE
2852 characters, starting at POSITION. If WINDOW has no scroll bar,
2855 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2856 struct window
*window
;
2857 int portion
, whole
, position
;
2859 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2860 int top
= XINT (window
->top
);
2861 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2862 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2864 /* Where should this scroll bar be, pixelwise? */
2865 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2866 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2868 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2869 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2870 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2871 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2873 struct scroll_bar
*bar
;
2875 /* Does the scroll bar exist yet? */
2876 if (NILP (window
->vertical_scroll_bar
))
2877 bar
= x_scroll_bar_create (window
,
2878 pixel_top
, pixel_left
,
2879 pixel_width
, pixel_height
);
2882 /* It may just need to be moved and resized. */
2883 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2884 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2887 /* Set the scroll bar's current state. */
2889 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2892 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2895 int start
= (int) (((double) position
* top_range
) / whole
);
2896 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2898 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2902 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2906 /* The following three hooks are used when we're doing a thorough
2907 redisplay of the frame. We don't explicitly know which scroll bars
2908 are going to be deleted, because keeping track of when windows go
2909 away is a real pain - "Can you say set-window-configuration, boys
2910 and girls?" Instead, we just assert at the beginning of redisplay
2911 that *all* scroll bars are to be removed, and then save a scroll bar
2912 from the fiery pit when we actually redisplay its window. */
2914 /* Arrange for all scroll bars on FRAME to be removed at the next call
2915 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2916 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2918 w32_condemn_scroll_bars (frame
)
2921 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2922 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2925 bar
= FRAME_SCROLL_BARS (frame
);
2926 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2927 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2928 XSCROLL_BAR (bar
)->prev
= Qnil
;
2929 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2930 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2931 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2934 /* The condemned list should be empty at this point; if it's not,
2935 then the rest of Emacs isn't using the condemn/redeem/judge
2936 protocol correctly. */
2937 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2940 /* Move them all to the "condemned" list. */
2941 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2942 FRAME_SCROLL_BARS (frame
) = Qnil
;
2946 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2947 Note that WINDOW isn't necessarily condemned at all. */
2949 w32_redeem_scroll_bar (window
)
2950 struct window
*window
;
2952 struct scroll_bar
*bar
;
2954 /* We can't redeem this window's scroll bar if it doesn't have one. */
2955 if (NILP (window
->vertical_scroll_bar
))
2958 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2960 /* Unlink it from the condemned list. */
2962 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2964 if (NILP (bar
->prev
))
2966 /* If the prev pointer is nil, it must be the first in one of
2968 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2969 /* It's not condemned. Everything's fine. */
2971 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2972 window
->vertical_scroll_bar
))
2973 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2975 /* If its prev pointer is nil, it must be at the front of
2976 one or the other! */
2980 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2982 if (! NILP (bar
->next
))
2983 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2985 bar
->next
= FRAME_SCROLL_BARS (f
);
2987 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2988 if (! NILP (bar
->next
))
2989 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2992 struct scroll_bar
*bar
;
2994 /* We can't redeem this window's scroll bar if it doesn't have one. */
2995 if (NILP (window
->vertical_scroll_bar
))
2998 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3000 /* Unlink it from the condemned list. */
3002 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3004 if (NILP (bar
->prev
))
3006 /* If the prev pointer is nil, it must be the first in one of
3008 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3009 /* It's not condemned. Everything's fine. */
3011 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3012 window
->vertical_scroll_bar
))
3013 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3015 /* If its prev pointer is nil, it must be at the front of
3016 one or the other! */
3020 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3022 if (! NILP (bar
->next
))
3023 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3025 bar
->next
= FRAME_SCROLL_BARS (f
);
3027 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3028 if (! NILP (bar
->next
))
3029 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3034 /* Remove all scroll bars on FRAME that haven't been saved since the
3035 last call to `*condemn_scroll_bars_hook'. */
3037 w32_judge_scroll_bars (f
)
3040 Lisp_Object bar
, next
;
3042 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3044 /* Clear out the condemned list now so we won't try to process any
3045 more events on the hapless scroll bars. */
3046 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3048 for (; ! NILP (bar
); bar
= next
)
3050 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3052 x_scroll_bar_remove (b
);
3055 b
->next
= b
->prev
= Qnil
;
3058 /* Now there should be no references to the condemned scroll bars,
3059 and they should get garbage-collected. */
3061 Lisp_Object bar
, next
;
3063 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3065 /* Clear out the condemned list now so we won't try to process any
3066 more events on the hapless scroll bars. */
3067 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3069 for (; ! NILP (bar
); bar
= next
)
3071 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3073 x_scroll_bar_remove (b
);
3076 b
->next
= b
->prev
= Qnil
;
3079 /* Now there should be no references to the condemned scroll bars,
3080 and they should get garbage-collected. */
3084 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3085 is set to something other than no_event, it is enqueued.
3087 This may be called from a signal handler, so we have to ignore GC
3091 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3092 struct scroll_bar
*bar
;
3094 struct input_event
*emacs_event
;
3096 if (! GC_WINDOWP (bar
->window
))
3099 emacs_event
->kind
= w32_scroll_bar_click
;
3100 emacs_event
->code
= 0;
3101 /* not really meaningful to distinguish up/down */
3102 emacs_event
->modifiers
= msg
->dwModifiers
;
3103 emacs_event
->frame_or_window
= bar
->window
;
3104 emacs_event
->timestamp
= msg
->msg
.time
;
3107 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3109 int dragging
= !NILP (bar
->dragging
);
3111 if (pfnGetScrollInfo
)
3115 si
.cbSize
= sizeof (si
);
3118 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3122 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
3124 bar
->dragging
= Qnil
;
3126 switch (LOWORD (msg
->msg
.wParam
))
3129 emacs_event
->part
= scroll_bar_down_arrow
;
3132 emacs_event
->part
= scroll_bar_up_arrow
;
3135 emacs_event
->part
= scroll_bar_above_handle
;
3138 emacs_event
->part
= scroll_bar_below_handle
;
3141 emacs_event
->part
= scroll_bar_handle
;
3145 emacs_event
->part
= scroll_bar_handle
;
3149 case SB_THUMBPOSITION
:
3150 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3151 y
= HIWORD (msg
->msg
.wParam
);
3153 emacs_event
->part
= scroll_bar_handle
;
3155 /* "Silently" update current position. */
3156 if (pfnSetScrollInfo
)
3160 si
.cbSize
= sizeof (si
);
3164 /* Shrink handle if necessary to allow full range for position. */
3166 int start
= XINT (bar
->start
);
3167 int end
= XINT (bar
->end
);
3168 int len
= end
- start
;
3170 /* If new end is nearly hitting bottom, we must shrink
3171 handle. How much we shrink it depends on the relative
3172 sizes of len and top_range. */
3173 if (y
+ len
> top_range
- 2)
3175 len
-= min (top_range
/ 10, (len
/ 3) + 2);
3179 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3180 si
.fMask
|= SIF_PAGE
;
3184 /* Remember apparent position (we actually lag behind the real
3185 position, so don't set that directly. */
3186 last_scroll_bar_drag_pos
= y
;
3188 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3191 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
3194 /* If this is the end of a drag sequence, then reset the scroll
3195 handle size to normal and do a final redraw. Otherwise do
3199 if (pfnSetScrollInfo
)
3202 int start
= XINT (bar
->start
);
3203 int end
= XINT (bar
->end
);
3205 si
.cbSize
= sizeof (si
);
3206 si
.fMask
= SIF_PAGE
| SIF_POS
;
3207 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3208 si
.nPos
= last_scroll_bar_drag_pos
;
3210 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3213 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
3217 emacs_event
->kind
= no_event
;
3221 XSETINT (emacs_event
->x
, y
);
3222 XSETINT (emacs_event
->y
, top_range
);
3228 /* Return information to the user about the current position of the mouse
3229 on the scroll bar. */
3231 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3233 Lisp_Object
*bar_window
;
3234 enum scroll_bar_part
*part
;
3236 unsigned long *time
;
3238 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3239 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3240 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3242 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3247 *bar_window
= bar
->window
;
3249 if (pfnGetScrollInfo
)
3253 si
.cbSize
= sizeof (si
);
3254 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3256 pfnGetScrollInfo (w
, SB_CTL
, &si
);
3258 top_range
= si
.nMax
- si
.nPage
+ 1;
3261 pos
= GetScrollPos (w
, SB_CTL
);
3263 switch (LOWORD (last_mouse_scroll_bar_pos
))
3265 case SB_THUMBPOSITION
:
3267 *part
= scroll_bar_handle
;
3268 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3269 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3272 *part
= scroll_bar_handle
;
3276 *part
= scroll_bar_handle
;
3281 XSETINT(*y
, top_range
);
3284 last_mouse_scroll_bar
= Qnil
;
3286 *time
= last_mouse_movement_time
;
3291 /* The screen has been cleared so we may have changed foreground or
3292 background colors, and the scroll bars may need to be redrawn.
3293 Clear out the scroll bars, and ask for expose events, so we can
3296 x_scroll_bar_clear (f
)
3301 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3302 bar
= XSCROLL_BAR (bar
)->next
)
3304 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3305 HDC hdc
= GetDC (window
);
3308 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3309 arranges to refresh the scroll bar if hidden. */
3310 my_show_window (f
, window
, SW_HIDE
);
3312 GetClientRect (window
, &rect
);
3313 select_palette (f
, hdc
);
3314 w32_clear_rect (f
, hdc
, &rect
);
3315 deselect_palette (f
, hdc
);
3317 ReleaseDC (window
, hdc
);
3321 show_scroll_bars (f
, how
)
3327 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3328 bar
= XSCROLL_BAR (bar
)->next
)
3330 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3331 my_show_window (f
, window
, how
);
3336 /* The main W32 event-reading loop - w32_read_socket. */
3338 /* Timestamp of enter window event. This is only used by w32_read_socket,
3339 but we have to put it out here, since static variables within functions
3340 sometimes don't work. */
3341 static Time enter_timestamp
;
3343 /* Record the last 100 characters stored
3344 to help debug the loss-of-chars-during-GC problem. */
3346 short temp_buffer
[100];
3349 /* Read events coming from the W32 shell.
3350 This routine is called by the SIGIO handler.
3351 We return as soon as there are no more events to be read.
3353 Events representing keys are stored in buffer BUFP,
3354 which can hold up to NUMCHARS characters.
3355 We return the number of characters stored into the buffer,
3356 thus pretending to be `read'.
3358 EXPECTED is nonzero if the caller knows input is available.
3360 Some of these messages are reposted back to the message queue since the
3361 system calls the windows proc directly in a context where we cannot return
3362 the data nor can we guarantee the state we are in. So if we dispatch them
3363 we will get into an infinite loop. To prevent this from ever happening we
3364 will set a variable to indicate we are in the read_socket call and indicate
3365 which message we are processing since the windows proc gets called
3366 recursively with different messages by the system.
3370 w32_read_socket (sd
, bufp
, numchars
, expected
)
3372 register struct input_event
*bufp
;
3373 register int numchars
;
3377 int check_visibility
= 0;
3381 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3383 if (interrupt_input_blocked
)
3385 interrupt_input_pending
= 1;
3389 interrupt_input_pending
= 0;
3392 /* So people can tell when we have read the available input. */
3393 input_signal_count
++;
3396 abort (); /* Don't think this happens. */
3398 while (get_next_msg (&msg
, FALSE
))
3400 switch (msg
.msg
.message
)
3403 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3407 if (msg
.rect
.right
== msg
.rect
.left
||
3408 msg
.rect
.bottom
== msg
.rect
.top
)
3410 /* We may get paint messages even though the client
3411 area is clipped - these are not expose events. */
3412 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3413 XSTRING (f
->name
)->data
));
3415 else if (f
->async_visible
!= 1)
3417 /* Definitely not obscured, so mark as visible. */
3418 f
->async_visible
= 1;
3419 f
->async_iconified
= 0;
3420 SET_FRAME_GARBAGED (f
);
3421 DebPrint (("frame %04x (%s) reexposed\n", f
,
3422 XSTRING (f
->name
)->data
));
3424 /* WM_PAINT serves as MapNotify as well, so report
3425 visibility changes properly. */
3428 bufp
->kind
= deiconify_event
;
3429 XSETFRAME (bufp
->frame_or_window
, f
);
3434 else if (! NILP(Vframe_list
)
3435 && ! NILP (XCONS (Vframe_list
)->cdr
))
3436 /* Force a redisplay sooner or later to update the
3437 frame titles in case this is the second frame. */
3438 record_asynch_buffer_change ();
3442 /* Erase background again for safety. */
3443 w32_clear_rect (f
, NULL
, &msg
.rect
);
3447 msg
.rect
.right
- msg
.rect
.left
,
3448 msg
.rect
.bottom
- msg
.rect
.top
);
3453 case WM_INPUTLANGCHANGE
:
3454 /* Generate a language change event. */
3455 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3462 bufp
->kind
= language_change_event
;
3463 XSETFRAME (bufp
->frame_or_window
, f
);
3464 bufp
->code
= msg
.msg
.wParam
;
3465 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
3474 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3476 if (f
&& !f
->iconified
)
3478 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3480 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3481 bufp
->kind
= non_ascii_keystroke
;
3482 bufp
->code
= msg
.msg
.wParam
;
3483 bufp
->modifiers
= msg
.dwModifiers
;
3484 XSETFRAME (bufp
->frame_or_window
, f
);
3485 bufp
->timestamp
= msg
.msg
.time
;
3494 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3496 if (f
&& !f
->iconified
)
3498 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3500 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3501 bufp
->kind
= ascii_keystroke
;
3502 bufp
->code
= msg
.msg
.wParam
;
3503 bufp
->modifiers
= msg
.dwModifiers
;
3504 XSETFRAME (bufp
->frame_or_window
, f
);
3505 bufp
->timestamp
= msg
.msg
.time
;
3513 if (dpyinfo
->grabbed
&& last_mouse_frame
3514 && FRAME_LIVE_P (last_mouse_frame
))
3515 f
= last_mouse_frame
;
3517 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3520 note_mouse_movement (f
, &msg
.msg
);
3522 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3526 case WM_LBUTTONDOWN
:
3528 case WM_MBUTTONDOWN
:
3530 case WM_RBUTTONDOWN
:
3536 if (dpyinfo
->grabbed
&& last_mouse_frame
3537 && FRAME_LIVE_P (last_mouse_frame
))
3538 f
= last_mouse_frame
;
3540 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3544 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3547 construct_mouse_click (bufp
, &msg
, f
);
3554 parse_button (msg
.msg
.message
, &button
, &up
);
3558 dpyinfo
->grabbed
&= ~ (1 << button
);
3562 dpyinfo
->grabbed
|= (1 << button
);
3563 last_mouse_frame
= f
;
3569 if (dpyinfo
->grabbed
&& last_mouse_frame
3570 && FRAME_LIVE_P (last_mouse_frame
))
3571 f
= last_mouse_frame
;
3573 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3577 if ((!dpyinfo
->w32_focus_frame
3578 || f
== dpyinfo
->w32_focus_frame
)
3581 construct_mouse_wheel (bufp
, &msg
, f
);
3590 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3594 construct_drag_n_drop (bufp
, &msg
, f
);
3603 struct scroll_bar
*bar
=
3604 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3606 if (bar
&& numchars
>= 1)
3608 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3618 case WM_WINDOWPOSCHANGED
:
3620 case WM_ACTIVATEAPP
:
3621 check_visibility
= 1;
3625 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3627 if (f
&& !f
->async_iconified
)
3631 x_real_positions (f
, &x
, &y
);
3632 f
->output_data
.w32
->left_pos
= x
;
3633 f
->output_data
.w32
->top_pos
= y
;
3636 check_visibility
= 1;
3640 /* If window has been obscured or exposed by another window
3641 being maximised or minimised/restored, then recheck
3642 visibility of all frames. Direct changes to our own
3643 windows get handled by WM_SIZE. */
3645 if (msg
.msg
.lParam
!= 0)
3646 check_visibility
= 1;
3649 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3650 f
->async_visible
= msg
.msg
.wParam
;
3654 check_visibility
= 1;
3658 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3660 /* Inform lisp of whether frame has been iconified etc. */
3663 switch (msg
.msg
.wParam
)
3665 case SIZE_MINIMIZED
:
3666 f
->async_visible
= 0;
3667 f
->async_iconified
= 1;
3669 bufp
->kind
= iconify_event
;
3670 XSETFRAME (bufp
->frame_or_window
, f
);
3676 case SIZE_MAXIMIZED
:
3678 f
->async_visible
= 1;
3679 f
->async_iconified
= 0;
3681 /* wait_reading_process_input will notice this and update
3682 the frame's display structures. */
3683 SET_FRAME_GARBAGED (f
);
3687 bufp
->kind
= deiconify_event
;
3688 XSETFRAME (bufp
->frame_or_window
, f
);
3694 /* Force a redisplay sooner or later
3695 to update the frame titles
3696 in case this is the second frame. */
3697 record_asynch_buffer_change ();
3702 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3710 GetClientRect(msg
.msg
.hwnd
, &rect
);
3712 height
= rect
.bottom
- rect
.top
;
3713 width
= rect
.right
- rect
.left
;
3715 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3716 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3718 /* TODO: Clip size to the screen dimensions. */
3720 /* Even if the number of character rows and columns has
3721 not changed, the font size may have changed, so we need
3722 to check the pixel dimensions as well. */
3724 if (columns
!= f
->width
3725 || rows
!= f
->height
3726 || width
!= f
->output_data
.w32
->pixel_width
3727 || height
!= f
->output_data
.w32
->pixel_height
)
3729 /* I had set this to 0, 0 - I am not sure why?? */
3731 change_frame_size (f
, rows
, columns
, 0, 1);
3732 SET_FRAME_GARBAGED (f
);
3734 f
->output_data
.w32
->pixel_width
= width
;
3735 f
->output_data
.w32
->pixel_height
= height
;
3736 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3740 check_visibility
= 1;
3745 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3747 if (msg
.msg
.message
== WM_SETFOCUS
)
3749 x_new_focus_frame (dpyinfo
, f
);
3751 else if (f
== dpyinfo
->w32_focus_frame
)
3753 x_new_focus_frame (dpyinfo
, 0);
3756 check_visibility
= 1;
3760 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3767 bufp
->kind
= delete_window_event
;
3768 XSETFRAME (bufp
->frame_or_window
, f
);
3776 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3783 bufp
->kind
= menu_bar_activate_event
;
3784 XSETFRAME (bufp
->frame_or_window
, f
);
3792 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3796 extern void menubar_selection_callback
3797 (FRAME_PTR f
, void * client_data
);
3798 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3801 check_visibility
= 1;
3804 case WM_DISPLAYCHANGE
:
3805 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3809 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3810 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3811 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3812 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3816 check_visibility
= 1;
3820 /* Check for messages registered at runtime. */
3821 if (msg
.msg
.message
== msh_mousewheel
)
3823 if (dpyinfo
->grabbed
&& last_mouse_frame
3824 && FRAME_LIVE_P (last_mouse_frame
))
3825 f
= last_mouse_frame
;
3827 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3831 if ((!dpyinfo
->w32_focus_frame
3832 || f
== dpyinfo
->w32_focus_frame
)
3835 construct_mouse_wheel (bufp
, &msg
, f
);
3846 /* If the focus was just given to an autoraising frame,
3848 /* ??? This ought to be able to handle more than one such frame. */
3849 if (pending_autoraise_frame
)
3851 x_raise_frame (pending_autoraise_frame
);
3852 pending_autoraise_frame
= 0;
3855 /* Check which frames are still visisble, if we have enqueued any user
3856 events or been notified of events that may affect visibility. We
3857 do this here because there doesn't seem to be any direct
3858 notification from Windows that the visibility of a window has
3859 changed (at least, not in all cases). */
3860 if (count
> 0 || check_visibility
)
3862 Lisp_Object tail
, frame
;
3864 FOR_EACH_FRAME (tail
, frame
)
3866 FRAME_PTR f
= XFRAME (frame
);
3867 /* Check "visible" frames and mark each as obscured or not.
3868 Note that async_visible is nonzero for unobscured and
3869 obscured frames, but zero for hidden and iconified frames. */
3870 if (FRAME_W32_P (f
) && f
->async_visible
)
3873 HDC hdc
= get_frame_dc (f
);
3874 GetClipBox (hdc
, &clipbox
);
3875 release_frame_dc (f
, hdc
);
3877 if (clipbox
.right
== clipbox
.left
3878 || clipbox
.bottom
== clipbox
.top
)
3880 /* Frame has become completely obscured so mark as
3881 such (we do this by setting async_visible to 2 so
3882 that FRAME_VISIBLE_P is still true, but redisplay
3884 f
->async_visible
= 2;
3886 if (!FRAME_OBSCURED_P (f
))
3888 DebPrint (("frame %04x (%s) obscured\n", f
,
3889 XSTRING (f
->name
)->data
));
3894 /* Frame is not obscured, so mark it as such. */
3895 f
->async_visible
= 1;
3897 if (FRAME_OBSCURED_P (f
))
3899 SET_FRAME_GARBAGED (f
);
3900 DebPrint (("frame %04x (%s) reexposed\n", f
,
3901 XSTRING (f
->name
)->data
));
3903 /* Force a redisplay sooner or later. */
3904 record_asynch_buffer_change ();
3915 /* Drawing the cursor. */
3918 /* Draw a hollow box cursor. Don't change the inside of the box. */
3928 hdc
= get_frame_dc (f
);
3930 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3932 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3933 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3934 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3935 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3937 FrameRect (hdc
, &rect
, hb
);
3940 release_frame_dc (f
, hdc
);
3943 /* Clear the cursor of frame F to background color,
3944 and mark the cursor as not shown.
3945 This is used when the text where the cursor is
3946 is about to be rewritten. */
3952 if (! FRAME_VISIBLE_P (f
)
3953 || !f
->phys_cursor_on
)
3956 x_display_cursor (f
, 0);
3957 f
->phys_cursor_on
= 0;
3960 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3961 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3965 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3972 CHAR_TO_PIXEL_COL (f
, column
),
3973 CHAR_TO_PIXEL_ROW (f
, row
),
3974 &glyph
, 1, highlight
, 0, NULL
);
3978 x_display_bar_cursor (f
, on
)
3982 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3984 /* This is pointless on invisible frames, and dangerous on garbaged
3985 frames; in the latter case, the frame may be in the midst of
3986 changing its size, and curs_x and curs_y may be off the frame. */
3987 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3990 if (! on
&& ! f
->phys_cursor_on
)
3993 /* If there is anything wrong with the current cursor state, remove it. */
3994 if (f
->phys_cursor_on
3996 || f
->phys_cursor_x
!= curs_x
3997 || f
->phys_cursor_y
!= curs_y
3998 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
4000 /* Erase the cursor by redrawing the character underneath it. */
4001 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4002 f
->phys_cursor_glyph
,
4003 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4004 f
->phys_cursor_on
= 0;
4007 /* If we now need a cursor in the new place or in the new form, do it so. */
4009 && (! f
->phys_cursor_on
4010 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4012 f
->phys_cursor_glyph
4013 = ((current_glyphs
->enable
[curs_y
]
4014 && curs_x
< current_glyphs
->used
[curs_y
])
4015 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4017 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4018 CHAR_TO_PIXEL_COL (f
, curs_x
),
4019 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4020 max (f
->output_data
.w32
->cursor_width
, 1),
4021 f
->output_data
.w32
->line_height
);
4023 f
->phys_cursor_x
= curs_x
;
4024 f
->phys_cursor_y
= curs_y
;
4025 f
->phys_cursor_on
= 1;
4027 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4032 /* Turn the displayed cursor of frame F on or off according to ON.
4033 If ON is nonzero, where to put the cursor is specified
4034 by F->cursor_x and F->cursor_y. */
4037 x_display_box_cursor (f
, on
)
4041 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4043 /* This is pointless on invisible frames, and dangerous on garbaged
4044 frames; in the latter case, the frame may be in the midst of
4045 changing its size, and curs_x and curs_y may be off the frame. */
4046 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4049 /* If cursor is off and we want it off, return quickly. */
4050 if (!on
&& ! f
->phys_cursor_on
)
4053 /* If cursor is currently being shown and we don't want it to be
4054 or it is in the wrong place,
4055 or we want a hollow box and it's not so, (pout!)
4057 if (f
->phys_cursor_on
4059 || f
->phys_cursor_x
!= curs_x
4060 || f
->phys_cursor_y
!= curs_y
4061 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4062 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4064 int mouse_face_here
= 0;
4065 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4067 /* If the cursor is in the mouse face area, redisplay that when
4068 we clear the cursor. */
4069 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4070 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4071 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4072 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4073 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4074 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4075 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4076 /* Don't redraw the cursor's spot in mouse face
4077 if it is at the end of a line (on a newline).
4078 The cursor appears there, but mouse highlighting does not. */
4079 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4080 mouse_face_here
= 1;
4082 /* If the font is not as tall as a whole line,
4083 we must explicitly clear the line's whole height. */
4084 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4085 w32_clear_area (f
, NULL
,
4086 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4087 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4088 FONT_WIDTH (f
->output_data
.w32
->font
),
4089 f
->output_data
.w32
->line_height
);
4090 /* Erase the cursor by redrawing the character underneath it. */
4091 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4092 f
->phys_cursor_glyph
,
4095 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4096 f
->phys_cursor_on
= 0;
4099 /* If we want to show a cursor,
4100 or we want a box cursor and it's not so,
4101 write it in the right place. */
4103 && (! f
->phys_cursor_on
4104 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4105 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4107 f
->phys_cursor_glyph
4108 = ((current_glyphs
->enable
[curs_y
]
4109 && curs_x
< current_glyphs
->used
[curs_y
])
4110 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4112 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4115 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4119 x_draw_single_glyph (f
, curs_y
, curs_x
,
4120 f
->phys_cursor_glyph
, 2);
4121 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4124 f
->phys_cursor_x
= curs_x
;
4125 f
->phys_cursor_y
= curs_y
;
4126 f
->phys_cursor_on
= 1;
4130 /* Display the cursor on frame F, or clear it, according to ON.
4131 Use the position specified by curs_x and curs_y
4132 if we are doing an update of frame F now.
4133 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4136 x_display_cursor (f
, on
)
4142 /* If we're not updating, then we want to use the current frame's
4143 cursor position, not our local idea of where the cursor ought to be. */
4144 if (f
!= updating_frame
)
4146 curs_x
= FRAME_CURSOR_X (f
);
4147 curs_y
= FRAME_CURSOR_Y (f
);
4150 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4151 x_display_box_cursor (f
, on
);
4152 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4153 x_display_bar_cursor (f
, on
);
4155 /* Those are the only two we have implemented! */
4161 /* Changing the font of the frame. */
4163 /* Give frame F the font named FONTNAME as its default font, and
4164 return the full name of that font. FONTNAME may be a wildcard
4165 pattern; in that case, we choose some font that fits the pattern.
4166 The return value shows which font we chose. */
4169 x_new_font (f
, fontname
)
4171 register char *fontname
;
4173 struct font_info
*fontp
4174 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4180 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4181 f
->output_data
.w32
->font_baseline
4182 = FONT_BASE (FRAME_FONT (f
)) + fontp
->baseline_offset
;
4183 FRAME_FONTSET (f
) = -1;
4185 /* Compute the scroll bar width in character columns. */
4186 if (f
->scroll_bar_pixel_width
> 0)
4188 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4189 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4192 f
->scroll_bar_cols
= 2;
4194 /* Now make the frame display the given font. */
4195 if (FRAME_W32_WINDOW (f
) != 0)
4197 frame_update_line_height (f
);
4198 x_set_window_size (f
, 0, f
->width
, f
->height
);
4201 /* If we are setting a new frame's font for the first time,
4202 there are no faces yet, so this font's height is the line height. */
4203 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4206 Lisp_Object lispy_name
;
4208 lispy_name
= build_string (fontname
);
4214 /* Give frame F the fontset named FONTSETNAME as its default font, and
4215 return the full name of that fontset. FONTSETNAME may be a wildcard
4216 pattern; in that case, we choose some fontset that fits the pattern.
4217 The return value shows which fontset we chose. */
4220 x_new_fontset (f
, fontsetname
)
4224 int fontset
= fs_query_fontset (f
, fontsetname
);
4225 struct fontset_info
*fontsetp
;
4231 if (FRAME_FONTSET (f
) == fontset
)
4232 /* This fontset is already set in frame F. There's nothing more
4234 return build_string (fontsetname
);
4236 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4238 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4239 /* This fontset doesn't contain ASCII font. */
4242 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4244 if (!STRINGP (result
))
4245 /* Can't load ASCII font. */
4248 /* Since x_new_font doesn't update any fontset information, do it now. */
4249 FRAME_FONTSET(f
) = fontset
;
4250 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4251 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4253 return build_string (fontsetname
);
4256 /* Calculate the absolute position in frame F
4257 from its current recorded position values and gravity. */
4259 x_calc_absolute_position (f
)
4264 int flags
= f
->output_data
.w32
->size_hint_flags
;
4268 /* Find the position of the outside upper-left corner of
4269 the inner window, with respect to the outer window. */
4270 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4273 MapWindowPoints (FRAME_W32_WINDOW (f
),
4274 f
->output_data
.w32
->parent_desc
,
4281 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4284 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4285 FRAME_EXTERNAL_MENU_BAR (f
));
4288 pt
.x
+= (rt
.right
- rt
.left
);
4289 pt
.y
+= (rt
.bottom
- rt
.top
);
4292 /* Treat negative positions as relative to the leftmost bottommost
4293 position that fits on the screen. */
4294 if (flags
& XNegative
)
4295 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4296 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4298 + f
->output_data
.w32
->left_pos
);
4300 if (flags
& YNegative
)
4301 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4302 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4304 + f
->output_data
.w32
->top_pos
);
4305 /* The left_pos and top_pos
4306 are now relative to the top and left screen edges,
4307 so the flags should correspond. */
4308 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4311 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4312 to really change the position, and 0 when calling from
4313 x_make_frame_visible (in that case, XOFF and YOFF are the current
4314 position values). It is -1 when calling from x_set_frame_parameters,
4315 which means, do adjust for borders but don't change the gravity. */
4317 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4319 register int xoff
, yoff
;
4322 int modified_top
, modified_left
;
4324 if (change_gravity
> 0)
4326 f
->output_data
.w32
->top_pos
= yoff
;
4327 f
->output_data
.w32
->left_pos
= xoff
;
4328 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4330 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4332 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4333 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4335 x_calc_absolute_position (f
);
4338 x_wm_set_size_hint (f
, (long) 0, 0);
4340 /* It is a mystery why we need to add the border_width here
4341 when the frame is already visible, but experiment says we do. */
4342 modified_left
= f
->output_data
.w32
->left_pos
;
4343 modified_top
= f
->output_data
.w32
->top_pos
;
4345 /* Do not add in border widths under W32. */
4346 if (change_gravity
!= 0)
4348 modified_left
+= f
->output_data
.w32
->border_width
;
4349 modified_top
+= f
->output_data
.w32
->border_width
;
4353 my_set_window_pos (FRAME_W32_WINDOW (f
),
4355 modified_left
, modified_top
,
4357 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4361 /* Call this to change the size of frame F's x-window.
4362 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4363 for this size change and subsequent size changes.
4364 Otherwise we leave the window gravity unchanged. */
4366 x_set_window_size (f
, change_gravity
, cols
, rows
)
4371 int pixelwidth
, pixelheight
;
4373 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4377 check_frame_size (f
, &rows
, &cols
);
4378 f
->output_data
.w32
->vertical_scroll_bar_extra
4379 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4381 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4382 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4383 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4384 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4385 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4387 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4388 x_wm_set_size_hint (f
, (long) 0, 0);
4393 rect
.left
= rect
.top
= 0;
4394 rect
.right
= pixelwidth
;
4395 rect
.bottom
= pixelheight
;
4397 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4398 FRAME_EXTERNAL_MENU_BAR (f
));
4400 my_set_window_pos (FRAME_W32_WINDOW (f
),
4403 rect
.right
- rect
.left
,
4404 rect
.bottom
- rect
.top
,
4405 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4408 /* Now, strictly speaking, we can't be sure that this is accurate,
4409 but the window manager will get around to dealing with the size
4410 change request eventually, and we'll hear how it went when the
4411 ConfigureNotify event gets here.
4413 We could just not bother storing any of this information here,
4414 and let the ConfigureNotify event set everything up, but that
4415 might be kind of confusing to the lisp code, since size changes
4416 wouldn't be reported in the frame parameters until some random
4417 point in the future when the ConfigureNotify event arrives. */
4418 change_frame_size (f
, rows
, cols
, 0, 0);
4419 PIXEL_WIDTH (f
) = pixelwidth
;
4420 PIXEL_HEIGHT (f
) = pixelheight
;
4422 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4423 receive in the ConfigureNotify event; if we get what we asked
4424 for, then the event won't cause the screen to become garbaged, so
4425 we have to make sure to do it here. */
4426 SET_FRAME_GARBAGED (f
);
4428 /* If cursor was outside the new size, mark it as off. */
4429 if (f
->phys_cursor_y
>= rows
4430 || f
->phys_cursor_x
>= cols
)
4432 f
->phys_cursor_x
= 0;
4433 f
->phys_cursor_y
= 0;
4434 f
->phys_cursor_on
= 0;
4437 /* Clear out any recollection of where the mouse highlighting was,
4438 since it might be in a place that's outside the new frame size.
4439 Actually checking whether it is outside is a pain in the neck,
4440 so don't try--just let the highlighting be done afresh with new size. */
4441 window
= dpyinfo
->mouse_face_window
;
4442 if (! NILP (window
) && XFRAME (window
) == f
)
4444 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4445 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4446 dpyinfo
->mouse_face_window
= Qnil
;
4452 /* Mouse warping. */
4455 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4464 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4465 pt
.x
= rect
.left
+ pix_x
;
4466 pt
.y
= rect
.top
+ pix_y
;
4467 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4469 SetCursorPos (pt
.x
, pt
.y
);
4475 x_set_mouse_position (f
, x
, y
)
4481 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4482 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4484 if (pix_x
< 0) pix_x
= 0;
4485 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4487 if (pix_y
< 0) pix_y
= 0;
4488 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4490 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4493 /* focus shifting, raising and lowering. */
4495 x_focus_on_frame (f
)
4498 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4500 /* Give input focus to frame. */
4503 /* Try not to change its Z-order if possible. */
4504 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4505 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4508 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4517 /* Raise frame F. */
4524 /* Strictly speaking, raise-frame should only change the frame's Z
4525 order, leaving input focus unchanged. This is reasonable behaviour
4526 on X where the usual policy is point-to-focus. However, this
4527 behaviour would be very odd on Windows where the usual policy is
4530 On X, if the mouse happens to be over the raised frame, it gets
4531 input focus anyway (so the window with focus will never be
4532 completely obscured) - if not, then just moving the mouse over it
4533 is sufficient to give it focus. On Windows, the user must actually
4534 click on the frame (preferrably the title bar so as not to move
4535 point), which is more awkward. Also, no other Windows program
4536 raises a window to the top but leaves another window (possibly now
4537 completely obscured) with input focus.
4539 Because there is a system setting on Windows that allows the user
4540 to choose the point to focus policy, we make the strict semantics
4541 optional, but by default we grab focus when raising. */
4543 if (NILP (Vw32_grab_focus_on_raise
))
4545 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4546 not already the foreground application: the frame is raised
4547 above all other frames belonging to us, but not above the
4548 current top window. To achieve that, we have to resort to this
4549 more cumbersome method. */
4551 HDWP handle
= BeginDeferWindowPos (2);
4554 DeferWindowPos (handle
,
4555 FRAME_W32_WINDOW (f
),
4558 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4560 DeferWindowPos (handle
,
4561 GetForegroundWindow (),
4562 FRAME_W32_WINDOW (f
),
4564 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4566 EndDeferWindowPos (handle
);
4571 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4577 /* Lower frame F. */
4583 my_set_window_pos (FRAME_W32_WINDOW (f
),
4586 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4591 w32_frame_raise_lower (f
, raise
)
4601 /* Change of visibility. */
4603 /* This tries to wait until the frame is really visible.
4604 However, if the window manager asks the user where to position
4605 the frame, this will return before the user finishes doing that.
4606 The frame will not actually be visible at that time,
4607 but it will become visible later when the window manager
4608 finishes with it. */
4610 x_make_frame_visible (f
)
4615 if (! FRAME_VISIBLE_P (f
))
4617 /* We test FRAME_GARBAGED_P here to make sure we don't
4618 call x_set_offset a second time
4619 if we get to x_make_frame_visible a second time
4620 before the window gets really visible. */
4621 if (! FRAME_ICONIFIED_P (f
)
4622 && ! f
->output_data
.w32
->asked_for_visible
)
4623 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4625 f
->output_data
.w32
->asked_for_visible
= 1;
4627 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4628 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4631 /* Synchronize to ensure Emacs knows the frame is visible
4632 before we do anything else. We do this loop with input not blocked
4633 so that incoming events are handled. */
4636 int count
= input_signal_count
;
4638 /* This must come after we set COUNT. */
4641 XSETFRAME (frame
, f
);
4645 /* Once we have handled input events,
4646 we should have received the MapNotify if one is coming.
4647 So if we have not got it yet, stop looping.
4648 Some window managers make their own decisions
4649 about visibility. */
4650 if (input_signal_count
!= count
)
4652 /* Machines that do polling rather than SIGIO have been observed
4653 to go into a busy-wait here. So we'll fake an alarm signal
4654 to let the handler know that there's something to be read.
4655 We used to raise a real alarm, but it seems that the handler
4656 isn't always enabled here. This is probably a bug. */
4657 if (input_polling_used ())
4659 /* It could be confusing if a real alarm arrives while processing
4660 the fake one. Turn it off and let the handler reset it. */
4662 input_poll_signal (0);
4664 /* Once we have handled input events,
4665 we should have received the MapNotify if one is coming.
4666 So if we have not got it yet, stop looping.
4667 Some window managers make their own decisions
4668 about visibility. */
4669 if (input_signal_count
!= count
)
4672 FRAME_SAMPLE_VISIBILITY (f
);
4676 /* Change from mapped state to withdrawn state. */
4678 /* Make the frame visible (mapped and not iconified). */
4680 x_make_frame_invisible (f
)
4685 /* Don't keep the highlight on an invisible frame. */
4686 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4687 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4691 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4693 /* We can't distinguish this from iconification
4694 just by the event that we get from the server.
4695 So we can't win using the usual strategy of letting
4696 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4697 and synchronize with the server to make sure we agree. */
4699 FRAME_ICONIFIED_P (f
) = 0;
4700 f
->async_visible
= 0;
4701 f
->async_iconified
= 0;
4706 /* Change window state from mapped to iconified. */
4714 /* Don't keep the highlight on an invisible frame. */
4715 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4716 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4718 if (f
->async_iconified
)
4723 /* Simulate the user minimizing the frame. */
4724 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4729 /* Destroy the window of frame F. */
4731 x_destroy_window (f
)
4734 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4738 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4739 free_frame_menubar (f
);
4740 free_frame_faces (f
);
4742 xfree (f
->output_data
.w32
);
4743 f
->output_data
.w32
= 0;
4744 if (f
== dpyinfo
->w32_focus_frame
)
4745 dpyinfo
->w32_focus_frame
= 0;
4746 if (f
== dpyinfo
->w32_focus_event_frame
)
4747 dpyinfo
->w32_focus_event_frame
= 0;
4748 if (f
== dpyinfo
->w32_highlight_frame
)
4749 dpyinfo
->w32_highlight_frame
= 0;
4751 dpyinfo
->reference_count
--;
4753 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4755 dpyinfo
->mouse_face_beg_row
4756 = dpyinfo
->mouse_face_beg_col
= -1;
4757 dpyinfo
->mouse_face_end_row
4758 = dpyinfo
->mouse_face_end_col
= -1;
4759 dpyinfo
->mouse_face_window
= Qnil
;
4765 /* Setting window manager hints. */
4767 /* Set the normal size hints for the window manager, for frame F.
4768 FLAGS is the flags word to use--or 0 meaning preserve the flags
4769 that the window now has.
4770 If USER_POSITION is nonzero, we set the USPosition
4771 flag (this is useful when FLAGS is 0). */
4773 x_wm_set_size_hint (f
, flags
, user_position
)
4778 Window window
= FRAME_W32_WINDOW (f
);
4780 flexlines
= f
->height
;
4784 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4785 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4786 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4787 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4792 /* Window manager things */
4793 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4798 Window window
= FRAME_W32_WINDOW (f
);
4800 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4801 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4802 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4804 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4809 /* Initialization. */
4811 #ifdef USE_X_TOOLKIT
4812 static XrmOptionDescRec emacs_options
[] = {
4813 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4814 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4816 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4817 XrmoptionSepArg
, NULL
},
4818 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4820 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4821 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4822 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4823 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4824 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4825 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4826 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4828 #endif /* USE_X_TOOLKIT */
4830 static int w32_initialized
= 0;
4832 struct w32_display_info
*
4833 w32_term_init (display_name
, xrm_option
, resource_name
)
4834 Lisp_Object display_name
;
4836 char *resource_name
;
4840 struct w32_display_info
*dpyinfo
;
4845 if (!w32_initialized
)
4848 w32_initialized
= 1;
4859 argv
[argc
++] = "-xrm";
4860 argv
[argc
++] = xrm_option
;
4864 dpyinfo
= &one_w32_display_info
;
4866 /* Put this display on the chain. */
4867 dpyinfo
->next
= NULL
;
4869 /* Put it on w32_display_name_list as well, to keep them parallel. */
4870 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4871 w32_display_name_list
);
4872 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4874 dpyinfo
->w32_id_name
4875 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4876 + XSTRING (Vsystem_name
)->size
4878 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4879 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4882 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4883 resource_name
, EMACS_CLASS
);
4885 /* Put the rdb where we can find it in a way that works on
4887 dpyinfo
->xrdb
= xrdb
;
4889 hdc
= GetDC (GetDesktopWindow ());
4891 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4892 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4893 dpyinfo
->root_window
= GetDesktopWindow ();
4894 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4895 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4896 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4897 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4898 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4899 dpyinfo
->grabbed
= 0;
4900 dpyinfo
->reference_count
= 0;
4901 dpyinfo
->n_fonts
= 0;
4902 dpyinfo
->font_table_size
= 0;
4903 dpyinfo
->bitmaps
= 0;
4904 dpyinfo
->bitmaps_size
= 0;
4905 dpyinfo
->bitmaps_last
= 0;
4906 dpyinfo
->mouse_face_mouse_frame
= 0;
4907 dpyinfo
->mouse_face_deferred_gc
= 0;
4908 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4909 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4910 dpyinfo
->mouse_face_face_id
= 0;
4911 dpyinfo
->mouse_face_window
= Qnil
;
4912 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4913 dpyinfo
->mouse_face_defer
= 0;
4914 dpyinfo
->w32_focus_frame
= 0;
4915 dpyinfo
->w32_focus_event_frame
= 0;
4916 dpyinfo
->w32_highlight_frame
= 0;
4918 ReleaseDC (GetDesktopWindow (), hdc
);
4920 /* Determine if there is a middle mouse button, to allow parse_button
4921 to decide whether right mouse events should be mouse-2 or
4923 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4925 /* initialise palette with white and black */
4928 defined_color (0, "white", &color
, 1);
4929 defined_color (0, "black", &color
, 1);
4932 #ifndef F_SETOWN_BUG
4934 #ifdef F_SETOWN_SOCK_NEG
4935 /* stdin is a socket here */
4936 fcntl (connection
, F_SETOWN
, -getpid ());
4937 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4938 fcntl (connection
, F_SETOWN
, getpid ());
4939 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4940 #endif /* ! defined (F_SETOWN) */
4941 #endif /* F_SETOWN_BUG */
4944 if (interrupt_input
)
4945 init_sigio (connection
);
4946 #endif /* ! defined (SIGIO) */
4953 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4956 x_delete_display (dpyinfo
)
4957 struct w32_display_info
*dpyinfo
;
4959 /* Discard this display from w32_display_name_list and w32_display_list.
4960 We can't use Fdelq because that can quit. */
4961 if (! NILP (w32_display_name_list
)
4962 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4963 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4968 tail
= w32_display_name_list
;
4969 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4971 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4972 dpyinfo
->name_list_element
))
4974 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4977 tail
= XCONS (tail
)->cdr
;
4981 /* free palette table */
4983 struct w32_palette_entry
* plist
;
4985 plist
= dpyinfo
->color_list
;
4988 struct w32_palette_entry
* pentry
= plist
;
4989 plist
= plist
->next
;
4992 dpyinfo
->color_list
= NULL
;
4993 if (dpyinfo
->palette
)
4994 DeleteObject(dpyinfo
->palette
);
4996 xfree (dpyinfo
->font_table
);
4997 xfree (dpyinfo
->w32_id_name
);
5000 /* Set up use of W32. */
5002 DWORD
w32_msg_worker ();
5006 /* MSVC does not type K&R functions with no arguments correctly, and
5007 so we must explicitly cast them. */
5008 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
5009 clear_end_of_line_hook
= w32_clear_end_of_line
;
5010 ins_del_lines_hook
= w32_ins_del_lines
;
5011 change_line_highlight_hook
= w32_change_line_highlight
;
5012 insert_glyphs_hook
= w32_insert_glyphs
;
5013 write_glyphs_hook
= w32_write_glyphs
;
5014 delete_glyphs_hook
= w32_delete_glyphs
;
5015 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5016 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5017 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5018 update_begin_hook
= w32_update_begin
;
5019 update_end_hook
= w32_update_end
;
5020 set_terminal_window_hook
= w32_set_terminal_window
;
5021 read_socket_hook
= w32_read_socket
;
5022 frame_up_to_date_hook
= w32_frame_up_to_date
;
5023 cursor_to_hook
= w32_cursor_to
;
5024 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5025 mouse_position_hook
= w32_mouse_position
;
5026 frame_rehighlight_hook
= w32_frame_rehighlight
;
5027 frame_raise_lower_hook
= w32_frame_raise_lower
;
5028 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5029 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5030 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5031 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5033 scroll_region_ok
= 1; /* we'll scroll partial frames */
5034 char_ins_del_ok
= 0; /* just as fast to write the line */
5035 line_ins_del_ok
= 1; /* we'll just blt 'em */
5036 fast_clear_end_of_line
= 1; /* X does this well */
5037 memory_below_frame
= 0; /* we don't remember what scrolls
5041 /* Initialize input mode: interrupt_input off, no flow control, allow
5042 8 bit character input, standard quit char. */
5043 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5045 /* Create the window thread - it will terminate itself or when the app terminates */
5049 dwMainThreadId
= GetCurrentThreadId ();
5050 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5051 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5053 /* Wait for thread to start */
5058 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5060 hWindowsThread
= CreateThread (NULL
, 0,
5061 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5062 0, 0, &dwWindowsThreadId
);
5064 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5067 /* It is desirable that mainThread should have the same notion of
5068 focus window and active window as windowsThread. Unfortunately, the
5069 following call to AttachThreadInput, which should do precisely what
5070 we need, causes major problems when Emacs is linked as a console
5071 program. Unfortunately, we have good reasons for doing that, so
5072 instead we need to send messages to windowsThread to make some API
5073 calls for us (ones that affect, or depend on, the active/focus
5075 #ifdef ATTACH_THREADS
5076 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5079 /* Dynamically link to optional system components. */
5081 HANDLE user_lib
= LoadLibrary ("user32.dll");
5083 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5085 /* New proportional scroll bar functions. */
5086 LOAD_PROC( SetScrollInfo
);
5087 LOAD_PROC( GetScrollInfo
);
5091 FreeLibrary (user_lib
);
5093 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5094 otherwise use the fixed height. */
5095 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5096 GetSystemMetrics (SM_CYVTHUMB
);
5098 /* For either kind of scroll bar, take account of the arrows; these
5099 effectively form the border of the main scroll bar range. */
5100 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5101 = GetSystemMetrics (SM_CYVSCROLL
);
5108 Lisp_Object codepage
;
5110 staticpro (&w32_display_name_list
);
5111 w32_display_name_list
= Qnil
;
5113 staticpro (&last_mouse_scroll_bar
);
5114 last_mouse_scroll_bar
= Qnil
;
5116 staticpro (&Qvendor_specific_keysyms
);
5117 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5119 DEFVAR_INT ("w32-num-mouse-buttons",
5120 &Vw32_num_mouse_buttons
,
5121 "Number of physical mouse buttons.");
5122 Vw32_num_mouse_buttons
= Qnil
;
5124 DEFVAR_LISP ("w32-swap-mouse-buttons",
5125 &Vw32_swap_mouse_buttons
,
5126 "Swap the mapping of middle and right mouse buttons.\n\
5127 When nil, middle button is mouse-2 and right button is mouse-3.");
5128 Vw32_swap_mouse_buttons
= Qnil
;
5130 DEFVAR_LISP ("w32-grab-focus-on-raise",
5131 &Vw32_grab_focus_on_raise
,
5132 "Raised frame grabs input focus.\n\
5133 When t, `raise-frame' grabs input focus as well. This fits well\n\
5134 with the normal Windows click-to-focus policy, but might not be\n\
5135 desirable when using a point-to-focus policy.");
5136 Vw32_grab_focus_on_raise
= Qt
;
5138 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5139 &Vw32_capslock_is_shiftlock
,
5140 "Apply CapsLock state to non character input keys.\n\
5141 When nil, CapsLock only affects normal character input keys.");
5142 Vw32_capslock_is_shiftlock
= Qnil
;
5144 DEFVAR_LISP ("w32-recognize-altgr",
5145 &Vw32_recognize_altgr
,
5146 "Recognize right-alt and left-ctrl as AltGr.\n\
5147 When nil, the right-alt and left-ctrl key combination is\n\
5148 interpreted normally.");
5149 Vw32_recognize_altgr
= Qt
;
5151 DEFVAR_BOOL ("w32-enable-unicode-output",
5152 &w32_enable_unicode_output
,
5153 "Enable the use of Unicode for text output if non-nil.\n\
5154 Unicode output may prevent some third party applications for displaying\n\
5155 Far-East Languages on Windows 95/98 from working properly.\n\
5156 NT uses Unicode internally anyway, so this flag will probably have no\n\
5157 affect on NT machines.");
5158 w32_enable_unicode_output
= 1;
5160 DEFVAR_LISP ("w32-charset-to-codepage-alist",
5161 &Vw32_charset_to_codepage_alist
,
5162 "Alist linking character sets to Windows Codepages.");
5163 Vw32_charset_to_codepage_alist
= Qnil
;
5164 /* Initialise the alist with some defaults. */
5165 XSETFASTINT (codepage
, 936);
5166 store_in_alist (&Vw32_charset_to_codepage_alist
,
5167 build_string ("gb2312"), codepage
);
5168 XSETFASTINT (codepage
, 950);
5169 store_in_alist (&Vw32_charset_to_codepage_alist
,
5170 build_string ("big5"), codepage
);
5171 XSETFASTINT (codepage
, 949);
5172 store_in_alist (&Vw32_charset_to_codepage_alist
,
5173 build_string ("ksc5601.1987"), codepage
);
5174 XSETFASTINT (codepage
, 1361);
5175 store_in_alist (&Vw32_charset_to_codepage_alist
,
5176 build_string ("ksc5601.1992"), codepage
);
5177 XSETFASTINT (codepage
, 932);
5178 store_in_alist (&Vw32_charset_to_codepage_alist
,
5179 build_string ("jisx0208-sjis"), codepage
);
5180 XSETFASTINT (codepage
, 874);
5181 store_in_alist (&Vw32_charset_to_codepage_alist
,
5182 build_string ("tis620"), codepage
);
5183 XSETFASTINT (codepage
, 20866);
5184 store_in_alist (&Vw32_charset_to_codepage_alist
,
5185 build_string ("koi8-r"), codepage
);
5186 /* iso8859-13 is not yet officially adopted, but it is conveniently
5187 covered by CP 1257. */
5188 XSETFASTINT (codepage
, 1257);
5189 store_in_alist (&Vw32_charset_to_codepage_alist
,
5190 build_string ("iso8859-13"), codepage
);
5191 XSETFASTINT (codepage
, 1254);
5192 store_in_alist (&Vw32_charset_to_codepage_alist
,
5193 build_string ("iso8859-9"), codepage
);
5194 XSETFASTINT (codepage
, 1255);
5195 store_in_alist (&Vw32_charset_to_codepage_alist
,
5196 build_string ("iso8859-8"), codepage
);
5197 XSETFASTINT (codepage
, 28597);
5198 store_in_alist (&Vw32_charset_to_codepage_alist
,
5199 build_string ("iso8859-7"), codepage
);
5200 XSETFASTINT (codepage
, 28596);
5201 store_in_alist (&Vw32_charset_to_codepage_alist
,
5202 build_string ("iso8859-6"), codepage
);
5203 XSETFASTINT (codepage
, 28595);
5204 store_in_alist (&Vw32_charset_to_codepage_alist
,
5205 build_string ("iso8859-5"), codepage
);
5206 XSETFASTINT (codepage
, 28594);
5207 store_in_alist (&Vw32_charset_to_codepage_alist
,
5208 build_string ("iso8859-4"), codepage
);
5209 XSETFASTINT (codepage
, 28593);
5210 store_in_alist (&Vw32_charset_to_codepage_alist
,
5211 build_string ("iso8859-3"), codepage
);
5212 XSETFASTINT (codepage
, 28592);
5213 store_in_alist (&Vw32_charset_to_codepage_alist
,
5214 build_string ("iso8859-2"), codepage
);
5215 XSETFASTINT (codepage
, 1252);
5216 store_in_alist (&Vw32_charset_to_codepage_alist
,
5217 build_string ("iso8859-1"), codepage
);