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