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
)
2399 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2403 if (f
->async_visible
== 0)
2405 f
->async_visible
= 1;
2406 f
->async_iconified
= 0;
2407 SET_FRAME_GARBAGED (f
);
2411 /* Erase background again for safety. */
2412 win32_clear_rect (f
, NULL
, &msg
.rect
);
2416 msg
.rect
.right
-msg
.rect
.left
+1,
2417 msg
.rect
.bottom
-msg
.rect
.top
+1);
2424 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2426 if (f
&& !f
->iconified
)
2428 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2430 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2431 bufp
->kind
= non_ascii_keystroke
;
2432 bufp
->code
= msg
.msg
.wParam
;
2433 bufp
->modifiers
= win32_kbd_mods_to_emacs (msg
.dwModifiers
);
2434 XSETFRAME (bufp
->frame_or_window
, f
);
2435 bufp
->timestamp
= msg
.msg
.time
;
2443 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2445 if (f
&& !f
->iconified
)
2450 KEY_EVENT_RECORD key
, *keyp
= &key
;
2452 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2455 convert_to_key_event (&msg
, keyp
);
2456 add
= key_event (keyp
, bufp
);
2457 XSETFRAME (bufp
->frame_or_window
, f
);
2460 /* The key pressed generated two characters, most likely
2461 an accent character and a key that could not be
2462 combined with it. Prepend the message on the queue
2463 again to process the second character (which is
2464 being held internally in key_event), and process
2465 the first character now. */
2470 /* Throw dead keys away. However, be sure not to
2471 throw away the dead key if it was produced using
2472 AltGr and there is a valid AltGr scan code for
2474 if (is_dead_key (msg
.msg
.wParam
)
2475 && !((VkKeyScan ((char) bufp
->code
) & 0xff00) == 0x600))
2489 if (dpyinfo
->grabbed
&& last_mouse_frame
2490 && FRAME_LIVE_P (last_mouse_frame
))
2491 f
= last_mouse_frame
;
2493 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2496 note_mouse_movement (f
, &msg
.msg
);
2498 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
2501 case WM_LBUTTONDOWN
:
2503 case WM_MBUTTONDOWN
:
2505 case WM_RBUTTONDOWN
:
2511 if (dpyinfo
->grabbed
&& last_mouse_frame
2512 && FRAME_LIVE_P (last_mouse_frame
))
2513 f
= last_mouse_frame
;
2515 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2519 if ((!dpyinfo
->win32_focus_frame
|| f
== dpyinfo
->win32_focus_frame
)
2522 construct_mouse_click (bufp
, &msg
, f
);
2529 parse_button (msg
.msg
.message
, &button
, &up
);
2533 dpyinfo
->grabbed
&= ~ (1 << button
);
2537 dpyinfo
->grabbed
|= (1 << button
);
2538 last_mouse_frame
= f
;
2545 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2547 if (bar
&& numchars
>= 1)
2549 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2560 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2562 if (f
&& !f
->async_iconified
)
2564 f
->output_data
.win32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2565 f
->output_data
.win32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2570 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2572 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2580 GetClientRect(msg
.msg
.hwnd
, &rect
);
2582 height
= rect
.bottom
- rect
.top
+ 1;
2583 width
= rect
.right
- rect
.left
+ 1;
2585 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2586 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2588 /* Even if the number of character rows and columns has
2589 not changed, the font size may have changed, so we need
2590 to check the pixel dimensions as well. */
2592 if (columns
!= f
->width
2593 || rows
!= f
->height
2594 || width
!= f
->output_data
.win32
->pixel_width
2595 || height
!= f
->output_data
.win32
->pixel_height
)
2597 /* I had set this to 0, 0 - I am not sure why?? */
2599 change_frame_size (f
, rows
, columns
, 0, 1);
2600 SET_FRAME_GARBAGED (f
);
2602 f
->output_data
.win32
->pixel_width
= width
;
2603 f
->output_data
.win32
->pixel_height
= height
;
2604 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
2611 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2613 if (msg
.msg
.message
== WM_SETFOCUS
)
2615 x_new_focus_frame (dpyinfo
, f
);
2617 else if (f
== dpyinfo
->win32_focus_frame
)
2618 x_new_focus_frame (dpyinfo
, 0);
2622 switch (msg
.msg
.wParam
& 0xfff0) /* Lower 4 bits used by Windows. */
2625 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2632 bufp
->kind
= delete_window_event
;
2633 XSETFRAME (bufp
->frame_or_window
, f
);
2641 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2645 f
->async_visible
= 1;
2646 f
->async_iconified
= 1;
2648 bufp
->kind
= iconify_event
;
2649 XSETFRAME (bufp
->frame_or_window
, f
);
2658 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2662 f
->async_visible
= 1;
2663 f
->async_iconified
= 0;
2665 /* wait_reading_process_input will notice this and update
2666 the frame's display structures. */
2667 SET_FRAME_GARBAGED (f
);
2671 bufp
->kind
= deiconify_event
;
2672 XSETFRAME (bufp
->frame_or_window
, f
);
2678 /* Force a redisplay sooner or later
2679 to update the frame titles
2680 in case this is the second frame. */
2681 record_asynch_buffer_change ();
2689 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2696 bufp
->kind
= delete_window_event
;
2697 XSETFRAME (bufp
->frame_or_window
, f
);
2705 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2709 if (msg
.msg
.lParam
== 0)
2711 /* Came from window menu */
2713 extern Lisp_Object
get_frame_menubar_event ();
2714 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2715 struct input_event buf
;
2718 XSETFRAME (frame
, f
);
2719 buf
.kind
= menu_bar_event
;
2721 /* Store initial menu bar event */
2725 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2726 kbd_buffer_store_event (&buf
);
2729 /* Enqueue the events */
2731 while (!NILP (event
))
2733 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2734 kbd_buffer_store_event (&buf
);
2735 event
= XCONS (event
)->cdr
;
2740 /* Came from popup menu */
2747 /* If the focus was just given to an autoraising frame,
2749 /* ??? This ought to be able to handle more than one such frame. */
2750 if (pending_autoraise_frame
)
2752 x_raise_frame (pending_autoraise_frame
);
2753 pending_autoraise_frame
= 0;
2760 /* Drawing the cursor. */
2763 /* Draw a hollow box cursor. Don't change the inside of the box. */
2773 hdc
= get_frame_dc (f
);
2775 hb
= CreateSolidBrush (f
->output_data
.win32
->cursor_pixel
);
2777 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2778 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2779 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.win32
->font
);
2780 rect
.bottom
= rect
.top
+ f
->output_data
.win32
->line_height
;
2782 FrameRect (hdc
, &rect
, hb
);
2785 release_frame_dc (f
, hdc
);
2788 /* Clear the cursor of frame F to background color,
2789 and mark the cursor as not shown.
2790 This is used when the text where the cursor is
2791 is about to be rewritten. */
2797 if (! FRAME_VISIBLE_P (f
)
2798 || f
->phys_cursor_x
< 0)
2801 x_display_cursor (f
, 0);
2802 f
->phys_cursor_x
= -1;
2805 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2806 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2810 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2817 CHAR_TO_PIXEL_COL (f
, column
),
2818 CHAR_TO_PIXEL_ROW (f
, row
),
2819 &glyph
, 1, highlight
, 0);
2823 x_display_bar_cursor (f
, on
)
2827 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2829 /* This is pointless on invisible frames, and dangerous on garbaged
2830 frames; in the latter case, the frame may be in the midst of
2831 changing its size, and curs_x and curs_y may be off the frame. */
2832 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2835 if (! on
&& f
->phys_cursor_x
< 0)
2838 /* If we're not updating, then we want to use the current frame's
2839 cursor position, not our local idea of where the cursor ought to be. */
2840 if (f
!= updating_frame
)
2842 curs_x
= FRAME_CURSOR_X (f
);
2843 curs_y
= FRAME_CURSOR_Y (f
);
2846 /* If there is anything wrong with the current cursor state, remove it. */
2847 if (f
->phys_cursor_x
>= 0
2849 || f
->phys_cursor_x
!= curs_x
2850 || f
->phys_cursor_y
!= curs_y
2851 || f
->output_data
.win32
->current_cursor
!= bar_cursor
))
2853 /* Erase the cursor by redrawing the character underneath it. */
2854 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2855 f
->phys_cursor_glyph
,
2856 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2857 f
->phys_cursor_x
= -1;
2860 /* If we now need a cursor in the new place or in the new form, do it so. */
2862 && (f
->phys_cursor_x
< 0
2863 || (f
->output_data
.win32
->current_cursor
!= bar_cursor
)))
2865 f
->phys_cursor_glyph
2866 = ((current_glyphs
->enable
[curs_y
]
2867 && curs_x
< current_glyphs
->used
[curs_y
])
2868 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2870 win32_fill_area (f
, NULL
, f
->output_data
.win32
->cursor_pixel
,
2871 CHAR_TO_PIXEL_COL (f
, curs_x
),
2872 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2873 max (f
->output_data
.win32
->cursor_width
, 1),
2874 f
->output_data
.win32
->line_height
);
2876 f
->phys_cursor_x
= curs_x
;
2877 f
->phys_cursor_y
= curs_y
;
2879 f
->output_data
.win32
->current_cursor
= bar_cursor
;
2884 /* Turn the displayed cursor of frame F on or off according to ON.
2885 If ON is nonzero, where to put the cursor is specified
2886 by F->cursor_x and F->cursor_y. */
2889 x_display_box_cursor (f
, on
)
2893 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2895 /* This is pointless on invisible frames, and dangerous on garbaged
2896 frames; in the latter case, the frame may be in the midst of
2897 changing its size, and curs_x and curs_y may be off the frame. */
2898 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2901 /* If cursor is off and we want it off, return quickly. */
2902 if (!on
&& f
->phys_cursor_x
< 0)
2905 /* If we're not updating, then we want to use the current frame's
2906 cursor position, not our local idea of where the cursor ought to be. */
2907 if (f
!= updating_frame
)
2909 curs_x
= FRAME_CURSOR_X (f
);
2910 curs_y
= FRAME_CURSOR_Y (f
);
2913 /* If cursor is currently being shown and we don't want it to be
2914 or it is in the wrong place,
2915 or we want a hollow box and it's not so, (pout!)
2917 if (f
->phys_cursor_x
>= 0
2919 || f
->phys_cursor_x
!= curs_x
2920 || f
->phys_cursor_y
!= curs_y
2921 || (f
->output_data
.win32
->current_cursor
!= hollow_box_cursor
2922 && (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
))))
2924 int mouse_face_here
= 0;
2925 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2927 /* If the cursor is in the mouse face area, redisplay that when
2928 we clear the cursor. */
2929 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2931 (f
->phys_cursor_y
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2932 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2933 && f
->phys_cursor_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2935 (f
->phys_cursor_y
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2936 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2937 && f
->phys_cursor_x
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2938 /* Don't redraw the cursor's spot in mouse face
2939 if it is at the end of a line (on a newline).
2940 The cursor appears there, but mouse highlighting does not. */
2941 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2942 mouse_face_here
= 1;
2944 /* If the font is not as tall as a whole line,
2945 we must explicitly clear the line's whole height. */
2946 if (FONT_HEIGHT (f
->output_data
.win32
->font
) != f
->output_data
.win32
->line_height
)
2947 win32_clear_area (f
, NULL
,
2948 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2949 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2950 FONT_WIDTH (f
->output_data
.win32
->font
),
2951 f
->output_data
.win32
->line_height
);
2952 /* Erase the cursor by redrawing the character underneath it. */
2953 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2954 f
->phys_cursor_glyph
,
2957 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2958 f
->phys_cursor_x
= -1;
2961 /* If we want to show a cursor,
2962 or we want a box cursor and it's not so,
2963 write it in the right place. */
2965 && (f
->phys_cursor_x
< 0
2966 || (f
->output_data
.win32
->current_cursor
!= filled_box_cursor
2967 && f
== FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)))
2969 f
->phys_cursor_glyph
2970 = ((current_glyphs
->enable
[curs_y
]
2971 && curs_x
< current_glyphs
->used
[curs_y
])
2972 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2974 if (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)
2977 f
->output_data
.win32
->current_cursor
= hollow_box_cursor
;
2981 x_draw_single_glyph (f
, curs_y
, curs_x
,
2982 f
->phys_cursor_glyph
, 2);
2983 f
->output_data
.win32
->current_cursor
= filled_box_cursor
;
2986 f
->phys_cursor_x
= curs_x
;
2987 f
->phys_cursor_y
= curs_y
;
2991 x_display_cursor (f
, on
)
2997 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
2998 x_display_box_cursor (f
, on
);
2999 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3000 x_display_bar_cursor (f
, on
);
3002 /* Those are the only two we have implemented! */
3008 /* Changing the font of the frame. */
3010 /* Give frame F the font named FONTNAME as its default font, and
3011 return the full name of that font. FONTNAME may be a wildcard
3012 pattern; in that case, we choose some font that fits the pattern.
3013 The return value shows which font we chose. */
3016 x_new_font (f
, fontname
)
3018 register char *fontname
;
3021 int n_matching_fonts
;
3022 XFontStruct
*font_info
;
3023 char new_font_name
[101];
3025 /* Get a font which matches this name */
3029 if (!x_to_win32_font(fontname
, &lf
)
3030 || !win32_to_x_font(&lf
, new_font_name
, 100))
3036 /* See if we've already loaded a matching font. */
3037 already_loaded
= -1;
3042 for (i
= 0; i
< FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3043 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3046 fontname
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3051 /* If we have, just return it from the table. */
3052 if (already_loaded
>= 0)
3053 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3054 /* Otherwise, load the font and add it to the table. */
3060 font
= win32_load_font(FRAME_WIN32_DISPLAY_INFO (f
), fontname
);
3067 /* Do we need to create the table? */
3068 if (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
== 0)
3070 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
= 16;
3071 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3072 = (struct font_info
*) xmalloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3073 * sizeof (struct font_info
));
3075 /* Do we need to grow the table? */
3076 else if (FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
3077 >= FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
)
3079 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3080 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3081 = (struct font_info
*) xrealloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
,
3082 (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3083 * sizeof (struct font_info
)));
3086 n_fonts
= FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
;
3087 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3088 bcopy (fontname
, FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3089 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3090 FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
++;
3093 /* Compute the scroll bar width in character columns. */
3094 if (f
->scroll_bar_pixel_width
> 0)
3096 int wid
= FONT_WIDTH (f
->output_data
.win32
->font
);
3097 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3100 f
->scroll_bar_cols
= 2;
3102 /* Now make the frame display the given font. */
3103 if (FRAME_WIN32_WINDOW (f
) != 0)
3105 frame_update_line_height (f
);
3106 x_set_window_size (f
, 0, f
->width
, f
->height
);
3109 /* If we are setting a new frame's font for the first time,
3110 there are no faces yet, so this font's height is the line height. */
3111 f
->output_data
.win32
->line_height
= FONT_HEIGHT (f
->output_data
.win32
->font
);
3114 Lisp_Object lispy_name
;
3116 lispy_name
= build_string (fontname
);
3122 x_calc_absolute_position (f
)
3127 int flags
= f
->output_data
.win32
->size_hint_flags
;
3131 /* Find the position of the outside upper-left corner of
3132 the inner window, with respect to the outer window. */
3133 if (f
->output_data
.win32
->parent_desc
!= FRAME_WIN32_DISPLAY_INFO (f
)->root_window
)
3136 MapWindowPoints (FRAME_WIN32_WINDOW (f
),
3137 f
->output_data
.win32
->parent_desc
,
3144 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3147 AdjustWindowRect(&rt
, f
->output_data
.win32
->dwStyle
,
3148 FRAME_EXTERNAL_MENU_BAR (f
));
3151 pt
.x
+= (rt
.right
- rt
.left
);
3152 pt
.y
+= (rt
.bottom
- rt
.top
);
3155 /* Treat negative positions as relative to the leftmost bottommost
3156 position that fits on the screen. */
3157 if (flags
& XNegative
)
3158 f
->output_data
.win32
->left_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->width
3159 - 2 * f
->output_data
.win32
->border_width
- pt
.x
3161 + f
->output_data
.win32
->left_pos
);
3163 if (flags
& YNegative
)
3164 f
->output_data
.win32
->top_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->height
3165 - 2 * f
->output_data
.win32
->border_width
- pt
.y
3167 + f
->output_data
.win32
->top_pos
);
3168 /* The left_pos and top_pos
3169 are now relative to the top and left screen edges,
3170 so the flags should correspond. */
3171 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3174 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3175 to really change the position, and 0 when calling from
3176 x_make_frame_visible (in that case, XOFF and YOFF are the current
3177 position values). It is -1 when calling from x_set_frame_parameters,
3178 which means, do adjust for borders but don't change the gravity. */
3180 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3182 register int xoff
, yoff
;
3185 int modified_top
, modified_left
;
3187 if (change_gravity
> 0)
3189 f
->output_data
.win32
->top_pos
= yoff
;
3190 f
->output_data
.win32
->left_pos
= xoff
;
3191 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3193 f
->output_data
.win32
->size_hint_flags
|= XNegative
;
3195 f
->output_data
.win32
->size_hint_flags
|= YNegative
;
3196 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3198 x_calc_absolute_position (f
);
3201 x_wm_set_size_hint (f
, (long) 0, 0);
3203 /* It is a mystery why we need to add the border_width here
3204 when the frame is already visible, but experiment says we do. */
3205 modified_left
= f
->output_data
.win32
->left_pos
;
3206 modified_top
= f
->output_data
.win32
->top_pos
;
3207 if (change_gravity
!= 0)
3209 modified_left
+= f
->output_data
.win32
->border_width
;
3210 modified_top
+= f
->output_data
.win32
->border_width
;
3213 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3215 modified_left
, modified_top
,
3217 SWP_NOZORDER
| SWP_NOSIZE
);
3221 /* Call this to change the size of frame F's x-window.
3222 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3223 for this size change and subsequent size changes.
3224 Otherwise we leave the window gravity unchanged. */
3226 x_set_window_size (f
, change_gravity
, cols
, rows
)
3231 int pixelwidth
, pixelheight
;
3235 check_frame_size (f
, &rows
, &cols
);
3236 f
->output_data
.win32
->vertical_scroll_bar_extra
3237 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3239 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3240 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3241 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
3242 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3243 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3245 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3246 x_wm_set_size_hint (f
, (long) 0, 0);
3251 rect
.left
= rect
.top
= 0;
3252 rect
.right
= pixelwidth
;
3253 rect
.bottom
= pixelheight
;
3255 AdjustWindowRect(&rect
, f
->output_data
.win32
->dwStyle
,
3256 FRAME_EXTERNAL_MENU_BAR (f
));
3258 /* All windows have an extra pixel */
3260 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3263 rect
.right
- rect
.left
+ 1,
3264 rect
.bottom
- rect
.top
+ 1,
3265 SWP_NOZORDER
| SWP_NOMOVE
);
3268 /* Now, strictly speaking, we can't be sure that this is accurate,
3269 but the window manager will get around to dealing with the size
3270 change request eventually, and we'll hear how it went when the
3271 ConfigureNotify event gets here.
3273 We could just not bother storing any of this information here,
3274 and let the ConfigureNotify event set everything up, but that
3275 might be kind of confusing to the lisp code, since size changes
3276 wouldn't be reported in the frame parameters until some random
3277 point in the future when the ConfigureNotify event arrives. */
3278 change_frame_size (f
, rows
, cols
, 0, 0);
3279 PIXEL_WIDTH (f
) = pixelwidth
;
3280 PIXEL_HEIGHT (f
) = pixelheight
;
3282 /* If cursor was outside the new size, mark it as off. */
3283 if (f
->phys_cursor_y
>= rows
3284 || f
->phys_cursor_x
>= cols
)
3286 f
->phys_cursor_x
= -1;
3287 f
->phys_cursor_y
= -1;
3290 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3291 receive in the ConfigureNotify event; if we get what we asked
3292 for, then the event won't cause the screen to become garbaged, so
3293 we have to make sure to do it here. */
3294 SET_FRAME_GARBAGED (f
);
3299 /* Mouse warping. */
3302 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3308 pix_x
+= f
->output_data
.win32
->left_pos
;
3309 pix_y
+= f
->output_data
.win32
->top_pos
;
3311 SetCursorPos (pix_x
, pix_y
);
3317 x_set_mouse_position (f
, x
, y
)
3323 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.win32
->font
) / 2;
3324 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.win32
->line_height
/ 2;
3326 if (pix_x
< 0) pix_x
= 0;
3327 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3329 if (pix_y
< 0) pix_y
= 0;
3330 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3332 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3335 /* focus shifting, raising and lowering. */
3337 x_focus_on_frame (f
)
3347 /* Raise frame F. */
3352 // if (f->async_visible)
3355 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3358 SWP_NOSIZE
| SWP_NOMOVE
);
3363 /* Lower frame F. */
3368 // if (f->async_visible)
3371 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3374 SWP_NOSIZE
| SWP_NOMOVE
);
3380 win32_frame_raise_lower (f
, raise
)
3390 /* Change of visibility. */
3392 /* This tries to wait until the frame is really visible.
3393 However, if the window manager asks the user where to position
3394 the frame, this will return before the user finishes doing that.
3395 The frame will not actually be visible at that time,
3396 but it will become visible later when the window manager
3397 finishes with it. */
3399 x_make_frame_visible (f
)
3404 if (! FRAME_VISIBLE_P (f
))
3406 /* We test FRAME_GARBAGED_P here to make sure we don't
3407 call x_set_offset a second time
3408 if we get to x_make_frame_visible a second time
3409 before the window gets really visible. */
3410 if (! FRAME_ICONIFIED_P (f
)
3411 && ! f
->output_data
.win32
->asked_for_visible
)
3413 x_set_offset (f
, f
->output_data
.win32
->left_pos
, f
->output_data
.win32
->top_pos
, 0);
3414 // SetForegroundWindow (FRAME_WIN32_WINDOW (f));
3417 f
->output_data
.win32
->asked_for_visible
= 1;
3419 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWNORMAL
);
3422 /* Synchronize to ensure Emacs knows the frame is visible
3423 before we do anything else. We do this loop with input not blocked
3424 so that incoming events are handled. */
3427 int count
= input_signal_count
;
3429 /* This must come after we set COUNT. */
3432 XSETFRAME (frame
, f
);
3436 /* Once we have handled input events,
3437 we should have received the MapNotify if one is coming.
3438 So if we have not got it yet, stop looping.
3439 Some window managers make their own decisions
3440 about visibility. */
3441 if (input_signal_count
!= count
)
3443 /* Machines that do polling rather than SIGIO have been observed
3444 to go into a busy-wait here. So we'll fake an alarm signal
3445 to let the handler know that there's something to be read.
3446 We used to raise a real alarm, but it seems that the handler
3447 isn't always enabled here. This is probably a bug. */
3448 if (input_polling_used ())
3450 /* It could be confusing if a real alarm arrives while processing
3451 the fake one. Turn it off and let the handler reset it. */
3453 input_poll_signal ();
3455 /* Once we have handled input events,
3456 we should have received the MapNotify if one is coming.
3457 So if we have not got it yet, stop looping.
3458 Some window managers make their own decisions
3459 about visibility. */
3460 if (input_signal_count
!= count
)
3463 FRAME_SAMPLE_VISIBILITY (f
);
3467 /* Change from mapped state to withdrawn state. */
3469 /* Make the frame visible (mapped and not iconified). */
3471 x_make_frame_invisible (f
)
3476 /* Don't keep the highlight on an invisible frame. */
3477 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3478 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3482 my_show_window (FRAME_WIN32_WINDOW (f
), SW_HIDE
);
3484 /* We can't distinguish this from iconification
3485 just by the event that we get from the server.
3486 So we can't win using the usual strategy of letting
3487 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3488 and synchronize with the server to make sure we agree. */
3490 FRAME_ICONIFIED_P (f
) = 0;
3491 f
->async_visible
= 0;
3492 f
->async_iconified
= 0;
3497 /* Change window state from mapped to iconified. */
3505 /* Don't keep the highlight on an invisible frame. */
3506 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3507 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3509 if (f
->async_iconified
)
3514 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWMINIMIZED
);
3515 /* The frame doesn't seem to be lowered automatically. */
3518 f
->async_iconified
= 1;
3523 /* Destroy the window of frame F. */
3525 x_destroy_window (f
)
3528 struct win32_display_info
*dpyinfo
= FRAME_WIN32_DISPLAY_INFO (f
);
3532 my_destroy_window (f
, FRAME_WIN32_WINDOW (f
));
3533 free_frame_menubar (f
);
3534 free_frame_faces (f
);
3536 xfree (f
->output_data
.win32
);
3537 f
->output_data
.win32
= 0;
3538 if (f
== dpyinfo
->win32_focus_frame
)
3539 dpyinfo
->win32_focus_frame
= 0;
3540 if (f
== dpyinfo
->win32_focus_event_frame
)
3541 dpyinfo
->win32_focus_event_frame
= 0;
3542 if (f
== dpyinfo
->win32_highlight_frame
)
3543 dpyinfo
->win32_highlight_frame
= 0;
3545 dpyinfo
->reference_count
--;
3547 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3549 dpyinfo
->mouse_face_beg_row
3550 = dpyinfo
->mouse_face_beg_col
= -1;
3551 dpyinfo
->mouse_face_end_row
3552 = dpyinfo
->mouse_face_end_col
= -1;
3553 dpyinfo
->mouse_face_window
= Qnil
;
3559 /* Setting window manager hints. */
3561 /* Set the normal size hints for the window manager, for frame F.
3562 FLAGS is the flags word to use--or 0 meaning preserve the flags
3563 that the window now has.
3564 If USER_POSITION is nonzero, we set the USPosition
3565 flag (this is useful when FLAGS is 0). */
3567 x_wm_set_size_hint (f
, flags
, user_position
)
3572 Window window
= FRAME_WIN32_WINDOW (f
);
3574 flexlines
= f
->height
;
3578 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.win32
->font
));
3579 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.win32
->line_height
);
3584 /* Window manager things */
3585 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3590 Window window
= FRAME_WIN32_WINDOW (f
);
3592 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3593 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3594 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3596 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3601 /* Initialization. */
3603 #ifdef USE_X_TOOLKIT
3604 static XrmOptionDescRec emacs_options
[] = {
3605 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3606 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3608 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3609 XrmoptionSepArg
, NULL
},
3610 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3612 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3613 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3614 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3615 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3616 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3617 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3618 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3620 #endif /* USE_X_TOOLKIT */
3622 static int win32_initialized
= 0;
3624 struct win32_display_info
*
3625 win32_term_init (display_name
, xrm_option
, resource_name
)
3626 Lisp_Object display_name
;
3628 char *resource_name
;
3632 struct win32_display_info
*dpyinfo
;
3637 if (!win32_initialized
)
3639 win32_initialize ();
3640 win32_initialized
= 1;
3651 argv
[argc
++] = "-xrm";
3652 argv
[argc
++] = xrm_option
;
3656 dpyinfo
= &one_win32_display_info
;
3658 /* Put this display on the chain. */
3659 dpyinfo
->next
= NULL
;
3661 /* Put it on win32_display_name_list as well, to keep them parallel. */
3662 win32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3663 win32_display_name_list
);
3664 dpyinfo
->name_list_element
= XCONS (win32_display_name_list
)->car
;
3666 dpyinfo
->win32_id_name
3667 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3668 + XSTRING (Vsystem_name
)->size
3670 sprintf (dpyinfo
->win32_id_name
, "%s@%s",
3671 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3674 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3675 resource_name
, EMACS_CLASS
);
3677 /* Put the rdb where we can find it in a way that works on
3679 dpyinfo
->xrdb
= xrdb
;
3681 hdc
= GetDC (GetDesktopWindow ());
3683 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3684 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3685 dpyinfo
->root_window
= GetDesktopWindow ();
3686 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3687 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3688 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3689 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3690 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
3691 dpyinfo
->grabbed
= 0;
3692 dpyinfo
->reference_count
= 0;
3693 dpyinfo
->n_fonts
= 0;
3694 dpyinfo
->font_table_size
= 0;
3695 dpyinfo
->bitmaps
= 0;
3696 dpyinfo
->bitmaps_size
= 0;
3697 dpyinfo
->bitmaps_last
= 0;
3698 dpyinfo
->mouse_face_mouse_frame
= 0;
3699 dpyinfo
->mouse_face_deferred_gc
= 0;
3700 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3701 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3702 dpyinfo
->mouse_face_face_id
= 0;
3703 dpyinfo
->mouse_face_window
= Qnil
;
3704 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3705 dpyinfo
->mouse_face_defer
= 0;
3706 dpyinfo
->win32_focus_frame
= 0;
3707 dpyinfo
->win32_focus_event_frame
= 0;
3708 dpyinfo
->win32_highlight_frame
= 0;
3710 ReleaseDC (GetDesktopWindow (), hdc
);
3712 /* Determine if there is a middle mouse button, to allow parse_button
3713 to decide whether right mouse events should be mouse-2 or
3715 XSETINT (Vwin32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
3717 /* initialise palette with white and black */
3720 defined_color (0, "white", &color
, 1);
3721 defined_color (0, "black", &color
, 1);
3724 #ifndef F_SETOWN_BUG
3726 #ifdef F_SETOWN_SOCK_NEG
3727 /* stdin is a socket here */
3728 fcntl (connection
, F_SETOWN
, -getpid ());
3729 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3730 fcntl (connection
, F_SETOWN
, getpid ());
3731 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3732 #endif /* ! defined (F_SETOWN) */
3733 #endif /* F_SETOWN_BUG */
3736 if (interrupt_input
)
3737 init_sigio (connection
);
3738 #endif /* ! defined (SIGIO) */
3745 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3748 x_delete_display (dpyinfo
)
3749 struct win32_display_info
*dpyinfo
;
3751 /* Discard this display from win32_display_name_list and win32_display_list.
3752 We can't use Fdelq because that can quit. */
3753 if (! NILP (win32_display_name_list
)
3754 && EQ (XCONS (win32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3755 win32_display_name_list
= XCONS (win32_display_name_list
)->cdr
;
3760 tail
= win32_display_name_list
;
3761 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3763 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3764 dpyinfo
->name_list_element
))
3766 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3769 tail
= XCONS (tail
)->cdr
;
3773 /* free palette table */
3775 struct win32_palette_entry
* plist
;
3777 plist
= dpyinfo
->color_list
;
3780 struct win32_palette_entry
* pentry
= plist
;
3781 plist
= plist
->next
;
3784 dpyinfo
->color_list
= NULL
;
3785 if (dpyinfo
->palette
)
3786 DeleteObject(dpyinfo
->palette
);
3788 xfree (dpyinfo
->font_table
);
3789 xfree (dpyinfo
->win32_id_name
);
3792 /* Set up use of Win32. */
3794 DWORD
win_msg_worker ();
3798 clear_frame_hook
= win32_clear_frame
;
3799 clear_end_of_line_hook
= win32_clear_end_of_line
;
3800 ins_del_lines_hook
= win32_ins_del_lines
;
3801 change_line_highlight_hook
= win32_change_line_highlight
;
3802 insert_glyphs_hook
= win32_insert_glyphs
;
3803 write_glyphs_hook
= win32_write_glyphs
;
3804 delete_glyphs_hook
= win32_delete_glyphs
;
3805 ring_bell_hook
= win32_ring_bell
;
3806 reset_terminal_modes_hook
= win32_reset_terminal_modes
;
3807 set_terminal_modes_hook
= win32_set_terminal_modes
;
3808 update_begin_hook
= win32_update_begin
;
3809 update_end_hook
= win32_update_end
;
3810 set_terminal_window_hook
= win32_set_terminal_window
;
3811 read_socket_hook
= w32_read_socket
;
3812 frame_up_to_date_hook
= win32_frame_up_to_date
;
3813 cursor_to_hook
= win32_cursor_to
;
3814 reassert_line_highlight_hook
= win32_reassert_line_highlight
;
3815 mouse_position_hook
= win32_mouse_position
;
3816 frame_rehighlight_hook
= win32_frame_rehighlight
;
3817 frame_raise_lower_hook
= win32_frame_raise_lower
;
3818 set_vertical_scroll_bar_hook
= win32_set_vertical_scroll_bar
;
3819 condemn_scroll_bars_hook
= win32_condemn_scroll_bars
;
3820 redeem_scroll_bar_hook
= win32_redeem_scroll_bar
;
3821 judge_scroll_bars_hook
= win32_judge_scroll_bars
;
3823 scroll_region_ok
= 1; /* we'll scroll partial frames */
3824 char_ins_del_ok
= 0; /* just as fast to write the line */
3825 line_ins_del_ok
= 1; /* we'll just blt 'em */
3826 fast_clear_end_of_line
= 1; /* X does this well */
3827 memory_below_frame
= 0; /* we don't remember what scrolls
3831 /* Try to use interrupt input; if we can't, then start polling. */
3832 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3834 /* Create the window thread - it will terminate itself or when the app terminates */
3838 dwMainThreadId
= GetCurrentThreadId ();
3839 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3840 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3842 /* Wait for thread to start */
3847 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3849 hWinThread
= CreateThread (NULL
, 0,
3850 (LPTHREAD_START_ROUTINE
) win_msg_worker
,
3851 0, 0, &dwWinThreadId
);
3853 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3856 /* It is desirable that mainThread should have the same notion of
3857 focus window and active window as winThread. Unfortunately, the
3858 following call to AttachThreadInput, which should do precisely what
3859 we need, causes major problems when Emacs is linked as a console
3860 program. Unfortunately, we have good reasons for doing that, so
3861 instead we need to send messages to winThread to make some API
3862 calls for us (ones that affect, or depend on, the active/focus
3864 #ifdef ATTACH_THREADS
3865 AttachThreadInput (dwMainThreadId
, dwWinThreadId
, TRUE
);
3870 syms_of_win32term ()
3872 staticpro (&win32_display_name_list
);
3873 win32_display_name_list
= Qnil
;
3875 staticpro (&last_mouse_scroll_bar
);
3876 last_mouse_scroll_bar
= Qnil
;
3878 staticpro (&Qvendor_specific_keysyms
);
3879 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
3881 DEFVAR_INT ("win32-num-mouse-buttons",
3882 &Vwin32_num_mouse_buttons
,
3883 "Number of physical mouse buttons.");
3884 Vwin32_num_mouse_buttons
= Qnil
;
3886 DEFVAR_LISP ("win32-swap-mouse-buttons",
3887 &Vwin32_swap_mouse_buttons
,
3888 "Swap the mapping of middle and right mouse buttons.\n\
3889 When nil, middle button is mouse-2 and right button is mouse-3.");
3890 Vwin32_swap_mouse_buttons
= Qnil
;