1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93,94,95,96,97,98, 1999 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
;
1238 hb
= CreateSolidBrush (bg
);
1239 hp
= CreatePen (PS_SOLID
, 0, fg
);
1240 oldhb
= SelectObject(hdc
, hb
);
1241 oldhp
= SelectObject(hdc
, hp
);
1243 for (i
= 0; i
< limit
; i
++)
1244 Rectangle (hdc
, left
+ glyph_width
* i
, top
,
1245 left
+ glyph_width
* (i
+ 1),
1248 SelectObject(hdc
, oldhb
);
1249 SelectObject(hdc
, oldhp
);
1253 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1255 /* Indicate that we found a font of inappropriate size. */
1256 int limit
= cmpcharp
? 1 : len
;
1258 for (i
= 0; i
< limit
; i
++)
1260 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1261 top
+ line_height
- 1, glyph_width
, 1);
1262 w32_fill_area (f
, hdc
, fg
, left
+ glyph_width
* i
,
1263 top
+ line_height
- 3, 1, 2);
1268 /* Setting underline position based on the metric of the
1269 current font results in shaky underline if it strides
1270 over different fonts. So, we set the position based only
1271 on the default font of this frame. */
1272 int underline_position
= 1;
1274 if (FONT_HEIGHT (FRAME_FONT (f
)) - FONT_BASE(FRAME_FONT (f
))
1275 <= underline_position
)
1276 underline_position
= (FONT_HEIGHT (FRAME_FONT (f
)) -
1277 FONT_BASE(FRAME_FONT (f
))) - 1;
1279 if (face
->underline
)
1280 w32_fill_area (f
, hdc
, fg
, left
,
1281 top
+ FONT_BASE (FRAME_FONT (f
))
1282 + underline_position
,
1290 release_frame_dc (f
, hdc
);
1292 return (left
- orig_left
);
1296 /* Output some text at the nominal frame cursor position.
1297 Advance the cursor over the text.
1298 Output LEN glyphs at START.
1300 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
1301 controls the pixel values used for foreground and background. */
1304 w32_write_glyphs (start
, len
)
1305 register GLYPH
*start
;
1308 register int temp_length
;
1318 /* If not within an update,
1319 output at the frame's visible cursor. */
1320 curs_x
= f
->cursor_x
;
1321 curs_y
= f
->cursor_y
;
1325 CHAR_TO_PIXEL_COL (f
, curs_x
),
1326 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1327 start
, len
, highlight
, 0, NULL
);
1329 /* If we drew on top of the cursor, note that it is turned off. */
1330 if (curs_y
== f
->phys_cursor_y
1331 && curs_x
<= f
->phys_cursor_x
1332 && curs_x
+ len
> f
->phys_cursor_x
)
1333 f
->phys_cursor_on
= 0;
1335 if (updating_frame
== 0)
1338 x_display_cursor (f
, 1);
1347 /* Clear to the end of the line.
1348 Erase the current text line from the nominal cursor position (inclusive)
1349 to column FIRST_UNUSED (exclusive). The idea is that everything
1350 from FIRST_UNUSED onward is already erased. */
1353 w32_clear_end_of_line (first_unused
)
1354 register int first_unused
;
1356 struct frame
*f
= updating_frame
;
1361 if (curs_y
< 0 || curs_y
>= f
->height
)
1363 if (first_unused
<= 0)
1366 if (first_unused
>= f
->width
)
1367 first_unused
= f
->width
;
1369 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1375 /* Notice if the cursor will be cleared by this operation. */
1376 if (curs_y
== f
->phys_cursor_y
1377 && curs_x
<= f
->phys_cursor_x
1378 && f
->phys_cursor_x
< first_unused
)
1379 f
->phys_cursor_on
= 0;
1381 w32_clear_area (f
, NULL
,
1382 CHAR_TO_PIXEL_COL (f
, curs_x
),
1383 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1384 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
1385 f
->output_data
.w32
->line_height
);
1393 struct frame
*f
= updating_frame
;
1398 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1399 curs_x
= 0; /* Nominal cursor position is top left. */
1404 w32_clear_window (f
);
1406 /* We have to clear the scroll bars, too. If we have changed
1407 colors or something like that, then they should be notified. */
1408 x_scroll_bar_clear (f
);
1413 /* Make audible bell. */
1416 w32_ring_bell (void)
1423 HWND hwnd
= FRAME_W32_WINDOW (selected_frame
);
1425 for (i
= 0; i
< 5; i
++)
1427 FlashWindow (hwnd
, TRUE
);
1430 FlashWindow (hwnd
, FALSE
);
1433 w32_sys_ring_bell ();
1438 /* Insert and delete character.
1439 These are not supposed to be used because we are supposed to turn
1440 off the feature of using them. */
1443 w32_insert_glyphs (start
, len
)
1444 register GLYPH
*start
;
1451 w32_delete_glyphs (n
)
1457 /* Specify how many text lines, from the top of the window,
1458 should be affected by insert-lines and delete-lines operations.
1459 This, and those operations, are used only within an update
1460 that is bounded by calls to w32_update_begin and w32_update_end. */
1463 w32_set_terminal_window (n
)
1466 if (updating_frame
== 0)
1469 if ((n
<= 0) || (n
> updating_frame
->height
))
1470 flexlines
= updating_frame
->height
;
1475 /* These variables need not be per frame
1476 because redisplay is done on a frame-by-frame basis
1477 and the line dance for one frame is finished before
1478 anything is done for another frame. */
1480 /* Array of line numbers from cached insert/delete operations.
1481 line_dance[i] is the old position of the line that we want
1482 to move to line i, or -1 if we want a blank line there. */
1483 static int *line_dance
;
1485 /* Allocated length of that array. */
1486 static int line_dance_len
;
1488 /* Flag indicating whether we've done any work. */
1489 static int line_dance_in_progress
;
1491 /* Perform an insert-lines or delete-lines operation,
1492 inserting N lines or deleting -N lines at vertical position VPOS. */
1495 w32_ins_del_lines (vpos
, n
)
1498 register int fence
, i
;
1500 if (vpos
>= flexlines
)
1503 if (!line_dance_in_progress
)
1505 int ht
= updating_frame
->height
;
1506 if (ht
> line_dance_len
)
1508 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1509 line_dance_len
= ht
;
1511 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1512 line_dance_in_progress
= 1;
1516 if (n
> flexlines
- vpos
)
1517 n
= flexlines
- vpos
;
1519 for (i
= flexlines
; --i
>= fence
;)
1520 line_dance
[i
] = line_dance
[i
-n
];
1521 for (i
= fence
; --i
>= vpos
;)
1527 if (n
> flexlines
- vpos
)
1528 n
= flexlines
- vpos
;
1529 fence
= flexlines
- n
;
1530 for (i
= vpos
; i
< fence
; ++i
)
1531 line_dance
[i
] = line_dance
[i
+ n
];
1532 for (i
= fence
; i
< flexlines
; ++i
)
1537 /* Here's where we actually move the pixels around.
1538 Must be called with input blocked. */
1542 register int i
, j
, distance
;
1543 register struct frame
*f
;
1548 /* Must check this flag first. If it's not set, then not only is the
1549 array uninitialized, but we might not even have a frame. */
1550 if (!line_dance_in_progress
)
1558 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1560 x_display_cursor (updating_frame
, 0);
1562 hdc
= get_frame_dc (f
);
1564 for (i
= 0; i
< ht
; ++i
)
1565 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1567 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1568 && line_dance
[j
]-j
== distance
); ++j
);
1569 /* Copy [i,j) upward from [i+distance, j+distance) */
1571 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1572 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1573 (j
-i
) * FRAME_LINE_HEIGHT (f
),
1575 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1580 for (i
= ht
; --i
>=0; )
1581 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1583 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1584 && line_dance
[j
]-j
== distance
););
1585 /* Copy (j, i] downward from (j+distance, i+distance] */
1587 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1588 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1589 (i
-j
) * FRAME_LINE_HEIGHT (f
),
1591 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1596 for (i
= 0; i
< ht
; ++i
)
1597 if (line_dance
[i
] == -1)
1599 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1601 w32_clear_area (f
, hdc
,
1603 CHAR_TO_PIXEL_ROW (f
, i
),
1604 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (FRAME_FONT (f
)),
1605 (j
-i
) * FRAME_LINE_HEIGHT (f
));
1608 line_dance_in_progress
= 0;
1610 release_frame_dc (f
, hdc
);
1613 /* Support routines for exposure events. */
1614 static void clear_cursor ();
1616 /* Output into a rectangle of a window (for frame F)
1617 the characters in f->phys_lines that overlap that rectangle.
1618 TOP and LEFT are the position of the upper left corner of the rectangle.
1619 ROWS and COLS are the size of the rectangle.
1620 Call this function with input blocked. */
1623 dumprectangle (f
, left
, top
, cols
, rows
)
1625 register int left
, top
, cols
, rows
;
1627 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1628 int cursor_cleared
= 0;
1632 if (FRAME_GARBAGED_P (f
))
1635 /* Express rectangle as four edges, instead of position-and-size. */
1636 bottom
= top
+ rows
;
1637 right
= left
+ cols
;
1639 /* Convert rectangle edges in pixels to edges in chars.
1640 Round down for left and top, up for right and bottom. */
1641 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1642 left
= PIXEL_TO_CHAR_COL (f
, left
);
1643 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1644 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1645 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1646 right
= PIXEL_TO_CHAR_COL (f
, right
);
1648 /* Clip the rectangle to what can be visible. */
1649 if (left
< FRAME_LEFT_SCROLL_BAR_WIDTH (f
))
1650 left
= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1653 if (right
> f
->width
+ FRAME_LEFT_SCROLL_BAR_WIDTH (f
))
1654 right
= f
->width
+ FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1655 if (bottom
> f
->height
)
1658 /* Get size in chars of the rectangle. */
1659 cols
= right
- left
;
1660 rows
= bottom
- top
;
1662 /* If rectangle has zero area, return. */
1663 if (rows
<= 0) return;
1664 if (cols
<= 0) return;
1666 /* Turn off the cursor if it is in the rectangle.
1667 We will turn it back on afterward. */
1668 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1669 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1675 /* Display the text in the rectangle, one text line at a time. */
1677 for (y
= top
; y
< bottom
; y
++)
1679 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1681 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1684 while (*line
& GLYPH_MASK_PADDING
)
1686 /* We must display the whole glyph of a wide-column
1693 CHAR_TO_PIXEL_COL (f
, left
),
1694 CHAR_TO_PIXEL_ROW (f
, y
),
1695 line
, min (cols
, active_frame
->used
[y
] - left
),
1696 active_frame
->highlight
[y
], 0, NULL
);
1699 /* Turn the cursor on if we turned it off. */
1702 x_display_cursor (f
, 1);
1709 x_display_cursor (f
, 1);
1713 frame_unhighlight (f
)
1716 x_display_cursor (f
, 1);
1719 static void x_frame_rehighlight ();
1721 /* The focus has changed. Update the frames as necessary to reflect
1722 the new situation. Note that we can't change the selected frame
1723 here, because the Lisp code we are interrupting might become confused.
1724 Each event gets marked with the frame in which it occurred, so the
1725 Lisp code can tell when the switch took place by examining the events. */
1728 x_new_focus_frame (dpyinfo
, frame
)
1729 struct w32_display_info
*dpyinfo
;
1730 struct frame
*frame
;
1732 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1733 int events_enqueued
= 0;
1735 if (frame
!= dpyinfo
->w32_focus_frame
)
1737 /* Set this before calling other routines, so that they see
1738 the correct value of w32_focus_frame. */
1739 dpyinfo
->w32_focus_frame
= frame
;
1741 if (old_focus
&& old_focus
->auto_lower
)
1742 x_lower_frame (old_focus
);
1744 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1745 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1747 pending_autoraise_frame
= 0;
1750 x_frame_rehighlight (dpyinfo
);
1753 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1756 x_mouse_leave (dpyinfo
)
1757 struct w32_display_info
*dpyinfo
;
1759 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1762 /* The focus has changed, or we have redirected a frame's focus to
1763 another frame (this happens when a frame uses a surrogate
1764 minibuffer frame). Shift the highlight as appropriate.
1766 The FRAME argument doesn't necessarily have anything to do with which
1767 frame is being highlighted or unhighlighted; we only use it to find
1768 the appropriate display info. */
1770 w32_frame_rehighlight (frame
)
1771 struct frame
*frame
;
1773 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1777 x_frame_rehighlight (dpyinfo
)
1778 struct w32_display_info
*dpyinfo
;
1780 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1782 if (dpyinfo
->w32_focus_frame
)
1784 dpyinfo
->w32_highlight_frame
1785 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1786 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1787 : dpyinfo
->w32_focus_frame
);
1788 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1790 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1791 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1795 dpyinfo
->w32_highlight_frame
= 0;
1797 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1800 frame_unhighlight (old_highlight
);
1801 if (dpyinfo
->w32_highlight_frame
)
1802 frame_highlight (dpyinfo
->w32_highlight_frame
);
1806 /* Keyboard processing - modifier keys, etc. */
1808 /* Convert a keysym to its name. */
1811 x_get_keysym_name (keysym
)
1814 /* Make static so we can always return it */
1815 static char value
[100];
1818 GetKeyNameText(keysym
, value
, 100);
1824 /* Mouse clicks and mouse movement. Rah. */
1826 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1827 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1828 that the glyph at X, Y occupies, if BOUNDS != 0.
1829 If NOCLIP is nonzero, do not force the value into range. */
1832 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1834 register int pix_x
, pix_y
;
1835 register int *x
, *y
;
1839 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1840 if (NILP (Vwindow_system
))
1847 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1848 even for negative values. */
1850 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1852 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1854 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1855 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1859 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1860 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1861 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1862 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1869 else if (pix_x
> f
->width
)
1874 else if (pix_y
> f
->height
)
1883 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1886 register int *pix_x
, *pix_y
;
1888 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1889 if (NILP (Vwindow_system
))
1896 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1897 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1901 parse_button (message
, pbutton
, pup
)
1911 case WM_LBUTTONDOWN
:
1919 case WM_MBUTTONDOWN
:
1920 if (NILP (Vw32_swap_mouse_buttons
))
1927 if (NILP (Vw32_swap_mouse_buttons
))
1933 case WM_RBUTTONDOWN
:
1934 if (NILP (Vw32_swap_mouse_buttons
))
1941 if (NILP (Vw32_swap_mouse_buttons
))
1952 if (pbutton
) *pbutton
= button
;
1958 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1960 If the event is a button press, then note that we have grabbed
1964 construct_mouse_click (result
, msg
, f
)
1965 struct input_event
*result
;
1972 parse_button (msg
->msg
.message
, &button
, &up
);
1974 /* Make the event type no_event; we'll change that when we decide
1976 result
->kind
= mouse_click
;
1977 result
->code
= button
;
1978 result
->timestamp
= msg
->msg
.time
;
1979 result
->modifiers
= (msg
->dwModifiers
1987 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1988 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1989 XSETFRAME (result
->frame_or_window
, f
);
1994 construct_mouse_wheel (result
, msg
, f
)
1995 struct input_event
*result
;
2000 result
->kind
= mouse_wheel
;
2001 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
2002 result
->timestamp
= msg
->msg
.time
;
2003 result
->modifiers
= msg
->dwModifiers
;
2004 p
.x
= LOWORD (msg
->msg
.lParam
);
2005 p
.y
= HIWORD (msg
->msg
.lParam
);
2006 ScreenToClient(msg
->msg
.hwnd
, &p
);
2007 XSETINT (result
->x
, p
.x
);
2008 XSETINT (result
->y
, p
.y
);
2009 XSETFRAME (result
->frame_or_window
, f
);
2013 construct_drag_n_drop (result
, msg
, f
)
2014 struct input_event
*result
;
2026 result
->kind
= drag_n_drop
;
2028 result
->timestamp
= msg
->msg
.time
;
2029 result
->modifiers
= msg
->dwModifiers
;
2031 hdrop
= (HDROP
) msg
->msg
.wParam
;
2032 DragQueryPoint (hdrop
, &p
);
2035 p
.x
= LOWORD (msg
->msg
.lParam
);
2036 p
.y
= HIWORD (msg
->msg
.lParam
);
2037 ScreenToClient (msg
->msg
.hwnd
, &p
);
2040 XSETINT (result
->x
, p
.x
);
2041 XSETINT (result
->y
, p
.y
);
2043 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
2046 for (i
= 0; i
< num_files
; i
++)
2048 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
2051 name
= alloca (len
+ 1);
2052 DragQueryFile (hdrop
, i
, name
, len
+ 1);
2053 files
= Fcons (build_string (name
), files
);
2058 XSETFRAME (frame
, f
);
2059 result
->frame_or_window
= Fcons (frame
, files
);
2063 /* Function to report a mouse movement to the mainstream Emacs code.
2064 The input handler calls this.
2066 We have received a mouse movement event, which is given in *event.
2067 If the mouse is over a different glyph than it was last time, tell
2068 the mainstream emacs code by setting mouse_moved. If not, ask for
2069 another motion event, so we can check again the next time it moves. */
2072 note_mouse_movement (frame
, msg
)
2076 last_mouse_movement_time
= msg
->time
;
2078 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
2080 frame
->mouse_moved
= 1;
2081 last_mouse_scroll_bar
= Qnil
;
2083 note_mouse_highlight (frame
, -1, -1);
2086 /* Has the mouse moved off the glyph it was on at the last sighting? */
2087 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
2088 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
2089 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
2090 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
2092 frame
->mouse_moved
= 1;
2093 last_mouse_scroll_bar
= Qnil
;
2095 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
2099 /* This is used for debugging, to turn off note_mouse_highlight. */
2100 static int disable_mouse_highlight
;
2102 /* Take proper action when the mouse has moved to position X, Y on frame F
2103 as regards highlighting characters that have mouse-face properties.
2104 Also dehighlighting chars where the mouse was before.
2105 X and Y can be negative or out of range. */
2108 note_mouse_highlight (f
, x
, y
)
2112 int row
, column
, portion
;
2117 if (disable_mouse_highlight
)
2120 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2121 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2122 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2124 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
2129 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2133 /* Find out which glyph the mouse is on. */
2134 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2135 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
2137 /* Which window is that in? */
2138 window
= window_from_coordinates (f
, column
, row
, &portion
);
2139 w
= XWINDOW (window
);
2141 /* If we were displaying active text in another window, clear that. */
2142 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
2143 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2145 /* Are we in a window whose display is up to date?
2146 And verify the buffer's text has not changed. */
2147 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2148 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2149 && EQ (w
->window_end_valid
, w
->buffer
)
2150 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2151 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2153 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2156 /* Find which buffer position the mouse corresponds to. */
2157 for (i
= column
; i
>= 0; i
--)
2161 /* Is it outside the displayed active region (if any)? */
2163 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2164 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
2165 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2166 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2167 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2168 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2169 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2170 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2171 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2173 Lisp_Object mouse_face
, overlay
, position
;
2174 Lisp_Object
*overlay_vec
;
2175 int len
, noverlays
, ignor1
;
2176 struct buffer
*obuf
;
2179 /* If we get an out-of-range value, return now; avoid an error. */
2180 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2183 /* Make the window's buffer temporarily current for
2184 overlays_at and compute_char_face. */
2185 obuf
= current_buffer
;
2186 current_buffer
= XBUFFER (w
->buffer
);
2192 /* Yes. Clear the display of the old active region, if any. */
2193 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2195 /* Is this char mouse-active? */
2196 XSETINT (position
, pos
);
2199 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2201 /* Put all the overlays we want in a vector in overlay_vec.
2202 Store the length in len. */
2203 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2205 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2207 /* Find the highest priority overlay that has a mouse-face prop. */
2209 for (i
= 0; i
< noverlays
; i
++)
2211 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2212 if (!NILP (mouse_face
))
2214 overlay
= overlay_vec
[i
];
2219 /* If no overlay applies, get a text property. */
2221 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2223 /* Handle the overlay case. */
2224 if (! NILP (overlay
))
2226 /* Find the range of text around this char that
2227 should be active. */
2228 Lisp_Object before
, after
;
2231 before
= Foverlay_start (overlay
);
2232 after
= Foverlay_end (overlay
);
2233 /* Record this as the current active region. */
2234 fast_find_position (window
, before
,
2235 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2236 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2237 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2238 = !fast_find_position (window
, after
,
2239 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2240 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2241 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2242 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2243 = compute_char_face (f
, w
, pos
, 0, 0,
2244 &ignore
, pos
+ 1, 1);
2246 /* Display it as active. */
2247 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2249 /* Handle the text property case. */
2250 else if (! NILP (mouse_face
))
2252 /* Find the range of text around this char that
2253 should be active. */
2254 Lisp_Object before
, after
, beginning
, end
;
2257 beginning
= Fmarker_position (w
->start
);
2258 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2259 - XFASTINT (w
->window_end_pos
)));
2261 = Fprevious_single_property_change (make_number (pos
+ 1),
2263 w
->buffer
, beginning
);
2265 = Fnext_single_property_change (position
, Qmouse_face
,
2267 /* Record this as the current active region. */
2268 fast_find_position (window
, before
,
2269 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2270 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2271 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2272 = !fast_find_position (window
, after
,
2273 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2274 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2275 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2276 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2277 = compute_char_face (f
, w
, pos
, 0, 0,
2278 &ignore
, pos
+ 1, 1);
2280 /* Display it as active. */
2281 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2285 current_buffer
= obuf
;
2290 /* Find the row and column of position POS in window WINDOW.
2291 Store them in *COLUMNP and *ROWP.
2292 This assumes display in WINDOW is up to date.
2293 If POS is above start of WINDOW, return coords
2294 of start of first screen line.
2295 If POS is after end of WINDOW, return coords of end of last screen line.
2297 Value is 1 if POS is in range, 0 if it was off screen. */
2300 fast_find_position (window
, pos
, columnp
, rowp
)
2303 int *columnp
, *rowp
;
2305 struct window
*w
= XWINDOW (window
);
2306 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2309 int left
= WINDOW_LEFT_MARGIN (w
);
2311 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2312 int width
= window_internal_width (w
);
2315 int maybe_next_line
= 0;
2317 /* Find the right row. */
2322 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2323 if (linestart
> pos
)
2325 /* If the position sought is the end of the buffer,
2326 don't include the blank lines at the bottom of the window. */
2327 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2329 maybe_next_line
= 1;
2336 /* Find the right column with in it. */
2337 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2339 for (i
= 0; i
< width
; i
++)
2341 if (charstarts
[left
+ i
] == pos
)
2344 *columnp
= i
+ left
;
2347 else if (charstarts
[left
+ i
] > pos
)
2349 else if (charstarts
[left
+ i
] > 0)
2353 /* If we're looking for the end of the buffer,
2354 and we didn't find it in the line we scanned,
2355 use the start of the following line. */
2356 if (maybe_next_line
)
2367 /* Display the active region described by mouse_face_*
2368 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2371 show_mouse_face (dpyinfo
, hl
)
2372 struct w32_display_info
*dpyinfo
;
2375 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2376 int width
= window_internal_width (w
);
2377 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2380 int old_curs_x
= curs_x
;
2381 int old_curs_y
= curs_y
;
2383 /* Set these variables temporarily
2384 so that if we have to turn the cursor off and on again
2385 we will put it back at the same place. */
2386 curs_x
= f
->phys_cursor_x
;
2387 curs_y
= f
->phys_cursor_y
;
2389 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2390 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2392 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2393 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
2394 : WINDOW_LEFT_MARGIN (w
));
2395 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2396 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2397 : WINDOW_LEFT_MARGIN (w
) + width
);
2398 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2400 /* If the cursor's in the text we are about to rewrite,
2401 turn the cursor off. */
2403 && curs_x
>= column
- 1
2404 && curs_x
<= endcolumn
)
2406 x_display_cursor (f
, 0);
2411 CHAR_TO_PIXEL_COL (f
, column
),
2412 CHAR_TO_PIXEL_ROW (f
, i
),
2413 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2415 /* Highlight with mouse face if hl > 0. */
2416 hl
> 0 ? 3 : 0, 0, NULL
);
2419 /* If we turned the cursor off, turn it back on. */
2421 x_display_cursor (f
, 1);
2423 curs_x
= old_curs_x
;
2424 curs_y
= old_curs_y
;
2426 /* Change the mouse cursor according to the value of HL. */
2428 SetCursor (f
->output_data
.w32
->cross_cursor
);
2430 SetCursor (f
->output_data
.w32
->text_cursor
);
2433 /* Clear out the mouse-highlighted active region.
2434 Redraw it unhighlighted first. */
2437 clear_mouse_face (dpyinfo
)
2438 struct w32_display_info
*dpyinfo
;
2440 if (! NILP (dpyinfo
->mouse_face_window
))
2441 show_mouse_face (dpyinfo
, 0);
2443 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2444 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2445 dpyinfo
->mouse_face_window
= Qnil
;
2448 /* Just discard the mouse face information for frame F, if any.
2449 This is used when the size of F is changed. */
2452 cancel_mouse_face (f
)
2456 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
2458 window
= dpyinfo
->mouse_face_window
;
2459 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2461 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2462 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2463 dpyinfo
->mouse_face_window
= Qnil
;
2467 struct scroll_bar
*x_window_to_scroll_bar ();
2468 static void x_scroll_bar_report_motion ();
2470 /* Return the current position of the mouse.
2471 *fp should be a frame which indicates which display to ask about.
2473 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2474 and *part to the frame, window, and scroll bar part that the mouse
2475 is over. Set *x and *y to the portion and whole of the mouse's
2476 position on the scroll bar.
2478 If the mouse movement started elsewhere, set *fp to the frame the
2479 mouse is on, *bar_window to nil, and *x and *y to the character cell
2482 Set *time to the server timestamp for the time at which the mouse
2483 was at this position.
2485 Don't store anything if we don't have a valid set of values to report.
2487 This clears the mouse_moved flag, so we can wait for the next mouse
2488 movement. This also calls XQueryPointer, which will cause the
2489 server to give us another MotionNotify when the mouse moves
2493 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2496 Lisp_Object
*bar_window
;
2497 enum scroll_bar_part
*part
;
2499 unsigned long *time
;
2505 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2506 /* This is never called at the moment. */
2507 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2512 Lisp_Object frame
, tail
;
2514 /* Clear the mouse-moved flag for every frame on this display. */
2515 FOR_EACH_FRAME (tail
, frame
)
2516 XFRAME (frame
)->mouse_moved
= 0;
2518 last_mouse_scroll_bar
= Qnil
;
2522 /* Now we have a position on the root; find the innermost window
2523 containing the pointer. */
2525 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2526 && FRAME_LIVE_P (last_mouse_frame
))
2528 /* If mouse was grabbed on a frame, give coords for that frame
2529 even if the mouse is now outside it. */
2530 f1
= last_mouse_frame
;
2534 /* Is window under mouse one of our frames? */
2535 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
2538 /* If not, is it one of our scroll bars? */
2541 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
2545 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2549 if (f1
== 0 && insist
> 0)
2550 f1
= selected_frame
;
2554 int ignore1
, ignore2
;
2556 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
2558 /* Ok, we found a frame. Store all the values. */
2560 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
2562 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
2570 *time
= last_mouse_movement_time
;
2578 /* Scroll bar support. */
2580 /* Given an window ID, find the struct scroll_bar which manages it.
2581 This can be called in GC, so we have to make sure to strip off mark
2584 x_window_to_scroll_bar (window_id
)
2587 Lisp_Object tail
, frame
;
2589 for (tail
= Vframe_list
;
2590 XGCTYPE (tail
) == Lisp_Cons
;
2593 Lisp_Object frame
, bar
, condemned
;
2595 frame
= XCAR (tail
);
2596 /* All elements of Vframe_list should be frames. */
2597 if (! GC_FRAMEP (frame
))
2600 /* Scan this frame's scroll bar list for a scroll bar with the
2602 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2603 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2604 /* This trick allows us to search both the ordinary and
2605 condemned scroll bar lists with one loop. */
2606 ! GC_NILP (bar
) || (bar
= condemned
,
2609 bar
= XSCROLL_BAR (bar
)->next
)
2610 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2611 return XSCROLL_BAR (bar
);
2618 my_create_scrollbar (f
, bar
)
2620 struct scroll_bar
* bar
;
2622 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2623 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2627 //#define ATTACH_THREADS
2630 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2632 #ifndef ATTACH_THREADS
2633 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2634 (WPARAM
) hwnd
, (LPARAM
) how
);
2636 return ShowWindow (hwnd
, how
);
2641 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2642 int x
, int y
, int cx
, int cy
, UINT flags
)
2644 #ifndef ATTACH_THREADS
2646 pos
.hwndInsertAfter
= hwndAfter
;
2652 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2654 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2659 my_set_focus (f
, hwnd
)
2663 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2668 my_set_foreground_window (hwnd
)
2671 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2675 my_destroy_window (f
, hwnd
)
2679 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2683 /* Open a new window to serve as a scroll bar, and return the
2684 scroll bar vector for it. */
2685 static struct scroll_bar
*
2686 x_scroll_bar_create (window
, top
, left
, width
, height
)
2687 struct window
*window
;
2688 int top
, left
, width
, height
;
2690 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2691 struct scroll_bar
*bar
2692 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2697 XSETWINDOW (bar
->window
, window
);
2698 XSETINT (bar
->top
, top
);
2699 XSETINT (bar
->left
, left
);
2700 XSETINT (bar
->width
, width
);
2701 XSETINT (bar
->height
, height
);
2702 XSETINT (bar
->start
, 0);
2703 XSETINT (bar
->end
, 0);
2704 bar
->dragging
= Qnil
;
2706 /* Requires geometry to be set before call to create the real window */
2708 hwnd
= my_create_scrollbar (f
, bar
);
2710 if (pfnSetScrollInfo
)
2714 si
.cbSize
= sizeof (si
);
2717 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2718 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2722 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2726 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2727 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2730 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2732 /* Add bar to its frame's list of scroll bars. */
2733 bar
->next
= FRAME_SCROLL_BARS (f
);
2735 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2736 if (! NILP (bar
->next
))
2737 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2744 /* Draw BAR's handle in the proper position.
2745 If the handle is already drawn from START to END, don't bother
2746 redrawing it, unless REBUILD is non-zero; in that case, always
2747 redraw it. (REBUILD is handy for drawing the handle after expose
2750 Normally, we want to constrain the start and end of the handle to
2751 fit inside its rectangle, but if the user is dragging the scroll bar
2752 handle, we want to let them drag it down all the way, so that the
2753 bar's top is as far down as it goes; otherwise, there's no way to
2754 move to the very end of the buffer. */
2756 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2757 struct scroll_bar
*bar
;
2761 int dragging
= ! NILP (bar
->dragging
);
2762 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2763 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2765 /* If the display is already accurate, do nothing. */
2767 && start
== XINT (bar
->start
)
2768 && end
== XINT (bar
->end
))
2774 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2776 /* Make sure the values are reasonable, and try to preserve
2777 the distance between start and end. */
2779 int length
= end
- start
;
2783 else if (start
> top_range
)
2785 end
= start
+ length
;
2789 else if (end
> top_range
&& ! dragging
)
2794 /* Store the adjusted setting in the scroll bar. */
2795 XSETINT (bar
->start
, start
);
2796 XSETINT (bar
->end
, end
);
2798 /* If being dragged, let scroll bar update itself. */
2801 if (pfnSetScrollInfo
)
2805 si
.cbSize
= sizeof (si
);
2806 si
.fMask
= SIF_PAGE
| SIF_POS
;
2807 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2810 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2813 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2819 /* Move a scroll bar around on the screen, to accommodate changing
2820 window configurations. */
2822 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2823 struct scroll_bar
*bar
;
2824 int top
, left
, width
, height
;
2826 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2827 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2829 /* If already correctly positioned, do nothing. */
2830 if ( XINT (bar
->left
) == left
2831 && XINT (bar
->top
) == top
2832 && XINT (bar
->width
) == width
2833 && XINT (bar
->height
) == height
)
2835 /* Redraw after clear_frame. */
2836 if (!my_show_window (f
, w
, SW_NORMAL
))
2837 InvalidateRect (w
, NULL
, FALSE
);
2843 /* Make sure scroll bar is "visible" before moving, to ensure the
2844 area of the parent window now exposed will be refreshed. */
2845 my_show_window (f
, w
, SW_HIDE
);
2846 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2847 if (pfnSetScrollInfo
)
2851 si
.cbSize
= sizeof (si
);
2852 si
.fMask
= SIF_RANGE
;
2854 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2855 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2857 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2860 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2861 my_show_window (f
, w
, SW_NORMAL
);
2862 // InvalidateRect (w, NULL, FALSE);
2864 XSETINT (bar
->left
, left
);
2865 XSETINT (bar
->top
, top
);
2866 XSETINT (bar
->width
, width
);
2867 XSETINT (bar
->height
, height
);
2872 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2875 x_scroll_bar_remove (bar
)
2876 struct scroll_bar
*bar
;
2878 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2882 /* Destroy the window. */
2883 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2885 /* Disassociate this scroll bar from its window. */
2886 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2891 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2892 that we are displaying PORTION characters out of a total of WHOLE
2893 characters, starting at POSITION. If WINDOW has no scroll bar,
2896 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2897 struct window
*window
;
2898 int portion
, whole
, position
;
2900 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2901 int top
= XINT (window
->top
);
2902 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2903 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2905 /* Where should this scroll bar be, pixelwise? */
2906 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2907 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2909 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2910 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2911 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2912 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2914 struct scroll_bar
*bar
;
2916 /* Does the scroll bar exist yet? */
2917 if (NILP (window
->vertical_scroll_bar
))
2918 bar
= x_scroll_bar_create (window
,
2919 pixel_top
, pixel_left
,
2920 pixel_width
, pixel_height
);
2923 /* It may just need to be moved and resized. */
2924 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2925 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2928 /* Set the scroll bar's current state. */
2930 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2933 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2936 int start
= (int) (((double) position
* top_range
) / whole
);
2937 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2939 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2943 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2947 /* The following three hooks are used when we're doing a thorough
2948 redisplay of the frame. We don't explicitly know which scroll bars
2949 are going to be deleted, because keeping track of when windows go
2950 away is a real pain - "Can you say set-window-configuration, boys
2951 and girls?" Instead, we just assert at the beginning of redisplay
2952 that *all* scroll bars are to be removed, and then save a scroll bar
2953 from the fiery pit when we actually redisplay its window. */
2955 /* Arrange for all scroll bars on FRAME to be removed at the next call
2956 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2957 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2959 w32_condemn_scroll_bars (frame
)
2962 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2963 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2966 bar
= FRAME_SCROLL_BARS (frame
);
2967 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2968 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2969 XSCROLL_BAR (bar
)->prev
= Qnil
;
2970 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2971 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2972 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2975 /* The condemned list should be empty at this point; if it's not,
2976 then the rest of Emacs isn't using the condemn/redeem/judge
2977 protocol correctly. */
2978 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2981 /* Move them all to the "condemned" list. */
2982 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2983 FRAME_SCROLL_BARS (frame
) = Qnil
;
2987 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2988 Note that WINDOW isn't necessarily condemned at all. */
2990 w32_redeem_scroll_bar (window
)
2991 struct window
*window
;
2993 struct scroll_bar
*bar
;
2995 /* We can't redeem this window's scroll bar if it doesn't have one. */
2996 if (NILP (window
->vertical_scroll_bar
))
2999 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3001 /* Unlink it from the condemned list. */
3003 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3005 if (NILP (bar
->prev
))
3007 /* If the prev pointer is nil, it must be the first in one of
3009 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3010 /* It's not condemned. Everything's fine. */
3012 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3013 window
->vertical_scroll_bar
))
3014 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3016 /* If its prev pointer is nil, it must be at the front of
3017 one or the other! */
3021 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3023 if (! NILP (bar
->next
))
3024 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3026 bar
->next
= FRAME_SCROLL_BARS (f
);
3028 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3029 if (! NILP (bar
->next
))
3030 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3033 struct scroll_bar
*bar
;
3035 /* We can't redeem this window's scroll bar if it doesn't have one. */
3036 if (NILP (window
->vertical_scroll_bar
))
3039 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3041 /* Unlink it from the condemned list. */
3043 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3045 if (NILP (bar
->prev
))
3047 /* If the prev pointer is nil, it must be the first in one of
3049 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3050 /* It's not condemned. Everything's fine. */
3052 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3053 window
->vertical_scroll_bar
))
3054 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3056 /* If its prev pointer is nil, it must be at the front of
3057 one or the other! */
3061 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3063 if (! NILP (bar
->next
))
3064 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3066 bar
->next
= FRAME_SCROLL_BARS (f
);
3068 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3069 if (! NILP (bar
->next
))
3070 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3075 /* Remove all scroll bars on FRAME that haven't been saved since the
3076 last call to `*condemn_scroll_bars_hook'. */
3078 w32_judge_scroll_bars (f
)
3081 Lisp_Object bar
, next
;
3083 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3085 /* Clear out the condemned list now so we won't try to process any
3086 more events on the hapless scroll bars. */
3087 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3089 for (; ! NILP (bar
); bar
= next
)
3091 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3093 x_scroll_bar_remove (b
);
3096 b
->next
= b
->prev
= Qnil
;
3099 /* Now there should be no references to the condemned scroll bars,
3100 and they should get garbage-collected. */
3102 Lisp_Object bar
, next
;
3104 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3106 /* Clear out the condemned list now so we won't try to process any
3107 more events on the hapless scroll bars. */
3108 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3110 for (; ! NILP (bar
); bar
= next
)
3112 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3114 x_scroll_bar_remove (b
);
3117 b
->next
= b
->prev
= Qnil
;
3120 /* Now there should be no references to the condemned scroll bars,
3121 and they should get garbage-collected. */
3125 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3126 is set to something other than no_event, it is enqueued.
3128 This may be called from a signal handler, so we have to ignore GC
3132 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3133 struct scroll_bar
*bar
;
3135 struct input_event
*emacs_event
;
3137 if (! GC_WINDOWP (bar
->window
))
3140 emacs_event
->kind
= w32_scroll_bar_click
;
3141 emacs_event
->code
= 0;
3142 /* not really meaningful to distinguish up/down */
3143 emacs_event
->modifiers
= msg
->dwModifiers
;
3144 emacs_event
->frame_or_window
= bar
->window
;
3145 emacs_event
->timestamp
= msg
->msg
.time
;
3148 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3150 int dragging
= !NILP (bar
->dragging
);
3152 if (pfnGetScrollInfo
)
3156 si
.cbSize
= sizeof (si
);
3159 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3163 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
3165 bar
->dragging
= Qnil
;
3167 switch (LOWORD (msg
->msg
.wParam
))
3170 emacs_event
->part
= scroll_bar_down_arrow
;
3173 emacs_event
->part
= scroll_bar_up_arrow
;
3176 emacs_event
->part
= scroll_bar_above_handle
;
3179 emacs_event
->part
= scroll_bar_below_handle
;
3182 emacs_event
->part
= scroll_bar_handle
;
3186 emacs_event
->part
= scroll_bar_handle
;
3190 case SB_THUMBPOSITION
:
3191 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3192 y
= HIWORD (msg
->msg
.wParam
);
3194 emacs_event
->part
= scroll_bar_handle
;
3196 /* "Silently" update current position. */
3197 if (pfnSetScrollInfo
)
3201 si
.cbSize
= sizeof (si
);
3205 /* Shrink handle if necessary to allow full range for position. */
3207 int start
= XINT (bar
->start
);
3208 int end
= XINT (bar
->end
);
3209 int len
= end
- start
;
3211 /* If new end is nearly hitting bottom, we must shrink
3212 handle. How much we shrink it depends on the relative
3213 sizes of len and top_range. */
3214 if (y
+ len
> top_range
- 2)
3216 len
-= min (top_range
/ 10, (len
/ 3) + 2);
3220 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3221 si
.fMask
|= SIF_PAGE
;
3225 /* Remember apparent position (we actually lag behind the real
3226 position, so don't set that directly. */
3227 last_scroll_bar_drag_pos
= y
;
3229 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3232 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
3235 /* If this is the end of a drag sequence, then reset the scroll
3236 handle size to normal and do a final redraw. Otherwise do
3240 if (pfnSetScrollInfo
)
3243 int start
= XINT (bar
->start
);
3244 int end
= XINT (bar
->end
);
3246 si
.cbSize
= sizeof (si
);
3247 si
.fMask
= SIF_PAGE
| SIF_POS
;
3248 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3249 si
.nPos
= last_scroll_bar_drag_pos
;
3251 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3254 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
3258 emacs_event
->kind
= no_event
;
3262 XSETINT (emacs_event
->x
, y
);
3263 XSETINT (emacs_event
->y
, top_range
);
3269 /* Return information to the user about the current position of the mouse
3270 on the scroll bar. */
3272 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3274 Lisp_Object
*bar_window
;
3275 enum scroll_bar_part
*part
;
3277 unsigned long *time
;
3279 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3280 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3281 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3283 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3288 *bar_window
= bar
->window
;
3290 if (pfnGetScrollInfo
)
3294 si
.cbSize
= sizeof (si
);
3295 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3297 pfnGetScrollInfo (w
, SB_CTL
, &si
);
3299 top_range
= si
.nMax
- si
.nPage
+ 1;
3302 pos
= GetScrollPos (w
, SB_CTL
);
3304 switch (LOWORD (last_mouse_scroll_bar_pos
))
3306 case SB_THUMBPOSITION
:
3308 *part
= scroll_bar_handle
;
3309 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3310 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3313 *part
= scroll_bar_handle
;
3317 *part
= scroll_bar_handle
;
3322 XSETINT(*y
, top_range
);
3325 last_mouse_scroll_bar
= Qnil
;
3327 *time
= last_mouse_movement_time
;
3332 /* The screen has been cleared so we may have changed foreground or
3333 background colors, and the scroll bars may need to be redrawn.
3334 Clear out the scroll bars, and ask for expose events, so we can
3337 x_scroll_bar_clear (f
)
3342 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3343 bar
= XSCROLL_BAR (bar
)->next
)
3345 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3346 HDC hdc
= GetDC (window
);
3349 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3350 arranges to refresh the scroll bar if hidden. */
3351 my_show_window (f
, window
, SW_HIDE
);
3353 GetClientRect (window
, &rect
);
3354 select_palette (f
, hdc
);
3355 w32_clear_rect (f
, hdc
, &rect
);
3356 deselect_palette (f
, hdc
);
3358 ReleaseDC (window
, hdc
);
3362 show_scroll_bars (f
, how
)
3368 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3369 bar
= XSCROLL_BAR (bar
)->next
)
3371 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3372 my_show_window (f
, window
, how
);
3377 /* The main W32 event-reading loop - w32_read_socket. */
3379 /* Timestamp of enter window event. This is only used by w32_read_socket,
3380 but we have to put it out here, since static variables within functions
3381 sometimes don't work. */
3382 static Time enter_timestamp
;
3384 /* Record the last 100 characters stored
3385 to help debug the loss-of-chars-during-GC problem. */
3387 short temp_buffer
[100];
3390 /* Read events coming from the W32 shell.
3391 This routine is called by the SIGIO handler.
3392 We return as soon as there are no more events to be read.
3394 Events representing keys are stored in buffer BUFP,
3395 which can hold up to NUMCHARS characters.
3396 We return the number of characters stored into the buffer,
3397 thus pretending to be `read'.
3399 EXPECTED is nonzero if the caller knows input is available.
3401 Some of these messages are reposted back to the message queue since the
3402 system calls the windows proc directly in a context where we cannot return
3403 the data nor can we guarantee the state we are in. So if we dispatch them
3404 we will get into an infinite loop. To prevent this from ever happening we
3405 will set a variable to indicate we are in the read_socket call and indicate
3406 which message we are processing since the windows proc gets called
3407 recursively with different messages by the system.
3411 w32_read_socket (sd
, bufp
, numchars
, expected
)
3413 register struct input_event
*bufp
;
3414 register int numchars
;
3418 int check_visibility
= 0;
3422 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3424 if (interrupt_input_blocked
)
3426 interrupt_input_pending
= 1;
3430 interrupt_input_pending
= 0;
3433 /* So people can tell when we have read the available input. */
3434 input_signal_count
++;
3437 abort (); /* Don't think this happens. */
3439 while (get_next_msg (&msg
, FALSE
))
3441 switch (msg
.msg
.message
)
3444 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3448 if (msg
.rect
.right
== msg
.rect
.left
||
3449 msg
.rect
.bottom
== msg
.rect
.top
)
3451 /* We may get paint messages even though the client
3452 area is clipped - these are not expose events. */
3453 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3454 XSTRING (f
->name
)->data
));
3456 else if (f
->async_visible
!= 1)
3458 /* Definitely not obscured, so mark as visible. */
3459 f
->async_visible
= 1;
3460 f
->async_iconified
= 0;
3461 SET_FRAME_GARBAGED (f
);
3462 DebPrint (("frame %04x (%s) reexposed\n", f
,
3463 XSTRING (f
->name
)->data
));
3465 /* WM_PAINT serves as MapNotify as well, so report
3466 visibility changes properly. */
3469 bufp
->kind
= deiconify_event
;
3470 XSETFRAME (bufp
->frame_or_window
, f
);
3475 else if (! NILP(Vframe_list
)
3476 && ! NILP (XCDR (Vframe_list
)))
3477 /* Force a redisplay sooner or later to update the
3478 frame titles in case this is the second frame. */
3479 record_asynch_buffer_change ();
3483 /* Erase background again for safety. */
3484 w32_clear_rect (f
, NULL
, &msg
.rect
);
3488 msg
.rect
.right
- msg
.rect
.left
,
3489 msg
.rect
.bottom
- msg
.rect
.top
);
3494 case WM_INPUTLANGCHANGE
:
3495 /* Generate a language change event. */
3496 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3503 bufp
->kind
= language_change_event
;
3504 XSETFRAME (bufp
->frame_or_window
, f
);
3505 bufp
->code
= msg
.msg
.wParam
;
3506 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
3515 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3517 if (f
&& !f
->iconified
)
3519 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3521 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3522 bufp
->kind
= non_ascii_keystroke
;
3523 bufp
->code
= msg
.msg
.wParam
;
3524 bufp
->modifiers
= msg
.dwModifiers
;
3525 XSETFRAME (bufp
->frame_or_window
, f
);
3526 bufp
->timestamp
= msg
.msg
.time
;
3535 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3537 if (f
&& !f
->iconified
)
3539 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3541 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3542 bufp
->kind
= ascii_keystroke
;
3543 bufp
->code
= msg
.msg
.wParam
;
3544 bufp
->modifiers
= msg
.dwModifiers
;
3545 XSETFRAME (bufp
->frame_or_window
, f
);
3546 bufp
->timestamp
= msg
.msg
.time
;
3554 if (dpyinfo
->grabbed
&& last_mouse_frame
3555 && FRAME_LIVE_P (last_mouse_frame
))
3556 f
= last_mouse_frame
;
3558 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3561 note_mouse_movement (f
, &msg
.msg
);
3563 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3567 case WM_LBUTTONDOWN
:
3569 case WM_MBUTTONDOWN
:
3571 case WM_RBUTTONDOWN
:
3577 if (dpyinfo
->grabbed
&& last_mouse_frame
3578 && FRAME_LIVE_P (last_mouse_frame
))
3579 f
= last_mouse_frame
;
3581 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3585 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3588 construct_mouse_click (bufp
, &msg
, f
);
3595 parse_button (msg
.msg
.message
, &button
, &up
);
3599 dpyinfo
->grabbed
&= ~ (1 << button
);
3603 dpyinfo
->grabbed
|= (1 << button
);
3604 last_mouse_frame
= f
;
3610 if (dpyinfo
->grabbed
&& last_mouse_frame
3611 && FRAME_LIVE_P (last_mouse_frame
))
3612 f
= last_mouse_frame
;
3614 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3618 if ((!dpyinfo
->w32_focus_frame
3619 || f
== dpyinfo
->w32_focus_frame
)
3622 construct_mouse_wheel (bufp
, &msg
, f
);
3631 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3635 construct_drag_n_drop (bufp
, &msg
, f
);
3644 struct scroll_bar
*bar
=
3645 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3647 if (bar
&& numchars
>= 1)
3649 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3659 case WM_WINDOWPOSCHANGED
:
3661 case WM_ACTIVATEAPP
:
3662 check_visibility
= 1;
3666 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3668 if (f
&& !f
->async_iconified
)
3672 x_real_positions (f
, &x
, &y
);
3673 f
->output_data
.w32
->left_pos
= x
;
3674 f
->output_data
.w32
->top_pos
= y
;
3677 check_visibility
= 1;
3681 /* If window has been obscured or exposed by another window
3682 being maximised or minimised/restored, then recheck
3683 visibility of all frames. Direct changes to our own
3684 windows get handled by WM_SIZE. */
3686 if (msg
.msg
.lParam
!= 0)
3687 check_visibility
= 1;
3690 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3691 f
->async_visible
= msg
.msg
.wParam
;
3695 check_visibility
= 1;
3699 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3701 /* Inform lisp of whether frame has been iconified etc. */
3704 switch (msg
.msg
.wParam
)
3706 case SIZE_MINIMIZED
:
3707 f
->async_visible
= 0;
3708 f
->async_iconified
= 1;
3710 bufp
->kind
= iconify_event
;
3711 XSETFRAME (bufp
->frame_or_window
, f
);
3717 case SIZE_MAXIMIZED
:
3719 f
->async_visible
= 1;
3720 f
->async_iconified
= 0;
3722 /* wait_reading_process_input will notice this and update
3723 the frame's display structures. */
3724 SET_FRAME_GARBAGED (f
);
3730 /* Reset top and left positions of the Window
3731 here since Windows sends a WM_MOVE message
3732 BEFORE telling us the Window is minimized
3733 when the Window is iconified, with 3000,3000
3735 x_real_positions (f
, &x
, &y
);
3736 f
->output_data
.w32
->left_pos
= x
;
3737 f
->output_data
.w32
->top_pos
= y
;
3739 bufp
->kind
= deiconify_event
;
3740 XSETFRAME (bufp
->frame_or_window
, f
);
3746 /* Force a redisplay sooner or later
3747 to update the frame titles
3748 in case this is the second frame. */
3749 record_asynch_buffer_change ();
3754 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3762 GetClientRect(msg
.msg
.hwnd
, &rect
);
3764 height
= rect
.bottom
- rect
.top
;
3765 width
= rect
.right
- rect
.left
;
3767 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3768 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3770 /* TODO: Clip size to the screen dimensions. */
3772 /* Even if the number of character rows and columns has
3773 not changed, the font size may have changed, so we need
3774 to check the pixel dimensions as well. */
3776 if (columns
!= f
->width
3777 || rows
!= f
->height
3778 || width
!= f
->output_data
.w32
->pixel_width
3779 || height
!= f
->output_data
.w32
->pixel_height
)
3781 /* I had set this to 0, 0 - I am not sure why?? */
3783 change_frame_size (f
, rows
, columns
, 0, 1);
3784 SET_FRAME_GARBAGED (f
);
3785 cancel_mouse_face (f
);
3786 f
->output_data
.w32
->pixel_width
= width
;
3787 f
->output_data
.w32
->pixel_height
= height
;
3788 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3792 check_visibility
= 1;
3797 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3799 if (msg
.msg
.message
== WM_SETFOCUS
)
3801 x_new_focus_frame (dpyinfo
, f
);
3803 else if (f
== dpyinfo
->w32_focus_frame
)
3805 x_new_focus_frame (dpyinfo
, 0);
3807 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3808 clear_mouse_face (dpyinfo
);
3811 dpyinfo
->grabbed
= 0;
3812 check_visibility
= 1;
3816 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3823 bufp
->kind
= delete_window_event
;
3824 XSETFRAME (bufp
->frame_or_window
, f
);
3832 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3839 bufp
->kind
= menu_bar_activate_event
;
3840 XSETFRAME (bufp
->frame_or_window
, f
);
3848 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3852 extern void menubar_selection_callback
3853 (FRAME_PTR f
, void * client_data
);
3854 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3857 check_visibility
= 1;
3860 case WM_DISPLAYCHANGE
:
3861 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3865 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3866 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3867 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3868 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3872 check_visibility
= 1;
3876 /* Check for messages registered at runtime. */
3877 if (msg
.msg
.message
== msh_mousewheel
)
3879 if (dpyinfo
->grabbed
&& last_mouse_frame
3880 && FRAME_LIVE_P (last_mouse_frame
))
3881 f
= last_mouse_frame
;
3883 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3887 if ((!dpyinfo
->w32_focus_frame
3888 || f
== dpyinfo
->w32_focus_frame
)
3891 construct_mouse_wheel (bufp
, &msg
, f
);
3902 /* If the focus was just given to an autoraising frame,
3904 /* ??? This ought to be able to handle more than one such frame. */
3905 if (pending_autoraise_frame
)
3907 x_raise_frame (pending_autoraise_frame
);
3908 pending_autoraise_frame
= 0;
3911 /* Check which frames are still visisble, if we have enqueued any user
3912 events or been notified of events that may affect visibility. We
3913 do this here because there doesn't seem to be any direct
3914 notification from Windows that the visibility of a window has
3915 changed (at least, not in all cases). */
3916 if (count
> 0 || check_visibility
)
3918 Lisp_Object tail
, frame
;
3920 FOR_EACH_FRAME (tail
, frame
)
3922 FRAME_PTR f
= XFRAME (frame
);
3923 /* Check "visible" frames and mark each as obscured or not.
3924 Note that async_visible is nonzero for unobscured and
3925 obscured frames, but zero for hidden and iconified frames. */
3926 if (FRAME_W32_P (f
) && f
->async_visible
)
3929 HDC hdc
= get_frame_dc (f
);
3930 GetClipBox (hdc
, &clipbox
);
3931 release_frame_dc (f
, hdc
);
3933 if (clipbox
.right
== clipbox
.left
3934 || clipbox
.bottom
== clipbox
.top
)
3936 /* Frame has become completely obscured so mark as
3937 such (we do this by setting async_visible to 2 so
3938 that FRAME_VISIBLE_P is still true, but redisplay
3940 f
->async_visible
= 2;
3942 if (!FRAME_OBSCURED_P (f
))
3944 DebPrint (("frame %04x (%s) obscured\n", f
,
3945 XSTRING (f
->name
)->data
));
3950 /* Frame is not obscured, so mark it as such. */
3951 f
->async_visible
= 1;
3953 if (FRAME_OBSCURED_P (f
))
3955 SET_FRAME_GARBAGED (f
);
3956 DebPrint (("frame %04x (%s) reexposed\n", f
,
3957 XSTRING (f
->name
)->data
));
3959 /* Force a redisplay sooner or later. */
3960 record_asynch_buffer_change ();
3971 /* Drawing the cursor. */
3974 /* Draw a hollow box cursor. Don't change the inside of the box. */
3984 hdc
= get_frame_dc (f
);
3986 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3988 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3989 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3990 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3991 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3993 FrameRect (hdc
, &rect
, hb
);
3996 release_frame_dc (f
, hdc
);
3999 /* Clear the cursor of frame F to background color,
4000 and mark the cursor as not shown.
4001 This is used when the text where the cursor is
4002 is about to be rewritten. */
4008 if (! FRAME_VISIBLE_P (f
)
4009 || !f
->phys_cursor_on
)
4012 x_display_cursor (f
, 0);
4013 f
->phys_cursor_on
= 0;
4016 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4017 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4021 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4028 CHAR_TO_PIXEL_COL (f
, column
),
4029 CHAR_TO_PIXEL_ROW (f
, row
),
4030 &glyph
, 1, highlight
, 0, NULL
);
4034 x_display_bar_cursor (f
, on
)
4038 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4040 /* This is pointless on invisible frames, and dangerous on garbaged
4041 frames; in the latter case, the frame may be in the midst of
4042 changing its size, and curs_x and curs_y may be off the frame. */
4043 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4046 if (! on
&& ! f
->phys_cursor_on
)
4049 /* If there is anything wrong with the current cursor state, remove it. */
4050 if (f
->phys_cursor_on
4052 || f
->phys_cursor_x
!= curs_x
4053 || f
->phys_cursor_y
!= curs_y
4054 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
4056 /* Erase the cursor by redrawing the character underneath it. */
4057 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4058 f
->phys_cursor_glyph
,
4059 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4060 f
->phys_cursor_on
= 0;
4063 /* If we now need a cursor in the new place or in the new form, do it so. */
4065 && (! f
->phys_cursor_on
4066 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4068 f
->phys_cursor_glyph
4069 = ((current_glyphs
->enable
[curs_y
]
4070 && curs_x
< current_glyphs
->used
[curs_y
])
4071 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4073 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4074 CHAR_TO_PIXEL_COL (f
, curs_x
),
4075 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4076 max (f
->output_data
.w32
->cursor_width
, 1),
4077 f
->output_data
.w32
->line_height
);
4079 f
->phys_cursor_x
= curs_x
;
4080 f
->phys_cursor_y
= curs_y
;
4081 f
->phys_cursor_on
= 1;
4083 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4088 /* Turn the displayed cursor of frame F on or off according to ON.
4089 If ON is nonzero, where to put the cursor is specified
4090 by F->cursor_x and F->cursor_y. */
4093 x_display_box_cursor (f
, on
)
4097 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4099 /* This is pointless on invisible frames, and dangerous on garbaged
4100 frames; in the latter case, the frame may be in the midst of
4101 changing its size, and curs_x and curs_y may be off the frame. */
4102 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4105 /* If cursor is off and we want it off, return quickly. */
4106 if (!on
&& ! f
->phys_cursor_on
)
4109 /* If cursor is currently being shown and we don't want it to be
4110 or it is in the wrong place,
4111 or we want a hollow box and it's not so, (pout!)
4113 if (f
->phys_cursor_on
4115 || f
->phys_cursor_x
!= curs_x
4116 || f
->phys_cursor_y
!= curs_y
4117 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4118 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4120 int mouse_face_here
= 0;
4121 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4123 /* If the cursor is in the mouse face area, redisplay that when
4124 we clear the cursor. */
4125 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4126 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4127 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4128 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4129 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4130 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4131 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4132 /* Don't redraw the cursor's spot in mouse face
4133 if it is at the end of a line (on a newline).
4134 The cursor appears there, but mouse highlighting does not. */
4135 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4136 mouse_face_here
= 1;
4138 /* If the font is not as tall as a whole line,
4139 we must explicitly clear the line's whole height. */
4140 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4141 w32_clear_area (f
, NULL
,
4142 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4143 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4144 FONT_WIDTH (f
->output_data
.w32
->font
),
4145 f
->output_data
.w32
->line_height
);
4146 /* Erase the cursor by redrawing the character underneath it. */
4147 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4148 f
->phys_cursor_glyph
,
4151 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4152 f
->phys_cursor_on
= 0;
4155 /* If we want to show a cursor,
4156 or we want a box cursor and it's not so,
4157 write it in the right place. */
4159 && (! f
->phys_cursor_on
4160 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4161 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4163 f
->phys_cursor_glyph
4164 = ((current_glyphs
->enable
[curs_y
]
4165 && curs_x
< current_glyphs
->used
[curs_y
])
4166 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4168 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4171 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4175 x_draw_single_glyph (f
, curs_y
, curs_x
,
4176 f
->phys_cursor_glyph
, 2);
4177 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4180 f
->phys_cursor_x
= curs_x
;
4181 f
->phys_cursor_y
= curs_y
;
4182 f
->phys_cursor_on
= 1;
4186 /* Display the cursor on frame F, or clear it, according to ON.
4187 Use the position specified by curs_x and curs_y
4188 if we are doing an update of frame F now.
4189 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4192 x_display_cursor (f
, on
)
4198 /* If we're not updating, then we want to use the current frame's
4199 cursor position, not our local idea of where the cursor ought to be. */
4200 if (f
!= updating_frame
)
4202 curs_x
= FRAME_CURSOR_X (f
);
4203 curs_y
= FRAME_CURSOR_Y (f
);
4206 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4207 x_display_box_cursor (f
, on
);
4208 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4209 x_display_bar_cursor (f
, on
);
4211 /* Those are the only two we have implemented! */
4220 x_bitmap_icon (f
, icon
)
4224 int mask
, bitmap_id
;
4228 if (FRAME_W32_WINDOW (f
) == 0)
4232 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4233 else if (STRINGP (icon
))
4234 hicon
= LoadImage (NULL
, (LPCTSTR
) XSTRING (icon
)->data
, IMAGE_ICON
, 0, 0,
4235 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4236 else if (SYMBOLP (icon
))
4240 if (EQ (icon
, intern ("application")))
4241 name
= (LPCTSTR
) IDI_APPLICATION
;
4242 else if (EQ (icon
, intern ("hand")))
4243 name
= (LPCTSTR
) IDI_HAND
;
4244 else if (EQ (icon
, intern ("question")))
4245 name
= (LPCTSTR
) IDI_QUESTION
;
4246 else if (EQ (icon
, intern ("exclamation")))
4247 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4248 else if (EQ (icon
, intern ("asterisk")))
4249 name
= (LPCTSTR
) IDI_ASTERISK
;
4250 else if (EQ (icon
, intern ("winlogo")))
4251 name
= (LPCTSTR
) IDI_WINLOGO
;
4255 hicon
= LoadIcon (NULL
, name
);
4263 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
, (LPARAM
) hicon
);
4269 /* Changing the font of the frame. */
4271 /* Give frame F the font named FONTNAME as its default font, and
4272 return the full name of that font. FONTNAME may be a wildcard
4273 pattern; in that case, we choose some font that fits the pattern.
4274 The return value shows which font we chose. */
4277 x_new_font (f
, fontname
)
4279 register char *fontname
;
4281 struct font_info
*fontp
4282 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4288 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4289 f
->output_data
.w32
->font_baseline
4290 = FONT_BASE (FRAME_FONT (f
)) + fontp
->baseline_offset
;
4291 FRAME_FONTSET (f
) = -1;
4293 /* Compute the scroll bar width in character columns. */
4294 if (f
->scroll_bar_pixel_width
> 0)
4296 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4297 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4300 f
->scroll_bar_cols
= 2;
4302 /* Now make the frame display the given font. */
4303 if (FRAME_W32_WINDOW (f
) != 0)
4305 frame_update_line_height (f
);
4306 x_set_window_size (f
, 0, f
->width
, f
->height
);
4309 /* If we are setting a new frame's font for the first time,
4310 there are no faces yet, so this font's height is the line height. */
4311 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4314 Lisp_Object lispy_name
;
4316 lispy_name
= build_string (fontname
);
4322 /* Give frame F the fontset named FONTSETNAME as its default font, and
4323 return the full name of that fontset. FONTSETNAME may be a wildcard
4324 pattern; in that case, we choose some fontset that fits the pattern.
4325 The return value shows which fontset we chose. */
4328 x_new_fontset (f
, fontsetname
)
4332 int fontset
= fs_query_fontset (f
, fontsetname
);
4333 struct fontset_info
*fontsetp
;
4339 if (FRAME_FONTSET (f
) == fontset
)
4340 /* This fontset is already set in frame F. There's nothing more
4342 return build_string (fontsetname
);
4344 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4346 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4347 /* This fontset doesn't contain ASCII font. */
4350 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4352 if (!STRINGP (result
))
4353 /* Can't load ASCII font. */
4356 /* Since x_new_font doesn't update any fontset information, do it now. */
4357 FRAME_FONTSET(f
) = fontset
;
4358 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4359 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4361 return build_string (fontsetname
);
4364 /* Calculate the absolute position in frame F
4365 from its current recorded position values and gravity. */
4367 x_calc_absolute_position (f
)
4372 int flags
= f
->output_data
.w32
->size_hint_flags
;
4376 /* Find the position of the outside upper-left corner of
4377 the inner window, with respect to the outer window. */
4378 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4381 MapWindowPoints (FRAME_W32_WINDOW (f
),
4382 f
->output_data
.w32
->parent_desc
,
4389 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4392 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4393 FRAME_EXTERNAL_MENU_BAR (f
));
4396 pt
.x
+= (rt
.right
- rt
.left
);
4397 pt
.y
+= (rt
.bottom
- rt
.top
);
4400 /* Treat negative positions as relative to the leftmost bottommost
4401 position that fits on the screen. */
4402 if (flags
& XNegative
)
4403 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4404 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4406 + f
->output_data
.w32
->left_pos
);
4408 if (flags
& YNegative
)
4409 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4410 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4412 + f
->output_data
.w32
->top_pos
);
4413 /* The left_pos and top_pos
4414 are now relative to the top and left screen edges,
4415 so the flags should correspond. */
4416 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4419 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4420 to really change the position, and 0 when calling from
4421 x_make_frame_visible (in that case, XOFF and YOFF are the current
4422 position values). It is -1 when calling from x_set_frame_parameters,
4423 which means, do adjust for borders but don't change the gravity. */
4425 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4427 register int xoff
, yoff
;
4430 int modified_top
, modified_left
;
4432 if (change_gravity
> 0)
4434 f
->output_data
.w32
->top_pos
= yoff
;
4435 f
->output_data
.w32
->left_pos
= xoff
;
4436 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4438 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4440 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4441 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4443 x_calc_absolute_position (f
);
4446 x_wm_set_size_hint (f
, (long) 0, 0);
4448 /* It is a mystery why we need to add the border_width here
4449 when the frame is already visible, but experiment says we do. */
4450 modified_left
= f
->output_data
.w32
->left_pos
;
4451 modified_top
= f
->output_data
.w32
->top_pos
;
4453 /* Do not add in border widths under W32. */
4454 if (change_gravity
!= 0)
4456 modified_left
+= f
->output_data
.w32
->border_width
;
4457 modified_top
+= f
->output_data
.w32
->border_width
;
4461 my_set_window_pos (FRAME_W32_WINDOW (f
),
4463 modified_left
, modified_top
,
4465 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4469 /* Call this to change the size of frame F's x-window.
4470 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4471 for this size change and subsequent size changes.
4472 Otherwise we leave the window gravity unchanged. */
4474 x_set_window_size (f
, change_gravity
, cols
, rows
)
4479 int pixelwidth
, pixelheight
;
4480 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4484 check_frame_size (f
, &rows
, &cols
);
4485 f
->output_data
.w32
->vertical_scroll_bar_extra
4486 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4488 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4489 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4490 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4491 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4492 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4494 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4495 x_wm_set_size_hint (f
, (long) 0, 0);
4500 rect
.left
= rect
.top
= 0;
4501 rect
.right
= pixelwidth
;
4502 rect
.bottom
= pixelheight
;
4504 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4505 FRAME_EXTERNAL_MENU_BAR (f
));
4507 my_set_window_pos (FRAME_W32_WINDOW (f
),
4510 rect
.right
- rect
.left
,
4511 rect
.bottom
- rect
.top
,
4512 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4515 /* Now, strictly speaking, we can't be sure that this is accurate,
4516 but the window manager will get around to dealing with the size
4517 change request eventually, and we'll hear how it went when the
4518 ConfigureNotify event gets here.
4520 We could just not bother storing any of this information here,
4521 and let the ConfigureNotify event set everything up, but that
4522 might be kind of confusing to the lisp code, since size changes
4523 wouldn't be reported in the frame parameters until some random
4524 point in the future when the ConfigureNotify event arrives. */
4525 change_frame_size (f
, rows
, cols
, 0, 0);
4526 PIXEL_WIDTH (f
) = pixelwidth
;
4527 PIXEL_HEIGHT (f
) = pixelheight
;
4529 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4530 receive in the ConfigureNotify event; if we get what we asked
4531 for, then the event won't cause the screen to become garbaged, so
4532 we have to make sure to do it here. */
4533 SET_FRAME_GARBAGED (f
);
4535 /* If cursor was outside the new size, mark it as off. */
4536 if (f
->phys_cursor_y
>= rows
4537 || f
->phys_cursor_x
>= cols
)
4539 f
->phys_cursor_x
= 0;
4540 f
->phys_cursor_y
= 0;
4541 f
->phys_cursor_on
= 0;
4544 /* Clear out any recollection of where the mouse highlighting was,
4545 since it might be in a place that's outside the new frame size.
4546 Actually checking whether it is outside is a pain in the neck,
4547 so don't try--just let the highlighting be done afresh with new size. */
4548 cancel_mouse_face (f
);
4553 /* Mouse warping. */
4556 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4565 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4566 pt
.x
= rect
.left
+ pix_x
;
4567 pt
.y
= rect
.top
+ pix_y
;
4568 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4570 SetCursorPos (pt
.x
, pt
.y
);
4576 x_set_mouse_position (f
, x
, y
)
4582 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4583 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4585 if (pix_x
< 0) pix_x
= 0;
4586 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4588 if (pix_y
< 0) pix_y
= 0;
4589 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4591 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4594 /* focus shifting, raising and lowering. */
4596 x_focus_on_frame (f
)
4599 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4601 /* Give input focus to frame. */
4604 /* Try not to change its Z-order if possible. */
4605 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4606 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4609 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4618 /* Raise frame F. */
4625 /* Strictly speaking, raise-frame should only change the frame's Z
4626 order, leaving input focus unchanged. This is reasonable behaviour
4627 on X where the usual policy is point-to-focus. However, this
4628 behaviour would be very odd on Windows where the usual policy is
4631 On X, if the mouse happens to be over the raised frame, it gets
4632 input focus anyway (so the window with focus will never be
4633 completely obscured) - if not, then just moving the mouse over it
4634 is sufficient to give it focus. On Windows, the user must actually
4635 click on the frame (preferrably the title bar so as not to move
4636 point), which is more awkward. Also, no other Windows program
4637 raises a window to the top but leaves another window (possibly now
4638 completely obscured) with input focus.
4640 Because there is a system setting on Windows that allows the user
4641 to choose the point to focus policy, we make the strict semantics
4642 optional, but by default we grab focus when raising. */
4644 if (NILP (Vw32_grab_focus_on_raise
))
4646 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4647 not already the foreground application: the frame is raised
4648 above all other frames belonging to us, but not above the
4649 current top window. To achieve that, we have to resort to this
4650 more cumbersome method. */
4652 HDWP handle
= BeginDeferWindowPos (2);
4655 DeferWindowPos (handle
,
4656 FRAME_W32_WINDOW (f
),
4659 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4661 DeferWindowPos (handle
,
4662 GetForegroundWindow (),
4663 FRAME_W32_WINDOW (f
),
4665 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4667 EndDeferWindowPos (handle
);
4672 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4678 /* Lower frame F. */
4684 my_set_window_pos (FRAME_W32_WINDOW (f
),
4687 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4692 w32_frame_raise_lower (f
, raise
)
4702 /* Change of visibility. */
4704 /* This tries to wait until the frame is really visible.
4705 However, if the window manager asks the user where to position
4706 the frame, this will return before the user finishes doing that.
4707 The frame will not actually be visible at that time,
4708 but it will become visible later when the window manager
4709 finishes with it. */
4711 x_make_frame_visible (f
)
4718 type
= x_icon_type (f
);
4720 x_bitmap_icon (f
, type
);
4722 if (! FRAME_VISIBLE_P (f
))
4724 /* We test FRAME_GARBAGED_P here to make sure we don't
4725 call x_set_offset a second time
4726 if we get to x_make_frame_visible a second time
4727 before the window gets really visible. */
4728 if (! FRAME_ICONIFIED_P (f
)
4729 && ! f
->output_data
.w32
->asked_for_visible
)
4730 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4732 f
->output_data
.w32
->asked_for_visible
= 1;
4734 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4735 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4738 /* Synchronize to ensure Emacs knows the frame is visible
4739 before we do anything else. We do this loop with input not blocked
4740 so that incoming events are handled. */
4743 int count
= input_signal_count
;
4745 /* This must come after we set COUNT. */
4748 XSETFRAME (frame
, f
);
4752 /* Once we have handled input events,
4753 we should have received the MapNotify if one is coming.
4754 So if we have not got it yet, stop looping.
4755 Some window managers make their own decisions
4756 about visibility. */
4757 if (input_signal_count
!= count
)
4759 /* Machines that do polling rather than SIGIO have been observed
4760 to go into a busy-wait here. So we'll fake an alarm signal
4761 to let the handler know that there's something to be read.
4762 We used to raise a real alarm, but it seems that the handler
4763 isn't always enabled here. This is probably a bug. */
4764 if (input_polling_used ())
4766 /* It could be confusing if a real alarm arrives while processing
4767 the fake one. Turn it off and let the handler reset it. */
4769 input_poll_signal (0);
4771 /* Once we have handled input events,
4772 we should have received the MapNotify if one is coming.
4773 So if we have not got it yet, stop looping.
4774 Some window managers make their own decisions
4775 about visibility. */
4776 if (input_signal_count
!= count
)
4779 FRAME_SAMPLE_VISIBILITY (f
);
4783 /* Change from mapped state to withdrawn state. */
4785 /* Make the frame visible (mapped and not iconified). */
4787 x_make_frame_invisible (f
)
4792 /* Don't keep the highlight on an invisible frame. */
4793 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4794 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4798 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4800 /* We can't distinguish this from iconification
4801 just by the event that we get from the server.
4802 So we can't win using the usual strategy of letting
4803 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4804 and synchronize with the server to make sure we agree. */
4806 FRAME_ICONIFIED_P (f
) = 0;
4807 f
->async_visible
= 0;
4808 f
->async_iconified
= 0;
4813 /* Change window state from mapped to iconified. */
4822 /* Don't keep the highlight on an invisible frame. */
4823 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4824 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4826 if (f
->async_iconified
)
4831 type
= x_icon_type (f
);
4833 x_bitmap_icon (f
, type
);
4835 /* Simulate the user minimizing the frame. */
4836 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4841 /* Destroy the window of frame F. */
4843 x_destroy_window (f
)
4846 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4850 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4851 free_frame_menubar (f
);
4852 free_frame_faces (f
);
4854 xfree (f
->output_data
.w32
);
4855 f
->output_data
.w32
= 0;
4856 if (f
== dpyinfo
->w32_focus_frame
)
4857 dpyinfo
->w32_focus_frame
= 0;
4858 if (f
== dpyinfo
->w32_focus_event_frame
)
4859 dpyinfo
->w32_focus_event_frame
= 0;
4860 if (f
== dpyinfo
->w32_highlight_frame
)
4861 dpyinfo
->w32_highlight_frame
= 0;
4863 dpyinfo
->reference_count
--;
4865 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4867 dpyinfo
->mouse_face_beg_row
4868 = dpyinfo
->mouse_face_beg_col
= -1;
4869 dpyinfo
->mouse_face_end_row
4870 = dpyinfo
->mouse_face_end_col
= -1;
4871 dpyinfo
->mouse_face_window
= Qnil
;
4877 /* Setting window manager hints. */
4879 /* Set the normal size hints for the window manager, for frame F.
4880 FLAGS is the flags word to use--or 0 meaning preserve the flags
4881 that the window now has.
4882 If USER_POSITION is nonzero, we set the USPosition
4883 flag (this is useful when FLAGS is 0). */
4885 x_wm_set_size_hint (f
, flags
, user_position
)
4890 Window window
= FRAME_W32_WINDOW (f
);
4892 flexlines
= f
->height
;
4896 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4897 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4898 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4899 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4904 /* Window manager things */
4905 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4910 Window window
= FRAME_W32_WINDOW (f
);
4912 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4913 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4914 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4916 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4921 /* Initialization. */
4923 #ifdef USE_X_TOOLKIT
4924 static XrmOptionDescRec emacs_options
[] = {
4925 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4926 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4928 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4929 XrmoptionSepArg
, NULL
},
4930 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4932 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4933 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4934 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4935 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4936 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4937 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4938 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4940 #endif /* USE_X_TOOLKIT */
4942 static int w32_initialized
= 0;
4944 struct w32_display_info
*
4945 w32_term_init (display_name
, xrm_option
, resource_name
)
4946 Lisp_Object display_name
;
4948 char *resource_name
;
4952 struct w32_display_info
*dpyinfo
;
4957 if (!w32_initialized
)
4960 w32_initialized
= 1;
4971 argv
[argc
++] = "-xrm";
4972 argv
[argc
++] = xrm_option
;
4976 dpyinfo
= &one_w32_display_info
;
4978 /* Put this display on the chain. */
4979 dpyinfo
->next
= NULL
;
4981 /* Put it on w32_display_name_list as well, to keep them parallel. */
4982 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4983 w32_display_name_list
);
4984 dpyinfo
->name_list_element
= XCAR (w32_display_name_list
);
4986 dpyinfo
->w32_id_name
4987 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4988 + XSTRING (Vsystem_name
)->size
4990 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4991 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4994 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4995 resource_name
, EMACS_CLASS
);
4997 /* Put the rdb where we can find it in a way that works on
4999 dpyinfo
->xrdb
= xrdb
;
5001 hdc
= GetDC (GetDesktopWindow ());
5003 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
5004 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
5005 dpyinfo
->root_window
= GetDesktopWindow ();
5006 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
5007 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
5008 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
5009 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
5010 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
5011 dpyinfo
->grabbed
= 0;
5012 dpyinfo
->reference_count
= 0;
5013 dpyinfo
->n_fonts
= 0;
5014 dpyinfo
->font_table_size
= 0;
5015 dpyinfo
->bitmaps
= 0;
5016 dpyinfo
->bitmaps_size
= 0;
5017 dpyinfo
->bitmaps_last
= 0;
5018 dpyinfo
->mouse_face_mouse_frame
= 0;
5019 dpyinfo
->mouse_face_deferred_gc
= 0;
5020 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
5021 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
5022 dpyinfo
->mouse_face_face_id
= 0;
5023 dpyinfo
->mouse_face_window
= Qnil
;
5024 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
5025 dpyinfo
->mouse_face_defer
= 0;
5026 dpyinfo
->w32_focus_frame
= 0;
5027 dpyinfo
->w32_focus_event_frame
= 0;
5028 dpyinfo
->w32_highlight_frame
= 0;
5030 ReleaseDC (GetDesktopWindow (), hdc
);
5032 /* Determine if there is a middle mouse button, to allow parse_button
5033 to decide whether right mouse events should be mouse-2 or
5035 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
5037 /* initialise palette with white and black */
5040 defined_color (0, "white", &color
, 1);
5041 defined_color (0, "black", &color
, 1);
5044 #ifndef F_SETOWN_BUG
5046 #ifdef F_SETOWN_SOCK_NEG
5047 /* stdin is a socket here */
5048 fcntl (connection
, F_SETOWN
, -getpid ());
5049 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5050 fcntl (connection
, F_SETOWN
, getpid ());
5051 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5052 #endif /* ! defined (F_SETOWN) */
5053 #endif /* F_SETOWN_BUG */
5056 if (interrupt_input
)
5057 init_sigio (connection
);
5058 #endif /* ! defined (SIGIO) */
5065 /* Get rid of display DPYINFO, assuming all frames are already gone. */
5068 x_delete_display (dpyinfo
)
5069 struct w32_display_info
*dpyinfo
;
5071 /* Discard this display from w32_display_name_list and w32_display_list.
5072 We can't use Fdelq because that can quit. */
5073 if (! NILP (w32_display_name_list
)
5074 && EQ (XCAR (w32_display_name_list
), dpyinfo
->name_list_element
))
5075 w32_display_name_list
= XCDR (w32_display_name_list
);
5080 tail
= w32_display_name_list
;
5081 while (CONSP (tail
) && CONSP (XCDR (tail
)))
5083 if (EQ (XCAR (XCDR (tail
)),
5084 dpyinfo
->name_list_element
))
5086 XCDR (tail
) = XCDR (XCDR (tail
));
5093 /* free palette table */
5095 struct w32_palette_entry
* plist
;
5097 plist
= dpyinfo
->color_list
;
5100 struct w32_palette_entry
* pentry
= plist
;
5101 plist
= plist
->next
;
5104 dpyinfo
->color_list
= NULL
;
5105 if (dpyinfo
->palette
)
5106 DeleteObject(dpyinfo
->palette
);
5108 xfree (dpyinfo
->font_table
);
5109 xfree (dpyinfo
->w32_id_name
);
5112 /* Set up use of W32. */
5114 DWORD
w32_msg_worker ();
5118 /* MSVC does not type K&R functions with no arguments correctly, and
5119 so we must explicitly cast them. */
5120 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
5121 clear_end_of_line_hook
= w32_clear_end_of_line
;
5122 ins_del_lines_hook
= w32_ins_del_lines
;
5123 change_line_highlight_hook
= w32_change_line_highlight
;
5124 insert_glyphs_hook
= w32_insert_glyphs
;
5125 write_glyphs_hook
= w32_write_glyphs
;
5126 delete_glyphs_hook
= w32_delete_glyphs
;
5127 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5128 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5129 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5130 update_begin_hook
= w32_update_begin
;
5131 update_end_hook
= w32_update_end
;
5132 set_terminal_window_hook
= w32_set_terminal_window
;
5133 read_socket_hook
= w32_read_socket
;
5134 frame_up_to_date_hook
= w32_frame_up_to_date
;
5135 cursor_to_hook
= w32_cursor_to
;
5136 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5137 mouse_position_hook
= w32_mouse_position
;
5138 frame_rehighlight_hook
= w32_frame_rehighlight
;
5139 frame_raise_lower_hook
= w32_frame_raise_lower
;
5140 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5141 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5142 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5143 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5145 scroll_region_ok
= 1; /* we'll scroll partial frames */
5146 char_ins_del_ok
= 0; /* just as fast to write the line */
5147 line_ins_del_ok
= 1; /* we'll just blt 'em */
5148 fast_clear_end_of_line
= 1; /* X does this well */
5149 memory_below_frame
= 0; /* we don't remember what scrolls
5153 /* Initialize input mode: interrupt_input off, no flow control, allow
5154 8 bit character input, standard quit char. */
5155 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5157 /* Create the window thread - it will terminate itself or when the app terminates */
5161 dwMainThreadId
= GetCurrentThreadId ();
5162 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5163 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5165 /* Wait for thread to start */
5170 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5172 hWindowsThread
= CreateThread (NULL
, 0,
5173 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5174 0, 0, &dwWindowsThreadId
);
5176 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5179 /* It is desirable that mainThread should have the same notion of
5180 focus window and active window as windowsThread. Unfortunately, the
5181 following call to AttachThreadInput, which should do precisely what
5182 we need, causes major problems when Emacs is linked as a console
5183 program. Unfortunately, we have good reasons for doing that, so
5184 instead we need to send messages to windowsThread to make some API
5185 calls for us (ones that affect, or depend on, the active/focus
5187 #ifdef ATTACH_THREADS
5188 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5191 /* Dynamically link to optional system components. */
5193 HANDLE user_lib
= LoadLibrary ("user32.dll");
5195 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5197 /* New proportional scroll bar functions. */
5198 LOAD_PROC( SetScrollInfo
);
5199 LOAD_PROC( GetScrollInfo
);
5203 FreeLibrary (user_lib
);
5205 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5206 otherwise use the fixed height. */
5207 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5208 GetSystemMetrics (SM_CYVTHUMB
);
5210 /* For either kind of scroll bar, take account of the arrows; these
5211 effectively form the border of the main scroll bar range. */
5212 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5213 = GetSystemMetrics (SM_CYVSCROLL
);
5220 Lisp_Object codepage
;
5222 staticpro (&w32_display_name_list
);
5223 w32_display_name_list
= Qnil
;
5225 staticpro (&last_mouse_scroll_bar
);
5226 last_mouse_scroll_bar
= Qnil
;
5228 staticpro (&Qvendor_specific_keysyms
);
5229 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5231 DEFVAR_INT ("w32-num-mouse-buttons",
5232 &Vw32_num_mouse_buttons
,
5233 "Number of physical mouse buttons.");
5234 Vw32_num_mouse_buttons
= Qnil
;
5236 DEFVAR_LISP ("w32-swap-mouse-buttons",
5237 &Vw32_swap_mouse_buttons
,
5238 "Swap the mapping of middle and right mouse buttons.\n\
5239 When nil, middle button is mouse-2 and right button is mouse-3.");
5240 Vw32_swap_mouse_buttons
= Qnil
;
5242 DEFVAR_LISP ("w32-grab-focus-on-raise",
5243 &Vw32_grab_focus_on_raise
,
5244 "Raised frame grabs input focus.\n\
5245 When t, `raise-frame' grabs input focus as well. This fits well\n\
5246 with the normal Windows click-to-focus policy, but might not be\n\
5247 desirable when using a point-to-focus policy.");
5248 Vw32_grab_focus_on_raise
= Qt
;
5250 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5251 &Vw32_capslock_is_shiftlock
,
5252 "Apply CapsLock state to non character input keys.\n\
5253 When nil, CapsLock only affects normal character input keys.");
5254 Vw32_capslock_is_shiftlock
= Qnil
;
5256 DEFVAR_LISP ("w32-recognize-altgr",
5257 &Vw32_recognize_altgr
,
5258 "Recognize right-alt and left-ctrl as AltGr.\n\
5259 When nil, the right-alt and left-ctrl key combination is\n\
5260 interpreted normally.");
5261 Vw32_recognize_altgr
= Qt
;
5263 DEFVAR_BOOL ("w32-enable-unicode-output",
5264 &w32_enable_unicode_output
,
5265 "Enable the use of Unicode for text output if non-nil.\n\
5266 Unicode output may prevent some third party applications for displaying\n\
5267 Far-East Languages on Windows 95/98 from working properly.\n\
5268 NT uses Unicode internally anyway, so this flag will probably have no\n\
5269 affect on NT machines.");
5270 w32_enable_unicode_output
= 1;
5272 DEFVAR_LISP ("w32-charset-to-codepage-alist",
5273 &Vw32_charset_to_codepage_alist
,
5274 "Alist linking character sets to Windows Codepages.");
5275 Vw32_charset_to_codepage_alist
= Qnil
;
5276 /* Initialise the alist with some defaults. */
5277 XSETFASTINT (codepage
, 936);
5278 store_in_alist (&Vw32_charset_to_codepage_alist
,
5279 build_string ("gb2312"), codepage
);
5280 XSETFASTINT (codepage
, 950);
5281 store_in_alist (&Vw32_charset_to_codepage_alist
,
5282 build_string ("big5"), codepage
);
5283 XSETFASTINT (codepage
, 949);
5284 store_in_alist (&Vw32_charset_to_codepage_alist
,
5285 build_string ("ksc5601.1987"), codepage
);
5286 XSETFASTINT (codepage
, 1361);
5287 store_in_alist (&Vw32_charset_to_codepage_alist
,
5288 build_string ("ksc5601.1992"), codepage
);
5289 XSETFASTINT (codepage
, 932);
5290 store_in_alist (&Vw32_charset_to_codepage_alist
,
5291 build_string ("jisx0208-sjis"), codepage
);
5292 XSETFASTINT (codepage
, 874);
5293 store_in_alist (&Vw32_charset_to_codepage_alist
,
5294 build_string ("tis620"), codepage
);
5295 XSETFASTINT (codepage
, 20866);
5296 store_in_alist (&Vw32_charset_to_codepage_alist
,
5297 build_string ("koi8-r"), codepage
);
5298 /* iso8859-13 is not yet officially adopted, but it is conveniently
5299 covered by CP 1257. */
5300 XSETFASTINT (codepage
, 1257);
5301 store_in_alist (&Vw32_charset_to_codepage_alist
,
5302 build_string ("iso8859-13"), codepage
);
5303 XSETFASTINT (codepage
, 1254);
5304 store_in_alist (&Vw32_charset_to_codepage_alist
,
5305 build_string ("iso8859-9"), codepage
);
5306 XSETFASTINT (codepage
, 1255);
5307 store_in_alist (&Vw32_charset_to_codepage_alist
,
5308 build_string ("iso8859-8"), codepage
);
5309 XSETFASTINT (codepage
, 28597);
5310 store_in_alist (&Vw32_charset_to_codepage_alist
,
5311 build_string ("iso8859-7"), codepage
);
5312 XSETFASTINT (codepage
, 28596);
5313 store_in_alist (&Vw32_charset_to_codepage_alist
,
5314 build_string ("iso8859-6"), codepage
);
5315 XSETFASTINT (codepage
, 28595);
5316 store_in_alist (&Vw32_charset_to_codepage_alist
,
5317 build_string ("iso8859-5"), codepage
);
5318 XSETFASTINT (codepage
, 28594);
5319 store_in_alist (&Vw32_charset_to_codepage_alist
,
5320 build_string ("iso8859-4"), codepage
);
5321 XSETFASTINT (codepage
, 28593);
5322 store_in_alist (&Vw32_charset_to_codepage_alist
,
5323 build_string ("iso8859-3"), codepage
);
5324 XSETFASTINT (codepage
, 28592);
5325 store_in_alist (&Vw32_charset_to_codepage_alist
,
5326 build_string ("iso8859-2"), codepage
);
5327 XSETFASTINT (codepage
, 1252);
5328 store_in_alist (&Vw32_charset_to_codepage_alist
,
5329 build_string ("iso8859-1"), codepage
);