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