mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-27 15:52:00 -08:00
Speed up scrolling when lines are very long and truncated
* src/window.c (window_scroll_for_long_lines): New function. (window_scroll): Call 'window_scroll_for_long_lines' when lines are very long and truncated on display. Also, disable 'fontification-functions' during scrolling in that case. * src/xdisp.c (redisplay_window): When recentering the window's display, go back to the centering position using a simplified method, if lines in the buffer are very long and truncated on display.
This commit is contained in:
parent
163000fb59
commit
4f114c0d95
2 changed files with 106 additions and 6 deletions
97
src/window.c
97
src/window.c
|
|
@ -52,6 +52,7 @@ static ptrdiff_t get_leaf_windows (struct window *, struct window **,
|
|||
ptrdiff_t);
|
||||
static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
|
||||
static void window_scroll_line_based (Lisp_Object, int, bool, bool);
|
||||
static void window_scroll_for_long_lines (struct window *, int, bool);
|
||||
static void foreach_window (struct frame *,
|
||||
bool (* fn) (struct window *, void *),
|
||||
void *);
|
||||
|
|
@ -5536,19 +5537,40 @@ window_internal_height (struct window *w)
|
|||
static void
|
||||
window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
|
||||
{
|
||||
struct window *w = XWINDOW (window);
|
||||
struct buffer *b = XBUFFER (w->contents);
|
||||
bool long_lines_truncated =
|
||||
b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines));
|
||||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
|
||||
n = clip_to_bounds (INT_MIN, n, INT_MAX);
|
||||
|
||||
wset_redisplay (XWINDOW (window));
|
||||
wset_redisplay (w);
|
||||
|
||||
if (whole && fast_but_imprecise_scrolling)
|
||||
/* Does this window's buffer have very long and truncated lines? */
|
||||
if (b->long_line_optimizations_p
|
||||
&& !long_lines_truncated
|
||||
&& !NILP (Vtruncate_partial_width_windows)
|
||||
&& w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w))))
|
||||
{
|
||||
if (FIXNUMP (Vtruncate_partial_width_windows))
|
||||
long_lines_truncated =
|
||||
w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
|
||||
else
|
||||
long_lines_truncated = true;
|
||||
}
|
||||
|
||||
if (whole && (fast_but_imprecise_scrolling || long_lines_truncated))
|
||||
specbind (Qfontification_functions, Qnil);
|
||||
|
||||
/* On GUI frames, use the pixel-based version which is much slower
|
||||
than the line-based one but can handle varying line heights. */
|
||||
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
|
||||
if (whole && long_lines_truncated)
|
||||
window_scroll_for_long_lines (w, n, noerror);
|
||||
else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
|
||||
{
|
||||
|
||||
/* On GUI frames, use the pixel-based version which is much
|
||||
slower than the line-based one, but can handle varying
|
||||
line heights. */
|
||||
record_unwind_protect_void (unwind_display_working_on_window);
|
||||
display_working_on_window_p = true;
|
||||
window_scroll_pixel_based (window, n, whole, noerror);
|
||||
|
|
@ -5598,6 +5620,71 @@ sanitize_next_screen_context_lines (void)
|
|||
return clip_to_bounds (0, next_screen_context_lines, 1000000);
|
||||
}
|
||||
|
||||
/* Implementation of window_scroll for very long and truncated lines.
|
||||
This is a simplified version, it only handles WHOLE window scrolls,
|
||||
and doesn't honor scroll-preserve-screen-position nor scroll-margin. */
|
||||
static void
|
||||
window_scroll_for_long_lines (struct window *w, int n, bool noerror)
|
||||
{
|
||||
ptrdiff_t startpos = marker_position (w->start);
|
||||
ptrdiff_t startbyte = marker_byte_position (w->start);
|
||||
int nscls = sanitize_next_screen_context_lines ();
|
||||
register int ht = window_internal_height (w);
|
||||
|
||||
n *= max (1, ht - nscls);
|
||||
|
||||
/* If point is not visible in window, bring it inside window. */
|
||||
struct position pos;
|
||||
int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y;
|
||||
if (!(PT >= startpos
|
||||
&& PT <= ZV
|
||||
&& startpos <= ZV
|
||||
&& pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh,
|
||||
&dummy_vpos)
|
||||
&& !rtop && !rbot))
|
||||
{
|
||||
pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
|
||||
startpos = pos.bufpos;
|
||||
startbyte = pos.bytepos;
|
||||
}
|
||||
SET_PT_BOTH (startpos, startbyte);
|
||||
|
||||
bool lose = n < 0 && PT == BEGV;
|
||||
pos = *vmotion (PT, PT_BYTE, n, w);
|
||||
if (lose)
|
||||
{
|
||||
if (noerror)
|
||||
return;
|
||||
else
|
||||
xsignal0 (Qbeginning_of_buffer);
|
||||
}
|
||||
|
||||
bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n';
|
||||
if (pos.bufpos < ZV)
|
||||
{
|
||||
set_marker_restricted_both (w->start, w->contents,
|
||||
pos.bufpos, pos.bytepos);
|
||||
w->start_at_line_beg = bolp;
|
||||
wset_update_mode_line (w);
|
||||
/* Set force_start so that redisplay_window will run
|
||||
the window-scroll-functions. */
|
||||
w->force_start = true;
|
||||
SET_PT_BOTH (pos.bufpos, pos.bytepos);
|
||||
if (n > 0)
|
||||
pos = *vmotion (PT, PT_BYTE, ht / 2, w);
|
||||
else if (n < 0)
|
||||
pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
|
||||
SET_PT_BOTH (pos.bufpos, pos.bytepos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (noerror)
|
||||
return;
|
||||
else
|
||||
xsignal0 (Qend_of_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation of window_scroll that works based on pixel line
|
||||
heights. See the comment of window_scroll for parameter
|
||||
descriptions. */
|
||||
|
|
|
|||
15
src/xdisp.c
15
src/xdisp.c
|
|
@ -20165,7 +20165,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|
|||
from point. */
|
||||
centering_position = window_box_height (w) / 2;
|
||||
}
|
||||
move_it_vertically_backward (&it, centering_position);
|
||||
if (current_buffer->long_line_optimizations_p
|
||||
&& it.line_wrap == TRUNCATE)
|
||||
{
|
||||
/* For very long and truncated lines, go back using a simplified
|
||||
method, which ignored any inaccuracies due to line-height
|
||||
differences, display properties/overlays, etc. */
|
||||
int nlines = centering_position / frame_line_height;
|
||||
|
||||
while (nlines-- && IT_CHARPOS (it) > BEGV)
|
||||
back_to_previous_visible_line_start (&it);
|
||||
reseat_1 (&it, it.current.pos, true);
|
||||
}
|
||||
else
|
||||
move_it_vertically_backward (&it, centering_position);
|
||||
|
||||
eassert (IT_CHARPOS (it) >= BEGV);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue