]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid annoying re-scroll when buffer has many overlay strings
authorEli Zaretskii <eliz@gnu.org>
Thu, 11 Aug 2016 15:04:42 +0000 (18:04 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 11 Aug 2016 15:04:42 +0000 (18:04 +0300)
* src/xdisp.c (redisplay_window): Add better recovery from a
situation where window-start is on buffer position which has a
before-string that includes newlines, with the result that point
is not visible in the window, because the display engine starts
displaying with the before-string.  (Bug#24179)

src/xdisp.c

index 21fc01f1e692d6dbf12ac444c2421034cd29b93d..a8376af978f9922532ee0173bd1acfd7c7aebb38 100644 (file)
@@ -16188,6 +16188,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   ptrdiff_t beg_unchanged, end_unchanged;
   int frame_line_height;
   bool use_desired_matrix;
+  void *itdata = NULL;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -16909,6 +16910,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Run scroll hooks.  */
   startp = run_window_scroll_functions (window, it.current.pos);
 
+  /* We invoke try_window and try_window_reusing_current_matrix below,
+     and they manipulate the bidi cache.  Save and restore the cache
+     state of our iterator, so we could continue using it after that.  */
+  itdata = bidi_shelve_cache ();
+
   /* Redisplay the window.  */
   use_desired_matrix = false;
   if (!current_matrix_up_to_date_p
@@ -16923,6 +16929,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
           = try_window_reusing_current_matrix (w)))
     use_desired_matrix = (try_window (window, startp, 0) == 1);
 
+  bidi_unshelve_cache (itdata, false);
+
   /* If new fonts have been loaded (due to fontsets), give up.  We
      have to start a new redisplay since we need to re-adjust glyph
      matrices.  */
@@ -16948,6 +16956,26 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
          move_it_by_lines (&it, -1);
          try_window (window, it.current.pos, 0);
        }
+      else if (scroll_conservatively > SCROLL_LIMIT
+              && it.method == GET_FROM_STRING
+              && IT_CHARPOS (it) < ZV)
+       {
+         /* If the window starts with a before-string that spans more
+            than one screen line, using that position to display the
+            window might fail to bring point into the view, because
+            start_display will always start by displaying the string,
+            whereas the code above determines where to set w->start
+            by the buffer position of the place where it takes screen
+            coordinates.  Try to recover by finding the next screen
+            line that displays buffer text.  */
+         ptrdiff_t pos0 = IT_CHARPOS (it);
+
+         clear_glyph_matrix (w->desired_matrix);
+         do {
+           move_it_by_lines (&it, 1);
+         } while (IT_CHARPOS (it) == pos0 && it.method == GET_FROM_STRING);
+         try_window (window, it.current.pos, 0);
+       }
       else
        {
          /* Not much we can do about it.  */