aboutsummaryrefslogtreecommitdiffstats
path: root/src/xdisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdisp.c')
-rw-r--r--src/xdisp.c203
1 files changed, 155 insertions, 48 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 1fcff2c2e3b..1e8f70b2db9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11040,6 +11040,15 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11040int 11040int
11041partial_line_height (struct it *it_origin) 11041partial_line_height (struct it *it_origin)
11042{ 11042{
11043 /* In a buffer with very long and truncated lines, we ignore the
11044 possibly-partial height of the last line in the window: it is too
11045 expensive to compute that (since in most cases that involves
11046 going all the way to ZV), and the effect of ignoring it is
11047 relatively minor. */
11048 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11049 && it_origin->line_wrap == TRUNCATE)
11050 return 0;
11051
11043 int partial_height; 11052 int partial_height;
11044 void *it_data = NULL; 11053 void *it_data = NULL;
11045 struct it it; 11054 struct it it;
@@ -11063,6 +11072,51 @@ partial_line_height (struct it *it_origin)
11063 return partial_height; 11072 return partial_height;
11064} 11073}
11065 11074
11075/* Approximate move_it_in_display_line_to for very long and truncated
11076 display lines, when moving horizontally. This is used when the
11077 buffer's long_line_optimizations_p flag is set. It ignores various
11078 complications, like different font sizes, invisible text, display
11079 and overlay strings, and, to some degree, bidirectional text. So
11080 caveat emptor!
11081
11082 Starting from IT's position, reseat IT after skipping NCHARS
11083 characters or to the next newline/ZV, whichever comes first. Return
11084 what move_it_in_display_line_to would have returned in this case. */
11085
11086static enum move_it_result
11087fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11088{
11089 ptrdiff_t nl_bytepos;
11090 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11091 1, &nl_bytepos);
11092 struct text_pos new_pos;
11093 enum move_it_result move_result;
11094
11095 if (nl_pos - IT_CHARPOS (*it) > nchars)
11096 {
11097 SET_TEXT_POS (new_pos,
11098 IT_CHARPOS (*it) + nchars,
11099 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11100 move_result = MOVE_X_REACHED;
11101 }
11102 else
11103 {
11104 if (nl_bytepos < ZV_BYTE
11105 || (nl_bytepos > BEGV_BYTE
11106 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11107 {
11108 nl_pos--;
11109 nl_bytepos--;
11110 move_result = MOVE_NEWLINE_OR_CR;
11111 }
11112 else
11113 move_result = MOVE_POS_MATCH_OR_ZV;
11114 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11115 }
11116 reseat (it, new_pos, false);
11117 return move_result;
11118}
11119
11066/* Return true if IT points into the middle of a display vector. */ 11120/* Return true if IT points into the middle of a display vector. */
11067 11121
11068bool 11122bool
@@ -13106,8 +13160,7 @@ mode_line_update_needed (struct window *w)
13106{ 13160{
13107 return (w->column_number_displayed != -1 13161 return (w->column_number_displayed != -1
13108 && !(PT == w->last_point && !window_outdated (w)) 13162 && !(PT == w->last_point && !window_outdated (w))
13109 && (!current_buffer->long_line_optimizations_p 13163 && (w->column_number_displayed != current_column ()));
13110 && w->column_number_displayed != current_column ()));
13111} 13164}
13112 13165
13113/* True if window start of W is frozen and may not be changed during 13166/* True if window start of W is frozen and may not be changed during
@@ -15776,7 +15829,20 @@ hscroll_window_tree (Lisp_Object window)
15776 it.first_visible_x = window_hscroll_limited (w, it.f) 15829 it.first_visible_x = window_hscroll_limited (w, it.f)
15777 * FRAME_COLUMN_WIDTH (it.f); 15830 * FRAME_COLUMN_WIDTH (it.f);
15778 it.last_visible_x = DISP_INFINITY; 15831 it.last_visible_x = DISP_INFINITY;
15779 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS); 15832
15833 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15834 if (current_buffer->long_line_optimizations_p
15835 && nchars > large_hscroll_threshold)
15836 {
15837 /* Special optimization for very long and truncated
15838 lines which need to be hscrolled far to the left:
15839 jump directly to the (approximate) first position
15840 that is visible, instead of slowly walking there. */
15841 fast_move_it_horizontally (&it, nchars);
15842 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15843 }
15844 else
15845 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15780 /* If the line ends in an overlay string with a newline, 15846 /* If the line ends in an overlay string with a newline,
15781 we might infloop, because displaying the window will 15847 we might infloop, because displaying the window will
15782 want to put the cursor after the overlay, i.e. at X 15848 want to put the cursor after the overlay, i.e. at X
@@ -15789,7 +15855,14 @@ hscroll_window_tree (Lisp_Object window)
15789 if (hscl) 15855 if (hscl)
15790 it.first_visible_x = (window_hscroll_limited (w, it.f) 15856 it.first_visible_x = (window_hscroll_limited (w, it.f)
15791 * FRAME_COLUMN_WIDTH (it.f)); 15857 * FRAME_COLUMN_WIDTH (it.f));
15792 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS); 15858 if (current_buffer->long_line_optimizations_p
15859 && nchars > large_hscroll_threshold)
15860 {
15861 fast_move_it_horizontally (&it, nchars - 1);
15862 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
15863 }
15864 else
15865 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
15793 } 15866 }
15794 current_buffer = saved_current_buffer; 15867 current_buffer = saved_current_buffer;
15795 15868
@@ -16727,9 +16800,23 @@ redisplay_internal (void)
16727 it.current_y = this_line_y; 16800 it.current_y = this_line_y;
16728 it.vpos = this_line_vpos; 16801 it.vpos = this_line_vpos;
16729 16802
16730 /* The call to move_it_to stops in front of PT, but 16803 if (current_buffer->long_line_optimizations_p
16731 moves over before-strings. */ 16804 && it.line_wrap == TRUNCATE
16732 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); 16805 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16806 {
16807 /* When lines are very long and truncated, jumping to
16808 the next visible line is much faster than slowly
16809 iterating there. */
16810 reseat_at_next_visible_line_start (&it, false);
16811 if (IT_CHARPOS (it) <= PT) /* point moved off this line */
16812 it.vpos = this_line_vpos + 1;
16813 }
16814 else
16815 {
16816 /* The call to move_it_to stops in front of PT, but
16817 moves over before-strings. */
16818 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16819 }
16733 16820
16734 if (it.vpos == this_line_vpos 16821 if (it.vpos == this_line_vpos
16735 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos), 16822 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
@@ -18119,8 +18206,8 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18119 { 18206 {
18120 specpdl_ref count = SPECPDL_INDEX (); 18207 specpdl_ref count = SPECPDL_INDEX ();
18121 specbind (Qinhibit_quit, Qt); 18208 specbind (Qinhibit_quit, Qt);
18122 run_hook_with_args_2 (Qwindow_scroll_functions, window, 18209 safe_run_hooks_2
18123 make_fixnum (CHARPOS (startp))); 18210 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18124 unbind_to (count, Qnil); 18211 unbind_to (count, Qnil);
18125 SET_TEXT_POS_FROM_MARKER (startp, w->start); 18212 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18126 /* In case the hook functions switch buffers. */ 18213 /* In case the hook functions switch buffers. */
@@ -19229,6 +19316,16 @@ window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19229 return true; 19316 return true;
19230} 19317}
19231 19318
19319DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19320 0, 0, 0,
19321 doc: /* Return non-nil if long-line optimizations are in effect in current buffer.
19322See `long-line-threshold' and `large-hscroll-threshold' for what these
19323optimizations mean and when they are in effect. */)
19324 (void)
19325{
19326 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19327}
19328
19232/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only 19329/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only
19233 selected_window is redisplayed. 19330 selected_window is redisplayed.
19234 19331
@@ -19504,33 +19601,36 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19504 ptrdiff_t it_charpos; 19601 ptrdiff_t it_charpos;
19505 19602
19506 w->optional_new_start = false; 19603 w->optional_new_start = false;
19507 start_display (&it, w, startp); 19604 if (!w->force_start)
19508 move_it_to (&it, PT, 0, it.last_visible_y, -1, 19605 {
19509 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); 19606 start_display (&it, w, startp);
19510 /* Record IT's position now, since line_bottom_y might change 19607 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19511 that. */ 19608 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19512 it_charpos = IT_CHARPOS (it); 19609 /* Record IT's position now, since line_bottom_y might
19513 /* Make sure we set the force_start flag only if the cursor row 19610 change that. */
19514 will be fully visible. Otherwise, the code under force_start 19611 it_charpos = IT_CHARPOS (it);
19515 label below will try to move point back into view, which is 19612 /* Make sure we set the force_start flag only if the cursor
19516 not what the code which sets optional_new_start wants. */ 19613 row will be fully visible. Otherwise, the code under
19517 if ((it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y) 19614 force_start label below will try to move point back into
19518 && !w->force_start) 19615 view, which is not what the code which sets
19519 { 19616 optional_new_start wants. */
19520 if (it_charpos == PT) 19617 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19521 w->force_start = true; 19618 {
19522 /* IT may overshoot PT if text at PT is invisible. */ 19619 if (it_charpos == PT)
19523 else if (it_charpos > PT && CHARPOS (startp) <= PT) 19620 w->force_start = true;
19524 w->force_start = true; 19621 /* IT may overshoot PT if text at PT is invisible. */
19622 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19623 w->force_start = true;
19525#ifdef GLYPH_DEBUG 19624#ifdef GLYPH_DEBUG
19526 if (w->force_start) 19625 if (w->force_start)
19527 { 19626 {
19528 if (window_frozen_p (w)) 19627 if (window_frozen_p (w))
19529 debug_method_add (w, "set force_start from frozen window start"); 19628 debug_method_add (w, "set force_start from frozen window start");
19530 else 19629 else
19531 debug_method_add (w, "set force_start from optional_new_start"); 19630 debug_method_add (w, "set force_start from optional_new_start");
19532 } 19631 }
19533#endif 19632#endif
19633 }
19534 } 19634 }
19535 } 19635 }
19536 19636
@@ -20256,7 +20356,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20256 || w->base_line_pos > 0 20356 || w->base_line_pos > 0
20257 /* Column number is displayed and different from the one displayed. */ 20357 /* Column number is displayed and different from the one displayed. */
20258 || (w->column_number_displayed != -1 20358 || (w->column_number_displayed != -1
20259 && !current_buffer->long_line_optimizations_p
20260 && (w->column_number_displayed != current_column ()))) 20359 && (w->column_number_displayed != current_column ())))
20261 /* This means that the window has a mode line. */ 20360 /* This means that the window has a mode line. */
20262 && (window_wants_mode_line (w) 20361 && (window_wants_mode_line (w)
@@ -24496,8 +24595,26 @@ display_line (struct it *it, int cursor_vpos)
24496 it->first_visible_x += x_incr; 24595 it->first_visible_x += x_incr;
24497 it->last_visible_x += x_incr; 24596 it->last_visible_x += x_incr;
24498 } 24597 }
24499 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x, 24598 if (current_buffer->long_line_optimizations_p
24500 MOVE_TO_POS | MOVE_TO_X); 24599 && it->line_wrap == TRUNCATE
24600 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24601 {
24602 /* Special optimization for very long and truncated lines
24603 which are hscrolled far to the left: jump directly to the
24604 (approximate) position that is visible, instead of slowly
24605 walking there. */
24606 ptrdiff_t chars_to_skip =
24607 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24608 move_result = fast_move_it_horizontally (it, chars_to_skip);
24609
24610 if (move_result == MOVE_X_REACHED)
24611 it->current_x = it->first_visible_x;
24612 else /* use arbitrary value < first_visible_x */
24613 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24614 }
24615 else
24616 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24617 MOVE_TO_POS | MOVE_TO_X);
24501 /* If we are under a large hscroll, move_it_in_display_line_to 24618 /* If we are under a large hscroll, move_it_in_display_line_to
24502 could hit the end of the line without reaching 24619 could hit the end of the line without reaching
24503 first_visible_x. Pretend that we did reach it. This is 24620 first_visible_x. Pretend that we did reach it. This is
@@ -27758,17 +27875,6 @@ decode_mode_spec (struct window *w, register int c, int field_width,
27758 even crash emacs.) */ 27875 even crash emacs.) */
27759 if (mode_line_target == MODE_LINE_TITLE) 27876 if (mode_line_target == MODE_LINE_TITLE)
27760 return ""; 27877 return "";
27761 else if (b->long_line_optimizations_p)
27762 {
27763 char *p = decode_mode_spec_buf;
27764 int pad = width - 2;
27765 while (pad-- > 0)
27766 *p++ = ' ';
27767 *p++ = '?';
27768 *p++ = '?';
27769 *p = '\0';
27770 return decode_mode_spec_buf;
27771 }
27772 else 27878 else
27773 { 27879 {
27774 ptrdiff_t col = current_column (); 27880 ptrdiff_t col = current_column ();
@@ -36112,6 +36218,7 @@ be let-bound around code that needs to disable messages temporarily. */);
36112 defsubr (&Sbidi_find_overridden_directionality); 36218 defsubr (&Sbidi_find_overridden_directionality);
36113 defsubr (&Sdisplay__line_is_continued_p); 36219 defsubr (&Sdisplay__line_is_continued_p);
36114 defsubr (&Sget_display_property); 36220 defsubr (&Sget_display_property);
36221 defsubr (&Slong_line_optimizations_p);
36115 36222
36116 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook"); 36223 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36117 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map"); 36224 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");