* lisp/emacs-lisp/package.el: New quickstart feature
[emacs.git] / src / w32term.c
blob24950dd25ecb2142ffe631d9f6fc0b8818ac03bf
1 /* Implementation of GUI terminal on the Microsoft Windows API.
3 Copyright (C) 1989, 1993-2018 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
20 #include <config.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include "lisp.h"
24 #include "blockinput.h"
25 #include "w32term.h"
26 #include "w32common.h" /* for OS version info */
28 #include <ctype.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #ifdef CYGWIN
32 #include <fcntl.h> /* for O_RDWR */
33 #endif
34 #include <imm.h>
35 #include <math.h>
37 #include "coding.h"
38 #include "frame.h"
39 #include "fontset.h"
40 #include "termhooks.h"
41 #include "termopts.h"
42 #include "termchar.h"
43 #include "buffer.h"
44 #include "window.h"
45 #include "keyboard.h"
46 #include "menu.h" /* for w32_menu_show */
48 #ifdef WINDOWSNT
49 #include "w32.h" /* for filename_from_utf16, filename_from_ansi */
50 #endif
52 #ifndef WINDOWSNT
53 #include <io.h> /* for get_osfhandle */
54 #endif
56 #include <shellapi.h>
58 #include "font.h"
59 #include "w32font.h"
61 #if 0 /* TODO: stipple */
62 #include "bitmaps/gray.xbm"
63 #endif
65 /* Fringe bitmaps. */
67 static int max_fringe_bmp = 0;
68 static HBITMAP *fringe_bmp = 0;
70 /* Temporary variables for w32_read_socket. */
72 static int last_mousemove_x = 0;
73 static int last_mousemove_y = 0;
75 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
76 #ifndef GET_WHEEL_DELTA_WPARAM
77 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
78 #endif
80 /* Non-zero means that a HELP_EVENT has been generated since Emacs
81 start. */
83 static int any_help_event_p;
85 extern unsigned int msh_mousewheel;
87 extern int w32_codepage_for_font (char *fontname);
88 extern Cursor w32_load_cursor (LPCTSTR name);
90 #define x_any_window_to_frame x_window_to_frame
91 #define x_top_window_to_frame x_window_to_frame
94 /* This is display since w32 does not support multiple ones. */
95 struct w32_display_info one_w32_display_info;
96 struct w32_display_info *x_display_list;
98 #if _WIN32_WINNT < 0x0500 && !defined(MINGW_W64)
99 /* Pre Windows 2000, this was not available, but define it here so
100 that Emacs compiled on such a platform will run on newer versions.
101 MinGW64 defines these unconditionally, so avoid redefining. */
103 typedef struct tagWCRANGE
105 WCHAR wcLow;
106 USHORT cGlyphs;
107 } WCRANGE;
109 typedef struct tagGLYPHSET
111 DWORD cbThis;
112 DWORD flAccel;
113 DWORD cGlyphsSupported;
114 DWORD cRanges;
115 WCRANGE ranges[1];
116 } GLYPHSET;
118 #endif /* compiling for pre-Win2k */
120 /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
121 BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
123 #ifndef LWA_ALPHA
124 #define LWA_ALPHA 0x02
125 #endif
126 /* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
127 later targets by MSVC headers. */
128 #ifndef WS_EX_LAYERED
129 #define WS_EX_LAYERED 0x80000
130 #endif
132 /* SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN are not defined on 95 and
133 NT4. */
134 #ifndef SM_CXVIRTUALSCREEN
135 #define SM_CXVIRTUALSCREEN 78
136 #endif
137 #ifndef SM_CYVIRTUALSCREEN
138 #define SM_CYVIRTUALSCREEN 79
139 #endif
141 /* The handle of the frame that currently owns the system caret. */
142 HWND w32_system_caret_hwnd;
143 int w32_system_caret_height;
144 int w32_system_caret_x;
145 int w32_system_caret_y;
146 struct window *w32_system_caret_window;
147 int w32_system_caret_hdr_height;
148 int w32_system_caret_mode_height;
149 DWORD dwWindowsThreadId = 0;
150 HANDLE hWindowsThread = NULL;
151 DWORD dwMainThreadId = 0;
152 HANDLE hMainThread = NULL;
154 int vertical_scroll_bar_min_handle;
155 int horizontal_scroll_bar_min_handle;
156 int vertical_scroll_bar_top_border;
157 int vertical_scroll_bar_bottom_border;
158 int horizontal_scroll_bar_left_border;
159 int horizontal_scroll_bar_right_border;
161 int last_scroll_bar_drag_pos;
163 /* Keyboard code page - may be changed by language-change events. */
164 int w32_keyboard_codepage;
166 #ifdef CYGWIN
167 int w32_message_fd = -1;
168 #endif /* CYGWIN */
170 static void w32_handle_tool_bar_click (struct frame *,
171 struct input_event *);
172 static void w32_define_cursor (Window, Cursor);
174 void x_lower_frame (struct frame *);
175 void x_scroll_bar_clear (struct frame *);
176 void x_raise_frame (struct frame *);
177 void x_wm_set_window_state (struct frame *, int);
178 void x_wm_set_icon_pixmap (struct frame *, int);
179 static void w32_initialize (void);
180 static void x_update_end (struct frame *);
181 static void w32_frame_up_to_date (struct frame *);
182 static void x_clear_frame (struct frame *);
183 static void frame_highlight (struct frame *);
184 static void frame_unhighlight (struct frame *);
185 static void x_new_focus_frame (struct w32_display_info *,
186 struct frame *);
187 static void x_focus_changed (int, int, struct w32_display_info *,
188 struct frame *, struct input_event *);
189 static void w32_detect_focus_change (struct w32_display_info *,
190 W32Msg *, struct input_event *);
191 static void w32_frame_rehighlight (struct frame *);
192 static void x_frame_rehighlight (struct w32_display_info *);
193 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
194 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
195 enum text_cursor_kinds);
196 static void w32_clip_to_row (struct window *, struct glyph_row *,
197 enum glyph_row_area, HDC);
198 static BOOL my_show_window (struct frame *, HWND, int);
199 static void my_set_window_pos (HWND, HWND, int, int, int, int, UINT);
200 #if 0
201 static void my_set_focus (struct frame *, HWND);
202 #endif
203 static void my_set_foreground_window (HWND);
204 static void my_destroy_window (struct frame *, HWND);
205 static void w32fullscreen_hook (struct frame *);
207 #ifdef GLYPH_DEBUG
208 static void x_check_font (struct frame *, struct font *);
209 #endif
212 /***********************************************************************
213 Debugging
214 ***********************************************************************/
216 #if 0
218 /* This is a function useful for recording debugging information about
219 the sequence of occurrences in this file. */
221 struct record
223 char *locus;
224 int type;
227 struct record event_record[100];
229 int event_record_index;
231 record_event (char *locus, int type)
233 if (event_record_index == sizeof (event_record) / sizeof (struct record))
234 event_record_index = 0;
236 event_record[event_record_index].locus = locus;
237 event_record[event_record_index].type = type;
238 event_record_index++;
241 #endif /* 0 */
244 static void
245 XChangeGC (void *ignore, XGCValues *gc, unsigned long mask,
246 XGCValues *xgcv)
248 if (mask & GCForeground)
249 gc->foreground = xgcv->foreground;
250 if (mask & GCBackground)
251 gc->background = xgcv->background;
252 if (mask & GCFont)
253 gc->font = xgcv->font;
256 XGCValues *
257 XCreateGC (void *ignore, HWND wignore, unsigned long mask, XGCValues *xgcv)
259 XGCValues *gc = xzalloc (sizeof (XGCValues));
261 XChangeGC (ignore, gc, mask, xgcv);
263 return gc;
266 #if 0 /* unused for now, see x_draw_image_glyph_string below */
267 static void
268 XGetGCValues (void *ignore, XGCValues *gc,
269 unsigned long mask, XGCValues *xgcv)
271 XChangeGC (ignore, xgcv, mask, gc);
273 #endif
275 static void
276 w32_set_clip_rectangle (HDC hdc, RECT *rect)
278 if (rect)
280 HRGN clip_region = CreateRectRgnIndirect (rect);
281 SelectClipRgn (hdc, clip_region);
282 DeleteObject (clip_region);
284 else
285 SelectClipRgn (hdc, NULL);
288 /* Restore clipping rectangle in S */
289 static void
290 w32_restore_glyph_string_clip (struct glyph_string *s)
292 RECT *r = s->clip;
293 int n = s->num_clips;
295 if (n == 1)
296 w32_set_clip_rectangle (s->hdc, r);
297 else if (n > 1)
299 HRGN clip1 = CreateRectRgnIndirect (r);
300 HRGN clip2 = CreateRectRgnIndirect (r + 1);
301 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
302 SelectClipRgn (s->hdc, clip1);
303 DeleteObject (clip1);
304 DeleteObject (clip2);
308 static void
309 x_get_scale_factor(struct w32_display_info *dpyinfo, int *scale_x, int *scale_y)
311 const int base_res = 96;
313 *scale_x = *scale_y = 1;
315 if (dpyinfo)
317 if (dpyinfo->resx > base_res)
318 *scale_x = floor (dpyinfo->resx / base_res);
319 if (dpyinfo->resy > base_res)
320 *scale_y = floor (dpyinfo->resy / base_res);
325 Draw a wavy line under S. The wave fills wave_height pixels from y0.
327 x0 wave_length = 2
329 y0 * * * * *
330 |* * * * * * * * *
331 wave_height = 3 | * * * *
335 static void
336 w32_draw_underwave (struct glyph_string *s, COLORREF color)
338 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
340 int scale_x, scale_y;
341 x_get_scale_factor (dpyinfo, &scale_x, &scale_y);
343 int wave_height = 3 * scale_y, wave_length = 2 * scale_x, thickness = scale_y;
344 int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
345 XRectangle wave_clip, string_clip, final_clip;
346 RECT w32_final_clip, w32_string_clip;
347 HPEN hp, oldhp;
349 dx = wave_length;
350 dy = wave_height - 1;
351 x0 = s->x;
352 y0 = s->ybase + wave_height / 2 - scale_y;
353 width = s->width;
354 xmax = x0 + width;
356 /* Find and set clipping rectangle */
358 wave_clip.x = x0;
359 wave_clip.y = y0;
360 wave_clip.width = width;
361 wave_clip.height = wave_height;
363 get_glyph_string_clip_rect (s, &w32_string_clip);
364 CONVERT_TO_XRECT (string_clip, w32_string_clip);
366 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
367 return;
369 hp = CreatePen (PS_SOLID, thickness, color);
370 oldhp = SelectObject (s->hdc, hp);
371 CONVERT_FROM_XRECT (final_clip, w32_final_clip);
372 w32_set_clip_rectangle (s->hdc, &w32_final_clip);
374 /* Draw the waves */
376 x1 = x0 - (x0 % dx);
377 x2 = x1 + dx;
378 odd = (x1/dx) % 2;
379 y1 = y2 = y0;
381 if (odd)
382 y1 += dy;
383 else
384 y2 += dy;
386 MoveToEx (s->hdc, x1, y1, NULL);
388 while (x1 <= xmax)
390 LineTo (s->hdc, x2, y2);
391 x1 = x2, y1 = y2;
392 x2 += dx, y2 = y0 + odd*dy;
393 odd = !odd;
396 /* Restore previous pen and clipping rectangle(s) */
397 w32_restore_glyph_string_clip (s);
398 SelectObject (s->hdc, oldhp);
399 DeleteObject (hp);
402 /* Draw a hollow rectangle at the specified position. */
403 static void
404 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
405 int width, int height)
407 HBRUSH hb, oldhb;
408 HPEN hp, oldhp;
410 hb = CreateSolidBrush (gc->background);
411 hp = CreatePen (PS_SOLID, 0, gc->foreground);
412 oldhb = SelectObject (hdc, hb);
413 oldhp = SelectObject (hdc, hp);
415 /* We enlarge WIDTH and HEIGHT by 1 to be bug-compatible to the
416 brain-dead design of XDrawRectangle, which draws a rectangle that
417 is 1 pixel wider and higher than its arguments WIDTH and HEIGHT.
418 This allows us to keep the code that calls this function similar
419 to the corresponding code in xterm.c. For the details, see
420 https://lists.gnu.org/r/emacs-devel/2014-10/msg00546.html. */
421 Rectangle (hdc, x, y, x + width + 1, y + height + 1);
423 SelectObject (hdc, oldhb);
424 SelectObject (hdc, oldhp);
425 DeleteObject (hb);
426 DeleteObject (hp);
429 /* Draw a filled rectangle at the specified position. */
430 void
431 w32_fill_rect (struct frame *f, HDC hdc, COLORREF pix, RECT *lprect)
433 HBRUSH hb;
435 hb = CreateSolidBrush (pix);
436 FillRect (hdc, lprect, hb);
437 DeleteObject (hb);
440 void
441 w32_clear_window (struct frame *f)
443 RECT rect;
444 HDC hdc = get_frame_dc (f);
446 /* Under certain conditions, this can be called at startup with
447 a console frame pointer before the GUI frame is created. An HDC
448 of 0 indicates this. */
449 if (hdc)
451 GetClientRect (FRAME_W32_WINDOW (f), &rect);
452 w32_clear_rect (f, hdc, &rect);
455 release_frame_dc (f, hdc);
458 #define OPAQUE_FRAME 255
460 void
461 x_set_frame_alpha (struct frame *f)
463 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
464 double alpha = 1.0;
465 double alpha_min = 1.0;
466 BYTE opac;
467 LONG ex_style;
468 HWND window = FRAME_W32_WINDOW (f);
470 /* Older versions of Windows do not support transparency. */
471 if (!pfnSetLayeredWindowAttributes)
472 return;
474 if (dpyinfo->w32_focus_frame == f)
475 alpha = f->alpha[0];
476 else
477 alpha = f->alpha[1];
479 if (FLOATP (Vframe_alpha_lower_limit))
480 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
481 else if (INTEGERP (Vframe_alpha_lower_limit))
482 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
484 if (alpha < 0.0)
485 return;
486 else if (alpha > 1.0)
487 alpha = 1.0;
488 else if (alpha < alpha_min && alpha_min <= 1.0)
489 alpha = alpha_min;
491 opac = alpha * OPAQUE_FRAME;
493 ex_style = GetWindowLong (window, GWL_EXSTYLE);
495 if (opac == OPAQUE_FRAME)
496 ex_style &= ~WS_EX_LAYERED;
497 else
498 ex_style |= WS_EX_LAYERED;
500 SetWindowLong (window, GWL_EXSTYLE, ex_style);
502 if (opac != OPAQUE_FRAME)
503 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
507 x_display_pixel_height (struct w32_display_info *dpyinfo)
509 int pixels = GetSystemMetrics (SM_CYVIRTUALSCREEN);
511 if (pixels == 0)
512 /* Fallback for Windows 95 or NT 4.0. */
513 pixels = GetSystemMetrics (SM_CYSCREEN);
515 return pixels;
519 x_display_pixel_width (struct w32_display_info *dpyinfo)
521 int pixels = GetSystemMetrics (SM_CXVIRTUALSCREEN);
523 if (pixels == 0)
524 /* Fallback for Windows 95 or NT 4.0. */
525 pixels = GetSystemMetrics (SM_CXSCREEN);
527 return pixels;
531 /***********************************************************************
532 Starting and ending an update
533 ***********************************************************************/
535 /* Start an update of frame F. This function is installed as a hook
536 for update_begin, i.e. it is called when update_begin is called.
537 This function is called prior to calls to x_update_window_begin for
538 each window being updated. */
540 static void
541 x_update_begin (struct frame *f)
543 struct w32_display_info *display_info = FRAME_DISPLAY_INFO (f);
545 if (! FRAME_W32_P (f))
546 return;
548 /* Regenerate display palette before drawing if list of requested
549 colors has changed. */
550 if (display_info->regen_palette)
552 w32_regenerate_palette (f);
553 display_info->regen_palette = FALSE;
558 /* Start update of window W. */
560 static void
561 x_update_window_begin (struct window *w)
563 struct frame *f = XFRAME (WINDOW_FRAME (w));
564 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
566 /* Hide the system caret during an update. */
567 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
569 SendMessageTimeout (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0,
570 0, 6000, NULL);
573 w->output_cursor = w->cursor;
575 block_input ();
577 if (f == hlinfo->mouse_face_mouse_frame)
579 /* Don't do highlighting for mouse motion during the update. */
580 hlinfo->mouse_face_defer = true;
582 /* If F needs to be redrawn, simply forget about any prior mouse
583 highlighting. */
584 if (FRAME_GARBAGED_P (f))
585 hlinfo->mouse_face_window = Qnil;
587 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
588 their mouse_face_p flag set, which means that they are always
589 unequal to rows in a desired matrix which never have that
590 flag set. So, rows containing mouse-face glyphs are never
591 scrolled, and we don't have to switch the mouse highlight off
592 here to prevent it from being scrolled. */
594 /* Can we tell that this update does not affect the window
595 where the mouse highlight is? If so, no need to turn off.
596 Likewise, don't do anything if the frame is garbaged;
597 in that case, the frame's current matrix that we would use
598 is all wrong, and we will redisplay that line anyway. */
599 if (!NILP (hlinfo->mouse_face_window)
600 && w == XWINDOW (hlinfo->mouse_face_window))
602 int i;
604 for (i = 0; i < w->desired_matrix->nrows; ++i)
605 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
606 break;
608 if (i < w->desired_matrix->nrows)
609 clear_mouse_face (hlinfo);
611 #endif /* 0 */
614 unblock_input ();
617 /* Draw a vertical window border from (x,y0) to (x,y1) */
619 static void
620 w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
622 struct frame *f = XFRAME (WINDOW_FRAME (w));
623 RECT r;
624 HDC hdc;
625 struct face *face;
627 r.left = x;
628 r.right = x + 1;
629 r.top = y0;
630 r.bottom = y1;
632 hdc = get_frame_dc (f);
633 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
634 if (face)
635 w32_fill_rect (f, hdc, face->foreground, &r);
636 else
637 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
639 release_frame_dc (f, hdc);
643 /* Draw a window divider from (x0, y0) to (x1, y1) */
645 static void
646 w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
648 struct frame *f = XFRAME (WINDOW_FRAME (w));
649 HDC hdc = get_frame_dc (f);
650 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
651 struct face *face_first
652 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
653 struct face *face_last
654 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
655 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
656 unsigned long color_first = (face_first
657 ? face_first->foreground
658 : FRAME_FOREGROUND_PIXEL (f));
659 unsigned long color_last = (face_last
660 ? face_last->foreground
661 : FRAME_FOREGROUND_PIXEL (f));
663 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
664 /* A vertical divider, at least three pixels wide: Draw first and
665 last pixels differently. */
667 w32_fill_area_abs (f, hdc, color_first, x0, y0, x0 + 1, y1);
668 w32_fill_area_abs (f, hdc, color, x0 + 1, y0, x1 - 1, y1);
669 w32_fill_area_abs (f, hdc, color_last, x1 - 1, y0, x1, y1);
671 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
672 /* A horizontal divider, at least three pixels high: Draw first and
673 last pixels differently. */
675 w32_fill_area_abs (f, hdc, color_first, x0, y0, x1, y0 + 1);
676 w32_fill_area_abs (f, hdc, color, x0, y0 + 1, x1, y1 - 1);
677 w32_fill_area_abs (f, hdc, color_last, x0, y1 - 1, x1, y1);
679 else
680 /* In any other case do not draw the first and last pixels
681 differently. */
682 w32_fill_area_abs (f, hdc, color, x0, y0, x1, y1);
684 release_frame_dc (f, hdc);
687 /* End update of window W.
689 Draw vertical borders between horizontally adjacent windows, and
690 display W's cursor if CURSOR_ON_P is non-zero.
692 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
693 glyphs in mouse-face were overwritten. In that case we have to
694 make sure that the mouse-highlight is properly redrawn.
696 W may be a menu bar pseudo-window in case we don't have X toolkit
697 support. Such windows don't have a cursor, so don't display it
698 here. */
700 static void
701 x_update_window_end (struct window *w, bool cursor_on_p,
702 bool mouse_face_overwritten_p)
704 if (!w->pseudo_window_p)
706 block_input ();
708 if (cursor_on_p)
709 display_and_set_cursor (w, true,
710 w->output_cursor.hpos, w->output_cursor.vpos,
711 w->output_cursor.x, w->output_cursor.y);
713 if (draw_window_fringes (w, true))
715 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
716 x_draw_right_divider (w);
717 else
718 x_draw_vertical_border (w);
721 unblock_input ();
724 /* If a row with mouse-face was overwritten, arrange for
725 XTframe_up_to_date to redisplay the mouse highlight. */
726 if (mouse_face_overwritten_p)
728 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
730 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
731 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
732 hlinfo->mouse_face_window = Qnil;
735 /* Unhide the caret. This won't actually show the cursor, unless it
736 was visible before the corresponding call to HideCaret in
737 x_update_window_begin. */
738 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
740 SendMessageTimeout (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0,
741 0, 6000, NULL);
746 /* End update of frame F. This function is installed as a hook in
747 update_end. */
749 static void
750 x_update_end (struct frame *f)
752 if (! FRAME_W32_P (f))
753 return;
755 /* Mouse highlight may be displayed again. */
756 MOUSE_HL_INFO (f)->mouse_face_defer = false;
760 /* This function is called from various places in xdisp.c
761 whenever a complete update has been performed. */
763 static void
764 w32_frame_up_to_date (struct frame *f)
766 if (FRAME_W32_P (f))
767 FRAME_MOUSE_UPDATE (f);
771 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
772 arrow bitmaps, or clear the fringes if no bitmaps are required
773 before DESIRED_ROW is made current. This function is called from
774 update_window_line only if it is known that there are differences
775 between bitmaps to be drawn between current row and DESIRED_ROW. */
777 static void
778 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
780 struct frame *f;
781 int width, height;
783 eassert (w);
785 if (!desired_row->mode_line_p && !w->pseudo_window_p)
786 desired_row->redraw_fringe_bitmaps_p = true;
788 /* When a window has disappeared, make sure that no rest of
789 full-width rows stays visible in the internal border. Could
790 check here if updated window is the leftmost/rightmost window,
791 but I guess it's not worth doing since vertically split windows
792 are almost never used, internal border is rarely set, and the
793 overhead is very small. */
794 if (windows_or_buffers_changed
795 && desired_row->full_width_p
796 && (f = XFRAME (w->frame),
797 width = FRAME_INTERNAL_BORDER_WIDTH (f),
798 width != 0)
799 && (height = desired_row->visible_height,
800 height > 0))
802 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
804 block_input ();
806 HDC hdc = get_frame_dc (f);
807 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
809 if (face)
811 /* Fill border with internal border face. */
812 unsigned long color = face->background;
814 w32_fill_area (f, hdc, color, 0, y, width, height);
815 w32_fill_area (f, hdc, color, FRAME_PIXEL_WIDTH (f) - width,
816 y, width, height);
818 else
820 w32_clear_area (f, hdc, 0, y, width, height);
821 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
822 y, width, height);
824 release_frame_dc (f, hdc);
826 unblock_input ();
831 /* Draw the bitmap WHICH in one of the left or right fringes of
832 window W. ROW is the glyph row for which to display the bitmap; it
833 determines the vertical position at which the bitmap has to be
834 drawn. */
836 static void
837 w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
838 struct draw_fringe_bitmap_params *p)
840 struct frame *f = XFRAME (WINDOW_FRAME (w));
841 HDC hdc;
842 struct face *face = p->face;
844 hdc = get_frame_dc (f);
846 /* Must clip because of partially visible lines. */
847 w32_clip_to_row (w, row, ANY_AREA, hdc);
849 if (p->bx >= 0 && !p->overlay_p)
850 w32_fill_area (f, hdc, face->background,
851 p->bx, p->by, p->nx, p->ny);
853 if (p->which && p->which < max_fringe_bmp)
855 HBITMAP pixmap = fringe_bmp[p->which];
856 HDC compat_hdc;
857 HANDLE horig_obj;
859 compat_hdc = CreateCompatibleDC (hdc);
861 SaveDC (hdc);
863 horig_obj = SelectObject (compat_hdc, pixmap);
865 /* Paint overlays transparently. */
866 if (p->overlay_p)
868 HBRUSH h_brush, h_orig_brush;
870 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
871 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
872 h_brush = CreateSolidBrush (face->foreground);
873 h_orig_brush = SelectObject (hdc, h_brush);
875 BitBlt (hdc, p->x, p->y, p->wd, p->h,
876 compat_hdc, 0, p->dh,
877 DSTINVERT);
878 BitBlt (hdc, p->x, p->y, p->wd, p->h,
879 compat_hdc, 0, p->dh,
880 0x2E064A);
881 BitBlt (hdc, p->x, p->y, p->wd, p->h,
882 compat_hdc, 0, p->dh,
883 DSTINVERT);
885 SelectObject (hdc, h_orig_brush);
886 DeleteObject (h_brush);
888 else
890 SetTextColor (hdc, face->background);
891 SetBkColor (hdc, (p->cursor_p
892 ? f->output_data.w32->cursor_pixel
893 : face->foreground));
895 BitBlt (hdc, p->x, p->y, p->wd, p->h,
896 compat_hdc, 0, p->dh,
897 SRCCOPY);
900 SelectObject (compat_hdc, horig_obj);
901 DeleteDC (compat_hdc);
902 RestoreDC (hdc, -1);
905 w32_set_clip_rectangle (hdc, NULL);
907 release_frame_dc (f, hdc);
910 static void
911 w32_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
913 if (which >= max_fringe_bmp)
915 int i = max_fringe_bmp;
916 max_fringe_bmp = which + 20;
917 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
918 while (i < max_fringe_bmp)
919 fringe_bmp[i++] = 0;
922 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
925 static void
926 w32_destroy_fringe_bitmap (int which)
928 if (which >= max_fringe_bmp)
929 return;
931 if (fringe_bmp[which])
932 DeleteObject (fringe_bmp[which]);
933 fringe_bmp[which] = 0;
936 /***********************************************************************
937 Display Iterator
938 ***********************************************************************/
940 /* Function prototypes of this page. */
942 static void x_set_glyph_string_clipping (struct glyph_string *);
943 static void x_set_glyph_string_gc (struct glyph_string *);
944 static void x_draw_glyph_string_background (struct glyph_string *,
945 bool);
946 static void x_draw_glyph_string_foreground (struct glyph_string *);
947 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
948 static void x_draw_glyph_string_box (struct glyph_string *);
949 static void x_draw_glyph_string (struct glyph_string *);
950 static void x_set_cursor_gc (struct glyph_string *);
951 static void x_set_mode_line_face_gc (struct glyph_string *);
952 static void x_set_mouse_face_gc (struct glyph_string *);
953 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
954 static void w32_setup_relief_color (struct frame *, struct relief *,
955 double, int, COLORREF);
956 static void x_setup_relief_colors (struct glyph_string *);
957 static void x_draw_image_glyph_string (struct glyph_string *);
958 static void x_draw_image_relief (struct glyph_string *);
959 static void x_draw_image_foreground (struct glyph_string *);
960 static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
961 static void x_clear_glyph_string_rect (struct glyph_string *, int,
962 int, int, int);
963 static void w32_draw_relief_rect (struct frame *, int, int, int, int,
964 int, int, int, int, int, int,
965 RECT *);
966 static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
967 int, bool, bool, RECT *);
970 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
971 face. */
973 static void
974 x_set_cursor_gc (struct glyph_string *s)
976 if (s->font == FRAME_FONT (s->f)
977 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
978 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
979 /* Sometimes we are not called for each change in the default
980 face's background color (e.g., bug#26851), so the additional
981 test in the next line gives us a chance to resync. */
982 && s->f->output_data.w32->cursor_gc->foreground == s->face->background
983 && !s->cmp)
984 s->gc = s->f->output_data.w32->cursor_gc;
985 else
987 /* Cursor on non-default face: must merge. */
988 XGCValues xgcv;
989 unsigned long mask;
991 xgcv.background = s->f->output_data.w32->cursor_pixel;
992 xgcv.foreground = s->face->background;
994 /* If the glyph would be invisible, try a different foreground. */
995 if (xgcv.foreground == xgcv.background)
996 xgcv.foreground = s->face->foreground;
997 if (xgcv.foreground == xgcv.background)
998 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
999 if (xgcv.foreground == xgcv.background)
1000 xgcv.foreground = s->face->foreground;
1002 /* Make sure the cursor is distinct from text in this face. */
1003 if (xgcv.background == s->face->background
1004 && xgcv.foreground == s->face->foreground)
1006 xgcv.background = s->face->foreground;
1007 xgcv.foreground = s->face->background;
1010 IF_DEBUG (x_check_font (s->f, s->font));
1011 xgcv.font = s->font;
1012 mask = GCForeground | GCBackground | GCFont;
1014 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1015 XChangeGC (NULL, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1016 mask, &xgcv);
1017 else
1018 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1019 = XCreateGC (NULL, FRAME_W32_WINDOW (s->f), mask, &xgcv);
1021 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1026 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1028 static void
1029 x_set_mouse_face_gc (struct glyph_string *s)
1031 int face_id;
1032 struct face *face;
1034 /* What face has to be used last for the mouse face? */
1035 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1036 face = FACE_FROM_ID_OR_NULL (s->f, face_id);
1037 if (face == NULL)
1038 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1040 if (s->first_glyph->type == CHAR_GLYPH)
1041 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1042 else
1043 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1044 s->face = FACE_FROM_ID (s->f, face_id);
1045 prepare_face_for_display (s->f, s->face);
1047 /* If font in this face is same as S->font, use it. */
1048 if (s->font == s->face->font)
1049 s->gc = s->face->gc;
1050 else
1052 /* Otherwise construct scratch_cursor_gc with values from FACE
1053 but font FONT. */
1054 XGCValues xgcv;
1055 unsigned long mask;
1057 xgcv.background = s->face->background;
1058 xgcv.foreground = s->face->foreground;
1059 IF_DEBUG (x_check_font (s->f, s->font));
1060 xgcv.font = s->font;
1061 mask = GCForeground | GCBackground | GCFont;
1063 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1064 XChangeGC (NULL, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1065 mask, &xgcv);
1066 else
1067 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
1068 = XCreateGC (NULL, FRAME_W32_WINDOW (s->f), mask, &xgcv);
1070 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1073 eassert (s->gc != 0);
1077 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1078 Faces to use in the mode line have already been computed when the
1079 matrix was built, so there isn't much to do, here. */
1081 static inline void
1082 x_set_mode_line_face_gc (struct glyph_string *s)
1084 s->gc = s->face->gc;
1088 /* Set S->gc of glyph string S for drawing that glyph string. Set
1089 S->stippled_p to a non-zero value if the face of S has a stipple
1090 pattern. */
1092 static inline void
1093 x_set_glyph_string_gc (struct glyph_string *s)
1095 prepare_face_for_display (s->f, s->face);
1097 if (s->hl == DRAW_NORMAL_TEXT)
1099 s->gc = s->face->gc;
1100 s->stippled_p = s->face->stipple != 0;
1102 else if (s->hl == DRAW_INVERSE_VIDEO)
1104 x_set_mode_line_face_gc (s);
1105 s->stippled_p = s->face->stipple != 0;
1107 else if (s->hl == DRAW_CURSOR)
1109 x_set_cursor_gc (s);
1110 s->stippled_p = false;
1112 else if (s->hl == DRAW_MOUSE_FACE)
1114 x_set_mouse_face_gc (s);
1115 s->stippled_p = s->face->stipple != 0;
1117 else if (s->hl == DRAW_IMAGE_RAISED
1118 || s->hl == DRAW_IMAGE_SUNKEN)
1120 s->gc = s->face->gc;
1121 s->stippled_p = s->face->stipple != 0;
1123 else
1124 emacs_abort ();
1126 /* GC must have been set. */
1127 eassert (s->gc != 0);
1131 /* Set clipping for output of glyph string S. S may be part of a mode
1132 line or menu if we don't have X toolkit support. */
1134 static inline void
1135 x_set_glyph_string_clipping (struct glyph_string *s)
1137 RECT *r = s->clip;
1138 int n = get_glyph_string_clip_rects (s, r, 2);
1140 if (n == 1)
1141 w32_set_clip_rectangle (s->hdc, r);
1142 else if (n > 1)
1144 HRGN clip1 = CreateRectRgnIndirect (r);
1145 HRGN clip2 = CreateRectRgnIndirect (r + 1);
1146 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
1147 SelectClipRgn (s->hdc, clip1);
1148 DeleteObject (clip1);
1149 DeleteObject (clip2);
1151 s->num_clips = n;
1154 /* Set SRC's clipping for output of glyph string DST. This is called
1155 when we are drawing DST's left_overhang or right_overhang only in
1156 the area of SRC. */
1158 static void
1159 x_set_glyph_string_clipping_exactly (struct glyph_string *src,
1160 struct glyph_string *dst)
1162 RECT r;
1164 r.left = src->x;
1165 r.right = r.left + src->width;
1166 r.top = src->y;
1167 r.bottom = r.top + src->height;
1168 dst->clip[0] = r;
1169 dst->num_clips = 1;
1170 w32_set_clip_rectangle (dst->hdc, &r);
1173 /* RIF:
1174 Compute left and right overhang of glyph string S. */
1176 static void
1177 w32_compute_glyph_string_overhangs (struct glyph_string *s)
1179 if (s->cmp == NULL
1180 && s->first_glyph->type == CHAR_GLYPH
1181 && !s->font_not_found_p)
1183 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1184 struct font *font = s->font;
1185 struct font_metrics metrics;
1186 int i;
1188 for (i = 0; i < s->nchars; i++)
1189 code[i] = s->char2b[i];
1190 font->driver->text_extents (font, code, s->nchars, &metrics);
1191 s->right_overhang = (metrics.rbearing > metrics.width
1192 ? metrics.rbearing - metrics.width : 0);
1193 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
1195 else if (s->cmp)
1197 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1198 s->left_overhang = -s->cmp->lbearing;
1202 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1204 static inline void
1205 x_clear_glyph_string_rect (struct glyph_string *s,
1206 int x, int y, int w, int h)
1208 int real_x = x;
1209 int real_y = y;
1210 int real_w = w;
1211 int real_h = h;
1212 #if 0
1213 /* Take clipping into account. */
1214 if (s->gc->clip_mask == Rect)
1216 real_x = max (real_x, s->gc->clip_rectangle.left);
1217 real_y = max (real_y, s->gc->clip_rectangle.top);
1218 real_w = min (real_w, s->gc->clip_rectangle.right
1219 - s->gc->clip_rectangle.left);
1220 real_h = min (real_h, s->gc->clip_rectangle.bottom
1221 - s->gc->clip_rectangle.top);
1223 #endif
1224 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1225 real_w, real_h);
1229 /* Draw the background of glyph_string S. If S->background_filled_p
1230 is non-zero don't draw it. FORCE_P non-zero means draw the
1231 background even if it wouldn't be drawn normally. This is used
1232 when a string preceding S draws into the background of S, or S
1233 contains the first component of a composition. */
1235 static void
1236 x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1238 /* Nothing to do if background has already been drawn or if it
1239 shouldn't be drawn in the first place. */
1240 if (!s->background_filled_p)
1242 int box_line_width = max (s->face->box_line_width, 0);
1244 #if 0 /* TODO: stipple */
1245 if (s->stippled_p)
1247 /* Fill background with a stipple pattern. */
1248 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1249 XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), s->gc, s->x,
1250 s->y + box_line_width,
1251 s->background_width,
1252 s->height - 2 * box_line_width);
1253 XSetFillStyle (s->display, s->gc, FillSolid);
1254 s->background_filled_p = true;
1256 else
1257 #endif
1258 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1259 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1260 font dimensions, since the actual glyphs might be
1261 much smaller. So in that case we always clear the
1262 rectangle with background color. */
1263 || FONT_TOO_HIGH (s->font)
1264 || s->font_not_found_p
1265 || s->extends_to_end_of_line_p
1266 || force_p)
1268 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1269 s->background_width,
1270 s->height - 2 * box_line_width);
1271 s->background_filled_p = true;
1277 /* Draw the foreground of glyph string S. */
1279 static void
1280 x_draw_glyph_string_foreground (struct glyph_string *s)
1282 int i, x;
1284 /* If first glyph of S has a left box line, start drawing the text
1285 of S to the right of that box line. */
1286 if (s->face->box != FACE_NO_BOX
1287 && s->first_glyph->left_box_line_p)
1288 x = s->x + eabs (s->face->box_line_width);
1289 else
1290 x = s->x;
1292 SetTextColor (s->hdc, s->gc->foreground);
1293 SetBkColor (s->hdc, s->gc->background);
1294 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1296 /* Draw characters of S as rectangles if S's font could not be
1297 loaded. */
1298 if (s->font_not_found_p)
1300 for (i = 0; i < s->nchars; ++i)
1302 struct glyph *g = s->first_glyph + i;
1304 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1305 s->height - 1);
1306 x += g->pixel_width;
1309 else
1311 struct font *font = s->font;
1312 int boff = font->baseline_offset;
1313 int y;
1314 HFONT old_font;
1316 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1318 if (font->vertical_centering)
1319 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1321 y = s->ybase - boff;
1322 if (s->for_overlaps
1323 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1324 font->driver->draw (s, 0, s->nchars, x, y, false);
1325 else
1326 font->driver->draw (s, 0, s->nchars, x, y, true);
1327 if (s->face->overstrike)
1328 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
1330 SelectObject (s->hdc, old_font);
1334 /* Draw the foreground of composite glyph string S. */
1336 static void
1337 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1339 int i, j, x;
1340 struct font *font = s->font;
1342 /* If first glyph of S has a left box line, start drawing the text
1343 of S to the right of that box line. */
1344 if (s->face && s->face->box != FACE_NO_BOX
1345 && s->first_glyph->left_box_line_p)
1346 x = s->x + eabs (s->face->box_line_width);
1347 else
1348 x = s->x;
1350 /* S is a glyph string for a composition. S->cmp_from is the index
1351 of the first character drawn for glyphs of this composition.
1352 S->cmp_from == 0 means we are drawing the very first character of
1353 this composition. */
1355 SetTextColor (s->hdc, s->gc->foreground);
1356 SetBkColor (s->hdc, s->gc->background);
1357 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1359 /* Draw a rectangle for the composition if the font for the very
1360 first character of the composition could not be loaded. */
1361 if (s->font_not_found_p)
1363 if (s->cmp_from == 0)
1364 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1365 s->height - 1);
1367 else if (! s->first_glyph->u.cmp.automatic)
1369 int y = s->ybase;
1370 HFONT old_font;
1372 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1374 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1375 /* TAB in a composition means display glyphs with padding
1376 space on the left or right. */
1377 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1379 int xx = x + s->cmp->offsets[j * 2];
1380 int yy = y - s->cmp->offsets[j * 2 + 1];
1382 font->driver->draw (s, j, j + 1, xx, yy, false);
1383 if (s->face->overstrike)
1384 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1386 SelectObject (s->hdc, old_font);
1388 else
1390 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1391 Lisp_Object glyph;
1392 int y = s->ybase;
1393 int width = 0;
1394 HFONT old_font;
1396 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1398 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1400 glyph = LGSTRING_GLYPH (gstring, i);
1401 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1402 width += LGLYPH_WIDTH (glyph);
1403 else
1405 int xoff, yoff, wadjust;
1407 if (j < i)
1409 font->driver->draw (s, j, i, x, y, false);
1410 x += width;
1412 xoff = LGLYPH_XOFF (glyph);
1413 yoff = LGLYPH_YOFF (glyph);
1414 wadjust = LGLYPH_WADJUST (glyph);
1415 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1416 x += wadjust;
1417 j = i + 1;
1418 width = 0;
1421 if (j < i)
1422 font->driver->draw (s, j, i, x, y, false);
1424 SelectObject (s->hdc, old_font);
1429 /* Draw the foreground of glyph string S for glyphless characters. */
1431 static void
1432 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1434 struct glyph *glyph = s->first_glyph;
1435 XChar2b char2b[8];
1436 int x, i, j;
1437 bool with_background;
1439 /* If first glyph of S has a left box line, start drawing the text
1440 of S to the right of that box line. */
1441 if (s->face->box != FACE_NO_BOX
1442 && s->first_glyph->left_box_line_p)
1443 x = s->x + eabs (s->face->box_line_width);
1444 else
1445 x = s->x;
1447 SetTextColor (s->hdc, s->gc->foreground);
1448 SetBkColor (s->hdc, s->gc->background);
1449 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1451 s->char2b = char2b;
1452 with_background = ((s->for_overlaps
1453 || (s->background_filled_p && s->hl != DRAW_CURSOR))) == 0;
1454 for (i = 0; i < s->nchars; i++, glyph++)
1456 char buf[7], *str = NULL;
1457 int len = glyph->u.glyphless.len;
1459 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1461 if (len > 0
1462 && CHAR_TABLE_P (Vglyphless_char_display)
1463 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1464 >= 1))
1466 Lisp_Object acronym
1467 = (! glyph->u.glyphless.for_no_font
1468 ? CHAR_TABLE_REF (Vglyphless_char_display,
1469 glyph->u.glyphless.ch)
1470 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1471 if (STRINGP (acronym))
1472 str = SSDATA (acronym);
1475 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1477 sprintf ((char *) buf, "%0*X",
1478 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1479 (unsigned int) glyph->u.glyphless.ch);
1480 str = buf;
1483 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1484 w32_draw_rectangle (s->hdc, s->gc,
1485 x, s->ybase - glyph->ascent,
1486 glyph->pixel_width - 1,
1487 glyph->ascent + glyph->descent - 1);
1488 if (str)
1490 struct font *font = s->font;
1491 int upper_len = (len + 1) / 2;
1492 unsigned code;
1493 HFONT old_font;
1495 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1496 /* It is certain that all LEN characters in STR are ASCII. */
1497 for (j = 0; j < len; j++)
1499 code = font->driver->encode_char (font, str[j]);
1500 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1502 font->driver->draw (s, 0, upper_len,
1503 x + glyph->slice.glyphless.upper_xoff,
1504 s->ybase + glyph->slice.glyphless.upper_yoff,
1505 with_background);
1506 font->driver->draw (s, upper_len, len,
1507 x + glyph->slice.glyphless.lower_xoff,
1508 s->ybase + glyph->slice.glyphless.lower_yoff,
1509 with_background);
1510 SelectObject (s->hdc, old_font);
1512 x += glyph->pixel_width;
1517 /* Brightness beyond which a color won't have its highlight brightness
1518 boosted.
1520 Nominally, highlight colors for `3d' faces are calculated by
1521 brightening an object's color by a constant scale factor, but this
1522 doesn't yield good results for dark colors, so for colors whose
1523 brightness is less than this value (on a scale of 0-255) have to
1524 use an additional additive factor.
1526 The value here is set so that the default menu-bar/mode-line color
1527 (grey75) will not have its highlights changed at all. */
1528 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1531 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1532 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1533 If this produces the same color as COLOR, try a color where all RGB
1534 values have DELTA added. Return the allocated color in *COLOR.
1535 DISPLAY is the X display, CMAP is the colormap to operate on.
1536 Value is non-zero if successful. */
1538 static int
1539 w32_alloc_lighter_color (struct frame *f, COLORREF *color,
1540 double factor, int delta)
1542 COLORREF new;
1543 long bright;
1545 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1546 delta /= 256;
1548 /* Change RGB values by specified FACTOR. Avoid overflow! */
1549 eassert (factor >= 0);
1550 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1551 min (0xff, factor * GetGValue (*color)),
1552 min (0xff, factor * GetBValue (*color)));
1554 /* Calculate brightness of COLOR. */
1555 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1556 + GetBValue (*color)) / 6;
1558 /* We only boost colors that are darker than
1559 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1560 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1561 /* Make an additive adjustment to NEW, because it's dark enough so
1562 that scaling by FACTOR alone isn't enough. */
1564 /* How far below the limit this color is (0 - 1, 1 being darker). */
1565 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1566 /* The additive adjustment. */
1567 int min_delta = delta * dimness * factor / 2;
1569 if (factor < 1)
1570 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1571 max (0, min (0xff, min_delta - GetGValue (*color))),
1572 max (0, min (0xff, min_delta - GetBValue (*color))));
1573 else
1574 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1575 max (0, min (0xff, min_delta + GetGValue (*color))),
1576 max (0, min (0xff, min_delta + GetBValue (*color))));
1579 if (new == *color)
1580 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1581 max (0, min (0xff, delta + GetGValue (*color))),
1582 max (0, min (0xff, delta + GetBValue (*color))));
1584 /* TODO: Map to palette and retry with delta if same? */
1585 /* TODO: Free colors (if using palette)? */
1587 if (new == *color)
1588 return 0;
1590 *color = new;
1592 return 1;
1595 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1596 colors in COLORS. On W32, we no longer try to map colors to
1597 a palette. */
1598 void
1599 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1601 int i;
1603 for (i = 0; i < ncolors; i++)
1605 DWORD pixel = colors[i].pixel;
1606 /* Convert to a 16 bit value in range 0 - 0xffff. */
1607 colors[i].red = GetRValue (pixel) * 257;
1608 colors[i].green = GetGValue (pixel) * 257;
1609 colors[i].blue = GetBValue (pixel) * 257;
1613 void
1614 x_query_color (struct frame *f, XColor *color)
1616 x_query_colors (f, color, 1);
1620 /* Set up the foreground color for drawing relief lines of glyph
1621 string S. RELIEF is a pointer to a struct relief containing the GC
1622 with which lines will be drawn. Use a color that is FACTOR or
1623 DELTA lighter or darker than the relief's background which is found
1624 in S->f->output_data.x->relief_background. If such a color cannot
1625 be allocated, use DEFAULT_PIXEL, instead. */
1627 static void
1628 w32_setup_relief_color (struct frame *f, struct relief *relief, double factor,
1629 int delta, COLORREF default_pixel)
1631 XGCValues xgcv;
1632 struct w32_output *di = f->output_data.w32;
1633 unsigned long mask = GCForeground;
1634 COLORREF pixel;
1635 COLORREF background = di->relief_background;
1636 #if 0
1637 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1638 #endif
1640 /* TODO: Free colors (if using palette)? */
1642 /* Allocate new color. */
1643 xgcv.foreground = default_pixel;
1644 pixel = background;
1645 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1646 xgcv.foreground = relief->pixel = pixel;
1648 xgcv.font = NULL; /* avoid compiler warnings */
1649 if (relief->gc == 0)
1651 #if 0 /* TODO: stipple */
1652 xgcv.stipple = dpyinfo->gray;
1653 mask |= GCStipple;
1654 #endif
1655 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1657 else
1658 XChangeGC (NULL, relief->gc, mask, &xgcv);
1662 /* Set up colors for the relief lines around glyph string S. */
1664 static void
1665 x_setup_relief_colors (struct glyph_string *s)
1667 struct w32_output *di = s->f->output_data.w32;
1668 COLORREF color;
1670 if (s->face->use_box_color_for_shadows_p)
1671 color = s->face->box_color;
1672 else if (s->first_glyph->type == IMAGE_GLYPH
1673 && s->img->pixmap
1674 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1675 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1676 else
1677 color = s->gc->background;
1679 if (di->white_relief.gc == 0
1680 || color != di->relief_background)
1682 di->relief_background = color;
1683 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1684 WHITE_PIX_DEFAULT (s->f));
1685 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1686 BLACK_PIX_DEFAULT (s->f));
1691 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1692 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1693 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1694 relief. LEFT_P non-zero means draw a relief on the left side of
1695 the rectangle. RIGHT_P non-zero means draw a relief on the right
1696 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1697 when drawing. */
1699 static void
1700 w32_draw_relief_rect (struct frame *f,
1701 int left_x, int top_y, int right_x, int bottom_y,
1702 int width, int raised_p,
1703 int top_p, int bot_p, int left_p, int right_p,
1704 RECT *clip_rect)
1706 int i;
1707 XGCValues gc;
1708 HDC hdc = get_frame_dc (f);
1710 if (raised_p)
1711 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1712 else
1713 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1715 w32_set_clip_rectangle (hdc, clip_rect);
1717 /* Top. */
1718 if (top_p)
1719 for (i = 0; i < width; ++i)
1720 w32_fill_area (f, hdc, gc.foreground,
1721 left_x + i * left_p, top_y + i,
1722 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1724 /* Left. */
1725 if (left_p)
1726 for (i = 0; i < width; ++i)
1727 w32_fill_area (f, hdc, gc.foreground,
1728 left_x + i, top_y + (i + 1) * top_p, 1,
1729 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
1731 if (raised_p)
1732 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1733 else
1734 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1736 /* Bottom. */
1737 if (bot_p)
1738 for (i = 0; i < width; ++i)
1739 w32_fill_area (f, hdc, gc.foreground,
1740 left_x + i * left_p, bottom_y - i,
1741 right_x - left_x - i * (left_p + right_p) + 1, 1);
1743 /* Right. */
1744 if (right_p)
1745 for (i = 0; i < width; ++i)
1746 w32_fill_area (f, hdc, gc.foreground,
1747 right_x - i, top_y + (i + 1) * top_p, 1,
1748 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
1750 w32_set_clip_rectangle (hdc, NULL);
1752 release_frame_dc (f, hdc);
1756 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1757 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1758 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1759 left side of the rectangle. RIGHT_P non-zero means draw a line
1760 on the right side of the rectangle. CLIP_RECT is the clipping
1761 rectangle to use when drawing. */
1763 static void
1764 w32_draw_box_rect (struct glyph_string *s,
1765 int left_x, int top_y, int right_x, int bottom_y, int width,
1766 bool left_p, bool right_p, RECT *clip_rect)
1768 w32_set_clip_rectangle (s->hdc, clip_rect);
1770 /* Top. */
1771 w32_fill_area (s->f, s->hdc, s->face->box_color,
1772 left_x, top_y, right_x - left_x + 1, width);
1774 /* Left. */
1775 if (left_p)
1777 w32_fill_area (s->f, s->hdc, s->face->box_color,
1778 left_x, top_y, width, bottom_y - top_y + 1);
1781 /* Bottom. */
1782 w32_fill_area (s->f, s->hdc, s->face->box_color,
1783 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1785 /* Right. */
1786 if (right_p)
1788 w32_fill_area (s->f, s->hdc, s->face->box_color,
1789 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1792 w32_set_clip_rectangle (s->hdc, NULL);
1796 /* Draw a box around glyph string S. */
1798 static void
1799 x_draw_glyph_string_box (struct glyph_string *s)
1801 int width, left_x, right_x, top_y, bottom_y, last_x;
1802 bool left_p, right_p, raised_p;
1803 struct glyph *last_glyph;
1804 RECT clip_rect;
1806 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1807 ? WINDOW_RIGHT_EDGE_X (s->w)
1808 : window_box_right (s->w, s->area));
1810 /* The glyph that may have a right box line. */
1811 last_glyph = (s->cmp || s->img
1812 ? s->first_glyph
1813 : s->first_glyph + s->nchars - 1);
1815 width = eabs (s->face->box_line_width);
1816 raised_p = s->face->box == FACE_RAISED_BOX;
1817 left_x = s->x;
1818 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1819 ? last_x - 1
1820 : min (last_x, s->x + s->background_width) - 1));
1821 top_y = s->y;
1822 bottom_y = top_y + s->height - 1;
1824 left_p = (s->first_glyph->left_box_line_p
1825 || (s->hl == DRAW_MOUSE_FACE
1826 && (s->prev == NULL
1827 || s->prev->hl != s->hl)));
1828 right_p = (last_glyph->right_box_line_p
1829 || (s->hl == DRAW_MOUSE_FACE
1830 && (s->next == NULL
1831 || s->next->hl != s->hl)));
1833 get_glyph_string_clip_rect (s, &clip_rect);
1835 if (s->face->box == FACE_SIMPLE_BOX)
1836 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1837 left_p, right_p, &clip_rect);
1838 else
1840 x_setup_relief_colors (s);
1841 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1842 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1847 /* Draw foreground of image glyph string S. */
1849 static void
1850 x_draw_image_foreground (struct glyph_string *s)
1852 int x = s->x;
1853 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1855 /* If first glyph of S has a left box line, start drawing it to the
1856 right of that line. */
1857 if (s->face->box != FACE_NO_BOX
1858 && s->first_glyph->left_box_line_p
1859 && s->slice.x == 0)
1860 x += eabs (s->face->box_line_width);
1862 /* If there is a margin around the image, adjust x- and y-position
1863 by that margin. */
1864 if (s->slice.x == 0)
1865 x += s->img->hmargin;
1866 if (s->slice.y == 0)
1867 y += s->img->vmargin;
1869 SaveDC (s->hdc);
1871 if (s->img->pixmap)
1873 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1874 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1875 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1876 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1877 SetBkColor (compat_hdc, RGB (255, 255, 255));
1878 SetTextColor (s->hdc, RGB (0, 0, 0));
1879 x_set_glyph_string_clipping (s);
1881 if (s->img->mask)
1883 HDC mask_dc = CreateCompatibleDC (s->hdc);
1884 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1886 SetTextColor (s->hdc, RGB (255, 255, 255));
1887 SetBkColor (s->hdc, RGB (0, 0, 0));
1889 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1890 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1891 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1892 mask_dc, s->slice.x, s->slice.y, SRCAND);
1893 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1894 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1896 SelectObject (mask_dc, mask_orig_obj);
1897 DeleteDC (mask_dc);
1899 else
1901 SetTextColor (s->hdc, s->gc->foreground);
1902 SetBkColor (s->hdc, s->gc->background);
1904 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1905 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1907 /* When the image has a mask, we can expect that at
1908 least part of a mouse highlight or a block cursor will
1909 be visible. If the image doesn't have a mask, make
1910 a block cursor visible by drawing a rectangle around
1911 the image. I believe it's looking better if we do
1912 nothing here for mouse-face. */
1913 if (s->hl == DRAW_CURSOR)
1915 int r = s->img->relief;
1916 if (r < 0) r = -r;
1917 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
1918 s->slice.width + r*2 - 1,
1919 s->slice.height + r*2 - 1);
1923 w32_set_clip_rectangle (s->hdc, NULL);
1924 SelectObject (s->hdc, orig_brush);
1925 DeleteObject (fg_brush);
1926 SelectObject (compat_hdc, orig_obj);
1927 DeleteDC (compat_hdc);
1929 else
1930 w32_draw_rectangle (s->hdc, s->gc, x, y,
1931 s->slice.width - 1, s->slice.height - 1);
1933 RestoreDC (s->hdc ,-1);
1937 /* Draw a relief around the image glyph string S. */
1939 static void
1940 x_draw_image_relief (struct glyph_string *s)
1942 int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
1943 int extra_x, extra_y;
1944 RECT r;
1945 int x = s->x;
1946 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1948 /* If first glyph of S has a left box line, start drawing it to the
1949 right of that line. */
1950 if (s->face->box != FACE_NO_BOX
1951 && s->first_glyph->left_box_line_p
1952 && s->slice.x == 0)
1953 x += eabs (s->face->box_line_width);
1955 /* If there is a margin around the image, adjust x- and y-position
1956 by that margin. */
1957 if (s->slice.x == 0)
1958 x += s->img->hmargin;
1959 if (s->slice.y == 0)
1960 y += s->img->vmargin;
1962 if (s->hl == DRAW_IMAGE_SUNKEN
1963 || s->hl == DRAW_IMAGE_RAISED)
1965 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief
1966 : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1967 raised_p = s->hl == DRAW_IMAGE_RAISED;
1969 else
1971 thick = eabs (s->img->relief);
1972 raised_p = s->img->relief > 0;
1975 x1 = x + s->slice.width - 1;
1976 y1 = y + s->slice.height - 1;
1978 extra_x = extra_y = 0;
1979 if (s->face->id == TOOL_BAR_FACE_ID)
1981 if (CONSP (Vtool_bar_button_margin)
1982 && INTEGERP (XCAR (Vtool_bar_button_margin))
1983 && INTEGERP (XCDR (Vtool_bar_button_margin)))
1985 extra_x = XINT (XCAR (Vtool_bar_button_margin));
1986 extra_y = XINT (XCDR (Vtool_bar_button_margin));
1988 else if (INTEGERP (Vtool_bar_button_margin))
1989 extra_x = extra_y = XINT (Vtool_bar_button_margin);
1992 top_p = bot_p = left_p = right_p = 0;
1994 if (s->slice.x == 0)
1995 x -= thick + extra_x, left_p = 1;
1996 if (s->slice.y == 0)
1997 y -= thick + extra_y, top_p = 1;
1998 if (s->slice.x + s->slice.width == s->img->width)
1999 x1 += thick + extra_x, right_p = 1;
2000 if (s->slice.y + s->slice.height == s->img->height)
2001 y1 += thick + extra_y, bot_p = 1;
2003 x_setup_relief_colors (s);
2004 get_glyph_string_clip_rect (s, &r);
2005 w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
2006 top_p, bot_p, left_p, right_p, &r);
2010 /* Draw the foreground of image glyph string S to PIXMAP. */
2012 static void
2013 w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
2015 HDC hdc = CreateCompatibleDC (s->hdc);
2016 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
2017 int x = 0;
2018 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2020 /* If first glyph of S has a left box line, start drawing it to the
2021 right of that line. */
2022 if (s->face->box != FACE_NO_BOX
2023 && s->first_glyph->left_box_line_p
2024 && s->slice.x == 0)
2025 x += eabs (s->face->box_line_width);
2027 /* If there is a margin around the image, adjust x- and y-position
2028 by that margin. */
2029 if (s->slice.x == 0)
2030 x += s->img->hmargin;
2031 if (s->slice.y == 0)
2032 y += s->img->vmargin;
2034 if (s->img->pixmap)
2036 HDC compat_hdc = CreateCompatibleDC (hdc);
2037 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2038 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2039 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2041 if (s->img->mask)
2043 HDC mask_dc = CreateCompatibleDC (hdc);
2044 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2046 SetTextColor (hdc, RGB (0, 0, 0));
2047 SetBkColor (hdc, RGB (255, 255, 255));
2048 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2049 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2050 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2051 mask_dc, s->slice.x, s->slice.y, SRCAND);
2052 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2053 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2055 SelectObject (mask_dc, mask_orig_obj);
2056 DeleteDC (mask_dc);
2058 else
2060 SetTextColor (hdc, s->gc->foreground);
2061 SetBkColor (hdc, s->gc->background);
2063 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2064 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2066 /* When the image has a mask, we can expect that at
2067 least part of a mouse highlight or a block cursor will
2068 be visible. If the image doesn't have a mask, make
2069 a block cursor visible by drawing a rectangle around
2070 the image. I believe it's looking better if we do
2071 nothing here for mouse-face. */
2072 if (s->hl == DRAW_CURSOR)
2074 int r = s->img->relief;
2075 if (r < 0) r = -r;
2076 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2077 s->slice.width + r*2 - 1,
2078 s->slice.height + r*2 - 1);
2082 SelectObject (hdc, orig_brush);
2083 DeleteObject (fg_brush);
2084 SelectObject (compat_hdc, orig_obj);
2085 DeleteDC (compat_hdc);
2087 else
2088 w32_draw_rectangle (hdc, s->gc, x, y,
2089 s->slice.width - 1, s->slice.height - 1);
2091 SelectObject (hdc, orig_hdc_obj);
2092 DeleteDC (hdc);
2096 /* Draw part of the background of glyph string S. X, Y, W, and H
2097 give the rectangle to draw. */
2099 static void
2100 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2102 #if 0 /* TODO: stipple */
2103 if (s->stippled_p)
2105 /* Fill background with a stipple pattern. */
2106 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2107 XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), s->gc, x, y, w, h);
2108 XSetFillStyle (s->display, s->gc, FillSolid);
2110 else
2111 #endif
2112 x_clear_glyph_string_rect (s, x, y, w, h);
2116 /* Draw image glyph string S.
2118 s->y
2119 s->x +-------------------------
2120 | s->face->box
2122 | +-------------------------
2123 | | s->img->vmargin
2125 | | +-------------------
2126 | | | the image
2130 static void
2131 x_draw_image_glyph_string (struct glyph_string *s)
2133 int x, y;
2134 int box_line_hwidth = eabs (s->face->box_line_width);
2135 int box_line_vwidth = max (s->face->box_line_width, 0);
2136 int height, width;
2137 HBITMAP pixmap = 0;
2139 height = s->height;
2140 if (s->slice.y == 0)
2141 height -= box_line_vwidth;
2142 if (s->slice.y + s->slice.height >= s->img->height)
2143 height -= box_line_vwidth;
2145 /* Fill background with face under the image. Do it only if row is
2146 taller than image or if image has a clip mask to reduce
2147 flickering. */
2148 s->stippled_p = s->face->stipple != 0;
2149 if (height > s->slice.height
2150 || s->img->hmargin
2151 || s->img->vmargin
2152 || s->img->mask
2153 || s->img->pixmap == 0
2154 || s->width != s->background_width)
2156 width = s->background_width;
2157 x = s->x;
2158 if (s->first_glyph->left_box_line_p
2159 && s->slice.x == 0)
2161 x += box_line_hwidth;
2162 width -= box_line_hwidth;
2165 y = s->y;
2166 if (s->slice.y == 0)
2167 y += box_line_vwidth;
2169 #if 0 /* TODO: figure out if we need to do this on Windows. */
2170 if (s->img->mask)
2172 /* Create a pixmap as large as the glyph string. Fill it
2173 with the background color. Copy the image to it, using
2174 its mask. Copy the temporary pixmap to the display. */
2175 Screen *screen = FRAME_X_SCREEN (s->f);
2176 int depth = DefaultDepthOfScreen (screen);
2178 /* Create a pixmap as large as the glyph string. */
2179 pixmap = XCreatePixmap (s->display, FRAME_W32_WINDOW (s->f),
2180 s->background_width,
2181 s->height, depth);
2183 /* Don't clip in the following because we're working on the
2184 pixmap. */
2185 XSetClipMask (s->display, s->gc, None);
2187 /* Fill the pixmap with the background color/stipple. */
2188 if (s->stippled_p)
2190 /* Fill background with a stipple pattern. */
2191 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2192 XFillRectangle (s->display, pixmap, s->gc,
2193 0, 0, s->background_width, s->height);
2194 XSetFillStyle (s->display, s->gc, FillSolid);
2196 else
2198 XGCValues xgcv;
2199 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2200 &xgcv);
2201 XSetForeground (s->display, s->gc, xgcv.background);
2202 XFillRectangle (s->display, pixmap, s->gc,
2203 0, 0, s->background_width, s->height);
2204 XSetForeground (s->display, s->gc, xgcv.foreground);
2207 else
2208 #endif
2209 x_draw_glyph_string_bg_rect (s, x, y, width, height);
2211 s->background_filled_p = true;
2214 /* Draw the foreground. */
2215 if (pixmap != 0)
2217 w32_draw_image_foreground_1 (s, pixmap);
2218 x_set_glyph_string_clipping (s);
2220 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2221 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2222 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2223 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2225 SetTextColor (s->hdc, s->gc->foreground);
2226 SetBkColor (s->hdc, s->gc->background);
2227 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2228 compat_hdc, 0, 0, SRCCOPY);
2230 SelectObject (s->hdc, orig_brush);
2231 DeleteObject (fg_brush);
2232 SelectObject (compat_hdc, orig_obj);
2233 DeleteDC (compat_hdc);
2235 DeleteObject (pixmap);
2236 pixmap = 0;
2238 else
2239 x_draw_image_foreground (s);
2241 /* If we must draw a relief around the image, do it. */
2242 if (s->img->relief
2243 || s->hl == DRAW_IMAGE_RAISED
2244 || s->hl == DRAW_IMAGE_SUNKEN)
2245 x_draw_image_relief (s);
2249 /* Draw stretch glyph string S. */
2251 static void
2252 x_draw_stretch_glyph_string (struct glyph_string *s)
2254 eassert (s->first_glyph->type == STRETCH_GLYPH);
2256 if (s->hl == DRAW_CURSOR
2257 && !x_stretch_cursor_p)
2259 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2260 wide as the stretch glyph. */
2261 int width, background_width = s->background_width;
2262 int x = s->x;
2264 if (!s->row->reversed_p)
2266 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2268 if (x < left_x)
2270 background_width -= left_x - x;
2271 x = left_x;
2274 else
2276 /* In R2L rows, draw the cursor on the right edge of the
2277 stretch glyph. */
2278 int right_x = window_box_right (s->w, TEXT_AREA);
2280 if (x + background_width > right_x)
2281 background_width -= x - right_x;
2282 x += background_width;
2284 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2285 if (s->row->reversed_p)
2286 x -= width;
2288 /* Draw cursor. */
2289 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2291 /* Clear rest using the GC of the original non-cursor face. */
2292 if (width < background_width)
2294 XGCValues *gc = s->face->gc;
2295 int y = s->y;
2296 int w = background_width - width, h = s->height;
2297 RECT r;
2298 HDC hdc = s->hdc;
2300 if (!s->row->reversed_p)
2301 x += width;
2302 else
2303 x = s->x;
2304 if (s->row->mouse_face_p
2305 && cursor_in_mouse_face_p (s->w))
2307 x_set_mouse_face_gc (s);
2308 gc = s->gc;
2310 else
2311 gc = s->face->gc;
2313 get_glyph_string_clip_rect (s, &r);
2314 w32_set_clip_rectangle (hdc, &r);
2316 #if 0 /* TODO: stipple */
2317 if (s->face->stipple)
2319 /* Fill background with a stipple pattern. */
2320 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2321 XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), gc, x, y, w, h);
2322 XSetFillStyle (s->display, gc, FillSolid);
2324 else
2325 #endif
2327 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2331 else if (!s->background_filled_p)
2333 int background_width = s->background_width;
2334 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2336 /* Don't draw into left margin, fringe or scrollbar area
2337 except for header line and mode line. */
2338 if (x < left_x && !s->row->mode_line_p)
2340 background_width -= left_x - x;
2341 x = left_x;
2343 if (background_width > 0)
2344 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2347 s->background_filled_p = true;
2351 /* Draw glyph string S. */
2353 static void
2354 x_draw_glyph_string (struct glyph_string *s)
2356 bool relief_drawn_p = 0;
2358 /* If S draws into the background of its successor, draw the
2359 background of the successor first so that S can draw into it.
2360 This makes S->next use XDrawString instead of XDrawImageString. */
2361 if (s->next && s->right_overhang && !s->for_overlaps)
2363 int width;
2364 struct glyph_string *next;
2365 for (width = 0, next = s->next;
2366 next && width < s->right_overhang;
2367 width += next->width, next = next->next)
2368 if (next->first_glyph->type != IMAGE_GLYPH)
2370 x_set_glyph_string_gc (next);
2371 x_set_glyph_string_clipping (next);
2372 if (next->first_glyph->type == STRETCH_GLYPH)
2373 x_draw_stretch_glyph_string (next);
2374 else
2375 x_draw_glyph_string_background (next, true);
2376 next->num_clips = 0;
2380 /* Set up S->gc, set clipping and draw S. */
2381 x_set_glyph_string_gc (s);
2383 /* Draw relief (if any) in advance for char/composition so that the
2384 glyph string can be drawn over it. */
2385 if (!s->for_overlaps
2386 && s->face->box != FACE_NO_BOX
2387 && (s->first_glyph->type == CHAR_GLYPH
2388 || s->first_glyph->type == COMPOSITE_GLYPH))
2391 x_set_glyph_string_clipping (s);
2392 x_draw_glyph_string_background (s, true);
2393 x_draw_glyph_string_box (s);
2394 x_set_glyph_string_clipping (s);
2395 relief_drawn_p = 1;
2397 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2398 && !s->clip_tail
2399 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2400 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2401 /* We must clip just this glyph. left_overhang part has already
2402 drawn when s->prev was drawn, and right_overhang part will be
2403 drawn later when s->next is drawn. */
2404 x_set_glyph_string_clipping_exactly (s, s);
2405 else
2406 x_set_glyph_string_clipping (s);
2408 switch (s->first_glyph->type)
2410 case IMAGE_GLYPH:
2411 x_draw_image_glyph_string (s);
2412 break;
2414 case STRETCH_GLYPH:
2415 x_draw_stretch_glyph_string (s);
2416 break;
2418 case CHAR_GLYPH:
2419 if (s->for_overlaps)
2420 s->background_filled_p = true;
2421 else
2422 x_draw_glyph_string_background (s, false);
2423 x_draw_glyph_string_foreground (s);
2424 break;
2426 case COMPOSITE_GLYPH:
2427 if (s->for_overlaps || (s->cmp_from > 0
2428 && ! s->first_glyph->u.cmp.automatic))
2429 s->background_filled_p = true;
2430 else
2431 x_draw_glyph_string_background (s, true);
2432 x_draw_composite_glyph_string_foreground (s);
2433 break;
2435 case GLYPHLESS_GLYPH:
2436 if (s->for_overlaps)
2437 s->background_filled_p = true;
2438 else
2439 x_draw_glyph_string_background (s, false);
2440 x_draw_glyphless_glyph_string_foreground (s);
2441 break;
2443 default:
2444 emacs_abort ();
2447 if (!s->for_overlaps)
2449 /* Draw underline. */
2450 if (s->face->underline_p)
2452 if (s->face->underline_type == FACE_UNDER_WAVE)
2454 COLORREF color;
2456 if (s->face->underline_defaulted_p)
2457 color = s->gc->foreground;
2458 else
2459 color = s->face->underline_color;
2461 w32_draw_underwave (s, color);
2463 else if (s->face->underline_type == FACE_UNDER_LINE)
2465 unsigned long thickness, position;
2466 int y;
2468 if (s->prev && s->prev->face->underline_p
2469 && s->prev->face->underline_type == FACE_UNDER_LINE)
2471 /* We use the same underline style as the previous one. */
2472 thickness = s->prev->underline_thickness;
2473 position = s->prev->underline_position;
2475 else
2477 struct font *font = font_for_underline_metrics (s);
2478 unsigned long minimum_offset;
2479 BOOL underline_at_descent_line;
2480 BOOL use_underline_position_properties;
2481 Lisp_Object val
2482 = buffer_local_value (Qunderline_minimum_offset,
2483 s->w->contents);
2484 if (INTEGERP (val))
2485 minimum_offset = XFASTINT (val);
2486 else
2487 minimum_offset = 1;
2488 val = buffer_local_value (Qx_underline_at_descent_line,
2489 s->w->contents);
2490 underline_at_descent_line
2491 = !(NILP (val) || EQ (val, Qunbound));
2493 = buffer_local_value (Qx_use_underline_position_properties,
2494 s->w->contents);
2495 use_underline_position_properties
2496 = !(NILP (val) || EQ (val, Qunbound));
2498 /* Get the underline thickness. Default is 1 pixel. */
2499 if (font && font->underline_thickness > 0)
2500 thickness = font->underline_thickness;
2501 else
2502 thickness = 1;
2503 if (underline_at_descent_line
2504 || !font)
2505 position = (s->height - thickness) - (s->ybase - s->y);
2506 else
2508 /* Get the underline position. This is the
2509 recommended vertical offset in pixels from
2510 the baseline to the top of the underline.
2511 This is a signed value according to the
2512 specs, and its default is
2514 ROUND ((maximum_descent) / 2), with
2515 ROUND (x) = floor (x + 0.5) */
2517 if (use_underline_position_properties
2518 && font->underline_position >= 0)
2519 position = font->underline_position;
2520 else
2521 position = (font->descent + 1) / 2;
2523 position = max (position, minimum_offset);
2525 /* Check the sanity of thickness and position. We should
2526 avoid drawing underline out of the current line area. */
2527 if (s->y + s->height <= s->ybase + position)
2528 position = (s->height - 1) - (s->ybase - s->y);
2529 if (s->y + s->height < s->ybase + position + thickness)
2530 thickness = (s->y + s->height) - (s->ybase + position);
2531 s->underline_thickness = thickness;
2532 s->underline_position = position;
2533 y = s->ybase + position;
2534 if (s->face->underline_defaulted_p)
2536 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2537 y, s->width, 1);
2539 else
2541 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2542 y, s->width, 1);
2546 /* Draw overline. */
2547 if (s->face->overline_p)
2549 unsigned long dy = 0, h = 1;
2551 if (s->face->overline_color_defaulted_p)
2553 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2554 s->y + dy, s->width, h);
2556 else
2558 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2559 s->y + dy, s->width, h);
2563 /* Draw strike-through. */
2564 if (s->face->strike_through_p
2565 && !FONT_TEXTMETRIC (s->font).tmStruckOut)
2567 /* Y-coordinate and height of the glyph string's first
2568 glyph. We cannot use s->y and s->height because those
2569 could be larger if there are taller display elements
2570 (e.g., characters displayed with a larger font) in the
2571 same glyph row. */
2572 int glyph_y = s->ybase - s->first_glyph->ascent;
2573 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
2574 /* Strike-through width and offset from the glyph string's
2575 top edge. */
2576 unsigned long h = 1;
2577 unsigned long dy = (glyph_height - h) / 2;
2579 if (s->face->strike_through_color_defaulted_p)
2581 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2582 glyph_y + dy, s->width, h);
2584 else
2586 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
2587 glyph_y + dy, s->width, h);
2591 /* Draw relief if not yet drawn. */
2592 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2593 x_draw_glyph_string_box (s);
2595 if (s->prev)
2597 struct glyph_string *prev;
2599 for (prev = s->prev; prev; prev = prev->prev)
2600 if (prev->hl != s->hl
2601 && prev->x + prev->width + prev->right_overhang > s->x)
2603 /* As prev was drawn while clipped to its own area, we
2604 must draw the right_overhang part using s->hl now. */
2605 enum draw_glyphs_face save = prev->hl;
2607 prev->hl = s->hl;
2608 x_set_glyph_string_gc (prev);
2609 x_set_glyph_string_clipping_exactly (s, prev);
2610 if (prev->first_glyph->type == CHAR_GLYPH)
2611 x_draw_glyph_string_foreground (prev);
2612 else
2613 x_draw_composite_glyph_string_foreground (prev);
2614 w32_set_clip_rectangle (prev->hdc, NULL);
2615 prev->hl = save;
2616 prev->num_clips = 0;
2620 if (s->next)
2622 struct glyph_string *next;
2624 for (next = s->next; next; next = next->next)
2625 if (next->hl != s->hl
2626 && next->x - next->left_overhang < s->x + s->width)
2628 /* As next will be drawn while clipped to its own area,
2629 we must draw the left_overhang part using s->hl now. */
2630 enum draw_glyphs_face save = next->hl;
2632 next->hl = s->hl;
2633 x_set_glyph_string_gc (next);
2634 x_set_glyph_string_clipping_exactly (s, next);
2635 if (next->first_glyph->type == CHAR_GLYPH)
2636 x_draw_glyph_string_foreground (next);
2637 else
2638 x_draw_composite_glyph_string_foreground (next);
2639 w32_set_clip_rectangle (next->hdc, NULL);
2640 next->hl = save;
2641 next->num_clips = 0;
2642 next->clip_head = s->next;
2647 /* Reset clipping. */
2648 w32_set_clip_rectangle (s->hdc, NULL);
2649 s->num_clips = 0;
2653 /* Shift display to make room for inserted glyphs. */
2655 static void
2656 w32_shift_glyphs_for_insert (struct frame *f, int x, int y,
2657 int width, int height, int shift_by)
2659 HDC hdc;
2661 hdc = get_frame_dc (f);
2662 BitBlt (hdc, x + shift_by, y, width, height,
2663 hdc, x, y, SRCCOPY);
2665 release_frame_dc (f, hdc);
2669 /* Delete N glyphs at the nominal cursor position. Not implemented
2670 for X frames. */
2672 static void
2673 x_delete_glyphs (struct frame *f, register int n)
2675 if (! FRAME_W32_P (f))
2676 return;
2678 emacs_abort ();
2682 /* Clear entire frame. */
2684 static void
2685 x_clear_frame (struct frame *f)
2687 if (! FRAME_W32_P (f))
2688 return;
2690 /* Clearing the frame will erase any cursor, so mark them all as no
2691 longer visible. */
2692 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2694 block_input ();
2696 w32_clear_window (f);
2698 /* We have to clear the scroll bars, too. If we have changed
2699 colors or something like that, then they should be notified. */
2700 x_scroll_bar_clear (f);
2702 unblock_input ();
2706 /* Make audible bell. */
2708 static void
2709 w32_ring_bell (struct frame *f)
2711 block_input ();
2713 if (FRAME_W32_P (f) && visible_bell)
2715 int i;
2716 HWND hwnd = FRAME_W32_WINDOW (f);
2718 for (i = 0; i < 5; i++)
2720 FlashWindow (hwnd, TRUE);
2721 Sleep (10);
2723 FlashWindow (hwnd, FALSE);
2725 else
2726 w32_sys_ring_bell (f);
2728 unblock_input ();
2731 /***********************************************************************
2732 Line Dance
2733 ***********************************************************************/
2735 /* Perform an insert-lines or delete-lines operation, inserting N
2736 lines or deleting -N lines at vertical position VPOS. */
2738 static void
2739 x_ins_del_lines (struct frame *f, int vpos, int n)
2741 if (! FRAME_W32_P (f))
2742 return;
2744 emacs_abort ();
2748 /* Scroll part of the display as described by RUN. */
2750 static void
2751 x_scroll_run (struct window *w, struct run *run)
2753 struct frame *f = XFRAME (w->frame);
2754 int x, y, width, height, from_y, to_y, bottom_y;
2755 HWND hwnd = FRAME_W32_WINDOW (f);
2756 HRGN expect_dirty;
2758 /* Get frame-relative bounding box of the text display area of W,
2759 without mode lines. Include in this box the left and right
2760 fringes of W. */
2761 window_box (w, ANY_AREA, &x, &y, &width, &height);
2763 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2764 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2765 bottom_y = y + height;
2767 if (to_y < from_y)
2769 /* Scrolling up. Make sure we don't copy part of the mode
2770 line at the bottom. */
2771 if (from_y + run->height > bottom_y)
2772 height = bottom_y - from_y;
2773 else
2774 height = run->height;
2775 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2777 else
2779 /* Scrolling down. Make sure we don't copy over the mode line.
2780 at the bottom. */
2781 if (to_y + run->height > bottom_y)
2782 height = bottom_y - to_y;
2783 else
2784 height = run->height;
2785 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2788 block_input ();
2790 /* Cursor off. Will be switched on again in x_update_window_end. */
2791 x_clear_cursor (w);
2794 RECT from;
2795 RECT to;
2796 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2797 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2799 from.left = to.left = x;
2800 from.right = to.right = x + width;
2801 from.top = from_y;
2802 from.bottom = from_y + height;
2803 to.top = y;
2804 to.bottom = bottom_y;
2806 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2807 NULL, SW_INVALIDATE);
2809 /* Combine this with what we expect to be dirty. This covers the
2810 case where not all of the region we expect is actually dirty. */
2811 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2813 /* If the dirty region is not what we expected, redraw the entire frame. */
2814 if (!EqualRgn (combined, expect_dirty))
2815 SET_FRAME_GARBAGED (f);
2817 DeleteObject (dirty);
2818 DeleteObject (combined);
2821 unblock_input ();
2822 DeleteObject (expect_dirty);
2827 /***********************************************************************
2828 Exposure Events
2829 ***********************************************************************/
2831 static void
2832 frame_highlight (struct frame *f)
2834 x_update_cursor (f, 1);
2835 x_set_frame_alpha (f);
2838 static void
2839 frame_unhighlight (struct frame *f)
2841 x_update_cursor (f, 1);
2842 x_set_frame_alpha (f);
2845 /* The focus has changed. Update the frames as necessary to reflect
2846 the new situation. Note that we can't change the selected frame
2847 here, because the Lisp code we are interrupting might become confused.
2848 Each event gets marked with the frame in which it occurred, so the
2849 Lisp code can tell when the switch took place by examining the events. */
2851 static void
2852 x_new_focus_frame (struct w32_display_info *dpyinfo, struct frame *frame)
2854 struct frame *old_focus = dpyinfo->w32_focus_frame;
2856 if (frame != dpyinfo->w32_focus_frame)
2858 /* Set this before calling other routines, so that they see
2859 the correct value of w32_focus_frame. */
2860 dpyinfo->w32_focus_frame = frame;
2862 if (old_focus && old_focus->auto_lower)
2863 x_lower_frame (old_focus);
2865 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2866 dpyinfo->w32_pending_autoraise_frame = dpyinfo->w32_focus_frame;
2867 else
2868 dpyinfo->w32_pending_autoraise_frame = NULL;
2871 x_frame_rehighlight (dpyinfo);
2875 /* Handle FocusIn and FocusOut state changes for FRAME.
2876 If FRAME has focus and there exists more than one frame, puts
2877 a FOCUS_IN_EVENT into *BUFP. */
2879 static void
2880 x_focus_changed (int type, int state, struct w32_display_info *dpyinfo,
2881 struct frame *frame, struct input_event *bufp)
2883 if (type == WM_SETFOCUS)
2885 if (dpyinfo->w32_focus_event_frame != frame)
2887 x_new_focus_frame (dpyinfo, frame);
2888 dpyinfo->w32_focus_event_frame = frame;
2890 /* Don't stop displaying the initial startup message
2891 for a switch-frame event we don't need. */
2892 if (NILP (Vterminal_frame)
2893 && CONSP (Vframe_list)
2894 && !NILP (XCDR (Vframe_list)))
2896 bufp->arg = Qt;
2898 else
2900 bufp->arg = Qnil;
2903 bufp->kind = FOCUS_IN_EVENT;
2904 XSETFRAME (bufp->frame_or_window, frame);
2907 frame->output_data.x->focus_state |= state;
2909 /* TODO: IME focus? */
2911 else if (type == WM_KILLFOCUS)
2913 frame->output_data.x->focus_state &= ~state;
2915 if (dpyinfo->w32_focus_event_frame == frame)
2917 dpyinfo->w32_focus_event_frame = 0;
2918 x_new_focus_frame (dpyinfo, 0);
2920 bufp->kind = FOCUS_OUT_EVENT;
2921 XSETFRAME (bufp->frame_or_window, frame);
2924 /* TODO: IME focus? */
2929 /* The focus may have changed. Figure out if it is a real focus change,
2930 by checking both FocusIn/Out and Enter/LeaveNotify events.
2932 Returns FOCUS_IN_EVENT event in *BUFP. */
2934 static void
2935 w32_detect_focus_change (struct w32_display_info *dpyinfo, W32Msg *event,
2936 struct input_event *bufp)
2938 struct frame *frame;
2940 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2941 if (! frame)
2942 return;
2944 /* On w32, this is only called from focus events, so no switch needed. */
2945 x_focus_changed (event->msg.message,
2946 (event->msg.message == WM_KILLFOCUS ?
2947 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2948 dpyinfo, frame, bufp);
2952 #if 0 /* unused */
2953 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2955 static void
2956 x_mouse_leave (struct w32_display_info *dpyinfo)
2958 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2960 #endif
2962 /* The focus has changed, or we have redirected a frame's focus to
2963 another frame (this happens when a frame uses a surrogate
2964 mini-buffer frame). Shift the highlight as appropriate.
2966 The FRAME argument doesn't necessarily have anything to do with which
2967 frame is being highlighted or un-highlighted; we only use it to find
2968 the appropriate X display info. */
2970 static void
2971 w32_frame_rehighlight (struct frame *frame)
2973 if (! FRAME_W32_P (frame))
2974 return;
2975 x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
2978 static void
2979 x_frame_rehighlight (struct w32_display_info *dpyinfo)
2981 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2983 if (dpyinfo->w32_focus_frame)
2985 dpyinfo->x_highlight_frame
2986 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2987 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2988 : dpyinfo->w32_focus_frame);
2989 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2991 fset_focus_frame (dpyinfo->w32_focus_frame, Qnil);
2992 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2995 else
2996 dpyinfo->x_highlight_frame = 0;
2998 if (dpyinfo->x_highlight_frame != old_highlight)
3000 if (old_highlight)
3001 frame_unhighlight (old_highlight);
3002 if (dpyinfo->x_highlight_frame)
3003 frame_highlight (dpyinfo->x_highlight_frame);
3007 /* Keyboard processing - modifier keys, etc. */
3009 /* Convert a keysym to its name. */
3011 char *
3012 x_get_keysym_name (int keysym)
3014 /* Make static so we can always return it */
3015 static char value[100];
3017 block_input ();
3018 GetKeyNameText (keysym, value, 100);
3019 unblock_input ();
3021 return value;
3024 static int
3025 codepage_for_locale (LCID locale)
3027 char cp[20];
3029 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
3030 return atoi (cp);
3031 else
3032 return CP_ACP;
3036 /* Mouse clicks and mouse movement. Rah. */
3038 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3039 the state in PUP. XBUTTON provides extra information for extended mouse
3040 button messages. Returns FALSE if unable to parse the message. */
3041 BOOL
3042 parse_button (int message, int xbutton, int * pbutton, int * pup)
3044 int button = 0;
3045 int up = 0;
3047 switch (message)
3049 case WM_LBUTTONDOWN:
3050 button = 0;
3051 up = 0;
3052 break;
3053 case WM_LBUTTONUP:
3054 button = 0;
3055 up = 1;
3056 break;
3057 case WM_MBUTTONDOWN:
3058 if (NILP (Vw32_swap_mouse_buttons))
3059 button = 1;
3060 else
3061 button = 2;
3062 up = 0;
3063 break;
3064 case WM_MBUTTONUP:
3065 if (NILP (Vw32_swap_mouse_buttons))
3066 button = 1;
3067 else
3068 button = 2;
3069 up = 1;
3070 break;
3071 case WM_RBUTTONDOWN:
3072 if (NILP (Vw32_swap_mouse_buttons))
3073 button = 2;
3074 else
3075 button = 1;
3076 up = 0;
3077 break;
3078 case WM_RBUTTONUP:
3079 if (NILP (Vw32_swap_mouse_buttons))
3080 button = 2;
3081 else
3082 button = 1;
3083 up = 1;
3084 break;
3085 case WM_XBUTTONDOWN:
3086 button = xbutton + 2;
3087 up = 0;
3088 break;
3089 case WM_XBUTTONUP:
3090 button = xbutton + 2;
3091 up = 1;
3092 break;
3093 default:
3094 return (FALSE);
3097 if (pup) *pup = up;
3098 if (pbutton) *pbutton = button;
3100 return (TRUE);
3104 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3106 If the event is a button press, then note that we have grabbed
3107 the mouse. */
3109 static Lisp_Object
3110 construct_mouse_click (struct input_event *result, W32Msg *msg, struct frame *f)
3112 int button = 0;
3113 int up = 0;
3115 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3116 &button, &up);
3118 /* Make the event type NO_EVENT; we'll change that when we decide
3119 otherwise. */
3120 result->kind = MOUSE_CLICK_EVENT;
3121 result->code = button;
3122 result->timestamp = msg->msg.time;
3123 result->modifiers = (msg->dwModifiers
3124 | (up
3125 ? up_modifier
3126 : down_modifier));
3128 XSETINT (result->x, LOWORD (msg->msg.lParam));
3129 XSETINT (result->y, HIWORD (msg->msg.lParam));
3130 XSETFRAME (result->frame_or_window, f);
3131 result->arg = Qnil;
3132 return Qnil;
3135 static Lisp_Object
3136 construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
3138 POINT p;
3139 int delta;
3141 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3142 : WHEEL_EVENT;
3143 result->code = 0;
3144 result->timestamp = msg->msg.time;
3146 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3147 forward, away from the user (up); a negative value indicates that
3148 the wheel was rotated backward, toward the user (down). */
3149 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3151 /* The up and down modifiers indicate if the wheel was rotated up or
3152 down based on WHEEL_DELTA value. */
3153 result->modifiers = (msg->dwModifiers
3154 | ((delta < 0 ) ? down_modifier : up_modifier));
3156 /* With multiple monitors, we can legitimately get negative
3157 coordinates, so cast to short to interpret them correctly. */
3158 p.x = (short) LOWORD (msg->msg.lParam);
3159 p.y = (short) HIWORD (msg->msg.lParam);
3160 /* For the case that F's w32 window is not msg->msg.hwnd. */
3161 ScreenToClient (FRAME_W32_WINDOW (f), &p);
3162 XSETINT (result->x, p.x);
3163 XSETINT (result->y, p.y);
3164 XSETFRAME (result->frame_or_window, f);
3165 result->arg = Qnil;
3166 return Qnil;
3169 static Lisp_Object
3170 construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
3172 Lisp_Object files;
3173 Lisp_Object frame;
3174 HDROP hdrop;
3175 POINT p;
3176 WORD num_files;
3177 wchar_t name_w[MAX_PATH];
3178 #ifdef NTGUI_UNICODE
3179 const int use_unicode = 1;
3180 #else
3181 int use_unicode = w32_unicode_filenames;
3182 char name_a[MAX_PATH];
3183 char file[MAX_UTF8_PATH];
3184 #endif
3185 int i;
3187 result->kind = DRAG_N_DROP_EVENT;
3188 result->code = 0;
3189 result->timestamp = msg->msg.time;
3190 result->modifiers = msg->dwModifiers;
3192 hdrop = (HDROP) msg->msg.wParam;
3193 DragQueryPoint (hdrop, &p);
3195 #if 0
3196 p.x = LOWORD (msg->msg.lParam);
3197 p.y = HIWORD (msg->msg.lParam);
3198 ScreenToClient (msg->msg.hwnd, &p);
3199 #endif
3201 XSETINT (result->x, p.x);
3202 XSETINT (result->y, p.y);
3204 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3205 files = Qnil;
3207 for (i = 0; i < num_files; i++)
3209 if (use_unicode)
3211 eassert (DragQueryFileW (hdrop, i, NULL, 0) < MAX_PATH);
3212 /* If DragQueryFile returns zero, it failed to fetch a file
3213 name. */
3214 if (DragQueryFileW (hdrop, i, name_w, MAX_PATH) == 0)
3215 continue;
3216 #ifdef NTGUI_UNICODE
3217 files = Fcons (from_unicode_buffer (name_w), files);
3218 #else
3219 filename_from_utf16 (name_w, file);
3220 files = Fcons (DECODE_FILE (build_unibyte_string (file)), files);
3221 #endif /* NTGUI_UNICODE */
3223 #ifndef NTGUI_UNICODE
3224 else
3226 eassert (DragQueryFileA (hdrop, i, NULL, 0) < MAX_PATH);
3227 if (DragQueryFileA (hdrop, i, name_a, MAX_PATH) == 0)
3228 continue;
3229 filename_from_ansi (name_a, file);
3230 files = Fcons (DECODE_FILE (build_unibyte_string (file)), files);
3232 #endif
3235 DragFinish (hdrop);
3237 XSETFRAME (frame, f);
3238 result->frame_or_window = frame;
3239 result->arg = files;
3240 return Qnil;
3244 #if HAVE_W32NOTIFY
3246 /* File event notifications (see w32notify.c). */
3248 Lisp_Object
3249 lispy_file_action (DWORD action)
3251 static char unknown_fmt[] = "unknown-action(%d)";
3252 Lisp_Object retval;
3254 switch (action)
3256 case FILE_ACTION_ADDED:
3257 retval = Qadded;
3258 break;
3259 case FILE_ACTION_REMOVED:
3260 retval = Qremoved;
3261 break;
3262 case FILE_ACTION_MODIFIED:
3263 retval = Qmodified;
3264 break;
3265 case FILE_ACTION_RENAMED_OLD_NAME:
3266 retval = Qrenamed_from;
3267 break;
3268 case FILE_ACTION_RENAMED_NEW_NAME:
3269 retval = Qrenamed_to;
3270 break;
3271 default:
3273 char buf[sizeof(unknown_fmt) - 1 + INT_STRLEN_BOUND (DWORD)];
3275 sprintf (buf, unknown_fmt, action);
3276 retval = intern (buf);
3278 break;
3281 return retval;
3284 #ifdef WINDOWSNT
3285 /* Put file notifications into the Emacs input event queue. This
3286 function runs when the WM_EMACS_FILENOTIFY message arrives from a
3287 watcher thread. */
3288 static void
3289 queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
3290 int *evcount)
3292 struct notifications_set *ns = NULL;
3293 Lisp_Object frame;
3294 int done = 0;
3296 /* We cannot process notification before Emacs is fully initialized,
3297 since we need the UTF-16LE coding-system to be set up. */
3298 if (!initialized)
3299 return;
3301 XSETFRAME (frame, f);
3303 while (!done)
3305 ns = NULL;
3307 /* Find out if there is a record available in the linked list of
3308 notifications sets. If so, unlink the set from the linked
3309 list. Use critical section. */
3310 enter_crit ();
3311 if (notifications_set_head->next != notifications_set_head)
3313 ns = notifications_set_head->next;
3314 ns->prev->next = ns->next;
3315 ns->next->prev = ns->prev;
3317 else
3318 done = 1;
3319 leave_crit();
3321 if (ns)
3323 BYTE *p = ns->notifications;
3324 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
3325 const DWORD min_size
3326 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
3327 DWORD info_size = ns->size;
3328 Lisp_Object cs = Qutf_16le;
3329 Lisp_Object obj = w32_get_watch_object (ns->desc);
3331 /* notifications size could be zero when the buffer of
3332 notifications overflowed on the OS level, or when the
3333 directory being watched was itself deleted. Do nothing in
3334 that case. */
3335 if (info_size
3336 && !NILP (obj) && CONSP (obj))
3338 Lisp_Object callback = XCDR (obj);
3340 while (info_size >= min_size)
3342 Lisp_Object utf_16_fn
3343 = make_unibyte_string ((char *)fni->FileName,
3344 fni->FileNameLength);
3345 /* Note: mule-conf is preloaded, so utf-16le must
3346 already be defined at this point. */
3347 Lisp_Object fname
3348 = code_convert_string_norecord (utf_16_fn, cs, 0);
3349 Lisp_Object action = lispy_file_action (fni->Action);
3351 event->kind = FILE_NOTIFY_EVENT;
3352 event->timestamp = msg->msg.time;
3353 event->modifiers = 0;
3354 event->frame_or_window = callback;
3355 event->arg = list3 (make_pointer_integer (ns->desc),
3356 action, fname);
3357 kbd_buffer_store_event (event);
3358 (*evcount)++;
3359 if (!fni->NextEntryOffset)
3360 break;
3361 p += fni->NextEntryOffset;
3362 fni = (PFILE_NOTIFY_INFORMATION)p;
3363 info_size -= fni->NextEntryOffset;
3366 /* Free this notifications set. */
3367 xfree (ns->notifications);
3368 xfree (ns);
3371 /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */
3372 event->kind = NO_EVENT;
3374 #endif /* WINDOWSNT */
3375 #endif /* HAVE_W32NOTIFY */
3378 /* Function to report a mouse movement to the mainstream Emacs code.
3379 The input handler calls this.
3381 We have received a mouse movement event, which is given in *event.
3382 If the mouse is over a different glyph than it was last time, tell
3383 the mainstream emacs code by setting mouse_moved. If not, ask for
3384 another motion event, so we can check again the next time it moves. */
3386 static int
3387 note_mouse_movement (struct frame *frame, MSG *msg)
3389 struct w32_display_info *dpyinfo;
3390 int mouse_x = LOWORD (msg->lParam);
3391 int mouse_y = HIWORD (msg->lParam);
3392 RECT *r;
3394 if (!FRAME_X_OUTPUT (frame))
3395 return 0;
3397 dpyinfo = FRAME_DISPLAY_INFO (frame);
3398 dpyinfo->last_mouse_movement_time = msg->time;
3399 dpyinfo->last_mouse_motion_frame = frame;
3400 dpyinfo->last_mouse_motion_x = mouse_x;
3401 dpyinfo->last_mouse_motion_y = mouse_y;
3403 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3405 frame->mouse_moved = true;
3406 dpyinfo->last_mouse_scroll_bar = NULL;
3407 note_mouse_highlight (frame, -1, -1);
3408 dpyinfo->last_mouse_glyph_frame = NULL;
3409 return 1;
3412 /* Has the mouse moved off the glyph it was on at the last sighting? */
3413 r = &dpyinfo->last_mouse_glyph;
3414 if (frame != dpyinfo->last_mouse_glyph_frame
3415 || mouse_x < r->left || mouse_x >= r->right
3416 || mouse_y < r->top || mouse_y >= r->bottom)
3418 frame->mouse_moved = true;
3419 dpyinfo->last_mouse_scroll_bar = NULL;
3420 note_mouse_highlight (frame, mouse_x, mouse_y);
3421 /* Remember the mouse position here, as w32_mouse_position only
3422 gets called when mouse tracking is enabled but we also need
3423 to keep track of the mouse for help_echo and highlighting at
3424 other times. */
3425 remember_mouse_glyph (frame, mouse_x, mouse_y, r);
3426 dpyinfo->last_mouse_glyph_frame = frame;
3427 return 1;
3430 return 0;
3434 /************************************************************************
3435 Mouse Face
3436 ************************************************************************/
3438 static struct scroll_bar *x_window_to_scroll_bar (Window, int);
3439 static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
3440 enum scroll_bar_part *,
3441 Lisp_Object *, Lisp_Object *,
3442 Time *);
3443 static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object *,
3444 enum scroll_bar_part *,
3445 Lisp_Object *, Lisp_Object *,
3446 Time *);
3447 static void
3448 w32_define_cursor (Window window, Cursor cursor)
3450 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3453 /* Return the current position of the mouse.
3454 *fp should be a frame which indicates which display to ask about.
3456 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3457 and *part to the frame, window, and scroll bar part that the mouse
3458 is over. Set *x and *y to the portion and whole of the mouse's
3459 position on the scroll bar.
3461 If the mouse movement started elsewhere, set *fp to the frame the
3462 mouse is on, *bar_window to nil, and *x and *y to the character cell
3463 the mouse is over.
3465 Set *time to the server time-stamp for the time at which the mouse
3466 was at this position.
3468 Don't store anything if we don't have a valid set of values to report.
3470 This clears the mouse_moved flag, so we can wait for the next mouse
3471 movement. */
3473 static void
3474 w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3475 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3476 Time *time)
3478 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
3480 block_input ();
3482 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
3484 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
3486 if (bar->horizontal)
3487 x_horizontal_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3488 else
3489 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3491 else
3493 POINT pt;
3494 Lisp_Object frame, tail;
3495 struct frame *f1 = NULL;
3497 /* Clear the mouse-moved flag for every frame on this display. */
3498 FOR_EACH_FRAME (tail, frame)
3499 XFRAME (frame)->mouse_moved = false;
3501 dpyinfo->last_mouse_scroll_bar = NULL;
3503 GetCursorPos (&pt);
3505 /* Now we have a position on the root; find the innermost window
3506 containing the pointer. */
3508 /* If mouse was grabbed on a frame, give coords for that
3509 frame even if the mouse is now outside it. Otherwise
3510 check for window under mouse on one of our frames. */
3511 if (x_mouse_grabbed (dpyinfo))
3512 f1 = dpyinfo->last_mouse_frame;
3513 else
3515 HWND wfp = WindowFromPoint (pt);
3517 if (wfp)
3519 f1 = x_any_window_to_frame (dpyinfo, wfp);
3520 if (f1)
3522 HWND cwfp = ChildWindowFromPoint (wfp, pt);
3524 if (cwfp)
3526 struct frame *f2 = x_any_window_to_frame (dpyinfo, cwfp);
3528 /* If a child window was found, make sure that its
3529 frame is a child frame (Bug#26615, maybe). */
3530 if (f2 && FRAME_PARENT_FRAME (f2))
3531 f1 = f2;
3537 /* If not, is it one of our scroll bars? */
3538 if (! f1)
3540 struct scroll_bar *bar
3541 = x_window_to_scroll_bar (WindowFromPoint (pt), 2);
3543 if (bar)
3544 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3547 if (f1 == 0 && insist > 0)
3548 f1 = SELECTED_FRAME ();
3550 if (f1)
3552 /* Ok, we found a frame. Store all the values.
3553 last_mouse_glyph is a rectangle used to reduce the
3554 generation of mouse events. To not miss any motion
3555 events, we must divide the frame into rectangles of the
3556 size of the smallest character that could be displayed
3557 on it, i.e. into the same rectangles that matrices on
3558 the frame are divided into. */
3560 dpyinfo = FRAME_DISPLAY_INFO (f1);
3561 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3562 remember_mouse_glyph (f1, pt.x, pt.y, &dpyinfo->last_mouse_glyph);
3563 dpyinfo->last_mouse_glyph_frame = f1;
3565 *bar_window = Qnil;
3566 *part = scroll_bar_above_handle;
3567 *fp = f1;
3568 XSETINT (*x, pt.x);
3569 XSETINT (*y, pt.y);
3570 *time = dpyinfo->last_mouse_movement_time;
3575 unblock_input ();
3579 /***********************************************************************
3580 Tool-bars
3581 ***********************************************************************/
3583 /* Handle mouse button event on the tool-bar of frame F, at
3584 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
3585 or ButtonRelease. */
3587 static void
3588 w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event)
3590 int x = XFASTINT (button_event->x);
3591 int y = XFASTINT (button_event->y);
3593 if (button_event->modifiers & down_modifier)
3594 handle_tool_bar_click (f, x, y, 1, 0);
3595 else
3596 handle_tool_bar_click (f, x, y, 0,
3597 button_event->modifiers & ~up_modifier);
3602 /***********************************************************************
3603 Scroll bars
3604 ***********************************************************************/
3606 /* Scroll bar support. */
3608 /* Given a window ID, find the struct scroll_bar which manages it
3609 vertically. This can be called in GC, so we have to make sure to
3610 strip off mark bits. */
3612 static struct scroll_bar *
3613 x_window_to_scroll_bar (Window window_id, int type)
3615 Lisp_Object tail, frame;
3617 FOR_EACH_FRAME (tail, frame)
3619 Lisp_Object bar, condemned;
3621 /* Scan this frame's scroll bar list for a scroll bar with the
3622 right window ID. */
3623 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3624 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3625 /* This trick allows us to search both the ordinary and
3626 condemned scroll bar lists with one loop. */
3627 ! NILP (bar) || (bar = condemned,
3628 condemned = Qnil,
3629 ! NILP (bar));
3630 bar = XSCROLL_BAR (bar)->next)
3631 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id
3632 && (type = 2
3633 || (type == 1 && XSCROLL_BAR (bar)->horizontal)
3634 || (type == 0 && !XSCROLL_BAR (bar)->horizontal)))
3635 return XSCROLL_BAR (bar);
3638 return 0;
3643 /* Set the thumb size and position of vertical scroll bar BAR. We are currently
3644 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3646 static void
3647 w32_set_scroll_bar_thumb (struct scroll_bar *bar,
3648 int portion, int position, int whole)
3650 Window w = SCROLL_BAR_W32_WINDOW (bar);
3651 /* We use the whole scroll-bar height in the calculations below, to
3652 avoid strange effects like scrolling backwards when just clicking
3653 on the handle (without moving it). */
3654 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height)
3655 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3656 int sb_page, sb_pos;
3657 BOOL draggingp = bar->dragging ? TRUE : FALSE;
3658 SCROLLINFO si;
3660 /* We used to change the nPage setting while dragging the handle,
3661 but that had very strange effects (such as scrolling backwards
3662 while dragging downwards).
3664 Now, we don't change the nPage setting while dragging unless we
3665 get near to the end of the buffer, in which case we often have to
3666 resize the handle to "go all the way". */
3668 if (draggingp)
3670 int near_bottom_p;
3671 block_input ();
3672 si.cbSize = sizeof (si);
3673 si.fMask = SIF_POS | SIF_PAGE;
3674 GetScrollInfo (w, SB_CTL, &si);
3675 near_bottom_p = si.nPos + si.nPage >= range;
3676 unblock_input ();
3677 if (!near_bottom_p)
3678 return;
3681 if (whole)
3683 /* Position scroll bar at rock bottom if the bottom of the
3684 buffer is visible. This avoids shrinking the thumb away
3685 to nothing if it is held at the bottom of the buffer. */
3686 if (position + portion >= whole && !draggingp)
3688 sb_page = range * (whole - position) / whole;
3689 sb_pos = range;
3691 else
3693 sb_pos = position * range / whole;
3694 sb_page = (min (portion, (whole - position)) * range) / whole;
3697 else
3699 sb_page = range;
3700 sb_pos = 0;
3703 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3705 block_input ();
3707 si.cbSize = sizeof (si);
3708 si.fMask = SIF_PAGE | SIF_POS;
3709 si.nPage = sb_page;
3710 si.nPos = sb_pos;
3712 SetScrollInfo (w, SB_CTL, &si, TRUE);
3714 unblock_input ();
3717 /* Set the thumb size and position of horizontal scroll bar BAR. We are currently
3718 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3720 static void
3721 w32_set_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
3722 int portion, int position, int whole)
3724 Window w = SCROLL_BAR_W32_WINDOW (bar);
3725 SCROLLINFO si;
3727 block_input ();
3729 si.cbSize = sizeof (si);
3730 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
3731 si.nMin = 0;
3732 si.nMax = whole;
3733 /* Allow nPage to be one larger than nPos so we don't allow the scrolling
3734 of an already fully visible buffer. */
3735 si.nPage = min (portion, si.nMax) + 1;
3736 si.nPos = min (position, si.nMax);
3737 SetScrollInfo (w, SB_CTL, &si, TRUE);
3739 unblock_input ();
3743 /************************************************************************
3744 Scroll bars, general
3745 ************************************************************************/
3747 static HWND
3748 my_create_vscrollbar (struct frame * f, struct scroll_bar * bar)
3750 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3751 WM_EMACS_CREATEVSCROLLBAR, (WPARAM) f,
3752 (LPARAM) bar);
3755 static HWND
3756 my_create_hscrollbar (struct frame * f, struct scroll_bar * bar)
3758 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3759 WM_EMACS_CREATEHSCROLLBAR, (WPARAM) f,
3760 (LPARAM) bar);
3763 /*#define ATTACH_THREADS*/
3765 static BOOL
3766 my_show_window (struct frame *f, HWND hwnd, int how)
3768 #ifndef ATTACH_THREADS
3769 return SendMessageTimeout (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3770 (WPARAM) hwnd, (LPARAM) how, 0, 6000, NULL);
3771 #else
3772 return ShowWindow (hwnd, how);
3773 #endif
3776 static void
3777 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3778 int x, int y, int cx, int cy, UINT flags)
3780 #ifndef ATTACH_THREADS
3781 WINDOWPOS pos;
3782 pos.hwndInsertAfter = hwndAfter;
3783 pos.x = x;
3784 pos.y = y;
3785 pos.cx = cx;
3786 pos.cy = cy;
3787 pos.flags = flags;
3788 SendMessageTimeout (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0,
3789 0, 6000, NULL);
3790 #else
3791 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3792 #endif
3795 #if 0
3796 static void
3797 my_set_focus (struct frame * f, HWND hwnd)
3799 SendMessageTimeout (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3800 (WPARAM) hwnd, 0, 0, 6000, NULL);
3802 #endif
3804 static void
3805 my_set_foreground_window (HWND hwnd)
3807 SendMessageTimeout (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0,
3808 0, 6000, NULL);
3812 static void
3813 my_destroy_window (struct frame * f, HWND hwnd)
3815 SendMessageTimeout (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3816 (WPARAM) hwnd, 0, 0, 6000, NULL);
3819 static void
3820 my_bring_window_to_top (HWND hwnd)
3822 SendMessageTimeout (hwnd, WM_EMACS_BRINGTOTOP, (WPARAM) hwnd, 0,
3823 0, 6000, NULL);
3826 /* Create a scroll bar and return the scroll bar vector for it. W is
3827 the Emacs window on which to create the scroll bar. TOP, LEFT,
3828 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
3829 scroll bar. */
3831 static struct scroll_bar *
3832 x_scroll_bar_create (struct window *w, int left, int top, int width, int height, bool horizontal)
3834 struct frame *f = XFRAME (WINDOW_FRAME (w));
3835 HWND hwnd;
3836 SCROLLINFO si;
3837 struct scroll_bar *bar
3838 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, top, PVEC_OTHER);
3839 Lisp_Object barobj;
3841 block_input ();
3843 XSETWINDOW (bar->window, w);
3844 bar->top = top;
3845 bar->left = left;
3846 bar->width = width;
3847 bar->height = height;
3848 bar->start = 0;
3849 bar->end = 0;
3850 bar->dragging = 0;
3851 bar->horizontal = horizontal;
3853 /* Requires geometry to be set before call to create the real window */
3855 if (horizontal)
3856 hwnd = my_create_hscrollbar (f, bar);
3857 else
3858 hwnd = my_create_vscrollbar (f, bar);
3860 si.cbSize = sizeof (si);
3861 si.fMask = SIF_ALL;
3862 si.nMin = 0;
3863 if (horizontal)
3864 si.nMax = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, width)
3865 + HORIZONTAL_SCROLL_BAR_MIN_HANDLE;
3866 else
3867 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3868 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3869 si.nPage = si.nMax;
3870 si.nPos = 0;
3872 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3874 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3876 /* Add bar to its frame's list of scroll bars. */
3877 bar->next = FRAME_SCROLL_BARS (f);
3878 bar->prev = Qnil;
3879 XSETVECTOR (barobj, bar);
3880 fset_scroll_bars (f, barobj);
3881 if (! NILP (bar->next))
3882 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3884 unblock_input ();
3886 return bar;
3890 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3891 nil. */
3893 static void
3894 x_scroll_bar_remove (struct scroll_bar *bar)
3896 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3898 block_input ();
3900 /* Destroy the window. */
3901 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3903 /* Dissociate this scroll bar from its window. */
3904 if (bar->horizontal)
3905 wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
3906 else
3907 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
3909 unblock_input ();
3912 /* Set the handle of the vertical scroll bar for WINDOW to indicate that
3913 we are displaying PORTION characters out of a total of WHOLE
3914 characters, starting at POSITION. If WINDOW has no vertical scroll
3915 bar, create one. */
3916 static void
3917 w32_set_vertical_scroll_bar (struct window *w,
3918 int portion, int whole, int position)
3920 struct frame *f = XFRAME (w->frame);
3921 Lisp_Object barobj;
3922 struct scroll_bar *bar;
3923 int top, height, left, width;
3924 int window_y, window_height;
3926 /* Get window dimensions. */
3927 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
3928 top = window_y;
3929 height = window_height;
3931 /* Compute the left edge and the width of the scroll bar area. */
3932 left = WINDOW_SCROLL_BAR_AREA_X (w);
3933 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
3935 /* Does the scroll bar exist yet? */
3936 if (NILP (w->vertical_scroll_bar))
3938 HDC hdc;
3939 block_input ();
3940 if (width > 0 && height > 0)
3942 hdc = get_frame_dc (f);
3943 w32_clear_area (f, hdc, left, top, width, height);
3944 release_frame_dc (f, hdc);
3946 unblock_input ();
3948 bar = x_scroll_bar_create (w, left, top, width, height, false);
3950 else
3952 /* It may just need to be moved and resized. */
3953 HWND hwnd;
3955 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3956 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3958 /* If already correctly positioned, do nothing. */
3959 if (bar->left == left
3960 && bar->top == top
3961 && bar->width == width
3962 && bar->height == height)
3964 /* Redraw after clear_frame. */
3965 if (!my_show_window (f, hwnd, SW_NORMAL))
3966 InvalidateRect (hwnd, NULL, FALSE);
3968 else
3970 HDC hdc;
3971 SCROLLINFO si;
3973 block_input ();
3974 if (width && height)
3976 hdc = get_frame_dc (f);
3977 /* Since Windows scroll bars are smaller than the space reserved
3978 for them on the frame, we have to clear "under" them. */
3979 w32_clear_area (f, hdc, left, top, width, height);
3980 release_frame_dc (f, hdc);
3981 x_clear_under_internal_border (f);
3983 /* Make sure scroll bar is "visible" before moving, to ensure the
3984 area of the parent window now exposed will be refreshed. */
3985 my_show_window (f, hwnd, SW_HIDE);
3986 /** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
3987 /* Try to not draw over child frames. */
3988 SetWindowPos (hwnd, HWND_BOTTOM, left, top, width, max (height, 1),
3989 SWP_FRAMECHANGED);
3991 si.cbSize = sizeof (si);
3992 si.fMask = SIF_RANGE;
3993 si.nMin = 0;
3994 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3995 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3997 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3999 my_show_window (f, hwnd, SW_NORMAL);
4000 /* InvalidateRect (w, NULL, FALSE); */
4002 /* Remember new settings. */
4003 bar->left = left;
4004 bar->top = top;
4005 bar->width = width;
4006 bar->height = height;
4008 unblock_input ();
4011 w32_set_scroll_bar_thumb (bar, portion, position, whole);
4012 XSETVECTOR (barobj, bar);
4013 wset_vertical_scroll_bar (w, barobj);
4016 /* Set the handle of the horizontal scroll bar for WINDOW to indicate
4017 that we are displaying PORTION characters out of a total of WHOLE
4018 characters, starting at POSITION. If WINDOW has no horizontal scroll
4019 bar, create one. */
4020 static void
4021 w32_set_horizontal_scroll_bar (struct window *w,
4022 int portion, int whole, int position)
4024 struct frame *f = XFRAME (w->frame);
4025 Lisp_Object barobj;
4026 struct scroll_bar *bar;
4027 int top, height, left, width;
4028 int window_x, window_width;
4029 int clear_left = WINDOW_LEFT_EDGE_X (w);
4030 int clear_width = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
4032 /* Get window dimensions. */
4033 window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
4034 left = window_x;
4035 height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
4036 width = window_width;
4037 top = WINDOW_SCROLL_BAR_AREA_Y (w);
4039 /* Does the scroll bar exist yet? */
4040 if (NILP (w->horizontal_scroll_bar))
4042 HDC hdc;
4043 block_input ();
4044 if (width > 0 && height > 0)
4046 hdc = get_frame_dc (f);
4047 w32_clear_area (f, hdc, clear_left, top, clear_width, height);
4048 release_frame_dc (f, hdc);
4050 unblock_input ();
4052 bar = x_scroll_bar_create (w, left, top, width, height, true);
4054 else
4056 /* It may just need to be moved and resized. */
4057 HWND hwnd;
4059 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
4060 hwnd = SCROLL_BAR_W32_WINDOW (bar);
4062 /* If already correctly positioned, do nothing. */
4063 if (bar->left == left && bar->top == top
4064 && bar->width == width && bar->height == height)
4066 /* Redraw after clear_frame. */
4067 if (!my_show_window (f, hwnd, SW_NORMAL))
4068 InvalidateRect (hwnd, NULL, FALSE);
4070 else
4072 HDC hdc;
4073 SCROLLINFO si;
4075 block_input ();
4076 if (width && height)
4078 hdc = get_frame_dc (f);
4079 /* Since Windows scroll bars are smaller than the space reserved
4080 for them on the frame, we have to clear "under" them. */
4081 w32_clear_area (f, hdc, clear_left, top, clear_width, height);
4082 release_frame_dc (f, hdc);
4083 x_clear_under_internal_border (f);
4085 /* Make sure scroll bar is "visible" before moving, to ensure the
4086 area of the parent window now exposed will be refreshed. */
4087 my_show_window (f, hwnd, SW_HIDE);
4088 /** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
4089 /* Try to not draw over child frames. */
4090 SetWindowPos (hwnd, HWND_BOTTOM, left, top, max (width, 1), height,
4091 SWP_FRAMECHANGED);
4093 /* +++ SetScrollInfo +++ */
4094 si.cbSize = sizeof (si);
4095 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
4096 si.nMin = 0;
4097 si.nMax = whole;
4098 si.nPage = min (portion, si.nMax) + 1;
4099 si.nPos = min (position, si.nMax);
4100 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
4102 my_show_window (f, hwnd, SW_NORMAL);
4103 /* InvalidateRect (w, NULL, FALSE); */
4105 /* Remember new settings. */
4106 bar->left = left;
4107 bar->top = top;
4108 bar->width = width;
4109 bar->height = height;
4111 unblock_input ();
4115 w32_set_horizontal_scroll_bar_thumb (bar, portion, position, whole);
4116 XSETVECTOR (barobj, bar);
4117 wset_horizontal_scroll_bar (w, barobj);
4121 /* The following three hooks are used when we're doing a thorough
4122 redisplay of the frame. We don't explicitly know which scroll bars
4123 are going to be deleted, because keeping track of when windows go
4124 away is a real pain - "Can you say set-window-configuration, boys
4125 and girls?" Instead, we just assert at the beginning of redisplay
4126 that *all* scroll bars are to be removed, and then save a scroll bar
4127 from the fiery pit when we actually redisplay its window. */
4129 /* Arrange for all scroll bars on FRAME to be removed at the next call
4130 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4131 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4133 static void
4134 w32_condemn_scroll_bars (struct frame *frame)
4136 if (!NILP (FRAME_SCROLL_BARS (frame)))
4138 if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4140 /* Prepend scrollbars to already condemned ones. */
4141 Lisp_Object last = FRAME_SCROLL_BARS (frame);
4143 while (!NILP (XSCROLL_BAR (last)->next))
4144 last = XSCROLL_BAR (last)->next;
4146 XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4147 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
4150 fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
4151 fset_scroll_bars (frame, Qnil);
4156 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4157 Note that WINDOW isn't necessarily condemned at all. */
4159 static void
4160 w32_redeem_scroll_bar (struct window *w)
4162 struct scroll_bar *bar;
4163 Lisp_Object barobj;
4164 struct frame *f;
4166 /* We can't redeem this window's scroll bar if it doesn't have one. */
4167 if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
4168 emacs_abort ();
4170 if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4172 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4173 /* Unlink it from the condemned list. */
4174 f = XFRAME (WINDOW_FRAME (w));
4175 if (NILP (bar->prev))
4177 /* If the prev pointer is nil, it must be the first in one of
4178 the lists. */
4179 if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
4180 /* It's not condemned. Everything's fine. */
4181 goto horizontal;
4182 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4183 w->vertical_scroll_bar))
4184 fset_condemned_scroll_bars (f, bar->next);
4185 else
4186 /* If its prev pointer is nil, it must be at the front of
4187 one or the other! */
4188 emacs_abort ();
4190 else
4191 XSCROLL_BAR (bar->prev)->next = bar->next;
4193 if (! NILP (bar->next))
4194 XSCROLL_BAR (bar->next)->prev = bar->prev;
4196 bar->next = FRAME_SCROLL_BARS (f);
4197 bar->prev = Qnil;
4198 XSETVECTOR (barobj, bar);
4199 fset_scroll_bars (f, barobj);
4200 if (! NILP (bar->next))
4201 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4204 horizontal:
4205 if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
4207 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
4208 /* Unlink it from the condemned list. */
4209 f = XFRAME (WINDOW_FRAME (w));
4210 if (NILP (bar->prev))
4212 /* If the prev pointer is nil, it must be the first in one of
4213 the lists. */
4214 if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
4215 /* It's not condemned. Everything's fine. */
4216 return;
4217 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4218 w->horizontal_scroll_bar))
4219 fset_condemned_scroll_bars (f, bar->next);
4220 else
4221 /* If its prev pointer is nil, it must be at the front of
4222 one or the other! */
4223 emacs_abort ();
4225 else
4226 XSCROLL_BAR (bar->prev)->next = bar->next;
4228 if (! NILP (bar->next))
4229 XSCROLL_BAR (bar->next)->prev = bar->prev;
4231 bar->next = FRAME_SCROLL_BARS (f);
4232 bar->prev = Qnil;
4233 XSETVECTOR (barobj, bar);
4234 fset_scroll_bars (f, barobj);
4235 if (! NILP (bar->next))
4236 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4240 /* Remove all scroll bars on FRAME that haven't been saved since the
4241 last call to `*condemn_scroll_bars_hook'. */
4243 static void
4244 w32_judge_scroll_bars (struct frame *f)
4246 Lisp_Object bar, next;
4248 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4250 /* Clear out the condemned list now so we won't try to process any
4251 more events on the hapless scroll bars. */
4252 fset_condemned_scroll_bars (f, Qnil);
4254 for (; ! NILP (bar); bar = next)
4256 struct scroll_bar *b = XSCROLL_BAR (bar);
4258 x_scroll_bar_remove (b);
4260 next = b->next;
4261 b->next = b->prev = Qnil;
4264 /* Now there should be no references to the condemned scroll bars,
4265 and they should get garbage-collected. */
4268 /* Handle a mouse click on the vertical scroll bar BAR. If
4269 *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
4270 enqueued.
4272 This may be called from a signal handler, so we have to ignore GC
4273 mark bits. */
4275 static int
4276 w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4277 struct input_event *emacs_event)
4279 if (! WINDOWP (bar->window))
4280 emacs_abort ();
4282 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
4283 emacs_event->code = 0;
4284 /* not really meaningful to distinguish up/down */
4285 emacs_event->modifiers = msg->dwModifiers;
4286 emacs_event->frame_or_window = bar->window;
4287 emacs_event->arg = Qnil;
4288 emacs_event->timestamp = msg->msg.time;
4291 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
4292 int y;
4293 int dragging = bar->dragging;
4294 SCROLLINFO si;
4295 int sb_event = LOWORD (msg->msg.wParam);
4297 si.cbSize = sizeof (si);
4298 if (sb_event == SB_THUMBTRACK)
4299 si.fMask = SIF_TRACKPOS;
4300 else
4301 si.fMask = SIF_POS;
4303 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4304 if (sb_event == SB_THUMBTRACK)
4305 y = si.nTrackPos;
4306 else
4307 y = si.nPos;
4309 bar->dragging = 0;
4310 struct frame *f; /* Value is not used. */
4311 FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
4313 switch (sb_event)
4315 case SB_LINEDOWN:
4316 emacs_event->part = scroll_bar_down_arrow;
4317 break;
4318 case SB_LINEUP:
4319 emacs_event->part = scroll_bar_up_arrow;
4320 break;
4321 case SB_PAGEUP:
4322 emacs_event->part = scroll_bar_above_handle;
4323 break;
4324 case SB_PAGEDOWN:
4325 emacs_event->part = scroll_bar_below_handle;
4326 break;
4327 case SB_TOP:
4328 emacs_event->part = scroll_bar_handle;
4329 y = 0;
4330 break;
4331 case SB_BOTTOM:
4332 emacs_event->part = scroll_bar_handle;
4333 y = top_range;
4334 break;
4335 case SB_THUMBTRACK:
4336 case SB_THUMBPOSITION:
4337 bar->dragging = 1; /* ??????? */
4338 emacs_event->part = scroll_bar_handle;
4340 /* "Silently" update current position. */
4342 SCROLLINFO si;
4344 si.cbSize = sizeof (si);
4345 si.fMask = SIF_POS;
4346 si.nPos = y;
4347 /* Remember apparent position (we actually lag behind the real
4348 position, so don't set that directly). */
4349 last_scroll_bar_drag_pos = y;
4351 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4353 break;
4354 case SB_ENDSCROLL:
4355 /* If this is the end of a drag sequence, then reset the scroll
4356 handle size to normal and do a final redraw. Otherwise do
4357 nothing. */
4358 if (dragging)
4360 SCROLLINFO si;
4361 int start = bar->start;
4362 int end = bar->end;
4364 si.cbSize = sizeof (si);
4365 si.fMask = SIF_PAGE | SIF_POS;
4366 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
4367 si.nPos = last_scroll_bar_drag_pos;
4368 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
4370 /* fall through */
4371 FALLTHROUGH;
4372 default:
4373 emacs_event->kind = NO_EVENT;
4374 return FALSE;
4377 XSETINT (emacs_event->x, y);
4378 XSETINT (emacs_event->y, top_range);
4380 return TRUE;
4384 /* Handle a mouse click on the horizontal scroll bar BAR. If
4385 *EMACS_EVENT's kind is set to something other than NO_EVENT, it is
4386 enqueued.
4388 This may be called from a signal handler, so we have to ignore GC
4389 mark bits. */
4391 static int
4392 w32_horizontal_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4393 struct input_event *emacs_event)
4395 if (! WINDOWP (bar->window))
4396 emacs_abort ();
4398 emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
4399 emacs_event->code = 0;
4400 /* not really meaningful to distinguish left/right */
4401 emacs_event->modifiers = msg->dwModifiers;
4402 emacs_event->frame_or_window = bar->window;
4403 emacs_event->arg = Qnil;
4404 emacs_event->timestamp = msg->msg.time;
4407 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
4408 int x, y;
4409 int dragging = bar->dragging;
4410 SCROLLINFO si;
4411 int sb_event = LOWORD (msg->msg.wParam);
4413 si.cbSize = sizeof (si);
4414 if (sb_event == SB_THUMBTRACK)
4415 si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
4416 else
4417 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4419 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4420 if (sb_event == SB_THUMBTRACK)
4421 x = si.nTrackPos;
4422 else
4423 x = si.nPos;
4424 y = si.nMax - si.nPage;
4426 bar->dragging = 0;
4427 struct frame *f; /* Value is not used. */
4428 FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
4430 switch (sb_event)
4432 case SB_LINELEFT:
4433 emacs_event->part = scroll_bar_left_arrow;
4434 break;
4435 case SB_LINERIGHT:
4436 emacs_event->part = scroll_bar_right_arrow;
4437 break;
4438 case SB_PAGELEFT:
4439 emacs_event->part = scroll_bar_before_handle;
4440 break;
4441 case SB_PAGERIGHT:
4442 emacs_event->part = scroll_bar_after_handle;
4443 break;
4444 case SB_LEFT:
4445 emacs_event->part = scroll_bar_horizontal_handle;
4446 x = 0;
4447 break;
4448 case SB_RIGHT:
4449 emacs_event->part = scroll_bar_horizontal_handle;
4450 x = left_range;
4451 break;
4452 case SB_THUMBTRACK:
4453 case SB_THUMBPOSITION:
4454 bar->dragging = 1;
4455 emacs_event->part = scroll_bar_horizontal_handle;
4457 /* "Silently" update current position. */
4459 SCROLLINFO si;
4461 si.cbSize = sizeof (si);
4462 si.fMask = SIF_POS;
4463 si.nPos = min (x, XWINDOW (bar->window)->hscroll_whole - 1);
4464 /* Remember apparent position (we actually lag behind the real
4465 position, so don't set that directly). */
4466 last_scroll_bar_drag_pos = x;
4468 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4470 break;
4471 case SB_ENDSCROLL:
4472 /* If this is the end of a drag sequence, then reset the scroll
4473 handle size to normal and do a final redraw. Otherwise do
4474 nothing. */
4475 if (dragging)
4477 SCROLLINFO si;
4479 si.cbSize = sizeof (si);
4480 si.fMask = SIF_POS;
4481 si.nPos = min (last_scroll_bar_drag_pos,
4482 XWINDOW (bar->window)->hscroll_whole - 1);
4483 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
4485 /* fall through */
4486 FALLTHROUGH;
4487 default:
4488 emacs_event->kind = NO_EVENT;
4489 return FALSE;
4492 XSETINT (emacs_event->x, x);
4493 XSETINT (emacs_event->y, y);
4495 return TRUE;
4499 /* Return information to the user about the current position of the mouse
4500 on the vertical scroll bar. */
4501 static void
4502 x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
4503 enum scroll_bar_part *part,
4504 Lisp_Object *x, Lisp_Object *y,
4505 Time *time)
4507 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
4508 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
4509 Window w = SCROLL_BAR_W32_WINDOW (bar);
4510 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4511 int pos;
4512 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
4513 SCROLLINFO si;
4514 int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos);
4516 block_input ();
4518 *fp = f;
4519 *bar_window = bar->window;
4521 si.cbSize = sizeof (si);
4522 if (sb_event == SB_THUMBTRACK)
4523 si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
4524 else
4525 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4527 GetScrollInfo (w, SB_CTL, &si);
4528 if (sb_event == SB_THUMBTRACK)
4529 pos = si.nTrackPos;
4530 else
4531 pos = si.nPos;
4532 top_range = si.nMax - si.nPage + 1;
4534 *part = scroll_bar_handle;
4535 if (sb_event == SB_LINEDOWN)
4536 pos++;
4538 XSETINT (*x, pos);
4539 XSETINT (*y, top_range);
4541 f->mouse_moved = false;
4542 dpyinfo->last_mouse_scroll_bar = NULL;
4544 *time = dpyinfo->last_mouse_movement_time;
4546 unblock_input ();
4549 /* Return information to the user about the current position of the mouse
4550 on the horizontal scroll bar. */
4551 static void
4552 x_horizontal_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
4553 enum scroll_bar_part *part,
4554 Lisp_Object *x, Lisp_Object *y,
4555 Time *time)
4557 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
4558 struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
4559 Window w = SCROLL_BAR_W32_WINDOW (bar);
4560 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4561 int pos;
4562 int left_range = HORIZONTAL_SCROLL_BAR_LEFT_RANGE (f, bar->width);
4563 SCROLLINFO si;
4564 int sb_event = LOWORD (dpyinfo->last_mouse_scroll_bar_pos);
4566 block_input ();
4568 *fp = f;
4569 *bar_window = bar->window;
4571 si.cbSize = sizeof (si);
4572 if (sb_event == SB_THUMBTRACK)
4573 si.fMask = SIF_TRACKPOS | SIF_PAGE | SIF_RANGE;
4574 else
4575 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4577 GetScrollInfo (w, SB_CTL, &si);
4578 if (sb_event == SB_THUMBTRACK)
4579 pos = si.nTrackPos;
4580 else
4581 pos = si.nPos;
4582 left_range = si.nMax - si.nPage + 1;
4584 *part = scroll_bar_handle;
4585 if (sb_event == SB_LINERIGHT)
4586 pos++;
4589 XSETINT (*y, pos);
4590 XSETINT (*x, left_range);
4592 f->mouse_moved = false;
4593 dpyinfo->last_mouse_scroll_bar = NULL;
4595 *time = dpyinfo->last_mouse_movement_time;
4597 unblock_input ();
4601 /* The screen has been cleared so we may have changed foreground or
4602 background colors, and the scroll bars may need to be redrawn.
4603 Clear out the scroll bars, and ask for expose events, so we can
4604 redraw them. */
4606 void
4607 x_scroll_bar_clear (struct frame *f)
4609 Lisp_Object bar;
4611 /* We can have scroll bars even if this is 0,
4612 if we just turned off scroll bar mode.
4613 But in that case we should not clear them. */
4614 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4615 || FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
4616 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4617 bar = XSCROLL_BAR (bar)->next)
4619 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4620 HDC hdc = GetDC (window);
4621 RECT rect;
4623 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4624 arranges to refresh the scroll bar if hidden. */
4625 my_show_window (f, window, SW_HIDE);
4627 GetClientRect (window, &rect);
4628 select_palette (f, hdc);
4629 w32_clear_rect (f, hdc, &rect);
4630 x_clear_under_internal_border (f);
4631 deselect_palette (f, hdc);
4633 ReleaseDC (window, hdc);
4637 /* The main W32 event-reading loop - w32_read_socket. */
4639 /* Record the last 100 characters stored
4640 to help debug the loss-of-chars-during-GC problem. */
4642 static int temp_index;
4643 static short temp_buffer[100];
4645 /* Temporarily store lead byte of DBCS input sequences. */
4646 static char dbcs_lead = 0;
4648 /* Read events coming from the W32 shell.
4649 This routine is called by the SIGIO handler.
4650 We return as soon as there are no more events to be read.
4652 For an overview of how Emacs input works on MS-Windows, see the
4653 commentary before w32_msg_pump in w32fns.c.
4655 We return the number of characters stored into the buffer,
4656 thus pretending to be `read'.
4658 Some of these messages are reposted back to the message queue since the
4659 system calls the windows proc directly in a context where we cannot return
4660 the data nor can we guarantee the state we are in. So if we dispatch them
4661 we will get into an infinite loop. To prevent this from ever happening we
4662 will set a variable to indicate we are in the read_socket call and indicate
4663 which message we are processing since the windows proc gets called
4664 recursively with different messages by the system.
4667 extern void menubar_selection_callback (struct frame *, void *);
4669 static int
4670 w32_read_socket (struct terminal *terminal,
4671 struct input_event *hold_quit)
4673 int count = 0;
4674 int check_visibility = 0;
4675 W32Msg msg;
4676 struct frame *f;
4677 struct w32_display_info *dpyinfo = &one_w32_display_info;
4678 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
4680 block_input ();
4682 /* Process any incoming thread messages. */
4683 drain_message_queue ();
4685 /* TODO: ghostscript integration. */
4686 while (get_next_msg (&msg, FALSE))
4688 struct input_event inev;
4689 int do_help = 0;
4691 /* DebPrint (("w32_read_socket: %s time:%u\n", */
4692 /* w32_name_of_message (msg.msg.message), */
4693 /* msg.msg.time)); */
4695 EVENT_INIT (inev);
4696 inev.kind = NO_EVENT;
4697 inev.arg = Qnil;
4699 switch (msg.msg.message)
4701 case WM_EMACS_PAINT:
4702 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4704 if (f)
4706 if (msg.rect.right == msg.rect.left ||
4707 msg.rect.bottom == msg.rect.top)
4709 /* We may get paint messages even though the client
4710 area is clipped - these are not expose events. */
4711 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4712 SDATA (f->name)));
4714 else if (FRAME_VISIBLE_P (f) != 1)
4716 bool iconified = FRAME_ICONIFIED_P (f);
4718 /* Definitely not obscured, so mark as visible. */
4719 SET_FRAME_VISIBLE (f, 1);
4720 SET_FRAME_ICONIFIED (f, false);
4721 SET_FRAME_GARBAGED (f);
4722 if (!f->output_data.w32->asked_for_visible)
4723 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4724 SDATA (f->name)));
4726 /* WM_PAINT serves as MapNotify as well, so report
4727 visibility changes properly. */
4728 if (iconified)
4730 inev.kind = DEICONIFY_EVENT;
4731 XSETFRAME (inev.frame_or_window, f);
4733 else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list)))
4734 /* Force a redisplay sooner or later to update the
4735 frame titles in case this is the second frame. */
4736 record_asynch_buffer_change ();
4738 else
4740 /* Erase background again for safety. But don't do
4741 that if the frame's 'garbaged' flag is set, since
4742 in that case expose_frame will do nothing, and if
4743 the various redisplay flags happen to be unset,
4744 we are left with a blank frame. */
4745 if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
4747 HDC hdc = get_frame_dc (f);
4749 w32_clear_rect (f, hdc, &msg.rect);
4750 release_frame_dc (f, hdc);
4752 expose_frame (f,
4753 msg.rect.left,
4754 msg.rect.top,
4755 msg.rect.right - msg.rect.left,
4756 msg.rect.bottom - msg.rect.top);
4757 x_clear_under_internal_border (f);
4760 break;
4762 case WM_INPUTLANGCHANGE:
4763 /* Generate a language change event. */
4764 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4766 /* lParam contains the input language ID in its low 16 bits.
4767 Use it to update our record of the keyboard codepage. */
4768 w32_keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4769 & 0xffff));
4771 if (f)
4773 inev.kind = LANGUAGE_CHANGE_EVENT;
4774 XSETFRAME (inev.frame_or_window, f);
4775 inev.code = w32_keyboard_codepage;
4776 inev.modifiers = msg.msg.lParam & 0xffff;
4778 break;
4780 case WM_KEYDOWN:
4781 case WM_SYSKEYDOWN:
4782 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4784 if (f && !FRAME_ICONIFIED_P (f))
4786 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4787 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4789 clear_mouse_face (hlinfo);
4790 hlinfo->mouse_face_hidden = true;
4793 if (temp_index == sizeof temp_buffer / sizeof (short))
4794 temp_index = 0;
4795 temp_buffer[temp_index++] = msg.msg.wParam;
4796 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4797 inev.code = msg.msg.wParam;
4798 inev.modifiers = msg.dwModifiers;
4799 XSETFRAME (inev.frame_or_window, f);
4800 inev.timestamp = msg.msg.time;
4802 break;
4804 case WM_UNICHAR:
4805 case WM_SYSCHAR:
4806 case WM_CHAR:
4807 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4809 if (f && !FRAME_ICONIFIED_P (f))
4811 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4812 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4814 clear_mouse_face (hlinfo);
4815 hlinfo->mouse_face_hidden = true;
4818 if (temp_index == sizeof temp_buffer / sizeof (short))
4819 temp_index = 0;
4820 temp_buffer[temp_index++] = msg.msg.wParam;
4822 inev.modifiers = msg.dwModifiers;
4823 XSETFRAME (inev.frame_or_window, f);
4824 inev.timestamp = msg.msg.time;
4826 if (msg.msg.message == WM_UNICHAR)
4828 inev.code = msg.msg.wParam;
4830 else if (msg.msg.wParam < 256)
4832 wchar_t code;
4833 char dbcs[2];
4834 dbcs[0] = 0;
4835 dbcs[1] = (char) msg.msg.wParam;
4837 if (dbcs_lead)
4839 dbcs[0] = dbcs_lead;
4840 dbcs_lead = 0;
4841 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
4842 dbcs, 2, &code, 1))
4844 /* Garbage */
4845 DebPrint (("Invalid DBCS sequence: %d %d\n",
4846 dbcs[0], dbcs[1]));
4847 inev.kind = NO_EVENT;
4848 break;
4851 else if (IsDBCSLeadByteEx (w32_keyboard_codepage,
4852 (BYTE) msg.msg.wParam))
4854 dbcs_lead = (char) msg.msg.wParam;
4855 inev.kind = NO_EVENT;
4856 break;
4858 else
4860 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
4861 &dbcs[1], 1, &code, 1))
4863 /* What to do with garbage? */
4864 DebPrint (("Invalid character: %d\n", dbcs[1]));
4865 inev.kind = NO_EVENT;
4866 break;
4869 inev.code = code;
4871 else
4873 /* Windows shouldn't generate WM_CHAR events above 0xFF
4874 in non-Unicode message handlers. */
4875 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4876 inev.kind = NO_EVENT;
4877 break;
4879 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4880 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
4882 break;
4884 case WM_APPCOMMAND:
4885 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4887 if (f && !FRAME_ICONIFIED_P (f))
4889 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4890 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4892 clear_mouse_face (hlinfo);
4893 hlinfo->mouse_face_hidden = true;
4896 if (temp_index == sizeof temp_buffer / sizeof (short))
4897 temp_index = 0;
4898 temp_buffer[temp_index++] = msg.msg.wParam;
4899 inev.kind = MULTIMEDIA_KEY_EVENT;
4900 inev.code = GET_APPCOMMAND_LPARAM (msg.msg.lParam);
4901 inev.modifiers = msg.dwModifiers;
4902 XSETFRAME (inev.frame_or_window, f);
4903 inev.timestamp = msg.msg.time;
4905 break;
4907 case WM_MOUSEMOVE:
4908 /* Ignore non-movement. */
4910 int x = LOWORD (msg.msg.lParam);
4911 int y = HIWORD (msg.msg.lParam);
4912 if (x == last_mousemove_x && y == last_mousemove_y)
4913 break;
4914 last_mousemove_x = x;
4915 last_mousemove_y = y;
4918 previous_help_echo_string = help_echo_string;
4919 help_echo_string = Qnil;
4921 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
4922 : x_window_to_frame (dpyinfo, msg.msg.hwnd));
4924 if (hlinfo->mouse_face_hidden)
4926 hlinfo->mouse_face_hidden = false;
4927 clear_mouse_face (hlinfo);
4930 if (f)
4932 /* Maybe generate SELECT_WINDOW_EVENTs for
4933 `mouse-autoselect-window'. */
4934 if (!NILP (Vmouse_autoselect_window)
4935 && (f == XFRAME (selected_frame)
4936 /* Switch to f from another frame iff
4937 focus_follows_mouse is set and f accepts
4938 focus. */
4939 || (!NILP (focus_follows_mouse)
4940 && !FRAME_NO_ACCEPT_FOCUS (f))))
4942 static Lisp_Object last_mouse_window;
4943 Lisp_Object window = window_from_coordinates
4944 (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0);
4946 /* Window will be selected only when it is not
4947 selected now and last mouse movement event was
4948 not in it. Minibuffer window will be selected
4949 only when it is active. */
4950 if (WINDOWP (window)
4951 && !EQ (window, last_mouse_window)
4952 && !EQ (window, selected_window))
4954 inev.kind = SELECT_WINDOW_EVENT;
4955 inev.frame_or_window = window;
4958 /* Remember the last window where we saw the mouse. */
4959 last_mouse_window = window;
4962 if (!note_mouse_movement (f, &msg.msg))
4963 help_echo_string = previous_help_echo_string;
4965 else
4967 /* If we move outside the frame, then we're
4968 certainly no longer on any text in the frame. */
4969 clear_mouse_face (hlinfo);
4972 /* If the contents of the global variable help_echo_string
4973 has changed, generate a HELP_EVENT. */
4974 #if 0 /* The below is an invalid comparison when CHECK_LISP_OBJECT_TYPE.
4975 But it was originally changed to this to fix a bug, so I have
4976 not removed it completely in case the bug is still there. */
4977 if (help_echo_string != previous_help_echo_string ||
4978 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4979 #else /* This is what xterm.c does. */
4980 if (!NILP (help_echo_string)
4981 || !NILP (previous_help_echo_string))
4982 do_help = 1;
4983 #endif
4984 break;
4986 case WM_LBUTTONDOWN:
4987 case WM_LBUTTONUP:
4988 case WM_MBUTTONDOWN:
4989 case WM_MBUTTONUP:
4990 case WM_RBUTTONDOWN:
4991 case WM_RBUTTONUP:
4992 case WM_XBUTTONDOWN:
4993 case WM_XBUTTONUP:
4995 /* If we decide we want to generate an event to be seen
4996 by the rest of Emacs, we put it here. */
4997 bool tool_bar_p = 0;
4998 int button = 0;
4999 int up = 0;
5001 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
5002 : x_window_to_frame (dpyinfo, msg.msg.hwnd));
5004 if (f)
5006 construct_mouse_click (&inev, &msg, f);
5008 /* Is this in the tool-bar? */
5009 if (WINDOWP (f->tool_bar_window)
5010 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
5012 Lisp_Object window;
5013 int x = XFASTINT (inev.x);
5014 int y = XFASTINT (inev.y);
5016 window = window_from_coordinates (f, x, y, 0, 1);
5018 if (EQ (window, f->tool_bar_window))
5020 w32_handle_tool_bar_click (f, &inev);
5021 tool_bar_p = 1;
5025 if (tool_bar_p
5026 || (dpyinfo->w32_focus_frame
5027 && f != dpyinfo->w32_focus_frame
5028 /* This does not help when the click happens in
5029 a grand-parent frame. */
5030 && !frame_ancestor_p (f, dpyinfo->w32_focus_frame)))
5031 inev.kind = NO_EVENT;
5034 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
5035 &button, &up);
5037 if (up)
5039 dpyinfo->grabbed &= ~ (1 << button);
5041 else
5043 dpyinfo->grabbed |= (1 << button);
5044 dpyinfo->last_mouse_frame = f;
5045 /* Ignore any mouse motion that happened
5046 before this event; any subsequent mouse-movement
5047 Emacs events should reflect only motion after
5048 the ButtonPress. */
5049 if (f != 0)
5051 f->mouse_moved = false;
5052 if (!tool_bar_p)
5053 f->last_tool_bar_item = -1;
5056 break;
5059 case WM_MOUSEWHEEL:
5060 case WM_MOUSEHWHEEL:
5062 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
5063 : x_window_to_frame (dpyinfo, msg.msg.hwnd));
5065 if (f)
5067 if (!dpyinfo->w32_focus_frame
5068 || f == dpyinfo->w32_focus_frame)
5069 /* Emit an Emacs wheel-up/down event. */
5071 construct_mouse_wheel (&inev, &msg, f);
5073 /* Ignore any mouse motion that happened before this
5074 event; any subsequent mouse-movement Emacs events
5075 should reflect only motion after the ButtonPress. */
5076 f->mouse_moved = false;
5077 f->last_tool_bar_item = -1;
5078 dpyinfo->last_mouse_frame = f;
5080 else if (FRAME_NO_ACCEPT_FOCUS (f)
5081 && !x_mouse_grabbed (dpyinfo))
5083 Lisp_Object frame1 = get_frame_param (f, Qmouse_wheel_frame);
5084 struct frame *f1 = FRAMEP (frame1) ? XFRAME (frame1) : NULL;
5086 if (f1 && FRAME_LIVE_P (f1) && FRAME_W32_P (f1))
5088 construct_mouse_wheel (&inev, &msg, f1);
5089 f1->mouse_moved = false;
5090 f1->last_tool_bar_item = -1;
5091 dpyinfo->last_mouse_frame = f1;
5093 else
5094 dpyinfo->last_mouse_frame = f;
5096 else
5097 dpyinfo->last_mouse_frame = f;
5099 else
5100 dpyinfo->last_mouse_frame = f;
5102 break;
5104 case WM_DROPFILES:
5105 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5107 if (f)
5108 construct_drag_n_drop (&inev, &msg, f);
5109 break;
5111 case WM_HSCROLL:
5113 struct scroll_bar *bar =
5114 x_window_to_scroll_bar ((HWND)msg.msg.lParam, 1);
5116 if (bar)
5117 w32_horizontal_scroll_bar_handle_click (bar, &msg, &inev);
5118 break;
5121 case WM_VSCROLL:
5123 struct scroll_bar *bar =
5124 x_window_to_scroll_bar ((HWND)msg.msg.lParam, 0);
5126 if (bar)
5127 w32_scroll_bar_handle_click (bar, &msg, &inev);
5128 break;
5131 case WM_WINDOWPOSCHANGED:
5132 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5134 if (f)
5136 RECT rect;
5137 int /* rows, columns, */ width, height, text_width, text_height;
5139 if (GetClientRect (msg.msg.hwnd, &rect)
5140 /* GetClientRect evidently returns (0, 0, 0, 0) if
5141 called on a minimized frame. Such "dimensions"
5142 aren't useful anyway. */
5143 && !(rect.bottom == 0
5144 && rect.top == 0
5145 && rect.left == 0
5146 && rect.right == 0))
5148 height = rect.bottom - rect.top;
5149 width = rect.right - rect.left;
5150 text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width);
5151 text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height);
5152 /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */
5153 /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */
5155 /* TODO: Clip size to the screen dimensions. */
5157 /* Even if the number of character rows and columns
5158 has not changed, the font size may have changed,
5159 so we need to check the pixel dimensions as well. */
5161 if (width != FRAME_PIXEL_WIDTH (f)
5162 || height != FRAME_PIXEL_HEIGHT (f)
5163 || text_width != FRAME_TEXT_WIDTH (f)
5164 || text_height != FRAME_TEXT_HEIGHT (f))
5166 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
5167 SET_FRAME_GARBAGED (f);
5168 cancel_mouse_face (f);
5169 f->win_gravity = NorthWestGravity;
5174 check_visibility = 1;
5175 break;
5177 case WM_ACTIVATE:
5178 case WM_ACTIVATEAPP:
5179 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5180 if (f)
5182 /* Run the full-screen hook function also when we are
5183 being activated, to actually install the required
5184 size in effect, if the WAIT flag is set. This is
5185 because when the hook is run from x_set_fullscreen,
5186 the frame might not yet be visible, if that call is a
5187 result of make-frame, and in that case the hook just
5188 sets the WAIT flag. */
5189 if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam)
5190 && (f->want_fullscreen & FULLSCREEN_WAIT))
5192 /* Must set visibility right here since otherwise
5193 w32fullscreen_hook returns immediately. */
5194 SET_FRAME_VISIBLE (f, 1);
5195 w32fullscreen_hook (f);
5199 check_visibility = 1;
5200 break;
5202 case WM_MOVE:
5203 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5205 if (f && FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P(f))
5207 x_real_positions (f, &f->left_pos, &f->top_pos);
5208 inev.kind = MOVE_FRAME_EVENT;
5209 XSETFRAME (inev.frame_or_window, f);
5212 check_visibility = 1;
5213 break;
5215 case WM_SHOWWINDOW:
5216 /* wParam non-zero means Window is about to be shown, 0 means
5217 about to be hidden. */
5218 /* Redo the mouse-highlight after the tooltip has gone. */
5219 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
5221 tip_window = NULL;
5222 x_redo_mouse_highlight (dpyinfo);
5225 /* If window has been obscured or exposed by another window
5226 being maximized or minimized/restored, then recheck
5227 visibility of all frames. Direct changes to our own
5228 windows get handled by WM_SIZE. */
5229 #if 0
5230 if (msg.msg.lParam != 0)
5231 check_visibility = 1;
5232 else
5234 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5235 f->async_visible = msg.msg.wParam;
5237 #endif
5239 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5240 if (f)
5241 x_clear_under_internal_border (f);
5243 check_visibility = 1;
5244 break;
5246 case WM_SIZE:
5247 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5249 /* Inform lisp of whether frame has been iconified etc. */
5250 if (f)
5252 switch (msg.msg.wParam)
5254 case SIZE_MINIMIZED:
5255 SET_FRAME_VISIBLE (f, 0);
5256 SET_FRAME_ICONIFIED (f, true);
5258 inev.kind = ICONIFY_EVENT;
5259 XSETFRAME (inev.frame_or_window, f);
5260 break;
5262 case SIZE_MAXIMIZED:
5264 bool iconified = FRAME_ICONIFIED_P (f);
5265 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
5267 SET_FRAME_VISIBLE (f, 1);
5268 SET_FRAME_ICONIFIED (f, false);
5270 /* wait_reading_process_output will notice this
5271 and update the frame's display structures. */
5272 SET_FRAME_GARBAGED (f);
5274 if (iconified)
5276 int x, y;
5278 /* Reset top and left positions of the Window
5279 here since Windows sends a WM_MOVE message
5280 BEFORE telling us the Window is minimized
5281 when the Window is iconified, with 3000,3000
5282 as the co-ords. */
5283 x_real_positions (f, &x, &y);
5284 f->left_pos = x;
5285 f->top_pos = y;
5287 inev.kind = DEICONIFY_EVENT;
5288 XSETFRAME (inev.frame_or_window, f);
5290 else if (! NILP (Vframe_list)
5291 && ! NILP (XCDR (Vframe_list)))
5292 /* Force a redisplay sooner or later
5293 to update the frame titles
5294 in case this is the second frame. */
5295 record_asynch_buffer_change ();
5297 /* Windows can send us a SIZE_MAXIMIZED message even
5298 when fullscreen is fullboth. The following is a
5299 simple hack to check that based on the fact that
5300 only a maximized fullscreen frame should have both
5301 top/left outside the screen. */
5302 if (EQ (fullscreen, Qfullwidth) || EQ (fullscreen, Qfullheight)
5303 || NILP (fullscreen))
5305 int x, y;
5307 x_real_positions (f, &x, &y);
5308 if (x < 0 && y < 0)
5309 store_frame_param (f, Qfullscreen, Qmaximized);
5313 break;
5315 case SIZE_RESTORED:
5317 bool iconified = FRAME_ICONIFIED_P (f);
5319 /* The following was made unconditional in a
5320 pathetic attempt to fix bug#16967 in revision
5321 116716 but, considered counterproductive was made
5322 conditional again in revision 116727. martin */
5323 if (iconified)
5324 SET_FRAME_VISIBLE (f, 1);
5325 SET_FRAME_ICONIFIED (f, false);
5327 /* wait_reading_process_output will notice this
5328 and update the frame's display structures. */
5329 SET_FRAME_GARBAGED (f);
5331 if (iconified)
5333 /* Reset top and left positions of the Window
5334 here since Windows sends a WM_MOVE message
5335 BEFORE telling us the Window is minimized
5336 when the Window is iconified, with 3000,3000
5337 as the co-ords. */
5338 x_real_positions (f, &f->left_pos, &f->top_pos);
5340 inev.kind = DEICONIFY_EVENT;
5341 XSETFRAME (inev.frame_or_window, f);
5343 else if (! NILP (Vframe_list)
5344 && ! NILP (XCDR (Vframe_list)))
5345 /* Force a redisplay sooner or later
5346 to update the frame titles
5347 in case this is the second frame. */
5348 record_asynch_buffer_change ();
5351 if (EQ (get_frame_param (f, Qfullscreen), Qmaximized))
5352 store_frame_param (f, Qfullscreen, Qnil);
5354 break;
5358 if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED)
5360 RECT rect;
5361 int /* rows, columns, */ width, height, text_width, text_height;
5363 if (GetClientRect (msg.msg.hwnd, &rect)
5364 /* GetClientRect evidently returns (0, 0, 0, 0) if
5365 called on a minimized frame. Such "dimensions"
5366 aren't useful anyway. */
5367 && !(rect.bottom == 0
5368 && rect.top == 0
5369 && rect.left == 0
5370 && rect.right == 0))
5372 height = rect.bottom - rect.top;
5373 width = rect.right - rect.left;
5374 text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width);
5375 text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height);
5376 /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */
5377 /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */
5379 /* TODO: Clip size to the screen dimensions. */
5381 /* Even if the number of character rows and columns
5382 has not changed, the font size may have changed,
5383 so we need to check the pixel dimensions as well. */
5385 if (width != FRAME_PIXEL_WIDTH (f)
5386 || height != FRAME_PIXEL_HEIGHT (f)
5387 || text_width != FRAME_TEXT_WIDTH (f)
5388 || text_height != FRAME_TEXT_HEIGHT (f))
5390 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
5391 SET_FRAME_GARBAGED (f);
5392 cancel_mouse_face (f);
5393 f->win_gravity = NorthWestGravity;
5398 check_visibility = 1;
5399 break;
5401 case WM_MOUSELEAVE:
5402 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
5403 if (f)
5405 if (f == hlinfo->mouse_face_mouse_frame)
5407 /* If we move outside the frame, then we're
5408 certainly no longer on any text in the frame. */
5409 clear_mouse_face (hlinfo);
5410 hlinfo->mouse_face_mouse_frame = 0;
5413 /* Generate a nil HELP_EVENT to cancel a help-echo.
5414 Do it only if there's something to cancel.
5415 Otherwise, the startup message is cleared when
5416 the mouse leaves the frame. */
5417 if (any_help_event_p)
5418 do_help = -1;
5420 break;
5422 case WM_SETFOCUS:
5423 w32_detect_focus_change (dpyinfo, &msg, &inev);
5425 dpyinfo->grabbed = 0;
5426 check_visibility = 1;
5427 break;
5429 case WM_KILLFOCUS:
5430 w32_detect_focus_change (dpyinfo, &msg, &inev);
5431 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
5433 if (f)
5435 if (f == hlinfo->mouse_face_mouse_frame)
5437 /* If we move outside the frame, then we're
5438 certainly no longer on any text in the frame. */
5439 clear_mouse_face (hlinfo);
5440 hlinfo->mouse_face_mouse_frame = 0;
5443 /* Generate a nil HELP_EVENT to cancel a help-echo.
5444 Do it only if there's something to cancel.
5445 Otherwise, the startup message is cleared when
5446 the mouse leaves the frame. */
5447 if (any_help_event_p)
5448 do_help = -1;
5451 dpyinfo->grabbed = 0;
5452 check_visibility = 1;
5453 break;
5455 case WM_CLOSE:
5456 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5458 if (f)
5460 inev.kind = DELETE_WINDOW_EVENT;
5461 XSETFRAME (inev.frame_or_window, f);
5463 break;
5465 case WM_ENDSESSION:
5466 inev.kind = END_SESSION_EVENT;
5467 break;
5469 case WM_INITMENU:
5470 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5472 if (f)
5474 inev.kind = MENU_BAR_ACTIVATE_EVENT;
5475 XSETFRAME (inev.frame_or_window, f);
5477 break;
5479 case WM_COMMAND:
5480 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5482 if (f)
5484 menubar_selection_callback (f, (void *)msg.msg.wParam);
5487 check_visibility = 1;
5488 break;
5490 case WM_DISPLAYCHANGE:
5491 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5493 if (f)
5495 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
5497 dpyinfo->n_cbits = msg.msg.wParam;
5498 /* The new display could have a different resolution, in
5499 which case we must reconsider what fullscreen means.
5500 The following code is untested yet. */
5501 if (!NILP (fullscreen))
5503 x_set_fullscreen (f, fullscreen, fullscreen);
5504 w32fullscreen_hook (f);
5507 DebPrint (("display change: %d %d\n",
5508 (short) LOWORD (msg.msg.lParam),
5509 (short) HIWORD (msg.msg.lParam)));
5512 check_visibility = 1;
5513 break;
5515 #if HAVE_W32NOTIFY
5516 case WM_EMACS_FILENOTIFY:
5517 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5518 if (f)
5519 queue_notifications (&inev, &msg, f, &count);
5520 break;
5521 #endif
5523 default:
5524 /* Check for messages registered at runtime. */
5525 if (msg.msg.message == msh_mousewheel)
5527 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
5528 msg.msg.message = WM_MOUSEWHEEL;
5529 prepend_msg (&msg);
5531 break;
5534 if (inev.kind != NO_EVENT)
5536 kbd_buffer_store_event_hold (&inev, hold_quit);
5537 count++;
5540 if (do_help
5541 && !(hold_quit && hold_quit->kind != NO_EVENT))
5543 Lisp_Object frame;
5545 if (f)
5546 XSETFRAME (frame, f);
5547 else
5548 frame = Qnil;
5550 if (do_help > 0)
5552 if (NILP (help_echo_string))
5554 help_echo_object = help_echo_window = Qnil;
5555 help_echo_pos = -1;
5558 any_help_event_p = 1;
5559 gen_help_event (help_echo_string, frame, help_echo_window,
5560 help_echo_object, help_echo_pos);
5562 else
5564 help_echo_string = Qnil;
5565 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
5567 count++;
5571 /* If the focus was just given to an autoraising frame,
5572 raise it now. FIXME: handle more than one such frame. */
5573 if (dpyinfo->w32_pending_autoraise_frame)
5575 x_raise_frame (dpyinfo->w32_pending_autoraise_frame);
5576 dpyinfo->w32_pending_autoraise_frame = NULL;
5579 /* Check which frames are still visible, if we have enqueued any user
5580 events or been notified of events that may affect visibility. We
5581 do this here because there doesn't seem to be any direct
5582 notification from Windows that the visibility of a window has
5583 changed (at least, not in all cases). */
5584 if (count > 0 || check_visibility)
5586 Lisp_Object tail, frame;
5588 FOR_EACH_FRAME (tail, frame)
5590 struct frame *f = XFRAME (frame);
5591 /* The tooltip has been drawn already. Avoid the
5592 SET_FRAME_GARBAGED below. */
5593 if (FRAME_TOOLTIP_P (f))
5594 continue;
5596 /* Check "visible" frames and mark each as obscured or not.
5597 Note that visible is nonzero for unobscured and obscured
5598 frames, but zero for hidden and iconified frames. */
5599 if (FRAME_W32_P (f) && FRAME_VISIBLE_P (f))
5601 RECT clipbox;
5602 HDC hdc;
5603 bool obscured;
5605 enter_crit ();
5606 /* Query clipping rectangle for the entire window area
5607 (GetWindowDC), not just the client portion (GetDC).
5608 Otherwise, the scrollbars and menubar aren't counted as
5609 part of the visible area of the frame, and we may think
5610 the frame is obscured when really a scrollbar is still
5611 visible and gets WM_PAINT messages above. */
5612 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
5613 GetClipBox (hdc, &clipbox);
5614 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
5615 leave_crit ();
5617 obscured = FRAME_OBSCURED_P (f);
5619 if (clipbox.right == clipbox.left || clipbox.bottom == clipbox.top)
5621 /* Frame has become completely obscured so mark as such (we
5622 do this by setting visible to 2 so that FRAME_VISIBLE_P
5623 is still true, but redisplay will skip it). */
5624 SET_FRAME_VISIBLE (f, 2);
5626 if (!obscured)
5627 DebPrint (("frame %p (%s) obscured\n", f, SDATA (f->name)));
5629 else
5631 /* Frame is not obscured, so mark it as such. */
5632 SET_FRAME_VISIBLE (f, 1);
5634 if (obscured)
5636 SET_FRAME_GARBAGED (f);
5637 DebPrint (("obscured frame %p (%s) found to be visible\n",
5638 f, SDATA (f->name)));
5640 /* Force a redisplay sooner or later. */
5641 record_asynch_buffer_change ();
5648 unblock_input ();
5649 return count;
5654 /***********************************************************************
5655 Text Cursor
5656 ***********************************************************************/
5658 /* Set clipping for output in glyph row ROW. W is the window in which
5659 we operate. GC is the graphics context to set clipping in.
5661 ROW may be a text row or, e.g., a mode line. Text rows must be
5662 clipped to the interior of the window dedicated to text display,
5663 mode lines must be clipped to the whole window. */
5665 static void
5666 w32_clip_to_row (struct window *w, struct glyph_row *row,
5667 enum glyph_row_area area, HDC hdc)
5669 RECT clip_rect;
5670 int window_x, window_y, window_width;
5672 window_box (w, area, &window_x, &window_y, &window_width, 0);
5674 clip_rect.left = window_x;
5675 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5676 clip_rect.top = max (clip_rect.top, window_y);
5677 clip_rect.right = clip_rect.left + window_width;
5678 clip_rect.bottom = clip_rect.top + row->visible_height;
5680 w32_set_clip_rectangle (hdc, &clip_rect);
5684 /* Draw a hollow box cursor on window W in glyph row ROW. */
5686 static void
5687 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
5689 struct frame *f = XFRAME (WINDOW_FRAME (w));
5690 HDC hdc;
5691 RECT rect;
5692 int left, top, h;
5693 struct glyph *cursor_glyph;
5694 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
5696 /* Get the glyph the cursor is on. If we can't tell because
5697 the current matrix is invalid or such, give up. */
5698 cursor_glyph = get_phys_cursor_glyph (w);
5699 if (cursor_glyph == NULL)
5701 DeleteObject (hb);
5702 return;
5705 /* Compute frame-relative coordinates for phys cursor. */
5706 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
5707 rect.left = left;
5708 /* When on R2L character, show cursor at the right edge of the
5709 glyph, unless the cursor box is as wide as the glyph or wider
5710 (the latter happens when x-stretch-cursor is non-nil). */
5711 if ((cursor_glyph->resolved_level & 1) != 0
5712 && cursor_glyph->pixel_width > w->phys_cursor_width)
5713 rect.left += cursor_glyph->pixel_width - w->phys_cursor_width;
5714 rect.top = top;
5715 rect.bottom = rect.top + h;
5716 rect.right = rect.left + w->phys_cursor_width;
5718 hdc = get_frame_dc (f);
5719 /* Set clipping, draw the rectangle, and reset clipping again. */
5720 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5721 FrameRect (hdc, &rect, hb);
5722 DeleteObject (hb);
5723 w32_set_clip_rectangle (hdc, NULL);
5724 release_frame_dc (f, hdc);
5728 /* Draw a bar cursor on window W in glyph row ROW.
5730 Implementation note: One would like to draw a bar cursor with an
5731 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5732 Unfortunately, I didn't find a font yet that has this property set.
5733 --gerd. */
5735 static void
5736 x_draw_bar_cursor (struct window *w, struct glyph_row *row,
5737 int width, enum text_cursor_kinds kind)
5739 struct frame *f = XFRAME (w->frame);
5740 struct glyph *cursor_glyph;
5742 /* If cursor is out of bounds, don't draw garbage. This can happen
5743 in mini-buffer windows when switching between echo area glyphs
5744 and mini-buffer. */
5745 cursor_glyph = get_phys_cursor_glyph (w);
5746 if (cursor_glyph == NULL)
5747 return;
5749 /* If on an image, draw like a normal cursor. That's usually better
5750 visible than drawing a bar, esp. if the image is large so that
5751 the bar might not be in the window. */
5752 if (cursor_glyph->type == IMAGE_GLYPH)
5754 struct glyph_row *row;
5755 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5756 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5758 else
5760 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5761 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5762 int x;
5763 HDC hdc;
5765 /* If the glyph's background equals the color we normally draw
5766 the bar cursor in, the bar cursor in its normal color is
5767 invisible. Use the glyph's foreground color instead in this
5768 case, on the assumption that the glyph's colors are chosen so
5769 that the glyph is legible. */
5770 if (face->background == cursor_color)
5771 cursor_color = face->foreground;
5773 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5775 hdc = get_frame_dc (f);
5776 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5778 if (kind == BAR_CURSOR)
5780 if (width < 0)
5781 width = FRAME_CURSOR_WIDTH (f);
5782 width = min (cursor_glyph->pixel_width, width);
5784 w->phys_cursor_width = width;
5786 /* If the character under cursor is R2L, draw the bar cursor
5787 on the right of its glyph, rather than on the left. */
5788 if ((cursor_glyph->resolved_level & 1) != 0)
5789 x += cursor_glyph->pixel_width - width;
5791 w32_fill_area (f, hdc, cursor_color, x,
5792 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5793 width, row->height);
5795 else /* HBAR_CURSOR */
5797 int dummy_x, dummy_y, dummy_h;
5799 if (width < 0)
5800 width = row->height;
5802 width = min (row->height, width);
5804 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5805 &dummy_y, &dummy_h);
5806 if ((cursor_glyph->resolved_level & 1) != 0
5807 && cursor_glyph->pixel_width > w->phys_cursor_width)
5808 x += cursor_glyph->pixel_width - w->phys_cursor_width;
5809 w32_fill_area (f, hdc, cursor_color, x,
5810 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5811 row->height - width),
5812 w->phys_cursor_width, width);
5815 w32_set_clip_rectangle (hdc, NULL);
5816 release_frame_dc (f, hdc);
5821 /* RIF: Define cursor CURSOR on frame F. */
5823 static void
5824 w32_define_frame_cursor (struct frame *f, Cursor cursor)
5826 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5830 /* RIF: Clear area on frame F. */
5832 static void
5833 w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
5835 HDC hdc;
5837 hdc = get_frame_dc (f);
5838 w32_clear_area (f, hdc, x, y, width, height);
5839 release_frame_dc (f, hdc);
5842 /* RIF: Draw or clear cursor on window W. */
5844 static void
5845 w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
5846 int x, int y, enum text_cursor_kinds cursor_type,
5847 int cursor_width, bool on_p, bool active_p)
5849 if (on_p)
5851 /* If the user wants to use the system caret, make sure our own
5852 cursor remains invisible. */
5853 if (w32_use_visible_system_caret)
5855 /* Call to erase_phys_cursor here seems to use the
5856 wrong values of w->phys_cursor, as they have been
5857 overwritten before this function was called. */
5858 if (w->phys_cursor_type != NO_CURSOR)
5859 erase_phys_cursor (w);
5861 cursor_type = w->phys_cursor_type = NO_CURSOR;
5862 w->phys_cursor_width = -1;
5864 else
5866 w->phys_cursor_type = cursor_type;
5869 w->phys_cursor_on_p = true;
5871 /* If this is the active cursor, we need to track it with the
5872 system caret, so third party software like screen magnifiers
5873 and speech synthesizers can follow the cursor. */
5874 if (active_p)
5876 struct frame *f = XFRAME (WINDOW_FRAME (w));
5877 HWND hwnd = FRAME_W32_WINDOW (f);
5879 w32_system_caret_x
5880 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5881 w32_system_caret_y
5882 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5883 + glyph_row->ascent - w->phys_cursor_ascent);
5884 w32_system_caret_window = w;
5885 w32_system_caret_hdr_height = WINDOW_HEADER_LINE_HEIGHT (w);
5886 w32_system_caret_mode_height = WINDOW_MODE_LINE_HEIGHT (w);
5888 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5890 /* If the size of the active cursor changed, destroy the old
5891 system caret. */
5892 if (w32_system_caret_hwnd
5893 && (w32_system_caret_height != w->phys_cursor_height))
5894 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5896 w32_system_caret_height = w->phys_cursor_height;
5898 /* Move the system caret. */
5899 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5902 if (glyph_row->exact_window_width_line_p
5903 && (glyph_row->reversed_p
5904 ? (w->phys_cursor.hpos < 0)
5905 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
5907 glyph_row->cursor_in_fringe_p = true;
5908 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
5909 return;
5912 switch (cursor_type)
5914 case HOLLOW_BOX_CURSOR:
5915 x_draw_hollow_cursor (w, glyph_row);
5916 break;
5918 case FILLED_BOX_CURSOR:
5919 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5920 break;
5922 case BAR_CURSOR:
5923 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5924 break;
5926 case HBAR_CURSOR:
5927 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5928 break;
5930 case NO_CURSOR:
5931 w->phys_cursor_width = 0;
5932 break;
5934 default:
5935 emacs_abort ();
5942 /* Icons. */
5944 bool
5945 x_bitmap_icon (struct frame *f, Lisp_Object icon)
5947 HANDLE main_icon;
5948 HANDLE small_icon = NULL;
5950 if (FRAME_W32_WINDOW (f) == 0)
5951 return 1;
5953 if (NILP (icon))
5954 main_icon = LoadIcon (hinst, EMACS_CLASS);
5955 else if (STRINGP (icon))
5957 /* Load the main icon from the named file. */
5958 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5959 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5960 /* Try to load a small icon to go with it. */
5961 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5962 GetSystemMetrics (SM_CXSMICON),
5963 GetSystemMetrics (SM_CYSMICON),
5964 LR_LOADFROMFILE);
5966 else if (SYMBOLP (icon))
5968 LPCTSTR name;
5970 if (EQ (icon, intern ("application")))
5971 name = (LPCTSTR) IDI_APPLICATION;
5972 else if (EQ (icon, intern ("hand")))
5973 name = (LPCTSTR) IDI_HAND;
5974 else if (EQ (icon, intern ("question")))
5975 name = (LPCTSTR) IDI_QUESTION;
5976 else if (EQ (icon, intern ("exclamation")))
5977 name = (LPCTSTR) IDI_EXCLAMATION;
5978 else if (EQ (icon, intern ("asterisk")))
5979 name = (LPCTSTR) IDI_ASTERISK;
5980 else if (EQ (icon, intern ("winlogo")))
5981 name = (LPCTSTR) IDI_WINLOGO;
5982 else
5983 return 1;
5985 main_icon = LoadIcon (NULL, name);
5987 else
5988 return 1;
5990 if (main_icon == NULL)
5991 return 1;
5993 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5994 (LPARAM) main_icon);
5996 /* If there is a small icon that goes with it, set that too. */
5997 if (small_icon)
5998 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5999 (LPARAM) small_icon);
6001 return 0;
6005 /************************************************************************
6006 Handling X errors
6007 ************************************************************************/
6009 /* Display Error Handling functions not used on W32. Listing them here
6010 helps diff stay in step when comparing w32term.c with xterm.c.
6012 x_error_catcher (display, error)
6013 x_catch_errors (dpy)
6014 x_catch_errors_unwind (old_val)
6015 x_check_errors (dpy, format)
6016 x_fully_uncatch_errors ()
6017 x_had_errors_p (dpy)
6018 x_clear_errors (dpy)
6019 x_uncatch_errors (dpy, count)
6020 x_trace_wire ()
6021 x_connection_signal (signalnum)
6022 x_connection_closed (dpy, error_message)
6023 x_error_quitter (display, error)
6024 x_error_handler (display, error)
6025 x_io_error_quitter (display)
6030 /* Changing the font of the frame. */
6032 Lisp_Object
6033 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
6035 struct font *font = XFONT_OBJECT (font_object);
6036 int unit, font_ascent, font_descent;
6038 if (fontset < 0)
6039 fontset = fontset_from_font (font_object);
6040 FRAME_FONTSET (f) = fontset;
6041 if (FRAME_FONT (f) == font)
6042 /* This font is already set in frame F. There's nothing more to
6043 do. */
6044 return font_object;
6046 FRAME_FONT (f) = font;
6047 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
6048 FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
6049 get_font_ascent_descent (font, &font_ascent, &font_descent);
6050 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
6052 /* Compute number of scrollbar columns. */
6053 unit = FRAME_COLUMN_WIDTH (f);
6054 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6055 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6056 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
6057 else
6059 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
6060 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) =
6061 FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
6064 /* Now make the frame display the given font. */
6065 if (FRAME_X_WINDOW (f) != 0)
6067 /* Don't change the size of a tip frame; there's no point in
6068 doing it because it's done in Fx_show_tip, and it leads to
6069 problems because the tip frame has no widget. */
6070 if (!FRAME_TOOLTIP_P (f))
6071 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
6072 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
6073 false, Qfont);
6076 /* X version sets font of input methods here also. */
6078 return font_object;
6082 /***********************************************************************
6083 TODO: W32 Input Methods
6084 ***********************************************************************/
6085 /* Listing missing functions from xterm.c helps diff stay in step.
6087 xim_destroy_callback (xim, client_data, call_data)
6088 xim_open_dpy (dpyinfo, resource_name)
6089 struct xim_inst_t
6090 xim_instantiate_callback (display, client_data, call_data)
6091 xim_initialize (dpyinfo, resource_name)
6092 xim_close_dpy (dpyinfo)
6097 /* Calculate the absolute position in frame F
6098 from its current recorded position values and gravity. */
6100 static void
6101 x_calc_absolute_position (struct frame *f)
6103 int flags = f->size_hint_flags;
6105 /* The sum of the widths of the frame's left and right borders, and
6106 the sum of the heights of the frame's top and bottom borders (in
6107 pixels) drawn by Windows. */
6108 unsigned int left_right_borders_width, top_bottom_borders_height;
6110 /* Try to get the actual values of these two variables. We compute
6111 the border width (height) by subtracting the width (height) of
6112 the frame's client area from the width (height) of the frame's
6113 entire window. */
6114 WINDOWPLACEMENT wp = { 0 };
6115 RECT client_rect = { 0 };
6117 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
6118 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
6120 left_right_borders_width =
6121 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
6122 (client_rect.right - client_rect.left);
6124 top_bottom_borders_height =
6125 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
6126 (client_rect.bottom - client_rect.top);
6128 else
6130 /* Use sensible default values. */
6131 left_right_borders_width = 8;
6132 top_bottom_borders_height = 32;
6135 /* With multiple monitors, we can legitimately get negative
6136 coordinates (for monitors above or to the left of the primary
6137 monitor). Find the display origin to ensure negative positions
6138 are computed correctly (Bug#21173). */
6139 int display_left = 0;
6140 int display_top = 0;
6141 struct frame *p = FRAME_PARENT_FRAME (f);
6143 if (!p && flags & (XNegative | YNegative))
6145 Lisp_Object list;
6147 list = Fw32_display_monitor_attributes_list (Qnil);
6148 while (CONSP (list))
6150 Lisp_Object attributes = CAR(list);
6151 Lisp_Object geometry;
6152 Lisp_Object monitor_left, monitor_top;
6154 list = CDR(list);
6156 geometry = Fassoc (Qgeometry, attributes, Qnil);
6157 if (!NILP (geometry))
6159 monitor_left = Fnth (make_number (1), geometry);
6160 monitor_top = Fnth (make_number (2), geometry);
6162 display_left = min (display_left, XINT (monitor_left));
6163 display_top = min (display_top, XINT (monitor_top));
6168 /* Treat negative positions as relative to the rightmost bottommost
6169 position that fits on the screen or parent frame.
6171 I see no need for subtracting 1 from the border widths - is there
6172 any on the remaining platforms? Here these subtractions did put
6173 the last pixel line/column of a frame off-display when, for
6174 example, a (set-frame-parameter nil 'left '(- 0)) specification was
6175 used - martin 20017-05-05. */
6176 if (flags & XNegative)
6178 if (p)
6179 f->left_pos = (FRAME_PIXEL_WIDTH (p)
6180 - FRAME_PIXEL_WIDTH (f)
6181 + f->left_pos
6182 - left_right_borders_width);
6183 else
6184 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
6185 + display_left
6186 - FRAME_PIXEL_WIDTH (f)
6187 + f->left_pos
6188 - left_right_borders_width);
6191 if (flags & YNegative)
6193 if (p)
6194 f->top_pos = (FRAME_PIXEL_HEIGHT (p)
6195 - FRAME_PIXEL_HEIGHT (f)
6196 + f->top_pos
6197 - top_bottom_borders_height);
6198 else
6199 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
6200 + display_top
6201 - FRAME_PIXEL_HEIGHT (f)
6202 + f->top_pos
6203 - top_bottom_borders_height);
6206 /* The left_pos and top_pos are now relative to the top and left
6207 screen edges, so the flags should correspond. */
6208 f->size_hint_flags &= ~ (XNegative | YNegative);
6211 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
6212 to really change the position, and 0 when calling from
6213 x_make_frame_visible (in that case, XOFF and YOFF are the current
6214 position values). It is -1 when calling from x_set_frame_parameters,
6215 which means, do adjust for borders but don't change the gravity. */
6217 void
6218 x_set_offset (struct frame *f, register int xoff, register int yoff,
6219 int change_gravity)
6221 int modified_top, modified_left;
6223 if (change_gravity > 0)
6225 f->top_pos = yoff;
6226 f->left_pos = xoff;
6227 f->size_hint_flags &= ~ (XNegative | YNegative);
6228 if (xoff < 0)
6229 f->size_hint_flags |= XNegative;
6230 if (yoff < 0)
6231 f->size_hint_flags |= YNegative;
6232 f->win_gravity = NorthWestGravity;
6234 x_calc_absolute_position (f);
6236 block_input ();
6237 x_wm_set_size_hint (f, (long) 0, false);
6239 modified_left = f->left_pos;
6240 modified_top = f->top_pos;
6242 if (!FRAME_PARENT_FRAME (f))
6243 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6244 modified_left, modified_top,
6245 0, 0,
6246 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6247 else
6248 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6249 modified_left, modified_top,
6250 0, 0,
6251 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6252 unblock_input ();
6255 static void
6256 w32fullscreen_hook (struct frame *f)
6258 if (FRAME_VISIBLE_P (f))
6260 HWND hwnd = FRAME_W32_WINDOW(f);
6261 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
6262 RECT rect;
6263 enum fullscreen_type prev_fsmode = FRAME_PREV_FSMODE (f);
6265 block_input();
6266 f->want_fullscreen &= ~FULLSCREEN_WAIT;
6268 if (FRAME_PREV_FSMODE (f) == FULLSCREEN_NONE)
6269 GetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
6271 if (FRAME_PREV_FSMODE (f) == FULLSCREEN_BOTH)
6273 if (!FRAME_UNDECORATED (f))
6274 SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
6275 SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
6277 else if (FRAME_PREV_FSMODE (f) == FULLSCREEN_HEIGHT
6278 || FRAME_PREV_FSMODE (f) == FULLSCREEN_WIDTH)
6279 SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
6281 FRAME_PREV_FSMODE (f) = f->want_fullscreen;
6283 if (f->want_fullscreen == FULLSCREEN_NONE)
6284 ShowWindow (hwnd, SW_SHOWNORMAL);
6285 else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
6287 if (prev_fsmode == FULLSCREEN_BOTH || prev_fsmode == FULLSCREEN_WIDTH
6288 || prev_fsmode == FULLSCREEN_HEIGHT)
6289 /* Make window normal since otherwise the subsequent
6290 maximization might fail in some cases. */
6291 ShowWindow (hwnd, SW_SHOWNORMAL);
6292 ShowWindow (hwnd, SW_MAXIMIZE);
6294 else if (f->want_fullscreen == FULLSCREEN_BOTH)
6296 int menu_bar_height = GetSystemMetrics (SM_CYMENU);
6298 w32_fullscreen_rect (hwnd, f->want_fullscreen,
6299 FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
6300 if (!FRAME_UNDECORATED (f))
6301 SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
6302 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
6303 rect.right - rect.left, rect.bottom - rect.top,
6304 SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
6305 change_frame_size
6306 (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, rect.right - rect.left),
6307 FRAME_PIXEL_TO_TEXT_HEIGHT (f, (rect.bottom - rect.top
6308 - menu_bar_height)),
6309 0, 1, 0, 1);
6311 else
6313 ShowWindow (hwnd, SW_SHOWNORMAL);
6314 w32_fullscreen_rect (hwnd, f->want_fullscreen,
6315 FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
6316 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
6317 rect.right - rect.left, rect.bottom - rect.top, 0);
6319 if (f->want_fullscreen == FULLSCREEN_WIDTH)
6321 int border_width = GetSystemMetrics (SM_CXFRAME);
6323 change_frame_size
6324 (f, (FRAME_PIXEL_TO_TEXT_WIDTH
6325 (f, rect.right - rect.left - 2 * border_width)),
6326 0, 0, 1, 0, 1);
6328 else
6330 int border_height = GetSystemMetrics (SM_CYFRAME);
6331 /* Won't work for wrapped menu bar. */
6332 int menu_bar_height = GetSystemMetrics (SM_CYMENU);
6333 int title_height = GetSystemMetrics (SM_CYCAPTION);
6335 change_frame_size
6336 (f, 0, (FRAME_PIXEL_TO_TEXT_HEIGHT
6337 (f, rect.bottom - rect.top - 2 * border_height
6338 - title_height - menu_bar_height)),
6339 0, 1, 0, 1);
6343 f->want_fullscreen = FULLSCREEN_NONE;
6344 unblock_input ();
6346 if (f->want_fullscreen == FULLSCREEN_BOTH
6347 || f->want_fullscreen == FULLSCREEN_WIDTH
6348 || f->want_fullscreen == FULLSCREEN_HEIGHT)
6349 do_pending_window_change (0);
6352 else
6353 f->want_fullscreen |= FULLSCREEN_WAIT;
6356 /* Call this to change the size of frame F's x-window.
6357 If CHANGE_GRAVITY, change to top-left-corner window gravity
6358 for this size change and subsequent size changes.
6359 Otherwise we leave the window gravity unchanged. */
6361 void
6362 x_set_window_size (struct frame *f, bool change_gravity,
6363 int width, int height, bool pixelwise)
6365 int pixelwidth, pixelheight;
6366 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
6367 RECT rect;
6368 MENUBARINFO info;
6369 int menu_bar_height;
6371 block_input ();
6373 /* Get the height of the menu bar here. It's used below to detect
6374 whether the menu bar is wrapped. It's also used to specify the
6375 third argument for AdjustWindowRect. See bug#22105. */
6376 info.cbSize = sizeof (info);
6377 info.rcBar.top = info.rcBar.bottom = 0;
6378 GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
6379 menu_bar_height = info.rcBar.bottom - info.rcBar.top;
6381 if (pixelwise)
6383 pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
6384 pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
6386 else
6388 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
6389 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
6392 if (w32_add_wrapped_menu_bar_lines)
6394 /* When the menu bar wraps sending a SetWindowPos shrinks the
6395 height of the frame then the wrapped menu bar lines are not
6396 accounted for (Bug#15174 and Bug#18720). Here we add these
6397 extra lines to the frame height. */
6398 int default_menu_bar_height;
6400 /* Why is (apparently) SM_CYMENUSIZE needed here instead of
6401 SM_CYMENU ?? */
6402 default_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
6404 if ((default_menu_bar_height > 0)
6405 && (menu_bar_height > default_menu_bar_height)
6406 && ((menu_bar_height % default_menu_bar_height) == 0))
6407 pixelheight = pixelheight + menu_bar_height - default_menu_bar_height;
6410 f->win_gravity = NorthWestGravity;
6411 x_wm_set_size_hint (f, (long) 0, false);
6413 rect.left = rect.top = 0;
6414 rect.right = pixelwidth;
6415 rect.bottom = pixelheight;
6417 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, menu_bar_height > 0);
6419 if (!(f->after_make_frame)
6420 && !(f->want_fullscreen & FULLSCREEN_WAIT)
6421 && FRAME_VISIBLE_P (f))
6423 RECT window_rect;
6425 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
6427 if (EQ (fullscreen, Qmaximized)
6428 || EQ (fullscreen, Qfullboth)
6429 || EQ (fullscreen, Qfullwidth))
6431 rect.left = window_rect.left;
6432 rect.right = window_rect.right;
6433 pixelwidth = 0;
6435 if (EQ (fullscreen, Qmaximized)
6436 || EQ (fullscreen, Qfullboth)
6437 || EQ (fullscreen, Qfullheight))
6439 rect.top = window_rect.top;
6440 rect.bottom = window_rect.bottom;
6441 pixelheight = 0;
6445 if (pixelwidth > 0 || pixelheight > 0)
6447 frame_size_history_add
6448 (f, Qx_set_window_size_1, width, height,
6449 list2 (Fcons (make_number (pixelwidth),
6450 make_number (pixelheight)),
6451 Fcons (make_number (rect.right - rect.left),
6452 make_number (rect.bottom - rect.top))));
6454 if (!FRAME_PARENT_FRAME (f))
6455 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6456 0, 0,
6457 rect.right - rect.left,
6458 rect.bottom - rect.top,
6459 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
6460 else
6461 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6462 0, 0,
6463 rect.right - rect.left,
6464 rect.bottom - rect.top,
6465 SWP_NOMOVE | SWP_NOACTIVATE);
6467 change_frame_size (f,
6468 ((pixelwidth == 0)
6469 ? 0 : FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth)),
6470 ((pixelheight == 0)
6471 ? 0 : FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)),
6472 0, 1, 0, 1);
6473 SET_FRAME_GARBAGED (f);
6475 /* If cursor was outside the new size, mark it as off. */
6476 mark_window_cursors_off (XWINDOW (f->root_window));
6478 /* Clear out any recollection of where the mouse highlighting was,
6479 since it might be in a place that's outside the new frame size.
6480 Actually checking whether it is outside is a pain in the neck,
6481 so don't try--just let the highlighting be done afresh with new
6482 size. */
6483 cancel_mouse_face (f);
6486 unblock_input ();
6488 do_pending_window_change (false);
6491 /* Mouse warping. */
6493 void
6494 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
6496 UINT trail_num = 0;
6497 BOOL ret = false;
6498 RECT rect;
6499 POINT pt;
6501 block_input ();
6503 GetClientRect (FRAME_W32_WINDOW (f), &rect);
6504 pt.x = rect.left + pix_x;
6505 pt.y = rect.top + pix_y;
6506 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
6508 /* When "mouse trails" are in effect, moving the mouse cursor
6509 sometimes leaves behind an annoying "ghost" of the pointer.
6510 Avoid that by momentarily switching off mouse trails. */
6511 if (os_subtype == OS_NT
6512 && w32_major_version + w32_minor_version >= 6)
6513 ret = SystemParametersInfo (SPI_GETMOUSETRAILS, 0, &trail_num, 0);
6514 SetCursorPos (pt.x, pt.y);
6515 if (ret)
6516 SystemParametersInfo (SPI_SETMOUSETRAILS, trail_num, NULL, 0);
6518 unblock_input ();
6522 /* Focus shifting, raising and lowering. */
6524 /* The NOACTIVATE argument has no effect on Windows. According to the
6525 Windows API: An application cannot activate an inactive window
6526 without also bringing it to the top of the Z order. */
6528 void
6529 x_focus_frame (struct frame *f, bool noactivate)
6531 #if 0
6532 struct w32_display_info *dpyinfo = &one_w32_display_info;
6533 #endif
6535 /* Give input focus to frame. */
6536 block_input ();
6537 #if 0
6538 /* Try not to change its Z-order if possible. */
6539 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
6540 my_set_focus (f, FRAME_W32_WINDOW (f));
6541 else
6542 #endif
6543 my_set_foreground_window (FRAME_W32_WINDOW (f));
6544 unblock_input ();
6547 /* Raise frame F. */
6548 void
6549 x_raise_frame (struct frame *f)
6551 block_input ();
6553 /* Strictly speaking, raise-frame should only change the frame's Z
6554 order, leaving input focus unchanged. This is reasonable behavior
6555 on X where the usual policy is point-to-focus. However, this
6556 behavior would be very odd on Windows where the usual policy is
6557 click-to-focus.
6559 On X, if the mouse happens to be over the raised frame, it gets
6560 input focus anyway (so the window with focus will never be
6561 completely obscured) - if not, then just moving the mouse over it
6562 is sufficient to give it focus. On Windows, the user must actually
6563 click on the frame (preferably the title bar so as not to move
6564 point), which is more awkward. Also, no other Windows program
6565 raises a window to the top but leaves another window (possibly now
6566 completely obscured) with input focus.
6568 Because there is a system setting on Windows that allows the user
6569 to choose the point to focus policy, we make the strict semantics
6570 optional, but by default we grab focus when raising. */
6572 if (NILP (Vw32_grab_focus_on_raise))
6574 /* The obvious call to my_set_window_pos doesn't work if Emacs is
6575 not already the foreground application: the frame is raised
6576 above all other frames belonging to us, but not above the
6577 current top window. To achieve that, we have to resort to this
6578 more cumbersome method. */
6580 HDWP handle = BeginDeferWindowPos (2);
6581 if (handle)
6583 handle = DeferWindowPos (handle,
6584 FRAME_W32_WINDOW (f),
6585 HWND_TOP,
6586 0, 0, 0, 0,
6587 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
6588 if (handle)
6590 handle = DeferWindowPos (handle,
6591 GetForegroundWindow (),
6592 FRAME_W32_WINDOW (f),
6593 0, 0, 0, 0,
6594 SWP_NOSIZE | SWP_NOMOVE |
6595 SWP_NOACTIVATE);
6596 if (handle)
6597 EndDeferWindowPos (handle);
6601 else
6603 my_bring_window_to_top (FRAME_W32_WINDOW (f));
6606 unblock_input ();
6609 /* Lower frame F. */
6610 void
6611 x_lower_frame (struct frame *f)
6613 block_input ();
6614 my_set_window_pos (FRAME_W32_WINDOW (f),
6615 HWND_BOTTOM,
6616 0, 0, 0, 0,
6617 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
6618 unblock_input ();
6621 static void
6622 w32_frame_raise_lower (struct frame *f, bool raise_flag)
6624 if (! FRAME_W32_P (f))
6625 return;
6627 if (raise_flag)
6628 x_raise_frame (f);
6629 else
6630 x_lower_frame (f);
6633 /* Change of visibility. */
6635 /* This tries to wait until the frame is really visible, depending on
6636 the value of Vx_visible_frame_timeout.
6637 However, if the window manager asks the user where to position
6638 the frame, this will return before the user finishes doing that.
6639 The frame will not actually be visible at that time,
6640 but it will become visible later when the window manager
6641 finishes with it. */
6643 void
6644 x_make_frame_visible (struct frame *f)
6646 block_input ();
6648 x_set_bitmap_icon (f);
6650 if (! FRAME_VISIBLE_P (f))
6652 /* We test FRAME_GARBAGED_P here to make sure we don't
6653 call x_set_offset a second time
6654 if we get to x_make_frame_visible a second time
6655 before the window gets really visible. */
6656 if (! FRAME_ICONIFIED_P (f)
6657 && ! f->output_data.w32->asked_for_visible)
6659 if (!FRAME_PARENT_FRAME (f))
6661 RECT workarea_rect;
6662 RECT window_rect;
6664 /* Adjust vertical window position in order to avoid being
6665 covered by a taskbar placed at the bottom of the desktop. */
6666 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
6667 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
6668 if (window_rect.bottom > workarea_rect.bottom
6669 && window_rect.top > workarea_rect.top)
6670 f->top_pos = max (window_rect.top
6671 - window_rect.bottom + workarea_rect.bottom,
6672 workarea_rect.top);
6675 x_set_offset (f, f->left_pos, f->top_pos, 0);
6678 f->output_data.w32->asked_for_visible = 1;
6680 /* According to a report in emacs-devel 2008-06-03, SW_SHOWNORMAL
6681 causes unexpected behavior when unminimizing frames that were
6682 previously maximized. But only SW_SHOWNORMAL works properly for
6683 frames that were truely hidden (using make-frame-invisible), so
6684 we need it to avoid Bug#5482. It seems that iconified is only
6685 set for minimized windows that are still visible, so use that to
6686 determine the appropriate flag to pass ShowWindow. */
6687 my_show_window (f, FRAME_W32_WINDOW (f),
6688 FRAME_ICONIFIED_P (f)
6689 ? SW_RESTORE
6690 : FRAME_NO_FOCUS_ON_MAP (f)
6691 ? SW_SHOWNOACTIVATE
6692 : SW_SHOWNORMAL);
6695 if (!FLOATP (Vx_wait_for_event_timeout))
6696 return;
6698 /* Synchronize to ensure Emacs knows the frame is visible
6699 before we do anything else. We do this loop with input not blocked
6700 so that incoming events are handled. */
6702 Lisp_Object frame;
6703 double timeout = XFLOAT_DATA (Vx_wait_for_event_timeout);
6704 double start_time = XFLOAT_DATA (Ffloat_time (Qnil));
6706 /* This must come after we set COUNT. */
6707 unblock_input ();
6709 XSETFRAME (frame, f);
6711 /* Wait until the frame is visible. Process X events until a
6712 MapNotify event has been seen, or until we think we won't get a
6713 MapNotify at all.. */
6714 while (timeout > (XFLOAT_DATA (Ffloat_time (Qnil)) - start_time) &&
6715 !FRAME_VISIBLE_P (f))
6717 /* Force processing of queued events. */
6718 /* TODO: x_sync equivalent? */
6720 /* Machines that do polling rather than SIGIO have been observed
6721 to go into a busy-wait here. So we'll fake an alarm signal
6722 to let the handler know that there's something to be read.
6723 We used to raise a real alarm, but it seems that the handler
6724 isn't always enabled here. This is probably a bug. */
6725 if (input_polling_used ())
6727 /* It could be confusing if a real alarm arrives while processing
6728 the fake one. Turn it off and let the handler reset it. */
6729 int old_poll_suppress_count = poll_suppress_count;
6730 poll_suppress_count = 1;
6731 poll_for_input_1 ();
6732 poll_suppress_count = old_poll_suppress_count;
6738 /* Change from mapped state to withdrawn state. */
6740 /* Make the frame visible (mapped and not iconified). */
6742 void
6743 x_make_frame_invisible (struct frame *f)
6745 /* Don't keep the highlight on an invisible frame. */
6746 if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
6747 FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
6749 block_input ();
6751 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
6753 /* We can't distinguish this from iconification
6754 just by the event that we get from the server.
6755 So we can't win using the usual strategy of letting
6756 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6757 and synchronize with the server to make sure we agree. */
6758 SET_FRAME_VISIBLE (f, 0);
6759 SET_FRAME_ICONIFIED (f, false);
6761 unblock_input ();
6764 /* Change window state from mapped to iconified. */
6766 void
6767 x_iconify_frame (struct frame *f)
6769 /* Don't keep the highlight on an invisible frame. */
6770 if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
6771 FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
6773 if (FRAME_ICONIFIED_P (f))
6774 return;
6776 block_input ();
6778 x_set_bitmap_icon (f);
6780 /* Simulate the user minimizing the frame. */
6781 SendMessageTimeout (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0,
6782 0, 6000, NULL);
6784 SET_FRAME_VISIBLE (f, 0);
6785 SET_FRAME_ICONIFIED (f, true);
6787 unblock_input ();
6791 /* Free X resources of frame F. */
6793 void
6794 x_free_frame_resources (struct frame *f)
6796 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
6797 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
6799 block_input ();
6801 /* We must free faces before destroying windows because some
6802 font-driver (e.g. xft) access a window while finishing a
6803 face. */
6804 free_frame_faces (f);
6806 if (FRAME_W32_WINDOW (f))
6807 my_destroy_window (f, FRAME_W32_WINDOW (f));
6809 free_frame_menubar (f);
6811 xfree (f->output_data.w32);
6812 f->output_data.w32 = NULL;
6814 if (f == dpyinfo->w32_focus_frame)
6815 dpyinfo->w32_focus_frame = 0;
6816 if (f == dpyinfo->w32_focus_event_frame)
6817 dpyinfo->w32_focus_event_frame = 0;
6818 if (f == dpyinfo->x_highlight_frame)
6819 dpyinfo->x_highlight_frame = 0;
6820 if (f == hlinfo->mouse_face_mouse_frame)
6821 reset_mouse_highlight (hlinfo);
6823 unblock_input ();
6827 /* Destroy the window of frame F. */
6828 static void
6829 x_destroy_window (struct frame *f)
6831 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
6833 x_free_frame_resources (f);
6834 dpyinfo->reference_count--;
6838 /* Setting window manager hints. */
6840 /* Set the normal size hints for the window manager, for frame F.
6841 FLAGS is the flags word to use--or 0 meaning preserve the flags
6842 that the window now has.
6843 If USER_POSITION, set the USPosition
6844 flag (this is useful when FLAGS is 0). */
6845 void
6846 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
6848 Window window = FRAME_W32_WINDOW (f);
6850 enter_crit ();
6852 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
6853 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
6854 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
6855 SetWindowLong (window, WND_VSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
6856 SetWindowLong (window, WND_HSCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_HEIGHT (f));
6858 leave_crit ();
6861 /***********************************************************************
6862 Fonts
6863 ***********************************************************************/
6865 #ifdef GLYPH_DEBUG
6867 /* Check that FONT is valid on frame F. It is if it can be found in F's
6868 font table. */
6870 static void
6871 x_check_font (struct frame *f, struct font *font)
6873 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
6874 if (font->driver->check)
6875 eassert (font->driver->check (f, font) == 0);
6878 #endif /* GLYPH_DEBUG */
6880 /* Show hourglass cursor on frame F. */
6882 static void
6883 w32_show_hourglass (struct frame *f)
6885 if (!menubar_in_use && !current_popup_menu)
6887 struct w32_output *w32 = FRAME_X_OUTPUT (f);
6889 w32->hourglass_p = 1;
6890 SetCursor (w32->hourglass_cursor);
6894 /* Hide hourglass cursor on frame F. */
6896 static void
6897 w32_hide_hourglass (struct frame *f)
6899 struct w32_output *w32 = FRAME_X_OUTPUT (f);
6901 w32->hourglass_p = 0;
6902 if (f->pointer_invisible)
6903 SetCursor (NULL);
6904 else
6905 SetCursor (w32->current_cursor);
6908 /* FIXME: old code did that, but I don't know why. Anyway,
6909 this is used for non-GUI frames (see cancel_hourglass). */
6911 void
6912 w32_arrow_cursor (void)
6914 SetCursor (w32_load_cursor (IDC_ARROW));
6917 static void
6918 w32_toggle_invisible_pointer (struct frame *f, bool invisible)
6920 block_input ();
6922 if (f->pointer_invisible != invisible)
6924 f->pointer_invisible = invisible;
6925 w32_define_cursor (FRAME_W32_WINDOW (f),
6926 f->output_data.w32->current_cursor);
6929 unblock_input ();
6932 /***********************************************************************
6933 Initialization
6934 ***********************************************************************/
6936 static int w32_initialized = 0;
6938 void
6939 w32_initialize_display_info (Lisp_Object display_name)
6941 struct w32_display_info *dpyinfo = &one_w32_display_info;
6943 memset (dpyinfo, 0, sizeof (*dpyinfo));
6945 dpyinfo->name_list_element = Fcons (display_name, Qnil);
6946 if (STRINGP (Vsystem_name))
6948 dpyinfo->w32_id_name = xmalloc (SCHARS (Vinvocation_name)
6949 + SCHARS (Vsystem_name) + 2);
6950 sprintf (dpyinfo->w32_id_name, "%s@%s",
6951 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6953 else
6954 dpyinfo->w32_id_name = xlispstrdup (Vinvocation_name);
6956 /* Default Console mode values - overridden when running in GUI mode
6957 with values obtained from system metrics. */
6958 dpyinfo->resx = 1;
6959 dpyinfo->resy = 1;
6960 dpyinfo->n_planes = 1;
6961 dpyinfo->n_cbits = 4;
6962 dpyinfo->n_fonts = 0;
6963 dpyinfo->smallest_font_height = 1;
6964 dpyinfo->smallest_char_width = 1;
6965 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6966 dpyinfo->horizontal_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6967 /* TODO: dpyinfo->gray */
6969 reset_mouse_highlight (&dpyinfo->mouse_highlight);
6972 /* Create an xrdb-style database of resources to supersede registry settings.
6973 The database is just a concatenation of C strings, finished by an additional
6974 \0. The strings are submitted to some basic normalization, so
6976 [ *]option[ *]:[ *]value...
6978 becomes
6980 option:value...
6982 but any whitespace following value is not removed. */
6984 static char *
6985 w32_make_rdb (char *xrm_option)
6987 char *buffer = xmalloc (strlen (xrm_option) + 2);
6988 char *current = buffer;
6989 char ch;
6990 int in_option = 1;
6991 int before_value = 0;
6993 do {
6994 ch = *xrm_option++;
6996 if (ch == '\n')
6998 *current++ = '\0';
6999 in_option = 1;
7000 before_value = 0;
7002 else if (ch != ' ')
7004 *current++ = ch;
7005 if (in_option && (ch == ':'))
7007 in_option = 0;
7008 before_value = 1;
7010 else if (before_value)
7012 before_value = 0;
7015 else if (!(in_option || before_value))
7017 *current++ = ch;
7019 } while (ch);
7021 *current = '\0';
7023 return buffer;
7026 extern frame_parm_handler w32_frame_parm_handlers[];
7028 static struct redisplay_interface w32_redisplay_interface =
7030 w32_frame_parm_handlers,
7031 x_produce_glyphs,
7032 x_write_glyphs,
7033 x_insert_glyphs,
7034 x_clear_end_of_line,
7035 x_scroll_run,
7036 x_after_update_window_line,
7037 x_update_window_begin,
7038 x_update_window_end,
7039 0, /* flush_display */
7040 x_clear_window_mouse_face,
7041 x_get_glyph_overhangs,
7042 x_fix_overlapping_area,
7043 w32_draw_fringe_bitmap,
7044 w32_define_fringe_bitmap,
7045 w32_destroy_fringe_bitmap,
7046 w32_compute_glyph_string_overhangs,
7047 x_draw_glyph_string,
7048 w32_define_frame_cursor,
7049 w32_clear_frame_area,
7050 w32_draw_window_cursor,
7051 w32_draw_vertical_window_border,
7052 w32_draw_window_divider,
7053 w32_shift_glyphs_for_insert,
7054 w32_show_hourglass,
7055 w32_hide_hourglass
7058 static void x_delete_terminal (struct terminal *term);
7060 static struct terminal *
7061 w32_create_terminal (struct w32_display_info *dpyinfo)
7063 struct terminal *terminal;
7065 terminal = create_terminal (output_w32, &w32_redisplay_interface);
7067 terminal->display_info.w32 = dpyinfo;
7068 dpyinfo->terminal = terminal;
7070 /* MSVC does not type K&R functions with no arguments correctly, and
7071 so we must explicitly cast them. */
7072 terminal->clear_frame_hook = x_clear_frame;
7073 terminal->ins_del_lines_hook = x_ins_del_lines;
7074 terminal->delete_glyphs_hook = x_delete_glyphs;
7075 terminal->ring_bell_hook = w32_ring_bell;
7076 terminal->toggle_invisible_pointer_hook = w32_toggle_invisible_pointer;
7077 terminal->update_begin_hook = x_update_begin;
7078 terminal->update_end_hook = x_update_end;
7079 terminal->read_socket_hook = w32_read_socket;
7080 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
7081 terminal->mouse_position_hook = w32_mouse_position;
7082 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
7083 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
7084 terminal->fullscreen_hook = w32fullscreen_hook;
7085 terminal->menu_show_hook = w32_menu_show;
7086 terminal->popup_dialog_hook = w32_popup_dialog;
7087 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
7088 terminal->set_horizontal_scroll_bar_hook = w32_set_horizontal_scroll_bar;
7089 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
7090 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
7091 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
7092 terminal->delete_frame_hook = x_destroy_window;
7093 terminal->delete_terminal_hook = x_delete_terminal;
7094 /* Other hooks are NULL by default. */
7096 /* We don't yet support separate terminals on W32, so don't try to share
7097 keyboards between virtual terminals that are on the same physical
7098 terminal like X does. */
7099 terminal->kboard = allocate_kboard (Qw32);
7100 /* Don't let the initial kboard remain current longer than necessary.
7101 That would cause problems if a file loaded on startup tries to
7102 prompt in the mini-buffer. */
7103 if (current_kboard == initial_kboard)
7104 current_kboard = terminal->kboard;
7105 terminal->kboard->reference_count++;
7107 return terminal;
7110 static void
7111 x_delete_terminal (struct terminal *terminal)
7113 struct w32_display_info *dpyinfo = terminal->display_info.w32;
7115 /* Protect against recursive calls. delete_frame in
7116 delete_terminal calls us back when it deletes our last frame. */
7117 if (!terminal->name)
7118 return;
7120 block_input ();
7122 x_delete_display (dpyinfo);
7123 unblock_input ();
7126 struct w32_display_info *
7127 w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
7129 struct w32_display_info *dpyinfo;
7130 struct terminal *terminal;
7131 HDC hdc;
7133 block_input ();
7135 if (!w32_initialized)
7137 w32_initialize ();
7138 w32_initialized = 1;
7141 w32_initialize_display_info (display_name);
7143 dpyinfo = &one_w32_display_info;
7144 terminal = w32_create_terminal (dpyinfo);
7146 /* Set the name of the terminal. */
7147 terminal->name = xlispstrdup (display_name);
7149 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
7151 /* Put this display on the chain. */
7152 dpyinfo->next = x_display_list;
7153 x_display_list = dpyinfo;
7155 hdc = GetDC (NULL);
7157 dpyinfo->root_window = GetDesktopWindow ();
7158 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
7159 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
7160 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
7161 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
7162 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
7163 ReleaseDC (NULL, hdc);
7165 /* initialize palette with white and black */
7167 XColor color;
7168 w32_defined_color (0, "white", &color, 1);
7169 w32_defined_color (0, "black", &color, 1);
7172 #ifdef WINDOWSNT
7173 /* Add the default keyboard. When !WINDOWSNT, we're using the
7174 standard Emacs console handling machinery and don't need an
7175 explicit FD here. */
7176 add_keyboard_wait_descriptor (0);
7177 #elif CYGWIN
7178 /* /dev/windows wakes us up when we have a thread message pending. */
7179 add_keyboard_wait_descriptor (w32_message_fd);
7180 #endif
7182 /* Create Fringe Bitmaps and store them for later use.
7184 On W32, bitmaps are all unsigned short, as Windows requires
7185 bitmap data to be Word aligned. For some reason they are
7186 horizontally reflected compared to how they appear on X, so we
7187 need to bitswap and convert to unsigned shorts before creating
7188 the bitmaps. */
7189 w32_init_fringe (terminal->rif);
7191 unblock_input ();
7193 return dpyinfo;
7196 /* Get rid of display DPYINFO, assuming all frames are already gone. */
7197 void
7198 x_delete_display (struct w32_display_info *dpyinfo)
7200 /* FIXME: the only display info apparently can't be deleted. */
7201 /* free palette table */
7203 struct w32_palette_entry * plist;
7205 plist = dpyinfo->color_list;
7206 while (plist)
7208 struct w32_palette_entry * pentry = plist;
7209 plist = plist->next;
7210 xfree (pentry);
7212 dpyinfo->color_list = NULL;
7213 if (dpyinfo->palette)
7214 DeleteObject (dpyinfo->palette);
7216 w32_reset_fringes ();
7220 /* Set up use of W32. */
7222 void
7223 w32_init_main_thread (void)
7225 dwMainThreadId = GetCurrentThreadId ();
7226 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
7227 GetCurrentProcess (), &hMainThread, 0, TRUE,
7228 DUPLICATE_SAME_ACCESS);
7233 DWORD WINAPI w32_msg_worker (void * arg);
7235 static void
7236 w32_initialize (void)
7238 HANDLE shell;
7239 HRESULT (WINAPI * set_user_model) (const wchar_t * id);
7241 baud_rate = 19200;
7243 w32_system_caret_hwnd = NULL;
7244 w32_system_caret_height = 0;
7245 w32_system_caret_x = 0;
7246 w32_system_caret_y = 0;
7248 /* On Windows 7 and later, we need to set the user model ID
7249 to associate emacsclient launched files with Emacs frames
7250 in the UI. */
7251 shell = GetModuleHandle ("shell32.dll");
7252 if (shell)
7254 set_user_model
7255 = (void *) GetProcAddress (shell,
7256 "SetCurrentProcessExplicitAppUserModelID");
7258 /* If the function is defined, then we are running on Windows 7
7259 or newer, and the UI uses this to group related windows
7260 together. Since emacs, runemacs, emacsclient are related, we
7261 want them grouped even though the executables are different,
7262 so we need to set a consistent ID between them. */
7263 if (set_user_model)
7264 set_user_model (L"GNU.Emacs");
7267 #ifdef CYGWIN
7268 if ((w32_message_fd = emacs_open ("/dev/windows", O_RDWR, 0)) == -1)
7269 fatal ("opening /dev/windows: %s", strerror (errno));
7270 #endif /* CYGWIN */
7272 /* Initialize w32_use_visible_system_caret based on whether a screen
7273 reader is in use. */
7274 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
7275 &w32_use_visible_system_caret, 0))
7276 w32_use_visible_system_caret = 0;
7278 any_help_event_p = 0;
7280 /* Initialize input mode: interrupt_input off, no flow control, allow
7281 8 bit character input, standard quit char. */
7282 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
7285 LCID input_locale_id = LOWORD (GetKeyboardLayout (0));
7286 w32_keyboard_codepage = codepage_for_locale (input_locale_id);
7289 /* Create the window thread - it will terminate itself when the app
7290 terminates */
7291 init_crit ();
7293 /* Wait for thread to start */
7295 MSG msg;
7297 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
7299 hWindowsThread = CreateThread (NULL, 0,
7300 w32_msg_worker,
7301 0, 0, &dwWindowsThreadId);
7303 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
7306 /* It is desirable that mainThread should have the same notion of
7307 focus window and active window as windowsThread. Unfortunately, the
7308 following call to AttachThreadInput, which should do precisely what
7309 we need, causes major problems when Emacs is linked as a console
7310 program. Unfortunately, we have good reasons for doing that, so
7311 instead we need to send messages to windowsThread to make some API
7312 calls for us (ones that affect, or depend on, the active/focus
7313 window state.) */
7314 #ifdef ATTACH_THREADS
7315 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
7316 #endif
7318 /* Dynamically link to optional system components. */
7320 HMODULE user_lib = GetModuleHandle ("user32.dll");
7322 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
7324 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
7326 #undef LOAD_PROC
7328 /* Ensure scrollbar handles are at least 5 pixels. */
7329 vertical_scroll_bar_min_handle = 5;
7330 horizontal_scroll_bar_min_handle = 5;
7332 /* For either kind of scroll bar, take account of the arrows; these
7333 effectively form the border of the main scroll bar range. */
7334 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
7335 = GetSystemMetrics (SM_CYVSCROLL);
7336 horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
7337 = GetSystemMetrics (SM_CYHSCROLL);
7341 void
7342 syms_of_w32term (void)
7344 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
7346 DEFSYM (Qadded, "added");
7347 DEFSYM (Qremoved, "removed");
7348 DEFSYM (Qmodified, "modified");
7349 DEFSYM (Qrenamed_from, "renamed-from");
7350 DEFSYM (Qrenamed_to, "renamed-to");
7352 DEFVAR_LISP ("x-wait-for-event-timeout", Vx_wait_for_event_timeout,
7353 doc: /* SKIP: real doc in xterm.c. */);
7354 Vx_wait_for_event_timeout = make_float (0.1);
7356 DEFVAR_INT ("w32-num-mouse-buttons",
7357 w32_num_mouse_buttons,
7358 doc: /* Number of physical mouse buttons. */);
7359 w32_num_mouse_buttons = 2;
7361 DEFVAR_LISP ("w32-swap-mouse-buttons",
7362 Vw32_swap_mouse_buttons,
7363 doc: /* Swap the mapping of middle and right mouse buttons.
7364 When nil, middle button is mouse-2 and right button is mouse-3. */);
7365 Vw32_swap_mouse_buttons = Qnil;
7367 DEFVAR_LISP ("w32-grab-focus-on-raise",
7368 Vw32_grab_focus_on_raise,
7369 doc: /* Raised frame grabs input focus.
7370 When t, `raise-frame' grabs input focus as well. This fits well
7371 with the normal Windows click-to-focus policy, but might not be
7372 desirable when using a point-to-focus policy. */);
7373 Vw32_grab_focus_on_raise = Qt;
7375 DEFVAR_LISP ("w32-capslock-is-shiftlock",
7376 Vw32_capslock_is_shiftlock,
7377 doc: /* Apply CapsLock state to non character input keys.
7378 When nil, CapsLock only affects normal character input keys. */);
7379 Vw32_capslock_is_shiftlock = Qnil;
7381 DEFVAR_LISP ("w32-recognize-altgr",
7382 Vw32_recognize_altgr,
7383 doc: /* Recognize right-alt and left-ctrl as AltGr.
7384 When nil, the right-alt and left-ctrl key combination is
7385 interpreted normally. */);
7386 Vw32_recognize_altgr = Qt;
7388 DEFVAR_BOOL ("w32-use-visible-system-caret",
7389 w32_use_visible_system_caret,
7390 doc: /* Flag to make the system caret visible.
7391 When this is non-nil, Emacs will indicate the position of point by
7392 using the system caret instead of drawing its own cursor. Some screen
7393 reader software does not track the system cursor properly when it is
7394 invisible, and gets confused by Emacs drawing its own cursor, so this
7395 variable is initialized to t when Emacs detects that screen reader
7396 software is running as it starts up.
7398 When this variable is set, other variables affecting the appearance of
7399 the cursor have no effect. */);
7401 w32_use_visible_system_caret = 0;
7403 /* We don't yet support this, but defining this here avoids whining
7404 from cus-start.el and other places, like "M-x set-variable". */
7405 DEFVAR_BOOL ("x-use-underline-position-properties",
7406 x_use_underline_position_properties,
7407 doc: /* SKIP: real doc in xterm.c. */);
7408 x_use_underline_position_properties = 0;
7409 DEFSYM (Qx_use_underline_position_properties,
7410 "x-use-underline-position-properties");
7412 DEFVAR_BOOL ("x-underline-at-descent-line",
7413 x_underline_at_descent_line,
7414 doc: /* SKIP: real doc in xterm.c. */);
7415 x_underline_at_descent_line = 0;
7416 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
7418 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
7419 doc: /* SKIP: real doc in xterm.c. */);
7420 Vx_toolkit_scroll_bars = Qt;
7422 DEFVAR_BOOL ("w32-unicode-filenames",
7423 w32_unicode_filenames,
7424 doc: /* Non-nil means use Unicode APIs when passing file names to the OS.
7425 A value of nil means file names passed to the OS APIs and returned
7426 from those APIs are encoded/decoded using the ANSI codepage
7427 specified by `file-name-coding-system'.
7429 This variable is set to non-nil by default when Emacs runs on Windows
7430 systems of the NT family, including W2K, XP, Vista, Windows 7 and
7431 Windows 8. It is set to nil on Windows 9X. */);
7432 if (os_subtype == OS_9X)
7433 w32_unicode_filenames = 0;
7434 else
7435 w32_unicode_filenames = 1;
7438 /* FIXME: The following variable will be (hopefully) removed
7439 before Emacs 25.1 gets released. */
7441 DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines",
7442 w32_add_wrapped_menu_bar_lines,
7443 doc: /* Non-nil means frame resizing accounts for wrapped menu bar lines.
7444 A value of nil means frame resizing does not add the height of wrapped
7445 menu bar lines when sending a frame resize request to the Windows API.
7446 This usually means that the resulting frame height is off by the number
7447 of wrapped menu bar lines. If this is non-nil, Emacs adds the height of
7448 wrapped menu bar lines when sending frame resize requests to the Windows
7449 API. */);
7450 w32_add_wrapped_menu_bar_lines = 1;
7452 /* Tell Emacs about this window system. */
7453 Fprovide (Qw32, Qnil);