(XChar2b): Move typedef here for consolidation.
[bpt/emacs.git] / src / w32term.c
CommitLineData
e9e23e23 1/* Implementation of GUI terminal on the Microsoft W32 API.
c2cc16fa 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
9ef2e2cf 3 Free Software Foundation, Inc.
ee78dc32
GV
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ef2e2cf
JR
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1fb87c77 20Boston, MA 02111-1307, USA. */
ee78dc32 21
ee78dc32 22#include <config.h>
68c45bf0 23#include <signal.h>
ee78dc32 24#include <stdio.h>
791f420f 25#include <stdlib.h>
ee78dc32 26#include "lisp.h"
2091aeb2 27#include "charset.h"
ee78dc32
GV
28#include "blockinput.h"
29
e12ca9c2 30#include "w32heap.h"
689004fa 31#include "w32term.h"
791f420f 32#include "w32bdf.h"
12857dfd 33#include <shellapi.h>
ee78dc32
GV
34
35#include "systty.h"
36#include "systime.h"
f7737f5d 37#include "atimer.h"
8feddab4 38#include "keymap.h"
ee78dc32
GV
39
40#include <ctype.h>
41#include <errno.h>
42#include <setjmp.h>
43#include <sys/stat.h>
44
38006079 45#include "keyboard.h"
ee78dc32
GV
46#include "frame.h"
47#include "dispextern.h"
93ff4395 48#include "fontset.h"
ee78dc32
GV
49#include "termhooks.h"
50#include "termopts.h"
51#include "termchar.h"
52#include "gnu.h"
53#include "disptab.h"
54#include "buffer.h"
55#include "window.h"
ee78dc32 56#include "intervals.h"
791f420f 57#include "composite.h"
ef0e360f 58#include "coding.h"
ee78dc32 59
791f420f
JR
60#define abs(x) ((x) < 0 ? -(x) : (x))
61
62#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
63
64\f
33c34bea 65/* Fringe bitmaps. */
791f420f 66
b6ae1532 67static HBITMAP fringe_bmp[MAX_FRINGE_BITMAPS];
791f420f
JR
68
69extern Lisp_Object Qhelp_echo;
70
5bf04520 71/* Non-nil means Emacs uses toolkit scroll bars. */
791f420f 72
5bf04520 73Lisp_Object Vx_toolkit_scroll_bars;
791f420f
JR
74
75/* If a string, w32_read_socket generates an event to display that string.
76 (The display is done in read_char.) */
d67d1627 77
791f420f 78static Lisp_Object help_echo;
158cba56 79static Lisp_Object help_echo_window;
ec48c3a7
JR
80static Lisp_Object help_echo_object;
81static int help_echo_pos;
791f420f 82
706ddb8f 83/* Temporary variables for w32_read_socket. */
791f420f
JR
84
85static Lisp_Object previous_help_echo;
706ddb8f
JR
86static int last_mousemove_x = 0;
87static int last_mousemove_y = 0;
791f420f
JR
88
89/* Non-zero means that a HELP_EVENT has been generated since Emacs
90 start. */
91
92static int any_help_event_p;
93
549808db
JR
94/* Non-zero means autoselect window with the mouse cursor. */
95
ee8ceff8 96int mouse_autoselect_window;
549808db 97
a18bb28d
JR
98/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
99static Lisp_Object last_window;
100
791f420f
JR
101/* Non-zero means draw block and hollow cursor as wide as the glyph
102 under it. For example, if a block cursor is over a tab, it will be
103 drawn as wide as that tab on the display. */
104
105int x_stretch_cursor_p;
106
9f5a911b
JR
107/* Non-zero means make use of UNDERLINE_POSITION font properties. */
108
109int x_use_underline_position_properties;
110
e7efd97e
GV
111extern unsigned int msh_mousewheel;
112
ee78dc32
GV
113extern void free_frame_menubar ();
114
9ef2e2cf 115extern int w32_codepage_for_font (char *fontname);
2bf04b9d 116extern Cursor w32_load_cursor (LPCTSTR name);
9ef2e2cf 117
82f9d565
AI
118extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
119 unsigned char *text, int dim);
52cf03a1
GV
120extern Lisp_Object Vwindow_system;
121
ee78dc32
GV
122#define x_any_window_to_frame x_window_to_frame
123#define x_top_window_to_frame x_window_to_frame
124
125\f
fbd6baed
GV
126/* This is display since w32 does not support multiple ones. */
127struct w32_display_info one_w32_display_info;
8c3b00cb 128struct w32_display_info *x_display_list;
ee78dc32
GV
129
130/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
fbd6baed 131 one for each element of w32_display_list and in the same order.
ee78dc32
GV
132 NAME is the name of the frame.
133 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
fbd6baed 134Lisp_Object w32_display_name_list;
ee78dc32
GV
135
136/* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the
fbd6baed 138 w32 functions. It is zero while not inside an update.
791f420f 139 In that case, the w32 functions assume that `SELECTED_FRAME ()'
ee78dc32
GV
140 is the frame to apply to. */
141extern struct frame *updating_frame;
142
143/* This is a frame waiting to be autoraised, within w32_read_socket. */
144struct frame *pending_autoraise_frame;
145
ee78dc32 146/* Nominal cursor position -- where to draw output.
791f420f
JR
147 HPOS and VPOS are window relative glyph matrix coordinates.
148 X and Y are window relative pixel coordinates. */
ee78dc32 149
791f420f 150struct cursor_pos output_cursor;
ee78dc32 151
abb15ebd
JR
152/* The handle of the frame that currently owns the system caret. */
153HWND w32_system_caret_hwnd;
abb15ebd
JR
154int w32_system_caret_height;
155int w32_system_caret_x;
156int w32_system_caret_y;
99558ce8 157int w32_use_visible_system_caret;
abb15ebd 158
484fa2c1 159/* Flag to enable Unicode output in case users wish to use programs
cabb23bc
GV
160 like Twinbridge on '95 rather than installed system level support
161 for Far East languages. */
484fa2c1 162int w32_enable_unicode_output;
cabb23bc 163
e9e23e23
GV
164DWORD dwWindowsThreadId = 0;
165HANDLE hWindowsThread = NULL;
ee78dc32
GV
166DWORD dwMainThreadId = 0;
167HANDLE hMainThread = NULL;
168
689004fa
GV
169#ifndef SIF_ALL
170/* These definitions are new with Windows 95. */
171#define SIF_RANGE 0x0001
172#define SIF_PAGE 0x0002
173#define SIF_POS 0x0004
174#define SIF_DISABLENOSCROLL 0x0008
175#define SIF_TRACKPOS 0x0010
176#define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
177
178typedef struct tagSCROLLINFO
179{
180 UINT cbSize;
181 UINT fMask;
182 int nMin;
183 int nMax;
184 UINT nPage;
185 int nPos;
186 int nTrackPos;
187} SCROLLINFO, FAR *LPSCROLLINFO;
188typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
189#endif /* SIF_ALL */
190
191/* Dynamic linking to new proportional scroll bar functions. */
192int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
193BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
194
195int vertical_scroll_bar_min_handle;
196int vertical_scroll_bar_top_border;
197int vertical_scroll_bar_bottom_border;
198
199int last_scroll_bar_drag_pos;
200
ee78dc32
GV
201/* Mouse movement. */
202
203/* Where the mouse was last time we reported a mouse event. */
9ef2e2cf 204
791f420f 205FRAME_PTR last_mouse_frame;
ee78dc32 206static RECT last_mouse_glyph;
791f420f 207static Lisp_Object last_mouse_press_frame;
ee78dc32 208
fbd6baed 209Lisp_Object Vw32_num_mouse_buttons;
52cf03a1 210
fbd6baed 211Lisp_Object Vw32_swap_mouse_buttons;
52cf03a1 212
689004fa
GV
213/* Control whether x_raise_frame also sets input focus. */
214Lisp_Object Vw32_grab_focus_on_raise;
215
216/* Control whether Caps Lock affects non-ascii characters. */
217Lisp_Object Vw32_capslock_is_shiftlock;
218
ef0e360f
GV
219/* Control whether right-alt and left-ctrl should be recognized as AltGr. */
220Lisp_Object Vw32_recognize_altgr;
221
ee78dc32
GV
222/* The scroll bar in which the last motion event occurred.
223
224 If the last motion event occurred in a scroll bar, we set this
fbd6baed 225 so w32_mouse_position can know whether to report a scroll bar motion or
ee78dc32
GV
226 an ordinary motion.
227
228 If the last motion event didn't occur in a scroll bar, we set this
fbd6baed 229 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
9ef2e2cf
JR
230static Lisp_Object last_mouse_scroll_bar;
231static int last_mouse_scroll_bar_pos;
ee78dc32 232
fbd6baed 233/* This is a hack. We would really prefer that w32_mouse_position would
ee78dc32 234 return the time associated with the position it returns, but there
9ef2e2cf 235 doesn't seem to be any way to wrest the time-stamp from the server
ee78dc32
GV
236 along with the position query. So, we just keep track of the time
237 of the last movement we received, and return that in hopes that
238 it's somewhat accurate. */
ee78dc32 239
9ef2e2cf
JR
240static Time last_mouse_movement_time;
241
242/* Incremented by w32_read_socket whenever it really tries to read
243 events. */
a1b9438c 244
ee78dc32
GV
245#ifdef __STDC__
246static int volatile input_signal_count;
247#else
248static int input_signal_count;
249#endif
250
251extern Lisp_Object Vcommand_line_args, Vsystem_name;
252
253extern Lisp_Object Qface, Qmouse_face;
254
38006079 255#ifndef USE_CRT_DLL
ee78dc32 256extern int errno;
38006079 257#endif
ee78dc32
GV
258
259/* A mask of extra modifier bits to put into every keyboard char. */
9ef2e2cf 260
31ade731 261extern EMACS_INT extra_keyboard_modifiers;
ee78dc32 262
38006079 263static void x_update_window_end P_ ((struct window *, int, int));
791f420f
JR
264static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
265void w32_delete_display P_ ((struct w32_display_info *));
266static int fast_find_position P_ ((struct window *, int, int *, int *,
9f5a911b
JR
267 int *, int *, Lisp_Object));
268static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
269 int *, int *, int *, int *, int));
791f420f
JR
270static void set_output_cursor P_ ((struct cursor_pos *));
271static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
9f5a911b 272 int *, int *, int *, int));
a18bb28d
JR
273static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
274 int, int));
791f420f
JR
275static void note_mouse_highlight P_ ((struct frame *, int, int));
276static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
277static void w32_handle_tool_bar_click P_ ((struct frame *,
278 struct input_event *));
279static void show_mouse_face P_ ((struct w32_display_info *,
280 enum draw_glyphs_face));
9f5a911b
JR
281static int cursor_in_mouse_face_p P_ ((struct window *));
282static int clear_mouse_face P_ ((struct w32_display_info *));
2bf04b9d 283void w32_define_cursor P_ ((Window, Cursor));
791f420f
JR
284
285void x_lower_frame P_ ((struct frame *));
286void x_scroll_bar_clear P_ ((struct frame *));
287void x_wm_set_size_hint P_ ((struct frame *, long, int));
288void x_raise_frame P_ ((struct frame *));
289void x_set_window_size P_ ((struct frame *, int, int, int));
290void x_wm_set_window_state P_ ((struct frame *, int));
291void x_wm_set_icon_pixmap P_ ((struct frame *, int));
292void w32_initialize P_ ((void));
293static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
294int x_compute_min_glyph_bounds P_ ((struct frame *));
295static void x_draw_phys_cursor_glyph P_ ((struct window *,
296 struct glyph_row *,
297 enum draw_glyphs_face));
298static void x_update_end P_ ((struct frame *));
299static void w32_frame_up_to_date P_ ((struct frame *));
791f420f
JR
300static void w32_set_terminal_modes P_ ((void));
301static void w32_reset_terminal_modes P_ ((void));
302static void w32_cursor_to P_ ((int, int, int, int));
303static void x_write_glyphs P_ ((struct glyph *, int));
304static void x_clear_end_of_line P_ ((int));
305static void x_clear_frame P_ ((void));
306static void x_clear_cursor P_ ((struct window *));
307static void frame_highlight P_ ((struct frame *));
308static void frame_unhighlight P_ ((struct frame *));
73dc743c
JR
309static void x_new_focus_frame P_ ((struct w32_display_info *,
310 struct frame *));
791f420f
JR
311static void w32_frame_rehighlight P_ ((struct frame *));
312static void x_frame_rehighlight P_ ((struct w32_display_info *));
313static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
70fa9f1f
JR
314static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
315 enum text_cursor_kinds));
791f420f 316static void expose_frame P_ ((struct frame *, int, int, int, int));
9f5a911b 317static int expose_window_tree P_ ((struct window *, RECT *));
95f2448c
RS
318static void expose_overlaps P_ ((struct window *, struct glyph_row *,
319 struct glyph_row *));
9f5a911b 320static int expose_window P_ ((struct window *, RECT *));
791f420f
JR
321static void expose_area P_ ((struct window *, struct glyph_row *,
322 RECT *, enum glyph_row_area));
9f5a911b
JR
323static int expose_line P_ ((struct window *, struct glyph_row *,
324 RECT *));
791f420f
JR
325void x_update_cursor P_ ((struct frame *, int));
326static void x_update_cursor_in_window_tree P_ ((struct window *, int));
327static void x_update_window_cursor P_ ((struct window *, int));
328static void x_erase_phys_cursor P_ ((struct window *));
329void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
330void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
c2cc16fa
JR
331static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
332 HDC, int));
791f420f 333static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
791f420f 334
ee78dc32
GV
335static Lisp_Object Qvendor_specific_keysyms;
336
ee78dc32 337\f
9ef2e2cf
JR
338/***********************************************************************
339 Debugging
340 ***********************************************************************/
341
ee78dc32 342#if 0
9ef2e2cf
JR
343
344/* This is a function useful for recording debugging information about
345 the sequence of occurrences in this file. */
ee78dc32 346
d67d1627 347struct record
ee78dc32
GV
348{
349 char *locus;
350 int type;
351};
352
353struct record event_record[100];
354
355int event_record_index;
356
357record_event (locus, type)
358 char *locus;
359 int type;
360{
361 if (event_record_index == sizeof (event_record) / sizeof (struct record))
362 event_record_index = 0;
363
364 event_record[event_record_index].locus = locus;
365 event_record[event_record_index].type = type;
366 event_record_index++;
367}
368
369#endif /* 0 */
370\f
791f420f
JR
371
372void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
373 XGCValues *xgcv)
374{
375 if (mask & GCForeground)
376 gc->foreground = xgcv->foreground;
377 if (mask & GCBackground)
378 gc->background = xgcv->background;
379 if (mask & GCFont)
380 gc->font = xgcv->font;
381}
382
383XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
384 XGCValues *xgcv)
385{
386 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
387 bzero (gc, sizeof (XGCValues));
388
389 XChangeGC (ignore, gc, mask, xgcv);
390
391 return gc;
392}
393
394void XGetGCValues (void* ignore, XGCValues *gc,
395 unsigned long mask, XGCValues *xgcv)
396{
397 XChangeGC (ignore, xgcv, mask, gc);
398}
399
791f420f
JR
400static void
401w32_set_clip_rectangle (HDC hdc, RECT *rect)
402{
403 if (rect)
404 {
405 HRGN clip_region = CreateRectRgnIndirect (rect);
406 SelectClipRgn (hdc, clip_region);
407 DeleteObject (clip_region);
408 }
409 else
410 SelectClipRgn (hdc, NULL);
411}
412
791f420f
JR
413
414/* Draw a hollow rectangle at the specified position. */
415void
416w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
417 int width, int height)
418{
419 HBRUSH hb, oldhb;
420 HPEN hp, oldhp;
421
422 hb = CreateSolidBrush (gc->background);
423 hp = CreatePen (PS_SOLID, 0, gc->foreground);
424 oldhb = SelectObject (hdc, hb);
425 oldhp = SelectObject (hdc, hp);
426
427 Rectangle (hdc, x, y, x + width, y + height);
428
429 SelectObject (hdc, oldhb);
430 SelectObject (hdc, oldhp);
431 DeleteObject (hb);
432 DeleteObject (hp);
433}
434
435/* Draw a filled rectangle at the specified position. */
d67d1627 436void
00fe468b 437w32_fill_rect (f, hdc, pix, lprect)
ee78dc32 438 FRAME_PTR f;
00fe468b 439 HDC hdc;
ee78dc32
GV
440 COLORREF pix;
441 RECT * lprect;
442{
ee78dc32 443 HBRUSH hb;
791f420f 444
ee78dc32 445 hb = CreateSolidBrush (pix);
ee78dc32 446 FillRect (hdc, lprect, hb);
ee78dc32 447 DeleteObject (hb);
ee78dc32
GV
448}
449
d67d1627 450void
fbd6baed 451w32_clear_window (f)
ee78dc32
GV
452 FRAME_PTR f;
453{
454 RECT rect;
00fe468b 455 HDC hdc = get_frame_dc (f);
52cf03a1 456
e4a52412
JR
457 /* Under certain conditions, this can be called at startup with
458 a console frame pointer before the GUI frame is created. An HDC
459 of 0 indicates this. */
460 if (hdc)
461 {
462 GetClientRect (FRAME_W32_WINDOW (f), &rect);
463 w32_clear_rect (f, hdc, &rect);
464 }
465
00fe468b 466 release_frame_dc (f, hdc);
ee78dc32
GV
467}
468
469\f
791f420f
JR
470/***********************************************************************
471 Starting and ending an update
472 ***********************************************************************/
d67d1627 473
791f420f
JR
474/* Start an update of frame F. This function is installed as a hook
475 for update_begin, i.e. it is called when update_begin is called.
476 This function is called prior to calls to x_update_window_begin for
99012074 477 each window being updated. */
ee78dc32 478
96214669 479static void
791f420f 480x_update_begin (f)
ee78dc32
GV
481 struct frame *f;
482{
99012074
AI
483 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
484
7e6ac5b9
AI
485 if (! FRAME_W32_P (f))
486 return;
487
99012074
AI
488 /* Regenerate display palette before drawing if list of requested
489 colors has changed. */
490 if (display_info->regen_palette)
491 {
492 w32_regenerate_palette (f);
493 display_info->regen_palette = FALSE;
494 }
791f420f 495}
ee78dc32 496
791f420f
JR
497
498/* Start update of window W. Set the global variable updated_window
499 to the window being updated and set output_cursor to the cursor
500 position of W. */
501
502static void
503x_update_window_begin (w)
504 struct window *w;
505{
506 struct frame *f = XFRAME (WINDOW_FRAME (w));
507 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
508
99558ce8 509 /* Hide the system caret during an update. */
9785d95b
BK
510 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
511 {
512 SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
513 }
99558ce8 514
791f420f
JR
515 updated_window = w;
516 set_output_cursor (&w->cursor);
ee78dc32
GV
517
518 BLOCK_INPUT;
519
791f420f 520 if (f == display_info->mouse_face_mouse_frame)
ee78dc32
GV
521 {
522 /* Don't do highlighting for mouse motion during the update. */
791f420f 523 display_info->mouse_face_defer = 1;
ee78dc32 524
9ef2e2cf
JR
525 /* If F needs to be redrawn, simply forget about any prior mouse
526 highlighting. */
ee78dc32 527 if (FRAME_GARBAGED_P (f))
791f420f
JR
528 display_info->mouse_face_window = Qnil;
529
ec48c3a7
JR
530#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
531 their mouse_face_p flag set, which means that they are always
532 unequal to rows in a desired matrix which never have that
533 flag set. So, rows containing mouse-face glyphs are never
534 scrolled, and we don't have to switch the mouse highlight off
535 here to prevent it from being scrolled. */
d67d1627 536
791f420f
JR
537 /* Can we tell that this update does not affect the window
538 where the mouse highlight is? If so, no need to turn off.
539 Likewise, don't do anything if the frame is garbaged;
540 in that case, the frame's current matrix that we would use
541 is all wrong, and we will redisplay that line anyway. */
542 if (!NILP (display_info->mouse_face_window)
543 && w == XWINDOW (display_info->mouse_face_window))
ee78dc32 544 {
791f420f 545 int i;
ee78dc32 546
791f420f
JR
547 for (i = 0; i < w->desired_matrix->nrows; ++i)
548 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
ee78dc32
GV
549 break;
550
791f420f
JR
551 if (i < w->desired_matrix->nrows)
552 clear_mouse_face (display_info);
ee78dc32 553 }
ec48c3a7 554#endif /* 0 */
ee78dc32
GV
555 }
556
557 UNBLOCK_INPUT;
558}
559
791f420f
JR
560
561/* Draw a vertical window border to the right of window W if W doesn't
562 have vertical scroll bars. */
563
96214669 564static void
791f420f
JR
565x_draw_vertical_border (w)
566 struct window *w;
ee78dc32 567{
791f420f 568 struct frame *f = XFRAME (WINDOW_FRAME (w));
d67d1627 569
791f420f
JR
570 /* Redraw borders between horizontally adjacent windows. Don't
571 do it for frames with vertical scroll bars because either the
572 right scroll bar of a window, or the left scroll bar of its
573 neighbor will suffice as a border. */
574 if (!WINDOW_RIGHTMOST_P (w)
575 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
576 {
577 RECT r;
00fe468b 578 HDC hdc;
ee78dc32 579
9f5a911b
JR
580 window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
581 (int *) &r.right, (int *) &r.bottom);
33c34bea 582 r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
791f420f
JR
583 r.right = r.left + 1;
584 r.bottom -= 1;
ee78dc32 585
00fe468b 586 hdc = get_frame_dc (f);
e4a52412 587 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
00fe468b 588 release_frame_dc (f, hdc);
791f420f
JR
589 }
590}
ee78dc32 591
d67d1627 592
ec48c3a7
JR
593/* End update of window W (which is equal to updated_window).
594
595 Draw vertical borders between horizontally adjacent windows, and
596 display W's cursor if CURSOR_ON_P is non-zero.
597
598 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
599 glyphs in mouse-face were overwritten. In that case we have to
600 make sure that the mouse-highlight is properly redrawn.
601
602 W may be a menu bar pseudo-window in case we don't have X toolkit
603 support. Such windows don't have a cursor, so don't display it
604 here. */
791f420f
JR
605
606static void
ec48c3a7 607x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
791f420f 608 struct window *w;
ec48c3a7 609 int cursor_on_p, mouse_face_overwritten_p;
791f420f 610{
9f5a911b
JR
611 struct w32_display_info *dpyinfo
612 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
613
791f420f
JR
614 if (!w->pseudo_window_p)
615 {
616 BLOCK_INPUT;
ec48c3a7 617
791f420f
JR
618 if (cursor_on_p)
619 x_display_and_set_cursor (w, 1, output_cursor.hpos,
620 output_cursor.vpos,
621 output_cursor.x, output_cursor.y);
d67d1627 622
791f420f
JR
623 x_draw_vertical_border (w);
624 UNBLOCK_INPUT;
625 }
9f5a911b
JR
626
627 /* If a row with mouse-face was overwritten, arrange for
628 XTframe_up_to_date to redisplay the mouse highlight. */
629 if (mouse_face_overwritten_p)
630 {
631 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
632 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
633 dpyinfo->mouse_face_window = Qnil;
634 }
635
99558ce8
JR
636 /* Unhide the caret. This won't actually show the cursor, unless it
637 was visible before the corresponding call to HideCaret in
638 x_update_window_begin. */
9785d95b
BK
639 if (w32_use_visible_system_caret && w32_system_caret_hwnd)
640 {
641 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
642 }
99558ce8 643
791f420f
JR
644 updated_window = NULL;
645}
646
9ef2e2cf
JR
647
648/* End update of frame F. This function is installed as a hook in
649 update_end. */
650
791f420f
JR
651static void
652x_update_end (f)
653 struct frame *f;
654{
7e6ac5b9
AI
655 if (! FRAME_W32_P (f))
656 return;
657
791f420f
JR
658 /* Mouse highlight may be displayed again. */
659 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
ee78dc32
GV
660}
661
9ef2e2cf 662
791f420f
JR
663/* This function is called from various places in xdisp.c whenever a
664 complete update has been performed. The global variable
665 updated_window is not available here. */
ee78dc32 666
96214669 667static void
fbd6baed 668w32_frame_up_to_date (f)
791f420f 669 struct frame *f;
ee78dc32 670{
791f420f 671 if (FRAME_W32_P (f))
ee78dc32 672 {
791f420f
JR
673 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
674 if (dpyinfo->mouse_face_deferred_gc
675 || f == dpyinfo->mouse_face_mouse_frame)
676 {
677 BLOCK_INPUT;
678 if (dpyinfo->mouse_face_mouse_frame)
679 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
680 dpyinfo->mouse_face_mouse_x,
681 dpyinfo->mouse_face_mouse_y);
682 dpyinfo->mouse_face_deferred_gc = 0;
683 UNBLOCK_INPUT;
684 }
ee78dc32
GV
685 }
686}
791f420f
JR
687
688
689/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
33c34bea 690 arrow bitmaps, or clear the fringes if no bitmaps are required
791f420f 691 before DESIRED_ROW is made current. The window being updated is
b71b8111 692 found in updated_window. This function is called from
791f420f
JR
693 update_window_line only if it is known that there are differences
694 between bitmaps to be drawn between current row and DESIRED_ROW. */
695
696static void
697x_after_update_window_line (desired_row)
698 struct glyph_row *desired_row;
699{
700 struct window *w = updated_window;
6ff3e5e3
JR
701 struct frame *f;
702 int width, height;
703
791f420f 704 xassert (w);
d67d1627 705
791f420f
JR
706 if (!desired_row->mode_line_p && !w->pseudo_window_p)
707 {
708 BLOCK_INPUT;
b6ae1532 709 draw_row_fringe_bitmaps (w, desired_row);
6ff3e5e3
JR
710 UNBLOCK_INPUT;
711 }
791f420f 712
6ff3e5e3
JR
713 /* When a window has disappeared, make sure that no rest of
714 full-width rows stays visible in the internal border. Could
715 check here if updated_window is the leftmost/rightmost window,
716 but I guess it's not worth doing since vertically split windows
717 are almost never used, internal border is rarely set, and the
718 overhead is very small. */
719 if (windows_or_buffers_changed
720 && desired_row->full_width_p
721 && (f = XFRAME (w->frame),
722 width = FRAME_INTERNAL_BORDER_WIDTH (f),
723 width != 0)
724 && (height = desired_row->visible_height,
725 height > 0))
726 {
727 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
728 /* Internal border is drawn below the tool bar. */
729 if (WINDOWP (f->tool_bar_window)
730 && w == XWINDOW (f->tool_bar_window))
731 y -= width;
732
733 BLOCK_INPUT;
734 {
735 HDC hdc = get_frame_dc (f);
736 w32_clear_area (f, hdc, 0, y, width, height);
737 w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
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;
760
761 hdc = get_frame_dc (f);
791f420f
JR
762
763 /* Must clip because of partially visible lines. */
764 w32_clip_to_row (w, row, hdc, 1);
765
b6ae1532 766 if (p->bx >= 0)
791f420f 767 {
d33c49e8 768 w32_fill_area (f, hdc, face->background,
b6ae1532 769 p->bx, p->by, p->nx, p->ny);
d33c49e8
KS
770 }
771
b6ae1532
KS
772 if (p->which != NO_FRINGE_BITMAP)
773 {
774 HBITMAP pixmap = fringe_bmp[p->which];
775 HDC compat_hdc;
776 HANDLE horig_obj;
791f420f 777
b6ae1532
KS
778 compat_hdc = CreateCompatibleDC (hdc);
779 SaveDC (hdc);
791f420f 780
b6ae1532
KS
781 horig_obj = SelectObject (compat_hdc, pixmap);
782 SetTextColor (hdc, face->background);
783 SetBkColor (hdc, face->foreground);
fccb8288 784
b6ae1532
KS
785 BitBlt (hdc, p->x, p->y, p->wd, p->h,
786 compat_hdc, 0, p->dh,
787 SRCCOPY);
791f420f 788
b6ae1532
KS
789 SelectObject (compat_hdc, horig_obj);
790 DeleteDC (compat_hdc);
791 RestoreDC (hdc, -1);
d33c49e8 792 }
791f420f 793
b6ae1532 794 w32_set_clip_rectangle (hdc, NULL);
791f420f 795
791f420f
JR
796 release_frame_dc (f, hdc);
797}
798
ee78dc32 799\f
9ef2e2cf
JR
800/* This is called when starting Emacs and when restarting after
801 suspend. When starting Emacs, no window is mapped. And nothing
802 must be done to Emacs's own window if it is suspended (though that
803 rarely happens). */
ee78dc32 804
96214669
GV
805static void
806w32_set_terminal_modes (void)
ee78dc32
GV
807{
808}
809
9ef2e2cf
JR
810/* This is called when exiting or suspending Emacs. Exiting will make
811 the W32 windows go away, and suspending requires no action. */
ee78dc32 812
96214669
GV
813static void
814w32_reset_terminal_modes (void)
ee78dc32
GV
815{
816}
791f420f 817
9ef2e2cf 818
ee78dc32 819\f
791f420f
JR
820/***********************************************************************
821 Output Cursor
822 ***********************************************************************/
823
824/* Set the global variable output_cursor to CURSOR. All cursor
825 positions are relative to updated_window. */
9ef2e2cf 826
791f420f
JR
827static void
828set_output_cursor (cursor)
829 struct cursor_pos *cursor;
830{
831 output_cursor.hpos = cursor->hpos;
832 output_cursor.vpos = cursor->vpos;
833 output_cursor.x = cursor->x;
834 output_cursor.y = cursor->y;
835}
836
837
838/* Set a nominal cursor position.
839
840 HPOS and VPOS are column/row positions in a window glyph matrix. X
841 and Y are window text area relative pixel positions.
d67d1627 842
791f420f
JR
843 If this is done during an update, updated_window will contain the
844 window that is being updated and the position is the future output
845 cursor position for that window. If updated_window is null, use
846 selected_window and display the cursor at the given position. */
ee78dc32 847
96214669 848static void
791f420f
JR
849w32_cursor_to (vpos, hpos, y, x)
850 int vpos, hpos, y, x;
ee78dc32 851{
791f420f 852 struct window *w;
ee78dc32 853
791f420f
JR
854 /* If updated_window is not set, work on selected_window. */
855 if (updated_window)
856 w = updated_window;
857 else
858 w = XWINDOW (selected_window);
859
860 /* Set the output cursor. */
861 output_cursor.hpos = hpos;
862 output_cursor.vpos = vpos;
863 output_cursor.x = x;
864 output_cursor.y = y;
ee78dc32 865
791f420f
JR
866 /* If not called as part of an update, really display the cursor.
867 This will also set the cursor position of W. */
868 if (updated_window == NULL)
ee78dc32
GV
869 {
870 BLOCK_INPUT;
791f420f 871 x_display_cursor (w, 1, hpos, vpos, x, y);
ee78dc32
GV
872 UNBLOCK_INPUT;
873 }
874}
791f420f 875
9ef2e2cf 876
ee78dc32 877\f
791f420f
JR
878/***********************************************************************
879 Display Iterator
880 ***********************************************************************/
881
882/* Function prototypes of this page. */
883
82f9d565 884static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
6b6bd726
KS
885 wchar_t *, int));
886static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
cabb23bc 887
791f420f
JR
888
889/* Get metrics of character CHAR2B in FONT. Value is always non-null.
890 If CHAR2B is not contained in FONT, the font's default character
9ef2e2cf 891 metric is returned. */
791f420f 892
82f9d565
AI
893static int
894w32_bdf_per_char_metric (font, char2b, dim, pcm)
9127e20e
JR
895 XFontStruct *font;
896 wchar_t *char2b;
897 int dim;
82f9d565 898 XCharStruct * pcm;
9127e20e
JR
899{
900 glyph_metric * bdf_metric;
901 char buf[2];
9127e20e
JR
902
903 if (dim == 1)
4b99045f 904 buf[0] = (char)(*char2b);
9127e20e
JR
905 else
906 {
6b6bd726
KS
907 buf[0] = XCHAR2B_BYTE1 (char2b);
908 buf[1] = XCHAR2B_BYTE2 (char2b);
9127e20e
JR
909 }
910
911 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
912
913 if (bdf_metric)
914 {
915 pcm->width = bdf_metric->dwidth;
916 pcm->lbearing = bdf_metric->bbox;
917 pcm->rbearing = bdf_metric->dwidth
918 - (bdf_metric->bbox + bdf_metric->bbw);
919 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
00c96995 920 pcm->descent = -bdf_metric->bboy;
82f9d565
AI
921
922 return 1;
9127e20e 923 }
82f9d565 924 return 0;
9127e20e
JR
925}
926
927
82f9d565
AI
928static int
929w32_native_per_char_metric (font, char2b, font_type, pcm)
791f420f
JR
930 XFontStruct *font;
931 wchar_t *char2b;
9ef2e2cf 932 enum w32_char_font_type font_type;
82f9d565 933 XCharStruct * pcm;
cabb23bc 934{
82f9d565
AI
935 HDC hdc = GetDC (NULL);
936 HFONT old_font;
937 BOOL retval = FALSE;
cabb23bc 938
791f420f 939 xassert (font && char2b);
82f9d565
AI
940 xassert (font->hfont);
941 xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
cabb23bc 942
82f9d565 943 old_font = SelectObject (hdc, font->hfont);
791f420f 944
dfaaaafb 945 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
791f420f 946 {
dfaaaafb
AI
947 ABC char_widths;
948
949 if (font_type == UNICODE_FONT)
950 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
82f9d565 951 else
dfaaaafb
AI
952 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
953
954 if (retval)
955 {
f6dd0c50
JR
956#if 0
957 /* Disabled until we can find a way to get the right results
958 on all versions of Windows. */
959
73dc743c
JR
960 /* Don't trust the ABC widths. For synthesized fonts they are
961 wrong, and so is the result of GetCharWidth()! */
962 int real_width;
963 GetCharWidth (hdc, *char2b, *char2b, &real_width);
f6dd0c50 964#endif
dfaaaafb 965 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
f6dd0c50 966#if 0
73dc743c
JR
967 /* As far as I can tell, this is the best way to determine what
968 ExtTextOut will do with the broken font. */
969 if (pcm->width != real_width)
970 pcm->width = (pcm->width + real_width) / 2;
f6dd0c50 971#endif
dfaaaafb 972 pcm->lbearing = char_widths.abcA;
73dc743c 973 pcm->rbearing = char_widths.abcA + char_widths.abcB;
82f9d565
AI
974 pcm->ascent = FONT_BASE (font);
975 pcm->descent = FONT_DESCENT (font);
dfaaaafb 976 }
791f420f 977 }
82f9d565
AI
978
979 if (!retval)
791f420f 980 {
82f9d565
AI
981 /* Either font is not a True-type font, or GetCharABCWidthsW
982 failed (it is not supported on Windows 9x for instance), so we
983 can't determine the full info we would like. All is not lost
984 though - we can call GetTextExtentPoint32 to get rbearing and
985 deduce width based on the font's per-string overhang. lbearing
986 is assumed to be zero. */
01b220b6
JR
987
988 /* TODO: Some Thai characters (and other composites if Windows
989 supports them) do have lbearing, and report their total width
990 as zero. Need some way of handling them when
991 GetCharABCWidthsW fails. */
82f9d565
AI
992 SIZE sz;
993
994 if (font_type == UNICODE_FONT)
995 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
996 else
997 retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
791f420f
JR
998
999 if (retval)
dfaaaafb 1000 {
82f9d565
AI
1001 pcm->width = sz.cx - font->tm.tmOverhang;
1002 pcm->rbearing = sz.cx;
dfaaaafb 1003 pcm->lbearing = 0;
82f9d565
AI
1004 pcm->ascent = FONT_BASE (font);
1005 pcm->descent = FONT_DESCENT (font);
dfaaaafb 1006 }
791f420f
JR
1007 }
1008
791f420f 1009
93ff4395
JR
1010 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1011 {
82f9d565 1012 retval = FALSE;
93ff4395
JR
1013 }
1014
82f9d565
AI
1015 SelectObject (hdc, old_font);
1016 ReleaseDC (NULL, hdc);
1017
1018 return retval;
1019}
1020
1021
1022static XCharStruct *
1023w32_per_char_metric (font, char2b, font_type)
1024 XFontStruct *font;
1025 wchar_t *char2b;
6b6bd726 1026 int /* enum w32_char_font_type */ font_type;
82f9d565
AI
1027{
1028 /* The result metric information. */
1029 XCharStruct *pcm;
1030 BOOL retval;
1031
1032 xassert (font && char2b);
1033 xassert (font_type != UNKNOWN_FONT);
1034
1035 /* Handle the common cases quickly. */
4b99045f 1036 if (!font->bdf && font->per_char == NULL)
82f9d565
AI
1037 /* TODO: determine whether char2b exists in font? */
1038 return &font->max_bounds;
4b99045f 1039 else if (!font->bdf && *char2b < 128)
82f9d565
AI
1040 return &font->per_char[*char2b];
1041
1042 pcm = &font->scratch;
1043
1044 if (font_type == BDF_1D_FONT)
1045 retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
1046 else if (font_type == BDF_2D_FONT)
1047 retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
1048 else
1049 retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
1050
1051 if (retval)
1052 return pcm;
1053
1054 return NULL;
1055}
1056
1057void
1058w32_cache_char_metrics (font)
1059 XFontStruct *font;
1060{
1061 wchar_t char2b = L'x';
1062
1063 /* Cache char metrics for the common cases. */
1064 if (font->bdf)
1065 {
1066 /* TODO: determine whether font is fixed-pitch. */
00c96995
JR
1067 if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
1068 {
1069 /* Use the font width and height as max bounds, as not all BDF
1070 fonts contain the letter 'x'. */
1071 font->max_bounds.width = FONT_MAX_WIDTH (font);
1072 font->max_bounds.lbearing = -font->bdf->llx;
1073 font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
1074 font->max_bounds.ascent = FONT_BASE (font);
1075 font->max_bounds.descent = FONT_DESCENT (font);
1076 }
82f9d565
AI
1077 }
1078 else
1079 {
f1eed8ff
JR
1080 if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
1081 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1082 though they contain characters of different widths. */
1083 || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
82f9d565
AI
1084 {
1085 /* Font is not fixed pitch, so cache per_char info for the
1086 ASCII characters. It would be much more work, and probably
1087 not worth it, to cache other chars, since we may change
1088 between using Unicode and ANSI text drawing functions at
1089 run-time. */
1090 int i;
1091
1092 font->per_char = xmalloc (128 * sizeof(XCharStruct));
1093 for (i = 0; i < 128; i++)
1094 {
1095 char2b = i;
1096 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1097 &font->per_char[i]);
1098 }
1099 }
1100 else
1101 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1102 &font->max_bounds);
1103 }
791f420f
JR
1104}
1105
1106
9ef2e2cf
JR
1107/* Determine if a font is double byte. */
1108int w32_font_is_double_byte (XFontStruct *font)
1109{
1110 return font->double_byte_p;
1111}
1112
1113
d67d1627 1114static BOOL
d6ff54d5
JR
1115w32_use_unicode_for_codepage (codepage)
1116 int codepage;
1117{
1118 /* If the current codepage is supported, use Unicode for output. */
1119 return (w32_enable_unicode_output
1120 && codepage != CP_8BIT
1121 && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
1122}
1123
791f420f
JR
1124/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1125 the two-byte form of C. Encoding is returned in *CHAR2B. */
1126
6b6bd726 1127static int /* enum w32_char_font_type */
9ef2e2cf 1128w32_encode_char (c, char2b, font_info, two_byte_p)
791f420f
JR
1129 int c;
1130 wchar_t *char2b;
1131 struct font_info *font_info;
9ef2e2cf 1132 int * two_byte_p;
791f420f
JR
1133{
1134 int charset = CHAR_CHARSET (c);
1135 int codepage;
9ef2e2cf
JR
1136 int unicode_p = 0;
1137
791f420f
JR
1138 XFontStruct *font = font_info->font;
1139
9127e20e 1140 xassert (two_byte_p);
9ef2e2cf 1141
6b6bd726
KS
1142 if (two_byte_p)
1143 *two_byte_p = w32_font_is_double_byte (font);
9ef2e2cf 1144
791f420f
JR
1145 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1146 This may be either a program in a special encoder language or a
1147 fixed encoding. */
1148 if (font_info->font_encoder)
1149 {
1150 /* It's a program. */
1151 struct ccl_program *ccl = font_info->font_encoder;
1152
1153 if (CHARSET_DIMENSION (charset) == 1)
1154 {
1155 ccl->reg[0] = charset;
6b6bd726 1156 ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
2bf04b9d 1157 ccl->reg[2] = -1;
791f420f
JR
1158 }
1159 else
1160 {
1161 ccl->reg[0] = charset;
6b6bd726
KS
1162 ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
1163 ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
791f420f
JR
1164 }
1165
1166 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1167
1168 /* We assume that MSBs are appropriately set/reset by CCL
1169 program. */
9ef2e2cf 1170 if (!*two_byte_p) /* 1-byte font */
6b6bd726 1171 STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
791f420f 1172 else
6b6bd726 1173 STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
791f420f
JR
1174 }
1175 else if (font_info->encoding[charset])
1176 {
1177 /* Fixed encoding scheme. See fontset.h for the meaning of the
1178 encoding numbers. */
1179 int enc = font_info->encoding[charset];
d67d1627 1180
791f420f
JR
1181 if ((enc == 1 || enc == 2)
1182 && CHARSET_DIMENSION (charset) == 2)
6b6bd726 1183 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
d67d1627 1184
791f420f
JR
1185 if (enc == 1 || enc == 3
1186 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
6b6bd726 1187 STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
791f420f
JR
1188 else if (enc == 4)
1189 {
1190 int sjis1, sjis2;
1191
6b6bd726 1192 ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
791f420f 1193 sjis1, sjis2);
6b6bd726 1194 STORE_XCHAR2B (char2b, sjis1, sjis2);
791f420f
JR
1195 }
1196 }
0e804d38 1197 codepage = font_info->codepage;
791f420f
JR
1198
1199 /* If charset is not ASCII or Latin-1, may need to move it into
1200 Unicode space. */
1201 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
49be9f70
JR
1202 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
1203 && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
791f420f
JR
1204 {
1205 char temp[3];
6b6bd726
KS
1206 temp[0] = XCHAR2B_BYTE1 (char2b);
1207 temp[1] = XCHAR2B_BYTE2 (char2b);
791f420f 1208 temp[2] = '\0';
02f593f3
JR
1209 if (codepage != CP_UNICODE)
1210 {
1211 if (temp[0])
1212 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1213 else
1214 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1215 }
9ef2e2cf
JR
1216 unicode_p = 1;
1217 *two_byte_p = 1;
1218 }
1219 if (!font)
1220 return UNKNOWN_FONT;
9127e20e
JR
1221 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1222 return BDF_1D_FONT;
9ef2e2cf 1223 else if (font->bdf)
9127e20e 1224 return BDF_2D_FONT;
9ef2e2cf
JR
1225 else if (unicode_p)
1226 return UNICODE_FONT;
1227 else
1228 return ANSI_FONT;
791f420f
JR
1229}
1230
1231
791f420f
JR
1232/* Estimate the pixel height of the mode or top line on frame F.
1233 FACE_ID specifies what line's height to estimate. */
1234
1235int
1236x_estimate_mode_line_height (f, face_id)
1237 struct frame *f;
1238 enum face_id face_id;
1239{
250cfece 1240 int height = FONT_HEIGHT (FRAME_FONT (f));
791f420f
JR
1241
1242 /* This function is called so early when Emacs starts that the face
1243 cache and mode line face are not yet initialized. */
1244 if (FRAME_FACE_CACHE (f))
1245 {
1246 struct face *face = FACE_FROM_ID (f, face_id);
9ef2e2cf 1247 if (face)
250cfece
JR
1248 {
1249 if (face->font)
1250 height = FONT_HEIGHT (face->font);
60222d69
AI
1251 if (face->box_line_width > 0)
1252 height += 2 * face->box_line_width;
250cfece 1253 }
791f420f 1254 }
d67d1627 1255
791f420f
JR
1256 return height;
1257}
cabb23bc 1258
cabb23bc 1259\f
791f420f
JR
1260/***********************************************************************
1261 Glyph display
1262 ***********************************************************************/
1263
791f420f 1264
9ef2e2cf 1265/* Encapsulate the different ways of displaying text under W32. */
791f420f 1266
1cb8c82e
JR
1267static void
1268w32_text_out (s, x, y,chars,nchars)
791f420f
JR
1269 struct glyph_string * s;
1270 int x, y;
1271 wchar_t * chars;
1272 int nchars;
1273{
9ef2e2cf 1274 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
791f420f
JR
1275 if (s->gc->font->bdf)
1276 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
00c96995
JR
1277 x, y, (char *) chars, charset_dim,
1278 nchars * charset_dim, 0);
6b6bd726 1279 else if (s->first_glyph->font_type == UNICODE_FONT)
791f420f
JR
1280 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
1281 else
1cb8c82e
JR
1282 ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
1283 nchars * charset_dim, NULL);
791f420f
JR
1284}
1285
6b6bd726
KS
1286
1287
791f420f
JR
1288static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1289static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1290static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1291 int));
1292static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1293static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
791f420f
JR
1294static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1295static void x_draw_glyph_string P_ ((struct glyph_string *));
791f420f
JR
1296static void x_set_cursor_gc P_ ((struct glyph_string *));
1297static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1298static void x_set_mouse_face_gc P_ ((struct glyph_string *));
791f420f
JR
1299static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
1300static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
1301 double, int, COLORREF));
1302static void x_setup_relief_colors P_ ((struct glyph_string *));
1303static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1304static void x_draw_image_relief P_ ((struct glyph_string *));
1305static void x_draw_image_foreground P_ ((struct glyph_string *));
1306static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
791f420f
JR
1307static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1308 int, int, int));
1309static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1310 int, int, int, int, RECT *));
1311static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1312 int, int, int, RECT *));
1313static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
1314 enum glyph_row_area));
c2cc16fa
JR
1315
1316#if GLYPH_DEBUG
1317static void x_check_font P_ ((struct frame *, XFontStruct *));
1318#endif
791f420f 1319
d67d1627 1320
791f420f
JR
1321/* Set S->gc to a suitable GC for drawing glyph string S in cursor
1322 face. */
1323
1324static void
1325x_set_cursor_gc (s)
1326 struct glyph_string *s;
1327{
1328 if (s->font == FRAME_FONT (s->f)
1329 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1330 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1331 && !s->cmp)
1332 s->gc = s->f->output_data.w32->cursor_gc;
1333 else
1334 {
1335 /* Cursor on non-default face: must merge. */
1336 XGCValues xgcv;
1337 unsigned long mask;
1338
1339 xgcv.background = s->f->output_data.w32->cursor_pixel;
1340 xgcv.foreground = s->face->background;
1341
1342 /* If the glyph would be invisible, try a different foreground. */
1343 if (xgcv.foreground == xgcv.background)
1344 xgcv.foreground = s->face->foreground;
1345 if (xgcv.foreground == xgcv.background)
1346 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
1347 if (xgcv.foreground == xgcv.background)
1348 xgcv.foreground = s->face->foreground;
1349
1350 /* Make sure the cursor is distinct from text in this face. */
1351 if (xgcv.background == s->face->background
1352 && xgcv.foreground == s->face->foreground)
1353 {
1354 xgcv.background = s->face->foreground;
1355 xgcv.foreground = s->face->background;
1356 }
1357
1358 IF_DEBUG (x_check_font (s->f, s->font));
1359 xgcv.font = s->font;
1360 mask = GCForeground | GCBackground | GCFont;
1361
1362 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1363 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1364 mask, &xgcv);
1365 else
1366 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1367 = XCreateGC (NULL, s->window, mask, &xgcv);
1368
1369 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1370 }
1371}
1372
1373
1374/* Set up S->gc of glyph string S for drawing text in mouse face. */
d67d1627 1375
791f420f
JR
1376static void
1377x_set_mouse_face_gc (s)
1378 struct glyph_string *s;
d67d1627 1379{
791f420f 1380 int face_id;
93ff4395 1381 struct face *face;
791f420f 1382
c2cc16fa 1383 /* What face has to be used last for the mouse face? */
791f420f 1384 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
93ff4395 1385 face = FACE_FROM_ID (s->f, face_id);
c2cc16fa
JR
1386 if (face == NULL)
1387 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
d67d1627 1388
c2cc16fa
JR
1389 if (s->first_glyph->type == CHAR_GLYPH)
1390 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1391 else
1392 face_id = FACE_FOR_CHAR (s->f, face, 0);
791f420f
JR
1393 s->face = FACE_FROM_ID (s->f, face_id);
1394 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1395
1396 /* If font in this face is same as S->font, use it. */
1397 if (s->font == s->face->font)
1398 s->gc = s->face->gc;
1399 else
1400 {
1401 /* Otherwise construct scratch_cursor_gc with values from FACE
1402 but font FONT. */
1403 XGCValues xgcv;
1404 unsigned long mask;
d67d1627 1405
791f420f
JR
1406 xgcv.background = s->face->background;
1407 xgcv.foreground = s->face->foreground;
1408 IF_DEBUG (x_check_font (s->f, s->font));
1409 xgcv.font = s->font;
1410 mask = GCForeground | GCBackground | GCFont;
d67d1627 1411
791f420f
JR
1412 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1413 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1414 mask, &xgcv);
1415 else
1416 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
1417 = XCreateGC (NULL, s->window, mask, &xgcv);
d67d1627 1418
791f420f
JR
1419 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1420 }
1421
1422 xassert (s->gc != 0);
1423}
1424
1425
1426/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1427 Faces to use in the mode line have already been computed when the
1428 matrix was built, so there isn't much to do, here. */
1429
1430static INLINE void
1431x_set_mode_line_face_gc (s)
1432 struct glyph_string *s;
d67d1627 1433{
791f420f 1434 s->gc = s->face->gc;
791f420f
JR
1435}
1436
1437
1438/* Set S->gc of glyph string S for drawing that glyph string. Set
1439 S->stippled_p to a non-zero value if the face of S has a stipple
1440 pattern. */
1441
1442static INLINE void
1443x_set_glyph_string_gc (s)
1444 struct glyph_string *s;
1445{
ec48c3a7 1446 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
d67d1627 1447
791f420f
JR
1448 if (s->hl == DRAW_NORMAL_TEXT)
1449 {
1450 s->gc = s->face->gc;
1451 s->stippled_p = s->face->stipple != 0;
1452 }
1453 else if (s->hl == DRAW_INVERSE_VIDEO)
1454 {
1455 x_set_mode_line_face_gc (s);
1456 s->stippled_p = s->face->stipple != 0;
1457 }
1458 else if (s->hl == DRAW_CURSOR)
1459 {
1460 x_set_cursor_gc (s);
1461 s->stippled_p = 0;
1462 }
1463 else if (s->hl == DRAW_MOUSE_FACE)
1464 {
1465 x_set_mouse_face_gc (s);
1466 s->stippled_p = s->face->stipple != 0;
1467 }
1468 else if (s->hl == DRAW_IMAGE_RAISED
1469 || s->hl == DRAW_IMAGE_SUNKEN)
1470 {
1471 s->gc = s->face->gc;
1472 s->stippled_p = s->face->stipple != 0;
1473 }
1474 else
1475 {
1476 s->gc = s->face->gc;
1477 s->stippled_p = s->face->stipple != 0;
1478 }
1479
1480 /* GC must have been set. */
1481 xassert (s->gc != 0);
1482}
1483
1484
1485/* Return in *R the clipping rectangle for glyph string S. */
1486
1487static void
1488w32_get_glyph_string_clip_rect (s, r)
1489 struct glyph_string *s;
1490 RECT *r;
1491{
1492 int r_height, r_width;
1493
1494 if (s->row->full_width_p)
1495 {
1496 /* Draw full-width. X coordinates are relative to S->w->left. */
1497 int canon_x = CANON_X_UNIT (s->f);
d67d1627 1498
791f420f
JR
1499 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
1500 r_width = XFASTINT (s->w->width) * canon_x;
1501
1502 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
1503 {
1504 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
1505 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
1506 r->left -= width;
1507 }
d67d1627 1508
791f420f
JR
1509 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1510
1511 /* Unless displaying a mode or menu bar line, which are always
1512 fully visible, clip to the visible part of the row. */
1513 if (s->w->pseudo_window_p)
1514 r_height = s->row->visible_height;
1515 else
1516 r_height = s->height;
1517 }
1518 else
1519 {
1520 /* This is a text line that may be partially visible. */
1521 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
1522 r_width = window_box_width (s->w, s->area);
1523 r_height = s->row->visible_height;
1524 }
1525
791f420f
JR
1526 /* If S draws overlapping rows, it's sufficient to use the top and
1527 bottom of the window for clipping because this glyph string
1528 intentionally draws over other lines. */
1529 if (s->for_overlaps_p)
1530 {
1531 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1532 r_height = window_text_bottom_y (s->w) - r->top;
1533 }
9f5a911b
JR
1534 else
1535 {
1536 /* Don't use S->y for clipping because it doesn't take partially
1537 visible lines into account. For example, it can be negative for
1538 partially visible lines at the top of a window. */
1539 if (!s->row->full_width_p
1540 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
1541 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1542 else
1543 r->top = max (0, s->row->y);
1544
1545 /* If drawing a tool-bar window, draw it over the internal border
1546 at the top of the window. */
1547 if (s->w == XWINDOW (s->f->tool_bar_window))
1548 r->top -= s->f->output_data.w32->internal_border_width;
1549 }
1550
791f420f
JR
1551 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
1552
2c26ee51
JR
1553 /* If drawing the cursor, don't let glyph draw outside its
1554 advertised boundaries. Cleartype does this under some circumstances. */
1555 if (s->hl == DRAW_CURSOR)
1556 {
1557 if (s->x > r->left)
1558 {
1559 r_width -= s->x - r->left;
1560 r->left = s->x;
1561 }
1562 r_width = min (r_width, s->first_glyph->pixel_width);
1563 }
1564
791f420f
JR
1565 r->bottom = r->top + r_height;
1566 r->right = r->left + r_width;
1567}
1568
1569
1570/* Set clipping for output of glyph string S. S may be part of a mode
1571 line or menu if we don't have X toolkit support. */
1572
1573static INLINE void
1574x_set_glyph_string_clipping (s)
1575 struct glyph_string *s;
1576{
1577 RECT r;
1578 w32_get_glyph_string_clip_rect (s, &r);
1579 w32_set_clip_rectangle (s->hdc, &r);
1580}
1581
1582
6b6bd726
KS
1583/* RIF:
1584 Compute left and right overhang of glyph string S. If S is a glyph
791f420f
JR
1585 string for a composition, assume overhangs don't exist. */
1586
6b6bd726
KS
1587static void
1588w32_compute_glyph_string_overhangs (s)
791f420f
JR
1589 struct glyph_string *s;
1590{
01b220b6 1591 /* TODO: Windows does not appear to have a method for
158cba56
JR
1592 getting this info without getting the ABC widths for each
1593 individual character and working it out manually. */
791f420f
JR
1594}
1595
1596
791f420f 1597static void
6b6bd726 1598w32_get_glyph_overhangs (glyph, f, left, right)
791f420f
JR
1599 struct glyph *glyph;
1600 struct frame *f;
1601 int *left, *right;
1602{
1603 HDC hdc = get_frame_dc (f);
9ef2e2cf 1604 /* Convert to unicode! */
6b6bd726 1605 x_get_glyph_overhangs (glyph, f, left, right);
791f420f
JR
1606 release_frame_dc (f, hdc);
1607}
1608
1609
791f420f
JR
1610/* Fill rectangle X, Y, W, H with background color of glyph string S. */
1611
1612static INLINE void
1613x_clear_glyph_string_rect (s, x, y, w, h)
1614 struct glyph_string *s;
1615 int x, y, w, h;
1616{
1617 int real_x = x;
1618 int real_y = y;
1619 int real_w = w;
1620 int real_h = h;
1621#if 0
1622 /* Take clipping into account. */
1623 if (s->gc->clip_mask == Rect)
1624 {
1625 real_x = max (real_x, s->gc->clip_rectangle.left);
1626 real_y = max (real_y, s->gc->clip_rectangle.top);
1627 real_w = min (real_w, s->gc->clip_rectangle.right
1628 - s->gc->clip_rectangle.left);
1629 real_h = min (real_h, s->gc->clip_rectangle.bottom
1630 - s->gc->clip_rectangle.top);
1631 }
1632#endif
1633 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
1634 real_w, real_h);
1635}
1636
1637
1638/* Draw the background of glyph_string S. If S->background_filled_p
1639 is non-zero don't draw it. FORCE_P non-zero means draw the
1640 background even if it wouldn't be drawn normally. This is used
1641 when a string preceding S draws into the background of S, or S
1642 contains the first component of a composition. */
1643
1644static void
1645x_draw_glyph_string_background (s, force_p)
1646 struct glyph_string *s;
1647 int force_p;
1648{
1649 /* Nothing to do if background has already been drawn or if it
1650 shouldn't be drawn in the first place. */
1651 if (!s->background_filled_p)
1652 {
60222d69
AI
1653 int box_line_width = max (s->face->box_line_width, 0);
1654
01b220b6 1655#if 0 /* TODO: stipple */
791f420f
JR
1656 if (s->stippled_p)
1657 {
1658 /* Fill background with a stipple pattern. */
1659 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1660 XFillRectangle (s->display, s->window, s->gc, s->x,
60222d69 1661 s->y + box_line_width,
791f420f 1662 s->background_width,
60222d69 1663 s->height - 2 * box_line_width);
791f420f
JR
1664 XSetFillStyle (s->display, s->gc, FillSolid);
1665 s->background_filled_p = 1;
1666 }
1667 else
1668#endif
60222d69 1669 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
791f420f
JR
1670 || s->font_not_found_p
1671 || s->extends_to_end_of_line_p
9127e20e 1672 || s->font->bdf
791f420f
JR
1673 || force_p)
1674 {
60222d69 1675 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
791f420f 1676 s->background_width,
60222d69 1677 s->height - 2 * box_line_width);
791f420f
JR
1678 s->background_filled_p = 1;
1679 }
1680 }
1681}
1682
1683
1684/* Draw the foreground of glyph string S. */
1685
1686static void
1687x_draw_glyph_string_foreground (s)
1688 struct glyph_string *s;
1689{
1690 int i, x;
01b220b6 1691 HFONT old_font;
791f420f
JR
1692
1693 /* If first glyph of S has a left box line, start drawing the text
1694 of S to the right of that box line. */
1695 if (s->face->box != FACE_NO_BOX
1696 && s->first_glyph->left_box_line_p)
60222d69 1697 x = s->x + abs (s->face->box_line_width);
791f420f
JR
1698 else
1699 x = s->x;
1700
1701 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
1702 SetBkMode (s->hdc, TRANSPARENT);
1703 else
1704 SetBkMode (s->hdc, OPAQUE);
1705
1706 SetTextColor (s->hdc, s->gc->foreground);
1707 SetBkColor (s->hdc, s->gc->background);
1708 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1709
1710 if (s->font && s->font->hfont)
01b220b6 1711 old_font = SelectObject (s->hdc, s->font->hfont);
791f420f
JR
1712
1713 /* Draw characters of S as rectangles if S's font could not be
1714 loaded. */
1715 if (s->font_not_found_p)
1716 {
1717 for (i = 0; i < s->nchars; ++i)
1718 {
1719 struct glyph *g = s->first_glyph + i;
1720
1721 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
1722 s->height - 1);
1723 x += g->pixel_width;
1724 }
1725 }
1726 else
1727 {
1728 char *char1b = (char *) s->char2b;
1729 int boff = s->font_info->baseline_offset;
1730
1731 if (s->font_info->vertical_centering)
1732 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
1733
1734 /* If we can use 8-bit functions, condense S->char2b. */
1735 if (!s->two_byte_p)
1736 for (i = 0; i < s->nchars; ++i)
6b6bd726 1737 char1b[i] = XCHAR2B_BYTE2 (&s->char2b[i]);
791f420f
JR
1738
1739 /* Draw text with TextOut and friends. */
1cb8c82e 1740 w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
a18bb28d
JR
1741
1742 if (s->face->overstrike)
1743 {
1744 /* For overstriking (to simulate bold-face), draw the
1745 characters again shifted to the right by one pixel. */
1746 w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
1747 }
791f420f 1748 }
01b220b6
JR
1749 if (s->font && s->font->hfont)
1750 SelectObject (s->hdc, old_font);
791f420f
JR
1751}
1752
1753/* Draw the foreground of composite glyph string S. */
1754
1755static void
1756x_draw_composite_glyph_string_foreground (s)
1757 struct glyph_string *s;
1758{
1759 int i, x;
01b220b6 1760 HFONT old_font;
791f420f
JR
1761
1762 /* If first glyph of S has a left box line, start drawing the text
1763 of S to the right of that box line. */
1764 if (s->face->box != FACE_NO_BOX
1765 && s->first_glyph->left_box_line_p)
60222d69 1766 x = s->x + abs (s->face->box_line_width);
791f420f
JR
1767 else
1768 x = s->x;
1769
1770 /* S is a glyph string for a composition. S->gidx is the index of
1771 the first character drawn for glyphs of this composition.
1772 S->gidx == 0 means we are drawing the very first character of
1773 this composition. */
1774
1775 SetTextColor (s->hdc, s->gc->foreground);
1776 SetBkColor (s->hdc, s->gc->background);
1777 SetBkMode (s->hdc, TRANSPARENT);
1778 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
1779
01b220b6
JR
1780 if (s->font && s->font->hfont)
1781 old_font = SelectObject (s->hdc, s->font->hfont);
1782
791f420f
JR
1783 /* Draw a rectangle for the composition if the font for the very
1784 first character of the composition could not be loaded. */
1785 if (s->font_not_found_p)
1786 {
1787 if (s->gidx == 0)
1788 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
1789 s->height - 1);
1790 }
1791 else
1792 {
1793 for (i = 0; i < s->nchars; i++, ++s->gidx)
a18bb28d
JR
1794 {
1795 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
1796 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1797 s->char2b + i, 1);
1798 if (s->face->overstrike)
1799 w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
1800 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1801 s->char2b + i, 1);
1802 }
791f420f 1803 }
a18bb28d 1804
01b220b6
JR
1805 if (s->font && s->font->hfont)
1806 SelectObject (s->hdc, old_font);
791f420f
JR
1807}
1808
e5fa381b
JR
1809
1810/* Brightness beyond which a color won't have its highlight brightness
1811 boosted.
1812
1813 Nominally, highlight colors for `3d' faces are calculated by
1814 brightening an object's color by a constant scale factor, but this
1815 doesn't yield good results for dark colors, so for colors who's
1816 brightness is less than this value (on a scale of 0-255) have to
1817 use an additional additive factor.
1818
1819 The value here is set so that the default menu-bar/mode-line color
1820 (grey75) will not have its highlights changed at all. */
1821#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
1822
1823
791f420f
JR
1824/* Allocate a color which is lighter or darker than *COLOR by FACTOR
1825 or DELTA. Try a color with RGB values multiplied by FACTOR first.
1826 If this produces the same color as COLOR, try a color where all RGB
1827 values have DELTA added. Return the allocated color in *COLOR.
1828 DISPLAY is the X display, CMAP is the colormap to operate on.
1829 Value is non-zero if successful. */
1830
1831static int
1832w32_alloc_lighter_color (f, color, factor, delta)
1833 struct frame *f;
1834 COLORREF *color;
1835 double factor;
1836 int delta;
1837{
1838 COLORREF new;
e5fa381b
JR
1839 long bright;
1840
1841 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
1842 delta /= 256;
791f420f
JR
1843
1844 /* Change RGB values by specified FACTOR. Avoid overflow! */
1845 xassert (factor >= 0);
1846 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
1847 min (0xff, factor * GetGValue (*color)),
1848 min (0xff, factor * GetBValue (*color)));
e5fa381b
JR
1849
1850 /* Calculate brightness of COLOR. */
1851 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
1852 + GetBValue (*color)) / 6;
1853
1854 /* We only boost colors that are darker than
1855 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
1856 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
1857 /* Make an additive adjustment to NEW, because it's dark enough so
1858 that scaling by FACTOR alone isn't enough. */
1859 {
1860 /* How far below the limit this color is (0 - 1, 1 being darker). */
1861 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
1862 /* The additive adjustment. */
1863 int min_delta = delta * dimness * factor / 2;
d67d1627 1864
e5fa381b
JR
1865 if (factor < 1)
1866 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
1867 max (0, min (0xff, min_delta - GetGValue (*color))),
1868 max (0, min (0xff, min_delta - GetBValue (*color))));
1869 else
1870 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
1871 max (0, min (0xff, min_delta + GetGValue (*color))),
1872 max (0, min (0xff, min_delta + GetBValue (*color))));
1873 }
d67d1627 1874
791f420f
JR
1875 if (new == *color)
1876 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
1877 max (0, min (0xff, delta + GetGValue (*color))),
1878 max (0, min (0xff, delta + GetBValue (*color))));
1879
01b220b6
JR
1880 /* TODO: Map to palette and retry with delta if same? */
1881 /* TODO: Free colors (if using palette)? */
93ff4395 1882
791f420f
JR
1883 if (new == *color)
1884 return 0;
1885
1886 *color = new;
1887
1888 return 1;
1889}
1890
1891
1892/* Set up the foreground color for drawing relief lines of glyph
1893 string S. RELIEF is a pointer to a struct relief containing the GC
1894 with which lines will be drawn. Use a color that is FACTOR or
1895 DELTA lighter or darker than the relief's background which is found
1896 in S->f->output_data.x->relief_background. If such a color cannot
1897 be allocated, use DEFAULT_PIXEL, instead. */
d67d1627 1898
791f420f
JR
1899static void
1900w32_setup_relief_color (f, relief, factor, delta, default_pixel)
1901 struct frame *f;
1902 struct relief *relief;
1903 double factor;
1904 int delta;
1905 COLORREF default_pixel;
1906{
1907 XGCValues xgcv;
1908 struct w32_output *di = f->output_data.w32;
1909 unsigned long mask = GCForeground;
1910 COLORREF pixel;
1911 COLORREF background = di->relief_background;
1912 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
1913
01b220b6 1914 /* TODO: Free colors (if using palette)? */
93ff4395 1915
791f420f
JR
1916 /* Allocate new color. */
1917 xgcv.foreground = default_pixel;
1918 pixel = background;
1919 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
1920 {
1921 relief->allocated_p = 1;
1922 xgcv.foreground = relief->pixel = pixel;
1923 }
d67d1627 1924
791f420f
JR
1925 if (relief->gc == 0)
1926 {
01b220b6 1927#if 0 /* TODO: stipple */
791f420f
JR
1928 xgcv.stipple = dpyinfo->gray;
1929 mask |= GCStipple;
1930#endif
1931 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
1932 }
1933 else
1934 XChangeGC (NULL, relief->gc, mask, &xgcv);
1935}
1936
1937
1938/* Set up colors for the relief lines around glyph string S. */
1939
1940static void
1941x_setup_relief_colors (s)
1942 struct glyph_string *s;
1943{
1944 struct w32_output *di = s->f->output_data.w32;
1945 COLORREF color;
1946
1947 if (s->face->use_box_color_for_shadows_p)
1948 color = s->face->box_color;
6ff3e5e3 1949 else if (s->first_glyph->type == IMAGE_GLYPH
6637c996 1950 && s->img->pixmap
6ff3e5e3
JR
1951 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
1952 color = IMAGE_BACKGROUND (s->img, s->f, 0);
791f420f
JR
1953 else
1954 color = s->gc->background;
1955
1956 if (di->white_relief.gc == 0
1957 || color != di->relief_background)
1958 {
1959 di->relief_background = color;
1960 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
1961 WHITE_PIX_DEFAULT (s->f));
1962 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
1963 BLACK_PIX_DEFAULT (s->f));
1964 }
1965}
1966
1967
1968/* Draw a relief on frame F inside the rectangle given by LEFT_X,
1969 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
1970 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
1971 relief. LEFT_P non-zero means draw a relief on the left side of
1972 the rectangle. RIGHT_P non-zero means draw a relief on the right
1973 side of the rectangle. CLIP_RECT is the clipping rectangle to use
1974 when drawing. */
1975
1976static void
1977w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1978 raised_p, left_p, right_p, clip_rect)
1979 struct frame *f;
2bf04b9d 1980 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
791f420f
JR
1981 RECT *clip_rect;
1982{
1983 int i;
1984 XGCValues gc;
1985 HDC hdc = get_frame_dc (f);
1986
1987 if (raised_p)
e5fa381b 1988 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
791f420f 1989 else
e5fa381b 1990 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
791f420f
JR
1991
1992 w32_set_clip_rectangle (hdc, clip_rect);
1993
1994 /* Top. */
1995 for (i = 0; i < width; ++i)
9f5a911b
JR
1996 w32_fill_area (f, hdc, gc.foreground,
1997 left_x + i * left_p, top_y + i,
df3bd29d 1998 right_x - left_x - i * (left_p + right_p ) + 1, 1);
791f420f
JR
1999
2000 /* Left. */
2001 if (left_p)
2002 for (i = 0; i < width; ++i)
9f5a911b
JR
2003 w32_fill_area (f, hdc, gc.foreground,
2004 left_x + i, top_y + i, 1,
df3bd29d 2005 bottom_y - top_y - 2 * i + 1);
791f420f
JR
2006
2007 if (raised_p)
e5fa381b 2008 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
791f420f 2009 else
e5fa381b 2010 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
d67d1627 2011
791f420f
JR
2012 /* Bottom. */
2013 for (i = 0; i < width; ++i)
d67d1627 2014 w32_fill_area (f, hdc, gc.foreground,
9f5a911b 2015 left_x + i * left_p, bottom_y - i,
df3bd29d 2016 right_x - left_x - i * (left_p + right_p) + 1, 1);
791f420f
JR
2017
2018 /* Right. */
2019 if (right_p)
2020 for (i = 0; i < width; ++i)
9f5a911b
JR
2021 w32_fill_area (f, hdc, gc.foreground,
2022 right_x - i, top_y + i + 1, 1,
df3bd29d 2023 bottom_y - top_y - 2 * i - 1);
791f420f
JR
2024
2025 w32_set_clip_rectangle (hdc, NULL);
d67d1627 2026
791f420f
JR
2027 release_frame_dc (f, hdc);
2028}
2029
2030
2031/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2032 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2033 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2034 left side of the rectangle. RIGHT_P non-zero means draw a line
2035 on the right side of the rectangle. CLIP_RECT is the clipping
2036 rectangle to use when drawing. */
2037
2038static void
2039w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2040 left_p, right_p, clip_rect)
2041 struct glyph_string *s;
2042 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2043 RECT *clip_rect;
2044{
00fe468b 2045 w32_set_clip_rectangle (s->hdc, clip_rect);
d67d1627 2046
791f420f 2047 /* Top. */
00fe468b 2048 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 2049 left_x, top_y, right_x - left_x + 1, width);
791f420f
JR
2050
2051 /* Left. */
2052 if (left_p)
2053 {
00fe468b 2054 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 2055 left_x, top_y, width, bottom_y - top_y + 1);
791f420f 2056 }
d67d1627 2057
791f420f 2058 /* Bottom. */
00fe468b 2059 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 2060 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
d67d1627 2061
791f420f
JR
2062 /* Right. */
2063 if (right_p)
2064 {
00fe468b 2065 w32_fill_area (s->f, s->hdc, s->face->box_color,
2d0c0bd7 2066 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
791f420f
JR
2067 }
2068
00fe468b 2069 w32_set_clip_rectangle (s->hdc, NULL);
791f420f
JR
2070}
2071
2072
2073/* Draw a box around glyph string S. */
2074
2075static void
2076x_draw_glyph_string_box (s)
2077 struct glyph_string *s;
2078{
2079 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2080 int left_p, right_p;
2081 struct glyph *last_glyph;
2082 RECT clip_rect;
2083
2084 last_x = window_box_right (s->w, s->area);
2085 if (s->row->full_width_p
2086 && !s->w->pseudo_window_p)
2087 {
33c34bea 2088 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
791f420f
JR
2089 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
2090 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
2091 }
d67d1627 2092
791f420f
JR
2093 /* The glyph that may have a right box line. */
2094 last_glyph = (s->cmp || s->img
2095 ? s->first_glyph
2096 : s->first_glyph + s->nchars - 1);
2097
60222d69 2098 width = abs (s->face->box_line_width);
791f420f
JR
2099 raised_p = s->face->box == FACE_RAISED_BOX;
2100 left_x = s->x;
9f5a911b 2101 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
791f420f
JR
2102 ? last_x - 1
2103 : min (last_x, s->x + s->background_width) - 1));
2104 top_y = s->y;
2105 bottom_y = top_y + s->height - 1;
2106
2107 left_p = (s->first_glyph->left_box_line_p
2108 || (s->hl == DRAW_MOUSE_FACE
2109 && (s->prev == NULL
2110 || s->prev->hl != s->hl)));
2111 right_p = (last_glyph->right_box_line_p
2112 || (s->hl == DRAW_MOUSE_FACE
2113 && (s->next == NULL
2114 || s->next->hl != s->hl)));
d67d1627 2115
791f420f
JR
2116 w32_get_glyph_string_clip_rect (s, &clip_rect);
2117
2118 if (s->face->box == FACE_SIMPLE_BOX)
2119 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2120 left_p, right_p, &clip_rect);
2121 else
2122 {
2123 x_setup_relief_colors (s);
2124 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2125 width, raised_p, left_p, right_p, &clip_rect);
2126 }
2127}
2128
2129
2130/* Draw foreground of image glyph string S. */
2131
2132static void
2133x_draw_image_foreground (s)
2134 struct glyph_string *s;
2135{
2136 int x;
9ef2e2cf 2137 int y = s->ybase - image_ascent (s->img, s->face);
791f420f
JR
2138
2139 /* If first glyph of S has a left box line, start drawing it to the
2140 right of that line. */
2141 if (s->face->box != FACE_NO_BOX
2142 && s->first_glyph->left_box_line_p)
60222d69 2143 x = s->x + abs (s->face->box_line_width);
791f420f
JR
2144 else
2145 x = s->x;
2146
2147 /* If there is a margin around the image, adjust x- and y-position
2148 by that margin. */
d6ff54d5
JR
2149 x += s->img->hmargin;
2150 y += s->img->vmargin;
791f420f
JR
2151
2152 SaveDC (s->hdc);
2153
2154 if (s->img->pixmap)
2155 {
d30591dc
JR
2156 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2157 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2158 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2159 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2160 SetBkColor (compat_hdc, RGB (255, 255, 255));
2161 SetTextColor (s->hdc, RGB (0, 0, 0));
2162 x_set_glyph_string_clipping (s);
2163
791f420f
JR
2164 if (s->img->mask)
2165 {
d30591dc
JR
2166 HDC mask_dc = CreateCompatibleDC (s->hdc);
2167 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2168
2169 SetTextColor (s->hdc, RGB (255, 255, 255));
2170 SetBkColor (s->hdc, RGB (0, 0, 0));
2171
2172 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
4108c39d 2173 compat_hdc, 0, 0, SRCINVERT);
d30591dc
JR
2174 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
2175 mask_dc, 0, 0, SRCAND);
2176 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
4108c39d 2177 compat_hdc, 0, 0, SRCINVERT);
d30591dc
JR
2178
2179 SelectObject (mask_dc, mask_orig_obj);
2180 DeleteDC (mask_dc);
791f420f
JR
2181 }
2182 else
791f420f 2183 {
d30591dc
JR
2184 SetTextColor (s->hdc, s->gc->foreground);
2185 SetBkColor (s->hdc, s->gc->background);
2186
9436cdf9 2187 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
4108c39d 2188 compat_hdc, 0, 0, SRCCOPY);
791f420f
JR
2189
2190 /* When the image has a mask, we can expect that at
2191 least part of a mouse highlight or a block cursor will
2192 be visible. If the image doesn't have a mask, make
2193 a block cursor visible by drawing a rectangle around
2194 the image. I believe it's looking better if we do
2195 nothing here for mouse-face. */
2196 if (s->hl == DRAW_CURSOR)
c65eff23
KS
2197 {
2198 int r = s->img->relief;
2199 if (r < 0) r = -r;
2200 w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
2201 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2202 }
791f420f 2203 }
d30591dc
JR
2204
2205 w32_set_clip_rectangle (s->hdc, NULL);
2206 SelectObject (s->hdc, orig_brush);
2207 DeleteObject (fg_brush);
2208 SelectObject (compat_hdc, orig_obj);
2209 DeleteDC (compat_hdc);
791f420f
JR
2210 }
2211 else
2212 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
2213 s->img->height - 1);
ee78dc32 2214
791f420f
JR
2215 RestoreDC (s->hdc ,-1);
2216}
ee78dc32 2217
791f420f
JR
2218
2219
2220/* Draw a relief around the image glyph string S. */
2221
2222static void
2223x_draw_image_relief (s)
2224 struct glyph_string *s;
2225{
2226 int x0, y0, x1, y1, thick, raised_p;
2227 RECT r;
2228 int x;
9ef2e2cf 2229 int y = s->ybase - image_ascent (s->img, s->face);
d67d1627 2230
791f420f
JR
2231 /* If first glyph of S has a left box line, start drawing it to the
2232 right of that line. */
2233 if (s->face->box != FACE_NO_BOX
2234 && s->first_glyph->left_box_line_p)
60222d69 2235 x = s->x + abs (s->face->box_line_width);
791f420f
JR
2236 else
2237 x = s->x;
d67d1627 2238
791f420f
JR
2239 /* If there is a margin around the image, adjust x- and y-position
2240 by that margin. */
d6ff54d5
JR
2241 x += s->img->hmargin;
2242 y += s->img->vmargin;
d67d1627 2243
791f420f
JR
2244 if (s->hl == DRAW_IMAGE_SUNKEN
2245 || s->hl == DRAW_IMAGE_RAISED)
2246 {
6637c996 2247 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
791f420f
JR
2248 raised_p = s->hl == DRAW_IMAGE_RAISED;
2249 }
2250 else
ee78dc32 2251 {
791f420f
JR
2252 thick = abs (s->img->relief);
2253 raised_p = s->img->relief > 0;
2254 }
d67d1627 2255
791f420f
JR
2256 x0 = x - thick;
2257 y0 = y - thick;
2258 x1 = x + s->img->width + thick - 1;
2259 y1 = y + s->img->height + thick - 1;
d67d1627 2260
791f420f
JR
2261 x_setup_relief_colors (s);
2262 w32_get_glyph_string_clip_rect (s, &r);
2263 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2264}
ee78dc32 2265
791f420f
JR
2266
2267/* Draw the foreground of image glyph string S to PIXMAP. */
2268
2269static void
2270w32_draw_image_foreground_1 (s, pixmap)
2271 struct glyph_string *s;
2272 HBITMAP pixmap;
2273{
2274 HDC hdc = CreateCompatibleDC (s->hdc);
2275 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
2276 int x;
9ef2e2cf 2277 int y = s->ybase - s->y - image_ascent (s->img, s->face);
791f420f
JR
2278
2279 /* If first glyph of S has a left box line, start drawing it to the
2280 right of that line. */
2281 if (s->face->box != FACE_NO_BOX
2282 && s->first_glyph->left_box_line_p)
60222d69 2283 x = abs (s->face->box_line_width);
791f420f
JR
2284 else
2285 x = 0;
2286
2287 /* If there is a margin around the image, adjust x- and y-position
2288 by that margin. */
d6ff54d5
JR
2289 x += s->img->hmargin;
2290 y += s->img->vmargin;
791f420f
JR
2291
2292 if (s->img->pixmap)
2293 {
d30591dc
JR
2294 HDC compat_hdc = CreateCompatibleDC (hdc);
2295 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2296 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
2297 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
2298
791f420f
JR
2299 if (s->img->mask)
2300 {
d30591dc
JR
2301 HDC mask_dc = CreateCompatibleDC (hdc);
2302 HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
2303
2304 SetTextColor (hdc, RGB (0, 0, 0));
2305 SetBkColor (hdc, RGB (255, 255, 255));
2306 BitBlt (hdc, x, y, s->img->width, s->img->height,
2307 compat_hdc, 0, 0, SRCINVERT);
2308 BitBlt (hdc, x, y, s->img->width, s->img->height,
2309 mask_dc, 0, 0, SRCAND);
2310 BitBlt (hdc, x, y, s->img->width, s->img->height,
2311 compat_hdc, 0, 0, SRCINVERT);
2312
2313 SelectObject (mask_dc, mask_orig_obj);
2314 DeleteDC (mask_dc);
791f420f
JR
2315 }
2316 else
ef0e360f 2317 {
d30591dc
JR
2318 SetTextColor (hdc, s->gc->foreground);
2319 SetBkColor (hdc, s->gc->background);
2320
9436cdf9 2321 BitBlt (hdc, x, y, s->img->width, s->img->height,
4108c39d 2322 compat_hdc, 0, 0, SRCCOPY);
791f420f
JR
2323
2324 /* When the image has a mask, we can expect that at
2325 least part of a mouse highlight or a block cursor will
2326 be visible. If the image doesn't have a mask, make
2327 a block cursor visible by drawing a rectangle around
2328 the image. I believe it's looking better if we do
2329 nothing here for mouse-face. */
2330 if (s->hl == DRAW_CURSOR)
c65eff23
KS
2331 {
2332 int r = s->img->relief;
2333 if (r < 0) r = -r;
d30591dc 2334 w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
c65eff23
KS
2335 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2336 }
ef0e360f 2337 }
d30591dc
JR
2338
2339 SelectObject (hdc, orig_brush);
2340 DeleteObject (fg_brush);
2341 SelectObject (compat_hdc, orig_obj);
2342 DeleteDC (compat_hdc);
791f420f
JR
2343 }
2344 else
2345 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
2346 s->img->height - 1);
2347
2348 SelectObject (hdc, orig_hdc_obj);
2349 DeleteDC (hdc);
2350}
2351
2352
2353/* Draw part of the background of glyph string S. X, Y, W, and H
2354 give the rectangle to draw. */
2355
2356static void
2357x_draw_glyph_string_bg_rect (s, x, y, w, h)
2358 struct glyph_string *s;
2359 int x, y, w, h;
2360{
01b220b6 2361#if 0 /* TODO: stipple */
791f420f
JR
2362 if (s->stippled_p)
2363 {
2364 /* Fill background with a stipple pattern. */
2365 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2366 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2367 XSetFillStyle (s->display, s->gc, FillSolid);
2368 }
2369 else
2370#endif
2371 x_clear_glyph_string_rect (s, x, y, w, h);
2372}
2373
2374
d67d1627 2375/* Draw image glyph string S.
791f420f
JR
2376
2377 s->y
2378 s->x +-------------------------
2379 | s->face->box
2380 |
2381 | +-------------------------
d6ff54d5 2382 | | s->img->vmargin
791f420f
JR
2383 | |
2384 | | +-------------------
2385 | | | the image
cabb23bc 2386
791f420f
JR
2387 */
2388
2389static void
2390x_draw_image_glyph_string (s)
2391 struct glyph_string *s;
2392{
2393 int x, y;
60222d69
AI
2394 int box_line_hwidth = abs (s->face->box_line_width);
2395 int box_line_vwidth = max (s->face->box_line_width, 0);
791f420f
JR
2396 int height;
2397 HBITMAP pixmap = 0;
2398
60222d69 2399 height = s->height - 2 * box_line_vwidth;
791f420f
JR
2400
2401 /* Fill background with face under the image. Do it only if row is
2402 taller than image or if image has a clip mask to reduce
2403 flickering. */
2404 s->stippled_p = s->face->stipple != 0;
2405 if (height > s->img->height
d6ff54d5 2406 || s->img->hmargin
c2cc16fa 2407 || s->img->vmargin
791f420f 2408 || s->img->mask
791f420f
JR
2409 || s->img->pixmap == 0
2410 || s->width != s->background_width)
2411 {
60222d69
AI
2412 if (box_line_hwidth && s->first_glyph->left_box_line_p)
2413 x = s->x + box_line_hwidth;
791f420f
JR
2414 else
2415 x = s->x;
d67d1627 2416
60222d69 2417 y = s->y + box_line_vwidth;
d30591dc 2418#if 0 /* TODO: figure out if we need to do this on Windows. */
791f420f 2419 if (s->img->mask)
ee78dc32 2420 {
c2cc16fa
JR
2421 /* Create a pixmap as large as the glyph string. Fill it
2422 with the background color. Copy the image to it, using
2423 its mask. Copy the temporary pixmap to the display. */
791f420f
JR
2424 Screen *screen = FRAME_X_SCREEN (s->f);
2425 int depth = DefaultDepthOfScreen (screen);
2426
2427 /* Create a pixmap as large as the glyph string. */
2428 pixmap = XCreatePixmap (s->display, s->window,
2429 s->background_width,
2430 s->height, depth);
d67d1627 2431
791f420f
JR
2432 /* Don't clip in the following because we're working on the
2433 pixmap. */
2434 XSetClipMask (s->display, s->gc, None);
ee78dc32 2435
791f420f
JR
2436 /* Fill the pixmap with the background color/stipple. */
2437 if (s->stippled_p)
2438 {
2439 /* Fill background with a stipple pattern. */
2440 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2441 XFillRectangle (s->display, pixmap, s->gc,
2442 0, 0, s->background_width, s->height);
2443 XSetFillStyle (s->display, s->gc, FillSolid);
2444 }
ef0e360f 2445 else
791f420f
JR
2446 {
2447 XGCValues xgcv;
2448 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2449 &xgcv);
2450 XSetForeground (s->display, s->gc, xgcv.background);
2451 XFillRectangle (s->display, pixmap, s->gc,
2452 0, 0, s->background_width, s->height);
2453 XSetForeground (s->display, s->gc, xgcv.foreground);
2454 }
ee78dc32 2455 }
791f420f
JR
2456 else
2457#endif
791f420f 2458 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
d67d1627 2459
791f420f
JR
2460 s->background_filled_p = 1;
2461 }
ee78dc32 2462
791f420f
JR
2463 /* Draw the foreground. */
2464 if (pixmap != 0)
2465 {
2466 w32_draw_image_foreground_1 (s, pixmap);
2467 x_set_glyph_string_clipping (s);
ee78dc32 2468 {
791f420f
JR
2469 HDC compat_hdc = CreateCompatibleDC (s->hdc);
2470 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
2471 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
2472 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
2473
2474 SetTextColor (s->hdc, s->gc->foreground);
2475 SetBkColor (s->hdc, s->gc->background);
791f420f
JR
2476 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
2477 compat_hdc, 0, 0, SRCCOPY);
d30591dc 2478
791f420f
JR
2479 SelectObject (s->hdc, orig_brush);
2480 DeleteObject (fg_brush);
2481 SelectObject (compat_hdc, orig_obj);
2482 DeleteDC (compat_hdc);
2483 }
2484 DeleteObject (pixmap);
2485 pixmap = 0;
2486 }
2487 else
2488 x_draw_image_foreground (s);
ee78dc32 2489
791f420f
JR
2490 /* If we must draw a relief around the image, do it. */
2491 if (s->img->relief
2492 || s->hl == DRAW_IMAGE_RAISED
2493 || s->hl == DRAW_IMAGE_SUNKEN)
2494 x_draw_image_relief (s);
2495}
ee78dc32 2496
cabb23bc 2497
791f420f 2498/* Draw stretch glyph string S. */
cabb23bc 2499
791f420f
JR
2500static void
2501x_draw_stretch_glyph_string (s)
2502 struct glyph_string *s;
2503{
2504 xassert (s->first_glyph->type == STRETCH_GLYPH);
2505 s->stippled_p = s->face->stipple != 0;
65c4903c 2506
791f420f
JR
2507 if (s->hl == DRAW_CURSOR
2508 && !x_stretch_cursor_p)
2509 {
2510 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2511 as wide as the stretch glyph. */
2512 int width = min (CANON_X_UNIT (s->f), s->background_width);
cabb23bc 2513
791f420f
JR
2514 /* Draw cursor. */
2515 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
cabb23bc 2516
791f420f
JR
2517 /* Clear rest using the GC of the original non-cursor face. */
2518 if (width < s->background_width)
2519 {
2520 XGCValues *gc = s->face->gc;
2521 int x = s->x + width, y = s->y;
2522 int w = s->background_width - width, h = s->height;
2523 RECT r;
2524 HDC hdc = s->hdc;
9f5a911b
JR
2525
2526 if (s->row->mouse_face_p
2527 && cursor_in_mouse_face_p (s->w))
2528 {
2529 x_set_mouse_face_gc (s);
2530 gc = s->gc;
2531 }
2532 else
2533 gc = s->face->gc;
d67d1627 2534
791f420f
JR
2535 w32_get_glyph_string_clip_rect (s, &r);
2536 w32_set_clip_rectangle (hdc, &r);
2537
01b220b6 2538#if 0 /* TODO: stipple */
791f420f
JR
2539 if (s->face->stipple)
2540 {
2541 /* Fill background with a stipple pattern. */
2542 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2543 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2544 XSetFillStyle (s->display, gc, FillSolid);
2545 }
2546 else
2547#endif
2548 {
2549 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
2550 }
2551 }
2552 }
9f5a911b 2553 else if (!s->background_filled_p)
791f420f
JR
2554 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2555 s->height);
d67d1627 2556
791f420f
JR
2557 s->background_filled_p = 1;
2558}
cabb23bc 2559
cabb23bc 2560
791f420f
JR
2561/* Draw glyph string S. */
2562
2563static void
2564x_draw_glyph_string (s)
2565 struct glyph_string *s;
2566{
858a55c1
AI
2567 int relief_drawn_p = 0;
2568
791f420f
JR
2569 /* If S draws into the background of its successor, draw the
2570 background of the successor first so that S can draw into it.
2571 This makes S->next use XDrawString instead of XDrawImageString. */
2572 if (s->next && s->right_overhang && !s->for_overlaps_p)
2573 {
2574 xassert (s->next->img == NULL);
2575 x_set_glyph_string_gc (s->next);
2576 x_set_glyph_string_clipping (s->next);
2577 x_draw_glyph_string_background (s->next, 1);
2578 }
2579
2580 /* Set up S->gc, set clipping and draw S. */
2581 x_set_glyph_string_gc (s);
791f420f 2582
858a55c1
AI
2583 /* Draw relief (if any) in advance for char/composition so that the
2584 glyph string can be drawn over it. */
2585 if (!s->for_overlaps_p
2586 && s->face->box != FACE_NO_BOX
2587 && (s->first_glyph->type == CHAR_GLYPH
2588 || s->first_glyph->type == COMPOSITE_GLYPH))
2589
2590 {
9f5a911b 2591 x_set_glyph_string_clipping (s);
858a55c1
AI
2592 x_draw_glyph_string_background (s, 1);
2593 x_draw_glyph_string_box (s);
9f5a911b 2594 x_set_glyph_string_clipping (s);
858a55c1
AI
2595 relief_drawn_p = 1;
2596 }
9f5a911b
JR
2597 else
2598 x_set_glyph_string_clipping (s);
858a55c1 2599
791f420f
JR
2600 switch (s->first_glyph->type)
2601 {
2602 case IMAGE_GLYPH:
2603 x_draw_image_glyph_string (s);
2604 break;
2605
2606 case STRETCH_GLYPH:
2607 x_draw_stretch_glyph_string (s);
2608 break;
2609
2610 case CHAR_GLYPH:
2611 if (s->for_overlaps_p)
2612 s->background_filled_p = 1;
2613 else
2614 x_draw_glyph_string_background (s, 0);
2615 x_draw_glyph_string_foreground (s);
2616 break;
2617
2618 case COMPOSITE_GLYPH:
2619 if (s->for_overlaps_p || s->gidx > 0)
2620 s->background_filled_p = 1;
2621 else
2622 x_draw_glyph_string_background (s, 1);
2623 x_draw_composite_glyph_string_foreground (s);
2624 break;
2625
2626 default:
2627 abort ();
2628 }
2629
2630 if (!s->for_overlaps_p)
2631 {
2632 /* Draw underline. */
9ef2e2cf
JR
2633 if (s->face->underline_p
2634 && (s->font->bdf || !s->font->tm.tmUnderlined))
791f420f
JR
2635 {
2636 unsigned long h = 1;
2637 unsigned long dy = s->height - h;
2638
9f5a911b
JR
2639 /* TODO: Use font information for positioning and thickness
2640 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
791f420f
JR
2641 if (s->face->underline_defaulted_p)
2642 {
2643 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2644 s->y + dy, s->width, 1);
2645 }
2646 else
2647 {
2648 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2649 s->y + dy, s->width, 1);
2650 }
2651 }
2652
2653 /* Draw overline. */
2654 if (s->face->overline_p)
2655 {
2656 unsigned long dy = 0, h = 1;
2657
2658 if (s->face->overline_color_defaulted_p)
2659 {
2660 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
2661 s->y + dy, s->width, h);
2662 }
2663 else
2664 {
2665 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2666 s->y + dy, s->width, h);
2667 }
2668 }
2669
2670 /* Draw strike-through. */
9ef2e2cf
JR
2671 if (s->face->strike_through_p
2672 && (s->font->bdf || !s->font->tm.tmStruckOut))
791f420f
JR
2673 {
2674 unsigned long h = 1;
2675 unsigned long dy = (s->height - h) / 2;
2676
2677 if (s->face->strike_through_color_defaulted_p)
2678 {
2679 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
2680 s->width, h);
2681 }
2682 else
2683 {
2684 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
2685 s->y + dy, s->width, h);
2686 }
2687 }
2688
2689 /* Draw relief. */
858a55c1 2690 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
791f420f
JR
2691 x_draw_glyph_string_box (s);
2692 }
2693
2694 /* Reset clipping. */
2695 w32_set_clip_rectangle (s->hdc, NULL);
2696}
2697
2698
791f420f
JR
2699/* Fix the display of area AREA of overlapping row ROW in window W. */
2700
2701static void
2702x_fix_overlapping_area (w, row, area)
2703 struct window *w;
2704 struct glyph_row *row;
2705 enum glyph_row_area area;
2706{
2707 int i, x;
d67d1627 2708
791f420f 2709 BLOCK_INPUT;
d67d1627 2710
791f420f
JR
2711 if (area == LEFT_MARGIN_AREA)
2712 x = 0;
2713 else if (area == TEXT_AREA)
2714 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
2715 else
2716 x = (window_box_width (w, LEFT_MARGIN_AREA)
2717 + window_box_width (w, TEXT_AREA));
b1ae662f 2718
791f420f
JR
2719 for (i = 0; i < row->used[area];)
2720 {
2721 if (row->glyphs[area][i].overlaps_vertically_p)
ee78dc32 2722 {
791f420f 2723 int start = i, start_x = x;
ee78dc32 2724
791f420f
JR
2725 do
2726 {
2727 x += row->glyphs[area][i].pixel_width;
2728 ++i;
2729 }
2730 while (i < row->used[area]
2731 && row->glyphs[area][i].overlaps_vertically_p);
cabb23bc 2732
791f420f 2733 x_draw_glyphs (w, start_x, row, area, start, i,
6ff3e5e3 2734 DRAW_NORMAL_TEXT, 1);
791f420f
JR
2735 }
2736 else
2737 {
2738 x += row->glyphs[area][i].pixel_width;
2739 ++i;
2740 }
2741 }
d67d1627 2742
791f420f 2743 UNBLOCK_INPUT;
ee78dc32
GV
2744}
2745
ee78dc32 2746
791f420f
JR
2747/* Output LEN glyphs starting at START at the nominal cursor position.
2748 Advance the nominal cursor over the text. The global variable
2749 updated_window contains the window being updated, updated_row is
2750 the glyph row being updated, and updated_area is the area of that
2751 row being updated. */
ee78dc32 2752
96214669 2753static void
791f420f
JR
2754x_write_glyphs (start, len)
2755 struct glyph *start;
ee78dc32
GV
2756 int len;
2757{
6ff3e5e3 2758 int x, hpos;
ee78dc32 2759
791f420f 2760 xassert (updated_window && updated_row);
ee78dc32 2761 BLOCK_INPUT;
d67d1627 2762
791f420f 2763 /* Write glyphs. */
ee78dc32 2764
791f420f
JR
2765 hpos = start - updated_row->glyphs[updated_area];
2766 x = x_draw_glyphs (updated_window, output_cursor.x,
2767 updated_row, updated_area,
2768 hpos, hpos + len,
6ff3e5e3 2769 DRAW_NORMAL_TEXT, 0);
791f420f 2770
a18bb28d
JR
2771 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
2772 if (updated_area == TEXT_AREA
2773 && updated_window->phys_cursor_on_p
2774 && updated_window->phys_cursor.vpos == output_cursor.vpos
2775 && updated_window->phys_cursor.hpos >= hpos
2776 && updated_window->phys_cursor.hpos < hpos + len)
2777 updated_window->phys_cursor_on_p = 0;
2778
791f420f 2779 UNBLOCK_INPUT;
d67d1627 2780
791f420f
JR
2781 /* Advance the output cursor. */
2782 output_cursor.hpos += len;
2783 output_cursor.x = x;
2784}
ee78dc32 2785
ee78dc32 2786
791f420f 2787/* Insert LEN glyphs from START at the nominal cursor position. */
ee78dc32 2788
791f420f
JR
2789static void
2790x_insert_glyphs (start, len)
2791 struct glyph *start;
2792 register int len;
2793{
2794 struct frame *f;
2795 struct window *w;
2796 int line_height, shift_by_width, shifted_region_width;
2797 struct glyph_row *row;
2798 struct glyph *glyph;
6ff3e5e3 2799 int frame_x, frame_y, hpos;
791f420f
JR
2800 HDC hdc;
2801
2802 xassert (updated_window && updated_row);
2803 BLOCK_INPUT;
2804 w = updated_window;
2805 f = XFRAME (WINDOW_FRAME (w));
2806 hdc = get_frame_dc (f);
2807
2808 /* Get the height of the line we are in. */
2809 row = updated_row;
2810 line_height = row->height;
2811
2812 /* Get the width of the glyphs to insert. */
2813 shift_by_width = 0;
2814 for (glyph = start; glyph < start + len; ++glyph)
2815 shift_by_width += glyph->pixel_width;
2816
2817 /* Get the width of the region to shift right. */
2818 shifted_region_width = (window_box_width (w, updated_area)
2819 - output_cursor.x
2820 - shift_by_width);
2821
2822 /* Shift right. */
5b844253 2823 frame_x = window_box_left (w, updated_area) + output_cursor.x;
791f420f
JR
2824 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
2825 BitBlt (hdc, frame_x + shift_by_width, frame_y,
2826 shifted_region_width, line_height,
2827 hdc, frame_x, frame_y, SRCCOPY);
2828
2829 /* Write the glyphs. */
2830 hpos = start - row->glyphs[updated_area];
2831 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
6ff3e5e3
JR
2832 DRAW_NORMAL_TEXT, 0);
2833
791f420f
JR
2834 /* Advance the output cursor. */
2835 output_cursor.hpos += len;
2836 output_cursor.x += shift_by_width;
2837 release_frame_dc (f, hdc);
ee78dc32
GV
2838
2839 UNBLOCK_INPUT;
2840}
791f420f
JR
2841
2842
2843/* Delete N glyphs at the nominal cursor position. Not implemented
2844 for X frames. */
ee78dc32 2845
96214669 2846static void
791f420f
JR
2847x_delete_glyphs (n)
2848 register int n;
ee78dc32 2849{
7e6ac5b9
AI
2850 struct frame *f;
2851
2852 if (updating_frame)
2853 f = updating_frame;
2854 else
2855 f = SELECTED_FRAME ();
2856
2857 if (! FRAME_W32_P (f))
2858 return;
2859
791f420f
JR
2860 abort ();
2861}
ee78dc32 2862
ee78dc32 2863
791f420f
JR
2864/* Erase the current text line from the nominal cursor position
2865 (inclusive) to pixel column TO_X (exclusive). The idea is that
2866 everything from TO_X onward is already erased.
ee78dc32 2867
791f420f
JR
2868 TO_X is a pixel position relative to updated_area of
2869 updated_window. TO_X == -1 means clear to the end of this area. */
11606873 2870
791f420f
JR
2871static void
2872x_clear_end_of_line (to_x)
2873 int to_x;
2874{
2875 struct frame *f;
2876 struct window *w = updated_window;
2877 int max_x, min_y, max_y;
2878 int from_x, from_y, to_y;
d67d1627 2879
791f420f
JR
2880 xassert (updated_window && updated_row);
2881 f = XFRAME (w->frame);
d67d1627 2882
791f420f
JR
2883 if (updated_row->full_width_p)
2884 {
2885 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
2886 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2887 && !w->pseudo_window_p)
2888 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
2889 }
2890 else
2891 max_x = window_box_width (w, updated_area);
2892 max_y = window_text_bottom_y (w);
ee78dc32 2893
791f420f
JR
2894 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
2895 of window. For TO_X > 0, truncate to end of drawing area. */
2896 if (to_x == 0)
2897 return;
2898 else if (to_x < 0)
2899 to_x = max_x;
2900 else
2901 to_x = min (to_x, max_x);
ee78dc32 2902
791f420f 2903 to_y = min (max_y, output_cursor.y + updated_row->height);
d67d1627 2904
ee78dc32 2905 /* Notice if the cursor will be cleared by this operation. */
791f420f 2906 if (!updated_row->full_width_p)
6637c996
JR
2907 notice_overwritten_cursor (w, updated_area,
2908 output_cursor.x, -1,
2909 updated_row->y,
2910 MATRIX_ROW_BOTTOM_Y (updated_row));
ee78dc32 2911
791f420f 2912 from_x = output_cursor.x;
6637c996 2913
791f420f
JR
2914 /* Translate to frame coordinates. */
2915 if (updated_row->full_width_p)
2916 {
2917 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
2918 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
2919 }
2920 else
2921 {
2922 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
2923 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
2924 }
d67d1627 2925
791f420f
JR
2926 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
2927 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
2928 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
d67d1627 2929
791f420f
JR
2930 /* Prevent inadvertently clearing to end of the X window. */
2931 if (to_x > from_x && to_y > from_y)
2932 {
00fe468b 2933 HDC hdc;
791f420f 2934 BLOCK_INPUT;
00fe468b
JR
2935 hdc = get_frame_dc (f);
2936
2937 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
2938 release_frame_dc (f, hdc);
791f420f
JR
2939 UNBLOCK_INPUT;
2940 }
ee78dc32
GV
2941}
2942
791f420f
JR
2943
2944/* Clear entire frame. If updating_frame is non-null, clear that
2945 frame. Otherwise clear the selected frame. */
2946
96214669 2947static void
791f420f 2948x_clear_frame ()
ee78dc32 2949{
791f420f 2950 struct frame *f;
ee78dc32 2951
791f420f
JR
2952 if (updating_frame)
2953 f = updating_frame;
2954 else
2955 f = SELECTED_FRAME ();
ee78dc32 2956
7e6ac5b9
AI
2957 if (! FRAME_W32_P (f))
2958 return;
2959
791f420f
JR
2960 /* Clearing the frame will erase any cursor, so mark them all as no
2961 longer visible. */
2962 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2963 output_cursor.hpos = output_cursor.vpos = 0;
2964 output_cursor.x = -1;
ee78dc32 2965
791f420f
JR
2966 /* We don't set the output cursor here because there will always
2967 follow an explicit cursor_to. */
ee78dc32
GV
2968 BLOCK_INPUT;
2969
fbd6baed 2970 w32_clear_window (f);
ee78dc32
GV
2971
2972 /* We have to clear the scroll bars, too. If we have changed
2973 colors or something like that, then they should be notified. */
2974 x_scroll_bar_clear (f);
2975
2976 UNBLOCK_INPUT;
2977}
791f420f 2978
ee78dc32
GV
2979\f
2980/* Make audible bell. */
2981
96214669
GV
2982static void
2983w32_ring_bell (void)
ee78dc32 2984{
7e6ac5b9
AI
2985 struct frame *f;
2986
2987 f = SELECTED_FRAME ();
2988
ee78dc32
GV
2989 BLOCK_INPUT;
2990
0f32f023 2991 if (FRAME_W32_P (f) && visible_bell)
8331e676
GV
2992 {
2993 int i;
791f420f 2994 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
8331e676 2995
d67d1627 2996 for (i = 0; i < 5; i++)
8331e676
GV
2997 {
2998 FlashWindow (hwnd, TRUE);
2999 Sleep (10);
3000 }
3001 FlashWindow (hwnd, FALSE);
3002 }
ee78dc32 3003 else
fbd6baed 3004 w32_sys_ring_bell ();
ee78dc32
GV
3005
3006 UNBLOCK_INPUT;
ee78dc32 3007}
791f420f 3008
ee78dc32 3009\f
791f420f
JR
3010/* Specify how many text lines, from the top of the window,
3011 should be affected by insert-lines and delete-lines operations.
3012 This, and those operations, are used only within an update
3013 that is bounded by calls to x_update_begin and x_update_end. */
ee78dc32 3014
96214669 3015static void
791f420f
JR
3016w32_set_terminal_window (n)
3017 register int n;
ee78dc32 3018{
791f420f 3019 /* This function intentionally left blank. */
ee78dc32 3020}
791f420f
JR
3021
3022\f
3023/***********************************************************************
3024 Line Dance
3025 ***********************************************************************/
3026
3027/* Perform an insert-lines or delete-lines operation, inserting N
3028 lines or deleting -N lines at vertical position VPOS. */
ee78dc32 3029
96214669 3030static void
791f420f
JR
3031x_ins_del_lines (vpos, n)
3032 int vpos, n;
ee78dc32 3033{
7e6ac5b9
AI
3034 struct frame *f;
3035
3036 if (updating_frame)
3037 f = updating_frame;
3038 else
3039 f = SELECTED_FRAME ();
3040
3041 if (! FRAME_W32_P (f))
3042 return;
3043
ee78dc32
GV
3044 abort ();
3045}
791f420f
JR
3046
3047
3048/* Scroll part of the display as described by RUN. */
3049
3050static void
3051x_scroll_run (w, run)
3052 struct window *w;
3053 struct run *run;
3054{
3055 struct frame *f = XFRAME (w->frame);
3056 int x, y, width, height, from_y, to_y, bottom_y;
4d6e8199
JR
3057 HWND hwnd = FRAME_W32_WINDOW (f);
3058 HRGN expect_dirty;
791f420f
JR
3059
3060 /* Get frame-relative bounding box of the text display area of W,
33c34bea
KS
3061 without mode lines. Include in this box the left and right
3062 fringes of W. */
791f420f 3063 window_box (w, -1, &x, &y, &width, &height);
33c34bea
KS
3064 width += FRAME_X_FRINGE_WIDTH (f);
3065 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
791f420f
JR
3066
3067 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3068 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3069 bottom_y = y + height;
3070
3071 if (to_y < from_y)
3072 {
3073 /* Scrolling up. Make sure we don't copy part of the mode
3074 line at the bottom. */
3075 if (from_y + run->height > bottom_y)
3076 height = bottom_y - from_y;
3077 else
3078 height = run->height;
4d6e8199 3079 expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
791f420f
JR
3080 }
3081 else
3082 {
3083 /* Scolling down. Make sure we don't copy over the mode line.
3084 at the bottom. */
3085 if (to_y + run->height > bottom_y)
3086 height = bottom_y - to_y;
3087 else
3088 height = run->height;
4d6e8199 3089 expect_dirty = CreateRectRgn (x, y, x + width, to_y);
791f420f
JR
3090 }
3091
3092 BLOCK_INPUT;
d67d1627 3093
791f420f
JR
3094 /* Cursor off. Will be switched on again in x_update_window_end. */
3095 updated_window = w;
3096 x_clear_cursor (w);
3097
4d6e8199
JR
3098 {
3099 RECT from;
3100 RECT to;
3101 HRGN dirty = CreateRectRgn (0, 0, 0, 0);
3102 HRGN combined = CreateRectRgn (0, 0, 0, 0);
3103
3104 from.left = to.left = x;
3105 from.right = to.right = x + width;
3106 from.top = from_y;
3107 from.bottom = from_y + height;
3108 to.top = y;
3109 to.bottom = bottom_y;
3110
3111 ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
3112 NULL, SW_INVALIDATE);
3113
3114 /* Combine this with what we expect to be dirty. This covers the
3115 case where not all of the region we expect is actually dirty. */
3116 CombineRgn (combined, dirty, expect_dirty, RGN_OR);
3117
3118 /* If the dirty region is not what we expected, redraw the entire frame. */
3119 if (!EqualRgn (combined, expect_dirty))
3120 SET_FRAME_GARBAGED (f);
3121 }
3122
791f420f 3123 UNBLOCK_INPUT;
791f420f
JR
3124}
3125
9ef2e2cf 3126
ee78dc32 3127\f
791f420f
JR
3128/***********************************************************************
3129 Exposure Events
3130 ***********************************************************************/
d67d1627 3131
791f420f
JR
3132/* Redisplay an exposed area of frame F. X and Y are the upper-left
3133 corner of the exposed rectangle. W and H are width and height of
3134 the exposed area. All are pixel values. W or H zero means redraw
3135 the entire frame. */
ee78dc32 3136
96214669 3137static void
791f420f
JR
3138expose_frame (f, x, y, w, h)
3139 struct frame *f;
3140 int x, y, w, h;
ee78dc32 3141{
791f420f 3142 RECT r;
9f5a911b 3143 int mouse_face_overwritten_p = 0;
791f420f
JR
3144
3145 TRACE ((stderr, "expose_frame "));
3146
3147 /* No need to redraw if frame will be redrawn soon. */
3148 if (FRAME_GARBAGED_P (f))
3149 {
3150 TRACE ((stderr, " garbaged\n"));
3151 return;
3152 }
3153
3154 /* If basic faces haven't been realized yet, there is no point in
3155 trying to redraw anything. This can happen when we get an expose
3156 event while Emacs is starting, e.g. by moving another window. */
3157 if (FRAME_FACE_CACHE (f) == NULL
3158 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
3159 {
3160 TRACE ((stderr, " no faces\n"));
3161 return;
3162 }
3163
3164 if (w == 0 || h == 0)
3165 {
3166 r.left = r.top = 0;
3167 r.right = CANON_X_UNIT (f) * f->width;
3168 r.bottom = CANON_Y_UNIT (f) * f->height;
3169 }
3170 else
3171 {
3172 r.left = x;
3173 r.top = y;
3174 r.right = x + w;
3175 r.bottom = y + h;
3176 }
3177
3178 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
9f5a911b 3179 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
791f420f
JR
3180
3181 if (WINDOWP (f->tool_bar_window))
9f5a911b
JR
3182 mouse_face_overwritten_p
3183 |= expose_window (XWINDOW (f->tool_bar_window), &r);
3184
3185 /* Some window managers support a focus-follows-mouse style with
3186 delayed raising of frames. Imagine a partially obscured frame,
3187 and moving the mouse into partially obscured mouse-face on that
3188 frame. The visible part of the mouse-face will be highlighted,
3189 then the WM raises the obscured frame. With at least one WM, KDE
3190 2.1, Emacs is not getting any event for the raising of the frame
3191 (even tried with SubstructureRedirectMask), only Expose events.
3192 These expose events will draw text normally, i.e. not
3193 highlighted. Which means we must redo the highlight here.
3194 Subsume it under ``we love X''. --gerd 2001-08-15 */
3195 /* Included in Windows version because Windows most likely does not
3196 do the right thing if any third party tool offers
3197 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
3198 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
791f420f 3199 {
9f5a911b
JR
3200 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3201 if (f == dpyinfo->mouse_face_mouse_frame)
3202 {
3203 int x = dpyinfo->mouse_face_mouse_x;
3204 int y = dpyinfo->mouse_face_mouse_y;
3205 clear_mouse_face (dpyinfo);
3206 note_mouse_highlight (f, x, y);
3207 }
791f420f
JR
3208 }
3209}
3210
3211
3212/* Redraw (parts) of all windows in the window tree rooted at W that
3213 intersect R. R contains frame pixel coordinates. */
3214
9f5a911b 3215static int
791f420f
JR
3216expose_window_tree (w, r)
3217 struct window *w;
3218 RECT *r;
3219{
9f5a911b
JR
3220 struct frame *f = XFRAME (w->frame);
3221 int mouse_face_overwritten_p = 0;
3222
3223 while (w && !FRAME_GARBAGED_P (f))
791f420f
JR
3224 {
3225 if (!NILP (w->hchild))
9f5a911b
JR
3226 mouse_face_overwritten_p
3227 |= expose_window_tree (XWINDOW (w->hchild), r);
791f420f 3228 else if (!NILP (w->vchild))
9f5a911b
JR
3229 mouse_face_overwritten_p
3230 |= expose_window_tree (XWINDOW (w->vchild), r);
791f420f 3231 else
9f5a911b 3232 mouse_face_overwritten_p |= expose_window (w, r);
791f420f 3233
9f5a911b 3234 w = NILP (w->next) ? NULL : XWINDOW (w->next);
791f420f 3235 }
9f5a911b
JR
3236
3237 return mouse_face_overwritten_p;
791f420f
JR
3238}
3239
3240
3241/* Redraw the part of glyph row area AREA of glyph row ROW on window W
3242 which intersects rectangle R. R is in window-relative coordinates. */
3243
3244static void
3245expose_area (w, row, r, area)
3246 struct window *w;
3247 struct glyph_row *row;
3248 RECT *r;
3249 enum glyph_row_area area;
3250{
791f420f
JR
3251 struct glyph *first = row->glyphs[area];
3252 struct glyph *end = row->glyphs[area] + row->used[area];
3253 struct glyph *last;
2df85294 3254 int first_x, start_x, x;
791f420f 3255
791f420f
JR
3256 if (area == TEXT_AREA && row->fill_line_p)
3257 /* If row extends face to end of line write the whole line. */
c2cc16fa 3258 x_draw_glyphs (w, 0, row, area,
791f420f 3259 0, row->used[area],
6ff3e5e3 3260 DRAW_NORMAL_TEXT, 0);
791f420f
JR
3261 else
3262 {
2df85294
JR
3263 /* Set START_X to the window-relative start position for drawing glyphs of
3264 AREA. The first glyph of the text area can be partially visible.
3265 The first glyphs of other areas cannot. */
3266 if (area == LEFT_MARGIN_AREA)
3267 start_x = 0;
3268 else if (area == TEXT_AREA)
3269 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
3270 else
3271 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
3272 + window_box_width (w, TEXT_AREA));
3273 x = start_x;
3274
791f420f
JR
3275 /* Find the first glyph that must be redrawn. */
3276 while (first < end
3277 && x + first->pixel_width < r->left)
3278 {
3279 x += first->pixel_width;
3280 ++first;
3281 }
d67d1627 3282
791f420f
JR
3283 /* Find the last one. */
3284 last = first;
3285 first_x = x;
3286 while (last < end
3287 && x < r->right)
3288 {
3289 x += last->pixel_width;
3290 ++last;
3291 }
2df85294 3292
791f420f
JR
3293 /* Repaint. */
3294 if (last > first)
f201d732 3295 x_draw_glyphs (w, first_x - start_x, row, area,
791f420f
JR
3296 first - row->glyphs[area],
3297 last - row->glyphs[area],
6ff3e5e3 3298 DRAW_NORMAL_TEXT, 0);
791f420f
JR
3299 }
3300}
3301
3302
3303/* Redraw the parts of the glyph row ROW on window W intersecting
9f5a911b
JR
3304 rectangle R. R is in window-relative coordinates. Value is
3305 non-zero if mouse face was overwritten. */
ee78dc32 3306
9f5a911b 3307static int
791f420f
JR
3308expose_line (w, row, r)
3309 struct window *w;
3310 struct glyph_row *row;
3311 RECT *r;
3312{
3313 xassert (row->enabled_p);
d67d1627 3314
791f420f
JR
3315 if (row->mode_line_p || w->pseudo_window_p)
3316 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6ff3e5e3 3317 DRAW_NORMAL_TEXT, 0);
ee78dc32 3318 else
791f420f
JR
3319 {
3320 if (row->used[LEFT_MARGIN_AREA])
3321 expose_area (w, row, r, LEFT_MARGIN_AREA);
3322 if (row->used[TEXT_AREA])
3323 expose_area (w, row, r, TEXT_AREA);
3324 if (row->used[RIGHT_MARGIN_AREA])
3325 expose_area (w, row, r, RIGHT_MARGIN_AREA);
b6ae1532 3326 draw_row_fringe_bitmaps (w, row);
791f420f 3327 }
9f5a911b
JR
3328
3329 return row->mouse_face_p;
ee78dc32 3330}
ee78dc32 3331
ee78dc32 3332
791f420f 3333/* Return non-zero if W's cursor intersects rectangle R. */
96214669 3334
791f420f
JR
3335static int
3336x_phys_cursor_in_rect_p (w, r)
3337 struct window *w;
3338 RECT *r;
ee78dc32 3339{
791f420f
JR
3340 RECT cr, result;
3341 struct glyph *cursor_glyph;
ee78dc32 3342
791f420f
JR
3343 cursor_glyph = get_phys_cursor_glyph (w);
3344 if (cursor_glyph)
ee78dc32 3345 {
791f420f
JR
3346 cr.left = w->phys_cursor.x;
3347 cr.top = w->phys_cursor.y;
3348 cr.right = cr.left + cursor_glyph->pixel_width;
3349 cr.bottom = cr.top + w->phys_cursor_height;
158cba56 3350 return IntersectRect (&result, &cr, r);
ee78dc32
GV
3351 }
3352 else
791f420f 3353 return 0;
ee78dc32
GV
3354}
3355
791f420f 3356
95f2448c
RS
3357/* Redraw those parts of glyphs rows during expose event handling that
3358 overlap other rows. Redrawing of an exposed line writes over parts
3359 of lines overlapping that exposed line; this function fixes that.
3360
3361 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
3362 row in W's current matrix that is exposed and overlaps other rows.
3363 LAST_OVERLAPPING_ROW is the last such row. */
3364
3365static void
3366expose_overlaps (w, first_overlapping_row, last_overlapping_row)
3367 struct window *w;
3368 struct glyph_row *first_overlapping_row;
3369 struct glyph_row *last_overlapping_row;
3370{
3371 struct glyph_row *row;
d67d1627 3372
95f2448c
RS
3373 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
3374 if (row->overlapping_p)
3375 {
3376 xassert (row->enabled_p && !row->mode_line_p);
d67d1627 3377
95f2448c
RS
3378 if (row->used[LEFT_MARGIN_AREA])
3379 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
d67d1627 3380
95f2448c
RS
3381 if (row->used[TEXT_AREA])
3382 x_fix_overlapping_area (w, row, TEXT_AREA);
d67d1627 3383
95f2448c
RS
3384 if (row->used[RIGHT_MARGIN_AREA])
3385 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
3386 }
3387}
3388
3389
9f5a911b
JR
3390/* Redraw the part of window W intersection rectagle FR. Pixel
3391 coordinates in FR are frame relative. Call this function with
3392 input blocked. Value is non-zero if the exposure overwrites
3393 mouse-face. */
791f420f 3394
9f5a911b
JR
3395static int
3396expose_window (w, fr)
791f420f 3397 struct window *w;
9f5a911b 3398 RECT *fr;
ee78dc32 3399{
9f5a911b
JR
3400 struct frame *f = XFRAME (w->frame);
3401 RECT wr, r;
3402 int mouse_face_overwritten_p = 0;
791f420f
JR
3403
3404 /* If window is not yet fully initialized, do nothing. This can
3405 happen when toolkit scroll bars are used and a window is split.
3406 Reconfiguring the scroll bar will generate an expose for a newly
3407 created window. */
9f5a911b
JR
3408 if (w->current_matrix == NULL)
3409 return 0;
ee78dc32 3410
9f5a911b
JR
3411 /* When we're currently updating the window, display and current
3412 matrix usually don't agree. Arrange for a thorough display
3413 later. */
3414 if (w == updated_window)
791f420f 3415 {
9f5a911b
JR
3416 SET_FRAME_GARBAGED (f);
3417 return 0;
791f420f 3418 }
791f420f 3419
9f5a911b
JR
3420 /* Frame-relative pixel rectangle of W. */
3421 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
3422 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
3423 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
3424 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
3425
3426 if (IntersectRect(&r, fr, &wr))
791f420f 3427 {
9f5a911b
JR
3428 int yb = window_text_bottom_y (w);
3429 struct glyph_row *row;
3430 int cursor_cleared_p;
95f2448c 3431 struct glyph_row *first_overlapping_row, *last_overlapping_row;
ee78dc32 3432
9f5a911b
JR
3433 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
3434 r.left, r.top, r.right, r.bottom));
689004fa 3435
9f5a911b
JR
3436 /* Convert to window coordinates. */
3437 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
3438 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
3439 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
3440 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
3441
3442 /* Turn off the cursor. */
3443 if (!w->pseudo_window_p
3444 && x_phys_cursor_in_rect_p (w, &r))
3445 {
3446 x_clear_cursor (w);
3447 cursor_cleared_p = 1;
3448 }
3449 else
3450 cursor_cleared_p = 0;
3451
95f2448c
RS
3452 /* Update lines intersecting rectangle R. */
3453 first_overlapping_row = last_overlapping_row = NULL;
9f5a911b
JR
3454 for (row = w->current_matrix->rows;
3455 row->enabled_p;
3456 ++row)
3457 {
3458 int y0 = row->y;
3459 int y1 = MATRIX_ROW_BOTTOM_Y (row);
3460
3461 if ((y0 >= r.top && y0 < r.bottom)
3462 || (y1 > r.top && y1 < r.bottom)
3463 || (r.top >= y0 && r.top < y1)
3464 || (r.bottom > y0 && r.bottom < y1))
3465 {
95f2448c
RS
3466 if (row->overlapping_p)
3467 {
3468 if (first_overlapping_row == NULL)
3469 first_overlapping_row = row;
3470 last_overlapping_row = row;
3471 }
d67d1627 3472
9f5a911b
JR
3473 if (expose_line (w, row, &r))
3474 mouse_face_overwritten_p = 1;
3475 }
3476
3477 if (y1 >= yb)
3478 break;
3479 }
3480
3481 /* Display the mode line if there is one. */
3482 if (WINDOW_WANTS_MODELINE_P (w)
3483 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
3484 row->enabled_p)
3485 && row->y < r.bottom)
3486 {
3487 if (expose_line (w, row, &r))
3488 mouse_face_overwritten_p = 1;
3489 }
3490
3491 if (!w->pseudo_window_p)
3492 {
95f2448c
RS
3493 /* Fix the display of overlapping rows. */
3494 if (first_overlapping_row)
3495 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
d67d1627 3496
9f5a911b
JR
3497 /* Draw border between windows. */
3498 x_draw_vertical_border (w);
3499
3500 /* Turn the cursor on again. */
3501 if (cursor_cleared_p)
3502 x_update_window_cursor (w, 1);
3503 }
791f420f 3504 }
9f5a911b
JR
3505
3506 return mouse_face_overwritten_p;
ee78dc32 3507}
ee78dc32 3508
ee78dc32
GV
3509\f
3510static void
3511frame_highlight (f)
3512 struct frame *f;
3513{
791f420f 3514 x_update_cursor (f, 1);
ee78dc32
GV
3515}
3516
3517static void
3518frame_unhighlight (f)
3519 struct frame *f;
3520{
791f420f 3521 x_update_cursor (f, 1);
ee78dc32
GV
3522}
3523
ee78dc32
GV
3524/* The focus has changed. Update the frames as necessary to reflect
3525 the new situation. Note that we can't change the selected frame
3526 here, because the Lisp code we are interrupting might become confused.
3527 Each event gets marked with the frame in which it occurred, so the
3528 Lisp code can tell when the switch took place by examining the events. */
3529
9ef2e2cf 3530static void
ee78dc32 3531x_new_focus_frame (dpyinfo, frame)
fbd6baed 3532 struct w32_display_info *dpyinfo;
ee78dc32
GV
3533 struct frame *frame;
3534{
fbd6baed 3535 struct frame *old_focus = dpyinfo->w32_focus_frame;
ee78dc32 3536
fbd6baed 3537 if (frame != dpyinfo->w32_focus_frame)
ee78dc32
GV
3538 {
3539 /* Set this before calling other routines, so that they see
fbd6baed
GV
3540 the correct value of w32_focus_frame. */
3541 dpyinfo->w32_focus_frame = frame;
ee78dc32
GV
3542
3543 if (old_focus && old_focus->auto_lower)
3544 x_lower_frame (old_focus);
3545
fbd6baed
GV
3546 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
3547 pending_autoraise_frame = dpyinfo->w32_focus_frame;
ee78dc32
GV
3548 else
3549 pending_autoraise_frame = 0;
3550 }
3551
3552 x_frame_rehighlight (dpyinfo);
3553}
3554
3555/* Handle an event saying the mouse has moved out of an Emacs frame. */
3556
3557void
3558x_mouse_leave (dpyinfo)
fbd6baed 3559 struct w32_display_info *dpyinfo;
ee78dc32 3560{
fbd6baed 3561 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
ee78dc32
GV
3562}
3563
3564/* The focus has changed, or we have redirected a frame's focus to
3565 another frame (this happens when a frame uses a surrogate
9ef2e2cf 3566 mini-buffer frame). Shift the highlight as appropriate.
ee78dc32
GV
3567
3568 The FRAME argument doesn't necessarily have anything to do with which
9ef2e2cf
JR
3569 frame is being highlighted or un-highlighted; we only use it to find
3570 the appropriate X display info. */
3571
ee78dc32 3572static void
fbd6baed 3573w32_frame_rehighlight (frame)
ee78dc32
GV
3574 struct frame *frame;
3575{
7e6ac5b9
AI
3576 if (! FRAME_W32_P (frame))
3577 return;
fbd6baed 3578 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
ee78dc32
GV
3579}
3580
3581static void
3582x_frame_rehighlight (dpyinfo)
fbd6baed 3583 struct w32_display_info *dpyinfo;
ee78dc32 3584{
4baaed0f 3585 struct frame *old_highlight = dpyinfo->x_highlight_frame;
ee78dc32 3586
fbd6baed 3587 if (dpyinfo->w32_focus_frame)
ee78dc32 3588 {
4baaed0f 3589 dpyinfo->x_highlight_frame
fbd6baed
GV
3590 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
3591 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
3592 : dpyinfo->w32_focus_frame);
4baaed0f 3593 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
ee78dc32 3594 {
fbd6baed 3595 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
4baaed0f 3596 dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
ee78dc32
GV
3597 }
3598 }
3599 else
4baaed0f 3600 dpyinfo->x_highlight_frame = 0;
ee78dc32 3601
4baaed0f 3602 if (dpyinfo->x_highlight_frame != old_highlight)
ee78dc32
GV
3603 {
3604 if (old_highlight)
3605 frame_unhighlight (old_highlight);
4baaed0f
KS
3606 if (dpyinfo->x_highlight_frame)
3607 frame_highlight (dpyinfo->x_highlight_frame);
ee78dc32
GV
3608 }
3609}
3610\f
3611/* Keyboard processing - modifier keys, etc. */
3612
3613/* Convert a keysym to its name. */
3614
3615char *
3616x_get_keysym_name (keysym)
3617 int keysym;
3618{
3619 /* Make static so we can always return it */
3620 static char value[100];
3621
3622 BLOCK_INPUT;
9127e20e 3623 GetKeyNameText (keysym, value, 100);
ee78dc32
GV
3624 UNBLOCK_INPUT;
3625
3626 return value;
3627}
9ef2e2cf
JR
3628
3629
ee78dc32
GV
3630\f
3631/* Mouse clicks and mouse movement. Rah. */
3632
9ef2e2cf
JR
3633/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
3634 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
3635 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
3636 not force the value into range. */
ee78dc32
GV
3637
3638void
3639pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
3640 FRAME_PTR f;
3641 register int pix_x, pix_y;
3642 register int *x, *y;
3643 RECT *bounds;
3644 int noclip;
3645{
52cf03a1
GV
3646 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
3647 if (NILP (Vwindow_system))
3648 {
3649 *x = pix_x;
3650 *y = pix_y;
3651 return;
3652 }
3653
ee78dc32
GV
3654 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
3655 even for negative values. */
3656 if (pix_x < 0)
9127e20e 3657 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
ee78dc32 3658 if (pix_y < 0)
fbd6baed 3659 pix_y -= (f)->output_data.w32->line_height - 1;
ee78dc32
GV
3660
3661 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
3662 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
3663
3664 if (bounds)
3665 {
3666 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
3667 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
9127e20e 3668 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
fbd6baed 3669 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
ee78dc32
GV
3670 }
3671
3672 if (!noclip)
3673 {
3674 if (pix_x < 0)
3675 pix_x = 0;
ec48c3a7
JR
3676 else if (pix_x > FRAME_WINDOW_WIDTH (f))
3677 pix_x = FRAME_WINDOW_WIDTH (f);
ee78dc32
GV
3678
3679 if (pix_y < 0)
3680 pix_y = 0;
3681 else if (pix_y > f->height)
3682 pix_y = f->height;
3683 }
3684
3685 *x = pix_x;
3686 *y = pix_y;
3687}
3688
791f420f
JR
3689
3690/* Given HPOS/VPOS in the current matrix of W, return corresponding
3691 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
3692 can't tell the positions because W's display is not up to date,
3693 return 0. */
3694
3695int
3696glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
3697 struct window *w;
3698 int hpos, vpos;
3699 int *frame_x, *frame_y;
ee78dc32 3700{
791f420f
JR
3701 int success_p;
3702
3703 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
3704 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
3705
3706 if (display_completed)
52cf03a1 3707 {
791f420f
JR
3708 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
3709 struct glyph *glyph = row->glyphs[TEXT_AREA];
3710 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
3711
3712 *frame_y = row->y;
3713 *frame_x = row->x;
3714 while (glyph < end)
3715 {
3716 *frame_x += glyph->pixel_width;
3717 ++glyph;
3718 }
3719
3720 success_p = 1;
3721 }
3722 else
3723 {
3724 *frame_y = *frame_x = 0;
3725 success_p = 0;
52cf03a1
GV
3726 }
3727
791f420f
JR
3728 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
3729 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
3730 return success_p;
ee78dc32
GV
3731}
3732
53823ab9
JR
3733/* Parse a button MESSAGE. The button index is returned in PBUTTON, and
3734 the state in PUP. XBUTTON provides extra information for extended mouse
3735 button messages. Returns FALSE if unable to parse the message. */
d67d1627 3736BOOL
53823ab9 3737parse_button (message, xbutton, pbutton, pup)
ee78dc32 3738 int message;
53823ab9 3739 int xbutton;
ee78dc32
GV
3740 int * pbutton;
3741 int * pup;
3742{
3743 int button = 0;
3744 int up = 0;
d67d1627 3745
ee78dc32
GV
3746 switch (message)
3747 {
3748 case WM_LBUTTONDOWN:
3749 button = 0;
3750 up = 0;
3751 break;
3752 case WM_LBUTTONUP:
3753 button = 0;
3754 up = 1;
3755 break;
3756 case WM_MBUTTONDOWN:
fbd6baed 3757 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3758 button = 1;
3759 else
3760 button = 2;
ee78dc32
GV
3761 up = 0;
3762 break;
3763 case WM_MBUTTONUP:
fbd6baed 3764 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3765 button = 1;
3766 else
3767 button = 2;
ee78dc32
GV
3768 up = 1;
3769 break;
3770 case WM_RBUTTONDOWN:
fbd6baed 3771 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3772 button = 2;
3773 else
3774 button = 1;
ee78dc32
GV
3775 up = 0;
3776 break;
3777 case WM_RBUTTONUP:
fbd6baed 3778 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
3779 button = 2;
3780 else
3781 button = 1;
ee78dc32
GV
3782 up = 1;
3783 break;
53823ab9
JR
3784 case WM_XBUTTONDOWN:
3785 button = xbutton + 2;
3786 up = 0;
3787 break;
3788 case WM_XBUTTONUP:
3789 button = xbutton + 2;
3790 up = 1;
3791 break;
ee78dc32
GV
3792 default:
3793 return (FALSE);
3794 }
d67d1627 3795
ee78dc32
GV
3796 if (pup) *pup = up;
3797 if (pbutton) *pbutton = button;
d67d1627 3798
ee78dc32
GV
3799 return (TRUE);
3800}
3801
3802
3803/* Prepare a mouse-event in *RESULT for placement in the input queue.
3804
3805 If the event is a button press, then note that we have grabbed
3806 the mouse. */
3807
ec48c3a7 3808static Lisp_Object
ee78dc32
GV
3809construct_mouse_click (result, msg, f)
3810 struct input_event *result;
fbd6baed 3811 W32Msg *msg;
ee78dc32
GV
3812 struct frame *f;
3813{
3814 int button;
3815 int up;
3816
53823ab9
JR
3817 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
3818 &button, &up);
ee78dc32 3819
3b8f9651 3820 /* Make the event type NO_EVENT; we'll change that when we decide
ee78dc32 3821 otherwise. */
3b8f9651 3822 result->kind = MOUSE_CLICK_EVENT;
ee78dc32
GV
3823 result->code = button;
3824 result->timestamp = msg->msg.time;
3825 result->modifiers = (msg->dwModifiers
3826 | (up
3827 ? up_modifier
3828 : down_modifier));
3829
ec48c3a7
JR
3830 XSETINT (result->x, LOWORD (msg->msg.lParam));
3831 XSETINT (result->y, HIWORD (msg->msg.lParam));
3832 XSETFRAME (result->frame_or_window, f);
3833 result->arg = Qnil;
3834 return Qnil;
ee78dc32
GV
3835}
3836
ec48c3a7 3837static Lisp_Object
689004fa
GV
3838construct_mouse_wheel (result, msg, f)
3839 struct input_event *result;
3840 W32Msg *msg;
3841 struct frame *f;
3842{
3843 POINT p;
3b8f9651 3844 result->kind = MOUSE_WHEEL_EVENT;
689004fa
GV
3845 result->code = (short) HIWORD (msg->msg.wParam);
3846 result->timestamp = msg->msg.time;
3847 result->modifiers = msg->dwModifiers;
3848 p.x = LOWORD (msg->msg.lParam);
3849 p.y = HIWORD (msg->msg.lParam);
9127e20e 3850 ScreenToClient (msg->msg.hwnd, &p);
689004fa
GV
3851 XSETINT (result->x, p.x);
3852 XSETINT (result->y, p.y);
3853 XSETFRAME (result->frame_or_window, f);
7e889510 3854 result->arg = Qnil;
ec48c3a7 3855 return Qnil;
689004fa
GV
3856}
3857
ec48c3a7 3858static Lisp_Object
12857dfd
RS
3859construct_drag_n_drop (result, msg, f)
3860 struct input_event *result;
3861 W32Msg *msg;
3862 struct frame *f;
3863{
3864 Lisp_Object files;
3865 Lisp_Object frame;
3866 HDROP hdrop;
3867 POINT p;
3868 WORD num_files;
3869 char *name;
3870 int i, len;
3871
3b8f9651 3872 result->kind = DRAG_N_DROP_EVENT;
12857dfd
RS
3873 result->code = 0;
3874 result->timestamp = msg->msg.time;
3875 result->modifiers = msg->dwModifiers;
3876
fb9cc9cc
AI
3877 hdrop = (HDROP) msg->msg.wParam;
3878 DragQueryPoint (hdrop, &p);
3879
e12ca9c2 3880#if 0
12857dfd
RS
3881 p.x = LOWORD (msg->msg.lParam);
3882 p.y = HIWORD (msg->msg.lParam);
3883 ScreenToClient (msg->msg.hwnd, &p);
e12ca9c2
AI
3884#endif
3885
12857dfd
RS
3886 XSETINT (result->x, p.x);
3887 XSETINT (result->y, p.y);
3888
12857dfd
RS
3889 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
3890 files = Qnil;
3891
3892 for (i = 0; i < num_files; i++)
3893 {
3894 len = DragQueryFile (hdrop, i, NULL, 0);
3895 if (len <= 0)
3896 continue;
3897 name = alloca (len + 1);
3898 DragQueryFile (hdrop, i, name, len + 1);
54a0ce0f 3899 files = Fcons (DECODE_FILE (build_string (name)), files);
12857dfd
RS
3900 }
3901
3902 DragFinish (hdrop);
3903
3904 XSETFRAME (frame, f);
3905 result->frame_or_window = Fcons (frame, files);
7e889510 3906 result->arg = Qnil;
ec48c3a7 3907 return Qnil;
12857dfd
RS
3908}
3909
ee78dc32
GV
3910\f
3911/* Function to report a mouse movement to the mainstream Emacs code.
3912 The input handler calls this.
3913
3914 We have received a mouse movement event, which is given in *event.
3915 If the mouse is over a different glyph than it was last time, tell
3916 the mainstream emacs code by setting mouse_moved. If not, ask for
3917 another motion event, so we can check again the next time it moves. */
3918
791f420f
JR
3919static MSG last_mouse_motion_event;
3920static Lisp_Object last_mouse_motion_frame;
3921
9f5a911b
JR
3922static void remember_mouse_glyph P_ ((struct frame *, int, int));
3923
ee78dc32
GV
3924static void
3925note_mouse_movement (frame, msg)
3926 FRAME_PTR frame;
3927 MSG *msg;
3928{
9f5a911b
JR
3929 int mouse_x = LOWORD (msg->lParam);
3930 int mouse_y = HIWORD (msg->lParam);
3931
ee78dc32 3932 last_mouse_movement_time = msg->time;
791f420f
JR
3933 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
3934 XSETFRAME (last_mouse_motion_frame, frame);
ee78dc32 3935
fbd6baed 3936 if (msg->hwnd != FRAME_W32_WINDOW (frame))
ee78dc32
GV
3937 {
3938 frame->mouse_moved = 1;
3939 last_mouse_scroll_bar = Qnil;
ee78dc32
GV
3940 note_mouse_highlight (frame, -1, -1);
3941 }
3942
3943 /* Has the mouse moved off the glyph it was on at the last sighting? */
9f5a911b
JR
3944 else if (mouse_x < last_mouse_glyph.left
3945 || mouse_x > last_mouse_glyph.right
3946 || mouse_y < last_mouse_glyph.top
3947 || mouse_y > last_mouse_glyph.bottom)
ee78dc32
GV
3948 {
3949 frame->mouse_moved = 1;
3950 last_mouse_scroll_bar = Qnil;
9f5a911b
JR
3951 note_mouse_highlight (frame, mouse_x, mouse_y);
3952 /* Remember the mouse position here, as w32_mouse_position only
3953 gets called when mouse tracking is enabled but we also need
3954 to keep track of the mouse for help_echo and highlighting at
3955 other times. */
3956 remember_mouse_glyph (frame, mouse_x, mouse_y);
ee78dc32
GV
3957 }
3958}
3959
791f420f
JR
3960\f
3961/************************************************************************
3962 Mouse Face
3963 ************************************************************************/
3964
3965/* Find the glyph under window-relative coordinates X/Y in window W.
3966 Consider only glyphs from buffer text, i.e. no glyphs from overlay
3967 strings. Return in *HPOS and *VPOS the row and column number of
3968 the glyph found. Return in *AREA the glyph area containing X.
3969 Value is a pointer to the glyph found or null if X/Y is not on
3970 text, or we can't tell because W's current matrix is not up to
3971 date. */
3972
3973static struct glyph *
9f5a911b 3974x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
791f420f
JR
3975 struct window *w;
3976 int x, y;
3977 int *hpos, *vpos, *area;
9f5a911b 3978 int buffer_only_p;
791f420f
JR
3979{
3980 struct glyph *glyph, *end;
ec48c3a7 3981 struct glyph_row *row = NULL;
791f420f
JR
3982 int x0, i, left_area_width;
3983
3984 /* Find row containing Y. Give up if some row is not enabled. */
3985 for (i = 0; i < w->current_matrix->nrows; ++i)
3986 {
3987 row = MATRIX_ROW (w->current_matrix, i);
3988 if (!row->enabled_p)
3989 return NULL;
3990 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
3991 break;
3992 }
3993
3994 *vpos = i;
3995 *hpos = 0;
3996
3997 /* Give up if Y is not in the window. */
3998 if (i == w->current_matrix->nrows)
3999 return NULL;
4000
4001 /* Get the glyph area containing X. */
4002 if (w->pseudo_window_p)
4003 {
4004 *area = TEXT_AREA;
4005 x0 = 0;
4006 }
4007 else
4008 {
4009 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
4010 if (x < left_area_width)
4011 {
4012 *area = LEFT_MARGIN_AREA;
4013 x0 = 0;
4014 }
4015 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
4016 {
4017 *area = TEXT_AREA;
4018 x0 = row->x + left_area_width;
4019 }
4020 else
4021 {
4022 *area = RIGHT_MARGIN_AREA;
4023 x0 = left_area_width + window_box_width (w, TEXT_AREA);
4024 }
4025 }
4026
4027 /* Find glyph containing X. */
4028 glyph = row->glyphs[*area];
4029 end = glyph + row->used[*area];
4030 while (glyph < end)
4031 {
4032 if (x < x0 + glyph->pixel_width)
4033 {
4034 if (w->pseudo_window_p)
4035 break;
9f5a911b 4036 else if (!buffer_only_p || BUFFERP (glyph->object))
791f420f
JR
4037 break;
4038 }
d67d1627 4039
791f420f
JR
4040 x0 += glyph->pixel_width;
4041 ++glyph;
4042 }
4043
4044 if (glyph == end)
4045 return NULL;
4046
4047 *hpos = glyph - row->glyphs[*area];
4048 return glyph;
4049}
4050
4051
4052/* Convert frame-relative x/y to coordinates relative to window W.
4053 Takes pseudo-windows into account. */
4054
4055static void
4056frame_to_window_pixel_xy (w, x, y)
4057 struct window *w;
4058 int *x, *y;
4059{
4060 if (w->pseudo_window_p)
4061 {
4062 /* A pseudo-window is always full-width, and starts at the
4063 left edge of the frame, plus a frame border. */
4064 struct frame *f = XFRAME (w->frame);
4065 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
4066 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
4067 }
4068 else
4069 {
4070 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
4071 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
4072 }
4073}
4074
4075
a18bb28d
JR
4076/* Take proper action when mouse has moved to the mode or header line
4077 or marginal area of window W, x-position X and y-position Y. Area
4078 is 1, 3, 6 or 7 for the mode line, header line, left and right
4079 marginal area respectively. X is relative to the start of the text
4080 display area of W, so the width of bitmap areas and scroll bars
4081 must be subtracted to get a position relative to the start of the
4082 mode line. */
791f420f
JR
4083
4084static void
a18bb28d 4085note_mode_line_or_margin_highlight (w, x, y, portion)
791f420f 4086 struct window *w;
a18bb28d 4087 int x, y, portion;
791f420f
JR
4088{
4089 struct frame *f = XFRAME (w->frame);
4090 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4091 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
a18bb28d
JR
4092 int charpos;
4093 Lisp_Object string, help, map, pos;
791f420f 4094
a18bb28d
JR
4095 if (portion == 1 || portion == 3)
4096 string = mode_line_string (w, x, y, portion == 1, &charpos);
791f420f 4097 else
a18bb28d 4098 string = marginal_area_string (w, x, y, portion, &charpos);
791f420f 4099
a18bb28d 4100 if (STRINGP (string))
791f420f 4101 {
a18bb28d 4102 pos = make_number (charpos);
d67d1627 4103
a18bb28d
JR
4104 /* If we're on a string with `help-echo' text property, arrange
4105 for the help to be displayed. This is done by setting the
4106 global variable help_echo to the help string. */
4107 help = Fget_text_property (pos, Qhelp_echo, string);
4108 if (!NILP (help))
791f420f 4109 {
a18bb28d
JR
4110 help_echo = help;
4111 XSETWINDOW (help_echo_window, w);
4112 help_echo_object = string;
4113 help_echo_pos = charpos;
791f420f
JR
4114 }
4115
a18bb28d
JR
4116 /* Change the mouse pointer according to what is under X/Y. */
4117 map = Fget_text_property (pos, Qlocal_map, string);
4118 if (!KEYMAPP (map))
4119 map = Fget_text_property (pos, Qkeymap, string);
4120 if (KEYMAPP (map))
4121 cursor = f->output_data.w32->nontext_cursor;
791f420f 4122 }
a18bb28d 4123
2bf04b9d 4124 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
791f420f 4125}
ee78dc32 4126
9ef2e2cf
JR
4127
4128/* Take proper action when the mouse has moved to position X, Y on
4129 frame F as regards highlighting characters that have mouse-face
4130 properties. Also de-highlighting chars where the mouse was before.
ee78dc32
GV
4131 X and Y can be negative or out of range. */
4132
4133static void
4134note_mouse_highlight (f, x, y)
9ef2e2cf 4135 struct frame *f;
ee78dc32
GV
4136 int x, y;
4137{
791f420f
JR
4138 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4139 int portion;
ee78dc32
GV
4140 Lisp_Object window;
4141 struct window *w;
2bf04b9d 4142 Cursor cursor = 0;
9f5a911b 4143 struct buffer *b;
ee78dc32 4144
791f420f
JR
4145 /* When a menu is active, don't highlight because this looks odd. */
4146 if (popup_activated ())
4147 return;
4148
3d26a7c2 4149 if (NILP (Vmouse_highlight)
9ef2e2cf 4150 || !f->glyphs_initialized_p)
ee78dc32
GV
4151 return;
4152
791f420f
JR
4153 dpyinfo->mouse_face_mouse_x = x;
4154 dpyinfo->mouse_face_mouse_y = y;
4155 dpyinfo->mouse_face_mouse_frame = f;
ee78dc32 4156
791f420f 4157 if (dpyinfo->mouse_face_defer)
ee78dc32
GV
4158 return;
4159
4160 if (gc_in_progress)
4161 {
791f420f 4162 dpyinfo->mouse_face_deferred_gc = 1;
ee78dc32
GV
4163 return;
4164 }
4165
ee78dc32 4166 /* Which window is that in? */
791f420f 4167 window = window_from_coordinates (f, x, y, &portion, 1);
ee78dc32
GV
4168
4169 /* If we were displaying active text in another window, clear that. */
791f420f
JR
4170 if (! EQ (window, dpyinfo->mouse_face_window))
4171 clear_mouse_face (dpyinfo);
4172
4173 /* Not on a window -> return. */
4174 if (!WINDOWP (window))
4175 return;
4176
abb15ebd
JR
4177 /* Reset help_echo. It will get recomputed below. */
4178 help_echo = Qnil;
4179
791f420f
JR
4180 /* Convert to window-relative pixel coordinates. */
4181 w = XWINDOW (window);
4182 frame_to_window_pixel_xy (w, &x, &y);
4183
4184 /* Handle tool-bar window differently since it doesn't display a
4185 buffer. */
4186 if (EQ (window, f->tool_bar_window))
4187 {
4188 note_tool_bar_highlight (f, x, y);
4189 return;
4190 }
4191
9f5a911b 4192 /* Mouse is on the mode or header line? */
a18bb28d 4193 if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
791f420f 4194 {
a18bb28d 4195 note_mode_line_or_margin_highlight (w, x, y, portion);
791f420f
JR
4196 return;
4197 }
2bf04b9d 4198
9f5a911b 4199 if (portion == 2)
2bf04b9d 4200 cursor = f->output_data.w32->horizontal_drag_cursor;
791f420f 4201 else
2bf04b9d
JR
4202 cursor = f->output_data.w32->text_cursor;
4203
ee78dc32
GV
4204 /* Are we in a window whose display is up to date?
4205 And verify the buffer's text has not changed. */
9f5a911b 4206 b = XBUFFER (w->buffer);
9ef2e2cf 4207 if (/* Within text portion of the window. */
791f420f 4208 portion == 0
ee78dc32 4209 && EQ (w->window_end_valid, w->buffer)
9f5a911b
JR
4210 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
4211 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
ee78dc32 4212 {
791f420f
JR
4213 int hpos, vpos, pos, i, area;
4214 struct glyph *glyph;
9f5a911b
JR
4215 Lisp_Object object;
4216 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
4217 Lisp_Object *overlay_vec = NULL;
4218 int len, noverlays;
4219 struct buffer *obuf;
4220 int obegv, ozv, same_region;
791f420f
JR
4221
4222 /* Find the glyph under X/Y. */
9f5a911b 4223 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
791f420f
JR
4224
4225 /* Clear mouse face if X/Y not over text. */
4226 if (glyph == NULL
4227 || area != TEXT_AREA
4228 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
4229 {
4230 clear_mouse_face (dpyinfo);
2bf04b9d 4231 cursor = f->output_data.w32->nontext_cursor;
9f5a911b 4232 goto set_cursor;
791f420f
JR
4233 }
4234
4235 pos = glyph->charpos;
9f5a911b
JR
4236 object = glyph->object;
4237 if (!STRINGP (object) && !BUFFERP (object))
4238 goto set_cursor;
4239
4240 /* If we get an out-of-range value, return now; avoid an error. */
4241 if (BUFFERP (object) && pos > BUF_Z (b))
4242 goto set_cursor;
4243
4244 /* Make the window's buffer temporarily current for
4245 overlays_at and compute_char_face. */
4246 obuf = current_buffer;
4247 current_buffer = b;
4248 obegv = BEGV;
4249 ozv = ZV;
4250 BEGV = BEG;
4251 ZV = Z;
4252
4253 /* Is this char mouse-active or does it have help-echo? */
4254 position = make_number (pos);
4255
4256 if (BUFFERP (object))
4257 {
4258 /* Put all the overlays we want in a vector in overlay_vec.
4259 Store the length in len. If there are more than 10, make
4260 enough space for all, and try again. */
4261 len = 10;
4262 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
4263 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
4264 if (noverlays > len)
4265 {
4266 len = noverlays;
4267 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
4268 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
4269 }
4270
4271 /* Sort overlays into increasing priority order. */
4272 noverlays = sort_overlays (overlay_vec, noverlays, w);
4273 }
4274 else
4275 noverlays = 0;
4276
4277 same_region = (EQ (window, dpyinfo->mouse_face_window)
4278 && vpos >= dpyinfo->mouse_face_beg_row
4279 && vpos <= dpyinfo->mouse_face_end_row
4280 && (vpos > dpyinfo->mouse_face_beg_row
4281 || hpos >= dpyinfo->mouse_face_beg_col)
4282 && (vpos < dpyinfo->mouse_face_end_row
4283 || hpos < dpyinfo->mouse_face_end_col
4284 || dpyinfo->mouse_face_past_end));
4285
2bf04b9d
JR
4286 if (same_region)
4287 cursor = 0;
9f5a911b
JR
4288
4289 /* Check mouse-face highlighting. */
4290 if (! same_region
4291 /* If there exists an overlay with mouse-face overlapping
4292 the one we are currently highlighting, we have to
4293 check if we enter the overlapping overlay, and then
4294 highlight that. */
4295 || (OVERLAYP (dpyinfo->mouse_face_overlay)
4296 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
4297 {
4298 /* Find the highest priority overlay that has a mouse-face
4299 property. */
4300 overlay = Qnil;
4301 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
4302 {
4303 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
4304 if (!NILP (mouse_face))
4305 overlay = overlay_vec[i];
4306 }
791f420f 4307
9f5a911b
JR
4308 /* If we're actually highlighting the same overlay as
4309 before, there's no need to do that again. */
4310 if (!NILP (overlay)
4311 && EQ (overlay, dpyinfo->mouse_face_overlay))
4312 goto check_help_echo;
4313
4314 dpyinfo->mouse_face_overlay = overlay;
4315
4316 /* Clear the display of the old active region, if any. */
2bf04b9d
JR
4317 if (clear_mouse_face (dpyinfo))
4318 cursor = 0;
9f5a911b
JR
4319
4320 /* If no overlay applies, get a text property. */
4321 if (NILP (overlay))
4322 mouse_face = Fget_text_property (position, Qmouse_face, object);
4323
4324 /* Handle the overlay case. */
4325 if (!NILP (overlay))
4326 {
4327 /* Find the range of text around this char that
4328 should be active. */
4329 Lisp_Object before, after;
4330 int ignore;
4331
4332 before = Foverlay_start (overlay);
4333 after = Foverlay_end (overlay);
4334 /* Record this as the current active region. */
4335 fast_find_position (w, XFASTINT (before),
4336 &dpyinfo->mouse_face_beg_col,
4337 &dpyinfo->mouse_face_beg_row,
4338 &dpyinfo->mouse_face_beg_x,
4339 &dpyinfo->mouse_face_beg_y, Qnil);
4340
4341 dpyinfo->mouse_face_past_end
4342 = !fast_find_position (w, XFASTINT (after),
4343 &dpyinfo->mouse_face_end_col,
4344 &dpyinfo->mouse_face_end_row,
4345 &dpyinfo->mouse_face_end_x,
4346 &dpyinfo->mouse_face_end_y, Qnil);
4347 dpyinfo->mouse_face_window = window;
4348
4349 dpyinfo->mouse_face_face_id
4350 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
4351 &ignore, pos + 1,
4352 !dpyinfo->mouse_face_hidden);
9f5a911b
JR
4353
4354 /* Display it as active. */
4355 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
2bf04b9d 4356 cursor = 0;
9f5a911b
JR
4357 }
4358 /* Handle the text property case. */
4359 else if (! NILP (mouse_face) && BUFFERP (object))
4360 {
4361 /* Find the range of text around this char that
4362 should be active. */
4363 Lisp_Object before, after, beginning, end;
4364 int ignore;
4365
4366 beginning = Fmarker_position (w->start);
4367 end = make_number (BUF_Z (XBUFFER (object))
4368 - XFASTINT (w->window_end_pos));
4369 before
4370 = Fprevious_single_property_change (make_number (pos + 1),
4371 Qmouse_face,
4372 object, beginning);
4373 after
4374 = Fnext_single_property_change (position, Qmouse_face,
4375 object, end);
4376
4377 /* Record this as the current active region. */
4378 fast_find_position (w, XFASTINT (before),
4379 &dpyinfo->mouse_face_beg_col,
4380 &dpyinfo->mouse_face_beg_row,
4381 &dpyinfo->mouse_face_beg_x,
4382 &dpyinfo->mouse_face_beg_y, Qnil);
4383 dpyinfo->mouse_face_past_end
4384 = !fast_find_position (w, XFASTINT (after),
4385 &dpyinfo->mouse_face_end_col,
4386 &dpyinfo->mouse_face_end_row,
4387 &dpyinfo->mouse_face_end_x,
4388 &dpyinfo->mouse_face_end_y, Qnil);
4389 dpyinfo->mouse_face_window = window;
4390
4391 if (BUFFERP (object))
4392 dpyinfo->mouse_face_face_id
4393 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
4394 &ignore, pos + 1,
4395 !dpyinfo->mouse_face_hidden);
9f5a911b
JR
4396
4397 /* Display it as active. */
4398 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
2bf04b9d 4399 cursor = 0;
9f5a911b
JR
4400 }
4401 else if (!NILP (mouse_face) && STRINGP (object))
4402 {
4403 Lisp_Object b, e;
4404 int ignore;
4405
4406 b = Fprevious_single_property_change (make_number (pos + 1),
4407 Qmouse_face,
4408 object, Qnil);
4409 e = Fnext_single_property_change (position, Qmouse_face,
4410 object, Qnil);
4411 if (NILP (b))
4412 b = make_number (0);
4413 if (NILP (e))
d5db4077 4414 e = make_number (SCHARS (object) - 1);
9f5a911b
JR
4415 fast_find_string_pos (w, XINT (b), object,
4416 &dpyinfo->mouse_face_beg_col,
4417 &dpyinfo->mouse_face_beg_row,
4418 &dpyinfo->mouse_face_beg_x,
4419 &dpyinfo->mouse_face_beg_y, 0);
4420 fast_find_string_pos (w, XINT (e), object,
4421 &dpyinfo->mouse_face_end_col,
4422 &dpyinfo->mouse_face_end_row,
4423 &dpyinfo->mouse_face_end_x,
4424 &dpyinfo->mouse_face_end_y, 1);
4425 dpyinfo->mouse_face_past_end = 0;
4426 dpyinfo->mouse_face_window = window;
4427 dpyinfo->mouse_face_face_id
4428 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
4429 glyph->face_id, 1);
4430 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
2bf04b9d 4431 cursor = 0;
9f5a911b
JR
4432 }
4433 else if (STRINGP (object) && NILP (mouse_face))
4434 {
4435 /* A string which doesn't have mouse-face, but
4436 the text ``under'' it might have. */
4437 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
4438 int start = MATRIX_ROW_START_CHARPOS (r);
d67d1627 4439
9f5a911b
JR
4440 pos = string_buffer_position (w, object, start);
4441 if (pos > 0)
4442 mouse_face = get_char_property_and_overlay (make_number (pos),
4443 Qmouse_face,
4444 w->buffer,
4445 &overlay);
4446 if (!NILP (mouse_face) && !NILP (overlay))
4447 {
4448 Lisp_Object before = Foverlay_start (overlay);
4449 Lisp_Object after = Foverlay_end (overlay);
6ff3e5e3 4450 int ignore;
9f5a911b
JR
4451
4452 /* Note that we might not be able to find position
4453 BEFORE in the glyph matrix if the overlay is
4454 entirely covered by a `display' property. In
4455 this case, we overshoot. So let's stop in
4456 the glyph matrix before glyphs for OBJECT. */
4457 fast_find_position (w, XFASTINT (before),
4458 &dpyinfo->mouse_face_beg_col,
4459 &dpyinfo->mouse_face_beg_row,
4460 &dpyinfo->mouse_face_beg_x,
4461 &dpyinfo->mouse_face_beg_y,
4462 object);
d67d1627 4463
9f5a911b
JR
4464 dpyinfo->mouse_face_past_end
4465 = !fast_find_position (w, XFASTINT (after),
4466 &dpyinfo->mouse_face_end_col,
4467 &dpyinfo->mouse_face_end_row,
4468 &dpyinfo->mouse_face_end_x,
4469 &dpyinfo->mouse_face_end_y,
4470 Qnil);
4471 dpyinfo->mouse_face_window = window;
4472 dpyinfo->mouse_face_face_id
4473 = face_at_buffer_position (w, pos, 0, 0,
1b7334a4
KS
4474 &ignore, pos + 1,
4475 !dpyinfo->mouse_face_hidden);
9f5a911b
JR
4476
4477 /* Display it as active. */
4478 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
2bf04b9d 4479 cursor = 0;
9f5a911b
JR
4480 }
4481 }
4482 }
4483
4484 check_help_echo:
4485
4486 /* Look for a `help-echo' property. */
791f420f 4487 {
9f5a911b
JR
4488 Lisp_Object help, overlay;
4489
4490 /* Check overlays first. */
4491 help = overlay = Qnil;
4492 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
791f420f 4493 {
9f5a911b 4494 overlay = overlay_vec[i];
d67d1627 4495 help = Foverlay_get (overlay, Qhelp_echo);
791f420f
JR
4496 }
4497
9f5a911b 4498 if (!NILP (help))
791f420f 4499 {
9f5a911b
JR
4500 help_echo = help;
4501 help_echo_window = window;
4502 help_echo_object = overlay;
4503 help_echo_pos = pos;
4504 }
4505 else
4506 {
4507 Lisp_Object object = glyph->object;
4508 int charpos = glyph->charpos;
ec48c3a7 4509
9f5a911b
JR
4510 /* Try text properties. */
4511 if (STRINGP (object)
4512 && charpos >= 0
d5db4077 4513 && charpos < SCHARS (object))
9f5a911b
JR
4514 {
4515 help = Fget_text_property (make_number (charpos),
4516 Qhelp_echo, object);
4517 if (NILP (help))
4518 {
4519 /* If the string itself doesn't specify a help-echo,
4520 see if the buffer text ``under'' it does. */
4521 struct glyph_row *r
4522 = MATRIX_ROW (w->current_matrix, vpos);
4523 int start = MATRIX_ROW_START_CHARPOS (r);
4524 int pos = string_buffer_position (w, object, start);
4525 if (pos > 0)
4526 {
4527 help = Fget_char_property (make_number (pos),
4528 Qhelp_echo, w->buffer);
4529 if (!NILP (help))
4530 {
4531 charpos = pos;
4532 object = w->buffer;
4533 }
4534 }
4535 }
4536 }
4537 else if (BUFFERP (object)
4538 && charpos >= BEGV
4539 && charpos < ZV)
4540 help = Fget_text_property (make_number (charpos), Qhelp_echo,
4541 object);
d67d1627 4542
9f5a911b
JR
4543 if (!NILP (help))
4544 {
4545 help_echo = help;
4546 help_echo_window = window;
4547 help_echo_object = object;
4548 help_echo_pos = charpos;
4549 }
4550 }
791f420f 4551 }
9f5a911b
JR
4552
4553 BEGV = obegv;
4554 ZV = ozv;
4555 current_buffer = obuf;
791f420f 4556 }
9f5a911b
JR
4557
4558 set_cursor:
2bf04b9d
JR
4559 if (cursor)
4560 w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
791f420f
JR
4561}
4562
791f420f
JR
4563static void
4564redo_mouse_highlight ()
4565{
4566 if (!NILP (last_mouse_motion_frame)
4567 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4568 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4569 LOWORD (last_mouse_motion_event.lParam),
4570 HIWORD (last_mouse_motion_event.lParam));
4571}
4572
2bf04b9d
JR
4573void
4574w32_define_cursor (window, cursor)
4575 Window window;
4576 Cursor cursor;
4577{
4578 PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
4579}
791f420f
JR
4580
4581\f
4582/***********************************************************************
4583 Tool-bars
4584 ***********************************************************************/
4585
4586static int x_tool_bar_item P_ ((struct frame *, int, int,
4587 struct glyph **, int *, int *, int *));
4588
4589/* Tool-bar item index of the item on which a mouse button was pressed
4590 or -1. */
4591
4592static int last_tool_bar_item;
4593
4594
4595/* Get information about the tool-bar item at position X/Y on frame F.
4596 Return in *GLYPH a pointer to the glyph of the tool-bar item in
4597 the current matrix of the tool-bar window of F, or NULL if not
4598 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
d417b5e0 4599 item in F->tool_bar_items. Value is
791f420f
JR
4600
4601 -1 if X/Y is not on a tool-bar item
4602 0 if X/Y is on the same item that was highlighted before.
4603 1 otherwise. */
4604
4605static int
4606x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
4607 struct frame *f;
4608 int x, y;
4609 struct glyph **glyph;
4610 int *hpos, *vpos, *prop_idx;
4611{
4612 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4613 struct window *w = XWINDOW (f->tool_bar_window);
4614 int area;
4615
4616 /* Find the glyph under X/Y. */
9f5a911b 4617 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
791f420f
JR
4618 if (*glyph == NULL)
4619 return -1;
4620
4621 /* Get the start of this tool-bar item's properties in
d417b5e0 4622 f->tool_bar_items. */
791f420f
JR
4623 if (!tool_bar_item_info (f, *glyph, prop_idx))
4624 return -1;
4625
4626 /* Is mouse on the highlighted item? */
4627 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
4628 && *vpos >= dpyinfo->mouse_face_beg_row
4629 && *vpos <= dpyinfo->mouse_face_end_row
4630 && (*vpos > dpyinfo->mouse_face_beg_row
4631 || *hpos >= dpyinfo->mouse_face_beg_col)
4632 && (*vpos < dpyinfo->mouse_face_end_row
4633 || *hpos < dpyinfo->mouse_face_end_col
4634 || dpyinfo->mouse_face_past_end))
4635 return 0;
d67d1627 4636
791f420f
JR
4637 return 1;
4638}
4639
4640
9ef2e2cf 4641/* Handle mouse button event on the tool-bar of frame F, at
791f420f
JR
4642 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4643 or ButtonRelase. */
4644
4645static void
4646w32_handle_tool_bar_click (f, button_event)
4647 struct frame *f;
4648 struct input_event *button_event;
4649{
4650 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4651 struct window *w = XWINDOW (f->tool_bar_window);
4652 int hpos, vpos, prop_idx;
4653 struct glyph *glyph;
4654 Lisp_Object enabled_p;
4655 int x = XFASTINT (button_event->x);
4656 int y = XFASTINT (button_event->y);
d67d1627 4657
791f420f
JR
4658 /* If not on the highlighted tool-bar item, return. */
4659 frame_to_window_pixel_xy (w, &x, &y);
4660 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
4661 return;
4662
4663 /* If item is disabled, do nothing. */
d417b5e0 4664 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
791f420f
JR
4665 if (NILP (enabled_p))
4666 return;
d67d1627 4667
d4ae780a 4668 if (button_event->modifiers & down_modifier)
791f420f
JR
4669 {
4670 /* Show item in pressed state. */
4671 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
4672 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
4673 last_tool_bar_item = prop_idx;
4674 }
4675 else
4676 {
4677 Lisp_Object key, frame;
4678 struct input_event event;
4679
4680 /* Show item in released state. */
4681 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
4682 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
4683
d417b5e0 4684 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
791f420f
JR
4685
4686 XSETFRAME (frame, f);
4687 event.kind = TOOL_BAR_EVENT;
c8b33aa6
GM
4688 event.frame_or_window = frame;
4689 event.arg = frame;
791f420f
JR
4690 kbd_buffer_store_event (&event);
4691
4692 event.kind = TOOL_BAR_EVENT;
c8b33aa6
GM
4693 event.frame_or_window = frame;
4694 event.arg = key;
d4ae780a
JR
4695 /* The keyboard buffer doesn't like the up modifier being set. */
4696 event.modifiers = button_event->modifiers & ~up_modifier;
791f420f
JR
4697 kbd_buffer_store_event (&event);
4698 last_tool_bar_item = -1;
4699 }
4700}
4701
4702
9ef2e2cf 4703/* Possibly highlight a tool-bar item on frame F when mouse moves to
791f420f
JR
4704 tool-bar window-relative coordinates X/Y. Called from
4705 note_mouse_highlight. */
4706
4707static void
4708note_tool_bar_highlight (f, x, y)
4709 struct frame *f;
4710 int x, y;
4711{
4712 Lisp_Object window = f->tool_bar_window;
4713 struct window *w = XWINDOW (window);
4714 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4715 int hpos, vpos;
4716 struct glyph *glyph;
4717 struct glyph_row *row;
4718 int i;
4719 Lisp_Object enabled_p;
4720 int prop_idx;
4721 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
4722 int mouse_down_p, rc;
4723
4724 /* Function note_mouse_highlight is called with negative x(y
4725 values when mouse moves outside of the frame. */
4726 if (x <= 0 || y <= 0)
4727 {
4728 clear_mouse_face (dpyinfo);
4729 return;
4730 }
4731
4732 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
4733 if (rc < 0)
4734 {
4735 /* Not on tool-bar item. */
4736 clear_mouse_face (dpyinfo);
4737 return;
4738 }
4739 else if (rc == 0)
4740 /* On same tool-bar item as before. */
4741 goto set_help_echo;
ee78dc32 4742
791f420f 4743 clear_mouse_face (dpyinfo);
d67d1627 4744
791f420f
JR
4745 /* Mouse is down, but on different tool-bar item? */
4746 mouse_down_p = (dpyinfo->grabbed
4747 && f == last_mouse_frame
4748 && FRAME_LIVE_P (f));
4749 if (mouse_down_p
4750 && last_tool_bar_item != prop_idx)
4751 return;
ee78dc32 4752
791f420f
JR
4753 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
4754 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
d67d1627 4755
791f420f 4756 /* If tool-bar item is not enabled, don't highlight it. */
d417b5e0 4757 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
791f420f
JR
4758 if (!NILP (enabled_p))
4759 {
4760 /* Compute the x-position of the glyph. In front and past the
4761 image is a space. We include this is the highlighted area. */
4762 row = MATRIX_ROW (w->current_matrix, vpos);
4763 for (i = x = 0; i < hpos; ++i)
4764 x += row->glyphs[TEXT_AREA][i].pixel_width;
d67d1627 4765
791f420f
JR
4766 /* Record this as the current active region. */
4767 dpyinfo->mouse_face_beg_col = hpos;
4768 dpyinfo->mouse_face_beg_row = vpos;
4769 dpyinfo->mouse_face_beg_x = x;
4770 dpyinfo->mouse_face_beg_y = row->y;
4771 dpyinfo->mouse_face_past_end = 0;
d67d1627 4772
791f420f
JR
4773 dpyinfo->mouse_face_end_col = hpos + 1;
4774 dpyinfo->mouse_face_end_row = vpos;
4775 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
4776 dpyinfo->mouse_face_end_y = row->y;
4777 dpyinfo->mouse_face_window = window;
4778 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
d67d1627 4779
791f420f
JR
4780 /* Display it as active. */
4781 show_mouse_face (dpyinfo, draw);
4782 dpyinfo->mouse_face_image_state = draw;
ee78dc32 4783 }
d67d1627 4784
791f420f 4785 set_help_echo:
d67d1627 4786
791f420f
JR
4787 /* Set help_echo to a help string.to display for this tool-bar item.
4788 w32_read_socket does the rest. */
158cba56 4789 help_echo_object = help_echo_window = Qnil;
ec48c3a7 4790 help_echo_pos = -1;
d417b5e0 4791 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
b7e80413 4792 if (NILP (help_echo))
d417b5e0 4793 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
ee78dc32 4794}
ee78dc32 4795
9ef2e2cf 4796
791f420f 4797\f
9f5a911b
JR
4798/* Find the glyph matrix position of buffer position CHARPOS in window
4799 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
4800 current glyphs must be up to date. If CHARPOS is above window
4801 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
4802 of last line in W. In the row containing CHARPOS, stop before glyphs
4803 having STOP as object. */
4804
4805#if 0 /* This is a version of fast_find_position that's more correct
4806 in the presence of hscrolling, for example. I didn't install
4807 it right away because the problem fixed is minor, it failed
d67d1627 4808 in 20.x as well, and I think it's too risky to install
9f5a911b 4809 so near the release of 21.1. 2001-09-25 gerd. */
ee78dc32
GV
4810
4811static int
9f5a911b
JR
4812fast_find_position (w, charpos, hpos, vpos, x, y, stop)
4813 struct window *w;
4814 int charpos;
4815 int *hpos, *vpos, *x, *y;
4816 Lisp_Object stop;
4817{
4818 struct glyph_row *row, *first;
4819 struct glyph *glyph, *end;
4820 int i, past_end = 0;
4821
4822 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
62e33982 4823 row = row_containing_pos (w, charpos, first, NULL, 0);
9f5a911b
JR
4824 if (row == NULL)
4825 {
4826 if (charpos < MATRIX_ROW_START_CHARPOS (first))
4827 {
4828 *x = *y = *hpos = *vpos = 0;
4829 return 0;
4830 }
4831 else
4832 {
4833 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
4834 past_end = 1;
4835 }
4836 }
4837
4838 *x = row->x;
4839 *y = row->y;
4840 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
d67d1627 4841
9f5a911b
JR
4842 glyph = row->glyphs[TEXT_AREA];
4843 end = glyph + row->used[TEXT_AREA];
d67d1627 4844
9f5a911b
JR
4845 /* Skip over glyphs not having an object at the start of the row.
4846 These are special glyphs like truncation marks on terminal
4847 frames. */
4848 if (row->displays_text_p)
4849 while (glyph < end
4850 && INTEGERP (glyph->object)
4851 && !EQ (stop, glyph->object)
4852 && glyph->charpos < 0)
4853 {
4854 *x += glyph->pixel_width;
4855 ++glyph;
4856 }
4857
4858 while (glyph < end
4859 && !INTEGERP (glyph->object)
4860 && !EQ (stop, glyph->object)
4861 && (!BUFFERP (glyph->object)
4862 || glyph->charpos < charpos))
4863 {
4864 *x += glyph->pixel_width;
4865 ++glyph;
4866 }
4867
4868 *hpos = glyph - row->glyphs[TEXT_AREA];
4869 return past_end;
4870}
4871
4872#else /* not 0 */
4873
4874static int
4875fast_find_position (w, pos, hpos, vpos, x, y, stop)
791f420f 4876 struct window *w;
ee78dc32 4877 int pos;
791f420f 4878 int *hpos, *vpos, *x, *y;
9f5a911b 4879 Lisp_Object stop;
ee78dc32 4880{
ee78dc32 4881 int i;
ee78dc32 4882 int lastcol;
791f420f
JR
4883 int maybe_next_line_p = 0;
4884 int line_start_position;
4885 int yb = window_text_bottom_y (w);
9f5a911b
JR
4886 struct glyph_row *row, *best_row;
4887 int row_vpos, best_row_vpos;
791f420f
JR
4888 int current_x;
4889
9f5a911b
JR
4890 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
4891 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
4892
791f420f 4893 while (row->y < yb)
ee78dc32 4894 {
791f420f
JR
4895 if (row->used[TEXT_AREA])
4896 line_start_position = row->glyphs[TEXT_AREA]->charpos;
4897 else
4898 line_start_position = 0;
4899
4900 if (line_start_position > pos)
ee78dc32
GV
4901 break;
4902 /* If the position sought is the end of the buffer,
4903 don't include the blank lines at the bottom of the window. */
791f420f
JR
4904 else if (line_start_position == pos
4905 && pos == BUF_ZV (XBUFFER (w->buffer)))
ee78dc32 4906 {
791f420f 4907 maybe_next_line_p = 1;
ee78dc32
GV
4908 break;
4909 }
791f420f
JR
4910 else if (line_start_position > 0)
4911 {
4912 best_row = row;
4913 best_row_vpos = row_vpos;
4914 }
4915
9ef2e2cf
JR
4916 if (row->y + row->height >= yb)
4917 break;
4918
791f420f
JR
4919 ++row;
4920 ++row_vpos;
ee78dc32
GV
4921 }
4922
791f420f
JR
4923 /* Find the right column within BEST_ROW. */
4924 lastcol = 0;
4925 current_x = best_row->x;
4926 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
ee78dc32 4927 {
791f420f 4928 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
9f5a911b 4929 int charpos = glyph->charpos;
791f420f 4930
9f5a911b 4931 if (BUFFERP (glyph->object))
ee78dc32 4932 {
9f5a911b
JR
4933 if (charpos == pos)
4934 {
4935 *hpos = i;
4936 *vpos = best_row_vpos;
4937 *x = current_x;
4938 *y = best_row->y;
4939 return 1;
4940 }
4941 else if (charpos > pos)
4942 break;
ee78dc32 4943 }
9f5a911b 4944 else if (EQ (glyph->object, stop))
ee78dc32 4945 break;
791f420f 4946
9f5a911b
JR
4947 if (charpos > 0)
4948 lastcol = i;
791f420f 4949 current_x += glyph->pixel_width;
ee78dc32
GV
4950 }
4951
4952 /* If we're looking for the end of the buffer,
4953 and we didn't find it in the line we scanned,
4954 use the start of the following line. */
791f420f 4955 if (maybe_next_line_p)
ee78dc32 4956 {
791f420f
JR
4957 ++best_row;
4958 ++best_row_vpos;
4959 lastcol = 0;
4960 current_x = best_row->x;
ee78dc32
GV
4961 }
4962
791f420f
JR
4963 *vpos = best_row_vpos;
4964 *hpos = lastcol + 1;
4965 *x = current_x;
4966 *y = best_row->y;
ee78dc32
GV
4967 return 0;
4968}
4969
9f5a911b
JR
4970#endif /* not 0 */
4971
4972
269b7745 4973/* Find the position of the glyph for position POS in OBJECT in
9f5a911b
JR
4974 window W's current matrix, and return in *X/*Y the pixel
4975 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
4976
4977 RIGHT_P non-zero means return the position of the right edge of the
4978 glyph, RIGHT_P zero means return the left edge position.
4979
4980 If no glyph for POS exists in the matrix, return the position of
4981 the glyph with the next smaller position that is in the matrix, if
4982 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
4983 exists in the matrix, return the position of the glyph with the
4984 next larger position in OBJECT.
4985
4986 Value is non-zero if a glyph was found. */
4987
4988static int
4989fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
4990 struct window *w;
4991 int pos;
4992 Lisp_Object object;
4993 int *hpos, *vpos, *x, *y;
4994 int right_p;
4995{
4996 int yb = window_text_bottom_y (w);
4997 struct glyph_row *r;
4998 struct glyph *best_glyph = NULL;
4999 struct glyph_row *best_row = NULL;
5000 int best_x = 0;
5001
5002 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
5003 r->enabled_p && r->y < yb;
5004 ++r)
5005 {
5006 struct glyph *g = r->glyphs[TEXT_AREA];
5007 struct glyph *e = g + r->used[TEXT_AREA];
5008 int gx;
5009
5010 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
5011 if (EQ (g->object, object))
5012 {
5013 if (g->charpos == pos)
5014 {
5015 best_glyph = g;
5016 best_x = gx;
5017 best_row = r;
5018 goto found;
5019 }
5020 else if (best_glyph == NULL
5021 || ((abs (g->charpos - pos)
5022 < abs (best_glyph->charpos - pos))
5023 && (right_p
5024 ? g->charpos < pos
5025 : g->charpos > pos)))
5026 {
5027 best_glyph = g;
5028 best_x = gx;
5029 best_row = r;
5030 }
5031 }
5032 }
5033
5034 found:
5035
5036 if (best_glyph)
5037 {
5038 *x = best_x;
5039 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
5040
5041 if (right_p)
5042 {
5043 *x += best_glyph->pixel_width;
5044 ++*hpos;
5045 }
d67d1627 5046
9f5a911b
JR
5047 *y = best_row->y;
5048 *vpos = best_row - w->current_matrix->rows;
5049 }
5050
5051 return best_glyph != NULL;
5052}
5053
791f420f 5054
ee78dc32
GV
5055/* Display the active region described by mouse_face_*
5056 in its mouse-face if HL > 0, in its normal face if HL = 0. */
5057
5058static void
791f420f 5059show_mouse_face (dpyinfo, draw)
fbd6baed 5060 struct w32_display_info *dpyinfo;
791f420f 5061 enum draw_glyphs_face draw;
ee78dc32
GV
5062{
5063 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
791f420f 5064 struct frame *f = XFRAME (WINDOW_FRAME (w));
d67d1627 5065
6ff3e5e3
JR
5066 if (/* If window is in the process of being destroyed, don't bother
5067 to do anything. */
5068 w->current_matrix != NULL
3d26a7c2
KS
5069 /* Don't update mouse highlight if hidden */
5070 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
6ff3e5e3
JR
5071 /* Recognize when we are called to operate on rows that don't exist
5072 anymore. This can happen when a window is split. */
5073 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
5074 {
5075 int phys_cursor_on_p = w->phys_cursor_on_p;
5076 struct glyph_row *row, *first, *last;
5077
5078 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
5079 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
d67d1627 5080
6ff3e5e3
JR
5081 for (row = first; row <= last && row->enabled_p; ++row)
5082 {
5083 int start_hpos, end_hpos, start_x;
791f420f 5084
6ff3e5e3
JR
5085 /* For all but the first row, the highlight starts at column 0. */
5086 if (row == first)
5087 {
5088 start_hpos = dpyinfo->mouse_face_beg_col;
5089 start_x = dpyinfo->mouse_face_beg_x;
5090 }
5091 else
5092 {
5093 start_hpos = 0;
5094 start_x = 0;
5095 }
791f420f 5096
6ff3e5e3
JR
5097 if (row == last)
5098 end_hpos = dpyinfo->mouse_face_end_col;
5099 else
5100 end_hpos = row->used[TEXT_AREA];
791f420f 5101
6ff3e5e3
JR
5102 if (end_hpos > start_hpos)
5103 {
d67d1627 5104 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6ff3e5e3 5105 start_hpos, end_hpos, draw, 0);
791f420f 5106
6637c996
JR
5107 row->mouse_face_p
5108 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
6ff3e5e3 5109 }
ee78dc32
GV
5110 }
5111
6ff3e5e3
JR
5112 /* When we've written over the cursor, arrange for it to
5113 be displayed again. */
5114 if (phys_cursor_on_p && !w->phys_cursor_on_p)
5115 x_display_cursor (w, 1,
5116 w->phys_cursor.hpos, w->phys_cursor.vpos,
5117 w->phys_cursor.x, w->phys_cursor.y);
ee78dc32
GV
5118 }
5119
791f420f
JR
5120 /* Change the mouse cursor. */
5121 if (draw == DRAW_NORMAL_TEXT)
2bf04b9d
JR
5122 w32_define_cursor (FRAME_W32_WINDOW (f),
5123 f->output_data.w32->text_cursor);
791f420f 5124 else if (draw == DRAW_MOUSE_FACE)
2bf04b9d
JR
5125 w32_define_cursor (FRAME_W32_WINDOW (f),
5126 f->output_data.w32->hand_cursor);
ee78dc32 5127 else
2bf04b9d
JR
5128 w32_define_cursor (FRAME_W32_WINDOW (f),
5129 f->output_data.w32->nontext_cursor);
5130
ee78dc32
GV
5131}
5132
5133/* Clear out the mouse-highlighted active region.
9ef2e2cf 5134 Redraw it un-highlighted first. */
ee78dc32 5135
9f5a911b 5136static int
ee78dc32 5137clear_mouse_face (dpyinfo)
fbd6baed 5138 struct w32_display_info *dpyinfo;
ee78dc32 5139{
9f5a911b 5140 int cleared = 0;
791f420f 5141
ee78dc32 5142 if (! NILP (dpyinfo->mouse_face_window))
9f5a911b
JR
5143 {
5144 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
5145 cleared = 1;
5146 }
ee78dc32
GV
5147
5148 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
5149 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
5150 dpyinfo->mouse_face_window = Qnil;
9f5a911b
JR
5151 dpyinfo->mouse_face_overlay = Qnil;
5152 return cleared;
ee78dc32 5153}
31d4844a 5154
ec48c3a7
JR
5155
5156/* Clear any mouse-face on window W. This function is part of the
5157 redisplay interface, and is called from try_window_id and similar
5158 functions to ensure the mouse-highlight is off. */
5159
5160static void
5161x_clear_mouse_face (w)
5162 struct window *w;
5163{
5164 struct w32_display_info *dpyinfo
5165 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
5166 Lisp_Object window;
5167
9127e20e 5168 BLOCK_INPUT;
ec48c3a7
JR
5169 XSETWINDOW (window, w);
5170 if (EQ (window, dpyinfo->mouse_face_window))
5171 clear_mouse_face (dpyinfo);
9127e20e 5172 UNBLOCK_INPUT;
ec48c3a7
JR
5173}
5174
5175
31d4844a
KH
5176/* Just discard the mouse face information for frame F, if any.
5177 This is used when the size of F is changed. */
5178
5179void
5180cancel_mouse_face (f)
5181 FRAME_PTR f;
5182{
5183 Lisp_Object window;
5184 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5185
5186 window = dpyinfo->mouse_face_window;
5187 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
5188 {
5189 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
5190 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
5191 dpyinfo->mouse_face_window = Qnil;
5192 }
5193}
ee78dc32 5194\f
9ef2e2cf 5195static struct scroll_bar *x_window_to_scroll_bar ();
ee78dc32 5196static void x_scroll_bar_report_motion ();
549808db
JR
5197static void x_check_fullscreen P_ ((struct frame *));
5198static void x_check_fullscreen_move P_ ((struct frame *));
9f5a911b
JR
5199static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
5200
5201
5202/* Try to determine frame pixel position and size of the glyph under
5203 frame pixel coordinates X/Y on frame F . Return the position and
5204 size in *RECT. Value is non-zero if we could compute these
5205 values. */
5206
5207static int
5208glyph_rect (f, x, y, rect)
5209 struct frame *f;
5210 int x, y;
5211 RECT *rect;
5212{
5213 Lisp_Object window;
1e2eddb4 5214 int part;
9f5a911b
JR
5215
5216 window = window_from_coordinates (f, x, y, &part, 0);
5217 if (!NILP (window))
5218 {
5219 struct window *w = XWINDOW (window);
5220 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
5221 struct glyph_row *end = r + w->current_matrix->nrows - 1;
9f5a911b
JR
5222
5223 frame_to_window_pixel_xy (w, &x, &y);
1e2eddb4
JR
5224
5225 for (; r < end && r->enabled_p; ++r)
5226 if (r->y <= y && r->y + r->height > y)
9f5a911b 5227 {
1e2eddb4 5228 /* Found the row at y. */
9f5a911b
JR
5229 struct glyph *g = r->glyphs[TEXT_AREA];
5230 struct glyph *end = g + r->used[TEXT_AREA];
5231 int gx;
1e2eddb4
JR
5232
5233 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
5234 rect->bottom = rect->top + r->height;
5235
5236 if (x < r->x)
5237 {
5238 /* x is to the left of the first glyph in the row. */
5239 rect->left = XINT (w->left);
5240 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
5241 return 1;
5242 }
5243
5244 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
5245 if (gx <= x && gx + g->pixel_width > x)
9f5a911b 5246 {
1e2eddb4 5247 /* x is on a glyph. */
9f5a911b 5248 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
9f5a911b 5249 rect->right = rect->left + g->pixel_width;
1e2eddb4 5250 return 1;
9f5a911b 5251 }
1e2eddb4
JR
5252
5253 /* x is to the right of the last glyph in the row. */
5254 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
5255 rect->right = XINT (w->left) + XINT (w->width);
5256 return 1;
9f5a911b
JR
5257 }
5258 }
5259
1e2eddb4
JR
5260 /* The y is not on any row. */
5261 return 0;
9f5a911b
JR
5262}
5263
5264/* Record the position of the mouse in last_mouse_glyph. */
565153ff
JR
5265static void
5266remember_mouse_glyph (f1, gx, gy)
9f5a911b
JR
5267 struct frame * f1;
5268 int gx, gy;
5269{
5270 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
5271 {
5272 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
5273 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
5274
5275 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
5276 round down even for negative values. */
5277 if (gx < 0)
5278 gx -= width - 1;
5279 if (gy < 0)
5280 gy -= height - 1;
5281#if 0
5282 /* This was the original code from XTmouse_position, but it seems
5283 to give the position of the glyph diagonally next to the one
5284 the mouse is over. */
5285 gx = (gx + width - 1) / width * width;
5286 gy = (gy + height - 1) / height * height;
5287#else
5288 gx = gx / width * width;
5289 gy = gy / height * height;
5290#endif
5291
5292 last_mouse_glyph.left = gx;
5293 last_mouse_glyph.top = gy;
5294 last_mouse_glyph.right = gx + width;
5295 last_mouse_glyph.bottom = gy + height;
5296 }
5297}
ee78dc32
GV
5298
5299/* Return the current position of the mouse.
5300 *fp should be a frame which indicates which display to ask about.
5301
5302 If the mouse movement started in a scroll bar, set *fp, *bar_window,
5303 and *part to the frame, window, and scroll bar part that the mouse
5304 is over. Set *x and *y to the portion and whole of the mouse's
5305 position on the scroll bar.
5306
5307 If the mouse movement started elsewhere, set *fp to the frame the
5308 mouse is on, *bar_window to nil, and *x and *y to the character cell
5309 the mouse is over.
5310
9ef2e2cf 5311 Set *time to the server time-stamp for the time at which the mouse
ee78dc32
GV
5312 was at this position.
5313
5314 Don't store anything if we don't have a valid set of values to report.
5315
5316 This clears the mouse_moved flag, so we can wait for the next mouse
9ef2e2cf 5317 movement. */
ee78dc32
GV
5318
5319static void
fbd6baed 5320w32_mouse_position (fp, insist, bar_window, part, x, y, time)
ee78dc32
GV
5321 FRAME_PTR *fp;
5322 int insist;
5323 Lisp_Object *bar_window;
5324 enum scroll_bar_part *part;
5325 Lisp_Object *x, *y;
5326 unsigned long *time;
5327{
5328 FRAME_PTR f1;
5329
5330 BLOCK_INPUT;
5331
95fa970d 5332 if (! NILP (last_mouse_scroll_bar) && insist == 0)
ee78dc32
GV
5333 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
5334 else
5335 {
5336 POINT pt;
5337
5338 Lisp_Object frame, tail;
5339
5340 /* Clear the mouse-moved flag for every frame on this display. */
5341 FOR_EACH_FRAME (tail, frame)
5342 XFRAME (frame)->mouse_moved = 0;
5343
5344 last_mouse_scroll_bar = Qnil;
d67d1627 5345
ee78dc32
GV
5346 GetCursorPos (&pt);
5347
5348 /* Now we have a position on the root; find the innermost window
5349 containing the pointer. */
5350 {
fbd6baed 5351 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
ee78dc32
GV
5352 && FRAME_LIVE_P (last_mouse_frame))
5353 {
08712a41
AI
5354 /* If mouse was grabbed on a frame, give coords for that frame
5355 even if the mouse is now outside it. */
ee78dc32
GV
5356 f1 = last_mouse_frame;
5357 }
5358 else
5359 {
08712a41 5360 /* Is window under mouse one of our frames? */
9f5a911b 5361 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
9127e20e 5362 WindowFromPoint (pt));
ee78dc32
GV
5363 }
5364
5365 /* If not, is it one of our scroll bars? */
5366 if (! f1)
5367 {
9127e20e
JR
5368 struct scroll_bar *bar
5369 = x_window_to_scroll_bar (WindowFromPoint (pt));
ee78dc32
GV
5370
5371 if (bar)
5372 {
5373 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5374 }
5375 }
5376
95fa970d 5377 if (f1 == 0 && insist > 0)
791f420f 5378 f1 = SELECTED_FRAME ();
ee78dc32
GV
5379
5380 if (f1)
5381 {
791f420f
JR
5382 /* Ok, we found a frame. Store all the values.
5383 last_mouse_glyph is a rectangle used to reduce the
5384 generation of mouse events. To not miss any motion
5385 events, we must divide the frame into rectangles of the
5386 size of the smallest character that could be displayed
5387 on it, i.e. into the same rectangles that matrices on
5388 the frame are divided into. */
5389
5390#if OLD_REDISPLAY_CODE
ee78dc32
GV
5391 int ignore1, ignore2;
5392
fbd6baed 5393 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
ee78dc32 5394
ee78dc32
GV
5395 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
5396 &last_mouse_glyph,
fbd6baed 5397 FRAME_W32_DISPLAY_INFO (f1)->grabbed
ee78dc32 5398 || insist);
791f420f
JR
5399#else
5400 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
9f5a911b 5401 remember_mouse_glyph (f1, pt.x, pt.y);
791f420f 5402#endif
ee78dc32
GV
5403
5404 *bar_window = Qnil;
5405 *part = 0;
5406 *fp = f1;
5407 XSETINT (*x, pt.x);
5408 XSETINT (*y, pt.y);
5409 *time = last_mouse_movement_time;
5410 }
5411 }
5412 }
5413
5414 UNBLOCK_INPUT;
5415}
791f420f 5416
ee78dc32
GV
5417\f
5418/* Scroll bar support. */
5419
ec48c3a7 5420/* Given a window ID, find the struct scroll_bar which manages it.
ee78dc32
GV
5421 This can be called in GC, so we have to make sure to strip off mark
5422 bits. */
9ef2e2cf
JR
5423
5424static struct scroll_bar *
ee78dc32
GV
5425x_window_to_scroll_bar (window_id)
5426 Window window_id;
5427{
791f420f 5428 Lisp_Object tail;
ee78dc32
GV
5429
5430 for (tail = Vframe_list;
5431 XGCTYPE (tail) == Lisp_Cons;
8e713be6 5432 tail = XCDR (tail))
ee78dc32
GV
5433 {
5434 Lisp_Object frame, bar, condemned;
5435
8e713be6 5436 frame = XCAR (tail);
ee78dc32
GV
5437 /* All elements of Vframe_list should be frames. */
5438 if (! GC_FRAMEP (frame))
5439 abort ();
5440
5441 /* Scan this frame's scroll bar list for a scroll bar with the
5442 right window ID. */
5443 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
5444 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
5445 /* This trick allows us to search both the ordinary and
5446 condemned scroll bar lists with one loop. */
5447 ! GC_NILP (bar) || (bar = condemned,
5448 condemned = Qnil,
5449 ! GC_NILP (bar));
5450 bar = XSCROLL_BAR (bar)->next)
fbd6baed 5451 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
ee78dc32
GV
5452 return XSCROLL_BAR (bar);
5453 }
5454
5455 return 0;
5456}
5457
791f420f
JR
5458
5459\f
5460/* Set the thumb size and position of scroll bar BAR. We are currently
5461 displaying PORTION out of a whole WHOLE, and our position POSITION. */
5462
5463static void
5464w32_set_scroll_bar_thumb (bar, portion, position, whole)
5465 struct scroll_bar *bar;
5466 int portion, position, whole;
5467{
5468 Window w = SCROLL_BAR_W32_WINDOW (bar);
d8e675f5 5469 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
791f420f
JR
5470 int sb_page, sb_pos;
5471 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
5472
5473 if (whole)
5474 {
5475 /* Position scroll bar at rock bottom if the bottom of the
5476 buffer is visible. This avoids shinking the thumb away
5477 to nothing if it is held at the bottom of the buffer. */
5478 if (position + portion >= whole)
5479 {
5480 sb_page = range * (whole - position) / whole
5481 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5482 sb_pos = range;
5483 }
5484
5485 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
5486 sb_pos = position * range / whole;
5487 }
5488 else
5489 {
5490 sb_page = range;
5491 sb_pos = 0;
5492 }
5493
5494 BLOCK_INPUT;
5495
5496 if (pfnSetScrollInfo)
5497 {
5498 SCROLLINFO si;
5499
5500 si.cbSize = sizeof (si);
5501 /* Only update page size if currently dragging, to reduce
5502 flicker effects. */
5503 if (draggingp)
5504 si.fMask = SIF_PAGE;
5505 else
5506 si.fMask = SIF_PAGE | SIF_POS;
5507 si.nPage = sb_page;
5508 si.nPos = sb_pos;
5509
5510 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
5511 }
5512 else
5513 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
5514
5515 UNBLOCK_INPUT;
5516}
5517
5518\f
5519/************************************************************************
5520 Scroll bars, general
5521 ************************************************************************/
d67d1627
JB
5522
5523HWND
ee78dc32
GV
5524my_create_scrollbar (f, bar)
5525 struct frame * f;
5526 struct scroll_bar * bar;
5527{
689004fa 5528 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
d67d1627 5529 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
689004fa 5530 (LPARAM) bar);
ee78dc32
GV
5531}
5532
ab76d376 5533/*#define ATTACH_THREADS*/
52cf03a1 5534
689004fa
GV
5535BOOL
5536my_show_window (FRAME_PTR f, HWND hwnd, int how)
52cf03a1
GV
5537{
5538#ifndef ATTACH_THREADS
689004fa
GV
5539 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
5540 (WPARAM) hwnd, (LPARAM) how);
52cf03a1 5541#else
689004fa 5542 return ShowWindow (hwnd, how);
52cf03a1
GV
5543#endif
5544}
5545
5546void
5547my_set_window_pos (HWND hwnd, HWND hwndAfter,
689004fa 5548 int x, int y, int cx, int cy, UINT flags)
52cf03a1
GV
5549{
5550#ifndef ATTACH_THREADS
689004fa
GV
5551 WINDOWPOS pos;
5552 pos.hwndInsertAfter = hwndAfter;
52cf03a1
GV
5553 pos.x = x;
5554 pos.y = y;
5555 pos.cx = cx;
5556 pos.cy = cy;
5557 pos.flags = flags;
5558 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
5559#else
5560 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
5561#endif
5562}
5563
ec48c3a7 5564void
689004fa
GV
5565my_set_focus (f, hwnd)
5566 struct frame * f;
5567 HWND hwnd;
5568{
d67d1627 5569 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
689004fa
GV
5570 (WPARAM) hwnd, 0);
5571}
5572
ec48c3a7 5573void
ef0e360f
GV
5574my_set_foreground_window (hwnd)
5575 HWND hwnd;
5576{
5577 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
5578}
5579
ee78dc32
GV
5580void
5581my_destroy_window (f, hwnd)
5582 struct frame * f;
5583 HWND hwnd;
5584{
d67d1627 5585 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
ee78dc32
GV
5586 (WPARAM) hwnd, 0);
5587}
5588
791f420f
JR
5589/* Create a scroll bar and return the scroll bar vector for it. W is
5590 the Emacs window on which to create the scroll bar. TOP, LEFT,
5591 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
5592 scroll bar. */
5593
ee78dc32 5594static struct scroll_bar *
791f420f
JR
5595x_scroll_bar_create (w, top, left, width, height)
5596 struct window *w;
ee78dc32
GV
5597 int top, left, width, height;
5598{
791f420f
JR
5599 struct frame *f = XFRAME (WINDOW_FRAME (w));
5600 HWND hwnd;
ee78dc32
GV
5601 struct scroll_bar *bar
5602 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
ee78dc32
GV
5603
5604 BLOCK_INPUT;
5605
791f420f 5606 XSETWINDOW (bar->window, w);
ee78dc32
GV
5607 XSETINT (bar->top, top);
5608 XSETINT (bar->left, left);
5609 XSETINT (bar->width, width);
5610 XSETINT (bar->height, height);
5611 XSETINT (bar->start, 0);
5612 XSETINT (bar->end, 0);
5613 bar->dragging = Qnil;
5614
5615 /* Requires geometry to be set before call to create the real window */
5616
5617 hwnd = my_create_scrollbar (f, bar);
5618
689004fa
GV
5619 if (pfnSetScrollInfo)
5620 {
5621 SCROLLINFO si;
5622
5623 si.cbSize = sizeof (si);
5624 si.fMask = SIF_ALL;
5625 si.nMin = 0;
791f420f
JR
5626 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
5627 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
689004fa
GV
5628 si.nPage = si.nMax;
5629 si.nPos = 0;
5630
5631 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
5632 }
5633 else
5634 {
791f420f
JR
5635 SetScrollRange (hwnd, SB_CTL, 0,
5636 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
689004fa
GV
5637 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
5638 }
ee78dc32 5639
fbd6baed 5640 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
ee78dc32
GV
5641
5642 /* Add bar to its frame's list of scroll bars. */
5643 bar->next = FRAME_SCROLL_BARS (f);
5644 bar->prev = Qnil;
5645 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5646 if (! NILP (bar->next))
5647 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5648
5649 UNBLOCK_INPUT;
5650
5651 return bar;
5652}
5653
ee78dc32 5654
791f420f
JR
5655/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
5656 nil. */
ee78dc32 5657
ee78dc32
GV
5658static void
5659x_scroll_bar_remove (bar)
5660 struct scroll_bar *bar;
5661{
5662 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5663
5664 BLOCK_INPUT;
5665
5666 /* Destroy the window. */
fbd6baed 5667 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
ee78dc32
GV
5668
5669 /* Disassociate this scroll bar from its window. */
5670 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
5671
5672 UNBLOCK_INPUT;
5673}
5674
5675/* Set the handle of the vertical scroll bar for WINDOW to indicate
5676 that we are displaying PORTION characters out of a total of WHOLE
5677 characters, starting at POSITION. If WINDOW has no scroll bar,
5678 create one. */
5679static void
791f420f
JR
5680w32_set_vertical_scroll_bar (w, portion, whole, position)
5681 struct window *w;
ee78dc32
GV
5682 int portion, whole, position;
5683{
791f420f 5684 struct frame *f = XFRAME (w->frame);
ee78dc32 5685 struct scroll_bar *bar;
9ef2e2cf 5686 int top, height, left, sb_left, width, sb_width;
791f420f
JR
5687 int window_x, window_y, window_width, window_height;
5688
5689 /* Get window dimensions. */
5690 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5691 top = window_y;
5692 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
5693 height = window_height;
5694
5695 /* Compute the left edge of the scroll bar area. */
5696 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5697 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
5698 else
5699 left = XFASTINT (w->left);
5700 left *= CANON_X_UNIT (f);
5701 left += FRAME_INTERNAL_BORDER_WIDTH (f);
5702
5703 /* Compute the width of the scroll bar which might be less than
5704 the width of the area reserved for the scroll bar. */
5705 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
5706 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
5707 else
5708 sb_width = width;
ee78dc32 5709
791f420f
JR
5710 /* Compute the left edge of the scroll bar. */
5711 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
d67d1627 5712 sb_left = left + width - sb_width - (width - sb_width) / 2;
ee78dc32 5713 else
791f420f
JR
5714 sb_left = left + (width - sb_width) / 2;
5715
5716 /* Does the scroll bar exist yet? */
5717 if (NILP (w->vertical_scroll_bar))
ee78dc32 5718 {
00fe468b 5719 HDC hdc;
791f420f 5720 BLOCK_INPUT;
6ff3e5e3 5721 if (width > 0 && height > 0)
9f5a911b
JR
5722 {
5723 hdc = get_frame_dc (f);
5724 w32_clear_area (f, hdc, left, top, width, height);
5725 release_frame_dc (f, hdc);
5726 }
791f420f 5727 UNBLOCK_INPUT;
00fe468b 5728
791f420f 5729 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
ee78dc32 5730 }
791f420f
JR
5731 else
5732 {
d67d1627 5733 /* It may just need to be moved and resized. */
791f420f
JR
5734 HWND hwnd;
5735
5736 bar = XSCROLL_BAR (w->vertical_scroll_bar);
5737 hwnd = SCROLL_BAR_W32_WINDOW (bar);
5738
5739 /* If already correctly positioned, do nothing. */
5740 if ( XINT (bar->left) == sb_left
5741 && XINT (bar->top) == top
5742 && XINT (bar->width) == sb_width
5743 && XINT (bar->height) == height )
5744 {
5745 /* Redraw after clear_frame. */
5746 if (!my_show_window (f, hwnd, SW_NORMAL))
5747 InvalidateRect (hwnd, NULL, FALSE);
5748 }
5749 else
5750 {
00fe468b 5751 HDC hdc;
791f420f 5752 BLOCK_INPUT;
9f5a911b
JR
5753 if (width && height)
5754 {
5755 hdc = get_frame_dc (f);
5756 /* Since Windows scroll bars are smaller than the space reserved
5757 for them on the frame, we have to clear "under" them. */
5758 w32_clear_area (f, hdc,
5759 left,
5760 top,
5761 width,
5762 height);
5763 release_frame_dc (f, hdc);
5764 }
791f420f
JR
5765 /* Make sure scroll bar is "visible" before moving, to ensure the
5766 area of the parent window now exposed will be refreshed. */
5767 my_show_window (f, hwnd, SW_HIDE);
9f5a911b
JR
5768 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5769 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5770 max (height, 1), TRUE);
791f420f
JR
5771 if (pfnSetScrollInfo)
5772 {
5773 SCROLLINFO si;
ee78dc32 5774
791f420f
JR
5775 si.cbSize = sizeof (si);
5776 si.fMask = SIF_RANGE;
5777 si.nMin = 0;
5778 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
5779 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
ee78dc32 5780
00fe468b 5781 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
791f420f
JR
5782 }
5783 else
00fe468b 5784 SetScrollRange (hwnd, SB_CTL, 0,
791f420f
JR
5785 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
5786 my_show_window (f, hwnd, SW_NORMAL);
ab76d376 5787 /* InvalidateRect (w, NULL, FALSE); */
791f420f
JR
5788
5789 /* Remember new settings. */
5790 XSETINT (bar->left, sb_left);
5791 XSETINT (bar->top, top);
5792 XSETINT (bar->width, sb_width);
5793 XSETINT (bar->height, height);
5794
5795 UNBLOCK_INPUT;
5796 }
5797 }
5798 w32_set_scroll_bar_thumb (bar, portion, position, whole);
ee78dc32 5799
791f420f 5800 XSETVECTOR (w->vertical_scroll_bar, bar);
ee78dc32
GV
5801}
5802
5803
5804/* The following three hooks are used when we're doing a thorough
5805 redisplay of the frame. We don't explicitly know which scroll bars
5806 are going to be deleted, because keeping track of when windows go
5807 away is a real pain - "Can you say set-window-configuration, boys
5808 and girls?" Instead, we just assert at the beginning of redisplay
5809 that *all* scroll bars are to be removed, and then save a scroll bar
5810 from the fiery pit when we actually redisplay its window. */
5811
5812/* Arrange for all scroll bars on FRAME to be removed at the next call
5813 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9ef2e2cf
JR
5814 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5815
ee78dc32 5816static void
fbd6baed 5817w32_condemn_scroll_bars (frame)
ee78dc32
GV
5818 FRAME_PTR frame;
5819{
ef0e360f
GV
5820 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5821 while (! NILP (FRAME_SCROLL_BARS (frame)))
5822 {
5823 Lisp_Object bar;
5824 bar = FRAME_SCROLL_BARS (frame);
5825 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5826 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5827 XSCROLL_BAR (bar)->prev = Qnil;
5828 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5829 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5830 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5831 }
ee78dc32
GV
5832}
5833
c2cc16fa 5834
9ef2e2cf 5835/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
ee78dc32 5836 Note that WINDOW isn't necessarily condemned at all. */
c2cc16fa 5837
ee78dc32 5838static void
fbd6baed 5839w32_redeem_scroll_bar (window)
ee78dc32
GV
5840 struct window *window;
5841{
5842 struct scroll_bar *bar;
c2cc16fa 5843 struct frame *f;
ee78dc32
GV
5844
5845 /* We can't redeem this window's scroll bar if it doesn't have one. */
5846 if (NILP (window->vertical_scroll_bar))
5847 abort ();
5848
5849 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5850
ef0e360f 5851 /* Unlink it from the condemned list. */
c2cc16fa
JR
5852 f = XFRAME (WINDOW_FRAME (window));
5853 if (NILP (bar->prev))
5854 {
5855 /* If the prev pointer is nil, it must be the first in one of
5856 the lists. */
5857 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5858 /* It's not condemned. Everything's fine. */
5859 return;
5860 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5861 window->vertical_scroll_bar))
5862 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5863 else
5864 /* If its prev pointer is nil, it must be at the front of
5865 one or the other! */
5866 abort ();
5867 }
5868 else
5869 XSCROLL_BAR (bar->prev)->next = bar->next;
ef0e360f 5870
c2cc16fa
JR
5871 if (! NILP (bar->next))
5872 XSCROLL_BAR (bar->next)->prev = bar->prev;
ef0e360f 5873
c2cc16fa
JR
5874 bar->next = FRAME_SCROLL_BARS (f);
5875 bar->prev = Qnil;
5876 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5877 if (! NILP (bar->next))
5878 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
ee78dc32
GV
5879}
5880
5881/* Remove all scroll bars on FRAME that haven't been saved since the
5882 last call to `*condemn_scroll_bars_hook'. */
9ef2e2cf 5883
ee78dc32 5884static void
fbd6baed 5885w32_judge_scroll_bars (f)
ee78dc32
GV
5886 FRAME_PTR f;
5887{
5888 Lisp_Object bar, next;
5889
5890 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5891
5892 /* Clear out the condemned list now so we won't try to process any
5893 more events on the hapless scroll bars. */
5894 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5895
5896 for (; ! NILP (bar); bar = next)
5897 {
5898 struct scroll_bar *b = XSCROLL_BAR (bar);
5899
5900 x_scroll_bar_remove (b);
5901
5902 next = b->next;
5903 b->next = b->prev = Qnil;
5904 }
5905
5906 /* Now there should be no references to the condemned scroll bars,
5907 and they should get garbage-collected. */
5908}
5909
5910/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3b8f9651 5911 is set to something other than NO_EVENT, it is enqueued.
ee78dc32
GV
5912
5913 This may be called from a signal handler, so we have to ignore GC
5914 mark bits. */
2c28562d 5915
52cf03a1 5916static int
c2cc16fa 5917w32_scroll_bar_handle_click (bar, msg, emacs_event)
ee78dc32 5918 struct scroll_bar *bar;
fbd6baed 5919 W32Msg *msg;
ee78dc32
GV
5920 struct input_event *emacs_event;
5921{
5922 if (! GC_WINDOWP (bar->window))
5923 abort ();
5924
3b8f9651 5925 emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
ee78dc32 5926 emacs_event->code = 0;
52cf03a1
GV
5927 /* not really meaningful to distinguish up/down */
5928 emacs_event->modifiers = msg->dwModifiers;
ee78dc32 5929 emacs_event->frame_or_window = bar->window;
7e889510 5930 emacs_event->arg = Qnil;
ee78dc32
GV
5931 emacs_event->timestamp = msg->msg.time;
5932
5933 {
791f420f 5934 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
689004fa
GV
5935 int y;
5936 int dragging = !NILP (bar->dragging);
5937
5938 if (pfnGetScrollInfo)
5939 {
5940 SCROLLINFO si;
5941
5942 si.cbSize = sizeof (si);
5943 si.fMask = SIF_POS;
5944
5945 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
5946 y = si.nPos;
5947 }
5948 else
5949 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
5950
5951 bar->dragging = Qnil;
ee78dc32 5952
9ef2e2cf
JR
5953
5954 last_mouse_scroll_bar_pos = msg->msg.wParam;
d67d1627 5955
ee78dc32 5956 switch (LOWORD (msg->msg.wParam))
2c28562d 5957 {
2c28562d 5958 case SB_LINEDOWN:
52cf03a1 5959 emacs_event->part = scroll_bar_down_arrow;
ee78dc32 5960 break;
2c28562d 5961 case SB_LINEUP:
52cf03a1 5962 emacs_event->part = scroll_bar_up_arrow;
ee78dc32 5963 break;
2c28562d 5964 case SB_PAGEUP:
ee78dc32
GV
5965 emacs_event->part = scroll_bar_above_handle;
5966 break;
2c28562d 5967 case SB_PAGEDOWN:
ee78dc32
GV
5968 emacs_event->part = scroll_bar_below_handle;
5969 break;
2c28562d 5970 case SB_TOP:
ee78dc32
GV
5971 emacs_event->part = scroll_bar_handle;
5972 y = 0;
5973 break;
2c28562d 5974 case SB_BOTTOM:
ee78dc32
GV
5975 emacs_event->part = scroll_bar_handle;
5976 y = top_range;
5977 break;
689004fa 5978 case SB_THUMBTRACK:
2c28562d 5979 case SB_THUMBPOSITION:
791f420f
JR
5980 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
5981 y = HIWORD (msg->msg.wParam);
689004fa 5982 bar->dragging = Qt;
ee78dc32 5983 emacs_event->part = scroll_bar_handle;
689004fa
GV
5984
5985 /* "Silently" update current position. */
5986 if (pfnSetScrollInfo)
5987 {
5988 SCROLLINFO si;
5989
5990 si.cbSize = sizeof (si);
5991 si.fMask = SIF_POS;
689004fa
GV
5992 si.nPos = y;
5993 /* Remember apparent position (we actually lag behind the real
5994 position, so don't set that directly. */
5995 last_scroll_bar_drag_pos = y;
5996
5997 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
5998 }
5999 else
6000 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
ee78dc32 6001 break;
2c28562d 6002 case SB_ENDSCROLL:
689004fa
GV
6003 /* If this is the end of a drag sequence, then reset the scroll
6004 handle size to normal and do a final redraw. Otherwise do
6005 nothing. */
6006 if (dragging)
6007 {
6008 if (pfnSetScrollInfo)
6009 {
6010 SCROLLINFO si;
6011 int start = XINT (bar->start);
6012 int end = XINT (bar->end);
6013
6014 si.cbSize = sizeof (si);
6015 si.fMask = SIF_PAGE | SIF_POS;
791f420f 6016 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
689004fa 6017 si.nPos = last_scroll_bar_drag_pos;
689004fa
GV
6018 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
6019 }
6020 else
6021 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
6022 }
6023 /* fall through */
2c28562d 6024 default:
3b8f9651 6025 emacs_event->kind = NO_EVENT;
52cf03a1 6026 return FALSE;
2c28562d 6027 }
52cf03a1 6028
ee78dc32
GV
6029 XSETINT (emacs_event->x, y);
6030 XSETINT (emacs_event->y, top_range);
52cf03a1
GV
6031
6032 return TRUE;
ee78dc32
GV
6033 }
6034}
6035
6036/* Return information to the user about the current position of the mouse
6037 on the scroll bar. */
9ef2e2cf 6038
ee78dc32
GV
6039static void
6040x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
6041 FRAME_PTR *fp;
6042 Lisp_Object *bar_window;
6043 enum scroll_bar_part *part;
6044 Lisp_Object *x, *y;
6045 unsigned long *time;
6046{
6047 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
fbd6baed 6048 Window w = SCROLL_BAR_W32_WINDOW (bar);
ee78dc32
GV
6049 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6050 int pos;
791f420f 6051 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ee78dc32
GV
6052
6053 BLOCK_INPUT;
6054
6055 *fp = f;
6056 *bar_window = bar->window;
6057
689004fa
GV
6058 if (pfnGetScrollInfo)
6059 {
6060 SCROLLINFO si;
6061
6062 si.cbSize = sizeof (si);
6063 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
6064
6065 pfnGetScrollInfo (w, SB_CTL, &si);
6066 pos = si.nPos;
6067 top_range = si.nMax - si.nPage + 1;
6068 }
6069 else
6070 pos = GetScrollPos (w, SB_CTL);
ee78dc32
GV
6071
6072 switch (LOWORD (last_mouse_scroll_bar_pos))
6073 {
6074 case SB_THUMBPOSITION:
6075 case SB_THUMBTRACK:
6076 *part = scroll_bar_handle;
791f420f 6077 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
ee78dc32
GV
6078 pos = HIWORD (last_mouse_scroll_bar_pos);
6079 break;
6080 case SB_LINEDOWN:
6081 *part = scroll_bar_handle;
6082 pos++;
6083 break;
6084 default:
6085 *part = scroll_bar_handle;
6086 break;
6087 }
6088
9127e20e
JR
6089 XSETINT (*x, pos);
6090 XSETINT (*y, top_range);
ee78dc32
GV
6091
6092 f->mouse_moved = 0;
6093 last_mouse_scroll_bar = Qnil;
6094
6095 *time = last_mouse_movement_time;
6096
6097 UNBLOCK_INPUT;
6098}
6099
9ef2e2cf 6100
ee78dc32
GV
6101/* The screen has been cleared so we may have changed foreground or
6102 background colors, and the scroll bars may need to be redrawn.
6103 Clear out the scroll bars, and ask for expose events, so we can
6104 redraw them. */
9ef2e2cf 6105
791f420f 6106void
ee78dc32 6107x_scroll_bar_clear (f)
9ef2e2cf 6108 FRAME_PTR f;
ee78dc32 6109{
ee78dc32
GV
6110 Lisp_Object bar;
6111
9ef2e2cf
JR
6112 /* We can have scroll bars even if this is 0,
6113 if we just turned off scroll bar mode.
6114 But in that case we should not clear them. */
6115 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
6116 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
6117 bar = XSCROLL_BAR (bar)->next)
6118 {
6119 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
6120 HDC hdc = GetDC (window);
6121 RECT rect;
52cf03a1 6122
9ef2e2cf
JR
6123 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
6124 arranges to refresh the scroll bar if hidden. */
6125 my_show_window (f, window, SW_HIDE);
689004fa 6126
9ef2e2cf
JR
6127 GetClientRect (window, &rect);
6128 select_palette (f, hdc);
6129 w32_clear_rect (f, hdc, &rect);
6130 deselect_palette (f, hdc);
689004fa 6131
9ef2e2cf
JR
6132 ReleaseDC (window, hdc);
6133 }
52cf03a1
GV
6134}
6135
ee78dc32 6136\f
fbd6baed 6137/* The main W32 event-reading loop - w32_read_socket. */
ee78dc32
GV
6138
6139/* Record the last 100 characters stored
6140 to help debug the loss-of-chars-during-GC problem. */
9ef2e2cf
JR
6141
6142static int temp_index;
6143static short temp_buffer[100];
ee78dc32 6144
afd153f0 6145
fbd6baed 6146/* Read events coming from the W32 shell.
ee78dc32
GV
6147 This routine is called by the SIGIO handler.
6148 We return as soon as there are no more events to be read.
6149
6150 Events representing keys are stored in buffer BUFP,
6151 which can hold up to NUMCHARS characters.
6152 We return the number of characters stored into the buffer,
6153 thus pretending to be `read'.
6154
d67d1627 6155 EXPECTED is nonzero if the caller knows input is available.
ee78dc32
GV
6156
6157 Some of these messages are reposted back to the message queue since the
d67d1627 6158 system calls the windows proc directly in a context where we cannot return
e9e23e23 6159 the data nor can we guarantee the state we are in. So if we dispatch them
ee78dc32
GV
6160 we will get into an infinite loop. To prevent this from ever happening we
6161 will set a variable to indicate we are in the read_socket call and indicate
d67d1627 6162 which message we are processing since the windows proc gets called
e9e23e23 6163 recursively with different messages by the system.
ee78dc32
GV
6164*/
6165
6166int
3aad7613 6167w32_read_socket (sd, bufp, numchars, expected)
ee78dc32 6168 register int sd;
9ef2e2cf
JR
6169 /* register */ struct input_event *bufp;
6170 /* register */ int numchars;
ee78dc32
GV
6171 int expected;
6172{
6173 int count = 0;
689004fa 6174 int check_visibility = 0;
fbd6baed 6175 W32Msg msg;
ee78dc32 6176 struct frame *f;
fbd6baed 6177 struct w32_display_info *dpyinfo = &one_w32_display_info;
ee78dc32
GV
6178
6179 if (interrupt_input_blocked)
6180 {
6181 interrupt_input_pending = 1;
6182 return -1;
6183 }
6184
6185 interrupt_input_pending = 0;
6186 BLOCK_INPUT;
6187
6188 /* So people can tell when we have read the available input. */
6189 input_signal_count++;
6190
6191 if (numchars <= 0)
6192 abort (); /* Don't think this happens. */
6193
b71b8111 6194 /* TODO: tool-bars, ghostscript integration, mouse
791f420f 6195 cursors. */
52cf03a1 6196 while (get_next_msg (&msg, FALSE))
ee78dc32
GV
6197 {
6198 switch (msg.msg.message)
6199 {
ee78dc32 6200 case WM_PAINT:
9f5a911b 6201 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
ee78dc32 6202
d67d1627 6203 if (f)
9f5a911b
JR
6204 {
6205 if (msg.rect.right == msg.rect.left ||
6206 msg.rect.bottom == msg.rect.top)
6207 {
6208 /* We may get paint messages even though the client
6209 area is clipped - these are not expose events. */
6210 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
d5db4077 6211 SDATA (f->name)));
9f5a911b
JR
6212 }
6213 else if (f->async_visible != 1)
6214 {
6215 /* Definitely not obscured, so mark as visible. */
6216 f->async_visible = 1;
6217 f->async_iconified = 0;
6218 SET_FRAME_GARBAGED (f);
6219 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
d5db4077 6220 SDATA (f->name)));
9f5a911b
JR
6221
6222 /* WM_PAINT serves as MapNotify as well, so report
6223 visibility changes properly. */
6224 if (f->iconified)
6225 {
3b8f9651 6226 bufp->kind = DEICONIFY_EVENT;
9f5a911b
JR
6227 XSETFRAME (bufp->frame_or_window, f);
6228 bufp->arg = Qnil;
6229 bufp++;
6230 count++;
6231 numchars--;
6232 }
6233 else if (! NILP (Vframe_list)
6234 && ! NILP (XCDR (Vframe_list)))
6235 /* Force a redisplay sooner or later to update the
6236 frame titles in case this is the second frame. */
6237 record_asynch_buffer_change ();
6238 }
6239 else
6240 {
6241 HDC hdc = get_frame_dc (f);
6242
6243 /* Erase background again for safety. */
6244 w32_clear_rect (f, hdc, &msg.rect);
6245 release_frame_dc (f, hdc);
6246 expose_frame (f,
6247 msg.rect.left,
6248 msg.rect.top,
6249 msg.rect.right - msg.rect.left,
6250 msg.rect.bottom - msg.rect.top);
6251 }
6252 }
52cf03a1 6253 break;
689004fa 6254
f98169a0
GV
6255 case WM_INPUTLANGCHANGE:
6256 /* Generate a language change event. */
6257 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6258
6259 if (f)
6260 {
6261 if (numchars == 0)
6262 abort ();
d67d1627 6263
3b8f9651 6264 bufp->kind = LANGUAGE_CHANGE_EVENT;
f98169a0 6265 XSETFRAME (bufp->frame_or_window, f);
7e889510 6266 bufp->arg = Qnil;
f98169a0
GV
6267 bufp->code = msg.msg.wParam;
6268 bufp->modifiers = msg.msg.lParam & 0xffff;
6269 bufp++;
6270 count++;
6271 numchars--;
6272 }
6273 break;
6274
ee78dc32
GV
6275 case WM_KEYDOWN:
6276 case WM_SYSKEYDOWN:
6277 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6278
ee78dc32
GV
6279 if (f && !f->iconified)
6280 {
3d26a7c2
KS
6281 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6282 {
6283 dpyinfo->mouse_face_hidden = 1;
6284 clear_mouse_face (dpyinfo);
6285 }
6286
ee78dc32
GV
6287 if (temp_index == sizeof temp_buffer / sizeof (short))
6288 temp_index = 0;
6289 temp_buffer[temp_index++] = msg.msg.wParam;
3b8f9651 6290 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
ee78dc32 6291 bufp->code = msg.msg.wParam;
f98169a0 6292 bufp->modifiers = msg.dwModifiers;
ee78dc32 6293 XSETFRAME (bufp->frame_or_window, f);
7e889510 6294 bufp->arg = Qnil;
ee78dc32
GV
6295 bufp->timestamp = msg.msg.time;
6296 bufp++;
6297 numchars--;
6298 count++;
6299 }
6300 break;
689004fa 6301
ee78dc32
GV
6302 case WM_SYSCHAR:
6303 case WM_CHAR:
6304 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6305
ee78dc32
GV
6306 if (f && !f->iconified)
6307 {
3d26a7c2
KS
6308 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6309 {
6310 dpyinfo->mouse_face_hidden = 1;
6311 clear_mouse_face (dpyinfo);
6312 }
6313
f98169a0
GV
6314 if (temp_index == sizeof temp_buffer / sizeof (short))
6315 temp_index = 0;
6316 temp_buffer[temp_index++] = msg.msg.wParam;
3b8f9651 6317 bufp->kind = ASCII_KEYSTROKE_EVENT;
f98169a0
GV
6318 bufp->code = msg.msg.wParam;
6319 bufp->modifiers = msg.dwModifiers;
6320 XSETFRAME (bufp->frame_or_window, f);
7e889510 6321 bufp->arg = Qnil;
f98169a0
GV
6322 bufp->timestamp = msg.msg.time;
6323 bufp++;
6324 numchars--;
6325 count++;
ee78dc32
GV
6326 }
6327 break;
689004fa 6328
ee78dc32 6329 case WM_MOUSEMOVE:
706ddb8f
JR
6330 /* Ignore non-movement. */
6331 {
6332 int x = LOWORD (msg.msg.lParam);
6333 int y = HIWORD (msg.msg.lParam);
6334 if (x == last_mousemove_x && y == last_mousemove_y)
6335 break;
6336 last_mousemove_x = x;
6337 last_mousemove_y = y;
6338 }
6339
791f420f 6340 previous_help_echo = help_echo;
791f420f 6341
ee78dc32
GV
6342 if (dpyinfo->grabbed && last_mouse_frame
6343 && FRAME_LIVE_P (last_mouse_frame))
6344 f = last_mouse_frame;
6345 else
6346 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6347
3d26a7c2
KS
6348 if (dpyinfo->mouse_face_hidden)
6349 {
6350 dpyinfo->mouse_face_hidden = 0;
6351 clear_mouse_face (dpyinfo);
6352 }
6353
ee78dc32 6354 if (f)
a18bb28d
JR
6355 {
6356 /* Generate SELECT_WINDOW_EVENTs when needed. */
6357 if (mouse_autoselect_window)
6358 {
6359 Lisp_Object window;
6360 int area;
6361 int x = LOWORD (msg.msg.lParam);
6362 int y = HIWORD (msg.msg.lParam);
6363
6364 window = window_from_coordinates (f,
6365 x, y,
6366 &area, 0);
6367
6368 /* Window will be selected only when it is not
6369 selected now and last mouse movement event was
6370 not in it. Minibuffer window will be selected
6371 iff it is active. */
6372 if (WINDOWP(window)
6373 && !EQ (window, last_window)
6374 && !EQ (window, selected_window)
6375 && numchars > 0)
6376 {
6377 bufp->kind = SELECT_WINDOW_EVENT;
6378 bufp->frame_or_window = window;
6379 bufp->arg = Qnil;
6380 ++bufp, ++count, --numchars;
6381 }
6382
6383 last_window=window;
6384 }
6385 note_mouse_movement (f, &msg.msg);
6386 }
ee78dc32 6387 else
791f420f
JR
6388 {
6389 /* If we move outside the frame, then we're
6390 certainly no longer on any text in the frame. */
5b844253 6391 clear_mouse_face (dpyinfo);
791f420f
JR
6392 }
6393
6394 /* If the contents of the global variable help_echo
6395 has changed, generate a HELP_EVENT. */
706ddb8f
JR
6396 if (help_echo != previous_help_echo ||
6397 (!NILP (help_echo) && !STRINGP (help_echo) && f->mouse_moved))
791f420f
JR
6398 {
6399 Lisp_Object frame;
ec48c3a7 6400 int n;
791f420f 6401
706ddb8f
JR
6402 if (help_echo == Qnil)
6403 {
6404 help_echo_object = help_echo_window = Qnil;
6405 help_echo_pos = -1;
6406 }
6407
791f420f
JR
6408 if (f)
6409 XSETFRAME (frame, f);
6410 else
6411 frame = Qnil;
6412
6413 any_help_event_p = 1;
b4165314
GM
6414 n = gen_help_event (bufp, numchars, help_echo, frame,
6415 help_echo_window, help_echo_object,
6416 help_echo_pos);
ec48c3a7 6417 bufp += n, count += n, numchars -= n;
791f420f
JR
6418 }
6419 break;
689004fa 6420
ee78dc32
GV
6421 case WM_LBUTTONDOWN:
6422 case WM_LBUTTONUP:
6423 case WM_MBUTTONDOWN:
6424 case WM_MBUTTONUP:
6425 case WM_RBUTTONDOWN:
6426 case WM_RBUTTONUP:
53823ab9
JR
6427 case WM_XBUTTONDOWN:
6428 case WM_XBUTTONUP:
ee78dc32 6429 {
791f420f
JR
6430 /* If we decide we want to generate an event to be seen
6431 by the rest of Emacs, we put it here. */
6432 struct input_event emacs_event;
6433 int tool_bar_p = 0;
ee78dc32
GV
6434 int button;
6435 int up;
791f420f 6436
3b8f9651 6437 emacs_event.kind = NO_EVENT;
d67d1627 6438
ee78dc32
GV
6439 if (dpyinfo->grabbed && last_mouse_frame
6440 && FRAME_LIVE_P (last_mouse_frame))
6441 f = last_mouse_frame;
6442 else
6443 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6444
ee78dc32
GV
6445 if (f)
6446 {
791f420f 6447 construct_mouse_click (&emacs_event, &msg, f);
d67d1627 6448
791f420f
JR
6449 /* Is this in the tool-bar? */
6450 if (WINDOWP (f->tool_bar_window)
6451 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
6452 {
6453 Lisp_Object window;
e81916d1
JR
6454 int p, x, y;
6455
6456 x = XFASTINT (emacs_event.x);
6457 y = XFASTINT (emacs_event.y);
791f420f
JR
6458
6459 /* Set x and y. */
b8b47c19
JR
6460 window = window_from_coordinates (f, x, y, &p, 1);
6461
791f420f
JR
6462 if (EQ (window, f->tool_bar_window))
6463 {
6464 w32_handle_tool_bar_click (f, &emacs_event);
6465 tool_bar_p = 1;
6466 }
6467 }
6468
6469 if (!tool_bar_p)
6470 if (!dpyinfo->w32_focus_frame
6471 || f == dpyinfo->w32_focus_frame
6472 && (numchars >= 1))
6473 {
6474 construct_mouse_click (bufp, &msg, f);
6475 bufp++;
6476 count++;
6477 numchars--;
6478 }
ee78dc32 6479 }
d67d1627 6480
53823ab9
JR
6481 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
6482 &button, &up);
6483
ee78dc32
GV
6484 if (up)
6485 {
6486 dpyinfo->grabbed &= ~ (1 << button);
6487 }
6488 else
6489 {
6490 dpyinfo->grabbed |= (1 << button);
6491 last_mouse_frame = f;
791f420f
JR
6492 /* Ignore any mouse motion that happened
6493 before this event; any subsequent mouse-movement
6494 Emacs events should reflect only motion after
6495 the ButtonPress. */
6496 if (f != 0)
6497 f->mouse_moved = 0;
6498
6499 if (!tool_bar_p)
6500 last_tool_bar_item = -1;
ee78dc32 6501 }
689004fa 6502 break;
ee78dc32 6503 }
d67d1627 6504
689004fa
GV
6505 case WM_MOUSEWHEEL:
6506 if (dpyinfo->grabbed && last_mouse_frame
6507 && FRAME_LIVE_P (last_mouse_frame))
6508 f = last_mouse_frame;
6509 else
6510 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6511
6512 if (f)
6513 {
d67d1627 6514 if ((!dpyinfo->w32_focus_frame
689004fa
GV
6515 || f == dpyinfo->w32_focus_frame)
6516 && (numchars >= 1))
6517 {
6518 construct_mouse_wheel (bufp, &msg, f);
6519 bufp++;
6520 count++;
6521 numchars--;
6522 }
6523 }
ee78dc32 6524 break;
689004fa 6525
12857dfd
RS
6526 case WM_DROPFILES:
6527 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6528
6529 if (f)
6530 {
6531 construct_drag_n_drop (bufp, &msg, f);
6532 bufp++;
6533 count++;
6534 numchars--;
6535 }
6536 break;
6537
ee78dc32
GV
6538 case WM_VSCROLL:
6539 {
689004fa
GV
6540 struct scroll_bar *bar =
6541 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
d67d1627 6542
ee78dc32
GV
6543 if (bar && numchars >= 1)
6544 {
c2cc16fa 6545 if (w32_scroll_bar_handle_click (bar, &msg, bufp))
52cf03a1
GV
6546 {
6547 bufp++;
6548 count++;
6549 numchars--;
6550 }
ee78dc32 6551 }
689004fa 6552 break;
ee78dc32 6553 }
d67d1627 6554
689004fa 6555 case WM_WINDOWPOSCHANGED:
549808db
JR
6556 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6557 if (f)
6558 {
6559 x_check_fullscreen_move(f);
6560 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
6561 f->output_data.w32->want_fullscreen &=
6562 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
6563 }
6564 check_visibility = 1;
6565 break;
6566
689004fa
GV
6567 case WM_ACTIVATE:
6568 case WM_ACTIVATEAPP:
549808db
JR
6569 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6570 if (f)
6571 x_check_fullscreen (f);
689004fa 6572 check_visibility = 1;
ee78dc32 6573 break;
689004fa 6574
ee78dc32
GV
6575 case WM_MOVE:
6576 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6577
ee78dc32
GV
6578 if (f && !f->async_iconified)
6579 {
689004fa
GV
6580 int x, y;
6581
6582 x_real_positions (f, &x, &y);
6583 f->output_data.w32->left_pos = x;
6584 f->output_data.w32->top_pos = y;
ee78dc32 6585 }
689004fa
GV
6586
6587 check_visibility = 1;
6588 break;
6589
6590 case WM_SHOWWINDOW:
b71b8111
JR
6591 /* wParam non-zero means Window is about to be shown, 0 means
6592 about to be hidden. */
6593 /* Redo the mouse-highlight after the tooltip has gone. */
6594 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
6595 {
6596 tip_window = NULL;
6597 redo_mouse_highlight ();
6598 }
6599
689004fa
GV
6600 /* If window has been obscured or exposed by another window
6601 being maximised or minimised/restored, then recheck
6602 visibility of all frames. Direct changes to our own
6603 windows get handled by WM_SIZE. */
6604#if 0
6605 if (msg.msg.lParam != 0)
6606 check_visibility = 1;
6607 else
6608 {
6609 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6610 f->async_visible = msg.msg.wParam;
6611 }
6612#endif
6613
6614 check_visibility = 1;
ee78dc32 6615 break;
689004fa 6616
ee78dc32
GV
6617 case WM_SIZE:
6618 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6619
689004fa
GV
6620 /* Inform lisp of whether frame has been iconified etc. */
6621 if (f)
ee78dc32 6622 {
689004fa 6623 switch (msg.msg.wParam)
ee78dc32 6624 {
689004fa
GV
6625 case SIZE_MINIMIZED:
6626 f->async_visible = 0;
ee78dc32 6627 f->async_iconified = 1;
d67d1627 6628
3b8f9651 6629 bufp->kind = ICONIFY_EVENT;
ee78dc32 6630 XSETFRAME (bufp->frame_or_window, f);
7e889510 6631 bufp->arg = Qnil;
ee78dc32
GV
6632 bufp++;
6633 count++;
6634 numchars--;
689004fa
GV
6635 break;
6636
6637 case SIZE_MAXIMIZED:
6638 case SIZE_RESTORED:
ee78dc32
GV
6639 f->async_visible = 1;
6640 f->async_iconified = 0;
d67d1627 6641
ee78dc32
GV
6642 /* wait_reading_process_input will notice this and update
6643 the frame's display structures. */
6644 SET_FRAME_GARBAGED (f);
d67d1627 6645
ee78dc32
GV
6646 if (f->iconified)
6647 {
31d4844a
KH
6648 int x, y;
6649
6650 /* Reset top and left positions of the Window
6651 here since Windows sends a WM_MOVE message
6652 BEFORE telling us the Window is minimized
6653 when the Window is iconified, with 3000,3000
6654 as the co-ords. */
6655 x_real_positions (f, &x, &y);
6656 f->output_data.w32->left_pos = x;
6657 f->output_data.w32->top_pos = y;
6658
3b8f9651 6659 bufp->kind = DEICONIFY_EVENT;
ee78dc32 6660 XSETFRAME (bufp->frame_or_window, f);
7e889510 6661 bufp->arg = Qnil;
ee78dc32
GV
6662 bufp++;
6663 count++;
6664 numchars--;
6665 }
9ef2e2cf
JR
6666 else if (! NILP (Vframe_list)
6667 && ! NILP (XCDR (Vframe_list)))
ee78dc32
GV
6668 /* Force a redisplay sooner or later
6669 to update the frame titles
6670 in case this is the second frame. */
6671 record_asynch_buffer_change ();
689004fa 6672 break;
ee78dc32 6673 }
ee78dc32 6674 }
689004fa 6675
ef0e360f
GV
6676 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
6677 {
6678 RECT rect;
6679 int rows;
6680 int columns;
6681 int width;
6682 int height;
d67d1627 6683
9127e20e 6684 GetClientRect (msg.msg.hwnd, &rect);
d67d1627 6685
ef0e360f
GV
6686 height = rect.bottom - rect.top;
6687 width = rect.right - rect.left;
d67d1627 6688
ef0e360f
GV
6689 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
6690 columns = PIXEL_TO_CHAR_WIDTH (f, width);
d67d1627 6691
ef0e360f 6692 /* TODO: Clip size to the screen dimensions. */
d67d1627 6693
ef0e360f
GV
6694 /* Even if the number of character rows and columns has
6695 not changed, the font size may have changed, so we need
6696 to check the pixel dimensions as well. */
d67d1627 6697
ef0e360f
GV
6698 if (columns != f->width
6699 || rows != f->height
6700 || width != f->output_data.w32->pixel_width
6701 || height != f->output_data.w32->pixel_height)
6702 {
791f420f 6703 change_frame_size (f, rows, columns, 0, 1, 0);
ef0e360f 6704 SET_FRAME_GARBAGED (f);
31d4844a 6705 cancel_mouse_face (f);
ef0e360f
GV
6706 f->output_data.w32->pixel_width = width;
6707 f->output_data.w32->pixel_height = height;
6708 f->output_data.w32->win_gravity = NorthWestGravity;
6709 }
6710 }
6711
689004fa
GV
6712 check_visibility = 1;
6713 break;
6714
1576fbfa
JR
6715 case WM_MOUSELEAVE:
6716 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
6717 if (f)
6718 {
6719 if (f == dpyinfo->mouse_face_mouse_frame)
6720 {
6721 /* If we move outside the frame, then we're
6722 certainly no longer on any text in the frame. */
6723 clear_mouse_face (dpyinfo);
6724 dpyinfo->mouse_face_mouse_frame = 0;
6725 }
6726
6727 /* Generate a nil HELP_EVENT to cancel a help-echo.
6728 Do it only if there's something to cancel.
6729 Otherwise, the startup message is cleared when
6730 the mouse leaves the frame. */
6731 if (any_help_event_p)
6732 {
6733 Lisp_Object frame;
6734 int n;
6735
6736 XSETFRAME (frame, f);
6737 help_echo = Qnil;
6738 n = gen_help_event (bufp, numchars,
6739 Qnil, frame, Qnil, Qnil, 0);
6740 bufp += n, count += n, numchars -= n;
6741 }
6742 }
6743 break;
d67d1627 6744
689004fa 6745 case WM_SETFOCUS:
a18bb28d
JR
6746 /* TODO: Port this change:
6747 2002-06-28 Jan D. <jan.h.d@swipnet.se>
6748 * xterm.h (struct x_output): Add focus_state.
6749 * xterm.c (x_focus_changed): New function.
6750 (x_detect_focus_change): New function.
6751 (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
6752 EnterNotify and LeaveNotify to track X focus changes.
6753 */
791f420f
JR
6754 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
6755
6756 dpyinfo->w32_focus_event_frame = f;
d67d1627 6757
791f420f
JR
6758 if (f)
6759 x_new_focus_frame (dpyinfo, f);
6760
6761
6762 dpyinfo->grabbed = 0;
6763 check_visibility = 1;
6764 break;
6765
689004fa 6766 case WM_KILLFOCUS:
01b220b6 6767 /* TODO: some of this belongs in MOUSE_LEAVE */
791f420f 6768 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
08712a41 6769
791f420f
JR
6770 if (f)
6771 {
791f420f
JR
6772 if (f == dpyinfo->w32_focus_event_frame)
6773 dpyinfo->w32_focus_event_frame = 0;
6774
6775 if (f == dpyinfo->w32_focus_frame)
6776 x_new_focus_frame (dpyinfo, 0);
6777
6778 if (f == dpyinfo->mouse_face_mouse_frame)
6779 {
6780 /* If we move outside the frame, then we're
6781 certainly no longer on any text in the frame. */
6782 clear_mouse_face (dpyinfo);
6783 dpyinfo->mouse_face_mouse_frame = 0;
6784 }
9ef2e2cf 6785
791f420f
JR
6786 /* Generate a nil HELP_EVENT to cancel a help-echo.
6787 Do it only if there's something to cancel.
6788 Otherwise, the startup message is cleared when
6789 the mouse leaves the frame. */
6790 if (any_help_event_p)
6791 {
c2cc16fa 6792 Lisp_Object frame;
ec48c3a7
JR
6793 int n;
6794
791f420f 6795 XSETFRAME (frame, f);
c2cc16fa
JR
6796 help_echo = Qnil;
6797 n = gen_help_event (bufp, numchars,
6798 Qnil, frame, Qnil, Qnil, 0);
ec48c3a7 6799 bufp += n, count += n, numchars -=n;
791f420f
JR
6800 }
6801 }
689004fa 6802
08712a41 6803 dpyinfo->grabbed = 0;
689004fa 6804 check_visibility = 1;
ee78dc32 6805 break;
689004fa 6806
ee78dc32
GV
6807 case WM_CLOSE:
6808 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6809
ee78dc32
GV
6810 if (f)
6811 {
6812 if (numchars == 0)
6813 abort ();
d67d1627 6814
3b8f9651 6815 bufp->kind = DELETE_WINDOW_EVENT;
ee78dc32 6816 XSETFRAME (bufp->frame_or_window, f);
7e889510 6817 bufp->arg = Qnil;
ee78dc32
GV
6818 bufp++;
6819 count++;
6820 numchars--;
6821 }
689004fa
GV
6822 break;
6823
6824 case WM_INITMENU:
6825 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6826
689004fa
GV
6827 if (f)
6828 {
6829 if (numchars == 0)
6830 abort ();
d67d1627 6831
3b8f9651 6832 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
689004fa 6833 XSETFRAME (bufp->frame_or_window, f);
7e889510 6834 bufp->arg = Qnil;
689004fa
GV
6835 bufp++;
6836 count++;
6837 numchars--;
6838 }
ee78dc32 6839 break;
689004fa 6840
ee78dc32
GV
6841 case WM_COMMAND:
6842 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
014b6ea1 6843
ee78dc32
GV
6844 if (f)
6845 {
f98169a0
GV
6846 extern void menubar_selection_callback
6847 (FRAME_PTR f, void * client_data);
014b6ea1 6848 menubar_selection_callback (f, (void *)msg.msg.wParam);
ee78dc32 6849 }
689004fa
GV
6850
6851 check_visibility = 1;
6852 break;
6853
6854 case WM_DISPLAYCHANGE:
6855 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
6856
d67d1627 6857 if (f)
689004fa
GV
6858 {
6859 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
6860 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
6861 dpyinfo->n_cbits = msg.msg.wParam;
6862 DebPrint (("display change: %d %d\n", dpyinfo->width,
6863 dpyinfo->height));
6864 }
d67d1627 6865
689004fa 6866 check_visibility = 1;
ee78dc32 6867 break;
e7efd97e
GV
6868
6869 default:
6870 /* Check for messages registered at runtime. */
6871 if (msg.msg.message == msh_mousewheel)
6872 {
d67d1627 6873 if (dpyinfo->grabbed && last_mouse_frame
e7efd97e
GV
6874 && FRAME_LIVE_P (last_mouse_frame))
6875 f = last_mouse_frame;
6876 else
6877 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
d67d1627 6878
e7efd97e
GV
6879 if (f)
6880 {
d67d1627 6881 if ((!dpyinfo->w32_focus_frame
e7efd97e
GV
6882 || f == dpyinfo->w32_focus_frame)
6883 && (numchars >= 1))
6884 {
6885 construct_mouse_wheel (bufp, &msg, f);
6886 bufp++;
6887 count++;
6888 numchars--;
6889 }
6890 }
6891 }
6892 break;
ee78dc32
GV
6893 }
6894 }
6895
6896 /* If the focus was just given to an autoraising frame,
6897 raise it now. */
6898 /* ??? This ought to be able to handle more than one such frame. */
6899 if (pending_autoraise_frame)
6900 {
6901 x_raise_frame (pending_autoraise_frame);
6902 pending_autoraise_frame = 0;
6903 }
6904
689004fa
GV
6905 /* Check which frames are still visisble, if we have enqueued any user
6906 events or been notified of events that may affect visibility. We
6907 do this here because there doesn't seem to be any direct
6908 notification from Windows that the visibility of a window has
6909 changed (at least, not in all cases). */
6910 if (count > 0 || check_visibility)
6911 {
6912 Lisp_Object tail, frame;
6913
6914 FOR_EACH_FRAME (tail, frame)
6915 {
6916 FRAME_PTR f = XFRAME (frame);
b71b8111
JR
6917 /* The tooltip has been drawn already. Avoid the
6918 SET_FRAME_GARBAGED below. */
eb77a5f4 6919 if (EQ (frame, tip_frame))
b71b8111
JR
6920 continue;
6921
689004fa
GV
6922 /* Check "visible" frames and mark each as obscured or not.
6923 Note that async_visible is nonzero for unobscured and
6924 obscured frames, but zero for hidden and iconified frames. */
6925 if (FRAME_W32_P (f) && f->async_visible)
6926 {
6927 RECT clipbox;
66e5868a
AI
6928 HDC hdc;
6929
6930 enter_crit ();
6931 /* Query clipping rectangle for the entire window area
6932 (GetWindowDC), not just the client portion (GetDC).
6933 Otherwise, the scrollbars and menubar aren't counted as
6934 part of the visible area of the frame, and we may think
6935 the frame is obscured when really a scrollbar is still
6936 visible and gets WM_PAINT messages above. */
6937 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
689004fa 6938 GetClipBox (hdc, &clipbox);
66e5868a
AI
6939 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
6940 leave_crit ();
689004fa
GV
6941
6942 if (clipbox.right == clipbox.left
6943 || clipbox.bottom == clipbox.top)
6944 {
6945 /* Frame has become completely obscured so mark as
6946 such (we do this by setting async_visible to 2 so
6947 that FRAME_VISIBLE_P is still true, but redisplay
6948 will skip it). */
6949 f->async_visible = 2;
6950
6951 if (!FRAME_OBSCURED_P (f))
6952 {
8f860180 6953 DebPrint (("frame %p (%s) obscured\n", f,
d5db4077 6954 SDATA (f->name)));
689004fa
GV
6955 }
6956 }
6957 else
6958 {
6959 /* Frame is not obscured, so mark it as such. */
6960 f->async_visible = 1;
6961
6962 if (FRAME_OBSCURED_P (f))
6963 {
6964 SET_FRAME_GARBAGED (f);
8f860180 6965 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
d5db4077 6966 SDATA (f->name)));
689004fa
GV
6967
6968 /* Force a redisplay sooner or later. */
6969 record_asynch_buffer_change ();
6970 }
6971 }
6972 }
6973 }
6974 }
6975
ee78dc32
GV
6976 UNBLOCK_INPUT;
6977 return count;
6978}
791f420f 6979
9ef2e2cf
JR
6980
6981
ee78dc32 6982\f
791f420f
JR
6983/***********************************************************************
6984 Text Cursor
6985 ***********************************************************************/
6986
791f420f
JR
6987/* Set clipping for output in glyph row ROW. W is the window in which
6988 we operate. GC is the graphics context to set clipping in.
6989 WHOLE_LINE_P non-zero means include the areas used for truncation
6990 mark display and alike in the clipping rectangle.
ee78dc32 6991
791f420f
JR
6992 ROW may be a text row or, e.g., a mode line. Text rows must be
6993 clipped to the interior of the window dedicated to text display,
6994 mode lines must be clipped to the whole window. */
ee78dc32
GV
6995
6996static void
791f420f
JR
6997w32_clip_to_row (w, row, hdc, whole_line_p)
6998 struct window *w;
6999 struct glyph_row *row;
7000 HDC hdc;
7001 int whole_line_p;
ee78dc32 7002{
791f420f
JR
7003 struct frame *f = XFRAME (WINDOW_FRAME (w));
7004 RECT clip_rect;
7005 int window_x, window_y, window_width, window_height;
52cf03a1 7006
791f420f 7007 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
52cf03a1 7008
791f420f
JR
7009 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
7010 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
7011 clip_rect.top = max (clip_rect.top, window_y);
7012 clip_rect.right = clip_rect.left + window_width;
7013 clip_rect.bottom = clip_rect.top + row->visible_height;
7014
7015 /* If clipping to the whole line, including trunc marks, extend
9ef2e2cf 7016 the rectangle to the left and increase its width. */
791f420f
JR
7017 if (whole_line_p)
7018 {
33c34bea
KS
7019 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
7020 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
791f420f
JR
7021 }
7022
7023 w32_set_clip_rectangle (hdc, &clip_rect);
ee78dc32
GV
7024}
7025
791f420f
JR
7026
7027/* Draw a hollow box cursor on window W in glyph row ROW. */
ee78dc32
GV
7028
7029static void
791f420f
JR
7030x_draw_hollow_cursor (w, row)
7031 struct window *w;
7032 struct glyph_row *row;
ee78dc32 7033{
791f420f 7034 struct frame *f = XFRAME (WINDOW_FRAME (w));
988646fc 7035 HDC hdc;
791f420f
JR
7036 RECT rect;
7037 int wd;
7038 struct glyph *cursor_glyph;
7039 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
7040
7041 /* Compute frame-relative coordinates from window-relative
7042 coordinates. */
7043 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7044 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
7045 + row->ascent - w->phys_cursor_ascent);
d6dc9151 7046 rect.bottom = rect.top + row->height;
791f420f
JR
7047
7048 /* Get the glyph the cursor is on. If we can't tell because
7049 the current matrix is invalid or such, give up. */
7050 cursor_glyph = get_phys_cursor_glyph (w);
7051 if (cursor_glyph == NULL)
ee78dc32
GV
7052 return;
7053
791f420f
JR
7054 /* Compute the width of the rectangle to draw. If on a stretch
7055 glyph, and `x-stretch-block-cursor' is nil, don't draw a
7056 rectangle as wide as the glyph, but use a canonical character
7057 width instead. */
d6dc9151 7058 wd = cursor_glyph->pixel_width;
791f420f
JR
7059 if (cursor_glyph->type == STRETCH_GLYPH
7060 && !x_stretch_cursor_p)
7061 wd = min (CANON_X_UNIT (f), wd);
a18bb28d 7062 w->phys_cursor_width = wd;
791f420f
JR
7063
7064 rect.right = rect.left + wd;
988646fc 7065 hdc = get_frame_dc (f);
a18bb28d
JR
7066 /* Set clipping, draw the rectangle, and reset clipping again. */
7067 w32_clip_to_row (w, row, hdc, 0);
791f420f
JR
7068 FrameRect (hdc, &rect, hb);
7069 DeleteObject (hb);
a18bb28d 7070 w32_set_clip_rectangle (hdc, NULL);
791f420f 7071 release_frame_dc (f, hdc);
ee78dc32
GV
7072}
7073
791f420f
JR
7074
7075/* Draw a bar cursor on window W in glyph row ROW.
7076
7077 Implementation note: One would like to draw a bar cursor with an
7078 angle equal to the one given by the font property XA_ITALIC_ANGLE.
7079 Unfortunately, I didn't find a font yet that has this property set.
7080 --gerd. */
ee78dc32
GV
7081
7082static void
17456df1 7083x_draw_bar_cursor (w, row, width, kind)
791f420f
JR
7084 struct window *w;
7085 struct glyph_row *row;
9ef2e2cf 7086 int width;
17456df1 7087 enum text_cursor_kinds kind;
ee78dc32 7088{
c2cc16fa
JR
7089 struct frame *f = XFRAME (w->frame);
7090 struct glyph *cursor_glyph;
7091 int x;
7092 HDC hdc;
791f420f 7093
c2cc16fa
JR
7094 /* If cursor is out of bounds, don't draw garbage. This can happen
7095 in mini-buffer windows when switching between echo area glyphs
7096 and mini-buffer. */
7097 cursor_glyph = get_phys_cursor_glyph (w);
7098 if (cursor_glyph == NULL)
7099 return;
9ef2e2cf 7100
c2cc16fa
JR
7101 /* If on an image, draw like a normal cursor. That's usually better
7102 visible than drawing a bar, esp. if the image is large so that
7103 the bar might not be in the window. */
7104 if (cursor_glyph->type == IMAGE_GLYPH)
7105 {
7106 struct glyph_row *row;
7107 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7108 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
7109 }
7110 else
7111 {
6ff3e5e3
JR
7112 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
7113 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
7114
6ff3e5e3
JR
7115 /* If the glyph's background equals the color we normally draw
7116 the bar cursor in, the bar cursor in its normal color is
7117 invisible. Use the glyph's foreground color instead in this
7118 case, on the assumption that the glyph's colors are chosen so
7119 that the glyph is legible. */
7120 if (face->background == cursor_color)
7121 cursor_color = face->foreground;
7122
c2cc16fa 7123 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
a18bb28d
JR
7124
7125 if (width < 0)
7126 width = FRAME_CURSOR_WIDTH (f);
7127 width = min (cursor_glyph->pixel_width, width);
7128
7129 w->phys_cursor_width = width;
7130
7131
c2cc16fa
JR
7132 hdc = get_frame_dc (f);
7133 w32_clip_to_row (w, row, hdc, 0);
17456df1
JR
7134
7135 if (kind == BAR_CURSOR)
7136 {
7137 w32_fill_area (f, hdc, cursor_color, x,
7138 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
7139 width, row->height);
7140 }
7141 else
7142 {
7143 w32_fill_area (f, hdc, cursor_color, x,
7144 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
7145 row->height - width),
7146 cursor_glyph->pixel_width, width);
7147 }
a18bb28d
JR
7148
7149 w32_set_clip_rectangle (hdc, NULL);
c2cc16fa 7150 release_frame_dc (f, hdc);
791f420f 7151 }
ee78dc32
GV
7152}
7153
791f420f
JR
7154
7155/* Clear the cursor of window W to background color, and mark the
7156 cursor as not shown. This is used when the text where the cursor
7157 is is about to be rewritten. */
7158
ee78dc32 7159static void
791f420f
JR
7160x_clear_cursor (w)
7161 struct window *w;
ee78dc32 7162{
791f420f
JR
7163 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
7164 x_update_window_cursor (w, 0);
7165}
ee78dc32 7166
ee78dc32 7167
791f420f
JR
7168/* Draw the cursor glyph of window W in glyph row ROW. See the
7169 comment of x_draw_glyphs for the meaning of HL. */
ee78dc32 7170
791f420f
JR
7171static void
7172x_draw_phys_cursor_glyph (w, row, hl)
7173 struct window *w;
7174 struct glyph_row *row;
7175 enum draw_glyphs_face hl;
7176{
7177 /* If cursor hpos is out of bounds, don't draw garbage. This can
7178 happen in mini-buffer windows when switching between echo area
7179 glyphs and mini-buffer. */
7180 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
ee78dc32 7181 {
6ff3e5e3 7182 int on_p = w->phys_cursor_on_p;
a18bb28d
JR
7183 int x1;
7184 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
7185 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
7186 hl, 0);
6ff3e5e3 7187 w->phys_cursor_on_p = on_p;
791f420f 7188
a18bb28d
JR
7189 if (hl == DRAW_CURSOR)
7190 w->phys_cursor_width = x1 - w->phys_cursor.x;
7191
791f420f
JR
7192 /* When we erase the cursor, and ROW is overlapped by other
7193 rows, make sure that these overlapping parts of other rows
7194 are redrawn. */
7195 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
7196 {
7197 if (row > w->current_matrix->rows
7198 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
7199 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
7200
7201 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
7202 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
7203 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
7204 }
ee78dc32 7205 }
791f420f 7206}
ee78dc32 7207
791f420f
JR
7208
7209/* Erase the image of a cursor of window W from the screen. */
7210
7211static void
7212x_erase_phys_cursor (w)
7213 struct window *w;
7214{
7215 struct frame *f = XFRAME (w->frame);
7216 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7217 int hpos = w->phys_cursor.hpos;
7218 int vpos = w->phys_cursor.vpos;
7219 int mouse_face_here_p = 0;
7220 struct glyph_matrix *active_glyphs = w->current_matrix;
7221 struct glyph_row *cursor_row;
7222 struct glyph *cursor_glyph;
7223 enum draw_glyphs_face hl;
7224
7225 /* No cursor displayed or row invalidated => nothing to do on the
7226 screen. */
7227 if (w->phys_cursor_type == NO_CURSOR)
7228 goto mark_cursor_off;
d67d1627 7229
791f420f
JR
7230 /* VPOS >= active_glyphs->nrows means that window has been resized.
7231 Don't bother to erase the cursor. */
7232 if (vpos >= active_glyphs->nrows)
7233 goto mark_cursor_off;
7234
7235 /* If row containing cursor is marked invalid, there is nothing we
7236 can do. */
7237 cursor_row = MATRIX_ROW (active_glyphs, vpos);
7238 if (!cursor_row->enabled_p)
7239 goto mark_cursor_off;
d67d1627 7240
a2c6de8e
KS
7241 /* If row is completely invisible, don't attempt to delete a cursor which
7242 isn't there. This may happen if cursor is at top of window, and
7243 we switch to a buffer with a header line in that window. */
7244 if (cursor_row->visible_height <= 0)
7245 goto mark_cursor_off;
d67d1627 7246
791f420f
JR
7247 /* This can happen when the new row is shorter than the old one.
7248 In this case, either x_draw_glyphs or clear_end_of_line
7249 should have cleared the cursor. Note that we wouldn't be
7250 able to erase the cursor in this case because we don't have a
7251 cursor glyph at hand. */
7252 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
7253 goto mark_cursor_off;
95f2448c 7254
791f420f
JR
7255 /* If the cursor is in the mouse face area, redisplay that when
7256 we clear the cursor. */
c2cc16fa
JR
7257 if (! NILP (dpyinfo->mouse_face_window)
7258 && w == XWINDOW (dpyinfo->mouse_face_window)
791f420f
JR
7259 && (vpos > dpyinfo->mouse_face_beg_row
7260 || (vpos == dpyinfo->mouse_face_beg_row
7261 && hpos >= dpyinfo->mouse_face_beg_col))
7262 && (vpos < dpyinfo->mouse_face_end_row
7263 || (vpos == dpyinfo->mouse_face_end_row
7264 && hpos < dpyinfo->mouse_face_end_col))
7265 /* Don't redraw the cursor's spot in mouse face if it is at the
7266 end of a line (on a newline). The cursor appears there, but
7267 mouse highlighting does not. */
7268 && cursor_row->used[TEXT_AREA] > hpos)
7269 mouse_face_here_p = 1;
7270
7271 /* Maybe clear the display under the cursor. */
7272 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
ee78dc32 7273 {
791f420f
JR
7274 int x;
7275 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
00fe468b 7276 HDC hdc;
ee78dc32 7277
791f420f
JR
7278 cursor_glyph = get_phys_cursor_glyph (w);
7279 if (cursor_glyph == NULL)
7280 goto mark_cursor_off;
ee78dc32 7281
791f420f 7282 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
00fe468b
JR
7283
7284 hdc = get_frame_dc (f);
7285 w32_clear_area (f, hdc, x,
791f420f
JR
7286 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
7287 cursor_row->y)),
7288 cursor_glyph->pixel_width,
7289 cursor_row->visible_height);
00fe468b 7290 release_frame_dc (f, hdc);
ee78dc32 7291 }
d67d1627 7292
791f420f
JR
7293 /* Erase the cursor by redrawing the character underneath it. */
7294 if (mouse_face_here_p)
7295 hl = DRAW_MOUSE_FACE;
791f420f
JR
7296 else
7297 hl = DRAW_NORMAL_TEXT;
7298 x_draw_phys_cursor_glyph (w, cursor_row, hl);
7299
7300 mark_cursor_off:
7301 w->phys_cursor_on_p = 0;
7302 w->phys_cursor_type = NO_CURSOR;
ee78dc32
GV
7303}
7304
7305
9f5a911b
JR
7306/* Non-zero if physical cursor of window W is within mouse face. */
7307
7308static int
7309cursor_in_mouse_face_p (w)
7310 struct window *w;
7311{
7312 struct w32_display_info *dpyinfo
7313 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
7314 int in_mouse_face = 0;
d67d1627 7315
9f5a911b
JR
7316 if (WINDOWP (dpyinfo->mouse_face_window)
7317 && XWINDOW (dpyinfo->mouse_face_window) == w)
7318 {
7319 int hpos = w->phys_cursor.hpos;
7320 int vpos = w->phys_cursor.vpos;
7321
7322 if (vpos >= dpyinfo->mouse_face_beg_row
7323 && vpos <= dpyinfo->mouse_face_end_row
7324 && (vpos > dpyinfo->mouse_face_beg_row
7325 || hpos >= dpyinfo->mouse_face_beg_col)
7326 && (vpos < dpyinfo->mouse_face_end_row
7327 || hpos < dpyinfo->mouse_face_end_col
7328 || dpyinfo->mouse_face_past_end))
7329 in_mouse_face = 1;
7330 }
7331
7332 return in_mouse_face;
7333}
7334
7335
791f420f
JR
7336/* Display or clear cursor of window W. If ON is zero, clear the
7337 cursor. If it is non-zero, display the cursor. If ON is nonzero,
7338 where to put the cursor is specified by HPOS, VPOS, X and Y. */
ee78dc32 7339
791f420f
JR
7340void
7341x_display_and_set_cursor (w, on, hpos, vpos, x, y)
7342 struct window *w;
7343 int on, hpos, vpos, x, y;
ee78dc32 7344{
791f420f
JR
7345 struct frame *f = XFRAME (w->frame);
7346 int new_cursor_type;
9ef2e2cf 7347 int new_cursor_width;
1cdf2e12 7348 int active_cursor;
791f420f
JR
7349 struct glyph_matrix *current_glyphs;
7350 struct glyph_row *glyph_row;
7351 struct glyph *glyph;
ee78dc32
GV
7352
7353 /* This is pointless on invisible frames, and dangerous on garbaged
791f420f
JR
7354 windows and frames; in the latter case, the frame or window may
7355 be in the midst of changing its size, and x and y may be off the
7356 window. */
7357 if (! FRAME_VISIBLE_P (f)
7358 || FRAME_GARBAGED_P (f)
7359 || vpos >= w->current_matrix->nrows
7360 || hpos >= w->current_matrix->matrix_w)
ee78dc32
GV
7361 return;
7362
7363 /* If cursor is off and we want it off, return quickly. */
791f420f 7364 if (!on && !w->phys_cursor_on_p)
ee78dc32
GV
7365 return;
7366
791f420f
JR
7367 current_glyphs = w->current_matrix;
7368 glyph_row = MATRIX_ROW (current_glyphs, vpos);
7369 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
d67d1627
JB
7370
7371 /* If cursor row is not enabled, we don't really know where to
791f420f
JR
7372 display the cursor. */
7373 if (!glyph_row->enabled_p)
7374 {
7375 w->phys_cursor_on_p = 0;
7376 return;
7377 }
7378
7379 xassert (interrupt_input_blocked);
7380
fdbe859c 7381 /* Set new_cursor_type to the cursor we want to be displayed. */
1cdf2e12 7382 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
95f2448c 7383
791f420f
JR
7384 /* If cursor is currently being shown and we don't want it to be or
7385 it is in the wrong place, or the cursor type is not what we want,
ee78dc32 7386 erase it. */
791f420f 7387 if (w->phys_cursor_on_p
ee78dc32 7388 && (!on
791f420f
JR
7389 || w->phys_cursor.x != x
7390 || w->phys_cursor.y != y
9652402e 7391 || new_cursor_type != w->phys_cursor_type
fdbe859c 7392 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
e1429afe 7393 && new_cursor_width != w->phys_cursor_width)))
791f420f
JR
7394 x_erase_phys_cursor (w);
7395
95f2448c
RS
7396 /* Don't check phys_cursor_on_p here because that flag is only set
7397 to zero in some cases where we know that the cursor has been
7398 completely erased, to avoid the extra work of erasing the cursor
7399 twice. In other words, phys_cursor_on_p can be 1 and the cursor
7400 still not be visible, or it has only been partly erased. */
7401 if (on)
791f420f
JR
7402 {
7403 w->phys_cursor_ascent = glyph_row->ascent;
7404 w->phys_cursor_height = glyph_row->height;
d67d1627 7405
791f420f
JR
7406 /* Set phys_cursor_.* before x_draw_.* is called because some
7407 of them may need the information. */
7408 w->phys_cursor.x = x;
7409 w->phys_cursor.y = glyph_row->y;
7410 w->phys_cursor.hpos = hpos;
7411 w->phys_cursor.vpos = vpos;
99558ce8
JR
7412
7413 /* If the user wants to use the system caret, make sure our own
7414 cursor remains invisible. */
7415 if (w32_use_visible_system_caret)
7416 {
7417 if (w->phys_cursor_type != NO_CURSOR)
7418 x_erase_phys_cursor (w);
7419
7420 new_cursor_type = w->phys_cursor_type = NO_CURSOR;
e1429afe 7421 w->phys_cursor_width = -1;
99558ce8
JR
7422 }
7423 else
e1429afe
KS
7424 {
7425 w->phys_cursor_type = new_cursor_type;
e1429afe 7426 }
99558ce8 7427
791f420f
JR
7428 w->phys_cursor_on_p = 1;
7429
abb15ebd
JR
7430 /* If this is the active cursor, we need to track it with the
7431 system caret, so third party software like screen magnifiers
7432 and speech synthesizers can follow the cursor. */
7433 if (active_cursor)
7434 {
99558ce8 7435 HWND hwnd = FRAME_W32_WINDOW (f);
abb15ebd 7436
99558ce8
JR
7437 w32_system_caret_x
7438 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
7439 w32_system_caret_y
7440 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
7441 + glyph_row->ascent - w->phys_cursor_ascent);
7442
7443 /* If the size of the active cursor changed, destroy the old
7444 system caret. */
7445 if (w32_system_caret_hwnd
7446 && (w32_system_caret_height != w->phys_cursor_height))
7447 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
7448
7449 w32_system_caret_height = w->phys_cursor_height;
7450
7451 /* Move the system caret. */
7452 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
abb15ebd
JR
7453 }
7454
791f420f 7455 switch (new_cursor_type)
ee78dc32 7456 {
791f420f
JR
7457 case HOLLOW_BOX_CURSOR:
7458 x_draw_hollow_cursor (w, glyph_row);
7459 break;
7460
7461 case FILLED_BOX_CURSOR:
7462 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7463 break;
7464
7465 case BAR_CURSOR:
17456df1
JR
7466 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
7467 break;
7468
7469 case HBAR_CURSOR:
7470 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
791f420f 7471 break;
ee78dc32 7472
791f420f 7473 case NO_CURSOR:
a18bb28d 7474 w->phys_cursor_width = 0;
791f420f
JR
7475 break;
7476
7477 default:
7478 abort ();
7479 }
ee78dc32
GV
7480 }
7481}
7482
689004fa 7483
791f420f
JR
7484/* Display the cursor on window W, or clear it. X and Y are window
7485 relative pixel coordinates. HPOS and VPOS are glyph matrix
7486 positions. If W is not the selected window, display a hollow
7487 cursor. ON non-zero means display the cursor at X, Y which
7488 correspond to HPOS, VPOS, otherwise it is cleared. */
7489
7490void
7491x_display_cursor (w, on, hpos, vpos, x, y)
7492 struct window *w;
7493 int on, hpos, vpos, x, y;
ee78dc32
GV
7494{
7495 BLOCK_INPUT;
791f420f
JR
7496 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
7497 UNBLOCK_INPUT;
7498}
7499
7500
7501/* Display the cursor on window W, or clear it, according to ON_P.
7502 Don't change the cursor's position. */
7503
7504void
7505x_update_cursor (f, on_p)
7506 struct frame *f;
7507 int on_p;
7508{
7509 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
7510}
7511
7512
7513/* Call x_update_window_cursor with parameter ON_P on all leaf windows
7514 in the window tree rooted at W. */
ee78dc32 7515
791f420f
JR
7516static void
7517x_update_cursor_in_window_tree (w, on_p)
7518 struct window *w;
7519 int on_p;
7520{
7521 while (w)
689004fa 7522 {
791f420f
JR
7523 if (!NILP (w->hchild))
7524 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
7525 else if (!NILP (w->vchild))
7526 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
7527 else
7528 x_update_window_cursor (w, on_p);
7529
7530 w = NILP (w->next) ? 0 : XWINDOW (w->next);
689004fa 7531 }
791f420f 7532}
689004fa 7533
ee78dc32 7534
791f420f
JR
7535/* Switch the display of W's cursor on or off, according to the value
7536 of ON. */
7537
7538static void
7539x_update_window_cursor (w, on)
7540 struct window *w;
7541 int on;
7542{
9ef2e2cf
JR
7543 /* Don't update cursor in windows whose frame is in the process
7544 of being deleted. */
7545 if (w->current_matrix)
7546 {
7547 BLOCK_INPUT;
7548 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
7549 w->phys_cursor.vpos, w->phys_cursor.x,
7550 w->phys_cursor.y);
7551 UNBLOCK_INPUT;
7552 }
ee78dc32 7553}
791f420f
JR
7554
7555
9ef2e2cf 7556
ee78dc32 7557\f
7f5d1df8
GV
7558/* Icons. */
7559
7560int
7561x_bitmap_icon (f, icon)
7562 struct frame *f;
7563 Lisp_Object icon;
7564{
7f5d1df8
GV
7565 HANDLE hicon;
7566
7567 if (FRAME_W32_WINDOW (f) == 0)
7568 return 1;
7569
7570 if (NILP (icon))
7571 hicon = LoadIcon (hinst, EMACS_CLASS);
7572 else if (STRINGP (icon))
d5db4077 7573 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
7f5d1df8
GV
7574 LR_DEFAULTSIZE | LR_LOADFROMFILE);
7575 else if (SYMBOLP (icon))
7576 {
7577 LPCTSTR name;
7578
7579 if (EQ (icon, intern ("application")))
7580 name = (LPCTSTR) IDI_APPLICATION;
7581 else if (EQ (icon, intern ("hand")))
7582 name = (LPCTSTR) IDI_HAND;
7583 else if (EQ (icon, intern ("question")))
7584 name = (LPCTSTR) IDI_QUESTION;
7585 else if (EQ (icon, intern ("exclamation")))
7586 name = (LPCTSTR) IDI_EXCLAMATION;
7587 else if (EQ (icon, intern ("asterisk")))
7588 name = (LPCTSTR) IDI_ASTERISK;
7589 else if (EQ (icon, intern ("winlogo")))
7590 name = (LPCTSTR) IDI_WINLOGO;
7591 else
7592 return 1;
7593
7594 hicon = LoadIcon (NULL, name);
7595 }
7596 else
7597 return 1;
7598
7599 if (hicon == NULL)
7600 return 1;
7601
791f420f
JR
7602 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
7603 (LPARAM) hicon);
7f5d1df8
GV
7604
7605 return 0;
7606}
7607
7608\f
c2cc16fa
JR
7609/************************************************************************
7610 Handling X errors
7611 ************************************************************************/
7612
7613/* Display Error Handling functions not used on W32. Listing them here
7614 helps diff stay in step when comparing w32term.c with xterm.c.
7615
7616x_error_catcher (display, error)
7617x_catch_errors (dpy)
7618x_catch_errors_unwind (old_val)
7619x_check_errors (dpy, format)
7620x_had_errors_p (dpy)
7621x_clear_errors (dpy)
7622x_uncatch_errors (dpy, count)
7623x_trace_wire ()
7624x_connection_signal (signalnum)
7625x_connection_closed (dpy, error_message)
7626x_error_quitter (display, error)
7627x_error_handler (display, error)
7628x_io_error_quitter (display)
7629
7630 */
7631
7632\f
ee78dc32
GV
7633/* Changing the font of the frame. */
7634
7635/* Give frame F the font named FONTNAME as its default font, and
7636 return the full name of that font. FONTNAME may be a wildcard
7637 pattern; in that case, we choose some font that fits the pattern.
7638 The return value shows which font we chose. */
7639
7640Lisp_Object
7641x_new_font (f, fontname)
7642 struct frame *f;
7643 register char *fontname;
7644{
cabb23bc 7645 struct font_info *fontp
93ff4395 7646 = FS_LOAD_FONT (f, 0, fontname, -1);
ee78dc32 7647
cabb23bc 7648 if (!fontp)
791f420f 7649 return Qnil;
ee78dc32 7650
cabb23bc 7651 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
791f420f 7652 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
cabb23bc 7653 FRAME_FONTSET (f) = -1;
ee78dc32
GV
7654
7655 /* Compute the scroll bar width in character columns. */
7656 if (f->scroll_bar_pixel_width > 0)
7657 {
ec48c3a7 7658 int wid = FONT_WIDTH (FRAME_FONT (f));
ee78dc32
GV
7659 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
7660 }
7661 else
ec48c3a7
JR
7662 {
7663 int wid = FONT_WIDTH (FRAME_FONT (f));
7664 f->scroll_bar_cols = (14 + wid - 1) / wid;
7665 }
ee78dc32
GV
7666
7667 /* Now make the frame display the given font. */
fbd6baed 7668 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
7669 {
7670 frame_update_line_height (f);
49be9f70
JR
7671 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
7672 x_set_window_size (f, 0, f->width, f->height);
ee78dc32
GV
7673 }
7674 else
7675 /* If we are setting a new frame's font for the first time,
7676 there are no faces yet, so this font's height is the line height. */
ec48c3a7 7677 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
ee78dc32 7678
791f420f 7679 return build_string (fontp->full_name);
ee78dc32
GV
7680}
7681\f
cabb23bc
GV
7682/* Give frame F the fontset named FONTSETNAME as its default font, and
7683 return the full name of that fontset. FONTSETNAME may be a wildcard
7684 pattern; in that case, we choose some fontset that fits the pattern.
7685 The return value shows which fontset we chose. */
7686
7687Lisp_Object
7688x_new_fontset (f, fontsetname)
7689 struct frame *f;
7690 char *fontsetname;
7691{
93ff4395 7692 int fontset = fs_query_fontset (build_string (fontsetname), 0);
cabb23bc
GV
7693 Lisp_Object result;
7694
7695 if (fontset < 0)
7696 return Qnil;
7697
7698 if (FRAME_FONTSET (f) == fontset)
7699 /* This fontset is already set in frame F. There's nothing more
7700 to do. */
93ff4395 7701 return fontset_name (fontset);
cabb23bc 7702
d5db4077 7703 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
cabb23bc
GV
7704
7705 if (!STRINGP (result))
7706 /* Can't load ASCII font. */
7707 return Qnil;
7708
7709 /* Since x_new_font doesn't update any fontset information, do it now. */
7710 FRAME_FONTSET(f) = fontset;
cabb23bc
GV
7711
7712 return build_string (fontsetname);
7713}
791f420f 7714
c2cc16fa
JR
7715\f
7716/***********************************************************************
7717 TODO: W32 Input Methods
7718 ***********************************************************************/
7719/* Listing missing functions from xterm.c helps diff stay in step.
791f420f 7720
c2cc16fa
JR
7721xim_destroy_callback (xim, client_data, call_data)
7722xim_open_dpy (dpyinfo, resource_name)
7723struct xim_inst_t
7724xim_instantiate_callback (display, client_data, call_data)
7725xim_initialize (dpyinfo, resource_name)
7726xim_close_dpy (dpyinfo)
791f420f 7727
c2cc16fa 7728 */
791f420f 7729
cabb23bc 7730\f
689004fa
GV
7731/* Calculate the absolute position in frame F
7732 from its current recorded position values and gravity. */
7733
9ef2e2cf 7734void
ee78dc32
GV
7735x_calc_absolute_position (f)
7736 struct frame *f;
7737{
ee78dc32 7738 POINT pt;
fbd6baed 7739 int flags = f->output_data.w32->size_hint_flags;
ee78dc32
GV
7740
7741 pt.x = pt.y = 0;
7742
7743 /* Find the position of the outside upper-left corner of
c2cc16fa
JR
7744 the inner window, with respect to the outer window.
7745 But do this only if we will need the results. */
fbd6baed 7746 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
ee78dc32
GV
7747 {
7748 BLOCK_INPUT;
fbd6baed
GV
7749 MapWindowPoints (FRAME_W32_WINDOW (f),
7750 f->output_data.w32->parent_desc,
ee78dc32
GV
7751 &pt, 1);
7752 UNBLOCK_INPUT;
7753 }
7754
7755 {
7756 RECT rt;
7757 rt.left = rt.right = rt.top = rt.bottom = 0;
d67d1627 7758
ee78dc32 7759 BLOCK_INPUT;
fbd6baed 7760 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
97c23857 7761 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
7762 UNBLOCK_INPUT;
7763
7764 pt.x += (rt.right - rt.left);
7765 pt.y += (rt.bottom - rt.top);
7766 }
7767
7768 /* Treat negative positions as relative to the leftmost bottommost
7769 position that fits on the screen. */
7770 if (flags & XNegative)
fbd6baed
GV
7771 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
7772 - 2 * f->output_data.w32->border_width - pt.x
ee78dc32 7773 - PIXEL_WIDTH (f)
fbd6baed 7774 + f->output_data.w32->left_pos);
158cba56 7775
ee78dc32 7776 if (flags & YNegative)
fbd6baed
GV
7777 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
7778 - 2 * f->output_data.w32->border_width - pt.y
ee78dc32 7779 - PIXEL_HEIGHT (f)
fbd6baed 7780 + f->output_data.w32->top_pos);
ee78dc32
GV
7781 /* The left_pos and top_pos
7782 are now relative to the top and left screen edges,
7783 so the flags should correspond. */
fbd6baed 7784 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32
GV
7785}
7786
7787/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
7788 to really change the position, and 0 when calling from
7789 x_make_frame_visible (in that case, XOFF and YOFF are the current
7790 position values). It is -1 when calling from x_set_frame_parameters,
7791 which means, do adjust for borders but don't change the gravity. */
7792
9ef2e2cf 7793void
ee78dc32
GV
7794x_set_offset (f, xoff, yoff, change_gravity)
7795 struct frame *f;
7796 register int xoff, yoff;
7797 int change_gravity;
7798{
7799 int modified_top, modified_left;
7800
7801 if (change_gravity > 0)
7802 {
fbd6baed
GV
7803 f->output_data.w32->top_pos = yoff;
7804 f->output_data.w32->left_pos = xoff;
7805 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32 7806 if (xoff < 0)
fbd6baed 7807 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32 7808 if (yoff < 0)
fbd6baed
GV
7809 f->output_data.w32->size_hint_flags |= YNegative;
7810 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
7811 }
7812 x_calc_absolute_position (f);
7813
7814 BLOCK_INPUT;
7815 x_wm_set_size_hint (f, (long) 0, 0);
7816
fbd6baed
GV
7817 modified_left = f->output_data.w32->left_pos;
7818 modified_top = f->output_data.w32->top_pos;
ee78dc32 7819
fbd6baed 7820 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
7821 NULL,
7822 modified_left, modified_top,
cabb23bc 7823 0, 0,
689004fa 7824 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
ee78dc32
GV
7825 UNBLOCK_INPUT;
7826}
7827
549808db
JR
7828
7829/* Check if we need to resize the frame due to a fullscreen request.
7830 If so needed, resize the frame. */
7831static void
7832x_check_fullscreen (f)
7833 struct frame *f;
7834{
7835 if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
7836 {
7837 int width, height, ign;
d67d1627 7838
549808db
JR
7839 x_real_positions (f, &f->output_data.w32->left_pos,
7840 &f->output_data.w32->top_pos);
7841
7842 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
d67d1627 7843
549808db
JR
7844 /* We do not need to move the window, it shall be taken care of
7845 when setting WM manager hints.
7846 If the frame is visible already, the position is checked by
7847 x_check_fullscreen_move. */
7848 if (f->width != width || f->height != height)
7849 {
7850 change_frame_size (f, height, width, 0, 1, 0);
7851 SET_FRAME_GARBAGED (f);
7852 cancel_mouse_face (f);
7853
7854 /* Wait for the change of frame size to occur */
7855 f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
7856 }
7857 }
7858}
7859
7860/* If frame parameters are set after the frame is mapped, we need to move
7861 the window. This is done in xfns.c.
7862 Some window managers moves the window to the right position, some
7863 moves the outer window manager window to the specified position.
7864 Here we check that we are in the right spot. If not, make a second
7865 move, assuming we are dealing with the second kind of window manager. */
7866static void
7867x_check_fullscreen_move (f)
7868 struct frame *f;
7869{
7870 if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
7871 {
7872 int expect_top = f->output_data.w32->top_pos;
7873 int expect_left = f->output_data.w32->left_pos;
7874
7875 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
7876 expect_top = 0;
7877 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
7878 expect_left = 0;
d67d1627 7879
549808db
JR
7880 if (expect_top != f->output_data.w32->top_pos
7881 || expect_left != f->output_data.w32->left_pos)
7882 x_set_offset (f, expect_left, expect_top, 1);
7883
7884 /* Just do this once */
7885 f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
7886 }
7887}
7888
7889
7890/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
7891 wanted positions of the WM window (not emacs window).
7892 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
7893 window (FRAME_X_WINDOW).
7894 */
7895void
7896x_fullscreen_adjust (f, width, height, top_pos, left_pos)
7897 struct frame *f;
7898 int *width;
7899 int *height;
7900 int *top_pos;
7901 int *left_pos;
7902{
7903 int newwidth = f->width, newheight = f->height;
7904
7905 *top_pos = f->output_data.w32->top_pos;
7906 *left_pos = f->output_data.w32->left_pos;
d67d1627 7907
549808db
JR
7908 if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
7909 {
7910 int ph;
d67d1627 7911
549808db
JR
7912 ph = FRAME_X_DISPLAY_INFO (f)->height;
7913 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
7914 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
7915 - f->output_data.w32->y_pixels_diff;
7916 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
7917 *top_pos = 0;
7918 }
7919
7920 if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
7921 {
7922 int pw;
d67d1627 7923
549808db
JR
7924 pw = FRAME_X_DISPLAY_INFO (f)->width;
7925 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
7926 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
7927 - f->output_data.w32->x_pixels_diff;
7928 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
7929 *left_pos = 0;
7930 }
7931
7932 *width = newwidth;
7933 *height = newheight;
7934}
7935
7936
ee78dc32
GV
7937/* Call this to change the size of frame F's x-window.
7938 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
7939 for this size change and subsequent size changes.
7940 Otherwise we leave the window gravity unchanged. */
c2cc16fa 7941
791f420f 7942void
ee78dc32
GV
7943x_set_window_size (f, change_gravity, cols, rows)
7944 struct frame *f;
7945 int change_gravity;
7946 int cols, rows;
7947{
7948 int pixelwidth, pixelheight;
d67d1627 7949
ee78dc32 7950 BLOCK_INPUT;
d67d1627 7951
ee78dc32 7952 check_frame_size (f, &rows, &cols);
fbd6baed 7953 f->output_data.w32->vertical_scroll_bar_extra
ee78dc32
GV
7954 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
7955 ? 0
fbd6baed 7956 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
d33c49e8 7957
b6ae1532 7958 compute_fringe_widths (f, 0);
d33c49e8 7959
ee78dc32
GV
7960 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
7961 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
d67d1627 7962
fbd6baed 7963 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32 7964 x_wm_set_size_hint (f, (long) 0, 0);
d67d1627 7965
ee78dc32
GV
7966 {
7967 RECT rect;
7968
7969 rect.left = rect.top = 0;
7970 rect.right = pixelwidth;
7971 rect.bottom = pixelheight;
d67d1627 7972
fbd6baed 7973 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
97c23857 7974 FRAME_EXTERNAL_MENU_BAR (f));
d67d1627 7975
fbd6baed 7976 my_set_window_pos (FRAME_W32_WINDOW (f),
d67d1627 7977 NULL,
52cf03a1 7978 0, 0,
689004fa
GV
7979 rect.right - rect.left,
7980 rect.bottom - rect.top,
7981 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
ee78dc32 7982 }
d67d1627 7983
ee78dc32
GV
7984 /* Now, strictly speaking, we can't be sure that this is accurate,
7985 but the window manager will get around to dealing with the size
7986 change request eventually, and we'll hear how it went when the
7987 ConfigureNotify event gets here.
d67d1627 7988
ee78dc32
GV
7989 We could just not bother storing any of this information here,
7990 and let the ConfigureNotify event set everything up, but that
ec48c3a7 7991 might be kind of confusing to the Lisp code, since size changes
ee78dc32 7992 wouldn't be reported in the frame parameters until some random
791f420f
JR
7993 point in the future when the ConfigureNotify event arrives.
7994
7995 We pass 1 for DELAY since we can't run Lisp code inside of
7996 a BLOCK_INPUT. */
7997 change_frame_size (f, rows, cols, 0, 1, 0);
ee78dc32
GV
7998 PIXEL_WIDTH (f) = pixelwidth;
7999 PIXEL_HEIGHT (f) = pixelheight;
8000
689004fa
GV
8001 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8002 receive in the ConfigureNotify event; if we get what we asked
8003 for, then the event won't cause the screen to become garbaged, so
8004 we have to make sure to do it here. */
8005 SET_FRAME_GARBAGED (f);
8006
ee78dc32 8007 /* If cursor was outside the new size, mark it as off. */
791f420f 8008 mark_window_cursors_off (XWINDOW (f->root_window));
ee78dc32 8009
689004fa 8010 /* Clear out any recollection of where the mouse highlighting was,
d67d1627 8011 since it might be in a place that's outside the new frame size.
689004fa
GV
8012 Actually checking whether it is outside is a pain in the neck,
8013 so don't try--just let the highlighting be done afresh with new size. */
31d4844a
KH
8014 cancel_mouse_face (f);
8015
ee78dc32
GV
8016 UNBLOCK_INPUT;
8017}
8018\f
8019/* Mouse warping. */
8020
ec48c3a7
JR
8021void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
8022
8023void
8024x_set_mouse_position (f, x, y)
8025 struct frame *f;
8026 int x, y;
8027{
8028 int pix_x, pix_y;
8029
8030 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
8031 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
8032
8033 if (pix_x < 0) pix_x = 0;
8034 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
8035
8036 if (pix_y < 0) pix_y = 0;
8037 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
8038
8039 x_set_mouse_pixel_position (f, pix_x, pix_y);
8040}
8041
1bcd16f2
MB
8042void
8043x_set_mouse_pixel_position (f, pix_x, pix_y)
8044 struct frame *f;
8045 int pix_x, pix_y;
8046{
689004fa
GV
8047 RECT rect;
8048 POINT pt;
8049
1bcd16f2
MB
8050 BLOCK_INPUT;
8051
689004fa
GV
8052 GetClientRect (FRAME_W32_WINDOW (f), &rect);
8053 pt.x = rect.left + pix_x;
8054 pt.y = rect.top + pix_y;
8055 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
1bcd16f2 8056
689004fa 8057 SetCursorPos (pt.x, pt.y);
1bcd16f2
MB
8058
8059 UNBLOCK_INPUT;
8060}
8061
ee78dc32
GV
8062\f
8063/* focus shifting, raising and lowering. */
8064
ec48c3a7 8065void
ee78dc32
GV
8066x_focus_on_frame (f)
8067 struct frame *f;
8068{
689004fa
GV
8069 struct w32_display_info *dpyinfo = &one_w32_display_info;
8070
8071 /* Give input focus to frame. */
8072 BLOCK_INPUT;
8073#if 0
8074 /* Try not to change its Z-order if possible. */
8075 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
8076 my_set_focus (f, FRAME_W32_WINDOW (f));
8077 else
8078#endif
ef0e360f 8079 my_set_foreground_window (FRAME_W32_WINDOW (f));
689004fa 8080 UNBLOCK_INPUT;
ee78dc32
GV
8081}
8082
ec48c3a7 8083void
ee78dc32
GV
8084x_unfocus_frame (f)
8085 struct frame *f;
8086{
8087}
8088
8089/* Raise frame F. */
791f420f 8090void
ee78dc32
GV
8091x_raise_frame (f)
8092 struct frame *f;
8093{
689004fa
GV
8094 BLOCK_INPUT;
8095
8096 /* Strictly speaking, raise-frame should only change the frame's Z
8097 order, leaving input focus unchanged. This is reasonable behaviour
8098 on X where the usual policy is point-to-focus. However, this
8099 behaviour would be very odd on Windows where the usual policy is
8100 click-to-focus.
8101
8102 On X, if the mouse happens to be over the raised frame, it gets
8103 input focus anyway (so the window with focus will never be
8104 completely obscured) - if not, then just moving the mouse over it
8105 is sufficient to give it focus. On Windows, the user must actually
8106 click on the frame (preferrably the title bar so as not to move
8107 point), which is more awkward. Also, no other Windows program
8108 raises a window to the top but leaves another window (possibly now
8109 completely obscured) with input focus.
8110
8111 Because there is a system setting on Windows that allows the user
8112 to choose the point to focus policy, we make the strict semantics
8113 optional, but by default we grab focus when raising. */
8114
8115 if (NILP (Vw32_grab_focus_on_raise))
ee78dc32 8116 {
689004fa
GV
8117 /* The obvious call to my_set_window_pos doesn't work if Emacs is
8118 not already the foreground application: the frame is raised
8119 above all other frames belonging to us, but not above the
8120 current top window. To achieve that, we have to resort to this
8121 more cumbersome method. */
8122
8123 HDWP handle = BeginDeferWindowPos (2);
8124 if (handle)
8125 {
8126 DeferWindowPos (handle,
8127 FRAME_W32_WINDOW (f),
8128 HWND_TOP,
8129 0, 0, 0, 0,
8130 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8131
8132 DeferWindowPos (handle,
8133 GetForegroundWindow (),
8134 FRAME_W32_WINDOW (f),
8135 0, 0, 0, 0,
8136 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8137
8138 EndDeferWindowPos (handle);
8139 }
ee78dc32 8140 }
689004fa
GV
8141 else
8142 {
ef0e360f 8143 my_set_foreground_window (FRAME_W32_WINDOW (f));
689004fa
GV
8144 }
8145
8146 UNBLOCK_INPUT;
ee78dc32
GV
8147}
8148
8149/* Lower frame F. */
791f420f 8150void
ee78dc32
GV
8151x_lower_frame (f)
8152 struct frame *f;
8153{
689004fa
GV
8154 BLOCK_INPUT;
8155 my_set_window_pos (FRAME_W32_WINDOW (f),
8156 HWND_BOTTOM,
8157 0, 0, 0, 0,
8158 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
8159 UNBLOCK_INPUT;
ee78dc32
GV
8160}
8161
8162static void
ec48c3a7 8163w32_frame_raise_lower (f, raise_flag)
ee78dc32 8164 FRAME_PTR f;
ec48c3a7 8165 int raise_flag;
ee78dc32 8166{
7e6ac5b9
AI
8167 if (! FRAME_W32_P (f))
8168 return;
8169
ec48c3a7 8170 if (raise_flag)
ee78dc32
GV
8171 x_raise_frame (f);
8172 else
8173 x_lower_frame (f);
8174}
8175\f
8176/* Change of visibility. */
8177
8178/* This tries to wait until the frame is really visible.
8179 However, if the window manager asks the user where to position
8180 the frame, this will return before the user finishes doing that.
8181 The frame will not actually be visible at that time,
8182 but it will become visible later when the window manager
8183 finishes with it. */
8184
ec48c3a7 8185void
ee78dc32
GV
8186x_make_frame_visible (f)
8187 struct frame *f;
8188{
7f5d1df8
GV
8189 Lisp_Object type;
8190
ee78dc32
GV
8191 BLOCK_INPUT;
8192
7f5d1df8
GV
8193 type = x_icon_type (f);
8194 if (!NILP (type))
8195 x_bitmap_icon (f, type);
8196
ee78dc32
GV
8197 if (! FRAME_VISIBLE_P (f))
8198 {
8199 /* We test FRAME_GARBAGED_P here to make sure we don't
8200 call x_set_offset a second time
8201 if we get to x_make_frame_visible a second time
8202 before the window gets really visible. */
8203 if (! FRAME_ICONIFIED_P (f)
fbd6baed 8204 && ! f->output_data.w32->asked_for_visible)
fbd6baed 8205 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
ee78dc32 8206
fbd6baed 8207 f->output_data.w32->asked_for_visible = 1;
52cf03a1 8208
4d6e8199 8209/* my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); */
689004fa 8210 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
ee78dc32
GV
8211 }
8212
8213 /* Synchronize to ensure Emacs knows the frame is visible
8214 before we do anything else. We do this loop with input not blocked
8215 so that incoming events are handled. */
8216 {
8217 Lisp_Object frame;
791f420f 8218 int count;
ee78dc32
GV
8219
8220 /* This must come after we set COUNT. */
8221 UNBLOCK_INPUT;
8222
8223 XSETFRAME (frame, f);
8224
791f420f
JR
8225 /* Wait until the frame is visible. Process X events until a
8226 MapNotify event has been seen, or until we think we won't get a
8227 MapNotify at all.. */
8228 for (count = input_signal_count + 10;
8229 input_signal_count < count && !FRAME_VISIBLE_P (f);)
ee78dc32 8230 {
791f420f 8231 /* Force processing of queued events. */
01b220b6 8232 /* TODO: x_sync equivalent? */
791f420f 8233
ee78dc32
GV
8234 /* Machines that do polling rather than SIGIO have been observed
8235 to go into a busy-wait here. So we'll fake an alarm signal
8236 to let the handler know that there's something to be read.
8237 We used to raise a real alarm, but it seems that the handler
8238 isn't always enabled here. This is probably a bug. */
8239 if (input_polling_used ())
8240 {
8241 /* It could be confusing if a real alarm arrives while processing
8242 the fake one. Turn it off and let the handler reset it. */
a9b4e0ec
AI
8243 int old_poll_suppress_count = poll_suppress_count;
8244 poll_suppress_count = 1;
8245 poll_for_input_1 ();
8246 poll_suppress_count = old_poll_suppress_count;
ee78dc32 8247 }
ee78dc32
GV
8248 }
8249 FRAME_SAMPLE_VISIBILITY (f);
8250 }
8251}
8252
8253/* Change from mapped state to withdrawn state. */
8254
8255/* Make the frame visible (mapped and not iconified). */
8256
8257x_make_frame_invisible (f)
8258 struct frame *f;
8259{
ee78dc32 8260 /* Don't keep the highlight on an invisible frame. */
4baaed0f
KS
8261 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
8262 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
d67d1627 8263
ee78dc32 8264 BLOCK_INPUT;
d67d1627 8265
689004fa 8266 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
d67d1627 8267
ee78dc32
GV
8268 /* We can't distinguish this from iconification
8269 just by the event that we get from the server.
8270 So we can't win using the usual strategy of letting
8271 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8272 and synchronize with the server to make sure we agree. */
8273 f->visible = 0;
8274 FRAME_ICONIFIED_P (f) = 0;
8275 f->async_visible = 0;
8276 f->async_iconified = 0;
d67d1627 8277
ee78dc32
GV
8278 UNBLOCK_INPUT;
8279}
8280
8281/* Change window state from mapped to iconified. */
8282
52cf03a1
GV
8283void
8284x_iconify_frame (f)
ee78dc32
GV
8285 struct frame *f;
8286{
7f5d1df8 8287 Lisp_Object type;
ee78dc32
GV
8288
8289 /* Don't keep the highlight on an invisible frame. */
4baaed0f
KS
8290 if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
8291 FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
ee78dc32
GV
8292
8293 if (f->async_iconified)
8294 return;
8295
8296 BLOCK_INPUT;
8297
7f5d1df8
GV
8298 type = x_icon_type (f);
8299 if (!NILP (type))
8300 x_bitmap_icon (f, type);
8301
689004fa 8302 /* Simulate the user minimizing the frame. */
4934bcdd 8303 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
ee78dc32
GV
8304
8305 UNBLOCK_INPUT;
8306}
c2cc16fa 8307
ee78dc32 8308\f
25badd7a 8309/* Free X resources of frame F. */
ee78dc32 8310
25badd7a
AI
8311void
8312x_free_frame_resources (f)
ee78dc32
GV
8313 struct frame *f;
8314{
fbd6baed 8315 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
8316
8317 BLOCK_INPUT;
8318
25badd7a
AI
8319 if (FRAME_W32_WINDOW (f))
8320 my_destroy_window (f, FRAME_W32_WINDOW (f));
d67d1627 8321
ee78dc32 8322 free_frame_menubar (f);
ee78dc32 8323
25badd7a
AI
8324 unload_color (f, f->output_data.x->foreground_pixel);
8325 unload_color (f, f->output_data.x->background_pixel);
8326 unload_color (f, f->output_data.w32->cursor_pixel);
8327 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
8328 unload_color (f, f->output_data.w32->border_pixel);
8329 unload_color (f, f->output_data.w32->mouse_pixel);
c2cc16fa
JR
8330 if (f->output_data.w32->white_relief.allocated_p)
8331 unload_color (f, f->output_data.w32->white_relief.pixel);
8332 if (f->output_data.w32->black_relief.allocated_p)
8333 unload_color (f, f->output_data.w32->black_relief.pixel);
8334
25badd7a
AI
8335 if (FRAME_FACE_CACHE (f))
8336 free_frame_faces (f);
d67d1627 8337
fbd6baed 8338 xfree (f->output_data.w32);
25badd7a 8339 f->output_data.w32 = NULL;
d67d1627 8340
fbd6baed
GV
8341 if (f == dpyinfo->w32_focus_frame)
8342 dpyinfo->w32_focus_frame = 0;
8343 if (f == dpyinfo->w32_focus_event_frame)
8344 dpyinfo->w32_focus_event_frame = 0;
4baaed0f
KS
8345 if (f == dpyinfo->x_highlight_frame)
8346 dpyinfo->x_highlight_frame = 0;
ee78dc32 8347
ee78dc32
GV
8348 if (f == dpyinfo->mouse_face_mouse_frame)
8349 {
8350 dpyinfo->mouse_face_beg_row
8351 = dpyinfo->mouse_face_beg_col = -1;
8352 dpyinfo->mouse_face_end_row
8353 = dpyinfo->mouse_face_end_col = -1;
8354 dpyinfo->mouse_face_window = Qnil;
25badd7a
AI
8355 dpyinfo->mouse_face_deferred_gc = 0;
8356 dpyinfo->mouse_face_mouse_frame = 0;
ee78dc32
GV
8357 }
8358
8359 UNBLOCK_INPUT;
8360}
25badd7a
AI
8361
8362
8363/* Destroy the window of frame F. */
8364
8365x_destroy_window (f)
8366 struct frame *f;
8367{
8368 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8369
8370 x_free_frame_resources (f);
8371
8372 dpyinfo->reference_count--;
8373}
c2cc16fa 8374
ee78dc32
GV
8375\f
8376/* Setting window manager hints. */
8377
8378/* Set the normal size hints for the window manager, for frame F.
8379 FLAGS is the flags word to use--or 0 meaning preserve the flags
8380 that the window now has.
8381 If USER_POSITION is nonzero, we set the USPosition
8382 flag (this is useful when FLAGS is 0). */
791f420f 8383void
ee78dc32
GV
8384x_wm_set_size_hint (f, flags, user_position)
8385 struct frame *f;
8386 long flags;
8387 int user_position;
8388{
fbd6baed 8389 Window window = FRAME_W32_WINDOW (f);
ee78dc32 8390
97c23857 8391 enter_crit ();
ee78dc32 8392
689004fa
GV
8393 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
8394 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
8395 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
8396 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
ee78dc32 8397
97c23857 8398 leave_crit ();
ee78dc32
GV
8399}
8400
8401/* Window manager things */
8402x_wm_set_icon_position (f, icon_x, icon_y)
8403 struct frame *f;
8404 int icon_x, icon_y;
8405{
8406#if 0
fbd6baed 8407 Window window = FRAME_W32_WINDOW (f);
ee78dc32
GV
8408
8409 f->display.x->wm_hints.flags |= IconPositionHint;
8410 f->display.x->wm_hints.icon_x = icon_x;
8411 f->display.x->wm_hints.icon_y = icon_y;
8412
8413 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
8414#endif
8415}
8416
c2cc16fa
JR
8417\f
8418/***********************************************************************
8419 Fonts
8420 ***********************************************************************/
8421
8422/* The following functions are listed here to help diff stay in step
8423 with xterm.c. See w32fns.c for definitions.
8424
8425x_get_font_info (f, font_idx)
8426x_list_fonts (f, pattern, size, maxnames)
8427
8428 */
8429
8430#if GLYPH_DEBUG
8431
8432/* Check that FONT is valid on frame F. It is if it can be found in F's
8433 font table. */
8434
8435static void
8436x_check_font (f, font)
8437 struct frame *f;
8438 XFontStruct *font;
8439{
8440 int i;
8441 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8442
8443 xassert (font != NULL);
9ef2e2cf 8444
c2cc16fa 8445 for (i = 0; i < dpyinfo->n_fonts; i++)
d67d1627 8446 if (dpyinfo->font_table[i].name
c2cc16fa
JR
8447 && font == dpyinfo->font_table[i].font)
8448 break;
8449
8450 xassert (i < dpyinfo->n_fonts);
8451}
8452
8453#endif /* GLYPH_DEBUG != 0 */
8454
8455/* Set *W to the minimum width, *H to the minimum font height of FONT.
8456 Note: There are (broken) X fonts out there with invalid XFontStruct
8457 min_bounds contents. For example, handa@etl.go.jp reports that
8458 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8459 have font->min_bounds.width == 0. */
8460
8461static INLINE void
8462x_font_min_bounds (font, w, h)
8463 XFontStruct *font;
8464 int *w, *h;
8465{
8466 /*
8467 * TODO: Windows does not appear to offer min bound, only
8468 * average and maximum width, and maximum height.
8469 */
8470 *h = FONT_HEIGHT (font);
8471 *w = FONT_WIDTH (font);
8472}
8473
8474
8475/* Compute the smallest character width and smallest font height over
8476 all fonts available on frame F. Set the members smallest_char_width
8477 and smallest_font_height in F's x_display_info structure to
8478 the values computed. Value is non-zero if smallest_font_height or
8479 smallest_char_width become smaller than they were before. */
8480
8481int
8482x_compute_min_glyph_bounds (f)
8483 struct frame *f;
8484{
8485 int i;
8486 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8487 XFontStruct *font;
8488 int old_width = dpyinfo->smallest_char_width;
8489 int old_height = dpyinfo->smallest_font_height;
d67d1627 8490
c2cc16fa
JR
8491 dpyinfo->smallest_font_height = 100000;
8492 dpyinfo->smallest_char_width = 100000;
d67d1627 8493
c2cc16fa
JR
8494 for (i = 0; i < dpyinfo->n_fonts; ++i)
8495 if (dpyinfo->font_table[i].name)
8496 {
8497 struct font_info *fontp = dpyinfo->font_table + i;
8498 int w, h;
d67d1627 8499
c2cc16fa
JR
8500 font = (XFontStruct *) fontp->font;
8501 xassert (font != (XFontStruct *) ~0);
8502 x_font_min_bounds (font, &w, &h);
d67d1627 8503
c2cc16fa
JR
8504 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8505 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8506 }
8507
8508 xassert (dpyinfo->smallest_char_width > 0
8509 && dpyinfo->smallest_font_height > 0);
8510
8511 return (dpyinfo->n_fonts == 1
8512 || dpyinfo->smallest_char_width < old_width
8513 || dpyinfo->smallest_font_height < old_height);
8514}
8515
8516/* The following functions are listed here to help diff stay in step
8517 with xterm.c. See w32fns.c for definitions.
8518
8519x_load_font (f, fontname, size)
8520x_query_font (f, fontname)
8521x_find_ccl_program (fontp)
8522
8523*/
ee78dc32 8524\f
791f420f
JR
8525/***********************************************************************
8526 Initialization
8527 ***********************************************************************/
ee78dc32 8528
fbd6baed 8529static int w32_initialized = 0;
ee78dc32 8530
f7737f5d
JR
8531void
8532w32_initialize_display_info (display_name)
8533 Lisp_Object display_name;
8534{
8535 struct w32_display_info *dpyinfo = &one_w32_display_info;
8536
8537 bzero (dpyinfo, sizeof (*dpyinfo));
8538
8539 /* Put it on w32_display_name_list. */
8540 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
8541 w32_display_name_list);
8542 dpyinfo->name_list_element = XCAR (w32_display_name_list);
d67d1627 8543
f7737f5d 8544 dpyinfo->w32_id_name
d5db4077
KR
8545 = (char *) xmalloc (SCHARS (Vinvocation_name)
8546 + SCHARS (Vsystem_name)
f7737f5d
JR
8547 + 2);
8548 sprintf (dpyinfo->w32_id_name, "%s@%s",
d5db4077 8549 SDATA (Vinvocation_name), SDATA (Vsystem_name));
f7737f5d
JR
8550
8551 /* Default Console mode values - overridden when running in GUI mode
8552 with values obtained from system metrics. */
8553 dpyinfo->resx = 1;
8554 dpyinfo->resy = 1;
8555 dpyinfo->height_in = 1;
8556 dpyinfo->width_in = 1;
8557 dpyinfo->n_planes = 1;
8558 dpyinfo->n_cbits = 4;
8559 dpyinfo->n_fonts = 0;
8560 dpyinfo->smallest_font_height = 1;
8561 dpyinfo->smallest_char_width = 1;
8562
8563 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8564 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8565 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8566 dpyinfo->mouse_face_window = Qnil;
9f5a911b 8567 dpyinfo->mouse_face_overlay = Qnil;
3d26a7c2 8568 dpyinfo->mouse_face_hidden = 0;
2bf04b9d
JR
8569
8570 dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
01b220b6 8571 /* TODO: dpyinfo->gray */
f7737f5d
JR
8572
8573}
8574
c13a8a91
JB
8575/* Create an xrdb-style database of resources to supercede registry settings.
8576 The database is just a concatenation of C strings, finished by an additional
8577 \0. The string are submitted to some basic normalization, so
8578
8579 [ *]option[ *]:[ *]value...
8580
8581 becomes
8582
8583 option:value...
8584
8585 but any whitespace following value is not removed. */
8586
8587static char *
8588w32_make_rdb (xrm_option)
8589 char *xrm_option;
8590{
8591 char *buffer = xmalloc (strlen (xrm_option) + 2);
8592 char *current = buffer;
8593 char ch;
8594 int in_option = 1;
8595 int before_value = 0;
8596
8597 do {
8598 ch = *xrm_option++;
8599
8600 if (ch == '\n')
8601 {
8602 *current++ = '\0';
8603 in_option = 1;
8604 before_value = 0;
8605 }
8606 else if (ch != ' ')
8607 {
8608 *current++ = ch;
8609 if (in_option && (ch == ':'))
8610 {
8611 in_option = 0;
8612 before_value = 1;
8613 }
8614 else if (before_value)
8615 {
8616 before_value = 0;
8617 }
8618 }
8619 else if (!(in_option || before_value))
8620 {
8621 *current++ = ch;
8622 }
8623 } while (ch);
8624
8625 *current = '\0';
8626
8627 return buffer;
8628}
8629
fbd6baed
GV
8630struct w32_display_info *
8631w32_term_init (display_name, xrm_option, resource_name)
ee78dc32
GV
8632 Lisp_Object display_name;
8633 char *xrm_option;
8634 char *resource_name;
8635{
fbd6baed 8636 struct w32_display_info *dpyinfo;
ee78dc32 8637 HDC hdc;
d67d1627 8638
ee78dc32 8639 BLOCK_INPUT;
d67d1627 8640
fbd6baed 8641 if (!w32_initialized)
ee78dc32 8642 {
fbd6baed
GV
8643 w32_initialize ();
8644 w32_initialized = 1;
ee78dc32 8645 }
d67d1627 8646
f7737f5d 8647 w32_initialize_display_info (display_name);
ee78dc32 8648
f7737f5d 8649 dpyinfo = &one_w32_display_info;
8c3b00cb 8650
c13a8a91
JB
8651 dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
8652
8c3b00cb
AI
8653 /* Put this display on the chain. */
8654 dpyinfo->next = x_display_list;
8655 x_display_list = dpyinfo;
d67d1627 8656
52cf03a1 8657 hdc = GetDC (GetDesktopWindow ());
791f420f 8658
ee78dc32
GV
8659 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
8660 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
8661 dpyinfo->root_window = GetDesktopWindow ();
8662 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
8663 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
55689ab1
JR
8664 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
8665 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
52cf03a1 8666 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
791f420f 8667 dpyinfo->image_cache = make_image_cache ();
55689ab1
JR
8668 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
8669 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
ee78dc32 8670 ReleaseDC (GetDesktopWindow (), hdc);
52cf03a1
GV
8671
8672 /* initialise palette with white and black */
8673 {
316ed821 8674 XColor color;
55689ab1
JR
8675 w32_defined_color (0, "white", &color, 1);
8676 w32_defined_color (0, "black", &color, 1);
52cf03a1
GV
8677 }
8678
b6ae1532
KS
8679 /* Create Fringe Bitmaps and store them for later use.
8680
8681 On W32, bitmaps are all unsigned short, as Windows requires
8682 bitmap data to be Word aligned. For some reason they are
8683 horizontally reflected compared to how they appear on X, so we
8684 need to bitswap and convert to unsigned shorts before creating
8685 the bitmaps. */
8686 {
8687 int i, j;
8688
8689 for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
8690 {
8691 int h = fringe_bitmaps[i].height;
8692 int wd = fringe_bitmaps[i].width;
8693 unsigned short *w32bits
8694 = (unsigned short *)alloca (h * sizeof (unsigned short));
8695 unsigned short *wb = w32bits;
8696 unsigned char *bits = fringe_bitmaps[i].bits;
8697 for (j = 0; j < h; j++)
8698 {
8699 static unsigned char swap_nibble[16]
8700 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
8701 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
8702 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
8703 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
8704
8705 unsigned char b = *bits++;
8706 *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4)
8707 | (swap_nibble[(b>>4) & 0xf]));
8708 }
8709 fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits);
8710 }
8711 }
f7737f5d 8712
ee78dc32
GV
8713#ifndef F_SETOWN_BUG
8714#ifdef F_SETOWN
8715#ifdef F_SETOWN_SOCK_NEG
8716 /* stdin is a socket here */
8717 fcntl (connection, F_SETOWN, -getpid ());
8718#else /* ! defined (F_SETOWN_SOCK_NEG) */
8719 fcntl (connection, F_SETOWN, getpid ());
8720#endif /* ! defined (F_SETOWN_SOCK_NEG) */
8721#endif /* ! defined (F_SETOWN) */
8722#endif /* F_SETOWN_BUG */
8723
8724#ifdef SIGIO
8725 if (interrupt_input)
8726 init_sigio (connection);
8727#endif /* ! defined (SIGIO) */
8728
8729 UNBLOCK_INPUT;
8730
8731 return dpyinfo;
8732}
8733\f
8734/* Get rid of display DPYINFO, assuming all frames are already gone. */
8735
8736void
8737x_delete_display (dpyinfo)
fbd6baed 8738 struct w32_display_info *dpyinfo;
ee78dc32 8739{
fbd6baed 8740 /* Discard this display from w32_display_name_list and w32_display_list.
ee78dc32 8741 We can't use Fdelq because that can quit. */
fbd6baed 8742 if (! NILP (w32_display_name_list)
8e713be6
KR
8743 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
8744 w32_display_name_list = XCDR (w32_display_name_list);
ee78dc32
GV
8745 else
8746 {
8747 Lisp_Object tail;
8748
fbd6baed 8749 tail = w32_display_name_list;
8e713be6 8750 while (CONSP (tail) && CONSP (XCDR (tail)))
ee78dc32 8751 {
f7737f5d 8752 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
ee78dc32 8753 {
f3fbd155 8754 XSETCDR (tail, XCDR (XCDR (tail)));
ee78dc32
GV
8755 break;
8756 }
8e713be6 8757 tail = XCDR (tail);
ee78dc32
GV
8758 }
8759 }
8760
52cf03a1
GV
8761 /* free palette table */
8762 {
fbd6baed 8763 struct w32_palette_entry * plist;
52cf03a1
GV
8764
8765 plist = dpyinfo->color_list;
8766 while (plist)
8767 {
fbd6baed 8768 struct w32_palette_entry * pentry = plist;
52cf03a1 8769 plist = plist->next;
9127e20e 8770 xfree (pentry);
52cf03a1
GV
8771 }
8772 dpyinfo->color_list = NULL;
8773 if (dpyinfo->palette)
8774 DeleteObject(dpyinfo->palette);
8775 }
ee78dc32 8776 xfree (dpyinfo->font_table);
fbd6baed 8777 xfree (dpyinfo->w32_id_name);
f7737f5d
JR
8778
8779 /* Destroy row bitmaps. */
b6ae1532
KS
8780 {
8781 int i;
8782
8783 for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
8784 DeleteObject (fringe_bmp[i]);
8785 }
ee78dc32
GV
8786}
8787\f
fbd6baed 8788/* Set up use of W32. */
ee78dc32 8789
689004fa 8790DWORD w32_msg_worker ();
ee78dc32 8791
791f420f
JR
8792void
8793x_flush (struct frame * f)
8794{ /* Nothing to do */ }
8795
8796static struct redisplay_interface w32_redisplay_interface =
8797{
8798 x_produce_glyphs,
8799 x_write_glyphs,
8800 x_insert_glyphs,
8801 x_clear_end_of_line,
8802 x_scroll_run,
8803 x_after_update_window_line,
8804 x_update_window_begin,
8805 x_update_window_end,
8806 w32_cursor_to,
8807 x_flush,
ec48c3a7 8808 x_clear_mouse_face,
6b6bd726 8809 w32_get_glyph_overhangs,
b6ae1532 8810 x_fix_overlapping_area,
6b6bd726
KS
8811 w32_draw_fringe_bitmap,
8812 w32_per_char_metric,
8813 w32_encode_char,
8814 NULL, /* w32_compute_glyph_string_overhangs */
8815 x_draw_glyph_string
791f420f
JR
8816};
8817
8818void
fbd6baed
GV
8819w32_initialize ()
8820{
791f420f
JR
8821 rif = &w32_redisplay_interface;
8822
96214669
GV
8823 /* MSVC does not type K&R functions with no arguments correctly, and
8824 so we must explicitly cast them. */
791f420f 8825 clear_frame_hook = (void (*)(void)) x_clear_frame;
96214669 8826 ring_bell_hook = (void (*)(void)) w32_ring_bell;
791f420f
JR
8827 update_begin_hook = x_update_begin;
8828 update_end_hook = x_update_end;
0f32f023 8829
ee78dc32 8830 read_socket_hook = w32_read_socket;
0f32f023 8831
fbd6baed 8832 frame_up_to_date_hook = w32_frame_up_to_date;
0f32f023 8833
fbd6baed
GV
8834 mouse_position_hook = w32_mouse_position;
8835 frame_rehighlight_hook = w32_frame_rehighlight;
8836 frame_raise_lower_hook = w32_frame_raise_lower;
8837 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
8838 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
8839 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
8840 judge_scroll_bars_hook = w32_judge_scroll_bars;
791f420f 8841 estimate_mode_line_height_hook = x_estimate_mode_line_height;
ee78dc32
GV
8842
8843 scroll_region_ok = 1; /* we'll scroll partial frames */
49be9f70 8844 char_ins_del_ok = 1;
ee78dc32
GV
8845 line_ins_del_ok = 1; /* we'll just blt 'em */
8846 fast_clear_end_of_line = 1; /* X does this well */
8847 memory_below_frame = 0; /* we don't remember what scrolls
8848 off the bottom */
8849 baud_rate = 19200;
8850
abb15ebd
JR
8851 w32_system_caret_hwnd = NULL;
8852 w32_system_caret_height = 0;
abb15ebd
JR
8853 w32_system_caret_x = 0;
8854 w32_system_caret_y = 0;
8855
791f420f
JR
8856 last_tool_bar_item = -1;
8857 any_help_event_p = 0;
8858
689004fa
GV
8859 /* Initialize input mode: interrupt_input off, no flow control, allow
8860 8 bit character input, standard quit char. */
8861 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
ee78dc32
GV
8862
8863 /* Create the window thread - it will terminate itself or when the app terminates */
8864
8865 init_crit ();
8866
8867 dwMainThreadId = GetCurrentThreadId ();
d67d1627 8868 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
ee78dc32
GV
8869 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
8870
8871 /* Wait for thread to start */
8872
8873 {
8874 MSG msg;
8875
8876 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
8877
d67d1627
JB
8878 hWindowsThread = CreateThread (NULL, 0,
8879 (LPTHREAD_START_ROUTINE) w32_msg_worker,
e9e23e23 8880 0, 0, &dwWindowsThreadId);
ee78dc32
GV
8881
8882 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
8883 }
d67d1627 8884
52cf03a1 8885 /* It is desirable that mainThread should have the same notion of
e9e23e23 8886 focus window and active window as windowsThread. Unfortunately, the
52cf03a1
GV
8887 following call to AttachThreadInput, which should do precisely what
8888 we need, causes major problems when Emacs is linked as a console
8889 program. Unfortunately, we have good reasons for doing that, so
e9e23e23 8890 instead we need to send messages to windowsThread to make some API
52cf03a1
GV
8891 calls for us (ones that affect, or depend on, the active/focus
8892 window state. */
8893#ifdef ATTACH_THREADS
e9e23e23 8894 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
52cf03a1 8895#endif
689004fa
GV
8896
8897 /* Dynamically link to optional system components. */
8898 {
8899 HANDLE user_lib = LoadLibrary ("user32.dll");
8900
8901#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
8902
8903 /* New proportional scroll bar functions. */
9127e20e
JR
8904 LOAD_PROC (SetScrollInfo);
8905 LOAD_PROC (GetScrollInfo);
689004fa
GV
8906
8907#undef LOAD_PROC
8908
8909 FreeLibrary (user_lib);
8910
8911 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
8912 otherwise use the fixed height. */
8913 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
8914 GetSystemMetrics (SM_CYVTHUMB);
8915
8916 /* For either kind of scroll bar, take account of the arrows; these
8917 effectively form the border of the main scroll bar range. */
8918 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
8919 = GetSystemMetrics (SM_CYVSCROLL);
8920 }
ee78dc32
GV
8921}
8922
8923void
fbd6baed 8924syms_of_w32term ()
ee78dc32 8925{
fbd6baed
GV
8926 staticpro (&w32_display_name_list);
8927 w32_display_name_list = Qnil;
ee78dc32
GV
8928
8929 staticpro (&last_mouse_scroll_bar);
8930 last_mouse_scroll_bar = Qnil;
8931
8932 staticpro (&Qvendor_specific_keysyms);
8933 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
52cf03a1 8934
fbd6baed
GV
8935 DEFVAR_INT ("w32-num-mouse-buttons",
8936 &Vw32_num_mouse_buttons,
33f09670 8937 doc: /* Number of physical mouse buttons. */);
fbd6baed 8938 Vw32_num_mouse_buttons = Qnil;
52cf03a1 8939
fbd6baed
GV
8940 DEFVAR_LISP ("w32-swap-mouse-buttons",
8941 &Vw32_swap_mouse_buttons,
33f09670
JR
8942 doc: /* Swap the mapping of middle and right mouse buttons.
8943When nil, middle button is mouse-2 and right button is mouse-3. */);
fbd6baed 8944 Vw32_swap_mouse_buttons = Qnil;
689004fa
GV
8945
8946 DEFVAR_LISP ("w32-grab-focus-on-raise",
8947 &Vw32_grab_focus_on_raise,
33f09670
JR
8948 doc: /* Raised frame grabs input focus.
8949When t, `raise-frame' grabs input focus as well. This fits well
8950with the normal Windows click-to-focus policy, but might not be
8951desirable when using a point-to-focus policy. */);
689004fa
GV
8952 Vw32_grab_focus_on_raise = Qt;
8953
8954 DEFVAR_LISP ("w32-capslock-is-shiftlock",
8955 &Vw32_capslock_is_shiftlock,
33f09670
JR
8956 doc: /* Apply CapsLock state to non character input keys.
8957When nil, CapsLock only affects normal character input keys. */);
689004fa 8958 Vw32_capslock_is_shiftlock = Qnil;
ef0e360f
GV
8959
8960 DEFVAR_LISP ("w32-recognize-altgr",
8961 &Vw32_recognize_altgr,
33f09670
JR
8962 doc: /* Recognize right-alt and left-ctrl as AltGr.
8963When nil, the right-alt and left-ctrl key combination is
d67d1627 8964interpreted normally. */);
ef0e360f 8965 Vw32_recognize_altgr = Qt;
bc6af935 8966
484fa2c1
GV
8967 DEFVAR_BOOL ("w32-enable-unicode-output",
8968 &w32_enable_unicode_output,
33f09670
JR
8969 doc: /* Enable the use of Unicode for text output if non-nil.
8970Unicode output may prevent some third party applications for displaying
8971Far-East Languages on Windows 95/98 from working properly.
8972NT uses Unicode internally anyway, so this flag will probably have no
8973affect on NT machines. */);
484fa2c1 8974 w32_enable_unicode_output = 1;
a1b9438c 8975
791f420f 8976 help_echo = Qnil;
ec48c3a7
JR
8977 staticpro (&help_echo);
8978 help_echo_object = Qnil;
8979 staticpro (&help_echo_object);
158cba56
JR
8980 help_echo_window = Qnil;
8981 staticpro (&help_echo_window);
791f420f 8982 previous_help_echo = Qnil;
ec48c3a7 8983 staticpro (&previous_help_echo);
158cba56 8984 help_echo_pos = -1;
791f420f 8985
ee8ceff8 8986 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
549808db 8987 doc: /* *Non-nil means autoselect window with mouse pointer. */);
ee8ceff8 8988 mouse_autoselect_window = 0;
549808db 8989
99558ce8
JR
8990 DEFVAR_BOOL ("w32-use-visible-system-caret",
8991 &w32_use_visible_system_caret,
8992 doc: /* Flag to make the system caret visible.
8993When this is non-nil, Emacs will indicate the position of point by
8994using the system caret instead of drawing its own cursor. Some screen
8995reader software does not track the system cursor properly when it is
8996invisible, and gets confused by Emacs drawing its own cursor, so this
d67d1627 8997variable is initialized to t when Emacs detects that screen reader
99558ce8
JR
8998software is running as it starts up.
8999
9000When this variable is set, other variables affecting the appearance of
9001the cursor have no effect. */);
9002
9003 /* Initialize w32_use_visible_system_caret based on whether a screen
9004 reader is in use. */
ab76d376
JR
9005 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
9006 &w32_use_visible_system_caret, 0))
9007 w32_use_visible_system_caret = 0;
99558ce8 9008
791f420f 9009 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
33f09670
JR
9010 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
9011For example, if a block cursor is over a tab, it will be drawn as
9012wide as that tab on the display. */);
791f420f
JR
9013 x_stretch_cursor_p = 0;
9014
9f5a911b
JR
9015 DEFVAR_BOOL ("x-use-underline-position-properties",
9016 &x_use_underline_position_properties,
33f09670 9017 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
f0529b5b 9018nil means ignore them. If you encounter fonts with bogus
33f09670
JR
9019UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9020to 4.1, set this to nil. */);
9f5a911b 9021 x_use_underline_position_properties = 1;
9f5a911b 9022
5bf04520 9023 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
33f09670 9024 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
5bf04520 9025 Vx_toolkit_scroll_bars = Qt;
791f420f
JR
9026
9027 staticpro (&last_mouse_motion_frame);
9028 last_mouse_motion_frame = Qnil;
ee78dc32 9029}