summaryrefslogtreecommitdiff
path: root/src/xdisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdisp.c')
-rw-r--r--src/xdisp.c646
1 files changed, 453 insertions, 193 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index aeaf8b34652..140d71129f3 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2508,7 +2508,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
r.x = s->clip_head->x;
}
if (s->clip_tail)
- if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
+ if (r.x + (int) r.width > s->clip_tail->x + s->clip_tail->background_width)
{
if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
@@ -2588,7 +2588,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
if (height < r.height)
{
- max_y = r.y + r.height;
+ max_y = r.y + (int) r.height;
r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
r.height = min (max_y - r.y, height);
}
@@ -2629,7 +2629,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
if (s->for_overlaps & OVERLAPS_PRED)
{
rs[i] = r;
- if (r.y + r.height > row_y)
+ if (r.y + (int) r.height > row_y)
{
if (r.y < row_y)
rs[i].height = row_y - r.y;
@@ -2643,10 +2643,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
rs[i] = r;
if (r.y < row_y + s->row->visible_height)
{
- if (r.y + r.height > row_y + s->row->visible_height)
+ if (r.y + (int) r.height > row_y + s->row->visible_height)
{
rs[i].y = row_y + s->row->visible_height;
- rs[i].height = r.y + r.height - rs[i].y;
+ rs[i].height = r.y + (int) r.height - rs[i].y;
}
else
rs[i].height = 0;
@@ -2831,7 +2831,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
text_glyph:
gr = 0; gy = 0;
for (; r <= end_row && r->enabled_p; ++r)
- if (r->y + r->height > y)
+ if (r->y + (int) r->height > y)
{
gr = r; gy = r->y;
break;
@@ -2931,7 +2931,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
row_glyph:
gr = 0, gy = 0;
for (; r <= end_row && r->enabled_p; ++r)
- if (r->y + r->height > y)
+ if (r->y + (int) r->height > y)
{
gr = r; gy = r->y;
break;
@@ -3072,10 +3072,24 @@ dsafe__call (bool inhibit_quit, Lisp_Object (f) (ptrdiff_t, Lisp_Object *),
return val;
}
+static Lisp_Object
+funcall_with_backtraces (ptrdiff_t nargs, Lisp_Object *args)
+{
+ /* If an error is signaled during a Lisp hook in redisplay, write a
+ backtrace into the buffer *Redisplay-trace*. */
+ push_handler_bind (list_of_error, Qdebug_early__muted, 0);
+ Lisp_Object res = Ffuncall (nargs, args);
+ pop_handler ();
+ return res;
+}
+
#define SAFE_CALLMANY(inhibit_quit, f, array) \
- dsafe__call ((inhibit_quit), f, ARRAYELTS (array), array)
-#define dsafe_calln(inhibit_quit, ...) \
- SAFE_CALLMANY ((inhibit_quit), Ffuncall, ((Lisp_Object []) {__VA_ARGS__}))
+ dsafe__call (inhibit_quit, f, ARRAYELTS (array), array)
+#define dsafe_calln(inhibit_quit, ...) \
+ SAFE_CALLMANY (inhibit_quit, \
+ backtrace_on_redisplay_error \
+ ? funcall_with_backtraces : Ffuncall, \
+ ((Lisp_Object []) {__VA_ARGS__}))
static Lisp_Object
dsafe_call1 (Lisp_Object f, Lisp_Object arg)
@@ -3807,7 +3821,7 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
it->current_y = first_y;
it->vpos = 0;
- it->current_x = it->hpos = 0;
+ it->current_x = it->hpos = it->wrap_prefix_width = 0;
}
}
}
@@ -4331,10 +4345,7 @@ compute_stop_pos (struct it *it)
}
}
- if (it->cmp_it.id < 0
- && (STRINGP (it->string)
- || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
- && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
+ if (it->cmp_it.id < 0)
{
ptrdiff_t stoppos = it->end_charpos;
@@ -4342,8 +4353,10 @@ compute_stop_pos (struct it *it)
an automatic composition, limit the search of composable
characters to that position. */
if (it->bidi_p && it->bidi_it.scan_dir < 0)
- stoppos = -1;
- else if (cmp_limit_pos > 0)
+ stoppos = bidi_level_start (it->bidi_it.resolved_level) - 1;
+ else if (!STRINGP (it->string)
+ && it->cmp_it.stop_pos <= IT_CHARPOS (*it)
+ && cmp_limit_pos > 0)
stoppos = cmp_limit_pos;
/* Force composition_compute_stop_pos avoid the costly search
for static compositions, since those were already found by
@@ -5048,31 +5061,169 @@ handle_invisible_prop (struct it *it)
{
enum prop_handled handled = HANDLED_NORMALLY;
int invis;
- Lisp_Object prop;
+ ptrdiff_t curpos, endpos;
+ Lisp_Object prop, pos, overlay;
+ /* Get the value of the invisible text property at the current
+ position. Value will be nil if there is no such property. */
if (STRINGP (it->string))
{
- Lisp_Object end_charpos, limit;
+ curpos = IT_STRING_CHARPOS (*it);
+ endpos = SCHARS (it->string);
+ pos = make_fixnum (curpos);
+ prop = Fget_text_property (pos, Qinvisible, it->string);
+ }
+ else /* buffer */
+ {
+ curpos = IT_CHARPOS (*it);
+ endpos = ZV;
+ pos = make_fixnum (curpos);
+ prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
+ &overlay);
+ }
- /* Get the value of the invisible text property at the
- current position. Value will be nil if there is no such
- property. */
- end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
- prop = Fget_text_property (end_charpos, Qinvisible, it->string);
- invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ /* Do we have anything to do here? */
+ invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ if (invis == 0 || curpos >= it->end_charpos)
+ return handled;
- if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
+ /* If not bidi, or the bidi iteration is at base paragraph level, we
+ can use a faster method; otherwise we need to check invisibility
+ of every character while bidi-iterating out of invisible text. */
+ bool slow = it->bidi_p && !BIDI_AT_BASE_LEVEL (it->bidi_it);
+ /* Record whether we have to display an ellipsis for the
+ invisible text. */
+ bool display_ellipsis_p = (invis == 2);
+
+ handled = HANDLED_RECOMPUTE_PROPS;
+
+ if (slow)
+ {
+ if (it->bidi_it.first_elt && it->bidi_it.charpos < endpos)
+ bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
+
+ if (STRINGP (it->string))
{
- /* Record whether we have to display an ellipsis for the
- invisible text. */
- bool display_ellipsis_p = (invis == 2);
- ptrdiff_t len, endpos;
+ bool done = false;
+ /* Bidi-iterate out of the invisible part of the string. */
+ do
+ {
+ bidi_move_to_visually_next (&it->bidi_it);
+ if (it->bidi_it.charpos < 0 || it->bidi_it.charpos >= endpos)
+ done = true;
+ else
+ {
+ pos = make_fixnum (it->bidi_it.charpos);
+ prop = Fget_text_property (pos, Qinvisible, it->string);
+ invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ /* If there are adjacent invisible texts, don't lose
+ the second one's ellipsis. */
+ if (invis == 2)
+ display_ellipsis_p = true;
+ }
+ }
+ while (!done && invis != 0);
- handled = HANDLED_RECOMPUTE_PROPS;
+ if (display_ellipsis_p)
+ it->ellipsis_p = true;
+ IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+ IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
+ if (IT_STRING_BYTEPOS (*it) >= endpos)
+ {
+ /* The rest of the string is invisible. If this is an
+ overlay string, proceed with the next overlay string
+ or whatever comes and return a character from there. */
+ if (it->current.overlay_string_index >= 0
+ && !display_ellipsis_p)
+ {
+ next_overlay_string (it);
+ /* Don't check for overlay strings when we just
+ finished processing them. */
+ handled = HANDLED_OVERLAY_STRING_CONSUMED;
+ }
+ }
+ }
+ else
+ {
+ bool done = false;
+ /* Bidi-iterate out of the invisible text. */
+ do
+ {
+ bidi_move_to_visually_next (&it->bidi_it);
+ if (it->bidi_it.charpos < BEGV || it->bidi_it.charpos >= endpos)
+ done = true;
+ else
+ {
+ pos = make_fixnum (it->bidi_it.charpos);
+ prop = Fget_char_property (pos, Qinvisible, it->window);
+ invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ /* If there are adjacent invisible texts, don't lose
+ the second one's ellipsis. */
+ if (invis == 2)
+ display_ellipsis_p = true;
+ }
+ }
+ while (!done && invis != 0);
+
+ IT_CHARPOS (*it) = it->bidi_it.charpos;
+ IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+ if (display_ellipsis_p)
+ {
+ /* Make sure that the glyphs of the ellipsis will get
+ correct `charpos' values. See below for detailed
+ explanation why this is needed. */
+ it->position.charpos = IT_CHARPOS (*it) - 1;
+ it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
+ }
+ /* If there are before-strings at the start of invisible
+ text, and the text is invisible because of a text
+ property, arrange to show before-strings because 20.x did
+ it that way. (If the text is invisible because of an
+ overlay property instead of a text property, this is
+ already handled in the overlay code.) */
+ if (NILP (overlay)
+ && get_overlay_strings (it, it->stop_charpos))
+ {
+ handled = HANDLED_RECOMPUTE_PROPS;
+ if (it->sp > 0)
+ {
+ it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
+ /* The call to get_overlay_strings above recomputes
+ it->stop_charpos, but it only considers changes
+ in properties and overlays beyond iterator's
+ current position. This causes us to miss changes
+ that happen exactly where the invisible property
+ ended. So we play it safe here and force the
+ iterator to check for potential stop positions
+ immediately after the invisible text. Note that
+ if get_overlay_strings returns true, it
+ normally also pushed the iterator stack, so we
+ need to update the stop position in the slot
+ below the current one. */
+ it->stack[it->sp - 1].stop_charpos
+ = CHARPOS (it->stack[it->sp - 1].current.pos);
+ }
+ }
+ else if (display_ellipsis_p)
+ {
+ it->ellipsis_p = true;
+ /* Let the ellipsis display before
+ considering any properties of the following char.
+ Fixes jasonr@gnu.org 01 Oct 07 bug. */
+ handled = HANDLED_RETURN;
+ }
+ }
+ }
+ else if (STRINGP (it->string))
+ {
+ Lisp_Object end_charpos = pos, limit;
+
+ if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
+ {
+ ptrdiff_t len = endpos;
/* Get the position at which the next visible text can be
found in IT->string, if any. */
- endpos = len = SCHARS (it->string);
XSETINT (limit, len);
do
{
@@ -5123,7 +5274,7 @@ handle_invisible_prop (struct it *it)
IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
- if (IT_CHARPOS (*it) >= endpos)
+ if (IT_STRING_CHARPOS (*it) >= endpos)
it->prev_stop = endpos;
}
else
@@ -5153,27 +5304,14 @@ handle_invisible_prop (struct it *it)
}
}
}
- else
+ else /* we are iterating over buffer text at base paragraph level */
{
- ptrdiff_t newpos, next_stop, start_charpos, tem;
- Lisp_Object pos, overlay;
-
- /* First of all, is there invisible text at this position? */
- tem = start_charpos = IT_CHARPOS (*it);
- pos = make_fixnum (tem);
- prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
- &overlay);
- invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ ptrdiff_t newpos, next_stop, tem = curpos;
+ Lisp_Object pos;
/* If we are on invisible text, skip over it. */
- if (invis != 0 && start_charpos < it->end_charpos)
+ if (invis != 0 && curpos < it->end_charpos)
{
- /* Record whether we have to display an ellipsis for the
- invisible text. */
- bool display_ellipsis_p = invis == 2;
-
- handled = HANDLED_RECOMPUTE_PROPS;
-
/* Loop skipping over invisible text. The loop is left at
ZV or with IT on the first char being visible again. */
do
@@ -5473,9 +5611,6 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
if (!NILP (it->min_width_property)
&& !EQ (width_spec, it->min_width_property))
{
- if (!it->glyph_row)
- return;
-
/* When called from display_string (i.e., the mode line),
we're being called with a string as the object, and we
may be called with many sub-strings belonging to the same
@@ -5518,7 +5653,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
it->object = list3 (Qspace, QCwidth, w);
produce_stretch_glyph (it);
if (it->area == TEXT_AREA)
- it->current_x += it->pixel_width;
+ {
+ it->current_x += it->pixel_width;
+
+ if (it->continuation_lines_width
+ && it->string_from_prefix_prop_p)
+ it->wrap_prefix_width = it->current_x;
+ }
it->min_width_property = Qnil;
}
}
@@ -6761,7 +6902,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
\
entries[n].string = (STRING); \
entries[n].overlay = (OVERLAY); \
- priority = Foverlay_get ((OVERLAY), Qpriority); \
+ priority = Foverlay_get (OVERLAY, Qpriority); \
entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
entries[n].after_string_p = (AFTER_P); \
++n; \
@@ -8571,9 +8712,8 @@ set_iterator_to_next (struct it *it, bool reseat_p)
ptrdiff_t stop = it->end_charpos;
if (it->bidi_it.scan_dir < 0)
- /* Now we are scanning backward and don't know
- where to stop. */
- stop = -1;
+ /* Now we are scanning backward; figure out where to stop. */
+ stop = bidi_level_start (it->bidi_it.resolved_level) - 1;
composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
IT_BYTEPOS (*it), stop, Qnil, true);
}
@@ -8604,7 +8744,7 @@ set_iterator_to_next (struct it *it, bool reseat_p)
re-compute the stop position for composition. */
ptrdiff_t stop = it->end_charpos;
if (it->bidi_it.scan_dir < 0)
- stop = -1;
+ stop = bidi_level_start (it->bidi_it.resolved_level) - 1;
composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
IT_BYTEPOS (*it), stop, Qnil,
true);
@@ -9049,7 +9189,9 @@ get_visually_first_element (struct it *it)
bytepos = IT_BYTEPOS (*it);
}
if (it->bidi_it.scan_dir < 0)
- stop = -1;
+ stop = STRINGP (it->string)
+ ? -1
+ : bidi_level_start (it->bidi_it.resolved_level) - 1;
composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
it->string, true);
}
@@ -9553,9 +9695,10 @@ next_element_from_buffer (struct it *it)
&& PT < it->end_charpos) ? PT : it->end_charpos;
}
else
- stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
- if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
- stop)
+ stop = it->bidi_it.scan_dir < 0
+ ? bidi_level_start (it->bidi_it.resolved_level) - 1
+ : it->end_charpos;
+ if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop)
&& next_element_from_composition (it))
{
return true;
@@ -9719,6 +9862,13 @@ move_it_in_display_line_to (struct it *it,
ptrdiff_t prev_pos = IT_CHARPOS (*it);
bool saw_smaller_pos = prev_pos < to_charpos;
bool line_number_pending = false;
+ int this_line_subject_to_line_prefix = 0;
+
+#ifdef GLYPH_DEBUG
+ /* atx_flag, atpos_flag and wrap_flag are assigned but never used;
+ these hold information useful while debugging. */
+ int atx_flag, atpos_flag, wrap_flag;
+#endif /* GLYPH_DEBUG */
/* Don't produce glyphs in produce_glyphs. */
saved_glyph_row = it->glyph_row;
@@ -9784,6 +9934,11 @@ move_it_in_display_line_to (struct it *it,
/* If there's a line-/wrap-prefix, handle it, if we didn't already. */
if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
handle_line_prefix (it);
+
+ /* Save whether this line has received a wrap prefix, as this
+ affects whether Emacs attempts to move glyphs into
+ continuation lines. */
+ this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
}
if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
@@ -9827,10 +9982,15 @@ move_it_in_display_line_to (struct it *it,
break;
}
else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
- /* If wrap_it is valid, the current position might be in a
- word that is wrapped. So, save the iterator in
- atpos_it and continue to see if wrapping happens. */
- SAVE_IT (atpos_it, *it, atpos_data);
+ {
+ /* If wrap_it is valid, the current position might be in
+ a word that is wrapped. So, save the iterator in
+ atpos_it and continue to see if wrapping happens. */
+ SAVE_IT (atpos_it, *it, atpos_data);
+#ifdef GLYPH_DEBUG
+ atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
+ }
}
/* Stop when ZV reached.
@@ -9892,6 +10052,9 @@ move_it_in_display_line_to (struct it *it,
}
/* Otherwise, we can wrap here. */
SAVE_IT (wrap_it, *it, wrap_data);
+#ifdef GLYPH_DEBUG
+ wrap_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
}
/* Update may_wrap for the next iteration. */
may_wrap = next_may_wrap;
@@ -9970,6 +10133,9 @@ move_it_in_display_line_to (struct it *it,
{
SAVE_IT (atpos_it, *it, atpos_data);
IT_RESET_X_ASCENT_DESCENT (&atpos_it);
+#ifdef GLYPH_DEBUG
+ atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
}
}
else
@@ -9984,6 +10150,9 @@ move_it_in_display_line_to (struct it *it,
{
SAVE_IT (atx_it, *it, atx_data);
IT_RESET_X_ASCENT_DESCENT (&atx_it);
+#ifdef GLYPH_DEBUG
+ atx_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
}
}
}
@@ -9998,12 +10167,27 @@ move_it_in_display_line_to (struct it *it,
&& FRAME_WINDOW_P (it->f)
&& ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
? WINDOW_LEFT_FRINGE_WIDTH (it->w)
- : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
+ /* There is no line prefix, next to which the
+ iterator _must_ produce a minimum of one actual
+ glyph. */
+ && (!this_line_subject_to_line_prefix
+ /* Or this is the second glyph to be produced
+ beyond the confines of the line. */
+ || (i != 0
+ && (x > it->last_visible_x
+ || (x == it->last_visible_x
+ && FRAME_WINDOW_P (it->f)
+ && ((it->bidi_p
+ && it->bidi_it.paragraph_dir == R2L)
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
{
bool moved_forward = false;
if (/* IT->hpos == 0 means the very first glyph
- doesn't fit on the line, e.g. a wide image. */
+ 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)))
@@ -10064,6 +10248,9 @@ move_it_in_display_line_to (struct it *it,
SAVE_IT (atpos_it, *it, atpos_data);
atpos_it.current_x = x_before_this_char;
atpos_it.hpos = hpos_before_this_char;
+#ifdef GLYPH_DEBUG
+ atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
}
}
@@ -10161,6 +10348,9 @@ move_it_in_display_line_to (struct it *it,
if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
{
SAVE_IT (atpos_it, *it, atpos_data);
+#ifdef GLYPH_DEBUG
+ atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
IT_RESET_X_ASCENT_DESCENT (&atpos_it);
}
}
@@ -10259,24 +10449,24 @@ move_it_in_display_line_to (struct it *it,
if (it->method == GET_FROM_BUFFER)
prev_pos = IT_CHARPOS (*it);
- /* Detect overly-wide wrap-prefixes made of (space ...) display
- properties. When such a wrap prefix reaches past the right
- margin of the window, we need to avoid the call to
- set_iterator_to_next below, so that it->line_wrap is left at
- its TRUNCATE value wisely set by handle_line_prefix.
- Otherwise, set_iterator_to_next will pop the iterator stack,
- restore it->line_wrap, and we might miss the opportunity to
- exit the loop and return. */
- bool overwide_wrap_prefix =
- CONSP (it->object) && EQ (XCAR (it->object), Qspace)
- && it->sp > 0 && it->method == GET_FROM_STRETCH
- && it->current_x >= it->last_visible_x
- && it->continuation_lines_width > 0
- && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
- /* The current display element has been consumed. Advance
- to the next. */
- if (!overwide_wrap_prefix)
- set_iterator_to_next (it, true);
+ /* The current display element has been consumed. Advance to
+ the next. */
+ set_iterator_to_next (it, true);
+
+ /* If IT has just finished producing glyphs for the wrap prefix
+ and is proceeding to the next method, there might not be
+ sufficient space remaining in this line to accommodate its
+ glyphs, and one real glyph must be produced to prevent an
+ infinite loop. Next, clear this flag if such a glyph has
+ already been produced. */
+
+ if (this_line_subject_to_line_prefix == 1
+ && !it->string_from_prefix_prop_p)
+ this_line_subject_to_line_prefix = 2;
+ else if (this_line_subject_to_line_prefix == 2
+ && !it->string_from_prefix_prop_p)
+ this_line_subject_to_line_prefix = 0;
+
if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
if (IT_CHARPOS (*it) < to_charpos)
@@ -10360,11 +10550,26 @@ move_it_in_display_line_to (struct it *it,
&& wrap_it.sp >= 0
&& ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
|| (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
- RESTORE_IT (it, &wrap_it, wrap_data);
+ {
+#ifdef GLYPH_DEBUG
+ this_line_subject_to_line_prefix = wrap_flag;
+#endif /* GLYPH_DEBUG */
+ RESTORE_IT (it, &wrap_it, wrap_data);
+ }
else if (atpos_it.sp >= 0)
- RESTORE_IT (it, &atpos_it, atpos_data);
+ {
+#ifdef GLYPH_DEBUG
+ this_line_subject_to_line_prefix = atpos_flag;
+#endif /* GLYPH_DEBUG */
+ RESTORE_IT (it, &atpos_it, atpos_data);
+ }
else if (atx_it.sp >= 0)
- RESTORE_IT (it, &atx_it, atx_data);
+ {
+#ifdef GLYPH_DEBUG
+ this_line_subject_to_line_prefix = atx_flag;
+#endif /* GLYPH_DEBUG */
+ RESTORE_IT (it, &atx_it, atx_data);
+ }
done:
@@ -10438,13 +10643,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
int line_height, line_start_x = 0, reached = 0;
int max_current_x = 0;
void *backup_data = NULL;
- ptrdiff_t orig_charpos = -1;
- enum it_method orig_method = NUM_IT_METHODS;
for (;;)
{
- orig_charpos = IT_CHARPOS (*it);
- orig_method = it->method;
if (op & MOVE_TO_VPOS)
{
/* If no TO_CHARPOS and no TO_X specified, stop at the
@@ -10716,21 +10917,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
}
}
else
- {
- /* Make sure we do advance, otherwise we might infloop.
- This could happen when the first display element is
- wider than the window, or if we have a wrap-prefix
- that doesn't leave enough space after it to display
- even a single character. We only do this for moving
- through buffer text, as with display/overlay strings
- we'd need to also compare it->object's, and this is
- unlikely to happen in that case anyway. */
- if (IT_CHARPOS (*it) == orig_charpos
- && it->method == orig_method
- && orig_method == GET_FROM_BUFFER)
- set_iterator_to_next (it, false);
- it->continuation_lines_width += it->current_x;
- }
+ it->continuation_lines_width += it->current_x;
break;
default:
@@ -10739,6 +10926,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
/* Reset/increment for the next run. */
it->current_x = line_start_x;
+ it->wrap_prefix_width = 0;
line_start_x = 0;
it->hpos = 0;
it->line_number_produced_p = false;
@@ -10769,6 +10957,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
{
it->continuation_lines_width += it->current_x;
it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
+ it->wrap_prefix_width = 0;
it->current_y += it->max_ascent + it->max_descent;
++it->vpos;
last_height = it->max_ascent + it->max_descent;
@@ -10828,6 +11017,7 @@ move_it_vertically_backward (struct it *it, int dy)
reseat_1 (it, it->current.pos, true);
/* We are now surely at a line start. */
+ it->wrap_prefix_width = 0;
it->current_x = it->hpos = 0; /* FIXME: this is incorrect when bidi
reordering is in effect. */
it->continuation_lines_width = 0;
@@ -11106,7 +11296,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
dvpos--;
}
- it->current_x = it->hpos = 0;
+ it->current_x = it->hpos = it->wrap_prefix_width = 0;
/* Above call may have moved too far if continuation lines
are involved. Scan forward and see if it did. */
@@ -11115,7 +11305,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
it->vpos -= it2.vpos;
it->current_y -= it2.current_y;
- it->current_x = it->hpos = 0;
+ it->current_x = it->hpos = it->wrap_prefix_width = 0;
/* If we moved too far back, move IT some lines forward. */
if (it2.vpos > -dvpos)
@@ -11394,7 +11584,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
IT.current_x will be incorrectly set to zero at some arbitrary
non-zero X coordinate. */
move_it_by_lines (&it, 0);
- it.current_x = it.hpos = 0;
+ it.current_x = it.hpos = it.wrap_prefix_width = 0;
if (IT_CHARPOS (it) != start)
{
void *it1data = NULL;
@@ -11447,7 +11637,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
/* If FROM is on a newline, pretend that we start at the beginning
of the next line, because the newline takes no place on display. */
if (FETCH_BYTE (start) == '\n')
- it.current_x = 0;
+ it.current_x = 0, it.wrap_prefix_width = 0;
if (!NILP (x_limit))
{
it.last_visible_x = max_x;
@@ -14359,7 +14549,7 @@ display_tab_bar_line (struct it *it, int height)
row->truncated_on_left_p = false;
row->truncated_on_right_p = false;
- it->current_x = it->hpos = 0;
+ it->current_x = it->hpos = it->wrap_prefix_width = 0;
it->current_y += row->height;
++it->vpos;
++it->glyph_row;
@@ -15383,7 +15573,7 @@ display_tool_bar_line (struct it *it, int height)
row->truncated_on_left_p = false;
row->truncated_on_right_p = false;
- it->current_x = it->hpos = 0;
+ it->current_x = it->hpos = it->wrap_prefix_width = 0;
it->current_y += row->height;
++it->vpos;
++it->glyph_row;
@@ -17083,6 +17273,7 @@ redisplay_internal (void)
NULL, DEFAULT_FACE_ID);
it.current_x = this_line_start_x;
it.current_y = this_line_y;
+ it.wrap_prefix_width = 0;
it.vpos = this_line_vpos;
if (current_buffer->long_line_optimizations_p
@@ -18668,6 +18859,14 @@ enum
`scroll-conservatively' and the Emacs manual. */
#define SCROLL_LIMIT 100
+/* The freshness of the w->base_line_number cache is only ensured at every
+ redisplay cycle, so the cache can be used only if there's been
+ no relevant changes to the buffer since the last redisplay. */
+#define BASE_LINE_NUMBER_VALID_P(w) \
+ (eassert (current_buffer == XBUFFER ((w)->contents)), \
+ !current_buffer->clip_changed \
+ && BEG_UNCHANGED >= (w)->base_line_pos)
+
static int
try_scrolling (Lisp_Object window, bool just_this_one_p,
intmax_t arg_scroll_conservatively, intmax_t scroll_step,
@@ -18968,9 +19167,10 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
else
{
/* Maybe forget recorded base line for line number display. */
- if (!just_this_one_p
- || current_buffer->clip_changed
- || BEG_UNCHANGED < CHARPOS (startp))
+ /* FIXME: Why do we need this? `try_scrolling` can only be called from
+ `redisplay_window` which should have flushed this cache already when
+ eeded. */
+ if (!BASE_LINE_NUMBER_VALID_P (w))
w->base_line_number = 0;
/* If cursor ends up on a partially visible line,
@@ -19740,9 +19940,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
/* Record it now because it's overwritten. */
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. */
- bool buffer_unchanged_p = false;
bool temp_scroll_step = false;
specpdl_ref count = SPECPDL_INDEX ();
int rc;
@@ -19848,11 +20045,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
specbind (Qinhibit_point_motion_hooks, Qt);
- buffer_unchanged_p
- = (w->window_end_valid
- && !current_buffer->clip_changed
- && !window_outdated (w));
-
/* When windows_or_buffers_changed is non-zero, we can't rely
on the window end being valid, so set it to zero there. */
if (windows_or_buffers_changed)
@@ -19992,6 +20184,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
}
}
+ if (!BASE_LINE_NUMBER_VALID_P (w))
+ /* Forget any recorded base line for line number display. */
+ w->base_line_number = 0;
+
force_start:
/* Handle case where place to start displaying has been specified,
@@ -20012,10 +20208,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
w->preserve_vscroll_p = false;
w->window_end_valid = false;
- /* Forget any recorded base line for line number display. */
- if (!buffer_unchanged_p)
- w->base_line_number = 0;
-
/* Redisplay the mode line. Select the buffer properly for that.
Also, run the hook window-scroll-functions
because we have scrolled. */
@@ -20344,12 +20536,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
if (w->cursor.vpos >= 0)
{
- if (!just_this_one_p
- || current_buffer->clip_changed
- || BEG_UNCHANGED < CHARPOS (startp))
- /* Forget any recorded base line for line number display. */
- w->base_line_number = 0;
-
if (!cursor_row_fully_visible_p (w, true, false, false))
{
clear_glyph_matrix (w->desired_matrix);
@@ -20420,10 +20606,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
debug_method_add (w, "recenter");
#endif
- /* Forget any previously recorded base line for line number display. */
- if (!buffer_unchanged_p)
- w->base_line_number = 0;
-
/* Determine the window start relative to point. */
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
it.current_y = it.last_visible_y;
@@ -20529,7 +20711,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
it.current_y = 0;
}
- it.current_x = it.hpos = 0;
+ it.current_x = it.wrap_prefix_width = it.hpos = 0;
/* Set the window start position here explicitly, to avoid an
infinite loop in case the functions in window-scroll-functions
@@ -22497,7 +22679,7 @@ try_window_id (struct window *w)
/* We may start in a continuation line. If so, we have to
get the right continuation_lines_width and current_x. */
it.continuation_lines_width = last_row->continuation_lines_width;
- it.hpos = it.current_x = 0;
+ it.hpos = it.current_x = it.wrap_prefix_width = 0;
/* Display the rest of the lines at the window end. */
it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
@@ -23102,6 +23284,7 @@ insert_left_trunc_glyphs (struct it *it)
/* Get the truncation glyphs. */
truncate_it = *it;
truncate_it.current_x = 0;
+ truncate_it.wrap_prefix_width = 0;
truncate_it.face_id = DEFAULT_FACE_ID;
truncate_it.glyph_row = &scratch_glyph_row;
truncate_it.area = TEXT_AREA;
@@ -23864,6 +24047,10 @@ extend_face_to_end_of_line (struct it *it)
for (it->current_x = 0; g < e; g++)
it->current_x += g->pixel_width;
+ if (it->continuation_lines_width
+ && it->string_from_prefix_prop_p)
+ it->wrap_prefix_width = it->current_x;
+
it->area = LEFT_MARGIN_AREA;
it->face_id = default_face->id;
while (it->glyph_row->used[LEFT_MARGIN_AREA]
@@ -24585,6 +24772,13 @@ maybe_produce_line_number (struct it *it)
if (!last_line)
{
/* If possible, reuse data cached by line-number-mode. */
+ /* NOTE: We use `base_line_number` without checking
+ BASE_LINE_NUMBER_VALID_P because we assume that `redisplay_window`
+ has already flushed this cache for us when needed.
+ NOTE2: Checking BASE_LINE_NUMBER_VALID_P here would be
+ overly pessimistic because it might say that the cache
+ was invalid before entering `redisplay_window` yet the
+ value has just been refreshed. */
if (it->w->base_line_number > 0
&& it->w->base_line_pos > 0
&& it->w->base_line_pos <= IT_CHARPOS (*it)
@@ -24634,7 +24828,7 @@ maybe_produce_line_number (struct it *it)
/* Produce the glyphs for the line number. */
struct it tem_it;
char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
- bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
+ bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE;
ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
int current_lnum_face_id
@@ -24864,7 +25058,7 @@ should_produce_line_number (struct it *it)
because get-char-property always returns nil for ZV, except if
the property is in 'default-text-properties'. */
if (NILP (val) && IT_CHARPOS (*it) >= ZV)
- val = disable_line_numbers_overlay_at_eob ();
+ return !disable_line_numbers_overlay_at_eob ();
return NILP (val) ? true : false;
}
@@ -24929,6 +25123,7 @@ display_line (struct it *it, int cursor_vpos)
int first_visible_x = it->first_visible_x;
int last_visible_x = it->last_visible_x;
int x_incr = 0;
+ int this_line_subject_to_line_prefix = 0;
/* We always start displaying at hpos zero even if hscrolled. */
eassert (it->hpos == 0 && it->current_x == 0);
@@ -25005,7 +25200,10 @@ display_line (struct it *it, int cursor_vpos)
if (it->current_x < it->first_visible_x
&& (move_result == MOVE_NEWLINE_OR_CR
|| move_result == MOVE_POS_MATCH_OR_ZV))
- it->current_x = it->first_visible_x;
+ {
+ it->current_x = it->first_visible_x;
+ it->wrap_prefix_width = 0;
+ }
/* In case move_it_in_display_line_to above "produced" the line
number. */
@@ -25034,6 +25232,7 @@ display_line (struct it *it, int cursor_vpos)
/* We only do this when not calling move_it_in_display_line_to
above, because that function calls itself handle_line_prefix. */
handle_line_prefix (it);
+ this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
}
else
{
@@ -25200,12 +25399,15 @@ display_line (struct it *it, int cursor_vpos)
process the prefix now. */
if (it->area == TEXT_AREA && pending_handle_line_prefix)
{
- /* Line numbers should precede the line-prefix or wrap-prefix. */
+ /* Line numbers should precede the line-prefix or
+ wrap-prefix. */
if (line_number_needed)
maybe_produce_line_number (it);
pending_handle_line_prefix = false;
handle_line_prefix (it);
+ this_line_subject_to_line_prefix
+ = it->string_from_prefix_prop_p;
}
continue;
}
@@ -25226,7 +25428,16 @@ display_line (struct it *it, int cursor_vpos)
if (/* Not a newline. */
nglyphs > 0
/* Glyphs produced fit entirely in the line. */
- && it->current_x < it->last_visible_x)
+ && (it->current_x < it->last_visible_x
+ /* Or a line or wrap prefix is in effect, and not
+ truncating the glyph produced immediately after it
+ would cause an infinite cycle. */
+ || (it->line_wrap != TRUNCATE
+ /* This code is not valid if multiple glyphs were
+ produced, as some of these glyphs might remain
+ within this line. */
+ && nglyphs == 1
+ && this_line_subject_to_line_prefix)))
{
it->hpos += nglyphs;
row->ascent = max (row->ascent, it->max_ascent);
@@ -25277,7 +25488,20 @@ display_line (struct it *it, int cursor_vpos)
&& FRAME_WINDOW_P (it->f)
&& (row->reversed_p
? WINDOW_LEFT_FRINGE_WIDTH (it->w)
- : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
+ /* There is no line prefix, next to which the
+ iterator _must_ produce a minimum of one actual
+ glyph. */
+ && (!this_line_subject_to_line_prefix
+ /* Or this is the second glyph to be produced
+ beyond the confines of the line. */
+ || (i != 0
+ && (x > it->last_visible_x
+ || (x == it->last_visible_x
+ && FRAME_WINDOW_P (it->f)
+ && (row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
{
/* End of a continued line. */
@@ -25574,24 +25798,23 @@ display_line (struct it *it, int cursor_vpos)
break;
}
- /* Detect overly-wide wrap-prefixes made of (space ...) display
- properties. When such a wrap prefix reaches past the right
- margin of the window, we need to avoid the call to
- set_iterator_to_next below, so that it->line_wrap is left at
- its TRUNCATE value wisely set by handle_line_prefix.
- Otherwise, set_iterator_to_next will pop the iterator stack,
- restore it->line_wrap, and redisplay might infloop. */
- bool overwide_wrap_prefix =
- CONSP (it->object) && EQ (XCAR (it->object), Qspace)
- && it->sp > 0 && it->method == GET_FROM_STRETCH
- && it->current_x >= it->last_visible_x
- && it->continuation_lines_width > 0
- && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
-
/* Proceed with next display element. Note that this skips
over lines invisible because of selective display. */
- if (!overwide_wrap_prefix)
- set_iterator_to_next (it, true);
+ set_iterator_to_next (it, true);
+
+ /* If IT has just finished producing glyphs for the wrap prefix
+ and is proceeding to the next method, there might not be
+ sufficient space remaining in this line to accommodate its
+ glyphs, and one real glyph must be produced to prevent an
+ infinite loop. Next, clear this flag if such a glyph has
+ already been produced. */
+
+ if (this_line_subject_to_line_prefix == 1
+ && !it->string_from_prefix_prop_p)
+ this_line_subject_to_line_prefix = 2;
+ else if (this_line_subject_to_line_prefix == 2
+ && !it->string_from_prefix_prop_p)
+ this_line_subject_to_line_prefix = 0;
/* If we truncate lines, we are done when the last displayed
glyphs reach past the right margin of the window. */
@@ -25837,7 +26060,7 @@ display_line (struct it *it, int cursor_vpos)
HPOS) = (0 0). Vertical positions are incremented. As a
convenience for the caller, IT->glyph_row is set to the next
row to be used. */
- it->current_x = it->hpos = 0;
+ it->wrap_prefix_width = it->current_x = it->hpos = 0;
it->current_y += row->height;
/* Restore the first and last visible X if we adjusted them for
current-line hscrolling. */
@@ -26316,7 +26539,7 @@ Value is the new character position of point. */)
{
struct text_pos pt;
struct it it;
- int pt_x, target_x, pixel_width, pt_vpos;
+ int pt_x, pt_wrap_prefix_x, target_x, pixel_width, pt_vpos;
bool at_eol_p;
bool overshoot_expected = false;
bool target_is_eol_p = false;
@@ -26348,6 +26571,7 @@ Value is the new character position of point. */)
reseat:
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = it.current_y = it.vpos = 0;
+ it.wrap_prefix_width = 0;
if (IT_CHARPOS (it) != PT)
{
move_it_to (&it, overshoot_expected ? PT - 1 : PT,
@@ -26366,6 +26590,7 @@ Value is the new character position of point. */)
move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
}
pt_x = it.current_x;
+ pt_wrap_prefix_x = it.wrap_prefix_width;
pt_vpos = it.vpos;
if (dir > 0 || overshoot_expected)
{
@@ -26380,10 +26605,11 @@ Value is the new character position of point. */)
it.glyph_row = NULL;
PRODUCE_GLYPHS (&it); /* compute it.pixel_width */
it.glyph_row = row;
- /* PRODUCE_GLYPHS advances it.current_x, so we must restore
- it, lest it will become out of sync with it's buffer
+ /* PRODUCE_GLYPHS advances it.current_x, so it must be
+ restored, lest it become out of sync with its buffer
position. */
it.current_x = pt_x;
+ it.wrap_prefix_width = pt_wrap_prefix_x;
}
else
at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
@@ -26428,6 +26654,7 @@ Value is the new character position of point. */)
it.last_visible_x = DISP_INFINITY;
reseat_at_previous_visible_line_start (&it);
it.current_x = it.current_y = it.hpos = 0;
+ it.wrap_prefix_width = 0;
if (pt_vpos != 0)
move_it_by_lines (&it, pt_vpos);
}
@@ -27944,6 +28171,11 @@ are the selected window and the WINDOW's buffer). */)
init_iterator (&it, w, -1, -1, NULL, face_id);
+ /* Make sure `base_line_number` is fresh in case we encounter a `%l`. */
+ if (current_buffer == XBUFFER ((w)->contents)
+ && !BASE_LINE_NUMBER_VALID_P (w))
+ w->base_line_number = 0;
+
if (no_props)
{
mode_line_target = MODE_LINE_NOPROP;
@@ -28396,30 +28628,29 @@ decode_mode_spec (struct window *w, register int c, int field_width,
when the buffer's restriction was changed, but the window
wasn't yet redisplayed after that. If that happens, we
need to determine a new base line. */
- if (!(BUF_BEGV_BYTE (b) <= startpos_byte
+ if (current_buffer != XBUFFER (w->contents)
+ || !(BUF_BEGV_BYTE (b) <= startpos_byte
&& startpos_byte <= BUF_ZV_BYTE (b)))
{
startpos = BUF_BEGV (b);
startpos_byte = BUF_BEGV_BYTE (b);
- w->base_line_pos = 0;
- w->base_line_number = 0;
}
/* If we decided that this buffer isn't suitable for line numbers,
- don't forget that too fast. */
+ don't forget that too fast.
+ FIXME: What if `current_buffer != w->contents`? */
if (w->base_line_pos == -1)
goto no_value;
/* If the buffer is very big, don't waste time. */
if (FIXNUMP (Vline_number_display_limit)
&& BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
- {
- w->base_line_pos = 0;
- w->base_line_number = 0;
- goto no_value;
- }
+ goto no_value;
- if (w->base_line_number > 0
+ /* Callers of `display_mode_element` are in charge of flushing
+ any stale `base_line_number` cache. */
+ if (current_buffer == XBUFFER ((w)->contents)
+ && w->base_line_number > 0
&& w->base_line_pos > 0
&& w->base_line_pos <= startpos)
{
@@ -28445,7 +28676,9 @@ decode_mode_spec (struct window *w, register int c, int field_width,
or too far away, or if we did not have one.
"Too close" means it's plausible a scroll-down would
go back past it. */
- if (startpos == BUF_BEGV (b))
+ if (current_buffer != XBUFFER (w->contents))
+ ; /* The base line is for another buffer, don't touch it! */
+ else if (startpos == BUF_BEGV (b))
{
w->base_line_number = topline;
w->base_line_pos = BUF_BEGV (b);
@@ -28482,6 +28715,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
goto no_value;
}
+ /* NOTE: if `clip_changed` is set or if `BEG_UNCHANGED` is
+ before `position`, this new cached value may get flushed
+ soon needlessly, because we can't reset `BEG_UNCHANGED` or
+ `clip_changed` from here (since they reflect the changes
+ since the last redisplay so they can only be reset from
+ `mark_window_display_accurate_1`). :-( */
w->base_line_number = topline - nlines;
w->base_line_pos = BYTE_TO_CHAR (position);
}
@@ -29509,9 +29748,9 @@ dump_glyph_string (struct glyph_string *s)
# define ALLOCATE_HDC(hdc, f) \
Lisp_Object prev_quit = Vinhibit_quit; \
Vinhibit_quit = Qt; \
- HDC hdc = get_frame_dc ((f))
+ HDC hdc = get_frame_dc (f)
# define RELEASE_HDC(hdc, f) \
- release_frame_dc ((f), (hdc)); \
+ release_frame_dc (f, hdc); \
Vinhibit_quit = prev_quit
#else
# define ALLOCATE_HDC(hdc, f)
@@ -30942,7 +31181,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
#ifdef HAVE_RSVG
/* Update SVG image glyphs with mouse face features. FIXME: it
- should be possible to have this behaviour with transparent
+ should be possible to have this behavior with transparent
background PNG. */
if (hl == DRAW_MOUSE_FACE)
{
@@ -32575,7 +32814,19 @@ gui_produce_glyphs (struct it *it)
if (font->space_width > 0)
{
int tab_width = it->tab_width * font->space_width;
- int x = it->current_x + it->continuation_lines_width;
+ /* wrap-prefix strings are prepended to continuation
+ lines, so the width of tab characters inside should
+ be computed from the start of this screen line rather
+ than as a product of the total width of the physical
+ line being wrapped. */
+ int x = it->current_x + (it->string_from_prefix_prop_p
+ /* Subtract the width of the
+ prefix from it->current_x if
+ it exists. */
+ ? 0 : (it->continuation_lines_width
+ ? (it->continuation_lines_width
+ - it->wrap_prefix_width)
+ : 0));
int x0 = x;
/* Adjust for line numbers, if needed. */
if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
@@ -33046,7 +33297,13 @@ gui_produce_glyphs (struct it *it)
because this isn't true for images with `:ascent 100'. */
eassert (it->ascent >= 0 && it->descent >= 0);
if (it->area == TEXT_AREA)
- it->current_x += it->pixel_width;
+ {
+ it->current_x += it->pixel_width;
+
+ if (it->continuation_lines_width
+ && it->string_from_prefix_prop_p)
+ it->wrap_prefix_width = it->current_x;
+ }
if (extra_line_spacing > 0)
{
@@ -36205,7 +36462,7 @@ expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
/* Use a signed int intermediate value to avoid catastrophic
failures due to comparison between signed and unsigned, when
x is negative (can happen for wide images that are hscrolled). */
- int r_end = r->x + r->width;
+ int r_end = r->x + (int) r->width;
while (last < end && x < r_end)
{
x += last->pixel_width;
@@ -36504,7 +36761,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr)
/* Use a signed int intermediate value to avoid catastrophic
failures due to comparison between signed and unsigned, when
y0 or y1 is negative (can happen for tall images). */
- int r_bottom = r.y + r.height;
+ int r_bottom = r.y + (int) r.height;
/* We must temporarily switch to the window's buffer, in case
the fringe face has been remapped in that buffer's
@@ -36551,7 +36808,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr)
/* We must redraw a row overlapping the exposed area. */
if (y0 < r.y
? y0 + row->phys_height > r.y
- : y0 + row->ascent - row->phys_ascent < r.y +r.height)
+ : y0 + row->ascent - row->phys_ascent < r.y + (int) r.height)
{
if (first_overlapping_row == NULL)
first_overlapping_row = row;
@@ -36730,7 +36987,7 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
const Emacs_Rectangle *upper, *lower;
bool intersection_p = false;
- /* Rearrange so that R1 is the left-most rectangle. */
+ /* Rearrange so that left is the left-most rectangle. */
if (r1->x < r2->x)
left = r1, right = r2;
else
@@ -36738,13 +36995,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
/* X0 of the intersection is right.x0, if this is inside R1,
otherwise there is no intersection. */
- if (right->x <= left->x + left->width)
+ if (right->x <= left->x + (int) left->width)
{
result->x = right->x;
/* The right end of the intersection is the minimum of
the right ends of left and right. */
- result->width = (min (left->x + left->width, right->x + right->width)
+ result->width = (min (left->x + (int) left->width,
+ right->x + (int) right->width)
- result->x);
/* Same game for Y. */
@@ -36755,14 +37013,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
/* The upper end of the intersection is lower.y0, if this is inside
of upper. Otherwise, there is no intersection. */
- if (lower->y <= upper->y + upper->height)
+ if (lower->y <= upper->y + (int) upper->height)
{
result->y = lower->y;
/* The lower end of the intersection is the minimum of the lower
ends of upper and lower. */
- result->height = (min (lower->y + lower->height,
- upper->y + upper->height)
+ result->height = (min (lower->y + (int) lower->height,
+ upper->y + (int) upper->height)
- result->y);
intersection_p = true;
}
@@ -37753,6 +38011,8 @@ cursor shapes. */);
DEFSYM (Qthin_space, "thin-space");
DEFSYM (Qzero_width, "zero-width");
+ DEFSYM (Qdebug_early__muted, "debug-early--muted");
+
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