(Fset_window_start): Clear last_overlay_modified field.
[bpt/emacs.git] / src / w32term.c
CommitLineData
ee78dc32
GV
1/* Implementation of Win32 GUI terminal
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
1fb87c77
KH
17along with GNU Emacs; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
ee78dc32
GV
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 "blockinput.h"
28
29#include <w32term.h>
30
31#include "systty.h"
32#include "systime.h"
33
34#include <ctype.h>
35#include <errno.h>
36#include <setjmp.h>
37#include <sys/stat.h>
38
39#include "frame.h"
40#include "dispextern.h"
41#include "termhooks.h"
42#include "termopts.h"
43#include "termchar.h"
44#include "gnu.h"
45#include "disptab.h"
46#include "buffer.h"
47#include "window.h"
48#include "keyboard.h"
49#include "intervals.h"
50
51extern void free_frame_menubar ();
52
52cf03a1
GV
53extern Lisp_Object Vwindow_system;
54
ee78dc32
GV
55#define x_any_window_to_frame x_window_to_frame
56#define x_top_window_to_frame x_window_to_frame
57
58\f
59/* This is display since win32 does not support multiple ones. */
60struct win32_display_info one_win32_display_info;
61
62/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
63 one for each element of win32_display_list and in the same order.
64 NAME is the name of the frame.
65 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
66Lisp_Object win32_display_name_list;
67
68/* Frame being updated by update_frame. This is declared in term.c.
69 This is set by update_begin and looked at by all the
70 win32 functions. It is zero while not inside an update.
71 In that case, the win32 functions assume that `selected_frame'
72 is the frame to apply to. */
73extern struct frame *updating_frame;
74
75/* This is a frame waiting to be autoraised, within w32_read_socket. */
76struct frame *pending_autoraise_frame;
77
78/* During an update, maximum vpos for ins/del line operations to affect. */
79
80static int flexlines;
81
82/* During an update, nonzero if chars output now should be highlighted. */
83
84static int highlight;
85
86/* Nominal cursor position -- where to draw output.
87 During an update, these are different from the cursor-box position. */
88
89static int curs_x;
90static int curs_y;
91
92DWORD dwWinThreadId = 0;
93HANDLE hWinThread = NULL;
94DWORD dwMainThreadId = 0;
95HANDLE hMainThread = NULL;
96
97/* Mouse movement. */
98
99/* Where the mouse was last time we reported a mouse event. */
100static FRAME_PTR last_mouse_frame;
101static RECT last_mouse_glyph;
102
52cf03a1
GV
103Lisp_Object Vwin32_num_mouse_buttons;
104
105Lisp_Object Vwin32_swap_mouse_buttons;
106
ee78dc32
GV
107/* The scroll bar in which the last motion event occurred.
108
109 If the last motion event occurred in a scroll bar, we set this
110 so win32_mouse_position can know whether to report a scroll bar motion or
111 an ordinary motion.
112
113 If the last motion event didn't occur in a scroll bar, we set this
114 to Qnil, to tell win32_mouse_position to return an ordinary motion event. */
115Lisp_Object last_mouse_scroll_bar;
116int last_mouse_scroll_bar_pos;
117
118/* This is a hack. We would really prefer that win32_mouse_position would
119 return the time associated with the position it returns, but there
120 doesn't seem to be any way to wrest the timestamp from the server
121 along with the position query. So, we just keep track of the time
122 of the last movement we received, and return that in hopes that
123 it's somewhat accurate. */
124Time last_mouse_movement_time;
125
126/* Incremented by w32_read_socket whenever it really tries to read events. */
127#ifdef __STDC__
128static int volatile input_signal_count;
129#else
130static int input_signal_count;
131#endif
132
133extern Lisp_Object Vcommand_line_args, Vsystem_name;
134
135extern Lisp_Object Qface, Qmouse_face;
136
137extern int errno;
138
139/* A mask of extra modifier bits to put into every keyboard char. */
140extern int extra_keyboard_modifiers;
141
142static Lisp_Object Qvendor_specific_keysyms;
143
144void win32_delete_display ();
145
146static void redraw_previous_char ();
147static void redraw_following_char ();
148static unsigned int win32_get_modifiers ();
149
150static int fast_find_position ();
151static void note_mouse_highlight ();
152static void clear_mouse_face ();
153static void show_mouse_face ();
154static void do_line_dance ();
155
156static int win32_cursor_to ();
157static int win32_clear_end_of_line ();
158\f
159#if 0
160/* This is a function useful for recording debugging information
161 about the sequence of occurrences in this file. */
162
163struct record
164{
165 char *locus;
166 int type;
167};
168
169struct record event_record[100];
170
171int event_record_index;
172
173record_event (locus, type)
174 char *locus;
175 int type;
176{
177 if (event_record_index == sizeof (event_record) / sizeof (struct record))
178 event_record_index = 0;
179
180 event_record[event_record_index].locus = locus;
181 event_record[event_record_index].type = type;
182 event_record_index++;
183}
184
185#endif /* 0 */
186\f
187/* Return the struct win32_display_info. */
188
189struct win32_display_info *
190win32_display_info_for_display ()
191{
192 return (&one_win32_display_info);
193}
194
195void
196win32_fill_rect (f, _hdc, pix, lprect)
197 FRAME_PTR f;
198 HDC _hdc;
199 COLORREF pix;
200 RECT * lprect;
201{
202 HDC hdc;
203 HBRUSH hb;
ee78dc32
GV
204 RECT rect;
205
206 if (_hdc)
207 hdc = _hdc;
208 else
209 {
210 if (!f) return;
52cf03a1 211 hdc = get_frame_dc (f);
ee78dc32
GV
212 }
213
214 hb = CreateSolidBrush (pix);
ee78dc32 215 FillRect (hdc, lprect, hb);
ee78dc32
GV
216 DeleteObject (hb);
217
218 if (!_hdc)
52cf03a1 219 release_frame_dc (f, hdc);
ee78dc32
GV
220}
221
222void
223win32_clear_window (f)
224 FRAME_PTR f;
225{
226 RECT rect;
52cf03a1 227
ee78dc32
GV
228 GetClientRect (FRAME_WIN32_WINDOW (f), &rect);
229 win32_clear_rect (f, NULL, &rect);
230}
231
232\f
233/* Starting and ending updates.
234
235 These hooks are called by update_frame at the beginning and end
236 of a frame update. We record in `updating_frame' the identity
237 of the frame being updated, so that the win32_... functions do not
238 need to take a frame as argument. Most of the win32_... functions
239 should never be called except during an update, the only exceptions
240 being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight. */
241
242static
243win32_update_begin (f)
244 struct frame *f;
245{
246 if (f == 0)
247 abort ();
248
249 flexlines = f->height;
250 highlight = 0;
251
252 BLOCK_INPUT;
253
52cf03a1
GV
254 /* Regenerate display palette before drawing if list of requested
255 colors has changed. */
256 if (FRAME_WIN32_DISPLAY_INFO (f)->regen_palette)
257 {
258 win32_regenerate_palette (f);
259 FRAME_WIN32_DISPLAY_INFO (f)->regen_palette = FALSE;
260 }
261
ee78dc32
GV
262 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
263 {
264 /* Don't do highlighting for mouse motion during the update. */
265 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 1;
266
267 /* If the frame needs to be redrawn,
268 simply forget about any prior mouse highlighting. */
269 if (FRAME_GARBAGED_P (f))
270 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
271
272 if (!NILP (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
273 {
274 int firstline, lastline, i;
275 struct window *w = XWINDOW (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window);
276
277 /* Find the first, and the last+1, lines affected by redisplay. */
278 for (firstline = 0; firstline < f->height; firstline++)
279 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
280 break;
281
282 lastline = f->height;
283 for (i = f->height - 1; i >= 0; i--)
284 {
285 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
286 break;
287 else
288 lastline = i;
289 }
290
291 /* Can we tell that this update does not affect the window
292 where the mouse highlight is? If so, no need to turn off.
293 Likewise, don't do anything if the frame is garbaged;
294 in that case, the FRAME_CURRENT_GLYPHS that we would use
295 are all wrong, and we will redisplay that line anyway. */
296 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
297 || lastline < XFASTINT (w->top)))
298 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
299 }
300 }
301
302 UNBLOCK_INPUT;
303}
304
305static
306win32_update_end (f)
307 struct frame *f;
308{
309 BLOCK_INPUT;
310
311 do_line_dance ();
312 x_display_cursor (f, 1);
313
314 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
315 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 0;
316
317 UNBLOCK_INPUT;
318}
319
320/* This is called after a redisplay on frame F. */
321
322static
323win32_frame_up_to_date (f)
324 FRAME_PTR f;
325{
326 if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc
327 || f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
328 {
329 note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
330 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x,
331 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y);
332 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
333 }
334}
335\f
336/* External interface to control of standout mode.
337 Call this when about to modify line at position VPOS
338 and not change whether it is highlighted. */
339
340win32_reassert_line_highlight (new, vpos)
341 int new, vpos;
342{
343 highlight = new;
344}
345
346/* Call this when about to modify line at position VPOS
347 and change whether it is highlighted. */
348
349static
350win32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
351 int new_highlight, vpos, first_unused_hpos;
352{
353 highlight = new_highlight;
354 win32_cursor_to (vpos, 0);
355 win32_clear_end_of_line (updating_frame->width);
356}
357
358/* This is used when starting Emacs and when restarting after suspend.
359 When starting Emacs, no window is mapped. And nothing must be done
360 to Emacs's own window if it is suspended (though that rarely happens). */
361
362static
363win32_set_terminal_modes ()
364{
365}
366
367/* This is called when exiting or suspending Emacs.
368 Exiting will make the Win32 windows go away, and suspending
369 requires no action. */
370
371static
372win32_reset_terminal_modes ()
373{
374}
375\f
376/* Set the nominal cursor position of the frame.
377 This is where display update commands will take effect.
378 This does not affect the place where the cursor-box is displayed. */
379
380static int
381win32_cursor_to (row, col)
382 register int row, col;
383{
384 int orow = row;
385
386 curs_x = col;
387 curs_y = row;
388
389 if (updating_frame == 0)
390 {
391 BLOCK_INPUT;
392 x_display_cursor (selected_frame, 1);
393 UNBLOCK_INPUT;
394 }
395}
396\f
397/* Display a sequence of N glyphs found at GP.
398 WINDOW is the window to output to. LEFT and TOP are starting coords.
399 HL is 1 if this text is highlighted, 2 if the cursor is on it,
400 3 if should appear in its mouse-face.
401 JUST_FOREGROUND if 1 means draw only the foreground;
402 don't alter the background.
403
404 FONT is the default font to use (for glyphs whose font-code is 0).
405
406 Since the display generation code is responsible for calling
407 compute_char_face and compute_glyph_face on everything it puts in
408 the display structure, we can assume that the face code on each
409 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
410 to which we can actually apply intern_face.
411 Call this function with input blocked. */
412
413static void
414dumpglyphs (f, left, top, gp, n, hl, just_foreground)
415 struct frame *f;
416 int left, top;
417 register GLYPH *gp; /* Points to first GLYPH. */
418 register int n; /* Number of glyphs to display. */
419 int hl;
420 int just_foreground;
421{
422 /* Holds characters to be displayed. */
423 char *buf = (char *) alloca (f->width * sizeof (*buf));
424 register char *cp; /* Steps through buf[]. */
425 register int tlen = GLYPH_TABLE_LENGTH;
426 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
427 Window window = FRAME_WIN32_WINDOW (f);
428 int orig_left = left;
429 HDC hdc;
430
52cf03a1 431 hdc = get_frame_dc (f);
ee78dc32
GV
432
433 while (n > 0)
434 {
435 /* Get the face-code of the next GLYPH. */
436 int cf, len;
437 int g = *gp;
438
439 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
440 cf = FAST_GLYPH_FACE (g);
441
442 /* Find the run of consecutive glyphs with the same face-code.
443 Extract their character codes into BUF. */
444 cp = buf;
445 while (n > 0)
446 {
447 g = *gp;
448 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
449 if (FAST_GLYPH_FACE (g) != cf)
450 break;
451
452 *cp++ = FAST_GLYPH_CHAR (g);
453 --n;
454 ++gp;
455 }
456
457 /* LEN gets the length of the run. */
458 len = cp - buf;
459
460 /* Now output this run of chars, with the font and pixel values
461 determined by the face code CF. */
462 {
463 struct face *face = FRAME_DEFAULT_FACE (f);
464 XFontStruct *font = FACE_FONT (face);
465 int stippled = 0;
466 COLORREF fg;
467 COLORREF bg;
468
469 /* HL = 3 means use a mouse face previously chosen. */
470 if (hl == 3)
471 cf = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id;
472
473 /* First look at the face of the text itself. */
474 if (cf != 0)
475 {
476 /* It's possible for the display table to specify
477 a face code that is out of range. Use 0 in that case. */
478 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
479 || FRAME_COMPUTED_FACES (f) [cf] == 0)
480 cf = 0;
481
482 if (cf == 1)
483 face = FRAME_MODE_LINE_FACE (f);
484 else
485 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
486 font = FACE_FONT (face);
487 if (FACE_STIPPLE (face))
488 stippled = 1;
489 }
490
491 /* Then comes the distinction between modeline and normal text. */
492 else if (hl == 0)
493 ;
494 else if (hl == 1)
495 {
496 face = FRAME_MODE_LINE_FACE (f);
497 font = FACE_FONT (face);
498 if (FACE_STIPPLE (face))
499 stippled = 1;
500 }
501
502 fg = face->foreground;
503 bg = face->background;
504
505 /* Now override that if the cursor's on this character. */
506 if (hl == 2)
507 {
508 /* The cursor overrides stippling. */
509 stippled = 0;
510
511 if ((!face->font
512 || face->font == (XFontStruct *) FACE_DEFAULT
513 || face->font == f->output_data.win32->font)
514 && face->background == f->output_data.win32->background_pixel
515 && face->foreground == f->output_data.win32->foreground_pixel)
516 {
517 bg = f->output_data.win32->cursor_pixel;
518 fg = face->background;
519 }
520 /* Cursor on non-default face: must merge. */
521 else
522 {
523 bg = f->output_data.win32->cursor_pixel;
524 fg = face->background;
525 /* If the glyph would be invisible,
526 try a different foreground. */
527 if (fg == bg)
528 fg = face->foreground;
529 if (fg == bg)
530 fg = f->output_data.win32->cursor_foreground_pixel;
531 if (fg == bg)
532 fg = face->foreground;
533 /* Make sure the cursor is distinct from text in this face. */
534 if (bg == face->background
535 && fg == face->foreground)
536 {
537 bg = face->foreground;
538 fg = face->background;
539 }
540 }
541 }
542
543 if (font == (XFontStruct *) FACE_DEFAULT)
544 font = f->output_data.win32->font;
545
546 SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
547
548 SetTextColor (hdc, fg);
549 SetBkColor (hdc, bg);
550
551 SelectObject (hdc, font->hfont);
552
553 TextOut (hdc, left, top, buf, len);
554
555 if (!just_foreground)
556 {
557 /* Clear the rest of the line's height. */
558 if (f->output_data.win32->line_height != FONT_HEIGHT (font))
559 win32_fill_area (f, hdc, bg,
560 left,
561 top + FONT_HEIGHT (font),
562 FONT_WIDTH (font) * len,
563 f->output_data.win32->line_height - FONT_HEIGHT (font));
564 }
565
566 {
567 int underline_position = 1;
568
569 if (font->tm.tmDescent <= underline_position)
570 underline_position = font->tm.tmDescent - 1;
571
572 if (face->underline)
573 win32_fill_area (f, hdc, fg,
574 left, (top
575 + FONT_BASE (font)
576 + underline_position),
577 len * FONT_WIDTH (font), 1);
578 }
579
580 left += len * FONT_WIDTH (font);
581 }
582 }
583
52cf03a1 584 release_frame_dc (f, hdc);
ee78dc32
GV
585}
586
587\f
588/* Output some text at the nominal frame cursor position.
589 Advance the cursor over the text.
590 Output LEN glyphs at START.
591
592 `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
593 controls the pixel values used for foreground and background. */
594
595static
596win32_write_glyphs (start, len)
597 register GLYPH *start;
598 int len;
599{
600 register int temp_length;
601 struct frame *f;
602
603 BLOCK_INPUT;
604
605 do_line_dance ();
606 f = updating_frame;
607 if (f == 0)
608 {
609 f = selected_frame;
610 /* If not within an update,
611 output at the frame's visible cursor. */
612 curs_x = f->cursor_x;
613 curs_y = f->cursor_y;
614 }
615
616 dumpglyphs (f,
617 CHAR_TO_PIXEL_COL (f, curs_x),
618 CHAR_TO_PIXEL_ROW (f, curs_y),
619 start, len, highlight, 0);
620
621 /* If we drew on top of the cursor, note that it is turned off. */
622 if (curs_y == f->phys_cursor_y
623 && curs_x <= f->phys_cursor_x
624 && curs_x + len > f->phys_cursor_x)
625 f->phys_cursor_x = -1;
626
627 if (updating_frame == 0)
628 {
629 f->cursor_x += len;
630 x_display_cursor (f, 1);
631 f->cursor_x -= len;
632 }
633 else
634 curs_x += len;
635
636 UNBLOCK_INPUT;
637}
638\f
639/* Clear to the end of the line.
640 Erase the current text line from the nominal cursor position (inclusive)
641 to column FIRST_UNUSED (exclusive). The idea is that everything
642 from FIRST_UNUSED onward is already erased. */
643
644static
645win32_clear_end_of_line (first_unused)
646 register int first_unused;
647{
648 struct frame *f = updating_frame;
649
650 if (f == 0)
651 abort ();
652
653 if (curs_y < 0 || curs_y >= f->height)
654 return 1;
655 if (first_unused <= 0)
656 return 1;
657
658 if (first_unused >= f->width)
659 first_unused = f->width;
660
661 BLOCK_INPUT;
662
663 do_line_dance ();
664
665 /* Notice if the cursor will be cleared by this operation. */
666 if (curs_y == f->phys_cursor_y
667 && curs_x <= f->phys_cursor_x
668 && f->phys_cursor_x < first_unused)
669 f->phys_cursor_x = -1;
670
671 win32_clear_area (f, NULL,
672 CHAR_TO_PIXEL_COL (f, curs_x),
673 CHAR_TO_PIXEL_ROW (f, curs_y),
674 FONT_WIDTH (f->output_data.win32->font) * (first_unused - curs_x),
675 f->output_data.win32->line_height);
676
677 UNBLOCK_INPUT;
678}
679
680static
681win32_clear_frame ()
682{
683 struct frame *f = updating_frame;
684
685 if (f == 0)
686 f = selected_frame;
687
688 f->phys_cursor_x = -1; /* Cursor not visible. */
689 curs_x = 0; /* Nominal cursor position is top left. */
690 curs_y = 0;
691
692 BLOCK_INPUT;
693
694 win32_clear_window (f);
695
696 /* We have to clear the scroll bars, too. If we have changed
697 colors or something like that, then they should be notified. */
698 x_scroll_bar_clear (f);
699
700 UNBLOCK_INPUT;
701}
702\f
703/* Make audible bell. */
704
705win32_ring_bell ()
706{
707 BLOCK_INPUT;
708
709 if (visible_bell)
710 FlashWindow (FRAME_WIN32_WINDOW (selected_frame), FALSE);
711 else
712 nt_ring_bell ();
713
714 UNBLOCK_INPUT;
715
716 return 1;
717}
718\f
719/* Insert and delete character.
720 These are not supposed to be used because we are supposed to turn
721 off the feature of using them. */
722
723static
724win32_insert_glyphs (start, len)
725 register char *start;
726 register int len;
727{
728 abort ();
729}
730
731static
732win32_delete_glyphs (n)
733 register int n;
734{
735 abort ();
736}
737\f
738/* Specify how many text lines, from the top of the window,
739 should be affected by insert-lines and delete-lines operations.
740 This, and those operations, are used only within an update
741 that is bounded by calls to win32_update_begin and win32_update_end. */
742
743static
744win32_set_terminal_window (n)
745 register int n;
746{
747 if (updating_frame == 0)
748 abort ();
749
750 if ((n <= 0) || (n > updating_frame->height))
751 flexlines = updating_frame->height;
752 else
753 flexlines = n;
754}
755\f
756/* These variables need not be per frame
757 because redisplay is done on a frame-by-frame basis
758 and the line dance for one frame is finished before
759 anything is done for another frame. */
760
761/* Array of line numbers from cached insert/delete operations.
762 line_dance[i] is the old position of the line that we want
763 to move to line i, or -1 if we want a blank line there. */
764static int *line_dance;
765
766/* Allocated length of that array. */
767static int line_dance_len;
768
769/* Flag indicating whether we've done any work. */
770static int line_dance_in_progress;
771
772/* Perform an insert-lines or delete-lines operation,
773 inserting N lines or deleting -N lines at vertical position VPOS. */
774win32_ins_del_lines (vpos, n)
775 int vpos, n;
776{
777 register int fence, i;
778
779 if (vpos >= flexlines)
780 return 1;
781
782 if (!line_dance_in_progress)
783 {
784 int ht = updating_frame->height;
785 if (ht > line_dance_len)
786 {
787 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
788 line_dance_len = ht;
789 }
790 for (i = 0; i < ht; ++i) line_dance[i] = i;
791 line_dance_in_progress = 1;
792 }
793 if (n >= 0)
794 {
795 if (n > flexlines - vpos)
796 n = flexlines - vpos;
797 fence = vpos + n;
798 for (i = flexlines; --i >= fence;)
799 line_dance[i] = line_dance[i-n];
800 for (i = fence; --i >= vpos;)
801 line_dance[i] = -1;
802 }
803 else
804 {
805 n = -n;
806 if (n > flexlines - vpos)
807 n = flexlines - vpos;
808 fence = flexlines - n;
809 for (i = vpos; i < fence; ++i)
810 line_dance[i] = line_dance[i + n];
811 for (i = fence; i < flexlines; ++i)
812 line_dance[i] = -1;
813 }
814}
815
816/* Here's where we actually move the pixels around.
817 Must be called with input blocked. */
818static void
819do_line_dance ()
820{
821 register int i, j, distance;
822 register struct frame *f;
823 int ht;
824 int intborder;
825 HDC hdc;
826
827 /* Must check this flag first. If it's not set, then not only is the
828 array uninitialized, but we might not even have a frame. */
829 if (!line_dance_in_progress)
830 return;
831
832 f = updating_frame;
833 if (f == 0)
834 abort ();
835
836 ht = f->height;
837 intborder = f->output_data.win32->internal_border_width;
838
839 x_display_cursor (updating_frame, 0);
840
52cf03a1 841 hdc = get_frame_dc (f);
ee78dc32
GV
842
843 for (i = 0; i < ht; ++i)
844 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
845 {
846 for (j = i; (j < ht && line_dance[j] != -1
847 && line_dance[j]-j == distance); ++j);
848 /* Copy [i,j) upward from [i+distance, j+distance) */
849 BitBlt (hdc,
850 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
851 f->width * FONT_WIDTH (f->output_data.win32->font),
852 (j-i) * f->output_data.win32->line_height,
853 hdc,
854 intborder, CHAR_TO_PIXEL_ROW (f, i),
855 SRCCOPY);
856 i = j-1;
857 }
858
859 for (i = ht; --i >=0; )
860 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
861 {
862 for (j = i; (--j >= 0 && line_dance[j] != -1
863 && line_dance[j]-j == distance););
864 /* Copy (j, i] downward from (j+distance, i+distance] */
865 BitBlt (hdc,
866 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
867 f->width * FONT_WIDTH (f->output_data.win32->font),
868 (i-j) * f->output_data.win32->line_height,
869 hdc,
870 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
871 SRCCOPY);
872 i = j+1;
873 }
874
52cf03a1 875 release_frame_dc (f, hdc);
ee78dc32
GV
876
877 for (i = 0; i < ht; ++i)
878 if (line_dance[i] == -1)
879 {
880 for (j = i; j < ht && line_dance[j] == -1; ++j);
881 /* Clear [i,j) */
882 win32_clear_area (f, NULL,
883 intborder,
884 CHAR_TO_PIXEL_ROW (f, i),
885 f->width * FONT_WIDTH (f->output_data.win32->font),
886 (j-i) * f->output_data.win32->line_height);
887 i = j-1;
888 }
889 line_dance_in_progress = 0;
890}
891\f
892/* Support routines for exposure events. */
893static void clear_cursor ();
894
895/* Output into a rectangle of a window (for frame F)
896 the characters in f->phys_lines that overlap that rectangle.
897 TOP and LEFT are the position of the upper left corner of the rectangle.
898 ROWS and COLS are the size of the rectangle.
899 Call this function with input blocked. */
900
901void
902dumprectangle (f, left, top, cols, rows)
903 struct frame *f;
904 register int left, top, cols, rows;
905{
906 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
907 int cursor_cleared = 0;
908 int bottom, right;
909 register int y;
910
911 if (FRAME_GARBAGED_P (f))
912 return;
913
914 /* Express rectangle as four edges, instead of position-and-size. */
915 bottom = top + rows;
916 right = left + cols;
917
918 /* Convert rectangle edges in pixels to edges in chars.
919 Round down for left and top, up for right and bottom. */
920 top = PIXEL_TO_CHAR_ROW (f, top);
921 left = PIXEL_TO_CHAR_COL (f, left);
922 bottom += (f->output_data.win32->line_height - 1);
923 right += (FONT_WIDTH (f->output_data.win32->font) - 1);
924 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
925 right = PIXEL_TO_CHAR_COL (f, right);
926
927 /* Clip the rectangle to what can be visible. */
928 if (left < 0)
929 left = 0;
930 if (top < 0)
931 top = 0;
932 if (right > f->width)
933 right = f->width;
934 if (bottom > f->height)
935 bottom = f->height;
936
937 /* Get size in chars of the rectangle. */
938 cols = right - left;
939 rows = bottom - top;
940
941 /* If rectangle has zero area, return. */
942 if (rows <= 0) return;
943 if (cols <= 0) return;
944
945 /* Turn off the cursor if it is in the rectangle.
946 We will turn it back on afterward. */
947 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
948 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
949 {
950 clear_cursor (f);
951 cursor_cleared = 1;
952 }
953
954 /* Display the text in the rectangle, one text line at a time. */
955
956 for (y = top; y < bottom; y++)
957 {
958 GLYPH *line = &active_frame->glyphs[y][left];
959
960 if (! active_frame->enable[y] || left > active_frame->used[y])
961 continue;
962
963 dumpglyphs (f,
964 CHAR_TO_PIXEL_COL (f, left),
965 CHAR_TO_PIXEL_ROW (f, y),
966 line, min (cols, active_frame->used[y] - left),
967 active_frame->highlight[y], 0);
968 }
969
970 /* Turn the cursor on if we turned it off. */
971
972 if (cursor_cleared)
973 x_display_cursor (f, 1);
974}
975\f
976static void
977frame_highlight (f)
978 struct frame *f;
979{
980 x_display_cursor (f, 1);
981}
982
983static void
984frame_unhighlight (f)
985 struct frame *f;
986{
987 x_display_cursor (f, 1);
988}
989
990static void win32_frame_rehighlight ();
991static void x_frame_rehighlight ();
992
993/* The focus has changed. Update the frames as necessary to reflect
994 the new situation. Note that we can't change the selected frame
995 here, because the Lisp code we are interrupting might become confused.
996 Each event gets marked with the frame in which it occurred, so the
997 Lisp code can tell when the switch took place by examining the events. */
998
999void
1000x_new_focus_frame (dpyinfo, frame)
1001 struct win32_display_info *dpyinfo;
1002 struct frame *frame;
1003{
1004 struct frame *old_focus = dpyinfo->win32_focus_frame;
1005 int events_enqueued = 0;
1006
1007 if (frame != dpyinfo->win32_focus_frame)
1008 {
1009 /* Set this before calling other routines, so that they see
1010 the correct value of win32_focus_frame. */
1011 dpyinfo->win32_focus_frame = frame;
1012
1013 if (old_focus && old_focus->auto_lower)
1014 x_lower_frame (old_focus);
1015
1016 if (dpyinfo->win32_focus_frame && dpyinfo->win32_focus_frame->auto_raise)
1017 pending_autoraise_frame = dpyinfo->win32_focus_frame;
1018 else
1019 pending_autoraise_frame = 0;
1020 }
1021
1022 x_frame_rehighlight (dpyinfo);
1023}
1024
1025/* Handle an event saying the mouse has moved out of an Emacs frame. */
1026
1027void
1028x_mouse_leave (dpyinfo)
1029 struct win32_display_info *dpyinfo;
1030{
1031 x_new_focus_frame (dpyinfo, dpyinfo->win32_focus_event_frame);
1032}
1033
1034/* The focus has changed, or we have redirected a frame's focus to
1035 another frame (this happens when a frame uses a surrogate
1036 minibuffer frame). Shift the highlight as appropriate.
1037
1038 The FRAME argument doesn't necessarily have anything to do with which
1039 frame is being highlighted or unhighlighted; we only use it to find
1040 the appropriate display info. */
1041static void
1042win32_frame_rehighlight (frame)
1043 struct frame *frame;
1044{
1045 x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame));
1046}
1047
1048static void
1049x_frame_rehighlight (dpyinfo)
1050 struct win32_display_info *dpyinfo;
1051{
1052 struct frame *old_highlight = dpyinfo->win32_highlight_frame;
1053
1054 if (dpyinfo->win32_focus_frame)
1055 {
1056 dpyinfo->win32_highlight_frame
1057 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame)))
1058 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame))
1059 : dpyinfo->win32_focus_frame);
1060 if (! FRAME_LIVE_P (dpyinfo->win32_highlight_frame))
1061 {
1062 FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame) = Qnil;
1063 dpyinfo->win32_highlight_frame = dpyinfo->win32_focus_frame;
1064 }
1065 }
1066 else
1067 dpyinfo->win32_highlight_frame = 0;
1068
1069 if (dpyinfo->win32_highlight_frame != old_highlight)
1070 {
1071 if (old_highlight)
1072 frame_unhighlight (old_highlight);
1073 if (dpyinfo->win32_highlight_frame)
1074 frame_highlight (dpyinfo->win32_highlight_frame);
1075 }
1076}
1077\f
1078/* Keyboard processing - modifier keys, etc. */
1079
1080/* Convert a keysym to its name. */
1081
1082char *
1083x_get_keysym_name (keysym)
1084 int keysym;
1085{
1086 /* Make static so we can always return it */
1087 static char value[100];
1088
1089 BLOCK_INPUT;
1090 GetKeyNameText(keysym, value, 100);
1091 UNBLOCK_INPUT;
1092
1093 return value;
1094}
1095\f
1096/* Mouse clicks and mouse movement. Rah. */
1097
1098/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1099 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1100 that the glyph at X, Y occupies, if BOUNDS != 0.
1101 If NOCLIP is nonzero, do not force the value into range. */
1102
1103void
1104pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1105 FRAME_PTR f;
1106 register int pix_x, pix_y;
1107 register int *x, *y;
1108 RECT *bounds;
1109 int noclip;
1110{
52cf03a1
GV
1111 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1112 if (NILP (Vwindow_system))
1113 {
1114 *x = pix_x;
1115 *y = pix_y;
1116 return;
1117 }
1118
ee78dc32
GV
1119 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1120 even for negative values. */
1121 if (pix_x < 0)
1122 pix_x -= FONT_WIDTH ((f)->output_data.win32->font) - 1;
1123 if (pix_y < 0)
1124 pix_y -= (f)->output_data.win32->line_height - 1;
1125
1126 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1127 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1128
1129 if (bounds)
1130 {
1131 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
1132 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
1133 bounds->right = bounds->left + FONT_WIDTH (f->output_data.win32->font) - 1;
1134 bounds->bottom = bounds->top + f->output_data.win32->line_height - 1;
1135 }
1136
1137 if (!noclip)
1138 {
1139 if (pix_x < 0)
1140 pix_x = 0;
1141 else if (pix_x > f->width)
1142 pix_x = f->width;
1143
1144 if (pix_y < 0)
1145 pix_y = 0;
1146 else if (pix_y > f->height)
1147 pix_y = f->height;
1148 }
1149
1150 *x = pix_x;
1151 *y = pix_y;
1152}
1153
1154void
1155glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1156 FRAME_PTR f;
1157 register int x, y;
1158 register int *pix_x, *pix_y;
1159{
52cf03a1
GV
1160 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1161 if (NILP (Vwindow_system))
1162 {
1163 *pix_x = x;
1164 *pix_y = y;
1165 return;
1166 }
1167
ee78dc32
GV
1168 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1169 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1170}
1171
1172BOOL
1173parse_button (message, pbutton, pup)
1174 int message;
1175 int * pbutton;
1176 int * pup;
1177{
1178 int button = 0;
1179 int up = 0;
1180
1181 switch (message)
1182 {
1183 case WM_LBUTTONDOWN:
1184 button = 0;
1185 up = 0;
1186 break;
1187 case WM_LBUTTONUP:
1188 button = 0;
1189 up = 1;
1190 break;
1191 case WM_MBUTTONDOWN:
52cf03a1
GV
1192 if (NILP (Vwin32_swap_mouse_buttons))
1193 button = 1;
1194 else
1195 button = 2;
ee78dc32
GV
1196 up = 0;
1197 break;
1198 case WM_MBUTTONUP:
52cf03a1
GV
1199 if (NILP (Vwin32_swap_mouse_buttons))
1200 button = 1;
1201 else
1202 button = 2;
ee78dc32
GV
1203 up = 1;
1204 break;
1205 case WM_RBUTTONDOWN:
52cf03a1
GV
1206 if (NILP (Vwin32_swap_mouse_buttons))
1207 button = 2;
1208 else
1209 button = 1;
ee78dc32
GV
1210 up = 0;
1211 break;
1212 case WM_RBUTTONUP:
52cf03a1
GV
1213 if (NILP (Vwin32_swap_mouse_buttons))
1214 button = 2;
1215 else
1216 button = 1;
ee78dc32
GV
1217 up = 1;
1218 break;
1219 default:
1220 return (FALSE);
1221 }
1222
1223 if (pup) *pup = up;
1224 if (pbutton) *pbutton = button;
1225
1226 return (TRUE);
1227}
1228
1229
1230/* Prepare a mouse-event in *RESULT for placement in the input queue.
1231
1232 If the event is a button press, then note that we have grabbed
1233 the mouse. */
1234
1235static void
1236construct_mouse_click (result, msg, f)
1237 struct input_event *result;
1238 Win32Msg *msg;
1239 struct frame *f;
1240{
1241 int button;
1242 int up;
1243
1244 parse_button (msg->msg.message, &button, &up);
1245
1246 /* Make the event type no_event; we'll change that when we decide
1247 otherwise. */
1248 result->kind = mouse_click;
1249 result->code = button;
1250 result->timestamp = msg->msg.time;
1251 result->modifiers = (msg->dwModifiers
1252 | (up
1253 ? up_modifier
1254 : down_modifier));
1255
1256 {
1257 int row, column;
1258
1259 XSETINT (result->x, LOWORD (msg->msg.lParam));
1260 XSETINT (result->y, HIWORD (msg->msg.lParam));
1261 XSETFRAME (result->frame_or_window, f);
1262 }
1263}
1264
1265\f
1266/* Function to report a mouse movement to the mainstream Emacs code.
1267 The input handler calls this.
1268
1269 We have received a mouse movement event, which is given in *event.
1270 If the mouse is over a different glyph than it was last time, tell
1271 the mainstream emacs code by setting mouse_moved. If not, ask for
1272 another motion event, so we can check again the next time it moves. */
1273
1274static void
1275note_mouse_movement (frame, msg)
1276 FRAME_PTR frame;
1277 MSG *msg;
1278{
1279 last_mouse_movement_time = msg->time;
1280
1281 if (msg->hwnd != FRAME_WIN32_WINDOW (frame))
1282 {
1283 frame->mouse_moved = 1;
1284 last_mouse_scroll_bar = Qnil;
1285
1286 note_mouse_highlight (frame, -1, -1);
1287 }
1288
1289 /* Has the mouse moved off the glyph it was on at the last sighting? */
1290 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
1291 || LOWORD (msg->lParam) > last_mouse_glyph.right
9bf7b6aa 1292 || HIWORD (msg->lParam) < last_mouse_glyph.top
ee78dc32
GV
1293 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
1294 {
1295 frame->mouse_moved = 1;
1296 last_mouse_scroll_bar = Qnil;
1297
1298 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1299 }
1300}
1301
1302/* This is used for debugging, to turn off note_mouse_highlight. */
1303static int disable_mouse_highlight;
1304
1305/* Take proper action when the mouse has moved to position X, Y on frame F
1306 as regards highlighting characters that have mouse-face properties.
1307 Also dehighlighting chars where the mouse was before.
1308 X and Y can be negative or out of range. */
1309
1310static void
1311note_mouse_highlight (f, x, y)
1312 FRAME_PTR f;
1313 int x, y;
1314{
1315 int row, column, portion;
1316 RECT new_glyph;
1317 Lisp_Object window;
1318 struct window *w;
1319
1320 if (disable_mouse_highlight)
1321 return;
1322
1323 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1324 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1325 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
1326
1327 if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer)
1328 return;
1329
1330 if (gc_in_progress)
1331 {
1332 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1333 return;
1334 }
1335
1336 /* Find out which glyph the mouse is on. */
1337 pixel_to_glyph_coords (f, x, y, &column, &row,
1338 &new_glyph, FRAME_WIN32_DISPLAY_INFO (f)->grabbed);
1339
1340 /* Which window is that in? */
1341 window = window_from_coordinates (f, column, row, &portion);
1342 w = XWINDOW (window);
1343
1344 /* If we were displaying active text in another window, clear that. */
1345 if (! EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
1346 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1347
1348 /* Are we in a window whose display is up to date?
1349 And verify the buffer's text has not changed. */
1350 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1351 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1352 && EQ (w->window_end_valid, w->buffer)
1353 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
1354 {
1355 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1356 int i, pos;
1357
1358 /* Find which buffer position the mouse corresponds to. */
1359 for (i = column; i >= 0; i--)
1360 if (ptr[i] > 0)
1361 break;
1362 pos = ptr[i];
1363 /* Is it outside the displayed active region (if any)? */
1364 if (pos <= 0)
1365 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1366 else if (! (EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window)
1367 && row >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1368 && row <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1369 && (row > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1370 || column >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col)
1371 && (row < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1372 || column < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
1373 || FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end)))
1374 {
1375 Lisp_Object mouse_face, overlay, position;
1376 Lisp_Object *overlay_vec;
1377 int len, noverlays, ignor1;
1378 struct buffer *obuf;
1379 int obegv, ozv;
1380
1381 /* If we get an out-of-range value, return now; avoid an error. */
1382 if (pos > BUF_Z (XBUFFER (w->buffer)))
1383 return;
1384
1385 /* Make the window's buffer temporarily current for
1386 overlays_at and compute_char_face. */
1387 obuf = current_buffer;
1388 current_buffer = XBUFFER (w->buffer);
1389 obegv = BEGV;
1390 ozv = ZV;
1391 BEGV = BEG;
1392 ZV = Z;
1393
1394 /* Yes. Clear the display of the old active region, if any. */
1395 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
1396
1397 /* Is this char mouse-active? */
1398 XSETINT (position, pos);
1399
1400 len = 10;
1401 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1402
1403 /* Put all the overlays we want in a vector in overlay_vec.
1404 Store the length in len. */
1405 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1406 NULL, NULL);
1407 noverlays = sort_overlays (overlay_vec, noverlays, w);
1408
1409 /* Find the highest priority overlay that has a mouse-face prop. */
1410 overlay = Qnil;
1411 for (i = 0; i < noverlays; i++)
1412 {
1413 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1414 if (!NILP (mouse_face))
1415 {
1416 overlay = overlay_vec[i];
1417 break;
1418 }
1419 }
1420 free (overlay_vec);
1421 /* If no overlay applies, get a text property. */
1422 if (NILP (overlay))
1423 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1424
1425 /* Handle the overlay case. */
1426 if (! NILP (overlay))
1427 {
1428 /* Find the range of text around this char that
1429 should be active. */
1430 Lisp_Object before, after;
1431 int ignore;
1432
1433 before = Foverlay_start (overlay);
1434 after = Foverlay_end (overlay);
1435 /* Record this as the current active region. */
1436 fast_find_position (window, before,
1437 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
1438 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
1439 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
1440 = !fast_find_position (window, after,
1441 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
1442 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
1443 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
1444 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
1445 = compute_char_face (f, w, pos, 0, 0,
1446 &ignore, pos + 1, 1);
1447
1448 /* Display it as active. */
1449 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
1450 }
1451 /* Handle the text property case. */
1452 else if (! NILP (mouse_face))
1453 {
1454 /* Find the range of text around this char that
1455 should be active. */
1456 Lisp_Object before, after, beginning, end;
1457 int ignore;
1458
1459 beginning = Fmarker_position (w->start);
1460 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1461 - XFASTINT (w->window_end_pos)));
1462 before
1463 = Fprevious_single_property_change (make_number (pos + 1),
1464 Qmouse_face,
1465 w->buffer, beginning);
1466 after
1467 = Fnext_single_property_change (position, Qmouse_face,
1468 w->buffer, end);
1469 /* Record this as the current active region. */
1470 fast_find_position (window, before,
1471 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
1472 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
1473 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
1474 = !fast_find_position (window, after,
1475 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
1476 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
1477 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
1478 FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
1479 = compute_char_face (f, w, pos, 0, 0,
1480 &ignore, pos + 1, 1);
1481
1482 /* Display it as active. */
1483 show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
1484 }
1485 BEGV = obegv;
1486 ZV = ozv;
1487 current_buffer = obuf;
1488 }
1489 }
1490}
1491\f
1492/* Find the row and column of position POS in window WINDOW.
1493 Store them in *COLUMNP and *ROWP.
1494 This assumes display in WINDOW is up to date.
1495 If POS is above start of WINDOW, return coords
1496 of start of first screen line.
1497 If POS is after end of WINDOW, return coords of end of last screen line.
1498
1499 Value is 1 if POS is in range, 0 if it was off screen. */
1500
1501static int
1502fast_find_position (window, pos, columnp, rowp)
1503 Lisp_Object window;
1504 int pos;
1505 int *columnp, *rowp;
1506{
1507 struct window *w = XWINDOW (window);
1508 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1509 int i;
1510 int row = 0;
1511 int left = w->left;
1512 int top = w->top;
1513 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
1514 int width = window_internal_width (w);
1515 int *charstarts;
1516 int lastcol;
1517 int maybe_next_line = 0;
1518
1519 /* Find the right row. */
1520 for (i = 0;
1521 i < height;
1522 i++)
1523 {
1524 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
1525 if (linestart > pos)
1526 break;
1527 /* If the position sought is the end of the buffer,
1528 don't include the blank lines at the bottom of the window. */
1529 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
1530 {
1531 maybe_next_line = 1;
1532 break;
1533 }
1534 if (linestart > 0)
1535 row = i;
1536 }
1537
1538 /* Find the right column with in it. */
1539 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
1540 lastcol = left;
1541 for (i = 0; i < width; i++)
1542 {
1543 if (charstarts[left + i] == pos)
1544 {
1545 *rowp = row + top;
1546 *columnp = i + left;
1547 return 1;
1548 }
1549 else if (charstarts[left + i] > pos)
1550 break;
1551 else if (charstarts[left + i] > 0)
1552 lastcol = left + i;
1553 }
1554
1555 /* If we're looking for the end of the buffer,
1556 and we didn't find it in the line we scanned,
1557 use the start of the following line. */
1558 if (maybe_next_line)
1559 {
1560 row++;
1561 i = 0;
1562 }
1563
1564 *rowp = row + top;
1565 *columnp = lastcol;
1566 return 0;
1567}
1568
1569/* Display the active region described by mouse_face_*
1570 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1571
1572static void
1573show_mouse_face (dpyinfo, hl)
1574 struct win32_display_info *dpyinfo;
1575 int hl;
1576{
1577 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1578 int width = window_internal_width (w);
1579 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1580 int i;
1581 int cursor_off = 0;
1582 int old_curs_x = curs_x;
1583 int old_curs_y = curs_y;
1584
1585 /* Set these variables temporarily
1586 so that if we have to turn the cursor off and on again
1587 we will put it back at the same place. */
1588 curs_x = f->phys_cursor_x;
1589 curs_y = f->phys_cursor_y;
1590
1591 for (i = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row;
1592 i <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
1593 {
1594 int column = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
1595 ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col
1596 : w->left);
1597 int endcolumn = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
1598 ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
1599 : w->left + width);
1600 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
1601
1602 /* If the cursor's in the text we are about to rewrite,
1603 turn the cursor off. */
1604 if (i == curs_y
1605 && curs_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col - 1
1606 && curs_x <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col)
1607 {
1608 x_display_cursor (f, 0);
1609 cursor_off = 1;
1610 }
1611
1612 dumpglyphs (f,
1613 CHAR_TO_PIXEL_COL (f, column),
1614 CHAR_TO_PIXEL_ROW (f, i),
1615 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
1616 endcolumn - column,
1617 /* Highlight with mouse face if hl > 0. */
1618 hl > 0 ? 3 : 0, 0);
1619 }
1620
1621 /* If we turned the cursor off, turn it back on. */
1622 if (cursor_off)
1623 x_display_cursor (f, 1);
1624
1625 curs_x = old_curs_x;
1626 curs_y = old_curs_y;
1627
1628 /* Change the mouse cursor according to the value of HL. */
1629 if (hl > 0)
1630 SetCursor (f->output_data.win32->cross_cursor);
1631 else
1632 SetCursor (f->output_data.win32->text_cursor);
1633}
1634
1635/* Clear out the mouse-highlighted active region.
1636 Redraw it unhighlighted first. */
1637
1638static void
1639clear_mouse_face (dpyinfo)
1640 struct win32_display_info *dpyinfo;
1641{
1642 if (! NILP (dpyinfo->mouse_face_window))
1643 show_mouse_face (dpyinfo, 0);
1644
1645 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1646 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1647 dpyinfo->mouse_face_window = Qnil;
1648}
1649\f
1650struct scroll_bar *x_window_to_scroll_bar ();
1651static void x_scroll_bar_report_motion ();
1652
1653/* Return the current position of the mouse.
1654 *fp should be a frame which indicates which display to ask about.
1655
1656 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1657 and *part to the frame, window, and scroll bar part that the mouse
1658 is over. Set *x and *y to the portion and whole of the mouse's
1659 position on the scroll bar.
1660
1661 If the mouse movement started elsewhere, set *fp to the frame the
1662 mouse is on, *bar_window to nil, and *x and *y to the character cell
1663 the mouse is over.
1664
1665 Set *time to the server timestamp for the time at which the mouse
1666 was at this position.
1667
1668 Don't store anything if we don't have a valid set of values to report.
1669
1670 This clears the mouse_moved flag, so we can wait for the next mouse
1671 movement. This also calls XQueryPointer, which will cause the
1672 server to give us another MotionNotify when the mouse moves
1673 again. */
1674
1675static void
1676win32_mouse_position (fp, insist, bar_window, part, x, y, time)
1677 FRAME_PTR *fp;
1678 int insist;
1679 Lisp_Object *bar_window;
1680 enum scroll_bar_part *part;
1681 Lisp_Object *x, *y;
1682 unsigned long *time;
1683{
1684 FRAME_PTR f1;
1685
1686 BLOCK_INPUT;
1687
1688 if (! NILP (last_mouse_scroll_bar))
1689 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1690 else
1691 {
1692 POINT pt;
1693
1694 Lisp_Object frame, tail;
1695
1696 /* Clear the mouse-moved flag for every frame on this display. */
1697 FOR_EACH_FRAME (tail, frame)
1698 XFRAME (frame)->mouse_moved = 0;
1699
1700 last_mouse_scroll_bar = Qnil;
1701
1702 GetCursorPos (&pt);
1703
1704 /* Now we have a position on the root; find the innermost window
1705 containing the pointer. */
1706 {
1707 if (FRAME_WIN32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
1708 && FRAME_LIVE_P (last_mouse_frame))
1709 {
1710 f1 = last_mouse_frame;
1711 }
1712 else
1713 {
1714 /* Is win one of our frames? */
1715 f1 = x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
1716 }
1717
1718 /* If not, is it one of our scroll bars? */
1719 if (! f1)
1720 {
1721 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1722
1723 if (bar)
1724 {
1725 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1726 }
1727 }
1728
1729 if (f1 == 0 && insist)
1730 f1 = selected_frame;
1731
1732 if (f1)
1733 {
1734 int ignore1, ignore2;
1735
1736 ScreenToClient (FRAME_WIN32_WINDOW (f1), &pt);
1737
1738 /* Ok, we found a frame. Store all the values. */
1739
1740 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
1741 &last_mouse_glyph,
1742 FRAME_WIN32_DISPLAY_INFO (f1)->grabbed
1743 || insist);
1744
1745 *bar_window = Qnil;
1746 *part = 0;
1747 *fp = f1;
1748 XSETINT (*x, pt.x);
1749 XSETINT (*y, pt.y);
1750 *time = last_mouse_movement_time;
1751 }
1752 }
1753 }
1754
1755 UNBLOCK_INPUT;
1756}
1757\f
1758/* Scroll bar support. */
1759
1760/* Given an window ID, find the struct scroll_bar which manages it.
1761 This can be called in GC, so we have to make sure to strip off mark
1762 bits. */
1763struct scroll_bar *
1764x_window_to_scroll_bar (window_id)
1765 Window window_id;
1766{
1767 Lisp_Object tail, frame;
1768
1769 for (tail = Vframe_list;
1770 XGCTYPE (tail) == Lisp_Cons;
1771 tail = XCONS (tail)->cdr)
1772 {
1773 Lisp_Object frame, bar, condemned;
1774
1775 frame = XCONS (tail)->car;
1776 /* All elements of Vframe_list should be frames. */
1777 if (! GC_FRAMEP (frame))
1778 abort ();
1779
1780 /* Scan this frame's scroll bar list for a scroll bar with the
1781 right window ID. */
1782 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1783 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1784 /* This trick allows us to search both the ordinary and
1785 condemned scroll bar lists with one loop. */
1786 ! GC_NILP (bar) || (bar = condemned,
1787 condemned = Qnil,
1788 ! GC_NILP (bar));
1789 bar = XSCROLL_BAR (bar)->next)
1790 if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar)) == window_id)
1791 return XSCROLL_BAR (bar);
1792 }
1793
1794 return 0;
1795}
1796
1797HWND
1798my_create_scrollbar (f, bar)
1799 struct frame * f;
1800 struct scroll_bar * bar;
1801{
1802 MSG msg;
1803
1804 PostThreadMessage (dwWinThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1805 (LPARAM) bar);
1806 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
1807
1808 return ((HWND) msg.wParam);
1809}
1810
52cf03a1
GV
1811//#define ATTACH_THREADS
1812
1813void
1814my_show_window (HWND hwnd, int how)
1815{
1816#ifndef ATTACH_THREADS
1817 SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0);
1818#else
1819 ShowWindow (hwnd , how);
1820#endif
1821}
1822
1823void
1824my_set_window_pos (HWND hwnd, HWND hwndAfter,
1825 int x, int y, int cx, int cy, int flags)
1826{
1827#ifndef ATTACH_THREADS
1828 Win32WindowPos pos;
1829 pos.hwndAfter = hwndAfter;
1830 pos.x = x;
1831 pos.y = y;
1832 pos.cx = cx;
1833 pos.cy = cy;
1834 pos.flags = flags;
1835 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
1836#else
1837 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
1838#endif
1839}
1840
ee78dc32
GV
1841void
1842my_destroy_window (f, hwnd)
1843 struct frame * f;
1844 HWND hwnd;
1845{
1846 SendMessage (FRAME_WIN32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
1847 (WPARAM) hwnd, 0);
1848}
1849
1850/* Open a new window to serve as a scroll bar, and return the
1851 scroll bar vector for it. */
1852static struct scroll_bar *
1853x_scroll_bar_create (window, top, left, width, height)
1854 struct window *window;
1855 int top, left, width, height;
1856{
1857 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1858 struct scroll_bar *bar
1859 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1860 HWND hwnd;
1861
1862 BLOCK_INPUT;
1863
1864 XSETWINDOW (bar->window, window);
1865 XSETINT (bar->top, top);
1866 XSETINT (bar->left, left);
1867 XSETINT (bar->width, width);
1868 XSETINT (bar->height, height);
1869 XSETINT (bar->start, 0);
1870 XSETINT (bar->end, 0);
1871 bar->dragging = Qnil;
1872
1873 /* Requires geometry to be set before call to create the real window */
1874
1875 hwnd = my_create_scrollbar (f, bar);
1876
1877 SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
1878 SetScrollPos (hwnd, SB_CTL, 0, TRUE);
1879
1880 SET_SCROLL_BAR_WIN32_WINDOW (bar, hwnd);
1881
1882 /* Add bar to its frame's list of scroll bars. */
1883 bar->next = FRAME_SCROLL_BARS (f);
1884 bar->prev = Qnil;
1885 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
1886 if (! NILP (bar->next))
1887 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1888
1889 UNBLOCK_INPUT;
1890
1891 return bar;
1892}
1893
1894/* Draw BAR's handle in the proper position.
1895 If the handle is already drawn from START to END, don't bother
1896 redrawing it, unless REBUILD is non-zero; in that case, always
1897 redraw it. (REBUILD is handy for drawing the handle after expose
1898 events.)
1899
1900 Normally, we want to constrain the start and end of the handle to
1901 fit inside its rectangle, but if the user is dragging the scroll bar
1902 handle, we want to let them drag it down all the way, so that the
1903 bar's top is as far down as it goes; otherwise, there's no way to
1904 move to the very end of the buffer. */
1905static void
1906x_scroll_bar_set_handle (bar, start, end, rebuild)
1907 struct scroll_bar *bar;
1908 int start, end;
1909 int rebuild;
1910{
1911 int dragging = ! NILP (bar->dragging);
1912 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
1913 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1914
1915 /* If the display is already accurate, do nothing. */
1916 if (! rebuild
1917 && start == XINT (bar->start)
1918 && end == XINT (bar->end))
1919 return;
1920
1921 BLOCK_INPUT;
1922
1923 /* Store the adjusted setting in the scroll bar. */
1924 XSETINT (bar->start, start);
1925 XSETINT (bar->end, end);
1926
2c28562d 1927 SetScrollPos (w, SB_CTL, start, TRUE);
ee78dc32
GV
1928
1929 UNBLOCK_INPUT;
1930}
1931
1932/* Move a scroll bar around on the screen, to accommodate changing
1933 window configurations. */
1934static void
1935x_scroll_bar_move (bar, top, left, width, height)
1936 struct scroll_bar *bar;
1937 int top, left, width, height;
1938{
1939 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
1940 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1941
1942 BLOCK_INPUT;
1943
1944 MoveWindow (w, left, top, width, height, TRUE);
1945 SetScrollRange (w, SB_CTL, 0, height, FALSE);
52cf03a1 1946 InvalidateRect (w, NULL, FALSE);
0b287713 1947 my_show_window (w, SW_NORMAL);
ee78dc32
GV
1948
1949 XSETINT (bar->left, left);
1950 XSETINT (bar->top, top);
1951 XSETINT (bar->width, width);
1952 XSETINT (bar->height, height);
1953
1954 UNBLOCK_INPUT;
1955}
1956
1957/* Destroy the window for BAR, and set its Emacs window's scroll bar
1958 to nil. */
1959static void
1960x_scroll_bar_remove (bar)
1961 struct scroll_bar *bar;
1962{
1963 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1964
1965 BLOCK_INPUT;
1966
1967 /* Destroy the window. */
1968 my_destroy_window (f, SCROLL_BAR_WIN32_WINDOW (bar));
1969
1970 /* Disassociate this scroll bar from its window. */
1971 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
1972
1973 UNBLOCK_INPUT;
1974}
1975
1976/* Set the handle of the vertical scroll bar for WINDOW to indicate
1977 that we are displaying PORTION characters out of a total of WHOLE
1978 characters, starting at POSITION. If WINDOW has no scroll bar,
1979 create one. */
1980static void
1981win32_set_vertical_scroll_bar (window, portion, whole, position)
1982 struct window *window;
1983 int portion, whole, position;
1984{
1985 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1986 int top = XINT (window->top);
1987 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
1988 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
1989
1990 /* Where should this scroll bar be, pixelwise? */
1991 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
1992 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
1993 int pixel_width
1994 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
1995 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
1996 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
1997 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
1998
1999 struct scroll_bar *bar;
2000
2001 /* Does the scroll bar exist yet? */
2002 if (NILP (window->vertical_scroll_bar))
2003 bar = x_scroll_bar_create (window,
2004 pixel_top, pixel_left,
2005 pixel_width, pixel_height);
2006 else
2007 {
2008 /* It may just need to be moved and resized. */
2009 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2010 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2011 }
2012
2013 /* Set the scroll bar's current state, unless we're currently being
2014 dragged. */
2015 if (NILP (bar->dragging))
2016 {
2017 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2018
2019 if (whole == 0)
2020 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2021 else
2022 {
2023 int start = (int) (((double) position * top_range) / whole);
2024 int end = (int) (((double) (position + portion) * top_range) / whole);
2025
2026 x_scroll_bar_set_handle (bar, start, end, 0);
2027 }
2028 }
2029
2030 XSETVECTOR (window->vertical_scroll_bar, bar);
2031}
2032
2033
2034/* The following three hooks are used when we're doing a thorough
2035 redisplay of the frame. We don't explicitly know which scroll bars
2036 are going to be deleted, because keeping track of when windows go
2037 away is a real pain - "Can you say set-window-configuration, boys
2038 and girls?" Instead, we just assert at the beginning of redisplay
2039 that *all* scroll bars are to be removed, and then save a scroll bar
2040 from the fiery pit when we actually redisplay its window. */
2041
2042/* Arrange for all scroll bars on FRAME to be removed at the next call
2043 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2044 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2045static void
2046win32_condemn_scroll_bars (frame)
2047 FRAME_PTR frame;
2048{
2049 /* The condemned list should be empty at this point; if it's not,
2050 then the rest of Emacs isn't using the condemn/redeem/judge
2051 protocol correctly. */
2052 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2053 abort ();
2054
2055 /* Move them all to the "condemned" list. */
2056 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2057 FRAME_SCROLL_BARS (frame) = Qnil;
2058}
2059
2060/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2061 Note that WINDOW isn't necessarily condemned at all. */
2062static void
2063win32_redeem_scroll_bar (window)
2064 struct window *window;
2065{
2066 struct scroll_bar *bar;
2067
2068 /* We can't redeem this window's scroll bar if it doesn't have one. */
2069 if (NILP (window->vertical_scroll_bar))
2070 abort ();
2071
2072 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2073
2074 /* Unlink it from the condemned list. */
2075 {
2076 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2077
2078 if (NILP (bar->prev))
2079 {
2080 /* If the prev pointer is nil, it must be the first in one of
2081 the lists. */
2082 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2083 /* It's not condemned. Everything's fine. */
2084 return;
2085 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2086 window->vertical_scroll_bar))
2087 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2088 else
2089 /* If its prev pointer is nil, it must be at the front of
2090 one or the other! */
2091 abort ();
2092 }
2093 else
2094 XSCROLL_BAR (bar->prev)->next = bar->next;
2095
2096 if (! NILP (bar->next))
2097 XSCROLL_BAR (bar->next)->prev = bar->prev;
2098
2099 bar->next = FRAME_SCROLL_BARS (f);
2100 bar->prev = Qnil;
2101 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2102 if (! NILP (bar->next))
2103 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2104 }
2105}
2106
2107/* Remove all scroll bars on FRAME that haven't been saved since the
2108 last call to `*condemn_scroll_bars_hook'. */
2109static void
2110win32_judge_scroll_bars (f)
2111 FRAME_PTR f;
2112{
2113 Lisp_Object bar, next;
2114
2115 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2116
2117 /* Clear out the condemned list now so we won't try to process any
2118 more events on the hapless scroll bars. */
2119 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2120
2121 for (; ! NILP (bar); bar = next)
2122 {
2123 struct scroll_bar *b = XSCROLL_BAR (bar);
2124
2125 x_scroll_bar_remove (b);
2126
2127 next = b->next;
2128 b->next = b->prev = Qnil;
2129 }
2130
2131 /* Now there should be no references to the condemned scroll bars,
2132 and they should get garbage-collected. */
2133}
2134
2135/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2136 is set to something other than no_event, it is enqueued.
2137
2138 This may be called from a signal handler, so we have to ignore GC
2139 mark bits. */
2c28562d 2140
52cf03a1 2141static int
ee78dc32
GV
2142x_scroll_bar_handle_click (bar, msg, emacs_event)
2143 struct scroll_bar *bar;
2144 Win32Msg *msg;
2145 struct input_event *emacs_event;
2146{
2147 if (! GC_WINDOWP (bar->window))
2148 abort ();
2149
52cf03a1 2150 emacs_event->kind = win32_scroll_bar_click;
ee78dc32 2151 emacs_event->code = 0;
52cf03a1
GV
2152 /* not really meaningful to distinguish up/down */
2153 emacs_event->modifiers = msg->dwModifiers;
ee78dc32
GV
2154 emacs_event->frame_or_window = bar->window;
2155 emacs_event->timestamp = msg->msg.time;
2156
2157 {
2158 int internal_height
2159 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2160 int top_range
2161 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2162 int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
2163
2164 switch (LOWORD (msg->msg.wParam))
2c28562d
RS
2165 {
2166 case SB_THUMBTRACK:
ee78dc32
GV
2167 emacs_event->part = scroll_bar_handle;
2168 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2169 y = HIWORD (msg->msg.wParam);
2170 break;
2c28562d 2171 case SB_LINEDOWN:
52cf03a1 2172 emacs_event->part = scroll_bar_down_arrow;
ee78dc32 2173 break;
2c28562d 2174 case SB_LINEUP:
52cf03a1 2175 emacs_event->part = scroll_bar_up_arrow;
ee78dc32 2176 break;
2c28562d 2177 case SB_PAGEUP:
ee78dc32
GV
2178 emacs_event->part = scroll_bar_above_handle;
2179 break;
2c28562d 2180 case SB_PAGEDOWN:
ee78dc32
GV
2181 emacs_event->part = scroll_bar_below_handle;
2182 break;
2c28562d 2183 case SB_TOP:
ee78dc32
GV
2184 emacs_event->part = scroll_bar_handle;
2185 y = 0;
2186 break;
2c28562d 2187 case SB_BOTTOM:
ee78dc32
GV
2188 emacs_event->part = scroll_bar_handle;
2189 y = top_range;
2190 break;
2c28562d 2191 case SB_THUMBPOSITION:
ee78dc32 2192 emacs_event->part = scroll_bar_handle;
ee78dc32 2193 break;
2c28562d
RS
2194 case SB_ENDSCROLL:
2195 default:
063b17e5 2196 SetScrollPos (SCROLL_BAR_WIN32_WINDOW (bar), SB_CTL, y, TRUE);
52cf03a1 2197 return FALSE;
2c28562d 2198 }
52cf03a1 2199
ee78dc32
GV
2200 XSETINT (emacs_event->x, y);
2201 XSETINT (emacs_event->y, top_range);
52cf03a1
GV
2202
2203 return TRUE;
ee78dc32
GV
2204 }
2205}
2206
2207/* Return information to the user about the current position of the mouse
2208 on the scroll bar. */
2209static void
2210x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
2211 FRAME_PTR *fp;
2212 Lisp_Object *bar_window;
2213 enum scroll_bar_part *part;
2214 Lisp_Object *x, *y;
2215 unsigned long *time;
2216{
2217 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2218 Window w = SCROLL_BAR_WIN32_WINDOW (bar);
2219 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2220 int pos;
2221
2222 BLOCK_INPUT;
2223
2224 *fp = f;
2225 *bar_window = bar->window;
2226
2227 pos = GetScrollPos (w, SB_CTL);
2228
2229 switch (LOWORD (last_mouse_scroll_bar_pos))
2230 {
2231 case SB_THUMBPOSITION:
2232 case SB_THUMBTRACK:
2233 *part = scroll_bar_handle;
2234 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2235 pos = HIWORD (last_mouse_scroll_bar_pos);
2236 break;
2237 case SB_LINEDOWN:
2238 *part = scroll_bar_handle;
2239 pos++;
2240 break;
2241 default:
2242 *part = scroll_bar_handle;
2243 break;
2244 }
2245
2246 XSETINT(*x, pos);
2247 XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
2248
2249 f->mouse_moved = 0;
2250 last_mouse_scroll_bar = Qnil;
2251
2252 *time = last_mouse_movement_time;
2253
2254 UNBLOCK_INPUT;
2255}
2256
2257/* The screen has been cleared so we may have changed foreground or
2258 background colors, and the scroll bars may need to be redrawn.
2259 Clear out the scroll bars, and ask for expose events, so we can
2260 redraw them. */
2261
2262x_scroll_bar_clear (f)
2263 FRAME_PTR f;
2264{
ee78dc32
GV
2265 Lisp_Object bar;
2266
2267 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2268 bar = XSCROLL_BAR (bar)->next)
52cf03a1
GV
2269 {
2270 HWND window = SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar));
2271 HDC hdc = GetDC (window);
2272 RECT rect;
2273
0b287713 2274 my_show_window (window, SW_HIDE);
52cf03a1
GV
2275 GetClientRect (window, &rect);
2276 select_palette (f, hdc);
2277 win32_clear_rect (f, hdc, &rect);
2278 deselect_palette (f, hdc);
2279 }
2280}
2281
2282show_scroll_bars (f, how)
2283 FRAME_PTR f;
2284 int how;
2285{
2286 Lisp_Object bar;
2287
2288 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2289 bar = XSCROLL_BAR (bar)->next)
2290 {
2291 HWND window = SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar));
2292 my_show_window (window, how);
2293 }
ee78dc32
GV
2294}
2295
2296\f
2297/* The main Win32 event-reading loop - w32_read_socket. */
2298
2299/* Timestamp of enter window event. This is only used by w32_read_socket,
2300 but we have to put it out here, since static variables within functions
2301 sometimes don't work. */
2302static Time enter_timestamp;
2303
2304/* Record the last 100 characters stored
2305 to help debug the loss-of-chars-during-GC problem. */
2306int temp_index;
2307short temp_buffer[100];
2308
afd153f0
GV
2309extern int key_event (KEY_EVENT_RECORD *, struct input_event *);
2310
2311/* Map a Win32 WM_CHAR message into a KEY_EVENT_RECORD so that
2312 we can use the same routines to handle input in both console
2313 and window modes. */
2314
2315static void
2316convert_to_key_event (Win32Msg *msgp, KEY_EVENT_RECORD *eventp)
2317{
2318 eventp->bKeyDown = TRUE;
2319 eventp->wRepeatCount = 1;
2320 eventp->wVirtualKeyCode = msgp->msg.wParam;
2321 eventp->wVirtualScanCode = (msgp->msg.lParam & 0xFF0000) >> 16;
2322 eventp->uChar.AsciiChar = 0;
2323 eventp->dwControlKeyState = msgp->dwModifiers;
2324}
2325
2326/* Return nonzero if the virtual key is a dead key. */
2327
2328static int
2329is_dead_key (int wparam)
2330{
2331 unsigned int code = MapVirtualKey (wparam, 2);
2332
2333 /* Win95 returns 0x8000, NT returns 0x80000000. */
2334 if ((code & 0x8000) || (code & 0x80000000))
2335 return 1;
2336 else
2337 return 0;
2338}
2339
ee78dc32
GV
2340/* Read events coming from the Win32 shell.
2341 This routine is called by the SIGIO handler.
2342 We return as soon as there are no more events to be read.
2343
2344 Events representing keys are stored in buffer BUFP,
2345 which can hold up to NUMCHARS characters.
2346 We return the number of characters stored into the buffer,
2347 thus pretending to be `read'.
2348
2349 WAITP is nonzero if we should block until input arrives.
2350 EXPECTED is nonzero if the caller knows input is available.
2351
2352 Some of these messages are reposted back to the message queue since the
2353 system calls the winproc directly in a context where we cannot return the
2354 data nor can we guarantee the state we are in. So if we dispatch them
2355 we will get into an infinite loop. To prevent this from ever happening we
2356 will set a variable to indicate we are in the read_socket call and indicate
2357 which message we are processing since the winproc gets called recursively with different
2358 messages by the system.
2359*/
2360
2361int
2362w32_read_socket (sd, bufp, numchars, waitp, expected)
2363 register int sd;
2364 register struct input_event *bufp;
2365 register int numchars;
2366 int waitp;
2367 int expected;
2368{
2369 int count = 0;
2370 int nbytes = 0;
2371 int items_pending; /* How many items are in the X queue. */
2372 Win32Msg msg;
2373 struct frame *f;
2374 int event_found = 0;
2375 int prefix;
2376 Lisp_Object part;
2377 struct win32_display_info *dpyinfo = &one_win32_display_info;
2378
2379 if (interrupt_input_blocked)
2380 {
2381 interrupt_input_pending = 1;
2382 return -1;
2383 }
2384
2385 interrupt_input_pending = 0;
2386 BLOCK_INPUT;
2387
2388 /* So people can tell when we have read the available input. */
2389 input_signal_count++;
2390
2391 if (numchars <= 0)
2392 abort (); /* Don't think this happens. */
2393
52cf03a1 2394 while (get_next_msg (&msg, FALSE))
ee78dc32
GV
2395 {
2396 switch (msg.msg.message)
2397 {
ee78dc32
GV
2398 case WM_PAINT:
2399 {
2400 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2401
2402 if (f)
2403 {
2404 if (f->async_visible == 0)
2405 {
2406 f->async_visible = 1;
2407 f->async_iconified = 0;
2408 SET_FRAME_GARBAGED (f);
2409 }
2410 else
2411 {
97e6de38
KH
2412 /* Erase background again for safety. */
2413 win32_clear_rect (f, NULL, &msg.rect);
ee78dc32
GV
2414 dumprectangle (f,
2415 msg.rect.left,
2416 msg.rect.top,
2417 msg.rect.right-msg.rect.left+1,
2418 msg.rect.bottom-msg.rect.top+1);
ee78dc32
GV
2419 }
2420 }
2421 }
52cf03a1 2422 break;
ee78dc32
GV
2423 case WM_KEYDOWN:
2424 case WM_SYSKEYDOWN:
2425 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2426
2427 if (f && !f->iconified)
2428 {
2429 if (temp_index == sizeof temp_buffer / sizeof (short))
2430 temp_index = 0;
2431 temp_buffer[temp_index++] = msg.msg.wParam;
2432 bufp->kind = non_ascii_keystroke;
2433 bufp->code = msg.msg.wParam;
52cf03a1 2434 bufp->modifiers = win32_kbd_mods_to_emacs (msg.dwModifiers);
ee78dc32
GV
2435 XSETFRAME (bufp->frame_or_window, f);
2436 bufp->timestamp = msg.msg.time;
2437 bufp++;
2438 numchars--;
2439 count++;
2440 }
2441 break;
2442 case WM_SYSCHAR:
2443 case WM_CHAR:
2444 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2445
2446 if (f && !f->iconified)
2447 {
2448 if (numchars > 1)
2449 {
afd153f0
GV
2450 int add;
2451 KEY_EVENT_RECORD key, *keyp = &key;
2452
ee78dc32
GV
2453 if (temp_index == sizeof temp_buffer / sizeof (short))
2454 temp_index = 0;
afd153f0
GV
2455
2456 convert_to_key_event (&msg, keyp);
2457 add = key_event (keyp, bufp);
a92989c3 2458 XSETFRAME (bufp->frame_or_window, f);
afd153f0
GV
2459 if (add == -1)
2460 {
2461 /* The key pressed generated two characters, most likely
2462 an accent character and a key that could not be
2463 combined with it. Prepend the message on the queue
2464 again to process the second character (which is
2465 being held internally in key_event), and process
2466 the first character now. */
2467 prepend_msg (&msg);
2468 add = 1;
2469 }
2470
7e797bdb
RS
2471 /* Throw dead keys away. However, be sure not to
2472 throw away the dead key if it was produced using
2473 AltGr and there is a valid AltGr scan code for
2474 this key. */
2475 if (is_dead_key (msg.msg.wParam)
ded385e2 2476 && !((VkKeyScan ((char) bufp->code) & 0xff00) == 0x600))
afd153f0
GV
2477 break;
2478
2479 bufp += add;
2480 numchars -= add;
2481 count += add;
ee78dc32
GV
2482 }
2483 else
2484 {
2485 abort ();
2486 }
2487 }
2488 break;
2489 case WM_MOUSEMOVE:
2490 if (dpyinfo->grabbed && last_mouse_frame
2491 && FRAME_LIVE_P (last_mouse_frame))
2492 f = last_mouse_frame;
2493 else
2494 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2495
2496 if (f)
2497 note_mouse_movement (f, &msg.msg);
2498 else
2499 clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
2500
2501 break;
2502 case WM_LBUTTONDOWN:
2503 case WM_LBUTTONUP:
2504 case WM_MBUTTONDOWN:
2505 case WM_MBUTTONUP:
2506 case WM_RBUTTONDOWN:
2507 case WM_RBUTTONUP:
2508 {
2509 int button;
2510 int up;
2511
2512 if (dpyinfo->grabbed && last_mouse_frame
2513 && FRAME_LIVE_P (last_mouse_frame))
2514 f = last_mouse_frame;
2515 else
2516 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2517
2518 if (f)
2519 {
2520 if ((!dpyinfo->win32_focus_frame || f == dpyinfo->win32_focus_frame)
2521 && (numchars >= 1))
2522 {
2523 construct_mouse_click (bufp, &msg, f);
2524 bufp++;
2525 count++;
2526 numchars--;
2527 }
2528 }
2529
2530 parse_button (msg.msg.message, &button, &up);
2531
2532 if (up)
2533 {
2534 dpyinfo->grabbed &= ~ (1 << button);
2535 }
2536 else
2537 {
2538 dpyinfo->grabbed |= (1 << button);
2539 last_mouse_frame = f;
2540 }
2541 }
2542
2543 break;
2544 case WM_VSCROLL:
2545 {
2546 struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam);
2547
2548 if (bar && numchars >= 1)
2549 {
52cf03a1
GV
2550 if (x_scroll_bar_handle_click (bar, &msg, bufp))
2551 {
2552 bufp++;
2553 count++;
2554 numchars--;
2555 }
ee78dc32
GV
2556 }
2557 }
2558
2559 break;
2560 case WM_MOVE:
2561 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2562
2563 if (f && !f->async_iconified)
2564 {
2565 f->output_data.win32->left_pos = LOWORD (msg.msg.lParam);
2566 f->output_data.win32->top_pos = HIWORD (msg.msg.lParam);
2567 }
2568
2569 break;
2570 case WM_SIZE:
2571 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2572
2573 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2574 {
2575 RECT rect;
2576 int rows;
2577 int columns;
2578 int width;
2579 int height;
2580
97c23857 2581 GetClientRect(msg.msg.hwnd, &rect);
ee78dc32
GV
2582
2583 height = rect.bottom - rect.top + 1;
2584 width = rect.right - rect.left + 1;
2585
2586 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2587 columns = PIXEL_TO_CHAR_WIDTH (f, width);
2588
2589 /* Even if the number of character rows and columns has
2590 not changed, the font size may have changed, so we need
2591 to check the pixel dimensions as well. */
2592
2593 if (columns != f->width
2594 || rows != f->height
2595 || width != f->output_data.win32->pixel_width
2596 || height != f->output_data.win32->pixel_height)
2597 {
2598 /* I had set this to 0, 0 - I am not sure why?? */
2599
2600 change_frame_size (f, rows, columns, 0, 1);
2601 SET_FRAME_GARBAGED (f);
2602
2603 f->output_data.win32->pixel_width = width;
2604 f->output_data.win32->pixel_height = height;
2605 f->output_data.win32->win_gravity = NorthWestGravity;
2606 }
2607 }
2608
2609 break;
2610 case WM_SETFOCUS:
2611 case WM_KILLFOCUS:
2612 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2613
2614 if (msg.msg.message == WM_SETFOCUS)
2615 {
2616 x_new_focus_frame (dpyinfo, f);
2617 }
2618 else if (f == dpyinfo->win32_focus_frame)
2619 x_new_focus_frame (dpyinfo, 0);
2620
2621 break;
2622 case WM_SYSCOMMAND:
ce2d626f 2623 switch (msg.msg.wParam & 0xfff0) /* Lower 4 bits used by Windows. */
ee78dc32
GV
2624 {
2625 case SC_CLOSE:
2626 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2627
2628 if (f)
2629 {
2630 if (numchars == 0)
2631 abort ();
2632
2633 bufp->kind = delete_window_event;
2634 XSETFRAME (bufp->frame_or_window, f);
2635 bufp++;
2636 count++;
2637 numchars--;
2638 }
2639
2640 break;
2641 case SC_MINIMIZE:
2642 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2643
2644 if (f)
2645 {
2646 f->async_visible = 1;
2647 f->async_iconified = 1;
2648
2649 bufp->kind = iconify_event;
2650 XSETFRAME (bufp->frame_or_window, f);
2651 bufp++;
2652 count++;
2653 numchars--;
2654 }
2655
2656 break;
2657 case SC_MAXIMIZE:
2658 case SC_RESTORE:
2659 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2660
2661 if (f)
2662 {
2663 f->async_visible = 1;
2664 f->async_iconified = 0;
2665
2666 /* wait_reading_process_input will notice this and update
2667 the frame's display structures. */
2668 SET_FRAME_GARBAGED (f);
2669
2670 if (f->iconified)
2671 {
2672 bufp->kind = deiconify_event;
2673 XSETFRAME (bufp->frame_or_window, f);
2674 bufp++;
2675 count++;
2676 numchars--;
2677 }
2678 else
2679 /* Force a redisplay sooner or later
2680 to update the frame titles
2681 in case this is the second frame. */
2682 record_asynch_buffer_change ();
2683 }
2684
2685 break;
2686 }
2687
2688 break;
2689 case WM_CLOSE:
2690 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2691
2692 if (f)
2693 {
2694 if (numchars == 0)
2695 abort ();
2696
2697 bufp->kind = delete_window_event;
2698 XSETFRAME (bufp->frame_or_window, f);
2699 bufp++;
2700 count++;
2701 numchars--;
2702 }
2703
2704 break;
2705 case WM_COMMAND:
2706 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2707
2708 if (f)
2709 {
2710 if (msg.msg.lParam == 0)
2711 {
2712 /* Came from window menu */
2713
2714 extern Lisp_Object get_frame_menubar_event ();
2715 Lisp_Object event = get_frame_menubar_event (f, msg.msg.wParam);
2716 struct input_event buf;
2717 Lisp_Object frame;
2718
2719 XSETFRAME (frame, f);
2720 buf.kind = menu_bar_event;
2721
2722 /* Store initial menu bar event */
2723
2724 if (!NILP (event))
2725 {
2726 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
2727 kbd_buffer_store_event (&buf);
2728 }
2729
2730 /* Enqueue the events */
2731
2732 while (!NILP (event))
2733 {
2734 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
2735 kbd_buffer_store_event (&buf);
2736 event = XCONS (event)->cdr;
2737 }
2738 }
2739 else
2740 {
2741 /* Came from popup menu */
2742 }
2743 }
2744 break;
2745 }
2746 }
2747
2748 /* If the focus was just given to an autoraising frame,
2749 raise it now. */
2750 /* ??? This ought to be able to handle more than one such frame. */
2751 if (pending_autoraise_frame)
2752 {
2753 x_raise_frame (pending_autoraise_frame);
2754 pending_autoraise_frame = 0;
2755 }
2756
2757 UNBLOCK_INPUT;
2758 return count;
2759}
2760\f
2761/* Drawing the cursor. */
2762
2763
2764/* Draw a hollow box cursor. Don't change the inside of the box. */
2765
2766static void
2767x_draw_box (f)
2768 struct frame *f;
2769{
2770 RECT rect;
2771 HBRUSH hb;
2772 HDC hdc;
2773
52cf03a1 2774 hdc = get_frame_dc (f);
ee78dc32
GV
2775
2776 hb = CreateSolidBrush (f->output_data.win32->cursor_pixel);
2777
2778 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
2779 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
52cf03a1
GV
2780 rect.right = rect.left + FONT_WIDTH (f->output_data.win32->font);
2781 rect.bottom = rect.top + f->output_data.win32->line_height;
2782
ee78dc32 2783 FrameRect (hdc, &rect, hb);
ee78dc32 2784 DeleteObject (hb);
52cf03a1
GV
2785
2786 release_frame_dc (f, hdc);
ee78dc32
GV
2787}
2788
2789/* Clear the cursor of frame F to background color,
2790 and mark the cursor as not shown.
2791 This is used when the text where the cursor is
2792 is about to be rewritten. */
2793
2794static void
2795clear_cursor (f)
2796 struct frame *f;
2797{
2798 if (! FRAME_VISIBLE_P (f)
2799 || f->phys_cursor_x < 0)
2800 return;
2801
2802 x_display_cursor (f, 0);
2803 f->phys_cursor_x = -1;
2804}
2805
2806/* Redraw the glyph at ROW, COLUMN on frame F, in the style
2807 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2808 glyph drawn. */
2809
2810static void
2811x_draw_single_glyph (f, row, column, glyph, highlight)
2812 struct frame *f;
2813 int row, column;
2814 GLYPH glyph;
2815 int highlight;
2816{
2817 dumpglyphs (f,
2818 CHAR_TO_PIXEL_COL (f, column),
2819 CHAR_TO_PIXEL_ROW (f, row),
2820 &glyph, 1, highlight, 0);
2821}
2822
2823static void
2824x_display_bar_cursor (f, on)
2825 struct frame *f;
2826 int on;
2827{
2828 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2829
2830 /* This is pointless on invisible frames, and dangerous on garbaged
2831 frames; in the latter case, the frame may be in the midst of
2832 changing its size, and curs_x and curs_y may be off the frame. */
2833 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2834 return;
2835
2836 if (! on && f->phys_cursor_x < 0)
2837 return;
2838
2839 /* If we're not updating, then we want to use the current frame's
2840 cursor position, not our local idea of where the cursor ought to be. */
2841 if (f != updating_frame)
2842 {
2843 curs_x = FRAME_CURSOR_X (f);
2844 curs_y = FRAME_CURSOR_Y (f);
2845 }
2846
2847 /* If there is anything wrong with the current cursor state, remove it. */
2848 if (f->phys_cursor_x >= 0
2849 && (!on
2850 || f->phys_cursor_x != curs_x
2851 || f->phys_cursor_y != curs_y
2852 || f->output_data.win32->current_cursor != bar_cursor))
2853 {
2854 /* Erase the cursor by redrawing the character underneath it. */
2855 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2856 f->phys_cursor_glyph,
2857 current_glyphs->highlight[f->phys_cursor_y]);
2858 f->phys_cursor_x = -1;
2859 }
2860
2861 /* If we now need a cursor in the new place or in the new form, do it so. */
2862 if (on
2863 && (f->phys_cursor_x < 0
2864 || (f->output_data.win32->current_cursor != bar_cursor)))
2865 {
2866 f->phys_cursor_glyph
2867 = ((current_glyphs->enable[curs_y]
2868 && curs_x < current_glyphs->used[curs_y])
2869 ? current_glyphs->glyphs[curs_y][curs_x]
2870 : SPACEGLYPH);
2871 win32_fill_area (f, NULL, f->output_data.win32->cursor_pixel,
2872 CHAR_TO_PIXEL_COL (f, curs_x),
2873 CHAR_TO_PIXEL_ROW (f, curs_y),
2874 max (f->output_data.win32->cursor_width, 1),
2875 f->output_data.win32->line_height);
2876
2877 f->phys_cursor_x = curs_x;
2878 f->phys_cursor_y = curs_y;
2879
2880 f->output_data.win32->current_cursor = bar_cursor;
2881 }
2882}
2883
2884
2885/* Turn the displayed cursor of frame F on or off according to ON.
2886 If ON is nonzero, where to put the cursor is specified
2887 by F->cursor_x and F->cursor_y. */
2888
2889static void
2890x_display_box_cursor (f, on)
2891 struct frame *f;
2892 int on;
2893{
2894 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2895
2896 /* This is pointless on invisible frames, and dangerous on garbaged
2897 frames; in the latter case, the frame may be in the midst of
2898 changing its size, and curs_x and curs_y may be off the frame. */
2899 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2900 return;
2901
2902 /* If cursor is off and we want it off, return quickly. */
2903 if (!on && f->phys_cursor_x < 0)
2904 return;
2905
2906 /* If we're not updating, then we want to use the current frame's
2907 cursor position, not our local idea of where the cursor ought to be. */
2908 if (f != updating_frame)
2909 {
2910 curs_x = FRAME_CURSOR_X (f);
2911 curs_y = FRAME_CURSOR_Y (f);
2912 }
2913
2914 /* If cursor is currently being shown and we don't want it to be
2915 or it is in the wrong place,
2916 or we want a hollow box and it's not so, (pout!)
2917 erase it. */
2918 if (f->phys_cursor_x >= 0
2919 && (!on
2920 || f->phys_cursor_x != curs_x
2921 || f->phys_cursor_y != curs_y
2922 || (f->output_data.win32->current_cursor != hollow_box_cursor
2923 && (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame))))
2924 {
2925 int mouse_face_here = 0;
2926 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
2927
2928 /* If the cursor is in the mouse face area, redisplay that when
2929 we clear the cursor. */
2930 if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame
2931 &&
2932 (f->phys_cursor_y > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
2933 || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
2934 && f->phys_cursor_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col))
2935 &&
2936 (f->phys_cursor_y < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
2937 || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
2938 && f->phys_cursor_x < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col))
2939 /* Don't redraw the cursor's spot in mouse face
2940 if it is at the end of a line (on a newline).
2941 The cursor appears there, but mouse highlighting does not. */
2942 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
2943 mouse_face_here = 1;
2944
2945 /* If the font is not as tall as a whole line,
2946 we must explicitly clear the line's whole height. */
2947 if (FONT_HEIGHT (f->output_data.win32->font) != f->output_data.win32->line_height)
2948 win32_clear_area (f, NULL,
2949 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
2950 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
2951 FONT_WIDTH (f->output_data.win32->font),
2952 f->output_data.win32->line_height);
2953 /* Erase the cursor by redrawing the character underneath it. */
2954 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2955 f->phys_cursor_glyph,
2956 (mouse_face_here
2957 ? 3
2958 : current_glyphs->highlight[f->phys_cursor_y]));
2959 f->phys_cursor_x = -1;
2960 }
2961
2962 /* If we want to show a cursor,
2963 or we want a box cursor and it's not so,
2964 write it in the right place. */
2965 if (on
2966 && (f->phys_cursor_x < 0
2967 || (f->output_data.win32->current_cursor != filled_box_cursor
2968 && f == FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)))
2969 {
2970 f->phys_cursor_glyph
2971 = ((current_glyphs->enable[curs_y]
2972 && curs_x < current_glyphs->used[curs_y])
2973 ? current_glyphs->glyphs[curs_y][curs_x]
2974 : SPACEGLYPH);
2975 if (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)
2976 {
2977 x_draw_box (f);
2978 f->output_data.win32->current_cursor = hollow_box_cursor;
2979 }
2980 else
2981 {
2982 x_draw_single_glyph (f, curs_y, curs_x,
2983 f->phys_cursor_glyph, 2);
2984 f->output_data.win32->current_cursor = filled_box_cursor;
2985 }
2986
2987 f->phys_cursor_x = curs_x;
2988 f->phys_cursor_y = curs_y;
2989 }
2990}
2991
2992x_display_cursor (f, on)
2993 struct frame *f;
2994 int on;
2995{
2996 BLOCK_INPUT;
2997
2998 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
2999 x_display_box_cursor (f, on);
3000 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3001 x_display_bar_cursor (f, on);
3002 else
3003 /* Those are the only two we have implemented! */
3004 abort ();
3005
3006 UNBLOCK_INPUT;
3007}
3008\f
3009/* Changing the font of the frame. */
3010
3011/* Give frame F the font named FONTNAME as its default font, and
3012 return the full name of that font. FONTNAME may be a wildcard
3013 pattern; in that case, we choose some font that fits the pattern.
3014 The return value shows which font we chose. */
3015
3016Lisp_Object
3017x_new_font (f, fontname)
3018 struct frame *f;
3019 register char *fontname;
3020{
3021 int already_loaded;
3022 int n_matching_fonts;
3023 XFontStruct *font_info;
3024 char new_font_name[101];
3025
3026 /* Get a font which matches this name */
3027 {
3028 LOGFONT lf;
3029
3030 if (!x_to_win32_font(fontname, &lf)
3031 || !win32_to_x_font(&lf, new_font_name, 100))
3032 {
3033 return Qnil;
3034 }
3035 }
3036
3037 /* See if we've already loaded a matching font. */
3038 already_loaded = -1;
3039
3040 {
3041 int i;
3042
3043 for (i = 0; i < FRAME_WIN32_DISPLAY_INFO (f)->n_fonts; i++)
3044 if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
3045 {
3046 already_loaded = i;
3047 fontname = FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name;
3048 break;
3049 }
3050 }
3051
3052 /* If we have, just return it from the table. */
3053 if (already_loaded >= 0)
3054 f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[already_loaded].font;
3055 /* Otherwise, load the font and add it to the table. */
3056 else
3057 {
3058 XFontStruct *font;
3059 int n_fonts;
3060
3061 font = win32_load_font(FRAME_WIN32_DISPLAY_INFO (f), fontname);
3062
3063 if (! font)
3064 {
3065 return Qnil;
3066 }
3067
3068 /* Do we need to create the table? */
3069 if (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size == 0)
3070 {
3071 FRAME_WIN32_DISPLAY_INFO (f)->font_table_size = 16;
3072 FRAME_WIN32_DISPLAY_INFO (f)->font_table
3073 = (struct font_info *) xmalloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
3074 * sizeof (struct font_info));
3075 }
3076 /* Do we need to grow the table? */
3077 else if (FRAME_WIN32_DISPLAY_INFO (f)->n_fonts
3078 >= FRAME_WIN32_DISPLAY_INFO (f)->font_table_size)
3079 {
3080 FRAME_WIN32_DISPLAY_INFO (f)->font_table_size *= 2;
3081 FRAME_WIN32_DISPLAY_INFO (f)->font_table
3082 = (struct font_info *) xrealloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table,
3083 (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
3084 * sizeof (struct font_info)));
3085 }
3086
3087 n_fonts = FRAME_WIN32_DISPLAY_INFO (f)->n_fonts;
3088 FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
3089 bcopy (fontname, FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
3090 f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
3091 FRAME_WIN32_DISPLAY_INFO (f)->n_fonts++;
3092 }
3093
3094 /* Compute the scroll bar width in character columns. */
3095 if (f->scroll_bar_pixel_width > 0)
3096 {
3097 int wid = FONT_WIDTH (f->output_data.win32->font);
3098 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
3099 }
3100 else
3101 f->scroll_bar_cols = 2;
3102
3103 /* Now make the frame display the given font. */
3104 if (FRAME_WIN32_WINDOW (f) != 0)
3105 {
3106 frame_update_line_height (f);
3107 x_set_window_size (f, 0, f->width, f->height);
3108 }
3109 else
3110 /* If we are setting a new frame's font for the first time,
3111 there are no faces yet, so this font's height is the line height. */
3112 f->output_data.win32->line_height = FONT_HEIGHT (f->output_data.win32->font);
3113
3114 {
3115 Lisp_Object lispy_name;
3116
3117 lispy_name = build_string (fontname);
3118
3119 return lispy_name;
3120 }
3121}
3122\f
3123x_calc_absolute_position (f)
3124 struct frame *f;
3125{
3126 Window win, child;
3127 POINT pt;
3128 int flags = f->output_data.win32->size_hint_flags;
3129
3130 pt.x = pt.y = 0;
3131
3132 /* Find the position of the outside upper-left corner of
3133 the inner window, with respect to the outer window. */
3134 if (f->output_data.win32->parent_desc != FRAME_WIN32_DISPLAY_INFO (f)->root_window)
3135 {
3136 BLOCK_INPUT;
3137 MapWindowPoints (FRAME_WIN32_WINDOW (f),
3138 f->output_data.win32->parent_desc,
3139 &pt, 1);
3140 UNBLOCK_INPUT;
3141 }
3142
3143 {
3144 RECT rt;
3145 rt.left = rt.right = rt.top = rt.bottom = 0;
3146
3147 BLOCK_INPUT;
97c23857
GV
3148 AdjustWindowRect(&rt, f->output_data.win32->dwStyle,
3149 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
3150 UNBLOCK_INPUT;
3151
3152 pt.x += (rt.right - rt.left);
3153 pt.y += (rt.bottom - rt.top);
3154 }
3155
3156 /* Treat negative positions as relative to the leftmost bottommost
3157 position that fits on the screen. */
3158 if (flags & XNegative)
3159 f->output_data.win32->left_pos = (FRAME_WIN32_DISPLAY_INFO (f)->width
3160 - 2 * f->output_data.win32->border_width - pt.x
3161 - PIXEL_WIDTH (f)
3162 + f->output_data.win32->left_pos);
3163
3164 if (flags & YNegative)
3165 f->output_data.win32->top_pos = (FRAME_WIN32_DISPLAY_INFO (f)->height
3166 - 2 * f->output_data.win32->border_width - pt.y
3167 - PIXEL_HEIGHT (f)
3168 + f->output_data.win32->top_pos);
3169 /* The left_pos and top_pos
3170 are now relative to the top and left screen edges,
3171 so the flags should correspond. */
3172 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
3173}
3174
3175/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3176 to really change the position, and 0 when calling from
3177 x_make_frame_visible (in that case, XOFF and YOFF are the current
3178 position values). It is -1 when calling from x_set_frame_parameters,
3179 which means, do adjust for borders but don't change the gravity. */
3180
3181x_set_offset (f, xoff, yoff, change_gravity)
3182 struct frame *f;
3183 register int xoff, yoff;
3184 int change_gravity;
3185{
3186 int modified_top, modified_left;
3187
3188 if (change_gravity > 0)
3189 {
3190 f->output_data.win32->top_pos = yoff;
3191 f->output_data.win32->left_pos = xoff;
3192 f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
3193 if (xoff < 0)
3194 f->output_data.win32->size_hint_flags |= XNegative;
3195 if (yoff < 0)
3196 f->output_data.win32->size_hint_flags |= YNegative;
3197 f->output_data.win32->win_gravity = NorthWestGravity;
3198 }
3199 x_calc_absolute_position (f);
3200
3201 BLOCK_INPUT;
3202 x_wm_set_size_hint (f, (long) 0, 0);
3203
3204 /* It is a mystery why we need to add the border_width here
3205 when the frame is already visible, but experiment says we do. */
3206 modified_left = f->output_data.win32->left_pos;
3207 modified_top = f->output_data.win32->top_pos;
3208 if (change_gravity != 0)
3209 {
3210 modified_left += f->output_data.win32->border_width;
3211 modified_top += f->output_data.win32->border_width;
3212 }
3213
52cf03a1
GV
3214 my_set_window_pos (FRAME_WIN32_WINDOW (f),
3215 NULL,
3216 modified_left, modified_top,
3217 0,0,
3218 SWP_NOZORDER | SWP_NOSIZE);
ee78dc32
GV
3219 UNBLOCK_INPUT;
3220}
3221
3222/* Call this to change the size of frame F's x-window.
3223 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3224 for this size change and subsequent size changes.
3225 Otherwise we leave the window gravity unchanged. */
3226
3227x_set_window_size (f, change_gravity, cols, rows)
3228 struct frame *f;
3229 int change_gravity;
3230 int cols, rows;
3231{
3232 int pixelwidth, pixelheight;
3233
3234 BLOCK_INPUT;
3235
3236 check_frame_size (f, &rows, &cols);
3237 f->output_data.win32->vertical_scroll_bar_extra
3238 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3239 ? 0
3240 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3241 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3242 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
3243 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3244 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3245
3246 f->output_data.win32->win_gravity = NorthWestGravity;
3247 x_wm_set_size_hint (f, (long) 0, 0);
3248
3249 {
3250 RECT rect;
3251
3252 rect.left = rect.top = 0;
3253 rect.right = pixelwidth;
3254 rect.bottom = pixelheight;
3255
97c23857
GV
3256 AdjustWindowRect(&rect, f->output_data.win32->dwStyle,
3257 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
3258
3259 /* All windows have an extra pixel */
3260
52cf03a1
GV
3261 my_set_window_pos (FRAME_WIN32_WINDOW (f),
3262 NULL,
3263 0, 0,
3264 rect.right - rect.left + 1,
3265 rect.bottom - rect.top + 1,
3266 SWP_NOZORDER | SWP_NOMOVE);
ee78dc32
GV
3267 }
3268
3269 /* Now, strictly speaking, we can't be sure that this is accurate,
3270 but the window manager will get around to dealing with the size
3271 change request eventually, and we'll hear how it went when the
3272 ConfigureNotify event gets here.
3273
3274 We could just not bother storing any of this information here,
3275 and let the ConfigureNotify event set everything up, but that
3276 might be kind of confusing to the lisp code, since size changes
3277 wouldn't be reported in the frame parameters until some random
3278 point in the future when the ConfigureNotify event arrives. */
3279 change_frame_size (f, rows, cols, 0, 0);
3280 PIXEL_WIDTH (f) = pixelwidth;
3281 PIXEL_HEIGHT (f) = pixelheight;
3282
3283 /* If cursor was outside the new size, mark it as off. */
3284 if (f->phys_cursor_y >= rows
3285 || f->phys_cursor_x >= cols)
3286 {
3287 f->phys_cursor_x = -1;
3288 f->phys_cursor_y = -1;
3289 }
3290
3291 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3292 receive in the ConfigureNotify event; if we get what we asked
3293 for, then the event won't cause the screen to become garbaged, so
3294 we have to make sure to do it here. */
3295 SET_FRAME_GARBAGED (f);
3296
3297 UNBLOCK_INPUT;
3298}
3299\f
3300/* Mouse warping. */
3301
1bcd16f2
MB
3302void
3303x_set_mouse_pixel_position (f, pix_x, pix_y)
3304 struct frame *f;
3305 int pix_x, pix_y;
3306{
3307 BLOCK_INPUT;
3308
3309 pix_x += f->output_data.win32->left_pos;
3310 pix_y += f->output_data.win32->top_pos;
3311
3312 SetCursorPos (pix_x, pix_y);
3313
3314 UNBLOCK_INPUT;
3315}
3316
ee78dc32
GV
3317void
3318x_set_mouse_position (f, x, y)
3319 struct frame *f;
3320 int x, y;
3321{
3322 int pix_x, pix_y;
3323
3324 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.win32->font) / 2;
3325 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.win32->line_height / 2;
3326
3327 if (pix_x < 0) pix_x = 0;
3328 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3329
3330 if (pix_y < 0) pix_y = 0;
3331 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3332
1bcd16f2 3333 x_set_mouse_pixel_position (f, pix_x, pix_y);
ee78dc32
GV
3334}
3335\f
3336/* focus shifting, raising and lowering. */
3337
3338x_focus_on_frame (f)
3339 struct frame *f;
3340{
3341}
3342
3343x_unfocus_frame (f)
3344 struct frame *f;
3345{
3346}
3347
3348/* Raise frame F. */
3349
3350x_raise_frame (f)
3351 struct frame *f;
3352{
52cf03a1 3353// if (f->async_visible)
ee78dc32
GV
3354 {
3355 BLOCK_INPUT;
52cf03a1
GV
3356 my_set_window_pos (FRAME_WIN32_WINDOW (f),
3357 HWND_TOP,
3358 0, 0, 0, 0,
3359 SWP_NOSIZE | SWP_NOMOVE);
ee78dc32
GV
3360 UNBLOCK_INPUT;
3361 }
3362}
3363
3364/* Lower frame F. */
3365
3366x_lower_frame (f)
3367 struct frame *f;
3368{
52cf03a1 3369// if (f->async_visible)
ee78dc32
GV
3370 {
3371 BLOCK_INPUT;
52cf03a1
GV
3372 my_set_window_pos (FRAME_WIN32_WINDOW (f),
3373 HWND_BOTTOM,
3374 0, 0, 0, 0,
3375 SWP_NOSIZE | SWP_NOMOVE);
ee78dc32
GV
3376 UNBLOCK_INPUT;
3377 }
3378}
3379
3380static void
3381win32_frame_raise_lower (f, raise)
3382 FRAME_PTR f;
3383 int raise;
3384{
3385 if (raise)
3386 x_raise_frame (f);
3387 else
3388 x_lower_frame (f);
3389}
3390\f
3391/* Change of visibility. */
3392
3393/* This tries to wait until the frame is really visible.
3394 However, if the window manager asks the user where to position
3395 the frame, this will return before the user finishes doing that.
3396 The frame will not actually be visible at that time,
3397 but it will become visible later when the window manager
3398 finishes with it. */
3399
3400x_make_frame_visible (f)
3401 struct frame *f;
3402{
3403 BLOCK_INPUT;
3404
3405 if (! FRAME_VISIBLE_P (f))
3406 {
3407 /* We test FRAME_GARBAGED_P here to make sure we don't
3408 call x_set_offset a second time
3409 if we get to x_make_frame_visible a second time
3410 before the window gets really visible. */
3411 if (! FRAME_ICONIFIED_P (f)
52cf03a1
GV
3412 && ! f->output_data.win32->asked_for_visible)
3413 {
3414 x_set_offset (f, f->output_data.win32->left_pos, f->output_data.win32->top_pos, 0);
3415// SetForegroundWindow (FRAME_WIN32_WINDOW (f));
3416 }
ee78dc32
GV
3417
3418 f->output_data.win32->asked_for_visible = 1;
52cf03a1
GV
3419
3420 my_show_window (FRAME_WIN32_WINDOW (f), SW_SHOWNORMAL);
ee78dc32
GV
3421 }
3422
3423 /* Synchronize to ensure Emacs knows the frame is visible
3424 before we do anything else. We do this loop with input not blocked
3425 so that incoming events are handled. */
3426 {
3427 Lisp_Object frame;
3428 int count = input_signal_count;
3429
3430 /* This must come after we set COUNT. */
3431 UNBLOCK_INPUT;
3432
3433 XSETFRAME (frame, f);
3434
3435 while (1)
3436 {
3437 /* Once we have handled input events,
3438 we should have received the MapNotify if one is coming.
3439 So if we have not got it yet, stop looping.
3440 Some window managers make their own decisions
3441 about visibility. */
3442 if (input_signal_count != count)
3443 break;
3444 /* Machines that do polling rather than SIGIO have been observed
3445 to go into a busy-wait here. So we'll fake an alarm signal
3446 to let the handler know that there's something to be read.
3447 We used to raise a real alarm, but it seems that the handler
3448 isn't always enabled here. This is probably a bug. */
3449 if (input_polling_used ())
3450 {
3451 /* It could be confusing if a real alarm arrives while processing
3452 the fake one. Turn it off and let the handler reset it. */
3453 alarm (0);
3454 input_poll_signal ();
3455 }
3456 /* Once we have handled input events,
3457 we should have received the MapNotify if one is coming.
3458 So if we have not got it yet, stop looping.
3459 Some window managers make their own decisions
3460 about visibility. */
3461 if (input_signal_count != count)
3462 break;
3463 }
3464 FRAME_SAMPLE_VISIBILITY (f);
3465 }
3466}
3467
3468/* Change from mapped state to withdrawn state. */
3469
3470/* Make the frame visible (mapped and not iconified). */
3471
3472x_make_frame_invisible (f)
3473 struct frame *f;
3474{
3475 Window window;
3476
3477 /* Don't keep the highlight on an invisible frame. */
3478 if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
3479 FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
3480
3481 BLOCK_INPUT;
3482
52cf03a1 3483 my_show_window (FRAME_WIN32_WINDOW (f), SW_HIDE);
ee78dc32
GV
3484
3485 /* We can't distinguish this from iconification
3486 just by the event that we get from the server.
3487 So we can't win using the usual strategy of letting
3488 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3489 and synchronize with the server to make sure we agree. */
3490 f->visible = 0;
3491 FRAME_ICONIFIED_P (f) = 0;
3492 f->async_visible = 0;
3493 f->async_iconified = 0;
3494
3495 UNBLOCK_INPUT;
3496}
3497
3498/* Change window state from mapped to iconified. */
3499
52cf03a1
GV
3500void
3501x_iconify_frame (f)
ee78dc32
GV
3502 struct frame *f;
3503{
3504 int result;
3505
3506 /* Don't keep the highlight on an invisible frame. */
3507 if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
3508 FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
3509
3510 if (f->async_iconified)
3511 return;
3512
3513 BLOCK_INPUT;
3514
52cf03a1
GV
3515 my_show_window (FRAME_WIN32_WINDOW (f), SW_SHOWMINIMIZED);
3516 /* The frame doesn't seem to be lowered automatically. */
3517 x_lower_frame (f);
ee78dc32
GV
3518
3519 f->async_iconified = 1;
3520
3521 UNBLOCK_INPUT;
3522}
3523\f
3524/* Destroy the window of frame F. */
3525
3526x_destroy_window (f)
3527 struct frame *f;
3528{
3529 struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
3530
3531 BLOCK_INPUT;
3532
3533 my_destroy_window (f, FRAME_WIN32_WINDOW (f));
3534 free_frame_menubar (f);
3535 free_frame_faces (f);
3536
3537 xfree (f->output_data.win32);
3538 f->output_data.win32 = 0;
3539 if (f == dpyinfo->win32_focus_frame)
3540 dpyinfo->win32_focus_frame = 0;
3541 if (f == dpyinfo->win32_focus_event_frame)
3542 dpyinfo->win32_focus_event_frame = 0;
3543 if (f == dpyinfo->win32_highlight_frame)
3544 dpyinfo->win32_highlight_frame = 0;
3545
3546 dpyinfo->reference_count--;
3547
3548 if (f == dpyinfo->mouse_face_mouse_frame)
3549 {
3550 dpyinfo->mouse_face_beg_row
3551 = dpyinfo->mouse_face_beg_col = -1;
3552 dpyinfo->mouse_face_end_row
3553 = dpyinfo->mouse_face_end_col = -1;
3554 dpyinfo->mouse_face_window = Qnil;
3555 }
3556
3557 UNBLOCK_INPUT;
3558}
3559\f
3560/* Setting window manager hints. */
3561
3562/* Set the normal size hints for the window manager, for frame F.
3563 FLAGS is the flags word to use--or 0 meaning preserve the flags
3564 that the window now has.
3565 If USER_POSITION is nonzero, we set the USPosition
3566 flag (this is useful when FLAGS is 0). */
3567
3568x_wm_set_size_hint (f, flags, user_position)
3569 struct frame *f;
3570 long flags;
3571 int user_position;
3572{
3573 Window window = FRAME_WIN32_WINDOW (f);
3574
3575 flexlines = f->height;
3576
97c23857 3577 enter_crit ();
ee78dc32
GV
3578
3579 SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
3580 SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
3581
97c23857 3582 leave_crit ();
ee78dc32
GV
3583}
3584
3585/* Window manager things */
3586x_wm_set_icon_position (f, icon_x, icon_y)
3587 struct frame *f;
3588 int icon_x, icon_y;
3589{
3590#if 0
3591 Window window = FRAME_WIN32_WINDOW (f);
3592
3593 f->display.x->wm_hints.flags |= IconPositionHint;
3594 f->display.x->wm_hints.icon_x = icon_x;
3595 f->display.x->wm_hints.icon_y = icon_y;
3596
3597 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
3598#endif
3599}
3600
3601\f
3602/* Initialization. */
3603
3604#ifdef USE_X_TOOLKIT
3605static XrmOptionDescRec emacs_options[] = {
3606 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
3607 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
3608
3609 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3610 XrmoptionSepArg, NULL},
3611 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
3612
3613 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3614 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3615 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3616 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3617 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3618 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
3619 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
3620};
3621#endif /* USE_X_TOOLKIT */
3622
3623static int win32_initialized = 0;
3624
3625struct win32_display_info *
3626win32_term_init (display_name, xrm_option, resource_name)
3627 Lisp_Object display_name;
3628 char *xrm_option;
3629 char *resource_name;
3630{
3631 Lisp_Object frame;
3632 char *defaultvalue;
3633 struct win32_display_info *dpyinfo;
3634 HDC hdc;
97c23857 3635
ee78dc32
GV
3636 BLOCK_INPUT;
3637
3638 if (!win32_initialized)
3639 {
3640 win32_initialize ();
3641 win32_initialized = 1;
3642 }
3643
3644 {
3645 int argc = 0;
3646 char *argv[3];
3647
3648 argv[0] = "";
3649 argc = 1;
3650 if (xrm_option)
3651 {
3652 argv[argc++] = "-xrm";
3653 argv[argc++] = xrm_option;
3654 }
3655 }
3656
3657 dpyinfo = &one_win32_display_info;
3658
3659 /* Put this display on the chain. */
3660 dpyinfo->next = NULL;
3661
3662 /* Put it on win32_display_name_list as well, to keep them parallel. */
3663 win32_display_name_list = Fcons (Fcons (display_name, Qnil),
3664 win32_display_name_list);
3665 dpyinfo->name_list_element = XCONS (win32_display_name_list)->car;
97c23857 3666
ee78dc32
GV
3667 dpyinfo->win32_id_name
3668 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
3669 + XSTRING (Vsystem_name)->size
3670 + 2);
3671 sprintf (dpyinfo->win32_id_name, "%s@%s",
3672 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
3673
3674#if 0
3675 xrdb = x_load_resources (dpyinfo->display, xrm_option,
3676 resource_name, EMACS_CLASS);
3677
3678 /* Put the rdb where we can find it in a way that works on
3679 all versions. */
3680 dpyinfo->xrdb = xrdb;
3681#endif
52cf03a1 3682 hdc = GetDC (GetDesktopWindow ());
ee78dc32
GV
3683
3684 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
3685 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
3686 dpyinfo->root_window = GetDesktopWindow ();
3687 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
3688 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
3689 dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
3690 dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
52cf03a1 3691 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
ee78dc32
GV
3692 dpyinfo->grabbed = 0;
3693 dpyinfo->reference_count = 0;
3694 dpyinfo->n_fonts = 0;
3695 dpyinfo->font_table_size = 0;
3696 dpyinfo->bitmaps = 0;
3697 dpyinfo->bitmaps_size = 0;
3698 dpyinfo->bitmaps_last = 0;
3699 dpyinfo->mouse_face_mouse_frame = 0;
3700 dpyinfo->mouse_face_deferred_gc = 0;
3701 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3702 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3703 dpyinfo->mouse_face_face_id = 0;
3704 dpyinfo->mouse_face_window = Qnil;
3705 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
3706 dpyinfo->mouse_face_defer = 0;
3707 dpyinfo->win32_focus_frame = 0;
3708 dpyinfo->win32_focus_event_frame = 0;
3709 dpyinfo->win32_highlight_frame = 0;
3710
3711 ReleaseDC (GetDesktopWindow (), hdc);
3712
52cf03a1
GV
3713 /* Determine if there is a middle mouse button, to allow parse_button
3714 to decide whether right mouse events should be mouse-2 or
3715 mouse-3. */
3716 XSETINT (Vwin32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
3717
3718 /* initialise palette with white and black */
3719 {
3720 COLORREF color;
3721 defined_color (0, "white", &color, 1);
3722 defined_color (0, "black", &color, 1);
3723 }
3724
ee78dc32
GV
3725#ifndef F_SETOWN_BUG
3726#ifdef F_SETOWN
3727#ifdef F_SETOWN_SOCK_NEG
3728 /* stdin is a socket here */
3729 fcntl (connection, F_SETOWN, -getpid ());
3730#else /* ! defined (F_SETOWN_SOCK_NEG) */
3731 fcntl (connection, F_SETOWN, getpid ());
3732#endif /* ! defined (F_SETOWN_SOCK_NEG) */
3733#endif /* ! defined (F_SETOWN) */
3734#endif /* F_SETOWN_BUG */
3735
3736#ifdef SIGIO
3737 if (interrupt_input)
3738 init_sigio (connection);
3739#endif /* ! defined (SIGIO) */
3740
3741 UNBLOCK_INPUT;
3742
3743 return dpyinfo;
3744}
3745\f
3746/* Get rid of display DPYINFO, assuming all frames are already gone. */
3747
3748void
3749x_delete_display (dpyinfo)
3750 struct win32_display_info *dpyinfo;
3751{
3752 /* Discard this display from win32_display_name_list and win32_display_list.
3753 We can't use Fdelq because that can quit. */
3754 if (! NILP (win32_display_name_list)
3755 && EQ (XCONS (win32_display_name_list)->car, dpyinfo->name_list_element))
3756 win32_display_name_list = XCONS (win32_display_name_list)->cdr;
3757 else
3758 {
3759 Lisp_Object tail;
3760
3761 tail = win32_display_name_list;
3762 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
3763 {
3764 if (EQ (XCONS (XCONS (tail)->cdr)->car,
3765 dpyinfo->name_list_element))
3766 {
3767 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
3768 break;
3769 }
3770 tail = XCONS (tail)->cdr;
3771 }
3772 }
3773
52cf03a1
GV
3774 /* free palette table */
3775 {
3776 struct win32_palette_entry * plist;
3777
3778 plist = dpyinfo->color_list;
3779 while (plist)
3780 {
3781 struct win32_palette_entry * pentry = plist;
3782 plist = plist->next;
3783 xfree(pentry);
3784 }
3785 dpyinfo->color_list = NULL;
3786 if (dpyinfo->palette)
3787 DeleteObject(dpyinfo->palette);
3788 }
ee78dc32
GV
3789 xfree (dpyinfo->font_table);
3790 xfree (dpyinfo->win32_id_name);
3791}
3792\f
3793/* Set up use of Win32. */
3794
3795DWORD win_msg_worker ();
3796
3797win32_initialize ()
3798{
3799 clear_frame_hook = win32_clear_frame;
3800 clear_end_of_line_hook = win32_clear_end_of_line;
3801 ins_del_lines_hook = win32_ins_del_lines;
3802 change_line_highlight_hook = win32_change_line_highlight;
3803 insert_glyphs_hook = win32_insert_glyphs;
3804 write_glyphs_hook = win32_write_glyphs;
3805 delete_glyphs_hook = win32_delete_glyphs;
3806 ring_bell_hook = win32_ring_bell;
3807 reset_terminal_modes_hook = win32_reset_terminal_modes;
3808 set_terminal_modes_hook = win32_set_terminal_modes;
3809 update_begin_hook = win32_update_begin;
3810 update_end_hook = win32_update_end;
3811 set_terminal_window_hook = win32_set_terminal_window;
3812 read_socket_hook = w32_read_socket;
3813 frame_up_to_date_hook = win32_frame_up_to_date;
3814 cursor_to_hook = win32_cursor_to;
3815 reassert_line_highlight_hook = win32_reassert_line_highlight;
3816 mouse_position_hook = win32_mouse_position;
3817 frame_rehighlight_hook = win32_frame_rehighlight;
3818 frame_raise_lower_hook = win32_frame_raise_lower;
3819 set_vertical_scroll_bar_hook = win32_set_vertical_scroll_bar;
3820 condemn_scroll_bars_hook = win32_condemn_scroll_bars;
3821 redeem_scroll_bar_hook = win32_redeem_scroll_bar;
3822 judge_scroll_bars_hook = win32_judge_scroll_bars;
3823
3824 scroll_region_ok = 1; /* we'll scroll partial frames */
3825 char_ins_del_ok = 0; /* just as fast to write the line */
3826 line_ins_del_ok = 1; /* we'll just blt 'em */
3827 fast_clear_end_of_line = 1; /* X does this well */
3828 memory_below_frame = 0; /* we don't remember what scrolls
3829 off the bottom */
3830 baud_rate = 19200;
3831
3832 /* Try to use interrupt input; if we can't, then start polling. */
3833 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3834
3835 /* Create the window thread - it will terminate itself or when the app terminates */
3836
3837 init_crit ();
3838
3839 dwMainThreadId = GetCurrentThreadId ();
3840 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3841 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
3842
3843 /* Wait for thread to start */
3844
3845 {
3846 MSG msg;
3847
3848 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
3849
3850 hWinThread = CreateThread (NULL, 0,
3851 (LPTHREAD_START_ROUTINE) win_msg_worker,
3852 0, 0, &dwWinThreadId);
3853
3854 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3855 }
3856
52cf03a1
GV
3857 /* It is desirable that mainThread should have the same notion of
3858 focus window and active window as winThread. Unfortunately, the
3859 following call to AttachThreadInput, which should do precisely what
3860 we need, causes major problems when Emacs is linked as a console
3861 program. Unfortunately, we have good reasons for doing that, so
3862 instead we need to send messages to winThread to make some API
3863 calls for us (ones that affect, or depend on, the active/focus
3864 window state. */
3865#ifdef ATTACH_THREADS
a92989c3 3866 AttachThreadInput (dwMainThreadId, dwWinThreadId, TRUE);
52cf03a1 3867#endif
ee78dc32
GV
3868}
3869
3870void
3871syms_of_win32term ()
3872{
3873 staticpro (&win32_display_name_list);
3874 win32_display_name_list = Qnil;
3875
3876 staticpro (&last_mouse_scroll_bar);
3877 last_mouse_scroll_bar = Qnil;
3878
3879 staticpro (&Qvendor_specific_keysyms);
3880 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
52cf03a1
GV
3881
3882 DEFVAR_INT ("win32-num-mouse-buttons",
3883 &Vwin32_num_mouse_buttons,
3884 "Number of physical mouse buttons.");
3885 Vwin32_num_mouse_buttons = Qnil;
3886
3887 DEFVAR_LISP ("win32-swap-mouse-buttons",
3888 &Vwin32_swap_mouse_buttons,
3889 "Swap the mapping of middle and right mouse buttons.\n\
3890When nil, middle button is mouse-2 and right button is mouse-3.");
3891 Vwin32_swap_mouse_buttons = Qnil;
ee78dc32 3892}