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