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