]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bidi_resolve_explicit when one directional control follows another.
authorEli Zaretskii <eliz@gnu.org>
Fri, 26 Sep 2014 09:24:15 +0000 (12:24 +0300)
committerEli Zaretskii <eliz@gnu.org>
Fri, 26 Sep 2014 09:24:15 +0000 (12:24 +0300)
src/bidi.c

index 0614f5f0263b81fba6469f35440072a01b7095be..7beadb25455174cdb1ac76d5b11107afc3580925 100644 (file)
@@ -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