Fix bug #9624 with crashes in Muse mode.
authorEli Zaretskii <eliz@gnu.org>
Wed, 28 Sep 2011 14:37:27 +0000 (17:37 +0300)
committerEli Zaretskii <eliz@gnu.org>
Wed, 28 Sep 2011 14:37:27 +0000 (17:37 +0300)
 src/xdisp.c (compute_display_string_end): If there's no display
 string at CHARPOS, return -1.
 src/bidi.c (bidi_fetch_char): When compute_display_string_end
 returns a negative value, treat the character as a normal
 character not covered by a display string.

src/ChangeLog
src/bidi.c
src/xdisp.c

index c6a321d..f26754d 100644 (file)
@@ -1,3 +1,12 @@
+2011-09-28  Eli Zaretskii  <eliz@gnu.org>
+
+       * xdisp.c (compute_display_string_end): If there's no display
+       string at CHARPOS, return -1.
+
+       * bidi.c (bidi_fetch_char): When compute_display_string_end
+       returns a negative value, treat the character as a normal
+       character not covered by a display string.  (Bug#9624)
+
 2011-09-28  Juanma Barranquero  <lekktu@gmail.com>
 
        * lread.c (Fread_from_string): Fix typo in docstring.
index 599c004..e3fc03f 100644 (file)
@@ -974,6 +974,15 @@ 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);
+      if (disp_end_pos < 0)
+       {
+         /* Somebody removed the display string from the buffer
+            behind our back.  Recover by processing this buffer
+            position as if no display property were present there to
+            begin with.  */
+         *disp_prop = 0;
+         goto normal_char;
+       }
       *nchars = disp_end_pos - *disp_pos;
       if (*nchars <= 0)
        abort ();
@@ -988,6 +997,7 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
     }
   else
     {
+    normal_char:
       if (string->s)
        {
          int len;
index 75f266f..a072ff2 100644 (file)
@@ -3386,9 +3386,10 @@ compute_display_string_pos (struct text_pos *position,
 }
 
 /* Return the character position of the end of the display string that
-   started at CHARPOS.  A display string is either an overlay with
-   `display' property whose value is a string or a `display' text
-   property whose value is a string.  */
+   started at CHARPOS.  If there's no display string at CHARPOS,
+   return -1.  A display string is either an overlay with `display'
+   property whose value is a string or a `display' text property whose
+   value is a string.  */
 EMACS_INT
 compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
 {
@@ -3402,8 +3403,22 @@ compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
   if (charpos >= eob || (string->s && !STRINGP (object)))
     return eob;
 
+  /* It could happen that the display property or overlay was removed
+     since we found it in compute_display_string_pos above.  One way
+     this can happen is if JIT font-lock was called (through
+     handle_fontified_prop), and jit-lock-functions remove text
+     properties or overlays from the portion of buffer that includes
+     CHARPOS.  Muse mode is known to do that, for example.  In this
+     case, we return -1 to the caller, to signal that no display
+     string is actually present at CHARPOS.  See bidi_fetch_char for
+     how this is handled.
+
+     An alternative would be to never look for display properties past
+     it->stop_charpos.  But neither compute_display_string_pos nor
+     bidi_fetch_char that calls it know or care where the next
+     stop_charpos is.  */
   if (NILP (Fget_char_property (pos, Qdisplay, object)))
-    abort ();
+    return -1;
 
   /* Look forward for the first character where the `display' property
      changes.  */