Merge from trunk.
[emacs.git] / src / w32term.c
blobe53fa5e7756d3cb60c90344bf6f070a0cffe3e7b
1 /* Implementation of GUI terminal on the Microsoft Windows API.
3 Copyright (C) 1989, 1993-2012 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
10 (at 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 <http://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"
27 #include "systty.h"
28 #include "systime.h"
30 #include <ctype.h>
31 #include <errno.h>
32 #include <sys/stat.h>
33 #include <imm.h>
35 #include "charset.h"
36 #include "character.h"
37 #include "coding.h"
38 #include "ccl.h"
39 #include "frame.h"
40 #include "dispextern.h"
41 #include "fontset.h"
42 #include "termhooks.h"
43 #include "termopts.h"
44 #include "termchar.h"
45 #include "disptab.h"
46 #include "buffer.h"
47 #include "window.h"
48 #include "keyboard.h"
49 #include "intervals.h"
50 #include "process.h"
51 #include "atimer.h"
52 #include "keymap.h"
54 #ifdef WINDOWSNT
55 #include "w32heap.h"
56 #endif
58 #ifndef WINDOWSNT
59 #include <io.h> /* for get_osfhandle */
60 #endif
62 #include <shellapi.h>
64 #include "font.h"
65 #include "w32font.h"
67 /* Fringe bitmaps. */
69 static int max_fringe_bmp = 0;
70 static HBITMAP *fringe_bmp = 0;
72 /* Temporary variables for w32_read_socket. */
74 static int last_mousemove_x = 0;
75 static int last_mousemove_y = 0;
77 /* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't. */
78 #ifndef GET_WHEEL_DELTA_WPARAM
79 #define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
80 #endif
82 /* Non-zero means that a HELP_EVENT has been generated since Emacs
83 start. */
85 static int any_help_event_p;
87 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88 static Lisp_Object last_window;
90 extern unsigned int msh_mousewheel;
92 extern void free_frame_menubar (struct frame *);
94 extern int w32_codepage_for_font (char *fontname);
95 extern Cursor w32_load_cursor (LPCTSTR name);
97 #define x_any_window_to_frame x_window_to_frame
98 #define x_top_window_to_frame x_window_to_frame
101 /* This is display since w32 does not support multiple ones. */
102 struct w32_display_info one_w32_display_info;
103 struct w32_display_info *x_display_list;
105 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
106 one for each element of w32_display_list and in the same order.
107 NAME is the name of the frame.
108 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
109 Lisp_Object w32_display_name_list;
112 #if _WIN32_WINNT < 0x0500
113 /* Pre Windows 2000, this was not available, but define it here so
114 that Emacs compiled on such a platform will run on newer versions. */
116 typedef struct tagWCRANGE
118 WCHAR wcLow;
119 USHORT cGlyphs;
120 } WCRANGE;
122 typedef struct tagGLYPHSET
124 DWORD cbThis;
125 DWORD flAccel;
126 DWORD cGlyphsSupported;
127 DWORD cRanges;
128 WCRANGE ranges[1];
129 } GLYPHSET;
131 #endif /* compiling for pre-Win2k */
133 /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
134 BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
136 #ifndef LWA_ALPHA
137 #define LWA_ALPHA 0x02
138 #endif
139 /* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
140 later targets by MSVC headers. */
141 #ifndef WS_EX_LAYERED
142 #define WS_EX_LAYERED 0x80000
143 #endif
145 /* This is a frame waiting to be autoraised, within w32_read_socket. */
146 struct frame *pending_autoraise_frame;
148 /* The handle of the frame that currently owns the system caret. */
149 HWND w32_system_caret_hwnd;
150 int w32_system_caret_height;
151 int w32_system_caret_x;
152 int w32_system_caret_y;
153 DWORD dwWindowsThreadId = 0;
154 HANDLE hWindowsThread = NULL;
155 DWORD dwMainThreadId = 0;
156 HANDLE hMainThread = NULL;
158 int vertical_scroll_bar_min_handle;
159 int vertical_scroll_bar_top_border;
160 int vertical_scroll_bar_bottom_border;
162 int last_scroll_bar_drag_pos;
164 /* Keyboard code page - may be changed by language-change events. */
165 int w32_keyboard_codepage;
167 /* Mouse movement. */
169 /* Where the mouse was last time we reported a mouse event. */
170 static RECT last_mouse_glyph;
171 static FRAME_PTR last_mouse_glyph_frame;
173 /* The scroll bar in which the last motion event occurred.
175 If the last motion event occurred in a scroll bar, we set this
176 so w32_mouse_position can know whether to report a scroll bar motion or
177 an ordinary motion.
179 If the last motion event didn't occur in a scroll bar, we set this
180 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
181 static Lisp_Object last_mouse_scroll_bar;
182 static int last_mouse_scroll_bar_pos;
184 /* This is a hack. We would really prefer that w32_mouse_position would
185 return the time associated with the position it returns, but there
186 doesn't seem to be any way to wrest the time-stamp from the server
187 along with the position query. So, we just keep track of the time
188 of the last movement we received, and return that in hopes that
189 it's somewhat accurate. */
190 static Time last_mouse_movement_time;
192 /* Incremented by w32_read_socket whenever it really tries to read
193 events. */
194 #ifdef __STDC__
195 static int volatile input_signal_count;
196 #else
197 static int input_signal_count;
198 #endif
200 #ifdef CYGWIN
201 int w32_message_fd = -1;
202 #endif /* CYGWIN */
204 static void x_update_window_end (struct window *, int, int);
205 static void w32_handle_tool_bar_click (struct frame *,
206 struct input_event *);
207 static void w32_define_cursor (Window, Cursor);
209 void x_lower_frame (struct frame *);
210 void x_scroll_bar_clear (struct frame *);
211 void x_wm_set_size_hint (struct frame *, long, bool);
212 void x_raise_frame (struct frame *);
213 void x_set_window_size (struct frame *, int, int, int);
214 void x_wm_set_window_state (struct frame *, int);
215 void x_wm_set_icon_pixmap (struct frame *, int);
216 static void w32_initialize (void);
217 static void x_update_end (struct frame *);
218 static void w32_frame_up_to_date (struct frame *);
219 static void w32_set_terminal_modes (struct terminal *);
220 static void w32_reset_terminal_modes (struct terminal *);
221 static void x_clear_frame (struct frame *);
222 static void frame_highlight (struct frame *);
223 static void frame_unhighlight (struct frame *);
224 static void x_new_focus_frame (struct w32_display_info *,
225 struct frame *);
226 static void x_focus_changed (int, int, struct w32_display_info *,
227 struct frame *, struct input_event *);
228 static void w32_detect_focus_change (struct w32_display_info *,
229 W32Msg *, struct input_event *);
230 static void w32_frame_rehighlight (struct frame *);
231 static void x_frame_rehighlight (struct w32_display_info *);
232 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
233 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
234 enum text_cursor_kinds);
235 static void w32_clip_to_row (struct window *, struct glyph_row *, int, HDC);
236 static BOOL my_show_window (struct frame *, HWND, int);
237 static void my_set_window_pos (HWND, HWND, int, int, int, int, UINT);
238 #if 0
239 static void my_set_focus (struct frame *, HWND);
240 #endif
241 static void my_set_foreground_window (HWND);
242 static void my_destroy_window (struct frame *, HWND);
244 #ifdef GLYPH_DEBUG
245 static void x_check_font (struct frame *, struct font *);
246 #endif
248 static Lisp_Object Qvendor_specific_keysyms;
249 static Lisp_Object Qadded, Qremoved, Qmodified;
250 static Lisp_Object Qrenamed_from, Qrenamed_to;
253 /***********************************************************************
254 Debugging
255 ***********************************************************************/
257 #if 0
259 /* This is a function useful for recording debugging information about
260 the sequence of occurrences in this file. */
262 struct record
264 char *locus;
265 int type;
268 struct record event_record[100];
270 int event_record_index;
272 record_event (char *locus, int type)
274 if (event_record_index == sizeof (event_record) / sizeof (struct record))
275 event_record_index = 0;
277 event_record[event_record_index].locus = locus;
278 event_record[event_record_index].type = type;
279 event_record_index++;
282 #endif /* 0 */
285 void
286 XChangeGC (void *ignore, XGCValues *gc, unsigned long mask,
287 XGCValues *xgcv)
289 if (mask & GCForeground)
290 gc->foreground = xgcv->foreground;
291 if (mask & GCBackground)
292 gc->background = xgcv->background;
293 if (mask & GCFont)
294 gc->font = xgcv->font;
297 XGCValues *
298 XCreateGC (void *ignore, Window window, unsigned long mask, XGCValues *xgcv)
300 XGCValues *gc = xzalloc (sizeof (XGCValues));
302 XChangeGC (ignore, gc, mask, xgcv);
304 return gc;
307 void
308 XGetGCValues (void *ignore, XGCValues *gc,
309 unsigned long mask, XGCValues *xgcv)
311 XChangeGC (ignore, xgcv, mask, gc);
314 static void
315 w32_set_clip_rectangle (HDC hdc, RECT *rect)
317 if (rect)
319 HRGN clip_region = CreateRectRgnIndirect (rect);
320 SelectClipRgn (hdc, clip_region);
321 DeleteObject (clip_region);
323 else
324 SelectClipRgn (hdc, NULL);
327 /* Restore clipping rectangle in S */
328 static void
329 w32_restore_glyph_string_clip (struct glyph_string *s)
331 RECT *r = s->clip;
332 int n = s->num_clips;
334 if (n == 1)
335 w32_set_clip_rectangle (s->hdc, r);
336 else if (n > 1)
338 HRGN clip1 = CreateRectRgnIndirect (r);
339 HRGN clip2 = CreateRectRgnIndirect (r + 1);
340 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
341 SelectClipRgn (s->hdc, clip1);
342 DeleteObject (clip1);
343 DeleteObject (clip2);
348 Draw a wavy line under S. The wave fills wave_height pixels from y0.
350 x0 wave_length = 2
352 y0 * * * * *
353 |* * * * * * * * *
354 wave_height = 3 | * * * *
358 void
359 w32_draw_underwave (struct glyph_string *s, COLORREF color)
361 int wave_height = 2, wave_length = 3;
362 int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
363 XRectangle wave_clip, string_clip, final_clip;
364 RECT w32_final_clip, w32_string_clip;
365 HPEN hp, oldhp;
367 dx = wave_length;
368 dy = wave_height - 1;
369 x0 = s->x;
370 y0 = s->ybase + 1;
371 width = s->width;
372 xmax = x0 + width;
374 /* Find and set clipping rectangle */
376 wave_clip.x = x0;
377 wave_clip.y = y0;
378 wave_clip.width = width;
379 wave_clip.height = wave_height;
381 get_glyph_string_clip_rect (s, &w32_string_clip);
382 CONVERT_TO_XRECT (string_clip, w32_string_clip);
384 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
385 return;
387 hp = CreatePen (PS_SOLID, 0, color);
388 oldhp = SelectObject (s->hdc, hp);
389 CONVERT_FROM_XRECT (final_clip, w32_final_clip);
390 w32_set_clip_rectangle (s->hdc, &w32_final_clip);
392 /* Draw the waves */
394 x1 = x0 - (x0 % dx);
395 x2 = x1 + dx;
396 odd = (x1/dx) % 2;
397 y1 = y2 = y0;
399 if (odd)
400 y1 += dy;
401 else
402 y2 += dy;
404 MoveToEx (s->hdc, x1, y1, NULL);
406 while (x1 <= xmax)
408 LineTo (s->hdc, x2, y2);
409 x1 = x2, y1 = y2;
410 x2 += dx, y2 = y0 + odd*dy;
411 odd = !odd;
414 /* Restore previous pen and clipping rectangle(s) */
415 w32_restore_glyph_string_clip (s);
416 SelectObject (s->hdc, oldhp);
417 DeleteObject (hp);
420 /* Draw a hollow rectangle at the specified position. */
421 void
422 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
423 int width, int height)
425 HBRUSH hb, oldhb;
426 HPEN hp, oldhp;
428 hb = CreateSolidBrush (gc->background);
429 hp = CreatePen (PS_SOLID, 0, gc->foreground);
430 oldhb = SelectObject (hdc, hb);
431 oldhp = SelectObject (hdc, hp);
433 Rectangle (hdc, x, y, x + width, y + height);
435 SelectObject (hdc, oldhb);
436 SelectObject (hdc, oldhp);
437 DeleteObject (hb);
438 DeleteObject (hp);
441 /* Draw a filled rectangle at the specified position. */
442 void
443 w32_fill_rect (FRAME_PTR f, HDC hdc, COLORREF pix, RECT *lprect)
445 HBRUSH hb;
447 hb = CreateSolidBrush (pix);
448 FillRect (hdc, lprect, hb);
449 DeleteObject (hb);
452 void
453 w32_clear_window (FRAME_PTR f)
455 RECT rect;
456 HDC hdc = get_frame_dc (f);
458 /* Under certain conditions, this can be called at startup with
459 a console frame pointer before the GUI frame is created. An HDC
460 of 0 indicates this. */
461 if (hdc)
463 GetClientRect (FRAME_W32_WINDOW (f), &rect);
464 w32_clear_rect (f, hdc, &rect);
467 release_frame_dc (f, hdc);
470 #define OPAQUE_FRAME 255
472 void
473 x_set_frame_alpha (struct frame *f)
475 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
476 double alpha = 1.0;
477 double alpha_min = 1.0;
478 BYTE opac;
479 LONG ex_style;
480 HWND window = FRAME_W32_WINDOW (f);
482 /* Older versions of Windows do not support transparency. */
483 if (!pfnSetLayeredWindowAttributes)
484 return;
486 if (dpyinfo->x_highlight_frame == f)
487 alpha = f->alpha[0];
488 else
489 alpha = f->alpha[1];
491 if (FLOATP (Vframe_alpha_lower_limit))
492 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
493 else if (INTEGERP (Vframe_alpha_lower_limit))
494 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
496 if (alpha < 0.0)
497 return;
498 else if (alpha > 1.0)
499 alpha = 1.0;
500 else if (alpha < alpha_min && alpha_min <= 1.0)
501 alpha = alpha_min;
503 opac = alpha * OPAQUE_FRAME;
505 ex_style = GetWindowLong (window, GWL_EXSTYLE);
507 if (opac == OPAQUE_FRAME)
508 ex_style &= ~WS_EX_LAYERED;
509 else
510 ex_style |= WS_EX_LAYERED;
512 SetWindowLong (window, GWL_EXSTYLE, ex_style);
514 if (opac != OPAQUE_FRAME)
515 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
519 x_display_pixel_height (struct w32_display_info *dpyinfo)
521 HDC dc = GetDC (NULL);
522 int pixels = GetDeviceCaps (dc, VERTRES);
523 ReleaseDC (NULL, dc);
524 return pixels;
528 x_display_pixel_width (struct w32_display_info *dpyinfo)
530 HDC dc = GetDC (NULL);
531 int pixels = GetDeviceCaps (dc, HORZRES);
532 ReleaseDC (NULL, dc);
533 return pixels;
537 /***********************************************************************
538 Starting and ending an update
539 ***********************************************************************/
541 /* Start an update of frame F. This function is installed as a hook
542 for update_begin, i.e. it is called when update_begin is called.
543 This function is called prior to calls to x_update_window_begin for
544 each window being updated. */
546 static void
547 x_update_begin (struct frame *f)
549 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
551 if (! FRAME_W32_P (f))
552 return;
554 /* Regenerate display palette before drawing if list of requested
555 colors has changed. */
556 if (display_info->regen_palette)
558 w32_regenerate_palette (f);
559 display_info->regen_palette = FALSE;
564 /* Start update of window W. Set the global variable updated_window
565 to the window being updated and set output_cursor to the cursor
566 position of W. */
568 static void
569 x_update_window_begin (struct window *w)
571 struct frame *f = XFRAME (WINDOW_FRAME (w));
572 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
574 /* Hide the system caret during an update. */
575 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
577 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
580 updated_window = w;
581 set_output_cursor (&w->cursor);
583 block_input ();
585 if (f == hlinfo->mouse_face_mouse_frame)
587 /* Don't do highlighting for mouse motion during the update. */
588 hlinfo->mouse_face_defer = 1;
590 /* If F needs to be redrawn, simply forget about any prior mouse
591 highlighting. */
592 if (FRAME_GARBAGED_P (f))
593 hlinfo->mouse_face_window = Qnil;
595 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
596 their mouse_face_p flag set, which means that they are always
597 unequal to rows in a desired matrix which never have that
598 flag set. So, rows containing mouse-face glyphs are never
599 scrolled, and we don't have to switch the mouse highlight off
600 here to prevent it from being scrolled. */
602 /* Can we tell that this update does not affect the window
603 where the mouse highlight is? If so, no need to turn off.
604 Likewise, don't do anything if the frame is garbaged;
605 in that case, the frame's current matrix that we would use
606 is all wrong, and we will redisplay that line anyway. */
607 if (!NILP (hlinfo->mouse_face_window)
608 && w == XWINDOW (hlinfo->mouse_face_window))
610 int i;
612 for (i = 0; i < w->desired_matrix->nrows; ++i)
613 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
614 break;
616 if (i < w->desired_matrix->nrows)
617 clear_mouse_face (hlinfo);
619 #endif /* 0 */
622 unblock_input ();
625 /* Draw a vertical window border from (x,y0) to (x,y1) */
627 static void
628 w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
630 struct frame *f = XFRAME (WINDOW_FRAME (w));
631 RECT r;
632 HDC hdc;
633 struct face *face;
635 r.left = x;
636 r.right = x + 1;
637 r.top = y0;
638 r.bottom = y1;
640 hdc = get_frame_dc (f);
641 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
642 if (face)
643 w32_fill_rect (f, hdc, face->foreground, &r);
644 else
645 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
647 release_frame_dc (f, hdc);
651 /* End update of window W (which is equal to updated_window).
653 Draw vertical borders between horizontally adjacent windows, and
654 display W's cursor if CURSOR_ON_P is non-zero.
656 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
657 glyphs in mouse-face were overwritten. In that case we have to
658 make sure that the mouse-highlight is properly redrawn.
660 W may be a menu bar pseudo-window in case we don't have X toolkit
661 support. Such windows don't have a cursor, so don't display it
662 here. */
664 static void
665 x_update_window_end (struct window *w, int cursor_on_p,
666 int mouse_face_overwritten_p)
668 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
670 if (!w->pseudo_window_p)
672 block_input ();
674 if (cursor_on_p)
675 display_and_set_cursor (w, 1, output_cursor.hpos,
676 output_cursor.vpos,
677 output_cursor.x, output_cursor.y);
679 if (draw_window_fringes (w, 1))
680 x_draw_vertical_border (w);
682 unblock_input ();
685 /* If a row with mouse-face was overwritten, arrange for
686 XTframe_up_to_date to redisplay the mouse highlight. */
687 if (mouse_face_overwritten_p)
689 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
690 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
691 hlinfo->mouse_face_window = Qnil;
694 /* Unhide the caret. This won't actually show the cursor, unless it
695 was visible before the corresponding call to HideCaret in
696 x_update_window_begin. */
697 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
699 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
702 updated_window = NULL;
706 /* End update of frame F. This function is installed as a hook in
707 update_end. */
709 static void
710 x_update_end (struct frame *f)
712 if (! FRAME_W32_P (f))
713 return;
715 /* Mouse highlight may be displayed again. */
716 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
720 /* This function is called from various places in xdisp.c whenever a
721 complete update has been performed. The global variable
722 updated_window is not available here. */
724 static void
725 w32_frame_up_to_date (struct frame *f)
727 if (FRAME_W32_P (f))
729 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
731 if (hlinfo->mouse_face_deferred_gc
732 || f == hlinfo->mouse_face_mouse_frame)
734 block_input ();
735 if (hlinfo->mouse_face_mouse_frame)
736 note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
737 hlinfo->mouse_face_mouse_x,
738 hlinfo->mouse_face_mouse_y);
739 hlinfo->mouse_face_deferred_gc = 0;
740 unblock_input ();
746 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
747 arrow bitmaps, or clear the fringes if no bitmaps are required
748 before DESIRED_ROW is made current. The window being updated is
749 found in updated_window. This function is called from
750 update_window_line only if it is known that there are differences
751 between bitmaps to be drawn between current row and DESIRED_ROW. */
753 static void
754 x_after_update_window_line (struct glyph_row *desired_row)
756 struct window *w = updated_window;
757 struct frame *f;
758 int width, height;
760 eassert (w);
762 if (!desired_row->mode_line_p && !w->pseudo_window_p)
763 desired_row->redraw_fringe_bitmaps_p = 1;
765 /* When a window has disappeared, make sure that no rest of
766 full-width rows stays visible in the internal border. Could
767 check here if updated_window is the leftmost/rightmost window,
768 but I guess it's not worth doing since vertically split windows
769 are almost never used, internal border is rarely set, and the
770 overhead is very small. */
771 if (windows_or_buffers_changed
772 && desired_row->full_width_p
773 && (f = XFRAME (w->frame),
774 width = FRAME_INTERNAL_BORDER_WIDTH (f),
775 width != 0)
776 && (height = desired_row->visible_height,
777 height > 0))
779 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
781 block_input ();
783 HDC hdc = get_frame_dc (f);
784 w32_clear_area (f, hdc, 0, y, width, height);
785 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
786 y, width, height);
787 release_frame_dc (f, hdc);
789 unblock_input ();
794 /* Draw the bitmap WHICH in one of the left or right fringes of
795 window W. ROW is the glyph row for which to display the bitmap; it
796 determines the vertical position at which the bitmap has to be
797 drawn. */
799 static void
800 w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
801 struct draw_fringe_bitmap_params *p)
803 struct frame *f = XFRAME (WINDOW_FRAME (w));
804 HDC hdc;
805 struct face *face = p->face;
807 hdc = get_frame_dc (f);
809 if (!p->overlay_p)
811 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
813 /* If the fringe is adjacent to the left (right) scroll bar of a
814 leftmost (rightmost, respectively) window, then extend its
815 background to the gap between the fringe and the bar. */
816 if ((WINDOW_LEFTMOST_P (w)
817 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
818 || (WINDOW_RIGHTMOST_P (w)
819 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
821 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
823 if (sb_width > 0)
825 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
826 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
827 * FRAME_COLUMN_WIDTH (f));
829 if (bx < 0)
831 /* Bitmap fills the fringe. */
832 if (bar_area_x + bar_area_width == p->x)
833 bx = bar_area_x + sb_width;
834 else if (p->x + p->wd == bar_area_x)
835 bx = bar_area_x;
836 if (bx >= 0)
838 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
840 nx = bar_area_width - sb_width;
841 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
842 row->y));
843 ny = row->visible_height;
846 else
848 if (bar_area_x + bar_area_width == bx)
850 bx = bar_area_x + sb_width;
851 nx += bar_area_width - sb_width;
853 else if (bx + nx == bar_area_x)
854 nx += bar_area_width - sb_width;
859 if (bx >= 0 && nx > 0)
860 w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
863 /* Must clip because of partially visible lines. */
864 w32_clip_to_row (w, row, -1, hdc);
866 if (p->which && p->which < max_fringe_bmp)
868 HBITMAP pixmap = fringe_bmp[p->which];
869 HDC compat_hdc;
870 HANDLE horig_obj;
872 compat_hdc = CreateCompatibleDC (hdc);
874 SaveDC (hdc);
876 horig_obj = SelectObject (compat_hdc, pixmap);
878 /* Paint overlays transparently. */
879 if (p->overlay_p)
881 HBRUSH h_brush, h_orig_brush;
883 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
884 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
885 h_brush = CreateSolidBrush (face->foreground);
886 h_orig_brush = SelectObject (hdc, h_brush);
888 BitBlt (hdc, p->x, p->y, p->wd, p->h,
889 compat_hdc, 0, p->dh,
890 DSTINVERT);
891 BitBlt (hdc, p->x, p->y, p->wd, p->h,
892 compat_hdc, 0, p->dh,
893 0x2E064A);
894 BitBlt (hdc, p->x, p->y, p->wd, p->h,
895 compat_hdc, 0, p->dh,
896 DSTINVERT);
898 SelectObject (hdc, h_orig_brush);
899 DeleteObject (h_brush);
901 else
903 SetTextColor (hdc, face->background);
904 SetBkColor (hdc, (p->cursor_p
905 ? f->output_data.w32->cursor_pixel
906 : face->foreground));
908 BitBlt (hdc, p->x, p->y, p->wd, p->h,
909 compat_hdc, 0, p->dh,
910 SRCCOPY);
913 SelectObject (compat_hdc, horig_obj);
914 DeleteDC (compat_hdc);
915 RestoreDC (hdc, -1);
918 w32_set_clip_rectangle (hdc, NULL);
920 release_frame_dc (f, hdc);
923 static void
924 w32_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
926 if (which >= max_fringe_bmp)
928 int i = max_fringe_bmp;
929 max_fringe_bmp = which + 20;
930 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
931 while (i < max_fringe_bmp)
932 fringe_bmp[i++] = 0;
935 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
938 static void
939 w32_destroy_fringe_bitmap (int which)
941 if (which >= max_fringe_bmp)
942 return;
944 if (fringe_bmp[which])
945 DeleteObject (fringe_bmp[which]);
946 fringe_bmp[which] = 0;
951 /* This is called when starting Emacs and when restarting after
952 suspend. When starting Emacs, no window is mapped. And nothing
953 must be done to Emacs's own window if it is suspended (though that
954 rarely happens). */
956 static void
957 w32_set_terminal_modes (struct terminal *term)
961 /* This is called when exiting or suspending Emacs. Exiting will make
962 the W32 windows go away, and suspending requires no action. */
964 static void
965 w32_reset_terminal_modes (struct terminal *term)
971 /***********************************************************************
972 Display Iterator
973 ***********************************************************************/
975 /* Function prototypes of this page. */
977 static void x_set_glyph_string_clipping (struct glyph_string *);
978 static void x_set_glyph_string_gc (struct glyph_string *);
979 static void x_draw_glyph_string_background (struct glyph_string *,
980 int);
981 static void x_draw_glyph_string_foreground (struct glyph_string *);
982 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
983 static void x_draw_glyph_string_box (struct glyph_string *);
984 static void x_draw_glyph_string (struct glyph_string *);
985 static void x_set_cursor_gc (struct glyph_string *);
986 static void x_set_mode_line_face_gc (struct glyph_string *);
987 static void x_set_mouse_face_gc (struct glyph_string *);
988 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
989 static void w32_setup_relief_color (struct frame *, struct relief *,
990 double, int, COLORREF);
991 static void x_setup_relief_colors (struct glyph_string *);
992 static void x_draw_image_glyph_string (struct glyph_string *);
993 static void x_draw_image_relief (struct glyph_string *);
994 static void x_draw_image_foreground (struct glyph_string *);
995 static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
996 static void x_clear_glyph_string_rect (struct glyph_string *, int,
997 int, int, int);
998 static void w32_draw_relief_rect (struct frame *, int, int, int, int,
999 int, int, int, int, int, int,
1000 RECT *);
1001 static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
1002 int, int, int, RECT *);
1005 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1006 face. */
1008 static void
1009 x_set_cursor_gc (struct glyph_string *s)
1011 if (s->font == FRAME_FONT (s->f)
1012 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1013 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1014 && !s->cmp)
1015 s->gc = s->f->output_data.w32->cursor_gc;
1016 else
1018 /* Cursor on non-default face: must merge. */
1019 XGCValues xgcv;
1020 unsigned long mask;
1022 xgcv.background = s->f->output_data.w32->cursor_pixel;
1023 xgcv.foreground = s->face->background;
1025 /* If the glyph would be invisible, try a different foreground. */
1026 if (xgcv.foreground == xgcv.background)
1027 xgcv.foreground = s->face->foreground;
1028 if (xgcv.foreground == xgcv.background)
1029 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1030 if (xgcv.foreground == xgcv.background)
1031 xgcv.foreground = s->face->foreground;
1033 /* Make sure the cursor is distinct from text in this face. */
1034 if (xgcv.background == s->face->background
1035 && xgcv.foreground == s->face->foreground)
1037 xgcv.background = s->face->foreground;
1038 xgcv.foreground = s->face->background;
1041 IF_DEBUG (x_check_font (s->f, s->font));
1042 xgcv.font = s->font;
1043 mask = GCForeground | GCBackground | GCFont;
1045 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1046 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1047 mask, &xgcv);
1048 else
1049 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1050 = XCreateGC (NULL, s->window, mask, &xgcv);
1052 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1057 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1059 static void
1060 x_set_mouse_face_gc (struct glyph_string *s)
1062 int face_id;
1063 struct face *face;
1065 /* What face has to be used last for the mouse face? */
1066 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
1067 face = FACE_FROM_ID (s->f, face_id);
1068 if (face == NULL)
1069 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1071 if (s->first_glyph->type == CHAR_GLYPH)
1072 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1073 else
1074 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1075 s->face = FACE_FROM_ID (s->f, face_id);
1076 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1078 /* If font in this face is same as S->font, use it. */
1079 if (s->font == s->face->font)
1080 s->gc = s->face->gc;
1081 else
1083 /* Otherwise construct scratch_cursor_gc with values from FACE
1084 but font FONT. */
1085 XGCValues xgcv;
1086 unsigned long mask;
1088 xgcv.background = s->face->background;
1089 xgcv.foreground = s->face->foreground;
1090 IF_DEBUG (x_check_font (s->f, s->font));
1091 xgcv.font = s->font;
1092 mask = GCForeground | GCBackground | GCFont;
1094 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1095 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1096 mask, &xgcv);
1097 else
1098 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1099 = XCreateGC (NULL, s->window, mask, &xgcv);
1101 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1104 eassert (s->gc != 0);
1108 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1109 Faces to use in the mode line have already been computed when the
1110 matrix was built, so there isn't much to do, here. */
1112 static inline void
1113 x_set_mode_line_face_gc (struct glyph_string *s)
1115 s->gc = s->face->gc;
1119 /* Set S->gc of glyph string S for drawing that glyph string. Set
1120 S->stippled_p to a non-zero value if the face of S has a stipple
1121 pattern. */
1123 static inline void
1124 x_set_glyph_string_gc (struct glyph_string *s)
1126 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1128 if (s->hl == DRAW_NORMAL_TEXT)
1130 s->gc = s->face->gc;
1131 s->stippled_p = s->face->stipple != 0;
1133 else if (s->hl == DRAW_INVERSE_VIDEO)
1135 x_set_mode_line_face_gc (s);
1136 s->stippled_p = s->face->stipple != 0;
1138 else if (s->hl == DRAW_CURSOR)
1140 x_set_cursor_gc (s);
1141 s->stippled_p = 0;
1143 else if (s->hl == DRAW_MOUSE_FACE)
1145 x_set_mouse_face_gc (s);
1146 s->stippled_p = s->face->stipple != 0;
1148 else if (s->hl == DRAW_IMAGE_RAISED
1149 || s->hl == DRAW_IMAGE_SUNKEN)
1151 s->gc = s->face->gc;
1152 s->stippled_p = s->face->stipple != 0;
1154 else
1156 s->gc = s->face->gc;
1157 s->stippled_p = s->face->stipple != 0;
1160 /* GC must have been set. */
1161 eassert (s->gc != 0);
1165 /* Set clipping for output of glyph string S. S may be part of a mode
1166 line or menu if we don't have X toolkit support. */
1168 static inline void
1169 x_set_glyph_string_clipping (struct glyph_string *s)
1171 RECT *r = s->clip;
1172 int n = get_glyph_string_clip_rects (s, r, 2);
1174 if (n == 1)
1175 w32_set_clip_rectangle (s->hdc, r);
1176 else if (n > 1)
1178 HRGN clip1 = CreateRectRgnIndirect (r);
1179 HRGN clip2 = CreateRectRgnIndirect (r + 1);
1180 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
1181 SelectClipRgn (s->hdc, clip1);
1182 DeleteObject (clip1);
1183 DeleteObject (clip2);
1185 s->num_clips = n;
1188 /* Set SRC's clipping for output of glyph string DST. This is called
1189 when we are drawing DST's left_overhang or right_overhang only in
1190 the area of SRC. */
1192 static void
1193 x_set_glyph_string_clipping_exactly (struct glyph_string *src,
1194 struct glyph_string *dst)
1196 RECT r;
1198 r.left = src->x;
1199 r.right = r.left + src->width;
1200 r.top = src->y;
1201 r.bottom = r.top + src->height;
1202 dst->clip[0] = r;
1203 dst->num_clips = 1;
1204 w32_set_clip_rectangle (dst->hdc, &r);
1207 /* RIF:
1208 Compute left and right overhang of glyph string S. */
1210 static void
1211 w32_compute_glyph_string_overhangs (struct glyph_string *s)
1213 if (s->cmp == NULL
1214 && s->first_glyph->type == CHAR_GLYPH
1215 && !s->font_not_found_p)
1217 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1218 struct font *font = s->font;
1219 struct font_metrics metrics;
1220 int i;
1222 for (i = 0; i < s->nchars; i++)
1223 code[i] = s->char2b[i];
1224 font->driver->text_extents (font, code, s->nchars, &metrics);
1225 s->right_overhang = (metrics.rbearing > metrics.width
1226 ? metrics.rbearing - metrics.width : 0);
1227 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
1229 else if (s->cmp)
1231 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1232 s->left_overhang = -s->cmp->lbearing;
1236 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1238 static inline void
1239 x_clear_glyph_string_rect (struct glyph_string *s,
1240 int x, int y, int w, int h)
1242 int real_x = x;
1243 int real_y = y;
1244 int real_w = w;
1245 int real_h = h;
1246 #if 0
1247 /* Take clipping into account. */
1248 if (s->gc->clip_mask == Rect)
1250 real_x = max (real_x, s->gc->clip_rectangle.left);
1251 real_y = max (real_y, s->gc->clip_rectangle.top);
1252 real_w = min (real_w, s->gc->clip_rectangle.right
1253 - s->gc->clip_rectangle.left);
1254 real_h = min (real_h, s->gc->clip_rectangle.bottom
1255 - s->gc->clip_rectangle.top);
1257 #endif
1258 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1259 real_w, real_h);
1263 /* Draw the background of glyph_string S. If S->background_filled_p
1264 is non-zero don't draw it. FORCE_P non-zero means draw the
1265 background even if it wouldn't be drawn normally. This is used
1266 when a string preceding S draws into the background of S, or S
1267 contains the first component of a composition. */
1269 static void
1270 x_draw_glyph_string_background (struct glyph_string *s, int force_p)
1272 /* Nothing to do if background has already been drawn or if it
1273 shouldn't be drawn in the first place. */
1274 if (!s->background_filled_p)
1276 int box_line_width = max (s->face->box_line_width, 0);
1278 #if 0 /* TODO: stipple */
1279 if (s->stippled_p)
1281 /* Fill background with a stipple pattern. */
1282 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1283 XFillRectangle (s->display, s->window, s->gc, s->x,
1284 s->y + box_line_width,
1285 s->background_width,
1286 s->height - 2 * box_line_width);
1287 XSetFillStyle (s->display, s->gc, FillSolid);
1288 s->background_filled_p = 1;
1290 else
1291 #endif
1292 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1293 || s->font_not_found_p
1294 || s->extends_to_end_of_line_p
1295 || force_p)
1297 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1298 s->background_width,
1299 s->height - 2 * box_line_width);
1300 s->background_filled_p = 1;
1306 /* Draw the foreground of glyph string S. */
1308 static void
1309 x_draw_glyph_string_foreground (struct glyph_string *s)
1311 int i, x;
1313 /* If first glyph of S has a left box line, start drawing the text
1314 of S to the right of that box line. */
1315 if (s->face->box != FACE_NO_BOX
1316 && s->first_glyph->left_box_line_p)
1317 x = s->x + eabs (s->face->box_line_width);
1318 else
1319 x = s->x;
1321 SetTextColor (s->hdc, s->gc->foreground);
1322 SetBkColor (s->hdc, s->gc->background);
1323 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1325 /* Draw characters of S as rectangles if S's font could not be
1326 loaded. */
1327 if (s->font_not_found_p)
1329 for (i = 0; i < s->nchars; ++i)
1331 struct glyph *g = s->first_glyph + i;
1333 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1334 s->height - 1);
1335 x += g->pixel_width;
1338 else
1340 struct font *font = s->font;
1341 int boff = font->baseline_offset;
1342 int y;
1343 HFONT old_font;
1345 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1347 if (font->vertical_centering)
1348 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1350 y = s->ybase - boff;
1351 if (s->for_overlaps
1352 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1353 font->driver->draw (s, 0, s->nchars, x, y, 0);
1354 else
1355 font->driver->draw (s, 0, s->nchars, x, y, 1);
1356 if (s->face->overstrike)
1357 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1359 SelectObject (s->hdc, old_font);
1363 /* Draw the foreground of composite glyph string S. */
1365 static void
1366 x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1368 int i, j, x;
1369 struct font *font = s->font;
1371 /* If first glyph of S has a left box line, start drawing the text
1372 of S to the right of that box line. */
1373 if (s->face && s->face->box != FACE_NO_BOX
1374 && s->first_glyph->left_box_line_p)
1375 x = s->x + eabs (s->face->box_line_width);
1376 else
1377 x = s->x;
1379 /* S is a glyph string for a composition. S->cmp_from is the index
1380 of the first character drawn for glyphs of this composition.
1381 S->cmp_from == 0 means we are drawing the very first character of
1382 this composition. */
1384 SetTextColor (s->hdc, s->gc->foreground);
1385 SetBkColor (s->hdc, s->gc->background);
1386 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1388 /* Draw a rectangle for the composition if the font for the very
1389 first character of the composition could not be loaded. */
1390 if (s->font_not_found_p)
1392 if (s->cmp_from == 0)
1393 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1394 s->height - 1);
1396 else if (! s->first_glyph->u.cmp.automatic)
1398 int y = s->ybase;
1399 HFONT old_font;
1401 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1403 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1404 /* TAB in a composition means display glyphs with padding
1405 space on the left or right. */
1406 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1408 int xx = x + s->cmp->offsets[j * 2];
1409 int yy = y - s->cmp->offsets[j * 2 + 1];
1411 font->driver->draw (s, j, j + 1, xx, yy, 0);
1412 if (s->face->overstrike)
1413 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1415 SelectObject (s->hdc, old_font);
1417 else
1419 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1420 Lisp_Object glyph;
1421 int y = s->ybase;
1422 int width = 0;
1423 HFONT old_font;
1425 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1427 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1429 glyph = LGSTRING_GLYPH (gstring, i);
1430 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1431 width += LGLYPH_WIDTH (glyph);
1432 else
1434 int xoff, yoff, wadjust;
1436 if (j < i)
1438 font->driver->draw (s, j, i, x, y, 0);
1439 x += width;
1441 xoff = LGLYPH_XOFF (glyph);
1442 yoff = LGLYPH_YOFF (glyph);
1443 wadjust = LGLYPH_WADJUST (glyph);
1444 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1445 x += wadjust;
1446 j = i + 1;
1447 width = 0;
1450 if (j < i)
1451 font->driver->draw (s, j, i, x, y, 0);
1453 SelectObject (s->hdc, old_font);
1458 /* Draw the foreground of glyph string S for glyphless characters. */
1460 static void
1461 x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1463 struct glyph *glyph = s->first_glyph;
1464 XChar2b char2b[8];
1465 int x, i, j;
1466 int with_background;
1468 /* If first glyph of S has a left box line, start drawing the text
1469 of S to the right of that box line. */
1470 if (s->face->box != FACE_NO_BOX
1471 && s->first_glyph->left_box_line_p)
1472 x = s->x + eabs (s->face->box_line_width);
1473 else
1474 x = s->x;
1476 SetTextColor (s->hdc, s->gc->foreground);
1477 SetBkColor (s->hdc, s->gc->background);
1478 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1480 s->char2b = char2b;
1481 with_background = ! (s->for_overlaps
1482 || (s->background_filled_p && s->hl != DRAW_CURSOR));
1483 for (i = 0; i < s->nchars; i++, glyph++)
1485 char buf[7], *str = NULL;
1486 int len = glyph->u.glyphless.len;
1488 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1490 if (len > 1
1491 && CHAR_TABLE_P (Vglyphless_char_display)
1492 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1493 >= 1))
1495 Lisp_Object acronym
1496 = (! glyph->u.glyphless.for_no_font
1497 ? CHAR_TABLE_REF (Vglyphless_char_display,
1498 glyph->u.glyphless.ch)
1499 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1500 if (STRINGP (acronym))
1501 str = SSDATA (acronym);
1504 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1506 sprintf ((char *) buf, "%0*X",
1507 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1508 glyph->u.glyphless.ch);
1509 str = buf;
1512 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1513 w32_draw_rectangle (s->hdc, s->gc,
1514 x, s->ybase - glyph->ascent,
1515 glyph->pixel_width - 1,
1516 glyph->ascent + glyph->descent - 1);
1517 if (str)
1519 struct font *font = s->font;
1520 int upper_len = (len + 1) / 2;
1521 unsigned code;
1522 HFONT old_font;
1524 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1525 /* It is certain that all LEN characters in STR are ASCII. */
1526 for (j = 0; j < len; j++)
1528 code = font->driver->encode_char (font, str[j]);
1529 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1531 font->driver->draw (s, 0, upper_len,
1532 x + glyph->slice.glyphless.upper_xoff,
1533 s->ybase + glyph->slice.glyphless.upper_yoff,
1534 with_background);
1535 font->driver->draw (s, upper_len, len,
1536 x + glyph->slice.glyphless.lower_xoff,
1537 s->ybase + glyph->slice.glyphless.lower_yoff,
1538 with_background);
1539 SelectObject (s->hdc, old_font);
1541 x += glyph->pixel_width;
1546 /* Brightness beyond which a color won't have its highlight brightness
1547 boosted.
1549 Nominally, highlight colors for `3d' faces are calculated by
1550 brightening an object's color by a constant scale factor, but this
1551 doesn't yield good results for dark colors, so for colors whose
1552 brightness is less than this value (on a scale of 0-255) have to
1553 use an additional additive factor.
1555 The value here is set so that the default menu-bar/mode-line color
1556 (grey75) will not have its highlights changed at all. */
1557 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1560 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1561 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1562 If this produces the same color as COLOR, try a color where all RGB
1563 values have DELTA added. Return the allocated color in *COLOR.
1564 DISPLAY is the X display, CMAP is the colormap to operate on.
1565 Value is non-zero if successful. */
1567 static int
1568 w32_alloc_lighter_color (struct frame *f, COLORREF *color,
1569 double factor, int delta)
1571 COLORREF new;
1572 long bright;
1574 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1575 delta /= 256;
1577 /* Change RGB values by specified FACTOR. Avoid overflow! */
1578 eassert (factor >= 0);
1579 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1580 min (0xff, factor * GetGValue (*color)),
1581 min (0xff, factor * GetBValue (*color)));
1583 /* Calculate brightness of COLOR. */
1584 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1585 + GetBValue (*color)) / 6;
1587 /* We only boost colors that are darker than
1588 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1589 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1590 /* Make an additive adjustment to NEW, because it's dark enough so
1591 that scaling by FACTOR alone isn't enough. */
1593 /* How far below the limit this color is (0 - 1, 1 being darker). */
1594 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1595 /* The additive adjustment. */
1596 int min_delta = delta * dimness * factor / 2;
1598 if (factor < 1)
1599 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1600 max (0, min (0xff, min_delta - GetGValue (*color))),
1601 max (0, min (0xff, min_delta - GetBValue (*color))));
1602 else
1603 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1604 max (0, min (0xff, min_delta + GetGValue (*color))),
1605 max (0, min (0xff, min_delta + GetBValue (*color))));
1608 if (new == *color)
1609 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1610 max (0, min (0xff, delta + GetGValue (*color))),
1611 max (0, min (0xff, delta + GetBValue (*color))));
1613 /* TODO: Map to palette and retry with delta if same? */
1614 /* TODO: Free colors (if using palette)? */
1616 if (new == *color)
1617 return 0;
1619 *color = new;
1621 return 1;
1624 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1625 colors in COLORS. On W32, we no longer try to map colors to
1626 a palette. */
1627 void
1628 x_query_colors (struct frame *f, XColor *colors, int ncolors)
1630 int i;
1632 for (i = 0; i < ncolors; i++)
1634 DWORD pixel = colors[i].pixel;
1635 /* Convert to a 16 bit value in range 0 - 0xffff. */
1636 colors[i].red = GetRValue (pixel) * 257;
1637 colors[i].green = GetGValue (pixel) * 257;
1638 colors[i].blue = GetBValue (pixel) * 257;
1642 void
1643 x_query_color (struct frame *f, XColor *color)
1645 x_query_colors (f, color, 1);
1649 /* Set up the foreground color for drawing relief lines of glyph
1650 string S. RELIEF is a pointer to a struct relief containing the GC
1651 with which lines will be drawn. Use a color that is FACTOR or
1652 DELTA lighter or darker than the relief's background which is found
1653 in S->f->output_data.x->relief_background. If such a color cannot
1654 be allocated, use DEFAULT_PIXEL, instead. */
1656 static void
1657 w32_setup_relief_color (struct frame *f, struct relief *relief, double factor,
1658 int delta, COLORREF default_pixel)
1660 XGCValues xgcv;
1661 struct w32_output *di = f->output_data.w32;
1662 unsigned long mask = GCForeground;
1663 COLORREF pixel;
1664 COLORREF background = di->relief_background;
1665 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1667 /* TODO: Free colors (if using palette)? */
1669 /* Allocate new color. */
1670 xgcv.foreground = default_pixel;
1671 pixel = background;
1672 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1674 relief->allocated_p = 1;
1675 xgcv.foreground = relief->pixel = pixel;
1678 if (relief->gc == 0)
1680 #if 0 /* TODO: stipple */
1681 xgcv.stipple = dpyinfo->gray;
1682 mask |= GCStipple;
1683 #endif
1684 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1686 else
1687 XChangeGC (NULL, relief->gc, mask, &xgcv);
1691 /* Set up colors for the relief lines around glyph string S. */
1693 static void
1694 x_setup_relief_colors (struct glyph_string *s)
1696 struct w32_output *di = s->f->output_data.w32;
1697 COLORREF color;
1699 if (s->face->use_box_color_for_shadows_p)
1700 color = s->face->box_color;
1701 else if (s->first_glyph->type == IMAGE_GLYPH
1702 && s->img->pixmap
1703 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1704 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1705 else
1706 color = s->gc->background;
1708 if (di->white_relief.gc == 0
1709 || color != di->relief_background)
1711 di->relief_background = color;
1712 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1713 WHITE_PIX_DEFAULT (s->f));
1714 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1715 BLACK_PIX_DEFAULT (s->f));
1720 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1721 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1722 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1723 relief. LEFT_P non-zero means draw a relief on the left side of
1724 the rectangle. RIGHT_P non-zero means draw a relief on the right
1725 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1726 when drawing. */
1728 static void
1729 w32_draw_relief_rect (struct frame *f,
1730 int left_x, int top_y, int right_x, int bottom_y,
1731 int width, int raised_p,
1732 int top_p, int bot_p, int left_p, int right_p,
1733 RECT *clip_rect)
1735 int i;
1736 XGCValues gc;
1737 HDC hdc = get_frame_dc (f);
1739 if (raised_p)
1740 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1741 else
1742 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1744 w32_set_clip_rectangle (hdc, clip_rect);
1746 /* Top. */
1747 if (top_p)
1748 for (i = 0; i < width; ++i)
1749 w32_fill_area (f, hdc, gc.foreground,
1750 left_x + i * left_p, top_y + i,
1751 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1753 /* Left. */
1754 if (left_p)
1755 for (i = 0; i < width; ++i)
1756 w32_fill_area (f, hdc, gc.foreground,
1757 left_x + i, top_y + i, 1,
1758 bottom_y - top_y - 2 * i + 1);
1760 if (raised_p)
1761 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1762 else
1763 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1765 /* Bottom. */
1766 if (bot_p)
1767 for (i = 0; i < width; ++i)
1768 w32_fill_area (f, hdc, gc.foreground,
1769 left_x + i * left_p, bottom_y - i,
1770 right_x - left_x - i * (left_p + right_p) + 1, 1);
1772 /* Right. */
1773 if (right_p)
1774 for (i = 0; i < width; ++i)
1775 w32_fill_area (f, hdc, gc.foreground,
1776 right_x - i, top_y + i + 1, 1,
1777 bottom_y - top_y - 2 * i - 1);
1779 w32_set_clip_rectangle (hdc, NULL);
1781 release_frame_dc (f, hdc);
1785 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1786 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1787 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1788 left side of the rectangle. RIGHT_P non-zero means draw a line
1789 on the right side of the rectangle. CLIP_RECT is the clipping
1790 rectangle to use when drawing. */
1792 static void
1793 w32_draw_box_rect (struct glyph_string *s,
1794 int left_x, int top_y, int right_x, int bottom_y, int width,
1795 int left_p, int right_p, RECT *clip_rect)
1797 w32_set_clip_rectangle (s->hdc, clip_rect);
1799 /* Top. */
1800 w32_fill_area (s->f, s->hdc, s->face->box_color,
1801 left_x, top_y, right_x - left_x + 1, width);
1803 /* Left. */
1804 if (left_p)
1806 w32_fill_area (s->f, s->hdc, s->face->box_color,
1807 left_x, top_y, width, bottom_y - top_y + 1);
1810 /* Bottom. */
1811 w32_fill_area (s->f, s->hdc, s->face->box_color,
1812 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1814 /* Right. */
1815 if (right_p)
1817 w32_fill_area (s->f, s->hdc, s->face->box_color,
1818 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1821 w32_set_clip_rectangle (s->hdc, NULL);
1825 /* Draw a box around glyph string S. */
1827 static void
1828 x_draw_glyph_string_box (struct glyph_string *s)
1830 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1831 int left_p, right_p;
1832 struct glyph *last_glyph;
1833 RECT clip_rect;
1835 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1836 ? WINDOW_RIGHT_EDGE_X (s->w)
1837 : window_box_right (s->w, s->area));
1839 /* The glyph that may have a right box line. */
1840 last_glyph = (s->cmp || s->img
1841 ? s->first_glyph
1842 : s->first_glyph + s->nchars - 1);
1844 width = eabs (s->face->box_line_width);
1845 raised_p = s->face->box == FACE_RAISED_BOX;
1846 left_x = s->x;
1847 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1848 ? last_x - 1
1849 : min (last_x, s->x + s->background_width) - 1));
1850 top_y = s->y;
1851 bottom_y = top_y + s->height - 1;
1853 left_p = (s->first_glyph->left_box_line_p
1854 || (s->hl == DRAW_MOUSE_FACE
1855 && (s->prev == NULL
1856 || s->prev->hl != s->hl)));
1857 right_p = (last_glyph->right_box_line_p
1858 || (s->hl == DRAW_MOUSE_FACE
1859 && (s->next == NULL
1860 || s->next->hl != s->hl)));
1862 get_glyph_string_clip_rect (s, &clip_rect);
1864 if (s->face->box == FACE_SIMPLE_BOX)
1865 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1866 left_p, right_p, &clip_rect);
1867 else
1869 x_setup_relief_colors (s);
1870 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1871 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1876 /* Draw foreground of image glyph string S. */
1878 static void
1879 x_draw_image_foreground (struct glyph_string *s)
1881 int x = s->x;
1882 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1884 /* If first glyph of S has a left box line, start drawing it to the
1885 right of that line. */
1886 if (s->face->box != FACE_NO_BOX
1887 && s->first_glyph->left_box_line_p
1888 && s->slice.x == 0)
1889 x += eabs (s->face->box_line_width);
1891 /* If there is a margin around the image, adjust x- and y-position
1892 by that margin. */
1893 if (s->slice.x == 0)
1894 x += s->img->hmargin;
1895 if (s->slice.y == 0)
1896 y += s->img->vmargin;
1898 SaveDC (s->hdc);
1900 if (s->img->pixmap)
1902 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1903 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1904 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1905 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1906 SetBkColor (compat_hdc, RGB (255, 255, 255));
1907 SetTextColor (s->hdc, RGB (0, 0, 0));
1908 x_set_glyph_string_clipping (s);
1910 if (s->img->mask)
1912 HDC mask_dc = CreateCompatibleDC (s->hdc);
1913 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1915 SetTextColor (s->hdc, RGB (255, 255, 255));
1916 SetBkColor (s->hdc, RGB (0, 0, 0));
1918 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1919 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1920 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1921 mask_dc, s->slice.x, s->slice.y, SRCAND);
1922 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1923 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1925 SelectObject (mask_dc, mask_orig_obj);
1926 DeleteDC (mask_dc);
1928 else
1930 SetTextColor (s->hdc, s->gc->foreground);
1931 SetBkColor (s->hdc, s->gc->background);
1933 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1934 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1936 /* When the image has a mask, we can expect that at
1937 least part of a mouse highlight or a block cursor will
1938 be visible. If the image doesn't have a mask, make
1939 a block cursor visible by drawing a rectangle around
1940 the image. I believe it's looking better if we do
1941 nothing here for mouse-face. */
1942 if (s->hl == DRAW_CURSOR)
1944 int r = s->img->relief;
1945 if (r < 0) r = -r;
1946 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
1947 s->slice.width + r*2 - 1,
1948 s->slice.height + r*2 - 1);
1952 w32_set_clip_rectangle (s->hdc, NULL);
1953 SelectObject (s->hdc, orig_brush);
1954 DeleteObject (fg_brush);
1955 SelectObject (compat_hdc, orig_obj);
1956 DeleteDC (compat_hdc);
1958 else
1959 w32_draw_rectangle (s->hdc, s->gc, x, y,
1960 s->slice.width - 1, s->slice.height - 1);
1962 RestoreDC (s->hdc ,-1);
1966 /* Draw a relief around the image glyph string S. */
1968 static void
1969 x_draw_image_relief (struct glyph_string *s)
1971 int x0, y0, x1, y1, thick, raised_p;
1972 RECT r;
1973 int x = s->x;
1974 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1976 /* If first glyph of S has a left box line, start drawing it to the
1977 right of that line. */
1978 if (s->face->box != FACE_NO_BOX
1979 && s->first_glyph->left_box_line_p
1980 && s->slice.x == 0)
1981 x += eabs (s->face->box_line_width);
1983 /* If there is a margin around the image, adjust x- and y-position
1984 by that margin. */
1985 if (s->slice.x == 0)
1986 x += s->img->hmargin;
1987 if (s->slice.y == 0)
1988 y += s->img->vmargin;
1990 if (s->hl == DRAW_IMAGE_SUNKEN
1991 || s->hl == DRAW_IMAGE_RAISED)
1993 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief
1994 : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1995 raised_p = s->hl == DRAW_IMAGE_RAISED;
1997 else
1999 thick = eabs (s->img->relief);
2000 raised_p = s->img->relief > 0;
2003 x0 = x - thick;
2004 y0 = y - thick;
2005 x1 = x + s->slice.width + thick - 1;
2006 y1 = y + s->slice.height + thick - 1;
2008 x_setup_relief_colors (s);
2009 get_glyph_string_clip_rect (s, &r);
2010 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2011 s->slice.y == 0,
2012 s->slice.y + s->slice.height == s->img->height,
2013 s->slice.x == 0,
2014 s->slice.x + s->slice.width == s->img->width,
2015 &r);
2019 /* Draw the foreground of image glyph string S to PIXMAP. */
2021 static void
2022 w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
2024 HDC hdc = CreateCompatibleDC (s->hdc);
2025 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
2026 int x = 0;
2027 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2029 /* If first glyph of S has a left box line, start drawing it to the
2030 right of that line. */
2031 if (s->face->box != FACE_NO_BOX
2032 && s->first_glyph->left_box_line_p
2033 && s->slice.x == 0)
2034 x += eabs (s->face->box_line_width);
2036 /* If there is a margin around the image, adjust x- and y-position
2037 by that margin. */
2038 if (s->slice.x == 0)
2039 x += s->img->hmargin;
2040 if (s->slice.y == 0)
2041 y += s->img->vmargin;
2043 if (s->img->pixmap)
2045 HDC compat_hdc = CreateCompatibleDC (hdc);
2046 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2047 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2048 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2050 if (s->img->mask)
2052 HDC mask_dc = CreateCompatibleDC (hdc);
2053 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2055 SetTextColor (hdc, RGB (0, 0, 0));
2056 SetBkColor (hdc, RGB (255, 255, 255));
2057 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2058 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2059 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2060 mask_dc, s->slice.x, s->slice.y, SRCAND);
2061 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2062 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2064 SelectObject (mask_dc, mask_orig_obj);
2065 DeleteDC (mask_dc);
2067 else
2069 SetTextColor (hdc, s->gc->foreground);
2070 SetBkColor (hdc, s->gc->background);
2072 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2073 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2075 /* When the image has a mask, we can expect that at
2076 least part of a mouse highlight or a block cursor will
2077 be visible. If the image doesn't have a mask, make
2078 a block cursor visible by drawing a rectangle around
2079 the image. I believe it's looking better if we do
2080 nothing here for mouse-face. */
2081 if (s->hl == DRAW_CURSOR)
2083 int r = s->img->relief;
2084 if (r < 0) r = -r;
2085 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2086 s->slice.width + r*2 - 1,
2087 s->slice.height + r*2 - 1);
2091 SelectObject (hdc, orig_brush);
2092 DeleteObject (fg_brush);
2093 SelectObject (compat_hdc, orig_obj);
2094 DeleteDC (compat_hdc);
2096 else
2097 w32_draw_rectangle (hdc, s->gc, x, y,
2098 s->slice.width - 1, s->slice.height - 1);
2100 SelectObject (hdc, orig_hdc_obj);
2101 DeleteDC (hdc);
2105 /* Draw part of the background of glyph string S. X, Y, W, and H
2106 give the rectangle to draw. */
2108 static void
2109 x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2111 #if 0 /* TODO: stipple */
2112 if (s->stippled_p)
2114 /* Fill background with a stipple pattern. */
2115 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2116 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2117 XSetFillStyle (s->display, s->gc, FillSolid);
2119 else
2120 #endif
2121 x_clear_glyph_string_rect (s, x, y, w, h);
2125 /* Draw image glyph string S.
2127 s->y
2128 s->x +-------------------------
2129 | s->face->box
2131 | +-------------------------
2132 | | s->img->vmargin
2134 | | +-------------------
2135 | | | the image
2139 static void
2140 x_draw_image_glyph_string (struct glyph_string *s)
2142 int x, y;
2143 int box_line_hwidth = eabs (s->face->box_line_width);
2144 int box_line_vwidth = max (s->face->box_line_width, 0);
2145 int height;
2146 HBITMAP pixmap = 0;
2148 height = s->height - 2 * box_line_vwidth;
2150 /* Fill background with face under the image. Do it only if row is
2151 taller than image or if image has a clip mask to reduce
2152 flickering. */
2153 s->stippled_p = s->face->stipple != 0;
2154 if (height > s->slice.height
2155 || s->img->hmargin
2156 || s->img->vmargin
2157 || s->img->mask
2158 || s->img->pixmap == 0
2159 || s->width != s->background_width)
2161 x = s->x;
2162 if (s->first_glyph->left_box_line_p
2163 && s->slice.x == 0)
2164 x += box_line_hwidth;
2166 y = s->y;
2167 if (s->slice.y == 0)
2168 y += box_line_vwidth;
2170 #if 0 /* TODO: figure out if we need to do this on Windows. */
2171 if (s->img->mask)
2173 /* Create a pixmap as large as the glyph string. Fill it
2174 with the background color. Copy the image to it, using
2175 its mask. Copy the temporary pixmap to the display. */
2176 Screen *screen = FRAME_X_SCREEN (s->f);
2177 int depth = DefaultDepthOfScreen (screen);
2179 /* Create a pixmap as large as the glyph string. */
2180 pixmap = XCreatePixmap (s->display, s->window,
2181 s->background_width,
2182 s->height, depth);
2184 /* Don't clip in the following because we're working on the
2185 pixmap. */
2186 XSetClipMask (s->display, s->gc, None);
2188 /* Fill the pixmap with the background color/stipple. */
2189 if (s->stippled_p)
2191 /* Fill background with a stipple pattern. */
2192 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2193 XFillRectangle (s->display, pixmap, s->gc,
2194 0, 0, s->background_width, s->height);
2195 XSetFillStyle (s->display, s->gc, FillSolid);
2197 else
2199 XGCValues xgcv;
2200 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2201 &xgcv);
2202 XSetForeground (s->display, s->gc, xgcv.background);
2203 XFillRectangle (s->display, pixmap, s->gc,
2204 0, 0, s->background_width, s->height);
2205 XSetForeground (s->display, s->gc, xgcv.foreground);
2208 else
2209 #endif
2210 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2212 s->background_filled_p = 1;
2215 /* Draw the foreground. */
2216 if (pixmap != 0)
2218 w32_draw_image_foreground_1 (s, pixmap);
2219 x_set_glyph_string_clipping (s);
2221 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2222 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2223 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2224 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2226 SetTextColor (s->hdc, s->gc->foreground);
2227 SetBkColor (s->hdc, s->gc->background);
2228 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2229 compat_hdc, 0, 0, SRCCOPY);
2231 SelectObject (s->hdc, orig_brush);
2232 DeleteObject (fg_brush);
2233 SelectObject (compat_hdc, orig_obj);
2234 DeleteDC (compat_hdc);
2236 DeleteObject (pixmap);
2237 pixmap = 0;
2239 else
2240 x_draw_image_foreground (s);
2242 /* If we must draw a relief around the image, do it. */
2243 if (s->img->relief
2244 || s->hl == DRAW_IMAGE_RAISED
2245 || s->hl == DRAW_IMAGE_SUNKEN)
2246 x_draw_image_relief (s);
2250 /* Draw stretch glyph string S. */
2252 static void
2253 x_draw_stretch_glyph_string (struct glyph_string *s)
2255 eassert (s->first_glyph->type == STRETCH_GLYPH);
2257 if (s->hl == DRAW_CURSOR
2258 && !x_stretch_cursor_p)
2260 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2261 wide as the stretch glyph. */
2262 int width, background_width = s->background_width;
2263 int x = s->x;
2265 if (!s->row->reversed_p)
2267 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2269 if (x < left_x)
2271 background_width -= left_x - x;
2272 x = left_x;
2275 else
2277 /* In R2L rows, draw the cursor on the right edge of the
2278 stretch glyph. */
2279 int right_x = window_box_right_offset (s->w, TEXT_AREA);
2281 if (x + background_width > right_x)
2282 background_width -= x - right_x;
2283 x += background_width;
2285 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2286 if (s->row->reversed_p)
2287 x -= width;
2289 /* Draw cursor. */
2290 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2292 /* Clear rest using the GC of the original non-cursor face. */
2293 if (width < background_width)
2295 XGCValues *gc = s->face->gc;
2296 int y = s->y;
2297 int w = background_width - width, h = s->height;
2298 RECT r;
2299 HDC hdc = s->hdc;
2301 if (!s->row->reversed_p)
2302 x += width;
2303 else
2304 x = s->x;
2305 if (s->row->mouse_face_p
2306 && cursor_in_mouse_face_p (s->w))
2308 x_set_mouse_face_gc (s);
2309 gc = s->gc;
2311 else
2312 gc = s->face->gc;
2314 get_glyph_string_clip_rect (s, &r);
2315 w32_set_clip_rectangle (hdc, &r);
2317 #if 0 /* TODO: stipple */
2318 if (s->face->stipple)
2320 /* Fill background with a stipple pattern. */
2321 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2322 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2323 XSetFillStyle (s->display, gc, FillSolid);
2325 else
2326 #endif
2328 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2332 else if (!s->background_filled_p)
2334 int background_width = s->background_width;
2335 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2337 /* Don't draw into left margin, fringe or scrollbar area
2338 except for header line and mode line. */
2339 if (x < left_x && !s->row->mode_line_p)
2341 background_width -= left_x - x;
2342 x = left_x;
2344 if (background_width > 0)
2345 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2348 s->background_filled_p = 1;
2352 /* Draw glyph string S. */
2354 static void
2355 x_draw_glyph_string (struct glyph_string *s)
2357 int relief_drawn_p = 0;
2359 /* If S draws into the background of its successor, draw the
2360 background of the successor first so that S can draw into it.
2361 This makes S->next use XDrawString instead of XDrawImageString. */
2362 if (s->next && s->right_overhang && !s->for_overlaps)
2364 int width;
2365 struct glyph_string *next;
2366 for (width = 0, next = s->next;
2367 next && width < s->right_overhang;
2368 width += next->width, next = next->next)
2369 if (next->first_glyph->type != IMAGE_GLYPH)
2371 x_set_glyph_string_gc (next);
2372 x_set_glyph_string_clipping (next);
2373 if (next->first_glyph->type == STRETCH_GLYPH)
2374 x_draw_stretch_glyph_string (next);
2375 else
2376 x_draw_glyph_string_background (next, 1);
2377 next->num_clips = 0;
2381 /* Set up S->gc, set clipping and draw S. */
2382 x_set_glyph_string_gc (s);
2384 /* Draw relief (if any) in advance for char/composition so that the
2385 glyph string can be drawn over it. */
2386 if (!s->for_overlaps
2387 && s->face->box != FACE_NO_BOX
2388 && (s->first_glyph->type == CHAR_GLYPH
2389 || s->first_glyph->type == COMPOSITE_GLYPH))
2392 x_set_glyph_string_clipping (s);
2393 x_draw_glyph_string_background (s, 1);
2394 x_draw_glyph_string_box (s);
2395 x_set_glyph_string_clipping (s);
2396 relief_drawn_p = 1;
2398 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2399 && !s->clip_tail
2400 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2401 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2402 /* We must clip just this glyph. left_overhang part has already
2403 drawn when s->prev was drawn, and right_overhang part will be
2404 drawn later when s->next is drawn. */
2405 x_set_glyph_string_clipping_exactly (s, s);
2406 else
2407 x_set_glyph_string_clipping (s);
2409 switch (s->first_glyph->type)
2411 case IMAGE_GLYPH:
2412 x_draw_image_glyph_string (s);
2413 break;
2415 case STRETCH_GLYPH:
2416 x_draw_stretch_glyph_string (s);
2417 break;
2419 case CHAR_GLYPH:
2420 if (s->for_overlaps)
2421 s->background_filled_p = 1;
2422 else
2423 x_draw_glyph_string_background (s, 0);
2424 x_draw_glyph_string_foreground (s);
2425 break;
2427 case COMPOSITE_GLYPH:
2428 if (s->for_overlaps || (s->cmp_from > 0
2429 && ! s->first_glyph->u.cmp.automatic))
2430 s->background_filled_p = 1;
2431 else
2432 x_draw_glyph_string_background (s, 1);
2433 x_draw_composite_glyph_string_foreground (s);
2434 break;
2436 case GLYPHLESS_GLYPH:
2437 if (s->for_overlaps)
2438 s->background_filled_p = 1;
2439 else
2440 x_draw_glyph_string_background (s, 0);
2441 x_draw_glyphless_glyph_string_foreground (s);
2442 break;
2444 default:
2445 emacs_abort ();
2448 if (!s->for_overlaps)
2450 /* Draw underline. */
2451 if (s->face->underline_p)
2453 if (s->face->underline_type == FACE_UNDER_WAVE)
2455 COLORREF color;
2457 if (s->face->underline_defaulted_p)
2458 color = s->gc->foreground;
2459 else
2460 color = s->face->underline_color;
2462 w32_draw_underwave (s, color);
2464 else if (s->face->underline_type == FACE_UNDER_LINE)
2466 unsigned long thickness, position;
2467 int y;
2469 if (s->prev && s->prev->face->underline_p)
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 /* Get the underline thickness. Default is 1 pixel. */
2478 if (s->font && s->font->underline_thickness > 0)
2479 thickness = s->font->underline_thickness;
2480 else
2481 thickness = 1;
2482 if (x_underline_at_descent_line)
2483 position = (s->height - thickness) - (s->ybase - s->y);
2484 else
2486 /* Get the underline position. This is the recommended
2487 vertical offset in pixels from the baseline to the top of
2488 the underline. This is a signed value according to the
2489 specs, and its default is
2491 ROUND ((maximum_descent) / 2), with
2492 ROUND (x) = floor (x + 0.5) */
2494 if (x_use_underline_position_properties
2495 && s->font && s->font->underline_position >= 0)
2496 position = s->font->underline_position;
2497 else if (s->font)
2498 position = (s->font->descent + 1) / 2;
2500 position = max (position, underline_minimum_offset);
2502 /* Check the sanity of thickness and position. We should
2503 avoid drawing underline out of the current line area. */
2504 if (s->y + s->height <= s->ybase + position)
2505 position = (s->height - 1) - (s->ybase - s->y);
2506 if (s->y + s->height < s->ybase + position + thickness)
2507 thickness = (s->y + s->height) - (s->ybase + position);
2508 s->underline_thickness = thickness;
2509 s->underline_position =position;
2510 y = s->ybase + position;
2511 if (s->face->underline_defaulted_p)
2513 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2514 y, s->width, 1);
2516 else
2518 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2519 y, s->width, 1);
2523 /* Draw overline. */
2524 if (s->face->overline_p)
2526 unsigned long dy = 0, h = 1;
2528 if (s->face->overline_color_defaulted_p)
2530 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2531 s->y + dy, s->width, h);
2533 else
2535 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2536 s->y + dy, s->width, h);
2540 /* Draw strike-through. */
2541 if (s->face->strike_through_p
2542 && !FONT_TEXTMETRIC (s->font).tmStruckOut)
2544 unsigned long h = 1;
2545 unsigned long dy = (s->height - h) / 2;
2547 if (s->face->strike_through_color_defaulted_p)
2549 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2550 s->width, h);
2552 else
2554 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
2555 s->y + dy, s->width, h);
2559 /* Draw relief if not yet drawn. */
2560 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2561 x_draw_glyph_string_box (s);
2563 if (s->prev)
2565 struct glyph_string *prev;
2567 for (prev = s->prev; prev; prev = prev->prev)
2568 if (prev->hl != s->hl
2569 && prev->x + prev->width + prev->right_overhang > s->x)
2571 /* As prev was drawn while clipped to its own area, we
2572 must draw the right_overhang part using s->hl now. */
2573 enum draw_glyphs_face save = prev->hl;
2575 prev->hl = s->hl;
2576 x_set_glyph_string_gc (prev);
2577 x_set_glyph_string_clipping_exactly (s, prev);
2578 if (prev->first_glyph->type == CHAR_GLYPH)
2579 x_draw_glyph_string_foreground (prev);
2580 else
2581 x_draw_composite_glyph_string_foreground (prev);
2582 w32_set_clip_rectangle (prev->hdc, NULL);
2583 prev->hl = save;
2584 prev->num_clips = 0;
2588 if (s->next)
2590 struct glyph_string *next;
2592 for (next = s->next; next; next = next->next)
2593 if (next->hl != s->hl
2594 && next->x - next->left_overhang < s->x + s->width)
2596 /* As next will be drawn while clipped to its own area,
2597 we must draw the left_overhang part using s->hl now. */
2598 enum draw_glyphs_face save = next->hl;
2600 next->hl = s->hl;
2601 x_set_glyph_string_gc (next);
2602 x_set_glyph_string_clipping_exactly (s, next);
2603 if (next->first_glyph->type == CHAR_GLYPH)
2604 x_draw_glyph_string_foreground (next);
2605 else
2606 x_draw_composite_glyph_string_foreground (next);
2607 w32_set_clip_rectangle (next->hdc, NULL);
2608 next->hl = save;
2609 next->num_clips = 0;
2610 next->clip_head = s->next;
2615 /* Reset clipping. */
2616 w32_set_clip_rectangle (s->hdc, NULL);
2617 s->num_clips = 0;
2621 /* Shift display to make room for inserted glyphs. */
2623 void
2624 w32_shift_glyphs_for_insert (struct frame *f, int x, int y,
2625 int width, int height, int shift_by)
2627 HDC hdc;
2629 hdc = get_frame_dc (f);
2630 BitBlt (hdc, x + shift_by, y, width, height,
2631 hdc, x, y, SRCCOPY);
2633 release_frame_dc (f, hdc);
2637 /* Delete N glyphs at the nominal cursor position. Not implemented
2638 for X frames. */
2640 static void
2641 x_delete_glyphs (struct frame *f, register int n)
2643 if (! FRAME_W32_P (f))
2644 return;
2646 emacs_abort ();
2650 /* Clear entire frame. */
2652 static void
2653 x_clear_frame (struct frame *f)
2655 if (! FRAME_W32_P (f))
2656 return;
2658 /* Clearing the frame will erase any cursor, so mark them all as no
2659 longer visible. */
2660 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2661 output_cursor.hpos = output_cursor.vpos = 0;
2662 output_cursor.x = -1;
2664 /* We don't set the output cursor here because there will always
2665 follow an explicit cursor_to. */
2666 block_input ();
2668 w32_clear_window (f);
2670 /* We have to clear the scroll bars, too. If we have changed
2671 colors or something like that, then they should be notified. */
2672 x_scroll_bar_clear (f);
2674 unblock_input ();
2678 /* Make audible bell. */
2680 static void
2681 w32_ring_bell (struct frame *f)
2683 block_input ();
2685 if (FRAME_W32_P (f) && visible_bell)
2687 int i;
2688 HWND hwnd = FRAME_W32_WINDOW (f);
2690 for (i = 0; i < 5; i++)
2692 FlashWindow (hwnd, TRUE);
2693 Sleep (10);
2695 FlashWindow (hwnd, FALSE);
2697 else
2698 w32_sys_ring_bell (f);
2700 unblock_input ();
2704 /* Specify how many text lines, from the top of the window,
2705 should be affected by insert-lines and delete-lines operations.
2706 This, and those operations, are used only within an update
2707 that is bounded by calls to x_update_begin and x_update_end. */
2709 static void
2710 w32_set_terminal_window (struct frame *f, int n)
2712 /* This function intentionally left blank. */
2716 /***********************************************************************
2717 Line Dance
2718 ***********************************************************************/
2720 /* Perform an insert-lines or delete-lines operation, inserting N
2721 lines or deleting -N lines at vertical position VPOS. */
2723 static void
2724 x_ins_del_lines (struct frame *f, int vpos, int n)
2726 if (! FRAME_W32_P (f))
2727 return;
2729 emacs_abort ();
2733 /* Scroll part of the display as described by RUN. */
2735 static void
2736 x_scroll_run (struct window *w, struct run *run)
2738 struct frame *f = XFRAME (w->frame);
2739 int x, y, width, height, from_y, to_y, bottom_y;
2740 HWND hwnd = FRAME_W32_WINDOW (f);
2741 HRGN expect_dirty;
2743 /* Get frame-relative bounding box of the text display area of W,
2744 without mode lines. Include in this box the left and right
2745 fringes of W. */
2746 window_box (w, -1, &x, &y, &width, &height);
2748 /* If the fringe is adjacent to the left (right) scroll bar of a
2749 leftmost (rightmost, respectively) window, then extend its
2750 background to the gap between the fringe and the bar. */
2751 if ((WINDOW_LEFTMOST_P (w)
2752 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2753 || (WINDOW_RIGHTMOST_P (w)
2754 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2756 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2758 if (sb_width > 0)
2760 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
2761 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2762 * FRAME_COLUMN_WIDTH (f));
2764 if (bar_area_x + bar_area_width == x)
2766 x = bar_area_x + sb_width;
2767 width += bar_area_width - sb_width;
2769 else if (x + width == bar_area_x)
2770 width += bar_area_width - sb_width;
2774 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2775 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2776 bottom_y = y + height;
2778 if (to_y < from_y)
2780 /* Scrolling up. Make sure we don't copy part of the mode
2781 line at the bottom. */
2782 if (from_y + run->height > bottom_y)
2783 height = bottom_y - from_y;
2784 else
2785 height = run->height;
2786 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2788 else
2790 /* Scrolling down. Make sure we don't copy over the mode line.
2791 at the bottom. */
2792 if (to_y + run->height > bottom_y)
2793 height = bottom_y - to_y;
2794 else
2795 height = run->height;
2796 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2799 block_input ();
2801 /* Cursor off. Will be switched on again in x_update_window_end. */
2802 updated_window = w;
2803 x_clear_cursor (w);
2806 RECT from;
2807 RECT to;
2808 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2809 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2811 from.left = to.left = x;
2812 from.right = to.right = x + width;
2813 from.top = from_y;
2814 from.bottom = from_y + height;
2815 to.top = y;
2816 to.bottom = bottom_y;
2818 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2819 NULL, SW_INVALIDATE);
2821 /* Combine this with what we expect to be dirty. This covers the
2822 case where not all of the region we expect is actually dirty. */
2823 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2825 /* If the dirty region is not what we expected, redraw the entire frame. */
2826 if (!EqualRgn (combined, expect_dirty))
2827 SET_FRAME_GARBAGED (f);
2829 DeleteObject (dirty);
2830 DeleteObject (combined);
2833 unblock_input ();
2834 DeleteObject (expect_dirty);
2839 /***********************************************************************
2840 Exposure Events
2841 ***********************************************************************/
2843 static void
2844 frame_highlight (struct frame *f)
2846 x_update_cursor (f, 1);
2847 x_set_frame_alpha (f);
2850 static void
2851 frame_unhighlight (struct frame *f)
2853 x_update_cursor (f, 1);
2854 x_set_frame_alpha (f);
2857 /* The focus has changed. Update the frames as necessary to reflect
2858 the new situation. Note that we can't change the selected frame
2859 here, because the Lisp code we are interrupting might become confused.
2860 Each event gets marked with the frame in which it occurred, so the
2861 Lisp code can tell when the switch took place by examining the events. */
2863 static void
2864 x_new_focus_frame (struct w32_display_info *dpyinfo, struct frame *frame)
2866 struct frame *old_focus = dpyinfo->w32_focus_frame;
2868 if (frame != dpyinfo->w32_focus_frame)
2870 /* Set this before calling other routines, so that they see
2871 the correct value of w32_focus_frame. */
2872 dpyinfo->w32_focus_frame = frame;
2874 if (old_focus && old_focus->auto_lower)
2875 x_lower_frame (old_focus);
2877 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2878 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2879 else
2880 pending_autoraise_frame = 0;
2883 x_frame_rehighlight (dpyinfo);
2887 /* Handle FocusIn and FocusOut state changes for FRAME.
2888 If FRAME has focus and there exists more than one frame, puts
2889 a FOCUS_IN_EVENT into *BUFP. */
2891 static void
2892 x_focus_changed (int type, int state, struct w32_display_info *dpyinfo,
2893 struct frame *frame, struct input_event *bufp)
2895 if (type == WM_SETFOCUS)
2897 if (dpyinfo->w32_focus_event_frame != frame)
2899 x_new_focus_frame (dpyinfo, frame);
2900 dpyinfo->w32_focus_event_frame = frame;
2902 /* Don't stop displaying the initial startup message
2903 for a switch-frame event we don't need. */
2904 if (NILP (Vterminal_frame)
2905 && CONSP (Vframe_list)
2906 && !NILP (XCDR (Vframe_list)))
2908 bufp->kind = FOCUS_IN_EVENT;
2909 XSETFRAME (bufp->frame_or_window, frame);
2913 frame->output_data.x->focus_state |= state;
2915 /* TODO: IME focus? */
2917 else if (type == WM_KILLFOCUS)
2919 frame->output_data.x->focus_state &= ~state;
2921 if (dpyinfo->w32_focus_event_frame == frame)
2923 dpyinfo->w32_focus_event_frame = 0;
2924 x_new_focus_frame (dpyinfo, 0);
2927 /* TODO: IME focus? */
2932 /* The focus may have changed. Figure out if it is a real focus change,
2933 by checking both FocusIn/Out and Enter/LeaveNotify events.
2935 Returns FOCUS_IN_EVENT event in *BUFP. */
2937 static void
2938 w32_detect_focus_change (struct w32_display_info *dpyinfo, W32Msg *event,
2939 struct input_event *bufp)
2941 struct frame *frame;
2943 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2944 if (! frame)
2945 return;
2947 /* On w32, this is only called from focus events, so no switch needed. */
2948 x_focus_changed (event->msg.message,
2949 (event->msg.message == WM_KILLFOCUS ?
2950 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2951 dpyinfo, frame, bufp);
2955 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2957 void
2958 x_mouse_leave (struct w32_display_info *dpyinfo)
2960 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2963 /* The focus has changed, or we have redirected a frame's focus to
2964 another frame (this happens when a frame uses a surrogate
2965 mini-buffer frame). Shift the highlight as appropriate.
2967 The FRAME argument doesn't necessarily have anything to do with which
2968 frame is being highlighted or un-highlighted; we only use it to find
2969 the appropriate X display info. */
2971 static void
2972 w32_frame_rehighlight (struct frame *frame)
2974 if (! FRAME_W32_P (frame))
2975 return;
2976 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
2979 static void
2980 x_frame_rehighlight (struct w32_display_info *dpyinfo)
2982 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2984 if (dpyinfo->w32_focus_frame)
2986 dpyinfo->x_highlight_frame
2987 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2988 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2989 : dpyinfo->w32_focus_frame);
2990 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2992 fset_focus_frame (dpyinfo->w32_focus_frame, Qnil);
2993 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2996 else
2997 dpyinfo->x_highlight_frame = 0;
2999 if (dpyinfo->x_highlight_frame != old_highlight)
3001 if (old_highlight)
3002 frame_unhighlight (old_highlight);
3003 if (dpyinfo->x_highlight_frame)
3004 frame_highlight (dpyinfo->x_highlight_frame);
3008 /* Keyboard processing - modifier keys, etc. */
3010 /* Convert a keysym to its name. */
3012 char *
3013 x_get_keysym_name (int keysym)
3015 /* Make static so we can always return it */
3016 static char value[100];
3018 block_input ();
3019 GetKeyNameText (keysym, value, 100);
3020 unblock_input ();
3022 return value;
3025 static int
3026 codepage_for_locale (LCID locale)
3028 char cp[20];
3030 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
3031 return atoi (cp);
3032 else
3033 return CP_ACP;
3037 /* Mouse clicks and mouse movement. Rah. */
3039 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3040 the state in PUP. XBUTTON provides extra information for extended mouse
3041 button messages. Returns FALSE if unable to parse the message. */
3042 BOOL
3043 parse_button (int message, int xbutton, int * pbutton, int * pup)
3045 int button = 0;
3046 int up = 0;
3048 switch (message)
3050 case WM_LBUTTONDOWN:
3051 button = 0;
3052 up = 0;
3053 break;
3054 case WM_LBUTTONUP:
3055 button = 0;
3056 up = 1;
3057 break;
3058 case WM_MBUTTONDOWN:
3059 if (NILP (Vw32_swap_mouse_buttons))
3060 button = 1;
3061 else
3062 button = 2;
3063 up = 0;
3064 break;
3065 case WM_MBUTTONUP:
3066 if (NILP (Vw32_swap_mouse_buttons))
3067 button = 1;
3068 else
3069 button = 2;
3070 up = 1;
3071 break;
3072 case WM_RBUTTONDOWN:
3073 if (NILP (Vw32_swap_mouse_buttons))
3074 button = 2;
3075 else
3076 button = 1;
3077 up = 0;
3078 break;
3079 case WM_RBUTTONUP:
3080 if (NILP (Vw32_swap_mouse_buttons))
3081 button = 2;
3082 else
3083 button = 1;
3084 up = 1;
3085 break;
3086 case WM_XBUTTONDOWN:
3087 button = xbutton + 2;
3088 up = 0;
3089 break;
3090 case WM_XBUTTONUP:
3091 button = xbutton + 2;
3092 up = 1;
3093 break;
3094 default:
3095 return (FALSE);
3098 if (pup) *pup = up;
3099 if (pbutton) *pbutton = button;
3101 return (TRUE);
3105 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3107 If the event is a button press, then note that we have grabbed
3108 the mouse. */
3110 static Lisp_Object
3111 construct_mouse_click (struct input_event *result, W32Msg *msg, struct frame *f)
3113 int button;
3114 int up;
3116 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3117 &button, &up);
3119 /* Make the event type NO_EVENT; we'll change that when we decide
3120 otherwise. */
3121 result->kind = MOUSE_CLICK_EVENT;
3122 result->code = button;
3123 result->timestamp = msg->msg.time;
3124 result->modifiers = (msg->dwModifiers
3125 | (up
3126 ? up_modifier
3127 : down_modifier));
3129 XSETINT (result->x, LOWORD (msg->msg.lParam));
3130 XSETINT (result->y, HIWORD (msg->msg.lParam));
3131 XSETFRAME (result->frame_or_window, f);
3132 result->arg = Qnil;
3133 return Qnil;
3136 static Lisp_Object
3137 construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
3139 POINT p;
3140 int delta;
3142 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3143 : WHEEL_EVENT;
3144 result->code = 0;
3145 result->timestamp = msg->msg.time;
3147 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3148 forward, away from the user (up); a negative value indicates that
3149 the wheel was rotated backward, toward the user (down). */
3150 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3152 /* The up and down modifiers indicate if the wheel was rotated up or
3153 down based on WHEEL_DELTA value. */
3154 result->modifiers = (msg->dwModifiers
3155 | ((delta < 0 ) ? down_modifier : up_modifier));
3157 /* With multiple monitors, we can legitimately get negative
3158 coordinates, so cast to short to interpret them correctly. */
3159 p.x = (short) LOWORD (msg->msg.lParam);
3160 p.y = (short) HIWORD (msg->msg.lParam);
3161 ScreenToClient (msg->msg.hwnd, &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 char *name;
3178 int i, len;
3180 result->kind = DRAG_N_DROP_EVENT;
3181 result->code = 0;
3182 result->timestamp = msg->msg.time;
3183 result->modifiers = msg->dwModifiers;
3185 hdrop = (HDROP) msg->msg.wParam;
3186 DragQueryPoint (hdrop, &p);
3188 #if 0
3189 p.x = LOWORD (msg->msg.lParam);
3190 p.y = HIWORD (msg->msg.lParam);
3191 ScreenToClient (msg->msg.hwnd, &p);
3192 #endif
3194 XSETINT (result->x, p.x);
3195 XSETINT (result->y, p.y);
3197 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3198 files = Qnil;
3200 for (i = 0; i < num_files; i++)
3202 len = DragQueryFile (hdrop, i, NULL, 0);
3203 if (len <= 0)
3204 continue;
3205 name = alloca (len + 1);
3206 DragQueryFile (hdrop, i, name, len + 1);
3207 files = Fcons (DECODE_FILE (build_string (name)), files);
3210 DragFinish (hdrop);
3212 XSETFRAME (frame, f);
3213 result->frame_or_window = frame;
3214 result->arg = files;
3215 return Qnil;
3219 /* File event notifications (see w32notify.c). */
3221 Lisp_Object
3222 lispy_file_action (DWORD action)
3224 static char unknown_fmt[] = "unknown-action(%d)";
3225 Lisp_Object retval;
3227 switch (action)
3229 case FILE_ACTION_ADDED:
3230 retval = Qadded;
3231 break;
3232 case FILE_ACTION_REMOVED:
3233 retval = Qremoved;
3234 break;
3235 case FILE_ACTION_MODIFIED:
3236 retval = Qmodified;
3237 break;
3238 case FILE_ACTION_RENAMED_OLD_NAME:
3239 retval = Qrenamed_from;
3240 break;
3241 case FILE_ACTION_RENAMED_NEW_NAME:
3242 retval = Qrenamed_to;
3243 break;
3244 default:
3246 char buf[sizeof(unknown_fmt) - 1 + INT_STRLEN_BOUND (DWORD)];
3248 sprintf (buf, unknown_fmt, action);
3249 retval = intern (buf);
3251 break;
3254 return retval;
3257 /* Put file notifications into the Emacs input event queue. This
3258 function runs when the WM_EMACS_FILENOTIFY message arrives from a
3259 watcher thread. */
3260 static void
3261 queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
3262 int *evcount)
3264 BYTE *p = file_notifications;
3265 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
3266 const DWORD min_size
3267 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
3268 Lisp_Object frame;
3270 /* We cannot process notification before Emacs is fully initialized,
3271 since we need the UTF-16LE coding-system to be set up. */
3272 if (!initialized)
3274 notification_buffer_in_use = 0;
3275 return;
3278 XSETFRAME (frame, f);
3280 enter_crit ();
3281 if (notification_buffer_in_use)
3283 DWORD info_size = notifications_size;
3284 Lisp_Object cs = intern ("utf-16le");
3285 Lisp_Object obj = w32_get_watch_object (notifications_desc);
3287 /* notifications_size could be zero when the buffer of
3288 notifications overflowed on the OS level, or when the
3289 directory being watched was itself deleted. Do nothing in
3290 that case. */
3291 if (info_size
3292 && !NILP (obj) && CONSP (obj))
3294 Lisp_Object callback = XCDR (obj);
3296 while (info_size >= min_size)
3298 Lisp_Object utf_16_fn
3299 = make_unibyte_string ((char *)fni->FileName,
3300 fni->FileNameLength);
3301 /* Note: mule-conf is preloaded, so utf-16le must
3302 already be defined at this point. */
3303 Lisp_Object fname
3304 = code_convert_string_norecord (utf_16_fn, cs, 0);
3305 Lisp_Object action = lispy_file_action (fni->Action);
3307 event->kind = FILE_NOTIFY_EVENT;
3308 event->code
3309 = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
3310 event->timestamp = msg->msg.time;
3311 event->modifiers = 0;
3312 event->frame_or_window = callback;
3313 event->arg = Fcons (action, fname);
3314 kbd_buffer_store_event (event);
3315 (*evcount)++;
3317 if (!fni->NextEntryOffset)
3318 break;
3319 p += fni->NextEntryOffset;
3320 fni = (PFILE_NOTIFY_INFORMATION)p;
3321 info_size -= fni->NextEntryOffset;
3324 notification_buffer_in_use = 0;
3326 else
3327 DebPrint (("We were promised notifications, but in-use flag is zero!\n"));
3328 leave_crit ();
3330 /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */
3331 event->kind = NO_EVENT;
3335 /* Function to report a mouse movement to the mainstream Emacs code.
3336 The input handler calls this.
3338 We have received a mouse movement event, which is given in *event.
3339 If the mouse is over a different glyph than it was last time, tell
3340 the mainstream emacs code by setting mouse_moved. If not, ask for
3341 another motion event, so we can check again the next time it moves. */
3343 static MSG last_mouse_motion_event;
3344 static Lisp_Object last_mouse_motion_frame;
3346 static int
3347 note_mouse_movement (FRAME_PTR frame, MSG *msg)
3349 int mouse_x = LOWORD (msg->lParam);
3350 int mouse_y = HIWORD (msg->lParam);
3352 last_mouse_movement_time = msg->time;
3353 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3354 XSETFRAME (last_mouse_motion_frame, frame);
3356 if (!FRAME_X_OUTPUT (frame))
3357 return 0;
3359 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3361 frame->mouse_moved = 1;
3362 last_mouse_scroll_bar = Qnil;
3363 note_mouse_highlight (frame, -1, -1);
3364 last_mouse_glyph_frame = 0;
3365 return 1;
3368 /* Has the mouse moved off the glyph it was on at the last sighting? */
3369 if (frame != last_mouse_glyph_frame
3370 || mouse_x < last_mouse_glyph.left
3371 || mouse_x >= last_mouse_glyph.right
3372 || mouse_y < last_mouse_glyph.top
3373 || mouse_y >= last_mouse_glyph.bottom)
3375 frame->mouse_moved = 1;
3376 last_mouse_scroll_bar = Qnil;
3377 note_mouse_highlight (frame, mouse_x, mouse_y);
3378 /* Remember the mouse position here, as w32_mouse_position only
3379 gets called when mouse tracking is enabled but we also need
3380 to keep track of the mouse for help_echo and highlighting at
3381 other times. */
3382 remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
3383 last_mouse_glyph_frame = frame;
3384 return 1;
3387 return 0;
3391 /************************************************************************
3392 Mouse Face
3393 ************************************************************************/
3395 static struct scroll_bar *x_window_to_scroll_bar (Window);
3396 static void x_scroll_bar_report_motion (FRAME_PTR *, Lisp_Object *,
3397 enum scroll_bar_part *,
3398 Lisp_Object *, Lisp_Object *,
3399 unsigned long *);
3400 static void x_check_fullscreen (struct frame *);
3402 static void
3403 redo_mouse_highlight (void)
3405 if (!NILP (last_mouse_motion_frame)
3406 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3407 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3408 LOWORD (last_mouse_motion_event.lParam),
3409 HIWORD (last_mouse_motion_event.lParam));
3412 static void
3413 w32_define_cursor (Window window, Cursor cursor)
3415 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3417 /* Return the current position of the mouse.
3418 *fp should be a frame which indicates which display to ask about.
3420 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3421 and *part to the frame, window, and scroll bar part that the mouse
3422 is over. Set *x and *y to the portion and whole of the mouse's
3423 position on the scroll bar.
3425 If the mouse movement started elsewhere, set *fp to the frame the
3426 mouse is on, *bar_window to nil, and *x and *y to the character cell
3427 the mouse is over.
3429 Set *time to the server time-stamp for the time at which the mouse
3430 was at this position.
3432 Don't store anything if we don't have a valid set of values to report.
3434 This clears the mouse_moved flag, so we can wait for the next mouse
3435 movement. */
3437 static void
3438 w32_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
3439 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3440 unsigned long *time)
3442 FRAME_PTR f1;
3444 block_input ();
3446 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3447 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3448 else
3450 POINT pt;
3452 Lisp_Object frame, tail;
3454 /* Clear the mouse-moved flag for every frame on this display. */
3455 FOR_EACH_FRAME (tail, frame)
3456 XFRAME (frame)->mouse_moved = 0;
3458 last_mouse_scroll_bar = Qnil;
3460 GetCursorPos (&pt);
3462 /* Now we have a position on the root; find the innermost window
3463 containing the pointer. */
3465 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3466 && FRAME_LIVE_P (last_mouse_frame))
3468 /* If mouse was grabbed on a frame, give coords for that frame
3469 even if the mouse is now outside it. */
3470 f1 = last_mouse_frame;
3472 else
3474 /* Is window under mouse one of our frames? */
3475 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
3476 WindowFromPoint (pt));
3479 /* If not, is it one of our scroll bars? */
3480 if (! f1)
3482 struct scroll_bar *bar
3483 = x_window_to_scroll_bar (WindowFromPoint (pt));
3485 if (bar)
3487 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3491 if (f1 == 0 && insist > 0)
3492 f1 = SELECTED_FRAME ();
3494 if (f1)
3496 /* Ok, we found a frame. Store all the values.
3497 last_mouse_glyph is a rectangle used to reduce the
3498 generation of mouse events. To not miss any motion
3499 events, we must divide the frame into rectangles of the
3500 size of the smallest character that could be displayed
3501 on it, i.e. into the same rectangles that matrices on
3502 the frame are divided into. */
3504 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3505 remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
3506 last_mouse_glyph_frame = f1;
3508 *bar_window = Qnil;
3509 *part = 0;
3510 *fp = f1;
3511 XSETINT (*x, pt.x);
3512 XSETINT (*y, pt.y);
3513 *time = last_mouse_movement_time;
3518 unblock_input ();
3522 /***********************************************************************
3523 Tool-bars
3524 ***********************************************************************/
3526 /* Handle mouse button event on the tool-bar of frame F, at
3527 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
3528 or ButtonRelease. */
3530 static void
3531 w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event)
3533 int x = XFASTINT (button_event->x);
3534 int y = XFASTINT (button_event->y);
3536 if (button_event->modifiers & down_modifier)
3537 handle_tool_bar_click (f, x, y, 1, 0);
3538 else
3539 handle_tool_bar_click (f, x, y, 0,
3540 button_event->modifiers & ~up_modifier);
3545 /***********************************************************************
3546 Scroll bars
3547 ***********************************************************************/
3549 /* Scroll bar support. */
3551 /* Given a window ID, find the struct scroll_bar which manages it.
3552 This can be called in GC, so we have to make sure to strip off mark
3553 bits. */
3555 static struct scroll_bar *
3556 x_window_to_scroll_bar (Window window_id)
3558 Lisp_Object tail, frame;
3560 FOR_EACH_FRAME (tail, frame)
3562 Lisp_Object bar, condemned;
3564 /* Scan this frame's scroll bar list for a scroll bar with the
3565 right window ID. */
3566 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3567 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3568 /* This trick allows us to search both the ordinary and
3569 condemned scroll bar lists with one loop. */
3570 ! NILP (bar) || (bar = condemned,
3571 condemned = Qnil,
3572 ! NILP (bar));
3573 bar = XSCROLL_BAR (bar)->next)
3574 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
3575 return XSCROLL_BAR (bar);
3578 return 0;
3583 /* Set the thumb size and position of scroll bar BAR. We are currently
3584 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3586 static void
3587 w32_set_scroll_bar_thumb (struct scroll_bar *bar,
3588 int portion, int position, int whole)
3590 Window w = SCROLL_BAR_W32_WINDOW (bar);
3591 /* We use the whole scroll-bar height in the calculations below, to
3592 avoid strange effects like scrolling backwards when just clicking
3593 on the handle (without moving it). */
3594 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
3595 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3596 int sb_page, sb_pos;
3597 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
3598 SCROLLINFO si;
3600 /* We used to change the nPage setting while dragging the handle,
3601 but that had very strange effects (such as scrolling backwards
3602 while dragging downwards).
3604 Now, we don't change the nPage setting while dragging unless we
3605 get near to the end of the buffer, in which case we often have to
3606 resize the handle to "go all the way". */
3608 if (draggingp)
3610 int near_bottom_p;
3611 block_input ();
3612 si.cbSize = sizeof (si);
3613 si.fMask = SIF_POS | SIF_PAGE;
3614 GetScrollInfo (w, SB_CTL, &si);
3615 near_bottom_p = si.nPos + si.nPage >= range;
3616 unblock_input ();
3617 if (!near_bottom_p)
3618 return;
3621 if (whole)
3623 /* Position scroll bar at rock bottom if the bottom of the
3624 buffer is visible. This avoids shrinking the thumb away
3625 to nothing if it is held at the bottom of the buffer. */
3626 if (position + portion >= whole && !draggingp)
3628 sb_page = range * (whole - position) / whole;
3629 sb_pos = range;
3631 else
3633 sb_pos = position * range / whole;
3634 sb_page = (min (portion, (whole - position)) * range) / whole;
3637 else
3639 sb_page = range;
3640 sb_pos = 0;
3643 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3645 block_input ();
3647 si.cbSize = sizeof (si);
3648 si.fMask = SIF_PAGE | SIF_POS;
3649 si.nPage = sb_page;
3650 si.nPos = sb_pos;
3652 SetScrollInfo (w, SB_CTL, &si, TRUE);
3654 unblock_input ();
3658 /************************************************************************
3659 Scroll bars, general
3660 ************************************************************************/
3662 static HWND
3663 my_create_scrollbar (struct frame * f, struct scroll_bar * bar)
3665 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3666 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
3667 (LPARAM) bar);
3670 /*#define ATTACH_THREADS*/
3672 static BOOL
3673 my_show_window (FRAME_PTR f, HWND hwnd, int how)
3675 #ifndef ATTACH_THREADS
3676 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3677 (WPARAM) hwnd, (LPARAM) how);
3678 #else
3679 return ShowWindow (hwnd, how);
3680 #endif
3683 static void
3684 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3685 int x, int y, int cx, int cy, UINT flags)
3687 #ifndef ATTACH_THREADS
3688 WINDOWPOS pos;
3689 pos.hwndInsertAfter = hwndAfter;
3690 pos.x = x;
3691 pos.y = y;
3692 pos.cx = cx;
3693 pos.cy = cy;
3694 pos.flags = flags;
3695 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3696 #else
3697 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3698 #endif
3701 #if 0
3702 static void
3703 my_set_focus (struct frame * f, HWND hwnd)
3705 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3706 (WPARAM) hwnd, 0);
3708 #endif
3710 static void
3711 my_set_foreground_window (HWND hwnd)
3713 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3717 static void
3718 my_destroy_window (struct frame * f, HWND hwnd)
3720 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3721 (WPARAM) hwnd, 0);
3724 static void
3725 my_bring_window_to_top (HWND hwnd)
3727 SendMessage (hwnd, WM_EMACS_BRINGTOTOP, (WPARAM) hwnd, 0);
3730 /* Create a scroll bar and return the scroll bar vector for it. W is
3731 the Emacs window on which to create the scroll bar. TOP, LEFT,
3732 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
3733 scroll bar. */
3735 static struct scroll_bar *
3736 x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
3738 struct frame *f = XFRAME (WINDOW_FRAME (w));
3739 HWND hwnd;
3740 SCROLLINFO si;
3741 struct scroll_bar *bar
3742 = XSCROLL_BAR (Fmake_vector (make_number (VECSIZE (struct scroll_bar)), Qnil));
3743 Lisp_Object barobj;
3745 block_input ();
3747 XSETWINDOW (bar->window, w);
3748 XSETINT (bar->top, top);
3749 XSETINT (bar->left, left);
3750 XSETINT (bar->width, width);
3751 XSETINT (bar->height, height);
3752 XSETINT (bar->start, 0);
3753 XSETINT (bar->end, 0);
3754 bar->dragging = Qnil;
3755 bar->fringe_extended_p = Qnil;
3757 /* Requires geometry to be set before call to create the real window */
3759 hwnd = my_create_scrollbar (f, bar);
3761 si.cbSize = sizeof (si);
3762 si.fMask = SIF_ALL;
3763 si.nMin = 0;
3764 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3765 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3766 si.nPage = si.nMax;
3767 si.nPos = 0;
3769 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3771 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3773 /* Add bar to its frame's list of scroll bars. */
3774 bar->next = FRAME_SCROLL_BARS (f);
3775 bar->prev = Qnil;
3776 XSETVECTOR (barobj, bar);
3777 fset_scroll_bars (f, barobj);
3778 if (! NILP (bar->next))
3779 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3781 unblock_input ();
3783 return bar;
3787 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3788 nil. */
3790 static void
3791 x_scroll_bar_remove (struct scroll_bar *bar)
3793 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3795 block_input ();
3797 /* Destroy the window. */
3798 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3800 /* Dissociate this scroll bar from its window. */
3801 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
3803 unblock_input ();
3806 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3807 that we are displaying PORTION characters out of a total of WHOLE
3808 characters, starting at POSITION. If WINDOW has no scroll bar,
3809 create one. */
3810 static void
3811 w32_set_vertical_scroll_bar (struct window *w,
3812 int portion, int whole, int position)
3814 struct frame *f = XFRAME (w->frame);
3815 Lisp_Object barobj;
3816 struct scroll_bar *bar;
3817 int top, height, left, sb_left, width, sb_width;
3818 int window_y, window_height;
3819 int fringe_extended_p;
3821 /* Get window dimensions. */
3822 window_box (w, -1, 0, &window_y, 0, &window_height);
3823 top = window_y;
3824 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3825 height = window_height;
3827 /* Compute the left edge of the scroll bar area. */
3828 left = WINDOW_SCROLL_BAR_AREA_X (w);
3830 /* Compute the width of the scroll bar which might be less than
3831 the width of the area reserved for the scroll bar. */
3832 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3833 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3834 else
3835 sb_width = width;
3837 /* Compute the left edge of the scroll bar. */
3838 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3839 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
3840 else
3841 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
3843 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3844 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
3845 && WINDOW_LEFT_FRINGE_WIDTH (w)
3846 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3847 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
3848 else
3849 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
3850 && WINDOW_RIGHT_FRINGE_WIDTH (w)
3851 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3852 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
3854 /* Does the scroll bar exist yet? */
3855 if (NILP (w->vertical_scroll_bar))
3857 HDC hdc;
3858 block_input ();
3859 if (width > 0 && height > 0)
3861 hdc = get_frame_dc (f);
3862 if (fringe_extended_p)
3863 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3864 else
3865 w32_clear_area (f, hdc, left, top, width, height);
3866 release_frame_dc (f, hdc);
3868 unblock_input ();
3870 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
3872 else
3874 /* It may just need to be moved and resized. */
3875 HWND hwnd;
3877 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3878 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3880 /* If already correctly positioned, do nothing. */
3881 if ( XINT (bar->left) == sb_left
3882 && XINT (bar->top) == top
3883 && XINT (bar->width) == sb_width
3884 && XINT (bar->height) == height
3885 && !NILP (bar->fringe_extended_p) == fringe_extended_p )
3887 /* Redraw after clear_frame. */
3888 if (!my_show_window (f, hwnd, SW_NORMAL))
3889 InvalidateRect (hwnd, NULL, FALSE);
3891 else
3893 HDC hdc;
3894 SCROLLINFO si;
3896 block_input ();
3897 if (width && height)
3899 hdc = get_frame_dc (f);
3900 /* Since Windows scroll bars are smaller than the space reserved
3901 for them on the frame, we have to clear "under" them. */
3902 if (fringe_extended_p)
3903 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3904 else
3905 w32_clear_area (f, hdc, left, top, width, height);
3906 release_frame_dc (f, hdc);
3908 /* Make sure scroll bar is "visible" before moving, to ensure the
3909 area of the parent window now exposed will be refreshed. */
3910 my_show_window (f, hwnd, SW_HIDE);
3911 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3912 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3913 max (height, 1), TRUE);
3915 si.cbSize = sizeof (si);
3916 si.fMask = SIF_RANGE;
3917 si.nMin = 0;
3918 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3919 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3921 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3923 my_show_window (f, hwnd, SW_NORMAL);
3924 /* InvalidateRect (w, NULL, FALSE); */
3926 /* Remember new settings. */
3927 XSETINT (bar->left, sb_left);
3928 XSETINT (bar->top, top);
3929 XSETINT (bar->width, sb_width);
3930 XSETINT (bar->height, height);
3932 unblock_input ();
3935 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
3937 w32_set_scroll_bar_thumb (bar, portion, position, whole);
3938 XSETVECTOR (barobj, bar);
3939 wset_vertical_scroll_bar (w, barobj);
3943 /* The following three hooks are used when we're doing a thorough
3944 redisplay of the frame. We don't explicitly know which scroll bars
3945 are going to be deleted, because keeping track of when windows go
3946 away is a real pain - "Can you say set-window-configuration, boys
3947 and girls?" Instead, we just assert at the beginning of redisplay
3948 that *all* scroll bars are to be removed, and then save a scroll bar
3949 from the fiery pit when we actually redisplay its window. */
3951 /* Arrange for all scroll bars on FRAME to be removed at the next call
3952 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3953 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3955 static void
3956 w32_condemn_scroll_bars (FRAME_PTR frame)
3958 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3959 while (! NILP (FRAME_SCROLL_BARS (frame)))
3961 Lisp_Object bar;
3962 bar = FRAME_SCROLL_BARS (frame);
3963 fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
3964 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3965 XSCROLL_BAR (bar)->prev = Qnil;
3966 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3967 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
3968 fset_condemned_scroll_bars (frame, bar);
3973 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3974 Note that WINDOW isn't necessarily condemned at all. */
3976 static void
3977 w32_redeem_scroll_bar (struct window *window)
3979 struct scroll_bar *bar;
3980 Lisp_Object barobj;
3981 struct frame *f;
3983 /* We can't redeem this window's scroll bar if it doesn't have one. */
3984 if (NILP (window->vertical_scroll_bar))
3985 emacs_abort ();
3987 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3989 /* Unlink it from the condemned list. */
3990 f = XFRAME (WINDOW_FRAME (window));
3991 if (NILP (bar->prev))
3993 /* If the prev pointer is nil, it must be the first in one of
3994 the lists. */
3995 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3996 /* It's not condemned. Everything's fine. */
3997 return;
3998 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3999 window->vertical_scroll_bar))
4000 fset_condemned_scroll_bars (f, bar->next);
4001 else
4002 /* If its prev pointer is nil, it must be at the front of
4003 one or the other! */
4004 emacs_abort ();
4006 else
4007 XSCROLL_BAR (bar->prev)->next = bar->next;
4009 if (! NILP (bar->next))
4010 XSCROLL_BAR (bar->next)->prev = bar->prev;
4012 bar->next = FRAME_SCROLL_BARS (f);
4013 bar->prev = Qnil;
4014 XSETVECTOR (barobj, bar);
4015 fset_scroll_bars (f, barobj);
4016 if (! NILP (bar->next))
4017 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4020 /* Remove all scroll bars on FRAME that haven't been saved since the
4021 last call to `*condemn_scroll_bars_hook'. */
4023 static void
4024 w32_judge_scroll_bars (FRAME_PTR f)
4026 Lisp_Object bar, next;
4028 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4030 /* Clear out the condemned list now so we won't try to process any
4031 more events on the hapless scroll bars. */
4032 fset_condemned_scroll_bars (f, Qnil);
4034 for (; ! NILP (bar); bar = next)
4036 struct scroll_bar *b = XSCROLL_BAR (bar);
4038 x_scroll_bar_remove (b);
4040 next = b->next;
4041 b->next = b->prev = Qnil;
4044 /* Now there should be no references to the condemned scroll bars,
4045 and they should get garbage-collected. */
4048 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4049 is set to something other than NO_EVENT, it is enqueued.
4051 This may be called from a signal handler, so we have to ignore GC
4052 mark bits. */
4054 static int
4055 w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4056 struct input_event *emacs_event)
4058 if (! WINDOWP (bar->window))
4059 emacs_abort ();
4061 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
4062 emacs_event->code = 0;
4063 /* not really meaningful to distinguish up/down */
4064 emacs_event->modifiers = msg->dwModifiers;
4065 emacs_event->frame_or_window = bar->window;
4066 emacs_event->arg = Qnil;
4067 emacs_event->timestamp = msg->msg.time;
4070 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4071 int y;
4072 int dragging = !NILP (bar->dragging);
4073 SCROLLINFO si;
4075 si.cbSize = sizeof (si);
4076 si.fMask = SIF_POS;
4078 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4079 y = si.nPos;
4081 bar->dragging = Qnil;
4084 last_mouse_scroll_bar_pos = msg->msg.wParam;
4086 switch (LOWORD (msg->msg.wParam))
4088 case SB_LINEDOWN:
4089 emacs_event->part = scroll_bar_down_arrow;
4090 break;
4091 case SB_LINEUP:
4092 emacs_event->part = scroll_bar_up_arrow;
4093 break;
4094 case SB_PAGEUP:
4095 emacs_event->part = scroll_bar_above_handle;
4096 break;
4097 case SB_PAGEDOWN:
4098 emacs_event->part = scroll_bar_below_handle;
4099 break;
4100 case SB_TOP:
4101 emacs_event->part = scroll_bar_handle;
4102 y = 0;
4103 break;
4104 case SB_BOTTOM:
4105 emacs_event->part = scroll_bar_handle;
4106 y = top_range;
4107 break;
4108 case SB_THUMBTRACK:
4109 case SB_THUMBPOSITION:
4110 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
4111 y = HIWORD (msg->msg.wParam);
4112 bar->dragging = Qt;
4113 emacs_event->part = scroll_bar_handle;
4115 /* "Silently" update current position. */
4117 SCROLLINFO si;
4119 si.cbSize = sizeof (si);
4120 si.fMask = SIF_POS;
4121 si.nPos = y;
4122 /* Remember apparent position (we actually lag behind the real
4123 position, so don't set that directly). */
4124 last_scroll_bar_drag_pos = y;
4126 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4128 break;
4129 case SB_ENDSCROLL:
4130 /* If this is the end of a drag sequence, then reset the scroll
4131 handle size to normal and do a final redraw. Otherwise do
4132 nothing. */
4133 if (dragging)
4135 SCROLLINFO si;
4136 int start = XINT (bar->start);
4137 int end = XINT (bar->end);
4139 si.cbSize = sizeof (si);
4140 si.fMask = SIF_PAGE | SIF_POS;
4141 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
4142 si.nPos = last_scroll_bar_drag_pos;
4143 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
4145 /* fall through */
4146 default:
4147 emacs_event->kind = NO_EVENT;
4148 return FALSE;
4151 XSETINT (emacs_event->x, y);
4152 XSETINT (emacs_event->y, top_range);
4154 return TRUE;
4158 /* Return information to the user about the current position of the mouse
4159 on the scroll bar. */
4161 static void
4162 x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
4163 enum scroll_bar_part *part,
4164 Lisp_Object *x, Lisp_Object *y,
4165 unsigned long *time)
4167 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4168 Window w = SCROLL_BAR_W32_WINDOW (bar);
4169 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4170 int pos;
4171 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4172 SCROLLINFO si;
4174 block_input ();
4176 *fp = f;
4177 *bar_window = bar->window;
4179 si.cbSize = sizeof (si);
4180 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
4182 GetScrollInfo (w, SB_CTL, &si);
4183 pos = si.nPos;
4184 top_range = si.nMax - si.nPage + 1;
4186 switch (LOWORD (last_mouse_scroll_bar_pos))
4188 case SB_THUMBPOSITION:
4189 case SB_THUMBTRACK:
4190 *part = scroll_bar_handle;
4191 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
4192 pos = HIWORD (last_mouse_scroll_bar_pos);
4193 break;
4194 case SB_LINEDOWN:
4195 *part = scroll_bar_handle;
4196 pos++;
4197 break;
4198 default:
4199 *part = scroll_bar_handle;
4200 break;
4203 XSETINT (*x, pos);
4204 XSETINT (*y, top_range);
4206 f->mouse_moved = 0;
4207 last_mouse_scroll_bar = Qnil;
4209 *time = last_mouse_movement_time;
4211 unblock_input ();
4215 /* The screen has been cleared so we may have changed foreground or
4216 background colors, and the scroll bars may need to be redrawn.
4217 Clear out the scroll bars, and ask for expose events, so we can
4218 redraw them. */
4220 void
4221 x_scroll_bar_clear (FRAME_PTR f)
4223 Lisp_Object bar;
4225 /* We can have scroll bars even if this is 0,
4226 if we just turned off scroll bar mode.
4227 But in that case we should not clear them. */
4228 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4229 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4230 bar = XSCROLL_BAR (bar)->next)
4232 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4233 HDC hdc = GetDC (window);
4234 RECT rect;
4236 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4237 arranges to refresh the scroll bar if hidden. */
4238 my_show_window (f, window, SW_HIDE);
4240 GetClientRect (window, &rect);
4241 select_palette (f, hdc);
4242 w32_clear_rect (f, hdc, &rect);
4243 deselect_palette (f, hdc);
4245 ReleaseDC (window, hdc);
4250 /* The main W32 event-reading loop - w32_read_socket. */
4252 /* Record the last 100 characters stored
4253 to help debug the loss-of-chars-during-GC problem. */
4255 static int temp_index;
4256 static short temp_buffer[100];
4258 /* Temporarily store lead byte of DBCS input sequences. */
4259 static char dbcs_lead = 0;
4261 /* Read events coming from the W32 shell.
4262 This routine is called by the SIGIO handler.
4263 We return as soon as there are no more events to be read.
4265 For an overview of how Emacs input works on MS-Windows, see the
4266 commentary before w32_msg_pump in w32fns.c.
4268 We return the number of characters stored into the buffer,
4269 thus pretending to be `read'.
4271 Some of these messages are reposted back to the message queue since the
4272 system calls the windows proc directly in a context where we cannot return
4273 the data nor can we guarantee the state we are in. So if we dispatch them
4274 we will get into an infinite loop. To prevent this from ever happening we
4275 will set a variable to indicate we are in the read_socket call and indicate
4276 which message we are processing since the windows proc gets called
4277 recursively with different messages by the system.
4280 static int
4281 w32_read_socket (struct terminal *terminal,
4282 struct input_event *hold_quit)
4284 int count = 0;
4285 int check_visibility = 0;
4286 W32Msg msg;
4287 struct frame *f;
4288 struct w32_display_info *dpyinfo = &one_w32_display_info;
4289 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
4290 static char buf[1];
4292 block_input ();
4294 /* So people can tell when we have read the available input. */
4295 input_signal_count++;
4297 /* Process any incoming thread messages. */
4298 drain_message_queue ();
4300 /* TODO: ghostscript integration. */
4301 while (get_next_msg (&msg, FALSE))
4303 struct input_event inev;
4304 int do_help = 0;
4306 /* DebPrint (("w32_read_socket: %s time:%u\n", */
4307 /* w32_name_of_message (msg.msg.message), */
4308 /* msg.msg.time)); */
4310 EVENT_INIT (inev);
4311 inev.kind = NO_EVENT;
4312 inev.arg = Qnil;
4314 switch (msg.msg.message)
4316 case WM_EMACS_PAINT:
4317 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4319 if (f)
4321 if (msg.rect.right == msg.rect.left ||
4322 msg.rect.bottom == msg.rect.top)
4324 /* We may get paint messages even though the client
4325 area is clipped - these are not expose events. */
4326 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4327 SDATA (f->name)));
4329 else if (f->async_visible != 1)
4331 /* Definitely not obscured, so mark as visible. */
4332 f->async_visible = 1;
4333 f->async_iconified = 0;
4334 SET_FRAME_GARBAGED (f);
4335 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4336 SDATA (f->name)));
4338 /* WM_PAINT serves as MapNotify as well, so report
4339 visibility changes properly. */
4340 if (f->iconified)
4342 inev.kind = DEICONIFY_EVENT;
4343 XSETFRAME (inev.frame_or_window, f);
4345 else if (! NILP (Vframe_list)
4346 && ! NILP (XCDR (Vframe_list)))
4347 /* Force a redisplay sooner or later to update the
4348 frame titles in case this is the second frame. */
4349 record_asynch_buffer_change ();
4351 else
4353 HDC hdc = get_frame_dc (f);
4355 /* Erase background again for safety. */
4356 w32_clear_rect (f, hdc, &msg.rect);
4357 release_frame_dc (f, hdc);
4358 expose_frame (f,
4359 msg.rect.left,
4360 msg.rect.top,
4361 msg.rect.right - msg.rect.left,
4362 msg.rect.bottom - msg.rect.top);
4365 break;
4367 case WM_INPUTLANGCHANGE:
4368 /* Generate a language change event. */
4369 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4371 /* lParam contains the input language ID in its low 16 bits.
4372 Use it to update our record of the keyboard codepage. */
4373 w32_keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4374 & 0xffff));
4376 if (f)
4378 inev.kind = LANGUAGE_CHANGE_EVENT;
4379 XSETFRAME (inev.frame_or_window, f);
4380 inev.code = w32_keyboard_codepage;
4381 inev.modifiers = msg.msg.lParam & 0xffff;
4383 break;
4385 case WM_KEYDOWN:
4386 case WM_SYSKEYDOWN:
4387 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4389 if (f && !f->iconified)
4391 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4392 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4394 clear_mouse_face (hlinfo);
4395 hlinfo->mouse_face_hidden = 1;
4398 if (temp_index == sizeof temp_buffer / sizeof (short))
4399 temp_index = 0;
4400 temp_buffer[temp_index++] = msg.msg.wParam;
4401 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4402 inev.code = msg.msg.wParam;
4403 inev.modifiers = msg.dwModifiers;
4404 XSETFRAME (inev.frame_or_window, f);
4405 inev.timestamp = msg.msg.time;
4407 break;
4409 case WM_UNICHAR:
4410 case WM_SYSCHAR:
4411 case WM_CHAR:
4412 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4414 if (f && !f->iconified)
4416 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4417 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4419 clear_mouse_face (hlinfo);
4420 hlinfo->mouse_face_hidden = 1;
4423 if (temp_index == sizeof temp_buffer / sizeof (short))
4424 temp_index = 0;
4425 temp_buffer[temp_index++] = msg.msg.wParam;
4427 inev.modifiers = msg.dwModifiers;
4428 XSETFRAME (inev.frame_or_window, f);
4429 inev.timestamp = msg.msg.time;
4431 if (msg.msg.message == WM_UNICHAR)
4433 inev.code = msg.msg.wParam;
4435 else if (msg.msg.wParam < 256)
4437 wchar_t code;
4438 char dbcs[2];
4439 dbcs[0] = 0;
4440 dbcs[1] = (char) msg.msg.wParam;
4442 if (dbcs_lead)
4444 dbcs[0] = dbcs_lead;
4445 dbcs_lead = 0;
4446 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
4447 dbcs, 2, &code, 1))
4449 /* Garbage */
4450 DebPrint (("Invalid DBCS sequence: %d %d\n",
4451 dbcs[0], dbcs[1]));
4452 inev.kind = NO_EVENT;
4453 break;
4456 else if (IsDBCSLeadByteEx (w32_keyboard_codepage,
4457 (BYTE) msg.msg.wParam))
4459 dbcs_lead = (char) msg.msg.wParam;
4460 inev.kind = NO_EVENT;
4461 break;
4463 else
4465 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
4466 &dbcs[1], 1, &code, 1))
4468 /* What to do with garbage? */
4469 DebPrint (("Invalid character: %d\n", dbcs[1]));
4470 inev.kind = NO_EVENT;
4471 break;
4474 inev.code = code;
4476 else
4478 /* Windows shouldn't generate WM_CHAR events above 0xFF
4479 in non-Unicode message handlers. */
4480 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4481 inev.kind = NO_EVENT;
4482 break;
4484 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4485 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
4487 break;
4489 case WM_APPCOMMAND:
4490 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4492 if (f && !f->iconified)
4494 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4495 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4497 clear_mouse_face (hlinfo);
4498 hlinfo->mouse_face_hidden = 1;
4501 if (temp_index == sizeof temp_buffer / sizeof (short))
4502 temp_index = 0;
4503 temp_buffer[temp_index++] = msg.msg.wParam;
4504 inev.kind = MULTIMEDIA_KEY_EVENT;
4505 inev.code = GET_APPCOMMAND_LPARAM (msg.msg.lParam);
4506 inev.modifiers = msg.dwModifiers;
4507 XSETFRAME (inev.frame_or_window, f);
4508 inev.timestamp = msg.msg.time;
4510 break;
4512 case WM_MOUSEMOVE:
4513 /* Ignore non-movement. */
4515 int x = LOWORD (msg.msg.lParam);
4516 int y = HIWORD (msg.msg.lParam);
4517 if (x == last_mousemove_x && y == last_mousemove_y)
4518 break;
4519 last_mousemove_x = x;
4520 last_mousemove_y = y;
4523 previous_help_echo_string = help_echo_string;
4524 help_echo_string = Qnil;
4526 if (dpyinfo->grabbed && last_mouse_frame
4527 && FRAME_LIVE_P (last_mouse_frame))
4528 f = last_mouse_frame;
4529 else
4530 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4532 if (hlinfo->mouse_face_hidden)
4534 hlinfo->mouse_face_hidden = 0;
4535 clear_mouse_face (hlinfo);
4538 if (f)
4540 /* Generate SELECT_WINDOW_EVENTs when needed. */
4541 if (!NILP (Vmouse_autoselect_window))
4543 Lisp_Object window;
4544 int x = LOWORD (msg.msg.lParam);
4545 int y = HIWORD (msg.msg.lParam);
4547 window = window_from_coordinates (f, x, y, 0, 0);
4549 /* Window will be selected only when it is not
4550 selected now and last mouse movement event was
4551 not in it. Minibuffer window will be selected
4552 only when it is active. */
4553 if (WINDOWP (window)
4554 && !EQ (window, last_window)
4555 && !EQ (window, selected_window)
4556 /* For click-to-focus window managers
4557 create event iff we don't leave the
4558 selected frame. */
4559 && (focus_follows_mouse
4560 || (EQ (XWINDOW (window)->frame,
4561 XWINDOW (selected_window)->frame))))
4563 inev.kind = SELECT_WINDOW_EVENT;
4564 inev.frame_or_window = window;
4567 last_window = window;
4569 if (!note_mouse_movement (f, &msg.msg))
4570 help_echo_string = previous_help_echo_string;
4572 else
4574 /* If we move outside the frame, then we're
4575 certainly no longer on any text in the frame. */
4576 clear_mouse_face (hlinfo);
4579 /* If the contents of the global variable help_echo_string
4580 has changed, generate a HELP_EVENT. */
4581 #if 0 /* The below is an invalid comparison when CHECK_LISP_OBJECT_TYPE.
4582 But it was originally changed to this to fix a bug, so I have
4583 not removed it completely in case the bug is still there. */
4584 if (help_echo_string != previous_help_echo_string ||
4585 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4586 #else /* This is what xterm.c does. */
4587 if (!NILP (help_echo_string)
4588 || !NILP (previous_help_echo_string))
4589 do_help = 1;
4590 #endif
4591 break;
4593 case WM_LBUTTONDOWN:
4594 case WM_LBUTTONUP:
4595 case WM_MBUTTONDOWN:
4596 case WM_MBUTTONUP:
4597 case WM_RBUTTONDOWN:
4598 case WM_RBUTTONUP:
4599 case WM_XBUTTONDOWN:
4600 case WM_XBUTTONUP:
4602 /* If we decide we want to generate an event to be seen
4603 by the rest of Emacs, we put it here. */
4604 int tool_bar_p = 0;
4605 int button;
4606 int up;
4608 if (dpyinfo->grabbed && last_mouse_frame
4609 && FRAME_LIVE_P (last_mouse_frame))
4610 f = last_mouse_frame;
4611 else
4612 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4614 if (f)
4616 construct_mouse_click (&inev, &msg, f);
4618 /* Is this in the tool-bar? */
4619 if (WINDOWP (f->tool_bar_window)
4620 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
4622 Lisp_Object window;
4623 int x = XFASTINT (inev.x);
4624 int y = XFASTINT (inev.y);
4626 window = window_from_coordinates (f, x, y, 0, 1);
4628 if (EQ (window, f->tool_bar_window))
4630 w32_handle_tool_bar_click (f, &inev);
4631 tool_bar_p = 1;
4635 if (tool_bar_p
4636 || (dpyinfo->w32_focus_frame
4637 && f != dpyinfo->w32_focus_frame))
4638 inev.kind = NO_EVENT;
4641 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4642 &button, &up);
4644 if (up)
4646 dpyinfo->grabbed &= ~ (1 << button);
4648 else
4650 dpyinfo->grabbed |= (1 << button);
4651 last_mouse_frame = f;
4652 /* Ignore any mouse motion that happened
4653 before this event; any subsequent mouse-movement
4654 Emacs events should reflect only motion after
4655 the ButtonPress. */
4656 if (f != 0)
4657 f->mouse_moved = 0;
4659 if (!tool_bar_p)
4660 last_tool_bar_item = -1;
4662 break;
4665 case WM_MOUSEWHEEL:
4666 case WM_MOUSEHWHEEL:
4668 if (dpyinfo->grabbed && last_mouse_frame
4669 && FRAME_LIVE_P (last_mouse_frame))
4670 f = last_mouse_frame;
4671 else
4672 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4674 if (f)
4677 if (!dpyinfo->w32_focus_frame
4678 || f == dpyinfo->w32_focus_frame)
4680 /* Emit an Emacs wheel-up/down event. */
4681 construct_mouse_wheel (&inev, &msg, f);
4683 /* Ignore any mouse motion that happened before this
4684 event; any subsequent mouse-movement Emacs events
4685 should reflect only motion after the
4686 ButtonPress. */
4687 f->mouse_moved = 0;
4689 last_mouse_frame = f;
4690 last_tool_bar_item = -1;
4692 break;
4694 case WM_DROPFILES:
4695 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4697 if (f)
4698 construct_drag_n_drop (&inev, &msg, f);
4699 break;
4701 case WM_VSCROLL:
4703 struct scroll_bar *bar =
4704 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
4706 if (bar)
4707 w32_scroll_bar_handle_click (bar, &msg, &inev);
4708 break;
4711 case WM_WINDOWPOSCHANGED:
4712 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4713 if (f)
4715 if (f->want_fullscreen & FULLSCREEN_WAIT)
4716 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
4718 check_visibility = 1;
4719 break;
4721 case WM_ACTIVATE:
4722 case WM_ACTIVATEAPP:
4723 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4724 if (f)
4725 x_check_fullscreen (f);
4726 check_visibility = 1;
4727 break;
4729 case WM_MOVE:
4730 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4732 if (f && !f->async_iconified)
4734 int x, y;
4736 x_real_positions (f, &x, &y);
4737 f->left_pos = x;
4738 f->top_pos = y;
4741 check_visibility = 1;
4742 break;
4744 case WM_SHOWWINDOW:
4745 /* wParam non-zero means Window is about to be shown, 0 means
4746 about to be hidden. */
4747 /* Redo the mouse-highlight after the tooltip has gone. */
4748 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4750 tip_window = NULL;
4751 redo_mouse_highlight ();
4754 /* If window has been obscured or exposed by another window
4755 being maximized or minimized/restored, then recheck
4756 visibility of all frames. Direct changes to our own
4757 windows get handled by WM_SIZE. */
4758 #if 0
4759 if (msg.msg.lParam != 0)
4760 check_visibility = 1;
4761 else
4763 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4764 f->async_visible = msg.msg.wParam;
4766 #endif
4768 check_visibility = 1;
4769 break;
4771 case WM_SIZE:
4772 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4774 /* Inform lisp of whether frame has been iconified etc. */
4775 if (f)
4777 switch (msg.msg.wParam)
4779 case SIZE_MINIMIZED:
4780 f->async_visible = 0;
4781 f->async_iconified = 1;
4783 inev.kind = ICONIFY_EVENT;
4784 XSETFRAME (inev.frame_or_window, f);
4785 break;
4787 case SIZE_MAXIMIZED:
4788 case SIZE_RESTORED:
4789 f->async_visible = 1;
4790 f->async_iconified = 0;
4792 /* wait_reading_process_output will notice this and update
4793 the frame's display structures. */
4794 SET_FRAME_GARBAGED (f);
4796 if (f->iconified)
4798 int x, y;
4800 /* Reset top and left positions of the Window
4801 here since Windows sends a WM_MOVE message
4802 BEFORE telling us the Window is minimized
4803 when the Window is iconified, with 3000,3000
4804 as the co-ords. */
4805 x_real_positions (f, &x, &y);
4806 f->left_pos = x;
4807 f->top_pos = y;
4809 inev.kind = DEICONIFY_EVENT;
4810 XSETFRAME (inev.frame_or_window, f);
4812 else if (! NILP (Vframe_list)
4813 && ! NILP (XCDR (Vframe_list)))
4814 /* Force a redisplay sooner or later
4815 to update the frame titles
4816 in case this is the second frame. */
4817 record_asynch_buffer_change ();
4818 break;
4822 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
4824 RECT rect;
4825 int rows;
4826 int columns;
4827 int width;
4828 int height;
4830 GetClientRect (msg.msg.hwnd, &rect);
4832 height = rect.bottom - rect.top;
4833 width = rect.right - rect.left;
4835 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4836 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
4838 /* TODO: Clip size to the screen dimensions. */
4840 /* Even if the number of character rows and columns has
4841 not changed, the font size may have changed, so we need
4842 to check the pixel dimensions as well. */
4844 if (columns != FRAME_COLS (f)
4845 || rows != FRAME_LINES (f)
4846 || width != FRAME_PIXEL_WIDTH (f)
4847 || height != FRAME_PIXEL_HEIGHT (f))
4849 change_frame_size (f, rows, columns, 0, 1, 0);
4850 SET_FRAME_GARBAGED (f);
4851 cancel_mouse_face (f);
4852 FRAME_PIXEL_WIDTH (f) = width;
4853 FRAME_PIXEL_HEIGHT (f) = height;
4854 f->win_gravity = NorthWestGravity;
4858 check_visibility = 1;
4859 break;
4861 case WM_MOUSELEAVE:
4862 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4863 if (f)
4865 if (f == hlinfo->mouse_face_mouse_frame)
4867 /* If we move outside the frame, then we're
4868 certainly no longer on any text in the frame. */
4869 clear_mouse_face (hlinfo);
4870 hlinfo->mouse_face_mouse_frame = 0;
4873 /* Generate a nil HELP_EVENT to cancel a help-echo.
4874 Do it only if there's something to cancel.
4875 Otherwise, the startup message is cleared when
4876 the mouse leaves the frame. */
4877 if (any_help_event_p)
4878 do_help = -1;
4880 break;
4882 case WM_SETFOCUS:
4883 w32_detect_focus_change (dpyinfo, &msg, &inev);
4885 dpyinfo->grabbed = 0;
4886 check_visibility = 1;
4887 break;
4889 case WM_KILLFOCUS:
4890 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
4892 if (f)
4894 if (f == dpyinfo->w32_focus_event_frame)
4895 dpyinfo->w32_focus_event_frame = 0;
4897 if (f == dpyinfo->w32_focus_frame)
4898 x_new_focus_frame (dpyinfo, 0);
4900 if (f == hlinfo->mouse_face_mouse_frame)
4902 /* If we move outside the frame, then we're
4903 certainly no longer on any text in the frame. */
4904 clear_mouse_face (hlinfo);
4905 hlinfo->mouse_face_mouse_frame = 0;
4908 /* Generate a nil HELP_EVENT to cancel a help-echo.
4909 Do it only if there's something to cancel.
4910 Otherwise, the startup message is cleared when
4911 the mouse leaves the frame. */
4912 if (any_help_event_p)
4913 do_help = -1;
4916 dpyinfo->grabbed = 0;
4917 check_visibility = 1;
4918 break;
4920 case WM_CLOSE:
4921 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4923 if (f)
4925 inev.kind = DELETE_WINDOW_EVENT;
4926 XSETFRAME (inev.frame_or_window, f);
4928 break;
4930 case WM_INITMENU:
4931 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4933 if (f)
4935 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4936 XSETFRAME (inev.frame_or_window, f);
4938 break;
4940 case WM_COMMAND:
4941 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4943 if (f)
4945 extern void menubar_selection_callback
4946 (FRAME_PTR f, void * client_data);
4947 menubar_selection_callback (f, (void *)msg.msg.wParam);
4950 check_visibility = 1;
4951 break;
4953 case WM_DISPLAYCHANGE:
4954 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4956 if (f)
4958 dpyinfo->n_cbits = msg.msg.wParam;
4959 DebPrint (("display change: %d %d\n",
4960 (short) LOWORD (msg.msg.lParam),
4961 (short) HIWORD (msg.msg.lParam)));
4964 check_visibility = 1;
4965 break;
4967 case WM_EMACS_FILENOTIFY:
4968 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4969 if (f)
4970 queue_notifications (&inev, &msg, f, &count);
4971 break;
4973 default:
4974 /* Check for messages registered at runtime. */
4975 if (msg.msg.message == msh_mousewheel)
4977 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4978 msg.msg.message = WM_MOUSEWHEEL;
4979 prepend_msg (&msg);
4981 break;
4984 if (inev.kind != NO_EVENT)
4986 kbd_buffer_store_event_hold (&inev, hold_quit);
4987 count++;
4990 if (do_help
4991 && !(hold_quit && hold_quit->kind != NO_EVENT))
4993 Lisp_Object frame;
4995 if (f)
4996 XSETFRAME (frame, f);
4997 else
4998 frame = Qnil;
5000 if (do_help > 0)
5002 if (NILP (help_echo_string))
5004 help_echo_object = help_echo_window = Qnil;
5005 help_echo_pos = -1;
5008 any_help_event_p = 1;
5009 gen_help_event (help_echo_string, frame, help_echo_window,
5010 help_echo_object, help_echo_pos);
5012 else
5014 help_echo_string = Qnil;
5015 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
5017 count++;
5021 /* If the focus was just given to an autoraising frame,
5022 raise it now. */
5023 /* ??? This ought to be able to handle more than one such frame. */
5024 if (pending_autoraise_frame)
5026 x_raise_frame (pending_autoraise_frame);
5027 pending_autoraise_frame = 0;
5030 /* Check which frames are still visible, if we have enqueued any user
5031 events or been notified of events that may affect visibility. We
5032 do this here because there doesn't seem to be any direct
5033 notification from Windows that the visibility of a window has
5034 changed (at least, not in all cases). */
5035 if (count > 0 || check_visibility)
5037 Lisp_Object tail, frame;
5039 FOR_EACH_FRAME (tail, frame)
5041 FRAME_PTR f = XFRAME (frame);
5042 /* The tooltip has been drawn already. Avoid the
5043 SET_FRAME_GARBAGED below. */
5044 if (EQ (frame, tip_frame))
5045 continue;
5047 /* Check "visible" frames and mark each as obscured or not.
5048 Note that async_visible is nonzero for unobscured and
5049 obscured frames, but zero for hidden and iconified frames. */
5050 if (FRAME_W32_P (f) && f->async_visible)
5052 RECT clipbox;
5053 HDC hdc;
5055 enter_crit ();
5056 /* Query clipping rectangle for the entire window area
5057 (GetWindowDC), not just the client portion (GetDC).
5058 Otherwise, the scrollbars and menubar aren't counted as
5059 part of the visible area of the frame, and we may think
5060 the frame is obscured when really a scrollbar is still
5061 visible and gets WM_PAINT messages above. */
5062 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
5063 GetClipBox (hdc, &clipbox);
5064 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
5065 leave_crit ();
5067 if (clipbox.right == clipbox.left
5068 || clipbox.bottom == clipbox.top)
5070 /* Frame has become completely obscured so mark as
5071 such (we do this by setting async_visible to 2 so
5072 that FRAME_VISIBLE_P is still true, but redisplay
5073 will skip it). */
5074 f->async_visible = 2;
5076 if (!FRAME_OBSCURED_P (f))
5078 DebPrint (("frame %p (%s) obscured\n", f,
5079 SDATA (f->name)));
5082 else
5084 /* Frame is not obscured, so mark it as such. */
5085 f->async_visible = 1;
5087 if (FRAME_OBSCURED_P (f))
5089 SET_FRAME_GARBAGED (f);
5090 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
5091 SDATA (f->name)));
5093 /* Force a redisplay sooner or later. */
5094 record_asynch_buffer_change ();
5101 unblock_input ();
5102 return count;
5107 /***********************************************************************
5108 Text Cursor
5109 ***********************************************************************/
5111 /* Set clipping for output in glyph row ROW. W is the window in which
5112 we operate. GC is the graphics context to set clipping in.
5114 ROW may be a text row or, e.g., a mode line. Text rows must be
5115 clipped to the interior of the window dedicated to text display,
5116 mode lines must be clipped to the whole window. */
5118 static void
5119 w32_clip_to_row (struct window *w, struct glyph_row *row, int area, HDC hdc)
5121 RECT clip_rect;
5122 int window_x, window_y, window_width;
5124 window_box (w, area, &window_x, &window_y, &window_width, 0);
5126 clip_rect.left = window_x;
5127 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5128 clip_rect.top = max (clip_rect.top, window_y);
5129 clip_rect.right = clip_rect.left + window_width;
5130 clip_rect.bottom = clip_rect.top + row->visible_height;
5132 w32_set_clip_rectangle (hdc, &clip_rect);
5136 /* Draw a hollow box cursor on window W in glyph row ROW. */
5138 static void
5139 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
5141 struct frame *f = XFRAME (WINDOW_FRAME (w));
5142 HDC hdc;
5143 RECT rect;
5144 int left, top, h;
5145 struct glyph *cursor_glyph;
5146 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
5148 /* Get the glyph the cursor is on. If we can't tell because
5149 the current matrix is invalid or such, give up. */
5150 cursor_glyph = get_phys_cursor_glyph (w);
5151 if (cursor_glyph == NULL)
5152 return;
5154 /* Compute frame-relative coordinates for phys cursor. */
5155 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
5156 rect.left = left;
5157 rect.top = top;
5158 rect.bottom = rect.top + h;
5159 rect.right = rect.left + w->phys_cursor_width;
5161 hdc = get_frame_dc (f);
5162 /* Set clipping, draw the rectangle, and reset clipping again. */
5163 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5164 FrameRect (hdc, &rect, hb);
5165 DeleteObject (hb);
5166 w32_set_clip_rectangle (hdc, NULL);
5167 release_frame_dc (f, hdc);
5171 /* Draw a bar cursor on window W in glyph row ROW.
5173 Implementation note: One would like to draw a bar cursor with an
5174 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5175 Unfortunately, I didn't find a font yet that has this property set.
5176 --gerd. */
5178 static void
5179 x_draw_bar_cursor (struct window *w, struct glyph_row *row,
5180 int width, enum text_cursor_kinds kind)
5182 struct frame *f = XFRAME (w->frame);
5183 struct glyph *cursor_glyph;
5185 /* If cursor is out of bounds, don't draw garbage. This can happen
5186 in mini-buffer windows when switching between echo area glyphs
5187 and mini-buffer. */
5188 cursor_glyph = get_phys_cursor_glyph (w);
5189 if (cursor_glyph == NULL)
5190 return;
5192 /* If on an image, draw like a normal cursor. That's usually better
5193 visible than drawing a bar, esp. if the image is large so that
5194 the bar might not be in the window. */
5195 if (cursor_glyph->type == IMAGE_GLYPH)
5197 struct glyph_row *row;
5198 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5199 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5201 else
5203 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5204 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5205 int x;
5206 HDC hdc;
5208 /* If the glyph's background equals the color we normally draw
5209 the bar cursor in, the bar cursor in its normal color is
5210 invisible. Use the glyph's foreground color instead in this
5211 case, on the assumption that the glyph's colors are chosen so
5212 that the glyph is legible. */
5213 if (face->background == cursor_color)
5214 cursor_color = face->foreground;
5216 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5218 hdc = get_frame_dc (f);
5219 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5221 if (kind == BAR_CURSOR)
5223 if (width < 0)
5224 width = FRAME_CURSOR_WIDTH (f);
5225 width = min (cursor_glyph->pixel_width, width);
5227 w->phys_cursor_width = width;
5229 /* If the character under cursor is R2L, draw the bar cursor
5230 on the right of its glyph, rather than on the left. */
5231 if ((cursor_glyph->resolved_level & 1) != 0)
5232 x += cursor_glyph->pixel_width - width;
5234 w32_fill_area (f, hdc, cursor_color, x,
5235 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5236 width, row->height);
5238 else
5240 int dummy_x, dummy_y, dummy_h;
5242 if (width < 0)
5243 width = row->height;
5245 width = min (row->height, width);
5247 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5248 &dummy_y, &dummy_h);
5249 w32_fill_area (f, hdc, cursor_color, x,
5250 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5251 row->height - width),
5252 w->phys_cursor_width, width);
5255 w32_set_clip_rectangle (hdc, NULL);
5256 release_frame_dc (f, hdc);
5261 /* RIF: Define cursor CURSOR on frame F. */
5263 static void
5264 w32_define_frame_cursor (struct frame *f, Cursor cursor)
5266 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5270 /* RIF: Clear area on frame F. */
5272 static void
5273 w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
5275 HDC hdc;
5277 hdc = get_frame_dc (f);
5278 w32_clear_area (f, hdc, x, y, width, height);
5279 release_frame_dc (f, hdc);
5282 /* RIF: Draw or clear cursor on window W. */
5284 static void
5285 w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
5286 int x, int y, int cursor_type, int cursor_width,
5287 int on_p, int active_p)
5289 if (on_p)
5291 /* If the user wants to use the system caret, make sure our own
5292 cursor remains invisible. */
5293 if (w32_use_visible_system_caret)
5295 /* Call to erase_phys_cursor here seems to use the
5296 wrong values of w->phys_cursor, as they have been
5297 overwritten before this function was called. */
5298 if (w->phys_cursor_type != NO_CURSOR)
5299 erase_phys_cursor (w);
5301 cursor_type = w->phys_cursor_type = NO_CURSOR;
5302 w->phys_cursor_width = -1;
5304 else
5306 w->phys_cursor_type = cursor_type;
5309 w->phys_cursor_on_p = 1;
5311 /* If this is the active cursor, we need to track it with the
5312 system caret, so third party software like screen magnifiers
5313 and speech synthesizers can follow the cursor. */
5314 if (active_p)
5316 struct frame *f = XFRAME (WINDOW_FRAME (w));
5317 HWND hwnd = FRAME_W32_WINDOW (f);
5319 w32_system_caret_x
5320 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5321 w32_system_caret_y
5322 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5323 + glyph_row->ascent - w->phys_cursor_ascent);
5325 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5327 /* If the size of the active cursor changed, destroy the old
5328 system caret. */
5329 if (w32_system_caret_hwnd
5330 && (w32_system_caret_height != w->phys_cursor_height))
5331 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5333 w32_system_caret_height = w->phys_cursor_height;
5335 /* Move the system caret. */
5336 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5339 if (glyph_row->exact_window_width_line_p
5340 && (glyph_row->reversed_p
5341 ? (w->phys_cursor.hpos < 0)
5342 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
5344 glyph_row->cursor_in_fringe_p = 1;
5345 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
5346 return;
5349 switch (cursor_type)
5351 case HOLLOW_BOX_CURSOR:
5352 x_draw_hollow_cursor (w, glyph_row);
5353 break;
5355 case FILLED_BOX_CURSOR:
5356 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5357 break;
5359 case BAR_CURSOR:
5360 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5361 break;
5363 case HBAR_CURSOR:
5364 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5365 break;
5367 case NO_CURSOR:
5368 w->phys_cursor_width = 0;
5369 break;
5371 default:
5372 emacs_abort ();
5379 /* Icons. */
5382 x_bitmap_icon (struct frame *f, Lisp_Object icon)
5384 HANDLE main_icon;
5385 HANDLE small_icon = NULL;
5387 if (FRAME_W32_WINDOW (f) == 0)
5388 return 1;
5390 if (NILP (icon))
5391 main_icon = LoadIcon (hinst, EMACS_CLASS);
5392 else if (STRINGP (icon))
5394 /* Load the main icon from the named file. */
5395 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5396 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5397 /* Try to load a small icon to go with it. */
5398 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5399 GetSystemMetrics (SM_CXSMICON),
5400 GetSystemMetrics (SM_CYSMICON),
5401 LR_LOADFROMFILE);
5403 else if (SYMBOLP (icon))
5405 LPCTSTR name;
5407 if (EQ (icon, intern ("application")))
5408 name = (LPCTSTR) IDI_APPLICATION;
5409 else if (EQ (icon, intern ("hand")))
5410 name = (LPCTSTR) IDI_HAND;
5411 else if (EQ (icon, intern ("question")))
5412 name = (LPCTSTR) IDI_QUESTION;
5413 else if (EQ (icon, intern ("exclamation")))
5414 name = (LPCTSTR) IDI_EXCLAMATION;
5415 else if (EQ (icon, intern ("asterisk")))
5416 name = (LPCTSTR) IDI_ASTERISK;
5417 else if (EQ (icon, intern ("winlogo")))
5418 name = (LPCTSTR) IDI_WINLOGO;
5419 else
5420 return 1;
5422 main_icon = LoadIcon (NULL, name);
5424 else
5425 return 1;
5427 if (main_icon == NULL)
5428 return 1;
5430 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5431 (LPARAM) main_icon);
5433 /* If there is a small icon that goes with it, set that too. */
5434 if (small_icon)
5435 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5436 (LPARAM) small_icon);
5438 return 0;
5442 /************************************************************************
5443 Handling X errors
5444 ************************************************************************/
5446 /* Display Error Handling functions not used on W32. Listing them here
5447 helps diff stay in step when comparing w32term.c with xterm.c.
5449 x_error_catcher (display, error)
5450 x_catch_errors (dpy)
5451 x_catch_errors_unwind (old_val)
5452 x_check_errors (dpy, format)
5453 x_fully_uncatch_errors ()
5454 x_had_errors_p (dpy)
5455 x_clear_errors (dpy)
5456 x_uncatch_errors (dpy, count)
5457 x_trace_wire ()
5458 x_connection_signal (signalnum)
5459 x_connection_closed (dpy, error_message)
5460 x_error_quitter (display, error)
5461 x_error_handler (display, error)
5462 x_io_error_quitter (display)
5467 /* Changing the font of the frame. */
5469 Lisp_Object
5470 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
5472 struct font *font = XFONT_OBJECT (font_object);
5474 if (fontset < 0)
5475 fontset = fontset_from_font (font_object);
5476 FRAME_FONTSET (f) = fontset;
5477 if (FRAME_FONT (f) == font)
5478 /* This font is already set in frame F. There's nothing more to
5479 do. */
5480 return font_object;
5482 FRAME_FONT (f) = font;
5483 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5484 FRAME_COLUMN_WIDTH (f) = font->average_width;
5485 FRAME_SPACE_WIDTH (f) = font->space_width;
5486 FRAME_LINE_HEIGHT (f) = font->height;
5488 compute_fringe_widths (f, 1);
5490 /* Compute the scroll bar width in character columns. */
5491 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5493 int wid = FRAME_COLUMN_WIDTH (f);
5494 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5495 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
5497 else
5499 int wid = FRAME_COLUMN_WIDTH (f);
5500 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5503 /* Now make the frame display the given font. */
5504 if (FRAME_X_WINDOW (f) != 0)
5506 /* Don't change the size of a tip frame; there's no point in
5507 doing it because it's done in Fx_show_tip, and it leads to
5508 problems because the tip frame has no widget. */
5509 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5510 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5513 /* X version sets font of input methods here also. */
5515 return font_object;
5519 /***********************************************************************
5520 TODO: W32 Input Methods
5521 ***********************************************************************/
5522 /* Listing missing functions from xterm.c helps diff stay in step.
5524 xim_destroy_callback (xim, client_data, call_data)
5525 xim_open_dpy (dpyinfo, resource_name)
5526 struct xim_inst_t
5527 xim_instantiate_callback (display, client_data, call_data)
5528 xim_initialize (dpyinfo, resource_name)
5529 xim_close_dpy (dpyinfo)
5534 /* Calculate the absolute position in frame F
5535 from its current recorded position values and gravity. */
5537 void
5538 x_calc_absolute_position (struct frame *f)
5540 int flags = f->size_hint_flags;
5542 /* The sum of the widths of the frame's left and right borders, and
5543 the sum of the heights of the frame's top and bottom borders (in
5544 pixels) drawn by Windows. */
5545 unsigned int left_right_borders_width, top_bottom_borders_height;
5547 /* Try to get the actual values of these two variables. We compute
5548 the border width (height) by subtracting the width (height) of
5549 the frame's client area from the width (height) of the frame's
5550 entire window. */
5551 WINDOWPLACEMENT wp = { 0 };
5552 RECT client_rect = { 0 };
5554 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
5555 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
5557 left_right_borders_width =
5558 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
5559 (client_rect.right - client_rect.left);
5561 top_bottom_borders_height =
5562 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
5563 (client_rect.bottom - client_rect.top);
5565 else
5567 /* Use sensible default values. */
5568 left_right_borders_width = 8;
5569 top_bottom_borders_height = 32;
5572 /* Treat negative positions as relative to the rightmost bottommost
5573 position that fits on the screen. */
5574 if (flags & XNegative)
5575 f->left_pos = (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f))
5576 - FRAME_PIXEL_WIDTH (f)
5577 + f->left_pos
5578 - (left_right_borders_width - 1));
5580 if (flags & YNegative)
5581 f->top_pos = (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f))
5582 - FRAME_PIXEL_HEIGHT (f)
5583 + f->top_pos
5584 - (top_bottom_borders_height - 1));
5586 /* The left_pos and top_pos are now relative to the top and left
5587 screen edges, so the flags should correspond. */
5588 f->size_hint_flags &= ~ (XNegative | YNegative);
5591 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5592 to really change the position, and 0 when calling from
5593 x_make_frame_visible (in that case, XOFF and YOFF are the current
5594 position values). It is -1 when calling from x_set_frame_parameters,
5595 which means, do adjust for borders but don't change the gravity. */
5597 void
5598 x_set_offset (struct frame *f, register int xoff, register int yoff,
5599 int change_gravity)
5601 int modified_top, modified_left;
5603 if (change_gravity > 0)
5605 f->top_pos = yoff;
5606 f->left_pos = xoff;
5607 f->size_hint_flags &= ~ (XNegative | YNegative);
5608 if (xoff < 0)
5609 f->size_hint_flags |= XNegative;
5610 if (yoff < 0)
5611 f->size_hint_flags |= YNegative;
5612 f->win_gravity = NorthWestGravity;
5614 x_calc_absolute_position (f);
5616 block_input ();
5617 x_wm_set_size_hint (f, (long) 0, 0);
5619 modified_left = f->left_pos;
5620 modified_top = f->top_pos;
5622 my_set_window_pos (FRAME_W32_WINDOW (f),
5623 NULL,
5624 modified_left, modified_top,
5625 0, 0,
5626 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
5627 unblock_input ();
5631 /* Check if we need to resize the frame due to a fullscreen request.
5632 If so needed, resize the frame. */
5633 static void
5634 x_check_fullscreen (struct frame *f)
5636 if (f->want_fullscreen & FULLSCREEN_BOTH)
5638 int width, height, ign;
5640 x_real_positions (f, &f->left_pos, &f->top_pos);
5642 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
5644 /* We do not need to move the window, it shall be taken care of
5645 when setting WM manager hints. */
5646 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
5648 change_frame_size (f, height, width, 0, 1, 0);
5649 SET_FRAME_GARBAGED (f);
5650 cancel_mouse_face (f);
5652 /* Wait for the change of frame size to occur. */
5653 f->want_fullscreen |= FULLSCREEN_WAIT;
5658 /* Call this to change the size of frame F's x-window.
5659 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5660 for this size change and subsequent size changes.
5661 Otherwise we leave the window gravity unchanged. */
5663 void
5664 x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
5666 int pixelwidth, pixelheight;
5668 block_input ();
5670 check_frame_size (f, &rows, &cols);
5671 f->scroll_bar_actual_width
5672 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5674 compute_fringe_widths (f, 0);
5676 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5677 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5679 f->win_gravity = NorthWestGravity;
5680 x_wm_set_size_hint (f, (long) 0, 0);
5683 RECT rect;
5685 rect.left = rect.top = 0;
5686 rect.right = pixelwidth;
5687 rect.bottom = pixelheight;
5689 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5690 FRAME_EXTERNAL_MENU_BAR (f));
5692 my_set_window_pos (FRAME_W32_WINDOW (f),
5693 NULL,
5694 0, 0,
5695 rect.right - rect.left,
5696 rect.bottom - rect.top,
5697 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5700 #if 0
5701 /* The following mirrors what is done in xterm.c. It appears to be
5702 for informing lisp of the new size immediately, while the actual
5703 resize will happen asynchronously. But on Windows, the menu bar
5704 automatically wraps when the frame is too narrow to contain it,
5705 and that causes any calculations made here to come out wrong. The
5706 end is some nasty buggy behavior, including the potential loss
5707 of the minibuffer.
5709 Disabling this code is either not sufficient to fix the problems
5710 completely, or it causes fresh problems, but at least it removes
5711 the most problematic symptom of the minibuffer becoming unusable.
5713 -----------------------------------------------------------------
5715 Now, strictly speaking, we can't be sure that this is accurate,
5716 but the window manager will get around to dealing with the size
5717 change request eventually, and we'll hear how it went when the
5718 ConfigureNotify event gets here.
5720 We could just not bother storing any of this information here,
5721 and let the ConfigureNotify event set everything up, but that
5722 might be kind of confusing to the Lisp code, since size changes
5723 wouldn't be reported in the frame parameters until some random
5724 point in the future when the ConfigureNotify event arrives.
5726 We pass 1 for DELAY since we can't run Lisp code inside of
5727 a BLOCK_INPUT. */
5728 change_frame_size (f, rows, cols, 0, 1, 0);
5729 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5730 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5732 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5733 receive in the ConfigureNotify event; if we get what we asked
5734 for, then the event won't cause the screen to become garbaged, so
5735 we have to make sure to do it here. */
5736 SET_FRAME_GARBAGED (f);
5738 /* If cursor was outside the new size, mark it as off. */
5739 mark_window_cursors_off (XWINDOW (f->root_window));
5741 /* Clear out any recollection of where the mouse highlighting was,
5742 since it might be in a place that's outside the new frame size.
5743 Actually checking whether it is outside is a pain in the neck,
5744 so don't try--just let the highlighting be done afresh with new size. */
5745 cancel_mouse_face (f);
5746 #endif
5748 unblock_input ();
5751 /* Mouse warping. */
5753 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5755 void
5756 x_set_mouse_position (struct frame *f, int x, int y)
5758 int pix_x, pix_y;
5760 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5761 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5763 if (pix_x < 0) pix_x = 0;
5764 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5766 if (pix_y < 0) pix_y = 0;
5767 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5769 x_set_mouse_pixel_position (f, pix_x, pix_y);
5772 void
5773 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
5775 RECT rect;
5776 POINT pt;
5778 block_input ();
5780 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5781 pt.x = rect.left + pix_x;
5782 pt.y = rect.top + pix_y;
5783 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
5785 SetCursorPos (pt.x, pt.y);
5787 unblock_input ();
5791 /* focus shifting, raising and lowering. */
5793 void
5794 x_focus_on_frame (struct frame *f)
5796 struct w32_display_info *dpyinfo = &one_w32_display_info;
5798 /* Give input focus to frame. */
5799 block_input ();
5800 #if 0
5801 /* Try not to change its Z-order if possible. */
5802 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5803 my_set_focus (f, FRAME_W32_WINDOW (f));
5804 else
5805 #endif
5806 my_set_foreground_window (FRAME_W32_WINDOW (f));
5807 unblock_input ();
5810 void
5811 x_unfocus_frame (struct frame *f)
5815 /* Raise frame F. */
5816 void
5817 x_raise_frame (struct frame *f)
5819 block_input ();
5821 /* Strictly speaking, raise-frame should only change the frame's Z
5822 order, leaving input focus unchanged. This is reasonable behavior
5823 on X where the usual policy is point-to-focus. However, this
5824 behavior would be very odd on Windows where the usual policy is
5825 click-to-focus.
5827 On X, if the mouse happens to be over the raised frame, it gets
5828 input focus anyway (so the window with focus will never be
5829 completely obscured) - if not, then just moving the mouse over it
5830 is sufficient to give it focus. On Windows, the user must actually
5831 click on the frame (preferably the title bar so as not to move
5832 point), which is more awkward. Also, no other Windows program
5833 raises a window to the top but leaves another window (possibly now
5834 completely obscured) with input focus.
5836 Because there is a system setting on Windows that allows the user
5837 to choose the point to focus policy, we make the strict semantics
5838 optional, but by default we grab focus when raising. */
5840 if (NILP (Vw32_grab_focus_on_raise))
5842 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5843 not already the foreground application: the frame is raised
5844 above all other frames belonging to us, but not above the
5845 current top window. To achieve that, we have to resort to this
5846 more cumbersome method. */
5848 HDWP handle = BeginDeferWindowPos (2);
5849 if (handle)
5851 handle = DeferWindowPos (handle,
5852 FRAME_W32_WINDOW (f),
5853 HWND_TOP,
5854 0, 0, 0, 0,
5855 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5856 if (handle)
5858 handle = DeferWindowPos (handle,
5859 GetForegroundWindow (),
5860 FRAME_W32_WINDOW (f),
5861 0, 0, 0, 0,
5862 SWP_NOSIZE | SWP_NOMOVE |
5863 SWP_NOACTIVATE);
5864 if (handle)
5865 EndDeferWindowPos (handle);
5869 else
5871 my_bring_window_to_top (FRAME_W32_WINDOW (f));
5874 unblock_input ();
5877 /* Lower frame F. */
5878 void
5879 x_lower_frame (struct frame *f)
5881 block_input ();
5882 my_set_window_pos (FRAME_W32_WINDOW (f),
5883 HWND_BOTTOM,
5884 0, 0, 0, 0,
5885 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5886 unblock_input ();
5889 static void
5890 w32_frame_raise_lower (FRAME_PTR f, int raise_flag)
5892 if (! FRAME_W32_P (f))
5893 return;
5895 if (raise_flag)
5896 x_raise_frame (f);
5897 else
5898 x_lower_frame (f);
5901 /* Change of visibility. */
5903 /* This tries to wait until the frame is really visible.
5904 However, if the window manager asks the user where to position
5905 the frame, this will return before the user finishes doing that.
5906 The frame will not actually be visible at that time,
5907 but it will become visible later when the window manager
5908 finishes with it. */
5910 void
5911 x_make_frame_visible (struct frame *f)
5913 Lisp_Object type;
5915 block_input ();
5917 type = x_icon_type (f);
5918 if (!NILP (type))
5919 x_bitmap_icon (f, type);
5921 if (! FRAME_VISIBLE_P (f))
5923 /* We test FRAME_GARBAGED_P here to make sure we don't
5924 call x_set_offset a second time
5925 if we get to x_make_frame_visible a second time
5926 before the window gets really visible. */
5927 if (! FRAME_ICONIFIED_P (f)
5928 && ! f->output_data.w32->asked_for_visible)
5930 RECT workarea_rect;
5931 RECT window_rect;
5933 /* Adjust vertical window position in order to avoid being
5934 covered by a task bar placed at the bottom of the desktop. */
5935 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
5936 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
5937 if (window_rect.bottom > workarea_rect.bottom
5938 && window_rect.top > workarea_rect.top)
5939 f->top_pos = max (window_rect.top
5940 - window_rect.bottom + workarea_rect.bottom,
5941 workarea_rect.top);
5943 x_set_offset (f, f->left_pos, f->top_pos, 0);
5946 f->output_data.w32->asked_for_visible = 1;
5948 /* According to a report in emacs-devel 2008-06-03, SW_SHOWNORMAL
5949 causes unexpected behavior when unminimizing frames that were
5950 previously maximized. But only SW_SHOWNORMAL works properly for
5951 frames that were truely hidden (using make-frame-invisible), so
5952 we need it to avoid Bug#5482. It seems that async_iconified
5953 is only set for minimized windows that are still visible, so
5954 use that to determine the appropriate flag to pass ShowWindow. */
5955 my_show_window (f, FRAME_W32_WINDOW (f),
5956 f->async_iconified ? SW_RESTORE : SW_SHOWNORMAL);
5959 /* Synchronize to ensure Emacs knows the frame is visible
5960 before we do anything else. We do this loop with input not blocked
5961 so that incoming events are handled. */
5963 Lisp_Object frame;
5964 int count;
5966 /* This must come after we set COUNT. */
5967 unblock_input ();
5969 XSETFRAME (frame, f);
5971 /* Wait until the frame is visible. Process X events until a
5972 MapNotify event has been seen, or until we think we won't get a
5973 MapNotify at all.. */
5974 for (count = input_signal_count + 10;
5975 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5977 /* Force processing of queued events. */
5978 /* TODO: x_sync equivalent? */
5980 /* Machines that do polling rather than SIGIO have been observed
5981 to go into a busy-wait here. So we'll fake an alarm signal
5982 to let the handler know that there's something to be read.
5983 We used to raise a real alarm, but it seems that the handler
5984 isn't always enabled here. This is probably a bug. */
5985 if (input_polling_used ())
5987 /* It could be confusing if a real alarm arrives while processing
5988 the fake one. Turn it off and let the handler reset it. */
5989 int old_poll_suppress_count = poll_suppress_count;
5990 poll_suppress_count = 1;
5991 poll_for_input_1 ();
5992 poll_suppress_count = old_poll_suppress_count;
5995 FRAME_SAMPLE_VISIBILITY (f);
5999 /* Change from mapped state to withdrawn state. */
6001 /* Make the frame visible (mapped and not iconified). */
6003 void
6004 x_make_frame_invisible (struct frame *f)
6006 /* Don't keep the highlight on an invisible frame. */
6007 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
6008 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
6010 block_input ();
6012 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
6014 /* We can't distinguish this from iconification
6015 just by the event that we get from the server.
6016 So we can't win using the usual strategy of letting
6017 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6018 and synchronize with the server to make sure we agree. */
6019 f->visible = 0;
6020 FRAME_ICONIFIED_P (f) = 0;
6021 f->async_visible = 0;
6022 f->async_iconified = 0;
6024 unblock_input ();
6027 /* Change window state from mapped to iconified. */
6029 void
6030 x_iconify_frame (struct frame *f)
6032 Lisp_Object type;
6034 /* Don't keep the highlight on an invisible frame. */
6035 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
6036 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
6038 if (f->async_iconified)
6039 return;
6041 block_input ();
6043 type = x_icon_type (f);
6044 if (!NILP (type))
6045 x_bitmap_icon (f, type);
6047 /* Simulate the user minimizing the frame. */
6048 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
6050 unblock_input ();
6054 /* Free X resources of frame F. */
6056 void
6057 x_free_frame_resources (struct frame *f)
6059 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6060 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
6062 block_input ();
6064 /* We must free faces before destroying windows because some
6065 font-driver (e.g. xft) access a window while finishing a
6066 face. */
6067 if (FRAME_FACE_CACHE (f))
6068 free_frame_faces (f);
6070 if (FRAME_W32_WINDOW (f))
6071 my_destroy_window (f, FRAME_W32_WINDOW (f));
6073 free_frame_menubar (f);
6075 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
6076 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
6077 unload_color (f, f->output_data.w32->cursor_pixel);
6078 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
6079 unload_color (f, f->output_data.w32->border_pixel);
6080 unload_color (f, f->output_data.w32->mouse_pixel);
6081 if (f->output_data.w32->white_relief.allocated_p)
6082 unload_color (f, f->output_data.w32->white_relief.pixel);
6083 if (f->output_data.w32->black_relief.allocated_p)
6084 unload_color (f, f->output_data.w32->black_relief.pixel);
6086 if (FRAME_FACE_CACHE (f))
6087 free_frame_faces (f);
6089 xfree (f->output_data.w32);
6090 f->output_data.w32 = NULL;
6092 if (f == dpyinfo->w32_focus_frame)
6093 dpyinfo->w32_focus_frame = 0;
6094 if (f == dpyinfo->w32_focus_event_frame)
6095 dpyinfo->w32_focus_event_frame = 0;
6096 if (f == dpyinfo->x_highlight_frame)
6097 dpyinfo->x_highlight_frame = 0;
6099 if (f == hlinfo->mouse_face_mouse_frame)
6101 hlinfo->mouse_face_beg_row
6102 = hlinfo->mouse_face_beg_col = -1;
6103 hlinfo->mouse_face_end_row
6104 = hlinfo->mouse_face_end_col = -1;
6105 hlinfo->mouse_face_window = Qnil;
6106 hlinfo->mouse_face_deferred_gc = 0;
6107 hlinfo->mouse_face_mouse_frame = 0;
6110 unblock_input ();
6114 /* Destroy the window of frame F. */
6115 void
6116 x_destroy_window (struct frame *f)
6118 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6120 x_free_frame_resources (f);
6121 dpyinfo->reference_count--;
6125 /* Setting window manager hints. */
6127 /* Set the normal size hints for the window manager, for frame F.
6128 FLAGS is the flags word to use--or 0 meaning preserve the flags
6129 that the window now has.
6130 If USER_POSITION, set the USPosition
6131 flag (this is useful when FLAGS is 0). */
6132 void
6133 x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
6135 Window window = FRAME_W32_WINDOW (f);
6137 enter_crit ();
6139 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
6140 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
6141 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
6142 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
6144 leave_crit ();
6147 /* Window manager things */
6148 void
6149 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
6151 #if 0
6152 Window window = FRAME_W32_WINDOW (f);
6154 f->display.x->wm_hints.flags |= IconPositionHint;
6155 f->display.x->wm_hints.icon_x = icon_x;
6156 f->display.x->wm_hints.icon_y = icon_y;
6158 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
6159 #endif
6163 /***********************************************************************
6164 Fonts
6165 ***********************************************************************/
6167 #ifdef GLYPH_DEBUG
6169 /* Check that FONT is valid on frame F. It is if it can be found in F's
6170 font table. */
6172 static void
6173 x_check_font (struct frame *f, struct font *font)
6175 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
6176 if (font->driver->check)
6177 eassert (font->driver->check (f, font) == 0);
6180 #endif /* GLYPH_DEBUG */
6184 /***********************************************************************
6185 Initialization
6186 ***********************************************************************/
6188 static int w32_initialized = 0;
6190 void
6191 w32_initialize_display_info (Lisp_Object display_name)
6193 struct w32_display_info *dpyinfo = &one_w32_display_info;
6194 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
6196 memset (dpyinfo, 0, sizeof (*dpyinfo));
6198 /* Put it on w32_display_name_list. */
6199 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6200 w32_display_name_list);
6201 dpyinfo->name_list_element = XCAR (w32_display_name_list);
6203 dpyinfo->w32_id_name = xmalloc (SCHARS (Vinvocation_name)
6204 + SCHARS (Vsystem_name) + 2);
6205 sprintf (dpyinfo->w32_id_name, "%s@%s",
6206 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6208 /* Default Console mode values - overridden when running in GUI mode
6209 with values obtained from system metrics. */
6210 dpyinfo->resx = 1;
6211 dpyinfo->resy = 1;
6212 dpyinfo->n_planes = 1;
6213 dpyinfo->n_cbits = 4;
6214 dpyinfo->n_fonts = 0;
6215 dpyinfo->smallest_font_height = 1;
6216 dpyinfo->smallest_char_width = 1;
6218 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
6219 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
6220 hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
6221 hlinfo->mouse_face_window = Qnil;
6222 hlinfo->mouse_face_overlay = Qnil;
6223 hlinfo->mouse_face_hidden = 0;
6225 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6226 /* TODO: dpyinfo->gray */
6230 /* Create an xrdb-style database of resources to supersede registry settings.
6231 The database is just a concatenation of C strings, finished by an additional
6232 \0. The strings are submitted to some basic normalization, so
6234 [ *]option[ *]:[ *]value...
6236 becomes
6238 option:value...
6240 but any whitespace following value is not removed. */
6242 static char *
6243 w32_make_rdb (char *xrm_option)
6245 char *buffer = xmalloc (strlen (xrm_option) + 2);
6246 char *current = buffer;
6247 char ch;
6248 int in_option = 1;
6249 int before_value = 0;
6251 do {
6252 ch = *xrm_option++;
6254 if (ch == '\n')
6256 *current++ = '\0';
6257 in_option = 1;
6258 before_value = 0;
6260 else if (ch != ' ')
6262 *current++ = ch;
6263 if (in_option && (ch == ':'))
6265 in_option = 0;
6266 before_value = 1;
6268 else if (before_value)
6270 before_value = 0;
6273 else if (!(in_option || before_value))
6275 *current++ = ch;
6277 } while (ch);
6279 *current = '\0';
6281 return buffer;
6284 void
6285 x_flush (struct frame * f)
6286 { /* Nothing to do */ }
6289 extern frame_parm_handler w32_frame_parm_handlers[];
6291 static struct redisplay_interface w32_redisplay_interface =
6293 w32_frame_parm_handlers,
6294 x_produce_glyphs,
6295 x_write_glyphs,
6296 x_insert_glyphs,
6297 x_clear_end_of_line,
6298 x_scroll_run,
6299 x_after_update_window_line,
6300 x_update_window_begin,
6301 x_update_window_end,
6302 x_cursor_to,
6303 x_flush,
6304 0, /* flush_display_optional */
6305 x_clear_window_mouse_face,
6306 x_get_glyph_overhangs,
6307 x_fix_overlapping_area,
6308 w32_draw_fringe_bitmap,
6309 w32_define_fringe_bitmap,
6310 w32_destroy_fringe_bitmap,
6311 w32_compute_glyph_string_overhangs,
6312 x_draw_glyph_string,
6313 w32_define_frame_cursor,
6314 w32_clear_frame_area,
6315 w32_draw_window_cursor,
6316 w32_draw_vertical_window_border,
6317 w32_shift_glyphs_for_insert
6320 static void x_delete_terminal (struct terminal *term);
6322 static struct terminal *
6323 w32_create_terminal (struct w32_display_info *dpyinfo)
6325 struct terminal *terminal;
6327 terminal = create_terminal ();
6329 terminal->type = output_w32;
6330 terminal->display_info.w32 = dpyinfo;
6331 dpyinfo->terminal = terminal;
6333 /* MSVC does not type K&R functions with no arguments correctly, and
6334 so we must explicitly cast them. */
6335 terminal->clear_frame_hook = x_clear_frame;
6336 terminal->ins_del_lines_hook = x_ins_del_lines;
6337 terminal->delete_glyphs_hook = x_delete_glyphs;
6338 terminal->ring_bell_hook = w32_ring_bell;
6339 terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
6340 terminal->set_terminal_modes_hook = w32_set_terminal_modes;
6341 terminal->update_begin_hook = x_update_begin;
6342 terminal->update_end_hook = x_update_end;
6343 terminal->set_terminal_window_hook = w32_set_terminal_window;
6344 terminal->read_socket_hook = w32_read_socket;
6345 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
6346 terminal->mouse_position_hook = w32_mouse_position;
6347 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
6348 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
6349 /* terminal->fullscreen_hook = XTfullscreen_hook; */
6350 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6351 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6352 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6353 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
6355 terminal->delete_frame_hook = x_destroy_window;
6356 terminal->delete_terminal_hook = x_delete_terminal;
6358 terminal->rif = &w32_redisplay_interface;
6359 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
6360 terminal->char_ins_del_ok = 1;
6361 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
6362 terminal->fast_clear_end_of_line = 1; /* X does this well. */
6363 terminal->memory_below_frame = 0; /* We don't remember what scrolls
6364 off the bottom. */
6366 /* We don't yet support separate terminals on W32, so don't try to share
6367 keyboards between virtual terminals that are on the same physical
6368 terminal like X does. */
6369 terminal->kboard = xmalloc (sizeof (KBOARD));
6370 init_kboard (terminal->kboard);
6371 kset_window_system (terminal->kboard, intern ("w32"));
6372 terminal->kboard->next_kboard = all_kboards;
6373 all_kboards = terminal->kboard;
6374 /* Don't let the initial kboard remain current longer than necessary.
6375 That would cause problems if a file loaded on startup tries to
6376 prompt in the mini-buffer. */
6377 if (current_kboard == initial_kboard)
6378 current_kboard = terminal->kboard;
6379 terminal->kboard->reference_count++;
6381 return terminal;
6384 static void
6385 x_delete_terminal (struct terminal *terminal)
6387 struct w32_display_info *dpyinfo = terminal->display_info.w32;
6389 /* Protect against recursive calls. delete_frame in
6390 delete_terminal calls us back when it deletes our last frame. */
6391 if (!terminal->name)
6392 return;
6394 block_input ();
6396 x_delete_display (dpyinfo);
6397 unblock_input ();
6400 struct w32_display_info *
6401 w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
6403 struct w32_display_info *dpyinfo;
6404 struct terminal *terminal;
6405 HDC hdc;
6407 block_input ();
6409 if (!w32_initialized)
6411 w32_initialize ();
6412 w32_initialized = 1;
6415 w32_initialize_display_info (display_name);
6417 dpyinfo = &one_w32_display_info;
6418 terminal = w32_create_terminal (dpyinfo);
6420 /* Set the name of the terminal. */
6421 terminal->name = xmalloc (SBYTES (display_name) + 1);
6422 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
6423 terminal->name[SBYTES (display_name)] = 0;
6425 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6427 /* Put this display on the chain. */
6428 dpyinfo->next = x_display_list;
6429 x_display_list = dpyinfo;
6431 hdc = GetDC (NULL);
6433 dpyinfo->root_window = GetDesktopWindow ();
6434 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6435 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
6436 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6437 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
6438 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
6439 ReleaseDC (NULL, hdc);
6441 /* initialize palette with white and black */
6443 XColor color;
6444 w32_defined_color (0, "white", &color, 1);
6445 w32_defined_color (0, "black", &color, 1);
6448 #ifdef WINDOWSNT
6449 /* Add the default keyboard. When !WINDOWSNT, we're using the
6450 standard Emacs console handling machinery and don't need an
6451 explicit FD here. */
6452 add_keyboard_wait_descriptor (0);
6453 #elif CYGWIN
6454 /* /dev/windows wakes us up when we have a thread message pending. */
6455 add_keyboard_wait_descriptor (w32_message_fd);
6456 #endif
6458 /* Create Fringe Bitmaps and store them for later use.
6460 On W32, bitmaps are all unsigned short, as Windows requires
6461 bitmap data to be Word aligned. For some reason they are
6462 horizontally reflected compared to how they appear on X, so we
6463 need to bitswap and convert to unsigned shorts before creating
6464 the bitmaps. */
6465 w32_init_fringe (terminal->rif);
6467 unblock_input ();
6469 return dpyinfo;
6472 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6473 void
6474 x_delete_display (struct w32_display_info *dpyinfo)
6476 /* Discard this display from w32_display_name_list and w32_display_list.
6477 We can't use Fdelq because that can quit. */
6478 if (! NILP (w32_display_name_list)
6479 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6480 w32_display_name_list = XCDR (w32_display_name_list);
6481 else
6483 Lisp_Object tail;
6485 tail = w32_display_name_list;
6486 while (CONSP (tail) && CONSP (XCDR (tail)))
6488 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
6490 XSETCDR (tail, XCDR (XCDR (tail)));
6491 break;
6493 tail = XCDR (tail);
6497 /* free palette table */
6499 struct w32_palette_entry * plist;
6501 plist = dpyinfo->color_list;
6502 while (plist)
6504 struct w32_palette_entry * pentry = plist;
6505 plist = plist->next;
6506 xfree (pentry);
6508 dpyinfo->color_list = NULL;
6509 if (dpyinfo->palette)
6510 DeleteObject (dpyinfo->palette);
6512 xfree (dpyinfo->w32_id_name);
6514 w32_reset_fringes ();
6518 /* Set up use of W32. */
6520 DWORD WINAPI w32_msg_worker (void * arg);
6522 static void
6523 w32_initialize (void)
6525 HANDLE shell;
6526 HRESULT (WINAPI * set_user_model) (wchar_t * id);
6528 baud_rate = 19200;
6530 w32_system_caret_hwnd = NULL;
6531 w32_system_caret_height = 0;
6532 w32_system_caret_x = 0;
6533 w32_system_caret_y = 0;
6535 /* On Windows 7 and later, we need to set the user model ID
6536 to associate emacsclient launched files with Emacs frames
6537 in the UI. */
6538 shell = GetModuleHandle ("shell32.dll");
6539 if (shell)
6541 set_user_model
6542 = (void *) GetProcAddress (shell,
6543 "SetCurrentProcessExplicitAppUserModelID");
6545 /* If the function is defined, then we are running on Windows 7
6546 or newer, and the UI uses this to group related windows
6547 together. Since emacs, runemacs, emacsclient are related, we
6548 want them grouped even though the executables are different,
6549 so we need to set a consistent ID between them. */
6550 if (set_user_model)
6551 set_user_model (L"GNU.Emacs");
6554 #ifdef CYGWIN
6555 if ((w32_message_fd = open ("/dev/windows", O_RDWR | O_CLOEXEC)) == -1)
6556 fatal ("opening /dev/windows: %s", strerror (errno));
6557 #endif /* CYGWIN */
6559 /* Initialize w32_use_visible_system_caret based on whether a screen
6560 reader is in use. */
6561 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6562 &w32_use_visible_system_caret, 0))
6563 w32_use_visible_system_caret = 0;
6565 last_tool_bar_item = -1;
6566 any_help_event_p = 0;
6568 /* Initialize input mode: interrupt_input off, no flow control, allow
6569 8 bit character input, standard quit char. */
6570 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6573 DWORD input_locale_id = (DWORD) GetKeyboardLayout (0);
6574 w32_keyboard_codepage =
6575 codepage_for_locale ((LCID) (input_locale_id & 0xffff));
6578 /* Create the window thread - it will terminate itself when the app
6579 terminates */
6580 init_crit ();
6582 dwMainThreadId = GetCurrentThreadId ();
6583 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6584 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6586 /* Wait for thread to start */
6588 MSG msg;
6590 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6592 hWindowsThread = CreateThread (NULL, 0,
6593 w32_msg_worker,
6594 0, 0, &dwWindowsThreadId);
6596 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6599 /* It is desirable that mainThread should have the same notion of
6600 focus window and active window as windowsThread. Unfortunately, the
6601 following call to AttachThreadInput, which should do precisely what
6602 we need, causes major problems when Emacs is linked as a console
6603 program. Unfortunately, we have good reasons for doing that, so
6604 instead we need to send messages to windowsThread to make some API
6605 calls for us (ones that affect, or depend on, the active/focus
6606 window state.) */
6607 #ifdef ATTACH_THREADS
6608 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
6609 #endif
6611 /* Dynamically link to optional system components. */
6613 HMODULE user_lib = GetModuleHandle ("user32.dll");
6615 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6617 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
6619 #undef LOAD_PROC
6621 /* Ensure scrollbar handle is at least 5 pixels. */
6622 vertical_scroll_bar_min_handle = 5;
6624 /* For either kind of scroll bar, take account of the arrows; these
6625 effectively form the border of the main scroll bar range. */
6626 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6627 = GetSystemMetrics (SM_CYVSCROLL);
6631 void
6632 syms_of_w32term (void)
6634 staticpro (&w32_display_name_list);
6635 w32_display_name_list = Qnil;
6637 staticpro (&last_mouse_scroll_bar);
6638 last_mouse_scroll_bar = Qnil;
6640 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
6642 DEFSYM (Qadded, "added");
6643 DEFSYM (Qremoved, "removed");
6644 DEFSYM (Qmodified, "modified");
6645 DEFSYM (Qrenamed_from, "renamed-from");
6646 DEFSYM (Qrenamed_to, "renamed-to");
6648 DEFVAR_INT ("w32-num-mouse-buttons",
6649 w32_num_mouse_buttons,
6650 doc: /* Number of physical mouse buttons. */);
6651 w32_num_mouse_buttons = 2;
6653 DEFVAR_LISP ("w32-swap-mouse-buttons",
6654 Vw32_swap_mouse_buttons,
6655 doc: /* Swap the mapping of middle and right mouse buttons.
6656 When nil, middle button is mouse-2 and right button is mouse-3. */);
6657 Vw32_swap_mouse_buttons = Qnil;
6659 DEFVAR_LISP ("w32-grab-focus-on-raise",
6660 Vw32_grab_focus_on_raise,
6661 doc: /* Raised frame grabs input focus.
6662 When t, `raise-frame' grabs input focus as well. This fits well
6663 with the normal Windows click-to-focus policy, but might not be
6664 desirable when using a point-to-focus policy. */);
6665 Vw32_grab_focus_on_raise = Qt;
6667 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6668 Vw32_capslock_is_shiftlock,
6669 doc: /* Apply CapsLock state to non character input keys.
6670 When nil, CapsLock only affects normal character input keys. */);
6671 Vw32_capslock_is_shiftlock = Qnil;
6673 DEFVAR_LISP ("w32-recognize-altgr",
6674 Vw32_recognize_altgr,
6675 doc: /* Recognize right-alt and left-ctrl as AltGr.
6676 When nil, the right-alt and left-ctrl key combination is
6677 interpreted normally. */);
6678 Vw32_recognize_altgr = Qt;
6680 DEFVAR_BOOL ("w32-use-visible-system-caret",
6681 w32_use_visible_system_caret,
6682 doc: /* Flag to make the system caret visible.
6683 When this is non-nil, Emacs will indicate the position of point by
6684 using the system caret instead of drawing its own cursor. Some screen
6685 reader software does not track the system cursor properly when it is
6686 invisible, and gets confused by Emacs drawing its own cursor, so this
6687 variable is initialized to t when Emacs detects that screen reader
6688 software is running as it starts up.
6690 When this variable is set, other variables affecting the appearance of
6691 the cursor have no effect. */);
6693 w32_use_visible_system_caret = 0;
6695 /* We don't yet support this, but defining this here avoids whining
6696 from cus-start.el and other places, like "M-x set-variable". */
6697 DEFVAR_BOOL ("x-use-underline-position-properties",
6698 x_use_underline_position_properties,
6699 doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
6700 A value of nil means ignore them. If you encounter fonts with bogus
6701 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6702 to 4.1, set this to nil. You can also use `underline-minimum-offset'
6703 to override the font's UNDERLINE_POSITION for small font display
6704 sizes. */);
6705 x_use_underline_position_properties = 0;
6707 DEFVAR_BOOL ("x-underline-at-descent-line",
6708 x_underline_at_descent_line,
6709 doc: /* Non-nil means to draw the underline at the same place as the descent line.
6710 A value of nil means to draw the underline according to the value of the
6711 variable `x-use-underline-position-properties', which is usually at the
6712 baseline level. The default value is nil. */);
6713 x_underline_at_descent_line = 0;
6715 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
6716 doc: /* Which toolkit scroll bars Emacs uses, if any.
6717 A value of nil means Emacs doesn't use toolkit scroll bars.
6718 With the X Window system, the value is a symbol describing the
6719 X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
6720 With MS Windows or Nextstep, the value is t. */);
6721 Vx_toolkit_scroll_bars = Qt;
6723 staticpro (&last_mouse_motion_frame);
6724 last_mouse_motion_frame = Qnil;
6726 Fprovide (intern_c_string ("w32"), Qnil);