\f
/* Function prototypes. */
+static int single_display_prop_intangible_p P_ ((Lisp_Object));
static void ensure_echo_area_buffers P_ ((void));
static struct glyph_row *row_containing_pos P_ ((struct window *, int,
struct glyph_row *,
it->dpvec = NULL;
it->current.dpvec_index = -1;
+ it->add_overlay_start = 0;
do
{
for (p = it_props; p->handler; ++p)
{
handled = p->handler (it);
-
+
if (handled == HANDLED_RECOMPUTE_PROPS)
break;
else if (handled == HANDLED_RETURN)
= TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
handled = HANDLED_RECOMPUTE_PROPS;
+ it->add_overlay_start = IT_CHARPOS (*it);
/* Loop skipping over invisible text. The loop is left at
ZV or with IT on the first char being visible again. */
{
Lisp_Object value;
int space_or_image_found_p = 0;
-
Lisp_Object form;
/* If PROP is a list of the form `(when FORM . VALUE)', FORM is
}
+/* Check if PROP is a display sub-property value whose text should be
+ treated as intangible. */
+
+static int
+single_display_prop_intangible_p (prop)
+ Lisp_Object prop;
+{
+ /* Skip over `when FORM'. */
+ if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+ {
+ prop = XCDR (prop);
+ if (!CONSP (prop))
+ return 0;
+ prop = XCDR (prop);
+ }
+
+ if (!CONSP (prop))
+ return 0;
+
+ /* Skip over `margin LOCATION'. If LOCATION is in the margins,
+ we don't need to treat text as intangible. */
+ if (EQ (XCAR (prop), Qmargin))
+ {
+ prop = XCDR (prop);
+ if (!CONSP (prop))
+ return 0;
+
+ prop = XCDR (prop);
+ if (!CONSP (prop)
+ || EQ (XCAR (prop), Qleft_margin)
+ || EQ (XCAR (prop), Qright_margin))
+ return 0;
+ }
+
+ return CONSP (prop) && EQ (XCAR (prop), Qimage);
+}
+
+
+/* Check if PROP is a display property value whose text should be
+ treated as intangible. */
+
+int
+display_prop_intangible_p (prop)
+ Lisp_Object prop;
+{
+ if (CONSP (prop)
+ && CONSP (XCAR (prop))
+ && !EQ (Qmargin, XCAR (XCAR (prop))))
+ {
+ /* A list of sub-properties. */
+ while (CONSP (prop))
+ {
+ if (single_display_prop_intangible_p (XCAR (prop)))
+ return 1;
+ prop = XCDR (prop);
+ }
+ }
+ else if (VECTORP (prop))
+ {
+ /* A vector of sub-properties. */
+ int i;
+ for (i = 0; i < XVECTOR (prop)->size; ++i)
+ if (single_display_prop_intangible_p (XVECTOR (prop)->contents[i]))
+ return 1;
+ }
+ else
+ return single_display_prop_intangible_p (prop);
+
+ return 0;
+}
+
\f
/***********************************************************************
`composition' property
struct overlay_entry
{
+ Lisp_Object overlay;
Lisp_Object string;
int priority;
int after_string_p;
handle_overlay_change (it)
struct it *it;
{
- /* Overlays are handled in current_buffer only. */
- if (STRINGP (it->string))
- return HANDLED_NORMALLY;
+ if (!STRINGP (it->string) && get_overlay_strings (it))
+ return HANDLED_RECOMPUTE_PROPS;
else
- return (get_overlay_strings (it)
- ? HANDLED_RECOMPUTE_PROPS
- : HANDLED_NORMALLY);
+ return HANDLED_NORMALLY;
}
SET_TEXT_POS (it->current.string_pos, -1, -1);
it->n_overlay_strings = 0;
it->method = next_element_from_buffer;
+
+ /* If we're at the end of the buffer, record that we have
+ processed the overlay strings there already, so that
+ next_element_from_buffer doesn't try it again. */
+ if (IT_CHARPOS (*it) >= it->end_charpos)
+ it->overlay_strings_at_end_processed_p = 1;
}
else
{
comparison function for qsort in load_overlay_strings. Overlay
strings for the same position are sorted so that
- 1. All after-strings come in front of before-strings.
+ 1. All after-strings come in front of before-strings, except
+ when they come from the same overlay.
2. Within after-strings, strings are sorted so that overlay strings
from overlays with higher priorities come first.
int result;
if (entry1->after_string_p != entry2->after_string_p)
- /* Let after-strings appear in front of before-strings. */
- result = entry1->after_string_p ? -1 : 1;
+ {
+ /* Let after-strings appear in front of before-strings if
+ they come from different overlays. */
+ if (EQ (entry1->overlay, entry2->overlay))
+ result = entry1->after_string_p ? 1 : -1;
+ else
+ result = entry1->after_string_p ? -1 : 1;
+ }
else if (entry1->after_string_p)
/* After-strings sorted in order of decreasing priority. */
result = entry2->priority - entry1->priority;
strings that have already been loaded by previous calls to this
function.
+ IT->add_overlay_start contains an additional overlay start
+ position to consider for taking overlay strings from, if non-zero.
+ This position comes into play when the overlay has an `invisible'
+ property, and both before and after-strings. When we've skipped to
+ the end of the overlay, because of its `invisible' property, we
+ nevertheless want its before-string to appear.
+ IT->add_overlay_start will contain the overlay start position
+ in this case.
+
Overlay strings are sorted so that after-string strings come in
front of before-string strings. Within before and after-strings,
strings are sorted by overlay priority. See also function
} \
\
entries[n].string = (STRING); \
+ entries[n].overlay = (OVERLAY); \
priority = Foverlay_get ((OVERLAY), Qpriority); \
- entries[n].priority \
- = INTEGERP (priority) ? XFASTINT (priority) : 0; \
+ entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
entries[n].after_string_p = (AFTER_P); \
++n; \
} \
while (0)
/* Process overlay before the overlay center. */
- for (ov = current_buffer->overlays_before;
- CONSP (ov);
- ov = XCDR (ov))
+ for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
{
overlay = XCAR (ov);
xassert (OVERLAYP (overlay));
/* Skip this overlay if it doesn't start or end at IT's current
position. */
- if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+ if (end != IT_CHARPOS (*it)
+ && start != IT_CHARPOS (*it)
+ && it->add_overlay_start != IT_CHARPOS (*it))
continue;
/* Skip this overlay if it doesn't apply to IT->w. */
continue;
/* If overlay has a non-empty before-string, record it. */
- if (start == IT_CHARPOS (*it)
+ if ((start == IT_CHARPOS (*it)
+ || start == it->add_overlay_start)
&& (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
&& XSTRING (str)->size)
RECORD_OVERLAY_STRING (overlay, str, 0);
}
/* Process overlays after the overlay center. */
- for (ov = current_buffer->overlays_after;
- CONSP (ov);
- ov = XCDR (ov))
+ for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
{
overlay = XCAR (ov);
xassert (OVERLAYP (overlay));
/* Skip this overlay if it doesn't start or end at IT's current
position. */
- if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+ if (end != IT_CHARPOS (*it)
+ && start != IT_CHARPOS (*it)
+ && it->add_overlay_start != IT_CHARPOS (*it))
continue;
/* Skip this overlay if it doesn't apply to IT->w. */
continue;
/* If overlay has a non-empty before-string, record it. */
- if (start == IT_CHARPOS (*it)
+ if ((start == IT_CHARPOS (*it)
+ || start == it->add_overlay_start)
&& (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
&& XSTRING (str)->size)
RECORD_OVERLAY_STRING (overlay, str, 0);
#undef RECORD_OVERLAY_STRING
/* Sort entries. */
- qsort (entries, n, sizeof *entries, compare_overlay_entries);
+ if (n)
+ qsort (entries, n, sizeof *entries, compare_overlay_entries);
/* Record the total number of strings to process. */
it->n_overlay_strings = n;
j = it->current.overlay_string_index;
while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
it->overlay_strings[i++] = entries[j++].string;
-
+
CHECK_IT (it);
}
height = it.current_y + last_height;
else
height = it.current_y + it.max_ascent + it.max_descent;
+ height -= it.extra_line_spacing;
height = (height + unit - 1) / unit;
}
struct glyph_row *start_row;
int start_vpos, min_y, max_y;
- /* Right now this function doesn't handle terminal frames. */
- if (!FRAME_WINDOW_P (f))
+
+ if (/* This function doesn't handle terminal frames. */
+ !FRAME_WINDOW_P (f)
+ /* Don't try to reuse the display if windows have been split
+ or such. */
+ || windows_or_buffers_changed)
return 0;
/* Can't do this if region may have changed. */
/* Dump the contents of glyph matrix MATRIX on stderr. If
WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
-void
+static void
dump_glyph_matrix (matrix, with_glyphs_p)
struct glyph_matrix *matrix;
int with_glyphs_p;
if (glyph < glyph_end)
{
- fprintf (stderr, " Glyph Type Pos W Code C Face LR\n");
+ fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
prev_had_glyphs_p = 1;
}
else
if (glyph->type == CHAR_GLYPH)
{
fprintf (stderr,
- " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
'C',
glyph->charpos,
+ (BUFFERP (glyph->object)
+ ? 'B'
+ : (STRINGP (glyph->object)
+ ? 'S'
+ : '-')),
glyph->pixel_width,
glyph->u.ch,
(glyph->u.ch < 0x80 && glyph->u.ch >= ' '
else if (glyph->type == STRETCH_GLYPH)
{
fprintf (stderr,
- " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
'S',
glyph->charpos,
+ (BUFFERP (glyph->object)
+ ? 'B'
+ : (STRINGP (glyph->object)
+ ? 'S'
+ : '-')),
glyph->pixel_width,
0,
'.',
else if (glyph->type == IMAGE_GLYPH)
{
fprintf (stderr,
- " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
'I',
glyph->charpos,
+ (BUFFERP (glyph->object)
+ ? 'B'
+ : (STRINGP (glyph->object)
+ ? 'S'
+ : '-')),
glyph->pixel_width,
glyph->u.img_id,
'.',
w->base_line_pos = Qnil;
/* If the buffer is very big, don't waste time. */
- if (!INTEGERP (Vline_number_display_limit)
+ if (INTEGERP (Vline_number_display_limit)
&& BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
{
w->base_line_pos = Qnil;
while (pad-- > 0)
*p++ = ' ';
*p++ = '?';
- *p = '?';
+ *p++ = '?';
+ *p = '\0';
return decode_mode_spec_buf;
}
}