Use -gcoff instead of -g in CFLAGS, for those who
[emacs.git] / src / w32term.c
blobc309665831ec1cd40946704646a21d1403351845
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98 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 #include <signal.h>
22 #include <config.h>
23 #include <stdio.h>
24 #include "lisp.h"
25 #include "charset.h"
26 #include "fontset.h"
27 #include "blockinput.h"
29 #include "w32heap.h"
30 #include "w32term.h"
31 #include <shellapi.h>
33 #include "systty.h"
34 #include "systime.h"
36 #include <ctype.h>
37 #include <errno.h>
38 #include <setjmp.h>
39 #include <sys/stat.h>
41 #include "frame.h"
42 #include "dispextern.h"
43 #include "termhooks.h"
44 #include "termopts.h"
45 #include "termchar.h"
46 #include "gnu.h"
47 #include "disptab.h"
48 #include "buffer.h"
49 #include "window.h"
50 #include "keyboard.h"
51 #include "intervals.h"
52 #include "coding.h"
54 #undef min
55 #undef max
56 #define min(x, y) (((x) < (y)) ? (x) : (y))
57 #define max(x, y) (((x) > (y)) ? (x) : (y))
59 #define CP_DEFAULT 1004
61 extern unsigned int msh_mousewheel;
63 extern void free_frame_menubar ();
65 extern Lisp_Object Vwindow_system;
67 #define x_any_window_to_frame x_window_to_frame
68 #define x_top_window_to_frame x_window_to_frame
71 /* This is display since w32 does not support multiple ones. */
72 struct w32_display_info one_w32_display_info;
74 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
75 one for each element of w32_display_list and in the same order.
76 NAME is the name of the frame.
77 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
78 Lisp_Object w32_display_name_list;
80 /* Frame being updated by update_frame. This is declared in term.c.
81 This is set by update_begin and looked at by all the
82 w32 functions. It is zero while not inside an update.
83 In that case, the w32 functions assume that `selected_frame'
84 is the frame to apply to. */
85 extern struct frame *updating_frame;
87 /* This is a frame waiting to be autoraised, within w32_read_socket. */
88 struct frame *pending_autoraise_frame;
90 /* During an update, maximum vpos for ins/del line operations to affect. */
92 static int flexlines;
94 /* During an update, nonzero if chars output now should be highlighted. */
96 static int highlight;
98 /* Nominal cursor position -- where to draw output.
99 During an update, these are different from the cursor-box position. */
101 static int curs_x;
102 static int curs_y;
104 /* Flag to enable Unicode output in case users wish to use programs
105 like Twinbridge on '95 rather than installed system level support
106 for Far East languages. */
107 int w32_enable_unicode_output;
109 DWORD dwWindowsThreadId = 0;
110 HANDLE hWindowsThread = NULL;
111 DWORD dwMainThreadId = 0;
112 HANDLE hMainThread = NULL;
114 #ifndef SIF_ALL
115 /* These definitions are new with Windows 95. */
116 #define SIF_RANGE 0x0001
117 #define SIF_PAGE 0x0002
118 #define SIF_POS 0x0004
119 #define SIF_DISABLENOSCROLL 0x0008
120 #define SIF_TRACKPOS 0x0010
121 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
123 typedef struct tagSCROLLINFO
125 UINT cbSize;
126 UINT fMask;
127 int nMin;
128 int nMax;
129 UINT nPage;
130 int nPos;
131 int nTrackPos;
132 } SCROLLINFO, FAR *LPSCROLLINFO;
133 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
134 #endif /* SIF_ALL */
136 /* Dynamic linking to new proportional scroll bar functions. */
137 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
138 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
140 int vertical_scroll_bar_min_handle;
141 int vertical_scroll_bar_top_border;
142 int vertical_scroll_bar_bottom_border;
144 int last_scroll_bar_drag_pos;
146 /* Mouse movement. */
148 /* Where the mouse was last time we reported a mouse event. */
149 static FRAME_PTR last_mouse_frame;
150 static RECT last_mouse_glyph;
152 Lisp_Object Vw32_num_mouse_buttons;
154 Lisp_Object Vw32_swap_mouse_buttons;
156 /* Control whether x_raise_frame also sets input focus. */
157 Lisp_Object Vw32_grab_focus_on_raise;
159 /* Control whether Caps Lock affects non-ascii characters. */
160 Lisp_Object Vw32_capslock_is_shiftlock;
162 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
163 Lisp_Object Vw32_recognize_altgr;
165 /* The scroll bar in which the last motion event occurred.
167 If the last motion event occurred in a scroll bar, we set this
168 so w32_mouse_position can know whether to report a scroll bar motion or
169 an ordinary motion.
171 If the last motion event didn't occur in a scroll bar, we set this
172 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
173 Lisp_Object last_mouse_scroll_bar;
174 int last_mouse_scroll_bar_pos;
176 /* This is a hack. We would really prefer that w32_mouse_position would
177 return the time associated with the position it returns, but there
178 doesn't seem to be any way to wrest the timestamp from the server
179 along with the position query. So, we just keep track of the time
180 of the last movement we received, and return that in hopes that
181 it's somewhat accurate. */
182 Time last_mouse_movement_time;
184 /* Associative list linking character set strings to Windows codepages. */
185 Lisp_Object Vw32_charset_to_codepage_alist;
187 /* Incremented by w32_read_socket whenever it really tries to read events. */
188 #ifdef __STDC__
189 static int volatile input_signal_count;
190 #else
191 static int input_signal_count;
192 #endif
194 extern Lisp_Object Vcommand_line_args, Vsystem_name;
196 extern Lisp_Object Qface, Qmouse_face;
198 extern int errno;
200 /* A mask of extra modifier bits to put into every keyboard char. */
201 extern int extra_keyboard_modifiers;
203 static Lisp_Object Qvendor_specific_keysyms;
205 void w32_delete_display ();
207 static void redraw_previous_char ();
208 static void redraw_following_char ();
209 static unsigned int w32_get_modifiers ();
211 static int fast_find_position ();
212 static void note_mouse_highlight ();
213 static void clear_mouse_face ();
214 static void show_mouse_face ();
215 static void do_line_dance ();
217 /* Forward declarations for term hooks. Consistency with the rest of Emacs
218 requires the use of K&R functions prototypes. However, MSVC does not
219 pick up the function prototypes correctly with K&R function definitions,
220 and so we declare them first to give a little help to MSVC. */
221 static void w32_clear_frame ();
222 static void w32_clear_end_of_line (int);
223 static void w32_ins_del_lines (int, int);
224 static void w32_change_line_highlight (int, int, int);
225 static void w32_insert_glyphs (GLYPH *, int);
226 static void w32_write_glyphs (GLYPH *, int);
227 static void w32_delete_glyphs (int);
228 static void w32_ring_bell ();
229 static void w32_reset_terminal_modes ();
230 static void w32_set_terminal_modes ();
231 static void w32_update_begin (FRAME_PTR);
232 static void w32_update_end (FRAME_PTR);
233 static void w32_set_terminal_window (int);
234 extern int w32_read_socket (int, struct input_event *, int, int);
235 static void w32_frame_up_to_date (FRAME_PTR);
236 static void w32_cursor_to (int, int);
237 static void w32_reassert_line_highlight (int, int);
238 static void w32_mouse_position (FRAME_PTR *, int, Lisp_Object *,
239 enum scroll_bar_part *, Lisp_Object *,
240 Lisp_Object *, unsigned long *);
241 static void w32_frame_rehighlight (FRAME_PTR);
242 static void w32_frame_raise_lower (FRAME_PTR, int);
243 static void w32_set_vertical_scroll_bar (struct window *, int, int, int);
244 static void w32_condemn_scroll_bars (FRAME_PTR);
245 static void w32_redeem_scroll_bar (struct window *);
246 static void w32_judge_scroll_bars (FRAME_PTR);
248 #if 0
249 /* This is a function useful for recording debugging information
250 about the sequence of occurrences in this file. */
252 struct record
254 char *locus;
255 int type;
258 struct record event_record[100];
260 int event_record_index;
262 record_event (locus, type)
263 char *locus;
264 int type;
266 if (event_record_index == sizeof (event_record) / sizeof (struct record))
267 event_record_index = 0;
269 event_record[event_record_index].locus = locus;
270 event_record[event_record_index].type = type;
271 event_record_index++;
274 #endif /* 0 */
276 /* Return the struct w32_display_info. */
278 struct w32_display_info *
279 w32_display_info_for_display ()
281 return (&one_w32_display_info);
284 void
285 w32_fill_rect (f, _hdc, pix, lprect)
286 FRAME_PTR f;
287 HDC _hdc;
288 COLORREF pix;
289 RECT * lprect;
291 HDC hdc;
292 HBRUSH hb;
293 RECT rect;
295 if (_hdc)
296 hdc = _hdc;
297 else
299 if (!f) return;
300 hdc = get_frame_dc (f);
303 hb = CreateSolidBrush (pix);
304 FillRect (hdc, lprect, hb);
305 DeleteObject (hb);
307 if (!_hdc)
308 release_frame_dc (f, hdc);
311 void
312 w32_clear_window (f)
313 FRAME_PTR f;
315 RECT rect;
317 GetClientRect (FRAME_W32_WINDOW (f), &rect);
318 w32_clear_rect (f, NULL, &rect);
322 /* Starting and ending updates.
324 These hooks are called by update_frame at the beginning and end
325 of a frame update. We record in `updating_frame' the identity
326 of the frame being updated, so that the w32_... functions do not
327 need to take a frame as argument. Most of the w32_... functions
328 should never be called except during an update, the only exceptions
329 being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight. */
331 static void
332 w32_update_begin (f)
333 struct frame *f;
335 if (f == 0)
336 abort ();
338 flexlines = f->height;
339 highlight = 0;
341 BLOCK_INPUT;
343 /* Regenerate display palette before drawing if list of requested
344 colors has changed. */
345 if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
347 w32_regenerate_palette (f);
348 FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
351 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
353 /* Don't do highlighting for mouse motion during the update. */
354 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
356 /* If the frame needs to be redrawn,
357 simply forget about any prior mouse highlighting. */
358 if (FRAME_GARBAGED_P (f))
359 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
361 if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
363 int firstline, lastline, i;
364 struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
366 /* Find the first, and the last+1, lines affected by redisplay. */
367 for (firstline = 0; firstline < f->height; firstline++)
368 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
369 break;
371 lastline = f->height;
372 for (i = f->height - 1; i >= 0; i--)
374 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
375 break;
376 else
377 lastline = i;
380 /* Can we tell that this update does not affect the window
381 where the mouse highlight is? If so, no need to turn off.
382 Likewise, don't do anything if the frame is garbaged;
383 in that case, the FRAME_CURRENT_GLYPHS that we would use
384 are all wrong, and we will redisplay that line anyway. */
385 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
386 || lastline < XFASTINT (w->top)))
387 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
391 UNBLOCK_INPUT;
394 static void
395 w32_update_end (f)
396 struct frame *f;
398 BLOCK_INPUT;
400 do_line_dance ();
401 x_display_cursor (f, 1);
403 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
404 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
406 UNBLOCK_INPUT;
409 /* This is called after a redisplay on frame F. */
411 static void
412 w32_frame_up_to_date (f)
413 FRAME_PTR f;
415 BLOCK_INPUT;
416 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
417 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
419 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
420 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x,
421 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y);
422 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
424 UNBLOCK_INPUT;
427 /* External interface to control of standout mode.
428 Call this when about to modify line at position VPOS
429 and not change whether it is highlighted. */
431 static void
432 w32_reassert_line_highlight (new, vpos)
433 int new, vpos;
435 highlight = new;
438 /* Call this when about to modify line at position VPOS
439 and change whether it is highlighted. */
441 static void
442 w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
443 int new_highlight, vpos, first_unused_hpos;
445 highlight = new_highlight;
446 w32_cursor_to (vpos, 0);
447 w32_clear_end_of_line (updating_frame->width);
450 /* This is used when starting Emacs and when restarting after suspend.
451 When starting Emacs, no window is mapped. And nothing must be done
452 to Emacs's own window if it is suspended (though that rarely happens). */
454 static void
455 w32_set_terminal_modes (void)
459 /* This is called when exiting or suspending Emacs.
460 Exiting will make the W32 windows go away, and suspending
461 requires no action. */
463 static void
464 w32_reset_terminal_modes (void)
468 /* Set the nominal cursor position of the frame.
469 This is where display update commands will take effect.
470 This does not affect the place where the cursor-box is displayed. */
472 static void
473 w32_cursor_to (row, col)
474 register int row, col;
476 int orow = row;
478 curs_x = col;
479 curs_y = row;
481 if (updating_frame == 0)
483 BLOCK_INPUT;
484 x_display_cursor (selected_frame, 1);
485 UNBLOCK_INPUT;
489 /* Get the Windows codepage corresponding to the specified font. The
490 charset info in the font name is used to look up
491 w32-charset-to-codepage-alist. */
492 int
493 w32_codepage_for_font (char *fontname)
495 Lisp_Object codepage;
496 char charset_str[20], *charset, *end;
498 /* Extract charset part of font string. */
499 if (sscanf (fontname,
500 "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
501 charset_str) == EOF)
502 return CP_DEFAULT;
504 /* Remove leading "*-". */
505 if (strncmp ("*-", charset_str, 2) == 0)
506 charset = charset_str + 2;
507 else
508 charset = charset_str;
510 /* Stop match at wildcard (including preceding '-'). */
511 if (end = strchr (charset, '*'))
513 if (end > charset && *(end-1) == '-')
514 end--;
515 *end = '\0';
518 codepage = Fcdr (Fassoc (build_string(charset),
519 Vw32_charset_to_codepage_alist));
521 if (INTEGERP (codepage))
522 return XINT (codepage);
523 else
524 return CP_DEFAULT;
527 BOOL
528 w32_use_unicode_for_codepage (codepage)
530 /* If the current codepage is supported, use Unicode for output. */
531 return (w32_enable_unicode_output
532 && codepage != CP_DEFAULT && IsValidCodePage (codepage));
535 /* Dealing with bits of wchar_t as if they were an XChar2B. */
536 #define BUILD_WCHAR_T(byte1, byte2) \
537 ((wchar_t)(((byte1 & 0x00ff) << 8) | (byte2 & 0x00ff)))
540 #define BYTE1(ch) \
541 ((ch & 0xff00) >> 8)
543 #define BYTE2(ch) \
544 (ch & 0x00ff)
546 #define W32_TEXTOUT(start_offset,nchars) \
548 int charset_dim = CHARSET_DIMENSION(charset); \
549 if (font->bdf) \
550 w32_BDF_TextOut (font->bdf, hdc, left + xoffset, \
551 top + yoffset, \
552 x_1byte_buffer + start_offset, \
553 charset_dim, nchars, 0); \
554 else if (print_via_unicode) \
555 ExtTextOutW (hdc, left + xoffset, top + yoffset, \
556 fuOptions, clip_region, \
557 x_2byte_buffer + start_offset, nchars, NULL); \
558 else \
559 ExtTextOut (hdc, left + xoffset, top + yoffset, \
560 fuOptions, clip_region, \
561 x_1byte_buffer + start_offset, \
562 nchars * charset_dim, NULL); \
563 start_offset += nchars * (print_via_unicode ? 1 : charset_dim ); \
564 xoffset += nchars * glyph_width; \
567 /* Display a sequence of N glyphs found at GP.
568 WINDOW is the window to output to. LEFT and TOP are starting coords.
569 HL is 1 if this text is highlighted, 2 if the cursor is on it,
570 3 if should appear in its mouse-face.
571 JUST_FOREGROUND if 1 means draw only the foreground;
572 don't alter the background.
574 FONT is the default font to use (for glyphs whose font-code is 0).
576 Since the display generation code is responsible for calling
577 compute_char_face and compute_glyph_face on everything it puts in
578 the display structure, we can assume that the face code on each
579 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
580 to which we can actually apply intern_face.
581 Call this function with input blocked. */
583 static int
584 dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
585 struct frame *f;
586 int left, top;
587 register GLYPH *gp; /* Points to first GLYPH. */
588 register int n; /* Number of glyphs to display. */
589 int hl;
590 int just_foreground;
591 struct cmpchar_info *cmpcharp;
593 wchar_t *x_2byte_buffer
594 = (wchar_t *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*x_2byte_buffer));
595 register wchar_t *cp; /* Steps through x_2byte_buffer[]. */
597 /* Allocate double the window width, as this buffer may contain MBCS
598 characters under w32. Unsigned to let GetCharABCWidths work. */
599 unsigned char *x_1byte_buffer
600 = (unsigned char *) alloca (2 * FRAME_WINDOW_WIDTH (f)
601 * sizeof (*x_1byte_buffer));
602 register unsigned char *bp; /* Steps through x_1byte_buffer[]. */
603 register int tlen = GLYPH_TABLE_LENGTH;
604 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
605 Window window = FRAME_W32_WINDOW (f);
606 HDC hdc = get_frame_dc (f);
607 int orig_left = left;
608 int gidx = 0;
609 int i;
611 while (n > 0)
613 /* Get the face-code of the next GLYPH. */
614 int cf, len, n_chars;
615 GLYPH g = *gp;
616 int ch, charset;
617 Lisp_Object first_ch;
618 /* HIGHEST and LOWEST are used while drawing a composite
619 character. The meanings are described later. */
620 int highest, lowest;
622 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
623 cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g));
624 ch = FAST_GLYPH_CHAR (g);
625 if (unibyte_display_via_language_environment
626 && SINGLE_BYTE_CHAR_P (ch)
627 && ch >= 160)
628 ch = unibyte_char_to_multibyte (ch);
629 if (gidx == 0) XSETFASTINT (first_ch, ch);
630 charset = CHAR_CHARSET (ch);
631 if (charset == CHARSET_COMPOSITION)
633 /* We must draw components of the composite character on the
634 same column. */
635 cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)];
637 /* Set the face in the slot for work. */
638 cmpcharp->face_work = cf;
640 /* We don't need the return value ... */
641 dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len,
642 hl, just_foreground, cmpcharp);
643 /* ... because the width of just drawn text can be
644 calculated as follows. */
645 left += FONT_WIDTH (FRAME_FONT (f)) * cmpcharp->width;
647 ++gp, --n;
648 while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n;
649 cmpcharp = NULL;
650 continue;
653 /* Find the run of consecutive glyphs which can be drawn with
654 the same DC (i.e. the same charset and the same face-code).
655 Extract their character codes into X_2BYTE_BUFFER.
656 If CMPCHARP is not NULL, face-code is not checked because we
657 use only the face specified in `cmpcharp->face_work'. */
658 cp = x_2byte_buffer;
659 while (n > 0)
661 int this_charset, c1, c2;
663 g = *gp;
664 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
665 ch = FAST_GLYPH_CHAR (g);
666 if (unibyte_display_via_language_environment
667 && SINGLE_BYTE_CHAR_P (ch)
668 && ch >= 160)
669 ch = unibyte_char_to_multibyte (ch);
670 SPLIT_CHAR (ch, this_charset, c1, c2);
671 if (this_charset != charset
672 || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
673 break;
675 if (c2 > 0)
676 *cp = BUILD_WCHAR_T (c1, c2);
677 else
678 *cp = BUILD_WCHAR_T (0, c1);
679 ++cp;
680 ++gp, --n;
681 while (gp && (*gp & GLYPH_MASK_PADDING))
682 ++gp, --n;
685 /* LEN gets the length of the run. */
686 len = cp - x_2byte_buffer;
687 /* Now output this run of chars, with the font and pixel values
688 determined by the face code CF. */
690 struct face *face = FRAME_DEFAULT_FACE (f);
691 XFontStruct *font = NULL;
692 int fontset;
693 struct font_info *fontp;
694 int font_id;
695 COLORREF fg;
696 COLORREF bg;
697 int stippled = 0;
698 int line_height = FRAME_LINE_HEIGHT (f);
699 /* Pixel width of each glyph in this run. */
700 int glyph_width
701 = (FONT_WIDTH (FRAME_FONT (f))
702 * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
703 /* Overall pixel width of this run. */
704 int run_width
705 = (FONT_WIDTH (FRAME_FONT (f))
706 * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
707 /* A flag to tell if we have already filled background. We
708 fill background in advance in the following cases:
709 1) A face has stipple.
710 2) A height of font is shorter than LINE_HEIGHT.
711 3) Drawing a composite character.
712 4) Font has non-zero _MULE_BASELINE_OFFSET property.
713 5) Font is a bdf font.
714 6) Font is italic (italic fonts falsely report their height).
715 After filling background, we draw glyphs by XDrawString16. */
716 int background_filled;
717 /* Baseline position of a character, offset from TOP. */
718 int baseline;
719 /* The property value of `_MULE_RELATIVE_COMPOSE' and
720 `_MULE_DEFAULT_ASCENT'. */
721 int relative_compose = 0, default_ascent = 0;
722 /* 1 if we find no font or a font of inappropriate size. */
723 int require_clipping;
724 RECT clip_rectangle;
725 LPRECT clip_region = NULL;
726 UINT fuOptions = 0;
728 int codepage = CP_DEFAULT;
729 BOOL print_via_unicode = FALSE;
731 /* HL = 3 means use a mouse face previously chosen. */
732 if (hl == 3)
733 cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
735 /* First look at the face of the text itself. */
736 if (cf != 0)
738 /* It's possible for the display table to specify
739 a face code that is out of range. Use 0 in that case. */
740 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
741 || FRAME_COMPUTED_FACES (f) [cf] == 0)
742 cf = 0;
744 if (cf == 1)
745 face = FRAME_MODE_LINE_FACE (f);
746 else
747 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
748 if (FACE_STIPPLE (face))
749 stippled = 1;
752 /* Then comes the distinction between modeline and normal text. */
753 else if (hl == 0)
755 else if (hl == 1)
757 face = FRAME_MODE_LINE_FACE (f);
758 if (FACE_STIPPLE (face))
759 stippled = 1;
762 /* Setting appropriate font and codepage for this charset. */
763 if (charset != CHARSET_ASCII)
765 fontset = FACE_FONTSET (face);
767 if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0)
768 || !(fontp = FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
769 charset, NULL, fontset)))
770 goto font_not_found;
772 font = (XFontStruct *) (fontp->font);
773 codepage = w32_codepage_for_font (fontp->name);
775 if ( font && !font->bdf )
776 print_via_unicode = w32_use_unicode_for_codepage (codepage);
778 baseline = FONT_BASE (font) + fontp->baseline_offset;
780 if (cmpcharp && cmpcharp->cmp_rule == NULL)
782 relative_compose = fontp->relative_compose;
783 default_ascent = fontp->default_ascent;
786 /* We have to change code points in the following cases. */
787 if (fontp->font_encoder)
789 /* This font requires CCL program to calculate code
790 point of characters. */
791 struct ccl_program *ccl = fontp->font_encoder;
793 if (CHARSET_DIMENSION (charset) == 1)
794 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
796 ccl->reg[0] = charset;
797 ccl->reg[1] = BYTE2 (*cp);
798 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
799 /* We assume that MSBs are appropriately
800 set/reset by CCL program. */
801 #if 0 /* this probably works under NT, but not under 95. */
802 if (font->tm.tmLastChar < 256) /* 1-byte font */
803 *cp = BUILD_WCHAR_T (0, ccl->reg[1]);
804 else
805 *cp = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
806 #else /* Assume single dimensional charsets stay so. */
807 *cp = BUILD_WCHAR_T (0, ccl->reg[1]);
808 #endif
810 else
811 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
813 ccl->reg[0] = charset;
814 ccl->reg[1] = BYTE1 (*cp) , ccl->reg[2] = BYTE2 (*cp);
815 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
816 /* We assume that MSBs are appropriately
817 set/reset by CCL program. */
818 #if 0 /* this probably works under NT, but not under 95. */
819 if (font->tm.tmLastChar < 256) /* 1-byte font */
820 *cp = BUILD_WCHAR_T (0, ccl->reg[1]);
821 else
822 *cp = BUILD_WCHAR_T (ccl->reg[1],ccl->reg[2]);
823 #else /* Assume multidimensional charsets stay so. */
824 *cp = BUILD_WCHAR_T (ccl->reg[1],ccl->reg[2]);
825 #endif
828 else if (fontp->encoding[charset])
830 int enc = fontp->encoding[charset];
832 if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2)
833 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
834 *cp = BUILD_WCHAR_T (BYTE1 (*cp) | 0x80, BYTE2 (*cp));
835 if (enc == 1 || enc == 3)
836 for (cp = x_2byte_buffer; cp < x_2byte_buffer + len; cp++)
837 *cp = BUILD_WCHAR_T (BYTE1 (*cp), BYTE2 (*cp) | 0x80);
838 /* Special encoding for SJIS Kanji. */
839 if (enc == 4)
841 if (CHARSET_DIMENSION (charset) == 2)
843 int sjis1, sjis2;
844 for (cp = x_2byte_buffer;
845 cp < x_2byte_buffer + len; cp++)
847 ENCODE_SJIS (BYTE1 (*cp), BYTE2 (*cp),
848 sjis1, sjis2);
849 *cp = BUILD_WCHAR_T (sjis1, sjis2);
852 else
853 for (cp = x_2byte_buffer;
854 cp < x_2byte_buffer + len; cp++)
855 *cp = BUILD_WCHAR_T (BYTE1 (*cp),
856 BYTE2 (*cp) | 0x80);
860 else
862 font_not_found:
863 if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
865 font = FACE_FONT (face);
866 if (!font || font == (XFontStruct *) FACE_DEFAULT)
867 font = FRAME_FONT (f);
868 baseline = FONT_BASE (FRAME_FONT (f));
869 if (charset == charset_latin_iso8859_1)
871 if (!font->bdf && font->tm.tmLastChar < 0x80)
872 /* This font can't display Latin1 characters. */
873 font = NULL;
874 else
876 for (cp = x_2byte_buffer;
877 cp < x_2byte_buffer + len; cp++)
878 *cp = BUILD_WCHAR_T (BYTE1 (*cp),
879 BYTE2 (*cp) | 0x80);
885 fg = face->foreground;
886 bg = face->background;
888 /* Now override that if the cursor's on this character. */
889 if (hl == 2)
891 /* The cursor overrides stippling. */
892 stippled = 0;
894 if (font == FRAME_FONT (f)
895 && face->background == FRAME_BACKGROUND_PIXEL (f)
896 && face->foreground == FRAME_FOREGROUND_PIXEL (f)
897 && !cmpcharp)
899 bg = f->output_data.w32->cursor_pixel;
900 fg = face->background;
902 /* Cursor on non-default face: must merge. */
903 else
905 bg = f->output_data.w32->cursor_pixel;
906 fg = face->background;
907 /* If the glyph would be invisible,
908 try a different foreground. */
909 if (fg == bg)
910 fg = face->foreground;
911 if (fg == bg)
912 fg = f->output_data.w32->cursor_foreground_pixel;
913 if (fg == bg)
914 fg = face->foreground;
915 /* Make sure the cursor is distinct from text in this face. */
916 if (bg == face->background
917 && fg == face->foreground)
919 bg = face->foreground;
920 fg = face->background;
925 if (font)
926 require_clipping = (!NILP (Vclip_large_size_font)
927 && ((font->bdf
928 ? (font->bdf->ury > baseline
929 || font->bdf->lly > line_height - baseline)
930 : (font->tm.tmAscent > baseline
931 || font->tm.tmDescent > line_height - baseline))
932 || (!cmpcharp && FONT_MAX_WIDTH (font) > glyph_width)));
934 if (font && (just_foreground || (cmpcharp && gidx > 0)))
935 background_filled = 1;
937 /* Stippling not supported under w32. */
939 else if (!font
940 || font->bdf
941 || FONT_HEIGHT (font) < line_height
942 || FONT_WIDTH (font) < glyph_width
943 || FONT_MAX_WIDTH (font) != FONT_WIDTH (font)
944 || font->tm.tmItalic
945 || cmpcharp)
947 /* Fill in the background for the current run. */
948 w32_fill_area (f, hdc, bg,
949 left,
950 top,
951 run_width,
952 line_height);
953 background_filled = 1;
954 if (cmpcharp)
955 /* To assure not to fill background while drawing
956 remaining components. */
957 just_foreground = 1;
959 else
960 background_filled = 0;
962 SetBkMode (hdc, background_filled ? TRANSPARENT : OPAQUE);
963 SetTextColor (hdc, fg);
964 SetBkColor (hdc, bg);
965 SetTextAlign (hdc, TA_BASELINE | TA_LEFT);
967 /* On NT, where conversion to Unicode has to happen sometime
968 when using the normal ExtTextOut facility, we might as well
969 take advantage of x_2byte_buffer which is already allocated,
970 to avoid the allocation overhead for implicit conversion. */
972 if (!print_via_unicode
973 && codepage == CP_DEFAULT
974 && w32_enable_unicode_output
975 && os_subtype == OS_NT
976 && font && !font->bdf)
978 print_via_unicode = TRUE;
981 /* Note that we can special-case the conversion to Unicode when
982 the charset is CHARSET_ASCII (an important case) or Latin-1,
983 because x_2byte_buffer in fact already contains the unicode
984 characters. So avoid setting up x_1byte_buffer in that case. */
985 if (!print_via_unicode
986 || (charset != CHARSET_ASCII && charset != charset_latin_iso8859_1))
988 /* Convert x_2byte_buffer into a buffer of single byte
989 characters - possibly containing MBCS runs. */
990 bp = x_1byte_buffer;
991 for (i = 0; i < len; i++)
993 if (BYTE1 (*(x_2byte_buffer + i)))
994 *bp++ = BYTE1 (*(x_2byte_buffer + i));
995 *bp++ = BYTE2 (*(x_2byte_buffer + i));
997 n_chars = bp - x_1byte_buffer;
999 else
1000 n_chars = len;
1002 if (print_via_unicode
1003 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1005 i = MultiByteToWideChar
1006 (codepage, 0, x_1byte_buffer, n_chars,
1007 x_2byte_buffer, FRAME_WINDOW_WIDTH (f));
1009 /* Make sure we don't display nothing if conversion fails. */
1010 if (i == 0)
1011 print_via_unicode = FALSE;
1012 else
1013 n_chars = i;
1016 if (font)
1018 if (font->hfont)
1019 SelectObject (hdc, font->hfont);
1021 if (!cmpcharp)
1023 int xoffset = 0, yoffset = baseline;
1024 if (require_clipping || FONT_WIDTH (font) != glyph_width
1025 || FONT_MAX_WIDTH (font) != FONT_WIDTH (font))
1027 /* The incrementing of i in this loop is done
1028 inside the W32_CHAROUT macro. */
1029 for (i = 0; i < n_chars; )
1031 if (require_clipping)
1033 /* Set up a clipping rectangle for ExtTextOut */
1034 fuOptions |= ETO_CLIPPED;
1035 clip_rectangle.left = left + i * glyph_width;
1036 clip_rectangle.right
1037 = left + (i + 1) * glyph_width;
1038 clip_rectangle.top = top;
1039 clip_rectangle.bottom = top + line_height;
1040 clip_region = &clip_rectangle;
1042 W32_TEXTOUT (i, 1);
1045 else
1047 i = 0;
1048 W32_TEXTOUT (i, n_chars);
1051 else
1053 /* Handle composite characters. */
1054 RECT clip_rectangle;
1055 LPRECT clip_region = NULL;
1056 UINT fuOptions = 0;
1057 ABC char_placement;
1058 int char_width = 0;
1060 if (require_clipping)
1062 /* Set up a clipping rectangle for ExtTextOut */
1063 fuOptions |= ETO_CLIPPED;
1064 clip_rectangle.left = left;
1065 clip_rectangle.right = left + glyph_width;
1066 clip_rectangle.top = top;
1067 clip_rectangle.bottom = top + line_height;
1068 clip_region = &clip_rectangle;
1070 if ((cmpcharp->cmp_rule || relative_compose)
1071 && gidx == 0)
1073 /* This is the first character. Initialize variables.
1074 HIGHEST is the highest position of glyphs ever
1075 written, LOWEST the lowest position. */
1076 int xoffset = 0;
1077 int yoffset = baseline;
1078 int start = 0;
1080 if (default_ascent
1081 && CHAR_TABLE_P (Vuse_default_ascent)
1082 && !NILP (Faref (Vuse_default_ascent, first_ch)))
1084 highest = default_ascent;
1085 lowest = 0;
1087 /* TODO: per char metrics for Truetype and BDF
1088 fonts. */
1090 highest = FONT_BASE (font) + 1;
1091 lowest = - (FONT_HEIGHT (font) - FONT_BASE (font));
1094 if (cmpcharp->cmp_rule)
1095 xoffset = (int)(cmpcharp->col_offset[0]
1096 * FONT_WIDTH (FRAME_FONT (f)));
1098 i = 1;
1100 /* Truetype fonts often contain underhangs to
1101 handle composition characters. This works
1102 against our attempts to position the characters
1103 manually, so we need to compensate for this.
1105 if (print_via_unicode ?
1106 GetCharABCWidthsW (hdc, *x_2byte_buffer,
1107 *x_2byte_buffer,
1108 &char_placement)
1109 : GetCharABCWidths (hdc, *x_1byte_buffer,
1110 *x_1byte_buffer,
1111 &char_placement))
1113 char_width = char_placement.abcA
1114 + char_placement.abcB + char_placement.abcC;
1115 xoffset += FONT_WIDTH (font) - char_width;
1117 /* Don't let characters go beyond the glyph
1118 boundary whatever their over/underhangs. */
1119 if (xoffset > glyph_width - char_width)
1120 xoffset = glyph_width - char_width;
1122 if (xoffset < 0)
1123 xoffset = 0;
1125 /* Draw the first character at the normal
1126 position. */
1127 W32_TEXTOUT (start, 1);
1128 gidx++;
1130 else
1131 i = 0;
1133 for (; i < n_chars; gidx++)
1135 int xoffset = 0, yoffset = FONT_BASE (font);
1137 if (relative_compose)
1139 /* No per char metrics on w32. */
1140 if (NILP (Vignore_relative_composition)
1141 || NILP (Faref (Vignore_relative_composition,
1142 make_number (cmpcharp->glyph[gidx]))))
1144 if (- (FONT_HEIGHT (font) - FONT_BASE (font))
1145 >= relative_compose)
1147 /* Draw above the current glyphs. */
1148 yoffset = highest + FONT_HEIGHT (font);
1149 highest += FONT_HEIGHT (font);
1151 else if (FONT_BASE (font) <= 0)
1153 /* Draw beneath the current glyphs. */
1154 yoffset = lowest;
1155 lowest -= FONT_HEIGHT (font);
1158 else
1160 /* Draw the glyph at normal position. If
1161 it sticks out of HIGHEST or LOWEST,
1162 update them appropriately. */
1163 if (FONT_BASE (font) > highest)
1164 highest = FONT_BASE (font);
1165 else if (- (FONT_HEIGHT (font) - FONT_BASE (font))
1166 < lowest)
1167 lowest = - (FONT_HEIGHT (font) -
1168 FONT_BASE (font));
1171 else if (cmpcharp->cmp_rule)
1173 int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9;
1174 int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9;
1175 int bottom, top;
1177 /* Re-encode GREF and NREF so that they specify
1178 only Y-axis information:
1179 0:top, 1:base, 2:bottom, 3:center */
1180 gref = gref / 3 + (gref == 4) * 2;
1181 nref = nref / 3 + (nref == 4) * 2;
1183 /* No per char metrics on w32. */
1184 bottom = ((gref == 0 ? highest : gref == 1 ? 0
1185 : gref == 2 ? lowest
1186 : (highest + lowest) / 2)
1187 - (nref == 0 ? FONT_HEIGHT (font)
1188 : nref == 1 ? (FONT_HEIGHT (font) -
1189 FONT_BASE (font))
1190 : nref == 2 ? 0
1191 : (FONT_HEIGHT (font) / 2)));
1192 top = bottom + FONT_HEIGHT (font);
1194 if (top > highest)
1195 highest = top;
1196 if (bottom < lowest)
1197 lowest = bottom;
1198 yoffset = bottom + FONT_HEIGHT (font);
1199 xoffset = (int)(cmpcharp->col_offset[gidx]
1200 * FONT_WIDTH (FRAME_FONT(f)));
1203 /* Truetype fonts often contain underhangs to
1204 handle composition characters. This works
1205 against our attempts to position the characters
1206 manually, so we need to compensate for this.
1208 if (print_via_unicode ?
1209 GetCharABCWidthsW (hdc, *(x_2byte_buffer + i),
1210 *(x_2byte_buffer + i),
1211 &char_placement)
1212 : GetCharABCWidths (hdc, *(x_1byte_buffer + i),
1213 *(x_1byte_buffer + i),
1214 &char_placement))
1216 char_width = char_placement.abcA
1217 + char_placement.abcB + char_placement.abcC;
1218 xoffset += FONT_WIDTH (font) - char_width;
1220 /* Don't let characters go beyond the glyph
1221 boundary whatever their over/underhangs. */
1222 if (xoffset > glyph_width - char_width)
1223 xoffset = glyph_width - char_width;
1225 if (xoffset < 0)
1226 xoffset = 0;
1228 W32_TEXTOUT (i, 1);
1232 if (!font)
1234 /* Show rectangles to indicate that we found no font. */
1235 int limit = cmpcharp ? 1 : len;
1236 HBRUSH hb, oldhb;
1237 HPEN hp, oldhp;
1238 hb = CreateSolidBrush (bg);
1239 hp = CreatePen (PS_SOLID, 0, fg);
1240 oldhb = SelectObject(hdc, hb);
1241 oldhp = SelectObject(hdc, hp);
1243 for (i = 0; i < limit; i++)
1244 Rectangle (hdc, left + glyph_width * i, top,
1245 left + glyph_width * (i + 1),
1246 top + line_height);
1248 SelectObject(hdc, oldhb);
1249 SelectObject(hdc, oldhp);
1250 DeleteObject (hb);
1251 DeleteObject (hp);
1253 else if (require_clipping && !NILP (Vhighlight_wrong_size_font))
1255 /* Indicate that we found a font of inappropriate size. */
1256 int limit = cmpcharp ? 1 : len;
1258 for (i = 0; i < limit; i++)
1260 w32_fill_area (f, hdc, fg, left + glyph_width * i,
1261 top + line_height - 1, glyph_width, 1);
1262 w32_fill_area (f, hdc, fg, left + glyph_width * i,
1263 top + line_height - 3, 1, 2);
1268 /* Setting underline position based on the metric of the
1269 current font results in shaky underline if it strides
1270 over different fonts. So, we set the position based only
1271 on the default font of this frame. */
1272 int underline_position = 1;
1274 if (FONT_HEIGHT (FRAME_FONT (f)) - FONT_BASE(FRAME_FONT (f))
1275 <= underline_position)
1276 underline_position = (FONT_HEIGHT (FRAME_FONT (f)) -
1277 FONT_BASE(FRAME_FONT (f))) - 1;
1279 if (face->underline)
1280 w32_fill_area (f, hdc, fg, left,
1281 top + FONT_BASE (FRAME_FONT (f))
1282 + underline_position,
1283 run_width, 1);
1286 if (!cmpcharp)
1287 left += run_width;
1290 release_frame_dc (f, hdc);
1292 return (left - orig_left);
1296 /* Output some text at the nominal frame cursor position.
1297 Advance the cursor over the text.
1298 Output LEN glyphs at START.
1300 `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
1301 controls the pixel values used for foreground and background. */
1303 static void
1304 w32_write_glyphs (start, len)
1305 register GLYPH *start;
1306 int len;
1308 register int temp_length;
1309 struct frame *f;
1311 BLOCK_INPUT;
1313 do_line_dance ();
1314 f = updating_frame;
1315 if (f == 0)
1317 f = selected_frame;
1318 /* If not within an update,
1319 output at the frame's visible cursor. */
1320 curs_x = f->cursor_x;
1321 curs_y = f->cursor_y;
1324 dumpglyphs (f,
1325 CHAR_TO_PIXEL_COL (f, curs_x),
1326 CHAR_TO_PIXEL_ROW (f, curs_y),
1327 start, len, highlight, 0, NULL);
1329 /* If we drew on top of the cursor, note that it is turned off. */
1330 if (curs_y == f->phys_cursor_y
1331 && curs_x <= f->phys_cursor_x
1332 && curs_x + len > f->phys_cursor_x)
1333 f->phys_cursor_on = 0;
1335 if (updating_frame == 0)
1337 f->cursor_x += len;
1338 x_display_cursor (f, 1);
1339 f->cursor_x -= len;
1341 else
1342 curs_x += len;
1344 UNBLOCK_INPUT;
1347 /* Clear to the end of the line.
1348 Erase the current text line from the nominal cursor position (inclusive)
1349 to column FIRST_UNUSED (exclusive). The idea is that everything
1350 from FIRST_UNUSED onward is already erased. */
1352 static void
1353 w32_clear_end_of_line (first_unused)
1354 register int first_unused;
1356 struct frame *f = updating_frame;
1358 if (f == 0)
1359 abort ();
1361 if (curs_y < 0 || curs_y >= f->height)
1362 return;
1363 if (first_unused <= 0)
1364 return;
1366 if (first_unused >= f->width)
1367 first_unused = f->width;
1369 first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
1371 BLOCK_INPUT;
1373 do_line_dance ();
1375 /* Notice if the cursor will be cleared by this operation. */
1376 if (curs_y == f->phys_cursor_y
1377 && curs_x <= f->phys_cursor_x
1378 && f->phys_cursor_x < first_unused)
1379 f->phys_cursor_on = 0;
1381 w32_clear_area (f, NULL,
1382 CHAR_TO_PIXEL_COL (f, curs_x),
1383 CHAR_TO_PIXEL_ROW (f, curs_y),
1384 FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
1385 f->output_data.w32->line_height);
1387 UNBLOCK_INPUT;
1390 static void
1391 w32_clear_frame ()
1393 struct frame *f = updating_frame;
1395 if (f == 0)
1396 f = selected_frame;
1398 f->phys_cursor_on = 0; /* Cursor not visible. */
1399 curs_x = 0; /* Nominal cursor position is top left. */
1400 curs_y = 0;
1402 BLOCK_INPUT;
1404 w32_clear_window (f);
1406 /* We have to clear the scroll bars, too. If we have changed
1407 colors or something like that, then they should be notified. */
1408 x_scroll_bar_clear (f);
1410 UNBLOCK_INPUT;
1413 /* Make audible bell. */
1415 static void
1416 w32_ring_bell (void)
1418 BLOCK_INPUT;
1420 if (visible_bell)
1422 int i;
1423 HWND hwnd = FRAME_W32_WINDOW (selected_frame);
1425 for (i = 0; i < 5; i++)
1427 FlashWindow (hwnd, TRUE);
1428 Sleep (10);
1430 FlashWindow (hwnd, FALSE);
1432 else
1433 w32_sys_ring_bell ();
1435 UNBLOCK_INPUT;
1438 /* Insert and delete character.
1439 These are not supposed to be used because we are supposed to turn
1440 off the feature of using them. */
1442 static void
1443 w32_insert_glyphs (start, len)
1444 register GLYPH *start;
1445 register int len;
1447 abort ();
1450 static void
1451 w32_delete_glyphs (n)
1452 register int n;
1454 abort ();
1457 /* Specify how many text lines, from the top of the window,
1458 should be affected by insert-lines and delete-lines operations.
1459 This, and those operations, are used only within an update
1460 that is bounded by calls to w32_update_begin and w32_update_end. */
1462 static void
1463 w32_set_terminal_window (n)
1464 register int n;
1466 if (updating_frame == 0)
1467 abort ();
1469 if ((n <= 0) || (n > updating_frame->height))
1470 flexlines = updating_frame->height;
1471 else
1472 flexlines = n;
1475 /* These variables need not be per frame
1476 because redisplay is done on a frame-by-frame basis
1477 and the line dance for one frame is finished before
1478 anything is done for another frame. */
1480 /* Array of line numbers from cached insert/delete operations.
1481 line_dance[i] is the old position of the line that we want
1482 to move to line i, or -1 if we want a blank line there. */
1483 static int *line_dance;
1485 /* Allocated length of that array. */
1486 static int line_dance_len;
1488 /* Flag indicating whether we've done any work. */
1489 static int line_dance_in_progress;
1491 /* Perform an insert-lines or delete-lines operation,
1492 inserting N lines or deleting -N lines at vertical position VPOS. */
1494 static void
1495 w32_ins_del_lines (vpos, n)
1496 int vpos, n;
1498 register int fence, i;
1500 if (vpos >= flexlines)
1501 return;
1503 if (!line_dance_in_progress)
1505 int ht = updating_frame->height;
1506 if (ht > line_dance_len)
1508 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
1509 line_dance_len = ht;
1511 for (i = 0; i < ht; ++i) line_dance[i] = i;
1512 line_dance_in_progress = 1;
1514 if (n >= 0)
1516 if (n > flexlines - vpos)
1517 n = flexlines - vpos;
1518 fence = vpos + n;
1519 for (i = flexlines; --i >= fence;)
1520 line_dance[i] = line_dance[i-n];
1521 for (i = fence; --i >= vpos;)
1522 line_dance[i] = -1;
1524 else
1526 n = -n;
1527 if (n > flexlines - vpos)
1528 n = flexlines - vpos;
1529 fence = flexlines - n;
1530 for (i = vpos; i < fence; ++i)
1531 line_dance[i] = line_dance[i + n];
1532 for (i = fence; i < flexlines; ++i)
1533 line_dance[i] = -1;
1537 /* Here's where we actually move the pixels around.
1538 Must be called with input blocked. */
1539 static void
1540 do_line_dance ()
1542 register int i, j, distance;
1543 register struct frame *f;
1544 int ht;
1545 int intborder;
1546 HDC hdc;
1548 /* Must check this flag first. If it's not set, then not only is the
1549 array uninitialized, but we might not even have a frame. */
1550 if (!line_dance_in_progress)
1551 return;
1553 f = updating_frame;
1554 if (f == 0)
1555 abort ();
1557 ht = f->height;
1558 intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f));
1560 x_display_cursor (updating_frame, 0);
1562 hdc = get_frame_dc (f);
1564 for (i = 0; i < ht; ++i)
1565 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
1567 for (j = i; (j < ht && line_dance[j] != -1
1568 && line_dance[j]-j == distance); ++j);
1569 /* Copy [i,j) upward from [i+distance, j+distance) */
1570 BitBlt (hdc,
1571 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
1572 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)),
1573 (j-i) * FRAME_LINE_HEIGHT (f),
1574 hdc,
1575 intborder, CHAR_TO_PIXEL_ROW (f, i),
1576 SRCCOPY);
1577 i = j-1;
1580 for (i = ht; --i >=0; )
1581 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
1583 for (j = i; (--j >= 0 && line_dance[j] != -1
1584 && line_dance[j]-j == distance););
1585 /* Copy (j, i] downward from (j+distance, i+distance] */
1586 BitBlt (hdc,
1587 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
1588 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)),
1589 (i-j) * FRAME_LINE_HEIGHT (f),
1590 hdc,
1591 intborder, CHAR_TO_PIXEL_ROW (f, j+1),
1592 SRCCOPY);
1593 i = j+1;
1596 for (i = 0; i < ht; ++i)
1597 if (line_dance[i] == -1)
1599 for (j = i; j < ht && line_dance[j] == -1; ++j);
1600 /* Clear [i,j) */
1601 w32_clear_area (f, hdc,
1602 intborder,
1603 CHAR_TO_PIXEL_ROW (f, i),
1604 FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (FRAME_FONT (f)),
1605 (j-i) * FRAME_LINE_HEIGHT (f));
1606 i = j-1;
1608 line_dance_in_progress = 0;
1610 release_frame_dc (f, hdc);
1613 /* Support routines for exposure events. */
1614 static void clear_cursor ();
1616 /* Output into a rectangle of a window (for frame F)
1617 the characters in f->phys_lines that overlap that rectangle.
1618 TOP and LEFT are the position of the upper left corner of the rectangle.
1619 ROWS and COLS are the size of the rectangle.
1620 Call this function with input blocked. */
1622 void
1623 dumprectangle (f, left, top, cols, rows)
1624 struct frame *f;
1625 register int left, top, cols, rows;
1627 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1628 int cursor_cleared = 0;
1629 int bottom, right;
1630 register int y;
1632 if (FRAME_GARBAGED_P (f))
1633 return;
1635 /* Express rectangle as four edges, instead of position-and-size. */
1636 bottom = top + rows;
1637 right = left + cols;
1639 /* Convert rectangle edges in pixels to edges in chars.
1640 Round down for left and top, up for right and bottom. */
1641 top = PIXEL_TO_CHAR_ROW (f, top);
1642 left = PIXEL_TO_CHAR_COL (f, left);
1643 bottom += (f->output_data.w32->line_height - 1);
1644 right += (FONT_WIDTH (f->output_data.w32->font) - 1);
1645 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1646 right = PIXEL_TO_CHAR_COL (f, right);
1648 /* Clip the rectangle to what can be visible. */
1649 if (left < FRAME_LEFT_SCROLL_BAR_WIDTH (f))
1650 left = FRAME_LEFT_SCROLL_BAR_WIDTH (f);
1651 if (top < 0)
1652 top = 0;
1653 if (right > f->width + FRAME_LEFT_SCROLL_BAR_WIDTH (f))
1654 right = f->width + FRAME_LEFT_SCROLL_BAR_WIDTH (f);
1655 if (bottom > f->height)
1656 bottom = f->height;
1658 /* Get size in chars of the rectangle. */
1659 cols = right - left;
1660 rows = bottom - top;
1662 /* If rectangle has zero area, return. */
1663 if (rows <= 0) return;
1664 if (cols <= 0) return;
1666 /* Turn off the cursor if it is in the rectangle.
1667 We will turn it back on afterward. */
1668 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1669 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1671 clear_cursor (f);
1672 cursor_cleared = 1;
1675 /* Display the text in the rectangle, one text line at a time. */
1677 for (y = top; y < bottom; y++)
1679 GLYPH *line = &active_frame->glyphs[y][left];
1681 if (! active_frame->enable[y] || left > active_frame->used[y])
1682 continue;
1684 dumpglyphs (f,
1685 CHAR_TO_PIXEL_COL (f, left),
1686 CHAR_TO_PIXEL_ROW (f, y),
1687 line, min (cols, active_frame->used[y] - left),
1688 active_frame->highlight[y], 0, NULL);
1691 /* Turn the cursor on if we turned it off. */
1693 if (cursor_cleared)
1694 x_display_cursor (f, 1);
1697 static void
1698 frame_highlight (f)
1699 struct frame *f;
1701 x_display_cursor (f, 1);
1704 static void
1705 frame_unhighlight (f)
1706 struct frame *f;
1708 x_display_cursor (f, 1);
1711 static void x_frame_rehighlight ();
1713 /* The focus has changed. Update the frames as necessary to reflect
1714 the new situation. Note that we can't change the selected frame
1715 here, because the Lisp code we are interrupting might become confused.
1716 Each event gets marked with the frame in which it occurred, so the
1717 Lisp code can tell when the switch took place by examining the events. */
1719 void
1720 x_new_focus_frame (dpyinfo, frame)
1721 struct w32_display_info *dpyinfo;
1722 struct frame *frame;
1724 struct frame *old_focus = dpyinfo->w32_focus_frame;
1725 int events_enqueued = 0;
1727 if (frame != dpyinfo->w32_focus_frame)
1729 /* Set this before calling other routines, so that they see
1730 the correct value of w32_focus_frame. */
1731 dpyinfo->w32_focus_frame = frame;
1733 if (old_focus && old_focus->auto_lower)
1734 x_lower_frame (old_focus);
1736 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
1737 pending_autoraise_frame = dpyinfo->w32_focus_frame;
1738 else
1739 pending_autoraise_frame = 0;
1742 x_frame_rehighlight (dpyinfo);
1745 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1747 void
1748 x_mouse_leave (dpyinfo)
1749 struct w32_display_info *dpyinfo;
1751 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
1754 /* The focus has changed, or we have redirected a frame's focus to
1755 another frame (this happens when a frame uses a surrogate
1756 minibuffer frame). Shift the highlight as appropriate.
1758 The FRAME argument doesn't necessarily have anything to do with which
1759 frame is being highlighted or unhighlighted; we only use it to find
1760 the appropriate display info. */
1761 static void
1762 w32_frame_rehighlight (frame)
1763 struct frame *frame;
1765 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
1768 static void
1769 x_frame_rehighlight (dpyinfo)
1770 struct w32_display_info *dpyinfo;
1772 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
1774 if (dpyinfo->w32_focus_frame)
1776 dpyinfo->w32_highlight_frame
1777 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
1778 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
1779 : dpyinfo->w32_focus_frame);
1780 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
1782 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
1783 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
1786 else
1787 dpyinfo->w32_highlight_frame = 0;
1789 if (dpyinfo->w32_highlight_frame != old_highlight)
1791 if (old_highlight)
1792 frame_unhighlight (old_highlight);
1793 if (dpyinfo->w32_highlight_frame)
1794 frame_highlight (dpyinfo->w32_highlight_frame);
1798 /* Keyboard processing - modifier keys, etc. */
1800 /* Convert a keysym to its name. */
1802 char *
1803 x_get_keysym_name (keysym)
1804 int keysym;
1806 /* Make static so we can always return it */
1807 static char value[100];
1809 BLOCK_INPUT;
1810 GetKeyNameText(keysym, value, 100);
1811 UNBLOCK_INPUT;
1813 return value;
1816 /* Mouse clicks and mouse movement. Rah. */
1818 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1819 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1820 that the glyph at X, Y occupies, if BOUNDS != 0.
1821 If NOCLIP is nonzero, do not force the value into range. */
1823 void
1824 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1825 FRAME_PTR f;
1826 register int pix_x, pix_y;
1827 register int *x, *y;
1828 RECT *bounds;
1829 int noclip;
1831 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1832 if (NILP (Vwindow_system))
1834 *x = pix_x;
1835 *y = pix_y;
1836 return;
1839 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1840 even for negative values. */
1841 if (pix_x < 0)
1842 pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
1843 if (pix_y < 0)
1844 pix_y -= (f)->output_data.w32->line_height - 1;
1846 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1847 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1849 if (bounds)
1851 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
1852 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
1853 bounds->right = bounds->left + FONT_WIDTH (f->output_data.w32->font) - 1;
1854 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
1857 if (!noclip)
1859 if (pix_x < 0)
1860 pix_x = 0;
1861 else if (pix_x > f->width)
1862 pix_x = f->width;
1864 if (pix_y < 0)
1865 pix_y = 0;
1866 else if (pix_y > f->height)
1867 pix_y = f->height;
1870 *x = pix_x;
1871 *y = pix_y;
1874 void
1875 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1876 FRAME_PTR f;
1877 register int x, y;
1878 register int *pix_x, *pix_y;
1880 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
1881 if (NILP (Vwindow_system))
1883 *pix_x = x;
1884 *pix_y = y;
1885 return;
1888 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1889 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1892 BOOL
1893 parse_button (message, pbutton, pup)
1894 int message;
1895 int * pbutton;
1896 int * pup;
1898 int button = 0;
1899 int up = 0;
1901 switch (message)
1903 case WM_LBUTTONDOWN:
1904 button = 0;
1905 up = 0;
1906 break;
1907 case WM_LBUTTONUP:
1908 button = 0;
1909 up = 1;
1910 break;
1911 case WM_MBUTTONDOWN:
1912 if (NILP (Vw32_swap_mouse_buttons))
1913 button = 1;
1914 else
1915 button = 2;
1916 up = 0;
1917 break;
1918 case WM_MBUTTONUP:
1919 if (NILP (Vw32_swap_mouse_buttons))
1920 button = 1;
1921 else
1922 button = 2;
1923 up = 1;
1924 break;
1925 case WM_RBUTTONDOWN:
1926 if (NILP (Vw32_swap_mouse_buttons))
1927 button = 2;
1928 else
1929 button = 1;
1930 up = 0;
1931 break;
1932 case WM_RBUTTONUP:
1933 if (NILP (Vw32_swap_mouse_buttons))
1934 button = 2;
1935 else
1936 button = 1;
1937 up = 1;
1938 break;
1939 default:
1940 return (FALSE);
1943 if (pup) *pup = up;
1944 if (pbutton) *pbutton = button;
1946 return (TRUE);
1950 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1952 If the event is a button press, then note that we have grabbed
1953 the mouse. */
1955 static void
1956 construct_mouse_click (result, msg, f)
1957 struct input_event *result;
1958 W32Msg *msg;
1959 struct frame *f;
1961 int button;
1962 int up;
1964 parse_button (msg->msg.message, &button, &up);
1966 /* Make the event type no_event; we'll change that when we decide
1967 otherwise. */
1968 result->kind = mouse_click;
1969 result->code = button;
1970 result->timestamp = msg->msg.time;
1971 result->modifiers = (msg->dwModifiers
1972 | (up
1973 ? up_modifier
1974 : down_modifier));
1977 int row, column;
1979 XSETINT (result->x, LOWORD (msg->msg.lParam));
1980 XSETINT (result->y, HIWORD (msg->msg.lParam));
1981 XSETFRAME (result->frame_or_window, f);
1985 static void
1986 construct_mouse_wheel (result, msg, f)
1987 struct input_event *result;
1988 W32Msg *msg;
1989 struct frame *f;
1991 POINT p;
1992 result->kind = mouse_wheel;
1993 result->code = (short) HIWORD (msg->msg.wParam);
1994 result->timestamp = msg->msg.time;
1995 result->modifiers = msg->dwModifiers;
1996 p.x = LOWORD (msg->msg.lParam);
1997 p.y = HIWORD (msg->msg.lParam);
1998 ScreenToClient(msg->msg.hwnd, &p);
1999 XSETINT (result->x, p.x);
2000 XSETINT (result->y, p.y);
2001 XSETFRAME (result->frame_or_window, f);
2004 static void
2005 construct_drag_n_drop (result, msg, f)
2006 struct input_event *result;
2007 W32Msg *msg;
2008 struct frame *f;
2010 Lisp_Object files;
2011 Lisp_Object frame;
2012 HDROP hdrop;
2013 POINT p;
2014 WORD num_files;
2015 char *name;
2016 int i, len;
2018 result->kind = drag_n_drop;
2019 result->code = 0;
2020 result->timestamp = msg->msg.time;
2021 result->modifiers = msg->dwModifiers;
2023 hdrop = (HDROP) msg->msg.wParam;
2024 DragQueryPoint (hdrop, &p);
2026 #if 0
2027 p.x = LOWORD (msg->msg.lParam);
2028 p.y = HIWORD (msg->msg.lParam);
2029 ScreenToClient (msg->msg.hwnd, &p);
2030 #endif
2032 XSETINT (result->x, p.x);
2033 XSETINT (result->y, p.y);
2035 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
2036 files = Qnil;
2038 for (i = 0; i < num_files; i++)
2040 len = DragQueryFile (hdrop, i, NULL, 0);
2041 if (len <= 0)
2042 continue;
2043 name = alloca (len + 1);
2044 DragQueryFile (hdrop, i, name, len + 1);
2045 files = Fcons (build_string (name), files);
2048 DragFinish (hdrop);
2050 XSETFRAME (frame, f);
2051 result->frame_or_window = Fcons (frame, files);
2055 /* Function to report a mouse movement to the mainstream Emacs code.
2056 The input handler calls this.
2058 We have received a mouse movement event, which is given in *event.
2059 If the mouse is over a different glyph than it was last time, tell
2060 the mainstream emacs code by setting mouse_moved. If not, ask for
2061 another motion event, so we can check again the next time it moves. */
2063 static void
2064 note_mouse_movement (frame, msg)
2065 FRAME_PTR frame;
2066 MSG *msg;
2068 last_mouse_movement_time = msg->time;
2070 if (msg->hwnd != FRAME_W32_WINDOW (frame))
2072 frame->mouse_moved = 1;
2073 last_mouse_scroll_bar = Qnil;
2075 note_mouse_highlight (frame, -1, -1);
2078 /* Has the mouse moved off the glyph it was on at the last sighting? */
2079 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
2080 || LOWORD (msg->lParam) > last_mouse_glyph.right
2081 || HIWORD (msg->lParam) < last_mouse_glyph.top
2082 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
2084 frame->mouse_moved = 1;
2085 last_mouse_scroll_bar = Qnil;
2087 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
2091 /* This is used for debugging, to turn off note_mouse_highlight. */
2092 static int disable_mouse_highlight;
2094 /* Take proper action when the mouse has moved to position X, Y on frame F
2095 as regards highlighting characters that have mouse-face properties.
2096 Also dehighlighting chars where the mouse was before.
2097 X and Y can be negative or out of range. */
2099 static void
2100 note_mouse_highlight (f, x, y)
2101 FRAME_PTR f;
2102 int x, y;
2104 int row, column, portion;
2105 RECT new_glyph;
2106 Lisp_Object window;
2107 struct window *w;
2109 if (disable_mouse_highlight)
2110 return;
2112 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
2113 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
2114 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
2116 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
2117 return;
2119 if (gc_in_progress)
2121 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
2122 return;
2125 /* Find out which glyph the mouse is on. */
2126 pixel_to_glyph_coords (f, x, y, &column, &row,
2127 &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
2129 /* Which window is that in? */
2130 window = window_from_coordinates (f, column, row, &portion);
2131 w = XWINDOW (window);
2133 /* If we were displaying active text in another window, clear that. */
2134 if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
2135 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2137 /* Are we in a window whose display is up to date?
2138 And verify the buffer's text has not changed. */
2139 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
2140 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
2141 && EQ (w->window_end_valid, w->buffer)
2142 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
2143 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
2145 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
2146 int i, pos;
2148 /* Find which buffer position the mouse corresponds to. */
2149 for (i = column; i >= 0; i--)
2150 if (ptr[i] > 0)
2151 break;
2152 pos = ptr[i];
2153 /* Is it outside the displayed active region (if any)? */
2154 if (pos <= 0)
2155 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2156 else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
2157 && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2158 && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2159 && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2160 || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
2161 && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2162 || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
2163 || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
2165 Lisp_Object mouse_face, overlay, position;
2166 Lisp_Object *overlay_vec;
2167 int len, noverlays, ignor1;
2168 struct buffer *obuf;
2169 int obegv, ozv;
2171 /* If we get an out-of-range value, return now; avoid an error. */
2172 if (pos > BUF_Z (XBUFFER (w->buffer)))
2173 return;
2175 /* Make the window's buffer temporarily current for
2176 overlays_at and compute_char_face. */
2177 obuf = current_buffer;
2178 current_buffer = XBUFFER (w->buffer);
2179 obegv = BEGV;
2180 ozv = ZV;
2181 BEGV = BEG;
2182 ZV = Z;
2184 /* Yes. Clear the display of the old active region, if any. */
2185 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
2187 /* Is this char mouse-active? */
2188 XSETINT (position, pos);
2190 len = 10;
2191 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
2193 /* Put all the overlays we want in a vector in overlay_vec.
2194 Store the length in len. */
2195 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
2196 NULL, NULL);
2197 noverlays = sort_overlays (overlay_vec, noverlays, w);
2199 /* Find the highest priority overlay that has a mouse-face prop. */
2200 overlay = Qnil;
2201 for (i = 0; i < noverlays; i++)
2203 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2204 if (!NILP (mouse_face))
2206 overlay = overlay_vec[i];
2207 break;
2210 free (overlay_vec);
2211 /* If no overlay applies, get a text property. */
2212 if (NILP (overlay))
2213 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
2215 /* Handle the overlay case. */
2216 if (! NILP (overlay))
2218 /* Find the range of text around this char that
2219 should be active. */
2220 Lisp_Object before, after;
2221 int ignore;
2223 before = Foverlay_start (overlay);
2224 after = Foverlay_end (overlay);
2225 /* Record this as the current active region. */
2226 fast_find_position (window, before,
2227 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
2228 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
2229 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
2230 = !fast_find_position (window, after,
2231 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
2232 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
2233 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
2234 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
2235 = compute_char_face (f, w, pos, 0, 0,
2236 &ignore, pos + 1, 1);
2238 /* Display it as active. */
2239 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
2241 /* Handle the text property case. */
2242 else if (! NILP (mouse_face))
2244 /* Find the range of text around this char that
2245 should be active. */
2246 Lisp_Object before, after, beginning, end;
2247 int ignore;
2249 beginning = Fmarker_position (w->start);
2250 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
2251 - XFASTINT (w->window_end_pos)));
2252 before
2253 = Fprevious_single_property_change (make_number (pos + 1),
2254 Qmouse_face,
2255 w->buffer, beginning);
2256 after
2257 = Fnext_single_property_change (position, Qmouse_face,
2258 w->buffer, end);
2259 /* Record this as the current active region. */
2260 fast_find_position (window, before,
2261 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
2262 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
2263 FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
2264 = !fast_find_position (window, after,
2265 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
2266 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
2267 FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
2268 FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
2269 = compute_char_face (f, w, pos, 0, 0,
2270 &ignore, pos + 1, 1);
2272 /* Display it as active. */
2273 show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
2275 BEGV = obegv;
2276 ZV = ozv;
2277 current_buffer = obuf;
2282 /* Find the row and column of position POS in window WINDOW.
2283 Store them in *COLUMNP and *ROWP.
2284 This assumes display in WINDOW is up to date.
2285 If POS is above start of WINDOW, return coords
2286 of start of first screen line.
2287 If POS is after end of WINDOW, return coords of end of last screen line.
2289 Value is 1 if POS is in range, 0 if it was off screen. */
2291 static int
2292 fast_find_position (window, pos, columnp, rowp)
2293 Lisp_Object window;
2294 int pos;
2295 int *columnp, *rowp;
2297 struct window *w = XWINDOW (window);
2298 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2299 int i;
2300 int row = 0;
2301 int left = WINDOW_LEFT_MARGIN (w);
2302 int top = w->top;
2303 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
2304 int width = window_internal_width (w);
2305 int *charstarts;
2306 int lastcol;
2307 int maybe_next_line = 0;
2309 /* Find the right row. */
2310 for (i = 0;
2311 i < height;
2312 i++)
2314 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
2315 if (linestart > pos)
2316 break;
2317 /* If the position sought is the end of the buffer,
2318 don't include the blank lines at the bottom of the window. */
2319 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
2321 maybe_next_line = 1;
2322 break;
2324 if (linestart > 0)
2325 row = i;
2328 /* Find the right column with in it. */
2329 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
2330 lastcol = left;
2331 for (i = 0; i < width; i++)
2333 if (charstarts[left + i] == pos)
2335 *rowp = row + top;
2336 *columnp = i + left;
2337 return 1;
2339 else if (charstarts[left + i] > pos)
2340 break;
2341 else if (charstarts[left + i] > 0)
2342 lastcol = left + i;
2345 /* If we're looking for the end of the buffer,
2346 and we didn't find it in the line we scanned,
2347 use the start of the following line. */
2348 if (maybe_next_line)
2350 row++;
2351 i = 0;
2354 *rowp = row + top;
2355 *columnp = lastcol;
2356 return 0;
2359 /* Display the active region described by mouse_face_*
2360 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2362 static void
2363 show_mouse_face (dpyinfo, hl)
2364 struct w32_display_info *dpyinfo;
2365 int hl;
2367 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
2368 int width = window_internal_width (w);
2369 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2370 int i;
2371 int cursor_off = 0;
2372 int old_curs_x = curs_x;
2373 int old_curs_y = curs_y;
2375 /* Set these variables temporarily
2376 so that if we have to turn the cursor off and on again
2377 we will put it back at the same place. */
2378 curs_x = f->phys_cursor_x;
2379 curs_y = f->phys_cursor_y;
2381 for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
2382 i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
2384 int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
2385 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
2386 : WINDOW_LEFT_MARGIN (w));
2387 int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
2388 ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
2389 : WINDOW_LEFT_MARGIN (w) + width);
2390 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
2392 /* If the cursor's in the text we are about to rewrite,
2393 turn the cursor off. */
2394 if (i == curs_y
2395 && curs_x >= column - 1
2396 && curs_x <= endcolumn)
2398 x_display_cursor (f, 0);
2399 cursor_off = 1;
2402 dumpglyphs (f,
2403 CHAR_TO_PIXEL_COL (f, column),
2404 CHAR_TO_PIXEL_ROW (f, i),
2405 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
2406 endcolumn - column,
2407 /* Highlight with mouse face if hl > 0. */
2408 hl > 0 ? 3 : 0, 0, NULL);
2411 /* If we turned the cursor off, turn it back on. */
2412 if (cursor_off)
2413 x_display_cursor (f, 1);
2415 curs_x = old_curs_x;
2416 curs_y = old_curs_y;
2418 /* Change the mouse cursor according to the value of HL. */
2419 if (hl > 0)
2420 SetCursor (f->output_data.w32->cross_cursor);
2421 else
2422 SetCursor (f->output_data.w32->text_cursor);
2425 /* Clear out the mouse-highlighted active region.
2426 Redraw it unhighlighted first. */
2428 static void
2429 clear_mouse_face (dpyinfo)
2430 struct w32_display_info *dpyinfo;
2432 if (! NILP (dpyinfo->mouse_face_window))
2433 show_mouse_face (dpyinfo, 0);
2435 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2436 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2437 dpyinfo->mouse_face_window = Qnil;
2440 struct scroll_bar *x_window_to_scroll_bar ();
2441 static void x_scroll_bar_report_motion ();
2443 /* Return the current position of the mouse.
2444 *fp should be a frame which indicates which display to ask about.
2446 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2447 and *part to the frame, window, and scroll bar part that the mouse
2448 is over. Set *x and *y to the portion and whole of the mouse's
2449 position on the scroll bar.
2451 If the mouse movement started elsewhere, set *fp to the frame the
2452 mouse is on, *bar_window to nil, and *x and *y to the character cell
2453 the mouse is over.
2455 Set *time to the server timestamp for the time at which the mouse
2456 was at this position.
2458 Don't store anything if we don't have a valid set of values to report.
2460 This clears the mouse_moved flag, so we can wait for the next mouse
2461 movement. This also calls XQueryPointer, which will cause the
2462 server to give us another MotionNotify when the mouse moves
2463 again. */
2465 static void
2466 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
2467 FRAME_PTR *fp;
2468 int insist;
2469 Lisp_Object *bar_window;
2470 enum scroll_bar_part *part;
2471 Lisp_Object *x, *y;
2472 unsigned long *time;
2474 FRAME_PTR f1;
2476 BLOCK_INPUT;
2478 if (! NILP (last_mouse_scroll_bar) && insist == 0)
2479 /* This is never called at the moment. */
2480 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
2481 else
2483 POINT pt;
2485 Lisp_Object frame, tail;
2487 /* Clear the mouse-moved flag for every frame on this display. */
2488 FOR_EACH_FRAME (tail, frame)
2489 XFRAME (frame)->mouse_moved = 0;
2491 last_mouse_scroll_bar = Qnil;
2493 GetCursorPos (&pt);
2495 /* Now we have a position on the root; find the innermost window
2496 containing the pointer. */
2498 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
2499 && FRAME_LIVE_P (last_mouse_frame))
2501 f1 = last_mouse_frame;
2503 else
2505 /* Is win one of our frames? */
2506 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
2509 /* If not, is it one of our scroll bars? */
2510 if (! f1)
2512 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
2514 if (bar)
2516 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2520 if (f1 == 0 && insist > 0)
2521 f1 = selected_frame;
2523 if (f1)
2525 int ignore1, ignore2;
2527 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
2529 /* Ok, we found a frame. Store all the values. */
2531 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
2532 &last_mouse_glyph,
2533 FRAME_W32_DISPLAY_INFO (f1)->grabbed
2534 || insist);
2536 *bar_window = Qnil;
2537 *part = 0;
2538 *fp = f1;
2539 XSETINT (*x, pt.x);
2540 XSETINT (*y, pt.y);
2541 *time = last_mouse_movement_time;
2546 UNBLOCK_INPUT;
2549 /* Scroll bar support. */
2551 /* Given an window ID, find the struct scroll_bar which manages it.
2552 This can be called in GC, so we have to make sure to strip off mark
2553 bits. */
2554 struct scroll_bar *
2555 x_window_to_scroll_bar (window_id)
2556 Window window_id;
2558 Lisp_Object tail, frame;
2560 for (tail = Vframe_list;
2561 XGCTYPE (tail) == Lisp_Cons;
2562 tail = XCONS (tail)->cdr)
2564 Lisp_Object frame, bar, condemned;
2566 frame = XCONS (tail)->car;
2567 /* All elements of Vframe_list should be frames. */
2568 if (! GC_FRAMEP (frame))
2569 abort ();
2571 /* Scan this frame's scroll bar list for a scroll bar with the
2572 right window ID. */
2573 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
2574 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
2575 /* This trick allows us to search both the ordinary and
2576 condemned scroll bar lists with one loop. */
2577 ! GC_NILP (bar) || (bar = condemned,
2578 condemned = Qnil,
2579 ! GC_NILP (bar));
2580 bar = XSCROLL_BAR (bar)->next)
2581 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
2582 return XSCROLL_BAR (bar);
2585 return 0;
2588 HWND
2589 my_create_scrollbar (f, bar)
2590 struct frame * f;
2591 struct scroll_bar * bar;
2593 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
2594 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
2595 (LPARAM) bar);
2598 //#define ATTACH_THREADS
2600 BOOL
2601 my_show_window (FRAME_PTR f, HWND hwnd, int how)
2603 #ifndef ATTACH_THREADS
2604 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
2605 (WPARAM) hwnd, (LPARAM) how);
2606 #else
2607 return ShowWindow (hwnd, how);
2608 #endif
2611 void
2612 my_set_window_pos (HWND hwnd, HWND hwndAfter,
2613 int x, int y, int cx, int cy, UINT flags)
2615 #ifndef ATTACH_THREADS
2616 WINDOWPOS pos;
2617 pos.hwndInsertAfter = hwndAfter;
2618 pos.x = x;
2619 pos.y = y;
2620 pos.cx = cx;
2621 pos.cy = cy;
2622 pos.flags = flags;
2623 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
2624 #else
2625 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
2626 #endif
2629 BOOL
2630 my_set_focus (f, hwnd)
2631 struct frame * f;
2632 HWND hwnd;
2634 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
2635 (WPARAM) hwnd, 0);
2638 BOOL
2639 my_set_foreground_window (hwnd)
2640 HWND hwnd;
2642 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
2645 void
2646 my_destroy_window (f, hwnd)
2647 struct frame * f;
2648 HWND hwnd;
2650 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
2651 (WPARAM) hwnd, 0);
2654 /* Open a new window to serve as a scroll bar, and return the
2655 scroll bar vector for it. */
2656 static struct scroll_bar *
2657 x_scroll_bar_create (window, top, left, width, height)
2658 struct window *window;
2659 int top, left, width, height;
2661 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2662 struct scroll_bar *bar
2663 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
2664 HWND hwnd;
2666 BLOCK_INPUT;
2668 XSETWINDOW (bar->window, window);
2669 XSETINT (bar->top, top);
2670 XSETINT (bar->left, left);
2671 XSETINT (bar->width, width);
2672 XSETINT (bar->height, height);
2673 XSETINT (bar->start, 0);
2674 XSETINT (bar->end, 0);
2675 bar->dragging = Qnil;
2677 /* Requires geometry to be set before call to create the real window */
2679 hwnd = my_create_scrollbar (f, bar);
2681 if (pfnSetScrollInfo)
2683 SCROLLINFO si;
2685 si.cbSize = sizeof (si);
2686 si.fMask = SIF_ALL;
2687 si.nMin = 0;
2688 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
2689 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2690 si.nPage = si.nMax;
2691 si.nPos = 0;
2693 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
2695 else
2697 SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
2698 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
2701 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
2703 /* Add bar to its frame's list of scroll bars. */
2704 bar->next = FRAME_SCROLL_BARS (f);
2705 bar->prev = Qnil;
2706 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2707 if (! NILP (bar->next))
2708 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2710 UNBLOCK_INPUT;
2712 return bar;
2715 /* Draw BAR's handle in the proper position.
2716 If the handle is already drawn from START to END, don't bother
2717 redrawing it, unless REBUILD is non-zero; in that case, always
2718 redraw it. (REBUILD is handy for drawing the handle after expose
2719 events.)
2721 Normally, we want to constrain the start and end of the handle to
2722 fit inside its rectangle, but if the user is dragging the scroll bar
2723 handle, we want to let them drag it down all the way, so that the
2724 bar's top is as far down as it goes; otherwise, there's no way to
2725 move to the very end of the buffer. */
2726 static void
2727 x_scroll_bar_set_handle (bar, start, end, rebuild)
2728 struct scroll_bar *bar;
2729 int start, end;
2730 int rebuild;
2732 int dragging = ! NILP (bar->dragging);
2733 Window w = SCROLL_BAR_W32_WINDOW (bar);
2734 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2736 /* If the display is already accurate, do nothing. */
2737 if (! rebuild
2738 && start == XINT (bar->start)
2739 && end == XINT (bar->end))
2740 return;
2742 BLOCK_INPUT;
2745 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2747 /* Make sure the values are reasonable, and try to preserve
2748 the distance between start and end. */
2750 int length = end - start;
2752 if (start < 0)
2753 start = 0;
2754 else if (start > top_range)
2755 start = top_range;
2756 end = start + length;
2758 if (end < start)
2759 end = start;
2760 else if (end > top_range && ! dragging)
2761 end = top_range;
2765 /* Store the adjusted setting in the scroll bar. */
2766 XSETINT (bar->start, start);
2767 XSETINT (bar->end, end);
2769 /* If being dragged, let scroll bar update itself. */
2770 if (!dragging)
2772 if (pfnSetScrollInfo)
2774 SCROLLINFO si;
2776 si.cbSize = sizeof (si);
2777 si.fMask = SIF_PAGE | SIF_POS;
2778 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2779 si.nPos = start;
2781 pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
2783 else
2784 SetScrollPos (w, SB_CTL, start, TRUE);
2787 UNBLOCK_INPUT;
2790 /* Move a scroll bar around on the screen, to accommodate changing
2791 window configurations. */
2792 static void
2793 x_scroll_bar_move (bar, top, left, width, height)
2794 struct scroll_bar *bar;
2795 int top, left, width, height;
2797 Window w = SCROLL_BAR_W32_WINDOW (bar);
2798 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2800 /* If already correctly positioned, do nothing. */
2801 if ( XINT (bar->left) == left
2802 && XINT (bar->top) == top
2803 && XINT (bar->width) == width
2804 && XINT (bar->height) == height )
2806 /* Redraw after clear_frame. */
2807 if (!my_show_window (f, w, SW_NORMAL))
2808 InvalidateRect (w, NULL, FALSE);
2809 return;
2812 BLOCK_INPUT;
2814 /* Make sure scroll bar is "visible" before moving, to ensure the
2815 area of the parent window now exposed will be refreshed. */
2816 my_show_window (f, w, SW_HIDE);
2817 MoveWindow (w, left, top, width, height, TRUE);
2818 if (pfnSetScrollInfo)
2820 SCROLLINFO si;
2822 si.cbSize = sizeof (si);
2823 si.fMask = SIF_RANGE;
2824 si.nMin = 0;
2825 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
2826 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
2828 pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
2830 else
2831 SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
2832 my_show_window (f, w, SW_NORMAL);
2833 // InvalidateRect (w, NULL, FALSE);
2835 XSETINT (bar->left, left);
2836 XSETINT (bar->top, top);
2837 XSETINT (bar->width, width);
2838 XSETINT (bar->height, height);
2840 UNBLOCK_INPUT;
2843 /* Destroy the window for BAR, and set its Emacs window's scroll bar
2844 to nil. */
2845 static void
2846 x_scroll_bar_remove (bar)
2847 struct scroll_bar *bar;
2849 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2851 BLOCK_INPUT;
2853 /* Destroy the window. */
2854 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
2856 /* Disassociate this scroll bar from its window. */
2857 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2859 UNBLOCK_INPUT;
2862 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2863 that we are displaying PORTION characters out of a total of WHOLE
2864 characters, starting at POSITION. If WINDOW has no scroll bar,
2865 create one. */
2866 static void
2867 w32_set_vertical_scroll_bar (window, portion, whole, position)
2868 struct window *window;
2869 int portion, whole, position;
2871 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2872 int top = XINT (window->top);
2873 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2874 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2876 /* Where should this scroll bar be, pixelwise? */
2877 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2878 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2879 int pixel_width
2880 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2881 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2882 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
2883 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2885 struct scroll_bar *bar;
2887 /* Does the scroll bar exist yet? */
2888 if (NILP (window->vertical_scroll_bar))
2889 bar = x_scroll_bar_create (window,
2890 pixel_top, pixel_left,
2891 pixel_width, pixel_height);
2892 else
2894 /* It may just need to be moved and resized. */
2895 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2896 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2899 /* Set the scroll bar's current state. */
2901 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2903 if (whole == 0)
2904 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2905 else
2907 int start = (int) (((double) position * top_range) / whole);
2908 int end = (int) (((double) (position + portion) * top_range) / whole);
2910 x_scroll_bar_set_handle (bar, start, end, 0);
2914 XSETVECTOR (window->vertical_scroll_bar, bar);
2918 /* The following three hooks are used when we're doing a thorough
2919 redisplay of the frame. We don't explicitly know which scroll bars
2920 are going to be deleted, because keeping track of when windows go
2921 away is a real pain - "Can you say set-window-configuration, boys
2922 and girls?" Instead, we just assert at the beginning of redisplay
2923 that *all* scroll bars are to be removed, and then save a scroll bar
2924 from the fiery pit when we actually redisplay its window. */
2926 /* Arrange for all scroll bars on FRAME to be removed at the next call
2927 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2928 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2929 static void
2930 w32_condemn_scroll_bars (frame)
2931 FRAME_PTR frame;
2933 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2934 while (! NILP (FRAME_SCROLL_BARS (frame)))
2936 Lisp_Object bar;
2937 bar = FRAME_SCROLL_BARS (frame);
2938 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
2939 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
2940 XSCROLL_BAR (bar)->prev = Qnil;
2941 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2942 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
2943 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
2945 #ifdef PIGSFLY
2946 /* The condemned list should be empty at this point; if it's not,
2947 then the rest of Emacs isn't using the condemn/redeem/judge
2948 protocol correctly. */
2949 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2950 abort ();
2952 /* Move them all to the "condemned" list. */
2953 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2954 FRAME_SCROLL_BARS (frame) = Qnil;
2955 #endif
2958 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2959 Note that WINDOW isn't necessarily condemned at all. */
2960 static void
2961 w32_redeem_scroll_bar (window)
2962 struct window *window;
2964 struct scroll_bar *bar;
2966 /* We can't redeem this window's scroll bar if it doesn't have one. */
2967 if (NILP (window->vertical_scroll_bar))
2968 abort ();
2970 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2972 /* Unlink it from the condemned list. */
2974 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2976 if (NILP (bar->prev))
2978 /* If the prev pointer is nil, it must be the first in one of
2979 the lists. */
2980 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2981 /* It's not condemned. Everything's fine. */
2982 return;
2983 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2984 window->vertical_scroll_bar))
2985 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2986 else
2987 /* If its prev pointer is nil, it must be at the front of
2988 one or the other! */
2989 abort ();
2991 else
2992 XSCROLL_BAR (bar->prev)->next = bar->next;
2994 if (! NILP (bar->next))
2995 XSCROLL_BAR (bar->next)->prev = bar->prev;
2997 bar->next = FRAME_SCROLL_BARS (f);
2998 bar->prev = Qnil;
2999 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3000 if (! NILP (bar->next))
3001 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3003 #ifdef PIGSFLY
3004 struct scroll_bar *bar;
3006 /* We can't redeem this window's scroll bar if it doesn't have one. */
3007 if (NILP (window->vertical_scroll_bar))
3008 abort ();
3010 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3012 /* Unlink it from the condemned list. */
3014 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
3016 if (NILP (bar->prev))
3018 /* If the prev pointer is nil, it must be the first in one of
3019 the lists. */
3020 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3021 /* It's not condemned. Everything's fine. */
3022 return;
3023 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3024 window->vertical_scroll_bar))
3025 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3026 else
3027 /* If its prev pointer is nil, it must be at the front of
3028 one or the other! */
3029 abort ();
3031 else
3032 XSCROLL_BAR (bar->prev)->next = bar->next;
3034 if (! NILP (bar->next))
3035 XSCROLL_BAR (bar->next)->prev = bar->prev;
3037 bar->next = FRAME_SCROLL_BARS (f);
3038 bar->prev = Qnil;
3039 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3040 if (! NILP (bar->next))
3041 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3043 #endif
3046 /* Remove all scroll bars on FRAME that haven't been saved since the
3047 last call to `*condemn_scroll_bars_hook'. */
3048 static void
3049 w32_judge_scroll_bars (f)
3050 FRAME_PTR f;
3052 Lisp_Object bar, next;
3054 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3056 /* Clear out the condemned list now so we won't try to process any
3057 more events on the hapless scroll bars. */
3058 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3060 for (; ! NILP (bar); bar = next)
3062 struct scroll_bar *b = XSCROLL_BAR (bar);
3064 x_scroll_bar_remove (b);
3066 next = b->next;
3067 b->next = b->prev = Qnil;
3070 /* Now there should be no references to the condemned scroll bars,
3071 and they should get garbage-collected. */
3072 #ifdef PIGSFLY
3073 Lisp_Object bar, next;
3075 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3077 /* Clear out the condemned list now so we won't try to process any
3078 more events on the hapless scroll bars. */
3079 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3081 for (; ! NILP (bar); bar = next)
3083 struct scroll_bar *b = XSCROLL_BAR (bar);
3085 x_scroll_bar_remove (b);
3087 next = b->next;
3088 b->next = b->prev = Qnil;
3091 /* Now there should be no references to the condemned scroll bars,
3092 and they should get garbage-collected. */
3093 #endif
3096 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3097 is set to something other than no_event, it is enqueued.
3099 This may be called from a signal handler, so we have to ignore GC
3100 mark bits. */
3102 static int
3103 x_scroll_bar_handle_click (bar, msg, emacs_event)
3104 struct scroll_bar *bar;
3105 W32Msg *msg;
3106 struct input_event *emacs_event;
3108 if (! GC_WINDOWP (bar->window))
3109 abort ();
3111 emacs_event->kind = w32_scroll_bar_click;
3112 emacs_event->code = 0;
3113 /* not really meaningful to distinguish up/down */
3114 emacs_event->modifiers = msg->dwModifiers;
3115 emacs_event->frame_or_window = bar->window;
3116 emacs_event->timestamp = msg->msg.time;
3119 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3120 int y;
3121 int dragging = !NILP (bar->dragging);
3123 if (pfnGetScrollInfo)
3125 SCROLLINFO si;
3127 si.cbSize = sizeof (si);
3128 si.fMask = SIF_POS;
3130 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
3131 y = si.nPos;
3133 else
3134 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
3136 bar->dragging = Qnil;
3138 switch (LOWORD (msg->msg.wParam))
3140 case SB_LINEDOWN:
3141 emacs_event->part = scroll_bar_down_arrow;
3142 break;
3143 case SB_LINEUP:
3144 emacs_event->part = scroll_bar_up_arrow;
3145 break;
3146 case SB_PAGEUP:
3147 emacs_event->part = scroll_bar_above_handle;
3148 break;
3149 case SB_PAGEDOWN:
3150 emacs_event->part = scroll_bar_below_handle;
3151 break;
3152 case SB_TOP:
3153 emacs_event->part = scroll_bar_handle;
3154 y = 0;
3155 break;
3156 case SB_BOTTOM:
3157 emacs_event->part = scroll_bar_handle;
3158 y = top_range;
3159 break;
3160 case SB_THUMBTRACK:
3161 case SB_THUMBPOSITION:
3162 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
3163 y = HIWORD (msg->msg.wParam);
3164 bar->dragging = Qt;
3165 emacs_event->part = scroll_bar_handle;
3167 /* "Silently" update current position. */
3168 if (pfnSetScrollInfo)
3170 SCROLLINFO si;
3172 si.cbSize = sizeof (si);
3173 si.fMask = SIF_POS;
3175 #if 0
3176 /* Shrink handle if necessary to allow full range for position. */
3178 int start = XINT (bar->start);
3179 int end = XINT (bar->end);
3180 int len = end - start;
3182 /* If new end is nearly hitting bottom, we must shrink
3183 handle. How much we shrink it depends on the relative
3184 sizes of len and top_range. */
3185 if (y + len > top_range - 2)
3187 len -= min (top_range / 10, (len / 3) + 2);
3188 if (len < 0)
3189 len = 0;
3191 si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3192 si.fMask |= SIF_PAGE;
3194 #endif
3195 si.nPos = y;
3196 /* Remember apparent position (we actually lag behind the real
3197 position, so don't set that directly. */
3198 last_scroll_bar_drag_pos = y;
3200 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
3202 else
3203 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
3204 break;
3205 case SB_ENDSCROLL:
3206 /* If this is the end of a drag sequence, then reset the scroll
3207 handle size to normal and do a final redraw. Otherwise do
3208 nothing. */
3209 if (dragging)
3211 if (pfnSetScrollInfo)
3213 SCROLLINFO si;
3214 int start = XINT (bar->start);
3215 int end = XINT (bar->end);
3217 si.cbSize = sizeof (si);
3218 si.fMask = SIF_PAGE | SIF_POS;
3219 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3220 si.nPos = last_scroll_bar_drag_pos;
3222 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
3224 else
3225 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
3227 /* fall through */
3228 default:
3229 emacs_event->kind = no_event;
3230 return FALSE;
3233 XSETINT (emacs_event->x, y);
3234 XSETINT (emacs_event->y, top_range);
3236 return TRUE;
3240 /* Return information to the user about the current position of the mouse
3241 on the scroll bar. */
3242 static void
3243 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3244 FRAME_PTR *fp;
3245 Lisp_Object *bar_window;
3246 enum scroll_bar_part *part;
3247 Lisp_Object *x, *y;
3248 unsigned long *time;
3250 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3251 Window w = SCROLL_BAR_W32_WINDOW (bar);
3252 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3253 int pos;
3254 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3256 BLOCK_INPUT;
3258 *fp = f;
3259 *bar_window = bar->window;
3261 if (pfnGetScrollInfo)
3263 SCROLLINFO si;
3265 si.cbSize = sizeof (si);
3266 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
3268 pfnGetScrollInfo (w, SB_CTL, &si);
3269 pos = si.nPos;
3270 top_range = si.nMax - si.nPage + 1;
3272 else
3273 pos = GetScrollPos (w, SB_CTL);
3275 switch (LOWORD (last_mouse_scroll_bar_pos))
3277 case SB_THUMBPOSITION:
3278 case SB_THUMBTRACK:
3279 *part = scroll_bar_handle;
3280 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
3281 pos = HIWORD (last_mouse_scroll_bar_pos);
3282 break;
3283 case SB_LINEDOWN:
3284 *part = scroll_bar_handle;
3285 pos++;
3286 break;
3287 default:
3288 *part = scroll_bar_handle;
3289 break;
3292 XSETINT(*x, pos);
3293 XSETINT(*y, top_range);
3295 f->mouse_moved = 0;
3296 last_mouse_scroll_bar = Qnil;
3298 *time = last_mouse_movement_time;
3300 UNBLOCK_INPUT;
3303 /* The screen has been cleared so we may have changed foreground or
3304 background colors, and the scroll bars may need to be redrawn.
3305 Clear out the scroll bars, and ask for expose events, so we can
3306 redraw them. */
3308 x_scroll_bar_clear (f)
3309 FRAME_PTR f;
3311 Lisp_Object bar;
3313 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
3314 bar = XSCROLL_BAR (bar)->next)
3316 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
3317 HDC hdc = GetDC (window);
3318 RECT rect;
3320 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
3321 arranges to refresh the scroll bar if hidden. */
3322 my_show_window (f, window, SW_HIDE);
3324 GetClientRect (window, &rect);
3325 select_palette (f, hdc);
3326 w32_clear_rect (f, hdc, &rect);
3327 deselect_palette (f, hdc);
3329 ReleaseDC (window, hdc);
3333 show_scroll_bars (f, how)
3334 FRAME_PTR f;
3335 int how;
3337 Lisp_Object bar;
3339 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
3340 bar = XSCROLL_BAR (bar)->next)
3342 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
3343 my_show_window (f, window, how);
3348 /* The main W32 event-reading loop - w32_read_socket. */
3350 /* Timestamp of enter window event. This is only used by w32_read_socket,
3351 but we have to put it out here, since static variables within functions
3352 sometimes don't work. */
3353 static Time enter_timestamp;
3355 /* Record the last 100 characters stored
3356 to help debug the loss-of-chars-during-GC problem. */
3357 int temp_index;
3358 short temp_buffer[100];
3361 /* Read events coming from the W32 shell.
3362 This routine is called by the SIGIO handler.
3363 We return as soon as there are no more events to be read.
3365 Events representing keys are stored in buffer BUFP,
3366 which can hold up to NUMCHARS characters.
3367 We return the number of characters stored into the buffer,
3368 thus pretending to be `read'.
3370 EXPECTED is nonzero if the caller knows input is available.
3372 Some of these messages are reposted back to the message queue since the
3373 system calls the windows proc directly in a context where we cannot return
3374 the data nor can we guarantee the state we are in. So if we dispatch them
3375 we will get into an infinite loop. To prevent this from ever happening we
3376 will set a variable to indicate we are in the read_socket call and indicate
3377 which message we are processing since the windows proc gets called
3378 recursively with different messages by the system.
3382 w32_read_socket (sd, bufp, numchars, expected)
3383 register int sd;
3384 register struct input_event *bufp;
3385 register int numchars;
3386 int expected;
3388 int count = 0;
3389 int check_visibility = 0;
3390 W32Msg msg;
3391 struct frame *f;
3392 Lisp_Object part;
3393 struct w32_display_info *dpyinfo = &one_w32_display_info;
3395 if (interrupt_input_blocked)
3397 interrupt_input_pending = 1;
3398 return -1;
3401 interrupt_input_pending = 0;
3402 BLOCK_INPUT;
3404 /* So people can tell when we have read the available input. */
3405 input_signal_count++;
3407 if (numchars <= 0)
3408 abort (); /* Don't think this happens. */
3410 while (get_next_msg (&msg, FALSE))
3412 switch (msg.msg.message)
3414 case WM_PAINT:
3415 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3417 if (f)
3419 if (msg.rect.right == msg.rect.left ||
3420 msg.rect.bottom == msg.rect.top)
3422 /* We may get paint messages even though the client
3423 area is clipped - these are not expose events. */
3424 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
3425 XSTRING (f->name)->data));
3427 else if (f->async_visible != 1)
3429 /* Definitely not obscured, so mark as visible. */
3430 f->async_visible = 1;
3431 f->async_iconified = 0;
3432 SET_FRAME_GARBAGED (f);
3433 DebPrint (("frame %04x (%s) reexposed\n", f,
3434 XSTRING (f->name)->data));
3436 /* WM_PAINT serves as MapNotify as well, so report
3437 visibility changes properly. */
3438 if (f->iconified)
3440 bufp->kind = deiconify_event;
3441 XSETFRAME (bufp->frame_or_window, f);
3442 bufp++;
3443 count++;
3444 numchars--;
3446 else if (! NILP(Vframe_list)
3447 && ! NILP (XCONS (Vframe_list)->cdr))
3448 /* Force a redisplay sooner or later to update the
3449 frame titles in case this is the second frame. */
3450 record_asynch_buffer_change ();
3452 else
3454 /* Erase background again for safety. */
3455 w32_clear_rect (f, NULL, &msg.rect);
3456 dumprectangle (f,
3457 msg.rect.left,
3458 msg.rect.top,
3459 msg.rect.right - msg.rect.left,
3460 msg.rect.bottom - msg.rect.top);
3463 break;
3465 case WM_INPUTLANGCHANGE:
3466 /* Generate a language change event. */
3467 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3469 if (f)
3471 if (numchars == 0)
3472 abort ();
3474 bufp->kind = language_change_event;
3475 XSETFRAME (bufp->frame_or_window, f);
3476 bufp->code = msg.msg.wParam;
3477 bufp->modifiers = msg.msg.lParam & 0xffff;
3478 bufp++;
3479 count++;
3480 numchars--;
3482 break;
3484 case WM_KEYDOWN:
3485 case WM_SYSKEYDOWN:
3486 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3488 if (f && !f->iconified)
3490 if (temp_index == sizeof temp_buffer / sizeof (short))
3491 temp_index = 0;
3492 temp_buffer[temp_index++] = msg.msg.wParam;
3493 bufp->kind = non_ascii_keystroke;
3494 bufp->code = msg.msg.wParam;
3495 bufp->modifiers = msg.dwModifiers;
3496 XSETFRAME (bufp->frame_or_window, f);
3497 bufp->timestamp = msg.msg.time;
3498 bufp++;
3499 numchars--;
3500 count++;
3502 break;
3504 case WM_SYSCHAR:
3505 case WM_CHAR:
3506 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3508 if (f && !f->iconified)
3510 if (temp_index == sizeof temp_buffer / sizeof (short))
3511 temp_index = 0;
3512 temp_buffer[temp_index++] = msg.msg.wParam;
3513 bufp->kind = ascii_keystroke;
3514 bufp->code = msg.msg.wParam;
3515 bufp->modifiers = msg.dwModifiers;
3516 XSETFRAME (bufp->frame_or_window, f);
3517 bufp->timestamp = msg.msg.time;
3518 bufp++;
3519 numchars--;
3520 count++;
3522 break;
3524 case WM_MOUSEMOVE:
3525 if (dpyinfo->grabbed && last_mouse_frame
3526 && FRAME_LIVE_P (last_mouse_frame))
3527 f = last_mouse_frame;
3528 else
3529 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3531 if (f)
3532 note_mouse_movement (f, &msg.msg);
3533 else
3534 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
3536 break;
3538 case WM_LBUTTONDOWN:
3539 case WM_LBUTTONUP:
3540 case WM_MBUTTONDOWN:
3541 case WM_MBUTTONUP:
3542 case WM_RBUTTONDOWN:
3543 case WM_RBUTTONUP:
3545 int button;
3546 int up;
3548 if (dpyinfo->grabbed && last_mouse_frame
3549 && FRAME_LIVE_P (last_mouse_frame))
3550 f = last_mouse_frame;
3551 else
3552 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3554 if (f)
3556 if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame)
3557 && (numchars >= 1))
3559 construct_mouse_click (bufp, &msg, f);
3560 bufp++;
3561 count++;
3562 numchars--;
3566 parse_button (msg.msg.message, &button, &up);
3568 if (up)
3570 dpyinfo->grabbed &= ~ (1 << button);
3572 else
3574 dpyinfo->grabbed |= (1 << button);
3575 last_mouse_frame = f;
3577 break;
3580 case WM_MOUSEWHEEL:
3581 if (dpyinfo->grabbed && last_mouse_frame
3582 && FRAME_LIVE_P (last_mouse_frame))
3583 f = last_mouse_frame;
3584 else
3585 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3587 if (f)
3589 if ((!dpyinfo->w32_focus_frame
3590 || f == dpyinfo->w32_focus_frame)
3591 && (numchars >= 1))
3593 construct_mouse_wheel (bufp, &msg, f);
3594 bufp++;
3595 count++;
3596 numchars--;
3599 break;
3601 case WM_DROPFILES:
3602 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3604 if (f)
3606 construct_drag_n_drop (bufp, &msg, f);
3607 bufp++;
3608 count++;
3609 numchars--;
3611 break;
3613 case WM_VSCROLL:
3615 struct scroll_bar *bar =
3616 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
3618 if (bar && numchars >= 1)
3620 if (x_scroll_bar_handle_click (bar, &msg, bufp))
3622 bufp++;
3623 count++;
3624 numchars--;
3627 break;
3630 case WM_WINDOWPOSCHANGED:
3631 case WM_ACTIVATE:
3632 case WM_ACTIVATEAPP:
3633 check_visibility = 1;
3634 break;
3636 case WM_MOVE:
3637 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3639 if (f && !f->async_iconified)
3641 int x, y;
3643 x_real_positions (f, &x, &y);
3644 f->output_data.w32->left_pos = x;
3645 f->output_data.w32->top_pos = y;
3648 check_visibility = 1;
3649 break;
3651 case WM_SHOWWINDOW:
3652 /* If window has been obscured or exposed by another window
3653 being maximised or minimised/restored, then recheck
3654 visibility of all frames. Direct changes to our own
3655 windows get handled by WM_SIZE. */
3656 #if 0
3657 if (msg.msg.lParam != 0)
3658 check_visibility = 1;
3659 else
3661 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3662 f->async_visible = msg.msg.wParam;
3664 #endif
3666 check_visibility = 1;
3667 break;
3669 case WM_SIZE:
3670 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3672 /* Inform lisp of whether frame has been iconified etc. */
3673 if (f)
3675 switch (msg.msg.wParam)
3677 case SIZE_MINIMIZED:
3678 f->async_visible = 0;
3679 f->async_iconified = 1;
3681 bufp->kind = iconify_event;
3682 XSETFRAME (bufp->frame_or_window, f);
3683 bufp++;
3684 count++;
3685 numchars--;
3686 break;
3688 case SIZE_MAXIMIZED:
3689 case SIZE_RESTORED:
3690 f->async_visible = 1;
3691 f->async_iconified = 0;
3693 /* wait_reading_process_input will notice this and update
3694 the frame's display structures. */
3695 SET_FRAME_GARBAGED (f);
3697 if (f->iconified)
3699 bufp->kind = deiconify_event;
3700 XSETFRAME (bufp->frame_or_window, f);
3701 bufp++;
3702 count++;
3703 numchars--;
3705 else
3706 /* Force a redisplay sooner or later
3707 to update the frame titles
3708 in case this is the second frame. */
3709 record_asynch_buffer_change ();
3710 break;
3714 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
3716 RECT rect;
3717 int rows;
3718 int columns;
3719 int width;
3720 int height;
3722 GetClientRect(msg.msg.hwnd, &rect);
3724 height = rect.bottom - rect.top;
3725 width = rect.right - rect.left;
3727 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
3728 columns = PIXEL_TO_CHAR_WIDTH (f, width);
3730 /* TODO: Clip size to the screen dimensions. */
3732 /* Even if the number of character rows and columns has
3733 not changed, the font size may have changed, so we need
3734 to check the pixel dimensions as well. */
3736 if (columns != f->width
3737 || rows != f->height
3738 || width != f->output_data.w32->pixel_width
3739 || height != f->output_data.w32->pixel_height)
3741 /* I had set this to 0, 0 - I am not sure why?? */
3743 change_frame_size (f, rows, columns, 0, 1);
3744 SET_FRAME_GARBAGED (f);
3746 f->output_data.w32->pixel_width = width;
3747 f->output_data.w32->pixel_height = height;
3748 f->output_data.w32->win_gravity = NorthWestGravity;
3752 check_visibility = 1;
3753 break;
3755 case WM_SETFOCUS:
3756 case WM_KILLFOCUS:
3757 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3759 if (msg.msg.message == WM_SETFOCUS)
3761 x_new_focus_frame (dpyinfo, f);
3763 else if (f == dpyinfo->w32_focus_frame)
3765 x_new_focus_frame (dpyinfo, 0);
3768 check_visibility = 1;
3769 break;
3771 case WM_CLOSE:
3772 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3774 if (f)
3776 if (numchars == 0)
3777 abort ();
3779 bufp->kind = delete_window_event;
3780 XSETFRAME (bufp->frame_or_window, f);
3781 bufp++;
3782 count++;
3783 numchars--;
3785 break;
3787 case WM_INITMENU:
3788 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3790 if (f)
3792 if (numchars == 0)
3793 abort ();
3795 bufp->kind = menu_bar_activate_event;
3796 XSETFRAME (bufp->frame_or_window, f);
3797 bufp++;
3798 count++;
3799 numchars--;
3801 break;
3803 case WM_COMMAND:
3804 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3806 if (f)
3808 extern void menubar_selection_callback
3809 (FRAME_PTR f, void * client_data);
3810 menubar_selection_callback (f, (void *)msg.msg.wParam);
3813 check_visibility = 1;
3814 break;
3816 case WM_DISPLAYCHANGE:
3817 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3819 if (f)
3821 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
3822 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
3823 dpyinfo->n_cbits = msg.msg.wParam;
3824 DebPrint (("display change: %d %d\n", dpyinfo->width,
3825 dpyinfo->height));
3828 check_visibility = 1;
3829 break;
3831 default:
3832 /* Check for messages registered at runtime. */
3833 if (msg.msg.message == msh_mousewheel)
3835 if (dpyinfo->grabbed && last_mouse_frame
3836 && FRAME_LIVE_P (last_mouse_frame))
3837 f = last_mouse_frame;
3838 else
3839 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
3841 if (f)
3843 if ((!dpyinfo->w32_focus_frame
3844 || f == dpyinfo->w32_focus_frame)
3845 && (numchars >= 1))
3847 construct_mouse_wheel (bufp, &msg, f);
3848 bufp++;
3849 count++;
3850 numchars--;
3854 break;
3858 /* If the focus was just given to an autoraising frame,
3859 raise it now. */
3860 /* ??? This ought to be able to handle more than one such frame. */
3861 if (pending_autoraise_frame)
3863 x_raise_frame (pending_autoraise_frame);
3864 pending_autoraise_frame = 0;
3867 /* Check which frames are still visisble, if we have enqueued any user
3868 events or been notified of events that may affect visibility. We
3869 do this here because there doesn't seem to be any direct
3870 notification from Windows that the visibility of a window has
3871 changed (at least, not in all cases). */
3872 if (count > 0 || check_visibility)
3874 Lisp_Object tail, frame;
3876 FOR_EACH_FRAME (tail, frame)
3878 FRAME_PTR f = XFRAME (frame);
3879 /* Check "visible" frames and mark each as obscured or not.
3880 Note that async_visible is nonzero for unobscured and
3881 obscured frames, but zero for hidden and iconified frames. */
3882 if (FRAME_W32_P (f) && f->async_visible)
3884 RECT clipbox;
3885 HDC hdc = get_frame_dc (f);
3886 GetClipBox (hdc, &clipbox);
3887 release_frame_dc (f, hdc);
3889 if (clipbox.right == clipbox.left
3890 || clipbox.bottom == clipbox.top)
3892 /* Frame has become completely obscured so mark as
3893 such (we do this by setting async_visible to 2 so
3894 that FRAME_VISIBLE_P is still true, but redisplay
3895 will skip it). */
3896 f->async_visible = 2;
3898 if (!FRAME_OBSCURED_P (f))
3900 DebPrint (("frame %04x (%s) obscured\n", f,
3901 XSTRING (f->name)->data));
3904 else
3906 /* Frame is not obscured, so mark it as such. */
3907 f->async_visible = 1;
3909 if (FRAME_OBSCURED_P (f))
3911 SET_FRAME_GARBAGED (f);
3912 DebPrint (("frame %04x (%s) reexposed\n", f,
3913 XSTRING (f->name)->data));
3915 /* Force a redisplay sooner or later. */
3916 record_asynch_buffer_change ();
3923 UNBLOCK_INPUT;
3924 return count;
3927 /* Drawing the cursor. */
3930 /* Draw a hollow box cursor. Don't change the inside of the box. */
3932 static void
3933 x_draw_box (f)
3934 struct frame *f;
3936 RECT rect;
3937 HBRUSH hb;
3938 HDC hdc;
3940 hdc = get_frame_dc (f);
3942 hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
3944 rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
3945 rect.top = CHAR_TO_PIXEL_ROW (f, curs_y);
3946 rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
3947 rect.bottom = rect.top + f->output_data.w32->line_height;
3949 FrameRect (hdc, &rect, hb);
3950 DeleteObject (hb);
3952 release_frame_dc (f, hdc);
3955 /* Clear the cursor of frame F to background color,
3956 and mark the cursor as not shown.
3957 This is used when the text where the cursor is
3958 is about to be rewritten. */
3960 static void
3961 clear_cursor (f)
3962 struct frame *f;
3964 if (! FRAME_VISIBLE_P (f)
3965 || !f->phys_cursor_on)
3966 return;
3968 x_display_cursor (f, 0);
3969 f->phys_cursor_on = 0;
3972 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3973 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3974 glyph drawn. */
3976 static void
3977 x_draw_single_glyph (f, row, column, glyph, highlight)
3978 struct frame *f;
3979 int row, column;
3980 GLYPH glyph;
3981 int highlight;
3983 dumpglyphs (f,
3984 CHAR_TO_PIXEL_COL (f, column),
3985 CHAR_TO_PIXEL_ROW (f, row),
3986 &glyph, 1, highlight, 0, NULL);
3989 static void
3990 x_display_bar_cursor (f, on)
3991 struct frame *f;
3992 int on;
3994 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3996 /* This is pointless on invisible frames, and dangerous on garbaged
3997 frames; in the latter case, the frame may be in the midst of
3998 changing its size, and curs_x and curs_y may be off the frame. */
3999 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4000 return;
4002 if (! on && ! f->phys_cursor_on)
4003 return;
4005 /* If there is anything wrong with the current cursor state, remove it. */
4006 if (f->phys_cursor_on
4007 && (!on
4008 || f->phys_cursor_x != curs_x
4009 || f->phys_cursor_y != curs_y
4010 || f->output_data.w32->current_cursor != bar_cursor))
4012 /* Erase the cursor by redrawing the character underneath it. */
4013 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4014 f->phys_cursor_glyph,
4015 current_glyphs->highlight[f->phys_cursor_y]);
4016 f->phys_cursor_on = 0;
4019 /* If we now need a cursor in the new place or in the new form, do it so. */
4020 if (on
4021 && (! f->phys_cursor_on
4022 || (f->output_data.w32->current_cursor != bar_cursor)))
4024 f->phys_cursor_glyph
4025 = ((current_glyphs->enable[curs_y]
4026 && curs_x < current_glyphs->used[curs_y])
4027 ? current_glyphs->glyphs[curs_y][curs_x]
4028 : SPACEGLYPH);
4029 w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
4030 CHAR_TO_PIXEL_COL (f, curs_x),
4031 CHAR_TO_PIXEL_ROW (f, curs_y),
4032 max (f->output_data.w32->cursor_width, 1),
4033 f->output_data.w32->line_height);
4035 f->phys_cursor_x = curs_x;
4036 f->phys_cursor_y = curs_y;
4037 f->phys_cursor_on = 1;
4039 f->output_data.w32->current_cursor = bar_cursor;
4044 /* Turn the displayed cursor of frame F on or off according to ON.
4045 If ON is nonzero, where to put the cursor is specified
4046 by F->cursor_x and F->cursor_y. */
4048 static void
4049 x_display_box_cursor (f, on)
4050 struct frame *f;
4051 int on;
4053 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4055 /* This is pointless on invisible frames, and dangerous on garbaged
4056 frames; in the latter case, the frame may be in the midst of
4057 changing its size, and curs_x and curs_y may be off the frame. */
4058 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4059 return;
4061 /* If cursor is off and we want it off, return quickly. */
4062 if (!on && ! f->phys_cursor_on)
4063 return;
4065 /* If cursor is currently being shown and we don't want it to be
4066 or it is in the wrong place,
4067 or we want a hollow box and it's not so, (pout!)
4068 erase it. */
4069 if (f->phys_cursor_on
4070 && (!on
4071 || f->phys_cursor_x != curs_x
4072 || f->phys_cursor_y != curs_y
4073 || (f->output_data.w32->current_cursor != hollow_box_cursor
4074 && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
4076 int mouse_face_here = 0;
4077 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
4079 /* If the cursor is in the mouse face area, redisplay that when
4080 we clear the cursor. */
4081 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
4082 && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
4083 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
4084 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
4085 && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
4086 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
4087 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
4088 /* Don't redraw the cursor's spot in mouse face
4089 if it is at the end of a line (on a newline).
4090 The cursor appears there, but mouse highlighting does not. */
4091 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
4092 mouse_face_here = 1;
4094 /* If the font is not as tall as a whole line,
4095 we must explicitly clear the line's whole height. */
4096 if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
4097 w32_clear_area (f, NULL,
4098 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4099 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4100 FONT_WIDTH (f->output_data.w32->font),
4101 f->output_data.w32->line_height);
4102 /* Erase the cursor by redrawing the character underneath it. */
4103 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4104 f->phys_cursor_glyph,
4105 (mouse_face_here
4107 : current_glyphs->highlight[f->phys_cursor_y]));
4108 f->phys_cursor_on = 0;
4111 /* If we want to show a cursor,
4112 or we want a box cursor and it's not so,
4113 write it in the right place. */
4114 if (on
4115 && (! f->phys_cursor_on
4116 || (f->output_data.w32->current_cursor != filled_box_cursor
4117 && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
4119 f->phys_cursor_glyph
4120 = ((current_glyphs->enable[curs_y]
4121 && curs_x < current_glyphs->used[curs_y])
4122 ? current_glyphs->glyphs[curs_y][curs_x]
4123 : SPACEGLYPH);
4124 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
4126 x_draw_box (f);
4127 f->output_data.w32->current_cursor = hollow_box_cursor;
4129 else
4131 x_draw_single_glyph (f, curs_y, curs_x,
4132 f->phys_cursor_glyph, 2);
4133 f->output_data.w32->current_cursor = filled_box_cursor;
4136 f->phys_cursor_x = curs_x;
4137 f->phys_cursor_y = curs_y;
4138 f->phys_cursor_on = 1;
4142 /* Display the cursor on frame F, or clear it, according to ON.
4143 Use the position specified by curs_x and curs_y
4144 if we are doing an update of frame F now.
4145 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4146 of F. */
4148 x_display_cursor (f, on)
4149 struct frame *f;
4150 int on;
4152 BLOCK_INPUT;
4154 /* If we're not updating, then we want to use the current frame's
4155 cursor position, not our local idea of where the cursor ought to be. */
4156 if (f != updating_frame)
4158 curs_x = FRAME_CURSOR_X (f);
4159 curs_y = FRAME_CURSOR_Y (f);
4162 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4163 x_display_box_cursor (f, on);
4164 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4165 x_display_bar_cursor (f, on);
4166 else
4167 /* Those are the only two we have implemented! */
4168 abort ();
4170 UNBLOCK_INPUT;
4173 /* Changing the font of the frame. */
4175 /* Give frame F the font named FONTNAME as its default font, and
4176 return the full name of that font. FONTNAME may be a wildcard
4177 pattern; in that case, we choose some font that fits the pattern.
4178 The return value shows which font we chose. */
4180 Lisp_Object
4181 x_new_font (f, fontname)
4182 struct frame *f;
4183 register char *fontname;
4185 struct font_info *fontp
4186 = fs_load_font (f, FRAME_W32_FONT_TABLE (f), CHARSET_ASCII,
4187 fontname, -1);
4189 if (!fontp)
4190 return Qnil;
4192 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4193 f->output_data.w32->font_baseline
4194 = FONT_BASE (FRAME_FONT (f)) + fontp->baseline_offset;
4195 FRAME_FONTSET (f) = -1;
4197 /* Compute the scroll bar width in character columns. */
4198 if (f->scroll_bar_pixel_width > 0)
4200 int wid = FONT_WIDTH (f->output_data.w32->font);
4201 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
4203 else
4204 f->scroll_bar_cols = 2;
4206 /* Now make the frame display the given font. */
4207 if (FRAME_W32_WINDOW (f) != 0)
4209 frame_update_line_height (f);
4210 x_set_window_size (f, 0, f->width, f->height);
4212 else
4213 /* If we are setting a new frame's font for the first time,
4214 there are no faces yet, so this font's height is the line height. */
4215 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
4218 Lisp_Object lispy_name;
4220 lispy_name = build_string (fontname);
4222 return lispy_name;
4226 /* Give frame F the fontset named FONTSETNAME as its default font, and
4227 return the full name of that fontset. FONTSETNAME may be a wildcard
4228 pattern; in that case, we choose some fontset that fits the pattern.
4229 The return value shows which fontset we chose. */
4231 Lisp_Object
4232 x_new_fontset (f, fontsetname)
4233 struct frame *f;
4234 char *fontsetname;
4236 int fontset = fs_query_fontset (f, fontsetname);
4237 struct fontset_info *fontsetp;
4238 Lisp_Object result;
4240 if (fontset < 0)
4241 return Qnil;
4243 if (FRAME_FONTSET (f) == fontset)
4244 /* This fontset is already set in frame F. There's nothing more
4245 to do. */
4246 return build_string (fontsetname);
4248 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
4250 if (!fontsetp->fontname[CHARSET_ASCII])
4251 /* This fontset doesn't contain ASCII font. */
4252 return Qnil;
4254 result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
4256 if (!STRINGP (result))
4257 /* Can't load ASCII font. */
4258 return Qnil;
4260 /* Since x_new_font doesn't update any fontset information, do it now. */
4261 FRAME_FONTSET(f) = fontset;
4262 FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
4263 CHARSET_ASCII, XSTRING (result)->data, fontset);
4265 return build_string (fontsetname);
4268 /* Calculate the absolute position in frame F
4269 from its current recorded position values and gravity. */
4271 x_calc_absolute_position (f)
4272 struct frame *f;
4274 Window win, child;
4275 POINT pt;
4276 int flags = f->output_data.w32->size_hint_flags;
4278 pt.x = pt.y = 0;
4280 /* Find the position of the outside upper-left corner of
4281 the inner window, with respect to the outer window. */
4282 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
4284 BLOCK_INPUT;
4285 MapWindowPoints (FRAME_W32_WINDOW (f),
4286 f->output_data.w32->parent_desc,
4287 &pt, 1);
4288 UNBLOCK_INPUT;
4292 RECT rt;
4293 rt.left = rt.right = rt.top = rt.bottom = 0;
4295 BLOCK_INPUT;
4296 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
4297 FRAME_EXTERNAL_MENU_BAR (f));
4298 UNBLOCK_INPUT;
4300 pt.x += (rt.right - rt.left);
4301 pt.y += (rt.bottom - rt.top);
4304 /* Treat negative positions as relative to the leftmost bottommost
4305 position that fits on the screen. */
4306 if (flags & XNegative)
4307 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
4308 - 2 * f->output_data.w32->border_width - pt.x
4309 - PIXEL_WIDTH (f)
4310 + f->output_data.w32->left_pos);
4312 if (flags & YNegative)
4313 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
4314 - 2 * f->output_data.w32->border_width - pt.y
4315 - PIXEL_HEIGHT (f)
4316 + f->output_data.w32->top_pos);
4317 /* The left_pos and top_pos
4318 are now relative to the top and left screen edges,
4319 so the flags should correspond. */
4320 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
4323 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4324 to really change the position, and 0 when calling from
4325 x_make_frame_visible (in that case, XOFF and YOFF are the current
4326 position values). It is -1 when calling from x_set_frame_parameters,
4327 which means, do adjust for borders but don't change the gravity. */
4329 x_set_offset (f, xoff, yoff, change_gravity)
4330 struct frame *f;
4331 register int xoff, yoff;
4332 int change_gravity;
4334 int modified_top, modified_left;
4336 if (change_gravity > 0)
4338 f->output_data.w32->top_pos = yoff;
4339 f->output_data.w32->left_pos = xoff;
4340 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
4341 if (xoff < 0)
4342 f->output_data.w32->size_hint_flags |= XNegative;
4343 if (yoff < 0)
4344 f->output_data.w32->size_hint_flags |= YNegative;
4345 f->output_data.w32->win_gravity = NorthWestGravity;
4347 x_calc_absolute_position (f);
4349 BLOCK_INPUT;
4350 x_wm_set_size_hint (f, (long) 0, 0);
4352 /* It is a mystery why we need to add the border_width here
4353 when the frame is already visible, but experiment says we do. */
4354 modified_left = f->output_data.w32->left_pos;
4355 modified_top = f->output_data.w32->top_pos;
4356 #ifndef HAVE_NTGUI
4357 /* Do not add in border widths under W32. */
4358 if (change_gravity != 0)
4360 modified_left += f->output_data.w32->border_width;
4361 modified_top += f->output_data.w32->border_width;
4363 #endif
4365 my_set_window_pos (FRAME_W32_WINDOW (f),
4366 NULL,
4367 modified_left, modified_top,
4368 0, 0,
4369 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
4370 UNBLOCK_INPUT;
4373 /* Call this to change the size of frame F's x-window.
4374 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4375 for this size change and subsequent size changes.
4376 Otherwise we leave the window gravity unchanged. */
4378 x_set_window_size (f, change_gravity, cols, rows)
4379 struct frame *f;
4380 int change_gravity;
4381 int cols, rows;
4383 int pixelwidth, pixelheight;
4384 Lisp_Object window;
4385 struct w32_display_info *dpyinfo = &one_w32_display_info;
4387 BLOCK_INPUT;
4389 check_frame_size (f, &rows, &cols);
4390 f->output_data.w32->vertical_scroll_bar_extra
4391 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4393 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
4394 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
4395 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
4396 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4397 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4399 f->output_data.w32->win_gravity = NorthWestGravity;
4400 x_wm_set_size_hint (f, (long) 0, 0);
4403 RECT rect;
4405 rect.left = rect.top = 0;
4406 rect.right = pixelwidth;
4407 rect.bottom = pixelheight;
4409 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
4410 FRAME_EXTERNAL_MENU_BAR (f));
4412 my_set_window_pos (FRAME_W32_WINDOW (f),
4413 NULL,
4414 0, 0,
4415 rect.right - rect.left,
4416 rect.bottom - rect.top,
4417 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
4420 /* Now, strictly speaking, we can't be sure that this is accurate,
4421 but the window manager will get around to dealing with the size
4422 change request eventually, and we'll hear how it went when the
4423 ConfigureNotify event gets here.
4425 We could just not bother storing any of this information here,
4426 and let the ConfigureNotify event set everything up, but that
4427 might be kind of confusing to the lisp code, since size changes
4428 wouldn't be reported in the frame parameters until some random
4429 point in the future when the ConfigureNotify event arrives. */
4430 change_frame_size (f, rows, cols, 0, 0);
4431 PIXEL_WIDTH (f) = pixelwidth;
4432 PIXEL_HEIGHT (f) = pixelheight;
4434 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4435 receive in the ConfigureNotify event; if we get what we asked
4436 for, then the event won't cause the screen to become garbaged, so
4437 we have to make sure to do it here. */
4438 SET_FRAME_GARBAGED (f);
4440 /* If cursor was outside the new size, mark it as off. */
4441 if (f->phys_cursor_y >= rows
4442 || f->phys_cursor_x >= cols)
4444 f->phys_cursor_x = 0;
4445 f->phys_cursor_y = 0;
4446 f->phys_cursor_on = 0;
4449 /* Clear out any recollection of where the mouse highlighting was,
4450 since it might be in a place that's outside the new frame size.
4451 Actually checking whether it is outside is a pain in the neck,
4452 so don't try--just let the highlighting be done afresh with new size. */
4453 window = dpyinfo->mouse_face_window;
4454 if (! NILP (window) && XFRAME (window) == f)
4456 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
4457 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
4458 dpyinfo->mouse_face_window = Qnil;
4461 UNBLOCK_INPUT;
4464 /* Mouse warping. */
4466 void
4467 x_set_mouse_pixel_position (f, pix_x, pix_y)
4468 struct frame *f;
4469 int pix_x, pix_y;
4471 RECT rect;
4472 POINT pt;
4474 BLOCK_INPUT;
4476 GetClientRect (FRAME_W32_WINDOW (f), &rect);
4477 pt.x = rect.left + pix_x;
4478 pt.y = rect.top + pix_y;
4479 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
4481 SetCursorPos (pt.x, pt.y);
4483 UNBLOCK_INPUT;
4486 void
4487 x_set_mouse_position (f, x, y)
4488 struct frame *f;
4489 int x, y;
4491 int pix_x, pix_y;
4493 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
4494 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
4496 if (pix_x < 0) pix_x = 0;
4497 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4499 if (pix_y < 0) pix_y = 0;
4500 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4502 x_set_mouse_pixel_position (f, pix_x, pix_y);
4505 /* focus shifting, raising and lowering. */
4507 x_focus_on_frame (f)
4508 struct frame *f;
4510 struct w32_display_info *dpyinfo = &one_w32_display_info;
4512 /* Give input focus to frame. */
4513 BLOCK_INPUT;
4514 #if 0
4515 /* Try not to change its Z-order if possible. */
4516 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
4517 my_set_focus (f, FRAME_W32_WINDOW (f));
4518 else
4519 #endif
4520 my_set_foreground_window (FRAME_W32_WINDOW (f));
4521 UNBLOCK_INPUT;
4524 x_unfocus_frame (f)
4525 struct frame *f;
4529 /* Raise frame F. */
4531 x_raise_frame (f)
4532 struct frame *f;
4534 BLOCK_INPUT;
4536 /* Strictly speaking, raise-frame should only change the frame's Z
4537 order, leaving input focus unchanged. This is reasonable behaviour
4538 on X where the usual policy is point-to-focus. However, this
4539 behaviour would be very odd on Windows where the usual policy is
4540 click-to-focus.
4542 On X, if the mouse happens to be over the raised frame, it gets
4543 input focus anyway (so the window with focus will never be
4544 completely obscured) - if not, then just moving the mouse over it
4545 is sufficient to give it focus. On Windows, the user must actually
4546 click on the frame (preferrably the title bar so as not to move
4547 point), which is more awkward. Also, no other Windows program
4548 raises a window to the top but leaves another window (possibly now
4549 completely obscured) with input focus.
4551 Because there is a system setting on Windows that allows the user
4552 to choose the point to focus policy, we make the strict semantics
4553 optional, but by default we grab focus when raising. */
4555 if (NILP (Vw32_grab_focus_on_raise))
4557 /* The obvious call to my_set_window_pos doesn't work if Emacs is
4558 not already the foreground application: the frame is raised
4559 above all other frames belonging to us, but not above the
4560 current top window. To achieve that, we have to resort to this
4561 more cumbersome method. */
4563 HDWP handle = BeginDeferWindowPos (2);
4564 if (handle)
4566 DeferWindowPos (handle,
4567 FRAME_W32_WINDOW (f),
4568 HWND_TOP,
4569 0, 0, 0, 0,
4570 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
4572 DeferWindowPos (handle,
4573 GetForegroundWindow (),
4574 FRAME_W32_WINDOW (f),
4575 0, 0, 0, 0,
4576 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
4578 EndDeferWindowPos (handle);
4581 else
4583 my_set_foreground_window (FRAME_W32_WINDOW (f));
4586 UNBLOCK_INPUT;
4589 /* Lower frame F. */
4591 x_lower_frame (f)
4592 struct frame *f;
4594 BLOCK_INPUT;
4595 my_set_window_pos (FRAME_W32_WINDOW (f),
4596 HWND_BOTTOM,
4597 0, 0, 0, 0,
4598 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
4599 UNBLOCK_INPUT;
4602 static void
4603 w32_frame_raise_lower (f, raise)
4604 FRAME_PTR f;
4605 int raise;
4607 if (raise)
4608 x_raise_frame (f);
4609 else
4610 x_lower_frame (f);
4613 /* Change of visibility. */
4615 /* This tries to wait until the frame is really visible.
4616 However, if the window manager asks the user where to position
4617 the frame, this will return before the user finishes doing that.
4618 The frame will not actually be visible at that time,
4619 but it will become visible later when the window manager
4620 finishes with it. */
4622 x_make_frame_visible (f)
4623 struct frame *f;
4625 BLOCK_INPUT;
4627 if (! FRAME_VISIBLE_P (f))
4629 /* We test FRAME_GARBAGED_P here to make sure we don't
4630 call x_set_offset a second time
4631 if we get to x_make_frame_visible a second time
4632 before the window gets really visible. */
4633 if (! FRAME_ICONIFIED_P (f)
4634 && ! f->output_data.w32->asked_for_visible)
4635 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
4637 f->output_data.w32->asked_for_visible = 1;
4639 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
4640 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
4643 /* Synchronize to ensure Emacs knows the frame is visible
4644 before we do anything else. We do this loop with input not blocked
4645 so that incoming events are handled. */
4647 Lisp_Object frame;
4648 int count = input_signal_count;
4650 /* This must come after we set COUNT. */
4651 UNBLOCK_INPUT;
4653 XSETFRAME (frame, f);
4655 while (1)
4657 /* Once we have handled input events,
4658 we should have received the MapNotify if one is coming.
4659 So if we have not got it yet, stop looping.
4660 Some window managers make their own decisions
4661 about visibility. */
4662 if (input_signal_count != count)
4663 break;
4664 /* Machines that do polling rather than SIGIO have been observed
4665 to go into a busy-wait here. So we'll fake an alarm signal
4666 to let the handler know that there's something to be read.
4667 We used to raise a real alarm, but it seems that the handler
4668 isn't always enabled here. This is probably a bug. */
4669 if (input_polling_used ())
4671 /* It could be confusing if a real alarm arrives while processing
4672 the fake one. Turn it off and let the handler reset it. */
4673 alarm (0);
4674 input_poll_signal (0);
4676 /* Once we have handled input events,
4677 we should have received the MapNotify if one is coming.
4678 So if we have not got it yet, stop looping.
4679 Some window managers make their own decisions
4680 about visibility. */
4681 if (input_signal_count != count)
4682 break;
4684 FRAME_SAMPLE_VISIBILITY (f);
4688 /* Change from mapped state to withdrawn state. */
4690 /* Make the frame visible (mapped and not iconified). */
4692 x_make_frame_invisible (f)
4693 struct frame *f;
4695 Window window;
4697 /* Don't keep the highlight on an invisible frame. */
4698 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
4699 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
4701 BLOCK_INPUT;
4703 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
4705 /* We can't distinguish this from iconification
4706 just by the event that we get from the server.
4707 So we can't win using the usual strategy of letting
4708 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
4709 and synchronize with the server to make sure we agree. */
4710 f->visible = 0;
4711 FRAME_ICONIFIED_P (f) = 0;
4712 f->async_visible = 0;
4713 f->async_iconified = 0;
4715 UNBLOCK_INPUT;
4718 /* Change window state from mapped to iconified. */
4720 void
4721 x_iconify_frame (f)
4722 struct frame *f;
4724 int result;
4726 /* Don't keep the highlight on an invisible frame. */
4727 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
4728 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
4730 if (f->async_iconified)
4731 return;
4733 BLOCK_INPUT;
4735 /* Simulate the user minimizing the frame. */
4736 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
4738 UNBLOCK_INPUT;
4741 /* Destroy the window of frame F. */
4743 x_destroy_window (f)
4744 struct frame *f;
4746 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4748 BLOCK_INPUT;
4750 my_destroy_window (f, FRAME_W32_WINDOW (f));
4751 free_frame_menubar (f);
4752 free_frame_faces (f);
4754 xfree (f->output_data.w32);
4755 f->output_data.w32 = 0;
4756 if (f == dpyinfo->w32_focus_frame)
4757 dpyinfo->w32_focus_frame = 0;
4758 if (f == dpyinfo->w32_focus_event_frame)
4759 dpyinfo->w32_focus_event_frame = 0;
4760 if (f == dpyinfo->w32_highlight_frame)
4761 dpyinfo->w32_highlight_frame = 0;
4763 dpyinfo->reference_count--;
4765 if (f == dpyinfo->mouse_face_mouse_frame)
4767 dpyinfo->mouse_face_beg_row
4768 = dpyinfo->mouse_face_beg_col = -1;
4769 dpyinfo->mouse_face_end_row
4770 = dpyinfo->mouse_face_end_col = -1;
4771 dpyinfo->mouse_face_window = Qnil;
4774 UNBLOCK_INPUT;
4777 /* Setting window manager hints. */
4779 /* Set the normal size hints for the window manager, for frame F.
4780 FLAGS is the flags word to use--or 0 meaning preserve the flags
4781 that the window now has.
4782 If USER_POSITION is nonzero, we set the USPosition
4783 flag (this is useful when FLAGS is 0). */
4785 x_wm_set_size_hint (f, flags, user_position)
4786 struct frame *f;
4787 long flags;
4788 int user_position;
4790 Window window = FRAME_W32_WINDOW (f);
4792 flexlines = f->height;
4794 enter_crit ();
4796 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
4797 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
4798 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
4799 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
4801 leave_crit ();
4804 /* Window manager things */
4805 x_wm_set_icon_position (f, icon_x, icon_y)
4806 struct frame *f;
4807 int icon_x, icon_y;
4809 #if 0
4810 Window window = FRAME_W32_WINDOW (f);
4812 f->display.x->wm_hints.flags |= IconPositionHint;
4813 f->display.x->wm_hints.icon_x = icon_x;
4814 f->display.x->wm_hints.icon_y = icon_y;
4816 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
4817 #endif
4821 /* Initialization. */
4823 #ifdef USE_X_TOOLKIT
4824 static XrmOptionDescRec emacs_options[] = {
4825 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
4826 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
4828 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
4829 XrmoptionSepArg, NULL},
4830 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
4832 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4833 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4834 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
4835 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4836 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
4837 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
4838 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
4840 #endif /* USE_X_TOOLKIT */
4842 static int w32_initialized = 0;
4844 struct w32_display_info *
4845 w32_term_init (display_name, xrm_option, resource_name)
4846 Lisp_Object display_name;
4847 char *xrm_option;
4848 char *resource_name;
4850 Lisp_Object frame;
4851 char *defaultvalue;
4852 struct w32_display_info *dpyinfo;
4853 HDC hdc;
4855 BLOCK_INPUT;
4857 if (!w32_initialized)
4859 w32_initialize ();
4860 w32_initialized = 1;
4864 int argc = 0;
4865 char *argv[3];
4867 argv[0] = "";
4868 argc = 1;
4869 if (xrm_option)
4871 argv[argc++] = "-xrm";
4872 argv[argc++] = xrm_option;
4876 dpyinfo = &one_w32_display_info;
4878 /* Put this display on the chain. */
4879 dpyinfo->next = NULL;
4881 /* Put it on w32_display_name_list as well, to keep them parallel. */
4882 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
4883 w32_display_name_list);
4884 dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
4886 dpyinfo->w32_id_name
4887 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4888 + XSTRING (Vsystem_name)->size
4889 + 2);
4890 sprintf (dpyinfo->w32_id_name, "%s@%s",
4891 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
4893 #if 0
4894 xrdb = x_load_resources (dpyinfo->display, xrm_option,
4895 resource_name, EMACS_CLASS);
4897 /* Put the rdb where we can find it in a way that works on
4898 all versions. */
4899 dpyinfo->xrdb = xrdb;
4900 #endif
4901 hdc = GetDC (GetDesktopWindow ());
4903 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
4904 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
4905 dpyinfo->root_window = GetDesktopWindow ();
4906 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
4907 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
4908 dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
4909 dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
4910 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
4911 dpyinfo->grabbed = 0;
4912 dpyinfo->reference_count = 0;
4913 dpyinfo->n_fonts = 0;
4914 dpyinfo->font_table_size = 0;
4915 dpyinfo->bitmaps = 0;
4916 dpyinfo->bitmaps_size = 0;
4917 dpyinfo->bitmaps_last = 0;
4918 dpyinfo->mouse_face_mouse_frame = 0;
4919 dpyinfo->mouse_face_deferred_gc = 0;
4920 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
4921 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
4922 dpyinfo->mouse_face_face_id = 0;
4923 dpyinfo->mouse_face_window = Qnil;
4924 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
4925 dpyinfo->mouse_face_defer = 0;
4926 dpyinfo->w32_focus_frame = 0;
4927 dpyinfo->w32_focus_event_frame = 0;
4928 dpyinfo->w32_highlight_frame = 0;
4930 ReleaseDC (GetDesktopWindow (), hdc);
4932 /* Determine if there is a middle mouse button, to allow parse_button
4933 to decide whether right mouse events should be mouse-2 or
4934 mouse-3. */
4935 XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
4937 /* initialise palette with white and black */
4939 COLORREF color;
4940 defined_color (0, "white", &color, 1);
4941 defined_color (0, "black", &color, 1);
4944 #ifndef F_SETOWN_BUG
4945 #ifdef F_SETOWN
4946 #ifdef F_SETOWN_SOCK_NEG
4947 /* stdin is a socket here */
4948 fcntl (connection, F_SETOWN, -getpid ());
4949 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4950 fcntl (connection, F_SETOWN, getpid ());
4951 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4952 #endif /* ! defined (F_SETOWN) */
4953 #endif /* F_SETOWN_BUG */
4955 #ifdef SIGIO
4956 if (interrupt_input)
4957 init_sigio (connection);
4958 #endif /* ! defined (SIGIO) */
4960 UNBLOCK_INPUT;
4962 return dpyinfo;
4965 /* Get rid of display DPYINFO, assuming all frames are already gone. */
4967 void
4968 x_delete_display (dpyinfo)
4969 struct w32_display_info *dpyinfo;
4971 /* Discard this display from w32_display_name_list and w32_display_list.
4972 We can't use Fdelq because that can quit. */
4973 if (! NILP (w32_display_name_list)
4974 && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
4975 w32_display_name_list = XCONS (w32_display_name_list)->cdr;
4976 else
4978 Lisp_Object tail;
4980 tail = w32_display_name_list;
4981 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
4983 if (EQ (XCONS (XCONS (tail)->cdr)->car,
4984 dpyinfo->name_list_element))
4986 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
4987 break;
4989 tail = XCONS (tail)->cdr;
4993 /* free palette table */
4995 struct w32_palette_entry * plist;
4997 plist = dpyinfo->color_list;
4998 while (plist)
5000 struct w32_palette_entry * pentry = plist;
5001 plist = plist->next;
5002 xfree(pentry);
5004 dpyinfo->color_list = NULL;
5005 if (dpyinfo->palette)
5006 DeleteObject(dpyinfo->palette);
5008 xfree (dpyinfo->font_table);
5009 xfree (dpyinfo->w32_id_name);
5012 /* Set up use of W32. */
5014 DWORD w32_msg_worker ();
5016 w32_initialize ()
5018 /* MSVC does not type K&R functions with no arguments correctly, and
5019 so we must explicitly cast them. */
5020 clear_frame_hook = (void (*)(void)) w32_clear_frame;
5021 clear_end_of_line_hook = w32_clear_end_of_line;
5022 ins_del_lines_hook = w32_ins_del_lines;
5023 change_line_highlight_hook = w32_change_line_highlight;
5024 insert_glyphs_hook = w32_insert_glyphs;
5025 write_glyphs_hook = w32_write_glyphs;
5026 delete_glyphs_hook = w32_delete_glyphs;
5027 ring_bell_hook = (void (*)(void)) w32_ring_bell;
5028 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
5029 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
5030 update_begin_hook = w32_update_begin;
5031 update_end_hook = w32_update_end;
5032 set_terminal_window_hook = w32_set_terminal_window;
5033 read_socket_hook = w32_read_socket;
5034 frame_up_to_date_hook = w32_frame_up_to_date;
5035 cursor_to_hook = w32_cursor_to;
5036 reassert_line_highlight_hook = w32_reassert_line_highlight;
5037 mouse_position_hook = w32_mouse_position;
5038 frame_rehighlight_hook = w32_frame_rehighlight;
5039 frame_raise_lower_hook = w32_frame_raise_lower;
5040 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
5041 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
5042 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
5043 judge_scroll_bars_hook = w32_judge_scroll_bars;
5045 scroll_region_ok = 1; /* we'll scroll partial frames */
5046 char_ins_del_ok = 0; /* just as fast to write the line */
5047 line_ins_del_ok = 1; /* we'll just blt 'em */
5048 fast_clear_end_of_line = 1; /* X does this well */
5049 memory_below_frame = 0; /* we don't remember what scrolls
5050 off the bottom */
5051 baud_rate = 19200;
5053 /* Initialize input mode: interrupt_input off, no flow control, allow
5054 8 bit character input, standard quit char. */
5055 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
5057 /* Create the window thread - it will terminate itself or when the app terminates */
5059 init_crit ();
5061 dwMainThreadId = GetCurrentThreadId ();
5062 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
5063 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
5065 /* Wait for thread to start */
5068 MSG msg;
5070 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
5072 hWindowsThread = CreateThread (NULL, 0,
5073 (LPTHREAD_START_ROUTINE) w32_msg_worker,
5074 0, 0, &dwWindowsThreadId);
5076 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
5079 /* It is desirable that mainThread should have the same notion of
5080 focus window and active window as windowsThread. Unfortunately, the
5081 following call to AttachThreadInput, which should do precisely what
5082 we need, causes major problems when Emacs is linked as a console
5083 program. Unfortunately, we have good reasons for doing that, so
5084 instead we need to send messages to windowsThread to make some API
5085 calls for us (ones that affect, or depend on, the active/focus
5086 window state. */
5087 #ifdef ATTACH_THREADS
5088 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
5089 #endif
5091 /* Dynamically link to optional system components. */
5093 HANDLE user_lib = LoadLibrary ("user32.dll");
5095 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
5097 /* New proportional scroll bar functions. */
5098 LOAD_PROC( SetScrollInfo );
5099 LOAD_PROC( GetScrollInfo );
5101 #undef LOAD_PROC
5103 FreeLibrary (user_lib);
5105 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
5106 otherwise use the fixed height. */
5107 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
5108 GetSystemMetrics (SM_CYVTHUMB);
5110 /* For either kind of scroll bar, take account of the arrows; these
5111 effectively form the border of the main scroll bar range. */
5112 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
5113 = GetSystemMetrics (SM_CYVSCROLL);
5117 void
5118 syms_of_w32term ()
5120 Lisp_Object codepage;
5122 staticpro (&w32_display_name_list);
5123 w32_display_name_list = Qnil;
5125 staticpro (&last_mouse_scroll_bar);
5126 last_mouse_scroll_bar = Qnil;
5128 staticpro (&Qvendor_specific_keysyms);
5129 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
5131 DEFVAR_INT ("w32-num-mouse-buttons",
5132 &Vw32_num_mouse_buttons,
5133 "Number of physical mouse buttons.");
5134 Vw32_num_mouse_buttons = Qnil;
5136 DEFVAR_LISP ("w32-swap-mouse-buttons",
5137 &Vw32_swap_mouse_buttons,
5138 "Swap the mapping of middle and right mouse buttons.\n\
5139 When nil, middle button is mouse-2 and right button is mouse-3.");
5140 Vw32_swap_mouse_buttons = Qnil;
5142 DEFVAR_LISP ("w32-grab-focus-on-raise",
5143 &Vw32_grab_focus_on_raise,
5144 "Raised frame grabs input focus.\n\
5145 When t, `raise-frame' grabs input focus as well. This fits well\n\
5146 with the normal Windows click-to-focus policy, but might not be\n\
5147 desirable when using a point-to-focus policy.");
5148 Vw32_grab_focus_on_raise = Qt;
5150 DEFVAR_LISP ("w32-capslock-is-shiftlock",
5151 &Vw32_capslock_is_shiftlock,
5152 "Apply CapsLock state to non character input keys.\n\
5153 When nil, CapsLock only affects normal character input keys.");
5154 Vw32_capslock_is_shiftlock = Qnil;
5156 DEFVAR_LISP ("w32-recognize-altgr",
5157 &Vw32_recognize_altgr,
5158 "Recognize right-alt and left-ctrl as AltGr.\n\
5159 When nil, the right-alt and left-ctrl key combination is\n\
5160 interpreted normally.");
5161 Vw32_recognize_altgr = Qt;
5163 DEFVAR_BOOL ("w32-enable-unicode-output",
5164 &w32_enable_unicode_output,
5165 "Enable the use of Unicode for text output if non-nil.\n\
5166 Unicode output may prevent some third party applications for displaying\n\
5167 Far-East Languages on Windows 95/98 from working properly.\n\
5168 NT uses Unicode internally anyway, so this flag will probably have no\n\
5169 affect on NT machines.");
5170 w32_enable_unicode_output = 1;
5172 DEFVAR_LISP ("w32-charset-to-codepage-alist",
5173 &Vw32_charset_to_codepage_alist,
5174 "Alist linking character sets to Windows Codepages.");
5175 Vw32_charset_to_codepage_alist = Qnil;
5176 /* Initialise the alist with some defaults. */
5177 XSETFASTINT (codepage, 936);
5178 store_in_alist (&Vw32_charset_to_codepage_alist,
5179 build_string ("gb2312"), codepage);
5180 XSETFASTINT (codepage, 950);
5181 store_in_alist (&Vw32_charset_to_codepage_alist,
5182 build_string ("big5"), codepage);
5183 XSETFASTINT (codepage, 949);
5184 store_in_alist (&Vw32_charset_to_codepage_alist,
5185 build_string ("ksc5601.1987"), codepage);
5186 XSETFASTINT (codepage, 1361);
5187 store_in_alist (&Vw32_charset_to_codepage_alist,
5188 build_string ("ksc5601.1992"), codepage);
5189 XSETFASTINT (codepage, 932);
5190 store_in_alist (&Vw32_charset_to_codepage_alist,
5191 build_string ("jisx0208-sjis"), codepage);
5192 XSETFASTINT (codepage, 874);
5193 store_in_alist (&Vw32_charset_to_codepage_alist,
5194 build_string ("tis620"), codepage);
5195 XSETFASTINT (codepage, 20866);
5196 store_in_alist (&Vw32_charset_to_codepage_alist,
5197 build_string ("koi8-r"), codepage);
5198 /* iso8859-13 is not yet officially adopted, but it is conveniently
5199 covered by CP 1257. */
5200 XSETFASTINT (codepage, 1257);
5201 store_in_alist (&Vw32_charset_to_codepage_alist,
5202 build_string ("iso8859-13"), codepage);
5203 XSETFASTINT (codepage, 1254);
5204 store_in_alist (&Vw32_charset_to_codepage_alist,
5205 build_string ("iso8859-9"), codepage);
5206 XSETFASTINT (codepage, 1255);
5207 store_in_alist (&Vw32_charset_to_codepage_alist,
5208 build_string ("iso8859-8"), codepage);
5209 XSETFASTINT (codepage, 28597);
5210 store_in_alist (&Vw32_charset_to_codepage_alist,
5211 build_string ("iso8859-7"), codepage);
5212 XSETFASTINT (codepage, 28596);
5213 store_in_alist (&Vw32_charset_to_codepage_alist,
5214 build_string ("iso8859-6"), codepage);
5215 XSETFASTINT (codepage, 28595);
5216 store_in_alist (&Vw32_charset_to_codepage_alist,
5217 build_string ("iso8859-5"), codepage);
5218 XSETFASTINT (codepage, 28594);
5219 store_in_alist (&Vw32_charset_to_codepage_alist,
5220 build_string ("iso8859-4"), codepage);
5221 XSETFASTINT (codepage, 28593);
5222 store_in_alist (&Vw32_charset_to_codepage_alist,
5223 build_string ("iso8859-3"), codepage);
5224 XSETFASTINT (codepage, 28592);
5225 store_in_alist (&Vw32_charset_to_codepage_alist,
5226 build_string ("iso8859-2"), codepage);
5227 XSETFASTINT (codepage, 1252);
5228 store_in_alist (&Vw32_charset_to_codepage_alist,
5229 build_string ("iso8859-1"), codepage);