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