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