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"
42 #include "dispextern.h"
43 #include "termhooks.h"
51 #include "intervals.h"
56 #define min(x, y) (((x) < (y)) ? (x) : (y))
57 #define max(x, y) (((x) > (y)) ? (x) : (y))
59 extern unsigned int msh_mousewheel
;
61 extern void free_frame_menubar ();
63 extern Lisp_Object Vwindow_system
;
65 #define x_any_window_to_frame x_window_to_frame
66 #define x_top_window_to_frame x_window_to_frame
69 /* This is display since w32 does not support multiple ones. */
70 struct w32_display_info one_w32_display_info
;
72 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
73 one for each element of w32_display_list and in the same order.
74 NAME is the name of the frame.
75 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
76 Lisp_Object w32_display_name_list
;
78 /* Frame being updated by update_frame. This is declared in term.c.
79 This is set by update_begin and looked at by all the
80 w32 functions. It is zero while not inside an update.
81 In that case, the w32 functions assume that `selected_frame'
82 is the frame to apply to. */
83 extern struct frame
*updating_frame
;
85 /* This is a frame waiting to be autoraised, within w32_read_socket. */
86 struct frame
*pending_autoraise_frame
;
88 /* During an update, maximum vpos for ins/del line operations to affect. */
92 /* During an update, nonzero if chars output now should be highlighted. */
96 /* Nominal cursor position -- where to draw output.
97 During an update, these are different from the cursor-box position. */
102 DWORD dwWindowsThreadId
= 0;
103 HANDLE hWindowsThread
= NULL
;
104 DWORD dwMainThreadId
= 0;
105 HANDLE hMainThread
= NULL
;
108 /* These definitions are new with Windows 95. */
109 #define SIF_RANGE 0x0001
110 #define SIF_PAGE 0x0002
111 #define SIF_POS 0x0004
112 #define SIF_DISABLENOSCROLL 0x0008
113 #define SIF_TRACKPOS 0x0010
114 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
116 typedef struct tagSCROLLINFO
125 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
126 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
129 /* Dynamic linking to new proportional scroll bar functions. */
130 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
131 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
133 int vertical_scroll_bar_min_handle
;
134 int vertical_scroll_bar_top_border
;
135 int vertical_scroll_bar_bottom_border
;
137 int last_scroll_bar_drag_pos
;
139 /* Mouse movement. */
141 /* Where the mouse was last time we reported a mouse event. */
142 static FRAME_PTR last_mouse_frame
;
143 static RECT last_mouse_glyph
;
145 Lisp_Object Vw32_num_mouse_buttons
;
147 Lisp_Object Vw32_swap_mouse_buttons
;
149 /* Control whether x_raise_frame also sets input focus. */
150 Lisp_Object Vw32_grab_focus_on_raise
;
152 /* Control whether Caps Lock affects non-ascii characters. */
153 Lisp_Object Vw32_capslock_is_shiftlock
;
155 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
156 Lisp_Object Vw32_recognize_altgr
;
158 /* The scroll bar in which the last motion event occurred.
160 If the last motion event occurred in a scroll bar, we set this
161 so w32_mouse_position can know whether to report a scroll bar motion or
164 If the last motion event didn't occur in a scroll bar, we set this
165 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
166 Lisp_Object last_mouse_scroll_bar
;
167 int last_mouse_scroll_bar_pos
;
169 /* This is a hack. We would really prefer that w32_mouse_position would
170 return the time associated with the position it returns, but there
171 doesn't seem to be any way to wrest the timestamp from the server
172 along with the position query. So, we just keep track of the time
173 of the last movement we received, and return that in hopes that
174 it's somewhat accurate. */
175 Time last_mouse_movement_time
;
177 /* Incremented by w32_read_socket whenever it really tries to read events. */
179 static int volatile input_signal_count
;
181 static int input_signal_count
;
184 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
186 extern Lisp_Object Qface
, Qmouse_face
;
190 /* A mask of extra modifier bits to put into every keyboard char. */
191 extern int extra_keyboard_modifiers
;
193 static Lisp_Object Qvendor_specific_keysyms
;
195 void w32_delete_display ();
197 static void redraw_previous_char ();
198 static void redraw_following_char ();
199 static unsigned int w32_get_modifiers ();
201 static int fast_find_position ();
202 static void note_mouse_highlight ();
203 static void clear_mouse_face ();
204 static void show_mouse_face ();
205 static void do_line_dance ();
207 /* Forward declarations for term hooks. Consistency with the rest of Emacs
208 requires the use of K&R functions prototypes. However, MSVC does not
209 pick up the function prototypes correctly with K&R function definitions,
210 and so we declare them first to give a little help to MSVC. */
211 static void w32_clear_frame ();
212 static void w32_clear_end_of_line (int);
213 static void w32_ins_del_lines (int, int);
214 static void w32_change_line_highlight (int, int, int);
215 static void w32_insert_glyphs (GLYPH
*, int);
216 static void w32_write_glyphs (GLYPH
*, int);
217 static void w32_delete_glyphs (int);
218 static void w32_ring_bell ();
219 static void w32_reset_terminal_modes ();
220 static void w32_set_terminal_modes ();
221 static void w32_update_begin (FRAME_PTR
);
222 static void w32_update_end (FRAME_PTR
);
223 static void w32_set_terminal_window (int);
224 extern int w32_read_socket (int, struct input_event
*, int, int);
225 static void w32_frame_up_to_date (FRAME_PTR
);
226 static void w32_cursor_to (int, int);
227 static void w32_reassert_line_highlight (int, int);
228 static void w32_mouse_position (FRAME_PTR
*, int, Lisp_Object
*,
229 enum scroll_bar_part
*, Lisp_Object
*,
230 Lisp_Object
*, unsigned long *);
231 static void w32_frame_rehighlight (FRAME_PTR
);
232 static void w32_frame_raise_lower (FRAME_PTR
, int);
233 static void w32_set_vertical_scroll_bar (struct window
*, int, int, int);
234 static void w32_condemn_scroll_bars (FRAME_PTR
);
235 static void w32_redeem_scroll_bar (struct window
*);
236 static void w32_judge_scroll_bars (FRAME_PTR
);
239 /* This is a function useful for recording debugging information
240 about the sequence of occurrences in this file. */
248 struct record event_record
[100];
250 int event_record_index
;
252 record_event (locus
, type
)
256 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
257 event_record_index
= 0;
259 event_record
[event_record_index
].locus
= locus
;
260 event_record
[event_record_index
].type
= type
;
261 event_record_index
++;
266 /* Return the struct w32_display_info. */
268 struct w32_display_info
*
269 w32_display_info_for_display ()
271 return (&one_w32_display_info
);
275 w32_fill_rect (f
, _hdc
, pix
, lprect
)
290 hdc
= get_frame_dc (f
);
293 hb
= CreateSolidBrush (pix
);
294 FillRect (hdc
, lprect
, hb
);
298 release_frame_dc (f
, hdc
);
307 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
308 w32_clear_rect (f
, NULL
, &rect
);
312 /* Starting and ending updates.
314 These hooks are called by update_frame at the beginning and end
315 of a frame update. We record in `updating_frame' the identity
316 of the frame being updated, so that the w32_... functions do not
317 need to take a frame as argument. Most of the w32_... functions
318 should never be called except during an update, the only exceptions
319 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
328 flexlines
= f
->height
;
333 /* Regenerate display palette before drawing if list of requested
334 colors has changed. */
335 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
337 w32_regenerate_palette (f
);
338 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
341 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
343 /* Don't do highlighting for mouse motion during the update. */
344 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
346 /* If the frame needs to be redrawn,
347 simply forget about any prior mouse highlighting. */
348 if (FRAME_GARBAGED_P (f
))
349 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
351 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
353 int firstline
, lastline
, i
;
354 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
356 /* Find the first, and the last+1, lines affected by redisplay. */
357 for (firstline
= 0; firstline
< f
->height
; firstline
++)
358 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
361 lastline
= f
->height
;
362 for (i
= f
->height
- 1; i
>= 0; i
--)
364 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
370 /* Can we tell that this update does not affect the window
371 where the mouse highlight is? If so, no need to turn off.
372 Likewise, don't do anything if the frame is garbaged;
373 in that case, the FRAME_CURRENT_GLYPHS that we would use
374 are all wrong, and we will redisplay that line anyway. */
375 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
376 || lastline
< XFASTINT (w
->top
)))
377 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
391 x_display_cursor (f
, 1);
393 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
394 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
399 /* This is called after a redisplay on frame F. */
402 w32_frame_up_to_date (f
)
406 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
407 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
409 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
410 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
411 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
412 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
417 /* External interface to control of standout mode.
418 Call this when about to modify line at position VPOS
419 and not change whether it is highlighted. */
422 w32_reassert_line_highlight (new, vpos
)
428 /* Call this when about to modify line at position VPOS
429 and change whether it is highlighted. */
432 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
433 int new_highlight
, vpos
, first_unused_hpos
;
435 highlight
= new_highlight
;
436 w32_cursor_to (vpos
, 0);
437 w32_clear_end_of_line (updating_frame
->width
);
440 /* This is used when starting Emacs and when restarting after suspend.
441 When starting Emacs, no window is mapped. And nothing must be done
442 to Emacs's own window if it is suspended (though that rarely happens). */
445 w32_set_terminal_modes (void)
449 /* This is called when exiting or suspending Emacs.
450 Exiting will make the W32 windows go away, and suspending
451 requires no action. */
454 w32_reset_terminal_modes (void)
458 /* Set the nominal cursor position of the frame.
459 This is where display update commands will take effect.
460 This does not affect the place where the cursor-box is displayed. */
463 w32_cursor_to (row
, col
)
464 register int row
, col
;
471 if (updating_frame
== 0)
474 x_display_cursor (selected_frame
, 1);
479 /* Display a sequence of N glyphs found at GP.
480 WINDOW is the window to output to. LEFT and TOP are starting coords.
481 HL is 1 if this text is highlighted, 2 if the cursor is on it,
482 3 if should appear in its mouse-face.
483 JUST_FOREGROUND if 1 means draw only the foreground;
484 don't alter the background.
486 FONT is the default font to use (for glyphs whose font-code is 0).
488 Since the display generation code is responsible for calling
489 compute_char_face and compute_glyph_face on everything it puts in
490 the display structure, we can assume that the face code on each
491 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
492 to which we can actually apply intern_face.
493 Call this function with input blocked. */
496 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
499 register GLYPH
*gp
; /* Points to first GLYPH. */
500 register int n
; /* Number of glyphs to display. */
503 struct cmpchar_info
*cmpcharp
;
505 /* Holds characters to be displayed. */
506 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
507 register char *cp
; /* Steps through buf[]. */
508 register int tlen
= GLYPH_TABLE_LENGTH
;
509 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
510 Window window
= FRAME_W32_WINDOW (f
);
511 int orig_left
= left
;
514 hdc
= get_frame_dc (f
);
518 /* Get the face-code of the next GLYPH. */
523 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
524 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
525 ch
= FAST_GLYPH_CHAR (g
);
526 charset
= CHAR_CHARSET (ch
);
527 if (charset
== CHARSET_COMPOSITION
)
529 struct face
*face
= FRAME_DEFAULT_FACE (f
);
530 XFontStruct
*font
= FACE_FONT (face
);
531 /* We must draw components of the composite character on the
533 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
535 /* Set the face in the slot for work. */
536 cmpcharp
->face_work
= cf
;
538 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
539 hl
, just_foreground
, cmpcharp
);
540 left
+= FONT_WIDTH (font
) * cmpcharp
->width
;
542 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
546 /* Find the run of consecutive glyphs with the same face-code.
547 Extract their character codes into BUF. */
551 int this_charset
, c
[2];
554 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
555 ch
= FAST_GLYPH_CHAR (g
);
556 SPLIT_CHAR (ch
, this_charset
, c
[0], c
[1]);
557 if (this_charset
!= charset
558 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
563 int consumed
, produced
;
564 /* Handle multibyte characters (still assuming user
565 selects correct font themselves for now */
566 produced
= encode_terminal_code(gp
, cp
, 1,
567 (f
->width
*sizeof(*buf
))-(cp
-buf
), &consumed
);
568 /* If we can't display this glyph, skip it */
572 gp
+= consumed
, n
-= consumed
;
580 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
584 /* LEN gets the length of the run. */
586 /* Now output this run of chars, with the font and pixel values
587 determined by the face code CF. */
590 struct face
*face
= FRAME_DEFAULT_FACE (f
);
591 XFontStruct
*font
= FACE_FONT (face
);
595 /* HL = 3 means use a mouse face previously chosen. */
597 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
599 /* First look at the face of the text itself. */
602 /* It's possible for the display table to specify
603 a face code that is out of range. Use 0 in that case. */
604 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
605 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
609 face
= FRAME_MODE_LINE_FACE (f
);
611 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
612 font
= FACE_FONT (face
);
613 if (FACE_STIPPLE (face
))
617 /* Then comes the distinction between modeline and normal text. */
622 face
= FRAME_MODE_LINE_FACE (f
);
623 font
= FACE_FONT (face
);
624 if (FACE_STIPPLE (face
))
628 fg
= face
->foreground
;
629 bg
= face
->background
;
631 /* Now override that if the cursor's on this character. */
634 /* The cursor overrides stippling. */
638 || face
->font
== (XFontStruct
*) FACE_DEFAULT
639 || face
->font
== f
->output_data
.w32
->font
)
640 && face
->background
== f
->output_data
.w32
->background_pixel
641 && face
->foreground
== f
->output_data
.w32
->foreground_pixel
)
643 bg
= f
->output_data
.w32
->cursor_pixel
;
644 fg
= face
->background
;
646 /* Cursor on non-default face: must merge. */
649 bg
= f
->output_data
.w32
->cursor_pixel
;
650 fg
= face
->background
;
651 /* If the glyph would be invisible,
652 try a different foreground. */
654 fg
= face
->foreground
;
656 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
658 fg
= face
->foreground
;
659 /* Make sure the cursor is distinct from text in this face. */
660 if (bg
== face
->background
661 && fg
== face
->foreground
)
663 bg
= face
->foreground
;
664 fg
= face
->background
;
669 if (font
== (XFontStruct
*) FACE_DEFAULT
)
670 font
= f
->output_data
.w32
->font
;
672 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
674 SetTextColor (hdc
, fg
);
675 SetBkColor (hdc
, bg
);
677 SelectObject (hdc
, font
->hfont
);
679 TextOut (hdc
, left
, top
, buf
, len
);
681 if (!just_foreground
)
683 /* Clear the rest of the line's height. */
684 if (f
->output_data
.w32
->line_height
!= FONT_HEIGHT (font
))
685 w32_fill_area (f
, hdc
, bg
,
687 top
+ FONT_HEIGHT (font
),
688 FONT_WIDTH (font
) * len
,
689 f
->output_data
.w32
->line_height
- FONT_HEIGHT (font
));
693 int underline_position
= 1;
695 if (font
->tm
.tmDescent
<= underline_position
)
696 underline_position
= font
->tm
.tmDescent
- 1;
699 w32_fill_area (f
, hdc
, fg
,
702 + underline_position
),
703 len
* FONT_WIDTH (font
), 1);
706 left
+= len
* FONT_WIDTH (font
);
710 release_frame_dc (f
, hdc
);
714 /* Output some text at the nominal frame cursor position.
715 Advance the cursor over the text.
716 Output LEN glyphs at START.
718 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
719 controls the pixel values used for foreground and background. */
722 w32_write_glyphs (start
, len
)
723 register GLYPH
*start
;
726 register int temp_length
;
736 /* If not within an update,
737 output at the frame's visible cursor. */
738 curs_x
= f
->cursor_x
;
739 curs_y
= f
->cursor_y
;
743 CHAR_TO_PIXEL_COL (f
, curs_x
),
744 CHAR_TO_PIXEL_ROW (f
, curs_y
),
745 start
, len
, highlight
, 0, NULL
);
747 /* If we drew on top of the cursor, note that it is turned off. */
748 if (curs_y
== f
->phys_cursor_y
749 && curs_x
<= f
->phys_cursor_x
750 && curs_x
+ len
> f
->phys_cursor_x
)
751 f
->phys_cursor_x
= -1;
753 if (updating_frame
== 0)
756 x_display_cursor (f
, 1);
765 /* Clear to the end of the line.
766 Erase the current text line from the nominal cursor position (inclusive)
767 to column FIRST_UNUSED (exclusive). The idea is that everything
768 from FIRST_UNUSED onward is already erased. */
771 w32_clear_end_of_line (first_unused
)
772 register int first_unused
;
774 struct frame
*f
= updating_frame
;
779 if (curs_y
< 0 || curs_y
>= f
->height
)
781 if (first_unused
<= 0)
784 if (first_unused
>= f
->width
)
785 first_unused
= f
->width
;
787 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
793 /* Notice if the cursor will be cleared by this operation. */
794 if (curs_y
== f
->phys_cursor_y
795 && curs_x
<= f
->phys_cursor_x
796 && f
->phys_cursor_x
< first_unused
)
797 f
->phys_cursor_x
= -1;
799 w32_clear_area (f
, NULL
,
800 CHAR_TO_PIXEL_COL (f
, curs_x
),
801 CHAR_TO_PIXEL_ROW (f
, curs_y
),
802 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
803 f
->output_data
.w32
->line_height
);
811 struct frame
*f
= updating_frame
;
816 f
->phys_cursor_x
= -1; /* Cursor not visible. */
817 curs_x
= 0; /* Nominal cursor position is top left. */
822 w32_clear_window (f
);
824 /* We have to clear the scroll bars, too. If we have changed
825 colors or something like that, then they should be notified. */
826 x_scroll_bar_clear (f
);
831 /* Make audible bell. */
841 HWND hwnd
= FRAME_W32_WINDOW (selected_frame
);
843 for (i
= 0; i
< 5; i
++)
845 FlashWindow (hwnd
, TRUE
);
848 FlashWindow (hwnd
, FALSE
);
851 w32_sys_ring_bell ();
856 /* Insert and delete character.
857 These are not supposed to be used because we are supposed to turn
858 off the feature of using them. */
861 w32_insert_glyphs (start
, len
)
862 register GLYPH
*start
;
869 w32_delete_glyphs (n
)
875 /* Specify how many text lines, from the top of the window,
876 should be affected by insert-lines and delete-lines operations.
877 This, and those operations, are used only within an update
878 that is bounded by calls to w32_update_begin and w32_update_end. */
881 w32_set_terminal_window (n
)
884 if (updating_frame
== 0)
887 if ((n
<= 0) || (n
> updating_frame
->height
))
888 flexlines
= updating_frame
->height
;
893 /* These variables need not be per frame
894 because redisplay is done on a frame-by-frame basis
895 and the line dance for one frame is finished before
896 anything is done for another frame. */
898 /* Array of line numbers from cached insert/delete operations.
899 line_dance[i] is the old position of the line that we want
900 to move to line i, or -1 if we want a blank line there. */
901 static int *line_dance
;
903 /* Allocated length of that array. */
904 static int line_dance_len
;
906 /* Flag indicating whether we've done any work. */
907 static int line_dance_in_progress
;
909 /* Perform an insert-lines or delete-lines operation,
910 inserting N lines or deleting -N lines at vertical position VPOS. */
913 w32_ins_del_lines (vpos
, n
)
916 register int fence
, i
;
918 if (vpos
>= flexlines
)
921 if (!line_dance_in_progress
)
923 int ht
= updating_frame
->height
;
924 if (ht
> line_dance_len
)
926 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
929 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
930 line_dance_in_progress
= 1;
934 if (n
> flexlines
- vpos
)
935 n
= flexlines
- vpos
;
937 for (i
= flexlines
; --i
>= fence
;)
938 line_dance
[i
] = line_dance
[i
-n
];
939 for (i
= fence
; --i
>= vpos
;)
945 if (n
> flexlines
- vpos
)
946 n
= flexlines
- vpos
;
947 fence
= flexlines
- n
;
948 for (i
= vpos
; i
< fence
; ++i
)
949 line_dance
[i
] = line_dance
[i
+ n
];
950 for (i
= fence
; i
< flexlines
; ++i
)
955 /* Here's where we actually move the pixels around.
956 Must be called with input blocked. */
960 register int i
, j
, distance
;
961 register struct frame
*f
;
966 /* Must check this flag first. If it's not set, then not only is the
967 array uninitialized, but we might not even have a frame. */
968 if (!line_dance_in_progress
)
976 intborder
= f
->output_data
.w32
->internal_border_width
;
978 x_display_cursor (updating_frame
, 0);
980 hdc
= get_frame_dc (f
);
982 for (i
= 0; i
< ht
; ++i
)
983 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
985 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
986 && line_dance
[j
]-j
== distance
); ++j
);
987 /* Copy [i,j) upward from [i+distance, j+distance) */
989 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
990 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
991 (j
-i
) * f
->output_data
.w32
->line_height
,
993 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
998 for (i
= ht
; --i
>=0; )
999 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1001 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1002 && line_dance
[j
]-j
== distance
););
1003 /* Copy (j, i] downward from (j+distance, i+distance] */
1005 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1006 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1007 (i
-j
) * f
->output_data
.w32
->line_height
,
1009 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
1014 for (i
= 0; i
< ht
; ++i
)
1015 if (line_dance
[i
] == -1)
1017 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1019 w32_clear_area (f
, hdc
,
1021 CHAR_TO_PIXEL_ROW (f
, i
),
1022 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
1023 (j
-i
) * f
->output_data
.w32
->line_height
);
1026 line_dance_in_progress
= 0;
1028 release_frame_dc (f
, hdc
);
1031 /* Support routines for exposure events. */
1032 static void clear_cursor ();
1034 /* Output into a rectangle of a window (for frame F)
1035 the characters in f->phys_lines that overlap that rectangle.
1036 TOP and LEFT are the position of the upper left corner of the rectangle.
1037 ROWS and COLS are the size of the rectangle.
1038 Call this function with input blocked. */
1041 dumprectangle (f
, left
, top
, cols
, rows
)
1043 register int left
, top
, cols
, rows
;
1045 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1046 int cursor_cleared
= 0;
1050 if (FRAME_GARBAGED_P (f
))
1053 /* Express rectangle as four edges, instead of position-and-size. */
1054 bottom
= top
+ rows
;
1055 right
= left
+ cols
;
1057 /* Convert rectangle edges in pixels to edges in chars.
1058 Round down for left and top, up for right and bottom. */
1059 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1060 left
= PIXEL_TO_CHAR_COL (f
, left
);
1061 bottom
+= (f
->output_data
.w32
->line_height
- 1);
1062 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
1063 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1064 right
= PIXEL_TO_CHAR_COL (f
, right
);
1066 /* Clip the rectangle to what can be visible. */
1071 if (right
> f
->width
)
1073 if (bottom
> f
->height
)
1076 /* Get size in chars of the rectangle. */
1077 cols
= right
- left
;
1078 rows
= bottom
- top
;
1080 /* If rectangle has zero area, return. */
1081 if (rows
<= 0) return;
1082 if (cols
<= 0) return;
1084 /* Turn off the cursor if it is in the rectangle.
1085 We will turn it back on afterward. */
1086 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1087 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1093 /* Display the text in the rectangle, one text line at a time. */
1095 for (y
= top
; y
< bottom
; y
++)
1097 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1099 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1103 CHAR_TO_PIXEL_COL (f
, left
),
1104 CHAR_TO_PIXEL_ROW (f
, y
),
1105 line
, min (cols
, active_frame
->used
[y
] - left
),
1106 active_frame
->highlight
[y
], 0, NULL
);
1109 /* Turn the cursor on if we turned it off. */
1112 x_display_cursor (f
, 1);
1119 x_display_cursor (f
, 1);
1123 frame_unhighlight (f
)
1126 x_display_cursor (f
, 1);
1129 static void x_frame_rehighlight ();
1131 /* The focus has changed. Update the frames as necessary to reflect
1132 the new situation. Note that we can't change the selected frame
1133 here, because the Lisp code we are interrupting might become confused.
1134 Each event gets marked with the frame in which it occurred, so the
1135 Lisp code can tell when the switch took place by examining the events. */
1138 x_new_focus_frame (dpyinfo
, frame
)
1139 struct w32_display_info
*dpyinfo
;
1140 struct frame
*frame
;
1142 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1143 int events_enqueued
= 0;
1145 if (frame
!= dpyinfo
->w32_focus_frame
)
1147 /* Set this before calling other routines, so that they see
1148 the correct value of w32_focus_frame. */
1149 dpyinfo
->w32_focus_frame
= frame
;
1151 if (old_focus
&& old_focus
->auto_lower
)
1152 x_lower_frame (old_focus
);
1154 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1155 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1157 pending_autoraise_frame
= 0;
1160 x_frame_rehighlight (dpyinfo
);
1163 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1166 x_mouse_leave (dpyinfo
)
1167 struct w32_display_info
*dpyinfo
;
1169 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1172 /* The focus has changed, or we have redirected a frame's focus to
1173 another frame (this happens when a frame uses a surrogate
1174 minibuffer frame). Shift the highlight as appropriate.
1176 The FRAME argument doesn't necessarily have anything to do with which
1177 frame is being highlighted or unhighlighted; we only use it to find
1178 the appropriate display info. */
1180 w32_frame_rehighlight (frame
)
1181 struct frame
*frame
;
1183 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1187 x_frame_rehighlight (dpyinfo
)
1188 struct w32_display_info
*dpyinfo
;
1190 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1192 if (dpyinfo
->w32_focus_frame
)
1194 dpyinfo
->w32_highlight_frame
1195 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1196 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1197 : dpyinfo
->w32_focus_frame
);
1198 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1200 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1201 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1205 dpyinfo
->w32_highlight_frame
= 0;
1207 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1210 frame_unhighlight (old_highlight
);
1211 if (dpyinfo
->w32_highlight_frame
)
1212 frame_highlight (dpyinfo
->w32_highlight_frame
);
1216 /* Keyboard processing - modifier keys, etc. */
1218 /* Convert a keysym to its name. */
1221 x_get_keysym_name (keysym
)
1224 /* Make static so we can always return it */
1225 static char value
[100];
1228 GetKeyNameText(keysym
, value
, 100);
1234 /* Mouse clicks and mouse movement. Rah. */
1236 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1237 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1238 that the glyph at X, Y occupies, if BOUNDS != 0.
1239 If NOCLIP is nonzero, do not force the value into range. */
1242 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1244 register int pix_x
, pix_y
;
1245 register int *x
, *y
;
1249 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1250 if (NILP (Vwindow_system
))
1257 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1258 even for negative values. */
1260 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1262 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1264 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1265 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1269 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1270 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1271 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1272 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1279 else if (pix_x
> f
->width
)
1284 else if (pix_y
> f
->height
)
1293 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1296 register int *pix_x
, *pix_y
;
1298 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1299 if (NILP (Vwindow_system
))
1306 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1307 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1311 parse_button (message
, pbutton
, pup
)
1321 case WM_LBUTTONDOWN
:
1329 case WM_MBUTTONDOWN
:
1330 if (NILP (Vw32_swap_mouse_buttons
))
1337 if (NILP (Vw32_swap_mouse_buttons
))
1343 case WM_RBUTTONDOWN
:
1344 if (NILP (Vw32_swap_mouse_buttons
))
1351 if (NILP (Vw32_swap_mouse_buttons
))
1362 if (pbutton
) *pbutton
= button
;
1368 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1370 If the event is a button press, then note that we have grabbed
1374 construct_mouse_click (result
, msg
, f
)
1375 struct input_event
*result
;
1382 parse_button (msg
->msg
.message
, &button
, &up
);
1384 /* Make the event type no_event; we'll change that when we decide
1386 result
->kind
= mouse_click
;
1387 result
->code
= button
;
1388 result
->timestamp
= msg
->msg
.time
;
1389 result
->modifiers
= (msg
->dwModifiers
1397 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1398 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1399 XSETFRAME (result
->frame_or_window
, f
);
1404 construct_mouse_wheel (result
, msg
, f
)
1405 struct input_event
*result
;
1410 result
->kind
= mouse_wheel
;
1411 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1412 result
->timestamp
= msg
->msg
.time
;
1413 result
->modifiers
= msg
->dwModifiers
;
1414 p
.x
= LOWORD (msg
->msg
.lParam
);
1415 p
.y
= HIWORD (msg
->msg
.lParam
);
1416 ScreenToClient(msg
->msg
.hwnd
, &p
);
1417 XSETINT (result
->x
, p
.x
);
1418 XSETINT (result
->y
, p
.y
);
1419 XSETFRAME (result
->frame_or_window
, f
);
1423 construct_drag_n_drop (result
, msg
, f
)
1424 struct input_event
*result
;
1436 result
->kind
= drag_n_drop
;
1438 result
->timestamp
= msg
->msg
.time
;
1439 result
->modifiers
= msg
->dwModifiers
;
1441 p
.x
= LOWORD (msg
->msg
.lParam
);
1442 p
.y
= HIWORD (msg
->msg
.lParam
);
1443 ScreenToClient (msg
->msg
.hwnd
, &p
);
1444 XSETINT (result
->x
, p
.x
);
1445 XSETINT (result
->y
, p
.y
);
1447 hdrop
= (HDROP
) msg
->msg
.wParam
;
1448 DragQueryPoint (hdrop
, &p
);
1449 num_files
= DragQueryFile (hdrop
, 0xFFFFFFFF, NULL
, 0);
1452 for (i
= 0; i
< num_files
; i
++)
1454 len
= DragQueryFile (hdrop
, i
, NULL
, 0);
1457 name
= alloca (len
+ 1);
1458 DragQueryFile (hdrop
, i
, name
, len
+ 1);
1459 files
= Fcons (build_string (name
), files
);
1464 XSETFRAME (frame
, f
);
1465 result
->frame_or_window
= Fcons (frame
, files
);
1469 /* Function to report a mouse movement to the mainstream Emacs code.
1470 The input handler calls this.
1472 We have received a mouse movement event, which is given in *event.
1473 If the mouse is over a different glyph than it was last time, tell
1474 the mainstream emacs code by setting mouse_moved. If not, ask for
1475 another motion event, so we can check again the next time it moves. */
1478 note_mouse_movement (frame
, msg
)
1482 last_mouse_movement_time
= msg
->time
;
1484 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
1486 frame
->mouse_moved
= 1;
1487 last_mouse_scroll_bar
= Qnil
;
1489 note_mouse_highlight (frame
, -1, -1);
1492 /* Has the mouse moved off the glyph it was on at the last sighting? */
1493 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1494 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1495 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
1496 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1498 frame
->mouse_moved
= 1;
1499 last_mouse_scroll_bar
= Qnil
;
1501 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1505 /* This is used for debugging, to turn off note_mouse_highlight. */
1506 static int disable_mouse_highlight
;
1508 /* Take proper action when the mouse has moved to position X, Y on frame F
1509 as regards highlighting characters that have mouse-face properties.
1510 Also dehighlighting chars where the mouse was before.
1511 X and Y can be negative or out of range. */
1514 note_mouse_highlight (f
, x
, y
)
1518 int row
, column
, portion
;
1523 if (disable_mouse_highlight
)
1526 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1527 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1528 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1530 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
1535 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1539 /* Find out which glyph the mouse is on. */
1540 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1541 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
1543 /* Which window is that in? */
1544 window
= window_from_coordinates (f
, column
, row
, &portion
);
1545 w
= XWINDOW (window
);
1547 /* If we were displaying active text in another window, clear that. */
1548 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
1549 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1551 /* Are we in a window whose display is up to date?
1552 And verify the buffer's text has not changed. */
1553 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1554 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1555 && EQ (w
->window_end_valid
, w
->buffer
)
1556 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
1557 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
1559 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1562 /* Find which buffer position the mouse corresponds to. */
1563 for (i
= column
; i
>= 0; i
--)
1567 /* Is it outside the displayed active region (if any)? */
1569 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1570 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
1571 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1572 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1573 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1574 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1575 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1576 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1577 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1579 Lisp_Object mouse_face
, overlay
, position
;
1580 Lisp_Object
*overlay_vec
;
1581 int len
, noverlays
, ignor1
;
1582 struct buffer
*obuf
;
1585 /* If we get an out-of-range value, return now; avoid an error. */
1586 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1589 /* Make the window's buffer temporarily current for
1590 overlays_at and compute_char_face. */
1591 obuf
= current_buffer
;
1592 current_buffer
= XBUFFER (w
->buffer
);
1598 /* Yes. Clear the display of the old active region, if any. */
1599 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1601 /* Is this char mouse-active? */
1602 XSETINT (position
, pos
);
1605 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1607 /* Put all the overlays we want in a vector in overlay_vec.
1608 Store the length in len. */
1609 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1611 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1613 /* Find the highest priority overlay that has a mouse-face prop. */
1615 for (i
= 0; i
< noverlays
; i
++)
1617 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1618 if (!NILP (mouse_face
))
1620 overlay
= overlay_vec
[i
];
1625 /* If no overlay applies, get a text property. */
1627 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1629 /* Handle the overlay case. */
1630 if (! NILP (overlay
))
1632 /* Find the range of text around this char that
1633 should be active. */
1634 Lisp_Object before
, after
;
1637 before
= Foverlay_start (overlay
);
1638 after
= Foverlay_end (overlay
);
1639 /* Record this as the current active region. */
1640 fast_find_position (window
, before
,
1641 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1642 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1643 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1644 = !fast_find_position (window
, after
,
1645 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1646 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1647 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1648 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1649 = compute_char_face (f
, w
, pos
, 0, 0,
1650 &ignore
, pos
+ 1, 1);
1652 /* Display it as active. */
1653 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1655 /* Handle the text property case. */
1656 else if (! NILP (mouse_face
))
1658 /* Find the range of text around this char that
1659 should be active. */
1660 Lisp_Object before
, after
, beginning
, end
;
1663 beginning
= Fmarker_position (w
->start
);
1664 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1665 - XFASTINT (w
->window_end_pos
)));
1667 = Fprevious_single_property_change (make_number (pos
+ 1),
1669 w
->buffer
, beginning
);
1671 = Fnext_single_property_change (position
, Qmouse_face
,
1673 /* Record this as the current active region. */
1674 fast_find_position (window
, before
,
1675 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1676 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1677 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1678 = !fast_find_position (window
, after
,
1679 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1680 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1681 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1682 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1683 = compute_char_face (f
, w
, pos
, 0, 0,
1684 &ignore
, pos
+ 1, 1);
1686 /* Display it as active. */
1687 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1691 current_buffer
= obuf
;
1696 /* Find the row and column of position POS in window WINDOW.
1697 Store them in *COLUMNP and *ROWP.
1698 This assumes display in WINDOW is up to date.
1699 If POS is above start of WINDOW, return coords
1700 of start of first screen line.
1701 If POS is after end of WINDOW, return coords of end of last screen line.
1703 Value is 1 if POS is in range, 0 if it was off screen. */
1706 fast_find_position (window
, pos
, columnp
, rowp
)
1709 int *columnp
, *rowp
;
1711 struct window
*w
= XWINDOW (window
);
1712 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1715 int left
= WINDOW_LEFT_MARGIN (w
);
1717 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1718 int width
= window_internal_width (w
);
1721 int maybe_next_line
= 0;
1723 /* Find the right row. */
1728 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1729 if (linestart
> pos
)
1731 /* If the position sought is the end of the buffer,
1732 don't include the blank lines at the bottom of the window. */
1733 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1735 maybe_next_line
= 1;
1742 /* Find the right column with in it. */
1743 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1745 for (i
= 0; i
< width
; i
++)
1747 if (charstarts
[left
+ i
] == pos
)
1750 *columnp
= i
+ left
;
1753 else if (charstarts
[left
+ i
] > pos
)
1755 else if (charstarts
[left
+ i
] > 0)
1759 /* If we're looking for the end of the buffer,
1760 and we didn't find it in the line we scanned,
1761 use the start of the following line. */
1762 if (maybe_next_line
)
1773 /* Display the active region described by mouse_face_*
1774 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1777 show_mouse_face (dpyinfo
, hl
)
1778 struct w32_display_info
*dpyinfo
;
1781 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1782 int width
= window_internal_width (w
);
1783 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1786 int old_curs_x
= curs_x
;
1787 int old_curs_y
= curs_y
;
1789 /* Set these variables temporarily
1790 so that if we have to turn the cursor off and on again
1791 we will put it back at the same place. */
1792 curs_x
= f
->phys_cursor_x
;
1793 curs_y
= f
->phys_cursor_y
;
1795 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1796 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1798 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1799 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
1800 : WINDOW_LEFT_MARGIN (w
));
1801 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1802 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1803 : WINDOW_LEFT_MARGIN (w
) + width
);
1804 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1806 /* If the cursor's in the text we are about to rewrite,
1807 turn the cursor off. */
1809 && curs_x
>= column
- 1
1810 && curs_x
<= endcolumn
)
1812 x_display_cursor (f
, 0);
1817 CHAR_TO_PIXEL_COL (f
, column
),
1818 CHAR_TO_PIXEL_ROW (f
, i
),
1819 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1821 /* Highlight with mouse face if hl > 0. */
1822 hl
> 0 ? 3 : 0, 0, NULL
);
1825 /* If we turned the cursor off, turn it back on. */
1827 x_display_cursor (f
, 1);
1829 curs_x
= old_curs_x
;
1830 curs_y
= old_curs_y
;
1832 /* Change the mouse cursor according to the value of HL. */
1834 SetCursor (f
->output_data
.w32
->cross_cursor
);
1836 SetCursor (f
->output_data
.w32
->text_cursor
);
1839 /* Clear out the mouse-highlighted active region.
1840 Redraw it unhighlighted first. */
1843 clear_mouse_face (dpyinfo
)
1844 struct w32_display_info
*dpyinfo
;
1846 if (! NILP (dpyinfo
->mouse_face_window
))
1847 show_mouse_face (dpyinfo
, 0);
1849 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1850 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1851 dpyinfo
->mouse_face_window
= Qnil
;
1854 struct scroll_bar
*x_window_to_scroll_bar ();
1855 static void x_scroll_bar_report_motion ();
1857 /* Return the current position of the mouse.
1858 *fp should be a frame which indicates which display to ask about.
1860 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1861 and *part to the frame, window, and scroll bar part that the mouse
1862 is over. Set *x and *y to the portion and whole of the mouse's
1863 position on the scroll bar.
1865 If the mouse movement started elsewhere, set *fp to the frame the
1866 mouse is on, *bar_window to nil, and *x and *y to the character cell
1869 Set *time to the server timestamp for the time at which the mouse
1870 was at this position.
1872 Don't store anything if we don't have a valid set of values to report.
1874 This clears the mouse_moved flag, so we can wait for the next mouse
1875 movement. This also calls XQueryPointer, which will cause the
1876 server to give us another MotionNotify when the mouse moves
1880 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1883 Lisp_Object
*bar_window
;
1884 enum scroll_bar_part
*part
;
1886 unsigned long *time
;
1892 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
1893 /* This is never called at the moment. */
1894 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1899 Lisp_Object frame
, tail
;
1901 /* Clear the mouse-moved flag for every frame on this display. */
1902 FOR_EACH_FRAME (tail
, frame
)
1903 XFRAME (frame
)->mouse_moved
= 0;
1905 last_mouse_scroll_bar
= Qnil
;
1909 /* Now we have a position on the root; find the innermost window
1910 containing the pointer. */
1912 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1913 && FRAME_LIVE_P (last_mouse_frame
))
1915 f1
= last_mouse_frame
;
1919 /* Is win one of our frames? */
1920 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1923 /* If not, is it one of our scroll bars? */
1926 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1930 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1934 if (f1
== 0 && insist
> 0)
1935 f1
= selected_frame
;
1939 int ignore1
, ignore2
;
1941 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
1943 /* Ok, we found a frame. Store all the values. */
1945 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1947 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
1955 *time
= last_mouse_movement_time
;
1963 /* Scroll bar support. */
1965 /* Given an window ID, find the struct scroll_bar which manages it.
1966 This can be called in GC, so we have to make sure to strip off mark
1969 x_window_to_scroll_bar (window_id
)
1972 Lisp_Object tail
, frame
;
1974 for (tail
= Vframe_list
;
1975 XGCTYPE (tail
) == Lisp_Cons
;
1976 tail
= XCONS (tail
)->cdr
)
1978 Lisp_Object frame
, bar
, condemned
;
1980 frame
= XCONS (tail
)->car
;
1981 /* All elements of Vframe_list should be frames. */
1982 if (! GC_FRAMEP (frame
))
1985 /* Scan this frame's scroll bar list for a scroll bar with the
1987 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1988 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1989 /* This trick allows us to search both the ordinary and
1990 condemned scroll bar lists with one loop. */
1991 ! GC_NILP (bar
) || (bar
= condemned
,
1994 bar
= XSCROLL_BAR (bar
)->next
)
1995 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1996 return XSCROLL_BAR (bar
);
2003 my_create_scrollbar (f
, bar
)
2005 struct scroll_bar
* bar
;
2007 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
2008 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
2012 //#define ATTACH_THREADS
2015 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
2017 #ifndef ATTACH_THREADS
2018 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
2019 (WPARAM
) hwnd
, (LPARAM
) how
);
2021 return ShowWindow (hwnd
, how
);
2026 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
2027 int x
, int y
, int cx
, int cy
, UINT flags
)
2029 #ifndef ATTACH_THREADS
2031 pos
.hwndInsertAfter
= hwndAfter
;
2037 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
2039 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
2044 my_set_focus (f
, hwnd
)
2048 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
2053 my_set_foreground_window (hwnd
)
2056 SendMessage (hwnd
, WM_EMACS_SETFOREGROUND
, (WPARAM
) hwnd
, 0);
2060 my_destroy_window (f
, hwnd
)
2064 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
2068 /* Open a new window to serve as a scroll bar, and return the
2069 scroll bar vector for it. */
2070 static struct scroll_bar
*
2071 x_scroll_bar_create (window
, top
, left
, width
, height
)
2072 struct window
*window
;
2073 int top
, left
, width
, height
;
2075 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2076 struct scroll_bar
*bar
2077 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2082 XSETWINDOW (bar
->window
, window
);
2083 XSETINT (bar
->top
, top
);
2084 XSETINT (bar
->left
, left
);
2085 XSETINT (bar
->width
, width
);
2086 XSETINT (bar
->height
, height
);
2087 XSETINT (bar
->start
, 0);
2088 XSETINT (bar
->end
, 0);
2089 bar
->dragging
= Qnil
;
2091 /* Requires geometry to be set before call to create the real window */
2093 hwnd
= my_create_scrollbar (f
, bar
);
2095 if (pfnSetScrollInfo
)
2099 si
.cbSize
= sizeof (si
);
2102 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2103 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2107 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
2111 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2112 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
2115 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
2117 /* Add bar to its frame's list of scroll bars. */
2118 bar
->next
= FRAME_SCROLL_BARS (f
);
2120 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2121 if (! NILP (bar
->next
))
2122 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2129 /* Draw BAR's handle in the proper position.
2130 If the handle is already drawn from START to END, don't bother
2131 redrawing it, unless REBUILD is non-zero; in that case, always
2132 redraw it. (REBUILD is handy for drawing the handle after expose
2135 Normally, we want to constrain the start and end of the handle to
2136 fit inside its rectangle, but if the user is dragging the scroll bar
2137 handle, we want to let them drag it down all the way, so that the
2138 bar's top is as far down as it goes; otherwise, there's no way to
2139 move to the very end of the buffer. */
2141 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2142 struct scroll_bar
*bar
;
2146 int dragging
= ! NILP (bar
->dragging
);
2147 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2148 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2150 /* If the display is already accurate, do nothing. */
2152 && start
== XINT (bar
->start
)
2153 && end
== XINT (bar
->end
))
2159 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2161 /* Make sure the values are reasonable, and try to preserve
2162 the distance between start and end. */
2164 int length
= end
- start
;
2168 else if (start
> top_range
)
2170 end
= start
+ length
;
2174 else if (end
> top_range
&& ! dragging
)
2179 /* Store the adjusted setting in the scroll bar. */
2180 XSETINT (bar
->start
, start
);
2181 XSETINT (bar
->end
, end
);
2183 /* If being dragged, let scroll bar update itself. */
2186 if (pfnSetScrollInfo
)
2190 si
.cbSize
= sizeof (si
);
2191 si
.fMask
= SIF_PAGE
| SIF_POS
;
2192 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2195 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2198 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2204 /* Move a scroll bar around on the screen, to accommodate changing
2205 window configurations. */
2207 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2208 struct scroll_bar
*bar
;
2209 int top
, left
, width
, height
;
2211 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2212 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2214 /* If already correctly positioned, do nothing. */
2215 if ( XINT (bar
->left
) == left
2216 && XINT (bar
->top
) == top
2217 && XINT (bar
->width
) == width
2218 && XINT (bar
->height
) == height
)
2220 /* Redraw after clear_frame. */
2221 if (!my_show_window (f
, w
, SW_NORMAL
))
2222 InvalidateRect (w
, NULL
, FALSE
);
2228 /* Make sure scroll bar is "visible" before moving, to ensure the
2229 area of the parent window now exposed will be refreshed. */
2230 my_show_window (f
, w
, SW_HIDE
);
2231 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2232 if (pfnSetScrollInfo
)
2236 si
.cbSize
= sizeof (si
);
2237 si
.fMask
= SIF_RANGE
;
2239 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2240 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2242 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2245 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2246 my_show_window (f
, w
, SW_NORMAL
);
2247 // InvalidateRect (w, NULL, FALSE);
2249 XSETINT (bar
->left
, left
);
2250 XSETINT (bar
->top
, top
);
2251 XSETINT (bar
->width
, width
);
2252 XSETINT (bar
->height
, height
);
2257 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2260 x_scroll_bar_remove (bar
)
2261 struct scroll_bar
*bar
;
2263 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2267 /* Destroy the window. */
2268 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2270 /* Disassociate this scroll bar from its window. */
2271 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2276 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2277 that we are displaying PORTION characters out of a total of WHOLE
2278 characters, starting at POSITION. If WINDOW has no scroll bar,
2281 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2282 struct window
*window
;
2283 int portion
, whole
, position
;
2285 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2286 int top
= XINT (window
->top
);
2287 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2288 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2290 /* Where should this scroll bar be, pixelwise? */
2291 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2292 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2294 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2295 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2296 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2297 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2299 struct scroll_bar
*bar
;
2301 /* Does the scroll bar exist yet? */
2302 if (NILP (window
->vertical_scroll_bar
))
2303 bar
= x_scroll_bar_create (window
,
2304 pixel_top
, pixel_left
,
2305 pixel_width
, pixel_height
);
2308 /* It may just need to be moved and resized. */
2309 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2310 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2313 /* Set the scroll bar's current state. */
2315 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2318 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2321 int start
= (int) (((double) position
* top_range
) / whole
);
2322 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2324 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2328 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2332 /* The following three hooks are used when we're doing a thorough
2333 redisplay of the frame. We don't explicitly know which scroll bars
2334 are going to be deleted, because keeping track of when windows go
2335 away is a real pain - "Can you say set-window-configuration, boys
2336 and girls?" Instead, we just assert at the beginning of redisplay
2337 that *all* scroll bars are to be removed, and then save a scroll bar
2338 from the fiery pit when we actually redisplay its window. */
2340 /* Arrange for all scroll bars on FRAME to be removed at the next call
2341 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2342 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2344 w32_condemn_scroll_bars (frame
)
2347 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2348 while (! NILP (FRAME_SCROLL_BARS (frame
)))
2351 bar
= FRAME_SCROLL_BARS (frame
);
2352 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
2353 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
2354 XSCROLL_BAR (bar
)->prev
= Qnil
;
2355 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2356 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
2357 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
2360 /* The condemned list should be empty at this point; if it's not,
2361 then the rest of Emacs isn't using the condemn/redeem/judge
2362 protocol correctly. */
2363 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2366 /* Move them all to the "condemned" list. */
2367 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2368 FRAME_SCROLL_BARS (frame
) = Qnil
;
2372 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2373 Note that WINDOW isn't necessarily condemned at all. */
2375 w32_redeem_scroll_bar (window
)
2376 struct window
*window
;
2378 struct scroll_bar
*bar
;
2380 /* We can't redeem this window's scroll bar if it doesn't have one. */
2381 if (NILP (window
->vertical_scroll_bar
))
2384 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2386 /* Unlink it from the condemned list. */
2388 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2390 if (NILP (bar
->prev
))
2392 /* If the prev pointer is nil, it must be the first in one of
2394 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2395 /* It's not condemned. Everything's fine. */
2397 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2398 window
->vertical_scroll_bar
))
2399 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2401 /* If its prev pointer is nil, it must be at the front of
2402 one or the other! */
2406 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2408 if (! NILP (bar
->next
))
2409 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2411 bar
->next
= FRAME_SCROLL_BARS (f
);
2413 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2414 if (! NILP (bar
->next
))
2415 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2418 struct scroll_bar
*bar
;
2420 /* We can't redeem this window's scroll bar if it doesn't have one. */
2421 if (NILP (window
->vertical_scroll_bar
))
2424 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2426 /* Unlink it from the condemned list. */
2428 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2430 if (NILP (bar
->prev
))
2432 /* If the prev pointer is nil, it must be the first in one of
2434 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2435 /* It's not condemned. Everything's fine. */
2437 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2438 window
->vertical_scroll_bar
))
2439 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2441 /* If its prev pointer is nil, it must be at the front of
2442 one or the other! */
2446 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2448 if (! NILP (bar
->next
))
2449 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2451 bar
->next
= FRAME_SCROLL_BARS (f
);
2453 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2454 if (! NILP (bar
->next
))
2455 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2460 /* Remove all scroll bars on FRAME that haven't been saved since the
2461 last call to `*condemn_scroll_bars_hook'. */
2463 w32_judge_scroll_bars (f
)
2466 Lisp_Object bar
, next
;
2468 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2470 /* Clear out the condemned list now so we won't try to process any
2471 more events on the hapless scroll bars. */
2472 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2474 for (; ! NILP (bar
); bar
= next
)
2476 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2478 x_scroll_bar_remove (b
);
2481 b
->next
= b
->prev
= Qnil
;
2484 /* Now there should be no references to the condemned scroll bars,
2485 and they should get garbage-collected. */
2487 Lisp_Object bar
, next
;
2489 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2491 /* Clear out the condemned list now so we won't try to process any
2492 more events on the hapless scroll bars. */
2493 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2495 for (; ! NILP (bar
); bar
= next
)
2497 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2499 x_scroll_bar_remove (b
);
2502 b
->next
= b
->prev
= Qnil
;
2505 /* Now there should be no references to the condemned scroll bars,
2506 and they should get garbage-collected. */
2510 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2511 is set to something other than no_event, it is enqueued.
2513 This may be called from a signal handler, so we have to ignore GC
2517 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2518 struct scroll_bar
*bar
;
2520 struct input_event
*emacs_event
;
2522 if (! GC_WINDOWP (bar
->window
))
2525 emacs_event
->kind
= w32_scroll_bar_click
;
2526 emacs_event
->code
= 0;
2527 /* not really meaningful to distinguish up/down */
2528 emacs_event
->modifiers
= msg
->dwModifiers
;
2529 emacs_event
->frame_or_window
= bar
->window
;
2530 emacs_event
->timestamp
= msg
->msg
.time
;
2533 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2535 int dragging
= !NILP (bar
->dragging
);
2537 if (pfnGetScrollInfo
)
2541 si
.cbSize
= sizeof (si
);
2544 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
2548 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2550 bar
->dragging
= Qnil
;
2552 switch (LOWORD (msg
->msg
.wParam
))
2555 emacs_event
->part
= scroll_bar_down_arrow
;
2558 emacs_event
->part
= scroll_bar_up_arrow
;
2561 emacs_event
->part
= scroll_bar_above_handle
;
2564 emacs_event
->part
= scroll_bar_below_handle
;
2567 emacs_event
->part
= scroll_bar_handle
;
2571 emacs_event
->part
= scroll_bar_handle
;
2575 case SB_THUMBPOSITION
:
2576 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2577 y
= HIWORD (msg
->msg
.wParam
);
2579 emacs_event
->part
= scroll_bar_handle
;
2581 /* "Silently" update current position. */
2582 if (pfnSetScrollInfo
)
2586 si
.cbSize
= sizeof (si
);
2590 /* Shrink handle if necessary to allow full range for position. */
2592 int start
= XINT (bar
->start
);
2593 int end
= XINT (bar
->end
);
2594 int len
= end
- start
;
2596 /* If new end is nearly hitting bottom, we must shrink
2597 handle. How much we shrink it depends on the relative
2598 sizes of len and top_range. */
2599 if (y
+ len
> top_range
- 2)
2601 len
-= min (top_range
/ 10, (len
/ 3) + 2);
2605 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2606 si
.fMask
|= SIF_PAGE
;
2610 /* Remember apparent position (we actually lag behind the real
2611 position, so don't set that directly. */
2612 last_scroll_bar_drag_pos
= y
;
2614 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
2617 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
2620 /* If this is the end of a drag sequence, then reset the scroll
2621 handle size to normal and do a final redraw. Otherwise do
2625 if (pfnSetScrollInfo
)
2628 int start
= XINT (bar
->start
);
2629 int end
= XINT (bar
->end
);
2631 si
.cbSize
= sizeof (si
);
2632 si
.fMask
= SIF_PAGE
| SIF_POS
;
2633 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2634 si
.nPos
= last_scroll_bar_drag_pos
;
2636 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
2639 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
2643 emacs_event
->kind
= no_event
;
2647 XSETINT (emacs_event
->x
, y
);
2648 XSETINT (emacs_event
->y
, top_range
);
2654 /* Return information to the user about the current position of the mouse
2655 on the scroll bar. */
2657 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2659 Lisp_Object
*bar_window
;
2660 enum scroll_bar_part
*part
;
2662 unsigned long *time
;
2664 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2665 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2666 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2668 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2673 *bar_window
= bar
->window
;
2675 if (pfnGetScrollInfo
)
2679 si
.cbSize
= sizeof (si
);
2680 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
2682 pfnGetScrollInfo (w
, SB_CTL
, &si
);
2684 top_range
= si
.nMax
- si
.nPage
+ 1;
2687 pos
= GetScrollPos (w
, SB_CTL
);
2689 switch (LOWORD (last_mouse_scroll_bar_pos
))
2691 case SB_THUMBPOSITION
:
2693 *part
= scroll_bar_handle
;
2694 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2695 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2698 *part
= scroll_bar_handle
;
2702 *part
= scroll_bar_handle
;
2707 XSETINT(*y
, top_range
);
2710 last_mouse_scroll_bar
= Qnil
;
2712 *time
= last_mouse_movement_time
;
2717 /* The screen has been cleared so we may have changed foreground or
2718 background colors, and the scroll bars may need to be redrawn.
2719 Clear out the scroll bars, and ask for expose events, so we can
2722 x_scroll_bar_clear (f
)
2727 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2728 bar
= XSCROLL_BAR (bar
)->next
)
2730 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2731 HDC hdc
= GetDC (window
);
2734 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
2735 arranges to refresh the scroll bar if hidden. */
2736 my_show_window (f
, window
, SW_HIDE
);
2738 GetClientRect (window
, &rect
);
2739 select_palette (f
, hdc
);
2740 w32_clear_rect (f
, hdc
, &rect
);
2741 deselect_palette (f
, hdc
);
2743 ReleaseDC (window
, hdc
);
2747 show_scroll_bars (f
, how
)
2753 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2754 bar
= XSCROLL_BAR (bar
)->next
)
2756 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2757 my_show_window (f
, window
, how
);
2762 /* The main W32 event-reading loop - w32_read_socket. */
2764 /* Timestamp of enter window event. This is only used by w32_read_socket,
2765 but we have to put it out here, since static variables within functions
2766 sometimes don't work. */
2767 static Time enter_timestamp
;
2769 /* Record the last 100 characters stored
2770 to help debug the loss-of-chars-during-GC problem. */
2772 short temp_buffer
[100];
2774 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*, int *isdead
);
2776 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
2777 we can use the same routines to handle input in both console
2778 and window modes. */
2781 convert_to_key_event (W32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2783 eventp
->bKeyDown
= TRUE
;
2784 eventp
->wRepeatCount
= 1;
2785 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2786 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2787 eventp
->uChar
.AsciiChar
= 0;
2788 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2791 /* Return nonzero if the virtual key is a dead key. */
2794 is_dead_key (int wparam
)
2796 unsigned int code
= MapVirtualKey (wparam
, 2);
2798 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2799 if ((code
& 0x8000) || (code
& 0x80000000))
2805 /* Read events coming from the W32 shell.
2806 This routine is called by the SIGIO handler.
2807 We return as soon as there are no more events to be read.
2809 Events representing keys are stored in buffer BUFP,
2810 which can hold up to NUMCHARS characters.
2811 We return the number of characters stored into the buffer,
2812 thus pretending to be `read'.
2814 EXPECTED is nonzero if the caller knows input is available.
2816 Some of these messages are reposted back to the message queue since the
2817 system calls the windows proc directly in a context where we cannot return
2818 the data nor can we guarantee the state we are in. So if we dispatch them
2819 we will get into an infinite loop. To prevent this from ever happening we
2820 will set a variable to indicate we are in the read_socket call and indicate
2821 which message we are processing since the windows proc gets called
2822 recursively with different messages by the system.
2826 w32_read_socket (sd
, bufp
, numchars
, expected
)
2828 register struct input_event
*bufp
;
2829 register int numchars
;
2833 int check_visibility
= 0;
2837 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2839 if (interrupt_input_blocked
)
2841 interrupt_input_pending
= 1;
2845 interrupt_input_pending
= 0;
2848 /* So people can tell when we have read the available input. */
2849 input_signal_count
++;
2852 abort (); /* Don't think this happens. */
2854 while (get_next_msg (&msg
, FALSE
))
2856 switch (msg
.msg
.message
)
2859 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2863 if (msg
.rect
.right
== msg
.rect
.left
||
2864 msg
.rect
.bottom
== msg
.rect
.top
)
2866 /* We may get paint messages even though the client
2867 area is clipped - these are not expose events. */
2868 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f
,
2869 XSTRING (f
->name
)->data
));
2871 else if (f
->async_visible
!= 1)
2873 /* Definitely not obscured, so mark as visible. */
2874 f
->async_visible
= 1;
2875 f
->async_iconified
= 0;
2876 SET_FRAME_GARBAGED (f
);
2877 DebPrint (("frame %04x (%s) reexposed\n", f
,
2878 XSTRING (f
->name
)->data
));
2880 /* WM_PAINT serves as MapNotify as well, so report
2881 visibility changes properly. */
2884 bufp
->kind
= deiconify_event
;
2885 XSETFRAME (bufp
->frame_or_window
, f
);
2890 else if (! NILP(Vframe_list
)
2891 && ! NILP (XCONS (Vframe_list
)->cdr
))
2892 /* Force a redisplay sooner or later to update the
2893 frame titles in case this is the second frame. */
2894 record_asynch_buffer_change ();
2898 /* Erase background again for safety. */
2899 w32_clear_rect (f
, NULL
, &msg
.rect
);
2903 msg
.rect
.right
- msg
.rect
.left
,
2904 msg
.rect
.bottom
- msg
.rect
.top
);
2911 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2913 if (f
&& !f
->iconified
)
2915 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2917 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2918 bufp
->kind
= non_ascii_keystroke
;
2919 bufp
->code
= msg
.msg
.wParam
;
2920 bufp
->modifiers
= w32_kbd_mods_to_emacs (msg
.dwModifiers
,
2922 XSETFRAME (bufp
->frame_or_window
, f
);
2923 bufp
->timestamp
= msg
.msg
.time
;
2932 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2934 if (f
&& !f
->iconified
)
2940 KEY_EVENT_RECORD key
, *keyp
= &key
;
2942 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2945 convert_to_key_event (&msg
, keyp
);
2946 add
= key_event (keyp
, bufp
, &isdead
);
2947 XSETFRAME (bufp
->frame_or_window
, f
);
2950 /* The key pressed generated two characters, most likely
2951 an accent character and a key that could not be
2952 combined with it. Prepend the message on the queue
2953 again to process the second character (which is
2954 being held internally in key_event), and process
2955 the first character now. */
2975 if (dpyinfo
->grabbed
&& last_mouse_frame
2976 && FRAME_LIVE_P (last_mouse_frame
))
2977 f
= last_mouse_frame
;
2979 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2982 note_mouse_movement (f
, &msg
.msg
);
2984 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2988 case WM_LBUTTONDOWN
:
2990 case WM_MBUTTONDOWN
:
2992 case WM_RBUTTONDOWN
:
2998 if (dpyinfo
->grabbed
&& last_mouse_frame
2999 && FRAME_LIVE_P (last_mouse_frame
))
3000 f
= last_mouse_frame
;
3002 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3006 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
3009 construct_mouse_click (bufp
, &msg
, f
);
3016 parse_button (msg
.msg
.message
, &button
, &up
);
3020 dpyinfo
->grabbed
&= ~ (1 << button
);
3024 dpyinfo
->grabbed
|= (1 << button
);
3025 last_mouse_frame
= f
;
3031 if (dpyinfo
->grabbed
&& last_mouse_frame
3032 && FRAME_LIVE_P (last_mouse_frame
))
3033 f
= last_mouse_frame
;
3035 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3039 if ((!dpyinfo
->w32_focus_frame
3040 || f
== dpyinfo
->w32_focus_frame
)
3043 construct_mouse_wheel (bufp
, &msg
, f
);
3052 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3056 construct_drag_n_drop (bufp
, &msg
, f
);
3065 struct scroll_bar
*bar
=
3066 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
3068 if (bar
&& numchars
>= 1)
3070 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
3080 case WM_WINDOWPOSCHANGED
:
3082 case WM_ACTIVATEAPP
:
3083 check_visibility
= 1;
3087 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3089 if (f
&& !f
->async_iconified
)
3093 x_real_positions (f
, &x
, &y
);
3094 f
->output_data
.w32
->left_pos
= x
;
3095 f
->output_data
.w32
->top_pos
= y
;
3098 check_visibility
= 1;
3102 /* If window has been obscured or exposed by another window
3103 being maximised or minimised/restored, then recheck
3104 visibility of all frames. Direct changes to our own
3105 windows get handled by WM_SIZE. */
3107 if (msg
.msg
.lParam
!= 0)
3108 check_visibility
= 1;
3111 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3112 f
->async_visible
= msg
.msg
.wParam
;
3116 check_visibility
= 1;
3120 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3122 /* Inform lisp of whether frame has been iconified etc. */
3125 switch (msg
.msg
.wParam
)
3127 case SIZE_MINIMIZED
:
3128 f
->async_visible
= 0;
3129 f
->async_iconified
= 1;
3131 bufp
->kind
= iconify_event
;
3132 XSETFRAME (bufp
->frame_or_window
, f
);
3138 case SIZE_MAXIMIZED
:
3140 f
->async_visible
= 1;
3141 f
->async_iconified
= 0;
3143 /* wait_reading_process_input will notice this and update
3144 the frame's display structures. */
3145 SET_FRAME_GARBAGED (f
);
3149 bufp
->kind
= deiconify_event
;
3150 XSETFRAME (bufp
->frame_or_window
, f
);
3156 /* Force a redisplay sooner or later
3157 to update the frame titles
3158 in case this is the second frame. */
3159 record_asynch_buffer_change ();
3164 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
3172 GetClientRect(msg
.msg
.hwnd
, &rect
);
3174 height
= rect
.bottom
- rect
.top
;
3175 width
= rect
.right
- rect
.left
;
3177 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
3178 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
3180 /* TODO: Clip size to the screen dimensions. */
3182 /* Even if the number of character rows and columns has
3183 not changed, the font size may have changed, so we need
3184 to check the pixel dimensions as well. */
3186 if (columns
!= f
->width
3187 || rows
!= f
->height
3188 || width
!= f
->output_data
.w32
->pixel_width
3189 || height
!= f
->output_data
.w32
->pixel_height
)
3191 /* I had set this to 0, 0 - I am not sure why?? */
3193 change_frame_size (f
, rows
, columns
, 0, 1);
3194 SET_FRAME_GARBAGED (f
);
3196 f
->output_data
.w32
->pixel_width
= width
;
3197 f
->output_data
.w32
->pixel_height
= height
;
3198 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3202 check_visibility
= 1;
3207 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3209 if (msg
.msg
.message
== WM_SETFOCUS
)
3211 x_new_focus_frame (dpyinfo
, f
);
3213 else if (f
== dpyinfo
->w32_focus_frame
)
3215 x_new_focus_frame (dpyinfo
, 0);
3218 check_visibility
= 1;
3222 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3229 bufp
->kind
= delete_window_event
;
3230 XSETFRAME (bufp
->frame_or_window
, f
);
3238 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3245 bufp
->kind
= menu_bar_activate_event
;
3246 XSETFRAME (bufp
->frame_or_window
, f
);
3254 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3258 extern void menubar_selection_callback (FRAME_PTR f
, void * client_data
);
3259 menubar_selection_callback (f
, (void *)msg
.msg
.wParam
);
3262 check_visibility
= 1;
3265 case WM_DISPLAYCHANGE
:
3266 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3270 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3271 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3272 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3273 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3277 check_visibility
= 1;
3281 /* Check for messages registered at runtime. */
3282 if (msg
.msg
.message
== msh_mousewheel
)
3284 if (dpyinfo
->grabbed
&& last_mouse_frame
3285 && FRAME_LIVE_P (last_mouse_frame
))
3286 f
= last_mouse_frame
;
3288 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3292 if ((!dpyinfo
->w32_focus_frame
3293 || f
== dpyinfo
->w32_focus_frame
)
3296 construct_mouse_wheel (bufp
, &msg
, f
);
3307 /* If the focus was just given to an autoraising frame,
3309 /* ??? This ought to be able to handle more than one such frame. */
3310 if (pending_autoraise_frame
)
3312 x_raise_frame (pending_autoraise_frame
);
3313 pending_autoraise_frame
= 0;
3316 /* Check which frames are still visisble, if we have enqueued any user
3317 events or been notified of events that may affect visibility. We
3318 do this here because there doesn't seem to be any direct
3319 notification from Windows that the visibility of a window has
3320 changed (at least, not in all cases). */
3321 if (count
> 0 || check_visibility
)
3323 Lisp_Object tail
, frame
;
3325 FOR_EACH_FRAME (tail
, frame
)
3327 FRAME_PTR f
= XFRAME (frame
);
3328 /* Check "visible" frames and mark each as obscured or not.
3329 Note that async_visible is nonzero for unobscured and
3330 obscured frames, but zero for hidden and iconified frames. */
3331 if (FRAME_W32_P (f
) && f
->async_visible
)
3334 HDC hdc
= get_frame_dc (f
);
3335 GetClipBox (hdc
, &clipbox
);
3336 release_frame_dc (f
, hdc
);
3338 if (clipbox
.right
== clipbox
.left
3339 || clipbox
.bottom
== clipbox
.top
)
3341 /* Frame has become completely obscured so mark as
3342 such (we do this by setting async_visible to 2 so
3343 that FRAME_VISIBLE_P is still true, but redisplay
3345 f
->async_visible
= 2;
3347 if (!FRAME_OBSCURED_P (f
))
3349 DebPrint (("frame %04x (%s) obscured\n", f
,
3350 XSTRING (f
->name
)->data
));
3355 /* Frame is not obscured, so mark it as such. */
3356 f
->async_visible
= 1;
3358 if (FRAME_OBSCURED_P (f
))
3360 SET_FRAME_GARBAGED (f
);
3361 DebPrint (("frame %04x (%s) reexposed\n", f
,
3362 XSTRING (f
->name
)->data
));
3364 /* Force a redisplay sooner or later. */
3365 record_asynch_buffer_change ();
3376 /* Drawing the cursor. */
3379 /* Draw a hollow box cursor. Don't change the inside of the box. */
3389 hdc
= get_frame_dc (f
);
3391 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3393 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3394 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3395 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3396 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3398 FrameRect (hdc
, &rect
, hb
);
3401 release_frame_dc (f
, hdc
);
3404 /* Clear the cursor of frame F to background color,
3405 and mark the cursor as not shown.
3406 This is used when the text where the cursor is
3407 is about to be rewritten. */
3413 if (! FRAME_VISIBLE_P (f
)
3414 || f
->phys_cursor_x
< 0)
3417 x_display_cursor (f
, 0);
3418 f
->phys_cursor_x
= -1;
3421 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3422 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3426 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3433 CHAR_TO_PIXEL_COL (f
, column
),
3434 CHAR_TO_PIXEL_ROW (f
, row
),
3435 &glyph
, 1, highlight
, 0, NULL
);
3439 x_display_bar_cursor (f
, on
)
3443 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3445 /* This is pointless on invisible frames, and dangerous on garbaged
3446 frames; in the latter case, the frame may be in the midst of
3447 changing its size, and curs_x and curs_y may be off the frame. */
3448 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3451 if (! on
&& f
->phys_cursor_x
< 0)
3454 /* If there is anything wrong with the current cursor state, remove it. */
3455 if (f
->phys_cursor_x
>= 0
3457 || f
->phys_cursor_x
!= curs_x
3458 || f
->phys_cursor_y
!= curs_y
3459 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
3461 /* Erase the cursor by redrawing the character underneath it. */
3462 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3463 f
->phys_cursor_glyph
,
3464 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3465 f
->phys_cursor_x
= -1;
3468 /* If we now need a cursor in the new place or in the new form, do it so. */
3470 && (f
->phys_cursor_x
< 0
3471 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
3473 f
->phys_cursor_glyph
3474 = ((current_glyphs
->enable
[curs_y
]
3475 && curs_x
< current_glyphs
->used
[curs_y
])
3476 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3478 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
3479 CHAR_TO_PIXEL_COL (f
, curs_x
),
3480 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3481 max (f
->output_data
.w32
->cursor_width
, 1),
3482 f
->output_data
.w32
->line_height
);
3484 f
->phys_cursor_x
= curs_x
;
3485 f
->phys_cursor_y
= curs_y
;
3487 f
->output_data
.w32
->current_cursor
= bar_cursor
;
3492 /* Turn the displayed cursor of frame F on or off according to ON.
3493 If ON is nonzero, where to put the cursor is specified
3494 by F->cursor_x and F->cursor_y. */
3497 x_display_box_cursor (f
, on
)
3501 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3503 /* This is pointless on invisible frames, and dangerous on garbaged
3504 frames; in the latter case, the frame may be in the midst of
3505 changing its size, and curs_x and curs_y may be off the frame. */
3506 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3509 /* If cursor is off and we want it off, return quickly. */
3510 if (!on
&& f
->phys_cursor_x
< 0)
3513 /* If cursor is currently being shown and we don't want it to be
3514 or it is in the wrong place,
3515 or we want a hollow box and it's not so, (pout!)
3517 if (f
->phys_cursor_x
>= 0
3519 || f
->phys_cursor_x
!= curs_x
3520 || f
->phys_cursor_y
!= curs_y
3521 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
3522 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
3524 int mouse_face_here
= 0;
3525 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3527 /* If the cursor is in the mouse face area, redisplay that when
3528 we clear the cursor. */
3529 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
3530 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3531 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3532 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
3533 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3534 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3535 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
3536 /* Don't redraw the cursor's spot in mouse face
3537 if it is at the end of a line (on a newline).
3538 The cursor appears there, but mouse highlighting does not. */
3539 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
3540 mouse_face_here
= 1;
3542 /* If the font is not as tall as a whole line,
3543 we must explicitly clear the line's whole height. */
3544 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
3545 w32_clear_area (f
, NULL
,
3546 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3547 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3548 FONT_WIDTH (f
->output_data
.w32
->font
),
3549 f
->output_data
.w32
->line_height
);
3550 /* Erase the cursor by redrawing the character underneath it. */
3551 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3552 f
->phys_cursor_glyph
,
3555 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
3556 f
->phys_cursor_x
= -1;
3559 /* If we want to show a cursor,
3560 or we want a box cursor and it's not so,
3561 write it in the right place. */
3563 && (f
->phys_cursor_x
< 0
3564 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
3565 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
3567 f
->phys_cursor_glyph
3568 = ((current_glyphs
->enable
[curs_y
]
3569 && curs_x
< current_glyphs
->used
[curs_y
])
3570 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3572 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
3575 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
3579 x_draw_single_glyph (f
, curs_y
, curs_x
,
3580 f
->phys_cursor_glyph
, 2);
3581 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
3584 f
->phys_cursor_x
= curs_x
;
3585 f
->phys_cursor_y
= curs_y
;
3589 /* Display the cursor on frame F, or clear it, according to ON.
3590 Use the position specified by curs_x and curs_y
3591 if we are doing an update of frame F now.
3592 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
3595 x_display_cursor (f
, on
)
3601 /* If we're not updating, then we want to use the current frame's
3602 cursor position, not our local idea of where the cursor ought to be. */
3603 if (f
!= updating_frame
)
3605 curs_x
= FRAME_CURSOR_X (f
);
3606 curs_y
= FRAME_CURSOR_Y (f
);
3609 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3610 x_display_box_cursor (f
, on
);
3611 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3612 x_display_bar_cursor (f
, on
);
3614 /* Those are the only two we have implemented! */
3620 /* Changing the font of the frame. */
3622 /* Give frame F the font named FONTNAME as its default font, and
3623 return the full name of that font. FONTNAME may be a wildcard
3624 pattern; in that case, we choose some font that fits the pattern.
3625 The return value shows which font we chose. */
3628 x_new_font (f
, fontname
)
3630 register char *fontname
;
3633 int n_matching_fonts
;
3634 XFontStruct
*font_info
;
3635 char new_font_name
[101];
3637 /* Get a font which matches this name */
3641 if (!x_to_w32_font(fontname
, &lf
)
3642 || !w32_to_x_font(&lf
, new_font_name
, 100))
3648 /* See if we've already loaded a matching font. */
3649 already_loaded
= -1;
3654 for (i
= 0; i
< FRAME_W32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3655 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3658 fontname
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3663 /* If we have, just return it from the table. */
3664 if (already_loaded
>= 0)
3665 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3666 /* Otherwise, load the font and add it to the table. */
3672 font
= w32_load_font(FRAME_W32_DISPLAY_INFO (f
), fontname
);
3679 /* Do we need to create the table? */
3680 if (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
== 0)
3682 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
= 16;
3683 FRAME_W32_DISPLAY_INFO (f
)->font_table
3684 = (struct font_info
*) xmalloc (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3685 * sizeof (struct font_info
));
3687 /* Do we need to grow the table? */
3688 else if (FRAME_W32_DISPLAY_INFO (f
)->n_fonts
3689 >= FRAME_W32_DISPLAY_INFO (f
)->font_table_size
)
3691 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3692 FRAME_W32_DISPLAY_INFO (f
)->font_table
3693 = (struct font_info
*) xrealloc (FRAME_W32_DISPLAY_INFO (f
)->font_table
,
3694 (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3695 * sizeof (struct font_info
)));
3698 n_fonts
= FRAME_W32_DISPLAY_INFO (f
)->n_fonts
;
3699 FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3700 bcopy (fontname
, FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3701 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3702 FRAME_W32_DISPLAY_INFO (f
)->n_fonts
++;
3705 /* Compute the scroll bar width in character columns. */
3706 if (f
->scroll_bar_pixel_width
> 0)
3708 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
3709 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3712 f
->scroll_bar_cols
= 2;
3714 /* Now make the frame display the given font. */
3715 if (FRAME_W32_WINDOW (f
) != 0)
3717 frame_update_line_height (f
);
3718 x_set_window_size (f
, 0, f
->width
, f
->height
);
3721 /* If we are setting a new frame's font for the first time,
3722 there are no faces yet, so this font's height is the line height. */
3723 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
3726 Lisp_Object lispy_name
;
3728 lispy_name
= build_string (fontname
);
3734 /* Calculate the absolute position in frame F
3735 from its current recorded position values and gravity. */
3737 x_calc_absolute_position (f
)
3742 int flags
= f
->output_data
.w32
->size_hint_flags
;
3746 /* Find the position of the outside upper-left corner of
3747 the inner window, with respect to the outer window. */
3748 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
3751 MapWindowPoints (FRAME_W32_WINDOW (f
),
3752 f
->output_data
.w32
->parent_desc
,
3759 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3762 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
3763 FRAME_EXTERNAL_MENU_BAR (f
));
3766 pt
.x
+= (rt
.right
- rt
.left
);
3767 pt
.y
+= (rt
.bottom
- rt
.top
);
3770 /* Treat negative positions as relative to the leftmost bottommost
3771 position that fits on the screen. */
3772 if (flags
& XNegative
)
3773 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
3774 - 2 * f
->output_data
.w32
->border_width
- pt
.x
3776 + f
->output_data
.w32
->left_pos
);
3778 if (flags
& YNegative
)
3779 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
3780 - 2 * f
->output_data
.w32
->border_width
- pt
.y
3782 + f
->output_data
.w32
->top_pos
);
3783 /* The left_pos and top_pos
3784 are now relative to the top and left screen edges,
3785 so the flags should correspond. */
3786 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3789 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3790 to really change the position, and 0 when calling from
3791 x_make_frame_visible (in that case, XOFF and YOFF are the current
3792 position values). It is -1 when calling from x_set_frame_parameters,
3793 which means, do adjust for borders but don't change the gravity. */
3795 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3797 register int xoff
, yoff
;
3800 int modified_top
, modified_left
;
3802 if (change_gravity
> 0)
3804 f
->output_data
.w32
->top_pos
= yoff
;
3805 f
->output_data
.w32
->left_pos
= xoff
;
3806 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3808 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
3810 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
3811 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3813 x_calc_absolute_position (f
);
3816 x_wm_set_size_hint (f
, (long) 0, 0);
3818 /* It is a mystery why we need to add the border_width here
3819 when the frame is already visible, but experiment says we do. */
3820 modified_left
= f
->output_data
.w32
->left_pos
;
3821 modified_top
= f
->output_data
.w32
->top_pos
;
3823 /* Do not add in border widths under W32. */
3824 if (change_gravity
!= 0)
3826 modified_left
+= f
->output_data
.w32
->border_width
;
3827 modified_top
+= f
->output_data
.w32
->border_width
;
3831 my_set_window_pos (FRAME_W32_WINDOW (f
),
3833 modified_left
, modified_top
,
3835 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
3839 /* Call this to change the size of frame F's x-window.
3840 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3841 for this size change and subsequent size changes.
3842 Otherwise we leave the window gravity unchanged. */
3844 x_set_window_size (f
, change_gravity
, cols
, rows
)
3849 int pixelwidth
, pixelheight
;
3851 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3855 check_frame_size (f
, &rows
, &cols
);
3856 f
->output_data
.w32
->vertical_scroll_bar_extra
3857 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3859 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3860 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3861 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
3862 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3863 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3865 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3866 x_wm_set_size_hint (f
, (long) 0, 0);
3871 rect
.left
= rect
.top
= 0;
3872 rect
.right
= pixelwidth
;
3873 rect
.bottom
= pixelheight
;
3875 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
3876 FRAME_EXTERNAL_MENU_BAR (f
));
3878 my_set_window_pos (FRAME_W32_WINDOW (f
),
3881 rect
.right
- rect
.left
,
3882 rect
.bottom
- rect
.top
,
3883 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3886 /* Now, strictly speaking, we can't be sure that this is accurate,
3887 but the window manager will get around to dealing with the size
3888 change request eventually, and we'll hear how it went when the
3889 ConfigureNotify event gets here.
3891 We could just not bother storing any of this information here,
3892 and let the ConfigureNotify event set everything up, but that
3893 might be kind of confusing to the lisp code, since size changes
3894 wouldn't be reported in the frame parameters until some random
3895 point in the future when the ConfigureNotify event arrives. */
3896 change_frame_size (f
, rows
, cols
, 0, 0);
3897 PIXEL_WIDTH (f
) = pixelwidth
;
3898 PIXEL_HEIGHT (f
) = pixelheight
;
3900 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3901 receive in the ConfigureNotify event; if we get what we asked
3902 for, then the event won't cause the screen to become garbaged, so
3903 we have to make sure to do it here. */
3904 SET_FRAME_GARBAGED (f
);
3906 /* If cursor was outside the new size, mark it as off. */
3907 if (f
->phys_cursor_y
>= rows
3908 || f
->phys_cursor_x
>= cols
)
3910 f
->phys_cursor_x
= -1;
3911 f
->phys_cursor_y
= -1;
3914 /* Clear out any recollection of where the mouse highlighting was,
3915 since it might be in a place that's outside the new frame size.
3916 Actually checking whether it is outside is a pain in the neck,
3917 so don't try--just let the highlighting be done afresh with new size. */
3918 window
= dpyinfo
->mouse_face_window
;
3919 if (! NILP (window
) && XFRAME (window
) == f
)
3921 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3922 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3923 dpyinfo
->mouse_face_window
= Qnil
;
3929 /* Mouse warping. */
3932 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3941 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
3942 pt
.x
= rect
.left
+ pix_x
;
3943 pt
.y
= rect
.top
+ pix_y
;
3944 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
3946 SetCursorPos (pt
.x
, pt
.y
);
3952 x_set_mouse_position (f
, x
, y
)
3958 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
3959 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
3961 if (pix_x
< 0) pix_x
= 0;
3962 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3964 if (pix_y
< 0) pix_y
= 0;
3965 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3967 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3970 /* focus shifting, raising and lowering. */
3972 x_focus_on_frame (f
)
3975 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3977 /* Give input focus to frame. */
3980 /* Try not to change its Z-order if possible. */
3981 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
3982 my_set_focus (f
, FRAME_W32_WINDOW (f
));
3985 my_set_foreground_window (FRAME_W32_WINDOW (f
));
3994 /* Raise frame F. */
4001 /* Strictly speaking, raise-frame should only change the frame's Z
4002 order, leaving input focus unchanged. This is reasonable behaviour
4003 on X where the usual policy is point-to-focus. However, this
4004 behaviour would be very odd on Windows where the usual policy is
4007 On X, if the mouse happens to be over the raised frame, it gets
4008 input focus anyway (so the window with focus will never be
4009 completely obscured) - if not, then just moving the mouse over it
4010 is sufficient to give it focus. On Windows, the user must actually
4011 click on the frame (preferrably the title bar so as not to move
4012 point), which is more awkward. Also, no other Windows program
4013 raises a window to the top but leaves another window (possibly now
4014 completely obscured) with input focus.
4016 Because there is a system setting on Windows that allows the user
4017 to choose the point to focus policy, we make the strict semantics
4018 optional, but by default we grab focus when raising. */
4020 if (NILP (Vw32_grab_focus_on_raise
))
4022 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4023 not already the foreground application: the frame is raised
4024 above all other frames belonging to us, but not above the
4025 current top window. To achieve that, we have to resort to this
4026 more cumbersome method. */
4028 HDWP handle
= BeginDeferWindowPos (2);
4031 DeferWindowPos (handle
,
4032 FRAME_W32_WINDOW (f
),
4035 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4037 DeferWindowPos (handle
,
4038 GetForegroundWindow (),
4039 FRAME_W32_WINDOW (f
),
4041 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4043 EndDeferWindowPos (handle
);
4048 my_set_foreground_window (FRAME_W32_WINDOW (f
));
4054 /* Lower frame F. */
4060 my_set_window_pos (FRAME_W32_WINDOW (f
),
4063 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
4068 w32_frame_raise_lower (f
, raise
)
4078 /* Change of visibility. */
4080 /* This tries to wait until the frame is really visible.
4081 However, if the window manager asks the user where to position
4082 the frame, this will return before the user finishes doing that.
4083 The frame will not actually be visible at that time,
4084 but it will become visible later when the window manager
4085 finishes with it. */
4087 x_make_frame_visible (f
)
4092 if (! FRAME_VISIBLE_P (f
))
4094 /* We test FRAME_GARBAGED_P here to make sure we don't
4095 call x_set_offset a second time
4096 if we get to x_make_frame_visible a second time
4097 before the window gets really visible. */
4098 if (! FRAME_ICONIFIED_P (f
)
4099 && ! f
->output_data
.w32
->asked_for_visible
)
4100 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
4102 f
->output_data
.w32
->asked_for_visible
= 1;
4104 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4105 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
4108 /* Synchronize to ensure Emacs knows the frame is visible
4109 before we do anything else. We do this loop with input not blocked
4110 so that incoming events are handled. */
4113 int count
= input_signal_count
;
4115 /* This must come after we set COUNT. */
4118 XSETFRAME (frame
, f
);
4122 /* Once we have handled input events,
4123 we should have received the MapNotify if one is coming.
4124 So if we have not got it yet, stop looping.
4125 Some window managers make their own decisions
4126 about visibility. */
4127 if (input_signal_count
!= count
)
4129 /* Machines that do polling rather than SIGIO have been observed
4130 to go into a busy-wait here. So we'll fake an alarm signal
4131 to let the handler know that there's something to be read.
4132 We used to raise a real alarm, but it seems that the handler
4133 isn't always enabled here. This is probably a bug. */
4134 if (input_polling_used ())
4136 /* It could be confusing if a real alarm arrives while processing
4137 the fake one. Turn it off and let the handler reset it. */
4139 input_poll_signal (0);
4141 /* Once we have handled input events,
4142 we should have received the MapNotify if one is coming.
4143 So if we have not got it yet, stop looping.
4144 Some window managers make their own decisions
4145 about visibility. */
4146 if (input_signal_count
!= count
)
4149 FRAME_SAMPLE_VISIBILITY (f
);
4153 /* Change from mapped state to withdrawn state. */
4155 /* Make the frame visible (mapped and not iconified). */
4157 x_make_frame_invisible (f
)
4162 /* Don't keep the highlight on an invisible frame. */
4163 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4164 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4168 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
4170 /* We can't distinguish this from iconification
4171 just by the event that we get from the server.
4172 So we can't win using the usual strategy of letting
4173 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4174 and synchronize with the server to make sure we agree. */
4176 FRAME_ICONIFIED_P (f
) = 0;
4177 f
->async_visible
= 0;
4178 f
->async_iconified
= 0;
4183 /* Change window state from mapped to iconified. */
4191 /* Don't keep the highlight on an invisible frame. */
4192 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
4193 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
4195 if (f
->async_iconified
)
4200 /* Simulate the user minimizing the frame. */
4201 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
4203 f
->async_iconified
= 1;
4208 /* Destroy the window of frame F. */
4210 x_destroy_window (f
)
4213 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
4217 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
4218 free_frame_menubar (f
);
4219 free_frame_faces (f
);
4221 xfree (f
->output_data
.w32
);
4222 f
->output_data
.w32
= 0;
4223 if (f
== dpyinfo
->w32_focus_frame
)
4224 dpyinfo
->w32_focus_frame
= 0;
4225 if (f
== dpyinfo
->w32_focus_event_frame
)
4226 dpyinfo
->w32_focus_event_frame
= 0;
4227 if (f
== dpyinfo
->w32_highlight_frame
)
4228 dpyinfo
->w32_highlight_frame
= 0;
4230 dpyinfo
->reference_count
--;
4232 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4234 dpyinfo
->mouse_face_beg_row
4235 = dpyinfo
->mouse_face_beg_col
= -1;
4236 dpyinfo
->mouse_face_end_row
4237 = dpyinfo
->mouse_face_end_col
= -1;
4238 dpyinfo
->mouse_face_window
= Qnil
;
4244 /* Setting window manager hints. */
4246 /* Set the normal size hints for the window manager, for frame F.
4247 FLAGS is the flags word to use--or 0 meaning preserve the flags
4248 that the window now has.
4249 If USER_POSITION is nonzero, we set the USPosition
4250 flag (this is useful when FLAGS is 0). */
4252 x_wm_set_size_hint (f
, flags
, user_position
)
4257 Window window
= FRAME_W32_WINDOW (f
);
4259 flexlines
= f
->height
;
4263 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4264 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4265 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4266 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4271 /* Window manager things */
4272 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4277 Window window
= FRAME_W32_WINDOW (f
);
4279 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4280 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4281 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4283 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4288 /* Initialization. */
4290 #ifdef USE_X_TOOLKIT
4291 static XrmOptionDescRec emacs_options
[] = {
4292 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4293 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4295 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4296 XrmoptionSepArg
, NULL
},
4297 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4299 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4300 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4301 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4302 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4303 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4304 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4305 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4307 #endif /* USE_X_TOOLKIT */
4309 static int w32_initialized
= 0;
4311 struct w32_display_info
*
4312 w32_term_init (display_name
, xrm_option
, resource_name
)
4313 Lisp_Object display_name
;
4315 char *resource_name
;
4319 struct w32_display_info
*dpyinfo
;
4324 if (!w32_initialized
)
4327 w32_initialized
= 1;
4338 argv
[argc
++] = "-xrm";
4339 argv
[argc
++] = xrm_option
;
4343 dpyinfo
= &one_w32_display_info
;
4345 /* Put this display on the chain. */
4346 dpyinfo
->next
= NULL
;
4348 /* Put it on w32_display_name_list as well, to keep them parallel. */
4349 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4350 w32_display_name_list
);
4351 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4353 dpyinfo
->w32_id_name
4354 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4355 + XSTRING (Vsystem_name
)->size
4357 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4358 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4361 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4362 resource_name
, EMACS_CLASS
);
4364 /* Put the rdb where we can find it in a way that works on
4366 dpyinfo
->xrdb
= xrdb
;
4368 hdc
= GetDC (GetDesktopWindow ());
4370 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4371 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4372 dpyinfo
->root_window
= GetDesktopWindow ();
4373 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4374 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4375 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4376 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4377 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4378 dpyinfo
->grabbed
= 0;
4379 dpyinfo
->reference_count
= 0;
4380 dpyinfo
->n_fonts
= 0;
4381 dpyinfo
->font_table_size
= 0;
4382 dpyinfo
->bitmaps
= 0;
4383 dpyinfo
->bitmaps_size
= 0;
4384 dpyinfo
->bitmaps_last
= 0;
4385 dpyinfo
->mouse_face_mouse_frame
= 0;
4386 dpyinfo
->mouse_face_deferred_gc
= 0;
4387 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4388 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4389 dpyinfo
->mouse_face_face_id
= 0;
4390 dpyinfo
->mouse_face_window
= Qnil
;
4391 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4392 dpyinfo
->mouse_face_defer
= 0;
4393 dpyinfo
->w32_focus_frame
= 0;
4394 dpyinfo
->w32_focus_event_frame
= 0;
4395 dpyinfo
->w32_highlight_frame
= 0;
4397 ReleaseDC (GetDesktopWindow (), hdc
);
4399 /* Determine if there is a middle mouse button, to allow parse_button
4400 to decide whether right mouse events should be mouse-2 or
4402 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4404 /* initialise palette with white and black */
4407 defined_color (0, "white", &color
, 1);
4408 defined_color (0, "black", &color
, 1);
4411 #ifndef F_SETOWN_BUG
4413 #ifdef F_SETOWN_SOCK_NEG
4414 /* stdin is a socket here */
4415 fcntl (connection
, F_SETOWN
, -getpid ());
4416 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4417 fcntl (connection
, F_SETOWN
, getpid ());
4418 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4419 #endif /* ! defined (F_SETOWN) */
4420 #endif /* F_SETOWN_BUG */
4423 if (interrupt_input
)
4424 init_sigio (connection
);
4425 #endif /* ! defined (SIGIO) */
4432 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4435 x_delete_display (dpyinfo
)
4436 struct w32_display_info
*dpyinfo
;
4438 /* Discard this display from w32_display_name_list and w32_display_list.
4439 We can't use Fdelq because that can quit. */
4440 if (! NILP (w32_display_name_list
)
4441 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4442 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4447 tail
= w32_display_name_list
;
4448 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4450 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4451 dpyinfo
->name_list_element
))
4453 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4456 tail
= XCONS (tail
)->cdr
;
4460 /* free palette table */
4462 struct w32_palette_entry
* plist
;
4464 plist
= dpyinfo
->color_list
;
4467 struct w32_palette_entry
* pentry
= plist
;
4468 plist
= plist
->next
;
4471 dpyinfo
->color_list
= NULL
;
4472 if (dpyinfo
->palette
)
4473 DeleteObject(dpyinfo
->palette
);
4475 xfree (dpyinfo
->font_table
);
4476 xfree (dpyinfo
->w32_id_name
);
4479 /* Set up use of W32. */
4481 DWORD
w32_msg_worker ();
4485 /* MSVC does not type K&R functions with no arguments correctly, and
4486 so we must explicitly cast them. */
4487 clear_frame_hook
= (void (*)(void)) w32_clear_frame
;
4488 clear_end_of_line_hook
= w32_clear_end_of_line
;
4489 ins_del_lines_hook
= w32_ins_del_lines
;
4490 change_line_highlight_hook
= w32_change_line_highlight
;
4491 insert_glyphs_hook
= w32_insert_glyphs
;
4492 write_glyphs_hook
= w32_write_glyphs
;
4493 delete_glyphs_hook
= w32_delete_glyphs
;
4494 ring_bell_hook
= (void (*)(void)) w32_ring_bell
;
4495 reset_terminal_modes_hook
= (void (*)(void)) w32_reset_terminal_modes
;
4496 set_terminal_modes_hook
= (void (*)(void)) w32_set_terminal_modes
;
4497 update_begin_hook
= w32_update_begin
;
4498 update_end_hook
= w32_update_end
;
4499 set_terminal_window_hook
= w32_set_terminal_window
;
4500 read_socket_hook
= w32_read_socket
;
4501 frame_up_to_date_hook
= w32_frame_up_to_date
;
4502 cursor_to_hook
= w32_cursor_to
;
4503 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
4504 mouse_position_hook
= w32_mouse_position
;
4505 frame_rehighlight_hook
= w32_frame_rehighlight
;
4506 frame_raise_lower_hook
= w32_frame_raise_lower
;
4507 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
4508 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
4509 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
4510 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
4512 scroll_region_ok
= 1; /* we'll scroll partial frames */
4513 char_ins_del_ok
= 0; /* just as fast to write the line */
4514 line_ins_del_ok
= 1; /* we'll just blt 'em */
4515 fast_clear_end_of_line
= 1; /* X does this well */
4516 memory_below_frame
= 0; /* we don't remember what scrolls
4520 /* Initialize input mode: interrupt_input off, no flow control, allow
4521 8 bit character input, standard quit char. */
4522 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
4524 /* Create the window thread - it will terminate itself or when the app terminates */
4528 dwMainThreadId
= GetCurrentThreadId ();
4529 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
4530 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
4532 /* Wait for thread to start */
4537 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
4539 hWindowsThread
= CreateThread (NULL
, 0,
4540 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
4541 0, 0, &dwWindowsThreadId
);
4543 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4546 /* It is desirable that mainThread should have the same notion of
4547 focus window and active window as windowsThread. Unfortunately, the
4548 following call to AttachThreadInput, which should do precisely what
4549 we need, causes major problems when Emacs is linked as a console
4550 program. Unfortunately, we have good reasons for doing that, so
4551 instead we need to send messages to windowsThread to make some API
4552 calls for us (ones that affect, or depend on, the active/focus
4554 #ifdef ATTACH_THREADS
4555 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
4558 /* Dynamically link to optional system components. */
4560 HANDLE user_lib
= LoadLibrary ("user32.dll");
4562 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
4564 /* New proportional scroll bar functions. */
4565 LOAD_PROC( SetScrollInfo
);
4566 LOAD_PROC( GetScrollInfo
);
4570 FreeLibrary (user_lib
);
4572 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
4573 otherwise use the fixed height. */
4574 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
4575 GetSystemMetrics (SM_CYVTHUMB
);
4577 /* For either kind of scroll bar, take account of the arrows; these
4578 effectively form the border of the main scroll bar range. */
4579 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
4580 = GetSystemMetrics (SM_CYVSCROLL
);
4587 staticpro (&w32_display_name_list
);
4588 w32_display_name_list
= Qnil
;
4590 staticpro (&last_mouse_scroll_bar
);
4591 last_mouse_scroll_bar
= Qnil
;
4593 staticpro (&Qvendor_specific_keysyms
);
4594 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
4596 DEFVAR_INT ("w32-num-mouse-buttons",
4597 &Vw32_num_mouse_buttons
,
4598 "Number of physical mouse buttons.");
4599 Vw32_num_mouse_buttons
= Qnil
;
4601 DEFVAR_LISP ("w32-swap-mouse-buttons",
4602 &Vw32_swap_mouse_buttons
,
4603 "Swap the mapping of middle and right mouse buttons.\n\
4604 When nil, middle button is mouse-2 and right button is mouse-3.");
4605 Vw32_swap_mouse_buttons
= Qnil
;
4607 DEFVAR_LISP ("w32-grab-focus-on-raise",
4608 &Vw32_grab_focus_on_raise
,
4609 "Raised frame grabs input focus.\n\
4610 When t, `raise-frame' grabs input focus as well. This fits well\n\
4611 with the normal Windows click-to-focus policy, but might not be\n\
4612 desirable when using a point-to-focus policy.");
4613 Vw32_grab_focus_on_raise
= Qt
;
4615 DEFVAR_LISP ("w32-capslock-is-shiftlock",
4616 &Vw32_capslock_is_shiftlock
,
4617 "Apply CapsLock state to non character input keys.\n\
4618 When nil, CapsLock only affects normal character input keys.");
4619 Vw32_capslock_is_shiftlock
= Qnil
;
4621 DEFVAR_LISP ("w32-recognize-altgr",
4622 &Vw32_recognize_altgr
,
4623 "Recognize right-alt and left-ctrl as AltGr.\n\
4624 When nil, the right-alt and left-ctrl key combination is\n\
4625 interpreted normally.");
4626 Vw32_recognize_altgr
= Qt
;