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