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
);
2402 win32_clear_rect (f
, NULL
, &msg
.rect
);
2408 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2412 if (f
->async_visible
== 0)
2414 f
->async_visible
= 1;
2415 f
->async_iconified
= 0;
2416 SET_FRAME_GARBAGED (f
);
2420 /* WM_ERASEBKGND is only generated (and processed)
2421 in response to WM_PAINT, so emulate that
2423 win32_clear_rect (f
, NULL
, &msg
.rect
);
2427 msg
.rect
.right
-msg
.rect
.left
+1,
2428 msg
.rect
.bottom
-msg
.rect
.top
+1);
2434 case WM_PALETTECHANGED
:
2435 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2437 /* Realize palette - will force update if needed. */
2438 release_frame_dc (f
, get_frame_dc (f
));
2442 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2444 if (f
&& !f
->iconified
)
2446 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2448 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2449 bufp
->kind
= non_ascii_keystroke
;
2450 bufp
->code
= msg
.msg
.wParam
;
2451 bufp
->modifiers
= win32_kbd_mods_to_emacs (msg
.dwModifiers
);
2452 XSETFRAME (bufp
->frame_or_window
, f
);
2453 bufp
->timestamp
= msg
.msg
.time
;
2461 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2463 if (f
&& !f
->iconified
)
2468 KEY_EVENT_RECORD key
, *keyp
= &key
;
2470 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2473 convert_to_key_event (&msg
, keyp
);
2474 add
= key_event (keyp
, bufp
);
2475 XSETFRAME (bufp
->frame_or_window
, f
);
2478 /* The key pressed generated two characters, most likely
2479 an accent character and a key that could not be
2480 combined with it. Prepend the message on the queue
2481 again to process the second character (which is
2482 being held internally in key_event), and process
2483 the first character now. */
2488 /* Throw dead keys away. However, be sure not to
2489 throw away the dead key if it was produced using
2490 AltGr and there is a valid AltGr scan code for
2492 if (is_dead_key (msg
.msg
.wParam
)
2493 && !((VkKeyScan (bufp
->code
) & 0xff00) == 0x600))
2507 if (dpyinfo
->grabbed
&& last_mouse_frame
2508 && FRAME_LIVE_P (last_mouse_frame
))
2509 f
= last_mouse_frame
;
2511 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2514 note_mouse_movement (f
, &msg
.msg
);
2516 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
2519 case WM_LBUTTONDOWN
:
2521 case WM_MBUTTONDOWN
:
2523 case WM_RBUTTONDOWN
:
2529 if (dpyinfo
->grabbed
&& last_mouse_frame
2530 && FRAME_LIVE_P (last_mouse_frame
))
2531 f
= last_mouse_frame
;
2533 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2537 if ((!dpyinfo
->win32_focus_frame
|| f
== dpyinfo
->win32_focus_frame
)
2540 construct_mouse_click (bufp
, &msg
, f
);
2547 parse_button (msg
.msg
.message
, &button
, &up
);
2551 dpyinfo
->grabbed
&= ~ (1 << button
);
2555 dpyinfo
->grabbed
|= (1 << button
);
2556 last_mouse_frame
= f
;
2563 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2565 if (bar
&& numchars
>= 1)
2567 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2578 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2580 if (f
&& !f
->async_iconified
)
2582 f
->output_data
.win32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2583 f
->output_data
.win32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2588 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2590 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2598 GetClientRect(msg
.msg
.hwnd
, &rect
);
2600 height
= rect
.bottom
- rect
.top
+ 1;
2601 width
= rect
.right
- rect
.left
+ 1;
2603 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2604 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2606 /* Even if the number of character rows and columns has
2607 not changed, the font size may have changed, so we need
2608 to check the pixel dimensions as well. */
2610 if (columns
!= f
->width
2611 || rows
!= f
->height
2612 || width
!= f
->output_data
.win32
->pixel_width
2613 || height
!= f
->output_data
.win32
->pixel_height
)
2615 /* I had set this to 0, 0 - I am not sure why?? */
2617 change_frame_size (f
, rows
, columns
, 0, 1);
2618 SET_FRAME_GARBAGED (f
);
2620 f
->output_data
.win32
->pixel_width
= width
;
2621 f
->output_data
.win32
->pixel_height
= height
;
2622 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
2629 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2631 if (msg
.msg
.message
== WM_SETFOCUS
)
2633 x_new_focus_frame (dpyinfo
, f
);
2635 else if (f
== dpyinfo
->win32_focus_frame
)
2636 x_new_focus_frame (dpyinfo
, 0);
2640 switch (msg
.msg
.wParam
& 0xfff0) /* Lower 4 bits used by Windows. */
2643 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2650 bufp
->kind
= delete_window_event
;
2651 XSETFRAME (bufp
->frame_or_window
, f
);
2659 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2663 f
->async_visible
= 1;
2664 f
->async_iconified
= 1;
2666 bufp
->kind
= iconify_event
;
2667 XSETFRAME (bufp
->frame_or_window
, f
);
2676 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2680 f
->async_visible
= 1;
2681 f
->async_iconified
= 0;
2683 /* wait_reading_process_input will notice this and update
2684 the frame's display structures. */
2685 SET_FRAME_GARBAGED (f
);
2689 bufp
->kind
= deiconify_event
;
2690 XSETFRAME (bufp
->frame_or_window
, f
);
2696 /* Force a redisplay sooner or later
2697 to update the frame titles
2698 in case this is the second frame. */
2699 record_asynch_buffer_change ();
2707 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2714 bufp
->kind
= delete_window_event
;
2715 XSETFRAME (bufp
->frame_or_window
, f
);
2723 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2727 if (msg
.msg
.lParam
== 0)
2729 /* Came from window menu */
2731 extern Lisp_Object
get_frame_menubar_event ();
2732 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2733 struct input_event buf
;
2736 XSETFRAME (frame
, f
);
2737 buf
.kind
= menu_bar_event
;
2739 /* Store initial menu bar event */
2743 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2744 kbd_buffer_store_event (&buf
);
2747 /* Enqueue the events */
2749 while (!NILP (event
))
2751 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2752 kbd_buffer_store_event (&buf
);
2753 event
= XCONS (event
)->cdr
;
2758 /* Came from popup menu */
2765 /* If the focus was just given to an autoraising frame,
2767 /* ??? This ought to be able to handle more than one such frame. */
2768 if (pending_autoraise_frame
)
2770 x_raise_frame (pending_autoraise_frame
);
2771 pending_autoraise_frame
= 0;
2778 /* Drawing the cursor. */
2781 /* Draw a hollow box cursor. Don't change the inside of the box. */
2791 hdc
= get_frame_dc (f
);
2793 hb
= CreateSolidBrush (f
->output_data
.win32
->cursor_pixel
);
2795 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2796 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2797 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.win32
->font
);
2798 rect
.bottom
= rect
.top
+ f
->output_data
.win32
->line_height
;
2800 FrameRect (hdc
, &rect
, hb
);
2803 release_frame_dc (f
, hdc
);
2806 /* Clear the cursor of frame F to background color,
2807 and mark the cursor as not shown.
2808 This is used when the text where the cursor is
2809 is about to be rewritten. */
2815 if (! FRAME_VISIBLE_P (f
)
2816 || f
->phys_cursor_x
< 0)
2819 x_display_cursor (f
, 0);
2820 f
->phys_cursor_x
= -1;
2823 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2824 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2828 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2835 CHAR_TO_PIXEL_COL (f
, column
),
2836 CHAR_TO_PIXEL_ROW (f
, row
),
2837 &glyph
, 1, highlight
, 0);
2841 x_display_bar_cursor (f
, on
)
2845 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2847 /* This is pointless on invisible frames, and dangerous on garbaged
2848 frames; in the latter case, the frame may be in the midst of
2849 changing its size, and curs_x and curs_y may be off the frame. */
2850 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2853 if (! on
&& f
->phys_cursor_x
< 0)
2856 /* If we're not updating, then we want to use the current frame's
2857 cursor position, not our local idea of where the cursor ought to be. */
2858 if (f
!= updating_frame
)
2860 curs_x
= FRAME_CURSOR_X (f
);
2861 curs_y
= FRAME_CURSOR_Y (f
);
2864 /* If there is anything wrong with the current cursor state, remove it. */
2865 if (f
->phys_cursor_x
>= 0
2867 || f
->phys_cursor_x
!= curs_x
2868 || f
->phys_cursor_y
!= curs_y
2869 || f
->output_data
.win32
->current_cursor
!= bar_cursor
))
2871 /* Erase the cursor by redrawing the character underneath it. */
2872 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2873 f
->phys_cursor_glyph
,
2874 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2875 f
->phys_cursor_x
= -1;
2878 /* If we now need a cursor in the new place or in the new form, do it so. */
2880 && (f
->phys_cursor_x
< 0
2881 || (f
->output_data
.win32
->current_cursor
!= bar_cursor
)))
2883 f
->phys_cursor_glyph
2884 = ((current_glyphs
->enable
[curs_y
]
2885 && curs_x
< current_glyphs
->used
[curs_y
])
2886 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2888 win32_fill_area (f
, NULL
, f
->output_data
.win32
->cursor_pixel
,
2889 CHAR_TO_PIXEL_COL (f
, curs_x
),
2890 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2891 max (f
->output_data
.win32
->cursor_width
, 1),
2892 f
->output_data
.win32
->line_height
);
2894 f
->phys_cursor_x
= curs_x
;
2895 f
->phys_cursor_y
= curs_y
;
2897 f
->output_data
.win32
->current_cursor
= bar_cursor
;
2902 /* Turn the displayed cursor of frame F on or off according to ON.
2903 If ON is nonzero, where to put the cursor is specified
2904 by F->cursor_x and F->cursor_y. */
2907 x_display_box_cursor (f
, on
)
2911 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2913 /* This is pointless on invisible frames, and dangerous on garbaged
2914 frames; in the latter case, the frame may be in the midst of
2915 changing its size, and curs_x and curs_y may be off the frame. */
2916 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2919 /* If cursor is off and we want it off, return quickly. */
2920 if (!on
&& f
->phys_cursor_x
< 0)
2923 /* If we're not updating, then we want to use the current frame's
2924 cursor position, not our local idea of where the cursor ought to be. */
2925 if (f
!= updating_frame
)
2927 curs_x
= FRAME_CURSOR_X (f
);
2928 curs_y
= FRAME_CURSOR_Y (f
);
2931 /* If cursor is currently being shown and we don't want it to be
2932 or it is in the wrong place,
2933 or we want a hollow box and it's not so, (pout!)
2935 if (f
->phys_cursor_x
>= 0
2937 || f
->phys_cursor_x
!= curs_x
2938 || f
->phys_cursor_y
!= curs_y
2939 || (f
->output_data
.win32
->current_cursor
!= hollow_box_cursor
2940 && (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
))))
2942 int mouse_face_here
= 0;
2943 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2945 /* If the cursor is in the mouse face area, redisplay that when
2946 we clear the cursor. */
2947 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2949 (f
->phys_cursor_y
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2950 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2951 && f
->phys_cursor_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2953 (f
->phys_cursor_y
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2954 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2955 && f
->phys_cursor_x
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2956 /* Don't redraw the cursor's spot in mouse face
2957 if it is at the end of a line (on a newline).
2958 The cursor appears there, but mouse highlighting does not. */
2959 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2960 mouse_face_here
= 1;
2962 /* If the font is not as tall as a whole line,
2963 we must explicitly clear the line's whole height. */
2964 if (FONT_HEIGHT (f
->output_data
.win32
->font
) != f
->output_data
.win32
->line_height
)
2965 win32_clear_area (f
, NULL
,
2966 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2967 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2968 FONT_WIDTH (f
->output_data
.win32
->font
),
2969 f
->output_data
.win32
->line_height
);
2970 /* Erase the cursor by redrawing the character underneath it. */
2971 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2972 f
->phys_cursor_glyph
,
2975 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2976 f
->phys_cursor_x
= -1;
2979 /* If we want to show a cursor,
2980 or we want a box cursor and it's not so,
2981 write it in the right place. */
2983 && (f
->phys_cursor_x
< 0
2984 || (f
->output_data
.win32
->current_cursor
!= filled_box_cursor
2985 && f
== FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)))
2987 f
->phys_cursor_glyph
2988 = ((current_glyphs
->enable
[curs_y
]
2989 && curs_x
< current_glyphs
->used
[curs_y
])
2990 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2992 if (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)
2995 f
->output_data
.win32
->current_cursor
= hollow_box_cursor
;
2999 x_draw_single_glyph (f
, curs_y
, curs_x
,
3000 f
->phys_cursor_glyph
, 2);
3001 f
->output_data
.win32
->current_cursor
= filled_box_cursor
;
3004 f
->phys_cursor_x
= curs_x
;
3005 f
->phys_cursor_y
= curs_y
;
3009 x_display_cursor (f
, on
)
3015 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3016 x_display_box_cursor (f
, on
);
3017 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3018 x_display_bar_cursor (f
, on
);
3020 /* Those are the only two we have implemented! */
3026 /* Changing the font of the frame. */
3028 /* Give frame F the font named FONTNAME as its default font, and
3029 return the full name of that font. FONTNAME may be a wildcard
3030 pattern; in that case, we choose some font that fits the pattern.
3031 The return value shows which font we chose. */
3034 x_new_font (f
, fontname
)
3036 register char *fontname
;
3039 int n_matching_fonts
;
3040 XFontStruct
*font_info
;
3041 char new_font_name
[101];
3043 /* Get a font which matches this name */
3047 if (!x_to_win32_font(fontname
, &lf
)
3048 || !win32_to_x_font(&lf
, new_font_name
, 100))
3054 /* See if we've already loaded a matching font. */
3055 already_loaded
= -1;
3060 for (i
= 0; i
< FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3061 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3064 fontname
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3069 /* If we have, just return it from the table. */
3070 if (already_loaded
>= 0)
3071 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3072 /* Otherwise, load the font and add it to the table. */
3078 font
= win32_load_font(FRAME_WIN32_DISPLAY_INFO (f
), fontname
);
3085 /* Do we need to create the table? */
3086 if (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
== 0)
3088 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
= 16;
3089 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3090 = (struct font_info
*) xmalloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3091 * sizeof (struct font_info
));
3093 /* Do we need to grow the table? */
3094 else if (FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
3095 >= FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
)
3097 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3098 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
3099 = (struct font_info
*) xrealloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
,
3100 (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
3101 * sizeof (struct font_info
)));
3104 n_fonts
= FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
;
3105 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3106 bcopy (fontname
, FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3107 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3108 FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
++;
3111 /* Compute the scroll bar width in character columns. */
3112 if (f
->scroll_bar_pixel_width
> 0)
3114 int wid
= FONT_WIDTH (f
->output_data
.win32
->font
);
3115 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3118 f
->scroll_bar_cols
= 2;
3120 /* Now make the frame display the given font. */
3121 if (FRAME_WIN32_WINDOW (f
) != 0)
3123 frame_update_line_height (f
);
3124 x_set_window_size (f
, 0, f
->width
, f
->height
);
3127 /* If we are setting a new frame's font for the first time,
3128 there are no faces yet, so this font's height is the line height. */
3129 f
->output_data
.win32
->line_height
= FONT_HEIGHT (f
->output_data
.win32
->font
);
3132 Lisp_Object lispy_name
;
3134 lispy_name
= build_string (fontname
);
3140 x_calc_absolute_position (f
)
3145 int flags
= f
->output_data
.win32
->size_hint_flags
;
3149 /* Find the position of the outside upper-left corner of
3150 the inner window, with respect to the outer window. */
3151 if (f
->output_data
.win32
->parent_desc
!= FRAME_WIN32_DISPLAY_INFO (f
)->root_window
)
3154 MapWindowPoints (FRAME_WIN32_WINDOW (f
),
3155 f
->output_data
.win32
->parent_desc
,
3162 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3165 AdjustWindowRect(&rt
, f
->output_data
.win32
->dwStyle
,
3166 FRAME_EXTERNAL_MENU_BAR (f
));
3169 pt
.x
+= (rt
.right
- rt
.left
);
3170 pt
.y
+= (rt
.bottom
- rt
.top
);
3173 /* Treat negative positions as relative to the leftmost bottommost
3174 position that fits on the screen. */
3175 if (flags
& XNegative
)
3176 f
->output_data
.win32
->left_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->width
3177 - 2 * f
->output_data
.win32
->border_width
- pt
.x
3179 + f
->output_data
.win32
->left_pos
);
3181 if (flags
& YNegative
)
3182 f
->output_data
.win32
->top_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->height
3183 - 2 * f
->output_data
.win32
->border_width
- pt
.y
3185 + f
->output_data
.win32
->top_pos
);
3186 /* The left_pos and top_pos
3187 are now relative to the top and left screen edges,
3188 so the flags should correspond. */
3189 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3192 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3193 to really change the position, and 0 when calling from
3194 x_make_frame_visible (in that case, XOFF and YOFF are the current
3195 position values). It is -1 when calling from x_set_frame_parameters,
3196 which means, do adjust for borders but don't change the gravity. */
3198 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3200 register int xoff
, yoff
;
3203 int modified_top
, modified_left
;
3205 if (change_gravity
> 0)
3207 f
->output_data
.win32
->top_pos
= yoff
;
3208 f
->output_data
.win32
->left_pos
= xoff
;
3209 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3211 f
->output_data
.win32
->size_hint_flags
|= XNegative
;
3213 f
->output_data
.win32
->size_hint_flags
|= YNegative
;
3214 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3216 x_calc_absolute_position (f
);
3219 x_wm_set_size_hint (f
, (long) 0, 0);
3221 /* It is a mystery why we need to add the border_width here
3222 when the frame is already visible, but experiment says we do. */
3223 modified_left
= f
->output_data
.win32
->left_pos
;
3224 modified_top
= f
->output_data
.win32
->top_pos
;
3225 if (change_gravity
!= 0)
3227 modified_left
+= f
->output_data
.win32
->border_width
;
3228 modified_top
+= f
->output_data
.win32
->border_width
;
3231 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3233 modified_left
, modified_top
,
3235 SWP_NOZORDER
| SWP_NOSIZE
);
3239 /* Call this to change the size of frame F's x-window.
3240 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3241 for this size change and subsequent size changes.
3242 Otherwise we leave the window gravity unchanged. */
3244 x_set_window_size (f
, change_gravity
, cols
, rows
)
3249 int pixelwidth
, pixelheight
;
3253 check_frame_size (f
, &rows
, &cols
);
3254 f
->output_data
.win32
->vertical_scroll_bar_extra
3255 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3257 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3258 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3259 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
3260 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3261 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3263 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3264 x_wm_set_size_hint (f
, (long) 0, 0);
3269 rect
.left
= rect
.top
= 0;
3270 rect
.right
= pixelwidth
;
3271 rect
.bottom
= pixelheight
;
3273 AdjustWindowRect(&rect
, f
->output_data
.win32
->dwStyle
,
3274 FRAME_EXTERNAL_MENU_BAR (f
));
3276 /* All windows have an extra pixel */
3278 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3281 rect
.right
- rect
.left
+ 1,
3282 rect
.bottom
- rect
.top
+ 1,
3283 SWP_NOZORDER
| SWP_NOMOVE
);
3286 /* Now, strictly speaking, we can't be sure that this is accurate,
3287 but the window manager will get around to dealing with the size
3288 change request eventually, and we'll hear how it went when the
3289 ConfigureNotify event gets here.
3291 We could just not bother storing any of this information here,
3292 and let the ConfigureNotify event set everything up, but that
3293 might be kind of confusing to the lisp code, since size changes
3294 wouldn't be reported in the frame parameters until some random
3295 point in the future when the ConfigureNotify event arrives. */
3296 change_frame_size (f
, rows
, cols
, 0, 0);
3297 PIXEL_WIDTH (f
) = pixelwidth
;
3298 PIXEL_HEIGHT (f
) = pixelheight
;
3300 /* If cursor was outside the new size, mark it as off. */
3301 if (f
->phys_cursor_y
>= rows
3302 || f
->phys_cursor_x
>= cols
)
3304 f
->phys_cursor_x
= -1;
3305 f
->phys_cursor_y
= -1;
3308 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3309 receive in the ConfigureNotify event; if we get what we asked
3310 for, then the event won't cause the screen to become garbaged, so
3311 we have to make sure to do it here. */
3312 SET_FRAME_GARBAGED (f
);
3317 /* Mouse warping. */
3320 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3326 pix_x
+= f
->output_data
.win32
->left_pos
;
3327 pix_y
+= f
->output_data
.win32
->top_pos
;
3329 SetCursorPos (pix_x
, pix_y
);
3335 x_set_mouse_position (f
, x
, y
)
3341 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.win32
->font
) / 2;
3342 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.win32
->line_height
/ 2;
3344 if (pix_x
< 0) pix_x
= 0;
3345 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3347 if (pix_y
< 0) pix_y
= 0;
3348 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3350 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3353 /* focus shifting, raising and lowering. */
3355 x_focus_on_frame (f
)
3365 /* Raise frame F. */
3370 // if (f->async_visible)
3373 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3376 SWP_NOSIZE
| SWP_NOMOVE
);
3381 /* Lower frame F. */
3386 // if (f->async_visible)
3389 my_set_window_pos (FRAME_WIN32_WINDOW (f
),
3392 SWP_NOSIZE
| SWP_NOMOVE
);
3398 win32_frame_raise_lower (f
, raise
)
3408 /* Change of visibility. */
3410 /* This tries to wait until the frame is really visible.
3411 However, if the window manager asks the user where to position
3412 the frame, this will return before the user finishes doing that.
3413 The frame will not actually be visible at that time,
3414 but it will become visible later when the window manager
3415 finishes with it. */
3417 x_make_frame_visible (f
)
3422 if (! FRAME_VISIBLE_P (f
))
3424 /* We test FRAME_GARBAGED_P here to make sure we don't
3425 call x_set_offset a second time
3426 if we get to x_make_frame_visible a second time
3427 before the window gets really visible. */
3428 if (! FRAME_ICONIFIED_P (f
)
3429 && ! f
->output_data
.win32
->asked_for_visible
)
3431 x_set_offset (f
, f
->output_data
.win32
->left_pos
, f
->output_data
.win32
->top_pos
, 0);
3432 // SetForegroundWindow (FRAME_WIN32_WINDOW (f));
3435 f
->output_data
.win32
->asked_for_visible
= 1;
3437 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWNORMAL
);
3440 /* Synchronize to ensure Emacs knows the frame is visible
3441 before we do anything else. We do this loop with input not blocked
3442 so that incoming events are handled. */
3445 int count
= input_signal_count
;
3447 /* This must come after we set COUNT. */
3450 XSETFRAME (frame
, f
);
3454 /* Once we have handled input events,
3455 we should have received the MapNotify if one is coming.
3456 So if we have not got it yet, stop looping.
3457 Some window managers make their own decisions
3458 about visibility. */
3459 if (input_signal_count
!= count
)
3461 /* Machines that do polling rather than SIGIO have been observed
3462 to go into a busy-wait here. So we'll fake an alarm signal
3463 to let the handler know that there's something to be read.
3464 We used to raise a real alarm, but it seems that the handler
3465 isn't always enabled here. This is probably a bug. */
3466 if (input_polling_used ())
3468 /* It could be confusing if a real alarm arrives while processing
3469 the fake one. Turn it off and let the handler reset it. */
3471 input_poll_signal ();
3473 /* Once we have handled input events,
3474 we should have received the MapNotify if one is coming.
3475 So if we have not got it yet, stop looping.
3476 Some window managers make their own decisions
3477 about visibility. */
3478 if (input_signal_count
!= count
)
3481 FRAME_SAMPLE_VISIBILITY (f
);
3485 /* Change from mapped state to withdrawn state. */
3487 /* Make the frame visible (mapped and not iconified). */
3489 x_make_frame_invisible (f
)
3494 /* Don't keep the highlight on an invisible frame. */
3495 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3496 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3500 my_show_window (FRAME_WIN32_WINDOW (f
), SW_HIDE
);
3502 /* We can't distinguish this from iconification
3503 just by the event that we get from the server.
3504 So we can't win using the usual strategy of letting
3505 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3506 and synchronize with the server to make sure we agree. */
3508 FRAME_ICONIFIED_P (f
) = 0;
3509 f
->async_visible
= 0;
3510 f
->async_iconified
= 0;
3515 /* Change window state from mapped to iconified. */
3523 /* Don't keep the highlight on an invisible frame. */
3524 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3525 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3527 if (f
->async_iconified
)
3532 my_show_window (FRAME_WIN32_WINDOW (f
), SW_SHOWMINIMIZED
);
3533 /* The frame doesn't seem to be lowered automatically. */
3536 f
->async_iconified
= 1;
3541 /* Destroy the window of frame F. */
3543 x_destroy_window (f
)
3546 struct win32_display_info
*dpyinfo
= FRAME_WIN32_DISPLAY_INFO (f
);
3550 my_destroy_window (f
, FRAME_WIN32_WINDOW (f
));
3551 free_frame_menubar (f
);
3552 free_frame_faces (f
);
3554 xfree (f
->output_data
.win32
);
3555 f
->output_data
.win32
= 0;
3556 if (f
== dpyinfo
->win32_focus_frame
)
3557 dpyinfo
->win32_focus_frame
= 0;
3558 if (f
== dpyinfo
->win32_focus_event_frame
)
3559 dpyinfo
->win32_focus_event_frame
= 0;
3560 if (f
== dpyinfo
->win32_highlight_frame
)
3561 dpyinfo
->win32_highlight_frame
= 0;
3563 dpyinfo
->reference_count
--;
3565 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3567 dpyinfo
->mouse_face_beg_row
3568 = dpyinfo
->mouse_face_beg_col
= -1;
3569 dpyinfo
->mouse_face_end_row
3570 = dpyinfo
->mouse_face_end_col
= -1;
3571 dpyinfo
->mouse_face_window
= Qnil
;
3577 /* Setting window manager hints. */
3579 /* Set the normal size hints for the window manager, for frame F.
3580 FLAGS is the flags word to use--or 0 meaning preserve the flags
3581 that the window now has.
3582 If USER_POSITION is nonzero, we set the USPosition
3583 flag (this is useful when FLAGS is 0). */
3585 x_wm_set_size_hint (f
, flags
, user_position
)
3590 Window window
= FRAME_WIN32_WINDOW (f
);
3592 flexlines
= f
->height
;
3596 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.win32
->font
));
3597 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.win32
->line_height
);
3602 /* Window manager things */
3603 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3608 Window window
= FRAME_WIN32_WINDOW (f
);
3610 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3611 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3612 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3614 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3619 /* Initialization. */
3621 #ifdef USE_X_TOOLKIT
3622 static XrmOptionDescRec emacs_options
[] = {
3623 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3624 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3626 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3627 XrmoptionSepArg
, NULL
},
3628 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3630 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3631 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3632 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3633 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3634 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3635 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3636 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3638 #endif /* USE_X_TOOLKIT */
3640 static int win32_initialized
= 0;
3642 struct win32_display_info
*
3643 win32_term_init (display_name
, xrm_option
, resource_name
)
3644 Lisp_Object display_name
;
3646 char *resource_name
;
3650 struct win32_display_info
*dpyinfo
;
3655 if (!win32_initialized
)
3657 win32_initialize ();
3658 win32_initialized
= 1;
3669 argv
[argc
++] = "-xrm";
3670 argv
[argc
++] = xrm_option
;
3674 dpyinfo
= &one_win32_display_info
;
3676 /* Put this display on the chain. */
3677 dpyinfo
->next
= NULL
;
3679 /* Put it on win32_display_name_list as well, to keep them parallel. */
3680 win32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3681 win32_display_name_list
);
3682 dpyinfo
->name_list_element
= XCONS (win32_display_name_list
)->car
;
3684 dpyinfo
->win32_id_name
3685 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3686 + XSTRING (Vsystem_name
)->size
3688 sprintf (dpyinfo
->win32_id_name
, "%s@%s",
3689 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3692 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3693 resource_name
, EMACS_CLASS
);
3695 /* Put the rdb where we can find it in a way that works on
3697 dpyinfo
->xrdb
= xrdb
;
3699 hdc
= GetDC (GetDesktopWindow ());
3701 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3702 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3703 dpyinfo
->root_window
= GetDesktopWindow ();
3704 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3705 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3706 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3707 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3708 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
3709 dpyinfo
->grabbed
= 0;
3710 dpyinfo
->reference_count
= 0;
3711 dpyinfo
->n_fonts
= 0;
3712 dpyinfo
->font_table_size
= 0;
3713 dpyinfo
->bitmaps
= 0;
3714 dpyinfo
->bitmaps_size
= 0;
3715 dpyinfo
->bitmaps_last
= 0;
3716 dpyinfo
->mouse_face_mouse_frame
= 0;
3717 dpyinfo
->mouse_face_deferred_gc
= 0;
3718 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3719 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3720 dpyinfo
->mouse_face_face_id
= 0;
3721 dpyinfo
->mouse_face_window
= Qnil
;
3722 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3723 dpyinfo
->mouse_face_defer
= 0;
3724 dpyinfo
->win32_focus_frame
= 0;
3725 dpyinfo
->win32_focus_event_frame
= 0;
3726 dpyinfo
->win32_highlight_frame
= 0;
3728 ReleaseDC (GetDesktopWindow (), hdc
);
3730 /* Determine if there is a middle mouse button, to allow parse_button
3731 to decide whether right mouse events should be mouse-2 or
3733 XSETINT (Vwin32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
3735 /* initialise palette with white and black */
3738 defined_color (0, "white", &color
, 1);
3739 defined_color (0, "black", &color
, 1);
3742 #ifndef F_SETOWN_BUG
3744 #ifdef F_SETOWN_SOCK_NEG
3745 /* stdin is a socket here */
3746 fcntl (connection
, F_SETOWN
, -getpid ());
3747 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3748 fcntl (connection
, F_SETOWN
, getpid ());
3749 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3750 #endif /* ! defined (F_SETOWN) */
3751 #endif /* F_SETOWN_BUG */
3754 if (interrupt_input
)
3755 init_sigio (connection
);
3756 #endif /* ! defined (SIGIO) */
3763 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3766 x_delete_display (dpyinfo
)
3767 struct win32_display_info
*dpyinfo
;
3769 /* Discard this display from win32_display_name_list and win32_display_list.
3770 We can't use Fdelq because that can quit. */
3771 if (! NILP (win32_display_name_list
)
3772 && EQ (XCONS (win32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3773 win32_display_name_list
= XCONS (win32_display_name_list
)->cdr
;
3778 tail
= win32_display_name_list
;
3779 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3781 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3782 dpyinfo
->name_list_element
))
3784 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3787 tail
= XCONS (tail
)->cdr
;
3791 /* free palette table */
3793 struct win32_palette_entry
* plist
;
3795 plist
= dpyinfo
->color_list
;
3798 struct win32_palette_entry
* pentry
= plist
;
3799 plist
= plist
->next
;
3802 dpyinfo
->color_list
= NULL
;
3803 if (dpyinfo
->palette
)
3804 DeleteObject(dpyinfo
->palette
);
3806 xfree (dpyinfo
->font_table
);
3807 xfree (dpyinfo
->win32_id_name
);
3810 /* Set up use of Win32. */
3812 DWORD
win_msg_worker ();
3816 clear_frame_hook
= win32_clear_frame
;
3817 clear_end_of_line_hook
= win32_clear_end_of_line
;
3818 ins_del_lines_hook
= win32_ins_del_lines
;
3819 change_line_highlight_hook
= win32_change_line_highlight
;
3820 insert_glyphs_hook
= win32_insert_glyphs
;
3821 write_glyphs_hook
= win32_write_glyphs
;
3822 delete_glyphs_hook
= win32_delete_glyphs
;
3823 ring_bell_hook
= win32_ring_bell
;
3824 reset_terminal_modes_hook
= win32_reset_terminal_modes
;
3825 set_terminal_modes_hook
= win32_set_terminal_modes
;
3826 update_begin_hook
= win32_update_begin
;
3827 update_end_hook
= win32_update_end
;
3828 set_terminal_window_hook
= win32_set_terminal_window
;
3829 read_socket_hook
= w32_read_socket
;
3830 frame_up_to_date_hook
= win32_frame_up_to_date
;
3831 cursor_to_hook
= win32_cursor_to
;
3832 reassert_line_highlight_hook
= win32_reassert_line_highlight
;
3833 mouse_position_hook
= win32_mouse_position
;
3834 frame_rehighlight_hook
= win32_frame_rehighlight
;
3835 frame_raise_lower_hook
= win32_frame_raise_lower
;
3836 set_vertical_scroll_bar_hook
= win32_set_vertical_scroll_bar
;
3837 condemn_scroll_bars_hook
= win32_condemn_scroll_bars
;
3838 redeem_scroll_bar_hook
= win32_redeem_scroll_bar
;
3839 judge_scroll_bars_hook
= win32_judge_scroll_bars
;
3841 scroll_region_ok
= 1; /* we'll scroll partial frames */
3842 char_ins_del_ok
= 0; /* just as fast to write the line */
3843 line_ins_del_ok
= 1; /* we'll just blt 'em */
3844 fast_clear_end_of_line
= 1; /* X does this well */
3845 memory_below_frame
= 0; /* we don't remember what scrolls
3849 /* Try to use interrupt input; if we can't, then start polling. */
3850 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3852 /* Create the window thread - it will terminate itself or when the app terminates */
3856 dwMainThreadId
= GetCurrentThreadId ();
3857 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3858 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3860 /* Wait for thread to start */
3865 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3867 hWinThread
= CreateThread (NULL
, 0,
3868 (LPTHREAD_START_ROUTINE
) win_msg_worker
,
3869 0, 0, &dwWinThreadId
);
3871 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3874 /* It is desirable that mainThread should have the same notion of
3875 focus window and active window as winThread. Unfortunately, the
3876 following call to AttachThreadInput, which should do precisely what
3877 we need, causes major problems when Emacs is linked as a console
3878 program. Unfortunately, we have good reasons for doing that, so
3879 instead we need to send messages to winThread to make some API
3880 calls for us (ones that affect, or depend on, the active/focus
3882 #ifdef ATTACH_THREADS
3883 AttachThreadInput (dwMainThreadId
, dwWinThreadId
, TRUE
);
3888 syms_of_win32term ()
3890 staticpro (&win32_display_name_list
);
3891 win32_display_name_list
= Qnil
;
3893 staticpro (&last_mouse_scroll_bar
);
3894 last_mouse_scroll_bar
= Qnil
;
3896 staticpro (&Qvendor_specific_keysyms
);
3897 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
3899 DEFVAR_INT ("win32-num-mouse-buttons",
3900 &Vwin32_num_mouse_buttons
,
3901 "Number of physical mouse buttons.");
3902 Vwin32_num_mouse_buttons
= Qnil
;
3904 DEFVAR_LISP ("win32-swap-mouse-buttons",
3905 &Vwin32_swap_mouse_buttons
,
3906 "Swap the mapping of middle and right mouse buttons.\n\
3907 When nil, middle button is mouse-2 and right button is mouse-3.");
3908 Vwin32_swap_mouse_buttons
= Qnil
;