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'.
This commit is contained in:
commit
63696a737c
4 changed files with 163 additions and 32 deletions
|
@ -1,3 +1,9 @@
|
|||
2011-03-30 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* display.texi (Auto Scrolling): Document the limit of 100 lines
|
||||
for never-recentering scrolling with `scroll-conservatively'.
|
||||
(Bug#6671)
|
||||
|
||||
2011-03-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* msdog.texi (Windows HOME): Fix the wording to clarify how Emacs sets
|
||||
|
|
|
@ -183,7 +183,20 @@ visible portion of the text.
|
|||
if you set @code{scroll-conservatively} to a small number @var{n},
|
||||
then if you move point just a little off the screen (less than @var{n}
|
||||
lines), Emacs scrolls the text just far enough to bring point back on
|
||||
screen. By default, @code{scroll-conservatively} is@tie{}0.
|
||||
screen. By default, @code{scroll-conservatively} is@tie{}0. If you
|
||||
set @code{scroll-conservatively} to a large number (larger than 100),
|
||||
Emacs will never center point as result of scrolling, even if point
|
||||
moves far away from the text previously displayed in the window. With
|
||||
such a large value, Emacs will always scroll text just enough for
|
||||
bringing point into view, so point will end up at the top or bottom of
|
||||
the window, depending on the scroll direction.
|
||||
|
||||
@vindex scroll-step
|
||||
The variable @code{scroll-step} determines how many lines to scroll
|
||||
the window when point moves off the screen. If moving by that number
|
||||
of lines fails to bring point back into view, point is centered
|
||||
instead. The default value is zero, which causes point to always be
|
||||
centered after scrolling.
|
||||
|
||||
@cindex aggressive scrolling
|
||||
@vindex scroll-up-aggressively
|
||||
|
@ -204,6 +217,9 @@ down. The value specifies how far point should be placed from the
|
|||
bottom of the window; thus, as with @code{scroll-up-aggressively}, a
|
||||
larger value is more aggressive.
|
||||
|
||||
These two variables are ignored if either @code{scroll-step} or
|
||||
@code{scroll-conservatively} are set to a non-zero value.
|
||||
|
||||
@vindex scroll-margin
|
||||
The variable @code{scroll-margin} restricts how close point can come
|
||||
to the top or bottom of a window. Its value is a number of screen
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
2011-03-31 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* 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. (Bug#6671)
|
||||
|
||||
(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.
|
||||
|
||||
2011-03-26 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* xdisp.c (redisplay_window): Don't check buffer's clip_changed
|
||||
flag as a prerequisite for invoking try_scrolling. (Bug#6671)
|
||||
|
||||
2011-03-31 Juanma Barranquero <lekktu@gmail.com>
|
||||
|
||||
* dispextern.h (move_it_by_lines):
|
||||
|
@ -184,11 +210,6 @@
|
|||
* s/usg5-4-common.h (SIGTYPE): Remove definition.
|
||||
* s/template.h (SIGTYPE): Remove commented out definition.
|
||||
|
||||
2011-03-26 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* xdisp.c (redisplay_window): Don't check buffer's clip_changed
|
||||
flag as a prerequisite for invoking try_scrolling. (Bug#6671)
|
||||
|
||||
2011-03-26 Juanma Barranquero <lekktu@gmail.com>
|
||||
|
||||
* w32.c (read_unc_volume): Use parameter `henum', instead of
|
||||
|
|
140
src/xdisp.c
140
src/xdisp.c
|
@ -12992,6 +12992,12 @@ enum
|
|||
SCROLLING_NEED_LARGER_MATRICES
|
||||
};
|
||||
|
||||
/* If scroll-conservatively is more than this, never recenter.
|
||||
|
||||
If you change this, don't forget to update the doc string of
|
||||
`scroll-conservatively' and the Emacs manual. */
|
||||
#define SCROLL_LIMIT 100
|
||||
|
||||
static int
|
||||
try_scrolling (Lisp_Object window, int just_this_one_p,
|
||||
EMACS_INT arg_scroll_conservatively, EMACS_INT scroll_step,
|
||||
|
@ -13005,7 +13011,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
|
||||
int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
|
||||
Lisp_Object aggressive;
|
||||
int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f);
|
||||
/* We will never try scrolling more than this number of lines. */
|
||||
int scroll_limit = SCROLL_LIMIT;
|
||||
|
||||
#if GLYPH_DEBUG
|
||||
debug_method_add (w, "try_scrolling");
|
||||
|
@ -13021,14 +13028,14 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
else
|
||||
this_scroll_margin = 0;
|
||||
|
||||
/* Force arg_scroll_conservatively to have a reasonable value, to avoid
|
||||
overflow while computing how much to scroll. Note that the user
|
||||
can supply scroll-conservatively equal to `most-positive-fixnum',
|
||||
which can be larger than INT_MAX. */
|
||||
/* Force arg_scroll_conservatively to have a reasonable value, to
|
||||
avoid scrolling too far away with slow move_it_* functions. Note
|
||||
that the user can supply scroll-conservatively equal to
|
||||
`most-positive-fixnum', which can be larger than INT_MAX. */
|
||||
if (arg_scroll_conservatively > scroll_limit)
|
||||
{
|
||||
arg_scroll_conservatively = scroll_limit;
|
||||
scroll_max = INT_MAX;
|
||||
arg_scroll_conservatively = scroll_limit + 1;
|
||||
scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f);
|
||||
}
|
||||
else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
|
||||
/* 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,
|
|||
/* Compute how many pixels below window bottom to stop searching
|
||||
for PT. This avoids costly search for PT that is far away if
|
||||
the user limited scrolling by a small number of lines, but
|
||||
always finds PT if arg_scroll_conservatively is set to a large
|
||||
always finds PT if scroll_conservatively is set to a large
|
||||
number, such as most-positive-fixnum. */
|
||||
int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
|
||||
int y_to_move =
|
||||
slack >= INT_MAX - it.last_visible_y
|
||||
? INT_MAX
|
||||
: it.last_visible_y + slack;
|
||||
int y_to_move = it.last_visible_y + slack;
|
||||
|
||||
/* Compute the distance from the scroll margin to PT or to
|
||||
the scroll limit, whichever comes first. This should
|
||||
|
@ -13110,6 +13114,10 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
amount_to_scroll = float_amount;
|
||||
if (amount_to_scroll == 0 && float_amount > 0)
|
||||
amount_to_scroll = 1;
|
||||
/* Don't let point enter the scroll margin near top of
|
||||
the window. */
|
||||
if (amount_to_scroll > height - 2*this_scroll_margin + dy)
|
||||
amount_to_scroll = height - 2*this_scroll_margin + dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13117,12 +13125,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
return SCROLLING_FAILED;
|
||||
|
||||
start_display (&it, w, startp);
|
||||
if (scroll_max < INT_MAX)
|
||||
if (arg_scroll_conservatively <= scroll_limit)
|
||||
move_it_vertically (&it, amount_to_scroll);
|
||||
else
|
||||
{
|
||||
/* Extra precision for users who set scroll-conservatively
|
||||
to most-positive-fixnum: make sure the amount we scroll
|
||||
to a large number: make sure the amount we scroll
|
||||
the window start is never less than amount_to_scroll,
|
||||
which was computed as distance from window bottom to
|
||||
point. This matters when lines at window top and lines
|
||||
|
@ -13160,16 +13168,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
{
|
||||
/* Point is in the scroll margin at the top of the window or
|
||||
above what is displayed in the window. */
|
||||
int y0;
|
||||
int y0, y_to_move;
|
||||
|
||||
/* Compute the vertical distance from PT to the scroll
|
||||
margin position. Give up if distance is greater than
|
||||
scroll_max. */
|
||||
margin position. Move as far as scroll_max allows, or
|
||||
one screenful, or 10 screen lines, whichever is largest.
|
||||
Give up if distance is greater than scroll_max. */
|
||||
SET_TEXT_POS (pos, PT, PT_BYTE);
|
||||
start_display (&it, w, pos);
|
||||
y0 = it.current_y;
|
||||
y_to_move = max (it.last_visible_y,
|
||||
max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)));
|
||||
move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
|
||||
it.last_visible_y, -1,
|
||||
y_to_move, -1,
|
||||
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
|
||||
dy = it.current_y - y0;
|
||||
if (dy > scroll_max)
|
||||
|
@ -13179,8 +13190,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
start_display (&it, w, startp);
|
||||
|
||||
if (arg_scroll_conservatively)
|
||||
amount_to_scroll
|
||||
= max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
|
||||
amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) *
|
||||
max (scroll_step, temp_scroll_step));
|
||||
else if (scroll_step || temp_scroll_step)
|
||||
amount_to_scroll = scroll_max;
|
||||
else
|
||||
|
@ -13193,6 +13204,12 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
|
|||
amount_to_scroll = float_amount;
|
||||
if (amount_to_scroll == 0 && float_amount > 0)
|
||||
amount_to_scroll = 1;
|
||||
amount_to_scroll -=
|
||||
this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
|
||||
/* Don't let point enter the scroll margin near
|
||||
bottom of the window. */
|
||||
if (amount_to_scroll > height - 2*this_scroll_margin + dy)
|
||||
amount_to_scroll = height - 2*this_scroll_margin + dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14190,11 +14207,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
|
|||
}
|
||||
}
|
||||
|
||||
/* Finally, just choose place to start which centers point */
|
||||
/* Finally, just choose a place to start which positions point
|
||||
according to user preferences. */
|
||||
|
||||
recenter:
|
||||
if (centering_position < 0)
|
||||
centering_position = window_box_height (w) / 2;
|
||||
|
||||
#if GLYPH_DEBUG
|
||||
debug_method_add (w, "recenter");
|
||||
|
@ -14206,10 +14222,77 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
|
|||
if (!buffer_unchanged_p)
|
||||
w->base_line_number = Qnil;
|
||||
|
||||
/* Move backward half the height of the window. */
|
||||
/* Determine the window start relative to point. */
|
||||
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
|
||||
it.current_y = it.last_visible_y;
|
||||
if (centering_position < 0)
|
||||
{
|
||||
int margin =
|
||||
scroll_margin > 0
|
||||
? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
|
||||
: 0;
|
||||
EMACS_INT margin_pos = CHARPOS (startp);
|
||||
int scrolling_up;
|
||||
Lisp_Object aggressive;
|
||||
|
||||
/* If there is a scroll margin at the top of the window, find
|
||||
its character position. */
|
||||
if (margin)
|
||||
{
|
||||
struct it it1;
|
||||
|
||||
start_display (&it1, w, startp);
|
||||
move_it_vertically (&it1, margin);
|
||||
margin_pos = IT_CHARPOS (it1);
|
||||
}
|
||||
scrolling_up = PT > margin_pos;
|
||||
aggressive =
|
||||
scrolling_up
|
||||
? BVAR (current_buffer, scroll_up_aggressively)
|
||||
: BVAR (current_buffer, scroll_down_aggressively);
|
||||
|
||||
if (!MINI_WINDOW_P (w)
|
||||
&& (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
|
||||
{
|
||||
int pt_offset = 0;
|
||||
|
||||
/* Setting scroll-conservatively overrides
|
||||
scroll-*-aggressively. */
|
||||
if (!scroll_conservatively && NUMBERP (aggressive))
|
||||
{
|
||||
double float_amount = XFLOATINT (aggressive);
|
||||
|
||||
pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
|
||||
if (pt_offset == 0 && float_amount > 0)
|
||||
pt_offset = 1;
|
||||
if (pt_offset)
|
||||
margin -= 1;
|
||||
}
|
||||
/* Compute how much to move the window start backward from
|
||||
point so that point will be displayed where the user
|
||||
wants it. */
|
||||
if (scrolling_up)
|
||||
{
|
||||
centering_position = it.last_visible_y;
|
||||
if (pt_offset)
|
||||
centering_position -= pt_offset;
|
||||
centering_position -=
|
||||
FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0));
|
||||
/* Don't let point enter the scroll margin near top of
|
||||
the window. */
|
||||
if (centering_position < margin * FRAME_LINE_HEIGHT (f))
|
||||
centering_position = margin * FRAME_LINE_HEIGHT (f);
|
||||
}
|
||||
else
|
||||
centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset;
|
||||
}
|
||||
else
|
||||
/* Set the window start half the height of the window backward
|
||||
from point. */
|
||||
centering_position = window_box_height (w) / 2;
|
||||
}
|
||||
move_it_vertically_backward (&it, centering_position);
|
||||
|
||||
xassert (IT_CHARPOS (it) >= BEGV);
|
||||
|
||||
/* The function move_it_vertically_backward may move over more
|
||||
|
@ -14226,8 +14309,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
|
|||
|
||||
it.current_x = it.hpos = 0;
|
||||
|
||||
/* Set startp here explicitly in case that helps avoid an infinite loop
|
||||
in case the window-scroll-functions functions get errors. */
|
||||
/* Set the window start position here explicitly, to avoid an
|
||||
infinite loop in case the functions in window-scroll-functions
|
||||
get errors. */
|
||||
set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
|
||||
|
||||
/* Run scroll hooks. */
|
||||
|
@ -26504,6 +26588,10 @@ If point moves off-screen, redisplay will scroll by up to
|
|||
onto the screen again. If that cannot be done, then redisplay
|
||||
recenters point as usual.
|
||||
|
||||
If the value is greater than 100, redisplay will never recenter point,
|
||||
but will always scroll just enough text to bring point into view, even
|
||||
if you move far away.
|
||||
|
||||
A value of zero means always recenter point if it moves off screen. */);
|
||||
scroll_conservatively = 0;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue