From b2eb6911dc8af51a5a9f8b7a011cf63c724d533b Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 18 Jan 2016 18:19:50 +0200 Subject: [PATCH] Fix scrolling under scroll-preserve-screen-position and margins * src/window.c (window_scroll_pixel_based): When setting point to preserve screen coordinates, don't let cursor enter either of the two scroll margins. Fix incorrect usage of WINDOW_WANTS_HEADER_LINE_P and use WINDOW_HEADER_LINE_HEIGHT instead of CURRENT_HEADER_LINE_HEIGHT. (Bug#22395) --- src/window.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/window.c b/src/window.c index bbe47c7255a..1a75342471f 100644 --- a/src/window.c +++ b/src/window.c @@ -4981,27 +4981,34 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) if (n > 0) { + int last_y = it.last_visible_y - this_scroll_margin - 1; + /* We moved the window start towards ZV, so PT may be now in the scroll margin at the top. */ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); - if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin + if (IT_CHARPOS (it) == PT + && it.current_y >= this_scroll_margin + && it.current_y <= last_y - WINDOW_HEADER_LINE_HEIGHT (w) && (NILP (Vscroll_preserve_screen_position) || EQ (Vscroll_preserve_screen_position, Qt))) /* We found PT at a legitimate height. Leave it alone. */ ; - else if (window_scroll_pixel_based_preserve_y >= 0) - { - /* If we have a header line, take account of it. - This is necessary because we set it.current_y to 0, above. */ - move_it_to (&it, -1, - window_scroll_pixel_based_preserve_x, - (window_scroll_pixel_based_preserve_y - - WINDOW_WANTS_HEADER_LINE_P (w)), - -1, MOVE_TO_Y | MOVE_TO_X); - SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); - } else { + if (window_scroll_pixel_based_preserve_y >= 0) + { + /* Don't enter the scroll margin at the end of the window. */ + int goal_y = min (last_y, window_scroll_pixel_based_preserve_y); + + /* If we have a header line, take account of it. This + is necessary because we set it.current_y to 0, above. */ + move_it_to (&it, -1, + window_scroll_pixel_based_preserve_x, + goal_y - WINDOW_HEADER_LINE_HEIGHT (w), + -1, MOVE_TO_Y | MOVE_TO_X); + } + + /* Get out of the scroll margin at the top of the window. */ while (it.current_y < this_scroll_margin) { int prev = it.current_y; @@ -5025,7 +5032,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) /* We moved the window start towards BEGV, so PT may be now in the scroll margin at the bottom. */ move_it_to (&it, PT, -1, - (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w) + (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w) - this_scroll_margin - 1), -1, MOVE_TO_POS | MOVE_TO_Y); @@ -5076,14 +5083,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) ; else if (window_scroll_pixel_based_preserve_y >= 0) { + int goal_y = min (it.last_visible_y - this_scroll_margin - 1, + window_scroll_pixel_based_preserve_y); + + /* Don't let the preserved screen Y coordinate put us inside + any of the two margins. */ + if (goal_y < this_scroll_margin) + goal_y = this_scroll_margin; SET_TEXT_POS_FROM_MARKER (start, w->start); start_display (&it, w, start); /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT here because we called start_display again and did not alter it.current_y this time. */ move_it_to (&it, -1, window_scroll_pixel_based_preserve_x, - window_scroll_pixel_based_preserve_y, -1, - MOVE_TO_Y | MOVE_TO_X); + goal_y, -1, MOVE_TO_Y | MOVE_TO_X); SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); } else -- 2.39.5