diff options
| author | Eli Zaretskii | 2011-03-31 21:12:30 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2011-03-31 21:12:30 +0200 |
| commit | 63696a737c9c28f203e1e4f8c73f8a765486543f (patch) | |
| tree | 52953c1f938dc657c5bc4023df7efcb6f58721b5 /src | |
| parent | c82b2579f0d0abc7cfe75f9f29bc2c7010473878 (diff) | |
| parent | 09725d2628e9b8a796d128d24e7255a57c2424f3 (diff) | |
| download | emacs-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/ChangeLog | 31 | ||||
| -rw-r--r-- | src/xdisp.c | 140 |
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 @@ | |||
| 1 | 2011-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 | |||
| 22 | 2011-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 | |||
| 1 | 2011-03-31 Juanma Barranquero <lekktu@gmail.com> | 27 | 2011-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 | ||
| 187 | 2011-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 | |||
| 192 | 2011-03-26 Juanma Barranquero <lekktu@gmail.com> | 213 | 2011-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 | |||
| 12995 | static int | 13001 | static int |
| 12996 | try_scrolling (Lisp_Object window, int just_this_one_p, | 13002 | try_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 | |||
| 26504 | onto the screen again. If that cannot be done, then redisplay | 26588 | onto the screen again. If that cannot be done, then redisplay |
| 26505 | recenters point as usual. | 26589 | recenters point as usual. |
| 26506 | 26590 | ||
| 26591 | If the value is greater than 100, redisplay will never recenter point, | ||
| 26592 | but will always scroll just enough text to bring point into view, even | ||
| 26593 | if you move far away. | ||
| 26594 | |||
| 26507 | A value of zero means always recenter point if it moves off screen. */); | 26595 | A value of zero means always recenter point if it moves off screen. */); |
| 26508 | scroll_conservatively = 0; | 26596 | scroll_conservatively = 0; |
| 26509 | 26597 | ||