Refactored saving prev info, resolve_neutrals, and high-level cache access.

This commit is contained in:
Eli Zaretskii 2014-10-12 19:23:43 +03:00
parent 4d5fab649d
commit 942ba67827
2 changed files with 179 additions and 198 deletions

View file

@ -394,6 +394,18 @@ bidi_mirror_char (int c)
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
@ -406,12 +418,11 @@ bidi_set_sos_type (struct bidi_it *bidi_it, int level_before, int level_after)
/* 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;
}
@ -471,8 +482,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
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;
@ -492,16 +502,16 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
/* 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
@ -721,7 +731,8 @@ bidi_cache_ensure_space (ptrdiff_t idx)
}
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;
@ -730,6 +741,9 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
emacs_abort ();
idx = bidi_cache_search (bidi_it->charpos, -1, 1);
if (idx < 0 && update_only)
return;
if (idx < 0)
{
idx = bidi_cache_idx;
@ -1045,17 +1059,13 @@ bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p,
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 */
@ -1084,6 +1094,7 @@ bidi_line_init (struct bidi_it *bidi_it)
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),
@ -1713,6 +1724,43 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
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. */
@ -1774,9 +1822,6 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
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;
@ -2055,11 +2100,11 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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
@ -2070,13 +2115,10 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
}
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)
@ -2087,17 +2129,17 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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)
@ -2126,11 +2168,11 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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
@ -2138,18 +2180,18 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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)
@ -2210,7 +2252,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
{
/* 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 */
@ -2230,9 +2272,9 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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
@ -2245,7 +2287,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
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;
}
@ -2275,17 +2317,6 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
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
@ -2363,7 +2394,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
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)
@ -2389,7 +2420,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
/* 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);
@ -2397,14 +2428,12 @@ bidi_resolve_bracket_pairs (struct bidi_it *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)
{
@ -2437,11 +2466,6 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
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. */
@ -2454,7 +2478,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
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);
}
}
@ -2477,7 +2501,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *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;
@ -2498,14 +2522,43 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
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
@ -2521,20 +2574,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
|| 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
@ -2593,9 +2634,6 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
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
@ -2606,14 +2644,9 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
/* 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
@ -2629,8 +2662,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
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
@ -2647,7 +2680,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
!= 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)
@ -2731,11 +2764,9 @@ bidi_type_of_next_char (struct bidi_it *bidi_it)
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)
{
@ -2743,50 +2774,14 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
= ((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
@ -2813,8 +2808,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
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
@ -2834,36 +2827,40 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
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 (type != UNKNOWN_BT)
{
/* 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 ();
/* 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
{
/* 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;
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. */
@ -2879,21 +2876,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
}
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
@ -2908,7 +2890,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
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;
@ -2935,6 +2917,9 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
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
@ -2957,8 +2942,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
}
bidi_it->resolved_level = level;
if (need_to_update_cache)
bidi_cache_iterator_state (bidi_it, 1);
return level;
}
@ -3000,10 +2983,10 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
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);
}
}
@ -3047,7 +3030,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
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;
@ -3162,7 +3145,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
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))

View file

@ -1915,9 +1915,7 @@ typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t;
struct bidi_saved_info {
ptrdiff_t charpos; /* character's buffer position */
bidi_type_t type; /* character's resolved bidi type */
bidi_type_t type_after_wn; /* bidi type of the character, after Wn */
bidi_type_t orig_type; /* bidi type as we found it in the buffer */
bool_bf bracket_resolved : 1; /* 1 if type was BPA-resolved */
};
/* Data type for keeping track of information about saved embedding