aboutsummaryrefslogtreecommitdiffstats
path: root/src/window.c
diff options
context:
space:
mode:
authorEli Zaretskii2022-10-11 13:26:01 +0300
committerEli Zaretskii2022-10-11 13:26:01 +0300
commit4f114c0d95caa0e26de3d188cebe9e3cbcb2dee8 (patch)
treebdc3a6ff63499502012a0957dd2f1bedd0f79405 /src/window.c
parent163000fb5980a0a098d1c4620b88a4717702d779 (diff)
downloademacs-4f114c0d95caa0e26de3d188cebe9e3cbcb2dee8.tar.gz
emacs-4f114c0d95caa0e26de3d188cebe9e3cbcb2dee8.zip
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.
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c97
1 files changed, 92 insertions, 5 deletions
diff --git a/src/window.c b/src/window.c
index da80fabe33f..4e8b352e164 100644
--- a/src/window.c
+++ b/src/window.c
@@ -52,6 +52,7 @@ static ptrdiff_t get_leaf_windows (struct window *, struct window **,
52 ptrdiff_t); 52 ptrdiff_t);
53static void window_scroll_pixel_based (Lisp_Object, int, bool, bool); 53static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
54static void window_scroll_line_based (Lisp_Object, int, bool, bool); 54static void window_scroll_line_based (Lisp_Object, int, bool, bool);
55static void window_scroll_for_long_lines (struct window *, int, bool);
55static void foreach_window (struct frame *, 56static void foreach_window (struct frame *,
56 bool (* fn) (struct window *, void *), 57 bool (* fn) (struct window *, void *),
57 void *); 58 void *);
@@ -5536,19 +5537,40 @@ window_internal_height (struct window *w)
5536static void 5537static void
5537window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror) 5538window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
5538{ 5539{
5540 struct window *w = XWINDOW (window);
5541 struct buffer *b = XBUFFER (w->contents);
5542 bool long_lines_truncated =
5543 b->long_line_optimizations_p && !NILP (BVAR (b, truncate_lines));
5539 specpdl_ref count = SPECPDL_INDEX (); 5544 specpdl_ref count = SPECPDL_INDEX ();
5540 5545
5541 n = clip_to_bounds (INT_MIN, n, INT_MAX); 5546 n = clip_to_bounds (INT_MIN, n, INT_MAX);
5542 5547
5543 wset_redisplay (XWINDOW (window)); 5548 wset_redisplay (w);
5544 5549
5545 if (whole && fast_but_imprecise_scrolling) 5550 /* Does this window's buffer have very long and truncated lines? */
5551 if (b->long_line_optimizations_p
5552 && !long_lines_truncated
5553 && !NILP (Vtruncate_partial_width_windows)
5554 && w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w))))
5555 {
5556 if (FIXNUMP (Vtruncate_partial_width_windows))
5557 long_lines_truncated =
5558 w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
5559 else
5560 long_lines_truncated = true;
5561 }
5562
5563 if (whole && (fast_but_imprecise_scrolling || long_lines_truncated))
5546 specbind (Qfontification_functions, Qnil); 5564 specbind (Qfontification_functions, Qnil);
5547 5565
5548 /* On GUI frames, use the pixel-based version which is much slower 5566 if (whole && long_lines_truncated)
5549 than the line-based one but can handle varying line heights. */ 5567 window_scroll_for_long_lines (w, n, noerror);
5550 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) 5568 else if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
5551 { 5569 {
5570
5571 /* On GUI frames, use the pixel-based version which is much
5572 slower than the line-based one, but can handle varying
5573 line heights. */
5552 record_unwind_protect_void (unwind_display_working_on_window); 5574 record_unwind_protect_void (unwind_display_working_on_window);
5553 display_working_on_window_p = true; 5575 display_working_on_window_p = true;
5554 window_scroll_pixel_based (window, n, whole, noerror); 5576 window_scroll_pixel_based (window, n, whole, noerror);
@@ -5598,6 +5620,71 @@ sanitize_next_screen_context_lines (void)
5598 return clip_to_bounds (0, next_screen_context_lines, 1000000); 5620 return clip_to_bounds (0, next_screen_context_lines, 1000000);
5599} 5621}
5600 5622
5623/* Implementation of window_scroll for very long and truncated lines.
5624 This is a simplified version, it only handles WHOLE window scrolls,
5625 and doesn't honor scroll-preserve-screen-position nor scroll-margin. */
5626static void
5627window_scroll_for_long_lines (struct window *w, int n, bool noerror)
5628{
5629 ptrdiff_t startpos = marker_position (w->start);
5630 ptrdiff_t startbyte = marker_byte_position (w->start);
5631 int nscls = sanitize_next_screen_context_lines ();
5632 register int ht = window_internal_height (w);
5633
5634 n *= max (1, ht - nscls);
5635
5636 /* If point is not visible in window, bring it inside window. */
5637 struct position pos;
5638 int rtop, rbot, dummy_rowh, dummy_vpos, dummy_x, dummy_y;
5639 if (!(PT >= startpos
5640 && PT <= ZV
5641 && startpos <= ZV
5642 && pos_visible_p (w, PT, &dummy_x, &dummy_y, &rtop, &rbot, &dummy_rowh,
5643 &dummy_vpos)
5644 && !rtop && !rbot))
5645 {
5646 pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
5647 startpos = pos.bufpos;
5648 startbyte = pos.bytepos;
5649 }
5650 SET_PT_BOTH (startpos, startbyte);
5651
5652 bool lose = n < 0 && PT == BEGV;
5653 pos = *vmotion (PT, PT_BYTE, n, w);
5654 if (lose)
5655 {
5656 if (noerror)
5657 return;
5658 else
5659 xsignal0 (Qbeginning_of_buffer);
5660 }
5661
5662 bool bolp = pos.bufpos == BEGV || FETCH_BYTE (pos.bytepos - 1) == '\n';
5663 if (pos.bufpos < ZV)
5664 {
5665 set_marker_restricted_both (w->start, w->contents,
5666 pos.bufpos, pos.bytepos);
5667 w->start_at_line_beg = bolp;
5668 wset_update_mode_line (w);
5669 /* Set force_start so that redisplay_window will run
5670 the window-scroll-functions. */
5671 w->force_start = true;
5672 SET_PT_BOTH (pos.bufpos, pos.bytepos);
5673 if (n > 0)
5674 pos = *vmotion (PT, PT_BYTE, ht / 2, w);
5675 else if (n < 0)
5676 pos = *vmotion (PT, PT_BYTE, - (ht / 2), w);
5677 SET_PT_BOTH (pos.bufpos, pos.bytepos);
5678 }
5679 else
5680 {
5681 if (noerror)
5682 return;
5683 else
5684 xsignal0 (Qend_of_buffer);
5685 }
5686}
5687
5601/* Implementation of window_scroll that works based on pixel line 5688/* Implementation of window_scroll that works based on pixel line
5602 heights. See the comment of window_scroll for parameter 5689 heights. See the comment of window_scroll for parameter
5603 descriptions. */ 5690 descriptions. */