(display_mode_element): When computing charpos, depend
[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
53823ab9
JR
6040/* Parse a button MESSAGE. The button index is returned in PBUTTON, and
6041 the state in PUP. XBUTTON provides extra information for extended mouse
6042 button messages. Returns FALSE if unable to parse the message. */
ee78dc32 6043BOOL
53823ab9 6044parse_button (message, xbutton, pbutton, pup)
ee78dc32 6045 int message;
53823ab9 6046 int xbutton;
ee78dc32
GV
6047 int * pbutton;
6048 int * pup;
6049{
6050 int button = 0;
6051 int up = 0;
6052
6053 switch (message)
6054 {
6055 case WM_LBUTTONDOWN:
6056 button = 0;
6057 up = 0;
6058 break;
6059 case WM_LBUTTONUP:
6060 button = 0;
6061 up = 1;
6062 break;
6063 case WM_MBUTTONDOWN:
fbd6baed 6064 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
6065 button = 1;
6066 else
6067 button = 2;
ee78dc32
GV
6068 up = 0;
6069 break;
6070 case WM_MBUTTONUP:
fbd6baed 6071 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
6072 button = 1;
6073 else
6074 button = 2;
ee78dc32
GV
6075 up = 1;
6076 break;
6077 case WM_RBUTTONDOWN:
fbd6baed 6078 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
6079 button = 2;
6080 else
6081 button = 1;
ee78dc32
GV
6082 up = 0;
6083 break;
6084 case WM_RBUTTONUP:
fbd6baed 6085 if (NILP (Vw32_swap_mouse_buttons))
52cf03a1
GV
6086 button = 2;
6087 else
6088 button = 1;
ee78dc32
GV
6089 up = 1;
6090 break;
53823ab9
JR
6091 case WM_XBUTTONDOWN:
6092 button = xbutton + 2;
6093 up = 0;
6094 break;
6095 case WM_XBUTTONUP:
6096 button = xbutton + 2;
6097 up = 1;
6098 break;
ee78dc32
GV
6099 default:
6100 return (FALSE);
6101 }
6102
6103 if (pup) *pup = up;
6104 if (pbutton) *pbutton = button;
6105
6106 return (TRUE);
6107}
6108
6109
6110/* Prepare a mouse-event in *RESULT for placement in the input queue.
6111
6112 If the event is a button press, then note that we have grabbed
6113 the mouse. */
6114
ec48c3a7 6115static Lisp_Object
ee78dc32
GV
6116construct_mouse_click (result, msg, f)
6117 struct input_event *result;
fbd6baed 6118 W32Msg *msg;
ee78dc32
GV
6119 struct frame *f;
6120{
6121 int button;
6122 int up;
6123
53823ab9
JR
6124 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
6125 &button, &up);
ee78dc32
GV
6126
6127 /* Make the event type no_event; we'll change that when we decide
6128 otherwise. */
6129 result->kind = mouse_click;
6130 result->code = button;
6131 result->timestamp = msg->msg.time;
6132 result->modifiers = (msg->dwModifiers
6133 | (up
6134 ? up_modifier
6135 : down_modifier));
6136
ec48c3a7
JR
6137 XSETINT (result->x, LOWORD (msg->msg.lParam));
6138 XSETINT (result->y, HIWORD (msg->msg.lParam));
6139 XSETFRAME (result->frame_or_window, f);
6140 result->arg = Qnil;
6141 return Qnil;
ee78dc32
GV
6142}
6143
ec48c3a7 6144static Lisp_Object
689004fa
GV
6145construct_mouse_wheel (result, msg, f)
6146 struct input_event *result;
6147 W32Msg *msg;
6148 struct frame *f;
6149{
6150 POINT p;
6151 result->kind = mouse_wheel;
6152 result->code = (short) HIWORD (msg->msg.wParam);
6153 result->timestamp = msg->msg.time;
6154 result->modifiers = msg->dwModifiers;
6155 p.x = LOWORD (msg->msg.lParam);
6156 p.y = HIWORD (msg->msg.lParam);
9127e20e 6157 ScreenToClient (msg->msg.hwnd, &p);
689004fa
GV
6158 XSETINT (result->x, p.x);
6159 XSETINT (result->y, p.y);
6160 XSETFRAME (result->frame_or_window, f);
7e889510 6161 result->arg = Qnil;
ec48c3a7 6162 return Qnil;
689004fa
GV
6163}
6164
ec48c3a7 6165static Lisp_Object
12857dfd
RS
6166construct_drag_n_drop (result, msg, f)
6167 struct input_event *result;
6168 W32Msg *msg;
6169 struct frame *f;
6170{
6171 Lisp_Object files;
6172 Lisp_Object frame;
6173 HDROP hdrop;
6174 POINT p;
6175 WORD num_files;
6176 char *name;
6177 int i, len;
6178
6179 result->kind = drag_n_drop;
6180 result->code = 0;
6181 result->timestamp = msg->msg.time;
6182 result->modifiers = msg->dwModifiers;
6183
fb9cc9cc
AI
6184 hdrop = (HDROP) msg->msg.wParam;
6185 DragQueryPoint (hdrop, &p);
6186
e12ca9c2 6187#if 0
12857dfd
RS
6188 p.x = LOWORD (msg->msg.lParam);
6189 p.y = HIWORD (msg->msg.lParam);
6190 ScreenToClient (msg->msg.hwnd, &p);
e12ca9c2
AI
6191#endif
6192
12857dfd
RS
6193 XSETINT (result->x, p.x);
6194 XSETINT (result->y, p.y);
6195
12857dfd
RS
6196 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
6197 files = Qnil;
6198
6199 for (i = 0; i < num_files; i++)
6200 {
6201 len = DragQueryFile (hdrop, i, NULL, 0);
6202 if (len <= 0)
6203 continue;
6204 name = alloca (len + 1);
6205 DragQueryFile (hdrop, i, name, len + 1);
6206 files = Fcons (build_string (name), files);
6207 }
6208
6209 DragFinish (hdrop);
6210
6211 XSETFRAME (frame, f);
6212 result->frame_or_window = Fcons (frame, files);
7e889510 6213 result->arg = Qnil;
ec48c3a7 6214 return Qnil;
12857dfd
RS
6215}
6216
ee78dc32
GV
6217\f
6218/* Function to report a mouse movement to the mainstream Emacs code.
6219 The input handler calls this.
6220
6221 We have received a mouse movement event, which is given in *event.
6222 If the mouse is over a different glyph than it was last time, tell
6223 the mainstream emacs code by setting mouse_moved. If not, ask for
6224 another motion event, so we can check again the next time it moves. */
6225
791f420f
JR
6226static MSG last_mouse_motion_event;
6227static Lisp_Object last_mouse_motion_frame;
6228
9f5a911b
JR
6229static void remember_mouse_glyph P_ ((struct frame *, int, int));
6230
ee78dc32
GV
6231static void
6232note_mouse_movement (frame, msg)
6233 FRAME_PTR frame;
6234 MSG *msg;
6235{
9f5a911b
JR
6236 int mouse_x = LOWORD (msg->lParam);
6237 int mouse_y = HIWORD (msg->lParam);
6238
ee78dc32 6239 last_mouse_movement_time = msg->time;
791f420f
JR
6240 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
6241 XSETFRAME (last_mouse_motion_frame, frame);
ee78dc32 6242
fbd6baed 6243 if (msg->hwnd != FRAME_W32_WINDOW (frame))
ee78dc32
GV
6244 {
6245 frame->mouse_moved = 1;
6246 last_mouse_scroll_bar = Qnil;
ee78dc32
GV
6247 note_mouse_highlight (frame, -1, -1);
6248 }
6249
6250 /* Has the mouse moved off the glyph it was on at the last sighting? */
9f5a911b
JR
6251 else if (mouse_x < last_mouse_glyph.left
6252 || mouse_x > last_mouse_glyph.right
6253 || mouse_y < last_mouse_glyph.top
6254 || mouse_y > last_mouse_glyph.bottom)
ee78dc32
GV
6255 {
6256 frame->mouse_moved = 1;
6257 last_mouse_scroll_bar = Qnil;
9f5a911b
JR
6258 note_mouse_highlight (frame, mouse_x, mouse_y);
6259 /* Remember the mouse position here, as w32_mouse_position only
6260 gets called when mouse tracking is enabled but we also need
6261 to keep track of the mouse for help_echo and highlighting at
6262 other times. */
6263 remember_mouse_glyph (frame, mouse_x, mouse_y);
ee78dc32
GV
6264 }
6265}
6266
6267/* This is used for debugging, to turn off note_mouse_highlight. */
9ef2e2cf 6268
791f420f
JR
6269int disable_mouse_highlight;
6270
6271
6272\f
6273/************************************************************************
6274 Mouse Face
6275 ************************************************************************/
6276
6277/* Find the glyph under window-relative coordinates X/Y in window W.
6278 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6279 strings. Return in *HPOS and *VPOS the row and column number of
6280 the glyph found. Return in *AREA the glyph area containing X.
6281 Value is a pointer to the glyph found or null if X/Y is not on
6282 text, or we can't tell because W's current matrix is not up to
6283 date. */
6284
6285static struct glyph *
9f5a911b 6286x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
791f420f
JR
6287 struct window *w;
6288 int x, y;
6289 int *hpos, *vpos, *area;
9f5a911b 6290 int buffer_only_p;
791f420f
JR
6291{
6292 struct glyph *glyph, *end;
ec48c3a7 6293 struct glyph_row *row = NULL;
791f420f
JR
6294 int x0, i, left_area_width;
6295
6296 /* Find row containing Y. Give up if some row is not enabled. */
6297 for (i = 0; i < w->current_matrix->nrows; ++i)
6298 {
6299 row = MATRIX_ROW (w->current_matrix, i);
6300 if (!row->enabled_p)
6301 return NULL;
6302 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6303 break;
6304 }
6305
6306 *vpos = i;
6307 *hpos = 0;
6308
6309 /* Give up if Y is not in the window. */
6310 if (i == w->current_matrix->nrows)
6311 return NULL;
6312
6313 /* Get the glyph area containing X. */
6314 if (w->pseudo_window_p)
6315 {
6316 *area = TEXT_AREA;
6317 x0 = 0;
6318 }
6319 else
6320 {
6321 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6322 if (x < left_area_width)
6323 {
6324 *area = LEFT_MARGIN_AREA;
6325 x0 = 0;
6326 }
6327 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6328 {
6329 *area = TEXT_AREA;
6330 x0 = row->x + left_area_width;
6331 }
6332 else
6333 {
6334 *area = RIGHT_MARGIN_AREA;
6335 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6336 }
6337 }
6338
6339 /* Find glyph containing X. */
6340 glyph = row->glyphs[*area];
6341 end = glyph + row->used[*area];
6342 while (glyph < end)
6343 {
6344 if (x < x0 + glyph->pixel_width)
6345 {
6346 if (w->pseudo_window_p)
6347 break;
9f5a911b 6348 else if (!buffer_only_p || BUFFERP (glyph->object))
791f420f
JR
6349 break;
6350 }
6351
6352 x0 += glyph->pixel_width;
6353 ++glyph;
6354 }
6355
6356 if (glyph == end)
6357 return NULL;
6358
6359 *hpos = glyph - row->glyphs[*area];
6360 return glyph;
6361}
6362
6363
6364/* Convert frame-relative x/y to coordinates relative to window W.
6365 Takes pseudo-windows into account. */
6366
6367static void
6368frame_to_window_pixel_xy (w, x, y)
6369 struct window *w;
6370 int *x, *y;
6371{
6372 if (w->pseudo_window_p)
6373 {
6374 /* A pseudo-window is always full-width, and starts at the
6375 left edge of the frame, plus a frame border. */
6376 struct frame *f = XFRAME (w->frame);
6377 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6378 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6379 }
6380 else
6381 {
6382 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6383 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6384 }
6385}
6386
6387
c2cc16fa 6388/* Take proper action when mouse has moved to the mode or header line of
791f420f
JR
6389 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6390 mode line. X is relative to the start of the text display area of
33c34bea 6391 W, so the width of fringes and scroll bars must be subtracted
791f420f
JR
6392 to get a position relative to the start of the mode line. */
6393
6394static void
6395note_mode_line_highlight (w, x, mode_line_p)
6396 struct window *w;
6397 int x, mode_line_p;
6398{
6399 struct frame *f = XFRAME (w->frame);
6400 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6401 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6402 struct glyph_row *row;
6403
6404 if (mode_line_p)
6405 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6406 else
6407 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6408
6409 if (row->enabled_p)
6410 {
6411 struct glyph *glyph, *end;
6412 Lisp_Object help, map;
6413 int x0;
6414
6415 /* Find the glyph under X. */
6416 glyph = row->glyphs[TEXT_AREA];
6417 end = glyph + row->used[TEXT_AREA];
6418 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
33c34bea 6419 + FRAME_X_LEFT_FRINGE_WIDTH (f));
c2cc16fa 6420
791f420f
JR
6421 while (glyph < end
6422 && x >= x0 + glyph->pixel_width)
6423 {
6424 x0 += glyph->pixel_width;
6425 ++glyph;
6426 }
6427
6428 if (glyph < end
6429 && STRINGP (glyph->object)
6430 && XSTRING (glyph->object)->intervals
6431 && glyph->charpos >= 0
6432 && glyph->charpos < XSTRING (glyph->object)->size)
6433 {
6434 /* If we're on a string with `help-echo' text property,
6435 arrange for the help to be displayed. This is done by
6436 setting the global variable help_echo to the help string. */
6437 help = Fget_text_property (make_number (glyph->charpos),
6438 Qhelp_echo, glyph->object);
b7e80413 6439 if (!NILP (help))
ec48c3a7
JR
6440 {
6441 help_echo = help;
158cba56 6442 XSETWINDOW (help_echo_window, w);
ec48c3a7
JR
6443 help_echo_object = glyph->object;
6444 help_echo_pos = glyph->charpos;
6445 }
791f420f
JR
6446
6447 /* Change the mouse pointer according to what is under X/Y. */
6448 map = Fget_text_property (make_number (glyph->charpos),
6449 Qlocal_map, glyph->object);
02067692 6450 if (KEYMAPP (map))
791f420f 6451 cursor = f->output_data.w32->nontext_cursor;
c2cc16fa
JR
6452 else
6453 {
6454 map = Fget_text_property (make_number (glyph->charpos),
6455 Qkeymap, glyph->object);
6456 if (KEYMAPP (map))
6457 cursor = f->output_data.w32->nontext_cursor;
6458 }
791f420f
JR
6459 }
6460 }
9ef2e2cf 6461
01b220b6 6462#if 0 /* TODO: mouse cursor */
791f420f
JR
6463 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6464#endif
6465}
ee78dc32 6466
9ef2e2cf
JR
6467
6468/* Take proper action when the mouse has moved to position X, Y on
6469 frame F as regards highlighting characters that have mouse-face
6470 properties. Also de-highlighting chars where the mouse was before.
ee78dc32
GV
6471 X and Y can be negative or out of range. */
6472
6473static void
6474note_mouse_highlight (f, x, y)
9ef2e2cf 6475 struct frame *f;
ee78dc32
GV
6476 int x, y;
6477{
791f420f
JR
6478 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6479 int portion;
ee78dc32
GV
6480 Lisp_Object window;
6481 struct window *w;
9f5a911b 6482 struct buffer *b;
ee78dc32 6483
791f420f
JR
6484 /* When a menu is active, don't highlight because this looks odd. */
6485 if (popup_activated ())
6486 return;
6487
9ef2e2cf
JR
6488 if (disable_mouse_highlight
6489 || !f->glyphs_initialized_p)
ee78dc32
GV
6490 return;
6491
791f420f
JR
6492 dpyinfo->mouse_face_mouse_x = x;
6493 dpyinfo->mouse_face_mouse_y = y;
6494 dpyinfo->mouse_face_mouse_frame = f;
ee78dc32 6495
791f420f 6496 if (dpyinfo->mouse_face_defer)
ee78dc32
GV
6497 return;
6498
6499 if (gc_in_progress)
6500 {
791f420f 6501 dpyinfo->mouse_face_deferred_gc = 1;
ee78dc32
GV
6502 return;
6503 }
6504
ee78dc32 6505 /* Which window is that in? */
791f420f 6506 window = window_from_coordinates (f, x, y, &portion, 1);
ee78dc32
GV
6507
6508 /* If we were displaying active text in another window, clear that. */
791f420f
JR
6509 if (! EQ (window, dpyinfo->mouse_face_window))
6510 clear_mouse_face (dpyinfo);
6511
6512 /* Not on a window -> return. */
6513 if (!WINDOWP (window))
6514 return;
6515
abb15ebd
JR
6516 /* Reset help_echo. It will get recomputed below. */
6517 help_echo = Qnil;
6518
791f420f
JR
6519 /* Convert to window-relative pixel coordinates. */
6520 w = XWINDOW (window);
6521 frame_to_window_pixel_xy (w, &x, &y);
6522
6523 /* Handle tool-bar window differently since it doesn't display a
6524 buffer. */
6525 if (EQ (window, f->tool_bar_window))
6526 {
6527 note_tool_bar_highlight (f, x, y);
6528 return;
6529 }
6530
9f5a911b 6531 /* Mouse is on the mode or header line? */
791f420f
JR
6532 if (portion == 1 || portion == 3)
6533 {
791f420f
JR
6534 note_mode_line_highlight (w, x, portion == 1);
6535 return;
6536 }
01b220b6 6537#if 0 /* TODO: mouse cursor */
9f5a911b
JR
6538 if (portion == 2)
6539 cursor = f->output_data.x->horizontal_drag_cursor;
791f420f 6540 else
9f5a911b 6541 cursor = f->output_data.x->text_cursor;
791f420f 6542#endif
ee78dc32
GV
6543 /* Are we in a window whose display is up to date?
6544 And verify the buffer's text has not changed. */
9f5a911b 6545 b = XBUFFER (w->buffer);
9ef2e2cf 6546 if (/* Within text portion of the window. */
791f420f 6547 portion == 0
ee78dc32 6548 && EQ (w->window_end_valid, w->buffer)
9f5a911b
JR
6549 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6550 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
ee78dc32 6551 {
791f420f
JR
6552 int hpos, vpos, pos, i, area;
6553 struct glyph *glyph;
9f5a911b
JR
6554 Lisp_Object object;
6555 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6556 Lisp_Object *overlay_vec = NULL;
6557 int len, noverlays;
6558 struct buffer *obuf;
6559 int obegv, ozv, same_region;
791f420f
JR
6560
6561 /* Find the glyph under X/Y. */
9f5a911b 6562 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
791f420f
JR
6563
6564 /* Clear mouse face if X/Y not over text. */
6565 if (glyph == NULL
6566 || area != TEXT_AREA
6567 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6568 {
6569 clear_mouse_face (dpyinfo);
9f5a911b
JR
6570 /* TODO: mouse cursor */
6571 goto set_cursor;
791f420f
JR
6572 }
6573
6574 pos = glyph->charpos;
9f5a911b
JR
6575 object = glyph->object;
6576 if (!STRINGP (object) && !BUFFERP (object))
6577 goto set_cursor;
6578
6579 /* If we get an out-of-range value, return now; avoid an error. */
6580 if (BUFFERP (object) && pos > BUF_Z (b))
6581 goto set_cursor;
6582
6583 /* Make the window's buffer temporarily current for
6584 overlays_at and compute_char_face. */
6585 obuf = current_buffer;
6586 current_buffer = b;
6587 obegv = BEGV;
6588 ozv = ZV;
6589 BEGV = BEG;
6590 ZV = Z;
6591
6592 /* Is this char mouse-active or does it have help-echo? */
6593 position = make_number (pos);
6594
6595 if (BUFFERP (object))
6596 {
6597 /* Put all the overlays we want in a vector in overlay_vec.
6598 Store the length in len. If there are more than 10, make
6599 enough space for all, and try again. */
6600 len = 10;
6601 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6602 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6603 if (noverlays > len)
6604 {
6605 len = noverlays;
6606 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6607 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6608 }
6609
6610 /* Sort overlays into increasing priority order. */
6611 noverlays = sort_overlays (overlay_vec, noverlays, w);
6612 }
6613 else
6614 noverlays = 0;
6615
6616 same_region = (EQ (window, dpyinfo->mouse_face_window)
6617 && vpos >= dpyinfo->mouse_face_beg_row
6618 && vpos <= dpyinfo->mouse_face_end_row
6619 && (vpos > dpyinfo->mouse_face_beg_row
6620 || hpos >= dpyinfo->mouse_face_beg_col)
6621 && (vpos < dpyinfo->mouse_face_end_row
6622 || hpos < dpyinfo->mouse_face_end_col
6623 || dpyinfo->mouse_face_past_end));
6624
6625 /* TODO: if (same_region)
6626 mouse cursor */
6627
6628 /* Check mouse-face highlighting. */
6629 if (! same_region
6630 /* If there exists an overlay with mouse-face overlapping
6631 the one we are currently highlighting, we have to
6632 check if we enter the overlapping overlay, and then
6633 highlight that. */
6634 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6635 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6636 {
6637 /* Find the highest priority overlay that has a mouse-face
6638 property. */
6639 overlay = Qnil;
6640 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6641 {
6642 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6643 if (!NILP (mouse_face))
6644 overlay = overlay_vec[i];
6645 }
791f420f 6646
9f5a911b
JR
6647 /* If we're actually highlighting the same overlay as
6648 before, there's no need to do that again. */
6649 if (!NILP (overlay)
6650 && EQ (overlay, dpyinfo->mouse_face_overlay))
6651 goto check_help_echo;
6652
6653 dpyinfo->mouse_face_overlay = overlay;
6654
6655 /* Clear the display of the old active region, if any. */
6656 clear_mouse_face (dpyinfo);
6657 /* TODO: mouse cursor changes. */
6658
6659 /* If no overlay applies, get a text property. */
6660 if (NILP (overlay))
6661 mouse_face = Fget_text_property (position, Qmouse_face, object);
6662
6663 /* Handle the overlay case. */
6664 if (!NILP (overlay))
6665 {
6666 /* Find the range of text around this char that
6667 should be active. */
6668 Lisp_Object before, after;
6669 int ignore;
6670
6671 before = Foverlay_start (overlay);
6672 after = Foverlay_end (overlay);
6673 /* Record this as the current active region. */
6674 fast_find_position (w, XFASTINT (before),
6675 &dpyinfo->mouse_face_beg_col,
6676 &dpyinfo->mouse_face_beg_row,
6677 &dpyinfo->mouse_face_beg_x,
6678 &dpyinfo->mouse_face_beg_y, Qnil);
6679
6680 dpyinfo->mouse_face_past_end
6681 = !fast_find_position (w, XFASTINT (after),
6682 &dpyinfo->mouse_face_end_col,
6683 &dpyinfo->mouse_face_end_row,
6684 &dpyinfo->mouse_face_end_x,
6685 &dpyinfo->mouse_face_end_y, Qnil);
6686 dpyinfo->mouse_face_window = window;
6687
6688 dpyinfo->mouse_face_face_id
6689 = face_at_buffer_position (w, pos, 0, 0,
6690 &ignore, pos + 1, 1);
6691
6692 /* Display it as active. */
6693 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6694 /* TODO: mouse cursor changes. */
6695 }
6696 /* Handle the text property case. */
6697 else if (! NILP (mouse_face) && BUFFERP (object))
6698 {
6699 /* Find the range of text around this char that
6700 should be active. */
6701 Lisp_Object before, after, beginning, end;
6702 int ignore;
6703
6704 beginning = Fmarker_position (w->start);
6705 end = make_number (BUF_Z (XBUFFER (object))
6706 - XFASTINT (w->window_end_pos));
6707 before
6708 = Fprevious_single_property_change (make_number (pos + 1),
6709 Qmouse_face,
6710 object, beginning);
6711 after
6712 = Fnext_single_property_change (position, Qmouse_face,
6713 object, end);
6714
6715 /* Record this as the current active region. */
6716 fast_find_position (w, XFASTINT (before),
6717 &dpyinfo->mouse_face_beg_col,
6718 &dpyinfo->mouse_face_beg_row,
6719 &dpyinfo->mouse_face_beg_x,
6720 &dpyinfo->mouse_face_beg_y, Qnil);
6721 dpyinfo->mouse_face_past_end
6722 = !fast_find_position (w, XFASTINT (after),
6723 &dpyinfo->mouse_face_end_col,
6724 &dpyinfo->mouse_face_end_row,
6725 &dpyinfo->mouse_face_end_x,
6726 &dpyinfo->mouse_face_end_y, Qnil);
6727 dpyinfo->mouse_face_window = window;
6728
6729 if (BUFFERP (object))
6730 dpyinfo->mouse_face_face_id
6731 = face_at_buffer_position (w, pos, 0, 0,
6732 &ignore, pos + 1, 1);
6733
6734 /* Display it as active. */
6735 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6736 /* TODO: mouse cursor changes. */
6737 }
6738 else if (!NILP (mouse_face) && STRINGP (object))
6739 {
6740 Lisp_Object b, e;
6741 int ignore;
6742
6743 b = Fprevious_single_property_change (make_number (pos + 1),
6744 Qmouse_face,
6745 object, Qnil);
6746 e = Fnext_single_property_change (position, Qmouse_face,
6747 object, Qnil);
6748 if (NILP (b))
6749 b = make_number (0);
6750 if (NILP (e))
6751 e = make_number (XSTRING (object)->size - 1);
6752 fast_find_string_pos (w, XINT (b), object,
6753 &dpyinfo->mouse_face_beg_col,
6754 &dpyinfo->mouse_face_beg_row,
6755 &dpyinfo->mouse_face_beg_x,
6756 &dpyinfo->mouse_face_beg_y, 0);
6757 fast_find_string_pos (w, XINT (e), object,
6758 &dpyinfo->mouse_face_end_col,
6759 &dpyinfo->mouse_face_end_row,
6760 &dpyinfo->mouse_face_end_x,
6761 &dpyinfo->mouse_face_end_y, 1);
6762 dpyinfo->mouse_face_past_end = 0;
6763 dpyinfo->mouse_face_window = window;
6764 dpyinfo->mouse_face_face_id
6765 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6766 glyph->face_id, 1);
6767 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6768 /* TODO: mouse cursor changes. */
6769 }
6770 else if (STRINGP (object) && NILP (mouse_face))
6771 {
6772 /* A string which doesn't have mouse-face, but
6773 the text ``under'' it might have. */
6774 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
6775 int start = MATRIX_ROW_START_CHARPOS (r);
6776
6777 pos = string_buffer_position (w, object, start);
6778 if (pos > 0)
6779 mouse_face = get_char_property_and_overlay (make_number (pos),
6780 Qmouse_face,
6781 w->buffer,
6782 &overlay);
6783 if (!NILP (mouse_face) && !NILP (overlay))
6784 {
6785 Lisp_Object before = Foverlay_start (overlay);
6786 Lisp_Object after = Foverlay_end (overlay);
6ff3e5e3 6787 int ignore;
9f5a911b
JR
6788
6789 /* Note that we might not be able to find position
6790 BEFORE in the glyph matrix if the overlay is
6791 entirely covered by a `display' property. In
6792 this case, we overshoot. So let's stop in
6793 the glyph matrix before glyphs for OBJECT. */
6794 fast_find_position (w, XFASTINT (before),
6795 &dpyinfo->mouse_face_beg_col,
6796 &dpyinfo->mouse_face_beg_row,
6797 &dpyinfo->mouse_face_beg_x,
6798 &dpyinfo->mouse_face_beg_y,
6799 object);
6800
6801 dpyinfo->mouse_face_past_end
6802 = !fast_find_position (w, XFASTINT (after),
6803 &dpyinfo->mouse_face_end_col,
6804 &dpyinfo->mouse_face_end_row,
6805 &dpyinfo->mouse_face_end_x,
6806 &dpyinfo->mouse_face_end_y,
6807 Qnil);
6808 dpyinfo->mouse_face_window = window;
6809 dpyinfo->mouse_face_face_id
6810 = face_at_buffer_position (w, pos, 0, 0,
6811 &ignore, pos + 1, 1);
6812
6813 /* Display it as active. */
6814 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6815 /* TODO: mouse cursor changes. */
6816 }
6817 }
6818 }
6819
6820 check_help_echo:
6821
6822 /* Look for a `help-echo' property. */
791f420f 6823 {
9f5a911b
JR
6824 Lisp_Object help, overlay;
6825
6826 /* Check overlays first. */
6827 help = overlay = Qnil;
6828 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
791f420f 6829 {
9f5a911b
JR
6830 overlay = overlay_vec[i];
6831 help = Foverlay_get (overlay, Qhelp_echo);
791f420f
JR
6832 }
6833
9f5a911b 6834 if (!NILP (help))
791f420f 6835 {
9f5a911b
JR
6836 help_echo = help;
6837 help_echo_window = window;
6838 help_echo_object = overlay;
6839 help_echo_pos = pos;
6840 }
6841 else
6842 {
6843 Lisp_Object object = glyph->object;
6844 int charpos = glyph->charpos;
ec48c3a7 6845
9f5a911b
JR
6846 /* Try text properties. */
6847 if (STRINGP (object)
6848 && charpos >= 0
6849 && charpos < XSTRING (object)->size)
6850 {
6851 help = Fget_text_property (make_number (charpos),
6852 Qhelp_echo, object);
6853 if (NILP (help))
6854 {
6855 /* If the string itself doesn't specify a help-echo,
6856 see if the buffer text ``under'' it does. */
6857 struct glyph_row *r
6858 = MATRIX_ROW (w->current_matrix, vpos);
6859 int start = MATRIX_ROW_START_CHARPOS (r);
6860 int pos = string_buffer_position (w, object, start);
6861 if (pos > 0)
6862 {
6863 help = Fget_char_property (make_number (pos),
6864 Qhelp_echo, w->buffer);
6865 if (!NILP (help))
6866 {
6867 charpos = pos;
6868 object = w->buffer;
6869 }
6870 }
6871 }
6872 }
6873 else if (BUFFERP (object)
6874 && charpos >= BEGV
6875 && charpos < ZV)
6876 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6877 object);
791f420f 6878
9f5a911b
JR
6879 if (!NILP (help))
6880 {
6881 help_echo = help;
6882 help_echo_window = window;
6883 help_echo_object = object;
6884 help_echo_pos = charpos;
6885 }
6886 }
791f420f 6887 }
9f5a911b
JR
6888
6889 BEGV = obegv;
6890 ZV = ozv;
6891 current_buffer = obuf;
791f420f 6892 }
9f5a911b
JR
6893
6894 set_cursor:
6895 /* TODO: mouse cursor changes. */
6896 ;
791f420f
JR
6897}
6898
791f420f
JR
6899static void
6900redo_mouse_highlight ()
6901{
6902 if (!NILP (last_mouse_motion_frame)
6903 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6904 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6905 LOWORD (last_mouse_motion_event.lParam),
6906 HIWORD (last_mouse_motion_event.lParam));
6907}
6908
6909
6910\f
6911/***********************************************************************
6912 Tool-bars
6913 ***********************************************************************/
6914
6915static int x_tool_bar_item P_ ((struct frame *, int, int,
6916 struct glyph **, int *, int *, int *));
6917
6918/* Tool-bar item index of the item on which a mouse button was pressed
6919 or -1. */
6920
6921static int last_tool_bar_item;
6922
6923
6924/* Get information about the tool-bar item at position X/Y on frame F.
6925 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6926 the current matrix of the tool-bar window of F, or NULL if not
6927 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
d417b5e0 6928 item in F->tool_bar_items. Value is
791f420f
JR
6929
6930 -1 if X/Y is not on a tool-bar item
6931 0 if X/Y is on the same item that was highlighted before.
6932 1 otherwise. */
6933
6934static int
6935x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6936 struct frame *f;
6937 int x, y;
6938 struct glyph **glyph;
6939 int *hpos, *vpos, *prop_idx;
6940{
6941 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6942 struct window *w = XWINDOW (f->tool_bar_window);
6943 int area;
6944
6945 /* Find the glyph under X/Y. */
9f5a911b 6946 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
791f420f
JR
6947 if (*glyph == NULL)
6948 return -1;
6949
6950 /* Get the start of this tool-bar item's properties in
d417b5e0 6951 f->tool_bar_items. */
791f420f
JR
6952 if (!tool_bar_item_info (f, *glyph, prop_idx))
6953 return -1;
6954
6955 /* Is mouse on the highlighted item? */
6956 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6957 && *vpos >= dpyinfo->mouse_face_beg_row
6958 && *vpos <= dpyinfo->mouse_face_end_row
6959 && (*vpos > dpyinfo->mouse_face_beg_row
6960 || *hpos >= dpyinfo->mouse_face_beg_col)
6961 && (*vpos < dpyinfo->mouse_face_end_row
6962 || *hpos < dpyinfo->mouse_face_end_col
6963 || dpyinfo->mouse_face_past_end))
6964 return 0;
6965
6966 return 1;
6967}
6968
6969
9ef2e2cf 6970/* Handle mouse button event on the tool-bar of frame F, at
791f420f
JR
6971 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6972 or ButtonRelase. */
6973
6974static void
6975w32_handle_tool_bar_click (f, button_event)
6976 struct frame *f;
6977 struct input_event *button_event;
6978{
6979 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6980 struct window *w = XWINDOW (f->tool_bar_window);
6981 int hpos, vpos, prop_idx;
6982 struct glyph *glyph;
6983 Lisp_Object enabled_p;
6984 int x = XFASTINT (button_event->x);
6985 int y = XFASTINT (button_event->y);
6986
6987 /* If not on the highlighted tool-bar item, return. */
6988 frame_to_window_pixel_xy (w, &x, &y);
6989 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6990 return;
6991
6992 /* If item is disabled, do nothing. */
d417b5e0 6993 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
791f420f
JR
6994 if (NILP (enabled_p))
6995 return;
6996
6997 if (button_event->kind == mouse_click)
6998 {
6999 /* Show item in pressed state. */
7000 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7001 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7002 last_tool_bar_item = prop_idx;
7003 }
7004 else
7005 {
7006 Lisp_Object key, frame;
7007 struct input_event event;
7008
7009 /* Show item in released state. */
7010 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7011 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7012
d417b5e0 7013 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
791f420f
JR
7014
7015 XSETFRAME (frame, f);
7016 event.kind = TOOL_BAR_EVENT;
c8b33aa6
GM
7017 event.frame_or_window = frame;
7018 event.arg = frame;
791f420f
JR
7019 kbd_buffer_store_event (&event);
7020
7021 event.kind = TOOL_BAR_EVENT;
c8b33aa6
GM
7022 event.frame_or_window = frame;
7023 event.arg = key;
791f420f
JR
7024 event.modifiers = button_event->modifiers;
7025 kbd_buffer_store_event (&event);
7026 last_tool_bar_item = -1;
7027 }
7028}
7029
7030
9ef2e2cf 7031/* Possibly highlight a tool-bar item on frame F when mouse moves to
791f420f
JR
7032 tool-bar window-relative coordinates X/Y. Called from
7033 note_mouse_highlight. */
7034
7035static void
7036note_tool_bar_highlight (f, x, y)
7037 struct frame *f;
7038 int x, y;
7039{
7040 Lisp_Object window = f->tool_bar_window;
7041 struct window *w = XWINDOW (window);
7042 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7043 int hpos, vpos;
7044 struct glyph *glyph;
7045 struct glyph_row *row;
7046 int i;
7047 Lisp_Object enabled_p;
7048 int prop_idx;
7049 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7050 int mouse_down_p, rc;
7051
7052 /* Function note_mouse_highlight is called with negative x(y
7053 values when mouse moves outside of the frame. */
7054 if (x <= 0 || y <= 0)
7055 {
7056 clear_mouse_face (dpyinfo);
7057 return;
7058 }
7059
7060 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7061 if (rc < 0)
7062 {
7063 /* Not on tool-bar item. */
7064 clear_mouse_face (dpyinfo);
7065 return;
7066 }
7067 else if (rc == 0)
7068 /* On same tool-bar item as before. */
7069 goto set_help_echo;
ee78dc32 7070
791f420f
JR
7071 clear_mouse_face (dpyinfo);
7072
7073 /* Mouse is down, but on different tool-bar item? */
7074 mouse_down_p = (dpyinfo->grabbed
7075 && f == last_mouse_frame
7076 && FRAME_LIVE_P (f));
7077 if (mouse_down_p
7078 && last_tool_bar_item != prop_idx)
7079 return;
ee78dc32 7080
791f420f
JR
7081 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7082 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7083
7084 /* If tool-bar item is not enabled, don't highlight it. */
d417b5e0 7085 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
791f420f
JR
7086 if (!NILP (enabled_p))
7087 {
7088 /* Compute the x-position of the glyph. In front and past the
7089 image is a space. We include this is the highlighted area. */
7090 row = MATRIX_ROW (w->current_matrix, vpos);
7091 for (i = x = 0; i < hpos; ++i)
7092 x += row->glyphs[TEXT_AREA][i].pixel_width;
7093
7094 /* Record this as the current active region. */
7095 dpyinfo->mouse_face_beg_col = hpos;
7096 dpyinfo->mouse_face_beg_row = vpos;
7097 dpyinfo->mouse_face_beg_x = x;
7098 dpyinfo->mouse_face_beg_y = row->y;
7099 dpyinfo->mouse_face_past_end = 0;
7100
7101 dpyinfo->mouse_face_end_col = hpos + 1;
7102 dpyinfo->mouse_face_end_row = vpos;
7103 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7104 dpyinfo->mouse_face_end_y = row->y;
7105 dpyinfo->mouse_face_window = window;
7106 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7107
7108 /* Display it as active. */
7109 show_mouse_face (dpyinfo, draw);
7110 dpyinfo->mouse_face_image_state = draw;
ee78dc32 7111 }
791f420f
JR
7112
7113 set_help_echo:
7114
7115 /* Set help_echo to a help string.to display for this tool-bar item.
7116 w32_read_socket does the rest. */
158cba56 7117 help_echo_object = help_echo_window = Qnil;
ec48c3a7 7118 help_echo_pos = -1;
d417b5e0 7119 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
b7e80413 7120 if (NILP (help_echo))
d417b5e0 7121 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
ee78dc32 7122}
ee78dc32 7123
9ef2e2cf 7124
791f420f 7125\f
9f5a911b
JR
7126/* Find the glyph matrix position of buffer position CHARPOS in window
7127 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7128 current glyphs must be up to date. If CHARPOS is above window
7129 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7130 of last line in W. In the row containing CHARPOS, stop before glyphs
7131 having STOP as object. */
7132
7133#if 0 /* This is a version of fast_find_position that's more correct
7134 in the presence of hscrolling, for example. I didn't install
7135 it right away because the problem fixed is minor, it failed
7136 in 20.x as well, and I think it's too risky to install
7137 so near the release of 21.1. 2001-09-25 gerd. */
ee78dc32
GV
7138
7139static int
9f5a911b
JR
7140fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7141 struct window *w;
7142 int charpos;
7143 int *hpos, *vpos, *x, *y;
7144 Lisp_Object stop;
7145{
7146 struct glyph_row *row, *first;
7147 struct glyph *glyph, *end;
7148 int i, past_end = 0;
7149
7150 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
62e33982 7151 row = row_containing_pos (w, charpos, first, NULL, 0);
9f5a911b
JR
7152 if (row == NULL)
7153 {
7154 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7155 {
7156 *x = *y = *hpos = *vpos = 0;
7157 return 0;
7158 }
7159 else
7160 {
7161 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7162 past_end = 1;
7163 }
7164 }
7165
7166 *x = row->x;
7167 *y = row->y;
7168 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7169
7170 glyph = row->glyphs[TEXT_AREA];
7171 end = glyph + row->used[TEXT_AREA];
7172
7173 /* Skip over glyphs not having an object at the start of the row.
7174 These are special glyphs like truncation marks on terminal
7175 frames. */
7176 if (row->displays_text_p)
7177 while (glyph < end
7178 && INTEGERP (glyph->object)
7179 && !EQ (stop, glyph->object)
7180 && glyph->charpos < 0)
7181 {
7182 *x += glyph->pixel_width;
7183 ++glyph;
7184 }
7185
7186 while (glyph < end
7187 && !INTEGERP (glyph->object)
7188 && !EQ (stop, glyph->object)
7189 && (!BUFFERP (glyph->object)
7190 || glyph->charpos < charpos))
7191 {
7192 *x += glyph->pixel_width;
7193 ++glyph;
7194 }
7195
7196 *hpos = glyph - row->glyphs[TEXT_AREA];
7197 return past_end;
7198}
7199
7200#else /* not 0 */
7201
7202static int
7203fast_find_position (w, pos, hpos, vpos, x, y, stop)
791f420f 7204 struct window *w;
ee78dc32 7205 int pos;
791f420f 7206 int *hpos, *vpos, *x, *y;
9f5a911b 7207 Lisp_Object stop;
ee78dc32 7208{
ee78dc32 7209 int i;
ee78dc32 7210 int lastcol;
791f420f
JR
7211 int maybe_next_line_p = 0;
7212 int line_start_position;
7213 int yb = window_text_bottom_y (w);
9f5a911b
JR
7214 struct glyph_row *row, *best_row;
7215 int row_vpos, best_row_vpos;
791f420f
JR
7216 int current_x;
7217
9f5a911b
JR
7218 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7219 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7220
791f420f 7221 while (row->y < yb)
ee78dc32 7222 {
791f420f
JR
7223 if (row->used[TEXT_AREA])
7224 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7225 else
7226 line_start_position = 0;
7227
7228 if (line_start_position > pos)
ee78dc32
GV
7229 break;
7230 /* If the position sought is the end of the buffer,
7231 don't include the blank lines at the bottom of the window. */
791f420f
JR
7232 else if (line_start_position == pos
7233 && pos == BUF_ZV (XBUFFER (w->buffer)))
ee78dc32 7234 {
791f420f 7235 maybe_next_line_p = 1;
ee78dc32
GV
7236 break;
7237 }
791f420f
JR
7238 else if (line_start_position > 0)
7239 {
7240 best_row = row;
7241 best_row_vpos = row_vpos;
7242 }
7243
9ef2e2cf
JR
7244 if (row->y + row->height >= yb)
7245 break;
7246
791f420f
JR
7247 ++row;
7248 ++row_vpos;
ee78dc32
GV
7249 }
7250
791f420f
JR
7251 /* Find the right column within BEST_ROW. */
7252 lastcol = 0;
7253 current_x = best_row->x;
7254 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
ee78dc32 7255 {
791f420f 7256 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
9f5a911b 7257 int charpos = glyph->charpos;
791f420f 7258
9f5a911b 7259 if (BUFFERP (glyph->object))
ee78dc32 7260 {
9f5a911b
JR
7261 if (charpos == pos)
7262 {
7263 *hpos = i;
7264 *vpos = best_row_vpos;
7265 *x = current_x;
7266 *y = best_row->y;
7267 return 1;
7268 }
7269 else if (charpos > pos)
7270 break;
ee78dc32 7271 }
9f5a911b 7272 else if (EQ (glyph->object, stop))
ee78dc32 7273 break;
791f420f 7274
9f5a911b
JR
7275 if (charpos > 0)
7276 lastcol = i;
791f420f 7277 current_x += glyph->pixel_width;
ee78dc32
GV
7278 }
7279
7280 /* If we're looking for the end of the buffer,
7281 and we didn't find it in the line we scanned,
7282 use the start of the following line. */
791f420f 7283 if (maybe_next_line_p)
ee78dc32 7284 {
791f420f
JR
7285 ++best_row;
7286 ++best_row_vpos;
7287 lastcol = 0;
7288 current_x = best_row->x;
ee78dc32
GV
7289 }
7290
791f420f
JR
7291 *vpos = best_row_vpos;
7292 *hpos = lastcol + 1;
7293 *x = current_x;
7294 *y = best_row->y;
ee78dc32
GV
7295 return 0;
7296}
7297
9f5a911b
JR
7298#endif /* not 0 */
7299
7300
269b7745 7301/* Find the position of the glyph for position POS in OBJECT in
9f5a911b
JR
7302 window W's current matrix, and return in *X/*Y the pixel
7303 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7304
7305 RIGHT_P non-zero means return the position of the right edge of the
7306 glyph, RIGHT_P zero means return the left edge position.
7307
7308 If no glyph for POS exists in the matrix, return the position of
7309 the glyph with the next smaller position that is in the matrix, if
7310 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7311 exists in the matrix, return the position of the glyph with the
7312 next larger position in OBJECT.
7313
7314 Value is non-zero if a glyph was found. */
7315
7316static int
7317fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7318 struct window *w;
7319 int pos;
7320 Lisp_Object object;
7321 int *hpos, *vpos, *x, *y;
7322 int right_p;
7323{
7324 int yb = window_text_bottom_y (w);
7325 struct glyph_row *r;
7326 struct glyph *best_glyph = NULL;
7327 struct glyph_row *best_row = NULL;
7328 int best_x = 0;
7329
7330 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7331 r->enabled_p && r->y < yb;
7332 ++r)
7333 {
7334 struct glyph *g = r->glyphs[TEXT_AREA];
7335 struct glyph *e = g + r->used[TEXT_AREA];
7336 int gx;
7337
7338 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7339 if (EQ (g->object, object))
7340 {
7341 if (g->charpos == pos)
7342 {
7343 best_glyph = g;
7344 best_x = gx;
7345 best_row = r;
7346 goto found;
7347 }
7348 else if (best_glyph == NULL
7349 || ((abs (g->charpos - pos)
7350 < abs (best_glyph->charpos - pos))
7351 && (right_p
7352 ? g->charpos < pos
7353 : g->charpos > pos)))
7354 {
7355 best_glyph = g;
7356 best_x = gx;
7357 best_row = r;
7358 }
7359 }
7360 }
7361
7362 found:
7363
7364 if (best_glyph)
7365 {
7366 *x = best_x;
7367 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7368
7369 if (right_p)
7370 {
7371 *x += best_glyph->pixel_width;
7372 ++*hpos;
7373 }
7374
7375 *y = best_row->y;
7376 *vpos = best_row - w->current_matrix->rows;
7377 }
7378
7379 return best_glyph != NULL;
7380}
7381
791f420f 7382
ee78dc32
GV
7383/* Display the active region described by mouse_face_*
7384 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7385
7386static void
791f420f 7387show_mouse_face (dpyinfo, draw)
fbd6baed 7388 struct w32_display_info *dpyinfo;
791f420f 7389 enum draw_glyphs_face draw;
ee78dc32
GV
7390{
7391 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
791f420f 7392 struct frame *f = XFRAME (WINDOW_FRAME (w));
791f420f 7393
6ff3e5e3
JR
7394 if (/* If window is in the process of being destroyed, don't bother
7395 to do anything. */
7396 w->current_matrix != NULL
7397 /* Recognize when we are called to operate on rows that don't exist
7398 anymore. This can happen when a window is split. */
7399 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7400 {
7401 int phys_cursor_on_p = w->phys_cursor_on_p;
7402 struct glyph_row *row, *first, *last;
7403
7404 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7405 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7406
7407 for (row = first; row <= last && row->enabled_p; ++row)
7408 {
7409 int start_hpos, end_hpos, start_x;
791f420f 7410
6ff3e5e3
JR
7411 /* For all but the first row, the highlight starts at column 0. */
7412 if (row == first)
7413 {
7414 start_hpos = dpyinfo->mouse_face_beg_col;
7415 start_x = dpyinfo->mouse_face_beg_x;
7416 }
7417 else
7418 {
7419 start_hpos = 0;
7420 start_x = 0;
7421 }
791f420f 7422
6ff3e5e3
JR
7423 if (row == last)
7424 end_hpos = dpyinfo->mouse_face_end_col;
7425 else
7426 end_hpos = row->used[TEXT_AREA];
791f420f 7427
6ff3e5e3
JR
7428 if (end_hpos > start_hpos)
7429 {
7430 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7431 start_hpos, end_hpos, draw, 0);
791f420f 7432
6637c996
JR
7433 row->mouse_face_p
7434 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
6ff3e5e3 7435 }
ee78dc32
GV
7436 }
7437
6ff3e5e3
JR
7438 /* When we've written over the cursor, arrange for it to
7439 be displayed again. */
7440 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7441 x_display_cursor (w, 1,
7442 w->phys_cursor.hpos, w->phys_cursor.vpos,
7443 w->phys_cursor.x, w->phys_cursor.y);
ee78dc32
GV
7444 }
7445
01b220b6 7446#if 0 /* TODO: mouse cursor */
791f420f
JR
7447 /* Change the mouse cursor. */
7448 if (draw == DRAW_NORMAL_TEXT)
7449 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7450 f->output_data.x->text_cursor);
7451 else if (draw == DRAW_MOUSE_FACE)
7452 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7453 f->output_data.x->cross_cursor);
ee78dc32 7454 else
791f420f
JR
7455 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7456 f->output_data.x->nontext_cursor);
7457#endif
ee78dc32
GV
7458}
7459
7460/* Clear out the mouse-highlighted active region.
9ef2e2cf 7461 Redraw it un-highlighted first. */
ee78dc32 7462
9f5a911b 7463static int
ee78dc32 7464clear_mouse_face (dpyinfo)
fbd6baed 7465 struct w32_display_info *dpyinfo;
ee78dc32 7466{
9f5a911b 7467 int cleared = 0;
791f420f 7468
ee78dc32 7469 if (! NILP (dpyinfo->mouse_face_window))
9f5a911b
JR
7470 {
7471 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7472 cleared = 1;
7473 }
ee78dc32
GV
7474
7475 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7476 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7477 dpyinfo->mouse_face_window = Qnil;
9f5a911b
JR
7478 dpyinfo->mouse_face_overlay = Qnil;
7479 return cleared;
ee78dc32 7480}
31d4844a 7481
ec48c3a7
JR
7482
7483/* Clear any mouse-face on window W. This function is part of the
7484 redisplay interface, and is called from try_window_id and similar
7485 functions to ensure the mouse-highlight is off. */
7486
7487static void
7488x_clear_mouse_face (w)
7489 struct window *w;
7490{
7491 struct w32_display_info *dpyinfo
7492 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
7493 Lisp_Object window;
7494
9127e20e 7495 BLOCK_INPUT;
ec48c3a7
JR
7496 XSETWINDOW (window, w);
7497 if (EQ (window, dpyinfo->mouse_face_window))
7498 clear_mouse_face (dpyinfo);
9127e20e 7499 UNBLOCK_INPUT;
ec48c3a7
JR
7500}
7501
7502
31d4844a
KH
7503/* Just discard the mouse face information for frame F, if any.
7504 This is used when the size of F is changed. */
7505
7506void
7507cancel_mouse_face (f)
7508 FRAME_PTR f;
7509{
7510 Lisp_Object window;
7511 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7512
7513 window = dpyinfo->mouse_face_window;
7514 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7515 {
7516 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7517 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7518 dpyinfo->mouse_face_window = Qnil;
7519 }
7520}
ee78dc32 7521\f
9ef2e2cf 7522static struct scroll_bar *x_window_to_scroll_bar ();
ee78dc32 7523static void x_scroll_bar_report_motion ();
9f5a911b
JR
7524static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
7525
7526
7527/* Try to determine frame pixel position and size of the glyph under
7528 frame pixel coordinates X/Y on frame F . Return the position and
7529 size in *RECT. Value is non-zero if we could compute these
7530 values. */
7531
7532static int
7533glyph_rect (f, x, y, rect)
7534 struct frame *f;
7535 int x, y;
7536 RECT *rect;
7537{
7538 Lisp_Object window;
7539 int part, found = 0;
7540
7541 window = window_from_coordinates (f, x, y, &part, 0);
7542 if (!NILP (window))
7543 {
7544 struct window *w = XWINDOW (window);
7545 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7546 struct glyph_row *end = r + w->current_matrix->nrows - 1;
9f5a911b
JR
7547
7548 frame_to_window_pixel_xy (w, &x, &y);
7549
7550 for (; !found && r < end && r->enabled_p; ++r)
7551 if (r->y + r->height >= y)
7552 {
7553 struct glyph *g = r->glyphs[TEXT_AREA];
7554 struct glyph *end = g + r->used[TEXT_AREA];
7555 int gx;
7556
7557 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7558 if (gx + g->pixel_width >= x)
7559 {
7560 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7561 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7562 rect->right = rect->left + g->pixel_width;
7563 rect->bottom = rect->top + r->height;
7564 found = 1;
7565 }
7566 }
7567 }
7568
7569 return found;
7570}
7571
7572/* Record the position of the mouse in last_mouse_glyph. */
565153ff
JR
7573static void
7574remember_mouse_glyph (f1, gx, gy)
9f5a911b
JR
7575 struct frame * f1;
7576 int gx, gy;
7577{
7578 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
7579 {
7580 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7581 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7582
7583 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7584 round down even for negative values. */
7585 if (gx < 0)
7586 gx -= width - 1;
7587 if (gy < 0)
7588 gy -= height - 1;
7589#if 0
7590 /* This was the original code from XTmouse_position, but it seems
7591 to give the position of the glyph diagonally next to the one
7592 the mouse is over. */
7593 gx = (gx + width - 1) / width * width;
7594 gy = (gy + height - 1) / height * height;
7595#else
7596 gx = gx / width * width;
7597 gy = gy / height * height;
7598#endif
7599
7600 last_mouse_glyph.left = gx;
7601 last_mouse_glyph.top = gy;
7602 last_mouse_glyph.right = gx + width;
7603 last_mouse_glyph.bottom = gy + height;
7604 }
7605}
ee78dc32
GV
7606
7607/* Return the current position of the mouse.
7608 *fp should be a frame which indicates which display to ask about.
7609
7610 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7611 and *part to the frame, window, and scroll bar part that the mouse
7612 is over. Set *x and *y to the portion and whole of the mouse's
7613 position on the scroll bar.
7614
7615 If the mouse movement started elsewhere, set *fp to the frame the
7616 mouse is on, *bar_window to nil, and *x and *y to the character cell
7617 the mouse is over.
7618
9ef2e2cf 7619 Set *time to the server time-stamp for the time at which the mouse
ee78dc32
GV
7620 was at this position.
7621
7622 Don't store anything if we don't have a valid set of values to report.
7623
7624 This clears the mouse_moved flag, so we can wait for the next mouse
9ef2e2cf 7625 movement. */
ee78dc32
GV
7626
7627static void
fbd6baed 7628w32_mouse_position (fp, insist, bar_window, part, x, y, time)
ee78dc32
GV
7629 FRAME_PTR *fp;
7630 int insist;
7631 Lisp_Object *bar_window;
7632 enum scroll_bar_part *part;
7633 Lisp_Object *x, *y;
7634 unsigned long *time;
7635{
7636 FRAME_PTR f1;
7637
7638 BLOCK_INPUT;
7639
95fa970d 7640 if (! NILP (last_mouse_scroll_bar) && insist == 0)
ee78dc32
GV
7641 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7642 else
7643 {
7644 POINT pt;
7645
7646 Lisp_Object frame, tail;
7647
7648 /* Clear the mouse-moved flag for every frame on this display. */
7649 FOR_EACH_FRAME (tail, frame)
7650 XFRAME (frame)->mouse_moved = 0;
7651
7652 last_mouse_scroll_bar = Qnil;
7653
7654 GetCursorPos (&pt);
7655
7656 /* Now we have a position on the root; find the innermost window
7657 containing the pointer. */
7658 {
fbd6baed 7659 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
ee78dc32
GV
7660 && FRAME_LIVE_P (last_mouse_frame))
7661 {
08712a41
AI
7662 /* If mouse was grabbed on a frame, give coords for that frame
7663 even if the mouse is now outside it. */
ee78dc32
GV
7664 f1 = last_mouse_frame;
7665 }
7666 else
7667 {
08712a41 7668 /* Is window under mouse one of our frames? */
9f5a911b 7669 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
9127e20e 7670 WindowFromPoint (pt));
ee78dc32
GV
7671 }
7672
7673 /* If not, is it one of our scroll bars? */
7674 if (! f1)
7675 {
9127e20e
JR
7676 struct scroll_bar *bar
7677 = x_window_to_scroll_bar (WindowFromPoint (pt));
ee78dc32
GV
7678
7679 if (bar)
7680 {
7681 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7682 }
7683 }
7684
95fa970d 7685 if (f1 == 0 && insist > 0)
791f420f 7686 f1 = SELECTED_FRAME ();
ee78dc32
GV
7687
7688 if (f1)
7689 {
791f420f
JR
7690 /* Ok, we found a frame. Store all the values.
7691 last_mouse_glyph is a rectangle used to reduce the
7692 generation of mouse events. To not miss any motion
7693 events, we must divide the frame into rectangles of the
7694 size of the smallest character that could be displayed
7695 on it, i.e. into the same rectangles that matrices on
7696 the frame are divided into. */
7697
7698#if OLD_REDISPLAY_CODE
ee78dc32
GV
7699 int ignore1, ignore2;
7700
fbd6baed 7701 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
ee78dc32 7702
ee78dc32
GV
7703 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
7704 &last_mouse_glyph,
fbd6baed 7705 FRAME_W32_DISPLAY_INFO (f1)->grabbed
ee78dc32 7706 || insist);
791f420f
JR
7707#else
7708 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
9f5a911b 7709 remember_mouse_glyph (f1, pt.x, pt.y);
791f420f 7710#endif
ee78dc32
GV
7711
7712 *bar_window = Qnil;
7713 *part = 0;
7714 *fp = f1;
7715 XSETINT (*x, pt.x);
7716 XSETINT (*y, pt.y);
7717 *time = last_mouse_movement_time;
7718 }
7719 }
7720 }
7721
7722 UNBLOCK_INPUT;
7723}
791f420f 7724
ee78dc32
GV
7725\f
7726/* Scroll bar support. */
7727
ec48c3a7 7728/* Given a window ID, find the struct scroll_bar which manages it.
ee78dc32
GV
7729 This can be called in GC, so we have to make sure to strip off mark
7730 bits. */
9ef2e2cf
JR
7731
7732static struct scroll_bar *
ee78dc32
GV
7733x_window_to_scroll_bar (window_id)
7734 Window window_id;
7735{
791f420f 7736 Lisp_Object tail;
ee78dc32
GV
7737
7738 for (tail = Vframe_list;
7739 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7740 tail = XCDR (tail))
ee78dc32
GV
7741 {
7742 Lisp_Object frame, bar, condemned;
7743
8e713be6 7744 frame = XCAR (tail);
ee78dc32
GV
7745 /* All elements of Vframe_list should be frames. */
7746 if (! GC_FRAMEP (frame))
7747 abort ();
7748
7749 /* Scan this frame's scroll bar list for a scroll bar with the
7750 right window ID. */
7751 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7752 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7753 /* This trick allows us to search both the ordinary and
7754 condemned scroll bar lists with one loop. */
7755 ! GC_NILP (bar) || (bar = condemned,
7756 condemned = Qnil,
7757 ! GC_NILP (bar));
7758 bar = XSCROLL_BAR (bar)->next)
fbd6baed 7759 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
ee78dc32
GV
7760 return XSCROLL_BAR (bar);
7761 }
7762
7763 return 0;
7764}
7765
791f420f
JR
7766
7767\f
7768/* Set the thumb size and position of scroll bar BAR. We are currently
7769 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7770
7771static void
7772w32_set_scroll_bar_thumb (bar, portion, position, whole)
7773 struct scroll_bar *bar;
7774 int portion, position, whole;
7775{
7776 Window w = SCROLL_BAR_W32_WINDOW (bar);
d8e675f5 7777 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
791f420f
JR
7778 int sb_page, sb_pos;
7779 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
7780
7781 if (whole)
7782 {
7783 /* Position scroll bar at rock bottom if the bottom of the
7784 buffer is visible. This avoids shinking the thumb away
7785 to nothing if it is held at the bottom of the buffer. */
7786 if (position + portion >= whole)
7787 {
7788 sb_page = range * (whole - position) / whole
7789 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7790 sb_pos = range;
7791 }
7792
7793 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7794 sb_pos = position * range / whole;
7795 }
7796 else
7797 {
7798 sb_page = range;
7799 sb_pos = 0;
7800 }
7801
7802 BLOCK_INPUT;
7803
7804 if (pfnSetScrollInfo)
7805 {
7806 SCROLLINFO si;
7807
7808 si.cbSize = sizeof (si);
7809 /* Only update page size if currently dragging, to reduce
7810 flicker effects. */
7811 if (draggingp)
7812 si.fMask = SIF_PAGE;
7813 else
7814 si.fMask = SIF_PAGE | SIF_POS;
7815 si.nPage = sb_page;
7816 si.nPos = sb_pos;
7817
7818 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
7819 }
7820 else
7821 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
7822
7823 UNBLOCK_INPUT;
7824}
7825
7826\f
7827/************************************************************************
7828 Scroll bars, general
7829 ************************************************************************/
7830
ee78dc32
GV
7831HWND
7832my_create_scrollbar (f, bar)
7833 struct frame * f;
7834 struct scroll_bar * bar;
7835{
689004fa
GV
7836 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
7837 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
7838 (LPARAM) bar);
ee78dc32
GV
7839}
7840
52cf03a1
GV
7841//#define ATTACH_THREADS
7842
689004fa
GV
7843BOOL
7844my_show_window (FRAME_PTR f, HWND hwnd, int how)
52cf03a1
GV
7845{
7846#ifndef ATTACH_THREADS
689004fa
GV
7847 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
7848 (WPARAM) hwnd, (LPARAM) how);
52cf03a1 7849#else
689004fa 7850 return ShowWindow (hwnd, how);
52cf03a1
GV
7851#endif
7852}
7853
7854void
7855my_set_window_pos (HWND hwnd, HWND hwndAfter,
689004fa 7856 int x, int y, int cx, int cy, UINT flags)
52cf03a1
GV
7857{
7858#ifndef ATTACH_THREADS
689004fa
GV
7859 WINDOWPOS pos;
7860 pos.hwndInsertAfter = hwndAfter;
52cf03a1
GV
7861 pos.x = x;
7862 pos.y = y;
7863 pos.cx = cx;
7864 pos.cy = cy;
7865 pos.flags = flags;
7866 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
7867#else
7868 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
7869#endif
7870}
7871
ec48c3a7 7872void
689004fa
GV
7873my_set_focus (f, hwnd)
7874 struct frame * f;
7875 HWND hwnd;
7876{
7877 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
7878 (WPARAM) hwnd, 0);
7879}
7880
ec48c3a7 7881void
ef0e360f
GV
7882my_set_foreground_window (hwnd)
7883 HWND hwnd;
7884{
7885 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
7886}
7887
ee78dc32
GV
7888void
7889my_destroy_window (f, hwnd)
7890 struct frame * f;
7891 HWND hwnd;
7892{
fbd6baed 7893 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
ee78dc32
GV
7894 (WPARAM) hwnd, 0);
7895}
7896
791f420f
JR
7897/* Create a scroll bar and return the scroll bar vector for it. W is
7898 the Emacs window on which to create the scroll bar. TOP, LEFT,
7899 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7900 scroll bar. */
7901
ee78dc32 7902static struct scroll_bar *
791f420f
JR
7903x_scroll_bar_create (w, top, left, width, height)
7904 struct window *w;
ee78dc32
GV
7905 int top, left, width, height;
7906{
791f420f
JR
7907 struct frame *f = XFRAME (WINDOW_FRAME (w));
7908 HWND hwnd;
ee78dc32
GV
7909 struct scroll_bar *bar
7910 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
ee78dc32
GV
7911
7912 BLOCK_INPUT;
7913
791f420f 7914 XSETWINDOW (bar->window, w);
ee78dc32
GV
7915 XSETINT (bar->top, top);
7916 XSETINT (bar->left, left);
7917 XSETINT (bar->width, width);
7918 XSETINT (bar->height, height);
7919 XSETINT (bar->start, 0);
7920 XSETINT (bar->end, 0);
7921 bar->dragging = Qnil;
7922
7923 /* Requires geometry to be set before call to create the real window */
7924
7925 hwnd = my_create_scrollbar (f, bar);
7926
689004fa
GV
7927 if (pfnSetScrollInfo)
7928 {
7929 SCROLLINFO si;
7930
7931 si.cbSize = sizeof (si);
7932 si.fMask = SIF_ALL;
7933 si.nMin = 0;
791f420f
JR
7934 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7935 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
689004fa
GV
7936 si.nPage = si.nMax;
7937 si.nPos = 0;
7938
7939 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7940 }
7941 else
7942 {
791f420f
JR
7943 SetScrollRange (hwnd, SB_CTL, 0,
7944 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
689004fa
GV
7945 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
7946 }
ee78dc32 7947
fbd6baed 7948 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
ee78dc32
GV
7949
7950 /* Add bar to its frame's list of scroll bars. */
7951 bar->next = FRAME_SCROLL_BARS (f);
7952 bar->prev = Qnil;
7953 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7954 if (! NILP (bar->next))
7955 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7956
7957 UNBLOCK_INPUT;
7958
7959 return bar;
7960}
7961
ee78dc32 7962
791f420f
JR
7963/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7964 nil. */
ee78dc32 7965
ee78dc32
GV
7966static void
7967x_scroll_bar_remove (bar)
7968 struct scroll_bar *bar;
7969{
7970 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7971
7972 BLOCK_INPUT;
7973
7974 /* Destroy the window. */
fbd6baed 7975 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
ee78dc32
GV
7976
7977 /* Disassociate this scroll bar from its window. */
7978 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7979
7980 UNBLOCK_INPUT;
7981}
7982
7983/* Set the handle of the vertical scroll bar for WINDOW to indicate
7984 that we are displaying PORTION characters out of a total of WHOLE
7985 characters, starting at POSITION. If WINDOW has no scroll bar,
7986 create one. */
7987static void
791f420f
JR
7988w32_set_vertical_scroll_bar (w, portion, whole, position)
7989 struct window *w;
ee78dc32
GV
7990 int portion, whole, position;
7991{
791f420f 7992 struct frame *f = XFRAME (w->frame);
ee78dc32 7993 struct scroll_bar *bar;
9ef2e2cf 7994 int top, height, left, sb_left, width, sb_width;
791f420f
JR
7995 int window_x, window_y, window_width, window_height;
7996
7997 /* Get window dimensions. */
7998 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7999 top = window_y;
8000 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8001 height = window_height;
8002
8003 /* Compute the left edge of the scroll bar area. */
8004 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8005 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8006 else
8007 left = XFASTINT (w->left);
8008 left *= CANON_X_UNIT (f);
8009 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8010
8011 /* Compute the width of the scroll bar which might be less than
8012 the width of the area reserved for the scroll bar. */
8013 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8014 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8015 else
8016 sb_width = width;
ee78dc32 8017
791f420f
JR
8018 /* Compute the left edge of the scroll bar. */
8019 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8020 sb_left = left + width - sb_width - (width - sb_width) / 2;
ee78dc32 8021 else
791f420f
JR
8022 sb_left = left + (width - sb_width) / 2;
8023
8024 /* Does the scroll bar exist yet? */
8025 if (NILP (w->vertical_scroll_bar))
ee78dc32 8026 {
00fe468b 8027 HDC hdc;
791f420f 8028 BLOCK_INPUT;
6ff3e5e3 8029 if (width > 0 && height > 0)
9f5a911b
JR
8030 {
8031 hdc = get_frame_dc (f);
8032 w32_clear_area (f, hdc, left, top, width, height);
8033 release_frame_dc (f, hdc);
8034 }
791f420f 8035 UNBLOCK_INPUT;
00fe468b 8036
791f420f 8037 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
ee78dc32 8038 }
791f420f
JR
8039 else
8040 {
8041 /* It may just need to be moved and resized. */
8042 HWND hwnd;
8043
8044 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8045 hwnd = SCROLL_BAR_W32_WINDOW (bar);
8046
8047 /* If already correctly positioned, do nothing. */
8048 if ( XINT (bar->left) == sb_left
8049 && XINT (bar->top) == top
8050 && XINT (bar->width) == sb_width
8051 && XINT (bar->height) == height )
8052 {
8053 /* Redraw after clear_frame. */
8054 if (!my_show_window (f, hwnd, SW_NORMAL))
8055 InvalidateRect (hwnd, NULL, FALSE);
8056 }
8057 else
8058 {
00fe468b 8059 HDC hdc;
791f420f 8060 BLOCK_INPUT;
9f5a911b
JR
8061 if (width && height)
8062 {
8063 hdc = get_frame_dc (f);
8064 /* Since Windows scroll bars are smaller than the space reserved
8065 for them on the frame, we have to clear "under" them. */
8066 w32_clear_area (f, hdc,
8067 left,
8068 top,
8069 width,
8070 height);
8071 release_frame_dc (f, hdc);
8072 }
791f420f
JR
8073 /* Make sure scroll bar is "visible" before moving, to ensure the
8074 area of the parent window now exposed will be refreshed. */
8075 my_show_window (f, hwnd, SW_HIDE);
9f5a911b
JR
8076 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8077 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8078 max (height, 1), TRUE);
791f420f
JR
8079 if (pfnSetScrollInfo)
8080 {
8081 SCROLLINFO si;
ee78dc32 8082
791f420f
JR
8083 si.cbSize = sizeof (si);
8084 si.fMask = SIF_RANGE;
8085 si.nMin = 0;
8086 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
8087 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
ee78dc32 8088
00fe468b 8089 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
791f420f
JR
8090 }
8091 else
00fe468b 8092 SetScrollRange (hwnd, SB_CTL, 0,
791f420f
JR
8093 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
8094 my_show_window (f, hwnd, SW_NORMAL);
8095 // InvalidateRect (w, NULL, FALSE);
8096
8097 /* Remember new settings. */
8098 XSETINT (bar->left, sb_left);
8099 XSETINT (bar->top, top);
8100 XSETINT (bar->width, sb_width);
8101 XSETINT (bar->height, height);
8102
8103 UNBLOCK_INPUT;
8104 }
8105 }
8106 w32_set_scroll_bar_thumb (bar, portion, position, whole);
ee78dc32 8107
791f420f 8108 XSETVECTOR (w->vertical_scroll_bar, bar);
ee78dc32
GV
8109}
8110
8111
8112/* The following three hooks are used when we're doing a thorough
8113 redisplay of the frame. We don't explicitly know which scroll bars
8114 are going to be deleted, because keeping track of when windows go
8115 away is a real pain - "Can you say set-window-configuration, boys
8116 and girls?" Instead, we just assert at the beginning of redisplay
8117 that *all* scroll bars are to be removed, and then save a scroll bar
8118 from the fiery pit when we actually redisplay its window. */
8119
8120/* Arrange for all scroll bars on FRAME to be removed at the next call
8121 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9ef2e2cf
JR
8122 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8123
ee78dc32 8124static void
fbd6baed 8125w32_condemn_scroll_bars (frame)
ee78dc32
GV
8126 FRAME_PTR frame;
8127{
ef0e360f
GV
8128 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8129 while (! NILP (FRAME_SCROLL_BARS (frame)))
8130 {
8131 Lisp_Object bar;
8132 bar = FRAME_SCROLL_BARS (frame);
8133 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8134 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8135 XSCROLL_BAR (bar)->prev = Qnil;
8136 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8137 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8138 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8139 }
ee78dc32
GV
8140}
8141
c2cc16fa 8142
9ef2e2cf 8143/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
ee78dc32 8144 Note that WINDOW isn't necessarily condemned at all. */
c2cc16fa 8145
ee78dc32 8146static void
fbd6baed 8147w32_redeem_scroll_bar (window)
ee78dc32
GV
8148 struct window *window;
8149{
8150 struct scroll_bar *bar;
c2cc16fa 8151 struct frame *f;
ee78dc32
GV
8152
8153 /* We can't redeem this window's scroll bar if it doesn't have one. */
8154 if (NILP (window->vertical_scroll_bar))
8155 abort ();
8156
8157 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8158
ef0e360f 8159 /* Unlink it from the condemned list. */
c2cc16fa
JR
8160 f = XFRAME (WINDOW_FRAME (window));
8161 if (NILP (bar->prev))
8162 {
8163 /* If the prev pointer is nil, it must be the first in one of
8164 the lists. */
8165 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8166 /* It's not condemned. Everything's fine. */
8167 return;
8168 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8169 window->vertical_scroll_bar))
8170 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8171 else
8172 /* If its prev pointer is nil, it must be at the front of
8173 one or the other! */
8174 abort ();
8175 }
8176 else
8177 XSCROLL_BAR (bar->prev)->next = bar->next;
ef0e360f 8178
c2cc16fa
JR
8179 if (! NILP (bar->next))
8180 XSCROLL_BAR (bar->next)->prev = bar->prev;
ef0e360f 8181
c2cc16fa
JR
8182 bar->next = FRAME_SCROLL_BARS (f);
8183 bar->prev = Qnil;
8184 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8185 if (! NILP (bar->next))
8186 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
ee78dc32
GV
8187}
8188
8189/* Remove all scroll bars on FRAME that haven't been saved since the
8190 last call to `*condemn_scroll_bars_hook'. */
9ef2e2cf 8191
ee78dc32 8192static void
fbd6baed 8193w32_judge_scroll_bars (f)
ee78dc32
GV
8194 FRAME_PTR f;
8195{
8196 Lisp_Object bar, next;
8197
8198 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8199
8200 /* Clear out the condemned list now so we won't try to process any
8201 more events on the hapless scroll bars. */
8202 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8203
8204 for (; ! NILP (bar); bar = next)
8205 {
8206 struct scroll_bar *b = XSCROLL_BAR (bar);
8207
8208 x_scroll_bar_remove (b);
8209
8210 next = b->next;
8211 b->next = b->prev = Qnil;
8212 }
8213
8214 /* Now there should be no references to the condemned scroll bars,
8215 and they should get garbage-collected. */
8216}
8217
8218/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8219 is set to something other than no_event, it is enqueued.
8220
8221 This may be called from a signal handler, so we have to ignore GC
8222 mark bits. */
2c28562d 8223
52cf03a1 8224static int
c2cc16fa 8225w32_scroll_bar_handle_click (bar, msg, emacs_event)
ee78dc32 8226 struct scroll_bar *bar;
fbd6baed 8227 W32Msg *msg;
ee78dc32
GV
8228 struct input_event *emacs_event;
8229{
8230 if (! GC_WINDOWP (bar->window))
8231 abort ();
8232
fbd6baed 8233 emacs_event->kind = w32_scroll_bar_click;
ee78dc32 8234 emacs_event->code = 0;
52cf03a1
GV
8235 /* not really meaningful to distinguish up/down */
8236 emacs_event->modifiers = msg->dwModifiers;
ee78dc32 8237 emacs_event->frame_or_window = bar->window;
7e889510 8238 emacs_event->arg = Qnil;
ee78dc32
GV
8239 emacs_event->timestamp = msg->msg.time;
8240
8241 {
791f420f 8242 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
689004fa
GV
8243 int y;
8244 int dragging = !NILP (bar->dragging);
8245
8246 if (pfnGetScrollInfo)
8247 {
8248 SCROLLINFO si;
8249
8250 si.cbSize = sizeof (si);
8251 si.fMask = SIF_POS;
8252
8253 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
8254 y = si.nPos;
8255 }
8256 else
8257 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
8258
8259 bar->dragging = Qnil;
ee78dc32 8260
9ef2e2cf
JR
8261
8262 last_mouse_scroll_bar_pos = msg->msg.wParam;
8263
ee78dc32 8264 switch (LOWORD (msg->msg.wParam))
2c28562d 8265 {
2c28562d 8266 case SB_LINEDOWN:
52cf03a1 8267 emacs_event->part = scroll_bar_down_arrow;
ee78dc32 8268 break;
2c28562d 8269 case SB_LINEUP:
52cf03a1 8270 emacs_event->part = scroll_bar_up_arrow;
ee78dc32 8271 break;
2c28562d 8272 case SB_PAGEUP:
ee78dc32
GV
8273 emacs_event->part = scroll_bar_above_handle;
8274 break;
2c28562d 8275 case SB_PAGEDOWN:
ee78dc32
GV
8276 emacs_event->part = scroll_bar_below_handle;
8277 break;
2c28562d 8278 case SB_TOP:
ee78dc32
GV
8279 emacs_event->part = scroll_bar_handle;
8280 y = 0;
8281 break;
2c28562d 8282 case SB_BOTTOM:
ee78dc32
GV
8283 emacs_event->part = scroll_bar_handle;
8284 y = top_range;
8285 break;
689004fa 8286 case SB_THUMBTRACK:
2c28562d 8287 case SB_THUMBPOSITION:
791f420f
JR
8288 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
8289 y = HIWORD (msg->msg.wParam);
689004fa 8290 bar->dragging = Qt;
ee78dc32 8291 emacs_event->part = scroll_bar_handle;
689004fa
GV
8292
8293 /* "Silently" update current position. */
8294 if (pfnSetScrollInfo)
8295 {
8296 SCROLLINFO si;
8297
8298 si.cbSize = sizeof (si);
8299 si.fMask = SIF_POS;
689004fa
GV
8300 si.nPos = y;
8301 /* Remember apparent position (we actually lag behind the real
8302 position, so don't set that directly. */
8303 last_scroll_bar_drag_pos = y;
8304
8305 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
8306 }
8307 else
8308 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
ee78dc32 8309 break;
2c28562d 8310 case SB_ENDSCROLL:
689004fa
GV
8311 /* If this is the end of a drag sequence, then reset the scroll
8312 handle size to normal and do a final redraw. Otherwise do
8313 nothing. */
8314 if (dragging)
8315 {
8316 if (pfnSetScrollInfo)
8317 {
8318 SCROLLINFO si;
8319 int start = XINT (bar->start);
8320 int end = XINT (bar->end);
8321
8322 si.cbSize = sizeof (si);
8323 si.fMask = SIF_PAGE | SIF_POS;
791f420f 8324 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
689004fa 8325 si.nPos = last_scroll_bar_drag_pos;
689004fa
GV
8326 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
8327 }
8328 else
8329 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
8330 }
8331 /* fall through */
2c28562d 8332 default:
689004fa 8333 emacs_event->kind = no_event;
52cf03a1 8334 return FALSE;
2c28562d 8335 }
52cf03a1 8336
ee78dc32
GV
8337 XSETINT (emacs_event->x, y);
8338 XSETINT (emacs_event->y, top_range);
52cf03a1
GV
8339
8340 return TRUE;
ee78dc32
GV
8341 }
8342}
8343
8344/* Return information to the user about the current position of the mouse
8345 on the scroll bar. */
9ef2e2cf 8346
ee78dc32
GV
8347static void
8348x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8349 FRAME_PTR *fp;
8350 Lisp_Object *bar_window;
8351 enum scroll_bar_part *part;
8352 Lisp_Object *x, *y;
8353 unsigned long *time;
8354{
8355 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
fbd6baed 8356 Window w = SCROLL_BAR_W32_WINDOW (bar);
ee78dc32
GV
8357 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8358 int pos;
791f420f 8359 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ee78dc32
GV
8360
8361 BLOCK_INPUT;
8362
8363 *fp = f;
8364 *bar_window = bar->window;
8365
689004fa
GV
8366 if (pfnGetScrollInfo)
8367 {
8368 SCROLLINFO si;
8369
8370 si.cbSize = sizeof (si);
8371 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
8372
8373 pfnGetScrollInfo (w, SB_CTL, &si);
8374 pos = si.nPos;
8375 top_range = si.nMax - si.nPage + 1;
8376 }
8377 else
8378 pos = GetScrollPos (w, SB_CTL);
ee78dc32
GV
8379
8380 switch (LOWORD (last_mouse_scroll_bar_pos))
8381 {
8382 case SB_THUMBPOSITION:
8383 case SB_THUMBTRACK:
8384 *part = scroll_bar_handle;
791f420f 8385 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
ee78dc32
GV
8386 pos = HIWORD (last_mouse_scroll_bar_pos);
8387 break;
8388 case SB_LINEDOWN:
8389 *part = scroll_bar_handle;
8390 pos++;
8391 break;
8392 default:
8393 *part = scroll_bar_handle;
8394 break;
8395 }
8396
9127e20e
JR
8397 XSETINT (*x, pos);
8398 XSETINT (*y, top_range);
ee78dc32
GV
8399
8400 f->mouse_moved = 0;
8401 last_mouse_scroll_bar = Qnil;
8402
8403 *time = last_mouse_movement_time;
8404
8405 UNBLOCK_INPUT;
8406}
8407
9ef2e2cf 8408
ee78dc32
GV
8409/* The screen has been cleared so we may have changed foreground or
8410 background colors, and the scroll bars may need to be redrawn.
8411 Clear out the scroll bars, and ask for expose events, so we can
8412 redraw them. */
9ef2e2cf 8413
791f420f 8414void
ee78dc32 8415x_scroll_bar_clear (f)
9ef2e2cf 8416 FRAME_PTR f;
ee78dc32 8417{
ee78dc32
GV
8418 Lisp_Object bar;
8419
9ef2e2cf
JR
8420 /* We can have scroll bars even if this is 0,
8421 if we just turned off scroll bar mode.
8422 But in that case we should not clear them. */
8423 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8424 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8425 bar = XSCROLL_BAR (bar)->next)
8426 {
8427 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
8428 HDC hdc = GetDC (window);
8429 RECT rect;
52cf03a1 8430
9ef2e2cf
JR
8431 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
8432 arranges to refresh the scroll bar if hidden. */
8433 my_show_window (f, window, SW_HIDE);
689004fa 8434
9ef2e2cf
JR
8435 GetClientRect (window, &rect);
8436 select_palette (f, hdc);
8437 w32_clear_rect (f, hdc, &rect);
8438 deselect_palette (f, hdc);
689004fa 8439
9ef2e2cf
JR
8440 ReleaseDC (window, hdc);
8441 }
52cf03a1
GV
8442}
8443
ee78dc32 8444\f
fbd6baed 8445/* The main W32 event-reading loop - w32_read_socket. */
ee78dc32 8446
9ef2e2cf 8447/* Time stamp of enter window event. This is only used by w32_read_socket,
ee78dc32
GV
8448 but we have to put it out here, since static variables within functions
8449 sometimes don't work. */
9ef2e2cf 8450
ee78dc32
GV
8451static Time enter_timestamp;
8452
8453/* Record the last 100 characters stored
8454 to help debug the loss-of-chars-during-GC problem. */
9ef2e2cf
JR
8455
8456static int temp_index;
8457static short temp_buffer[100];
ee78dc32 8458
afd153f0 8459
fbd6baed 8460/* Read events coming from the W32 shell.
ee78dc32
GV
8461 This routine is called by the SIGIO handler.
8462 We return as soon as there are no more events to be read.
8463
8464 Events representing keys are stored in buffer BUFP,
8465 which can hold up to NUMCHARS characters.
8466 We return the number of characters stored into the buffer,
8467 thus pretending to be `read'.
8468
ee78dc32
GV
8469 EXPECTED is nonzero if the caller knows input is available.
8470
8471 Some of these messages are reposted back to the message queue since the
e9e23e23
GV
8472 system calls the windows proc directly in a context where we cannot return
8473 the data nor can we guarantee the state we are in. So if we dispatch them
ee78dc32
GV
8474 we will get into an infinite loop. To prevent this from ever happening we
8475 will set a variable to indicate we are in the read_socket call and indicate
e9e23e23
GV
8476 which message we are processing since the windows proc gets called
8477 recursively with different messages by the system.
ee78dc32
GV
8478*/
8479
8480int
3aad7613 8481w32_read_socket (sd, bufp, numchars, expected)
ee78dc32 8482 register int sd;
9ef2e2cf
JR
8483 /* register */ struct input_event *bufp;
8484 /* register */ int numchars;
ee78dc32
GV
8485 int expected;
8486{
8487 int count = 0;
689004fa 8488 int check_visibility = 0;
fbd6baed 8489 W32Msg msg;
ee78dc32 8490 struct frame *f;
fbd6baed 8491 struct w32_display_info *dpyinfo = &one_w32_display_info;
ee78dc32
GV
8492
8493 if (interrupt_input_blocked)
8494 {
8495 interrupt_input_pending = 1;
8496 return -1;
8497 }
8498
8499 interrupt_input_pending = 0;
8500 BLOCK_INPUT;
8501
8502 /* So people can tell when we have read the available input. */
8503 input_signal_count++;
8504
8505 if (numchars <= 0)
8506 abort (); /* Don't think this happens. */
8507
b71b8111 8508 /* TODO: tool-bars, ghostscript integration, mouse
791f420f 8509 cursors. */
52cf03a1 8510 while (get_next_msg (&msg, FALSE))
ee78dc32
GV
8511 {
8512 switch (msg.msg.message)
8513 {
ee78dc32 8514 case WM_PAINT:
9f5a911b 8515 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
ee78dc32 8516
9f5a911b
JR
8517 if (f)
8518 {
8519 if (msg.rect.right == msg.rect.left ||
8520 msg.rect.bottom == msg.rect.top)
8521 {
8522 /* We may get paint messages even though the client
8523 area is clipped - these are not expose events. */
8524 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
8525 XSTRING (f->name)->data));
8526 }
8527 else if (f->async_visible != 1)
8528 {
8529 /* Definitely not obscured, so mark as visible. */
8530 f->async_visible = 1;
8531 f->async_iconified = 0;
8532 SET_FRAME_GARBAGED (f);
8533 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
8534 XSTRING (f->name)->data));
8535
8536 /* WM_PAINT serves as MapNotify as well, so report
8537 visibility changes properly. */
8538 if (f->iconified)
8539 {
8540 bufp->kind = deiconify_event;
8541 XSETFRAME (bufp->frame_or_window, f);
8542 bufp->arg = Qnil;
8543 bufp++;
8544 count++;
8545 numchars--;
8546 }
8547 else if (! NILP (Vframe_list)
8548 && ! NILP (XCDR (Vframe_list)))
8549 /* Force a redisplay sooner or later to update the
8550 frame titles in case this is the second frame. */
8551 record_asynch_buffer_change ();
8552 }
8553 else
8554 {
8555 HDC hdc = get_frame_dc (f);
8556
8557 /* Erase background again for safety. */
8558 w32_clear_rect (f, hdc, &msg.rect);
8559 release_frame_dc (f, hdc);
8560 expose_frame (f,
8561 msg.rect.left,
8562 msg.rect.top,
8563 msg.rect.right - msg.rect.left,
8564 msg.rect.bottom - msg.rect.top);
8565 }
8566 }
52cf03a1 8567 break;
689004fa 8568
f98169a0
GV
8569 case WM_INPUTLANGCHANGE:
8570 /* Generate a language change event. */
8571 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8572
8573 if (f)
8574 {
8575 if (numchars == 0)
8576 abort ();
8577
8578 bufp->kind = language_change_event;
8579 XSETFRAME (bufp->frame_or_window, f);
7e889510 8580 bufp->arg = Qnil;
f98169a0
GV
8581 bufp->code = msg.msg.wParam;
8582 bufp->modifiers = msg.msg.lParam & 0xffff;
8583 bufp++;
8584 count++;
8585 numchars--;
8586 }
8587 break;
8588
ee78dc32
GV
8589 case WM_KEYDOWN:
8590 case WM_SYSKEYDOWN:
8591 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8592
8593 if (f && !f->iconified)
8594 {
8595 if (temp_index == sizeof temp_buffer / sizeof (short))
8596 temp_index = 0;
8597 temp_buffer[temp_index++] = msg.msg.wParam;
8598 bufp->kind = non_ascii_keystroke;
8599 bufp->code = msg.msg.wParam;
f98169a0 8600 bufp->modifiers = msg.dwModifiers;
ee78dc32 8601 XSETFRAME (bufp->frame_or_window, f);
7e889510 8602 bufp->arg = Qnil;
ee78dc32
GV
8603 bufp->timestamp = msg.msg.time;
8604 bufp++;
8605 numchars--;
8606 count++;
8607 }
8608 break;
689004fa 8609
ee78dc32
GV
8610 case WM_SYSCHAR:
8611 case WM_CHAR:
8612 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8613
8614 if (f && !f->iconified)
8615 {
f98169a0
GV
8616 if (temp_index == sizeof temp_buffer / sizeof (short))
8617 temp_index = 0;
8618 temp_buffer[temp_index++] = msg.msg.wParam;
8619 bufp->kind = ascii_keystroke;
8620 bufp->code = msg.msg.wParam;
8621 bufp->modifiers = msg.dwModifiers;
8622 XSETFRAME (bufp->frame_or_window, f);
7e889510 8623 bufp->arg = Qnil;
f98169a0
GV
8624 bufp->timestamp = msg.msg.time;
8625 bufp++;
8626 numchars--;
8627 count++;
ee78dc32
GV
8628 }
8629 break;
689004fa 8630
ee78dc32 8631 case WM_MOUSEMOVE:
791f420f 8632 previous_help_echo = help_echo;
9f5a911b 8633 help_echo_object = help_echo_window = Qnil;
158cba56 8634 help_echo_pos = -1;
791f420f 8635
ee78dc32
GV
8636 if (dpyinfo->grabbed && last_mouse_frame
8637 && FRAME_LIVE_P (last_mouse_frame))
8638 f = last_mouse_frame;
8639 else
8640 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8641
8642 if (f)
8643 note_mouse_movement (f, &msg.msg);
8644 else
791f420f
JR
8645 {
8646 /* If we move outside the frame, then we're
8647 certainly no longer on any text in the frame. */
5b844253 8648 clear_mouse_face (dpyinfo);
791f420f
JR
8649 }
8650
8651 /* If the contents of the global variable help_echo
8652 has changed, generate a HELP_EVENT. */
9f5a911b 8653 if (help_echo != previous_help_echo)
791f420f
JR
8654 {
8655 Lisp_Object frame;
ec48c3a7 8656 int n;
791f420f
JR
8657
8658 if (f)
8659 XSETFRAME (frame, f);
8660 else
8661 frame = Qnil;
8662
8663 any_help_event_p = 1;
b4165314
GM
8664 n = gen_help_event (bufp, numchars, help_echo, frame,
8665 help_echo_window, help_echo_object,
8666 help_echo_pos);
ec48c3a7 8667 bufp += n, count += n, numchars -= n;
791f420f
JR
8668 }
8669 break;
689004fa 8670
ee78dc32
GV
8671 case WM_LBUTTONDOWN:
8672 case WM_LBUTTONUP:
8673 case WM_MBUTTONDOWN:
8674 case WM_MBUTTONUP:
8675 case WM_RBUTTONDOWN:
8676 case WM_RBUTTONUP:
53823ab9
JR
8677 case WM_XBUTTONDOWN:
8678 case WM_XBUTTONUP:
ee78dc32 8679 {
791f420f
JR
8680 /* If we decide we want to generate an event to be seen
8681 by the rest of Emacs, we put it here. */
8682 struct input_event emacs_event;
8683 int tool_bar_p = 0;
ee78dc32
GV
8684 int button;
8685 int up;
791f420f
JR
8686
8687 emacs_event.kind = no_event;
ee78dc32
GV
8688
8689 if (dpyinfo->grabbed && last_mouse_frame
8690 && FRAME_LIVE_P (last_mouse_frame))
8691 f = last_mouse_frame;
8692 else
8693 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8694
8695 if (f)
8696 {
791f420f
JR
8697 construct_mouse_click (&emacs_event, &msg, f);
8698
8699 /* Is this in the tool-bar? */
8700 if (WINDOWP (f->tool_bar_window)
8701 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
8702 {
8703 Lisp_Object window;
d6ff54d5 8704 int p;
791f420f
JR
8705
8706 /* Set x and y. */
8707 window = window_from_coordinates (f,
8708 emacs_event.x,
8709 emacs_event.y,
8710 &p, 1);
8711 if (EQ (window, f->tool_bar_window))
8712 {
8713 w32_handle_tool_bar_click (f, &emacs_event);
8714 tool_bar_p = 1;
8715 }
8716 }
8717
8718 if (!tool_bar_p)
8719 if (!dpyinfo->w32_focus_frame
8720 || f == dpyinfo->w32_focus_frame
8721 && (numchars >= 1))
8722 {
8723 construct_mouse_click (bufp, &msg, f);
8724 bufp++;
8725 count++;
8726 numchars--;
8727 }
ee78dc32
GV
8728 }
8729
53823ab9
JR
8730 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
8731 &button, &up);
8732
ee78dc32
GV
8733 if (up)
8734 {
8735 dpyinfo->grabbed &= ~ (1 << button);
8736 }
8737 else
8738 {
8739 dpyinfo->grabbed |= (1 << button);
8740 last_mouse_frame = f;
791f420f
JR
8741 /* Ignore any mouse motion that happened
8742 before this event; any subsequent mouse-movement
8743 Emacs events should reflect only motion after
8744 the ButtonPress. */
8745 if (f != 0)
8746 f->mouse_moved = 0;
8747
8748 if (!tool_bar_p)
8749 last_tool_bar_item = -1;
ee78dc32 8750 }
689004fa 8751 break;
ee78dc32
GV
8752 }
8753
689004fa
GV
8754 case WM_MOUSEWHEEL:
8755 if (dpyinfo->grabbed && last_mouse_frame
8756 && FRAME_LIVE_P (last_mouse_frame))
8757 f = last_mouse_frame;
8758 else
8759 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8760
8761 if (f)
8762 {
8763 if ((!dpyinfo->w32_focus_frame
8764 || f == dpyinfo->w32_focus_frame)
8765 && (numchars >= 1))
8766 {
8767 construct_mouse_wheel (bufp, &msg, f);
8768 bufp++;
8769 count++;
8770 numchars--;
8771 }
8772 }
ee78dc32 8773 break;
689004fa 8774
12857dfd
RS
8775 case WM_DROPFILES:
8776 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8777
8778 if (f)
8779 {
8780 construct_drag_n_drop (bufp, &msg, f);
8781 bufp++;
8782 count++;
8783 numchars--;
8784 }
8785 break;
8786
ee78dc32
GV
8787 case WM_VSCROLL:
8788 {
689004fa
GV
8789 struct scroll_bar *bar =
8790 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
ee78dc32
GV
8791
8792 if (bar && numchars >= 1)
8793 {
c2cc16fa 8794 if (w32_scroll_bar_handle_click (bar, &msg, bufp))
52cf03a1
GV
8795 {
8796 bufp++;
8797 count++;
8798 numchars--;
8799 }
ee78dc32 8800 }
689004fa 8801 break;
ee78dc32
GV
8802 }
8803
689004fa
GV
8804 case WM_WINDOWPOSCHANGED:
8805 case WM_ACTIVATE:
8806 case WM_ACTIVATEAPP:
8807 check_visibility = 1;
ee78dc32 8808 break;
689004fa 8809
ee78dc32
GV
8810 case WM_MOVE:
8811 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8812
8813 if (f && !f->async_iconified)
8814 {
689004fa
GV
8815 int x, y;
8816
8817 x_real_positions (f, &x, &y);
8818 f->output_data.w32->left_pos = x;
8819 f->output_data.w32->top_pos = y;
ee78dc32 8820 }
689004fa
GV
8821
8822 check_visibility = 1;
8823 break;
8824
8825 case WM_SHOWWINDOW:
b71b8111
JR
8826 /* wParam non-zero means Window is about to be shown, 0 means
8827 about to be hidden. */
8828 /* Redo the mouse-highlight after the tooltip has gone. */
8829 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
8830 {
8831 tip_window = NULL;
8832 redo_mouse_highlight ();
8833 }
8834
689004fa
GV
8835 /* If window has been obscured or exposed by another window
8836 being maximised or minimised/restored, then recheck
8837 visibility of all frames. Direct changes to our own
8838 windows get handled by WM_SIZE. */
8839#if 0
8840 if (msg.msg.lParam != 0)
8841 check_visibility = 1;
8842 else
8843 {
8844 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8845 f->async_visible = msg.msg.wParam;
8846 }
8847#endif
8848
8849 check_visibility = 1;
ee78dc32 8850 break;
689004fa 8851
ee78dc32
GV
8852 case WM_SIZE:
8853 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8854
689004fa
GV
8855 /* Inform lisp of whether frame has been iconified etc. */
8856 if (f)
ee78dc32 8857 {
689004fa 8858 switch (msg.msg.wParam)
ee78dc32 8859 {
689004fa
GV
8860 case SIZE_MINIMIZED:
8861 f->async_visible = 0;
ee78dc32
GV
8862 f->async_iconified = 1;
8863
8864 bufp->kind = iconify_event;
8865 XSETFRAME (bufp->frame_or_window, f);
7e889510 8866 bufp->arg = Qnil;
ee78dc32
GV
8867 bufp++;
8868 count++;
8869 numchars--;
689004fa
GV
8870 break;
8871
8872 case SIZE_MAXIMIZED:
8873 case SIZE_RESTORED:
ee78dc32
GV
8874 f->async_visible = 1;
8875 f->async_iconified = 0;
8876
8877 /* wait_reading_process_input will notice this and update
8878 the frame's display structures. */
8879 SET_FRAME_GARBAGED (f);
8880
8881 if (f->iconified)
8882 {
31d4844a
KH
8883 int x, y;
8884
8885 /* Reset top and left positions of the Window
8886 here since Windows sends a WM_MOVE message
8887 BEFORE telling us the Window is minimized
8888 when the Window is iconified, with 3000,3000
8889 as the co-ords. */
8890 x_real_positions (f, &x, &y);
8891 f->output_data.w32->left_pos = x;
8892 f->output_data.w32->top_pos = y;
8893
ee78dc32
GV
8894 bufp->kind = deiconify_event;
8895 XSETFRAME (bufp->frame_or_window, f);
7e889510 8896 bufp->arg = Qnil;
ee78dc32
GV
8897 bufp++;
8898 count++;
8899 numchars--;
8900 }
9ef2e2cf
JR
8901 else if (! NILP (Vframe_list)
8902 && ! NILP (XCDR (Vframe_list)))
ee78dc32
GV
8903 /* Force a redisplay sooner or later
8904 to update the frame titles
8905 in case this is the second frame. */
8906 record_asynch_buffer_change ();
689004fa 8907 break;
ee78dc32 8908 }
ee78dc32 8909 }
689004fa 8910
ef0e360f
GV
8911 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
8912 {
8913 RECT rect;
8914 int rows;
8915 int columns;
8916 int width;
8917 int height;
8918
9127e20e 8919 GetClientRect (msg.msg.hwnd, &rect);
ef0e360f
GV
8920
8921 height = rect.bottom - rect.top;
8922 width = rect.right - rect.left;
8923
8924 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
8925 columns = PIXEL_TO_CHAR_WIDTH (f, width);
8926
8927 /* TODO: Clip size to the screen dimensions. */
8928
8929 /* Even if the number of character rows and columns has
8930 not changed, the font size may have changed, so we need
8931 to check the pixel dimensions as well. */
8932
8933 if (columns != f->width
8934 || rows != f->height
8935 || width != f->output_data.w32->pixel_width
8936 || height != f->output_data.w32->pixel_height)
8937 {
791f420f 8938 change_frame_size (f, rows, columns, 0, 1, 0);
ef0e360f 8939 SET_FRAME_GARBAGED (f);
31d4844a 8940 cancel_mouse_face (f);
ef0e360f
GV
8941 f->output_data.w32->pixel_width = width;
8942 f->output_data.w32->pixel_height = height;
8943 f->output_data.w32->win_gravity = NorthWestGravity;
8944 }
8945 }
8946
689004fa
GV
8947 check_visibility = 1;
8948 break;
8949
1576fbfa
JR
8950 case WM_MOUSELEAVE:
8951 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8952 if (f)
8953 {
8954 if (f == dpyinfo->mouse_face_mouse_frame)
8955 {
8956 /* If we move outside the frame, then we're
8957 certainly no longer on any text in the frame. */
8958 clear_mouse_face (dpyinfo);
8959 dpyinfo->mouse_face_mouse_frame = 0;
8960 }
8961
8962 /* Generate a nil HELP_EVENT to cancel a help-echo.
8963 Do it only if there's something to cancel.
8964 Otherwise, the startup message is cleared when
8965 the mouse leaves the frame. */
8966 if (any_help_event_p)
8967 {
8968 Lisp_Object frame;
8969 int n;
8970
8971 XSETFRAME (frame, f);
8972 help_echo = Qnil;
8973 n = gen_help_event (bufp, numchars,
8974 Qnil, frame, Qnil, Qnil, 0);
8975 bufp += n, count += n, numchars -= n;
8976 }
8977 }
8978 break;
8979
689004fa 8980 case WM_SETFOCUS:
791f420f
JR
8981 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8982
8983 dpyinfo->w32_focus_event_frame = f;
8984
8985 if (f)
8986 x_new_focus_frame (dpyinfo, f);
8987
8988
8989 dpyinfo->grabbed = 0;
8990 check_visibility = 1;
8991 break;
8992
689004fa 8993 case WM_KILLFOCUS:
01b220b6 8994 /* TODO: some of this belongs in MOUSE_LEAVE */
791f420f 8995 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
08712a41 8996
791f420f
JR
8997 if (f)
8998 {
791f420f
JR
8999 if (f == dpyinfo->w32_focus_event_frame)
9000 dpyinfo->w32_focus_event_frame = 0;
9001
9002 if (f == dpyinfo->w32_focus_frame)
9003 x_new_focus_frame (dpyinfo, 0);
9004
9005 if (f == dpyinfo->mouse_face_mouse_frame)
9006 {
9007 /* If we move outside the frame, then we're
9008 certainly no longer on any text in the frame. */
9009 clear_mouse_face (dpyinfo);
9010 dpyinfo->mouse_face_mouse_frame = 0;
9011 }
9ef2e2cf 9012
791f420f
JR
9013 /* Generate a nil HELP_EVENT to cancel a help-echo.
9014 Do it only if there's something to cancel.
9015 Otherwise, the startup message is cleared when
9016 the mouse leaves the frame. */
9017 if (any_help_event_p)
9018 {
c2cc16fa 9019 Lisp_Object frame;
ec48c3a7
JR
9020 int n;
9021
791f420f 9022 XSETFRAME (frame, f);
c2cc16fa
JR
9023 help_echo = Qnil;
9024 n = gen_help_event (bufp, numchars,
9025 Qnil, frame, Qnil, Qnil, 0);
ec48c3a7 9026 bufp += n, count += n, numchars -=n;
791f420f
JR
9027 }
9028 }
689004fa 9029
08712a41 9030 dpyinfo->grabbed = 0;
689004fa 9031 check_visibility = 1;
ee78dc32 9032 break;
689004fa 9033
ee78dc32
GV
9034 case WM_CLOSE:
9035 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9036
9037 if (f)
9038 {
9039 if (numchars == 0)
9040 abort ();
9041
9042 bufp->kind = delete_window_event;
9043 XSETFRAME (bufp->frame_or_window, f);
7e889510 9044 bufp->arg = Qnil;
ee78dc32
GV
9045 bufp++;
9046 count++;
9047 numchars--;
9048 }
689004fa
GV
9049 break;
9050
9051 case WM_INITMENU:
9052 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9053
9054 if (f)
9055 {
9056 if (numchars == 0)
9057 abort ();
ee78dc32 9058
689004fa
GV
9059 bufp->kind = menu_bar_activate_event;
9060 XSETFRAME (bufp->frame_or_window, f);
7e889510 9061 bufp->arg = Qnil;
689004fa
GV
9062 bufp++;
9063 count++;
9064 numchars--;
9065 }
ee78dc32 9066 break;
689004fa 9067
ee78dc32
GV
9068 case WM_COMMAND:
9069 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
014b6ea1 9070
ee78dc32
GV
9071 if (f)
9072 {
f98169a0
GV
9073 extern void menubar_selection_callback
9074 (FRAME_PTR f, void * client_data);
014b6ea1 9075 menubar_selection_callback (f, (void *)msg.msg.wParam);
ee78dc32 9076 }
689004fa
GV
9077
9078 check_visibility = 1;
9079 break;
9080
9081 case WM_DISPLAYCHANGE:
9082 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9083
9084 if (f)
9085 {
9086 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
9087 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
9088 dpyinfo->n_cbits = msg.msg.wParam;
9089 DebPrint (("display change: %d %d\n", dpyinfo->width,
9090 dpyinfo->height));
9091 }
9092
9093 check_visibility = 1;
ee78dc32 9094 break;
e7efd97e
GV
9095
9096 default:
9097 /* Check for messages registered at runtime. */
9098 if (msg.msg.message == msh_mousewheel)
9099 {
9100 if (dpyinfo->grabbed && last_mouse_frame
9101 && FRAME_LIVE_P (last_mouse_frame))
9102 f = last_mouse_frame;
9103 else
9104 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9105
9106 if (f)
9107 {
9108 if ((!dpyinfo->w32_focus_frame
9109 || f == dpyinfo->w32_focus_frame)
9110 && (numchars >= 1))
9111 {
9112 construct_mouse_wheel (bufp, &msg, f);
9113 bufp++;
9114 count++;
9115 numchars--;
9116 }
9117 }
9118 }
9119 break;
ee78dc32
GV
9120 }
9121 }
9122
9123 /* If the focus was just given to an autoraising frame,
9124 raise it now. */
9125 /* ??? This ought to be able to handle more than one such frame. */
9126 if (pending_autoraise_frame)
9127 {
9128 x_raise_frame (pending_autoraise_frame);
9129 pending_autoraise_frame = 0;
9130 }
9131
689004fa
GV
9132 /* Check which frames are still visisble, if we have enqueued any user
9133 events or been notified of events that may affect visibility. We
9134 do this here because there doesn't seem to be any direct
9135 notification from Windows that the visibility of a window has
9136 changed (at least, not in all cases). */
9137 if (count > 0 || check_visibility)
9138 {
9139 Lisp_Object tail, frame;
9140
9141 FOR_EACH_FRAME (tail, frame)
9142 {
9143 FRAME_PTR f = XFRAME (frame);
b71b8111
JR
9144 /* The tooltip has been drawn already. Avoid the
9145 SET_FRAME_GARBAGED below. */
eb77a5f4 9146 if (EQ (frame, tip_frame))
b71b8111
JR
9147 continue;
9148
689004fa
GV
9149 /* Check "visible" frames and mark each as obscured or not.
9150 Note that async_visible is nonzero for unobscured and
9151 obscured frames, but zero for hidden and iconified frames. */
9152 if (FRAME_W32_P (f) && f->async_visible)
9153 {
9154 RECT clipbox;
66e5868a
AI
9155 HDC hdc;
9156
9157 enter_crit ();
9158 /* Query clipping rectangle for the entire window area
9159 (GetWindowDC), not just the client portion (GetDC).
9160 Otherwise, the scrollbars and menubar aren't counted as
9161 part of the visible area of the frame, and we may think
9162 the frame is obscured when really a scrollbar is still
9163 visible and gets WM_PAINT messages above. */
9164 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
689004fa 9165 GetClipBox (hdc, &clipbox);
66e5868a
AI
9166 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
9167 leave_crit ();
689004fa
GV
9168
9169 if (clipbox.right == clipbox.left
9170 || clipbox.bottom == clipbox.top)
9171 {
9172 /* Frame has become completely obscured so mark as
9173 such (we do this by setting async_visible to 2 so
9174 that FRAME_VISIBLE_P is still true, but redisplay
9175 will skip it). */
9176 f->async_visible = 2;
9177
9178 if (!FRAME_OBSCURED_P (f))
9179 {
8f860180 9180 DebPrint (("frame %p (%s) obscured\n", f,
689004fa
GV
9181 XSTRING (f->name)->data));
9182 }
9183 }
9184 else
9185 {
9186 /* Frame is not obscured, so mark it as such. */
9187 f->async_visible = 1;
9188
9189 if (FRAME_OBSCURED_P (f))
9190 {
9191 SET_FRAME_GARBAGED (f);
8f860180 9192 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
689004fa
GV
9193 XSTRING (f->name)->data));
9194
9195 /* Force a redisplay sooner or later. */
9196 record_asynch_buffer_change ();
9197 }
9198 }
9199 }
9200 }
9201 }
9202
ee78dc32
GV
9203 UNBLOCK_INPUT;
9204 return count;
9205}
791f420f 9206
9ef2e2cf
JR
9207
9208
ee78dc32 9209\f
791f420f
JR
9210/***********************************************************************
9211 Text Cursor
9212 ***********************************************************************/
9213
6ff3e5e3
JR
9214/* Notice if the text cursor of window W has been overwritten by a
9215 drawing operation that outputs glyphs starting at START_X and
9216 ending at END_X in the line given by output_cursor.vpos.
9217 Coordinates are area-relative. END_X < 0 means all the rest
9218 of the line after START_X has been written. */
791f420f
JR
9219
9220static void
6637c996 9221notice_overwritten_cursor (w, area, x0, x1, y0, y1)
791f420f 9222 struct window *w;
6637c996
JR
9223 enum glyph_row_area area;
9224 int x0, x1, y0, y1;
791f420f 9225{
6637c996 9226 if (area == TEXT_AREA
6ff3e5e3 9227 && w->phys_cursor_on_p
6637c996
JR
9228 && y0 <= w->phys_cursor.y
9229 && y1 >= w->phys_cursor.y + w->phys_cursor_height
9230 && x0 <= w->phys_cursor.x
9231 && (x1 < 0 || x1 > w->phys_cursor.x))
791f420f
JR
9232 w->phys_cursor_on_p = 0;
9233}
9234
ee78dc32 9235
791f420f
JR
9236/* Set clipping for output in glyph row ROW. W is the window in which
9237 we operate. GC is the graphics context to set clipping in.
9238 WHOLE_LINE_P non-zero means include the areas used for truncation
9239 mark display and alike in the clipping rectangle.
ee78dc32 9240
791f420f
JR
9241 ROW may be a text row or, e.g., a mode line. Text rows must be
9242 clipped to the interior of the window dedicated to text display,
9243 mode lines must be clipped to the whole window. */
ee78dc32
GV
9244
9245static void
791f420f
JR
9246w32_clip_to_row (w, row, hdc, whole_line_p)
9247 struct window *w;
9248 struct glyph_row *row;
9249 HDC hdc;
9250 int whole_line_p;
ee78dc32 9251{
791f420f
JR
9252 struct frame *f = XFRAME (WINDOW_FRAME (w));
9253 RECT clip_rect;
9254 int window_x, window_y, window_width, window_height;
52cf03a1 9255
791f420f 9256 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
52cf03a1 9257
791f420f
JR
9258 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9259 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9260 clip_rect.top = max (clip_rect.top, window_y);
9261 clip_rect.right = clip_rect.left + window_width;
9262 clip_rect.bottom = clip_rect.top + row->visible_height;
9263
9264 /* If clipping to the whole line, including trunc marks, extend
9ef2e2cf 9265 the rectangle to the left and increase its width. */
791f420f
JR
9266 if (whole_line_p)
9267 {
33c34bea
KS
9268 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
9269 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
791f420f
JR
9270 }
9271
9272 w32_set_clip_rectangle (hdc, &clip_rect);
ee78dc32
GV
9273}
9274
791f420f
JR
9275
9276/* Draw a hollow box cursor on window W in glyph row ROW. */
ee78dc32
GV
9277
9278static void
791f420f
JR
9279x_draw_hollow_cursor (w, row)
9280 struct window *w;
9281 struct glyph_row *row;
ee78dc32 9282{
791f420f 9283 struct frame *f = XFRAME (WINDOW_FRAME (w));
988646fc 9284 HDC hdc;
791f420f
JR
9285 RECT rect;
9286 int wd;
9287 struct glyph *cursor_glyph;
9288 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
9289
9290 /* Compute frame-relative coordinates from window-relative
9291 coordinates. */
9292 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9293 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9294 + row->ascent - w->phys_cursor_ascent);
9295 rect.bottom = rect.top + row->height - 1;
9296
9297 /* Get the glyph the cursor is on. If we can't tell because
9298 the current matrix is invalid or such, give up. */
9299 cursor_glyph = get_phys_cursor_glyph (w);
9300 if (cursor_glyph == NULL)
ee78dc32
GV
9301 return;
9302
791f420f
JR
9303 /* Compute the width of the rectangle to draw. If on a stretch
9304 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9305 rectangle as wide as the glyph, but use a canonical character
9306 width instead. */
9307 wd = cursor_glyph->pixel_width - 1;
9308 if (cursor_glyph->type == STRETCH_GLYPH
9309 && !x_stretch_cursor_p)
9310 wd = min (CANON_X_UNIT (f), wd);
9311
9312 rect.right = rect.left + wd;
988646fc 9313 hdc = get_frame_dc (f);
791f420f
JR
9314 FrameRect (hdc, &rect, hb);
9315 DeleteObject (hb);
9316
9317 release_frame_dc (f, hdc);
ee78dc32
GV
9318}
9319
791f420f
JR
9320
9321/* Draw a bar cursor on window W in glyph row ROW.
9322
9323 Implementation note: One would like to draw a bar cursor with an
9324 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9325 Unfortunately, I didn't find a font yet that has this property set.
9326 --gerd. */
ee78dc32
GV
9327
9328static void
9ef2e2cf 9329x_draw_bar_cursor (w, row, width)
791f420f
JR
9330 struct window *w;
9331 struct glyph_row *row;
9ef2e2cf 9332 int width;
ee78dc32 9333{
c2cc16fa
JR
9334 struct frame *f = XFRAME (w->frame);
9335 struct glyph *cursor_glyph;
9336 int x;
9337 HDC hdc;
791f420f 9338
c2cc16fa
JR
9339 /* If cursor is out of bounds, don't draw garbage. This can happen
9340 in mini-buffer windows when switching between echo area glyphs
9341 and mini-buffer. */
9342 cursor_glyph = get_phys_cursor_glyph (w);
9343 if (cursor_glyph == NULL)
9344 return;
9ef2e2cf 9345
c2cc16fa
JR
9346 /* If on an image, draw like a normal cursor. That's usually better
9347 visible than drawing a bar, esp. if the image is large so that
9348 the bar might not be in the window. */
9349 if (cursor_glyph->type == IMAGE_GLYPH)
9350 {
9351 struct glyph_row *row;
9352 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
9353 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
9354 }
9355 else
9356 {
6ff3e5e3
JR
9357 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
9358 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
9359
c2cc16fa
JR
9360 if (width < 0)
9361 width = f->output_data.w32->cursor_width;
158cba56 9362
6ff3e5e3
JR
9363 /* If the glyph's background equals the color we normally draw
9364 the bar cursor in, the bar cursor in its normal color is
9365 invisible. Use the glyph's foreground color instead in this
9366 case, on the assumption that the glyph's colors are chosen so
9367 that the glyph is legible. */
9368 if (face->background == cursor_color)
9369 cursor_color = face->foreground;
9370
c2cc16fa
JR
9371 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9372 hdc = get_frame_dc (f);
9373 w32_clip_to_row (w, row, hdc, 0);
6ff3e5e3 9374 w32_fill_area (f, hdc, cursor_color, x,
c2cc16fa
JR
9375 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9376 min (cursor_glyph->pixel_width, width),
9377 row->height);
9378 release_frame_dc (f, hdc);
791f420f 9379 }
ee78dc32
GV
9380}
9381
791f420f
JR
9382
9383/* Clear the cursor of window W to background color, and mark the
9384 cursor as not shown. This is used when the text where the cursor
9385 is is about to be rewritten. */
9386
ee78dc32 9387static void
791f420f
JR
9388x_clear_cursor (w)
9389 struct window *w;
ee78dc32 9390{
791f420f
JR
9391 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9392 x_update_window_cursor (w, 0);
9393}
ee78dc32 9394
ee78dc32 9395
791f420f
JR
9396/* Draw the cursor glyph of window W in glyph row ROW. See the
9397 comment of x_draw_glyphs for the meaning of HL. */
ee78dc32 9398
791f420f
JR
9399static void
9400x_draw_phys_cursor_glyph (w, row, hl)
9401 struct window *w;
9402 struct glyph_row *row;
9403 enum draw_glyphs_face hl;
9404{
9405 /* If cursor hpos is out of bounds, don't draw garbage. This can
9406 happen in mini-buffer windows when switching between echo area
9407 glyphs and mini-buffer. */
9408 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
ee78dc32 9409 {
6ff3e5e3 9410 int on_p = w->phys_cursor_on_p;
791f420f
JR
9411 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9412 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
6ff3e5e3
JR
9413 hl, 0);
9414 w->phys_cursor_on_p = on_p;
791f420f
JR
9415
9416 /* When we erase the cursor, and ROW is overlapped by other
9417 rows, make sure that these overlapping parts of other rows
9418 are redrawn. */
9419 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9420 {
9421 if (row > w->current_matrix->rows
9422 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9423 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9424
9425 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9426 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9427 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9428 }
ee78dc32 9429 }
791f420f 9430}
ee78dc32 9431
791f420f
JR
9432
9433/* Erase the image of a cursor of window W from the screen. */
9434
9435static void
9436x_erase_phys_cursor (w)
9437 struct window *w;
9438{
9439 struct frame *f = XFRAME (w->frame);
9440 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9441 int hpos = w->phys_cursor.hpos;
9442 int vpos = w->phys_cursor.vpos;
9443 int mouse_face_here_p = 0;
9444 struct glyph_matrix *active_glyphs = w->current_matrix;
9445 struct glyph_row *cursor_row;
9446 struct glyph *cursor_glyph;
9447 enum draw_glyphs_face hl;
9448
9449 /* No cursor displayed or row invalidated => nothing to do on the
9450 screen. */
9451 if (w->phys_cursor_type == NO_CURSOR)
9452 goto mark_cursor_off;
9453
9454 /* VPOS >= active_glyphs->nrows means that window has been resized.
9455 Don't bother to erase the cursor. */
9456 if (vpos >= active_glyphs->nrows)
9457 goto mark_cursor_off;
9458
9459 /* If row containing cursor is marked invalid, there is nothing we
9460 can do. */
9461 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9462 if (!cursor_row->enabled_p)
9463 goto mark_cursor_off;
9464
9465 /* This can happen when the new row is shorter than the old one.
9466 In this case, either x_draw_glyphs or clear_end_of_line
9467 should have cleared the cursor. Note that we wouldn't be
9468 able to erase the cursor in this case because we don't have a
9469 cursor glyph at hand. */
9470 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9471 goto mark_cursor_off;
9472
9473 /* If the cursor is in the mouse face area, redisplay that when
9474 we clear the cursor. */
c2cc16fa
JR
9475 if (! NILP (dpyinfo->mouse_face_window)
9476 && w == XWINDOW (dpyinfo->mouse_face_window)
791f420f
JR
9477 && (vpos > dpyinfo->mouse_face_beg_row
9478 || (vpos == dpyinfo->mouse_face_beg_row
9479 && hpos >= dpyinfo->mouse_face_beg_col))
9480 && (vpos < dpyinfo->mouse_face_end_row
9481 || (vpos == dpyinfo->mouse_face_end_row
9482 && hpos < dpyinfo->mouse_face_end_col))
9483 /* Don't redraw the cursor's spot in mouse face if it is at the
9484 end of a line (on a newline). The cursor appears there, but
9485 mouse highlighting does not. */
9486 && cursor_row->used[TEXT_AREA] > hpos)
9487 mouse_face_here_p = 1;
9488
9489 /* Maybe clear the display under the cursor. */
9490 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
ee78dc32 9491 {
791f420f
JR
9492 int x;
9493 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
00fe468b 9494 HDC hdc;
ee78dc32 9495
791f420f
JR
9496 cursor_glyph = get_phys_cursor_glyph (w);
9497 if (cursor_glyph == NULL)
9498 goto mark_cursor_off;
ee78dc32 9499
791f420f 9500 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
00fe468b
JR
9501
9502 hdc = get_frame_dc (f);
9503 w32_clear_area (f, hdc, x,
791f420f
JR
9504 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9505 cursor_row->y)),
9506 cursor_glyph->pixel_width,
9507 cursor_row->visible_height);
00fe468b 9508 release_frame_dc (f, hdc);
ee78dc32 9509 }
791f420f
JR
9510
9511 /* Erase the cursor by redrawing the character underneath it. */
9512 if (mouse_face_here_p)
9513 hl = DRAW_MOUSE_FACE;
791f420f
JR
9514 else
9515 hl = DRAW_NORMAL_TEXT;
9516 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9517
9518 mark_cursor_off:
9519 w->phys_cursor_on_p = 0;
9520 w->phys_cursor_type = NO_CURSOR;
ee78dc32
GV
9521}
9522
9523
9f5a911b
JR
9524/* Non-zero if physical cursor of window W is within mouse face. */
9525
9526static int
9527cursor_in_mouse_face_p (w)
9528 struct window *w;
9529{
9530 struct w32_display_info *dpyinfo
9531 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
9532 int in_mouse_face = 0;
9533
9534 if (WINDOWP (dpyinfo->mouse_face_window)
9535 && XWINDOW (dpyinfo->mouse_face_window) == w)
9536 {
9537 int hpos = w->phys_cursor.hpos;
9538 int vpos = w->phys_cursor.vpos;
9539
9540 if (vpos >= dpyinfo->mouse_face_beg_row
9541 && vpos <= dpyinfo->mouse_face_end_row
9542 && (vpos > dpyinfo->mouse_face_beg_row
9543 || hpos >= dpyinfo->mouse_face_beg_col)
9544 && (vpos < dpyinfo->mouse_face_end_row
9545 || hpos < dpyinfo->mouse_face_end_col
9546 || dpyinfo->mouse_face_past_end))
9547 in_mouse_face = 1;
9548 }
9549
9550 return in_mouse_face;
9551}
9552
9553
791f420f
JR
9554/* Display or clear cursor of window W. If ON is zero, clear the
9555 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9556 where to put the cursor is specified by HPOS, VPOS, X and Y. */
ee78dc32 9557
791f420f
JR
9558void
9559x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9560 struct window *w;
9561 int on, hpos, vpos, x, y;
ee78dc32 9562{
791f420f
JR
9563 struct frame *f = XFRAME (w->frame);
9564 int new_cursor_type;
9ef2e2cf 9565 int new_cursor_width;
791f420f
JR
9566 struct glyph_matrix *current_glyphs;
9567 struct glyph_row *glyph_row;
9568 struct glyph *glyph;
34368a22 9569 int cursor_non_selected;
abb15ebd 9570 int active_cursor = 1;
ee78dc32
GV
9571
9572 /* This is pointless on invisible frames, and dangerous on garbaged
791f420f
JR
9573 windows and frames; in the latter case, the frame or window may
9574 be in the midst of changing its size, and x and y may be off the
9575 window. */
9576 if (! FRAME_VISIBLE_P (f)
9577 || FRAME_GARBAGED_P (f)
9578 || vpos >= w->current_matrix->nrows
9579 || hpos >= w->current_matrix->matrix_w)
ee78dc32
GV
9580 return;
9581
9582 /* If cursor is off and we want it off, return quickly. */
791f420f 9583 if (!on && !w->phys_cursor_on_p)
ee78dc32
GV
9584 return;
9585
791f420f
JR
9586 current_glyphs = w->current_matrix;
9587 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9588 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9589
9590 /* If cursor row is not enabled, we don't really know where to
9591 display the cursor. */
9592 if (!glyph_row->enabled_p)
9593 {
9594 w->phys_cursor_on_p = 0;
9595 return;
9596 }
9597
9598 xassert (interrupt_input_blocked);
9599
9600 /* Set new_cursor_type to the cursor we want to be displayed. In a
9601 mini-buffer window, we want the cursor only to appear if we are
9602 reading input from this window. For the selected window, we want
9603 the cursor type given by the frame parameter. If explicitly
9604 marked off, draw no cursor. In all other cases, we want a hollow
9605 box cursor. */
34368a22 9606 cursor_non_selected
b116830b 9607 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
34368a22 9608 w->buffer));
9ef2e2cf 9609 new_cursor_width = -1;
791f420f
JR
9610 if (cursor_in_echo_area
9611 && FRAME_HAS_MINIBUF_P (f)
9612 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9613 {
9614 if (w == XWINDOW (echo_area_window))
9615 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9616 else
abb15ebd 9617 {
6ff3e5e3
JR
9618 if (cursor_non_selected)
9619 new_cursor_type = HOLLOW_BOX_CURSOR;
9620 else
9621 new_cursor_type = NO_CURSOR;
abb15ebd
JR
9622 active_cursor = 0;
9623 }
791f420f
JR
9624 }
9625 else
9626 {
49be9f70
JR
9627 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame
9628 || w != XWINDOW (f->selected_window))
791f420f 9629 {
abb15ebd 9630 active_cursor = 0;
a2bc11d4 9631
9127e20e 9632 if (MINI_WINDOW_P (w)
34368a22 9633 || !cursor_non_selected
9127e20e 9634 || NILP (XBUFFER (w->buffer)->cursor_type))
791f420f
JR
9635 new_cursor_type = NO_CURSOR;
9636 else
9637 new_cursor_type = HOLLOW_BOX_CURSOR;
9638 }
9639 else if (w->cursor_off_p)
9640 new_cursor_type = NO_CURSOR;
9641 else
9ef2e2cf
JR
9642 {
9643 struct buffer *b = XBUFFER (w->buffer);
9644
9645 if (EQ (b->cursor_type, Qt))
9646 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9647 else
9648 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9649 &new_cursor_width);
9650 }
791f420f
JR
9651 }
9652
9653 /* If cursor is currently being shown and we don't want it to be or
9654 it is in the wrong place, or the cursor type is not what we want,
ee78dc32 9655 erase it. */
791f420f 9656 if (w->phys_cursor_on_p
ee78dc32 9657 && (!on
791f420f
JR
9658 || w->phys_cursor.x != x
9659 || w->phys_cursor.y != y
9660 || new_cursor_type != w->phys_cursor_type))
9661 x_erase_phys_cursor (w);
9662
9663 /* If the cursor is now invisible and we want it to be visible,
9664 display it. */
9665 if (on && !w->phys_cursor_on_p)
9666 {
9667 w->phys_cursor_ascent = glyph_row->ascent;
9668 w->phys_cursor_height = glyph_row->height;
9669
9670 /* Set phys_cursor_.* before x_draw_.* is called because some
9671 of them may need the information. */
9672 w->phys_cursor.x = x;
9673 w->phys_cursor.y = glyph_row->y;
9674 w->phys_cursor.hpos = hpos;
9675 w->phys_cursor.vpos = vpos;
9676 w->phys_cursor_type = new_cursor_type;
9677 w->phys_cursor_on_p = 1;
9678
abb15ebd
JR
9679 /* If this is the active cursor, we need to track it with the
9680 system caret, so third party software like screen magnifiers
9681 and speech synthesizers can follow the cursor. */
9682 if (active_cursor)
9683 {
abb15ebd 9684 struct glyph * cursor_glyph = get_phys_cursor_glyph (w);
1f41b196 9685 if (cursor_glyph)
abb15ebd 9686 {
1f41b196
JR
9687 HWND hwnd = FRAME_W32_WINDOW (f);
9688 int caret_width = cursor_glyph->pixel_width;
9689 w32_system_caret_x
9690 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9691 w32_system_caret_y
9692 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9693 + glyph_row->ascent - w->phys_cursor_ascent);
9694
9695 /* If the size of the active cursor changed, destroy the old
9696 system caret. */
9697 if (w32_system_caret_hwnd
9698 && (w32_system_caret_height != w->phys_cursor_height
9699 || w32_system_caret_width != caret_width))
6637c996 9700 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
1f41b196
JR
9701
9702 if (!w32_system_caret_hwnd)
9703 {
9704 w32_system_caret_height = w->phys_cursor_height;
9705 w32_system_caret_width = caret_width;
9706 }
abb15ebd 9707
1f41b196 9708 /* Move the system caret. */
6637c996 9709 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
1f41b196 9710 }
abb15ebd
JR
9711 }
9712
791f420f 9713 switch (new_cursor_type)
ee78dc32 9714 {
791f420f
JR
9715 case HOLLOW_BOX_CURSOR:
9716 x_draw_hollow_cursor (w, glyph_row);
9717 break;
9718
9719 case FILLED_BOX_CURSOR:
9720 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9721 break;
9722
9723 case BAR_CURSOR:
9ef2e2cf 9724 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
791f420f 9725 break;
ee78dc32 9726
791f420f
JR
9727 case NO_CURSOR:
9728 break;
9729
9730 default:
9731 abort ();
9732 }
ee78dc32
GV
9733 }
9734}
9735
689004fa 9736
791f420f
JR
9737/* Display the cursor on window W, or clear it. X and Y are window
9738 relative pixel coordinates. HPOS and VPOS are glyph matrix
9739 positions. If W is not the selected window, display a hollow
9740 cursor. ON non-zero means display the cursor at X, Y which
9741 correspond to HPOS, VPOS, otherwise it is cleared. */
9742
9743void
9744x_display_cursor (w, on, hpos, vpos, x, y)
9745 struct window *w;
9746 int on, hpos, vpos, x, y;
ee78dc32
GV
9747{
9748 BLOCK_INPUT;
791f420f
JR
9749 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9750 UNBLOCK_INPUT;
9751}
9752
9753
9754/* Display the cursor on window W, or clear it, according to ON_P.
9755 Don't change the cursor's position. */
9756
9757void
9758x_update_cursor (f, on_p)
9759 struct frame *f;
9760 int on_p;
9761{
9762 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9763}
9764
9765
9766/* Call x_update_window_cursor with parameter ON_P on all leaf windows
9767 in the window tree rooted at W. */
ee78dc32 9768
791f420f
JR
9769static void
9770x_update_cursor_in_window_tree (w, on_p)
9771 struct window *w;
9772 int on_p;
9773{
9774 while (w)
689004fa 9775 {
791f420f
JR
9776 if (!NILP (w->hchild))
9777 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9778 else if (!NILP (w->vchild))
9779 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9780 else
9781 x_update_window_cursor (w, on_p);
9782
9783 w = NILP (w->next) ? 0 : XWINDOW (w->next);
689004fa 9784 }
791f420f 9785}
689004fa 9786
ee78dc32 9787
791f420f
JR
9788/* Switch the display of W's cursor on or off, according to the value
9789 of ON. */
9790
9791static void
9792x_update_window_cursor (w, on)
9793 struct window *w;
9794 int on;
9795{
9ef2e2cf
JR
9796 /* Don't update cursor in windows whose frame is in the process
9797 of being deleted. */
9798 if (w->current_matrix)
9799 {
9800 BLOCK_INPUT;
9801 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9802 w->phys_cursor.vpos, w->phys_cursor.x,
9803 w->phys_cursor.y);
9804 UNBLOCK_INPUT;
9805 }
ee78dc32 9806}
791f420f
JR
9807
9808
9ef2e2cf 9809
ee78dc32 9810\f
7f5d1df8
GV
9811/* Icons. */
9812
9813int
9814x_bitmap_icon (f, icon)
9815 struct frame *f;
9816 Lisp_Object icon;
9817{
7f5d1df8
GV
9818 HANDLE hicon;
9819
9820 if (FRAME_W32_WINDOW (f) == 0)
9821 return 1;
9822
9823 if (NILP (icon))
9824 hicon = LoadIcon (hinst, EMACS_CLASS);
9825 else if (STRINGP (icon))
9826 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
9827 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9828 else if (SYMBOLP (icon))
9829 {
9830 LPCTSTR name;
9831
9832 if (EQ (icon, intern ("application")))
9833 name = (LPCTSTR) IDI_APPLICATION;
9834 else if (EQ (icon, intern ("hand")))
9835 name = (LPCTSTR) IDI_HAND;
9836 else if (EQ (icon, intern ("question")))
9837 name = (LPCTSTR) IDI_QUESTION;
9838 else if (EQ (icon, intern ("exclamation")))
9839 name = (LPCTSTR) IDI_EXCLAMATION;
9840 else if (EQ (icon, intern ("asterisk")))
9841 name = (LPCTSTR) IDI_ASTERISK;
9842 else if (EQ (icon, intern ("winlogo")))
9843 name = (LPCTSTR) IDI_WINLOGO;
9844 else
9845 return 1;
9846
9847 hicon = LoadIcon (NULL, name);
9848 }
9849 else
9850 return 1;
9851
9852 if (hicon == NULL)
9853 return 1;
9854
791f420f
JR
9855 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9856 (LPARAM) hicon);
7f5d1df8
GV
9857
9858 return 0;
9859}
9860
9861\f
c2cc16fa
JR
9862/************************************************************************
9863 Handling X errors
9864 ************************************************************************/
9865
9866/* Display Error Handling functions not used on W32. Listing them here
9867 helps diff stay in step when comparing w32term.c with xterm.c.
9868
9869x_error_catcher (display, error)
9870x_catch_errors (dpy)
9871x_catch_errors_unwind (old_val)
9872x_check_errors (dpy, format)
9873x_had_errors_p (dpy)
9874x_clear_errors (dpy)
9875x_uncatch_errors (dpy, count)
9876x_trace_wire ()
9877x_connection_signal (signalnum)
9878x_connection_closed (dpy, error_message)
9879x_error_quitter (display, error)
9880x_error_handler (display, error)
9881x_io_error_quitter (display)
9882
9883 */
9884
9885\f
ee78dc32
GV
9886/* Changing the font of the frame. */
9887
9888/* Give frame F the font named FONTNAME as its default font, and
9889 return the full name of that font. FONTNAME may be a wildcard
9890 pattern; in that case, we choose some font that fits the pattern.
9891 The return value shows which font we chose. */
9892
9893Lisp_Object
9894x_new_font (f, fontname)
9895 struct frame *f;
9896 register char *fontname;
9897{
cabb23bc 9898 struct font_info *fontp
93ff4395 9899 = FS_LOAD_FONT (f, 0, fontname, -1);
ee78dc32 9900
cabb23bc 9901 if (!fontp)
791f420f 9902 return Qnil;
ee78dc32 9903
cabb23bc 9904 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
791f420f 9905 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
cabb23bc 9906 FRAME_FONTSET (f) = -1;
ee78dc32
GV
9907
9908 /* Compute the scroll bar width in character columns. */
9909 if (f->scroll_bar_pixel_width > 0)
9910 {
ec48c3a7 9911 int wid = FONT_WIDTH (FRAME_FONT (f));
ee78dc32
GV
9912 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9913 }
9914 else
ec48c3a7
JR
9915 {
9916 int wid = FONT_WIDTH (FRAME_FONT (f));
9917 f->scroll_bar_cols = (14 + wid - 1) / wid;
9918 }
ee78dc32
GV
9919
9920 /* Now make the frame display the given font. */
fbd6baed 9921 if (FRAME_W32_WINDOW (f) != 0)
ee78dc32
GV
9922 {
9923 frame_update_line_height (f);
49be9f70
JR
9924 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9925 x_set_window_size (f, 0, f->width, f->height);
ee78dc32
GV
9926 }
9927 else
9928 /* If we are setting a new frame's font for the first time,
9929 there are no faces yet, so this font's height is the line height. */
ec48c3a7 9930 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
ee78dc32 9931
791f420f 9932 return build_string (fontp->full_name);
ee78dc32
GV
9933}
9934\f
cabb23bc
GV
9935/* Give frame F the fontset named FONTSETNAME as its default font, and
9936 return the full name of that fontset. FONTSETNAME may be a wildcard
9937 pattern; in that case, we choose some fontset that fits the pattern.
9938 The return value shows which fontset we chose. */
9939
9940Lisp_Object
9941x_new_fontset (f, fontsetname)
9942 struct frame *f;
9943 char *fontsetname;
9944{
93ff4395 9945 int fontset = fs_query_fontset (build_string (fontsetname), 0);
cabb23bc
GV
9946 Lisp_Object result;
9947
9948 if (fontset < 0)
9949 return Qnil;
9950
9951 if (FRAME_FONTSET (f) == fontset)
9952 /* This fontset is already set in frame F. There's nothing more
9953 to do. */
93ff4395 9954 return fontset_name (fontset);
cabb23bc 9955
93ff4395 9956 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
cabb23bc
GV
9957
9958 if (!STRINGP (result))
9959 /* Can't load ASCII font. */
9960 return Qnil;
9961
9962 /* Since x_new_font doesn't update any fontset information, do it now. */
9963 FRAME_FONTSET(f) = fontset;
cabb23bc
GV
9964
9965 return build_string (fontsetname);
9966}
791f420f 9967
d33c49e8
KS
9968/* Compute actual fringe widths */
9969
9970void
9971x_compute_fringe_widths (f, redraw)
9972 struct frame *f;
9973 int redraw;
9974{
9975 int o_left = f->output_data.w32->left_fringe_width;
9976 int o_right = f->output_data.w32->right_fringe_width;
9977 int o_cols = f->output_data.w32->fringe_cols;
9978
9979 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9980 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9981 int left_fringe_width, right_fringe_width;
9982
9983 if (!NILP (left_fringe))
9984 left_fringe = Fcdr (left_fringe);
9985 if (!NILP (right_fringe))
9986 right_fringe = Fcdr (right_fringe);
9987
9988 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9989 XINT (left_fringe));
9990 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9991 XINT (right_fringe));
9992
9993 if (left_fringe_width || right_fringe_width)
9994 {
9995 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9996 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9997 int conf_wid = left_wid + right_wid;
9998 int font_wid = FONT_WIDTH (f->output_data.w32->font);
9999 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
10000 int real_wid = cols * font_wid;
10001 if (left_wid && right_wid)
10002 {
10003 if (left_fringe_width < 0)
10004 {
10005 /* Left fringe width is fixed, adjust right fringe if necessary */
10006 f->output_data.w32->left_fringe_width = left_wid;
10007 f->output_data.w32->right_fringe_width = real_wid - left_wid;
10008 }
10009 else if (right_fringe_width < 0)
10010 {
10011 /* Right fringe width is fixed, adjust left fringe if necessary */
10012 f->output_data.w32->left_fringe_width = real_wid - right_wid;
10013 f->output_data.w32->right_fringe_width = right_wid;
10014 }
10015 else
10016 {
10017 /* Adjust both fringes with an equal amount.
10018 Note that we are doing integer arithmetic here, so don't
10019 lose a pixel if the total width is an odd number. */
10020 int fill = real_wid - conf_wid;
10021 f->output_data.w32->left_fringe_width = left_wid + fill/2;
10022 f->output_data.w32->right_fringe_width = right_wid + fill - fill/2;
10023 }
10024 }
10025 else if (left_fringe_width)
10026 {
10027 f->output_data.w32->left_fringe_width = real_wid;
10028 f->output_data.w32->right_fringe_width = 0;
10029 }
10030 else
10031 {
10032 f->output_data.w32->left_fringe_width = 0;
10033 f->output_data.w32->right_fringe_width = real_wid;
10034 }
10035 f->output_data.w32->fringe_cols = cols;
10036 f->output_data.w32->fringes_extra = real_wid;
10037 }
10038 else
10039 {
10040 f->output_data.w32->left_fringe_width = 0;
10041 f->output_data.w32->right_fringe_width = 0;
10042 f->output_data.w32->fringe_cols = 0;
10043 f->output_data.w32->fringes_extra = 0;
10044 }
10045
10046 if (redraw && FRAME_VISIBLE_P (f))
10047 if (o_left != f->output_data.w32->left_fringe_width ||
10048 o_right != f->output_data.w32->right_fringe_width ||
10049 o_cols != f->output_data.w32->fringe_cols)
10050 redraw_frame (f);
10051}
c2cc16fa
JR
10052\f
10053/***********************************************************************
10054 TODO: W32 Input Methods
10055 ***********************************************************************/
10056/* Listing missing functions from xterm.c helps diff stay in step.
791f420f 10057
c2cc16fa
JR
10058xim_destroy_callback (xim, client_data, call_data)
10059xim_open_dpy (dpyinfo, resource_name)
10060struct xim_inst_t
10061xim_instantiate_callback (display, client_data, call_data)
10062xim_initialize (dpyinfo, resource_name)
10063xim_close_dpy (dpyinfo)
791f420f 10064
c2cc16fa 10065 */
791f420f 10066
cabb23bc 10067\f
689004fa
GV
10068/* Calculate the absolute position in frame F
10069 from its current recorded position values and gravity. */
10070
9ef2e2cf 10071void
ee78dc32
GV
10072x_calc_absolute_position (f)
10073 struct frame *f;
10074{
ee78dc32 10075 POINT pt;
fbd6baed 10076 int flags = f->output_data.w32->size_hint_flags;
ee78dc32
GV
10077
10078 pt.x = pt.y = 0;
10079
10080 /* Find the position of the outside upper-left corner of
c2cc16fa
JR
10081 the inner window, with respect to the outer window.
10082 But do this only if we will need the results. */
fbd6baed 10083 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
ee78dc32
GV
10084 {
10085 BLOCK_INPUT;
fbd6baed
GV
10086 MapWindowPoints (FRAME_W32_WINDOW (f),
10087 f->output_data.w32->parent_desc,
ee78dc32
GV
10088 &pt, 1);
10089 UNBLOCK_INPUT;
10090 }
10091
10092 {
10093 RECT rt;
10094 rt.left = rt.right = rt.top = rt.bottom = 0;
10095
10096 BLOCK_INPUT;
fbd6baed 10097 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
97c23857 10098 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32
GV
10099 UNBLOCK_INPUT;
10100
10101 pt.x += (rt.right - rt.left);
10102 pt.y += (rt.bottom - rt.top);
10103 }
10104
10105 /* Treat negative positions as relative to the leftmost bottommost
10106 position that fits on the screen. */
10107 if (flags & XNegative)
fbd6baed
GV
10108 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
10109 - 2 * f->output_data.w32->border_width - pt.x
ee78dc32 10110 - PIXEL_WIDTH (f)
fbd6baed 10111 + f->output_data.w32->left_pos);
158cba56 10112
ee78dc32 10113 if (flags & YNegative)
fbd6baed
GV
10114 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
10115 - 2 * f->output_data.w32->border_width - pt.y
ee78dc32 10116 - PIXEL_HEIGHT (f)
fbd6baed 10117 + f->output_data.w32->top_pos);
ee78dc32
GV
10118 /* The left_pos and top_pos
10119 are now relative to the top and left screen edges,
10120 so the flags should correspond. */
fbd6baed 10121 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32
GV
10122}
10123
10124/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10125 to really change the position, and 0 when calling from
10126 x_make_frame_visible (in that case, XOFF and YOFF are the current
10127 position values). It is -1 when calling from x_set_frame_parameters,
10128 which means, do adjust for borders but don't change the gravity. */
10129
9ef2e2cf 10130void
ee78dc32
GV
10131x_set_offset (f, xoff, yoff, change_gravity)
10132 struct frame *f;
10133 register int xoff, yoff;
10134 int change_gravity;
10135{
10136 int modified_top, modified_left;
10137
10138 if (change_gravity > 0)
10139 {
fbd6baed
GV
10140 f->output_data.w32->top_pos = yoff;
10141 f->output_data.w32->left_pos = xoff;
10142 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
ee78dc32 10143 if (xoff < 0)
fbd6baed 10144 f->output_data.w32->size_hint_flags |= XNegative;
ee78dc32 10145 if (yoff < 0)
fbd6baed
GV
10146 f->output_data.w32->size_hint_flags |= YNegative;
10147 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
10148 }
10149 x_calc_absolute_position (f);
10150
10151 BLOCK_INPUT;
10152 x_wm_set_size_hint (f, (long) 0, 0);
10153
fbd6baed
GV
10154 modified_left = f->output_data.w32->left_pos;
10155 modified_top = f->output_data.w32->top_pos;
ee78dc32 10156
fbd6baed 10157 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
10158 NULL,
10159 modified_left, modified_top,
cabb23bc 10160 0, 0,
689004fa 10161 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
ee78dc32
GV
10162 UNBLOCK_INPUT;
10163}
10164
10165/* Call this to change the size of frame F's x-window.
10166 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10167 for this size change and subsequent size changes.
10168 Otherwise we leave the window gravity unchanged. */
c2cc16fa 10169
791f420f 10170void
ee78dc32
GV
10171x_set_window_size (f, change_gravity, cols, rows)
10172 struct frame *f;
10173 int change_gravity;
10174 int cols, rows;
10175{
10176 int pixelwidth, pixelheight;
10177
10178 BLOCK_INPUT;
10179
10180 check_frame_size (f, &rows, &cols);
fbd6baed 10181 f->output_data.w32->vertical_scroll_bar_extra
ee78dc32
GV
10182 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10183 ? 0
fbd6baed 10184 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
d33c49e8
KS
10185
10186 x_compute_fringe_widths (f, 0);
10187
ee78dc32
GV
10188 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10189 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
10190
fbd6baed 10191 f->output_data.w32->win_gravity = NorthWestGravity;
ee78dc32
GV
10192 x_wm_set_size_hint (f, (long) 0, 0);
10193
10194 {
10195 RECT rect;
10196
10197 rect.left = rect.top = 0;
10198 rect.right = pixelwidth;
10199 rect.bottom = pixelheight;
10200
fbd6baed 10201 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
97c23857 10202 FRAME_EXTERNAL_MENU_BAR (f));
ee78dc32 10203
fbd6baed 10204 my_set_window_pos (FRAME_W32_WINDOW (f),
52cf03a1
GV
10205 NULL,
10206 0, 0,
689004fa
GV
10207 rect.right - rect.left,
10208 rect.bottom - rect.top,
10209 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
ee78dc32
GV
10210 }
10211
10212 /* Now, strictly speaking, we can't be sure that this is accurate,
10213 but the window manager will get around to dealing with the size
10214 change request eventually, and we'll hear how it went when the
10215 ConfigureNotify event gets here.
10216
10217 We could just not bother storing any of this information here,
10218 and let the ConfigureNotify event set everything up, but that
ec48c3a7 10219 might be kind of confusing to the Lisp code, since size changes
ee78dc32 10220 wouldn't be reported in the frame parameters until some random
791f420f
JR
10221 point in the future when the ConfigureNotify event arrives.
10222
10223 We pass 1 for DELAY since we can't run Lisp code inside of
10224 a BLOCK_INPUT. */
10225 change_frame_size (f, rows, cols, 0, 1, 0);
ee78dc32
GV
10226 PIXEL_WIDTH (f) = pixelwidth;
10227 PIXEL_HEIGHT (f) = pixelheight;
10228
689004fa
GV
10229 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10230 receive in the ConfigureNotify event; if we get what we asked
10231 for, then the event won't cause the screen to become garbaged, so
10232 we have to make sure to do it here. */
10233 SET_FRAME_GARBAGED (f);
10234
ee78dc32 10235 /* If cursor was outside the new size, mark it as off. */
791f420f 10236 mark_window_cursors_off (XWINDOW (f->root_window));
ee78dc32 10237
689004fa
GV
10238 /* Clear out any recollection of where the mouse highlighting was,
10239 since it might be in a place that's outside the new frame size.
10240 Actually checking whether it is outside is a pain in the neck,
10241 so don't try--just let the highlighting be done afresh with new size. */
31d4844a
KH
10242 cancel_mouse_face (f);
10243
ee78dc32
GV
10244 UNBLOCK_INPUT;
10245}
10246\f
10247/* Mouse warping. */
10248
ec48c3a7
JR
10249void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
10250
10251void
10252x_set_mouse_position (f, x, y)
10253 struct frame *f;
10254 int x, y;
10255{
10256 int pix_x, pix_y;
10257
10258 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
10259 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
10260
10261 if (pix_x < 0) pix_x = 0;
10262 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10263
10264 if (pix_y < 0) pix_y = 0;
10265 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
10266
10267 x_set_mouse_pixel_position (f, pix_x, pix_y);
10268}
10269
1bcd16f2
MB
10270void
10271x_set_mouse_pixel_position (f, pix_x, pix_y)
10272 struct frame *f;
10273 int pix_x, pix_y;
10274{
689004fa
GV
10275 RECT rect;
10276 POINT pt;
10277
1bcd16f2
MB
10278 BLOCK_INPUT;
10279
689004fa
GV
10280 GetClientRect (FRAME_W32_WINDOW (f), &rect);
10281 pt.x = rect.left + pix_x;
10282 pt.y = rect.top + pix_y;
10283 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
1bcd16f2 10284
689004fa 10285 SetCursorPos (pt.x, pt.y);
1bcd16f2
MB
10286
10287 UNBLOCK_INPUT;
10288}
10289
ee78dc32
GV
10290\f
10291/* focus shifting, raising and lowering. */
10292
ec48c3a7 10293void
ee78dc32
GV
10294x_focus_on_frame (f)
10295 struct frame *f;
10296{
689004fa
GV
10297 struct w32_display_info *dpyinfo = &one_w32_display_info;
10298
10299 /* Give input focus to frame. */
10300 BLOCK_INPUT;
10301#if 0
10302 /* Try not to change its Z-order if possible. */
10303 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
10304 my_set_focus (f, FRAME_W32_WINDOW (f));
10305 else
10306#endif
ef0e360f 10307 my_set_foreground_window (FRAME_W32_WINDOW (f));
689004fa 10308 UNBLOCK_INPUT;
ee78dc32
GV
10309}
10310
ec48c3a7 10311void
ee78dc32
GV
10312x_unfocus_frame (f)
10313 struct frame *f;
10314{
10315}
10316
10317/* Raise frame F. */
791f420f 10318void
ee78dc32
GV
10319x_raise_frame (f)
10320 struct frame *f;
10321{
689004fa
GV
10322 BLOCK_INPUT;
10323
10324 /* Strictly speaking, raise-frame should only change the frame's Z
10325 order, leaving input focus unchanged. This is reasonable behaviour
10326 on X where the usual policy is point-to-focus. However, this
10327 behaviour would be very odd on Windows where the usual policy is
10328 click-to-focus.
10329
10330 On X, if the mouse happens to be over the raised frame, it gets
10331 input focus anyway (so the window with focus will never be
10332 completely obscured) - if not, then just moving the mouse over it
10333 is sufficient to give it focus. On Windows, the user must actually
10334 click on the frame (preferrably the title bar so as not to move
10335 point), which is more awkward. Also, no other Windows program
10336 raises a window to the top but leaves another window (possibly now
10337 completely obscured) with input focus.
10338
10339 Because there is a system setting on Windows that allows the user
10340 to choose the point to focus policy, we make the strict semantics
10341 optional, but by default we grab focus when raising. */
10342
10343 if (NILP (Vw32_grab_focus_on_raise))
ee78dc32 10344 {
689004fa
GV
10345 /* The obvious call to my_set_window_pos doesn't work if Emacs is
10346 not already the foreground application: the frame is raised
10347 above all other frames belonging to us, but not above the
10348 current top window. To achieve that, we have to resort to this
10349 more cumbersome method. */
10350
10351 HDWP handle = BeginDeferWindowPos (2);
10352 if (handle)
10353 {
10354 DeferWindowPos (handle,
10355 FRAME_W32_WINDOW (f),
10356 HWND_TOP,
10357 0, 0, 0, 0,
10358 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10359
10360 DeferWindowPos (handle,
10361 GetForegroundWindow (),
10362 FRAME_W32_WINDOW (f),
10363 0, 0, 0, 0,
10364 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10365
10366 EndDeferWindowPos (handle);
10367 }
ee78dc32 10368 }
689004fa
GV
10369 else
10370 {
ef0e360f 10371 my_set_foreground_window (FRAME_W32_WINDOW (f));
689004fa
GV
10372 }
10373
10374 UNBLOCK_INPUT;
ee78dc32
GV
10375}
10376
10377/* Lower frame F. */
791f420f 10378void
ee78dc32
GV
10379x_lower_frame (f)
10380 struct frame *f;
10381{
689004fa
GV
10382 BLOCK_INPUT;
10383 my_set_window_pos (FRAME_W32_WINDOW (f),
10384 HWND_BOTTOM,
10385 0, 0, 0, 0,
10386 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10387 UNBLOCK_INPUT;
ee78dc32
GV
10388}
10389
10390static void
ec48c3a7 10391w32_frame_raise_lower (f, raise_flag)
ee78dc32 10392 FRAME_PTR f;
ec48c3a7 10393 int raise_flag;
ee78dc32 10394{
7e6ac5b9
AI
10395 if (! FRAME_W32_P (f))
10396 return;
10397
ec48c3a7 10398 if (raise_flag)
ee78dc32
GV
10399 x_raise_frame (f);
10400 else
10401 x_lower_frame (f);
10402}
10403\f
10404/* Change of visibility. */
10405
10406/* This tries to wait until the frame is really visible.
10407 However, if the window manager asks the user where to position
10408 the frame, this will return before the user finishes doing that.
10409 The frame will not actually be visible at that time,
10410 but it will become visible later when the window manager
10411 finishes with it. */
10412
ec48c3a7 10413void
ee78dc32
GV
10414x_make_frame_visible (f)
10415 struct frame *f;
10416{
7f5d1df8
GV
10417 Lisp_Object type;
10418
ee78dc32
GV
10419 BLOCK_INPUT;
10420
7f5d1df8
GV
10421 type = x_icon_type (f);
10422 if (!NILP (type))
10423 x_bitmap_icon (f, type);
10424
ee78dc32
GV
10425 if (! FRAME_VISIBLE_P (f))
10426 {
10427 /* We test FRAME_GARBAGED_P here to make sure we don't
10428 call x_set_offset a second time
10429 if we get to x_make_frame_visible a second time
10430 before the window gets really visible. */
10431 if (! FRAME_ICONIFIED_P (f)
fbd6baed 10432 && ! f->output_data.w32->asked_for_visible)
fbd6baed 10433 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
ee78dc32 10434
fbd6baed 10435 f->output_data.w32->asked_for_visible = 1;
52cf03a1 10436
689004fa
GV
10437// my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
10438 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
ee78dc32
GV
10439 }
10440
10441 /* Synchronize to ensure Emacs knows the frame is visible
10442 before we do anything else. We do this loop with input not blocked
10443 so that incoming events are handled. */
10444 {
10445 Lisp_Object frame;
791f420f 10446 int count;
ee78dc32
GV
10447
10448 /* This must come after we set COUNT. */
10449 UNBLOCK_INPUT;
10450
10451 XSETFRAME (frame, f);
10452
791f420f
JR
10453 /* Wait until the frame is visible. Process X events until a
10454 MapNotify event has been seen, or until we think we won't get a
10455 MapNotify at all.. */
10456 for (count = input_signal_count + 10;
10457 input_signal_count < count && !FRAME_VISIBLE_P (f);)
ee78dc32 10458 {
791f420f 10459 /* Force processing of queued events. */
01b220b6 10460 /* TODO: x_sync equivalent? */
791f420f 10461
ee78dc32
GV
10462 /* Machines that do polling rather than SIGIO have been observed
10463 to go into a busy-wait here. So we'll fake an alarm signal
10464 to let the handler know that there's something to be read.
10465 We used to raise a real alarm, but it seems that the handler
10466 isn't always enabled here. This is probably a bug. */
10467 if (input_polling_used ())
10468 {
10469 /* It could be confusing if a real alarm arrives while processing
10470 the fake one. Turn it off and let the handler reset it. */
a9b4e0ec
AI
10471 int old_poll_suppress_count = poll_suppress_count;
10472 poll_suppress_count = 1;
10473 poll_for_input_1 ();
10474 poll_suppress_count = old_poll_suppress_count;
ee78dc32 10475 }
ee78dc32
GV
10476 }
10477 FRAME_SAMPLE_VISIBILITY (f);
10478 }
10479}
10480
10481/* Change from mapped state to withdrawn state. */
10482
10483/* Make the frame visible (mapped and not iconified). */
10484
10485x_make_frame_invisible (f)
10486 struct frame *f;
10487{
ee78dc32 10488 /* Don't keep the highlight on an invisible frame. */
fbd6baed
GV
10489 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
10490 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
ee78dc32
GV
10491
10492 BLOCK_INPUT;
10493
689004fa 10494 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
ee78dc32
GV
10495
10496 /* We can't distinguish this from iconification
10497 just by the event that we get from the server.
10498 So we can't win using the usual strategy of letting
10499 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10500 and synchronize with the server to make sure we agree. */
10501 f->visible = 0;
10502 FRAME_ICONIFIED_P (f) = 0;
10503 f->async_visible = 0;
10504 f->async_iconified = 0;
10505
10506 UNBLOCK_INPUT;
10507}
10508
10509/* Change window state from mapped to iconified. */
10510
52cf03a1
GV
10511void
10512x_iconify_frame (f)
ee78dc32
GV
10513 struct frame *f;
10514{
7f5d1df8 10515 Lisp_Object type;
ee78dc32
GV
10516
10517 /* Don't keep the highlight on an invisible frame. */
fbd6baed
GV
10518 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
10519 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
ee78dc32
GV
10520
10521 if (f->async_iconified)
10522 return;
10523
10524 BLOCK_INPUT;
10525
7f5d1df8
GV
10526 type = x_icon_type (f);
10527 if (!NILP (type))
10528 x_bitmap_icon (f, type);
10529
689004fa 10530 /* Simulate the user minimizing the frame. */
4934bcdd 10531 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
ee78dc32
GV
10532
10533 UNBLOCK_INPUT;
10534}
c2cc16fa 10535
ee78dc32 10536\f
25badd7a 10537/* Free X resources of frame F. */
ee78dc32 10538
25badd7a
AI
10539void
10540x_free_frame_resources (f)
ee78dc32
GV
10541 struct frame *f;
10542{
fbd6baed 10543 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
ee78dc32
GV
10544
10545 BLOCK_INPUT;
10546
25badd7a
AI
10547 if (FRAME_W32_WINDOW (f))
10548 my_destroy_window (f, FRAME_W32_WINDOW (f));
10549
ee78dc32 10550 free_frame_menubar (f);
ee78dc32 10551
25badd7a
AI
10552 unload_color (f, f->output_data.x->foreground_pixel);
10553 unload_color (f, f->output_data.x->background_pixel);
10554 unload_color (f, f->output_data.w32->cursor_pixel);
10555 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
10556 unload_color (f, f->output_data.w32->border_pixel);
10557 unload_color (f, f->output_data.w32->mouse_pixel);
c2cc16fa
JR
10558 if (f->output_data.w32->white_relief.allocated_p)
10559 unload_color (f, f->output_data.w32->white_relief.pixel);
10560 if (f->output_data.w32->black_relief.allocated_p)
10561 unload_color (f, f->output_data.w32->black_relief.pixel);
10562
25badd7a
AI
10563 if (FRAME_FACE_CACHE (f))
10564 free_frame_faces (f);
10565
fbd6baed 10566 xfree (f->output_data.w32);
25badd7a
AI
10567 f->output_data.w32 = NULL;
10568
fbd6baed
GV
10569 if (f == dpyinfo->w32_focus_frame)
10570 dpyinfo->w32_focus_frame = 0;
10571 if (f == dpyinfo->w32_focus_event_frame)
10572 dpyinfo->w32_focus_event_frame = 0;
10573 if (f == dpyinfo->w32_highlight_frame)
10574 dpyinfo->w32_highlight_frame = 0;
ee78dc32 10575
ee78dc32
GV
10576 if (f == dpyinfo->mouse_face_mouse_frame)
10577 {
10578 dpyinfo->mouse_face_beg_row
10579 = dpyinfo->mouse_face_beg_col = -1;
10580 dpyinfo->mouse_face_end_row
10581 = dpyinfo->mouse_face_end_col = -1;
10582 dpyinfo->mouse_face_window = Qnil;
25badd7a
AI
10583 dpyinfo->mouse_face_deferred_gc = 0;
10584 dpyinfo->mouse_face_mouse_frame = 0;
ee78dc32
GV
10585 }
10586
10587 UNBLOCK_INPUT;
10588}
25badd7a
AI
10589
10590
10591/* Destroy the window of frame F. */
10592
10593x_destroy_window (f)
10594 struct frame *f;
10595{
10596 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10597
10598 x_free_frame_resources (f);
10599
10600 dpyinfo->reference_count--;
10601}
c2cc16fa 10602
ee78dc32
GV
10603\f
10604/* Setting window manager hints. */
10605
10606/* Set the normal size hints for the window manager, for frame F.
10607 FLAGS is the flags word to use--or 0 meaning preserve the flags
10608 that the window now has.
10609 If USER_POSITION is nonzero, we set the USPosition
10610 flag (this is useful when FLAGS is 0). */
791f420f 10611void
ee78dc32
GV
10612x_wm_set_size_hint (f, flags, user_position)
10613 struct frame *f;
10614 long flags;
10615 int user_position;
10616{
fbd6baed 10617 Window window = FRAME_W32_WINDOW (f);
ee78dc32 10618
97c23857 10619 enter_crit ();
ee78dc32 10620
689004fa
GV
10621 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
10622 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
10623 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
10624 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
ee78dc32 10625
97c23857 10626 leave_crit ();
ee78dc32
GV
10627}
10628
10629/* Window manager things */
10630x_wm_set_icon_position (f, icon_x, icon_y)
10631 struct frame *f;
10632 int icon_x, icon_y;
10633{
10634#if 0
fbd6baed 10635 Window window = FRAME_W32_WINDOW (f);
ee78dc32
GV
10636
10637 f->display.x->wm_hints.flags |= IconPositionHint;
10638 f->display.x->wm_hints.icon_x = icon_x;
10639 f->display.x->wm_hints.icon_y = icon_y;
10640
10641 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
10642#endif
10643}
10644
c2cc16fa
JR
10645\f
10646/***********************************************************************
10647 Fonts
10648 ***********************************************************************/
10649
10650/* The following functions are listed here to help diff stay in step
10651 with xterm.c. See w32fns.c for definitions.
10652
10653x_get_font_info (f, font_idx)
10654x_list_fonts (f, pattern, size, maxnames)
10655
10656 */
10657
10658#if GLYPH_DEBUG
10659
10660/* Check that FONT is valid on frame F. It is if it can be found in F's
10661 font table. */
10662
10663static void
10664x_check_font (f, font)
10665 struct frame *f;
10666 XFontStruct *font;
10667{
10668 int i;
10669 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10670
10671 xassert (font != NULL);
9ef2e2cf 10672
c2cc16fa
JR
10673 for (i = 0; i < dpyinfo->n_fonts; i++)
10674 if (dpyinfo->font_table[i].name
10675 && font == dpyinfo->font_table[i].font)
10676 break;
10677
10678 xassert (i < dpyinfo->n_fonts);
10679}
10680
10681#endif /* GLYPH_DEBUG != 0 */
10682
10683/* Set *W to the minimum width, *H to the minimum font height of FONT.
10684 Note: There are (broken) X fonts out there with invalid XFontStruct
10685 min_bounds contents. For example, handa@etl.go.jp reports that
10686 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10687 have font->min_bounds.width == 0. */
10688
10689static INLINE void
10690x_font_min_bounds (font, w, h)
10691 XFontStruct *font;
10692 int *w, *h;
10693{
10694 /*
10695 * TODO: Windows does not appear to offer min bound, only
10696 * average and maximum width, and maximum height.
10697 */
10698 *h = FONT_HEIGHT (font);
10699 *w = FONT_WIDTH (font);
10700}
10701
10702
10703/* Compute the smallest character width and smallest font height over
10704 all fonts available on frame F. Set the members smallest_char_width
10705 and smallest_font_height in F's x_display_info structure to
10706 the values computed. Value is non-zero if smallest_font_height or
10707 smallest_char_width become smaller than they were before. */
10708
10709int
10710x_compute_min_glyph_bounds (f)
10711 struct frame *f;
10712{
10713 int i;
10714 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10715 XFontStruct *font;
10716 int old_width = dpyinfo->smallest_char_width;
10717 int old_height = dpyinfo->smallest_font_height;
10718
10719 dpyinfo->smallest_font_height = 100000;
10720 dpyinfo->smallest_char_width = 100000;
10721
10722 for (i = 0; i < dpyinfo->n_fonts; ++i)
10723 if (dpyinfo->font_table[i].name)
10724 {
10725 struct font_info *fontp = dpyinfo->font_table + i;
10726 int w, h;
10727
10728 font = (XFontStruct *) fontp->font;
10729 xassert (font != (XFontStruct *) ~0);
10730 x_font_min_bounds (font, &w, &h);
10731
10732 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10733 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10734 }
10735
10736 xassert (dpyinfo->smallest_char_width > 0
10737 && dpyinfo->smallest_font_height > 0);
10738
10739 return (dpyinfo->n_fonts == 1
10740 || dpyinfo->smallest_char_width < old_width
10741 || dpyinfo->smallest_font_height < old_height);
10742}
10743
10744/* The following functions are listed here to help diff stay in step
10745 with xterm.c. See w32fns.c for definitions.
10746
10747x_load_font (f, fontname, size)
10748x_query_font (f, fontname)
10749x_find_ccl_program (fontp)
10750
10751*/
ee78dc32 10752\f
791f420f
JR
10753/***********************************************************************
10754 Initialization
10755 ***********************************************************************/
ee78dc32 10756
fbd6baed 10757static int w32_initialized = 0;
ee78dc32 10758
f7737f5d
JR
10759void
10760w32_initialize_display_info (display_name)
10761 Lisp_Object display_name;
10762{
10763 struct w32_display_info *dpyinfo = &one_w32_display_info;
10764
10765 bzero (dpyinfo, sizeof (*dpyinfo));
10766
10767 /* Put it on w32_display_name_list. */
10768 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
10769 w32_display_name_list);
10770 dpyinfo->name_list_element = XCAR (w32_display_name_list);
10771
10772 dpyinfo->w32_id_name
10773 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
10774 + XSTRING (Vsystem_name)->size
10775 + 2);
10776 sprintf (dpyinfo->w32_id_name, "%s@%s",
10777 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
10778
10779 /* Default Console mode values - overridden when running in GUI mode
10780 with values obtained from system metrics. */
10781 dpyinfo->resx = 1;
10782 dpyinfo->resy = 1;
10783 dpyinfo->height_in = 1;
10784 dpyinfo->width_in = 1;
10785 dpyinfo->n_planes = 1;
10786 dpyinfo->n_cbits = 4;
10787 dpyinfo->n_fonts = 0;
10788 dpyinfo->smallest_font_height = 1;
10789 dpyinfo->smallest_char_width = 1;
10790
10791 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10792 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10793 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10794 dpyinfo->mouse_face_window = Qnil;
9f5a911b 10795 dpyinfo->mouse_face_overlay = Qnil;
01b220b6 10796 /* TODO: dpyinfo->gray */
f7737f5d
JR
10797
10798}
10799
fbd6baed
GV
10800struct w32_display_info *
10801w32_term_init (display_name, xrm_option, resource_name)
ee78dc32
GV
10802 Lisp_Object display_name;
10803 char *xrm_option;
10804 char *resource_name;
10805{
fbd6baed 10806 struct w32_display_info *dpyinfo;
ee78dc32 10807 HDC hdc;
97c23857 10808
ee78dc32
GV
10809 BLOCK_INPUT;
10810
fbd6baed 10811 if (!w32_initialized)
ee78dc32 10812 {
fbd6baed
GV
10813 w32_initialize ();
10814 w32_initialized = 1;
ee78dc32
GV
10815 }
10816
10817 {
10818 int argc = 0;
10819 char *argv[3];
10820
10821 argv[0] = "";
10822 argc = 1;
10823 if (xrm_option)
10824 {
10825 argv[argc++] = "-xrm";
10826 argv[argc++] = xrm_option;
10827 }
10828 }
10829
f7737f5d 10830 w32_initialize_display_info (display_name);
ee78dc32 10831
f7737f5d 10832 dpyinfo = &one_w32_display_info;
8c3b00cb
AI
10833
10834 /* Put this display on the chain. */
10835 dpyinfo->next = x_display_list;
10836 x_display_list = dpyinfo;
ee78dc32 10837
52cf03a1 10838 hdc = GetDC (GetDesktopWindow ());
791f420f 10839
ee78dc32
GV
10840 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
10841 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
10842 dpyinfo->root_window = GetDesktopWindow ();
10843 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
10844 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
55689ab1
JR
10845 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
10846 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
52cf03a1 10847 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
791f420f 10848 dpyinfo->image_cache = make_image_cache ();
55689ab1
JR
10849 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
10850 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
ee78dc32 10851 ReleaseDC (GetDesktopWindow (), hdc);
52cf03a1
GV
10852
10853 /* initialise palette with white and black */
10854 {
10855 COLORREF color;
55689ab1
JR
10856 w32_defined_color (0, "white", &color, 1);
10857 w32_defined_color (0, "black", &color, 1);
52cf03a1
GV
10858 }
10859
f7737f5d
JR
10860 /* Create Row Bitmaps and store them for later use. */
10861 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
10862 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
10863 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
10864 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
10865 1, continued_bits);
10866 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
10867 1, 1, continuation_bits);
10868 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
10869
ee78dc32
GV
10870#ifndef F_SETOWN_BUG
10871#ifdef F_SETOWN
10872#ifdef F_SETOWN_SOCK_NEG
10873 /* stdin is a socket here */
10874 fcntl (connection, F_SETOWN, -getpid ());
10875#else /* ! defined (F_SETOWN_SOCK_NEG) */
10876 fcntl (connection, F_SETOWN, getpid ());
10877#endif /* ! defined (F_SETOWN_SOCK_NEG) */
10878#endif /* ! defined (F_SETOWN) */
10879#endif /* F_SETOWN_BUG */
10880
10881#ifdef SIGIO
10882 if (interrupt_input)
10883 init_sigio (connection);
10884#endif /* ! defined (SIGIO) */
10885
10886 UNBLOCK_INPUT;
10887
10888 return dpyinfo;
10889}
10890\f
10891/* Get rid of display DPYINFO, assuming all frames are already gone. */
10892
10893void
10894x_delete_display (dpyinfo)
fbd6baed 10895 struct w32_display_info *dpyinfo;
ee78dc32 10896{
fbd6baed 10897 /* Discard this display from w32_display_name_list and w32_display_list.
ee78dc32 10898 We can't use Fdelq because that can quit. */
fbd6baed 10899 if (! NILP (w32_display_name_list)
8e713be6
KR
10900 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
10901 w32_display_name_list = XCDR (w32_display_name_list);
ee78dc32
GV
10902 else
10903 {
10904 Lisp_Object tail;
10905
fbd6baed 10906 tail = w32_display_name_list;
8e713be6 10907 while (CONSP (tail) && CONSP (XCDR (tail)))
ee78dc32 10908 {
f7737f5d 10909 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
ee78dc32 10910 {
f3fbd155 10911 XSETCDR (tail, XCDR (XCDR (tail)));
ee78dc32
GV
10912 break;
10913 }
8e713be6 10914 tail = XCDR (tail);
ee78dc32
GV
10915 }
10916 }
10917
52cf03a1
GV
10918 /* free palette table */
10919 {
fbd6baed 10920 struct w32_palette_entry * plist;
52cf03a1
GV
10921
10922 plist = dpyinfo->color_list;
10923 while (plist)
10924 {
fbd6baed 10925 struct w32_palette_entry * pentry = plist;
52cf03a1 10926 plist = plist->next;
9127e20e 10927 xfree (pentry);
52cf03a1
GV
10928 }
10929 dpyinfo->color_list = NULL;
10930 if (dpyinfo->palette)
10931 DeleteObject(dpyinfo->palette);
10932 }
ee78dc32 10933 xfree (dpyinfo->font_table);
fbd6baed 10934 xfree (dpyinfo->w32_id_name);
f7737f5d
JR
10935
10936 /* Destroy row bitmaps. */
10937 DeleteObject (left_bmp);
10938 DeleteObject (ov_bmp);
10939 DeleteObject (right_bmp);
10940 DeleteObject (continued_bmp);
10941 DeleteObject (continuation_bmp);
10942 DeleteObject (zv_bmp);
ee78dc32
GV
10943}
10944\f
fbd6baed 10945/* Set up use of W32. */
ee78dc32 10946
689004fa 10947DWORD w32_msg_worker ();
ee78dc32 10948
791f420f
JR
10949void
10950x_flush (struct frame * f)
10951{ /* Nothing to do */ }
10952
10953static struct redisplay_interface w32_redisplay_interface =
10954{
10955 x_produce_glyphs,
10956 x_write_glyphs,
10957 x_insert_glyphs,
10958 x_clear_end_of_line,
10959 x_scroll_run,
10960 x_after_update_window_line,
10961 x_update_window_begin,
10962 x_update_window_end,
10963 w32_cursor_to,
10964 x_flush,
ec48c3a7 10965 x_clear_mouse_face,
791f420f
JR
10966 x_get_glyph_overhangs,
10967 x_fix_overlapping_area
10968};
10969
10970void
fbd6baed
GV
10971w32_initialize ()
10972{
791f420f
JR
10973 rif = &w32_redisplay_interface;
10974
96214669
GV
10975 /* MSVC does not type K&R functions with no arguments correctly, and
10976 so we must explicitly cast them. */
791f420f 10977 clear_frame_hook = (void (*)(void)) x_clear_frame;
96214669 10978 ring_bell_hook = (void (*)(void)) w32_ring_bell;
791f420f
JR
10979 update_begin_hook = x_update_begin;
10980 update_end_hook = x_update_end;
0f32f023 10981
ee78dc32 10982 read_socket_hook = w32_read_socket;
0f32f023 10983
fbd6baed 10984 frame_up_to_date_hook = w32_frame_up_to_date;
0f32f023 10985
fbd6baed
GV
10986 mouse_position_hook = w32_mouse_position;
10987 frame_rehighlight_hook = w32_frame_rehighlight;
10988 frame_raise_lower_hook = w32_frame_raise_lower;
10989 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
10990 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
10991 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
10992 judge_scroll_bars_hook = w32_judge_scroll_bars;
791f420f 10993 estimate_mode_line_height_hook = x_estimate_mode_line_height;
ee78dc32
GV
10994
10995 scroll_region_ok = 1; /* we'll scroll partial frames */
49be9f70 10996 char_ins_del_ok = 1;
ee78dc32
GV
10997 line_ins_del_ok = 1; /* we'll just blt 'em */
10998 fast_clear_end_of_line = 1; /* X does this well */
10999 memory_below_frame = 0; /* we don't remember what scrolls
11000 off the bottom */
11001 baud_rate = 19200;
11002
abb15ebd
JR
11003 w32_system_caret_hwnd = NULL;
11004 w32_system_caret_height = 0;
11005 w32_system_caret_width = 0;
11006 w32_system_caret_x = 0;
11007 w32_system_caret_y = 0;
11008
791f420f
JR
11009 last_tool_bar_item = -1;
11010 any_help_event_p = 0;
11011
689004fa
GV
11012 /* Initialize input mode: interrupt_input off, no flow control, allow
11013 8 bit character input, standard quit char. */
11014 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
ee78dc32
GV
11015
11016 /* Create the window thread - it will terminate itself or when the app terminates */
11017
11018 init_crit ();
11019
11020 dwMainThreadId = GetCurrentThreadId ();
11021 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
11022 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
11023
11024 /* Wait for thread to start */
11025
11026 {
11027 MSG msg;
11028
11029 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
11030
e9e23e23 11031 hWindowsThread = CreateThread (NULL, 0,
689004fa 11032 (LPTHREAD_START_ROUTINE) w32_msg_worker,
e9e23e23 11033 0, 0, &dwWindowsThreadId);
ee78dc32
GV
11034
11035 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
11036 }
11037
52cf03a1 11038 /* It is desirable that mainThread should have the same notion of
e9e23e23 11039 focus window and active window as windowsThread. Unfortunately, the
52cf03a1
GV
11040 following call to AttachThreadInput, which should do precisely what
11041 we need, causes major problems when Emacs is linked as a console
11042 program. Unfortunately, we have good reasons for doing that, so
e9e23e23 11043 instead we need to send messages to windowsThread to make some API
52cf03a1
GV
11044 calls for us (ones that affect, or depend on, the active/focus
11045 window state. */
11046#ifdef ATTACH_THREADS
e9e23e23 11047 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
52cf03a1 11048#endif
689004fa
GV
11049
11050 /* Dynamically link to optional system components. */
11051 {
11052 HANDLE user_lib = LoadLibrary ("user32.dll");
11053
11054#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
11055
11056 /* New proportional scroll bar functions. */
9127e20e
JR
11057 LOAD_PROC (SetScrollInfo);
11058 LOAD_PROC (GetScrollInfo);
689004fa
GV
11059
11060#undef LOAD_PROC
11061
11062 FreeLibrary (user_lib);
11063
11064 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
11065 otherwise use the fixed height. */
11066 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
11067 GetSystemMetrics (SM_CYVTHUMB);
11068
11069 /* For either kind of scroll bar, take account of the arrows; these
11070 effectively form the border of the main scroll bar range. */
11071 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
11072 = GetSystemMetrics (SM_CYVSCROLL);
11073 }
ee78dc32
GV
11074}
11075
11076void
fbd6baed 11077syms_of_w32term ()
ee78dc32 11078{
fbd6baed
GV
11079 staticpro (&w32_display_name_list);
11080 w32_display_name_list = Qnil;
ee78dc32
GV
11081
11082 staticpro (&last_mouse_scroll_bar);
11083 last_mouse_scroll_bar = Qnil;
11084
11085 staticpro (&Qvendor_specific_keysyms);
11086 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
52cf03a1 11087
fbd6baed
GV
11088 DEFVAR_INT ("w32-num-mouse-buttons",
11089 &Vw32_num_mouse_buttons,
33f09670 11090 doc: /* Number of physical mouse buttons. */);
fbd6baed 11091 Vw32_num_mouse_buttons = Qnil;
52cf03a1 11092
fbd6baed
GV
11093 DEFVAR_LISP ("w32-swap-mouse-buttons",
11094 &Vw32_swap_mouse_buttons,
33f09670
JR
11095 doc: /* Swap the mapping of middle and right mouse buttons.
11096When nil, middle button is mouse-2 and right button is mouse-3. */);
fbd6baed 11097 Vw32_swap_mouse_buttons = Qnil;
689004fa
GV
11098
11099 DEFVAR_LISP ("w32-grab-focus-on-raise",
11100 &Vw32_grab_focus_on_raise,
33f09670
JR
11101 doc: /* Raised frame grabs input focus.
11102When t, `raise-frame' grabs input focus as well. This fits well
11103with the normal Windows click-to-focus policy, but might not be
11104desirable when using a point-to-focus policy. */);
689004fa
GV
11105 Vw32_grab_focus_on_raise = Qt;
11106
11107 DEFVAR_LISP ("w32-capslock-is-shiftlock",
11108 &Vw32_capslock_is_shiftlock,
33f09670
JR
11109 doc: /* Apply CapsLock state to non character input keys.
11110When nil, CapsLock only affects normal character input keys. */);
689004fa 11111 Vw32_capslock_is_shiftlock = Qnil;
ef0e360f
GV
11112
11113 DEFVAR_LISP ("w32-recognize-altgr",
11114 &Vw32_recognize_altgr,
33f09670
JR
11115 doc: /* Recognize right-alt and left-ctrl as AltGr.
11116When nil, the right-alt and left-ctrl key combination is
11117interpreted normally. */);
ef0e360f 11118 Vw32_recognize_altgr = Qt;
bc6af935 11119
484fa2c1
GV
11120 DEFVAR_BOOL ("w32-enable-unicode-output",
11121 &w32_enable_unicode_output,
33f09670
JR
11122 doc: /* Enable the use of Unicode for text output if non-nil.
11123Unicode output may prevent some third party applications for displaying
11124Far-East Languages on Windows 95/98 from working properly.
11125NT uses Unicode internally anyway, so this flag will probably have no
11126affect on NT machines. */);
484fa2c1 11127 w32_enable_unicode_output = 1;
a1b9438c 11128
791f420f 11129 help_echo = Qnil;
ec48c3a7
JR
11130 staticpro (&help_echo);
11131 help_echo_object = Qnil;
11132 staticpro (&help_echo_object);
158cba56
JR
11133 help_echo_window = Qnil;
11134 staticpro (&help_echo_window);
791f420f 11135 previous_help_echo = Qnil;
ec48c3a7 11136 staticpro (&previous_help_echo);
158cba56 11137 help_echo_pos = -1;
791f420f
JR
11138
11139 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
33f09670
JR
11140 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
11141For example, if a block cursor is over a tab, it will be drawn as
11142wide as that tab on the display. */);
791f420f
JR
11143 x_stretch_cursor_p = 0;
11144
9f5a911b
JR
11145#if 0 /* TODO: Setting underline position from font properties. */
11146 DEFVAR_BOOL ("x-use-underline-position-properties",
11147 &x_use_underline_position_properties,
33f09670 11148 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
f0529b5b 11149nil means ignore them. If you encounter fonts with bogus
33f09670
JR
11150UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11151to 4.1, set this to nil. */);
9f5a911b
JR
11152 x_use_underline_position_properties = 1;
11153#endif
11154
5bf04520 11155 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
33f09670 11156 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
5bf04520 11157 Vx_toolkit_scroll_bars = Qt;
791f420f
JR
11158
11159 staticpro (&last_mouse_motion_frame);
11160 last_mouse_motion_frame = Qnil;
ee78dc32 11161}