if (bidi_it->next_en_type == WEAK_EN) /* ET/BN with EN after it */
type = WEAK_EN;
}
- else if (bidi_it->next_en_pos >=0)
+ else if (type == WEAK_BN
+ /* This condition is for the following important case:
+
+ . we are at level zero
+ . either previous strong character was L,
+ or we've seen no strong characters since sos
+ and the base paragraph direction is L2R
+ . this BN is NOT a bidi directional control
+
+ For such a situation, either this BN will be
+ converted to EN per W5, and then to L by virtue
+ of W7; or it will become ON per W6, and then L
+ because of N1/N2. So we take a shortcut here
+ and make it L right away, to avoid the
+ potentially costly loop below. This is
+ important when the buffer has a long series of
+ control characters, like binary nulls, and no
+ R2L characters at all. */
+ && new_level == 0
+ && !bidi_explicit_dir_char (bidi_it->ch)
+ && ((bidi_it->last_strong.type == STRONG_L)
+ || (bidi_it->last_strong.type == UNKNOWN_BT
+ && bidi_it->sos == L2R)))
+ type = STRONG_L;
+ else if (bidi_it->next_en_pos >= 0)
{
/* We overstepped the last known position for ET
resolution but there could be other such characters
entering the expensive loop in the "else" clause. */
else if (current_level == 0
&& bidi_it->prev_for_neutral.type == STRONG_L
- && type != WEAK_BN
- && !bidi_explicit_dir_char (bidi_it->ch)
- && !bidi_isolate_fmt_char (type))
+ && (ASCII_CHAR_P (bidi_it->ch)
+ || (type != WEAK_BN
+ && !bidi_explicit_dir_char (bidi_it->ch)
+ && !bidi_isolate_fmt_char (type))))
type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
STRONG_L, current_level);
else if (/* current level is 1 */
}
}
- /* Perhaps the character we want is already cached s fully resolved.
+ /* Perhaps the character we want is already cached as fully resolved.
If it is, the call to bidi_cache_find below will return a type
other than UNKNOWN_BT. */
if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
if ((bidi_it->orig_type == NEUTRAL_WS
|| bidi_it->orig_type == WEAK_BN
|| bidi_isolate_fmt_char (bidi_it->orig_type))
- && bidi_it->next_for_ws.charpos < bidi_it->charpos)
+ && bidi_it->next_for_ws.charpos < bidi_it->charpos
+ /* If this character is already at base level, we don't need to
+ reset it, so avoid the potentially costly loop below. */
+ && level != bidi_it->level_stack[0].level)
{
int ch;
ptrdiff_t clen = bidi_it->ch_len;