X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/3d798ba7dbad4bac02226959cfd82099bf11fd9f..30f667fbf472401bc6b9c2281a5c54a4b670a3a8:/src/xdisp.c
diff --git a/src/xdisp.c b/src/xdisp.c
index 395a74e412..5fe278079e 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1,6 +1,7 @@
/* Display generation from window structure and buffer text.
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
@@ -97,7 +98,9 @@ along with GNU Emacs. If not, see . */
This function attempts to redisplay a window by reusing parts of
its existing display. It finds and reuses the part that was not
- changed, and redraws the rest.
+ changed, and redraws the rest. (The "id" part in the function's
+ name stands for "insert/delete", not for "identification" or
+ somesuch.)
. try_window
@@ -112,6 +115,19 @@ along with GNU Emacs. If not, see . */
optimizations were successful, redisplay calls redisplay_windows,
which performs a full redisplay of all windows.
+ Note that there's one more important optimization up Emacs's
+ sleeve, but it is related to actually redrawing the potentially
+ changed portions of the window/frame, not to reproducing the
+ desired matrices of those potentially changed portions. Namely,
+ the function update_frame and its subroutines, which you will find
+ in dispnew.c, compare the desired matrices with the current
+ matrices, and only redraw the portions that changed. So it could
+ happen that the functions in this file for some reason decide that
+ the entire desired matrix needs to be regenerated from scratch, and
+ still only parts of the Emacs display, or even nothing at all, will
+ be actually delivered to the glass, because update_frame has found
+ that the new and the old screen contents are similar or identical.
+
Desired matrices.
Desired matrices are always built per Emacs window. The function
@@ -502,12 +518,20 @@ static Lisp_Object Vmessage_stack;
static bool message_enable_multibyte;
-/* Nonzero if we should redraw the mode lines on the next redisplay. */
+/* Nonzero if we should redraw the mode lines on the next redisplay.
+ If it has value REDISPLAY_SOME, then only redisplay the mode lines where
+ the `redisplay' bit has been set. Otherwise, redisplay all mode lines
+ (the number used is then only used to track down the cause for this
+ full-redisplay). */
int update_mode_lines;
-/* Nonzero if window sizes or contents have changed since last
- redisplay that finished. */
+/* Nonzero if window sizes or contents other than selected-window have changed
+ since last redisplay that finished.
+ If it has value REDISPLAY_SOME, then only redisplay the windows where
+ the `redisplay' bit has been set. Otherwise, redisplay all windows
+ (the number used is then only used to track down the cause for this
+ full-redisplay). */
int windows_or_buffers_changed;
@@ -599,12 +623,62 @@ bool help_echo_showing_p;
CACHE = NULL; \
} while (0)
+/* Functions to mark elements as needing redisplay. */
+enum { REDISPLAY_SOME = 2}; /* Arbitrary choice. */
+
+void
+redisplay_other_windows (void)
+{
+ if (!windows_or_buffers_changed)
+ windows_or_buffers_changed = REDISPLAY_SOME;
+}
+
+void
+wset_redisplay (struct window *w)
+{
+ /* Beware: selected_window can be nil during early stages. */
+ if (!EQ (w->header.self, selected_window))
+ redisplay_other_windows ();
+ w->redisplay = true;
+}
+
+void
+fset_redisplay (struct frame *f)
+{
+ redisplay_other_windows ();
+ f->redisplay = true;
+}
+
+void
+bset_redisplay (struct buffer *b)
+{
+ int count = buffer_window_count (b);
+ if (count > 0)
+ {
+ /* ... it's visible in other window than selected, */
+ if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
+ redisplay_other_windows ();
+ /* Even if we don't set windows_or_buffers_changed, do set `redisplay'
+ so that if we later set windows_or_buffers_changed, this buffer will
+ not be omitted. */
+ b->text->redisplay = true;
+ }
+}
+
+void
+bset_update_mode_line (struct buffer *b)
+{
+ if (!update_mode_lines)
+ update_mode_lines = REDISPLAY_SOME;
+ b->text->redisplay = true;
+}
+
#ifdef GLYPH_DEBUG
/* Non-zero means print traces of redisplay if compiled with
GLYPH_DEBUG defined. */
-int trace_redisplay_p;
+bool trace_redisplay_p;
#endif /* GLYPH_DEBUG */
@@ -737,7 +811,7 @@ ptrdiff_t help_echo_pos;
Lisp_Object previous_help_echo_string;
-/* Platform-independent portion of hourglass implementation. */
+/* Platform-independent portion of hourglass implementation. */
#ifdef HAVE_WINDOW_SYSTEM
@@ -779,7 +853,7 @@ static int single_display_spec_string_p (Lisp_Object, Lisp_Object);
static int display_prop_string_p (Lisp_Object, Lisp_Object);
static int row_for_charpos_p (struct glyph_row *, ptrdiff_t);
static int cursor_row_p (struct glyph_row *);
-static int redisplay_mode_lines (Lisp_Object, int);
+static int redisplay_mode_lines (Lisp_Object, bool);
static char *decode_mode_spec_coding (Lisp_Object, char *, int);
static Lisp_Object get_it_property (struct it *it, Lisp_Object prop);
@@ -833,7 +907,7 @@ static void sync_frame_with_window_matrix_rows (struct window *);
static void redisplay_internal (void);
static int echo_area_display (int);
static void redisplay_windows (Lisp_Object);
-static void redisplay_window (Lisp_Object, int);
+static void redisplay_window (Lisp_Object, bool);
static Lisp_Object redisplay_window_error (Lisp_Object);
static Lisp_Object redisplay_window_0 (Lisp_Object);
static Lisp_Object redisplay_window_1 (Lisp_Object);
@@ -914,6 +988,7 @@ static int in_ellipses_for_invisible_text_p (struct display_pos *,
static void x_consider_frame_title (Lisp_Object);
static void update_tool_bar (struct frame *, int);
static int redisplay_tool_bar (struct frame *);
+static void x_draw_bottom_divider (struct window *w);
static void notice_overwritten_cursor (struct window *,
enum glyph_row_area,
int, int, int, int);
@@ -925,7 +1000,7 @@ static void append_stretch_glyph (struct it *, Lisp_Object,
static void produce_special_glyphs (struct it *, enum display_element_type);
static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
-static int coords_in_mouse_face_p (struct window *, int, int);
+static bool coords_in_mouse_face_p (struct window *, int, int);
@@ -942,10 +1017,13 @@ static int coords_in_mouse_face_p (struct window *, int, int);
int
window_text_bottom_y (struct window *w)
{
- int height = WINDOW_TOTAL_HEIGHT (w);
+ int height = WINDOW_PIXEL_HEIGHT (w);
+
+ height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
if (WINDOW_WANTS_MODELINE_P (w))
height -= CURRENT_MODE_LINE_HEIGHT (w);
+
return height;
}
@@ -956,32 +1034,25 @@ window_text_bottom_y (struct window *w)
int
window_box_width (struct window *w, enum glyph_row_area area)
{
- int cols = w->total_cols;
- int pixels = 0;
+ int width = w->pixel_width;
if (!w->pseudo_window_p)
{
- cols -= WINDOW_SCROLL_BAR_COLS (w);
+ width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+ width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
if (area == TEXT_AREA)
- {
- cols -= max (0, w->left_margin_cols);
- cols -= max (0, w->right_margin_cols);
- pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
- }
+ width -= (WINDOW_MARGINS_WIDTH (w)
+ + WINDOW_FRINGES_WIDTH (w));
else if (area == LEFT_MARGIN_AREA)
- {
- cols = max (0, w->left_margin_cols);
- pixels = 0;
- }
+ width = WINDOW_LEFT_MARGIN_WIDTH (w);
else if (area == RIGHT_MARGIN_AREA)
- {
- cols = max (0, w->right_margin_cols);
- pixels = 0;
- }
+ width = WINDOW_RIGHT_MARGIN_WIDTH (w);
}
- return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
+ /* With wide margins, fringes, etc. we might end up with a negative
+ width, correct that here. */
+ return max (0, width);
}
@@ -992,10 +1063,12 @@ int
window_box_height (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- int height = WINDOW_TOTAL_HEIGHT (w);
+ int height = WINDOW_PIXEL_HEIGHT (w);
eassert (height >= 0);
+ height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+
/* Note: the code below that determines the mode-line/header-line
height is essentially the same as that contained in the macro
CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
@@ -1059,7 +1132,8 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
&& WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
x += WINDOW_LEFT_FRINGE_WIDTH (w);
- return x;
+ /* Don't return more than the window's pixel width. */
+ return min (x, w->pixel_width);
}
@@ -1070,7 +1144,9 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
int
window_box_right_offset (struct window *w, enum glyph_row_area area)
{
- return window_box_left_offset (w, area) + window_box_width (w, area);
+ /* Don't return more than the window's pixel width. */
+ return min (window_box_left_offset (w, area) + window_box_width (w, area),
+ w->pixel_width);
}
/* Return the frame-relative coordinate of the left edge of display
@@ -1201,12 +1277,23 @@ Value is the height in pixels of the line at point. */)
struct it it;
struct text_pos pt;
struct window *w = XWINDOW (selected_window);
+ struct buffer *old_buffer = NULL;
+ Lisp_Object result;
+ if (XBUFFER (w->contents) != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal_1 (XBUFFER (w->contents));
+ }
SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt);
it.vpos = it.current_y = 0;
last_height = 0;
- return make_number (line_bottom_y (&it));
+ result = make_number (line_bottom_y (&it));
+ if (old_buffer)
+ set_buffer_internal_1 (old_buffer);
+
+ return result;
}
/* Return the default pixel height of text lines in window W. The
@@ -1373,7 +1460,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
if (top_y < window_top_y)
visible_p = bottom_y > window_top_y;
else if (top_y < it.last_visible_y)
- visible_p = 1;
+ visible_p = true;
if (bottom_y >= it.last_visible_y
&& it.bidi_p && it.bidi_it.scan_dir == -1
&& IT_CHARPOS (it) < charpos)
@@ -1611,7 +1698,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
if (charpos < IT_CHARPOS (it)
|| (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
{
- visible_p = 1;
+ visible_p = true;
RESTORE_IT (&it2, &it2, it2data);
move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
*x = it2.current_x;
@@ -1854,6 +1941,7 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
FRAME_COLUMN_WIDTH (f) - 1,
FRAME_LINE_HEIGHT (f) - 1);
+ /* PXW: Should we clip pixels before converting to columns/lines? */
if (!noclip)
{
if (pix_x < 0)
@@ -1994,7 +2082,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
{
/* Draw full-width. X coordinates are relative to S->w->left_col. */
r.x = WINDOW_LEFT_EDGE_X (s->w);
- r.width = WINDOW_TOTAL_WIDTH (s->w);
+ if (s->row->mode_line_p)
+ r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
+ else
+ r.width = WINDOW_PIXEL_WIDTH (s->w);
/* Unless displaying a mode or menu bar line, which are always
fully visible, clip to the visible part of the row. */
@@ -2262,9 +2353,14 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
/* Try to determine frame pixel position and size of the glyph under
frame pixel coordinates X/Y on frame F. */
- if (!f->glyphs_initialized_p
- || (window = window_from_coordinates (f, gx, gy, &part, 0),
- NILP (window)))
+ if (window_resize_pixelwise)
+ {
+ width = height = 1;
+ goto virtual_glyph;
+ }
+ else if (!f->glyphs_initialized_p
+ || (window = window_from_coordinates (f, gx, gy, &part, 0),
+ NILP (window)))
{
width = FRAME_SMALLEST_CHAR_WIDTH (f);
height = FRAME_SMALLEST_FONT_HEIGHT (f);
@@ -2349,7 +2445,13 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
}
if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
- gx += window_box_left_offset (w, area);
+ {
+ gx += window_box_left_offset (w, area);
+ /* Don't expand over the modeline to make sure the vertical
+ drag cursor is shown early enough. */
+ height = min (height,
+ max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
+ }
}
else
{
@@ -2357,6 +2459,10 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
gx = (x / width) * width;
y -= gy;
gy += (y / height) * height;
+ if (part != ON_MODE_LINE && part != ON_HEADER_LINE)
+ /* See comment above. */
+ height = min (height,
+ max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
}
break;
@@ -2371,7 +2477,22 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? window_box_right_offset (w, RIGHT_MARGIN_AREA)
: window_box_right_offset (w, TEXT_AREA));
- width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
+ && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+ && !WINDOW_RIGHTMOST_P (w))
+ if (gx < WINDOW_PIXEL_WIDTH (w) - width)
+ /* Make sure the vertical border can get her own glyph to the
+ right of the one we build here. */
+ width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
+ else
+ width = WINDOW_PIXEL_WIDTH (w) - gx;
+ else
+ width = WINDOW_RIGHT_FRINGE_WIDTH (w);
+
+ goto row_glyph;
+
+ case ON_VERTICAL_BORDER:
+ gx = WINDOW_PIXEL_WIDTH (w) - width;
goto row_glyph;
case ON_SCROLL_BAR:
@@ -2402,6 +2523,21 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
}
break;
+ case ON_RIGHT_DIVIDER:
+ gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+ width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
+ gy = 0;
+ /* The bottom divider prevails. */
+ height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ goto add_edge;;
+
+ case ON_BOTTOM_DIVIDER:
+ gx = 0;
+ width = WINDOW_PIXEL_WIDTH (w);
+ gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ goto add_edge;
+
default:
;
virtual_glyph:
@@ -2422,6 +2558,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
goto store_rect;
}
+ add_edge:
gx += WINDOW_LEFT_EDGE_X (w);
gy += WINDOW_TOP_EDGE_Y (w);
@@ -2469,8 +2606,8 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
following. Return the result, or nil if something went
wrong. Prevent redisplay during the evaluation. */
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+static Lisp_Object
+safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
{
Lisp_Object val;
@@ -2478,32 +2615,42 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
val = Qnil;
else
{
- va_list ap;
ptrdiff_t i;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
struct gcpro gcpro1;
Lisp_Object *args = alloca (nargs * word_size);
args[0] = func;
- va_start (ap, func);
for (i = 1; i < nargs; i++)
args[i] = va_arg (ap, Lisp_Object);
- va_end (ap);
GCPRO1 (args[0]);
gcpro1.nvars = nargs;
specbind (Qinhibit_redisplay, Qt);
+ if (inhibit_quit)
+ specbind (Qinhibit_quit, Qt);
/* Use Qt to ensure debugger does not run,
so there is no possibility of wanting to redisplay. */
val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
safe_eval_handler);
UNGCPRO;
- val = unbind_to (count, val);
+ dynwind_end ();
}
return val;
}
+Lisp_Object
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+{
+ Lisp_Object retval;
+ va_list ap;
+
+ va_start (ap, func);
+ retval = safe__call (false, nargs, func, ap);
+ va_end (ap);
+ return retval;
+}
/* Call function FN with one argument ARG.
Return the result, or nil if something went wrong. */
@@ -2514,12 +2661,30 @@ safe_call1 (Lisp_Object fn, Lisp_Object arg)
return safe_call (2, fn, arg);
}
+static Lisp_Object
+safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+{
+ Lisp_Object retval;
+ va_list ap;
+
+ va_start (ap, fn);
+ retval = safe__call (inhibit_quit, 2, fn, ap);
+ va_end (ap);
+ return retval;
+}
+
static Lisp_Object Qeval;
Lisp_Object
safe_eval (Lisp_Object sexpr)
{
- return safe_call1 (Qeval, sexpr);
+ return safe__call1 (false, Qeval, sexpr);
+}
+
+static Lisp_Object
+safe__eval (bool inhibit_quit, Lisp_Object sexpr)
+{
+ return safe__call1 (inhibit_quit, Qeval, sexpr);
}
/* Call function FN with two arguments ARG1 and ARG2.
@@ -2601,24 +2766,6 @@ check_window_end (struct window *w)
#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
-/* Return mark position if current buffer has the region of non-zero length,
- or -1 otherwise. */
-
-static ptrdiff_t
-markpos_of_region (void)
-{
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active))
- && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
- {
- ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
-
- if (markpos != PT)
- return markpos;
- }
- return -1;
-}
-
/***********************************************************************
Iterator initialization
***********************************************************************/
@@ -2647,7 +2794,6 @@ init_iterator (struct it *it, struct window *w,
ptrdiff_t charpos, ptrdiff_t bytepos,
struct glyph_row *row, enum face_id base_face_id)
{
- ptrdiff_t markpos;
enum face_id remapped_base_face_id = base_face_id;
/* Some precondition checks. */
@@ -2751,28 +2897,6 @@ init_iterator (struct it *it, struct window *w,
/* Are multibyte characters enabled in current_buffer? */
it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
- /* If visible region is of non-zero length, set IT->region_beg_charpos
- and IT->region_end_charpos to the start and end of a visible region
- in window IT->w. Set both to -1 to indicate no region. */
- markpos = markpos_of_region ();
- if (markpos >= 0
- /* Maybe highlight only in selected window. */
- && (/* Either show region everywhere. */
- highlight_nonselected_windows
- /* Or show region in the selected window. */
- || w == XWINDOW (selected_window)
- /* Or show the region if we are in the mini-buffer and W is
- the window the mini-buffer refers to. */
- || (MINI_WINDOW_P (XWINDOW (selected_window))
- && WINDOWP (minibuf_selected_window)
- && w == XWINDOW (minibuf_selected_window))))
- {
- it->region_beg_charpos = min (PT, markpos);
- it->region_end_charpos = max (PT, markpos);
- }
- else
- it->region_beg_charpos = it->region_end_charpos = -1;
-
/* Get the position at which the redisplay_end_trigger hook should
be run, if it is to be run at all. */
if (MARKERP (w->redisplay_end_trigger)
@@ -2780,8 +2904,9 @@ init_iterator (struct it *it, struct window *w,
it->redisplay_end_trigger_charpos
= marker_position (w->redisplay_end_trigger);
else if (INTEGERP (w->redisplay_end_trigger))
- it->redisplay_end_trigger_charpos =
- clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), PTRDIFF_MAX);
+ it->redisplay_end_trigger_charpos
+ = clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger),
+ PTRDIFF_MAX);
it->tab_width = SANE_TAB_WIDTH (current_buffer);
@@ -2792,6 +2917,7 @@ init_iterator (struct it *it, struct window *w,
&& ((!NILP (Vtruncate_partial_width_windows)
&& !INTEGERP (Vtruncate_partial_width_windows))
|| (INTEGERP (Vtruncate_partial_width_windows)
+ /* PXW: Shall we do something about this? */
&& (WINDOW_TOTAL_COLS (it->w)
< XINT (Vtruncate_partial_width_windows))))))
it->line_wrap = TRUNCATE;
@@ -2851,12 +2977,12 @@ init_iterator (struct it *it, struct window *w,
{
/* Mode lines, menu bar in terminal frames. */
it->first_visible_x = 0;
- it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
+ it->last_visible_x = WINDOW_PIXEL_WIDTH (w);
}
else
{
- it->first_visible_x =
- window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
+ it->first_visible_x
+ = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
it->last_visible_x = (it->first_visible_x
+ window_box_width (w, TEXT_AREA));
@@ -2897,8 +3023,8 @@ init_iterator (struct it *it, struct window *w,
/* If we have a boxed mode line, make the first character appear
with a left box line. */
face = FACE_FROM_ID (it->f, remapped_base_face_id);
- if (face->box != FACE_NO_BOX)
- it->start_of_box_run_p = 1;
+ if (face && face->box != FACE_NO_BOX)
+ it->start_of_box_run_p = true;
}
/* If a buffer position was specified, set the iterator there,
@@ -3326,7 +3452,7 @@ handle_stop (struct it *it)
pop_it (it);
else
{
- it->ignore_overlay_strings_at_pos_p = 1;
+ it->ignore_overlay_strings_at_pos_p = true;
it->string_from_display_prop_p = 0;
it->from_disp_prop_p = 0;
handle_overlay_change_p = 0;
@@ -3406,16 +3532,6 @@ compute_stop_pos (struct it *it)
if (pos < it->stop_charpos)
it->stop_charpos = pos;
- /* If showing the region, we have to stop at the region
- start or end because the face might change there. */
- if (it->region_beg_charpos > 0)
- {
- if (IT_CHARPOS (*it) < it->region_beg_charpos)
- it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
- else if (IT_CHARPOS (*it) < it->region_end_charpos)
- it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
- }
-
/* Set up variables for computing the stop position from text
property changes. */
XSETBUFFER (object, current_buffer);
@@ -3695,7 +3811,7 @@ handle_fontified_prop (struct it *it)
no amount of fontifying will be able to change it. */
NILP (prop) && IT_CHARPOS (*it) < Z))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object val;
struct buffer *obuf = current_buffer;
ptrdiff_t begv = BEGV, zv = ZV;
@@ -3743,7 +3859,7 @@ handle_fontified_prop (struct it *it)
UNGCPRO;
}
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Fontification functions routinely call `save-restriction'.
Normally, this tags clip_changed, which can confuse redisplay
@@ -3799,8 +3915,6 @@ handle_face_prop (struct it *it)
new_face_id
= face_at_buffer_position (it->w,
IT_CHARPOS (*it),
- it->region_beg_charpos,
- it->region_end_charpos,
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
@@ -3877,8 +3991,6 @@ handle_face_prop (struct it *it)
base_face_id
= face_for_overlay_string (it->w,
IT_CHARPOS (*it),
- it->region_beg_charpos,
- it->region_end_charpos,
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
@@ -3896,6 +4008,15 @@ handle_face_prop (struct it *it)
For strings from wrap-prefix and line-prefix properties,
use the default face, possibly remapped via
Vface_remapping_alist. */
+ /* Note that the fact that we use the face at _buffer_
+ position means that a 'display' property on an overlay
+ string will not inherit the face of that overlay string,
+ but will instead revert to the face of buffer text
+ covered by the overlay. This is visible, e.g., when the
+ overlay specifies a box face, but neither the buffer nor
+ the display string do. This sounds like a design bug,
+ but Emacs always did that since v21.1, so changing that
+ might be a big deal. */
base_face_id = it->string_from_prefix_prop_p
? (!NILP (Vface_remapping_alist)
? lookup_basic_face (it->f, DEFAULT_FACE_ID)
@@ -3907,8 +4028,6 @@ handle_face_prop (struct it *it)
it->string,
IT_STRING_CHARPOS (*it),
bufpos,
- it->region_beg_charpos,
- it->region_end_charpos,
&next_stop,
base_face_id, 0);
@@ -4051,8 +4170,6 @@ face_before_or_after_it_pos (struct it *it, int before_p)
it->string,
charpos,
bufpos,
- it->region_beg_charpos,
- it->region_end_charpos,
&next_check_charpos,
base_face_id, 0);
@@ -4142,8 +4259,6 @@ face_before_or_after_it_pos (struct it *it, int before_p)
/* Determine face for CHARSET_ASCII, or unibyte. */
face_id = face_at_buffer_position (it->w,
CHARPOS (pos),
- it->region_beg_charpos,
- it->region_end_charpos,
&next_check_charpos,
limit, 0, -1);
@@ -4211,13 +4326,13 @@ handle_invisible_prop (struct it *it)
prop = Fget_text_property (end_charpos, Qinvisible, it->string);
invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
if (invis_p == 2)
- display_ellipsis_p = 1;
+ display_ellipsis_p = true;
}
}
while (invis_p && endpos < len);
if (display_ellipsis_p)
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
if (endpos < len)
{
@@ -4329,9 +4444,9 @@ handle_invisible_prop (struct it *it)
tem = next_stop;
/* If there are adjacent invisible texts, don't lose the
- second one's ellipsis. */
+ second one's ellipsis. */
if (invis_p == 2)
- display_ellipsis_p = 1;
+ display_ellipsis_p = true;
}
while (invis_p);
@@ -4339,10 +4454,10 @@ handle_invisible_prop (struct it *it)
if (it->bidi_p)
{
ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
- int on_newline =
- bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
- int after_newline =
- newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
+ int on_newline
+ = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
+ int after_newline
+ = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
/* If the invisible text ends on a newline or on a
character after a newline, we can avoid the costly,
@@ -4449,7 +4564,7 @@ handle_invisible_prop (struct it *it)
it->position.charpos = newpos - 1;
it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
}
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
/* Let the ellipsis display before
considering any properties of the following char.
Fixes jasonr@gnu.org 01 Oct 07 bug. */
@@ -4473,8 +4588,8 @@ setup_for_ellipsis (struct it *it, int len)
if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
{
struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
- it->dpvec = v->u.contents;
- it->dpend = v->u.contents + v->header.size;
+ it->dpvec = v->contents;
+ it->dpend = v->contents + v->header.size;
}
else
{
@@ -4494,7 +4609,7 @@ setup_for_ellipsis (struct it *it, int len)
it->saved_face_id = it->face_id = DEFAULT_FACE_ID;
it->method = GET_FROM_DISPLAY_VECTOR;
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
}
@@ -4708,7 +4823,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
if (!NILP (form) && !EQ (form, Qt))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
struct gcpro gcpro1;
/* Bind `object' to the object having the `display' property, a
@@ -4724,7 +4839,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
GCPRO1 (form);
form = safe_eval (form);
UNGCPRO;
- unbind_to (count, Qnil);
+ dynwind_end ();
}
if (NILP (form))
@@ -4782,11 +4897,11 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
{
/* Evaluate IT->font_height with `height' bound to the
current specified height to get the new height. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
value = safe_eval (it->font_height);
- unbind_to (count, Qnil);
+ dynwind_end ();
if (NUMBERP (value))
new_height = XFLOATINT (value);
@@ -4963,7 +5078,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->method = GET_FROM_IMAGE;
it->from_overlay = Qnil;
it->face_id = face_id;
- it->from_disp_prop_p = 1;
+ it->from_disp_prop_p = true;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
@@ -5045,7 +5160,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
when we are finished with the glyph property value. */
push_it (it, position);
it->from_overlay = overlay;
- it->from_disp_prop_p = 1;
+ it->from_disp_prop_p = true;
if (NILP (location))
it->area = TEXT_AREA;
@@ -5065,7 +5180,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->stop_charpos = 0;
it->prev_stop = 0;
it->base_level_stop = 0;
- it->string_from_display_prop_p = 1;
+ it->string_from_display_prop_p = true;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
set_iterator_to_next will clean this up. */
@@ -5431,7 +5546,7 @@ next_overlay_string (struct it *it)
processed the overlay strings there already, so that
next_element_from_buffer doesn't try it again. */
if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
- it->overlay_strings_at_end_processed_p = 1;
+ it->overlay_strings_at_end_processed_p = true;
}
else
{
@@ -5935,7 +6050,16 @@ pop_it (struct it *it)
it->object = it->w->contents;
break;
case GET_FROM_STRING:
- it->object = it->string;
+ {
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+
+ /* Restore the face_box_p flag, since it could have been
+ overwritten by the face of the object that we just finished
+ displaying. */
+ if (face)
+ it->face_box_p = face->box != FACE_NO_BOX;
+ it->object = it->string;
+ }
break;
case GET_FROM_DISPLAY_VECTOR:
if (it->s)
@@ -6114,7 +6238,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p,
if (bidi_it_prev)
*bidi_it_prev = bprev;
}
- *skipped_p = newline_found_p = 1;
+ *skipped_p = newline_found_p = true;
}
else
{
@@ -6404,6 +6528,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
it->bidi_it.string.s = NULL;
it->bidi_it.string.lstring = Qnil;
it->bidi_it.string.bufpos = 0;
+ it->bidi_it.string.from_disp_str = 0;
it->bidi_it.string.unibyte = 0;
it->bidi_it.w = it->w;
}
@@ -6441,9 +6566,6 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
ptrdiff_t charpos, ptrdiff_t precision, int field_width,
int multibyte)
{
- /* No region in strings. */
- it->region_beg_charpos = it->region_end_charpos = -1;
-
/* No text property checks performed by default, but see below. */
it->stop_charpos = -1;
@@ -6618,8 +6740,8 @@ lookup_glyphless_char_display (int c, struct it *it)
if (c >= 0)
{
glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
- if (CONSP (glyphless_method))
- glyphless_method = FRAME_WINDOW_P (it->f)
+ if (CONSP (glyphless_method))
+ glyphless_method = FRAME_WINDOW_P (it->f)
? XCAR (glyphless_method)
: XCDR (glyphless_method);
}
@@ -6778,8 +6900,8 @@ get_next_display_element (struct it *it)
if (v->header.size)
{
it->dpvec_char_len = it->len;
- it->dpvec = v->u.contents;
- it->dpend = v->u.contents + v->header.size;
+ it->dpvec = v->contents;
+ it->dpend = v->contents + v->header.size;
it->current.dpvec_index = 0;
it->dpvec_face_id = -1;
it->saved_face_id = it->face_id;
@@ -6807,9 +6929,9 @@ get_next_display_element (struct it *it)
if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
{
if (c == 0xA0)
- nonascii_space_p = 1;
+ nonascii_space_p = true;
else if (c == 0xAD || c == 0x2010 || c == 0x2011)
- nonascii_hyphen_p = 1;
+ nonascii_hyphen_p = true;
}
/* Translate control characters into `\003' or `^C' form.
@@ -6823,7 +6945,7 @@ get_next_display_element (struct it *it)
Non-printable characters and raw-byte characters are also
translated to octal form. */
- if (((c < ' ' || c == 127) /* ASCII control chars */
+ if (((c < ' ' || c == 127) /* ASCII control chars. */
? (it->area != TEXT_AREA
/* In mode line, treat \n, \t like other crl chars. */
|| (c != '\t'
@@ -7024,22 +7146,44 @@ get_next_display_element (struct it *it)
If this is the last string character displayed, check
the next buffer location. */
else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
- && (it->current.overlay_string_index
- == it->n_overlay_strings - 1))
+ /* n_overlay_strings is unreliable unless
+ overlay_string_index is non-negative. */
+ && ((it->current.overlay_string_index >= 0
+ && (it->current.overlay_string_index
+ == it->n_overlay_strings - 1))
+ /* A string from display property. */
+ || it->from_disp_prop_p))
{
ptrdiff_t ignore;
int next_face_id;
struct text_pos pos = it->current.pos;
- INC_TEXT_POS (pos, it->multibyte_p);
- next_face_id = face_at_buffer_position
- (it->w, CHARPOS (pos), it->region_beg_charpos,
- it->region_end_charpos, &ignore,
- (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0,
- -1);
- it->end_of_box_run_p
- = (FACE_FROM_ID (it->f, next_face_id)->box
- == FACE_NO_BOX);
+ /* For a string from a display property, the next
+ buffer position is stored in the 'position'
+ member of the iteration stack slot below the
+ current one, see handle_single_display_spec. By
+ contrast, it->current.pos was is not yet updated
+ to point to that buffer position; that will
+ happen in pop_it, after we finish displaying the
+ current string. Note that we already checked
+ above that it->sp is positive, so subtracting one
+ from it is safe. */
+ if (it->from_disp_prop_p)
+ pos = (it->stack + it->sp - 1)->position;
+ else
+ INC_TEXT_POS (pos, it->multibyte_p);
+
+ if (CHARPOS (pos) >= ZV)
+ it->end_of_box_run_p = true;
+ else
+ {
+ next_face_id = face_at_buffer_position
+ (it->w, CHARPOS (pos), &ignore,
+ CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, 0, -1);
+ it->end_of_box_run_p
+ = (FACE_FROM_ID (it->f, next_face_id)->box
+ == FACE_NO_BOX);
+ }
}
}
}
@@ -7269,12 +7413,12 @@ set_iterator_to_next (struct it *it, int reseat_p)
if (it->method == GET_FROM_STRING
&& it->current.overlay_string_index >= 0
&& it->n_overlay_strings > 0)
- it->ignore_overlay_strings_at_pos_p = 1;
+ it->ignore_overlay_strings_at_pos_p = true;
it->len = it->dpvec_char_len;
set_iterator_to_next (it, reseat_p);
}
- /* Maybe recheck faces after display vector */
+ /* Maybe recheck faces after display vector. */
if (recheck_faces)
it->stop_charpos = IT_CHARPOS (*it);
}
@@ -7299,7 +7443,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
else
{
/* Not an overlay string. There could be padding, so test
- against it->end_charpos . */
+ against it->end_charpos. */
if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
goto consider_string_end;
}
@@ -7811,7 +7955,7 @@ next_element_from_string (struct it *it)
static int
next_element_from_c_string (struct it *it)
{
- int success_p = 1;
+ bool success_p = true;
eassert (it->s);
eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
@@ -7870,7 +8014,7 @@ next_element_from_ellipsis (struct it *it)
it->method = GET_FROM_BUFFER;
it->object = it->w->contents;
reseat_at_next_visible_line_start (it, 1);
- it->face_before_selective_p = 1;
+ it->face_before_selective_p = true;
}
return GET_NEXT_DISPLAY_ELEMENT (it);
@@ -7939,7 +8083,7 @@ compute_stop_pos_backwards (struct it *it)
it->prev_stop = it->stop_charpos;
else
it->prev_stop = BEGV;
- it->bidi_p = 1;
+ it->bidi_p = true;
it->current = save_current;
it->position = save_position;
it->stop_charpos = save_stop_pos;
@@ -7985,7 +8129,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
}
while (charpos <= where_we_are);
- it->bidi_p = 1;
+ it->bidi_p = true;
it->current = save_current;
it->position = save_position;
next_stop = it->stop_charpos;
@@ -8002,7 +8146,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
static int
next_element_from_buffer (struct it *it)
{
- int success_p = 1;
+ bool success_p = true;
eassert (IT_CHARPOS (*it) >= BEGV);
eassert (NILP (it->string) && !it->s);
@@ -8032,7 +8176,7 @@ next_element_from_buffer (struct it *it)
overlay_strings_follow_p = 0;
else
{
- it->overlay_strings_at_end_processed_p = 1;
+ it->overlay_strings_at_end_processed_p = true;
overlay_strings_follow_p = get_overlay_strings (it, 0);
}
@@ -8125,7 +8269,7 @@ next_element_from_buffer (struct it *it)
/* Get the next character, maybe multibyte. */
p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
- if (it->multibyte_p && !ASCII_BYTE_P (*p))
+ if (it->multibyte_p && !ASCII_CHAR_P (*p))
it->c = STRING_CHAR_AND_LENGTH (p, it->len);
else
it->c = *p, it->len = 1;
@@ -8305,7 +8449,7 @@ move_it_in_display_line_to (struct it *it,
void *ppos_data = NULL;
int may_wrap = 0;
enum it_method prev_method = it->method;
- ptrdiff_t prev_pos = IT_CHARPOS (*it);
+ ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it);
int saw_smaller_pos = prev_pos < to_charpos;
/* Don't produce glyphs in produce_glyphs. */
@@ -8322,16 +8466,21 @@ move_it_in_display_line_to (struct it *it,
atx_it.sp = -1;
/* Use ppos_it under bidi reordering to save a copy of IT for the
- position > CHARPOS that is the closest to CHARPOS. We restore
- that position in IT when we have scanned the entire display line
- without finding a match for CHARPOS and all the character
- positions are greater than CHARPOS. */
+ initial position. We restore that position in IT when we have
+ scanned the entire display line without finding a match for
+ TO_CHARPOS and all the character positions are greater than
+ TO_CHARPOS. We then restart the scan from the initial position,
+ and stop at CLOSEST_POS, which is a position > TO_CHARPOS that is
+ the closest to TO_CHARPOS. */
if (it->bidi_p)
{
- SAVE_IT (ppos_it, *it, ppos_data);
- SET_TEXT_POS (ppos_it.current.pos, ZV, ZV_BYTE);
if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
- SAVE_IT (ppos_it, *it, ppos_data);
+ {
+ SAVE_IT (ppos_it, *it, ppos_data);
+ closest_pos = IT_CHARPOS (*it);
+ }
+ else
+ closest_pos = ZV;
}
#define BUFFER_POS_REACHED_P() \
@@ -8422,7 +8571,7 @@ move_it_in_display_line_to (struct it *it,
}
else
{
- if (it->line_wrap == WORD_WRAP)
+ if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
{
if (IT_DISPLAYING_WHITESPACE (it))
may_wrap = 1;
@@ -8475,8 +8624,8 @@ move_it_in_display_line_to (struct it *it,
if (it->bidi_p
&& (op & MOVE_TO_POS)
&& IT_CHARPOS (*it) > to_charpos
- && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
- SAVE_IT (ppos_it, *it, ppos_data);
+ && IT_CHARPOS (*it) < closest_pos)
+ closest_pos = IT_CHARPOS (*it);
continue;
}
@@ -8556,7 +8705,12 @@ move_it_in_display_line_to (struct it *it,
doesn't fit on the line, e.g. a wide image. */
it->hpos == 0
|| (new_x == it->last_visible_x
- && FRAME_WINDOW_P (it->f)))
+ && FRAME_WINDOW_P (it->f)
+ /* When word-wrap is ON and we have a valid
+ wrap point, we don't allow the last glyph
+ to "just barely fit" on the line. */
+ && (it->line_wrap != WORD_WRAP
+ || wrap_it.sp < 0)))
{
++it->hpos;
it->current_x = new_x;
@@ -8698,9 +8852,14 @@ move_it_in_display_line_to (struct it *it,
{
if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
{
- if (IT_CHARPOS (ppos_it) < ZV)
+ if (closest_pos < ZV)
{
RESTORE_IT (it, &ppos_it, ppos_data);
+ /* Don't recurse if closest_pos is equal to
+ to_charpos, since we have just tried that. */
+ if (closest_pos != to_charpos)
+ move_it_in_display_line_to (it, closest_pos, -1,
+ MOVE_TO_POS);
result = MOVE_POS_MATCH_OR_ZV;
}
else
@@ -8730,8 +8889,8 @@ move_it_in_display_line_to (struct it *it,
if (it->bidi_p
&& (op & MOVE_TO_POS)
&& IT_CHARPOS (*it) >= to_charpos
- && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
- SAVE_IT (ppos_it, *it, ppos_data);
+ && IT_CHARPOS (*it) < closest_pos)
+ closest_pos = IT_CHARPOS (*it);
/* Stop if lines are truncated and IT's current x-position is
past the right edge of the window now. */
@@ -8757,8 +8916,14 @@ move_it_in_display_line_to (struct it *it,
&& IT_CHARPOS (*it) > to_charpos))
{
if (it->bidi_p
- && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
- RESTORE_IT (it, &ppos_it, ppos_data);
+ && !BUFFER_POS_REACHED_P ()
+ && !at_eob_p && closest_pos < ZV)
+ {
+ RESTORE_IT (it, &ppos_it, ppos_data);
+ if (closest_pos != to_charpos)
+ move_it_in_display_line_to (it, closest_pos, -1,
+ MOVE_TO_POS);
+ }
result = MOVE_POS_MATCH_OR_ZV;
break;
}
@@ -8772,8 +8937,13 @@ move_it_in_display_line_to (struct it *it,
&& !saw_smaller_pos
&& IT_CHARPOS (*it) > to_charpos)
{
- if (IT_CHARPOS (ppos_it) < ZV)
- RESTORE_IT (it, &ppos_it, ppos_data);
+ if (closest_pos < ZV)
+ {
+ RESTORE_IT (it, &ppos_it, ppos_data);
+ if (closest_pos != to_charpos)
+ move_it_in_display_line_to (it, closest_pos, -1,
+ MOVE_TO_POS);
+ }
result = MOVE_POS_MATCH_OR_ZV;
break;
}
@@ -8852,13 +9022,17 @@ move_it_in_display_line (struct it *it,
If TO_CHARPOS is in invisible text, e.g. a truncated part of a
screen line, this function will set IT to the next position that is
- displayed to the right of TO_CHARPOS on the screen. */
+ displayed to the right of TO_CHARPOS on the screen.
-void
+ Return the maximum pixel length of any line scanned but never more
+ than it.last_visible_x. */
+
+int
move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
{
enum move_it_result skip, skip2 = MOVE_X_REACHED;
int line_height, line_start_x = 0, reached = 0;
+ int max_current_x = 0;
void *backup_data = NULL;
for (;;)
@@ -8989,6 +9163,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
if (to_y >= it->current_y
&& to_y < it->current_y + line_height)
{
+ if (to_y > it->current_y)
+ max_current_x = max (it->current_x, max_current_x);
+
/* When word-wrap is on, TO_X may lie past the end
of a wrapped line. Then it->current is the
character on the next line, so backtrack to the
@@ -9001,12 +9178,16 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
skip = move_it_in_display_line_to
(it, -1, prev_x, MOVE_TO_X);
}
+
reached = 6;
}
}
if (reached)
- break;
+ {
+ max_current_x = max (it->current_x, max_current_x);
+ break;
+ }
}
else if (BUFFERP (it->object)
&& (it->method == GET_FROM_BUFFER
@@ -9026,15 +9207,18 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
switch (skip)
{
case MOVE_POS_MATCH_OR_ZV:
+ max_current_x = max (it->current_x, max_current_x);
reached = 8;
goto out;
case MOVE_NEWLINE_OR_CR:
+ max_current_x = max (it->current_x, max_current_x);
set_iterator_to_next (it, 1);
it->continuation_lines_width = 0;
break;
case MOVE_LINE_TRUNCATED:
+ max_current_x = it->last_visible_x;
it->continuation_lines_width = 0;
reseat_at_next_visible_line_start (it, 0);
if ((op & MOVE_TO_POS) != 0
@@ -9046,6 +9230,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
break;
case MOVE_LINE_CONTINUED:
+ max_current_x = it->last_visible_x;
/* For continued lines ending in a tab, some of the glyphs
associated with the tab are displayed on the current
line. Since it->current_x does not include these glyphs,
@@ -9113,6 +9298,8 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
bidi_unshelve_cache (backup_data, 1);
TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
+
+ return max_current_x;
}
@@ -9337,7 +9524,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
/* The commented-out optimization uses vmotion on terminals. This
gives bad results, because elements like it->what, on which
- callers such as pos_visible_p rely, aren't updated. */
+ callers such as pos_visible_p rely, aren't updated. */
/* struct position pos;
if (!FRAME_WINDOW_P (it->f))
{
@@ -9355,7 +9542,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
{
/* DVPOS == 0 means move to the start of the screen line. */
move_it_vertically_backward (it, 0);
- /* Let next call to line_bottom_y calculate real line height */
+ /* Let next call to line_bottom_y calculate real line height. */
last_height = 0;
}
else if (dvpos > 0)
@@ -9384,6 +9571,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
ptrdiff_t start_charpos, i;
int nchars_per_row
= (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+ bool hit_pos_limit = false;
ptrdiff_t pos_limit;
/* Start at the beginning of the screen line containing IT's
@@ -9400,8 +9588,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
pos_limit = BEGV;
else
pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+
for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
back_to_previous_visible_line_start (it);
+ if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
+ hit_pos_limit = true;
reseat (it, it->current.pos, 1);
/* Move further back if we end up in a string or an image. */
@@ -9445,14 +9636,33 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
else
bidi_unshelve_cache (it2data, 1);
}
+ else if (hit_pos_limit && pos_limit > BEGV
+ && dvpos < 0 && it2.vpos < -dvpos)
+ {
+ /* If we hit the limit, but still didn't make it far enough
+ back, that means there's a display string with a newline
+ covering a large chunk of text, and that caused
+ back_to_previous_visible_line_start try to go too far.
+ Punish those who commit such atrocities by going back
+ until we've reached DVPOS, after lifting the limit, which
+ could make it slow for very long lines. "If it hurts,
+ don't do that!" */
+ dvpos += it2.vpos;
+ RESTORE_IT (it, it, it2data);
+ for (i = -dvpos; i > 0; --i)
+ {
+ back_to_previous_visible_line_start (it);
+ it->vpos--;
+ }
+ }
else
RESTORE_IT (it, it, it2data);
}
}
-/* Return 1 if IT points into the middle of a display vector. */
+/* Return true if IT points into the middle of a display vector. */
-int
+bool
in_display_vector_p (struct it *it)
{
return (it->method == GET_FROM_DISPLAY_VECTOR
@@ -9460,6 +9670,141 @@ in_display_vector_p (struct it *it)
&& it->dpvec + it->current.dpvec_index != it->dpend);
}
+DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0,
+ doc: /* Return the size of the text of WINDOW's buffer in pixels.
+WINDOW must be a live window and defaults to the selected one. The
+return value is a cons of the maximum pixel-width of any text line and
+the maximum pixel-height of all text lines.
+
+The optional argument FROM, if non-nil, specifies the first text
+position and defaults to the minimum accessible position of the buffer.
+If FROM is t, use the minimum accessible position that is not a newline
+character. TO, if non-nil, specifies the last text position and
+defaults to the maximum accessible position of the buffer. If TO is t,
+use the maximum accessible position that is not a newline character.
+
+The optional argument X-LIMIT, if non-nil, specifies the maximum text
+width that can be returned. X-LIMIT nil or omitted, means to use the
+pixel-width of WINDOW's body; use this if you do not intend to change
+the width of WINDOW. Use the maximum width WINDOW may assume if you
+intend to change WINDOW's width. In any case, text whose x-coordinate
+is beyond X-LIMIT is ignored. Since calculating the width of long lines
+can take some time, it's always a good idea to make this argument as
+small as possible; in particular, if the buffer contains long lines that
+shall be truncated anyway.
+
+The optional argument Y-LIMIT, if non-nil, specifies the maximum text
+height that can be returned. Text lines whose y-coordinate is beyond
+Y-LIMIT are ignored. Since calculating the text height of a large
+buffer can take some time, it makes sense to specify this argument if
+the size of the buffer is unknown.
+
+Optional argument MODE-AND-HEADER-LINE nil or omitted means do not
+include the height of the mode- or header-line of WINDOW in the return
+value. If it is either the symbol `mode-line' or `header-line', include
+only the height of that line, if present, in the return value. If t,
+include the height of both, if present, in the return value. */)
+ (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
+ Lisp_Object mode_and_header_line)
+{
+ struct window *w = decode_live_window (window);
+ Lisp_Object buf;
+ struct buffer *b;
+ struct it it;
+ struct buffer *old_buffer = NULL;
+ ptrdiff_t start, end, pos;
+ struct text_pos startp;
+ void *itdata = NULL;
+ int c, max_y = -1, x = 0, y = 0;
+
+ buf = w->contents;
+ CHECK_BUFFER (buf);
+ b = XBUFFER (buf);
+
+ if (b != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (b);
+ }
+
+ if (NILP (from))
+ start = BEGV;
+ else if (EQ (from, Qt))
+ {
+ start = pos = BEGV;
+ while ((pos++ < ZV) && (c = FETCH_CHAR (pos))
+ && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+ start = pos;
+ while ((pos-- > BEGV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+ start = pos;
+ }
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (from);
+ start = min (max (XINT (from), BEGV), ZV);
+ }
+
+ if (NILP (to))
+ end = ZV;
+ else if (EQ (to, Qt))
+ {
+ end = pos = ZV;
+ while ((pos-- > BEGV) && (c = FETCH_CHAR (pos))
+ && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+ end = pos;
+ while ((pos++ < ZV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+ end = pos;
+ }
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (to);
+ end = max (start, min (XINT (to), ZV));
+ }
+
+ if (!NILP (y_limit))
+ {
+ CHECK_NUMBER (y_limit);
+ max_y = min (XINT (y_limit), INT_MAX);
+ }
+
+ itdata = bidi_shelve_cache ();
+ SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
+ start_display (&it, w, startp);
+
+ if (NILP (x_limit))
+ x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
+ else
+ {
+ CHECK_NUMBER (x_limit);
+ it.last_visible_x = min (XINT (x_limit), INFINITY);
+ /* Actually, we never want move_it_to stop at to_x. But to make
+ sure that move_it_in_display_line_to always moves far enough,
+ we set it to INT_MAX and specify MOVE_TO_X. */
+ x = move_it_to (&it, end, INT_MAX, max_y, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ }
+
+ y = it.current_y + it.max_ascent + it.max_descent;
+
+ if (!EQ (mode_and_header_line, Qheader_line)
+ && !EQ (mode_and_header_line, Qt))
+ /* Do not count the header-line which was counted automatically by
+ start_display. */
+ y = y - WINDOW_HEADER_LINE_HEIGHT (w);
+
+ if (EQ (mode_and_header_line, Qmode_line)
+ || EQ (mode_and_header_line, Qt))
+ /* Do count the mode-line which is not included automatically by
+ start_display. */
+ y = y + WINDOW_MODE_LINE_HEIGHT (w);
+
+ bidi_unshelve_cache (itdata, 0);
+
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+
+ return Fcons (make_number (x), make_number (y));
+}
/***********************************************************************
Messages
@@ -9533,7 +9878,6 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
ptrdiff_t point_at_end = 0;
ptrdiff_t zv_at_end = 0;
Lisp_Object old_deactivate_mark;
- bool shown;
struct gcpro gcpro1;
old_deactivate_mark = Vdeactivate_mark;
@@ -9547,12 +9891,13 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
- if (newbuffer &&
- !NILP (Ffboundp (intern ("messages-buffer-mode"))))
+ if (newbuffer
+ && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
call0 (intern ("messages-buffer-mode"));
}
bset_undo_list (current_buffer, Qt);
+ bset_cache_long_scans (current_buffer, Qnil);
oldpoint = message_dolog_marker1;
set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
@@ -9587,9 +9932,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
for (i = 0; i < nbytes; i += char_bytes)
{
c = string_char_and_length (msg + i, &char_bytes);
- work[0] = (ASCII_CHAR_P (c)
- ? c
- : multibyte_char_to_unibyte (c));
+ work[0] = CHAR_TO_BYTE8 (c);
insert_1_both (work, 1, 1, 1, 0, 0);
}
}
@@ -9689,18 +10032,17 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
unchain_marker (XMARKER (oldbegv));
unchain_marker (XMARKER (oldzv));
- shown = buffer_window_count (current_buffer) > 0;
- set_buffer_internal (oldbuf);
/* We called insert_1_both above with its 5th argument (PREPARE)
zero, which prevents insert_1_both from calling
prepare_to_modify_buffer, which in turns prevents us from
incrementing windows_or_buffers_changed even if *Messages* is
- shown in some window. So we must manually incrementing
+ shown in some window. So we must manually set
windows_or_buffers_changed here to make up for that. */
- if (shown)
- windows_or_buffers_changed++;
- else
- windows_or_buffers_changed = old_windows_or_buffers_changed;
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
+ bset_redisplay (current_buffer);
+
+ set_buffer_internal (oldbuf);
+
message_log_need_newline = !nlflag;
Vdeactivate_mark = old_deactivate_mark;
}
@@ -9756,7 +10098,7 @@ message3 (Lisp_Object m)
struct gcpro gcpro1;
GCPRO1 (m);
- clear_message (1,1);
+ clear_message (true, true);
cancel_echoing ();
/* First flush out any partial line written with print. */
@@ -9793,7 +10135,11 @@ message3_nolog (Lisp_Object m)
putc ('\n', stderr);
noninteractive_need_newline = 0;
if (STRINGP (m))
- fwrite (SDATA (m), SBYTES (m), 1, stderr);
+ {
+ Lisp_Object s = ENCODE_SYSTEM (m);
+
+ fwrite (SDATA (s), SBYTES (s), 1, stderr);
+ }
if (cursor_in_echo_area == 0)
fprintf (stderr, "\n");
fflush (stderr);
@@ -9822,7 +10168,7 @@ message3_nolog (Lisp_Object m)
echo_message_buffer = Qnil;
}
else
- clear_message (1, 1);
+ clear_message (true, true);
do_pending_window_change (0);
echo_area_display (1);
@@ -9868,10 +10214,14 @@ message_with_string (const char *m, Lisp_Object string, int log)
{
if (m)
{
+ /* ENCODE_SYSTEM below can GC and/or relocate the
+ Lisp data, so make sure we don't use it here. */
+ eassert (relocatable_string_data_p (m) != 1);
+
if (noninteractive_need_newline)
putc ('\n', stderr);
noninteractive_need_newline = 0;
- fprintf (stderr, m, SDATA (string));
+ fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
if (!cursor_in_echo_area)
fprintf (stderr, "\n");
fflush (stderr);
@@ -10075,7 +10425,7 @@ with_echo_area_buffer (struct window *w, int which,
{
Lisp_Object buffer;
int this_one, the_other, clear_buffer_p, rc;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
/* If buffers aren't live, make new ones. */
ensure_echo_area_buffers ();
@@ -10089,7 +10439,7 @@ with_echo_area_buffer (struct window *w, int which,
else
{
this_one = 0, the_other = 1;
- clear_buffer_p = 1;
+ clear_buffer_p = true;
/* We need a fresh one in case the current echo buffer equals
the one containing the last displayed echo area message. */
@@ -10106,7 +10456,7 @@ with_echo_area_buffer (struct window *w, int which,
= (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
? echo_buffer[the_other]
: echo_buffer[this_one]);
- clear_buffer_p = 1;
+ clear_buffer_p = true;
}
buffer = echo_area_buffer[this_one];
@@ -10149,7 +10499,7 @@ with_echo_area_buffer (struct window *w, int which,
eassert (BEGV >= BEG);
eassert (ZV <= Z && ZV >= BEGV);
- unbind_to (count, Qnil);
+ dynwind_end ();
return rc;
}
@@ -10254,11 +10604,11 @@ setup_echo_area_for_printing (int multibyte_p)
if (Z > BEG)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_read_only, Qt);
/* Note that undo recording is always disabled. */
del_range (BEG, Z);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
@@ -10309,13 +10659,6 @@ display_echo_area (struct window *w)
{
int i, no_message_p, window_height_changed_p;
- /* Temporarily disable garbage collections while displaying the echo
- area. This is done because a GC can print a message itself.
- That message would modify the echo area buffer's contents while a
- redisplay of the buffer is going on, and seriously confuse
- redisplay. */
- ptrdiff_t count = inhibit_garbage_collection ();
-
/* If there is no message, we must call display_echo_area_1
nevertheless because it resizes the window. But we will have to
reset the echo_area_buffer in question to nil at the end because
@@ -10331,7 +10674,6 @@ display_echo_area (struct window *w)
if (no_message_p)
echo_area_buffer[i] = Qnil;
- unbind_to (count, Qnil);
return window_height_changed_p;
}
@@ -10379,20 +10721,13 @@ resize_echo_area_exactly (void)
&& WINDOWP (echo_area_window))
{
struct window *w = XWINDOW (echo_area_window);
- int resized_p;
- Lisp_Object resize_exactly;
-
- if (minibuf_level == 0)
- resize_exactly = Qt;
- else
- resize_exactly = Qnil;
-
- resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
+ Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
+ int resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
(intptr_t) w, resize_exactly);
if (resized_p)
{
- ++windows_or_buffers_changed;
- ++update_mode_lines;
+ windows_or_buffers_changed = 42;
+ update_mode_lines = 30;
redisplay_internal ();
}
}
@@ -10454,11 +10789,10 @@ resize_mini_window (struct window *w, int exact_p)
if (!FRAME_MINIBUF_ONLY_P (f))
{
struct it it;
- struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
- int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
- int height;
- EMACS_INT max_height;
+ int total_height = (WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)))
+ + WINDOW_PIXEL_HEIGHT (w));
int unit = FRAME_LINE_HEIGHT (f);
+ int height, max_height;
struct text_pos start;
struct buffer *old_current_buffer = NULL;
@@ -10472,18 +10806,18 @@ resize_mini_window (struct window *w, int exact_p)
/* Compute the max. number of lines specified by the user. */
if (FLOATP (Vmax_mini_window_height))
- max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
+ max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
else if (INTEGERP (Vmax_mini_window_height))
- max_height = XINT (Vmax_mini_window_height);
+ max_height = XINT (Vmax_mini_window_height) * unit;
else
max_height = total_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = clip_to_bounds (1, max_height, total_height);
+ max_height = clip_to_bounds (unit, max_height, total_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
- height = 1;
+ height = unit;
else
{
last_height = 0;
@@ -10493,15 +10827,14 @@ resize_mini_window (struct window *w, int exact_p)
else
height = it.current_y + it.max_ascent + it.max_descent;
height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
- height = (height + unit - 1) / unit;
}
/* Compute a suitable window start. */
if (height > max_height)
{
- height = max_height;
+ height = (max_height / unit) * unit;
init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
- move_it_vertically_backward (&it, (height - 1) * unit);
+ move_it_vertically_backward (&it, height - unit);
start = it.current.pos;
}
else
@@ -10512,49 +10845,49 @@ resize_mini_window (struct window *w, int exact_p)
{
/* Let it grow only, until we display an empty message, in which
case the window shrinks again. */
- if (height > WINDOW_TOTAL_LINES (w))
+ if (height > WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
- else if (height < WINDOW_TOTAL_LINES (w)
+ else if (height < WINDOW_PIXEL_HEIGHT (w)
&& (exact_p || BEGV == ZV))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 0;
- shrink_mini_window (w);
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ shrink_mini_window (w, 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
}
else
{
/* Always resize to exact size needed. */
- if (height > WINDOW_TOTAL_LINES (w))
+ if (height > WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
- else if (height < WINDOW_TOTAL_LINES (w))
+ else if (height < WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 0;
- shrink_mini_window (w);
+ shrink_mini_window (w, 1);
if (height)
{
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
}
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
}
@@ -10739,12 +11072,12 @@ set_message_1 (ptrdiff_t a1, Lisp_Object string)
last displayed. */
void
-clear_message (int current_p, int last_displayed_p)
+clear_message (bool current_p, bool last_displayed_p)
{
if (current_p)
{
echo_area_buffer[0] = Qnil;
- message_cleared_p = 1;
+ message_cleared_p = true;
}
if (last_displayed_p)
@@ -10768,7 +11101,6 @@ clear_garbaged_frames (void)
if (frame_garbaged)
{
Lisp_Object tail, frame;
- int changed_count = 0;
FOR_EACH_FRAME (tail, frame)
{
@@ -10780,15 +11112,13 @@ clear_garbaged_frames (void)
redraw_frame (f);
else
clear_current_matrices (f);
- changed_count++;
- f->garbaged = 0;
- f->resized_p = 0;
+ fset_redisplay (f);
+ f->garbaged = false;
+ f->resized_p = false;
}
}
- frame_garbaged = 0;
- if (changed_count)
- ++windows_or_buffers_changed;
+ frame_garbaged = false;
}
}
@@ -10829,7 +11159,7 @@ echo_area_display (int update_frame_p)
{
echo_area_window = mini_window;
window_height_changed_p = display_echo_area (w);
- w->must_be_updated_p = 1;
+ w->must_be_updated_p = true;
/* Update the display, unless called from redisplay_internal.
Also don't update the screen during redisplay itself. The
@@ -10845,7 +11175,7 @@ echo_area_display (int update_frame_p)
been called, so that mode lines above the echo area are
garbaged. This looks odd, so we prevent it here. */
if (!display_completed)
- n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
+ n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
if (window_height_changed_p
/* Don't do this if Emacs is shutting down. Redisplay
@@ -10855,11 +11185,11 @@ echo_area_display (int update_frame_p)
/* Must update other windows. Likewise as in other
cases, don't let this update be interrupted by
pending input. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qredisplay_dont_pause, Qt);
- windows_or_buffers_changed = 1;
+ windows_or_buffers_changed = 44;
redisplay_internal ();
- unbind_to (count, Qnil);
+ dynwind_end ();
}
else if (FRAME_WINDOW_P (f) && n == 0)
{
@@ -10876,11 +11206,11 @@ echo_area_display (int update_frame_p)
redisplay displays the minibuffer, so that the cursor will
be replaced with what the minibuffer wants. */
if (cursor_in_echo_area)
- ++windows_or_buffers_changed;
+ wset_redisplay (XWINDOW (mini_window));
}
}
else if (!EQ (mini_window, selected_window))
- windows_or_buffers_changed++;
+ wset_redisplay (XWINDOW (mini_window));
/* Last displayed message is now the current message. */
echo_area_buffer[1] = echo_area_buffer[0];
@@ -10896,18 +11226,7 @@ echo_area_display (int update_frame_p)
return window_height_changed_p;
}
-/* Nonzero if the current window's buffer is shown in more than one
- window and was modified since last redisplay. */
-
-static int
-buffer_shared_and_changed (void)
-{
- return (buffer_window_count (current_buffer) > 1
- && UNCHANGED_MODIFIED < MODIFF);
-}
-
-/* Nonzero if W's buffer was changed but not saved or Transient Mark mode
- is enabled and mark of W's buffer was changed since last W's update. */
+/* Nonzero if W's buffer was changed but not saved. */
static int
window_buffer_changed (struct window *w)
@@ -10916,9 +11235,7 @@ window_buffer_changed (struct window *w)
eassert (BUFFER_LIVE_P (b));
- return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
- || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
- != (w->region_showing != 0)));
+ return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star));
}
/* Nonzero if W has %c in its mode line and mode line should be updated. */
@@ -11164,7 +11481,7 @@ x_consider_frame_title (Lisp_Object frame)
char *title;
ptrdiff_t len;
struct it it;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
FOR_EACH_FRAME (tail, other_frame)
{
@@ -11200,7 +11517,7 @@ x_consider_frame_title (Lisp_Object frame)
display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
len = MODE_LINE_NOPROP_LEN (title_start);
title = mode_line_noprop_buf + title_start;
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Set the title only if it's changed. This avoids consing in
the common case where it hasn't. (If it turns out that we've
@@ -11221,16 +11538,22 @@ x_consider_frame_title (Lisp_Object frame)
Menu Bars
***********************************************************************/
+/* Non-zero if we will not redisplay all visible windows. */
+#define REDISPLAY_SOME_P() \
+ ((windows_or_buffers_changed == 0 \
+ || windows_or_buffers_changed == REDISPLAY_SOME) \
+ && (update_mode_lines == 0 \
+ || update_mode_lines == REDISPLAY_SOME))
/* Prepare for redisplay by updating menu-bar item lists when
appropriate. This can call eval. */
-void
+static void
prepare_menu_bars (void)
{
- int all_windows;
+ bool all_windows = windows_or_buffers_changed || update_mode_lines;
+ bool some_windows = REDISPLAY_SOME_P ();
struct gcpro gcpro1, gcpro2;
- struct frame *f;
Lisp_Object tooltip_frame;
#ifdef HAVE_WINDOW_SYSTEM
@@ -11239,17 +11562,45 @@ prepare_menu_bars (void)
tooltip_frame = Qnil;
#endif
+ if (FUNCTIONP (Vpre_redisplay_function))
+ {
+ Lisp_Object windows = all_windows ? Qt : Qnil;
+ if (all_windows && some_windows)
+ {
+ Lisp_Object ws = window_list ();
+ for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
+ {
+ Lisp_Object this = XCAR (ws);
+ struct window *w = XWINDOW (this);
+ if (w->redisplay
+ || XFRAME (w->frame)->redisplay
+ || XBUFFER (w->contents)->text->redisplay)
+ {
+ windows = Fcons (this, windows);
+ }
+ }
+ }
+ safe__call1 (true, Vpre_redisplay_function, windows);
+ }
+
/* Update all frame titles based on their buffer names, etc. We do
this before the menu bars so that the buffer-menu will show the
up-to-date frame titles. */
#ifdef HAVE_WINDOW_SYSTEM
- if (windows_or_buffers_changed || update_mode_lines)
+ if (all_windows)
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
{
- f = XFRAME (frame);
+ struct frame *f = XFRAME (frame);
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+ if (some_windows
+ && !f->redisplay
+ && !w->redisplay
+ && !XBUFFER (w->contents)->text->redisplay)
+ continue;
+
if (!EQ (frame, tooltip_frame)
&& (FRAME_ICONIFIED_P (f)
|| FRAME_VISIBLE_P (f) == 1
@@ -11270,13 +11621,11 @@ prepare_menu_bars (void)
/* Update the menu bar item lists, if appropriate. This has to be
done before any actual redisplay or generation of display lines. */
- all_windows = (update_mode_lines
- || buffer_shared_and_changed ()
- || windows_or_buffers_changed);
+
if (all_windows)
{
Lisp_Object tail, frame;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
/* 1 means that update_menu_bar has run its hooks
so any further calls to update_menu_bar shouldn't do so again. */
int menu_bar_hooks_run = 0;
@@ -11285,12 +11634,19 @@ prepare_menu_bars (void)
FOR_EACH_FRAME (tail, frame)
{
- f = XFRAME (frame);
+ struct frame *f = XFRAME (frame);
+ struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
/* Ignore tooltip frame. */
if (EQ (frame, tooltip_frame))
continue;
+ if (some_windows
+ && !f->redisplay
+ && !w->redisplay
+ && !XBUFFER (w->contents)->text->redisplay)
+ continue;
+
/* If a window on this frame changed size, report that to
the user and clear the size-change flag. */
if (FRAME_WINDOW_SIZES_CHANGED (f))
@@ -11325,7 +11681,7 @@ prepare_menu_bars (void)
UNGCPRO;
}
- unbind_to (count, Qnil);
+ dynwind_end ();
}
else
{
@@ -11388,7 +11744,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
|| window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
specbind (Qinhibit_menubar_update, Qt);
@@ -11441,7 +11797,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
w->update_mode_line = 1;
#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
- unbind_to (count, Qnil);
+ dynwind_end ();
set_buffer_internal_1 (prev);
}
}
@@ -11455,11 +11811,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
#ifdef HAVE_WINDOW_SYSTEM
-/* Tool-bar item index of the item on which a mouse button was pressed
- or -1. */
-
-int last_tool_bar_item;
-
/* Select `frame' temporarily without running all the code in
do_switch_frame.
FIXME: Maybe do_switch_frame should be trimmed down similarly
@@ -11485,8 +11836,8 @@ update_tool_bar (struct frame *f, int save_match_data)
#if defined (USE_GTK) || defined (HAVE_NS)
int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
#else
- int do_update = WINDOWP (f->tool_bar_window)
- && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
+ int do_update = (WINDOWP (f->tool_bar_window)
+ && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
#endif
if (do_update)
@@ -11510,7 +11861,7 @@ update_tool_bar (struct frame *f, int save_match_data)
|| window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object frame, new_tool_bar;
int new_n_tool_bar;
struct gcpro gcpro1;
@@ -11566,7 +11917,7 @@ update_tool_bar (struct frame *f, int save_match_data)
UNGCPRO;
- unbind_to (count, Qnil);
+ dynwind_end ();
set_buffer_internal_1 (prev);
}
}
@@ -11756,7 +12107,9 @@ display_tool_bar_line (struct it *it, int height)
int max_x = it->last_visible_x;
struct glyph *last;
- prepare_desired_row (row);
+ /* Don't extend on a previously drawn tool bar items (Bug#16058). */
+ clear_glyph_row (row);
+ row->enabled_p = true;
row->y = it->current_y;
/* Note that this isn't made use of if the face hasn't a box,
@@ -11868,21 +12221,22 @@ display_tool_bar_line (struct it *it, int height)
}
-/* Max tool-bar height. */
+/* Max tool-bar height. Basically, this is what makes all other windows
+ disappear when the frame gets too small. Rethink this! */
#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
-/* Value is the number of screen lines needed to make all tool-bar
- items of frame F visible. The number of actual rows needed is
+/* Value is the number of pixels needed to make all tool-bar items of
+ frame F visible. The actual number of glyph rows needed is
returned in *N_ROWS if non-NULL. */
static int
-tool_bar_lines_needed (struct frame *f, int *n_rows)
+tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
{
struct window *w = XWINDOW (f->tool_bar_window);
struct it it;
- /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+ /* tool_bar_height is called from redisplay_tool_bar after building
the desired matrix, so use (unused) mode-line row as temporary row to
avoid destroying the first tool-bar row. */
struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
@@ -11891,7 +12245,7 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
F->desired_tool_bar_string in the tool-bar window of frame F. */
init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
it.paragraph_embedding = L2R;
@@ -11907,39 +12261,39 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
if (n_rows)
*n_rows = it.vpos > 0 ? it.vpos : -1;
- return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
+ if (pixelwise)
+ return it.current_y;
+ else
+ return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
}
#endif /* !USE_GTK && !HAVE_NS */
-#if defined USE_GTK || defined HAVE_NS
-EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
-#endif
-
-DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
- 0, 1, 0,
+DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
+ 0, 2, 0,
doc: /* Return the number of lines occupied by the tool bar of FRAME.
-If FRAME is nil or omitted, use the selected frame. */)
- (Lisp_Object frame)
+If FRAME is nil or omitted, use the selected frame. Optional argument
+PIXELWISE non-nil means return the height of the tool bar in pixels. */)
+ (Lisp_Object frame, Lisp_Object pixelwise)
{
- int nlines = 0;
+ int height = 0;
+
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
struct frame *f = decode_any_frame (frame);
- struct window *w;
if (WINDOWP (f->tool_bar_window)
- && (w = XWINDOW (f->tool_bar_window),
- WINDOW_TOTAL_LINES (w) > 0))
+ && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
{
update_tool_bar (f, 1);
if (f->n_tool_bar_items)
{
build_desired_tool_bar_string (f);
- nlines = tool_bar_lines_needed (f, NULL);
+ height = tool_bar_height (f, NULL, NILP (pixelwise) ? 0 : 1);
}
}
#endif
- return make_number (nlines);
+
+ return make_number (height);
}
@@ -11967,13 +12321,13 @@ redisplay_tool_bar (struct frame *f)
can turn off tool-bars by specifying tool-bar-lines zero. */
if (!WINDOWP (f->tool_bar_window)
|| (w = XWINDOW (f->tool_bar_window),
- WINDOW_TOTAL_LINES (w) == 0))
+ WINDOW_PIXEL_HEIGHT (w) == 0))
return 0;
/* Set up an iterator for the tool-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
row = it.glyph_row;
/* Build a string that represents the contents of the tool-bar. */
@@ -11990,24 +12344,22 @@ redisplay_tool_bar (struct frame *f)
if (f->n_tool_bar_rows == 0)
{
- int nlines;
+ int new_height = tool_bar_height (f, &f->n_tool_bar_rows, 1);
- if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
- nlines != WINDOW_TOTAL_LINES (w)))
+ if (new_height != WINDOW_PIXEL_HEIGHT (w))
{
Lisp_Object frame;
- int old_height = WINDOW_TOTAL_LINES (w);
+ int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+ / FRAME_LINE_HEIGHT (f));
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame,
list1 (Fcons (Qtool_bar_lines,
- make_number (nlines))));
- if (WINDOW_TOTAL_LINES (w) != old_height)
- {
- clear_glyph_matrix (w->desired_matrix);
- f->fonts_changed = 1;
- return 1;
- }
+ make_number (new_lines))));
+ /* Always do that now. */
+ clear_glyph_matrix (w->desired_matrix);
+ f->fonts_changed = 1;
+ return 1;
}
}
@@ -12056,6 +12408,7 @@ redisplay_tool_bar (struct frame *f)
if (!NILP (Vauto_resize_tool_bars))
{
+ /* Do we really allow the toolbar to occupy the whole frame? */
int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
int change_height_p = 0;
@@ -12065,6 +12418,10 @@ redisplay_tool_bar (struct frame *f)
&& it.current_y < max_tool_bar_height)
change_height_p = 1;
+ /* We subtract 1 because display_tool_bar_line advances the
+ glyph_row pointer before returning to its caller. We want to
+ examine the last glyph row produced by
+ display_tool_bar_line. */
row = it.glyph_row - 1;
/* If there are blank lines at the end, except for a partially
@@ -12086,24 +12443,41 @@ redisplay_tool_bar (struct frame *f)
if (change_height_p)
{
Lisp_Object frame;
- int old_height = WINDOW_TOTAL_LINES (w);
int nrows;
- int nlines = tool_bar_lines_needed (f, &nrows);
+ int new_height = tool_bar_height (f, &nrows, 1);
change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
&& !f->minimize_tool_bar_window_p)
- ? (nlines > old_height)
- : (nlines != old_height));
+ ? (new_height > WINDOW_PIXEL_HEIGHT (w))
+ : (new_height != WINDOW_PIXEL_HEIGHT (w)));
f->minimize_tool_bar_window_p = 0;
if (change_height_p)
{
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (nlines))));
- if (WINDOW_TOTAL_LINES (w) != old_height)
+ /* Current size of the tool-bar window in canonical line
+ units. */
+ int old_lines = WINDOW_TOTAL_LINES (w);
+ /* Required size of the tool-bar window in canonical
+ line units. */
+ int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+ / FRAME_LINE_HEIGHT (f));
+ /* Maximum size of the tool-bar window in canonical line
+ units that this frame can allow. */
+ int max_lines =
+ WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
+
+ /* Don't try to change the tool-bar window size and set
+ the fonts_changed flag unless really necessary. That
+ flag causes redisplay to give up and retry
+ redisplaying the frame from scratch, so setting it
+ unnecessarily can lead to nasty redisplay loops. */
+ if (new_lines <= max_lines
+ && eabs (new_lines - old_lines) >= 1)
{
+ XSETFRAME (frame, f);
+ Fmodify_frame_parameters (frame,
+ list1 (Fcons (Qtool_bar_lines,
+ make_number (new_lines))));
clear_glyph_matrix (w->desired_matrix);
f->n_tool_bar_rows = nrows;
f->fonts_changed = 1;
@@ -12233,7 +12607,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
where the button was pressed, disregarding where it was
released. */
if (NILP (Vmouse_highlight) && !down_p)
- prop_idx = last_tool_bar_item;
+ prop_idx = f->last_tool_bar_item;
/* If item is disabled, do nothing. */
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
@@ -12245,7 +12619,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
/* Show item in pressed state. */
if (!NILP (Vmouse_highlight))
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- last_tool_bar_item = prop_idx;
+ f->last_tool_bar_item = prop_idx;
}
else
{
@@ -12270,7 +12644,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
event.arg = key;
event.modifiers = modifiers;
kbd_buffer_store_event (&event);
- last_tool_bar_item = -1;
+ f->last_tool_bar_item = -1;
}
}
@@ -12320,8 +12694,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
mouse_down_p = (x_mouse_grabbed (dpyinfo)
&& f == dpyinfo->last_mouse_frame);
- if (mouse_down_p
- && last_tool_bar_item != prop_idx)
+ if (mouse_down_p && f->last_tool_bar_item != prop_idx)
return;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
@@ -12418,15 +12791,25 @@ hscroll_window_tree (Lisp_Object window)
{
int h_margin;
int text_area_width;
- struct glyph_row *current_cursor_row
- = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
- struct glyph_row *desired_cursor_row
- = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
- struct glyph_row *cursor_row
- = (desired_cursor_row->enabled_p
- ? desired_cursor_row
- : current_cursor_row);
- int row_r2l_p = cursor_row->reversed_p;
+ struct glyph_row *cursor_row;
+ struct glyph_row *bottom_row;
+ int row_r2l_p;
+
+ bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
+ if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
+ cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
+ else
+ cursor_row = bottom_row - 1;
+
+ if (!cursor_row->enabled_p)
+ {
+ bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+ if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
+ cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+ else
+ cursor_row = bottom_row - 1;
+ }
+ row_r2l_p = cursor_row->reversed_p;
text_area_width = window_box_width (w, TEXT_AREA);
@@ -12437,7 +12820,7 @@ hscroll_window_tree (Lisp_Object window)
/* For left-to-right rows, hscroll when cursor is either
(i) inside the right hscroll margin, or (ii) if it is
inside the left margin and the window is already
- hscrolled. */
+ hscrolled. */
&& ((!row_r2l_p
&& ((w->hscroll
&& w->cursor.x <= h_margin)
@@ -12454,7 +12837,7 @@ hscroll_window_tree (Lisp_Object window)
&& ((cursor_row->enabled_p
/* FIXME: It is confusing to set the
truncated_on_right_p flag when R2L rows
- are actually truncated on the left. */
+ are actually truncated on the left. */
&& cursor_row->truncated_on_right_p
&& w->cursor.x <= h_margin)
|| (w->hscroll
@@ -12582,7 +12965,7 @@ static ptrdiff_t debug_delta, debug_delta_bytes;
static ptrdiff_t debug_end_vpos;
/* Append a string to W->desired_matrix->method. FMT is a printf
- format string. If trace_redisplay_p is non-zero also printf the
+ format string. If trace_redisplay_p is true also printf the
resulting string to stderr. */
static void debug_method_add (struct window *, char const *, ...)
@@ -12913,6 +13296,28 @@ reconsider_clip_changes (struct window *w)
}
}
+static void
+propagate_buffer_redisplay (void)
+{ /* Resetting b->text->redisplay is problematic!
+ We can't just reset it in the case that some window that displays
+ it has not been redisplayed; and such a window can stay
+ unredisplayed for a long time if it's currently invisible.
+ But we do want to reset it at the end of redisplay otherwise
+ its displayed windows will keep being redisplayed over and over
+ again.
+ So we copy all b->text->redisplay flags up to their windows here,
+ such that mark_window_display_accurate can safely reset
+ b->text->redisplay. */
+ Lisp_Object ws = window_list ();
+ for (; CONSP (ws); ws = XCDR (ws))
+ {
+ struct window *thisw = XWINDOW (XCAR (ws));
+ struct buffer *thisb = XBUFFER (thisw->contents);
+ if (thisb->text->redisplay)
+ thisw->redisplay = true;
+ }
+}
+
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
polling_stopped_here = 1; } while (0)
@@ -12940,12 +13345,12 @@ redisplay_internal (void)
int polling_stopped_here = 0;
Lisp_Object tail, frame;
- /* Non-zero means redisplay has to consider all windows on all
- frames. Zero means, only selected_window is considered. */
- int consider_all_windows_p;
+ /* True means redisplay has to consider all windows on all
+ frames. False, only selected_window is considered. */
+ bool consider_all_windows_p;
- /* Non-zero means redisplay has to redisplay the miniwindow. */
- int update_miniwindow_p = 0;
+ /* True means redisplay has to redisplay the miniwindow. */
+ bool update_miniwindow_p = false;
TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
@@ -12976,7 +13381,7 @@ redisplay_internal (void)
/* Record a function that clears redisplaying_p
when we leave this function. */
- count = SPECPDL_INDEX ();
+ dynwind_begin ();
record_unwind_protect_void (unwind_redisplay);
redisplaying_p = 1;
specbind (Qinhibit_free_realized_faces, Qnil);
@@ -13001,7 +13406,7 @@ redisplay_internal (void)
realized faces, which includes the faces referenced from current
matrices. So, we can't reuse current matrices in this case. */
if (face_change_count)
- ++windows_or_buffers_changed;
+ windows_or_buffers_changed = 47;
if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
&& FRAME_TTY (sf)->previous_frame != sf)
@@ -13009,7 +13414,6 @@ redisplay_internal (void)
/* Since frames on a single ASCII terminal share the same
display area, displaying a different frame means redisplay
the whole thing. */
- windows_or_buffers_changed++;
SET_FRAME_GARBAGED (sf);
#ifndef DOS_NT
set_tty_color_mode (FRAME_TTY (sf), sf);
@@ -13038,7 +13442,7 @@ redisplay_internal (void)
/* If cursor type has been changed on the frame
other than selected, consider all frames. */
if (f != sf && f->cursor_type_changed)
- update_mode_lines++;
+ update_mode_lines = 31;
}
clear_desired_matrices (f);
}
@@ -13058,9 +13462,6 @@ redisplay_internal (void)
if (NILP (Vmemory_full))
prepare_menu_bars ();
- if (windows_or_buffers_changed)
- update_mode_lines++;
-
reconsider_clip_changes (w);
/* In most cases selected window displays current buffer. */
@@ -13069,24 +13470,12 @@ redisplay_internal (void)
{
/* Detect case that we need to write or remove a star in the mode line. */
if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
- {
w->update_mode_line = 1;
- if (buffer_shared_and_changed ())
- update_mode_lines++;
- }
if (mode_line_update_needed (w))
w->update_mode_line = 1;
}
- consider_all_windows_p = (update_mode_lines
- || buffer_shared_and_changed ());
-
- /* If specs for an arrow have changed, do thorough redisplay
- to ensure we remove any arrow that should no longer exist. */
- if (overlay_arrows_changed_p ())
- consider_all_windows_p = windows_or_buffers_changed = 1;
-
/* Normally the message* functions will have already displayed and
updated the echo area, but the frame may have been trashed, or
the update may have been preempted, so display the echo area
@@ -13103,7 +13492,7 @@ redisplay_internal (void)
int window_height_changed_p = echo_area_display (0);
if (message_cleared_p)
- update_miniwindow_p = 1;
+ update_miniwindow_p = true;
must_finish = 1;
@@ -13116,9 +13505,7 @@ redisplay_internal (void)
if (window_height_changed_p)
{
- consider_all_windows_p = 1;
- ++update_mode_lines;
- ++windows_or_buffers_changed;
+ windows_or_buffers_changed = 50;
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
@@ -13133,13 +13520,6 @@ redisplay_internal (void)
/* Resized active mini-window to fit the size of what it is
showing if its contents might have changed. */
must_finish = 1;
- /* FIXME: this causes all frames to be updated, which seems unnecessary
- since only the current frame needs to be considered. This function
- needs to be rewritten with two variables, consider_all_windows and
- consider_all_frames. */
- consider_all_windows_p = 1;
- ++windows_or_buffers_changed;
- ++update_mode_lines;
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
@@ -13147,16 +13527,29 @@ redisplay_internal (void)
clear_garbaged_frames ();
}
- /* If showing the region, and mark has changed, we must redisplay
- the whole window. The assignment to this_line_start_pos prevents
- the optimization directly below this if-statement. */
- if (((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (XBUFFER (w->contents), mark_active)))
- != (w->region_showing > 0))
- || (w->region_showing
- && w->region_showing
- != XINT (Fmarker_position (BVAR (XBUFFER (w->contents), mark)))))
- CHARPOS (this_line_start_pos) = 0;
+ if (windows_or_buffers_changed && !update_mode_lines)
+ /* Code that sets windows_or_buffers_changed doesn't distinguish whether
+ only the windows's contents needs to be refreshed, or whether the
+ mode-lines also need a refresh. */
+ update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
+ ? REDISPLAY_SOME : 32);
+
+ /* If specs for an arrow have changed, do thorough redisplay
+ to ensure we remove any arrow that should no longer exist. */
+ if (overlay_arrows_changed_p ())
+ /* Apparently, this is the only case where we update other windows,
+ without updating other mode-lines. */
+ windows_or_buffers_changed = 49;
+
+ consider_all_windows_p = (update_mode_lines
+ || windows_or_buffers_changed);
+
+#define AINC(a,i) \
+ if (VECTORP (a) && i >= 0 && i < ASIZE (a) && INTEGERP (AREF (a, i))) \
+ ASET (a, i, make_number (1 + XINT (AREF (a, i))))
+
+ AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
+ AINC (Vredisplay__mode_lines_cause, update_mode_lines);
/* Optimize the case that only the line containing the cursor in the
selected window has changed. Variables starting with this_ are
@@ -13297,6 +13690,8 @@ redisplay_internal (void)
PT == w->last_point
/* Make sure the cursor was last displayed
in this window. Otherwise we have to reposition it. */
+
+ /* PXW: Must be converted to pixels, probably. */
&& 0 <= w->cursor.vpos
&& w->cursor.vpos < WINDOW_TOTAL_LINES (w))
{
@@ -13317,13 +13712,7 @@ redisplay_internal (void)
}
/* If highlighting the region, or if the cursor is in the echo area,
then we can't just move the cursor. */
- else if (! (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
- && (EQ (selected_window,
- BVAR (current_buffer, last_selected_window))
- || highlight_nonselected_windows)
- && !w->region_showing
- && NILP (Vshow_trailing_whitespace)
+ else if (NILP (Vshow_trailing_whitespace)
&& !cursor_in_echo_area)
{
struct it it;
@@ -13361,11 +13750,10 @@ redisplay_internal (void)
cancel:
/* Text changed drastically or point moved off of line. */
- SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
+ SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
}
CHARPOS (this_line_start_pos) = 0;
- consider_all_windows_p |= buffer_shared_and_changed ();
++clear_face_cache_count;
#ifdef HAVE_WINDOW_SYSTEM
++clear_image_cache_count;
@@ -13380,6 +13768,8 @@ redisplay_internal (void)
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->updated_p = 0;
+ propagate_buffer_redisplay ();
+
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
@@ -13394,13 +13784,20 @@ redisplay_internal (void)
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
+ bool gcscrollbars
+ /* Only GC scrollbars when we redisplay the whole frame. */
+ = f->redisplay || !REDISPLAY_SOME_P ();
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
- if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
+ if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
redisplay_windows (FRAME_ROOT_WINDOW (f));
+ /* Remember that the invisible frames need to be redisplayed next
+ time they're visible. */
+ else if (!REDISPLAY_SOME_P ())
+ f->redisplay = true;
/* The X error handler may have deleted that frame. */
if (!FRAME_LIVE_P (f))
@@ -13408,7 +13805,7 @@ redisplay_internal (void)
/* Any scroll bars which redisplay_windows should have
nuked should now go away. */
- if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
+ if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
@@ -13431,19 +13828,11 @@ redisplay_internal (void)
/* Prevent various kinds of signals during display
update. stdio is not robust about handling
- signals, which can cause an apparent I/O
- error. */
+ signals, which can cause an apparent I/O error. */
if (interrupt_input)
unrequest_sigio ();
STOP_POLLING;
- /* Mark windows on frame F to update. If we decide to
- update all frames but windows_or_buffers_changed is
- zero, we assume that only the windows that shows
- current buffer should be really updated. */
- set_window_update_flags
- (XWINDOW (f->root_window),
- (windows_or_buffers_changed ? NULL : current_buffer), 1);
pending |= update_frame (f, 0, 0);
f->cursor_type_changed = 0;
f->updated_p = 1;
@@ -13463,6 +13852,7 @@ redisplay_internal (void)
struct frame *f = XFRAME (frame);
if (f->updated_p)
{
+ f->redisplay = false;
mark_window_display_accurate (f->root_window, 1);
if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
@@ -13505,7 +13895,7 @@ redisplay_internal (void)
if (hscroll_windows (selected_window))
goto retry;
- XWINDOW (selected_window)->must_be_updated_p = 1;
+ XWINDOW (selected_window)->must_be_updated_p = true;
pending = update_frame (sf, 0, 0);
sf->cursor_type_changed = 0;
}
@@ -13520,7 +13910,7 @@ redisplay_internal (void)
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
{
- XWINDOW (mini_window)->must_be_updated_p = 1;
+ XWINDOW (mini_window)->must_be_updated_p = true;
pending |= update_frame (mini_frame, 0, 0);
mini_frame->cursor_type_changed = 0;
if (!pending && hscroll_windows (mini_window))
@@ -13544,7 +13934,7 @@ redisplay_internal (void)
matrices of some windows are not valid. */
if (!WINDOW_FULL_WIDTH_P (w)
&& !FRAME_WINDOW_P (XFRAME (w->frame)))
- update_mode_lines = 1;
+ update_mode_lines = 36;
}
else
{
@@ -13552,6 +13942,11 @@ redisplay_internal (void)
{
/* This has already been done above if
consider_all_windows_p is set. */
+ if (XBUFFER (w->contents)->text->redisplay
+ && buffer_window_count (XBUFFER (w->contents)) > 1)
+ /* This can happen if b->text->redisplay was set during
+ jit-lock. */
+ propagate_buffer_redisplay ();
mark_window_display_accurate_1 (w, 1);
/* Say overlay arrows are up to date. */
@@ -13585,17 +13980,12 @@ redisplay_internal (void)
FOR_EACH_FRAME (tail, frame)
{
- int this_is_visible = 0;
-
if (XFRAME (frame)->visible)
- this_is_visible = 1;
-
- if (this_is_visible)
new_count++;
}
if (new_count != number_of_visible_frames)
- windows_or_buffers_changed++;
+ windows_or_buffers_changed = 52;
}
/* Change frame size now if a change is pending. */
@@ -13628,7 +14018,10 @@ redisplay_internal (void)
#endif /* HAVE_WINDOW_SYSTEM */
end_of_redisplay:
- unbind_to (count, Qnil);
+ if (interrupt_input && interrupts_deferred)
+ request_sigio ();
+
+ dynwind_end ();
RESUME_POLLING;
}
@@ -13689,8 +14082,13 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
if (accurate_p)
{
- b->clip_changed = 0;
- b->prevent_redisplay_optimizations_p = 0;
+ b->clip_changed = false;
+ b->prevent_redisplay_optimizations_p = false;
+ eassert (buffer_window_count (b) > 0);
+ /* Resetting b->text->redisplay is problematic!
+ In order to make it safer to do it here, redisplay_internal must
+ have copied all b->text->redisplay to their respective windows. */
+ b->text->redisplay = false;
BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
@@ -13709,9 +14107,11 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
else
w->last_point = marker_position (w->pointm);
- w->window_end_valid = 1;
- w->update_mode_line = 0;
+ w->window_end_valid = true;
+ w->update_mode_line = false;
}
+
+ w->redisplay = !accurate_p;
}
@@ -13814,7 +14214,7 @@ static Lisp_Object
redisplay_window_0 (Lisp_Object window)
{
if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
- redisplay_window (window, 0);
+ redisplay_window (window, false);
return Qnil;
}
@@ -13822,7 +14222,7 @@ static Lisp_Object
redisplay_window_1 (Lisp_Object window)
{
if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
- redisplay_window (window, 1);
+ redisplay_window (window, true);
return Qnil;
}
@@ -14013,7 +14413,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
pos_after, 0);
if (prop_pos >= pos_before)
- bpos_max = prop_pos - 1;
+ bpos_max = prop_pos;
}
if (INTEGERP (chprop))
{
@@ -14087,7 +14487,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
pos_after, 0);
if (prop_pos >= pos_before)
- bpos_max = prop_pos - 1;
+ bpos_max = prop_pos;
}
if (INTEGERP (chprop))
{
@@ -14117,7 +14517,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
GLYPH_BEFORE and GLYPH_AFTER. */
if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
- && !(bpos_max < pt_old && pt_old <= bpos_covered))
+ && !(bpos_max <= pt_old && pt_old <= bpos_covered))
{
/* An empty line has a single glyph whose OBJECT is zero and
whose CHARPOS is the position of a newline on that line.
@@ -14364,9 +14764,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
occlude point. Only set w->cursor if we found a better
approximation to the cursor position than we have from previously
examined candidate rows belonging to the same continued line. */
- if (/* we already have a candidate row */
+ if (/* We already have a candidate row. */
w->cursor.vpos >= 0
- /* that candidate is not the row we are processing */
+ /* That candidate is not the row we are processing. */
&& MATRIX_ROW (matrix, w->cursor.vpos) != row
/* Make sure cursor.vpos specifies a row whose start and end
charpos occlude point, and it is valid candidate for being a
@@ -14377,30 +14777,30 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
&& pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
&& cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
{
- struct glyph *g1 =
- MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
+ struct glyph *g1
+ = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
/* Don't consider glyphs that are outside TEXT_AREA. */
if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
return 0;
/* Keep the candidate whose buffer position is the closest to
point or has the `cursor' property. */
- if (/* previous candidate is a glyph in TEXT_AREA of that row */
+ if (/* Previous candidate is a glyph in TEXT_AREA of that row. */
w->cursor.hpos >= 0
&& w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
&& ((BUFFERP (g1->object)
- && (g1->charpos == pt_old /* an exact match always wins */
+ && (g1->charpos == pt_old /* An exact match always wins. */
|| (BUFFERP (glyph->object)
&& eabs (g1->charpos - pt_old)
< eabs (glyph->charpos - pt_old))))
- /* previous candidate is a glyph from a string that has
- a non-nil `cursor' property */
+ /* Previous candidate is a glyph from a string that has
+ a non-nil `cursor' property. */
|| (STRINGP (g1->object)
&& (!NILP (Fget_char_property (make_number (g1->charpos),
Qcursor, g1->object))
- /* previous candidate is from the same display
+ /* Previous candidate is from the same display
string as this one, and the display string
- came from a text property */
+ came from a text property. */
|| (EQ (g1->object, glyph->object)
&& string_from_text_prop)
/* this candidate is from newline and its
@@ -14843,7 +15243,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0)
/* It's possible that the cursor is on the first line of the
buffer, which is partially obscured due to a vscroll
- (Bug#7537). In that case, avoid looping forever . */
+ (Bug#7537). In that case, avoid looping forever. */
&& extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
{
clear_glyph_matrix (w->desired_matrix);
@@ -14898,6 +15298,7 @@ compute_window_start_on_continuation_line (struct window *w)
/* If the line start is "too far" away from the window start,
say it takes too much time to compute a new window start. */
if (CHARPOS (start_pos) - IT_CHARPOS (it)
+ /* PXW: Do we need upper bounds here? */
< WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
{
int min_distance, distance;
@@ -15003,11 +15404,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
&& !update_mode_lines
&& !windows_or_buffers_changed
&& !f->cursor_type_changed
- /* Can't use this case if highlighting a region. When a
- region exists, cursor movement has to do more than just
- set the cursor. */
- && markpos_of_region () < 0
- && !w->region_showing
&& NILP (Vshow_trailing_whitespace)
/* This code is not used for mini-buffer for the sake of the case
of redisplaying to replace an echo area message; since in
@@ -15240,29 +15636,32 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
/* As soon as we've found the exact match for point,
or the first suitable row whose ends_at_zv_p flag
is set, we are done. */
- at_zv_p =
- MATRIX_ROW (w->current_matrix, w->cursor.vpos)->ends_at_zv_p;
- if (rv && !at_zv_p
- && w->cursor.hpos >= 0
- && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
- w->cursor.vpos))
- {
- struct glyph_row *candidate =
- MATRIX_ROW (w->current_matrix, w->cursor.vpos);
- struct glyph *g =
- candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
- ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
-
- exact_match_p =
- (BUFFERP (g->object) && g->charpos == PT)
- || (INTEGERP (g->object)
- && (g->charpos == PT
- || (g->charpos == 0 && endpos - 1 == PT)));
- }
- if (rv && (at_zv_p || exact_match_p))
+ if (rv)
{
- rc = CURSOR_MOVEMENT_SUCCESS;
- break;
+ at_zv_p = MATRIX_ROW (w->current_matrix,
+ w->cursor.vpos)->ends_at_zv_p;
+ if (!at_zv_p
+ && w->cursor.hpos >= 0
+ && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
+ w->cursor.vpos))
+ {
+ struct glyph_row *candidate =
+ MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+ struct glyph *g =
+ candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
+ ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
+
+ exact_match_p =
+ (BUFFERP (g->object) && g->charpos == PT)
+ || (INTEGERP (g->object)
+ && (g->charpos == PT
+ || (g->charpos == 0 && endpos - 1 == PT)));
+ }
+ if (at_zv_p || exact_match_p)
+ {
+ rc = CURSOR_MOVEMENT_SUCCESS;
+ break;
+ }
}
if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
break;
@@ -15305,9 +15704,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
return rc;
}
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
void
set_vertical_scroll_bar (struct window *w)
{
@@ -15350,10 +15746,54 @@ set_vertical_scroll_bar (struct window *w)
selected_window is redisplayed.
We can return without actually redisplaying the window if fonts has been
- changed on window's frame. In that case, redisplay_internal will retry. */
+ changed on window's frame. In that case, redisplay_internal will retry.
+
+ As one of the important parts of redisplaying a window, we need to
+ decide whether the previous window-start position (stored in the
+ window's w->start marker position) is still valid, and if it isn't,
+ recompute it. Some details about that:
+
+ . The previous window-start could be in a continuation line, in
+ which case we need to recompute it when the window width
+ changes. See compute_window_start_on_continuation_line and its
+ call below.
+
+ . The text that changed since last redisplay could include the
+ previous window-start position. In that case, we try to salvage
+ what we can from the current glyph matrix by calling
+ try_scrolling, which see.
+
+ . Some Emacs command could force us to use a specific window-start
+ position by setting the window's force_start flag, or gently
+ propose doing that by setting the window's optional_new_start
+ flag. In these cases, we try using the specified start point if
+ that succeeds (i.e. the window desired matrix is successfully
+ recomputed, and point location is within the window). In case
+ of optional_new_start, we first check if the specified start
+ position is feasible, i.e. if it will allow point to be
+ displayed in the window. If using the specified start point
+ fails, e.g., if new fonts are needed to be loaded, we abort the
+ redisplay cycle and leave it up to the next cycle to figure out
+ things.
+
+ . Note that the window's force_start flag is sometimes set by
+ redisplay itself, when it decides that the previous window start
+ point is fine and should be kept. Search for "goto force_start"
+ below to see the details. Like the values of window-start
+ specified outside of redisplay, these internally-deduced values
+ are tested for feasibility, and ignored if found to be
+ unfeasible.
+
+ . Note that the function try_window, used to completely redisplay
+ a window, accepts the window's start point as its argument.
+ This is used several times in the redisplay code to control
+ where the window start will be, according to user options such
+ as scroll-conservatively, and also to ensure the screen line
+ showing point will be fully (as opposed to partially) visible on
+ display. */
static void
-redisplay_window (Lisp_Object window, int just_this_one_p)
+redisplay_window (Lisp_Object window, bool just_this_one_p)
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
@@ -15364,13 +15804,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
int tem;
struct it it;
/* Record it now because it's overwritten. */
- int current_matrix_up_to_date_p = 0;
- int used_current_matrix_p = 0;
+ bool current_matrix_up_to_date_p = false;
+ bool used_current_matrix_p = false;
/* This is less strict than current_matrix_up_to_date_p.
It indicates that the buffer contents and narrowing are unchanged. */
- int buffer_unchanged_p = 0;
+ bool buffer_unchanged_p = false;
int temp_scroll_step = 0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
int rc;
int centering_position = -1;
int last_line_misfit = 0;
@@ -15384,10 +15824,20 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
*w->desired_matrix->method = 0;
#endif
+ if (!just_this_one_p
+ && REDISPLAY_SOME_P ()
+ && !w->redisplay
+ && !f->redisplay
+ && !buffer->text->redisplay
+ && BUF_PT (buffer) == w->last_point)
+ return;
+
/* Make sure that both W's markers are valid. */
eassert (XMARKER (w->start)->buffer == buffer);
eassert (XMARKER (w->pointm)->buffer == buffer);
+ /* We come here again if we need to run window-text-change-functions
+ below. */
restart:
reconsider_clip_changes (w);
frame_line_height = default_line_pixel_height (w);
@@ -15398,6 +15848,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
|| buffer->clip_changed
|| buffer->prevent_redisplay_optimizations_p);
+ if (!just_this_one_p)
+ /* If `just_this_one_p' is set, we apparently set must_be_updated_p more
+ cleverly elsewhere. */
+ w->must_be_updated_p = true;
+
if (MINI_WINDOW_P (w))
{
if (w == XWINDOW (echo_area_window)
@@ -15413,7 +15868,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
}
else if ((w != XWINDOW (minibuf_window)
|| minibuf_level == 0)
- /* When buffer is nonempty, redisplay window normally. */
+ /* When buffer is nonempty, redisplay window normally. */
&& BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
/* Quail displays non-mini buffers in minibuffer window.
In that case, redisplay the window normally. */
@@ -15447,7 +15902,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
&& !current_buffer->prevent_redisplay_optimizations_p
&& !window_outdated (w));
- /* Run the window-bottom-change-functions
+ /* Run the window-text-change-functions
if it is possible that the text on the screen has changed
(either due to modification of the text, or any other reason). */
if (!current_matrix_up_to_date_p
@@ -15478,10 +15933,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
if (XMARKER (w->start)->buffer == current_buffer)
compute_window_start_on_continuation_line (w);
- w->window_end_valid = 0;
+ w->window_end_valid = false;
/* If so, we also can't rely on current matrix
and should not fool try_cursor_movement below. */
- current_matrix_up_to_date_p = 0;
+ current_matrix_up_to_date_p = false;
}
/* Some sanity checks. */
@@ -15522,16 +15977,20 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
this may be a bit late to catch such changes, but the rest of
redisplay goes (non-fatally) haywire when the display table is
changed, so why should we worry about doing any better? */
- if (current_buffer->width_run_cache)
+ if (current_buffer->width_run_cache
+ || (current_buffer->base_buffer
+ && current_buffer->base_buffer->width_run_cache))
{
struct Lisp_Char_Table *disptab = buffer_display_table ();
if (! disptab_matches_widthtab
(disptab, XVECTOR (BVAR (current_buffer, width_table))))
{
- invalidate_region_cache (current_buffer,
- current_buffer->width_run_cache,
- BEG, Z);
+ struct buffer *buf = current_buffer;
+
+ if (buf->base_buffer)
+ buf = buf->base_buffer;
+ invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
recompute_width_table (current_buffer, disptab);
}
}
@@ -15622,7 +16081,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
Move it back to a fully-visible line. */
new_vpos = window_box_height (w);
}
- else if (w->cursor.vpos >=0)
+ else if (w->cursor.vpos >= 0)
{
/* Some people insist on not letting point enter the scroll
margin, even though this part handles windows that didn't
@@ -15680,12 +16139,14 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
/* If we are highlighting the region, then we just changed
the region, so redisplay to show it. */
- if (markpos_of_region () >= 0)
+ /* FIXME: We need to (re)run pre-redisplay-function! */
+ /* if (markpos_of_region () >= 0)
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp, 0))
goto need_larger_matrices;
}
+ */
}
#ifdef GLYPH_DEBUG
@@ -16042,12 +16503,50 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
/* Consider the following case: Window starts at BEGV, there is
invisible, intangible text at BEGV, so that display starts at
some point START > BEGV. It can happen that we are called with
- PT somewhere between BEGV and START. Try to handle that case. */
+ PT somewhere between BEGV and START. Try to handle that case,
+ and similar ones. */
if (w->cursor.vpos < 0)
{
- struct glyph_row *row = w->current_matrix->rows;
- if (row->mode_line_p)
- ++row;
+ /* First, try locating the proper glyph row for PT. */
+ struct glyph_row *row =
+ row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0);
+
+ /* Sometimes point is at the beginning of invisible text that is
+ before the 1st character displayed in the row. In that case,
+ row_containing_pos fails to find the row, because no glyphs
+ with appropriate buffer positions are present in the row.
+ Therefore, we next try to find the row which shows the 1st
+ position after the invisible text. */
+ if (!row)
+ {
+ Lisp_Object val =
+ get_char_property_and_overlay (make_number (PT), Qinvisible,
+ Qnil, NULL);
+
+ if (TEXT_PROP_MEANS_INVISIBLE (val))
+ {
+ ptrdiff_t alt_pos;
+ Lisp_Object invis_end =
+ Fnext_single_char_property_change (make_number (PT), Qinvisible,
+ Qnil, Qnil);
+
+ if (NATNUMP (invis_end))
+ alt_pos = XFASTINT (invis_end);
+ else
+ alt_pos = ZV;
+ row = row_containing_pos (w, alt_pos, w->current_matrix->rows,
+ NULL, 0);
+ }
+ }
+ /* Finally, fall back on the first row of the window after the
+ header line (if any). This is slightly better than not
+ displaying the cursor at all. */
+ if (!row)
+ {
+ row = w->current_matrix->rows;
+ if (row->mode_line_p)
+ ++row;
+ }
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
}
@@ -16097,7 +16596,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
SET_TEXT_POS_FROM_MARKER (startp, w->start);
w->start_at_line_beg = (CHARPOS (startp) == BEGV
- || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
+ || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
/* Display the mode line, if we must. */
if ((update_mode_line
@@ -16117,6 +16616,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
&& (WINDOW_WANTS_MODELINE_P (w)
|| WINDOW_WANTS_HEADER_LINE_P (w)))
{
+
display_mode_lines (w);
/* If mode line height has changed, arrange for a thorough
@@ -16182,7 +16682,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
redisplay_tool_bar (f);
#else
if (WINDOWP (f->tool_bar_window)
- && (FRAME_TOOL_BAR_LINES (f) > 0
+ && (FRAME_TOOL_BAR_HEIGHT (f) > 0
|| !NILP (Vauto_resize_tool_bars))
&& redisplay_tool_bar (f))
ignore_mouse_drag_p = 1;
@@ -16200,10 +16700,18 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
update_begin (f);
block_input ();
if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+ }
unblock_input ();
update_end (f);
}
+
+ if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ x_draw_bottom_divider (w);
#endif /* HAVE_WINDOW_SYSTEM */
/* We go to this label, with fonts_changed set, if it is
@@ -16237,11 +16745,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
set_buffer_internal_1 (old);
/* Avoid an abort in TEMP_SET_PT_BOTH if the buffer has become
- shorter. This can be caused by log truncation in *Messages*. */
+ shorter. This can be caused by log truncation in *Messages*. */
if (CHARPOS (lpoint) <= ZV)
TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
- unbind_to (count, Qnil);
+ dynwind_end ();
}
@@ -16380,10 +16888,8 @@ try_window_reusing_current_matrix (struct window *w)
|| f->cursor_type_changed)
return 0;
- /* Can't do this if region may have changed. */
- if (markpos_of_region () >= 0
- || w->region_showing
- || !NILP (Vshow_trailing_whitespace))
+ /* Can't do this if showing trailing whitespace. */
+ if (!NILP (Vshow_trailing_whitespace))
return 0;
/* If top-line visibility has changed, give up. */
@@ -16519,7 +17025,7 @@ try_window_reusing_current_matrix (struct window *w)
/* Disable lines that must be updated. */
for (i = 0; i < nrows_scrolled; ++i)
- (start_row + i)->enabled_p = 0;
+ (start_row + i)->enabled_p = false;
/* Re-compute Y positions. */
min_y = WINDOW_HEADER_LINE_HEIGHT (w);
@@ -16699,7 +17205,7 @@ try_window_reusing_current_matrix (struct window *w)
/* Disable rows not reused. */
for (row -= nrows_scrolled; row < bottom_row; ++row)
- row->enabled_p = 0;
+ row->enabled_p = false;
/* Point may have moved to a different line, so we cannot assume that
the previous cursor position is valid; locate the correct row. */
@@ -16984,7 +17490,7 @@ sync_frame_with_window_matrix_rows (struct window *w)
/* Disable frame rows whose corresponding window rows have
been disabled in try_window_id. */
if (!window_row->enabled_p)
- frame_row->enabled_p = 0;
+ frame_row->enabled_p = false;
++window_row, ++frame_row;
}
@@ -17074,9 +17580,16 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
Value is
- 1 if display has been updated
- 0 if otherwise unsuccessful
+ >= 1 if successful, i.e. display has been updated
+ specifically:
+ 1 means the changes were in front of a newline that precedes
+ the window start, and the whole current matrix was reused
+ 2 means the changes were after the last position displayed
+ in the window, and the whole current matrix was reused
+ 3 means portions of the current matrix were reused, while
+ some of the screen lines were redrawn
-1 if redisplay with same window start is known not to succeed
+ 0 if otherwise unsuccessful
The following steps are performed:
@@ -17151,6 +17664,12 @@ try_window_id (struct window *w)
if (windows_or_buffers_changed || f->cursor_type_changed)
GIVE_UP (2);
+ /* This function's optimizations cannot be used if overlays have
+ changed in the buffer displayed by the window, so give up if they
+ have. */
+ if (w->last_overlay_modified != OVERLAY_MODIFF)
+ GIVE_UP (21);
+
/* Verify that narrowing has not changed.
Also verify that we were not told to prevent redisplay optimizations.
It would be nice to further
@@ -17181,19 +17700,10 @@ try_window_id (struct window *w)
if (!w->window_end_valid)
GIVE_UP (8);
- /* Can't use this if highlighting a region because a cursor movement
- will do more than just set the cursor. */
- if (markpos_of_region () >= 0)
- GIVE_UP (9);
-
/* Likewise if highlighting trailing whitespace. */
if (!NILP (Vshow_trailing_whitespace))
GIVE_UP (11);
- /* Likewise if showing a region. */
- if (w->region_showing)
- GIVE_UP (10);
-
/* Can't use this if overlay arrow position and/or string have
changed. */
if (overlay_arrows_changed_p ())
@@ -17509,7 +18019,7 @@ try_window_id (struct window *w)
= run.current_y = run.desired_y = run.height = 0;
first_unchanged_at_end_row = NULL;
}
- IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
+ IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
/* Find the cursor if not already found. We have to decide whether
@@ -17736,7 +18246,7 @@ try_window_id (struct window *w)
the current matrix? I don't think so, so we mark rows
displayed invalid in the current matrix by setting their
enabled_p flag to zero. */
- MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
+ SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
if (display_line (&it))
last_text_row_at_end = it.glyph_row - 1;
}
@@ -17805,8 +18315,8 @@ try_window_id (struct window *w)
else
emacs_abort ();
- IF_DEBUG (debug_end_pos = w->window_end_pos;
- debug_end_vpos = w->window_end_vpos);
+ IF_DEBUG ((debug_end_pos = w->window_end_pos,
+ debug_end_vpos = w->window_end_vpos));
/* Record that display has not been completed. */
w->window_end_valid = 0;
@@ -18247,6 +18757,7 @@ insert_left_trunc_glyphs (struct it *it)
truncate_it.current_x = 0;
truncate_it.face_id = DEFAULT_FACE_ID;
truncate_it.glyph_row = &scratch_glyph_row;
+ truncate_it.area = TEXT_AREA;
truncate_it.glyph_row->used[TEXT_AREA] = 0;
CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
truncate_it.object = make_number (0);
@@ -18537,7 +19048,7 @@ append_space_for_newline (struct it *it, int default_face_p)
it->len = 1;
/* If the default face was remapped, be sure to use the
- remapped face for the appended newline. */
+ remapped face for the appended newline. */
if (default_face_p)
it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
else if (it->face_before_selective_p)
@@ -18594,10 +19105,14 @@ extend_face_to_end_of_line (struct it *it)
1-``pixel'' wide, so they hit the equality too early. This grace
is needed only for R2L rows that are not continued, to produce
one extra blank where we could display the cursor. */
- if (it->current_x >= it->last_visible_x
- + (!FRAME_WINDOW_P (f)
- && it->glyph_row->reversed_p
- && !it->glyph_row->continued_p))
+ if ((it->current_x >= it->last_visible_x
+ + (!FRAME_WINDOW_P (f)
+ && it->glyph_row->reversed_p
+ && !it->glyph_row->continued_p))
+ /* If the window has display margins, we will need to extend
+ their face even if the text area is filled. */
+ && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
return;
/* The default face, possibly remapped. */
@@ -18615,7 +19130,9 @@ extend_face_to_end_of_line (struct it *it)
&& MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
&& face->box == FACE_NO_BOX
&& face->background == FRAME_BACKGROUND_PIXEL (f)
+#ifdef HAVE_WINDOW_SYSTEM
&& !face->stipple
+#endif
&& !it->glyph_row->reversed_p)
return;
@@ -18643,6 +19160,32 @@ extend_face_to_end_of_line (struct it *it)
it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
it->glyph_row->used[TEXT_AREA] = 1;
}
+ /* Mode line and the header line don't have margins, and
+ likewise the frame's tool-bar window, if there is any. */
+ if (!(it->glyph_row->mode_line_p
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+ || (WINDOWP (f->tool_bar_window)
+ && it->w == XWINDOW (f->tool_bar_window))
+#endif
+ ))
+ {
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
+ {
+ it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
+ it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
+ default_face->id;
+ it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
+ }
+ if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+ && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
+ {
+ it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
+ it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
+ default_face->id;
+ it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
+ }
+ }
#ifdef HAVE_WINDOW_SYSTEM
if (it->glyph_row->reversed_p)
{
@@ -18708,6 +19251,34 @@ extend_face_to_end_of_line (struct it *it)
it->object = make_number (0);
it->c = it->char_to_display = ' ';
it->len = 1;
+
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ && (it->glyph_row->used[LEFT_MARGIN_AREA]
+ < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+ && !it->glyph_row->mode_line_p
+ && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+ {
+ struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
+ struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
+
+ for (it->current_x = 0; g < e; g++)
+ it->current_x += g->pixel_width;
+
+ it->area = LEFT_MARGIN_AREA;
+ it->face_id = default_face->id;
+ while (it->glyph_row->used[LEFT_MARGIN_AREA]
+ < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+ {
+ PRODUCE_GLYPHS (it);
+ /* term.c:produce_glyphs advances it->current_x only for
+ TEXT_AREA. */
+ it->current_x += it->pixel_width;
+ }
+
+ it->current_x = saved_x;
+ it->area = TEXT_AREA;
+ }
+
/* The last row's blank glyphs should get the default face, to
avoid painting the rest of the window with the region face,
if the region ends at ZV. */
@@ -18715,12 +19286,35 @@ extend_face_to_end_of_line (struct it *it)
it->face_id = default_face->id;
else
it->face_id = face->id;
-
PRODUCE_GLYPHS (it);
while (it->current_x <= it->last_visible_x)
PRODUCE_GLYPHS (it);
+ if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+ && (it->glyph_row->used[RIGHT_MARGIN_AREA]
+ < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+ && !it->glyph_row->mode_line_p
+ && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+ {
+ struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
+ struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
+
+ for ( ; g < e; g++)
+ it->current_x += g->pixel_width;
+
+ it->area = RIGHT_MARGIN_AREA;
+ it->face_id = default_face->id;
+ while (it->glyph_row->used[RIGHT_MARGIN_AREA]
+ < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+ {
+ PRODUCE_GLYPHS (it);
+ it->current_x += it->pixel_width;
+ }
+
+ it->area = TEXT_AREA;
+ }
+
/* Don't count these blanks really. It would let us insert a left
truncation glyph below and make us set the cursor on them, maybe. */
it->current_x = saved_x;
@@ -19275,9 +19869,6 @@ display_line (struct it *it)
return 0;
}
- /* Is IT->w showing the region? */
- it->w->region_showing = it->region_beg_charpos > 0 ? it->region_beg_charpos : 0;
-
/* Clear the result glyph row and enable it. */
prepare_desired_row (row);
@@ -19576,6 +20167,9 @@ display_line (struct it *it)
}
else if (it->bidi_p)
RECORD_MAX_MIN_POS (it);
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else if (CHAR_GLYPH_PADDING_P (*glyph)
&& !FRAME_WINDOW_P (it->f))
@@ -19604,6 +20198,9 @@ display_line (struct it *it)
it->max_descent = descent;
it->max_phys_ascent = phys_ascent;
it->max_phys_descent = phys_descent;
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else if (wrap_row_used > 0)
{
@@ -19648,6 +20245,9 @@ display_line (struct it *it)
row->continued_p = 1;
glyph->pixel_width = it->last_visible_x - x;
it->starts_in_middle_of_char_p = 1;
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else
{
@@ -19770,7 +20370,12 @@ display_line (struct it *it)
/* If we truncate lines, we are done when the last displayed
glyphs reach past the right margin of the window. */
if (it->line_wrap == TRUNCATE
- && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+ && ((FRAME_WINDOW_P (it->f)
+ /* Images are preprocessed in produce_image_glyph such
+ that they are cropped at the right edge of the
+ window, so an image glyph will always end exactly at
+ last_visible_x, even if there's no right fringe. */
+ && (WINDOW_RIGHT_FRINGE_WIDTH (it->w) || it->what == IT_IMAGE))
? (it->current_x >= it->last_visible_x)
: (it->current_x > it->last_visible_x)))
{
@@ -19803,19 +20408,26 @@ display_line (struct it *it)
i = row->used[TEXT_AREA] - (i + 1);
}
- it->current_x = x_before;
- if (!FRAME_WINDOW_P (it->f))
+ /* produce_special_glyphs overwrites the last glyph, so
+ we don't want that if we want to keep that last
+ glyph, which means it's an image. */
+ if (it->current_x > it->last_visible_x)
{
- for (n = row->used[TEXT_AREA]; i < n; ++i)
+ it->current_x = x_before;
+ if (!FRAME_WINDOW_P (it->f))
+ {
+ for (n = row->used[TEXT_AREA]; i < n; ++i)
+ {
+ row->used[TEXT_AREA] = i;
+ produce_special_glyphs (it, IT_TRUNCATION);
+ }
+ }
+ else
{
row->used[TEXT_AREA] = i;
produce_special_glyphs (it, IT_TRUNCATION);
}
- }
- else
- {
- row->used[TEXT_AREA] = i;
- produce_special_glyphs (it, IT_TRUNCATION);
+ it->hpos = hpos_before;
}
}
else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -19834,13 +20446,13 @@ display_line (struct it *it)
goto at_end_of_line;
}
it->current_x = x_before;
+ it->hpos = hpos_before;
}
row->truncated_on_right_p = 1;
it->continuation_lines_width = 0;
reseat_at_next_visible_line_start (it, 0);
row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
- it->hpos = hpos_before;
break;
}
}
@@ -19854,9 +20466,12 @@ display_line (struct it *it)
&& IT_CHARPOS (*it) != CHARPOS (row->start.pos))
{
if (!FRAME_WINDOW_P (it->f)
- || (row->reversed_p
- ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
- : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
+ || (((row->reversed_p
+ ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+ : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
+ /* Don't let insert_left_trunc_glyphs overwrite the
+ first glyph of the row if it is an image. */
+ && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
insert_left_trunc_glyphs (it);
row->truncated_on_left_p = 1;
}
@@ -20059,6 +20674,7 @@ See also `bidi-paragraph-direction'. */)
itb.string.s = NULL;
itb.string.lstring = Qnil;
itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
itb.string.unibyte = 0;
/* We have no window to use here for ignoring window-specific
overlays. Using NULL for window pointer will cause
@@ -20120,6 +20736,10 @@ Value is the new character position of point. */)
&& !b->clip_changed
&& !b->prevent_redisplay_optimizations_p
&& !window_outdated (w)
+ /* We rely below on the cursor coordinates to be up to date, but
+ we cannot trust them if some command moved point since the
+ last complete redisplay. */
+ && w->last_point == BUF_PT (b)
&& w->cursor.vpos >= 0
&& w->cursor.vpos < w->current_matrix->nrows
&& (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
@@ -20303,11 +20923,26 @@ Value is the new character position of point. */)
of this or previous line to make sure we are before point in
the logical order (since the move_it_* functions can only
move forward). */
+ reseat:
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = it.current_y = it.vpos = 0;
if (IT_CHARPOS (it) != PT)
- move_it_to (&it, overshoot_expected ? PT - 1 : PT,
- -1, -1, -1, MOVE_TO_POS);
+ {
+ move_it_to (&it, overshoot_expected ? PT - 1 : PT,
+ -1, -1, -1, MOVE_TO_POS);
+ /* If we missed point because the character there is
+ displayed out of a display vector that has more than one
+ glyph, retry expecting overshoot. */
+ if (it.method == GET_FROM_DISPLAY_VECTOR
+ && it.current.dpvec_index > 0
+ && !overshoot_expected)
+ {
+ overshoot_expected = true;
+ goto reseat;
+ }
+ else if (IT_CHARPOS (it) != PT && !overshoot_expected)
+ move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
+ }
pt_x = it.current_x;
pt_vpos = it.vpos;
if (dir > 0 || overshoot_expected)
@@ -20336,11 +20971,16 @@ Value is the new character position of point. */)
else if (pixel_width <= 0)
pixel_width = 1;
- /* If there's a display string at point, we are actually at the
- glyph to the left of point, so we need to correct the X
- coordinate. */
+ /* If there's a display string (or something similar) at point,
+ we are actually at the glyph to the left of point, so we need
+ to correct the X coordinate. */
if (overshoot_expected)
- pt_x += pixel_width;
+ {
+ if (it.bidi_p)
+ pt_x += pixel_width * it.bidi_it.scan_dir;
+ else
+ pt_x += pixel_width;
+ }
/* Compute target X coordinate, either to the left or to the
right of point. On TTY frames, all characters have the same
@@ -20372,6 +21012,30 @@ Value is the new character position of point. */)
move_it_by_lines (&it, -1);
target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
target_is_eol_p = true;
+ /* Under word-wrap, we don't know the x coordinate of
+ the last character displayed on the previous line,
+ which immediately precedes the wrap point. To find
+ out its x coordinate, we try moving to the right
+ margin of the window, which will stop at the wrap
+ point, and then reset target_x to point at the
+ character that precedes the wrap point. This is not
+ needed on GUI frames, because (see below) there we
+ move from the left margin one grapheme cluster at a
+ time, and stop when we hit the wrap point. */
+ if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
+ {
+ void *it_data = NULL;
+ struct it it2;
+
+ SAVE_IT (it2, it, it_data);
+ move_it_in_display_line_to (&it, ZV, target_x,
+ MOVE_TO_POS | MOVE_TO_X);
+ /* If we arrived at target_x, that _is_ the last
+ character on the previous line. */
+ if (it.current_x != target_x)
+ target_x = it.current_x - 1;
+ RESTORE_IT (&it, &it2, it_data);
+ }
}
}
else
@@ -20396,15 +21060,42 @@ Value is the new character position of point. */)
character at point. */
if (FRAME_WINDOW_P (it.f) && dir < 0)
{
- struct text_pos new_pos = it.current.pos;
+ struct text_pos new_pos;
enum move_it_result rc = MOVE_X_REACHED;
+ if (it.current_x == 0)
+ get_next_display_element (&it);
+ if (it.what == IT_COMPOSITION)
+ {
+ new_pos.charpos = it.cmp_it.charpos;
+ new_pos.bytepos = -1;
+ }
+ else
+ new_pos = it.current.pos;
+
while (it.current_x + it.pixel_width <= target_x
- && rc == MOVE_X_REACHED)
+ && (rc == MOVE_X_REACHED
+ /* Under word-wrap, move_it_in_display_line_to
+ stops at correct coordinates, but sometimes
+ returns MOVE_POS_MATCH_OR_ZV. */
+ || (it.line_wrap == WORD_WRAP
+ && rc == MOVE_POS_MATCH_OR_ZV)))
{
int new_x = it.current_x + it.pixel_width;
- new_pos = it.current.pos;
+ /* For composed characters, we want the position of the
+ first character in the grapheme cluster (usually, the
+ composition's base character), whereas it.current
+ might give us the position of the _last_ one, e.g. if
+ the composition is rendered in reverse due to bidi
+ reordering. */
+ if (it.what == IT_COMPOSITION)
+ {
+ new_pos.charpos = it.cmp_it.charpos;
+ new_pos.bytepos = -1;
+ }
+ else
+ new_pos = it.current.pos;
if (new_x == it.current_x)
new_x++;
rc = move_it_in_display_line_to (&it, ZV, new_x,
@@ -20412,21 +21103,10 @@ Value is the new character position of point. */)
if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
break;
}
- /* If we ended up on a composed character inside
- bidi-reordered text (e.g., Hebrew text with diacritics),
- the iterator gives us the buffer position of the last (in
- logical order) character of the composed grapheme cluster,
- which is not what we want. So we cheat: we compute the
- character position of the character that follows (in the
- logical order) the one where the above loop stopped. That
- character will appear on display to the left of point. */
- if (it.bidi_p
- && it.bidi_it.scan_dir == -1
- && new_pos.charpos - IT_CHARPOS (it) > 1)
- {
- new_pos.charpos = IT_CHARPOS (it) + 1;
- new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
- }
+ /* The previous position we saw in the loop is the one we
+ want. */
+ if (new_pos.bytepos == -1)
+ new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
it.current.pos = new_pos;
}
else
@@ -20518,7 +21198,7 @@ display_menu_bar (struct window *w)
eassert (!FRAME_WINDOW_P (f));
init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
if (FRAME_WINDOW_P (f))
{
@@ -20529,7 +21209,7 @@ display_menu_bar (struct window *w)
init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
MENU_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = FRAME_PIXEL_WIDTH (f);
}
else
#endif /* not USE_X_TOOLKIT and not USE_GTK */
@@ -20552,7 +21232,7 @@ display_menu_bar (struct window *w)
{
struct glyph_row *row = it.glyph_row + i;
clear_glyph_row (row);
- row->enabled_p = 1;
+ row->enabled_p = true;
row->full_width_p = 1;
}
@@ -20584,7 +21264,6 @@ display_menu_bar (struct window *w)
compute_line_metrics (&it);
}
-#ifdef HAVE_MENUS
/* Deep copy of a glyph row, including the glyphs. */
static void
deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
@@ -20663,7 +21342,7 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
row->full_width_p = 1;
saved_reversed = row->reversed_p;
row->reversed_p = 0;
- row->enabled_p = 1;
+ row->enabled_p = true;
/* Arrange for the menu item glyphs to start at (X,Y) and have the
desired face. */
@@ -20706,7 +21385,6 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
row->full_width_p = saved_width;
row->reversed_p = saved_reversed;
}
-#endif /* HAVE_MENUS */
/***********************************************************************
Mode Line
@@ -20718,7 +21396,7 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
the number of windows whose mode lines were redisplayed. */
static int
-redisplay_mode_lines (Lisp_Object window, int force)
+redisplay_mode_lines (Lisp_Object window, bool force)
{
int nwindows = 0;
@@ -20752,10 +21430,7 @@ redisplay_mode_lines (Lisp_Object window, int force)
/* Display mode lines. */
clear_glyph_matrix (w->desired_matrix);
if (display_mode_lines (w))
- {
- ++nwindows;
- w->must_be_updated_p = 1;
- }
+ ++nwindows;
/* Restore old settings. */
set_buffer_internal_1 (old);
@@ -20811,6 +21486,8 @@ display_mode_lines (struct window *w)
XFRAME (new_frame)->selected_window = old_frame_selected_window;
selected_frame = old_selected_frame;
selected_window = old_selected_window;
+ if (n > 0)
+ w->must_be_updated_p = true;
return n;
}
@@ -20826,12 +21503,12 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
{
struct it it;
struct face *face;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
init_iterator (&it, w, -1, -1, NULL, face_id);
/* Don't extend on a previously drawn mode-line.
This may happen if called from pos_visible_p. */
- it.glyph_row->enabled_p = 0;
+ it.glyph_row->enabled_p = false;
prepare_desired_row (it.glyph_row);
it.glyph_row->mode_line_p = 1;
@@ -20854,7 +21531,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
pop_kboard ();
- unbind_to (count, Qnil);
+ dynwind_end ();
/* Fill up with spaces. */
display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
@@ -21253,7 +21930,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
if (CONSP (XCDR (elt)))
{
Lisp_Object spec;
- spec = safe_eval (XCAR (XCDR (elt)));
+ spec = safe__eval (true, XCAR (XCDR (elt)));
n += display_mode_element (it, depth, field_width - n,
precision - n, spec, props,
risky);
@@ -21506,7 +22183,7 @@ are the selected window and the WINDOW's buffer). */)
struct buffer *old_buffer = NULL;
int face_id;
int no_props = INTEGERP (face);
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object str;
int string_start = 0;
@@ -21519,8 +22196,10 @@ are the selected window and the WINDOW's buffer). */)
/* Make formatting the modeline a non-op when noninteractive, otherwise
there will be problems later caused by a partially initialized frame. */
- if (NILP (format) || noninteractive)
+ if (NILP (format) || noninteractive) {
+ dynwind_end ();
return empty_unibyte_string;
+ }
if (no_props)
face = Qnil;
@@ -21581,7 +22260,7 @@ are the selected window and the WINDOW's buffer). */)
empty_unibyte_string);
}
- unbind_to (count, Qnil);
+ dynwind_end ();
return str;
}
@@ -22070,7 +22749,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
return decode_mode_spec_buf;
no_value:
{
- char* p = decode_mode_spec_buf;
+ char *p = decode_mode_spec_buf;
int pad = width - 2;
while (pad-- > 0)
*p++ = ' ';
@@ -22166,10 +22845,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
case '@':
{
- ptrdiff_t count = inhibit_garbage_collection ();
Lisp_Object val = call1 (intern ("file-remote-p"),
BVAR (current_buffer, directory));
- unbind_to (count, Qnil);
if (NILP (val))
return "-";
@@ -22411,9 +23088,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
it->face_id
= face_at_string_position (it->w, face_string, face_string_pos,
- 0, it->region_beg_charpos,
- it->region_end_charpos,
- &endptr, it->base_face_id, 0);
+ 0, &endptr, it->base_face_id, 0);
face = FACE_FROM_ID (it->f, it->face_id);
it->face_box_p = face->box != FACE_NO_BOX;
}
@@ -22820,7 +23495,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
}
- prop = buffer_local_value_1 (prop, it->w->contents);
+ prop = buffer_local_value (prop, it->w->contents);
if (EQ (prop, Qunbound))
prop = Qnil;
}
@@ -22872,7 +23547,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
return OK_PIXELS (pixels);
}
- car = buffer_local_value_1 (car, it->w->contents);
+ car = buffer_local_value (car, it->w->contents);
if (EQ (car, Qunbound))
car = Qnil;
}
@@ -23049,7 +23724,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
#endif
{
eassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ prepare_face_for_display (f, face);
}
return face;
@@ -23072,7 +23747,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
/* Make sure X resources of the face are allocated. */
eassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ prepare_face_for_display (f, face);
if (two_byte_p)
*two_byte_p = 0;
@@ -23389,7 +24064,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
s->ybase += voffset;
/* The case that face->gc == 0 is handled when drawing the glyph
- string by calling PREPARE_FACE_FOR_DISPLAY. */
+ string by calling prepare_face_for_display. */
eassert (s->face);
return glyph - s->row->glyphs[s->area];
}
@@ -23580,7 +24255,6 @@ set_glyph_string_background_width (struct glyph_string *s, int start, int last_x
the drawing area, set S->extends_to_end_of_line_p. */
if (start == s->row->used[s->area]
- && s->area == TEXT_AREA
&& ((s->row->fill_line_p
&& (s->hl == DRAW_NORMAL_TEXT
|| s->hl == DRAW_IMAGE_RAISED
@@ -23908,7 +24582,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
/* X is relative to the left edge of W, without scroll bars
or fringes. */
area_left = WINDOW_LEFT_EDGE_X (w);
- last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
+ last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
+ - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
}
else
{
@@ -23987,13 +24662,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
+ if (hl != overlap_hl)
+ clip_head = head;
j = i;
BUILD_GLYPH_STRINGS (j, start, h, t,
overlap_hl, dummy_x, last_x);
start = i;
compute_overhangs_and_x (t, head->x, 1);
prepend_glyph_string_lists (&head, &tail, h, t);
- clip_head = head;
+ if (clip_head == NULL)
+ clip_head = head;
}
/* Prepend glyph strings for glyphs in front of the first glyph
@@ -24014,7 +24692,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
- clip_head = head;
+ if (hl == overlap_hl || clip_head == NULL)
+ clip_head = head;
BUILD_GLYPH_STRINGS (i, start, h, t,
overlap_hl, dummy_x, last_x);
for (s = h; s; s = s->next)
@@ -24038,13 +24717,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
+ if (hl != overlap_hl)
+ clip_tail = tail;
BUILD_GLYPH_STRINGS (end, i, h, t,
overlap_hl, x, last_x);
/* Because BUILD_GLYPH_STRINGS updates the first argument,
we don't have `end = i;' here. */
compute_overhangs_and_x (h, tail->x + tail->width, 0);
append_glyph_string_lists (&head, &tail, h, t);
- clip_tail = tail;
+ if (clip_tail == NULL)
+ clip_tail = tail;
}
/* Append glyph strings for glyphs following the last glyph
@@ -24062,7 +24744,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
- clip_tail = tail;
+ if (hl == overlap_hl || clip_tail == NULL)
+ clip_tail = tail;
i++; /* We must include the Ith glyph. */
BUILD_GLYPH_STRINGS (end, i, h, t,
overlap_hl, x, last_x);
@@ -24330,7 +25013,7 @@ produce_image_glyph (struct it *it)
face = FACE_FROM_ID (it->f, it->face_id);
eassert (face);
/* Make sure X resources of the face is loaded. */
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_face_for_display (it->f, face);
if (it->image_id < 0)
{
@@ -24608,7 +25291,7 @@ produce_stretch_glyph (struct it *it)
{
struct face *face = FACE_FROM_ID (it->f, it->face_id);
font = face->font ? face->font : FRAME_FONT (it->f);
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_face_for_display (it->f, face);
}
#endif
@@ -25072,7 +25755,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
face = FACE_FROM_ID (it->f, face_id);
font = face->font ? face->font : FRAME_FONT (it->f);
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_face_for_display (it->f, face);
if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
{
@@ -25088,7 +25771,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
str = buf;
}
- for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
+ for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
code[len] = font->driver->encode_char (font, str[len]);
upper_len = (len + 1) / 2;
font->driver->text_extents (font, code, upper_len,
@@ -25140,7 +25823,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
lower_yoff = descent - 2 - metrics_lower.descent;
upper_yoff = (lower_yoff - metrics_lower.ascent - 1
- metrics_upper.descent);
- /* Don't make the height shorter than the base height. */
+ /* Don't make the height shorter than the base height. */
if (height > base_height)
{
it->ascent = ascent;
@@ -25177,16 +25860,16 @@ x_produce_glyphs (struct it *it)
struct face *face = FACE_FROM_ID (it->f, it->face_id);
struct font *font = face->font;
struct font_metrics *pcm = NULL;
- int boff; /* baseline offset */
+ int boff; /* Baseline offset. */
if (font == NULL)
{
/* When no suitable font is found, display this character by
the method specified in the first extra slot of
Vglyphless_char_display. */
- Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
+ Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
- eassert (it->what == IT_GLYPHLESS);
+ eassert (it->what == IT_GLYPHLESS);
produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil);
goto done;
}
@@ -25324,7 +26007,7 @@ x_produce_glyphs (struct it *it)
{
/* A newline has no width, but we need the height of the
line. But if previous part of the line sets a height,
- don't increase that height */
+ don't increase that height. */
Lisp_Object height;
Lisp_Object total_height = Qnil;
@@ -25334,7 +26017,7 @@ x_produce_glyphs (struct it *it)
it->nglyphs = 0;
height = get_it_property (it, Qline_height);
- /* Split (line-height total-height) list */
+ /* Split (line-height total-height) list. */
if (CONSP (height)
&& CONSP (XCDR (height))
&& NILP (XCDR (XCDR (height))))
@@ -25946,7 +26629,8 @@ x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
f = XFRAME (w->frame);
if (updated_row->full_width_p)
- max_x = WINDOW_TOTAL_WIDTH (w);
+ max_x = (WINDOW_PIXEL_WIDTH (w)
+ - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
else
max_x = window_box_width (w, updated_area);
max_y = window_text_bottom_y (w);
@@ -26412,9 +27096,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
/* Erase the image of a cursor of window W from the screen. */
-#ifndef WINDOWSNT
-static
-#endif
void
erase_phys_cursor (struct window *w)
{
@@ -26723,7 +27404,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
if (/* If window is in the process of being destroyed, don't bother
to do anything. */
w->current_matrix != NULL
- /* Don't update mouse highlight if hidden */
+ /* Don't update mouse highlight if hidden. */
&& (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
/* Recognize when we are called to operate on rows that don't exist
anymore. This can happen when a window is split. */
@@ -26863,13 +27544,16 @@ clear_mouse_face (Mouse_HLInfo *hlinfo)
cleared = 1;
}
- reset_mouse_highlight (hlinfo);
+ hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+ hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+ hlinfo->mouse_face_window = Qnil;
+ hlinfo->mouse_face_overlay = Qnil;
return cleared;
}
-/* Return non-zero if the coordinates HPOS and VPOS on windows W are
+/* Return true if the coordinates HPOS and VPOS on windows W are
within the mouse face on that window. */
-static int
+static bool
coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
@@ -26877,48 +27561,48 @@ coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
/* Quickly resolve the easy cases. */
if (!(WINDOWP (hlinfo->mouse_face_window)
&& XWINDOW (hlinfo->mouse_face_window) == w))
- return 0;
+ return false;
if (vpos < hlinfo->mouse_face_beg_row
|| vpos > hlinfo->mouse_face_end_row)
- return 0;
+ return false;
if (vpos > hlinfo->mouse_face_beg_row
&& vpos < hlinfo->mouse_face_end_row)
- return 1;
+ return true;
if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
{
if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
- return 1;
+ return true;
}
else if ((vpos == hlinfo->mouse_face_beg_row
&& hpos >= hlinfo->mouse_face_beg_col)
|| (vpos == hlinfo->mouse_face_end_row
&& hpos < hlinfo->mouse_face_end_col))
- return 1;
+ return true;
}
else
{
if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
- return 1;
+ return true;
}
else if ((vpos == hlinfo->mouse_face_beg_row
&& hpos <= hlinfo->mouse_face_beg_col)
|| (vpos == hlinfo->mouse_face_end_row
&& hpos > hlinfo->mouse_face_end_col))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* EXPORT:
- Non-zero if physical cursor of window W is within mouse face. */
+ True if physical cursor of window W is within mouse face. */
-int
+bool
cursor_in_mouse_face_p (struct window *w)
{
int hpos = w->phys_cursor.hpos;
@@ -27417,7 +28101,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id
- = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore,
+ = face_at_buffer_position (w, mouse_charpos, &ignore,
mouse_charpos + 1,
!hlinfo->mouse_face_hidden, -1);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
@@ -27683,7 +28367,7 @@ on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
if (VECTORP (XCDR (hot_spot)))
{
struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
- Lisp_Object *poly = v->u.contents;
+ Lisp_Object *poly = v->contents;
ptrdiff_t n = v->header.size;
ptrdiff_t i;
int inside = 0;
@@ -27787,6 +28471,8 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
cursor = FRAME_X_OUTPUT (f)->text_cursor;
else if (EQ (pointer, intern ("hdrag")))
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ else if (EQ (pointer, intern ("nhdrag")))
+ cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
#ifdef HAVE_X_WINDOWS
else if (EQ (pointer, intern ("vdrag")))
cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
@@ -27935,8 +28621,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
else if (area == ON_MODE_LINE)
{
Lisp_Object default_help
- = buffer_local_value_1 (Qmode_line_default_help_echo,
- w->contents);
+ = buffer_local_value (Qmode_line_default_help_echo,
+ w->contents);
if (STRINGP (default_help))
{
@@ -27952,6 +28638,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
/* Change the mouse pointer according to what is under it. */
if (FRAME_WINDOW_P (f))
{
+ bool draggable = (! WINDOW_BOTTOMMOST_P (w)
+ || minibuf_level
+ || NILP (Vresize_mini_windows));
+
dpyinfo = FRAME_DISPLAY_INFO (f);
if (STRINGP (string))
{
@@ -27968,11 +28658,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
map = Fget_text_property (pos, Qlocal_map, string);
if (!KEYMAPP (map))
map = Fget_text_property (pos, Qkeymap, string);
- if (!KEYMAPP (map))
+ if (!KEYMAPP (map) && draggable)
cursor = dpyinfo->vertical_scroll_bar_cursor;
}
}
- else
+ else if (draggable)
/* Default mode-line pointer. */
cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
}
@@ -28098,8 +28788,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
hlinfo->mouse_face_face_id = face_at_string_position (w, string,
charpos,
- 0, 0, 0,
- &ignore,
+ 0, &ignore,
glyph->face_id,
1);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
@@ -28192,7 +28881,17 @@ note_mouse_highlight (struct frame *f, int x, int y)
|| part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
{
note_mode_line_or_margin_highlight (window, x, y, part);
- return;
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+ {
+ cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+ /* Show non-text cursor (Bug#16647). */
+ goto set_cursor;
+ }
+ else
+#endif
+ return;
}
#ifdef HAVE_WINDOW_SYSTEM
@@ -28201,6 +28900,21 @@ note_mouse_highlight (struct frame *f, int x, int y)
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
help_echo_string = build_string ("drag-mouse-1: resize");
}
+ else if (part == ON_RIGHT_DIVIDER)
+ {
+ cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ help_echo_string = build_string ("drag-mouse-1: resize");
+ }
+ else if (part == ON_BOTTOM_DIVIDER)
+ if (! WINDOW_BOTTOMMOST_P (w)
+ || minibuf_level
+ || NILP (Vresize_mini_windows))
+ {
+ cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
+ help_echo_string = build_string ("drag-mouse-1: resize");
+ }
+ else
+ cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
|| part == ON_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -28400,7 +29114,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
hlinfo->mouse_face_past_end = 0;
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id
- = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
+ = face_at_string_position (w, object, pos, 0, &ignore,
glyph->face_id, 1);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
cursor = No_Cursor;
@@ -28447,13 +29161,14 @@ note_mouse_highlight (struct frame *f, int x, int y)
the first row visible in a window does not
necessarily display the character whose position
is the smallest. */
- Lisp_Object lim1 =
- NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
+ Lisp_Object lim1
+ = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
? Fmarker_position (w->start)
: Qnil;
- Lisp_Object lim2 =
- NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
- ? make_number (BUF_Z (XBUFFER (buffer)) - w->window_end_pos)
+ Lisp_Object lim2
+ = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
+ ? make_number (BUF_Z (XBUFFER (buffer))
+ - w->window_end_pos)
: Qnil;
if (NILP (overlay))
@@ -28840,7 +29555,7 @@ x_draw_vertical_border (struct window *w)
do it for frames with vertical scroll bars because either the
right scroll bar of a window, or the left scroll bar of its
neighbor will suffice as a border. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
return;
/* Note: It is necessary to redraw both the left and the right
@@ -28859,6 +29574,7 @@ x_draw_vertical_border (struct window *w)
FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
}
+
if (!WINDOW_LEFTMOST_P (w)
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
{
@@ -28875,6 +29591,45 @@ x_draw_vertical_border (struct window *w)
}
+/* Draw window dividers for window W. */
+
+void
+x_draw_right_divider (struct window *w)
+{
+ struct frame *f = WINDOW_XFRAME (w);
+
+ if (w->mini || w->pseudo_window_p)
+ return;
+ else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ {
+ int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+ int x1 = WINDOW_RIGHT_EDGE_X (w);
+ int y0 = WINDOW_TOP_EDGE_Y (w);
+ /* The bottom divider prevails. */
+ int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+
+ FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+ }
+}
+
+static void
+x_draw_bottom_divider (struct window *w)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+ if (w->mini || w->pseudo_window_p)
+ return;
+ else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ {
+ int x0 = WINDOW_LEFT_EDGE_X (w);
+ int x1 = WINDOW_RIGHT_EDGE_X (w);
+ int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+
+ FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+ }
+}
+
/* Redraw the part of window W intersection rectangle FR. Pixel
coordinates in FR are frame-relative. Call this function with
input blocked. Value is non-zero if the exposure overwrites
@@ -28906,8 +29661,8 @@ expose_window (struct window *w, XRectangle *fr)
/* Frame-relative pixel rectangle of W. */
wr.x = WINDOW_LEFT_EDGE_X (w);
wr.y = WINDOW_TOP_EDGE_Y (w);
- wr.width = WINDOW_TOTAL_WIDTH (w);
- wr.height = WINDOW_TOTAL_HEIGHT (w);
+ wr.width = WINDOW_PIXEL_WIDTH (w);
+ wr.height = WINDOW_PIXEL_HEIGHT (w);
if (x_intersect_rectangles (fr, &wr, &r))
{
@@ -29003,7 +29758,13 @@ expose_window (struct window *w, XRectangle *fr)
fr);
/* Draw border between windows. */
- x_draw_vertical_border (w);
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+
+ if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ x_draw_bottom_divider (w);
/* Turn the cursor on again. */
if (cursor_cleared_p
@@ -29196,6 +29957,8 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result)
void
syms_of_xdisp (void)
{
+#include "xdisp.x"
+
Vwith_echo_area_save_vector = Qnil;
staticpro (&Vwith_echo_area_save_vector);
@@ -29212,24 +29975,6 @@ syms_of_xdisp (void)
message_dolog_marker3 = Fmake_marker ();
staticpro (&message_dolog_marker3);
-#ifdef GLYPH_DEBUG
- defsubr (&Sdump_frame_glyph_matrix);
- defsubr (&Sdump_glyph_matrix);
- defsubr (&Sdump_glyph_row);
- defsubr (&Sdump_tool_bar_row);
- defsubr (&Strace_redisplay);
- defsubr (&Strace_to_stderr);
-#endif
-#ifdef HAVE_WINDOW_SYSTEM
- defsubr (&Stool_bar_lines_needed);
- defsubr (&Slookup_image_map);
-#endif
- defsubr (&Sline_pixel_height);
- defsubr (&Sformat_mode_line);
- defsubr (&Sinvisible_p);
- defsubr (&Scurrent_bidi_paragraph_direction);
- defsubr (&Smove_point_visually);
-
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
DEFSYM (Qoverriding_local_map, "overriding-local-map");
@@ -29689,8 +30434,8 @@ Bind this around calls to `message' to let it take effect. */);
DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
doc: /* Normal hook run to update the menu bar definitions.
Redisplay runs this hook before it redisplays the menu bar.
-This is used to update submenus such as Buffers,
-whose contents depend on various data. */);
+This is used to update menus such as Buffers, whose contents depend on
+various data. */);
Vmenu_bar_update_hook = Qnil;
DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
@@ -29786,6 +30531,13 @@ cursor shapes. */);
DEFSYM (Qthin_space, "thin-space");
DEFSYM (Qzero_width, "zero-width");
+ DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
+ doc: /* Function run just before redisplay.
+It is called with one argument, which is the set of windows that are to
+be redisplayed. This set can be nil (meaning, only the selected window),
+or t (meaning all windows). */);
+ Vpre_redisplay_function = intern ("ignore");
+
DEFSYM (Qglyphless_char_display, "glyphless-char-display");
Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
@@ -29804,7 +30556,11 @@ GRAPHICAL and TEXT should each have one of the values listed above.
The char-table has one extra slot to control the display of a character for
which no font is found. This slot only takes effect on graphical terminals.
Its value should be an ASCII acronym string, `hex-code', `empty-box', or
-`thin-space'. The default is `empty-box'. */);
+`thin-space'. The default is `empty-box'.
+
+If a character has a non-nil entry in an active display table, the
+display table takes effect; in this case, Emacs does not consult
+`glyphless-char-display' at all. */);
Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
Qempty_box);
@@ -29812,6 +30568,16 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
doc: /* If non-nil, debug if a message matching this regexp is displayed. */);
Vdebug_on_message = Qnil;
+
+ DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
+ doc: /* */);
+ Vredisplay__all_windows_cause
+ = Fmake_vector (make_number (100), make_number (0));
+
+ DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
+ doc: /* */);
+ Vredisplay__mode_lines_cause
+ = Fmake_vector (make_number (100), make_number (0));
}
@@ -29834,12 +30600,18 @@ init_xdisp (void)
echo_area_window = minibuf_window;
r->top_line = FRAME_TOP_MARGIN (f);
- r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
r->total_cols = FRAME_COLS (f);
+ r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
+ r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
m->top_line = FRAME_LINES (f) - 1;
- m->total_lines = 1;
+ m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
m->total_cols = FRAME_COLS (f);
+ m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
+ m->total_lines = 1;
+ m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
scratch_glyph_row.glyphs[TEXT_AREA + 1]
@@ -29854,7 +30626,7 @@ init_xdisp (void)
/* Allocate the buffer for frame titles.
Also used for `format-mode-line'. */
int size = 100;
- mode_line_noprop_buf = xmalloc (size);
+ mode_line_noprop_buf = xmalloc_atomic (size);
mode_line_noprop_buf_end = mode_line_noprop_buf + size;
mode_line_noprop_ptr = mode_line_noprop_buf;
mode_line_target = MODE_LINE_DISPLAY;