Fix bug in displaying header line with a box face

* src/xdisp.c (get_next_display_element): Handle the case when a
display string acquires the box face from an underlying string,
not from the buffer.  (Bug#23091)
This commit is contained in:
Eli Zaretskii 2016-03-22 20:16:42 +02:00
parent 91e667692b
commit 38a43f1a8f

View file

@ -7229,18 +7229,21 @@ get_next_display_element (struct it *it)
{ {
ptrdiff_t ignore; ptrdiff_t ignore;
int next_face_id; int next_face_id;
bool text_from_string = false;
/* Normally, the next buffer location is stored in
IT->current.pos... */
struct text_pos pos = it->current.pos; struct text_pos pos = it->current.pos;
/* For a string from a display property, the next /* ...but for a string from a display property, the
buffer position is stored in the 'position' next buffer position is stored in the 'position'
member of the iteration stack slot below the member of the iteration stack slot below the
current one, see handle_single_display_spec. By current one, see handle_single_display_spec. By
contrast, it->current.pos was not yet updated contrast, it->current.pos was not yet updated to
to point to that buffer position; that will point to that buffer position; that will happen
happen in pop_it, after we finish displaying the in pop_it, after we finish displaying the current
current string. Note that we already checked string. Note that we already checked above that
above that it->sp is positive, so subtracting one it->sp is positive, so subtracting one from it is
from it is safe. */ safe. */
if (it->from_disp_prop_p) if (it->from_disp_prop_p)
{ {
int stackp = it->sp - 1; int stackp = it->sp - 1;
@ -7249,19 +7252,49 @@ get_next_display_element (struct it *it)
while (stackp >= 0 while (stackp >= 0
&& STRINGP ((it->stack + stackp)->string)) && STRINGP ((it->stack + stackp)->string))
stackp--; stackp--;
eassert (stackp >= 0); if (stackp < 0)
pos = (it->stack + stackp)->position; {
/* If no stack slot was found for iterating
a buffer, we are displaying text from a
string, most probably the mode line or
the header line, and that string has a
display string on some of its
characters. */
text_from_string = true;
pos = it->stack[it->sp - 1].position;
}
else
pos = (it->stack + stackp)->position;
} }
else else
INC_TEXT_POS (pos, it->multibyte_p); INC_TEXT_POS (pos, it->multibyte_p);
if (CHARPOS (pos) >= ZV) if (text_from_string)
{
Lisp_Object base_string = it->stack[it->sp - 1].string;
if (CHARPOS (pos) >= SCHARS (base_string) - 1)
it->end_of_box_run_p = true;
else
{
next_face_id
= face_at_string_position (it->w, base_string,
CHARPOS (pos), 0,
&ignore, face_id, false);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
}
}
else if (CHARPOS (pos) >= ZV)
it->end_of_box_run_p = true; it->end_of_box_run_p = true;
else else
{ {
next_face_id = face_at_buffer_position next_face_id =
(it->w, CHARPOS (pos), &ignore, face_at_buffer_position (it->w, CHARPOS (pos), &ignore,
CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, false, -1); CHARPOS (pos)
+ TEXT_PROP_DISTANCE_LIMIT,
false, -1);
it->end_of_box_run_p it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box = (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX); == FACE_NO_BOX);