1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Added by Kevin Gallo */
28 #include "blockinput.h"
41 #include "dispextern.h"
42 #include "termhooks.h"
50 #include "intervals.h"
52 extern void free_frame_menubar ();
54 extern Lisp_Object Vwindow_system
;
56 #define x_any_window_to_frame x_window_to_frame
57 #define x_top_window_to_frame x_window_to_frame
60 /* This is display since w32 does not support multiple ones. */
61 struct w32_display_info one_w32_display_info
;
63 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
64 one for each element of w32_display_list and in the same order.
65 NAME is the name of the frame.
66 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
67 Lisp_Object w32_display_name_list
;
69 /* Frame being updated by update_frame. This is declared in term.c.
70 This is set by update_begin and looked at by all the
71 w32 functions. It is zero while not inside an update.
72 In that case, the w32 functions assume that `selected_frame'
73 is the frame to apply to. */
74 extern struct frame
*updating_frame
;
76 /* This is a frame waiting to be autoraised, within w32_read_socket. */
77 struct frame
*pending_autoraise_frame
;
79 /* During an update, maximum vpos for ins/del line operations to affect. */
83 /* During an update, nonzero if chars output now should be highlighted. */
87 /* Nominal cursor position -- where to draw output.
88 During an update, these are different from the cursor-box position. */
93 DWORD dwWindowsThreadId
= 0;
94 HANDLE hWindowsThread
= NULL
;
95 DWORD dwMainThreadId
= 0;
96 HANDLE hMainThread
= NULL
;
100 /* Where the mouse was last time we reported a mouse event. */
101 static FRAME_PTR last_mouse_frame
;
102 static RECT last_mouse_glyph
;
104 Lisp_Object Vw32_num_mouse_buttons
;
106 Lisp_Object Vw32_swap_mouse_buttons
;
108 /* The scroll bar in which the last motion event occurred.
110 If the last motion event occurred in a scroll bar, we set this
111 so w32_mouse_position can know whether to report a scroll bar motion or
114 If the last motion event didn't occur in a scroll bar, we set this
115 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
116 Lisp_Object last_mouse_scroll_bar
;
117 int last_mouse_scroll_bar_pos
;
119 /* This is a hack. We would really prefer that w32_mouse_position would
120 return the time associated with the position it returns, but there
121 doesn't seem to be any way to wrest the timestamp from the server
122 along with the position query. So, we just keep track of the time
123 of the last movement we received, and return that in hopes that
124 it's somewhat accurate. */
125 Time last_mouse_movement_time
;
127 /* Incremented by w32_read_socket whenever it really tries to read events. */
129 static int volatile input_signal_count
;
131 static int input_signal_count
;
134 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
136 extern Lisp_Object Qface
, Qmouse_face
;
140 /* A mask of extra modifier bits to put into every keyboard char. */
141 extern int extra_keyboard_modifiers
;
143 static Lisp_Object Qvendor_specific_keysyms
;
145 void w32_delete_display ();
147 static void redraw_previous_char ();
148 static void redraw_following_char ();
149 static unsigned int w32_get_modifiers ();
151 static int fast_find_position ();
152 static void note_mouse_highlight ();
153 static void clear_mouse_face ();
154 static void show_mouse_face ();
155 static void do_line_dance ();
157 static int w32_cursor_to ();
158 static int w32_clear_end_of_line ();
161 /* This is a function useful for recording debugging information
162 about the sequence of occurrences in this file. */
170 struct record event_record
[100];
172 int event_record_index
;
174 record_event (locus
, type
)
178 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
179 event_record_index
= 0;
181 event_record
[event_record_index
].locus
= locus
;
182 event_record
[event_record_index
].type
= type
;
183 event_record_index
++;
188 /* Return the struct w32_display_info. */
190 struct w32_display_info
*
191 w32_display_info_for_display ()
193 return (&one_w32_display_info
);
197 w32_fill_rect (f
, _hdc
, pix
, lprect
)
212 hdc
= get_frame_dc (f
);
215 hb
= CreateSolidBrush (pix
);
216 FillRect (hdc
, lprect
, hb
);
220 release_frame_dc (f
, hdc
);
229 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
230 w32_clear_rect (f
, NULL
, &rect
);
234 /* Starting and ending updates.
236 These hooks are called by update_frame at the beginning and end
237 of a frame update. We record in `updating_frame' the identity
238 of the frame being updated, so that the w32_... functions do not
239 need to take a frame as argument. Most of the w32_... functions
240 should never be called except during an update, the only exceptions
241 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
250 flexlines
= f
->height
;
255 /* Regenerate display palette before drawing if list of requested
256 colors has changed. */
257 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
259 w32_regenerate_palette (f
);
260 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
263 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
265 /* Don't do highlighting for mouse motion during the update. */
266 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
268 /* If the frame needs to be redrawn,
269 simply forget about any prior mouse highlighting. */
270 if (FRAME_GARBAGED_P (f
))
271 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
273 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
275 int firstline
, lastline
, i
;
276 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
278 /* Find the first, and the last+1, lines affected by redisplay. */
279 for (firstline
= 0; firstline
< f
->height
; firstline
++)
280 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
283 lastline
= f
->height
;
284 for (i
= f
->height
- 1; i
>= 0; i
--)
286 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
292 /* Can we tell that this update does not affect the window
293 where the mouse highlight is? If so, no need to turn off.
294 Likewise, don't do anything if the frame is garbaged;
295 in that case, the FRAME_CURRENT_GLYPHS that we would use
296 are all wrong, and we will redisplay that line anyway. */
297 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
298 || lastline
< XFASTINT (w
->top
)))
299 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
313 x_display_cursor (f
, 1);
315 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
316 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
321 /* This is called after a redisplay on frame F. */
324 w32_frame_up_to_date (f
)
327 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
328 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
330 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
331 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
332 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
333 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
337 /* External interface to control of standout mode.
338 Call this when about to modify line at position VPOS
339 and not change whether it is highlighted. */
341 w32_reassert_line_highlight (new, vpos
)
347 /* Call this when about to modify line at position VPOS
348 and change whether it is highlighted. */
351 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
352 int new_highlight
, vpos
, first_unused_hpos
;
354 highlight
= new_highlight
;
355 w32_cursor_to (vpos
, 0);
356 w32_clear_end_of_line (updating_frame
->width
);
359 /* This is used when starting Emacs and when restarting after suspend.
360 When starting Emacs, no window is mapped. And nothing must be done
361 to Emacs's own window if it is suspended (though that rarely happens). */
364 w32_set_terminal_modes ()
368 /* This is called when exiting or suspending Emacs.
369 Exiting will make the W32 windows go away, and suspending
370 requires no action. */
373 w32_reset_terminal_modes ()
377 /* Set the nominal cursor position of the frame.
378 This is where display update commands will take effect.
379 This does not affect the place where the cursor-box is displayed. */
382 w32_cursor_to (row
, col
)
383 register int row
, col
;
390 if (updating_frame
== 0)
393 x_display_cursor (selected_frame
, 1);
398 /* Display a sequence of N glyphs found at GP.
399 WINDOW is the window to output to. LEFT and TOP are starting coords.
400 HL is 1 if this text is highlighted, 2 if the cursor is on it,
401 3 if should appear in its mouse-face.
402 JUST_FOREGROUND if 1 means draw only the foreground;
403 don't alter the background.
405 FONT is the default font to use (for glyphs whose font-code is 0).
407 Since the display generation code is responsible for calling
408 compute_char_face and compute_glyph_face on everything it puts in
409 the display structure, we can assume that the face code on each
410 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
411 to which we can actually apply intern_face.
412 Call this function with input blocked. */
415 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
418 register GLYPH
*gp
; /* Points to first GLYPH. */
419 register int n
; /* Number of glyphs to display. */
423 /* Holds characters to be displayed. */
424 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
425 register char *cp
; /* Steps through buf[]. */
426 register int tlen
= GLYPH_TABLE_LENGTH
;
427 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
428 Window window
= FRAME_W32_WINDOW (f
);
429 int orig_left
= left
;
432 hdc
= get_frame_dc (f
);
436 /* Get the face-code of the next GLYPH. */
440 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
441 cf
= FAST_GLYPH_FACE (g
);
443 /* Find the run of consecutive glyphs with the same face-code.
444 Extract their character codes into BUF. */
449 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
450 if (FAST_GLYPH_FACE (g
) != cf
)
453 *cp
++ = FAST_GLYPH_CHAR (g
);
458 /* LEN gets the length of the run. */
461 /* Now output this run of chars, with the font and pixel values
462 determined by the face code CF. */
464 struct face
*face
= FRAME_DEFAULT_FACE (f
);
465 XFontStruct
*font
= FACE_FONT (face
);
470 /* HL = 3 means use a mouse face previously chosen. */
472 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
474 /* First look at the face of the text itself. */
477 /* It's possible for the display table to specify
478 a face code that is out of range. Use 0 in that case. */
479 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
480 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
484 face
= FRAME_MODE_LINE_FACE (f
);
486 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
487 font
= FACE_FONT (face
);
488 if (FACE_STIPPLE (face
))
492 /* Then comes the distinction between modeline and normal text. */
497 face
= FRAME_MODE_LINE_FACE (f
);
498 font
= FACE_FONT (face
);
499 if (FACE_STIPPLE (face
))
503 fg
= face
->foreground
;
504 bg
= face
->background
;
506 /* Now override that if the cursor's on this character. */
509 /* The cursor overrides stippling. */
513 || face
->font
== (XFontStruct
*) FACE_DEFAULT
514 || face
->font
== f
->output_data
.w32
->font
)
515 && face
->background
== f
->output_data
.w32
->background_pixel
516 && face
->foreground
== f
->output_data
.w32
->foreground_pixel
)
518 bg
= f
->output_data
.w32
->cursor_pixel
;
519 fg
= face
->background
;
521 /* Cursor on non-default face: must merge. */
524 bg
= f
->output_data
.w32
->cursor_pixel
;
525 fg
= face
->background
;
526 /* If the glyph would be invisible,
527 try a different foreground. */
529 fg
= face
->foreground
;
531 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
533 fg
= face
->foreground
;
534 /* Make sure the cursor is distinct from text in this face. */
535 if (bg
== face
->background
536 && fg
== face
->foreground
)
538 bg
= face
->foreground
;
539 fg
= face
->background
;
544 if (font
== (XFontStruct
*) FACE_DEFAULT
)
545 font
= f
->output_data
.w32
->font
;
547 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
549 SetTextColor (hdc
, fg
);
550 SetBkColor (hdc
, bg
);
552 SelectObject (hdc
, font
->hfont
);
554 TextOut (hdc
, left
, top
, buf
, len
);
556 if (!just_foreground
)
558 /* Clear the rest of the line's height. */
559 if (f
->output_data
.w32
->line_height
!= FONT_HEIGHT (font
))
560 w32_fill_area (f
, hdc
, bg
,
562 top
+ FONT_HEIGHT (font
),
563 FONT_WIDTH (font
) * len
,
564 f
->output_data
.w32
->line_height
- FONT_HEIGHT (font
));
568 int underline_position
= 1;
570 if (font
->tm
.tmDescent
<= underline_position
)
571 underline_position
= font
->tm
.tmDescent
- 1;
574 w32_fill_area (f
, hdc
, fg
,
577 + underline_position
),
578 len
* FONT_WIDTH (font
), 1);
581 left
+= len
* FONT_WIDTH (font
);
585 release_frame_dc (f
, hdc
);
589 /* Output some text at the nominal frame cursor position.
590 Advance the cursor over the text.
591 Output LEN glyphs at START.
593 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
594 controls the pixel values used for foreground and background. */
597 w32_write_glyphs (start
, len
)
598 register GLYPH
*start
;
601 register int temp_length
;
611 /* If not within an update,
612 output at the frame's visible cursor. */
613 curs_x
= f
->cursor_x
;
614 curs_y
= f
->cursor_y
;
618 CHAR_TO_PIXEL_COL (f
, curs_x
),
619 CHAR_TO_PIXEL_ROW (f
, curs_y
),
620 start
, len
, highlight
, 0);
622 /* If we drew on top of the cursor, note that it is turned off. */
623 if (curs_y
== f
->phys_cursor_y
624 && curs_x
<= f
->phys_cursor_x
625 && curs_x
+ len
> f
->phys_cursor_x
)
626 f
->phys_cursor_x
= -1;
628 if (updating_frame
== 0)
631 x_display_cursor (f
, 1);
640 /* Clear to the end of the line.
641 Erase the current text line from the nominal cursor position (inclusive)
642 to column FIRST_UNUSED (exclusive). The idea is that everything
643 from FIRST_UNUSED onward is already erased. */
646 w32_clear_end_of_line (first_unused
)
647 register int first_unused
;
649 struct frame
*f
= updating_frame
;
654 if (curs_y
< 0 || curs_y
>= f
->height
)
656 if (first_unused
<= 0)
659 if (first_unused
>= f
->width
)
660 first_unused
= f
->width
;
662 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
668 /* Notice if the cursor will be cleared by this operation. */
669 if (curs_y
== f
->phys_cursor_y
670 && curs_x
<= f
->phys_cursor_x
671 && f
->phys_cursor_x
< first_unused
)
672 f
->phys_cursor_x
= -1;
674 w32_clear_area (f
, NULL
,
675 CHAR_TO_PIXEL_COL (f
, curs_x
),
676 CHAR_TO_PIXEL_ROW (f
, curs_y
),
677 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
678 f
->output_data
.w32
->line_height
);
686 struct frame
*f
= updating_frame
;
691 f
->phys_cursor_x
= -1; /* Cursor not visible. */
692 curs_x
= 0; /* Nominal cursor position is top left. */
697 w32_clear_window (f
);
699 /* We have to clear the scroll bars, too. If we have changed
700 colors or something like that, then they should be notified. */
701 x_scroll_bar_clear (f
);
706 /* Make audible bell. */
713 FlashWindow (FRAME_W32_WINDOW (selected_frame
), FALSE
);
715 w32_sys_ring_bell ();
722 /* Insert and delete character.
723 These are not supposed to be used because we are supposed to turn
724 off the feature of using them. */
727 w32_insert_glyphs (start
, len
)
728 register char *start
;
735 w32_delete_glyphs (n
)
741 /* Specify how many text lines, from the top of the window,
742 should be affected by insert-lines and delete-lines operations.
743 This, and those operations, are used only within an update
744 that is bounded by calls to w32_update_begin and w32_update_end. */
747 w32_set_terminal_window (n
)
750 if (updating_frame
== 0)
753 if ((n
<= 0) || (n
> updating_frame
->height
))
754 flexlines
= updating_frame
->height
;
759 /* These variables need not be per frame
760 because redisplay is done on a frame-by-frame basis
761 and the line dance for one frame is finished before
762 anything is done for another frame. */
764 /* Array of line numbers from cached insert/delete operations.
765 line_dance[i] is the old position of the line that we want
766 to move to line i, or -1 if we want a blank line there. */
767 static int *line_dance
;
769 /* Allocated length of that array. */
770 static int line_dance_len
;
772 /* Flag indicating whether we've done any work. */
773 static int line_dance_in_progress
;
775 /* Perform an insert-lines or delete-lines operation,
776 inserting N lines or deleting -N lines at vertical position VPOS. */
777 w32_ins_del_lines (vpos
, n
)
780 register int fence
, i
;
782 if (vpos
>= flexlines
)
785 if (!line_dance_in_progress
)
787 int ht
= updating_frame
->height
;
788 if (ht
> line_dance_len
)
790 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
793 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
794 line_dance_in_progress
= 1;
798 if (n
> flexlines
- vpos
)
799 n
= flexlines
- vpos
;
801 for (i
= flexlines
; --i
>= fence
;)
802 line_dance
[i
] = line_dance
[i
-n
];
803 for (i
= fence
; --i
>= vpos
;)
809 if (n
> flexlines
- vpos
)
810 n
= flexlines
- vpos
;
811 fence
= flexlines
- n
;
812 for (i
= vpos
; i
< fence
; ++i
)
813 line_dance
[i
] = line_dance
[i
+ n
];
814 for (i
= fence
; i
< flexlines
; ++i
)
819 /* Here's where we actually move the pixels around.
820 Must be called with input blocked. */
824 register int i
, j
, distance
;
825 register struct frame
*f
;
830 /* Must check this flag first. If it's not set, then not only is the
831 array uninitialized, but we might not even have a frame. */
832 if (!line_dance_in_progress
)
840 intborder
= f
->output_data
.w32
->internal_border_width
;
842 x_display_cursor (updating_frame
, 0);
844 hdc
= get_frame_dc (f
);
846 for (i
= 0; i
< ht
; ++i
)
847 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
849 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
850 && line_dance
[j
]-j
== distance
); ++j
);
851 /* Copy [i,j) upward from [i+distance, j+distance) */
853 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
854 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
855 (j
-i
) * f
->output_data
.w32
->line_height
,
857 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
862 for (i
= ht
; --i
>=0; )
863 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
865 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
866 && line_dance
[j
]-j
== distance
););
867 /* Copy (j, i] downward from (j+distance, i+distance] */
869 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
870 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
871 (i
-j
) * f
->output_data
.w32
->line_height
,
873 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
878 release_frame_dc (f
, hdc
);
880 for (i
= 0; i
< ht
; ++i
)
881 if (line_dance
[i
] == -1)
883 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
885 w32_clear_area (f
, NULL
,
887 CHAR_TO_PIXEL_ROW (f
, i
),
888 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
889 (j
-i
) * f
->output_data
.w32
->line_height
);
892 line_dance_in_progress
= 0;
895 /* Support routines for exposure events. */
896 static void clear_cursor ();
898 /* Output into a rectangle of a window (for frame F)
899 the characters in f->phys_lines that overlap that rectangle.
900 TOP and LEFT are the position of the upper left corner of the rectangle.
901 ROWS and COLS are the size of the rectangle.
902 Call this function with input blocked. */
905 dumprectangle (f
, left
, top
, cols
, rows
)
907 register int left
, top
, cols
, rows
;
909 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
910 int cursor_cleared
= 0;
914 if (FRAME_GARBAGED_P (f
))
917 /* Express rectangle as four edges, instead of position-and-size. */
921 /* Convert rectangle edges in pixels to edges in chars.
922 Round down for left and top, up for right and bottom. */
923 top
= PIXEL_TO_CHAR_ROW (f
, top
);
924 left
= PIXEL_TO_CHAR_COL (f
, left
);
925 bottom
+= (f
->output_data
.w32
->line_height
- 1);
926 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
927 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
928 right
= PIXEL_TO_CHAR_COL (f
, right
);
930 /* Clip the rectangle to what can be visible. */
935 if (right
> f
->width
)
937 if (bottom
> f
->height
)
940 /* Get size in chars of the rectangle. */
944 /* If rectangle has zero area, return. */
945 if (rows
<= 0) return;
946 if (cols
<= 0) return;
948 /* Turn off the cursor if it is in the rectangle.
949 We will turn it back on afterward. */
950 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
951 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
957 /* Display the text in the rectangle, one text line at a time. */
959 for (y
= top
; y
< bottom
; y
++)
961 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
963 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
967 CHAR_TO_PIXEL_COL (f
, left
),
968 CHAR_TO_PIXEL_ROW (f
, y
),
969 line
, min (cols
, active_frame
->used
[y
] - left
),
970 active_frame
->highlight
[y
], 0);
973 /* Turn the cursor on if we turned it off. */
976 x_display_cursor (f
, 1);
983 x_display_cursor (f
, 1);
987 frame_unhighlight (f
)
990 x_display_cursor (f
, 1);
993 static void w32_frame_rehighlight ();
994 static void x_frame_rehighlight ();
996 /* The focus has changed. Update the frames as necessary to reflect
997 the new situation. Note that we can't change the selected frame
998 here, because the Lisp code we are interrupting might become confused.
999 Each event gets marked with the frame in which it occurred, so the
1000 Lisp code can tell when the switch took place by examining the events. */
1003 x_new_focus_frame (dpyinfo
, frame
)
1004 struct w32_display_info
*dpyinfo
;
1005 struct frame
*frame
;
1007 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1008 int events_enqueued
= 0;
1010 if (frame
!= dpyinfo
->w32_focus_frame
)
1012 /* Set this before calling other routines, so that they see
1013 the correct value of w32_focus_frame. */
1014 dpyinfo
->w32_focus_frame
= frame
;
1016 if (old_focus
&& old_focus
->auto_lower
)
1017 x_lower_frame (old_focus
);
1019 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1020 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1022 pending_autoraise_frame
= 0;
1025 x_frame_rehighlight (dpyinfo
);
1028 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1031 x_mouse_leave (dpyinfo
)
1032 struct w32_display_info
*dpyinfo
;
1034 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1037 /* The focus has changed, or we have redirected a frame's focus to
1038 another frame (this happens when a frame uses a surrogate
1039 minibuffer frame). Shift the highlight as appropriate.
1041 The FRAME argument doesn't necessarily have anything to do with which
1042 frame is being highlighted or unhighlighted; we only use it to find
1043 the appropriate display info. */
1045 w32_frame_rehighlight (frame
)
1046 struct frame
*frame
;
1048 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1052 x_frame_rehighlight (dpyinfo
)
1053 struct w32_display_info
*dpyinfo
;
1055 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1057 if (dpyinfo
->w32_focus_frame
)
1059 dpyinfo
->w32_highlight_frame
1060 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1061 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1062 : dpyinfo
->w32_focus_frame
);
1063 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1065 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1066 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1070 dpyinfo
->w32_highlight_frame
= 0;
1072 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1075 frame_unhighlight (old_highlight
);
1076 if (dpyinfo
->w32_highlight_frame
)
1077 frame_highlight (dpyinfo
->w32_highlight_frame
);
1081 /* Keyboard processing - modifier keys, etc. */
1083 /* Convert a keysym to its name. */
1086 x_get_keysym_name (keysym
)
1089 /* Make static so we can always return it */
1090 static char value
[100];
1093 GetKeyNameText(keysym
, value
, 100);
1099 /* Mouse clicks and mouse movement. Rah. */
1101 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1102 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1103 that the glyph at X, Y occupies, if BOUNDS != 0.
1104 If NOCLIP is nonzero, do not force the value into range. */
1107 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1109 register int pix_x
, pix_y
;
1110 register int *x
, *y
;
1114 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1115 if (NILP (Vwindow_system
))
1122 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1123 even for negative values. */
1125 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1127 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1129 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1130 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1134 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1135 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1136 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1137 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1144 else if (pix_x
> f
->width
)
1149 else if (pix_y
> f
->height
)
1158 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1161 register int *pix_x
, *pix_y
;
1163 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1164 if (NILP (Vwindow_system
))
1171 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1172 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1176 parse_button (message
, pbutton
, pup
)
1186 case WM_LBUTTONDOWN
:
1194 case WM_MBUTTONDOWN
:
1195 if (NILP (Vw32_swap_mouse_buttons
))
1202 if (NILP (Vw32_swap_mouse_buttons
))
1208 case WM_RBUTTONDOWN
:
1209 if (NILP (Vw32_swap_mouse_buttons
))
1216 if (NILP (Vw32_swap_mouse_buttons
))
1227 if (pbutton
) *pbutton
= button
;
1233 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1235 If the event is a button press, then note that we have grabbed
1239 construct_mouse_click (result
, msg
, f
)
1240 struct input_event
*result
;
1247 parse_button (msg
->msg
.message
, &button
, &up
);
1249 /* Make the event type no_event; we'll change that when we decide
1251 result
->kind
= mouse_click
;
1252 result
->code
= button
;
1253 result
->timestamp
= msg
->msg
.time
;
1254 result
->modifiers
= (msg
->dwModifiers
1262 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1263 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1264 XSETFRAME (result
->frame_or_window
, f
);
1269 /* Function to report a mouse movement to the mainstream Emacs code.
1270 The input handler calls this.
1272 We have received a mouse movement event, which is given in *event.
1273 If the mouse is over a different glyph than it was last time, tell
1274 the mainstream emacs code by setting mouse_moved. If not, ask for
1275 another motion event, so we can check again the next time it moves. */
1278 note_mouse_movement (frame
, msg
)
1282 last_mouse_movement_time
= msg
->time
;
1284 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
1286 frame
->mouse_moved
= 1;
1287 last_mouse_scroll_bar
= Qnil
;
1289 note_mouse_highlight (frame
, -1, -1);
1292 /* Has the mouse moved off the glyph it was on at the last sighting? */
1293 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1294 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1295 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
1296 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1298 frame
->mouse_moved
= 1;
1299 last_mouse_scroll_bar
= Qnil
;
1301 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1305 /* This is used for debugging, to turn off note_mouse_highlight. */
1306 static int disable_mouse_highlight
;
1308 /* Take proper action when the mouse has moved to position X, Y on frame F
1309 as regards highlighting characters that have mouse-face properties.
1310 Also dehighlighting chars where the mouse was before.
1311 X and Y can be negative or out of range. */
1314 note_mouse_highlight (f
, x
, y
)
1318 int row
, column
, portion
;
1323 if (disable_mouse_highlight
)
1326 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1327 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1328 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1330 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
1335 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1339 /* Find out which glyph the mouse is on. */
1340 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1341 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
1343 /* Which window is that in? */
1344 window
= window_from_coordinates (f
, column
, row
, &portion
);
1345 w
= XWINDOW (window
);
1347 /* If we were displaying active text in another window, clear that. */
1348 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
1349 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1351 /* Are we in a window whose display is up to date?
1352 And verify the buffer's text has not changed. */
1353 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1354 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1355 && EQ (w
->window_end_valid
, w
->buffer
)
1356 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
1357 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
1359 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1362 /* Find which buffer position the mouse corresponds to. */
1363 for (i
= column
; i
>= 0; i
--)
1367 /* Is it outside the displayed active region (if any)? */
1369 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1370 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
1371 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1372 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1373 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1374 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1375 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1376 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1377 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1379 Lisp_Object mouse_face
, overlay
, position
;
1380 Lisp_Object
*overlay_vec
;
1381 int len
, noverlays
, ignor1
;
1382 struct buffer
*obuf
;
1385 /* If we get an out-of-range value, return now; avoid an error. */
1386 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1389 /* Make the window's buffer temporarily current for
1390 overlays_at and compute_char_face. */
1391 obuf
= current_buffer
;
1392 current_buffer
= XBUFFER (w
->buffer
);
1398 /* Yes. Clear the display of the old active region, if any. */
1399 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1401 /* Is this char mouse-active? */
1402 XSETINT (position
, pos
);
1405 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1407 /* Put all the overlays we want in a vector in overlay_vec.
1408 Store the length in len. */
1409 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1411 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1413 /* Find the highest priority overlay that has a mouse-face prop. */
1415 for (i
= 0; i
< noverlays
; i
++)
1417 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1418 if (!NILP (mouse_face
))
1420 overlay
= overlay_vec
[i
];
1425 /* If no overlay applies, get a text property. */
1427 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1429 /* Handle the overlay case. */
1430 if (! NILP (overlay
))
1432 /* Find the range of text around this char that
1433 should be active. */
1434 Lisp_Object before
, after
;
1437 before
= Foverlay_start (overlay
);
1438 after
= Foverlay_end (overlay
);
1439 /* Record this as the current active region. */
1440 fast_find_position (window
, before
,
1441 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1442 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1443 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1444 = !fast_find_position (window
, after
,
1445 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1446 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1447 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1448 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1449 = compute_char_face (f
, w
, pos
, 0, 0,
1450 &ignore
, pos
+ 1, 1);
1452 /* Display it as active. */
1453 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1455 /* Handle the text property case. */
1456 else if (! NILP (mouse_face
))
1458 /* Find the range of text around this char that
1459 should be active. */
1460 Lisp_Object before
, after
, beginning
, end
;
1463 beginning
= Fmarker_position (w
->start
);
1464 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1465 - XFASTINT (w
->window_end_pos
)));
1467 = Fprevious_single_property_change (make_number (pos
+ 1),
1469 w
->buffer
, beginning
);
1471 = Fnext_single_property_change (position
, Qmouse_face
,
1473 /* Record this as the current active region. */
1474 fast_find_position (window
, before
,
1475 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1476 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1477 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1478 = !fast_find_position (window
, after
,
1479 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1480 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1481 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1482 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1483 = compute_char_face (f
, w
, pos
, 0, 0,
1484 &ignore
, pos
+ 1, 1);
1486 /* Display it as active. */
1487 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1491 current_buffer
= obuf
;
1496 /* Find the row and column of position POS in window WINDOW.
1497 Store them in *COLUMNP and *ROWP.
1498 This assumes display in WINDOW is up to date.
1499 If POS is above start of WINDOW, return coords
1500 of start of first screen line.
1501 If POS is after end of WINDOW, return coords of end of last screen line.
1503 Value is 1 if POS is in range, 0 if it was off screen. */
1506 fast_find_position (window
, pos
, columnp
, rowp
)
1509 int *columnp
, *rowp
;
1511 struct window
*w
= XWINDOW (window
);
1512 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1515 int left
= WINDOW_LEFT_MARGIN (w
);
1517 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1518 int width
= window_internal_width (w
);
1521 int maybe_next_line
= 0;
1523 /* Find the right row. */
1528 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1529 if (linestart
> pos
)
1531 /* If the position sought is the end of the buffer,
1532 don't include the blank lines at the bottom of the window. */
1533 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1535 maybe_next_line
= 1;
1542 /* Find the right column with in it. */
1543 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1545 for (i
= 0; i
< width
; i
++)
1547 if (charstarts
[left
+ i
] == pos
)
1550 *columnp
= i
+ left
;
1553 else if (charstarts
[left
+ i
] > pos
)
1555 else if (charstarts
[left
+ i
] > 0)
1559 /* If we're looking for the end of the buffer,
1560 and we didn't find it in the line we scanned,
1561 use the start of the following line. */
1562 if (maybe_next_line
)
1573 /* Display the active region described by mouse_face_*
1574 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1577 show_mouse_face (dpyinfo
, hl
)
1578 struct w32_display_info
*dpyinfo
;
1581 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1582 int width
= window_internal_width (w
);
1583 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1586 int old_curs_x
= curs_x
;
1587 int old_curs_y
= curs_y
;
1589 /* Set these variables temporarily
1590 so that if we have to turn the cursor off and on again
1591 we will put it back at the same place. */
1592 curs_x
= f
->phys_cursor_x
;
1593 curs_y
= f
->phys_cursor_y
;
1595 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1596 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1598 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1599 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
1600 : WINDOW_LEFT_MARGIN (w
));
1601 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1602 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1603 : WINDOW_LEFT_MARGIN (w
) + width
);
1604 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1606 /* If the cursor's in the text we are about to rewrite,
1607 turn the cursor off. */
1609 && curs_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
1610 && curs_x
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
)
1612 x_display_cursor (f
, 0);
1617 CHAR_TO_PIXEL_COL (f
, column
),
1618 CHAR_TO_PIXEL_ROW (f
, i
),
1619 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1621 /* Highlight with mouse face if hl > 0. */
1625 /* If we turned the cursor off, turn it back on. */
1627 x_display_cursor (f
, 1);
1629 curs_x
= old_curs_x
;
1630 curs_y
= old_curs_y
;
1632 /* Change the mouse cursor according to the value of HL. */
1634 SetCursor (f
->output_data
.w32
->cross_cursor
);
1636 SetCursor (f
->output_data
.w32
->text_cursor
);
1639 /* Clear out the mouse-highlighted active region.
1640 Redraw it unhighlighted first. */
1643 clear_mouse_face (dpyinfo
)
1644 struct w32_display_info
*dpyinfo
;
1646 if (! NILP (dpyinfo
->mouse_face_window
))
1647 show_mouse_face (dpyinfo
, 0);
1649 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1650 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1651 dpyinfo
->mouse_face_window
= Qnil
;
1654 struct scroll_bar
*x_window_to_scroll_bar ();
1655 static void x_scroll_bar_report_motion ();
1657 /* Return the current position of the mouse.
1658 *fp should be a frame which indicates which display to ask about.
1660 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1661 and *part to the frame, window, and scroll bar part that the mouse
1662 is over. Set *x and *y to the portion and whole of the mouse's
1663 position on the scroll bar.
1665 If the mouse movement started elsewhere, set *fp to the frame the
1666 mouse is on, *bar_window to nil, and *x and *y to the character cell
1669 Set *time to the server timestamp for the time at which the mouse
1670 was at this position.
1672 Don't store anything if we don't have a valid set of values to report.
1674 This clears the mouse_moved flag, so we can wait for the next mouse
1675 movement. This also calls XQueryPointer, which will cause the
1676 server to give us another MotionNotify when the mouse moves
1680 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1683 Lisp_Object
*bar_window
;
1684 enum scroll_bar_part
*part
;
1686 unsigned long *time
;
1692 if (! NILP (last_mouse_scroll_bar
))
1693 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1698 Lisp_Object frame
, tail
;
1700 /* Clear the mouse-moved flag for every frame on this display. */
1701 FOR_EACH_FRAME (tail
, frame
)
1702 XFRAME (frame
)->mouse_moved
= 0;
1704 last_mouse_scroll_bar
= Qnil
;
1708 /* Now we have a position on the root; find the innermost window
1709 containing the pointer. */
1711 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1712 && FRAME_LIVE_P (last_mouse_frame
))
1714 f1
= last_mouse_frame
;
1718 /* Is win one of our frames? */
1719 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1722 /* If not, is it one of our scroll bars? */
1725 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1729 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1733 if (f1
== 0 && insist
)
1734 f1
= selected_frame
;
1738 int ignore1
, ignore2
;
1740 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
1742 /* Ok, we found a frame. Store all the values. */
1744 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1746 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
1754 *time
= last_mouse_movement_time
;
1762 /* Scroll bar support. */
1764 /* Given an window ID, find the struct scroll_bar which manages it.
1765 This can be called in GC, so we have to make sure to strip off mark
1768 x_window_to_scroll_bar (window_id
)
1771 Lisp_Object tail
, frame
;
1773 for (tail
= Vframe_list
;
1774 XGCTYPE (tail
) == Lisp_Cons
;
1775 tail
= XCONS (tail
)->cdr
)
1777 Lisp_Object frame
, bar
, condemned
;
1779 frame
= XCONS (tail
)->car
;
1780 /* All elements of Vframe_list should be frames. */
1781 if (! GC_FRAMEP (frame
))
1784 /* Scan this frame's scroll bar list for a scroll bar with the
1786 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1787 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1788 /* This trick allows us to search both the ordinary and
1789 condemned scroll bar lists with one loop. */
1790 ! GC_NILP (bar
) || (bar
= condemned
,
1793 bar
= XSCROLL_BAR (bar
)->next
)
1794 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1795 return XSCROLL_BAR (bar
);
1802 my_create_scrollbar (f
, bar
)
1804 struct scroll_bar
* bar
;
1808 PostThreadMessage (dwWindowsThreadId
, WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1810 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
1812 return ((HWND
) msg
.wParam
);
1815 //#define ATTACH_THREADS
1818 my_show_window (HWND hwnd
, int how
)
1820 #ifndef ATTACH_THREADS
1821 SendMessage (hwnd
, WM_EMACS_SHOWWINDOW
, (WPARAM
) how
, 0);
1823 ShowWindow (hwnd
, how
);
1828 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
1829 int x
, int y
, int cx
, int cy
, int flags
)
1831 #ifndef ATTACH_THREADS
1833 pos
.hwndAfter
= hwndAfter
;
1839 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
1841 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1846 my_destroy_window (f
, hwnd
)
1850 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
1854 /* Open a new window to serve as a scroll bar, and return the
1855 scroll bar vector for it. */
1856 static struct scroll_bar
*
1857 x_scroll_bar_create (window
, top
, left
, width
, height
)
1858 struct window
*window
;
1859 int top
, left
, width
, height
;
1861 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1862 struct scroll_bar
*bar
1863 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1868 XSETWINDOW (bar
->window
, window
);
1869 XSETINT (bar
->top
, top
);
1870 XSETINT (bar
->left
, left
);
1871 XSETINT (bar
->width
, width
);
1872 XSETINT (bar
->height
, height
);
1873 XSETINT (bar
->start
, 0);
1874 XSETINT (bar
->end
, 0);
1875 bar
->dragging
= Qnil
;
1877 /* Requires geometry to be set before call to create the real window */
1879 hwnd
= my_create_scrollbar (f
, bar
);
1881 SetScrollRange (hwnd
, SB_CTL
, 0, height
, FALSE
);
1882 SetScrollPos (hwnd
, SB_CTL
, 0, TRUE
);
1884 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
1886 /* Add bar to its frame's list of scroll bars. */
1887 bar
->next
= FRAME_SCROLL_BARS (f
);
1889 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
1890 if (! NILP (bar
->next
))
1891 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
1898 /* Draw BAR's handle in the proper position.
1899 If the handle is already drawn from START to END, don't bother
1900 redrawing it, unless REBUILD is non-zero; in that case, always
1901 redraw it. (REBUILD is handy for drawing the handle after expose
1904 Normally, we want to constrain the start and end of the handle to
1905 fit inside its rectangle, but if the user is dragging the scroll bar
1906 handle, we want to let them drag it down all the way, so that the
1907 bar's top is as far down as it goes; otherwise, there's no way to
1908 move to the very end of the buffer. */
1910 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1911 struct scroll_bar
*bar
;
1915 int dragging
= ! NILP (bar
->dragging
);
1916 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
1917 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1919 /* If the display is already accurate, do nothing. */
1921 && start
== XINT (bar
->start
)
1922 && end
== XINT (bar
->end
))
1927 /* Store the adjusted setting in the scroll bar. */
1928 XSETINT (bar
->start
, start
);
1929 XSETINT (bar
->end
, end
);
1931 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
1936 /* Move a scroll bar around on the screen, to accommodate changing
1937 window configurations. */
1939 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1940 struct scroll_bar
*bar
;
1941 int top
, left
, width
, height
;
1943 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
1944 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1948 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
1949 SetScrollRange (w
, SB_CTL
, 0, height
, FALSE
);
1950 InvalidateRect (w
, NULL
, FALSE
);
1951 my_show_window (w
, SW_NORMAL
);
1953 XSETINT (bar
->left
, left
);
1954 XSETINT (bar
->top
, top
);
1955 XSETINT (bar
->width
, width
);
1956 XSETINT (bar
->height
, height
);
1961 /* Destroy the window for BAR, and set its Emacs window's scroll bar
1964 x_scroll_bar_remove (bar
)
1965 struct scroll_bar
*bar
;
1967 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1971 /* Destroy the window. */
1972 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
1974 /* Disassociate this scroll bar from its window. */
1975 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
1980 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1981 that we are displaying PORTION characters out of a total of WHOLE
1982 characters, starting at POSITION. If WINDOW has no scroll bar,
1985 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
1986 struct window
*window
;
1987 int portion
, whole
, position
;
1989 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1990 int top
= XINT (window
->top
);
1991 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
1992 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
1994 /* Where should this scroll bar be, pixelwise? */
1995 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
1996 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
1998 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
1999 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2000 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2001 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2003 struct scroll_bar
*bar
;
2005 /* Does the scroll bar exist yet? */
2006 if (NILP (window
->vertical_scroll_bar
))
2007 bar
= x_scroll_bar_create (window
,
2008 pixel_top
, pixel_left
,
2009 pixel_width
, pixel_height
);
2012 /* It may just need to be moved and resized. */
2013 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2014 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2017 /* Set the scroll bar's current state, unless we're currently being
2019 if (NILP (bar
->dragging
))
2021 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2024 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2027 int start
= (int) (((double) position
* top_range
) / whole
);
2028 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2030 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2034 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2038 /* The following three hooks are used when we're doing a thorough
2039 redisplay of the frame. We don't explicitly know which scroll bars
2040 are going to be deleted, because keeping track of when windows go
2041 away is a real pain - "Can you say set-window-configuration, boys
2042 and girls?" Instead, we just assert at the beginning of redisplay
2043 that *all* scroll bars are to be removed, and then save a scroll bar
2044 from the fiery pit when we actually redisplay its window. */
2046 /* Arrange for all scroll bars on FRAME to be removed at the next call
2047 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2048 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2050 w32_condemn_scroll_bars (frame
)
2053 /* The condemned list should be empty at this point; if it's not,
2054 then the rest of Emacs isn't using the condemn/redeem/judge
2055 protocol correctly. */
2056 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2059 /* Move them all to the "condemned" list. */
2060 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2061 FRAME_SCROLL_BARS (frame
) = Qnil
;
2064 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2065 Note that WINDOW isn't necessarily condemned at all. */
2067 w32_redeem_scroll_bar (window
)
2068 struct window
*window
;
2070 struct scroll_bar
*bar
;
2072 /* We can't redeem this window's scroll bar if it doesn't have one. */
2073 if (NILP (window
->vertical_scroll_bar
))
2076 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2078 /* Unlink it from the condemned list. */
2080 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2082 if (NILP (bar
->prev
))
2084 /* If the prev pointer is nil, it must be the first in one of
2086 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2087 /* It's not condemned. Everything's fine. */
2089 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2090 window
->vertical_scroll_bar
))
2091 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2093 /* If its prev pointer is nil, it must be at the front of
2094 one or the other! */
2098 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2100 if (! NILP (bar
->next
))
2101 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2103 bar
->next
= FRAME_SCROLL_BARS (f
);
2105 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2106 if (! NILP (bar
->next
))
2107 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2111 /* Remove all scroll bars on FRAME that haven't been saved since the
2112 last call to `*condemn_scroll_bars_hook'. */
2114 w32_judge_scroll_bars (f
)
2117 Lisp_Object bar
, next
;
2119 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2121 /* Clear out the condemned list now so we won't try to process any
2122 more events on the hapless scroll bars. */
2123 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2125 for (; ! NILP (bar
); bar
= next
)
2127 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2129 x_scroll_bar_remove (b
);
2132 b
->next
= b
->prev
= Qnil
;
2135 /* Now there should be no references to the condemned scroll bars,
2136 and they should get garbage-collected. */
2139 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2140 is set to something other than no_event, it is enqueued.
2142 This may be called from a signal handler, so we have to ignore GC
2146 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2147 struct scroll_bar
*bar
;
2149 struct input_event
*emacs_event
;
2151 if (! GC_WINDOWP (bar
->window
))
2154 emacs_event
->kind
= w32_scroll_bar_click
;
2155 emacs_event
->code
= 0;
2156 /* not really meaningful to distinguish up/down */
2157 emacs_event
->modifiers
= msg
->dwModifiers
;
2158 emacs_event
->frame_or_window
= bar
->window
;
2159 emacs_event
->timestamp
= msg
->msg
.time
;
2163 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2165 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2166 int y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2168 switch (LOWORD (msg
->msg
.wParam
))
2171 emacs_event
->part
= scroll_bar_handle
;
2172 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2173 y
= HIWORD (msg
->msg
.wParam
);
2176 emacs_event
->part
= scroll_bar_down_arrow
;
2179 emacs_event
->part
= scroll_bar_up_arrow
;
2182 emacs_event
->part
= scroll_bar_above_handle
;
2185 emacs_event
->part
= scroll_bar_below_handle
;
2188 emacs_event
->part
= scroll_bar_handle
;
2192 emacs_event
->part
= scroll_bar_handle
;
2195 case SB_THUMBPOSITION
:
2196 emacs_event
->part
= scroll_bar_handle
;
2200 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
2204 XSETINT (emacs_event
->x
, y
);
2205 XSETINT (emacs_event
->y
, top_range
);
2211 /* Return information to the user about the current position of the mouse
2212 on the scroll bar. */
2214 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2216 Lisp_Object
*bar_window
;
2217 enum scroll_bar_part
*part
;
2219 unsigned long *time
;
2221 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2222 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2223 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2229 *bar_window
= bar
->window
;
2231 pos
= GetScrollPos (w
, SB_CTL
);
2233 switch (LOWORD (last_mouse_scroll_bar_pos
))
2235 case SB_THUMBPOSITION
:
2237 *part
= scroll_bar_handle
;
2238 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2239 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2242 *part
= scroll_bar_handle
;
2246 *part
= scroll_bar_handle
;
2251 XSETINT(*y
, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)));
2254 last_mouse_scroll_bar
= Qnil
;
2256 *time
= last_mouse_movement_time
;
2261 /* The screen has been cleared so we may have changed foreground or
2262 background colors, and the scroll bars may need to be redrawn.
2263 Clear out the scroll bars, and ask for expose events, so we can
2266 x_scroll_bar_clear (f
)
2271 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2272 bar
= XSCROLL_BAR (bar
)->next
)
2274 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2275 HDC hdc
= GetDC (window
);
2278 my_show_window (window
, SW_HIDE
);
2279 GetClientRect (window
, &rect
);
2280 select_palette (f
, hdc
);
2281 w32_clear_rect (f
, hdc
, &rect
);
2282 deselect_palette (f
, hdc
);
2286 show_scroll_bars (f
, how
)
2292 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2293 bar
= XSCROLL_BAR (bar
)->next
)
2295 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2296 my_show_window (window
, how
);
2301 /* The main W32 event-reading loop - w32_read_socket. */
2303 /* Timestamp of enter window event. This is only used by w32_read_socket,
2304 but we have to put it out here, since static variables within functions
2305 sometimes don't work. */
2306 static Time enter_timestamp
;
2308 /* Record the last 100 characters stored
2309 to help debug the loss-of-chars-during-GC problem. */
2311 short temp_buffer
[100];
2313 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*);
2315 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
2316 we can use the same routines to handle input in both console
2317 and window modes. */
2320 convert_to_key_event (W32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2322 eventp
->bKeyDown
= TRUE
;
2323 eventp
->wRepeatCount
= 1;
2324 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2325 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2326 eventp
->uChar
.AsciiChar
= 0;
2327 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2330 /* Return nonzero if the virtual key is a dead key. */
2333 is_dead_key (int wparam
)
2335 unsigned int code
= MapVirtualKey (wparam
, 2);
2337 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2338 if ((code
& 0x8000) || (code
& 0x80000000))
2344 /* Read events coming from the W32 shell.
2345 This routine is called by the SIGIO handler.
2346 We return as soon as there are no more events to be read.
2348 Events representing keys are stored in buffer BUFP,
2349 which can hold up to NUMCHARS characters.
2350 We return the number of characters stored into the buffer,
2351 thus pretending to be `read'.
2353 EXPECTED is nonzero if the caller knows input is available.
2355 Some of these messages are reposted back to the message queue since the
2356 system calls the windows proc directly in a context where we cannot return
2357 the data nor can we guarantee the state we are in. So if we dispatch them
2358 we will get into an infinite loop. To prevent this from ever happening we
2359 will set a variable to indicate we are in the read_socket call and indicate
2360 which message we are processing since the windows proc gets called
2361 recursively with different messages by the system.
2365 w32_read_socket (sd
, bufp
, numchars
, expected
)
2367 register struct input_event
*bufp
;
2368 register int numchars
;
2373 int items_pending
; /* How many items are in the X queue. */
2376 int event_found
= 0;
2379 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2381 if (interrupt_input_blocked
)
2383 interrupt_input_pending
= 1;
2387 interrupt_input_pending
= 0;
2390 /* So people can tell when we have read the available input. */
2391 input_signal_count
++;
2394 abort (); /* Don't think this happens. */
2396 while (get_next_msg (&msg
, FALSE
))
2398 switch (msg
.msg
.message
)
2402 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2406 if (f
->async_visible
== 0)
2408 f
->async_visible
= 1;
2409 f
->async_iconified
= 0;
2410 SET_FRAME_GARBAGED (f
);
2414 /* Erase background again for safety. */
2415 w32_clear_rect (f
, NULL
, &msg
.rect
);
2419 msg
.rect
.right
-msg
.rect
.left
+1,
2420 msg
.rect
.bottom
-msg
.rect
.top
+1);
2427 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2429 if (f
&& !f
->iconified
)
2431 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2433 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2434 bufp
->kind
= non_ascii_keystroke
;
2435 bufp
->code
= msg
.msg
.wParam
;
2436 bufp
->modifiers
= w32_kbd_mods_to_emacs (msg
.dwModifiers
);
2437 XSETFRAME (bufp
->frame_or_window
, f
);
2438 bufp
->timestamp
= msg
.msg
.time
;
2446 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2448 if (f
&& !f
->iconified
)
2453 KEY_EVENT_RECORD key
, *keyp
= &key
;
2455 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2458 convert_to_key_event (&msg
, keyp
);
2459 add
= key_event (keyp
, bufp
);
2460 XSETFRAME (bufp
->frame_or_window
, f
);
2463 /* The key pressed generated two characters, most likely
2464 an accent character and a key that could not be
2465 combined with it. Prepend the message on the queue
2466 again to process the second character (which is
2467 being held internally in key_event), and process
2468 the first character now. */
2473 /* Throw dead keys away. However, be sure not to
2474 throw away the dead key if it was produced using
2475 AltGr and there is a valid AltGr scan code for
2477 if (is_dead_key (msg
.msg
.wParam
)
2478 && !((VkKeyScan ((char) bufp
->code
) & 0xff00) == 0x600))
2492 if (dpyinfo
->grabbed
&& last_mouse_frame
2493 && FRAME_LIVE_P (last_mouse_frame
))
2494 f
= last_mouse_frame
;
2496 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2499 note_mouse_movement (f
, &msg
.msg
);
2501 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2504 case WM_LBUTTONDOWN
:
2506 case WM_MBUTTONDOWN
:
2508 case WM_RBUTTONDOWN
:
2514 if (dpyinfo
->grabbed
&& last_mouse_frame
2515 && FRAME_LIVE_P (last_mouse_frame
))
2516 f
= last_mouse_frame
;
2518 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2522 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
2525 construct_mouse_click (bufp
, &msg
, f
);
2532 parse_button (msg
.msg
.message
, &button
, &up
);
2536 dpyinfo
->grabbed
&= ~ (1 << button
);
2540 dpyinfo
->grabbed
|= (1 << button
);
2541 last_mouse_frame
= f
;
2548 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2550 if (bar
&& numchars
>= 1)
2552 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2563 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2565 if (f
&& !f
->async_iconified
)
2567 f
->output_data
.w32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2568 f
->output_data
.w32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2573 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2575 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2583 GetClientRect(msg
.msg
.hwnd
, &rect
);
2585 height
= rect
.bottom
- rect
.top
+ 1;
2586 width
= rect
.right
- rect
.left
+ 1;
2588 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2589 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2591 /* Even if the number of character rows and columns has
2592 not changed, the font size may have changed, so we need
2593 to check the pixel dimensions as well. */
2595 if (columns
!= f
->width
2596 || rows
!= f
->height
2597 || width
!= f
->output_data
.w32
->pixel_width
2598 || height
!= f
->output_data
.w32
->pixel_height
)
2600 /* I had set this to 0, 0 - I am not sure why?? */
2602 change_frame_size (f
, rows
, columns
, 0, 1);
2603 SET_FRAME_GARBAGED (f
);
2605 f
->output_data
.w32
->pixel_width
= width
;
2606 f
->output_data
.w32
->pixel_height
= height
;
2607 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
2614 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2616 if (msg
.msg
.message
== WM_SETFOCUS
)
2618 x_new_focus_frame (dpyinfo
, f
);
2620 else if (f
== dpyinfo
->w32_focus_frame
)
2621 x_new_focus_frame (dpyinfo
, 0);
2625 switch (msg
.msg
.wParam
& 0xfff0) /* Lower 4 bits used by Windows. */
2628 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2635 bufp
->kind
= delete_window_event
;
2636 XSETFRAME (bufp
->frame_or_window
, f
);
2644 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2648 f
->async_visible
= 1;
2649 f
->async_iconified
= 1;
2651 bufp
->kind
= iconify_event
;
2652 XSETFRAME (bufp
->frame_or_window
, f
);
2661 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2665 f
->async_visible
= 1;
2666 f
->async_iconified
= 0;
2668 /* wait_reading_process_input will notice this and update
2669 the frame's display structures. */
2670 SET_FRAME_GARBAGED (f
);
2674 bufp
->kind
= deiconify_event
;
2675 XSETFRAME (bufp
->frame_or_window
, f
);
2681 /* Force a redisplay sooner or later
2682 to update the frame titles
2683 in case this is the second frame. */
2684 record_asynch_buffer_change ();
2692 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2699 bufp
->kind
= delete_window_event
;
2700 XSETFRAME (bufp
->frame_or_window
, f
);
2708 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2712 if (msg
.msg
.lParam
== 0)
2714 /* Came from window menu */
2716 extern Lisp_Object
get_frame_menubar_event ();
2717 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2718 struct input_event buf
;
2721 XSETFRAME (frame
, f
);
2722 buf
.kind
= menu_bar_event
;
2724 /* Store initial menu bar event */
2728 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2729 kbd_buffer_store_event (&buf
);
2732 /* Enqueue the events */
2734 while (!NILP (event
))
2736 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2737 kbd_buffer_store_event (&buf
);
2738 event
= XCONS (event
)->cdr
;
2743 /* Came from popup menu */
2750 /* If the focus was just given to an autoraising frame,
2752 /* ??? This ought to be able to handle more than one such frame. */
2753 if (pending_autoraise_frame
)
2755 x_raise_frame (pending_autoraise_frame
);
2756 pending_autoraise_frame
= 0;
2763 /* Drawing the cursor. */
2766 /* Draw a hollow box cursor. Don't change the inside of the box. */
2776 hdc
= get_frame_dc (f
);
2778 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
2780 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2781 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2782 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
2783 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
2785 FrameRect (hdc
, &rect
, hb
);
2788 release_frame_dc (f
, hdc
);
2791 /* Clear the cursor of frame F to background color,
2792 and mark the cursor as not shown.
2793 This is used when the text where the cursor is
2794 is about to be rewritten. */
2800 if (! FRAME_VISIBLE_P (f
)
2801 || f
->phys_cursor_x
< 0)
2804 x_display_cursor (f
, 0);
2805 f
->phys_cursor_x
= -1;
2808 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2809 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2813 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2820 CHAR_TO_PIXEL_COL (f
, column
),
2821 CHAR_TO_PIXEL_ROW (f
, row
),
2822 &glyph
, 1, highlight
, 0);
2826 x_display_bar_cursor (f
, on
)
2830 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2832 /* This is pointless on invisible frames, and dangerous on garbaged
2833 frames; in the latter case, the frame may be in the midst of
2834 changing its size, and curs_x and curs_y may be off the frame. */
2835 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2838 if (! on
&& f
->phys_cursor_x
< 0)
2841 /* If we're not updating, then we want to use the current frame's
2842 cursor position, not our local idea of where the cursor ought to be. */
2843 if (f
!= updating_frame
)
2845 curs_x
= FRAME_CURSOR_X (f
);
2846 curs_y
= FRAME_CURSOR_Y (f
);
2849 /* If there is anything wrong with the current cursor state, remove it. */
2850 if (f
->phys_cursor_x
>= 0
2852 || f
->phys_cursor_x
!= curs_x
2853 || f
->phys_cursor_y
!= curs_y
2854 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
2856 /* Erase the cursor by redrawing the character underneath it. */
2857 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2858 f
->phys_cursor_glyph
,
2859 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2860 f
->phys_cursor_x
= -1;
2863 /* If we now need a cursor in the new place or in the new form, do it so. */
2865 && (f
->phys_cursor_x
< 0
2866 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
2868 f
->phys_cursor_glyph
2869 = ((current_glyphs
->enable
[curs_y
]
2870 && curs_x
< current_glyphs
->used
[curs_y
])
2871 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2873 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
2874 CHAR_TO_PIXEL_COL (f
, curs_x
),
2875 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2876 max (f
->output_data
.w32
->cursor_width
, 1),
2877 f
->output_data
.w32
->line_height
);
2879 f
->phys_cursor_x
= curs_x
;
2880 f
->phys_cursor_y
= curs_y
;
2882 f
->output_data
.w32
->current_cursor
= bar_cursor
;
2887 /* Turn the displayed cursor of frame F on or off according to ON.
2888 If ON is nonzero, where to put the cursor is specified
2889 by F->cursor_x and F->cursor_y. */
2892 x_display_box_cursor (f
, on
)
2896 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2898 /* This is pointless on invisible frames, and dangerous on garbaged
2899 frames; in the latter case, the frame may be in the midst of
2900 changing its size, and curs_x and curs_y may be off the frame. */
2901 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2904 /* If cursor is off and we want it off, return quickly. */
2905 if (!on
&& f
->phys_cursor_x
< 0)
2908 /* If we're not updating, then we want to use the current frame's
2909 cursor position, not our local idea of where the cursor ought to be. */
2910 if (f
!= updating_frame
)
2912 curs_x
= FRAME_CURSOR_X (f
);
2913 curs_y
= FRAME_CURSOR_Y (f
);
2916 /* If cursor is currently being shown and we don't want it to be
2917 or it is in the wrong place,
2918 or we want a hollow box and it's not so, (pout!)
2920 if (f
->phys_cursor_x
>= 0
2922 || f
->phys_cursor_x
!= curs_x
2923 || f
->phys_cursor_y
!= curs_y
2924 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
2925 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
2927 int mouse_face_here
= 0;
2928 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2930 /* If the cursor is in the mouse face area, redisplay that when
2931 we clear the cursor. */
2932 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2934 (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2935 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
2936 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2938 (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2939 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
2940 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2941 /* Don't redraw the cursor's spot in mouse face
2942 if it is at the end of a line (on a newline).
2943 The cursor appears there, but mouse highlighting does not. */
2944 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2945 mouse_face_here
= 1;
2947 /* If the font is not as tall as a whole line,
2948 we must explicitly clear the line's whole height. */
2949 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
2950 w32_clear_area (f
, NULL
,
2951 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2952 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2953 FONT_WIDTH (f
->output_data
.w32
->font
),
2954 f
->output_data
.w32
->line_height
);
2955 /* Erase the cursor by redrawing the character underneath it. */
2956 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2957 f
->phys_cursor_glyph
,
2960 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2961 f
->phys_cursor_x
= -1;
2964 /* If we want to show a cursor,
2965 or we want a box cursor and it's not so,
2966 write it in the right place. */
2968 && (f
->phys_cursor_x
< 0
2969 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
2970 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
2972 f
->phys_cursor_glyph
2973 = ((current_glyphs
->enable
[curs_y
]
2974 && curs_x
< current_glyphs
->used
[curs_y
])
2975 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2977 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
2980 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
2984 x_draw_single_glyph (f
, curs_y
, curs_x
,
2985 f
->phys_cursor_glyph
, 2);
2986 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
2989 f
->phys_cursor_x
= curs_x
;
2990 f
->phys_cursor_y
= curs_y
;
2994 x_display_cursor (f
, on
)
3000 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3001 x_display_box_cursor (f
, on
);
3002 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3003 x_display_bar_cursor (f
, on
);
3005 /* Those are the only two we have implemented! */
3011 /* Changing the font of the frame. */
3013 /* Give frame F the font named FONTNAME as its default font, and
3014 return the full name of that font. FONTNAME may be a wildcard
3015 pattern; in that case, we choose some font that fits the pattern.
3016 The return value shows which font we chose. */
3019 x_new_font (f
, fontname
)
3021 register char *fontname
;
3024 int n_matching_fonts
;
3025 XFontStruct
*font_info
;
3026 char new_font_name
[101];
3028 /* Get a font which matches this name */
3032 if (!x_to_w32_font(fontname
, &lf
)
3033 || !w32_to_x_font(&lf
, new_font_name
, 100))
3039 /* See if we've already loaded a matching font. */
3040 already_loaded
= -1;
3045 for (i
= 0; i
< FRAME_W32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3046 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3049 fontname
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3054 /* If we have, just return it from the table. */
3055 if (already_loaded
>= 0)
3056 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3057 /* Otherwise, load the font and add it to the table. */
3063 font
= w32_load_font(FRAME_W32_DISPLAY_INFO (f
), fontname
);
3070 /* Do we need to create the table? */
3071 if (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
== 0)
3073 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
= 16;
3074 FRAME_W32_DISPLAY_INFO (f
)->font_table
3075 = (struct font_info
*) xmalloc (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3076 * sizeof (struct font_info
));
3078 /* Do we need to grow the table? */
3079 else if (FRAME_W32_DISPLAY_INFO (f
)->n_fonts
3080 >= FRAME_W32_DISPLAY_INFO (f
)->font_table_size
)
3082 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3083 FRAME_W32_DISPLAY_INFO (f
)->font_table
3084 = (struct font_info
*) xrealloc (FRAME_W32_DISPLAY_INFO (f
)->font_table
,
3085 (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3086 * sizeof (struct font_info
)));
3089 n_fonts
= FRAME_W32_DISPLAY_INFO (f
)->n_fonts
;
3090 FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3091 bcopy (fontname
, FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3092 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3093 FRAME_W32_DISPLAY_INFO (f
)->n_fonts
++;
3096 /* Compute the scroll bar width in character columns. */
3097 if (f
->scroll_bar_pixel_width
> 0)
3099 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
3100 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3103 f
->scroll_bar_cols
= 2;
3105 /* Now make the frame display the given font. */
3106 if (FRAME_W32_WINDOW (f
) != 0)
3108 frame_update_line_height (f
);
3109 x_set_window_size (f
, 0, f
->width
, f
->height
);
3112 /* If we are setting a new frame's font for the first time,
3113 there are no faces yet, so this font's height is the line height. */
3114 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
3117 Lisp_Object lispy_name
;
3119 lispy_name
= build_string (fontname
);
3125 x_calc_absolute_position (f
)
3130 int flags
= f
->output_data
.w32
->size_hint_flags
;
3134 /* Find the position of the outside upper-left corner of
3135 the inner window, with respect to the outer window. */
3136 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
3139 MapWindowPoints (FRAME_W32_WINDOW (f
),
3140 f
->output_data
.w32
->parent_desc
,
3147 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3150 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
3151 FRAME_EXTERNAL_MENU_BAR (f
));
3154 pt
.x
+= (rt
.right
- rt
.left
);
3155 pt
.y
+= (rt
.bottom
- rt
.top
);
3158 /* Treat negative positions as relative to the leftmost bottommost
3159 position that fits on the screen. */
3160 if (flags
& XNegative
)
3161 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
3162 - 2 * f
->output_data
.w32
->border_width
- pt
.x
3164 + f
->output_data
.w32
->left_pos
);
3166 if (flags
& YNegative
)
3167 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
3168 - 2 * f
->output_data
.w32
->border_width
- pt
.y
3170 + f
->output_data
.w32
->top_pos
);
3171 /* The left_pos and top_pos
3172 are now relative to the top and left screen edges,
3173 so the flags should correspond. */
3174 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3177 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3178 to really change the position, and 0 when calling from
3179 x_make_frame_visible (in that case, XOFF and YOFF are the current
3180 position values). It is -1 when calling from x_set_frame_parameters,
3181 which means, do adjust for borders but don't change the gravity. */
3183 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3185 register int xoff
, yoff
;
3188 int modified_top
, modified_left
;
3190 if (change_gravity
> 0)
3192 f
->output_data
.w32
->top_pos
= yoff
;
3193 f
->output_data
.w32
->left_pos
= xoff
;
3194 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3196 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
3198 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
3199 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3201 x_calc_absolute_position (f
);
3204 x_wm_set_size_hint (f
, (long) 0, 0);
3206 /* It is a mystery why we need to add the border_width here
3207 when the frame is already visible, but experiment says we do. */
3208 modified_left
= f
->output_data
.w32
->left_pos
;
3209 modified_top
= f
->output_data
.w32
->top_pos
;
3210 if (change_gravity
!= 0)
3212 modified_left
+= f
->output_data
.w32
->border_width
;
3213 modified_top
+= f
->output_data
.w32
->border_width
;
3216 my_set_window_pos (FRAME_W32_WINDOW (f
),
3218 modified_left
, modified_top
,
3220 SWP_NOZORDER
| SWP_NOSIZE
);
3224 /* Call this to change the size of frame F's x-window.
3225 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3226 for this size change and subsequent size changes.
3227 Otherwise we leave the window gravity unchanged. */
3229 x_set_window_size (f
, change_gravity
, cols
, rows
)
3234 int pixelwidth
, pixelheight
;
3238 check_frame_size (f
, &rows
, &cols
);
3239 f
->output_data
.w32
->vertical_scroll_bar_extra
3240 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3242 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3243 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3244 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
3245 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3246 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3248 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3249 x_wm_set_size_hint (f
, (long) 0, 0);
3254 rect
.left
= rect
.top
= 0;
3255 rect
.right
= pixelwidth
;
3256 rect
.bottom
= pixelheight
;
3258 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
3259 FRAME_EXTERNAL_MENU_BAR (f
));
3261 /* All windows have an extra pixel */
3263 my_set_window_pos (FRAME_W32_WINDOW (f
),
3266 rect
.right
- rect
.left
+ 1,
3267 rect
.bottom
- rect
.top
+ 1,
3268 SWP_NOZORDER
| SWP_NOMOVE
);
3271 /* Now, strictly speaking, we can't be sure that this is accurate,
3272 but the window manager will get around to dealing with the size
3273 change request eventually, and we'll hear how it went when the
3274 ConfigureNotify event gets here.
3276 We could just not bother storing any of this information here,
3277 and let the ConfigureNotify event set everything up, but that
3278 might be kind of confusing to the lisp code, since size changes
3279 wouldn't be reported in the frame parameters until some random
3280 point in the future when the ConfigureNotify event arrives. */
3281 change_frame_size (f
, rows
, cols
, 0, 0);
3282 PIXEL_WIDTH (f
) = pixelwidth
;
3283 PIXEL_HEIGHT (f
) = pixelheight
;
3285 /* If cursor was outside the new size, mark it as off. */
3286 if (f
->phys_cursor_y
>= rows
3287 || f
->phys_cursor_x
>= cols
)
3289 f
->phys_cursor_x
= -1;
3290 f
->phys_cursor_y
= -1;
3293 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3294 receive in the ConfigureNotify event; if we get what we asked
3295 for, then the event won't cause the screen to become garbaged, so
3296 we have to make sure to do it here. */
3297 SET_FRAME_GARBAGED (f
);
3302 /* Mouse warping. */
3305 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3311 pix_x
+= f
->output_data
.w32
->left_pos
;
3312 pix_y
+= f
->output_data
.w32
->top_pos
;
3314 SetCursorPos (pix_x
, pix_y
);
3320 x_set_mouse_position (f
, x
, y
)
3326 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
3327 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
3329 if (pix_x
< 0) pix_x
= 0;
3330 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3332 if (pix_y
< 0) pix_y
= 0;
3333 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3335 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3338 /* focus shifting, raising and lowering. */
3340 x_focus_on_frame (f
)
3350 /* Raise frame F. */
3355 // if (f->async_visible)
3358 my_set_window_pos (FRAME_W32_WINDOW (f
),
3361 SWP_NOSIZE
| SWP_NOMOVE
);
3366 /* Lower frame F. */
3371 // if (f->async_visible)
3374 my_set_window_pos (FRAME_W32_WINDOW (f
),
3377 SWP_NOSIZE
| SWP_NOMOVE
);
3383 w32_frame_raise_lower (f
, raise
)
3393 /* Change of visibility. */
3395 /* This tries to wait until the frame is really visible.
3396 However, if the window manager asks the user where to position
3397 the frame, this will return before the user finishes doing that.
3398 The frame will not actually be visible at that time,
3399 but it will become visible later when the window manager
3400 finishes with it. */
3402 x_make_frame_visible (f
)
3407 if (! FRAME_VISIBLE_P (f
))
3409 /* We test FRAME_GARBAGED_P here to make sure we don't
3410 call x_set_offset a second time
3411 if we get to x_make_frame_visible a second time
3412 before the window gets really visible. */
3413 if (! FRAME_ICONIFIED_P (f
)
3414 && ! f
->output_data
.w32
->asked_for_visible
)
3416 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
3417 // SetForegroundWindow (FRAME_W32_WINDOW (f));
3420 f
->output_data
.w32
->asked_for_visible
= 1;
3422 my_show_window (FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
3425 /* Synchronize to ensure Emacs knows the frame is visible
3426 before we do anything else. We do this loop with input not blocked
3427 so that incoming events are handled. */
3430 int count
= input_signal_count
;
3432 /* This must come after we set COUNT. */
3435 XSETFRAME (frame
, f
);
3439 /* Once we have handled input events,
3440 we should have received the MapNotify if one is coming.
3441 So if we have not got it yet, stop looping.
3442 Some window managers make their own decisions
3443 about visibility. */
3444 if (input_signal_count
!= count
)
3446 /* Machines that do polling rather than SIGIO have been observed
3447 to go into a busy-wait here. So we'll fake an alarm signal
3448 to let the handler know that there's something to be read.
3449 We used to raise a real alarm, but it seems that the handler
3450 isn't always enabled here. This is probably a bug. */
3451 if (input_polling_used ())
3453 /* It could be confusing if a real alarm arrives while processing
3454 the fake one. Turn it off and let the handler reset it. */
3456 input_poll_signal ();
3458 /* Once we have handled input events,
3459 we should have received the MapNotify if one is coming.
3460 So if we have not got it yet, stop looping.
3461 Some window managers make their own decisions
3462 about visibility. */
3463 if (input_signal_count
!= count
)
3466 FRAME_SAMPLE_VISIBILITY (f
);
3470 /* Change from mapped state to withdrawn state. */
3472 /* Make the frame visible (mapped and not iconified). */
3474 x_make_frame_invisible (f
)
3479 /* Don't keep the highlight on an invisible frame. */
3480 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
3481 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
3485 my_show_window (FRAME_W32_WINDOW (f
), SW_HIDE
);
3487 /* We can't distinguish this from iconification
3488 just by the event that we get from the server.
3489 So we can't win using the usual strategy of letting
3490 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3491 and synchronize with the server to make sure we agree. */
3493 FRAME_ICONIFIED_P (f
) = 0;
3494 f
->async_visible
= 0;
3495 f
->async_iconified
= 0;
3500 /* Change window state from mapped to iconified. */
3508 /* Don't keep the highlight on an invisible frame. */
3509 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
3510 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
3512 if (f
->async_iconified
)
3517 my_show_window (FRAME_W32_WINDOW (f
), SW_SHOWMINIMIZED
);
3518 /* The frame doesn't seem to be lowered automatically. */
3521 f
->async_iconified
= 1;
3526 /* Destroy the window of frame F. */
3528 x_destroy_window (f
)
3531 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
3535 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
3536 free_frame_menubar (f
);
3537 free_frame_faces (f
);
3539 xfree (f
->output_data
.w32
);
3540 f
->output_data
.w32
= 0;
3541 if (f
== dpyinfo
->w32_focus_frame
)
3542 dpyinfo
->w32_focus_frame
= 0;
3543 if (f
== dpyinfo
->w32_focus_event_frame
)
3544 dpyinfo
->w32_focus_event_frame
= 0;
3545 if (f
== dpyinfo
->w32_highlight_frame
)
3546 dpyinfo
->w32_highlight_frame
= 0;
3548 dpyinfo
->reference_count
--;
3550 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3552 dpyinfo
->mouse_face_beg_row
3553 = dpyinfo
->mouse_face_beg_col
= -1;
3554 dpyinfo
->mouse_face_end_row
3555 = dpyinfo
->mouse_face_end_col
= -1;
3556 dpyinfo
->mouse_face_window
= Qnil
;
3562 /* Setting window manager hints. */
3564 /* Set the normal size hints for the window manager, for frame F.
3565 FLAGS is the flags word to use--or 0 meaning preserve the flags
3566 that the window now has.
3567 If USER_POSITION is nonzero, we set the USPosition
3568 flag (this is useful when FLAGS is 0). */
3570 x_wm_set_size_hint (f
, flags
, user_position
)
3575 Window window
= FRAME_W32_WINDOW (f
);
3577 flexlines
= f
->height
;
3581 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
3582 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.w32
->line_height
);
3587 /* Window manager things */
3588 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3593 Window window
= FRAME_W32_WINDOW (f
);
3595 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3596 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3597 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3599 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3604 /* Initialization. */
3606 #ifdef USE_X_TOOLKIT
3607 static XrmOptionDescRec emacs_options
[] = {
3608 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3609 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3611 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3612 XrmoptionSepArg
, NULL
},
3613 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3615 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3616 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3617 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3618 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3619 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3620 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3621 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3623 #endif /* USE_X_TOOLKIT */
3625 static int w32_initialized
= 0;
3627 struct w32_display_info
*
3628 w32_term_init (display_name
, xrm_option
, resource_name
)
3629 Lisp_Object display_name
;
3631 char *resource_name
;
3635 struct w32_display_info
*dpyinfo
;
3640 if (!w32_initialized
)
3643 w32_initialized
= 1;
3654 argv
[argc
++] = "-xrm";
3655 argv
[argc
++] = xrm_option
;
3659 dpyinfo
= &one_w32_display_info
;
3661 /* Put this display on the chain. */
3662 dpyinfo
->next
= NULL
;
3664 /* Put it on w32_display_name_list as well, to keep them parallel. */
3665 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3666 w32_display_name_list
);
3667 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
3669 dpyinfo
->w32_id_name
3670 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3671 + XSTRING (Vsystem_name
)->size
3673 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
3674 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3677 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3678 resource_name
, EMACS_CLASS
);
3680 /* Put the rdb where we can find it in a way that works on
3682 dpyinfo
->xrdb
= xrdb
;
3684 hdc
= GetDC (GetDesktopWindow ());
3686 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3687 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3688 dpyinfo
->root_window
= GetDesktopWindow ();
3689 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3690 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3691 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3692 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3693 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
3694 dpyinfo
->grabbed
= 0;
3695 dpyinfo
->reference_count
= 0;
3696 dpyinfo
->n_fonts
= 0;
3697 dpyinfo
->font_table_size
= 0;
3698 dpyinfo
->bitmaps
= 0;
3699 dpyinfo
->bitmaps_size
= 0;
3700 dpyinfo
->bitmaps_last
= 0;
3701 dpyinfo
->mouse_face_mouse_frame
= 0;
3702 dpyinfo
->mouse_face_deferred_gc
= 0;
3703 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3704 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3705 dpyinfo
->mouse_face_face_id
= 0;
3706 dpyinfo
->mouse_face_window
= Qnil
;
3707 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3708 dpyinfo
->mouse_face_defer
= 0;
3709 dpyinfo
->w32_focus_frame
= 0;
3710 dpyinfo
->w32_focus_event_frame
= 0;
3711 dpyinfo
->w32_highlight_frame
= 0;
3713 ReleaseDC (GetDesktopWindow (), hdc
);
3715 /* Determine if there is a middle mouse button, to allow parse_button
3716 to decide whether right mouse events should be mouse-2 or
3718 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
3720 /* initialise palette with white and black */
3723 defined_color (0, "white", &color
, 1);
3724 defined_color (0, "black", &color
, 1);
3727 #ifndef F_SETOWN_BUG
3729 #ifdef F_SETOWN_SOCK_NEG
3730 /* stdin is a socket here */
3731 fcntl (connection
, F_SETOWN
, -getpid ());
3732 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3733 fcntl (connection
, F_SETOWN
, getpid ());
3734 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3735 #endif /* ! defined (F_SETOWN) */
3736 #endif /* F_SETOWN_BUG */
3739 if (interrupt_input
)
3740 init_sigio (connection
);
3741 #endif /* ! defined (SIGIO) */
3748 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3751 x_delete_display (dpyinfo
)
3752 struct w32_display_info
*dpyinfo
;
3754 /* Discard this display from w32_display_name_list and w32_display_list.
3755 We can't use Fdelq because that can quit. */
3756 if (! NILP (w32_display_name_list
)
3757 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3758 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
3763 tail
= w32_display_name_list
;
3764 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3766 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3767 dpyinfo
->name_list_element
))
3769 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3772 tail
= XCONS (tail
)->cdr
;
3776 /* free palette table */
3778 struct w32_palette_entry
* plist
;
3780 plist
= dpyinfo
->color_list
;
3783 struct w32_palette_entry
* pentry
= plist
;
3784 plist
= plist
->next
;
3787 dpyinfo
->color_list
= NULL
;
3788 if (dpyinfo
->palette
)
3789 DeleteObject(dpyinfo
->palette
);
3791 xfree (dpyinfo
->font_table
);
3792 xfree (dpyinfo
->w32_id_name
);
3795 /* Set up use of W32. */
3797 DWORD
windows_msg_worker ();
3801 clear_frame_hook
= w32_clear_frame
;
3802 clear_end_of_line_hook
= w32_clear_end_of_line
;
3803 ins_del_lines_hook
= w32_ins_del_lines
;
3804 change_line_highlight_hook
= w32_change_line_highlight
;
3805 insert_glyphs_hook
= w32_insert_glyphs
;
3806 write_glyphs_hook
= w32_write_glyphs
;
3807 delete_glyphs_hook
= w32_delete_glyphs
;
3808 ring_bell_hook
= w32_ring_bell
;
3809 reset_terminal_modes_hook
= w32_reset_terminal_modes
;
3810 set_terminal_modes_hook
= w32_set_terminal_modes
;
3811 update_begin_hook
= w32_update_begin
;
3812 update_end_hook
= w32_update_end
;
3813 set_terminal_window_hook
= w32_set_terminal_window
;
3814 read_socket_hook
= w32_read_socket
;
3815 frame_up_to_date_hook
= w32_frame_up_to_date
;
3816 cursor_to_hook
= w32_cursor_to
;
3817 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
3818 mouse_position_hook
= w32_mouse_position
;
3819 frame_rehighlight_hook
= w32_frame_rehighlight
;
3820 frame_raise_lower_hook
= w32_frame_raise_lower
;
3821 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
3822 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
3823 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
3824 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
3826 scroll_region_ok
= 1; /* we'll scroll partial frames */
3827 char_ins_del_ok
= 0; /* just as fast to write the line */
3828 line_ins_del_ok
= 1; /* we'll just blt 'em */
3829 fast_clear_end_of_line
= 1; /* X does this well */
3830 memory_below_frame
= 0; /* we don't remember what scrolls
3834 /* Try to use interrupt input; if we can't, then start polling. */
3835 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3837 /* Create the window thread - it will terminate itself or when the app terminates */
3841 dwMainThreadId
= GetCurrentThreadId ();
3842 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3843 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3845 /* Wait for thread to start */
3850 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3852 hWindowsThread
= CreateThread (NULL
, 0,
3853 (LPTHREAD_START_ROUTINE
) windows_msg_worker
,
3854 0, 0, &dwWindowsThreadId
);
3856 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3859 /* It is desirable that mainThread should have the same notion of
3860 focus window and active window as windowsThread. Unfortunately, the
3861 following call to AttachThreadInput, which should do precisely what
3862 we need, causes major problems when Emacs is linked as a console
3863 program. Unfortunately, we have good reasons for doing that, so
3864 instead we need to send messages to windowsThread to make some API
3865 calls for us (ones that affect, or depend on, the active/focus
3867 #ifdef ATTACH_THREADS
3868 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
3875 staticpro (&w32_display_name_list
);
3876 w32_display_name_list
= Qnil
;
3878 staticpro (&last_mouse_scroll_bar
);
3879 last_mouse_scroll_bar
= Qnil
;
3881 staticpro (&Qvendor_specific_keysyms
);
3882 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
3884 DEFVAR_INT ("w32-num-mouse-buttons",
3885 &Vw32_num_mouse_buttons
,
3886 "Number of physical mouse buttons.");
3887 Vw32_num_mouse_buttons
= Qnil
;
3889 DEFVAR_LISP ("w32-swap-mouse-buttons",
3890 &Vw32_swap_mouse_buttons
,
3891 "Swap the mapping of middle and right mouse buttons.\n\
3892 When nil, middle button is mouse-2 and right button is mouse-3.");
3893 Vw32_swap_mouse_buttons
= Qnil
;