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