1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Added by Kevin Gallo */
28 #include "blockinput.h"
41 #include "dispextern.h"
42 #include "termhooks.h"
50 #include "intervals.h"
52 extern void free_frame_menubar ();
54 extern Lisp_Object Vwindow_system
;
56 #define x_any_window_to_frame x_window_to_frame
57 #define x_top_window_to_frame x_window_to_frame
60 /* This is display since w32 does not support multiple ones. */
61 struct w32_display_info one_w32_display_info
;
63 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
64 one for each element of w32_display_list and in the same order.
65 NAME is the name of the frame.
66 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
67 Lisp_Object w32_display_name_list
;
69 /* Frame being updated by update_frame. This is declared in term.c.
70 This is set by update_begin and looked at by all the
71 w32 functions. It is zero while not inside an update.
72 In that case, the w32 functions assume that `selected_frame'
73 is the frame to apply to. */
74 extern struct frame
*updating_frame
;
76 /* This is a frame waiting to be autoraised, within w32_read_socket. */
77 struct frame
*pending_autoraise_frame
;
79 /* During an update, maximum vpos for ins/del line operations to affect. */
83 /* During an update, nonzero if chars output now should be highlighted. */
87 /* Nominal cursor position -- where to draw output.
88 During an update, these are different from the cursor-box position. */
93 DWORD dwWindowsThreadId
= 0;
94 HANDLE hWindowsThread
= NULL
;
95 DWORD dwMainThreadId
= 0;
96 HANDLE hMainThread
= NULL
;
99 /* These definitions are new with Windows 95. */
100 #define SIF_RANGE 0x0001
101 #define SIF_PAGE 0x0002
102 #define SIF_POS 0x0004
103 #define SIF_DISABLENOSCROLL 0x0008
104 #define SIF_TRACKPOS 0x0010
105 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
107 typedef struct tagSCROLLINFO
116 } SCROLLINFO
, FAR
*LPSCROLLINFO
;
117 typedef SCROLLINFO CONST FAR
*LPCSCROLLINFO
;
120 /* Dynamic linking to new proportional scroll bar functions. */
121 int (PASCAL
*pfnSetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
, BOOL fRedraw
);
122 BOOL (PASCAL
*pfnGetScrollInfo
) (HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
);
124 int vertical_scroll_bar_min_handle
;
125 int vertical_scroll_bar_top_border
;
126 int vertical_scroll_bar_bottom_border
;
128 int last_scroll_bar_drag_pos
;
130 /* Mouse movement. */
132 /* Where the mouse was last time we reported a mouse event. */
133 static FRAME_PTR last_mouse_frame
;
134 static RECT last_mouse_glyph
;
136 Lisp_Object Vw32_num_mouse_buttons
;
138 Lisp_Object Vw32_swap_mouse_buttons
;
140 /* Control whether x_raise_frame also sets input focus. */
141 Lisp_Object Vw32_grab_focus_on_raise
;
143 /* Control whether Caps Lock affects non-ascii characters. */
144 Lisp_Object Vw32_capslock_is_shiftlock
;
146 /* The scroll bar in which the last motion event occurred.
148 If the last motion event occurred in a scroll bar, we set this
149 so w32_mouse_position can know whether to report a scroll bar motion or
152 If the last motion event didn't occur in a scroll bar, we set this
153 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
154 Lisp_Object last_mouse_scroll_bar
;
155 int last_mouse_scroll_bar_pos
;
157 /* This is a hack. We would really prefer that w32_mouse_position would
158 return the time associated with the position it returns, but there
159 doesn't seem to be any way to wrest the timestamp from the server
160 along with the position query. So, we just keep track of the time
161 of the last movement we received, and return that in hopes that
162 it's somewhat accurate. */
163 Time last_mouse_movement_time
;
165 /* Incremented by w32_read_socket whenever it really tries to read events. */
167 static int volatile input_signal_count
;
169 static int input_signal_count
;
172 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
174 extern Lisp_Object Qface
, Qmouse_face
;
178 /* A mask of extra modifier bits to put into every keyboard char. */
179 extern int extra_keyboard_modifiers
;
181 static Lisp_Object Qvendor_specific_keysyms
;
183 void w32_delete_display ();
185 static void redraw_previous_char ();
186 static void redraw_following_char ();
187 static unsigned int w32_get_modifiers ();
189 static int fast_find_position ();
190 static void note_mouse_highlight ();
191 static void clear_mouse_face ();
192 static void show_mouse_face ();
193 static void do_line_dance ();
195 static int w32_cursor_to ();
196 static int w32_clear_end_of_line ();
199 /* This is a function useful for recording debugging information
200 about the sequence of occurrences in this file. */
208 struct record event_record
[100];
210 int event_record_index
;
212 record_event (locus
, type
)
216 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
217 event_record_index
= 0;
219 event_record
[event_record_index
].locus
= locus
;
220 event_record
[event_record_index
].type
= type
;
221 event_record_index
++;
226 /* Return the struct w32_display_info. */
228 struct w32_display_info
*
229 w32_display_info_for_display ()
231 return (&one_w32_display_info
);
235 w32_fill_rect (f
, _hdc
, pix
, lprect
)
250 hdc
= get_frame_dc (f
);
253 hb
= CreateSolidBrush (pix
);
254 FillRect (hdc
, lprect
, hb
);
258 release_frame_dc (f
, hdc
);
267 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
268 w32_clear_rect (f
, NULL
, &rect
);
272 /* Starting and ending updates.
274 These hooks are called by update_frame at the beginning and end
275 of a frame update. We record in `updating_frame' the identity
276 of the frame being updated, so that the w32_... functions do not
277 need to take a frame as argument. Most of the w32_... functions
278 should never be called except during an update, the only exceptions
279 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
288 flexlines
= f
->height
;
293 /* Regenerate display palette before drawing if list of requested
294 colors has changed. */
295 if (FRAME_W32_DISPLAY_INFO (f
)->regen_palette
)
297 w32_regenerate_palette (f
);
298 FRAME_W32_DISPLAY_INFO (f
)->regen_palette
= FALSE
;
301 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
303 /* Don't do highlighting for mouse motion during the update. */
304 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
306 /* If the frame needs to be redrawn,
307 simply forget about any prior mouse highlighting. */
308 if (FRAME_GARBAGED_P (f
))
309 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
311 if (!NILP (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
313 int firstline
, lastline
, i
;
314 struct window
*w
= XWINDOW (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
);
316 /* Find the first, and the last+1, lines affected by redisplay. */
317 for (firstline
= 0; firstline
< f
->height
; firstline
++)
318 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
321 lastline
= f
->height
;
322 for (i
= f
->height
- 1; i
>= 0; i
--)
324 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
330 /* Can we tell that this update does not affect the window
331 where the mouse highlight is? If so, no need to turn off.
332 Likewise, don't do anything if the frame is garbaged;
333 in that case, the FRAME_CURRENT_GLYPHS that we would use
334 are all wrong, and we will redisplay that line anyway. */
335 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
336 || lastline
< XFASTINT (w
->top
)))
337 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
351 x_display_cursor (f
, 1);
353 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
354 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
359 /* This is called after a redisplay on frame F. */
362 w32_frame_up_to_date (f
)
366 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
367 || f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
369 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
370 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
371 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
372 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
377 /* External interface to control of standout mode.
378 Call this when about to modify line at position VPOS
379 and not change whether it is highlighted. */
381 w32_reassert_line_highlight (new, vpos
)
387 /* Call this when about to modify line at position VPOS
388 and change whether it is highlighted. */
391 w32_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
392 int new_highlight
, vpos
, first_unused_hpos
;
394 highlight
= new_highlight
;
395 w32_cursor_to (vpos
, 0);
396 w32_clear_end_of_line (updating_frame
->width
);
399 /* This is used when starting Emacs and when restarting after suspend.
400 When starting Emacs, no window is mapped. And nothing must be done
401 to Emacs's own window if it is suspended (though that rarely happens). */
404 w32_set_terminal_modes ()
408 /* This is called when exiting or suspending Emacs.
409 Exiting will make the W32 windows go away, and suspending
410 requires no action. */
413 w32_reset_terminal_modes ()
417 /* Set the nominal cursor position of the frame.
418 This is where display update commands will take effect.
419 This does not affect the place where the cursor-box is displayed. */
422 w32_cursor_to (row
, col
)
423 register int row
, col
;
430 if (updating_frame
== 0)
433 x_display_cursor (selected_frame
, 1);
438 /* Display a sequence of N glyphs found at GP.
439 WINDOW is the window to output to. LEFT and TOP are starting coords.
440 HL is 1 if this text is highlighted, 2 if the cursor is on it,
441 3 if should appear in its mouse-face.
442 JUST_FOREGROUND if 1 means draw only the foreground;
443 don't alter the background.
445 FONT is the default font to use (for glyphs whose font-code is 0).
447 Since the display generation code is responsible for calling
448 compute_char_face and compute_glyph_face on everything it puts in
449 the display structure, we can assume that the face code on each
450 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
451 to which we can actually apply intern_face.
452 Call this function with input blocked. */
455 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
)
458 register GLYPH
*gp
; /* Points to first GLYPH. */
459 register int n
; /* Number of glyphs to display. */
463 /* Holds characters to be displayed. */
464 char *buf
= (char *) alloca (f
->width
* sizeof (*buf
));
465 register char *cp
; /* Steps through buf[]. */
466 register int tlen
= GLYPH_TABLE_LENGTH
;
467 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
468 Window window
= FRAME_W32_WINDOW (f
);
469 int orig_left
= left
;
472 hdc
= get_frame_dc (f
);
476 /* Get the face-code of the next GLYPH. */
480 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
481 cf
= FAST_GLYPH_FACE (g
);
483 /* Find the run of consecutive glyphs with the same face-code.
484 Extract their character codes into BUF. */
489 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
490 if (FAST_GLYPH_FACE (g
) != cf
)
493 *cp
++ = FAST_GLYPH_CHAR (g
);
498 /* LEN gets the length of the run. */
501 /* Now output this run of chars, with the font and pixel values
502 determined by the face code CF. */
504 struct face
*face
= FRAME_DEFAULT_FACE (f
);
505 XFontStruct
*font
= FACE_FONT (face
);
510 /* HL = 3 means use a mouse face previously chosen. */
512 cf
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
;
514 /* First look at the face of the text itself. */
517 /* It's possible for the display table to specify
518 a face code that is out of range. Use 0 in that case. */
519 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
520 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
524 face
= FRAME_MODE_LINE_FACE (f
);
526 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
527 font
= FACE_FONT (face
);
528 if (FACE_STIPPLE (face
))
532 /* Then comes the distinction between modeline and normal text. */
537 face
= FRAME_MODE_LINE_FACE (f
);
538 font
= FACE_FONT (face
);
539 if (FACE_STIPPLE (face
))
543 fg
= face
->foreground
;
544 bg
= face
->background
;
546 /* Now override that if the cursor's on this character. */
549 /* The cursor overrides stippling. */
553 || face
->font
== (XFontStruct
*) FACE_DEFAULT
554 || face
->font
== f
->output_data
.w32
->font
)
555 && face
->background
== f
->output_data
.w32
->background_pixel
556 && face
->foreground
== f
->output_data
.w32
->foreground_pixel
)
558 bg
= f
->output_data
.w32
->cursor_pixel
;
559 fg
= face
->background
;
561 /* Cursor on non-default face: must merge. */
564 bg
= f
->output_data
.w32
->cursor_pixel
;
565 fg
= face
->background
;
566 /* If the glyph would be invisible,
567 try a different foreground. */
569 fg
= face
->foreground
;
571 fg
= f
->output_data
.w32
->cursor_foreground_pixel
;
573 fg
= face
->foreground
;
574 /* Make sure the cursor is distinct from text in this face. */
575 if (bg
== face
->background
576 && fg
== face
->foreground
)
578 bg
= face
->foreground
;
579 fg
= face
->background
;
584 if (font
== (XFontStruct
*) FACE_DEFAULT
)
585 font
= f
->output_data
.w32
->font
;
587 SetBkMode (hdc
, just_foreground
? TRANSPARENT
: OPAQUE
);
589 SetTextColor (hdc
, fg
);
590 SetBkColor (hdc
, bg
);
592 SelectObject (hdc
, font
->hfont
);
594 TextOut (hdc
, left
, top
, buf
, len
);
596 if (!just_foreground
)
598 /* Clear the rest of the line's height. */
599 if (f
->output_data
.w32
->line_height
!= FONT_HEIGHT (font
))
600 w32_fill_area (f
, hdc
, bg
,
602 top
+ FONT_HEIGHT (font
),
603 FONT_WIDTH (font
) * len
,
604 f
->output_data
.w32
->line_height
- FONT_HEIGHT (font
));
608 int underline_position
= 1;
610 if (font
->tm
.tmDescent
<= underline_position
)
611 underline_position
= font
->tm
.tmDescent
- 1;
614 w32_fill_area (f
, hdc
, fg
,
617 + underline_position
),
618 len
* FONT_WIDTH (font
), 1);
621 left
+= len
* FONT_WIDTH (font
);
625 release_frame_dc (f
, hdc
);
629 /* Output some text at the nominal frame cursor position.
630 Advance the cursor over the text.
631 Output LEN glyphs at START.
633 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
634 controls the pixel values used for foreground and background. */
637 w32_write_glyphs (start
, len
)
638 register GLYPH
*start
;
641 register int temp_length
;
651 /* If not within an update,
652 output at the frame's visible cursor. */
653 curs_x
= f
->cursor_x
;
654 curs_y
= f
->cursor_y
;
658 CHAR_TO_PIXEL_COL (f
, curs_x
),
659 CHAR_TO_PIXEL_ROW (f
, curs_y
),
660 start
, len
, highlight
, 0);
662 /* If we drew on top of the cursor, note that it is turned off. */
663 if (curs_y
== f
->phys_cursor_y
664 && curs_x
<= f
->phys_cursor_x
665 && curs_x
+ len
> f
->phys_cursor_x
)
666 f
->phys_cursor_x
= -1;
668 if (updating_frame
== 0)
671 x_display_cursor (f
, 1);
680 /* Clear to the end of the line.
681 Erase the current text line from the nominal cursor position (inclusive)
682 to column FIRST_UNUSED (exclusive). The idea is that everything
683 from FIRST_UNUSED onward is already erased. */
686 w32_clear_end_of_line (first_unused
)
687 register int first_unused
;
689 struct frame
*f
= updating_frame
;
694 if (curs_y
< 0 || curs_y
>= f
->height
)
696 if (first_unused
<= 0)
699 if (first_unused
>= f
->width
)
700 first_unused
= f
->width
;
702 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
708 /* Notice if the cursor will be cleared by this operation. */
709 if (curs_y
== f
->phys_cursor_y
710 && curs_x
<= f
->phys_cursor_x
711 && f
->phys_cursor_x
< first_unused
)
712 f
->phys_cursor_x
= -1;
714 w32_clear_area (f
, NULL
,
715 CHAR_TO_PIXEL_COL (f
, curs_x
),
716 CHAR_TO_PIXEL_ROW (f
, curs_y
),
717 FONT_WIDTH (f
->output_data
.w32
->font
) * (first_unused
- curs_x
),
718 f
->output_data
.w32
->line_height
);
726 struct frame
*f
= updating_frame
;
731 f
->phys_cursor_x
= -1; /* Cursor not visible. */
732 curs_x
= 0; /* Nominal cursor position is top left. */
737 w32_clear_window (f
);
739 /* We have to clear the scroll bars, too. If we have changed
740 colors or something like that, then they should be notified. */
741 x_scroll_bar_clear (f
);
746 /* Make audible bell. */
753 FlashWindow (FRAME_W32_WINDOW (selected_frame
), FALSE
);
755 w32_sys_ring_bell ();
762 /* Insert and delete character.
763 These are not supposed to be used because we are supposed to turn
764 off the feature of using them. */
767 w32_insert_glyphs (start
, len
)
768 register char *start
;
775 w32_delete_glyphs (n
)
781 /* Specify how many text lines, from the top of the window,
782 should be affected by insert-lines and delete-lines operations.
783 This, and those operations, are used only within an update
784 that is bounded by calls to w32_update_begin and w32_update_end. */
787 w32_set_terminal_window (n
)
790 if (updating_frame
== 0)
793 if ((n
<= 0) || (n
> updating_frame
->height
))
794 flexlines
= updating_frame
->height
;
799 /* These variables need not be per frame
800 because redisplay is done on a frame-by-frame basis
801 and the line dance for one frame is finished before
802 anything is done for another frame. */
804 /* Array of line numbers from cached insert/delete operations.
805 line_dance[i] is the old position of the line that we want
806 to move to line i, or -1 if we want a blank line there. */
807 static int *line_dance
;
809 /* Allocated length of that array. */
810 static int line_dance_len
;
812 /* Flag indicating whether we've done any work. */
813 static int line_dance_in_progress
;
815 /* Perform an insert-lines or delete-lines operation,
816 inserting N lines or deleting -N lines at vertical position VPOS. */
817 w32_ins_del_lines (vpos
, n
)
820 register int fence
, i
;
822 if (vpos
>= flexlines
)
825 if (!line_dance_in_progress
)
827 int ht
= updating_frame
->height
;
828 if (ht
> line_dance_len
)
830 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
833 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
834 line_dance_in_progress
= 1;
838 if (n
> flexlines
- vpos
)
839 n
= flexlines
- vpos
;
841 for (i
= flexlines
; --i
>= fence
;)
842 line_dance
[i
] = line_dance
[i
-n
];
843 for (i
= fence
; --i
>= vpos
;)
849 if (n
> flexlines
- vpos
)
850 n
= flexlines
- vpos
;
851 fence
= flexlines
- n
;
852 for (i
= vpos
; i
< fence
; ++i
)
853 line_dance
[i
] = line_dance
[i
+ n
];
854 for (i
= fence
; i
< flexlines
; ++i
)
859 /* Here's where we actually move the pixels around.
860 Must be called with input blocked. */
864 register int i
, j
, distance
;
865 register struct frame
*f
;
870 /* Must check this flag first. If it's not set, then not only is the
871 array uninitialized, but we might not even have a frame. */
872 if (!line_dance_in_progress
)
880 intborder
= f
->output_data
.w32
->internal_border_width
;
882 x_display_cursor (updating_frame
, 0);
884 hdc
= get_frame_dc (f
);
886 for (i
= 0; i
< ht
; ++i
)
887 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
889 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
890 && line_dance
[j
]-j
== distance
); ++j
);
891 /* Copy [i,j) upward from [i+distance, j+distance) */
893 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
894 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
895 (j
-i
) * f
->output_data
.w32
->line_height
,
897 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
902 for (i
= ht
; --i
>=0; )
903 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
905 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
906 && line_dance
[j
]-j
== distance
););
907 /* Copy (j, i] downward from (j+distance, i+distance] */
909 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
910 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
911 (i
-j
) * f
->output_data
.w32
->line_height
,
913 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1),
918 for (i
= 0; i
< ht
; ++i
)
919 if (line_dance
[i
] == -1)
921 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
923 w32_clear_area (f
, hdc
,
925 CHAR_TO_PIXEL_ROW (f
, i
),
926 f
->width
* FONT_WIDTH (f
->output_data
.w32
->font
),
927 (j
-i
) * f
->output_data
.w32
->line_height
);
930 line_dance_in_progress
= 0;
932 release_frame_dc (f
, hdc
);
935 /* Support routines for exposure events. */
936 static void clear_cursor ();
938 /* Output into a rectangle of a window (for frame F)
939 the characters in f->phys_lines that overlap that rectangle.
940 TOP and LEFT are the position of the upper left corner of the rectangle.
941 ROWS and COLS are the size of the rectangle.
942 Call this function with input blocked. */
945 dumprectangle (f
, left
, top
, cols
, rows
)
947 register int left
, top
, cols
, rows
;
949 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
950 int cursor_cleared
= 0;
954 if (FRAME_GARBAGED_P (f
))
957 /* Express rectangle as four edges, instead of position-and-size. */
961 /* Convert rectangle edges in pixels to edges in chars.
962 Round down for left and top, up for right and bottom. */
963 top
= PIXEL_TO_CHAR_ROW (f
, top
);
964 left
= PIXEL_TO_CHAR_COL (f
, left
);
965 bottom
+= (f
->output_data
.w32
->line_height
- 1);
966 right
+= (FONT_WIDTH (f
->output_data
.w32
->font
) - 1);
967 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
968 right
= PIXEL_TO_CHAR_COL (f
, right
);
970 /* Clip the rectangle to what can be visible. */
975 if (right
> f
->width
)
977 if (bottom
> f
->height
)
980 /* Get size in chars of the rectangle. */
984 /* If rectangle has zero area, return. */
985 if (rows
<= 0) return;
986 if (cols
<= 0) return;
988 /* Turn off the cursor if it is in the rectangle.
989 We will turn it back on afterward. */
990 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
991 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
997 /* Display the text in the rectangle, one text line at a time. */
999 for (y
= top
; y
< bottom
; y
++)
1001 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1003 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1007 CHAR_TO_PIXEL_COL (f
, left
),
1008 CHAR_TO_PIXEL_ROW (f
, y
),
1009 line
, min (cols
, active_frame
->used
[y
] - left
),
1010 active_frame
->highlight
[y
], 0);
1013 /* Turn the cursor on if we turned it off. */
1016 x_display_cursor (f
, 1);
1023 x_display_cursor (f
, 1);
1027 frame_unhighlight (f
)
1030 x_display_cursor (f
, 1);
1033 static void w32_frame_rehighlight ();
1034 static void x_frame_rehighlight ();
1036 /* The focus has changed. Update the frames as necessary to reflect
1037 the new situation. Note that we can't change the selected frame
1038 here, because the Lisp code we are interrupting might become confused.
1039 Each event gets marked with the frame in which it occurred, so the
1040 Lisp code can tell when the switch took place by examining the events. */
1043 x_new_focus_frame (dpyinfo
, frame
)
1044 struct w32_display_info
*dpyinfo
;
1045 struct frame
*frame
;
1047 struct frame
*old_focus
= dpyinfo
->w32_focus_frame
;
1048 int events_enqueued
= 0;
1050 if (frame
!= dpyinfo
->w32_focus_frame
)
1052 /* Set this before calling other routines, so that they see
1053 the correct value of w32_focus_frame. */
1054 dpyinfo
->w32_focus_frame
= frame
;
1056 if (old_focus
&& old_focus
->auto_lower
)
1057 x_lower_frame (old_focus
);
1059 if (dpyinfo
->w32_focus_frame
&& dpyinfo
->w32_focus_frame
->auto_raise
)
1060 pending_autoraise_frame
= dpyinfo
->w32_focus_frame
;
1062 pending_autoraise_frame
= 0;
1065 x_frame_rehighlight (dpyinfo
);
1068 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1071 x_mouse_leave (dpyinfo
)
1072 struct w32_display_info
*dpyinfo
;
1074 x_new_focus_frame (dpyinfo
, dpyinfo
->w32_focus_event_frame
);
1077 /* The focus has changed, or we have redirected a frame's focus to
1078 another frame (this happens when a frame uses a surrogate
1079 minibuffer frame). Shift the highlight as appropriate.
1081 The FRAME argument doesn't necessarily have anything to do with which
1082 frame is being highlighted or unhighlighted; we only use it to find
1083 the appropriate display info. */
1085 w32_frame_rehighlight (frame
)
1086 struct frame
*frame
;
1088 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame
));
1092 x_frame_rehighlight (dpyinfo
)
1093 struct w32_display_info
*dpyinfo
;
1095 struct frame
*old_highlight
= dpyinfo
->w32_highlight_frame
;
1097 if (dpyinfo
->w32_focus_frame
)
1099 dpyinfo
->w32_highlight_frame
1100 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
)))
1101 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
))
1102 : dpyinfo
->w32_focus_frame
);
1103 if (! FRAME_LIVE_P (dpyinfo
->w32_highlight_frame
))
1105 FRAME_FOCUS_FRAME (dpyinfo
->w32_focus_frame
) = Qnil
;
1106 dpyinfo
->w32_highlight_frame
= dpyinfo
->w32_focus_frame
;
1110 dpyinfo
->w32_highlight_frame
= 0;
1112 if (dpyinfo
->w32_highlight_frame
!= old_highlight
)
1115 frame_unhighlight (old_highlight
);
1116 if (dpyinfo
->w32_highlight_frame
)
1117 frame_highlight (dpyinfo
->w32_highlight_frame
);
1121 /* Keyboard processing - modifier keys, etc. */
1123 /* Convert a keysym to its name. */
1126 x_get_keysym_name (keysym
)
1129 /* Make static so we can always return it */
1130 static char value
[100];
1133 GetKeyNameText(keysym
, value
, 100);
1139 /* Mouse clicks and mouse movement. Rah. */
1141 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1142 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1143 that the glyph at X, Y occupies, if BOUNDS != 0.
1144 If NOCLIP is nonzero, do not force the value into range. */
1147 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1149 register int pix_x
, pix_y
;
1150 register int *x
, *y
;
1154 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1155 if (NILP (Vwindow_system
))
1162 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1163 even for negative values. */
1165 pix_x
-= FONT_WIDTH ((f
)->output_data
.w32
->font
) - 1;
1167 pix_y
-= (f
)->output_data
.w32
->line_height
- 1;
1169 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
1170 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
1174 bounds
->left
= CHAR_TO_PIXEL_COL (f
, pix_x
);
1175 bounds
->top
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
1176 bounds
->right
= bounds
->left
+ FONT_WIDTH (f
->output_data
.w32
->font
) - 1;
1177 bounds
->bottom
= bounds
->top
+ f
->output_data
.w32
->line_height
- 1;
1184 else if (pix_x
> f
->width
)
1189 else if (pix_y
> f
->height
)
1198 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1201 register int *pix_x
, *pix_y
;
1203 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1204 if (NILP (Vwindow_system
))
1211 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
1212 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
1216 parse_button (message
, pbutton
, pup
)
1226 case WM_LBUTTONDOWN
:
1234 case WM_MBUTTONDOWN
:
1235 if (NILP (Vw32_swap_mouse_buttons
))
1242 if (NILP (Vw32_swap_mouse_buttons
))
1248 case WM_RBUTTONDOWN
:
1249 if (NILP (Vw32_swap_mouse_buttons
))
1256 if (NILP (Vw32_swap_mouse_buttons
))
1267 if (pbutton
) *pbutton
= button
;
1273 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1275 If the event is a button press, then note that we have grabbed
1279 construct_mouse_click (result
, msg
, f
)
1280 struct input_event
*result
;
1287 parse_button (msg
->msg
.message
, &button
, &up
);
1289 /* Make the event type no_event; we'll change that when we decide
1291 result
->kind
= mouse_click
;
1292 result
->code
= button
;
1293 result
->timestamp
= msg
->msg
.time
;
1294 result
->modifiers
= (msg
->dwModifiers
1302 XSETINT (result
->x
, LOWORD (msg
->msg
.lParam
));
1303 XSETINT (result
->y
, HIWORD (msg
->msg
.lParam
));
1304 XSETFRAME (result
->frame_or_window
, f
);
1309 construct_mouse_wheel (result
, msg
, f
)
1310 struct input_event
*result
;
1315 result
->kind
= mouse_wheel
;
1316 result
->code
= (short) HIWORD (msg
->msg
.wParam
);
1317 result
->timestamp
= msg
->msg
.time
;
1318 result
->modifiers
= msg
->dwModifiers
;
1319 p
.x
= LOWORD (msg
->msg
.lParam
);
1320 p
.y
= HIWORD (msg
->msg
.lParam
);
1321 ScreenToClient(msg
->msg
.hwnd
, &p
);
1322 XSETINT (result
->x
, p
.x
);
1323 XSETINT (result
->y
, p
.y
);
1324 XSETFRAME (result
->frame_or_window
, f
);
1328 /* Function to report a mouse movement to the mainstream Emacs code.
1329 The input handler calls this.
1331 We have received a mouse movement event, which is given in *event.
1332 If the mouse is over a different glyph than it was last time, tell
1333 the mainstream emacs code by setting mouse_moved. If not, ask for
1334 another motion event, so we can check again the next time it moves. */
1337 note_mouse_movement (frame
, msg
)
1341 last_mouse_movement_time
= msg
->time
;
1343 if (msg
->hwnd
!= FRAME_W32_WINDOW (frame
))
1345 frame
->mouse_moved
= 1;
1346 last_mouse_scroll_bar
= Qnil
;
1348 note_mouse_highlight (frame
, -1, -1);
1351 /* Has the mouse moved off the glyph it was on at the last sighting? */
1352 else if (LOWORD (msg
->lParam
) < last_mouse_glyph
.left
1353 || LOWORD (msg
->lParam
) > last_mouse_glyph
.right
1354 || HIWORD (msg
->lParam
) < last_mouse_glyph
.top
1355 || HIWORD (msg
->lParam
) > last_mouse_glyph
.bottom
)
1357 frame
->mouse_moved
= 1;
1358 last_mouse_scroll_bar
= Qnil
;
1360 note_mouse_highlight (frame
, LOWORD (msg
->lParam
), HIWORD (msg
->lParam
));
1364 /* This is used for debugging, to turn off note_mouse_highlight. */
1365 static int disable_mouse_highlight
;
1367 /* Take proper action when the mouse has moved to position X, Y on frame F
1368 as regards highlighting characters that have mouse-face properties.
1369 Also dehighlighting chars where the mouse was before.
1370 X and Y can be negative or out of range. */
1373 note_mouse_highlight (f
, x
, y
)
1377 int row
, column
, portion
;
1382 if (disable_mouse_highlight
)
1385 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
1386 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
1387 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
1389 if (FRAME_W32_DISPLAY_INFO (f
)->mouse_face_defer
)
1394 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
1398 /* Find out which glyph the mouse is on. */
1399 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
1400 &new_glyph
, FRAME_W32_DISPLAY_INFO (f
)->grabbed
);
1402 /* Which window is that in? */
1403 window
= window_from_coordinates (f
, column
, row
, &portion
);
1404 w
= XWINDOW (window
);
1406 /* If we were displaying active text in another window, clear that. */
1407 if (! EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
))
1408 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1410 /* Are we in a window whose display is up to date?
1411 And verify the buffer's text has not changed. */
1412 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
1413 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
1414 && EQ (w
->window_end_valid
, w
->buffer
)
1415 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
1416 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
1418 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
1421 /* Find which buffer position the mouse corresponds to. */
1422 for (i
= column
; i
>= 0; i
--)
1426 /* Is it outside the displayed active region (if any)? */
1428 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1429 else if (! (EQ (window
, FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
)
1430 && row
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1431 && row
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1432 && (row
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1433 || column
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
)
1434 && (row
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1435 || column
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1436 || FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
)))
1438 Lisp_Object mouse_face
, overlay
, position
;
1439 Lisp_Object
*overlay_vec
;
1440 int len
, noverlays
, ignor1
;
1441 struct buffer
*obuf
;
1444 /* If we get an out-of-range value, return now; avoid an error. */
1445 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
1448 /* Make the window's buffer temporarily current for
1449 overlays_at and compute_char_face. */
1450 obuf
= current_buffer
;
1451 current_buffer
= XBUFFER (w
->buffer
);
1457 /* Yes. Clear the display of the old active region, if any. */
1458 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
1460 /* Is this char mouse-active? */
1461 XSETINT (position
, pos
);
1464 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
1466 /* Put all the overlays we want in a vector in overlay_vec.
1467 Store the length in len. */
1468 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
1470 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
1472 /* Find the highest priority overlay that has a mouse-face prop. */
1474 for (i
= 0; i
< noverlays
; i
++)
1476 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
1477 if (!NILP (mouse_face
))
1479 overlay
= overlay_vec
[i
];
1484 /* If no overlay applies, get a text property. */
1486 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
1488 /* Handle the overlay case. */
1489 if (! NILP (overlay
))
1491 /* Find the range of text around this char that
1492 should be active. */
1493 Lisp_Object before
, after
;
1496 before
= Foverlay_start (overlay
);
1497 after
= Foverlay_end (overlay
);
1498 /* Record this as the current active region. */
1499 fast_find_position (window
, before
,
1500 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1501 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1502 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1503 = !fast_find_position (window
, after
,
1504 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1505 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1506 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1507 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1508 = compute_char_face (f
, w
, pos
, 0, 0,
1509 &ignore
, pos
+ 1, 1);
1511 /* Display it as active. */
1512 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1514 /* Handle the text property case. */
1515 else if (! NILP (mouse_face
))
1517 /* Find the range of text around this char that
1518 should be active. */
1519 Lisp_Object before
, after
, beginning
, end
;
1522 beginning
= Fmarker_position (w
->start
);
1523 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
1524 - XFASTINT (w
->window_end_pos
)));
1526 = Fprevious_single_property_change (make_number (pos
+ 1),
1528 w
->buffer
, beginning
);
1530 = Fnext_single_property_change (position
, Qmouse_face
,
1532 /* Record this as the current active region. */
1533 fast_find_position (window
, before
,
1534 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
,
1535 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
);
1536 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_past_end
1537 = !fast_find_position (window
, after
,
1538 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
,
1539 &FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
);
1540 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_window
= window
;
1541 FRAME_W32_DISPLAY_INFO (f
)->mouse_face_face_id
1542 = compute_char_face (f
, w
, pos
, 0, 0,
1543 &ignore
, pos
+ 1, 1);
1545 /* Display it as active. */
1546 show_mouse_face (FRAME_W32_DISPLAY_INFO (f
), 1);
1550 current_buffer
= obuf
;
1555 /* Find the row and column of position POS in window WINDOW.
1556 Store them in *COLUMNP and *ROWP.
1557 This assumes display in WINDOW is up to date.
1558 If POS is above start of WINDOW, return coords
1559 of start of first screen line.
1560 If POS is after end of WINDOW, return coords of end of last screen line.
1562 Value is 1 if POS is in range, 0 if it was off screen. */
1565 fast_find_position (window
, pos
, columnp
, rowp
)
1568 int *columnp
, *rowp
;
1570 struct window
*w
= XWINDOW (window
);
1571 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1574 int left
= WINDOW_LEFT_MARGIN (w
);
1576 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
1577 int width
= window_internal_width (w
);
1580 int maybe_next_line
= 0;
1582 /* Find the right row. */
1587 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
1588 if (linestart
> pos
)
1590 /* If the position sought is the end of the buffer,
1591 don't include the blank lines at the bottom of the window. */
1592 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
1594 maybe_next_line
= 1;
1601 /* Find the right column with in it. */
1602 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
1604 for (i
= 0; i
< width
; i
++)
1606 if (charstarts
[left
+ i
] == pos
)
1609 *columnp
= i
+ left
;
1612 else if (charstarts
[left
+ i
] > pos
)
1614 else if (charstarts
[left
+ i
] > 0)
1618 /* If we're looking for the end of the buffer,
1619 and we didn't find it in the line we scanned,
1620 use the start of the following line. */
1621 if (maybe_next_line
)
1632 /* Display the active region described by mouse_face_*
1633 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1636 show_mouse_face (dpyinfo
, hl
)
1637 struct w32_display_info
*dpyinfo
;
1640 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
1641 int width
= window_internal_width (w
);
1642 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1645 int old_curs_x
= curs_x
;
1646 int old_curs_y
= curs_y
;
1648 /* Set these variables temporarily
1649 so that if we have to turn the cursor off and on again
1650 we will put it back at the same place. */
1651 curs_x
= f
->phys_cursor_x
;
1652 curs_y
= f
->phys_cursor_y
;
1654 for (i
= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
;
1655 i
<= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
1657 int column
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
1658 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
1659 : WINDOW_LEFT_MARGIN (w
));
1660 int endcolumn
= (i
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
1661 ? FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
1662 : WINDOW_LEFT_MARGIN (w
) + width
);
1663 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
1665 /* If the cursor's in the text we are about to rewrite,
1666 turn the cursor off. */
1668 && curs_x
>= column
- 1
1669 && curs_x
<= endcolumn
)
1671 x_display_cursor (f
, 0);
1676 CHAR_TO_PIXEL_COL (f
, column
),
1677 CHAR_TO_PIXEL_ROW (f
, i
),
1678 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
1680 /* Highlight with mouse face if hl > 0. */
1684 /* If we turned the cursor off, turn it back on. */
1686 x_display_cursor (f
, 1);
1688 curs_x
= old_curs_x
;
1689 curs_y
= old_curs_y
;
1691 /* Change the mouse cursor according to the value of HL. */
1693 SetCursor (f
->output_data
.w32
->cross_cursor
);
1695 SetCursor (f
->output_data
.w32
->text_cursor
);
1698 /* Clear out the mouse-highlighted active region.
1699 Redraw it unhighlighted first. */
1702 clear_mouse_face (dpyinfo
)
1703 struct w32_display_info
*dpyinfo
;
1705 if (! NILP (dpyinfo
->mouse_face_window
))
1706 show_mouse_face (dpyinfo
, 0);
1708 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1709 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1710 dpyinfo
->mouse_face_window
= Qnil
;
1713 struct scroll_bar
*x_window_to_scroll_bar ();
1714 static void x_scroll_bar_report_motion ();
1716 /* Return the current position of the mouse.
1717 *fp should be a frame which indicates which display to ask about.
1719 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1720 and *part to the frame, window, and scroll bar part that the mouse
1721 is over. Set *x and *y to the portion and whole of the mouse's
1722 position on the scroll bar.
1724 If the mouse movement started elsewhere, set *fp to the frame the
1725 mouse is on, *bar_window to nil, and *x and *y to the character cell
1728 Set *time to the server timestamp for the time at which the mouse
1729 was at this position.
1731 Don't store anything if we don't have a valid set of values to report.
1733 This clears the mouse_moved flag, so we can wait for the next mouse
1734 movement. This also calls XQueryPointer, which will cause the
1735 server to give us another MotionNotify when the mouse moves
1739 w32_mouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
1742 Lisp_Object
*bar_window
;
1743 enum scroll_bar_part
*part
;
1745 unsigned long *time
;
1751 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
1752 /* This is never called at the moment. */
1753 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
1758 Lisp_Object frame
, tail
;
1760 /* Clear the mouse-moved flag for every frame on this display. */
1761 FOR_EACH_FRAME (tail
, frame
)
1762 XFRAME (frame
)->mouse_moved
= 0;
1764 last_mouse_scroll_bar
= Qnil
;
1768 /* Now we have a position on the root; find the innermost window
1769 containing the pointer. */
1771 if (FRAME_W32_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
1772 && FRAME_LIVE_P (last_mouse_frame
))
1774 f1
= last_mouse_frame
;
1778 /* Is win one of our frames? */
1779 f1
= x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp
), WindowFromPoint(pt
));
1782 /* If not, is it one of our scroll bars? */
1785 struct scroll_bar
*bar
= x_window_to_scroll_bar (WindowFromPoint(pt
));
1789 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
1793 if (f1
== 0 && insist
> 0)
1794 f1
= selected_frame
;
1798 int ignore1
, ignore2
;
1800 ScreenToClient (FRAME_W32_WINDOW (f1
), &pt
);
1802 /* Ok, we found a frame. Store all the values. */
1804 pixel_to_glyph_coords (f1
, pt
.x
, pt
.y
, &ignore1
, &ignore2
,
1806 FRAME_W32_DISPLAY_INFO (f1
)->grabbed
1814 *time
= last_mouse_movement_time
;
1822 /* Scroll bar support. */
1824 /* Given an window ID, find the struct scroll_bar which manages it.
1825 This can be called in GC, so we have to make sure to strip off mark
1828 x_window_to_scroll_bar (window_id
)
1831 Lisp_Object tail
, frame
;
1833 for (tail
= Vframe_list
;
1834 XGCTYPE (tail
) == Lisp_Cons
;
1835 tail
= XCONS (tail
)->cdr
)
1837 Lisp_Object frame
, bar
, condemned
;
1839 frame
= XCONS (tail
)->car
;
1840 /* All elements of Vframe_list should be frames. */
1841 if (! GC_FRAMEP (frame
))
1844 /* Scan this frame's scroll bar list for a scroll bar with the
1846 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
1847 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
1848 /* This trick allows us to search both the ordinary and
1849 condemned scroll bar lists with one loop. */
1850 ! GC_NILP (bar
) || (bar
= condemned
,
1853 bar
= XSCROLL_BAR (bar
)->next
)
1854 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
1855 return XSCROLL_BAR (bar
);
1862 my_create_scrollbar (f
, bar
)
1864 struct scroll_bar
* bar
;
1866 return (HWND
) SendMessage (FRAME_W32_WINDOW (f
),
1867 WM_EMACS_CREATESCROLLBAR
, (WPARAM
) f
,
1871 //#define ATTACH_THREADS
1874 my_show_window (FRAME_PTR f
, HWND hwnd
, int how
)
1876 #ifndef ATTACH_THREADS
1877 return SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SHOWWINDOW
,
1878 (WPARAM
) hwnd
, (LPARAM
) how
);
1880 return ShowWindow (hwnd
, how
);
1885 my_set_window_pos (HWND hwnd
, HWND hwndAfter
,
1886 int x
, int y
, int cx
, int cy
, UINT flags
)
1888 #ifndef ATTACH_THREADS
1890 pos
.hwndInsertAfter
= hwndAfter
;
1896 SendMessage (hwnd
, WM_EMACS_SETWINDOWPOS
, (WPARAM
) &pos
, 0);
1898 SetWindowPos (hwnd
, hwndAfter
, x
, y
, cx
, cy
, flags
);
1903 my_set_focus (f
, hwnd
)
1907 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_SETFOCUS
,
1912 my_destroy_window (f
, hwnd
)
1916 SendMessage (FRAME_W32_WINDOW (f
), WM_EMACS_DESTROYWINDOW
,
1920 /* Open a new window to serve as a scroll bar, and return the
1921 scroll bar vector for it. */
1922 static struct scroll_bar
*
1923 x_scroll_bar_create (window
, top
, left
, width
, height
)
1924 struct window
*window
;
1925 int top
, left
, width
, height
;
1927 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
1928 struct scroll_bar
*bar
1929 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
1934 XSETWINDOW (bar
->window
, window
);
1935 XSETINT (bar
->top
, top
);
1936 XSETINT (bar
->left
, left
);
1937 XSETINT (bar
->width
, width
);
1938 XSETINT (bar
->height
, height
);
1939 XSETINT (bar
->start
, 0);
1940 XSETINT (bar
->end
, 0);
1941 bar
->dragging
= Qnil
;
1943 /* Requires geometry to be set before call to create the real window */
1945 hwnd
= my_create_scrollbar (f
, bar
);
1947 if (pfnSetScrollInfo
)
1951 si
.cbSize
= sizeof (si
);
1954 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
1955 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
1959 pfnSetScrollInfo (hwnd
, SB_CTL
, &si
, FALSE
);
1963 SetScrollRange (hwnd
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
1964 SetScrollPos (hwnd
, SB_CTL
, 0, FALSE
);
1967 SET_SCROLL_BAR_W32_WINDOW (bar
, hwnd
);
1969 /* Add bar to its frame's list of scroll bars. */
1970 bar
->next
= FRAME_SCROLL_BARS (f
);
1972 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
1973 if (! NILP (bar
->next
))
1974 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
1981 /* Draw BAR's handle in the proper position.
1982 If the handle is already drawn from START to END, don't bother
1983 redrawing it, unless REBUILD is non-zero; in that case, always
1984 redraw it. (REBUILD is handy for drawing the handle after expose
1987 Normally, we want to constrain the start and end of the handle to
1988 fit inside its rectangle, but if the user is dragging the scroll bar
1989 handle, we want to let them drag it down all the way, so that the
1990 bar's top is as far down as it goes; otherwise, there's no way to
1991 move to the very end of the buffer. */
1993 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
1994 struct scroll_bar
*bar
;
1998 int dragging
= ! NILP (bar
->dragging
);
1999 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2000 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2002 /* If the display is already accurate, do nothing. */
2004 && start
== XINT (bar
->start
)
2005 && end
== XINT (bar
->end
))
2011 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2013 /* Make sure the values are reasonable, and try to preserve
2014 the distance between start and end. */
2016 int length
= end
- start
;
2020 else if (start
> top_range
)
2022 end
= start
+ length
;
2026 else if (end
> top_range
&& ! dragging
)
2031 /* Store the adjusted setting in the scroll bar. */
2032 XSETINT (bar
->start
, start
);
2033 XSETINT (bar
->end
, end
);
2035 /* If being dragged, let scroll bar update itself. */
2038 if (pfnSetScrollInfo
)
2042 si
.cbSize
= sizeof (si
);
2043 si
.fMask
= SIF_PAGE
| SIF_POS
;
2044 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2047 pfnSetScrollInfo (w
, SB_CTL
, &si
, TRUE
);
2050 SetScrollPos (w
, SB_CTL
, start
, TRUE
);
2056 /* Move a scroll bar around on the screen, to accommodate changing
2057 window configurations. */
2059 x_scroll_bar_move (bar
, top
, left
, width
, height
)
2060 struct scroll_bar
*bar
;
2061 int top
, left
, width
, height
;
2063 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2064 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2066 /* If already correctly positioned, do nothing. */
2067 if ( XINT (bar
->left
) == left
2068 && XINT (bar
->top
) == top
2069 && XINT (bar
->width
) == width
2070 && XINT (bar
->height
) == height
)
2072 /* Redraw after clear_frame. */
2073 if (!my_show_window (f
, w
, SW_NORMAL
))
2074 InvalidateRect (w
, NULL
, FALSE
);
2080 /* Make sure scroll bar is "visible" before moving, to ensure the
2081 area of the parent window now exposed will be refreshed. */
2082 my_show_window (f
, w
, SW_HIDE
);
2083 MoveWindow (w
, left
, top
, width
, height
, TRUE
);
2084 if (pfnSetScrollInfo
)
2088 si
.cbSize
= sizeof (si
);
2089 si
.fMask
= SIF_RANGE
;
2091 si
.nMax
= VERTICAL_SCROLL_BAR_TOP_RANGE (height
)
2092 + VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2094 pfnSetScrollInfo (w
, SB_CTL
, &si
, FALSE
);
2097 SetScrollRange (w
, SB_CTL
, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height
), FALSE
);
2098 my_show_window (f
, w
, SW_NORMAL
);
2099 // InvalidateRect (w, NULL, FALSE);
2101 XSETINT (bar
->left
, left
);
2102 XSETINT (bar
->top
, top
);
2103 XSETINT (bar
->width
, width
);
2104 XSETINT (bar
->height
, height
);
2109 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2112 x_scroll_bar_remove (bar
)
2113 struct scroll_bar
*bar
;
2115 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2119 /* Destroy the window. */
2120 my_destroy_window (f
, SCROLL_BAR_W32_WINDOW (bar
));
2122 /* Disassociate this scroll bar from its window. */
2123 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
2128 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2129 that we are displaying PORTION characters out of a total of WHOLE
2130 characters, starting at POSITION. If WINDOW has no scroll bar,
2133 w32_set_vertical_scroll_bar (window
, portion
, whole
, position
)
2134 struct window
*window
;
2135 int portion
, whole
, position
;
2137 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2138 int top
= XINT (window
->top
);
2139 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
2140 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
2142 /* Where should this scroll bar be, pixelwise? */
2143 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
2144 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
2146 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
2147 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
2148 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
2149 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
2151 struct scroll_bar
*bar
;
2153 /* Does the scroll bar exist yet? */
2154 if (NILP (window
->vertical_scroll_bar
))
2155 bar
= x_scroll_bar_create (window
,
2156 pixel_top
, pixel_left
,
2157 pixel_width
, pixel_height
);
2160 /* It may just need to be moved and resized. */
2161 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2162 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
2165 /* Set the scroll bar's current state. */
2167 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height
);
2170 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
2173 int start
= (int) (((double) position
* top_range
) / whole
);
2174 int end
= (int) (((double) (position
+ portion
) * top_range
) / whole
);
2176 x_scroll_bar_set_handle (bar
, start
, end
, 0);
2180 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
2184 /* The following three hooks are used when we're doing a thorough
2185 redisplay of the frame. We don't explicitly know which scroll bars
2186 are going to be deleted, because keeping track of when windows go
2187 away is a real pain - "Can you say set-window-configuration, boys
2188 and girls?" Instead, we just assert at the beginning of redisplay
2189 that *all* scroll bars are to be removed, and then save a scroll bar
2190 from the fiery pit when we actually redisplay its window. */
2192 /* Arrange for all scroll bars on FRAME to be removed at the next call
2193 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2194 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2196 w32_condemn_scroll_bars (frame
)
2199 /* The condemned list should be empty at this point; if it's not,
2200 then the rest of Emacs isn't using the condemn/redeem/judge
2201 protocol correctly. */
2202 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
2205 /* Move them all to the "condemned" list. */
2206 FRAME_CONDEMNED_SCROLL_BARS (frame
) = FRAME_SCROLL_BARS (frame
);
2207 FRAME_SCROLL_BARS (frame
) = Qnil
;
2210 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2211 Note that WINDOW isn't necessarily condemned at all. */
2213 w32_redeem_scroll_bar (window
)
2214 struct window
*window
;
2216 struct scroll_bar
*bar
;
2218 /* We can't redeem this window's scroll bar if it doesn't have one. */
2219 if (NILP (window
->vertical_scroll_bar
))
2222 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
2224 /* Unlink it from the condemned list. */
2226 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2228 if (NILP (bar
->prev
))
2230 /* If the prev pointer is nil, it must be the first in one of
2232 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
2233 /* It's not condemned. Everything's fine. */
2235 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
2236 window
->vertical_scroll_bar
))
2237 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
2239 /* If its prev pointer is nil, it must be at the front of
2240 one or the other! */
2244 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
2246 if (! NILP (bar
->next
))
2247 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
2249 bar
->next
= FRAME_SCROLL_BARS (f
);
2251 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2252 if (! NILP (bar
->next
))
2253 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2257 /* Remove all scroll bars on FRAME that haven't been saved since the
2258 last call to `*condemn_scroll_bars_hook'. */
2260 w32_judge_scroll_bars (f
)
2263 Lisp_Object bar
, next
;
2265 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
2267 /* Clear out the condemned list now so we won't try to process any
2268 more events on the hapless scroll bars. */
2269 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
2271 for (; ! NILP (bar
); bar
= next
)
2273 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
2275 x_scroll_bar_remove (b
);
2278 b
->next
= b
->prev
= Qnil
;
2281 /* Now there should be no references to the condemned scroll bars,
2282 and they should get garbage-collected. */
2285 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2286 is set to something other than no_event, it is enqueued.
2288 This may be called from a signal handler, so we have to ignore GC
2292 x_scroll_bar_handle_click (bar
, msg
, emacs_event
)
2293 struct scroll_bar
*bar
;
2295 struct input_event
*emacs_event
;
2297 if (! GC_WINDOWP (bar
->window
))
2300 emacs_event
->kind
= w32_scroll_bar_click
;
2301 emacs_event
->code
= 0;
2302 /* not really meaningful to distinguish up/down */
2303 emacs_event
->modifiers
= msg
->dwModifiers
;
2304 emacs_event
->frame_or_window
= bar
->window
;
2305 emacs_event
->timestamp
= msg
->msg
.time
;
2308 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2310 int dragging
= !NILP (bar
->dragging
);
2312 if (pfnGetScrollInfo
)
2316 si
.cbSize
= sizeof (si
);
2319 pfnGetScrollInfo ((HWND
) msg
->msg
.lParam
, SB_CTL
, &si
);
2323 y
= GetScrollPos ((HWND
) msg
->msg
.lParam
, SB_CTL
);
2325 bar
->dragging
= Qnil
;
2327 switch (LOWORD (msg
->msg
.wParam
))
2330 emacs_event
->part
= scroll_bar_down_arrow
;
2333 emacs_event
->part
= scroll_bar_up_arrow
;
2336 emacs_event
->part
= scroll_bar_above_handle
;
2339 emacs_event
->part
= scroll_bar_below_handle
;
2342 emacs_event
->part
= scroll_bar_handle
;
2346 emacs_event
->part
= scroll_bar_handle
;
2350 case SB_THUMBPOSITION
:
2351 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2352 y
= HIWORD (msg
->msg
.wParam
);
2354 emacs_event
->part
= scroll_bar_handle
;
2356 /* "Silently" update current position. */
2357 if (pfnSetScrollInfo
)
2361 si
.cbSize
= sizeof (si
);
2365 /* Shrink handle if necessary to allow full range for position. */
2367 int start
= XINT (bar
->start
);
2368 int end
= XINT (bar
->end
);
2369 int len
= end
- start
;
2371 /* If new end is nearly hitting bottom, we must shrink
2372 handle. How much we shrink it depends on the relative
2373 sizes of len and top_range. */
2374 if (y
+ len
> top_range
- 2)
2376 len
-= min (top_range
/ 10, (len
/ 3) + 2);
2380 si
.nPage
= len
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2381 si
.fMask
|= SIF_PAGE
;
2385 /* Remember apparent position (we actually lag behind the real
2386 position, so don't set that directly. */
2387 last_scroll_bar_drag_pos
= y
;
2389 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, FALSE
);
2392 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, FALSE
);
2395 /* If this is the end of a drag sequence, then reset the scroll
2396 handle size to normal and do a final redraw. Otherwise do
2400 if (pfnSetScrollInfo
)
2403 int start
= XINT (bar
->start
);
2404 int end
= XINT (bar
->end
);
2406 si
.cbSize
= sizeof (si
);
2407 si
.fMask
= SIF_PAGE
| SIF_POS
;
2408 si
.nPage
= end
- start
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2409 si
.nPos
= last_scroll_bar_drag_pos
;
2411 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, &si
, TRUE
);
2414 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar
), SB_CTL
, y
, TRUE
);
2418 emacs_event
->kind
= no_event
;
2422 XSETINT (emacs_event
->x
, y
);
2423 XSETINT (emacs_event
->y
, top_range
);
2429 /* Return information to the user about the current position of the mouse
2430 on the scroll bar. */
2432 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2434 Lisp_Object
*bar_window
;
2435 enum scroll_bar_part
*part
;
2437 unsigned long *time
;
2439 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2440 Window w
= SCROLL_BAR_W32_WINDOW (bar
);
2441 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2443 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
));
2448 *bar_window
= bar
->window
;
2450 if (pfnGetScrollInfo
)
2454 si
.cbSize
= sizeof (si
);
2455 si
.fMask
= SIF_POS
| SIF_PAGE
| SIF_RANGE
;
2457 pfnGetScrollInfo (w
, SB_CTL
, &si
);
2459 top_range
= si
.nMax
- si
.nPage
+ 1;
2462 pos
= GetScrollPos (w
, SB_CTL
);
2464 switch (LOWORD (last_mouse_scroll_bar_pos
))
2466 case SB_THUMBPOSITION
:
2468 *part
= scroll_bar_handle
;
2469 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar
->height
)) <= 0xffff)
2470 pos
= HIWORD (last_mouse_scroll_bar_pos
);
2473 *part
= scroll_bar_handle
;
2477 *part
= scroll_bar_handle
;
2482 XSETINT(*y
, top_range
);
2485 last_mouse_scroll_bar
= Qnil
;
2487 *time
= last_mouse_movement_time
;
2492 /* The screen has been cleared so we may have changed foreground or
2493 background colors, and the scroll bars may need to be redrawn.
2494 Clear out the scroll bars, and ask for expose events, so we can
2497 x_scroll_bar_clear (f
)
2502 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2503 bar
= XSCROLL_BAR (bar
)->next
)
2505 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2506 HDC hdc
= GetDC (window
);
2509 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
2510 arranges to refresh the scroll bar if hidden. */
2511 my_show_window (f
, window
, SW_HIDE
);
2513 GetClientRect (window
, &rect
);
2514 select_palette (f
, hdc
);
2515 w32_clear_rect (f
, hdc
, &rect
);
2516 deselect_palette (f
, hdc
);
2518 ReleaseDC (window
, hdc
);
2522 show_scroll_bars (f
, how
)
2528 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
2529 bar
= XSCROLL_BAR (bar
)->next
)
2531 HWND window
= SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar
));
2532 my_show_window (f
, window
, how
);
2537 /* The main W32 event-reading loop - w32_read_socket. */
2539 /* Timestamp of enter window event. This is only used by w32_read_socket,
2540 but we have to put it out here, since static variables within functions
2541 sometimes don't work. */
2542 static Time enter_timestamp
;
2544 /* Record the last 100 characters stored
2545 to help debug the loss-of-chars-during-GC problem. */
2547 short temp_buffer
[100];
2549 extern int key_event (KEY_EVENT_RECORD
*, struct input_event
*, int *isdead
);
2551 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
2552 we can use the same routines to handle input in both console
2553 and window modes. */
2556 convert_to_key_event (W32Msg
*msgp
, KEY_EVENT_RECORD
*eventp
)
2558 eventp
->bKeyDown
= TRUE
;
2559 eventp
->wRepeatCount
= 1;
2560 eventp
->wVirtualKeyCode
= msgp
->msg
.wParam
;
2561 eventp
->wVirtualScanCode
= (msgp
->msg
.lParam
& 0xFF0000) >> 16;
2562 eventp
->uChar
.AsciiChar
= 0;
2563 eventp
->dwControlKeyState
= msgp
->dwModifiers
;
2566 /* Return nonzero if the virtual key is a dead key. */
2569 is_dead_key (int wparam
)
2571 unsigned int code
= MapVirtualKey (wparam
, 2);
2573 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2574 if ((code
& 0x8000) || (code
& 0x80000000))
2580 /* Read events coming from the W32 shell.
2581 This routine is called by the SIGIO handler.
2582 We return as soon as there are no more events to be read.
2584 Events representing keys are stored in buffer BUFP,
2585 which can hold up to NUMCHARS characters.
2586 We return the number of characters stored into the buffer,
2587 thus pretending to be `read'.
2589 EXPECTED is nonzero if the caller knows input is available.
2591 Some of these messages are reposted back to the message queue since the
2592 system calls the windows proc directly in a context where we cannot return
2593 the data nor can we guarantee the state we are in. So if we dispatch them
2594 we will get into an infinite loop. To prevent this from ever happening we
2595 will set a variable to indicate we are in the read_socket call and indicate
2596 which message we are processing since the windows proc gets called
2597 recursively with different messages by the system.
2601 w32_read_socket (sd
, bufp
, numchars
, expected
)
2603 register struct input_event
*bufp
;
2604 register int numchars
;
2608 int check_visibility
= 0;
2612 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
2614 if (interrupt_input_blocked
)
2616 interrupt_input_pending
= 1;
2620 interrupt_input_pending
= 0;
2623 /* So people can tell when we have read the available input. */
2624 input_signal_count
++;
2627 abort (); /* Don't think this happens. */
2629 while (get_next_msg (&msg
, FALSE
))
2631 switch (msg
.msg
.message
)
2634 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2638 if (f
->async_visible
!= 1)
2640 /* Definitely not obscured, so mark as visible. */
2641 f
->async_visible
= 1;
2642 f
->async_iconified
= 0;
2643 SET_FRAME_GARBAGED (f
);
2644 DebPrint (("frame %04x (%s) reexposed\n", f
,
2645 XSTRING (f
->name
)->data
));
2647 /* WM_PAINT serves as MapNotify as well, so report
2648 visibility changes properly. */
2651 bufp
->kind
= deiconify_event
;
2652 XSETFRAME (bufp
->frame_or_window
, f
);
2657 else if (! NILP(Vframe_list
)
2658 && ! NILP (XCONS (Vframe_list
)->cdr
))
2659 /* Force a redisplay sooner or later to update the
2660 frame titles in case this is the second frame. */
2661 record_asynch_buffer_change ();
2665 /* Erase background again for safety. */
2666 w32_clear_rect (f
, NULL
, &msg
.rect
);
2670 msg
.rect
.right
- msg
.rect
.left
,
2671 msg
.rect
.bottom
- msg
.rect
.top
);
2678 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2680 if (f
&& !f
->iconified
)
2682 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2684 temp_buffer
[temp_index
++] = msg
.msg
.wParam
;
2685 bufp
->kind
= non_ascii_keystroke
;
2686 bufp
->code
= msg
.msg
.wParam
;
2687 bufp
->modifiers
= w32_kbd_mods_to_emacs (msg
.dwModifiers
,
2689 XSETFRAME (bufp
->frame_or_window
, f
);
2690 bufp
->timestamp
= msg
.msg
.time
;
2699 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2701 if (f
&& !f
->iconified
)
2707 KEY_EVENT_RECORD key
, *keyp
= &key
;
2709 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
2712 convert_to_key_event (&msg
, keyp
);
2713 add
= key_event (keyp
, bufp
, &isdead
);
2714 XSETFRAME (bufp
->frame_or_window
, f
);
2717 /* The key pressed generated two characters, most likely
2718 an accent character and a key that could not be
2719 combined with it. Prepend the message on the queue
2720 again to process the second character (which is
2721 being held internally in key_event), and process
2722 the first character now. */
2742 if (dpyinfo
->grabbed
&& last_mouse_frame
2743 && FRAME_LIVE_P (last_mouse_frame
))
2744 f
= last_mouse_frame
;
2746 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2749 note_mouse_movement (f
, &msg
.msg
);
2751 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f
));
2755 case WM_LBUTTONDOWN
:
2757 case WM_MBUTTONDOWN
:
2759 case WM_RBUTTONDOWN
:
2765 if (dpyinfo
->grabbed
&& last_mouse_frame
2766 && FRAME_LIVE_P (last_mouse_frame
))
2767 f
= last_mouse_frame
;
2769 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2773 if ((!dpyinfo
->w32_focus_frame
|| f
== dpyinfo
->w32_focus_frame
)
2776 construct_mouse_click (bufp
, &msg
, f
);
2783 parse_button (msg
.msg
.message
, &button
, &up
);
2787 dpyinfo
->grabbed
&= ~ (1 << button
);
2791 dpyinfo
->grabbed
|= (1 << button
);
2792 last_mouse_frame
= f
;
2798 if (dpyinfo
->grabbed
&& last_mouse_frame
2799 && FRAME_LIVE_P (last_mouse_frame
))
2800 f
= last_mouse_frame
;
2802 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2806 if ((!dpyinfo
->w32_focus_frame
2807 || f
== dpyinfo
->w32_focus_frame
)
2810 construct_mouse_wheel (bufp
, &msg
, f
);
2820 struct scroll_bar
*bar
=
2821 x_window_to_scroll_bar ((HWND
)msg
.msg
.lParam
);
2823 if (bar
&& numchars
>= 1)
2825 if (x_scroll_bar_handle_click (bar
, &msg
, bufp
))
2835 case WM_WINDOWPOSCHANGED
:
2837 case WM_ACTIVATEAPP
:
2838 check_visibility
= 1;
2842 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2844 if (f
&& !f
->async_iconified
)
2848 x_real_positions (f
, &x
, &y
);
2849 f
->output_data
.w32
->left_pos
= x
;
2850 f
->output_data
.w32
->top_pos
= y
;
2853 check_visibility
= 1;
2857 /* If window has been obscured or exposed by another window
2858 being maximised or minimised/restored, then recheck
2859 visibility of all frames. Direct changes to our own
2860 windows get handled by WM_SIZE. */
2862 if (msg
.msg
.lParam
!= 0)
2863 check_visibility
= 1;
2866 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2867 f
->async_visible
= msg
.msg
.wParam
;
2871 check_visibility
= 1;
2875 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2877 if (f
&& !f
->async_iconified
&& msg
.msg
.wParam
!= SIZE_MINIMIZED
)
2885 GetClientRect(msg
.msg
.hwnd
, &rect
);
2887 height
= rect
.bottom
- rect
.top
;
2888 width
= rect
.right
- rect
.left
;
2890 rows
= PIXEL_TO_CHAR_HEIGHT (f
, height
);
2891 columns
= PIXEL_TO_CHAR_WIDTH (f
, width
);
2893 /* TODO: Clip size to the screen dimensions. */
2895 /* Even if the number of character rows and columns has
2896 not changed, the font size may have changed, so we need
2897 to check the pixel dimensions as well. */
2899 if (columns
!= f
->width
2900 || rows
!= f
->height
2901 || width
!= f
->output_data
.w32
->pixel_width
2902 || height
!= f
->output_data
.w32
->pixel_height
)
2904 /* I had set this to 0, 0 - I am not sure why?? */
2906 change_frame_size (f
, rows
, columns
, 0, 1);
2907 SET_FRAME_GARBAGED (f
);
2909 f
->output_data
.w32
->pixel_width
= width
;
2910 f
->output_data
.w32
->pixel_height
= height
;
2911 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
2915 /* Inform lisp of whether frame has been iconified etc. */
2918 switch (msg
.msg
.wParam
)
2920 case SIZE_MINIMIZED
:
2921 f
->async_visible
= 0;
2922 f
->async_iconified
= 1;
2924 bufp
->kind
= iconify_event
;
2925 XSETFRAME (bufp
->frame_or_window
, f
);
2931 case SIZE_MAXIMIZED
:
2933 f
->async_visible
= 1;
2934 f
->async_iconified
= 0;
2936 /* wait_reading_process_input will notice this and update
2937 the frame's display structures. */
2938 SET_FRAME_GARBAGED (f
);
2942 bufp
->kind
= deiconify_event
;
2943 XSETFRAME (bufp
->frame_or_window
, f
);
2949 /* Force a redisplay sooner or later
2950 to update the frame titles
2951 in case this is the second frame. */
2952 record_asynch_buffer_change ();
2957 check_visibility
= 1;
2962 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2964 if (msg
.msg
.message
== WM_SETFOCUS
)
2966 x_new_focus_frame (dpyinfo
, f
);
2968 else if (f
== dpyinfo
->w32_focus_frame
)
2970 x_new_focus_frame (dpyinfo
, 0);
2973 check_visibility
= 1;
2977 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
2984 bufp
->kind
= delete_window_event
;
2985 XSETFRAME (bufp
->frame_or_window
, f
);
2993 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3000 bufp
->kind
= menu_bar_activate_event
;
3001 XSETFRAME (bufp
->frame_or_window
, f
);
3009 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3014 if (msg
.msg
.lParam
== 0)
3016 /* Came from window menu */
3018 extern Lisp_Object
get_frame_menubar_event ();
3019 Lisp_Object event
= get_frame_menubar_event (f
, msg
.msg
.wParam
);
3020 struct input_event buf
;
3023 XSETFRAME (frame
, f
);
3024 buf
.kind
= menu_bar_event
;
3026 /* Store initial menu bar event */
3030 buf
.frame_or_window
= Fcons (frame
, Fcons (Qmenu_bar
, Qnil
));
3031 kbd_buffer_store_event (&buf
);
3034 /* Enqueue the events */
3036 while (!NILP (event
))
3038 buf
.frame_or_window
= Fcons (frame
, XCONS (event
)->car
);
3039 kbd_buffer_store_event (&buf
);
3040 event
= XCONS (event
)->cdr
;
3045 /* Came from popup menu */
3050 check_visibility
= 1;
3053 case WM_DISPLAYCHANGE
:
3054 f
= x_window_to_frame (dpyinfo
, msg
.msg
.hwnd
);
3058 dpyinfo
->width
= (short) LOWORD (msg
.msg
.lParam
);
3059 dpyinfo
->height
= (short) HIWORD (msg
.msg
.lParam
);
3060 dpyinfo
->n_cbits
= msg
.msg
.wParam
;
3061 DebPrint (("display change: %d %d\n", dpyinfo
->width
,
3065 check_visibility
= 1;
3070 /* If the focus was just given to an autoraising frame,
3072 /* ??? This ought to be able to handle more than one such frame. */
3073 if (pending_autoraise_frame
)
3075 x_raise_frame (pending_autoraise_frame
);
3076 pending_autoraise_frame
= 0;
3079 /* Check which frames are still visisble, if we have enqueued any user
3080 events or been notified of events that may affect visibility. We
3081 do this here because there doesn't seem to be any direct
3082 notification from Windows that the visibility of a window has
3083 changed (at least, not in all cases). */
3084 if (count
> 0 || check_visibility
)
3086 Lisp_Object tail
, frame
;
3088 FOR_EACH_FRAME (tail
, frame
)
3090 FRAME_PTR f
= XFRAME (frame
);
3091 /* Check "visible" frames and mark each as obscured or not.
3092 Note that async_visible is nonzero for unobscured and
3093 obscured frames, but zero for hidden and iconified frames. */
3094 if (FRAME_W32_P (f
) && f
->async_visible
)
3097 HDC hdc
= get_frame_dc (f
);
3098 GetClipBox (hdc
, &clipbox
);
3099 release_frame_dc (f
, hdc
);
3101 if (clipbox
.right
== clipbox
.left
3102 || clipbox
.bottom
== clipbox
.top
)
3104 /* Frame has become completely obscured so mark as
3105 such (we do this by setting async_visible to 2 so
3106 that FRAME_VISIBLE_P is still true, but redisplay
3108 f
->async_visible
= 2;
3110 if (!FRAME_OBSCURED_P (f
))
3112 DebPrint (("frame %04x (%s) obscured\n", f
,
3113 XSTRING (f
->name
)->data
));
3118 /* Frame is not obscured, so mark it as such. */
3119 f
->async_visible
= 1;
3121 if (FRAME_OBSCURED_P (f
))
3123 SET_FRAME_GARBAGED (f
);
3124 DebPrint (("frame %04x (%s) reexposed\n", f
,
3125 XSTRING (f
->name
)->data
));
3127 /* Force a redisplay sooner or later. */
3128 record_asynch_buffer_change ();
3139 /* Drawing the cursor. */
3142 /* Draw a hollow box cursor. Don't change the inside of the box. */
3152 hdc
= get_frame_dc (f
);
3154 hb
= CreateSolidBrush (f
->output_data
.w32
->cursor_pixel
);
3156 rect
.left
= CHAR_TO_PIXEL_COL (f
, curs_x
);
3157 rect
.top
= CHAR_TO_PIXEL_ROW (f
, curs_y
);
3158 rect
.right
= rect
.left
+ FONT_WIDTH (f
->output_data
.w32
->font
);
3159 rect
.bottom
= rect
.top
+ f
->output_data
.w32
->line_height
;
3161 FrameRect (hdc
, &rect
, hb
);
3164 release_frame_dc (f
, hdc
);
3167 /* Clear the cursor of frame F to background color,
3168 and mark the cursor as not shown.
3169 This is used when the text where the cursor is
3170 is about to be rewritten. */
3176 if (! FRAME_VISIBLE_P (f
)
3177 || f
->phys_cursor_x
< 0)
3180 x_display_cursor (f
, 0);
3181 f
->phys_cursor_x
= -1;
3184 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3185 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3189 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
3196 CHAR_TO_PIXEL_COL (f
, column
),
3197 CHAR_TO_PIXEL_ROW (f
, row
),
3198 &glyph
, 1, highlight
, 0);
3202 x_display_bar_cursor (f
, on
)
3206 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3208 /* This is pointless on invisible frames, and dangerous on garbaged
3209 frames; in the latter case, the frame may be in the midst of
3210 changing its size, and curs_x and curs_y may be off the frame. */
3211 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3214 if (! on
&& f
->phys_cursor_x
< 0)
3217 /* If there is anything wrong with the current cursor state, remove it. */
3218 if (f
->phys_cursor_x
>= 0
3220 || f
->phys_cursor_x
!= curs_x
3221 || f
->phys_cursor_y
!= curs_y
3222 || f
->output_data
.w32
->current_cursor
!= bar_cursor
))
3224 /* Erase the cursor by redrawing the character underneath it. */
3225 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3226 f
->phys_cursor_glyph
,
3227 current_glyphs
->highlight
[f
->phys_cursor_y
]);
3228 f
->phys_cursor_x
= -1;
3231 /* If we now need a cursor in the new place or in the new form, do it so. */
3233 && (f
->phys_cursor_x
< 0
3234 || (f
->output_data
.w32
->current_cursor
!= bar_cursor
)))
3236 f
->phys_cursor_glyph
3237 = ((current_glyphs
->enable
[curs_y
]
3238 && curs_x
< current_glyphs
->used
[curs_y
])
3239 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3241 w32_fill_area (f
, NULL
, f
->output_data
.w32
->cursor_pixel
,
3242 CHAR_TO_PIXEL_COL (f
, curs_x
),
3243 CHAR_TO_PIXEL_ROW (f
, curs_y
),
3244 max (f
->output_data
.w32
->cursor_width
, 1),
3245 f
->output_data
.w32
->line_height
);
3247 f
->phys_cursor_x
= curs_x
;
3248 f
->phys_cursor_y
= curs_y
;
3250 f
->output_data
.w32
->current_cursor
= bar_cursor
;
3255 /* Turn the displayed cursor of frame F on or off according to ON.
3256 If ON is nonzero, where to put the cursor is specified
3257 by F->cursor_x and F->cursor_y. */
3260 x_display_box_cursor (f
, on
)
3264 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3266 /* This is pointless on invisible frames, and dangerous on garbaged
3267 frames; in the latter case, the frame may be in the midst of
3268 changing its size, and curs_x and curs_y may be off the frame. */
3269 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
3272 /* If cursor is off and we want it off, return quickly. */
3273 if (!on
&& f
->phys_cursor_x
< 0)
3276 /* If cursor is currently being shown and we don't want it to be
3277 or it is in the wrong place,
3278 or we want a hollow box and it's not so, (pout!)
3280 if (f
->phys_cursor_x
>= 0
3282 || f
->phys_cursor_x
!= curs_x
3283 || f
->phys_cursor_y
!= curs_y
3284 || (f
->output_data
.w32
->current_cursor
!= hollow_box_cursor
3285 && (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
))))
3287 int mouse_face_here
= 0;
3288 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
3290 /* If the cursor is in the mouse face area, redisplay that when
3291 we clear the cursor. */
3292 if (f
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_mouse_frame
3293 && (f
->phys_cursor_y
> FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3294 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_row
3295 && f
->phys_cursor_x
>= FRAME_W32_DISPLAY_INFO (f
)->mouse_face_beg_col
))
3296 && (f
->phys_cursor_y
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3297 || (f
->phys_cursor_y
== FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_row
3298 && f
->phys_cursor_x
< FRAME_W32_DISPLAY_INFO (f
)->mouse_face_end_col
))
3299 /* Don't redraw the cursor's spot in mouse face
3300 if it is at the end of a line (on a newline).
3301 The cursor appears there, but mouse highlighting does not. */
3302 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
3303 mouse_face_here
= 1;
3305 /* If the font is not as tall as a whole line,
3306 we must explicitly clear the line's whole height. */
3307 if (FONT_HEIGHT (f
->output_data
.w32
->font
) != f
->output_data
.w32
->line_height
)
3308 w32_clear_area (f
, NULL
,
3309 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
3310 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
3311 FONT_WIDTH (f
->output_data
.w32
->font
),
3312 f
->output_data
.w32
->line_height
);
3313 /* Erase the cursor by redrawing the character underneath it. */
3314 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
3315 f
->phys_cursor_glyph
,
3318 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
3319 f
->phys_cursor_x
= -1;
3322 /* If we want to show a cursor,
3323 or we want a box cursor and it's not so,
3324 write it in the right place. */
3326 && (f
->phys_cursor_x
< 0
3327 || (f
->output_data
.w32
->current_cursor
!= filled_box_cursor
3328 && f
== FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)))
3330 f
->phys_cursor_glyph
3331 = ((current_glyphs
->enable
[curs_y
]
3332 && curs_x
< current_glyphs
->used
[curs_y
])
3333 ? current_glyphs
->glyphs
[curs_y
][curs_x
]
3335 if (f
!= FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
)
3338 f
->output_data
.w32
->current_cursor
= hollow_box_cursor
;
3342 x_draw_single_glyph (f
, curs_y
, curs_x
,
3343 f
->phys_cursor_glyph
, 2);
3344 f
->output_data
.w32
->current_cursor
= filled_box_cursor
;
3347 f
->phys_cursor_x
= curs_x
;
3348 f
->phys_cursor_y
= curs_y
;
3352 /* Display the cursor on frame F, or clear it, according to ON.
3353 Use the position specified by curs_x and curs_y
3354 if we are doing an update of frame F now.
3355 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
3358 x_display_cursor (f
, on
)
3364 /* If we're not updating, then we want to use the current frame's
3365 cursor position, not our local idea of where the cursor ought to be. */
3366 if (f
!= updating_frame
)
3368 curs_x
= FRAME_CURSOR_X (f
);
3369 curs_y
= FRAME_CURSOR_Y (f
);
3372 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
3373 x_display_box_cursor (f
, on
);
3374 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
3375 x_display_bar_cursor (f
, on
);
3377 /* Those are the only two we have implemented! */
3383 /* Changing the font of the frame. */
3385 /* Give frame F the font named FONTNAME as its default font, and
3386 return the full name of that font. FONTNAME may be a wildcard
3387 pattern; in that case, we choose some font that fits the pattern.
3388 The return value shows which font we chose. */
3391 x_new_font (f
, fontname
)
3393 register char *fontname
;
3396 int n_matching_fonts
;
3397 XFontStruct
*font_info
;
3398 char new_font_name
[101];
3400 /* Get a font which matches this name */
3404 if (!x_to_w32_font(fontname
, &lf
)
3405 || !w32_to_x_font(&lf
, new_font_name
, 100))
3411 /* See if we've already loaded a matching font. */
3412 already_loaded
= -1;
3417 for (i
= 0; i
< FRAME_W32_DISPLAY_INFO (f
)->n_fonts
; i
++)
3418 if (!strcmp (FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
, new_font_name
))
3421 fontname
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[i
].name
;
3426 /* If we have, just return it from the table. */
3427 if (already_loaded
>= 0)
3428 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[already_loaded
].font
;
3429 /* Otherwise, load the font and add it to the table. */
3435 font
= w32_load_font(FRAME_W32_DISPLAY_INFO (f
), fontname
);
3442 /* Do we need to create the table? */
3443 if (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
== 0)
3445 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
= 16;
3446 FRAME_W32_DISPLAY_INFO (f
)->font_table
3447 = (struct font_info
*) xmalloc (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3448 * sizeof (struct font_info
));
3450 /* Do we need to grow the table? */
3451 else if (FRAME_W32_DISPLAY_INFO (f
)->n_fonts
3452 >= FRAME_W32_DISPLAY_INFO (f
)->font_table_size
)
3454 FRAME_W32_DISPLAY_INFO (f
)->font_table_size
*= 2;
3455 FRAME_W32_DISPLAY_INFO (f
)->font_table
3456 = (struct font_info
*) xrealloc (FRAME_W32_DISPLAY_INFO (f
)->font_table
,
3457 (FRAME_W32_DISPLAY_INFO (f
)->font_table_size
3458 * sizeof (struct font_info
)));
3461 n_fonts
= FRAME_W32_DISPLAY_INFO (f
)->n_fonts
;
3462 FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
= (char *) xmalloc (strlen (fontname
) + 1);
3463 bcopy (fontname
, FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].name
, strlen (fontname
) + 1);
3464 f
->output_data
.w32
->font
= FRAME_W32_DISPLAY_INFO (f
)->font_table
[n_fonts
].font
= font
;
3465 FRAME_W32_DISPLAY_INFO (f
)->n_fonts
++;
3468 /* Compute the scroll bar width in character columns. */
3469 if (f
->scroll_bar_pixel_width
> 0)
3471 int wid
= FONT_WIDTH (f
->output_data
.w32
->font
);
3472 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
3475 f
->scroll_bar_cols
= 2;
3477 /* Now make the frame display the given font. */
3478 if (FRAME_W32_WINDOW (f
) != 0)
3480 frame_update_line_height (f
);
3481 x_set_window_size (f
, 0, f
->width
, f
->height
);
3484 /* If we are setting a new frame's font for the first time,
3485 there are no faces yet, so this font's height is the line height. */
3486 f
->output_data
.w32
->line_height
= FONT_HEIGHT (f
->output_data
.w32
->font
);
3489 Lisp_Object lispy_name
;
3491 lispy_name
= build_string (fontname
);
3497 /* Calculate the absolute position in frame F
3498 from its current recorded position values and gravity. */
3500 x_calc_absolute_position (f
)
3505 int flags
= f
->output_data
.w32
->size_hint_flags
;
3509 /* Find the position of the outside upper-left corner of
3510 the inner window, with respect to the outer window. */
3511 if (f
->output_data
.w32
->parent_desc
!= FRAME_W32_DISPLAY_INFO (f
)->root_window
)
3514 MapWindowPoints (FRAME_W32_WINDOW (f
),
3515 f
->output_data
.w32
->parent_desc
,
3522 rt
.left
= rt
.right
= rt
.top
= rt
.bottom
= 0;
3525 AdjustWindowRect(&rt
, f
->output_data
.w32
->dwStyle
,
3526 FRAME_EXTERNAL_MENU_BAR (f
));
3529 pt
.x
+= (rt
.right
- rt
.left
);
3530 pt
.y
+= (rt
.bottom
- rt
.top
);
3533 /* Treat negative positions as relative to the leftmost bottommost
3534 position that fits on the screen. */
3535 if (flags
& XNegative
)
3536 f
->output_data
.w32
->left_pos
= (FRAME_W32_DISPLAY_INFO (f
)->width
3537 - 2 * f
->output_data
.w32
->border_width
- pt
.x
3539 + f
->output_data
.w32
->left_pos
);
3541 if (flags
& YNegative
)
3542 f
->output_data
.w32
->top_pos
= (FRAME_W32_DISPLAY_INFO (f
)->height
3543 - 2 * f
->output_data
.w32
->border_width
- pt
.y
3545 + f
->output_data
.w32
->top_pos
);
3546 /* The left_pos and top_pos
3547 are now relative to the top and left screen edges,
3548 so the flags should correspond. */
3549 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3552 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3553 to really change the position, and 0 when calling from
3554 x_make_frame_visible (in that case, XOFF and YOFF are the current
3555 position values). It is -1 when calling from x_set_frame_parameters,
3556 which means, do adjust for borders but don't change the gravity. */
3558 x_set_offset (f
, xoff
, yoff
, change_gravity
)
3560 register int xoff
, yoff
;
3563 int modified_top
, modified_left
;
3565 if (change_gravity
> 0)
3567 f
->output_data
.w32
->top_pos
= yoff
;
3568 f
->output_data
.w32
->left_pos
= xoff
;
3569 f
->output_data
.w32
->size_hint_flags
&= ~ (XNegative
| YNegative
);
3571 f
->output_data
.w32
->size_hint_flags
|= XNegative
;
3573 f
->output_data
.w32
->size_hint_flags
|= YNegative
;
3574 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3576 x_calc_absolute_position (f
);
3579 x_wm_set_size_hint (f
, (long) 0, 0);
3581 /* It is a mystery why we need to add the border_width here
3582 when the frame is already visible, but experiment says we do. */
3583 modified_left
= f
->output_data
.w32
->left_pos
;
3584 modified_top
= f
->output_data
.w32
->top_pos
;
3586 /* Do not add in border widths under W32. */
3587 if (change_gravity
!= 0)
3589 modified_left
+= f
->output_data
.w32
->border_width
;
3590 modified_top
+= f
->output_data
.w32
->border_width
;
3594 my_set_window_pos (FRAME_W32_WINDOW (f
),
3596 modified_left
, modified_top
,
3598 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
3602 /* Call this to change the size of frame F's x-window.
3603 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3604 for this size change and subsequent size changes.
3605 Otherwise we leave the window gravity unchanged. */
3607 x_set_window_size (f
, change_gravity
, cols
, rows
)
3612 int pixelwidth
, pixelheight
;
3614 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3618 check_frame_size (f
, &rows
, &cols
);
3619 f
->output_data
.w32
->vertical_scroll_bar_extra
3620 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3622 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3623 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3624 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.w32
->font
)));
3625 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
3626 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
3628 f
->output_data
.w32
->win_gravity
= NorthWestGravity
;
3629 x_wm_set_size_hint (f
, (long) 0, 0);
3634 rect
.left
= rect
.top
= 0;
3635 rect
.right
= pixelwidth
;
3636 rect
.bottom
= pixelheight
;
3638 AdjustWindowRect(&rect
, f
->output_data
.w32
->dwStyle
,
3639 FRAME_EXTERNAL_MENU_BAR (f
));
3641 my_set_window_pos (FRAME_W32_WINDOW (f
),
3644 rect
.right
- rect
.left
,
3645 rect
.bottom
- rect
.top
,
3646 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3649 /* Now, strictly speaking, we can't be sure that this is accurate,
3650 but the window manager will get around to dealing with the size
3651 change request eventually, and we'll hear how it went when the
3652 ConfigureNotify event gets here.
3654 We could just not bother storing any of this information here,
3655 and let the ConfigureNotify event set everything up, but that
3656 might be kind of confusing to the lisp code, since size changes
3657 wouldn't be reported in the frame parameters until some random
3658 point in the future when the ConfigureNotify event arrives. */
3659 change_frame_size (f
, rows
, cols
, 0, 0);
3660 PIXEL_WIDTH (f
) = pixelwidth
;
3661 PIXEL_HEIGHT (f
) = pixelheight
;
3663 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3664 receive in the ConfigureNotify event; if we get what we asked
3665 for, then the event won't cause the screen to become garbaged, so
3666 we have to make sure to do it here. */
3667 SET_FRAME_GARBAGED (f
);
3669 /* If cursor was outside the new size, mark it as off. */
3670 if (f
->phys_cursor_y
>= rows
3671 || f
->phys_cursor_x
>= cols
)
3673 f
->phys_cursor_x
= -1;
3674 f
->phys_cursor_y
= -1;
3677 /* Clear out any recollection of where the mouse highlighting was,
3678 since it might be in a place that's outside the new frame size.
3679 Actually checking whether it is outside is a pain in the neck,
3680 so don't try--just let the highlighting be done afresh with new size. */
3681 window
= dpyinfo
->mouse_face_window
;
3682 if (! NILP (window
) && XFRAME (window
) == f
)
3684 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
3685 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
3686 dpyinfo
->mouse_face_window
= Qnil
;
3692 /* Mouse warping. */
3695 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
3704 GetClientRect (FRAME_W32_WINDOW (f
), &rect
);
3705 pt
.x
= rect
.left
+ pix_x
;
3706 pt
.y
= rect
.top
+ pix_y
;
3707 ClientToScreen (FRAME_W32_WINDOW (f
), &pt
);
3709 SetCursorPos (pt
.x
, pt
.y
);
3715 x_set_mouse_position (f
, x
, y
)
3721 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.w32
->font
) / 2;
3722 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.w32
->line_height
/ 2;
3724 if (pix_x
< 0) pix_x
= 0;
3725 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
3727 if (pix_y
< 0) pix_y
= 0;
3728 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
3730 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
3733 /* focus shifting, raising and lowering. */
3735 x_focus_on_frame (f
)
3738 struct w32_display_info
*dpyinfo
= &one_w32_display_info
;
3740 /* Give input focus to frame. */
3743 /* Try not to change its Z-order if possible. */
3744 if (x_window_to_frame (dpyinfo
, GetForegroundWindow ()))
3745 my_set_focus (f
, FRAME_W32_WINDOW (f
));
3748 SetForegroundWindow (FRAME_W32_WINDOW (f
));
3757 /* Raise frame F. */
3764 /* Strictly speaking, raise-frame should only change the frame's Z
3765 order, leaving input focus unchanged. This is reasonable behaviour
3766 on X where the usual policy is point-to-focus. However, this
3767 behaviour would be very odd on Windows where the usual policy is
3770 On X, if the mouse happens to be over the raised frame, it gets
3771 input focus anyway (so the window with focus will never be
3772 completely obscured) - if not, then just moving the mouse over it
3773 is sufficient to give it focus. On Windows, the user must actually
3774 click on the frame (preferrably the title bar so as not to move
3775 point), which is more awkward. Also, no other Windows program
3776 raises a window to the top but leaves another window (possibly now
3777 completely obscured) with input focus.
3779 Because there is a system setting on Windows that allows the user
3780 to choose the point to focus policy, we make the strict semantics
3781 optional, but by default we grab focus when raising. */
3783 if (NILP (Vw32_grab_focus_on_raise
))
3785 /* The obvious call to my_set_window_pos doesn't work if Emacs is
3786 not already the foreground application: the frame is raised
3787 above all other frames belonging to us, but not above the
3788 current top window. To achieve that, we have to resort to this
3789 more cumbersome method. */
3791 HDWP handle
= BeginDeferWindowPos (2);
3794 DeferWindowPos (handle
,
3795 FRAME_W32_WINDOW (f
),
3798 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3800 DeferWindowPos (handle
,
3801 GetForegroundWindow (),
3802 FRAME_W32_WINDOW (f
),
3804 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3806 EndDeferWindowPos (handle
);
3811 SetForegroundWindow (FRAME_W32_WINDOW (f
));
3817 /* Lower frame F. */
3823 my_set_window_pos (FRAME_W32_WINDOW (f
),
3826 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
3831 w32_frame_raise_lower (f
, raise
)
3841 /* Change of visibility. */
3843 /* This tries to wait until the frame is really visible.
3844 However, if the window manager asks the user where to position
3845 the frame, this will return before the user finishes doing that.
3846 The frame will not actually be visible at that time,
3847 but it will become visible later when the window manager
3848 finishes with it. */
3850 x_make_frame_visible (f
)
3855 if (! FRAME_VISIBLE_P (f
))
3857 /* We test FRAME_GARBAGED_P here to make sure we don't
3858 call x_set_offset a second time
3859 if we get to x_make_frame_visible a second time
3860 before the window gets really visible. */
3861 if (! FRAME_ICONIFIED_P (f
)
3862 && ! f
->output_data
.w32
->asked_for_visible
)
3863 x_set_offset (f
, f
->output_data
.w32
->left_pos
, f
->output_data
.w32
->top_pos
, 0);
3865 f
->output_data
.w32
->asked_for_visible
= 1;
3867 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
3868 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_SHOWNORMAL
);
3871 /* Synchronize to ensure Emacs knows the frame is visible
3872 before we do anything else. We do this loop with input not blocked
3873 so that incoming events are handled. */
3876 int count
= input_signal_count
;
3878 /* This must come after we set COUNT. */
3881 XSETFRAME (frame
, f
);
3885 /* Once we have handled input events,
3886 we should have received the MapNotify if one is coming.
3887 So if we have not got it yet, stop looping.
3888 Some window managers make their own decisions
3889 about visibility. */
3890 if (input_signal_count
!= count
)
3892 /* Machines that do polling rather than SIGIO have been observed
3893 to go into a busy-wait here. So we'll fake an alarm signal
3894 to let the handler know that there's something to be read.
3895 We used to raise a real alarm, but it seems that the handler
3896 isn't always enabled here. This is probably a bug. */
3897 if (input_polling_used ())
3899 /* It could be confusing if a real alarm arrives while processing
3900 the fake one. Turn it off and let the handler reset it. */
3902 input_poll_signal ();
3904 /* Once we have handled input events,
3905 we should have received the MapNotify if one is coming.
3906 So if we have not got it yet, stop looping.
3907 Some window managers make their own decisions
3908 about visibility. */
3909 if (input_signal_count
!= count
)
3912 FRAME_SAMPLE_VISIBILITY (f
);
3916 /* Change from mapped state to withdrawn state. */
3918 /* Make the frame visible (mapped and not iconified). */
3920 x_make_frame_invisible (f
)
3925 /* Don't keep the highlight on an invisible frame. */
3926 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
3927 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
3931 my_show_window (f
, FRAME_W32_WINDOW (f
), SW_HIDE
);
3933 /* We can't distinguish this from iconification
3934 just by the event that we get from the server.
3935 So we can't win using the usual strategy of letting
3936 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3937 and synchronize with the server to make sure we agree. */
3939 FRAME_ICONIFIED_P (f
) = 0;
3940 f
->async_visible
= 0;
3941 f
->async_iconified
= 0;
3946 /* Change window state from mapped to iconified. */
3954 /* Don't keep the highlight on an invisible frame. */
3955 if (FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
== f
)
3956 FRAME_W32_DISPLAY_INFO (f
)->w32_highlight_frame
= 0;
3958 if (f
->async_iconified
)
3963 /* Simulate the user minimizing the frame. */
3964 PostMessage (FRAME_W32_WINDOW (f
), WM_SYSCOMMAND
, SC_MINIMIZE
, 0);
3966 f
->async_iconified
= 1;
3971 /* Destroy the window of frame F. */
3973 x_destroy_window (f
)
3976 struct w32_display_info
*dpyinfo
= FRAME_W32_DISPLAY_INFO (f
);
3980 my_destroy_window (f
, FRAME_W32_WINDOW (f
));
3981 free_frame_menubar (f
);
3982 free_frame_faces (f
);
3984 xfree (f
->output_data
.w32
);
3985 f
->output_data
.w32
= 0;
3986 if (f
== dpyinfo
->w32_focus_frame
)
3987 dpyinfo
->w32_focus_frame
= 0;
3988 if (f
== dpyinfo
->w32_focus_event_frame
)
3989 dpyinfo
->w32_focus_event_frame
= 0;
3990 if (f
== dpyinfo
->w32_highlight_frame
)
3991 dpyinfo
->w32_highlight_frame
= 0;
3993 dpyinfo
->reference_count
--;
3995 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3997 dpyinfo
->mouse_face_beg_row
3998 = dpyinfo
->mouse_face_beg_col
= -1;
3999 dpyinfo
->mouse_face_end_row
4000 = dpyinfo
->mouse_face_end_col
= -1;
4001 dpyinfo
->mouse_face_window
= Qnil
;
4007 /* Setting window manager hints. */
4009 /* Set the normal size hints for the window manager, for frame F.
4010 FLAGS is the flags word to use--or 0 meaning preserve the flags
4011 that the window now has.
4012 If USER_POSITION is nonzero, we set the USPosition
4013 flag (this is useful when FLAGS is 0). */
4015 x_wm_set_size_hint (f
, flags
, user_position
)
4020 Window window
= FRAME_W32_WINDOW (f
);
4022 flexlines
= f
->height
;
4026 SetWindowLong (window
, WND_FONTWIDTH_INDEX
, FONT_WIDTH (f
->output_data
.w32
->font
));
4027 SetWindowLong (window
, WND_LINEHEIGHT_INDEX
, f
->output_data
.w32
->line_height
);
4028 SetWindowLong (window
, WND_BORDER_INDEX
, f
->output_data
.w32
->internal_border_width
);
4029 SetWindowLong (window
, WND_SCROLLBAR_INDEX
, f
->output_data
.w32
->vertical_scroll_bar_extra
);
4034 /* Window manager things */
4035 x_wm_set_icon_position (f
, icon_x
, icon_y
)
4040 Window window
= FRAME_W32_WINDOW (f
);
4042 f
->display
.x
->wm_hints
.flags
|= IconPositionHint
;
4043 f
->display
.x
->wm_hints
.icon_x
= icon_x
;
4044 f
->display
.x
->wm_hints
.icon_y
= icon_y
;
4046 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->display
.x
->wm_hints
);
4051 /* Initialization. */
4053 #ifdef USE_X_TOOLKIT
4054 static XrmOptionDescRec emacs_options
[] = {
4055 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
4056 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
4058 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4059 XrmoptionSepArg
, NULL
},
4060 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
4062 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4063 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4064 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
4065 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4066 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
4067 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
4068 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
4070 #endif /* USE_X_TOOLKIT */
4072 static int w32_initialized
= 0;
4074 struct w32_display_info
*
4075 w32_term_init (display_name
, xrm_option
, resource_name
)
4076 Lisp_Object display_name
;
4078 char *resource_name
;
4082 struct w32_display_info
*dpyinfo
;
4087 if (!w32_initialized
)
4090 w32_initialized
= 1;
4101 argv
[argc
++] = "-xrm";
4102 argv
[argc
++] = xrm_option
;
4106 dpyinfo
= &one_w32_display_info
;
4108 /* Put this display on the chain. */
4109 dpyinfo
->next
= NULL
;
4111 /* Put it on w32_display_name_list as well, to keep them parallel. */
4112 w32_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
4113 w32_display_name_list
);
4114 dpyinfo
->name_list_element
= XCONS (w32_display_name_list
)->car
;
4116 dpyinfo
->w32_id_name
4117 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
4118 + XSTRING (Vsystem_name
)->size
4120 sprintf (dpyinfo
->w32_id_name
, "%s@%s",
4121 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
4124 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
4125 resource_name
, EMACS_CLASS
);
4127 /* Put the rdb where we can find it in a way that works on
4129 dpyinfo
->xrdb
= xrdb
;
4131 hdc
= GetDC (GetDesktopWindow ());
4133 dpyinfo
->height
= GetDeviceCaps (hdc
, VERTRES
);
4134 dpyinfo
->width
= GetDeviceCaps (hdc
, HORZRES
);
4135 dpyinfo
->root_window
= GetDesktopWindow ();
4136 dpyinfo
->n_planes
= GetDeviceCaps (hdc
, PLANES
);
4137 dpyinfo
->n_cbits
= GetDeviceCaps (hdc
, BITSPIXEL
);
4138 dpyinfo
->height_in
= GetDeviceCaps (hdc
, LOGPIXELSX
);
4139 dpyinfo
->width_in
= GetDeviceCaps (hdc
, LOGPIXELSY
);
4140 dpyinfo
->has_palette
= GetDeviceCaps (hdc
, RASTERCAPS
) & RC_PALETTE
;
4141 dpyinfo
->grabbed
= 0;
4142 dpyinfo
->reference_count
= 0;
4143 dpyinfo
->n_fonts
= 0;
4144 dpyinfo
->font_table_size
= 0;
4145 dpyinfo
->bitmaps
= 0;
4146 dpyinfo
->bitmaps_size
= 0;
4147 dpyinfo
->bitmaps_last
= 0;
4148 dpyinfo
->mouse_face_mouse_frame
= 0;
4149 dpyinfo
->mouse_face_deferred_gc
= 0;
4150 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
4151 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
4152 dpyinfo
->mouse_face_face_id
= 0;
4153 dpyinfo
->mouse_face_window
= Qnil
;
4154 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
4155 dpyinfo
->mouse_face_defer
= 0;
4156 dpyinfo
->w32_focus_frame
= 0;
4157 dpyinfo
->w32_focus_event_frame
= 0;
4158 dpyinfo
->w32_highlight_frame
= 0;
4160 ReleaseDC (GetDesktopWindow (), hdc
);
4162 /* Determine if there is a middle mouse button, to allow parse_button
4163 to decide whether right mouse events should be mouse-2 or
4165 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
4167 /* initialise palette with white and black */
4170 defined_color (0, "white", &color
, 1);
4171 defined_color (0, "black", &color
, 1);
4174 #ifndef F_SETOWN_BUG
4176 #ifdef F_SETOWN_SOCK_NEG
4177 /* stdin is a socket here */
4178 fcntl (connection
, F_SETOWN
, -getpid ());
4179 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4180 fcntl (connection
, F_SETOWN
, getpid ());
4181 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4182 #endif /* ! defined (F_SETOWN) */
4183 #endif /* F_SETOWN_BUG */
4186 if (interrupt_input
)
4187 init_sigio (connection
);
4188 #endif /* ! defined (SIGIO) */
4195 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4198 x_delete_display (dpyinfo
)
4199 struct w32_display_info
*dpyinfo
;
4201 /* Discard this display from w32_display_name_list and w32_display_list.
4202 We can't use Fdelq because that can quit. */
4203 if (! NILP (w32_display_name_list
)
4204 && EQ (XCONS (w32_display_name_list
)->car
, dpyinfo
->name_list_element
))
4205 w32_display_name_list
= XCONS (w32_display_name_list
)->cdr
;
4210 tail
= w32_display_name_list
;
4211 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
4213 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
4214 dpyinfo
->name_list_element
))
4216 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
4219 tail
= XCONS (tail
)->cdr
;
4223 /* free palette table */
4225 struct w32_palette_entry
* plist
;
4227 plist
= dpyinfo
->color_list
;
4230 struct w32_palette_entry
* pentry
= plist
;
4231 plist
= plist
->next
;
4234 dpyinfo
->color_list
= NULL
;
4235 if (dpyinfo
->palette
)
4236 DeleteObject(dpyinfo
->palette
);
4238 xfree (dpyinfo
->font_table
);
4239 xfree (dpyinfo
->w32_id_name
);
4242 /* Set up use of W32. */
4244 DWORD
w32_msg_worker ();
4248 clear_frame_hook
= w32_clear_frame
;
4249 clear_end_of_line_hook
= w32_clear_end_of_line
;
4250 ins_del_lines_hook
= w32_ins_del_lines
;
4251 change_line_highlight_hook
= w32_change_line_highlight
;
4252 insert_glyphs_hook
= w32_insert_glyphs
;
4253 write_glyphs_hook
= w32_write_glyphs
;
4254 delete_glyphs_hook
= w32_delete_glyphs
;
4255 ring_bell_hook
= w32_ring_bell
;
4256 reset_terminal_modes_hook
= w32_reset_terminal_modes
;
4257 set_terminal_modes_hook
= w32_set_terminal_modes
;
4258 update_begin_hook
= w32_update_begin
;
4259 update_end_hook
= w32_update_end
;
4260 set_terminal_window_hook
= w32_set_terminal_window
;
4261 read_socket_hook
= w32_read_socket
;
4262 frame_up_to_date_hook
= w32_frame_up_to_date
;
4263 cursor_to_hook
= w32_cursor_to
;
4264 reassert_line_highlight_hook
= w32_reassert_line_highlight
;
4265 mouse_position_hook
= w32_mouse_position
;
4266 frame_rehighlight_hook
= w32_frame_rehighlight
;
4267 frame_raise_lower_hook
= w32_frame_raise_lower
;
4268 set_vertical_scroll_bar_hook
= w32_set_vertical_scroll_bar
;
4269 condemn_scroll_bars_hook
= w32_condemn_scroll_bars
;
4270 redeem_scroll_bar_hook
= w32_redeem_scroll_bar
;
4271 judge_scroll_bars_hook
= w32_judge_scroll_bars
;
4273 scroll_region_ok
= 1; /* we'll scroll partial frames */
4274 char_ins_del_ok
= 0; /* just as fast to write the line */
4275 line_ins_del_ok
= 1; /* we'll just blt 'em */
4276 fast_clear_end_of_line
= 1; /* X does this well */
4277 memory_below_frame
= 0; /* we don't remember what scrolls
4281 /* Initialize input mode: interrupt_input off, no flow control, allow
4282 8 bit character input, standard quit char. */
4283 Fset_input_mode (Qnil
, Qnil
, make_number (2), Qnil
);
4285 /* Create the window thread - it will terminate itself or when the app terminates */
4289 dwMainThreadId
= GetCurrentThreadId ();
4290 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
4291 GetCurrentProcess (), &hMainThread
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
4293 /* Wait for thread to start */
4298 PeekMessage (&msg
, NULL
, 0, 0, PM_NOREMOVE
);
4300 hWindowsThread
= CreateThread (NULL
, 0,
4301 (LPTHREAD_START_ROUTINE
) w32_msg_worker
,
4302 0, 0, &dwWindowsThreadId
);
4304 GetMessage (&msg
, NULL
, WM_EMACS_DONE
, WM_EMACS_DONE
);
4307 /* It is desirable that mainThread should have the same notion of
4308 focus window and active window as windowsThread. Unfortunately, the
4309 following call to AttachThreadInput, which should do precisely what
4310 we need, causes major problems when Emacs is linked as a console
4311 program. Unfortunately, we have good reasons for doing that, so
4312 instead we need to send messages to windowsThread to make some API
4313 calls for us (ones that affect, or depend on, the active/focus
4315 #ifdef ATTACH_THREADS
4316 AttachThreadInput (dwMainThreadId
, dwWindowsThreadId
, TRUE
);
4319 /* Dynamically link to optional system components. */
4321 HANDLE user_lib
= LoadLibrary ("user32.dll");
4323 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
4325 /* New proportional scroll bar functions. */
4326 LOAD_PROC( SetScrollInfo
);
4327 LOAD_PROC( GetScrollInfo
);
4331 FreeLibrary (user_lib
);
4333 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
4334 otherwise use the fixed height. */
4335 vertical_scroll_bar_min_handle
= (pfnSetScrollInfo
!= NULL
) ? 5 :
4336 GetSystemMetrics (SM_CYVTHUMB
);
4338 /* For either kind of scroll bar, take account of the arrows; these
4339 effectively form the border of the main scroll bar range. */
4340 vertical_scroll_bar_top_border
= vertical_scroll_bar_bottom_border
4341 = GetSystemMetrics (SM_CYVSCROLL
);
4348 staticpro (&w32_display_name_list
);
4349 w32_display_name_list
= Qnil
;
4351 staticpro (&last_mouse_scroll_bar
);
4352 last_mouse_scroll_bar
= Qnil
;
4354 staticpro (&Qvendor_specific_keysyms
);
4355 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
4357 DEFVAR_INT ("w32-num-mouse-buttons",
4358 &Vw32_num_mouse_buttons
,
4359 "Number of physical mouse buttons.");
4360 Vw32_num_mouse_buttons
= Qnil
;
4362 DEFVAR_LISP ("w32-swap-mouse-buttons",
4363 &Vw32_swap_mouse_buttons
,
4364 "Swap the mapping of middle and right mouse buttons.\n\
4365 When nil, middle button is mouse-2 and right button is mouse-3.");
4366 Vw32_swap_mouse_buttons
= Qnil
;
4368 DEFVAR_LISP ("w32-grab-focus-on-raise",
4369 &Vw32_grab_focus_on_raise
,
4370 "Raised frame grabs input focus.\n\
4371 When t, `raise-frame' grabs input focus as well. This fits well\n\
4372 with the normal Windows click-to-focus policy, but might not be\n\
4373 desirable when using a point-to-focus policy.");
4374 Vw32_grab_focus_on_raise
= Qt
;
4376 DEFVAR_LISP ("w32-capslock-is-shiftlock",
4377 &Vw32_capslock_is_shiftlock
,
4378 "Apply CapsLock state to non character input keys.\n\
4379 When nil, CapsLock only affects normal character input keys.");
4380 Vw32_capslock_is_shiftlock
= Qnil
;