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