return c;
}
+/* Return the Bidi_Paired_Bracket_Type property of the character C. */
+static bidi_bracket_type_t
+bidi_paired_bracket_type (int c)
+{
+ if (c == BIDI_EOB)
+ return BIDI_BRACKET_NONE;
+ if (c < 0 || c > MAX_CHAR)
+ emacs_abort ();
+
+ return (bidi_bracket_type_t) XINT (CHAR_TABLE_REF (bidi_brackets_table, c));
+}
+
/* Determine the start-of-sequence (sos) directional type given the two
embedding levels on either side of the run boundary. Also, update
the saved info about previously seen characters, since that info is
/* FIXME: should the default sos direction be user selectable? */
bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R); /* X10 */
- bidi_it->prev.type = bidi_it->prev.type_after_wn = UNKNOWN_BT;
- bidi_it->last_strong.type = bidi_it->last_strong.type_after_wn
- = bidi_it->last_strong.orig_type = UNKNOWN_BT;
+ bidi_it->prev.type = UNKNOWN_BT;
+ bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT;
bidi_it->prev_for_neutral.type = (bidi_it->sos == R2L ? STRONG_R : STRONG_L);
bidi_it->prev_for_neutral.charpos = bidi_it->charpos;
- bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_wn
+ bidi_it->next_for_neutral.type
= bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
}
the time we first use it. We initialize it here to
UNKNOWN_BT to be able to catch any blunders in this
logic. */
- bidi_it->prev.orig_type = bidi_it->prev.type_after_wn
- = bidi_it->prev.type = UNKNOWN_BT;
+ bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT;
bidi_it->last_strong = st.last_strong;
bidi_it->prev_for_neutral = st.prev_for_neutral;
bidi_it->next_for_neutral = st.next_for_neutral;
/* Record in SAVED_INFO the information about the current character. */
static void
bidi_remember_char (struct bidi_saved_info *saved_info,
- struct bidi_it *bidi_it)
+ struct bidi_it *bidi_it, bool from_type)
{
saved_info->charpos = bidi_it->charpos;
- saved_info->type = bidi_it->type;
- bidi_check_type (bidi_it->type);
- saved_info->type_after_wn = bidi_it->type_after_wn;
- bidi_check_type (bidi_it->type_after_wn);
+ if (from_type)
+ saved_info->type = bidi_it->type;
+ else
+ saved_info->type = bidi_it->type_after_wn;
+ bidi_check_type (saved_info->type);
saved_info->orig_type = bidi_it->orig_type;
- bidi_check_type (bidi_it->orig_type);
- saved_info->bracket_resolved = bidi_it->bracket_resolved;
+ bidi_check_type (saved_info->orig_type);
}
/* Copy the bidi iterator from FROM to TO. To save cycles, this only
}
static void
-bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
+bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved,
+ bool update_only)
{
ptrdiff_t idx;
emacs_abort ();
idx = bidi_cache_search (bidi_it->charpos, -1, 1);
+ if (idx < 0 && update_only)
+ return;
+
if (idx < 0)
{
idx = bidi_cache_idx;
bidi_it->type_after_wn = NEUTRAL_B;
bidi_it->orig_type = NEUTRAL_B;
/* FIXME: Review this!!! */
- bidi_it->prev.type = bidi_it->prev.type_after_wn
- = bidi_it->prev.orig_type = UNKNOWN_BT;
- bidi_it->last_strong.type = bidi_it->last_strong.type_after_wn
- = bidi_it->last_strong.orig_type = UNKNOWN_BT;
+ bidi_it->prev.type = bidi_it->prev.orig_type = UNKNOWN_BT;
+ bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT;
bidi_it->next_for_neutral.charpos = -1;
bidi_it->next_for_neutral.type
- = bidi_it->next_for_neutral.type_after_wn
= bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
bidi_it->prev_for_neutral.charpos = -1;
bidi_it->prev_for_neutral.type
- = bidi_it->prev_for_neutral.type_after_wn
= bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
bidi_it->sos = L2R; /* FIXME: should it be user-selectable? */
bidi_it->disp_pos = -1; /* invalid/unknown */
we need it for W5. */
bidi_it->next_en_pos = 0;
bidi_it->next_en_type = UNKNOWN_BT;
+ bidi_it->next_for_ws.charpos = -1;
bidi_it->next_for_ws.type = UNKNOWN_BT;
bidi_set_sos_type (bidi_it,
(bidi_it->paragraph_dir == R2L ? 1 : 0),
ptrdiff_t ch_len, nchars, disp_pos, end;
int disp_prop;
+ /* Record the info about the previous character. */
+ if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
+ && bidi_it->type != WEAK_BN)
+ {
+ /* This special case is needed in support of Unicode 8.0
+ correction to N0, as implemented in bidi_resolve_weak/W1
+ below. */
+ if (bidi_it->type_after_wn == NEUTRAL_ON
+ && bidi_it->bracket_resolved
+ && bidi_get_category (bidi_it->type) == STRONG
+ && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE)
+ bidi_remember_char (&bidi_it->prev, bidi_it, 1);
+ else
+ bidi_remember_char (&bidi_it->prev, bidi_it, 0);
+ }
+ if (bidi_it->type_after_wn == STRONG_R
+ || bidi_it->type_after_wn == STRONG_L
+ || bidi_it->type_after_wn == STRONG_AL)
+ bidi_remember_char (&bidi_it->last_strong, bidi_it, 0);
+ if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L
+ || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN)
+ bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it, 1);
+
+ /* If we overstepped the characters used for resolving neutrals
+ and whitespace, invalidate their info in the iterator. */
+ if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos)
+ bidi_it->next_for_neutral.type = UNKNOWN_BT;
+ if (bidi_it->next_en_pos >= 0
+ && bidi_it->charpos >= bidi_it->next_en_pos)
+ {
+ bidi_it->next_en_pos = 0;
+ bidi_it->next_en_type = UNKNOWN_BT;
+ }
+
+ /* Reset the bracket_resolved flag. */
+ bidi_it->bracket_resolved = 0;
+
/* If reseat()'ed, don't advance, so as to start iteration from the
position where we were reseated. bidi_it->bytepos can be less
than BEGV_BYTE after reseat to BEGV. */
else /* EOB or end of string */
prev_type = NEUTRAL_B;
- /* Reset the bracket_resolved flag. */
- bidi_it->bracket_resolved = 0;
-
current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */
override = bidi_it->level_stack[bidi_it->stack_idx].override;
isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
This is why NSM gets the type_after_wn of the previous
character. */
/* bidi_set_sos_type sets type_after_wn to UNKNOWN_BT. */
- if (bidi_it->prev.type_after_wn != UNKNOWN_BT
+ if (bidi_it->prev.type != UNKNOWN_BT
/* If type_after_wn is NEUTRAL_B, this NSM is at sos. */
- && bidi_it->prev.type_after_wn != NEUTRAL_B)
+ && bidi_it->prev.type != NEUTRAL_B)
{
- if (bidi_isolate_fmt_char (bidi_it->prev.type_after_wn))
+ if (bidi_isolate_fmt_char (bidi_it->prev.type))
{
/* From W1: "Note that in an isolating run sequence,
an isolate initiator followed by an NSM or any
}
else
{
- type = bidi_it->prev.type_after_wn;
- /* Unicode 8.0 correction for N0. */
- if (type == NEUTRAL_ON
- && bidi_it->prev.bracket_resolved
- && (bidi_it->prev.type == STRONG_L
- || bidi_it->prev.type == STRONG_R))
- type = bidi_it->prev.type;
+ /* This includes the Unicode 8.0 correction for N0,
+ due to how we set prev.type in bidi_resolve_explicit,
+ which see. */
+ type = bidi_it->prev.type;
}
}
else if (bidi_it->sos == R2L)
emacs_abort ();
}
if (type == WEAK_EN /* W2 */
- && bidi_it->last_strong.type_after_wn == STRONG_AL)
+ && bidi_it->last_strong.type == STRONG_AL)
type = WEAK_AN;
else if (type == STRONG_AL) /* W3 */
type = STRONG_R;
else if ((type == WEAK_ES /* W4 */
- && bidi_it->prev.type_after_wn == WEAK_EN
+ && bidi_it->prev.type == WEAK_EN
&& bidi_it->prev.orig_type == WEAK_EN)
|| (type == WEAK_CS
- && ((bidi_it->prev.type_after_wn == WEAK_EN
+ && ((bidi_it->prev.type == WEAK_EN
&& bidi_it->prev.orig_type == WEAK_EN)
- || bidi_it->prev.type_after_wn == WEAK_AN)))
+ || bidi_it->prev.type == WEAK_AN)))
{
const unsigned char *s
= (STRINGP (bidi_it->string.lstring)
should not be changed into EN. */
if (type == WEAK_ES
&& type_of_next == WEAK_EN
- && bidi_it->last_strong.type_after_wn != STRONG_AL)
+ && bidi_it->last_strong.type != STRONG_AL)
type = WEAK_EN;
else if (type == WEAK_CS)
{
- if (bidi_it->prev.type_after_wn == WEAK_AN
+ if (bidi_it->prev.type == WEAK_AN
&& (type_of_next == WEAK_AN
/* If the next character is EN, but the last
strong-type character is AL, EN will be later
So in that case, this ES should not be
changed into EN. */
|| (type_of_next == WEAK_EN
- && bidi_it->last_strong.type_after_wn == STRONG_AL)))
+ && bidi_it->last_strong.type == STRONG_AL)))
type = WEAK_AN;
- else if (bidi_it->prev.type_after_wn == WEAK_EN
+ else if (bidi_it->prev.type == WEAK_EN
&& type_of_next == WEAK_EN
- && bidi_it->last_strong.type_after_wn != STRONG_AL)
+ && bidi_it->last_strong.type != STRONG_AL)
type = WEAK_EN;
}
}
else if (type == WEAK_ET /* W5: ET with EN before or after it */
|| type == WEAK_BN) /* W5/Retaining */
{
- if (bidi_it->prev.type_after_wn == WEAK_EN) /* ET/BN w/EN before it */
+ if (bidi_it->prev.type == WEAK_EN) /* ET/BN w/EN before it */
type = WEAK_EN;
else if (bidi_it->next_en_pos > bidi_it->charpos
&& bidi_it->next_en_type != WEAK_BN)
{
/* If the last strong character is AL, the EN we've
found will become AN when we get to it (W2). */
- if (bidi_it->last_strong.type_after_wn == STRONG_AL)
+ if (bidi_it->last_strong.type == STRONG_AL)
type_of_next = WEAK_AN;
else if (type == WEAK_BN)
type = NEUTRAL_ON; /* W6/Retaining */
if (type == WEAK_ES || type == WEAK_ET || type == WEAK_CS /* W6 */
|| (type == WEAK_BN
- && (bidi_it->prev.type_after_wn == WEAK_CS /* W6/Retaining */
- || bidi_it->prev.type_after_wn == WEAK_ES
- || bidi_it->prev.type_after_wn == WEAK_ET)))
+ && (bidi_it->prev.type == WEAK_CS /* W6/Retaining */
+ || bidi_it->prev.type == WEAK_ES
+ || bidi_it->prev.type == WEAK_ET)))
type = NEUTRAL_ON;
/* Store the type we've got so far, before we clobber it with strong
if (type == WEAK_EN) /* W7 */
{
- if ((bidi_it->last_strong.type_after_wn == STRONG_L)
+ if ((bidi_it->last_strong.type == STRONG_L)
|| (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sos == L2R))
type = STRONG_L;
}
return STRONG_R;
}
-static bidi_bracket_type_t
-bidi_paired_bracket_type (int c)
-{
- if (c == BIDI_EOB)
- return BIDI_BRACKET_NONE;
- if (c < 0 || c > MAX_CHAR)
- emacs_abort ();
-
- return (bidi_bracket_type_t) XINT (CHAR_TABLE_REF (bidi_brackets_table, c));
-}
-
#define FLAG_EMBEDDING_INSIDE 1
#define FLAG_OPPOSITE_INSIDE 2
#define FLAG_EMBEDDING_OUTSIDE 4
int old_sidx, new_sidx;
int current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
- bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B);
+ bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
if (btype == BIDI_BRACKET_OPEN)
PUSH_BPA_STACK (embedding_level, last_strong);
else if (btype == BIDI_BRACKET_CLOSE)
/* Update and cache the closing bracket. */
bidi_it->type = type;
bidi_it->bracket_resolved = 1;
- bidi_cache_iterator_state (bidi_it, 0);
+ bidi_cache_iterator_state (bidi_it, 0, 0);
/* Update and cache the corresponding opening bracket. */
bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx,
bidi_it);
eassert (bpa_stack[sp].open_bracket_pos == bidi_it->charpos);
#endif
bidi_it->type = type;
- bidi_it->bracket_resolved = 1;
- bidi_cache_iterator_state (bidi_it, 0);
bpa_sp = sp - 1;
- if (bpa_sp < 0)
- break;
}
- else
- bidi_it->bracket_resolved = 1;
+ bidi_it->bracket_resolved = 1;
+ bidi_cache_iterator_state (bidi_it, 0, 0);
+ if (bpa_sp < 0)
+ break;
}
else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL)
{
next_for_neutral, and when found, update cached
states for which it is relevant. */
}
- /* Record the info about the previous character, so that it
- will be cached with this state. */
- if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
- && bidi_it->type != WEAK_BN)
- bidi_remember_char (&bidi_it->prev, bidi_it);
old_sidx = bidi_it->stack_idx;
type = bidi_resolve_weak (bidi_it);
/* Skip level runs excluded from this isolating run sequence. */
while (bidi_it->level_stack[bidi_it->stack_idx].level
> current_level)
{
- bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B);
+ bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
type = bidi_resolve_weak (bidi_it);
}
}
== bidi_it->charpos);
#endif
bidi_it->bracket_resolved = 1;
- bidi_cache_iterator_state (bidi_it, 0);
+ bidi_cache_iterator_state (bidi_it, 0, 0);
bpa_sp--;
}
type = saved_it.type;
return type;
}
+static bidi_type_t
+bidi_resolve_brackets (struct bidi_it *bidi_it)
+{
+ bidi_type_t type = bidi_resolve_weak (bidi_it);
+ int ch = bidi_it->ch;
+
+ if (type == NEUTRAL_ON
+ && bidi_paired_bracket_type (ch) != BIDI_BRACKET_NONE)
+ {
+ if (bidi_cache_idx > bidi_cache_start
+ && bidi_cache_find (bidi_it->charpos, 1, bidi_it) != UNKNOWN_BT
+ && bidi_it->bracket_resolved)
+ type = bidi_it->type;
+ else
+ type = bidi_resolve_bracket_pairs (bidi_it);
+ }
+
+ return type;
+}
+
static bidi_type_t
bidi_resolve_neutral (struct bidi_it *bidi_it)
{
+ bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring);
int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
- bidi_type_t type = bidi_resolve_weak (bidi_it);
- int current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
+ bidi_type_t type = UNKNOWN_BT;
+ int current_level;
bool is_neutral;
- int ch = bidi_it->ch;
+
+ if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
+ {
+ if (bidi_it->nchars <= 0)
+ emacs_abort ();
+ type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 1, bidi_it);
+ }
+ if (type == UNKNOWN_BT)
+ type = bidi_resolve_brackets (bidi_it);
eassert (type == STRONG_R
|| type == STRONG_L
|| type == PDI);
eassert (prev_level >= 0);
+ current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
eassert (current_level >= 0);
-
- /* FIXME: Insert the code for N0 here. */
- if (type == NEUTRAL_ON
- && bidi_paired_bracket_type (ch) != BIDI_BRACKET_NONE)
- {
- if (bidi_cache_idx > bidi_cache_start
- && bidi_cache_find (bidi_it->charpos, 1, bidi_it) != UNKNOWN_BT
- && bidi_it->bracket_resolved)
- type = bidi_it->type;
- else
- type = bidi_resolve_bracket_pairs (bidi_it);
- }
-
is_neutral = bidi_get_category (type) == NEUTRAL;
if ((type != NEUTRAL_B /* Don't risk entering the long loop below if
bidi_type_t next_type;
bool adjacent_to_neutrals = is_neutral;
- if (bidi_it->scan_dir == -1)
- emacs_abort ();
-
bidi_copy_it (&saved_it, bidi_it);
/* Scan the text forward until we find the first non-neutral
character, and then use that to resolve the neutral we
/* Paragraph separators have their levels fully resolved
at this point, so cache them as resolved. */
- bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B);
- /* Record the info about the previous character, so that
- it will be cached with this state. */
- if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
- && bidi_it->type != WEAK_BN)
- bidi_remember_char (&bidi_it->prev, bidi_it);
+ bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
old_sidx = bidi_it->stack_idx;
- type = bidi_resolve_weak (bidi_it);
+ type = bidi_resolve_brackets (bidi_it);
/* Skip level runs excluded from this isolating run sequence. */
new_sidx = bidi_it->stack_idx;
if (bidi_it->level_stack[new_sidx].level > current_level
while (bidi_it->level_stack[bidi_it->stack_idx].level
> current_level)
{
- bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B);
- type = bidi_resolve_weak (bidi_it);
+ bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
+ type = bidi_resolve_brackets (bidi_it);
}
}
if (!adjacent_to_neutrals
!= current_level)));
/* Record the character we stopped at. */
- bidi_remember_char (&saved_it.next_for_neutral, bidi_it);
+ bidi_remember_char (&saved_it.next_for_neutral, bidi_it, 1);
if ((bidi_it->level_stack[bidi_it->stack_idx].level != current_level)
|| type == NEUTRAL_B)
static int
bidi_level_of_next_char (struct bidi_it *bidi_it)
{
- bidi_type_t type;
- int level, prev_level = -1;
- struct bidi_saved_info next_for_neutral;
+ bidi_type_t type = UNKNOWN_BT;
+ int level;
ptrdiff_t next_char_pos = -2;
- bool need_to_update_cache = false;
if (bidi_it->scan_dir == 1)
{
= ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
? bidi_it->string.schars : ZV);
- /* There's no sense in trying to advance if we hit end of text. */
+ /* There's no sense in trying to advance if we've already hit
+ the end of text. */
if (bidi_it->charpos >= eob)
{
eassert (bidi_it->resolved_level >= 0);
return bidi_it->resolved_level;
}
-
- /* Record the info about the previous character. */
- if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
- && bidi_it->type != WEAK_BN)
- bidi_remember_char (&bidi_it->prev, bidi_it);
- if (bidi_it->type_after_wn == STRONG_R
- || bidi_it->type_after_wn == STRONG_L
- || bidi_it->type_after_wn == STRONG_AL)
- bidi_remember_char (&bidi_it->last_strong, bidi_it);
- /* FIXME: it sounds like we don't need both prev and
- prev_for_neutral members, but I'm leaving them both for now. */
- if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L
- || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN)
- bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it);
-
- /* If we overstepped the characters used for resolving neutrals
- and whitespace, invalidate their info in the iterator. */
- if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos)
- bidi_it->next_for_neutral.type = UNKNOWN_BT;
- if (bidi_it->next_en_pos >= 0
- && bidi_it->charpos >= bidi_it->next_en_pos)
- {
- bidi_it->next_en_pos = 0;
- bidi_it->next_en_type = UNKNOWN_BT;
- }
- if (bidi_it->next_for_ws.type != UNKNOWN_BT
- && bidi_it->charpos >= bidi_it->next_for_ws.charpos)
- bidi_it->next_for_ws.type = UNKNOWN_BT;
-
- /* This must be taken before we fill the iterator with the info
- about the next char. If we scan backwards, the iterator
- state must be already cached, so there's no need to know the
- embedding level of the previous character, since we will be
- returning to our caller shortly. */
- prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
- eassert (prev_level >= 0);
}
- next_for_neutral = bidi_it->next_for_neutral;
/* Perhaps the character we want is already cached. If it is, the
call to bidi_cache_find below will return a type other than
next_char_pos = bidi_it->charpos - 1;
if (next_char_pos >= bob - 1)
type = bidi_cache_find (next_char_pos, 0, bidi_it);
- else
- type = UNKNOWN_BT;
/* For a sequence of BN and NI, copy the type from the previous
character. This is because the loop in bidi_resolve_neutral
type = prev_type;
eassert (type != UNKNOWN_BT);
}
- }
- else
- type = UNKNOWN_BT;
- if (type != UNKNOWN_BT)
- {
- /* Don't lose the information for resolving neutrals! The
- cached states could have been cached before their
- next_for_neutral member was computed. If we are on our way
- forward, we can simply take the info from the previous
- state. */
- if (bidi_it->scan_dir == 1
- && bidi_it->next_for_neutral.type == UNKNOWN_BT)
- bidi_it->next_for_neutral = next_for_neutral;
-
- /* If resolved_level is -1, it means this state was cached
- before it was completely resolved, so we cannot return
- it. */
- if (bidi_it->resolved_level != -1)
- {
- eassert (bidi_it->resolved_level >= 0);
- return bidi_it->resolved_level;
- }
- else
+ if (type != UNKNOWN_BT)
{
- /* Take note when we've got a cached state that is not fully
- resolved, so that we could make sure we update the cache
- below, when we do resolve it. */
- need_to_update_cache = true;
+ /* If resolved_level is -1, it means this state was cached
+ before it was completely resolved, so we cannot return
+ it. */
+ if (bidi_it->resolved_level != -1)
+ {
+ eassert (bidi_it->resolved_level >= 0);
+ return bidi_it->resolved_level;
+ }
+ else if (next_char_pos >= bob - 1)
+ {
+ level = bidi_it->level_stack[bidi_it->stack_idx].level;
+ if (bidi_get_category (type) == NEUTRAL
+ || bidi_isolate_fmt_char (type))
+ {
+ /* Make sure the data for resolving neutrals we are
+ about to use is valid. */
+ if (bidi_it->next_for_neutral.charpos < bidi_it->charpos
+ /* PDI defines an eos, so it's OK for it to
+ serve as its own next_for_neutral. */
+ || (bidi_it->next_for_neutral.charpos == bidi_it->charpos
+ && bidi_it->type != PDI)
+ || bidi_it->next_for_neutral.type == UNKNOWN_BT)
+ emacs_abort ();
+
+ type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
+ bidi_it->next_for_neutral.type,
+ level);
+ }
+ }
}
}
+
if (bidi_it->scan_dir == -1)
/* If we are going backwards, the iterator state is already cached
from previous scans, and should be fully resolved. */
}
level = bidi_it->level_stack[bidi_it->stack_idx].level;
- if (bidi_get_category (type) == NEUTRAL /* && type != NEUTRAL_B */
- || bidi_isolate_fmt_char (type))
- {
- /* Make sure the data for resolving neutrals we are about to use
- is valid. */
- if (bidi_it->next_for_neutral.charpos <= bidi_it->charpos
- || bidi_it->next_for_neutral.type == UNKNOWN_BT)
- emacs_abort ();
-
- /* If the cached state shows a neutral character, it was not
- resolved by bidi_resolve_neutral, so do it now. */
- type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
- bidi_it->next_for_neutral.type,
- level);
- }
eassert ((type == STRONG_R
|| type == STRONG_L
or a TAB or a paragraph separator. */
if ((bidi_it->orig_type == NEUTRAL_WS
|| bidi_isolate_fmt_char (bidi_it->orig_type))
- && bidi_it->next_for_ws.type == UNKNOWN_BT)
+ && bidi_it->next_for_ws.charpos < bidi_it->charpos)
{
int ch;
ptrdiff_t clen = bidi_it->ch_len;
bidi_it->next_for_ws.charpos = cpos;
}
+ /* Update the cache, but only if this state was already cached. */
+ bidi_cache_iterator_state (bidi_it, 1, 1);
+
/* Resolve implicit levels. */
if (bidi_it->orig_type == NEUTRAL_B /* L1 */
|| bidi_it->orig_type == NEUTRAL_S
}
bidi_it->resolved_level = level;
- if (need_to_update_cache)
- bidi_cache_iterator_state (bidi_it, 1);
return level;
}
if (end_flag)
emacs_abort ();
- bidi_cache_iterator_state (bidi_it, 1);
+ bidi_cache_iterator_state (bidi_it, 1, 0);
do {
new_level = bidi_level_of_next_char (bidi_it);
- bidi_cache_iterator_state (bidi_it, 1);
+ bidi_cache_iterator_state (bidi_it, 1, 0);
} while (new_level >= level);
}
}
sentinel.ch_len = 1;
sentinel.nchars = 1;
}
- bidi_cache_iterator_state (&sentinel, 1);
+ bidi_cache_iterator_state (&sentinel, 1, 0);
}
old_level = bidi_it->resolved_level;
compromised: it assumes cached states correspond to buffer
positions 1:1. */
else
- bidi_cache_iterator_state (bidi_it, 1);
+ bidi_cache_iterator_state (bidi_it, 1, 0);
}
if (STRINGP (bidi_it->string.lstring))