From: Eli Zaretskii Date: Fri, 26 Sep 2014 09:24:15 +0000 (+0300) Subject: Fix bidi_resolve_explicit when one directional control follows another. X-Git-Tag: emacs-25.0.90~2635^2~679^2~50^2~28 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0df5896cd2851947d2bc186ff82c5a43e7bdd0c7;p=emacs.git Fix bidi_resolve_explicit when one directional control follows another. --- diff --git a/src/bidi.c b/src/bidi.c index 0614f5f0263..7beadb25455 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -1680,7 +1680,7 @@ static int bidi_resolve_explicit (struct bidi_it *bidi_it) { int curchar; - bidi_type_t type, typ1, prev_type = UNKNOWN_BT;; + bidi_type_t type, typ1, prev_type = UNKNOWN_BT; int current_level; int new_level; bidi_dir_t override; @@ -1743,12 +1743,13 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) bidi_it->bytepos += bidi_it->ch_len; prev_type = bidi_it->orig_type; } + else /* EOB or end of string */ + prev_type = NEUTRAL_B; 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; new_level = current_level; - bidi_it->resolved_level = new_level; if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) { @@ -1760,6 +1761,82 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) } else { + /* LRI, RLI, and FSI increment, and PDF decrements, the + embedding level of the _following_ characters, so we must + first look at the type of the previous character to support + that. */ + switch (prev_type) + { + case FSI: /* X5c */ + end = string_p ? bidi_it->string.schars : ZV; + disp_pos = bidi_it->disp_pos; + disp_prop = bidi_it->disp_prop; + nchars = bidi_it->nchars; + ch_len = bidi_it->ch_len; + typ1 = find_first_strong_char (bidi_it->charpos, + bidi_it->bytepos, end, + &disp_pos, &disp_prop, + &bidi_it->string, bidi_it->w, + string_p, bidi_it->frame_window_p, + &ch_len, &nchars, true); + if (typ1 != STRONG_R && typ1 != STRONG_AL) + { + type = LRI; + goto fsi_as_lri; + } + else + type = RLI; + /* FALLTHROUGH */ + case RLI: /* X5a */ + if (override == NEUTRAL_DIR) + bidi_it->type_after_w1 = type; + else /* Unicode 8.0 correction. */ + bidi_it->type_after_w1 = (override == L2R ? STRONG_L : STRONG_R); + bidi_check_type (bidi_it->type_after_w1); + if (current_level < BIDI_MAXDEPTH + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) + { + new_level = ((current_level + 1) & ~1) + 1; + bidi_it->isolate_level++; + bidi_push_embedding_level (bidi_it, new_level, + NEUTRAL_DIR, true); + } + else + bidi_it->invalid_isolates++; + break; + case LRI: /* X5b */ + fsi_as_lri: + if (override == NEUTRAL_DIR) + bidi_it->type_after_w1 = type; + else /* Unicode 8.0 correction. */ + bidi_it->type_after_w1 = (override == L2R ? STRONG_L : STRONG_R); + bidi_check_type (bidi_it->type_after_w1); + if (current_level < BIDI_MAXDEPTH - 1 + && bidi_it->invalid_levels == 0 + && bidi_it->invalid_isolates == 0) + { + new_level = ((current_level + 2) & ~1); + bidi_it->isolate_level++; + bidi_push_embedding_level (bidi_it, new_level, + NEUTRAL_DIR, true); + } + else + bidi_it->invalid_isolates++; + break; + case PDF: /* X7 */ + if (!bidi_it->invalid_isolates) + { + if (bidi_it->invalid_levels) + bidi_it->invalid_levels--; + else if (!isolate_status && bidi_it->stack_idx >= 1) + new_level = bidi_pop_embedding_level (bidi_it); + } + break; + default: + /* Nothing. */ + break; + } /* Fetch the character at BYTEPOS. If it is covered by a display string, treat the entire run of covered characters as a single character u+FFFC. */ @@ -1770,6 +1847,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) &bidi_it->ch_len, &bidi_it->nchars); } bidi_it->ch = curchar; + bidi_it->resolved_level = new_level; /* Don't apply directional override here, as all the types we handle below will not be affected by the override anyway, and we need @@ -1788,13 +1866,13 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) bidi_it->type_after_w1 = type; bidi_check_type (bidi_it->type_after_w1); type = WEAK_BN; /* X9/Retaining */ - if (current_level < BIDI_MAXDEPTH + if (new_level < BIDI_MAXDEPTH && bidi_it->invalid_levels == 0 && bidi_it->invalid_isolates == 0) { /* Compute the least odd embedding level greater than the current level. */ - new_level = ((current_level + 1) & ~1) + 1; + new_level = ((new_level + 1) & ~1) + 1; if (bidi_it->type_after_w1 == RLE) override = NEUTRAL_DIR; else @@ -1813,13 +1891,13 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) bidi_it->type_after_w1 = type; bidi_check_type (bidi_it->type_after_w1); type = WEAK_BN; /* X9/Retaining */ - if (current_level < BIDI_MAXDEPTH - 1 + if (new_level < BIDI_MAXDEPTH - 1 && bidi_it->invalid_levels == 0 && bidi_it->invalid_isolates == 0) { /* Compute the least even embedding level greater than the current level. */ - new_level = ((current_level + 2) & ~1); + new_level = ((new_level + 2) & ~1); if (bidi_it->type_after_w1 == LRE) override = NEUTRAL_DIR; else @@ -1835,10 +1913,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) break; case PDI: /* X6a */ if (bidi_it->invalid_isolates) - { - bidi_it->invalid_isolates--; - new_level = current_level; - } + bidi_it->invalid_isolates--; else if (bidi_it->isolate_level > 0) { bidi_it->invalid_levels = 0; @@ -1863,83 +1938,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) type = WEAK_BN; /* X9/Retaining */ break; default: - /* LRI, RLI, and FSI increment, and PDF decrements, the - embedding level of the _following_ characters, so we must - look at the type of the previous character to support - that. */ - switch (prev_type) - { - case FSI: /* X5c */ - end = string_p ? bidi_it->string.schars : ZV; - disp_pos = bidi_it->disp_pos; - disp_prop = bidi_it->disp_prop; - nchars = bidi_it->nchars; - ch_len = bidi_it->ch_len; - typ1 = find_first_strong_char (bidi_it->charpos, - bidi_it->bytepos, end, - &disp_pos, &disp_prop, - &bidi_it->string, bidi_it->w, - string_p, bidi_it->frame_window_p, - &ch_len, &nchars, true); - if (typ1 != STRONG_R && typ1 != STRONG_AL) - { - type = LRI; - goto fsi_as_lri; - } - else - type = RLI; - /* FALLTHROUGH */ - case RLI: /* X5a */ - if (override == NEUTRAL_DIR) - bidi_it->type_after_w1 = type; - else /* Unicode 8.0 correction. */ - bidi_it->type_after_w1 = (override == L2R ? STRONG_L : STRONG_R); - bidi_check_type (bidi_it->type_after_w1); - if (current_level < BIDI_MAXDEPTH - && bidi_it->invalid_levels == 0 - && bidi_it->invalid_isolates == 0) - { - new_level = ((current_level + 1) & ~1) + 1; - bidi_it->isolate_level++; - bidi_push_embedding_level (bidi_it, new_level, - NEUTRAL_DIR, true); - } - else - bidi_it->invalid_isolates++; - break; - case LRI: /* X5b */ - fsi_as_lri: - if (override == NEUTRAL_DIR) - bidi_it->type_after_w1 = type; - else /* Unicode 8.0 correction. */ - bidi_it->type_after_w1 = (override == L2R ? STRONG_L : STRONG_R); - bidi_check_type (bidi_it->type_after_w1); - if (current_level < BIDI_MAXDEPTH - 1 - && bidi_it->invalid_levels == 0 - && bidi_it->invalid_isolates == 0) - { - new_level = ((current_level + 2) & ~1); - bidi_it->isolate_level++; - bidi_push_embedding_level (bidi_it, new_level, - NEUTRAL_DIR, true); - } - else - bidi_it->invalid_isolates++; - break; - case PDF: /* X7 */ - if (!bidi_it->invalid_isolates) - { - if (bidi_it->invalid_levels) - bidi_it->invalid_levels--; - else if (!isolate_status && bidi_it->stack_idx >= 1) - new_level = bidi_pop_embedding_level (bidi_it); - } - bidi_it->resolved_level = new_level; - break; - default: - /* Nothing. */ - break; - } + /* Nothing. */ + break; } bidi_it->type = type; @@ -1959,7 +1959,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) static bool bidi_isolate_fmt_char (bidi_type_t ch_type) { - return (ch_type == LRI || ch_type == RLI || ch_type == PDI); + return (ch_type == LRI || ch_type == RLI || ch_type == PDI || ch_type == FSI); } /* Advance in the buffer/string, resolve weak types and return the