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