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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Added by Kevin Gallo */
27 #include "blockinput.h"
40 #include "dispextern.h"
41 #include "termhooks.h"
49 #include "intervals.h"
51 extern void free_frame_menubar ();
53 #define x_any_window_to_frame x_window_to_frame
54 #define x_top_window_to_frame x_window_to_frame
57 /* This is display since win32 does not support multiple ones. */
58 struct win32_display_info one_win32_display_info
;
60 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
61 one for each element of win32_display_list and in the same order.
62 NAME is the name of the frame.
63 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
64 Lisp_Object win32_display_name_list
;
66 /* Frame being updated by update_frame. This is declared in term.c.
67 This is set by update_begin and looked at by all the
68 win32 functions. It is zero while not inside an update.
69 In that case, the win32 functions assume that `selected_frame'
70 is the frame to apply to. */
71 extern struct frame
*updating_frame
;
73 /* This is a frame waiting to be autoraised, within w32_read_socket. */
74 struct frame
*pending_autoraise_frame
;
76 /* During an update, maximum vpos for ins/del line operations to affect. */
80 /* During an update, nonzero if chars output now should be highlighted. */
84 /* Nominal cursor position -- where to draw output.
85 During an update, these are different from the cursor-box position. */
90 DWORD dwWinThreadId
= 0;
91 HANDLE hWinThread
= NULL
;
92 DWORD dwMainThreadId
= 0;
93 HANDLE hMainThread
= NULL
;
97 /* Where the mouse was last time we reported a mouse event. */
98 static FRAME_PTR last_mouse_frame
;
99 static RECT last_mouse_glyph
;
101 /* The scroll bar in which the last motion event occurred.
103 If the last motion event occurred in a scroll bar, we set this
104 so win32_mouse_position can know whether to report a scroll bar motion or
107 If the last motion event didn't occur in a scroll bar, we set this
108 to Qnil, to tell win32_mouse_position to return an ordinary motion event. */
109 Lisp_Object last_mouse_scroll_bar
;
110 int last_mouse_scroll_bar_pos
;
112 /* This is a hack. We would really prefer that win32_mouse_position would
113 return the time associated with the position it returns, but there
114 doesn't seem to be any way to wrest the timestamp from the server
115 along with the position query. So, we just keep track of the time
116 of the last movement we received, and return that in hopes that
117 it's somewhat accurate. */
118 Time last_mouse_movement_time
;
120 /* Incremented by w32_read_socket whenever it really tries to read events. */
122 static int volatile input_signal_count
;
124 static int input_signal_count
;
127 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
129 extern Lisp_Object Qface
, Qmouse_face
;
133 /* A mask of extra modifier bits to put into every keyboard char. */
134 extern int extra_keyboard_modifiers
;
136 static Lisp_Object Qvendor_specific_keysyms
;
138 void win32_delete_display ();
140 static void redraw_previous_char ();
141 static void redraw_following_char ();
142 static unsigned int win32_get_modifiers ();
144 static int fast_find_position ();
145 static void note_mouse_highlight ();
146 static void clear_mouse_face ();
147 static void show_mouse_face ();
148 static void do_line_dance ();
150 static int win32_cursor_to ();
151 static int win32_clear_end_of_line ();
154 /* This is a function useful for recording debugging information
155 about the sequence of occurrences in this file. */
163 struct record event_record
[100];
165 int event_record_index
;
167 record_event (locus
, type
)
171 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
172 event_record_index
= 0;
174 event_record
[event_record_index
].locus
= locus
;
175 event_record
[event_record_index
].type
= type
;
176 event_record_index
++;
181 /* Return the struct win32_display_info. */
183 struct win32_display_info
*
184 win32_display_info_for_display ()
186 return (&one_win32_display_info
);
190 win32_fill_rect (f
, _hdc
, pix
, lprect
)
206 hdc
= my_get_dc (FRAME_WIN32_WINDOW (f
));
209 hb
= CreateSolidBrush (pix
);
210 oldobj
= SelectObject (hdc
, hb
);
212 FillRect (hdc
, lprect
, hb
);
213 SelectObject (hdc
, oldobj
);
217 ReleaseDC (FRAME_WIN32_WINDOW (f
), hdc
);
221 win32_clear_window (f
)
226 GetClientRect (FRAME_WIN32_WINDOW (f
), &rect
);
227 win32_clear_rect (f
, NULL
, &rect
);
231 /* Starting and ending updates.
233 These hooks are called by update_frame at the beginning and end
234 of a frame update. We record in `updating_frame' the identity
235 of the frame being updated, so that the win32_... functions do not
236 need to take a frame as argument. Most of the win32_... functions
237 should never be called except during an update, the only exceptions
238 being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight. */
241 win32_update_begin (f
)
247 flexlines
= f
->height
;
252 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
254 /* Don't do highlighting for mouse motion during the update. */
255 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
257 /* If the frame needs to be redrawn,
258 simply forget about any prior mouse highlighting. */
259 if (FRAME_GARBAGED_P (f
))
260 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
262 if (!NILP (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
264 int firstline
, lastline
, i
;
265 struct window
*w
= XWINDOW (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
);
267 /* Find the first, and the last+1, lines affected by redisplay. */
268 for (firstline
= 0; firstline
< f
->height
; firstline
++)
269 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
272 lastline
= f
->height
;
273 for (i
= f
->height
- 1; i
>= 0; i
--)
275 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
281 /* Can we tell that this update does not affect the window
282 where the mouse highlight is? If so, no need to turn off.
283 Likewise, don't do anything if the frame is garbaged;
284 in that case, the FRAME_CURRENT_GLYPHS that we would use
285 are all wrong, and we will redisplay that line anyway. */
286 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
287 || lastline
< XFASTINT (w
->top
)))
288 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
302 x_display_cursor (f
, 1);
304 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
305 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
310 /* This is called after a redisplay on frame F. */
313 win32_frame_up_to_date (f
)
316 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
317 || f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
319 note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
320 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
321 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
322 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
326 /* External interface to control of standout mode.
327 Call this when about to modify line at position VPOS
328 and not change whether it is highlighted. */
330 win32_reassert_line_highlight (new, vpos
)
336 /* Call this when about to modify line at position VPOS
337 and change whether it is highlighted. */
340 win32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
341 int new_highlight
, vpos
, first_unused_hpos
;
343 highlight
= new_highlight
;
344 win32_cursor_to (vpos
, 0);
345 win32_clear_end_of_line (updating_frame
->width
);
348 /* This is used when starting Emacs and when restarting after suspend.
349 When starting Emacs, no window is mapped. And nothing must be done
350 to Emacs's own window if it is suspended (though that rarely happens). */
353 win32_set_terminal_modes ()
357 /* This is called when exiting or suspending Emacs.
358 Exiting will make the Win32 windows go away, and suspending
359 requires no action. */
362 win32_reset_terminal_modes ()
366 /* Set the nominal cursor position of the frame.
367 This is where display update commands will take effect.
368 This does not affect the place where the cursor-box is displayed. */
371 win32_cursor_to (row
, col
)
372 register int row
, col
;
379 if (updating_frame
== 0)
382 x_display_cursor (selected_frame
, 1);
387 /* Display a sequence of N glyphs found at GP.
388 WINDOW is the window to output to. LEFT and TOP are starting coords.
389 HL is 1 if this text is highlighted, 2 if the cursor is on it,
390 3 if should appear in its mouse-face.
391 JUST_FOREGROUND if 1 means draw only the foreground;
392 don't alter the background.
394 FONT is the default font to use (for glyphs whose font-code is 0).
396 Since the display generation code is responsible for calling
397 compute_char_face and compute_glyph_face on everything it puts in
398 the display structure, we can assume that the face code on each
399 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
400 to which we can actually apply intern_face.
401 Call this function with input blocked. */
404 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
407 register GLYPH
*gp
; /* Points to first GLYPH. */
408 register int n
; /* Number of glyphs to display. */
412 /* Holds characters to be displayed. */
413 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
414 register char *cp
; /* Steps through buf[]. */
415 register int tlen
= GLYPH_TABLE_LENGTH
;
416 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
417 Window window
= FRAME_WIN32_WINDOW (f
);
418 int orig_left
= left
;
421 hdc
= my_get_dc (window
);
425 /* Get the face-code of the next GLYPH. */
429 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
430 cf
= FAST_GLYPH_FACE (g
);
432 /* Find the run of consecutive glyphs with the same face-code.
433 Extract their character codes into BUF. */
438 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
439 if (FAST_GLYPH_FACE (g
) != cf
)
442 *cp
++ = FAST_GLYPH_CHAR (g
);
447 /* LEN gets the length of the run. */
450 /* Now output this run of chars, with the font and pixel values
451 determined by the face code CF. */
453 struct face
*face
= FRAME_DEFAULT_FACE (f
);
454 XFontStruct
*font
= FACE_FONT (face
);
459 /* HL = 3 means use a mouse face previously chosen. */
461 cf
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
;
463 /* First look at the face of the text itself. */
466 /* It's possible for the display table to specify
467 a face code that is out of range. Use 0 in that case. */
468 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
469 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
473 face
= FRAME_MODE_LINE_FACE (f
);
475 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
476 font
= FACE_FONT (face
);
477 if (FACE_STIPPLE (face
))
481 /* Then comes the distinction between modeline and normal text. */
486 face
= FRAME_MODE_LINE_FACE (f
);
487 font
= FACE_FONT (face
);
488 if (FACE_STIPPLE (face
))
492 fg
= face
->foreground
;
493 bg
= face
->background
;
495 /* Now override that if the cursor's on this character. */
498 /* The cursor overrides stippling. */
502 || face
->font
== (XFontStruct
*) FACE_DEFAULT
503 || face
->font
== f
->output_data
.win32
->font
)
504 && face
->background
== f
->output_data
.win32
->background_pixel
505 && face
->foreground
== f
->output_data
.win32
->foreground_pixel
)
507 bg
= f
->output_data
.win32
->cursor_pixel
;
508 fg
= face
->background
;
510 /* Cursor on non-default face: must merge. */
513 bg
= f
->output_data
.win32
->cursor_pixel
;
514 fg
= face
->background
;
515 /* If the glyph would be invisible,
516 try a different foreground. */
518 fg
= face
->foreground
;
520 fg
= f
->output_data
.win32
->cursor_foreground_pixel
;
522 fg
= face
->foreground
;
523 /* Make sure the cursor is distinct from text in this face. */
524 if (bg
== face
->background
525 && fg
== face
->foreground
)
527 bg
= face
->foreground
;
528 fg
= face
->background
;
533 if (font
== (XFontStruct
*) FACE_DEFAULT
)
534 font
= f
->output_data
.win32
->font
;
536 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
538 SetTextColor (hdc
, fg
);
539 SetBkColor (hdc
, bg
);
541 SelectObject (hdc
, font
->hfont
);
543 TextOut (hdc
, left
, top
, buf
, len
);
545 if (!just_foreground
)
547 /* Clear the rest of the line's height. */
548 if (f
->output_data
.win32
->line_height
!= FONT_HEIGHT (font
))
549 win32_fill_area (f
, hdc
, bg
,
551 top
+ FONT_HEIGHT (font
),
552 FONT_WIDTH (font
) * len
,
553 f
->output_data
.win32
->line_height
- FONT_HEIGHT (font
));
557 int underline_position
= 1;
559 if (font
->tm
.tmDescent
<= underline_position
)
560 underline_position
= font
->tm
.tmDescent
- 1;
563 win32_fill_area (f
, hdc
, fg
,
566 + underline_position
),
567 len
* FONT_WIDTH (font
), 1);
570 left
+= len
* FONT_WIDTH (font
);
574 ReleaseDC (window
, hdc
);
578 /* Output some text at the nominal frame cursor position.
579 Advance the cursor over the text.
580 Output LEN glyphs at START.
582 `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
583 controls the pixel values used for foreground and background. */
586 win32_write_glyphs (start
, len
)
587 register GLYPH
*start
;
590 register int temp_length
;
600 /* If not within an update,
601 output at the frame's visible cursor. */
602 curs_x
= f
->cursor_x
;
603 curs_y
= f
->cursor_y
;
607 CHAR_TO_PIXEL_COL (f
, curs_x
),
608 CHAR_TO_PIXEL_ROW (f
, curs_y
),
609 start
, len
, highlight
, 0);
611 /* If we drew on top of the cursor, note that it is turned off. */
612 if (curs_y
== f
->phys_cursor_y
613 && curs_x
<= f
->phys_cursor_x
614 && curs_x
+ len
> f
->phys_cursor_x
)
615 f
->phys_cursor_x
= -1;
617 if (updating_frame
== 0)
620 x_display_cursor (f
, 1);
629 /* Clear to the end of the line.
630 Erase the current text line from the nominal cursor position (inclusive)
631 to column FIRST_UNUSED (exclusive). The idea is that everything
632 from FIRST_UNUSED onward is already erased. */
635 win32_clear_end_of_line (first_unused
)
636 register int first_unused
;
638 struct frame
*f
= updating_frame
;
643 if (curs_y
< 0 || curs_y
>= f
->height
)
645 if (first_unused
<= 0)
648 if (first_unused
>= f
->width
)
649 first_unused
= f
->width
;
655 /* Notice if the cursor will be cleared by this operation. */
656 if (curs_y
== f
->phys_cursor_y
657 && curs_x
<= f
->phys_cursor_x
658 && f
->phys_cursor_x
< first_unused
)
659 f
->phys_cursor_x
= -1;
661 win32_clear_area (f
, NULL
,
662 CHAR_TO_PIXEL_COL (f
, curs_x
),
663 CHAR_TO_PIXEL_ROW (f
, curs_y
),
664 FONT_WIDTH (f
->output_data
.win32
->font
) * (first_unused
- curs_x
),
665 f
->output_data
.win32
->line_height
);
673 struct frame
*f
= updating_frame
;
678 f
->phys_cursor_x
= -1; /* Cursor not visible. */
679 curs_x
= 0; /* Nominal cursor position is top left. */
684 win32_clear_window (f
);
686 /* We have to clear the scroll bars, too. If we have changed
687 colors or something like that, then they should be notified. */
688 x_scroll_bar_clear (f
);
693 /* Make audible bell. */
700 FlashWindow (FRAME_WIN32_WINDOW (selected_frame
), FALSE
);
709 /* Insert and delete character.
710 These are not supposed to be used because we are supposed to turn
711 off the feature of using them. */
714 win32_insert_glyphs (start
, len
)
715 register char *start
;
722 win32_delete_glyphs (n
)
728 /* Specify how many text lines, from the top of the window,
729 should be affected by insert-lines and delete-lines operations.
730 This, and those operations, are used only within an update
731 that is bounded by calls to win32_update_begin and win32_update_end. */
734 win32_set_terminal_window (n
)
737 if (updating_frame
== 0)
740 if ((n
<= 0) || (n
> updating_frame
->height
))
741 flexlines
= updating_frame
->height
;
746 /* These variables need not be per frame
747 because redisplay is done on a frame-by-frame basis
748 and the line dance for one frame is finished before
749 anything is done for another frame. */
751 /* Array of line numbers from cached insert/delete operations.
752 line_dance[i] is the old position of the line that we want
753 to move to line i, or -1 if we want a blank line there. */
754 static int *line_dance
;
756 /* Allocated length of that array. */
757 static int line_dance_len
;
759 /* Flag indicating whether we've done any work. */
760 static int line_dance_in_progress
;
762 /* Perform an insert-lines or delete-lines operation,
763 inserting N lines or deleting -N lines at vertical position VPOS. */
764 win32_ins_del_lines (vpos
, n
)
767 register int fence
, i
;
769 if (vpos
>= flexlines
)
772 if (!line_dance_in_progress
)
774 int ht
= updating_frame
->height
;
775 if (ht
> line_dance_len
)
777 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
780 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
781 line_dance_in_progress
= 1;
785 if (n
> flexlines
- vpos
)
786 n
= flexlines
- vpos
;
788 for (i
= flexlines
; --i
>= fence
;)
789 line_dance
[i
] = line_dance
[i
-n
];
790 for (i
= fence
; --i
>= vpos
;)
796 if (n
> flexlines
- vpos
)
797 n
= flexlines
- vpos
;
798 fence
= flexlines
- n
;
799 for (i
= vpos
; i
< fence
; ++i
)
800 line_dance
[i
] = line_dance
[i
+ n
];
801 for (i
= fence
; i
< flexlines
; ++i
)
806 /* Here's where we actually move the pixels around.
807 Must be called with input blocked. */
811 register int i
, j
, distance
;
812 register struct frame
*f
;
817 /* Must check this flag first. If it's not set, then not only is the
818 array uninitialized, but we might not even have a frame. */
819 if (!line_dance_in_progress
)
827 intborder
= f
->output_data
.win32
->internal_border_width
;
829 x_display_cursor (updating_frame
, 0);
831 hdc
= my_get_dc (FRAME_WIN32_WINDOW (f
));
833 for (i
= 0; i
< ht
; ++i
)
834 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
836 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
837 && line_dance
[j
]-j
== distance
); ++j
);
838 /* Copy [i,j) upward from [i+distance, j+distance) */
840 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
841 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
842 (j
-i
) * f
->output_data
.win32
->line_height
,
844 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
849 for (i
= ht
; --i
>=0; )
850 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
852 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
853 && line_dance
[j
]-j
== distance
););
854 /* Copy (j, i] downward from (j+distance, i+distance] */
856 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
857 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
858 (i
-j
) * f
->output_data
.win32
->line_height
,
860 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
865 ReleaseDC (FRAME_WIN32_WINDOW (f
), hdc
);
867 for (i
= 0; i
< ht
; ++i
)
868 if (line_dance
[i
] == -1)
870 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
872 win32_clear_area (f
, NULL
,
874 CHAR_TO_PIXEL_ROW (f
, i
),
875 f
->width
* FONT_WIDTH (f
->output_data
.win32
->font
),
876 (j
-i
) * f
->output_data
.win32
->line_height
);
879 line_dance_in_progress
= 0;
882 /* Support routines for exposure events. */
883 static void clear_cursor ();
885 /* Output into a rectangle of a window (for frame F)
886 the characters in f->phys_lines that overlap that rectangle.
887 TOP and LEFT are the position of the upper left corner of the rectangle.
888 ROWS and COLS are the size of the rectangle.
889 Call this function with input blocked. */
892 dumprectangle (f
, left
, top
, cols
, rows
)
894 register int left
, top
, cols
, rows
;
896 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
897 int cursor_cleared
= 0;
901 if (FRAME_GARBAGED_P (f
))
904 /* Express rectangle as four edges, instead of position-and-size. */
908 /* Convert rectangle edges in pixels to edges in chars.
909 Round down for left and top, up for right and bottom. */
910 top
= PIXEL_TO_CHAR_ROW (f
, top
);
911 left
= PIXEL_TO_CHAR_COL (f
, left
);
912 bottom
+= (f
->output_data
.win32
->line_height
- 1);
913 right
+= (FONT_WIDTH (f
->output_data
.win32
->font
) - 1);
914 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
915 right
= PIXEL_TO_CHAR_COL (f
, right
);
917 /* Clip the rectangle to what can be visible. */
922 if (right
> f
->width
)
924 if (bottom
> f
->height
)
927 /* Get size in chars of the rectangle. */
931 /* If rectangle has zero area, return. */
932 if (rows
<= 0) return;
933 if (cols
<= 0) return;
935 /* Turn off the cursor if it is in the rectangle.
936 We will turn it back on afterward. */
937 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
938 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
944 /* Display the text in the rectangle, one text line at a time. */
946 for (y
= top
; y
< bottom
; y
++)
948 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
950 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
954 CHAR_TO_PIXEL_COL (f
, left
),
955 CHAR_TO_PIXEL_ROW (f
, y
),
956 line
, min (cols
, active_frame
->used
[y
] - left
),
957 active_frame
->highlight
[y
], 0);
960 /* Turn the cursor on if we turned it off. */
963 x_display_cursor (f
, 1);
970 x_display_cursor (f
, 1);
974 frame_unhighlight (f
)
977 x_display_cursor (f
, 1);
980 static void win32_frame_rehighlight ();
981 static void x_frame_rehighlight ();
983 /* The focus has changed. Update the frames as necessary to reflect
984 the new situation. Note that we can't change the selected frame
985 here, because the Lisp code we are interrupting might become confused.
986 Each event gets marked with the frame in which it occurred, so the
987 Lisp code can tell when the switch took place by examining the events. */
990 x_new_focus_frame (dpyinfo
, frame
)
991 struct win32_display_info
*dpyinfo
;
994 struct frame
*old_focus
= dpyinfo
->win32_focus_frame
;
995 int events_enqueued
= 0;
997 if (frame
!= dpyinfo
->win32_focus_frame
)
999 /* Set this before calling other routines, so that they see
1000 the correct value of win32_focus_frame. */
1001 dpyinfo
->win32_focus_frame
= frame
;
1003 if (old_focus
&& old_focus
->auto_lower
)
1004 x_lower_frame (old_focus
);
1006 if (dpyinfo
->win32_focus_frame
&& dpyinfo
->win32_focus_frame
->auto_raise
)
1007 pending_autoraise_frame
= dpyinfo
->win32_focus_frame
;
1009 pending_autoraise_frame
= 0;
1012 x_frame_rehighlight (dpyinfo
);
1015 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1018 x_mouse_leave (dpyinfo
)
1019 struct win32_display_info
*dpyinfo
;
1021 x_new_focus_frame (dpyinfo
, dpyinfo
->win32_focus_event_frame
);
1024 /* The focus has changed, or we have redirected a frame's focus to
1025 another frame (this happens when a frame uses a surrogate
1026 minibuffer frame). Shift the highlight as appropriate.
1028 The FRAME argument doesn't necessarily have anything to do with which
1029 frame is being highlighted or unhighlighted; we only use it to find
1030 the appropriate display info. */
1032 win32_frame_rehighlight (frame
)
1033 struct frame
*frame
;
1035 x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame
));
1039 x_frame_rehighlight (dpyinfo
)
1040 struct win32_display_info
*dpyinfo
;
1042 struct frame
*old_highlight
= dpyinfo
->win32_highlight_frame
;
1044 if (dpyinfo
->win32_focus_frame
)
1046 dpyinfo
->win32_highlight_frame
1047 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
)))
1048 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
))
1049 : dpyinfo
->win32_focus_frame
);
1050 if (! FRAME_LIVE_P (dpyinfo
->win32_highlight_frame
))
1052 FRAME_FOCUS_FRAME (dpyinfo
->win32_focus_frame
) = Qnil
;
1053 dpyinfo
->win32_highlight_frame
= dpyinfo
->win32_focus_frame
;
1057 dpyinfo
->win32_highlight_frame
= 0;
1059 if (dpyinfo
->win32_highlight_frame
!= old_highlight
)
1062 frame_unhighlight (old_highlight
);
1063 if (dpyinfo
->win32_highlight_frame
)
1064 frame_highlight (dpyinfo
->win32_highlight_frame
);
1068 /* Keyboard processing - modifier keys, etc. */
1070 /* Convert a keysym to its name. */
1073 x_get_keysym_name (keysym
)
1076 /* Make static so we can always return it */
1077 static char value
[100];
1080 GetKeyNameText(keysym
, value
, 100);
1086 /* Mouse clicks and mouse movement. Rah. */
1088 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1089 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1090 that the glyph at X, Y occupies, if BOUNDS != 0.
1091 If NOCLIP is nonzero, do not force the value into range. */
1094 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1096 register int pix_x
, pix_y
;
1097 register int *x
, *y
;
1101 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1102 even for negative values. */
1104 pix_x
-= FONT_WIDTH ((f
)->output_data
.win32
->font
) - 1;
1106 pix_y
-= (f
)->output_data
.win32
->line_height
- 1;
1108 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1109 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1113 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1114 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1115 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.win32
->font
) - 1;
1116 bounds
->bottom
= bounds
->top
+ f
->output_data
.win32
->line_height
- 1;
1123 else if (pix_x
> f
->width
)
1128 else if (pix_y
> f
->height
)
1137 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1140 register int *pix_x
, *pix_y
;
1142 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1143 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1147 parse_button (message
, pbutton
, pup
)
1157 case WM_LBUTTONDOWN
:
1165 case WM_MBUTTONDOWN
:
1173 case WM_RBUTTONDOWN
:
1186 if (pbutton
) *pbutton
= button
;
1192 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1194 If the event is a button press, then note that we have grabbed
1198 construct_mouse_click (result
, msg
, f
)
1199 struct input_event
*result
;
1206 parse_button (msg
->msg
.message
, &button
, &up
);
1208 /* Make the event type no_event; we'll change that when we decide
1210 result
->kind
= mouse_click
;
1211 result
->code
= button
;
1212 result
->timestamp
= msg
->msg
.time
;
1213 result
->modifiers
= (msg
->dwModifiers
1221 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1222 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1223 XSETFRAME (result
->frame_or_window
, f
);
1228 /* Function to report a mouse movement to the mainstream Emacs code.
1229 The input handler calls this.
1231 We have received a mouse movement event, which is given in *event.
1232 If the mouse is over a different glyph than it was last time, tell
1233 the mainstream emacs code by setting mouse_moved. If not, ask for
1234 another motion event, so we can check again the next time it moves. */
1237 note_mouse_movement (frame
, msg
)
1241 last_mouse_movement_time
= msg
->time
;
1243 if (msg
->hwnd
!= FRAME_WIN32_WINDOW (frame
))
1245 frame
->mouse_moved
= 1;
1246 last_mouse_scroll_bar
= Qnil
;
1248 note_mouse_highlight (frame
, -1, -1);
1251 /* Has the mouse moved off the glyph it was on at the last sighting? */
1252 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1253 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1254 || HIWORD (msg
->lParam
) < last_mouse_glyph
.left
1255 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1257 frame
->mouse_moved
= 1;
1258 last_mouse_scroll_bar
= Qnil
;
1260 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1264 /* This is used for debugging, to turn off note_mouse_highlight. */
1265 static int disable_mouse_highlight
;
1267 /* Take proper action when the mouse has moved to position X, Y on frame F
1268 as regards highlighting characters that have mouse-face properties.
1269 Also dehighlighting chars where the mouse was before.
1270 X and Y can be negative or out of range. */
1273 note_mouse_highlight (f
, x
, y
)
1277 int row
, column
, portion
;
1282 if (disable_mouse_highlight
)
1285 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1286 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1287 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1289 if (FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_defer
)
1294 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1298 /* Find out which glyph the mouse is on. */
1299 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1300 &new_glyph
, FRAME_WIN32_DISPLAY_INFO (f
)->grabbed
);
1302 /* Which window is that in? */
1303 window
= window_from_coordinates (f
, column
, row
, &portion
);
1304 w
= XWINDOW (window
);
1306 /* If we were displaying active text in another window, clear that. */
1307 if (! EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
))
1308 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1310 /* Are we in a window whose display is up to date?
1311 And verify the buffer's text has not changed. */
1312 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1313 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1314 && EQ (w
->window_end_valid
, w
->buffer
)
1315 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
)))
1317 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1320 /* Find which buffer position the mouse corresponds to. */
1321 for (i
= column
; i
>= 0; i
--)
1325 /* Is it outside the displayed active region (if any)? */
1327 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1328 else if (! (EQ (window
, FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
)
1329 && row
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1330 && row
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1331 && (row
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1332 || column
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1333 && (row
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1334 || column
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1335 || FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1337 Lisp_Object mouse_face
, overlay
, position
;
1338 Lisp_Object
*overlay_vec
;
1339 int len
, noverlays
, ignor1
;
1340 struct buffer
*obuf
;
1343 /* If we get an out-of-range value, return now; avoid an error. */
1344 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1347 /* Make the window's buffer temporarily current for
1348 overlays_at and compute_char_face. */
1349 obuf
= current_buffer
;
1350 current_buffer
= XBUFFER (w
->buffer
);
1356 /* Yes. Clear the display of the old active region, if any. */
1357 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
1359 /* Is this char mouse-active? */
1360 XSETINT (position
, pos
);
1363 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1365 /* Put all the overlays we want in a vector in overlay_vec.
1366 Store the length in len. */
1367 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1369 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1371 /* Find the highest priority overlay that has a mouse-face prop. */
1373 for (i
= 0; i
< noverlays
; i
++)
1375 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1376 if (!NILP (mouse_face
))
1378 overlay
= overlay_vec
[i
];
1383 /* If no overlay applies, get a text property. */
1385 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1387 /* Handle the overlay case. */
1388 if (! NILP (overlay
))
1390 /* Find the range of text around this char that
1391 should be active. */
1392 Lisp_Object before
, after
;
1395 before
= Foverlay_start (overlay
);
1396 after
= Foverlay_end (overlay
);
1397 /* Record this as the current active region. */
1398 fast_find_position (window
, before
,
1399 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1400 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1401 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1402 = !fast_find_position (window
, after
,
1403 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1404 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1405 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1406 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1407 = compute_char_face (f
, w
, pos
, 0, 0,
1408 &ignore
, pos
+ 1, 1);
1410 /* Display it as active. */
1411 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1413 /* Handle the text property case. */
1414 else if (! NILP (mouse_face
))
1416 /* Find the range of text around this char that
1417 should be active. */
1418 Lisp_Object before
, after
, beginning
, end
;
1421 beginning
= Fmarker_position (w
->start
);
1422 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1423 - XFASTINT (w
->window_end_pos
)));
1425 = Fprevious_single_property_change (make_number (pos
+ 1),
1427 w
->buffer
, beginning
);
1429 = Fnext_single_property_change (position
, Qmouse_face
,
1431 /* Record this as the current active region. */
1432 fast_find_position (window
, before
,
1433 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1434 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1435 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_past_end
1436 = !fast_find_position (window
, after
,
1437 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1438 &FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1439 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1440 FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_face_id
1441 = compute_char_face (f
, w
, pos
, 0, 0,
1442 &ignore
, pos
+ 1, 1);
1444 /* Display it as active. */
1445 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
), 1);
1449 current_buffer
= obuf
;
1454 /* Find the row and column of position POS in window WINDOW.
1455 Store them in *COLUMNP and *ROWP.
1456 This assumes display in WINDOW is up to date.
1457 If POS is above start of WINDOW, return coords
1458 of start of first screen line.
1459 If POS is after end of WINDOW, return coords of end of last screen line.
1461 Value is 1 if POS is in range, 0 if it was off screen. */
1464 fast_find_position (window
, pos
, columnp
, rowp
)
1467 int *columnp
, *rowp
;
1469 struct window
*w
= XWINDOW (window
);
1470 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1475 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1476 int width
= window_internal_width (w
);
1479 int maybe_next_line
= 0;
1481 /* Find the right row. */
1486 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1487 if (linestart
> pos
)
1489 /* If the position sought is the end of the buffer,
1490 don't include the blank lines at the bottom of the window. */
1491 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1493 maybe_next_line
= 1;
1500 /* Find the right column with in it. */
1501 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1503 for (i
= 0; i
< width
; i
++)
1505 if (charstarts
[left
+ i
] == pos
)
1508 *columnp
= i
+ left
;
1511 else if (charstarts
[left
+ i
] > pos
)
1513 else if (charstarts
[left
+ i
] > 0)
1517 /* If we're looking for the end of the buffer,
1518 and we didn't find it in the line we scanned,
1519 use the start of the following line. */
1520 if (maybe_next_line
)
1531 /* Display the active region described by mouse_face_*
1532 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1535 show_mouse_face (dpyinfo
, hl
)
1536 struct win32_display_info
*dpyinfo
;
1539 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1540 int width
= window_internal_width (w
);
1541 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1544 int old_curs_x
= curs_x
;
1545 int old_curs_y
= curs_y
;
1547 /* Set these variables temporarily
1548 so that if we have to turn the cursor off and on again
1549 we will put it back at the same place. */
1550 curs_x
= f
->phys_cursor_x
;
1551 curs_y
= f
->phys_cursor_y
;
1553 for (i
= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1554 i
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1556 int column
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
1557 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
1559 int endcolumn
= (i
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
1560 ? FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
1562 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1564 /* If the cursor's in the text we are about to rewrite,
1565 turn the cursor off. */
1567 && curs_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
- 1
1568 && curs_x
<= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
)
1570 x_display_cursor (f
, 0);
1575 CHAR_TO_PIXEL_COL (f
, column
),
1576 CHAR_TO_PIXEL_ROW (f
, i
),
1577 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1579 /* Highlight with mouse face if hl > 0. */
1583 /* If we turned the cursor off, turn it back on. */
1585 x_display_cursor (f
, 1);
1587 curs_x
= old_curs_x
;
1588 curs_y
= old_curs_y
;
1590 /* Change the mouse cursor according to the value of HL. */
1592 SetCursor (f
->output_data
.win32
->cross_cursor
);
1594 SetCursor (f
->output_data
.win32
->text_cursor
);
1597 /* Clear out the mouse-highlighted active region.
1598 Redraw it unhighlighted first. */
1601 clear_mouse_face (dpyinfo
)
1602 struct win32_display_info
*dpyinfo
;
1604 if (! NILP (dpyinfo
->mouse_face_window
))
1605 show_mouse_face (dpyinfo
, 0);
1607 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1608 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1609 dpyinfo
->mouse_face_window
= Qnil
;
1612 struct scroll_bar
*x_window_to_scroll_bar ();
1613 static void x_scroll_bar_report_motion ();
1615 /* Return the current position of the mouse.
1616 *fp should be a frame which indicates which display to ask about.
1618 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1619 and *part to the frame, window, and scroll bar part that the mouse
1620 is over. Set *x and *y to the portion and whole of the mouse's
1621 position on the scroll bar.
1623 If the mouse movement started elsewhere, set *fp to the frame the
1624 mouse is on, *bar_window to nil, and *x and *y to the character cell
1627 Set *time to the server timestamp for the time at which the mouse
1628 was at this position.
1630 Don't store anything if we don't have a valid set of values to report.
1632 This clears the mouse_moved flag, so we can wait for the next mouse
1633 movement. This also calls XQueryPointer, which will cause the
1634 server to give us another MotionNotify when the mouse moves
1638 win32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1641 Lisp_Object
*bar_window
;
1642 enum scroll_bar_part
*part
;
1644 unsigned long *time
;
1650 if (! NILP (last_mouse_scroll_bar
))
1651 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1656 Lisp_Object frame
, tail
;
1658 /* Clear the mouse-moved flag for every frame on this display. */
1659 FOR_EACH_FRAME (tail
, frame
)
1660 XFRAME (frame
)->mouse_moved
= 0;
1662 last_mouse_scroll_bar
= Qnil
;
1666 /* Now we have a position on the root; find the innermost window
1667 containing the pointer. */
1669 if (FRAME_WIN32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1670 && FRAME_LIVE_P (last_mouse_frame
))
1672 f1
= last_mouse_frame
;
1676 /* Is win one of our frames? */
1677 f1
= x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1680 /* If not, is it one of our scroll bars? */
1683 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1687 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1691 if (f1
== 0 && insist
)
1692 f1
= selected_frame
;
1696 int ignore1
, ignore2
;
1698 ScreenToClient (FRAME_WIN32_WINDOW (f1
), &pt
);
1700 /* Ok, we found a frame. Store all the values. */
1702 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1704 FRAME_WIN32_DISPLAY_INFO (f1
)->grabbed
1712 *time
= last_mouse_movement_time
;
1720 /* Scroll bar support. */
1722 /* Given an window ID, find the struct scroll_bar which manages it.
1723 This can be called in GC, so we have to make sure to strip off mark
1726 x_window_to_scroll_bar (window_id
)
1729 Lisp_Object tail
, frame
;
1731 for (tail
= Vframe_list
;
1732 XGCTYPE (tail
) == Lisp_Cons
;
1733 tail
= XCONS (tail
)->cdr
)
1735 Lisp_Object frame
, bar
, condemned
;
1737 frame
= XCONS (tail
)->car
;
1738 /* All elements of Vframe_list should be frames. */
1739 if (! GC_FRAMEP (frame
))
1742 /* Scan this frame's scroll bar list for a scroll bar with the
1744 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1745 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1746 /* This trick allows us to search both the ordinary and
1747 condemned scroll bar lists with one loop. */
1748 ! GC_NILP (bar
) || (bar
= condemned
,
1751 bar
= XSCROLL_BAR (bar
)->next
)
1752 if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1753 return XSCROLL_BAR (bar
);
1760 my_create_scrollbar (f
, bar
)
1762 struct scroll_bar
* bar
;
1766 PostThreadMessage (dwWinThreadId
, WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1768 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
1770 return ((HWND
) msg
.wParam
);
1774 my_destroy_window (f
, hwnd
)
1778 SendMessage (FRAME_WIN32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
1782 /* Open a new window to serve as a scroll bar, and return the
1783 scroll bar vector for it. */
1784 static struct scroll_bar
*
1785 x_scroll_bar_create (window
, top
, left
, width
, height
)
1786 struct window
*window
;
1787 int top
, left
, width
, height
;
1789 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1790 struct scroll_bar
*bar
1791 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1796 XSETWINDOW (bar
->window
, window
);
1797 XSETINT (bar
->top
, top
);
1798 XSETINT (bar
->left
, left
);
1799 XSETINT (bar
->width
, width
);
1800 XSETINT (bar
->height
, height
);
1801 XSETINT (bar
->start
, 0);
1802 XSETINT (bar
->end
, 0);
1803 bar
->dragging
= Qnil
;
1805 /* Requires geometry to be set before call to create the real window */
1807 hwnd
= my_create_scrollbar (f
, bar
);
1809 SetScrollRange (hwnd
, SB_CTL
, 0, height
, FALSE
);
1810 SetScrollPos (hwnd
, SB_CTL
, 0, TRUE
);
1812 SET_SCROLL_BAR_WIN32_WINDOW (bar
, hwnd
);
1814 /* Add bar to its frame's list of scroll bars. */
1815 bar
->next
= FRAME_SCROLL_BARS (f
);
1817 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
1818 if (! NILP (bar
->next
))
1819 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
1826 /* Draw BAR's handle in the proper position.
1827 If the handle is already drawn from START to END, don't bother
1828 redrawing it, unless REBUILD is non-zero; in that case, always
1829 redraw it. (REBUILD is handy for drawing the handle after expose
1832 Normally, we want to constrain the start and end of the handle to
1833 fit inside its rectangle, but if the user is dragging the scroll bar
1834 handle, we want to let them drag it down all the way, so that the
1835 bar's top is as far down as it goes; otherwise, there's no way to
1836 move to the very end of the buffer. */
1838 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1839 struct scroll_bar
*bar
;
1843 int dragging
= ! NILP (bar
->dragging
);
1844 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1845 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1847 /* If the display is already accurate, do nothing. */
1849 && start
== XINT (bar
->start
)
1850 && end
== XINT (bar
->end
))
1855 /* Store the adjusted setting in the scroll bar. */
1856 XSETINT (bar
->start
, start
);
1857 XSETINT (bar
->end
, end
);
1859 /* If we are less than half of the page use start otherwise use end */
1861 SetScrollPos (w
, SB_CTL
, ((start
>> 1) < bar
->height
)?start
:end
, TRUE
);
1866 /* Move a scroll bar around on the screen, to accommodate changing
1867 window configurations. */
1869 x_scroll_bar_move (bar
, top
, left
, width
, height
)
1870 struct scroll_bar
*bar
;
1871 int top
, left
, width
, height
;
1873 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
1874 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1878 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
1879 SetScrollRange (w
, SB_CTL
, 0, height
, FALSE
);
1881 XSETINT (bar
->left
, left
);
1882 XSETINT (bar
->top
, top
);
1883 XSETINT (bar
->width
, width
);
1884 XSETINT (bar
->height
, height
);
1889 /* Destroy the window for BAR, and set its Emacs window's scroll bar
1892 x_scroll_bar_remove (bar
)
1893 struct scroll_bar
*bar
;
1895 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1899 /* Destroy the window. */
1900 my_destroy_window (f
, SCROLL_BAR_WIN32_WINDOW (bar
));
1902 /* Disassociate this scroll bar from its window. */
1903 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
1908 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1909 that we are displaying PORTION characters out of a total of WHOLE
1910 characters, starting at POSITION. If WINDOW has no scroll bar,
1913 win32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
1914 struct window
*window
;
1915 int portion
, whole
, position
;
1917 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1918 int top
= XINT (window
->top
);
1919 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
1920 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
1922 /* Where should this scroll bar be, pixelwise? */
1923 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
1924 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
1926 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
1927 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
1928 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
1929 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
1931 struct scroll_bar
*bar
;
1933 /* Does the scroll bar exist yet? */
1934 if (NILP (window
->vertical_scroll_bar
))
1935 bar
= x_scroll_bar_create (window
,
1936 pixel_top
, pixel_left
,
1937 pixel_width
, pixel_height
);
1940 /* It may just need to be moved and resized. */
1941 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
1942 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
1945 /* Set the scroll bar's current state, unless we're currently being
1947 if (NILP (bar
->dragging
))
1949 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
1952 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
1955 int start
= (int) (((double) position
* top_range
) / whole
);
1956 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
1958 x_scroll_bar_set_handle (bar
, start
, end
, 0);
1962 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
1966 /* The following three hooks are used when we're doing a thorough
1967 redisplay of the frame. We don't explicitly know which scroll bars
1968 are going to be deleted, because keeping track of when windows go
1969 away is a real pain - "Can you say set-window-configuration, boys
1970 and girls?" Instead, we just assert at the beginning of redisplay
1971 that *all* scroll bars are to be removed, and then save a scroll bar
1972 from the fiery pit when we actually redisplay its window. */
1974 /* Arrange for all scroll bars on FRAME to be removed at the next call
1975 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
1976 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
1978 win32_condemn_scroll_bars (frame
)
1981 /* The condemned list should be empty at this point; if it's not,
1982 then the rest of Emacs isn't using the condemn/redeem/judge
1983 protocol correctly. */
1984 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
1987 /* Move them all to the "condemned" list. */
1988 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
1989 FRAME_SCROLL_BARS (frame
) = Qnil
;
1992 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
1993 Note that WINDOW isn't necessarily condemned at all. */
1995 win32_redeem_scroll_bar (window
)
1996 struct window
*window
;
1998 struct scroll_bar
*bar
;
2000 /* We can't redeem this window's scroll bar if it doesn't have one. */
2001 if (NILP (window
->vertical_scroll_bar
))
2004 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2006 /* Unlink it from the condemned list. */
2008 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2010 if (NILP (bar
->prev
))
2012 /* If the prev pointer is nil, it must be the first in one of
2014 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2015 /* It's not condemned. Everything's fine. */
2017 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2018 window
->vertical_scroll_bar
))
2019 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2021 /* If its prev pointer is nil, it must be at the front of
2022 one or the other! */
2026 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2028 if (! NILP (bar
->next
))
2029 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2031 bar
->next
= FRAME_SCROLL_BARS (f
);
2033 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2034 if (! NILP (bar
->next
))
2035 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2039 /* Remove all scroll bars on FRAME that haven't been saved since the
2040 last call to `*condemn_scroll_bars_hook'. */
2042 win32_judge_scroll_bars (f
)
2045 Lisp_Object bar
, next
;
2047 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2049 /* Clear out the condemned list now so we won't try to process any
2050 more events on the hapless scroll bars. */
2051 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2053 for (; ! NILP (bar
); bar
= next
)
2055 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2057 x_scroll_bar_remove (b
);
2060 b
->next
= b
->prev
= Qnil
;
2063 /* Now there should be no references to the condemned scroll bars,
2064 and they should get garbage-collected. */
2067 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2068 is set to something other than no_event, it is enqueued.
2070 This may be called from a signal handler, so we have to ignore GC
2073 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2074 struct scroll_bar
*bar
;
2076 struct input_event
*emacs_event
;
2078 if (! GC_WINDOWP (bar
->window
))
2081 emacs_event
->kind
= scroll_bar_click
;
2082 emacs_event
->code
= 0;
2083 emacs_event
->modifiers
= (msg
->dwModifiers
2084 | ((LOWORD (msg
->msg
.wParam
) == SB_ENDSCROLL
)
2087 emacs_event
->frame_or_window
= bar
->window
;
2088 emacs_event
->timestamp
= msg
->msg
.time
;
2092 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar
->height
));
2094 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2095 int y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2097 switch (LOWORD (msg
->msg
.wParam
))
2099 case SB_THUMBPOSITION
:
2101 emacs_event
->part
= scroll_bar_handle
;
2102 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2103 y
= HIWORD (msg
->msg
.wParam
);
2106 emacs_event
->part
= scroll_bar_handle
;
2107 if (y
< top_range
) y
++;
2110 emacs_event
->part
= scroll_bar_handle
;
2114 emacs_event
->part
= scroll_bar_above_handle
;
2117 emacs_event
->part
= scroll_bar_below_handle
;
2120 emacs_event
->part
= scroll_bar_handle
;
2124 emacs_event
->part
= scroll_bar_handle
;
2128 emacs_event
->part
= scroll_bar_handle
;
2129 x_scroll_bar_set_handle (bar
, y
, y
, 0);
2132 emacs_event
->part
= scroll_bar_handle
;
2136 XSETINT (emacs_event
->x
, y
);
2137 XSETINT (emacs_event
->y
, top_range
);
2141 /* Return information to the user about the current position of the mouse
2142 on the scroll bar. */
2144 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2146 Lisp_Object
*bar_window
;
2147 enum scroll_bar_part
*part
;
2149 unsigned long *time
;
2151 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2152 Window w
= SCROLL_BAR_WIN32_WINDOW (bar
);
2153 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2159 *bar_window
= bar
->window
;
2161 pos
= GetScrollPos (w
, SB_CTL
);
2163 switch (LOWORD (last_mouse_scroll_bar_pos
))
2165 case SB_THUMBPOSITION
:
2167 *part
= scroll_bar_handle
;
2168 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2169 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2172 *part
= scroll_bar_handle
;
2176 *part
= scroll_bar_handle
;
2181 XSETINT(*y
, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)));
2184 last_mouse_scroll_bar
= Qnil
;
2186 *time
= last_mouse_movement_time
;
2191 /* The screen has been cleared so we may have changed foreground or
2192 background colors, and the scroll bars may need to be redrawn.
2193 Clear out the scroll bars, and ask for expose events, so we can
2196 x_scroll_bar_clear (f
)
2202 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2203 bar
= XSCROLL_BAR (bar
)->next
)
2204 UpdateWindow (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar
)));
2209 /* The main Win32 event-reading loop - w32_read_socket. */
2211 /* Timestamp of enter window event. This is only used by w32_read_socket,
2212 but we have to put it out here, since static variables within functions
2213 sometimes don't work. */
2214 static Time enter_timestamp
;
2216 /* Record the last 100 characters stored
2217 to help debug the loss-of-chars-during-GC problem. */
2219 short temp_buffer
[100];
2221 /* Read events coming from the Win32 shell.
2222 This routine is called by the SIGIO handler.
2223 We return as soon as there are no more events to be read.
2225 Events representing keys are stored in buffer BUFP,
2226 which can hold up to NUMCHARS characters.
2227 We return the number of characters stored into the buffer,
2228 thus pretending to be `read'.
2230 WAITP is nonzero if we should block until input arrives.
2231 EXPECTED is nonzero if the caller knows input is available.
2233 Some of these messages are reposted back to the message queue since the
2234 system calls the winproc directly in a context where we cannot return the
2235 data nor can we guarantee the state we are in. So if we dispatch them
2236 we will get into an infinite loop. To prevent this from ever happening we
2237 will set a variable to indicate we are in the read_socket call and indicate
2238 which message we are processing since the winproc gets called recursively with different
2239 messages by the system.
2243 w32_read_socket (sd
, bufp
, numchars
, waitp
, expected
)
2245 register struct input_event
*bufp
;
2246 register int numchars
;
2252 int items_pending
; /* How many items are in the X queue. */
2255 int event_found
= 0;
2258 struct win32_display_info
*dpyinfo
= &one_win32_display_info
;
2260 if (interrupt_input_blocked
)
2262 interrupt_input_pending
= 1;
2266 interrupt_input_pending
= 0;
2269 /* So people can tell when we have read the available input. */
2270 input_signal_count
++;
2273 abort (); /* Don't think this happens. */
2275 while (get_next_msg (&msg
, 0))
2277 switch (msg
.msg
.message
)
2280 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2283 win32_clear_rect (f
, NULL
, &msg
.rect
);
2288 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2292 if (f
->async_visible
== 0)
2294 f
->async_visible
= 1;
2295 f
->async_iconified
= 0;
2296 SET_FRAME_GARBAGED (f
);
2303 msg
.rect
.right
-msg
.rect
.left
+1,
2304 msg
.rect
.bottom
-msg
.rect
.top
+1);
2313 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2315 if (f
&& !f
->iconified
)
2317 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2319 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2320 bufp
->kind
= non_ascii_keystroke
;
2321 bufp
->code
= msg
.msg
.wParam
;
2322 bufp
->modifiers
= msg
.dwModifiers
;
2323 XSETFRAME (bufp
->frame_or_window
, f
);
2324 bufp
->timestamp
= msg
.msg
.time
;
2332 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2334 if (f
&& !f
->iconified
)
2338 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2340 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2341 bufp
->kind
= ascii_keystroke
;
2342 bufp
->code
= msg
.msg
.wParam
;
2343 XSETFRAME (bufp
->frame_or_window
, f
);
2344 bufp
->modifiers
= msg
.dwModifiers
;
2345 bufp
->timestamp
= msg
.msg
.time
;
2357 if (dpyinfo
->grabbed
&& last_mouse_frame
2358 && FRAME_LIVE_P (last_mouse_frame
))
2359 f
= last_mouse_frame
;
2361 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2364 note_mouse_movement (f
, &msg
.msg
);
2366 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f
));
2369 case WM_LBUTTONDOWN
:
2371 case WM_MBUTTONDOWN
:
2373 case WM_RBUTTONDOWN
:
2379 if (dpyinfo
->grabbed
&& last_mouse_frame
2380 && FRAME_LIVE_P (last_mouse_frame
))
2381 f
= last_mouse_frame
;
2383 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2387 if ((!dpyinfo
->win32_focus_frame
|| f
== dpyinfo
->win32_focus_frame
)
2390 construct_mouse_click (bufp
, &msg
, f
);
2397 parse_button (msg
.msg
.message
, &button
, &up
);
2401 dpyinfo
->grabbed
&= ~ (1 << button
);
2405 dpyinfo
->grabbed
|= (1 << button
);
2406 last_mouse_frame
= f
;
2413 struct scroll_bar
*bar
= x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2415 if (bar
&& numchars
>= 1)
2417 x_scroll_bar_handle_click (bar
, &msg
, bufp
);
2426 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2428 if (f
&& !f
->async_iconified
)
2430 f
->output_data
.win32
->left_pos
= LOWORD (msg
.msg
.lParam
);
2431 f
->output_data
.win32
->top_pos
= HIWORD (msg
.msg
.lParam
);
2436 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2438 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2446 GetClientRect(msg
.msg
.hwnd
, &rect
);
2448 height
= rect
.bottom
- rect
.top
+ 1;
2449 width
= rect
.right
- rect
.left
+ 1;
2451 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2452 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2454 /* Even if the number of character rows and columns has
2455 not changed, the font size may have changed, so we need
2456 to check the pixel dimensions as well. */
2458 if (columns
!= f
->width
2459 || rows
!= f
->height
2460 || width
!= f
->output_data
.win32
->pixel_width
2461 || height
!= f
->output_data
.win32
->pixel_height
)
2463 /* I had set this to 0, 0 - I am not sure why?? */
2465 change_frame_size (f
, rows
, columns
, 0, 1);
2466 SET_FRAME_GARBAGED (f
);
2468 f
->output_data
.win32
->pixel_width
= width
;
2469 f
->output_data
.win32
->pixel_height
= height
;
2470 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
2477 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2479 if (msg
.msg
.message
== WM_SETFOCUS
)
2481 x_new_focus_frame (dpyinfo
, f
);
2483 else if (f
== dpyinfo
->win32_focus_frame
)
2484 x_new_focus_frame (dpyinfo
, 0);
2488 switch (msg
.msg
.wParam
)
2491 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2498 bufp
->kind
= delete_window_event
;
2499 XSETFRAME (bufp
->frame_or_window
, f
);
2507 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2511 f
->async_visible
= 1;
2512 f
->async_iconified
= 1;
2514 bufp
->kind
= iconify_event
;
2515 XSETFRAME (bufp
->frame_or_window
, f
);
2524 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2528 f
->async_visible
= 1;
2529 f
->async_iconified
= 0;
2531 /* wait_reading_process_input will notice this and update
2532 the frame's display structures. */
2533 SET_FRAME_GARBAGED (f
);
2537 bufp
->kind
= deiconify_event
;
2538 XSETFRAME (bufp
->frame_or_window
, f
);
2544 /* Force a redisplay sooner or later
2545 to update the frame titles
2546 in case this is the second frame. */
2547 record_asynch_buffer_change ();
2555 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2562 bufp
->kind
= delete_window_event
;
2563 XSETFRAME (bufp
->frame_or_window
, f
);
2571 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2575 if (msg
.msg
.lParam
== 0)
2577 /* Came from window menu */
2579 extern Lisp_Object
get_frame_menubar_event ();
2580 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
2581 struct input_event buf
;
2584 XSETFRAME (frame
, f
);
2585 buf
.kind
= menu_bar_event
;
2587 /* Store initial menu bar event */
2591 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
2592 kbd_buffer_store_event (&buf
);
2595 /* Enqueue the events */
2597 while (!NILP (event
))
2599 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
2600 kbd_buffer_store_event (&buf
);
2601 event
= XCONS (event
)->cdr
;
2606 /* Came from popup menu */
2613 /* If the focus was just given to an autoraising frame,
2615 /* ??? This ought to be able to handle more than one such frame. */
2616 if (pending_autoraise_frame
)
2618 x_raise_frame (pending_autoraise_frame
);
2619 pending_autoraise_frame
= 0;
2626 /* Drawing the cursor. */
2629 /* Draw a hollow box cursor. Don't change the inside of the box. */
2639 hdc
= my_get_dc (FRAME_WIN32_WINDOW (f
));
2641 hb
= CreateSolidBrush (f
->output_data
.win32
->cursor_pixel
);
2643 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
2644 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
2645 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.win32
->font
) - 1;
2646 rect
.bottom
= rect
.top
+ f
->output_data
.win32
->line_height
- 1;
2653 FrameRect (hdc
, &rect
, hb
);
2657 ReleaseDC (FRAME_WIN32_WINDOW (f
), hdc
);
2660 /* Clear the cursor of frame F to background color,
2661 and mark the cursor as not shown.
2662 This is used when the text where the cursor is
2663 is about to be rewritten. */
2669 if (! FRAME_VISIBLE_P (f
)
2670 || f
->phys_cursor_x
< 0)
2673 x_display_cursor (f
, 0);
2674 f
->phys_cursor_x
= -1;
2677 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2678 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2682 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
2689 CHAR_TO_PIXEL_COL (f
, column
),
2690 CHAR_TO_PIXEL_ROW (f
, row
),
2691 &glyph
, 1, highlight
, 0);
2695 x_display_bar_cursor (f
, on
)
2699 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2701 /* This is pointless on invisible frames, and dangerous on garbaged
2702 frames; in the latter case, the frame may be in the midst of
2703 changing its size, and curs_x and curs_y may be off the frame. */
2704 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2707 if (! on
&& f
->phys_cursor_x
< 0)
2710 /* If we're not updating, then we want to use the current frame's
2711 cursor position, not our local idea of where the cursor ought to be. */
2712 if (f
!= updating_frame
)
2714 curs_x
= FRAME_CURSOR_X (f
);
2715 curs_y
= FRAME_CURSOR_Y (f
);
2718 /* If there is anything wrong with the current cursor state, remove it. */
2719 if (f
->phys_cursor_x
>= 0
2721 || f
->phys_cursor_x
!= curs_x
2722 || f
->phys_cursor_y
!= curs_y
2723 || f
->output_data
.win32
->current_cursor
!= bar_cursor
))
2725 /* Erase the cursor by redrawing the character underneath it. */
2726 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2727 f
->phys_cursor_glyph
,
2728 current_glyphs
->highlight
[f
->phys_cursor_y
]);
2729 f
->phys_cursor_x
= -1;
2732 /* If we now need a cursor in the new place or in the new form, do it so. */
2734 && (f
->phys_cursor_x
< 0
2735 || (f
->output_data
.win32
->current_cursor
!= bar_cursor
)))
2737 f
->phys_cursor_glyph
2738 = ((current_glyphs
->enable
[curs_y
]
2739 && curs_x
< current_glyphs
->used
[curs_y
])
2740 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2742 win32_fill_area (f
, NULL
, f
->output_data
.win32
->cursor_pixel
,
2743 CHAR_TO_PIXEL_COL (f
, curs_x
),
2744 CHAR_TO_PIXEL_ROW (f
, curs_y
),
2745 max (f
->output_data
.win32
->cursor_width
, 1),
2746 f
->output_data
.win32
->line_height
);
2748 f
->phys_cursor_x
= curs_x
;
2749 f
->phys_cursor_y
= curs_y
;
2751 f
->output_data
.win32
->current_cursor
= bar_cursor
;
2756 /* Turn the displayed cursor of frame F on or off according to ON.
2757 If ON is nonzero, where to put the cursor is specified
2758 by F->cursor_x and F->cursor_y. */
2761 x_display_box_cursor (f
, on
)
2765 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2767 /* This is pointless on invisible frames, and dangerous on garbaged
2768 frames; in the latter case, the frame may be in the midst of
2769 changing its size, and curs_x and curs_y may be off the frame. */
2770 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
2773 /* If cursor is off and we want it off, return quickly. */
2774 if (!on
&& f
->phys_cursor_x
< 0)
2777 /* If we're not updating, then we want to use the current frame's
2778 cursor position, not our local idea of where the cursor ought to be. */
2779 if (f
!= updating_frame
)
2781 curs_x
= FRAME_CURSOR_X (f
);
2782 curs_y
= FRAME_CURSOR_Y (f
);
2785 /* If cursor is currently being shown and we don't want it to be
2786 or it is in the wrong place,
2787 or we want a hollow box and it's not so, (pout!)
2789 if (f
->phys_cursor_x
>= 0
2791 || f
->phys_cursor_x
!= curs_x
2792 || f
->phys_cursor_y
!= curs_y
2793 || (f
->output_data
.win32
->current_cursor
!= hollow_box_cursor
2794 && (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
))))
2796 int mouse_face_here
= 0;
2797 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
2799 /* If the cursor is in the mouse face area, redisplay that when
2800 we clear the cursor. */
2801 if (f
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
2803 (f
->phys_cursor_y
> FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2804 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_row
2805 && f
->phys_cursor_x
>= FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
2807 (f
->phys_cursor_y
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2808 || (f
->phys_cursor_y
== FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_row
2809 && f
->phys_cursor_x
< FRAME_WIN32_DISPLAY_INFO (f
)->mouse_face_end_col
))
2810 /* Don't redraw the cursor's spot in mouse face
2811 if it is at the end of a line (on a newline).
2812 The cursor appears there, but mouse highlighting does not. */
2813 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
2814 mouse_face_here
= 1;
2816 /* If the font is not as tall as a whole line,
2817 we must explicitly clear the line's whole height. */
2818 if (FONT_HEIGHT (f
->output_data
.win32
->font
) != f
->output_data
.win32
->line_height
)
2819 win32_clear_area (f
, NULL
,
2820 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
2821 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
2822 FONT_WIDTH (f
->output_data
.win32
->font
),
2823 f
->output_data
.win32
->line_height
);
2824 /* Erase the cursor by redrawing the character underneath it. */
2825 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
2826 f
->phys_cursor_glyph
,
2829 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
2830 f
->phys_cursor_x
= -1;
2833 /* If we want to show a cursor,
2834 or we want a box cursor and it's not so,
2835 write it in the right place. */
2837 && (f
->phys_cursor_x
< 0
2838 || (f
->output_data
.win32
->current_cursor
!= filled_box_cursor
2839 && f
== FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)))
2841 f
->phys_cursor_glyph
2842 = ((current_glyphs
->enable
[curs_y
]
2843 && curs_x
< current_glyphs
->used
[curs_y
])
2844 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
2846 if (f
!= FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
)
2849 f
->output_data
.win32
->current_cursor
= hollow_box_cursor
;
2853 x_draw_single_glyph (f
, curs_y
, curs_x
,
2854 f
->phys_cursor_glyph
, 2);
2855 f
->output_data
.win32
->current_cursor
= filled_box_cursor
;
2858 f
->phys_cursor_x
= curs_x
;
2859 f
->phys_cursor_y
= curs_y
;
2863 x_display_cursor (f
, on
)
2869 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
2870 x_display_box_cursor (f
, on
);
2871 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
2872 x_display_bar_cursor (f
, on
);
2874 /* Those are the only two we have implemented! */
2880 /* Changing the font of the frame. */
2882 /* Give frame F the font named FONTNAME as its default font, and
2883 return the full name of that font. FONTNAME may be a wildcard
2884 pattern; in that case, we choose some font that fits the pattern.
2885 The return value shows which font we chose. */
2888 x_new_font (f
, fontname
)
2890 register char *fontname
;
2893 int n_matching_fonts
;
2894 XFontStruct
*font_info
;
2895 char new_font_name
[101];
2897 /* Get a font which matches this name */
2901 if (!x_to_win32_font(fontname
, &lf
)
2902 || !win32_to_x_font(&lf
, new_font_name
, 100))
2908 /* See if we've already loaded a matching font. */
2909 already_loaded
= -1;
2914 for (i
= 0; i
< FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
; i
++)
2915 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
2918 fontname
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[i
].name
;
2923 /* If we have, just return it from the table. */
2924 if (already_loaded
>= 0)
2925 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
2926 /* Otherwise, load the font and add it to the table. */
2932 font
= win32_load_font(FRAME_WIN32_DISPLAY_INFO (f
), fontname
);
2939 /* Do we need to create the table? */
2940 if (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
== 0)
2942 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
= 16;
2943 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
2944 = (struct font_info
*) xmalloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
2945 * sizeof (struct font_info
));
2947 /* Do we need to grow the table? */
2948 else if (FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
2949 >= FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
)
2951 FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
*= 2;
2952 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
2953 = (struct font_info
*) xrealloc (FRAME_WIN32_DISPLAY_INFO (f
)->font_table
,
2954 (FRAME_WIN32_DISPLAY_INFO (f
)->font_table_size
2955 * sizeof (struct font_info
)));
2958 n_fonts
= FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
;
2959 FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
2960 bcopy (fontname
, FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
2961 f
->output_data
.win32
->font
= FRAME_WIN32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
2962 FRAME_WIN32_DISPLAY_INFO (f
)->n_fonts
++;
2965 /* Compute the scroll bar width in character columns. */
2966 if (f
->scroll_bar_pixel_width
> 0)
2968 int wid
= FONT_WIDTH (f
->output_data
.win32
->font
);
2969 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
2972 f
->scroll_bar_cols
= 2;
2974 /* Now make the frame display the given font. */
2975 if (FRAME_WIN32_WINDOW (f
) != 0)
2977 frame_update_line_height (f
);
2978 x_set_window_size (f
, 0, f
->width
, f
->height
);
2981 /* If we are setting a new frame's font for the first time,
2982 there are no faces yet, so this font's height is the line height. */
2983 f
->output_data
.win32
->line_height
= FONT_HEIGHT (f
->output_data
.win32
->font
);
2986 Lisp_Object lispy_name
;
2988 lispy_name
= build_string (fontname
);
2994 x_calc_absolute_position (f
)
2999 int flags
= f
->output_data
.win32
->size_hint_flags
;
3003 /* Find the position of the outside upper-left corner of
3004 the inner window, with respect to the outer window. */
3005 if (f
->output_data
.win32
->parent_desc
!= FRAME_WIN32_DISPLAY_INFO (f
)->root_window
)
3008 MapWindowPoints (FRAME_WIN32_WINDOW (f
),
3009 f
->output_data
.win32
->parent_desc
,
3016 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3019 AdjustWindowRect(&rt
, f
->output_data
.win32
->dwStyle
,
3020 FRAME_EXTERNAL_MENU_BAR (f
));
3023 pt
.x
+= (rt
.right
- rt
.left
);
3024 pt
.y
+= (rt
.bottom
- rt
.top
);
3027 /* Treat negative positions as relative to the leftmost bottommost
3028 position that fits on the screen. */
3029 if (flags
& XNegative
)
3030 f
->output_data
.win32
->left_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->width
3031 - 2 * f
->output_data
.win32
->border_width
- pt
.x
3033 + f
->output_data
.win32
->left_pos
);
3035 if (flags
& YNegative
)
3036 f
->output_data
.win32
->top_pos
= (FRAME_WIN32_DISPLAY_INFO (f
)->height
3037 - 2 * f
->output_data
.win32
->border_width
- pt
.y
3039 + f
->output_data
.win32
->top_pos
);
3040 /* The left_pos and top_pos
3041 are now relative to the top and left screen edges,
3042 so the flags should correspond. */
3043 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3046 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3047 to really change the position, and 0 when calling from
3048 x_make_frame_visible (in that case, XOFF and YOFF are the current
3049 position values). It is -1 when calling from x_set_frame_parameters,
3050 which means, do adjust for borders but don't change the gravity. */
3052 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3054 register int xoff
, yoff
;
3057 int modified_top
, modified_left
;
3059 if (change_gravity
> 0)
3061 f
->output_data
.win32
->top_pos
= yoff
;
3062 f
->output_data
.win32
->left_pos
= xoff
;
3063 f
->output_data
.win32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3065 f
->output_data
.win32
->size_hint_flags
|= XNegative
;
3067 f
->output_data
.win32
->size_hint_flags
|= YNegative
;
3068 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3070 x_calc_absolute_position (f
);
3073 x_wm_set_size_hint (f
, (long) 0, 0);
3075 /* It is a mystery why we need to add the border_width here
3076 when the frame is already visible, but experiment says we do. */
3077 modified_left
= f
->output_data
.win32
->left_pos
;
3078 modified_top
= f
->output_data
.win32
->top_pos
;
3079 if (change_gravity
!= 0)
3081 modified_left
+= f
->output_data
.win32
->border_width
;
3082 modified_top
+= f
->output_data
.win32
->border_width
;
3085 SetWindowPos (FRAME_WIN32_WINDOW (f
),
3087 modified_left
, modified_top
,
3089 SWP_NOZORDER
| SWP_NOSIZE
);
3093 /* Call this to change the size of frame F's x-window.
3094 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3095 for this size change and subsequent size changes.
3096 Otherwise we leave the window gravity unchanged. */
3098 x_set_window_size (f
, change_gravity
, cols
, rows
)
3103 int pixelwidth
, pixelheight
;
3107 check_frame_size (f
, &rows
, &cols
);
3108 f
->output_data
.win32
->vertical_scroll_bar_extra
3109 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3111 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3112 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3113 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.win32
->font
)));
3114 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3115 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3117 f
->output_data
.win32
->win_gravity
= NorthWestGravity
;
3118 x_wm_set_size_hint (f
, (long) 0, 0);
3123 rect
.left
= rect
.top
= 0;
3124 rect
.right
= pixelwidth
;
3125 rect
.bottom
= pixelheight
;
3127 AdjustWindowRect(&rect
, f
->output_data
.win32
->dwStyle
,
3128 FRAME_EXTERNAL_MENU_BAR (f
));
3130 /* All windows have an extra pixel */
3132 SetWindowPos (FRAME_WIN32_WINDOW (f
),
3135 rect
.right
- rect
.left
+ 1,
3136 rect
.bottom
- rect
.top
+ 1,
3137 SWP_NOZORDER
| SWP_NOMOVE
);
3140 /* Now, strictly speaking, we can't be sure that this is accurate,
3141 but the window manager will get around to dealing with the size
3142 change request eventually, and we'll hear how it went when the
3143 ConfigureNotify event gets here.
3145 We could just not bother storing any of this information here,
3146 and let the ConfigureNotify event set everything up, but that
3147 might be kind of confusing to the lisp code, since size changes
3148 wouldn't be reported in the frame parameters until some random
3149 point in the future when the ConfigureNotify event arrives. */
3150 change_frame_size (f
, rows
, cols
, 0, 0);
3151 PIXEL_WIDTH (f
) = pixelwidth
;
3152 PIXEL_HEIGHT (f
) = pixelheight
;
3154 /* If cursor was outside the new size, mark it as off. */
3155 if (f
->phys_cursor_y
>= rows
3156 || f
->phys_cursor_x
>= cols
)
3158 f
->phys_cursor_x
= -1;
3159 f
->phys_cursor_y
= -1;
3162 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3163 receive in the ConfigureNotify event; if we get what we asked
3164 for, then the event won't cause the screen to become garbaged, so
3165 we have to make sure to do it here. */
3166 SET_FRAME_GARBAGED (f
);
3171 /* Mouse warping. */
3174 x_set_mouse_position (f
, x
, y
)
3180 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.win32
->font
) / 2;
3181 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.win32
->line_height
/ 2;
3183 if (pix_x
< 0) pix_x
= 0;
3184 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3186 if (pix_y
< 0) pix_y
= 0;
3187 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3191 SetCursorPos (pix_x
, pix_y
);
3196 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
3199 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3205 SetCursorPos (pix_x
, pix_y
);
3210 /* focus shifting, raising and lowering. */
3212 x_focus_on_frame (f
)
3222 /* Raise frame F. */
3227 if (f
->async_visible
)
3230 SetWindowPos (FRAME_WIN32_WINDOW (f
),
3233 SWP_NOSIZE
| SWP_NOMOVE
);
3238 /* Lower frame F. */
3243 if (f
->async_visible
)
3246 SetWindowPos (FRAME_WIN32_WINDOW (f
),
3249 SWP_NOSIZE
| SWP_NOMOVE
);
3255 win32_frame_raise_lower (f
, raise
)
3265 /* Change of visibility. */
3267 /* This tries to wait until the frame is really visible.
3268 However, if the window manager asks the user where to position
3269 the frame, this will return before the user finishes doing that.
3270 The frame will not actually be visible at that time,
3271 but it will become visible later when the window manager
3272 finishes with it. */
3274 x_make_frame_visible (f
)
3279 if (! FRAME_VISIBLE_P (f
))
3281 /* We test FRAME_GARBAGED_P here to make sure we don't
3282 call x_set_offset a second time
3283 if we get to x_make_frame_visible a second time
3284 before the window gets really visible. */
3285 if (! FRAME_ICONIFIED_P (f
)
3286 && ! f
->output_data
.win32
->asked_for_visible
)
3287 x_set_offset (f
, f
->output_data
.win32
->left_pos
, f
->output_data
.win32
->top_pos
, 0);
3289 f
->output_data
.win32
->asked_for_visible
= 1;
3291 ShowWindow (FRAME_WIN32_WINDOW (f
), SW_SHOW
);
3294 /* Synchronize to ensure Emacs knows the frame is visible
3295 before we do anything else. We do this loop with input not blocked
3296 so that incoming events are handled. */
3299 int count
= input_signal_count
;
3301 /* This must come after we set COUNT. */
3304 XSETFRAME (frame
, f
);
3308 /* Once we have handled input events,
3309 we should have received the MapNotify if one is coming.
3310 So if we have not got it yet, stop looping.
3311 Some window managers make their own decisions
3312 about visibility. */
3313 if (input_signal_count
!= count
)
3315 /* Machines that do polling rather than SIGIO have been observed
3316 to go into a busy-wait here. So we'll fake an alarm signal
3317 to let the handler know that there's something to be read.
3318 We used to raise a real alarm, but it seems that the handler
3319 isn't always enabled here. This is probably a bug. */
3320 if (input_polling_used ())
3322 /* It could be confusing if a real alarm arrives while processing
3323 the fake one. Turn it off and let the handler reset it. */
3325 input_poll_signal ();
3327 /* Once we have handled input events,
3328 we should have received the MapNotify if one is coming.
3329 So if we have not got it yet, stop looping.
3330 Some window managers make their own decisions
3331 about visibility. */
3332 if (input_signal_count
!= count
)
3335 FRAME_SAMPLE_VISIBILITY (f
);
3339 /* Change from mapped state to withdrawn state. */
3341 /* Make the frame visible (mapped and not iconified). */
3343 x_make_frame_invisible (f
)
3348 /* Don't keep the highlight on an invisible frame. */
3349 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3350 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3354 ShowWindow (FRAME_WIN32_WINDOW (f
), SW_HIDE
);
3356 /* We can't distinguish this from iconification
3357 just by the event that we get from the server.
3358 So we can't win using the usual strategy of letting
3359 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3360 and synchronize with the server to make sure we agree. */
3362 FRAME_ICONIFIED_P (f
) = 0;
3363 f
->async_visible
= 0;
3364 f
->async_iconified
= 0;
3369 /* Change window state from mapped to iconified. */
3371 void x_iconify_frame (f
)
3376 /* Don't keep the highlight on an invisible frame. */
3377 if (FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
== f
)
3378 FRAME_WIN32_DISPLAY_INFO (f
)->win32_highlight_frame
= 0;
3380 if (f
->async_iconified
)
3385 ShowWindow (FRAME_WIN32_WINDOW (f
), SW_SHOWMINIMIZED
);
3387 f
->async_iconified
= 1;
3392 /* Destroy the window of frame F. */
3394 x_destroy_window (f
)
3397 struct win32_display_info
*dpyinfo
= FRAME_WIN32_DISPLAY_INFO (f
);
3401 my_destroy_window (f
, FRAME_WIN32_WINDOW (f
));
3402 free_frame_menubar (f
);
3403 free_frame_faces (f
);
3405 xfree (f
->output_data
.win32
);
3406 f
->output_data
.win32
= 0;
3407 if (f
== dpyinfo
->win32_focus_frame
)
3408 dpyinfo
->win32_focus_frame
= 0;
3409 if (f
== dpyinfo
->win32_focus_event_frame
)
3410 dpyinfo
->win32_focus_event_frame
= 0;
3411 if (f
== dpyinfo
->win32_highlight_frame
)
3412 dpyinfo
->win32_highlight_frame
= 0;
3414 dpyinfo
->reference_count
--;
3416 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3418 dpyinfo
->mouse_face_beg_row
3419 = dpyinfo
->mouse_face_beg_col
= -1;
3420 dpyinfo
->mouse_face_end_row
3421 = dpyinfo
->mouse_face_end_col
= -1;
3422 dpyinfo
->mouse_face_window
= Qnil
;
3428 /* Setting window manager hints. */
3430 /* Set the normal size hints for the window manager, for frame F.
3431 FLAGS is the flags word to use--or 0 meaning preserve the flags
3432 that the window now has.
3433 If USER_POSITION is nonzero, we set the USPosition
3434 flag (this is useful when FLAGS is 0). */
3436 x_wm_set_size_hint (f
, flags
, user_position
)
3441 Window window
= FRAME_WIN32_WINDOW (f
);
3443 flexlines
= f
->height
;
3447 SetWindowLong (window
, WND_X_UNITS_INDEX
, FONT_WIDTH (f
->output_data
.win32
->font
));
3448 SetWindowLong (window
, WND_Y_UNITS_INDEX
, f
->output_data
.win32
->line_height
);
3453 /* Window manager things */
3454 x_wm_set_icon_position (f
, icon_x
, icon_y
)
3459 Window window
= FRAME_WIN32_WINDOW (f
);
3461 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
3462 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
3463 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
3465 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
3470 /* Initialization. */
3472 #ifdef USE_X_TOOLKIT
3473 static XrmOptionDescRec emacs_options
[] = {
3474 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
3475 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
3477 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3478 XrmoptionSepArg
, NULL
},
3479 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
3481 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3482 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3483 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
3484 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3485 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
3486 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
3487 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
3489 #endif /* USE_X_TOOLKIT */
3491 static int win32_initialized
= 0;
3493 struct win32_display_info
*
3494 win32_term_init (display_name
, xrm_option
, resource_name
)
3495 Lisp_Object display_name
;
3497 char *resource_name
;
3501 struct win32_display_info
*dpyinfo
;
3506 if (!win32_initialized
)
3508 win32_initialize ();
3509 win32_initialized
= 1;
3520 argv
[argc
++] = "-xrm";
3521 argv
[argc
++] = xrm_option
;
3525 dpyinfo
= &one_win32_display_info
;
3527 /* Put this display on the chain. */
3528 dpyinfo
->next
= NULL
;
3530 /* Put it on win32_display_name_list as well, to keep them parallel. */
3531 win32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
3532 win32_display_name_list
);
3533 dpyinfo
->name_list_element
= XCONS (win32_display_name_list
)->car
;
3535 dpyinfo
->win32_id_name
3536 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
3537 + XSTRING (Vsystem_name
)->size
3539 sprintf (dpyinfo
->win32_id_name
, "%s@%s",
3540 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
3543 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
3544 resource_name
, EMACS_CLASS
);
3546 /* Put the rdb where we can find it in a way that works on
3548 dpyinfo
->xrdb
= xrdb
;
3550 hdc
= my_get_dc (GetDesktopWindow ());
3552 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
3553 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
3554 dpyinfo
->root_window
= GetDesktopWindow ();
3555 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
3556 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
3557 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
3558 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
3559 dpyinfo
->grabbed
= 0;
3560 dpyinfo
->reference_count
= 0;
3561 dpyinfo
->n_fonts
= 0;
3562 dpyinfo
->font_table_size
= 0;
3563 dpyinfo
->bitmaps
= 0;
3564 dpyinfo
->bitmaps_size
= 0;
3565 dpyinfo
->bitmaps_last
= 0;
3566 dpyinfo
->mouse_face_mouse_frame
= 0;
3567 dpyinfo
->mouse_face_deferred_gc
= 0;
3568 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3569 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3570 dpyinfo
->mouse_face_face_id
= 0;
3571 dpyinfo
->mouse_face_window
= Qnil
;
3572 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
3573 dpyinfo
->mouse_face_defer
= 0;
3574 dpyinfo
->win32_focus_frame
= 0;
3575 dpyinfo
->win32_focus_event_frame
= 0;
3576 dpyinfo
->win32_highlight_frame
= 0;
3578 ReleaseDC (GetDesktopWindow (), hdc
);
3580 #ifndef F_SETOWN_BUG
3582 #ifdef F_SETOWN_SOCK_NEG
3583 /* stdin is a socket here */
3584 fcntl (connection
, F_SETOWN
, -getpid ());
3585 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3586 fcntl (connection
, F_SETOWN
, getpid ());
3587 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3588 #endif /* ! defined (F_SETOWN) */
3589 #endif /* F_SETOWN_BUG */
3592 if (interrupt_input
)
3593 init_sigio (connection
);
3594 #endif /* ! defined (SIGIO) */
3601 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3604 x_delete_display (dpyinfo
)
3605 struct win32_display_info
*dpyinfo
;
3607 /* Discard this display from win32_display_name_list and win32_display_list.
3608 We can't use Fdelq because that can quit. */
3609 if (! NILP (win32_display_name_list
)
3610 && EQ (XCONS (win32_display_name_list
)->car
, dpyinfo
->name_list_element
))
3611 win32_display_name_list
= XCONS (win32_display_name_list
)->cdr
;
3616 tail
= win32_display_name_list
;
3617 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
3619 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
3620 dpyinfo
->name_list_element
))
3622 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
3625 tail
= XCONS (tail
)->cdr
;
3629 xfree (dpyinfo
->font_table
);
3630 xfree (dpyinfo
->win32_id_name
);
3633 /* Set up use of Win32. */
3635 DWORD
win_msg_worker ();
3639 clear_frame_hook
= win32_clear_frame
;
3640 clear_end_of_line_hook
= win32_clear_end_of_line
;
3641 ins_del_lines_hook
= win32_ins_del_lines
;
3642 change_line_highlight_hook
= win32_change_line_highlight
;
3643 insert_glyphs_hook
= win32_insert_glyphs
;
3644 write_glyphs_hook
= win32_write_glyphs
;
3645 delete_glyphs_hook
= win32_delete_glyphs
;
3646 ring_bell_hook
= win32_ring_bell
;
3647 reset_terminal_modes_hook
= win32_reset_terminal_modes
;
3648 set_terminal_modes_hook
= win32_set_terminal_modes
;
3649 update_begin_hook
= win32_update_begin
;
3650 update_end_hook
= win32_update_end
;
3651 set_terminal_window_hook
= win32_set_terminal_window
;
3652 read_socket_hook
= w32_read_socket
;
3653 frame_up_to_date_hook
= win32_frame_up_to_date
;
3654 cursor_to_hook
= win32_cursor_to
;
3655 reassert_line_highlight_hook
= win32_reassert_line_highlight
;
3656 mouse_position_hook
= win32_mouse_position
;
3657 frame_rehighlight_hook
= win32_frame_rehighlight
;
3658 frame_raise_lower_hook
= win32_frame_raise_lower
;
3659 set_vertical_scroll_bar_hook
= win32_set_vertical_scroll_bar
;
3660 condemn_scroll_bars_hook
= win32_condemn_scroll_bars
;
3661 redeem_scroll_bar_hook
= win32_redeem_scroll_bar
;
3662 judge_scroll_bars_hook
= win32_judge_scroll_bars
;
3664 scroll_region_ok
= 1; /* we'll scroll partial frames */
3665 char_ins_del_ok
= 0; /* just as fast to write the line */
3666 line_ins_del_ok
= 1; /* we'll just blt 'em */
3667 fast_clear_end_of_line
= 1; /* X does this well */
3668 memory_below_frame
= 0; /* we don't remember what scrolls
3672 /* Try to use interrupt input; if we can't, then start polling. */
3673 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
3675 /* Create the window thread - it will terminate itself or when the app terminates */
3679 dwMainThreadId
= GetCurrentThreadId ();
3680 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3681 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
3683 /* Wait for thread to start */
3688 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
3690 hWinThread
= CreateThread (NULL
, 0,
3691 (LPTHREAD_START_ROUTINE
) win_msg_worker
,
3692 0, 0, &dwWinThreadId
);
3694 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
3697 /* AttachThreadInput (dwWinThreadId, dwMainThreadId, TRUE); */
3702 syms_of_win32term ()
3704 staticpro (&win32_display_name_list
);
3705 win32_display_name_list
= Qnil
;
3707 staticpro (&last_mouse_scroll_bar
);
3708 last_mouse_scroll_bar
= Qnil
;
3710 staticpro (&Qvendor_specific_keysyms
);
3711 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");