aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-10-12 19:23:43 +0300
committerEli Zaretskii2014-10-12 19:23:43 +0300
commit942ba67827412eee5ddc4d1a8827ff76c2bbe730 (patch)
treeb4e45d09173054edefd1ac7746904f9158263fdb /src
parent4d5fab649d6673d1d270a6b7b35ae41cfced374e (diff)
downloademacs-942ba67827412eee5ddc4d1a8827ff76c2bbe730.tar.gz
emacs-942ba67827412eee5ddc4d1a8827ff76c2bbe730.zip
Refactored saving prev info, resolve_neutrals, and high-level cache access.
Diffstat (limited to 'src')
-rw-r--r--src/bidi.c375
-rw-r--r--src/dispextern.h2
2 files changed, 179 insertions, 198 deletions
diff --git a/src/bidi.c b/src/bidi.c
index d14d6f6186a..2e980e92b27 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -394,6 +394,18 @@ bidi_mirror_char (int c)
394 return c; 394 return c;
395} 395}
396 396
397/* Return the Bidi_Paired_Bracket_Type property of the character C. */
398static bidi_bracket_type_t
399bidi_paired_bracket_type (int c)
400{
401 if (c == BIDI_EOB)
402 return BIDI_BRACKET_NONE;
403 if (c < 0 || c > MAX_CHAR)
404 emacs_abort ();
405
406 return (bidi_bracket_type_t) XINT (CHAR_TABLE_REF (bidi_brackets_table, c));
407}
408
397/* Determine the start-of-sequence (sos) directional type given the two 409/* Determine the start-of-sequence (sos) directional type given the two
398 embedding levels on either side of the run boundary. Also, update 410 embedding levels on either side of the run boundary. Also, update
399 the saved info about previously seen characters, since that info is 411 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)
406 /* FIXME: should the default sos direction be user selectable? */ 418 /* FIXME: should the default sos direction be user selectable? */
407 bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R); /* X10 */ 419 bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R); /* X10 */
408 420
409 bidi_it->prev.type = bidi_it->prev.type_after_wn = UNKNOWN_BT; 421 bidi_it->prev.type = UNKNOWN_BT;
410 bidi_it->last_strong.type = bidi_it->last_strong.type_after_wn 422 bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT;
411 = bidi_it->last_strong.orig_type = UNKNOWN_BT;
412 bidi_it->prev_for_neutral.type = (bidi_it->sos == R2L ? STRONG_R : STRONG_L); 423 bidi_it->prev_for_neutral.type = (bidi_it->sos == R2L ? STRONG_R : STRONG_L);
413 bidi_it->prev_for_neutral.charpos = bidi_it->charpos; 424 bidi_it->prev_for_neutral.charpos = bidi_it->charpos;
414 bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_wn 425 bidi_it->next_for_neutral.type
415 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; 426 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
416} 427}
417 428
@@ -471,8 +482,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
471 the time we first use it. We initialize it here to 482 the time we first use it. We initialize it here to
472 UNKNOWN_BT to be able to catch any blunders in this 483 UNKNOWN_BT to be able to catch any blunders in this
473 logic. */ 484 logic. */
474 bidi_it->prev.orig_type = bidi_it->prev.type_after_wn 485 bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT;
475 = bidi_it->prev.type = UNKNOWN_BT;
476 bidi_it->last_strong = st.last_strong; 486 bidi_it->last_strong = st.last_strong;
477 bidi_it->prev_for_neutral = st.prev_for_neutral; 487 bidi_it->prev_for_neutral = st.prev_for_neutral;
478 bidi_it->next_for_neutral = st.next_for_neutral; 488 bidi_it->next_for_neutral = st.next_for_neutral;
@@ -492,16 +502,16 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
492/* Record in SAVED_INFO the information about the current character. */ 502/* Record in SAVED_INFO the information about the current character. */
493static void 503static void
494bidi_remember_char (struct bidi_saved_info *saved_info, 504bidi_remember_char (struct bidi_saved_info *saved_info,
495 struct bidi_it *bidi_it) 505 struct bidi_it *bidi_it, bool from_type)
496{ 506{
497 saved_info->charpos = bidi_it->charpos; 507 saved_info->charpos = bidi_it->charpos;
498 saved_info->type = bidi_it->type; 508 if (from_type)
499 bidi_check_type (bidi_it->type); 509 saved_info->type = bidi_it->type;
500 saved_info->type_after_wn = bidi_it->type_after_wn; 510 else
501 bidi_check_type (bidi_it->type_after_wn); 511 saved_info->type = bidi_it->type_after_wn;
512 bidi_check_type (saved_info->type);
502 saved_info->orig_type = bidi_it->orig_type; 513 saved_info->orig_type = bidi_it->orig_type;
503 bidi_check_type (bidi_it->orig_type); 514 bidi_check_type (saved_info->orig_type);
504 saved_info->bracket_resolved = bidi_it->bracket_resolved;
505} 515}
506 516
507/* Copy the bidi iterator from FROM to TO. To save cycles, this only 517/* Copy the bidi iterator from FROM to TO. To save cycles, this only
@@ -721,7 +731,8 @@ bidi_cache_ensure_space (ptrdiff_t idx)
721} 731}
722 732
723static void 733static void
724bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved) 734bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved,
735 bool update_only)
725{ 736{
726 ptrdiff_t idx; 737 ptrdiff_t idx;
727 738
@@ -730,6 +741,9 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
730 emacs_abort (); 741 emacs_abort ();
731 idx = bidi_cache_search (bidi_it->charpos, -1, 1); 742 idx = bidi_cache_search (bidi_it->charpos, -1, 1);
732 743
744 if (idx < 0 && update_only)
745 return;
746
733 if (idx < 0) 747 if (idx < 0)
734 { 748 {
735 idx = bidi_cache_idx; 749 idx = bidi_cache_idx;
@@ -1045,17 +1059,13 @@ bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p,
1045 bidi_it->type_after_wn = NEUTRAL_B; 1059 bidi_it->type_after_wn = NEUTRAL_B;
1046 bidi_it->orig_type = NEUTRAL_B; 1060 bidi_it->orig_type = NEUTRAL_B;
1047 /* FIXME: Review this!!! */ 1061 /* FIXME: Review this!!! */
1048 bidi_it->prev.type = bidi_it->prev.type_after_wn 1062 bidi_it->prev.type = bidi_it->prev.orig_type = UNKNOWN_BT;
1049 = bidi_it->prev.orig_type = UNKNOWN_BT; 1063 bidi_it->last_strong.type = bidi_it->last_strong.orig_type = UNKNOWN_BT;
1050 bidi_it->last_strong.type = bidi_it->last_strong.type_after_wn
1051 = bidi_it->last_strong.orig_type = UNKNOWN_BT;
1052 bidi_it->next_for_neutral.charpos = -1; 1064 bidi_it->next_for_neutral.charpos = -1;
1053 bidi_it->next_for_neutral.type 1065 bidi_it->next_for_neutral.type
1054 = bidi_it->next_for_neutral.type_after_wn
1055 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; 1066 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
1056 bidi_it->prev_for_neutral.charpos = -1; 1067 bidi_it->prev_for_neutral.charpos = -1;
1057 bidi_it->prev_for_neutral.type 1068 bidi_it->prev_for_neutral.type
1058 = bidi_it->prev_for_neutral.type_after_wn
1059 = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; 1069 = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
1060 bidi_it->sos = L2R; /* FIXME: should it be user-selectable? */ 1070 bidi_it->sos = L2R; /* FIXME: should it be user-selectable? */
1061 bidi_it->disp_pos = -1; /* invalid/unknown */ 1071 bidi_it->disp_pos = -1; /* invalid/unknown */
@@ -1084,6 +1094,7 @@ bidi_line_init (struct bidi_it *bidi_it)
1084 we need it for W5. */ 1094 we need it for W5. */
1085 bidi_it->next_en_pos = 0; 1095 bidi_it->next_en_pos = 0;
1086 bidi_it->next_en_type = UNKNOWN_BT; 1096 bidi_it->next_en_type = UNKNOWN_BT;
1097 bidi_it->next_for_ws.charpos = -1;
1087 bidi_it->next_for_ws.type = UNKNOWN_BT; 1098 bidi_it->next_for_ws.type = UNKNOWN_BT;
1088 bidi_set_sos_type (bidi_it, 1099 bidi_set_sos_type (bidi_it,
1089 (bidi_it->paragraph_dir == R2L ? 1 : 0), 1100 (bidi_it->paragraph_dir == R2L ? 1 : 0),
@@ -1713,6 +1724,43 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1713 ptrdiff_t ch_len, nchars, disp_pos, end; 1724 ptrdiff_t ch_len, nchars, disp_pos, end;
1714 int disp_prop; 1725 int disp_prop;
1715 1726
1727 /* Record the info about the previous character. */
1728 if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
1729 && bidi_it->type != WEAK_BN)
1730 {
1731 /* This special case is needed in support of Unicode 8.0
1732 correction to N0, as implemented in bidi_resolve_weak/W1
1733 below. */
1734 if (bidi_it->type_after_wn == NEUTRAL_ON
1735 && bidi_it->bracket_resolved
1736 && bidi_get_category (bidi_it->type) == STRONG
1737 && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE)
1738 bidi_remember_char (&bidi_it->prev, bidi_it, 1);
1739 else
1740 bidi_remember_char (&bidi_it->prev, bidi_it, 0);
1741 }
1742 if (bidi_it->type_after_wn == STRONG_R
1743 || bidi_it->type_after_wn == STRONG_L
1744 || bidi_it->type_after_wn == STRONG_AL)
1745 bidi_remember_char (&bidi_it->last_strong, bidi_it, 0);
1746 if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L
1747 || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN)
1748 bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it, 1);
1749
1750 /* If we overstepped the characters used for resolving neutrals
1751 and whitespace, invalidate their info in the iterator. */
1752 if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos)
1753 bidi_it->next_for_neutral.type = UNKNOWN_BT;
1754 if (bidi_it->next_en_pos >= 0
1755 && bidi_it->charpos >= bidi_it->next_en_pos)
1756 {
1757 bidi_it->next_en_pos = 0;
1758 bidi_it->next_en_type = UNKNOWN_BT;
1759 }
1760
1761 /* Reset the bracket_resolved flag. */
1762 bidi_it->bracket_resolved = 0;
1763
1716 /* If reseat()'ed, don't advance, so as to start iteration from the 1764 /* If reseat()'ed, don't advance, so as to start iteration from the
1717 position where we were reseated. bidi_it->bytepos can be less 1765 position where we were reseated. bidi_it->bytepos can be less
1718 than BEGV_BYTE after reseat to BEGV. */ 1766 than BEGV_BYTE after reseat to BEGV. */
@@ -1774,9 +1822,6 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1774 else /* EOB or end of string */ 1822 else /* EOB or end of string */
1775 prev_type = NEUTRAL_B; 1823 prev_type = NEUTRAL_B;
1776 1824
1777 /* Reset the bracket_resolved flag. */
1778 bidi_it->bracket_resolved = 0;
1779
1780 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */ 1825 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */
1781 override = bidi_it->level_stack[bidi_it->stack_idx].override; 1826 override = bidi_it->level_stack[bidi_it->stack_idx].override;
1782 isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status; 1827 isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
@@ -2055,11 +2100,11 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2055 This is why NSM gets the type_after_wn of the previous 2100 This is why NSM gets the type_after_wn of the previous
2056 character. */ 2101 character. */
2057 /* bidi_set_sos_type sets type_after_wn to UNKNOWN_BT. */ 2102 /* bidi_set_sos_type sets type_after_wn to UNKNOWN_BT. */
2058 if (bidi_it->prev.type_after_wn != UNKNOWN_BT 2103 if (bidi_it->prev.type != UNKNOWN_BT
2059 /* If type_after_wn is NEUTRAL_B, this NSM is at sos. */ 2104 /* If type_after_wn is NEUTRAL_B, this NSM is at sos. */
2060 && bidi_it->prev.type_after_wn != NEUTRAL_B) 2105 && bidi_it->prev.type != NEUTRAL_B)
2061 { 2106 {
2062 if (bidi_isolate_fmt_char (bidi_it->prev.type_after_wn)) 2107 if (bidi_isolate_fmt_char (bidi_it->prev.type))
2063 { 2108 {
2064 /* From W1: "Note that in an isolating run sequence, 2109 /* From W1: "Note that in an isolating run sequence,
2065 an isolate initiator followed by an NSM or any 2110 an isolate initiator followed by an NSM or any
@@ -2070,13 +2115,10 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2070 } 2115 }
2071 else 2116 else
2072 { 2117 {
2073 type = bidi_it->prev.type_after_wn; 2118 /* This includes the Unicode 8.0 correction for N0,
2074 /* Unicode 8.0 correction for N0. */ 2119 due to how we set prev.type in bidi_resolve_explicit,
2075 if (type == NEUTRAL_ON 2120 which see. */
2076 && bidi_it->prev.bracket_resolved 2121 type = bidi_it->prev.type;
2077 && (bidi_it->prev.type == STRONG_L
2078 || bidi_it->prev.type == STRONG_R))
2079 type = bidi_it->prev.type;
2080 } 2122 }
2081 } 2123 }
2082 else if (bidi_it->sos == R2L) 2124 else if (bidi_it->sos == R2L)
@@ -2087,17 +2129,17 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2087 emacs_abort (); 2129 emacs_abort ();
2088 } 2130 }
2089 if (type == WEAK_EN /* W2 */ 2131 if (type == WEAK_EN /* W2 */
2090 && bidi_it->last_strong.type_after_wn == STRONG_AL) 2132 && bidi_it->last_strong.type == STRONG_AL)
2091 type = WEAK_AN; 2133 type = WEAK_AN;
2092 else if (type == STRONG_AL) /* W3 */ 2134 else if (type == STRONG_AL) /* W3 */
2093 type = STRONG_R; 2135 type = STRONG_R;
2094 else if ((type == WEAK_ES /* W4 */ 2136 else if ((type == WEAK_ES /* W4 */
2095 && bidi_it->prev.type_after_wn == WEAK_EN 2137 && bidi_it->prev.type == WEAK_EN
2096 && bidi_it->prev.orig_type == WEAK_EN) 2138 && bidi_it->prev.orig_type == WEAK_EN)
2097 || (type == WEAK_CS 2139 || (type == WEAK_CS
2098 && ((bidi_it->prev.type_after_wn == WEAK_EN 2140 && ((bidi_it->prev.type == WEAK_EN
2099 && bidi_it->prev.orig_type == WEAK_EN) 2141 && bidi_it->prev.orig_type == WEAK_EN)
2100 || bidi_it->prev.type_after_wn == WEAK_AN))) 2142 || bidi_it->prev.type == WEAK_AN)))
2101 { 2143 {
2102 const unsigned char *s 2144 const unsigned char *s
2103 = (STRINGP (bidi_it->string.lstring) 2145 = (STRINGP (bidi_it->string.lstring)
@@ -2126,11 +2168,11 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2126 should not be changed into EN. */ 2168 should not be changed into EN. */
2127 if (type == WEAK_ES 2169 if (type == WEAK_ES
2128 && type_of_next == WEAK_EN 2170 && type_of_next == WEAK_EN
2129 && bidi_it->last_strong.type_after_wn != STRONG_AL) 2171 && bidi_it->last_strong.type != STRONG_AL)
2130 type = WEAK_EN; 2172 type = WEAK_EN;
2131 else if (type == WEAK_CS) 2173 else if (type == WEAK_CS)
2132 { 2174 {
2133 if (bidi_it->prev.type_after_wn == WEAK_AN 2175 if (bidi_it->prev.type == WEAK_AN
2134 && (type_of_next == WEAK_AN 2176 && (type_of_next == WEAK_AN
2135 /* If the next character is EN, but the last 2177 /* If the next character is EN, but the last
2136 strong-type character is AL, EN will be later 2178 strong-type character is AL, EN will be later
@@ -2138,18 +2180,18 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2138 So in that case, this ES should not be 2180 So in that case, this ES should not be
2139 changed into EN. */ 2181 changed into EN. */
2140 || (type_of_next == WEAK_EN 2182 || (type_of_next == WEAK_EN
2141 && bidi_it->last_strong.type_after_wn == STRONG_AL))) 2183 && bidi_it->last_strong.type == STRONG_AL)))
2142 type = WEAK_AN; 2184 type = WEAK_AN;
2143 else if (bidi_it->prev.type_after_wn == WEAK_EN 2185 else if (bidi_it->prev.type == WEAK_EN
2144 && type_of_next == WEAK_EN 2186 && type_of_next == WEAK_EN
2145 && bidi_it->last_strong.type_after_wn != STRONG_AL) 2187 && bidi_it->last_strong.type != STRONG_AL)
2146 type = WEAK_EN; 2188 type = WEAK_EN;
2147 } 2189 }
2148 } 2190 }
2149 else if (type == WEAK_ET /* W5: ET with EN before or after it */ 2191 else if (type == WEAK_ET /* W5: ET with EN before or after it */
2150 || type == WEAK_BN) /* W5/Retaining */ 2192 || type == WEAK_BN) /* W5/Retaining */
2151 { 2193 {
2152 if (bidi_it->prev.type_after_wn == WEAK_EN) /* ET/BN w/EN before it */ 2194 if (bidi_it->prev.type == WEAK_EN) /* ET/BN w/EN before it */
2153 type = WEAK_EN; 2195 type = WEAK_EN;
2154 else if (bidi_it->next_en_pos > bidi_it->charpos 2196 else if (bidi_it->next_en_pos > bidi_it->charpos
2155 && bidi_it->next_en_type != WEAK_BN) 2197 && bidi_it->next_en_type != WEAK_BN)
@@ -2210,7 +2252,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2210 { 2252 {
2211 /* If the last strong character is AL, the EN we've 2253 /* If the last strong character is AL, the EN we've
2212 found will become AN when we get to it (W2). */ 2254 found will become AN when we get to it (W2). */
2213 if (bidi_it->last_strong.type_after_wn == STRONG_AL) 2255 if (bidi_it->last_strong.type == STRONG_AL)
2214 type_of_next = WEAK_AN; 2256 type_of_next = WEAK_AN;
2215 else if (type == WEAK_BN) 2257 else if (type == WEAK_BN)
2216 type = NEUTRAL_ON; /* W6/Retaining */ 2258 type = NEUTRAL_ON; /* W6/Retaining */
@@ -2230,9 +2272,9 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2230 2272
2231 if (type == WEAK_ES || type == WEAK_ET || type == WEAK_CS /* W6 */ 2273 if (type == WEAK_ES || type == WEAK_ET || type == WEAK_CS /* W6 */
2232 || (type == WEAK_BN 2274 || (type == WEAK_BN
2233 && (bidi_it->prev.type_after_wn == WEAK_CS /* W6/Retaining */ 2275 && (bidi_it->prev.type == WEAK_CS /* W6/Retaining */
2234 || bidi_it->prev.type_after_wn == WEAK_ES 2276 || bidi_it->prev.type == WEAK_ES
2235 || bidi_it->prev.type_after_wn == WEAK_ET))) 2277 || bidi_it->prev.type == WEAK_ET)))
2236 type = NEUTRAL_ON; 2278 type = NEUTRAL_ON;
2237 2279
2238 /* Store the type we've got so far, before we clobber it with strong 2280 /* 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)
2245 2287
2246 if (type == WEAK_EN) /* W7 */ 2288 if (type == WEAK_EN) /* W7 */
2247 { 2289 {
2248 if ((bidi_it->last_strong.type_after_wn == STRONG_L) 2290 if ((bidi_it->last_strong.type == STRONG_L)
2249 || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sos == L2R)) 2291 || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sos == L2R))
2250 type = STRONG_L; 2292 type = STRONG_L;
2251 } 2293 }
@@ -2275,17 +2317,6 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
2275 return STRONG_R; 2317 return STRONG_R;
2276} 2318}
2277 2319
2278static bidi_bracket_type_t
2279bidi_paired_bracket_type (int c)
2280{
2281 if (c == BIDI_EOB)
2282 return BIDI_BRACKET_NONE;
2283 if (c < 0 || c > MAX_CHAR)
2284 emacs_abort ();
2285
2286 return (bidi_bracket_type_t) XINT (CHAR_TABLE_REF (bidi_brackets_table, c));
2287}
2288
2289#define FLAG_EMBEDDING_INSIDE 1 2320#define FLAG_EMBEDDING_INSIDE 1
2290#define FLAG_OPPOSITE_INSIDE 2 2321#define FLAG_OPPOSITE_INSIDE 2
2291#define FLAG_EMBEDDING_OUTSIDE 4 2322#define FLAG_EMBEDDING_OUTSIDE 4
@@ -2363,7 +2394,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2363 int old_sidx, new_sidx; 2394 int old_sidx, new_sidx;
2364 int current_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2395 int current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2365 2396
2366 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B); 2397 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
2367 if (btype == BIDI_BRACKET_OPEN) 2398 if (btype == BIDI_BRACKET_OPEN)
2368 PUSH_BPA_STACK (embedding_level, last_strong); 2399 PUSH_BPA_STACK (embedding_level, last_strong);
2369 else if (btype == BIDI_BRACKET_CLOSE) 2400 else if (btype == BIDI_BRACKET_CLOSE)
@@ -2389,7 +2420,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2389 /* Update and cache the closing bracket. */ 2420 /* Update and cache the closing bracket. */
2390 bidi_it->type = type; 2421 bidi_it->type = type;
2391 bidi_it->bracket_resolved = 1; 2422 bidi_it->bracket_resolved = 1;
2392 bidi_cache_iterator_state (bidi_it, 0); 2423 bidi_cache_iterator_state (bidi_it, 0, 0);
2393 /* Update and cache the corresponding opening bracket. */ 2424 /* Update and cache the corresponding opening bracket. */
2394 bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx, 2425 bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx,
2395 bidi_it); 2426 bidi_it);
@@ -2397,14 +2428,12 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2397 eassert (bpa_stack[sp].open_bracket_pos == bidi_it->charpos); 2428 eassert (bpa_stack[sp].open_bracket_pos == bidi_it->charpos);
2398#endif 2429#endif
2399 bidi_it->type = type; 2430 bidi_it->type = type;
2400 bidi_it->bracket_resolved = 1;
2401 bidi_cache_iterator_state (bidi_it, 0);
2402 bpa_sp = sp - 1; 2431 bpa_sp = sp - 1;
2403 if (bpa_sp < 0)
2404 break;
2405 } 2432 }
2406 else 2433 bidi_it->bracket_resolved = 1;
2407 bidi_it->bracket_resolved = 1; 2434 bidi_cache_iterator_state (bidi_it, 0, 0);
2435 if (bpa_sp < 0)
2436 break;
2408 } 2437 }
2409 else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL) 2438 else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL)
2410 { 2439 {
@@ -2437,11 +2466,6 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2437 next_for_neutral, and when found, update cached 2466 next_for_neutral, and when found, update cached
2438 states for which it is relevant. */ 2467 states for which it is relevant. */
2439 } 2468 }
2440 /* Record the info about the previous character, so that it
2441 will be cached with this state. */
2442 if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
2443 && bidi_it->type != WEAK_BN)
2444 bidi_remember_char (&bidi_it->prev, bidi_it);
2445 old_sidx = bidi_it->stack_idx; 2469 old_sidx = bidi_it->stack_idx;
2446 type = bidi_resolve_weak (bidi_it); 2470 type = bidi_resolve_weak (bidi_it);
2447 /* Skip level runs excluded from this isolating run sequence. */ 2471 /* Skip level runs excluded from this isolating run sequence. */
@@ -2454,7 +2478,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2454 while (bidi_it->level_stack[bidi_it->stack_idx].level 2478 while (bidi_it->level_stack[bidi_it->stack_idx].level
2455 > current_level) 2479 > current_level)
2456 { 2480 {
2457 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B); 2481 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
2458 type = bidi_resolve_weak (bidi_it); 2482 type = bidi_resolve_weak (bidi_it);
2459 } 2483 }
2460 } 2484 }
@@ -2477,7 +2501,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2477 == bidi_it->charpos); 2501 == bidi_it->charpos);
2478#endif 2502#endif
2479 bidi_it->bracket_resolved = 1; 2503 bidi_it->bracket_resolved = 1;
2480 bidi_cache_iterator_state (bidi_it, 0); 2504 bidi_cache_iterator_state (bidi_it, 0, 0);
2481 bpa_sp--; 2505 bpa_sp--;
2482 } 2506 }
2483 type = saved_it.type; 2507 type = saved_it.type;
@@ -2499,13 +2523,42 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2499} 2523}
2500 2524
2501static bidi_type_t 2525static bidi_type_t
2526bidi_resolve_brackets (struct bidi_it *bidi_it)
2527{
2528 bidi_type_t type = bidi_resolve_weak (bidi_it);
2529 int ch = bidi_it->ch;
2530
2531 if (type == NEUTRAL_ON
2532 && bidi_paired_bracket_type (ch) != BIDI_BRACKET_NONE)
2533 {
2534 if (bidi_cache_idx > bidi_cache_start
2535 && bidi_cache_find (bidi_it->charpos, 1, bidi_it) != UNKNOWN_BT
2536 && bidi_it->bracket_resolved)
2537 type = bidi_it->type;
2538 else
2539 type = bidi_resolve_bracket_pairs (bidi_it);
2540 }
2541
2542 return type;
2543}
2544
2545static bidi_type_t
2502bidi_resolve_neutral (struct bidi_it *bidi_it) 2546bidi_resolve_neutral (struct bidi_it *bidi_it)
2503{ 2547{
2548 bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring);
2504 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2549 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2505 bidi_type_t type = bidi_resolve_weak (bidi_it); 2550 bidi_type_t type = UNKNOWN_BT;
2506 int current_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2551 int current_level;
2507 bool is_neutral; 2552 bool is_neutral;
2508 int ch = bidi_it->ch; 2553
2554 if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
2555 {
2556 if (bidi_it->nchars <= 0)
2557 emacs_abort ();
2558 type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 1, bidi_it);
2559 }
2560 if (type == UNKNOWN_BT)
2561 type = bidi_resolve_brackets (bidi_it);
2509 2562
2510 eassert (type == STRONG_R 2563 eassert (type == STRONG_R
2511 || type == STRONG_L 2564 || type == STRONG_L
@@ -2521,20 +2574,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2521 || type == PDI); 2574 || type == PDI);
2522 2575
2523 eassert (prev_level >= 0); 2576 eassert (prev_level >= 0);
2577 current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2524 eassert (current_level >= 0); 2578 eassert (current_level >= 0);
2525
2526 /* FIXME: Insert the code for N0 here. */
2527 if (type == NEUTRAL_ON
2528 && bidi_paired_bracket_type (ch) != BIDI_BRACKET_NONE)
2529 {
2530 if (bidi_cache_idx > bidi_cache_start
2531 && bidi_cache_find (bidi_it->charpos, 1, bidi_it) != UNKNOWN_BT
2532 && bidi_it->bracket_resolved)
2533 type = bidi_it->type;
2534 else
2535 type = bidi_resolve_bracket_pairs (bidi_it);
2536 }
2537
2538 is_neutral = bidi_get_category (type) == NEUTRAL; 2579 is_neutral = bidi_get_category (type) == NEUTRAL;
2539 2580
2540 if ((type != NEUTRAL_B /* Don't risk entering the long loop below if 2581 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)
2593 bidi_type_t next_type; 2634 bidi_type_t next_type;
2594 bool adjacent_to_neutrals = is_neutral; 2635 bool adjacent_to_neutrals = is_neutral;
2595 2636
2596 if (bidi_it->scan_dir == -1)
2597 emacs_abort ();
2598
2599 bidi_copy_it (&saved_it, bidi_it); 2637 bidi_copy_it (&saved_it, bidi_it);
2600 /* Scan the text forward until we find the first non-neutral 2638 /* Scan the text forward until we find the first non-neutral
2601 character, and then use that to resolve the neutral we 2639 character, and then use that to resolve the neutral we
@@ -2606,14 +2644,9 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2606 2644
2607 /* Paragraph separators have their levels fully resolved 2645 /* Paragraph separators have their levels fully resolved
2608 at this point, so cache them as resolved. */ 2646 at this point, so cache them as resolved. */
2609 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B); 2647 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
2610 /* Record the info about the previous character, so that
2611 it will be cached with this state. */
2612 if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
2613 && bidi_it->type != WEAK_BN)
2614 bidi_remember_char (&bidi_it->prev, bidi_it);
2615 old_sidx = bidi_it->stack_idx; 2648 old_sidx = bidi_it->stack_idx;
2616 type = bidi_resolve_weak (bidi_it); 2649 type = bidi_resolve_brackets (bidi_it);
2617 /* Skip level runs excluded from this isolating run sequence. */ 2650 /* Skip level runs excluded from this isolating run sequence. */
2618 new_sidx = bidi_it->stack_idx; 2651 new_sidx = bidi_it->stack_idx;
2619 if (bidi_it->level_stack[new_sidx].level > current_level 2652 if (bidi_it->level_stack[new_sidx].level > current_level
@@ -2629,8 +2662,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2629 while (bidi_it->level_stack[bidi_it->stack_idx].level 2662 while (bidi_it->level_stack[bidi_it->stack_idx].level
2630 > current_level) 2663 > current_level)
2631 { 2664 {
2632 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B); 2665 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
2633 type = bidi_resolve_weak (bidi_it); 2666 type = bidi_resolve_brackets (bidi_it);
2634 } 2667 }
2635 } 2668 }
2636 if (!adjacent_to_neutrals 2669 if (!adjacent_to_neutrals
@@ -2647,7 +2680,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2647 != current_level))); 2680 != current_level)));
2648 2681
2649 /* Record the character we stopped at. */ 2682 /* Record the character we stopped at. */
2650 bidi_remember_char (&saved_it.next_for_neutral, bidi_it); 2683 bidi_remember_char (&saved_it.next_for_neutral, bidi_it, 1);
2651 2684
2652 if ((bidi_it->level_stack[bidi_it->stack_idx].level != current_level) 2685 if ((bidi_it->level_stack[bidi_it->stack_idx].level != current_level)
2653 || type == NEUTRAL_B) 2686 || type == NEUTRAL_B)
@@ -2731,11 +2764,9 @@ bidi_type_of_next_char (struct bidi_it *bidi_it)
2731static int 2764static int
2732bidi_level_of_next_char (struct bidi_it *bidi_it) 2765bidi_level_of_next_char (struct bidi_it *bidi_it)
2733{ 2766{
2734 bidi_type_t type; 2767 bidi_type_t type = UNKNOWN_BT;
2735 int level, prev_level = -1; 2768 int level;
2736 struct bidi_saved_info next_for_neutral;
2737 ptrdiff_t next_char_pos = -2; 2769 ptrdiff_t next_char_pos = -2;
2738 bool need_to_update_cache = false;
2739 2770
2740 if (bidi_it->scan_dir == 1) 2771 if (bidi_it->scan_dir == 1)
2741 { 2772 {
@@ -2743,50 +2774,14 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2743 = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring)) 2774 = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
2744 ? bidi_it->string.schars : ZV); 2775 ? bidi_it->string.schars : ZV);
2745 2776
2746 /* There's no sense in trying to advance if we hit end of text. */ 2777 /* There's no sense in trying to advance if we've already hit
2778 the end of text. */
2747 if (bidi_it->charpos >= eob) 2779 if (bidi_it->charpos >= eob)
2748 { 2780 {
2749 eassert (bidi_it->resolved_level >= 0); 2781 eassert (bidi_it->resolved_level >= 0);
2750 return bidi_it->resolved_level; 2782 return bidi_it->resolved_level;
2751 } 2783 }
2752
2753 /* Record the info about the previous character. */
2754 if (bidi_it->type_after_wn != WEAK_BN /* W1/Retaining */
2755 && bidi_it->type != WEAK_BN)
2756 bidi_remember_char (&bidi_it->prev, bidi_it);
2757 if (bidi_it->type_after_wn == STRONG_R
2758 || bidi_it->type_after_wn == STRONG_L
2759 || bidi_it->type_after_wn == STRONG_AL)
2760 bidi_remember_char (&bidi_it->last_strong, bidi_it);
2761 /* FIXME: it sounds like we don't need both prev and
2762 prev_for_neutral members, but I'm leaving them both for now. */
2763 if (bidi_it->type == STRONG_R || bidi_it->type == STRONG_L
2764 || bidi_it->type == WEAK_EN || bidi_it->type == WEAK_AN)
2765 bidi_remember_char (&bidi_it->prev_for_neutral, bidi_it);
2766
2767 /* If we overstepped the characters used for resolving neutrals
2768 and whitespace, invalidate their info in the iterator. */
2769 if (bidi_it->charpos >= bidi_it->next_for_neutral.charpos)
2770 bidi_it->next_for_neutral.type = UNKNOWN_BT;
2771 if (bidi_it->next_en_pos >= 0
2772 && bidi_it->charpos >= bidi_it->next_en_pos)
2773 {
2774 bidi_it->next_en_pos = 0;
2775 bidi_it->next_en_type = UNKNOWN_BT;
2776 }
2777 if (bidi_it->next_for_ws.type != UNKNOWN_BT
2778 && bidi_it->charpos >= bidi_it->next_for_ws.charpos)
2779 bidi_it->next_for_ws.type = UNKNOWN_BT;
2780
2781 /* This must be taken before we fill the iterator with the info
2782 about the next char. If we scan backwards, the iterator
2783 state must be already cached, so there's no need to know the
2784 embedding level of the previous character, since we will be
2785 returning to our caller shortly. */
2786 prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2787 eassert (prev_level >= 0);
2788 } 2784 }
2789 next_for_neutral = bidi_it->next_for_neutral;
2790 2785
2791 /* Perhaps the character we want is already cached. If it is, the 2786 /* Perhaps the character we want is already cached. If it is, the
2792 call to bidi_cache_find below will return a type other than 2787 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)
2813 next_char_pos = bidi_it->charpos - 1; 2808 next_char_pos = bidi_it->charpos - 1;
2814 if (next_char_pos >= bob - 1) 2809 if (next_char_pos >= bob - 1)
2815 type = bidi_cache_find (next_char_pos, 0, bidi_it); 2810 type = bidi_cache_find (next_char_pos, 0, bidi_it);
2816 else
2817 type = UNKNOWN_BT;
2818 2811
2819 /* For a sequence of BN and NI, copy the type from the previous 2812 /* For a sequence of BN and NI, copy the type from the previous
2820 character. This is because the loop in bidi_resolve_neutral 2813 character. This is because the loop in bidi_resolve_neutral
@@ -2834,36 +2827,40 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2834 type = prev_type; 2827 type = prev_type;
2835 eassert (type != UNKNOWN_BT); 2828 eassert (type != UNKNOWN_BT);
2836 } 2829 }
2837 } 2830 if (type != UNKNOWN_BT)
2838 else
2839 type = UNKNOWN_BT;
2840 if (type != UNKNOWN_BT)
2841 {
2842 /* Don't lose the information for resolving neutrals! The
2843 cached states could have been cached before their
2844 next_for_neutral member was computed. If we are on our way
2845 forward, we can simply take the info from the previous
2846 state. */
2847 if (bidi_it->scan_dir == 1
2848 && bidi_it->next_for_neutral.type == UNKNOWN_BT)
2849 bidi_it->next_for_neutral = next_for_neutral;
2850
2851 /* If resolved_level is -1, it means this state was cached
2852 before it was completely resolved, so we cannot return
2853 it. */
2854 if (bidi_it->resolved_level != -1)
2855 {
2856 eassert (bidi_it->resolved_level >= 0);
2857 return bidi_it->resolved_level;
2858 }
2859 else
2860 { 2831 {
2861 /* Take note when we've got a cached state that is not fully 2832 /* If resolved_level is -1, it means this state was cached
2862 resolved, so that we could make sure we update the cache 2833 before it was completely resolved, so we cannot return
2863 below, when we do resolve it. */ 2834 it. */
2864 need_to_update_cache = true; 2835 if (bidi_it->resolved_level != -1)
2836 {
2837 eassert (bidi_it->resolved_level >= 0);
2838 return bidi_it->resolved_level;
2839 }
2840 else if (next_char_pos >= bob - 1)
2841 {
2842 level = bidi_it->level_stack[bidi_it->stack_idx].level;
2843 if (bidi_get_category (type) == NEUTRAL
2844 || bidi_isolate_fmt_char (type))
2845 {
2846 /* Make sure the data for resolving neutrals we are
2847 about to use is valid. */
2848 if (bidi_it->next_for_neutral.charpos < bidi_it->charpos
2849 /* PDI defines an eos, so it's OK for it to
2850 serve as its own next_for_neutral. */
2851 || (bidi_it->next_for_neutral.charpos == bidi_it->charpos
2852 && bidi_it->type != PDI)
2853 || bidi_it->next_for_neutral.type == UNKNOWN_BT)
2854 emacs_abort ();
2855
2856 type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
2857 bidi_it->next_for_neutral.type,
2858 level);
2859 }
2860 }
2865 } 2861 }
2866 } 2862 }
2863
2867 if (bidi_it->scan_dir == -1) 2864 if (bidi_it->scan_dir == -1)
2868 /* If we are going backwards, the iterator state is already cached 2865 /* If we are going backwards, the iterator state is already cached
2869 from previous scans, and should be fully resolved. */ 2866 from previous scans, and should be fully resolved. */
@@ -2879,21 +2876,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2879 } 2876 }
2880 2877
2881 level = bidi_it->level_stack[bidi_it->stack_idx].level; 2878 level = bidi_it->level_stack[bidi_it->stack_idx].level;
2882 if (bidi_get_category (type) == NEUTRAL /* && type != NEUTRAL_B */
2883 || bidi_isolate_fmt_char (type))
2884 {
2885 /* Make sure the data for resolving neutrals we are about to use
2886 is valid. */
2887 if (bidi_it->next_for_neutral.charpos <= bidi_it->charpos
2888 || bidi_it->next_for_neutral.type == UNKNOWN_BT)
2889 emacs_abort ();
2890
2891 /* If the cached state shows a neutral character, it was not
2892 resolved by bidi_resolve_neutral, so do it now. */
2893 type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
2894 bidi_it->next_for_neutral.type,
2895 level);
2896 }
2897 2879
2898 eassert ((type == STRONG_R 2880 eassert ((type == STRONG_R
2899 || type == STRONG_L 2881 || type == STRONG_L
@@ -2908,7 +2890,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2908 or a TAB or a paragraph separator. */ 2890 or a TAB or a paragraph separator. */
2909 if ((bidi_it->orig_type == NEUTRAL_WS 2891 if ((bidi_it->orig_type == NEUTRAL_WS
2910 || bidi_isolate_fmt_char (bidi_it->orig_type)) 2892 || bidi_isolate_fmt_char (bidi_it->orig_type))
2911 && bidi_it->next_for_ws.type == UNKNOWN_BT) 2893 && bidi_it->next_for_ws.charpos < bidi_it->charpos)
2912 { 2894 {
2913 int ch; 2895 int ch;
2914 ptrdiff_t clen = bidi_it->ch_len; 2896 ptrdiff_t clen = bidi_it->ch_len;
@@ -2935,6 +2917,9 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2935 bidi_it->next_for_ws.charpos = cpos; 2917 bidi_it->next_for_ws.charpos = cpos;
2936 } 2918 }
2937 2919
2920 /* Update the cache, but only if this state was already cached. */
2921 bidi_cache_iterator_state (bidi_it, 1, 1);
2922
2938 /* Resolve implicit levels. */ 2923 /* Resolve implicit levels. */
2939 if (bidi_it->orig_type == NEUTRAL_B /* L1 */ 2924 if (bidi_it->orig_type == NEUTRAL_B /* L1 */
2940 || bidi_it->orig_type == NEUTRAL_S 2925 || bidi_it->orig_type == NEUTRAL_S
@@ -2957,8 +2942,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2957 } 2942 }
2958 2943
2959 bidi_it->resolved_level = level; 2944 bidi_it->resolved_level = level;
2960 if (need_to_update_cache)
2961 bidi_cache_iterator_state (bidi_it, 1);
2962 return level; 2945 return level;
2963} 2946}
2964 2947
@@ -3000,10 +2983,10 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
3000 if (end_flag) 2983 if (end_flag)
3001 emacs_abort (); 2984 emacs_abort ();
3002 2985
3003 bidi_cache_iterator_state (bidi_it, 1); 2986 bidi_cache_iterator_state (bidi_it, 1, 0);
3004 do { 2987 do {
3005 new_level = bidi_level_of_next_char (bidi_it); 2988 new_level = bidi_level_of_next_char (bidi_it);
3006 bidi_cache_iterator_state (bidi_it, 1); 2989 bidi_cache_iterator_state (bidi_it, 1, 0);
3007 } while (new_level >= level); 2990 } while (new_level >= level);
3008 } 2991 }
3009} 2992}
@@ -3047,7 +3030,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
3047 sentinel.ch_len = 1; 3030 sentinel.ch_len = 1;
3048 sentinel.nchars = 1; 3031 sentinel.nchars = 1;
3049 } 3032 }
3050 bidi_cache_iterator_state (&sentinel, 1); 3033 bidi_cache_iterator_state (&sentinel, 1, 0);
3051 } 3034 }
3052 3035
3053 old_level = bidi_it->resolved_level; 3036 old_level = bidi_it->resolved_level;
@@ -3162,7 +3145,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
3162 compromised: it assumes cached states correspond to buffer 3145 compromised: it assumes cached states correspond to buffer
3163 positions 1:1. */ 3146 positions 1:1. */
3164 else 3147 else
3165 bidi_cache_iterator_state (bidi_it, 1); 3148 bidi_cache_iterator_state (bidi_it, 1, 0);
3166 } 3149 }
3167 3150
3168 if (STRINGP (bidi_it->string.lstring)) 3151 if (STRINGP (bidi_it->string.lstring))
diff --git a/src/dispextern.h b/src/dispextern.h
index 80b3879b806..9d7eb57fc8c 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1915,9 +1915,7 @@ typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t;
1915struct bidi_saved_info { 1915struct bidi_saved_info {
1916 ptrdiff_t charpos; /* character's buffer position */ 1916 ptrdiff_t charpos; /* character's buffer position */
1917 bidi_type_t type; /* character's resolved bidi type */ 1917 bidi_type_t type; /* character's resolved bidi type */
1918 bidi_type_t type_after_wn; /* bidi type of the character, after Wn */
1919 bidi_type_t orig_type; /* bidi type as we found it in the buffer */ 1918 bidi_type_t orig_type; /* bidi type as we found it in the buffer */
1920 bool_bf bracket_resolved : 1; /* 1 if type was BPA-resolved */
1921}; 1919};
1922 1920
1923/* Data type for keeping track of information about saved embedding 1921/* Data type for keeping track of information about saved embedding