new version
[emacs.git] / src / w32term.c
blob75e53a1216fbdfa386615ba3e94ace76dc90d7e4
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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. */
21 /* Added by Kevin Gallo */
23 #include <signal.h>
24 #include <config.h>
25 #include <stdio.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
30 #include <w32term.h>
32 #include "systty.h"
33 #include "systime.h"
35 #include <ctype.h>
36 #include <errno.h>
37 #include <setjmp.h>
38 #include <sys/stat.h>
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"
52 extern void free_frame_menubar ();
54 extern Lisp_Object Vwindow_system;
56 #define x_any_window_to_frame x_window_to_frame
57 #define x_top_window_to_frame x_window_to_frame
60 /* This is display since w32 does not support multiple ones. */
61 struct w32_display_info one_w32_display_info;
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;
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;
76 /* This is a frame waiting to be autoraised, within w32_read_socket. */
77 struct frame *pending_autoraise_frame;
79 /* During an update, maximum vpos for ins/del line operations to affect. */
81 static int flexlines;
83 /* During an update, nonzero if chars output now should be highlighted. */
85 static int highlight;
87 /* Nominal cursor position -- where to draw output.
88 During an update, these are different from the cursor-box position. */
90 static int curs_x;
91 static int curs_y;
93 DWORD dwWindowsThreadId = 0;
94 HANDLE hWindowsThread = NULL;
95 DWORD dwMainThreadId = 0;
96 HANDLE hMainThread = NULL;
98 /* Mouse movement. */
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;
104 Lisp_Object Vw32_num_mouse_buttons;
106 Lisp_Object Vw32_swap_mouse_buttons;
108 /* The scroll bar in which the last motion event occurred.
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.
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;
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;
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
134 extern Lisp_Object Vcommand_line_args, Vsystem_name;
136 extern Lisp_Object Qface, Qmouse_face;
138 extern int errno;
140 /* A mask of extra modifier bits to put into every keyboard char. */
141 extern int extra_keyboard_modifiers;
143 static Lisp_Object Qvendor_specific_keysyms;
145 void w32_delete_display ();
147 static void redraw_previous_char ();
148 static void redraw_following_char ();
149 static unsigned int w32_get_modifiers ();
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 ();
157 static int w32_cursor_to ();
158 static int w32_clear_end_of_line ();
160 #if 0
161 /* This is a function useful for recording debugging information
162 about the sequence of occurrences in this file. */
164 struct record
166 char *locus;
167 int type;
170 struct record event_record[100];
172 int event_record_index;
174 record_event (locus, type)
175 char *locus;
176 int type;
178 if (event_record_index == sizeof (event_record) / sizeof (struct record))
179 event_record_index = 0;
181 event_record[event_record_index].locus = locus;
182 event_record[event_record_index].type = type;
183 event_record_index++;
186 #endif /* 0 */
188 /* Return the struct w32_display_info. */
190 struct w32_display_info *
191 w32_display_info_for_display ()
193 return (&one_w32_display_info);
196 void
197 w32_fill_rect (f, _hdc, pix, lprect)
198 FRAME_PTR f;
199 HDC _hdc;
200 COLORREF pix;
201 RECT * lprect;
203 HDC hdc;
204 HBRUSH hb;
205 RECT rect;
207 if (_hdc)
208 hdc = _hdc;
209 else
211 if (!f) return;
212 hdc = get_frame_dc (f);
215 hb = CreateSolidBrush (pix);
216 FillRect (hdc, lprect, hb);
217 DeleteObject (hb);
219 if (!_hdc)
220 release_frame_dc (f, hdc);
223 void
224 w32_clear_window (f)
225 FRAME_PTR f;
227 RECT rect;
229 GetClientRect (FRAME_W32_WINDOW (f), &rect);
230 w32_clear_rect (f, NULL, &rect);
234 /* Starting and ending updates.
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. */
243 static
244 w32_update_begin (f)
245 struct frame *f;
247 if (f == 0)
248 abort ();
250 flexlines = f->height;
251 highlight = 0;
253 BLOCK_INPUT;
255 /* Regenerate display palette before drawing if list of requested
256 colors has changed. */
257 if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
259 w32_regenerate_palette (f);
260 FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
263 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
265 /* Don't do highlighting for mouse motion during the update. */
266 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
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;
273 if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
275 int firstline, lastline, i;
276 struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
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;
283 lastline = f->height;
284 for (i = f->height - 1; i >= 0; i--)
286 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
287 break;
288 else
289 lastline = i;
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));
303 UNBLOCK_INPUT;
306 static
307 w32_update_end (f)
308 struct frame *f;
310 BLOCK_INPUT;
312 do_line_dance ();
313 x_display_cursor (f, 1);
315 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
316 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
318 UNBLOCK_INPUT;
321 /* This is called after a redisplay on frame F. */
323 static
324 w32_frame_up_to_date (f)
325 FRAME_PTR f;
327 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
328 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
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;
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. */
341 w32_reassert_line_highlight (new, vpos)
342 int new, vpos;
344 highlight = new;
347 /* Call this when about to modify line at position VPOS
348 and change whether it is highlighted. */
350 static
351 w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
352 int new_highlight, vpos, first_unused_hpos;
354 highlight = new_highlight;
355 w32_cursor_to (vpos, 0);
356 w32_clear_end_of_line (updating_frame->width);
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). */
363 static
364 w32_set_terminal_modes ()
368 /* This is called when exiting or suspending Emacs.
369 Exiting will make the W32 windows go away, and suspending
370 requires no action. */
372 static
373 w32_reset_terminal_modes ()
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. */
381 static int
382 w32_cursor_to (row, col)
383 register int row, col;
385 int orow = row;
387 curs_x = col;
388 curs_y = row;
390 if (updating_frame == 0)
392 BLOCK_INPUT;
393 x_display_cursor (selected_frame, 1);
394 UNBLOCK_INPUT;
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.
405 FONT is the default font to use (for glyphs whose font-code is 0).
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. */
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;
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;
432 hdc = get_frame_dc (f);
434 while (n > 0)
436 /* Get the face-code of the next GLYPH. */
437 int cf, len;
438 int g = *gp;
440 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
441 cf = FAST_GLYPH_FACE (g);
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)
448 g = *gp;
449 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
450 if (FAST_GLYPH_FACE (g) != cf)
451 break;
453 *cp++ = FAST_GLYPH_CHAR (g);
454 --n;
455 ++gp;
458 /* LEN gets the length of the run. */
459 len = cp - buf;
461 /* Now output this run of chars, with the font and pixel values
462 determined by the face code CF. */
464 struct face *face = FRAME_DEFAULT_FACE (f);
465 XFontStruct *font = FACE_FONT (face);
466 int stippled = 0;
467 COLORREF fg;
468 COLORREF bg;
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;
474 /* First look at the face of the text itself. */
475 if (cf != 0)
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;
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;
492 /* Then comes the distinction between modeline and normal text. */
493 else if (hl == 0)
495 else if (hl == 1)
497 face = FRAME_MODE_LINE_FACE (f);
498 font = FACE_FONT (face);
499 if (FACE_STIPPLE (face))
500 stippled = 1;
503 fg = face->foreground;
504 bg = face->background;
506 /* Now override that if the cursor's on this character. */
507 if (hl == 2)
509 /* The cursor overrides stippling. */
510 stippled = 0;
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)
518 bg = f->output_data.w32->cursor_pixel;
519 fg = face->background;
521 /* Cursor on non-default face: must merge. */
522 else
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)
538 bg = face->foreground;
539 fg = face->background;
544 if (font == (XFontStruct *) FACE_DEFAULT)
545 font = f->output_data.w32->font;
547 SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
549 SetTextColor (hdc, fg);
550 SetBkColor (hdc, bg);
552 SelectObject (hdc, font->hfont);
554 TextOut (hdc, left, top, buf, len);
556 if (!just_foreground)
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));
568 int underline_position = 1;
570 if (font->tm.tmDescent <= underline_position)
571 underline_position = font->tm.tmDescent - 1;
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);
581 left += len * FONT_WIDTH (font);
585 release_frame_dc (f, hdc);
589 /* Output some text at the nominal frame cursor position.
590 Advance the cursor over the text.
591 Output LEN glyphs at START.
593 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
594 controls the pixel values used for foreground and background. */
596 static
597 w32_write_glyphs (start, len)
598 register GLYPH *start;
599 int len;
601 register int temp_length;
602 struct frame *f;
604 BLOCK_INPUT;
606 do_line_dance ();
607 f = updating_frame;
608 if (f == 0)
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;
617 dumpglyphs (f,
618 CHAR_TO_PIXEL_COL (f, curs_x),
619 CHAR_TO_PIXEL_ROW (f, curs_y),
620 start, len, highlight, 0);
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;
628 if (updating_frame == 0)
630 f->cursor_x += len;
631 x_display_cursor (f, 1);
632 f->cursor_x -= len;
634 else
635 curs_x += len;
637 UNBLOCK_INPUT;
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. */
645 static
646 w32_clear_end_of_line (first_unused)
647 register int first_unused;
649 struct frame *f = updating_frame;
651 if (f == 0)
652 abort ();
654 if (curs_y < 0 || curs_y >= f->height)
655 return 1;
656 if (first_unused <= 0)
657 return 1;
659 if (first_unused >= f->width)
660 first_unused = f->width;
662 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
664 BLOCK_INPUT;
666 do_line_dance ();
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;
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);
680 UNBLOCK_INPUT;
683 static
684 w32_clear_frame ()
686 struct frame *f = updating_frame;
688 if (f == 0)
689 f = selected_frame;
691 f->phys_cursor_x = -1; /* Cursor not visible. */
692 curs_x = 0; /* Nominal cursor position is top left. */
693 curs_y = 0;
695 BLOCK_INPUT;
697 w32_clear_window (f);
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);
703 UNBLOCK_INPUT;
706 /* Make audible bell. */
708 w32_ring_bell ()
710 BLOCK_INPUT;
712 if (visible_bell)
713 FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
714 else
715 w32_sys_ring_bell ();
717 UNBLOCK_INPUT;
719 return 1;
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. */
726 static
727 w32_insert_glyphs (start, len)
728 register char *start;
729 register int len;
731 abort ();
734 static
735 w32_delete_glyphs (n)
736 register int n;
738 abort ();
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. */
746 static
747 w32_set_terminal_window (n)
748 register int n;
750 if (updating_frame == 0)
751 abort ();
753 if ((n <= 0) || (n > updating_frame->height))
754 flexlines = updating_frame->height;
755 else
756 flexlines = n;
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. */
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;
769 /* Allocated length of that array. */
770 static int line_dance_len;
772 /* Flag indicating whether we've done any work. */
773 static int line_dance_in_progress;
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;
780 register int fence, i;
782 if (vpos >= flexlines)
783 return 1;
785 if (!line_dance_in_progress)
787 int ht = updating_frame->height;
788 if (ht > line_dance_len)
790 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
791 line_dance_len = ht;
793 for (i = 0; i < ht; ++i) line_dance[i] = i;
794 line_dance_in_progress = 1;
796 if (n >= 0)
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;
806 else
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;
819 /* Here's where we actually move the pixels around.
820 Must be called with input blocked. */
821 static void
822 do_line_dance ()
824 register int i, j, distance;
825 register struct frame *f;
826 int ht;
827 int intborder;
828 HDC hdc;
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;
835 f = updating_frame;
836 if (f == 0)
837 abort ();
839 ht = f->height;
840 intborder = f->output_data.w32->internal_border_width;
842 x_display_cursor (updating_frame, 0);
844 hdc = get_frame_dc (f);
846 for (i = 0; i < ht; ++i)
847 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
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;
862 for (i = ht; --i >=0; )
863 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
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;
878 release_frame_dc (f, hdc);
880 for (i = 0; i < ht; ++i)
881 if (line_dance[i] == -1)
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;
892 line_dance_in_progress = 0;
895 /* Support routines for exposure events. */
896 static void clear_cursor ();
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. */
904 void
905 dumprectangle (f, left, top, cols, rows)
906 struct frame *f;
907 register int left, top, cols, rows;
909 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
910 int cursor_cleared = 0;
911 int bottom, right;
912 register int y;
914 if (FRAME_GARBAGED_P (f))
915 return;
917 /* Express rectangle as four edges, instead of position-and-size. */
918 bottom = top + rows;
919 right = left + cols;
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);
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;
940 /* Get size in chars of the rectangle. */
941 cols = right - left;
942 rows = bottom - top;
944 /* If rectangle has zero area, return. */
945 if (rows <= 0) return;
946 if (cols <= 0) return;
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))
953 clear_cursor (f);
954 cursor_cleared = 1;
957 /* Display the text in the rectangle, one text line at a time. */
959 for (y = top; y < bottom; y++)
961 GLYPH *line = &active_frame->glyphs[y][left];
963 if (! active_frame->enable[y] || left > active_frame->used[y])
964 continue;
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);
973 /* Turn the cursor on if we turned it off. */
975 if (cursor_cleared)
976 x_display_cursor (f, 1);
979 static void
980 frame_highlight (f)
981 struct frame *f;
983 x_display_cursor (f, 1);
986 static void
987 frame_unhighlight (f)
988 struct frame *f;
990 x_display_cursor (f, 1);
993 static void w32_frame_rehighlight ();
994 static void x_frame_rehighlight ();
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. */
1002 void
1003 x_new_focus_frame (dpyinfo, frame)
1004 struct w32_display_info *dpyinfo;
1005 struct frame *frame;
1007 struct frame *old_focus = dpyinfo->w32_focus_frame;
1008 int events_enqueued = 0;
1010 if (frame != dpyinfo->w32_focus_frame)
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;
1016 if (old_focus && old_focus->auto_lower)
1017 x_lower_frame (old_focus);
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;
1025 x_frame_rehighlight (dpyinfo);
1028 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1030 void
1031 x_mouse_leave (dpyinfo)
1032 struct w32_display_info *dpyinfo;
1034 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
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.
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;
1048 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
1051 static void
1052 x_frame_rehighlight (dpyinfo)
1053 struct w32_display_info *dpyinfo;
1055 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
1057 if (dpyinfo->w32_focus_frame)
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))
1065 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
1066 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
1069 else
1070 dpyinfo->w32_highlight_frame = 0;
1072 if (dpyinfo->w32_highlight_frame != old_highlight)
1074 if (old_highlight)
1075 frame_unhighlight (old_highlight);
1076 if (dpyinfo->w32_highlight_frame)
1077 frame_highlight (dpyinfo->w32_highlight_frame);
1081 /* Keyboard processing - modifier keys, etc. */
1083 /* Convert a keysym to its name. */
1085 char *
1086 x_get_keysym_name (keysym)
1087 int keysym;
1089 /* Make static so we can always return it */
1090 static char value[100];
1092 BLOCK_INPUT;
1093 GetKeyNameText(keysym, value, 100);
1094 UNBLOCK_INPUT;
1096 return value;
1099 /* Mouse clicks and mouse movement. Rah. */
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. */
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;
1114 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1115 if (NILP (Vwindow_system))
1117 *x = pix_x;
1118 *y = pix_y;
1119 return;
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;
1129 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1130 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1132 if (bounds)
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;
1140 if (!noclip)
1142 if (pix_x < 0)
1143 pix_x = 0;
1144 else if (pix_x > f->width)
1145 pix_x = f->width;
1147 if (pix_y < 0)
1148 pix_y = 0;
1149 else if (pix_y > f->height)
1150 pix_y = f->height;
1153 *x = pix_x;
1154 *y = pix_y;
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;
1163 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1164 if (NILP (Vwindow_system))
1166 *pix_x = x;
1167 *pix_y = y;
1168 return;
1171 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1172 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1175 BOOL
1176 parse_button (message, pbutton, pup)
1177 int message;
1178 int * pbutton;
1179 int * pup;
1181 int button = 0;
1182 int up = 0;
1184 switch (message)
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);
1226 if (pup) *pup = up;
1227 if (pbutton) *pbutton = button;
1229 return (TRUE);
1233 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1235 If the event is a button press, then note that we have grabbed
1236 the mouse. */
1238 static void
1239 construct_mouse_click (result, msg, f)
1240 struct input_event *result;
1241 W32Msg *msg;
1242 struct frame *f;
1244 int button;
1245 int up;
1247 parse_button (msg->msg.message, &button, &up);
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));
1260 int row, column;
1262 XSETINT (result->x, LOWORD (msg->msg.lParam));
1263 XSETINT (result->y, HIWORD (msg->msg.lParam));
1264 XSETFRAME (result->frame_or_window, f);
1269 /* Function to report a mouse movement to the mainstream Emacs code.
1270 The input handler calls this.
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. */
1277 static void
1278 note_mouse_movement (frame, msg)
1279 FRAME_PTR frame;
1280 MSG *msg;
1282 last_mouse_movement_time = msg->time;
1284 if (msg->hwnd != FRAME_W32_WINDOW (frame))
1286 frame->mouse_moved = 1;
1287 last_mouse_scroll_bar = Qnil;
1289 note_mouse_highlight (frame, -1, -1);
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)
1298 frame->mouse_moved = 1;
1299 last_mouse_scroll_bar = Qnil;
1301 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1305 /* This is used for debugging, to turn off note_mouse_highlight. */
1306 static int disable_mouse_highlight;
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. */
1313 static void
1314 note_mouse_highlight (f, x, y)
1315 FRAME_PTR f;
1316 int x, y;
1318 int row, column, portion;
1319 RECT new_glyph;
1320 Lisp_Object window;
1321 struct window *w;
1323 if (disable_mouse_highlight)
1324 return;
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;
1330 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
1331 return;
1333 if (gc_in_progress)
1335 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1336 return;
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);
1343 /* Which window is that in? */
1344 window = window_from_coordinates (f, column, row, &portion);
1345 w = XWINDOW (window);
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));
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)))
1359 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1360 int i, pos;
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)))
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;
1385 /* If we get an out-of-range value, return now; avoid an error. */
1386 if (pos > BUF_Z (XBUFFER (w->buffer)))
1387 return;
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;
1398 /* Yes. Clear the display of the old active region, if any. */
1399 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1401 /* Is this char mouse-active? */
1402 XSETINT (position, pos);
1404 len = 10;
1405 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
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);
1413 /* Find the highest priority overlay that has a mouse-face prop. */
1414 overlay = Qnil;
1415 for (i = 0; i < noverlays; i++)
1417 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1418 if (!NILP (mouse_face))
1420 overlay = overlay_vec[i];
1421 break;
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);
1429 /* Handle the overlay case. */
1430 if (! NILP (overlay))
1432 /* Find the range of text around this char that
1433 should be active. */
1434 Lisp_Object before, after;
1435 int ignore;
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);
1452 /* Display it as active. */
1453 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1455 /* Handle the text property case. */
1456 else if (! NILP (mouse_face))
1458 /* Find the range of text around this char that
1459 should be active. */
1460 Lisp_Object before, after, beginning, end;
1461 int ignore;
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);
1486 /* Display it as active. */
1487 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1489 BEGV = obegv;
1490 ZV = ozv;
1491 current_buffer = obuf;
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.
1503 Value is 1 if POS is in range, 0 if it was off screen. */
1505 static int
1506 fast_find_position (window, pos, columnp, rowp)
1507 Lisp_Object window;
1508 int pos;
1509 int *columnp, *rowp;
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;
1523 /* Find the right row. */
1524 for (i = 0;
1525 i < height;
1526 i++)
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)))
1535 maybe_next_line = 1;
1536 break;
1538 if (linestart > 0)
1539 row = i;
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++)
1547 if (charstarts[left + i] == pos)
1549 *rowp = row + top;
1550 *columnp = i + left;
1551 return 1;
1553 else if (charstarts[left + i] > pos)
1554 break;
1555 else if (charstarts[left + i] > 0)
1556 lastcol = left + i;
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)
1564 row++;
1565 i = 0;
1568 *rowp = row + top;
1569 *columnp = lastcol;
1570 return 0;
1573 /* Display the active region described by mouse_face_*
1574 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1576 static void
1577 show_mouse_face (dpyinfo, hl)
1578 struct w32_display_info *dpyinfo;
1579 int hl;
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;
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;
1595 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
1596 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
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]);
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)
1612 x_display_cursor (f, 0);
1613 cursor_off = 1;
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);
1625 /* If we turned the cursor off, turn it back on. */
1626 if (cursor_off)
1627 x_display_cursor (f, 1);
1629 curs_x = old_curs_x;
1630 curs_y = old_curs_y;
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);
1639 /* Clear out the mouse-highlighted active region.
1640 Redraw it unhighlighted first. */
1642 static void
1643 clear_mouse_face (dpyinfo)
1644 struct w32_display_info *dpyinfo;
1646 if (! NILP (dpyinfo->mouse_face_window))
1647 show_mouse_face (dpyinfo, 0);
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;
1654 struct scroll_bar *x_window_to_scroll_bar ();
1655 static void x_scroll_bar_report_motion ();
1657 /* Return the current position of the mouse.
1658 *fp should be a frame which indicates which display to ask about.
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.
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.
1669 Set *time to the server timestamp for the time at which the mouse
1670 was at this position.
1672 Don't store anything if we don't have a valid set of values to report.
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. */
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;
1688 FRAME_PTR f1;
1690 BLOCK_INPUT;
1692 if (! NILP (last_mouse_scroll_bar))
1693 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1694 else
1696 POINT pt;
1698 Lisp_Object frame, tail;
1700 /* Clear the mouse-moved flag for every frame on this display. */
1701 FOR_EACH_FRAME (tail, frame)
1702 XFRAME (frame)->mouse_moved = 0;
1704 last_mouse_scroll_bar = Qnil;
1706 GetCursorPos (&pt);
1708 /* Now we have a position on the root; find the innermost window
1709 containing the pointer. */
1711 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
1712 && FRAME_LIVE_P (last_mouse_frame))
1714 f1 = last_mouse_frame;
1716 else
1718 /* Is win one of our frames? */
1719 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
1722 /* If not, is it one of our scroll bars? */
1723 if (! f1)
1725 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1727 if (bar)
1729 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1733 if (f1 == 0 && insist)
1734 f1 = selected_frame;
1736 if (f1)
1738 int ignore1, ignore2;
1740 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
1742 /* Ok, we found a frame. Store all the values. */
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);
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;
1759 UNBLOCK_INPUT;
1762 /* Scroll bar support. */
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;
1771 Lisp_Object tail, frame;
1773 for (tail = Vframe_list;
1774 XGCTYPE (tail) == Lisp_Cons;
1775 tail = XCONS (tail)->cdr)
1777 Lisp_Object frame, bar, condemned;
1779 frame = XCONS (tail)->car;
1780 /* All elements of Vframe_list should be frames. */
1781 if (! GC_FRAMEP (frame))
1782 abort ();
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);
1798 return 0;
1801 HWND
1802 my_create_scrollbar (f, bar)
1803 struct frame * f;
1804 struct scroll_bar * bar;
1806 MSG msg;
1808 PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1809 (LPARAM) bar);
1810 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
1812 return ((HWND) msg.wParam);
1815 //#define ATTACH_THREADS
1817 void
1818 my_show_window (HWND hwnd, int how)
1820 #ifndef ATTACH_THREADS
1821 SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0);
1822 #else
1823 ShowWindow (hwnd , how);
1824 #endif
1827 void
1828 my_set_window_pos (HWND hwnd, HWND hwndAfter,
1829 int x, int y, int cx, int cy, int flags)
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
1845 void
1846 my_destroy_window (f, hwnd)
1847 struct frame * f;
1848 HWND hwnd;
1850 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
1851 (WPARAM) hwnd, 0);
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;
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;
1866 BLOCK_INPUT;
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;
1877 /* Requires geometry to be set before call to create the real window */
1879 hwnd = my_create_scrollbar (f, bar);
1881 SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
1882 SetScrollPos (hwnd, SB_CTL, 0, TRUE);
1884 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
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);
1893 UNBLOCK_INPUT;
1895 return bar;
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.)
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;
1915 int dragging = ! NILP (bar->dragging);
1916 Window w = SCROLL_BAR_W32_WINDOW (bar);
1917 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1919 /* If the display is already accurate, do nothing. */
1920 if (! rebuild
1921 && start == XINT (bar->start)
1922 && end == XINT (bar->end))
1923 return;
1925 BLOCK_INPUT;
1927 /* Store the adjusted setting in the scroll bar. */
1928 XSETINT (bar->start, start);
1929 XSETINT (bar->end, end);
1931 SetScrollPos (w, SB_CTL, start, TRUE);
1933 UNBLOCK_INPUT;
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;
1943 Window w = SCROLL_BAR_W32_WINDOW (bar);
1944 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1946 BLOCK_INPUT;
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);
1953 XSETINT (bar->left, left);
1954 XSETINT (bar->top, top);
1955 XSETINT (bar->width, width);
1956 XSETINT (bar->height, height);
1958 UNBLOCK_INPUT;
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;
1967 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1969 BLOCK_INPUT;
1971 /* Destroy the window. */
1972 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
1974 /* Disassociate this scroll bar from its window. */
1975 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
1977 UNBLOCK_INPUT;
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;
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);
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);
2003 struct scroll_bar *bar;
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
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);
2017 /* Set the scroll bar's current state, unless we're currently being
2018 dragged. */
2019 if (NILP (bar->dragging))
2021 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2023 if (whole == 0)
2024 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2025 else
2027 int start = (int) (((double) position * top_range) / whole);
2028 int end = (int) (((double) (position + portion) * top_range) / whole);
2030 x_scroll_bar_set_handle (bar, start, end, 0);
2034 XSETVECTOR (window->vertical_scroll_bar, bar);
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. */
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;
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 ();
2059 /* Move them all to the "condemned" list. */
2060 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2061 FRAME_SCROLL_BARS (frame) = Qnil;
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;
2070 struct scroll_bar *bar;
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 ();
2076 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2078 /* Unlink it from the condemned list. */
2080 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2082 if (NILP (bar->prev))
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 ();
2097 else
2098 XSCROLL_BAR (bar->prev)->next = bar->next;
2100 if (! NILP (bar->next))
2101 XSCROLL_BAR (bar->next)->prev = bar->prev;
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);
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;
2117 Lisp_Object bar, next;
2119 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
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;
2125 for (; ! NILP (bar); bar = next)
2127 struct scroll_bar *b = XSCROLL_BAR (bar);
2129 x_scroll_bar_remove (b);
2131 next = b->next;
2132 b->next = b->prev = Qnil;
2135 /* Now there should be no references to the condemned scroll bars,
2136 and they should get garbage-collected. */
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.
2142 This may be called from a signal handler, so we have to ignore GC
2143 mark bits. */
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;
2151 if (! GC_WINDOWP (bar->window))
2152 abort ();
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;
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);
2168 switch (LOWORD (msg->msg.wParam))
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;
2204 XSETINT (emacs_event->x, y);
2205 XSETINT (emacs_event->y, top_range);
2207 return TRUE;
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;
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;
2226 BLOCK_INPUT;
2228 *fp = f;
2229 *bar_window = bar->window;
2231 pos = GetScrollPos (w, SB_CTL);
2233 switch (LOWORD (last_mouse_scroll_bar_pos))
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;
2250 XSETINT(*x, pos);
2251 XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
2253 f->mouse_moved = 0;
2254 last_mouse_scroll_bar = Qnil;
2256 *time = last_mouse_movement_time;
2258 UNBLOCK_INPUT;
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. */
2266 x_scroll_bar_clear (f)
2267 FRAME_PTR f;
2269 Lisp_Object bar;
2271 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2272 bar = XSCROLL_BAR (bar)->next)
2274 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2275 HDC hdc = GetDC (window);
2276 RECT rect;
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);
2286 show_scroll_bars (f, how)
2287 FRAME_PTR f;
2288 int how;
2290 Lisp_Object bar;
2292 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2293 bar = XSCROLL_BAR (bar)->next)
2295 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2296 my_show_window (window, how);
2301 /* The main W32 event-reading loop - w32_read_socket. */
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;
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];
2313 extern int key_event (KEY_EVENT_RECORD *, struct input_event *);
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. */
2319 static void
2320 convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
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;
2330 /* Return nonzero if the virtual key is a dead key. */
2332 static int
2333 is_dead_key (int wparam)
2335 unsigned int code = MapVirtualKey (wparam, 2);
2337 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2338 if ((code & 0x8000) || (code & 0x80000000))
2339 return 1;
2340 else
2341 return 0;
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.
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'.
2353 EXPECTED is nonzero if the caller knows input is available.
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.
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;
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;
2381 if (interrupt_input_blocked)
2383 interrupt_input_pending = 1;
2384 return -1;
2387 interrupt_input_pending = 0;
2388 BLOCK_INPUT;
2390 /* So people can tell when we have read the available input. */
2391 input_signal_count++;
2393 if (numchars <= 0)
2394 abort (); /* Don't think this happens. */
2396 while (get_next_msg (&msg, FALSE))
2398 switch (msg.msg.message)
2400 case WM_PAINT:
2402 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2404 if (f)
2406 if (f->async_visible == 0)
2408 f->async_visible = 1;
2409 f->async_iconified = 0;
2410 SET_FRAME_GARBAGED (f);
2412 else
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);
2424 break;
2425 case WM_KEYDOWN:
2426 case WM_SYSKEYDOWN:
2427 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2429 if (f && !f->iconified)
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++;
2443 break;
2444 case WM_SYSCHAR:
2445 case WM_CHAR:
2446 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2448 if (f && !f->iconified)
2450 if (numchars > 1)
2452 int add;
2453 KEY_EVENT_RECORD key, *keyp = &key;
2455 if (temp_index == sizeof temp_buffer / sizeof (short))
2456 temp_index = 0;
2458 convert_to_key_event (&msg, keyp);
2459 add = key_event (keyp, bufp);
2460 XSETFRAME (bufp->frame_or_window, f);
2461 if (add == -1)
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;
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;
2481 bufp += add;
2482 numchars -= add;
2483 count += add;
2485 else
2487 abort ();
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);
2498 if (f)
2499 note_mouse_movement (f, &msg.msg);
2500 else
2501 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
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:
2511 int button;
2512 int up;
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);
2520 if (f)
2522 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
2523 && (numchars >= 1))
2525 construct_mouse_click (bufp, &msg, f);
2526 bufp++;
2527 count++;
2528 numchars--;
2532 parse_button (msg.msg.message, &button, &up);
2534 if (up)
2536 dpyinfo->grabbed &= ~ (1 << button);
2538 else
2540 dpyinfo->grabbed |= (1 << button);
2541 last_mouse_frame = f;
2545 break;
2546 case WM_VSCROLL:
2548 struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam);
2550 if (bar && numchars >= 1)
2552 if (x_scroll_bar_handle_click (bar, &msg, bufp))
2554 bufp++;
2555 count++;
2556 numchars--;
2561 break;
2562 case WM_MOVE:
2563 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2565 if (f && !f->async_iconified)
2567 f->output_data.w32->left_pos = LOWORD (msg.msg.lParam);
2568 f->output_data.w32->top_pos = HIWORD (msg.msg.lParam);
2571 break;
2572 case WM_SIZE:
2573 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2575 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2577 RECT rect;
2578 int rows;
2579 int columns;
2580 int width;
2581 int height;
2583 GetClientRect(msg.msg.hwnd, &rect);
2585 height = rect.bottom - rect.top + 1;
2586 width = rect.right - rect.left + 1;
2588 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2589 columns = PIXEL_TO_CHAR_WIDTH (f, width);
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. */
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)
2600 /* I had set this to 0, 0 - I am not sure why?? */
2602 change_frame_size (f, rows, columns, 0, 1);
2603 SET_FRAME_GARBAGED (f);
2605 f->output_data.w32->pixel_width = width;
2606 f->output_data.w32->pixel_height = height;
2607 f->output_data.w32->win_gravity = NorthWestGravity;
2611 break;
2612 case WM_SETFOCUS:
2613 case WM_KILLFOCUS:
2614 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2616 if (msg.msg.message == WM_SETFOCUS)
2618 x_new_focus_frame (dpyinfo, f);
2620 else if (f == dpyinfo->w32_focus_frame)
2621 x_new_focus_frame (dpyinfo, 0);
2623 break;
2624 case WM_SYSCOMMAND:
2625 switch (msg.msg.wParam & 0xfff0) /* Lower 4 bits used by Windows. */
2627 case SC_CLOSE:
2628 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2630 if (f)
2632 if (numchars == 0)
2633 abort ();
2635 bufp->kind = delete_window_event;
2636 XSETFRAME (bufp->frame_or_window, f);
2637 bufp++;
2638 count++;
2639 numchars--;
2642 break;
2643 case SC_MINIMIZE:
2644 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2646 if (f)
2648 f->async_visible = 1;
2649 f->async_iconified = 1;
2651 bufp->kind = iconify_event;
2652 XSETFRAME (bufp->frame_or_window, f);
2653 bufp++;
2654 count++;
2655 numchars--;
2658 break;
2659 case SC_MAXIMIZE:
2660 case SC_RESTORE:
2661 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2663 if (f)
2665 f->async_visible = 1;
2666 f->async_iconified = 0;
2668 /* wait_reading_process_input will notice this and update
2669 the frame's display structures. */
2670 SET_FRAME_GARBAGED (f);
2672 if (f->iconified)
2674 bufp->kind = deiconify_event;
2675 XSETFRAME (bufp->frame_or_window, f);
2676 bufp++;
2677 count++;
2678 numchars--;
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 ();
2687 break;
2690 break;
2691 case WM_CLOSE:
2692 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2694 if (f)
2696 if (numchars == 0)
2697 abort ();
2699 bufp->kind = delete_window_event;
2700 XSETFRAME (bufp->frame_or_window, f);
2701 bufp++;
2702 count++;
2703 numchars--;
2706 break;
2707 case WM_COMMAND:
2708 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2710 if (f)
2712 if (msg.msg.lParam == 0)
2714 /* Came from window menu */
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;
2721 XSETFRAME (frame, f);
2722 buf.kind = menu_bar_event;
2724 /* Store initial menu bar event */
2726 if (!NILP (event))
2728 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
2729 kbd_buffer_store_event (&buf);
2732 /* Enqueue the events */
2734 while (!NILP (event))
2736 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
2737 kbd_buffer_store_event (&buf);
2738 event = XCONS (event)->cdr;
2741 else
2743 /* Came from popup menu */
2746 break;
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)
2755 x_raise_frame (pending_autoraise_frame);
2756 pending_autoraise_frame = 0;
2759 UNBLOCK_INPUT;
2760 return count;
2763 /* Drawing the cursor. */
2766 /* Draw a hollow box cursor. Don't change the inside of the box. */
2768 static void
2769 x_draw_box (f)
2770 struct frame *f;
2772 RECT rect;
2773 HBRUSH hb;
2774 HDC hdc;
2776 hdc = get_frame_dc (f);
2778 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
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;
2785 FrameRect (hdc, &rect, hb);
2786 DeleteObject (hb);
2788 release_frame_dc (f, hdc);
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. */
2796 static void
2797 clear_cursor (f)
2798 struct frame *f;
2800 if (! FRAME_VISIBLE_P (f)
2801 || f->phys_cursor_x < 0)
2802 return;
2804 x_display_cursor (f, 0);
2805 f->phys_cursor_x = -1;
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. */
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;
2819 dumpglyphs (f,
2820 CHAR_TO_PIXEL_COL (f, column),
2821 CHAR_TO_PIXEL_ROW (f, row),
2822 &glyph, 1, highlight, 0);
2825 static void
2826 x_display_bar_cursor (f, on)
2827 struct frame *f;
2828 int on;
2830 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
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;
2838 if (! on && f->phys_cursor_x < 0)
2839 return;
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)
2845 curs_x = FRAME_CURSOR_X (f);
2846 curs_y = FRAME_CURSOR_Y (f);
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))
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;
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)))
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);
2879 f->phys_cursor_x = curs_x;
2880 f->phys_cursor_y = curs_y;
2882 f->output_data.w32->current_cursor = bar_cursor;
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. */
2891 static void
2892 x_display_box_cursor (f, on)
2893 struct frame *f;
2894 int on;
2896 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
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;
2904 /* If cursor is off and we want it off, return quickly. */
2905 if (!on && f->phys_cursor_x < 0)
2906 return;
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)
2912 curs_x = FRAME_CURSOR_X (f);
2913 curs_y = FRAME_CURSOR_Y (f);
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))))
2927 int mouse_face_here = 0;
2928 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
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
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))
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;
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
2960 : current_glyphs->highlight[f->phys_cursor_y]));
2961 f->phys_cursor_x = -1;
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)))
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)
2979 x_draw_box (f);
2980 f->output_data.w32->current_cursor = hollow_box_cursor;
2982 else
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;
2989 f->phys_cursor_x = curs_x;
2990 f->phys_cursor_y = curs_y;
2994 x_display_cursor (f, on)
2995 struct frame *f;
2996 int on;
2998 BLOCK_INPUT;
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 ();
3008 UNBLOCK_INPUT;
3011 /* Changing the font of the frame. */
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. */
3018 Lisp_Object
3019 x_new_font (f, fontname)
3020 struct frame *f;
3021 register char *fontname;
3023 int already_loaded;
3024 int n_matching_fonts;
3025 XFontStruct *font_info;
3026 char new_font_name[101];
3028 /* Get a font which matches this name */
3030 LOGFONT lf;
3032 if (!x_to_w32_font(fontname, &lf)
3033 || !w32_to_x_font(&lf, new_font_name, 100))
3035 return Qnil;
3039 /* See if we've already loaded a matching font. */
3040 already_loaded = -1;
3043 int i;
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))
3048 already_loaded = i;
3049 fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
3050 break;
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
3060 XFontStruct *font;
3061 int n_fonts;
3063 font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
3065 if (! font)
3067 return Qnil;
3070 /* Do we need to create the table? */
3071 if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
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));
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)
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)));
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++;
3096 /* Compute the scroll bar width in character columns. */
3097 if (f->scroll_bar_pixel_width > 0)
3099 int wid = FONT_WIDTH (f->output_data.w32->font);
3100 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
3102 else
3103 f->scroll_bar_cols = 2;
3105 /* Now make the frame display the given font. */
3106 if (FRAME_W32_WINDOW (f) != 0)
3108 frame_update_line_height (f);
3109 x_set_window_size (f, 0, f->width, f->height);
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);
3117 Lisp_Object lispy_name;
3119 lispy_name = build_string (fontname);
3121 return lispy_name;
3125 x_calc_absolute_position (f)
3126 struct frame *f;
3128 Window win, child;
3129 POINT pt;
3130 int flags = f->output_data.w32->size_hint_flags;
3132 pt.x = pt.y = 0;
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)
3138 BLOCK_INPUT;
3139 MapWindowPoints (FRAME_W32_WINDOW (f),
3140 f->output_data.w32->parent_desc,
3141 &pt, 1);
3142 UNBLOCK_INPUT;
3146 RECT rt;
3147 rt.left = rt.right = rt.top = rt.bottom = 0;
3149 BLOCK_INPUT;
3150 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
3151 FRAME_EXTERNAL_MENU_BAR (f));
3152 UNBLOCK_INPUT;
3154 pt.x += (rt.right - rt.left);
3155 pt.y += (rt.bottom - rt.top);
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);
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);
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. */
3183 x_set_offset (f, xoff, yoff, change_gravity)
3184 struct frame *f;
3185 register int xoff, yoff;
3186 int change_gravity;
3188 int modified_top, modified_left;
3190 if (change_gravity > 0)
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;
3201 x_calc_absolute_position (f);
3203 BLOCK_INPUT;
3204 x_wm_set_size_hint (f, (long) 0, 0);
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)
3212 modified_left += f->output_data.w32->border_width;
3213 modified_top += f->output_data.w32->border_width;
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;
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. */
3229 x_set_window_size (f, change_gravity, cols, rows)
3230 struct frame *f;
3231 int change_gravity;
3232 int cols, rows;
3234 int pixelwidth, pixelheight;
3236 BLOCK_INPUT;
3238 check_frame_size (f, &rows, &cols);
3239 f->output_data.w32->vertical_scroll_bar_extra
3240 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
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);
3248 f->output_data.w32->win_gravity = NorthWestGravity;
3249 x_wm_set_size_hint (f, (long) 0, 0);
3252 RECT rect;
3254 rect.left = rect.top = 0;
3255 rect.right = pixelwidth;
3256 rect.bottom = pixelheight;
3258 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
3259 FRAME_EXTERNAL_MENU_BAR (f));
3261 /* All windows have an extra pixel */
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);
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.
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;
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)
3289 f->phys_cursor_x = -1;
3290 f->phys_cursor_y = -1;
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);
3299 UNBLOCK_INPUT;
3302 /* Mouse warping. */
3304 void
3305 x_set_mouse_pixel_position (f, pix_x, pix_y)
3306 struct frame *f;
3307 int pix_x, pix_y;
3309 BLOCK_INPUT;
3311 pix_x += f->output_data.w32->left_pos;
3312 pix_y += f->output_data.w32->top_pos;
3314 SetCursorPos (pix_x, pix_y);
3316 UNBLOCK_INPUT;
3319 void
3320 x_set_mouse_position (f, x, y)
3321 struct frame *f;
3322 int x, y;
3324 int pix_x, pix_y;
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;
3329 if (pix_x < 0) pix_x = 0;
3330 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3332 if (pix_y < 0) pix_y = 0;
3333 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3335 x_set_mouse_pixel_position (f, pix_x, pix_y);
3338 /* focus shifting, raising and lowering. */
3340 x_focus_on_frame (f)
3341 struct frame *f;
3345 x_unfocus_frame (f)
3346 struct frame *f;
3350 /* Raise frame F. */
3352 x_raise_frame (f)
3353 struct frame *f;
3355 // if (f->async_visible)
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;
3366 /* Lower frame F. */
3368 x_lower_frame (f)
3369 struct frame *f;
3371 // if (f->async_visible)
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;
3382 static void
3383 w32_frame_raise_lower (f, raise)
3384 FRAME_PTR f;
3385 int raise;
3387 if (raise)
3388 x_raise_frame (f);
3389 else
3390 x_lower_frame (f);
3393 /* Change of visibility. */
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. */
3402 x_make_frame_visible (f)
3403 struct frame *f;
3405 BLOCK_INPUT;
3407 if (! FRAME_VISIBLE_P (f))
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)
3416 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
3417 // SetForegroundWindow (FRAME_W32_WINDOW (f));
3420 f->output_data.w32->asked_for_visible = 1;
3422 my_show_window (FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
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. */
3429 Lisp_Object frame;
3430 int count = input_signal_count;
3432 /* This must come after we set COUNT. */
3433 UNBLOCK_INPUT;
3435 XSETFRAME (frame, f);
3437 while (1)
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 ())
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 ();
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;
3466 FRAME_SAMPLE_VISIBILITY (f);
3470 /* Change from mapped state to withdrawn state. */
3472 /* Make the frame visible (mapped and not iconified). */
3474 x_make_frame_invisible (f)
3475 struct frame *f;
3477 Window window;
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;
3483 BLOCK_INPUT;
3485 my_show_window (FRAME_W32_WINDOW (f), SW_HIDE);
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;
3497 UNBLOCK_INPUT;
3500 /* Change window state from mapped to iconified. */
3502 void
3503 x_iconify_frame (f)
3504 struct frame *f;
3506 int result;
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;
3512 if (f->async_iconified)
3513 return;
3515 BLOCK_INPUT;
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);
3521 f->async_iconified = 1;
3523 UNBLOCK_INPUT;
3526 /* Destroy the window of frame F. */
3528 x_destroy_window (f)
3529 struct frame *f;
3531 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3533 BLOCK_INPUT;
3535 my_destroy_window (f, FRAME_W32_WINDOW (f));
3536 free_frame_menubar (f);
3537 free_frame_faces (f);
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;
3548 dpyinfo->reference_count--;
3550 if (f == dpyinfo->mouse_face_mouse_frame)
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;
3559 UNBLOCK_INPUT;
3562 /* Setting window manager hints. */
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). */
3570 x_wm_set_size_hint (f, flags, user_position)
3571 struct frame *f;
3572 long flags;
3573 int user_position;
3575 Window window = FRAME_W32_WINDOW (f);
3577 flexlines = f->height;
3579 enter_crit ();
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);
3584 leave_crit ();
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;
3592 #if 0
3593 Window window = FRAME_W32_WINDOW (f);
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;
3599 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
3600 #endif
3604 /* Initialization. */
3606 #ifdef USE_X_TOOLKIT
3607 static XrmOptionDescRec emacs_options[] = {
3608 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
3609 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
3611 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3612 XrmoptionSepArg, NULL},
3613 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
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}
3623 #endif /* USE_X_TOOLKIT */
3625 static int w32_initialized = 0;
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;
3633 Lisp_Object frame;
3634 char *defaultvalue;
3635 struct w32_display_info *dpyinfo;
3636 HDC hdc;
3638 BLOCK_INPUT;
3640 if (!w32_initialized)
3642 w32_initialize ();
3643 w32_initialized = 1;
3647 int argc = 0;
3648 char *argv[3];
3650 argv[0] = "";
3651 argc = 1;
3652 if (xrm_option)
3654 argv[argc++] = "-xrm";
3655 argv[argc++] = xrm_option;
3659 dpyinfo = &one_w32_display_info;
3661 /* Put this display on the chain. */
3662 dpyinfo->next = NULL;
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;
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);
3676 #if 0
3677 xrdb = x_load_resources (dpyinfo->display, xrm_option,
3678 resource_name, EMACS_CLASS);
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 ());
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;
3713 ReleaseDC (GetDesktopWindow (), hdc);
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));
3720 /* initialise palette with white and black */
3722 COLORREF color;
3723 defined_color (0, "white", &color, 1);
3724 defined_color (0, "black", &color, 1);
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 */
3738 #ifdef SIGIO
3739 if (interrupt_input)
3740 init_sigio (connection);
3741 #endif /* ! defined (SIGIO) */
3743 UNBLOCK_INPUT;
3745 return dpyinfo;
3748 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3750 void
3751 x_delete_display (dpyinfo)
3752 struct w32_display_info *dpyinfo;
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
3761 Lisp_Object tail;
3763 tail = w32_display_name_list;
3764 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
3766 if (EQ (XCONS (XCONS (tail)->cdr)->car,
3767 dpyinfo->name_list_element))
3769 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
3770 break;
3772 tail = XCONS (tail)->cdr;
3776 /* free palette table */
3778 struct w32_palette_entry * plist;
3780 plist = dpyinfo->color_list;
3781 while (plist)
3783 struct w32_palette_entry * pentry = plist;
3784 plist = plist->next;
3785 xfree(pentry);
3787 dpyinfo->color_list = NULL;
3788 if (dpyinfo->palette)
3789 DeleteObject(dpyinfo->palette);
3791 xfree (dpyinfo->font_table);
3792 xfree (dpyinfo->w32_id_name);
3795 /* Set up use of W32. */
3797 DWORD windows_msg_worker ();
3799 w32_initialize ()
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;
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;
3834 /* Try to use interrupt input; if we can't, then start polling. */
3835 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3837 /* Create the window thread - it will terminate itself or when the app terminates */
3839 init_crit ();
3841 dwMainThreadId = GetCurrentThreadId ();
3842 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3843 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
3845 /* Wait for thread to start */
3848 MSG msg;
3850 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
3852 hWindowsThread = CreateThread (NULL, 0,
3853 (LPTHREAD_START_ROUTINE) windows_msg_worker,
3854 0, 0, &dwWindowsThreadId);
3856 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
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
3872 void
3873 syms_of_w32term ()
3875 staticpro (&w32_display_name_list);
3876 w32_display_name_list = Qnil;
3878 staticpro (&last_mouse_scroll_bar);
3879 last_mouse_scroll_bar = Qnil;
3881 staticpro (&Qvendor_specific_keysyms);
3882 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
3884 DEFVAR_INT ("w32-num-mouse-buttons",
3885 &Vw32_num_mouse_buttons,
3886 "Number of physical mouse buttons.");
3887 Vw32_num_mouse_buttons = Qnil;
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;