]> git.eshelyaron.com Git - emacs.git/commitdiff
Support bidi reordering of unibyte strings. Fix crash displaying "All" in mode line...
authorEli Zaretskii <eliz@gnu.org>
Fri, 1 Jul 2011 10:53:29 +0000 (13:53 +0300)
committerEli Zaretskii <eliz@gnu.org>
Fri, 1 Jul 2011 10:53:29 +0000 (13:53 +0300)
 src/dispextern.h (struct bidi_string_data): New member `unibyte'.
 src/xdisp.c (handle_single_display_spec, next_overlay_string)
 (get_overlay_strings_1, reseat_1, reseat_to_string)
 (push_display_prop): Set up the `unibyte' member of bidi_it.string
 correctly.  Don't assume unibyte strings are not bidi-reordered.
 (compute_display_string_pos)
 (compute_display_string_end): Fix handling the case of C string.
 src/bidi.c (bidi_count_bytes, bidi_char_at_pos): Accept an
 additional argument UNIBYTE, and support unibyte strings.  All
 callers changed.
 (bidi_fetch_char): Support unibyte strings.

src/ChangeLog
src/bidi.c
src/dispextern.h
src/xdisp.c

index 8d5275f9702db83d2059610d829e6d4cac0627ed..8cb94b3ff2247c6c4641f36bdfad1d01a7e69596 100644 (file)
@@ -1,3 +1,19 @@
+2011-07-01  Eli Zaretskii  <eliz@gnu.org>
+
+       * dispextern.h (struct bidi_string_data): New member `unibyte'.
+
+       * xdisp.c (handle_single_display_spec, next_overlay_string)
+       (get_overlay_strings_1, reseat_1, reseat_to_string)
+       (push_display_prop): Set up the `unibyte' member of bidi_it.string
+       correctly.  Don't assume unibyte strings are not bidi-reordered.
+       (compute_display_string_pos)
+       (compute_display_string_end): Fix handling the case of C string.
+
+       * bidi.c (bidi_count_bytes, bidi_char_at_pos): Accept an
+       additional argument UNIBYTE, and support unibyte strings.  All
+       callers changed.
+       (bidi_fetch_char): Support unibyte strings.
+
 2011-06-25  Eli Zaretskii  <eliz@gnu.org>
 
        * xdisp.c (set_iterator_to_next, get_visually_first_element): Use
index 5c9239d60f08f4629563440a3bcabeac0e61e9b2..87978058a5b60ae981ab1cc9be44af7db976e0ad 100644 (file)
@@ -721,23 +721,29 @@ bidi_line_init (struct bidi_it *bidi_it)
                        Fetching characters
  ***********************************************************************/
 
-/* Count bytes in multibyte string S between BEG/BEGBYTE and END.  BEG
-   and END are zero-based character positions in S, BEGBYTE is byte
-   position corresponding to BEG.  */
+/* Count bytes in string S between BEG/BEGBYTE and END.  BEG and END
+   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)
+                 const EMACS_INT begbyte, const EMACS_INT end, int unibyte)
 {
   EMACS_INT pos = beg;
   const unsigned char *p = s + begbyte, *start = p;
 
-  if (!CHAR_HEAD_P (*p))
-    abort ();
-
-  while (pos < end)
+  if (unibyte)
+    p = s + end;
+  else
     {
-      p += BYTES_BY_CHAR_HEAD (*p);
-      pos++;
+      if (!CHAR_HEAD_P (*p))
+       abort ();
+
+      while (pos < end)
+       {
+         p += BYTES_BY_CHAR_HEAD (*p);
+         pos++;
+       }
     }
 
   return p - start;
@@ -745,12 +751,18 @@ bidi_count_bytes (const unsigned char *s, const EMACS_INT beg,
 
 /* Fetch and returns the character at byte position BYTEPOS.  If S is
    non-NULL, fetch the character from string S; otherwise fetch the
-   character from the current buffer.  */
+   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)
+bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte)
 {
   if (s)
-    return STRING_CHAR (s + bytepos);
+    {
+      if (unibyte)
+       return s[bytepos];
+      else
+       return STRING_CHAR (s + bytepos);
+    }
   else
     return FETCH_MULTIBYTE_CHAR (bytepos);
 }
@@ -804,12 +816,14 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
       ch = 0xFFFC;
       disp_end_pos = compute_display_string_end (*disp_pos, string);
       *nchars = disp_end_pos - *disp_pos;
+      if (*nchars <= 0)
+       abort ();
       if (string->s)
        *ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos,
-                                   disp_end_pos);
+                                   disp_end_pos, string->unibyte);
       else if (STRINGP (string->lstring))
        *ch_len = bidi_count_bytes (SDATA (string->lstring), *disp_pos,
-                                   bytepos, disp_end_pos);
+                                   bytepos, disp_end_pos, string->unibyte);
       else
        *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos;
     }
@@ -819,15 +833,32 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
        {
          EMACS_INT len;
 
-         ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len);
-         *ch_len = len;
+         if (!string->unibyte)
+           {
+             ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len);
+             *ch_len = len;
+           }
+         else
+           {
+             ch = UNIBYTE_TO_CHAR (string->s[bytepos]);
+             *ch_len = 1;
+           }
        }
       else if (STRINGP (string->lstring))
        {
          EMACS_INT len;
 
-         ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos, len);
-         *ch_len = len;
+         if (!string->unibyte)
+           {
+             ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos,
+                                          len);
+             *ch_len = len;
+           }
+         else
+           {
+             ch = UNIBYTE_TO_CHAR (SREF (string->lstring, bytepos));
+             *ch_len = 1;
+           }
        }
       else
        {
@@ -971,7 +1002,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
       pos = bidi_it->charpos;
       s = STRINGP (bidi_it->string.lstring) ?
        SDATA (bidi_it->string.lstring) : bidi_it->string.s;
-      if (bytepos > begbyte && bidi_char_at_pos (bytepos, s) == '\n')
+      if (bytepos > begbyte
+         && bidi_char_at_pos (bytepos, s, bidi_it->string.unibyte) == '\n')
        {
          bytepos++;
          pos++;
@@ -1123,7 +1155,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
 
          if (bidi_it->charpos < 0)
            bidi_it->charpos = 0;
-         bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos);
+         bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos,
+                                              bidi_it->string.unibyte);
        }
       else
        {
@@ -1308,7 +1341,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
       && bidi_it->ignore_bn_limit == -1 /* only if not already known */
       && bidi_it->charpos < eob                /* not already at EOB */
       && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
-                                                  + bidi_it->ch_len, s)))
+                                                  + bidi_it->ch_len, s,
+                                                  bidi_it->string.unibyte)))
     {
       /* Avoid pushing and popping embedding levels if the level run
         is empty, as this breaks level runs where it shouldn't.
@@ -1321,7 +1355,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
       bidi_copy_it (&saved_it, bidi_it);
 
       while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
-                                                      + bidi_it->ch_len, s)))
+                                                      + bidi_it->ch_len, s,
+                                                      bidi_it->string.unibyte)))
        {
          /* This advances to the next character, skipping any
             characters covered by display strings.  */
@@ -1459,7 +1494,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
          next_char =
            bidi_it->charpos + bidi_it->nchars >= eob
            ? BIDI_EOB
-           : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
+           : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s,
+                               bidi_it->string.unibyte);
          type_of_next = bidi_get_type (next_char, override);
 
          if (type_of_next == WEAK_BN
@@ -1517,7 +1553,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
              next_char =
                bidi_it->charpos + bidi_it->nchars >= eob
                ? BIDI_EOB
-               : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
+               : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s,
+                                   bidi_it->string.unibyte);
              type_of_next = bidi_get_type (next_char, override);
 
              if (type_of_next == WEAK_ET
index 16fa3abdd19e2cf6ccc63ba22a2d8858b21a7a7b..9586edab63b403b1df9f6c5cd3c57e5aa012fa4c 100644 (file)
@@ -1821,6 +1821,7 @@ struct bidi_string_data {
   EMACS_INT bufpos;            /* buffer position of lstring, or 0 if N/A */
   unsigned from_disp_str : 1;  /* 1 means the string comes from a
                                   display property */
+  unsigned unibyte : 1;                /* 1 means the string is unibyte */
 };
 
 /* Data type for reordering bidirectional text.  */
index 3b934547471ba3029ca824f0363d2935194847dd..43913eb886eb2614bcdeedbf6498d5a2b6dfa077 100644 (file)
@@ -3113,8 +3113,9 @@ compute_display_string_pos (struct text_pos *position,
   Lisp_Object object =
     (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
   Lisp_Object pos, spec;
-  EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
-  EMACS_INT begb = STRINGP (object) ? 0 : BEGV;
+  int string_p = (string && (STRINGP (string->lstring) || string->s));
+  EMACS_INT eob = string_p ? string->schars : ZV;
+  EMACS_INT begb = string_p ? 0 : BEGV;
   EMACS_INT bufpos, charpos = CHARPOS (*position);
   struct text_pos tpos;
 
@@ -3175,7 +3176,8 @@ compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
   Lisp_Object object =
     (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
   Lisp_Object pos = make_number (charpos);
-  EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
+  EMACS_INT eob =
+    (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
 
   if (charpos >= eob || (string->s && !STRINGP (object)))
     return eob;
@@ -4496,19 +4498,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          it->paragraph_embedding =
            (it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
 
-         /* Do we need to reorder this display string?  */
-         if (it->multibyte_p)
-           {
-             if (BUFFERP (object))
-               it->bidi_p =
-                 !NILP (BVAR (XBUFFER (object), bidi_display_reordering));
-             else
-               it->bidi_p =
-                 !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
-           }
-         else
-           it->bidi_p = 0;
-
          /* Set up the bidi iterator for this display string.  */
          if (it->bidi_p)
            {
@@ -4517,6 +4506,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
              it->bidi_it.string.schars = it->end_charpos;
              it->bidi_it.string.bufpos = bufpos;
              it->bidi_it.string.from_disp_str = 1;
+             it->bidi_it.string.unibyte = !it->multibyte_p;
              bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
            }
        }
@@ -4873,11 +4863,6 @@ next_overlay_string (struct it *it)
       it->prev_stop = 0;
       it->base_level_stop = 0;
 
-      /* Do we need to reorder this overlay string?  */
-      it->bidi_p =
-       it->multibyte_p
-       && !NILP (BVAR (current_buffer, bidi_display_reordering));
-
       /* Set up the bidi iterator for this overlay string.  */
       if (it->bidi_p)
        {
@@ -4886,6 +4871,7 @@ next_overlay_string (struct it *it)
          it->bidi_it.string.schars = SCHARS (it->string);
          it->bidi_it.string.bufpos = it->overlay_strings_charpos;
          it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
          bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
        }
     }
@@ -5159,11 +5145,6 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       it->method = GET_FROM_STRING;
 
-      /* Do we need to reorder this overlay string?  */
-      it->bidi_p =
-       it->multibyte_p
-       && !NILP (BVAR (current_buffer, bidi_display_reordering));
-
       /* Force paragraph direction to be that of the parent
         buffer.  */
       it->paragraph_embedding = (it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
@@ -5178,6 +5159,7 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
          it->bidi_it.string.schars = SCHARS (it->string);
          it->bidi_it.string.bufpos = pos;
          it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
          bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
        }
       return 1;
@@ -5747,6 +5729,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
       it->bidi_it.string.bufpos = 0;
+      it->bidi_it.string.unibyte = 0;
     }
 
   if (set_stop_p)
@@ -5799,9 +5782,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
 
   /* Bidirectional reordering of strings is controlled by the default
      value of bidi-display-reordering.  */
-  it->bidi_p =
-    !NILP (BVAR (&buffer_defaults, bidi_display_reordering))
-    && it->multibyte_p;
+  it->bidi_p = !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
 
   if (s == NULL)
     {
@@ -5819,6 +5800,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
          it->bidi_it.string.schars = it->end_charpos;
          it->bidi_it.string.bufpos = 0;
          it->bidi_it.string.from_disp_str = 0;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
          bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
                        FRAME_WINDOW_P (it->f), &it->bidi_it);
        }
@@ -5835,25 +5817,24 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
        {
          it->current.pos = c_string_pos (charpos, s, 1);
          it->end_charpos = it->string_nchars = number_of_chars (s, 1);
-
-         if (it->bidi_p)
-           {
-             it->bidi_it.string.lstring = Qnil;
-             it->bidi_it.string.s = s;
-             it->bidi_it.string.schars = it->end_charpos;
-             it->bidi_it.string.bufpos = 0;
-             it->bidi_it.string.from_disp_str = 0;
-             bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
-                           &it->bidi_it);
-           }
        }
       else
        {
-         /* Unibyte (a.k.a. ASCII) C strings are never bidi-reordered.  */
          IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
          it->end_charpos = it->string_nchars = strlen (s);
        }
 
+      if (it->bidi_p)
+       {
+         it->bidi_it.string.lstring = Qnil;
+         it->bidi_it.string.s = s;
+         it->bidi_it.string.schars = it->end_charpos;
+         it->bidi_it.string.bufpos = 0;
+         it->bidi_it.string.from_disp_str = 0;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
+         bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
+                       &it->bidi_it);
+       }
       it->method = GET_FROM_C_STRING;
     }
 
@@ -17788,12 +17769,6 @@ push_display_prop (struct it *it, Lisp_Object prop)
         buffer.  */
       it->paragraph_embedding = (it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
 
-      /* Do we need to reorder this string?  */
-      if (it->multibyte_p)
-       it->bidi_p = !NILP (BVAR (current_buffer, bidi_display_reordering));
-      else
-       it->bidi_p = 0;
-
       /* Set up the bidi iterator for this display string.  */
       if (it->bidi_p)
        {
@@ -17802,6 +17777,7 @@ push_display_prop (struct it *it, Lisp_Object prop)
          it->bidi_it.string.schars = it->end_charpos;
          it->bidi_it.string.bufpos = IT_CHARPOS (*it);
          it->bidi_it.string.from_disp_str = 1;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
          bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
        }
     }