* window.h (Vmouse_window, Vmouse_event): Remove the leftovers.
[bpt/emacs.git] / src / w32term.c
CommitLineData
b46a6a83 1/* Implementation of GUI terminal on the Microsoft Windows API.
e9bffc61 2
ab422c4d 3Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
ee78dc32
GV
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
ee78dc32 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
ee78dc32
GV
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
ee78dc32 19
ee78dc32 20#include <config.h>
68c45bf0 21#include <signal.h>
ee78dc32
GV
22#include <stdio.h>
23#include "lisp.h"
24#include "blockinput.h"
689004fa 25#include "w32term.h"
ee78dc32
GV
26
27#include "systty.h"
28#include "systime.h"
29
30#include <ctype.h>
31#include <errno.h>
ee78dc32 32#include <sys/stat.h>
c902b920 33#include <imm.h>
ee78dc32 34
66f30e44
JR
35#include "charset.h"
36#include "character.h"
37#include "coding.h"
38#include "ccl.h"
ee78dc32
GV
39#include "frame.h"
40#include "dispextern.h"
93ff4395 41#include "fontset.h"
ee78dc32
GV
42#include "termhooks.h"
43#include "termopts.h"
44#include "termchar.h"
ee78dc32
GV
45#include "disptab.h"
46#include "buffer.h"
47#include "window.h"
66f30e44 48#include "keyboard.h"
ee78dc32 49#include "intervals.h"
66f30e44
JR
50#include "process.h"
51#include "atimer.h"
52#include "keymap.h"
53
0fda9b75 54#ifdef WINDOWSNT
66f30e44 55#include "w32heap.h"
0fda9b75
DC
56#endif
57
58#ifndef WINDOWSNT
59#include <io.h> /* for get_osfhandle */
60#endif
61
66f30e44 62#include <shellapi.h>
ee78dc32 63
027f6f90 64#include "font.h"
ef39ccbb 65#include "w32font.h"
791f420f 66\f
33c34bea 67/* Fringe bitmaps. */
791f420f 68
0e9e9a2c
KS
69static int max_fringe_bmp = 0;
70static HBITMAP *fringe_bmp = 0;
791f420f 71
706ddb8f 72/* Temporary variables for w32_read_socket. */
791f420f 73
706ddb8f
JR
74static int last_mousemove_x = 0;
75static int last_mousemove_y = 0;
791f420f 76
af3a05ed
JR
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
81
791f420f
JR
82/* Non-zero means that a HELP_EVENT has been generated since Emacs
83 start. */
84
85static int any_help_event_p;
86
a18bb28d
JR
87/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
88static Lisp_Object last_window;
89
e7efd97e
GV
90extern unsigned int msh_mousewheel;
91
b56ceb92 92extern void free_frame_menubar (struct frame *);
ee78dc32 93
9ef2e2cf 94extern int w32_codepage_for_font (char *fontname);
2bf04b9d 95extern Cursor w32_load_cursor (LPCTSTR name);
9ef2e2cf 96
ee78dc32
GV
97#define x_any_window_to_frame x_window_to_frame
98#define x_top_window_to_frame x_window_to_frame
99
100\f
fbd6baed
GV
101/* This is display since w32 does not support multiple ones. */
102struct w32_display_info one_w32_display_info;
8c3b00cb 103struct w32_display_info *x_display_list;
ee78dc32
GV
104
105/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
fbd6baed 106 one for each element of w32_display_list and in the same order.
ee78dc32
GV
107 NAME is the name of the frame.
108 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
fbd6baed 109Lisp_Object w32_display_name_list;
ee78dc32 110
41375f89 111
b88b62de 112#if _WIN32_WINNT < 0x0500 && !defined(_W64)
41375f89 113/* Pre Windows 2000, this was not available, but define it here so
b88b62de
EZ
114 that Emacs compiled on such a platform will run on newer versions.
115 MinGW64 (_W64) defines these unconditionally, so avoid redefining. */
41375f89
JR
116
117typedef struct tagWCRANGE
118{
119 WCHAR wcLow;
120 USHORT cGlyphs;
121} WCRANGE;
122
65a6ff8f 123typedef struct tagGLYPHSET
41375f89
JR
124{
125 DWORD cbThis;
126 DWORD flAccel;
127 DWORD cGlyphsSupported;
128 DWORD cRanges;
129 WCRANGE ranges[1];
65a6ff8f 130} GLYPHSET;
41375f89 131
0fda9b75 132#endif /* compiling for pre-Win2k */
41375f89 133
8b61a891 134/* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */
ff90fbde 135BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
8b61a891
JR
136
137#ifndef LWA_ALPHA
138#define LWA_ALPHA 0x02
139#endif
ec7e221c
JR
140/* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
141 later targets by MSVC headers. */
142#ifndef WS_EX_LAYERED
143#define WS_EX_LAYERED 0x80000
144#endif
41375f89 145
cf13177e
YM
146/* SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN are not defined on 95 and
147 NT4. */
148#ifndef SM_CXVIRTUALSCREEN
149#define SM_CXVIRTUALSCREEN 78
150#endif
151#ifndef SM_CYVIRTUALSCREEN
152#define SM_CYVIRTUALSCREEN 79
153#endif
154
ee78dc32
GV
155/* This is a frame waiting to be autoraised, within w32_read_socket. */
156struct frame *pending_autoraise_frame;
157
abb15ebd
JR
158/* The handle of the frame that currently owns the system caret. */
159HWND w32_system_caret_hwnd;
abb15ebd
JR
160int w32_system_caret_height;
161int w32_system_caret_x;
162int w32_system_caret_y;
b932cad7
EZ
163struct window *w32_system_caret_window;
164int w32_system_caret_hdr_height;
165int w32_system_caret_mode_height;
e9e23e23
GV
166DWORD dwWindowsThreadId = 0;
167HANDLE hWindowsThread = NULL;
ee78dc32
GV
168DWORD dwMainThreadId = 0;
169HANDLE hMainThread = NULL;
170
689004fa
GV
171int vertical_scroll_bar_min_handle;
172int vertical_scroll_bar_top_border;
173int vertical_scroll_bar_bottom_border;
174
175int last_scroll_bar_drag_pos;
176
302fc036
EZ
177/* Keyboard code page - may be changed by language-change events. */
178int w32_keyboard_codepage;
179
ee78dc32
GV
180/* Mouse movement. */
181
182/* Where the mouse was last time we reported a mouse event. */
ee78dc32 183static RECT last_mouse_glyph;
a10c8269 184static struct frame *last_mouse_glyph_frame;
ee78dc32
GV
185
186/* The scroll bar in which the last motion event occurred.
187
188 If the last motion event occurred in a scroll bar, we set this
fbd6baed 189 so w32_mouse_position can know whether to report a scroll bar motion or
ee78dc32
GV
190 an ordinary motion.
191
192 If the last motion event didn't occur in a scroll bar, we set this
fbd6baed 193 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
9ef2e2cf
JR
194static Lisp_Object last_mouse_scroll_bar;
195static int last_mouse_scroll_bar_pos;
ee78dc32 196
fbd6baed 197/* This is a hack. We would really prefer that w32_mouse_position would
ee78dc32 198 return the time associated with the position it returns, but there
9ef2e2cf 199 doesn't seem to be any way to wrest the time-stamp from the server
ee78dc32
GV
200 along with the position query. So, we just keep track of the time
201 of the last movement we received, and return that in hopes that
202 it's somewhat accurate. */
9ef2e2cf
JR
203static Time last_mouse_movement_time;
204
205/* Incremented by w32_read_socket whenever it really tries to read
206 events. */
ee78dc32 207static int volatile input_signal_count;
ee78dc32 208
0fda9b75
DC
209#ifdef CYGWIN
210int w32_message_fd = -1;
211#endif /* CYGWIN */
212
f57e2426
J
213static void w32_handle_tool_bar_click (struct frame *,
214 struct input_event *);
215static void w32_define_cursor (Window, Cursor);
216
217void x_lower_frame (struct frame *);
218void x_scroll_bar_clear (struct frame *);
18e27ea8 219void x_wm_set_size_hint (struct frame *, long, bool);
f57e2426
J
220void x_raise_frame (struct frame *);
221void x_set_window_size (struct frame *, int, int, int);
222void x_wm_set_window_state (struct frame *, int);
223void x_wm_set_icon_pixmap (struct frame *, int);
224static void w32_initialize (void);
225static void x_update_end (struct frame *);
226static void w32_frame_up_to_date (struct frame *);
f57e2426
J
227static void x_clear_frame (struct frame *);
228static void frame_highlight (struct frame *);
229static void frame_unhighlight (struct frame *);
230static void x_new_focus_frame (struct w32_display_info *,
231 struct frame *);
232static void x_focus_changed (int, int, struct w32_display_info *,
233 struct frame *, struct input_event *);
234static void w32_detect_focus_change (struct w32_display_info *,
235 W32Msg *, struct input_event *);
236static void w32_frame_rehighlight (struct frame *);
237static void x_frame_rehighlight (struct w32_display_info *);
238static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
239static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
240 enum text_cursor_kinds);
c3c4768d
DA
241static void w32_clip_to_row (struct window *, struct glyph_row *,
242 enum glyph_row_area, HDC);
f57e2426
J
243static BOOL my_show_window (struct frame *, HWND, int);
244static void my_set_window_pos (HWND, HWND, int, int, int, int, UINT);
361358ea 245#if 0
f57e2426 246static void my_set_focus (struct frame *, HWND);
361358ea 247#endif
f57e2426
J
248static void my_set_foreground_window (HWND);
249static void my_destroy_window (struct frame *, HWND);
a10c8269 250static void w32fullscreen_hook (struct frame *);
791f420f 251
e509cfa6 252#ifdef GLYPH_DEBUG
784b56e2
EZ
253static void x_check_font (struct frame *, struct font *);
254#endif
255
ee78dc32 256static Lisp_Object Qvendor_specific_keysyms;
477f1e50
EZ
257static Lisp_Object Qadded, Qremoved, Qmodified;
258static Lisp_Object Qrenamed_from, Qrenamed_to;
ee78dc32 259
ee78dc32 260\f
9ef2e2cf
JR
261/***********************************************************************
262 Debugging
263 ***********************************************************************/
264
ee78dc32 265#if 0
9ef2e2cf
JR
266
267/* This is a function useful for recording debugging information about
268 the sequence of occurrences in this file. */
ee78dc32 269
d67d1627 270struct record
ee78dc32
GV
271{
272 char *locus;
273 int type;
274};
275
276struct record event_record[100];
277
278int event_record_index;
279
b56ceb92 280record_event (char *locus, int type)
ee78dc32
GV
281{
282 if (event_record_index == sizeof (event_record) / sizeof (struct record))
283 event_record_index = 0;
284
285 event_record[event_record_index].locus = locus;
286 event_record[event_record_index].type = type;
287 event_record_index++;
288}
289
290#endif /* 0 */
291\f
791f420f 292
c65fd370 293void
b56ceb92 294XChangeGC (void *ignore, XGCValues *gc, unsigned long mask,
c65fd370 295 XGCValues *xgcv)
791f420f
JR
296{
297 if (mask & GCForeground)
298 gc->foreground = xgcv->foreground;
299 if (mask & GCBackground)
300 gc->background = xgcv->background;
301 if (mask & GCFont)
302 gc->font = xgcv->font;
303}
304
b56ceb92
JB
305XGCValues *
306XCreateGC (void *ignore, Window window, unsigned long mask, XGCValues *xgcv)
791f420f 307{
23f86fce 308 XGCValues *gc = xzalloc (sizeof (XGCValues));
791f420f
JR
309
310 XChangeGC (ignore, gc, mask, xgcv);
311
312 return gc;
313}
314
c65fd370 315void
b56ceb92
JB
316XGetGCValues (void *ignore, XGCValues *gc,
317 unsigned long mask, XGCValues *xgcv)
791f420f
JR
318{
319 XChangeGC (ignore, xgcv, mask, gc);
320}
321
791f420f
JR
322static void
323w32_set_clip_rectangle (HDC hdc, RECT *rect)
324{
325 if (rect)
326 {
327 HRGN clip_region = CreateRectRgnIndirect (rect);
328 SelectClipRgn (hdc, clip_region);
329 DeleteObject (clip_region);
330 }
331 else
332 SelectClipRgn (hdc, NULL);
333}
334
9b0e3eba
AA
335/* Restore clipping rectangle in S */
336static void
337w32_restore_glyph_string_clip (struct glyph_string *s)
338{
339 RECT *r = s->clip;
340 int n = s->num_clips;
341
342 if (n == 1)
343 w32_set_clip_rectangle (s->hdc, r);
344 else if (n > 1)
345 {
346 HRGN clip1 = CreateRectRgnIndirect (r);
347 HRGN clip2 = CreateRectRgnIndirect (r + 1);
348 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
349 SelectClipRgn (s->hdc, clip1);
350 DeleteObject (clip1);
351 DeleteObject (clip2);
352 }
353}
354
355/*
356 Draw a wavy line under S. The wave fills wave_height pixels from y0.
357
358 x0 wave_length = 2
359 --
360 y0 * * * * *
361 |* * * * * * * * *
362 wave_height = 3 | * * * *
363
364*/
365
366void
367w32_draw_underwave (struct glyph_string *s, COLORREF color)
368{
f032a318 369 int wave_height = 3, wave_length = 2;
9b0e3eba
AA
370 int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
371 XRectangle wave_clip, string_clip, final_clip;
372 RECT w32_final_clip, w32_string_clip;
373 HPEN hp, oldhp;
374
375 dx = wave_length;
376 dy = wave_height - 1;
377 x0 = s->x;
f032a318 378 y0 = s->ybase - wave_height + 3;
9b0e3eba
AA
379 width = s->width;
380 xmax = x0 + width;
381
382 /* Find and set clipping rectangle */
383
62aba0d4
FP
384 wave_clip.x = x0;
385 wave_clip.y = y0;
386 wave_clip.width = width;
387 wave_clip.height = wave_height;
388
9b0e3eba
AA
389 get_glyph_string_clip_rect (s, &w32_string_clip);
390 CONVERT_TO_XRECT (string_clip, w32_string_clip);
391
392 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
393 return;
394
395 hp = CreatePen (PS_SOLID, 0, color);
396 oldhp = SelectObject (s->hdc, hp);
397 CONVERT_FROM_XRECT (final_clip, w32_final_clip);
398 w32_set_clip_rectangle (s->hdc, &w32_final_clip);
399
400 /* Draw the waves */
401
402 x1 = x0 - (x0 % dx);
403 x2 = x1 + dx;
404 odd = (x1/dx) % 2;
405 y1 = y2 = y0;
406
407 if (odd)
408 y1 += dy;
409 else
410 y2 += dy;
411
412 MoveToEx (s->hdc, x1, y1, NULL);
413
414 while (x1 <= xmax)
415 {
416 LineTo (s->hdc, x2, y2);
417 x1 = x2, y1 = y2;
418 x2 += dx, y2 = y0 + odd*dy;
419 odd = !odd;
420 }
421
422 /* Restore previous pen and clipping rectangle(s) */
423 w32_restore_glyph_string_clip (s);
424 SelectObject (s->hdc, oldhp);
425 DeleteObject (hp);
426}
791f420f
JR
427
428/* Draw a hollow rectangle at the specified position. */
429void
430w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
431 int width, int height)
432{
433 HBRUSH hb, oldhb;
434 HPEN hp, oldhp;
435
436 hb = CreateSolidBrush (gc->background);
437 hp = CreatePen (PS_SOLID, 0, gc->foreground);
438 oldhb = SelectObject (hdc, hb);
439 oldhp = SelectObject (hdc, hp);
440
441 Rectangle (hdc, x, y, x + width, y + height);
442
443 SelectObject (hdc, oldhb);
444 SelectObject (hdc, oldhp);
445 DeleteObject (hb);
446 DeleteObject (hp);
447}
448
449/* Draw a filled rectangle at the specified position. */
d67d1627 450void
a10c8269 451w32_fill_rect (struct frame *f, HDC hdc, COLORREF pix, RECT *lprect)
ee78dc32 452{
ee78dc32 453 HBRUSH hb;
791f420f 454
ee78dc32 455 hb = CreateSolidBrush (pix);
ee78dc32 456 FillRect (hdc, lprect, hb);
ee78dc32 457 DeleteObject (hb);
ee78dc32
GV
458}
459
d67d1627 460void
a10c8269 461w32_clear_window (struct frame *f)
ee78dc32
GV
462{
463 RECT rect;
00fe468b 464 HDC hdc = get_frame_dc (f);
52cf03a1 465
e4a52412
JR
466 /* Under certain conditions, this can be called at startup with
467 a console frame pointer before the GUI frame is created. An HDC
468 of 0 indicates this. */
469 if (hdc)
470 {
471 GetClientRect (FRAME_W32_WINDOW (f), &rect);
472 w32_clear_rect (f, hdc, &rect);
473 }
474
00fe468b 475 release_frame_dc (f, hdc);
ee78dc32
GV
476}
477
8b61a891
JR
478#define OPAQUE_FRAME 255
479
480void
b56ceb92 481x_set_frame_alpha (struct frame *f)
8b61a891
JR
482{
483 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
484 double alpha = 1.0;
485 double alpha_min = 1.0;
486 BYTE opac;
487 LONG ex_style;
488 HWND window = FRAME_W32_WINDOW (f);
489
490 /* Older versions of Windows do not support transparency. */
491 if (!pfnSetLayeredWindowAttributes)
492 return;
493
494 if (dpyinfo->x_highlight_frame == f)
495 alpha = f->alpha[0];
496 else
497 alpha = f->alpha[1];
498
499 if (FLOATP (Vframe_alpha_lower_limit))
500 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
501 else if (INTEGERP (Vframe_alpha_lower_limit))
502 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
503
2f8e69cc
CY
504 if (alpha < 0.0)
505 return;
506 else if (alpha > 1.0)
8b61a891
JR
507 alpha = 1.0;
508 else if (alpha < alpha_min && alpha_min <= 1.0)
509 alpha = alpha_min;
510
511 opac = alpha * OPAQUE_FRAME;
512
513 ex_style = GetWindowLong (window, GWL_EXSTYLE);
514
515 if (opac == OPAQUE_FRAME)
4e179b19 516 ex_style &= ~WS_EX_LAYERED;
8b61a891
JR
517 else
518 ex_style |= WS_EX_LAYERED;
519
520 SetWindowLong (window, GWL_EXSTYLE, ex_style);
521
522 if (opac != OPAQUE_FRAME)
523 pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
524}
525
b89c78a5 526int
b56ceb92 527x_display_pixel_height (struct w32_display_info *dpyinfo)
b89c78a5 528{
cf13177e
YM
529 int pixels = GetSystemMetrics (SM_CYVIRTUALSCREEN);
530
531 if (pixels == 0)
532 /* Fallback for Windows 95 or NT 4.0. */
533 pixels = GetSystemMetrics (SM_CYSCREEN);
534
cb4a3e42 535 return pixels;
b89c78a5
CY
536}
537
538int
b56ceb92 539x_display_pixel_width (struct w32_display_info *dpyinfo)
b89c78a5 540{
cf13177e
YM
541 int pixels = GetSystemMetrics (SM_CXVIRTUALSCREEN);
542
543 if (pixels == 0)
544 /* Fallback for Windows 95 or NT 4.0. */
545 pixels = GetSystemMetrics (SM_CXSCREEN);
546
cb4a3e42 547 return pixels;
b89c78a5
CY
548}
549
ee78dc32 550\f
791f420f
JR
551/***********************************************************************
552 Starting and ending an update
553 ***********************************************************************/
d67d1627 554
791f420f
JR
555/* Start an update of frame F. This function is installed as a hook
556 for update_begin, i.e. it is called when update_begin is called.
557 This function is called prior to calls to x_update_window_begin for
99012074 558 each window being updated. */
ee78dc32 559
96214669 560static void
b56ceb92 561x_update_begin (struct frame *f)
ee78dc32 562{
99012074
AI
563 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
564
7e6ac5b9
AI
565 if (! FRAME_W32_P (f))
566 return;
567
99012074
AI
568 /* Regenerate display palette before drawing if list of requested
569 colors has changed. */
570 if (display_info->regen_palette)
571 {
572 w32_regenerate_palette (f);
573 display_info->regen_palette = FALSE;
574 }
791f420f 575}
ee78dc32 576
791f420f 577
f60e429a 578/* Start update of window W. */
791f420f
JR
579
580static void
b56ceb92 581x_update_window_begin (struct window *w)
791f420f
JR
582{
583 struct frame *f = XFRAME (WINDOW_FRAME (w));
bbf534ce 584 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
791f420f 585
99558ce8 586 /* Hide the system caret during an update. */
9785d95b
BK
587 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
588 {
589 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
590 }
99558ce8 591
f60e429a 592 w->output_cursor = w->cursor;
ee78dc32 593
4d7e6e51 594 block_input ();
ee78dc32 595
bbf534ce 596 if (f == hlinfo->mouse_face_mouse_frame)
ee78dc32
GV
597 {
598 /* Don't do highlighting for mouse motion during the update. */
bbf534ce 599 hlinfo->mouse_face_defer = 1;
ee78dc32 600
9ef2e2cf
JR
601 /* If F needs to be redrawn, simply forget about any prior mouse
602 highlighting. */
ee78dc32 603 if (FRAME_GARBAGED_P (f))
bbf534ce 604 hlinfo->mouse_face_window = Qnil;
791f420f 605
ec48c3a7
JR
606#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
607 their mouse_face_p flag set, which means that they are always
608 unequal to rows in a desired matrix which never have that
609 flag set. So, rows containing mouse-face glyphs are never
610 scrolled, and we don't have to switch the mouse highlight off
611 here to prevent it from being scrolled. */
d67d1627 612
791f420f
JR
613 /* Can we tell that this update does not affect the window
614 where the mouse highlight is? If so, no need to turn off.
615 Likewise, don't do anything if the frame is garbaged;
616 in that case, the frame's current matrix that we would use
617 is all wrong, and we will redisplay that line anyway. */
bbf534ce
EZ
618 if (!NILP (hlinfo->mouse_face_window)
619 && w == XWINDOW (hlinfo->mouse_face_window))
ee78dc32 620 {
791f420f 621 int i;
ee78dc32 622
791f420f
JR
623 for (i = 0; i < w->desired_matrix->nrows; ++i)
624 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
ee78dc32
GV
625 break;
626
791f420f 627 if (i < w->desired_matrix->nrows)
bbf534ce 628 clear_mouse_face (hlinfo);
ee78dc32 629 }
ec48c3a7 630#endif /* 0 */
ee78dc32
GV
631 }
632
4d7e6e51 633 unblock_input ();
ee78dc32
GV
634}
635
89271099 636/* Draw a vertical window border from (x,y0) to (x,y1) */
791f420f 637
96214669 638static void
b56ceb92 639w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
ee78dc32 640{
791f420f 641 struct frame *f = XFRAME (WINDOW_FRAME (w));
89271099
KS
642 RECT r;
643 HDC hdc;
cf2c08ca 644 struct face *face;
1c64a4a2 645
89271099
KS
646 r.left = x;
647 r.right = x + 1;
648 r.top = y0;
649 r.bottom = y1;
d67d1627 650
89271099 651 hdc = get_frame_dc (f);
cf2c08ca
EZ
652 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
653 if (face)
654 w32_fill_rect (f, hdc, face->foreground, &r);
655 else
656 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
657
89271099 658 release_frame_dc (f, hdc);
791f420f 659}
ee78dc32 660
d67d1627 661
65620264 662/* End update of window W.
ec48c3a7
JR
663
664 Draw vertical borders between horizontally adjacent windows, and
665 display W's cursor if CURSOR_ON_P is non-zero.
666
667 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
668 glyphs in mouse-face were overwritten. In that case we have to
669 make sure that the mouse-highlight is properly redrawn.
670
671 W may be a menu bar pseudo-window in case we don't have X toolkit
672 support. Such windows don't have a cursor, so don't display it
673 here. */
791f420f
JR
674
675static void
9997ec56
DA
676x_update_window_end (struct window *w, bool cursor_on_p,
677 bool mouse_face_overwritten_p)
791f420f
JR
678{
679 if (!w->pseudo_window_p)
680 {
4d7e6e51 681 block_input ();
ec48c3a7 682
791f420f 683 if (cursor_on_p)
f60e429a
DA
684 display_and_set_cursor (w, 1,
685 w->output_cursor.hpos, w->output_cursor.vpos,
686 w->output_cursor.x, w->output_cursor.y);
d67d1627 687
f94a2622
KS
688 if (draw_window_fringes (w, 1))
689 x_draw_vertical_border (w);
6b61353c 690
4d7e6e51 691 unblock_input ();
791f420f 692 }
9f5a911b
JR
693
694 /* If a row with mouse-face was overwritten, arrange for
695 XTframe_up_to_date to redisplay the mouse highlight. */
696 if (mouse_face_overwritten_p)
9fed9729 697 reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
9f5a911b 698
99558ce8
JR
699 /* Unhide the caret. This won't actually show the cursor, unless it
700 was visible before the corresponding call to HideCaret in
701 x_update_window_begin. */
9785d95b
BK
702 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
703 {
704 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
705 }
791f420f
JR
706}
707
9ef2e2cf
JR
708
709/* End update of frame F. This function is installed as a hook in
710 update_end. */
711
791f420f 712static void
b56ceb92 713x_update_end (struct frame *f)
791f420f 714{
7e6ac5b9
AI
715 if (! FRAME_W32_P (f))
716 return;
717
791f420f 718 /* Mouse highlight may be displayed again. */
bbf534ce 719 MOUSE_HL_INFO (f)->mouse_face_defer = 0;
ee78dc32
GV
720}
721
9ef2e2cf 722
65620264
DA
723/* This function is called from various places in xdisp.c
724 whenever a complete update has been performed. */
ee78dc32 725
96214669 726static void
b56ceb92 727w32_frame_up_to_date (struct frame *f)
ee78dc32 728{
791f420f 729 if (FRAME_W32_P (f))
5c747675 730 FRAME_MOUSE_UPDATE (f);
ee78dc32 731}
791f420f
JR
732
733
734/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
33c34bea 735 arrow bitmaps, or clear the fringes if no bitmaps are required
65620264 736 before DESIRED_ROW is made current. This function is called from
791f420f
JR
737 update_window_line only if it is known that there are differences
738 between bitmaps to be drawn between current row and DESIRED_ROW. */
739
740static void
65620264 741x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
791f420f 742{
6ff3e5e3
JR
743 struct frame *f;
744 int width, height;
745
a54e2c05 746 eassert (w);
d67d1627 747
791f420f 748 if (!desired_row->mode_line_p && !w->pseudo_window_p)
6b61353c 749 desired_row->redraw_fringe_bitmaps_p = 1;
791f420f 750
6ff3e5e3
JR
751 /* When a window has disappeared, make sure that no rest of
752 full-width rows stays visible in the internal border. Could
65620264 753 check here if updated window is the leftmost/rightmost window,
6ff3e5e3
JR
754 but I guess it's not worth doing since vertically split windows
755 are almost never used, internal border is rarely set, and the
756 overhead is very small. */
757 if (windows_or_buffers_changed
758 && desired_row->full_width_p
d3d50620 759 && (f = XFRAME (w->frame),
6ff3e5e3
JR
760 width = FRAME_INTERNAL_BORDER_WIDTH (f),
761 width != 0)
762 && (height = desired_row->visible_height,
763 height > 0))
764 {
765 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
89271099 766
4d7e6e51 767 block_input ();
6ff3e5e3
JR
768 {
769 HDC hdc = get_frame_dc (f);
770 w32_clear_area (f, hdc, 0, y, width, height);
62e50ec6 771 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
6ff3e5e3
JR
772 y, width, height);
773 release_frame_dc (f, hdc);
774 }
4d7e6e51 775 unblock_input ();
791f420f
JR
776 }
777}
778
779
33c34bea 780/* Draw the bitmap WHICH in one of the left or right fringes of
791f420f
JR
781 window W. ROW is the glyph row for which to display the bitmap; it
782 determines the vertical position at which the bitmap has to be
783 drawn. */
784
785static void
b56ceb92
JB
786w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
787 struct draw_fringe_bitmap_params *p)
791f420f
JR
788{
789 struct frame *f = XFRAME (WINDOW_FRAME (w));
b6ae1532
KS
790 HDC hdc;
791 struct face *face = p->face;
792
793 hdc = get_frame_dc (f);
791f420f 794
06929222
YM
795 if (!p->overlay_p)
796 {
797 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
798
799 /* If the fringe is adjacent to the left (right) scroll bar of a
800 leftmost (rightmost, respectively) window, then extend its
801 background to the gap between the fringe and the bar. */
802 if ((WINDOW_LEFTMOST_P (w)
803 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
804 || (WINDOW_RIGHTMOST_P (w)
805 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
806 {
807 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
808
809 if (sb_width > 0)
810 {
7db47798
YM
811 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
812 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
813 * FRAME_COLUMN_WIDTH (f));
06929222
YM
814
815 if (bx < 0)
816 {
817 /* Bitmap fills the fringe. */
7db47798
YM
818 if (bar_area_x + bar_area_width == p->x)
819 bx = bar_area_x + sb_width;
820 else if (p->x + p->wd == bar_area_x)
821 bx = bar_area_x;
06929222
YM
822 if (bx >= 0)
823 {
824 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
825
7db47798 826 nx = bar_area_width - sb_width;
06929222
YM
827 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
828 row->y));
829 ny = row->visible_height;
830 }
831 }
832 else
833 {
7db47798 834 if (bar_area_x + bar_area_width == bx)
06929222 835 {
7db47798
YM
836 bx = bar_area_x + sb_width;
837 nx += bar_area_width - sb_width;
06929222 838 }
7db47798
YM
839 else if (bx + nx == bar_area_x)
840 nx += bar_area_width - sb_width;
06929222
YM
841 }
842 }
843 }
844
845 if (bx >= 0 && nx > 0)
846 w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
847 }
848
791f420f 849 /* Must clip because of partially visible lines. */
c3c4768d 850 w32_clip_to_row (w, row, ANY_AREA, hdc);
791f420f 851
0e9e9a2c 852 if (p->which && p->which < max_fringe_bmp)
b6ae1532
KS
853 {
854 HBITMAP pixmap = fringe_bmp[p->which];
855 HDC compat_hdc;
856 HANDLE horig_obj;
791f420f 857
b6ae1532 858 compat_hdc = CreateCompatibleDC (hdc);
6b61353c 859
b6ae1532 860 SaveDC (hdc);
791f420f 861
b6ae1532 862 horig_obj = SelectObject (compat_hdc, pixmap);
fccb8288 863
6b61353c
KH
864 /* Paint overlays transparently. */
865 if (p->overlay_p)
866 {
867 HBRUSH h_brush, h_orig_brush;
868
869 SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
870 SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
871 h_brush = CreateSolidBrush (face->foreground);
872 h_orig_brush = SelectObject (hdc, h_brush);
873
874 BitBlt (hdc, p->x, p->y, p->wd, p->h,
875 compat_hdc, 0, p->dh,
876 DSTINVERT);
877 BitBlt (hdc, p->x, p->y, p->wd, p->h,
878 compat_hdc, 0, p->dh,
879 0x2E064A);
880 BitBlt (hdc, p->x, p->y, p->wd, p->h,
881 compat_hdc, 0, p->dh,
882 DSTINVERT);
883
884 SelectObject (hdc, h_orig_brush);
885 DeleteObject (h_brush);
886 }
887 else
888 {
889 SetTextColor (hdc, face->background);
890 SetBkColor (hdc, (p->cursor_p
891 ? f->output_data.w32->cursor_pixel
892 : face->foreground));
893
894 BitBlt (hdc, p->x, p->y, p->wd, p->h,
895 compat_hdc, 0, p->dh,
896 SRCCOPY);
897 }
791f420f 898
b6ae1532
KS
899 SelectObject (compat_hdc, horig_obj);
900 DeleteDC (compat_hdc);
901 RestoreDC (hdc, -1);
d33c49e8 902 }
791f420f 903
b6ae1532 904 w32_set_clip_rectangle (hdc, NULL);
791f420f 905
791f420f
JR
906 release_frame_dc (f, hdc);
907}
908
6b61353c 909static void
b56ceb92 910w32_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
6b61353c 911{
0e9e9a2c
KS
912 if (which >= max_fringe_bmp)
913 {
914 int i = max_fringe_bmp;
915 max_fringe_bmp = which + 20;
916 fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
917 while (i < max_fringe_bmp)
918 fringe_bmp[i++] = 0;
919 }
920
6b61353c
KH
921 fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
922}
923
924static void
b56ceb92 925w32_destroy_fringe_bitmap (int which)
6b61353c 926{
0e9e9a2c
KS
927 if (which >= max_fringe_bmp)
928 return;
929
6b61353c
KH
930 if (fringe_bmp[which])
931 DeleteObject (fringe_bmp[which]);
932 fringe_bmp[which] = 0;
933}
934
791f420f
JR
935/***********************************************************************
936 Display Iterator
937 ***********************************************************************/
938
939/* Function prototypes of this page. */
940
f57e2426
J
941static void x_set_glyph_string_clipping (struct glyph_string *);
942static void x_set_glyph_string_gc (struct glyph_string *);
943static void x_draw_glyph_string_background (struct glyph_string *,
944 int);
945static void x_draw_glyph_string_foreground (struct glyph_string *);
946static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
947static void x_draw_glyph_string_box (struct glyph_string *);
948static void x_draw_glyph_string (struct glyph_string *);
949static void x_set_cursor_gc (struct glyph_string *);
950static void x_set_mode_line_face_gc (struct glyph_string *);
951static void x_set_mouse_face_gc (struct glyph_string *);
791f420f 952static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
f57e2426
J
953static void w32_setup_relief_color (struct frame *, struct relief *,
954 double, int, COLORREF);
955static void x_setup_relief_colors (struct glyph_string *);
956static void x_draw_image_glyph_string (struct glyph_string *);
957static void x_draw_image_relief (struct glyph_string *);
958static void x_draw_image_foreground (struct glyph_string *);
959static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
960static void x_clear_glyph_string_rect (struct glyph_string *, int,
961 int, int, int);
962static void w32_draw_relief_rect (struct frame *, int, int, int, int,
963 int, int, int, int, int, int,
964 RECT *);
965static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
966 int, int, int, RECT *);
c2cc16fa 967
d67d1627 968
791f420f
JR
969/* Set S->gc to a suitable GC for drawing glyph string S in cursor
970 face. */
971
972static void
b56ceb92 973x_set_cursor_gc (struct glyph_string *s)
791f420f
JR
974{
975 if (s->font == FRAME_FONT (s->f)
976 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
977 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
978 && !s->cmp)
979 s->gc = s->f->output_data.w32->cursor_gc;
980 else
981 {
982 /* Cursor on non-default face: must merge. */
983 XGCValues xgcv;
984 unsigned long mask;
985
986 xgcv.background = s->f->output_data.w32->cursor_pixel;
987 xgcv.foreground = s->face->background;
988
989 /* If the glyph would be invisible, try a different foreground. */
990 if (xgcv.foreground == xgcv.background)
991 xgcv.foreground = s->face->foreground;
992 if (xgcv.foreground == xgcv.background)
993 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
994 if (xgcv.foreground == xgcv.background)
995 xgcv.foreground = s->face->foreground;
996
997 /* Make sure the cursor is distinct from text in this face. */
998 if (xgcv.background == s->face->background
999 && xgcv.foreground == s->face->foreground)
1000 {
1001 xgcv.background = s->face->foreground;
1002 xgcv.foreground = s->face->background;
1003 }
1004
1005 IF_DEBUG (x_check_font (s->f, s->font));
1006 xgcv.font = s->font;
1007 mask = GCForeground | GCBackground | GCFont;
1008
1009 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1010 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1011 mask, &xgcv);
1012 else
1013 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1014 = XCreateGC (NULL, s->window, mask, &xgcv);
1015
1016 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1017 }
1018}
1019
1020
1021/* Set up S->gc of glyph string S for drawing text in mouse face. */
d67d1627 1022
791f420f 1023static void
b56ceb92 1024x_set_mouse_face_gc (struct glyph_string *s)
d67d1627 1025{
791f420f 1026 int face_id;
93ff4395 1027 struct face *face;
791f420f 1028
c2cc16fa 1029 /* What face has to be used last for the mouse face? */
bbf534ce 1030 face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
93ff4395 1031 face = FACE_FROM_ID (s->f, face_id);
c2cc16fa
JR
1032 if (face == NULL)
1033 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
d67d1627 1034
c2cc16fa 1035 if (s->first_glyph->type == CHAR_GLYPH)
14ee5d4c 1036 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
c2cc16fa 1037 else
14ee5d4c 1038 face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
791f420f
JR
1039 s->face = FACE_FROM_ID (s->f, face_id);
1040 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1041
1042 /* If font in this face is same as S->font, use it. */
1043 if (s->font == s->face->font)
1044 s->gc = s->face->gc;
1045 else
1046 {
1047 /* Otherwise construct scratch_cursor_gc with values from FACE
1048 but font FONT. */
1049 XGCValues xgcv;
1050 unsigned long mask;
d67d1627 1051
791f420f
JR
1052 xgcv.background = s->face->background;
1053 xgcv.foreground = s->face->foreground;
1054 IF_DEBUG (x_check_font (s->f, s->font));
1055 xgcv.font = s->font;
1056 mask = GCForeground | GCBackground | GCFont;
d67d1627 1057
791f420f
JR
1058 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1059 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1060 mask, &xgcv);
1061 else
1062 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1063 = XCreateGC (NULL, s->window, mask, &xgcv);
d67d1627 1064
791f420f
JR
1065 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1066 }
1067
a54e2c05 1068 eassert (s->gc != 0);
791f420f
JR
1069}
1070
1071
1072/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1073 Faces to use in the mode line have already been computed when the
1074 matrix was built, so there isn't much to do, here. */
1075
55d4c1b2 1076static inline void
b56ceb92 1077x_set_mode_line_face_gc (struct glyph_string *s)
d67d1627 1078{
791f420f 1079 s->gc = s->face->gc;
791f420f
JR
1080}
1081
1082
1083/* Set S->gc of glyph string S for drawing that glyph string. Set
1084 S->stippled_p to a non-zero value if the face of S has a stipple
1085 pattern. */
1086
55d4c1b2 1087static inline void
b56ceb92 1088x_set_glyph_string_gc (struct glyph_string *s)
791f420f 1089{
ec48c3a7 1090 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
d67d1627 1091
791f420f
JR
1092 if (s->hl == DRAW_NORMAL_TEXT)
1093 {
1094 s->gc = s->face->gc;
1095 s->stippled_p = s->face->stipple != 0;
1096 }
1097 else if (s->hl == DRAW_INVERSE_VIDEO)
1098 {
1099 x_set_mode_line_face_gc (s);
1100 s->stippled_p = s->face->stipple != 0;
1101 }
1102 else if (s->hl == DRAW_CURSOR)
1103 {
1104 x_set_cursor_gc (s);
1105 s->stippled_p = 0;
1106 }
1107 else if (s->hl == DRAW_MOUSE_FACE)
1108 {
1109 x_set_mouse_face_gc (s);
1110 s->stippled_p = s->face->stipple != 0;
1111 }
1112 else if (s->hl == DRAW_IMAGE_RAISED
1113 || s->hl == DRAW_IMAGE_SUNKEN)
1114 {
1115 s->gc = s->face->gc;
1116 s->stippled_p = s->face->stipple != 0;
1117 }
1118 else
1119 {
1120 s->gc = s->face->gc;
1121 s->stippled_p = s->face->stipple != 0;
1122 }
1123
1124 /* GC must have been set. */
a54e2c05 1125 eassert (s->gc != 0);
791f420f
JR
1126}
1127
1128
791f420f
JR
1129/* Set clipping for output of glyph string S. S may be part of a mode
1130 line or menu if we don't have X toolkit support. */
1131
55d4c1b2 1132static inline void
b56ceb92 1133x_set_glyph_string_clipping (struct glyph_string *s)
791f420f 1134{
3ca3504a 1135 RECT *r = s->clip;
3ca3504a
JR
1136 int n = get_glyph_string_clip_rects (s, r, 2);
1137
1138 if (n == 1)
1139 w32_set_clip_rectangle (s->hdc, r);
1140 else if (n > 1)
1141 {
1149507c
JB
1142 HRGN clip1 = CreateRectRgnIndirect (r);
1143 HRGN clip2 = CreateRectRgnIndirect (r + 1);
1144 if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
1145 SelectClipRgn (s->hdc, clip1);
3ca3504a
JR
1146 DeleteObject (clip1);
1147 DeleteObject (clip2);
3ca3504a 1148 }
3ca3504a 1149 s->num_clips = n;
791f420f
JR
1150}
1151
027f6f90
JR
1152/* Set SRC's clipping for output of glyph string DST. This is called
1153 when we are drawing DST's left_overhang or right_overhang only in
1154 the area of SRC. */
1155
1156static void
b56ceb92
JB
1157x_set_glyph_string_clipping_exactly (struct glyph_string *src,
1158 struct glyph_string *dst)
027f6f90
JR
1159{
1160 RECT r;
1161
ef39ccbb
KH
1162 r.left = src->x;
1163 r.right = r.left + src->width;
1164 r.top = src->y;
1165 r.bottom = r.top + src->height;
1166 dst->clip[0] = r;
1167 dst->num_clips = 1;
027f6f90
JR
1168 w32_set_clip_rectangle (dst->hdc, &r);
1169}
791f420f 1170
6b6bd726 1171/* RIF:
ef39ccbb 1172 Compute left and right overhang of glyph string S. */
791f420f 1173
6b6bd726 1174static void
b56ceb92 1175w32_compute_glyph_string_overhangs (struct glyph_string *s)
791f420f 1176{
cf907d69 1177 if (s->cmp == NULL
ef39ccbb
KH
1178 && s->first_glyph->type == CHAR_GLYPH
1179 && !s->font_not_found_p)
cf907d69 1180 {
ef39ccbb
KH
1181 unsigned *code = alloca (sizeof (unsigned) * s->nchars);
1182 struct font *font = s->font;
1183 struct font_metrics metrics;
1184 int i;
cf907d69 1185
ef39ccbb
KH
1186 for (i = 0; i < s->nchars; i++)
1187 code[i] = s->char2b[i];
1188 font->driver->text_extents (font, code, s->nchars, &metrics);
1189 s->right_overhang = (metrics.rbearing > metrics.width
1190 ? metrics.rbearing - metrics.width : 0);
1191 s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
cf907d69
JR
1192 }
1193 else if (s->cmp)
1194 {
1195 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
1196 s->left_overhang = -s->cmp->lbearing;
1197 }
791f420f
JR
1198}
1199
791f420f
JR
1200/* Fill rectangle X, Y, W, H with background color of glyph string S. */
1201
55d4c1b2 1202static inline void
b56ceb92
JB
1203x_clear_glyph_string_rect (struct glyph_string *s,
1204 int x, int y, int w, int h)
791f420f
JR
1205{
1206 int real_x = x;
1207 int real_y = y;
1208 int real_w = w;
1209 int real_h = h;
1210#if 0
1211 /* Take clipping into account. */
1212 if (s->gc->clip_mask == Rect)
1213 {
1214 real_x = max (real_x, s->gc->clip_rectangle.left);
1215 real_y = max (real_y, s->gc->clip_rectangle.top);
1216 real_w = min (real_w, s->gc->clip_rectangle.right
1217 - s->gc->clip_rectangle.left);
1218 real_h = min (real_h, s->gc->clip_rectangle.bottom
1219 - s->gc->clip_rectangle.top);
1220 }
1221#endif
1222 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1223 real_w, real_h);
1224}
1225
1226
1227/* Draw the background of glyph_string S. If S->background_filled_p
1228 is non-zero don't draw it. FORCE_P non-zero means draw the
1229 background even if it wouldn't be drawn normally. This is used
1230 when a string preceding S draws into the background of S, or S
1231 contains the first component of a composition. */
1232
1233static void
b56ceb92 1234x_draw_glyph_string_background (struct glyph_string *s, int force_p)
791f420f
JR
1235{
1236 /* Nothing to do if background has already been drawn or if it
1237 shouldn't be drawn in the first place. */
1238 if (!s->background_filled_p)
1239 {
60222d69
AI
1240 int box_line_width = max (s->face->box_line_width, 0);
1241
01b220b6 1242#if 0 /* TODO: stipple */
791f420f
JR
1243 if (s->stippled_p)
1244 {
1245 /* Fill background with a stipple pattern. */
1246 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1247 XFillRectangle (s->display, s->window, s->gc, s->x,
60222d69 1248 s->y + box_line_width,
791f420f 1249 s->background_width,
60222d69 1250 s->height - 2 * box_line_width);
791f420f
JR
1251 XSetFillStyle (s->display, s->gc, FillSolid);
1252 s->background_filled_p = 1;
1253 }
1254 else
1255#endif
60222d69 1256 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
791f420f
JR
1257 || s->font_not_found_p
1258 || s->extends_to_end_of_line_p
1259 || force_p)
1260 {
60222d69 1261 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
791f420f 1262 s->background_width,
60222d69 1263 s->height - 2 * box_line_width);
791f420f
JR
1264 s->background_filled_p = 1;
1265 }
1266 }
1267}
1268
1269
1270/* Draw the foreground of glyph string S. */
1271
1272static void
b56ceb92 1273x_draw_glyph_string_foreground (struct glyph_string *s)
791f420f
JR
1274{
1275 int i, x;
1276
1277 /* If first glyph of S has a left box line, start drawing the text
1278 of S to the right of that box line. */
1279 if (s->face->box != FACE_NO_BOX
1280 && s->first_glyph->left_box_line_p)
1ea40aa2 1281 x = s->x + eabs (s->face->box_line_width);
791f420f
JR
1282 else
1283 x = s->x;
1284
791f420f
JR
1285 SetTextColor (s->hdc, s->gc->foreground);
1286 SetBkColor (s->hdc, s->gc->background);
1287 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1288
791f420f
JR
1289 /* Draw characters of S as rectangles if S's font could not be
1290 loaded. */
1291 if (s->font_not_found_p)
1292 {
1293 for (i = 0; i < s->nchars; ++i)
1294 {
1295 struct glyph *g = s->first_glyph + i;
1296
1297 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1298 s->height - 1);
1299 x += g->pixel_width;
1300 }
1301 }
ef39ccbb 1302 else
027f6f90 1303 {
c35f9821
JR
1304 struct font *font = s->font;
1305 int boff = font->baseline_offset;
027f6f90 1306 int y;
c35f9821
JR
1307 HFONT old_font;
1308
1309 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
027f6f90 1310
c35f9821
JR
1311 if (font->vertical_centering)
1312 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
027f6f90
JR
1313
1314 y = s->ybase - boff;
1315 if (s->for_overlaps
1316 || (s->background_filled_p && s->hl != DRAW_CURSOR))
c35f9821 1317 font->driver->draw (s, 0, s->nchars, x, y, 0);
027f6f90 1318 else
c35f9821 1319 font->driver->draw (s, 0, s->nchars, x, y, 1);
027f6f90 1320 if (s->face->overstrike)
c35f9821 1321 font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
791f420f 1322
c35f9821
JR
1323 SelectObject (s->hdc, old_font);
1324 }
791f420f
JR
1325}
1326
1327/* Draw the foreground of composite glyph string S. */
1328
1329static void
b56ceb92 1330x_draw_composite_glyph_string_foreground (struct glyph_string *s)
791f420f 1331{
027f6f90 1332 int i, j, x;
2b107652 1333 struct font *font = s->font;
791f420f
JR
1334
1335 /* If first glyph of S has a left box line, start drawing the text
1336 of S to the right of that box line. */
027f6f90 1337 if (s->face && s->face->box != FACE_NO_BOX
791f420f 1338 && s->first_glyph->left_box_line_p)
1ea40aa2 1339 x = s->x + eabs (s->face->box_line_width);
791f420f
JR
1340 else
1341 x = s->x;
1342
2b107652
KH
1343 /* S is a glyph string for a composition. S->cmp_from is the index
1344 of the first character drawn for glyphs of this composition.
1345 S->cmp_from == 0 means we are drawing the very first character of
791f420f
JR
1346 this composition. */
1347
1348 SetTextColor (s->hdc, s->gc->foreground);
1349 SetBkColor (s->hdc, s->gc->background);
791f420f
JR
1350 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1351
1352 /* Draw a rectangle for the composition if the font for the very
1353 first character of the composition could not be loaded. */
1354 if (s->font_not_found_p)
1355 {
2b107652 1356 if (s->cmp_from == 0)
791f420f
JR
1357 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1358 s->height - 1);
1359 }
2b107652
KH
1360 else if (! s->first_glyph->u.cmp.automatic)
1361 {
1362 int y = s->ybase;
2b107652
KH
1363 HFONT old_font;
1364
1365 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
1366
1367 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
bd01620e
EZ
1368 /* TAB in a composition means display glyphs with padding
1369 space on the left or right. */
2b107652
KH
1370 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1371 {
1372 int xx = x + s->cmp->offsets[j * 2];
1373 int yy = y - s->cmp->offsets[j * 2 + 1];
1374
1375 font->driver->draw (s, j, j + 1, xx, yy, 0);
1376 if (s->face->overstrike)
1377 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
1378 }
1379 SelectObject (s->hdc, old_font);
1380 }
c35f9821 1381 else
791f420f 1382 {
2b107652
KH
1383 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1384 Lisp_Object glyph;
027f6f90
JR
1385 int y = s->ybase;
1386 int width = 0;
c35f9821
JR
1387 HFONT old_font;
1388
1389 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
027f6f90 1390
2b107652 1391 for (i = j = s->cmp_from; i < s->cmp_to; i++)
a18bb28d 1392 {
2b107652
KH
1393 glyph = LGSTRING_GLYPH (gstring, i);
1394 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1395 width += LGLYPH_WIDTH (glyph);
1396 else
027f6f90 1397 {
027f6f90
JR
1398 int xoff, yoff, wadjust;
1399
2b107652 1400 if (j < i)
027f6f90 1401 {
2b107652 1402 font->driver->draw (s, j, i, x, y, 0);
027f6f90
JR
1403 x += width;
1404 }
2b107652
KH
1405 xoff = LGLYPH_XOFF (glyph);
1406 yoff = LGLYPH_YOFF (glyph);
1407 wadjust = LGLYPH_WADJUST (glyph);
027f6f90 1408 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
0c16681f 1409 x += wadjust;
2b107652 1410 j = i + 1;
027f6f90
JR
1411 width = 0;
1412 }
a18bb28d 1413 }
2b107652
KH
1414 if (j < i)
1415 font->driver->draw (s, j, i, x, y, 0);
1416
c35f9821 1417 SelectObject (s->hdc, old_font);
791f420f
JR
1418 }
1419}
1420
e5fa381b 1421
b2cca856
KH
1422/* Draw the foreground of glyph string S for glyphless characters. */
1423
1424static void
1425x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1426{
1427 struct glyph *glyph = s->first_glyph;
1428 XChar2b char2b[8];
1429 int x, i, j;
65b6b59a 1430 int with_background;
b2cca856
KH
1431
1432 /* If first glyph of S has a left box line, start drawing the text
1433 of S to the right of that box line. */
1434 if (s->face->box != FACE_NO_BOX
1435 && s->first_glyph->left_box_line_p)
1436 x = s->x + eabs (s->face->box_line_width);
1437 else
1438 x = s->x;
1439
1440 SetTextColor (s->hdc, s->gc->foreground);
1441 SetBkColor (s->hdc, s->gc->background);
1442 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1443
1444 s->char2b = char2b;
65b6b59a
KH
1445 with_background = ! (s->for_overlaps
1446 || (s->background_filled_p && s->hl != DRAW_CURSOR));
b2cca856
KH
1447 for (i = 0; i < s->nchars; i++, glyph++)
1448 {
1449 char buf[7], *str = NULL;
1450 int len = glyph->u.glyphless.len;
1451
1452 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
1453 {
1454 if (len > 1
1455 && CHAR_TABLE_P (Vglyphless_char_display)
1456 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
1457 >= 1))
1458 {
1459 Lisp_Object acronym
1460 = (! glyph->u.glyphless.for_no_font
1461 ? CHAR_TABLE_REF (Vglyphless_char_display,
1462 glyph->u.glyphless.ch)
1463 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
1464 if (STRINGP (acronym))
51b59d79 1465 str = SSDATA (acronym);
b2cca856
KH
1466 }
1467 }
0eb025fb 1468 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
b2cca856
KH
1469 {
1470 sprintf ((char *) buf, "%0*X",
1471 glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
1472 glyph->u.glyphless.ch);
1473 str = buf;
1474 }
1475
0eb025fb
EZ
1476 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1477 w32_draw_rectangle (s->hdc, s->gc,
1478 x, s->ybase - glyph->ascent,
1479 glyph->pixel_width - 1,
1480 glyph->ascent + glyph->descent - 1);
b2cca856
KH
1481 if (str)
1482 {
1483 struct font *font = s->font;
1484 int upper_len = (len + 1) / 2;
1485 unsigned code;
1486 HFONT old_font;
1487
65b6b59a 1488 old_font = SelectObject (s->hdc, FONT_HANDLE (font));
0eb025fb 1489 /* It is certain that all LEN characters in STR are ASCII. */
b2cca856
KH
1490 for (j = 0; j < len; j++)
1491 {
1492 code = font->driver->encode_char (font, str[j]);
1493 STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
1494 }
1495 font->driver->draw (s, 0, upper_len,
1496 x + glyph->slice.glyphless.upper_xoff,
1497 s->ybase + glyph->slice.glyphless.upper_yoff,
65b6b59a 1498 with_background);
b2cca856
KH
1499 font->driver->draw (s, upper_len, len,
1500 x + glyph->slice.glyphless.lower_xoff,
1501 s->ybase + glyph->slice.glyphless.lower_yoff,
65b6b59a 1502 with_background);
b2cca856
KH
1503 SelectObject (s->hdc, old_font);
1504 }
b2cca856
KH
1505 x += glyph->pixel_width;
1506 }
1507}
1508
1509
e5fa381b
JR
1510/* Brightness beyond which a color won't have its highlight brightness
1511 boosted.
1512
1513 Nominally, highlight colors for `3d' faces are calculated by
1514 brightening an object's color by a constant scale factor, but this
e8500ff4 1515 doesn't yield good results for dark colors, so for colors whose
e5fa381b
JR
1516 brightness is less than this value (on a scale of 0-255) have to
1517 use an additional additive factor.
1518
1519 The value here is set so that the default menu-bar/mode-line color
1520 (grey75) will not have its highlights changed at all. */
1521#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1522
1523
791f420f
JR
1524/* Allocate a color which is lighter or darker than *COLOR by FACTOR
1525 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1526 If this produces the same color as COLOR, try a color where all RGB
1527 values have DELTA added. Return the allocated color in *COLOR.
1528 DISPLAY is the X display, CMAP is the colormap to operate on.
1529 Value is non-zero if successful. */
1530
1531static int
b56ceb92
JB
1532w32_alloc_lighter_color (struct frame *f, COLORREF *color,
1533 double factor, int delta)
791f420f
JR
1534{
1535 COLORREF new;
e5fa381b
JR
1536 long bright;
1537
1538 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1539 delta /= 256;
791f420f
JR
1540
1541 /* Change RGB values by specified FACTOR. Avoid overflow! */
a54e2c05 1542 eassert (factor >= 0);
791f420f
JR
1543 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1544 min (0xff, factor * GetGValue (*color)),
1545 min (0xff, factor * GetBValue (*color)));
e5fa381b
JR
1546
1547 /* Calculate brightness of COLOR. */
1548 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1549 + GetBValue (*color)) / 6;
1550
1551 /* We only boost colors that are darker than
1552 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1553 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1554 /* Make an additive adjustment to NEW, because it's dark enough so
1555 that scaling by FACTOR alone isn't enough. */
1556 {
1557 /* How far below the limit this color is (0 - 1, 1 being darker). */
1558 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1559 /* The additive adjustment. */
1560 int min_delta = delta * dimness * factor / 2;
d67d1627 1561
e5fa381b
JR
1562 if (factor < 1)
1563 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1564 max (0, min (0xff, min_delta - GetGValue (*color))),
1565 max (0, min (0xff, min_delta - GetBValue (*color))));
1566 else
1567 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1568 max (0, min (0xff, min_delta + GetGValue (*color))),
1569 max (0, min (0xff, min_delta + GetBValue (*color))));
1570 }
d67d1627 1571
791f420f
JR
1572 if (new == *color)
1573 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1574 max (0, min (0xff, delta + GetGValue (*color))),
1575 max (0, min (0xff, delta + GetBValue (*color))));
1576
01b220b6
JR
1577 /* TODO: Map to palette and retry with delta if same? */
1578 /* TODO: Free colors (if using palette)? */
93ff4395 1579
791f420f
JR
1580 if (new == *color)
1581 return 0;
1582
1583 *color = new;
1584
1585 return 1;
1586}
1587
8b7d0a16
JR
1588/* On frame F, translate pixel colors to RGB values for the NCOLORS
1589 colors in COLORS. On W32, we no longer try to map colors to
1590 a palette. */
1591void
b56ceb92 1592x_query_colors (struct frame *f, XColor *colors, int ncolors)
8b7d0a16
JR
1593{
1594 int i;
1595
1596 for (i = 0; i < ncolors; i++)
1597 {
1598 DWORD pixel = colors[i].pixel;
1599 /* Convert to a 16 bit value in range 0 - 0xffff. */
1600 colors[i].red = GetRValue (pixel) * 257;
1601 colors[i].green = GetGValue (pixel) * 257;
1602 colors[i].blue = GetBValue (pixel) * 257;
1603 }
1604}
1605
1606void
b56ceb92 1607x_query_color (struct frame *f, XColor *color)
8b7d0a16
JR
1608{
1609 x_query_colors (f, color, 1);
1610}
1611
791f420f
JR
1612
1613/* Set up the foreground color for drawing relief lines of glyph
1614 string S. RELIEF is a pointer to a struct relief containing the GC
1615 with which lines will be drawn. Use a color that is FACTOR or
1616 DELTA lighter or darker than the relief's background which is found
1617 in S->f->output_data.x->relief_background. If such a color cannot
1618 be allocated, use DEFAULT_PIXEL, instead. */
d67d1627 1619
791f420f 1620static void
b56ceb92
JB
1621w32_setup_relief_color (struct frame *f, struct relief *relief, double factor,
1622 int delta, COLORREF default_pixel)
791f420f
JR
1623{
1624 XGCValues xgcv;
1625 struct w32_output *di = f->output_data.w32;
1626 unsigned long mask = GCForeground;
1627 COLORREF pixel;
1628 COLORREF background = di->relief_background;
1629 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1630
01b220b6 1631 /* TODO: Free colors (if using palette)? */
93ff4395 1632
791f420f
JR
1633 /* Allocate new color. */
1634 xgcv.foreground = default_pixel;
1635 pixel = background;
1636 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1637 {
1638 relief->allocated_p = 1;
1639 xgcv.foreground = relief->pixel = pixel;
1640 }
d67d1627 1641
791f420f
JR
1642 if (relief->gc == 0)
1643 {
01b220b6 1644#if 0 /* TODO: stipple */
791f420f
JR
1645 xgcv.stipple = dpyinfo->gray;
1646 mask |= GCStipple;
1647#endif
1648 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1649 }
1650 else
1651 XChangeGC (NULL, relief->gc, mask, &xgcv);
1652}
1653
1654
1655/* Set up colors for the relief lines around glyph string S. */
1656
1657static void
b56ceb92 1658x_setup_relief_colors (struct glyph_string *s)
791f420f
JR
1659{
1660 struct w32_output *di = s->f->output_data.w32;
1661 COLORREF color;
1662
1663 if (s->face->use_box_color_for_shadows_p)
1664 color = s->face->box_color;
6ff3e5e3 1665 else if (s->first_glyph->type == IMAGE_GLYPH
6637c996 1666 && s->img->pixmap
6ff3e5e3
JR
1667 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1668 color = IMAGE_BACKGROUND (s->img, s->f, 0);
791f420f
JR
1669 else
1670 color = s->gc->background;
1671
1672 if (di->white_relief.gc == 0
1673 || color != di->relief_background)
1674 {
1675 di->relief_background = color;
1676 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1677 WHITE_PIX_DEFAULT (s->f));
1678 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1679 BLACK_PIX_DEFAULT (s->f));
1680 }
1681}
1682
1683
1684/* Draw a relief on frame F inside the rectangle given by LEFT_X,
1685 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1686 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1687 relief. LEFT_P non-zero means draw a relief on the left side of
1688 the rectangle. RIGHT_P non-zero means draw a relief on the right
1689 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1690 when drawing. */
1691
1692static void
b56ceb92 1693w32_draw_relief_rect (struct frame *f,
e8500ff4
JB
1694 int left_x, int top_y, int right_x, int bottom_y,
1695 int width, int raised_p,
1696 int top_p, int bot_p, int left_p, int right_p,
b56ceb92 1697 RECT *clip_rect)
791f420f
JR
1698{
1699 int i;
1700 XGCValues gc;
1701 HDC hdc = get_frame_dc (f);
1702
1703 if (raised_p)
e5fa381b 1704 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
791f420f 1705 else
e5fa381b 1706 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
791f420f
JR
1707
1708 w32_set_clip_rectangle (hdc, clip_rect);
1709
1710 /* Top. */
cb0b194a
KS
1711 if (top_p)
1712 for (i = 0; i < width; ++i)
1713 w32_fill_area (f, hdc, gc.foreground,
1714 left_x + i * left_p, top_y + i,
1715 right_x - left_x - i * (left_p + right_p ) + 1, 1);
791f420f
JR
1716
1717 /* Left. */
1718 if (left_p)
1719 for (i = 0; i < width; ++i)
9f5a911b 1720 w32_fill_area (f, hdc, gc.foreground,
75b4f59c
YM
1721 left_x + i, top_y + (i + 1) * top_p, 1,
1722 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
791f420f
JR
1723
1724 if (raised_p)
e5fa381b 1725 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
791f420f 1726 else
e5fa381b 1727 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
d67d1627 1728
791f420f 1729 /* Bottom. */
cb0b194a
KS
1730 if (bot_p)
1731 for (i = 0; i < width; ++i)
1732 w32_fill_area (f, hdc, gc.foreground,
1733 left_x + i * left_p, bottom_y - i,
1734 right_x - left_x - i * (left_p + right_p) + 1, 1);
791f420f
JR
1735
1736 /* Right. */
1737 if (right_p)
1738 for (i = 0; i < width; ++i)
9f5a911b 1739 w32_fill_area (f, hdc, gc.foreground,
75b4f59c
YM
1740 right_x - i, top_y + (i + 1) * top_p, 1,
1741 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
791f420f
JR
1742
1743 w32_set_clip_rectangle (hdc, NULL);
d67d1627 1744
791f420f
JR
1745 release_frame_dc (f, hdc);
1746}
1747
1748
1749/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
1750 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
1751 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
1752 left side of the rectangle. RIGHT_P non-zero means draw a line
1753 on the right side of the rectangle. CLIP_RECT is the clipping
1754 rectangle to use when drawing. */
1755
1756static void
b56ceb92
JB
1757w32_draw_box_rect (struct glyph_string *s,
1758 int left_x, int top_y, int right_x, int bottom_y, int width,
1759 int left_p, int right_p, RECT *clip_rect)
791f420f 1760{
00fe468b 1761 w32_set_clip_rectangle (s->hdc, clip_rect);
d67d1627 1762
791f420f 1763 /* Top. */
00fe468b 1764 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 1765 left_x, top_y, right_x - left_x + 1, width);
791f420f
JR
1766
1767 /* Left. */
1768 if (left_p)
1769 {
00fe468b 1770 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 1771 left_x, top_y, width, bottom_y - top_y + 1);
791f420f 1772 }
d67d1627 1773
791f420f 1774 /* Bottom. */
00fe468b 1775 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 1776 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
d67d1627 1777
791f420f
JR
1778 /* Right. */
1779 if (right_p)
1780 {
00fe468b 1781 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 1782 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
791f420f
JR
1783 }
1784
00fe468b 1785 w32_set_clip_rectangle (s->hdc, NULL);
791f420f
JR
1786}
1787
1788
1789/* Draw a box around glyph string S. */
1790
1791static void
b56ceb92 1792x_draw_glyph_string_box (struct glyph_string *s)
791f420f
JR
1793{
1794 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
1795 int left_p, right_p;
1796 struct glyph *last_glyph;
1797 RECT clip_rect;
1798
82ead4b1
KS
1799 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
1800 ? WINDOW_RIGHT_EDGE_X (s->w)
1801 : window_box_right (s->w, s->area));
d67d1627 1802
791f420f
JR
1803 /* The glyph that may have a right box line. */
1804 last_glyph = (s->cmp || s->img
1805 ? s->first_glyph
1806 : s->first_glyph + s->nchars - 1);
1807
1ea40aa2 1808 width = eabs (s->face->box_line_width);
791f420f
JR
1809 raised_p = s->face->box == FACE_RAISED_BOX;
1810 left_x = s->x;
9f5a911b 1811 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
791f420f
JR
1812 ? last_x - 1
1813 : min (last_x, s->x + s->background_width) - 1));
1814 top_y = s->y;
1815 bottom_y = top_y + s->height - 1;
1816
1817 left_p = (s->first_glyph->left_box_line_p
1818 || (s->hl == DRAW_MOUSE_FACE
1819 && (s->prev == NULL
1820 || s->prev->hl != s->hl)));
1821 right_p = (last_glyph->right_box_line_p
1822 || (s->hl == DRAW_MOUSE_FACE
1823 && (s->next == NULL
1824 || s->next->hl != s->hl)));
d67d1627 1825
89271099 1826 get_glyph_string_clip_rect (s, &clip_rect);
791f420f
JR
1827
1828 if (s->face->box == FACE_SIMPLE_BOX)
1829 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
1830 left_p, right_p, &clip_rect);
1831 else
1832 {
1833 x_setup_relief_colors (s);
1834 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
cb0b194a 1835 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
791f420f
JR
1836 }
1837}
1838
1839
1840/* Draw foreground of image glyph string S. */
1841
1842static void
b56ceb92 1843x_draw_image_foreground (struct glyph_string *s)
791f420f 1844{
cb0b194a
KS
1845 int x = s->x;
1846 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
791f420f
JR
1847
1848 /* If first glyph of S has a left box line, start drawing it to the
1849 right of that line. */
1850 if (s->face->box != FACE_NO_BOX
cb0b194a
KS
1851 && s->first_glyph->left_box_line_p
1852 && s->slice.x == 0)
1ea40aa2 1853 x += eabs (s->face->box_line_width);
791f420f
JR
1854
1855 /* If there is a margin around the image, adjust x- and y-position
1856 by that margin. */
cb0b194a
KS
1857 if (s->slice.x == 0)
1858 x += s->img->hmargin;
1859 if (s->slice.y == 0)
1860 y += s->img->vmargin;
791f420f
JR
1861
1862 SaveDC (s->hdc);
1863
1864 if (s->img->pixmap)
1865 {
d30591dc
JR
1866 HDC compat_hdc = CreateCompatibleDC (s->hdc);
1867 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
1868 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
1869 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
1870 SetBkColor (compat_hdc, RGB (255, 255, 255));
1871 SetTextColor (s->hdc, RGB (0, 0, 0));
1872 x_set_glyph_string_clipping (s);
1873
791f420f
JR
1874 if (s->img->mask)
1875 {
d30591dc
JR
1876 HDC mask_dc = CreateCompatibleDC (s->hdc);
1877 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
1878
1879 SetTextColor (s->hdc, RGB (255, 255, 255));
1880 SetBkColor (s->hdc, RGB (0, 0, 0));
1881
cb0b194a
KS
1882 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1883 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
1884 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1885 mask_dc, s->slice.x, s->slice.y, SRCAND);
1886 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1887 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
d30591dc
JR
1888
1889 SelectObject (mask_dc, mask_orig_obj);
1890 DeleteDC (mask_dc);
791f420f
JR
1891 }
1892 else
791f420f 1893 {
d30591dc
JR
1894 SetTextColor (s->hdc, s->gc->foreground);
1895 SetBkColor (s->hdc, s->gc->background);
1896
cb0b194a
KS
1897 BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
1898 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
791f420f
JR
1899
1900 /* When the image has a mask, we can expect that at
1901 least part of a mouse highlight or a block cursor will
1902 be visible. If the image doesn't have a mask, make
1903 a block cursor visible by drawing a rectangle around
1904 the image. I believe it's looking better if we do
1905 nothing here for mouse-face. */
1906 if (s->hl == DRAW_CURSOR)
c65eff23
KS
1907 {
1908 int r = s->img->relief;
1909 if (r < 0) r = -r;
1910 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
cb0b194a
KS
1911 s->slice.width + r*2 - 1,
1912 s->slice.height + r*2 - 1);
c65eff23 1913 }
791f420f 1914 }
d30591dc
JR
1915
1916 w32_set_clip_rectangle (s->hdc, NULL);
1917 SelectObject (s->hdc, orig_brush);
1918 DeleteObject (fg_brush);
1919 SelectObject (compat_hdc, orig_obj);
1920 DeleteDC (compat_hdc);
791f420f
JR
1921 }
1922 else
cb0b194a
KS
1923 w32_draw_rectangle (s->hdc, s->gc, x, y,
1924 s->slice.width - 1, s->slice.height - 1);
ee78dc32 1925
791f420f
JR
1926 RestoreDC (s->hdc ,-1);
1927}
ee78dc32 1928
791f420f 1929
791f420f
JR
1930/* Draw a relief around the image glyph string S. */
1931
1932static void
b56ceb92 1933x_draw_image_relief (struct glyph_string *s)
791f420f 1934{
75b4f59c 1935 int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
791f420f 1936 RECT r;
cb0b194a
KS
1937 int x = s->x;
1938 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
d67d1627 1939
791f420f
JR
1940 /* If first glyph of S has a left box line, start drawing it to the
1941 right of that line. */
1942 if (s->face->box != FACE_NO_BOX
cb0b194a
KS
1943 && s->first_glyph->left_box_line_p
1944 && s->slice.x == 0)
1ea40aa2 1945 x += eabs (s->face->box_line_width);
d67d1627 1946
791f420f
JR
1947 /* If there is a margin around the image, adjust x- and y-position
1948 by that margin. */
cb0b194a
KS
1949 if (s->slice.x == 0)
1950 x += s->img->hmargin;
1951 if (s->slice.y == 0)
1952 y += s->img->vmargin;
d67d1627 1953
791f420f
JR
1954 if (s->hl == DRAW_IMAGE_SUNKEN
1955 || s->hl == DRAW_IMAGE_RAISED)
1956 {
e8500ff4
JB
1957 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief
1958 : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
791f420f
JR
1959 raised_p = s->hl == DRAW_IMAGE_RAISED;
1960 }
1961 else
ee78dc32 1962 {
1ea40aa2 1963 thick = eabs (s->img->relief);
791f420f
JR
1964 raised_p = s->img->relief > 0;
1965 }
d67d1627 1966
75b4f59c
YM
1967 x1 = x + s->slice.width - 1;
1968 y1 = y + s->slice.height - 1;
1969 top_p = bot_p = left_p = right_p = 0;
1970
1971 if (s->slice.x == 0)
1972 x -= thick, left_p = 1;
1973 if (s->slice.y == 0)
1974 y -= thick, top_p = 1;
1975 if (s->slice.x + s->slice.width == s->img->width)
1976 x1 += thick, right_p = 1;
1977 if (s->slice.y + s->slice.height == s->img->height)
1978 y1 += thick, bot_p = 1;
d67d1627 1979
791f420f 1980 x_setup_relief_colors (s);
89271099 1981 get_glyph_string_clip_rect (s, &r);
75b4f59c
YM
1982 w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
1983 top_p, bot_p, left_p, right_p, &r);
791f420f 1984}
ee78dc32 1985
791f420f
JR
1986
1987/* Draw the foreground of image glyph string S to PIXMAP. */
1988
1989static void
b56ceb92 1990w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
791f420f
JR
1991{
1992 HDC hdc = CreateCompatibleDC (s->hdc);
1993 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
cb0b194a
KS
1994 int x = 0;
1995 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
791f420f
JR
1996
1997 /* If first glyph of S has a left box line, start drawing it to the
1998 right of that line. */
1999 if (s->face->box != FACE_NO_BOX
cb0b194a
KS
2000 && s->first_glyph->left_box_line_p
2001 && s->slice.x == 0)
1ea40aa2 2002 x += eabs (s->face->box_line_width);
791f420f
JR
2003
2004 /* If there is a margin around the image, adjust x- and y-position
2005 by that margin. */
cb0b194a
KS
2006 if (s->slice.x == 0)
2007 x += s->img->hmargin;
2008 if (s->slice.y == 0)
2009 y += s->img->vmargin;
791f420f
JR
2010
2011 if (s->img->pixmap)
2012 {
d30591dc
JR
2013 HDC compat_hdc = CreateCompatibleDC (hdc);
2014 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2015 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2016 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2017
791f420f
JR
2018 if (s->img->mask)
2019 {
d30591dc
JR
2020 HDC mask_dc = CreateCompatibleDC (hdc);
2021 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2022
2023 SetTextColor (hdc, RGB (0, 0, 0));
2024 SetBkColor (hdc, RGB (255, 255, 255));
cb0b194a
KS
2025 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2026 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
2027 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2028 mask_dc, s->slice.x, s->slice.y, SRCAND);
2029 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2030 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
d30591dc
JR
2031
2032 SelectObject (mask_dc, mask_orig_obj);
2033 DeleteDC (mask_dc);
791f420f
JR
2034 }
2035 else
ef0e360f 2036 {
d30591dc
JR
2037 SetTextColor (hdc, s->gc->foreground);
2038 SetBkColor (hdc, s->gc->background);
2039
cb0b194a
KS
2040 BitBlt (hdc, x, y, s->slice.width, s->slice.height,
2041 compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
791f420f
JR
2042
2043 /* When the image has a mask, we can expect that at
2044 least part of a mouse highlight or a block cursor will
2045 be visible. If the image doesn't have a mask, make
2046 a block cursor visible by drawing a rectangle around
2047 the image. I believe it's looking better if we do
2048 nothing here for mouse-face. */
2049 if (s->hl == DRAW_CURSOR)
c65eff23
KS
2050 {
2051 int r = s->img->relief;
2052 if (r < 0) r = -r;
cb0b194a
KS
2053 w32_draw_rectangle (hdc, s->gc, x - r, y - r,
2054 s->slice.width + r*2 - 1,
2055 s->slice.height + r*2 - 1);
c65eff23 2056 }
ef0e360f 2057 }
d30591dc
JR
2058
2059 SelectObject (hdc, orig_brush);
2060 DeleteObject (fg_brush);
2061 SelectObject (compat_hdc, orig_obj);
2062 DeleteDC (compat_hdc);
791f420f
JR
2063 }
2064 else
cb0b194a
KS
2065 w32_draw_rectangle (hdc, s->gc, x, y,
2066 s->slice.width - 1, s->slice.height - 1);
791f420f
JR
2067
2068 SelectObject (hdc, orig_hdc_obj);
2069 DeleteDC (hdc);
2070}
2071
2072
2073/* Draw part of the background of glyph string S. X, Y, W, and H
2074 give the rectangle to draw. */
2075
2076static void
b56ceb92 2077x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
791f420f 2078{
01b220b6 2079#if 0 /* TODO: stipple */
791f420f
JR
2080 if (s->stippled_p)
2081 {
2082 /* Fill background with a stipple pattern. */
2083 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2084 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2085 XSetFillStyle (s->display, s->gc, FillSolid);
2086 }
2087 else
2088#endif
2089 x_clear_glyph_string_rect (s, x, y, w, h);
2090}
2091
2092
d67d1627 2093/* Draw image glyph string S.
791f420f
JR
2094
2095 s->y
2096 s->x +-------------------------
2097 | s->face->box
2098 |
2099 | +-------------------------
d6ff54d5 2100 | | s->img->vmargin
791f420f
JR
2101 | |
2102 | | +-------------------
2103 | | | the image
cabb23bc 2104
791f420f
JR
2105 */
2106
2107static void
b56ceb92 2108x_draw_image_glyph_string (struct glyph_string *s)
791f420f
JR
2109{
2110 int x, y;
1ea40aa2 2111 int box_line_hwidth = eabs (s->face->box_line_width);
60222d69 2112 int box_line_vwidth = max (s->face->box_line_width, 0);
791f420f
JR
2113 int height;
2114 HBITMAP pixmap = 0;
2115
60222d69 2116 height = s->height - 2 * box_line_vwidth;
791f420f
JR
2117
2118 /* Fill background with face under the image. Do it only if row is
2119 taller than image or if image has a clip mask to reduce
2120 flickering. */
2121 s->stippled_p = s->face->stipple != 0;
cb0b194a 2122 if (height > s->slice.height
d6ff54d5 2123 || s->img->hmargin
c2cc16fa 2124 || s->img->vmargin
791f420f 2125 || s->img->mask
791f420f
JR
2126 || s->img->pixmap == 0
2127 || s->width != s->background_width)
2128 {
cb0b194a
KS
2129 x = s->x;
2130 if (s->first_glyph->left_box_line_p
2131 && s->slice.x == 0)
2132 x += box_line_hwidth;
2133
2134 y = s->y;
2135 if (s->slice.y == 0)
2136 y += box_line_vwidth;
d67d1627 2137
d30591dc 2138#if 0 /* TODO: figure out if we need to do this on Windows. */
791f420f 2139 if (s->img->mask)
ee78dc32 2140 {
c2cc16fa
JR
2141 /* Create a pixmap as large as the glyph string. Fill it
2142 with the background color. Copy the image to it, using
2143 its mask. Copy the temporary pixmap to the display. */
791f420f
JR
2144 Screen *screen = FRAME_X_SCREEN (s->f);
2145 int depth = DefaultDepthOfScreen (screen);
2146
2147 /* Create a pixmap as large as the glyph string. */
2148 pixmap = XCreatePixmap (s->display, s->window,
2149 s->background_width,
2150 s->height, depth);
d67d1627 2151
791f420f
JR
2152 /* Don't clip in the following because we're working on the
2153 pixmap. */
2154 XSetClipMask (s->display, s->gc, None);
ee78dc32 2155
791f420f
JR
2156 /* Fill the pixmap with the background color/stipple. */
2157 if (s->stippled_p)
2158 {
2159 /* Fill background with a stipple pattern. */
2160 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2161 XFillRectangle (s->display, pixmap, s->gc,
2162 0, 0, s->background_width, s->height);
2163 XSetFillStyle (s->display, s->gc, FillSolid);
2164 }
ef0e360f 2165 else
791f420f
JR
2166 {
2167 XGCValues xgcv;
2168 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2169 &xgcv);
2170 XSetForeground (s->display, s->gc, xgcv.background);
2171 XFillRectangle (s->display, pixmap, s->gc,
2172 0, 0, s->background_width, s->height);
2173 XSetForeground (s->display, s->gc, xgcv.foreground);
2174 }
ee78dc32 2175 }
791f420f
JR
2176 else
2177#endif
791f420f 2178 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
d67d1627 2179
791f420f
JR
2180 s->background_filled_p = 1;
2181 }
ee78dc32 2182
791f420f
JR
2183 /* Draw the foreground. */
2184 if (pixmap != 0)
2185 {
2186 w32_draw_image_foreground_1 (s, pixmap);
2187 x_set_glyph_string_clipping (s);
ee78dc32 2188 {
791f420f
JR
2189 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2190 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2191 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2192 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2193
2194 SetTextColor (s->hdc, s->gc->foreground);
2195 SetBkColor (s->hdc, s->gc->background);
791f420f
JR
2196 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2197 compat_hdc, 0, 0, SRCCOPY);
d30591dc 2198
791f420f
JR
2199 SelectObject (s->hdc, orig_brush);
2200 DeleteObject (fg_brush);
2201 SelectObject (compat_hdc, orig_obj);
2202 DeleteDC (compat_hdc);
2203 }
2204 DeleteObject (pixmap);
2205 pixmap = 0;
2206 }
2207 else
2208 x_draw_image_foreground (s);
ee78dc32 2209
791f420f
JR
2210 /* If we must draw a relief around the image, do it. */
2211 if (s->img->relief
2212 || s->hl == DRAW_IMAGE_RAISED
2213 || s->hl == DRAW_IMAGE_SUNKEN)
2214 x_draw_image_relief (s);
2215}
ee78dc32 2216
cabb23bc 2217
791f420f 2218/* Draw stretch glyph string S. */
cabb23bc 2219
791f420f 2220static void
b56ceb92 2221x_draw_stretch_glyph_string (struct glyph_string *s)
791f420f 2222{
a54e2c05 2223 eassert (s->first_glyph->type == STRETCH_GLYPH);
65c4903c 2224
791f420f
JR
2225 if (s->hl == DRAW_CURSOR
2226 && !x_stretch_cursor_p)
2227 {
b236615c
EZ
2228 /* If `x-stretch-cursor' is nil, don't draw a block cursor as
2229 wide as the stretch glyph. */
e8f6b0db 2230 int width, background_width = s->background_width;
b236615c 2231 int x = s->x;
e8f6b0db 2232
b236615c 2233 if (!s->row->reversed_p)
e8f6b0db 2234 {
b236615c
EZ
2235 int left_x = window_box_left_offset (s->w, TEXT_AREA);
2236
2237 if (x < left_x)
2238 {
2239 background_width -= left_x - x;
2240 x = left_x;
2241 }
2242 }
2243 else
2244 {
2245 /* In R2L rows, draw the cursor on the right edge of the
2246 stretch glyph. */
2247 int right_x = window_box_right_offset (s->w, TEXT_AREA);
2248
2249 if (x + background_width > right_x)
2250 background_width -= x - right_x;
2251 x += background_width;
e8f6b0db
KS
2252 }
2253 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
b236615c
EZ
2254 if (s->row->reversed_p)
2255 x -= width;
cabb23bc 2256
791f420f 2257 /* Draw cursor. */
e8f6b0db 2258 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
cabb23bc 2259
791f420f 2260 /* Clear rest using the GC of the original non-cursor face. */
e8f6b0db 2261 if (width < background_width)
791f420f
JR
2262 {
2263 XGCValues *gc = s->face->gc;
e8f6b0db
KS
2264 int y = s->y;
2265 int w = background_width - width, h = s->height;
791f420f
JR
2266 RECT r;
2267 HDC hdc = s->hdc;
9f5a911b 2268
b236615c
EZ
2269 if (!s->row->reversed_p)
2270 x += width;
2271 else
2272 x = s->x;
9f5a911b
JR
2273 if (s->row->mouse_face_p
2274 && cursor_in_mouse_face_p (s->w))
2275 {
2276 x_set_mouse_face_gc (s);
2277 gc = s->gc;
2278 }
2279 else
2280 gc = s->face->gc;
d67d1627 2281
89271099 2282 get_glyph_string_clip_rect (s, &r);
791f420f
JR
2283 w32_set_clip_rectangle (hdc, &r);
2284
01b220b6 2285#if 0 /* TODO: stipple */
791f420f
JR
2286 if (s->face->stipple)
2287 {
2288 /* Fill background with a stipple pattern. */
2289 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2290 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2291 XSetFillStyle (s->display, gc, FillSolid);
2292 }
2293 else
2294#endif
2295 {
2296 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2297 }
2298 }
2299 }
9f5a911b 2300 else if (!s->background_filled_p)
e8f6b0db
KS
2301 {
2302 int background_width = s->background_width;
2303 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
2304
6c693929
KS
2305 /* Don't draw into left margin, fringe or scrollbar area
2306 except for header line and mode line. */
2307 if (x < left_x && !s->row->mode_line_p)
e8f6b0db
KS
2308 {
2309 background_width -= left_x - x;
2310 x = left_x;
2311 }
2312 if (background_width > 0)
2313 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
5e6b6dcd 2314 }
d67d1627 2315
791f420f
JR
2316 s->background_filled_p = 1;
2317}
cabb23bc 2318
cabb23bc 2319
791f420f
JR
2320/* Draw glyph string S. */
2321
2322static void
b56ceb92 2323x_draw_glyph_string (struct glyph_string *s)
791f420f 2324{
d7e6881a 2325 bool relief_drawn_p = 0;
858a55c1 2326
791f420f
JR
2327 /* If S draws into the background of its successor, draw the
2328 background of the successor first so that S can draw into it.
2329 This makes S->next use XDrawString instead of XDrawImageString. */
c2ded1b7 2330 if (s->next && s->right_overhang && !s->for_overlaps)
791f420f 2331 {
027f6f90
JR
2332 int width;
2333 struct glyph_string *next;
e3f81cd5
CY
2334 for (width = 0, next = s->next;
2335 next && width < s->right_overhang;
027f6f90
JR
2336 width += next->width, next = next->next)
2337 if (next->first_glyph->type != IMAGE_GLYPH)
2338 {
2339 x_set_glyph_string_gc (next);
2340 x_set_glyph_string_clipping (next);
85bdc6d2
CY
2341 if (next->first_glyph->type == STRETCH_GLYPH)
2342 x_draw_stretch_glyph_string (next);
2343 else
2344 x_draw_glyph_string_background (next, 1);
3ca3504a 2345 next->num_clips = 0;
027f6f90 2346 }
791f420f
JR
2347 }
2348
2349 /* Set up S->gc, set clipping and draw S. */
2350 x_set_glyph_string_gc (s);
791f420f 2351
858a55c1
AI
2352 /* Draw relief (if any) in advance for char/composition so that the
2353 glyph string can be drawn over it. */
c2ded1b7 2354 if (!s->for_overlaps
858a55c1
AI
2355 && s->face->box != FACE_NO_BOX
2356 && (s->first_glyph->type == CHAR_GLYPH
2357 || s->first_glyph->type == COMPOSITE_GLYPH))
2358
2359 {
9f5a911b 2360 x_set_glyph_string_clipping (s);
858a55c1
AI
2361 x_draw_glyph_string_background (s, 1);
2362 x_draw_glyph_string_box (s);
9f5a911b 2363 x_set_glyph_string_clipping (s);
858a55c1
AI
2364 relief_drawn_p = 1;
2365 }
a6e0b7e5
JR
2366 else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
2367 && !s->clip_tail
2368 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
2369 || (s->next && s->next->hl != s->hl && s->right_overhang)))
027f6f90
JR
2370 /* We must clip just this glyph. left_overhang part has already
2371 drawn when s->prev was drawn, and right_overhang part will be
2372 drawn later when s->next is drawn. */
2373 x_set_glyph_string_clipping_exactly (s, s);
9f5a911b
JR
2374 else
2375 x_set_glyph_string_clipping (s);
858a55c1 2376
791f420f
JR
2377 switch (s->first_glyph->type)
2378 {
2379 case IMAGE_GLYPH:
2380 x_draw_image_glyph_string (s);
2381 break;
2382
2383 case STRETCH_GLYPH:
2384 x_draw_stretch_glyph_string (s);
2385 break;
2386
2387 case CHAR_GLYPH:
c2ded1b7 2388 if (s->for_overlaps)
791f420f
JR
2389 s->background_filled_p = 1;
2390 else
2391 x_draw_glyph_string_background (s, 0);
2392 x_draw_glyph_string_foreground (s);
2393 break;
2394
2395 case COMPOSITE_GLYPH:
2b107652
KH
2396 if (s->for_overlaps || (s->cmp_from > 0
2397 && ! s->first_glyph->u.cmp.automatic))
791f420f
JR
2398 s->background_filled_p = 1;
2399 else
2400 x_draw_glyph_string_background (s, 1);
2401 x_draw_composite_glyph_string_foreground (s);
2402 break;
2403
b2cca856 2404 case GLYPHLESS_GLYPH:
65b6b59a 2405 if (s->for_overlaps)
b2cca856
KH
2406 s->background_filled_p = 1;
2407 else
65b6b59a 2408 x_draw_glyph_string_background (s, 0);
b2cca856
KH
2409 x_draw_glyphless_glyph_string_foreground (s);
2410 break;
2411
791f420f 2412 default:
1088b922 2413 emacs_abort ();
791f420f
JR
2414 }
2415
c2ded1b7 2416 if (!s->for_overlaps)
791f420f
JR
2417 {
2418 /* Draw underline. */
ef39ccbb 2419 if (s->face->underline_p)
791f420f 2420 {
9b0e3eba 2421 if (s->face->underline_type == FACE_UNDER_WAVE)
30f27523 2422 {
9b0e3eba
AA
2423 COLORREF color;
2424
2425 if (s->face->underline_defaulted_p)
2426 color = s->gc->foreground;
2427 else
2428 color = s->face->underline_color;
2429
2430 w32_draw_underwave (s, color);
ef39ccbb 2431 }
9b0e3eba 2432 else if (s->face->underline_type == FACE_UNDER_LINE)
ef39ccbb 2433 {
9b0e3eba
AA
2434 unsigned long thickness, position;
2435 int y;
2436
4240dd3c
YM
2437 if (s->prev && s->prev->face->underline_p
2438 && s->prev->face->underline_type == FACE_UNDER_LINE)
9b0e3eba
AA
2439 {
2440 /* We use the same underline style as the previous one. */
2441 thickness = s->prev->underline_thickness;
2442 position = s->prev->underline_position;
2443 }
ef39ccbb 2444 else
9b0e3eba
AA
2445 {
2446 /* Get the underline thickness. Default is 1 pixel. */
2447 if (s->font && s->font->underline_thickness > 0)
2448 thickness = s->font->underline_thickness;
2449 else
2450 thickness = 1;
2451 if (x_underline_at_descent_line)
2452 position = (s->height - thickness) - (s->ybase - s->y);
2453 else
2454 {
2455 /* Get the underline position. This is the recommended
2456 vertical offset in pixels from the baseline to the top of
2457 the underline. This is a signed value according to the
2458 specs, and its default is
2459
2460 ROUND ((maximum_descent) / 2), with
2461 ROUND (x) = floor (x + 0.5) */
2462
2463 if (x_use_underline_position_properties
2464 && s->font && s->font->underline_position >= 0)
2465 position = s->font->underline_position;
2466 else if (s->font)
2467 position = (s->font->descent + 1) / 2;
2468 }
2469 position = max (position, underline_minimum_offset);
2470 }
2471 /* Check the sanity of thickness and position. We should
2472 avoid drawing underline out of the current line area. */
2473 if (s->y + s->height <= s->ybase + position)
2474 position = (s->height - 1) - (s->ybase - s->y);
2475 if (s->y + s->height < s->ybase + position + thickness)
2476 thickness = (s->y + s->height) - (s->ybase + position);
2477 s->underline_thickness = thickness;
2478 s->underline_position =position;
2479 y = s->ybase + position;
2480 if (s->face->underline_defaulted_p)
2481 {
2482 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2483 y, s->width, 1);
2484 }
ef39ccbb 2485 else
027f6f90 2486 {
9b0e3eba
AA
2487 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2488 y, s->width, 1);
027f6f90 2489 }
791f420f
JR
2490 }
2491 }
791f420f
JR
2492 /* Draw overline. */
2493 if (s->face->overline_p)
2494 {
2495 unsigned long dy = 0, h = 1;
2496
2497 if (s->face->overline_color_defaulted_p)
027f6f90
JR
2498 {
2499 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
9a01ee33 2500 s->y + dy, s->width, h);
027f6f90 2501 }
791f420f
JR
2502 else
2503 {
59508699 2504 w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
9a01ee33 2505 s->y + dy, s->width, h);
791f420f
JR
2506 }
2507 }
2508
2509 /* Draw strike-through. */
9ef2e2cf 2510 if (s->face->strike_through_p
ed3751c8 2511 && !FONT_TEXTMETRIC (s->font).tmStruckOut)
791f420f
JR
2512 {
2513 unsigned long h = 1;
2514 unsigned long dy = (s->height - h) / 2;
2515
2516 if (s->face->strike_through_color_defaulted_p)
2517 {
2518 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2519 s->width, h);
2520 }
2521 else
2522 {
def7fa34 2523 w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
791f420f
JR
2524 s->y + dy, s->width, h);
2525 }
2526 }
2527
027f6f90 2528 /* Draw relief if not yet drawn. */
858a55c1 2529 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
791f420f 2530 x_draw_glyph_string_box (s);
027f6f90
JR
2531
2532 if (s->prev)
2533 {
2534 struct glyph_string *prev;
2535
2536 for (prev = s->prev; prev; prev = prev->prev)
2537 if (prev->hl != s->hl
2538 && prev->x + prev->width + prev->right_overhang > s->x)
2539 {
2540 /* As prev was drawn while clipped to its own area, we
2541 must draw the right_overhang part using s->hl now. */
2542 enum draw_glyphs_face save = prev->hl;
2543
2544 prev->hl = s->hl;
2545 x_set_glyph_string_gc (prev);
2546 x_set_glyph_string_clipping_exactly (s, prev);
2547 if (prev->first_glyph->type == CHAR_GLYPH)
2548 x_draw_glyph_string_foreground (prev);
2549 else
2550 x_draw_composite_glyph_string_foreground (prev);
2551 w32_set_clip_rectangle (prev->hdc, NULL);
2552 prev->hl = save;
3ca3504a 2553 prev->num_clips = 0;
027f6f90
JR
2554 }
2555 }
2556
2557 if (s->next)
2558 {
2559 struct glyph_string *next;
2560
2561 for (next = s->next; next; next = next->next)
2562 if (next->hl != s->hl
2563 && next->x - next->left_overhang < s->x + s->width)
2564 {
2565 /* As next will be drawn while clipped to its own area,
2566 we must draw the left_overhang part using s->hl now. */
2567 enum draw_glyphs_face save = next->hl;
2568
2569 next->hl = s->hl;
2570 x_set_glyph_string_gc (next);
2571 x_set_glyph_string_clipping_exactly (s, next);
2572 if (next->first_glyph->type == CHAR_GLYPH)
2573 x_draw_glyph_string_foreground (next);
2574 else
2575 x_draw_composite_glyph_string_foreground (next);
2576 w32_set_clip_rectangle (next->hdc, NULL);
2577 next->hl = save;
3ca3504a 2578 next->num_clips = 0;
3057e615 2579 next->clip_head = s->next;
027f6f90
JR
2580 }
2581 }
791f420f
JR
2582 }
2583
2584 /* Reset clipping. */
2585 w32_set_clip_rectangle (s->hdc, NULL);
3ca3504a 2586 s->num_clips = 0;
791f420f
JR
2587}
2588
2589
89271099 2590/* Shift display to make room for inserted glyphs. */
ee78dc32 2591
89271099 2592void
b56ceb92
JB
2593w32_shift_glyphs_for_insert (struct frame *f, int x, int y,
2594 int width, int height, int shift_by)
791f420f 2595{
791f420f
JR
2596 HDC hdc;
2597
791f420f 2598 hdc = get_frame_dc (f);
89271099
KS
2599 BitBlt (hdc, x + shift_by, y, width, height,
2600 hdc, x, y, SRCCOPY);
791f420f 2601
791f420f 2602 release_frame_dc (f, hdc);
ee78dc32 2603}
791f420f
JR
2604
2605
2606/* Delete N glyphs at the nominal cursor position. Not implemented
2607 for X frames. */
ee78dc32 2608
96214669 2609static void
b56ceb92 2610x_delete_glyphs (struct frame *f, register int n)
ee78dc32 2611{
7e6ac5b9
AI
2612 if (! FRAME_W32_P (f))
2613 return;
2614
1088b922 2615 emacs_abort ();
791f420f 2616}
ee78dc32 2617
ee78dc32 2618
7684e57b 2619/* Clear entire frame. */
791f420f 2620
96214669 2621static void
4a418b10 2622x_clear_frame (struct frame *f)
ee78dc32 2623{
7e6ac5b9
AI
2624 if (! FRAME_W32_P (f))
2625 return;
2626
791f420f
JR
2627 /* Clearing the frame will erase any cursor, so mark them all as no
2628 longer visible. */
2629 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
ee78dc32 2630
4d7e6e51 2631 block_input ();
ee78dc32 2632
fbd6baed 2633 w32_clear_window (f);
ee78dc32
GV
2634
2635 /* We have to clear the scroll bars, too. If we have changed
2636 colors or something like that, then they should be notified. */
2637 x_scroll_bar_clear (f);
2638
4d7e6e51 2639 unblock_input ();
ee78dc32 2640}
791f420f 2641
ee78dc32
GV
2642\f
2643/* Make audible bell. */
2644
96214669 2645static void
4a418b10 2646w32_ring_bell (struct frame *f)
ee78dc32 2647{
4d7e6e51 2648 block_input ();
ee78dc32 2649
0f32f023 2650 if (FRAME_W32_P (f) && visible_bell)
8331e676
GV
2651 {
2652 int i;
4a418b10 2653 HWND hwnd = FRAME_W32_WINDOW (f);
8331e676 2654
d67d1627 2655 for (i = 0; i < 5; i++)
8331e676
GV
2656 {
2657 FlashWindow (hwnd, TRUE);
2658 Sleep (10);
2659 }
2660 FlashWindow (hwnd, FALSE);
2661 }
ee78dc32 2662 else
4a418b10 2663 w32_sys_ring_bell (f);
ee78dc32 2664
4d7e6e51 2665 unblock_input ();
ee78dc32 2666}
791f420f 2667
791f420f
JR
2668/***********************************************************************
2669 Line Dance
2670 ***********************************************************************/
2671
2672/* Perform an insert-lines or delete-lines operation, inserting N
2673 lines or deleting -N lines at vertical position VPOS. */
ee78dc32 2674
96214669 2675static void
b56ceb92 2676x_ins_del_lines (struct frame *f, int vpos, int n)
ee78dc32 2677{
7e6ac5b9
AI
2678 if (! FRAME_W32_P (f))
2679 return;
2680
1088b922 2681 emacs_abort ();
ee78dc32 2682}
791f420f
JR
2683
2684
2685/* Scroll part of the display as described by RUN. */
2686
2687static void
b56ceb92 2688x_scroll_run (struct window *w, struct run *run)
791f420f 2689{
d3d50620 2690 struct frame *f = XFRAME (w->frame);
791f420f 2691 int x, y, width, height, from_y, to_y, bottom_y;
4d6e8199
JR
2692 HWND hwnd = FRAME_W32_WINDOW (f);
2693 HRGN expect_dirty;
791f420f
JR
2694
2695 /* Get frame-relative bounding box of the text display area of W,
33c34bea
KS
2696 without mode lines. Include in this box the left and right
2697 fringes of W. */
c3c4768d 2698 window_box (w, ANY_AREA, &x, &y, &width, &height);
791f420f 2699
7db47798
YM
2700 /* If the fringe is adjacent to the left (right) scroll bar of a
2701 leftmost (rightmost, respectively) window, then extend its
2702 background to the gap between the fringe and the bar. */
2703 if ((WINDOW_LEFTMOST_P (w)
2704 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2705 || (WINDOW_RIGHTMOST_P (w)
2706 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2707 {
2708 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2709
2710 if (sb_width > 0)
2711 {
2712 int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
2713 int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2714 * FRAME_COLUMN_WIDTH (f));
2715
2716 if (bar_area_x + bar_area_width == x)
2717 {
2718 x = bar_area_x + sb_width;
2719 width += bar_area_width - sb_width;
2720 }
2721 else if (x + width == bar_area_x)
2722 width += bar_area_width - sb_width;
2723 }
2724 }
2725
791f420f
JR
2726 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2727 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2728 bottom_y = y + height;
2729
2730 if (to_y < from_y)
2731 {
2732 /* Scrolling up. Make sure we don't copy part of the mode
2733 line at the bottom. */
2734 if (from_y + run->height > bottom_y)
2735 height = bottom_y - from_y;
2736 else
2737 height = run->height;
4d6e8199 2738 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
791f420f
JR
2739 }
2740 else
2741 {
fa463103 2742 /* Scrolling down. Make sure we don't copy over the mode line.
791f420f
JR
2743 at the bottom. */
2744 if (to_y + run->height > bottom_y)
2745 height = bottom_y - to_y;
2746 else
2747 height = run->height;
4d6e8199 2748 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
791f420f
JR
2749 }
2750
4d7e6e51 2751 block_input ();
d67d1627 2752
791f420f 2753 /* Cursor off. Will be switched on again in x_update_window_end. */
791f420f
JR
2754 x_clear_cursor (w);
2755
4d6e8199
JR
2756 {
2757 RECT from;
2758 RECT to;
2759 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
2760 HRGN combined = CreateRectRgn (0, 0, 0, 0);
2761
2762 from.left = to.left = x;
2763 from.right = to.right = x + width;
2764 from.top = from_y;
2765 from.bottom = from_y + height;
2766 to.top = y;
2767 to.bottom = bottom_y;
2768
2769 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
2770 NULL, SW_INVALIDATE);
2771
2772 /* Combine this with what we expect to be dirty. This covers the
2773 case where not all of the region we expect is actually dirty. */
2774 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
2775
2776 /* If the dirty region is not what we expected, redraw the entire frame. */
2777 if (!EqualRgn (combined, expect_dirty))
2778 SET_FRAME_GARBAGED (f);
e8ac5d88
JR
2779
2780 DeleteObject (dirty);
2781 DeleteObject (combined);
4d6e8199
JR
2782 }
2783
4d7e6e51 2784 unblock_input ();
e8ac5d88 2785 DeleteObject (expect_dirty);
791f420f
JR
2786}
2787
9ef2e2cf 2788
ee78dc32 2789\f
791f420f
JR
2790/***********************************************************************
2791 Exposure Events
2792 ***********************************************************************/
d67d1627 2793
96214669 2794static void
b56ceb92 2795frame_highlight (struct frame *f)
ee78dc32 2796{
89271099 2797 x_update_cursor (f, 1);
8b61a891 2798 x_set_frame_alpha (f);
89271099 2799}
791f420f 2800
89271099 2801static void
b56ceb92 2802frame_unhighlight (struct frame *f)
89271099
KS
2803{
2804 x_update_cursor (f, 1);
8b61a891 2805 x_set_frame_alpha (f);
89271099 2806}
791f420f 2807
89271099
KS
2808/* The focus has changed. Update the frames as necessary to reflect
2809 the new situation. Note that we can't change the selected frame
2810 here, because the Lisp code we are interrupting might become confused.
2811 Each event gets marked with the frame in which it occurred, so the
2812 Lisp code can tell when the switch took place by examining the events. */
791f420f 2813
89271099 2814static void
b56ceb92 2815x_new_focus_frame (struct w32_display_info *dpyinfo, struct frame *frame)
89271099
KS
2816{
2817 struct frame *old_focus = dpyinfo->w32_focus_frame;
791f420f 2818
89271099 2819 if (frame != dpyinfo->w32_focus_frame)
791f420f 2820 {
89271099
KS
2821 /* Set this before calling other routines, so that they see
2822 the correct value of w32_focus_frame. */
2823 dpyinfo->w32_focus_frame = frame;
791f420f 2824
89271099
KS
2825 if (old_focus && old_focus->auto_lower)
2826 x_lower_frame (old_focus);
791f420f 2827
89271099
KS
2828 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
2829 pending_autoraise_frame = dpyinfo->w32_focus_frame;
2df85294 2830 else
89271099 2831 pending_autoraise_frame = 0;
791f420f 2832 }
89271099
KS
2833
2834 x_frame_rehighlight (dpyinfo);
791f420f
JR
2835}
2836
55131bef
JR
2837
2838/* Handle FocusIn and FocusOut state changes for FRAME.
2839 If FRAME has focus and there exists more than one frame, puts
2840 a FOCUS_IN_EVENT into *BUFP. */
2841
2842static void
b56ceb92
JB
2843x_focus_changed (int type, int state, struct w32_display_info *dpyinfo,
2844 struct frame *frame, struct input_event *bufp)
55131bef
JR
2845{
2846 if (type == WM_SETFOCUS)
2847 {
2848 if (dpyinfo->w32_focus_event_frame != frame)
2849 {
2850 x_new_focus_frame (dpyinfo, frame);
2851 dpyinfo->w32_focus_event_frame = frame;
2852
2853 /* Don't stop displaying the initial startup message
2854 for a switch-frame event we don't need. */
8e50cc2d
SM
2855 if (NILP (Vterminal_frame)
2856 && CONSP (Vframe_list)
2857 && !NILP (XCDR (Vframe_list)))
55131bef 2858 {
945c5bb1 2859 bufp->arg = Qt;
55131bef 2860 }
945c5bb1
JB
2861 else
2862 {
2863 bufp->arg = Qnil;
2864 }
2865
2866 bufp->kind = FOCUS_IN_EVENT;
2867 XSETFRAME (bufp->frame_or_window, frame);
55131bef
JR
2868 }
2869
2870 frame->output_data.x->focus_state |= state;
2871
2872 /* TODO: IME focus? */
2873 }
2874 else if (type == WM_KILLFOCUS)
2875 {
2876 frame->output_data.x->focus_state &= ~state;
2877
2878 if (dpyinfo->w32_focus_event_frame == frame)
2879 {
2880 dpyinfo->w32_focus_event_frame = 0;
2881 x_new_focus_frame (dpyinfo, 0);
945c5bb1
JB
2882
2883 bufp->kind = FOCUS_OUT_EVENT;
2884 XSETFRAME (bufp->frame_or_window, frame);
2885 }
55131bef
JR
2886
2887 /* TODO: IME focus? */
2888 }
2889}
2890
2891
2892/* The focus may have changed. Figure out if it is a real focus change,
2893 by checking both FocusIn/Out and Enter/LeaveNotify events.
2894
2895 Returns FOCUS_IN_EVENT event in *BUFP. */
2896
2897static void
b56ceb92
JB
2898w32_detect_focus_change (struct w32_display_info *dpyinfo, W32Msg *event,
2899 struct input_event *bufp)
55131bef
JR
2900{
2901 struct frame *frame;
2902
2903 frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
2904 if (! frame)
2905 return;
2906
2907 /* On w32, this is only called from focus events, so no switch needed. */
2908 x_focus_changed (event->msg.message,
2909 (event->msg.message == WM_KILLFOCUS ?
2910 FOCUS_IMPLICIT : FOCUS_EXPLICIT),
2911 dpyinfo, frame, bufp);
2912}
2913
2914
89271099 2915/* Handle an event saying the mouse has moved out of an Emacs frame. */
ee78dc32
GV
2916
2917void
b56ceb92 2918x_mouse_leave (struct w32_display_info *dpyinfo)
ee78dc32 2919{
fbd6baed 2920 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
ee78dc32
GV
2921}
2922
2923/* The focus has changed, or we have redirected a frame's focus to
2924 another frame (this happens when a frame uses a surrogate
9ef2e2cf 2925 mini-buffer frame). Shift the highlight as appropriate.
ee78dc32
GV
2926
2927 The FRAME argument doesn't necessarily have anything to do with which
9ef2e2cf
JR
2928 frame is being highlighted or un-highlighted; we only use it to find
2929 the appropriate X display info. */
2930
ee78dc32 2931static void
b56ceb92 2932w32_frame_rehighlight (struct frame *frame)
ee78dc32 2933{
7e6ac5b9
AI
2934 if (! FRAME_W32_P (frame))
2935 return;
fbd6baed 2936 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
ee78dc32
GV
2937}
2938
2939static void
b56ceb92 2940x_frame_rehighlight (struct w32_display_info *dpyinfo)
ee78dc32 2941{
4baaed0f 2942 struct frame *old_highlight = dpyinfo->x_highlight_frame;
ee78dc32 2943
fbd6baed 2944 if (dpyinfo->w32_focus_frame)
ee78dc32 2945 {
4baaed0f 2946 dpyinfo->x_highlight_frame
8e50cc2d 2947 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
fbd6baed
GV
2948 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
2949 : dpyinfo->w32_focus_frame);
4baaed0f 2950 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
ee78dc32 2951 {
f00af5b1 2952 fset_focus_frame (dpyinfo->w32_focus_frame, Qnil);
4baaed0f 2953 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
ee78dc32
GV
2954 }
2955 }
2956 else
4baaed0f 2957 dpyinfo->x_highlight_frame = 0;
ee78dc32 2958
4baaed0f 2959 if (dpyinfo->x_highlight_frame != old_highlight)
ee78dc32
GV
2960 {
2961 if (old_highlight)
2962 frame_unhighlight (old_highlight);
4baaed0f
KS
2963 if (dpyinfo->x_highlight_frame)
2964 frame_highlight (dpyinfo->x_highlight_frame);
ee78dc32
GV
2965 }
2966}
2967\f
2968/* Keyboard processing - modifier keys, etc. */
2969
2970/* Convert a keysym to its name. */
2971
2972char *
b56ceb92 2973x_get_keysym_name (int keysym)
ee78dc32
GV
2974{
2975 /* Make static so we can always return it */
2976 static char value[100];
2977
4d7e6e51 2978 block_input ();
9127e20e 2979 GetKeyNameText (keysym, value, 100);
4d7e6e51 2980 unblock_input ();
ee78dc32
GV
2981
2982 return value;
2983}
9ef2e2cf 2984
b56ceb92
JB
2985static int
2986codepage_for_locale (LCID locale)
13087e59
JR
2987{
2988 char cp[20];
2989
2990 if (GetLocaleInfo (locale, LOCALE_IDEFAULTANSICODEPAGE, cp, 20) > 0)
2991 return atoi (cp);
2992 else
2993 return CP_ACP;
2994}
9ef2e2cf 2995
ee78dc32
GV
2996\f
2997/* Mouse clicks and mouse movement. Rah. */
2998
53823ab9
JR
2999/* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3000 the state in PUP. XBUTTON provides extra information for extended mouse
3001 button messages. Returns FALSE if unable to parse the message. */
d67d1627 3002BOOL
b56ceb92 3003parse_button (int message, int xbutton, int * pbutton, int * pup)
ee78dc32
GV
3004{
3005 int button = 0;
3006 int up = 0;
d67d1627 3007
ee78dc32
GV
3008 switch (message)
3009 {
3010 case WM_LBUTTONDOWN:
3011 button = 0;
3012 up = 0;
3013 break;
3014 case WM_LBUTTONUP:
3015 button = 0;
3016 up = 1;
3017 break;
3018 case WM_MBUTTONDOWN:
fbd6baed 3019 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3020 button = 1;
3021 else
3022 button = 2;
ee78dc32
GV
3023 up = 0;
3024 break;
3025 case WM_MBUTTONUP:
fbd6baed 3026 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3027 button = 1;
3028 else
3029 button = 2;
ee78dc32
GV
3030 up = 1;
3031 break;
3032 case WM_RBUTTONDOWN:
fbd6baed 3033 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3034 button = 2;
3035 else
3036 button = 1;
ee78dc32
GV
3037 up = 0;
3038 break;
3039 case WM_RBUTTONUP:
fbd6baed 3040 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3041 button = 2;
3042 else
3043 button = 1;
ee78dc32
GV
3044 up = 1;
3045 break;
53823ab9
JR
3046 case WM_XBUTTONDOWN:
3047 button = xbutton + 2;
3048 up = 0;
3049 break;
3050 case WM_XBUTTONUP:
3051 button = xbutton + 2;
3052 up = 1;
3053 break;
ee78dc32
GV
3054 default:
3055 return (FALSE);
3056 }
d67d1627 3057
ee78dc32
GV
3058 if (pup) *pup = up;
3059 if (pbutton) *pbutton = button;
d67d1627 3060
ee78dc32
GV
3061 return (TRUE);
3062}
3063
3064
3065/* Prepare a mouse-event in *RESULT for placement in the input queue.
3066
3067 If the event is a button press, then note that we have grabbed
3068 the mouse. */
3069
ec48c3a7 3070static Lisp_Object
b56ceb92 3071construct_mouse_click (struct input_event *result, W32Msg *msg, struct frame *f)
ee78dc32
GV
3072{
3073 int button;
3074 int up;
3075
53823ab9
JR
3076 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3077 &button, &up);
ee78dc32 3078
3b8f9651 3079 /* Make the event type NO_EVENT; we'll change that when we decide
ee78dc32 3080 otherwise. */
3b8f9651 3081 result->kind = MOUSE_CLICK_EVENT;
ee78dc32
GV
3082 result->code = button;
3083 result->timestamp = msg->msg.time;
3084 result->modifiers = (msg->dwModifiers
3085 | (up
3086 ? up_modifier
3087 : down_modifier));
3088
ec48c3a7
JR
3089 XSETINT (result->x, LOWORD (msg->msg.lParam));
3090 XSETINT (result->y, HIWORD (msg->msg.lParam));
3091 XSETFRAME (result->frame_or_window, f);
3092 result->arg = Qnil;
3093 return Qnil;
ee78dc32
GV
3094}
3095
ec48c3a7 3096static Lisp_Object
b56ceb92 3097construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
689004fa
GV
3098{
3099 POINT p;
637ad49d
JR
3100 int delta;
3101
1526bc23
JR
3102 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3103 : WHEEL_EVENT;
637ad49d 3104 result->code = 0;
689004fa 3105 result->timestamp = msg->msg.time;
637ad49d
JR
3106
3107 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3108 forward, away from the user (up); a negative value indicates that
3109 the wheel was rotated backward, toward the user (down). */
3110 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3111
3112 /* The up and down modifiers indicate if the wheel was rotated up or
3113 down based on WHEEL_DELTA value. */
3114 result->modifiers = (msg->dwModifiers
3115 | ((delta < 0 ) ? down_modifier : up_modifier));
3116
8b03732e
JR
3117 /* With multiple monitors, we can legitimately get negative
3118 coordinates, so cast to short to interpret them correctly. */
3119 p.x = (short) LOWORD (msg->msg.lParam);
3120 p.y = (short) HIWORD (msg->msg.lParam);
9127e20e 3121 ScreenToClient (msg->msg.hwnd, &p);
689004fa
GV
3122 XSETINT (result->x, p.x);
3123 XSETINT (result->y, p.y);
3124 XSETFRAME (result->frame_or_window, f);
7e889510 3125 result->arg = Qnil;
ec48c3a7 3126 return Qnil;
689004fa
GV
3127}
3128
ec48c3a7 3129static Lisp_Object
b56ceb92 3130construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
12857dfd
RS
3131{
3132 Lisp_Object files;
3133 Lisp_Object frame;
3134 HDROP hdrop;
3135 POINT p;
3136 WORD num_files;
819e2da9 3137 guichar_t *name;
89271099 3138 int i, len;
d67d1627 3139
89271099
KS
3140 result->kind = DRAG_N_DROP_EVENT;
3141 result->code = 0;
3142 result->timestamp = msg->msg.time;
3143 result->modifiers = msg->dwModifiers;
791f420f 3144
89271099
KS
3145 hdrop = (HDROP) msg->msg.wParam;
3146 DragQueryPoint (hdrop, &p);
791f420f 3147
89271099
KS
3148#if 0
3149 p.x = LOWORD (msg->msg.lParam);
3150 p.y = HIWORD (msg->msg.lParam);
3151 ScreenToClient (msg->msg.hwnd, &p);
3152#endif
791f420f 3153
89271099
KS
3154 XSETINT (result->x, p.x);
3155 XSETINT (result->y, p.y);
791f420f 3156
89271099
KS
3157 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3158 files = Qnil;
ee78dc32 3159
89271099
KS
3160 for (i = 0; i < num_files; i++)
3161 {
819e2da9 3162 len = GUI_FN (DragQueryFile) (hdrop, i, NULL, 0);
89271099
KS
3163 if (len <= 0)
3164 continue;
819e2da9
DC
3165
3166 name = alloca ((len + 1) * sizeof (*name));
3167 GUI_FN (DragQueryFile) (hdrop, i, name, len + 1);
3168#ifdef NTGUI_UNICODE
3169 files = Fcons (from_unicode_buffer (name), files);
3170#else
89271099 3171 files = Fcons (DECODE_FILE (build_string (name)), files);
819e2da9 3172#endif /* NTGUI_UNICODE */
ee78dc32
GV
3173 }
3174
89271099 3175 DragFinish (hdrop);
2bf04b9d 3176
89271099 3177 XSETFRAME (frame, f);
00cff0a1
YM
3178 result->frame_or_window = frame;
3179 result->arg = files;
89271099 3180 return Qnil;
ee78dc32
GV
3181}
3182
c5c91b84 3183\f
7f203aa1
EZ
3184#if HAVE_W32NOTIFY
3185
c5c91b84
EZ
3186/* File event notifications (see w32notify.c). */
3187
182b170f 3188Lisp_Object
477f1e50
EZ
3189lispy_file_action (DWORD action)
3190{
3191 static char unknown_fmt[] = "unknown-action(%d)";
3192 Lisp_Object retval;
3193
3194 switch (action)
3195 {
3196 case FILE_ACTION_ADDED:
3197 retval = Qadded;
3198 break;
3199 case FILE_ACTION_REMOVED:
3200 retval = Qremoved;
3201 break;
3202 case FILE_ACTION_MODIFIED:
3203 retval = Qmodified;
3204 break;
3205 case FILE_ACTION_RENAMED_OLD_NAME:
3206 retval = Qrenamed_from;
3207 break;
3208 case FILE_ACTION_RENAMED_NEW_NAME:
3209 retval = Qrenamed_to;
3210 break;
3211 default:
3212 {
3213 char buf[sizeof(unknown_fmt) - 1 + INT_STRLEN_BOUND (DWORD)];
3214
3215 sprintf (buf, unknown_fmt, action);
3216 retval = intern (buf);
3217 }
3218 break;
3219 }
3220
3221 return retval;
3222}
3223
8db4b52f 3224#ifdef WINDOWSNT
477f1e50
EZ
3225/* Put file notifications into the Emacs input event queue. This
3226 function runs when the WM_EMACS_FILENOTIFY message arrives from a
3227 watcher thread. */
3228static void
3229queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
3230 int *evcount)
3231{
3232 BYTE *p = file_notifications;
3233 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
3234 const DWORD min_size
3235 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
3236 Lisp_Object frame;
3237
3238 /* We cannot process notification before Emacs is fully initialized,
3239 since we need the UTF-16LE coding-system to be set up. */
3240 if (!initialized)
3241 {
3242 notification_buffer_in_use = 0;
3243 return;
3244 }
3245
3246 XSETFRAME (frame, f);
3247
3248 enter_crit ();
3249 if (notification_buffer_in_use)
3250 {
3251 DWORD info_size = notifications_size;
4f0800ec 3252 Lisp_Object cs = intern ("utf-16le");
0b86d359 3253 Lisp_Object obj = w32_get_watch_object (notifications_desc);
477f1e50
EZ
3254
3255 /* notifications_size could be zero when the buffer of
3256 notifications overflowed on the OS level, or when the
3257 directory being watched was itself deleted. Do nothing in
3258 that case. */
4f0800ec
EZ
3259 if (info_size
3260 && !NILP (obj) && CONSP (obj))
477f1e50 3261 {
4f0800ec
EZ
3262 Lisp_Object callback = XCDR (obj);
3263
477f1e50
EZ
3264 while (info_size >= min_size)
3265 {
3266 Lisp_Object utf_16_fn
3267 = make_unibyte_string ((char *)fni->FileName,
3268 fni->FileNameLength);
3269 /* Note: mule-conf is preloaded, so utf-16le must
3270 already be defined at this point. */
3271 Lisp_Object fname
4f0800ec 3272 = code_convert_string_norecord (utf_16_fn, cs, 0);
477f1e50 3273 Lisp_Object action = lispy_file_action (fni->Action);
477f1e50 3274
4f0800ec 3275 event->kind = FILE_NOTIFY_EVENT;
d884121b
EZ
3276 event->code
3277 = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
4f0800ec
EZ
3278 event->timestamp = msg->msg.time;
3279 event->modifiers = 0;
3280 event->frame_or_window = callback;
3281 event->arg = Fcons (action, fname);
3282 kbd_buffer_store_event (event);
3283 (*evcount)++;
477f1e50
EZ
3284
3285 if (!fni->NextEntryOffset)
3286 break;
3287 p += fni->NextEntryOffset;
3288 fni = (PFILE_NOTIFY_INFORMATION)p;
3289 info_size -= fni->NextEntryOffset;
3290 }
3291 }
3292 notification_buffer_in_use = 0;
3293 }
3294 else
3295 DebPrint (("We were promised notifications, but in-use flag is zero!\n"));
3296 leave_crit ();
3297
3298 /* We've stuffed all the events ourselves, so w32_read_socket shouldn't. */
3299 event->kind = NO_EVENT;
3300}
7f203aa1
EZ
3301#endif /* WINDOWSNT */
3302#endif /* HAVE_W32NOTIFY */
477f1e50 3303
89271099
KS
3304\f
3305/* Function to report a mouse movement to the mainstream Emacs code.
3306 The input handler calls this.
ee78dc32 3307
89271099
KS
3308 We have received a mouse movement event, which is given in *event.
3309 If the mouse is over a different glyph than it was last time, tell
3310 the mainstream emacs code by setting mouse_moved. If not, ask for
3311 another motion event, so we can check again the next time it moves. */
31d4844a 3312
89271099
KS
3313static MSG last_mouse_motion_event;
3314static Lisp_Object last_mouse_motion_frame;
ec48c3a7 3315
fc5c7550 3316static int
a10c8269 3317note_mouse_movement (struct frame *frame, MSG *msg)
ec48c3a7 3318{
89271099
KS
3319 int mouse_x = LOWORD (msg->lParam);
3320 int mouse_y = HIWORD (msg->lParam);
ec48c3a7 3321
89271099
KS
3322 last_mouse_movement_time = msg->time;
3323 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3324 XSETFRAME (last_mouse_motion_frame, frame);
31d4844a 3325
027f6f90
JR
3326 if (!FRAME_X_OUTPUT (frame))
3327 return 0;
3328
89271099
KS
3329 if (msg->hwnd != FRAME_W32_WINDOW (frame))
3330 {
3331 frame->mouse_moved = 1;
3332 last_mouse_scroll_bar = Qnil;
3333 note_mouse_highlight (frame, -1, -1);
d3499758 3334 last_mouse_glyph_frame = 0;
fc5c7550 3335 return 1;
89271099 3336 }
31d4844a 3337
89271099 3338 /* Has the mouse moved off the glyph it was on at the last sighting? */
d3499758
JR
3339 if (frame != last_mouse_glyph_frame
3340 || mouse_x < last_mouse_glyph.left
fc5c7550
YM
3341 || mouse_x >= last_mouse_glyph.right
3342 || mouse_y < last_mouse_glyph.top
3343 || mouse_y >= last_mouse_glyph.bottom)
31d4844a 3344 {
89271099
KS
3345 frame->mouse_moved = 1;
3346 last_mouse_scroll_bar = Qnil;
3347 note_mouse_highlight (frame, mouse_x, mouse_y);
3348 /* Remember the mouse position here, as w32_mouse_position only
3349 gets called when mouse tracking is enabled but we also need
3350 to keep track of the mouse for help_echo and highlighting at
3351 other times. */
1bb92eca 3352 remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
d3499758 3353 last_mouse_glyph_frame = frame;
fc5c7550 3354 return 1;
31d4844a 3355 }
fc5c7550
YM
3356
3357 return 0;
31d4844a 3358}
89271099 3359
ee78dc32 3360\f
89271099
KS
3361/************************************************************************
3362 Mouse Face
3363 ************************************************************************/
3364
b56ceb92 3365static struct scroll_bar *x_window_to_scroll_bar (Window);
a10c8269 3366static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
b56ceb92
JB
3367 enum scroll_bar_part *,
3368 Lisp_Object *, Lisp_Object *,
3369 unsigned long *);
f57e2426 3370static void x_check_fullscreen (struct frame *);
9f5a911b 3371
89271099 3372static void
b56ceb92 3373redo_mouse_highlight (void)
89271099
KS
3374{
3375 if (!NILP (last_mouse_motion_frame)
3376 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3377 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3378 LOWORD (last_mouse_motion_event.lParam),
3379 HIWORD (last_mouse_motion_event.lParam));
3380}
3381
1bb8a291 3382static void
b56ceb92 3383w32_define_cursor (Window window, Cursor cursor)
89271099
KS
3384{
3385 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
3386}
ee78dc32
GV
3387/* Return the current position of the mouse.
3388 *fp should be a frame which indicates which display to ask about.
3389
3390 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3391 and *part to the frame, window, and scroll bar part that the mouse
3392 is over. Set *x and *y to the portion and whole of the mouse's
3393 position on the scroll bar.
3394
3395 If the mouse movement started elsewhere, set *fp to the frame the
3396 mouse is on, *bar_window to nil, and *x and *y to the character cell
3397 the mouse is over.
3398
9ef2e2cf 3399 Set *time to the server time-stamp for the time at which the mouse
ee78dc32
GV
3400 was at this position.
3401
3402 Don't store anything if we don't have a valid set of values to report.
3403
3404 This clears the mouse_moved flag, so we can wait for the next mouse
9ef2e2cf 3405 movement. */
ee78dc32
GV
3406
3407static void
a10c8269 3408w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
b56ceb92
JB
3409 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3410 unsigned long *time)
ee78dc32 3411{
a10c8269 3412 struct frame *f1;
ee78dc32 3413
4d7e6e51 3414 block_input ();
ee78dc32 3415
95fa970d 3416 if (! NILP (last_mouse_scroll_bar) && insist == 0)
ee78dc32
GV
3417 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3418 else
3419 {
3420 POINT pt;
3421
3422 Lisp_Object frame, tail;
3423
3424 /* Clear the mouse-moved flag for every frame on this display. */
3425 FOR_EACH_FRAME (tail, frame)
3426 XFRAME (frame)->mouse_moved = 0;
3427
3428 last_mouse_scroll_bar = Qnil;
d67d1627 3429
ee78dc32
GV
3430 GetCursorPos (&pt);
3431
3432 /* Now we have a position on the root; find the innermost window
3433 containing the pointer. */
3434 {
fbd6baed 3435 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
ee78dc32
GV
3436 && FRAME_LIVE_P (last_mouse_frame))
3437 {
08712a41
AI
3438 /* If mouse was grabbed on a frame, give coords for that frame
3439 even if the mouse is now outside it. */
ee78dc32
GV
3440 f1 = last_mouse_frame;
3441 }
3442 else
3443 {
08712a41 3444 /* Is window under mouse one of our frames? */
9f5a911b 3445 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
9127e20e 3446 WindowFromPoint (pt));
ee78dc32
GV
3447 }
3448
3449 /* If not, is it one of our scroll bars? */
3450 if (! f1)
3451 {
9127e20e
JR
3452 struct scroll_bar *bar
3453 = x_window_to_scroll_bar (WindowFromPoint (pt));
ee78dc32
GV
3454
3455 if (bar)
3456 {
3457 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3458 }
3459 }
3460
95fa970d 3461 if (f1 == 0 && insist > 0)
791f420f 3462 f1 = SELECTED_FRAME ();
ee78dc32
GV
3463
3464 if (f1)
3465 {
791f420f
JR
3466 /* Ok, we found a frame. Store all the values.
3467 last_mouse_glyph is a rectangle used to reduce the
3468 generation of mouse events. To not miss any motion
3469 events, we must divide the frame into rectangles of the
3470 size of the smallest character that could be displayed
3471 on it, i.e. into the same rectangles that matrices on
3472 the frame are divided into. */
3473
791f420f 3474 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
1bb92eca 3475 remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
d3499758 3476 last_mouse_glyph_frame = f1;
ee78dc32
GV
3477
3478 *bar_window = Qnil;
3479 *part = 0;
3480 *fp = f1;
3481 XSETINT (*x, pt.x);
3482 XSETINT (*y, pt.y);
3483 *time = last_mouse_movement_time;
3484 }
3485 }
3486 }
3487
4d7e6e51 3488 unblock_input ();
ee78dc32 3489}
791f420f 3490
ee78dc32 3491\f
89271099
KS
3492/***********************************************************************
3493 Tool-bars
3494 ***********************************************************************/
3495
3496/* Handle mouse button event on the tool-bar of frame F, at
301b181a 3497 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
09e80d9f 3498 or ButtonRelease. */
89271099
KS
3499
3500static void
b56ceb92 3501w32_handle_tool_bar_click (struct frame *f, struct input_event *button_event)
89271099
KS
3502{
3503 int x = XFASTINT (button_event->x);
3504 int y = XFASTINT (button_event->y);
3505
3506 if (button_event->modifiers & down_modifier)
3507 handle_tool_bar_click (f, x, y, 1, 0);
3508 else
3509 handle_tool_bar_click (f, x, y, 0,
3510 button_event->modifiers & ~up_modifier);
3511}
3512
3513
3514\f
3515/***********************************************************************
3516 Scroll bars
3517 ***********************************************************************/
3518
ee78dc32
GV
3519/* Scroll bar support. */
3520
ec48c3a7 3521/* Given a window ID, find the struct scroll_bar which manages it.
ee78dc32
GV
3522 This can be called in GC, so we have to make sure to strip off mark
3523 bits. */
9ef2e2cf
JR
3524
3525static struct scroll_bar *
b56ceb92 3526x_window_to_scroll_bar (Window window_id)
ee78dc32 3527{
5b04e9f9 3528 Lisp_Object tail, frame;
ee78dc32 3529
5b04e9f9 3530 FOR_EACH_FRAME (tail, frame)
ee78dc32 3531 {
5b04e9f9 3532 Lisp_Object bar, condemned;
ee78dc32
GV
3533
3534 /* Scan this frame's scroll bar list for a scroll bar with the
3535 right window ID. */
3536 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
3537 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
3538 /* This trick allows us to search both the ordinary and
3539 condemned scroll bar lists with one loop. */
8e50cc2d 3540 ! NILP (bar) || (bar = condemned,
ee78dc32 3541 condemned = Qnil,
8e50cc2d 3542 ! NILP (bar));
ee78dc32 3543 bar = XSCROLL_BAR (bar)->next)
fbd6baed 3544 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
ee78dc32
GV
3545 return XSCROLL_BAR (bar);
3546 }
3547
3548 return 0;
3549}
3550
791f420f
JR
3551
3552\f
3553/* Set the thumb size and position of scroll bar BAR. We are currently
3554 displaying PORTION out of a whole WHOLE, and our position POSITION. */
3555
3556static void
b56ceb92
JB
3557w32_set_scroll_bar_thumb (struct scroll_bar *bar,
3558 int portion, int position, int whole)
791f420f
JR
3559{
3560 Window w = SCROLL_BAR_W32_WINDOW (bar);
feade168
KS
3561 /* We use the whole scroll-bar height in the calculations below, to
3562 avoid strange effects like scrolling backwards when just clicking
3563 on the handle (without moving it). */
3564 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
3565 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
791f420f
JR
3566 int sb_page, sb_pos;
3567 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
818a1a5d 3568 SCROLLINFO si;
791f420f 3569
feade168
KS
3570 /* We used to change the nPage setting while dragging the handle,
3571 but that had very strange effects (such as scrolling backwards
3572 while dragging downwards).
3573
3574 Now, we don't change the nPage setting while dragging unless we
3575 get near to the end of the buffer, in which case we often have to
3576 resize the handle to "go all the way". */
3577
3578 if (draggingp)
791f420f 3579 {
feade168 3580 int near_bottom_p;
4d7e6e51 3581 block_input ();
feade168
KS
3582 si.cbSize = sizeof (si);
3583 si.fMask = SIF_POS | SIF_PAGE;
ed3751c8 3584 GetScrollInfo (w, SB_CTL, &si);
feade168 3585 near_bottom_p = si.nPos + si.nPage >= range;
4d7e6e51 3586 unblock_input ();
feade168
KS
3587 if (!near_bottom_p)
3588 return;
3589 }
f65aa365 3590
791f420f
JR
3591 if (whole)
3592 {
3593 /* Position scroll bar at rock bottom if the bottom of the
9858f6c3 3594 buffer is visible. This avoids shrinking the thumb away
791f420f 3595 to nothing if it is held at the bottom of the buffer. */
feade168
KS
3596 if (position + portion >= whole && !draggingp)
3597 {
3598 sb_page = range * (whole - position) / whole;
3599 sb_pos = range;
3600 }
3601 else
3602 {
3603 sb_pos = position * range / whole;
3604 sb_page = (min (portion, (whole - position)) * range) / whole;
3605 }
791f420f
JR
3606 }
3607 else
3608 {
3609 sb_page = range;
3610 sb_pos = 0;
3611 }
3612
feade168
KS
3613 sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
3614
4d7e6e51 3615 block_input ();
791f420f 3616
818a1a5d 3617 si.cbSize = sizeof (si);
feade168 3618 si.fMask = SIF_PAGE | SIF_POS;
818a1a5d
JR
3619 si.nPage = sb_page;
3620 si.nPos = sb_pos;
3621
feade168 3622 SetScrollInfo (w, SB_CTL, &si, TRUE);
791f420f 3623
4d7e6e51 3624 unblock_input ();
791f420f
JR
3625}
3626
3627\f
3628/************************************************************************
3629 Scroll bars, general
3630 ************************************************************************/
d67d1627 3631
decb374a 3632static HWND
b56ceb92 3633my_create_scrollbar (struct frame * f, struct scroll_bar * bar)
ee78dc32 3634{
689004fa 3635 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
d67d1627 3636 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
689004fa 3637 (LPARAM) bar);
ee78dc32
GV
3638}
3639
ab76d376 3640/*#define ATTACH_THREADS*/
52cf03a1 3641
14d050df 3642static BOOL
a10c8269 3643my_show_window (struct frame *f, HWND hwnd, int how)
52cf03a1
GV
3644{
3645#ifndef ATTACH_THREADS
689004fa
GV
3646 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
3647 (WPARAM) hwnd, (LPARAM) how);
52cf03a1 3648#else
689004fa 3649 return ShowWindow (hwnd, how);
52cf03a1
GV
3650#endif
3651}
3652
14d050df 3653static void
52cf03a1 3654my_set_window_pos (HWND hwnd, HWND hwndAfter,
689004fa 3655 int x, int y, int cx, int cy, UINT flags)
52cf03a1
GV
3656{
3657#ifndef ATTACH_THREADS
689004fa
GV
3658 WINDOWPOS pos;
3659 pos.hwndInsertAfter = hwndAfter;
52cf03a1
GV
3660 pos.x = x;
3661 pos.y = y;
3662 pos.cx = cx;
3663 pos.cy = cy;
3664 pos.flags = flags;
3665 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
3666#else
3667 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
3668#endif
3669}
3670
2e6c8532 3671#if 0
14d050df 3672static void
b56ceb92 3673my_set_focus (struct frame * f, HWND hwnd)
689004fa 3674{
d67d1627 3675 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
689004fa
GV
3676 (WPARAM) hwnd, 0);
3677}
2e6c8532 3678#endif
689004fa 3679
14d050df 3680static void
b56ceb92 3681my_set_foreground_window (HWND hwnd)
ef0e360f
GV
3682{
3683 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
3684}
3685
14d050df
JB
3686
3687static void
b56ceb92 3688my_destroy_window (struct frame * f, HWND hwnd)
ee78dc32 3689{
d67d1627 3690 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
ee78dc32
GV
3691 (WPARAM) hwnd, 0);
3692}
3693
85d0efd1
EZ
3694static void
3695my_bring_window_to_top (HWND hwnd)
3696{
3697 SendMessage (hwnd, WM_EMACS_BRINGTOTOP, (WPARAM) hwnd, 0);
3698}
3699
791f420f
JR
3700/* Create a scroll bar and return the scroll bar vector for it. W is
3701 the Emacs window on which to create the scroll bar. TOP, LEFT,
e8500ff4 3702 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
791f420f
JR
3703 scroll bar. */
3704
ee78dc32 3705static struct scroll_bar *
b56ceb92 3706x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
ee78dc32 3707{
791f420f
JR
3708 struct frame *f = XFRAME (WINDOW_FRAME (w));
3709 HWND hwnd;
818a1a5d 3710 SCROLLINFO si;
ee78dc32 3711 struct scroll_bar *bar
2fa611b7 3712 = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, fringe_extended_p, PVEC_OTHER);
71688bd7 3713 Lisp_Object barobj;
ee78dc32 3714
4d7e6e51 3715 block_input ();
ee78dc32 3716
791f420f 3717 XSETWINDOW (bar->window, w);
ee78dc32
GV
3718 XSETINT (bar->top, top);
3719 XSETINT (bar->left, left);
3720 XSETINT (bar->width, width);
3721 XSETINT (bar->height, height);
3722 XSETINT (bar->start, 0);
3723 XSETINT (bar->end, 0);
3724 bar->dragging = Qnil;
c8ae93b0 3725 bar->fringe_extended_p = 0;
ee78dc32
GV
3726
3727 /* Requires geometry to be set before call to create the real window */
3728
3729 hwnd = my_create_scrollbar (f, bar);
3730
818a1a5d
JR
3731 si.cbSize = sizeof (si);
3732 si.fMask = SIF_ALL;
3733 si.nMin = 0;
3734 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3735 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3736 si.nPage = si.nMax;
3737 si.nPos = 0;
689004fa 3738
818a1a5d 3739 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
ee78dc32 3740
fbd6baed 3741 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
ee78dc32
GV
3742
3743 /* Add bar to its frame's list of scroll bars. */
3744 bar->next = FRAME_SCROLL_BARS (f);
3745 bar->prev = Qnil;
71688bd7 3746 XSETVECTOR (barobj, bar);
f00af5b1 3747 fset_scroll_bars (f, barobj);
ee78dc32
GV
3748 if (! NILP (bar->next))
3749 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3750
4d7e6e51 3751 unblock_input ();
ee78dc32
GV
3752
3753 return bar;
3754}
3755
ee78dc32 3756
791f420f
JR
3757/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3758 nil. */
ee78dc32 3759
ee78dc32 3760static void
b56ceb92 3761x_scroll_bar_remove (struct scroll_bar *bar)
ee78dc32 3762{
a10c8269 3763 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
ee78dc32 3764
4d7e6e51 3765 block_input ();
ee78dc32
GV
3766
3767 /* Destroy the window. */
fbd6baed 3768 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
ee78dc32 3769
99d99081 3770 /* Dissociate this scroll bar from its window. */
e8c17b81 3771 wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
ee78dc32 3772
4d7e6e51 3773 unblock_input ();
ee78dc32
GV
3774}
3775
3776/* Set the handle of the vertical scroll bar for WINDOW to indicate
3777 that we are displaying PORTION characters out of a total of WHOLE
3778 characters, starting at POSITION. If WINDOW has no scroll bar,
3779 create one. */
3780static void
b56ceb92
JB
3781w32_set_vertical_scroll_bar (struct window *w,
3782 int portion, int whole, int position)
ee78dc32 3783{
d3d50620 3784 struct frame *f = XFRAME (w->frame);
dd86bd82 3785 Lisp_Object barobj;
ee78dc32 3786 struct scroll_bar *bar;
9ef2e2cf 3787 int top, height, left, sb_left, width, sb_width;
62e50ec6 3788 int window_y, window_height;
c8ae93b0 3789 bool fringe_extended_p;
791f420f
JR
3790
3791 /* Get window dimensions. */
c3c4768d 3792 window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
791f420f 3793 top = window_y;
62e50ec6 3794 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
791f420f
JR
3795 height = window_height;
3796
3797 /* Compute the left edge of the scroll bar area. */
62e50ec6 3798 left = WINDOW_SCROLL_BAR_AREA_X (w);
791f420f
JR
3799
3800 /* Compute the width of the scroll bar which might be less than
3801 the width of the area reserved for the scroll bar. */
62e50ec6
KS
3802 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3803 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
791f420f
JR
3804 else
3805 sb_width = width;
ee78dc32 3806
791f420f 3807 /* Compute the left edge of the scroll bar. */
62e50ec6 3808 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
06929222 3809 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
ee78dc32 3810 else
06929222
YM
3811 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
3812
c8ae93b0 3813 fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
791f420f
JR
3814
3815 /* Does the scroll bar exist yet? */
d3d50620 3816 if (NILP (w->vertical_scroll_bar))
ee78dc32 3817 {
00fe468b 3818 HDC hdc;
4d7e6e51 3819 block_input ();
6ff3e5e3 3820 if (width > 0 && height > 0)
9f5a911b
JR
3821 {
3822 hdc = get_frame_dc (f);
06929222
YM
3823 if (fringe_extended_p)
3824 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3825 else
3826 w32_clear_area (f, hdc, left, top, width, height);
9f5a911b
JR
3827 release_frame_dc (f, hdc);
3828 }
4d7e6e51 3829 unblock_input ();
00fe468b 3830
791f420f 3831 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
ee78dc32 3832 }
791f420f
JR
3833 else
3834 {
d67d1627 3835 /* It may just need to be moved and resized. */
791f420f
JR
3836 HWND hwnd;
3837
d3d50620 3838 bar = XSCROLL_BAR (w->vertical_scroll_bar);
791f420f
JR
3839 hwnd = SCROLL_BAR_W32_WINDOW (bar);
3840
3841 /* If already correctly positioned, do nothing. */
c8ae93b0
DA
3842 if (XINT (bar->left) == sb_left
3843 && XINT (bar->top) == top
3844 && XINT (bar->width) == sb_width
3845 && XINT (bar->height) == height
3846 && bar->fringe_extended_p == fringe_extended_p)
791f420f
JR
3847 {
3848 /* Redraw after clear_frame. */
3849 if (!my_show_window (f, hwnd, SW_NORMAL))
3850 InvalidateRect (hwnd, NULL, FALSE);
3851 }
3852 else
3853 {
00fe468b 3854 HDC hdc;
818a1a5d
JR
3855 SCROLLINFO si;
3856
4d7e6e51 3857 block_input ();
9f5a911b
JR
3858 if (width && height)
3859 {
3860 hdc = get_frame_dc (f);
3861 /* Since Windows scroll bars are smaller than the space reserved
3862 for them on the frame, we have to clear "under" them. */
06929222
YM
3863 if (fringe_extended_p)
3864 w32_clear_area (f, hdc, sb_left, top, sb_width, height);
3865 else
3866 w32_clear_area (f, hdc, left, top, width, height);
9f5a911b
JR
3867 release_frame_dc (f, hdc);
3868 }
791f420f
JR
3869 /* Make sure scroll bar is "visible" before moving, to ensure the
3870 area of the parent window now exposed will be refreshed. */
3871 my_show_window (f, hwnd, SW_HIDE);
9f5a911b
JR
3872 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
3873 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
3874 max (height, 1), TRUE);
ee78dc32 3875
818a1a5d
JR
3876 si.cbSize = sizeof (si);
3877 si.fMask = SIF_RANGE;
3878 si.nMin = 0;
3879 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
3880 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
3881
3882 SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
ee78dc32 3883
791f420f 3884 my_show_window (f, hwnd, SW_NORMAL);
ab76d376 3885 /* InvalidateRect (w, NULL, FALSE); */
791f420f
JR
3886
3887 /* Remember new settings. */
3888 XSETINT (bar->left, sb_left);
3889 XSETINT (bar->top, top);
3890 XSETINT (bar->width, sb_width);
3891 XSETINT (bar->height, height);
3892
4d7e6e51 3893 unblock_input ();
791f420f
JR
3894 }
3895 }
c8ae93b0 3896 bar->fringe_extended_p = fringe_extended_p;
06929222 3897
791f420f 3898 w32_set_scroll_bar_thumb (bar, portion, position, whole);
dd86bd82 3899 XSETVECTOR (barobj, bar);
e8c17b81 3900 wset_vertical_scroll_bar (w, barobj);
ee78dc32
GV
3901}
3902
3903
3904/* The following three hooks are used when we're doing a thorough
3905 redisplay of the frame. We don't explicitly know which scroll bars
3906 are going to be deleted, because keeping track of when windows go
3907 away is a real pain - "Can you say set-window-configuration, boys
3908 and girls?" Instead, we just assert at the beginning of redisplay
3909 that *all* scroll bars are to be removed, and then save a scroll bar
3910 from the fiery pit when we actually redisplay its window. */
3911
3912/* Arrange for all scroll bars on FRAME to be removed at the next call
3913 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9ef2e2cf
JR
3914 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
3915
ee78dc32 3916static void
a10c8269 3917w32_condemn_scroll_bars (struct frame *frame)
ee78dc32 3918{
ef0e360f
GV
3919 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3920 while (! NILP (FRAME_SCROLL_BARS (frame)))
3921 {
3922 Lisp_Object bar;
3923 bar = FRAME_SCROLL_BARS (frame);
f00af5b1 3924 fset_scroll_bars (frame, XSCROLL_BAR (bar)->next);
ef0e360f
GV
3925 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
3926 XSCROLL_BAR (bar)->prev = Qnil;
3927 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
3928 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
f00af5b1 3929 fset_condemned_scroll_bars (frame, bar);
ef0e360f 3930 }
ee78dc32
GV
3931}
3932
c2cc16fa 3933
9ef2e2cf 3934/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
ee78dc32 3935 Note that WINDOW isn't necessarily condemned at all. */
c2cc16fa 3936
ee78dc32 3937static void
b56ceb92 3938w32_redeem_scroll_bar (struct window *window)
ee78dc32
GV
3939{
3940 struct scroll_bar *bar;
71688bd7 3941 Lisp_Object barobj;
c2cc16fa 3942 struct frame *f;
ee78dc32
GV
3943
3944 /* We can't redeem this window's scroll bar if it doesn't have one. */
d3d50620 3945 if (NILP (window->vertical_scroll_bar))
1088b922 3946 emacs_abort ();
ee78dc32 3947
d3d50620 3948 bar = XSCROLL_BAR (window->vertical_scroll_bar);
ee78dc32 3949
ef0e360f 3950 /* Unlink it from the condemned list. */
c2cc16fa
JR
3951 f = XFRAME (WINDOW_FRAME (window));
3952 if (NILP (bar->prev))
3953 {
3954 /* If the prev pointer is nil, it must be the first in one of
3955 the lists. */
d3d50620 3956 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
c2cc16fa
JR
3957 /* It's not condemned. Everything's fine. */
3958 return;
3959 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
d3d50620 3960 window->vertical_scroll_bar))
f00af5b1 3961 fset_condemned_scroll_bars (f, bar->next);
c2cc16fa
JR
3962 else
3963 /* If its prev pointer is nil, it must be at the front of
3964 one or the other! */
1088b922 3965 emacs_abort ();
c2cc16fa
JR
3966 }
3967 else
3968 XSCROLL_BAR (bar->prev)->next = bar->next;
ef0e360f 3969
c2cc16fa
JR
3970 if (! NILP (bar->next))
3971 XSCROLL_BAR (bar->next)->prev = bar->prev;
ef0e360f 3972
c2cc16fa
JR
3973 bar->next = FRAME_SCROLL_BARS (f);
3974 bar->prev = Qnil;
71688bd7 3975 XSETVECTOR (barobj, bar);
f00af5b1 3976 fset_scroll_bars (f, barobj);
c2cc16fa
JR
3977 if (! NILP (bar->next))
3978 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
ee78dc32
GV
3979}
3980
3981/* Remove all scroll bars on FRAME that haven't been saved since the
3982 last call to `*condemn_scroll_bars_hook'. */
9ef2e2cf 3983
ee78dc32 3984static void
a10c8269 3985w32_judge_scroll_bars (struct frame *f)
ee78dc32
GV
3986{
3987 Lisp_Object bar, next;
3988
3989 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
3990
3991 /* Clear out the condemned list now so we won't try to process any
3992 more events on the hapless scroll bars. */
f00af5b1 3993 fset_condemned_scroll_bars (f, Qnil);
ee78dc32
GV
3994
3995 for (; ! NILP (bar); bar = next)
3996 {
3997 struct scroll_bar *b = XSCROLL_BAR (bar);
3998
3999 x_scroll_bar_remove (b);
4000
4001 next = b->next;
4002 b->next = b->prev = Qnil;
4003 }
4004
4005 /* Now there should be no references to the condemned scroll bars,
4006 and they should get garbage-collected. */
4007}
4008
4009/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 4010 is set to something other than NO_EVENT, it is enqueued.
ee78dc32
GV
4011
4012 This may be called from a signal handler, so we have to ignore GC
4013 mark bits. */
2c28562d 4014
52cf03a1 4015static int
b56ceb92
JB
4016w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
4017 struct input_event *emacs_event)
ee78dc32 4018{
8e50cc2d 4019 if (! WINDOWP (bar->window))
1088b922 4020 emacs_abort ();
ee78dc32 4021
4b219faa 4022 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
ee78dc32 4023 emacs_event->code = 0;
52cf03a1
GV
4024 /* not really meaningful to distinguish up/down */
4025 emacs_event->modifiers = msg->dwModifiers;
ee78dc32 4026 emacs_event->frame_or_window = bar->window;
7e889510 4027 emacs_event->arg = Qnil;
ee78dc32
GV
4028 emacs_event->timestamp = msg->msg.time;
4029
4030 {
791f420f 4031 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
689004fa
GV
4032 int y;
4033 int dragging = !NILP (bar->dragging);
818a1a5d 4034 SCROLLINFO si;
689004fa 4035
818a1a5d
JR
4036 si.cbSize = sizeof (si);
4037 si.fMask = SIF_POS;
689004fa 4038
818a1a5d
JR
4039 GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
4040 y = si.nPos;
689004fa
GV
4041
4042 bar->dragging = Qnil;
ee78dc32 4043
9ef2e2cf
JR
4044
4045 last_mouse_scroll_bar_pos = msg->msg.wParam;
d67d1627 4046
ee78dc32 4047 switch (LOWORD (msg->msg.wParam))
2c28562d 4048 {
2c28562d 4049 case SB_LINEDOWN:
52cf03a1 4050 emacs_event->part = scroll_bar_down_arrow;
ee78dc32 4051 break;
2c28562d 4052 case SB_LINEUP:
52cf03a1 4053 emacs_event->part = scroll_bar_up_arrow;
ee78dc32 4054 break;
2c28562d 4055 case SB_PAGEUP:
ee78dc32
GV
4056 emacs_event->part = scroll_bar_above_handle;
4057 break;
2c28562d 4058 case SB_PAGEDOWN:
ee78dc32
GV
4059 emacs_event->part = scroll_bar_below_handle;
4060 break;
2c28562d 4061 case SB_TOP:
ee78dc32
GV
4062 emacs_event->part = scroll_bar_handle;
4063 y = 0;
4064 break;
2c28562d 4065 case SB_BOTTOM:
ee78dc32
GV
4066 emacs_event->part = scroll_bar_handle;
4067 y = top_range;
4068 break;
689004fa 4069 case SB_THUMBTRACK:
2c28562d 4070 case SB_THUMBPOSITION:
791f420f
JR
4071 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
4072 y = HIWORD (msg->msg.wParam);
689004fa 4073 bar->dragging = Qt;
ee78dc32 4074 emacs_event->part = scroll_bar_handle;
689004fa
GV
4075
4076 /* "Silently" update current position. */
818a1a5d
JR
4077 {
4078 SCROLLINFO si;
689004fa 4079
818a1a5d
JR
4080 si.cbSize = sizeof (si);
4081 si.fMask = SIF_POS;
4082 si.nPos = y;
4083 /* Remember apparent position (we actually lag behind the real
e8500ff4 4084 position, so don't set that directly). */
818a1a5d 4085 last_scroll_bar_drag_pos = y;
689004fa 4086
818a1a5d
JR
4087 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
4088 }
ee78dc32 4089 break;
2c28562d 4090 case SB_ENDSCROLL:
689004fa
GV
4091 /* If this is the end of a drag sequence, then reset the scroll
4092 handle size to normal and do a final redraw. Otherwise do
4093 nothing. */
4094 if (dragging)
4095 {
818a1a5d
JR
4096 SCROLLINFO si;
4097 int start = XINT (bar->start);
4098 int end = XINT (bar->end);
4099
4100 si.cbSize = sizeof (si);
4101 si.fMask = SIF_PAGE | SIF_POS;
4102 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
4103 si.nPos = last_scroll_bar_drag_pos;
4104 SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
689004fa
GV
4105 }
4106 /* fall through */
2c28562d 4107 default:
3b8f9651 4108 emacs_event->kind = NO_EVENT;
52cf03a1 4109 return FALSE;
2c28562d 4110 }
52cf03a1 4111
ee78dc32
GV
4112 XSETINT (emacs_event->x, y);
4113 XSETINT (emacs_event->y, top_range);
52cf03a1
GV
4114
4115 return TRUE;
ee78dc32
GV
4116 }
4117}
4118
4119/* Return information to the user about the current position of the mouse
4120 on the scroll bar. */
9ef2e2cf 4121
ee78dc32 4122static void
a10c8269 4123x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
b56ceb92
JB
4124 enum scroll_bar_part *part,
4125 Lisp_Object *x, Lisp_Object *y,
4126 unsigned long *time)
ee78dc32
GV
4127{
4128 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
fbd6baed 4129 Window w = SCROLL_BAR_W32_WINDOW (bar);
a10c8269 4130 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
ee78dc32 4131 int pos;
791f420f 4132 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
818a1a5d 4133 SCROLLINFO si;
ee78dc32 4134
4d7e6e51 4135 block_input ();
ee78dc32
GV
4136
4137 *fp = f;
4138 *bar_window = bar->window;
4139
818a1a5d
JR
4140 si.cbSize = sizeof (si);
4141 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
689004fa 4142
818a1a5d
JR
4143 GetScrollInfo (w, SB_CTL, &si);
4144 pos = si.nPos;
4145 top_range = si.nMax - si.nPage + 1;
ee78dc32
GV
4146
4147 switch (LOWORD (last_mouse_scroll_bar_pos))
4148 {
4149 case SB_THUMBPOSITION:
4150 case SB_THUMBTRACK:
4151 *part = scroll_bar_handle;
791f420f 4152 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
ee78dc32
GV
4153 pos = HIWORD (last_mouse_scroll_bar_pos);
4154 break;
4155 case SB_LINEDOWN:
4156 *part = scroll_bar_handle;
4157 pos++;
4158 break;
4159 default:
4160 *part = scroll_bar_handle;
4161 break;
4162 }
4163
9127e20e
JR
4164 XSETINT (*x, pos);
4165 XSETINT (*y, top_range);
ee78dc32
GV
4166
4167 f->mouse_moved = 0;
4168 last_mouse_scroll_bar = Qnil;
4169
4170 *time = last_mouse_movement_time;
4171
4d7e6e51 4172 unblock_input ();
ee78dc32
GV
4173}
4174
9ef2e2cf 4175
ee78dc32
GV
4176/* The screen has been cleared so we may have changed foreground or
4177 background colors, and the scroll bars may need to be redrawn.
4178 Clear out the scroll bars, and ask for expose events, so we can
4179 redraw them. */
9ef2e2cf 4180
791f420f 4181void
a10c8269 4182x_scroll_bar_clear (struct frame *f)
ee78dc32 4183{
ee78dc32
GV
4184 Lisp_Object bar;
4185
9ef2e2cf
JR
4186 /* We can have scroll bars even if this is 0,
4187 if we just turned off scroll bar mode.
4188 But in that case we should not clear them. */
4189 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4190 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4191 bar = XSCROLL_BAR (bar)->next)
4192 {
4193 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
4194 HDC hdc = GetDC (window);
4195 RECT rect;
52cf03a1 4196
9ef2e2cf
JR
4197 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
4198 arranges to refresh the scroll bar if hidden. */
4199 my_show_window (f, window, SW_HIDE);
689004fa 4200
9ef2e2cf
JR
4201 GetClientRect (window, &rect);
4202 select_palette (f, hdc);
4203 w32_clear_rect (f, hdc, &rect);
4204 deselect_palette (f, hdc);
689004fa 4205
9ef2e2cf
JR
4206 ReleaseDC (window, hdc);
4207 }
52cf03a1
GV
4208}
4209
ee78dc32 4210\f
fbd6baed 4211/* The main W32 event-reading loop - w32_read_socket. */
ee78dc32
GV
4212
4213/* Record the last 100 characters stored
4214 to help debug the loss-of-chars-during-GC problem. */
9ef2e2cf
JR
4215
4216static int temp_index;
4217static short temp_buffer[100];
ee78dc32 4218
2e3566d8
JR
4219/* Temporarily store lead byte of DBCS input sequences. */
4220static char dbcs_lead = 0;
afd153f0 4221
fbd6baed 4222/* Read events coming from the W32 shell.
ee78dc32
GV
4223 This routine is called by the SIGIO handler.
4224 We return as soon as there are no more events to be read.
4225
d263a633
EZ
4226 For an overview of how Emacs input works on MS-Windows, see the
4227 commentary before w32_msg_pump in w32fns.c.
4228
ee78dc32
GV
4229 We return the number of characters stored into the buffer,
4230 thus pretending to be `read'.
4231
ee78dc32 4232 Some of these messages are reposted back to the message queue since the
d67d1627 4233 system calls the windows proc directly in a context where we cannot return
decb374a 4234 the data nor can we guarantee the state we are in. So if we dispatch them
ee78dc32
GV
4235 we will get into an infinite loop. To prevent this from ever happening we
4236 will set a variable to indicate we are in the read_socket call and indicate
d67d1627 4237 which message we are processing since the windows proc gets called
e9e23e23 4238 recursively with different messages by the system.
ee78dc32
GV
4239*/
4240
24f981c9 4241static int
f75beb47 4242w32_read_socket (struct terminal *terminal,
b56ceb92 4243 struct input_event *hold_quit)
ee78dc32
GV
4244{
4245 int count = 0;
689004fa 4246 int check_visibility = 0;
fbd6baed 4247 W32Msg msg;
ee78dc32 4248 struct frame *f;
fbd6baed 4249 struct w32_display_info *dpyinfo = &one_w32_display_info;
bbf534ce 4250 Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
0fda9b75 4251 static char buf[1];
ee78dc32 4252
4d7e6e51 4253 block_input ();
ee78dc32
GV
4254
4255 /* So people can tell when we have read the available input. */
4256 input_signal_count++;
4257
0fda9b75
DC
4258 /* Process any incoming thread messages. */
4259 drain_message_queue ();
4260
07c07cfe 4261 /* TODO: ghostscript integration. */
52cf03a1 4262 while (get_next_msg (&msg, FALSE))
ee78dc32 4263 {
6b61353c
KH
4264 struct input_event inev;
4265 int do_help = 0;
4266
0fda9b75
DC
4267 /* DebPrint (("w32_read_socket: %s time:%u\n", */
4268 /* w32_name_of_message (msg.msg.message), */
4269 /* msg.msg.time)); */
4270
6b61353c
KH
4271 EVENT_INIT (inev);
4272 inev.kind = NO_EVENT;
4273 inev.arg = Qnil;
4274
ee78dc32
GV
4275 switch (msg.msg.message)
4276 {
f7b146dc 4277 case WM_EMACS_PAINT:
9f5a911b 4278 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
ee78dc32 4279
d67d1627 4280 if (f)
9f5a911b
JR
4281 {
4282 if (msg.rect.right == msg.rect.left ||
4283 msg.rect.bottom == msg.rect.top)
4284 {
4285 /* We may get paint messages even though the client
4286 area is clipped - these are not expose events. */
4287 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
e69b0960 4288 SDATA (f->name)));
9f5a911b 4289 }
edfa7fa0 4290 else if (FRAME_VISIBLE_P (f) != 1)
9f5a911b 4291 {
edfa7fa0
DA
4292 bool iconified = FRAME_ICONIFIED_P (f);
4293
9f5a911b 4294 /* Definitely not obscured, so mark as visible. */
edfa7fa0
DA
4295 SET_FRAME_VISIBLE (f, 1);
4296 SET_FRAME_ICONIFIED (f, 0);
9f5a911b 4297 SET_FRAME_GARBAGED (f);
a8f93651
EZ
4298 if (!f->output_data.w32->asked_for_visible)
4299 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
4300 SDATA (f->name)));
9f5a911b
JR
4301
4302 /* WM_PAINT serves as MapNotify as well, so report
4303 visibility changes properly. */
edfa7fa0 4304 if (iconified)
9f5a911b 4305 {
6b61353c
KH
4306 inev.kind = DEICONIFY_EVENT;
4307 XSETFRAME (inev.frame_or_window, f);
9f5a911b 4308 }
edfa7fa0 4309 else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list)))
9f5a911b
JR
4310 /* Force a redisplay sooner or later to update the
4311 frame titles in case this is the second frame. */
4312 record_asynch_buffer_change ();
4313 }
4314 else
4315 {
4316 HDC hdc = get_frame_dc (f);
4317
4318 /* Erase background again for safety. */
4319 w32_clear_rect (f, hdc, &msg.rect);
4320 release_frame_dc (f, hdc);
4321 expose_frame (f,
4322 msg.rect.left,
4323 msg.rect.top,
4324 msg.rect.right - msg.rect.left,
4325 msg.rect.bottom - msg.rect.top);
4326 }
4327 }
52cf03a1 4328 break;
689004fa 4329
f98169a0
GV
4330 case WM_INPUTLANGCHANGE:
4331 /* Generate a language change event. */
4332 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4333
0bd8297f
EZ
4334 /* lParam contains the input language ID in its low 16 bits.
4335 Use it to update our record of the keyboard codepage. */
302fc036
EZ
4336 w32_keyboard_codepage = codepage_for_locale ((LCID)(msg.msg.lParam
4337 & 0xffff));
13087e59 4338
f98169a0
GV
4339 if (f)
4340 {
6b61353c
KH
4341 inev.kind = LANGUAGE_CHANGE_EVENT;
4342 XSETFRAME (inev.frame_or_window, f);
302fc036 4343 inev.code = w32_keyboard_codepage;
6b61353c 4344 inev.modifiers = msg.msg.lParam & 0xffff;
f98169a0
GV
4345 }
4346 break;
4347
ee78dc32
GV
4348 case WM_KEYDOWN:
4349 case WM_SYSKEYDOWN:
4350 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4351
edfa7fa0 4352 if (f && !FRAME_ICONIFIED_P (f))
ee78dc32 4353 {
bbf534ce 4354 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
e69b0960 4355 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
3d26a7c2 4356 {
bbf534ce
EZ
4357 clear_mouse_face (hlinfo);
4358 hlinfo->mouse_face_hidden = 1;
3d26a7c2
KS
4359 }
4360
ee78dc32
GV
4361 if (temp_index == sizeof temp_buffer / sizeof (short))
4362 temp_index = 0;
4363 temp_buffer[temp_index++] = msg.msg.wParam;
6b61353c
KH
4364 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
4365 inev.code = msg.msg.wParam;
4366 inev.modifiers = msg.dwModifiers;
4367 XSETFRAME (inev.frame_or_window, f);
4368 inev.timestamp = msg.msg.time;
ee78dc32
GV
4369 }
4370 break;
689004fa 4371
a60b0333 4372 case WM_UNICHAR:
ee78dc32
GV
4373 case WM_SYSCHAR:
4374 case WM_CHAR:
4375 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4376
edfa7fa0 4377 if (f && !FRAME_ICONIFIED_P (f))
ee78dc32 4378 {
bbf534ce 4379 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
e69b0960 4380 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
3d26a7c2 4381 {
bbf534ce
EZ
4382 clear_mouse_face (hlinfo);
4383 hlinfo->mouse_face_hidden = 1;
3d26a7c2
KS
4384 }
4385
f98169a0
GV
4386 if (temp_index == sizeof temp_buffer / sizeof (short))
4387 temp_index = 0;
4388 temp_buffer[temp_index++] = msg.msg.wParam;
480cb5d2
JR
4389
4390 inev.modifiers = msg.dwModifiers;
4391 XSETFRAME (inev.frame_or_window, f);
4392 inev.timestamp = msg.msg.time;
4393
a60b0333
JR
4394 if (msg.msg.message == WM_UNICHAR)
4395 {
a60b0333
JR
4396 inev.code = msg.msg.wParam;
4397 }
480cb5d2
JR
4398 else if (msg.msg.wParam < 256)
4399 {
4400 wchar_t code;
4401 char dbcs[2];
4402 dbcs[0] = 0;
4403 dbcs[1] = (char) msg.msg.wParam;
4404
4405 if (dbcs_lead)
4406 {
4407 dbcs[0] = dbcs_lead;
4408 dbcs_lead = 0;
302fc036 4409 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
13087e59 4410 dbcs, 2, &code, 1))
480cb5d2
JR
4411 {
4412 /* Garbage */
4413 DebPrint (("Invalid DBCS sequence: %d %d\n",
4414 dbcs[0], dbcs[1]));
4415 inev.kind = NO_EVENT;
4416 break;
4417 }
4418 }
302fc036 4419 else if (IsDBCSLeadByteEx (w32_keyboard_codepage,
13087e59 4420 (BYTE) msg.msg.wParam))
480cb5d2
JR
4421 {
4422 dbcs_lead = (char) msg.msg.wParam;
4423 inev.kind = NO_EVENT;
4424 break;
4425 }
4426 else
4427 {
302fc036 4428 if (!MultiByteToWideChar (w32_keyboard_codepage, 0,
13087e59 4429 &dbcs[1], 1, &code, 1))
480cb5d2
JR
4430 {
4431 /* What to do with garbage? */
4432 DebPrint (("Invalid character: %d\n", dbcs[1]));
4433 inev.kind = NO_EVENT;
4434 break;
4435 }
4436 }
4437 inev.code = code;
4438 }
a60b0333
JR
4439 else
4440 {
480cb5d2
JR
4441 /* Windows shouldn't generate WM_CHAR events above 0xFF
4442 in non-Unicode message handlers. */
4443 DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
4444 inev.kind = NO_EVENT;
4445 break;
a60b0333 4446 }
480cb5d2
JR
4447 inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
4448 : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
ee78dc32
GV
4449 }
4450 break;
689004fa 4451
4b219faa
JR
4452 case WM_APPCOMMAND:
4453 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4454
edfa7fa0 4455 if (f && !FRAME_ICONIFIED_P (f))
4b219faa 4456 {
bbf534ce 4457 if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
e69b0960 4458 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
4b219faa 4459 {
bbf534ce
EZ
4460 clear_mouse_face (hlinfo);
4461 hlinfo->mouse_face_hidden = 1;
4b219faa
JR
4462 }
4463
4464 if (temp_index == sizeof temp_buffer / sizeof (short))
4465 temp_index = 0;
4466 temp_buffer[temp_index++] = msg.msg.wParam;
4467 inev.kind = MULTIMEDIA_KEY_EVENT;
ed3751c8 4468 inev.code = GET_APPCOMMAND_LPARAM (msg.msg.lParam);
4b219faa
JR
4469 inev.modifiers = msg.dwModifiers;
4470 XSETFRAME (inev.frame_or_window, f);
4471 inev.timestamp = msg.msg.time;
4472 }
4473 break;
65a6ff8f 4474
ee78dc32 4475 case WM_MOUSEMOVE:
706ddb8f
JR
4476 /* Ignore non-movement. */
4477 {
4478 int x = LOWORD (msg.msg.lParam);
4479 int y = HIWORD (msg.msg.lParam);
4480 if (x == last_mousemove_x && y == last_mousemove_y)
4481 break;
4482 last_mousemove_x = x;
4483 last_mousemove_y = y;
4484 }
4485
89271099 4486 previous_help_echo_string = help_echo_string;
fc5c7550 4487 help_echo_string = Qnil;
791f420f 4488
ee78dc32
GV
4489 if (dpyinfo->grabbed && last_mouse_frame
4490 && FRAME_LIVE_P (last_mouse_frame))
4491 f = last_mouse_frame;
4492 else
4493 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4494
bbf534ce 4495 if (hlinfo->mouse_face_hidden)
3d26a7c2 4496 {
bbf534ce
EZ
4497 hlinfo->mouse_face_hidden = 0;
4498 clear_mouse_face (hlinfo);
3d26a7c2
KS
4499 }
4500
ee78dc32 4501 if (f)
a18bb28d
JR
4502 {
4503 /* Generate SELECT_WINDOW_EVENTs when needed. */
92b23323 4504 if (!NILP (Vmouse_autoselect_window))
a18bb28d
JR
4505 {
4506 Lisp_Object window;
a18bb28d
JR
4507 int x = LOWORD (msg.msg.lParam);
4508 int y = HIWORD (msg.msg.lParam);
4509
9173a8fb 4510 window = window_from_coordinates (f, x, y, 0, 0);
a18bb28d
JR
4511
4512 /* Window will be selected only when it is not
4513 selected now and last mouse movement event was
4514 not in it. Minibuffer window will be selected
e0f24100 4515 only when it is active. */
ed3751c8 4516 if (WINDOWP (window)
a18bb28d 4517 && !EQ (window, last_window)
74a9b36f
MR
4518 && !EQ (window, selected_window)
4519 /* For click-to-focus window managers
4520 create event iff we don't leave the
4521 selected frame. */
4522 && (focus_follows_mouse
d3d50620
DA
4523 || (EQ (XWINDOW (window)->frame,
4524 XWINDOW (selected_window)->frame))))
a18bb28d 4525 {
6b61353c
KH
4526 inev.kind = SELECT_WINDOW_EVENT;
4527 inev.frame_or_window = window;
a18bb28d
JR
4528 }
4529
9d4f32e8 4530 last_window = window;
a18bb28d 4531 }
fc5c7550
YM
4532 if (!note_mouse_movement (f, &msg.msg))
4533 help_echo_string = previous_help_echo_string;
a18bb28d 4534 }
ee78dc32 4535 else
791f420f
JR
4536 {
4537 /* If we move outside the frame, then we're
4538 certainly no longer on any text in the frame. */
bbf534ce 4539 clear_mouse_face (hlinfo);
791f420f
JR
4540 }
4541
89271099 4542 /* If the contents of the global variable help_echo_string
791f420f 4543 has changed, generate a HELP_EVENT. */
646b5f55 4544#if 0 /* The below is an invalid comparison when CHECK_LISP_OBJECT_TYPE.
e597eb7d
JR
4545 But it was originally changed to this to fix a bug, so I have
4546 not removed it completely in case the bug is still there. */
89271099
KS
4547 if (help_echo_string != previous_help_echo_string ||
4548 (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
e597eb7d
JR
4549#else /* This is what xterm.c does. */
4550 if (!NILP (help_echo_string)
4551 || !NILP (previous_help_echo_string))
6b61353c 4552 do_help = 1;
e597eb7d 4553#endif
791f420f 4554 break;
689004fa 4555
ee78dc32
GV
4556 case WM_LBUTTONDOWN:
4557 case WM_LBUTTONUP:
4558 case WM_MBUTTONDOWN:
4559 case WM_MBUTTONUP:
4560 case WM_RBUTTONDOWN:
4561 case WM_RBUTTONUP:
53823ab9
JR
4562 case WM_XBUTTONDOWN:
4563 case WM_XBUTTONUP:
ee78dc32 4564 {
791f420f
JR
4565 /* If we decide we want to generate an event to be seen
4566 by the rest of Emacs, we put it here. */
d7e6881a 4567 bool tool_bar_p = 0;
ee78dc32
GV
4568 int button;
4569 int up;
791f420f 4570
ee78dc32
GV
4571 if (dpyinfo->grabbed && last_mouse_frame
4572 && FRAME_LIVE_P (last_mouse_frame))
4573 f = last_mouse_frame;
4574 else
4575 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4576
ee78dc32
GV
4577 if (f)
4578 {
6b61353c 4579 construct_mouse_click (&inev, &msg, f);
d67d1627 4580
791f420f 4581 /* Is this in the tool-bar? */
e69b0960
DA
4582 if (WINDOWP (f->tool_bar_window)
4583 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
791f420f
JR
4584 {
4585 Lisp_Object window;
6b61353c
KH
4586 int x = XFASTINT (inev.x);
4587 int y = XFASTINT (inev.y);
791f420f 4588
9173a8fb 4589 window = window_from_coordinates (f, x, y, 0, 1);
b8b47c19 4590
e69b0960 4591 if (EQ (window, f->tool_bar_window))
791f420f 4592 {
6b61353c 4593 w32_handle_tool_bar_click (f, &inev);
791f420f
JR
4594 tool_bar_p = 1;
4595 }
4596 }
4597
6b61353c
KH
4598 if (tool_bar_p
4599 || (dpyinfo->w32_focus_frame
4600 && f != dpyinfo->w32_focus_frame))
4601 inev.kind = NO_EVENT;
ee78dc32 4602 }
d67d1627 4603
53823ab9
JR
4604 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
4605 &button, &up);
4606
ee78dc32
GV
4607 if (up)
4608 {
4609 dpyinfo->grabbed &= ~ (1 << button);
4610 }
4611 else
4612 {
4613 dpyinfo->grabbed |= (1 << button);
4614 last_mouse_frame = f;
791f420f
JR
4615 /* Ignore any mouse motion that happened
4616 before this event; any subsequent mouse-movement
4617 Emacs events should reflect only motion after
4618 the ButtonPress. */
4619 if (f != 0)
4620 f->mouse_moved = 0;
4621
4622 if (!tool_bar_p)
4623 last_tool_bar_item = -1;
ee78dc32 4624 }
689004fa 4625 break;
ee78dc32 4626 }
d67d1627 4627
1c64a4a2 4628 case WM_MOUSEWHEEL:
1526bc23 4629 case WM_MOUSEHWHEEL:
1c64a4a2 4630 {
1c64a4a2
JB
4631 if (dpyinfo->grabbed && last_mouse_frame
4632 && FRAME_LIVE_P (last_mouse_frame))
4633 f = last_mouse_frame;
4634 else
4635 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4636
4637 if (f)
4638 {
1c64a4a2 4639
6b61353c
KH
4640 if (!dpyinfo->w32_focus_frame
4641 || f == dpyinfo->w32_focus_frame)
1c64a4a2 4642 {
637ad49d 4643 /* Emit an Emacs wheel-up/down event. */
6b61353c 4644 construct_mouse_wheel (&inev, &msg, f);
1c64a4a2 4645 }
637ad49d
JR
4646 /* Ignore any mouse motion that happened before this
4647 event; any subsequent mouse-movement Emacs events
4648 should reflect only motion after the
db9cd97a 4649 ButtonPress. */
637ad49d 4650 f->mouse_moved = 0;
1c64a4a2 4651 }
637ad49d
JR
4652 last_mouse_frame = f;
4653 last_tool_bar_item = -1;
1c64a4a2 4654 }
ee78dc32 4655 break;
689004fa 4656
12857dfd
RS
4657 case WM_DROPFILES:
4658 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4659
4660 if (f)
6b61353c 4661 construct_drag_n_drop (&inev, &msg, f);
12857dfd
RS
4662 break;
4663
ee78dc32
GV
4664 case WM_VSCROLL:
4665 {
689004fa
GV
4666 struct scroll_bar *bar =
4667 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
d67d1627 4668
6b61353c
KH
4669 if (bar)
4670 w32_scroll_bar_handle_click (bar, &msg, &inev);
689004fa 4671 break;
ee78dc32 4672 }
d67d1627 4673
689004fa
GV
4674 case WM_WINDOWPOSCHANGED:
4675 case WM_ACTIVATE:
4676 case WM_ACTIVATEAPP:
549808db
JR
4677 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4678 if (f)
c7ffccaf 4679 {
a5cc4dde
EZ
4680 /* Run the full-screen hook function also when we are
4681 being activated, to actually install the required
4682 size in effect, if the WAIT flag is set. This is
4683 because when the hook is run from x_set_fullscreen,
4684 the frame might not yet be visible, if that call is a
4685 result of make-frame, and in that case the hook just
4686 sets the WAIT flag. */
4687 if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam)
4688 && (f->want_fullscreen & FULLSCREEN_WAIT))
c7ffccaf
EZ
4689 w32fullscreen_hook (f);
4690 x_check_fullscreen (f);
4691 }
689004fa 4692 check_visibility = 1;
ee78dc32 4693 break;
689004fa 4694
ee78dc32
GV
4695 case WM_MOVE:
4696 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4697
edfa7fa0 4698 if (f && !FRAME_ICONIFIED_P (f))
ee78dc32 4699 {
689004fa
GV
4700 int x, y;
4701
4702 x_real_positions (f, &x, &y);
62e50ec6
KS
4703 f->left_pos = x;
4704 f->top_pos = y;
ee78dc32 4705 }
689004fa
GV
4706
4707 check_visibility = 1;
4708 break;
4709
4710 case WM_SHOWWINDOW:
b71b8111
JR
4711 /* wParam non-zero means Window is about to be shown, 0 means
4712 about to be hidden. */
4713 /* Redo the mouse-highlight after the tooltip has gone. */
4714 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
4715 {
4716 tip_window = NULL;
4717 redo_mouse_highlight ();
4718 }
4719
689004fa 4720 /* If window has been obscured or exposed by another window
53964682 4721 being maximized or minimized/restored, then recheck
689004fa
GV
4722 visibility of all frames. Direct changes to our own
4723 windows get handled by WM_SIZE. */
4724#if 0
4725 if (msg.msg.lParam != 0)
4726 check_visibility = 1;
4727 else
4728 {
4729 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4730 f->async_visible = msg.msg.wParam;
4731 }
4732#endif
4733
4734 check_visibility = 1;
ee78dc32 4735 break;
689004fa 4736
ee78dc32
GV
4737 case WM_SIZE:
4738 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4739
689004fa
GV
4740 /* Inform lisp of whether frame has been iconified etc. */
4741 if (f)
ee78dc32 4742 {
689004fa 4743 switch (msg.msg.wParam)
ee78dc32 4744 {
689004fa 4745 case SIZE_MINIMIZED:
edfa7fa0
DA
4746 SET_FRAME_VISIBLE (f, 0);
4747 SET_FRAME_ICONIFIED (f, 1);
d67d1627 4748
6b61353c
KH
4749 inev.kind = ICONIFY_EVENT;
4750 XSETFRAME (inev.frame_or_window, f);
689004fa
GV
4751 break;
4752
4753 case SIZE_MAXIMIZED:
4754 case SIZE_RESTORED:
edfa7fa0
DA
4755 {
4756 bool iconified = FRAME_ICONIFIED_P (f);
d67d1627 4757
a8f93651
EZ
4758 if (iconified)
4759 SET_FRAME_VISIBLE (f, 1);
edfa7fa0 4760 SET_FRAME_ICONIFIED (f, 0);
d67d1627 4761
edfa7fa0
DA
4762 /* wait_reading_process_output will notice this
4763 and update the frame's display structures. */
4764 SET_FRAME_GARBAGED (f);
31d4844a 4765
edfa7fa0
DA
4766 if (iconified)
4767 {
4768 int x, y;
4769
4770 /* Reset top and left positions of the Window
4771 here since Windows sends a WM_MOVE message
4772 BEFORE telling us the Window is minimized
4773 when the Window is iconified, with 3000,3000
4774 as the co-ords. */
4775 x_real_positions (f, &x, &y);
4776 f->left_pos = x;
4777 f->top_pos = y;
4778
4779 inev.kind = DEICONIFY_EVENT;
4780 XSETFRAME (inev.frame_or_window, f);
4781 }
4782 else if (! NILP (Vframe_list)
4783 && ! NILP (XCDR (Vframe_list)))
4784 /* Force a redisplay sooner or later
4785 to update the frame titles
4786 in case this is the second frame. */
4787 record_asynch_buffer_change ();
4788 }
689004fa 4789 break;
ee78dc32 4790 }
ee78dc32 4791 }
689004fa 4792
edfa7fa0 4793 if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED)
ef0e360f
GV
4794 {
4795 RECT rect;
4796 int rows;
4797 int columns;
4798 int width;
4799 int height;
d67d1627 4800
9127e20e 4801 GetClientRect (msg.msg.hwnd, &rect);
d67d1627 4802
ef0e360f
GV
4803 height = rect.bottom - rect.top;
4804 width = rect.right - rect.left;
d67d1627 4805
62e50ec6
KS
4806 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
4807 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
d67d1627 4808
ef0e360f 4809 /* TODO: Clip size to the screen dimensions. */
d67d1627 4810
ef0e360f
GV
4811 /* Even if the number of character rows and columns has
4812 not changed, the font size may have changed, so we need
4813 to check the pixel dimensions as well. */
d67d1627 4814
62e50ec6
KS
4815 if (columns != FRAME_COLS (f)
4816 || rows != FRAME_LINES (f)
4817 || width != FRAME_PIXEL_WIDTH (f)
4818 || height != FRAME_PIXEL_HEIGHT (f))
ef0e360f 4819 {
791f420f 4820 change_frame_size (f, rows, columns, 0, 1, 0);
ef0e360f 4821 SET_FRAME_GARBAGED (f);
31d4844a 4822 cancel_mouse_face (f);
62e50ec6
KS
4823 FRAME_PIXEL_WIDTH (f) = width;
4824 FRAME_PIXEL_HEIGHT (f) = height;
4825 f->win_gravity = NorthWestGravity;
ef0e360f
GV
4826 }
4827 }
4828
689004fa
GV
4829 check_visibility = 1;
4830 break;
4831
1576fbfa
JR
4832 case WM_MOUSELEAVE:
4833 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
4834 if (f)
4835 {
bbf534ce 4836 if (f == hlinfo->mouse_face_mouse_frame)
1576fbfa
JR
4837 {
4838 /* If we move outside the frame, then we're
4839 certainly no longer on any text in the frame. */
bbf534ce
EZ
4840 clear_mouse_face (hlinfo);
4841 hlinfo->mouse_face_mouse_frame = 0;
1576fbfa
JR
4842 }
4843
4844 /* Generate a nil HELP_EVENT to cancel a help-echo.
4845 Do it only if there's something to cancel.
4846 Otherwise, the startup message is cleared when
4847 the mouse leaves the frame. */
4848 if (any_help_event_p)
6b61353c 4849 do_help = -1;
1576fbfa
JR
4850 }
4851 break;
d67d1627 4852
689004fa 4853 case WM_SETFOCUS:
55131bef 4854 w32_detect_focus_change (dpyinfo, &msg, &inev);
791f420f 4855
791f420f
JR
4856 dpyinfo->grabbed = 0;
4857 check_visibility = 1;
4858 break;
4859
689004fa 4860 case WM_KILLFOCUS:
e95da6d3 4861 w32_detect_focus_change (dpyinfo, &msg, &inev);
791f420f 4862 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
08712a41 4863
791f420f
JR
4864 if (f)
4865 {
bbf534ce 4866 if (f == hlinfo->mouse_face_mouse_frame)
791f420f
JR
4867 {
4868 /* If we move outside the frame, then we're
4869 certainly no longer on any text in the frame. */
bbf534ce
EZ
4870 clear_mouse_face (hlinfo);
4871 hlinfo->mouse_face_mouse_frame = 0;
791f420f 4872 }
9ef2e2cf 4873
791f420f
JR
4874 /* Generate a nil HELP_EVENT to cancel a help-echo.
4875 Do it only if there's something to cancel.
4876 Otherwise, the startup message is cleared when
4877 the mouse leaves the frame. */
4878 if (any_help_event_p)
6b61353c 4879 do_help = -1;
791f420f 4880 }
689004fa 4881
08712a41 4882 dpyinfo->grabbed = 0;
689004fa 4883 check_visibility = 1;
ee78dc32 4884 break;
689004fa 4885
ee78dc32
GV
4886 case WM_CLOSE:
4887 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4888
ee78dc32
GV
4889 if (f)
4890 {
6b61353c
KH
4891 inev.kind = DELETE_WINDOW_EVENT;
4892 XSETFRAME (inev.frame_or_window, f);
ee78dc32 4893 }
689004fa
GV
4894 break;
4895
4896 case WM_INITMENU:
4897 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 4898
689004fa
GV
4899 if (f)
4900 {
6b61353c
KH
4901 inev.kind = MENU_BAR_ACTIVATE_EVENT;
4902 XSETFRAME (inev.frame_or_window, f);
689004fa 4903 }
ee78dc32 4904 break;
689004fa 4905
ee78dc32
GV
4906 case WM_COMMAND:
4907 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
014b6ea1 4908
ee78dc32
GV
4909 if (f)
4910 {
f98169a0 4911 extern void menubar_selection_callback
a10c8269 4912 (struct frame *f, void * client_data);
014b6ea1 4913 menubar_selection_callback (f, (void *)msg.msg.wParam);
ee78dc32 4914 }
689004fa
GV
4915
4916 check_visibility = 1;
4917 break;
4918
4919 case WM_DISPLAYCHANGE:
4920 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4921
d67d1627 4922 if (f)
689004fa 4923 {
689004fa 4924 dpyinfo->n_cbits = msg.msg.wParam;
b89c78a5
CY
4925 DebPrint (("display change: %d %d\n",
4926 (short) LOWORD (msg.msg.lParam),
4927 (short) HIWORD (msg.msg.lParam)));
689004fa 4928 }
d67d1627 4929
689004fa 4930 check_visibility = 1;
ee78dc32 4931 break;
e7efd97e 4932
7f203aa1 4933#if HAVE_W32NOTIFY
477f1e50
EZ
4934 case WM_EMACS_FILENOTIFY:
4935 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
4936 if (f)
4937 queue_notifications (&inev, &msg, f, &count);
4938 break;
8db4b52f 4939#endif
477f1e50 4940
e7efd97e 4941 default:
e471b241 4942 /* Check for messages registered at runtime. */
e7efd97e
GV
4943 if (msg.msg.message == msh_mousewheel)
4944 {
e471b241 4945 /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL. */
66f30e44 4946 msg.msg.message = WM_MOUSEWHEEL;
e471b241 4947 prepend_msg (&msg);
e7efd97e
GV
4948 }
4949 break;
ee78dc32 4950 }
6b61353c
KH
4951
4952 if (inev.kind != NO_EVENT)
4953 {
4954 kbd_buffer_store_event_hold (&inev, hold_quit);
4955 count++;
4956 }
4957
4958 if (do_help
4959 && !(hold_quit && hold_quit->kind != NO_EVENT))
4960 {
4961 Lisp_Object frame;
4962
4963 if (f)
4964 XSETFRAME (frame, f);
4965 else
4966 frame = Qnil;
4967
4968 if (do_help > 0)
4969 {
e597eb7d 4970 if (NILP (help_echo_string))
6b61353c
KH
4971 {
4972 help_echo_object = help_echo_window = Qnil;
4973 help_echo_pos = -1;
4974 }
4975
4976 any_help_event_p = 1;
4977 gen_help_event (help_echo_string, frame, help_echo_window,
4978 help_echo_object, help_echo_pos);
4979 }
4980 else
4981 {
4982 help_echo_string = Qnil;
4983 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4984 }
4985 count++;
4986 }
ee78dc32
GV
4987 }
4988
4989 /* If the focus was just given to an autoraising frame,
4990 raise it now. */
4991 /* ??? This ought to be able to handle more than one such frame. */
4992 if (pending_autoraise_frame)
4993 {
4994 x_raise_frame (pending_autoraise_frame);
4995 pending_autoraise_frame = 0;
4996 }
4997
e8500ff4 4998 /* Check which frames are still visible, if we have enqueued any user
689004fa
GV
4999 events or been notified of events that may affect visibility. We
5000 do this here because there doesn't seem to be any direct
5001 notification from Windows that the visibility of a window has
5002 changed (at least, not in all cases). */
5003 if (count > 0 || check_visibility)
5004 {
5005 Lisp_Object tail, frame;
5006
5007 FOR_EACH_FRAME (tail, frame)
1c64a4a2 5008 {
a10c8269 5009 struct frame *f = XFRAME (frame);
1c64a4a2
JB
5010 /* The tooltip has been drawn already. Avoid the
5011 SET_FRAME_GARBAGED below. */
5012 if (EQ (frame, tip_frame))
5013 continue;
5014
5015 /* Check "visible" frames and mark each as obscured or not.
edfa7fa0
DA
5016 Note that visible is nonzero for unobscured and obscured
5017 frames, but zero for hidden and iconified frames. */
5018 if (FRAME_W32_P (f) && FRAME_VISIBLE_P (f))
1c64a4a2
JB
5019 {
5020 RECT clipbox;
5021 HDC hdc;
edfa7fa0 5022 bool obscured;
1c64a4a2
JB
5023
5024 enter_crit ();
5025 /* Query clipping rectangle for the entire window area
5026 (GetWindowDC), not just the client portion (GetDC).
5027 Otherwise, the scrollbars and menubar aren't counted as
5028 part of the visible area of the frame, and we may think
5029 the frame is obscured when really a scrollbar is still
5030 visible and gets WM_PAINT messages above. */
5031 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
5032 GetClipBox (hdc, &clipbox);
5033 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
5034 leave_crit ();
5035
edfa7fa0
DA
5036 obscured = FRAME_OBSCURED_P (f);
5037
5038 if (clipbox.right == clipbox.left || clipbox.bottom == clipbox.top)
1c64a4a2 5039 {
edfa7fa0
DA
5040 /* Frame has become completely obscured so mark as such (we
5041 do this by setting visible to 2 so that FRAME_VISIBLE_P
5042 is still true, but redisplay will skip it). */
5043 SET_FRAME_VISIBLE (f, 2);
689004fa 5044
edfa7fa0
DA
5045 if (!obscured)
5046 DebPrint (("frame %p (%s) obscured\n", f, SDATA (f->name)));
1c64a4a2
JB
5047 }
5048 else
5049 {
5050 /* Frame is not obscured, so mark it as such. */
edfa7fa0 5051 SET_FRAME_VISIBLE (f, 1);
689004fa 5052
edfa7fa0 5053 if (obscured)
1c64a4a2
JB
5054 {
5055 SET_FRAME_GARBAGED (f);
edfa7fa0
DA
5056 DebPrint (("obscured frame %p (%s) found to be visible\n",
5057 f, SDATA (f->name)));
689004fa 5058
1c64a4a2
JB
5059 /* Force a redisplay sooner or later. */
5060 record_asynch_buffer_change ();
5061 }
5062 }
5063 }
5064 }
689004fa
GV
5065 }
5066
4d7e6e51 5067 unblock_input ();
ee78dc32
GV
5068 return count;
5069}
791f420f 5070
9ef2e2cf 5071
ee78dc32 5072\f
791f420f
JR
5073/***********************************************************************
5074 Text Cursor
5075 ***********************************************************************/
5076
791f420f
JR
5077/* Set clipping for output in glyph row ROW. W is the window in which
5078 we operate. GC is the graphics context to set clipping in.
ee78dc32 5079
791f420f
JR
5080 ROW may be a text row or, e.g., a mode line. Text rows must be
5081 clipped to the interior of the window dedicated to text display,
5082 mode lines must be clipped to the whole window. */
ee78dc32
GV
5083
5084static void
c3c4768d
DA
5085w32_clip_to_row (struct window *w, struct glyph_row *row,
5086 enum glyph_row_area area, HDC hdc)
ee78dc32 5087{
791f420f 5088 RECT clip_rect;
b5a2e277 5089 int window_x, window_y, window_width;
52cf03a1 5090
b5a2e277 5091 window_box (w, area, &window_x, &window_y, &window_width, 0);
52cf03a1 5092
b5a2e277 5093 clip_rect.left = window_x;
791f420f
JR
5094 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5095 clip_rect.top = max (clip_rect.top, window_y);
5096 clip_rect.right = clip_rect.left + window_width;
5097 clip_rect.bottom = clip_rect.top + row->visible_height;
5098
791f420f 5099 w32_set_clip_rectangle (hdc, &clip_rect);
ee78dc32
GV
5100}
5101
791f420f
JR
5102
5103/* Draw a hollow box cursor on window W in glyph row ROW. */
ee78dc32
GV
5104
5105static void
b56ceb92 5106x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
ee78dc32 5107{
791f420f 5108 struct frame *f = XFRAME (WINDOW_FRAME (w));
988646fc 5109 HDC hdc;
791f420f 5110 RECT rect;
b756209d 5111 int left, top, h;
791f420f
JR
5112 struct glyph *cursor_glyph;
5113 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
5114
07c07cfe
JR
5115 /* Get the glyph the cursor is on. If we can't tell because
5116 the current matrix is invalid or such, give up. */
5117 cursor_glyph = get_phys_cursor_glyph (w);
5118 if (cursor_glyph == NULL)
922ae7ee
EZ
5119 {
5120 DeleteObject (hb);
5121 return;
5122 }
07c07cfe 5123
4d91ce74 5124 /* Compute frame-relative coordinates for phys cursor. */
b756209d
EZ
5125 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
5126 rect.left = left;
5127 rect.top = top;
07c07cfe 5128 rect.bottom = rect.top + h;
4d91ce74 5129 rect.right = rect.left + w->phys_cursor_width;
ee78dc32 5130
988646fc 5131 hdc = get_frame_dc (f);
a18bb28d 5132 /* Set clipping, draw the rectangle, and reset clipping again. */
b5a2e277 5133 w32_clip_to_row (w, row, TEXT_AREA, hdc);
791f420f
JR
5134 FrameRect (hdc, &rect, hb);
5135 DeleteObject (hb);
a18bb28d 5136 w32_set_clip_rectangle (hdc, NULL);
791f420f 5137 release_frame_dc (f, hdc);
ee78dc32
GV
5138}
5139
791f420f
JR
5140
5141/* Draw a bar cursor on window W in glyph row ROW.
5142
5143 Implementation note: One would like to draw a bar cursor with an
5144 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5145 Unfortunately, I didn't find a font yet that has this property set.
5146 --gerd. */
ee78dc32
GV
5147
5148static void
b56ceb92
JB
5149x_draw_bar_cursor (struct window *w, struct glyph_row *row,
5150 int width, enum text_cursor_kinds kind)
ee78dc32 5151{
d3d50620 5152 struct frame *f = XFRAME (w->frame);
c2cc16fa 5153 struct glyph *cursor_glyph;
791f420f 5154
c2cc16fa
JR
5155 /* If cursor is out of bounds, don't draw garbage. This can happen
5156 in mini-buffer windows when switching between echo area glyphs
5157 and mini-buffer. */
5158 cursor_glyph = get_phys_cursor_glyph (w);
5159 if (cursor_glyph == NULL)
5160 return;
9ef2e2cf 5161
c2cc16fa
JR
5162 /* If on an image, draw like a normal cursor. That's usually better
5163 visible than drawing a bar, esp. if the image is large so that
5164 the bar might not be in the window. */
5165 if (cursor_glyph->type == IMAGE_GLYPH)
5166 {
5167 struct glyph_row *row;
5168 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
89271099 5169 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
c2cc16fa
JR
5170 }
5171 else
5172 {
6ff3e5e3
JR
5173 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
5174 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
705af33f
JR
5175 int x;
5176 HDC hdc;
6ff3e5e3 5177
6ff3e5e3
JR
5178 /* If the glyph's background equals the color we normally draw
5179 the bar cursor in, the bar cursor in its normal color is
5180 invisible. Use the glyph's foreground color instead in this
5181 case, on the assumption that the glyph's colors are chosen so
5182 that the glyph is legible. */
5183 if (face->background == cursor_color)
5184 cursor_color = face->foreground;
5185
c2cc16fa 5186 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
a18bb28d 5187
c2cc16fa 5188 hdc = get_frame_dc (f);
b5a2e277 5189 w32_clip_to_row (w, row, TEXT_AREA, hdc);
17456df1
JR
5190
5191 if (kind == BAR_CURSOR)
5192 {
705af33f
JR
5193 if (width < 0)
5194 width = FRAME_CURSOR_WIDTH (f);
5195 width = min (cursor_glyph->pixel_width, width);
5196
5197 w->phys_cursor_width = width;
5198
93352106
EZ
5199 /* If the character under cursor is R2L, draw the bar cursor
5200 on the right of its glyph, rather than on the left. */
5201 if ((cursor_glyph->resolved_level & 1) != 0)
5202 x += cursor_glyph->pixel_width - width;
5203
17456df1
JR
5204 w32_fill_area (f, hdc, cursor_color, x,
5205 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5206 width, row->height);
5207 }
5208 else
5209 {
705af33f
JR
5210 int dummy_x, dummy_y, dummy_h;
5211
5212 if (width < 0)
5213 width = row->height;
5214
5215 width = min (row->height, width);
5216
5217 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
5218 &dummy_y, &dummy_h);
17456df1
JR
5219 w32_fill_area (f, hdc, cursor_color, x,
5220 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5221 row->height - width),
705af33f 5222 w->phys_cursor_width, width);
17456df1 5223 }
a18bb28d
JR
5224
5225 w32_set_clip_rectangle (hdc, NULL);
c2cc16fa 5226 release_frame_dc (f, hdc);
791f420f 5227 }
ee78dc32
GV
5228}
5229
791f420f 5230
89271099 5231/* RIF: Define cursor CURSOR on frame F. */
791f420f 5232
ee78dc32 5233static void
b56ceb92 5234w32_define_frame_cursor (struct frame *f, Cursor cursor)
ee78dc32 5235{
89271099 5236 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
791f420f 5237}
ee78dc32 5238
ee78dc32 5239
89271099 5240/* RIF: Clear area on frame F. */
ee78dc32 5241
791f420f 5242static void
b56ceb92 5243w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
791f420f 5244{
89271099 5245 HDC hdc;
791f420f 5246
89271099
KS
5247 hdc = get_frame_dc (f);
5248 w32_clear_area (f, hdc, x, y, width, height);
5249 release_frame_dc (f, hdc);
791f420f 5250}
ee78dc32 5251
89271099 5252/* RIF: Draw or clear cursor on window W. */
791f420f
JR
5253
5254static void
b56ceb92 5255w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
9997ec56
DA
5256 int x, int y, enum text_cursor_kinds cursor_type,
5257 int cursor_width, bool on_p, bool active_p)
ee78dc32 5258{
e5a3b7d9 5259 if (on_p)
791f420f 5260 {
99558ce8
JR
5261 /* If the user wants to use the system caret, make sure our own
5262 cursor remains invisible. */
5263 if (w32_use_visible_system_caret)
5264 {
6b61353c
KH
5265 /* Call to erase_phys_cursor here seems to use the
5266 wrong values of w->phys_cursor, as they have been
5267 overwritten before this function was called. */
99558ce8 5268 if (w->phys_cursor_type != NO_CURSOR)
89271099 5269 erase_phys_cursor (w);
99558ce8 5270
e5a3b7d9 5271 cursor_type = w->phys_cursor_type = NO_CURSOR;
e1429afe 5272 w->phys_cursor_width = -1;
99558ce8
JR
5273 }
5274 else
e1429afe 5275 {
e5a3b7d9 5276 w->phys_cursor_type = cursor_type;
e1429afe 5277 }
99558ce8 5278
791f420f
JR
5279 w->phys_cursor_on_p = 1;
5280
abb15ebd
JR
5281 /* If this is the active cursor, we need to track it with the
5282 system caret, so third party software like screen magnifiers
5283 and speech synthesizers can follow the cursor. */
e5a3b7d9 5284 if (active_p)
abb15ebd 5285 {
0648dde0 5286 struct frame *f = XFRAME (WINDOW_FRAME (w));
99558ce8 5287 HWND hwnd = FRAME_W32_WINDOW (f);
abb15ebd 5288
99558ce8
JR
5289 w32_system_caret_x
5290 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5291 w32_system_caret_y
5292 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
5293 + glyph_row->ascent - w->phys_cursor_ascent);
b932cad7
EZ
5294 w32_system_caret_window = w;
5295 w32_system_caret_hdr_height = WINDOW_HEADER_LINE_HEIGHT (w);
5296 w32_system_caret_mode_height = WINDOW_MODE_LINE_HEIGHT (w);
99558ce8 5297
c902b920
JR
5298 PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
5299
99558ce8
JR
5300 /* If the size of the active cursor changed, destroy the old
5301 system caret. */
5302 if (w32_system_caret_hwnd
5303 && (w32_system_caret_height != w->phys_cursor_height))
5304 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
5305
5306 w32_system_caret_height = w->phys_cursor_height;
5307
5308 /* Move the system caret. */
5309 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
abb15ebd
JR
5310 }
5311
6b61353c 5312 if (glyph_row->exact_window_width_line_p
f951a506
EZ
5313 && (glyph_row->reversed_p
5314 ? (w->phys_cursor.hpos < 0)
5315 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
6b61353c
KH
5316 {
5317 glyph_row->cursor_in_fringe_p = 1;
f951a506 5318 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
6b61353c
KH
5319 return;
5320 }
5321
e5a3b7d9 5322 switch (cursor_type)
ee78dc32 5323 {
791f420f
JR
5324 case HOLLOW_BOX_CURSOR:
5325 x_draw_hollow_cursor (w, glyph_row);
5326 break;
5327
5328 case FILLED_BOX_CURSOR:
89271099 5329 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
791f420f
JR
5330 break;
5331
5332 case BAR_CURSOR:
e5a3b7d9 5333 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
17456df1
JR
5334 break;
5335
5336 case HBAR_CURSOR:
e5a3b7d9 5337 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
791f420f 5338 break;
ee78dc32 5339
791f420f 5340 case NO_CURSOR:
a18bb28d 5341 w->phys_cursor_width = 0;
791f420f
JR
5342 break;
5343
5344 default:
1088b922 5345 emacs_abort ();
791f420f 5346 }
ee78dc32
GV
5347 }
5348}
5349
689004fa 5350
ee78dc32 5351\f
7f5d1df8
GV
5352/* Icons. */
5353
5354int
b56ceb92 5355x_bitmap_icon (struct frame *f, Lisp_Object icon)
7f5d1df8 5356{
945a75f8
JR
5357 HANDLE main_icon;
5358 HANDLE small_icon = NULL;
7f5d1df8
GV
5359
5360 if (FRAME_W32_WINDOW (f) == 0)
5361 return 1;
5362
5363 if (NILP (icon))
945a75f8 5364 main_icon = LoadIcon (hinst, EMACS_CLASS);
7f5d1df8 5365 else if (STRINGP (icon))
945a75f8
JR
5366 {
5367 /* Load the main icon from the named file. */
5368 main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5369 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5370 /* Try to load a small icon to go with it. */
5371 small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
5372 GetSystemMetrics (SM_CXSMICON),
5373 GetSystemMetrics (SM_CYSMICON),
5374 LR_LOADFROMFILE);
5375 }
7f5d1df8
GV
5376 else if (SYMBOLP (icon))
5377 {
5378 LPCTSTR name;
5379
5380 if (EQ (icon, intern ("application")))
5381 name = (LPCTSTR) IDI_APPLICATION;
5382 else if (EQ (icon, intern ("hand")))
5383 name = (LPCTSTR) IDI_HAND;
5384 else if (EQ (icon, intern ("question")))
5385 name = (LPCTSTR) IDI_QUESTION;
5386 else if (EQ (icon, intern ("exclamation")))
5387 name = (LPCTSTR) IDI_EXCLAMATION;
5388 else if (EQ (icon, intern ("asterisk")))
5389 name = (LPCTSTR) IDI_ASTERISK;
5390 else if (EQ (icon, intern ("winlogo")))
5391 name = (LPCTSTR) IDI_WINLOGO;
5392 else
5393 return 1;
5394
945a75f8 5395 main_icon = LoadIcon (NULL, name);
7f5d1df8
GV
5396 }
5397 else
5398 return 1;
5399
945a75f8 5400 if (main_icon == NULL)
7f5d1df8
GV
5401 return 1;
5402
791f420f 5403 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
945a75f8
JR
5404 (LPARAM) main_icon);
5405
5406 /* If there is a small icon that goes with it, set that too. */
5407 if (small_icon)
5408 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
5409 (LPARAM) small_icon);
7f5d1df8
GV
5410
5411 return 0;
5412}
5413
5414\f
c2cc16fa
JR
5415/************************************************************************
5416 Handling X errors
5417 ************************************************************************/
5418
5419/* Display Error Handling functions not used on W32. Listing them here
5420 helps diff stay in step when comparing w32term.c with xterm.c.
5421
5422x_error_catcher (display, error)
5423x_catch_errors (dpy)
5424x_catch_errors_unwind (old_val)
5425x_check_errors (dpy, format)
16ca6226 5426x_fully_uncatch_errors ()
c2cc16fa
JR
5427x_had_errors_p (dpy)
5428x_clear_errors (dpy)
5429x_uncatch_errors (dpy, count)
5430x_trace_wire ()
5431x_connection_signal (signalnum)
5432x_connection_closed (dpy, error_message)
5433x_error_quitter (display, error)
5434x_error_handler (display, error)
5435x_io_error_quitter (display)
5436
5437 */
5438
5439\f
ee78dc32
GV
5440/* Changing the font of the frame. */
5441
027f6f90 5442Lisp_Object
b56ceb92 5443x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
027f6f90 5444{
ef39ccbb 5445 struct font *font = XFONT_OBJECT (font_object);
027f6f90 5446
ef39ccbb
KH
5447 if (fontset < 0)
5448 fontset = fontset_from_font (font_object);
5449 FRAME_FONTSET (f) = fontset;
5450 if (FRAME_FONT (f) == font)
027f6f90
JR
5451 /* This font is already set in frame F. There's nothing more to
5452 do. */
f9c34147 5453 return font_object;
027f6f90 5454
ef39ccbb
KH
5455 FRAME_FONT (f) = font;
5456 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5457 FRAME_COLUMN_WIDTH (f) = font->average_width;
ef39ccbb 5458 FRAME_LINE_HEIGHT (f) = font->height;
027f6f90
JR
5459
5460 compute_fringe_widths (f, 1);
5461
5462 /* Compute the scroll bar width in character columns. */
5463 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5464 {
5465 int wid = FRAME_COLUMN_WIDTH (f);
5466 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5467 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
5468 }
5469 else
5470 {
5471 int wid = FRAME_COLUMN_WIDTH (f);
5472 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5473 }
5474
5475 /* Now make the frame display the given font. */
5476 if (FRAME_X_WINDOW (f) != 0)
5477 {
5478 /* Don't change the size of a tip frame; there's no point in
5479 doing it because it's done in Fx_show_tip, and it leads to
5480 problems because the tip frame has no widget. */
5481 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5482 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5483 }
5484
f9c34147 5485 /* X version sets font of input methods here also. */
027f6f90 5486
f9c34147 5487 return font_object;
027f6f90 5488}
027f6f90 5489
c2cc16fa
JR
5490\f
5491/***********************************************************************
5492 TODO: W32 Input Methods
5493 ***********************************************************************/
5494/* Listing missing functions from xterm.c helps diff stay in step.
791f420f 5495
c2cc16fa
JR
5496xim_destroy_callback (xim, client_data, call_data)
5497xim_open_dpy (dpyinfo, resource_name)
5498struct xim_inst_t
5499xim_instantiate_callback (display, client_data, call_data)
5500xim_initialize (dpyinfo, resource_name)
5501xim_close_dpy (dpyinfo)
791f420f 5502
c2cc16fa 5503 */
791f420f 5504
cabb23bc 5505\f
689004fa
GV
5506/* Calculate the absolute position in frame F
5507 from its current recorded position values and gravity. */
5508
9ef2e2cf 5509void
b56ceb92 5510x_calc_absolute_position (struct frame *f)
ee78dc32 5511{
62e50ec6 5512 int flags = f->size_hint_flags;
ee78dc32 5513
83676aa2
KS
5514 /* The sum of the widths of the frame's left and right borders, and
5515 the sum of the heights of the frame's top and bottom borders (in
5516 pixels) drawn by Windows. */
5517 unsigned int left_right_borders_width, top_bottom_borders_height;
5518
5519 /* Try to get the actual values of these two variables. We compute
5520 the border width (height) by subtracting the width (height) of
5521 the frame's client area from the width (height) of the frame's
5522 entire window. */
5523 WINDOWPLACEMENT wp = { 0 };
5524 RECT client_rect = { 0 };
5525
5526 if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
5527 && GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
5528 {
5529 left_right_borders_width =
5530 (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
5531 (client_rect.right - client_rect.left);
5532
5533 top_bottom_borders_height =
5534 (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
5535 (client_rect.bottom - client_rect.top);
5536 }
5537 else
5538 {
5539 /* Use sensible default values. */
5540 left_right_borders_width = 8;
5541 top_bottom_borders_height = 32;
5542 }
5543
5544 /* Treat negative positions as relative to the rightmost bottommost
ee78dc32
GV
5545 position that fits on the screen. */
5546 if (flags & XNegative)
b89c78a5 5547 f->left_pos = (x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f))
62e50ec6 5548 - FRAME_PIXEL_WIDTH (f)
83676aa2
KS
5549 + f->left_pos
5550 - (left_right_borders_width - 1));
158cba56 5551
ee78dc32 5552 if (flags & YNegative)
b89c78a5 5553 f->top_pos = (x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f))
62e50ec6 5554 - FRAME_PIXEL_HEIGHT (f)
83676aa2
KS
5555 + f->top_pos
5556 - (top_bottom_borders_height - 1));
5557
5558 /* The left_pos and top_pos are now relative to the top and left
5559 screen edges, so the flags should correspond. */
62e50ec6 5560 f->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32
GV
5561}
5562
5563/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5564 to really change the position, and 0 when calling from
5565 x_make_frame_visible (in that case, XOFF and YOFF are the current
5566 position values). It is -1 when calling from x_set_frame_parameters,
5567 which means, do adjust for borders but don't change the gravity. */
5568
9ef2e2cf 5569void
b56ceb92
JB
5570x_set_offset (struct frame *f, register int xoff, register int yoff,
5571 int change_gravity)
ee78dc32
GV
5572{
5573 int modified_top, modified_left;
5574
5575 if (change_gravity > 0)
5576 {
62e50ec6
KS
5577 f->top_pos = yoff;
5578 f->left_pos = xoff;
5579 f->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32 5580 if (xoff < 0)
62e50ec6 5581 f->size_hint_flags |= XNegative;
ee78dc32 5582 if (yoff < 0)
62e50ec6
KS
5583 f->size_hint_flags |= YNegative;
5584 f->win_gravity = NorthWestGravity;
ee78dc32
GV
5585 }
5586 x_calc_absolute_position (f);
5587
4d7e6e51 5588 block_input ();
ee78dc32
GV
5589 x_wm_set_size_hint (f, (long) 0, 0);
5590
62e50ec6
KS
5591 modified_left = f->left_pos;
5592 modified_top = f->top_pos;
ee78dc32 5593
fbd6baed 5594 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
5595 NULL,
5596 modified_left, modified_top,
cabb23bc 5597 0, 0,
689004fa 5598 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
4d7e6e51 5599 unblock_input ();
ee78dc32
GV
5600}
5601
549808db
JR
5602
5603/* Check if we need to resize the frame due to a fullscreen request.
cc92c454 5604 If so needed, resize the frame. */
549808db 5605static void
b56ceb92 5606x_check_fullscreen (struct frame *f)
549808db 5607{
62e50ec6 5608 if (f->want_fullscreen & FULLSCREEN_BOTH)
549808db
JR
5609 {
5610 int width, height, ign;
d67d1627 5611
62e50ec6 5612 x_real_positions (f, &f->left_pos, &f->top_pos);
549808db
JR
5613
5614 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
d67d1627 5615
549808db 5616 /* We do not need to move the window, it shall be taken care of
66f30e44 5617 when setting WM manager hints. */
62e50ec6 5618 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
549808db
JR
5619 {
5620 change_frame_size (f, height, width, 0, 1, 0);
5621 SET_FRAME_GARBAGED (f);
5622 cancel_mouse_face (f);
5623
cc92c454 5624 /* Wait for the change of frame size to occur. */
62e50ec6 5625 f->want_fullscreen |= FULLSCREEN_WAIT;
549808db
JR
5626 }
5627 }
5628}
5629
b2faf49c 5630static void
a10c8269 5631w32fullscreen_hook (struct frame *f)
b2faf49c 5632{
edfa7fa0 5633 if (FRAME_VISIBLE_P (f))
b2faf49c 5634 {
1f635a07
EC
5635 HWND hwnd = FRAME_W32_WINDOW(f);
5636 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
5637 RECT rect;
b2faf49c 5638
1f635a07
EC
5639 block_input();
5640 f->want_fullscreen &= ~FULLSCREEN_WAIT;
5641
5642 if (FRAME_PREV_FSMODE (f) == FULLSCREEN_NONE)
5643 GetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
5644
5645 if (FRAME_PREV_FSMODE (f) == FULLSCREEN_BOTH)
5646 {
5647 SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
5648 SetWindowPos (hwnd, NULL, 0, 0, 0, 0,
5649 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
5650 SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
5651 }
b2faf49c 5652
1f635a07
EC
5653 w32_fullscreen_rect (hwnd, f->want_fullscreen,
5654 FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
cdc0d0bd 5655 FRAME_PREV_FSMODE (f) = f->want_fullscreen;
16ddd1a6
MR
5656 if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
5657 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0);
5658 else if (f->want_fullscreen == FULLSCREEN_BOTH)
1f635a07
EC
5659 {
5660 SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
5661 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
5662 rect.right - rect.left, rect.bottom - rect.top,
5663 SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
5664 }
5665 else
5666 {
5667 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
5668 rect.right - rect.left, rect.bottom - rect.top, 0);
5669 }
b2faf49c 5670
a5cc4dde 5671 f->want_fullscreen = FULLSCREEN_NONE;
b2faf49c
EZ
5672 unblock_input ();
5673 }
a5cc4dde
EZ
5674 else
5675 f->want_fullscreen |= FULLSCREEN_WAIT;
b2faf49c
EZ
5676}
5677
ee78dc32
GV
5678/* Call this to change the size of frame F's x-window.
5679 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5680 for this size change and subsequent size changes.
5681 Otherwise we leave the window gravity unchanged. */
c2cc16fa 5682
791f420f 5683void
b56ceb92 5684x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
ee78dc32
GV
5685{
5686 int pixelwidth, pixelheight;
d67d1627 5687
4d7e6e51 5688 block_input ();
d67d1627 5689
ee78dc32 5690 check_frame_size (f, &rows, &cols);
62e50ec6
KS
5691 f->scroll_bar_actual_width
5692 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
d33c49e8 5693
b6ae1532 5694 compute_fringe_widths (f, 0);
d33c49e8 5695
62e50ec6
KS
5696 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5697 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
d67d1627 5698
62e50ec6 5699 f->win_gravity = NorthWestGravity;
ee78dc32 5700 x_wm_set_size_hint (f, (long) 0, 0);
d67d1627 5701
ee78dc32
GV
5702 {
5703 RECT rect;
5704
5705 rect.left = rect.top = 0;
5706 rect.right = pixelwidth;
5707 rect.bottom = pixelheight;
d67d1627 5708
ed3751c8
JB
5709 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
5710 FRAME_EXTERNAL_MENU_BAR (f));
d67d1627 5711
fbd6baed 5712 my_set_window_pos (FRAME_W32_WINDOW (f),
d67d1627 5713 NULL,
52cf03a1 5714 0, 0,
689004fa
GV
5715 rect.right - rect.left,
5716 rect.bottom - rect.top,
5717 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
ee78dc32 5718 }
d67d1627 5719
f8d1a163
JR
5720#if 0
5721 /* The following mirrors what is done in xterm.c. It appears to be
5722 for informing lisp of the new size immediately, while the actual
5723 resize will happen asynchronously. But on Windows, the menu bar
5724 automatically wraps when the frame is too narrow to contain it,
5725 and that causes any calculations made here to come out wrong. The
fffa137c 5726 end is some nasty buggy behavior, including the potential loss
f8d1a163
JR
5727 of the minibuffer.
5728
5729 Disabling this code is either not sufficient to fix the problems
5730 completely, or it causes fresh problems, but at least it removes
5731 the most problematic symptom of the minibuffer becoming unusable.
5732
5733 -----------------------------------------------------------------
5734
5735 Now, strictly speaking, we can't be sure that this is accurate,
ee78dc32
GV
5736 but the window manager will get around to dealing with the size
5737 change request eventually, and we'll hear how it went when the
5738 ConfigureNotify event gets here.
d67d1627 5739
ee78dc32
GV
5740 We could just not bother storing any of this information here,
5741 and let the ConfigureNotify event set everything up, but that
ec48c3a7 5742 might be kind of confusing to the Lisp code, since size changes
ee78dc32 5743 wouldn't be reported in the frame parameters until some random
791f420f
JR
5744 point in the future when the ConfigureNotify event arrives.
5745
5746 We pass 1 for DELAY since we can't run Lisp code inside of
5747 a BLOCK_INPUT. */
5748 change_frame_size (f, rows, cols, 0, 1, 0);
62e50ec6
KS
5749 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5750 FRAME_PIXEL_HEIGHT (f) = pixelheight;
ee78dc32 5751
689004fa
GV
5752 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5753 receive in the ConfigureNotify event; if we get what we asked
5754 for, then the event won't cause the screen to become garbaged, so
5755 we have to make sure to do it here. */
5756 SET_FRAME_GARBAGED (f);
5757
ee78dc32 5758 /* If cursor was outside the new size, mark it as off. */
e69b0960 5759 mark_window_cursors_off (XWINDOW (f->root_window));
ee78dc32 5760
689004fa 5761 /* Clear out any recollection of where the mouse highlighting was,
d67d1627 5762 since it might be in a place that's outside the new frame size.
689004fa
GV
5763 Actually checking whether it is outside is a pain in the neck,
5764 so don't try--just let the highlighting be done afresh with new size. */
31d4844a 5765 cancel_mouse_face (f);
f8d1a163 5766#endif
31d4844a 5767
4d7e6e51 5768 unblock_input ();
ee78dc32
GV
5769}
5770\f
5771/* Mouse warping. */
5772
ec48c3a7
JR
5773void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5774
5775void
b56ceb92 5776x_set_mouse_position (struct frame *f, int x, int y)
ec48c3a7
JR
5777{
5778 int pix_x, pix_y;
5779
62e50ec6
KS
5780 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5781 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
ec48c3a7
JR
5782
5783 if (pix_x < 0) pix_x = 0;
62e50ec6 5784 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
ec48c3a7
JR
5785
5786 if (pix_y < 0) pix_y = 0;
62e50ec6 5787 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
ec48c3a7
JR
5788
5789 x_set_mouse_pixel_position (f, pix_x, pix_y);
5790}
5791
1bcd16f2 5792void
b56ceb92 5793x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1bcd16f2 5794{
689004fa
GV
5795 RECT rect;
5796 POINT pt;
5797
4d7e6e51 5798 block_input ();
1bcd16f2 5799
689004fa
GV
5800 GetClientRect (FRAME_W32_WINDOW (f), &rect);
5801 pt.x = rect.left + pix_x;
5802 pt.y = rect.top + pix_y;
5803 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
1bcd16f2 5804
689004fa 5805 SetCursorPos (pt.x, pt.y);
1bcd16f2 5806
4d7e6e51 5807 unblock_input ();
1bcd16f2
MB
5808}
5809
ee78dc32
GV
5810\f
5811/* focus shifting, raising and lowering. */
5812
ec48c3a7 5813void
b56ceb92 5814x_focus_on_frame (struct frame *f)
ee78dc32 5815{
689004fa
GV
5816 struct w32_display_info *dpyinfo = &one_w32_display_info;
5817
5818 /* Give input focus to frame. */
4d7e6e51 5819 block_input ();
689004fa
GV
5820#if 0
5821 /* Try not to change its Z-order if possible. */
5822 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
5823 my_set_focus (f, FRAME_W32_WINDOW (f));
5824 else
5825#endif
ef0e360f 5826 my_set_foreground_window (FRAME_W32_WINDOW (f));
4d7e6e51 5827 unblock_input ();
ee78dc32
GV
5828}
5829
ee78dc32 5830/* Raise frame F. */
791f420f 5831void
b56ceb92 5832x_raise_frame (struct frame *f)
ee78dc32 5833{
4d7e6e51 5834 block_input ();
689004fa
GV
5835
5836 /* Strictly speaking, raise-frame should only change the frame's Z
fffa137c 5837 order, leaving input focus unchanged. This is reasonable behavior
689004fa 5838 on X where the usual policy is point-to-focus. However, this
fffa137c 5839 behavior would be very odd on Windows where the usual policy is
689004fa
GV
5840 click-to-focus.
5841
5842 On X, if the mouse happens to be over the raised frame, it gets
5843 input focus anyway (so the window with focus will never be
5844 completely obscured) - if not, then just moving the mouse over it
5845 is sufficient to give it focus. On Windows, the user must actually
e1dbe924 5846 click on the frame (preferably the title bar so as not to move
689004fa
GV
5847 point), which is more awkward. Also, no other Windows program
5848 raises a window to the top but leaves another window (possibly now
5849 completely obscured) with input focus.
5850
5851 Because there is a system setting on Windows that allows the user
5852 to choose the point to focus policy, we make the strict semantics
5853 optional, but by default we grab focus when raising. */
5854
5855 if (NILP (Vw32_grab_focus_on_raise))
ee78dc32 5856 {
689004fa
GV
5857 /* The obvious call to my_set_window_pos doesn't work if Emacs is
5858 not already the foreground application: the frame is raised
5859 above all other frames belonging to us, but not above the
5860 current top window. To achieve that, we have to resort to this
5861 more cumbersome method. */
5862
5863 HDWP handle = BeginDeferWindowPos (2);
5864 if (handle)
5865 {
85d0efd1
EZ
5866 handle = DeferWindowPos (handle,
5867 FRAME_W32_WINDOW (f),
5868 HWND_TOP,
5869 0, 0, 0, 0,
5870 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
5871 if (handle)
5872 {
5873 handle = DeferWindowPos (handle,
5874 GetForegroundWindow (),
5875 FRAME_W32_WINDOW (f),
5876 0, 0, 0, 0,
5877 SWP_NOSIZE | SWP_NOMOVE |
5878 SWP_NOACTIVATE);
5879 if (handle)
5880 EndDeferWindowPos (handle);
5881 }
689004fa 5882 }
ee78dc32 5883 }
689004fa
GV
5884 else
5885 {
85d0efd1 5886 my_bring_window_to_top (FRAME_W32_WINDOW (f));
689004fa
GV
5887 }
5888
4d7e6e51 5889 unblock_input ();
ee78dc32
GV
5890}
5891
5892/* Lower frame F. */
791f420f 5893void
b56ceb92 5894x_lower_frame (struct frame *f)
ee78dc32 5895{
4d7e6e51 5896 block_input ();
689004fa
GV
5897 my_set_window_pos (FRAME_W32_WINDOW (f),
5898 HWND_BOTTOM,
5899 0, 0, 0, 0,
5900 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
4d7e6e51 5901 unblock_input ();
ee78dc32
GV
5902}
5903
5904static void
a10c8269 5905w32_frame_raise_lower (struct frame *f, int raise_flag)
ee78dc32 5906{
7e6ac5b9
AI
5907 if (! FRAME_W32_P (f))
5908 return;
5909
ec48c3a7 5910 if (raise_flag)
ee78dc32
GV
5911 x_raise_frame (f);
5912 else
5913 x_lower_frame (f);
5914}
5915\f
5916/* Change of visibility. */
5917
5918/* This tries to wait until the frame is really visible.
5919 However, if the window manager asks the user where to position
5920 the frame, this will return before the user finishes doing that.
5921 The frame will not actually be visible at that time,
5922 but it will become visible later when the window manager
5923 finishes with it. */
5924
ec48c3a7 5925void
b56ceb92 5926x_make_frame_visible (struct frame *f)
ee78dc32 5927{
7f5d1df8
GV
5928 Lisp_Object type;
5929
4d7e6e51 5930 block_input ();
ee78dc32 5931
7f5d1df8
GV
5932 type = x_icon_type (f);
5933 if (!NILP (type))
5934 x_bitmap_icon (f, type);
5935
ee78dc32
GV
5936 if (! FRAME_VISIBLE_P (f))
5937 {
5938 /* We test FRAME_GARBAGED_P here to make sure we don't
5939 call x_set_offset a second time
5940 if we get to x_make_frame_visible a second time
5941 before the window gets really visible. */
5942 if (! FRAME_ICONIFIED_P (f)
fbd6baed 5943 && ! f->output_data.w32->asked_for_visible)
8958048c
EZ
5944 {
5945 RECT workarea_rect;
5946 RECT window_rect;
5947
5948 /* Adjust vertical window position in order to avoid being
5949 covered by a task bar placed at the bottom of the desktop. */
ed3751c8 5950 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
9d4f32e8 5951 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
8958048c
EZ
5952 if (window_rect.bottom > workarea_rect.bottom
5953 && window_rect.top > workarea_rect.top)
5954 f->top_pos = max (window_rect.top
5955 - window_rect.bottom + workarea_rect.bottom,
5956 workarea_rect.top);
5957
5958 x_set_offset (f, f->left_pos, f->top_pos, 0);
5959 }
ee78dc32 5960
fbd6baed 5961 f->output_data.w32->asked_for_visible = 1;
52cf03a1 5962
22610910 5963 /* According to a report in emacs-devel 2008-06-03, SW_SHOWNORMAL
91af3942 5964 causes unexpected behavior when unminimizing frames that were
53964682 5965 previously maximized. But only SW_SHOWNORMAL works properly for
22610910 5966 frames that were truely hidden (using make-frame-invisible), so
edfa7fa0
DA
5967 we need it to avoid Bug#5482. It seems that iconified is only
5968 set for minimized windows that are still visible, so use that to
5969 determine the appropriate flag to pass ShowWindow. */
12f71857 5970 my_show_window (f, FRAME_W32_WINDOW (f),
edfa7fa0 5971 FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL);
ee78dc32
GV
5972 }
5973
5974 /* Synchronize to ensure Emacs knows the frame is visible
5975 before we do anything else. We do this loop with input not blocked
5976 so that incoming events are handled. */
5977 {
5978 Lisp_Object frame;
791f420f 5979 int count;
ee78dc32
GV
5980
5981 /* This must come after we set COUNT. */
4d7e6e51 5982 unblock_input ();
ee78dc32
GV
5983
5984 XSETFRAME (frame, f);
5985
791f420f
JR
5986 /* Wait until the frame is visible. Process X events until a
5987 MapNotify event has been seen, or until we think we won't get a
5988 MapNotify at all.. */
5989 for (count = input_signal_count + 10;
5990 input_signal_count < count && !FRAME_VISIBLE_P (f);)
ee78dc32 5991 {
791f420f 5992 /* Force processing of queued events. */
01b220b6 5993 /* TODO: x_sync equivalent? */
791f420f 5994
ee78dc32
GV
5995 /* Machines that do polling rather than SIGIO have been observed
5996 to go into a busy-wait here. So we'll fake an alarm signal
5997 to let the handler know that there's something to be read.
5998 We used to raise a real alarm, but it seems that the handler
5999 isn't always enabled here. This is probably a bug. */
6000 if (input_polling_used ())
6001 {
6002 /* It could be confusing if a real alarm arrives while processing
6003 the fake one. Turn it off and let the handler reset it. */
a9b4e0ec
AI
6004 int old_poll_suppress_count = poll_suppress_count;
6005 poll_suppress_count = 1;
6006 poll_for_input_1 ();
6007 poll_suppress_count = old_poll_suppress_count;
ee78dc32 6008 }
ee78dc32 6009 }
ee78dc32
GV
6010 }
6011}
6012
6013/* Change from mapped state to withdrawn state. */
6014
6015/* Make the frame visible (mapped and not iconified). */
6016
b56ceb92
JB
6017void
6018x_make_frame_invisible (struct frame *f)
ee78dc32 6019{
ee78dc32 6020 /* Don't keep the highlight on an invisible frame. */
4baaed0f
KS
6021 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
6022 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
d67d1627 6023
4d7e6e51 6024 block_input ();
d67d1627 6025
689004fa 6026 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
d67d1627 6027
ee78dc32
GV
6028 /* We can't distinguish this from iconification
6029 just by the event that we get from the server.
6030 So we can't win using the usual strategy of letting
6031 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6032 and synchronize with the server to make sure we agree. */
edfa7fa0
DA
6033 SET_FRAME_VISIBLE (f, 0);
6034 SET_FRAME_ICONIFIED (f, 0);
d67d1627 6035
4d7e6e51 6036 unblock_input ();
ee78dc32
GV
6037}
6038
6039/* Change window state from mapped to iconified. */
6040
52cf03a1 6041void
b56ceb92 6042x_iconify_frame (struct frame *f)
ee78dc32 6043{
7f5d1df8 6044 Lisp_Object type;
ee78dc32
GV
6045
6046 /* Don't keep the highlight on an invisible frame. */
4baaed0f
KS
6047 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
6048 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
ee78dc32 6049
edfa7fa0 6050 if (FRAME_ICONIFIED_P (f))
ee78dc32
GV
6051 return;
6052
4d7e6e51 6053 block_input ();
ee78dc32 6054
7f5d1df8
GV
6055 type = x_icon_type (f);
6056 if (!NILP (type))
6057 x_bitmap_icon (f, type);
6058
689004fa 6059 /* Simulate the user minimizing the frame. */
4934bcdd 6060 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
ee78dc32 6061
a8f93651
EZ
6062 SET_FRAME_VISIBLE (f, 0);
6063 SET_FRAME_ICONIFIED (f, 1);
6064
4d7e6e51 6065 unblock_input ();
ee78dc32 6066}
c2cc16fa 6067
ee78dc32 6068\f
25badd7a 6069/* Free X resources of frame F. */
ee78dc32 6070
25badd7a 6071void
7c3320d8 6072x_free_frame_resources (struct frame *f)
ee78dc32 6073{
fbd6baed 6074 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
bbf534ce 6075 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
ee78dc32 6076
4d7e6e51 6077 block_input ();
ee78dc32 6078
ef39ccbb
KH
6079 /* We must free faces before destroying windows because some
6080 font-driver (e.g. xft) access a window while finishing a
6081 face. */
6082 if (FRAME_FACE_CACHE (f))
6083 free_frame_faces (f);
027f6f90 6084
25badd7a
AI
6085 if (FRAME_W32_WINDOW (f))
6086 my_destroy_window (f, FRAME_W32_WINDOW (f));
d67d1627 6087
ee78dc32 6088 free_frame_menubar (f);
ee78dc32 6089
5bcee7ef
KL
6090 unload_color (f, FRAME_FOREGROUND_PIXEL (f));
6091 unload_color (f, FRAME_BACKGROUND_PIXEL (f));
25badd7a
AI
6092 unload_color (f, f->output_data.w32->cursor_pixel);
6093 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
6094 unload_color (f, f->output_data.w32->border_pixel);
6095 unload_color (f, f->output_data.w32->mouse_pixel);
c2cc16fa
JR
6096 if (f->output_data.w32->white_relief.allocated_p)
6097 unload_color (f, f->output_data.w32->white_relief.pixel);
6098 if (f->output_data.w32->black_relief.allocated_p)
6099 unload_color (f, f->output_data.w32->black_relief.pixel);
6100
25badd7a
AI
6101 if (FRAME_FACE_CACHE (f))
6102 free_frame_faces (f);
d67d1627 6103
fbd6baed 6104 xfree (f->output_data.w32);
25badd7a 6105 f->output_data.w32 = NULL;
d67d1627 6106
fbd6baed
GV
6107 if (f == dpyinfo->w32_focus_frame)
6108 dpyinfo->w32_focus_frame = 0;
6109 if (f == dpyinfo->w32_focus_event_frame)
6110 dpyinfo->w32_focus_event_frame = 0;
4baaed0f
KS
6111 if (f == dpyinfo->x_highlight_frame)
6112 dpyinfo->x_highlight_frame = 0;
bbf534ce 6113 if (f == hlinfo->mouse_face_mouse_frame)
9fed9729 6114 reset_mouse_highlight (hlinfo);
ee78dc32 6115
4d7e6e51 6116 unblock_input ();
ee78dc32 6117}
25badd7a
AI
6118
6119
6120/* Destroy the window of frame F. */
4a418b10 6121void
b56ceb92 6122x_destroy_window (struct frame *f)
25badd7a
AI
6123{
6124 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6125
6126 x_free_frame_resources (f);
25badd7a
AI
6127 dpyinfo->reference_count--;
6128}
c2cc16fa 6129
ee78dc32
GV
6130\f
6131/* Setting window manager hints. */
6132
6133/* Set the normal size hints for the window manager, for frame F.
6134 FLAGS is the flags word to use--or 0 meaning preserve the flags
6135 that the window now has.
18e27ea8 6136 If USER_POSITION, set the USPosition
ee78dc32 6137 flag (this is useful when FLAGS is 0). */
791f420f 6138void
18e27ea8 6139x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
ee78dc32 6140{
fbd6baed 6141 Window window = FRAME_W32_WINDOW (f);
ee78dc32 6142
97c23857 6143 enter_crit ();
ee78dc32 6144
62e50ec6
KS
6145 SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
6146 SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
6147 SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
6148 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
ee78dc32 6149
97c23857 6150 leave_crit ();
ee78dc32
GV
6151}
6152
784b56e2
EZ
6153/***********************************************************************
6154 Fonts
6155 ***********************************************************************/
6156
e509cfa6 6157#ifdef GLYPH_DEBUG
784b56e2
EZ
6158
6159/* Check that FONT is valid on frame F. It is if it can be found in F's
6160 font table. */
6161
6162static void
6163x_check_font (struct frame *f, struct font *font)
6164{
a54e2c05 6165 eassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
784b56e2 6166 if (font->driver->check)
a54e2c05 6167 eassert (font->driver->check (f, font) == 0);
784b56e2
EZ
6168}
6169
e509cfa6 6170#endif /* GLYPH_DEBUG */
784b56e2
EZ
6171
6172
6173\f
791f420f
JR
6174/***********************************************************************
6175 Initialization
6176 ***********************************************************************/
ee78dc32 6177
fbd6baed 6178static int w32_initialized = 0;
ee78dc32 6179
f7737f5d 6180void
b56ceb92 6181w32_initialize_display_info (Lisp_Object display_name)
f7737f5d
JR
6182{
6183 struct w32_display_info *dpyinfo = &one_w32_display_info;
6184
72af86bd 6185 memset (dpyinfo, 0, sizeof (*dpyinfo));
f7737f5d
JR
6186
6187 /* Put it on w32_display_name_list. */
6188 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
6189 w32_display_name_list);
6190 dpyinfo->name_list_element = XCAR (w32_display_name_list);
d67d1627 6191
23f86fce
DA
6192 dpyinfo->w32_id_name = xmalloc (SCHARS (Vinvocation_name)
6193 + SCHARS (Vsystem_name) + 2);
f7737f5d 6194 sprintf (dpyinfo->w32_id_name, "%s@%s",
d5db4077 6195 SDATA (Vinvocation_name), SDATA (Vsystem_name));
f7737f5d
JR
6196
6197 /* Default Console mode values - overridden when running in GUI mode
6198 with values obtained from system metrics. */
6199 dpyinfo->resx = 1;
6200 dpyinfo->resy = 1;
f7737f5d
JR
6201 dpyinfo->n_planes = 1;
6202 dpyinfo->n_cbits = 4;
6203 dpyinfo->n_fonts = 0;
6204 dpyinfo->smallest_font_height = 1;
6205 dpyinfo->smallest_char_width = 1;
2bf04b9d 6206 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
01b220b6 6207 /* TODO: dpyinfo->gray */
f7737f5d 6208
9fed9729 6209 reset_mouse_highlight (&dpyinfo->mouse_highlight);
f7737f5d
JR
6210}
6211
0105dc3e 6212/* Create an xrdb-style database of resources to supersede registry settings.
c13a8a91 6213 The database is just a concatenation of C strings, finished by an additional
decb374a 6214 \0. The strings are submitted to some basic normalization, so
c13a8a91
JB
6215
6216 [ *]option[ *]:[ *]value...
6217
6218 becomes
6219
6220 option:value...
6221
6222 but any whitespace following value is not removed. */
6223
6224static char *
b56ceb92 6225w32_make_rdb (char *xrm_option)
c13a8a91
JB
6226{
6227 char *buffer = xmalloc (strlen (xrm_option) + 2);
6228 char *current = buffer;
6229 char ch;
6230 int in_option = 1;
6231 int before_value = 0;
6232
6233 do {
6234 ch = *xrm_option++;
6235
6236 if (ch == '\n')
6237 {
6238 *current++ = '\0';
6239 in_option = 1;
6240 before_value = 0;
6241 }
6242 else if (ch != ' ')
6243 {
6244 *current++ = ch;
6245 if (in_option && (ch == ':'))
6246 {
6247 in_option = 0;
6248 before_value = 1;
6249 }
6250 else if (before_value)
6251 {
6252 before_value = 0;
6253 }
6254 }
6255 else if (!(in_option || before_value))
6256 {
6257 *current++ = ch;
6258 }
6259 } while (ch);
6260
6261 *current = '\0';
6262
6263 return buffer;
6264}
6265
4a418b10
JR
6266void
6267x_flush (struct frame * f)
6268{ /* Nothing to do */ }
6269
6270
6271extern frame_parm_handler w32_frame_parm_handlers[];
6272
6273static struct redisplay_interface w32_redisplay_interface =
6274{
6275 w32_frame_parm_handlers,
6276 x_produce_glyphs,
6277 x_write_glyphs,
6278 x_insert_glyphs,
6279 x_clear_end_of_line,
6280 x_scroll_run,
6281 x_after_update_window_line,
6282 x_update_window_begin,
6283 x_update_window_end,
4a418b10
JR
6284 x_flush,
6285 0, /* flush_display_optional */
6286 x_clear_window_mouse_face,
e5e29349 6287 x_get_glyph_overhangs,
4a418b10
JR
6288 x_fix_overlapping_area,
6289 w32_draw_fringe_bitmap,
6290 w32_define_fringe_bitmap,
6291 w32_destroy_fringe_bitmap,
cf907d69 6292 w32_compute_glyph_string_overhangs,
4a418b10
JR
6293 x_draw_glyph_string,
6294 w32_define_frame_cursor,
6295 w32_clear_frame_area,
6296 w32_draw_window_cursor,
6297 w32_draw_vertical_window_border,
6298 w32_shift_glyphs_for_insert
6299};
6300
6301static void x_delete_terminal (struct terminal *term);
6302
6303static struct terminal *
6304w32_create_terminal (struct w32_display_info *dpyinfo)
6305{
6306 struct terminal *terminal;
def7fa34 6307
4a418b10
JR
6308 terminal = create_terminal ();
6309
6310 terminal->type = output_w32;
6311 terminal->display_info.w32 = dpyinfo;
6312 dpyinfo->terminal = terminal;
6313
6314 /* MSVC does not type K&R functions with no arguments correctly, and
6315 so we must explicitly cast them. */
6316 terminal->clear_frame_hook = x_clear_frame;
6317 terminal->ins_del_lines_hook = x_ins_del_lines;
6318 terminal->delete_glyphs_hook = x_delete_glyphs;
6319 terminal->ring_bell_hook = w32_ring_bell;
a892a94c
DA
6320 terminal->reset_terminal_modes_hook = NULL;
6321 terminal->set_terminal_modes_hook = NULL;
4a418b10
JR
6322 terminal->update_begin_hook = x_update_begin;
6323 terminal->update_end_hook = x_update_end;
0c7f856e 6324 terminal->set_terminal_window_hook = NULL;
4a418b10
JR
6325 terminal->read_socket_hook = w32_read_socket;
6326 terminal->frame_up_to_date_hook = w32_frame_up_to_date;
6327 terminal->mouse_position_hook = w32_mouse_position;
6328 terminal->frame_rehighlight_hook = w32_frame_rehighlight;
6329 terminal->frame_raise_lower_hook = w32_frame_raise_lower;
b2faf49c 6330 terminal->fullscreen_hook = w32fullscreen_hook;
4a418b10
JR
6331 terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
6332 terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
6333 terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
6334 terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
6335
6336 terminal->delete_frame_hook = x_destroy_window;
6337 terminal->delete_terminal_hook = x_delete_terminal;
def7fa34 6338
4a418b10
JR
6339 terminal->rif = &w32_redisplay_interface;
6340 terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
6341 terminal->char_ins_del_ok = 1;
6342 terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
6343 terminal->fast_clear_end_of_line = 1; /* X does this well. */
6344 terminal->memory_below_frame = 0; /* We don't remember what scrolls
6345 off the bottom. */
6346
1526bc23
JR
6347 /* We don't yet support separate terminals on W32, so don't try to share
6348 keyboards between virtual terminals that are on the same physical
6349 terminal like X does. */
23f86fce 6350 terminal->kboard = xmalloc (sizeof (KBOARD));
1526bc23 6351 init_kboard (terminal->kboard);
15dbb4d6 6352 kset_window_system (terminal->kboard, intern ("w32"));
1526bc23
JR
6353 terminal->kboard->next_kboard = all_kboards;
6354 all_kboards = terminal->kboard;
6355 /* Don't let the initial kboard remain current longer than necessary.
6356 That would cause problems if a file loaded on startup tries to
6357 prompt in the mini-buffer. */
6358 if (current_kboard == initial_kboard)
6359 current_kboard = terminal->kboard;
6360 terminal->kboard->reference_count++;
1526bc23 6361
4a418b10
JR
6362 return terminal;
6363}
6364
6365static void
6366x_delete_terminal (struct terminal *terminal)
6367{
6368 struct w32_display_info *dpyinfo = terminal->display_info.w32;
4a418b10 6369
e2749141 6370 /* Protect against recursive calls. delete_frame in
4a418b10 6371 delete_terminal calls us back when it deletes our last frame. */
adc54316 6372 if (!terminal->name)
4a418b10
JR
6373 return;
6374
4d7e6e51 6375 block_input ();
4a418b10
JR
6376
6377 x_delete_display (dpyinfo);
4d7e6e51 6378 unblock_input ();
4a418b10
JR
6379}
6380
fbd6baed 6381struct w32_display_info *
b56ceb92 6382w32_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
ee78dc32 6383{
fbd6baed 6384 struct w32_display_info *dpyinfo;
4a418b10 6385 struct terminal *terminal;
ee78dc32 6386 HDC hdc;
d67d1627 6387
4d7e6e51 6388 block_input ();
d67d1627 6389
fbd6baed 6390 if (!w32_initialized)
ee78dc32 6391 {
fbd6baed
GV
6392 w32_initialize ();
6393 w32_initialized = 1;
ee78dc32 6394 }
d67d1627 6395
f7737f5d 6396 w32_initialize_display_info (display_name);
ee78dc32 6397
f7737f5d 6398 dpyinfo = &one_w32_display_info;
4a418b10
JR
6399 terminal = w32_create_terminal (dpyinfo);
6400
6401 /* Set the name of the terminal. */
5b71542d 6402 terminal->name = xlispstrdup (display_name);
8c3b00cb 6403
c13a8a91
JB
6404 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
6405
8c3b00cb
AI
6406 /* Put this display on the chain. */
6407 dpyinfo->next = x_display_list;
6408 x_display_list = dpyinfo;
d67d1627 6409
cb4a3e42 6410 hdc = GetDC (NULL);
791f420f 6411
ee78dc32
GV
6412 dpyinfo->root_window = GetDesktopWindow ();
6413 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
6414 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
55689ab1
JR
6415 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
6416 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
52cf03a1 6417 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
cb4a3e42 6418 ReleaseDC (NULL, hdc);
52cf03a1 6419
e1dbe924 6420 /* initialize palette with white and black */
52cf03a1 6421 {
316ed821 6422 XColor color;
55689ab1
JR
6423 w32_defined_color (0, "white", &color, 1);
6424 w32_defined_color (0, "black", &color, 1);
52cf03a1
GV
6425 }
6426
0fda9b75
DC
6427#ifdef WINDOWSNT
6428 /* Add the default keyboard. When !WINDOWSNT, we're using the
6429 standard Emacs console handling machinery and don't need an
6430 explicit FD here. */
543c3ccd 6431 add_keyboard_wait_descriptor (0);
0fda9b75
DC
6432#elif CYGWIN
6433 /* /dev/windows wakes us up when we have a thread message pending. */
6434 add_keyboard_wait_descriptor (w32_message_fd);
6435#endif
543c3ccd 6436
b6ae1532
KS
6437 /* Create Fringe Bitmaps and store them for later use.
6438
6439 On W32, bitmaps are all unsigned short, as Windows requires
6440 bitmap data to be Word aligned. For some reason they are
6441 horizontally reflected compared to how they appear on X, so we
6442 need to bitswap and convert to unsigned shorts before creating
6443 the bitmaps. */
09b69f01 6444 w32_init_fringe (terminal->rif);
f7737f5d 6445
4d7e6e51 6446 unblock_input ();
ee78dc32
GV
6447
6448 return dpyinfo;
6449}
6450\f
6451/* Get rid of display DPYINFO, assuming all frames are already gone. */
ee78dc32 6452void
b56ceb92 6453x_delete_display (struct w32_display_info *dpyinfo)
ee78dc32 6454{
fbd6baed 6455 /* Discard this display from w32_display_name_list and w32_display_list.
ee78dc32 6456 We can't use Fdelq because that can quit. */
fbd6baed 6457 if (! NILP (w32_display_name_list)
8e713be6
KR
6458 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
6459 w32_display_name_list = XCDR (w32_display_name_list);
ee78dc32
GV
6460 else
6461 {
6462 Lisp_Object tail;
6463
fbd6baed 6464 tail = w32_display_name_list;
8e713be6 6465 while (CONSP (tail) && CONSP (XCDR (tail)))
ee78dc32 6466 {
f7737f5d 6467 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
ee78dc32 6468 {
f3fbd155 6469 XSETCDR (tail, XCDR (XCDR (tail)));
ee78dc32
GV
6470 break;
6471 }
8e713be6 6472 tail = XCDR (tail);
ee78dc32
GV
6473 }
6474 }
6475
52cf03a1
GV
6476 /* free palette table */
6477 {
fbd6baed 6478 struct w32_palette_entry * plist;
52cf03a1
GV
6479
6480 plist = dpyinfo->color_list;
6481 while (plist)
6482 {
fbd6baed 6483 struct w32_palette_entry * pentry = plist;
52cf03a1 6484 plist = plist->next;
9127e20e 6485 xfree (pentry);
52cf03a1
GV
6486 }
6487 dpyinfo->color_list = NULL;
6488 if (dpyinfo->palette)
ed3751c8 6489 DeleteObject (dpyinfo->palette);
52cf03a1 6490 }
fbd6baed 6491 xfree (dpyinfo->w32_id_name);
f7737f5d 6492
6b61353c 6493 w32_reset_fringes ();
ee78dc32 6494}
0fda9b75 6495
ee78dc32 6496\f
fbd6baed 6497/* Set up use of W32. */
ee78dc32 6498
b0d4e0c7 6499DWORD WINAPI w32_msg_worker (void * arg);
ee78dc32 6500
1bb8a291 6501static void
b56ceb92 6502w32_initialize (void)
fbd6baed 6503{
ff90fbde 6504 HANDLE shell;
0a3472c7 6505 HRESULT (WINAPI * set_user_model) (wchar_t * id);
ff90fbde 6506
ee78dc32
GV
6507 baud_rate = 19200;
6508
abb15ebd
JR
6509 w32_system_caret_hwnd = NULL;
6510 w32_system_caret_height = 0;
abb15ebd
JR
6511 w32_system_caret_x = 0;
6512 w32_system_caret_y = 0;
6513
ff90fbde
JR
6514 /* On Windows 7 and later, we need to set the user model ID
6515 to associate emacsclient launched files with Emacs frames
6516 in the UI. */
6517 shell = GetModuleHandle ("shell32.dll");
6518 if (shell)
6519 {
6520 set_user_model
6521 = (void *) GetProcAddress (shell,
6522 "SetCurrentProcessExplicitAppUserModelID");
6523
6524 /* If the function is defined, then we are running on Windows 7
6525 or newer, and the UI uses this to group related windows
6526 together. Since emacs, runemacs, emacsclient are related, we
6527 want them grouped even though the executables are different,
6528 so we need to set a consistent ID between them. */
6529 if (set_user_model)
6530 set_user_model (L"GNU.Emacs");
6531 }
6532
0fda9b75 6533#ifdef CYGWIN
406af475 6534 if ((w32_message_fd = emacs_open ("/dev/windows", O_RDWR, 0)) == -1)
0fda9b75
DC
6535 fatal ("opening /dev/windows: %s", strerror (errno));
6536#endif /* CYGWIN */
6537
c2baa2b6
JR
6538 /* Initialize w32_use_visible_system_caret based on whether a screen
6539 reader is in use. */
6540 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
6541 &w32_use_visible_system_caret, 0))
6542 w32_use_visible_system_caret = 0;
6543
791f420f
JR
6544 last_tool_bar_item = -1;
6545 any_help_event_p = 0;
6546
689004fa
GV
6547 /* Initialize input mode: interrupt_input off, no flow control, allow
6548 8 bit character input, standard quit char. */
6549 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
ee78dc32 6550
13087e59 6551 {
4f3576ee 6552 DWORD input_locale_id = ((DWORD_PTR) GetKeyboardLayout (0) & 0xffffffff);
302fc036
EZ
6553 w32_keyboard_codepage =
6554 codepage_for_locale ((LCID) (input_locale_id & 0xffff));
13087e59 6555 }
ee78dc32 6556
13087e59
JR
6557 /* Create the window thread - it will terminate itself when the app
6558 terminates */
ee78dc32
GV
6559 init_crit ();
6560
6561 dwMainThreadId = GetCurrentThreadId ();
d67d1627 6562 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
ee78dc32
GV
6563 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
6564
6565 /* Wait for thread to start */
ee78dc32
GV
6566 {
6567 MSG msg;
6568
6569 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
6570
d67d1627 6571 hWindowsThread = CreateThread (NULL, 0,
b0d4e0c7
JR
6572 w32_msg_worker,
6573 0, 0, &dwWindowsThreadId);
ee78dc32
GV
6574
6575 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6576 }
d67d1627 6577
52cf03a1 6578 /* It is desirable that mainThread should have the same notion of
e9e23e23 6579 focus window and active window as windowsThread. Unfortunately, the
52cf03a1
GV
6580 following call to AttachThreadInput, which should do precisely what
6581 we need, causes major problems when Emacs is linked as a console
6582 program. Unfortunately, we have good reasons for doing that, so
e9e23e23 6583 instead we need to send messages to windowsThread to make some API
52cf03a1 6584 calls for us (ones that affect, or depend on, the active/focus
65a6ff8f 6585 window state.) */
52cf03a1 6586#ifdef ATTACH_THREADS
e9e23e23 6587 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
52cf03a1 6588#endif
689004fa 6589
33e40ce7 6590 /* Dynamically link to optional system components. */
689004fa 6591 {
ff90fbde 6592 HMODULE user_lib = GetModuleHandle ("user32.dll");
689004fa 6593
41375f89 6594#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
689004fa 6595
8b61a891 6596 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
65a6ff8f 6597
689004fa
GV
6598#undef LOAD_PROC
6599
33e40ce7
JR
6600 /* Ensure scrollbar handle is at least 5 pixels. */
6601 vertical_scroll_bar_min_handle = 5;
689004fa
GV
6602
6603 /* For either kind of scroll bar, take account of the arrows; these
6604 effectively form the border of the main scroll bar range. */
6605 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
6606 = GetSystemMetrics (SM_CYVSCROLL);
6607 }
ee78dc32
GV
6608}
6609
6610void
b56ceb92 6611syms_of_w32term (void)
ee78dc32 6612{
fbd6baed
GV
6613 staticpro (&w32_display_name_list);
6614 w32_display_name_list = Qnil;
ee78dc32
GV
6615
6616 staticpro (&last_mouse_scroll_bar);
6617 last_mouse_scroll_bar = Qnil;
6618
5f33dbf7 6619 DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
52cf03a1 6620
477f1e50
EZ
6621 DEFSYM (Qadded, "added");
6622 DEFSYM (Qremoved, "removed");
6623 DEFSYM (Qmodified, "modified");
6624 DEFSYM (Qrenamed_from, "renamed-from");
6625 DEFSYM (Qrenamed_to, "renamed-to");
6626
fbd6baed 6627 DEFVAR_INT ("w32-num-mouse-buttons",
29208e82 6628 w32_num_mouse_buttons,
33f09670 6629 doc: /* Number of physical mouse buttons. */);
e597eb7d 6630 w32_num_mouse_buttons = 2;
52cf03a1 6631
fbd6baed 6632 DEFVAR_LISP ("w32-swap-mouse-buttons",
29208e82 6633 Vw32_swap_mouse_buttons,
33f09670
JR
6634 doc: /* Swap the mapping of middle and right mouse buttons.
6635When nil, middle button is mouse-2 and right button is mouse-3. */);
fbd6baed 6636 Vw32_swap_mouse_buttons = Qnil;
689004fa
GV
6637
6638 DEFVAR_LISP ("w32-grab-focus-on-raise",
29208e82 6639 Vw32_grab_focus_on_raise,
33f09670
JR
6640 doc: /* Raised frame grabs input focus.
6641When t, `raise-frame' grabs input focus as well. This fits well
6642with the normal Windows click-to-focus policy, but might not be
6643desirable when using a point-to-focus policy. */);
689004fa
GV
6644 Vw32_grab_focus_on_raise = Qt;
6645
6646 DEFVAR_LISP ("w32-capslock-is-shiftlock",
29208e82 6647 Vw32_capslock_is_shiftlock,
33f09670
JR
6648 doc: /* Apply CapsLock state to non character input keys.
6649When nil, CapsLock only affects normal character input keys. */);
689004fa 6650 Vw32_capslock_is_shiftlock = Qnil;
ef0e360f
GV
6651
6652 DEFVAR_LISP ("w32-recognize-altgr",
29208e82 6653 Vw32_recognize_altgr,
33f09670
JR
6654 doc: /* Recognize right-alt and left-ctrl as AltGr.
6655When nil, the right-alt and left-ctrl key combination is
d67d1627 6656interpreted normally. */);
ef0e360f 6657 Vw32_recognize_altgr = Qt;
bc6af935 6658
99558ce8 6659 DEFVAR_BOOL ("w32-use-visible-system-caret",
29208e82 6660 w32_use_visible_system_caret,
99558ce8
JR
6661 doc: /* Flag to make the system caret visible.
6662When this is non-nil, Emacs will indicate the position of point by
6663using the system caret instead of drawing its own cursor. Some screen
6664reader software does not track the system cursor properly when it is
6665invisible, and gets confused by Emacs drawing its own cursor, so this
d67d1627 6666variable is initialized to t when Emacs detects that screen reader
99558ce8
JR
6667software is running as it starts up.
6668
6669When this variable is set, other variables affecting the appearance of
6670the cursor have no effect. */);
6671
c2baa2b6 6672 w32_use_visible_system_caret = 0;
99558ce8 6673
099b6577
EZ
6674 /* We don't yet support this, but defining this here avoids whining
6675 from cus-start.el and other places, like "M-x set-variable". */
6676 DEFVAR_BOOL ("x-use-underline-position-properties",
29208e82 6677 x_use_underline_position_properties,
fb7ada5f 6678 doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
e1e4b63b 6679A value of nil means ignore them. If you encounter fonts with bogus
099b6577 6680UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
ea883883
GM
6681to 4.1, set this to nil. You can also use `underline-minimum-offset'
6682to override the font's UNDERLINE_POSITION for small font display
6683sizes. */);
099b6577
EZ
6684 x_use_underline_position_properties = 0;
6685
30f27523 6686 DEFVAR_BOOL ("x-underline-at-descent-line",
29208e82 6687 x_underline_at_descent_line,
fb7ada5f 6688 doc: /* Non-nil means to draw the underline at the same place as the descent line.
e1e4b63b
JB
6689A value of nil means to draw the underline according to the value of the
6690variable `x-use-underline-position-properties', which is usually at the
6691baseline level. The default value is nil. */);
30f27523
KS
6692 x_underline_at_descent_line = 0;
6693
29208e82 6694 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
65807d73
GM
6695 doc: /* Which toolkit scroll bars Emacs uses, if any.
6696A value of nil means Emacs doesn't use toolkit scroll bars.
6697With the X Window system, the value is a symbol describing the
6698X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
44f92739 6699With MS Windows or Nextstep, the value is t. */);
5bf04520 6700 Vx_toolkit_scroll_bars = Qt;
791f420f
JR
6701
6702 staticpro (&last_mouse_motion_frame);
6703 last_mouse_motion_frame = Qnil;
0fda9b75
DC
6704
6705 Fprovide (intern_c_string ("w32"), Qnil);
ee78dc32 6706}