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