(SIF_*): Win95 macros defined for NT.
[bpt/emacs.git] / src / w32term.c
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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)
9 any later version.
10
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.
15
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. */
20
21 /* Added by Kevin Gallo */
22
23 #include <signal.h>
24 #include <config.h>
25 #include <stdio.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
29
30 #include "w32term.h"
31
32 #include "systty.h"
33 #include "systime.h"
34
35 #include <ctype.h>
36 #include <errno.h>
37 #include <setjmp.h>
38 #include <sys/stat.h>
39
40 #include "frame.h"
41 #include "dispextern.h"
42 #include "termhooks.h"
43 #include "termopts.h"
44 #include "termchar.h"
45 #include "gnu.h"
46 #include "disptab.h"
47 #include "buffer.h"
48 #include "window.h"
49 #include "keyboard.h"
50 #include "intervals.h"
51
52 extern void free_frame_menubar ();
53
54 extern Lisp_Object Vwindow_system;
55
56 #define x_any_window_to_frame x_window_to_frame
57 #define x_top_window_to_frame x_window_to_frame
58
59 \f
60 /* This is display since w32 does not support multiple ones. */
61 struct w32_display_info one_w32_display_info;
62
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;
68
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;
75
76 /* This is a frame waiting to be autoraised, within w32_read_socket. */
77 struct frame *pending_autoraise_frame;
78
79 /* During an update, maximum vpos for ins/del line operations to affect. */
80
81 static int flexlines;
82
83 /* During an update, nonzero if chars output now should be highlighted. */
84
85 static int highlight;
86
87 /* Nominal cursor position -- where to draw output.
88 During an update, these are different from the cursor-box position. */
89
90 static int curs_x;
91 static int curs_y;
92
93 DWORD dwWindowsThreadId = 0;
94 HANDLE hWindowsThread = NULL;
95 DWORD dwMainThreadId = 0;
96 HANDLE hMainThread = NULL;
97
98 #ifndef SIF_ALL
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)
106
107 typedef struct tagSCROLLINFO
108 {
109 UINT cbSize;
110 UINT fMask;
111 int nMin;
112 int nMax;
113 UINT nPage;
114 int nPos;
115 int nTrackPos;
116 } SCROLLINFO, FAR *LPSCROLLINFO;
117 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
118 #endif /* SIF_ALL */
119
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);
123
124 int vertical_scroll_bar_min_handle;
125 int vertical_scroll_bar_top_border;
126 int vertical_scroll_bar_bottom_border;
127
128 int last_scroll_bar_drag_pos;
129
130 /* Mouse movement. */
131
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;
135
136 Lisp_Object Vw32_num_mouse_buttons;
137
138 Lisp_Object Vw32_swap_mouse_buttons;
139
140 /* Control whether x_raise_frame also sets input focus. */
141 Lisp_Object Vw32_grab_focus_on_raise;
142
143 /* Control whether Caps Lock affects non-ascii characters. */
144 Lisp_Object Vw32_capslock_is_shiftlock;
145
146 /* The scroll bar in which the last motion event occurred.
147
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
150 an ordinary motion.
151
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;
156
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;
164
165 /* Incremented by w32_read_socket whenever it really tries to read events. */
166 #ifdef __STDC__
167 static int volatile input_signal_count;
168 #else
169 static int input_signal_count;
170 #endif
171
172 extern Lisp_Object Vcommand_line_args, Vsystem_name;
173
174 extern Lisp_Object Qface, Qmouse_face;
175
176 extern int errno;
177
178 /* A mask of extra modifier bits to put into every keyboard char. */
179 extern int extra_keyboard_modifiers;
180
181 static Lisp_Object Qvendor_specific_keysyms;
182
183 void w32_delete_display ();
184
185 static void redraw_previous_char ();
186 static void redraw_following_char ();
187 static unsigned int w32_get_modifiers ();
188
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 ();
194
195 static int w32_cursor_to ();
196 static int w32_clear_end_of_line ();
197 \f
198 #if 0
199 /* This is a function useful for recording debugging information
200 about the sequence of occurrences in this file. */
201
202 struct record
203 {
204 char *locus;
205 int type;
206 };
207
208 struct record event_record[100];
209
210 int event_record_index;
211
212 record_event (locus, type)
213 char *locus;
214 int type;
215 {
216 if (event_record_index == sizeof (event_record) / sizeof (struct record))
217 event_record_index = 0;
218
219 event_record[event_record_index].locus = locus;
220 event_record[event_record_index].type = type;
221 event_record_index++;
222 }
223
224 #endif /* 0 */
225 \f
226 /* Return the struct w32_display_info. */
227
228 struct w32_display_info *
229 w32_display_info_for_display ()
230 {
231 return (&one_w32_display_info);
232 }
233
234 void
235 w32_fill_rect (f, _hdc, pix, lprect)
236 FRAME_PTR f;
237 HDC _hdc;
238 COLORREF pix;
239 RECT * lprect;
240 {
241 HDC hdc;
242 HBRUSH hb;
243 RECT rect;
244
245 if (_hdc)
246 hdc = _hdc;
247 else
248 {
249 if (!f) return;
250 hdc = get_frame_dc (f);
251 }
252
253 hb = CreateSolidBrush (pix);
254 FillRect (hdc, lprect, hb);
255 DeleteObject (hb);
256
257 if (!_hdc)
258 release_frame_dc (f, hdc);
259 }
260
261 void
262 w32_clear_window (f)
263 FRAME_PTR f;
264 {
265 RECT rect;
266
267 GetClientRect (FRAME_W32_WINDOW (f), &rect);
268 w32_clear_rect (f, NULL, &rect);
269 }
270
271 \f
272 /* Starting and ending updates.
273
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. */
280
281 static
282 w32_update_begin (f)
283 struct frame *f;
284 {
285 if (f == 0)
286 abort ();
287
288 flexlines = f->height;
289 highlight = 0;
290
291 BLOCK_INPUT;
292
293 /* Regenerate display palette before drawing if list of requested
294 colors has changed. */
295 if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
296 {
297 w32_regenerate_palette (f);
298 FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
299 }
300
301 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
302 {
303 /* Don't do highlighting for mouse motion during the update. */
304 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
305
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;
310
311 if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
312 {
313 int firstline, lastline, i;
314 struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
315
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])
319 break;
320
321 lastline = f->height;
322 for (i = f->height - 1; i >= 0; i--)
323 {
324 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
325 break;
326 else
327 lastline = i;
328 }
329
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));
338 }
339 }
340
341 UNBLOCK_INPUT;
342 }
343
344 static
345 w32_update_end (f)
346 struct frame *f;
347 {
348 BLOCK_INPUT;
349
350 do_line_dance ();
351 x_display_cursor (f, 1);
352
353 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
354 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
355
356 UNBLOCK_INPUT;
357 }
358
359 /* This is called after a redisplay on frame F. */
360
361 static
362 w32_frame_up_to_date (f)
363 FRAME_PTR f;
364 {
365 BLOCK_INPUT;
366 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
367 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
368 {
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;
373 }
374 UNBLOCK_INPUT;
375 }
376 \f
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. */
380
381 w32_reassert_line_highlight (new, vpos)
382 int new, vpos;
383 {
384 highlight = new;
385 }
386
387 /* Call this when about to modify line at position VPOS
388 and change whether it is highlighted. */
389
390 static
391 w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
392 int new_highlight, vpos, first_unused_hpos;
393 {
394 highlight = new_highlight;
395 w32_cursor_to (vpos, 0);
396 w32_clear_end_of_line (updating_frame->width);
397 }
398
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). */
402
403 static
404 w32_set_terminal_modes ()
405 {
406 }
407
408 /* This is called when exiting or suspending Emacs.
409 Exiting will make the W32 windows go away, and suspending
410 requires no action. */
411
412 static
413 w32_reset_terminal_modes ()
414 {
415 }
416 \f
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. */
420
421 static int
422 w32_cursor_to (row, col)
423 register int row, col;
424 {
425 int orow = row;
426
427 curs_x = col;
428 curs_y = row;
429
430 if (updating_frame == 0)
431 {
432 BLOCK_INPUT;
433 x_display_cursor (selected_frame, 1);
434 UNBLOCK_INPUT;
435 }
436 }
437 \f
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.
444
445 FONT is the default font to use (for glyphs whose font-code is 0).
446
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. */
453
454 static void
455 dumpglyphs (f, left, top, gp, n, hl, just_foreground)
456 struct frame *f;
457 int left, top;
458 register GLYPH *gp; /* Points to first GLYPH. */
459 register int n; /* Number of glyphs to display. */
460 int hl;
461 int just_foreground;
462 {
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;
470 HDC hdc;
471
472 hdc = get_frame_dc (f);
473
474 while (n > 0)
475 {
476 /* Get the face-code of the next GLYPH. */
477 int cf, len;
478 int g = *gp;
479
480 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
481 cf = FAST_GLYPH_FACE (g);
482
483 /* Find the run of consecutive glyphs with the same face-code.
484 Extract their character codes into BUF. */
485 cp = buf;
486 while (n > 0)
487 {
488 g = *gp;
489 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
490 if (FAST_GLYPH_FACE (g) != cf)
491 break;
492
493 *cp++ = FAST_GLYPH_CHAR (g);
494 --n;
495 ++gp;
496 }
497
498 /* LEN gets the length of the run. */
499 len = cp - buf;
500
501 /* Now output this run of chars, with the font and pixel values
502 determined by the face code CF. */
503 {
504 struct face *face = FRAME_DEFAULT_FACE (f);
505 XFontStruct *font = FACE_FONT (face);
506 int stippled = 0;
507 COLORREF fg;
508 COLORREF bg;
509
510 /* HL = 3 means use a mouse face previously chosen. */
511 if (hl == 3)
512 cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
513
514 /* First look at the face of the text itself. */
515 if (cf != 0)
516 {
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)
521 cf = 0;
522
523 if (cf == 1)
524 face = FRAME_MODE_LINE_FACE (f);
525 else
526 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
527 font = FACE_FONT (face);
528 if (FACE_STIPPLE (face))
529 stippled = 1;
530 }
531
532 /* Then comes the distinction between modeline and normal text. */
533 else if (hl == 0)
534 ;
535 else if (hl == 1)
536 {
537 face = FRAME_MODE_LINE_FACE (f);
538 font = FACE_FONT (face);
539 if (FACE_STIPPLE (face))
540 stippled = 1;
541 }
542
543 fg = face->foreground;
544 bg = face->background;
545
546 /* Now override that if the cursor's on this character. */
547 if (hl == 2)
548 {
549 /* The cursor overrides stippling. */
550 stippled = 0;
551
552 if ((!face->font
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)
557 {
558 bg = f->output_data.w32->cursor_pixel;
559 fg = face->background;
560 }
561 /* Cursor on non-default face: must merge. */
562 else
563 {
564 bg = f->output_data.w32->cursor_pixel;
565 fg = face->background;
566 /* If the glyph would be invisible,
567 try a different foreground. */
568 if (fg == bg)
569 fg = face->foreground;
570 if (fg == bg)
571 fg = f->output_data.w32->cursor_foreground_pixel;
572 if (fg == bg)
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)
577 {
578 bg = face->foreground;
579 fg = face->background;
580 }
581 }
582 }
583
584 if (font == (XFontStruct *) FACE_DEFAULT)
585 font = f->output_data.w32->font;
586
587 SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
588
589 SetTextColor (hdc, fg);
590 SetBkColor (hdc, bg);
591
592 SelectObject (hdc, font->hfont);
593
594 TextOut (hdc, left, top, buf, len);
595
596 if (!just_foreground)
597 {
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,
601 left,
602 top + FONT_HEIGHT (font),
603 FONT_WIDTH (font) * len,
604 f->output_data.w32->line_height - FONT_HEIGHT (font));
605 }
606
607 {
608 int underline_position = 1;
609
610 if (font->tm.tmDescent <= underline_position)
611 underline_position = font->tm.tmDescent - 1;
612
613 if (face->underline)
614 w32_fill_area (f, hdc, fg,
615 left, (top
616 + FONT_BASE (font)
617 + underline_position),
618 len * FONT_WIDTH (font), 1);
619 }
620
621 left += len * FONT_WIDTH (font);
622 }
623 }
624
625 release_frame_dc (f, hdc);
626 }
627
628 \f
629 /* Output some text at the nominal frame cursor position.
630 Advance the cursor over the text.
631 Output LEN glyphs at START.
632
633 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
634 controls the pixel values used for foreground and background. */
635
636 static
637 w32_write_glyphs (start, len)
638 register GLYPH *start;
639 int len;
640 {
641 register int temp_length;
642 struct frame *f;
643
644 BLOCK_INPUT;
645
646 do_line_dance ();
647 f = updating_frame;
648 if (f == 0)
649 {
650 f = selected_frame;
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;
655 }
656
657 dumpglyphs (f,
658 CHAR_TO_PIXEL_COL (f, curs_x),
659 CHAR_TO_PIXEL_ROW (f, curs_y),
660 start, len, highlight, 0);
661
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;
667
668 if (updating_frame == 0)
669 {
670 f->cursor_x += len;
671 x_display_cursor (f, 1);
672 f->cursor_x -= len;
673 }
674 else
675 curs_x += len;
676
677 UNBLOCK_INPUT;
678 }
679 \f
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. */
684
685 static
686 w32_clear_end_of_line (first_unused)
687 register int first_unused;
688 {
689 struct frame *f = updating_frame;
690
691 if (f == 0)
692 abort ();
693
694 if (curs_y < 0 || curs_y >= f->height)
695 return 1;
696 if (first_unused <= 0)
697 return 1;
698
699 if (first_unused >= f->width)
700 first_unused = f->width;
701
702 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
703
704 BLOCK_INPUT;
705
706 do_line_dance ();
707
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;
713
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);
719
720 UNBLOCK_INPUT;
721 }
722
723 static
724 w32_clear_frame ()
725 {
726 struct frame *f = updating_frame;
727
728 if (f == 0)
729 f = selected_frame;
730
731 f->phys_cursor_x = -1; /* Cursor not visible. */
732 curs_x = 0; /* Nominal cursor position is top left. */
733 curs_y = 0;
734
735 BLOCK_INPUT;
736
737 w32_clear_window (f);
738
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);
742
743 UNBLOCK_INPUT;
744 }
745 \f
746 /* Make audible bell. */
747
748 w32_ring_bell ()
749 {
750 BLOCK_INPUT;
751
752 if (visible_bell)
753 FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
754 else
755 w32_sys_ring_bell ();
756
757 UNBLOCK_INPUT;
758
759 return 1;
760 }
761 \f
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. */
765
766 static
767 w32_insert_glyphs (start, len)
768 register char *start;
769 register int len;
770 {
771 abort ();
772 }
773
774 static
775 w32_delete_glyphs (n)
776 register int n;
777 {
778 abort ();
779 }
780 \f
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. */
785
786 static
787 w32_set_terminal_window (n)
788 register int n;
789 {
790 if (updating_frame == 0)
791 abort ();
792
793 if ((n <= 0) || (n > updating_frame->height))
794 flexlines = updating_frame->height;
795 else
796 flexlines = n;
797 }
798 \f
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. */
803
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;
808
809 /* Allocated length of that array. */
810 static int line_dance_len;
811
812 /* Flag indicating whether we've done any work. */
813 static int line_dance_in_progress;
814
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)
818 int vpos, n;
819 {
820 register int fence, i;
821
822 if (vpos >= flexlines)
823 return 1;
824
825 if (!line_dance_in_progress)
826 {
827 int ht = updating_frame->height;
828 if (ht > line_dance_len)
829 {
830 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
831 line_dance_len = ht;
832 }
833 for (i = 0; i < ht; ++i) line_dance[i] = i;
834 line_dance_in_progress = 1;
835 }
836 if (n >= 0)
837 {
838 if (n > flexlines - vpos)
839 n = flexlines - vpos;
840 fence = vpos + n;
841 for (i = flexlines; --i >= fence;)
842 line_dance[i] = line_dance[i-n];
843 for (i = fence; --i >= vpos;)
844 line_dance[i] = -1;
845 }
846 else
847 {
848 n = -n;
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)
855 line_dance[i] = -1;
856 }
857 }
858
859 /* Here's where we actually move the pixels around.
860 Must be called with input blocked. */
861 static void
862 do_line_dance ()
863 {
864 register int i, j, distance;
865 register struct frame *f;
866 int ht;
867 int intborder;
868 HDC hdc;
869
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)
873 return;
874
875 f = updating_frame;
876 if (f == 0)
877 abort ();
878
879 ht = f->height;
880 intborder = f->output_data.w32->internal_border_width;
881
882 x_display_cursor (updating_frame, 0);
883
884 hdc = get_frame_dc (f);
885
886 for (i = 0; i < ht; ++i)
887 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
888 {
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) */
892 BitBlt (hdc,
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,
896 hdc,
897 intborder, CHAR_TO_PIXEL_ROW (f, i),
898 SRCCOPY);
899 i = j-1;
900 }
901
902 for (i = ht; --i >=0; )
903 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
904 {
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] */
908 BitBlt (hdc,
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,
912 hdc,
913 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
914 SRCCOPY);
915 i = j+1;
916 }
917
918 for (i = 0; i < ht; ++i)
919 if (line_dance[i] == -1)
920 {
921 for (j = i; j < ht && line_dance[j] == -1; ++j);
922 /* Clear [i,j) */
923 w32_clear_area (f, hdc,
924 intborder,
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);
928 i = j-1;
929 }
930 line_dance_in_progress = 0;
931
932 release_frame_dc (f, hdc);
933 }
934 \f
935 /* Support routines for exposure events. */
936 static void clear_cursor ();
937
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. */
943
944 void
945 dumprectangle (f, left, top, cols, rows)
946 struct frame *f;
947 register int left, top, cols, rows;
948 {
949 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
950 int cursor_cleared = 0;
951 int bottom, right;
952 register int y;
953
954 if (FRAME_GARBAGED_P (f))
955 return;
956
957 /* Express rectangle as four edges, instead of position-and-size. */
958 bottom = top + rows;
959 right = left + cols;
960
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);
969
970 /* Clip the rectangle to what can be visible. */
971 if (left < 0)
972 left = 0;
973 if (top < 0)
974 top = 0;
975 if (right > f->width)
976 right = f->width;
977 if (bottom > f->height)
978 bottom = f->height;
979
980 /* Get size in chars of the rectangle. */
981 cols = right - left;
982 rows = bottom - top;
983
984 /* If rectangle has zero area, return. */
985 if (rows <= 0) return;
986 if (cols <= 0) return;
987
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))
992 {
993 clear_cursor (f);
994 cursor_cleared = 1;
995 }
996
997 /* Display the text in the rectangle, one text line at a time. */
998
999 for (y = top; y < bottom; y++)
1000 {
1001 GLYPH *line = &active_frame->glyphs[y][left];
1002
1003 if (! active_frame->enable[y] || left > active_frame->used[y])
1004 continue;
1005
1006 dumpglyphs (f,
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);
1011 }
1012
1013 /* Turn the cursor on if we turned it off. */
1014
1015 if (cursor_cleared)
1016 x_display_cursor (f, 1);
1017 }
1018 \f
1019 static void
1020 frame_highlight (f)
1021 struct frame *f;
1022 {
1023 x_display_cursor (f, 1);
1024 }
1025
1026 static void
1027 frame_unhighlight (f)
1028 struct frame *f;
1029 {
1030 x_display_cursor (f, 1);
1031 }
1032
1033 static void w32_frame_rehighlight ();
1034 static void x_frame_rehighlight ();
1035
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. */
1041
1042 void
1043 x_new_focus_frame (dpyinfo, frame)
1044 struct w32_display_info *dpyinfo;
1045 struct frame *frame;
1046 {
1047 struct frame *old_focus = dpyinfo->w32_focus_frame;
1048 int events_enqueued = 0;
1049
1050 if (frame != dpyinfo->w32_focus_frame)
1051 {
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;
1055
1056 if (old_focus && old_focus->auto_lower)
1057 x_lower_frame (old_focus);
1058
1059 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
1060 pending_autoraise_frame = dpyinfo->w32_focus_frame;
1061 else
1062 pending_autoraise_frame = 0;
1063 }
1064
1065 x_frame_rehighlight (dpyinfo);
1066 }
1067
1068 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1069
1070 void
1071 x_mouse_leave (dpyinfo)
1072 struct w32_display_info *dpyinfo;
1073 {
1074 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
1075 }
1076
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.
1080
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. */
1084 static void
1085 w32_frame_rehighlight (frame)
1086 struct frame *frame;
1087 {
1088 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
1089 }
1090
1091 static void
1092 x_frame_rehighlight (dpyinfo)
1093 struct w32_display_info *dpyinfo;
1094 {
1095 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
1096
1097 if (dpyinfo->w32_focus_frame)
1098 {
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))
1104 {
1105 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
1106 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
1107 }
1108 }
1109 else
1110 dpyinfo->w32_highlight_frame = 0;
1111
1112 if (dpyinfo->w32_highlight_frame != old_highlight)
1113 {
1114 if (old_highlight)
1115 frame_unhighlight (old_highlight);
1116 if (dpyinfo->w32_highlight_frame)
1117 frame_highlight (dpyinfo->w32_highlight_frame);
1118 }
1119 }
1120 \f
1121 /* Keyboard processing - modifier keys, etc. */
1122
1123 /* Convert a keysym to its name. */
1124
1125 char *
1126 x_get_keysym_name (keysym)
1127 int keysym;
1128 {
1129 /* Make static so we can always return it */
1130 static char value[100];
1131
1132 BLOCK_INPUT;
1133 GetKeyNameText(keysym, value, 100);
1134 UNBLOCK_INPUT;
1135
1136 return value;
1137 }
1138 \f
1139 /* Mouse clicks and mouse movement. Rah. */
1140
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. */
1145
1146 void
1147 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1148 FRAME_PTR f;
1149 register int pix_x, pix_y;
1150 register int *x, *y;
1151 RECT *bounds;
1152 int noclip;
1153 {
1154 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1155 if (NILP (Vwindow_system))
1156 {
1157 *x = pix_x;
1158 *y = pix_y;
1159 return;
1160 }
1161
1162 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1163 even for negative values. */
1164 if (pix_x < 0)
1165 pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
1166 if (pix_y < 0)
1167 pix_y -= (f)->output_data.w32->line_height - 1;
1168
1169 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1170 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1171
1172 if (bounds)
1173 {
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;
1178 }
1179
1180 if (!noclip)
1181 {
1182 if (pix_x < 0)
1183 pix_x = 0;
1184 else if (pix_x > f->width)
1185 pix_x = f->width;
1186
1187 if (pix_y < 0)
1188 pix_y = 0;
1189 else if (pix_y > f->height)
1190 pix_y = f->height;
1191 }
1192
1193 *x = pix_x;
1194 *y = pix_y;
1195 }
1196
1197 void
1198 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1199 FRAME_PTR f;
1200 register int x, y;
1201 register int *pix_x, *pix_y;
1202 {
1203 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1204 if (NILP (Vwindow_system))
1205 {
1206 *pix_x = x;
1207 *pix_y = y;
1208 return;
1209 }
1210
1211 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1212 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1213 }
1214
1215 BOOL
1216 parse_button (message, pbutton, pup)
1217 int message;
1218 int * pbutton;
1219 int * pup;
1220 {
1221 int button = 0;
1222 int up = 0;
1223
1224 switch (message)
1225 {
1226 case WM_LBUTTONDOWN:
1227 button = 0;
1228 up = 0;
1229 break;
1230 case WM_LBUTTONUP:
1231 button = 0;
1232 up = 1;
1233 break;
1234 case WM_MBUTTONDOWN:
1235 if (NILP (Vw32_swap_mouse_buttons))
1236 button = 1;
1237 else
1238 button = 2;
1239 up = 0;
1240 break;
1241 case WM_MBUTTONUP:
1242 if (NILP (Vw32_swap_mouse_buttons))
1243 button = 1;
1244 else
1245 button = 2;
1246 up = 1;
1247 break;
1248 case WM_RBUTTONDOWN:
1249 if (NILP (Vw32_swap_mouse_buttons))
1250 button = 2;
1251 else
1252 button = 1;
1253 up = 0;
1254 break;
1255 case WM_RBUTTONUP:
1256 if (NILP (Vw32_swap_mouse_buttons))
1257 button = 2;
1258 else
1259 button = 1;
1260 up = 1;
1261 break;
1262 default:
1263 return (FALSE);
1264 }
1265
1266 if (pup) *pup = up;
1267 if (pbutton) *pbutton = button;
1268
1269 return (TRUE);
1270 }
1271
1272
1273 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1274
1275 If the event is a button press, then note that we have grabbed
1276 the mouse. */
1277
1278 static void
1279 construct_mouse_click (result, msg, f)
1280 struct input_event *result;
1281 W32Msg *msg;
1282 struct frame *f;
1283 {
1284 int button;
1285 int up;
1286
1287 parse_button (msg->msg.message, &button, &up);
1288
1289 /* Make the event type no_event; we'll change that when we decide
1290 otherwise. */
1291 result->kind = mouse_click;
1292 result->code = button;
1293 result->timestamp = msg->msg.time;
1294 result->modifiers = (msg->dwModifiers
1295 | (up
1296 ? up_modifier
1297 : down_modifier));
1298
1299 {
1300 int row, column;
1301
1302 XSETINT (result->x, LOWORD (msg->msg.lParam));
1303 XSETINT (result->y, HIWORD (msg->msg.lParam));
1304 XSETFRAME (result->frame_or_window, f);
1305 }
1306 }
1307
1308 static void
1309 construct_mouse_wheel (result, msg, f)
1310 struct input_event *result;
1311 W32Msg *msg;
1312 struct frame *f;
1313 {
1314 POINT p;
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);
1325 }
1326
1327 \f
1328 /* Function to report a mouse movement to the mainstream Emacs code.
1329 The input handler calls this.
1330
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. */
1335
1336 static void
1337 note_mouse_movement (frame, msg)
1338 FRAME_PTR frame;
1339 MSG *msg;
1340 {
1341 last_mouse_movement_time = msg->time;
1342
1343 if (msg->hwnd != FRAME_W32_WINDOW (frame))
1344 {
1345 frame->mouse_moved = 1;
1346 last_mouse_scroll_bar = Qnil;
1347
1348 note_mouse_highlight (frame, -1, -1);
1349 }
1350
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)
1356 {
1357 frame->mouse_moved = 1;
1358 last_mouse_scroll_bar = Qnil;
1359
1360 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1361 }
1362 }
1363
1364 /* This is used for debugging, to turn off note_mouse_highlight. */
1365 static int disable_mouse_highlight;
1366
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. */
1371
1372 static void
1373 note_mouse_highlight (f, x, y)
1374 FRAME_PTR f;
1375 int x, y;
1376 {
1377 int row, column, portion;
1378 RECT new_glyph;
1379 Lisp_Object window;
1380 struct window *w;
1381
1382 if (disable_mouse_highlight)
1383 return;
1384
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;
1388
1389 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
1390 return;
1391
1392 if (gc_in_progress)
1393 {
1394 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1395 return;
1396 }
1397
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);
1401
1402 /* Which window is that in? */
1403 window = window_from_coordinates (f, column, row, &portion);
1404 w = XWINDOW (window);
1405
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));
1409
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)))
1417 {
1418 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1419 int i, pos;
1420
1421 /* Find which buffer position the mouse corresponds to. */
1422 for (i = column; i >= 0; i--)
1423 if (ptr[i] > 0)
1424 break;
1425 pos = ptr[i];
1426 /* Is it outside the displayed active region (if any)? */
1427 if (pos <= 0)
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)))
1437 {
1438 Lisp_Object mouse_face, overlay, position;
1439 Lisp_Object *overlay_vec;
1440 int len, noverlays, ignor1;
1441 struct buffer *obuf;
1442 int obegv, ozv;
1443
1444 /* If we get an out-of-range value, return now; avoid an error. */
1445 if (pos > BUF_Z (XBUFFER (w->buffer)))
1446 return;
1447
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);
1452 obegv = BEGV;
1453 ozv = ZV;
1454 BEGV = BEG;
1455 ZV = Z;
1456
1457 /* Yes. Clear the display of the old active region, if any. */
1458 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1459
1460 /* Is this char mouse-active? */
1461 XSETINT (position, pos);
1462
1463 len = 10;
1464 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1465
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,
1469 NULL, NULL);
1470 noverlays = sort_overlays (overlay_vec, noverlays, w);
1471
1472 /* Find the highest priority overlay that has a mouse-face prop. */
1473 overlay = Qnil;
1474 for (i = 0; i < noverlays; i++)
1475 {
1476 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1477 if (!NILP (mouse_face))
1478 {
1479 overlay = overlay_vec[i];
1480 break;
1481 }
1482 }
1483 free (overlay_vec);
1484 /* If no overlay applies, get a text property. */
1485 if (NILP (overlay))
1486 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1487
1488 /* Handle the overlay case. */
1489 if (! NILP (overlay))
1490 {
1491 /* Find the range of text around this char that
1492 should be active. */
1493 Lisp_Object before, after;
1494 int ignore;
1495
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);
1510
1511 /* Display it as active. */
1512 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1513 }
1514 /* Handle the text property case. */
1515 else if (! NILP (mouse_face))
1516 {
1517 /* Find the range of text around this char that
1518 should be active. */
1519 Lisp_Object before, after, beginning, end;
1520 int ignore;
1521
1522 beginning = Fmarker_position (w->start);
1523 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1524 - XFASTINT (w->window_end_pos)));
1525 before
1526 = Fprevious_single_property_change (make_number (pos + 1),
1527 Qmouse_face,
1528 w->buffer, beginning);
1529 after
1530 = Fnext_single_property_change (position, Qmouse_face,
1531 w->buffer, end);
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);
1544
1545 /* Display it as active. */
1546 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1547 }
1548 BEGV = obegv;
1549 ZV = ozv;
1550 current_buffer = obuf;
1551 }
1552 }
1553 }
1554 \f
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.
1561
1562 Value is 1 if POS is in range, 0 if it was off screen. */
1563
1564 static int
1565 fast_find_position (window, pos, columnp, rowp)
1566 Lisp_Object window;
1567 int pos;
1568 int *columnp, *rowp;
1569 {
1570 struct window *w = XWINDOW (window);
1571 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1572 int i;
1573 int row = 0;
1574 int left = WINDOW_LEFT_MARGIN (w);
1575 int top = w->top;
1576 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
1577 int width = window_internal_width (w);
1578 int *charstarts;
1579 int lastcol;
1580 int maybe_next_line = 0;
1581
1582 /* Find the right row. */
1583 for (i = 0;
1584 i < height;
1585 i++)
1586 {
1587 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
1588 if (linestart > pos)
1589 break;
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)))
1593 {
1594 maybe_next_line = 1;
1595 break;
1596 }
1597 if (linestart > 0)
1598 row = i;
1599 }
1600
1601 /* Find the right column with in it. */
1602 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
1603 lastcol = left;
1604 for (i = 0; i < width; i++)
1605 {
1606 if (charstarts[left + i] == pos)
1607 {
1608 *rowp = row + top;
1609 *columnp = i + left;
1610 return 1;
1611 }
1612 else if (charstarts[left + i] > pos)
1613 break;
1614 else if (charstarts[left + i] > 0)
1615 lastcol = left + i;
1616 }
1617
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)
1622 {
1623 row++;
1624 i = 0;
1625 }
1626
1627 *rowp = row + top;
1628 *columnp = lastcol;
1629 return 0;
1630 }
1631
1632 /* Display the active region described by mouse_face_*
1633 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1634
1635 static void
1636 show_mouse_face (dpyinfo, hl)
1637 struct w32_display_info *dpyinfo;
1638 int hl;
1639 {
1640 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1641 int width = window_internal_width (w);
1642 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1643 int i;
1644 int cursor_off = 0;
1645 int old_curs_x = curs_x;
1646 int old_curs_y = curs_y;
1647
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;
1653
1654 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
1655 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
1656 {
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]);
1664
1665 /* If the cursor's in the text we are about to rewrite,
1666 turn the cursor off. */
1667 if (i == curs_y
1668 && curs_x >= column - 1
1669 && curs_x <= endcolumn)
1670 {
1671 x_display_cursor (f, 0);
1672 cursor_off = 1;
1673 }
1674
1675 dumpglyphs (f,
1676 CHAR_TO_PIXEL_COL (f, column),
1677 CHAR_TO_PIXEL_ROW (f, i),
1678 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
1679 endcolumn - column,
1680 /* Highlight with mouse face if hl > 0. */
1681 hl > 0 ? 3 : 0, 0);
1682 }
1683
1684 /* If we turned the cursor off, turn it back on. */
1685 if (cursor_off)
1686 x_display_cursor (f, 1);
1687
1688 curs_x = old_curs_x;
1689 curs_y = old_curs_y;
1690
1691 /* Change the mouse cursor according to the value of HL. */
1692 if (hl > 0)
1693 SetCursor (f->output_data.w32->cross_cursor);
1694 else
1695 SetCursor (f->output_data.w32->text_cursor);
1696 }
1697
1698 /* Clear out the mouse-highlighted active region.
1699 Redraw it unhighlighted first. */
1700
1701 static void
1702 clear_mouse_face (dpyinfo)
1703 struct w32_display_info *dpyinfo;
1704 {
1705 if (! NILP (dpyinfo->mouse_face_window))
1706 show_mouse_face (dpyinfo, 0);
1707
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;
1711 }
1712 \f
1713 struct scroll_bar *x_window_to_scroll_bar ();
1714 static void x_scroll_bar_report_motion ();
1715
1716 /* Return the current position of the mouse.
1717 *fp should be a frame which indicates which display to ask about.
1718
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.
1723
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
1726 the mouse is over.
1727
1728 Set *time to the server timestamp for the time at which the mouse
1729 was at this position.
1730
1731 Don't store anything if we don't have a valid set of values to report.
1732
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
1736 again. */
1737
1738 static void
1739 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
1740 FRAME_PTR *fp;
1741 int insist;
1742 Lisp_Object *bar_window;
1743 enum scroll_bar_part *part;
1744 Lisp_Object *x, *y;
1745 unsigned long *time;
1746 {
1747 FRAME_PTR f1;
1748
1749 BLOCK_INPUT;
1750
1751 if (! NILP (last_mouse_scroll_bar))
1752 /* This is never called at the moment. */
1753 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1754 else
1755 {
1756 POINT pt;
1757
1758 Lisp_Object frame, tail;
1759
1760 /* Clear the mouse-moved flag for every frame on this display. */
1761 FOR_EACH_FRAME (tail, frame)
1762 XFRAME (frame)->mouse_moved = 0;
1763
1764 last_mouse_scroll_bar = Qnil;
1765
1766 GetCursorPos (&pt);
1767
1768 /* Now we have a position on the root; find the innermost window
1769 containing the pointer. */
1770 {
1771 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
1772 && FRAME_LIVE_P (last_mouse_frame))
1773 {
1774 f1 = last_mouse_frame;
1775 }
1776 else
1777 {
1778 /* Is win one of our frames? */
1779 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
1780 }
1781
1782 /* If not, is it one of our scroll bars? */
1783 if (! f1)
1784 {
1785 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1786
1787 if (bar)
1788 {
1789 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1790 }
1791 }
1792
1793 if (f1 == 0 && insist)
1794 f1 = selected_frame;
1795
1796 if (f1)
1797 {
1798 int ignore1, ignore2;
1799
1800 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
1801
1802 /* Ok, we found a frame. Store all the values. */
1803
1804 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
1805 &last_mouse_glyph,
1806 FRAME_W32_DISPLAY_INFO (f1)->grabbed
1807 || insist);
1808
1809 *bar_window = Qnil;
1810 *part = 0;
1811 *fp = f1;
1812 XSETINT (*x, pt.x);
1813 XSETINT (*y, pt.y);
1814 *time = last_mouse_movement_time;
1815 }
1816 }
1817 }
1818
1819 UNBLOCK_INPUT;
1820 }
1821 \f
1822 /* Scroll bar support. */
1823
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
1826 bits. */
1827 struct scroll_bar *
1828 x_window_to_scroll_bar (window_id)
1829 Window window_id;
1830 {
1831 Lisp_Object tail, frame;
1832
1833 for (tail = Vframe_list;
1834 XGCTYPE (tail) == Lisp_Cons;
1835 tail = XCONS (tail)->cdr)
1836 {
1837 Lisp_Object frame, bar, condemned;
1838
1839 frame = XCONS (tail)->car;
1840 /* All elements of Vframe_list should be frames. */
1841 if (! GC_FRAMEP (frame))
1842 abort ();
1843
1844 /* Scan this frame's scroll bar list for a scroll bar with the
1845 right window ID. */
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,
1851 condemned = Qnil,
1852 ! GC_NILP (bar));
1853 bar = XSCROLL_BAR (bar)->next)
1854 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
1855 return XSCROLL_BAR (bar);
1856 }
1857
1858 return 0;
1859 }
1860
1861 HWND
1862 my_create_scrollbar (f, bar)
1863 struct frame * f;
1864 struct scroll_bar * bar;
1865 {
1866 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
1867 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1868 (LPARAM) bar);
1869 }
1870
1871 //#define ATTACH_THREADS
1872
1873 BOOL
1874 my_show_window (FRAME_PTR f, HWND hwnd, int how)
1875 {
1876 #ifndef ATTACH_THREADS
1877 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
1878 (WPARAM) hwnd, (LPARAM) how);
1879 #else
1880 return ShowWindow (hwnd, how);
1881 #endif
1882 }
1883
1884 void
1885 my_set_window_pos (HWND hwnd, HWND hwndAfter,
1886 int x, int y, int cx, int cy, UINT flags)
1887 {
1888 #ifndef ATTACH_THREADS
1889 WINDOWPOS pos;
1890 pos.hwndInsertAfter = hwndAfter;
1891 pos.x = x;
1892 pos.y = y;
1893 pos.cx = cx;
1894 pos.cy = cy;
1895 pos.flags = flags;
1896 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
1897 #else
1898 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
1899 #endif
1900 }
1901
1902 BOOL
1903 my_set_focus (f, hwnd)
1904 struct frame * f;
1905 HWND hwnd;
1906 {
1907 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
1908 (WPARAM) hwnd, 0);
1909 }
1910
1911 void
1912 my_destroy_window (f, hwnd)
1913 struct frame * f;
1914 HWND hwnd;
1915 {
1916 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
1917 (WPARAM) hwnd, 0);
1918 }
1919
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;
1926 {
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));
1930 HWND hwnd;
1931
1932 BLOCK_INPUT;
1933
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;
1942
1943 /* Requires geometry to be set before call to create the real window */
1944
1945 hwnd = my_create_scrollbar (f, bar);
1946
1947 if (pfnSetScrollInfo)
1948 {
1949 SCROLLINFO si;
1950
1951 si.cbSize = sizeof (si);
1952 si.fMask = SIF_ALL;
1953 si.nMin = 0;
1954 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
1955 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
1956 si.nPage = si.nMax;
1957 si.nPos = 0;
1958
1959 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
1960 }
1961 else
1962 {
1963 SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
1964 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
1965 }
1966
1967 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
1968
1969 /* Add bar to its frame's list of scroll bars. */
1970 bar->next = FRAME_SCROLL_BARS (f);
1971 bar->prev = Qnil;
1972 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
1973 if (! NILP (bar->next))
1974 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1975
1976 UNBLOCK_INPUT;
1977
1978 return bar;
1979 }
1980
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
1985 events.)
1986
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. */
1992 static void
1993 x_scroll_bar_set_handle (bar, start, end, rebuild)
1994 struct scroll_bar *bar;
1995 int start, end;
1996 int rebuild;
1997 {
1998 int dragging = ! NILP (bar->dragging);
1999 Window w = SCROLL_BAR_W32_WINDOW (bar);
2000 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2001
2002 /* If the display is already accurate, do nothing. */
2003 if (! rebuild
2004 && start == XINT (bar->start)
2005 && end == XINT (bar->end))
2006 return;
2007
2008 BLOCK_INPUT;
2009
2010 {
2011 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2012
2013 /* Make sure the values are reasonable, and try to preserve
2014 the distance between start and end. */
2015 {
2016 int length = end - start;
2017
2018 if (start < 0)
2019 start = 0;
2020 else if (start > top_range)
2021 start = top_range;
2022 end = start + length;
2023
2024 if (end < start)
2025 end = start;
2026 else if (end > top_range && ! dragging)
2027 end = top_range;
2028 }
2029 }
2030
2031 /* Store the adjusted setting in the scroll bar. */
2032 XSETINT (bar->start, start);
2033 XSETINT (bar->end, end);
2034
2035 /* If being dragged, let scroll bar update itself. */
2036 if (!dragging)
2037 {
2038 if (pfnSetScrollInfo)
2039 {
2040 SCROLLINFO si;
2041
2042 si.cbSize = sizeof (si);
2043 si.fMask = SIF_PAGE | SIF_POS;
2044 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2045 si.nPos = start;
2046
2047 pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
2048 }
2049 else
2050 SetScrollPos (w, SB_CTL, start, TRUE);
2051 }
2052
2053 UNBLOCK_INPUT;
2054 }
2055
2056 /* Move a scroll bar around on the screen, to accommodate changing
2057 window configurations. */
2058 static void
2059 x_scroll_bar_move (bar, top, left, width, height)
2060 struct scroll_bar *bar;
2061 int top, left, width, height;
2062 {
2063 Window w = SCROLL_BAR_W32_WINDOW (bar);
2064 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2065
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 )
2071 {
2072 /* Redraw after clear_frame. */
2073 if (!my_show_window (f, w, SW_NORMAL))
2074 InvalidateRect (w, NULL, FALSE);
2075 return;
2076 }
2077
2078 BLOCK_INPUT;
2079
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)
2085 {
2086 SCROLLINFO si;
2087
2088 si.cbSize = sizeof (si);
2089 si.fMask = SIF_RANGE;
2090 si.nMin = 0;
2091 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
2092 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2093
2094 pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
2095 }
2096 else
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);
2100
2101 XSETINT (bar->left, left);
2102 XSETINT (bar->top, top);
2103 XSETINT (bar->width, width);
2104 XSETINT (bar->height, height);
2105
2106 UNBLOCK_INPUT;
2107 }
2108
2109 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2110 to nil. */
2111 static void
2112 x_scroll_bar_remove (bar)
2113 struct scroll_bar *bar;
2114 {
2115 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2116
2117 BLOCK_INPUT;
2118
2119 /* Destroy the window. */
2120 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
2121
2122 /* Disassociate this scroll bar from its window. */
2123 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2124
2125 UNBLOCK_INPUT;
2126 }
2127
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,
2131 create one. */
2132 static void
2133 w32_set_vertical_scroll_bar (window, portion, whole, position)
2134 struct window *window;
2135 int portion, whole, position;
2136 {
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);
2141
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);
2145 int pixel_width
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);
2150
2151 struct scroll_bar *bar;
2152
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);
2158 else
2159 {
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);
2163 }
2164
2165 /* Set the scroll bar's current state. */
2166 {
2167 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2168
2169 if (whole == 0)
2170 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2171 else
2172 {
2173 int start = (int) (((double) position * top_range) / whole);
2174 int end = (int) (((double) (position + portion) * top_range) / whole);
2175
2176 x_scroll_bar_set_handle (bar, start, end, 0);
2177 }
2178 }
2179
2180 XSETVECTOR (window->vertical_scroll_bar, bar);
2181 }
2182
2183
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. */
2191
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. */
2195 static void
2196 w32_condemn_scroll_bars (frame)
2197 FRAME_PTR frame;
2198 {
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)))
2203 abort ();
2204
2205 /* Move them all to the "condemned" list. */
2206 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2207 FRAME_SCROLL_BARS (frame) = Qnil;
2208 }
2209
2210 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2211 Note that WINDOW isn't necessarily condemned at all. */
2212 static void
2213 w32_redeem_scroll_bar (window)
2214 struct window *window;
2215 {
2216 struct scroll_bar *bar;
2217
2218 /* We can't redeem this window's scroll bar if it doesn't have one. */
2219 if (NILP (window->vertical_scroll_bar))
2220 abort ();
2221
2222 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2223
2224 /* Unlink it from the condemned list. */
2225 {
2226 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2227
2228 if (NILP (bar->prev))
2229 {
2230 /* If the prev pointer is nil, it must be the first in one of
2231 the lists. */
2232 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2233 /* It's not condemned. Everything's fine. */
2234 return;
2235 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2236 window->vertical_scroll_bar))
2237 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2238 else
2239 /* If its prev pointer is nil, it must be at the front of
2240 one or the other! */
2241 abort ();
2242 }
2243 else
2244 XSCROLL_BAR (bar->prev)->next = bar->next;
2245
2246 if (! NILP (bar->next))
2247 XSCROLL_BAR (bar->next)->prev = bar->prev;
2248
2249 bar->next = FRAME_SCROLL_BARS (f);
2250 bar->prev = Qnil;
2251 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2252 if (! NILP (bar->next))
2253 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2254 }
2255 }
2256
2257 /* Remove all scroll bars on FRAME that haven't been saved since the
2258 last call to `*condemn_scroll_bars_hook'. */
2259 static void
2260 w32_judge_scroll_bars (f)
2261 FRAME_PTR f;
2262 {
2263 Lisp_Object bar, next;
2264
2265 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2266
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;
2270
2271 for (; ! NILP (bar); bar = next)
2272 {
2273 struct scroll_bar *b = XSCROLL_BAR (bar);
2274
2275 x_scroll_bar_remove (b);
2276
2277 next = b->next;
2278 b->next = b->prev = Qnil;
2279 }
2280
2281 /* Now there should be no references to the condemned scroll bars,
2282 and they should get garbage-collected. */
2283 }
2284
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.
2287
2288 This may be called from a signal handler, so we have to ignore GC
2289 mark bits. */
2290
2291 static int
2292 x_scroll_bar_handle_click (bar, msg, emacs_event)
2293 struct scroll_bar *bar;
2294 W32Msg *msg;
2295 struct input_event *emacs_event;
2296 {
2297 if (! GC_WINDOWP (bar->window))
2298 abort ();
2299
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;
2306
2307 {
2308 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2309 int y;
2310 int dragging = !NILP (bar->dragging);
2311
2312 if (pfnGetScrollInfo)
2313 {
2314 SCROLLINFO si;
2315
2316 si.cbSize = sizeof (si);
2317 si.fMask = SIF_POS;
2318
2319 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
2320 y = si.nPos;
2321 }
2322 else
2323 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
2324
2325 bar->dragging = Qnil;
2326
2327 switch (LOWORD (msg->msg.wParam))
2328 {
2329 case SB_LINEDOWN:
2330 emacs_event->part = scroll_bar_down_arrow;
2331 break;
2332 case SB_LINEUP:
2333 emacs_event->part = scroll_bar_up_arrow;
2334 break;
2335 case SB_PAGEUP:
2336 emacs_event->part = scroll_bar_above_handle;
2337 break;
2338 case SB_PAGEDOWN:
2339 emacs_event->part = scroll_bar_below_handle;
2340 break;
2341 case SB_TOP:
2342 emacs_event->part = scroll_bar_handle;
2343 y = 0;
2344 break;
2345 case SB_BOTTOM:
2346 emacs_event->part = scroll_bar_handle;
2347 y = top_range;
2348 break;
2349 case SB_THUMBTRACK:
2350 case SB_THUMBPOSITION:
2351 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2352 y = HIWORD (msg->msg.wParam);
2353 bar->dragging = Qt;
2354 emacs_event->part = scroll_bar_handle;
2355
2356 /* "Silently" update current position. */
2357 if (pfnSetScrollInfo)
2358 {
2359 SCROLLINFO si;
2360
2361 si.cbSize = sizeof (si);
2362 si.fMask = SIF_POS;
2363
2364 #if 0
2365 /* Shrink handle if necessary to allow full range for position. */
2366 {
2367 int start = XINT (bar->start);
2368 int end = XINT (bar->end);
2369 int len = end - start;
2370
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)
2375 {
2376 len -= min (top_range / 10, (len / 3) + 2);
2377 if (len < 0)
2378 len = 0;
2379 }
2380 si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2381 si.fMask |= SIF_PAGE;
2382 }
2383 #endif
2384 si.nPos = y;
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;
2388
2389 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
2390 }
2391 else
2392 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
2393 break;
2394 case SB_ENDSCROLL:
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
2397 nothing. */
2398 if (dragging)
2399 {
2400 if (pfnSetScrollInfo)
2401 {
2402 SCROLLINFO si;
2403 int start = XINT (bar->start);
2404 int end = XINT (bar->end);
2405
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;
2410
2411 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
2412 }
2413 else
2414 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
2415 }
2416 /* fall through */
2417 default:
2418 emacs_event->kind = no_event;
2419 return FALSE;
2420 }
2421
2422 XSETINT (emacs_event->x, y);
2423 XSETINT (emacs_event->y, top_range);
2424
2425 return TRUE;
2426 }
2427 }
2428
2429 /* Return information to the user about the current position of the mouse
2430 on the scroll bar. */
2431 static void
2432 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
2433 FRAME_PTR *fp;
2434 Lisp_Object *bar_window;
2435 enum scroll_bar_part *part;
2436 Lisp_Object *x, *y;
2437 unsigned long *time;
2438 {
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)));
2442 int pos;
2443 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2444
2445 BLOCK_INPUT;
2446
2447 *fp = f;
2448 *bar_window = bar->window;
2449
2450 if (pfnGetScrollInfo)
2451 {
2452 SCROLLINFO si;
2453
2454 si.cbSize = sizeof (si);
2455 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
2456
2457 pfnGetScrollInfo (w, SB_CTL, &si);
2458 pos = si.nPos;
2459 top_range = si.nMax - si.nPage + 1;
2460 }
2461 else
2462 pos = GetScrollPos (w, SB_CTL);
2463
2464 switch (LOWORD (last_mouse_scroll_bar_pos))
2465 {
2466 case SB_THUMBPOSITION:
2467 case SB_THUMBTRACK:
2468 *part = scroll_bar_handle;
2469 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2470 pos = HIWORD (last_mouse_scroll_bar_pos);
2471 break;
2472 case SB_LINEDOWN:
2473 *part = scroll_bar_handle;
2474 pos++;
2475 break;
2476 default:
2477 *part = scroll_bar_handle;
2478 break;
2479 }
2480
2481 XSETINT(*x, pos);
2482 XSETINT(*y, top_range);
2483
2484 f->mouse_moved = 0;
2485 last_mouse_scroll_bar = Qnil;
2486
2487 *time = last_mouse_movement_time;
2488
2489 UNBLOCK_INPUT;
2490 }
2491
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
2495 redraw them. */
2496
2497 x_scroll_bar_clear (f)
2498 FRAME_PTR f;
2499 {
2500 Lisp_Object bar;
2501
2502 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2503 bar = XSCROLL_BAR (bar)->next)
2504 {
2505 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2506 HDC hdc = GetDC (window);
2507 RECT rect;
2508
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);
2512
2513 GetClientRect (window, &rect);
2514 select_palette (f, hdc);
2515 w32_clear_rect (f, hdc, &rect);
2516 deselect_palette (f, hdc);
2517
2518 ReleaseDC (window, hdc);
2519 }
2520 }
2521
2522 show_scroll_bars (f, how)
2523 FRAME_PTR f;
2524 int how;
2525 {
2526 Lisp_Object bar;
2527
2528 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2529 bar = XSCROLL_BAR (bar)->next)
2530 {
2531 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2532 my_show_window (f, window, how);
2533 }
2534 }
2535
2536 \f
2537 /* The main W32 event-reading loop - w32_read_socket. */
2538
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;
2543
2544 /* Record the last 100 characters stored
2545 to help debug the loss-of-chars-during-GC problem. */
2546 int temp_index;
2547 short temp_buffer[100];
2548
2549 extern int key_event (KEY_EVENT_RECORD *, struct input_event *, int *isdead);
2550
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. */
2554
2555 static void
2556 convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
2557 {
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;
2564 }
2565
2566 /* Return nonzero if the virtual key is a dead key. */
2567
2568 static int
2569 is_dead_key (int wparam)
2570 {
2571 unsigned int code = MapVirtualKey (wparam, 2);
2572
2573 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2574 if ((code & 0x8000) || (code & 0x80000000))
2575 return 1;
2576 else
2577 return 0;
2578 }
2579
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.
2583
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'.
2588
2589 EXPECTED is nonzero if the caller knows input is available.
2590
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.
2598 */
2599
2600 int
2601 w32_read_socket (sd, bufp, numchars, expected)
2602 register int sd;
2603 register struct input_event *bufp;
2604 register int numchars;
2605 int expected;
2606 {
2607 int count = 0;
2608 int check_visibility = 0;
2609 W32Msg msg;
2610 struct frame *f;
2611 Lisp_Object part;
2612 struct w32_display_info *dpyinfo = &one_w32_display_info;
2613
2614 if (interrupt_input_blocked)
2615 {
2616 interrupt_input_pending = 1;
2617 return -1;
2618 }
2619
2620 interrupt_input_pending = 0;
2621 BLOCK_INPUT;
2622
2623 /* So people can tell when we have read the available input. */
2624 input_signal_count++;
2625
2626 if (numchars <= 0)
2627 abort (); /* Don't think this happens. */
2628
2629 while (get_next_msg (&msg, FALSE))
2630 {
2631 switch (msg.msg.message)
2632 {
2633 case WM_PAINT:
2634 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2635
2636 if (f)
2637 {
2638 if (f->async_visible != 1)
2639 {
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));
2646
2647 /* WM_PAINT serves as MapNotify as well, so report
2648 visibility changes properly. */
2649 if (f->iconified)
2650 {
2651 bufp->kind = deiconify_event;
2652 XSETFRAME (bufp->frame_or_window, f);
2653 bufp++;
2654 count++;
2655 numchars--;
2656 }
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 ();
2662 }
2663 else
2664 {
2665 /* Erase background again for safety. */
2666 w32_clear_rect (f, NULL, &msg.rect);
2667 dumprectangle (f,
2668 msg.rect.left,
2669 msg.rect.top,
2670 msg.rect.right - msg.rect.left,
2671 msg.rect.bottom - msg.rect.top);
2672 }
2673 }
2674 break;
2675
2676 case WM_KEYDOWN:
2677 case WM_SYSKEYDOWN:
2678 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2679
2680 if (f && !f->iconified)
2681 {
2682 if (temp_index == sizeof temp_buffer / sizeof (short))
2683 temp_index = 0;
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,
2688 msg.msg.wParam);
2689 XSETFRAME (bufp->frame_or_window, f);
2690 bufp->timestamp = msg.msg.time;
2691 bufp++;
2692 numchars--;
2693 count++;
2694 }
2695 break;
2696
2697 case WM_SYSCHAR:
2698 case WM_CHAR:
2699 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2700
2701 if (f && !f->iconified)
2702 {
2703 if (numchars > 1)
2704 {
2705 int add;
2706 int isdead = 0;
2707 KEY_EVENT_RECORD key, *keyp = &key;
2708
2709 if (temp_index == sizeof temp_buffer / sizeof (short))
2710 temp_index = 0;
2711
2712 convert_to_key_event (&msg, keyp);
2713 add = key_event (keyp, bufp, &isdead);
2714 XSETFRAME (bufp->frame_or_window, f);
2715 if (add == -1)
2716 {
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. */
2723 prepend_msg (&msg);
2724 add = 1;
2725 }
2726
2727 if (isdead)
2728 break;
2729
2730 bufp += add;
2731 numchars -= add;
2732 count += add;
2733 }
2734 else
2735 {
2736 abort ();
2737 }
2738 }
2739 break;
2740
2741 case WM_MOUSEMOVE:
2742 if (dpyinfo->grabbed && last_mouse_frame
2743 && FRAME_LIVE_P (last_mouse_frame))
2744 f = last_mouse_frame;
2745 else
2746 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2747
2748 if (f)
2749 note_mouse_movement (f, &msg.msg);
2750 else
2751 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2752
2753 break;
2754
2755 case WM_LBUTTONDOWN:
2756 case WM_LBUTTONUP:
2757 case WM_MBUTTONDOWN:
2758 case WM_MBUTTONUP:
2759 case WM_RBUTTONDOWN:
2760 case WM_RBUTTONUP:
2761 {
2762 int button;
2763 int up;
2764
2765 if (dpyinfo->grabbed && last_mouse_frame
2766 && FRAME_LIVE_P (last_mouse_frame))
2767 f = last_mouse_frame;
2768 else
2769 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2770
2771 if (f)
2772 {
2773 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
2774 && (numchars >= 1))
2775 {
2776 construct_mouse_click (bufp, &msg, f);
2777 bufp++;
2778 count++;
2779 numchars--;
2780 }
2781 }
2782
2783 parse_button (msg.msg.message, &button, &up);
2784
2785 if (up)
2786 {
2787 dpyinfo->grabbed &= ~ (1 << button);
2788 }
2789 else
2790 {
2791 dpyinfo->grabbed |= (1 << button);
2792 last_mouse_frame = f;
2793 }
2794 break;
2795 }
2796
2797 case WM_MOUSEWHEEL:
2798 if (dpyinfo->grabbed && last_mouse_frame
2799 && FRAME_LIVE_P (last_mouse_frame))
2800 f = last_mouse_frame;
2801 else
2802 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2803
2804 if (f)
2805 {
2806 if ((!dpyinfo->w32_focus_frame
2807 || f == dpyinfo->w32_focus_frame)
2808 && (numchars >= 1))
2809 {
2810 construct_mouse_wheel (bufp, &msg, f);
2811 bufp++;
2812 count++;
2813 numchars--;
2814 }
2815 }
2816 break;
2817
2818 case WM_VSCROLL:
2819 {
2820 struct scroll_bar *bar =
2821 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
2822
2823 if (bar && numchars >= 1)
2824 {
2825 if (x_scroll_bar_handle_click (bar, &msg, bufp))
2826 {
2827 bufp++;
2828 count++;
2829 numchars--;
2830 }
2831 }
2832 break;
2833 }
2834
2835 case WM_WINDOWPOSCHANGED:
2836 case WM_ACTIVATE:
2837 case WM_ACTIVATEAPP:
2838 check_visibility = 1;
2839 break;
2840
2841 case WM_MOVE:
2842 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2843
2844 if (f && !f->async_iconified)
2845 {
2846 int x, y;
2847
2848 x_real_positions (f, &x, &y);
2849 f->output_data.w32->left_pos = x;
2850 f->output_data.w32->top_pos = y;
2851 }
2852
2853 check_visibility = 1;
2854 break;
2855
2856 case WM_SHOWWINDOW:
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. */
2861 #if 0
2862 if (msg.msg.lParam != 0)
2863 check_visibility = 1;
2864 else
2865 {
2866 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2867 f->async_visible = msg.msg.wParam;
2868 }
2869 #endif
2870
2871 check_visibility = 1;
2872 break;
2873
2874 case WM_SIZE:
2875 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2876
2877 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2878 {
2879 RECT rect;
2880 int rows;
2881 int columns;
2882 int width;
2883 int height;
2884
2885 GetClientRect(msg.msg.hwnd, &rect);
2886
2887 height = rect.bottom - rect.top;
2888 width = rect.right - rect.left;
2889
2890 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2891 columns = PIXEL_TO_CHAR_WIDTH (f, width);
2892
2893 /* TODO: Clip size to the screen dimensions. */
2894
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. */
2898
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)
2903 {
2904 /* I had set this to 0, 0 - I am not sure why?? */
2905
2906 change_frame_size (f, rows, columns, 0, 1);
2907 SET_FRAME_GARBAGED (f);
2908
2909 f->output_data.w32->pixel_width = width;
2910 f->output_data.w32->pixel_height = height;
2911 f->output_data.w32->win_gravity = NorthWestGravity;
2912 }
2913 }
2914
2915 /* Inform lisp of whether frame has been iconified etc. */
2916 if (f)
2917 {
2918 switch (msg.msg.wParam)
2919 {
2920 case SIZE_MINIMIZED:
2921 f->async_visible = 0;
2922 f->async_iconified = 1;
2923
2924 bufp->kind = iconify_event;
2925 XSETFRAME (bufp->frame_or_window, f);
2926 bufp++;
2927 count++;
2928 numchars--;
2929 break;
2930
2931 case SIZE_MAXIMIZED:
2932 case SIZE_RESTORED:
2933 f->async_visible = 1;
2934 f->async_iconified = 0;
2935
2936 /* wait_reading_process_input will notice this and update
2937 the frame's display structures. */
2938 SET_FRAME_GARBAGED (f);
2939
2940 if (f->iconified)
2941 {
2942 bufp->kind = deiconify_event;
2943 XSETFRAME (bufp->frame_or_window, f);
2944 bufp++;
2945 count++;
2946 numchars--;
2947 }
2948 else
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 ();
2953 break;
2954 }
2955 }
2956
2957 check_visibility = 1;
2958 break;
2959
2960 case WM_SETFOCUS:
2961 case WM_KILLFOCUS:
2962 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2963
2964 if (msg.msg.message == WM_SETFOCUS)
2965 {
2966 x_new_focus_frame (dpyinfo, f);
2967 }
2968 else if (f == dpyinfo->w32_focus_frame)
2969 {
2970 x_new_focus_frame (dpyinfo, 0);
2971 }
2972
2973 check_visibility = 1;
2974 break;
2975
2976 case WM_CLOSE:
2977 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2978
2979 if (f)
2980 {
2981 if (numchars == 0)
2982 abort ();
2983
2984 bufp->kind = delete_window_event;
2985 XSETFRAME (bufp->frame_or_window, f);
2986 bufp++;
2987 count++;
2988 numchars--;
2989 }
2990 break;
2991
2992 case WM_INITMENU:
2993 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2994
2995 if (f)
2996 {
2997 if (numchars == 0)
2998 abort ();
2999
3000 bufp->kind = menu_bar_activate_event;
3001 XSETFRAME (bufp->frame_or_window, f);
3002 bufp++;
3003 count++;
3004 numchars--;
3005 }
3006 break;
3007
3008 case WM_COMMAND:
3009 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3010
3011 #if 1
3012 if (f)
3013 {
3014 if (msg.msg.lParam == 0)
3015 {
3016 /* Came from window menu */
3017
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;
3021 Lisp_Object frame;
3022
3023 XSETFRAME (frame, f);
3024 buf.kind = menu_bar_event;
3025
3026 /* Store initial menu bar event */
3027
3028 if (!NILP (event))
3029 {
3030 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
3031 kbd_buffer_store_event (&buf);
3032 }
3033
3034 /* Enqueue the events */
3035
3036 while (!NILP (event))
3037 {
3038 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
3039 kbd_buffer_store_event (&buf);
3040 event = XCONS (event)->cdr;
3041 }
3042 }
3043 else
3044 {
3045 /* Came from popup menu */
3046 }
3047 }
3048 #endif
3049
3050 check_visibility = 1;
3051 break;
3052
3053 case WM_DISPLAYCHANGE:
3054 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3055
3056 if (f)
3057 {
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,
3062 dpyinfo->height));
3063 }
3064
3065 check_visibility = 1;
3066 break;
3067 }
3068 }
3069
3070 /* If the focus was just given to an autoraising frame,
3071 raise it now. */
3072 /* ??? This ought to be able to handle more than one such frame. */
3073 if (pending_autoraise_frame)
3074 {
3075 x_raise_frame (pending_autoraise_frame);
3076 pending_autoraise_frame = 0;
3077 }
3078
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)
3085 {
3086 Lisp_Object tail, frame;
3087
3088 FOR_EACH_FRAME (tail, frame)
3089 {
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)
3095 {
3096 RECT clipbox;
3097 HDC hdc = get_frame_dc (f);
3098 GetClipBox (hdc, &clipbox);
3099 release_frame_dc (f, hdc);
3100
3101 if (clipbox.right == clipbox.left
3102 || clipbox.bottom == clipbox.top)
3103 {
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
3107 will skip it). */
3108 f->async_visible = 2;
3109
3110 if (!FRAME_OBSCURED_P (f))
3111 {
3112 DebPrint (("frame %04x (%s) obscured\n", f,
3113 XSTRING (f->name)->data));
3114 }
3115 }
3116 else
3117 {
3118 /* Frame is not obscured, so mark it as such. */
3119 f->async_visible = 1;
3120
3121 if (FRAME_OBSCURED_P (f))
3122 {
3123 SET_FRAME_GARBAGED (f);
3124 DebPrint (("frame %04x (%s) reexposed\n", f,
3125 XSTRING (f->name)->data));
3126
3127 /* Force a redisplay sooner or later. */
3128 record_asynch_buffer_change ();
3129 }
3130 }
3131 }
3132 }
3133 }
3134
3135 UNBLOCK_INPUT;
3136 return count;
3137 }
3138 \f
3139 /* Drawing the cursor. */
3140
3141
3142 /* Draw a hollow box cursor. Don't change the inside of the box. */
3143
3144 static void
3145 x_draw_box (f)
3146 struct frame *f;
3147 {
3148 RECT rect;
3149 HBRUSH hb;
3150 HDC hdc;
3151
3152 hdc = get_frame_dc (f);
3153
3154 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
3155
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;
3160
3161 FrameRect (hdc, &rect, hb);
3162 DeleteObject (hb);
3163
3164 release_frame_dc (f, hdc);
3165 }
3166
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. */
3171
3172 static void
3173 clear_cursor (f)
3174 struct frame *f;
3175 {
3176 if (! FRAME_VISIBLE_P (f)
3177 || f->phys_cursor_x < 0)
3178 return;
3179
3180 x_display_cursor (f, 0);
3181 f->phys_cursor_x = -1;
3182 }
3183
3184 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3185 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3186 glyph drawn. */
3187
3188 static void
3189 x_draw_single_glyph (f, row, column, glyph, highlight)
3190 struct frame *f;
3191 int row, column;
3192 GLYPH glyph;
3193 int highlight;
3194 {
3195 dumpglyphs (f,
3196 CHAR_TO_PIXEL_COL (f, column),
3197 CHAR_TO_PIXEL_ROW (f, row),
3198 &glyph, 1, highlight, 0);
3199 }
3200
3201 static void
3202 x_display_bar_cursor (f, on)
3203 struct frame *f;
3204 int on;
3205 {
3206 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3207
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))
3212 return;
3213
3214 if (! on && f->phys_cursor_x < 0)
3215 return;
3216
3217 /* If there is anything wrong with the current cursor state, remove it. */
3218 if (f->phys_cursor_x >= 0
3219 && (!on
3220 || f->phys_cursor_x != curs_x
3221 || f->phys_cursor_y != curs_y
3222 || f->output_data.w32->current_cursor != bar_cursor))
3223 {
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;
3229 }
3230
3231 /* If we now need a cursor in the new place or in the new form, do it so. */
3232 if (on
3233 && (f->phys_cursor_x < 0
3234 || (f->output_data.w32->current_cursor != bar_cursor)))
3235 {
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]
3240 : SPACEGLYPH);
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);
3246
3247 f->phys_cursor_x = curs_x;
3248 f->phys_cursor_y = curs_y;
3249
3250 f->output_data.w32->current_cursor = bar_cursor;
3251 }
3252 }
3253
3254
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. */
3258
3259 static void
3260 x_display_box_cursor (f, on)
3261 struct frame *f;
3262 int on;
3263 {
3264 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3265
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))
3270 return;
3271
3272 /* If cursor is off and we want it off, return quickly. */
3273 if (!on && f->phys_cursor_x < 0)
3274 return;
3275
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!)
3279 erase it. */
3280 if (f->phys_cursor_x >= 0
3281 && (!on
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))))
3286 {
3287 int mouse_face_here = 0;
3288 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
3289
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;
3304
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,
3316 (mouse_face_here
3317 ? 3
3318 : current_glyphs->highlight[f->phys_cursor_y]));
3319 f->phys_cursor_x = -1;
3320 }
3321
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. */
3325 if (on
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)))
3329 {
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]
3334 : SPACEGLYPH);
3335 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
3336 {
3337 x_draw_box (f);
3338 f->output_data.w32->current_cursor = hollow_box_cursor;
3339 }
3340 else
3341 {
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;
3345 }
3346
3347 f->phys_cursor_x = curs_x;
3348 f->phys_cursor_y = curs_y;
3349 }
3350 }
3351
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
3356 of F. */
3357
3358 x_display_cursor (f, on)
3359 struct frame *f;
3360 int on;
3361 {
3362 BLOCK_INPUT;
3363
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)
3367 {
3368 curs_x = FRAME_CURSOR_X (f);
3369 curs_y = FRAME_CURSOR_Y (f);
3370 }
3371
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);
3376 else
3377 /* Those are the only two we have implemented! */
3378 abort ();
3379
3380 UNBLOCK_INPUT;
3381 }
3382 \f
3383 /* Changing the font of the frame. */
3384
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. */
3389
3390 Lisp_Object
3391 x_new_font (f, fontname)
3392 struct frame *f;
3393 register char *fontname;
3394 {
3395 int already_loaded;
3396 int n_matching_fonts;
3397 XFontStruct *font_info;
3398 char new_font_name[101];
3399
3400 /* Get a font which matches this name */
3401 {
3402 LOGFONT lf;
3403
3404 if (!x_to_w32_font(fontname, &lf)
3405 || !w32_to_x_font(&lf, new_font_name, 100))
3406 {
3407 return Qnil;
3408 }
3409 }
3410
3411 /* See if we've already loaded a matching font. */
3412 already_loaded = -1;
3413
3414 {
3415 int i;
3416
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))
3419 {
3420 already_loaded = i;
3421 fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
3422 break;
3423 }
3424 }
3425
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. */
3430 else
3431 {
3432 XFontStruct *font;
3433 int n_fonts;
3434
3435 font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
3436
3437 if (! font)
3438 {
3439 return Qnil;
3440 }
3441
3442 /* Do we need to create the table? */
3443 if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
3444 {
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));
3449 }
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)
3453 {
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)));
3459 }
3460
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++;
3466 }
3467
3468 /* Compute the scroll bar width in character columns. */
3469 if (f->scroll_bar_pixel_width > 0)
3470 {
3471 int wid = FONT_WIDTH (f->output_data.w32->font);
3472 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
3473 }
3474 else
3475 f->scroll_bar_cols = 2;
3476
3477 /* Now make the frame display the given font. */
3478 if (FRAME_W32_WINDOW (f) != 0)
3479 {
3480 frame_update_line_height (f);
3481 x_set_window_size (f, 0, f->width, f->height);
3482 }
3483 else
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);
3487
3488 {
3489 Lisp_Object lispy_name;
3490
3491 lispy_name = build_string (fontname);
3492
3493 return lispy_name;
3494 }
3495 }
3496 \f
3497 /* Calculate the absolute position in frame F
3498 from its current recorded position values and gravity. */
3499
3500 x_calc_absolute_position (f)
3501 struct frame *f;
3502 {
3503 Window win, child;
3504 POINT pt;
3505 int flags = f->output_data.w32->size_hint_flags;
3506
3507 pt.x = pt.y = 0;
3508
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)
3512 {
3513 BLOCK_INPUT;
3514 MapWindowPoints (FRAME_W32_WINDOW (f),
3515 f->output_data.w32->parent_desc,
3516 &pt, 1);
3517 UNBLOCK_INPUT;
3518 }
3519
3520 {
3521 RECT rt;
3522 rt.left = rt.right = rt.top = rt.bottom = 0;
3523
3524 BLOCK_INPUT;
3525 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
3526 FRAME_EXTERNAL_MENU_BAR (f));
3527 UNBLOCK_INPUT;
3528
3529 pt.x += (rt.right - rt.left);
3530 pt.y += (rt.bottom - rt.top);
3531 }
3532
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
3538 - PIXEL_WIDTH (f)
3539 + f->output_data.w32->left_pos);
3540
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
3544 - PIXEL_HEIGHT (f)
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);
3550 }
3551
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. */
3557
3558 x_set_offset (f, xoff, yoff, change_gravity)
3559 struct frame *f;
3560 register int xoff, yoff;
3561 int change_gravity;
3562 {
3563 int modified_top, modified_left;
3564
3565 if (change_gravity > 0)
3566 {
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);
3570 if (xoff < 0)
3571 f->output_data.w32->size_hint_flags |= XNegative;
3572 if (yoff < 0)
3573 f->output_data.w32->size_hint_flags |= YNegative;
3574 f->output_data.w32->win_gravity = NorthWestGravity;
3575 }
3576 x_calc_absolute_position (f);
3577
3578 BLOCK_INPUT;
3579 x_wm_set_size_hint (f, (long) 0, 0);
3580
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;
3585 #ifndef HAVE_NTGUI
3586 /* Do not add in border widths under W32. */
3587 if (change_gravity != 0)
3588 {
3589 modified_left += f->output_data.w32->border_width;
3590 modified_top += f->output_data.w32->border_width;
3591 }
3592 #endif
3593
3594 my_set_window_pos (FRAME_W32_WINDOW (f),
3595 NULL,
3596 modified_left, modified_top,
3597 0,0,
3598 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
3599 UNBLOCK_INPUT;
3600 }
3601
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. */
3606
3607 x_set_window_size (f, change_gravity, cols, rows)
3608 struct frame *f;
3609 int change_gravity;
3610 int cols, rows;
3611 {
3612 int pixelwidth, pixelheight;
3613 Lisp_Object window;
3614 struct w32_display_info *dpyinfo = &one_w32_display_info;
3615
3616 BLOCK_INPUT;
3617
3618 check_frame_size (f, &rows, &cols);
3619 f->output_data.w32->vertical_scroll_bar_extra
3620 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3621 ? 0
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);
3627
3628 f->output_data.w32->win_gravity = NorthWestGravity;
3629 x_wm_set_size_hint (f, (long) 0, 0);
3630
3631 {
3632 RECT rect;
3633
3634 rect.left = rect.top = 0;
3635 rect.right = pixelwidth;
3636 rect.bottom = pixelheight;
3637
3638 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
3639 FRAME_EXTERNAL_MENU_BAR (f));
3640
3641 my_set_window_pos (FRAME_W32_WINDOW (f),
3642 NULL,
3643 0, 0,
3644 rect.right - rect.left,
3645 rect.bottom - rect.top,
3646 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
3647 }
3648
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.
3653
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;
3662
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);
3668
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)
3672 {
3673 f->phys_cursor_x = -1;
3674 f->phys_cursor_y = -1;
3675 }
3676
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)
3683 {
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;
3687 }
3688
3689 UNBLOCK_INPUT;
3690 }
3691 \f
3692 /* Mouse warping. */
3693
3694 void
3695 x_set_mouse_pixel_position (f, pix_x, pix_y)
3696 struct frame *f;
3697 int pix_x, pix_y;
3698 {
3699 RECT rect;
3700 POINT pt;
3701
3702 BLOCK_INPUT;
3703
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);
3708
3709 SetCursorPos (pt.x, pt.y);
3710
3711 UNBLOCK_INPUT;
3712 }
3713
3714 void
3715 x_set_mouse_position (f, x, y)
3716 struct frame *f;
3717 int x, y;
3718 {
3719 int pix_x, pix_y;
3720
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;
3723
3724 if (pix_x < 0) pix_x = 0;
3725 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3726
3727 if (pix_y < 0) pix_y = 0;
3728 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3729
3730 x_set_mouse_pixel_position (f, pix_x, pix_y);
3731 }
3732 \f
3733 /* focus shifting, raising and lowering. */
3734
3735 x_focus_on_frame (f)
3736 struct frame *f;
3737 {
3738 struct w32_display_info *dpyinfo = &one_w32_display_info;
3739
3740 /* Give input focus to frame. */
3741 BLOCK_INPUT;
3742 #if 0
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));
3746 else
3747 #endif
3748 SetForegroundWindow (FRAME_W32_WINDOW (f));
3749 UNBLOCK_INPUT;
3750 }
3751
3752 x_unfocus_frame (f)
3753 struct frame *f;
3754 {
3755 }
3756
3757 /* Raise frame F. */
3758
3759 x_raise_frame (f)
3760 struct frame *f;
3761 {
3762 BLOCK_INPUT;
3763
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
3768 click-to-focus.
3769
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.
3778
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. */
3782
3783 if (NILP (Vw32_grab_focus_on_raise))
3784 {
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. */
3790
3791 HDWP handle = BeginDeferWindowPos (2);
3792 if (handle)
3793 {
3794 DeferWindowPos (handle,
3795 FRAME_W32_WINDOW (f),
3796 HWND_TOP,
3797 0, 0, 0, 0,
3798 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3799
3800 DeferWindowPos (handle,
3801 GetForegroundWindow (),
3802 FRAME_W32_WINDOW (f),
3803 0, 0, 0, 0,
3804 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3805
3806 EndDeferWindowPos (handle);
3807 }
3808 }
3809 else
3810 {
3811 SetForegroundWindow (FRAME_W32_WINDOW (f));
3812 }
3813
3814 UNBLOCK_INPUT;
3815 }
3816
3817 /* Lower frame F. */
3818
3819 x_lower_frame (f)
3820 struct frame *f;
3821 {
3822 BLOCK_INPUT;
3823 my_set_window_pos (FRAME_W32_WINDOW (f),
3824 HWND_BOTTOM,
3825 0, 0, 0, 0,
3826 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
3827 UNBLOCK_INPUT;
3828 }
3829
3830 static void
3831 w32_frame_raise_lower (f, raise)
3832 FRAME_PTR f;
3833 int raise;
3834 {
3835 if (raise)
3836 x_raise_frame (f);
3837 else
3838 x_lower_frame (f);
3839 }
3840 \f
3841 /* Change of visibility. */
3842
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. */
3849
3850 x_make_frame_visible (f)
3851 struct frame *f;
3852 {
3853 BLOCK_INPUT;
3854
3855 if (! FRAME_VISIBLE_P (f))
3856 {
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);
3864
3865 f->output_data.w32->asked_for_visible = 1;
3866
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);
3869 }
3870
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. */
3874 {
3875 Lisp_Object frame;
3876 int count = input_signal_count;
3877
3878 /* This must come after we set COUNT. */
3879 UNBLOCK_INPUT;
3880
3881 XSETFRAME (frame, f);
3882
3883 while (1)
3884 {
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)
3891 break;
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 ())
3898 {
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. */
3901 alarm (0);
3902 input_poll_signal ();
3903 }
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)
3910 break;
3911 }
3912 FRAME_SAMPLE_VISIBILITY (f);
3913 }
3914 }
3915
3916 /* Change from mapped state to withdrawn state. */
3917
3918 /* Make the frame visible (mapped and not iconified). */
3919
3920 x_make_frame_invisible (f)
3921 struct frame *f;
3922 {
3923 Window window;
3924
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;
3928
3929 BLOCK_INPUT;
3930
3931 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
3932
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. */
3938 f->visible = 0;
3939 FRAME_ICONIFIED_P (f) = 0;
3940 f->async_visible = 0;
3941 f->async_iconified = 0;
3942
3943 UNBLOCK_INPUT;
3944 }
3945
3946 /* Change window state from mapped to iconified. */
3947
3948 void
3949 x_iconify_frame (f)
3950 struct frame *f;
3951 {
3952 int result;
3953
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;
3957
3958 if (f->async_iconified)
3959 return;
3960
3961 BLOCK_INPUT;
3962
3963 /* Simulate the user minimizing the frame. */
3964 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
3965
3966 f->async_iconified = 1;
3967
3968 UNBLOCK_INPUT;
3969 }
3970 \f
3971 /* Destroy the window of frame F. */
3972
3973 x_destroy_window (f)
3974 struct frame *f;
3975 {
3976 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3977
3978 BLOCK_INPUT;
3979
3980 my_destroy_window (f, FRAME_W32_WINDOW (f));
3981 free_frame_menubar (f);
3982 free_frame_faces (f);
3983
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;
3992
3993 dpyinfo->reference_count--;
3994
3995 if (f == dpyinfo->mouse_face_mouse_frame)
3996 {
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;
4002 }
4003
4004 UNBLOCK_INPUT;
4005 }
4006 \f
4007 /* Setting window manager hints. */
4008
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). */
4014
4015 x_wm_set_size_hint (f, flags, user_position)
4016 struct frame *f;
4017 long flags;
4018 int user_position;
4019 {
4020 Window window = FRAME_W32_WINDOW (f);
4021
4022 flexlines = f->height;
4023
4024 enter_crit ();
4025
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);
4030
4031 leave_crit ();
4032 }
4033
4034 /* Window manager things */
4035 x_wm_set_icon_position (f, icon_x, icon_y)
4036 struct frame *f;
4037 int icon_x, icon_y;
4038 {
4039 #if 0
4040 Window window = FRAME_W32_WINDOW (f);
4041
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;
4045
4046 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
4047 #endif
4048 }
4049
4050 \f
4051 /* Initialization. */
4052
4053 #ifdef USE_X_TOOLKIT
4054 static XrmOptionDescRec emacs_options[] = {
4055 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
4056 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
4057
4058 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4059 XrmoptionSepArg, NULL},
4060 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
4061
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}
4069 };
4070 #endif /* USE_X_TOOLKIT */
4071
4072 static int w32_initialized = 0;
4073
4074 struct w32_display_info *
4075 w32_term_init (display_name, xrm_option, resource_name)
4076 Lisp_Object display_name;
4077 char *xrm_option;
4078 char *resource_name;
4079 {
4080 Lisp_Object frame;
4081 char *defaultvalue;
4082 struct w32_display_info *dpyinfo;
4083 HDC hdc;
4084
4085 BLOCK_INPUT;
4086
4087 if (!w32_initialized)
4088 {
4089 w32_initialize ();
4090 w32_initialized = 1;
4091 }
4092
4093 {
4094 int argc = 0;
4095 char *argv[3];
4096
4097 argv[0] = "";
4098 argc = 1;
4099 if (xrm_option)
4100 {
4101 argv[argc++] = "-xrm";
4102 argv[argc++] = xrm_option;
4103 }
4104 }
4105
4106 dpyinfo = &one_w32_display_info;
4107
4108 /* Put this display on the chain. */
4109 dpyinfo->next = NULL;
4110
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;
4115
4116 dpyinfo->w32_id_name
4117 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4118 + XSTRING (Vsystem_name)->size
4119 + 2);
4120 sprintf (dpyinfo->w32_id_name, "%s@%s",
4121 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
4122
4123 #if 0
4124 xrdb = x_load_resources (dpyinfo->display, xrm_option,
4125 resource_name, EMACS_CLASS);
4126
4127 /* Put the rdb where we can find it in a way that works on
4128 all versions. */
4129 dpyinfo->xrdb = xrdb;
4130 #endif
4131 hdc = GetDC (GetDesktopWindow ());
4132
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;
4159
4160 ReleaseDC (GetDesktopWindow (), hdc);
4161
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
4164 mouse-3. */
4165 XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
4166
4167 /* initialise palette with white and black */
4168 {
4169 COLORREF color;
4170 defined_color (0, "white", &color, 1);
4171 defined_color (0, "black", &color, 1);
4172 }
4173
4174 #ifndef F_SETOWN_BUG
4175 #ifdef F_SETOWN
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 */
4184
4185 #ifdef SIGIO
4186 if (interrupt_input)
4187 init_sigio (connection);
4188 #endif /* ! defined (SIGIO) */
4189
4190 UNBLOCK_INPUT;
4191
4192 return dpyinfo;
4193 }
4194 \f
4195 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4196
4197 void
4198 x_delete_display (dpyinfo)
4199 struct w32_display_info *dpyinfo;
4200 {
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;
4206 else
4207 {
4208 Lisp_Object tail;
4209
4210 tail = w32_display_name_list;
4211 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
4212 {
4213 if (EQ (XCONS (XCONS (tail)->cdr)->car,
4214 dpyinfo->name_list_element))
4215 {
4216 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
4217 break;
4218 }
4219 tail = XCONS (tail)->cdr;
4220 }
4221 }
4222
4223 /* free palette table */
4224 {
4225 struct w32_palette_entry * plist;
4226
4227 plist = dpyinfo->color_list;
4228 while (plist)
4229 {
4230 struct w32_palette_entry * pentry = plist;
4231 plist = plist->next;
4232 xfree(pentry);
4233 }
4234 dpyinfo->color_list = NULL;
4235 if (dpyinfo->palette)
4236 DeleteObject(dpyinfo->palette);
4237 }
4238 xfree (dpyinfo->font_table);
4239 xfree (dpyinfo->w32_id_name);
4240 }
4241 \f
4242 /* Set up use of W32. */
4243
4244 DWORD w32_msg_worker ();
4245
4246 w32_initialize ()
4247 {
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;
4272
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
4278 off the bottom */
4279 baud_rate = 19200;
4280
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);
4284
4285 /* Create the window thread - it will terminate itself or when the app terminates */
4286
4287 init_crit ();
4288
4289 dwMainThreadId = GetCurrentThreadId ();
4290 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
4291 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
4292
4293 /* Wait for thread to start */
4294
4295 {
4296 MSG msg;
4297
4298 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
4299
4300 hWindowsThread = CreateThread (NULL, 0,
4301 (LPTHREAD_START_ROUTINE) w32_msg_worker,
4302 0, 0, &dwWindowsThreadId);
4303
4304 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
4305 }
4306
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
4314 window state. */
4315 #ifdef ATTACH_THREADS
4316 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
4317 #endif
4318
4319 /* Dynamically link to optional system components. */
4320 {
4321 HANDLE user_lib = LoadLibrary ("user32.dll");
4322
4323 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
4324
4325 /* New proportional scroll bar functions. */
4326 LOAD_PROC( SetScrollInfo );
4327 LOAD_PROC( GetScrollInfo );
4328
4329 #undef LOAD_PROC
4330
4331 FreeLibrary (user_lib);
4332
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);
4337
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);
4342 }
4343 }
4344
4345 void
4346 syms_of_w32term ()
4347 {
4348 staticpro (&w32_display_name_list);
4349 w32_display_name_list = Qnil;
4350
4351 staticpro (&last_mouse_scroll_bar);
4352 last_mouse_scroll_bar = Qnil;
4353
4354 staticpro (&Qvendor_specific_keysyms);
4355 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
4356
4357 DEFVAR_INT ("w32-num-mouse-buttons",
4358 &Vw32_num_mouse_buttons,
4359 "Number of physical mouse buttons.");
4360 Vw32_num_mouse_buttons = Qnil;
4361
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;
4367
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;
4375
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;
4381 }