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