* buffer.h (FETCH_MULTIBYTE_CHAR): Define as inline.
[bpt/emacs.git] / src / bidi.c
index e3fc03f..675e202 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level bidirectional buffer/string-scanning functions for GNU Emacs.
-   Copyright (C) 2000-2001, 2004-2005, 2009-2011
+   Copyright (C) 2000-2001, 2004-2005, 2009-2012
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -51,7 +51,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
    A note about references to UAX#9 rules: if the reference says
    something like "X9/Retaining", it means that you need to refer to
-   rule X9 and to its modifications decribed in the "Implementation
+   rule X9 and to its modifications described in the "Implementation
    Notes" section of UAX#9, under "Retaining Format Codes".  */
 
 #include <config.h>
@@ -59,8 +59,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <setjmp.h>
 
 #include "lisp.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "dispextern.h"
 
 static int bidi_initialized = 0;
@@ -204,8 +204,16 @@ bidi_mirror_char (int c)
   val = CHAR_TABLE_REF (bidi_mirror_table, c);
   if (INTEGERP (val))
     {
-      int v = XINT (val);
+      int v;
+
+      /* When debugging, check before assigning to V, so that the check
+        isn't broken by undefined behavior due to int overflow.  */
+      eassert (CHAR_VALID_P (XINT (val)));
 
+      v = XINT (val);
+
+      /* Minimal test we must do in optimized builds, to prevent weird
+        crashes further down the road.  */
       if (v < 0 || v > MAX_CHAR)
        abort ();
 
@@ -378,7 +386,7 @@ bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it)
    resolved levels in cached states.  DIR, if non-zero, means search
    in that direction from the last cache hit.  */
 static inline ptrdiff_t
-bidi_cache_search (EMACS_INT charpos, int level, int dir)
+bidi_cache_search (ptrdiff_t charpos, int level, int dir)
 {
   ptrdiff_t i, i_start;
 
@@ -562,7 +570,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
 }
 
 static inline bidi_type_t
-bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it)
+bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it)
 {
   ptrdiff_t i = bidi_cache_search (charpos, level, bidi_it->scan_dir);
 
@@ -572,7 +580,7 @@ bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it)
 
       bidi_copy_it (bidi_it, &bidi_cache[i]);
       bidi_cache_last_idx = i;
-      /* Don't let scan direction from from the cached state override
+      /* Don't let scan direction from the cached state override
         the current scan direction.  */
       bidi_it->scan_dir = current_scan_dir;
       return bidi_it->type;
@@ -795,7 +803,7 @@ bidi_set_paragraph_end (struct bidi_it *bidi_it)
 
 /* Initialize the bidi iterator from buffer/string position CHARPOS.  */
 void
-bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p,
+bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, int frame_window_p,
              struct bidi_it *bidi_it)
 {
   if (! bidi_initialized)
@@ -846,7 +854,10 @@ bidi_line_init (struct bidi_it *bidi_it)
   bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */
   bidi_it->invalid_levels = 0;
   bidi_it->invalid_rl_levels = -1;
-  bidi_it->next_en_pos = -1;
+  /* Setting this to zero will force its recomputation the first time
+     we need it for W5.  */
+  bidi_it->next_en_pos = 0;
+  bidi_it->next_en_type = UNKNOWN_BT;
   bidi_it->next_for_ws.type = UNKNOWN_BT;
   bidi_set_sor_type (bidi_it,
                     (bidi_it->paragraph_dir == R2L ? 1 : 0),
@@ -864,11 +875,11 @@ bidi_line_init (struct bidi_it *bidi_it)
    are zero-based character positions in S, BEGBYTE is byte position
    corresponding to BEG.  UNIBYTE, if non-zero, means S is a unibyte
    string.  */
-static inline EMACS_INT
-bidi_count_bytes (const unsigned char *s, const EMACS_INT beg,
-                 const EMACS_INT begbyte, const EMACS_INT end, int unibyte)
+static inline ptrdiff_t
+bidi_count_bytes (const unsigned char *s, const ptrdiff_t beg,
+                 const ptrdiff_t begbyte, const ptrdiff_t end, int unibyte)
 {
-  EMACS_INT pos = beg;
+  ptrdiff_t pos = beg;
   const unsigned char *p = s + begbyte, *start = p;
 
   if (unibyte)
@@ -893,7 +904,7 @@ bidi_count_bytes (const unsigned char *s, const EMACS_INT beg,
    character from the current buffer.  UNIBYTE non-zero means S is a
    unibyte string.  */
 static inline int
-bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte)
+bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, int unibyte)
 {
   if (s)
     {
@@ -921,14 +932,15 @@ bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte)
    string to iterate, or NULL if iterating over a buffer or a Lisp
    string; in the latter case, STRING->lstring is the Lisp string.  */
 static inline int
-bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
+bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos,
                 int *disp_prop, struct bidi_string_data *string,
-                int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars)
+                int frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
 {
   int ch;
-  EMACS_INT endpos
+  ptrdiff_t endpos
     = (string->s || STRINGP (string->lstring)) ? string->schars : ZV;
   struct text_pos pos;
+  int len;
 
   /* If we got past the last known position of display string, compute
      the position of the next one.  That position could be at CHARPOS.  */
@@ -950,7 +962,7 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
     }
   else if (charpos >= *disp_pos && *disp_prop)
     {
-      EMACS_INT disp_end_pos;
+      ptrdiff_t disp_end_pos;
 
       /* We don't expect to find ourselves in the middle of a display
         property.  Hopefully, it will never be needed.  */
@@ -1000,7 +1012,6 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
     normal_char:
       if (string->s)
        {
-         int len;
 
          if (!string->unibyte)
            {
@@ -1015,8 +1026,6 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
        }
       else if (STRINGP (string->lstring))
        {
-         int len;
-
          if (!string->unibyte)
            {
              ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos,
@@ -1031,8 +1040,8 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
        }
       else
        {
-         ch = FETCH_MULTIBYTE_CHAR (bytepos);
-         *ch_len = CHAR_BYTES (ch);
+         ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (bytepos), len);
+         *ch_len = len;
        }
       *nchars = 1;
     }
@@ -1060,12 +1069,12 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
    following the buffer position, -1 if position is at the beginning
    of a new paragraph, or -2 if position is neither at beginning nor
    at end of a paragraph.  */
-static EMACS_INT
-bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos)
+static ptrdiff_t
+bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
 {
   Lisp_Object sep_re;
   Lisp_Object start_re;
-  EMACS_INT val;
+  ptrdiff_t val;
 
   sep_re = paragraph_separate_re;
   start_re = paragraph_start_re;
@@ -1092,12 +1101,12 @@ bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos)
    Value is the byte position of the paragraph's beginning, or
    BEGV_BYTE if paragraph_start_re is still not found after looking
    back MAX_PARAGRAPH_SEARCH lines in the buffer.  */
-static EMACS_INT
-bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
+static ptrdiff_t
+bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
 {
   Lisp_Object re = paragraph_start_re;
-  EMACS_INT limit = ZV, limit_byte = ZV_BYTE;
-  EMACS_INT n = 0;
+  ptrdiff_t limit = ZV, limit_byte = ZV_BYTE;
+  ptrdiff_t n = 0;
 
   while (pos_byte > BEGV_BYTE
         && n++ < MAX_PARAGRAPH_SEARCH
@@ -1129,18 +1138,18 @@ bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
 
    Note that this function gives the paragraph separator the same
    direction as the preceding paragraph, even though Emacs generally
-   views the separartor as not belonging to any paragraph.  */
+   views the separator as not belonging to any paragraph.  */
 void
 bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
 {
-  EMACS_INT bytepos = bidi_it->bytepos;
+  ptrdiff_t bytepos = bidi_it->bytepos;
   int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring);
-  EMACS_INT pstartbyte;
+  ptrdiff_t pstartbyte;
   /* Note that begbyte is a byte position, while end is a character
      position.  Yes, this is ugly, but we are trying to avoid costly
      calls to BYTE_TO_CHAR and its ilk.  */
-  EMACS_INT begbyte = string_p ? 0 : BEGV_BYTE;
-  EMACS_INT end = string_p ? bidi_it->string.schars : ZV;
+  ptrdiff_t begbyte = string_p ? 0 : BEGV_BYTE;
+  ptrdiff_t end = string_p ? bidi_it->string.schars : ZV;
 
   /* Special case for an empty buffer. */
   if (bytepos == begbyte && bidi_it->charpos == end)
@@ -1162,8 +1171,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
   else if (dir == NEUTRAL_DIR) /* P2 */
     {
       int ch;
-      EMACS_INT ch_len, nchars;
-      EMACS_INT pos, disp_pos = -1;
+      ptrdiff_t ch_len, nchars;
+      ptrdiff_t pos, disp_pos = -1;
       int disp_prop = 0;
       bidi_type_t type;
       const unsigned char *s;
@@ -1259,8 +1268,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
              bidi_it->paragraph_dir = L2R; /* P3 and HL1 */
            else
              {
-               EMACS_INT prevpbyte = pstartbyte;
-               EMACS_INT p = BYTE_TO_CHAR (pstartbyte), pbyte = pstartbyte;
+               ptrdiff_t prevpbyte = pstartbyte;
+               ptrdiff_t p = BYTE_TO_CHAR (pstartbyte), pbyte = pstartbyte;
 
                /* Find the beginning of the previous paragraph, if any.  */
                while (pbyte > BEGV_BYTE && prevpbyte >= pstartbyte)
@@ -1435,7 +1444,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       case LRE:        /* X3 */
@@ -1471,7 +1481,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       case PDF:        /* X7 */
@@ -1497,7 +1508,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       default:
@@ -1521,7 +1533,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
 {
   int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
   int new_level  = bidi_resolve_explicit_1 (bidi_it);
-  EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV;
+  ptrdiff_t eob = bidi_it->string.s ? bidi_it->string.schars : ZV;
   const unsigned char *s
     = (STRINGP (bidi_it->string.lstring)
        ? SDATA (bidi_it->string.lstring)
@@ -1609,7 +1621,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
   int next_char;
   bidi_type_t type_of_next;
   struct bidi_it saved_it;
-  EMACS_INT eob
+  ptrdiff_t eob
     = ((STRINGP (bidi_it->string.lstring) || bidi_it->string.s)
        ? bidi_it->string.schars : ZV);
 
@@ -1729,12 +1741,17 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
       else if (type == WEAK_ET /* W5: ET with EN before or after it */
               || type == WEAK_BN)      /* W5/Retaining */
        {
-         if (bidi_it->prev.type_after_w1 == WEAK_EN /* ET/BN w/EN before it */
-             || bidi_it->next_en_pos > bidi_it->charpos)
+         if (bidi_it->prev.type_after_w1 == WEAK_EN) /* ET/BN w/EN before it */
            type = WEAK_EN;
-         else                  /* W5: ET/BN with EN after it.  */
+         else if (bidi_it->next_en_pos > bidi_it->charpos
+                  && bidi_it->next_en_type != WEAK_BN)
            {
-             EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars;
+             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)
+           {
+             ptrdiff_t en_pos = bidi_it->charpos + bidi_it->nchars;
              const unsigned char *s = (STRINGP (bidi_it->string.lstring)
                                        ? SDATA (bidi_it->string.lstring)
                                        : bidi_it->string.s);
@@ -1761,20 +1778,27 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
                  en_pos = bidi_it->charpos;
                  bidi_copy_it (bidi_it, &saved_it);
                }
+             /* Remember this position, to speed up processing of the
+                next ETs.  */
+             bidi_it->next_en_pos = en_pos;
              if (type_of_next == WEAK_EN)
                {
                  /* 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_w1 != STRONG_AL)
-                   {
-                     type = WEAK_EN;
-                     /* Remember this EN position, to speed up processing
-                        of the next ETs.  */
-                     bidi_it->next_en_pos = en_pos;
-                   }
+                 if (bidi_it->last_strong.type_after_w1 == STRONG_AL)
+                   type_of_next = WEAK_AN;
                  else if (type == WEAK_BN)
                    type = NEUTRAL_ON; /* W6/Retaining */
+                 else
+                   type = WEAK_EN;
                }
+             else if (type_of_next == NEUTRAL_B)
+               /* Record the fact that there are no more ENs from
+                  here to the end of paragraph, to avoid entering the
+                  loop above ever again in this paragraph.  */
+               bidi_it->next_en_pos = -1;
+             /* Record the type of the character where we ended our search.  */
+             bidi_it->next_en_type = type_of_next;
            }
        }
     }
@@ -1843,13 +1867,45 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
        || type == NEUTRAL_ON))
     abort ();
 
-  if (bidi_get_category (type) == NEUTRAL
+  if ((type != NEUTRAL_B /* Don't risk entering the long loop below if
+                           we are already at paragraph end.  */
+       && bidi_get_category (type) == NEUTRAL)
       || (type == WEAK_BN && prev_level == current_level))
     {
       if (bidi_it->next_for_neutral.type != UNKNOWN_BT)
        type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
                                       bidi_it->next_for_neutral.type,
                                       current_level);
+      /* The next two "else if" clauses are shortcuts for the
+        important special case when we have a long sequence of
+        neutral or WEAK_BN characters, such as whitespace or nulls or
+        other control characters, on the base embedding level of the
+        paragraph, and that sequence goes all the way to the end of
+        the paragraph and follows a character whose resolved
+        directionality is identical to the base embedding level.
+        (This is what happens in a buffer with plain L2R text that
+        happens to include long sequences of control characters.)  By
+        virtue of N1, the result of examining this long sequence will
+        always be either STRONG_L or STRONG_R, depending on the base
+        embedding level.  So we use this fact directly instead of
+        entering the expensive loop in the "else" clause.  */
+      else if (current_level == 0
+              && bidi_it->prev_for_neutral.type == STRONG_L
+              && !bidi_explicit_dir_char (bidi_it->ch))
+       type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
+                                      STRONG_L, current_level);
+      else if (/* current level is 1 */
+              current_level == 1
+              /* base embedding level is also 1 */
+              && bidi_it->level_stack[0].level == 1
+              /* previous character is one of those considered R for
+                 the purposes of W5 */
+              && (bidi_it->prev_for_neutral.type == STRONG_R
+                  || bidi_it->prev_for_neutral.type == WEAK_EN
+                  || bidi_it->prev_for_neutral.type == WEAK_AN)
+              && !bidi_explicit_dir_char (bidi_it->ch))
+       type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
+                                      STRONG_R, current_level);
       else
        {
          /* Arrrgh!!  The UAX#9 algorithm is too deeply entrenched in
@@ -1900,6 +1956,9 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
              case STRONG_L:
              case STRONG_R:
              case STRONG_AL:
+               /* Actually, STRONG_AL cannot happen here, because
+                  bidi_resolve_weak converts it to STRONG_R, per W3.  */
+               xassert (type != STRONG_AL);
                next_type = type;
                break;
              case WEAK_EN:
@@ -1907,7 +1966,6 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
                /* N1: ``European and Arabic numbers are treated as
                   though they were R.''  */
                next_type = STRONG_R;
-               saved_it.next_for_neutral.type = STRONG_R;
                break;
              case WEAK_BN:
                if (!bidi_explicit_dir_char (bidi_it->ch))
@@ -1920,11 +1978,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
                   member.  */
                if (saved_it.type != WEAK_BN
                    || bidi_get_category (bidi_it->prev.type_after_w1) == NEUTRAL)
-                 {
-                   next_type = bidi_it->prev_for_neutral.type;
-                   saved_it.next_for_neutral.type = next_type;
-                   bidi_check_type (next_type);
-                 }
+                 next_type = bidi_it->prev_for_neutral.type;
                else
                  {
                    /* This is a BN which does not adjoin neutrals.
@@ -1938,7 +1992,9 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
            }
          type = bidi_resolve_neutral_1 (saved_it.prev_for_neutral.type,
                                         next_type, current_level);
+         saved_it.next_for_neutral.type = next_type;
          saved_it.type = type;
+         bidi_check_type (next_type);
          bidi_check_type (type);
          bidi_copy_it (bidi_it, &saved_it);
        }
@@ -1982,11 +2038,11 @@ 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;
-  EMACS_INT next_char_pos = -2;
+  ptrdiff_t next_char_pos = -2;
 
   if (bidi_it->scan_dir == 1)
     {
-      EMACS_INT eob
+      ptrdiff_t eob
        = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
           ? bidi_it->string.schars : ZV);
 
@@ -2014,7 +2070,10 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
        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 = -1;
+       {
+         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;
@@ -2112,11 +2171,11 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
       && bidi_it->next_for_ws.type == UNKNOWN_BT)
     {
       int ch;
-      EMACS_INT clen = bidi_it->ch_len;
-      EMACS_INT bpos = bidi_it->bytepos;
-      EMACS_INT cpos = bidi_it->charpos;
-      EMACS_INT disp_pos = bidi_it->disp_pos;
-      EMACS_INT nc = bidi_it->nchars;
+      ptrdiff_t clen = bidi_it->ch_len;
+      ptrdiff_t bpos = bidi_it->bytepos;
+      ptrdiff_t cpos = bidi_it->charpos;
+      ptrdiff_t disp_pos = bidi_it->disp_pos;
+      ptrdiff_t nc = bidi_it->nchars;
       struct bidi_string_data bs = bidi_it->string;
       bidi_type_t chtype;
       int fwp = bidi_it->frame_window_p;
@@ -2127,7 +2186,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
       do {
        ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs,
                              fwp, &clen, &nc);
-       if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */)
+       if (ch == '\n' || ch == BIDI_EOB)
          chtype = NEUTRAL_B;
        else
          chtype = bidi_get_type (ch, NEUTRAL_DIR);
@@ -2140,7 +2199,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
     }
 
   /* Resolve implicit levels, with a twist: PDFs get the embedding
-     level of the enbedding they terminate.  See below for the
+     level of the embedding they terminate.  See below for the
      reason.  */
   if (bidi_it->orig_type == PDF
       /* Don't do this if this formatting code didn't change the
@@ -2177,7 +2236,6 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
   else if (bidi_it->orig_type == NEUTRAL_B /* L1 */
           || bidi_it->orig_type == NEUTRAL_S
           || bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB
-          /* || bidi_it->ch == LINESEP_CHAR */
           || (bidi_it->orig_type == NEUTRAL_WS
               && (bidi_it->next_for_ws.type == NEUTRAL_B
                   || bidi_it->next_for_ws.type == NEUTRAL_S)))
@@ -2359,7 +2417,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
        bidi_it->separator_limit = bidi_it->string.schars;
       else if (bidi_it->bytepos < ZV_BYTE)
        {
-         EMACS_INT sep_len
+         ptrdiff_t sep_len
            = bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars,
                                     bidi_it->bytepos + bidi_it->ch_len);
          if (bidi_it->nchars <= 0)
@@ -2425,6 +2483,6 @@ bidi_dump_cached_states (void)
   fputs ("\n", stderr);
   fputs ("pos ", stderr);
   for (i = 0; i < bidi_cache_idx; i++)
-    fprintf (stderr, "%*"pI"d", ndigits, bidi_cache[i].charpos);
+    fprintf (stderr, "%*"pD"d", ndigits, bidi_cache[i].charpos);
   fputs ("\n", stderr);
 }