* buff-menu.el (Buffer-menu-buffer+size): Use display property to
[emacs.git] / src / w32term.c
blob008042c810a9e171d44cbb78d6847d7b8c387b53
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 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 #ifndef USE_CRT_DLL
232 extern int errno;
233 #endif
235 /* A mask of extra modifier bits to put into every keyboard char. */
236 extern EMACS_INT extra_keyboard_modifiers;
238 /* Keyboard code page - may be changed by language-change events. */
239 static int keyboard_codepage;
241 static void x_update_window_end P_ ((struct window *, int, int));
242 static void w32_handle_tool_bar_click P_ ((struct frame *,
243 struct input_event *));
244 static void w32_define_cursor P_ ((Window, Cursor));
246 void x_lower_frame P_ ((struct frame *));
247 void x_scroll_bar_clear P_ ((struct frame *));
248 void x_wm_set_size_hint P_ ((struct frame *, long, int));
249 void x_raise_frame P_ ((struct frame *));
250 void x_set_window_size P_ ((struct frame *, int, int, int));
251 void x_wm_set_window_state P_ ((struct frame *, int));
252 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
253 static void w32_initialize P_ ((void));
254 static void x_update_end P_ ((struct frame *));
255 static void w32_frame_up_to_date P_ ((struct frame *));
256 static void w32_set_terminal_modes P_ ((struct terminal *));
257 static void w32_reset_terminal_modes P_ ((struct terminal *));
258 static void x_clear_frame P_ ((struct frame *));
259 static void frame_highlight P_ ((struct frame *));
260 static void frame_unhighlight P_ ((struct frame *));
261 static void x_new_focus_frame P_ ((struct w32_display_info *,
262 struct frame *));
263 static void x_focus_changed P_ ((int, int, struct w32_display_info *,
264 struct frame *, struct input_event *));
265 static void w32_detect_focus_change P_ ((struct w32_display_info *,
266 W32Msg *, struct input_event *));
267 static void w32_frame_rehighlight P_ ((struct frame *));
268 static void x_frame_rehighlight P_ ((struct w32_display_info *));
269 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
270 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
271 enum text_cursor_kinds));
272 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
273 static BOOL my_show_window P_ ((struct frame *, HWND, int));
274 static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
275 static void my_set_focus P_ ((struct frame *, HWND));
276 static void my_set_foreground_window P_ ((HWND));
277 static void my_destroy_window P_ ((struct frame *, HWND));
279 static Lisp_Object Qvendor_specific_keysyms;
282 /***********************************************************************
283 Debugging
284 ***********************************************************************/
286 #if 0
288 /* This is a function useful for recording debugging information about
289 the sequence of occurrences in this file. */
291 struct record
293 char *locus;
294 int type;
297 struct record event_record[100];
299 int event_record_index;
301 record_event (locus, type)
302 char *locus;
303 int type;
305 if (event_record_index == sizeof (event_record) / sizeof (struct record))
306 event_record_index = 0;
308 event_record[event_record_index].locus = locus;
309 event_record[event_record_index].type = type;
310 event_record_index++;
313 #endif /* 0 */
316 void
317 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
318 XGCValues *xgcv)
320 if (mask & GCForeground)
321 gc->foreground = xgcv->foreground;
322 if (mask & GCBackground)
323 gc->background = xgcv->background;
324 if (mask & GCFont)
325 gc->font = xgcv->font;
328 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
329 XGCValues *xgcv)
331 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
332 bzero (gc, sizeof (XGCValues));
334 XChangeGC (ignore, gc, mask, xgcv);
336 return gc;
339 void
340 XGetGCValues (void* ignore, XGCValues *gc,
341 unsigned long mask, XGCValues *xgcv)
343 XChangeGC (ignore, xgcv, mask, gc);
346 static void
347 w32_set_clip_rectangle (HDC hdc, RECT *rect)
349 if (rect)
351 HRGN clip_region = CreateRectRgnIndirect (rect);
352 SelectClipRgn (hdc, clip_region);
353 DeleteObject (clip_region);
355 else
356 SelectClipRgn (hdc, NULL);
360 /* Draw a hollow rectangle at the specified position. */
361 void
362 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
363 int width, int height)
365 HBRUSH hb, oldhb;
366 HPEN hp, oldhp;
368 hb = CreateSolidBrush (gc->background);
369 hp = CreatePen (PS_SOLID, 0, gc->foreground);
370 oldhb = SelectObject (hdc, hb);
371 oldhp = SelectObject (hdc, hp);
373 Rectangle (hdc, x, y, x + width, y + height);
375 SelectObject (hdc, oldhb);
376 SelectObject (hdc, oldhp);
377 DeleteObject (hb);
378 DeleteObject (hp);
381 /* Draw a filled rectangle at the specified position. */
382 void
383 w32_fill_rect (f, hdc, pix, lprect)
384 FRAME_PTR f;
385 HDC hdc;
386 COLORREF pix;
387 RECT * lprect;
389 HBRUSH hb;
391 hb = CreateSolidBrush (pix);
392 FillRect (hdc, lprect, hb);
393 DeleteObject (hb);
396 void
397 w32_clear_window (f)
398 FRAME_PTR f;
400 RECT rect;
401 HDC hdc = get_frame_dc (f);
403 /* Under certain conditions, this can be called at startup with
404 a console frame pointer before the GUI frame is created. An HDC
405 of 0 indicates this. */
406 if (hdc)
408 GetClientRect (FRAME_W32_WINDOW (f), &rect);
409 w32_clear_rect (f, hdc, &rect);
412 release_frame_dc (f, hdc);
415 #define OPAQUE_FRAME 255
417 void
418 x_set_frame_alpha (f)
419 struct frame *f;
421 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
422 double alpha = 1.0;
423 double alpha_min = 1.0;
424 BYTE opac;
425 LONG ex_style;
426 HWND window = FRAME_W32_WINDOW (f);
428 /* Older versions of Windows do not support transparency. */
429 if (!pfnSetLayeredWindowAttributes)
430 return;
432 if (dpyinfo->x_highlight_frame == f)
433 alpha = f->alpha[0];
434 else
435 alpha = f->alpha[1];
437 if (FLOATP (Vframe_alpha_lower_limit))
438 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
439 else if (INTEGERP (Vframe_alpha_lower_limit))
440 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
442 if (alpha < 0.0)
443 return;
444 else if (alpha > 1.0)
445 alpha = 1.0;
446 else if (alpha < alpha_min && alpha_min <= 1.0)
447 alpha = alpha_min;
449 opac = alpha * OPAQUE_FRAME;
451 ex_style = GetWindowLong (window, GWL_EXSTYLE);
453 if (opac == OPAQUE_FRAME)
454 ex_style &= ~WS_EX_LAYERED;
455 else
456 ex_style |= WS_EX_LAYERED;
458 SetWindowLong (window, GWL_EXSTYLE, ex_style);
460 if (opac != OPAQUE_FRAME)
461 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
465 x_display_pixel_height (dpyinfo)
466 struct w32_display_info *dpyinfo;
468 HDC dc = GetDC (NULL);
469 int pixels = GetDeviceCaps (dc, VERTRES);
470 ReleaseDC (NULL, dc);
471 return pixels;
475 x_display_pixel_width (dpyinfo)
476 struct w32_display_info *dpyinfo;
478 HDC dc = GetDC (NULL);
479 int pixels = GetDeviceCaps (dc, HORZRES);
480 ReleaseDC (NULL, dc);
481 return pixels;
485 /***********************************************************************
486 Starting and ending an update
487 ***********************************************************************/
489 /* Start an update of frame F. This function is installed as a hook
490 for update_begin, i.e. it is called when update_begin is called.
491 This function is called prior to calls to x_update_window_begin for
492 each window being updated. */
494 static void
495 x_update_begin (f)
496 struct frame *f;
498 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
500 if (! FRAME_W32_P (f))
501 return;
503 /* Regenerate display palette before drawing if list of requested
504 colors has changed. */
505 if (display_info->regen_palette)
507 w32_regenerate_palette (f);
508 display_info->regen_palette = FALSE;
513 /* Start update of window W. Set the global variable updated_window
514 to the window being updated and set output_cursor to the cursor
515 position of W. */
517 static void
518 x_update_window_begin (w)
519 struct window *w;
521 struct frame *f = XFRAME (WINDOW_FRAME (w));
522 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
524 /* Hide the system caret during an update. */
525 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
527 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
530 updated_window = w;
531 set_output_cursor (&w->cursor);
533 BLOCK_INPUT;
535 if (f == display_info->mouse_face_mouse_frame)
537 /* Don't do highlighting for mouse motion during the update. */
538 display_info->mouse_face_defer = 1;
540 /* If F needs to be redrawn, simply forget about any prior mouse
541 highlighting. */
542 if (FRAME_GARBAGED_P (f))
543 display_info->mouse_face_window = Qnil;
545 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
546 their mouse_face_p flag set, which means that they are always
547 unequal to rows in a desired matrix which never have that
548 flag set. So, rows containing mouse-face glyphs are never
549 scrolled, and we don't have to switch the mouse highlight off
550 here to prevent it from being scrolled. */
552 /* Can we tell that this update does not affect the window
553 where the mouse highlight is? If so, no need to turn off.
554 Likewise, don't do anything if the frame is garbaged;
555 in that case, the frame's current matrix that we would use
556 is all wrong, and we will redisplay that line anyway. */
557 if (!NILP (display_info->mouse_face_window)
558 && w == XWINDOW (display_info->mouse_face_window))
560 int i;
562 for (i = 0; i < w->desired_matrix->nrows; ++i)
563 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
564 break;
566 if (i < w->desired_matrix->nrows)
567 clear_mouse_face (display_info);
569 #endif /* 0 */
572 UNBLOCK_INPUT;
575 /* Draw a vertical window border from (x,y0) to (x,y1) */
577 static void
578 w32_draw_vertical_window_border (w, x, y0, y1)
579 struct window *w;
580 int x, y0, y1;
582 struct frame *f = XFRAME (WINDOW_FRAME (w));
583 RECT r;
584 HDC hdc;
585 struct face *face;
587 r.left = x;
588 r.right = x + 1;
589 r.top = y0;
590 r.bottom = y1;
592 hdc = get_frame_dc (f);
593 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
594 if (face)
595 w32_fill_rect (f, hdc, face->foreground, &r);
596 else
597 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
599 release_frame_dc (f, hdc);
603 /* End update of window W (which is equal to updated_window).
605 Draw vertical borders between horizontally adjacent windows, and
606 display W's cursor if CURSOR_ON_P is non-zero.
608 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
609 glyphs in mouse-face were overwritten. In that case we have to
610 make sure that the mouse-highlight is properly redrawn.
612 W may be a menu bar pseudo-window in case we don't have X toolkit
613 support. Such windows don't have a cursor, so don't display it
614 here. */
616 static void
617 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
618 struct window *w;
619 int cursor_on_p, mouse_face_overwritten_p;
621 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
623 if (!w->pseudo_window_p)
625 BLOCK_INPUT;
627 if (cursor_on_p)
628 display_and_set_cursor (w, 1, output_cursor.hpos,
629 output_cursor.vpos,
630 output_cursor.x, output_cursor.y);
632 if (draw_window_fringes (w, 1))
633 x_draw_vertical_border (w);
635 UNBLOCK_INPUT;
638 /* If a row with mouse-face was overwritten, arrange for
639 XTframe_up_to_date to redisplay the mouse highlight. */
640 if (mouse_face_overwritten_p)
642 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
643 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
644 dpyinfo->mouse_face_window = Qnil;
647 /* Unhide the caret. This won't actually show the cursor, unless it
648 was visible before the corresponding call to HideCaret in
649 x_update_window_begin. */
650 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
652 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
655 updated_window = NULL;
659 /* End update of frame F. This function is installed as a hook in
660 update_end. */
662 static void
663 x_update_end (f)
664 struct frame *f;
666 if (! FRAME_W32_P (f))
667 return;
669 /* Mouse highlight may be displayed again. */
670 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
674 /* This function is called from various places in xdisp.c whenever a
675 complete update has been performed. The global variable
676 updated_window is not available here. */
678 static void
679 w32_frame_up_to_date (f)
680 struct frame *f;
682 if (FRAME_W32_P (f))
684 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
686 if (dpyinfo->mouse_face_deferred_gc
687 || f == dpyinfo->mouse_face_mouse_frame)
689 BLOCK_INPUT;
690 if (dpyinfo->mouse_face_mouse_frame)
691 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
692 dpyinfo->mouse_face_mouse_x,
693 dpyinfo->mouse_face_mouse_y);
694 dpyinfo->mouse_face_deferred_gc = 0;
695 UNBLOCK_INPUT;
701 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
702 arrow bitmaps, or clear the fringes if no bitmaps are required
703 before DESIRED_ROW is made current. The window being updated is
704 found in updated_window. This function is called from
705 update_window_line only if it is known that there are differences
706 between bitmaps to be drawn between current row and DESIRED_ROW. */
708 static void
709 x_after_update_window_line (desired_row)
710 struct glyph_row *desired_row;
712 struct window *w = updated_window;
713 struct frame *f;
714 int width, height;
716 xassert (w);
718 if (!desired_row->mode_line_p && !w->pseudo_window_p)
719 desired_row->redraw_fringe_bitmaps_p = 1;
721 /* When a window has disappeared, make sure that no rest of
722 full-width rows stays visible in the internal border. Could
723 check here if updated_window is the leftmost/rightmost window,
724 but I guess it's not worth doing since vertically split windows
725 are almost never used, internal border is rarely set, and the
726 overhead is very small. */
727 if (windows_or_buffers_changed
728 && desired_row->full_width_p
729 && (f = XFRAME (w->frame),
730 width = FRAME_INTERNAL_BORDER_WIDTH (f),
731 width != 0)
732 && (height = desired_row->visible_height,
733 height > 0))
735 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
737 /* Internal border is drawn below the tool bar. */
738 if (WINDOWP (f->tool_bar_window)
739 && w == XWINDOW (f->tool_bar_window))
740 y -= width;
742 BLOCK_INPUT;
744 HDC hdc = get_frame_dc (f);
745 w32_clear_area (f, hdc, 0, y, width, height);
746 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
747 y, width, height);
748 release_frame_dc (f, hdc);
750 UNBLOCK_INPUT;
755 /* Draw the bitmap WHICH in one of the left or right fringes of
756 window W. ROW is the glyph row for which to display the bitmap; it
757 determines the vertical position at which the bitmap has to be
758 drawn. */
760 static void
761 w32_draw_fringe_bitmap (w, row, p)
762 struct window *w;
763 struct glyph_row *row;
764 struct draw_fringe_bitmap_params *p;
766 struct frame *f = XFRAME (WINDOW_FRAME (w));
767 HDC hdc;
768 struct face *face = p->face;
769 int rowY;
771 hdc = get_frame_dc (f);
773 if (!p->overlay_p)
775 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
777 /* If the fringe is adjacent to the left (right) scroll bar of a
778 leftmost (rightmost, respectively) window, then extend its
779 background to the gap between the fringe and the bar. */
780 if ((WINDOW_LEFTMOST_P (w)
781 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
782 || (WINDOW_RIGHTMOST_P (w)
783 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
785 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
787 if (sb_width > 0)
789 int left = WINDOW_SCROLL_BAR_AREA_X (w);
790 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
791 * FRAME_COLUMN_WIDTH (f));
793 if (bx < 0)
795 /* Bitmap fills the fringe. */
796 if (left + width == p->x)
797 bx = left + sb_width;
798 else if (p->x + p->wd == left)
799 bx = left;
800 if (bx >= 0)
802 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
804 nx = width - sb_width;
805 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
806 row->y));
807 ny = row->visible_height;
810 else
812 if (left + width == bx)
814 bx = left + sb_width;
815 nx += width - sb_width;
817 else if (bx + nx == left)
818 nx += width - sb_width;
823 if (bx >= 0 && nx > 0)
824 w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
827 /* Must clip because of partially visible lines. */
828 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
829 if (p->y < rowY)
831 /* Adjust position of "bottom aligned" bitmap on partially
832 visible last row. */
833 int oldY = row->y;
834 int oldVH = row->visible_height;
835 row->visible_height = p->h;
836 row->y -= rowY - p->y;
837 w32_clip_to_row (w, row, -1, hdc);
838 row->y = oldY;
839 row->visible_height = oldVH;
841 else
842 w32_clip_to_row (w, row, -1, hdc);
844 if (p->which && p->which < max_fringe_bmp)
846 HBITMAP pixmap = fringe_bmp[p->which];
847 HDC compat_hdc;
848 HANDLE horig_obj;
850 compat_hdc = CreateCompatibleDC (hdc);
852 SaveDC (hdc);
854 horig_obj = SelectObject (compat_hdc, pixmap);
856 /* Paint overlays transparently. */
857 if (p->overlay_p)
859 HBRUSH h_brush, h_orig_brush;
861 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
862 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
863 h_brush = CreateSolidBrush (face->foreground);
864 h_orig_brush = SelectObject (hdc, h_brush);
866 BitBlt (hdc, p->x, p->y, p->wd, p->h,
867 compat_hdc, 0, p->dh,
868 DSTINVERT);
869 BitBlt (hdc, p->x, p->y, p->wd, p->h,
870 compat_hdc, 0, p->dh,
871 0x2E064A);
872 BitBlt (hdc, p->x, p->y, p->wd, p->h,
873 compat_hdc, 0, p->dh,
874 DSTINVERT);
876 SelectObject (hdc, h_orig_brush);
877 DeleteObject (h_brush);
879 else
881 SetTextColor (hdc, face->background);
882 SetBkColor (hdc, (p->cursor_p
883 ? f->output_data.w32->cursor_pixel
884 : face->foreground));
886 BitBlt (hdc, p->x, p->y, p->wd, p->h,
887 compat_hdc, 0, p->dh,
888 SRCCOPY);
891 SelectObject (compat_hdc, horig_obj);
892 DeleteDC (compat_hdc);
893 RestoreDC (hdc, -1);
896 w32_set_clip_rectangle (hdc, NULL);
898 release_frame_dc (f, hdc);
901 static void
902 w32_define_fringe_bitmap (which, bits, h, wd)
903 int which;
904 unsigned short *bits;
905 int h, wd;
907 if (which >= max_fringe_bmp)
909 int i = max_fringe_bmp;
910 max_fringe_bmp = which + 20;
911 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
912 while (i < max_fringe_bmp)
913 fringe_bmp[i++] = 0;
916 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
919 static void
920 w32_destroy_fringe_bitmap (which)
921 int which;
923 if (which >= max_fringe_bmp)
924 return;
926 if (fringe_bmp[which])
927 DeleteObject (fringe_bmp[which]);
928 fringe_bmp[which] = 0;
933 /* This is called when starting Emacs and when restarting after
934 suspend. When starting Emacs, no window is mapped. And nothing
935 must be done to Emacs's own window if it is suspended (though that
936 rarely happens). */
938 static void
939 w32_set_terminal_modes (struct terminal *term)
943 /* This is called when exiting or suspending Emacs. Exiting will make
944 the W32 windows go away, and suspending requires no action. */
946 static void
947 w32_reset_terminal_modes (struct terminal *term)
953 /***********************************************************************
954 Display Iterator
955 ***********************************************************************/
957 /* Function prototypes of this page. */
959 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
960 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
961 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
962 int));
963 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
964 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
965 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
966 static void x_draw_glyph_string P_ ((struct glyph_string *));
967 static void x_set_cursor_gc P_ ((struct glyph_string *));
968 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
969 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
970 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
971 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
972 double, int, COLORREF));
973 static void x_setup_relief_colors P_ ((struct glyph_string *));
974 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
975 static void x_draw_image_relief P_ ((struct glyph_string *));
976 static void x_draw_image_foreground P_ ((struct glyph_string *));
977 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
978 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
979 int, int, int));
980 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
981 int, int, int, int, int, int,
982 RECT *));
983 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
984 int, int, int, RECT *));
987 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
988 face. */
990 static void
991 x_set_cursor_gc (s)
992 struct glyph_string *s;
994 if (s->font == FRAME_FONT (s->f)
995 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
996 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
997 && !s->cmp)
998 s->gc = s->f->output_data.w32->cursor_gc;
999 else
1001 /* Cursor on non-default face: must merge. */
1002 XGCValues xgcv;
1003 unsigned long mask;
1005 xgcv.background = s->f->output_data.w32->cursor_pixel;
1006 xgcv.foreground = s->face->background;
1008 /* If the glyph would be invisible, try a different foreground. */
1009 if (xgcv.foreground == xgcv.background)
1010 xgcv.foreground = s->face->foreground;
1011 if (xgcv.foreground == xgcv.background)
1012 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1013 if (xgcv.foreground == xgcv.background)
1014 xgcv.foreground = s->face->foreground;
1016 /* Make sure the cursor is distinct from text in this face. */
1017 if (xgcv.background == s->face->background
1018 && xgcv.foreground == s->face->foreground)
1020 xgcv.background = s->face->foreground;
1021 xgcv.foreground = s->face->background;
1024 IF_DEBUG (x_check_font (s->f, s->font));
1025 xgcv.font = s->font;
1026 mask = GCForeground | GCBackground | GCFont;
1028 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1029 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1030 mask, &xgcv);
1031 else
1032 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1033 = XCreateGC (NULL, s->window, mask, &xgcv);
1035 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1040 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1042 static void
1043 x_set_mouse_face_gc (s)
1044 struct glyph_string *s;
1046 int face_id;
1047 struct face *face;
1049 /* What face has to be used last for the mouse face? */
1050 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
1051 face = FACE_FROM_ID (s->f, face_id);
1052 if (face == NULL)
1053 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1055 if (s->first_glyph->type == CHAR_GLYPH)
1056 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
1057 else
1058 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
1059 s->face = FACE_FROM_ID (s->f, face_id);
1060 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1062 /* If font in this face is same as S->font, use it. */
1063 if (s->font == s->face->font)
1064 s->gc = s->face->gc;
1065 else
1067 /* Otherwise construct scratch_cursor_gc with values from FACE
1068 but font FONT. */
1069 XGCValues xgcv;
1070 unsigned long mask;
1072 xgcv.background = s->face->background;
1073 xgcv.foreground = s->face->foreground;
1074 IF_DEBUG (x_check_font (s->f, s->font));
1075 xgcv.font = s->font;
1076 mask = GCForeground | GCBackground | GCFont;
1078 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1079 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1080 mask, &xgcv);
1081 else
1082 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1083 = XCreateGC (NULL, s->window, mask, &xgcv);
1085 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1088 xassert (s->gc != 0);
1092 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1093 Faces to use in the mode line have already been computed when the
1094 matrix was built, so there isn't much to do, here. */
1096 static INLINE void
1097 x_set_mode_line_face_gc (s)
1098 struct glyph_string *s;
1100 s->gc = s->face->gc;
1104 /* Set S->gc of glyph string S for drawing that glyph string. Set
1105 S->stippled_p to a non-zero value if the face of S has a stipple
1106 pattern. */
1108 static INLINE void
1109 x_set_glyph_string_gc (s)
1110 struct glyph_string *s;
1112 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1114 if (s->hl == DRAW_NORMAL_TEXT)
1116 s->gc = s->face->gc;
1117 s->stippled_p = s->face->stipple != 0;
1119 else if (s->hl == DRAW_INVERSE_VIDEO)
1121 x_set_mode_line_face_gc (s);
1122 s->stippled_p = s->face->stipple != 0;
1124 else if (s->hl == DRAW_CURSOR)
1126 x_set_cursor_gc (s);
1127 s->stippled_p = 0;
1129 else if (s->hl == DRAW_MOUSE_FACE)
1131 x_set_mouse_face_gc (s);
1132 s->stippled_p = s->face->stipple != 0;
1134 else if (s->hl == DRAW_IMAGE_RAISED
1135 || s->hl == DRAW_IMAGE_SUNKEN)
1137 s->gc = s->face->gc;
1138 s->stippled_p = s->face->stipple != 0;
1140 else
1142 s->gc = s->face->gc;
1143 s->stippled_p = s->face->stipple != 0;
1146 /* GC must have been set. */
1147 xassert (s->gc != 0);
1151 /* Set clipping for output of glyph string S. S may be part of a mode
1152 line or menu if we don't have X toolkit support. */
1154 static INLINE void
1155 x_set_glyph_string_clipping (s)
1156 struct glyph_string *s;
1158 RECT *r = s->clip;
1159 int n = get_glyph_string_clip_rects (s, r, 2);
1161 if (n == 1)
1162 w32_set_clip_rectangle (s->hdc, r);
1163 else if (n > 1)
1165 HRGN full_clip, clip1, clip2;
1166 clip1 = CreateRectRgnIndirect (r);
1167 clip2 = CreateRectRgnIndirect (r + 1);
1168 if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
1170 SelectClipRgn (s->hdc, full_clip);
1172 DeleteObject (clip1);
1173 DeleteObject (clip2);
1174 DeleteObject (full_clip);
1176 s->num_clips = n;
1179 /* Set SRC's clipping for output of glyph string DST. This is called
1180 when we are drawing DST's left_overhang or right_overhang only in
1181 the area of SRC. */
1183 static void
1184 x_set_glyph_string_clipping_exactly (src, dst)
1185 struct glyph_string *src, *dst;
1187 RECT r;
1189 r.left = src->x;
1190 r.right = r.left + src->width;
1191 r.top = src->y;
1192 r.bottom = r.top + src->height;
1193 dst->clip[0] = r;
1194 dst->num_clips = 1;
1195 w32_set_clip_rectangle (dst->hdc, &r);
1198 /* RIF:
1199 Compute left and right overhang of glyph string S. */
1201 static void
1202 w32_compute_glyph_string_overhangs (s)
1203 struct glyph_string *s;
1205 if (s->cmp == NULL
1206 && s->first_glyph->type == CHAR_GLYPH
1207 && !s->font_not_found_p)
1209 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1210 struct font *font = s->font;
1211 struct font_metrics metrics;
1212 int i;
1214 for (i = 0; i < s->nchars; i++)
1215 code[i] = s->char2b[i];
1216 font->driver->text_extents (font, code, s->nchars, &metrics);
1217 s->right_overhang = (metrics.rbearing > metrics.width
1218 ? metrics.rbearing - metrics.width : 0);
1219 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
1221 else if (s->cmp)
1223 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1224 s->left_overhang = -s->cmp->lbearing;
1228 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1230 static INLINE void
1231 x_clear_glyph_string_rect (s, x, y, w, h)
1232 struct glyph_string *s;
1233 int x, y, w, h;
1235 int real_x = x;
1236 int real_y = y;
1237 int real_w = w;
1238 int real_h = h;
1239 #if 0
1240 /* Take clipping into account. */
1241 if (s->gc->clip_mask == Rect)
1243 real_x = max (real_x, s->gc->clip_rectangle.left);
1244 real_y = max (real_y, s->gc->clip_rectangle.top);
1245 real_w = min (real_w, s->gc->clip_rectangle.right
1246 - s->gc->clip_rectangle.left);
1247 real_h = min (real_h, s->gc->clip_rectangle.bottom
1248 - s->gc->clip_rectangle.top);
1250 #endif
1251 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1252 real_w, real_h);
1256 /* Draw the background of glyph_string S. If S->background_filled_p
1257 is non-zero don't draw it. FORCE_P non-zero means draw the
1258 background even if it wouldn't be drawn normally. This is used
1259 when a string preceding S draws into the background of S, or S
1260 contains the first component of a composition. */
1262 static void
1263 x_draw_glyph_string_background (s, force_p)
1264 struct glyph_string *s;
1265 int force_p;
1267 /* Nothing to do if background has already been drawn or if it
1268 shouldn't be drawn in the first place. */
1269 if (!s->background_filled_p)
1271 int box_line_width = max (s->face->box_line_width, 0);
1273 #if 0 /* TODO: stipple */
1274 if (s->stippled_p)
1276 /* Fill background with a stipple pattern. */
1277 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1278 XFillRectangle (s->display, s->window, s->gc, s->x,
1279 s->y + box_line_width,
1280 s->background_width,
1281 s->height - 2 * box_line_width);
1282 XSetFillStyle (s->display, s->gc, FillSolid);
1283 s->background_filled_p = 1;
1285 else
1286 #endif
1287 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1288 || s->font_not_found_p
1289 || s->extends_to_end_of_line_p
1290 || force_p)
1292 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1293 s->background_width,
1294 s->height - 2 * box_line_width);
1295 s->background_filled_p = 1;
1301 /* Draw the foreground of glyph string S. */
1303 static void
1304 x_draw_glyph_string_foreground (s)
1305 struct glyph_string *s;
1307 int i, x;
1309 /* If first glyph of S has a left box line, start drawing the text
1310 of S to the right of that box line. */
1311 if (s->face->box != FACE_NO_BOX
1312 && s->first_glyph->left_box_line_p)
1313 x = s->x + eabs (s->face->box_line_width);
1314 else
1315 x = s->x;
1317 SetTextColor (s->hdc, s->gc->foreground);
1318 SetBkColor (s->hdc, s->gc->background);
1319 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1321 /* Draw characters of S as rectangles if S's font could not be
1322 loaded. */
1323 if (s->font_not_found_p)
1325 for (i = 0; i < s->nchars; ++i)
1327 struct glyph *g = s->first_glyph + i;
1329 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1330 s->height - 1);
1331 x += g->pixel_width;
1334 else
1336 struct font *font = s->font;
1337 int boff = font->baseline_offset;
1338 int y;
1339 HFONT old_font;
1341 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1343 if (font->vertical_centering)
1344 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1346 y = s->ybase - boff;
1347 if (s->for_overlaps
1348 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1349 font->driver->draw (s, 0, s->nchars, x, y, 0);
1350 else
1351 font->driver->draw (s, 0, s->nchars, x, y, 1);
1352 if (s->face->overstrike)
1353 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
1355 SelectObject (s->hdc, old_font);
1359 /* Draw the foreground of composite glyph string S. */
1361 static void
1362 x_draw_composite_glyph_string_foreground (s)
1363 struct glyph_string *s;
1365 int i, j, x;
1366 struct font *font = s->font;
1368 /* If first glyph of S has a left box line, start drawing the text
1369 of S to the right of that box line. */
1370 if (s->face && s->face->box != FACE_NO_BOX
1371 && s->first_glyph->left_box_line_p)
1372 x = s->x + eabs (s->face->box_line_width);
1373 else
1374 x = s->x;
1376 /* S is a glyph string for a composition. S->cmp_from is the index
1377 of the first character drawn for glyphs of this composition.
1378 S->cmp_from == 0 means we are drawing the very first character of
1379 this composition. */
1381 SetTextColor (s->hdc, s->gc->foreground);
1382 SetBkColor (s->hdc, s->gc->background);
1383 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1385 /* Draw a rectangle for the composition if the font for the very
1386 first character of the composition could not be loaded. */
1387 if (s->font_not_found_p)
1389 if (s->cmp_from == 0)
1390 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1391 s->height - 1);
1393 else if (! s->first_glyph->u.cmp.automatic)
1395 int y = s->ybase;
1396 int width = 0;
1397 HFONT old_font;
1399 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1401 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1402 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1404 int xx = x + s->cmp->offsets[j * 2];
1405 int yy = y - s->cmp->offsets[j * 2 + 1];
1407 font->driver->draw (s, j, j + 1, xx, yy, 0);
1408 if (s->face->overstrike)
1409 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1411 SelectObject (s->hdc, old_font);
1413 else
1415 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1416 Lisp_Object glyph;
1417 int y = s->ybase;
1418 int width = 0;
1419 HFONT old_font;
1421 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1423 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1425 glyph = LGSTRING_GLYPH (gstring, i);
1426 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1427 width += LGLYPH_WIDTH (glyph);
1428 else
1430 int xoff, yoff, wadjust;
1432 if (j < i)
1434 font->driver->draw (s, j, i, x, y, 0);
1435 x += width;
1437 xoff = LGLYPH_XOFF (glyph);
1438 yoff = LGLYPH_YOFF (glyph);
1439 wadjust = LGLYPH_WADJUST (glyph);
1440 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
1441 x += wadjust;
1442 j = i + 1;
1443 width = 0;
1446 if (j < i)
1447 font->driver->draw (s, j, i, x, y, 0);
1449 SelectObject (s->hdc, old_font);
1454 /* Brightness beyond which a color won't have its highlight brightness
1455 boosted.
1457 Nominally, highlight colors for `3d' faces are calculated by
1458 brightening an object's color by a constant scale factor, but this
1459 doesn't yield good results for dark colors, so for colors who's
1460 brightness is less than this value (on a scale of 0-255) have to
1461 use an additional additive factor.
1463 The value here is set so that the default menu-bar/mode-line color
1464 (grey75) will not have its highlights changed at all. */
1465 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1468 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
1469 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1470 If this produces the same color as COLOR, try a color where all RGB
1471 values have DELTA added. Return the allocated color in *COLOR.
1472 DISPLAY is the X display, CMAP is the colormap to operate on.
1473 Value is non-zero if successful. */
1475 static int
1476 w32_alloc_lighter_color (f, color, factor, delta)
1477 struct frame *f;
1478 COLORREF *color;
1479 double factor;
1480 int delta;
1482 COLORREF new;
1483 long bright;
1485 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1486 delta /= 256;
1488 /* Change RGB values by specified FACTOR. Avoid overflow! */
1489 xassert (factor >= 0);
1490 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1491 min (0xff, factor * GetGValue (*color)),
1492 min (0xff, factor * GetBValue (*color)));
1494 /* Calculate brightness of COLOR. */
1495 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1496 + GetBValue (*color)) / 6;
1498 /* We only boost colors that are darker than
1499 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1500 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1501 /* Make an additive adjustment to NEW, because it's dark enough so
1502 that scaling by FACTOR alone isn't enough. */
1504 /* How far below the limit this color is (0 - 1, 1 being darker). */
1505 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1506 /* The additive adjustment. */
1507 int min_delta = delta * dimness * factor / 2;
1509 if (factor < 1)
1510 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1511 max (0, min (0xff, min_delta - GetGValue (*color))),
1512 max (0, min (0xff, min_delta - GetBValue (*color))));
1513 else
1514 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1515 max (0, min (0xff, min_delta + GetGValue (*color))),
1516 max (0, min (0xff, min_delta + GetBValue (*color))));
1519 if (new == *color)
1520 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1521 max (0, min (0xff, delta + GetGValue (*color))),
1522 max (0, min (0xff, delta + GetBValue (*color))));
1524 /* TODO: Map to palette and retry with delta if same? */
1525 /* TODO: Free colors (if using palette)? */
1527 if (new == *color)
1528 return 0;
1530 *color = new;
1532 return 1;
1535 /* On frame F, translate pixel colors to RGB values for the NCOLORS
1536 colors in COLORS. On W32, we no longer try to map colors to
1537 a palette. */
1538 void
1539 x_query_colors (f, colors, ncolors)
1540 struct frame *f;
1541 XColor *colors;
1542 int ncolors;
1544 int i;
1546 for (i = 0; i < ncolors; i++)
1548 DWORD pixel = colors[i].pixel;
1549 /* Convert to a 16 bit value in range 0 - 0xffff. */
1550 colors[i].red = GetRValue (pixel) * 257;
1551 colors[i].green = GetGValue (pixel) * 257;
1552 colors[i].blue = GetBValue (pixel) * 257;
1556 void
1557 x_query_color (f, color)
1558 struct frame *f;
1559 XColor *color;
1561 x_query_colors (f, color, 1);
1565 /* Set up the foreground color for drawing relief lines of glyph
1566 string S. RELIEF is a pointer to a struct relief containing the GC
1567 with which lines will be drawn. Use a color that is FACTOR or
1568 DELTA lighter or darker than the relief's background which is found
1569 in S->f->output_data.x->relief_background. If such a color cannot
1570 be allocated, use DEFAULT_PIXEL, instead. */
1572 static void
1573 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1574 struct frame *f;
1575 struct relief *relief;
1576 double factor;
1577 int delta;
1578 COLORREF default_pixel;
1580 XGCValues xgcv;
1581 struct w32_output *di = f->output_data.w32;
1582 unsigned long mask = GCForeground;
1583 COLORREF pixel;
1584 COLORREF background = di->relief_background;
1585 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1587 /* TODO: Free colors (if using palette)? */
1589 /* Allocate new color. */
1590 xgcv.foreground = default_pixel;
1591 pixel = background;
1592 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1594 relief->allocated_p = 1;
1595 xgcv.foreground = relief->pixel = pixel;
1598 if (relief->gc == 0)
1600 #if 0 /* TODO: stipple */
1601 xgcv.stipple = dpyinfo->gray;
1602 mask |= GCStipple;
1603 #endif
1604 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1606 else
1607 XChangeGC (NULL, relief->gc, mask, &xgcv);
1611 /* Set up colors for the relief lines around glyph string S. */
1613 static void
1614 x_setup_relief_colors (s)
1615 struct glyph_string *s;
1617 struct w32_output *di = s->f->output_data.w32;
1618 COLORREF color;
1620 if (s->face->use_box_color_for_shadows_p)
1621 color = s->face->box_color;
1622 else if (s->first_glyph->type == IMAGE_GLYPH
1623 && s->img->pixmap
1624 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1625 color = IMAGE_BACKGROUND (s->img, s->f, 0);
1626 else
1627 color = s->gc->background;
1629 if (di->white_relief.gc == 0
1630 || color != di->relief_background)
1632 di->relief_background = color;
1633 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1634 WHITE_PIX_DEFAULT (s->f));
1635 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1636 BLACK_PIX_DEFAULT (s->f));
1641 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
1642 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1643 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1644 relief. LEFT_P non-zero means draw a relief on the left side of
1645 the rectangle. RIGHT_P non-zero means draw a relief on the right
1646 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1647 when drawing. */
1649 static void
1650 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1651 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
1652 struct frame *f;
1653 int left_x, top_y, right_x, bottom_y, width;
1654 int top_p, bot_p, left_p, right_p, raised_p;
1655 RECT *clip_rect;
1657 int i;
1658 XGCValues gc;
1659 HDC hdc = get_frame_dc (f);
1661 if (raised_p)
1662 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1663 else
1664 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1666 w32_set_clip_rectangle (hdc, clip_rect);
1668 /* Top. */
1669 if (top_p)
1670 for (i = 0; i < width; ++i)
1671 w32_fill_area (f, hdc, gc.foreground,
1672 left_x + i * left_p, top_y + i,
1673 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1675 /* Left. */
1676 if (left_p)
1677 for (i = 0; i < width; ++i)
1678 w32_fill_area (f, hdc, gc.foreground,
1679 left_x + i, top_y + i, 1,
1680 bottom_y - top_y - 2 * i + 1);
1682 if (raised_p)
1683 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
1684 else
1685 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
1687 /* Bottom. */
1688 if (bot_p)
1689 for (i = 0; i < width; ++i)
1690 w32_fill_area (f, hdc, gc.foreground,
1691 left_x + i * left_p, bottom_y - i,
1692 right_x - left_x - i * (left_p + right_p) + 1, 1);
1694 /* Right. */
1695 if (right_p)
1696 for (i = 0; i < width; ++i)
1697 w32_fill_area (f, hdc, gc.foreground,
1698 right_x - i, top_y + i + 1, 1,
1699 bottom_y - top_y - 2 * i - 1);
1701 w32_set_clip_rectangle (hdc, NULL);
1703 release_frame_dc (f, hdc);
1707 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1708 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1709 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1710 left side of the rectangle. RIGHT_P non-zero means draw a line
1711 on the right side of the rectangle. CLIP_RECT is the clipping
1712 rectangle to use when drawing. */
1714 static void
1715 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1716 left_p, right_p, clip_rect)
1717 struct glyph_string *s;
1718 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
1719 RECT *clip_rect;
1721 w32_set_clip_rectangle (s->hdc, clip_rect);
1723 /* Top. */
1724 w32_fill_area (s->f, s->hdc, s->face->box_color,
1725 left_x, top_y, right_x - left_x + 1, width);
1727 /* Left. */
1728 if (left_p)
1730 w32_fill_area (s->f, s->hdc, s->face->box_color,
1731 left_x, top_y, width, bottom_y - top_y + 1);
1734 /* Bottom. */
1735 w32_fill_area (s->f, s->hdc, s->face->box_color,
1736 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
1738 /* Right. */
1739 if (right_p)
1741 w32_fill_area (s->f, s->hdc, s->face->box_color,
1742 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
1745 w32_set_clip_rectangle (s->hdc, NULL);
1749 /* Draw a box around glyph string S. */
1751 static void
1752 x_draw_glyph_string_box (s)
1753 struct glyph_string *s;
1755 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1756 int left_p, right_p;
1757 struct glyph *last_glyph;
1758 RECT clip_rect;
1760 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1761 ? WINDOW_RIGHT_EDGE_X (s->w)
1762 : window_box_right (s->w, s->area));
1764 /* The glyph that may have a right box line. */
1765 last_glyph = (s->cmp || s->img
1766 ? s->first_glyph
1767 : s->first_glyph + s->nchars - 1);
1769 width = eabs (s->face->box_line_width);
1770 raised_p = s->face->box == FACE_RAISED_BOX;
1771 left_x = s->x;
1772 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
1773 ? last_x - 1
1774 : min (last_x, s->x + s->background_width) - 1));
1775 top_y = s->y;
1776 bottom_y = top_y + s->height - 1;
1778 left_p = (s->first_glyph->left_box_line_p
1779 || (s->hl == DRAW_MOUSE_FACE
1780 && (s->prev == NULL
1781 || s->prev->hl != s->hl)));
1782 right_p = (last_glyph->right_box_line_p
1783 || (s->hl == DRAW_MOUSE_FACE
1784 && (s->next == NULL
1785 || s->next->hl != s->hl)));
1787 get_glyph_string_clip_rect (s, &clip_rect);
1789 if (s->face->box == FACE_SIMPLE_BOX)
1790 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1791 left_p, right_p, &clip_rect);
1792 else
1794 x_setup_relief_colors (s);
1795 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
1796 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
1801 /* Draw foreground of image glyph string S. */
1803 static void
1804 x_draw_image_foreground (s)
1805 struct glyph_string *s;
1807 int x = s->x;
1808 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1810 /* If first glyph of S has a left box line, start drawing it to the
1811 right of that line. */
1812 if (s->face->box != FACE_NO_BOX
1813 && s->first_glyph->left_box_line_p
1814 && s->slice.x == 0)
1815 x += eabs (s->face->box_line_width);
1817 /* If there is a margin around the image, adjust x- and y-position
1818 by that margin. */
1819 if (s->slice.x == 0)
1820 x += s->img->hmargin;
1821 if (s->slice.y == 0)
1822 y += s->img->vmargin;
1824 SaveDC (s->hdc);
1826 if (s->img->pixmap)
1828 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1829 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1830 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1831 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1832 SetBkColor (compat_hdc, RGB (255, 255, 255));
1833 SetTextColor (s->hdc, RGB (0, 0, 0));
1834 x_set_glyph_string_clipping (s);
1836 if (s->img->mask)
1838 HDC mask_dc = CreateCompatibleDC (s->hdc);
1839 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1841 SetTextColor (s->hdc, RGB (255, 255, 255));
1842 SetBkColor (s->hdc, RGB (0, 0, 0));
1844 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1845 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1846 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1847 mask_dc, s->slice.x, s->slice.y, SRCAND);
1848 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1849 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1851 SelectObject (mask_dc, mask_orig_obj);
1852 DeleteDC (mask_dc);
1854 else
1856 SetTextColor (s->hdc, s->gc->foreground);
1857 SetBkColor (s->hdc, s->gc->background);
1859 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1860 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
1862 /* When the image has a mask, we can expect that at
1863 least part of a mouse highlight or a block cursor will
1864 be visible. If the image doesn't have a mask, make
1865 a block cursor visible by drawing a rectangle around
1866 the image. I believe it's looking better if we do
1867 nothing here for mouse-face. */
1868 if (s->hl == DRAW_CURSOR)
1870 int r = s->img->relief;
1871 if (r < 0) r = -r;
1872 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
1873 s->slice.width + r*2 - 1,
1874 s->slice.height + r*2 - 1);
1878 w32_set_clip_rectangle (s->hdc, NULL);
1879 SelectObject (s->hdc, orig_brush);
1880 DeleteObject (fg_brush);
1881 SelectObject (compat_hdc, orig_obj);
1882 DeleteDC (compat_hdc);
1884 else
1885 w32_draw_rectangle (s->hdc, s->gc, x, y,
1886 s->slice.width - 1, s->slice.height - 1);
1888 RestoreDC (s->hdc ,-1);
1892 /* Draw a relief around the image glyph string S. */
1894 static void
1895 x_draw_image_relief (s)
1896 struct glyph_string *s;
1898 int x0, y0, x1, y1, thick, raised_p;
1899 RECT r;
1900 int x = s->x;
1901 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
1903 /* If first glyph of S has a left box line, start drawing it to the
1904 right of that line. */
1905 if (s->face->box != FACE_NO_BOX
1906 && s->first_glyph->left_box_line_p
1907 && s->slice.x == 0)
1908 x += eabs (s->face->box_line_width);
1910 /* If there is a margin around the image, adjust x- and y-position
1911 by that margin. */
1912 if (s->slice.x == 0)
1913 x += s->img->hmargin;
1914 if (s->slice.y == 0)
1915 y += s->img->vmargin;
1917 if (s->hl == DRAW_IMAGE_SUNKEN
1918 || s->hl == DRAW_IMAGE_RAISED)
1920 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
1921 raised_p = s->hl == DRAW_IMAGE_RAISED;
1923 else
1925 thick = eabs (s->img->relief);
1926 raised_p = s->img->relief > 0;
1929 x0 = x - thick;
1930 y0 = y - thick;
1931 x1 = x + s->slice.width + thick - 1;
1932 y1 = y + s->slice.height + thick - 1;
1934 x_setup_relief_colors (s);
1935 get_glyph_string_clip_rect (s, &r);
1936 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
1937 s->slice.y == 0,
1938 s->slice.y + s->slice.height == s->img->height,
1939 s->slice.x == 0,
1940 s->slice.x + s->slice.width == s->img->width,
1941 &r);
1945 /* Draw the foreground of image glyph string S to PIXMAP. */
1947 static void
1948 w32_draw_image_foreground_1 (s, pixmap)
1949 struct glyph_string *s;
1950 HBITMAP pixmap;
1952 HDC hdc = CreateCompatibleDC (s->hdc);
1953 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
1954 int x = 0;
1955 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1957 /* If first glyph of S has a left box line, start drawing it to the
1958 right of that line. */
1959 if (s->face->box != FACE_NO_BOX
1960 && s->first_glyph->left_box_line_p
1961 && s->slice.x == 0)
1962 x += eabs (s->face->box_line_width);
1964 /* If there is a margin around the image, adjust x- and y-position
1965 by that margin. */
1966 if (s->slice.x == 0)
1967 x += s->img->hmargin;
1968 if (s->slice.y == 0)
1969 y += s->img->vmargin;
1971 if (s->img->pixmap)
1973 HDC compat_hdc = CreateCompatibleDC (hdc);
1974 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1975 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
1976 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1978 if (s->img->mask)
1980 HDC mask_dc = CreateCompatibleDC (hdc);
1981 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1983 SetTextColor (hdc, RGB (0, 0, 0));
1984 SetBkColor (hdc, RGB (255, 255, 255));
1985 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1986 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1987 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1988 mask_dc, s->slice.x, s->slice.y, SRCAND);
1989 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
1990 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1992 SelectObject (mask_dc, mask_orig_obj);
1993 DeleteDC (mask_dc);
1995 else
1997 SetTextColor (hdc, s->gc->foreground);
1998 SetBkColor (hdc, s->gc->background);
2000 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2001 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
2003 /* When the image has a mask, we can expect that at
2004 least part of a mouse highlight or a block cursor will
2005 be visible. If the image doesn't have a mask, make
2006 a block cursor visible by drawing a rectangle around
2007 the image. I believe it's looking better if we do
2008 nothing here for mouse-face. */
2009 if (s->hl == DRAW_CURSOR)
2011 int r = s->img->relief;
2012 if (r < 0) r = -r;
2013 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2014 s->slice.width + r*2 - 1,
2015 s->slice.height + r*2 - 1);
2019 SelectObject (hdc, orig_brush);
2020 DeleteObject (fg_brush);
2021 SelectObject (compat_hdc, orig_obj);
2022 DeleteDC (compat_hdc);
2024 else
2025 w32_draw_rectangle (hdc, s->gc, x, y,
2026 s->slice.width - 1, s->slice.height - 1);
2028 SelectObject (hdc, orig_hdc_obj);
2029 DeleteDC (hdc);
2033 /* Draw part of the background of glyph string S. X, Y, W, and H
2034 give the rectangle to draw. */
2036 static void
2037 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2038 struct glyph_string *s;
2039 int x, y, w, h;
2041 #if 0 /* TODO: stipple */
2042 if (s->stippled_p)
2044 /* Fill background with a stipple pattern. */
2045 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2046 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2047 XSetFillStyle (s->display, s->gc, FillSolid);
2049 else
2050 #endif
2051 x_clear_glyph_string_rect (s, x, y, w, h);
2055 /* Draw image glyph string S.
2057 s->y
2058 s->x +-------------------------
2059 | s->face->box
2061 | +-------------------------
2062 | | s->img->vmargin
2064 | | +-------------------
2065 | | | the image
2069 static void
2070 x_draw_image_glyph_string (s)
2071 struct glyph_string *s;
2073 int x, y;
2074 int box_line_hwidth = eabs (s->face->box_line_width);
2075 int box_line_vwidth = max (s->face->box_line_width, 0);
2076 int height;
2077 HBITMAP pixmap = 0;
2079 height = s->height - 2 * box_line_vwidth;
2081 /* Fill background with face under the image. Do it only if row is
2082 taller than image or if image has a clip mask to reduce
2083 flickering. */
2084 s->stippled_p = s->face->stipple != 0;
2085 if (height > s->slice.height
2086 || s->img->hmargin
2087 || s->img->vmargin
2088 || s->img->mask
2089 || s->img->pixmap == 0
2090 || s->width != s->background_width)
2092 x = s->x;
2093 if (s->first_glyph->left_box_line_p
2094 && s->slice.x == 0)
2095 x += box_line_hwidth;
2097 y = s->y;
2098 if (s->slice.y == 0)
2099 y += box_line_vwidth;
2101 #if 0 /* TODO: figure out if we need to do this on Windows. */
2102 if (s->img->mask)
2104 /* Create a pixmap as large as the glyph string. Fill it
2105 with the background color. Copy the image to it, using
2106 its mask. Copy the temporary pixmap to the display. */
2107 Screen *screen = FRAME_X_SCREEN (s->f);
2108 int depth = DefaultDepthOfScreen (screen);
2110 /* Create a pixmap as large as the glyph string. */
2111 pixmap = XCreatePixmap (s->display, s->window,
2112 s->background_width,
2113 s->height, depth);
2115 /* Don't clip in the following because we're working on the
2116 pixmap. */
2117 XSetClipMask (s->display, s->gc, None);
2119 /* Fill the pixmap with the background color/stipple. */
2120 if (s->stippled_p)
2122 /* Fill background with a stipple pattern. */
2123 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2124 XFillRectangle (s->display, pixmap, s->gc,
2125 0, 0, s->background_width, s->height);
2126 XSetFillStyle (s->display, s->gc, FillSolid);
2128 else
2130 XGCValues xgcv;
2131 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2132 &xgcv);
2133 XSetForeground (s->display, s->gc, xgcv.background);
2134 XFillRectangle (s->display, pixmap, s->gc,
2135 0, 0, s->background_width, s->height);
2136 XSetForeground (s->display, s->gc, xgcv.foreground);
2139 else
2140 #endif
2141 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2143 s->background_filled_p = 1;
2146 /* Draw the foreground. */
2147 if (pixmap != 0)
2149 w32_draw_image_foreground_1 (s, pixmap);
2150 x_set_glyph_string_clipping (s);
2152 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2153 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2154 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2155 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2157 SetTextColor (s->hdc, s->gc->foreground);
2158 SetBkColor (s->hdc, s->gc->background);
2159 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2160 compat_hdc, 0, 0, SRCCOPY);
2162 SelectObject (s->hdc, orig_brush);
2163 DeleteObject (fg_brush);
2164 SelectObject (compat_hdc, orig_obj);
2165 DeleteDC (compat_hdc);
2167 DeleteObject (pixmap);
2168 pixmap = 0;
2170 else
2171 x_draw_image_foreground (s);
2173 /* If we must draw a relief around the image, do it. */
2174 if (s->img->relief
2175 || s->hl == DRAW_IMAGE_RAISED
2176 || s->hl == DRAW_IMAGE_SUNKEN)
2177 x_draw_image_relief (s);
2181 /* Draw stretch glyph string S. */
2183 static void
2184 x_draw_stretch_glyph_string (s)
2185 struct glyph_string *s;
2187 xassert (s->first_glyph->type == STRETCH_GLYPH);
2189 if (s->hl == DRAW_CURSOR
2190 && !x_stretch_cursor_p)
2192 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2193 as wide as the stretch glyph. */
2194 int width, background_width = s->background_width;
2195 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2197 if (x < left_x)
2199 background_width -= left_x - x;
2200 x = left_x;
2202 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
2204 /* Draw cursor. */
2205 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
2207 /* Clear rest using the GC of the original non-cursor face. */
2208 if (width < background_width)
2210 XGCValues *gc = s->face->gc;
2211 int y = s->y;
2212 int w = background_width - width, h = s->height;
2213 RECT r;
2214 HDC hdc = s->hdc;
2216 x += width;
2217 if (s->row->mouse_face_p
2218 && cursor_in_mouse_face_p (s->w))
2220 x_set_mouse_face_gc (s);
2221 gc = s->gc;
2223 else
2224 gc = s->face->gc;
2226 get_glyph_string_clip_rect (s, &r);
2227 w32_set_clip_rectangle (hdc, &r);
2229 #if 0 /* TODO: stipple */
2230 if (s->face->stipple)
2232 /* Fill background with a stipple pattern. */
2233 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2234 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2235 XSetFillStyle (s->display, gc, FillSolid);
2237 else
2238 #endif
2240 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2244 else if (!s->background_filled_p)
2246 int background_width = s->background_width;
2247 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2249 /* Don't draw into left margin, fringe or scrollbar area
2250 except for header line and mode line. */
2251 if (x < left_x && !s->row->mode_line_p)
2253 background_width -= left_x - x;
2254 x = left_x;
2256 if (background_width > 0)
2257 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
2260 s->background_filled_p = 1;
2264 /* Draw glyph string S. */
2266 static void
2267 x_draw_glyph_string (s)
2268 struct glyph_string *s;
2270 int relief_drawn_p = 0;
2272 /* If S draws into the background of its successor, draw the
2273 background of the successor first so that S can draw into it.
2274 This makes S->next use XDrawString instead of XDrawImageString. */
2275 if (s->next && s->right_overhang && !s->for_overlaps)
2277 int width;
2278 struct glyph_string *next;
2279 for (width = 0, next = s->next;
2280 next && width < s->right_overhang;
2281 width += next->width, next = next->next)
2282 if (next->first_glyph->type != IMAGE_GLYPH)
2284 x_set_glyph_string_gc (next);
2285 x_set_glyph_string_clipping (next);
2286 if (next->first_glyph->type == STRETCH_GLYPH)
2287 x_draw_stretch_glyph_string (next);
2288 else
2289 x_draw_glyph_string_background (next, 1);
2290 next->num_clips = 0;
2294 /* Set up S->gc, set clipping and draw S. */
2295 x_set_glyph_string_gc (s);
2297 /* Draw relief (if any) in advance for char/composition so that the
2298 glyph string can be drawn over it. */
2299 if (!s->for_overlaps
2300 && s->face->box != FACE_NO_BOX
2301 && (s->first_glyph->type == CHAR_GLYPH
2302 || s->first_glyph->type == COMPOSITE_GLYPH))
2305 x_set_glyph_string_clipping (s);
2306 x_draw_glyph_string_background (s, 1);
2307 x_draw_glyph_string_box (s);
2308 x_set_glyph_string_clipping (s);
2309 relief_drawn_p = 1;
2311 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2312 && !s->clip_tail
2313 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2314 || (s->next && s->next->hl != s->hl && s->right_overhang)))
2315 /* We must clip just this glyph. left_overhang part has already
2316 drawn when s->prev was drawn, and right_overhang part will be
2317 drawn later when s->next is drawn. */
2318 x_set_glyph_string_clipping_exactly (s, s);
2319 else
2320 x_set_glyph_string_clipping (s);
2322 switch (s->first_glyph->type)
2324 case IMAGE_GLYPH:
2325 x_draw_image_glyph_string (s);
2326 break;
2328 case STRETCH_GLYPH:
2329 x_draw_stretch_glyph_string (s);
2330 break;
2332 case CHAR_GLYPH:
2333 if (s->for_overlaps)
2334 s->background_filled_p = 1;
2335 else
2336 x_draw_glyph_string_background (s, 0);
2337 x_draw_glyph_string_foreground (s);
2338 break;
2340 case COMPOSITE_GLYPH:
2341 if (s->for_overlaps || (s->cmp_from > 0
2342 && ! s->first_glyph->u.cmp.automatic))
2343 s->background_filled_p = 1;
2344 else
2345 x_draw_glyph_string_background (s, 1);
2346 x_draw_composite_glyph_string_foreground (s);
2347 break;
2349 default:
2350 abort ();
2353 if (!s->for_overlaps)
2355 /* Draw underline. */
2356 if (s->face->underline_p)
2358 unsigned long thickness, position;
2359 int y;
2361 if (s->prev && s->prev->face->underline_p)
2363 /* We use the same underline style as the previous one. */
2364 thickness = s->prev->underline_thickness;
2365 position = s->prev->underline_position;
2367 else
2369 /* Get the underline thickness. Default is 1 pixel. */
2370 if (s->font && s->font->underline_thickness > 0)
2371 thickness = s->font->underline_thickness;
2372 else
2373 thickness = 1;
2374 if (x_underline_at_descent_line)
2375 position = (s->height - thickness) - (s->ybase - s->y);
2376 else
2378 /* Get the underline position. This is the recommended
2379 vertical offset in pixels from the baseline to the top of
2380 the underline. This is a signed value according to the
2381 specs, and its default is
2383 ROUND ((maximum_descent) / 2), with
2384 ROUND (x) = floor (x + 0.5) */
2386 if (x_use_underline_position_properties
2387 && s->font && s->font->underline_position >= 0)
2388 position = s->font->underline_position;
2389 else if (s->font)
2390 position = (s->font->descent + 1) / 2;
2392 position = max (position, underline_minimum_offset);
2394 /* Check the sanity of thickness and position. We should
2395 avoid drawing underline out of the current line area. */
2396 if (s->y + s->height <= s->ybase + position)
2397 position = (s->height - 1) - (s->ybase - s->y);
2398 if (s->y + s->height < s->ybase + position + thickness)
2399 thickness = (s->y + s->height) - (s->ybase + position);
2400 s->underline_thickness = thickness;
2401 s->underline_position =position;
2402 y = s->ybase + position;
2403 if (s->face->underline_defaulted_p)
2405 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2406 y, s->width, 1);
2408 else
2410 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2411 y, s->width, 1);
2414 /* Draw overline. */
2415 if (s->face->overline_p)
2417 unsigned long dy = 0, h = 1;
2419 if (s->face->overline_color_defaulted_p)
2421 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2422 s->y + dy, s->width, h);
2424 else
2426 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
2427 s->y + dy, s->width, h);
2431 /* Draw strike-through. */
2432 if (s->face->strike_through_p
2433 && !FONT_TEXTMETRIC(s->font).tmStruckOut)
2435 unsigned long h = 1;
2436 unsigned long dy = (s->height - h) / 2;
2438 if (s->face->strike_through_color_defaulted_p)
2440 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2441 s->width, h);
2443 else
2445 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
2446 s->y + dy, s->width, h);
2450 /* Draw relief if not yet drawn. */
2451 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2452 x_draw_glyph_string_box (s);
2454 if (s->prev)
2456 struct glyph_string *prev;
2458 for (prev = s->prev; prev; prev = prev->prev)
2459 if (prev->hl != s->hl
2460 && prev->x + prev->width + prev->right_overhang > s->x)
2462 /* As prev was drawn while clipped to its own area, we
2463 must draw the right_overhang part using s->hl now. */
2464 enum draw_glyphs_face save = prev->hl;
2466 prev->hl = s->hl;
2467 x_set_glyph_string_gc (prev);
2468 x_set_glyph_string_clipping_exactly (s, prev);
2469 if (prev->first_glyph->type == CHAR_GLYPH)
2470 x_draw_glyph_string_foreground (prev);
2471 else
2472 x_draw_composite_glyph_string_foreground (prev);
2473 w32_set_clip_rectangle (prev->hdc, NULL);
2474 prev->hl = save;
2475 prev->num_clips = 0;
2479 if (s->next)
2481 struct glyph_string *next;
2483 for (next = s->next; next; next = next->next)
2484 if (next->hl != s->hl
2485 && next->x - next->left_overhang < s->x + s->width)
2487 /* As next will be drawn while clipped to its own area,
2488 we must draw the left_overhang part using s->hl now. */
2489 enum draw_glyphs_face save = next->hl;
2491 next->hl = s->hl;
2492 x_set_glyph_string_gc (next);
2493 x_set_glyph_string_clipping_exactly (s, next);
2494 if (next->first_glyph->type == CHAR_GLYPH)
2495 x_draw_glyph_string_foreground (next);
2496 else
2497 x_draw_composite_glyph_string_foreground (next);
2498 w32_set_clip_rectangle (next->hdc, NULL);
2499 next->hl = save;
2500 next->num_clips = 0;
2505 /* Reset clipping. */
2506 w32_set_clip_rectangle (s->hdc, NULL);
2507 s->num_clips = 0;
2511 /* Shift display to make room for inserted glyphs. */
2513 void
2514 w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2515 struct frame *f;
2516 int x, y, width, height, shift_by;
2518 HDC hdc;
2520 hdc = get_frame_dc (f);
2521 BitBlt (hdc, x + shift_by, y, width, height,
2522 hdc, x, y, SRCCOPY);
2524 release_frame_dc (f, hdc);
2528 /* Delete N glyphs at the nominal cursor position. Not implemented
2529 for X frames. */
2531 static void
2532 x_delete_glyphs (f, n)
2533 struct frame *f;
2534 register int n;
2536 if (! FRAME_W32_P (f))
2537 return;
2539 abort ();
2543 /* Clear entire frame. If updating_frame is non-null, clear that
2544 frame. Otherwise clear the selected frame. */
2546 static void
2547 x_clear_frame (struct frame *f)
2549 if (! FRAME_W32_P (f))
2550 return;
2552 /* Clearing the frame will erase any cursor, so mark them all as no
2553 longer visible. */
2554 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2555 output_cursor.hpos = output_cursor.vpos = 0;
2556 output_cursor.x = -1;
2558 /* We don't set the output cursor here because there will always
2559 follow an explicit cursor_to. */
2560 BLOCK_INPUT;
2562 w32_clear_window (f);
2564 /* We have to clear the scroll bars, too. If we have changed
2565 colors or something like that, then they should be notified. */
2566 x_scroll_bar_clear (f);
2568 UNBLOCK_INPUT;
2572 /* Make audible bell. */
2574 static void
2575 w32_ring_bell (struct frame *f)
2577 BLOCK_INPUT;
2579 if (FRAME_W32_P (f) && visible_bell)
2581 int i;
2582 HWND hwnd = FRAME_W32_WINDOW (f);
2584 for (i = 0; i < 5; i++)
2586 FlashWindow (hwnd, TRUE);
2587 Sleep (10);
2589 FlashWindow (hwnd, FALSE);
2591 else
2592 w32_sys_ring_bell (f);
2594 UNBLOCK_INPUT;
2598 /* Specify how many text lines, from the top of the window,
2599 should be affected by insert-lines and delete-lines operations.
2600 This, and those operations, are used only within an update
2601 that is bounded by calls to x_update_begin and x_update_end. */
2603 static void
2604 w32_set_terminal_window (n)
2605 register int n;
2607 /* This function intentionally left blank. */
2611 /***********************************************************************
2612 Line Dance
2613 ***********************************************************************/
2615 /* Perform an insert-lines or delete-lines operation, inserting N
2616 lines or deleting -N lines at vertical position VPOS. */
2618 static void
2619 x_ins_del_lines (f, vpos, n)
2620 struct frame *f;
2621 int vpos, n;
2623 if (! FRAME_W32_P (f))
2624 return;
2626 abort ();
2630 /* Scroll part of the display as described by RUN. */
2632 static void
2633 x_scroll_run (w, run)
2634 struct window *w;
2635 struct run *run;
2637 struct frame *f = XFRAME (w->frame);
2638 int x, y, width, height, from_y, to_y, bottom_y;
2639 HWND hwnd = FRAME_W32_WINDOW (f);
2640 HRGN expect_dirty;
2642 /* Get frame-relative bounding box of the text display area of W,
2643 without mode lines. Include in this box the left and right
2644 fringes of W. */
2645 window_box (w, -1, &x, &y, &width, &height);
2647 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2648 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2649 bottom_y = y + height;
2651 if (to_y < from_y)
2653 /* Scrolling up. Make sure we don't copy part of the mode
2654 line at the bottom. */
2655 if (from_y + run->height > bottom_y)
2656 height = bottom_y - from_y;
2657 else
2658 height = run->height;
2659 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
2661 else
2663 /* Scolling down. Make sure we don't copy over the mode line.
2664 at the bottom. */
2665 if (to_y + run->height > bottom_y)
2666 height = bottom_y - to_y;
2667 else
2668 height = run->height;
2669 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
2672 BLOCK_INPUT;
2674 /* Cursor off. Will be switched on again in x_update_window_end. */
2675 updated_window = w;
2676 x_clear_cursor (w);
2679 RECT from;
2680 RECT to;
2681 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2682 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2684 from.left = to.left = x;
2685 from.right = to.right = x + width;
2686 from.top = from_y;
2687 from.bottom = from_y + height;
2688 to.top = y;
2689 to.bottom = bottom_y;
2691 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2692 NULL, SW_INVALIDATE);
2694 /* Combine this with what we expect to be dirty. This covers the
2695 case where not all of the region we expect is actually dirty. */
2696 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2698 /* If the dirty region is not what we expected, redraw the entire frame. */
2699 if (!EqualRgn (combined, expect_dirty))
2700 SET_FRAME_GARBAGED (f);
2702 DeleteObject (dirty);
2703 DeleteObject (combined);
2706 UNBLOCK_INPUT;
2707 DeleteObject (expect_dirty);
2712 /***********************************************************************
2713 Exposure Events
2714 ***********************************************************************/
2716 static void
2717 frame_highlight (f)
2718 struct frame *f;
2720 x_update_cursor (f, 1);
2721 x_set_frame_alpha (f);
2724 static void
2725 frame_unhighlight (f)
2726 struct frame *f;
2728 x_update_cursor (f, 1);
2729 x_set_frame_alpha (f);
2732 /* The focus has changed. Update the frames as necessary to reflect
2733 the new situation. Note that we can't change the selected frame
2734 here, because the Lisp code we are interrupting might become confused.
2735 Each event gets marked with the frame in which it occurred, so the
2736 Lisp code can tell when the switch took place by examining the events. */
2738 static void
2739 x_new_focus_frame (dpyinfo, frame)
2740 struct w32_display_info *dpyinfo;
2741 struct frame *frame;
2743 struct frame *old_focus = dpyinfo->w32_focus_frame;
2745 if (frame != dpyinfo->w32_focus_frame)
2747 /* Set this before calling other routines, so that they see
2748 the correct value of w32_focus_frame. */
2749 dpyinfo->w32_focus_frame = frame;
2751 if (old_focus && old_focus->auto_lower)
2752 x_lower_frame (old_focus);
2754 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2755 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2756 else
2757 pending_autoraise_frame = 0;
2760 x_frame_rehighlight (dpyinfo);
2764 /* Handle FocusIn and FocusOut state changes for FRAME.
2765 If FRAME has focus and there exists more than one frame, puts
2766 a FOCUS_IN_EVENT into *BUFP. */
2768 static void
2769 x_focus_changed (type, state, dpyinfo, frame, bufp)
2770 int type;
2771 int state;
2772 struct w32_display_info *dpyinfo;
2773 struct frame *frame;
2774 struct input_event *bufp;
2776 if (type == WM_SETFOCUS)
2778 if (dpyinfo->w32_focus_event_frame != frame)
2780 x_new_focus_frame (dpyinfo, frame);
2781 dpyinfo->w32_focus_event_frame = frame;
2783 /* Don't stop displaying the initial startup message
2784 for a switch-frame event we don't need. */
2785 if (NILP (Vterminal_frame)
2786 && CONSP (Vframe_list)
2787 && !NILP (XCDR (Vframe_list)))
2789 bufp->kind = FOCUS_IN_EVENT;
2790 XSETFRAME (bufp->frame_or_window, frame);
2794 frame->output_data.x->focus_state |= state;
2796 /* TODO: IME focus? */
2798 else if (type == WM_KILLFOCUS)
2800 frame->output_data.x->focus_state &= ~state;
2802 if (dpyinfo->w32_focus_event_frame == frame)
2804 dpyinfo->w32_focus_event_frame = 0;
2805 x_new_focus_frame (dpyinfo, 0);
2808 /* TODO: IME focus? */
2813 /* The focus may have changed. Figure out if it is a real focus change,
2814 by checking both FocusIn/Out and Enter/LeaveNotify events.
2816 Returns FOCUS_IN_EVENT event in *BUFP. */
2818 static void
2819 w32_detect_focus_change (dpyinfo, event, bufp)
2820 struct w32_display_info *dpyinfo;
2821 W32Msg *event;
2822 struct input_event *bufp;
2824 struct frame *frame;
2826 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2827 if (! frame)
2828 return;
2830 /* On w32, this is only called from focus events, so no switch needed. */
2831 x_focus_changed (event->msg.message,
2832 (event->msg.message == WM_KILLFOCUS ?
2833 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2834 dpyinfo, frame, bufp);
2838 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2840 void
2841 x_mouse_leave (dpyinfo)
2842 struct w32_display_info *dpyinfo;
2844 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
2847 /* The focus has changed, or we have redirected a frame's focus to
2848 another frame (this happens when a frame uses a surrogate
2849 mini-buffer frame). Shift the highlight as appropriate.
2851 The FRAME argument doesn't necessarily have anything to do with which
2852 frame is being highlighted or un-highlighted; we only use it to find
2853 the appropriate X display info. */
2855 static void
2856 w32_frame_rehighlight (frame)
2857 struct frame *frame;
2859 if (! FRAME_W32_P (frame))
2860 return;
2861 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
2864 static void
2865 x_frame_rehighlight (dpyinfo)
2866 struct w32_display_info *dpyinfo;
2868 struct frame *old_highlight = dpyinfo->x_highlight_frame;
2870 if (dpyinfo->w32_focus_frame)
2872 dpyinfo->x_highlight_frame
2873 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
2874 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2875 : dpyinfo->w32_focus_frame);
2876 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
2878 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
2879 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
2882 else
2883 dpyinfo->x_highlight_frame = 0;
2885 if (dpyinfo->x_highlight_frame != old_highlight)
2887 if (old_highlight)
2888 frame_unhighlight (old_highlight);
2889 if (dpyinfo->x_highlight_frame)
2890 frame_highlight (dpyinfo->x_highlight_frame);
2894 /* Keyboard processing - modifier keys, etc. */
2896 /* Convert a keysym to its name. */
2898 char *
2899 x_get_keysym_name (keysym)
2900 int keysym;
2902 /* Make static so we can always return it */
2903 static char value[100];
2905 BLOCK_INPUT;
2906 GetKeyNameText (keysym, value, 100);
2907 UNBLOCK_INPUT;
2909 return value;
2912 static int codepage_for_locale(LCID locale)
2914 char cp[20];
2916 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
2917 return atoi (cp);
2918 else
2919 return CP_ACP;
2923 /* Mouse clicks and mouse movement. Rah. */
2925 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
2926 the state in PUP. XBUTTON provides extra information for extended mouse
2927 button messages. Returns FALSE if unable to parse the message. */
2928 BOOL
2929 parse_button (message, xbutton, pbutton, pup)
2930 int message;
2931 int xbutton;
2932 int * pbutton;
2933 int * pup;
2935 int button = 0;
2936 int up = 0;
2938 switch (message)
2940 case WM_LBUTTONDOWN:
2941 button = 0;
2942 up = 0;
2943 break;
2944 case WM_LBUTTONUP:
2945 button = 0;
2946 up = 1;
2947 break;
2948 case WM_MBUTTONDOWN:
2949 if (NILP (Vw32_swap_mouse_buttons))
2950 button = 1;
2951 else
2952 button = 2;
2953 up = 0;
2954 break;
2955 case WM_MBUTTONUP:
2956 if (NILP (Vw32_swap_mouse_buttons))
2957 button = 1;
2958 else
2959 button = 2;
2960 up = 1;
2961 break;
2962 case WM_RBUTTONDOWN:
2963 if (NILP (Vw32_swap_mouse_buttons))
2964 button = 2;
2965 else
2966 button = 1;
2967 up = 0;
2968 break;
2969 case WM_RBUTTONUP:
2970 if (NILP (Vw32_swap_mouse_buttons))
2971 button = 2;
2972 else
2973 button = 1;
2974 up = 1;
2975 break;
2976 case WM_XBUTTONDOWN:
2977 button = xbutton + 2;
2978 up = 0;
2979 break;
2980 case WM_XBUTTONUP:
2981 button = xbutton + 2;
2982 up = 1;
2983 break;
2984 default:
2985 return (FALSE);
2988 if (pup) *pup = up;
2989 if (pbutton) *pbutton = button;
2991 return (TRUE);
2995 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2997 If the event is a button press, then note that we have grabbed
2998 the mouse. */
3000 static Lisp_Object
3001 construct_mouse_click (result, msg, f)
3002 struct input_event *result;
3003 W32Msg *msg;
3004 struct frame *f;
3006 int button;
3007 int up;
3009 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3010 &button, &up);
3012 /* Make the event type NO_EVENT; we'll change that when we decide
3013 otherwise. */
3014 result->kind = MOUSE_CLICK_EVENT;
3015 result->code = button;
3016 result->timestamp = msg->msg.time;
3017 result->modifiers = (msg->dwModifiers
3018 | (up
3019 ? up_modifier
3020 : down_modifier));
3022 XSETINT (result->x, LOWORD (msg->msg.lParam));
3023 XSETINT (result->y, HIWORD (msg->msg.lParam));
3024 XSETFRAME (result->frame_or_window, f);
3025 result->arg = Qnil;
3026 return Qnil;
3029 static Lisp_Object
3030 construct_mouse_wheel (result, msg, f)
3031 struct input_event *result;
3032 W32Msg *msg;
3033 struct frame *f;
3035 POINT p;
3036 int delta;
3038 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3039 : WHEEL_EVENT;
3040 result->code = 0;
3041 result->timestamp = msg->msg.time;
3043 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3044 forward, away from the user (up); a negative value indicates that
3045 the wheel was rotated backward, toward the user (down). */
3046 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3048 /* The up and down modifiers indicate if the wheel was rotated up or
3049 down based on WHEEL_DELTA value. */
3050 result->modifiers = (msg->dwModifiers
3051 | ((delta < 0 ) ? down_modifier : up_modifier));
3053 /* With multiple monitors, we can legitimately get negative
3054 coordinates, so cast to short to interpret them correctly. */
3055 p.x = (short) LOWORD (msg->msg.lParam);
3056 p.y = (short) HIWORD (msg->msg.lParam);
3057 ScreenToClient (msg->msg.hwnd, &p);
3058 XSETINT (result->x, p.x);
3059 XSETINT (result->y, p.y);
3060 XSETFRAME (result->frame_or_window, f);
3061 result->arg = Qnil;
3062 return Qnil;
3065 static Lisp_Object
3066 construct_drag_n_drop (result, msg, f)
3067 struct input_event *result;
3068 W32Msg *msg;
3069 struct frame *f;
3071 Lisp_Object files;
3072 Lisp_Object frame;
3073 HDROP hdrop;
3074 POINT p;
3075 WORD num_files;
3076 char *name;
3077 int i, len;
3079 result->kind = DRAG_N_DROP_EVENT;
3080 result->code = 0;
3081 result->timestamp = msg->msg.time;
3082 result->modifiers = msg->dwModifiers;
3084 hdrop = (HDROP) msg->msg.wParam;
3085 DragQueryPoint (hdrop, &p);
3087 #if 0
3088 p.x = LOWORD (msg->msg.lParam);
3089 p.y = HIWORD (msg->msg.lParam);
3090 ScreenToClient (msg->msg.hwnd, &p);
3091 #endif
3093 XSETINT (result->x, p.x);
3094 XSETINT (result->y, p.y);
3096 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3097 files = Qnil;
3099 for (i = 0; i < num_files; i++)
3101 len = DragQueryFile (hdrop, i, NULL, 0);
3102 if (len <= 0)
3103 continue;
3104 name = alloca (len + 1);
3105 DragQueryFile (hdrop, i, name, len + 1);
3106 files = Fcons (DECODE_FILE (build_string (name)), files);
3109 DragFinish (hdrop);
3111 XSETFRAME (frame, f);
3112 result->frame_or_window = frame;
3113 result->arg = files;
3114 return Qnil;
3118 /* Function to report a mouse movement to the mainstream Emacs code.
3119 The input handler calls this.
3121 We have received a mouse movement event, which is given in *event.
3122 If the mouse is over a different glyph than it was last time, tell
3123 the mainstream emacs code by setting mouse_moved. If not, ask for
3124 another motion event, so we can check again the next time it moves. */
3126 static MSG last_mouse_motion_event;
3127 static Lisp_Object last_mouse_motion_frame;
3129 static int
3130 note_mouse_movement (frame, msg)
3131 FRAME_PTR frame;
3132 MSG *msg;
3134 int mouse_x = LOWORD (msg->lParam);
3135 int mouse_y = HIWORD (msg->lParam);
3137 last_mouse_movement_time = msg->time;
3138 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3139 XSETFRAME (last_mouse_motion_frame, frame);
3141 if (!FRAME_X_OUTPUT (frame))
3142 return 0;
3144 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3146 frame->mouse_moved = 1;
3147 last_mouse_scroll_bar = Qnil;
3148 note_mouse_highlight (frame, -1, -1);
3149 last_mouse_glyph_frame = 0;
3150 return 1;
3153 /* Has the mouse moved off the glyph it was on at the last sighting? */
3154 if (frame != last_mouse_glyph_frame
3155 || mouse_x < last_mouse_glyph.left
3156 || mouse_x >= last_mouse_glyph.right
3157 || mouse_y < last_mouse_glyph.top
3158 || mouse_y >= last_mouse_glyph.bottom)
3160 frame->mouse_moved = 1;
3161 last_mouse_scroll_bar = Qnil;
3162 note_mouse_highlight (frame, mouse_x, mouse_y);
3163 /* Remember the mouse position here, as w32_mouse_position only
3164 gets called when mouse tracking is enabled but we also need
3165 to keep track of the mouse for help_echo and highlighting at
3166 other times. */
3167 remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
3168 last_mouse_glyph_frame = frame;
3169 return 1;
3172 return 0;
3176 /************************************************************************
3177 Mouse Face
3178 ************************************************************************/
3180 static struct scroll_bar *x_window_to_scroll_bar ();
3181 static void x_scroll_bar_report_motion ();
3182 static void x_check_fullscreen P_ ((struct frame *));
3184 static void
3185 redo_mouse_highlight ()
3187 if (!NILP (last_mouse_motion_frame)
3188 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3189 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3190 LOWORD (last_mouse_motion_event.lParam),
3191 HIWORD (last_mouse_motion_event.lParam));
3194 static void
3195 w32_define_cursor (window, cursor)
3196 Window window;
3197 Cursor cursor;
3199 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3201 /* Return the current position of the mouse.
3202 *fp should be a frame which indicates which display to ask about.
3204 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3205 and *part to the frame, window, and scroll bar part that the mouse
3206 is over. Set *x and *y to the portion and whole of the mouse's
3207 position on the scroll bar.
3209 If the mouse movement started elsewhere, set *fp to the frame the
3210 mouse is on, *bar_window to nil, and *x and *y to the character cell
3211 the mouse is over.
3213 Set *time to the server time-stamp for the time at which the mouse
3214 was at this position.
3216 Don't store anything if we don't have a valid set of values to report.
3218 This clears the mouse_moved flag, so we can wait for the next mouse
3219 movement. */
3221 static void
3222 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
3223 FRAME_PTR *fp;
3224 int insist;
3225 Lisp_Object *bar_window;
3226 enum scroll_bar_part *part;
3227 Lisp_Object *x, *y;
3228 unsigned long *time;
3230 FRAME_PTR f1;
3232 BLOCK_INPUT;
3234 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3235 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3236 else
3238 POINT pt;
3240 Lisp_Object frame, tail;
3242 /* Clear the mouse-moved flag for every frame on this display. */
3243 FOR_EACH_FRAME (tail, frame)
3244 XFRAME (frame)->mouse_moved = 0;
3246 last_mouse_scroll_bar = Qnil;
3248 GetCursorPos (&pt);
3250 /* Now we have a position on the root; find the innermost window
3251 containing the pointer. */
3253 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
3254 && FRAME_LIVE_P (last_mouse_frame))
3256 /* If mouse was grabbed on a frame, give coords for that frame
3257 even if the mouse is now outside it. */
3258 f1 = last_mouse_frame;
3260 else
3262 /* Is window under mouse one of our frames? */
3263 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
3264 WindowFromPoint (pt));
3267 /* If not, is it one of our scroll bars? */
3268 if (! f1)
3270 struct scroll_bar *bar
3271 = x_window_to_scroll_bar (WindowFromPoint (pt));
3273 if (bar)
3275 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3279 if (f1 == 0 && insist > 0)
3280 f1 = SELECTED_FRAME ();
3282 if (f1)
3284 /* Ok, we found a frame. Store all the values.
3285 last_mouse_glyph is a rectangle used to reduce the
3286 generation of mouse events. To not miss any motion
3287 events, we must divide the frame into rectangles of the
3288 size of the smallest character that could be displayed
3289 on it, i.e. into the same rectangles that matrices on
3290 the frame are divided into. */
3292 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
3293 remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
3294 last_mouse_glyph_frame = f1;
3296 *bar_window = Qnil;
3297 *part = 0;
3298 *fp = f1;
3299 XSETINT (*x, pt.x);
3300 XSETINT (*y, pt.y);
3301 *time = last_mouse_movement_time;
3306 UNBLOCK_INPUT;
3310 /***********************************************************************
3311 Tool-bars
3312 ***********************************************************************/
3314 /* Handle mouse button event on the tool-bar of frame F, at
3315 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3316 or ButtonRelase. */
3318 static void
3319 w32_handle_tool_bar_click (f, button_event)
3320 struct frame *f;
3321 struct input_event *button_event;
3323 int x = XFASTINT (button_event->x);
3324 int y = XFASTINT (button_event->y);
3326 if (button_event->modifiers & down_modifier)
3327 handle_tool_bar_click (f, x, y, 1, 0);
3328 else
3329 handle_tool_bar_click (f, x, y, 0,
3330 button_event->modifiers & ~up_modifier);
3335 /***********************************************************************
3336 Scroll bars
3337 ***********************************************************************/
3339 /* Scroll bar support. */
3341 /* Given a window ID, find the struct scroll_bar which manages it.
3342 This can be called in GC, so we have to make sure to strip off mark
3343 bits. */
3345 static struct scroll_bar *
3346 x_window_to_scroll_bar (window_id)
3347 Window window_id;
3349 Lisp_Object tail;
3351 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
3353 Lisp_Object frame, bar, condemned;
3355 frame = XCAR (tail);
3356 /* All elements of Vframe_list should be frames. */
3357 if (! FRAMEP (frame))
3358 abort ();
3360 /* Scan this frame's scroll bar list for a scroll bar with the
3361 right window ID. */
3362 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3363 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3364 /* This trick allows us to search both the ordinary and
3365 condemned scroll bar lists with one loop. */
3366 ! NILP (bar) || (bar = condemned,
3367 condemned = Qnil,
3368 ! NILP (bar));
3369 bar = XSCROLL_BAR (bar)->next)
3370 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
3371 return XSCROLL_BAR (bar);
3374 return 0;
3379 /* Set the thumb size and position of scroll bar BAR. We are currently
3380 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3382 static void
3383 w32_set_scroll_bar_thumb (bar, portion, position, whole)
3384 struct scroll_bar *bar;
3385 int portion, position, whole;
3387 Window w = SCROLL_BAR_W32_WINDOW (bar);
3388 /* We use the whole scroll-bar height in the calculations below, to
3389 avoid strange effects like scrolling backwards when just clicking
3390 on the handle (without moving it). */
3391 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
3392 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3393 int sb_page, sb_pos;
3394 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
3395 SCROLLINFO si;
3397 /* We used to change the nPage setting while dragging the handle,
3398 but that had very strange effects (such as scrolling backwards
3399 while dragging downwards).
3401 Now, we don't change the nPage setting while dragging unless we
3402 get near to the end of the buffer, in which case we often have to
3403 resize the handle to "go all the way". */
3405 if (draggingp)
3407 int near_bottom_p;
3408 BLOCK_INPUT;
3409 si.cbSize = sizeof (si);
3410 si.fMask = SIF_POS | SIF_PAGE;
3411 GetScrollInfo(w, SB_CTL, &si);
3412 near_bottom_p = si.nPos + si.nPage >= range;
3413 UNBLOCK_INPUT;
3414 if (!near_bottom_p)
3415 return;
3418 if (whole)
3420 /* Position scroll bar at rock bottom if the bottom of the
3421 buffer is visible. This avoids shinking the thumb away
3422 to nothing if it is held at the bottom of the buffer. */
3423 if (position + portion >= whole && !draggingp)
3425 sb_page = range * (whole - position) / whole;
3426 sb_pos = range;
3428 else
3430 sb_pos = position * range / whole;
3431 sb_page = (min (portion, (whole - position)) * range) / whole;
3434 else
3436 sb_page = range;
3437 sb_pos = 0;
3440 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3442 BLOCK_INPUT;
3444 si.cbSize = sizeof (si);
3445 si.fMask = SIF_PAGE | SIF_POS;
3446 si.nPage = sb_page;
3447 si.nPos = sb_pos;
3449 SetScrollInfo (w, SB_CTL, &si, TRUE);
3451 UNBLOCK_INPUT;
3455 /************************************************************************
3456 Scroll bars, general
3457 ************************************************************************/
3459 static HWND
3460 my_create_scrollbar (f, bar)
3461 struct frame * f;
3462 struct scroll_bar * bar;
3464 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
3465 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
3466 (LPARAM) bar);
3469 /*#define ATTACH_THREADS*/
3471 static BOOL
3472 my_show_window (FRAME_PTR f, HWND hwnd, int how)
3474 #ifndef ATTACH_THREADS
3475 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3476 (WPARAM) hwnd, (LPARAM) how);
3477 #else
3478 return ShowWindow (hwnd, how);
3479 #endif
3482 static void
3483 my_set_window_pos (HWND hwnd, HWND hwndAfter,
3484 int x, int y, int cx, int cy, UINT flags)
3486 #ifndef ATTACH_THREADS
3487 WINDOWPOS pos;
3488 pos.hwndInsertAfter = hwndAfter;
3489 pos.x = x;
3490 pos.y = y;
3491 pos.cx = cx;
3492 pos.cy = cy;
3493 pos.flags = flags;
3494 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3495 #else
3496 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3497 #endif
3500 static void
3501 my_set_focus (f, hwnd)
3502 struct frame * f;
3503 HWND hwnd;
3505 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
3506 (WPARAM) hwnd, 0);
3509 static void
3510 my_set_foreground_window (hwnd)
3511 HWND hwnd;
3513 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3517 static void
3518 my_destroy_window (f, hwnd)
3519 struct frame * f;
3520 HWND hwnd;
3522 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
3523 (WPARAM) hwnd, 0);
3526 /* Create a scroll bar and return the scroll bar vector for it. W is
3527 the Emacs window on which to create the scroll bar. TOP, LEFT,
3528 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
3529 scroll bar. */
3531 static struct scroll_bar *
3532 x_scroll_bar_create (w, top, left, width, height)
3533 struct window *w;
3534 int top, left, width, height;
3536 struct frame *f = XFRAME (WINDOW_FRAME (w));
3537 HWND hwnd;
3538 SCROLLINFO si;
3539 struct scroll_bar *bar
3540 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3542 BLOCK_INPUT;
3544 XSETWINDOW (bar->window, w);
3545 XSETINT (bar->top, top);
3546 XSETINT (bar->left, left);
3547 XSETINT (bar->width, width);
3548 XSETINT (bar->height, height);
3549 XSETINT (bar->start, 0);
3550 XSETINT (bar->end, 0);
3551 bar->dragging = Qnil;
3552 bar->fringe_extended_p = Qnil;
3554 /* Requires geometry to be set before call to create the real window */
3556 hwnd = my_create_scrollbar (f, bar);
3558 si.cbSize = sizeof (si);
3559 si.fMask = SIF_ALL;
3560 si.nMin = 0;
3561 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3562 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3563 si.nPage = si.nMax;
3564 si.nPos = 0;
3566 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3568 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
3570 /* Add bar to its frame's list of scroll bars. */
3571 bar->next = FRAME_SCROLL_BARS (f);
3572 bar->prev = Qnil;
3573 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3574 if (! NILP (bar->next))
3575 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3577 UNBLOCK_INPUT;
3579 return bar;
3583 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3584 nil. */
3586 static void
3587 x_scroll_bar_remove (bar)
3588 struct scroll_bar *bar;
3590 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3592 BLOCK_INPUT;
3594 /* Destroy the window. */
3595 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
3597 /* Disassociate this scroll bar from its window. */
3598 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3600 UNBLOCK_INPUT;
3603 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3604 that we are displaying PORTION characters out of a total of WHOLE
3605 characters, starting at POSITION. If WINDOW has no scroll bar,
3606 create one. */
3607 static void
3608 w32_set_vertical_scroll_bar (w, portion, whole, position)
3609 struct window *w;
3610 int portion, whole, position;
3612 struct frame *f = XFRAME (w->frame);
3613 struct scroll_bar *bar;
3614 int top, height, left, sb_left, width, sb_width;
3615 int window_y, window_height;
3616 int fringe_extended_p;
3618 /* Get window dimensions. */
3619 window_box (w, -1, 0, &window_y, 0, &window_height);
3620 top = window_y;
3621 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3622 height = window_height;
3624 /* Compute the left edge of the scroll bar area. */
3625 left = WINDOW_SCROLL_BAR_AREA_X (w);
3627 /* Compute the width of the scroll bar which might be less than
3628 the width of the area reserved for the scroll bar. */
3629 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3630 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3631 else
3632 sb_width = width;
3634 /* Compute the left edge of the scroll bar. */
3635 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3636 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
3637 else
3638 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
3640 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
3641 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
3642 && WINDOW_LEFT_FRINGE_WIDTH (w)
3643 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3644 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
3645 else
3646 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
3647 && WINDOW_RIGHT_FRINGE_WIDTH (w)
3648 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
3649 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
3651 /* Does the scroll bar exist yet? */
3652 if (NILP (w->vertical_scroll_bar))
3654 HDC hdc;
3655 BLOCK_INPUT;
3656 if (width > 0 && height > 0)
3658 hdc = get_frame_dc (f);
3659 if (fringe_extended_p)
3660 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3661 else
3662 w32_clear_area (f, hdc, left, top, width, height);
3663 release_frame_dc (f, hdc);
3665 UNBLOCK_INPUT;
3667 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
3669 else
3671 /* It may just need to be moved and resized. */
3672 HWND hwnd;
3674 bar = XSCROLL_BAR (w->vertical_scroll_bar);
3675 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3677 /* If already correctly positioned, do nothing. */
3678 if ( XINT (bar->left) == sb_left
3679 && XINT (bar->top) == top
3680 && XINT (bar->width) == sb_width
3681 && XINT (bar->height) == height
3682 && !NILP (bar->fringe_extended_p) == fringe_extended_p )
3684 /* Redraw after clear_frame. */
3685 if (!my_show_window (f, hwnd, SW_NORMAL))
3686 InvalidateRect (hwnd, NULL, FALSE);
3688 else
3690 HDC hdc;
3691 SCROLLINFO si;
3693 BLOCK_INPUT;
3694 if (width && height)
3696 hdc = get_frame_dc (f);
3697 /* Since Windows scroll bars are smaller than the space reserved
3698 for them on the frame, we have to clear "under" them. */
3699 if (fringe_extended_p)
3700 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3701 else
3702 w32_clear_area (f, hdc, left, top, width, height);
3703 release_frame_dc (f, hdc);
3705 /* Make sure scroll bar is "visible" before moving, to ensure the
3706 area of the parent window now exposed will be refreshed. */
3707 my_show_window (f, hwnd, SW_HIDE);
3708 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3709 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3710 max (height, 1), TRUE);
3712 si.cbSize = sizeof (si);
3713 si.fMask = SIF_RANGE;
3714 si.nMin = 0;
3715 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3716 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3718 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
3720 my_show_window (f, hwnd, SW_NORMAL);
3721 /* InvalidateRect (w, NULL, FALSE); */
3723 /* Remember new settings. */
3724 XSETINT (bar->left, sb_left);
3725 XSETINT (bar->top, top);
3726 XSETINT (bar->width, sb_width);
3727 XSETINT (bar->height, height);
3729 UNBLOCK_INPUT;
3732 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
3734 w32_set_scroll_bar_thumb (bar, portion, position, whole);
3736 XSETVECTOR (w->vertical_scroll_bar, bar);
3740 /* The following three hooks are used when we're doing a thorough
3741 redisplay of the frame. We don't explicitly know which scroll bars
3742 are going to be deleted, because keeping track of when windows go
3743 away is a real pain - "Can you say set-window-configuration, boys
3744 and girls?" Instead, we just assert at the beginning of redisplay
3745 that *all* scroll bars are to be removed, and then save a scroll bar
3746 from the fiery pit when we actually redisplay its window. */
3748 /* Arrange for all scroll bars on FRAME to be removed at the next call
3749 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3750 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3752 static void
3753 w32_condemn_scroll_bars (frame)
3754 FRAME_PTR frame;
3756 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3757 while (! NILP (FRAME_SCROLL_BARS (frame)))
3759 Lisp_Object bar;
3760 bar = FRAME_SCROLL_BARS (frame);
3761 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
3762 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3763 XSCROLL_BAR (bar)->prev = Qnil;
3764 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3765 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
3766 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
3771 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
3772 Note that WINDOW isn't necessarily condemned at all. */
3774 static void
3775 w32_redeem_scroll_bar (window)
3776 struct window *window;
3778 struct scroll_bar *bar;
3779 struct frame *f;
3781 /* We can't redeem this window's scroll bar if it doesn't have one. */
3782 if (NILP (window->vertical_scroll_bar))
3783 abort ();
3785 bar = XSCROLL_BAR (window->vertical_scroll_bar);
3787 /* Unlink it from the condemned list. */
3788 f = XFRAME (WINDOW_FRAME (window));
3789 if (NILP (bar->prev))
3791 /* If the prev pointer is nil, it must be the first in one of
3792 the lists. */
3793 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
3794 /* It's not condemned. Everything's fine. */
3795 return;
3796 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
3797 window->vertical_scroll_bar))
3798 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
3799 else
3800 /* If its prev pointer is nil, it must be at the front of
3801 one or the other! */
3802 abort ();
3804 else
3805 XSCROLL_BAR (bar->prev)->next = bar->next;
3807 if (! NILP (bar->next))
3808 XSCROLL_BAR (bar->next)->prev = bar->prev;
3810 bar->next = FRAME_SCROLL_BARS (f);
3811 bar->prev = Qnil;
3812 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3813 if (! NILP (bar->next))
3814 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3817 /* Remove all scroll bars on FRAME that haven't been saved since the
3818 last call to `*condemn_scroll_bars_hook'. */
3820 static void
3821 w32_judge_scroll_bars (f)
3822 FRAME_PTR f;
3824 Lisp_Object bar, next;
3826 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3828 /* Clear out the condemned list now so we won't try to process any
3829 more events on the hapless scroll bars. */
3830 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
3832 for (; ! NILP (bar); bar = next)
3834 struct scroll_bar *b = XSCROLL_BAR (bar);
3836 x_scroll_bar_remove (b);
3838 next = b->next;
3839 b->next = b->prev = Qnil;
3842 /* Now there should be no references to the condemned scroll bars,
3843 and they should get garbage-collected. */
3846 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3847 is set to something other than NO_EVENT, it is enqueued.
3849 This may be called from a signal handler, so we have to ignore GC
3850 mark bits. */
3852 static int
3853 w32_scroll_bar_handle_click (bar, msg, emacs_event)
3854 struct scroll_bar *bar;
3855 W32Msg *msg;
3856 struct input_event *emacs_event;
3858 if (! WINDOWP (bar->window))
3859 abort ();
3861 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
3862 emacs_event->code = 0;
3863 /* not really meaningful to distinguish up/down */
3864 emacs_event->modifiers = msg->dwModifiers;
3865 emacs_event->frame_or_window = bar->window;
3866 emacs_event->arg = Qnil;
3867 emacs_event->timestamp = msg->msg.time;
3870 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3871 int y;
3872 int dragging = !NILP (bar->dragging);
3873 SCROLLINFO si;
3875 si.cbSize = sizeof (si);
3876 si.fMask = SIF_POS;
3878 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
3879 y = si.nPos;
3881 bar->dragging = Qnil;
3884 last_mouse_scroll_bar_pos = msg->msg.wParam;
3886 switch (LOWORD (msg->msg.wParam))
3888 case SB_LINEDOWN:
3889 emacs_event->part = scroll_bar_down_arrow;
3890 break;
3891 case SB_LINEUP:
3892 emacs_event->part = scroll_bar_up_arrow;
3893 break;
3894 case SB_PAGEUP:
3895 emacs_event->part = scroll_bar_above_handle;
3896 break;
3897 case SB_PAGEDOWN:
3898 emacs_event->part = scroll_bar_below_handle;
3899 break;
3900 case SB_TOP:
3901 emacs_event->part = scroll_bar_handle;
3902 y = 0;
3903 break;
3904 case SB_BOTTOM:
3905 emacs_event->part = scroll_bar_handle;
3906 y = top_range;
3907 break;
3908 case SB_THUMBTRACK:
3909 case SB_THUMBPOSITION:
3910 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3911 y = HIWORD (msg->msg.wParam);
3912 bar->dragging = Qt;
3913 emacs_event->part = scroll_bar_handle;
3915 /* "Silently" update current position. */
3917 SCROLLINFO si;
3919 si.cbSize = sizeof (si);
3920 si.fMask = SIF_POS;
3921 si.nPos = y;
3922 /* Remember apparent position (we actually lag behind the real
3923 position, so don't set that directly. */
3924 last_scroll_bar_drag_pos = y;
3926 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
3928 break;
3929 case SB_ENDSCROLL:
3930 /* If this is the end of a drag sequence, then reset the scroll
3931 handle size to normal and do a final redraw. Otherwise do
3932 nothing. */
3933 if (dragging)
3935 SCROLLINFO si;
3936 int start = XINT (bar->start);
3937 int end = XINT (bar->end);
3939 si.cbSize = sizeof (si);
3940 si.fMask = SIF_PAGE | SIF_POS;
3941 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3942 si.nPos = last_scroll_bar_drag_pos;
3943 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
3945 /* fall through */
3946 default:
3947 emacs_event->kind = NO_EVENT;
3948 return FALSE;
3951 XSETINT (emacs_event->x, y);
3952 XSETINT (emacs_event->y, top_range);
3954 return TRUE;
3958 /* Return information to the user about the current position of the mouse
3959 on the scroll bar. */
3961 static void
3962 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3963 FRAME_PTR *fp;
3964 Lisp_Object *bar_window;
3965 enum scroll_bar_part *part;
3966 Lisp_Object *x, *y;
3967 unsigned long *time;
3969 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3970 Window w = SCROLL_BAR_W32_WINDOW (bar);
3971 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3972 int pos;
3973 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3974 SCROLLINFO si;
3976 BLOCK_INPUT;
3978 *fp = f;
3979 *bar_window = bar->window;
3981 si.cbSize = sizeof (si);
3982 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
3984 GetScrollInfo (w, SB_CTL, &si);
3985 pos = si.nPos;
3986 top_range = si.nMax - si.nPage + 1;
3988 switch (LOWORD (last_mouse_scroll_bar_pos))
3990 case SB_THUMBPOSITION:
3991 case SB_THUMBTRACK:
3992 *part = scroll_bar_handle;
3993 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
3994 pos = HIWORD (last_mouse_scroll_bar_pos);
3995 break;
3996 case SB_LINEDOWN:
3997 *part = scroll_bar_handle;
3998 pos++;
3999 break;
4000 default:
4001 *part = scroll_bar_handle;
4002 break;
4005 XSETINT (*x, pos);
4006 XSETINT (*y, top_range);
4008 f->mouse_moved = 0;
4009 last_mouse_scroll_bar = Qnil;
4011 *time = last_mouse_movement_time;
4013 UNBLOCK_INPUT;
4017 /* The screen has been cleared so we may have changed foreground or
4018 background colors, and the scroll bars may need to be redrawn.
4019 Clear out the scroll bars, and ask for expose events, so we can
4020 redraw them. */
4022 void
4023 x_scroll_bar_clear (f)
4024 FRAME_PTR f;
4026 Lisp_Object bar;
4028 /* We can have scroll bars even if this is 0,
4029 if we just turned off scroll bar mode.
4030 But in that case we should not clear them. */
4031 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4032 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4033 bar = XSCROLL_BAR (bar)->next)
4035 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4036 HDC hdc = GetDC (window);
4037 RECT rect;
4039 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4040 arranges to refresh the scroll bar if hidden. */
4041 my_show_window (f, window, SW_HIDE);
4043 GetClientRect (window, &rect);
4044 select_palette (f, hdc);
4045 w32_clear_rect (f, hdc, &rect);
4046 deselect_palette (f, hdc);
4048 ReleaseDC (window, hdc);
4053 /* The main W32 event-reading loop - w32_read_socket. */
4055 /* Record the last 100 characters stored
4056 to help debug the loss-of-chars-during-GC problem. */
4058 static int temp_index;
4059 static short temp_buffer[100];
4061 /* Temporarily store lead byte of DBCS input sequences. */
4062 static char dbcs_lead = 0;
4064 /* Read events coming from the W32 shell.
4065 This routine is called by the SIGIO handler.
4066 We return as soon as there are no more events to be read.
4068 We return the number of characters stored into the buffer,
4069 thus pretending to be `read'.
4071 EXPECTED is nonzero if the caller knows input is available.
4073 Some of these messages are reposted back to the message queue since the
4074 system calls the windows proc directly in a context where we cannot return
4075 the data nor can we guarantee the state we are in. So if we dispatch them
4076 we will get into an infinite loop. To prevent this from ever happening we
4077 will set a variable to indicate we are in the read_socket call and indicate
4078 which message we are processing since the windows proc gets called
4079 recursively with different messages by the system.
4083 w32_read_socket (sd, expected, hold_quit)
4084 register int sd;
4085 int expected;
4086 struct input_event *hold_quit;
4088 int count = 0;
4089 int check_visibility = 0;
4090 W32Msg msg;
4091 struct frame *f;
4092 struct w32_display_info *dpyinfo = &one_w32_display_info;
4094 if (interrupt_input_blocked)
4096 interrupt_input_pending = 1;
4097 return -1;
4100 interrupt_input_pending = 0;
4101 BLOCK_INPUT;
4103 /* So people can tell when we have read the available input. */
4104 input_signal_count++;
4106 /* TODO: ghostscript integration. */
4107 while (get_next_msg (&msg, FALSE))
4109 struct input_event inev;
4110 int do_help = 0;
4112 EVENT_INIT (inev);
4113 inev.kind = NO_EVENT;
4114 inev.arg = Qnil;
4116 switch (msg.msg.message)
4118 case WM_EMACS_PAINT:
4119 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4121 if (f)
4123 if (msg.rect.right == msg.rect.left ||
4124 msg.rect.bottom == msg.rect.top)
4126 /* We may get paint messages even though the client
4127 area is clipped - these are not expose events. */
4128 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
4129 SDATA (f->name)));
4131 else if (f->async_visible != 1)
4133 /* Definitely not obscured, so mark as visible. */
4134 f->async_visible = 1;
4135 f->async_iconified = 0;
4136 SET_FRAME_GARBAGED (f);
4137 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4138 SDATA (f->name)));
4140 /* WM_PAINT serves as MapNotify as well, so report
4141 visibility changes properly. */
4142 if (f->iconified)
4144 inev.kind = DEICONIFY_EVENT;
4145 XSETFRAME (inev.frame_or_window, f);
4147 else if (! NILP (Vframe_list)
4148 && ! NILP (XCDR (Vframe_list)))
4149 /* Force a redisplay sooner or later to update the
4150 frame titles in case this is the second frame. */
4151 record_asynch_buffer_change ();
4153 else
4155 HDC hdc = get_frame_dc (f);
4157 /* Erase background again for safety. */
4158 w32_clear_rect (f, hdc, &msg.rect);
4159 release_frame_dc (f, hdc);
4160 expose_frame (f,
4161 msg.rect.left,
4162 msg.rect.top,
4163 msg.rect.right - msg.rect.left,
4164 msg.rect.bottom - msg.rect.top);
4167 break;
4169 case WM_INPUTLANGCHANGE:
4170 /* Generate a language change event. */
4171 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4173 /* lParam contains the input lang ID. Use it to update our
4174 record of the keyboard codepage. */
4175 keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4176 & 0xffff));
4178 if (f)
4180 inev.kind = LANGUAGE_CHANGE_EVENT;
4181 XSETFRAME (inev.frame_or_window, f);
4182 inev.code = msg.msg.wParam;
4183 inev.modifiers = msg.msg.lParam & 0xffff;
4185 break;
4187 case WM_KEYDOWN:
4188 case WM_SYSKEYDOWN:
4189 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4191 if (f && !f->iconified)
4193 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4194 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4196 clear_mouse_face (dpyinfo);
4197 dpyinfo->mouse_face_hidden = 1;
4200 if (temp_index == sizeof temp_buffer / sizeof (short))
4201 temp_index = 0;
4202 temp_buffer[temp_index++] = msg.msg.wParam;
4203 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4204 inev.code = msg.msg.wParam;
4205 inev.modifiers = msg.dwModifiers;
4206 XSETFRAME (inev.frame_or_window, f);
4207 inev.timestamp = msg.msg.time;
4209 break;
4211 case WM_UNICHAR:
4212 case WM_SYSCHAR:
4213 case WM_CHAR:
4214 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4216 if (f && !f->iconified)
4218 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4219 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4221 clear_mouse_face (dpyinfo);
4222 dpyinfo->mouse_face_hidden = 1;
4225 if (temp_index == sizeof temp_buffer / sizeof (short))
4226 temp_index = 0;
4227 temp_buffer[temp_index++] = msg.msg.wParam;
4229 inev.modifiers = msg.dwModifiers;
4230 XSETFRAME (inev.frame_or_window, f);
4231 inev.timestamp = msg.msg.time;
4233 if (msg.msg.message == WM_UNICHAR)
4235 inev.code = msg.msg.wParam;
4237 else if (msg.msg.wParam < 256)
4239 wchar_t code;
4240 char dbcs[2];
4241 dbcs[0] = 0;
4242 dbcs[1] = (char) msg.msg.wParam;
4244 if (dbcs_lead)
4246 dbcs[0] = dbcs_lead;
4247 dbcs_lead = 0;
4248 if (!MultiByteToWideChar (keyboard_codepage, 0,
4249 dbcs, 2, &code, 1))
4251 /* Garbage */
4252 DebPrint (("Invalid DBCS sequence: %d %d\n",
4253 dbcs[0], dbcs[1]));
4254 inev.kind = NO_EVENT;
4255 break;
4258 else if (IsDBCSLeadByteEx (keyboard_codepage,
4259 (BYTE) msg.msg.wParam))
4261 dbcs_lead = (char) msg.msg.wParam;
4262 inev.kind = NO_EVENT;
4263 break;
4265 else
4267 if (!MultiByteToWideChar (keyboard_codepage, 0,
4268 &dbcs[1], 1, &code, 1))
4270 /* What to do with garbage? */
4271 DebPrint (("Invalid character: %d\n", dbcs[1]));
4272 inev.kind = NO_EVENT;
4273 break;
4276 inev.code = code;
4278 else
4280 /* Windows shouldn't generate WM_CHAR events above 0xFF
4281 in non-Unicode message handlers. */
4282 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4283 inev.kind = NO_EVENT;
4284 break;
4286 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4287 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
4289 break;
4291 case WM_APPCOMMAND:
4292 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4294 if (f && !f->iconified)
4296 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
4297 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
4299 clear_mouse_face (dpyinfo);
4300 dpyinfo->mouse_face_hidden = 1;
4303 if (temp_index == sizeof temp_buffer / sizeof (short))
4304 temp_index = 0;
4305 temp_buffer[temp_index++] = msg.msg.wParam;
4306 inev.kind = MULTIMEDIA_KEY_EVENT;
4307 inev.code = GET_APPCOMMAND_LPARAM(msg.msg.lParam);
4308 inev.modifiers = msg.dwModifiers;
4309 XSETFRAME (inev.frame_or_window, f);
4310 inev.timestamp = msg.msg.time;
4312 break;
4314 case WM_MOUSEMOVE:
4315 /* Ignore non-movement. */
4317 int x = LOWORD (msg.msg.lParam);
4318 int y = HIWORD (msg.msg.lParam);
4319 if (x == last_mousemove_x && y == last_mousemove_y)
4320 break;
4321 last_mousemove_x = x;
4322 last_mousemove_y = y;
4325 previous_help_echo_string = help_echo_string;
4326 help_echo_string = Qnil;
4328 if (dpyinfo->grabbed && last_mouse_frame
4329 && FRAME_LIVE_P (last_mouse_frame))
4330 f = last_mouse_frame;
4331 else
4332 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4334 if (dpyinfo->mouse_face_hidden)
4336 dpyinfo->mouse_face_hidden = 0;
4337 clear_mouse_face (dpyinfo);
4340 if (f)
4342 /* Generate SELECT_WINDOW_EVENTs when needed. */
4343 if (!NILP (Vmouse_autoselect_window))
4345 Lisp_Object window;
4346 int x = LOWORD (msg.msg.lParam);
4347 int y = HIWORD (msg.msg.lParam);
4349 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
4351 /* Window will be selected only when it is not
4352 selected now and last mouse movement event was
4353 not in it. Minibuffer window will be selected
4354 only when it is active. */
4355 if (WINDOWP(window)
4356 && !EQ (window, last_window)
4357 && !EQ (window, selected_window)
4358 /* For click-to-focus window managers
4359 create event iff we don't leave the
4360 selected frame. */
4361 && (focus_follows_mouse
4362 || (EQ (XWINDOW (window)->frame,
4363 XWINDOW (selected_window)->frame))))
4365 inev.kind = SELECT_WINDOW_EVENT;
4366 inev.frame_or_window = window;
4369 last_window=window;
4371 if (!note_mouse_movement (f, &msg.msg))
4372 help_echo_string = previous_help_echo_string;
4374 else
4376 /* If we move outside the frame, then we're
4377 certainly no longer on any text in the frame. */
4378 clear_mouse_face (dpyinfo);
4381 /* If the contents of the global variable help_echo_string
4382 has changed, generate a HELP_EVENT. */
4383 #if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
4384 But it was originally changed to this to fix a bug, so I have
4385 not removed it completely in case the bug is still there. */
4386 if (help_echo_string != previous_help_echo_string ||
4387 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
4388 #else /* This is what xterm.c does. */
4389 if (!NILP (help_echo_string)
4390 || !NILP (previous_help_echo_string))
4391 do_help = 1;
4392 #endif
4393 break;
4395 case WM_LBUTTONDOWN:
4396 case WM_LBUTTONUP:
4397 case WM_MBUTTONDOWN:
4398 case WM_MBUTTONUP:
4399 case WM_RBUTTONDOWN:
4400 case WM_RBUTTONUP:
4401 case WM_XBUTTONDOWN:
4402 case WM_XBUTTONUP:
4404 /* If we decide we want to generate an event to be seen
4405 by the rest of Emacs, we put it here. */
4406 int tool_bar_p = 0;
4407 int button;
4408 int up;
4410 if (dpyinfo->grabbed && last_mouse_frame
4411 && FRAME_LIVE_P (last_mouse_frame))
4412 f = last_mouse_frame;
4413 else
4414 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4416 if (f)
4418 construct_mouse_click (&inev, &msg, f);
4420 /* Is this in the tool-bar? */
4421 if (WINDOWP (f->tool_bar_window)
4422 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
4424 Lisp_Object window;
4425 int x = XFASTINT (inev.x);
4426 int y = XFASTINT (inev.y);
4428 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
4430 if (EQ (window, f->tool_bar_window))
4432 w32_handle_tool_bar_click (f, &inev);
4433 tool_bar_p = 1;
4437 if (tool_bar_p
4438 || (dpyinfo->w32_focus_frame
4439 && f != dpyinfo->w32_focus_frame))
4440 inev.kind = NO_EVENT;
4443 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4444 &button, &up);
4446 if (up)
4448 dpyinfo->grabbed &= ~ (1 << button);
4450 else
4452 dpyinfo->grabbed |= (1 << button);
4453 last_mouse_frame = f;
4454 /* Ignore any mouse motion that happened
4455 before this event; any subsequent mouse-movement
4456 Emacs events should reflect only motion after
4457 the ButtonPress. */
4458 if (f != 0)
4459 f->mouse_moved = 0;
4461 if (!tool_bar_p)
4462 last_tool_bar_item = -1;
4464 break;
4467 case WM_MOUSEWHEEL:
4468 case WM_MOUSEHWHEEL:
4470 if (dpyinfo->grabbed && last_mouse_frame
4471 && FRAME_LIVE_P (last_mouse_frame))
4472 f = last_mouse_frame;
4473 else
4474 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4476 if (f)
4479 if (!dpyinfo->w32_focus_frame
4480 || f == dpyinfo->w32_focus_frame)
4482 /* Emit an Emacs wheel-up/down event. */
4483 construct_mouse_wheel (&inev, &msg, f);
4485 /* Ignore any mouse motion that happened before this
4486 event; any subsequent mouse-movement Emacs events
4487 should reflect only motion after the
4488 ButtonPress. */
4489 f->mouse_moved = 0;
4491 last_mouse_frame = f;
4492 last_tool_bar_item = -1;
4494 break;
4496 case WM_DROPFILES:
4497 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4499 if (f)
4500 construct_drag_n_drop (&inev, &msg, f);
4501 break;
4503 case WM_VSCROLL:
4505 struct scroll_bar *bar =
4506 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
4508 if (bar)
4509 w32_scroll_bar_handle_click (bar, &msg, &inev);
4510 break;
4513 case WM_WINDOWPOSCHANGED:
4514 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4515 if (f)
4517 if (f->want_fullscreen & FULLSCREEN_WAIT)
4518 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
4520 check_visibility = 1;
4521 break;
4523 case WM_ACTIVATE:
4524 case WM_ACTIVATEAPP:
4525 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4526 if (f)
4527 x_check_fullscreen (f);
4528 check_visibility = 1;
4529 break;
4531 case WM_MOVE:
4532 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4534 if (f && !f->async_iconified)
4536 int x, y;
4538 x_real_positions (f, &x, &y);
4539 f->left_pos = x;
4540 f->top_pos = y;
4543 check_visibility = 1;
4544 break;
4546 case WM_SHOWWINDOW:
4547 /* wParam non-zero means Window is about to be shown, 0 means
4548 about to be hidden. */
4549 /* Redo the mouse-highlight after the tooltip has gone. */
4550 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4552 tip_window = NULL;
4553 redo_mouse_highlight ();
4556 /* If window has been obscured or exposed by another window
4557 being maximised or minimised/restored, then recheck
4558 visibility of all frames. Direct changes to our own
4559 windows get handled by WM_SIZE. */
4560 #if 0
4561 if (msg.msg.lParam != 0)
4562 check_visibility = 1;
4563 else
4565 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4566 f->async_visible = msg.msg.wParam;
4568 #endif
4570 check_visibility = 1;
4571 break;
4573 case WM_SIZE:
4574 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4576 /* Inform lisp of whether frame has been iconified etc. */
4577 if (f)
4579 switch (msg.msg.wParam)
4581 case SIZE_MINIMIZED:
4582 f->async_visible = 0;
4583 f->async_iconified = 1;
4585 inev.kind = ICONIFY_EVENT;
4586 XSETFRAME (inev.frame_or_window, f);
4587 break;
4589 case SIZE_MAXIMIZED:
4590 case SIZE_RESTORED:
4591 f->async_visible = 1;
4592 f->async_iconified = 0;
4594 /* wait_reading_process_output will notice this and update
4595 the frame's display structures. */
4596 SET_FRAME_GARBAGED (f);
4598 if (f->iconified)
4600 int x, y;
4602 /* Reset top and left positions of the Window
4603 here since Windows sends a WM_MOVE message
4604 BEFORE telling us the Window is minimized
4605 when the Window is iconified, with 3000,3000
4606 as the co-ords. */
4607 x_real_positions (f, &x, &y);
4608 f->left_pos = x;
4609 f->top_pos = y;
4611 inev.kind = DEICONIFY_EVENT;
4612 XSETFRAME (inev.frame_or_window, f);
4614 else if (! NILP (Vframe_list)
4615 && ! NILP (XCDR (Vframe_list)))
4616 /* Force a redisplay sooner or later
4617 to update the frame titles
4618 in case this is the second frame. */
4619 record_asynch_buffer_change ();
4620 break;
4624 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
4626 RECT rect;
4627 int rows;
4628 int columns;
4629 int width;
4630 int height;
4632 GetClientRect (msg.msg.hwnd, &rect);
4634 height = rect.bottom - rect.top;
4635 width = rect.right - rect.left;
4637 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4638 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
4640 /* TODO: Clip size to the screen dimensions. */
4642 /* Even if the number of character rows and columns has
4643 not changed, the font size may have changed, so we need
4644 to check the pixel dimensions as well. */
4646 if (columns != FRAME_COLS (f)
4647 || rows != FRAME_LINES (f)
4648 || width != FRAME_PIXEL_WIDTH (f)
4649 || height != FRAME_PIXEL_HEIGHT (f))
4651 change_frame_size (f, rows, columns, 0, 1, 0);
4652 SET_FRAME_GARBAGED (f);
4653 cancel_mouse_face (f);
4654 FRAME_PIXEL_WIDTH (f) = width;
4655 FRAME_PIXEL_HEIGHT (f) = height;
4656 f->win_gravity = NorthWestGravity;
4660 check_visibility = 1;
4661 break;
4663 case WM_MOUSELEAVE:
4664 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4665 if (f)
4667 if (f == dpyinfo->mouse_face_mouse_frame)
4669 /* If we move outside the frame, then we're
4670 certainly no longer on any text in the frame. */
4671 clear_mouse_face (dpyinfo);
4672 dpyinfo->mouse_face_mouse_frame = 0;
4675 /* Generate a nil HELP_EVENT to cancel a help-echo.
4676 Do it only if there's something to cancel.
4677 Otherwise, the startup message is cleared when
4678 the mouse leaves the frame. */
4679 if (any_help_event_p)
4680 do_help = -1;
4682 break;
4684 case WM_SETFOCUS:
4685 w32_detect_focus_change (dpyinfo, &msg, &inev);
4687 dpyinfo->grabbed = 0;
4688 check_visibility = 1;
4689 break;
4691 case WM_KILLFOCUS:
4692 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
4694 if (f)
4696 if (f == dpyinfo->w32_focus_event_frame)
4697 dpyinfo->w32_focus_event_frame = 0;
4699 if (f == dpyinfo->w32_focus_frame)
4700 x_new_focus_frame (dpyinfo, 0);
4702 if (f == dpyinfo->mouse_face_mouse_frame)
4704 /* If we move outside the frame, then we're
4705 certainly no longer on any text in the frame. */
4706 clear_mouse_face (dpyinfo);
4707 dpyinfo->mouse_face_mouse_frame = 0;
4710 /* Generate a nil HELP_EVENT to cancel a help-echo.
4711 Do it only if there's something to cancel.
4712 Otherwise, the startup message is cleared when
4713 the mouse leaves the frame. */
4714 if (any_help_event_p)
4715 do_help = -1;
4718 dpyinfo->grabbed = 0;
4719 check_visibility = 1;
4720 break;
4722 case WM_CLOSE:
4723 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4725 if (f)
4727 inev.kind = DELETE_WINDOW_EVENT;
4728 XSETFRAME (inev.frame_or_window, f);
4730 break;
4732 case WM_INITMENU:
4733 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4735 if (f)
4737 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4738 XSETFRAME (inev.frame_or_window, f);
4740 break;
4742 case WM_COMMAND:
4743 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4745 if (f)
4747 extern void menubar_selection_callback
4748 (FRAME_PTR f, void * client_data);
4749 menubar_selection_callback (f, (void *)msg.msg.wParam);
4752 check_visibility = 1;
4753 break;
4755 case WM_DISPLAYCHANGE:
4756 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4758 if (f)
4760 dpyinfo->n_cbits = msg.msg.wParam;
4761 DebPrint (("display change: %d %d\n",
4762 (short) LOWORD (msg.msg.lParam),
4763 (short) HIWORD (msg.msg.lParam)));
4766 check_visibility = 1;
4767 break;
4769 default:
4770 /* Check for messages registered at runtime. */
4771 if (msg.msg.message == msh_mousewheel)
4773 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
4774 msg.msg.message = WM_MOUSEWHEEL;
4775 prepend_msg (&msg);
4777 break;
4780 if (inev.kind != NO_EVENT)
4782 kbd_buffer_store_event_hold (&inev, hold_quit);
4783 count++;
4786 if (do_help
4787 && !(hold_quit && hold_quit->kind != NO_EVENT))
4789 Lisp_Object frame;
4791 if (f)
4792 XSETFRAME (frame, f);
4793 else
4794 frame = Qnil;
4796 if (do_help > 0)
4798 if (NILP (help_echo_string))
4800 help_echo_object = help_echo_window = Qnil;
4801 help_echo_pos = -1;
4804 any_help_event_p = 1;
4805 gen_help_event (help_echo_string, frame, help_echo_window,
4806 help_echo_object, help_echo_pos);
4808 else
4810 help_echo_string = Qnil;
4811 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4813 count++;
4817 /* If the focus was just given to an autoraising frame,
4818 raise it now. */
4819 /* ??? This ought to be able to handle more than one such frame. */
4820 if (pending_autoraise_frame)
4822 x_raise_frame (pending_autoraise_frame);
4823 pending_autoraise_frame = 0;
4826 /* Check which frames are still visisble, if we have enqueued any user
4827 events or been notified of events that may affect visibility. We
4828 do this here because there doesn't seem to be any direct
4829 notification from Windows that the visibility of a window has
4830 changed (at least, not in all cases). */
4831 if (count > 0 || check_visibility)
4833 Lisp_Object tail, frame;
4835 FOR_EACH_FRAME (tail, frame)
4837 FRAME_PTR f = XFRAME (frame);
4838 /* The tooltip has been drawn already. Avoid the
4839 SET_FRAME_GARBAGED below. */
4840 if (EQ (frame, tip_frame))
4841 continue;
4843 /* Check "visible" frames and mark each as obscured or not.
4844 Note that async_visible is nonzero for unobscured and
4845 obscured frames, but zero for hidden and iconified frames. */
4846 if (FRAME_W32_P (f) && f->async_visible)
4848 RECT clipbox;
4849 HDC hdc;
4851 enter_crit ();
4852 /* Query clipping rectangle for the entire window area
4853 (GetWindowDC), not just the client portion (GetDC).
4854 Otherwise, the scrollbars and menubar aren't counted as
4855 part of the visible area of the frame, and we may think
4856 the frame is obscured when really a scrollbar is still
4857 visible and gets WM_PAINT messages above. */
4858 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
4859 GetClipBox (hdc, &clipbox);
4860 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
4861 leave_crit ();
4863 if (clipbox.right == clipbox.left
4864 || clipbox.bottom == clipbox.top)
4866 /* Frame has become completely obscured so mark as
4867 such (we do this by setting async_visible to 2 so
4868 that FRAME_VISIBLE_P is still true, but redisplay
4869 will skip it). */
4870 f->async_visible = 2;
4872 if (!FRAME_OBSCURED_P (f))
4874 DebPrint (("frame %p (%s) obscured\n", f,
4875 SDATA (f->name)));
4878 else
4880 /* Frame is not obscured, so mark it as such. */
4881 f->async_visible = 1;
4883 if (FRAME_OBSCURED_P (f))
4885 SET_FRAME_GARBAGED (f);
4886 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
4887 SDATA (f->name)));
4889 /* Force a redisplay sooner or later. */
4890 record_asynch_buffer_change ();
4897 UNBLOCK_INPUT;
4898 return count;
4903 /***********************************************************************
4904 Text Cursor
4905 ***********************************************************************/
4907 /* Set clipping for output in glyph row ROW. W is the window in which
4908 we operate. GC is the graphics context to set clipping in.
4910 ROW may be a text row or, e.g., a mode line. Text rows must be
4911 clipped to the interior of the window dedicated to text display,
4912 mode lines must be clipped to the whole window. */
4914 static void
4915 w32_clip_to_row (w, row, area, hdc)
4916 struct window *w;
4917 struct glyph_row *row;
4918 int area;
4919 HDC hdc;
4921 struct frame *f = XFRAME (WINDOW_FRAME (w));
4922 RECT clip_rect;
4923 int window_x, window_y, window_width;
4925 window_box (w, area, &window_x, &window_y, &window_width, 0);
4927 clip_rect.left = window_x;
4928 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4929 clip_rect.top = max (clip_rect.top, window_y);
4930 clip_rect.right = clip_rect.left + window_width;
4931 clip_rect.bottom = clip_rect.top + row->visible_height;
4933 w32_set_clip_rectangle (hdc, &clip_rect);
4937 /* Draw a hollow box cursor on window W in glyph row ROW. */
4939 static void
4940 x_draw_hollow_cursor (w, row)
4941 struct window *w;
4942 struct glyph_row *row;
4944 struct frame *f = XFRAME (WINDOW_FRAME (w));
4945 HDC hdc;
4946 RECT rect;
4947 int left, top, h;
4948 struct glyph *cursor_glyph;
4949 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
4951 /* Get the glyph the cursor is on. If we can't tell because
4952 the current matrix is invalid or such, give up. */
4953 cursor_glyph = get_phys_cursor_glyph (w);
4954 if (cursor_glyph == NULL)
4955 return;
4957 /* Compute frame-relative coordinates for phys cursor. */
4958 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
4959 rect.left = left;
4960 rect.top = top;
4961 rect.bottom = rect.top + h;
4962 rect.right = rect.left + w->phys_cursor_width;
4964 hdc = get_frame_dc (f);
4965 /* Set clipping, draw the rectangle, and reset clipping again. */
4966 w32_clip_to_row (w, row, TEXT_AREA, hdc);
4967 FrameRect (hdc, &rect, hb);
4968 DeleteObject (hb);
4969 w32_set_clip_rectangle (hdc, NULL);
4970 release_frame_dc (f, hdc);
4974 /* Draw a bar cursor on window W in glyph row ROW.
4976 Implementation note: One would like to draw a bar cursor with an
4977 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4978 Unfortunately, I didn't find a font yet that has this property set.
4979 --gerd. */
4981 static void
4982 x_draw_bar_cursor (w, row, width, kind)
4983 struct window *w;
4984 struct glyph_row *row;
4985 int width;
4986 enum text_cursor_kinds kind;
4988 struct frame *f = XFRAME (w->frame);
4989 struct glyph *cursor_glyph;
4991 /* If cursor is out of bounds, don't draw garbage. This can happen
4992 in mini-buffer windows when switching between echo area glyphs
4993 and mini-buffer. */
4994 cursor_glyph = get_phys_cursor_glyph (w);
4995 if (cursor_glyph == NULL)
4996 return;
4998 /* If on an image, draw like a normal cursor. That's usually better
4999 visible than drawing a bar, esp. if the image is large so that
5000 the bar might not be in the window. */
5001 if (cursor_glyph->type == IMAGE_GLYPH)
5003 struct glyph_row *row;
5004 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5005 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5007 else
5009 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5010 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5011 int x;
5012 HDC hdc;
5014 /* If the glyph's background equals the color we normally draw
5015 the bar cursor in, the bar cursor in its normal color is
5016 invisible. Use the glyph's foreground color instead in this
5017 case, on the assumption that the glyph's colors are chosen so
5018 that the glyph is legible. */
5019 if (face->background == cursor_color)
5020 cursor_color = face->foreground;
5022 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5024 hdc = get_frame_dc (f);
5025 w32_clip_to_row (w, row, TEXT_AREA, hdc);
5027 if (kind == BAR_CURSOR)
5029 if (width < 0)
5030 width = FRAME_CURSOR_WIDTH (f);
5031 width = min (cursor_glyph->pixel_width, width);
5033 w->phys_cursor_width = width;
5035 w32_fill_area (f, hdc, cursor_color, x,
5036 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5037 width, row->height);
5039 else
5041 int dummy_x, dummy_y, dummy_h;
5043 if (width < 0)
5044 width = row->height;
5046 width = min (row->height, width);
5048 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5049 &dummy_y, &dummy_h);
5050 w32_fill_area (f, hdc, cursor_color, x,
5051 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5052 row->height - width),
5053 w->phys_cursor_width, width);
5056 w32_set_clip_rectangle (hdc, NULL);
5057 release_frame_dc (f, hdc);
5062 /* RIF: Define cursor CURSOR on frame F. */
5064 static void
5065 w32_define_frame_cursor (f, cursor)
5066 struct frame *f;
5067 Cursor cursor;
5069 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
5073 /* RIF: Clear area on frame F. */
5075 static void
5076 w32_clear_frame_area (f, x, y, width, height)
5077 struct frame *f;
5078 int x, y, width, height;
5080 HDC hdc;
5082 hdc = get_frame_dc (f);
5083 w32_clear_area (f, hdc, x, y, width, height);
5084 release_frame_dc (f, hdc);
5087 /* RIF: Draw or clear cursor on window W. */
5089 static void
5090 w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5091 struct window *w;
5092 struct glyph_row *glyph_row;
5093 int x, y;
5094 int cursor_type, cursor_width;
5095 int on_p, active_p;
5097 if (on_p)
5099 /* If the user wants to use the system caret, make sure our own
5100 cursor remains invisible. */
5101 if (w32_use_visible_system_caret)
5103 /* Call to erase_phys_cursor here seems to use the
5104 wrong values of w->phys_cursor, as they have been
5105 overwritten before this function was called. */
5106 if (w->phys_cursor_type != NO_CURSOR)
5107 erase_phys_cursor (w);
5109 cursor_type = w->phys_cursor_type = NO_CURSOR;
5110 w->phys_cursor_width = -1;
5112 else
5114 w->phys_cursor_type = cursor_type;
5117 w->phys_cursor_on_p = 1;
5119 /* If this is the active cursor, we need to track it with the
5120 system caret, so third party software like screen magnifiers
5121 and speech synthesizers can follow the cursor. */
5122 if (active_p)
5124 struct frame *f = XFRAME (WINDOW_FRAME (w));
5125 HWND hwnd = FRAME_W32_WINDOW (f);
5127 w32_system_caret_x
5128 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5129 w32_system_caret_y
5130 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5131 + glyph_row->ascent - w->phys_cursor_ascent);
5133 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5135 /* If the size of the active cursor changed, destroy the old
5136 system caret. */
5137 if (w32_system_caret_hwnd
5138 && (w32_system_caret_height != w->phys_cursor_height))
5139 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5141 w32_system_caret_height = w->phys_cursor_height;
5143 /* Move the system caret. */
5144 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
5147 if (glyph_row->exact_window_width_line_p
5148 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5150 glyph_row->cursor_in_fringe_p = 1;
5151 draw_fringe_bitmap (w, glyph_row, 0);
5152 return;
5155 switch (cursor_type)
5157 case HOLLOW_BOX_CURSOR:
5158 x_draw_hollow_cursor (w, glyph_row);
5159 break;
5161 case FILLED_BOX_CURSOR:
5162 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5163 break;
5165 case BAR_CURSOR:
5166 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5167 break;
5169 case HBAR_CURSOR:
5170 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5171 break;
5173 case NO_CURSOR:
5174 w->phys_cursor_width = 0;
5175 break;
5177 default:
5178 abort ();
5185 /* Icons. */
5188 x_bitmap_icon (f, icon)
5189 struct frame *f;
5190 Lisp_Object icon;
5192 HANDLE main_icon;
5193 HANDLE small_icon = NULL;
5195 if (FRAME_W32_WINDOW (f) == 0)
5196 return 1;
5198 if (NILP (icon))
5199 main_icon = LoadIcon (hinst, EMACS_CLASS);
5200 else if (STRINGP (icon))
5202 /* Load the main icon from the named file. */
5203 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5204 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5205 /* Try to load a small icon to go with it. */
5206 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5207 GetSystemMetrics (SM_CXSMICON),
5208 GetSystemMetrics (SM_CYSMICON),
5209 LR_LOADFROMFILE);
5211 else if (SYMBOLP (icon))
5213 LPCTSTR name;
5215 if (EQ (icon, intern ("application")))
5216 name = (LPCTSTR) IDI_APPLICATION;
5217 else if (EQ (icon, intern ("hand")))
5218 name = (LPCTSTR) IDI_HAND;
5219 else if (EQ (icon, intern ("question")))
5220 name = (LPCTSTR) IDI_QUESTION;
5221 else if (EQ (icon, intern ("exclamation")))
5222 name = (LPCTSTR) IDI_EXCLAMATION;
5223 else if (EQ (icon, intern ("asterisk")))
5224 name = (LPCTSTR) IDI_ASTERISK;
5225 else if (EQ (icon, intern ("winlogo")))
5226 name = (LPCTSTR) IDI_WINLOGO;
5227 else
5228 return 1;
5230 main_icon = LoadIcon (NULL, name);
5232 else
5233 return 1;
5235 if (main_icon == NULL)
5236 return 1;
5238 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5239 (LPARAM) main_icon);
5241 /* If there is a small icon that goes with it, set that too. */
5242 if (small_icon)
5243 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5244 (LPARAM) small_icon);
5246 return 0;
5250 /************************************************************************
5251 Handling X errors
5252 ************************************************************************/
5254 /* Display Error Handling functions not used on W32. Listing them here
5255 helps diff stay in step when comparing w32term.c with xterm.c.
5257 x_error_catcher (display, error)
5258 x_catch_errors (dpy)
5259 x_catch_errors_unwind (old_val)
5260 x_check_errors (dpy, format)
5261 x_fully_uncatch_errors ()
5262 x_catching_errors ()
5263 x_had_errors_p (dpy)
5264 x_clear_errors (dpy)
5265 x_uncatch_errors (dpy, count)
5266 x_trace_wire ()
5267 x_connection_signal (signalnum)
5268 x_connection_closed (dpy, error_message)
5269 x_error_quitter (display, error)
5270 x_error_handler (display, error)
5271 x_io_error_quitter (display)
5276 /* Changing the font of the frame. */
5278 Lisp_Object
5279 x_new_font (f, font_object, fontset)
5280 struct frame *f;
5281 Lisp_Object font_object;
5282 int fontset;
5284 struct font *font = XFONT_OBJECT (font_object);
5286 if (fontset < 0)
5287 fontset = fontset_from_font (font_object);
5288 FRAME_FONTSET (f) = fontset;
5289 if (FRAME_FONT (f) == font)
5290 /* This font is already set in frame F. There's nothing more to
5291 do. */
5292 return font_object;
5294 FRAME_FONT (f) = font;
5295 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5296 FRAME_COLUMN_WIDTH (f) = font->average_width;
5297 FRAME_SPACE_WIDTH (f) = font->space_width;
5298 FRAME_LINE_HEIGHT (f) = font->height;
5300 compute_fringe_widths (f, 1);
5302 /* Compute the scroll bar width in character columns. */
5303 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5305 int wid = FRAME_COLUMN_WIDTH (f);
5306 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5307 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
5309 else
5311 int wid = FRAME_COLUMN_WIDTH (f);
5312 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5315 /* Now make the frame display the given font. */
5316 if (FRAME_X_WINDOW (f) != 0)
5318 /* Don't change the size of a tip frame; there's no point in
5319 doing it because it's done in Fx_show_tip, and it leads to
5320 problems because the tip frame has no widget. */
5321 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5322 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5325 /* X version sets font of input methods here also. */
5327 return font_object;
5331 /***********************************************************************
5332 TODO: W32 Input Methods
5333 ***********************************************************************/
5334 /* Listing missing functions from xterm.c helps diff stay in step.
5336 xim_destroy_callback (xim, client_data, call_data)
5337 xim_open_dpy (dpyinfo, resource_name)
5338 struct xim_inst_t
5339 xim_instantiate_callback (display, client_data, call_data)
5340 xim_initialize (dpyinfo, resource_name)
5341 xim_close_dpy (dpyinfo)
5346 /* Calculate the absolute position in frame F
5347 from its current recorded position values and gravity. */
5349 void
5350 x_calc_absolute_position (f)
5351 struct frame *f;
5353 int flags = f->size_hint_flags;
5355 /* The sum of the widths of the frame's left and right borders, and
5356 the sum of the heights of the frame's top and bottom borders (in
5357 pixels) drawn by Windows. */
5358 unsigned int left_right_borders_width, top_bottom_borders_height;
5360 /* Try to get the actual values of these two variables. We compute
5361 the border width (height) by subtracting the width (height) of
5362 the frame's client area from the width (height) of the frame's
5363 entire window. */
5364 WINDOWPLACEMENT wp = { 0 };
5365 RECT client_rect = { 0 };
5367 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
5368 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
5370 left_right_borders_width =
5371 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
5372 (client_rect.right - client_rect.left);
5374 top_bottom_borders_height =
5375 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
5376 (client_rect.bottom - client_rect.top);
5378 else
5380 /* Use sensible default values. */
5381 left_right_borders_width = 8;
5382 top_bottom_borders_height = 32;
5385 /* Treat negative positions as relative to the rightmost bottommost
5386 position that fits on the screen. */
5387 if (flags & XNegative)
5388 f->left_pos = (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f))
5389 - FRAME_PIXEL_WIDTH (f)
5390 + f->left_pos
5391 - (left_right_borders_width - 1));
5393 if (flags & YNegative)
5394 f->top_pos = (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f))
5395 - FRAME_PIXEL_HEIGHT (f)
5396 + f->top_pos
5397 - (top_bottom_borders_height - 1));
5399 /* The left_pos and top_pos are now relative to the top and left
5400 screen edges, so the flags should correspond. */
5401 f->size_hint_flags &= ~ (XNegative | YNegative);
5404 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5405 to really change the position, and 0 when calling from
5406 x_make_frame_visible (in that case, XOFF and YOFF are the current
5407 position values). It is -1 when calling from x_set_frame_parameters,
5408 which means, do adjust for borders but don't change the gravity. */
5410 void
5411 x_set_offset (f, xoff, yoff, change_gravity)
5412 struct frame *f;
5413 register int xoff, yoff;
5414 int change_gravity;
5416 int modified_top, modified_left;
5418 if (change_gravity > 0)
5420 f->top_pos = yoff;
5421 f->left_pos = xoff;
5422 f->size_hint_flags &= ~ (XNegative | YNegative);
5423 if (xoff < 0)
5424 f->size_hint_flags |= XNegative;
5425 if (yoff < 0)
5426 f->size_hint_flags |= YNegative;
5427 f->win_gravity = NorthWestGravity;
5429 x_calc_absolute_position (f);
5431 BLOCK_INPUT;
5432 x_wm_set_size_hint (f, (long) 0, 0);
5434 modified_left = f->left_pos;
5435 modified_top = f->top_pos;
5437 my_set_window_pos (FRAME_W32_WINDOW (f),
5438 NULL,
5439 modified_left, modified_top,
5440 0, 0,
5441 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
5442 UNBLOCK_INPUT;
5446 /* Check if we need to resize the frame due to a fullscreen request.
5447 If so needed, resize the frame. */
5448 static void
5449 x_check_fullscreen (f)
5450 struct frame *f;
5452 if (f->want_fullscreen & FULLSCREEN_BOTH)
5454 int width, height, ign;
5456 x_real_positions (f, &f->left_pos, &f->top_pos);
5458 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
5460 /* We do not need to move the window, it shall be taken care of
5461 when setting WM manager hints. */
5462 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
5464 change_frame_size (f, height, width, 0, 1, 0);
5465 SET_FRAME_GARBAGED (f);
5466 cancel_mouse_face (f);
5468 /* Wait for the change of frame size to occur */
5469 f->want_fullscreen |= FULLSCREEN_WAIT;
5474 /* Call this to change the size of frame F's x-window.
5475 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5476 for this size change and subsequent size changes.
5477 Otherwise we leave the window gravity unchanged. */
5479 void
5480 x_set_window_size (f, change_gravity, cols, rows)
5481 struct frame *f;
5482 int change_gravity;
5483 int cols, rows;
5485 int pixelwidth, pixelheight;
5487 BLOCK_INPUT;
5489 check_frame_size (f, &rows, &cols);
5490 f->scroll_bar_actual_width
5491 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5493 compute_fringe_widths (f, 0);
5495 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5496 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5498 f->win_gravity = NorthWestGravity;
5499 x_wm_set_size_hint (f, (long) 0, 0);
5502 RECT rect;
5504 rect.left = rect.top = 0;
5505 rect.right = pixelwidth;
5506 rect.bottom = pixelheight;
5508 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
5509 FRAME_EXTERNAL_MENU_BAR (f));
5511 my_set_window_pos (FRAME_W32_WINDOW (f),
5512 NULL,
5513 0, 0,
5514 rect.right - rect.left,
5515 rect.bottom - rect.top,
5516 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
5519 #if 0
5520 /* The following mirrors what is done in xterm.c. It appears to be
5521 for informing lisp of the new size immediately, while the actual
5522 resize will happen asynchronously. But on Windows, the menu bar
5523 automatically wraps when the frame is too narrow to contain it,
5524 and that causes any calculations made here to come out wrong. The
5525 end is some nasty buggy behavior, including the potential loss
5526 of the minibuffer.
5528 Disabling this code is either not sufficient to fix the problems
5529 completely, or it causes fresh problems, but at least it removes
5530 the most problematic symptom of the minibuffer becoming unusable.
5532 -----------------------------------------------------------------
5534 Now, strictly speaking, we can't be sure that this is accurate,
5535 but the window manager will get around to dealing with the size
5536 change request eventually, and we'll hear how it went when the
5537 ConfigureNotify event gets here.
5539 We could just not bother storing any of this information here,
5540 and let the ConfigureNotify event set everything up, but that
5541 might be kind of confusing to the Lisp code, since size changes
5542 wouldn't be reported in the frame parameters until some random
5543 point in the future when the ConfigureNotify event arrives.
5545 We pass 1 for DELAY since we can't run Lisp code inside of
5546 a BLOCK_INPUT. */
5547 change_frame_size (f, rows, cols, 0, 1, 0);
5548 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5549 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5551 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5552 receive in the ConfigureNotify event; if we get what we asked
5553 for, then the event won't cause the screen to become garbaged, so
5554 we have to make sure to do it here. */
5555 SET_FRAME_GARBAGED (f);
5557 /* If cursor was outside the new size, mark it as off. */
5558 mark_window_cursors_off (XWINDOW (f->root_window));
5560 /* Clear out any recollection of where the mouse highlighting was,
5561 since it might be in a place that's outside the new frame size.
5562 Actually checking whether it is outside is a pain in the neck,
5563 so don't try--just let the highlighting be done afresh with new size. */
5564 cancel_mouse_face (f);
5565 #endif
5567 UNBLOCK_INPUT;
5570 /* Mouse warping. */
5572 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5574 void
5575 x_set_mouse_position (f, x, y)
5576 struct frame *f;
5577 int x, y;
5579 int pix_x, pix_y;
5581 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5582 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5584 if (pix_x < 0) pix_x = 0;
5585 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5587 if (pix_y < 0) pix_y = 0;
5588 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5590 x_set_mouse_pixel_position (f, pix_x, pix_y);
5593 void
5594 x_set_mouse_pixel_position (f, pix_x, pix_y)
5595 struct frame *f;
5596 int pix_x, pix_y;
5598 RECT rect;
5599 POINT pt;
5601 BLOCK_INPUT;
5603 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5604 pt.x = rect.left + pix_x;
5605 pt.y = rect.top + pix_y;
5606 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
5608 SetCursorPos (pt.x, pt.y);
5610 UNBLOCK_INPUT;
5614 /* focus shifting, raising and lowering. */
5616 void
5617 x_focus_on_frame (f)
5618 struct frame *f;
5620 struct w32_display_info *dpyinfo = &one_w32_display_info;
5622 /* Give input focus to frame. */
5623 BLOCK_INPUT;
5624 #if 0
5625 /* Try not to change its Z-order if possible. */
5626 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5627 my_set_focus (f, FRAME_W32_WINDOW (f));
5628 else
5629 #endif
5630 my_set_foreground_window (FRAME_W32_WINDOW (f));
5631 UNBLOCK_INPUT;
5634 void
5635 x_unfocus_frame (f)
5636 struct frame *f;
5640 /* Raise frame F. */
5641 void
5642 x_raise_frame (f)
5643 struct frame *f;
5645 BLOCK_INPUT;
5647 /* Strictly speaking, raise-frame should only change the frame's Z
5648 order, leaving input focus unchanged. This is reasonable behavior
5649 on X where the usual policy is point-to-focus. However, this
5650 behavior would be very odd on Windows where the usual policy is
5651 click-to-focus.
5653 On X, if the mouse happens to be over the raised frame, it gets
5654 input focus anyway (so the window with focus will never be
5655 completely obscured) - if not, then just moving the mouse over it
5656 is sufficient to give it focus. On Windows, the user must actually
5657 click on the frame (preferrably the title bar so as not to move
5658 point), which is more awkward. Also, no other Windows program
5659 raises a window to the top but leaves another window (possibly now
5660 completely obscured) with input focus.
5662 Because there is a system setting on Windows that allows the user
5663 to choose the point to focus policy, we make the strict semantics
5664 optional, but by default we grab focus when raising. */
5666 if (NILP (Vw32_grab_focus_on_raise))
5668 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5669 not already the foreground application: the frame is raised
5670 above all other frames belonging to us, but not above the
5671 current top window. To achieve that, we have to resort to this
5672 more cumbersome method. */
5674 HDWP handle = BeginDeferWindowPos (2);
5675 if (handle)
5677 DeferWindowPos (handle,
5678 FRAME_W32_WINDOW (f),
5679 HWND_TOP,
5680 0, 0, 0, 0,
5681 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5683 DeferWindowPos (handle,
5684 GetForegroundWindow (),
5685 FRAME_W32_WINDOW (f),
5686 0, 0, 0, 0,
5687 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5689 EndDeferWindowPos (handle);
5692 else
5694 my_set_foreground_window (FRAME_W32_WINDOW (f));
5697 UNBLOCK_INPUT;
5700 /* Lower frame F. */
5701 void
5702 x_lower_frame (f)
5703 struct frame *f;
5705 BLOCK_INPUT;
5706 my_set_window_pos (FRAME_W32_WINDOW (f),
5707 HWND_BOTTOM,
5708 0, 0, 0, 0,
5709 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5710 UNBLOCK_INPUT;
5713 static void
5714 w32_frame_raise_lower (f, raise_flag)
5715 FRAME_PTR f;
5716 int raise_flag;
5718 if (! FRAME_W32_P (f))
5719 return;
5721 if (raise_flag)
5722 x_raise_frame (f);
5723 else
5724 x_lower_frame (f);
5727 /* Change of visibility. */
5729 /* This tries to wait until the frame is really visible.
5730 However, if the window manager asks the user where to position
5731 the frame, this will return before the user finishes doing that.
5732 The frame will not actually be visible at that time,
5733 but it will become visible later when the window manager
5734 finishes with it. */
5736 void
5737 x_make_frame_visible (f)
5738 struct frame *f;
5740 Lisp_Object type;
5742 BLOCK_INPUT;
5744 type = x_icon_type (f);
5745 if (!NILP (type))
5746 x_bitmap_icon (f, type);
5748 if (! FRAME_VISIBLE_P (f))
5750 /* We test FRAME_GARBAGED_P here to make sure we don't
5751 call x_set_offset a second time
5752 if we get to x_make_frame_visible a second time
5753 before the window gets really visible. */
5754 if (! FRAME_ICONIFIED_P (f)
5755 && ! f->output_data.w32->asked_for_visible)
5757 RECT workarea_rect;
5758 RECT window_rect;
5760 /* Adjust vertical window position in order to avoid being
5761 covered by a task bar placed at the bottom of the desktop. */
5762 SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
5763 GetWindowRect(FRAME_W32_WINDOW(f), &window_rect);
5764 if (window_rect.bottom > workarea_rect.bottom
5765 && window_rect.top > workarea_rect.top)
5766 f->top_pos = max (window_rect.top
5767 - window_rect.bottom + workarea_rect.bottom,
5768 workarea_rect.top);
5770 x_set_offset (f, f->left_pos, f->top_pos, 0);
5773 f->output_data.w32->asked_for_visible = 1;
5775 /* The first of these seems to give more expected behavior, but
5776 was added as a commented out line in Sept 1997, with the
5777 second version remaining uncommented. There may have been
5778 some problem with it that led to it not being enabled,
5779 so the old version remains commented out below in case we
5780 decide we need to go back to it [23.0.60 2008-06-09]. */
5781 my_show_window (f, FRAME_W32_WINDOW (f),
5782 f->async_iconified ? SW_RESTORE : SW_SHOW);
5783 /* my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); */
5786 /* Synchronize to ensure Emacs knows the frame is visible
5787 before we do anything else. We do this loop with input not blocked
5788 so that incoming events are handled. */
5790 Lisp_Object frame;
5791 int count;
5793 /* This must come after we set COUNT. */
5794 UNBLOCK_INPUT;
5796 XSETFRAME (frame, f);
5798 /* Wait until the frame is visible. Process X events until a
5799 MapNotify event has been seen, or until we think we won't get a
5800 MapNotify at all.. */
5801 for (count = input_signal_count + 10;
5802 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5804 /* Force processing of queued events. */
5805 /* TODO: x_sync equivalent? */
5807 /* Machines that do polling rather than SIGIO have been observed
5808 to go into a busy-wait here. So we'll fake an alarm signal
5809 to let the handler know that there's something to be read.
5810 We used to raise a real alarm, but it seems that the handler
5811 isn't always enabled here. This is probably a bug. */
5812 if (input_polling_used ())
5814 /* It could be confusing if a real alarm arrives while processing
5815 the fake one. Turn it off and let the handler reset it. */
5816 int old_poll_suppress_count = poll_suppress_count;
5817 poll_suppress_count = 1;
5818 poll_for_input_1 ();
5819 poll_suppress_count = old_poll_suppress_count;
5822 FRAME_SAMPLE_VISIBILITY (f);
5826 /* Change from mapped state to withdrawn state. */
5828 /* Make the frame visible (mapped and not iconified). */
5830 x_make_frame_invisible (f)
5831 struct frame *f;
5833 /* Don't keep the highlight on an invisible frame. */
5834 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5835 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5837 BLOCK_INPUT;
5839 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
5841 /* We can't distinguish this from iconification
5842 just by the event that we get from the server.
5843 So we can't win using the usual strategy of letting
5844 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5845 and synchronize with the server to make sure we agree. */
5846 f->visible = 0;
5847 FRAME_ICONIFIED_P (f) = 0;
5848 f->async_visible = 0;
5849 f->async_iconified = 0;
5851 UNBLOCK_INPUT;
5854 /* Change window state from mapped to iconified. */
5856 void
5857 x_iconify_frame (f)
5858 struct frame *f;
5860 Lisp_Object type;
5862 /* Don't keep the highlight on an invisible frame. */
5863 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
5864 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
5866 if (f->async_iconified)
5867 return;
5869 BLOCK_INPUT;
5871 type = x_icon_type (f);
5872 if (!NILP (type))
5873 x_bitmap_icon (f, type);
5875 /* Simulate the user minimizing the frame. */
5876 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
5878 UNBLOCK_INPUT;
5882 /* Free X resources of frame F. */
5884 void
5885 x_free_frame_resources (f)
5886 struct frame *f;
5888 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5890 BLOCK_INPUT;
5892 /* We must free faces before destroying windows because some
5893 font-driver (e.g. xft) access a window while finishing a
5894 face. */
5895 if (FRAME_FACE_CACHE (f))
5896 free_frame_faces (f);
5898 if (FRAME_W32_WINDOW (f))
5899 my_destroy_window (f, FRAME_W32_WINDOW (f));
5901 free_frame_menubar (f);
5903 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
5904 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
5905 unload_color (f, f->output_data.w32->cursor_pixel);
5906 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
5907 unload_color (f, f->output_data.w32->border_pixel);
5908 unload_color (f, f->output_data.w32->mouse_pixel);
5909 if (f->output_data.w32->white_relief.allocated_p)
5910 unload_color (f, f->output_data.w32->white_relief.pixel);
5911 if (f->output_data.w32->black_relief.allocated_p)
5912 unload_color (f, f->output_data.w32->black_relief.pixel);
5914 if (FRAME_FACE_CACHE (f))
5915 free_frame_faces (f);
5917 xfree (f->output_data.w32);
5918 f->output_data.w32 = NULL;
5920 if (f == dpyinfo->w32_focus_frame)
5921 dpyinfo->w32_focus_frame = 0;
5922 if (f == dpyinfo->w32_focus_event_frame)
5923 dpyinfo->w32_focus_event_frame = 0;
5924 if (f == dpyinfo->x_highlight_frame)
5925 dpyinfo->x_highlight_frame = 0;
5927 if (f == dpyinfo->mouse_face_mouse_frame)
5929 dpyinfo->mouse_face_beg_row
5930 = dpyinfo->mouse_face_beg_col = -1;
5931 dpyinfo->mouse_face_end_row
5932 = dpyinfo->mouse_face_end_col = -1;
5933 dpyinfo->mouse_face_window = Qnil;
5934 dpyinfo->mouse_face_deferred_gc = 0;
5935 dpyinfo->mouse_face_mouse_frame = 0;
5938 UNBLOCK_INPUT;
5942 /* Destroy the window of frame F. */
5943 void
5944 x_destroy_window (f)
5945 struct frame *f;
5947 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5949 x_free_frame_resources (f);
5950 dpyinfo->reference_count--;
5954 /* Setting window manager hints. */
5956 /* Set the normal size hints for the window manager, for frame F.
5957 FLAGS is the flags word to use--or 0 meaning preserve the flags
5958 that the window now has.
5959 If USER_POSITION is nonzero, we set the USPosition
5960 flag (this is useful when FLAGS is 0). */
5961 void
5962 x_wm_set_size_hint (f, flags, user_position)
5963 struct frame *f;
5964 long flags;
5965 int user_position;
5967 Window window = FRAME_W32_WINDOW (f);
5969 enter_crit ();
5971 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
5972 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
5973 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
5974 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
5976 leave_crit ();
5979 /* Window manager things */
5980 void
5981 x_wm_set_icon_position (f, icon_x, icon_y)
5982 struct frame *f;
5983 int icon_x, icon_y;
5985 #if 0
5986 Window window = FRAME_W32_WINDOW (f);
5988 f->display.x->wm_hints.flags |= IconPositionHint;
5989 f->display.x->wm_hints.icon_x = icon_x;
5990 f->display.x->wm_hints.icon_y = icon_y;
5992 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
5993 #endif
5997 /***********************************************************************
5998 Initialization
5999 ***********************************************************************/
6001 static int w32_initialized = 0;
6003 void
6004 w32_initialize_display_info (display_name)
6005 Lisp_Object display_name;
6007 struct w32_display_info *dpyinfo = &one_w32_display_info;
6009 bzero (dpyinfo, sizeof (*dpyinfo));
6011 /* Put it on w32_display_name_list. */
6012 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6013 w32_display_name_list);
6014 dpyinfo->name_list_element = XCAR (w32_display_name_list);
6016 dpyinfo->w32_id_name
6017 = (char *) xmalloc (SCHARS (Vinvocation_name)
6018 + SCHARS (Vsystem_name)
6019 + 2);
6020 sprintf (dpyinfo->w32_id_name, "%s@%s",
6021 SDATA (Vinvocation_name), SDATA (Vsystem_name));
6023 /* Default Console mode values - overridden when running in GUI mode
6024 with values obtained from system metrics. */
6025 dpyinfo->resx = 1;
6026 dpyinfo->resy = 1;
6027 dpyinfo->n_planes = 1;
6028 dpyinfo->n_cbits = 4;
6029 dpyinfo->n_fonts = 0;
6030 dpyinfo->smallest_font_height = 1;
6031 dpyinfo->smallest_char_width = 1;
6033 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6034 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6035 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
6036 dpyinfo->mouse_face_window = Qnil;
6037 dpyinfo->mouse_face_overlay = Qnil;
6038 dpyinfo->mouse_face_hidden = 0;
6040 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
6041 /* TODO: dpyinfo->gray */
6045 /* Create an xrdb-style database of resources to supercede registry settings.
6046 The database is just a concatenation of C strings, finished by an additional
6047 \0. The strings are submitted to some basic normalization, so
6049 [ *]option[ *]:[ *]value...
6051 becomes
6053 option:value...
6055 but any whitespace following value is not removed. */
6057 static char *
6058 w32_make_rdb (xrm_option)
6059 char *xrm_option;
6061 char *buffer = xmalloc (strlen (xrm_option) + 2);
6062 char *current = buffer;
6063 char ch;
6064 int in_option = 1;
6065 int before_value = 0;
6067 do {
6068 ch = *xrm_option++;
6070 if (ch == '\n')
6072 *current++ = '\0';
6073 in_option = 1;
6074 before_value = 0;
6076 else if (ch != ' ')
6078 *current++ = ch;
6079 if (in_option && (ch == ':'))
6081 in_option = 0;
6082 before_value = 1;
6084 else if (before_value)
6086 before_value = 0;
6089 else if (!(in_option || before_value))
6091 *current++ = ch;
6093 } while (ch);
6095 *current = '\0';
6097 return buffer;
6100 void
6101 x_flush (struct frame * f)
6102 { /* Nothing to do */ }
6105 extern frame_parm_handler w32_frame_parm_handlers[];
6107 static struct redisplay_interface w32_redisplay_interface =
6109 w32_frame_parm_handlers,
6110 x_produce_glyphs,
6111 x_write_glyphs,
6112 x_insert_glyphs,
6113 x_clear_end_of_line,
6114 x_scroll_run,
6115 x_after_update_window_line,
6116 x_update_window_begin,
6117 x_update_window_end,
6118 x_cursor_to,
6119 x_flush,
6120 0, /* flush_display_optional */
6121 x_clear_window_mouse_face,
6122 x_get_glyph_overhangs,
6123 x_fix_overlapping_area,
6124 w32_draw_fringe_bitmap,
6125 w32_define_fringe_bitmap,
6126 w32_destroy_fringe_bitmap,
6127 w32_compute_glyph_string_overhangs,
6128 x_draw_glyph_string,
6129 w32_define_frame_cursor,
6130 w32_clear_frame_area,
6131 w32_draw_window_cursor,
6132 w32_draw_vertical_window_border,
6133 w32_shift_glyphs_for_insert
6136 static void x_delete_terminal (struct terminal *term);
6138 static struct terminal *
6139 w32_create_terminal (struct w32_display_info *dpyinfo)
6141 struct terminal *terminal;
6143 terminal = create_terminal ();
6145 terminal->type = output_w32;
6146 terminal->display_info.w32 = dpyinfo;
6147 dpyinfo->terminal = terminal;
6149 /* MSVC does not type K&R functions with no arguments correctly, and
6150 so we must explicitly cast them. */
6151 terminal->clear_frame_hook = x_clear_frame;
6152 terminal->ins_del_lines_hook = x_ins_del_lines;
6153 terminal->delete_glyphs_hook = x_delete_glyphs;
6154 terminal->ring_bell_hook = w32_ring_bell;
6155 terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
6156 terminal->set_terminal_modes_hook = w32_set_terminal_modes;
6157 terminal->update_begin_hook = x_update_begin;
6158 terminal->update_end_hook = x_update_end;
6159 terminal->set_terminal_window_hook = w32_set_terminal_window;
6160 terminal->read_socket_hook = w32_read_socket;
6161 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
6162 terminal->mouse_position_hook = w32_mouse_position;
6163 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
6164 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
6165 // terminal->fullscreen_hook = XTfullscreen_hook;
6166 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6167 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6168 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6169 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
6171 terminal->delete_frame_hook = x_destroy_window;
6172 terminal->delete_terminal_hook = x_delete_terminal;
6174 terminal->rif = &w32_redisplay_interface;
6175 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
6176 terminal->char_ins_del_ok = 1;
6177 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
6178 terminal->fast_clear_end_of_line = 1; /* X does this well. */
6179 terminal->memory_below_frame = 0; /* We don't remember what scrolls
6180 off the bottom. */
6182 /* We don't yet support separate terminals on W32, so don't try to share
6183 keyboards between virtual terminals that are on the same physical
6184 terminal like X does. */
6185 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
6186 init_kboard (terminal->kboard);
6187 terminal->kboard->Vwindow_system = intern ("w32");
6188 terminal->kboard->next_kboard = all_kboards;
6189 all_kboards = terminal->kboard;
6190 /* Don't let the initial kboard remain current longer than necessary.
6191 That would cause problems if a file loaded on startup tries to
6192 prompt in the mini-buffer. */
6193 if (current_kboard == initial_kboard)
6194 current_kboard = terminal->kboard;
6195 terminal->kboard->reference_count++;
6197 return terminal;
6200 static void
6201 x_delete_terminal (struct terminal *terminal)
6203 struct w32_display_info *dpyinfo = terminal->display_info.w32;
6204 int i;
6206 /* Protect against recursive calls. delete_frame in
6207 delete_terminal calls us back when it deletes our last frame. */
6208 if (!terminal->name)
6209 return;
6211 BLOCK_INPUT;
6213 x_delete_display (dpyinfo);
6214 UNBLOCK_INPUT;
6217 struct w32_display_info *
6218 w32_term_init (display_name, xrm_option, resource_name)
6219 Lisp_Object display_name;
6220 char *xrm_option;
6221 char *resource_name;
6223 struct w32_display_info *dpyinfo;
6224 struct terminal *terminal;
6225 HDC hdc;
6227 BLOCK_INPUT;
6229 if (!w32_initialized)
6231 w32_initialize ();
6232 w32_initialized = 1;
6235 w32_initialize_display_info (display_name);
6237 dpyinfo = &one_w32_display_info;
6238 terminal = w32_create_terminal (dpyinfo);
6240 /* Set the name of the terminal. */
6241 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
6242 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
6243 terminal->name[SBYTES (display_name)] = 0;
6245 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6247 /* Put this display on the chain. */
6248 dpyinfo->next = x_display_list;
6249 x_display_list = dpyinfo;
6251 hdc = GetDC (NULL);
6253 dpyinfo->root_window = GetDesktopWindow ();
6254 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6255 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
6256 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6257 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
6258 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
6259 ReleaseDC (NULL, hdc);
6261 /* initialise palette with white and black */
6263 XColor color;
6264 w32_defined_color (0, "white", &color, 1);
6265 w32_defined_color (0, "black", &color, 1);
6268 /* Add the default keyboard. */
6269 add_keyboard_wait_descriptor (0);
6271 /* Create Fringe Bitmaps and store them for later use.
6273 On W32, bitmaps are all unsigned short, as Windows requires
6274 bitmap data to be Word aligned. For some reason they are
6275 horizontally reflected compared to how they appear on X, so we
6276 need to bitswap and convert to unsigned shorts before creating
6277 the bitmaps. */
6278 w32_init_fringe (terminal->rif);
6280 #ifdef F_SETOWN
6281 fcntl (connection, F_SETOWN, getpid ());
6282 #endif /* ! defined (F_SETOWN) */
6284 #ifdef SIGIO
6285 if (interrupt_input)
6286 init_sigio (connection);
6287 #endif /* ! defined (SIGIO) */
6289 UNBLOCK_INPUT;
6291 return dpyinfo;
6294 /* Get rid of display DPYINFO, assuming all frames are already gone. */
6295 void
6296 x_delete_display (dpyinfo)
6297 struct w32_display_info *dpyinfo;
6299 /* Discard this display from w32_display_name_list and w32_display_list.
6300 We can't use Fdelq because that can quit. */
6301 if (! NILP (w32_display_name_list)
6302 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6303 w32_display_name_list = XCDR (w32_display_name_list);
6304 else
6306 Lisp_Object tail;
6308 tail = w32_display_name_list;
6309 while (CONSP (tail) && CONSP (XCDR (tail)))
6311 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
6313 XSETCDR (tail, XCDR (XCDR (tail)));
6314 break;
6316 tail = XCDR (tail);
6320 /* free palette table */
6322 struct w32_palette_entry * plist;
6324 plist = dpyinfo->color_list;
6325 while (plist)
6327 struct w32_palette_entry * pentry = plist;
6328 plist = plist->next;
6329 xfree (pentry);
6331 dpyinfo->color_list = NULL;
6332 if (dpyinfo->palette)
6333 DeleteObject(dpyinfo->palette);
6335 xfree (dpyinfo->w32_id_name);
6337 w32_reset_fringes ();
6340 /* Set up use of W32. */
6342 DWORD WINAPI w32_msg_worker (void * arg);
6344 static void
6345 w32_initialize ()
6347 HANDLE shell;
6348 HRESULT (WINAPI * set_user_model) (wchar_t * id);
6350 baud_rate = 19200;
6352 w32_system_caret_hwnd = NULL;
6353 w32_system_caret_height = 0;
6354 w32_system_caret_x = 0;
6355 w32_system_caret_y = 0;
6357 /* On Windows 7 and later, we need to set the user model ID
6358 to associate emacsclient launched files with Emacs frames
6359 in the UI. */
6360 shell = GetModuleHandle ("shell32.dll");
6361 if (shell)
6363 set_user_model
6364 = (void *) GetProcAddress (shell,
6365 "SetCurrentProcessExplicitAppUserModelID");
6367 /* If the function is defined, then we are running on Windows 7
6368 or newer, and the UI uses this to group related windows
6369 together. Since emacs, runemacs, emacsclient are related, we
6370 want them grouped even though the executables are different,
6371 so we need to set a consistent ID between them. */
6372 if (set_user_model)
6373 set_user_model (L"GNU.Emacs");
6376 /* Initialize w32_use_visible_system_caret based on whether a screen
6377 reader is in use. */
6378 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6379 &w32_use_visible_system_caret, 0))
6380 w32_use_visible_system_caret = 0;
6382 last_tool_bar_item = -1;
6383 any_help_event_p = 0;
6385 /* Initialize input mode: interrupt_input off, no flow control, allow
6386 8 bit character input, standard quit char. */
6387 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
6390 DWORD input_locale_id = (DWORD) GetKeyboardLayout (0);
6391 keyboard_codepage = codepage_for_locale ((LCID) (input_locale_id & 0xffff));
6394 /* Create the window thread - it will terminate itself when the app
6395 terminates */
6396 init_crit ();
6398 dwMainThreadId = GetCurrentThreadId ();
6399 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
6400 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6402 /* Wait for thread to start */
6404 MSG msg;
6406 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6408 hWindowsThread = CreateThread (NULL, 0,
6409 w32_msg_worker,
6410 0, 0, &dwWindowsThreadId);
6412 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6415 /* It is desirable that mainThread should have the same notion of
6416 focus window and active window as windowsThread. Unfortunately, the
6417 following call to AttachThreadInput, which should do precisely what
6418 we need, causes major problems when Emacs is linked as a console
6419 program. Unfortunately, we have good reasons for doing that, so
6420 instead we need to send messages to windowsThread to make some API
6421 calls for us (ones that affect, or depend on, the active/focus
6422 window state.) */
6423 #ifdef ATTACH_THREADS
6424 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
6425 #endif
6427 /* Dynamically link to optional system components. */
6429 HMODULE user_lib = GetModuleHandle ("user32.dll");
6431 #define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
6433 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
6435 #undef LOAD_PROC
6437 /* Ensure scrollbar handle is at least 5 pixels. */
6438 vertical_scroll_bar_min_handle = 5;
6440 /* For either kind of scroll bar, take account of the arrows; these
6441 effectively form the border of the main scroll bar range. */
6442 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6443 = GetSystemMetrics (SM_CYVSCROLL);
6447 void
6448 syms_of_w32term ()
6450 staticpro (&w32_display_name_list);
6451 w32_display_name_list = Qnil;
6453 staticpro (&last_mouse_scroll_bar);
6454 last_mouse_scroll_bar = Qnil;
6456 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
6458 DEFVAR_INT ("w32-num-mouse-buttons",
6459 &w32_num_mouse_buttons,
6460 doc: /* Number of physical mouse buttons. */);
6461 w32_num_mouse_buttons = 2;
6463 DEFVAR_LISP ("w32-swap-mouse-buttons",
6464 &Vw32_swap_mouse_buttons,
6465 doc: /* Swap the mapping of middle and right mouse buttons.
6466 When nil, middle button is mouse-2 and right button is mouse-3. */);
6467 Vw32_swap_mouse_buttons = Qnil;
6469 DEFVAR_LISP ("w32-grab-focus-on-raise",
6470 &Vw32_grab_focus_on_raise,
6471 doc: /* Raised frame grabs input focus.
6472 When t, `raise-frame' grabs input focus as well. This fits well
6473 with the normal Windows click-to-focus policy, but might not be
6474 desirable when using a point-to-focus policy. */);
6475 Vw32_grab_focus_on_raise = Qt;
6477 DEFVAR_LISP ("w32-capslock-is-shiftlock",
6478 &Vw32_capslock_is_shiftlock,
6479 doc: /* Apply CapsLock state to non character input keys.
6480 When nil, CapsLock only affects normal character input keys. */);
6481 Vw32_capslock_is_shiftlock = Qnil;
6483 DEFVAR_LISP ("w32-recognize-altgr",
6484 &Vw32_recognize_altgr,
6485 doc: /* Recognize right-alt and left-ctrl as AltGr.
6486 When nil, the right-alt and left-ctrl key combination is
6487 interpreted normally. */);
6488 Vw32_recognize_altgr = Qt;
6490 DEFVAR_BOOL ("w32-use-visible-system-caret",
6491 &w32_use_visible_system_caret,
6492 doc: /* Flag to make the system caret visible.
6493 When this is non-nil, Emacs will indicate the position of point by
6494 using the system caret instead of drawing its own cursor. Some screen
6495 reader software does not track the system cursor properly when it is
6496 invisible, and gets confused by Emacs drawing its own cursor, so this
6497 variable is initialized to t when Emacs detects that screen reader
6498 software is running as it starts up.
6500 When this variable is set, other variables affecting the appearance of
6501 the cursor have no effect. */);
6503 w32_use_visible_system_caret = 0;
6505 /* We don't yet support this, but defining this here avoids whining
6506 from cus-start.el and other places, like "M-x set-variable". */
6507 DEFVAR_BOOL ("x-use-underline-position-properties",
6508 &x_use_underline_position_properties,
6509 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
6510 A value of nil means ignore them. If you encounter fonts with bogus
6511 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6512 to 4.1, set this to nil. */);
6513 x_use_underline_position_properties = 0;
6515 DEFVAR_BOOL ("x-underline-at-descent-line",
6516 &x_underline_at_descent_line,
6517 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
6518 A value of nil means to draw the underline according to the value of the
6519 variable `x-use-underline-position-properties', which is usually at the
6520 baseline level. The default value is nil. */);
6521 x_underline_at_descent_line = 0;
6523 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
6524 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
6525 Vx_toolkit_scroll_bars = Qt;
6527 staticpro (&last_mouse_motion_frame);
6528 last_mouse_motion_frame = Qnil;
6531 /* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
6532 (do not change this comment) */