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