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