1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 #include "blockinput.h"
42 #include "dispextern.h"
43 #include "termhooks.h"
51 #include "intervals.h"
56 #define min(x, y) (((x) < (y)) ? (x) : (y))
57 #define max(x, y) (((x) > (y)) ? (x) : (y))
59 #define CP_DEFAULT 1004
61 extern unsigned int msh_mousewheel
;
63 extern void free_frame_menubar ();
65 extern Lisp_Object Vwindow_system
;
67 #define x_any_window_to_frame x_window_to_frame
68 #define x_top_window_to_frame x_window_to_frame
71 /* This is display since w32 does not support multiple ones. */
72 struct w32_display_info one_w32_display_info
;
74 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
75 one for each element of w32_display_list and in the same order.
76 NAME is the name of the frame.
77 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
78 Lisp_Object w32_display_name_list
;
80 /* Frame being updated by update_frame. This is declared in term.c.
81 This is set by update_begin and looked at by all the
82 w32 functions. It is zero while not inside an update.
83 In that case, the w32 functions assume that `selected_frame'
84 is the frame to apply to. */
85 extern struct frame
*updating_frame
;
87 /* This is a frame waiting to be autoraised, within w32_read_socket. */
88 struct frame
*pending_autoraise_frame
;
90 /* During an update, maximum vpos for ins/del line operations to affect. */
94 /* During an update, nonzero if chars output now should be highlighted. */
98 /* Nominal cursor position -- where to draw output.
99 During an update, these are different from the cursor-box position. */
104 /* Flag to enable Unicode output in case users wish to use programs
105 like Twinbridge on '95 rather than installed system level support
106 for Far East languages. */
107 int w32_enable_unicode_output
;
109 DWORD dwWindowsThreadId
= 0;
110 HANDLE hWindowsThread
= NULL
;
111 DWORD dwMainThreadId
= 0;
112 HANDLE hMainThread
= NULL
;
115 /* These definitions are new with Windows 95. */
116 #define SIF_RANGE 0x0001
117 #define SIF_PAGE 0x0002
118 #define SIF_POS 0x0004
119 #define SIF_DISABLENOSCROLL 0x0008
120 #define SIF_TRACKPOS 0x0010
121 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
123 typedef struct tagSCROLLINFO
132 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
133 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
136 /* Dynamic linking to new proportional scroll bar functions. */
137 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
138 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
140 int vertical_scroll_bar_min_handle
;
141 int vertical_scroll_bar_top_border
;
142 int vertical_scroll_bar_bottom_border
;
144 int last_scroll_bar_drag_pos
;
146 /* Mouse movement. */
148 /* Where the mouse was last time we reported a mouse event. */
149 static FRAME_PTR last_mouse_frame
;
150 static RECT last_mouse_glyph
;
152 Lisp_Object Vw32_num_mouse_buttons
;
154 Lisp_Object Vw32_swap_mouse_buttons
;
156 /* Control whether x_raise_frame also sets input focus. */
157 Lisp_Object Vw32_grab_focus_on_raise
;
159 /* Control whether Caps Lock affects non-ascii characters. */
160 Lisp_Object Vw32_capslock_is_shiftlock
;
162 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
163 Lisp_Object Vw32_recognize_altgr
;
165 /* The scroll bar in which the last motion event occurred.
167 If the last motion event occurred in a scroll bar, we set this
168 so w32_mouse_position can know whether to report a scroll bar motion or
171 If the last motion event didn't occur in a scroll bar, we set this
172 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
173 Lisp_Object last_mouse_scroll_bar
;
174 int last_mouse_scroll_bar_pos
;
176 /* This is a hack. We would really prefer that w32_mouse_position would
177 return the time associated with the position it returns, but there
178 doesn't seem to be any way to wrest the timestamp from the server
179 along with the position query. So, we just keep track of the time
180 of the last movement we received, and return that in hopes that
181 it's somewhat accurate. */
182 Time last_mouse_movement_time
;
184 /* Associative list linking character set strings to Windows codepages. */
185 Lisp_Object Vw32_charset_to_codepage_alist
;
187 /* Incremented by w32_read_socket whenever it really tries to read events. */
189 static int volatile input_signal_count
;
191 static int input_signal_count
;
194 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
196 extern Lisp_Object Qface
, Qmouse_face
;
200 /* A mask of extra modifier bits to put into every keyboard char. */
201 extern int extra_keyboard_modifiers
;
203 static Lisp_Object Qvendor_specific_keysyms
;
205 void w32_delete_display ();
207 static void redraw_previous_char ();
208 static void redraw_following_char ();
209 static unsigned int w32_get_modifiers ();
211 static int fast_find_position ();
212 static void note_mouse_highlight ();
213 static void clear_mouse_face ();
214 static void show_mouse_face ();
215 static void do_line_dance ();
217 /* Forward declarations for term hooks. Consistency with the rest of Emacs
218 requires the use of K&R functions prototypes. However, MSVC does not
219 pick up the function prototypes correctly with K&R function definitions,
220 and so we declare them first to give a little help to MSVC. */
221 static void w32_clear_frame ();
222 static void w32_clear_end_of_line (int);
223 static void w32_ins_del_lines (int, int);
224 static void w32_change_line_highlight (int, int, int);
225 static void w32_insert_glyphs (GLYPH
*, int);
226 static void w32_write_glyphs (GLYPH
*, int);
227 static void w32_delete_glyphs (int);
228 static void w32_ring_bell ();
229 static void w32_reset_terminal_modes ();
230 static void w32_set_terminal_modes ();
231 static void w32_update_begin (FRAME_PTR
);
232 static void w32_update_end (FRAME_PTR
);
233 static void w32_set_terminal_window (int);
234 extern int w32_read_socket (int, struct input_event
*, int, int);
235 static void w32_frame_up_to_date (FRAME_PTR
);
236 static void w32_cursor_to (int, int);
237 static void w32_reassert_line_highlight (int, int);
238 static void w32_mouse_position (FRAME_PTR
*, int, Lisp_Object
*,
239 enum scroll_bar_part
*, Lisp_Object
*,
240 Lisp_Object
*, unsigned long *);
241 static void w32_frame_rehighlight (FRAME_PTR
);
242 static void w32_frame_raise_lower (FRAME_PTR
, int);
243 static void w32_set_vertical_scroll_bar (struct window
*, int, int, int);
244 static void w32_condemn_scroll_bars (FRAME_PTR
);
245 static void w32_redeem_scroll_bar (struct window
*);
246 static void w32_judge_scroll_bars (FRAME_PTR
);
249 /* This is a function useful for recording debugging information
250 about the sequence of occurrences in this file. */
258 struct record event_record
[100];
260 int event_record_index
;
262 record_event (locus
, type
)
266 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
267 event_record_index
= 0;
269 event_record
[event_record_index
].locus
= locus
;
270 event_record
[event_record_index
].type
= type
;
271 event_record_index
++;
276 /* Return the struct w32_display_info. */
278 struct w32_display_info
*
279 w32_display_info_for_display ()
281 return (&one_w32_display_info
);
285 w32_fill_rect (f
, _hdc
, pix
, lprect
)
300 hdc
= get_frame_dc (f
);
303 hb
= CreateSolidBrush (pix
);
304 FillRect (hdc
, lprect
, hb
);
308 release_frame_dc (f
, hdc
);
317 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
318 w32_clear_rect (f
, NULL
, &rect
);
322 /* Starting and ending updates.
324 These hooks are called by update_frame at the beginning and end
325 of a frame update. We record in `updating_frame' the identity
326 of the frame being updated, so that the w32_... functions do not
327 need to take a frame as argument. Most of the w32_... functions
328 should never be called except during an update, the only exceptions
329 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
338 flexlines
= f
->height
;
343 /* Regenerate display palette before drawing if list of requested
344 colors has changed. */
345 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
347 w32_regenerate_palette (f
);
348 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
351 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
353 /* Don't do highlighting for mouse motion during the update. */
354 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
356 /* If the frame needs to be redrawn,
357 simply forget about any prior mouse highlighting. */
358 if (FRAME_GARBAGED_P (f
))
359 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
361 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
363 int firstline
, lastline
, i
;
364 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
366 /* Find the first, and the last+1, lines affected by redisplay. */
367 for (firstline
= 0; firstline
< f
->height
; firstline
++)
368 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
371 lastline
= f
->height
;
372 for (i
= f
->height
- 1; i
>= 0; i
--)
374 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
380 /* Can we tell that this update does not affect the window
381 where the mouse highlight is? If so, no need to turn off.
382 Likewise, don't do anything if the frame is garbaged;
383 in that case, the FRAME_CURRENT_GLYPHS that we would use
384 are all wrong, and we will redisplay that line anyway. */
385 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
386 || lastline
< XFASTINT (w
->top
)))
387 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
401 x_display_cursor (f
, 1);
403 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
404 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
409 /* This is called after a redisplay on frame F. */
412 w32_frame_up_to_date (f
)
416 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
417 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
419 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
420 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
421 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
422 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
427 /* External interface to control of standout mode.
428 Call this when about to modify line at position VPOS
429 and not change whether it is highlighted. */
432 w32_reassert_line_highlight (new, vpos
)
438 /* Call this when about to modify line at position VPOS
439 and change whether it is highlighted. */
442 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
443 int new_highlight
, vpos
, first_unused_hpos
;
445 highlight
= new_highlight
;
446 w32_cursor_to (vpos
, 0);
447 w32_clear_end_of_line (updating_frame
->width
);
450 /* This is used when starting Emacs and when restarting after suspend.
451 When starting Emacs, no window is mapped. And nothing must be done
452 to Emacs's own window if it is suspended (though that rarely happens). */
455 w32_set_terminal_modes (void)
459 /* This is called when exiting or suspending Emacs.
460 Exiting will make the W32 windows go away, and suspending
461 requires no action. */
464 w32_reset_terminal_modes (void)
468 /* Set the nominal cursor position of the frame.
469 This is where display update commands will take effect.
470 This does not affect the place where the cursor-box is displayed. */
473 w32_cursor_to (row
, col
)
474 register int row
, col
;
481 if (updating_frame
== 0)
484 x_display_cursor (selected_frame
, 1);
489 /* Get the Windows codepage corresponding to the specified font. The
490 charset info in the font name is used to look up
491 w32-charset-to-codepage-alist. */
493 w32_codepage_for_font (char *fontname
)
495 Lisp_Object codepage
;
496 char charset_str
[20], *charset
, *end
;
498 /* Extract charset part of font string. */
499 if (sscanf (fontname
,
500 "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
504 /* Remove leading "*-". */
505 if (strncmp ("*-", charset_str
, 2) == 0)
506 charset
= charset_str
+ 2;
508 charset
= charset_str
;
510 /* Stop match at wildcard (including preceding '-'). */
511 if (end
= strchr (charset
, '*'))
513 if (end
> charset
&& *(end
-1) == '-')
518 codepage
= Fcdr (Fassoc (build_string(charset
),
519 Vw32_charset_to_codepage_alist
));
521 if (INTEGERP (codepage
))
522 return XINT (codepage
);
528 w32_use_unicode_for_codepage (codepage
)
530 /* If the current codepage is supported, use Unicode for output. */
531 return (w32_enable_unicode_output
532 && codepage
!= CP_DEFAULT
&& IsValidCodePage (codepage
));
535 /* Dealing with bits of wchar_t as if they were an XChar2B. */
536 #define BUILD_WCHAR_T(byte1, byte2) \
537 ((wchar_t)(((byte1 & 0x00ff) << 8) | (byte2 & 0x00ff)))
546 #define W32_TEXTOUT(start_offset,nchars) \
548 int charset_dim = CHARSET_DIMENSION(charset); \
550 w32_BDF_TextOut (font->bdf, hdc, left + xoffset, \
552 x_1byte_buffer + start_offset, \
553 charset_dim, nchars, 0); \
554 else if (print_via_unicode) \
555 ExtTextOutW (hdc, left + xoffset, top + yoffset, \
556 fuOptions, clip_region, \
557 x_2byte_buffer + start_offset, nchars, NULL); \
559 ExtTextOut (hdc, left + xoffset, top + yoffset, \
560 fuOptions, clip_region, \
561 x_1byte_buffer + start_offset, \
562 nchars * charset_dim, NULL); \
563 start_offset += nchars * (print_via_unicode ? 1 : charset_dim ); \
564 xoffset += nchars * glyph_width; \
567 /* Display a sequence of N glyphs found at GP.
568 WINDOW is the window to output to. LEFT and TOP are starting coords.
569 HL is 1 if this text is highlighted, 2 if the cursor is on it,
570 3 if should appear in its mouse-face.
571 JUST_FOREGROUND if 1 means draw only the foreground;
572 don't alter the background.
574 FONT is the default font to use (for glyphs whose font-code is 0).
576 Since the display generation code is responsible for calling
577 compute_char_face and compute_glyph_face on everything it puts in
578 the display structure, we can assume that the face code on each
579 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
580 to which we can actually apply intern_face.
581 Call this function with input blocked. */
584 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
587 register GLYPH
*gp
; /* Points to first GLYPH. */
588 register int n
; /* Number of glyphs to display. */
591 struct cmpchar_info
*cmpcharp
;
593 wchar_t *x_2byte_buffer
594 = (wchar_t *) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_2byte_buffer
));
595 register wchar_t *cp
; /* Steps through x_2byte_buffer[]. */
597 /* Allocate double the window width, as this buffer may contain MBCS
598 characters under w32. Unsigned to let GetCharABCWidths work. */
599 unsigned char *x_1byte_buffer
600 = (unsigned char *) alloca (2 * FRAME_WINDOW_WIDTH (f
)
601 * sizeof (*x_1byte_buffer
));
602 register unsigned char *bp
; /* Steps through x_1byte_buffer[]. */
603 register int tlen
= GLYPH_TABLE_LENGTH
;
604 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
605 Window window
= FRAME_W32_WINDOW (f
);
606 HDC hdc
= get_frame_dc (f
);
607 int orig_left
= left
;
613 /* Get the face-code of the next GLYPH. */
614 int cf
, len
, n_chars
;
617 Lisp_Object first_ch
;
618 /* HIGHEST and LOWEST are used while drawing a composite
619 character. The meanings are described later. */
622 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
623 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
624 ch
= FAST_GLYPH_CHAR (g
);
625 if (unibyte_display_via_language_environment
626 && SINGLE_BYTE_CHAR_P (ch
)
628 ch
= unibyte_char_to_multibyte (ch
);
629 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
630 charset
= CHAR_CHARSET (ch
);
631 if (charset
== CHARSET_COMPOSITION
)
633 /* We must draw components of the composite character on the
635 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
637 /* Set the face in the slot for work. */
638 cmpcharp
->face_work
= cf
;
640 /* We don't need the return value ... */
641 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
642 hl
, just_foreground
, cmpcharp
);
643 /* ... because the width of just drawn text can be
644 calculated as follows. */
645 left
+= FONT_WIDTH (FRAME_FONT (f
)) * cmpcharp
->width
;
648 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
653 /* Find the run of consecutive glyphs which can be drawn with
654 the same DC (i.e. the same charset and the same face-code).
655 Extract their character codes into X_2BYTE_BUFFER.
656 If CMPCHARP is not NULL, face-code is not checked because we
657 use only the face specified in `cmpcharp->face_work'. */
661 int this_charset
, c1
, c2
;
664 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
665 ch
= FAST_GLYPH_CHAR (g
);
666 if (unibyte_display_via_language_environment
667 && SINGLE_BYTE_CHAR_P (ch
)
669 ch
= unibyte_char_to_multibyte (ch
);
670 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
671 if (this_charset
!= charset
672 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
676 *cp
= BUILD_WCHAR_T (c1
, c2
);
678 *cp
= BUILD_WCHAR_T (0, c1
);
681 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
685 /* LEN gets the length of the run. */
686 len
= cp
- x_2byte_buffer
;
687 /* Now output this run of chars, with the font and pixel values
688 determined by the face code CF. */
690 struct face
*face
= FRAME_DEFAULT_FACE (f
);
691 XFontStruct
*font
= NULL
;
693 struct font_info
*fontp
;
698 int line_height
= FRAME_LINE_HEIGHT (f
);
699 /* Pixel width of each glyph in this run. */
701 = (FONT_WIDTH (FRAME_FONT (f
))
702 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
703 /* Overall pixel width of this run. */
705 = (FONT_WIDTH (FRAME_FONT (f
))
706 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
707 /* A flag to tell if we have already filled background. We
708 fill background in advance in the following cases:
709 1) A face has stipple.
710 2) A height of font is shorter than LINE_HEIGHT.
711 3) Drawing a composite character.
712 4) Font has non-zero _MULE_BASELINE_OFFSET property.
713 5) Font is a bdf font.
714 6) Font is italic (italic fonts falsely report their height).
715 After filling background, we draw glyphs by XDrawString16. */
716 int background_filled
;
717 /* Baseline position of a character, offset from TOP. */
719 /* The property value of `_MULE_RELATIVE_COMPOSE' and
720 `_MULE_DEFAULT_ASCENT'. */
721 int relative_compose
= 0, default_ascent
= 0;
722 /* 1 if we find no font or a font of inappropriate size. */
723 int require_clipping
;
725 LPRECT clip_region
= NULL
;
728 int codepage
= CP_DEFAULT
;
729 BOOL print_via_unicode
= FALSE
;
731 /* HL = 3 means use a mouse face previously chosen. */
733 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
735 /* First look at the face of the text itself. */
738 /* It's possible for the display table to specify
739 a face code that is out of range. Use 0 in that case. */
740 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
741 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
745 face
= FRAME_MODE_LINE_FACE (f
);
747 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
748 if (FACE_STIPPLE (face
))
752 /* Then comes the distinction between modeline and normal text. */
757 face
= FRAME_MODE_LINE_FACE (f
);
758 if (FACE_STIPPLE (face
))
762 /* Setting appropriate font and codepage for this charset. */
763 if (charset
!= CHARSET_ASCII
)
765 fontset
= FACE_FONTSET (face
);
767 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
768 || !(fontp
= FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
769 charset
, NULL
, fontset
)))
772 font
= (XFontStruct
*) (fontp
->font
);
773 codepage
= w32_codepage_for_font (fontp
->name
);
775 if ( font
&& !font
->bdf
)
776 print_via_unicode
= w32_use_unicode_for_codepage (codepage
);
778 baseline
= FONT_BASE (font
) + fontp
->baseline_offset
;
780 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
782 relative_compose
= fontp
->relative_compose
;
783 default_ascent
= fontp
->default_ascent
;
786 /* We have to change code points in the following cases. */
787 if (fontp
->font_encoder
)
789 /* This font requires CCL program to calculate code
790 point of characters. */
791 struct ccl_program
*ccl
= fontp
->font_encoder
;
793 if (CHARSET_DIMENSION (charset
) == 1)
794 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
796 ccl
->reg
[0] = charset
;
797 ccl
->reg
[1] = BYTE2 (*cp
);
798 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
799 /* We assume that MSBs are appropriately
800 set/reset by CCL program. */
801 #if 0 /* this probably works under NT, but not under 95. */
802 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
803 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
805 *cp
= BUILD_WCHAR_T (ccl
->reg
[1], ccl
->reg
[2]);
806 #else /* Assume single dimensional charsets stay so. */
807 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
811 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
813 ccl
->reg
[0] = charset
;
814 ccl
->reg
[1] = BYTE1 (*cp
) , ccl
->reg
[2] = BYTE2 (*cp
);
815 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
816 /* We assume that MSBs are appropriately
817 set/reset by CCL program. */
818 #if 0 /* this probably works under NT, but not under 95. */
819 if (font
->tm
.tmLastChar
< 256) /* 1-byte font */
820 *cp
= BUILD_WCHAR_T (0, ccl
->reg
[1]);
822 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
823 #else /* Assume multidimensional charsets stay so. */
824 *cp
= BUILD_WCHAR_T (ccl
->reg
[1],ccl
->reg
[2]);
828 else if (fontp
->encoding
[charset
])
830 int enc
= fontp
->encoding
[charset
];
832 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
833 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
834 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
) | 0x80, BYTE2 (*cp
));
835 if (enc
== 1 || enc
== 3)
836 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
837 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
), BYTE2 (*cp
) | 0x80);
838 /* Special encoding for SJIS Kanji. */
841 if (CHARSET_DIMENSION (charset
) == 2)
844 for (cp
= x_2byte_buffer
;
845 cp
< x_2byte_buffer
+ len
; cp
++)
847 ENCODE_SJIS (BYTE1 (*cp
), BYTE2 (*cp
),
849 *cp
= BUILD_WCHAR_T (sjis1
, sjis2
);
853 for (cp
= x_2byte_buffer
;
854 cp
< x_2byte_buffer
+ len
; cp
++)
855 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
863 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
865 font
= FACE_FONT (face
);
866 if (!font
|| font
== (XFontStruct
*) FACE_DEFAULT
)
867 font
= FRAME_FONT (f
);
868 baseline
= FONT_BASE (FRAME_FONT (f
));
869 if (charset
== charset_latin_iso8859_1
)
871 if (!font
->bdf
&& font
->tm
.tmLastChar
< 0x80)
872 /* This font can't display Latin1 characters. */
876 for (cp
= x_2byte_buffer
;
877 cp
< x_2byte_buffer
+ len
; cp
++)
878 *cp
= BUILD_WCHAR_T (BYTE1 (*cp
),
885 fg
= face
->foreground
;
886 bg
= face
->background
;
888 /* Now override that if the cursor's on this character. */
891 /* The cursor overrides stippling. */
894 if (font
== FRAME_FONT (f
)
895 && face
->background
== FRAME_BACKGROUND_PIXEL (f
)
896 && face
->foreground
== FRAME_FOREGROUND_PIXEL (f
)
899 bg
= f
->output_data
.w32
->cursor_pixel
;
900 fg
= face
->background
;
902 /* Cursor on non-default face: must merge. */
905 bg
= f
->output_data
.w32
->cursor_pixel
;
906 fg
= face
->background
;
907 /* If the glyph would be invisible,
908 try a different foreground. */
910 fg
= face
->foreground
;
912 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
914 fg
= face
->foreground
;
915 /* Make sure the cursor is distinct from text in this face. */
916 if (bg
== face
->background
917 && fg
== face
->foreground
)
919 bg
= face
->foreground
;
920 fg
= face
->background
;
926 require_clipping
= (!NILP (Vclip_large_size_font
)
928 ? (font
->bdf
->ury
> baseline
929 || font
->bdf
->lly
> line_height
- baseline
)
930 : (font
->tm
.tmAscent
> baseline
931 || font
->tm
.tmDescent
> line_height
- baseline
))
932 || (!cmpcharp
&& FONT_MAX_WIDTH (font
) > glyph_width
)));
934 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
935 background_filled
= 1;
937 /* Stippling not supported under w32. */
941 || FONT_HEIGHT (font
) < line_height
942 || FONT_WIDTH (font
) < glyph_width
943 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
)
947 /* Fill in the background for the current run. */
948 w32_fill_area (f
, hdc
, bg
,
953 background_filled
= 1;
955 /* To assure not to fill background while drawing
956 remaining components. */
960 background_filled
= 0;
962 SetBkMode (hdc
, background_filled
? TRANSPARENT
: OPAQUE
);
963 SetTextColor (hdc
, fg
);
964 SetBkColor (hdc
, bg
);
965 SetTextAlign (hdc
, TA_BASELINE
| TA_LEFT
);
967 /* On NT, where conversion to Unicode has to happen sometime
968 when using the normal ExtTextOut facility, we might as well
969 take advantage of x_2byte_buffer which is already allocated,
970 to avoid the allocation overhead for implicit conversion. */
972 if (!print_via_unicode
973 && codepage
== CP_DEFAULT
974 && w32_enable_unicode_output
975 && os_subtype
== OS_NT
976 && font
&& !font
->bdf
)
978 print_via_unicode
= TRUE
;
981 /* Note that we can special-case the conversion to Unicode when
982 the charset is CHARSET_ASCII (an important case) or Latin-1,
983 because x_2byte_buffer in fact already contains the unicode
984 characters. So avoid setting up x_1byte_buffer in that case. */
985 if (!print_via_unicode
986 || (charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
))
988 /* Convert x_2byte_buffer into a buffer of single byte
989 characters - possibly containing MBCS runs. */
991 for (i
= 0; i
< len
; i
++)
993 if (BYTE1 (*(x_2byte_buffer
+ i
)))
994 *bp
++ = BYTE1 (*(x_2byte_buffer
+ i
));
995 *bp
++ = BYTE2 (*(x_2byte_buffer
+ i
));
997 n_chars
= bp
- x_1byte_buffer
;
1002 if (print_via_unicode
1003 && charset
!= CHARSET_ASCII
&& charset
!= charset_latin_iso8859_1
)
1005 i
= MultiByteToWideChar
1006 (codepage
, 0, x_1byte_buffer
, n_chars
,
1007 x_2byte_buffer
, FRAME_WINDOW_WIDTH (f
));
1009 /* Make sure we don't display nothing if conversion fails. */
1011 print_via_unicode
= FALSE
;
1019 SelectObject (hdc
, font
->hfont
);
1023 int xoffset
= 0, yoffset
= baseline
;
1024 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
1025 || FONT_MAX_WIDTH (font
) != FONT_WIDTH (font
))
1027 /* The incrementing of i in this loop is done
1028 inside the W32_CHAROUT macro. */
1029 for (i
= 0; i
< n_chars
; )
1031 if (require_clipping
)
1033 /* Set up a clipping rectangle for ExtTextOut */
1034 fuOptions
|= ETO_CLIPPED
;
1035 clip_rectangle
.left
= left
+ i
* glyph_width
;
1036 clip_rectangle
.right
1037 = left
+ (i
+ 1) * glyph_width
;
1038 clip_rectangle
.top
= top
;
1039 clip_rectangle
.bottom
= top
+ line_height
;
1040 clip_region
= &clip_rectangle
;
1048 W32_TEXTOUT (i
, n_chars
);
1053 /* Handle composite characters. */
1054 RECT clip_rectangle
;
1055 LPRECT clip_region
= NULL
;
1060 if (require_clipping
)
1062 /* Set up a clipping rectangle for ExtTextOut */
1063 fuOptions
|= ETO_CLIPPED
;
1064 clip_rectangle
.left
= left
;
1065 clip_rectangle
.right
= left
+ glyph_width
;
1066 clip_rectangle
.top
= top
;
1067 clip_rectangle
.bottom
= top
+ line_height
;
1068 clip_region
= &clip_rectangle
;
1070 if ((cmpcharp
->cmp_rule
|| relative_compose
)
1073 /* This is the first character. Initialize variables.
1074 HIGHEST is the highest position of glyphs ever
1075 written, LOWEST the lowest position. */
1077 int yoffset
= baseline
;
1081 && CHAR_TABLE_P (Vuse_default_ascent
)
1082 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
1084 highest
= default_ascent
;
1087 /* TODO: per char metrics for Truetype and BDF
1090 highest
= FONT_BASE (font
) + 1;
1091 lowest
= - (FONT_HEIGHT (font
) - FONT_BASE (font
));
1094 if (cmpcharp
->cmp_rule
)
1095 xoffset
= (int)(cmpcharp
->col_offset
[0]
1096 * FONT_WIDTH (FRAME_FONT (f
)));
1100 /* Truetype fonts often contain underhangs to
1101 handle composition characters. This works
1102 against our attempts to position the characters
1103 manually, so we need to compensate for this.
1105 if (print_via_unicode
?
1106 GetCharABCWidthsW (hdc
, *x_2byte_buffer
,
1109 : GetCharABCWidths (hdc
, *x_1byte_buffer
,
1113 char_width
= char_placement
.abcA
1114 + char_placement
.abcB
+ char_placement
.abcC
;
1115 xoffset
+= FONT_WIDTH (font
) - char_width
;
1117 /* Don't let characters go beyond the glyph
1118 boundary whatever their over/underhangs. */
1119 if (xoffset
> glyph_width
- char_width
)
1120 xoffset
= glyph_width
- char_width
;
1125 /* Draw the first character at the normal
1127 W32_TEXTOUT (start
, 1);
1133 for (; i
< n_chars
; gidx
++)
1135 int xoffset
= 0, yoffset
= FONT_BASE (font
);
1137 if (relative_compose
)
1139 /* No per char metrics on w32. */
1140 if (NILP (Vignore_relative_composition
)
1141 || NILP (Faref (Vignore_relative_composition
,
1142 make_number (cmpcharp
->glyph
[gidx
]))))
1144 if (- (FONT_HEIGHT (font
) - FONT_BASE (font
))
1145 >= relative_compose
)
1147 /* Draw above the current glyphs. */
1148 yoffset
= highest
+ FONT_HEIGHT (font
);
1149 highest
+= FONT_HEIGHT (font
);
1151 else if (FONT_BASE (font
) <= 0)
1153 /* Draw beneath the current glyphs. */
1155 lowest
-= FONT_HEIGHT (font
);
1160 /* Draw the glyph at normal position. If
1161 it sticks out of HIGHEST or LOWEST,
1162 update them appropriately. */
1163 if (FONT_BASE (font
) > highest
)
1164 highest
= FONT_BASE (font
);
1165 else if (- (FONT_HEIGHT (font
) - FONT_BASE (font
))
1167 lowest
= - (FONT_HEIGHT (font
) -
1171 else if (cmpcharp
->cmp_rule
)
1173 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1174 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1177 /* Re-encode GREF and NREF so that they specify
1178 only Y-axis information:
1179 0:top, 1:base, 2:bottom, 3:center */
1180 gref
= gref
/ 3 + (gref
== 4) * 2;
1181 nref
= nref
/ 3 + (nref
== 4) * 2;
1183 /* No per char metrics on w32. */
1184 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1185 : gref
== 2 ? lowest
1186 : (highest
+ lowest
) / 2)
1187 - (nref
== 0 ? FONT_HEIGHT (font
)
1188 : nref
== 1 ? (FONT_HEIGHT (font
) -
1191 : (FONT_HEIGHT (font
) / 2)));
1192 top
= bottom
+ FONT_HEIGHT (font
);
1196 if (bottom
< lowest
)
1198 yoffset
= bottom
+ FONT_HEIGHT (font
);
1199 xoffset
= (int)(cmpcharp
->col_offset
[gidx
]
1200 * FONT_WIDTH (FRAME_FONT(f
)));
1203 /* Truetype fonts often contain underhangs to
1204 handle composition characters. This works
1205 against our attempts to position the characters
1206 manually, so we need to compensate for this.
1208 if (print_via_unicode
?
1209 GetCharABCWidthsW (hdc
, *(x_2byte_buffer
+ i
),
1210 *(x_2byte_buffer
+ i
),
1212 : GetCharABCWidths (hdc
, *(x_1byte_buffer
+ i
),
1213 *(x_1byte_buffer
+ i
),
1216 char_width
= char_placement
.abcA
1217 + char_placement
.abcB
+ char_placement
.abcC
;
1218 xoffset
+= FONT_WIDTH (font
) - char_width
;
1220 /* Don't let characters go beyond the glyph
1221 boundary whatever their over/underhangs. */
1222 if (xoffset
> glyph_width
- char_width
)
1223 xoffset
= glyph_width
- char_width
;
1234 /* Show rectangles to indicate that we found no font. */
1235 int limit
= cmpcharp
? 1 : len
;
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
])
1685 CHAR_TO_PIXEL_COL (f
, left
),
1686 CHAR_TO_PIXEL_ROW (f
, y
),
1687 line
, min (cols
, active_frame
->used
[y
] - left
),
1688 active_frame
->highlight
[y
], 0, NULL
);
1691 /* Turn the cursor on if we turned it off. */
1694 x_display_cursor (f
, 1);
1701 x_display_cursor (f
, 1);
1705 frame_unhighlight (f
)
1708 x_display_cursor (f
, 1);
1711 static void x_frame_rehighlight ();
1713 /* The focus has changed. Update the frames as necessary to reflect
1714 the new situation. Note that we can't change the selected frame
1715 here, because the Lisp code we are interrupting might become confused.
1716 Each event gets marked with the frame in which it occurred, so the
1717 Lisp code can tell when the switch took place by examining the events. */
1720 x_new_focus_frame (dpyinfo
, frame
)
1721 struct w32_display_info
*dpyinfo
;
1722 struct frame
*frame
;
1724 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1725 int events_enqueued
= 0;
1727 if (frame
!= dpyinfo
->w32_focus_frame
)
1729 /* Set this before calling other routines, so that they see
1730 the correct value of w32_focus_frame. */
1731 dpyinfo
->w32_focus_frame
= frame
;
1733 if (old_focus
&& old_focus
->auto_lower
)
1734 x_lower_frame (old_focus
);
1736 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1737 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1739 pending_autoraise_frame
= 0;
1742 x_frame_rehighlight (dpyinfo
);
1745 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1748 x_mouse_leave (dpyinfo
)
1749 struct w32_display_info
*dpyinfo
;
1751 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1754 /* The focus has changed, or we have redirected a frame's focus to
1755 another frame (this happens when a frame uses a surrogate
1756 minibuffer frame). Shift the highlight as appropriate.
1758 The FRAME argument doesn't necessarily have anything to do with which
1759 frame is being highlighted or unhighlighted; we only use it to find
1760 the appropriate display info. */
1762 w32_frame_rehighlight (frame
)
1763 struct frame
*frame
;
1765 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1769 x_frame_rehighlight (dpyinfo
)
1770 struct w32_display_info
*dpyinfo
;
1772 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1774 if (dpyinfo
->w32_focus_frame
)
1776 dpyinfo
->w32_highlight_frame
1777 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1778 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1779 : dpyinfo
->w32_focus_frame
);
1780 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1782 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1783 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1787 dpyinfo
->w32_highlight_frame
= 0;
1789 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1792 frame_unhighlight (old_highlight
);
1793 if (dpyinfo
->w32_highlight_frame
)
1794 frame_highlight (dpyinfo
->w32_highlight_frame
);
1798 /* Keyboard processing - modifier keys, etc. */
1800 /* Convert a keysym to its name. */
1803 x_get_keysym_name (keysym
)
1806 /* Make static so we can always return it */
1807 static char value
[100];
1810 GetKeyNameText(keysym
, value
, 100);
1816 /* Mouse clicks and mouse movement. Rah. */
1818 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1819 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1820 that the glyph at X, Y occupies, if BOUNDS != 0.
1821 If NOCLIP is nonzero, do not force the value into range. */
1824 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1826 register int pix_x
, pix_y
;
1827 register int *x
, *y
;
1831 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1832 if (NILP (Vwindow_system
))
1839 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1840 even for negative values. */
1842 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1844 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1846 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1847 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1851 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1852 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1853 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1854 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1861 else if (pix_x
> f
->width
)
1866 else if (pix_y
> f
->height
)
1875 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1878 register int *pix_x
, *pix_y
;
1880 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1881 if (NILP (Vwindow_system
))
1888 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1889 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1893 parse_button (message
, pbutton
, pup
)
1903 case WM_LBUTTONDOWN
:
1911 case WM_MBUTTONDOWN
:
1912 if (NILP (Vw32_swap_mouse_buttons
))
1919 if (NILP (Vw32_swap_mouse_buttons
))
1925 case WM_RBUTTONDOWN
:
1926 if (NILP (Vw32_swap_mouse_buttons
))
1933 if (NILP (Vw32_swap_mouse_buttons
))
1944 if (pbutton
) *pbutton
= button
;
1950 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1952 If the event is a button press, then note that we have grabbed
1956 construct_mouse_click (result
, msg
, f
)
1957 struct input_event
*result
;
1964 parse_button (msg
->msg
.message
, &button
, &up
);
1966 /* Make the event type no_event; we'll change that when we decide
1968 result
->kind
= mouse_click
;
1969 result
->code
= button
;
1970 result
->timestamp
= msg
->msg
.time
;
1971 result
->modifiers
= (msg
->dwModifiers
1979 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1980 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1981 XSETFRAME (result
->frame_or_window
, f
);
1986 construct_mouse_wheel (result
, msg
, f
)
1987 struct input_event
*result
;
1992 result
->kind
= mouse_wheel
;
1993 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1994 result
->timestamp
= msg
->msg
.time
;
1995 result
->modifiers
= msg
->dwModifiers
;
1996 p
.x
= LOWORD (msg
->msg
.lParam
);
1997 p
.y
= HIWORD (msg
->msg
.lParam
);
1998 ScreenToClient(msg
->msg
.hwnd
, &p
);
1999 XSETINT (result
->x
, p
.x
);
2000 XSETINT (result
->y
, p
.y
);
2001 XSETFRAME (result
->frame_or_window
, f
);
2005 construct_drag_n_drop (result
, msg
, f
)
2006 struct input_event
*result
;
2018 result
->kind
= drag_n_drop
;
2020 result
->timestamp
= msg
->msg
.time
;
2021 result
->modifiers
= msg
->dwModifiers
;
2023 hdrop
= (HDROP
) msg
->msg
.wParam
;
2024 DragQueryPoint (hdrop
, &p
);
2027 p
.x
= LOWORD (msg
->msg
.lParam
);
2028 p
.y
= HIWORD (msg
->msg
.lParam
);
2029 ScreenToClient (msg
->msg
.hwnd
, &p
);
2032 XSETINT (result
->x
, p
.x
);
2033 XSETINT (result
->y
, p
.y
);
2035 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
2038 for (i
= 0; i
< num_files
; i
++)
2040 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
2043 name
= alloca (len
+ 1);
2044 DragQueryFile (hdrop
, i
, name
, len
+ 1);
2045 files
= Fcons (build_string (name
), files
);
2050 XSETFRAME (frame
, f
);
2051 result
->frame_or_window
= Fcons (frame
, files
);
2055 /* Function to report a mouse movement to the mainstream Emacs code.
2056 The input handler calls this.
2058 We have received a mouse movement event, which is given in *event.
2059 If the mouse is over a different glyph than it was last time, tell
2060 the mainstream emacs code by setting mouse_moved. If not, ask for
2061 another motion event, so we can check again the next time it moves. */
2064 note_mouse_movement (frame
, msg
)
2068 last_mouse_movement_time
= msg
->time
;
2070 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
2072 frame
->mouse_moved
= 1;
2073 last_mouse_scroll_bar
= Qnil
;
2075 note_mouse_highlight (frame
, -1, -1);
2078 /* Has the mouse moved off the glyph it was on at the last sighting? */
2079 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
2080 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
2081 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
2082 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
2084 frame
->mouse_moved
= 1;
2085 last_mouse_scroll_bar
= Qnil
;
2087 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
2091 /* This is used for debugging, to turn off note_mouse_highlight. */
2092 static int disable_mouse_highlight
;
2094 /* Take proper action when the mouse has moved to position X, Y on frame F
2095 as regards highlighting characters that have mouse-face properties.
2096 Also dehighlighting chars where the mouse was before.
2097 X and Y can be negative or out of range. */
2100 note_mouse_highlight (f
, x
, y
)
2104 int row
, column
, portion
;
2109 if (disable_mouse_highlight
)
2112 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2113 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2114 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2116 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
2121 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2125 /* Find out which glyph the mouse is on. */
2126 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2127 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
2129 /* Which window is that in? */
2130 window
= window_from_coordinates (f
, column
, row
, &portion
);
2131 w
= XWINDOW (window
);
2133 /* If we were displaying active text in another window, clear that. */
2134 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
2135 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2137 /* Are we in a window whose display is up to date?
2138 And verify the buffer's text has not changed. */
2139 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2140 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2141 && EQ (w
->window_end_valid
, w
->buffer
)
2142 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2143 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2145 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2148 /* Find which buffer position the mouse corresponds to. */
2149 for (i
= column
; i
>= 0; i
--)
2153 /* Is it outside the displayed active region (if any)? */
2155 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2156 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
2157 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2158 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2159 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2160 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2161 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2162 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2163 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2165 Lisp_Object mouse_face
, overlay
, position
;
2166 Lisp_Object
*overlay_vec
;
2167 int len
, noverlays
, ignor1
;
2168 struct buffer
*obuf
;
2171 /* If we get an out-of-range value, return now; avoid an error. */
2172 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2175 /* Make the window's buffer temporarily current for
2176 overlays_at and compute_char_face. */
2177 obuf
= current_buffer
;
2178 current_buffer
= XBUFFER (w
->buffer
);
2184 /* Yes. Clear the display of the old active region, if any. */
2185 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2187 /* Is this char mouse-active? */
2188 XSETINT (position
, pos
);
2191 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2193 /* Put all the overlays we want in a vector in overlay_vec.
2194 Store the length in len. */
2195 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2197 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2199 /* Find the highest priority overlay that has a mouse-face prop. */
2201 for (i
= 0; i
< noverlays
; i
++)
2203 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2204 if (!NILP (mouse_face
))
2206 overlay
= overlay_vec
[i
];
2211 /* If no overlay applies, get a text property. */
2213 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2215 /* Handle the overlay case. */
2216 if (! NILP (overlay
))
2218 /* Find the range of text around this char that
2219 should be active. */
2220 Lisp_Object before
, after
;
2223 before
= Foverlay_start (overlay
);
2224 after
= Foverlay_end (overlay
);
2225 /* Record this as the current active region. */
2226 fast_find_position (window
, before
,
2227 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2228 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2229 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2230 = !fast_find_position (window
, after
,
2231 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2232 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2233 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2234 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2235 = compute_char_face (f
, w
, pos
, 0, 0,
2236 &ignore
, pos
+ 1, 1);
2238 /* Display it as active. */
2239 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2241 /* Handle the text property case. */
2242 else if (! NILP (mouse_face
))
2244 /* Find the range of text around this char that
2245 should be active. */
2246 Lisp_Object before
, after
, beginning
, end
;
2249 beginning
= Fmarker_position (w
->start
);
2250 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2251 - XFASTINT (w
->window_end_pos
)));
2253 = Fprevious_single_property_change (make_number (pos
+ 1),
2255 w
->buffer
, beginning
);
2257 = Fnext_single_property_change (position
, Qmouse_face
,
2259 /* Record this as the current active region. */
2260 fast_find_position (window
, before
,
2261 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2262 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2263 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
2264 = !fast_find_position (window
, after
,
2265 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
2266 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
2267 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2268 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
2269 = compute_char_face (f
, w
, pos
, 0, 0,
2270 &ignore
, pos
+ 1, 1);
2272 /* Display it as active. */
2273 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
2277 current_buffer
= obuf
;
2282 /* Find the row and column of position POS in window WINDOW.
2283 Store them in *COLUMNP and *ROWP.
2284 This assumes display in WINDOW is up to date.
2285 If POS is above start of WINDOW, return coords
2286 of start of first screen line.
2287 If POS is after end of WINDOW, return coords of end of last screen line.
2289 Value is 1 if POS is in range, 0 if it was off screen. */
2292 fast_find_position (window
, pos
, columnp
, rowp
)
2295 int *columnp
, *rowp
;
2297 struct window
*w
= XWINDOW (window
);
2298 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2301 int left
= WINDOW_LEFT_MARGIN (w
);
2303 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2304 int width
= window_internal_width (w
);
2307 int maybe_next_line
= 0;
2309 /* Find the right row. */
2314 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2315 if (linestart
> pos
)
2317 /* If the position sought is the end of the buffer,
2318 don't include the blank lines at the bottom of the window. */
2319 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2321 maybe_next_line
= 1;
2328 /* Find the right column with in it. */
2329 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2331 for (i
= 0; i
< width
; i
++)
2333 if (charstarts
[left
+ i
] == pos
)
2336 *columnp
= i
+ left
;
2339 else if (charstarts
[left
+ i
] > pos
)
2341 else if (charstarts
[left
+ i
] > 0)
2345 /* If we're looking for the end of the buffer,
2346 and we didn't find it in the line we scanned,
2347 use the start of the following line. */
2348 if (maybe_next_line
)
2359 /* Display the active region described by mouse_face_*
2360 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2363 show_mouse_face (dpyinfo
, hl
)
2364 struct w32_display_info
*dpyinfo
;
2367 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2368 int width
= window_internal_width (w
);
2369 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2372 int old_curs_x
= curs_x
;
2373 int old_curs_y
= curs_y
;
2375 /* Set these variables temporarily
2376 so that if we have to turn the cursor off and on again
2377 we will put it back at the same place. */
2378 curs_x
= f
->phys_cursor_x
;
2379 curs_y
= f
->phys_cursor_y
;
2381 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2382 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2384 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2385 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
2386 : WINDOW_LEFT_MARGIN (w
));
2387 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2388 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
2389 : WINDOW_LEFT_MARGIN (w
) + width
);
2390 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2392 /* If the cursor's in the text we are about to rewrite,
2393 turn the cursor off. */
2395 && curs_x
>= column
- 1
2396 && curs_x
<= endcolumn
)
2398 x_display_cursor (f
, 0);
2403 CHAR_TO_PIXEL_COL (f
, column
),
2404 CHAR_TO_PIXEL_ROW (f
, i
),
2405 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2407 /* Highlight with mouse face if hl > 0. */
2408 hl
> 0 ? 3 : 0, 0, NULL
);
2411 /* If we turned the cursor off, turn it back on. */
2413 x_display_cursor (f
, 1);
2415 curs_x
= old_curs_x
;
2416 curs_y
= old_curs_y
;
2418 /* Change the mouse cursor according to the value of HL. */
2420 SetCursor (f
->output_data
.w32
->cross_cursor
);
2422 SetCursor (f
->output_data
.w32
->text_cursor
);
2425 /* Clear out the mouse-highlighted active region.
2426 Redraw it unhighlighted first. */
2429 clear_mouse_face (dpyinfo
)
2430 struct w32_display_info
*dpyinfo
;
2432 if (! NILP (dpyinfo
->mouse_face_window
))
2433 show_mouse_face (dpyinfo
, 0);
2435 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2436 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2437 dpyinfo
->mouse_face_window
= Qnil
;
2440 struct scroll_bar
*x_window_to_scroll_bar ();
2441 static void x_scroll_bar_report_motion ();
2443 /* Return the current position of the mouse.
2444 *fp should be a frame which indicates which display to ask about.
2446 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2447 and *part to the frame, window, and scroll bar part that the mouse
2448 is over. Set *x and *y to the portion and whole of the mouse's
2449 position on the scroll bar.
2451 If the mouse movement started elsewhere, set *fp to the frame the
2452 mouse is on, *bar_window to nil, and *x and *y to the character cell
2455 Set *time to the server timestamp for the time at which the mouse
2456 was at this position.
2458 Don't store anything if we don't have a valid set of values to report.
2460 This clears the mouse_moved flag, so we can wait for the next mouse
2461 movement. This also calls XQueryPointer, which will cause the
2462 server to give us another MotionNotify when the mouse moves
2466 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2469 Lisp_Object
*bar_window
;
2470 enum scroll_bar_part
*part
;
2472 unsigned long *time
;
2478 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2479 /* This is never called at the moment. */
2480 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2485 Lisp_Object frame
, tail
;
2487 /* Clear the mouse-moved flag for every frame on this display. */
2488 FOR_EACH_FRAME (tail
, frame
)
2489 XFRAME (frame
)->mouse_moved
= 0;
2491 last_mouse_scroll_bar
= Qnil
;
2495 /* Now we have a position on the root; find the innermost window
2496 containing the pointer. */
2498 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2499 && FRAME_LIVE_P (last_mouse_frame
))
2501 f1
= last_mouse_frame
;
2505 /* Is win one of our frames? */
2506 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
2509 /* If not, is it one of our scroll bars? */
2512 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
2516 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2520 if (f1
== 0 && insist
> 0)
2521 f1
= selected_frame
;
2525 int ignore1
, ignore2
;
2527 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
2529 /* Ok, we found a frame. Store all the values. */
2531 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
2533 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
2541 *time
= last_mouse_movement_time
;
2549 /* Scroll bar support. */
2551 /* Given an window ID, find the struct scroll_bar which manages it.
2552 This can be called in GC, so we have to make sure to strip off mark
2555 x_window_to_scroll_bar (window_id
)
2558 Lisp_Object tail
, frame
;
2560 for (tail
= Vframe_list
;
2561 XGCTYPE (tail
) == Lisp_Cons
;
2562 tail
= XCONS (tail
)->cdr
)
2564 Lisp_Object frame
, bar
, condemned
;
2566 frame
= XCONS (tail
)->car
;
2567 /* All elements of Vframe_list should be frames. */
2568 if (! GC_FRAMEP (frame
))
2571 /* Scan this frame's scroll bar list for a scroll bar with the
2573 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2574 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2575 /* This trick allows us to search both the ordinary and
2576 condemned scroll bar lists with one loop. */
2577 ! GC_NILP (bar
) || (bar
= condemned
,
2580 bar
= XSCROLL_BAR (bar
)->next
)
2581 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2582 return XSCROLL_BAR (bar
);
2589 my_create_scrollbar (f
, bar
)
2591 struct scroll_bar
* bar
;
2593 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2594 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2598 //#define ATTACH_THREADS
2601 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2603 #ifndef ATTACH_THREADS
2604 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2605 (WPARAM
) hwnd
, (LPARAM
) how
);
2607 return ShowWindow (hwnd
, how
);
2612 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2613 int x
, int y
, int cx
, int cy
, UINT flags
)
2615 #ifndef ATTACH_THREADS
2617 pos
.hwndInsertAfter
= hwndAfter
;
2623 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2625 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2630 my_set_focus (f
, hwnd
)
2634 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2639 my_set_foreground_window (hwnd
)
2642 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2646 my_destroy_window (f
, hwnd
)
2650 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2654 /* Open a new window to serve as a scroll bar, and return the
2655 scroll bar vector for it. */
2656 static struct scroll_bar
*
2657 x_scroll_bar_create (window
, top
, left
, width
, height
)
2658 struct window
*window
;
2659 int top
, left
, width
, height
;
2661 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2662 struct scroll_bar
*bar
2663 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2668 XSETWINDOW (bar
->window
, window
);
2669 XSETINT (bar
->top
, top
);
2670 XSETINT (bar
->left
, left
);
2671 XSETINT (bar
->width
, width
);
2672 XSETINT (bar
->height
, height
);
2673 XSETINT (bar
->start
, 0);
2674 XSETINT (bar
->end
, 0);
2675 bar
->dragging
= Qnil
;
2677 /* Requires geometry to be set before call to create the real window */
2679 hwnd
= my_create_scrollbar (f
, bar
);
2681 if (pfnSetScrollInfo
)
2685 si
.cbSize
= sizeof (si
);
2688 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2689 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2693 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2697 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2698 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2701 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2703 /* Add bar to its frame's list of scroll bars. */
2704 bar
->next
= FRAME_SCROLL_BARS (f
);
2706 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2707 if (! NILP (bar
->next
))
2708 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2715 /* Draw BAR's handle in the proper position.
2716 If the handle is already drawn from START to END, don't bother
2717 redrawing it, unless REBUILD is non-zero; in that case, always
2718 redraw it. (REBUILD is handy for drawing the handle after expose
2721 Normally, we want to constrain the start and end of the handle to
2722 fit inside its rectangle, but if the user is dragging the scroll bar
2723 handle, we want to let them drag it down all the way, so that the
2724 bar's top is as far down as it goes; otherwise, there's no way to
2725 move to the very end of the buffer. */
2727 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2728 struct scroll_bar
*bar
;
2732 int dragging
= ! NILP (bar
->dragging
);
2733 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2734 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2736 /* If the display is already accurate, do nothing. */
2738 && start
== XINT (bar
->start
)
2739 && end
== XINT (bar
->end
))
2745 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2747 /* Make sure the values are reasonable, and try to preserve
2748 the distance between start and end. */
2750 int length
= end
- start
;
2754 else if (start
> top_range
)
2756 end
= start
+ length
;
2760 else if (end
> top_range
&& ! dragging
)
2765 /* Store the adjusted setting in the scroll bar. */
2766 XSETINT (bar
->start
, start
);
2767 XSETINT (bar
->end
, end
);
2769 /* If being dragged, let scroll bar update itself. */
2772 if (pfnSetScrollInfo
)
2776 si
.cbSize
= sizeof (si
);
2777 si
.fMask
= SIF_PAGE
| SIF_POS
;
2778 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2781 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2784 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2790 /* Move a scroll bar around on the screen, to accommodate changing
2791 window configurations. */
2793 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2794 struct scroll_bar
*bar
;
2795 int top
, left
, width
, height
;
2797 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2798 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2800 /* If already correctly positioned, do nothing. */
2801 if ( XINT (bar
->left
) == left
2802 && XINT (bar
->top
) == top
2803 && XINT (bar
->width
) == width
2804 && XINT (bar
->height
) == height
)
2806 /* Redraw after clear_frame. */
2807 if (!my_show_window (f
, w
, SW_NORMAL
))
2808 InvalidateRect (w
, NULL
, FALSE
);
2814 /* Make sure scroll bar is "visible" before moving, to ensure the
2815 area of the parent window now exposed will be refreshed. */
2816 my_show_window (f
, w
, SW_HIDE
);
2817 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2818 if (pfnSetScrollInfo
)
2822 si
.cbSize
= sizeof (si
);
2823 si
.fMask
= SIF_RANGE
;
2825 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2826 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2828 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2831 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2832 my_show_window (f
, w
, SW_NORMAL
);
2833 // InvalidateRect (w, NULL, FALSE);
2835 XSETINT (bar
->left
, left
);
2836 XSETINT (bar
->top
, top
);
2837 XSETINT (bar
->width
, width
);
2838 XSETINT (bar
->height
, height
);
2843 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2846 x_scroll_bar_remove (bar
)
2847 struct scroll_bar
*bar
;
2849 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2853 /* Destroy the window. */
2854 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2856 /* Disassociate this scroll bar from its window. */
2857 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2862 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2863 that we are displaying PORTION characters out of a total of WHOLE
2864 characters, starting at POSITION. If WINDOW has no scroll bar,
2867 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2868 struct window
*window
;
2869 int portion
, whole
, position
;
2871 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2872 int top
= XINT (window
->top
);
2873 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2874 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2876 /* Where should this scroll bar be, pixelwise? */
2877 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2878 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2880 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2881 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2882 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2883 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2885 struct scroll_bar
*bar
;
2887 /* Does the scroll bar exist yet? */
2888 if (NILP (window
->vertical_scroll_bar
))
2889 bar
= x_scroll_bar_create (window
,
2890 pixel_top
, pixel_left
,
2891 pixel_width
, pixel_height
);
2894 /* It may just need to be moved and resized. */
2895 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2896 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2899 /* Set the scroll bar's current state. */
2901 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2904 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2907 int start
= (int) (((double) position
* top_range
) / whole
);
2908 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2910 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2914 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2918 /* The following three hooks are used when we're doing a thorough
2919 redisplay of the frame. We don't explicitly know which scroll bars
2920 are going to be deleted, because keeping track of when windows go
2921 away is a real pain - "Can you say set-window-configuration, boys
2922 and girls?" Instead, we just assert at the beginning of redisplay
2923 that *all* scroll bars are to be removed, and then save a scroll bar
2924 from the fiery pit when we actually redisplay its window. */
2926 /* Arrange for all scroll bars on FRAME to be removed at the next call
2927 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2928 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2930 w32_condemn_scroll_bars (frame
)
2933 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2934 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2937 bar
= FRAME_SCROLL_BARS (frame
);
2938 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2939 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2940 XSCROLL_BAR (bar
)->prev
= Qnil
;
2941 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2942 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2943 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2946 /* The condemned list should be empty at this point; if it's not,
2947 then the rest of Emacs isn't using the condemn/redeem/judge
2948 protocol correctly. */
2949 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2952 /* Move them all to the "condemned" list. */
2953 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2954 FRAME_SCROLL_BARS (frame
) = Qnil
;
2958 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2959 Note that WINDOW isn't necessarily condemned at all. */
2961 w32_redeem_scroll_bar (window
)
2962 struct window
*window
;
2964 struct scroll_bar
*bar
;
2966 /* We can't redeem this window's scroll bar if it doesn't have one. */
2967 if (NILP (window
->vertical_scroll_bar
))
2970 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2972 /* Unlink it from the condemned list. */
2974 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2976 if (NILP (bar
->prev
))
2978 /* If the prev pointer is nil, it must be the first in one of
2980 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2981 /* It's not condemned. Everything's fine. */
2983 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2984 window
->vertical_scroll_bar
))
2985 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2987 /* If its prev pointer is nil, it must be at the front of
2988 one or the other! */
2992 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2994 if (! NILP (bar
->next
))
2995 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2997 bar
->next
= FRAME_SCROLL_BARS (f
);
2999 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3000 if (! NILP (bar
->next
))
3001 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3004 struct scroll_bar
*bar
;
3006 /* We can't redeem this window's scroll bar if it doesn't have one. */
3007 if (NILP (window
->vertical_scroll_bar
))
3010 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3012 /* Unlink it from the condemned list. */
3014 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3016 if (NILP (bar
->prev
))
3018 /* If the prev pointer is nil, it must be the first in one of
3020 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3021 /* It's not condemned. Everything's fine. */
3023 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3024 window
->vertical_scroll_bar
))
3025 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3027 /* If its prev pointer is nil, it must be at the front of
3028 one or the other! */
3032 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3034 if (! NILP (bar
->next
))
3035 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3037 bar
->next
= FRAME_SCROLL_BARS (f
);
3039 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3040 if (! NILP (bar
->next
))
3041 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3046 /* Remove all scroll bars on FRAME that haven't been saved since the
3047 last call to `*condemn_scroll_bars_hook'. */
3049 w32_judge_scroll_bars (f
)
3052 Lisp_Object bar
, next
;
3054 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3056 /* Clear out the condemned list now so we won't try to process any
3057 more events on the hapless scroll bars. */
3058 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3060 for (; ! NILP (bar
); bar
= next
)
3062 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3064 x_scroll_bar_remove (b
);
3067 b
->next
= b
->prev
= Qnil
;
3070 /* Now there should be no references to the condemned scroll bars,
3071 and they should get garbage-collected. */
3073 Lisp_Object bar
, next
;
3075 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3077 /* Clear out the condemned list now so we won't try to process any
3078 more events on the hapless scroll bars. */
3079 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3081 for (; ! NILP (bar
); bar
= next
)
3083 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3085 x_scroll_bar_remove (b
);
3088 b
->next
= b
->prev
= Qnil
;
3091 /* Now there should be no references to the condemned scroll bars,
3092 and they should get garbage-collected. */
3096 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3097 is set to something other than no_event, it is enqueued.
3099 This may be called from a signal handler, so we have to ignore GC
3103 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
3104 struct scroll_bar
*bar
;
3106 struct input_event
*emacs_event
;
3108 if (! GC_WINDOWP (bar
->window
))
3111 emacs_event
->kind
= w32_scroll_bar_click
;
3112 emacs_event
->code
= 0;
3113 /* not really meaningful to distinguish up/down */
3114 emacs_event
->modifiers
= msg
->dwModifiers
;
3115 emacs_event
->frame_or_window
= bar
->window
;
3116 emacs_event
->timestamp
= msg
->msg
.time
;
3119 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3121 int dragging
= !NILP (bar
->dragging
);
3123 if (pfnGetScrollInfo
)
3127 si
.cbSize
= sizeof (si
);
3130 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
3134 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
3136 bar
->dragging
= Qnil
;
3138 switch (LOWORD (msg
->msg
.wParam
))
3141 emacs_event
->part
= scroll_bar_down_arrow
;
3144 emacs_event
->part
= scroll_bar_up_arrow
;
3147 emacs_event
->part
= scroll_bar_above_handle
;
3150 emacs_event
->part
= scroll_bar_below_handle
;
3153 emacs_event
->part
= scroll_bar_handle
;
3157 emacs_event
->part
= scroll_bar_handle
;
3161 case SB_THUMBPOSITION
:
3162 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3163 y
= HIWORD (msg
->msg
.wParam
);
3165 emacs_event
->part
= scroll_bar_handle
;
3167 /* "Silently" update current position. */
3168 if (pfnSetScrollInfo
)
3172 si
.cbSize
= sizeof (si
);
3176 /* Shrink handle if necessary to allow full range for position. */
3178 int start
= XINT (bar
->start
);
3179 int end
= XINT (bar
->end
);
3180 int len
= end
- start
;
3182 /* If new end is nearly hitting bottom, we must shrink
3183 handle. How much we shrink it depends on the relative
3184 sizes of len and top_range. */
3185 if (y
+ len
> top_range
- 2)
3187 len
-= min (top_range
/ 10, (len
/ 3) + 2);
3191 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3192 si
.fMask
|= SIF_PAGE
;
3196 /* Remember apparent position (we actually lag behind the real
3197 position, so don't set that directly. */
3198 last_scroll_bar_drag_pos
= y
;
3200 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
3203 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
3206 /* If this is the end of a drag sequence, then reset the scroll
3207 handle size to normal and do a final redraw. Otherwise do
3211 if (pfnSetScrollInfo
)
3214 int start
= XINT (bar
->start
);
3215 int end
= XINT (bar
->end
);
3217 si
.cbSize
= sizeof (si
);
3218 si
.fMask
= SIF_PAGE
| SIF_POS
;
3219 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3220 si
.nPos
= last_scroll_bar_drag_pos
;
3222 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
3225 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
3229 emacs_event
->kind
= no_event
;
3233 XSETINT (emacs_event
->x
, y
);
3234 XSETINT (emacs_event
->y
, top_range
);
3240 /* Return information to the user about the current position of the mouse
3241 on the scroll bar. */
3243 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3245 Lisp_Object
*bar_window
;
3246 enum scroll_bar_part
*part
;
3248 unsigned long *time
;
3250 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3251 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
3252 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3254 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
3259 *bar_window
= bar
->window
;
3261 if (pfnGetScrollInfo
)
3265 si
.cbSize
= sizeof (si
);
3266 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
3268 pfnGetScrollInfo (w
, SB_CTL
, &si
);
3270 top_range
= si
.nMax
- si
.nPage
+ 1;
3273 pos
= GetScrollPos (w
, SB_CTL
);
3275 switch (LOWORD (last_mouse_scroll_bar_pos
))
3277 case SB_THUMBPOSITION
:
3279 *part
= scroll_bar_handle
;
3280 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
3281 pos
= HIWORD (last_mouse_scroll_bar_pos
);
3284 *part
= scroll_bar_handle
;
3288 *part
= scroll_bar_handle
;
3293 XSETINT(*y
, top_range
);
3296 last_mouse_scroll_bar
= Qnil
;
3298 *time
= last_mouse_movement_time
;
3303 /* The screen has been cleared so we may have changed foreground or
3304 background colors, and the scroll bars may need to be redrawn.
3305 Clear out the scroll bars, and ask for expose events, so we can
3308 x_scroll_bar_clear (f
)
3313 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3314 bar
= XSCROLL_BAR (bar
)->next
)
3316 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3317 HDC hdc
= GetDC (window
);
3320 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3321 arranges to refresh the scroll bar if hidden. */
3322 my_show_window (f
, window
, SW_HIDE
);
3324 GetClientRect (window
, &rect
);
3325 select_palette (f
, hdc
);
3326 w32_clear_rect (f
, hdc
, &rect
);
3327 deselect_palette (f
, hdc
);
3329 ReleaseDC (window
, hdc
);
3333 show_scroll_bars (f
, how
)
3339 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3340 bar
= XSCROLL_BAR (bar
)->next
)
3342 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
3343 my_show_window (f
, window
, how
);
3348 /* The main W32 event-reading loop - w32_read_socket. */
3350 /* Timestamp of enter window event. This is only used by w32_read_socket,
3351 but we have to put it out here, since static variables within functions
3352 sometimes don't work. */
3353 static Time enter_timestamp
;
3355 /* Record the last 100 characters stored
3356 to help debug the loss-of-chars-during-GC problem. */
3358 short temp_buffer
[100];
3361 /* Read events coming from the W32 shell.
3362 This routine is called by the SIGIO handler.
3363 We return as soon as there are no more events to be read.
3365 Events representing keys are stored in buffer BUFP,
3366 which can hold up to NUMCHARS characters.
3367 We return the number of characters stored into the buffer,
3368 thus pretending to be `read'.
3370 EXPECTED is nonzero if the caller knows input is available.
3372 Some of these messages are reposted back to the message queue since the
3373 system calls the windows proc directly in a context where we cannot return
3374 the data nor can we guarantee the state we are in. So if we dispatch them
3375 we will get into an infinite loop. To prevent this from ever happening we
3376 will set a variable to indicate we are in the read_socket call and indicate
3377 which message we are processing since the windows proc gets called
3378 recursively with different messages by the system.
3382 w32_read_socket (sd
, bufp
, numchars
, expected
)
3384 register struct input_event
*bufp
;
3385 register int numchars
;
3389 int check_visibility
= 0;
3393 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3395 if (interrupt_input_blocked
)
3397 interrupt_input_pending
= 1;
3401 interrupt_input_pending
= 0;
3404 /* So people can tell when we have read the available input. */
3405 input_signal_count
++;
3408 abort (); /* Don't think this happens. */
3410 while (get_next_msg (&msg
, FALSE
))
3412 switch (msg
.msg
.message
)
3415 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3419 if (msg
.rect
.right
== msg
.rect
.left
||
3420 msg
.rect
.bottom
== msg
.rect
.top
)
3422 /* We may get paint messages even though the client
3423 area is clipped - these are not expose events. */
3424 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
3425 XSTRING (f
->name
)->data
));
3427 else if (f
->async_visible
!= 1)
3429 /* Definitely not obscured, so mark as visible. */
3430 f
->async_visible
= 1;
3431 f
->async_iconified
= 0;
3432 SET_FRAME_GARBAGED (f
);
3433 DebPrint (("frame %04x (%s) reexposed\n", f
,
3434 XSTRING (f
->name
)->data
));
3436 /* WM_PAINT serves as MapNotify as well, so report
3437 visibility changes properly. */
3440 bufp
->kind
= deiconify_event
;
3441 XSETFRAME (bufp
->frame_or_window
, f
);
3446 else if (! NILP(Vframe_list
)
3447 && ! NILP (XCONS (Vframe_list
)->cdr
))
3448 /* Force a redisplay sooner or later to update the
3449 frame titles in case this is the second frame. */
3450 record_asynch_buffer_change ();
3454 /* Erase background again for safety. */
3455 w32_clear_rect (f
, NULL
, &msg
.rect
);
3459 msg
.rect
.right
- msg
.rect
.left
,
3460 msg
.rect
.bottom
- msg
.rect
.top
);
3465 case WM_INPUTLANGCHANGE
:
3466 /* Generate a language change event. */
3467 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3474 bufp
->kind
= language_change_event
;
3475 XSETFRAME (bufp
->frame_or_window
, f
);
3476 bufp
->code
= msg
.msg
.wParam
;
3477 bufp
->modifiers
= msg
.msg
.lParam
& 0xffff;
3486 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3488 if (f
&& !f
->iconified
)
3490 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3492 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3493 bufp
->kind
= non_ascii_keystroke
;
3494 bufp
->code
= msg
.msg
.wParam
;
3495 bufp
->modifiers
= msg
.dwModifiers
;
3496 XSETFRAME (bufp
->frame_or_window
, f
);
3497 bufp
->timestamp
= msg
.msg
.time
;
3506 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3508 if (f
&& !f
->iconified
)
3510 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
3512 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
3513 bufp
->kind
= ascii_keystroke
;
3514 bufp
->code
= msg
.msg
.wParam
;
3515 bufp
->modifiers
= msg
.dwModifiers
;
3516 XSETFRAME (bufp
->frame_or_window
, f
);
3517 bufp
->timestamp
= msg
.msg
.time
;
3525 if (dpyinfo
->grabbed
&& last_mouse_frame
3526 && FRAME_LIVE_P (last_mouse_frame
))
3527 f
= last_mouse_frame
;
3529 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3532 note_mouse_movement (f
, &msg
.msg
);
3534 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
3538 case WM_LBUTTONDOWN
:
3540 case WM_MBUTTONDOWN
:
3542 case WM_RBUTTONDOWN
:
3548 if (dpyinfo
->grabbed
&& last_mouse_frame
3549 && FRAME_LIVE_P (last_mouse_frame
))
3550 f
= last_mouse_frame
;
3552 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3556 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3559 construct_mouse_click (bufp
, &msg
, f
);
3566 parse_button (msg
.msg
.message
, &button
, &up
);
3570 dpyinfo
->grabbed
&= ~ (1 << button
);
3574 dpyinfo
->grabbed
|= (1 << button
);
3575 last_mouse_frame
= f
;
3581 if (dpyinfo
->grabbed
&& last_mouse_frame
3582 && FRAME_LIVE_P (last_mouse_frame
))
3583 f
= last_mouse_frame
;
3585 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3589 if ((!dpyinfo
->w32_focus_frame
3590 || f
== dpyinfo
->w32_focus_frame
)
3593 construct_mouse_wheel (bufp
, &msg
, f
);
3602 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3606 construct_drag_n_drop (bufp
, &msg
, f
);
3615 struct scroll_bar
*bar
=
3616 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3618 if (bar
&& numchars
>= 1)
3620 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3630 case WM_WINDOWPOSCHANGED
:
3632 case WM_ACTIVATEAPP
:
3633 check_visibility
= 1;
3637 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3639 if (f
&& !f
->async_iconified
)
3643 x_real_positions (f
, &x
, &y
);
3644 f
->output_data
.w32
->left_pos
= x
;
3645 f
->output_data
.w32
->top_pos
= y
;
3648 check_visibility
= 1;
3652 /* If window has been obscured or exposed by another window
3653 being maximised or minimised/restored, then recheck
3654 visibility of all frames. Direct changes to our own
3655 windows get handled by WM_SIZE. */
3657 if (msg
.msg
.lParam
!= 0)
3658 check_visibility
= 1;
3661 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3662 f
->async_visible
= msg
.msg
.wParam
;
3666 check_visibility
= 1;
3670 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3672 /* Inform lisp of whether frame has been iconified etc. */
3675 switch (msg
.msg
.wParam
)
3677 case SIZE_MINIMIZED
:
3678 f
->async_visible
= 0;
3679 f
->async_iconified
= 1;
3681 bufp
->kind
= iconify_event
;
3682 XSETFRAME (bufp
->frame_or_window
, f
);
3688 case SIZE_MAXIMIZED
:
3690 f
->async_visible
= 1;
3691 f
->async_iconified
= 0;
3693 /* wait_reading_process_input will notice this and update
3694 the frame's display structures. */
3695 SET_FRAME_GARBAGED (f
);
3699 bufp
->kind
= deiconify_event
;
3700 XSETFRAME (bufp
->frame_or_window
, f
);
3706 /* Force a redisplay sooner or later
3707 to update the frame titles
3708 in case this is the second frame. */
3709 record_asynch_buffer_change ();
3714 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3722 GetClientRect(msg
.msg
.hwnd
, &rect
);
3724 height
= rect
.bottom
- rect
.top
;
3725 width
= rect
.right
- rect
.left
;
3727 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3728 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3730 /* TODO: Clip size to the screen dimensions. */
3732 /* Even if the number of character rows and columns has
3733 not changed, the font size may have changed, so we need
3734 to check the pixel dimensions as well. */
3736 if (columns
!= f
->width
3737 || rows
!= f
->height
3738 || width
!= f
->output_data
.w32
->pixel_width
3739 || height
!= f
->output_data
.w32
->pixel_height
)
3741 /* I had set this to 0, 0 - I am not sure why?? */
3743 change_frame_size (f
, rows
, columns
, 0, 1);
3744 SET_FRAME_GARBAGED (f
);
3746 f
->output_data
.w32
->pixel_width
= width
;
3747 f
->output_data
.w32
->pixel_height
= height
;
3748 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3752 check_visibility
= 1;
3757 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3759 if (msg
.msg
.message
== WM_SETFOCUS
)
3761 x_new_focus_frame (dpyinfo
, f
);
3763 else if (f
== dpyinfo
->w32_focus_frame
)
3765 x_new_focus_frame (dpyinfo
, 0);
3768 check_visibility
= 1;
3772 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3779 bufp
->kind
= delete_window_event
;
3780 XSETFRAME (bufp
->frame_or_window
, f
);
3788 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3795 bufp
->kind
= menu_bar_activate_event
;
3796 XSETFRAME (bufp
->frame_or_window
, f
);
3804 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3808 extern void menubar_selection_callback
3809 (FRAME_PTR f
, void * client_data
);
3810 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3813 check_visibility
= 1;
3816 case WM_DISPLAYCHANGE
:
3817 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3821 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3822 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3823 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3824 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3828 check_visibility
= 1;
3832 /* Check for messages registered at runtime. */
3833 if (msg
.msg
.message
== msh_mousewheel
)
3835 if (dpyinfo
->grabbed
&& last_mouse_frame
3836 && FRAME_LIVE_P (last_mouse_frame
))
3837 f
= last_mouse_frame
;
3839 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3843 if ((!dpyinfo
->w32_focus_frame
3844 || f
== dpyinfo
->w32_focus_frame
)
3847 construct_mouse_wheel (bufp
, &msg
, f
);
3858 /* If the focus was just given to an autoraising frame,
3860 /* ??? This ought to be able to handle more than one such frame. */
3861 if (pending_autoraise_frame
)
3863 x_raise_frame (pending_autoraise_frame
);
3864 pending_autoraise_frame
= 0;
3867 /* Check which frames are still visisble, if we have enqueued any user
3868 events or been notified of events that may affect visibility. We
3869 do this here because there doesn't seem to be any direct
3870 notification from Windows that the visibility of a window has
3871 changed (at least, not in all cases). */
3872 if (count
> 0 || check_visibility
)
3874 Lisp_Object tail
, frame
;
3876 FOR_EACH_FRAME (tail
, frame
)
3878 FRAME_PTR f
= XFRAME (frame
);
3879 /* Check "visible" frames and mark each as obscured or not.
3880 Note that async_visible is nonzero for unobscured and
3881 obscured frames, but zero for hidden and iconified frames. */
3882 if (FRAME_W32_P (f
) && f
->async_visible
)
3885 HDC hdc
= get_frame_dc (f
);
3886 GetClipBox (hdc
, &clipbox
);
3887 release_frame_dc (f
, hdc
);
3889 if (clipbox
.right
== clipbox
.left
3890 || clipbox
.bottom
== clipbox
.top
)
3892 /* Frame has become completely obscured so mark as
3893 such (we do this by setting async_visible to 2 so
3894 that FRAME_VISIBLE_P is still true, but redisplay
3896 f
->async_visible
= 2;
3898 if (!FRAME_OBSCURED_P (f
))
3900 DebPrint (("frame %04x (%s) obscured\n", f
,
3901 XSTRING (f
->name
)->data
));
3906 /* Frame is not obscured, so mark it as such. */
3907 f
->async_visible
= 1;
3909 if (FRAME_OBSCURED_P (f
))
3911 SET_FRAME_GARBAGED (f
);
3912 DebPrint (("frame %04x (%s) reexposed\n", f
,
3913 XSTRING (f
->name
)->data
));
3915 /* Force a redisplay sooner or later. */
3916 record_asynch_buffer_change ();
3927 /* Drawing the cursor. */
3930 /* Draw a hollow box cursor. Don't change the inside of the box. */
3940 hdc
= get_frame_dc (f
);
3942 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3944 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3945 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3946 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3947 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3949 FrameRect (hdc
, &rect
, hb
);
3952 release_frame_dc (f
, hdc
);
3955 /* Clear the cursor of frame F to background color,
3956 and mark the cursor as not shown.
3957 This is used when the text where the cursor is
3958 is about to be rewritten. */
3964 if (! FRAME_VISIBLE_P (f
)
3965 || !f
->phys_cursor_on
)
3968 x_display_cursor (f
, 0);
3969 f
->phys_cursor_on
= 0;
3972 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3973 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3977 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3984 CHAR_TO_PIXEL_COL (f
, column
),
3985 CHAR_TO_PIXEL_ROW (f
, row
),
3986 &glyph
, 1, highlight
, 0, NULL
);
3990 x_display_bar_cursor (f
, on
)
3994 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3996 /* This is pointless on invisible frames, and dangerous on garbaged
3997 frames; in the latter case, the frame may be in the midst of
3998 changing its size, and curs_x and curs_y may be off the frame. */
3999 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4002 if (! on
&& ! f
->phys_cursor_on
)
4005 /* If there is anything wrong with the current cursor state, remove it. */
4006 if (f
->phys_cursor_on
4008 || f
->phys_cursor_x
!= curs_x
4009 || f
->phys_cursor_y
!= curs_y
4010 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
4012 /* Erase the cursor by redrawing the character underneath it. */
4013 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4014 f
->phys_cursor_glyph
,
4015 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4016 f
->phys_cursor_on
= 0;
4019 /* If we now need a cursor in the new place or in the new form, do it so. */
4021 && (! f
->phys_cursor_on
4022 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
4024 f
->phys_cursor_glyph
4025 = ((current_glyphs
->enable
[curs_y
]
4026 && curs_x
< current_glyphs
->used
[curs_y
])
4027 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4029 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
4030 CHAR_TO_PIXEL_COL (f
, curs_x
),
4031 CHAR_TO_PIXEL_ROW (f
, curs_y
),
4032 max (f
->output_data
.w32
->cursor_width
, 1),
4033 f
->output_data
.w32
->line_height
);
4035 f
->phys_cursor_x
= curs_x
;
4036 f
->phys_cursor_y
= curs_y
;
4037 f
->phys_cursor_on
= 1;
4039 f
->output_data
.w32
->current_cursor
= bar_cursor
;
4044 /* Turn the displayed cursor of frame F on or off according to ON.
4045 If ON is nonzero, where to put the cursor is specified
4046 by F->cursor_x and F->cursor_y. */
4049 x_display_box_cursor (f
, on
)
4053 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4055 /* This is pointless on invisible frames, and dangerous on garbaged
4056 frames; in the latter case, the frame may be in the midst of
4057 changing its size, and curs_x and curs_y may be off the frame. */
4058 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4061 /* If cursor is off and we want it off, return quickly. */
4062 if (!on
&& ! f
->phys_cursor_on
)
4065 /* If cursor is currently being shown and we don't want it to be
4066 or it is in the wrong place,
4067 or we want a hollow box and it's not so, (pout!)
4069 if (f
->phys_cursor_on
4071 || f
->phys_cursor_x
!= curs_x
4072 || f
->phys_cursor_y
!= curs_y
4073 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
4074 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
4076 int mouse_face_here
= 0;
4077 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4079 /* If the cursor is in the mouse face area, redisplay that when
4080 we clear the cursor. */
4081 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4082 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4083 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
4084 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4085 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4086 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
4087 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
4088 /* Don't redraw the cursor's spot in mouse face
4089 if it is at the end of a line (on a newline).
4090 The cursor appears there, but mouse highlighting does not. */
4091 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4092 mouse_face_here
= 1;
4094 /* If the font is not as tall as a whole line,
4095 we must explicitly clear the line's whole height. */
4096 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
4097 w32_clear_area (f
, NULL
,
4098 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4099 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4100 FONT_WIDTH (f
->output_data
.w32
->font
),
4101 f
->output_data
.w32
->line_height
);
4102 /* Erase the cursor by redrawing the character underneath it. */
4103 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4104 f
->phys_cursor_glyph
,
4107 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4108 f
->phys_cursor_on
= 0;
4111 /* If we want to show a cursor,
4112 or we want a box cursor and it's not so,
4113 write it in the right place. */
4115 && (! f
->phys_cursor_on
4116 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
4117 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
4119 f
->phys_cursor_glyph
4120 = ((current_glyphs
->enable
[curs_y
]
4121 && curs_x
< current_glyphs
->used
[curs_y
])
4122 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
4124 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
4127 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
4131 x_draw_single_glyph (f
, curs_y
, curs_x
,
4132 f
->phys_cursor_glyph
, 2);
4133 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
4136 f
->phys_cursor_x
= curs_x
;
4137 f
->phys_cursor_y
= curs_y
;
4138 f
->phys_cursor_on
= 1;
4142 /* Display the cursor on frame F, or clear it, according to ON.
4143 Use the position specified by curs_x and curs_y
4144 if we are doing an update of frame F now.
4145 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4148 x_display_cursor (f
, on
)
4154 /* If we're not updating, then we want to use the current frame's
4155 cursor position, not our local idea of where the cursor ought to be. */
4156 if (f
!= updating_frame
)
4158 curs_x
= FRAME_CURSOR_X (f
);
4159 curs_y
= FRAME_CURSOR_Y (f
);
4162 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4163 x_display_box_cursor (f
, on
);
4164 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4165 x_display_bar_cursor (f
, on
);
4167 /* Those are the only two we have implemented! */
4173 /* Changing the font of the frame. */
4175 /* Give frame F the font named FONTNAME as its default font, and
4176 return the full name of that font. FONTNAME may be a wildcard
4177 pattern; in that case, we choose some font that fits the pattern.
4178 The return value shows which font we chose. */
4181 x_new_font (f
, fontname
)
4183 register char *fontname
;
4185 struct font_info
*fontp
4186 = fs_load_font (f
, FRAME_W32_FONT_TABLE (f
), CHARSET_ASCII
,
4192 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4193 f
->output_data
.w32
->font_baseline
4194 = FONT_BASE (FRAME_FONT (f
)) + fontp
->baseline_offset
;
4195 FRAME_FONTSET (f
) = -1;
4197 /* Compute the scroll bar width in character columns. */
4198 if (f
->scroll_bar_pixel_width
> 0)
4200 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
4201 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
4204 f
->scroll_bar_cols
= 2;
4206 /* Now make the frame display the given font. */
4207 if (FRAME_W32_WINDOW (f
) != 0)
4209 frame_update_line_height (f
);
4210 x_set_window_size (f
, 0, f
->width
, f
->height
);
4213 /* If we are setting a new frame's font for the first time,
4214 there are no faces yet, so this font's height is the line height. */
4215 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
4218 Lisp_Object lispy_name
;
4220 lispy_name
= build_string (fontname
);
4226 /* Give frame F the fontset named FONTSETNAME as its default font, and
4227 return the full name of that fontset. FONTSETNAME may be a wildcard
4228 pattern; in that case, we choose some fontset that fits the pattern.
4229 The return value shows which fontset we chose. */
4232 x_new_fontset (f
, fontsetname
)
4236 int fontset
= fs_query_fontset (f
, fontsetname
);
4237 struct fontset_info
*fontsetp
;
4243 if (FRAME_FONTSET (f
) == fontset
)
4244 /* This fontset is already set in frame F. There's nothing more
4246 return build_string (fontsetname
);
4248 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
4250 if (!fontsetp
->fontname
[CHARSET_ASCII
])
4251 /* This fontset doesn't contain ASCII font. */
4254 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
4256 if (!STRINGP (result
))
4257 /* Can't load ASCII font. */
4260 /* Since x_new_font doesn't update any fontset information, do it now. */
4261 FRAME_FONTSET(f
) = fontset
;
4262 FS_LOAD_FONT (f
, FRAME_W32_FONT_TABLE (f
),
4263 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
4265 return build_string (fontsetname
);
4268 /* Calculate the absolute position in frame F
4269 from its current recorded position values and gravity. */
4271 x_calc_absolute_position (f
)
4276 int flags
= f
->output_data
.w32
->size_hint_flags
;
4280 /* Find the position of the outside upper-left corner of
4281 the inner window, with respect to the outer window. */
4282 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
4285 MapWindowPoints (FRAME_W32_WINDOW (f
),
4286 f
->output_data
.w32
->parent_desc
,
4293 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
4296 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
4297 FRAME_EXTERNAL_MENU_BAR (f
));
4300 pt
.x
+= (rt
.right
- rt
.left
);
4301 pt
.y
+= (rt
.bottom
- rt
.top
);
4304 /* Treat negative positions as relative to the leftmost bottommost
4305 position that fits on the screen. */
4306 if (flags
& XNegative
)
4307 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
4308 - 2 * f
->output_data
.w32
->border_width
- pt
.x
4310 + f
->output_data
.w32
->left_pos
);
4312 if (flags
& YNegative
)
4313 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
4314 - 2 * f
->output_data
.w32
->border_width
- pt
.y
4316 + f
->output_data
.w32
->top_pos
);
4317 /* The left_pos and top_pos
4318 are now relative to the top and left screen edges,
4319 so the flags should correspond. */
4320 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4323 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4324 to really change the position, and 0 when calling from
4325 x_make_frame_visible (in that case, XOFF and YOFF are the current
4326 position values). It is -1 when calling from x_set_frame_parameters,
4327 which means, do adjust for borders but don't change the gravity. */
4329 x_set_offset (f
, xoff
, yoff
, change_gravity
)
4331 register int xoff
, yoff
;
4334 int modified_top
, modified_left
;
4336 if (change_gravity
> 0)
4338 f
->output_data
.w32
->top_pos
= yoff
;
4339 f
->output_data
.w32
->left_pos
= xoff
;
4340 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
4342 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
4344 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
4345 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4347 x_calc_absolute_position (f
);
4350 x_wm_set_size_hint (f
, (long) 0, 0);
4352 /* It is a mystery why we need to add the border_width here
4353 when the frame is already visible, but experiment says we do. */
4354 modified_left
= f
->output_data
.w32
->left_pos
;
4355 modified_top
= f
->output_data
.w32
->top_pos
;
4357 /* Do not add in border widths under W32. */
4358 if (change_gravity
!= 0)
4360 modified_left
+= f
->output_data
.w32
->border_width
;
4361 modified_top
+= f
->output_data
.w32
->border_width
;
4365 my_set_window_pos (FRAME_W32_WINDOW (f
),
4367 modified_left
, modified_top
,
4369 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
4373 /* Call this to change the size of frame F's x-window.
4374 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4375 for this size change and subsequent size changes.
4376 Otherwise we leave the window gravity unchanged. */
4378 x_set_window_size (f
, change_gravity
, cols
, rows
)
4383 int pixelwidth
, pixelheight
;
4385 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4389 check_frame_size (f
, &rows
, &cols
);
4390 f
->output_data
.w32
->vertical_scroll_bar_extra
4391 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4393 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
4394 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
4395 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
4396 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
4397 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
4399 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
4400 x_wm_set_size_hint (f
, (long) 0, 0);
4405 rect
.left
= rect
.top
= 0;
4406 rect
.right
= pixelwidth
;
4407 rect
.bottom
= pixelheight
;
4409 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
4410 FRAME_EXTERNAL_MENU_BAR (f
));
4412 my_set_window_pos (FRAME_W32_WINDOW (f
),
4415 rect
.right
- rect
.left
,
4416 rect
.bottom
- rect
.top
,
4417 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4420 /* Now, strictly speaking, we can't be sure that this is accurate,
4421 but the window manager will get around to dealing with the size
4422 change request eventually, and we'll hear how it went when the
4423 ConfigureNotify event gets here.
4425 We could just not bother storing any of this information here,
4426 and let the ConfigureNotify event set everything up, but that
4427 might be kind of confusing to the lisp code, since size changes
4428 wouldn't be reported in the frame parameters until some random
4429 point in the future when the ConfigureNotify event arrives. */
4430 change_frame_size (f
, rows
, cols
, 0, 0);
4431 PIXEL_WIDTH (f
) = pixelwidth
;
4432 PIXEL_HEIGHT (f
) = pixelheight
;
4434 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4435 receive in the ConfigureNotify event; if we get what we asked
4436 for, then the event won't cause the screen to become garbaged, so
4437 we have to make sure to do it here. */
4438 SET_FRAME_GARBAGED (f
);
4440 /* If cursor was outside the new size, mark it as off. */
4441 if (f
->phys_cursor_y
>= rows
4442 || f
->phys_cursor_x
>= cols
)
4444 f
->phys_cursor_x
= 0;
4445 f
->phys_cursor_y
= 0;
4446 f
->phys_cursor_on
= 0;
4449 /* Clear out any recollection of where the mouse highlighting was,
4450 since it might be in a place that's outside the new frame size.
4451 Actually checking whether it is outside is a pain in the neck,
4452 so don't try--just let the highlighting be done afresh with new size. */
4453 window
= dpyinfo
->mouse_face_window
;
4454 if (! NILP (window
) && XFRAME (window
) == f
)
4456 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4457 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4458 dpyinfo
->mouse_face_window
= Qnil
;
4464 /* Mouse warping. */
4467 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
4476 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
4477 pt
.x
= rect
.left
+ pix_x
;
4478 pt
.y
= rect
.top
+ pix_y
;
4479 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
4481 SetCursorPos (pt
.x
, pt
.y
);
4487 x_set_mouse_position (f
, x
, y
)
4493 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
4494 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
4496 if (pix_x
< 0) pix_x
= 0;
4497 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
4499 if (pix_y
< 0) pix_y
= 0;
4500 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
4502 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
4505 /* focus shifting, raising and lowering. */
4507 x_focus_on_frame (f
)
4510 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
4512 /* Give input focus to frame. */
4515 /* Try not to change its Z-order if possible. */
4516 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
4517 my_set_focus (f
, FRAME_W32_WINDOW (f
));
4520 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4529 /* Raise frame F. */
4536 /* Strictly speaking, raise-frame should only change the frame's Z
4537 order, leaving input focus unchanged. This is reasonable behaviour
4538 on X where the usual policy is point-to-focus. However, this
4539 behaviour would be very odd on Windows where the usual policy is
4542 On X, if the mouse happens to be over the raised frame, it gets
4543 input focus anyway (so the window with focus will never be
4544 completely obscured) - if not, then just moving the mouse over it
4545 is sufficient to give it focus. On Windows, the user must actually
4546 click on the frame (preferrably the title bar so as not to move
4547 point), which is more awkward. Also, no other Windows program
4548 raises a window to the top but leaves another window (possibly now
4549 completely obscured) with input focus.
4551 Because there is a system setting on Windows that allows the user
4552 to choose the point to focus policy, we make the strict semantics
4553 optional, but by default we grab focus when raising. */
4555 if (NILP (Vw32_grab_focus_on_raise
))
4557 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4558 not already the foreground application: the frame is raised
4559 above all other frames belonging to us, but not above the
4560 current top window. To achieve that, we have to resort to this
4561 more cumbersome method. */
4563 HDWP handle
= BeginDeferWindowPos (2);
4566 DeferWindowPos (handle
,
4567 FRAME_W32_WINDOW (f
),
4570 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4572 DeferWindowPos (handle
,
4573 GetForegroundWindow (),
4574 FRAME_W32_WINDOW (f
),
4576 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4578 EndDeferWindowPos (handle
);
4583 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4589 /* Lower frame F. */
4595 my_set_window_pos (FRAME_W32_WINDOW (f
),
4598 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4603 w32_frame_raise_lower (f
, raise
)
4613 /* Change of visibility. */
4615 /* This tries to wait until the frame is really visible.
4616 However, if the window manager asks the user where to position
4617 the frame, this will return before the user finishes doing that.
4618 The frame will not actually be visible at that time,
4619 but it will become visible later when the window manager
4620 finishes with it. */
4622 x_make_frame_visible (f
)
4627 if (! FRAME_VISIBLE_P (f
))
4629 /* We test FRAME_GARBAGED_P here to make sure we don't
4630 call x_set_offset a second time
4631 if we get to x_make_frame_visible a second time
4632 before the window gets really visible. */
4633 if (! FRAME_ICONIFIED_P (f
)
4634 && ! f
->output_data
.w32
->asked_for_visible
)
4635 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4637 f
->output_data
.w32
->asked_for_visible
= 1;
4639 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4640 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4643 /* Synchronize to ensure Emacs knows the frame is visible
4644 before we do anything else. We do this loop with input not blocked
4645 so that incoming events are handled. */
4648 int count
= input_signal_count
;
4650 /* This must come after we set COUNT. */
4653 XSETFRAME (frame
, f
);
4657 /* Once we have handled input events,
4658 we should have received the MapNotify if one is coming.
4659 So if we have not got it yet, stop looping.
4660 Some window managers make their own decisions
4661 about visibility. */
4662 if (input_signal_count
!= count
)
4664 /* Machines that do polling rather than SIGIO have been observed
4665 to go into a busy-wait here. So we'll fake an alarm signal
4666 to let the handler know that there's something to be read.
4667 We used to raise a real alarm, but it seems that the handler
4668 isn't always enabled here. This is probably a bug. */
4669 if (input_polling_used ())
4671 /* It could be confusing if a real alarm arrives while processing
4672 the fake one. Turn it off and let the handler reset it. */
4674 input_poll_signal (0);
4676 /* Once we have handled input events,
4677 we should have received the MapNotify if one is coming.
4678 So if we have not got it yet, stop looping.
4679 Some window managers make their own decisions
4680 about visibility. */
4681 if (input_signal_count
!= count
)
4684 FRAME_SAMPLE_VISIBILITY (f
);
4688 /* Change from mapped state to withdrawn state. */
4690 /* Make the frame visible (mapped and not iconified). */
4692 x_make_frame_invisible (f
)
4697 /* Don't keep the highlight on an invisible frame. */
4698 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4699 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4703 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4705 /* We can't distinguish this from iconification
4706 just by the event that we get from the server.
4707 So we can't win using the usual strategy of letting
4708 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4709 and synchronize with the server to make sure we agree. */
4711 FRAME_ICONIFIED_P (f
) = 0;
4712 f
->async_visible
= 0;
4713 f
->async_iconified
= 0;
4718 /* Change window state from mapped to iconified. */
4726 /* Don't keep the highlight on an invisible frame. */
4727 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4728 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4730 if (f
->async_iconified
)
4735 /* Simulate the user minimizing the frame. */
4736 SendMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4741 /* Destroy the window of frame F. */
4743 x_destroy_window (f
)
4746 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4750 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4751 free_frame_menubar (f
);
4752 free_frame_faces (f
);
4754 xfree (f
->output_data
.w32
);
4755 f
->output_data
.w32
= 0;
4756 if (f
== dpyinfo
->w32_focus_frame
)
4757 dpyinfo
->w32_focus_frame
= 0;
4758 if (f
== dpyinfo
->w32_focus_event_frame
)
4759 dpyinfo
->w32_focus_event_frame
= 0;
4760 if (f
== dpyinfo
->w32_highlight_frame
)
4761 dpyinfo
->w32_highlight_frame
= 0;
4763 dpyinfo
->reference_count
--;
4765 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4767 dpyinfo
->mouse_face_beg_row
4768 = dpyinfo
->mouse_face_beg_col
= -1;
4769 dpyinfo
->mouse_face_end_row
4770 = dpyinfo
->mouse_face_end_col
= -1;
4771 dpyinfo
->mouse_face_window
= Qnil
;
4777 /* Setting window manager hints. */
4779 /* Set the normal size hints for the window manager, for frame F.
4780 FLAGS is the flags word to use--or 0 meaning preserve the flags
4781 that the window now has.
4782 If USER_POSITION is nonzero, we set the USPosition
4783 flag (this is useful when FLAGS is 0). */
4785 x_wm_set_size_hint (f
, flags
, user_position
)
4790 Window window
= FRAME_W32_WINDOW (f
);
4792 flexlines
= f
->height
;
4796 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4797 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4798 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4799 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4804 /* Window manager things */
4805 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4810 Window window
= FRAME_W32_WINDOW (f
);
4812 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4813 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4814 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4816 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4821 /* Initialization. */
4823 #ifdef USE_X_TOOLKIT
4824 static XrmOptionDescRec emacs_options
[] = {
4825 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4826 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4828 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4829 XrmoptionSepArg
, NULL
},
4830 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4832 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4833 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4834 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4835 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4836 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4837 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4838 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4840 #endif /* USE_X_TOOLKIT */
4842 static int w32_initialized
= 0;
4844 struct w32_display_info
*
4845 w32_term_init (display_name
, xrm_option
, resource_name
)
4846 Lisp_Object display_name
;
4848 char *resource_name
;
4852 struct w32_display_info
*dpyinfo
;
4857 if (!w32_initialized
)
4860 w32_initialized
= 1;
4871 argv
[argc
++] = "-xrm";
4872 argv
[argc
++] = xrm_option
;
4876 dpyinfo
= &one_w32_display_info
;
4878 /* Put this display on the chain. */
4879 dpyinfo
->next
= NULL
;
4881 /* Put it on w32_display_name_list as well, to keep them parallel. */
4882 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4883 w32_display_name_list
);
4884 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4886 dpyinfo
->w32_id_name
4887 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4888 + XSTRING (Vsystem_name
)->size
4890 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4891 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4894 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4895 resource_name
, EMACS_CLASS
);
4897 /* Put the rdb where we can find it in a way that works on
4899 dpyinfo
->xrdb
= xrdb
;
4901 hdc
= GetDC (GetDesktopWindow ());
4903 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4904 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4905 dpyinfo
->root_window
= GetDesktopWindow ();
4906 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4907 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4908 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4909 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4910 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4911 dpyinfo
->grabbed
= 0;
4912 dpyinfo
->reference_count
= 0;
4913 dpyinfo
->n_fonts
= 0;
4914 dpyinfo
->font_table_size
= 0;
4915 dpyinfo
->bitmaps
= 0;
4916 dpyinfo
->bitmaps_size
= 0;
4917 dpyinfo
->bitmaps_last
= 0;
4918 dpyinfo
->mouse_face_mouse_frame
= 0;
4919 dpyinfo
->mouse_face_deferred_gc
= 0;
4920 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4921 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4922 dpyinfo
->mouse_face_face_id
= 0;
4923 dpyinfo
->mouse_face_window
= Qnil
;
4924 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4925 dpyinfo
->mouse_face_defer
= 0;
4926 dpyinfo
->w32_focus_frame
= 0;
4927 dpyinfo
->w32_focus_event_frame
= 0;
4928 dpyinfo
->w32_highlight_frame
= 0;
4930 ReleaseDC (GetDesktopWindow (), hdc
);
4932 /* Determine if there is a middle mouse button, to allow parse_button
4933 to decide whether right mouse events should be mouse-2 or
4935 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4937 /* initialise palette with white and black */
4940 defined_color (0, "white", &color
, 1);
4941 defined_color (0, "black", &color
, 1);
4944 #ifndef F_SETOWN_BUG
4946 #ifdef F_SETOWN_SOCK_NEG
4947 /* stdin is a socket here */
4948 fcntl (connection
, F_SETOWN
, -getpid ());
4949 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4950 fcntl (connection
, F_SETOWN
, getpid ());
4951 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4952 #endif /* ! defined (F_SETOWN) */
4953 #endif /* F_SETOWN_BUG */
4956 if (interrupt_input
)
4957 init_sigio (connection
);
4958 #endif /* ! defined (SIGIO) */
4965 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4968 x_delete_display (dpyinfo
)
4969 struct w32_display_info
*dpyinfo
;
4971 /* Discard this display from w32_display_name_list and w32_display_list.
4972 We can't use Fdelq because that can quit. */
4973 if (! NILP (w32_display_name_list
)
4974 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4975 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4980 tail
= w32_display_name_list
;
4981 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4983 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4984 dpyinfo
->name_list_element
))
4986 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4989 tail
= XCONS (tail
)->cdr
;
4993 /* free palette table */
4995 struct w32_palette_entry
* plist
;
4997 plist
= dpyinfo
->color_list
;
5000 struct w32_palette_entry
* pentry
= plist
;
5001 plist
= plist
->next
;
5004 dpyinfo
->color_list
= NULL
;
5005 if (dpyinfo
->palette
)
5006 DeleteObject(dpyinfo
->palette
);
5008 xfree (dpyinfo
->font_table
);
5009 xfree (dpyinfo
->w32_id_name
);
5012 /* Set up use of W32. */
5014 DWORD
w32_msg_worker ();
5018 /* MSVC does not type K&R functions with no arguments correctly, and
5019 so we must explicitly cast them. */
5020 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
5021 clear_end_of_line_hook
= w32_clear_end_of_line
;
5022 ins_del_lines_hook
= w32_ins_del_lines
;
5023 change_line_highlight_hook
= w32_change_line_highlight
;
5024 insert_glyphs_hook
= w32_insert_glyphs
;
5025 write_glyphs_hook
= w32_write_glyphs
;
5026 delete_glyphs_hook
= w32_delete_glyphs
;
5027 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
5028 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
5029 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
5030 update_begin_hook
= w32_update_begin
;
5031 update_end_hook
= w32_update_end
;
5032 set_terminal_window_hook
= w32_set_terminal_window
;
5033 read_socket_hook
= w32_read_socket
;
5034 frame_up_to_date_hook
= w32_frame_up_to_date
;
5035 cursor_to_hook
= w32_cursor_to
;
5036 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
5037 mouse_position_hook
= w32_mouse_position
;
5038 frame_rehighlight_hook
= w32_frame_rehighlight
;
5039 frame_raise_lower_hook
= w32_frame_raise_lower
;
5040 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
5041 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
5042 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
5043 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
5045 scroll_region_ok
= 1; /* we'll scroll partial frames */
5046 char_ins_del_ok
= 0; /* just as fast to write the line */
5047 line_ins_del_ok
= 1; /* we'll just blt 'em */
5048 fast_clear_end_of_line
= 1; /* X does this well */
5049 memory_below_frame
= 0; /* we don't remember what scrolls
5053 /* Initialize input mode: interrupt_input off, no flow control, allow
5054 8 bit character input, standard quit char. */
5055 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
5057 /* Create the window thread - it will terminate itself or when the app terminates */
5061 dwMainThreadId
= GetCurrentThreadId ();
5062 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5063 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
5065 /* Wait for thread to start */
5070 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
5072 hWindowsThread
= CreateThread (NULL
, 0,
5073 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
5074 0, 0, &dwWindowsThreadId
);
5076 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
5079 /* It is desirable that mainThread should have the same notion of
5080 focus window and active window as windowsThread. Unfortunately, the
5081 following call to AttachThreadInput, which should do precisely what
5082 we need, causes major problems when Emacs is linked as a console
5083 program. Unfortunately, we have good reasons for doing that, so
5084 instead we need to send messages to windowsThread to make some API
5085 calls for us (ones that affect, or depend on, the active/focus
5087 #ifdef ATTACH_THREADS
5088 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
5091 /* Dynamically link to optional system components. */
5093 HANDLE user_lib
= LoadLibrary ("user32.dll");
5095 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5097 /* New proportional scroll bar functions. */
5098 LOAD_PROC( SetScrollInfo
);
5099 LOAD_PROC( GetScrollInfo
);
5103 FreeLibrary (user_lib
);
5105 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5106 otherwise use the fixed height. */
5107 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
5108 GetSystemMetrics (SM_CYVTHUMB
);
5110 /* For either kind of scroll bar, take account of the arrows; these
5111 effectively form the border of the main scroll bar range. */
5112 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
5113 = GetSystemMetrics (SM_CYVSCROLL
);
5120 Lisp_Object codepage
;
5122 staticpro (&w32_display_name_list
);
5123 w32_display_name_list
= Qnil
;
5125 staticpro (&last_mouse_scroll_bar
);
5126 last_mouse_scroll_bar
= Qnil
;
5128 staticpro (&Qvendor_specific_keysyms
);
5129 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
5131 DEFVAR_INT ("w32-num-mouse-buttons",
5132 &Vw32_num_mouse_buttons
,
5133 "Number of physical mouse buttons.");
5134 Vw32_num_mouse_buttons
= Qnil
;
5136 DEFVAR_LISP ("w32-swap-mouse-buttons",
5137 &Vw32_swap_mouse_buttons
,
5138 "Swap the mapping of middle and right mouse buttons.\n\
5139 When nil, middle button is mouse-2 and right button is mouse-3.");
5140 Vw32_swap_mouse_buttons
= Qnil
;
5142 DEFVAR_LISP ("w32-grab-focus-on-raise",
5143 &Vw32_grab_focus_on_raise
,
5144 "Raised frame grabs input focus.\n\
5145 When t, `raise-frame' grabs input focus as well. This fits well\n\
5146 with the normal Windows click-to-focus policy, but might not be\n\
5147 desirable when using a point-to-focus policy.");
5148 Vw32_grab_focus_on_raise
= Qt
;
5150 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5151 &Vw32_capslock_is_shiftlock
,
5152 "Apply CapsLock state to non character input keys.\n\
5153 When nil, CapsLock only affects normal character input keys.");
5154 Vw32_capslock_is_shiftlock
= Qnil
;
5156 DEFVAR_LISP ("w32-recognize-altgr",
5157 &Vw32_recognize_altgr
,
5158 "Recognize right-alt and left-ctrl as AltGr.\n\
5159 When nil, the right-alt and left-ctrl key combination is\n\
5160 interpreted normally.");
5161 Vw32_recognize_altgr
= Qt
;
5163 DEFVAR_BOOL ("w32-enable-unicode-output",
5164 &w32_enable_unicode_output
,
5165 "Enable the use of Unicode for text output if non-nil.\n\
5166 Unicode output may prevent some third party applications for displaying\n\
5167 Far-East Languages on Windows 95/98 from working properly.\n\
5168 NT uses Unicode internally anyway, so this flag will probably have no\n\
5169 affect on NT machines.");
5170 w32_enable_unicode_output
= 1;
5172 DEFVAR_LISP ("w32-charset-to-codepage-alist",
5173 &Vw32_charset_to_codepage_alist
,
5174 "Alist linking character sets to Windows Codepages.");
5175 Vw32_charset_to_codepage_alist
= Qnil
;
5176 /* Initialise the alist with some defaults. */
5177 XSETFASTINT (codepage
, 936);
5178 store_in_alist (&Vw32_charset_to_codepage_alist
,
5179 build_string ("gb2312"), codepage
);
5180 XSETFASTINT (codepage
, 950);
5181 store_in_alist (&Vw32_charset_to_codepage_alist
,
5182 build_string ("big5"), codepage
);
5183 XSETFASTINT (codepage
, 949);
5184 store_in_alist (&Vw32_charset_to_codepage_alist
,
5185 build_string ("ksc5601.1987"), codepage
);
5186 XSETFASTINT (codepage
, 1361);
5187 store_in_alist (&Vw32_charset_to_codepage_alist
,
5188 build_string ("ksc5601.1992"), codepage
);
5189 XSETFASTINT (codepage
, 932);
5190 store_in_alist (&Vw32_charset_to_codepage_alist
,
5191 build_string ("jisx0208-sjis"), codepage
);
5192 XSETFASTINT (codepage
, 874);
5193 store_in_alist (&Vw32_charset_to_codepage_alist
,
5194 build_string ("tis620"), codepage
);
5195 XSETFASTINT (codepage
, 20866);
5196 store_in_alist (&Vw32_charset_to_codepage_alist
,
5197 build_string ("koi8-r"), codepage
);
5198 /* iso8859-13 is not yet officially adopted, but it is conveniently
5199 covered by CP 1257. */
5200 XSETFASTINT (codepage
, 1257);
5201 store_in_alist (&Vw32_charset_to_codepage_alist
,
5202 build_string ("iso8859-13"), codepage
);
5203 XSETFASTINT (codepage
, 1254);
5204 store_in_alist (&Vw32_charset_to_codepage_alist
,
5205 build_string ("iso8859-9"), codepage
);
5206 XSETFASTINT (codepage
, 1255);
5207 store_in_alist (&Vw32_charset_to_codepage_alist
,
5208 build_string ("iso8859-8"), codepage
);
5209 XSETFASTINT (codepage
, 28597);
5210 store_in_alist (&Vw32_charset_to_codepage_alist
,
5211 build_string ("iso8859-7"), codepage
);
5212 XSETFASTINT (codepage
, 28596);
5213 store_in_alist (&Vw32_charset_to_codepage_alist
,
5214 build_string ("iso8859-6"), codepage
);
5215 XSETFASTINT (codepage
, 28595);
5216 store_in_alist (&Vw32_charset_to_codepage_alist
,
5217 build_string ("iso8859-5"), codepage
);
5218 XSETFASTINT (codepage
, 28594);
5219 store_in_alist (&Vw32_charset_to_codepage_alist
,
5220 build_string ("iso8859-4"), codepage
);
5221 XSETFASTINT (codepage
, 28593);
5222 store_in_alist (&Vw32_charset_to_codepage_alist
,
5223 build_string ("iso8859-3"), codepage
);
5224 XSETFASTINT (codepage
, 28592);
5225 store_in_alist (&Vw32_charset_to_codepage_alist
,
5226 build_string ("iso8859-2"), codepage
);
5227 XSETFASTINT (codepage
, 1252);
5228 store_in_alist (&Vw32_charset_to_codepage_alist
,
5229 build_string ("iso8859-1"), codepage
);