emacs-diffs
[Top][All Lists]
Advanced

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

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


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r105941: Fix bug #9610 with slow cursor motion in buffers with invisible text.
Date: Tue, 27 Sep 2011 20:18:31 +0300
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 105941
fixes bug(s): http://debbugs.gnu.org/9610
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Tue 2011-09-27 20:18:31 +0300
message:
  Fix bug #9610 with slow cursor motion in buffers with invisible text.
  
   src/xdisp.c (handle_invisible_prop): If invisible text ends on a
   newline, reseat the iterator instead of bidi-iterating there one
   character at a time.  (Bug#9610)
   (BUFFER_POS_REACHED_P, move_it_in_display_line_to): Bail when past
   TO_CHARPOS if the bidi iterator is at base embedding level.
modified:
  src/ChangeLog
  src/xdisp.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-09-27 08:37:07 +0000
+++ b/src/ChangeLog     2011-09-27 17:18:31 +0000
@@ -1,3 +1,11 @@
+2011-09-27  Eli Zaretskii  <address@hidden>
+
+       * xdisp.c (handle_invisible_prop): If invisible text ends on a
+       newline, reseat the iterator instead of bidi-iterating there one
+       character at a time.  (Bug#9610)
+       (BUFFER_POS_REACHED_P, move_it_in_display_line_to): Bail when past
+       TO_CHARPOS if the bidi iterator is at base embedding level.
+
 2011-09-27  Andreas Schwab  <address@hidden>
 
        * lread.c (readevalloop): Use correct code for NBSP.

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2011-09-24 16:28:25 +0000
+++ b/src/xdisp.c       2011-09-27 17:18:31 +0000
@@ -4056,40 +4056,67 @@
          /* The position newpos is now either ZV or on visible text.  */
          if (it->bidi_p && newpos < ZV)
            {
-             /* With bidi iteration, the region of invisible text
-                could start and/or end in the middle of a non-base
-                embedding level.  Therefore, we need to skip
-                invisible text using the bidi iterator, starting at
-                IT's current position, until we find ourselves
-                outside the invisible text.  Skipping invisible text
-                _after_ bidi iteration avoids affecting the visual
-                order of the displayed text when invisible properties
-                are added or removed.  */
-             if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
-               {
-                 /* If we were `reseat'ed to a new paragraph,
-                    determine the paragraph base direction.  We need
-                    to do it now because next_element_from_buffer may
-                    not have a chance to do it, if we are going to
-                    skip any text at the beginning, which resets the
-                    FIRST_ELT flag.  */
-                 bidi_paragraph_init (it->paragraph_embedding,
-                                      &it->bidi_it, 1);
-               }
-             do
-               {
-                 bidi_move_to_visually_next (&it->bidi_it);
-               }
-             while (it->stop_charpos <= it->bidi_it.charpos
-                    && it->bidi_it.charpos < newpos);
-             IT_CHARPOS (*it) = it->bidi_it.charpos;
-             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
-             /* If we overstepped NEWPOS, record its position in the
-                iterator, so that we skip invisible text if later the
-                bidi iteration lands us in the invisible region
-                again. */
-             if (IT_CHARPOS (*it) >= newpos)
-               it->prev_stop = newpos;
+             EMACS_INT bpos = CHAR_TO_BYTE (newpos);
+
+             if (FETCH_BYTE (bpos) == '\n'
+                 || (newpos > BEGV && FETCH_BYTE (bpos - 1) == '\n'))
+               {
+                 /* If the invisible text ends on a newline or the
+                    character after a newline, we can avoid the
+                    costly, character by character, bidi iteration to
+                    newpos, and instead simply reseat the iterator
+                    there.  That's because all bidi reordering
+                    information is tossed at the newline.  This is a
+                    big win for modes that hide complete lines, like
+                    Outline, Org, etc.  (Implementation note: the
+                    call to reseat_1 is necessary, because it signals
+                    to the bidi iterator that it needs to reinit its
+                    internal information when the next element for
+                    display is requested.  */
+                 struct text_pos tpos;
+
+                 SET_TEXT_POS (tpos, newpos, bpos);
+                 reseat_1 (it, tpos, 0);
+               }
+             else      /* Must use the slow method.  */
+               {
+                 /* With bidi iteration, the region of invisible text
+                    could start and/or end in the middle of a
+                    non-base embedding level.  Therefore, we need to
+                    skip invisible text using the bidi iterator,
+                    starting at IT's current position, until we find
+                    ourselves outside the invisible text.  Skipping
+                    invisible text _after_ bidi iteration avoids
+                    affecting the visual order of the displayed text
+                    when invisible properties are added or
+                    removed.  */
+                 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+                   {
+                     /* If we were `reseat'ed to a new paragraph,
+                        determine the paragraph base direction.  We
+                        need to do it now because
+                        next_element_from_buffer may not have a
+                        chance to do it, if we are going to skip any
+                        text at the beginning, which resets the
+                        FIRST_ELT flag.  */
+                     bidi_paragraph_init (it->paragraph_embedding,
+                                          &it->bidi_it, 1);
+                   }
+                 do
+                   {
+                     bidi_move_to_visually_next (&it->bidi_it);
+                   }
+                 while (it->stop_charpos <= it->bidi_it.charpos
+                        && it->bidi_it.charpos < newpos);
+                 IT_CHARPOS (*it) = it->bidi_it.charpos;
+                 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+                 /* If we overstepped NEWPOS, record its position in
+                    the iterator, so that we skip invisible text if
+                    later the bidi iteration lands us in the
+                    invisible region again. */
+                 if (IT_CHARPOS (*it) >= newpos)
+                   it->prev_stop = newpos;
+               }
            }
          else
            {
@@ -7880,7 +7907,9 @@
   ((op & MOVE_TO_POS) != 0                                     \
    && BUFFERP (it->object)                                     \
    && (IT_CHARPOS (*it) == to_charpos                          \
-       || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos)       \
+       || ((!it->bidi_p                                                \
+           || BIDI_AT_BASE_LEVEL (it->bidi_it))                \
+          && IT_CHARPOS (*it) > to_charpos)                    \
        || (it->what == IT_COMPOSITION                          \
           && ((IT_CHARPOS (*it) > to_charpos                   \
                && to_charpos >= it->cmp_it.charpos)            \
@@ -7912,7 +7941,13 @@
       if ((op & MOVE_TO_POS) != 0
          && BUFFERP (it->object)
          && it->method == GET_FROM_BUFFER
-         && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos)
+         && (((!it->bidi_p
+               /* When the iterator is at base embedding level, we
+                  are guaranteed that characters are delivered for
+                  display in strictly increasing order of their
+                  buffer positions.  */
+               || BIDI_AT_BASE_LEVEL (it->bidi_it))
+              && IT_CHARPOS (*it) > to_charpos)
              || (it->bidi_p
                  && (prev_method == GET_FROM_IMAGE
                      || prev_method == GET_FROM_STRETCH


reply via email to

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