Mention multi-planes text-properties
[emacs.git] / src / w32term.c
blob0b71b7e02b76c6e56aa7e822d272cac0e31fa5e9
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <setjmp.h>
26 #include "lisp.h"
27 #include "blockinput.h"
28 #include "w32term.h"
30 #include "systty.h"
31 #include "systime.h"
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/stat.h>
36 #include <imm.h>
38 #include "charset.h"
39 #include "character.h"
40 #include "coding.h"
41 #include "ccl.h"
42 #include "frame.h"
43 #include "dispextern.h"
44 #include "fontset.h"
45 #include "termhooks.h"
46 #include "termopts.h"
47 #include "termchar.h"
48 #include "disptab.h"
49 #include "buffer.h"
50 #include "window.h"
51 #include "keyboard.h"
52 #include "intervals.h"
53 #include "process.h"
54 #include "atimer.h"
55 #include "keymap.h"
57 #include "w32heap.h"
58 #include <shellapi.h>
60 #include "font.h"
61 #include "w32font.h"
63 /* Fringe bitmaps. */
65 static int max_fringe_bmp = 0;
66 static HBITMAP *fringe_bmp = 0;
68 /* Non-nil means Emacs uses toolkit scroll bars. */
70 Lisp_Object Vx_toolkit_scroll_bars;
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 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
91 int x_use_underline_position_properties;
93 /* Non-zero means to draw the underline at the same place as the descent line. */
95 int x_underline_at_descent_line;
97 extern unsigned int msh_mousewheel;
99 extern void free_frame_menubar ();
101 extern int w32_codepage_for_font (char *fontname);
102 extern Cursor w32_load_cursor (LPCTSTR name);
104 extern Lisp_Object Vwindow_system;
106 #define x_any_window_to_frame x_window_to_frame
107 #define x_top_window_to_frame x_window_to_frame
110 /* This is display since w32 does not support multiple ones. */
111 struct w32_display_info one_w32_display_info;
112 struct w32_display_info *x_display_list;
114 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
115 one for each element of w32_display_list and in the same order.
116 NAME is the name of the frame.
117 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
118 Lisp_Object w32_display_name_list;
121 #ifndef GLYPHSET
122 /* Pre Windows 2000, this was not available, but define it here so
123 that Emacs compiled on such a platform will run on newer versions. */
125 typedef struct tagWCRANGE
127 WCHAR wcLow;
128 USHORT cGlyphs;
129 } WCRANGE;
131 typedef struct tagGLYPHSET
133 DWORD cbThis;
134 DWORD flAccel;
135 DWORD cGlyphsSupported;
136 DWORD cRanges;
137 WCRANGE ranges[1];
138 } GLYPHSET;
140 #endif
142 /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
143 BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
145 #ifndef LWA_ALPHA
146 #define LWA_ALPHA 0x02
147 #endif
148 /* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
149 later targets by MSVC headers. */
150 #ifndef WS_EX_LAYERED
151 #define WS_EX_LAYERED 0x80000
152 #endif
154 /* Frame being updated by update_frame. This is declared in term.c.
155 This is set by update_begin and looked at by all the
156 w32 functions. It is zero while not inside an update.
157 In that case, the w32 functions assume that `SELECTED_FRAME ()'
158 is the frame to apply to. */
159 extern struct frame *updating_frame;
161 /* This is a frame waiting to be autoraised, within w32_read_socket. */
162 struct frame *pending_autoraise_frame;
164 /* The handle of the frame that currently owns the system caret. */
165 HWND w32_system_caret_hwnd;
166 int w32_system_caret_height;
167 int w32_system_caret_x;
168 int w32_system_caret_y;
169 int w32_use_visible_system_caret;
171 DWORD dwWindowsThreadId = 0;
172 HANDLE hWindowsThread = NULL;
173 DWORD dwMainThreadId = 0;
174 HANDLE hMainThread = NULL;
176 int vertical_scroll_bar_min_handle;
177 int vertical_scroll_bar_top_border;
178 int vertical_scroll_bar_bottom_border;
180 int last_scroll_bar_drag_pos;
182 /* Mouse movement. */
184 /* Where the mouse was last time we reported a mouse event. */
185 static RECT last_mouse_glyph;
186 static FRAME_PTR last_mouse_glyph_frame;
187 static Lisp_Object last_mouse_press_frame;
189 int w32_num_mouse_buttons;
191 Lisp_Object Vw32_swap_mouse_buttons;
193 /* Control whether x_raise_frame also sets input focus. */
194 Lisp_Object Vw32_grab_focus_on_raise;
196 /* Control whether Caps Lock affects non-ascii characters. */
197 Lisp_Object Vw32_capslock_is_shiftlock;
199 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
200 Lisp_Object Vw32_recognize_altgr;
202 /* The scroll bar in which the last motion event occurred.
204 If the last motion event occurred in a scroll bar, we set this
205 so w32_mouse_position can know whether to report a scroll bar motion or
206 an ordinary motion.
208 If the last motion event didn't occur in a scroll bar, we set this
209 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
210 static Lisp_Object last_mouse_scroll_bar;
211 static int last_mouse_scroll_bar_pos;
213 /* This is a hack. We would really prefer that w32_mouse_position would
214 return the time associated with the position it returns, but there
215 doesn't seem to be any way to wrest the time-stamp from the server
216 along with the position query. So, we just keep track of the time
217 of the last movement we received, and return that in hopes that
218 it's somewhat accurate. */
219 static Time last_mouse_movement_time;
221 /* Incremented by w32_read_socket whenever it really tries to read
222 events. */
223 #ifdef __STDC__
224 static int volatile input_signal_count;
225 #else
226 static int input_signal_count;
227 #endif
229 extern Lisp_Object Vcommand_line_args, Vsystem_name;
231 /* A mask of extra modifier bits to put into every keyboard char. */
232 extern EMACS_INT extra_keyboard_modifiers;
234 /* Keyboard code page - may be changed by language-change events. */
235 static int keyboard_codepage;
237 static void x_update_window_end P_ ((struct window *, int, int));
238 static void w32_handle_tool_bar_click P_ ((struct frame *,
239 struct input_event *));
240 static void w32_define_cursor P_ ((Window, Cursor));
242 void x_lower_frame P_ ((struct frame *));
243 void x_scroll_bar_clear P_ ((struct frame *));
244 void x_wm_set_size_hint P_ ((struct frame *, long, int));
245 void x_raise_frame P_ ((struct frame *));
246 void x_set_window_size P_ ((struct frame *, int, int, int));
247 void x_wm_set_window_state P_ ((struct frame *, int));
248 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
249 static void w32_initialize P_ ((void));
250 static void x_update_end P_ ((struct frame *));
251 static void w32_frame_up_to_date P_ ((struct frame *));
252 static void w32_set_terminal_modes P_ ((struct terminal *));
253 static void w32_reset_terminal_modes P_ ((struct terminal *));
254 static void x_clear_frame P_ ((struct frame *));
255 static void frame_highlight P_ ((struct frame *));
256 static void frame_unhighlight P_ ((struct frame *));
257 static void x_new_focus_frame P_ ((struct w32_display_info *,
258 struct frame *));
259 static void x_focus_changed P_ ((int, int, struct w32_display_info *,
260 struct frame *, struct input_event *));
261 static void w32_detect_focus_change P_ ((struct w32_display_info *,
262 W32Msg *, struct input_event *));
263 static void w32_frame_rehighlight P_ ((struct frame *));
264 static void x_frame_rehighlight P_ ((struct w32_display_info *));
265 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
266 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
267 enum text_cursor_kinds));
268 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
269 static BOOL my_show_window P_ ((struct frame *, HWND, int));
270 static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
271 static void my_set_focus P_ ((struct frame *, HWND));
272 static void my_set_foreground_window P_ ((HWND));
273 static void my_destroy_window P_ ((struct frame *, HWND));
275 static Lisp_Object Qvendor_specific_keysyms;
278 /***********************************************************************
279 Debugging
280 ***********************************************************************/
282 #if 0
284 /* This is a function useful for recording debugging information about
285 the sequence of occurrences in this file. */
287 struct record
289 char *locus;
290 int type;
293 struct record event_record[100];
295 int event_record_index;
297 record_event (locus, type)
298 char *locus;
299 int type;
301 if (event_record_index == sizeof (event_record) / sizeof (struct record))
302 event_record_index = 0;
304 event_record[event_record_index].locus = locus;
305 event_record[event_record_index].type = type;
306 event_record_index++;
309 #endif /* 0 */
312 void
313 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
314 XGCValues *xgcv)
316 if (mask & GCForeground)
317 gc->foreground = xgcv->foreground;
318 if (mask & GCBackground)
319 gc->background = xgcv->background;
320 if (mask & GCFont)
321 gc->font = xgcv->font;
324 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
325 XGCValues *xgcv)
327 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
328 bzero (gc, sizeof (XGCValues));
330 XChangeGC (ignore, gc, mask, xgcv);
332 return gc;
335 void
336 XGetGCValues (void* ignore, XGCValues *gc,
337 unsigned long mask, XGCValues *xgcv)
339 XChangeGC (ignore, xgcv, mask, gc);
342 static void
343 w32_set_clip_rectangle (HDC hdc, RECT *rect)
345 if (rect)
347 HRGN clip_region = CreateRectRgnIndirect (rect);
348 SelectClipRgn (hdc, clip_region);
349 DeleteObject (clip_region);
351 else
352 SelectClipRgn (hdc, NULL);
356 /* Draw a hollow rectangle at the specified position. */
357 void
358 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
359 int width, int height)
361 HBRUSH hb, oldhb;
362 HPEN hp, oldhp;
364 hb = CreateSolidBrush (gc->background);
365 hp = CreatePen (PS_SOLID, 0, gc->foreground);
366 oldhb = SelectObject (hdc, hb);
367 oldhp = SelectObject (hdc, hp);
369 Rectangle (hdc, x, y, x + width, y + height);
371 SelectObject (hdc, oldhb);
372 SelectObject (hdc, oldhp);
373 DeleteObject (hb);
374 DeleteObject (hp);
377 /* Draw a filled rectangle at the specified position. */
378 void
379 w32_fill_rect (f, hdc, pix, lprect)
380 FRAME_PTR f;
381 HDC hdc;
382 COLORREF pix;
383 RECT * lprect;
385 HBRUSH hb;
387 hb = CreateSolidBrush (pix);
388 FillRect (hdc, lprect, hb);
389 DeleteObject (hb);
392 void
393 w32_clear_window (f)
394 FRAME_PTR f;
396 RECT rect;
397 HDC hdc = get_frame_dc (f);
399 /* Under certain conditions, this can be called at startup with
400 a console frame pointer before the GUI frame is created. An HDC
401 of 0 indicates this. */
402 if (hdc)
404 GetClientRect (FRAME_W32_WINDOW (f), &rect);
405 w32_clear_rect (f, hdc, &rect);
408 release_frame_dc (f, hdc);
411 #define OPAQUE_FRAME 255
413 void
414 x_set_frame_alpha (f)
415 struct frame *f;
417 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
418 double alpha = 1.0;
419 double alpha_min = 1.0;
420 BYTE opac;
421 LONG ex_style;
422 HWND window = FRAME_W32_WINDOW (f);
424 /* Older versions of Windows do not support transparency. */
425 if (!pfnSetLayeredWindowAttributes)
426 return;
428 if (dpyinfo->x_highlight_frame == f)
429 alpha = f->alpha[0];
430 else
431 alpha = f->alpha[1];
433 if (FLOATP (Vframe_alpha_lower_limit))
434 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
435 else if (INTEGERP (Vframe_alpha_lower_limit))
436 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
438 if (alpha < 0.0)
439 return;
440 else if (alpha > 1.0)
441 alpha = 1.0;
442 else if (alpha < alpha_min && alpha_min <= 1.0)
443 alpha = alpha_min;
445 opac = alpha * OPAQUE_FRAME;
447 ex_style = GetWindowLong (window, GWL_EXSTYLE);
449 if (opac == OPAQUE_FRAME)
450 ex_style &= ~WS_EX_LAYERED;
451 else
452 ex_style |= WS_EX_LAYERED;
454 SetWindowLong (window, GWL_EXSTYLE, ex_style);
456 if (opac != OPAQUE_FRAME)
457 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
461 x_display_pixel_height (dpyinfo)
462 struct w32_display_info *dpyinfo;
464 HDC dc = GetDC (NULL);
465 int pixels = GetDeviceCaps (dc, VERTRES);
466 ReleaseDC (NULL, dc);
467 return pixels;
471 x_display_pixel_width (dpyinfo)
472 struct w32_display_info *dpyinfo;
474 HDC dc = GetDC (NULL);
475 int pixels = GetDeviceCaps (dc, HORZRES);
476 ReleaseDC (NULL, dc);
477 return pixels;
481 /***********************************************************************
482 Starting and ending an update
483 ***********************************************************************/
485 /* Start an update of frame F. This function is installed as a hook
486 for update_begin, i.e. it is called when update_begin is called.
487 This function is called prior to calls to x_update_window_begin for
488 each window being updated. */
490 static void
491 x_update_begin (f)
492 struct frame *f;
494 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
496 if (! FRAME_W32_P (f))
497 return;
499 /* Regenerate display palette before drawing if list of requested
500 colors has changed. */
501 if (display_info->regen_palette)
503 w32_regenerate_palette (f);
504 display_info->regen_palette = FALSE;
509 /* Start update of window W. Set the global variable updated_window
510 to the window being updated and set output_cursor to the cursor
511 position of W. */
513 static void
514 x_update_window_begin (w)
515 struct window *w;
517 struct frame *f = XFRAME (WINDOW_FRAME (w));
518 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
520 /* Hide the system caret during an update. */
521 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
523 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
526 updated_window = w;
527 set_output_cursor (&w->cursor);
529 BLOCK_INPUT;
531 if (f == display_info->mouse_face_mouse_frame)
533 /* Don't do highlighting for mouse motion during the update. */
534 display_info->mouse_face_defer = 1;
536 /* If F needs to be redrawn, simply forget about any prior mouse
537 highlighting. */
538 if (FRAME_GARBAGED_P (f))
539 display_info->mouse_face_window = Qnil;
541 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
542 their mouse_face_p flag set, which means that they are always
543 unequal to rows in a desired matrix which never have that
544 flag set. So, rows containing mouse-face glyphs are never
545 scrolled, and we don't have to switch the mouse highlight off
546 here to prevent it from being scrolled. */
548 /* Can we tell that this update does not affect the window
549 where the mouse highlight is? If so, no need to turn off.
550 Likewise, don't do anything if the frame is garbaged;
551 in that case, the frame's current matrix that we would use
552 is all wrong, and we will redisplay that line anyway. */
553 if (!NILP (display_info->mouse_face_window)
554 && w == XWINDOW (display_info->mouse_face_window))
556 int i;
558 for (i = 0; i < w->desired_matrix->nrows; ++i)
559 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
560 break;
562 if (i < w->desired_matrix->nrows)
563 clear_mouse_face (display_info);
565 #endif /* 0 */
568 UNBLOCK_INPUT;
571 /* Draw a vertical window border from (x,y0) to (x,y1) */
573 static void
574 w32_draw_vertical_window_border (w, x, y0, y1)
575 struct window *w;
576 int x, y0, y1;
578 struct frame *f = XFRAME (WINDOW_FRAME (w));
579 RECT r;
580 HDC hdc;
581 struct face *face;
583 r.left = x;
584 r.right = x + 1;
585 r.top = y0;
586 r.bottom = y1;
588 hdc = get_frame_dc (f);
589 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
590 if (face)
591 w32_fill_rect (f, hdc, face->foreground, &r);
592 else
593 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
595 release_frame_dc (f, hdc);
599 /* End update of window W (which is equal to updated_window).
601 Draw vertical borders between horizontally adjacent windows, and
602 display W's cursor if CURSOR_ON_P is non-zero.
604 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
605 glyphs in mouse-face were overwritten. In that case we have to
606 make sure that the mouse-highlight is properly redrawn.
608 W may be a menu bar pseudo-window in case we don't have X toolkit
609 support. Such windows don't have a cursor, so don't display it
610 here. */
612 static void
613 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
614 struct window *w;
615 int cursor_on_p, mouse_face_overwritten_p;
617 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
619 if (!w->pseudo_window_p)
621 BLOCK_INPUT;
623 if (cursor_on_p)
624 display_and_set_cursor (w, 1, output_cursor.hpos,
625 output_cursor.vpos,
626 output_cursor.x, output_cursor.y);
628 if (draw_window_fringes (w, 1))
629 x_draw_vertical_border (w);
631 UNBLOCK_INPUT;
634 /* If a row with mouse-face was overwritten, arrange for
635 XTframe_up_to_date to redisplay the mouse highlight. */
636 if (mouse_face_overwritten_p)
638 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
639 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
640 dpyinfo->mouse_face_window = Qnil;
643 /* Unhide the caret. This won't actually show the cursor, unless it
644 was visible before the corresponding call to HideCaret in
645 x_update_window_begin. */
646 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
648 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
651 updated_window = NULL;
655 /* End update of frame F. This function is installed as a hook in
656 update_end. */
658 static void
659 x_update_end (f)
660 struct frame *f;
662 if (! FRAME_W32_P (f))
663 return;
665 /* Mouse highlight may be displayed again. */
666 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
670 /* This function is called from various places in xdisp.c whenever a
671 complete update has been performed. The global variable
672 updated_window is not available here. */
674 static void
675 w32_frame_up_to_date (f)
676 struct frame *f;
678 if (FRAME_W32_P (f))
680 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
682 if (dpyinfo->mouse_face_deferred_gc
683 || f == dpyinfo->mouse_face_mouse_frame)
685 BLOCK_INPUT;
686 if (dpyinfo->mouse_face_mouse_frame)
687 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
688 dpyinfo->mouse_face_mouse_x,
689 dpyinfo->mouse_face_mouse_y);
690 dpyinfo->mouse_face_deferred_gc = 0;
691 UNBLOCK_INPUT;
697 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
698 arrow bitmaps, or clear the fringes if no bitmaps are required
699 before DESIRED_ROW is made current. The window being updated is
700 found in updated_window. This function is called from
701 update_window_line only if it is known that there are differences
702 between bitmaps to be drawn between current row and DESIRED_ROW. */
704 static void
705 x_after_update_window_line (desired_row)
706 struct glyph_row *desired_row;
708 struct window *w = updated_window;
709 struct frame *f;
710 int width, height;
712 xassert (w);
714 if (!desired_row->mode_line_p && !w->pseudo_window_p)
715 desired_row->redraw_fringe_bitmaps_p = 1;
717 /* When a window has disappeared, make sure that no rest of
718 full-width rows stays visible in the internal border. Could
719 check here if updated_window is the leftmost/rightmost window,
720 but I guess it's not worth doing since vertically split windows
721 are almost never used, internal border is rarely set, and the
722 overhead is very small. */
723 if (windows_or_buffers_changed
724 && desired_row->full_width_p
725 && (f = XFRAME (w->frame),
726 width = FRAME_INTERNAL_BORDER_WIDTH (f),
727 width != 0)
728 && (height = desired_row->visible_height,
729 height > 0))
731 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
733 BLOCK_INPUT;
735 HDC hdc = get_frame_dc (f);
736 w32_clear_area (f, hdc, 0, y, width, height);
737 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
738 y, width, height);
739 release_frame_dc (f, hdc);
741 UNBLOCK_INPUT;
746 /* Draw the bitmap WHICH in one of the left or right fringes of
747 window W. ROW is the glyph row for which to display the bitmap; it
748 determines the vertical position at which the bitmap has to be
749 drawn. */
751 static void
752 w32_draw_fringe_bitmap (w, row, p)
753 struct window *w;
754 struct glyph_row *row;
755 struct draw_fringe_bitmap_params *p;
757 struct frame *f = XFRAME (WINDOW_FRAME (w));
758 HDC hdc;
759 struct face *face = p->face;
760 int rowY;
762 hdc = get_frame_dc (f);
764 if (!p->overlay_p)
766 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
768 /* If the fringe is adjacent to the left (right) scroll bar of a
769 leftmost (rightmost, respectively) window, then extend its
770 background to the gap between the fringe and the bar. */
771 if ((WINDOW_LEFTMOST_P (w)
772 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
773 || (WINDOW_RIGHTMOST_P (w)
774 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
776 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
778 if (sb_width > 0)
780 int left = WINDOW_SCROLL_BAR_AREA_X (w);
781 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
782 * FRAME_COLUMN_WIDTH (f));
784 if (bx < 0)
786 /* Bitmap fills the fringe. */
787 if (left + width == p->x)
788 bx = left + sb_width;
789 else if (p->x + p->wd == left)
790 bx = left;
791 if (bx >= 0)
793 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
795 nx = width - sb_width;
796 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
797 row->y));
798 ny = row->visible_height;
801 else
803 if (left + width == bx)
805 bx = left + sb_width;
806 nx += width - sb_width;
808 else if (bx + nx == left)
809 nx += width - sb_width;
814 if (bx >= 0 && nx > 0)
815 w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
818 /* Must clip because of partially visible lines. */
819 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
820 if (p->y < rowY)
822 /* Adjust position of "bottom aligned" bitmap on partially
823 visible last row. */
824 int oldY = row->y;
825 int oldVH = row->visible_height;
826 row->visible_height = p->h;
827 row->y -= rowY - p->y;
828 w32_clip_to_row (w, row, -1, hdc);
829 row->y = oldY;
830 row->visible_height = oldVH;
832 else
833 w32_clip_to_row (w, row, -1, hdc);
835 if (p->which && p->which < max_fringe_bmp)
837 HBITMAP pixmap = fringe_bmp[p->which];
838 HDC compat_hdc;
839 HANDLE horig_obj;
841 compat_hdc = CreateCompatibleDC (hdc);
843 SaveDC (hdc);
845 horig_obj = SelectObject (compat_hdc, pixmap);
847 /* Paint overlays transparently. */
848 if (p->overlay_p)
850 HBRUSH h_brush, h_orig_brush;
852 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
853 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
854 h_brush = CreateSolidBrush (face->foreground);
855 h_orig_brush = SelectObject (hdc, h_brush);
857 BitBlt (hdc, p->x, p->y, p->wd, p->h,
858 compat_hdc, 0, p->dh,
859 DSTINVERT);
860 BitBlt (hdc, p->x, p->y, p->wd, p->h,
861 compat_hdc, 0, p->dh,
862 0x2E064A);
863 BitBlt (hdc, p->x, p->y, p->wd, p->h,
864 compat_hdc, 0, p->dh,
865 DSTINVERT);
867 SelectObject (hdc, h_orig_brush);
868 DeleteObject (h_brush);
870 else
872 SetTextColor (hdc, face->background);
873 SetBkColor (hdc, (p->cursor_p
874 ? f->output_data.w32->cursor_pixel
875 : face->foreground));
877 BitBlt (hdc, p->x, p->y, p->wd, p->h,
878 compat_hdc, 0, p->dh,
879 SRCCOPY);
882 SelectObject (compat_hdc, horig_obj);
883 DeleteDC (compat_hdc);
884 RestoreDC (hdc, -1);
887 w32_set_clip_rectangle (hdc, NULL);
889 release_frame_dc (f, hdc);
892 static void
893 w32_define_fringe_bitmap (which, bits, h, wd)
894 int which;
895 unsigned short *bits;
896 int h, wd;
898 if (which >= max_fringe_bmp)
900 int i = max_fringe_bmp;
901 max_fringe_bmp = which + 20;
902 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
903 while (i < max_fringe_bmp)
904 fringe_bmp[i++] = 0;
907 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
910 static void
911 w32_destroy_fringe_bitmap (which)
912 int which;
914 if (which >= max_fringe_bmp)
915 return;
917 if (fringe_bmp[which])
918 DeleteObject (fringe_bmp[which]);
919 fringe_bmp[which] = 0;
924 /* This is called when starting Emacs and when restarting after
925 suspend. When starting Emacs, no window is mapped. And nothing
926 must be done to Emacs's own window if it is suspended (though that
927 rarely happens). */
929 static void
930 w32_set_terminal_modes (struct terminal *term)
934 /* This is called when exiting or suspending Emacs. Exiting will make
935 the W32 windows go away, and suspending requires no action. */
937 static void
938 w32_reset_terminal_modes (struct terminal *term)
944 /***********************************************************************
945 Display Iterator
946 ***********************************************************************/
948 /* Function prototypes of this page. */
950 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
951 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
952 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
953 int));
954 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
955 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
956 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
957 static void x_draw_glyph_string P_ ((struct glyph_string *));
958 static void x_set_cursor_gc P_ ((struct glyph_string *));
959 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
960 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
961 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
962 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
963 double, int, COLORREF));
964 static void x_setup_relief_colors P_ ((struct glyph_string *));
965 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
966 static void x_draw_image_relief P_ ((struct glyph_string *));
967 static void x_draw_image_foreground P_ ((struct glyph_string *));
968 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
969 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
970 int, int, int));
971 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
972 int, int, int, int, int, int,
973 RECT *));
974 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
975 int, int, int, RECT *));
978 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
979 face. */
981 static void
982 x_set_cursor_gc (s)
983 struct glyph_string *s;
985 if (s->font == FRAME_FONT (s->f)
986 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
987 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
988 && !s->cmp)
989 s->gc = s->f->output_data.w32->cursor_gc;
990 else
992 /* Cursor on non-default face: must merge. */
993 XGCValues xgcv;
994 unsigned long mask;
996 xgcv.background = s->f->output_data.w32->cursor_pixel;
997 xgcv.foreground = s->face->background;
999 /* If the glyph would be invisible, try a different foreground. */
1000 if (xgcv.foreground == xgcv.background)
1001 xgcv.foreground = s->face->foreground;
1002 if (xgcv.foreground == xgcv.background)
1003 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1004 if (xgcv.foreground == xgcv.background)
1005 xgcv.foreground = s->face->foreground;
1007 /* Make sure the cursor is distinct from text in this face. */
1008 if (xgcv.background == s->face->background
1009 && xgcv.foreground == s->face->foreground)
1011 xgcv.background = s->face->foreground;
1012 xgcv.foreground = s->face->background;
1015 IF_DEBUG (x_check_font (s->f, s->font));
1016 xgcv.font = s->font;
1017 mask = GCForeground | GCBackground | GCFont;
1019 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1020 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1021 mask, &xgcv);
1022 else
1023 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1024 = XCreateGC (NULL, s->window, mask, &xgcv);
1026 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1031 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1033 static void
1034 x_set_mouse_face_gc (s)
1035 struct glyph_string *s;
1037 int face_id;
1038 struct face *face;
1040 /* What face has to be used last for the mouse face? */
1041 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
1042 face = FACE_FROM_ID (s->f, face_id);
1043 if (face == NULL)
1044 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1046 if (s->first_glyph->type == CHAR_GLYPH)
1047 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1048 else
1049 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1050 s->face = FACE_FROM_ID (s->f, face_id);
1051 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1053 /* If font in this face is same as S->font, use it. */
1054 if (s->font == s->face->font)
1055 s->gc = s->face->gc;
1056 else
1058 /* Otherwise construct scratch_cursor_gc with values from FACE
1059 but font FONT. */
1060 XGCValues xgcv;
1061 unsigned long mask;
1063 xgcv.background = s->face->background;
1064 xgcv.foreground = s->face->foreground;
1065 IF_DEBUG (x_check_font (s->f, s->font));
1066 xgcv.font = s->font;
1067 mask = GCForeground | GCBackground | GCFont;
1069 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1070 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1071 mask, &xgcv);
1072 else
1073 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1074 = XCreateGC (NULL, s->window, mask, &xgcv);
1076 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1079 xassert (s->gc != 0);
1083 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1084 Faces to use in the mode line have already been computed when the
1085 matrix was built, so there isn't much to do, here. */
1087 static INLINE void
1088 x_set_mode_line_face_gc (s)
1089 struct glyph_string *s;
1091 s->gc = s->face->gc;
1095 /* Set S->gc of glyph string S for drawing that glyph string. Set
1096 S->stippled_p to a non-zero value if the face of S has a stipple
1097 pattern. */
1099 static INLINE void
1100 x_set_glyph_string_gc (s)
1101 struct glyph_string *s;
1103 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1105 if (s->hl == DRAW_NORMAL_TEXT)
1107 s->gc = s->face->gc;
1108 s->stippled_p = s->face->stipple != 0;
1110 else if (s->hl == DRAW_INVERSE_VIDEO)
1112 x_set_mode_line_face_gc (s);
1113 s->stippled_p = s->face->stipple != 0;
1115 else if (s->hl == DRAW_CURSOR)
1117 x_set_cursor_gc (s);
1118 s->stippled_p = 0;
1120 else if (s->hl == DRAW_MOUSE_FACE)
1122 x_set_mouse_face_gc (s);
1123 s->stippled_p = s->face->stipple != 0;
1125 else if (s->hl == DRAW_IMAGE_RAISED
1126 || s->hl == DRAW_IMAGE_SUNKEN)
1128 s->gc = s->face->gc;
1129 s->stippled_p = s->face->stipple != 0;
1131 else
1133 s->gc = s->face->gc;
1134 s->stippled_p = s->face->stipple != 0;
1137 /* GC must have been set. */
1138 xassert (s->gc != 0);
1142 /* Set clipping for output of glyph string S. S may be part of a mode
1143 line or menu if we don't have X toolkit support. */
1145 static INLINE void
1146 x_set_glyph_string_clipping (s)
1147 struct glyph_string *s;
1149 RECT *r = s->clip;
1150 int n = get_glyph_string_clip_rects (s, r, 2);
1152 if (n == 1)
1153 w32_set_clip_rectangle (s->hdc, r);
1154 else if (n > 1)
1156 HRGN full_clip, clip1, clip2;
1157 clip1 = CreateRectRgnIndirect (r);
1158 clip2 = CreateRectRgnIndirect (r + 1);
1159 if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
1161 SelectClipRgn (s->hdc, full_clip);
1163 DeleteObject (clip1);
1164 DeleteObject (clip2);
1165 DeleteObject (full_clip);
1167 s->num_clips = n;
1170 /* Set SRC's clipping for output of glyph string DST. This is called
1171 when we are drawing DST's left_overhang or right_overhang only in
1172 the area of SRC. */
1174 static void
1175 x_set_glyph_string_clipping_exactly (src, dst)
1176 struct glyph_string *src, *dst;
1178 RECT r;
1180 r.left = src->x;
1181 r.right = r.left + src->width;
1182 r.top = src->y;
1183 r.bottom = r.top + src->height;
1184 dst->clip[0] = r;
1185 dst->num_clips = 1;
1186 w32_set_clip_rectangle (dst->hdc, &r);
1189 /* RIF:
1190 Compute left and right overhang of glyph string S. */
1192 static void
1193 w32_compute_glyph_string_overhangs (s)
1194 struct glyph_string *s;
1196 if (s->cmp == NULL
1197 && s->first_glyph->type == CHAR_GLYPH
1198 && !s->font_not_found_p)
1200 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1201 struct font *font = s->font;
1202 struct font_metrics metrics;
1203 int i;
1205 for (i = 0; i < s->nchars; i++)
1206 code[i] = s->char2b[i];
1207 font->driver->text_extents (font, code, s->nchars, &metrics);
1208 s->right_overhang = (metrics.rbearing > metrics.width
1209 ? metrics.rbearing - metrics.width : 0);
1210 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
1212 else if (s->cmp)
1214 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1215 s->left_overhang = -s->cmp->lbearing;
1219 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1221 static INLINE void
1222 x_clear_glyph_string_rect (s, x, y, w, h)
1223 struct glyph_string *s;
1224 int x, y, w, h;
1226 int real_x = x;
1227 int real_y = y;
1228 int real_w = w;
1229 int real_h = h;
1230 #if 0
1231 /* Take clipping into account. */
1232 if (s->gc->clip_mask == Rect)
1234 real_x = max (real_x, s->gc->clip_rectangle.left);
1235 real_y = max (real_y, s->gc->clip_rectangle.top);
1236 real_w = min (real_w, s->gc->clip_rectangle.right
1237 - s->gc->clip_rectangle.left);
1238 real_h = min (real_h, s->gc->clip_rectangle.bottom
1239 - s->gc->clip_rectangle.top);
1241 #endif
1242 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1243 real_w, real_h);
1247 /* Draw the background of glyph_string S. If S->background_filled_p
1248 is non-zero don't draw it. FORCE_P non-zero means draw the
1249 background even if it wouldn't be drawn normally. This is used
1250 when a string preceding S draws into the background of S, or S
1251 contains the first component of a composition. */
1253 static void
1254 x_draw_glyph_string_background (s, force_p)
1255 struct glyph_string *s;
1256 int force_p;
1258 /* Nothing to do if background has already been drawn or if it
1259 shouldn't be drawn in the first place. */
1260 if (!s->background_filled_p)
1262 int box_line_width = max (s->face->box_line_width, 0);
1264 #if 0 /* TODO: stipple */
1265 if (s->stippled_p)
1267 /* Fill background with a stipple pattern. */
1268 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1269 XFillRectangle (s->display, s->window, s->gc, s->x,
1270 s->y + box_line_width,
1271 s->background_width,
1272 s->height - 2 * box_line_width);
1273 XSetFillStyle (s->display, s->gc, FillSolid);
1274 s->background_filled_p = 1;
1276 else
1277 #endif
1278 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1279 || s->font_not_found_p
1280 || s->extends_to_end_of_line_p
1281 || force_p)
1283 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1284 s->background_width,
1285 s->height - 2 * box_line_width);
1286 s->background_filled_p = 1;
1292 /* Draw the foreground of glyph string S. */
1294 static void
1295 x_draw_glyph_string_foreground (s)
1296 struct glyph_string *s;
1298 int i, x;
1300 /* If first glyph of S has a left box line, start drawing the text
1301 of S to the right of that box line. */
1302 if (s->face->box != FACE_NO_BOX
1303 && s->first_glyph->left_box_line_p)
1304 x = s->x + eabs (s->face->box_line_width);
1305 else
1306 x = s->x;
1308 SetTextColor (s->hdc, s->gc->foreground);
1309 SetBkColor (s->hdc, s->gc->background);
1310 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1312 /* Draw characters of S as rectangles if S's font could not be
1313 loaded. */
1314 if (s->font_not_found_p)
1316 for (i = 0; i < s->nchars; ++i)
1318 struct glyph *g = s->first_glyph + i;
1320 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1321 s->height - 1);
1322 x += g->pixel_width;
1325 else
1327 struct font *font = s->font;
1328 int boff = font->baseline_offset;
1329 int y;
1330 HFONT old_font;
1332 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1334 if (font->vertical_centering)
1335 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1337 y = s->ybase - boff;
1338 if (s->for_overlaps
1339 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1340 font->driver->draw (s, 0, s->nchars, x, y, 0);
1341 else
1342 font->driver->draw (s, 0, s->nchars, x, y, 1);
1343 if (s->face->overstrike)
1344 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1346 SelectObject (s->hdc, old_font);
1350 /* Draw the foreground of composite glyph string S. */
1352 static void
1353 x_draw_composite_glyph_string_foreground (s)
1354 struct glyph_string *s;
1356 int i, j, x;
1357 struct font *font = s->font;
1359 /* If first glyph of S has a left box line, start drawing the text
1360 of S to the right of that box line. */
1361 if (s->face && s->face->box != FACE_NO_BOX
1362 && s->first_glyph->left_box_line_p)
1363 x = s->x + eabs (s->face->box_line_width);
1364 else
1365 x = s->x;
1367 /* S is a glyph string for a composition. S->cmp_from is the index
1368 of the first character drawn for glyphs of this composition.
1369 S->cmp_from == 0 means we are drawing the very first character of
1370 this composition. */
1372 SetTextColor (s->hdc, s->gc->foreground);
1373 SetBkColor (s->hdc, s->gc->background);
1374 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1376 /* Draw a rectangle for the composition if the font for the very
1377 first character of the composition could not be loaded. */
1378 if (s->font_not_found_p)
1380 if (s->cmp_from == 0)
1381 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1382 s->height - 1);
1384 else if (! s->first_glyph->u.cmp.automatic)
1386 int y = s->ybase;
1387 int width = 0;
1388 HFONT old_font;
1390 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1392 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1393 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1395 int xx = x + s->cmp->offsets[j * 2];
1396 int yy = y - s->cmp->offsets[j * 2 + 1];
1398 font->driver->draw (s, j, j + 1, xx, yy, 0);
1399 if (s->face->overstrike)
1400 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1402 SelectObject (s->hdc, old_font);
1404 else
1406 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1407 Lisp_Object glyph;
1408 int y = s->ybase;
1409 int width = 0;
1410 HFONT old_font;
1412 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1414 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1416 glyph = LGSTRING_GLYPH (gstring, i);
1417 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1418 width += LGLYPH_WIDTH (glyph);
1419 else
1421 int xoff, yoff, wadjust;
1423 if (j < i)
1425 font->driver->draw (s, j, i, x, y, 0);
1426 x += width;
1428 xoff = LGLYPH_XOFF (glyph);
1429 yoff = LGLYPH_YOFF (glyph);
1430 wadjust = LGLYPH_WADJUST (glyph);
1431 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1432 x += wadjust;
1433 j = i + 1;
1434 width = 0;
1437 if (j < i)
1438 font->driver->draw (s, j, i, x, y, 0);
1440 SelectObject (s->hdc, old_font);
1445 /* Brightness beyond which a color won't have its highlight brightness
1446 boosted.
1448 Nominally, highlight colors for `3d' faces are calculated by
1449 brightening an object's color by a constant scale factor, but this
1450 doesn't yield good results for dark colors, so for colors who's
1451 brightness is less than this value (on a scale of 0-255) have to
1452 use an additional additive factor.
1454 The value here is set so that the default menu-bar/mode-line color
1455 (grey75) will not have its highlights changed at all. */
1456 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1459 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1460 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1461 If this produces the same color as COLOR, try a color where all RGB
1462 values have DELTA added. Return the allocated color in *COLOR.
1463 DISPLAY is the X display, CMAP is the colormap to operate on.
1464 Value is non-zero if successful. */
1466 static int
1467 w32_alloc_lighter_color (f, color, factor, delta)
1468 struct frame *f;
1469 COLORREF *color;
1470 double factor;
1471 int delta;
1473 COLORREF new;
1474 long bright;
1476 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1477 delta /= 256;
1479 /* Change RGB values by specified FACTOR. Avoid overflow! */
1480 xassert (factor >= 0);
1481 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1482 min (0xff, factor * GetGValue (*color)),
1483 min (0xff, factor * GetBValue (*color)));
1485 /* Calculate brightness of COLOR. */
1486 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1487 + GetBValue (*color)) / 6;
1489 /* We only boost colors that are darker than
1490 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1491 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1492 /* Make an additive adjustment to NEW, because it's dark enough so
1493 that scaling by FACTOR alone isn't enough. */
1495 /* How far below the limit this color is (0 - 1, 1 being darker). */
1496 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1497 /* The additive adjustment. */
1498 int min_delta = delta * dimness * factor / 2;
1500 if (factor < 1)
1501 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1502 max (0, min (0xff, min_delta - GetGValue (*color))),
1503 max (0, min (0xff, min_delta - GetBValue (*color))));
1504 else
1505 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1506 max (0, min (0xff, min_delta + GetGValue (*color))),
1507 max (0, min (0xff, min_delta + GetBValue (*color))));
1510 if (new == *color)
1511 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1512 max (0, min (0xff, delta + GetGValue (*color))),
1513 max (0, min (0xff, delta + GetBValue (*color))));
1515 /* TODO: Map to palette and retry with delta if same? */
1516 /* TODO: Free colors (if using palette)? */
1518 if (new == *color)
1519 return 0;
1521 *color = new;
1523 return 1;
1526 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1527 colors in COLORS. On W32, we no longer try to map colors to
1528 a palette. */
1529 void
1530 x_query_colors (f, colors, ncolors)
1531 struct frame *f;
1532 XColor *colors;
1533 int ncolors;
1535 int i;
1537 for (i = 0; i < ncolors; i++)
1539 DWORD pixel = colors[i].pixel;
1540 /* Convert to a 16 bit value in range 0 - 0xffff. */
1541 colors[i].red = GetRValue (pixel) * 257;
1542 colors[i].green = GetGValue (pixel) * 257;
1543 colors[i].blue = GetBValue (pixel) * 257;
1547 void
1548 x_query_color (f, color)
1549 struct frame *f;
1550 XColor *color;
1552 x_query_colors (f, color, 1);
1556 /* Set up the foreground color for drawing relief lines of glyph
1557 string S. RELIEF is a pointer to a struct relief containing the GC
1558 with which lines will be drawn. Use a color that is FACTOR or
1559 DELTA lighter or darker than the relief's background which is found
1560 in S->f->output_data.x->relief_background. If such a color cannot
1561 be allocated, use DEFAULT_PIXEL, instead. */
1563 static void
1564 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1565 struct frame *f;
1566 struct relief *relief;
1567 double factor;
1568 int delta;
1569 COLORREF default_pixel;
1571 XGCValues xgcv;
1572 struct w32_output *di = f->output_data.w32;
1573 unsigned long mask = GCForeground;
1574 COLORREF pixel;
1575 COLORREF background = di->relief_background;
1576 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1578 /* TODO: Free colors (if using palette)? */
1580 /* Allocate new color. */
1581 xgcv.foreground = default_pixel;
1582 pixel = background;
1583 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1585 relief->allocated_p = 1;
1586 xgcv.foreground = relief->pixel = pixel;
1589 if (relief->gc == 0)
1591 #if 0 /* TODO: stipple */
1592 xgcv.stipple = dpyinfo->gray;
1593 mask |= GCStipple;
1594 #endif
1595 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1597 else
1598 XChangeGC (NULL, relief->gc, mask, &xgcv);
1602 /* Set up colors for the relief lines around glyph string S. */
1604 static void
1605 x_setup_relief_colors (s)
1606 struct glyph_string *s;
1608 struct w32_output *di = s->f->output_data.w32;
1609 COLORREF color;
1611 if (s->face->use_box_color_for_shadows_p)
1612 color = s->face->box_color;
1613 else if (s->first_glyph->type == IMAGE_GLYPH
1614 && s->img->pixmap
1615 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1616 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1617 else
1618 color = s->gc->background;
1620 if (di->white_relief.gc == 0
1621 || color != di->relief_background)
1623 di->relief_background = color;
1624 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1625 WHITE_PIX_DEFAULT (s->f));
1626 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1627 BLACK_PIX_DEFAULT (s->f));
1632 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1633 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1634 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1635 relief. LEFT_P non-zero means draw a relief on the left side of
1636 the rectangle. RIGHT_P non-zero means draw a relief on the right
1637 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1638 when drawing. */
1640 static void
1641 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1642 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1643 struct frame *f;
1644 int left_x, top_y, right_x, bottom_y, width;
1645 int top_p, bot_p, left_p, right_p, raised_p;
1646 RECT *clip_rect;
1648 int i;
1649 XGCValues gc;
1650 HDC hdc = get_frame_dc (f);
1652 if (raised_p)
1653 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1654 else
1655 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1657 w32_set_clip_rectangle (hdc, clip_rect);
1659 /* Top. */
1660 if (top_p)
1661 for (i = 0; i < width; ++i)
1662 w32_fill_area (f, hdc, gc.foreground,
1663 left_x + i * left_p, top_y + i,
1664 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1666 /* Left. */
1667 if (left_p)
1668 for (i = 0; i < width; ++i)
1669 w32_fill_area (f, hdc, gc.foreground,
1670 left_x + i, top_y + i, 1,
1671 bottom_y - top_y - 2 * i + 1);
1673 if (raised_p)
1674 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1675 else
1676 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1678 /* Bottom. */
1679 if (bot_p)
1680 for (i = 0; i < width; ++i)
1681 w32_fill_area (f, hdc, gc.foreground,
1682 left_x + i * left_p, bottom_y - i,
1683 right_x - left_x - i * (left_p + right_p) + 1, 1);
1685 /* Right. */
1686 if (right_p)
1687 for (i = 0; i < width; ++i)
1688 w32_fill_area (f, hdc, gc.foreground,
1689 right_x - i, top_y + i + 1, 1,
1690 bottom_y - top_y - 2 * i - 1);
1692 w32_set_clip_rectangle (hdc, NULL);
1694 release_frame_dc (f, hdc);
1698 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1699 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1700 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1701 left side of the rectangle. RIGHT_P non-zero means draw a line
1702 on the right side of the rectangle. CLIP_RECT is the clipping
1703 rectangle to use when drawing. */
1705 static void
1706 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1707 left_p, right_p, clip_rect)
1708 struct glyph_string *s;
1709 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1710 RECT *clip_rect;
1712 w32_set_clip_rectangle (s->hdc, clip_rect);
1714 /* Top. */
1715 w32_fill_area (s->f, s->hdc, s->face->box_color,
1716 left_x, top_y, right_x - left_x + 1, width);
1718 /* Left. */
1719 if (left_p)
1721 w32_fill_area (s->f, s->hdc, s->face->box_color,
1722 left_x, top_y, width, bottom_y - top_y + 1);
1725 /* Bottom. */
1726 w32_fill_area (s->f, s->hdc, s->face->box_color,
1727 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1729 /* Right. */
1730 if (right_p)
1732 w32_fill_area (s->f, s->hdc, s->face->box_color,
1733 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1736 w32_set_clip_rectangle (s->hdc, NULL);
1740 /* Draw a box around glyph string S. */
1742 static void
1743 x_draw_glyph_string_box (s)
1744 struct glyph_string *s;
1746 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1747 int left_p, right_p;
1748 struct glyph *last_glyph;
1749 RECT clip_rect;
1751 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1752 ? WINDOW_RIGHT_EDGE_X (s->w)
1753 : window_box_right (s->w, s->area));
1755 /* The glyph that may have a right box line. */
1756 last_glyph = (s->cmp || s->img
1757 ? s->first_glyph
1758 : s->first_glyph + s->nchars - 1);
1760 width = eabs (s->face->box_line_width);
1761 raised_p = s->face->box == FACE_RAISED_BOX;
1762 left_x = s->x;
1763 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1764 ? last_x - 1
1765 : min (last_x, s->x + s->background_width) - 1));
1766 top_y = s->y;
1767 bottom_y = top_y + s->height - 1;
1769 left_p = (s->first_glyph->left_box_line_p
1770 || (s->hl == DRAW_MOUSE_FACE
1771 && (s->prev == NULL
1772 || s->prev->hl != s->hl)));
1773 right_p = (last_glyph->right_box_line_p
1774 || (s->hl == DRAW_MOUSE_FACE
1775 && (s->next == NULL
1776 || s->next->hl != s->hl)));
1778 get_glyph_string_clip_rect (s, &clip_rect);
1780 if (s->face->box == FACE_SIMPLE_BOX)
1781 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1782 left_p, right_p, &clip_rect);
1783 else
1785 x_setup_relief_colors (s);
1786 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1787 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1792 /* Draw foreground of image glyph string S. */
1794 static void
1795 x_draw_image_foreground (s)
1796 struct glyph_string *s;
1798 int x = s->x;
1799 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1801 /* If first glyph of S has a left box line, start drawing it to the
1802 right of that line. */
1803 if (s->face->box != FACE_NO_BOX
1804 && s->first_glyph->left_box_line_p
1805 && s->slice.x == 0)
1806 x += eabs (s->face->box_line_width);
1808 /* If there is a margin around the image, adjust x- and y-position
1809 by that margin. */
1810 if (s->slice.x == 0)
1811 x += s->img->hmargin;
1812 if (s->slice.y == 0)
1813 y += s->img->vmargin;
1815 SaveDC (s->hdc);
1817 if (s->img->pixmap)
1819 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1820 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1821 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1822 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1823 SetBkColor (compat_hdc, RGB (255, 255, 255));
1824 SetTextColor (s->hdc, RGB (0, 0, 0));
1825 x_set_glyph_string_clipping (s);
1827 if (s->img->mask)
1829 HDC mask_dc = CreateCompatibleDC (s->hdc);
1830 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1832 SetTextColor (s->hdc, RGB (255, 255, 255));
1833 SetBkColor (s->hdc, RGB (0, 0, 0));
1835 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1836 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1837 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1838 mask_dc, s->slice.x, s->slice.y, SRCAND);
1839 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1840 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1842 SelectObject (mask_dc, mask_orig_obj);
1843 DeleteDC (mask_dc);
1845 else
1847 SetTextColor (s->hdc, s->gc->foreground);
1848 SetBkColor (s->hdc, s->gc->background);
1850 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1851 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1853 /* When the image has a mask, we can expect that at
1854 least part of a mouse highlight or a block cursor will
1855 be visible. If the image doesn't have a mask, make
1856 a block cursor visible by drawing a rectangle around
1857 the image. I believe it's looking better if we do
1858 nothing here for mouse-face. */
1859 if (s->hl == DRAW_CURSOR)
1861 int r = s->img->relief;
1862 if (r < 0) r = -r;
1863 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
1864 s->slice.width + r*2 - 1,
1865 s->slice.height + r*2 - 1);
1869 w32_set_clip_rectangle (s->hdc, NULL);
1870 SelectObject (s->hdc, orig_brush);
1871 DeleteObject (fg_brush);
1872 SelectObject (compat_hdc, orig_obj);
1873 DeleteDC (compat_hdc);
1875 else
1876 w32_draw_rectangle (s->hdc, s->gc, x, y,
1877 s->slice.width - 1, s->slice.height - 1);
1879 RestoreDC (s->hdc ,-1);
1883 /* Draw a relief around the image glyph string S. */
1885 static void
1886 x_draw_image_relief (s)
1887 struct glyph_string *s;
1889 int x0, y0, x1, y1, thick, raised_p;
1890 RECT r;
1891 int x = s->x;
1892 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1894 /* If first glyph of S has a left box line, start drawing it to the
1895 right of that line. */
1896 if (s->face->box != FACE_NO_BOX
1897 && s->first_glyph->left_box_line_p
1898 && s->slice.x == 0)
1899 x += eabs (s->face->box_line_width);
1901 /* If there is a margin around the image, adjust x- and y-position
1902 by that margin. */
1903 if (s->slice.x == 0)
1904 x += s->img->hmargin;
1905 if (s->slice.y == 0)
1906 y += s->img->vmargin;
1908 if (s->hl == DRAW_IMAGE_SUNKEN
1909 || s->hl == DRAW_IMAGE_RAISED)
1911 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1912 raised_p = s->hl == DRAW_IMAGE_RAISED;
1914 else
1916 thick = eabs (s->img->relief);
1917 raised_p = s->img->relief > 0;
1920 x0 = x - thick;
1921 y0 = y - thick;
1922 x1 = x + s->slice.width + thick - 1;
1923 y1 = y + s->slice.height + thick - 1;
1925 x_setup_relief_colors (s);
1926 get_glyph_string_clip_rect (s, &r);
1927 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
1928 s->slice.y == 0,
1929 s->slice.y + s->slice.height == s->img->height,
1930 s->slice.x == 0,
1931 s->slice.x + s->slice.width == s->img->width,
1932 &r);
1936 /* Draw the foreground of image glyph string S to PIXMAP. */
1938 static void
1939 w32_draw_image_foreground_1 (s, pixmap)
1940 struct glyph_string *s;
1941 HBITMAP pixmap;
1943 HDC hdc = CreateCompatibleDC (s->hdc);
1944 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
1945 int x = 0;
1946 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1948 /* If first glyph of S has a left box line, start drawing it to the
1949 right of that line. */
1950 if (s->face->box != FACE_NO_BOX
1951 && s->first_glyph->left_box_line_p
1952 && s->slice.x == 0)
1953 x += eabs (s->face->box_line_width);
1955 /* If there is a margin around the image, adjust x- and y-position
1956 by that margin. */
1957 if (s->slice.x == 0)
1958 x += s->img->hmargin;
1959 if (s->slice.y == 0)
1960 y += s->img->vmargin;
1962 if (s->img->pixmap)
1964 HDC compat_hdc = CreateCompatibleDC (hdc);
1965 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1966 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
1967 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1969 if (s->img->mask)
1971 HDC mask_dc = CreateCompatibleDC (hdc);
1972 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1974 SetTextColor (hdc, RGB (0, 0, 0));
1975 SetBkColor (hdc, RGB (255, 255, 255));
1976 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1977 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1978 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1979 mask_dc, s->slice.x, s->slice.y, SRCAND);
1980 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1981 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1983 SelectObject (mask_dc, mask_orig_obj);
1984 DeleteDC (mask_dc);
1986 else
1988 SetTextColor (hdc, s->gc->foreground);
1989 SetBkColor (hdc, s->gc->background);
1991 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1992 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1994 /* When the image has a mask, we can expect that at
1995 least part of a mouse highlight or a block cursor will
1996 be visible. If the image doesn't have a mask, make
1997 a block cursor visible by drawing a rectangle around
1998 the image. I believe it's looking better if we do
1999 nothing here for mouse-face. */
2000 if (s->hl == DRAW_CURSOR)
2002 int r = s->img->relief;
2003 if (r < 0) r = -r;
2004 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2005 s->slice.width + r*2 - 1,
2006 s->slice.height + r*2 - 1);
2010 SelectObject (hdc, orig_brush);
2011 DeleteObject (fg_brush);
2012 SelectObject (compat_hdc, orig_obj);
2013 DeleteDC (compat_hdc);
2015 else
2016 w32_draw_rectangle (hdc, s->gc, x, y,
2017 s->slice.width - 1, s->slice.height - 1);
2019 SelectObject (hdc, orig_hdc_obj);
2020 DeleteDC (hdc);
2024 /* Draw part of the background of glyph string S. X, Y, W, and H
2025 give the rectangle to draw. */
2027 static void
2028 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2029 struct glyph_string *s;
2030 int x, y, w, h;
2032 #if 0 /* TODO: stipple */
2033 if (s->stippled_p)
2035 /* Fill background with a stipple pattern. */
2036 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2037 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2038 XSetFillStyle (s->display, s->gc, FillSolid);
2040 else
2041 #endif
2042 x_clear_glyph_string_rect (s, x, y, w, h);
2046 /* Draw image glyph string S.
2048 s->y
2049 s->x +-------------------------
2050 | s->face->box
2052 | +-------------------------
2053 | | s->img->vmargin
2055 | | +-------------------
2056 | | | the image
2060 static void
2061 x_draw_image_glyph_string (s)
2062 struct glyph_string *s;
2064 int x, y;
2065 int box_line_hwidth = eabs (s->face->box_line_width);
2066 int box_line_vwidth = max (s->face->box_line_width, 0);
2067 int height;
2068 HBITMAP pixmap = 0;
2070 height = s->height - 2 * box_line_vwidth;
2072 /* Fill background with face under the image. Do it only if row is
2073 taller than image or if image has a clip mask to reduce
2074 flickering. */
2075 s->stippled_p = s->face->stipple != 0;
2076 if (height > s->slice.height
2077 || s->img->hmargin
2078 || s->img->vmargin
2079 || s->img->mask
2080 || s->img->pixmap == 0
2081 || s->width != s->background_width)
2083 x = s->x;
2084 if (s->first_glyph->left_box_line_p
2085 && s->slice.x == 0)
2086 x += box_line_hwidth;
2088 y = s->y;
2089 if (s->slice.y == 0)
2090 y += box_line_vwidth;
2092 #if 0 /* TODO: figure out if we need to do this on Windows. */
2093 if (s->img->mask)
2095 /* Create a pixmap as large as the glyph string. Fill it
2096 with the background color. Copy the image to it, using
2097 its mask. Copy the temporary pixmap to the display. */
2098 Screen *screen = FRAME_X_SCREEN (s->f);
2099 int depth = DefaultDepthOfScreen (screen);
2101 /* Create a pixmap as large as the glyph string. */
2102 pixmap = XCreatePixmap (s->display, s->window,
2103 s->background_width,
2104 s->height, depth);
2106 /* Don't clip in the following because we're working on the
2107 pixmap. */
2108 XSetClipMask (s->display, s->gc, None);
2110 /* Fill the pixmap with the background color/stipple. */
2111 if (s->stippled_p)
2113 /* Fill background with a stipple pattern. */
2114 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2115 XFillRectangle (s->display, pixmap, s->gc,
2116 0, 0, s->background_width, s->height);
2117 XSetFillStyle (s->display, s->gc, FillSolid);
2119 else
2121 XGCValues xgcv;
2122 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2123 &xgcv);
2124 XSetForeground (s->display, s->gc, xgcv.background);
2125 XFillRectangle (s->display, pixmap, s->gc,
2126 0, 0, s->background_width, s->height);
2127 XSetForeground (s->display, s->gc, xgcv.foreground);
2130 else
2131 #endif
2132 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2134 s->background_filled_p = 1;
2137 /* Draw the foreground. */
2138 if (pixmap != 0)
2140 w32_draw_image_foreground_1 (s, pixmap);
2141 x_set_glyph_string_clipping (s);
2143 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2144 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2145 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2146 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2148 SetTextColor (s->hdc, s->gc->foreground);
2149 SetBkColor (s->hdc, s->gc->background);
2150 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2151 compat_hdc, 0, 0, SRCCOPY);
2153 SelectObject (s->hdc, orig_brush);
2154 DeleteObject (fg_brush);
2155 SelectObject (compat_hdc, orig_obj);
2156 DeleteDC (compat_hdc);
2158 DeleteObject (pixmap);
2159 pixmap = 0;
2161 else
2162 x_draw_image_foreground (s);
2164 /* If we must draw a relief around the image, do it. */
2165 if (s->img->relief
2166 || s->hl == DRAW_IMAGE_RAISED
2167 || s->hl == DRAW_IMAGE_SUNKEN)
2168 x_draw_image_relief (s);
2172 /* Draw stretch glyph string S. */
2174 static void
2175 x_draw_stretch_glyph_string (s)
2176 struct glyph_string *s;
2178 xassert (s->first_glyph->type == STRETCH_GLYPH);
2180 if (s->hl == DRAW_CURSOR
2181 && !x_stretch_cursor_p)
2183 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2184 as wide as the stretch glyph. */
2185 int width, background_width = s->background_width;
2186 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2188 if (x < left_x)
2190 background_width -= left_x - x;
2191 x = left_x;
2193 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2195 /* Draw cursor. */
2196 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2198 /* Clear rest using the GC of the original non-cursor face. */
2199 if (width < background_width)
2201 XGCValues *gc = s->face->gc;
2202 int y = s->y;
2203 int w = background_width - width, h = s->height;
2204 RECT r;
2205 HDC hdc = s->hdc;
2207 x += width;
2208 if (s->row->mouse_face_p
2209 && cursor_in_mouse_face_p (s->w))
2211 x_set_mouse_face_gc (s);
2212 gc = s->gc;
2214 else
2215 gc = s->face->gc;
2217 get_glyph_string_clip_rect (s, &r);
2218 w32_set_clip_rectangle (hdc, &r);
2220 #if 0 /* TODO: stipple */
2221 if (s->face->stipple)
2223 /* Fill background with a stipple pattern. */
2224 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2225 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2226 XSetFillStyle (s->display, gc, FillSolid);
2228 else
2229 #endif
2231 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2235 else if (!s->background_filled_p)
2237 int background_width = s->background_width;
2238 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2240 /* Don't draw into left margin, fringe or scrollbar area
2241 except for header line and mode line. */
2242 if (x < left_x && !s->row->mode_line_p)
2244 background_width -= left_x - x;
2245 x = left_x;
2247 if (background_width > 0)
2248 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2251 s->background_filled_p = 1;
2255 /* Draw glyph string S. */
2257 static void
2258 x_draw_glyph_string (s)
2259 struct glyph_string *s;
2261 int relief_drawn_p = 0;
2263 /* If S draws into the background of its successor, draw the
2264 background of the successor first so that S can draw into it.
2265 This makes S->next use XDrawString instead of XDrawImageString. */
2266 if (s->next && s->right_overhang && !s->for_overlaps)
2268 int width;
2269 struct glyph_string *next;
2270 for (width = 0, next = s->next;
2271 next && width < s->right_overhang;
2272 width += next->width, next = next->next)
2273 if (next->first_glyph->type != IMAGE_GLYPH)
2275 x_set_glyph_string_gc (next);
2276 x_set_glyph_string_clipping (next);
2277 if (next->first_glyph->type == STRETCH_GLYPH)
2278 x_draw_stretch_glyph_string (next);
2279 else
2280 x_draw_glyph_string_background (next, 1);
2281 next->num_clips = 0;
2285 /* Set up S->gc, set clipping and draw S. */
2286 x_set_glyph_string_gc (s);
2288 /* Draw relief (if any) in advance for char/composition so that the
2289 glyph string can be drawn over it. */
2290 if (!s->for_overlaps
2291 && s->face->box != FACE_NO_BOX
2292 && (s->first_glyph->type == CHAR_GLYPH
2293 || s->first_glyph->type == COMPOSITE_GLYPH))
2296 x_set_glyph_string_clipping (s);
2297 x_draw_glyph_string_background (s, 1);
2298 x_draw_glyph_string_box (s);
2299 x_set_glyph_string_clipping (s);
2300 relief_drawn_p = 1;
2302 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2303 && !s->clip_tail
2304 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2305 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2306 /* We must clip just this glyph. left_overhang part has already
2307 drawn when s->prev was drawn, and right_overhang part will be
2308 drawn later when s->next is drawn. */
2309 x_set_glyph_string_clipping_exactly (s, s);
2310 else
2311 x_set_glyph_string_clipping (s);
2313 switch (s->first_glyph->type)
2315 case IMAGE_GLYPH:
2316 x_draw_image_glyph_string (s);
2317 break;
2319 case STRETCH_GLYPH:
2320 x_draw_stretch_glyph_string (s);
2321 break;
2323 case CHAR_GLYPH:
2324 if (s->for_overlaps)
2325 s->background_filled_p = 1;
2326 else
2327 x_draw_glyph_string_background (s, 0);
2328 x_draw_glyph_string_foreground (s);
2329 break;
2331 case COMPOSITE_GLYPH:
2332 if (s->for_overlaps || (s->cmp_from > 0
2333 && ! s->first_glyph->u.cmp.automatic))
2334 s->background_filled_p = 1;
2335 else
2336 x_draw_glyph_string_background (s, 1);
2337 x_draw_composite_glyph_string_foreground (s);
2338 break;
2340 default:
2341 abort ();
2344 if (!s->for_overlaps)
2346 /* Draw underline. */
2347 if (s->face->underline_p)
2349 unsigned long thickness, position;
2350 int y;
2352 if (s->prev && s->prev->face->underline_p)
2354 /* We use the same underline style as the previous one. */
2355 thickness = s->prev->underline_thickness;
2356 position = s->prev->underline_position;
2358 else
2360 /* Get the underline thickness. Default is 1 pixel. */
2361 if (s->font && s->font->underline_thickness > 0)
2362 thickness = s->font->underline_thickness;
2363 else
2364 thickness = 1;
2365 if (x_underline_at_descent_line)
2366 position = (s->height - thickness) - (s->ybase - s->y);
2367 else
2369 /* Get the underline position. This is the recommended
2370 vertical offset in pixels from the baseline to the top of
2371 the underline. This is a signed value according to the
2372 specs, and its default is
2374 ROUND ((maximum_descent) / 2), with
2375 ROUND (x) = floor (x + 0.5) */
2377 if (x_use_underline_position_properties
2378 && s->font && s->font->underline_position >= 0)
2379 position = s->font->underline_position;
2380 else if (s->font)
2381 position = (s->font->descent + 1) / 2;
2383 position = max (position, underline_minimum_offset);
2385 /* Check the sanity of thickness and position. We should
2386 avoid drawing underline out of the current line area. */
2387 if (s->y + s->height <= s->ybase + position)
2388 position = (s->height - 1) - (s->ybase - s->y);
2389 if (s->y + s->height < s->ybase + position + thickness)
2390 thickness = (s->y + s->height) - (s->ybase + position);
2391 s->underline_thickness = thickness;
2392 s->underline_position =position;
2393 y = s->ybase + position;
2394 if (s->face->underline_defaulted_p)
2396 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2397 y, s->width, 1);
2399 else
2401 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2402 y, s->width, 1);
2405 /* Draw overline. */
2406 if (s->face->overline_p)
2408 unsigned long dy = 0, h = 1;
2410 if (s->face->overline_color_defaulted_p)
2412 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2413 s->y + dy, s->width, h);
2415 else
2417 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2418 s->y + dy, s->width, h);
2422 /* Draw strike-through. */
2423 if (s->face->strike_through_p
2424 && !FONT_TEXTMETRIC(s->font).tmStruckOut)
2426 unsigned long h = 1;
2427 unsigned long dy = (s->height - h) / 2;
2429 if (s->face->strike_through_color_defaulted_p)
2431 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2432 s->width, h);
2434 else
2436 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
2437 s->y + dy, s->width, h);
2441 /* Draw relief if not yet drawn. */
2442 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2443 x_draw_glyph_string_box (s);
2445 if (s->prev)
2447 struct glyph_string *prev;
2449 for (prev = s->prev; prev; prev = prev->prev)
2450 if (prev->hl != s->hl
2451 && prev->x + prev->width + prev->right_overhang > s->x)
2453 /* As prev was drawn while clipped to its own area, we
2454 must draw the right_overhang part using s->hl now. */
2455 enum draw_glyphs_face save = prev->hl;
2457 prev->hl = s->hl;
2458 x_set_glyph_string_gc (prev);
2459 x_set_glyph_string_clipping_exactly (s, prev);
2460 if (prev->first_glyph->type == CHAR_GLYPH)
2461 x_draw_glyph_string_foreground (prev);
2462 else
2463 x_draw_composite_glyph_string_foreground (prev);
2464 w32_set_clip_rectangle (prev->hdc, NULL);
2465 prev->hl = save;
2466 prev->num_clips = 0;
2470 if (s->next)
2472 struct glyph_string *next;
2474 for (next = s->next; next; next = next->next)
2475 if (next->hl != s->hl
2476 && next->x - next->left_overhang < s->x + s->width)
2478 /* As next will be drawn while clipped to its own area,
2479 we must draw the left_overhang part using s->hl now. */
2480 enum draw_glyphs_face save = next->hl;
2482 next->hl = s->hl;
2483 x_set_glyph_string_gc (next);
2484 x_set_glyph_string_clipping_exactly (s, next);
2485 if (next->first_glyph->type == CHAR_GLYPH)
2486 x_draw_glyph_string_foreground (next);
2487 else
2488 x_draw_composite_glyph_string_foreground (next);
2489 w32_set_clip_rectangle (next->hdc, NULL);
2490 next->hl = save;
2491 next->num_clips = 0;
2496 /* Reset clipping. */
2497 w32_set_clip_rectangle (s->hdc, NULL);
2498 s->num_clips = 0;
2502 /* Shift display to make room for inserted glyphs. */
2504 void
2505 w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2506 struct frame *f;
2507 int x, y, width, height, shift_by;
2509 HDC hdc;
2511 hdc = get_frame_dc (f);
2512 BitBlt (hdc, x + shift_by, y, width, height,
2513 hdc, x, y, SRCCOPY);
2515 release_frame_dc (f, hdc);
2519 /* Delete N glyphs at the nominal cursor position. Not implemented
2520 for X frames. */
2522 static void
2523 x_delete_glyphs (f, n)
2524 struct frame *f;
2525 register int n;
2527 if (! FRAME_W32_P (f))
2528 return;
2530 abort ();
2534 /* Clear entire frame. If updating_frame is non-null, clear that
2535 frame. Otherwise clear the selected frame. */
2537 static void
2538 x_clear_frame (struct frame *f)
2540 if (! FRAME_W32_P (f))
2541 return;
2543 /* Clearing the frame will erase any cursor, so mark them all as no
2544 longer visible. */
2545 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2546 output_cursor.hpos = output_cursor.vpos = 0;
2547 output_cursor.x = -1;
2549 /* We don't set the output cursor here because there will always
2550 follow an explicit cursor_to. */
2551 BLOCK_INPUT;
2553 w32_clear_window (f);
2555 /* We have to clear the scroll bars, too. If we have changed
2556 colors or something like that, then they should be notified. */
2557 x_scroll_bar_clear (f);
2559 UNBLOCK_INPUT;
2563 /* Make audible bell. */
2565 static void
2566 w32_ring_bell (struct frame *f)
2568 BLOCK_INPUT;
2570 if (FRAME_W32_P (f) && visible_bell)
2572 int i;
2573 HWND hwnd = FRAME_W32_WINDOW (f);
2575 for (i = 0; i < 5; i++)
2577 FlashWindow (hwnd, TRUE);
2578 Sleep (10);
2580 FlashWindow (hwnd, FALSE);
2582 else
2583 w32_sys_ring_bell (f);
2585 UNBLOCK_INPUT;
2589 /* Specify how many text lines, from the top of the window,
2590 should be affected by insert-lines and delete-lines operations.
2591 This, and those operations, are used only within an update
2592 that is bounded by calls to x_update_begin and x_update_end. */
2594 static void
2595 w32_set_terminal_window (n)
2596 register int n;
2598 /* This function intentionally left blank. */
2602 /***********************************************************************
2603 Line Dance
2604 ***********************************************************************/
2606 /* Perform an insert-lines or delete-lines operation, inserting N
2607 lines or deleting -N lines at vertical position VPOS. */
2609 static void
2610 x_ins_del_lines (f, vpos, n)
2611 struct frame *f;
2612 int vpos, n;
2614 if (! FRAME_W32_P (f))
2615 return;
2617 abort ();
2621 /* Scroll part of the display as described by RUN. */
2623 static void
2624 x_scroll_run (w, run)
2625 struct window *w;
2626 struct run *run;
2628 struct frame *f = XFRAME (w->frame);
2629 int x, y, width, height, from_y, to_y, bottom_y;
2630 HWND hwnd = FRAME_W32_WINDOW (f);
2631 HRGN expect_dirty;
2633 /* Get frame-relative bounding box of the text display area of W,
2634 without mode lines. Include in this box the left and right
2635 fringes of W. */
2636 window_box (w, -1, &x, &y, &width, &height);
2638 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2639 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2640 bottom_y = y + height;
2642 if (to_y < from_y)
2644 /* Scrolling up. Make sure we don't copy part of the mode
2645 line at the bottom. */
2646 if (from_y + run->height > bottom_y)
2647 height = bottom_y - from_y;
2648 else
2649 height = run->height;
2650 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2652 else
2654 /* Scolling down. Make sure we don't copy over the mode line.
2655 at the bottom. */
2656 if (to_y + run->height > bottom_y)
2657 height = bottom_y - to_y;
2658 else
2659 height = run->height;
2660 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2663 BLOCK_INPUT;
2665 /* Cursor off. Will be switched on again in x_update_window_end. */
2666 updated_window = w;
2667 x_clear_cursor (w);
2670 RECT from;
2671 RECT to;
2672 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2673 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2675 from.left = to.left = x;
2676 from.right = to.right = x + width;
2677 from.top = from_y;
2678 from.bottom = from_y + height;
2679 to.top = y;
2680 to.bottom = bottom_y;
2682 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2683 NULL, SW_INVALIDATE);
2685 /* Combine this with what we expect to be dirty. This covers the
2686 case where not all of the region we expect is actually dirty. */
2687 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2689 /* If the dirty region is not what we expected, redraw the entire frame. */
2690 if (!EqualRgn (combined, expect_dirty))
2691 SET_FRAME_GARBAGED (f);
2693 DeleteObject (dirty);
2694 DeleteObject (combined);
2697 UNBLOCK_INPUT;
2698 DeleteObject (expect_dirty);
2703 /***********************************************************************
2704 Exposure Events
2705 ***********************************************************************/
2707 static void
2708 frame_highlight (f)
2709 struct frame *f;
2711 x_update_cursor (f, 1);
2712 x_set_frame_alpha (f);
2715 static void
2716 frame_unhighlight (f)
2717 struct frame *f;
2719 x_update_cursor (f, 1);
2720 x_set_frame_alpha (f);
2723 /* The focus has changed. Update the frames as necessary to reflect
2724 the new situation. Note that we can't change the selected frame
2725 here, because the Lisp code we are interrupting might become confused.
2726 Each event gets marked with the frame in which it occurred, so the
2727 Lisp code can tell when the switch took place by examining the events. */
2729 static void
2730 x_new_focus_frame (dpyinfo, frame)
2731 struct w32_display_info *dpyinfo;
2732 struct frame *frame;
2734 struct frame *old_focus = dpyinfo->w32_focus_frame;
2736 if (frame != dpyinfo->w32_focus_frame)
2738 /* Set this before calling other routines, so that they see
2739 the correct value of w32_focus_frame. */
2740 dpyinfo->w32_focus_frame = frame;
2742 if (old_focus && old_focus->auto_lower)
2743 x_lower_frame (old_focus);
2745 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2746 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2747 else
2748 pending_autoraise_frame = 0;
2751 x_frame_rehighlight (dpyinfo);
2755 /* Handle FocusIn and FocusOut state changes for FRAME.
2756 If FRAME has focus and there exists more than one frame, puts
2757 a FOCUS_IN_EVENT into *BUFP. */
2759 static void
2760 x_focus_changed (type, state, dpyinfo, frame, bufp)
2761 int type;
2762 int state;
2763 struct w32_display_info *dpyinfo;
2764 struct frame *frame;
2765 struct input_event *bufp;
2767 if (type == WM_SETFOCUS)
2769 if (dpyinfo->w32_focus_event_frame != frame)
2771 x_new_focus_frame (dpyinfo, frame);
2772 dpyinfo->w32_focus_event_frame = frame;
2774 /* Don't stop displaying the initial startup message
2775 for a switch-frame event we don't need. */
2776 if (NILP (Vterminal_frame)
2777 && CONSP (Vframe_list)
2778 && !NILP (XCDR (Vframe_list)))
2780 bufp->kind = FOCUS_IN_EVENT;
2781 XSETFRAME (bufp->frame_or_window, frame);
2785 frame->output_data.x->focus_state |= state;
2787 /* TODO: IME focus? */
2789 else if (type == WM_KILLFOCUS)
2791 frame->output_data.x->focus_state &= ~state;
2793 if (dpyinfo->w32_focus_event_frame == frame)
2795 dpyinfo->w32_focus_event_frame = 0;
2796 x_new_focus_frame (dpyinfo, 0);
2799 /* TODO: IME focus? */
2804 /* The focus may have changed. Figure out if it is a real focus change,
2805 by checking both FocusIn/Out and Enter/LeaveNotify events.
2807 Returns FOCUS_IN_EVENT event in *BUFP. */
2809 static void
2810 w32_detect_focus_change (dpyinfo, event, bufp)
2811 struct w32_display_info *dpyinfo;
2812 W32Msg *event;
2813 struct input_event *bufp;
2815 struct frame *frame;
2817 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2818 if (! frame)
2819 return;
2821 /* On w32, this is only called from focus events, so no switch needed. */
2822 x_focus_changed (event->msg.message,
2823 (event->msg.message == WM_KILLFOCUS ?
2824 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2825 dpyinfo, frame, bufp);
2829 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2831 void
2832 x_mouse_leave (dpyinfo)
2833 struct w32_display_info *dpyinfo;
2835 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2838 /* The focus has changed, or we have redirected a frame's focus to
2839 another frame (this happens when a frame uses a surrogate
2840 mini-buffer frame). Shift the highlight as appropriate.
2842 The FRAME argument doesn't necessarily have anything to do with which
2843 frame is being highlighted or un-highlighted; we only use it to find
2844 the appropriate X display info. */
2846 static void
2847 w32_frame_rehighlight (frame)
2848 struct frame *frame;
2850 if (! FRAME_W32_P (frame))
2851 return;
2852 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
2855 static void
2856 x_frame_rehighlight (dpyinfo)
2857 struct w32_display_info *dpyinfo;
2859 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2861 if (dpyinfo->w32_focus_frame)
2863 dpyinfo->x_highlight_frame
2864 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2865 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2866 : dpyinfo->w32_focus_frame);
2867 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2869 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
2870 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2873 else
2874 dpyinfo->x_highlight_frame = 0;
2876 if (dpyinfo->x_highlight_frame != old_highlight)
2878 if (old_highlight)
2879 frame_unhighlight (old_highlight);
2880 if (dpyinfo->x_highlight_frame)
2881 frame_highlight (dpyinfo->x_highlight_frame);
2885 /* Keyboard processing - modifier keys, etc. */
2887 /* Convert a keysym to its name. */
2889 char *
2890 x_get_keysym_name (keysym)
2891 int keysym;
2893 /* Make static so we can always return it */
2894 static char value[100];
2896 BLOCK_INPUT;
2897 GetKeyNameText (keysym, value, 100);
2898 UNBLOCK_INPUT;
2900 return value;
2903 static int codepage_for_locale(LCID locale)
2905 char cp[20];
2907 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
2908 return atoi (cp);
2909 else
2910 return CP_ACP;
2914 /* Mouse clicks and mouse movement. Rah. */
2916 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2917 the state in PUP. XBUTTON provides extra information for extended mouse
2918 button messages. Returns FALSE if unable to parse the message. */
2919 BOOL
2920 parse_button (message, xbutton, pbutton, pup)
2921 int message;
2922 int xbutton;
2923 int * pbutton;
2924 int * pup;
2926 int button = 0;
2927 int up = 0;
2929 switch (message)
2931 case WM_LBUTTONDOWN:
2932 button = 0;
2933 up = 0;
2934 break;
2935 case WM_LBUTTONUP:
2936 button = 0;
2937 up = 1;
2938 break;
2939 case WM_MBUTTONDOWN:
2940 if (NILP (Vw32_swap_mouse_buttons))
2941 button = 1;
2942 else
2943 button = 2;
2944 up = 0;
2945 break;
2946 case WM_MBUTTONUP:
2947 if (NILP (Vw32_swap_mouse_buttons))
2948 button = 1;
2949 else
2950 button = 2;
2951 up = 1;
2952 break;
2953 case WM_RBUTTONDOWN:
2954 if (NILP (Vw32_swap_mouse_buttons))
2955 button = 2;
2956 else
2957 button = 1;
2958 up = 0;
2959 break;
2960 case WM_RBUTTONUP:
2961 if (NILP (Vw32_swap_mouse_buttons))
2962 button = 2;
2963 else
2964 button = 1;
2965 up = 1;
2966 break;
2967 case WM_XBUTTONDOWN:
2968 button = xbutton + 2;
2969 up = 0;
2970 break;
2971 case WM_XBUTTONUP:
2972 button = xbutton + 2;
2973 up = 1;
2974 break;
2975 default:
2976 return (FALSE);
2979 if (pup) *pup = up;
2980 if (pbutton) *pbutton = button;
2982 return (TRUE);
2986 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2988 If the event is a button press, then note that we have grabbed
2989 the mouse. */
2991 static Lisp_Object
2992 construct_mouse_click (result, msg, f)
2993 struct input_event *result;
2994 W32Msg *msg;
2995 struct frame *f;
2997 int button;
2998 int up;
3000 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3001 &button, &up);
3003 /* Make the event type NO_EVENT; we'll change that when we decide
3004 otherwise. */
3005 result->kind = MOUSE_CLICK_EVENT;
3006 result->code = button;
3007 result->timestamp = msg->msg.time;
3008 result->modifiers = (msg->dwModifiers
3009 | (up
3010 ? up_modifier
3011 : down_modifier));
3013 XSETINT (result->x, LOWORD (msg->msg.lParam));
3014 XSETINT (result->y, HIWORD (msg->msg.lParam));
3015 XSETFRAME (result->frame_or_window, f);
3016 result->arg = Qnil;
3017 return Qnil;
3020 static Lisp_Object
3021 construct_mouse_wheel (result, msg, f)
3022 struct input_event *result;
3023 W32Msg *msg;
3024 struct frame *f;
3026 POINT p;
3027 int delta;
3029 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3030 : WHEEL_EVENT;
3031 result->code = 0;
3032 result->timestamp = msg->msg.time;
3034 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3035 forward, away from the user (up); a negative value indicates that
3036 the wheel was rotated backward, toward the user (down). */
3037 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3039 /* The up and down modifiers indicate if the wheel was rotated up or
3040 down based on WHEEL_DELTA value. */
3041 result->modifiers = (msg->dwModifiers
3042 | ((delta < 0 ) ? down_modifier : up_modifier));
3044 /* With multiple monitors, we can legitimately get negative
3045 coordinates, so cast to short to interpret them correctly. */
3046 p.x = (short) LOWORD (msg->msg.lParam);
3047 p.y = (short) HIWORD (msg->msg.lParam);
3048 ScreenToClient (msg->msg.hwnd, &p);
3049 XSETINT (result->x, p.x);
3050 XSETINT (result->y, p.y);
3051 XSETFRAME (result->frame_or_window, f);
3052 result->arg = Qnil;
3053 return Qnil;
3056 static Lisp_Object
3057 construct_drag_n_drop (result, msg, f)
3058 struct input_event *result;
3059 W32Msg *msg;
3060 struct frame *f;
3062 Lisp_Object files;
3063 Lisp_Object frame;
3064 HDROP hdrop;
3065 POINT p;
3066 WORD num_files;
3067 char *name;
3068 int i, len;
3070 result->kind = DRAG_N_DROP_EVENT;
3071 result->code = 0;
3072 result->timestamp = msg->msg.time;
3073 result->modifiers = msg->dwModifiers;
3075 hdrop = (HDROP) msg->msg.wParam;
3076 DragQueryPoint (hdrop, &p);
3078 #if 0
3079 p.x = LOWORD (msg->msg.lParam);
3080 p.y = HIWORD (msg->msg.lParam);
3081 ScreenToClient (msg->msg.hwnd, &p);
3082 #endif
3084 XSETINT (result->x, p.x);
3085 XSETINT (result->y, p.y);
3087 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3088 files = Qnil;
3090 for (i = 0; i < num_files; i++)
3092 len = DragQueryFile (hdrop, i, NULL, 0);
3093 if (len <= 0)
3094 continue;
3095 name = alloca (len + 1);
3096 DragQueryFile (hdrop, i, name, len + 1);
3097 files = Fcons (DECODE_FILE (build_string (name)), files);
3100 DragFinish (hdrop);
3102 XSETFRAME (frame, f);
3103 result->frame_or_window = frame;
3104 result->arg = files;
3105 return Qnil;
3109 /* Function to report a mouse movement to the mainstream Emacs code.
3110 The input handler calls this.
3112 We have received a mouse movement event, which is given in *event.
3113 If the mouse is over a different glyph than it was last time, tell
3114 the mainstream emacs code by setting mouse_moved. If not, ask for
3115 another motion event, so we can check again the next time it moves. */
3117 static MSG last_mouse_motion_event;
3118 static Lisp_Object last_mouse_motion_frame;
3120 static int
3121 note_mouse_movement (frame, msg)
3122 FRAME_PTR frame;
3123 MSG *msg;
3125 int mouse_x = LOWORD (msg->lParam);
3126 int mouse_y = HIWORD (msg->lParam);
3128 last_mouse_movement_time = msg->time;
3129 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3130 XSETFRAME (last_mouse_motion_frame, frame);
3132 if (!FRAME_X_OUTPUT (frame))
3133 return 0;
3135 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3137 frame->mouse_moved = 1;
3138 last_mouse_scroll_bar = Qnil;
3139 note_mouse_highlight (frame, -1, -1);
3140 last_mouse_glyph_frame = 0;
3141 return 1;
3144 /* Has the mouse moved off the glyph it was on at the last sighting? */
3145 if (frame != last_mouse_glyph_frame
3146 || mouse_x < last_mouse_glyph.left
3147 || mouse_x >= last_mouse_glyph.right
3148 || mouse_y < last_mouse_glyph.top
3149 || mouse_y >= last_mouse_glyph.bottom)
3151 frame->mouse_moved = 1;
3152 last_mouse_scroll_bar = Qnil;
3153 note_mouse_highlight (frame, mouse_x, mouse_y);
3154 /* Remember the mouse position here, as w32_mouse_position only
3155 gets called when mouse tracking is enabled but we also need
3156 to keep track of the mouse for help_echo and highlighting at
3157 other times. */
3158 remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
3159 last_mouse_glyph_frame = frame;
3160 return 1;
3163 return 0;
3167 /************************************************************************
3168 Mouse Face
3169 ************************************************************************/
3171 static struct scroll_bar *x_window_to_scroll_bar ();
3172 static void x_scroll_bar_report_motion ();
3173 static void x_check_fullscreen P_ ((struct frame *));
3175 static void
3176 redo_mouse_highlight ()
3178 if (!NILP (last_mouse_motion_frame)
3179 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3180 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3181 LOWORD (last_mouse_motion_event.lParam),
3182 HIWORD (last_mouse_motion_event.lParam));
3185 static void
3186 w32_define_cursor (window, cursor)
3187 Window window;
3188 Cursor cursor;
3190 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3192 /* Return the current position of the mouse.
3193 *fp should be a frame which indicates which display to ask about.
3195 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3196 and *part to the frame, window, and scroll bar part that the mouse
3197 is over. Set *x and *y to the portion and whole of the mouse's
3198 position on the scroll bar.
3200 If the mouse movement started elsewhere, set *fp to the frame the
3201 mouse is on, *bar_window to nil, and *x and *y to the character cell
3202 the mouse is over.
3204 Set *time to the server time-stamp for the time at which the mouse
3205 was at this position.
3207 Don't store anything if we don't have a valid set of values to report.
3209 This clears the mouse_moved flag, so we can wait for the next mouse
3210 movement. */
3212 static void
3213 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
3214 FRAME_PTR *fp;
3215 int insist;
3216 Lisp_Object *bar_window;
3217 enum scroll_bar_part *part;
3218 Lisp_Object *x, *y;
3219 unsigned long *time;
3221 FRAME_PTR f1;
3223 BLOCK_INPUT;
3225 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3226 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3227 else
3229 POINT pt;
3231 Lisp_Object frame, tail;
3233 /* Clear the mouse-moved flag for every frame on this display. */
3234 FOR_EACH_FRAME (tail, frame)
3235 XFRAME (frame)->mouse_moved = 0;
3237 last_mouse_scroll_bar = Qnil;
3239 GetCursorPos (&pt);
3241 /* Now we have a position on the root; find the innermost window
3242 containing the pointer. */
3244 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3245 && FRAME_LIVE_P (last_mouse_frame))
3247 /* If mouse was grabbed on a frame, give coords for that frame
3248 even if the mouse is now outside it. */
3249 f1 = last_mouse_frame;
3251 else
3253 /* Is window under mouse one of our frames? */
3254 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
3255 WindowFromPoint (pt));
3258 /* If not, is it one of our scroll bars? */
3259 if (! f1)
3261 struct scroll_bar *bar
3262 = x_window_to_scroll_bar (WindowFromPoint (pt));
3264 if (bar)
3266 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3270 if (f1 == 0 && insist > 0)
3271 f1 = SELECTED_FRAME ();
3273 if (f1)
3275 /* Ok, we found a frame. Store all the values.
3276 last_mouse_glyph is a rectangle used to reduce the
3277 generation of mouse events. To not miss any motion
3278 events, we must divide the frame into rectangles of the
3279 size of the smallest character that could be displayed
3280 on it, i.e. into the same rectangles that matrices on
3281 the frame are divided into. */
3283 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3284 remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
3285 last_mouse_glyph_frame = f1;
3287 *bar_window = Qnil;
3288 *part = 0;
3289 *fp = f1;
3290 XSETINT (*x, pt.x);
3291 XSETINT (*y, pt.y);
3292 *time = last_mouse_movement_time;
3297 UNBLOCK_INPUT;
3301 /***********************************************************************
3302 Tool-bars
3303 ***********************************************************************/
3305 /* Handle mouse button event on the tool-bar of frame F, at
3306 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3307 or ButtonRelase. */
3309 static void
3310 w32_handle_tool_bar_click (f, button_event)
3311 struct frame *f;
3312 struct input_event *button_event;
3314 int x = XFASTINT (button_event->x);
3315 int y = XFASTINT (button_event->y);
3317 if (button_event->modifiers & down_modifier)
3318 handle_tool_bar_click (f, x, y, 1, 0);
3319 else
3320 handle_tool_bar_click (f, x, y, 0,
3321 button_event->modifiers & ~up_modifier);
3326 /***********************************************************************
3327 Scroll bars
3328 ***********************************************************************/
3330 /* Scroll bar support. */
3332 /* Given a window ID, find the struct scroll_bar which manages it.
3333 This can be called in GC, so we have to make sure to strip off mark
3334 bits. */
3336 static struct scroll_bar *
3337 x_window_to_scroll_bar (window_id)
3338 Window window_id;
3340 Lisp_Object tail;
3342 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3344 Lisp_Object frame, bar, condemned;
3346 frame = XCAR (tail);
3347 /* All elements of Vframe_list should be frames. */
3348 if (! FRAMEP (frame))
3349 abort ();
3351 /* Scan this frame's scroll bar list for a scroll bar with the
3352 right window ID. */
3353 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3354 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3355 /* This trick allows us to search both the ordinary and
3356 condemned scroll bar lists with one loop. */
3357 ! NILP (bar) || (bar = condemned,
3358 condemned = Qnil,
3359 ! NILP (bar));
3360 bar = XSCROLL_BAR (bar)->next)
3361 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
3362 return XSCROLL_BAR (bar);
3365 return 0;
3370 /* Set the thumb size and position of scroll bar BAR. We are currently
3371 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3373 static void
3374 w32_set_scroll_bar_thumb (bar, portion, position, whole)
3375 struct scroll_bar *bar;
3376 int portion, position, whole;
3378 Window w = SCROLL_BAR_W32_WINDOW (bar);
3379 /* We use the whole scroll-bar height in the calculations below, to
3380 avoid strange effects like scrolling backwards when just clicking
3381 on the handle (without moving it). */
3382 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
3383 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3384 int sb_page, sb_pos;
3385 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
3386 SCROLLINFO si;
3388 /* We used to change the nPage setting while dragging the handle,
3389 but that had very strange effects (such as scrolling backwards
3390 while dragging downwards).
3392 Now, we don't change the nPage setting while dragging unless we
3393 get near to the end of the buffer, in which case we often have to
3394 resize the handle to "go all the way". */
3396 if (draggingp)
3398 int near_bottom_p;
3399 BLOCK_INPUT;
3400 si.cbSize = sizeof (si);
3401 si.fMask = SIF_POS | SIF_PAGE;
3402 GetScrollInfo(w, SB_CTL, &si);
3403 near_bottom_p = si.nPos + si.nPage >= range;
3404 UNBLOCK_INPUT;
3405 if (!near_bottom_p)
3406 return;
3409 if (whole)
3411 /* Position scroll bar at rock bottom if the bottom of the
3412 buffer is visible. This avoids shinking the thumb away
3413 to nothing if it is held at the bottom of the buffer. */
3414 if (position + portion >= whole && !draggingp)
3416 sb_page = range * (whole - position) / whole;
3417 sb_pos = range;
3419 else
3421 sb_pos = position * range / whole;
3422 sb_page = (min (portion, (whole - position)) * range) / whole;
3425 else
3427 sb_page = range;
3428 sb_pos = 0;
3431 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3433 BLOCK_INPUT;
3435 si.cbSize = sizeof (si);
3436 si.fMask = SIF_PAGE | SIF_POS;
3437 si.nPage = sb_page;
3438 si.nPos = sb_pos;
3440 SetScrollInfo (w, SB_CTL, &si, TRUE);
3442 UNBLOCK_INPUT;
3446 /************************************************************************
3447 Scroll bars, general
3448 ************************************************************************/
3450 static HWND
3451 my_create_scrollbar (f, bar)
3452 struct frame * f;
3453 struct scroll_bar * bar;
3455 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3456 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
3457 (LPARAM) bar);
3460 /*#define ATTACH_THREADS*/
3462 static BOOL
3463 my_show_window (FRAME_PTR f, HWND hwnd, int how)
3465 #ifndef ATTACH_THREADS
3466 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3467 (WPARAM) hwnd, (LPARAM) how);
3468 #else
3469 return ShowWindow (hwnd, how);
3470 #endif
3473 static void
3474 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3475 int x, int y, int cx, int cy, UINT flags)
3477 #ifndef ATTACH_THREADS
3478 WINDOWPOS pos;
3479 pos.hwndInsertAfter = hwndAfter;
3480 pos.x = x;
3481 pos.y = y;
3482 pos.cx = cx;
3483 pos.cy = cy;
3484 pos.flags = flags;
3485 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3486 #else
3487 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3488 #endif
3491 static void
3492 my_set_focus (f, hwnd)
3493 struct frame * f;
3494 HWND hwnd;
3496 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3497 (WPARAM) hwnd, 0);
3500 static void
3501 my_set_foreground_window (hwnd)
3502 HWND hwnd;
3504 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3508 static void
3509 my_destroy_window (f, hwnd)
3510 struct frame * f;
3511 HWND hwnd;
3513 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3514 (WPARAM) hwnd, 0);
3517 /* Create a scroll bar and return the scroll bar vector for it. W is
3518 the Emacs window on which to create the scroll bar. TOP, LEFT,
3519 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3520 scroll bar. */
3522 static struct scroll_bar *
3523 x_scroll_bar_create (w, top, left, width, height)
3524 struct window *w;
3525 int top, left, width, height;
3527 struct frame *f = XFRAME (WINDOW_FRAME (w));
3528 HWND hwnd;
3529 SCROLLINFO si;
3530 struct scroll_bar *bar
3531 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3533 BLOCK_INPUT;
3535 XSETWINDOW (bar->window, w);
3536 XSETINT (bar->top, top);
3537 XSETINT (bar->left, left);
3538 XSETINT (bar->width, width);
3539 XSETINT (bar->height, height);
3540 XSETINT (bar->start, 0);
3541 XSETINT (bar->end, 0);
3542 bar->dragging = Qnil;
3543 bar->fringe_extended_p = Qnil;
3545 /* Requires geometry to be set before call to create the real window */
3547 hwnd = my_create_scrollbar (f, bar);
3549 si.cbSize = sizeof (si);
3550 si.fMask = SIF_ALL;
3551 si.nMin = 0;
3552 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3553 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3554 si.nPage = si.nMax;
3555 si.nPos = 0;
3557 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3559 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3561 /* Add bar to its frame's list of scroll bars. */
3562 bar->next = FRAME_SCROLL_BARS (f);
3563 bar->prev = Qnil;
3564 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3565 if (! NILP (bar->next))
3566 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3568 UNBLOCK_INPUT;
3570 return bar;
3574 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3575 nil. */
3577 static void
3578 x_scroll_bar_remove (bar)
3579 struct scroll_bar *bar;
3581 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3583 BLOCK_INPUT;
3585 /* Destroy the window. */
3586 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3588 /* Disassociate this scroll bar from its window. */
3589 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3591 UNBLOCK_INPUT;
3594 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3595 that we are displaying PORTION characters out of a total of WHOLE
3596 characters, starting at POSITION. If WINDOW has no scroll bar,
3597 create one. */
3598 static void
3599 w32_set_vertical_scroll_bar (w, portion, whole, position)
3600 struct window *w;
3601 int portion, whole, position;
3603 struct frame *f = XFRAME (w->frame);
3604 struct scroll_bar *bar;
3605 int top, height, left, sb_left, width, sb_width;
3606 int window_y, window_height;
3607 int fringe_extended_p;
3609 /* Get window dimensions. */
3610 window_box (w, -1, 0, &window_y, 0, &window_height);
3611 top = window_y;
3612 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3613 height = window_height;
3615 /* Compute the left edge of the scroll bar area. */
3616 left = WINDOW_SCROLL_BAR_AREA_X (w);
3618 /* Compute the width of the scroll bar which might be less than
3619 the width of the area reserved for the scroll bar. */
3620 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3621 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3622 else
3623 sb_width = width;
3625 /* Compute the left edge of the scroll bar. */
3626 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3627 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
3628 else
3629 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
3631 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3632 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
3633 && WINDOW_LEFT_FRINGE_WIDTH (w)
3634 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3635 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
3636 else
3637 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
3638 && WINDOW_RIGHT_FRINGE_WIDTH (w)
3639 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3640 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
3642 /* Does the scroll bar exist yet? */
3643 if (NILP (w->vertical_scroll_bar))
3645 HDC hdc;
3646 BLOCK_INPUT;
3647 if (width > 0 && height > 0)
3649 hdc = get_frame_dc (f);
3650 if (fringe_extended_p)
3651 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3652 else
3653 w32_clear_area (f, hdc, left, top, width, height);
3654 release_frame_dc (f, hdc);
3656 UNBLOCK_INPUT;
3658 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
3660 else
3662 /* It may just need to be moved and resized. */
3663 HWND hwnd;
3665 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3666 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3668 /* If already correctly positioned, do nothing. */
3669 if ( XINT (bar->left) == sb_left
3670 && XINT (bar->top) == top
3671 && XINT (bar->width) == sb_width
3672 && XINT (bar->height) == height
3673 && !NILP (bar->fringe_extended_p) == fringe_extended_p )
3675 /* Redraw after clear_frame. */
3676 if (!my_show_window (f, hwnd, SW_NORMAL))
3677 InvalidateRect (hwnd, NULL, FALSE);
3679 else
3681 HDC hdc;
3682 SCROLLINFO si;
3684 BLOCK_INPUT;
3685 if (width && height)
3687 hdc = get_frame_dc (f);
3688 /* Since Windows scroll bars are smaller than the space reserved
3689 for them on the frame, we have to clear "under" them. */
3690 if (fringe_extended_p)
3691 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3692 else
3693 w32_clear_area (f, hdc, left, top, width, height);
3694 release_frame_dc (f, hdc);
3696 /* Make sure scroll bar is "visible" before moving, to ensure the
3697 area of the parent window now exposed will be refreshed. */
3698 my_show_window (f, hwnd, SW_HIDE);
3699 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3700 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3701 max (height, 1), TRUE);
3703 si.cbSize = sizeof (si);
3704 si.fMask = SIF_RANGE;
3705 si.nMin = 0;
3706 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3707 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3709 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3711 my_show_window (f, hwnd, SW_NORMAL);
3712 /* InvalidateRect (w, NULL, FALSE); */
3714 /* Remember new settings. */
3715 XSETINT (bar->left, sb_left);
3716 XSETINT (bar->top, top);
3717 XSETINT (bar->width, sb_width);
3718 XSETINT (bar->height, height);
3720 UNBLOCK_INPUT;
3723 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
3725 w32_set_scroll_bar_thumb (bar, portion, position, whole);
3727 XSETVECTOR (w->vertical_scroll_bar, bar);
3731 /* The following three hooks are used when we're doing a thorough
3732 redisplay of the frame. We don't explicitly know which scroll bars
3733 are going to be deleted, because keeping track of when windows go
3734 away is a real pain - "Can you say set-window-configuration, boys
3735 and girls?" Instead, we just assert at the beginning of redisplay
3736 that *all* scroll bars are to be removed, and then save a scroll bar
3737 from the fiery pit when we actually redisplay its window. */
3739 /* Arrange for all scroll bars on FRAME to be removed at the next call
3740 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3741 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3743 static void
3744 w32_condemn_scroll_bars (frame)
3745 FRAME_PTR frame;
3747 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3748 while (! NILP (FRAME_SCROLL_BARS (frame)))
3750 Lisp_Object bar;
3751 bar = FRAME_SCROLL_BARS (frame);
3752 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
3753 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3754 XSCROLL_BAR (bar)->prev = Qnil;
3755 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3756 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
3757 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
3762 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3763 Note that WINDOW isn't necessarily condemned at all. */
3765 static void
3766 w32_redeem_scroll_bar (window)
3767 struct window *window;
3769 struct scroll_bar *bar;
3770 struct frame *f;
3772 /* We can't redeem this window's scroll bar if it doesn't have one. */
3773 if (NILP (window->vertical_scroll_bar))
3774 abort ();
3776 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3778 /* Unlink it from the condemned list. */
3779 f = XFRAME (WINDOW_FRAME (window));
3780 if (NILP (bar->prev))
3782 /* If the prev pointer is nil, it must be the first in one of
3783 the lists. */
3784 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3785 /* It's not condemned. Everything's fine. */
3786 return;
3787 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3788 window->vertical_scroll_bar))
3789 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3790 else
3791 /* If its prev pointer is nil, it must be at the front of
3792 one or the other! */
3793 abort ();
3795 else
3796 XSCROLL_BAR (bar->prev)->next = bar->next;
3798 if (! NILP (bar->next))
3799 XSCROLL_BAR (bar->next)->prev = bar->prev;
3801 bar->next = FRAME_SCROLL_BARS (f);
3802 bar->prev = Qnil;
3803 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3804 if (! NILP (bar->next))
3805 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3808 /* Remove all scroll bars on FRAME that haven't been saved since the
3809 last call to `*condemn_scroll_bars_hook'. */
3811 static void
3812 w32_judge_scroll_bars (f)
3813 FRAME_PTR f;
3815 Lisp_Object bar, next;
3817 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3819 /* Clear out the condemned list now so we won't try to process any
3820 more events on the hapless scroll bars. */
3821 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3823 for (; ! NILP (bar); bar = next)
3825 struct scroll_bar *b = XSCROLL_BAR (bar);
3827 x_scroll_bar_remove (b);
3829 next = b->next;
3830 b->next = b->prev = Qnil;
3833 /* Now there should be no references to the condemned scroll bars,
3834 and they should get garbage-collected. */
3837 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3838 is set to something other than NO_EVENT, it is enqueued.
3840 This may be called from a signal handler, so we have to ignore GC
3841 mark bits. */
3843 static int
3844 w32_scroll_bar_handle_click (bar, msg, emacs_event)
3845 struct scroll_bar *bar;
3846 W32Msg *msg;
3847 struct input_event *emacs_event;
3849 if (! WINDOWP (bar->window))
3850 abort ();
3852 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
3853 emacs_event->code = 0;
3854 /* not really meaningful to distinguish up/down */
3855 emacs_event->modifiers = msg->dwModifiers;
3856 emacs_event->frame_or_window = bar->window;
3857 emacs_event->arg = Qnil;
3858 emacs_event->timestamp = msg->msg.time;
3861 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3862 int y;
3863 int dragging = !NILP (bar->dragging);
3864 SCROLLINFO si;
3866 si.cbSize = sizeof (si);
3867 si.fMask = SIF_POS;
3869 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
3870 y = si.nPos;
3872 bar->dragging = Qnil;
3875 last_mouse_scroll_bar_pos = msg->msg.wParam;
3877 switch (LOWORD (msg->msg.wParam))
3879 case SB_LINEDOWN:
3880 emacs_event->part = scroll_bar_down_arrow;
3881 break;
3882 case SB_LINEUP:
3883 emacs_event->part = scroll_bar_up_arrow;
3884 break;
3885 case SB_PAGEUP:
3886 emacs_event->part = scroll_bar_above_handle;
3887 break;
3888 case SB_PAGEDOWN:
3889 emacs_event->part = scroll_bar_below_handle;
3890 break;
3891 case SB_TOP:
3892 emacs_event->part = scroll_bar_handle;
3893 y = 0;
3894 break;
3895 case SB_BOTTOM:
3896 emacs_event->part = scroll_bar_handle;
3897 y = top_range;
3898 break;
3899 case SB_THUMBTRACK:
3900 case SB_THUMBPOSITION:
3901 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3902 y = HIWORD (msg->msg.wParam);
3903 bar->dragging = Qt;
3904 emacs_event->part = scroll_bar_handle;
3906 /* "Silently" update current position. */
3908 SCROLLINFO si;
3910 si.cbSize = sizeof (si);
3911 si.fMask = SIF_POS;
3912 si.nPos = y;
3913 /* Remember apparent position (we actually lag behind the real
3914 position, so don't set that directly. */
3915 last_scroll_bar_drag_pos = y;
3917 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
3919 break;
3920 case SB_ENDSCROLL:
3921 /* If this is the end of a drag sequence, then reset the scroll
3922 handle size to normal and do a final redraw. Otherwise do
3923 nothing. */
3924 if (dragging)
3926 SCROLLINFO si;
3927 int start = XINT (bar->start);
3928 int end = XINT (bar->end);
3930 si.cbSize = sizeof (si);
3931 si.fMask = SIF_PAGE | SIF_POS;
3932 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3933 si.nPos = last_scroll_bar_drag_pos;
3934 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
3936 /* fall through */
3937 default:
3938 emacs_event->kind = NO_EVENT;
3939 return FALSE;
3942 XSETINT (emacs_event->x, y);
3943 XSETINT (emacs_event->y, top_range);
3945 return TRUE;
3949 /* Return information to the user about the current position of the mouse
3950 on the scroll bar. */
3952 static void
3953 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3954 FRAME_PTR *fp;
3955 Lisp_Object *bar_window;
3956 enum scroll_bar_part *part;
3957 Lisp_Object *x, *y;
3958 unsigned long *time;
3960 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3961 Window w = SCROLL_BAR_W32_WINDOW (bar);
3962 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3963 int pos;
3964 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3965 SCROLLINFO si;
3967 BLOCK_INPUT;
3969 *fp = f;
3970 *bar_window = bar->window;
3972 si.cbSize = sizeof (si);
3973 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
3975 GetScrollInfo (w, SB_CTL, &si);
3976 pos = si.nPos;
3977 top_range = si.nMax - si.nPage + 1;
3979 switch (LOWORD (last_mouse_scroll_bar_pos))
3981 case SB_THUMBPOSITION:
3982 case SB_THUMBTRACK:
3983 *part = scroll_bar_handle;
3984 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3985 pos = HIWORD (last_mouse_scroll_bar_pos);
3986 break;
3987 case SB_LINEDOWN:
3988 *part = scroll_bar_handle;
3989 pos++;
3990 break;
3991 default:
3992 *part = scroll_bar_handle;
3993 break;
3996 XSETINT (*x, pos);
3997 XSETINT (*y, top_range);
3999 f->mouse_moved = 0;
4000 last_mouse_scroll_bar = Qnil;
4002 *time = last_mouse_movement_time;
4004 UNBLOCK_INPUT;
4008 /* The screen has been cleared so we may have changed foreground or
4009 background colors, and the scroll bars may need to be redrawn.
4010 Clear out the scroll bars, and ask for expose events, so we can
4011 redraw them. */
4013 void
4014 x_scroll_bar_clear (f)
4015 FRAME_PTR f;
4017 Lisp_Object bar;
4019 /* We can have scroll bars even if this is 0,
4020 if we just turned off scroll bar mode.
4021 But in that case we should not clear them. */
4022 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4023 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4024 bar = XSCROLL_BAR (bar)->next)
4026 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4027 HDC hdc = GetDC (window);
4028 RECT rect;
4030 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4031 arranges to refresh the scroll bar if hidden. */
4032 my_show_window (f, window, SW_HIDE);
4034 GetClientRect (window, &rect);
4035 select_palette (f, hdc);
4036 w32_clear_rect (f, hdc, &rect);
4037 deselect_palette (f, hdc);
4039 ReleaseDC (window, hdc);
4044 /* The main W32 event-reading loop - w32_read_socket. */
4046 /* Record the last 100 characters stored
4047 to help debug the loss-of-chars-during-GC problem. */
4049 static int temp_index;
4050 static short temp_buffer[100];
4052 /* Temporarily store lead byte of DBCS input sequences. */
4053 static char dbcs_lead = 0;
4055 /* Read events coming from the W32 shell.
4056 This routine is called by the SIGIO handler.
4057 We return as soon as there are no more events to be read.
4059 We return the number of characters stored into the buffer,
4060 thus pretending to be `read'.
4062 EXPECTED is nonzero if the caller knows input is available.
4064 Some of these messages are reposted back to the message queue since the
4065 system calls the windows proc directly in a context where we cannot return
4066 the data nor can we guarantee the state we are in. So if we dispatch them
4067 we will get into an infinite loop. To prevent this from ever happening we
4068 will set a variable to indicate we are in the read_socket call and indicate
4069 which message we are processing since the windows proc gets called
4070 recursively with different messages by the system.
4074 w32_read_socket (sd, expected, hold_quit)
4075 register int sd;
4076 int expected;
4077 struct input_event *hold_quit;
4079 int count = 0;
4080 int check_visibility = 0;
4081 W32Msg msg;
4082 struct frame *f;
4083 struct w32_display_info *dpyinfo = &one_w32_display_info;
4085 if (interrupt_input_blocked)
4087 interrupt_input_pending = 1;
4088 return -1;
4091 interrupt_input_pending = 0;
4092 BLOCK_INPUT;
4094 /* So people can tell when we have read the available input. */
4095 input_signal_count++;
4097 /* TODO: ghostscript integration. */
4098 while (get_next_msg (&msg, FALSE))
4100 struct input_event inev;
4101 int do_help = 0;
4103 EVENT_INIT (inev);
4104 inev.kind = NO_EVENT;
4105 inev.arg = Qnil;
4107 switch (msg.msg.message)
4109 case WM_EMACS_PAINT:
4110 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4112 if (f)
4114 if (msg.rect.right == msg.rect.left ||
4115 msg.rect.bottom == msg.rect.top)
4117 /* We may get paint messages even though the client
4118 area is clipped - these are not expose events. */
4119 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4120 SDATA (f->name)));
4122 else if (f->async_visible != 1)
4124 /* Definitely not obscured, so mark as visible. */
4125 f->async_visible = 1;
4126 f->async_iconified = 0;
4127 SET_FRAME_GARBAGED (f);
4128 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4129 SDATA (f->name)));
4131 /* WM_PAINT serves as MapNotify as well, so report
4132 visibility changes properly. */
4133 if (f->iconified)
4135 inev.kind = DEICONIFY_EVENT;
4136 XSETFRAME (inev.frame_or_window, f);
4138 else if (! NILP (Vframe_list)
4139 && ! NILP (XCDR (Vframe_list)))
4140 /* Force a redisplay sooner or later to update the
4141 frame titles in case this is the second frame. */
4142 record_asynch_buffer_change ();
4144 else
4146 HDC hdc = get_frame_dc (f);
4148 /* Erase background again for safety. */
4149 w32_clear_rect (f, hdc, &msg.rect);
4150 release_frame_dc (f, hdc);
4151 expose_frame (f,
4152 msg.rect.left,
4153 msg.rect.top,
4154 msg.rect.right - msg.rect.left,
4155 msg.rect.bottom - msg.rect.top);
4158 break;
4160 case WM_INPUTLANGCHANGE:
4161 /* Generate a language change event. */
4162 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4164 /* lParam contains the input lang ID. Use it to update our
4165 record of the keyboard codepage. */
4166 keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4167 & 0xffff));
4169 if (f)
4171 inev.kind = LANGUAGE_CHANGE_EVENT;
4172 XSETFRAME (inev.frame_or_window, f);
4173 inev.code = msg.msg.wParam;
4174 inev.modifiers = msg.msg.lParam & 0xffff;
4176 break;
4178 case WM_KEYDOWN:
4179 case WM_SYSKEYDOWN:
4180 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4182 if (f && !f->iconified)
4184 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4185 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4187 clear_mouse_face (dpyinfo);
4188 dpyinfo->mouse_face_hidden = 1;
4191 if (temp_index == sizeof temp_buffer / sizeof (short))
4192 temp_index = 0;
4193 temp_buffer[temp_index++] = msg.msg.wParam;
4194 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4195 inev.code = msg.msg.wParam;
4196 inev.modifiers = msg.dwModifiers;
4197 XSETFRAME (inev.frame_or_window, f);
4198 inev.timestamp = msg.msg.time;
4200 break;
4202 case WM_UNICHAR:
4203 case WM_SYSCHAR:
4204 case WM_CHAR:
4205 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4207 if (f && !f->iconified)
4209 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4210 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4212 clear_mouse_face (dpyinfo);
4213 dpyinfo->mouse_face_hidden = 1;
4216 if (temp_index == sizeof temp_buffer / sizeof (short))
4217 temp_index = 0;
4218 temp_buffer[temp_index++] = msg.msg.wParam;
4220 inev.modifiers = msg.dwModifiers;
4221 XSETFRAME (inev.frame_or_window, f);
4222 inev.timestamp = msg.msg.time;
4224 if (msg.msg.message == WM_UNICHAR)
4226 inev.code = msg.msg.wParam;
4228 else if (msg.msg.wParam < 256)
4230 wchar_t code;
4231 char dbcs[2];
4232 dbcs[0] = 0;
4233 dbcs[1] = (char) msg.msg.wParam;
4235 if (dbcs_lead)
4237 dbcs[0] = dbcs_lead;
4238 dbcs_lead = 0;
4239 if (!MultiByteToWideChar (keyboard_codepage, 0,
4240 dbcs, 2, &code, 1))
4242 /* Garbage */
4243 DebPrint (("Invalid DBCS sequence: %d %d\n",
4244 dbcs[0], dbcs[1]));
4245 inev.kind = NO_EVENT;
4246 break;
4249 else if (IsDBCSLeadByteEx (keyboard_codepage,
4250 (BYTE) msg.msg.wParam))
4252 dbcs_lead = (char) msg.msg.wParam;
4253 inev.kind = NO_EVENT;
4254 break;
4256 else
4258 if (!MultiByteToWideChar (keyboard_codepage, 0,
4259 &dbcs[1], 1, &code, 1))
4261 /* What to do with garbage? */
4262 DebPrint (("Invalid character: %d\n", dbcs[1]));
4263 inev.kind = NO_EVENT;
4264 break;
4267 inev.code = code;
4269 else
4271 /* Windows shouldn't generate WM_CHAR events above 0xFF
4272 in non-Unicode message handlers. */
4273 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4274 inev.kind = NO_EVENT;
4275 break;
4277 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4278 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
4280 break;
4282 case WM_APPCOMMAND:
4283 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4285 if (f && !f->iconified)
4287 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4288 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4290 clear_mouse_face (dpyinfo);
4291 dpyinfo->mouse_face_hidden = 1;
4294 if (temp_index == sizeof temp_buffer / sizeof (short))
4295 temp_index = 0;
4296 temp_buffer[temp_index++] = msg.msg.wParam;
4297 inev.kind = MULTIMEDIA_KEY_EVENT;
4298 inev.code = GET_APPCOMMAND_LPARAM(msg.msg.lParam);
4299 inev.modifiers = msg.dwModifiers;
4300 XSETFRAME (inev.frame_or_window, f);
4301 inev.timestamp = msg.msg.time;
4303 break;
4305 case WM_MOUSEMOVE:
4306 /* Ignore non-movement. */
4308 int x = LOWORD (msg.msg.lParam);
4309 int y = HIWORD (msg.msg.lParam);
4310 if (x == last_mousemove_x && y == last_mousemove_y)
4311 break;
4312 last_mousemove_x = x;
4313 last_mousemove_y = y;
4316 previous_help_echo_string = help_echo_string;
4317 help_echo_string = Qnil;
4319 if (dpyinfo->grabbed && last_mouse_frame
4320 && FRAME_LIVE_P (last_mouse_frame))
4321 f = last_mouse_frame;
4322 else
4323 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4325 if (dpyinfo->mouse_face_hidden)
4327 dpyinfo->mouse_face_hidden = 0;
4328 clear_mouse_face (dpyinfo);
4331 if (f)
4333 /* Generate SELECT_WINDOW_EVENTs when needed. */
4334 if (!NILP (Vmouse_autoselect_window))
4336 Lisp_Object window;
4337 int x = LOWORD (msg.msg.lParam);
4338 int y = HIWORD (msg.msg.lParam);
4340 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
4342 /* Window will be selected only when it is not
4343 selected now and last mouse movement event was
4344 not in it. Minibuffer window will be selected
4345 only when it is active. */
4346 if (WINDOWP(window)
4347 && !EQ (window, last_window)
4348 && !EQ (window, selected_window)
4349 /* For click-to-focus window managers
4350 create event iff we don't leave the
4351 selected frame. */
4352 && (focus_follows_mouse
4353 || (EQ (XWINDOW (window)->frame,
4354 XWINDOW (selected_window)->frame))))
4356 inev.kind = SELECT_WINDOW_EVENT;
4357 inev.frame_or_window = window;
4360 last_window=window;
4362 if (!note_mouse_movement (f, &msg.msg))
4363 help_echo_string = previous_help_echo_string;
4365 else
4367 /* If we move outside the frame, then we're
4368 certainly no longer on any text in the frame. */
4369 clear_mouse_face (dpyinfo);
4372 /* If the contents of the global variable help_echo_string
4373 has changed, generate a HELP_EVENT. */
4374 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4375 But it was originally changed to this to fix a bug, so I have
4376 not removed it completely in case the bug is still there. */
4377 if (help_echo_string != previous_help_echo_string ||
4378 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4379 #else /* This is what xterm.c does. */
4380 if (!NILP (help_echo_string)
4381 || !NILP (previous_help_echo_string))
4382 do_help = 1;
4383 #endif
4384 break;
4386 case WM_LBUTTONDOWN:
4387 case WM_LBUTTONUP:
4388 case WM_MBUTTONDOWN:
4389 case WM_MBUTTONUP:
4390 case WM_RBUTTONDOWN:
4391 case WM_RBUTTONUP:
4392 case WM_XBUTTONDOWN:
4393 case WM_XBUTTONUP:
4395 /* If we decide we want to generate an event to be seen
4396 by the rest of Emacs, we put it here. */
4397 int tool_bar_p = 0;
4398 int button;
4399 int up;
4401 if (dpyinfo->grabbed && last_mouse_frame
4402 && FRAME_LIVE_P (last_mouse_frame))
4403 f = last_mouse_frame;
4404 else
4405 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4407 if (f)
4409 construct_mouse_click (&inev, &msg, f);
4411 /* Is this in the tool-bar? */
4412 if (WINDOWP (f->tool_bar_window)
4413 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
4415 Lisp_Object window;
4416 int x = XFASTINT (inev.x);
4417 int y = XFASTINT (inev.y);
4419 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
4421 if (EQ (window, f->tool_bar_window))
4423 w32_handle_tool_bar_click (f, &inev);
4424 tool_bar_p = 1;
4428 if (tool_bar_p
4429 || (dpyinfo->w32_focus_frame
4430 && f != dpyinfo->w32_focus_frame))
4431 inev.kind = NO_EVENT;
4434 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4435 &button, &up);
4437 if (up)
4439 dpyinfo->grabbed &= ~ (1 << button);
4441 else
4443 dpyinfo->grabbed |= (1 << button);
4444 last_mouse_frame = f;
4445 /* Ignore any mouse motion that happened
4446 before this event; any subsequent mouse-movement
4447 Emacs events should reflect only motion after
4448 the ButtonPress. */
4449 if (f != 0)
4450 f->mouse_moved = 0;
4452 if (!tool_bar_p)
4453 last_tool_bar_item = -1;
4455 break;
4458 case WM_MOUSEWHEEL:
4459 case WM_MOUSEHWHEEL:
4461 if (dpyinfo->grabbed && last_mouse_frame
4462 && FRAME_LIVE_P (last_mouse_frame))
4463 f = last_mouse_frame;
4464 else
4465 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4467 if (f)
4470 if (!dpyinfo->w32_focus_frame
4471 || f == dpyinfo->w32_focus_frame)
4473 /* Emit an Emacs wheel-up/down event. */
4474 construct_mouse_wheel (&inev, &msg, f);
4476 /* Ignore any mouse motion that happened before this
4477 event; any subsequent mouse-movement Emacs events
4478 should reflect only motion after the
4479 ButtonPress. */
4480 f->mouse_moved = 0;
4482 last_mouse_frame = f;
4483 last_tool_bar_item = -1;
4485 break;
4487 case WM_DROPFILES:
4488 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4490 if (f)
4491 construct_drag_n_drop (&inev, &msg, f);
4492 break;
4494 case WM_VSCROLL:
4496 struct scroll_bar *bar =
4497 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
4499 if (bar)
4500 w32_scroll_bar_handle_click (bar, &msg, &inev);
4501 break;
4504 case WM_WINDOWPOSCHANGED:
4505 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4506 if (f)
4508 if (f->want_fullscreen & FULLSCREEN_WAIT)
4509 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
4511 check_visibility = 1;
4512 break;
4514 case WM_ACTIVATE:
4515 case WM_ACTIVATEAPP:
4516 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4517 if (f)
4518 x_check_fullscreen (f);
4519 check_visibility = 1;
4520 break;
4522 case WM_MOVE:
4523 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4525 if (f && !f->async_iconified)
4527 int x, y;
4529 x_real_positions (f, &x, &y);
4530 f->left_pos = x;
4531 f->top_pos = y;
4534 check_visibility = 1;
4535 break;
4537 case WM_SHOWWINDOW:
4538 /* wParam non-zero means Window is about to be shown, 0 means
4539 about to be hidden. */
4540 /* Redo the mouse-highlight after the tooltip has gone. */
4541 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4543 tip_window = NULL;
4544 redo_mouse_highlight ();
4547 /* If window has been obscured or exposed by another window
4548 being maximised or minimised/restored, then recheck
4549 visibility of all frames. Direct changes to our own
4550 windows get handled by WM_SIZE. */
4551 #if 0
4552 if (msg.msg.lParam != 0)
4553 check_visibility = 1;
4554 else
4556 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4557 f->async_visible = msg.msg.wParam;
4559 #endif
4561 check_visibility = 1;
4562 break;
4564 case WM_SIZE:
4565 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4567 /* Inform lisp of whether frame has been iconified etc. */
4568 if (f)
4570 switch (msg.msg.wParam)
4572 case SIZE_MINIMIZED:
4573 f->async_visible = 0;
4574 f->async_iconified = 1;
4576 inev.kind = ICONIFY_EVENT;
4577 XSETFRAME (inev.frame_or_window, f);
4578 break;
4580 case SIZE_MAXIMIZED:
4581 case SIZE_RESTORED:
4582 f->async_visible = 1;
4583 f->async_iconified = 0;
4585 /* wait_reading_process_output will notice this and update
4586 the frame's display structures. */
4587 SET_FRAME_GARBAGED (f);
4589 if (f->iconified)
4591 int x, y;
4593 /* Reset top and left positions of the Window
4594 here since Windows sends a WM_MOVE message
4595 BEFORE telling us the Window is minimized
4596 when the Window is iconified, with 3000,3000
4597 as the co-ords. */
4598 x_real_positions (f, &x, &y);
4599 f->left_pos = x;
4600 f->top_pos = y;
4602 inev.kind = DEICONIFY_EVENT;
4603 XSETFRAME (inev.frame_or_window, f);
4605 else if (! NILP (Vframe_list)
4606 && ! NILP (XCDR (Vframe_list)))
4607 /* Force a redisplay sooner or later
4608 to update the frame titles
4609 in case this is the second frame. */
4610 record_asynch_buffer_change ();
4611 break;
4615 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
4617 RECT rect;
4618 int rows;
4619 int columns;
4620 int width;
4621 int height;
4623 GetClientRect (msg.msg.hwnd, &rect);
4625 height = rect.bottom - rect.top;
4626 width = rect.right - rect.left;
4628 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4629 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
4631 /* TODO: Clip size to the screen dimensions. */
4633 /* Even if the number of character rows and columns has
4634 not changed, the font size may have changed, so we need
4635 to check the pixel dimensions as well. */
4637 if (columns != FRAME_COLS (f)
4638 || rows != FRAME_LINES (f)
4639 || width != FRAME_PIXEL_WIDTH (f)
4640 || height != FRAME_PIXEL_HEIGHT (f))
4642 change_frame_size (f, rows, columns, 0, 1, 0);
4643 SET_FRAME_GARBAGED (f);
4644 cancel_mouse_face (f);
4645 FRAME_PIXEL_WIDTH (f) = width;
4646 FRAME_PIXEL_HEIGHT (f) = height;
4647 f->win_gravity = NorthWestGravity;
4651 check_visibility = 1;
4652 break;
4654 case WM_MOUSELEAVE:
4655 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4656 if (f)
4658 if (f == dpyinfo->mouse_face_mouse_frame)
4660 /* If we move outside the frame, then we're
4661 certainly no longer on any text in the frame. */
4662 clear_mouse_face (dpyinfo);
4663 dpyinfo->mouse_face_mouse_frame = 0;
4666 /* Generate a nil HELP_EVENT to cancel a help-echo.
4667 Do it only if there's something to cancel.
4668 Otherwise, the startup message is cleared when
4669 the mouse leaves the frame. */
4670 if (any_help_event_p)
4671 do_help = -1;
4673 break;
4675 case WM_SETFOCUS:
4676 w32_detect_focus_change (dpyinfo, &msg, &inev);
4678 dpyinfo->grabbed = 0;
4679 check_visibility = 1;
4680 break;
4682 case WM_KILLFOCUS:
4683 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
4685 if (f)
4687 if (f == dpyinfo->w32_focus_event_frame)
4688 dpyinfo->w32_focus_event_frame = 0;
4690 if (f == dpyinfo->w32_focus_frame)
4691 x_new_focus_frame (dpyinfo, 0);
4693 if (f == dpyinfo->mouse_face_mouse_frame)
4695 /* If we move outside the frame, then we're
4696 certainly no longer on any text in the frame. */
4697 clear_mouse_face (dpyinfo);
4698 dpyinfo->mouse_face_mouse_frame = 0;
4701 /* Generate a nil HELP_EVENT to cancel a help-echo.
4702 Do it only if there's something to cancel.
4703 Otherwise, the startup message is cleared when
4704 the mouse leaves the frame. */
4705 if (any_help_event_p)
4706 do_help = -1;
4709 dpyinfo->grabbed = 0;
4710 check_visibility = 1;
4711 break;
4713 case WM_CLOSE:
4714 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4716 if (f)
4718 inev.kind = DELETE_WINDOW_EVENT;
4719 XSETFRAME (inev.frame_or_window, f);
4721 break;
4723 case WM_INITMENU:
4724 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4726 if (f)
4728 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4729 XSETFRAME (inev.frame_or_window, f);
4731 break;
4733 case WM_COMMAND:
4734 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4736 if (f)
4738 extern void menubar_selection_callback
4739 (FRAME_PTR f, void * client_data);
4740 menubar_selection_callback (f, (void *)msg.msg.wParam);
4743 check_visibility = 1;
4744 break;
4746 case WM_DISPLAYCHANGE:
4747 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4749 if (f)
4751 dpyinfo->n_cbits = msg.msg.wParam;
4752 DebPrint (("display change: %d %d\n",
4753 (short) LOWORD (msg.msg.lParam),
4754 (short) HIWORD (msg.msg.lParam)));
4757 check_visibility = 1;
4758 break;
4760 default:
4761 /* Check for messages registered at runtime. */
4762 if (msg.msg.message == msh_mousewheel)
4764 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4765 msg.msg.message = WM_MOUSEWHEEL;
4766 prepend_msg (&msg);
4768 break;
4771 if (inev.kind != NO_EVENT)
4773 kbd_buffer_store_event_hold (&inev, hold_quit);
4774 count++;
4777 if (do_help
4778 && !(hold_quit && hold_quit->kind != NO_EVENT))
4780 Lisp_Object frame;
4782 if (f)
4783 XSETFRAME (frame, f);
4784 else
4785 frame = Qnil;
4787 if (do_help > 0)
4789 if (NILP (help_echo_string))
4791 help_echo_object = help_echo_window = Qnil;
4792 help_echo_pos = -1;
4795 any_help_event_p = 1;
4796 gen_help_event (help_echo_string, frame, help_echo_window,
4797 help_echo_object, help_echo_pos);
4799 else
4801 help_echo_string = Qnil;
4802 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4804 count++;
4808 /* If the focus was just given to an autoraising frame,
4809 raise it now. */
4810 /* ??? This ought to be able to handle more than one such frame. */
4811 if (pending_autoraise_frame)
4813 x_raise_frame (pending_autoraise_frame);
4814 pending_autoraise_frame = 0;
4817 /* Check which frames are still visisble, if we have enqueued any user
4818 events or been notified of events that may affect visibility. We
4819 do this here because there doesn't seem to be any direct
4820 notification from Windows that the visibility of a window has
4821 changed (at least, not in all cases). */
4822 if (count > 0 || check_visibility)
4824 Lisp_Object tail, frame;
4826 FOR_EACH_FRAME (tail, frame)
4828 FRAME_PTR f = XFRAME (frame);
4829 /* The tooltip has been drawn already. Avoid the
4830 SET_FRAME_GARBAGED below. */
4831 if (EQ (frame, tip_frame))
4832 continue;
4834 /* Check "visible" frames and mark each as obscured or not.
4835 Note that async_visible is nonzero for unobscured and
4836 obscured frames, but zero for hidden and iconified frames. */
4837 if (FRAME_W32_P (f) && f->async_visible)
4839 RECT clipbox;
4840 HDC hdc;
4842 enter_crit ();
4843 /* Query clipping rectangle for the entire window area
4844 (GetWindowDC), not just the client portion (GetDC).
4845 Otherwise, the scrollbars and menubar aren't counted as
4846 part of the visible area of the frame, and we may think
4847 the frame is obscured when really a scrollbar is still
4848 visible and gets WM_PAINT messages above. */
4849 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
4850 GetClipBox (hdc, &clipbox);
4851 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
4852 leave_crit ();
4854 if (clipbox.right == clipbox.left
4855 || clipbox.bottom == clipbox.top)
4857 /* Frame has become completely obscured so mark as
4858 such (we do this by setting async_visible to 2 so
4859 that FRAME_VISIBLE_P is still true, but redisplay
4860 will skip it). */
4861 f->async_visible = 2;
4863 if (!FRAME_OBSCURED_P (f))
4865 DebPrint (("frame %p (%s) obscured\n", f,
4866 SDATA (f->name)));
4869 else
4871 /* Frame is not obscured, so mark it as such. */
4872 f->async_visible = 1;
4874 if (FRAME_OBSCURED_P (f))
4876 SET_FRAME_GARBAGED (f);
4877 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
4878 SDATA (f->name)));
4880 /* Force a redisplay sooner or later. */
4881 record_asynch_buffer_change ();
4888 UNBLOCK_INPUT;
4889 return count;
4894 /***********************************************************************
4895 Text Cursor
4896 ***********************************************************************/
4898 /* Set clipping for output in glyph row ROW. W is the window in which
4899 we operate. GC is the graphics context to set clipping in.
4901 ROW may be a text row or, e.g., a mode line. Text rows must be
4902 clipped to the interior of the window dedicated to text display,
4903 mode lines must be clipped to the whole window. */
4905 static void
4906 w32_clip_to_row (w, row, area, hdc)
4907 struct window *w;
4908 struct glyph_row *row;
4909 int area;
4910 HDC hdc;
4912 struct frame *f = XFRAME (WINDOW_FRAME (w));
4913 RECT clip_rect;
4914 int window_x, window_y, window_width;
4916 window_box (w, area, &window_x, &window_y, &window_width, 0);
4918 clip_rect.left = window_x;
4919 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4920 clip_rect.top = max (clip_rect.top, window_y);
4921 clip_rect.right = clip_rect.left + window_width;
4922 clip_rect.bottom = clip_rect.top + row->visible_height;
4924 w32_set_clip_rectangle (hdc, &clip_rect);
4928 /* Draw a hollow box cursor on window W in glyph row ROW. */
4930 static void
4931 x_draw_hollow_cursor (w, row)
4932 struct window *w;
4933 struct glyph_row *row;
4935 struct frame *f = XFRAME (WINDOW_FRAME (w));
4936 HDC hdc;
4937 RECT rect;
4938 int left, top, h;
4939 struct glyph *cursor_glyph;
4940 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
4942 /* Get the glyph the cursor is on. If we can't tell because
4943 the current matrix is invalid or such, give up. */
4944 cursor_glyph = get_phys_cursor_glyph (w);
4945 if (cursor_glyph == NULL)
4946 return;
4948 /* Compute frame-relative coordinates for phys cursor. */
4949 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
4950 rect.left = left;
4951 rect.top = top;
4952 rect.bottom = rect.top + h;
4953 rect.right = rect.left + w->phys_cursor_width;
4955 hdc = get_frame_dc (f);
4956 /* Set clipping, draw the rectangle, and reset clipping again. */
4957 w32_clip_to_row (w, row, TEXT_AREA, hdc);
4958 FrameRect (hdc, &rect, hb);
4959 DeleteObject (hb);
4960 w32_set_clip_rectangle (hdc, NULL);
4961 release_frame_dc (f, hdc);
4965 /* Draw a bar cursor on window W in glyph row ROW.
4967 Implementation note: One would like to draw a bar cursor with an
4968 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4969 Unfortunately, I didn't find a font yet that has this property set.
4970 --gerd. */
4972 static void
4973 x_draw_bar_cursor (w, row, width, kind)
4974 struct window *w;
4975 struct glyph_row *row;
4976 int width;
4977 enum text_cursor_kinds kind;
4979 struct frame *f = XFRAME (w->frame);
4980 struct glyph *cursor_glyph;
4982 /* If cursor is out of bounds, don't draw garbage. This can happen
4983 in mini-buffer windows when switching between echo area glyphs
4984 and mini-buffer. */
4985 cursor_glyph = get_phys_cursor_glyph (w);
4986 if (cursor_glyph == NULL)
4987 return;
4989 /* If on an image, draw like a normal cursor. That's usually better
4990 visible than drawing a bar, esp. if the image is large so that
4991 the bar might not be in the window. */
4992 if (cursor_glyph->type == IMAGE_GLYPH)
4994 struct glyph_row *row;
4995 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4996 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4998 else
5000 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5001 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5002 int x;
5003 HDC hdc;
5005 /* If the glyph's background equals the color we normally draw
5006 the bar cursor in, the bar cursor in its normal color is
5007 invisible. Use the glyph's foreground color instead in this
5008 case, on the assumption that the glyph's colors are chosen so
5009 that the glyph is legible. */
5010 if (face->background == cursor_color)
5011 cursor_color = face->foreground;
5013 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5015 hdc = get_frame_dc (f);
5016 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5018 if (kind == BAR_CURSOR)
5020 if (width < 0)
5021 width = FRAME_CURSOR_WIDTH (f);
5022 width = min (cursor_glyph->pixel_width, width);
5024 w->phys_cursor_width = width;
5026 w32_fill_area (f, hdc, cursor_color, x,
5027 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5028 width, row->height);
5030 else
5032 int dummy_x, dummy_y, dummy_h;
5034 if (width < 0)
5035 width = row->height;
5037 width = min (row->height, width);
5039 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5040 &dummy_y, &dummy_h);
5041 w32_fill_area (f, hdc, cursor_color, x,
5042 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5043 row->height - width),
5044 w->phys_cursor_width, width);
5047 w32_set_clip_rectangle (hdc, NULL);
5048 release_frame_dc (f, hdc);
5053 /* RIF: Define cursor CURSOR on frame F. */
5055 static void
5056 w32_define_frame_cursor (f, cursor)
5057 struct frame *f;
5058 Cursor cursor;
5060 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5064 /* RIF: Clear area on frame F. */
5066 static void
5067 w32_clear_frame_area (f, x, y, width, height)
5068 struct frame *f;
5069 int x, y, width, height;
5071 HDC hdc;
5073 hdc = get_frame_dc (f);
5074 w32_clear_area (f, hdc, x, y, width, height);
5075 release_frame_dc (f, hdc);
5078 /* RIF: Draw or clear cursor on window W. */
5080 static void
5081 w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5082 struct window *w;
5083 struct glyph_row *glyph_row;
5084 int x, y;
5085 int cursor_type, cursor_width;
5086 int on_p, active_p;
5088 if (on_p)
5090 /* If the user wants to use the system caret, make sure our own
5091 cursor remains invisible. */
5092 if (w32_use_visible_system_caret)
5094 /* Call to erase_phys_cursor here seems to use the
5095 wrong values of w->phys_cursor, as they have been
5096 overwritten before this function was called. */
5097 if (w->phys_cursor_type != NO_CURSOR)
5098 erase_phys_cursor (w);
5100 cursor_type = w->phys_cursor_type = NO_CURSOR;
5101 w->phys_cursor_width = -1;
5103 else
5105 w->phys_cursor_type = cursor_type;
5108 w->phys_cursor_on_p = 1;
5110 /* If this is the active cursor, we need to track it with the
5111 system caret, so third party software like screen magnifiers
5112 and speech synthesizers can follow the cursor. */
5113 if (active_p)
5115 struct frame *f = XFRAME (WINDOW_FRAME (w));
5116 HWND hwnd = FRAME_W32_WINDOW (f);
5118 w32_system_caret_x
5119 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5120 w32_system_caret_y
5121 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5122 + glyph_row->ascent - w->phys_cursor_ascent);
5124 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5126 /* If the size of the active cursor changed, destroy the old
5127 system caret. */
5128 if (w32_system_caret_hwnd
5129 && (w32_system_caret_height != w->phys_cursor_height))
5130 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5132 w32_system_caret_height = w->phys_cursor_height;
5134 /* Move the system caret. */
5135 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5138 if (glyph_row->exact_window_width_line_p
5139 && (glyph_row->reversed_p
5140 ? (w->phys_cursor.hpos < 0)
5141 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
5143 glyph_row->cursor_in_fringe_p = 1;
5144 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
5145 return;
5148 switch (cursor_type)
5150 case HOLLOW_BOX_CURSOR:
5151 x_draw_hollow_cursor (w, glyph_row);
5152 break;
5154 case FILLED_BOX_CURSOR:
5155 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5156 break;
5158 case BAR_CURSOR:
5159 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5160 break;
5162 case HBAR_CURSOR:
5163 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5164 break;
5166 case NO_CURSOR:
5167 w->phys_cursor_width = 0;
5168 break;
5170 default:
5171 abort ();
5178 /* Icons. */
5181 x_bitmap_icon (f, icon)
5182 struct frame *f;
5183 Lisp_Object icon;
5185 HANDLE main_icon;
5186 HANDLE small_icon = NULL;
5188 if (FRAME_W32_WINDOW (f) == 0)
5189 return 1;
5191 if (NILP (icon))
5192 main_icon = LoadIcon (hinst, EMACS_CLASS);
5193 else if (STRINGP (icon))
5195 /* Load the main icon from the named file. */
5196 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5197 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5198 /* Try to load a small icon to go with it. */
5199 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5200 GetSystemMetrics (SM_CXSMICON),
5201 GetSystemMetrics (SM_CYSMICON),
5202 LR_LOADFROMFILE);
5204 else if (SYMBOLP (icon))
5206 LPCTSTR name;
5208 if (EQ (icon, intern ("application")))
5209 name = (LPCTSTR) IDI_APPLICATION;
5210 else if (EQ (icon, intern ("hand")))
5211 name = (LPCTSTR) IDI_HAND;
5212 else if (EQ (icon, intern ("question")))
5213 name = (LPCTSTR) IDI_QUESTION;
5214 else if (EQ (icon, intern ("exclamation")))
5215 name = (LPCTSTR) IDI_EXCLAMATION;
5216 else if (EQ (icon, intern ("asterisk")))
5217 name = (LPCTSTR) IDI_ASTERISK;
5218 else if (EQ (icon, intern ("winlogo")))
5219 name = (LPCTSTR) IDI_WINLOGO;
5220 else
5221 return 1;
5223 main_icon = LoadIcon (NULL, name);
5225 else
5226 return 1;
5228 if (main_icon == NULL)
5229 return 1;
5231 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5232 (LPARAM) main_icon);
5234 /* If there is a small icon that goes with it, set that too. */
5235 if (small_icon)
5236 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5237 (LPARAM) small_icon);
5239 return 0;
5243 /************************************************************************
5244 Handling X errors
5245 ************************************************************************/
5247 /* Display Error Handling functions not used on W32. Listing them here
5248 helps diff stay in step when comparing w32term.c with xterm.c.
5250 x_error_catcher (display, error)
5251 x_catch_errors (dpy)
5252 x_catch_errors_unwind (old_val)
5253 x_check_errors (dpy, format)
5254 x_fully_uncatch_errors ()
5255 x_catching_errors ()
5256 x_had_errors_p (dpy)
5257 x_clear_errors (dpy)
5258 x_uncatch_errors (dpy, count)
5259 x_trace_wire ()
5260 x_connection_signal (signalnum)
5261 x_connection_closed (dpy, error_message)
5262 x_error_quitter (display, error)
5263 x_error_handler (display, error)
5264 x_io_error_quitter (display)
5269 /* Changing the font of the frame. */
5271 Lisp_Object
5272 x_new_font (f, font_object, fontset)
5273 struct frame *f;
5274 Lisp_Object font_object;
5275 int fontset;
5277 struct font *font = XFONT_OBJECT (font_object);
5279 if (fontset < 0)
5280 fontset = fontset_from_font (font_object);
5281 FRAME_FONTSET (f) = fontset;
5282 if (FRAME_FONT (f) == font)
5283 /* This font is already set in frame F. There's nothing more to
5284 do. */
5285 return font_object;
5287 FRAME_FONT (f) = font;
5288 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5289 FRAME_COLUMN_WIDTH (f) = font->average_width;
5290 FRAME_SPACE_WIDTH (f) = font->space_width;
5291 FRAME_LINE_HEIGHT (f) = font->height;
5293 compute_fringe_widths (f, 1);
5295 /* Compute the scroll bar width in character columns. */
5296 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5298 int wid = FRAME_COLUMN_WIDTH (f);
5299 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5300 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
5302 else
5304 int wid = FRAME_COLUMN_WIDTH (f);
5305 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5308 /* Now make the frame display the given font. */
5309 if (FRAME_X_WINDOW (f) != 0)
5311 /* Don't change the size of a tip frame; there's no point in
5312 doing it because it's done in Fx_show_tip, and it leads to
5313 problems because the tip frame has no widget. */
5314 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5315 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5318 /* X version sets font of input methods here also. */
5320 return font_object;
5324 /***********************************************************************
5325 TODO: W32 Input Methods
5326 ***********************************************************************/
5327 /* Listing missing functions from xterm.c helps diff stay in step.
5329 xim_destroy_callback (xim, client_data, call_data)
5330 xim_open_dpy (dpyinfo, resource_name)
5331 struct xim_inst_t
5332 xim_instantiate_callback (display, client_data, call_data)
5333 xim_initialize (dpyinfo, resource_name)
5334 xim_close_dpy (dpyinfo)
5339 /* Calculate the absolute position in frame F
5340 from its current recorded position values and gravity. */
5342 void
5343 x_calc_absolute_position (f)
5344 struct frame *f;
5346 int flags = f->size_hint_flags;
5348 /* The sum of the widths of the frame's left and right borders, and
5349 the sum of the heights of the frame's top and bottom borders (in
5350 pixels) drawn by Windows. */
5351 unsigned int left_right_borders_width, top_bottom_borders_height;
5353 /* Try to get the actual values of these two variables. We compute
5354 the border width (height) by subtracting the width (height) of
5355 the frame's client area from the width (height) of the frame's
5356 entire window. */
5357 WINDOWPLACEMENT wp = { 0 };
5358 RECT client_rect = { 0 };
5360 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
5361 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
5363 left_right_borders_width =
5364 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
5365 (client_rect.right - client_rect.left);
5367 top_bottom_borders_height =
5368 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
5369 (client_rect.bottom - client_rect.top);
5371 else
5373 /* Use sensible default values. */
5374 left_right_borders_width = 8;
5375 top_bottom_borders_height = 32;
5378 /* Treat negative positions as relative to the rightmost bottommost
5379 position that fits on the screen. */
5380 if (flags & XNegative)
5381 f->left_pos = (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f))
5382 - FRAME_PIXEL_WIDTH (f)
5383 + f->left_pos
5384 - (left_right_borders_width - 1));
5386 if (flags & YNegative)
5387 f->top_pos = (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f))
5388 - FRAME_PIXEL_HEIGHT (f)
5389 + f->top_pos
5390 - (top_bottom_borders_height - 1));
5392 /* The left_pos and top_pos are now relative to the top and left
5393 screen edges, so the flags should correspond. */
5394 f->size_hint_flags &= ~ (XNegative | YNegative);
5397 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5398 to really change the position, and 0 when calling from
5399 x_make_frame_visible (in that case, XOFF and YOFF are the current
5400 position values). It is -1 when calling from x_set_frame_parameters,
5401 which means, do adjust for borders but don't change the gravity. */
5403 void
5404 x_set_offset (f, xoff, yoff, change_gravity)
5405 struct frame *f;
5406 register int xoff, yoff;
5407 int change_gravity;
5409 int modified_top, modified_left;
5411 if (change_gravity > 0)
5413 f->top_pos = yoff;
5414 f->left_pos = xoff;
5415 f->size_hint_flags &= ~ (XNegative | YNegative);
5416 if (xoff < 0)
5417 f->size_hint_flags |= XNegative;
5418 if (yoff < 0)
5419 f->size_hint_flags |= YNegative;
5420 f->win_gravity = NorthWestGravity;
5422 x_calc_absolute_position (f);
5424 BLOCK_INPUT;
5425 x_wm_set_size_hint (f, (long) 0, 0);
5427 modified_left = f->left_pos;
5428 modified_top = f->top_pos;
5430 my_set_window_pos (FRAME_W32_WINDOW (f),
5431 NULL,
5432 modified_left, modified_top,
5433 0, 0,
5434 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
5435 UNBLOCK_INPUT;
5439 /* Check if we need to resize the frame due to a fullscreen request.
5440 If so needed, resize the frame. */
5441 static void
5442 x_check_fullscreen (f)
5443 struct frame *f;
5445 if (f->want_fullscreen & FULLSCREEN_BOTH)
5447 int width, height, ign;
5449 x_real_positions (f, &f->left_pos, &f->top_pos);
5451 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
5453 /* We do not need to move the window, it shall be taken care of
5454 when setting WM manager hints. */
5455 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
5457 change_frame_size (f, height, width, 0, 1, 0);
5458 SET_FRAME_GARBAGED (f);
5459 cancel_mouse_face (f);
5461 /* Wait for the change of frame size to occur */
5462 f->want_fullscreen |= FULLSCREEN_WAIT;
5467 /* Call this to change the size of frame F's x-window.
5468 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5469 for this size change and subsequent size changes.
5470 Otherwise we leave the window gravity unchanged. */
5472 void
5473 x_set_window_size (f, change_gravity, cols, rows)
5474 struct frame *f;
5475 int change_gravity;
5476 int cols, rows;
5478 int pixelwidth, pixelheight;
5480 BLOCK_INPUT;
5482 check_frame_size (f, &rows, &cols);
5483 f->scroll_bar_actual_width
5484 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5486 compute_fringe_widths (f, 0);
5488 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5489 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5491 f->win_gravity = NorthWestGravity;
5492 x_wm_set_size_hint (f, (long) 0, 0);
5495 RECT rect;
5497 rect.left = rect.top = 0;
5498 rect.right = pixelwidth;
5499 rect.bottom = pixelheight;
5501 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
5502 FRAME_EXTERNAL_MENU_BAR (f));
5504 my_set_window_pos (FRAME_W32_WINDOW (f),
5505 NULL,
5506 0, 0,
5507 rect.right - rect.left,
5508 rect.bottom - rect.top,
5509 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5512 #if 0
5513 /* The following mirrors what is done in xterm.c. It appears to be
5514 for informing lisp of the new size immediately, while the actual
5515 resize will happen asynchronously. But on Windows, the menu bar
5516 automatically wraps when the frame is too narrow to contain it,
5517 and that causes any calculations made here to come out wrong. The
5518 end is some nasty buggy behavior, including the potential loss
5519 of the minibuffer.
5521 Disabling this code is either not sufficient to fix the problems
5522 completely, or it causes fresh problems, but at least it removes
5523 the most problematic symptom of the minibuffer becoming unusable.
5525 -----------------------------------------------------------------
5527 Now, strictly speaking, we can't be sure that this is accurate,
5528 but the window manager will get around to dealing with the size
5529 change request eventually, and we'll hear how it went when the
5530 ConfigureNotify event gets here.
5532 We could just not bother storing any of this information here,
5533 and let the ConfigureNotify event set everything up, but that
5534 might be kind of confusing to the Lisp code, since size changes
5535 wouldn't be reported in the frame parameters until some random
5536 point in the future when the ConfigureNotify event arrives.
5538 We pass 1 for DELAY since we can't run Lisp code inside of
5539 a BLOCK_INPUT. */
5540 change_frame_size (f, rows, cols, 0, 1, 0);
5541 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5542 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5544 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5545 receive in the ConfigureNotify event; if we get what we asked
5546 for, then the event won't cause the screen to become garbaged, so
5547 we have to make sure to do it here. */
5548 SET_FRAME_GARBAGED (f);
5550 /* If cursor was outside the new size, mark it as off. */
5551 mark_window_cursors_off (XWINDOW (f->root_window));
5553 /* Clear out any recollection of where the mouse highlighting was,
5554 since it might be in a place that's outside the new frame size.
5555 Actually checking whether it is outside is a pain in the neck,
5556 so don't try--just let the highlighting be done afresh with new size. */
5557 cancel_mouse_face (f);
5558 #endif
5560 UNBLOCK_INPUT;
5563 /* Mouse warping. */
5565 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5567 void
5568 x_set_mouse_position (f, x, y)
5569 struct frame *f;
5570 int x, y;
5572 int pix_x, pix_y;
5574 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5575 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5577 if (pix_x < 0) pix_x = 0;
5578 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5580 if (pix_y < 0) pix_y = 0;
5581 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5583 x_set_mouse_pixel_position (f, pix_x, pix_y);
5586 void
5587 x_set_mouse_pixel_position (f, pix_x, pix_y)
5588 struct frame *f;
5589 int pix_x, pix_y;
5591 RECT rect;
5592 POINT pt;
5594 BLOCK_INPUT;
5596 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5597 pt.x = rect.left + pix_x;
5598 pt.y = rect.top + pix_y;
5599 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
5601 SetCursorPos (pt.x, pt.y);
5603 UNBLOCK_INPUT;
5607 /* focus shifting, raising and lowering. */
5609 void
5610 x_focus_on_frame (f)
5611 struct frame *f;
5613 struct w32_display_info *dpyinfo = &one_w32_display_info;
5615 /* Give input focus to frame. */
5616 BLOCK_INPUT;
5617 #if 0
5618 /* Try not to change its Z-order if possible. */
5619 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5620 my_set_focus (f, FRAME_W32_WINDOW (f));
5621 else
5622 #endif
5623 my_set_foreground_window (FRAME_W32_WINDOW (f));
5624 UNBLOCK_INPUT;
5627 void
5628 x_unfocus_frame (f)
5629 struct frame *f;
5633 /* Raise frame F. */
5634 void
5635 x_raise_frame (f)
5636 struct frame *f;
5638 BLOCK_INPUT;
5640 /* Strictly speaking, raise-frame should only change the frame's Z
5641 order, leaving input focus unchanged. This is reasonable behavior
5642 on X where the usual policy is point-to-focus. However, this
5643 behavior would be very odd on Windows where the usual policy is
5644 click-to-focus.
5646 On X, if the mouse happens to be over the raised frame, it gets
5647 input focus anyway (so the window with focus will never be
5648 completely obscured) - if not, then just moving the mouse over it
5649 is sufficient to give it focus. On Windows, the user must actually
5650 click on the frame (preferrably the title bar so as not to move
5651 point), which is more awkward. Also, no other Windows program
5652 raises a window to the top but leaves another window (possibly now
5653 completely obscured) with input focus.
5655 Because there is a system setting on Windows that allows the user
5656 to choose the point to focus policy, we make the strict semantics
5657 optional, but by default we grab focus when raising. */
5659 if (NILP (Vw32_grab_focus_on_raise))
5661 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5662 not already the foreground application: the frame is raised
5663 above all other frames belonging to us, but not above the
5664 current top window. To achieve that, we have to resort to this
5665 more cumbersome method. */
5667 HDWP handle = BeginDeferWindowPos (2);
5668 if (handle)
5670 DeferWindowPos (handle,
5671 FRAME_W32_WINDOW (f),
5672 HWND_TOP,
5673 0, 0, 0, 0,
5674 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5676 DeferWindowPos (handle,
5677 GetForegroundWindow (),
5678 FRAME_W32_WINDOW (f),
5679 0, 0, 0, 0,
5680 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5682 EndDeferWindowPos (handle);
5685 else
5687 my_set_foreground_window (FRAME_W32_WINDOW (f));
5690 UNBLOCK_INPUT;
5693 /* Lower frame F. */
5694 void
5695 x_lower_frame (f)
5696 struct frame *f;
5698 BLOCK_INPUT;
5699 my_set_window_pos (FRAME_W32_WINDOW (f),
5700 HWND_BOTTOM,
5701 0, 0, 0, 0,
5702 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5703 UNBLOCK_INPUT;
5706 static void
5707 w32_frame_raise_lower (f, raise_flag)
5708 FRAME_PTR f;
5709 int raise_flag;
5711 if (! FRAME_W32_P (f))
5712 return;
5714 if (raise_flag)
5715 x_raise_frame (f);
5716 else
5717 x_lower_frame (f);
5720 /* Change of visibility. */
5722 /* This tries to wait until the frame is really visible.
5723 However, if the window manager asks the user where to position
5724 the frame, this will return before the user finishes doing that.
5725 The frame will not actually be visible at that time,
5726 but it will become visible later when the window manager
5727 finishes with it. */
5729 void
5730 x_make_frame_visible (f)
5731 struct frame *f;
5733 Lisp_Object type;
5735 BLOCK_INPUT;
5737 type = x_icon_type (f);
5738 if (!NILP (type))
5739 x_bitmap_icon (f, type);
5741 if (! FRAME_VISIBLE_P (f))
5743 /* We test FRAME_GARBAGED_P here to make sure we don't
5744 call x_set_offset a second time
5745 if we get to x_make_frame_visible a second time
5746 before the window gets really visible. */
5747 if (! FRAME_ICONIFIED_P (f)
5748 && ! f->output_data.w32->asked_for_visible)
5750 RECT workarea_rect;
5751 RECT window_rect;
5753 /* Adjust vertical window position in order to avoid being
5754 covered by a task bar placed at the bottom of the desktop. */
5755 SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
5756 GetWindowRect(FRAME_W32_WINDOW(f), &window_rect);
5757 if (window_rect.bottom > workarea_rect.bottom
5758 && window_rect.top > workarea_rect.top)
5759 f->top_pos = max (window_rect.top
5760 - window_rect.bottom + workarea_rect.bottom,
5761 workarea_rect.top);
5763 x_set_offset (f, f->left_pos, f->top_pos, 0);
5766 f->output_data.w32->asked_for_visible = 1;
5768 /* The first of these seems to give more expected behavior, but
5769 was added as a commented out line in Sept 1997, with the
5770 second version remaining uncommented. There may have been
5771 some problem with it that led to it not being enabled,
5772 so the old version remains commented out below in case we
5773 decide we need to go back to it [23.0.60 2008-06-09]. */
5774 my_show_window (f, FRAME_W32_WINDOW (f),
5775 f->async_iconified ? SW_RESTORE : SW_SHOW);
5776 /* my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); */
5779 /* Synchronize to ensure Emacs knows the frame is visible
5780 before we do anything else. We do this loop with input not blocked
5781 so that incoming events are handled. */
5783 Lisp_Object frame;
5784 int count;
5786 /* This must come after we set COUNT. */
5787 UNBLOCK_INPUT;
5789 XSETFRAME (frame, f);
5791 /* Wait until the frame is visible. Process X events until a
5792 MapNotify event has been seen, or until we think we won't get a
5793 MapNotify at all.. */
5794 for (count = input_signal_count + 10;
5795 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5797 /* Force processing of queued events. */
5798 /* TODO: x_sync equivalent? */
5800 /* Machines that do polling rather than SIGIO have been observed
5801 to go into a busy-wait here. So we'll fake an alarm signal
5802 to let the handler know that there's something to be read.
5803 We used to raise a real alarm, but it seems that the handler
5804 isn't always enabled here. This is probably a bug. */
5805 if (input_polling_used ())
5807 /* It could be confusing if a real alarm arrives while processing
5808 the fake one. Turn it off and let the handler reset it. */
5809 int old_poll_suppress_count = poll_suppress_count;
5810 poll_suppress_count = 1;
5811 poll_for_input_1 ();
5812 poll_suppress_count = old_poll_suppress_count;
5815 FRAME_SAMPLE_VISIBILITY (f);
5819 /* Change from mapped state to withdrawn state. */
5821 /* Make the frame visible (mapped and not iconified). */
5823 x_make_frame_invisible (f)
5824 struct frame *f;
5826 /* Don't keep the highlight on an invisible frame. */
5827 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5828 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5830 BLOCK_INPUT;
5832 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
5834 /* We can't distinguish this from iconification
5835 just by the event that we get from the server.
5836 So we can't win using the usual strategy of letting
5837 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5838 and synchronize with the server to make sure we agree. */
5839 f->visible = 0;
5840 FRAME_ICONIFIED_P (f) = 0;
5841 f->async_visible = 0;
5842 f->async_iconified = 0;
5844 UNBLOCK_INPUT;
5847 /* Change window state from mapped to iconified. */
5849 void
5850 x_iconify_frame (f)
5851 struct frame *f;
5853 Lisp_Object type;
5855 /* Don't keep the highlight on an invisible frame. */
5856 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5857 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5859 if (f->async_iconified)
5860 return;
5862 BLOCK_INPUT;
5864 type = x_icon_type (f);
5865 if (!NILP (type))
5866 x_bitmap_icon (f, type);
5868 /* Simulate the user minimizing the frame. */
5869 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
5871 UNBLOCK_INPUT;
5875 /* Free X resources of frame F. */
5877 void
5878 x_free_frame_resources (f)
5879 struct frame *f;
5881 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5883 BLOCK_INPUT;
5885 /* We must free faces before destroying windows because some
5886 font-driver (e.g. xft) access a window while finishing a
5887 face. */
5888 if (FRAME_FACE_CACHE (f))
5889 free_frame_faces (f);
5891 if (FRAME_W32_WINDOW (f))
5892 my_destroy_window (f, FRAME_W32_WINDOW (f));
5894 free_frame_menubar (f);
5896 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
5897 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
5898 unload_color (f, f->output_data.w32->cursor_pixel);
5899 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
5900 unload_color (f, f->output_data.w32->border_pixel);
5901 unload_color (f, f->output_data.w32->mouse_pixel);
5902 if (f->output_data.w32->white_relief.allocated_p)
5903 unload_color (f, f->output_data.w32->white_relief.pixel);
5904 if (f->output_data.w32->black_relief.allocated_p)
5905 unload_color (f, f->output_data.w32->black_relief.pixel);
5907 if (FRAME_FACE_CACHE (f))
5908 free_frame_faces (f);
5910 xfree (f->output_data.w32);
5911 f->output_data.w32 = NULL;
5913 if (f == dpyinfo->w32_focus_frame)
5914 dpyinfo->w32_focus_frame = 0;
5915 if (f == dpyinfo->w32_focus_event_frame)
5916 dpyinfo->w32_focus_event_frame = 0;
5917 if (f == dpyinfo->x_highlight_frame)
5918 dpyinfo->x_highlight_frame = 0;
5920 if (f == dpyinfo->mouse_face_mouse_frame)
5922 dpyinfo->mouse_face_beg_row
5923 = dpyinfo->mouse_face_beg_col = -1;
5924 dpyinfo->mouse_face_end_row
5925 = dpyinfo->mouse_face_end_col = -1;
5926 dpyinfo->mouse_face_window = Qnil;
5927 dpyinfo->mouse_face_deferred_gc = 0;
5928 dpyinfo->mouse_face_mouse_frame = 0;
5931 UNBLOCK_INPUT;
5935 /* Destroy the window of frame F. */
5936 void
5937 x_destroy_window (f)
5938 struct frame *f;
5940 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5942 x_free_frame_resources (f);
5943 dpyinfo->reference_count--;
5947 /* Setting window manager hints. */
5949 /* Set the normal size hints for the window manager, for frame F.
5950 FLAGS is the flags word to use--or 0 meaning preserve the flags
5951 that the window now has.
5952 If USER_POSITION is nonzero, we set the USPosition
5953 flag (this is useful when FLAGS is 0). */
5954 void
5955 x_wm_set_size_hint (f, flags, user_position)
5956 struct frame *f;
5957 long flags;
5958 int user_position;
5960 Window window = FRAME_W32_WINDOW (f);
5962 enter_crit ();
5964 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
5965 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
5966 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
5967 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
5969 leave_crit ();
5972 /* Window manager things */
5973 void
5974 x_wm_set_icon_position (f, icon_x, icon_y)
5975 struct frame *f;
5976 int icon_x, icon_y;
5978 #if 0
5979 Window window = FRAME_W32_WINDOW (f);
5981 f->display.x->wm_hints.flags |= IconPositionHint;
5982 f->display.x->wm_hints.icon_x = icon_x;
5983 f->display.x->wm_hints.icon_y = icon_y;
5985 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
5986 #endif
5990 /***********************************************************************
5991 Initialization
5992 ***********************************************************************/
5994 static int w32_initialized = 0;
5996 void
5997 w32_initialize_display_info (display_name)
5998 Lisp_Object display_name;
6000 struct w32_display_info *dpyinfo = &one_w32_display_info;
6002 bzero (dpyinfo, sizeof (*dpyinfo));
6004 /* Put it on w32_display_name_list. */
6005 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6006 w32_display_name_list);
6007 dpyinfo->name_list_element = XCAR (w32_display_name_list);
6009 dpyinfo->w32_id_name
6010 = (char *) xmalloc (SCHARS (Vinvocation_name)
6011 + SCHARS (Vsystem_name)
6012 + 2);
6013 sprintf (dpyinfo->w32_id_name, "%s@%s",
6014 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6016 /* Default Console mode values - overridden when running in GUI mode
6017 with values obtained from system metrics. */
6018 dpyinfo->resx = 1;
6019 dpyinfo->resy = 1;
6020 dpyinfo->n_planes = 1;
6021 dpyinfo->n_cbits = 4;
6022 dpyinfo->n_fonts = 0;
6023 dpyinfo->smallest_font_height = 1;
6024 dpyinfo->smallest_char_width = 1;
6026 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6027 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6028 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
6029 dpyinfo->mouse_face_window = Qnil;
6030 dpyinfo->mouse_face_overlay = Qnil;
6031 dpyinfo->mouse_face_hidden = 0;
6033 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6034 /* TODO: dpyinfo->gray */
6038 /* Create an xrdb-style database of resources to supercede registry settings.
6039 The database is just a concatenation of C strings, finished by an additional
6040 \0. The strings are submitted to some basic normalization, so
6042 [ *]option[ *]:[ *]value...
6044 becomes
6046 option:value...
6048 but any whitespace following value is not removed. */
6050 static char *
6051 w32_make_rdb (xrm_option)
6052 char *xrm_option;
6054 char *buffer = xmalloc (strlen (xrm_option) + 2);
6055 char *current = buffer;
6056 char ch;
6057 int in_option = 1;
6058 int before_value = 0;
6060 do {
6061 ch = *xrm_option++;
6063 if (ch == '\n')
6065 *current++ = '\0';
6066 in_option = 1;
6067 before_value = 0;
6069 else if (ch != ' ')
6071 *current++ = ch;
6072 if (in_option && (ch == ':'))
6074 in_option = 0;
6075 before_value = 1;
6077 else if (before_value)
6079 before_value = 0;
6082 else if (!(in_option || before_value))
6084 *current++ = ch;
6086 } while (ch);
6088 *current = '\0';
6090 return buffer;
6093 void
6094 x_flush (struct frame * f)
6095 { /* Nothing to do */ }
6098 extern frame_parm_handler w32_frame_parm_handlers[];
6100 static struct redisplay_interface w32_redisplay_interface =
6102 w32_frame_parm_handlers,
6103 x_produce_glyphs,
6104 x_write_glyphs,
6105 x_insert_glyphs,
6106 x_clear_end_of_line,
6107 x_scroll_run,
6108 x_after_update_window_line,
6109 x_update_window_begin,
6110 x_update_window_end,
6111 x_cursor_to,
6112 x_flush,
6113 0, /* flush_display_optional */
6114 x_clear_window_mouse_face,
6115 x_get_glyph_overhangs,
6116 x_fix_overlapping_area,
6117 w32_draw_fringe_bitmap,
6118 w32_define_fringe_bitmap,
6119 w32_destroy_fringe_bitmap,
6120 w32_compute_glyph_string_overhangs,
6121 x_draw_glyph_string,
6122 w32_define_frame_cursor,
6123 w32_clear_frame_area,
6124 w32_draw_window_cursor,
6125 w32_draw_vertical_window_border,
6126 w32_shift_glyphs_for_insert
6129 static void x_delete_terminal (struct terminal *term);
6131 static struct terminal *
6132 w32_create_terminal (struct w32_display_info *dpyinfo)
6134 struct terminal *terminal;
6136 terminal = create_terminal ();
6138 terminal->type = output_w32;
6139 terminal->display_info.w32 = dpyinfo;
6140 dpyinfo->terminal = terminal;
6142 /* MSVC does not type K&R functions with no arguments correctly, and
6143 so we must explicitly cast them. */
6144 terminal->clear_frame_hook = x_clear_frame;
6145 terminal->ins_del_lines_hook = x_ins_del_lines;
6146 terminal->delete_glyphs_hook = x_delete_glyphs;
6147 terminal->ring_bell_hook = w32_ring_bell;
6148 terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
6149 terminal->set_terminal_modes_hook = w32_set_terminal_modes;
6150 terminal->update_begin_hook = x_update_begin;
6151 terminal->update_end_hook = x_update_end;
6152 terminal->set_terminal_window_hook = w32_set_terminal_window;
6153 terminal->read_socket_hook = w32_read_socket;
6154 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
6155 terminal->mouse_position_hook = w32_mouse_position;
6156 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
6157 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
6158 // terminal->fullscreen_hook = XTfullscreen_hook;
6159 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6160 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6161 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6162 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
6164 terminal->delete_frame_hook = x_destroy_window;
6165 terminal->delete_terminal_hook = x_delete_terminal;
6167 terminal->rif = &w32_redisplay_interface;
6168 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
6169 terminal->char_ins_del_ok = 1;
6170 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
6171 terminal->fast_clear_end_of_line = 1; /* X does this well. */
6172 terminal->memory_below_frame = 0; /* We don't remember what scrolls
6173 off the bottom. */
6175 /* We don't yet support separate terminals on W32, so don't try to share
6176 keyboards between virtual terminals that are on the same physical
6177 terminal like X does. */
6178 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
6179 init_kboard (terminal->kboard);
6180 terminal->kboard->Vwindow_system = intern ("w32");
6181 terminal->kboard->next_kboard = all_kboards;
6182 all_kboards = terminal->kboard;
6183 /* Don't let the initial kboard remain current longer than necessary.
6184 That would cause problems if a file loaded on startup tries to
6185 prompt in the mini-buffer. */
6186 if (current_kboard == initial_kboard)
6187 current_kboard = terminal->kboard;
6188 terminal->kboard->reference_count++;
6190 return terminal;
6193 static void
6194 x_delete_terminal (struct terminal *terminal)
6196 struct w32_display_info *dpyinfo = terminal->display_info.w32;
6197 int i;
6199 /* Protect against recursive calls. delete_frame in
6200 delete_terminal calls us back when it deletes our last frame. */
6201 if (!terminal->name)
6202 return;
6204 BLOCK_INPUT;
6206 x_delete_display (dpyinfo);
6207 UNBLOCK_INPUT;
6210 struct w32_display_info *
6211 w32_term_init (display_name, xrm_option, resource_name)
6212 Lisp_Object display_name;
6213 char *xrm_option;
6214 char *resource_name;
6216 struct w32_display_info *dpyinfo;
6217 struct terminal *terminal;
6218 HDC hdc;
6220 BLOCK_INPUT;
6222 if (!w32_initialized)
6224 w32_initialize ();
6225 w32_initialized = 1;
6228 w32_initialize_display_info (display_name);
6230 dpyinfo = &one_w32_display_info;
6231 terminal = w32_create_terminal (dpyinfo);
6233 /* Set the name of the terminal. */
6234 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
6235 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
6236 terminal->name[SBYTES (display_name)] = 0;
6238 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6240 /* Put this display on the chain. */
6241 dpyinfo->next = x_display_list;
6242 x_display_list = dpyinfo;
6244 hdc = GetDC (NULL);
6246 dpyinfo->root_window = GetDesktopWindow ();
6247 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6248 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
6249 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6250 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
6251 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
6252 ReleaseDC (NULL, hdc);
6254 /* initialise palette with white and black */
6256 XColor color;
6257 w32_defined_color (0, "white", &color, 1);
6258 w32_defined_color (0, "black", &color, 1);
6261 /* Add the default keyboard. */
6262 add_keyboard_wait_descriptor (0);
6264 /* Create Fringe Bitmaps and store them for later use.
6266 On W32, bitmaps are all unsigned short, as Windows requires
6267 bitmap data to be Word aligned. For some reason they are
6268 horizontally reflected compared to how they appear on X, so we
6269 need to bitswap and convert to unsigned shorts before creating
6270 the bitmaps. */
6271 w32_init_fringe (terminal->rif);
6273 #ifdef F_SETOWN
6274 fcntl (connection, F_SETOWN, getpid ());
6275 #endif /* ! defined (F_SETOWN) */
6277 #ifdef SIGIO
6278 if (interrupt_input)
6279 init_sigio (connection);
6280 #endif /* ! defined (SIGIO) */
6282 UNBLOCK_INPUT;
6284 return dpyinfo;
6287 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6288 void
6289 x_delete_display (dpyinfo)
6290 struct w32_display_info *dpyinfo;
6292 /* Discard this display from w32_display_name_list and w32_display_list.
6293 We can't use Fdelq because that can quit. */
6294 if (! NILP (w32_display_name_list)
6295 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6296 w32_display_name_list = XCDR (w32_display_name_list);
6297 else
6299 Lisp_Object tail;
6301 tail = w32_display_name_list;
6302 while (CONSP (tail) && CONSP (XCDR (tail)))
6304 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
6306 XSETCDR (tail, XCDR (XCDR (tail)));
6307 break;
6309 tail = XCDR (tail);
6313 /* free palette table */
6315 struct w32_palette_entry * plist;
6317 plist = dpyinfo->color_list;
6318 while (plist)
6320 struct w32_palette_entry * pentry = plist;
6321 plist = plist->next;
6322 xfree (pentry);
6324 dpyinfo->color_list = NULL;
6325 if (dpyinfo->palette)
6326 DeleteObject(dpyinfo->palette);
6328 xfree (dpyinfo->w32_id_name);
6330 w32_reset_fringes ();
6333 /* Set up use of W32. */
6335 DWORD WINAPI w32_msg_worker (void * arg);
6337 static void
6338 w32_initialize ()
6340 HANDLE shell;
6341 HRESULT (WINAPI * set_user_model) (wchar_t * id);
6343 baud_rate = 19200;
6345 w32_system_caret_hwnd = NULL;
6346 w32_system_caret_height = 0;
6347 w32_system_caret_x = 0;
6348 w32_system_caret_y = 0;
6350 /* On Windows 7 and later, we need to set the user model ID
6351 to associate emacsclient launched files with Emacs frames
6352 in the UI. */
6353 shell = GetModuleHandle ("shell32.dll");
6354 if (shell)
6356 set_user_model
6357 = (void *) GetProcAddress (shell,
6358 "SetCurrentProcessExplicitAppUserModelID");
6360 /* If the function is defined, then we are running on Windows 7
6361 or newer, and the UI uses this to group related windows
6362 together. Since emacs, runemacs, emacsclient are related, we
6363 want them grouped even though the executables are different,
6364 so we need to set a consistent ID between them. */
6365 if (set_user_model)
6366 set_user_model (L"GNU.Emacs");
6369 /* Initialize w32_use_visible_system_caret based on whether a screen
6370 reader is in use. */
6371 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6372 &w32_use_visible_system_caret, 0))
6373 w32_use_visible_system_caret = 0;
6375 last_tool_bar_item = -1;
6376 any_help_event_p = 0;
6378 /* Initialize input mode: interrupt_input off, no flow control, allow
6379 8 bit character input, standard quit char. */
6380 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6383 DWORD input_locale_id = (DWORD) GetKeyboardLayout (0);
6384 keyboard_codepage = codepage_for_locale ((LCID) (input_locale_id & 0xffff));
6387 /* Create the window thread - it will terminate itself when the app
6388 terminates */
6389 init_crit ();
6391 dwMainThreadId = GetCurrentThreadId ();
6392 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6393 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6395 /* Wait for thread to start */
6397 MSG msg;
6399 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6401 hWindowsThread = CreateThread (NULL, 0,
6402 w32_msg_worker,
6403 0, 0, &dwWindowsThreadId);
6405 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6408 /* It is desirable that mainThread should have the same notion of
6409 focus window and active window as windowsThread. Unfortunately, the
6410 following call to AttachThreadInput, which should do precisely what
6411 we need, causes major problems when Emacs is linked as a console
6412 program. Unfortunately, we have good reasons for doing that, so
6413 instead we need to send messages to windowsThread to make some API
6414 calls for us (ones that affect, or depend on, the active/focus
6415 window state.) */
6416 #ifdef ATTACH_THREADS
6417 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
6418 #endif
6420 /* Dynamically link to optional system components. */
6422 HMODULE user_lib = GetModuleHandle ("user32.dll");
6424 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6426 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
6428 #undef LOAD_PROC
6430 /* Ensure scrollbar handle is at least 5 pixels. */
6431 vertical_scroll_bar_min_handle = 5;
6433 /* For either kind of scroll bar, take account of the arrows; these
6434 effectively form the border of the main scroll bar range. */
6435 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6436 = GetSystemMetrics (SM_CYVSCROLL);
6440 void
6441 syms_of_w32term ()
6443 staticpro (&w32_display_name_list);
6444 w32_display_name_list = Qnil;
6446 staticpro (&last_mouse_scroll_bar);
6447 last_mouse_scroll_bar = Qnil;
6449 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
6451 DEFVAR_INT ("w32-num-mouse-buttons",
6452 &w32_num_mouse_buttons,
6453 doc: /* Number of physical mouse buttons. */);
6454 w32_num_mouse_buttons = 2;
6456 DEFVAR_LISP ("w32-swap-mouse-buttons",
6457 &Vw32_swap_mouse_buttons,
6458 doc: /* Swap the mapping of middle and right mouse buttons.
6459 When nil, middle button is mouse-2 and right button is mouse-3. */);
6460 Vw32_swap_mouse_buttons = Qnil;
6462 DEFVAR_LISP ("w32-grab-focus-on-raise",
6463 &Vw32_grab_focus_on_raise,
6464 doc: /* Raised frame grabs input focus.
6465 When t, `raise-frame' grabs input focus as well. This fits well
6466 with the normal Windows click-to-focus policy, but might not be
6467 desirable when using a point-to-focus policy. */);
6468 Vw32_grab_focus_on_raise = Qt;
6470 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6471 &Vw32_capslock_is_shiftlock,
6472 doc: /* Apply CapsLock state to non character input keys.
6473 When nil, CapsLock only affects normal character input keys. */);
6474 Vw32_capslock_is_shiftlock = Qnil;
6476 DEFVAR_LISP ("w32-recognize-altgr",
6477 &Vw32_recognize_altgr,
6478 doc: /* Recognize right-alt and left-ctrl as AltGr.
6479 When nil, the right-alt and left-ctrl key combination is
6480 interpreted normally. */);
6481 Vw32_recognize_altgr = Qt;
6483 DEFVAR_BOOL ("w32-use-visible-system-caret",
6484 &w32_use_visible_system_caret,
6485 doc: /* Flag to make the system caret visible.
6486 When this is non-nil, Emacs will indicate the position of point by
6487 using the system caret instead of drawing its own cursor. Some screen
6488 reader software does not track the system cursor properly when it is
6489 invisible, and gets confused by Emacs drawing its own cursor, so this
6490 variable is initialized to t when Emacs detects that screen reader
6491 software is running as it starts up.
6493 When this variable is set, other variables affecting the appearance of
6494 the cursor have no effect. */);
6496 w32_use_visible_system_caret = 0;
6498 /* We don't yet support this, but defining this here avoids whining
6499 from cus-start.el and other places, like "M-x set-variable". */
6500 DEFVAR_BOOL ("x-use-underline-position-properties",
6501 &x_use_underline_position_properties,
6502 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
6503 A value of nil means ignore them. If you encounter fonts with bogus
6504 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6505 to 4.1, set this to nil. */);
6506 x_use_underline_position_properties = 0;
6508 DEFVAR_BOOL ("x-underline-at-descent-line",
6509 &x_underline_at_descent_line,
6510 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
6511 A value of nil means to draw the underline according to the value of the
6512 variable `x-use-underline-position-properties', which is usually at the
6513 baseline level. The default value is nil. */);
6514 x_underline_at_descent_line = 0;
6516 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
6517 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
6518 Vx_toolkit_scroll_bars = Qt;
6520 staticpro (&last_mouse_motion_frame);
6521 last_mouse_motion_frame = Qnil;
6524 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6525 (do not change this comment) */