emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r105387: Fix bug #9218 with slow curs


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r105387: Fix bug #9218 with slow cursor motion and scrolling Org Mode buffers.
Date: Tue, 02 Aug 2011 22:16:32 +0300
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 105387
fixes bug(s): http://debbugs.gnu.org/9218
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Tue 2011-08-02 22:16:32 +0300
message:
  Fix bug #9218 with slow cursor motion and scrolling Org Mode buffers.
  
   src/dispextern.h (struct bidi_it): New member disp_prop_p.
   src/xdisp.c: Remove one-slot cache of display string positions.
   (compute_display_string_pos): Accept an additional argument
   DISP_PROP_P; callers changed. Scan at most 5K characters forward
   for a display string or property.  If found, set DISP_PROP_P
   non-zero.
   src/bidi.c (bidi_fetch_char): Accept an additional argument
   DISP_PROP_P, and pass it to compute_display_string_pos.  Only
   handle text covered by a display string if DISP_PROP_P is returned
   non-zero.  All callers of bidi_fetch_char changed.
modified:
  src/ChangeLog
  src/bidi.c
  src/dispextern.h
  src/xdisp.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-08-02 16:02:52 +0000
+++ b/src/ChangeLog     2011-08-02 19:16:32 +0000
@@ -1,3 +1,21 @@
+2011-08-02  Eli Zaretskii  <address@hidden>
+
+       Fix slow cursor motion and scrolling in large buffers with
+       selective display, like Org Mode buffers.  (Bug#9218)
+
+       * dispextern.h (struct bidi_it): New member disp_prop_p.
+
+       * xdisp.c: Remove one-slot cache of display string positions.
+       (compute_display_string_pos): Accept an additional argument
+       DISP_PROP_P; callers changed. Scan at most 5K characters forward
+       for a display string or property.  If found, set DISP_PROP_P
+       non-zero.
+
+       * bidi.c (bidi_fetch_char): Accept an additional argument
+       DISP_PROP_P, and pass it to compute_display_string_pos.  Only
+       handle text covered by a display string if DISP_PROP_P is returned
+       non-zero.  All callers of bidi_fetch_char changed.
+
 2011-08-02  Stefan Monnier  <address@hidden>
 
        * keymap.c (Fdefine_key): Fix Lisp_Object/int mixup; apply some CSE.

=== modified file 'src/bidi.c'
--- a/src/bidi.c        2011-07-28 00:24:58 +0000
+++ b/src/bidi.c        2011-08-02 19:16:32 +0000
@@ -792,6 +792,7 @@
     bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
   bidi_it->sor = L2R;   /* FIXME: should it be user-selectable? */
   bidi_it->disp_pos = -1;      /* invalid/unknown */
+  bidi_it->disp_prop_p = 0;
   /* We can only shrink the cache if we are at the bottom level of its
      "stack".  */
   if (bidi_cache_start == 0)
@@ -874,14 +875,16 @@
    covered characters as a single character u+FFFC, and return their
    combined length in CH_LEN and NCHARS.  DISP_POS specifies the
    character position of the next display string, or -1 if not yet
-   computed.  When the next character is at or beyond that position,
-   the function updates DISP_POS with the position of the next display
-   string.  STRING->s is the C string to iterate, or NULL if iterating
-   over a buffer or a Lisp string; in the latter case, STRING->lstring
-   is the Lisp string.  */
+   computed.  DISP_PROP_P non-zero means that there's really a display
+   string at DISP_POS, as opposed to when we searched till DISP_POS
+   without findingone.  When the next character is at or beyond that
+   position, the function updates DISP_POS with the position of the
+   next display string.  STRING->s is the C 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,
-                struct bidi_string_data *string,
+                int *disp_prop_p, struct bidi_string_data *string,
                 int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars)
 {
   int ch;
@@ -894,7 +897,8 @@
   if (charpos < endpos && charpos > *disp_pos)
     {
       SET_TEXT_POS (pos, charpos, bytepos);
-      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p);
+      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
+                                             disp_prop_p);
     }
 
   /* Fetch the character at BYTEPOS.  */
@@ -904,8 +908,9 @@
       *ch_len = 1;
       *nchars = 1;
       *disp_pos = endpos;
+      *disp_prop_p = 0;
     }
-  else if (charpos >= *disp_pos)
+  else if (charpos >= *disp_pos && *disp_prop_p)
     {
       EMACS_INT disp_end_pos;
 
@@ -972,10 +977,12 @@
 
   /* If we just entered a run of characters covered by a display
      string, compute the position of the next display string.  */
-  if (charpos + *nchars <= endpos && charpos + *nchars > *disp_pos)
+  if (charpos + *nchars <= endpos && charpos + *nchars > *disp_pos
+      && *disp_prop_p)
     {
       SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len);
-      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p);
+      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
+                                             disp_prop_p);
     }
 
   return ch;
@@ -1083,6 +1090,7 @@
       int ch;
       EMACS_INT ch_len, nchars;
       EMACS_INT pos, disp_pos = -1;
+      int disp_prop_p = 0;
       bidi_type_t type;
       const unsigned char *s;
 
@@ -1130,7 +1138,8 @@
        bytepos = pstartbyte;
        if (!string_p)
          pos = BYTE_TO_CHAR (bytepos);
-       ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string,
+       ch = bidi_fetch_char (bytepos, pos, &disp_pos, &disp_prop_p,
+                             &bidi_it->string,
                              bidi_it->frame_window_p, &ch_len, &nchars);
        type = bidi_get_type (ch, NEUTRAL_DIR);
 
@@ -1157,7 +1166,8 @@
                && bidi_at_paragraph_end (pos, bytepos) >= -1)
              break;
            /* Fetch next character and advance to get past it.  */
-           ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string,
+           ch = bidi_fetch_char (bytepos, pos, &disp_pos,
+                                 &disp_prop_p, &bidi_it->string,
                                  bidi_it->frame_window_p, &ch_len, &nchars);
            pos += nchars;
            bytepos += ch_len;
@@ -1290,6 +1300,7 @@
       bidi_it->ch_len = 1;
       bidi_it->nchars = 1;
       bidi_it->disp_pos = (string_p ? bidi_it->string.schars : ZV);
+      bidi_it->disp_prop_p = 0;
     }
   else
     {
@@ -1297,8 +1308,8 @@
         display string, treat the entire run of covered characters as
         a single character u+FFFC.  */
       curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos,
-                                &bidi_it->disp_pos, &bidi_it->string,
-                                bidi_it->frame_window_p,
+                                &bidi_it->disp_pos, &bidi_it->disp_prop_p,
+                                &bidi_it->string, bidi_it->frame_window_p,
                                 &bidi_it->ch_len, &bidi_it->nchars);
     }
   bidi_it->ch = curchar;
@@ -2032,12 +2043,13 @@
       struct bidi_string_data bs = bidi_it->string;
       bidi_type_t chtype;
       int fwp = bidi_it->frame_window_p;
+      int dpp = bidi_it->disp_prop_p;
 
       if (bidi_it->nchars <= 0)
        abort ();
       do {
-       ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &bs, fwp,
-                             &clen, &nc);
+       ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs,
+                             fwp, &clen, &nc);
        if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */)
          chtype = NEUTRAL_B;
        else

=== modified file 'src/dispextern.h'
--- a/src/dispextern.h  2011-07-14 17:28:42 +0000
+++ b/src/dispextern.h  2011-08-02 19:16:32 +0000
@@ -1868,6 +1868,8 @@
   bidi_dir_t paragraph_dir;    /* current paragraph direction */
   EMACS_INT separator_limit;   /* where paragraph separator should end */
   EMACS_INT disp_pos;          /* position of display string after ch */
+  int disp_prop_p;             /* if non-zero, there really is a
+                                  `display' property/string at disp_pos */
   unsigned first_elt : 1;      /* if non-zero, examine current char first */
   unsigned new_paragraph : 1;  /* if non-zero, we expect a new paragraph */
   unsigned frame_window_p : 1; /* non-zero if displaying on a GUI frame */
@@ -3035,7 +3037,8 @@
 extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
                                        struct font *, int, int *);
 extern EMACS_INT compute_display_string_pos (struct text_pos *,
-                                            struct bidi_string_data *, int);
+                                            struct bidi_string_data *,
+                                            int, int *);
 extern EMACS_INT compute_display_string_end (EMACS_INT,
                                             struct bidi_string_data *);
 

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2011-08-01 17:59:35 +0000
+++ b/src/xdisp.c       2011-08-02 19:16:32 +0000
@@ -3134,13 +3134,10 @@
   return endpos;
 }
 
-/* Record one cached display string position found recently by
-   compute_display_string_pos.  */
-static EMACS_INT cached_disp_pos;
-static EMACS_INT cached_prev_pos = -1;
-static struct buffer *cached_disp_buffer;
-static int cached_disp_modiff;
-static int cached_disp_overlay_modiff;
+/* How many characters forward to search for a display property or
+   display string.  Enough for a screenful of 100 lines x 50
+   characters in a line.  */
+#define MAX_DISP_SCAN 5000
 
 /* Return the character position of a display string at or after
    position specified by POSITION.  If no display string exists at or
@@ -3152,57 +3149,33 @@
    on a GUI frame.  */
 EMACS_INT
 compute_display_string_pos (struct text_pos *position,
-                           struct bidi_string_data *string, int frame_window_p)
+                           struct bidi_string_data *string,
+                           int frame_window_p, int *disp_prop_p)
 {
   /* OBJECT = nil means current buffer.  */
   Lisp_Object object =
     (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
-  Lisp_Object pos, spec;
+  Lisp_Object pos, spec, limpos;
   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);
+  EMACS_INT lim =
+    (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
   struct text_pos tpos;
   struct buffer *b;
 
+  *disp_prop_p = 1;
+
   if (charpos >= eob
       /* We don't support display properties whose values are strings
         that have display string properties.  */
       || string->from_disp_str
       /* C strings cannot have display properties.  */
       || (string->s && !STRINGP (object)))
-    return eob;
-
-  /* Check the cached values.  */
-  if (!STRINGP (object))
     {
-      if (NILP (object))
-       b = current_buffer;
-      else
-       b = XBUFFER (object);
-      if (b == cached_disp_buffer
-         && BUF_MODIFF (b) == cached_disp_modiff
-         && BUF_OVERLAY_MODIFF (b) == cached_disp_overlay_modiff
-         && !b->clip_changed)
-       {
-         if (cached_prev_pos >= 0
-             && cached_prev_pos < charpos && charpos <= cached_disp_pos)
-           return cached_disp_pos;
-         /* Handle overstepping either end of the known interval.  */
-         if (charpos > cached_disp_pos)
-           cached_prev_pos = cached_disp_pos;
-         else  /* charpos <= cached_prev_pos */
-           cached_prev_pos = max (charpos - 1, 0);
-       }
-
-      /* Record new values in the cache.  */
-      if (b != cached_disp_buffer)
-       {
-         cached_disp_buffer = b;
-         cached_prev_pos = max (charpos - 1, 0);
-       }
-      cached_disp_modiff = BUF_MODIFF (b);
-      cached_disp_overlay_modiff = BUF_OVERLAY_MODIFF (b);
+      *disp_prop_p = 0;
+      return eob;
     }
 
   /* If the character at CHARPOS is where the display string begins,
@@ -3221,22 +3194,24 @@
       && handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos,
                              frame_window_p))
     {
-      if (!STRINGP (object))
-       cached_disp_pos = charpos;
       return charpos;
     }
 
   /* Look forward for the first character with a `display' property
      that will replace the underlying text when displayed.  */
+  limpos = make_number (lim);
   do {
-    pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
+    pos = Fnext_single_char_property_change (pos, Qdisplay, object, limpos);
     CHARPOS (tpos) = XFASTINT (pos);
+    if (CHARPOS (tpos) >= lim)
+      {
+       *disp_prop_p = 0;
+       break;
+      }
     if (STRINGP (object))
       BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
     else
       BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
-    if (CHARPOS (tpos) >= eob)
-      break;
     spec = Fget_char_property (pos, Qdisplay, object);
     if (!STRINGP (object))
       bufpos = CHARPOS (tpos);
@@ -3244,8 +3219,6 @@
           || !handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos,
                                    frame_window_p));
 
-  if (!STRINGP (object))
-    cached_disp_pos = CHARPOS (tpos);
   return CHARPOS (tpos);
 }
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]