1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995 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. */
21 /* Added by Kevin Gallo */
28 #include "blockinput.h"
41 #include "dispextern.h"
42 #include "termhooks.h"
50 #include "intervals.h"
55 #define min(x, y) (((x) < (y)) ? (x) : (y))
56 #define max(x, y) (((x) > (y)) ? (x) : (y))
58 extern void free_frame_menubar ();
60 extern Lisp_Object Vwindow_system
;
62 #define x_any_window_to_frame x_window_to_frame
63 #define x_top_window_to_frame x_window_to_frame
66 /* This is display since w32 does not support multiple ones. */
67 struct w32_display_info one_w32_display_info
;
69 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
70 one for each element of w32_display_list and in the same order.
71 NAME is the name of the frame.
72 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
73 Lisp_Object w32_display_name_list
;
75 /* Frame being updated by update_frame. This is declared in term.c.
76 This is set by update_begin and looked at by all the
77 w32 functions. It is zero while not inside an update.
78 In that case, the w32 functions assume that `selected_frame'
79 is the frame to apply to. */
80 extern struct frame
*updating_frame
;
82 /* This is a frame waiting to be autoraised, within w32_read_socket. */
83 struct frame
*pending_autoraise_frame
;
85 /* During an update, maximum vpos for ins/del line operations to affect. */
89 /* During an update, nonzero if chars output now should be highlighted. */
93 /* Nominal cursor position -- where to draw output.
94 During an update, these are different from the cursor-box position. */
99 DWORD dwWindowsThreadId
= 0;
100 HANDLE hWindowsThread
= NULL
;
101 DWORD dwMainThreadId
= 0;
102 HANDLE hMainThread
= NULL
;
105 /* These definitions are new with Windows 95. */
106 #define SIF_RANGE 0x0001
107 #define SIF_PAGE 0x0002
108 #define SIF_POS 0x0004
109 #define SIF_DISABLENOSCROLL 0x0008
110 #define SIF_TRACKPOS 0x0010
111 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
113 typedef struct tagSCROLLINFO
122 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
123 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
126 /* Dynamic linking to new proportional scroll bar functions. */
127 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
128 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
130 int vertical_scroll_bar_min_handle
;
131 int vertical_scroll_bar_top_border
;
132 int vertical_scroll_bar_bottom_border
;
134 int last_scroll_bar_drag_pos
;
136 /* Mouse movement. */
138 /* Where the mouse was last time we reported a mouse event. */
139 static FRAME_PTR last_mouse_frame
;
140 static RECT last_mouse_glyph
;
142 Lisp_Object Vw32_num_mouse_buttons
;
144 Lisp_Object Vw32_swap_mouse_buttons
;
146 /* Control whether x_raise_frame also sets input focus. */
147 Lisp_Object Vw32_grab_focus_on_raise
;
149 /* Control whether Caps Lock affects non-ascii characters. */
150 Lisp_Object Vw32_capslock_is_shiftlock
;
152 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
153 Lisp_Object Vw32_recognize_altgr
;
155 /* The scroll bar in which the last motion event occurred.
157 If the last motion event occurred in a scroll bar, we set this
158 so w32_mouse_position can know whether to report a scroll bar motion or
161 If the last motion event didn't occur in a scroll bar, we set this
162 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
163 Lisp_Object last_mouse_scroll_bar
;
164 int last_mouse_scroll_bar_pos
;
166 /* This is a hack. We would really prefer that w32_mouse_position would
167 return the time associated with the position it returns, but there
168 doesn't seem to be any way to wrest the timestamp from the server
169 along with the position query. So, we just keep track of the time
170 of the last movement we received, and return that in hopes that
171 it's somewhat accurate. */
172 Time last_mouse_movement_time
;
174 /* Incremented by w32_read_socket whenever it really tries to read events. */
176 static int volatile input_signal_count
;
178 static int input_signal_count
;
181 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
183 extern Lisp_Object Qface
, Qmouse_face
;
187 /* A mask of extra modifier bits to put into every keyboard char. */
188 extern int extra_keyboard_modifiers
;
190 static Lisp_Object Qvendor_specific_keysyms
;
192 void w32_delete_display ();
194 static void redraw_previous_char ();
195 static void redraw_following_char ();
196 static unsigned int w32_get_modifiers ();
198 static int fast_find_position ();
199 static void note_mouse_highlight ();
200 static void clear_mouse_face ();
201 static void show_mouse_face ();
202 static void do_line_dance ();
204 /* Forward declarations for term hooks. Consistency with the rest of Emacs
205 requires the use of K&R functions prototypes. However, MSVC does not
206 pick up the function prototypes correctly with K&R function definitions,
207 and so we declare them first to give a little help to MSVC. */
208 static void w32_clear_frame ();
209 static void w32_clear_end_of_line (int);
210 static void w32_ins_del_lines (int, int);
211 static void w32_change_line_highlight (int, int, int);
212 static void w32_insert_glyphs (GLYPH
*, int);
213 static void w32_write_glyphs (GLYPH
*, int);
214 static void w32_delete_glyphs (int);
215 static void w32_ring_bell ();
216 static void w32_reset_terminal_modes ();
217 static void w32_set_terminal_modes ();
218 static void w32_update_begin (FRAME_PTR
);
219 static void w32_update_end (FRAME_PTR
);
220 static void w32_set_terminal_window (int);
221 extern int w32_read_socket (int, struct input_event
*, int, int);
222 static void w32_frame_up_to_date (FRAME_PTR
);
223 static void w32_cursor_to (int, int);
224 static void w32_reassert_line_highlight (int, int);
225 static void w32_mouse_position (FRAME_PTR
*, int, Lisp_Object
*,
226 enum scroll_bar_part
*, Lisp_Object
*,
227 Lisp_Object
*, unsigned long *);
228 static void w32_frame_rehighlight (FRAME_PTR
);
229 static void w32_frame_raise_lower (FRAME_PTR
, int);
230 static void w32_set_vertical_scroll_bar (struct window
*, int, int, int);
231 static void w32_condemn_scroll_bars (FRAME_PTR
);
232 static void w32_redeem_scroll_bar (struct window
*);
233 static void w32_judge_scroll_bars (FRAME_PTR
);
236 /* This is a function useful for recording debugging information
237 about the sequence of occurrences in this file. */
245 struct record event_record
[100];
247 int event_record_index
;
249 record_event (locus
, type
)
253 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
254 event_record_index
= 0;
256 event_record
[event_record_index
].locus
= locus
;
257 event_record
[event_record_index
].type
= type
;
258 event_record_index
++;
263 /* Return the struct w32_display_info. */
265 struct w32_display_info
*
266 w32_display_info_for_display ()
268 return (&one_w32_display_info
);
272 w32_fill_rect (f
, _hdc
, pix
, lprect
)
287 hdc
= get_frame_dc (f
);
290 hb
= CreateSolidBrush (pix
);
291 FillRect (hdc
, lprect
, hb
);
295 release_frame_dc (f
, hdc
);
304 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
305 w32_clear_rect (f
, NULL
, &rect
);
309 /* Starting and ending updates.
311 These hooks are called by update_frame at the beginning and end
312 of a frame update. We record in `updating_frame' the identity
313 of the frame being updated, so that the w32_... functions do not
314 need to take a frame as argument. Most of the w32_... functions
315 should never be called except during an update, the only exceptions
316 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
325 flexlines
= f
->height
;
330 /* Regenerate display palette before drawing if list of requested
331 colors has changed. */
332 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
334 w32_regenerate_palette (f
);
335 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
338 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
340 /* Don't do highlighting for mouse motion during the update. */
341 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
343 /* If the frame needs to be redrawn,
344 simply forget about any prior mouse highlighting. */
345 if (FRAME_GARBAGED_P (f
))
346 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
348 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
350 int firstline
, lastline
, i
;
351 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
353 /* Find the first, and the last+1, lines affected by redisplay. */
354 for (firstline
= 0; firstline
< f
->height
; firstline
++)
355 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
358 lastline
= f
->height
;
359 for (i
= f
->height
- 1; i
>= 0; i
--)
361 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
367 /* Can we tell that this update does not affect the window
368 where the mouse highlight is? If so, no need to turn off.
369 Likewise, don't do anything if the frame is garbaged;
370 in that case, the FRAME_CURRENT_GLYPHS that we would use
371 are all wrong, and we will redisplay that line anyway. */
372 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
373 || lastline
< XFASTINT (w
->top
)))
374 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
388 x_display_cursor (f
, 1);
390 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
391 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
396 /* This is called after a redisplay on frame F. */
399 w32_frame_up_to_date (f
)
403 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
404 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
406 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
407 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
408 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
409 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
414 /* External interface to control of standout mode.
415 Call this when about to modify line at position VPOS
416 and not change whether it is highlighted. */
419 w32_reassert_line_highlight (new, vpos
)
425 /* Call this when about to modify line at position VPOS
426 and change whether it is highlighted. */
429 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
430 int new_highlight
, vpos
, first_unused_hpos
;
432 highlight
= new_highlight
;
433 w32_cursor_to (vpos
, 0);
434 w32_clear_end_of_line (updating_frame
->width
);
437 /* This is used when starting Emacs and when restarting after suspend.
438 When starting Emacs, no window is mapped. And nothing must be done
439 to Emacs's own window if it is suspended (though that rarely happens). */
442 w32_set_terminal_modes (void)
446 /* This is called when exiting or suspending Emacs.
447 Exiting will make the W32 windows go away, and suspending
448 requires no action. */
451 w32_reset_terminal_modes (void)
455 /* Set the nominal cursor position of the frame.
456 This is where display update commands will take effect.
457 This does not affect the place where the cursor-box is displayed. */
460 w32_cursor_to (row
, col
)
461 register int row
, col
;
468 if (updating_frame
== 0)
471 x_display_cursor (selected_frame
, 1);
476 /* Display a sequence of N glyphs found at GP.
477 WINDOW is the window to output to. LEFT and TOP are starting coords.
478 HL is 1 if this text is highlighted, 2 if the cursor is on it,
479 3 if should appear in its mouse-face.
480 JUST_FOREGROUND if 1 means draw only the foreground;
481 don't alter the background.
483 FONT is the default font to use (for glyphs whose font-code is 0).
485 Since the display generation code is responsible for calling
486 compute_char_face and compute_glyph_face on everything it puts in
487 the display structure, we can assume that the face code on each
488 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
489 to which we can actually apply intern_face.
490 Call this function with input blocked. */
493 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
496 register GLYPH
*gp
; /* Points to first GLYPH. */
497 register int n
; /* Number of glyphs to display. */
500 struct cmpchar_info
*cmpcharp
;
502 /* Holds characters to be displayed. */
503 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
504 register char *cp
; /* Steps through buf[]. */
505 register int tlen
= GLYPH_TABLE_LENGTH
;
506 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
507 Window window
= FRAME_W32_WINDOW (f
);
508 int orig_left
= left
;
511 hdc
= get_frame_dc (f
);
515 /* Get the face-code of the next GLYPH. */
520 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
521 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
522 ch
= FAST_GLYPH_CHAR (g
);
523 charset
= CHAR_CHARSET (ch
);
524 if (charset
== CHARSET_COMPOSITION
)
526 struct face
*face
= FRAME_DEFAULT_FACE (f
);
527 XFontStruct
*font
= FACE_FONT (face
);
528 /* We must draw components of the composite character on the
530 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
532 /* Set the face in the slot for work. */
533 cmpcharp
->face_work
= cf
;
535 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
536 hl
, just_foreground
, cmpcharp
);
537 left
+= FONT_WIDTH (font
) * cmpcharp
->width
;
539 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
543 /* Find the run of consecutive glyphs with the same face-code.
544 Extract their character codes into BUF. */
548 int this_charset
, c
[2];
551 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
552 ch
= FAST_GLYPH_CHAR (g
);
553 SPLIT_CHAR (ch
, this_charset
, c
[0], c
[1]);
554 if (this_charset
!= charset
555 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
560 int consumed
, produced
;
561 /* Handle multibyte characters (still assuming user
562 selects correct font themselves for now */
563 produced
= encode_terminal_code(gp
, cp
, 1,
564 (f
->width
*sizeof(*buf
))-(cp
-buf
), &consumed
);
565 /* If we can't display this glyph, skip it */
569 gp
+= consumed
, n
-= consumed
;
577 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
581 /* LEN gets the length of the run. */
583 /* Now output this run of chars, with the font and pixel values
584 determined by the face code CF. */
587 struct face
*face
= FRAME_DEFAULT_FACE (f
);
588 XFontStruct
*font
= FACE_FONT (face
);
592 /* HL = 3 means use a mouse face previously chosen. */
594 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
596 /* First look at the face of the text itself. */
599 /* It's possible for the display table to specify
600 a face code that is out of range. Use 0 in that case. */
601 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
602 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
606 face
= FRAME_MODE_LINE_FACE (f
);
608 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
609 font
= FACE_FONT (face
);
610 if (FACE_STIPPLE (face
))
614 /* Then comes the distinction between modeline and normal text. */
619 face
= FRAME_MODE_LINE_FACE (f
);
620 font
= FACE_FONT (face
);
621 if (FACE_STIPPLE (face
))
625 fg
= face
->foreground
;
626 bg
= face
->background
;
628 /* Now override that if the cursor's on this character. */
631 /* The cursor overrides stippling. */
635 || face
->font
== (XFontStruct
*) FACE_DEFAULT
636 || face
->font
== f
->output_data
.w32
->font
)
637 && face
->background
== f
->output_data
.w32
->background_pixel
638 && face
->foreground
== f
->output_data
.w32
->foreground_pixel
)
640 bg
= f
->output_data
.w32
->cursor_pixel
;
641 fg
= face
->background
;
643 /* Cursor on non-default face: must merge. */
646 bg
= f
->output_data
.w32
->cursor_pixel
;
647 fg
= face
->background
;
648 /* If the glyph would be invisible,
649 try a different foreground. */
651 fg
= face
->foreground
;
653 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
655 fg
= face
->foreground
;
656 /* Make sure the cursor is distinct from text in this face. */
657 if (bg
== face
->background
658 && fg
== face
->foreground
)
660 bg
= face
->foreground
;
661 fg
= face
->background
;
666 if (font
== (XFontStruct
*) FACE_DEFAULT
)
667 font
= f
->output_data
.w32
->font
;
669 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
671 SetTextColor (hdc
, fg
);
672 SetBkColor (hdc
, bg
);
674 SelectObject (hdc
, font
->hfont
);
676 TextOut (hdc
, left
, top
, buf
, len
);
678 if (!just_foreground
)
680 /* Clear the rest of the line's height. */
681 if (f
->output_data
.w32
->line_height
!= FONT_HEIGHT (font
))
682 w32_fill_area (f
, hdc
, bg
,
684 top
+ FONT_HEIGHT (font
),
685 FONT_WIDTH (font
) * len
,
686 f
->output_data
.w32
->line_height
- FONT_HEIGHT (font
));
690 int underline_position
= 1;
692 if (font
->tm
.tmDescent
<= underline_position
)
693 underline_position
= font
->tm
.tmDescent
- 1;
696 w32_fill_area (f
, hdc
, fg
,
699 + underline_position
),
700 len
* FONT_WIDTH (font
), 1);
703 left
+= len
* FONT_WIDTH (font
);
707 release_frame_dc (f
, hdc
);
711 /* Output some text at the nominal frame cursor position.
712 Advance the cursor over the text.
713 Output LEN glyphs at START.
715 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
716 controls the pixel values used for foreground and background. */
719 w32_write_glyphs (start
, len
)
720 register GLYPH
*start
;
723 register int temp_length
;
733 /* If not within an update,
734 output at the frame's visible cursor. */
735 curs_x
= f
->cursor_x
;
736 curs_y
= f
->cursor_y
;
740 CHAR_TO_PIXEL_COL (f
, curs_x
),
741 CHAR_TO_PIXEL_ROW (f
, curs_y
),
742 start
, len
, highlight
, 0, NULL
);
744 /* If we drew on top of the cursor, note that it is turned off. */
745 if (curs_y
== f
->phys_cursor_y
746 && curs_x
<= f
->phys_cursor_x
747 && curs_x
+ len
> f
->phys_cursor_x
)
748 f
->phys_cursor_x
= -1;
750 if (updating_frame
== 0)
753 x_display_cursor (f
, 1);
762 /* Clear to the end of the line.
763 Erase the current text line from the nominal cursor position (inclusive)
764 to column FIRST_UNUSED (exclusive). The idea is that everything
765 from FIRST_UNUSED onward is already erased. */
768 w32_clear_end_of_line (first_unused
)
769 register int first_unused
;
771 struct frame
*f
= updating_frame
;
776 if (curs_y
< 0 || curs_y
>= f
->height
)
778 if (first_unused
<= 0)
781 if (first_unused
>= f
->width
)
782 first_unused
= f
->width
;
784 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
790 /* Notice if the cursor will be cleared by this operation. */
791 if (curs_y
== f
->phys_cursor_y
792 && curs_x
<= f
->phys_cursor_x
793 && f
->phys_cursor_x
< first_unused
)
794 f
->phys_cursor_x
= -1;
796 w32_clear_area (f
, NULL
,
797 CHAR_TO_PIXEL_COL (f
, curs_x
),
798 CHAR_TO_PIXEL_ROW (f
, curs_y
),
799 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
800 f
->output_data
.w32
->line_height
);
808 struct frame
*f
= updating_frame
;
813 f
->phys_cursor_x
= -1; /* Cursor not visible. */
814 curs_x
= 0; /* Nominal cursor position is top left. */
819 w32_clear_window (f
);
821 /* We have to clear the scroll bars, too. If we have changed
822 colors or something like that, then they should be notified. */
823 x_scroll_bar_clear (f
);
828 /* Make audible bell. */
836 FlashWindow (FRAME_W32_WINDOW (selected_frame
), TRUE
);
838 w32_sys_ring_bell ();
843 /* Insert and delete character.
844 These are not supposed to be used because we are supposed to turn
845 off the feature of using them. */
848 w32_insert_glyphs (start
, len
)
849 register GLYPH
*start
;
856 w32_delete_glyphs (n
)
862 /* Specify how many text lines, from the top of the window,
863 should be affected by insert-lines and delete-lines operations.
864 This, and those operations, are used only within an update
865 that is bounded by calls to w32_update_begin and w32_update_end. */
868 w32_set_terminal_window (n
)
871 if (updating_frame
== 0)
874 if ((n
<= 0) || (n
> updating_frame
->height
))
875 flexlines
= updating_frame
->height
;
880 /* These variables need not be per frame
881 because redisplay is done on a frame-by-frame basis
882 and the line dance for one frame is finished before
883 anything is done for another frame. */
885 /* Array of line numbers from cached insert/delete operations.
886 line_dance[i] is the old position of the line that we want
887 to move to line i, or -1 if we want a blank line there. */
888 static int *line_dance
;
890 /* Allocated length of that array. */
891 static int line_dance_len
;
893 /* Flag indicating whether we've done any work. */
894 static int line_dance_in_progress
;
896 /* Perform an insert-lines or delete-lines operation,
897 inserting N lines or deleting -N lines at vertical position VPOS. */
900 w32_ins_del_lines (vpos
, n
)
903 register int fence
, i
;
905 if (vpos
>= flexlines
)
908 if (!line_dance_in_progress
)
910 int ht
= updating_frame
->height
;
911 if (ht
> line_dance_len
)
913 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
916 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
917 line_dance_in_progress
= 1;
921 if (n
> flexlines
- vpos
)
922 n
= flexlines
- vpos
;
924 for (i
= flexlines
; --i
>= fence
;)
925 line_dance
[i
] = line_dance
[i
-n
];
926 for (i
= fence
; --i
>= vpos
;)
932 if (n
> flexlines
- vpos
)
933 n
= flexlines
- vpos
;
934 fence
= flexlines
- n
;
935 for (i
= vpos
; i
< fence
; ++i
)
936 line_dance
[i
] = line_dance
[i
+ n
];
937 for (i
= fence
; i
< flexlines
; ++i
)
942 /* Here's where we actually move the pixels around.
943 Must be called with input blocked. */
947 register int i
, j
, distance
;
948 register struct frame
*f
;
953 /* Must check this flag first. If it's not set, then not only is the
954 array uninitialized, but we might not even have a frame. */
955 if (!line_dance_in_progress
)
963 intborder
= f
->output_data
.w32
->internal_border_width
;
965 x_display_cursor (updating_frame
, 0);
967 hdc
= get_frame_dc (f
);
969 for (i
= 0; i
< ht
; ++i
)
970 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
972 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
973 && line_dance
[j
]-j
== distance
); ++j
);
974 /* Copy [i,j) upward from [i+distance, j+distance) */
976 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
977 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
978 (j
-i
) * f
->output_data
.w32
->line_height
,
980 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
985 for (i
= ht
; --i
>=0; )
986 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
988 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
989 && line_dance
[j
]-j
== distance
););
990 /* Copy (j, i] downward from (j+distance, i+distance] */
992 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
993 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
994 (i
-j
) * f
->output_data
.w32
->line_height
,
996 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1001 for (i
= 0; i
< ht
; ++i
)
1002 if (line_dance
[i
] == -1)
1004 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1006 w32_clear_area (f
, hdc
,
1008 CHAR_TO_PIXEL_ROW (f
, i
),
1009 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1010 (j
-i
) * f
->output_data
.w32
->line_height
);
1013 line_dance_in_progress
= 0;
1015 release_frame_dc (f
, hdc
);
1018 /* Support routines for exposure events. */
1019 static void clear_cursor ();
1021 /* Output into a rectangle of a window (for frame F)
1022 the characters in f->phys_lines that overlap that rectangle.
1023 TOP and LEFT are the position of the upper left corner of the rectangle.
1024 ROWS and COLS are the size of the rectangle.
1025 Call this function with input blocked. */
1028 dumprectangle (f
, left
, top
, cols
, rows
)
1030 register int left
, top
, cols
, rows
;
1032 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1033 int cursor_cleared
= 0;
1037 if (FRAME_GARBAGED_P (f
))
1040 /* Express rectangle as four edges, instead of position-and-size. */
1041 bottom
= top
+ rows
;
1042 right
= left
+ cols
;
1044 /* Convert rectangle edges in pixels to edges in chars.
1045 Round down for left and top, up for right and bottom. */
1046 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1047 left
= PIXEL_TO_CHAR_COL (f
, left
);
1048 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1049 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1050 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1051 right
= PIXEL_TO_CHAR_COL (f
, right
);
1053 /* Clip the rectangle to what can be visible. */
1058 if (right
> f
->width
)
1060 if (bottom
> f
->height
)
1063 /* Get size in chars of the rectangle. */
1064 cols
= right
- left
;
1065 rows
= bottom
- top
;
1067 /* If rectangle has zero area, return. */
1068 if (rows
<= 0) return;
1069 if (cols
<= 0) return;
1071 /* Turn off the cursor if it is in the rectangle.
1072 We will turn it back on afterward. */
1073 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1074 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1080 /* Display the text in the rectangle, one text line at a time. */
1082 for (y
= top
; y
< bottom
; y
++)
1084 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1086 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1090 CHAR_TO_PIXEL_COL (f
, left
),
1091 CHAR_TO_PIXEL_ROW (f
, y
),
1092 line
, min (cols
, active_frame
->used
[y
] - left
),
1093 active_frame
->highlight
[y
], 0, NULL
);
1096 /* Turn the cursor on if we turned it off. */
1099 x_display_cursor (f
, 1);
1106 x_display_cursor (f
, 1);
1110 frame_unhighlight (f
)
1113 x_display_cursor (f
, 1);
1116 static void x_frame_rehighlight ();
1118 /* The focus has changed. Update the frames as necessary to reflect
1119 the new situation. Note that we can't change the selected frame
1120 here, because the Lisp code we are interrupting might become confused.
1121 Each event gets marked with the frame in which it occurred, so the
1122 Lisp code can tell when the switch took place by examining the events. */
1125 x_new_focus_frame (dpyinfo
, frame
)
1126 struct w32_display_info
*dpyinfo
;
1127 struct frame
*frame
;
1129 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1130 int events_enqueued
= 0;
1132 if (frame
!= dpyinfo
->w32_focus_frame
)
1134 /* Set this before calling other routines, so that they see
1135 the correct value of w32_focus_frame. */
1136 dpyinfo
->w32_focus_frame
= frame
;
1138 if (old_focus
&& old_focus
->auto_lower
)
1139 x_lower_frame (old_focus
);
1141 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1142 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1144 pending_autoraise_frame
= 0;
1147 x_frame_rehighlight (dpyinfo
);
1150 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1153 x_mouse_leave (dpyinfo
)
1154 struct w32_display_info
*dpyinfo
;
1156 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1159 /* The focus has changed, or we have redirected a frame's focus to
1160 another frame (this happens when a frame uses a surrogate
1161 minibuffer frame). Shift the highlight as appropriate.
1163 The FRAME argument doesn't necessarily have anything to do with which
1164 frame is being highlighted or unhighlighted; we only use it to find
1165 the appropriate display info. */
1167 w32_frame_rehighlight (frame
)
1168 struct frame
*frame
;
1170 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1174 x_frame_rehighlight (dpyinfo
)
1175 struct w32_display_info
*dpyinfo
;
1177 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1179 if (dpyinfo
->w32_focus_frame
)
1181 dpyinfo
->w32_highlight_frame
1182 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1183 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1184 : dpyinfo
->w32_focus_frame
);
1185 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1187 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1188 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1192 dpyinfo
->w32_highlight_frame
= 0;
1194 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1197 frame_unhighlight (old_highlight
);
1198 if (dpyinfo
->w32_highlight_frame
)
1199 frame_highlight (dpyinfo
->w32_highlight_frame
);
1203 /* Keyboard processing - modifier keys, etc. */
1205 /* Convert a keysym to its name. */
1208 x_get_keysym_name (keysym
)
1211 /* Make static so we can always return it */
1212 static char value
[100];
1215 GetKeyNameText(keysym
, value
, 100);
1221 /* Mouse clicks and mouse movement. Rah. */
1223 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1224 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1225 that the glyph at X, Y occupies, if BOUNDS != 0.
1226 If NOCLIP is nonzero, do not force the value into range. */
1229 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1231 register int pix_x
, pix_y
;
1232 register int *x
, *y
;
1236 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1237 if (NILP (Vwindow_system
))
1244 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1245 even for negative values. */
1247 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1249 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1251 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1252 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1256 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1257 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1258 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1259 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1266 else if (pix_x
> f
->width
)
1271 else if (pix_y
> f
->height
)
1280 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1283 register int *pix_x
, *pix_y
;
1285 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1286 if (NILP (Vwindow_system
))
1293 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1294 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1298 parse_button (message
, pbutton
, pup
)
1308 case WM_LBUTTONDOWN
:
1316 case WM_MBUTTONDOWN
:
1317 if (NILP (Vw32_swap_mouse_buttons
))
1324 if (NILP (Vw32_swap_mouse_buttons
))
1330 case WM_RBUTTONDOWN
:
1331 if (NILP (Vw32_swap_mouse_buttons
))
1338 if (NILP (Vw32_swap_mouse_buttons
))
1349 if (pbutton
) *pbutton
= button
;
1355 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1357 If the event is a button press, then note that we have grabbed
1361 construct_mouse_click (result
, msg
, f
)
1362 struct input_event
*result
;
1369 parse_button (msg
->msg
.message
, &button
, &up
);
1371 /* Make the event type no_event; we'll change that when we decide
1373 result
->kind
= mouse_click
;
1374 result
->code
= button
;
1375 result
->timestamp
= msg
->msg
.time
;
1376 result
->modifiers
= (msg
->dwModifiers
1384 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1385 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1386 XSETFRAME (result
->frame_or_window
, f
);
1391 construct_mouse_wheel (result
, msg
, f
)
1392 struct input_event
*result
;
1397 result
->kind
= mouse_wheel
;
1398 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1399 result
->timestamp
= msg
->msg
.time
;
1400 result
->modifiers
= msg
->dwModifiers
;
1401 p
.x
= LOWORD (msg
->msg
.lParam
);
1402 p
.y
= HIWORD (msg
->msg
.lParam
);
1403 ScreenToClient(msg
->msg
.hwnd
, &p
);
1404 XSETINT (result
->x
, p
.x
);
1405 XSETINT (result
->y
, p
.y
);
1406 XSETFRAME (result
->frame_or_window
, f
);
1410 /* Function to report a mouse movement to the mainstream Emacs code.
1411 The input handler calls this.
1413 We have received a mouse movement event, which is given in *event.
1414 If the mouse is over a different glyph than it was last time, tell
1415 the mainstream emacs code by setting mouse_moved. If not, ask for
1416 another motion event, so we can check again the next time it moves. */
1419 note_mouse_movement (frame
, msg
)
1423 last_mouse_movement_time
= msg
->time
;
1425 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
1427 frame
->mouse_moved
= 1;
1428 last_mouse_scroll_bar
= Qnil
;
1430 note_mouse_highlight (frame
, -1, -1);
1433 /* Has the mouse moved off the glyph it was on at the last sighting? */
1434 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1435 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1436 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
1437 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1439 frame
->mouse_moved
= 1;
1440 last_mouse_scroll_bar
= Qnil
;
1442 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1446 /* This is used for debugging, to turn off note_mouse_highlight. */
1447 static int disable_mouse_highlight
;
1449 /* Take proper action when the mouse has moved to position X, Y on frame F
1450 as regards highlighting characters that have mouse-face properties.
1451 Also dehighlighting chars where the mouse was before.
1452 X and Y can be negative or out of range. */
1455 note_mouse_highlight (f
, x
, y
)
1459 int row
, column
, portion
;
1464 if (disable_mouse_highlight
)
1467 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1468 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1469 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1471 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
1476 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1480 /* Find out which glyph the mouse is on. */
1481 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1482 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
1484 /* Which window is that in? */
1485 window
= window_from_coordinates (f
, column
, row
, &portion
);
1486 w
= XWINDOW (window
);
1488 /* If we were displaying active text in another window, clear that. */
1489 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
1490 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1492 /* Are we in a window whose display is up to date?
1493 And verify the buffer's text has not changed. */
1494 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1495 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1496 && EQ (w
->window_end_valid
, w
->buffer
)
1497 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
1498 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
1500 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1503 /* Find which buffer position the mouse corresponds to. */
1504 for (i
= column
; i
>= 0; i
--)
1508 /* Is it outside the displayed active region (if any)? */
1510 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1511 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
1512 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1513 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1514 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1515 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1516 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1517 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1518 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1520 Lisp_Object mouse_face
, overlay
, position
;
1521 Lisp_Object
*overlay_vec
;
1522 int len
, noverlays
, ignor1
;
1523 struct buffer
*obuf
;
1526 /* If we get an out-of-range value, return now; avoid an error. */
1527 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1530 /* Make the window's buffer temporarily current for
1531 overlays_at and compute_char_face. */
1532 obuf
= current_buffer
;
1533 current_buffer
= XBUFFER (w
->buffer
);
1539 /* Yes. Clear the display of the old active region, if any. */
1540 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1542 /* Is this char mouse-active? */
1543 XSETINT (position
, pos
);
1546 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1548 /* Put all the overlays we want in a vector in overlay_vec.
1549 Store the length in len. */
1550 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1552 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1554 /* Find the highest priority overlay that has a mouse-face prop. */
1556 for (i
= 0; i
< noverlays
; i
++)
1558 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1559 if (!NILP (mouse_face
))
1561 overlay
= overlay_vec
[i
];
1566 /* If no overlay applies, get a text property. */
1568 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1570 /* Handle the overlay case. */
1571 if (! NILP (overlay
))
1573 /* Find the range of text around this char that
1574 should be active. */
1575 Lisp_Object before
, after
;
1578 before
= Foverlay_start (overlay
);
1579 after
= Foverlay_end (overlay
);
1580 /* Record this as the current active region. */
1581 fast_find_position (window
, before
,
1582 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1583 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1584 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1585 = !fast_find_position (window
, after
,
1586 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1587 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1588 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1589 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1590 = compute_char_face (f
, w
, pos
, 0, 0,
1591 &ignore
, pos
+ 1, 1);
1593 /* Display it as active. */
1594 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1596 /* Handle the text property case. */
1597 else if (! NILP (mouse_face
))
1599 /* Find the range of text around this char that
1600 should be active. */
1601 Lisp_Object before
, after
, beginning
, end
;
1604 beginning
= Fmarker_position (w
->start
);
1605 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1606 - XFASTINT (w
->window_end_pos
)));
1608 = Fprevious_single_property_change (make_number (pos
+ 1),
1610 w
->buffer
, beginning
);
1612 = Fnext_single_property_change (position
, Qmouse_face
,
1614 /* Record this as the current active region. */
1615 fast_find_position (window
, before
,
1616 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1617 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1618 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1619 = !fast_find_position (window
, after
,
1620 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1621 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1622 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1623 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1624 = compute_char_face (f
, w
, pos
, 0, 0,
1625 &ignore
, pos
+ 1, 1);
1627 /* Display it as active. */
1628 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1632 current_buffer
= obuf
;
1637 /* Find the row and column of position POS in window WINDOW.
1638 Store them in *COLUMNP and *ROWP.
1639 This assumes display in WINDOW is up to date.
1640 If POS is above start of WINDOW, return coords
1641 of start of first screen line.
1642 If POS is after end of WINDOW, return coords of end of last screen line.
1644 Value is 1 if POS is in range, 0 if it was off screen. */
1647 fast_find_position (window
, pos
, columnp
, rowp
)
1650 int *columnp
, *rowp
;
1652 struct window
*w
= XWINDOW (window
);
1653 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1656 int left
= WINDOW_LEFT_MARGIN (w
);
1658 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1659 int width
= window_internal_width (w
);
1662 int maybe_next_line
= 0;
1664 /* Find the right row. */
1669 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1670 if (linestart
> pos
)
1672 /* If the position sought is the end of the buffer,
1673 don't include the blank lines at the bottom of the window. */
1674 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1676 maybe_next_line
= 1;
1683 /* Find the right column with in it. */
1684 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1686 for (i
= 0; i
< width
; i
++)
1688 if (charstarts
[left
+ i
] == pos
)
1691 *columnp
= i
+ left
;
1694 else if (charstarts
[left
+ i
] > pos
)
1696 else if (charstarts
[left
+ i
] > 0)
1700 /* If we're looking for the end of the buffer,
1701 and we didn't find it in the line we scanned,
1702 use the start of the following line. */
1703 if (maybe_next_line
)
1714 /* Display the active region described by mouse_face_*
1715 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1718 show_mouse_face (dpyinfo
, hl
)
1719 struct w32_display_info
*dpyinfo
;
1722 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1723 int width
= window_internal_width (w
);
1724 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1727 int old_curs_x
= curs_x
;
1728 int old_curs_y
= curs_y
;
1730 /* Set these variables temporarily
1731 so that if we have to turn the cursor off and on again
1732 we will put it back at the same place. */
1733 curs_x
= f
->phys_cursor_x
;
1734 curs_y
= f
->phys_cursor_y
;
1736 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1737 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1739 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1740 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
1741 : WINDOW_LEFT_MARGIN (w
));
1742 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1743 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1744 : WINDOW_LEFT_MARGIN (w
) + width
);
1745 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1747 /* If the cursor's in the text we are about to rewrite,
1748 turn the cursor off. */
1750 && curs_x
>= column
- 1
1751 && curs_x
<= endcolumn
)
1753 x_display_cursor (f
, 0);
1758 CHAR_TO_PIXEL_COL (f
, column
),
1759 CHAR_TO_PIXEL_ROW (f
, i
),
1760 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1762 /* Highlight with mouse face if hl > 0. */
1763 hl
> 0 ? 3 : 0, 0, NULL
);
1766 /* If we turned the cursor off, turn it back on. */
1768 x_display_cursor (f
, 1);
1770 curs_x
= old_curs_x
;
1771 curs_y
= old_curs_y
;
1773 /* Change the mouse cursor according to the value of HL. */
1775 SetCursor (f
->output_data
.w32
->cross_cursor
);
1777 SetCursor (f
->output_data
.w32
->text_cursor
);
1780 /* Clear out the mouse-highlighted active region.
1781 Redraw it unhighlighted first. */
1784 clear_mouse_face (dpyinfo
)
1785 struct w32_display_info
*dpyinfo
;
1787 if (! NILP (dpyinfo
->mouse_face_window
))
1788 show_mouse_face (dpyinfo
, 0);
1790 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1791 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1792 dpyinfo
->mouse_face_window
= Qnil
;
1795 struct scroll_bar
*x_window_to_scroll_bar ();
1796 static void x_scroll_bar_report_motion ();
1798 /* Return the current position of the mouse.
1799 *fp should be a frame which indicates which display to ask about.
1801 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1802 and *part to the frame, window, and scroll bar part that the mouse
1803 is over. Set *x and *y to the portion and whole of the mouse's
1804 position on the scroll bar.
1806 If the mouse movement started elsewhere, set *fp to the frame the
1807 mouse is on, *bar_window to nil, and *x and *y to the character cell
1810 Set *time to the server timestamp for the time at which the mouse
1811 was at this position.
1813 Don't store anything if we don't have a valid set of values to report.
1815 This clears the mouse_moved flag, so we can wait for the next mouse
1816 movement. This also calls XQueryPointer, which will cause the
1817 server to give us another MotionNotify when the mouse moves
1821 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1824 Lisp_Object
*bar_window
;
1825 enum scroll_bar_part
*part
;
1827 unsigned long *time
;
1833 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
1834 /* This is never called at the moment. */
1835 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1840 Lisp_Object frame
, tail
;
1842 /* Clear the mouse-moved flag for every frame on this display. */
1843 FOR_EACH_FRAME (tail
, frame
)
1844 XFRAME (frame
)->mouse_moved
= 0;
1846 last_mouse_scroll_bar
= Qnil
;
1850 /* Now we have a position on the root; find the innermost window
1851 containing the pointer. */
1853 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1854 && FRAME_LIVE_P (last_mouse_frame
))
1856 f1
= last_mouse_frame
;
1860 /* Is win one of our frames? */
1861 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1864 /* If not, is it one of our scroll bars? */
1867 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1871 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1875 if (f1
== 0 && insist
> 0)
1876 f1
= selected_frame
;
1880 int ignore1
, ignore2
;
1882 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
1884 /* Ok, we found a frame. Store all the values. */
1886 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1888 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
1896 *time
= last_mouse_movement_time
;
1904 /* Scroll bar support. */
1906 /* Given an window ID, find the struct scroll_bar which manages it.
1907 This can be called in GC, so we have to make sure to strip off mark
1910 x_window_to_scroll_bar (window_id
)
1913 Lisp_Object tail
, frame
;
1915 for (tail
= Vframe_list
;
1916 XGCTYPE (tail
) == Lisp_Cons
;
1917 tail
= XCONS (tail
)->cdr
)
1919 Lisp_Object frame
, bar
, condemned
;
1921 frame
= XCONS (tail
)->car
;
1922 /* All elements of Vframe_list should be frames. */
1923 if (! GC_FRAMEP (frame
))
1926 /* Scan this frame's scroll bar list for a scroll bar with the
1928 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1929 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1930 /* This trick allows us to search both the ordinary and
1931 condemned scroll bar lists with one loop. */
1932 ! GC_NILP (bar
) || (bar
= condemned
,
1935 bar
= XSCROLL_BAR (bar
)->next
)
1936 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1937 return XSCROLL_BAR (bar
);
1944 my_create_scrollbar (f
, bar
)
1946 struct scroll_bar
* bar
;
1948 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
1949 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1953 //#define ATTACH_THREADS
1956 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
1958 #ifndef ATTACH_THREADS
1959 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
1960 (WPARAM
) hwnd
, (LPARAM
) how
);
1962 return ShowWindow (hwnd
, how
);
1967 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
1968 int x
, int y
, int cx
, int cy
, UINT flags
)
1970 #ifndef ATTACH_THREADS
1972 pos
.hwndInsertAfter
= hwndAfter
;
1978 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
1980 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1985 my_set_focus (f
, hwnd
)
1989 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
1994 my_set_foreground_window (hwnd
)
1997 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2001 my_destroy_window (f
, hwnd
)
2005 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2009 /* Open a new window to serve as a scroll bar, and return the
2010 scroll bar vector for it. */
2011 static struct scroll_bar
*
2012 x_scroll_bar_create (window
, top
, left
, width
, height
)
2013 struct window
*window
;
2014 int top
, left
, width
, height
;
2016 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2017 struct scroll_bar
*bar
2018 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2023 XSETWINDOW (bar
->window
, window
);
2024 XSETINT (bar
->top
, top
);
2025 XSETINT (bar
->left
, left
);
2026 XSETINT (bar
->width
, width
);
2027 XSETINT (bar
->height
, height
);
2028 XSETINT (bar
->start
, 0);
2029 XSETINT (bar
->end
, 0);
2030 bar
->dragging
= Qnil
;
2032 /* Requires geometry to be set before call to create the real window */
2034 hwnd
= my_create_scrollbar (f
, bar
);
2036 if (pfnSetScrollInfo
)
2040 si
.cbSize
= sizeof (si
);
2043 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2044 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2048 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2052 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2053 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2056 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2058 /* Add bar to its frame's list of scroll bars. */
2059 bar
->next
= FRAME_SCROLL_BARS (f
);
2061 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2062 if (! NILP (bar
->next
))
2063 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2070 /* Draw BAR's handle in the proper position.
2071 If the handle is already drawn from START to END, don't bother
2072 redrawing it, unless REBUILD is non-zero; in that case, always
2073 redraw it. (REBUILD is handy for drawing the handle after expose
2076 Normally, we want to constrain the start and end of the handle to
2077 fit inside its rectangle, but if the user is dragging the scroll bar
2078 handle, we want to let them drag it down all the way, so that the
2079 bar's top is as far down as it goes; otherwise, there's no way to
2080 move to the very end of the buffer. */
2082 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2083 struct scroll_bar
*bar
;
2087 int dragging
= ! NILP (bar
->dragging
);
2088 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2089 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2091 /* If the display is already accurate, do nothing. */
2093 && start
== XINT (bar
->start
)
2094 && end
== XINT (bar
->end
))
2100 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2102 /* Make sure the values are reasonable, and try to preserve
2103 the distance between start and end. */
2105 int length
= end
- start
;
2109 else if (start
> top_range
)
2111 end
= start
+ length
;
2115 else if (end
> top_range
&& ! dragging
)
2120 /* Store the adjusted setting in the scroll bar. */
2121 XSETINT (bar
->start
, start
);
2122 XSETINT (bar
->end
, end
);
2124 /* If being dragged, let scroll bar update itself. */
2127 if (pfnSetScrollInfo
)
2131 si
.cbSize
= sizeof (si
);
2132 si
.fMask
= SIF_PAGE
| SIF_POS
;
2133 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2136 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2139 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2145 /* Move a scroll bar around on the screen, to accommodate changing
2146 window configurations. */
2148 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2149 struct scroll_bar
*bar
;
2150 int top
, left
, width
, height
;
2152 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2153 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2155 /* If already correctly positioned, do nothing. */
2156 if ( XINT (bar
->left
) == left
2157 && XINT (bar
->top
) == top
2158 && XINT (bar
->width
) == width
2159 && XINT (bar
->height
) == height
)
2161 /* Redraw after clear_frame. */
2162 if (!my_show_window (f
, w
, SW_NORMAL
))
2163 InvalidateRect (w
, NULL
, FALSE
);
2169 /* Make sure scroll bar is "visible" before moving, to ensure the
2170 area of the parent window now exposed will be refreshed. */
2171 my_show_window (f
, w
, SW_HIDE
);
2172 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2173 if (pfnSetScrollInfo
)
2177 si
.cbSize
= sizeof (si
);
2178 si
.fMask
= SIF_RANGE
;
2180 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2181 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2183 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2186 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2187 my_show_window (f
, w
, SW_NORMAL
);
2188 // InvalidateRect (w, NULL, FALSE);
2190 XSETINT (bar
->left
, left
);
2191 XSETINT (bar
->top
, top
);
2192 XSETINT (bar
->width
, width
);
2193 XSETINT (bar
->height
, height
);
2198 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2201 x_scroll_bar_remove (bar
)
2202 struct scroll_bar
*bar
;
2204 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2208 /* Destroy the window. */
2209 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2211 /* Disassociate this scroll bar from its window. */
2212 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2217 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2218 that we are displaying PORTION characters out of a total of WHOLE
2219 characters, starting at POSITION. If WINDOW has no scroll bar,
2222 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2223 struct window
*window
;
2224 int portion
, whole
, position
;
2226 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2227 int top
= XINT (window
->top
);
2228 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2229 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2231 /* Where should this scroll bar be, pixelwise? */
2232 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2233 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2235 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2236 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2237 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2238 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2240 struct scroll_bar
*bar
;
2242 /* Does the scroll bar exist yet? */
2243 if (NILP (window
->vertical_scroll_bar
))
2244 bar
= x_scroll_bar_create (window
,
2245 pixel_top
, pixel_left
,
2246 pixel_width
, pixel_height
);
2249 /* It may just need to be moved and resized. */
2250 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2251 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2254 /* Set the scroll bar's current state. */
2256 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2259 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2262 int start
= (int) (((double) position
* top_range
) / whole
);
2263 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2265 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2269 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2273 /* The following three hooks are used when we're doing a thorough
2274 redisplay of the frame. We don't explicitly know which scroll bars
2275 are going to be deleted, because keeping track of when windows go
2276 away is a real pain - "Can you say set-window-configuration, boys
2277 and girls?" Instead, we just assert at the beginning of redisplay
2278 that *all* scroll bars are to be removed, and then save a scroll bar
2279 from the fiery pit when we actually redisplay its window. */
2281 /* Arrange for all scroll bars on FRAME to be removed at the next call
2282 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2283 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2285 w32_condemn_scroll_bars (frame
)
2288 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2289 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2292 bar
= FRAME_SCROLL_BARS (frame
);
2293 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2294 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2295 XSCROLL_BAR (bar
)->prev
= Qnil
;
2296 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2297 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2298 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2301 /* The condemned list should be empty at this point; if it's not,
2302 then the rest of Emacs isn't using the condemn/redeem/judge
2303 protocol correctly. */
2304 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2307 /* Move them all to the "condemned" list. */
2308 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2309 FRAME_SCROLL_BARS (frame
) = Qnil
;
2313 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2314 Note that WINDOW isn't necessarily condemned at all. */
2316 w32_redeem_scroll_bar (window
)
2317 struct window
*window
;
2319 struct scroll_bar
*bar
;
2321 /* We can't redeem this window's scroll bar if it doesn't have one. */
2322 if (NILP (window
->vertical_scroll_bar
))
2325 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2327 /* Unlink it from the condemned list. */
2329 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2331 if (NILP (bar
->prev
))
2333 /* If the prev pointer is nil, it must be the first in one of
2335 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2336 /* It's not condemned. Everything's fine. */
2338 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2339 window
->vertical_scroll_bar
))
2340 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2342 /* If its prev pointer is nil, it must be at the front of
2343 one or the other! */
2347 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2349 if (! NILP (bar
->next
))
2350 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2352 bar
->next
= FRAME_SCROLL_BARS (f
);
2354 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2355 if (! NILP (bar
->next
))
2356 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2359 struct scroll_bar
*bar
;
2361 /* We can't redeem this window's scroll bar if it doesn't have one. */
2362 if (NILP (window
->vertical_scroll_bar
))
2365 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2367 /* Unlink it from the condemned list. */
2369 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2371 if (NILP (bar
->prev
))
2373 /* If the prev pointer is nil, it must be the first in one of
2375 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2376 /* It's not condemned. Everything's fine. */
2378 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2379 window
->vertical_scroll_bar
))
2380 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2382 /* If its prev pointer is nil, it must be at the front of
2383 one or the other! */
2387 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2389 if (! NILP (bar
->next
))
2390 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2392 bar
->next
= FRAME_SCROLL_BARS (f
);
2394 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2395 if (! NILP (bar
->next
))
2396 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2401 /* Remove all scroll bars on FRAME that haven't been saved since the
2402 last call to `*condemn_scroll_bars_hook'. */
2404 w32_judge_scroll_bars (f
)
2407 Lisp_Object bar
, next
;
2409 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2411 /* Clear out the condemned list now so we won't try to process any
2412 more events on the hapless scroll bars. */
2413 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2415 for (; ! NILP (bar
); bar
= next
)
2417 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2419 x_scroll_bar_remove (b
);
2422 b
->next
= b
->prev
= Qnil
;
2425 /* Now there should be no references to the condemned scroll bars,
2426 and they should get garbage-collected. */
2428 Lisp_Object bar
, next
;
2430 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2432 /* Clear out the condemned list now so we won't try to process any
2433 more events on the hapless scroll bars. */
2434 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2436 for (; ! NILP (bar
); bar
= next
)
2438 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2440 x_scroll_bar_remove (b
);
2443 b
->next
= b
->prev
= Qnil
;
2446 /* Now there should be no references to the condemned scroll bars,
2447 and they should get garbage-collected. */
2451 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2452 is set to something other than no_event, it is enqueued.
2454 This may be called from a signal handler, so we have to ignore GC
2458 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2459 struct scroll_bar
*bar
;
2461 struct input_event
*emacs_event
;
2463 if (! GC_WINDOWP (bar
->window
))
2466 emacs_event
->kind
= w32_scroll_bar_click
;
2467 emacs_event
->code
= 0;
2468 /* not really meaningful to distinguish up/down */
2469 emacs_event
->modifiers
= msg
->dwModifiers
;
2470 emacs_event
->frame_or_window
= bar
->window
;
2471 emacs_event
->timestamp
= msg
->msg
.time
;
2474 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2476 int dragging
= !NILP (bar
->dragging
);
2478 if (pfnGetScrollInfo
)
2482 si
.cbSize
= sizeof (si
);
2485 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
2489 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2491 bar
->dragging
= Qnil
;
2493 switch (LOWORD (msg
->msg
.wParam
))
2496 emacs_event
->part
= scroll_bar_down_arrow
;
2499 emacs_event
->part
= scroll_bar_up_arrow
;
2502 emacs_event
->part
= scroll_bar_above_handle
;
2505 emacs_event
->part
= scroll_bar_below_handle
;
2508 emacs_event
->part
= scroll_bar_handle
;
2512 emacs_event
->part
= scroll_bar_handle
;
2516 case SB_THUMBPOSITION
:
2517 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2518 y
= HIWORD (msg
->msg
.wParam
);
2520 emacs_event
->part
= scroll_bar_handle
;
2522 /* "Silently" update current position. */
2523 if (pfnSetScrollInfo
)
2527 si
.cbSize
= sizeof (si
);
2531 /* Shrink handle if necessary to allow full range for position. */
2533 int start
= XINT (bar
->start
);
2534 int end
= XINT (bar
->end
);
2535 int len
= end
- start
;
2537 /* If new end is nearly hitting bottom, we must shrink
2538 handle. How much we shrink it depends on the relative
2539 sizes of len and top_range. */
2540 if (y
+ len
> top_range
- 2)
2542 len
-= min (top_range
/ 10, (len
/ 3) + 2);
2546 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2547 si
.fMask
|= SIF_PAGE
;
2551 /* Remember apparent position (we actually lag behind the real
2552 position, so don't set that directly. */
2553 last_scroll_bar_drag_pos
= y
;
2555 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
2558 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
2561 /* If this is the end of a drag sequence, then reset the scroll
2562 handle size to normal and do a final redraw. Otherwise do
2566 if (pfnSetScrollInfo
)
2569 int start
= XINT (bar
->start
);
2570 int end
= XINT (bar
->end
);
2572 si
.cbSize
= sizeof (si
);
2573 si
.fMask
= SIF_PAGE
| SIF_POS
;
2574 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2575 si
.nPos
= last_scroll_bar_drag_pos
;
2577 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
2580 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
2584 emacs_event
->kind
= no_event
;
2588 XSETINT (emacs_event
->x
, y
);
2589 XSETINT (emacs_event
->y
, top_range
);
2595 /* Return information to the user about the current position of the mouse
2596 on the scroll bar. */
2598 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2600 Lisp_Object
*bar_window
;
2601 enum scroll_bar_part
*part
;
2603 unsigned long *time
;
2605 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2606 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2607 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2609 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2614 *bar_window
= bar
->window
;
2616 if (pfnGetScrollInfo
)
2620 si
.cbSize
= sizeof (si
);
2621 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
2623 pfnGetScrollInfo (w
, SB_CTL
, &si
);
2625 top_range
= si
.nMax
- si
.nPage
+ 1;
2628 pos
= GetScrollPos (w
, SB_CTL
);
2630 switch (LOWORD (last_mouse_scroll_bar_pos
))
2632 case SB_THUMBPOSITION
:
2634 *part
= scroll_bar_handle
;
2635 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2636 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2639 *part
= scroll_bar_handle
;
2643 *part
= scroll_bar_handle
;
2648 XSETINT(*y
, top_range
);
2651 last_mouse_scroll_bar
= Qnil
;
2653 *time
= last_mouse_movement_time
;
2658 /* The screen has been cleared so we may have changed foreground or
2659 background colors, and the scroll bars may need to be redrawn.
2660 Clear out the scroll bars, and ask for expose events, so we can
2663 x_scroll_bar_clear (f
)
2668 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2669 bar
= XSCROLL_BAR (bar
)->next
)
2671 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2672 HDC hdc
= GetDC (window
);
2675 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
2676 arranges to refresh the scroll bar if hidden. */
2677 my_show_window (f
, window
, SW_HIDE
);
2679 GetClientRect (window
, &rect
);
2680 select_palette (f
, hdc
);
2681 w32_clear_rect (f
, hdc
, &rect
);
2682 deselect_palette (f
, hdc
);
2684 ReleaseDC (window
, hdc
);
2688 show_scroll_bars (f
, how
)
2694 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2695 bar
= XSCROLL_BAR (bar
)->next
)
2697 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2698 my_show_window (f
, window
, how
);
2703 /* The main W32 event-reading loop - w32_read_socket. */
2705 /* Timestamp of enter window event. This is only used by w32_read_socket,
2706 but we have to put it out here, since static variables within functions
2707 sometimes don't work. */
2708 static Time enter_timestamp
;
2710 /* Record the last 100 characters stored
2711 to help debug the loss-of-chars-during-GC problem. */
2713 short temp_buffer
[100];
2715 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*, int *isdead
);
2717 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
2718 we can use the same routines to handle input in both console
2719 and window modes. */
2722 convert_to_key_event (W32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2724 eventp
->bKeyDown
= TRUE
;
2725 eventp
->wRepeatCount
= 1;
2726 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2727 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2728 eventp
->uChar
.AsciiChar
= 0;
2729 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2732 /* Return nonzero if the virtual key is a dead key. */
2735 is_dead_key (int wparam
)
2737 unsigned int code
= MapVirtualKey (wparam
, 2);
2739 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2740 if ((code
& 0x8000) || (code
& 0x80000000))
2746 /* Read events coming from the W32 shell.
2747 This routine is called by the SIGIO handler.
2748 We return as soon as there are no more events to be read.
2750 Events representing keys are stored in buffer BUFP,
2751 which can hold up to NUMCHARS characters.
2752 We return the number of characters stored into the buffer,
2753 thus pretending to be `read'.
2755 EXPECTED is nonzero if the caller knows input is available.
2757 Some of these messages are reposted back to the message queue since the
2758 system calls the windows proc directly in a context where we cannot return
2759 the data nor can we guarantee the state we are in. So if we dispatch them
2760 we will get into an infinite loop. To prevent this from ever happening we
2761 will set a variable to indicate we are in the read_socket call and indicate
2762 which message we are processing since the windows proc gets called
2763 recursively with different messages by the system.
2767 w32_read_socket (sd
, bufp
, numchars
, expected
)
2769 register struct input_event
*bufp
;
2770 register int numchars
;
2774 int check_visibility
= 0;
2778 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2780 if (interrupt_input_blocked
)
2782 interrupt_input_pending
= 1;
2786 interrupt_input_pending
= 0;
2789 /* So people can tell when we have read the available input. */
2790 input_signal_count
++;
2793 abort (); /* Don't think this happens. */
2795 while (get_next_msg (&msg
, FALSE
))
2797 switch (msg
.msg
.message
)
2800 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2804 if (msg
.rect
.right
== msg
.rect
.left
||
2805 msg
.rect
.bottom
== msg
.rect
.top
)
2807 /* We may get paint messages even though the client
2808 area is clipped - these are not expose events. */
2809 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
2810 XSTRING (f
->name
)->data
));
2812 else if (f
->async_visible
!= 1)
2814 /* Definitely not obscured, so mark as visible. */
2815 f
->async_visible
= 1;
2816 f
->async_iconified
= 0;
2817 SET_FRAME_GARBAGED (f
);
2818 DebPrint (("frame %04x (%s) reexposed\n", f
,
2819 XSTRING (f
->name
)->data
));
2821 /* WM_PAINT serves as MapNotify as well, so report
2822 visibility changes properly. */
2825 bufp
->kind
= deiconify_event
;
2826 XSETFRAME (bufp
->frame_or_window
, f
);
2831 else if (! NILP(Vframe_list
)
2832 && ! NILP (XCONS (Vframe_list
)->cdr
))
2833 /* Force a redisplay sooner or later to update the
2834 frame titles in case this is the second frame. */
2835 record_asynch_buffer_change ();
2839 /* Erase background again for safety. */
2840 w32_clear_rect (f
, NULL
, &msg
.rect
);
2844 msg
.rect
.right
- msg
.rect
.left
,
2845 msg
.rect
.bottom
- msg
.rect
.top
);
2852 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2854 if (f
&& !f
->iconified
)
2856 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2858 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2859 bufp
->kind
= non_ascii_keystroke
;
2860 bufp
->code
= msg
.msg
.wParam
;
2861 bufp
->modifiers
= w32_kbd_mods_to_emacs (msg
.dwModifiers
,
2863 XSETFRAME (bufp
->frame_or_window
, f
);
2864 bufp
->timestamp
= msg
.msg
.time
;
2873 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2875 if (f
&& !f
->iconified
)
2881 KEY_EVENT_RECORD key
, *keyp
= &key
;
2883 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2886 convert_to_key_event (&msg
, keyp
);
2887 add
= key_event (keyp
, bufp
, &isdead
);
2888 XSETFRAME (bufp
->frame_or_window
, f
);
2891 /* The key pressed generated two characters, most likely
2892 an accent character and a key that could not be
2893 combined with it. Prepend the message on the queue
2894 again to process the second character (which is
2895 being held internally in key_event), and process
2896 the first character now. */
2916 if (dpyinfo
->grabbed
&& last_mouse_frame
2917 && FRAME_LIVE_P (last_mouse_frame
))
2918 f
= last_mouse_frame
;
2920 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2923 note_mouse_movement (f
, &msg
.msg
);
2925 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2929 case WM_LBUTTONDOWN
:
2931 case WM_MBUTTONDOWN
:
2933 case WM_RBUTTONDOWN
:
2939 if (dpyinfo
->grabbed
&& last_mouse_frame
2940 && FRAME_LIVE_P (last_mouse_frame
))
2941 f
= last_mouse_frame
;
2943 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2947 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
2950 construct_mouse_click (bufp
, &msg
, f
);
2957 parse_button (msg
.msg
.message
, &button
, &up
);
2961 dpyinfo
->grabbed
&= ~ (1 << button
);
2965 dpyinfo
->grabbed
|= (1 << button
);
2966 last_mouse_frame
= f
;
2972 if (dpyinfo
->grabbed
&& last_mouse_frame
2973 && FRAME_LIVE_P (last_mouse_frame
))
2974 f
= last_mouse_frame
;
2976 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2980 if ((!dpyinfo
->w32_focus_frame
2981 || f
== dpyinfo
->w32_focus_frame
)
2984 construct_mouse_wheel (bufp
, &msg
, f
);
2994 struct scroll_bar
*bar
=
2995 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2997 if (bar
&& numchars
>= 1)
2999 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3009 case WM_WINDOWPOSCHANGED
:
3011 case WM_ACTIVATEAPP
:
3012 check_visibility
= 1;
3016 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3018 if (f
&& !f
->async_iconified
)
3022 x_real_positions (f
, &x
, &y
);
3023 f
->output_data
.w32
->left_pos
= x
;
3024 f
->output_data
.w32
->top_pos
= y
;
3027 check_visibility
= 1;
3031 /* If window has been obscured or exposed by another window
3032 being maximised or minimised/restored, then recheck
3033 visibility of all frames. Direct changes to our own
3034 windows get handled by WM_SIZE. */
3036 if (msg
.msg
.lParam
!= 0)
3037 check_visibility
= 1;
3040 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3041 f
->async_visible
= msg
.msg
.wParam
;
3045 check_visibility
= 1;
3049 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3051 /* Inform lisp of whether frame has been iconified etc. */
3054 switch (msg
.msg
.wParam
)
3056 case SIZE_MINIMIZED
:
3057 f
->async_visible
= 0;
3058 f
->async_iconified
= 1;
3060 bufp
->kind
= iconify_event
;
3061 XSETFRAME (bufp
->frame_or_window
, f
);
3067 case SIZE_MAXIMIZED
:
3069 f
->async_visible
= 1;
3070 f
->async_iconified
= 0;
3072 /* wait_reading_process_input will notice this and update
3073 the frame's display structures. */
3074 SET_FRAME_GARBAGED (f
);
3078 bufp
->kind
= deiconify_event
;
3079 XSETFRAME (bufp
->frame_or_window
, f
);
3085 /* Force a redisplay sooner or later
3086 to update the frame titles
3087 in case this is the second frame. */
3088 record_asynch_buffer_change ();
3093 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3101 GetClientRect(msg
.msg
.hwnd
, &rect
);
3103 height
= rect
.bottom
- rect
.top
;
3104 width
= rect
.right
- rect
.left
;
3106 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3107 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3109 /* TODO: Clip size to the screen dimensions. */
3111 /* Even if the number of character rows and columns has
3112 not changed, the font size may have changed, so we need
3113 to check the pixel dimensions as well. */
3115 if (columns
!= f
->width
3116 || rows
!= f
->height
3117 || width
!= f
->output_data
.w32
->pixel_width
3118 || height
!= f
->output_data
.w32
->pixel_height
)
3120 /* I had set this to 0, 0 - I am not sure why?? */
3122 change_frame_size (f
, rows
, columns
, 0, 1);
3123 SET_FRAME_GARBAGED (f
);
3125 f
->output_data
.w32
->pixel_width
= width
;
3126 f
->output_data
.w32
->pixel_height
= height
;
3127 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3131 check_visibility
= 1;
3136 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3138 if (msg
.msg
.message
== WM_SETFOCUS
)
3140 x_new_focus_frame (dpyinfo
, f
);
3142 else if (f
== dpyinfo
->w32_focus_frame
)
3144 x_new_focus_frame (dpyinfo
, 0);
3147 check_visibility
= 1;
3151 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3158 bufp
->kind
= delete_window_event
;
3159 XSETFRAME (bufp
->frame_or_window
, f
);
3167 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3174 bufp
->kind
= menu_bar_activate_event
;
3175 XSETFRAME (bufp
->frame_or_window
, f
);
3183 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3187 extern void menubar_selection_callback (FRAME_PTR f
, void * client_data
);
3188 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3191 check_visibility
= 1;
3194 case WM_DISPLAYCHANGE
:
3195 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3199 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3200 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3201 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3202 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3206 check_visibility
= 1;
3211 /* If the focus was just given to an autoraising frame,
3213 /* ??? This ought to be able to handle more than one such frame. */
3214 if (pending_autoraise_frame
)
3216 x_raise_frame (pending_autoraise_frame
);
3217 pending_autoraise_frame
= 0;
3220 /* Check which frames are still visisble, if we have enqueued any user
3221 events or been notified of events that may affect visibility. We
3222 do this here because there doesn't seem to be any direct
3223 notification from Windows that the visibility of a window has
3224 changed (at least, not in all cases). */
3225 if (count
> 0 || check_visibility
)
3227 Lisp_Object tail
, frame
;
3229 FOR_EACH_FRAME (tail
, frame
)
3231 FRAME_PTR f
= XFRAME (frame
);
3232 /* Check "visible" frames and mark each as obscured or not.
3233 Note that async_visible is nonzero for unobscured and
3234 obscured frames, but zero for hidden and iconified frames. */
3235 if (FRAME_W32_P (f
) && f
->async_visible
)
3238 HDC hdc
= get_frame_dc (f
);
3239 GetClipBox (hdc
, &clipbox
);
3240 release_frame_dc (f
, hdc
);
3242 if (clipbox
.right
== clipbox
.left
3243 || clipbox
.bottom
== clipbox
.top
)
3245 /* Frame has become completely obscured so mark as
3246 such (we do this by setting async_visible to 2 so
3247 that FRAME_VISIBLE_P is still true, but redisplay
3249 f
->async_visible
= 2;
3251 if (!FRAME_OBSCURED_P (f
))
3253 DebPrint (("frame %04x (%s) obscured\n", f
,
3254 XSTRING (f
->name
)->data
));
3259 /* Frame is not obscured, so mark it as such. */
3260 f
->async_visible
= 1;
3262 if (FRAME_OBSCURED_P (f
))
3264 SET_FRAME_GARBAGED (f
);
3265 DebPrint (("frame %04x (%s) reexposed\n", f
,
3266 XSTRING (f
->name
)->data
));
3268 /* Force a redisplay sooner or later. */
3269 record_asynch_buffer_change ();
3280 /* Drawing the cursor. */
3283 /* Draw a hollow box cursor. Don't change the inside of the box. */
3293 hdc
= get_frame_dc (f
);
3295 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3297 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3298 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3299 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3300 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3302 FrameRect (hdc
, &rect
, hb
);
3305 release_frame_dc (f
, hdc
);
3308 /* Clear the cursor of frame F to background color,
3309 and mark the cursor as not shown.
3310 This is used when the text where the cursor is
3311 is about to be rewritten. */
3317 if (! FRAME_VISIBLE_P (f
)
3318 || f
->phys_cursor_x
< 0)
3321 x_display_cursor (f
, 0);
3322 f
->phys_cursor_x
= -1;
3325 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3326 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3330 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3337 CHAR_TO_PIXEL_COL (f
, column
),
3338 CHAR_TO_PIXEL_ROW (f
, row
),
3339 &glyph
, 1, highlight
, 0, NULL
);
3343 x_display_bar_cursor (f
, on
)
3347 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3349 /* This is pointless on invisible frames, and dangerous on garbaged
3350 frames; in the latter case, the frame may be in the midst of
3351 changing its size, and curs_x and curs_y may be off the frame. */
3352 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3355 if (! on
&& f
->phys_cursor_x
< 0)
3358 /* If there is anything wrong with the current cursor state, remove it. */
3359 if (f
->phys_cursor_x
>= 0
3361 || f
->phys_cursor_x
!= curs_x
3362 || f
->phys_cursor_y
!= curs_y
3363 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
3365 /* Erase the cursor by redrawing the character underneath it. */
3366 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3367 f
->phys_cursor_glyph
,
3368 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3369 f
->phys_cursor_x
= -1;
3372 /* If we now need a cursor in the new place or in the new form, do it so. */
3374 && (f
->phys_cursor_x
< 0
3375 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
3377 f
->phys_cursor_glyph
3378 = ((current_glyphs
->enable
[curs_y
]
3379 && curs_x
< current_glyphs
->used
[curs_y
])
3380 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3382 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
3383 CHAR_TO_PIXEL_COL (f
, curs_x
),
3384 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3385 max (f
->output_data
.w32
->cursor_width
, 1),
3386 f
->output_data
.w32
->line_height
);
3388 f
->phys_cursor_x
= curs_x
;
3389 f
->phys_cursor_y
= curs_y
;
3391 f
->output_data
.w32
->current_cursor
= bar_cursor
;
3396 /* Turn the displayed cursor of frame F on or off according to ON.
3397 If ON is nonzero, where to put the cursor is specified
3398 by F->cursor_x and F->cursor_y. */
3401 x_display_box_cursor (f
, on
)
3405 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3407 /* This is pointless on invisible frames, and dangerous on garbaged
3408 frames; in the latter case, the frame may be in the midst of
3409 changing its size, and curs_x and curs_y may be off the frame. */
3410 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3413 /* If cursor is off and we want it off, return quickly. */
3414 if (!on
&& f
->phys_cursor_x
< 0)
3417 /* If cursor is currently being shown and we don't want it to be
3418 or it is in the wrong place,
3419 or we want a hollow box and it's not so, (pout!)
3421 if (f
->phys_cursor_x
>= 0
3423 || f
->phys_cursor_x
!= curs_x
3424 || f
->phys_cursor_y
!= curs_y
3425 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
3426 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
3428 int mouse_face_here
= 0;
3429 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3431 /* If the cursor is in the mouse face area, redisplay that when
3432 we clear the cursor. */
3433 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
3434 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3435 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3436 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
3437 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3438 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3439 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
3440 /* Don't redraw the cursor's spot in mouse face
3441 if it is at the end of a line (on a newline).
3442 The cursor appears there, but mouse highlighting does not. */
3443 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
3444 mouse_face_here
= 1;
3446 /* If the font is not as tall as a whole line,
3447 we must explicitly clear the line's whole height. */
3448 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
3449 w32_clear_area (f
, NULL
,
3450 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3451 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3452 FONT_WIDTH (f
->output_data
.w32
->font
),
3453 f
->output_data
.w32
->line_height
);
3454 /* Erase the cursor by redrawing the character underneath it. */
3455 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3456 f
->phys_cursor_glyph
,
3459 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
3460 f
->phys_cursor_x
= -1;
3463 /* If we want to show a cursor,
3464 or we want a box cursor and it's not so,
3465 write it in the right place. */
3467 && (f
->phys_cursor_x
< 0
3468 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
3469 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
3471 f
->phys_cursor_glyph
3472 = ((current_glyphs
->enable
[curs_y
]
3473 && curs_x
< current_glyphs
->used
[curs_y
])
3474 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3476 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
3479 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
3483 x_draw_single_glyph (f
, curs_y
, curs_x
,
3484 f
->phys_cursor_glyph
, 2);
3485 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
3488 f
->phys_cursor_x
= curs_x
;
3489 f
->phys_cursor_y
= curs_y
;
3493 /* Display the cursor on frame F, or clear it, according to ON.
3494 Use the position specified by curs_x and curs_y
3495 if we are doing an update of frame F now.
3496 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
3499 x_display_cursor (f
, on
)
3505 /* If we're not updating, then we want to use the current frame's
3506 cursor position, not our local idea of where the cursor ought to be. */
3507 if (f
!= updating_frame
)
3509 curs_x
= FRAME_CURSOR_X (f
);
3510 curs_y
= FRAME_CURSOR_Y (f
);
3513 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3514 x_display_box_cursor (f
, on
);
3515 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3516 x_display_bar_cursor (f
, on
);
3518 /* Those are the only two we have implemented! */
3524 /* Changing the font of the frame. */
3526 /* Give frame F the font named FONTNAME as its default font, and
3527 return the full name of that font. FONTNAME may be a wildcard
3528 pattern; in that case, we choose some font that fits the pattern.
3529 The return value shows which font we chose. */
3532 x_new_font (f
, fontname
)
3534 register char *fontname
;
3537 int n_matching_fonts
;
3538 XFontStruct
*font_info
;
3539 char new_font_name
[101];
3541 /* Get a font which matches this name */
3545 if (!x_to_w32_font(fontname
, &lf
)
3546 || !w32_to_x_font(&lf
, new_font_name
, 100))
3552 /* See if we've already loaded a matching font. */
3553 already_loaded
= -1;
3558 for (i
= 0; i
< FRAME_W32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3559 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3562 fontname
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3567 /* If we have, just return it from the table. */
3568 if (already_loaded
>= 0)
3569 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3570 /* Otherwise, load the font and add it to the table. */
3576 font
= w32_load_font(FRAME_W32_DISPLAY_INFO (f
), fontname
);
3583 /* Do we need to create the table? */
3584 if (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
== 0)
3586 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
= 16;
3587 FRAME_W32_DISPLAY_INFO (f
)->font_table
3588 = (struct font_info
*) xmalloc (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3589 * sizeof (struct font_info
));
3591 /* Do we need to grow the table? */
3592 else if (FRAME_W32_DISPLAY_INFO (f
)->n_fonts
3593 >= FRAME_W32_DISPLAY_INFO (f
)->font_table_size
)
3595 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3596 FRAME_W32_DISPLAY_INFO (f
)->font_table
3597 = (struct font_info
*) xrealloc (FRAME_W32_DISPLAY_INFO (f
)->font_table
,
3598 (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3599 * sizeof (struct font_info
)));
3602 n_fonts
= FRAME_W32_DISPLAY_INFO (f
)->n_fonts
;
3603 FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3604 bcopy (fontname
, FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3605 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3606 FRAME_W32_DISPLAY_INFO (f
)->n_fonts
++;
3609 /* Compute the scroll bar width in character columns. */
3610 if (f
->scroll_bar_pixel_width
> 0)
3612 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
3613 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3616 f
->scroll_bar_cols
= 2;
3618 /* Now make the frame display the given font. */
3619 if (FRAME_W32_WINDOW (f
) != 0)
3621 frame_update_line_height (f
);
3622 x_set_window_size (f
, 0, f
->width
, f
->height
);
3625 /* If we are setting a new frame's font for the first time,
3626 there are no faces yet, so this font's height is the line height. */
3627 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
3630 Lisp_Object lispy_name
;
3632 lispy_name
= build_string (fontname
);
3638 /* Calculate the absolute position in frame F
3639 from its current recorded position values and gravity. */
3641 x_calc_absolute_position (f
)
3646 int flags
= f
->output_data
.w32
->size_hint_flags
;
3650 /* Find the position of the outside upper-left corner of
3651 the inner window, with respect to the outer window. */
3652 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
3655 MapWindowPoints (FRAME_W32_WINDOW (f
),
3656 f
->output_data
.w32
->parent_desc
,
3663 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3666 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
3667 FRAME_EXTERNAL_MENU_BAR (f
));
3670 pt
.x
+= (rt
.right
- rt
.left
);
3671 pt
.y
+= (rt
.bottom
- rt
.top
);
3674 /* Treat negative positions as relative to the leftmost bottommost
3675 position that fits on the screen. */
3676 if (flags
& XNegative
)
3677 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
3678 - 2 * f
->output_data
.w32
->border_width
- pt
.x
3680 + f
->output_data
.w32
->left_pos
);
3682 if (flags
& YNegative
)
3683 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
3684 - 2 * f
->output_data
.w32
->border_width
- pt
.y
3686 + f
->output_data
.w32
->top_pos
);
3687 /* The left_pos and top_pos
3688 are now relative to the top and left screen edges,
3689 so the flags should correspond. */
3690 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3693 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3694 to really change the position, and 0 when calling from
3695 x_make_frame_visible (in that case, XOFF and YOFF are the current
3696 position values). It is -1 when calling from x_set_frame_parameters,
3697 which means, do adjust for borders but don't change the gravity. */
3699 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3701 register int xoff
, yoff
;
3704 int modified_top
, modified_left
;
3706 if (change_gravity
> 0)
3708 f
->output_data
.w32
->top_pos
= yoff
;
3709 f
->output_data
.w32
->left_pos
= xoff
;
3710 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3712 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
3714 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
3715 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3717 x_calc_absolute_position (f
);
3720 x_wm_set_size_hint (f
, (long) 0, 0);
3722 /* It is a mystery why we need to add the border_width here
3723 when the frame is already visible, but experiment says we do. */
3724 modified_left
= f
->output_data
.w32
->left_pos
;
3725 modified_top
= f
->output_data
.w32
->top_pos
;
3727 /* Do not add in border widths under W32. */
3728 if (change_gravity
!= 0)
3730 modified_left
+= f
->output_data
.w32
->border_width
;
3731 modified_top
+= f
->output_data
.w32
->border_width
;
3735 my_set_window_pos (FRAME_W32_WINDOW (f
),
3737 modified_left
, modified_top
,
3739 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
3743 /* Call this to change the size of frame F's x-window.
3744 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3745 for this size change and subsequent size changes.
3746 Otherwise we leave the window gravity unchanged. */
3748 x_set_window_size (f
, change_gravity
, cols
, rows
)
3753 int pixelwidth
, pixelheight
;
3755 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3759 check_frame_size (f
, &rows
, &cols
);
3760 f
->output_data
.w32
->vertical_scroll_bar_extra
3761 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3763 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3764 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3765 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
3766 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3767 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3769 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3770 x_wm_set_size_hint (f
, (long) 0, 0);
3775 rect
.left
= rect
.top
= 0;
3776 rect
.right
= pixelwidth
;
3777 rect
.bottom
= pixelheight
;
3779 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
3780 FRAME_EXTERNAL_MENU_BAR (f
));
3782 my_set_window_pos (FRAME_W32_WINDOW (f
),
3785 rect
.right
- rect
.left
,
3786 rect
.bottom
- rect
.top
,
3787 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3790 /* Now, strictly speaking, we can't be sure that this is accurate,
3791 but the window manager will get around to dealing with the size
3792 change request eventually, and we'll hear how it went when the
3793 ConfigureNotify event gets here.
3795 We could just not bother storing any of this information here,
3796 and let the ConfigureNotify event set everything up, but that
3797 might be kind of confusing to the lisp code, since size changes
3798 wouldn't be reported in the frame parameters until some random
3799 point in the future when the ConfigureNotify event arrives. */
3800 change_frame_size (f
, rows
, cols
, 0, 0);
3801 PIXEL_WIDTH (f
) = pixelwidth
;
3802 PIXEL_HEIGHT (f
) = pixelheight
;
3804 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3805 receive in the ConfigureNotify event; if we get what we asked
3806 for, then the event won't cause the screen to become garbaged, so
3807 we have to make sure to do it here. */
3808 SET_FRAME_GARBAGED (f
);
3810 /* If cursor was outside the new size, mark it as off. */
3811 if (f
->phys_cursor_y
>= rows
3812 || f
->phys_cursor_x
>= cols
)
3814 f
->phys_cursor_x
= -1;
3815 f
->phys_cursor_y
= -1;
3818 /* Clear out any recollection of where the mouse highlighting was,
3819 since it might be in a place that's outside the new frame size.
3820 Actually checking whether it is outside is a pain in the neck,
3821 so don't try--just let the highlighting be done afresh with new size. */
3822 window
= dpyinfo
->mouse_face_window
;
3823 if (! NILP (window
) && XFRAME (window
) == f
)
3825 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3826 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3827 dpyinfo
->mouse_face_window
= Qnil
;
3833 /* Mouse warping. */
3836 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3845 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
3846 pt
.x
= rect
.left
+ pix_x
;
3847 pt
.y
= rect
.top
+ pix_y
;
3848 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
3850 SetCursorPos (pt
.x
, pt
.y
);
3856 x_set_mouse_position (f
, x
, y
)
3862 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
3863 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
3865 if (pix_x
< 0) pix_x
= 0;
3866 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3868 if (pix_y
< 0) pix_y
= 0;
3869 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3871 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3874 /* focus shifting, raising and lowering. */
3876 x_focus_on_frame (f
)
3879 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3881 /* Give input focus to frame. */
3884 /* Try not to change its Z-order if possible. */
3885 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
3886 my_set_focus (f
, FRAME_W32_WINDOW (f
));
3889 my_set_foreground_window (FRAME_W32_WINDOW (f
));
3898 /* Raise frame F. */
3905 /* Strictly speaking, raise-frame should only change the frame's Z
3906 order, leaving input focus unchanged. This is reasonable behaviour
3907 on X where the usual policy is point-to-focus. However, this
3908 behaviour would be very odd on Windows where the usual policy is
3911 On X, if the mouse happens to be over the raised frame, it gets
3912 input focus anyway (so the window with focus will never be
3913 completely obscured) - if not, then just moving the mouse over it
3914 is sufficient to give it focus. On Windows, the user must actually
3915 click on the frame (preferrably the title bar so as not to move
3916 point), which is more awkward. Also, no other Windows program
3917 raises a window to the top but leaves another window (possibly now
3918 completely obscured) with input focus.
3920 Because there is a system setting on Windows that allows the user
3921 to choose the point to focus policy, we make the strict semantics
3922 optional, but by default we grab focus when raising. */
3924 if (NILP (Vw32_grab_focus_on_raise
))
3926 /* The obvious call to my_set_window_pos doesn't work if Emacs is
3927 not already the foreground application: the frame is raised
3928 above all other frames belonging to us, but not above the
3929 current top window. To achieve that, we have to resort to this
3930 more cumbersome method. */
3932 HDWP handle
= BeginDeferWindowPos (2);
3935 DeferWindowPos (handle
,
3936 FRAME_W32_WINDOW (f
),
3939 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3941 DeferWindowPos (handle
,
3942 GetForegroundWindow (),
3943 FRAME_W32_WINDOW (f
),
3945 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3947 EndDeferWindowPos (handle
);
3952 my_set_foreground_window (FRAME_W32_WINDOW (f
));
3958 /* Lower frame F. */
3964 my_set_window_pos (FRAME_W32_WINDOW (f
),
3967 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3972 w32_frame_raise_lower (f
, raise
)
3982 /* Change of visibility. */
3984 /* This tries to wait until the frame is really visible.
3985 However, if the window manager asks the user where to position
3986 the frame, this will return before the user finishes doing that.
3987 The frame will not actually be visible at that time,
3988 but it will become visible later when the window manager
3989 finishes with it. */
3991 x_make_frame_visible (f
)
3996 if (! FRAME_VISIBLE_P (f
))
3998 /* We test FRAME_GARBAGED_P here to make sure we don't
3999 call x_set_offset a second time
4000 if we get to x_make_frame_visible a second time
4001 before the window gets really visible. */
4002 if (! FRAME_ICONIFIED_P (f
)
4003 && ! f
->output_data
.w32
->asked_for_visible
)
4004 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4006 f
->output_data
.w32
->asked_for_visible
= 1;
4008 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4009 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4012 /* Synchronize to ensure Emacs knows the frame is visible
4013 before we do anything else. We do this loop with input not blocked
4014 so that incoming events are handled. */
4017 int count
= input_signal_count
;
4019 /* This must come after we set COUNT. */
4022 XSETFRAME (frame
, f
);
4026 /* Once we have handled input events,
4027 we should have received the MapNotify if one is coming.
4028 So if we have not got it yet, stop looping.
4029 Some window managers make their own decisions
4030 about visibility. */
4031 if (input_signal_count
!= count
)
4033 /* Machines that do polling rather than SIGIO have been observed
4034 to go into a busy-wait here. So we'll fake an alarm signal
4035 to let the handler know that there's something to be read.
4036 We used to raise a real alarm, but it seems that the handler
4037 isn't always enabled here. This is probably a bug. */
4038 if (input_polling_used ())
4040 /* It could be confusing if a real alarm arrives while processing
4041 the fake one. Turn it off and let the handler reset it. */
4043 input_poll_signal (0);
4045 /* Once we have handled input events,
4046 we should have received the MapNotify if one is coming.
4047 So if we have not got it yet, stop looping.
4048 Some window managers make their own decisions
4049 about visibility. */
4050 if (input_signal_count
!= count
)
4053 FRAME_SAMPLE_VISIBILITY (f
);
4057 /* Change from mapped state to withdrawn state. */
4059 /* Make the frame visible (mapped and not iconified). */
4061 x_make_frame_invisible (f
)
4066 /* Don't keep the highlight on an invisible frame. */
4067 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4068 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4072 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4074 /* We can't distinguish this from iconification
4075 just by the event that we get from the server.
4076 So we can't win using the usual strategy of letting
4077 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4078 and synchronize with the server to make sure we agree. */
4080 FRAME_ICONIFIED_P (f
) = 0;
4081 f
->async_visible
= 0;
4082 f
->async_iconified
= 0;
4087 /* Change window state from mapped to iconified. */
4095 /* Don't keep the highlight on an invisible frame. */
4096 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4097 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4099 if (f
->async_iconified
)
4104 /* Simulate the user minimizing the frame. */
4105 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4107 f
->async_iconified
= 1;
4112 /* Destroy the window of frame F. */
4114 x_destroy_window (f
)
4117 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4121 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4122 free_frame_menubar (f
);
4123 free_frame_faces (f
);
4125 xfree (f
->output_data
.w32
);
4126 f
->output_data
.w32
= 0;
4127 if (f
== dpyinfo
->w32_focus_frame
)
4128 dpyinfo
->w32_focus_frame
= 0;
4129 if (f
== dpyinfo
->w32_focus_event_frame
)
4130 dpyinfo
->w32_focus_event_frame
= 0;
4131 if (f
== dpyinfo
->w32_highlight_frame
)
4132 dpyinfo
->w32_highlight_frame
= 0;
4134 dpyinfo
->reference_count
--;
4136 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4138 dpyinfo
->mouse_face_beg_row
4139 = dpyinfo
->mouse_face_beg_col
= -1;
4140 dpyinfo
->mouse_face_end_row
4141 = dpyinfo
->mouse_face_end_col
= -1;
4142 dpyinfo
->mouse_face_window
= Qnil
;
4148 /* Setting window manager hints. */
4150 /* Set the normal size hints for the window manager, for frame F.
4151 FLAGS is the flags word to use--or 0 meaning preserve the flags
4152 that the window now has.
4153 If USER_POSITION is nonzero, we set the USPosition
4154 flag (this is useful when FLAGS is 0). */
4156 x_wm_set_size_hint (f
, flags
, user_position
)
4161 Window window
= FRAME_W32_WINDOW (f
);
4163 flexlines
= f
->height
;
4167 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4168 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4169 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4170 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4175 /* Window manager things */
4176 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4181 Window window
= FRAME_W32_WINDOW (f
);
4183 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4184 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4185 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4187 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4192 /* Initialization. */
4194 #ifdef USE_X_TOOLKIT
4195 static XrmOptionDescRec emacs_options
[] = {
4196 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4197 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4199 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4200 XrmoptionSepArg
, NULL
},
4201 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4203 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4204 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4205 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4206 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4207 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4208 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4209 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4211 #endif /* USE_X_TOOLKIT */
4213 static int w32_initialized
= 0;
4215 struct w32_display_info
*
4216 w32_term_init (display_name
, xrm_option
, resource_name
)
4217 Lisp_Object display_name
;
4219 char *resource_name
;
4223 struct w32_display_info
*dpyinfo
;
4228 if (!w32_initialized
)
4231 w32_initialized
= 1;
4242 argv
[argc
++] = "-xrm";
4243 argv
[argc
++] = xrm_option
;
4247 dpyinfo
= &one_w32_display_info
;
4249 /* Put this display on the chain. */
4250 dpyinfo
->next
= NULL
;
4252 /* Put it on w32_display_name_list as well, to keep them parallel. */
4253 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4254 w32_display_name_list
);
4255 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4257 dpyinfo
->w32_id_name
4258 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4259 + XSTRING (Vsystem_name
)->size
4261 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4262 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4265 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4266 resource_name
, EMACS_CLASS
);
4268 /* Put the rdb where we can find it in a way that works on
4270 dpyinfo
->xrdb
= xrdb
;
4272 hdc
= GetDC (GetDesktopWindow ());
4274 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4275 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4276 dpyinfo
->root_window
= GetDesktopWindow ();
4277 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4278 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4279 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4280 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4281 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4282 dpyinfo
->grabbed
= 0;
4283 dpyinfo
->reference_count
= 0;
4284 dpyinfo
->n_fonts
= 0;
4285 dpyinfo
->font_table_size
= 0;
4286 dpyinfo
->bitmaps
= 0;
4287 dpyinfo
->bitmaps_size
= 0;
4288 dpyinfo
->bitmaps_last
= 0;
4289 dpyinfo
->mouse_face_mouse_frame
= 0;
4290 dpyinfo
->mouse_face_deferred_gc
= 0;
4291 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4292 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4293 dpyinfo
->mouse_face_face_id
= 0;
4294 dpyinfo
->mouse_face_window
= Qnil
;
4295 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4296 dpyinfo
->mouse_face_defer
= 0;
4297 dpyinfo
->w32_focus_frame
= 0;
4298 dpyinfo
->w32_focus_event_frame
= 0;
4299 dpyinfo
->w32_highlight_frame
= 0;
4301 ReleaseDC (GetDesktopWindow (), hdc
);
4303 /* Determine if there is a middle mouse button, to allow parse_button
4304 to decide whether right mouse events should be mouse-2 or
4306 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4308 /* initialise palette with white and black */
4311 defined_color (0, "white", &color
, 1);
4312 defined_color (0, "black", &color
, 1);
4315 #ifndef F_SETOWN_BUG
4317 #ifdef F_SETOWN_SOCK_NEG
4318 /* stdin is a socket here */
4319 fcntl (connection
, F_SETOWN
, -getpid ());
4320 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4321 fcntl (connection
, F_SETOWN
, getpid ());
4322 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4323 #endif /* ! defined (F_SETOWN) */
4324 #endif /* F_SETOWN_BUG */
4327 if (interrupt_input
)
4328 init_sigio (connection
);
4329 #endif /* ! defined (SIGIO) */
4336 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4339 x_delete_display (dpyinfo
)
4340 struct w32_display_info
*dpyinfo
;
4342 /* Discard this display from w32_display_name_list and w32_display_list.
4343 We can't use Fdelq because that can quit. */
4344 if (! NILP (w32_display_name_list
)
4345 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4346 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4351 tail
= w32_display_name_list
;
4352 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4354 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4355 dpyinfo
->name_list_element
))
4357 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4360 tail
= XCONS (tail
)->cdr
;
4364 /* free palette table */
4366 struct w32_palette_entry
* plist
;
4368 plist
= dpyinfo
->color_list
;
4371 struct w32_palette_entry
* pentry
= plist
;
4372 plist
= plist
->next
;
4375 dpyinfo
->color_list
= NULL
;
4376 if (dpyinfo
->palette
)
4377 DeleteObject(dpyinfo
->palette
);
4379 xfree (dpyinfo
->font_table
);
4380 xfree (dpyinfo
->w32_id_name
);
4383 /* Set up use of W32. */
4385 DWORD
w32_msg_worker ();
4389 /* MSVC does not type K&R functions with no arguments correctly, and
4390 so we must explicitly cast them. */
4391 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
4392 clear_end_of_line_hook
= w32_clear_end_of_line
;
4393 ins_del_lines_hook
= w32_ins_del_lines
;
4394 change_line_highlight_hook
= w32_change_line_highlight
;
4395 insert_glyphs_hook
= w32_insert_glyphs
;
4396 write_glyphs_hook
= w32_write_glyphs
;
4397 delete_glyphs_hook
= w32_delete_glyphs
;
4398 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
4399 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
4400 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
4401 update_begin_hook
= w32_update_begin
;
4402 update_end_hook
= w32_update_end
;
4403 set_terminal_window_hook
= w32_set_terminal_window
;
4404 read_socket_hook
= w32_read_socket
;
4405 frame_up_to_date_hook
= w32_frame_up_to_date
;
4406 cursor_to_hook
= w32_cursor_to
;
4407 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
4408 mouse_position_hook
= w32_mouse_position
;
4409 frame_rehighlight_hook
= w32_frame_rehighlight
;
4410 frame_raise_lower_hook
= w32_frame_raise_lower
;
4411 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
4412 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
4413 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
4414 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
4416 scroll_region_ok
= 1; /* we'll scroll partial frames */
4417 char_ins_del_ok
= 0; /* just as fast to write the line */
4418 line_ins_del_ok
= 1; /* we'll just blt 'em */
4419 fast_clear_end_of_line
= 1; /* X does this well */
4420 memory_below_frame
= 0; /* we don't remember what scrolls
4424 /* Initialize input mode: interrupt_input off, no flow control, allow
4425 8 bit character input, standard quit char. */
4426 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
4428 /* Create the window thread - it will terminate itself or when the app terminates */
4432 dwMainThreadId
= GetCurrentThreadId ();
4433 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
4434 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
4436 /* Wait for thread to start */
4441 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
4443 hWindowsThread
= CreateThread (NULL
, 0,
4444 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
4445 0, 0, &dwWindowsThreadId
);
4447 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4450 /* It is desirable that mainThread should have the same notion of
4451 focus window and active window as windowsThread. Unfortunately, the
4452 following call to AttachThreadInput, which should do precisely what
4453 we need, causes major problems when Emacs is linked as a console
4454 program. Unfortunately, we have good reasons for doing that, so
4455 instead we need to send messages to windowsThread to make some API
4456 calls for us (ones that affect, or depend on, the active/focus
4458 #ifdef ATTACH_THREADS
4459 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
4462 /* Dynamically link to optional system components. */
4464 HANDLE user_lib
= LoadLibrary ("user32.dll");
4466 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
4468 /* New proportional scroll bar functions. */
4469 LOAD_PROC( SetScrollInfo
);
4470 LOAD_PROC( GetScrollInfo
);
4474 FreeLibrary (user_lib
);
4476 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
4477 otherwise use the fixed height. */
4478 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
4479 GetSystemMetrics (SM_CYVTHUMB
);
4481 /* For either kind of scroll bar, take account of the arrows; these
4482 effectively form the border of the main scroll bar range. */
4483 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
4484 = GetSystemMetrics (SM_CYVSCROLL
);
4491 staticpro (&w32_display_name_list
);
4492 w32_display_name_list
= Qnil
;
4494 staticpro (&last_mouse_scroll_bar
);
4495 last_mouse_scroll_bar
= Qnil
;
4497 staticpro (&Qvendor_specific_keysyms
);
4498 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
4500 DEFVAR_INT ("w32-num-mouse-buttons",
4501 &Vw32_num_mouse_buttons
,
4502 "Number of physical mouse buttons.");
4503 Vw32_num_mouse_buttons
= Qnil
;
4505 DEFVAR_LISP ("w32-swap-mouse-buttons",
4506 &Vw32_swap_mouse_buttons
,
4507 "Swap the mapping of middle and right mouse buttons.\n\
4508 When nil, middle button is mouse-2 and right button is mouse-3.");
4509 Vw32_swap_mouse_buttons
= Qnil
;
4511 DEFVAR_LISP ("w32-grab-focus-on-raise",
4512 &Vw32_grab_focus_on_raise
,
4513 "Raised frame grabs input focus.\n\
4514 When t, `raise-frame' grabs input focus as well. This fits well\n\
4515 with the normal Windows click-to-focus policy, but might not be\n\
4516 desirable when using a point-to-focus policy.");
4517 Vw32_grab_focus_on_raise
= Qt
;
4519 DEFVAR_LISP ("w32-capslock-is-shiftlock",
4520 &Vw32_capslock_is_shiftlock
,
4521 "Apply CapsLock state to non character input keys.\n\
4522 When nil, CapsLock only affects normal character input keys.");
4523 Vw32_capslock_is_shiftlock
= Qnil
;
4525 DEFVAR_LISP ("w32-recognize-altgr",
4526 &Vw32_recognize_altgr
,
4527 "Recognize right-alt and left-ctrl as AltGr.\n\
4528 When nil, the right-alt and left-ctrl key combination is\n\
4529 interpreted normally.");
4530 Vw32_recognize_altgr
= Qt
;