1 /* Implementation of Win32 GUI terminal
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
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Added by Kevin Gallo */
26 #include "blockinput.h"
39 #include "dispextern.h"
40 #include "termhooks.h"
48 #include "intervals.h"
50 extern void free_frame_menubar ();
52 extern Lisp_Object Vwindow_system
;
54 #define x_any_window_to_frame x_window_to_frame
55 #define x_top_window_to_frame x_window_to_frame
58 /* This is display since win32 does not support multiple ones. */
59 struct win32_display_info one_win32_display_info
;
61 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
62 one for each element of win32_display_list and in the same order.
63 NAME is the name of the frame.
64 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
65 Lisp_Object win32_display_name_list
;
67 /* Frame being updated by update_frame. This is declared in term.c.
68 This is set by update_begin and looked at by all the
69 win32 functions. It is zero while not inside an update.
70 In that case, the win32 functions assume that `selected_frame'
71 is the frame to apply to. */
72 extern struct frame
*updating_frame
;
74 /* This is a frame waiting to be autoraised, within w32_read_socket. */
75 struct frame
*pending_autoraise_frame
;
77 /* During an update, maximum vpos for ins/del line operations to affect. */
81 /* During an update, nonzero if chars output now should be highlighted. */
85 /* Nominal cursor position -- where to draw output.
86 During an update, these are different from the cursor-box position. */
91 DWORD dwWinThreadId
= 0;
92 HANDLE hWinThread
= NULL
;
93 DWORD dwMainThreadId
= 0;
94 HANDLE hMainThread
= NULL
;
98 /* Where the mouse was last time we reported a mouse event. */
99 static FRAME_PTR last_mouse_frame
;
100 static RECT last_mouse_glyph
;
102 Lisp_Object Vwin32_num_mouse_buttons
;
104 Lisp_Object Vwin32_swap_mouse_buttons
;
106 /* The scroll bar in which the last motion event occurred.
108 If the last motion event occurred in a scroll bar, we set this
109 so win32_mouse_position can know whether to report a scroll bar motion or
112 If the last motion event didn't occur in a scroll bar, we set this
113 to Qnil, to tell win32_mouse_position to return an ordinary motion event. */
114 Lisp_Object last_mouse_scroll_bar
;
115 int last_mouse_scroll_bar_pos
;
117 /* This is a hack. We would really prefer that win32_mouse_position would
118 return the time associated with the position it returns, but there
119 doesn't seem to be any way to wrest the timestamp from the server
120 along with the position query. So, we just keep track of the time
121 of the last movement we received, and return that in hopes that
122 it's somewhat accurate. */
123 Time last_mouse_movement_time
;
125 /* Incremented by w32_read_socket whenever it really tries to read events. */
127 static int volatile input_signal_count
;
129 static int input_signal_count
;
132 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
134 extern Lisp_Object Qface
, Qmouse_face
;
138 /* A mask of extra modifier bits to put into every keyboard char. */
139 extern int extra_keyboard_modifiers
;
141 static Lisp_Object Qvendor_specific_keysyms
;
143 void win32_delete_display ();
145 static void redraw_previous_char ();
146 static void redraw_following_char ();
147 static unsigned int win32_get_modifiers ();
149 static int fast_find_position ();
150 static void note_mouse_highlight ();
151 static void clear_mouse_face ();
152 static void show_mouse_face ();
153 static void do_line_dance ();
155 static int win32_cursor_to ();
156 static int win32_clear_end_of_line ();
159 /* This is a function useful for recording debugging information
160 about the sequence of occurrences in this file. */
168 struct record event_record
[100];
170 int event_record_index
;
172 record_event (locus
, type
)
176 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
177 event_record_index
= 0;
179 event_record
[event_record_index
].locus
= locus
;
180 event_record
[event_record_index
].type
= type
;
181 event_record_index
++;
186 /* Return the struct win32_display_info. */
188 struct win32_display_info
*
189 win32_display_info_for_display ()
191 return (&one_win32_display_info
);
195 win32_fill_rect (f
, _hdc
, pix
, lprect
)
210 hdc
= get_frame_dc (f
);
213 hb
= CreateSolidBrush (pix
);
214 FillRect (hdc
, lprect
, hb
);
218 release_frame_dc (f
, hdc
);
222 win32_clear_window (f
)
227 GetClientRect (FRAME_WIN32_WINDOW (f
), &rect
);
228 win32_clear_rect (f
, NULL
, &rect
);
232 /* Starting and ending updates.
234 These hooks are called by update_frame at the beginning and end
235 of a frame update. We record in `updating_frame' the identity
236 of the frame being updated, so that the win32_... functions do not
237 need to take a frame as argument. Most of the win32_... functions
238 should never be called except during an update, the only exceptions
239 being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight. */
242 win32_update_begin (f
)
248 flexlines
= f
->height
;
253 /* Regenerate display palette before drawing if list of requested
254 colors has changed. */
255 if (FRAME_WIN32_DISPLAY_INFO (f
)->regen_palette
)
257 win32_regenerate_palette (f
);
258 FRAME_WIN32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
261 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
263 /* Don't do highlighting for mouse motion during the update. */
264 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
266 /* If the frame needs to be redrawn,
267 simply forget about any prior mouse highlighting. */
268 if (FRAME_GARBAGED_P (f
))
269 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
271 if (!NILP (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
273 int firstline
, lastline
, i
;
274 struct window
*w
= XWINDOW (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
);
276 /* Find the first, and the last+1, lines affected by redisplay. */
277 for (firstline
= 0; firstline
< f
->height
; firstline
++)
278 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
281 lastline
= f
->height
;
282 for (i
= f
->height
- 1; i
>= 0; i
--)
284 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
290 /* Can we tell that this update does not affect the window
291 where the mouse highlight is? If so, no need to turn off.
292 Likewise, don't do anything if the frame is garbaged;
293 in that case, the FRAME_CURRENT_GLYPHS that we would use
294 are all wrong, and we will redisplay that line anyway. */
295 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
296 || lastline
< XFASTINT (w
->top
)))
297 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
311 x_display_cursor (f
, 1);
313 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
314 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
319 /* This is called after a redisplay on frame F. */
322 win32_frame_up_to_date (f
)
325 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
326 || f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
328 note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
329 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
330 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
331 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
335 /* External interface to control of standout mode.
336 Call this when about to modify line at position VPOS
337 and not change whether it is highlighted. */
339 win32_reassert_line_highlight (new, vpos
)
345 /* Call this when about to modify line at position VPOS
346 and change whether it is highlighted. */
349 win32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
350 int new_highlight
, vpos
, first_unused_hpos
;
352 highlight
= new_highlight
;
353 win32_cursor_to (vpos
, 0);
354 win32_clear_end_of_line (updating_frame
->width
);
357 /* This is used when starting Emacs and when restarting after suspend.
358 When starting Emacs, no window is mapped. And nothing must be done
359 to Emacs's own window if it is suspended (though that rarely happens). */
362 win32_set_terminal_modes ()
366 /* This is called when exiting or suspending Emacs.
367 Exiting will make the Win32 windows go away, and suspending
368 requires no action. */
371 win32_reset_terminal_modes ()
375 /* Set the nominal cursor position of the frame.
376 This is where display update commands will take effect.
377 This does not affect the place where the cursor-box is displayed. */
380 win32_cursor_to (row
, col
)
381 register int row
, col
;
388 if (updating_frame
== 0)
391 x_display_cursor (selected_frame
, 1);
396 /* Display a sequence of N glyphs found at GP.
397 WINDOW is the window to output to. LEFT and TOP are starting coords.
398 HL is 1 if this text is highlighted, 2 if the cursor is on it,
399 3 if should appear in its mouse-face.
400 JUST_FOREGROUND if 1 means draw only the foreground;
401 don't alter the background.
403 FONT is the default font to use (for glyphs whose font-code is 0).
405 Since the display generation code is responsible for calling
406 compute_char_face and compute_glyph_face on everything it puts in
407 the display structure, we can assume that the face code on each
408 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
409 to which we can actually apply intern_face.
410 Call this function with input blocked. */
413 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
416 register GLYPH
*gp
; /* Points to first GLYPH. */
417 register int n
; /* Number of glyphs to display. */
421 /* Holds characters to be displayed. */
422 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
423 register char *cp
; /* Steps through buf[]. */
424 register int tlen
= GLYPH_TABLE_LENGTH
;
425 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
426 Window window
= FRAME_WIN32_WINDOW (f
);
427 int orig_left
= left
;
430 hdc
= get_frame_dc (f
);
434 /* Get the face-code of the next GLYPH. */
438 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
439 cf
= FAST_GLYPH_FACE (g
);
441 /* Find the run of consecutive glyphs with the same face-code.
442 Extract their character codes into BUF. */
447 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
448 if (FAST_GLYPH_FACE (g
) != cf
)
451 *cp
++ = FAST_GLYPH_CHAR (g
);
456 /* LEN gets the length of the run. */
459 /* Now output this run of chars, with the font and pixel values
460 determined by the face code CF. */
462 struct face
*face
= FRAME_DEFAULT_FACE (f
);
463 XFontStruct
*font
= FACE_FONT (face
);
468 /* HL = 3 means use a mouse face previously chosen. */
470 cf
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
;
472 /* First look at the face of the text itself. */
475 /* It's possible for the display table to specify
476 a face code that is out of range. Use 0 in that case. */
477 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
478 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
482 face
= FRAME_MODE_LINE_FACE (f
);
484 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
485 font
= FACE_FONT (face
);
486 if (FACE_STIPPLE (face
))
490 /* Then comes the distinction between modeline and normal text. */
495 face
= FRAME_MODE_LINE_FACE (f
);
496 font
= FACE_FONT (face
);
497 if (FACE_STIPPLE (face
))
501 fg
= face
->foreground
;
502 bg
= face
->background
;
504 /* Now override that if the cursor's on this character. */
507 /* The cursor overrides stippling. */
511 || face
->font
== (XFontStruct
*) FACE_DEFAULT
512 || face
->font
== f
->output_data
.win32
->font
)
513 && face
->background
== f
->output_data
.win32
->background_pixel
514 && face
->foreground
== f
->output_data
.win32
->foreground_pixel
)
516 bg
= f
->output_data
.win32
->cursor_pixel
;
517 fg
= face
->background
;
519 /* Cursor on non-default face: must merge. */
522 bg
= f
->output_data
.win32
->cursor_pixel
;
523 fg
= face
->background
;
524 /* If the glyph would be invisible,
525 try a different foreground. */
527 fg
= face
->foreground
;
529 fg
= f
->output_data
.win32
->cursor_foreground_pixel
;
531 fg
= face
->foreground
;
532 /* Make sure the cursor is distinct from text in this face. */
533 if (bg
== face
->background
534 && fg
== face
->foreground
)
536 bg
= face
->foreground
;
537 fg
= face
->background
;
542 if (font
== (XFontStruct
*) FACE_DEFAULT
)
543 font
= f
->output_data
.win32
->font
;
545 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
547 SetTextColor (hdc
, fg
);
548 SetBkColor (hdc
, bg
);
550 SelectObject (hdc
, font
->hfont
);
552 TextOut (hdc
, left
, top
, buf
, len
);
554 if (!just_foreground
)
556 /* Clear the rest of the line's height. */
557 if (f
->output_data
.win32
->line_height
!= FONT_HEIGHT (font
))
558 win32_fill_area (f
, hdc
, bg
,
560 top
+ FONT_HEIGHT (font
),
561 FONT_WIDTH (font
) * len
,
562 f
->output_data
.win32
->line_height
- FONT_HEIGHT (font
));
566 int underline_position
= 1;
568 if (font
->tm
.tmDescent
<= underline_position
)
569 underline_position
= font
->tm
.tmDescent
- 1;
572 win32_fill_area (f
, hdc
, fg
,
575 + underline_position
),
576 len
* FONT_WIDTH (font
), 1);
579 left
+= len
* FONT_WIDTH (font
);
583 release_frame_dc (f
, hdc
);
587 /* Output some text at the nominal frame cursor position.
588 Advance the cursor over the text.
589 Output LEN glyphs at START.
591 `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
592 controls the pixel values used for foreground and background. */
595 win32_write_glyphs (start
, len
)
596 register GLYPH
*start
;
599 register int temp_length
;
609 /* If not within an update,
610 output at the frame's visible cursor. */
611 curs_x
= f
->cursor_x
;
612 curs_y
= f
->cursor_y
;
616 CHAR_TO_PIXEL_COL (f
, curs_x
),
617 CHAR_TO_PIXEL_ROW (f
, curs_y
),
618 start
, len
, highlight
, 0);
620 /* If we drew on top of the cursor, note that it is turned off. */
621 if (curs_y
== f
->phys_cursor_y
622 && curs_x
<= f
->phys_cursor_x
623 && curs_x
+ len
> f
->phys_cursor_x
)
624 f
->phys_cursor_x
= -1;
626 if (updating_frame
== 0)
629 x_display_cursor (f
, 1);
638 /* Clear to the end of the line.
639 Erase the current text line from the nominal cursor position (inclusive)
640 to column FIRST_UNUSED (exclusive). The idea is that everything
641 from FIRST_UNUSED onward is already erased. */
644 win32_clear_end_of_line (first_unused
)
645 register int first_unused
;
647 struct frame
*f
= updating_frame
;
652 if (curs_y
< 0 || curs_y
>= f
->height
)
654 if (first_unused
<= 0)
657 if (first_unused
>= f
->width
)
658 first_unused
= f
->width
;
664 /* Notice if the cursor will be cleared by this operation. */
665 if (curs_y
== f
->phys_cursor_y
666 && curs_x
<= f
->phys_cursor_x
667 && f
->phys_cursor_x
< first_unused
)
668 f
->phys_cursor_x
= -1;
670 win32_clear_area (f
, NULL
,
671 CHAR_TO_PIXEL_COL (f
, curs_x
),
672 CHAR_TO_PIXEL_ROW (f
, curs_y
),
673 FONT_WIDTH (f
->output_data
.win32
->font
) * (first_unused
- curs_x
),
674 f
->output_data
.win32
->line_height
);
682 struct frame
*f
= updating_frame
;
687 f
->phys_cursor_x
= -1; /* Cursor not visible. */
688 curs_x
= 0; /* Nominal cursor position is top left. */
693 win32_clear_window (f
);
695 /* We have to clear the scroll bars, too. If we have changed
696 colors or something like that, then they should be notified. */
697 x_scroll_bar_clear (f
);
702 /* Make audible bell. */
709 FlashWindow (FRAME_WIN32_WINDOW (selected_frame
), FALSE
);
718 /* Insert and delete character.
719 These are not supposed to be used because we are supposed to turn
720 off the feature of using them. */
723 win32_insert_glyphs (start
, len
)
724 register char *start
;
731 win32_delete_glyphs (n
)
737 /* Specify how many text lines, from the top of the window,
738 should be affected by insert-lines and delete-lines operations.
739 This, and those operations, are used only within an update
740 that is bounded by calls to win32_update_begin and win32_update_end. */
743 win32_set_terminal_window (n
)
746 if (updating_frame
== 0)
749 if ((n
<= 0) || (n
> updating_frame
->height
))
750 flexlines
= updating_frame
->height
;
755 /* These variables need not be per frame
756 because redisplay is done on a frame-by-frame basis
757 and the line dance for one frame is finished before
758 anything is done for another frame. */
760 /* Array of line numbers from cached insert/delete operations.
761 line_dance[i] is the old position of the line that we want
762 to move to line i, or -1 if we want a blank line there. */
763 static int *line_dance
;
765 /* Allocated length of that array. */
766 static int line_dance_len
;
768 /* Flag indicating whether we've done any work. */
769 static int line_dance_in_progress
;
771 /* Perform an insert-lines or delete-lines operation,
772 inserting N lines or deleting -N lines at vertical position VPOS. */
773 win32_ins_del_lines (vpos
, n
)
776 register int fence
, i
;
778 if (vpos
>= flexlines
)
781 if (!line_dance_in_progress
)
783 int ht
= updating_frame
->height
;
784 if (ht
> line_dance_len
)
786 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
789 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
790 line_dance_in_progress
= 1;
794 if (n
> flexlines
- vpos
)
795 n
= flexlines
- vpos
;
797 for (i
= flexlines
; --i
>= fence
;)
798 line_dance
[i
] = line_dance
[i
-n
];
799 for (i
= fence
; --i
>= vpos
;)
805 if (n
> flexlines
- vpos
)
806 n
= flexlines
- vpos
;
807 fence
= flexlines
- n
;
808 for (i
= vpos
; i
< fence
; ++i
)
809 line_dance
[i
] = line_dance
[i
+ n
];
810 for (i
= fence
; i
< flexlines
; ++i
)
815 /* Here's where we actually move the pixels around.
816 Must be called with input blocked. */
820 register int i
, j
, distance
;
821 register struct frame
*f
;
826 /* Must check this flag first. If it's not set, then not only is the
827 array uninitialized, but we might not even have a frame. */
828 if (!line_dance_in_progress
)
836 intborder
= f
->output_data
.win32
->internal_border_width
;
838 x_display_cursor (updating_frame
, 0);
840 hdc
= get_frame_dc (f
);
842 for (i
= 0; i
< ht
; ++i
)
843 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
845 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
846 && line_dance
[j
]-j
== distance
); ++j
);
847 /* Copy [i,j) upward from [i+distance, j+distance) */
849 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
850 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
851 (j
-i
) * f
->output_data
.win32
->line_height
,
853 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
858 for (i
= ht
; --i
>=0; )
859 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
861 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
862 && line_dance
[j
]-j
== distance
););
863 /* Copy (j, i] downward from (j+distance, i+distance] */
865 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
866 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
867 (i
-j
) * f
->output_data
.win32
->line_height
,
869 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
874 release_frame_dc (f
, hdc
);
876 for (i
= 0; i
< ht
; ++i
)
877 if (line_dance
[i
] == -1)
879 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
881 win32_clear_area (f
, NULL
,
883 CHAR_TO_PIXEL_ROW (f
, i
),
884 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
885 (j
-i
) * f
->output_data
.win32
->line_height
);
888 line_dance_in_progress
= 0;
891 /* Support routines for exposure events. */
892 static void clear_cursor ();
894 /* Output into a rectangle of a window (for frame F)
895 the characters in f->phys_lines that overlap that rectangle.
896 TOP and LEFT are the position of the upper left corner of the rectangle.
897 ROWS and COLS are the size of the rectangle.
898 Call this function with input blocked. */
901 dumprectangle (f
, left
, top
, cols
, rows
)
903 register int left
, top
, cols
, rows
;
905 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
906 int cursor_cleared
= 0;
910 if (FRAME_GARBAGED_P (f
))
913 /* Express rectangle as four edges, instead of position-and-size. */
917 /* Convert rectangle edges in pixels to edges in chars.
918 Round down for left and top, up for right and bottom. */
919 top
= PIXEL_TO_CHAR_ROW (f
, top
);
920 left
= PIXEL_TO_CHAR_COL (f
, left
);
921 bottom
+= (f
->output_data
.win32
->line_height
- 1);
922 right
+= (FONT_WIDTH (f
->output_data
.win32
->font
) - 1);
923 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
924 right
= PIXEL_TO_CHAR_COL (f
, right
);
926 /* Clip the rectangle to what can be visible. */
931 if (right
> f
->width
)
933 if (bottom
> f
->height
)
936 /* Get size in chars of the rectangle. */
940 /* If rectangle has zero area, return. */
941 if (rows
<= 0) return;
942 if (cols
<= 0) return;
944 /* Turn off the cursor if it is in the rectangle.
945 We will turn it back on afterward. */
946 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
947 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
953 /* Display the text in the rectangle, one text line at a time. */
955 for (y
= top
; y
< bottom
; y
++)
957 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
959 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
963 CHAR_TO_PIXEL_COL (f
, left
),
964 CHAR_TO_PIXEL_ROW (f
, y
),
965 line
, min (cols
, active_frame
->used
[y
] - left
),
966 active_frame
->highlight
[y
], 0);
969 /* Turn the cursor on if we turned it off. */
972 x_display_cursor (f
, 1);
979 x_display_cursor (f
, 1);
983 frame_unhighlight (f
)
986 x_display_cursor (f
, 1);
989 static void win32_frame_rehighlight ();
990 static void x_frame_rehighlight ();
992 /* The focus has changed. Update the frames as necessary to reflect
993 the new situation. Note that we can't change the selected frame
994 here, because the Lisp code we are interrupting might become confused.
995 Each event gets marked with the frame in which it occurred, so the
996 Lisp code can tell when the switch took place by examining the events. */
999 x_new_focus_frame (dpyinfo
, frame
)
1000 struct win32_display_info
*dpyinfo
;
1001 struct frame
*frame
;
1003 struct frame
*old_focus
= dpyinfo
->win32_focus_frame
;
1004 int events_enqueued
= 0;
1006 if (frame
!= dpyinfo
->win32_focus_frame
)
1008 /* Set this before calling other routines, so that they see
1009 the correct value of win32_focus_frame. */
1010 dpyinfo
->win32_focus_frame
= frame
;
1012 if (old_focus
&& old_focus
->auto_lower
)
1013 x_lower_frame (old_focus
);
1015 if (dpyinfo
->win32_focus_frame
&& dpyinfo
->win32_focus_frame
->auto_raise
)
1016 pending_autoraise_frame
= dpyinfo
->win32_focus_frame
;
1018 pending_autoraise_frame
= 0;
1021 x_frame_rehighlight (dpyinfo
);
1024 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1027 x_mouse_leave (dpyinfo
)
1028 struct win32_display_info
*dpyinfo
;
1030 x_new_focus_frame (dpyinfo
, dpyinfo
->win32_focus_event_frame
);
1033 /* The focus has changed, or we have redirected a frame's focus to
1034 another frame (this happens when a frame uses a surrogate
1035 minibuffer frame). Shift the highlight as appropriate.
1037 The FRAME argument doesn't necessarily have anything to do with which
1038 frame is being highlighted or unhighlighted; we only use it to find
1039 the appropriate display info. */
1041 win32_frame_rehighlight (frame
)
1042 struct frame
*frame
;
1044 x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame
));
1048 x_frame_rehighlight (dpyinfo
)
1049 struct win32_display_info
*dpyinfo
;
1051 struct frame
*old_highlight
= dpyinfo
->win32_highlight_frame
;
1053 if (dpyinfo
->win32_focus_frame
)
1055 dpyinfo
->win32_highlight_frame
1056 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
)))
1057 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
))
1058 : dpyinfo
->win32_focus_frame
);
1059 if (! FRAME_LIVE_P (dpyinfo
->win32_highlight_frame
))
1061 FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
) = Qnil
;
1062 dpyinfo
->win32_highlight_frame
= dpyinfo
->win32_focus_frame
;
1066 dpyinfo
->win32_highlight_frame
= 0;
1068 if (dpyinfo
->win32_highlight_frame
!= old_highlight
)
1071 frame_unhighlight (old_highlight
);
1072 if (dpyinfo
->win32_highlight_frame
)
1073 frame_highlight (dpyinfo
->win32_highlight_frame
);
1077 /* Keyboard processing - modifier keys, etc. */
1079 /* Convert a keysym to its name. */
1082 x_get_keysym_name (keysym
)
1085 /* Make static so we can always return it */
1086 static char value
[100];
1089 GetKeyNameText(keysym
, value
, 100);
1095 /* Mouse clicks and mouse movement. Rah. */
1097 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1098 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1099 that the glyph at X, Y occupies, if BOUNDS != 0.
1100 If NOCLIP is nonzero, do not force the value into range. */
1103 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1105 register int pix_x
, pix_y
;
1106 register int *x
, *y
;
1110 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1111 if (NILP (Vwindow_system
))
1118 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1119 even for negative values. */
1121 pix_x
-= FONT_WIDTH ((f
)->output_data
.win32
->font
) - 1;
1123 pix_y
-= (f
)->output_data
.win32
->line_height
- 1;
1125 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1126 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1130 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1131 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1132 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.win32
->font
) - 1;
1133 bounds
->bottom
= bounds
->top
+ f
->output_data
.win32
->line_height
- 1;
1140 else if (pix_x
> f
->width
)
1145 else if (pix_y
> f
->height
)
1154 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1157 register int *pix_x
, *pix_y
;
1159 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1160 if (NILP (Vwindow_system
))
1167 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1168 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1172 parse_button (message
, pbutton
, pup
)
1182 case WM_LBUTTONDOWN
:
1190 case WM_MBUTTONDOWN
:
1191 if (NILP (Vwin32_swap_mouse_buttons
))
1198 if (NILP (Vwin32_swap_mouse_buttons
))
1204 case WM_RBUTTONDOWN
:
1205 if (NILP (Vwin32_swap_mouse_buttons
))
1212 if (NILP (Vwin32_swap_mouse_buttons
))
1223 if (pbutton
) *pbutton
= button
;
1229 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1231 If the event is a button press, then note that we have grabbed
1235 construct_mouse_click (result
, msg
, f
)
1236 struct input_event
*result
;
1243 parse_button (msg
->msg
.message
, &button
, &up
);
1245 /* Make the event type no_event; we'll change that when we decide
1247 result
->kind
= mouse_click
;
1248 result
->code
= button
;
1249 result
->timestamp
= msg
->msg
.time
;
1250 result
->modifiers
= (msg
->dwModifiers
1258 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1259 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1260 XSETFRAME (result
->frame_or_window
, f
);
1265 /* Function to report a mouse movement to the mainstream Emacs code.
1266 The input handler calls this.
1268 We have received a mouse movement event, which is given in *event.
1269 If the mouse is over a different glyph than it was last time, tell
1270 the mainstream emacs code by setting mouse_moved. If not, ask for
1271 another motion event, so we can check again the next time it moves. */
1274 note_mouse_movement (frame
, msg
)
1278 last_mouse_movement_time
= msg
->time
;
1280 if (msg
->hwnd
!= FRAME_WIN32_WINDOW (frame
))
1282 frame
->mouse_moved
= 1;
1283 last_mouse_scroll_bar
= Qnil
;
1285 note_mouse_highlight (frame
, -1, -1);
1288 /* Has the mouse moved off the glyph it was on at the last sighting? */
1289 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1290 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1291 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
1292 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1294 frame
->mouse_moved
= 1;
1295 last_mouse_scroll_bar
= Qnil
;
1297 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1301 /* This is used for debugging, to turn off note_mouse_highlight. */
1302 static int disable_mouse_highlight
;
1304 /* Take proper action when the mouse has moved to position X, Y on frame F
1305 as regards highlighting characters that have mouse-face properties.
1306 Also dehighlighting chars where the mouse was before.
1307 X and Y can be negative or out of range. */
1310 note_mouse_highlight (f
, x
, y
)
1314 int row
, column
, portion
;
1319 if (disable_mouse_highlight
)
1322 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1323 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1324 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1326 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
)
1331 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1335 /* Find out which glyph the mouse is on. */
1336 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1337 &new_glyph
, FRAME_WIN32_DISPLAY_INFO (f
)->grabbed
);
1339 /* Which window is that in? */
1340 window
= window_from_coordinates (f
, column
, row
, &portion
);
1341 w
= XWINDOW (window
);
1343 /* If we were displaying active text in another window, clear that. */
1344 if (! EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
1345 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1347 /* Are we in a window whose display is up to date?
1348 And verify the buffer's text has not changed. */
1349 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1350 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1351 && EQ (w
->window_end_valid
, w
->buffer
)
1352 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1354 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1357 /* Find which buffer position the mouse corresponds to. */
1358 for (i
= column
; i
>= 0; i
--)
1362 /* Is it outside the displayed active region (if any)? */
1364 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1365 else if (! (EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
)
1366 && row
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1367 && row
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1368 && (row
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1369 || column
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1370 && (row
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1371 || column
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1372 || FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1374 Lisp_Object mouse_face
, overlay
, position
;
1375 Lisp_Object
*overlay_vec
;
1376 int len
, noverlays
, ignor1
;
1377 struct buffer
*obuf
;
1380 /* If we get an out-of-range value, return now; avoid an error. */
1381 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1384 /* Make the window's buffer temporarily current for
1385 overlays_at and compute_char_face. */
1386 obuf
= current_buffer
;
1387 current_buffer
= XBUFFER (w
->buffer
);
1393 /* Yes. Clear the display of the old active region, if any. */
1394 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1396 /* Is this char mouse-active? */
1397 XSETINT (position
, pos
);
1400 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1402 /* Put all the overlays we want in a vector in overlay_vec.
1403 Store the length in len. */
1404 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1406 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1408 /* Find the highest priority overlay that has a mouse-face prop. */
1410 for (i
= 0; i
< noverlays
; i
++)
1412 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1413 if (!NILP (mouse_face
))
1415 overlay
= overlay_vec
[i
];
1420 /* If no overlay applies, get a text property. */
1422 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1424 /* Handle the overlay case. */
1425 if (! NILP (overlay
))
1427 /* Find the range of text around this char that
1428 should be active. */
1429 Lisp_Object before
, after
;
1432 before
= Foverlay_start (overlay
);
1433 after
= Foverlay_end (overlay
);
1434 /* Record this as the current active region. */
1435 fast_find_position (window
, before
,
1436 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1437 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1438 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1439 = !fast_find_position (window
, after
,
1440 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1441 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1442 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1443 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1444 = compute_char_face (f
, w
, pos
, 0, 0,
1445 &ignore
, pos
+ 1, 1);
1447 /* Display it as active. */
1448 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1450 /* Handle the text property case. */
1451 else if (! NILP (mouse_face
))
1453 /* Find the range of text around this char that
1454 should be active. */
1455 Lisp_Object before
, after
, beginning
, end
;
1458 beginning
= Fmarker_position (w
->start
);
1459 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1460 - XFASTINT (w
->window_end_pos
)));
1462 = Fprevious_single_property_change (make_number (pos
+ 1),
1464 w
->buffer
, beginning
);
1466 = Fnext_single_property_change (position
, Qmouse_face
,
1468 /* Record this as the current active region. */
1469 fast_find_position (window
, before
,
1470 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1471 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1472 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1473 = !fast_find_position (window
, after
,
1474 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1475 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1476 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1477 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1478 = compute_char_face (f
, w
, pos
, 0, 0,
1479 &ignore
, pos
+ 1, 1);
1481 /* Display it as active. */
1482 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1486 current_buffer
= obuf
;
1491 /* Find the row and column of position POS in window WINDOW.
1492 Store them in *COLUMNP and *ROWP.
1493 This assumes display in WINDOW is up to date.
1494 If POS is above start of WINDOW, return coords
1495 of start of first screen line.
1496 If POS is after end of WINDOW, return coords of end of last screen line.
1498 Value is 1 if POS is in range, 0 if it was off screen. */
1501 fast_find_position (window
, pos
, columnp
, rowp
)
1504 int *columnp
, *rowp
;
1506 struct window
*w
= XWINDOW (window
);
1507 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1512 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1513 int width
= window_internal_width (w
);
1516 int maybe_next_line
= 0;
1518 /* Find the right row. */
1523 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1524 if (linestart
> pos
)
1526 /* If the position sought is the end of the buffer,
1527 don't include the blank lines at the bottom of the window. */
1528 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1530 maybe_next_line
= 1;
1537 /* Find the right column with in it. */
1538 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1540 for (i
= 0; i
< width
; i
++)
1542 if (charstarts
[left
+ i
] == pos
)
1545 *columnp
= i
+ left
;
1548 else if (charstarts
[left
+ i
] > pos
)
1550 else if (charstarts
[left
+ i
] > 0)
1554 /* If we're looking for the end of the buffer,
1555 and we didn't find it in the line we scanned,
1556 use the start of the following line. */
1557 if (maybe_next_line
)
1568 /* Display the active region described by mouse_face_*
1569 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1572 show_mouse_face (dpyinfo
, hl
)
1573 struct win32_display_info
*dpyinfo
;
1576 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1577 int width
= window_internal_width (w
);
1578 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1581 int old_curs_x
= curs_x
;
1582 int old_curs_y
= curs_y
;
1584 /* Set these variables temporarily
1585 so that if we have to turn the cursor off and on again
1586 we will put it back at the same place. */
1587 curs_x
= f
->phys_cursor_x
;
1588 curs_y
= f
->phys_cursor_y
;
1590 for (i
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1591 i
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1593 int column
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1594 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
1596 int endcolumn
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1597 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1599 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1601 /* If the cursor's in the text we are about to rewrite,
1602 turn the cursor off. */
1604 && curs_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
1605 && curs_x
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
)
1607 x_display_cursor (f
, 0);
1612 CHAR_TO_PIXEL_COL (f
, column
),
1613 CHAR_TO_PIXEL_ROW (f
, i
),
1614 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1616 /* Highlight with mouse face if hl > 0. */
1620 /* If we turned the cursor off, turn it back on. */
1622 x_display_cursor (f
, 1);
1624 curs_x
= old_curs_x
;
1625 curs_y
= old_curs_y
;
1627 /* Change the mouse cursor according to the value of HL. */
1629 SetCursor (f
->output_data
.win32
->cross_cursor
);
1631 SetCursor (f
->output_data
.win32
->text_cursor
);
1634 /* Clear out the mouse-highlighted active region.
1635 Redraw it unhighlighted first. */
1638 clear_mouse_face (dpyinfo
)
1639 struct win32_display_info
*dpyinfo
;
1641 if (! NILP (dpyinfo
->mouse_face_window
))
1642 show_mouse_face (dpyinfo
, 0);
1644 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1645 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1646 dpyinfo
->mouse_face_window
= Qnil
;
1649 struct scroll_bar
*x_window_to_scroll_bar ();
1650 static void x_scroll_bar_report_motion ();
1652 /* Return the current position of the mouse.
1653 *fp should be a frame which indicates which display to ask about.
1655 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1656 and *part to the frame, window, and scroll bar part that the mouse
1657 is over. Set *x and *y to the portion and whole of the mouse's
1658 position on the scroll bar.
1660 If the mouse movement started elsewhere, set *fp to the frame the
1661 mouse is on, *bar_window to nil, and *x and *y to the character cell
1664 Set *time to the server timestamp for the time at which the mouse
1665 was at this position.
1667 Don't store anything if we don't have a valid set of values to report.
1669 This clears the mouse_moved flag, so we can wait for the next mouse
1670 movement. This also calls XQueryPointer, which will cause the
1671 server to give us another MotionNotify when the mouse moves
1675 win32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1678 Lisp_Object
*bar_window
;
1679 enum scroll_bar_part
*part
;
1681 unsigned long *time
;
1687 if (! NILP (last_mouse_scroll_bar
))
1688 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1693 Lisp_Object frame
, tail
;
1695 /* Clear the mouse-moved flag for every frame on this display. */
1696 FOR_EACH_FRAME (tail
, frame
)
1697 XFRAME (frame
)->mouse_moved
= 0;
1699 last_mouse_scroll_bar
= Qnil
;
1703 /* Now we have a position on the root; find the innermost window
1704 containing the pointer. */
1706 if (FRAME_WIN32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1707 && FRAME_LIVE_P (last_mouse_frame
))
1709 f1
= last_mouse_frame
;
1713 /* Is win one of our frames? */
1714 f1
= x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1717 /* If not, is it one of our scroll bars? */
1720 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1724 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1728 if (f1
== 0 && insist
)
1729 f1
= selected_frame
;
1733 int ignore1
, ignore2
;
1735 ScreenToClient (FRAME_WIN32_WINDOW (f1
), &pt
);
1737 /* Ok, we found a frame. Store all the values. */
1739 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1741 FRAME_WIN32_DISPLAY_INFO (f1
)->grabbed
1749 *time
= last_mouse_movement_time
;
1757 /* Scroll bar support. */
1759 /* Given an window ID, find the struct scroll_bar which manages it.
1760 This can be called in GC, so we have to make sure to strip off mark
1763 x_window_to_scroll_bar (window_id
)
1766 Lisp_Object tail
, frame
;
1768 for (tail
= Vframe_list
;
1769 XGCTYPE (tail
) == Lisp_Cons
;
1770 tail
= XCONS (tail
)->cdr
)
1772 Lisp_Object frame
, bar
, condemned
;
1774 frame
= XCONS (tail
)->car
;
1775 /* All elements of Vframe_list should be frames. */
1776 if (! GC_FRAMEP (frame
))
1779 /* Scan this frame's scroll bar list for a scroll bar with the
1781 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1782 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1783 /* This trick allows us to search both the ordinary and
1784 condemned scroll bar lists with one loop. */
1785 ! GC_NILP (bar
) || (bar
= condemned
,
1788 bar
= XSCROLL_BAR (bar
)->next
)
1789 if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1790 return XSCROLL_BAR (bar
);
1797 my_create_scrollbar (f
, bar
)
1799 struct scroll_bar
* bar
;
1803 PostThreadMessage (dwWinThreadId
, WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1805 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
1807 return ((HWND
) msg
.wParam
);
1810 //#define ATTACH_THREADS
1813 my_show_window (HWND hwnd
, int how
)
1815 #ifndef ATTACH_THREADS
1816 SendMessage (hwnd
, WM_EMACS_SHOWWINDOW
, (WPARAM
) how
, 0);
1818 ShowWindow (hwnd
, how
);
1823 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
1824 int x
, int y
, int cx
, int cy
, int flags
)
1826 #ifndef ATTACH_THREADS
1828 pos
.hwndAfter
= hwndAfter
;
1834 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
1836 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1841 my_destroy_window (f
, hwnd
)
1845 SendMessage (FRAME_WIN32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
1849 /* Open a new window to serve as a scroll bar, and return the
1850 scroll bar vector for it. */
1851 static struct scroll_bar
*
1852 x_scroll_bar_create (window
, top
, left
, width
, height
)
1853 struct window
*window
;
1854 int top
, left
, width
, height
;
1856 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1857 struct scroll_bar
*bar
1858 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1863 XSETWINDOW (bar
->window
, window
);
1864 XSETINT (bar
->top
, top
);
1865 XSETINT (bar
->left
, left
);
1866 XSETINT (bar
->width
, width
);
1867 XSETINT (bar
->height
, height
);
1868 XSETINT (bar
->start
, 0);
1869 XSETINT (bar
->end
, 0);
1870 bar
->dragging
= Qnil
;
1872 /* Requires geometry to be set before call to create the real window */
1874 hwnd
= my_create_scrollbar (f
, bar
);
1876 SetScrollRange (hwnd
, SB_CTL
, 0, height
, FALSE
);
1877 SetScrollPos (hwnd
, SB_CTL
, 0, TRUE
);
1879 SET_SCROLL_BAR_WIN32_WINDOW (bar
, hwnd
);
1881 /* Add bar to its frame's list of scroll bars. */
1882 bar
->next
= FRAME_SCROLL_BARS (f
);
1884 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
1885 if (! NILP (bar
->next
))
1886 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
1893 /* Draw BAR's handle in the proper position.
1894 If the handle is already drawn from START to END, don't bother
1895 redrawing it, unless REBUILD is non-zero; in that case, always
1896 redraw it. (REBUILD is handy for drawing the handle after expose
1899 Normally, we want to constrain the start and end of the handle to
1900 fit inside its rectangle, but if the user is dragging the scroll bar
1901 handle, we want to let them drag it down all the way, so that the
1902 bar's top is as far down as it goes; otherwise, there's no way to
1903 move to the very end of the buffer. */
1905 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1906 struct scroll_bar
*bar
;
1910 int dragging
= ! NILP (bar
->dragging
);
1911 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1912 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1914 /* If the display is already accurate, do nothing. */
1916 && start
== XINT (bar
->start
)
1917 && end
== XINT (bar
->end
))
1922 /* Store the adjusted setting in the scroll bar. */
1923 XSETINT (bar
->start
, start
);
1924 XSETINT (bar
->end
, end
);
1926 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
1931 /* Move a scroll bar around on the screen, to accommodate changing
1932 window configurations. */
1934 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1935 struct scroll_bar
*bar
;
1936 int top
, left
, width
, height
;
1938 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1939 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1943 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
1944 SetScrollRange (w
, SB_CTL
, 0, height
, FALSE
);
1945 InvalidateRect (w
, NULL
, FALSE
);
1946 my_show_window (w
, SW_NORMAL
);
1948 XSETINT (bar
->left
, left
);
1949 XSETINT (bar
->top
, top
);
1950 XSETINT (bar
->width
, width
);
1951 XSETINT (bar
->height
, height
);
1956 /* Destroy the window for BAR, and set its Emacs window's scroll bar
1959 x_scroll_bar_remove (bar
)
1960 struct scroll_bar
*bar
;
1962 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1966 /* Destroy the window. */
1967 my_destroy_window (f
, SCROLL_BAR_WIN32_WINDOW (bar
));
1969 /* Disassociate this scroll bar from its window. */
1970 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
1975 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1976 that we are displaying PORTION characters out of a total of WHOLE
1977 characters, starting at POSITION. If WINDOW has no scroll bar,
1980 win32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
1981 struct window
*window
;
1982 int portion
, whole
, position
;
1984 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1985 int top
= XINT (window
->top
);
1986 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
1987 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
1989 /* Where should this scroll bar be, pixelwise? */
1990 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
1991 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
1993 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
1994 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
1995 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
1996 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
1998 struct scroll_bar
*bar
;
2000 /* Does the scroll bar exist yet? */
2001 if (NILP (window
->vertical_scroll_bar
))
2002 bar
= x_scroll_bar_create (window
,
2003 pixel_top
, pixel_left
,
2004 pixel_width
, pixel_height
);
2007 /* It may just need to be moved and resized. */
2008 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2009 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2012 /* Set the scroll bar's current state, unless we're currently being
2014 if (NILP (bar
->dragging
))
2016 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2019 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2022 int start
= (int) (((double) position
* top_range
) / whole
);
2023 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2025 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2029 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2033 /* The following three hooks are used when we're doing a thorough
2034 redisplay of the frame. We don't explicitly know which scroll bars
2035 are going to be deleted, because keeping track of when windows go
2036 away is a real pain - "Can you say set-window-configuration, boys
2037 and girls?" Instead, we just assert at the beginning of redisplay
2038 that *all* scroll bars are to be removed, and then save a scroll bar
2039 from the fiery pit when we actually redisplay its window. */
2041 /* Arrange for all scroll bars on FRAME to be removed at the next call
2042 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2043 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2045 win32_condemn_scroll_bars (frame
)
2048 /* The condemned list should be empty at this point; if it's not,
2049 then the rest of Emacs isn't using the condemn/redeem/judge
2050 protocol correctly. */
2051 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2054 /* Move them all to the "condemned" list. */
2055 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2056 FRAME_SCROLL_BARS (frame
) = Qnil
;
2059 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2060 Note that WINDOW isn't necessarily condemned at all. */
2062 win32_redeem_scroll_bar (window
)
2063 struct window
*window
;
2065 struct scroll_bar
*bar
;
2067 /* We can't redeem this window's scroll bar if it doesn't have one. */
2068 if (NILP (window
->vertical_scroll_bar
))
2071 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2073 /* Unlink it from the condemned list. */
2075 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2077 if (NILP (bar
->prev
))
2079 /* If the prev pointer is nil, it must be the first in one of
2081 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2082 /* It's not condemned. Everything's fine. */
2084 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2085 window
->vertical_scroll_bar
))
2086 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2088 /* If its prev pointer is nil, it must be at the front of
2089 one or the other! */
2093 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2095 if (! NILP (bar
->next
))
2096 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2098 bar
->next
= FRAME_SCROLL_BARS (f
);
2100 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2101 if (! NILP (bar
->next
))
2102 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2106 /* Remove all scroll bars on FRAME that haven't been saved since the
2107 last call to `*condemn_scroll_bars_hook'. */
2109 win32_judge_scroll_bars (f
)
2112 Lisp_Object bar
, next
;
2114 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2116 /* Clear out the condemned list now so we won't try to process any
2117 more events on the hapless scroll bars. */
2118 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2120 for (; ! NILP (bar
); bar
= next
)
2122 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2124 x_scroll_bar_remove (b
);
2127 b
->next
= b
->prev
= Qnil
;
2130 /* Now there should be no references to the condemned scroll bars,
2131 and they should get garbage-collected. */
2134 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2135 is set to something other than no_event, it is enqueued.
2137 This may be called from a signal handler, so we have to ignore GC
2141 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2142 struct scroll_bar
*bar
;
2144 struct input_event
*emacs_event
;
2146 if (! GC_WINDOWP (bar
->window
))
2149 emacs_event
->kind
= win32_scroll_bar_click
;
2150 emacs_event
->code
= 0;
2151 /* not really meaningful to distinguish up/down */
2152 emacs_event
->modifiers
= msg
->dwModifiers
;
2153 emacs_event
->frame_or_window
= bar
->window
;
2154 emacs_event
->timestamp
= msg
->msg
.time
;
2158 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2160 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2161 int y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2163 switch (LOWORD (msg
->msg
.wParam
))
2166 emacs_event
->part
= scroll_bar_handle
;
2167 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2168 y
= HIWORD (msg
->msg
.wParam
);
2171 emacs_event
->part
= scroll_bar_down_arrow
;
2174 emacs_event
->part
= scroll_bar_up_arrow
;
2177 emacs_event
->part
= scroll_bar_above_handle
;
2180 emacs_event
->part
= scroll_bar_below_handle
;
2183 emacs_event
->part
= scroll_bar_handle
;
2187 emacs_event
->part
= scroll_bar_handle
;
2190 case SB_THUMBPOSITION
:
2191 emacs_event
->part
= scroll_bar_handle
;
2195 SetScrollPos (SCROLL_BAR_WIN32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
2199 XSETINT (emacs_event
->x
, y
);
2200 XSETINT (emacs_event
->y
, top_range
);
2206 /* Return information to the user about the current position of the mouse
2207 on the scroll bar. */
2209 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2211 Lisp_Object
*bar_window
;
2212 enum scroll_bar_part
*part
;
2214 unsigned long *time
;
2216 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2217 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
2218 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2224 *bar_window
= bar
->window
;
2226 pos
= GetScrollPos (w
, SB_CTL
);
2228 switch (LOWORD (last_mouse_scroll_bar_pos
))
2230 case SB_THUMBPOSITION
:
2232 *part
= scroll_bar_handle
;
2233 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2234 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2237 *part
= scroll_bar_handle
;
2241 *part
= scroll_bar_handle
;
2246 XSETINT(*y
, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)));
2249 last_mouse_scroll_bar
= Qnil
;
2251 *time
= last_mouse_movement_time
;
2256 /* The screen has been cleared so we may have changed foreground or
2257 background colors, and the scroll bars may need to be redrawn.
2258 Clear out the scroll bars, and ask for expose events, so we can
2261 x_scroll_bar_clear (f
)
2266 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2267 bar
= XSCROLL_BAR (bar
)->next
)
2269 HWND window
= SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
));
2270 HDC hdc
= GetDC (window
);
2273 my_show_window (window
, SW_HIDE
);
2274 GetClientRect (window
, &rect
);
2275 select_palette (f
, hdc
);
2276 win32_clear_rect (f
, hdc
, &rect
);
2277 deselect_palette (f
, hdc
);
2281 show_scroll_bars (f
, how
)
2287 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2288 bar
= XSCROLL_BAR (bar
)->next
)
2290 HWND window
= SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
));
2291 my_show_window (window
, how
);
2296 /* The main Win32 event-reading loop - w32_read_socket. */
2298 /* Timestamp of enter window event. This is only used by w32_read_socket,
2299 but we have to put it out here, since static variables within functions
2300 sometimes don't work. */
2301 static Time enter_timestamp
;
2303 /* Record the last 100 characters stored
2304 to help debug the loss-of-chars-during-GC problem. */
2306 short temp_buffer
[100];
2308 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*);
2310 /* Map a Win32 WM_CHAR message into a KEY_EVENT_RECORD so that
2311 we can use the same routines to handle input in both console
2312 and window modes. */
2315 convert_to_key_event (Win32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2317 eventp
->bKeyDown
= TRUE
;
2318 eventp
->wRepeatCount
= 1;
2319 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2320 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2321 eventp
->uChar
.AsciiChar
= 0;
2322 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2325 /* Return nonzero if the virtual key is a dead key. */
2328 is_dead_key (int wparam
)
2330 unsigned int code
= MapVirtualKey (wparam
, 2);
2332 /* Win95 returns 0x8000, NT returns 0x80000000. */
2333 if ((code
& 0x8000) || (code
& 0x80000000))
2339 /* Read events coming from the Win32 shell.
2340 This routine is called by the SIGIO handler.
2341 We return as soon as there are no more events to be read.
2343 Events representing keys are stored in buffer BUFP,
2344 which can hold up to NUMCHARS characters.
2345 We return the number of characters stored into the buffer,
2346 thus pretending to be `read'.
2348 WAITP is nonzero if we should block until input arrives.
2349 EXPECTED is nonzero if the caller knows input is available.
2351 Some of these messages are reposted back to the message queue since the
2352 system calls the winproc directly in a context where we cannot return the
2353 data nor can we guarantee the state we are in. So if we dispatch them
2354 we will get into an infinite loop. To prevent this from ever happening we
2355 will set a variable to indicate we are in the read_socket call and indicate
2356 which message we are processing since the winproc gets called recursively with different
2357 messages by the system.
2361 w32_read_socket (sd
, bufp
, numchars
, waitp
, expected
)
2363 register struct input_event
*bufp
;
2364 register int numchars
;
2370 int items_pending
; /* How many items are in the X queue. */
2373 int event_found
= 0;
2376 struct win32_display_info
*dpyinfo
= &one_win32_display_info
;
2378 if (interrupt_input_blocked
)
2380 interrupt_input_pending
= 1;
2384 interrupt_input_pending
= 0;
2387 /* So people can tell when we have read the available input. */
2388 input_signal_count
++;
2391 abort (); /* Don't think this happens. */
2393 while (get_next_msg (&msg
, FALSE
))
2395 switch (msg
.msg
.message
)
2398 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2401 win32_clear_rect (f
, NULL
, &msg
.rect
);
2406 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2410 if (f
->async_visible
== 0)
2412 f
->async_visible
= 1;
2413 f
->async_iconified
= 0;
2414 SET_FRAME_GARBAGED (f
);
2421 msg
.rect
.right
-msg
.rect
.left
+1,
2422 msg
.rect
.bottom
-msg
.rect
.top
+1);
2429 case WM_PALETTECHANGED
:
2430 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2432 /* Realize palette - will force update if needed. */
2433 release_frame_dc (f
, get_frame_dc (f
));
2437 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2439 if (f
&& !f
->iconified
)
2441 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2443 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2444 bufp
->kind
= non_ascii_keystroke
;
2445 bufp
->code
= msg
.msg
.wParam
;
2446 bufp
->modifiers
= win32_kbd_mods_to_emacs (msg
.dwModifiers
);
2447 XSETFRAME (bufp
->frame_or_window
, f
);
2448 bufp
->timestamp
= msg
.msg
.time
;
2456 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2458 if (f
&& !f
->iconified
)
2463 KEY_EVENT_RECORD key
, *keyp
= &key
;
2465 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2468 convert_to_key_event (&msg
, keyp
);
2469 add
= key_event (keyp
, bufp
);
2470 XSETFRAME (bufp
->frame_or_window
, f
);
2473 /* The key pressed generated two characters, most likely
2474 an accent character and a key that could not be
2475 combined with it. Prepend the message on the queue
2476 again to process the second character (which is
2477 being held internally in key_event), and process
2478 the first character now. */
2483 /* Throw dead keys away. However, be sure not to
2484 throw away the dead key if it was produced using
2485 AltGr and there is a valid AltGr scan code for
2487 if (is_dead_key (msg
.msg
.wParam
)
2488 && !((VkKeyScan (bufp
->code
) & 0xff00) == 0x600))
2502 if (dpyinfo
->grabbed
&& last_mouse_frame
2503 && FRAME_LIVE_P (last_mouse_frame
))
2504 f
= last_mouse_frame
;
2506 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2509 note_mouse_movement (f
, &msg
.msg
);
2511 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
2514 case WM_LBUTTONDOWN
:
2516 case WM_MBUTTONDOWN
:
2518 case WM_RBUTTONDOWN
:
2524 if (dpyinfo
->grabbed
&& last_mouse_frame
2525 && FRAME_LIVE_P (last_mouse_frame
))
2526 f
= last_mouse_frame
;
2528 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2532 if ((!dpyinfo
->win32_focus_frame
|| f
== dpyinfo
->win32_focus_frame
)
2535 construct_mouse_click (bufp
, &msg
, f
);
2542 parse_button (msg
.msg
.message
, &button
, &up
);
2546 dpyinfo
->grabbed
&= ~ (1 << button
);
2550 dpyinfo
->grabbed
|= (1 << button
);
2551 last_mouse_frame
= f
;
2558 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2560 if (bar
&& numchars
>= 1)
2562 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2573 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2575 if (f
&& !f
->async_iconified
)
2577 f
->output_data
.win32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2578 f
->output_data
.win32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2583 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2585 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2593 GetClientRect(msg
.msg
.hwnd
, &rect
);
2595 height
= rect
.bottom
- rect
.top
+ 1;
2596 width
= rect
.right
- rect
.left
+ 1;
2598 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2599 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2601 /* Even if the number of character rows and columns has
2602 not changed, the font size may have changed, so we need
2603 to check the pixel dimensions as well. */
2605 if (columns
!= f
->width
2606 || rows
!= f
->height
2607 || width
!= f
->output_data
.win32
->pixel_width
2608 || height
!= f
->output_data
.win32
->pixel_height
)
2610 /* I had set this to 0, 0 - I am not sure why?? */
2612 change_frame_size (f
, rows
, columns
, 0, 1);
2613 SET_FRAME_GARBAGED (f
);
2615 f
->output_data
.win32
->pixel_width
= width
;
2616 f
->output_data
.win32
->pixel_height
= height
;
2617 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
2624 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2626 if (msg
.msg
.message
== WM_SETFOCUS
)
2628 x_new_focus_frame (dpyinfo
, f
);
2630 else if (f
== dpyinfo
->win32_focus_frame
)
2631 x_new_focus_frame (dpyinfo
, 0);
2635 switch (msg
.msg
.wParam
& 0xfff0) /* Lower 4 bits used by Windows. */
2638 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2645 bufp
->kind
= delete_window_event
;
2646 XSETFRAME (bufp
->frame_or_window
, f
);
2654 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2658 f
->async_visible
= 1;
2659 f
->async_iconified
= 1;
2661 bufp
->kind
= iconify_event
;
2662 XSETFRAME (bufp
->frame_or_window
, f
);
2671 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2675 f
->async_visible
= 1;
2676 f
->async_iconified
= 0;
2678 /* wait_reading_process_input will notice this and update
2679 the frame's display structures. */
2680 SET_FRAME_GARBAGED (f
);
2684 bufp
->kind
= deiconify_event
;
2685 XSETFRAME (bufp
->frame_or_window
, f
);
2691 /* Force a redisplay sooner or later
2692 to update the frame titles
2693 in case this is the second frame. */
2694 record_asynch_buffer_change ();
2702 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2709 bufp
->kind
= delete_window_event
;
2710 XSETFRAME (bufp
->frame_or_window
, f
);
2718 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2722 if (msg
.msg
.lParam
== 0)
2724 /* Came from window menu */
2726 extern Lisp_Object
get_frame_menubar_event ();
2727 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2728 struct input_event buf
;
2731 XSETFRAME (frame
, f
);
2732 buf
.kind
= menu_bar_event
;
2734 /* Store initial menu bar event */
2738 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2739 kbd_buffer_store_event (&buf
);
2742 /* Enqueue the events */
2744 while (!NILP (event
))
2746 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2747 kbd_buffer_store_event (&buf
);
2748 event
= XCONS (event
)->cdr
;
2753 /* Came from popup menu */
2760 /* If the focus was just given to an autoraising frame,
2762 /* ??? This ought to be able to handle more than one such frame. */
2763 if (pending_autoraise_frame
)
2765 x_raise_frame (pending_autoraise_frame
);
2766 pending_autoraise_frame
= 0;
2773 /* Drawing the cursor. */
2776 /* Draw a hollow box cursor. Don't change the inside of the box. */
2786 hdc
= get_frame_dc (f
);
2788 hb
= CreateSolidBrush (f
->output_data
.win32
->cursor_pixel
);
2790 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2791 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2792 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.win32
->font
);
2793 rect
.bottom
= rect
.top
+ f
->output_data
.win32
->line_height
;
2795 FrameRect (hdc
, &rect
, hb
);
2798 release_frame_dc (f
, hdc
);
2801 /* Clear the cursor of frame F to background color,
2802 and mark the cursor as not shown.
2803 This is used when the text where the cursor is
2804 is about to be rewritten. */
2810 if (! FRAME_VISIBLE_P (f
)
2811 || f
->phys_cursor_x
< 0)
2814 x_display_cursor (f
, 0);
2815 f
->phys_cursor_x
= -1;
2818 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2819 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2823 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2830 CHAR_TO_PIXEL_COL (f
, column
),
2831 CHAR_TO_PIXEL_ROW (f
, row
),
2832 &glyph
, 1, highlight
, 0);
2836 x_display_bar_cursor (f
, on
)
2840 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2842 /* This is pointless on invisible frames, and dangerous on garbaged
2843 frames; in the latter case, the frame may be in the midst of
2844 changing its size, and curs_x and curs_y may be off the frame. */
2845 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2848 if (! on
&& f
->phys_cursor_x
< 0)
2851 /* If we're not updating, then we want to use the current frame's
2852 cursor position, not our local idea of where the cursor ought to be. */
2853 if (f
!= updating_frame
)
2855 curs_x
= FRAME_CURSOR_X (f
);
2856 curs_y
= FRAME_CURSOR_Y (f
);
2859 /* If there is anything wrong with the current cursor state, remove it. */
2860 if (f
->phys_cursor_x
>= 0
2862 || f
->phys_cursor_x
!= curs_x
2863 || f
->phys_cursor_y
!= curs_y
2864 || f
->output_data
.win32
->current_cursor
!= bar_cursor
))
2866 /* Erase the cursor by redrawing the character underneath it. */
2867 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2868 f
->phys_cursor_glyph
,
2869 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2870 f
->phys_cursor_x
= -1;
2873 /* If we now need a cursor in the new place or in the new form, do it so. */
2875 && (f
->phys_cursor_x
< 0
2876 || (f
->output_data
.win32
->current_cursor
!= bar_cursor
)))
2878 f
->phys_cursor_glyph
2879 = ((current_glyphs
->enable
[curs_y
]
2880 && curs_x
< current_glyphs
->used
[curs_y
])
2881 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2883 win32_fill_area (f
, NULL
, f
->output_data
.win32
->cursor_pixel
,
2884 CHAR_TO_PIXEL_COL (f
, curs_x
),
2885 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2886 max (f
->output_data
.win32
->cursor_width
, 1),
2887 f
->output_data
.win32
->line_height
);
2889 f
->phys_cursor_x
= curs_x
;
2890 f
->phys_cursor_y
= curs_y
;
2892 f
->output_data
.win32
->current_cursor
= bar_cursor
;
2897 /* Turn the displayed cursor of frame F on or off according to ON.
2898 If ON is nonzero, where to put the cursor is specified
2899 by F->cursor_x and F->cursor_y. */
2902 x_display_box_cursor (f
, on
)
2906 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2908 /* This is pointless on invisible frames, and dangerous on garbaged
2909 frames; in the latter case, the frame may be in the midst of
2910 changing its size, and curs_x and curs_y may be off the frame. */
2911 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2914 /* If cursor is off and we want it off, return quickly. */
2915 if (!on
&& f
->phys_cursor_x
< 0)
2918 /* If we're not updating, then we want to use the current frame's
2919 cursor position, not our local idea of where the cursor ought to be. */
2920 if (f
!= updating_frame
)
2922 curs_x
= FRAME_CURSOR_X (f
);
2923 curs_y
= FRAME_CURSOR_Y (f
);
2926 /* If cursor is currently being shown and we don't want it to be
2927 or it is in the wrong place,
2928 or we want a hollow box and it's not so, (pout!)
2930 if (f
->phys_cursor_x
>= 0
2932 || f
->phys_cursor_x
!= curs_x
2933 || f
->phys_cursor_y
!= curs_y
2934 || (f
->output_data
.win32
->current_cursor
!= hollow_box_cursor
2935 && (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
))))
2937 int mouse_face_here
= 0;
2938 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2940 /* If the cursor is in the mouse face area, redisplay that when
2941 we clear the cursor. */
2942 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2944 (f
->phys_cursor_y
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2945 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2946 && f
->phys_cursor_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2948 (f
->phys_cursor_y
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2949 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2950 && f
->phys_cursor_x
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2951 /* Don't redraw the cursor's spot in mouse face
2952 if it is at the end of a line (on a newline).
2953 The cursor appears there, but mouse highlighting does not. */
2954 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2955 mouse_face_here
= 1;
2957 /* If the font is not as tall as a whole line,
2958 we must explicitly clear the line's whole height. */
2959 if (FONT_HEIGHT (f
->output_data
.win32
->font
) != f
->output_data
.win32
->line_height
)
2960 win32_clear_area (f
, NULL
,
2961 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2962 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2963 FONT_WIDTH (f
->output_data
.win32
->font
),
2964 f
->output_data
.win32
->line_height
);
2965 /* Erase the cursor by redrawing the character underneath it. */
2966 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2967 f
->phys_cursor_glyph
,
2970 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2971 f
->phys_cursor_x
= -1;
2974 /* If we want to show a cursor,
2975 or we want a box cursor and it's not so,
2976 write it in the right place. */
2978 && (f
->phys_cursor_x
< 0
2979 || (f
->output_data
.win32
->current_cursor
!= filled_box_cursor
2980 && f
== FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)))
2982 f
->phys_cursor_glyph
2983 = ((current_glyphs
->enable
[curs_y
]
2984 && curs_x
< current_glyphs
->used
[curs_y
])
2985 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2987 if (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)
2990 f
->output_data
.win32
->current_cursor
= hollow_box_cursor
;
2994 x_draw_single_glyph (f
, curs_y
, curs_x
,
2995 f
->phys_cursor_glyph
, 2);
2996 f
->output_data
.win32
->current_cursor
= filled_box_cursor
;
2999 f
->phys_cursor_x
= curs_x
;
3000 f
->phys_cursor_y
= curs_y
;
3004 x_display_cursor (f
, on
)
3010 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3011 x_display_box_cursor (f
, on
);
3012 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3013 x_display_bar_cursor (f
, on
);
3015 /* Those are the only two we have implemented! */
3021 /* Changing the font of the frame. */
3023 /* Give frame F the font named FONTNAME as its default font, and
3024 return the full name of that font. FONTNAME may be a wildcard
3025 pattern; in that case, we choose some font that fits the pattern.
3026 The return value shows which font we chose. */
3029 x_new_font (f
, fontname
)
3031 register char *fontname
;
3034 int n_matching_fonts
;
3035 XFontStruct
*font_info
;
3036 char new_font_name
[101];
3038 /* Get a font which matches this name */
3042 if (!x_to_win32_font(fontname
, &lf
)
3043 || !win32_to_x_font(&lf
, new_font_name
, 100))
3049 /* See if we've already loaded a matching font. */
3050 already_loaded
= -1;
3055 for (i
= 0; i
< FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3056 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3059 fontname
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3064 /* If we have, just return it from the table. */
3065 if (already_loaded
>= 0)
3066 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3067 /* Otherwise, load the font and add it to the table. */
3073 font
= win32_load_font(FRAME_WIN32_DISPLAY_INFO (f
), fontname
);
3080 /* Do we need to create the table? */
3081 if (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
== 0)
3083 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
= 16;
3084 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3085 = (struct font_info
*) xmalloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3086 * sizeof (struct font_info
));
3088 /* Do we need to grow the table? */
3089 else if (FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
3090 >= FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
)
3092 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3093 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3094 = (struct font_info
*) xrealloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
,
3095 (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3096 * sizeof (struct font_info
)));
3099 n_fonts
= FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
;
3100 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3101 bcopy (fontname
, FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3102 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3103 FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
++;
3106 /* Compute the scroll bar width in character columns. */
3107 if (f
->scroll_bar_pixel_width
> 0)
3109 int wid
= FONT_WIDTH (f
->output_data
.win32
->font
);
3110 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3113 f
->scroll_bar_cols
= 2;
3115 /* Now make the frame display the given font. */
3116 if (FRAME_WIN32_WINDOW (f
) != 0)
3118 frame_update_line_height (f
);
3119 x_set_window_size (f
, 0, f
->width
, f
->height
);
3122 /* If we are setting a new frame's font for the first time,
3123 there are no faces yet, so this font's height is the line height. */
3124 f
->output_data
.win32
->line_height
= FONT_HEIGHT (f
->output_data
.win32
->font
);
3127 Lisp_Object lispy_name
;
3129 lispy_name
= build_string (fontname
);
3135 x_calc_absolute_position (f
)
3140 int flags
= f
->output_data
.win32
->size_hint_flags
;
3144 /* Find the position of the outside upper-left corner of
3145 the inner window, with respect to the outer window. */
3146 if (f
->output_data
.win32
->parent_desc
!= FRAME_WIN32_DISPLAY_INFO (f
)->root_window
)
3149 MapWindowPoints (FRAME_WIN32_WINDOW (f
),
3150 f
->output_data
.win32
->parent_desc
,
3157 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3160 AdjustWindowRect(&rt
, f
->output_data
.win32
->dwStyle
,
3161 FRAME_EXTERNAL_MENU_BAR (f
));
3164 pt
.x
+= (rt
.right
- rt
.left
);
3165 pt
.y
+= (rt
.bottom
- rt
.top
);
3168 /* Treat negative positions as relative to the leftmost bottommost
3169 position that fits on the screen. */
3170 if (flags
& XNegative
)
3171 f
->output_data
.win32
->left_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->width
3172 - 2 * f
->output_data
.win32
->border_width
- pt
.x
3174 + f
->output_data
.win32
->left_pos
);
3176 if (flags
& YNegative
)
3177 f
->output_data
.win32
->top_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->height
3178 - 2 * f
->output_data
.win32
->border_width
- pt
.y
3180 + f
->output_data
.win32
->top_pos
);
3181 /* The left_pos and top_pos
3182 are now relative to the top and left screen edges,
3183 so the flags should correspond. */
3184 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3187 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3188 to really change the position, and 0 when calling from
3189 x_make_frame_visible (in that case, XOFF and YOFF are the current
3190 position values). It is -1 when calling from x_set_frame_parameters,
3191 which means, do adjust for borders but don't change the gravity. */
3193 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3195 register int xoff
, yoff
;
3198 int modified_top
, modified_left
;
3200 if (change_gravity
> 0)
3202 f
->output_data
.win32
->top_pos
= yoff
;
3203 f
->output_data
.win32
->left_pos
= xoff
;
3204 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3206 f
->output_data
.win32
->size_hint_flags
|= XNegative
;
3208 f
->output_data
.win32
->size_hint_flags
|= YNegative
;
3209 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3211 x_calc_absolute_position (f
);
3214 x_wm_set_size_hint (f
, (long) 0, 0);
3216 /* It is a mystery why we need to add the border_width here
3217 when the frame is already visible, but experiment says we do. */
3218 modified_left
= f
->output_data
.win32
->left_pos
;
3219 modified_top
= f
->output_data
.win32
->top_pos
;
3220 if (change_gravity
!= 0)
3222 modified_left
+= f
->output_data
.win32
->border_width
;
3223 modified_top
+= f
->output_data
.win32
->border_width
;
3226 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3228 modified_left
, modified_top
,
3230 SWP_NOZORDER
| SWP_NOSIZE
);
3234 /* Call this to change the size of frame F's x-window.
3235 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3236 for this size change and subsequent size changes.
3237 Otherwise we leave the window gravity unchanged. */
3239 x_set_window_size (f
, change_gravity
, cols
, rows
)
3244 int pixelwidth
, pixelheight
;
3248 check_frame_size (f
, &rows
, &cols
);
3249 f
->output_data
.win32
->vertical_scroll_bar_extra
3250 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3252 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3253 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3254 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
3255 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3256 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3258 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3259 x_wm_set_size_hint (f
, (long) 0, 0);
3264 rect
.left
= rect
.top
= 0;
3265 rect
.right
= pixelwidth
;
3266 rect
.bottom
= pixelheight
;
3268 AdjustWindowRect(&rect
, f
->output_data
.win32
->dwStyle
,
3269 FRAME_EXTERNAL_MENU_BAR (f
));
3271 /* All windows have an extra pixel */
3273 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3276 rect
.right
- rect
.left
+ 1,
3277 rect
.bottom
- rect
.top
+ 1,
3278 SWP_NOZORDER
| SWP_NOMOVE
);
3281 /* Now, strictly speaking, we can't be sure that this is accurate,
3282 but the window manager will get around to dealing with the size
3283 change request eventually, and we'll hear how it went when the
3284 ConfigureNotify event gets here.
3286 We could just not bother storing any of this information here,
3287 and let the ConfigureNotify event set everything up, but that
3288 might be kind of confusing to the lisp code, since size changes
3289 wouldn't be reported in the frame parameters until some random
3290 point in the future when the ConfigureNotify event arrives. */
3291 change_frame_size (f
, rows
, cols
, 0, 0);
3292 PIXEL_WIDTH (f
) = pixelwidth
;
3293 PIXEL_HEIGHT (f
) = pixelheight
;
3295 /* If cursor was outside the new size, mark it as off. */
3296 if (f
->phys_cursor_y
>= rows
3297 || f
->phys_cursor_x
>= cols
)
3299 f
->phys_cursor_x
= -1;
3300 f
->phys_cursor_y
= -1;
3303 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3304 receive in the ConfigureNotify event; if we get what we asked
3305 for, then the event won't cause the screen to become garbaged, so
3306 we have to make sure to do it here. */
3307 SET_FRAME_GARBAGED (f
);
3312 /* Mouse warping. */
3315 x_set_mouse_position (f
, x
, y
)
3321 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.win32
->font
) / 2;
3322 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.win32
->line_height
/ 2;
3324 if (pix_x
< 0) pix_x
= 0;
3325 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3327 if (pix_y
< 0) pix_y
= 0;
3328 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3332 SetCursorPos (pix_x
, pix_y
);
3337 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
3340 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3346 SetCursorPos (pix_x
, pix_y
);
3351 /* focus shifting, raising and lowering. */
3353 x_focus_on_frame (f
)
3363 /* Raise frame F. */
3368 // if (f->async_visible)
3371 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3374 SWP_NOSIZE
| SWP_NOMOVE
);
3379 /* Lower frame F. */
3384 // if (f->async_visible)
3387 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3390 SWP_NOSIZE
| SWP_NOMOVE
);
3396 win32_frame_raise_lower (f
, raise
)
3406 /* Change of visibility. */
3408 /* This tries to wait until the frame is really visible.
3409 However, if the window manager asks the user where to position
3410 the frame, this will return before the user finishes doing that.
3411 The frame will not actually be visible at that time,
3412 but it will become visible later when the window manager
3413 finishes with it. */
3415 x_make_frame_visible (f
)
3420 if (! FRAME_VISIBLE_P (f
))
3422 /* We test FRAME_GARBAGED_P here to make sure we don't
3423 call x_set_offset a second time
3424 if we get to x_make_frame_visible a second time
3425 before the window gets really visible. */
3426 if (! FRAME_ICONIFIED_P (f
)
3427 && ! f
->output_data
.win32
->asked_for_visible
)
3429 x_set_offset (f
, f
->output_data
.win32
->left_pos
, f
->output_data
.win32
->top_pos
, 0);
3430 // SetForegroundWindow (FRAME_WIN32_WINDOW (f));
3433 f
->output_data
.win32
->asked_for_visible
= 1;
3435 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWNORMAL
);
3438 /* Synchronize to ensure Emacs knows the frame is visible
3439 before we do anything else. We do this loop with input not blocked
3440 so that incoming events are handled. */
3443 int count
= input_signal_count
;
3445 /* This must come after we set COUNT. */
3448 XSETFRAME (frame
, f
);
3452 /* Once we have handled input events,
3453 we should have received the MapNotify if one is coming.
3454 So if we have not got it yet, stop looping.
3455 Some window managers make their own decisions
3456 about visibility. */
3457 if (input_signal_count
!= count
)
3459 /* Machines that do polling rather than SIGIO have been observed
3460 to go into a busy-wait here. So we'll fake an alarm signal
3461 to let the handler know that there's something to be read.
3462 We used to raise a real alarm, but it seems that the handler
3463 isn't always enabled here. This is probably a bug. */
3464 if (input_polling_used ())
3466 /* It could be confusing if a real alarm arrives while processing
3467 the fake one. Turn it off and let the handler reset it. */
3469 input_poll_signal ();
3471 /* Once we have handled input events,
3472 we should have received the MapNotify if one is coming.
3473 So if we have not got it yet, stop looping.
3474 Some window managers make their own decisions
3475 about visibility. */
3476 if (input_signal_count
!= count
)
3479 FRAME_SAMPLE_VISIBILITY (f
);
3483 /* Change from mapped state to withdrawn state. */
3485 /* Make the frame visible (mapped and not iconified). */
3487 x_make_frame_invisible (f
)
3492 /* Don't keep the highlight on an invisible frame. */
3493 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3494 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3498 my_show_window (FRAME_WIN32_WINDOW (f
), SW_HIDE
);
3500 /* We can't distinguish this from iconification
3501 just by the event that we get from the server.
3502 So we can't win using the usual strategy of letting
3503 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3504 and synchronize with the server to make sure we agree. */
3506 FRAME_ICONIFIED_P (f
) = 0;
3507 f
->async_visible
= 0;
3508 f
->async_iconified
= 0;
3513 /* Change window state from mapped to iconified. */
3521 /* Don't keep the highlight on an invisible frame. */
3522 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3523 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3525 if (f
->async_iconified
)
3530 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWMINIMIZED
);
3531 /* The frame doesn't seem to be lowered automatically. */
3534 f
->async_iconified
= 1;
3539 /* Destroy the window of frame F. */
3541 x_destroy_window (f
)
3544 struct win32_display_info
*dpyinfo
= FRAME_WIN32_DISPLAY_INFO (f
);
3548 my_destroy_window (f
, FRAME_WIN32_WINDOW (f
));
3549 free_frame_menubar (f
);
3550 free_frame_faces (f
);
3552 xfree (f
->output_data
.win32
);
3553 f
->output_data
.win32
= 0;
3554 if (f
== dpyinfo
->win32_focus_frame
)
3555 dpyinfo
->win32_focus_frame
= 0;
3556 if (f
== dpyinfo
->win32_focus_event_frame
)
3557 dpyinfo
->win32_focus_event_frame
= 0;
3558 if (f
== dpyinfo
->win32_highlight_frame
)
3559 dpyinfo
->win32_highlight_frame
= 0;
3561 dpyinfo
->reference_count
--;
3563 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3565 dpyinfo
->mouse_face_beg_row
3566 = dpyinfo
->mouse_face_beg_col
= -1;
3567 dpyinfo
->mouse_face_end_row
3568 = dpyinfo
->mouse_face_end_col
= -1;
3569 dpyinfo
->mouse_face_window
= Qnil
;
3575 /* Setting window manager hints. */
3577 /* Set the normal size hints for the window manager, for frame F.
3578 FLAGS is the flags word to use--or 0 meaning preserve the flags
3579 that the window now has.
3580 If USER_POSITION is nonzero, we set the USPosition
3581 flag (this is useful when FLAGS is 0). */
3583 x_wm_set_size_hint (f
, flags
, user_position
)
3588 Window window
= FRAME_WIN32_WINDOW (f
);
3590 flexlines
= f
->height
;
3594 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.win32
->font
));
3595 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.win32
->line_height
);
3600 /* Window manager things */
3601 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3606 Window window
= FRAME_WIN32_WINDOW (f
);
3608 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3609 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3610 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3612 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3617 /* Initialization. */
3619 #ifdef USE_X_TOOLKIT
3620 static XrmOptionDescRec emacs_options
[] = {
3621 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3622 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3624 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3625 XrmoptionSepArg
, NULL
},
3626 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3628 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3629 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3630 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3631 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3632 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3633 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3634 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3636 #endif /* USE_X_TOOLKIT */
3638 static int win32_initialized
= 0;
3640 struct win32_display_info
*
3641 win32_term_init (display_name
, xrm_option
, resource_name
)
3642 Lisp_Object display_name
;
3644 char *resource_name
;
3648 struct win32_display_info
*dpyinfo
;
3653 if (!win32_initialized
)
3655 win32_initialize ();
3656 win32_initialized
= 1;
3667 argv
[argc
++] = "-xrm";
3668 argv
[argc
++] = xrm_option
;
3672 dpyinfo
= &one_win32_display_info
;
3674 /* Put this display on the chain. */
3675 dpyinfo
->next
= NULL
;
3677 /* Put it on win32_display_name_list as well, to keep them parallel. */
3678 win32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3679 win32_display_name_list
);
3680 dpyinfo
->name_list_element
= XCONS (win32_display_name_list
)->car
;
3682 dpyinfo
->win32_id_name
3683 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3684 + XSTRING (Vsystem_name
)->size
3686 sprintf (dpyinfo
->win32_id_name
, "%s@%s",
3687 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3690 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3691 resource_name
, EMACS_CLASS
);
3693 /* Put the rdb where we can find it in a way that works on
3695 dpyinfo
->xrdb
= xrdb
;
3697 hdc
= GetDC (GetDesktopWindow ());
3699 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3700 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3701 dpyinfo
->root_window
= GetDesktopWindow ();
3702 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3703 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3704 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3705 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3706 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
3707 dpyinfo
->grabbed
= 0;
3708 dpyinfo
->reference_count
= 0;
3709 dpyinfo
->n_fonts
= 0;
3710 dpyinfo
->font_table_size
= 0;
3711 dpyinfo
->bitmaps
= 0;
3712 dpyinfo
->bitmaps_size
= 0;
3713 dpyinfo
->bitmaps_last
= 0;
3714 dpyinfo
->mouse_face_mouse_frame
= 0;
3715 dpyinfo
->mouse_face_deferred_gc
= 0;
3716 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3717 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3718 dpyinfo
->mouse_face_face_id
= 0;
3719 dpyinfo
->mouse_face_window
= Qnil
;
3720 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3721 dpyinfo
->mouse_face_defer
= 0;
3722 dpyinfo
->win32_focus_frame
= 0;
3723 dpyinfo
->win32_focus_event_frame
= 0;
3724 dpyinfo
->win32_highlight_frame
= 0;
3726 ReleaseDC (GetDesktopWindow (), hdc
);
3728 /* Determine if there is a middle mouse button, to allow parse_button
3729 to decide whether right mouse events should be mouse-2 or
3731 XSETINT (Vwin32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
3733 /* initialise palette with white and black */
3736 defined_color (0, "white", &color
, 1);
3737 defined_color (0, "black", &color
, 1);
3740 #ifndef F_SETOWN_BUG
3742 #ifdef F_SETOWN_SOCK_NEG
3743 /* stdin is a socket here */
3744 fcntl (connection
, F_SETOWN
, -getpid ());
3745 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3746 fcntl (connection
, F_SETOWN
, getpid ());
3747 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3748 #endif /* ! defined (F_SETOWN) */
3749 #endif /* F_SETOWN_BUG */
3752 if (interrupt_input
)
3753 init_sigio (connection
);
3754 #endif /* ! defined (SIGIO) */
3761 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3764 x_delete_display (dpyinfo
)
3765 struct win32_display_info
*dpyinfo
;
3767 /* Discard this display from win32_display_name_list and win32_display_list.
3768 We can't use Fdelq because that can quit. */
3769 if (! NILP (win32_display_name_list
)
3770 && EQ (XCONS (win32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3771 win32_display_name_list
= XCONS (win32_display_name_list
)->cdr
;
3776 tail
= win32_display_name_list
;
3777 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3779 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3780 dpyinfo
->name_list_element
))
3782 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3785 tail
= XCONS (tail
)->cdr
;
3789 /* free palette table */
3791 struct win32_palette_entry
* plist
;
3793 plist
= dpyinfo
->color_list
;
3796 struct win32_palette_entry
* pentry
= plist
;
3797 plist
= plist
->next
;
3800 dpyinfo
->color_list
= NULL
;
3801 if (dpyinfo
->palette
)
3802 DeleteObject(dpyinfo
->palette
);
3804 xfree (dpyinfo
->font_table
);
3805 xfree (dpyinfo
->win32_id_name
);
3808 /* Set up use of Win32. */
3810 DWORD
win_msg_worker ();
3814 clear_frame_hook
= win32_clear_frame
;
3815 clear_end_of_line_hook
= win32_clear_end_of_line
;
3816 ins_del_lines_hook
= win32_ins_del_lines
;
3817 change_line_highlight_hook
= win32_change_line_highlight
;
3818 insert_glyphs_hook
= win32_insert_glyphs
;
3819 write_glyphs_hook
= win32_write_glyphs
;
3820 delete_glyphs_hook
= win32_delete_glyphs
;
3821 ring_bell_hook
= win32_ring_bell
;
3822 reset_terminal_modes_hook
= win32_reset_terminal_modes
;
3823 set_terminal_modes_hook
= win32_set_terminal_modes
;
3824 update_begin_hook
= win32_update_begin
;
3825 update_end_hook
= win32_update_end
;
3826 set_terminal_window_hook
= win32_set_terminal_window
;
3827 read_socket_hook
= w32_read_socket
;
3828 frame_up_to_date_hook
= win32_frame_up_to_date
;
3829 cursor_to_hook
= win32_cursor_to
;
3830 reassert_line_highlight_hook
= win32_reassert_line_highlight
;
3831 mouse_position_hook
= win32_mouse_position
;
3832 frame_rehighlight_hook
= win32_frame_rehighlight
;
3833 frame_raise_lower_hook
= win32_frame_raise_lower
;
3834 set_vertical_scroll_bar_hook
= win32_set_vertical_scroll_bar
;
3835 condemn_scroll_bars_hook
= win32_condemn_scroll_bars
;
3836 redeem_scroll_bar_hook
= win32_redeem_scroll_bar
;
3837 judge_scroll_bars_hook
= win32_judge_scroll_bars
;
3839 scroll_region_ok
= 1; /* we'll scroll partial frames */
3840 char_ins_del_ok
= 0; /* just as fast to write the line */
3841 line_ins_del_ok
= 1; /* we'll just blt 'em */
3842 fast_clear_end_of_line
= 1; /* X does this well */
3843 memory_below_frame
= 0; /* we don't remember what scrolls
3847 /* Try to use interrupt input; if we can't, then start polling. */
3848 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3850 /* Create the window thread - it will terminate itself or when the app terminates */
3854 dwMainThreadId
= GetCurrentThreadId ();
3855 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3856 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3858 /* Wait for thread to start */
3863 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3865 hWinThread
= CreateThread (NULL
, 0,
3866 (LPTHREAD_START_ROUTINE
) win_msg_worker
,
3867 0, 0, &dwWinThreadId
);
3869 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3872 /* It is desirable that mainThread should have the same notion of
3873 focus window and active window as winThread. Unfortunately, the
3874 following call to AttachThreadInput, which should do precisely what
3875 we need, causes major problems when Emacs is linked as a console
3876 program. Unfortunately, we have good reasons for doing that, so
3877 instead we need to send messages to winThread to make some API
3878 calls for us (ones that affect, or depend on, the active/focus
3880 #ifdef ATTACH_THREADS
3881 AttachThreadInput (dwMainThreadId
, dwWinThreadId
, TRUE
);
3886 syms_of_win32term ()
3888 staticpro (&win32_display_name_list
);
3889 win32_display_name_list
= Qnil
;
3891 staticpro (&last_mouse_scroll_bar
);
3892 last_mouse_scroll_bar
= Qnil
;
3894 staticpro (&Qvendor_specific_keysyms
);
3895 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
3897 DEFVAR_INT ("win32-num-mouse-buttons",
3898 &Vwin32_num_mouse_buttons
,
3899 "Number of physical mouse buttons.");
3900 Vwin32_num_mouse_buttons
= Qnil
;
3902 DEFVAR_LISP ("win32-swap-mouse-buttons",
3903 &Vwin32_swap_mouse_buttons
,
3904 "Swap the mapping of middle and right mouse buttons.\n\
3905 When nil, middle button is mouse-2 and right button is mouse-3.");
3906 Vwin32_swap_mouse_buttons
= Qnil
;