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