(display_text_line): Handle the case of point being in
[emacs.git] / src / w32term.c
blob3b147b91a298e5eabc964635cc2259fdfe716ae3
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 BLOCK_INPUT;
664 do_line_dance ();
666 /* Notice if the cursor will be cleared by this operation. */
667 if (curs_y == f->phys_cursor_y
668 && curs_x <= f->phys_cursor_x
669 && f->phys_cursor_x < first_unused)
670 f->phys_cursor_x = -1;
672 w32_clear_area (f, NULL,
673 CHAR_TO_PIXEL_COL (f, curs_x),
674 CHAR_TO_PIXEL_ROW (f, curs_y),
675 FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
676 f->output_data.w32->line_height);
678 UNBLOCK_INPUT;
681 static
682 w32_clear_frame ()
684 struct frame *f = updating_frame;
686 if (f == 0)
687 f = selected_frame;
689 f->phys_cursor_x = -1; /* Cursor not visible. */
690 curs_x = 0; /* Nominal cursor position is top left. */
691 curs_y = 0;
693 BLOCK_INPUT;
695 w32_clear_window (f);
697 /* We have to clear the scroll bars, too. If we have changed
698 colors or something like that, then they should be notified. */
699 x_scroll_bar_clear (f);
701 UNBLOCK_INPUT;
704 /* Make audible bell. */
706 w32_ring_bell ()
708 BLOCK_INPUT;
710 if (visible_bell)
711 FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
712 else
713 w32_sys_ring_bell ();
715 UNBLOCK_INPUT;
717 return 1;
720 /* Insert and delete character.
721 These are not supposed to be used because we are supposed to turn
722 off the feature of using them. */
724 static
725 w32_insert_glyphs (start, len)
726 register char *start;
727 register int len;
729 abort ();
732 static
733 w32_delete_glyphs (n)
734 register int n;
736 abort ();
739 /* Specify how many text lines, from the top of the window,
740 should be affected by insert-lines and delete-lines operations.
741 This, and those operations, are used only within an update
742 that is bounded by calls to w32_update_begin and w32_update_end. */
744 static
745 w32_set_terminal_window (n)
746 register int n;
748 if (updating_frame == 0)
749 abort ();
751 if ((n <= 0) || (n > updating_frame->height))
752 flexlines = updating_frame->height;
753 else
754 flexlines = n;
757 /* These variables need not be per frame
758 because redisplay is done on a frame-by-frame basis
759 and the line dance for one frame is finished before
760 anything is done for another frame. */
762 /* Array of line numbers from cached insert/delete operations.
763 line_dance[i] is the old position of the line that we want
764 to move to line i, or -1 if we want a blank line there. */
765 static int *line_dance;
767 /* Allocated length of that array. */
768 static int line_dance_len;
770 /* Flag indicating whether we've done any work. */
771 static int line_dance_in_progress;
773 /* Perform an insert-lines or delete-lines operation,
774 inserting N lines or deleting -N lines at vertical position VPOS. */
775 w32_ins_del_lines (vpos, n)
776 int vpos, n;
778 register int fence, i;
780 if (vpos >= flexlines)
781 return 1;
783 if (!line_dance_in_progress)
785 int ht = updating_frame->height;
786 if (ht > line_dance_len)
788 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
789 line_dance_len = ht;
791 for (i = 0; i < ht; ++i) line_dance[i] = i;
792 line_dance_in_progress = 1;
794 if (n >= 0)
796 if (n > flexlines - vpos)
797 n = flexlines - vpos;
798 fence = vpos + n;
799 for (i = flexlines; --i >= fence;)
800 line_dance[i] = line_dance[i-n];
801 for (i = fence; --i >= vpos;)
802 line_dance[i] = -1;
804 else
806 n = -n;
807 if (n > flexlines - vpos)
808 n = flexlines - vpos;
809 fence = flexlines - n;
810 for (i = vpos; i < fence; ++i)
811 line_dance[i] = line_dance[i + n];
812 for (i = fence; i < flexlines; ++i)
813 line_dance[i] = -1;
817 /* Here's where we actually move the pixels around.
818 Must be called with input blocked. */
819 static void
820 do_line_dance ()
822 register int i, j, distance;
823 register struct frame *f;
824 int ht;
825 int intborder;
826 HDC hdc;
828 /* Must check this flag first. If it's not set, then not only is the
829 array uninitialized, but we might not even have a frame. */
830 if (!line_dance_in_progress)
831 return;
833 f = updating_frame;
834 if (f == 0)
835 abort ();
837 ht = f->height;
838 intborder = f->output_data.w32->internal_border_width;
840 x_display_cursor (updating_frame, 0);
842 hdc = get_frame_dc (f);
844 for (i = 0; i < ht; ++i)
845 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
847 for (j = i; (j < ht && line_dance[j] != -1
848 && line_dance[j]-j == distance); ++j);
849 /* Copy [i,j) upward from [i+distance, j+distance) */
850 BitBlt (hdc,
851 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
852 f->width * FONT_WIDTH (f->output_data.w32->font),
853 (j-i) * f->output_data.w32->line_height,
854 hdc,
855 intborder, CHAR_TO_PIXEL_ROW (f, i),
856 SRCCOPY);
857 i = j-1;
860 for (i = ht; --i >=0; )
861 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
863 for (j = i; (--j >= 0 && line_dance[j] != -1
864 && line_dance[j]-j == distance););
865 /* Copy (j, i] downward from (j+distance, i+distance] */
866 BitBlt (hdc,
867 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
868 f->width * FONT_WIDTH (f->output_data.w32->font),
869 (i-j) * f->output_data.w32->line_height,
870 hdc,
871 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
872 SRCCOPY);
873 i = j+1;
876 release_frame_dc (f, hdc);
878 for (i = 0; i < ht; ++i)
879 if (line_dance[i] == -1)
881 for (j = i; j < ht && line_dance[j] == -1; ++j);
882 /* Clear [i,j) */
883 w32_clear_area (f, NULL,
884 intborder,
885 CHAR_TO_PIXEL_ROW (f, i),
886 f->width * FONT_WIDTH (f->output_data.w32->font),
887 (j-i) * f->output_data.w32->line_height);
888 i = j-1;
890 line_dance_in_progress = 0;
893 /* Support routines for exposure events. */
894 static void clear_cursor ();
896 /* Output into a rectangle of a window (for frame F)
897 the characters in f->phys_lines that overlap that rectangle.
898 TOP and LEFT are the position of the upper left corner of the rectangle.
899 ROWS and COLS are the size of the rectangle.
900 Call this function with input blocked. */
902 void
903 dumprectangle (f, left, top, cols, rows)
904 struct frame *f;
905 register int left, top, cols, rows;
907 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
908 int cursor_cleared = 0;
909 int bottom, right;
910 register int y;
912 if (FRAME_GARBAGED_P (f))
913 return;
915 /* Express rectangle as four edges, instead of position-and-size. */
916 bottom = top + rows;
917 right = left + cols;
919 /* Convert rectangle edges in pixels to edges in chars.
920 Round down for left and top, up for right and bottom. */
921 top = PIXEL_TO_CHAR_ROW (f, top);
922 left = PIXEL_TO_CHAR_COL (f, left);
923 bottom += (f->output_data.w32->line_height - 1);
924 right += (FONT_WIDTH (f->output_data.w32->font) - 1);
925 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
926 right = PIXEL_TO_CHAR_COL (f, right);
928 /* Clip the rectangle to what can be visible. */
929 if (left < 0)
930 left = 0;
931 if (top < 0)
932 top = 0;
933 if (right > f->width)
934 right = f->width;
935 if (bottom > f->height)
936 bottom = f->height;
938 /* Get size in chars of the rectangle. */
939 cols = right - left;
940 rows = bottom - top;
942 /* If rectangle has zero area, return. */
943 if (rows <= 0) return;
944 if (cols <= 0) return;
946 /* Turn off the cursor if it is in the rectangle.
947 We will turn it back on afterward. */
948 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
949 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
951 clear_cursor (f);
952 cursor_cleared = 1;
955 /* Display the text in the rectangle, one text line at a time. */
957 for (y = top; y < bottom; y++)
959 GLYPH *line = &active_frame->glyphs[y][left];
961 if (! active_frame->enable[y] || left > active_frame->used[y])
962 continue;
964 dumpglyphs (f,
965 CHAR_TO_PIXEL_COL (f, left),
966 CHAR_TO_PIXEL_ROW (f, y),
967 line, min (cols, active_frame->used[y] - left),
968 active_frame->highlight[y], 0);
971 /* Turn the cursor on if we turned it off. */
973 if (cursor_cleared)
974 x_display_cursor (f, 1);
977 static void
978 frame_highlight (f)
979 struct frame *f;
981 x_display_cursor (f, 1);
984 static void
985 frame_unhighlight (f)
986 struct frame *f;
988 x_display_cursor (f, 1);
991 static void w32_frame_rehighlight ();
992 static void x_frame_rehighlight ();
994 /* The focus has changed. Update the frames as necessary to reflect
995 the new situation. Note that we can't change the selected frame
996 here, because the Lisp code we are interrupting might become confused.
997 Each event gets marked with the frame in which it occurred, so the
998 Lisp code can tell when the switch took place by examining the events. */
1000 void
1001 x_new_focus_frame (dpyinfo, frame)
1002 struct w32_display_info *dpyinfo;
1003 struct frame *frame;
1005 struct frame *old_focus = dpyinfo->w32_focus_frame;
1006 int events_enqueued = 0;
1008 if (frame != dpyinfo->w32_focus_frame)
1010 /* Set this before calling other routines, so that they see
1011 the correct value of w32_focus_frame. */
1012 dpyinfo->w32_focus_frame = frame;
1014 if (old_focus && old_focus->auto_lower)
1015 x_lower_frame (old_focus);
1017 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
1018 pending_autoraise_frame = dpyinfo->w32_focus_frame;
1019 else
1020 pending_autoraise_frame = 0;
1023 x_frame_rehighlight (dpyinfo);
1026 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1028 void
1029 x_mouse_leave (dpyinfo)
1030 struct w32_display_info *dpyinfo;
1032 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
1035 /* The focus has changed, or we have redirected a frame's focus to
1036 another frame (this happens when a frame uses a surrogate
1037 minibuffer frame). Shift the highlight as appropriate.
1039 The FRAME argument doesn't necessarily have anything to do with which
1040 frame is being highlighted or unhighlighted; we only use it to find
1041 the appropriate display info. */
1042 static void
1043 w32_frame_rehighlight (frame)
1044 struct frame *frame;
1046 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
1049 static void
1050 x_frame_rehighlight (dpyinfo)
1051 struct w32_display_info *dpyinfo;
1053 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
1055 if (dpyinfo->w32_focus_frame)
1057 dpyinfo->w32_highlight_frame
1058 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
1059 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
1060 : dpyinfo->w32_focus_frame);
1061 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
1063 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
1064 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
1067 else
1068 dpyinfo->w32_highlight_frame = 0;
1070 if (dpyinfo->w32_highlight_frame != old_highlight)
1072 if (old_highlight)
1073 frame_unhighlight (old_highlight);
1074 if (dpyinfo->w32_highlight_frame)
1075 frame_highlight (dpyinfo->w32_highlight_frame);
1079 /* Keyboard processing - modifier keys, etc. */
1081 /* Convert a keysym to its name. */
1083 char *
1084 x_get_keysym_name (keysym)
1085 int keysym;
1087 /* Make static so we can always return it */
1088 static char value[100];
1090 BLOCK_INPUT;
1091 GetKeyNameText(keysym, value, 100);
1092 UNBLOCK_INPUT;
1094 return value;
1097 /* Mouse clicks and mouse movement. Rah. */
1099 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1100 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1101 that the glyph at X, Y occupies, if BOUNDS != 0.
1102 If NOCLIP is nonzero, do not force the value into range. */
1104 void
1105 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1106 FRAME_PTR f;
1107 register int pix_x, pix_y;
1108 register int *x, *y;
1109 RECT *bounds;
1110 int noclip;
1112 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1113 if (NILP (Vwindow_system))
1115 *x = pix_x;
1116 *y = pix_y;
1117 return;
1120 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1121 even for negative values. */
1122 if (pix_x < 0)
1123 pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
1124 if (pix_y < 0)
1125 pix_y -= (f)->output_data.w32->line_height - 1;
1127 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1128 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1130 if (bounds)
1132 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
1133 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
1134 bounds->right = bounds->left + FONT_WIDTH (f->output_data.w32->font) - 1;
1135 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
1138 if (!noclip)
1140 if (pix_x < 0)
1141 pix_x = 0;
1142 else if (pix_x > f->width)
1143 pix_x = f->width;
1145 if (pix_y < 0)
1146 pix_y = 0;
1147 else if (pix_y > f->height)
1148 pix_y = f->height;
1151 *x = pix_x;
1152 *y = pix_y;
1155 void
1156 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1157 FRAME_PTR f;
1158 register int x, y;
1159 register int *pix_x, *pix_y;
1161 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1162 if (NILP (Vwindow_system))
1164 *pix_x = x;
1165 *pix_y = y;
1166 return;
1169 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1170 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1173 BOOL
1174 parse_button (message, pbutton, pup)
1175 int message;
1176 int * pbutton;
1177 int * pup;
1179 int button = 0;
1180 int up = 0;
1182 switch (message)
1184 case WM_LBUTTONDOWN:
1185 button = 0;
1186 up = 0;
1187 break;
1188 case WM_LBUTTONUP:
1189 button = 0;
1190 up = 1;
1191 break;
1192 case WM_MBUTTONDOWN:
1193 if (NILP (Vw32_swap_mouse_buttons))
1194 button = 1;
1195 else
1196 button = 2;
1197 up = 0;
1198 break;
1199 case WM_MBUTTONUP:
1200 if (NILP (Vw32_swap_mouse_buttons))
1201 button = 1;
1202 else
1203 button = 2;
1204 up = 1;
1205 break;
1206 case WM_RBUTTONDOWN:
1207 if (NILP (Vw32_swap_mouse_buttons))
1208 button = 2;
1209 else
1210 button = 1;
1211 up = 0;
1212 break;
1213 case WM_RBUTTONUP:
1214 if (NILP (Vw32_swap_mouse_buttons))
1215 button = 2;
1216 else
1217 button = 1;
1218 up = 1;
1219 break;
1220 default:
1221 return (FALSE);
1224 if (pup) *pup = up;
1225 if (pbutton) *pbutton = button;
1227 return (TRUE);
1231 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1233 If the event is a button press, then note that we have grabbed
1234 the mouse. */
1236 static void
1237 construct_mouse_click (result, msg, f)
1238 struct input_event *result;
1239 W32Msg *msg;
1240 struct frame *f;
1242 int button;
1243 int up;
1245 parse_button (msg->msg.message, &button, &up);
1247 /* Make the event type no_event; we'll change that when we decide
1248 otherwise. */
1249 result->kind = mouse_click;
1250 result->code = button;
1251 result->timestamp = msg->msg.time;
1252 result->modifiers = (msg->dwModifiers
1253 | (up
1254 ? up_modifier
1255 : down_modifier));
1258 int row, column;
1260 XSETINT (result->x, LOWORD (msg->msg.lParam));
1261 XSETINT (result->y, HIWORD (msg->msg.lParam));
1262 XSETFRAME (result->frame_or_window, f);
1267 /* Function to report a mouse movement to the mainstream Emacs code.
1268 The input handler calls this.
1270 We have received a mouse movement event, which is given in *event.
1271 If the mouse is over a different glyph than it was last time, tell
1272 the mainstream emacs code by setting mouse_moved. If not, ask for
1273 another motion event, so we can check again the next time it moves. */
1275 static void
1276 note_mouse_movement (frame, msg)
1277 FRAME_PTR frame;
1278 MSG *msg;
1280 last_mouse_movement_time = msg->time;
1282 if (msg->hwnd != FRAME_W32_WINDOW (frame))
1284 frame->mouse_moved = 1;
1285 last_mouse_scroll_bar = Qnil;
1287 note_mouse_highlight (frame, -1, -1);
1290 /* Has the mouse moved off the glyph it was on at the last sighting? */
1291 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
1292 || LOWORD (msg->lParam) > last_mouse_glyph.right
1293 || HIWORD (msg->lParam) < last_mouse_glyph.top
1294 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
1296 frame->mouse_moved = 1;
1297 last_mouse_scroll_bar = Qnil;
1299 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
1303 /* This is used for debugging, to turn off note_mouse_highlight. */
1304 static int disable_mouse_highlight;
1306 /* Take proper action when the mouse has moved to position X, Y on frame F
1307 as regards highlighting characters that have mouse-face properties.
1308 Also dehighlighting chars where the mouse was before.
1309 X and Y can be negative or out of range. */
1311 static void
1312 note_mouse_highlight (f, x, y)
1313 FRAME_PTR f;
1314 int x, y;
1316 int row, column, portion;
1317 RECT new_glyph;
1318 Lisp_Object window;
1319 struct window *w;
1321 if (disable_mouse_highlight)
1322 return;
1324 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1325 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1326 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
1328 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
1329 return;
1331 if (gc_in_progress)
1333 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1334 return;
1337 /* Find out which glyph the mouse is on. */
1338 pixel_to_glyph_coords (f, x, y, &column, &row,
1339 &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
1341 /* Which window is that in? */
1342 window = window_from_coordinates (f, column, row, &portion);
1343 w = XWINDOW (window);
1345 /* If we were displaying active text in another window, clear that. */
1346 if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
1347 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1349 /* Are we in a window whose display is up to date?
1350 And verify the buffer's text has not changed. */
1351 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1352 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1353 && EQ (w->window_end_valid, w->buffer)
1354 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
1355 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
1357 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1358 int i, pos;
1360 /* Find which buffer position the mouse corresponds to. */
1361 for (i = column; i >= 0; i--)
1362 if (ptr[i] > 0)
1363 break;
1364 pos = ptr[i];
1365 /* Is it outside the displayed active region (if any)? */
1366 if (pos <= 0)
1367 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1368 else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
1369 && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1370 && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1371 && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1372 || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
1373 && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1374 || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
1375 || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
1377 Lisp_Object mouse_face, overlay, position;
1378 Lisp_Object *overlay_vec;
1379 int len, noverlays, ignor1;
1380 struct buffer *obuf;
1381 int obegv, ozv;
1383 /* If we get an out-of-range value, return now; avoid an error. */
1384 if (pos > BUF_Z (XBUFFER (w->buffer)))
1385 return;
1387 /* Make the window's buffer temporarily current for
1388 overlays_at and compute_char_face. */
1389 obuf = current_buffer;
1390 current_buffer = XBUFFER (w->buffer);
1391 obegv = BEGV;
1392 ozv = ZV;
1393 BEGV = BEG;
1394 ZV = Z;
1396 /* Yes. Clear the display of the old active region, if any. */
1397 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
1399 /* Is this char mouse-active? */
1400 XSETINT (position, pos);
1402 len = 10;
1403 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1405 /* Put all the overlays we want in a vector in overlay_vec.
1406 Store the length in len. */
1407 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1408 NULL, NULL);
1409 noverlays = sort_overlays (overlay_vec, noverlays, w);
1411 /* Find the highest priority overlay that has a mouse-face prop. */
1412 overlay = Qnil;
1413 for (i = 0; i < noverlays; i++)
1415 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1416 if (!NILP (mouse_face))
1418 overlay = overlay_vec[i];
1419 break;
1422 free (overlay_vec);
1423 /* If no overlay applies, get a text property. */
1424 if (NILP (overlay))
1425 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1427 /* Handle the overlay case. */
1428 if (! NILP (overlay))
1430 /* Find the range of text around this char that
1431 should be active. */
1432 Lisp_Object before, after;
1433 int ignore;
1435 before = Foverlay_start (overlay);
1436 after = Foverlay_end (overlay);
1437 /* Record this as the current active region. */
1438 fast_find_position (window, before,
1439 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
1440 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
1441 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
1442 = !fast_find_position (window, after,
1443 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
1444 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
1445 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
1446 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
1447 = compute_char_face (f, w, pos, 0, 0,
1448 &ignore, pos + 1, 1);
1450 /* Display it as active. */
1451 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1453 /* Handle the text property case. */
1454 else if (! NILP (mouse_face))
1456 /* Find the range of text around this char that
1457 should be active. */
1458 Lisp_Object before, after, beginning, end;
1459 int ignore;
1461 beginning = Fmarker_position (w->start);
1462 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1463 - XFASTINT (w->window_end_pos)));
1464 before
1465 = Fprevious_single_property_change (make_number (pos + 1),
1466 Qmouse_face,
1467 w->buffer, beginning);
1468 after
1469 = Fnext_single_property_change (position, Qmouse_face,
1470 w->buffer, end);
1471 /* Record this as the current active region. */
1472 fast_find_position (window, before,
1473 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
1474 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
1475 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
1476 = !fast_find_position (window, after,
1477 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
1478 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
1479 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
1480 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
1481 = compute_char_face (f, w, pos, 0, 0,
1482 &ignore, pos + 1, 1);
1484 /* Display it as active. */
1485 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
1487 BEGV = obegv;
1488 ZV = ozv;
1489 current_buffer = obuf;
1494 /* Find the row and column of position POS in window WINDOW.
1495 Store them in *COLUMNP and *ROWP.
1496 This assumes display in WINDOW is up to date.
1497 If POS is above start of WINDOW, return coords
1498 of start of first screen line.
1499 If POS is after end of WINDOW, return coords of end of last screen line.
1501 Value is 1 if POS is in range, 0 if it was off screen. */
1503 static int
1504 fast_find_position (window, pos, columnp, rowp)
1505 Lisp_Object window;
1506 int pos;
1507 int *columnp, *rowp;
1509 struct window *w = XWINDOW (window);
1510 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1511 int i;
1512 int row = 0;
1513 int left = WINDOW_LEFT_MARGIN (w);
1514 int top = w->top;
1515 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
1516 int width = window_internal_width (w);
1517 int *charstarts;
1518 int lastcol;
1519 int maybe_next_line = 0;
1521 /* Find the right row. */
1522 for (i = 0;
1523 i < height;
1524 i++)
1526 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
1527 if (linestart > pos)
1528 break;
1529 /* If the position sought is the end of the buffer,
1530 don't include the blank lines at the bottom of the window. */
1531 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
1533 maybe_next_line = 1;
1534 break;
1536 if (linestart > 0)
1537 row = i;
1540 /* Find the right column with in it. */
1541 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
1542 lastcol = left;
1543 for (i = 0; i < width; i++)
1545 if (charstarts[left + i] == pos)
1547 *rowp = row + top;
1548 *columnp = i + left;
1549 return 1;
1551 else if (charstarts[left + i] > pos)
1552 break;
1553 else if (charstarts[left + i] > 0)
1554 lastcol = left + i;
1557 /* If we're looking for the end of the buffer,
1558 and we didn't find it in the line we scanned,
1559 use the start of the following line. */
1560 if (maybe_next_line)
1562 row++;
1563 i = 0;
1566 *rowp = row + top;
1567 *columnp = lastcol;
1568 return 0;
1571 /* Display the active region described by mouse_face_*
1572 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1574 static void
1575 show_mouse_face (dpyinfo, hl)
1576 struct w32_display_info *dpyinfo;
1577 int hl;
1579 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1580 int width = window_internal_width (w);
1581 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1582 int i;
1583 int cursor_off = 0;
1584 int old_curs_x = curs_x;
1585 int old_curs_y = curs_y;
1587 /* Set these variables temporarily
1588 so that if we have to turn the cursor off and on again
1589 we will put it back at the same place. */
1590 curs_x = f->phys_cursor_x;
1591 curs_y = f->phys_cursor_y;
1593 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
1594 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
1596 int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
1597 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
1598 : WINDOW_LEFT_MARGIN (w));
1599 int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
1600 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
1601 : WINDOW_LEFT_MARGIN (w) + width);
1602 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
1604 /* If the cursor's in the text we are about to rewrite,
1605 turn the cursor off. */
1606 if (i == curs_y
1607 && curs_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col - 1
1608 && curs_x <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col)
1610 x_display_cursor (f, 0);
1611 cursor_off = 1;
1614 dumpglyphs (f,
1615 CHAR_TO_PIXEL_COL (f, column),
1616 CHAR_TO_PIXEL_ROW (f, i),
1617 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
1618 endcolumn - column,
1619 /* Highlight with mouse face if hl > 0. */
1620 hl > 0 ? 3 : 0, 0);
1623 /* If we turned the cursor off, turn it back on. */
1624 if (cursor_off)
1625 x_display_cursor (f, 1);
1627 curs_x = old_curs_x;
1628 curs_y = old_curs_y;
1630 /* Change the mouse cursor according to the value of HL. */
1631 if (hl > 0)
1632 SetCursor (f->output_data.w32->cross_cursor);
1633 else
1634 SetCursor (f->output_data.w32->text_cursor);
1637 /* Clear out the mouse-highlighted active region.
1638 Redraw it unhighlighted first. */
1640 static void
1641 clear_mouse_face (dpyinfo)
1642 struct w32_display_info *dpyinfo;
1644 if (! NILP (dpyinfo->mouse_face_window))
1645 show_mouse_face (dpyinfo, 0);
1647 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1648 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1649 dpyinfo->mouse_face_window = Qnil;
1652 struct scroll_bar *x_window_to_scroll_bar ();
1653 static void x_scroll_bar_report_motion ();
1655 /* Return the current position of the mouse.
1656 *fp should be a frame which indicates which display to ask about.
1658 If the mouse movement started in a scroll bar, set *fp, *bar_window,
1659 and *part to the frame, window, and scroll bar part that the mouse
1660 is over. Set *x and *y to the portion and whole of the mouse's
1661 position on the scroll bar.
1663 If the mouse movement started elsewhere, set *fp to the frame the
1664 mouse is on, *bar_window to nil, and *x and *y to the character cell
1665 the mouse is over.
1667 Set *time to the server timestamp for the time at which the mouse
1668 was at this position.
1670 Don't store anything if we don't have a valid set of values to report.
1672 This clears the mouse_moved flag, so we can wait for the next mouse
1673 movement. This also calls XQueryPointer, which will cause the
1674 server to give us another MotionNotify when the mouse moves
1675 again. */
1677 static void
1678 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
1679 FRAME_PTR *fp;
1680 int insist;
1681 Lisp_Object *bar_window;
1682 enum scroll_bar_part *part;
1683 Lisp_Object *x, *y;
1684 unsigned long *time;
1686 FRAME_PTR f1;
1688 BLOCK_INPUT;
1690 if (! NILP (last_mouse_scroll_bar))
1691 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
1692 else
1694 POINT pt;
1696 Lisp_Object frame, tail;
1698 /* Clear the mouse-moved flag for every frame on this display. */
1699 FOR_EACH_FRAME (tail, frame)
1700 XFRAME (frame)->mouse_moved = 0;
1702 last_mouse_scroll_bar = Qnil;
1704 GetCursorPos (&pt);
1706 /* Now we have a position on the root; find the innermost window
1707 containing the pointer. */
1709 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
1710 && FRAME_LIVE_P (last_mouse_frame))
1712 f1 = last_mouse_frame;
1714 else
1716 /* Is win one of our frames? */
1717 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
1720 /* If not, is it one of our scroll bars? */
1721 if (! f1)
1723 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
1725 if (bar)
1727 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1731 if (f1 == 0 && insist)
1732 f1 = selected_frame;
1734 if (f1)
1736 int ignore1, ignore2;
1738 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
1740 /* Ok, we found a frame. Store all the values. */
1742 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
1743 &last_mouse_glyph,
1744 FRAME_W32_DISPLAY_INFO (f1)->grabbed
1745 || insist);
1747 *bar_window = Qnil;
1748 *part = 0;
1749 *fp = f1;
1750 XSETINT (*x, pt.x);
1751 XSETINT (*y, pt.y);
1752 *time = last_mouse_movement_time;
1757 UNBLOCK_INPUT;
1760 /* Scroll bar support. */
1762 /* Given an window ID, find the struct scroll_bar which manages it.
1763 This can be called in GC, so we have to make sure to strip off mark
1764 bits. */
1765 struct scroll_bar *
1766 x_window_to_scroll_bar (window_id)
1767 Window window_id;
1769 Lisp_Object tail, frame;
1771 for (tail = Vframe_list;
1772 XGCTYPE (tail) == Lisp_Cons;
1773 tail = XCONS (tail)->cdr)
1775 Lisp_Object frame, bar, condemned;
1777 frame = XCONS (tail)->car;
1778 /* All elements of Vframe_list should be frames. */
1779 if (! GC_FRAMEP (frame))
1780 abort ();
1782 /* Scan this frame's scroll bar list for a scroll bar with the
1783 right window ID. */
1784 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1785 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1786 /* This trick allows us to search both the ordinary and
1787 condemned scroll bar lists with one loop. */
1788 ! GC_NILP (bar) || (bar = condemned,
1789 condemned = Qnil,
1790 ! GC_NILP (bar));
1791 bar = XSCROLL_BAR (bar)->next)
1792 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
1793 return XSCROLL_BAR (bar);
1796 return 0;
1799 HWND
1800 my_create_scrollbar (f, bar)
1801 struct frame * f;
1802 struct scroll_bar * bar;
1804 MSG msg;
1806 PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
1807 (LPARAM) bar);
1808 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
1810 return ((HWND) msg.wParam);
1813 //#define ATTACH_THREADS
1815 void
1816 my_show_window (HWND hwnd, int how)
1818 #ifndef ATTACH_THREADS
1819 SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0);
1820 #else
1821 ShowWindow (hwnd , how);
1822 #endif
1825 void
1826 my_set_window_pos (HWND hwnd, HWND hwndAfter,
1827 int x, int y, int cx, int cy, int flags)
1829 #ifndef ATTACH_THREADS
1830 W32WindowPos pos;
1831 pos.hwndAfter = hwndAfter;
1832 pos.x = x;
1833 pos.y = y;
1834 pos.cx = cx;
1835 pos.cy = cy;
1836 pos.flags = flags;
1837 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
1838 #else
1839 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
1840 #endif
1843 void
1844 my_destroy_window (f, hwnd)
1845 struct frame * f;
1846 HWND hwnd;
1848 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
1849 (WPARAM) hwnd, 0);
1852 /* Open a new window to serve as a scroll bar, and return the
1853 scroll bar vector for it. */
1854 static struct scroll_bar *
1855 x_scroll_bar_create (window, top, left, width, height)
1856 struct window *window;
1857 int top, left, width, height;
1859 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1860 struct scroll_bar *bar
1861 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1862 HWND hwnd;
1864 BLOCK_INPUT;
1866 XSETWINDOW (bar->window, window);
1867 XSETINT (bar->top, top);
1868 XSETINT (bar->left, left);
1869 XSETINT (bar->width, width);
1870 XSETINT (bar->height, height);
1871 XSETINT (bar->start, 0);
1872 XSETINT (bar->end, 0);
1873 bar->dragging = Qnil;
1875 /* Requires geometry to be set before call to create the real window */
1877 hwnd = my_create_scrollbar (f, bar);
1879 SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
1880 SetScrollPos (hwnd, SB_CTL, 0, TRUE);
1882 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
1884 /* Add bar to its frame's list of scroll bars. */
1885 bar->next = FRAME_SCROLL_BARS (f);
1886 bar->prev = Qnil;
1887 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
1888 if (! NILP (bar->next))
1889 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
1891 UNBLOCK_INPUT;
1893 return bar;
1896 /* Draw BAR's handle in the proper position.
1897 If the handle is already drawn from START to END, don't bother
1898 redrawing it, unless REBUILD is non-zero; in that case, always
1899 redraw it. (REBUILD is handy for drawing the handle after expose
1900 events.)
1902 Normally, we want to constrain the start and end of the handle to
1903 fit inside its rectangle, but if the user is dragging the scroll bar
1904 handle, we want to let them drag it down all the way, so that the
1905 bar's top is as far down as it goes; otherwise, there's no way to
1906 move to the very end of the buffer. */
1907 static void
1908 x_scroll_bar_set_handle (bar, start, end, rebuild)
1909 struct scroll_bar *bar;
1910 int start, end;
1911 int rebuild;
1913 int dragging = ! NILP (bar->dragging);
1914 Window w = SCROLL_BAR_W32_WINDOW (bar);
1915 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1917 /* If the display is already accurate, do nothing. */
1918 if (! rebuild
1919 && start == XINT (bar->start)
1920 && end == XINT (bar->end))
1921 return;
1923 BLOCK_INPUT;
1925 /* Store the adjusted setting in the scroll bar. */
1926 XSETINT (bar->start, start);
1927 XSETINT (bar->end, end);
1929 SetScrollPos (w, SB_CTL, start, TRUE);
1931 UNBLOCK_INPUT;
1934 /* Move a scroll bar around on the screen, to accommodate changing
1935 window configurations. */
1936 static void
1937 x_scroll_bar_move (bar, top, left, width, height)
1938 struct scroll_bar *bar;
1939 int top, left, width, height;
1941 Window w = SCROLL_BAR_W32_WINDOW (bar);
1942 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1944 BLOCK_INPUT;
1946 MoveWindow (w, left, top, width, height, TRUE);
1947 SetScrollRange (w, SB_CTL, 0, height, FALSE);
1948 InvalidateRect (w, NULL, FALSE);
1949 my_show_window (w, SW_NORMAL);
1951 XSETINT (bar->left, left);
1952 XSETINT (bar->top, top);
1953 XSETINT (bar->width, width);
1954 XSETINT (bar->height, height);
1956 UNBLOCK_INPUT;
1959 /* Destroy the window for BAR, and set its Emacs window's scroll bar
1960 to nil. */
1961 static void
1962 x_scroll_bar_remove (bar)
1963 struct scroll_bar *bar;
1965 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1967 BLOCK_INPUT;
1969 /* Destroy the window. */
1970 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
1972 /* Disassociate this scroll bar from its window. */
1973 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
1975 UNBLOCK_INPUT;
1978 /* Set the handle of the vertical scroll bar for WINDOW to indicate
1979 that we are displaying PORTION characters out of a total of WHOLE
1980 characters, starting at POSITION. If WINDOW has no scroll bar,
1981 create one. */
1982 static void
1983 w32_set_vertical_scroll_bar (window, portion, whole, position)
1984 struct window *window;
1985 int portion, whole, position;
1987 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
1988 int top = XINT (window->top);
1989 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
1990 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
1992 /* Where should this scroll bar be, pixelwise? */
1993 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
1994 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
1995 int pixel_width
1996 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
1997 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
1998 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
1999 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2001 struct scroll_bar *bar;
2003 /* Does the scroll bar exist yet? */
2004 if (NILP (window->vertical_scroll_bar))
2005 bar = x_scroll_bar_create (window,
2006 pixel_top, pixel_left,
2007 pixel_width, pixel_height);
2008 else
2010 /* It may just need to be moved and resized. */
2011 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2012 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2015 /* Set the scroll bar's current state, unless we're currently being
2016 dragged. */
2017 if (NILP (bar->dragging))
2019 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2021 if (whole == 0)
2022 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2023 else
2025 int start = (int) (((double) position * top_range) / whole);
2026 int end = (int) (((double) (position + portion) * top_range) / whole);
2028 x_scroll_bar_set_handle (bar, start, end, 0);
2032 XSETVECTOR (window->vertical_scroll_bar, bar);
2036 /* The following three hooks are used when we're doing a thorough
2037 redisplay of the frame. We don't explicitly know which scroll bars
2038 are going to be deleted, because keeping track of when windows go
2039 away is a real pain - "Can you say set-window-configuration, boys
2040 and girls?" Instead, we just assert at the beginning of redisplay
2041 that *all* scroll bars are to be removed, and then save a scroll bar
2042 from the fiery pit when we actually redisplay its window. */
2044 /* Arrange for all scroll bars on FRAME to be removed at the next call
2045 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2046 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2047 static void
2048 w32_condemn_scroll_bars (frame)
2049 FRAME_PTR frame;
2051 /* The condemned list should be empty at this point; if it's not,
2052 then the rest of Emacs isn't using the condemn/redeem/judge
2053 protocol correctly. */
2054 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2055 abort ();
2057 /* Move them all to the "condemned" list. */
2058 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2059 FRAME_SCROLL_BARS (frame) = Qnil;
2062 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2063 Note that WINDOW isn't necessarily condemned at all. */
2064 static void
2065 w32_redeem_scroll_bar (window)
2066 struct window *window;
2068 struct scroll_bar *bar;
2070 /* We can't redeem this window's scroll bar if it doesn't have one. */
2071 if (NILP (window->vertical_scroll_bar))
2072 abort ();
2074 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2076 /* Unlink it from the condemned list. */
2078 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2080 if (NILP (bar->prev))
2082 /* If the prev pointer is nil, it must be the first in one of
2083 the lists. */
2084 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2085 /* It's not condemned. Everything's fine. */
2086 return;
2087 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2088 window->vertical_scroll_bar))
2089 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2090 else
2091 /* If its prev pointer is nil, it must be at the front of
2092 one or the other! */
2093 abort ();
2095 else
2096 XSCROLL_BAR (bar->prev)->next = bar->next;
2098 if (! NILP (bar->next))
2099 XSCROLL_BAR (bar->next)->prev = bar->prev;
2101 bar->next = FRAME_SCROLL_BARS (f);
2102 bar->prev = Qnil;
2103 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2104 if (! NILP (bar->next))
2105 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2109 /* Remove all scroll bars on FRAME that haven't been saved since the
2110 last call to `*condemn_scroll_bars_hook'. */
2111 static void
2112 w32_judge_scroll_bars (f)
2113 FRAME_PTR f;
2115 Lisp_Object bar, next;
2117 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2119 /* Clear out the condemned list now so we won't try to process any
2120 more events on the hapless scroll bars. */
2121 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2123 for (; ! NILP (bar); bar = next)
2125 struct scroll_bar *b = XSCROLL_BAR (bar);
2127 x_scroll_bar_remove (b);
2129 next = b->next;
2130 b->next = b->prev = Qnil;
2133 /* Now there should be no references to the condemned scroll bars,
2134 and they should get garbage-collected. */
2137 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2138 is set to something other than no_event, it is enqueued.
2140 This may be called from a signal handler, so we have to ignore GC
2141 mark bits. */
2143 static int
2144 x_scroll_bar_handle_click (bar, msg, emacs_event)
2145 struct scroll_bar *bar;
2146 W32Msg *msg;
2147 struct input_event *emacs_event;
2149 if (! GC_WINDOWP (bar->window))
2150 abort ();
2152 emacs_event->kind = w32_scroll_bar_click;
2153 emacs_event->code = 0;
2154 /* not really meaningful to distinguish up/down */
2155 emacs_event->modifiers = msg->dwModifiers;
2156 emacs_event->frame_or_window = bar->window;
2157 emacs_event->timestamp = msg->msg.time;
2160 int internal_height
2161 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2162 int top_range
2163 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2164 int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
2166 switch (LOWORD (msg->msg.wParam))
2168 case SB_THUMBTRACK:
2169 emacs_event->part = scroll_bar_handle;
2170 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2171 y = HIWORD (msg->msg.wParam);
2172 break;
2173 case SB_LINEDOWN:
2174 emacs_event->part = scroll_bar_down_arrow;
2175 break;
2176 case SB_LINEUP:
2177 emacs_event->part = scroll_bar_up_arrow;
2178 break;
2179 case SB_PAGEUP:
2180 emacs_event->part = scroll_bar_above_handle;
2181 break;
2182 case SB_PAGEDOWN:
2183 emacs_event->part = scroll_bar_below_handle;
2184 break;
2185 case SB_TOP:
2186 emacs_event->part = scroll_bar_handle;
2187 y = 0;
2188 break;
2189 case SB_BOTTOM:
2190 emacs_event->part = scroll_bar_handle;
2191 y = top_range;
2192 break;
2193 case SB_THUMBPOSITION:
2194 emacs_event->part = scroll_bar_handle;
2195 break;
2196 case SB_ENDSCROLL:
2197 default:
2198 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
2199 return FALSE;
2202 XSETINT (emacs_event->x, y);
2203 XSETINT (emacs_event->y, top_range);
2205 return TRUE;
2209 /* Return information to the user about the current position of the mouse
2210 on the scroll bar. */
2211 static void
2212 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
2213 FRAME_PTR *fp;
2214 Lisp_Object *bar_window;
2215 enum scroll_bar_part *part;
2216 Lisp_Object *x, *y;
2217 unsigned long *time;
2219 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2220 Window w = SCROLL_BAR_W32_WINDOW (bar);
2221 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2222 int pos;
2224 BLOCK_INPUT;
2226 *fp = f;
2227 *bar_window = bar->window;
2229 pos = GetScrollPos (w, SB_CTL);
2231 switch (LOWORD (last_mouse_scroll_bar_pos))
2233 case SB_THUMBPOSITION:
2234 case SB_THUMBTRACK:
2235 *part = scroll_bar_handle;
2236 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
2237 pos = HIWORD (last_mouse_scroll_bar_pos);
2238 break;
2239 case SB_LINEDOWN:
2240 *part = scroll_bar_handle;
2241 pos++;
2242 break;
2243 default:
2244 *part = scroll_bar_handle;
2245 break;
2248 XSETINT(*x, pos);
2249 XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
2251 f->mouse_moved = 0;
2252 last_mouse_scroll_bar = Qnil;
2254 *time = last_mouse_movement_time;
2256 UNBLOCK_INPUT;
2259 /* The screen has been cleared so we may have changed foreground or
2260 background colors, and the scroll bars may need to be redrawn.
2261 Clear out the scroll bars, and ask for expose events, so we can
2262 redraw them. */
2264 x_scroll_bar_clear (f)
2265 FRAME_PTR f;
2267 Lisp_Object bar;
2269 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2270 bar = XSCROLL_BAR (bar)->next)
2272 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2273 HDC hdc = GetDC (window);
2274 RECT rect;
2276 my_show_window (window, SW_HIDE);
2277 GetClientRect (window, &rect);
2278 select_palette (f, hdc);
2279 w32_clear_rect (f, hdc, &rect);
2280 deselect_palette (f, hdc);
2284 show_scroll_bars (f, how)
2285 FRAME_PTR f;
2286 int how;
2288 Lisp_Object bar;
2290 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
2291 bar = XSCROLL_BAR (bar)->next)
2293 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
2294 my_show_window (window, how);
2299 /* The main W32 event-reading loop - w32_read_socket. */
2301 /* Timestamp of enter window event. This is only used by w32_read_socket,
2302 but we have to put it out here, since static variables within functions
2303 sometimes don't work. */
2304 static Time enter_timestamp;
2306 /* Record the last 100 characters stored
2307 to help debug the loss-of-chars-during-GC problem. */
2308 int temp_index;
2309 short temp_buffer[100];
2311 extern int key_event (KEY_EVENT_RECORD *, struct input_event *);
2313 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
2314 we can use the same routines to handle input in both console
2315 and window modes. */
2317 static void
2318 convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
2320 eventp->bKeyDown = TRUE;
2321 eventp->wRepeatCount = 1;
2322 eventp->wVirtualKeyCode = msgp->msg.wParam;
2323 eventp->wVirtualScanCode = (msgp->msg.lParam & 0xFF0000) >> 16;
2324 eventp->uChar.AsciiChar = 0;
2325 eventp->dwControlKeyState = msgp->dwModifiers;
2328 /* Return nonzero if the virtual key is a dead key. */
2330 static int
2331 is_dead_key (int wparam)
2333 unsigned int code = MapVirtualKey (wparam, 2);
2335 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
2336 if ((code & 0x8000) || (code & 0x80000000))
2337 return 1;
2338 else
2339 return 0;
2342 /* Read events coming from the W32 shell.
2343 This routine is called by the SIGIO handler.
2344 We return as soon as there are no more events to be read.
2346 Events representing keys are stored in buffer BUFP,
2347 which can hold up to NUMCHARS characters.
2348 We return the number of characters stored into the buffer,
2349 thus pretending to be `read'.
2351 EXPECTED is nonzero if the caller knows input is available.
2353 Some of these messages are reposted back to the message queue since the
2354 system calls the windows proc directly in a context where we cannot return
2355 the data nor can we guarantee the state we are in. So if we dispatch them
2356 we will get into an infinite loop. To prevent this from ever happening we
2357 will set a variable to indicate we are in the read_socket call and indicate
2358 which message we are processing since the windows proc gets called
2359 recursively with different messages by the system.
2363 w32_read_socket (sd, bufp, numchars, expected)
2364 register int sd;
2365 register struct input_event *bufp;
2366 register int numchars;
2367 int expected;
2369 int count = 0;
2370 int nbytes = 0;
2371 int items_pending; /* How many items are in the X queue. */
2372 W32Msg msg;
2373 struct frame *f;
2374 int event_found = 0;
2375 int prefix;
2376 Lisp_Object part;
2377 struct w32_display_info *dpyinfo = &one_w32_display_info;
2379 if (interrupt_input_blocked)
2381 interrupt_input_pending = 1;
2382 return -1;
2385 interrupt_input_pending = 0;
2386 BLOCK_INPUT;
2388 /* So people can tell when we have read the available input. */
2389 input_signal_count++;
2391 if (numchars <= 0)
2392 abort (); /* Don't think this happens. */
2394 while (get_next_msg (&msg, FALSE))
2396 switch (msg.msg.message)
2398 case WM_PAINT:
2400 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2402 if (f)
2404 if (f->async_visible == 0)
2406 f->async_visible = 1;
2407 f->async_iconified = 0;
2408 SET_FRAME_GARBAGED (f);
2410 else
2412 /* Erase background again for safety. */
2413 w32_clear_rect (f, NULL, &msg.rect);
2414 dumprectangle (f,
2415 msg.rect.left,
2416 msg.rect.top,
2417 msg.rect.right-msg.rect.left+1,
2418 msg.rect.bottom-msg.rect.top+1);
2422 break;
2423 case WM_KEYDOWN:
2424 case WM_SYSKEYDOWN:
2425 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2427 if (f && !f->iconified)
2429 if (temp_index == sizeof temp_buffer / sizeof (short))
2430 temp_index = 0;
2431 temp_buffer[temp_index++] = msg.msg.wParam;
2432 bufp->kind = non_ascii_keystroke;
2433 bufp->code = msg.msg.wParam;
2434 bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers);
2435 XSETFRAME (bufp->frame_or_window, f);
2436 bufp->timestamp = msg.msg.time;
2437 bufp++;
2438 numchars--;
2439 count++;
2441 break;
2442 case WM_SYSCHAR:
2443 case WM_CHAR:
2444 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2446 if (f && !f->iconified)
2448 if (numchars > 1)
2450 int add;
2451 KEY_EVENT_RECORD key, *keyp = &key;
2453 if (temp_index == sizeof temp_buffer / sizeof (short))
2454 temp_index = 0;
2456 convert_to_key_event (&msg, keyp);
2457 add = key_event (keyp, bufp);
2458 XSETFRAME (bufp->frame_or_window, f);
2459 if (add == -1)
2461 /* The key pressed generated two characters, most likely
2462 an accent character and a key that could not be
2463 combined with it. Prepend the message on the queue
2464 again to process the second character (which is
2465 being held internally in key_event), and process
2466 the first character now. */
2467 prepend_msg (&msg);
2468 add = 1;
2471 /* Throw dead keys away. However, be sure not to
2472 throw away the dead key if it was produced using
2473 AltGr and there is a valid AltGr scan code for
2474 this key. */
2475 if (is_dead_key (msg.msg.wParam)
2476 && !((VkKeyScan ((char) bufp->code) & 0xff00) == 0x600))
2477 break;
2479 bufp += add;
2480 numchars -= add;
2481 count += add;
2483 else
2485 abort ();
2488 break;
2489 case WM_MOUSEMOVE:
2490 if (dpyinfo->grabbed && last_mouse_frame
2491 && FRAME_LIVE_P (last_mouse_frame))
2492 f = last_mouse_frame;
2493 else
2494 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2496 if (f)
2497 note_mouse_movement (f, &msg.msg);
2498 else
2499 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2501 break;
2502 case WM_LBUTTONDOWN:
2503 case WM_LBUTTONUP:
2504 case WM_MBUTTONDOWN:
2505 case WM_MBUTTONUP:
2506 case WM_RBUTTONDOWN:
2507 case WM_RBUTTONUP:
2509 int button;
2510 int up;
2512 if (dpyinfo->grabbed && last_mouse_frame
2513 && FRAME_LIVE_P (last_mouse_frame))
2514 f = last_mouse_frame;
2515 else
2516 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2518 if (f)
2520 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
2521 && (numchars >= 1))
2523 construct_mouse_click (bufp, &msg, f);
2524 bufp++;
2525 count++;
2526 numchars--;
2530 parse_button (msg.msg.message, &button, &up);
2532 if (up)
2534 dpyinfo->grabbed &= ~ (1 << button);
2536 else
2538 dpyinfo->grabbed |= (1 << button);
2539 last_mouse_frame = f;
2543 break;
2544 case WM_VSCROLL:
2546 struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam);
2548 if (bar && numchars >= 1)
2550 if (x_scroll_bar_handle_click (bar, &msg, bufp))
2552 bufp++;
2553 count++;
2554 numchars--;
2559 break;
2560 case WM_MOVE:
2561 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2563 if (f && !f->async_iconified)
2565 f->output_data.w32->left_pos = LOWORD (msg.msg.lParam);
2566 f->output_data.w32->top_pos = HIWORD (msg.msg.lParam);
2569 break;
2570 case WM_SIZE:
2571 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2573 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
2575 RECT rect;
2576 int rows;
2577 int columns;
2578 int width;
2579 int height;
2581 GetClientRect(msg.msg.hwnd, &rect);
2583 height = rect.bottom - rect.top + 1;
2584 width = rect.right - rect.left + 1;
2586 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
2587 columns = PIXEL_TO_CHAR_WIDTH (f, width);
2589 /* Even if the number of character rows and columns has
2590 not changed, the font size may have changed, so we need
2591 to check the pixel dimensions as well. */
2593 if (columns != f->width
2594 || rows != f->height
2595 || width != f->output_data.w32->pixel_width
2596 || height != f->output_data.w32->pixel_height)
2598 /* I had set this to 0, 0 - I am not sure why?? */
2600 change_frame_size (f, rows, columns, 0, 1);
2601 SET_FRAME_GARBAGED (f);
2603 f->output_data.w32->pixel_width = width;
2604 f->output_data.w32->pixel_height = height;
2605 f->output_data.w32->win_gravity = NorthWestGravity;
2609 break;
2610 case WM_SETFOCUS:
2611 case WM_KILLFOCUS:
2612 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2614 if (msg.msg.message == WM_SETFOCUS)
2616 x_new_focus_frame (dpyinfo, f);
2618 else if (f == dpyinfo->w32_focus_frame)
2619 x_new_focus_frame (dpyinfo, 0);
2621 break;
2622 case WM_SYSCOMMAND:
2623 switch (msg.msg.wParam & 0xfff0) /* Lower 4 bits used by Windows. */
2625 case SC_CLOSE:
2626 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2628 if (f)
2630 if (numchars == 0)
2631 abort ();
2633 bufp->kind = delete_window_event;
2634 XSETFRAME (bufp->frame_or_window, f);
2635 bufp++;
2636 count++;
2637 numchars--;
2640 break;
2641 case SC_MINIMIZE:
2642 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2644 if (f)
2646 f->async_visible = 1;
2647 f->async_iconified = 1;
2649 bufp->kind = iconify_event;
2650 XSETFRAME (bufp->frame_or_window, f);
2651 bufp++;
2652 count++;
2653 numchars--;
2656 break;
2657 case SC_MAXIMIZE:
2658 case SC_RESTORE:
2659 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2661 if (f)
2663 f->async_visible = 1;
2664 f->async_iconified = 0;
2666 /* wait_reading_process_input will notice this and update
2667 the frame's display structures. */
2668 SET_FRAME_GARBAGED (f);
2670 if (f->iconified)
2672 bufp->kind = deiconify_event;
2673 XSETFRAME (bufp->frame_or_window, f);
2674 bufp++;
2675 count++;
2676 numchars--;
2678 else
2679 /* Force a redisplay sooner or later
2680 to update the frame titles
2681 in case this is the second frame. */
2682 record_asynch_buffer_change ();
2685 break;
2688 break;
2689 case WM_CLOSE:
2690 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2692 if (f)
2694 if (numchars == 0)
2695 abort ();
2697 bufp->kind = delete_window_event;
2698 XSETFRAME (bufp->frame_or_window, f);
2699 bufp++;
2700 count++;
2701 numchars--;
2704 break;
2705 case WM_COMMAND:
2706 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
2708 if (f)
2710 if (msg.msg.lParam == 0)
2712 /* Came from window menu */
2714 extern Lisp_Object get_frame_menubar_event ();
2715 Lisp_Object event = get_frame_menubar_event (f, msg.msg.wParam);
2716 struct input_event buf;
2717 Lisp_Object frame;
2719 XSETFRAME (frame, f);
2720 buf.kind = menu_bar_event;
2722 /* Store initial menu bar event */
2724 if (!NILP (event))
2726 buf.frame_or_window = Fcons (frame, Fcons (Qmenu_bar, Qnil));
2727 kbd_buffer_store_event (&buf);
2730 /* Enqueue the events */
2732 while (!NILP (event))
2734 buf.frame_or_window = Fcons (frame, XCONS (event)->car);
2735 kbd_buffer_store_event (&buf);
2736 event = XCONS (event)->cdr;
2739 else
2741 /* Came from popup menu */
2744 break;
2748 /* If the focus was just given to an autoraising frame,
2749 raise it now. */
2750 /* ??? This ought to be able to handle more than one such frame. */
2751 if (pending_autoraise_frame)
2753 x_raise_frame (pending_autoraise_frame);
2754 pending_autoraise_frame = 0;
2757 UNBLOCK_INPUT;
2758 return count;
2761 /* Drawing the cursor. */
2764 /* Draw a hollow box cursor. Don't change the inside of the box. */
2766 static void
2767 x_draw_box (f)
2768 struct frame *f;
2770 RECT rect;
2771 HBRUSH hb;
2772 HDC hdc;
2774 hdc = get_frame_dc (f);
2776 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
2778 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
2779 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
2780 rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
2781 rect.bottom = rect.top + f->output_data.w32->line_height;
2783 FrameRect (hdc, &rect, hb);
2784 DeleteObject (hb);
2786 release_frame_dc (f, hdc);
2789 /* Clear the cursor of frame F to background color,
2790 and mark the cursor as not shown.
2791 This is used when the text where the cursor is
2792 is about to be rewritten. */
2794 static void
2795 clear_cursor (f)
2796 struct frame *f;
2798 if (! FRAME_VISIBLE_P (f)
2799 || f->phys_cursor_x < 0)
2800 return;
2802 x_display_cursor (f, 0);
2803 f->phys_cursor_x = -1;
2806 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2807 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2808 glyph drawn. */
2810 static void
2811 x_draw_single_glyph (f, row, column, glyph, highlight)
2812 struct frame *f;
2813 int row, column;
2814 GLYPH glyph;
2815 int highlight;
2817 dumpglyphs (f,
2818 CHAR_TO_PIXEL_COL (f, column),
2819 CHAR_TO_PIXEL_ROW (f, row),
2820 &glyph, 1, highlight, 0);
2823 static void
2824 x_display_bar_cursor (f, on)
2825 struct frame *f;
2826 int on;
2828 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2830 /* This is pointless on invisible frames, and dangerous on garbaged
2831 frames; in the latter case, the frame may be in the midst of
2832 changing its size, and curs_x and curs_y may be off the frame. */
2833 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2834 return;
2836 if (! on && f->phys_cursor_x < 0)
2837 return;
2839 /* If we're not updating, then we want to use the current frame's
2840 cursor position, not our local idea of where the cursor ought to be. */
2841 if (f != updating_frame)
2843 curs_x = FRAME_CURSOR_X (f);
2844 curs_y = FRAME_CURSOR_Y (f);
2847 /* If there is anything wrong with the current cursor state, remove it. */
2848 if (f->phys_cursor_x >= 0
2849 && (!on
2850 || f->phys_cursor_x != curs_x
2851 || f->phys_cursor_y != curs_y
2852 || f->output_data.w32->current_cursor != bar_cursor))
2854 /* Erase the cursor by redrawing the character underneath it. */
2855 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2856 f->phys_cursor_glyph,
2857 current_glyphs->highlight[f->phys_cursor_y]);
2858 f->phys_cursor_x = -1;
2861 /* If we now need a cursor in the new place or in the new form, do it so. */
2862 if (on
2863 && (f->phys_cursor_x < 0
2864 || (f->output_data.w32->current_cursor != bar_cursor)))
2866 f->phys_cursor_glyph
2867 = ((current_glyphs->enable[curs_y]
2868 && curs_x < current_glyphs->used[curs_y])
2869 ? current_glyphs->glyphs[curs_y][curs_x]
2870 : SPACEGLYPH);
2871 w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
2872 CHAR_TO_PIXEL_COL (f, curs_x),
2873 CHAR_TO_PIXEL_ROW (f, curs_y),
2874 max (f->output_data.w32->cursor_width, 1),
2875 f->output_data.w32->line_height);
2877 f->phys_cursor_x = curs_x;
2878 f->phys_cursor_y = curs_y;
2880 f->output_data.w32->current_cursor = bar_cursor;
2885 /* Turn the displayed cursor of frame F on or off according to ON.
2886 If ON is nonzero, where to put the cursor is specified
2887 by F->cursor_x and F->cursor_y. */
2889 static void
2890 x_display_box_cursor (f, on)
2891 struct frame *f;
2892 int on;
2894 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2896 /* This is pointless on invisible frames, and dangerous on garbaged
2897 frames; in the latter case, the frame may be in the midst of
2898 changing its size, and curs_x and curs_y may be off the frame. */
2899 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
2900 return;
2902 /* If cursor is off and we want it off, return quickly. */
2903 if (!on && f->phys_cursor_x < 0)
2904 return;
2906 /* If we're not updating, then we want to use the current frame's
2907 cursor position, not our local idea of where the cursor ought to be. */
2908 if (f != updating_frame)
2910 curs_x = FRAME_CURSOR_X (f);
2911 curs_y = FRAME_CURSOR_Y (f);
2914 /* If cursor is currently being shown and we don't want it to be
2915 or it is in the wrong place,
2916 or we want a hollow box and it's not so, (pout!)
2917 erase it. */
2918 if (f->phys_cursor_x >= 0
2919 && (!on
2920 || f->phys_cursor_x != curs_x
2921 || f->phys_cursor_y != curs_y
2922 || (f->output_data.w32->current_cursor != hollow_box_cursor
2923 && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
2925 int mouse_face_here = 0;
2926 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
2928 /* If the cursor is in the mouse face area, redisplay that when
2929 we clear the cursor. */
2930 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
2932 (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2933 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2934 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
2936 (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2937 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2938 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
2939 /* Don't redraw the cursor's spot in mouse face
2940 if it is at the end of a line (on a newline).
2941 The cursor appears there, but mouse highlighting does not. */
2942 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
2943 mouse_face_here = 1;
2945 /* If the font is not as tall as a whole line,
2946 we must explicitly clear the line's whole height. */
2947 if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
2948 w32_clear_area (f, NULL,
2949 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
2950 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
2951 FONT_WIDTH (f->output_data.w32->font),
2952 f->output_data.w32->line_height);
2953 /* Erase the cursor by redrawing the character underneath it. */
2954 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2955 f->phys_cursor_glyph,
2956 (mouse_face_here
2958 : current_glyphs->highlight[f->phys_cursor_y]));
2959 f->phys_cursor_x = -1;
2962 /* If we want to show a cursor,
2963 or we want a box cursor and it's not so,
2964 write it in the right place. */
2965 if (on
2966 && (f->phys_cursor_x < 0
2967 || (f->output_data.w32->current_cursor != filled_box_cursor
2968 && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
2970 f->phys_cursor_glyph
2971 = ((current_glyphs->enable[curs_y]
2972 && curs_x < current_glyphs->used[curs_y])
2973 ? current_glyphs->glyphs[curs_y][curs_x]
2974 : SPACEGLYPH);
2975 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
2977 x_draw_box (f);
2978 f->output_data.w32->current_cursor = hollow_box_cursor;
2980 else
2982 x_draw_single_glyph (f, curs_y, curs_x,
2983 f->phys_cursor_glyph, 2);
2984 f->output_data.w32->current_cursor = filled_box_cursor;
2987 f->phys_cursor_x = curs_x;
2988 f->phys_cursor_y = curs_y;
2992 x_display_cursor (f, on)
2993 struct frame *f;
2994 int on;
2996 BLOCK_INPUT;
2998 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
2999 x_display_box_cursor (f, on);
3000 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3001 x_display_bar_cursor (f, on);
3002 else
3003 /* Those are the only two we have implemented! */
3004 abort ();
3006 UNBLOCK_INPUT;
3009 /* Changing the font of the frame. */
3011 /* Give frame F the font named FONTNAME as its default font, and
3012 return the full name of that font. FONTNAME may be a wildcard
3013 pattern; in that case, we choose some font that fits the pattern.
3014 The return value shows which font we chose. */
3016 Lisp_Object
3017 x_new_font (f, fontname)
3018 struct frame *f;
3019 register char *fontname;
3021 int already_loaded;
3022 int n_matching_fonts;
3023 XFontStruct *font_info;
3024 char new_font_name[101];
3026 /* Get a font which matches this name */
3028 LOGFONT lf;
3030 if (!x_to_w32_font(fontname, &lf)
3031 || !w32_to_x_font(&lf, new_font_name, 100))
3033 return Qnil;
3037 /* See if we've already loaded a matching font. */
3038 already_loaded = -1;
3041 int i;
3043 for (i = 0; i < FRAME_W32_DISPLAY_INFO (f)->n_fonts; i++)
3044 if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
3046 already_loaded = i;
3047 fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
3048 break;
3052 /* If we have, just return it from the table. */
3053 if (already_loaded >= 0)
3054 f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[already_loaded].font;
3055 /* Otherwise, load the font and add it to the table. */
3056 else
3058 XFontStruct *font;
3059 int n_fonts;
3061 font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
3063 if (! font)
3065 return Qnil;
3068 /* Do we need to create the table? */
3069 if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
3071 FRAME_W32_DISPLAY_INFO (f)->font_table_size = 16;
3072 FRAME_W32_DISPLAY_INFO (f)->font_table
3073 = (struct font_info *) xmalloc (FRAME_W32_DISPLAY_INFO (f)->font_table_size
3074 * sizeof (struct font_info));
3076 /* Do we need to grow the table? */
3077 else if (FRAME_W32_DISPLAY_INFO (f)->n_fonts
3078 >= FRAME_W32_DISPLAY_INFO (f)->font_table_size)
3080 FRAME_W32_DISPLAY_INFO (f)->font_table_size *= 2;
3081 FRAME_W32_DISPLAY_INFO (f)->font_table
3082 = (struct font_info *) xrealloc (FRAME_W32_DISPLAY_INFO (f)->font_table,
3083 (FRAME_W32_DISPLAY_INFO (f)->font_table_size
3084 * sizeof (struct font_info)));
3087 n_fonts = FRAME_W32_DISPLAY_INFO (f)->n_fonts;
3088 FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
3089 bcopy (fontname, FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
3090 f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
3091 FRAME_W32_DISPLAY_INFO (f)->n_fonts++;
3094 /* Compute the scroll bar width in character columns. */
3095 if (f->scroll_bar_pixel_width > 0)
3097 int wid = FONT_WIDTH (f->output_data.w32->font);
3098 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
3100 else
3101 f->scroll_bar_cols = 2;
3103 /* Now make the frame display the given font. */
3104 if (FRAME_W32_WINDOW (f) != 0)
3106 frame_update_line_height (f);
3107 x_set_window_size (f, 0, f->width, f->height);
3109 else
3110 /* If we are setting a new frame's font for the first time,
3111 there are no faces yet, so this font's height is the line height. */
3112 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
3115 Lisp_Object lispy_name;
3117 lispy_name = build_string (fontname);
3119 return lispy_name;
3123 x_calc_absolute_position (f)
3124 struct frame *f;
3126 Window win, child;
3127 POINT pt;
3128 int flags = f->output_data.w32->size_hint_flags;
3130 pt.x = pt.y = 0;
3132 /* Find the position of the outside upper-left corner of
3133 the inner window, with respect to the outer window. */
3134 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
3136 BLOCK_INPUT;
3137 MapWindowPoints (FRAME_W32_WINDOW (f),
3138 f->output_data.w32->parent_desc,
3139 &pt, 1);
3140 UNBLOCK_INPUT;
3144 RECT rt;
3145 rt.left = rt.right = rt.top = rt.bottom = 0;
3147 BLOCK_INPUT;
3148 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
3149 FRAME_EXTERNAL_MENU_BAR (f));
3150 UNBLOCK_INPUT;
3152 pt.x += (rt.right - rt.left);
3153 pt.y += (rt.bottom - rt.top);
3156 /* Treat negative positions as relative to the leftmost bottommost
3157 position that fits on the screen. */
3158 if (flags & XNegative)
3159 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
3160 - 2 * f->output_data.w32->border_width - pt.x
3161 - PIXEL_WIDTH (f)
3162 + f->output_data.w32->left_pos);
3164 if (flags & YNegative)
3165 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
3166 - 2 * f->output_data.w32->border_width - pt.y
3167 - PIXEL_HEIGHT (f)
3168 + f->output_data.w32->top_pos);
3169 /* The left_pos and top_pos
3170 are now relative to the top and left screen edges,
3171 so the flags should correspond. */
3172 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
3175 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
3176 to really change the position, and 0 when calling from
3177 x_make_frame_visible (in that case, XOFF and YOFF are the current
3178 position values). It is -1 when calling from x_set_frame_parameters,
3179 which means, do adjust for borders but don't change the gravity. */
3181 x_set_offset (f, xoff, yoff, change_gravity)
3182 struct frame *f;
3183 register int xoff, yoff;
3184 int change_gravity;
3186 int modified_top, modified_left;
3188 if (change_gravity > 0)
3190 f->output_data.w32->top_pos = yoff;
3191 f->output_data.w32->left_pos = xoff;
3192 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
3193 if (xoff < 0)
3194 f->output_data.w32->size_hint_flags |= XNegative;
3195 if (yoff < 0)
3196 f->output_data.w32->size_hint_flags |= YNegative;
3197 f->output_data.w32->win_gravity = NorthWestGravity;
3199 x_calc_absolute_position (f);
3201 BLOCK_INPUT;
3202 x_wm_set_size_hint (f, (long) 0, 0);
3204 /* It is a mystery why we need to add the border_width here
3205 when the frame is already visible, but experiment says we do. */
3206 modified_left = f->output_data.w32->left_pos;
3207 modified_top = f->output_data.w32->top_pos;
3208 if (change_gravity != 0)
3210 modified_left += f->output_data.w32->border_width;
3211 modified_top += f->output_data.w32->border_width;
3214 my_set_window_pos (FRAME_W32_WINDOW (f),
3215 NULL,
3216 modified_left, modified_top,
3217 0,0,
3218 SWP_NOZORDER | SWP_NOSIZE);
3219 UNBLOCK_INPUT;
3222 /* Call this to change the size of frame F's x-window.
3223 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
3224 for this size change and subsequent size changes.
3225 Otherwise we leave the window gravity unchanged. */
3227 x_set_window_size (f, change_gravity, cols, rows)
3228 struct frame *f;
3229 int change_gravity;
3230 int cols, rows;
3232 int pixelwidth, pixelheight;
3234 BLOCK_INPUT;
3236 check_frame_size (f, &rows, &cols);
3237 f->output_data.w32->vertical_scroll_bar_extra
3238 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3240 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
3241 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
3242 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
3243 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3244 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3246 f->output_data.w32->win_gravity = NorthWestGravity;
3247 x_wm_set_size_hint (f, (long) 0, 0);
3250 RECT rect;
3252 rect.left = rect.top = 0;
3253 rect.right = pixelwidth;
3254 rect.bottom = pixelheight;
3256 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
3257 FRAME_EXTERNAL_MENU_BAR (f));
3259 /* All windows have an extra pixel */
3261 my_set_window_pos (FRAME_W32_WINDOW (f),
3262 NULL,
3263 0, 0,
3264 rect.right - rect.left + 1,
3265 rect.bottom - rect.top + 1,
3266 SWP_NOZORDER | SWP_NOMOVE);
3269 /* Now, strictly speaking, we can't be sure that this is accurate,
3270 but the window manager will get around to dealing with the size
3271 change request eventually, and we'll hear how it went when the
3272 ConfigureNotify event gets here.
3274 We could just not bother storing any of this information here,
3275 and let the ConfigureNotify event set everything up, but that
3276 might be kind of confusing to the lisp code, since size changes
3277 wouldn't be reported in the frame parameters until some random
3278 point in the future when the ConfigureNotify event arrives. */
3279 change_frame_size (f, rows, cols, 0, 0);
3280 PIXEL_WIDTH (f) = pixelwidth;
3281 PIXEL_HEIGHT (f) = pixelheight;
3283 /* If cursor was outside the new size, mark it as off. */
3284 if (f->phys_cursor_y >= rows
3285 || f->phys_cursor_x >= cols)
3287 f->phys_cursor_x = -1;
3288 f->phys_cursor_y = -1;
3291 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
3292 receive in the ConfigureNotify event; if we get what we asked
3293 for, then the event won't cause the screen to become garbaged, so
3294 we have to make sure to do it here. */
3295 SET_FRAME_GARBAGED (f);
3297 UNBLOCK_INPUT;
3300 /* Mouse warping. */
3302 void
3303 x_set_mouse_pixel_position (f, pix_x, pix_y)
3304 struct frame *f;
3305 int pix_x, pix_y;
3307 BLOCK_INPUT;
3309 pix_x += f->output_data.w32->left_pos;
3310 pix_y += f->output_data.w32->top_pos;
3312 SetCursorPos (pix_x, pix_y);
3314 UNBLOCK_INPUT;
3317 void
3318 x_set_mouse_position (f, x, y)
3319 struct frame *f;
3320 int x, y;
3322 int pix_x, pix_y;
3324 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
3325 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
3327 if (pix_x < 0) pix_x = 0;
3328 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
3330 if (pix_y < 0) pix_y = 0;
3331 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
3333 x_set_mouse_pixel_position (f, pix_x, pix_y);
3336 /* focus shifting, raising and lowering. */
3338 x_focus_on_frame (f)
3339 struct frame *f;
3343 x_unfocus_frame (f)
3344 struct frame *f;
3348 /* Raise frame F. */
3350 x_raise_frame (f)
3351 struct frame *f;
3353 // if (f->async_visible)
3355 BLOCK_INPUT;
3356 my_set_window_pos (FRAME_W32_WINDOW (f),
3357 HWND_TOP,
3358 0, 0, 0, 0,
3359 SWP_NOSIZE | SWP_NOMOVE);
3360 UNBLOCK_INPUT;
3364 /* Lower frame F. */
3366 x_lower_frame (f)
3367 struct frame *f;
3369 // if (f->async_visible)
3371 BLOCK_INPUT;
3372 my_set_window_pos (FRAME_W32_WINDOW (f),
3373 HWND_BOTTOM,
3374 0, 0, 0, 0,
3375 SWP_NOSIZE | SWP_NOMOVE);
3376 UNBLOCK_INPUT;
3380 static void
3381 w32_frame_raise_lower (f, raise)
3382 FRAME_PTR f;
3383 int raise;
3385 if (raise)
3386 x_raise_frame (f);
3387 else
3388 x_lower_frame (f);
3391 /* Change of visibility. */
3393 /* This tries to wait until the frame is really visible.
3394 However, if the window manager asks the user where to position
3395 the frame, this will return before the user finishes doing that.
3396 The frame will not actually be visible at that time,
3397 but it will become visible later when the window manager
3398 finishes with it. */
3400 x_make_frame_visible (f)
3401 struct frame *f;
3403 BLOCK_INPUT;
3405 if (! FRAME_VISIBLE_P (f))
3407 /* We test FRAME_GARBAGED_P here to make sure we don't
3408 call x_set_offset a second time
3409 if we get to x_make_frame_visible a second time
3410 before the window gets really visible. */
3411 if (! FRAME_ICONIFIED_P (f)
3412 && ! f->output_data.w32->asked_for_visible)
3414 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
3415 // SetForegroundWindow (FRAME_W32_WINDOW (f));
3418 f->output_data.w32->asked_for_visible = 1;
3420 my_show_window (FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
3423 /* Synchronize to ensure Emacs knows the frame is visible
3424 before we do anything else. We do this loop with input not blocked
3425 so that incoming events are handled. */
3427 Lisp_Object frame;
3428 int count = input_signal_count;
3430 /* This must come after we set COUNT. */
3431 UNBLOCK_INPUT;
3433 XSETFRAME (frame, f);
3435 while (1)
3437 /* Once we have handled input events,
3438 we should have received the MapNotify if one is coming.
3439 So if we have not got it yet, stop looping.
3440 Some window managers make their own decisions
3441 about visibility. */
3442 if (input_signal_count != count)
3443 break;
3444 /* Machines that do polling rather than SIGIO have been observed
3445 to go into a busy-wait here. So we'll fake an alarm signal
3446 to let the handler know that there's something to be read.
3447 We used to raise a real alarm, but it seems that the handler
3448 isn't always enabled here. This is probably a bug. */
3449 if (input_polling_used ())
3451 /* It could be confusing if a real alarm arrives while processing
3452 the fake one. Turn it off and let the handler reset it. */
3453 alarm (0);
3454 input_poll_signal ();
3456 /* Once we have handled input events,
3457 we should have received the MapNotify if one is coming.
3458 So if we have not got it yet, stop looping.
3459 Some window managers make their own decisions
3460 about visibility. */
3461 if (input_signal_count != count)
3462 break;
3464 FRAME_SAMPLE_VISIBILITY (f);
3468 /* Change from mapped state to withdrawn state. */
3470 /* Make the frame visible (mapped and not iconified). */
3472 x_make_frame_invisible (f)
3473 struct frame *f;
3475 Window window;
3477 /* Don't keep the highlight on an invisible frame. */
3478 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
3479 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
3481 BLOCK_INPUT;
3483 my_show_window (FRAME_W32_WINDOW (f), SW_HIDE);
3485 /* We can't distinguish this from iconification
3486 just by the event that we get from the server.
3487 So we can't win using the usual strategy of letting
3488 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
3489 and synchronize with the server to make sure we agree. */
3490 f->visible = 0;
3491 FRAME_ICONIFIED_P (f) = 0;
3492 f->async_visible = 0;
3493 f->async_iconified = 0;
3495 UNBLOCK_INPUT;
3498 /* Change window state from mapped to iconified. */
3500 void
3501 x_iconify_frame (f)
3502 struct frame *f;
3504 int result;
3506 /* Don't keep the highlight on an invisible frame. */
3507 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
3508 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
3510 if (f->async_iconified)
3511 return;
3513 BLOCK_INPUT;
3515 my_show_window (FRAME_W32_WINDOW (f), SW_SHOWMINIMIZED);
3516 /* The frame doesn't seem to be lowered automatically. */
3517 x_lower_frame (f);
3519 f->async_iconified = 1;
3521 UNBLOCK_INPUT;
3524 /* Destroy the window of frame F. */
3526 x_destroy_window (f)
3527 struct frame *f;
3529 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3531 BLOCK_INPUT;
3533 my_destroy_window (f, FRAME_W32_WINDOW (f));
3534 free_frame_menubar (f);
3535 free_frame_faces (f);
3537 xfree (f->output_data.w32);
3538 f->output_data.w32 = 0;
3539 if (f == dpyinfo->w32_focus_frame)
3540 dpyinfo->w32_focus_frame = 0;
3541 if (f == dpyinfo->w32_focus_event_frame)
3542 dpyinfo->w32_focus_event_frame = 0;
3543 if (f == dpyinfo->w32_highlight_frame)
3544 dpyinfo->w32_highlight_frame = 0;
3546 dpyinfo->reference_count--;
3548 if (f == dpyinfo->mouse_face_mouse_frame)
3550 dpyinfo->mouse_face_beg_row
3551 = dpyinfo->mouse_face_beg_col = -1;
3552 dpyinfo->mouse_face_end_row
3553 = dpyinfo->mouse_face_end_col = -1;
3554 dpyinfo->mouse_face_window = Qnil;
3557 UNBLOCK_INPUT;
3560 /* Setting window manager hints. */
3562 /* Set the normal size hints for the window manager, for frame F.
3563 FLAGS is the flags word to use--or 0 meaning preserve the flags
3564 that the window now has.
3565 If USER_POSITION is nonzero, we set the USPosition
3566 flag (this is useful when FLAGS is 0). */
3568 x_wm_set_size_hint (f, flags, user_position)
3569 struct frame *f;
3570 long flags;
3571 int user_position;
3573 Window window = FRAME_W32_WINDOW (f);
3575 flexlines = f->height;
3577 enter_crit ();
3579 SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.w32->font));
3580 SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.w32->line_height);
3582 leave_crit ();
3585 /* Window manager things */
3586 x_wm_set_icon_position (f, icon_x, icon_y)
3587 struct frame *f;
3588 int icon_x, icon_y;
3590 #if 0
3591 Window window = FRAME_W32_WINDOW (f);
3593 f->display.x->wm_hints.flags |= IconPositionHint;
3594 f->display.x->wm_hints.icon_x = icon_x;
3595 f->display.x->wm_hints.icon_y = icon_y;
3597 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
3598 #endif
3602 /* Initialization. */
3604 #ifdef USE_X_TOOLKIT
3605 static XrmOptionDescRec emacs_options[] = {
3606 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
3607 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
3609 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
3610 XrmoptionSepArg, NULL},
3611 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
3613 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3614 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3615 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
3616 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3617 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
3618 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
3619 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
3621 #endif /* USE_X_TOOLKIT */
3623 static int w32_initialized = 0;
3625 struct w32_display_info *
3626 w32_term_init (display_name, xrm_option, resource_name)
3627 Lisp_Object display_name;
3628 char *xrm_option;
3629 char *resource_name;
3631 Lisp_Object frame;
3632 char *defaultvalue;
3633 struct w32_display_info *dpyinfo;
3634 HDC hdc;
3636 BLOCK_INPUT;
3638 if (!w32_initialized)
3640 w32_initialize ();
3641 w32_initialized = 1;
3645 int argc = 0;
3646 char *argv[3];
3648 argv[0] = "";
3649 argc = 1;
3650 if (xrm_option)
3652 argv[argc++] = "-xrm";
3653 argv[argc++] = xrm_option;
3657 dpyinfo = &one_w32_display_info;
3659 /* Put this display on the chain. */
3660 dpyinfo->next = NULL;
3662 /* Put it on w32_display_name_list as well, to keep them parallel. */
3663 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
3664 w32_display_name_list);
3665 dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
3667 dpyinfo->w32_id_name
3668 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
3669 + XSTRING (Vsystem_name)->size
3670 + 2);
3671 sprintf (dpyinfo->w32_id_name, "%s@%s",
3672 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
3674 #if 0
3675 xrdb = x_load_resources (dpyinfo->display, xrm_option,
3676 resource_name, EMACS_CLASS);
3678 /* Put the rdb where we can find it in a way that works on
3679 all versions. */
3680 dpyinfo->xrdb = xrdb;
3681 #endif
3682 hdc = GetDC (GetDesktopWindow ());
3684 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
3685 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
3686 dpyinfo->root_window = GetDesktopWindow ();
3687 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
3688 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
3689 dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
3690 dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
3691 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
3692 dpyinfo->grabbed = 0;
3693 dpyinfo->reference_count = 0;
3694 dpyinfo->n_fonts = 0;
3695 dpyinfo->font_table_size = 0;
3696 dpyinfo->bitmaps = 0;
3697 dpyinfo->bitmaps_size = 0;
3698 dpyinfo->bitmaps_last = 0;
3699 dpyinfo->mouse_face_mouse_frame = 0;
3700 dpyinfo->mouse_face_deferred_gc = 0;
3701 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3702 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3703 dpyinfo->mouse_face_face_id = 0;
3704 dpyinfo->mouse_face_window = Qnil;
3705 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
3706 dpyinfo->mouse_face_defer = 0;
3707 dpyinfo->w32_focus_frame = 0;
3708 dpyinfo->w32_focus_event_frame = 0;
3709 dpyinfo->w32_highlight_frame = 0;
3711 ReleaseDC (GetDesktopWindow (), hdc);
3713 /* Determine if there is a middle mouse button, to allow parse_button
3714 to decide whether right mouse events should be mouse-2 or
3715 mouse-3. */
3716 XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
3718 /* initialise palette with white and black */
3720 COLORREF color;
3721 defined_color (0, "white", &color, 1);
3722 defined_color (0, "black", &color, 1);
3725 #ifndef F_SETOWN_BUG
3726 #ifdef F_SETOWN
3727 #ifdef F_SETOWN_SOCK_NEG
3728 /* stdin is a socket here */
3729 fcntl (connection, F_SETOWN, -getpid ());
3730 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3731 fcntl (connection, F_SETOWN, getpid ());
3732 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3733 #endif /* ! defined (F_SETOWN) */
3734 #endif /* F_SETOWN_BUG */
3736 #ifdef SIGIO
3737 if (interrupt_input)
3738 init_sigio (connection);
3739 #endif /* ! defined (SIGIO) */
3741 UNBLOCK_INPUT;
3743 return dpyinfo;
3746 /* Get rid of display DPYINFO, assuming all frames are already gone. */
3748 void
3749 x_delete_display (dpyinfo)
3750 struct w32_display_info *dpyinfo;
3752 /* Discard this display from w32_display_name_list and w32_display_list.
3753 We can't use Fdelq because that can quit. */
3754 if (! NILP (w32_display_name_list)
3755 && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
3756 w32_display_name_list = XCONS (w32_display_name_list)->cdr;
3757 else
3759 Lisp_Object tail;
3761 tail = w32_display_name_list;
3762 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
3764 if (EQ (XCONS (XCONS (tail)->cdr)->car,
3765 dpyinfo->name_list_element))
3767 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
3768 break;
3770 tail = XCONS (tail)->cdr;
3774 /* free palette table */
3776 struct w32_palette_entry * plist;
3778 plist = dpyinfo->color_list;
3779 while (plist)
3781 struct w32_palette_entry * pentry = plist;
3782 plist = plist->next;
3783 xfree(pentry);
3785 dpyinfo->color_list = NULL;
3786 if (dpyinfo->palette)
3787 DeleteObject(dpyinfo->palette);
3789 xfree (dpyinfo->font_table);
3790 xfree (dpyinfo->w32_id_name);
3793 /* Set up use of W32. */
3795 DWORD windows_msg_worker ();
3797 w32_initialize ()
3799 clear_frame_hook = w32_clear_frame;
3800 clear_end_of_line_hook = w32_clear_end_of_line;
3801 ins_del_lines_hook = w32_ins_del_lines;
3802 change_line_highlight_hook = w32_change_line_highlight;
3803 insert_glyphs_hook = w32_insert_glyphs;
3804 write_glyphs_hook = w32_write_glyphs;
3805 delete_glyphs_hook = w32_delete_glyphs;
3806 ring_bell_hook = w32_ring_bell;
3807 reset_terminal_modes_hook = w32_reset_terminal_modes;
3808 set_terminal_modes_hook = w32_set_terminal_modes;
3809 update_begin_hook = w32_update_begin;
3810 update_end_hook = w32_update_end;
3811 set_terminal_window_hook = w32_set_terminal_window;
3812 read_socket_hook = w32_read_socket;
3813 frame_up_to_date_hook = w32_frame_up_to_date;
3814 cursor_to_hook = w32_cursor_to;
3815 reassert_line_highlight_hook = w32_reassert_line_highlight;
3816 mouse_position_hook = w32_mouse_position;
3817 frame_rehighlight_hook = w32_frame_rehighlight;
3818 frame_raise_lower_hook = w32_frame_raise_lower;
3819 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
3820 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
3821 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
3822 judge_scroll_bars_hook = w32_judge_scroll_bars;
3824 scroll_region_ok = 1; /* we'll scroll partial frames */
3825 char_ins_del_ok = 0; /* just as fast to write the line */
3826 line_ins_del_ok = 1; /* we'll just blt 'em */
3827 fast_clear_end_of_line = 1; /* X does this well */
3828 memory_below_frame = 0; /* we don't remember what scrolls
3829 off the bottom */
3830 baud_rate = 19200;
3832 /* Try to use interrupt input; if we can't, then start polling. */
3833 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3835 /* Create the window thread - it will terminate itself or when the app terminates */
3837 init_crit ();
3839 dwMainThreadId = GetCurrentThreadId ();
3840 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
3841 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
3843 /* Wait for thread to start */
3846 MSG msg;
3848 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
3850 hWindowsThread = CreateThread (NULL, 0,
3851 (LPTHREAD_START_ROUTINE) windows_msg_worker,
3852 0, 0, &dwWindowsThreadId);
3854 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3857 /* It is desirable that mainThread should have the same notion of
3858 focus window and active window as windowsThread. Unfortunately, the
3859 following call to AttachThreadInput, which should do precisely what
3860 we need, causes major problems when Emacs is linked as a console
3861 program. Unfortunately, we have good reasons for doing that, so
3862 instead we need to send messages to windowsThread to make some API
3863 calls for us (ones that affect, or depend on, the active/focus
3864 window state. */
3865 #ifdef ATTACH_THREADS
3866 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
3867 #endif
3870 void
3871 syms_of_w32term ()
3873 staticpro (&w32_display_name_list);
3874 w32_display_name_list = Qnil;
3876 staticpro (&last_mouse_scroll_bar);
3877 last_mouse_scroll_bar = Qnil;
3879 staticpro (&Qvendor_specific_keysyms);
3880 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
3882 DEFVAR_INT ("w32-num-mouse-buttons",
3883 &Vw32_num_mouse_buttons,
3884 "Number of physical mouse buttons.");
3885 Vw32_num_mouse_buttons = Qnil;
3887 DEFVAR_LISP ("w32-swap-mouse-buttons",
3888 &Vw32_swap_mouse_buttons,
3889 "Swap the mapping of middle and right mouse buttons.\n\
3890 When nil, middle button is mouse-2 and right button is mouse-3.");
3891 Vw32_swap_mouse_buttons = Qnil;