From 2e0a2b376f51dd515ffeb6449181cc37fe912f5e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 11 Aug 2016 18:04:42 +0300 Subject: [PATCH] Avoid annoying re-scroll when buffer has many overlay strings * 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 | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/xdisp.c b/src/xdisp.c index 21fc01f1e69..a8376af978f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -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. */ -- 2.39.2