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