/* The position newpos is now either ZV or on visible text. */
if (it->bidi_p && newpos < ZV)
{
- /* With bidi iteration, the region of invisible text
- could start and/or end in the middle of a non-base
- embedding level. Therefore, we need to skip
- invisible text using the bidi iterator, starting at
- IT's current position, until we find ourselves
- outside the invisible text. Skipping invisible text
- _after_ bidi iteration avoids affecting the visual
- order of the displayed text when invisible properties
- are added or removed. */
- if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+ EMACS_INT bpos = CHAR_TO_BYTE (newpos);
+
+ if (FETCH_BYTE (bpos) == '\n'
+ || (newpos > BEGV && FETCH_BYTE (bpos - 1) == '\n'))
{
- /* If we were `reseat'ed to a new paragraph,
- determine the paragraph base direction. We need
- to do it now because next_element_from_buffer may
- not have a chance to do it, if we are going to
- skip any text at the beginning, which resets the
- FIRST_ELT flag. */
- bidi_paragraph_init (it->paragraph_embedding,
- &it->bidi_it, 1);
+ /* If the invisible text ends on a newline or the
+ character after a newline, we can avoid the
+ costly, character by character, bidi iteration to
+ newpos, and instead simply reseat the iterator
+ there. That's because all bidi reordering
+ information is tossed at the newline. This is a
+ big win for modes that hide complete lines, like
+ Outline, Org, etc. (Implementation note: the
+ call to reseat_1 is necessary, because it signals
+ to the bidi iterator that it needs to reinit its
+ internal information when the next element for
+ display is requested. */
+ struct text_pos tpos;
+
+ SET_TEXT_POS (tpos, newpos, bpos);
+ reseat_1 (it, tpos, 0);
}
- do
+ else /* Must use the slow method. */
{
- bidi_move_to_visually_next (&it->bidi_it);
+ /* With bidi iteration, the region of invisible text
+ could start and/or end in the middle of a
+ non-base embedding level. Therefore, we need to
+ skip invisible text using the bidi iterator,
+ starting at IT's current position, until we find
+ ourselves outside the invisible text. Skipping
+ invisible text _after_ bidi iteration avoids
+ affecting the visual order of the displayed text
+ when invisible properties are added or
+ removed. */
+ if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+ {
+ /* If we were `reseat'ed to a new paragraph,
+ determine the paragraph base direction. We
+ need to do it now because
+ next_element_from_buffer may not have a
+ chance to do it, if we are going to skip any
+ text at the beginning, which resets the
+ FIRST_ELT flag. */
+ bidi_paragraph_init (it->paragraph_embedding,
+ &it->bidi_it, 1);
+ }
+ do
+ {
+ bidi_move_to_visually_next (&it->bidi_it);
+ }
+ while (it->stop_charpos <= it->bidi_it.charpos
+ && it->bidi_it.charpos < newpos);
+ IT_CHARPOS (*it) = it->bidi_it.charpos;
+ IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+ /* If we overstepped NEWPOS, record its position in
+ the iterator, so that we skip invisible text if
+ later the bidi iteration lands us in the
+ invisible region again. */
+ if (IT_CHARPOS (*it) >= newpos)
+ it->prev_stop = newpos;
}
- while (it->stop_charpos <= it->bidi_it.charpos
- && it->bidi_it.charpos < newpos);
- IT_CHARPOS (*it) = it->bidi_it.charpos;
- IT_BYTEPOS (*it) = it->bidi_it.bytepos;
- /* If we overstepped NEWPOS, record its position in the
- iterator, so that we skip invisible text if later the
- bidi iteration lands us in the invisible region
- again. */
- if (IT_CHARPOS (*it) >= newpos)
- it->prev_stop = newpos;
}
else
{
((op & MOVE_TO_POS) != 0 \
&& BUFFERP (it->object) \
&& (IT_CHARPOS (*it) == to_charpos \
- || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos) \
+ || ((!it->bidi_p \
+ || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
+ && IT_CHARPOS (*it) > to_charpos) \
|| (it->what == IT_COMPOSITION \
&& ((IT_CHARPOS (*it) > to_charpos \
&& to_charpos >= it->cmp_it.charpos) \
if ((op & MOVE_TO_POS) != 0
&& BUFFERP (it->object)
&& it->method == GET_FROM_BUFFER
- && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos)
+ && (((!it->bidi_p
+ /* When the iterator is at base embedding level, we
+ are guaranteed that characters are delivered for
+ display in strictly increasing order of their
+ buffer positions. */
+ || BIDI_AT_BASE_LEVEL (it->bidi_it))
+ && IT_CHARPOS (*it) > to_charpos)
|| (it->bidi_p
&& (prev_method == GET_FROM_IMAGE
|| prev_method == GET_FROM_STRETCH