aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-03-31 21:12:30 +0200
committerEli Zaretskii2011-03-31 21:12:30 +0200
commit63696a737c9c28f203e1e4f8c73f8a765486543f (patch)
tree52953c1f938dc657c5bc4023df7efcb6f58721b5 /src
parentc82b2579f0d0abc7cfe75f9f29bc2c7010473878 (diff)
parent09725d2628e9b8a796d128d24e7255a57c2424f3 (diff)
downloademacs-63696a737c9c28f203e1e4f8c73f8a765486543f.tar.gz
emacs-63696a737c9c28f203e1e4f8c73f8a765486543f.zip
Fix bug #6671 with recentering and other scrolling problems.
src/xdisp.c (SCROLL_LIMIT): New macro. (try_scrolling): Use it when setting scroll_limit. Limit scrolling to 100 screen lines. (redisplay_window): Even when falling back on "recentering", position point in the window according to scroll-conservatively, scroll-margin, and scroll-*-aggressively variables. (try_scrolling): When point is above the window, allow searching as far as scroll_max, or one screenful, to compute vertical distance from PT to the scroll margin position. This prevents try_scrolling from unnecessarily failing when scroll-conservatively is set to a value slightly larger than the window height. Clean up the case of PT below the margin at bottom of window: scroll_max can no longer be INT_MAX. When aggressive scrolling is in use, don't let point enter the opposite scroll margin as result of the scroll. (syms_of_xdisp) <scroll-conservatively>: Document the threshold of 100 lines for never-recentering scrolling. doc/emacs/display.texi (Auto Scrolling): Document the limit of 100 lines for never-recentering scrolling with `scroll-conservatively'.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog31
-rw-r--r--src/xdisp.c140
2 files changed, 140 insertions, 31 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c168a7133eb..98589b69cfb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,29 @@
12011-03-31 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (SCROLL_LIMIT): New macro.
4 (try_scrolling): Use it when setting scroll_limit. Limit
5 scrolling to 100 screen lines.
6 (redisplay_window): Even when falling back on "recentering",
7 position point in the window according to scroll-conservatively,
8 scroll-margin, and scroll-*-aggressively variables. (Bug#6671)
9
10 (try_scrolling): When point is above the window, allow searching
11 as far as scroll_max, or one screenful, to compute vertical
12 distance from PT to the scroll margin position. This prevents
13 try_scrolling from unnecessarily failing when
14 scroll-conservatively is set to a value slightly larger than the
15 window height. Clean up the case of PT below the margin at bottom
16 of window: scroll_max can no longer be INT_MAX. When aggressive
17 scrolling is in use, don't let point enter the opposite scroll
18 margin as result of the scroll.
19 (syms_of_xdisp) <scroll-conservatively>: Document the
20 threshold of 100 lines for never-recentering scrolling.
21
222011-03-26 Eli Zaretskii <eliz@gnu.org>
23
24 * xdisp.c (redisplay_window): Don't check buffer's clip_changed
25 flag as a prerequisite for invoking try_scrolling. (Bug#6671)
26
12011-03-31 Juanma Barranquero <lekktu@gmail.com> 272011-03-31 Juanma Barranquero <lekktu@gmail.com>
2 28
3 * dispextern.h (move_it_by_lines): 29 * dispextern.h (move_it_by_lines):
@@ -184,11 +210,6 @@
184 * s/usg5-4-common.h (SIGTYPE): Remove definition. 210 * s/usg5-4-common.h (SIGTYPE): Remove definition.
185 * s/template.h (SIGTYPE): Remove commented out definition. 211 * s/template.h (SIGTYPE): Remove commented out definition.
186 212
1872011-03-26 Eli Zaretskii <eliz@gnu.org>
188
189 * xdisp.c (redisplay_window): Don't check buffer's clip_changed
190 flag as a prerequisite for invoking try_scrolling. (Bug#6671)
191
1922011-03-26 Juanma Barranquero <lekktu@gmail.com> 2132011-03-26 Juanma Barranquero <lekktu@gmail.com>
193 214
194 * w32.c (read_unc_volume): Use parameter `henum', instead of 215 * w32.c (read_unc_volume): Use parameter `henum', instead of
diff --git a/src/xdisp.c b/src/xdisp.c
index 0ed8ec46cf4..4b5835a322a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12992,6 +12992,12 @@ enum
12992 SCROLLING_NEED_LARGER_MATRICES 12992 SCROLLING_NEED_LARGER_MATRICES
12993}; 12993};
12994 12994
12995/* If scroll-conservatively is more than this, never recenter.
12996
12997 If you change this, don't forget to update the doc string of
12998 `scroll-conservatively' and the Emacs manual. */
12999#define SCROLL_LIMIT 100
13000
12995static int 13001static int
12996try_scrolling (Lisp_Object window, int just_this_one_p, 13002try_scrolling (Lisp_Object window, int just_this_one_p,
12997 EMACS_INT arg_scroll_conservatively, EMACS_INT scroll_step, 13003 EMACS_INT arg_scroll_conservatively, EMACS_INT scroll_step,
@@ -13005,7 +13011,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13005 int dy = 0, amount_to_scroll = 0, scroll_down_p = 0; 13011 int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
13006 int extra_scroll_margin_lines = last_line_misfit ? 1 : 0; 13012 int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
13007 Lisp_Object aggressive; 13013 Lisp_Object aggressive;
13008 int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f); 13014 /* We will never try scrolling more than this number of lines. */
13015 int scroll_limit = SCROLL_LIMIT;
13009 13016
13010#if GLYPH_DEBUG 13017#if GLYPH_DEBUG
13011 debug_method_add (w, "try_scrolling"); 13018 debug_method_add (w, "try_scrolling");
@@ -13021,14 +13028,14 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13021 else 13028 else
13022 this_scroll_margin = 0; 13029 this_scroll_margin = 0;
13023 13030
13024 /* Force arg_scroll_conservatively to have a reasonable value, to avoid 13031 /* Force arg_scroll_conservatively to have a reasonable value, to
13025 overflow while computing how much to scroll. Note that the user 13032 avoid scrolling too far away with slow move_it_* functions. Note
13026 can supply scroll-conservatively equal to `most-positive-fixnum', 13033 that the user can supply scroll-conservatively equal to
13027 which can be larger than INT_MAX. */ 13034 `most-positive-fixnum', which can be larger than INT_MAX. */
13028 if (arg_scroll_conservatively > scroll_limit) 13035 if (arg_scroll_conservatively > scroll_limit)
13029 { 13036 {
13030 arg_scroll_conservatively = scroll_limit; 13037 arg_scroll_conservatively = scroll_limit + 1;
13031 scroll_max = INT_MAX; 13038 scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f);
13032 } 13039 }
13033 else if (scroll_step || arg_scroll_conservatively || temp_scroll_step) 13040 else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
13034 /* Compute how much we should try to scroll maximally to bring 13041 /* Compute how much we should try to scroll maximally to bring
@@ -13065,13 +13072,10 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13065 /* Compute how many pixels below window bottom to stop searching 13072 /* Compute how many pixels below window bottom to stop searching
13066 for PT. This avoids costly search for PT that is far away if 13073 for PT. This avoids costly search for PT that is far away if
13067 the user limited scrolling by a small number of lines, but 13074 the user limited scrolling by a small number of lines, but
13068 always finds PT if arg_scroll_conservatively is set to a large 13075 always finds PT if scroll_conservatively is set to a large
13069 number, such as most-positive-fixnum. */ 13076 number, such as most-positive-fixnum. */
13070 int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)); 13077 int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
13071 int y_to_move = 13078 int y_to_move = it.last_visible_y + slack;
13072 slack >= INT_MAX - it.last_visible_y
13073 ? INT_MAX
13074 : it.last_visible_y + slack;
13075 13079
13076 /* Compute the distance from the scroll margin to PT or to 13080 /* Compute the distance from the scroll margin to PT or to
13077 the scroll limit, whichever comes first. This should 13081 the scroll limit, whichever comes first. This should
@@ -13110,6 +13114,10 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13110 amount_to_scroll = float_amount; 13114 amount_to_scroll = float_amount;
13111 if (amount_to_scroll == 0 && float_amount > 0) 13115 if (amount_to_scroll == 0 && float_amount > 0)
13112 amount_to_scroll = 1; 13116 amount_to_scroll = 1;
13117 /* Don't let point enter the scroll margin near top of
13118 the window. */
13119 if (amount_to_scroll > height - 2*this_scroll_margin + dy)
13120 amount_to_scroll = height - 2*this_scroll_margin + dy;
13113 } 13121 }
13114 } 13122 }
13115 13123
@@ -13117,12 +13125,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13117 return SCROLLING_FAILED; 13125 return SCROLLING_FAILED;
13118 13126
13119 start_display (&it, w, startp); 13127 start_display (&it, w, startp);
13120 if (scroll_max < INT_MAX) 13128 if (arg_scroll_conservatively <= scroll_limit)
13121 move_it_vertically (&it, amount_to_scroll); 13129 move_it_vertically (&it, amount_to_scroll);
13122 else 13130 else
13123 { 13131 {
13124 /* Extra precision for users who set scroll-conservatively 13132 /* Extra precision for users who set scroll-conservatively
13125 to most-positive-fixnum: make sure the amount we scroll 13133 to a large number: make sure the amount we scroll
13126 the window start is never less than amount_to_scroll, 13134 the window start is never less than amount_to_scroll,
13127 which was computed as distance from window bottom to 13135 which was computed as distance from window bottom to
13128 point. This matters when lines at window top and lines 13136 point. This matters when lines at window top and lines
@@ -13160,16 +13168,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13160 { 13168 {
13161 /* Point is in the scroll margin at the top of the window or 13169 /* Point is in the scroll margin at the top of the window or
13162 above what is displayed in the window. */ 13170 above what is displayed in the window. */
13163 int y0; 13171 int y0, y_to_move;
13164 13172
13165 /* Compute the vertical distance from PT to the scroll 13173 /* Compute the vertical distance from PT to the scroll
13166 margin position. Give up if distance is greater than 13174 margin position. Move as far as scroll_max allows, or
13167 scroll_max. */ 13175 one screenful, or 10 screen lines, whichever is largest.
13176 Give up if distance is greater than scroll_max. */
13168 SET_TEXT_POS (pos, PT, PT_BYTE); 13177 SET_TEXT_POS (pos, PT, PT_BYTE);
13169 start_display (&it, w, pos); 13178 start_display (&it, w, pos);
13170 y0 = it.current_y; 13179 y0 = it.current_y;
13180 y_to_move = max (it.last_visible_y,
13181 max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)));
13171 move_it_to (&it, CHARPOS (scroll_margin_pos), 0, 13182 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
13172 it.last_visible_y, -1, 13183 y_to_move, -1,
13173 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); 13184 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
13174 dy = it.current_y - y0; 13185 dy = it.current_y - y0;
13175 if (dy > scroll_max) 13186 if (dy > scroll_max)
@@ -13179,8 +13190,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13179 start_display (&it, w, startp); 13190 start_display (&it, w, startp);
13180 13191
13181 if (arg_scroll_conservatively) 13192 if (arg_scroll_conservatively)
13182 amount_to_scroll 13193 amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) *
13183 = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); 13194 max (scroll_step, temp_scroll_step));
13184 else if (scroll_step || temp_scroll_step) 13195 else if (scroll_step || temp_scroll_step)
13185 amount_to_scroll = scroll_max; 13196 amount_to_scroll = scroll_max;
13186 else 13197 else
@@ -13193,6 +13204,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
13193 amount_to_scroll = float_amount; 13204 amount_to_scroll = float_amount;
13194 if (amount_to_scroll == 0 && float_amount > 0) 13205 if (amount_to_scroll == 0 && float_amount > 0)
13195 amount_to_scroll = 1; 13206 amount_to_scroll = 1;
13207 amount_to_scroll -=
13208 this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
13209 /* Don't let point enter the scroll margin near
13210 bottom of the window. */
13211 if (amount_to_scroll > height - 2*this_scroll_margin + dy)
13212 amount_to_scroll = height - 2*this_scroll_margin + dy;
13196 } 13213 }
13197 } 13214 }
13198 13215
@@ -14190,11 +14207,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
14190 } 14207 }
14191 } 14208 }
14192 14209
14193 /* Finally, just choose place to start which centers point */ 14210 /* Finally, just choose a place to start which positions point
14211 according to user preferences. */
14194 14212
14195 recenter: 14213 recenter:
14196 if (centering_position < 0)
14197 centering_position = window_box_height (w) / 2;
14198 14214
14199#if GLYPH_DEBUG 14215#if GLYPH_DEBUG
14200 debug_method_add (w, "recenter"); 14216 debug_method_add (w, "recenter");
@@ -14206,10 +14222,77 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
14206 if (!buffer_unchanged_p) 14222 if (!buffer_unchanged_p)
14207 w->base_line_number = Qnil; 14223 w->base_line_number = Qnil;
14208 14224
14209 /* Move backward half the height of the window. */ 14225 /* Determine the window start relative to point. */
14210 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); 14226 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
14211 it.current_y = it.last_visible_y; 14227 it.current_y = it.last_visible_y;
14228 if (centering_position < 0)
14229 {
14230 int margin =
14231 scroll_margin > 0
14232 ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
14233 : 0;
14234 EMACS_INT margin_pos = CHARPOS (startp);
14235 int scrolling_up;
14236 Lisp_Object aggressive;
14237
14238 /* If there is a scroll margin at the top of the window, find
14239 its character position. */
14240 if (margin)
14241 {
14242 struct it it1;
14243
14244 start_display (&it1, w, startp);
14245 move_it_vertically (&it1, margin);
14246 margin_pos = IT_CHARPOS (it1);
14247 }
14248 scrolling_up = PT > margin_pos;
14249 aggressive =
14250 scrolling_up
14251 ? BVAR (current_buffer, scroll_up_aggressively)
14252 : BVAR (current_buffer, scroll_down_aggressively);
14253
14254 if (!MINI_WINDOW_P (w)
14255 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
14256 {
14257 int pt_offset = 0;
14258
14259 /* Setting scroll-conservatively overrides
14260 scroll-*-aggressively. */
14261 if (!scroll_conservatively && NUMBERP (aggressive))
14262 {
14263 double float_amount = XFLOATINT (aggressive);
14264
14265 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
14266 if (pt_offset == 0 && float_amount > 0)
14267 pt_offset = 1;
14268 if (pt_offset)
14269 margin -= 1;
14270 }
14271 /* Compute how much to move the window start backward from
14272 point so that point will be displayed where the user
14273 wants it. */
14274 if (scrolling_up)
14275 {
14276 centering_position = it.last_visible_y;
14277 if (pt_offset)
14278 centering_position -= pt_offset;
14279 centering_position -=
14280 FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0));
14281 /* Don't let point enter the scroll margin near top of
14282 the window. */
14283 if (centering_position < margin * FRAME_LINE_HEIGHT (f))
14284 centering_position = margin * FRAME_LINE_HEIGHT (f);
14285 }
14286 else
14287 centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset;
14288 }
14289 else
14290 /* Set the window start half the height of the window backward
14291 from point. */
14292 centering_position = window_box_height (w) / 2;
14293 }
14212 move_it_vertically_backward (&it, centering_position); 14294 move_it_vertically_backward (&it, centering_position);
14295
14213 xassert (IT_CHARPOS (it) >= BEGV); 14296 xassert (IT_CHARPOS (it) >= BEGV);
14214 14297
14215 /* The function move_it_vertically_backward may move over more 14298 /* The function move_it_vertically_backward may move over more
@@ -14226,8 +14309,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
14226 14309
14227 it.current_x = it.hpos = 0; 14310 it.current_x = it.hpos = 0;
14228 14311
14229 /* Set startp here explicitly in case that helps avoid an infinite loop 14312 /* Set the window start position here explicitly, to avoid an
14230 in case the window-scroll-functions functions get errors. */ 14313 infinite loop in case the functions in window-scroll-functions
14314 get errors. */
14231 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it)); 14315 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
14232 14316
14233 /* Run scroll hooks. */ 14317 /* Run scroll hooks. */
@@ -26504,6 +26588,10 @@ If point moves off-screen, redisplay will scroll by up to
26504onto the screen again. If that cannot be done, then redisplay 26588onto the screen again. If that cannot be done, then redisplay
26505recenters point as usual. 26589recenters point as usual.
26506 26590
26591If the value is greater than 100, redisplay will never recenter point,
26592but will always scroll just enough text to bring point into view, even
26593if you move far away.
26594
26507A value of zero means always recenter point if it moves off screen. */); 26595A value of zero means always recenter point if it moves off screen. */);
26508 scroll_conservatively = 0; 26596 scroll_conservatively = 0;
26509 26597