]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bug #17244 with line-move-visual when display string covers a lot of text.
authorEli Zaretskii <eliz@gnu.org>
Sat, 12 Apr 2014 11:21:47 +0000 (14:21 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 12 Apr 2014 11:21:47 +0000 (14:21 +0300)
 src/xdisp.c (move_it_by_lines): If a large portion of buffer text is
 covered by a display string that ends in a newline, and that cases
 going back by DVPOS lines to hit the search limit, lift the limit
 and go back until DVPOS is reached.
 src/indent.c (Fvertical_motion): Handle correctly the case when the
 display string is preceded by an empty line.

src/ChangeLog
src/indent.c
src/xdisp.c

index 22f25bef6f33f34e2b6395181da472d72735dd82..cb17738d13946811d52a7613c5ac63c89d48c38e 100644 (file)
@@ -1,3 +1,13 @@
+2014-04-12  Eli Zaretskii  <eliz@gnu.org>
+
+       * xdisp.c (move_it_by_lines): If a large portion of buffer text is
+       covered by a display string that ends in a newline, and that cases
+       going back by DVPOS lines to hit the search limit, lift the limit
+       and go back until DVPOS is reached.  (Bug#17244)
+
+       * indent.c (Fvertical_motion): Handle correctly the case when the
+       display string is preceded by an empty line.
+
 2014-04-11  Eli Zaretskii  <eliz@gnu.org>
 
        * w32.c (sys_umask) <WRITE_USER>: Remove redundant constant, and
index 683d44841b98ed90777f187bed1fedac88094c45..dc862518924ebd723cc0c00a67ab112dd13ce99a 100644 (file)
@@ -2051,8 +2051,15 @@ whether or not it is currently displayed in some window.  */)
           string, move_it_to will overshoot it, while vertical-motion
           wants to put the cursor _before_ the display string.  So in
           that case, we move to buffer position before the display
-          string, and avoid overshooting.  */
-       move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT,
+          string, and avoid overshooting.  But if the position before
+          the display string is a newline, we don't do this, because
+          otherwise we will end up in a screen line that is one too
+          far back.  */
+       move_it_to (&it,
+                   (!disp_string_at_start_p
+                    || FETCH_BYTE (IT_BYTEPOS (it)) == '\n')
+                   ? PT
+                   : PT - 1,
                    -1, -1, -1, MOVE_TO_POS);
 
       /* IT may move too far if truncate-lines is on and PT lies
index 53bd46328f2674a10d660bc69d030543559383e6..eb3a6df1fc5afce394ebf13b89aba92e3da0f06c 100644 (file)
@@ -9511,6 +9511,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
       ptrdiff_t start_charpos, i;
       int nchars_per_row
        = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+      bool hit_pos_limit = false;
       ptrdiff_t pos_limit;
 
       /* Start at the beginning of the screen line containing IT's
@@ -9527,8 +9528,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
        pos_limit = BEGV;
       else
        pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+
       for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
        back_to_previous_visible_line_start (it);
+      if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
+       hit_pos_limit = true;
       reseat (it, it->current.pos, 1);
 
       /* Move further back if we end up in a string or an image.  */
@@ -9572,6 +9576,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
          else
            bidi_unshelve_cache (it2data, 1);
        }
+      else if (hit_pos_limit && pos_limit > BEGV
+              && dvpos < 0 && it2.vpos < -dvpos)
+       {
+         /* If we hit the limit, but still didn't make it far enough
+            back, that means there's a display string with a newline
+            covering a large chunk of text, and that caused
+            back_to_previous_visible_line_start try to go too far.
+            Punish those who commit such atrocities by going back
+            until we've reached DVPOS, after lifting the limit, which
+            could make it slow for very long lines.  "If it hurts,
+            don't do that!"  */
+         dvpos += it2.vpos;
+         RESTORE_IT (it, it, it2data);
+         for (i = -dvpos; i > 0; --i)
+           {
+             back_to_previous_visible_line_start (it);
+             it->vpos--;
+           }
+       }
       else
        RESTORE_IT (it, it, it2data);
     }