summaryrefslogtreecommitdiff
path: root/src/xdisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdisp.c')
-rw-r--r--src/xdisp.c159
1 files changed, 123 insertions, 36 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 0b190529404..fa411e6e8dc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3482,7 +3482,7 @@ init_iterator (struct it *it, struct window *w,
/* This is set only when long_line_optimizations_p is non-zero
for the current buffer. */
- it->narrowed_begv = 0;
+ it->medium_narrowing_begv = 0;
/* Compute faces etc. */
reseat (it, it->current.pos, true);
@@ -3491,9 +3491,91 @@ init_iterator (struct it *it, struct window *w,
CHECK_IT (it);
}
-/* Compute a suitable alternate value for BEGV and ZV that may be used
- temporarily to optimize display if the buffer in window W contains
- long lines. */
+/* How Emacs deals with long lines.
+
+ (1) When a buffer is about to be (re)displayed, 'redisplay_window'
+ detects, with a heuristic, whether it contains long lines.
+
+ This happens in 'redisplay_window' because it is only displaying
+ buffers with long lines that is problematic. In other words, none
+ of the optimizations described below is ever used in buffers that
+ are never displayed.
+
+ This happens with a heuristic, which checks whether a buffer
+ contains long lines, each time its contents have changed "enough"
+ between two redisplay cycles, because a buffer without long lines
+ can become a buffer with long lines at any time, for example after
+ a yank command, or after a replace command, or while the output of
+ an external process is inserted in a buffer.
+
+ When Emacs has detected that a buffer contains long lines, the
+ buffer-local variable 'long_line_optimizations_p' (in 'struct
+ buffer') is set, and Emacs does not try to detect whether the
+ buffer does or does not contain long lines anymore.
+
+ What a long line is depends on the variable 'long-line-threshold',
+ whose default value is 50000 (characters).
+
+ (2) When a buffer with long lines is (re)displayed, the amount of
+ data that the display routines consider is, in a few well-chosen
+ places, limited with a temporary restriction, whose bounds are
+ calculated with the functions below.
+
+ (2.1) 'get_small_narrowing_begv' is used to create a restriction
+ which starts a few hundred characters before point. The exact
+ number of characters depends on the width of the window in which
+ the buffer is displayed.
+
+ There is no corresponding 'get_small_narrowing_zv' function,
+ because it is not necessary to set the end limit of that
+ restriction.
+
+ This restriction is used in four places, namely:
+ 'back_to_previous_line_start' and 'move_it_vertically_backward'
+ (with the 'SET_WITH_NARROWED_BEGV' macro), and in
+ 'composition_compute_stop_pos' and 'find_automatic_composition' (in
+ a conditional statement depending on 'long_line_optimizations_p').
+
+ (2.2) 'get_medium_narrowing_begv' is used to create a restriction
+ which starts a few thousand characters before point. The exact
+ number of characters depends on the size (width and height) of the
+ window in which the buffer is displayed. For performance reasons,
+ the return value of that function is cached in 'struct it', in the
+ 'medium_narrowing_begv' field.
+
+ The corresponding function 'get_medium_narrowing_zv' (and
+ 'medium_narrowing_zv' field in 'struct it') is not used to set the
+ end limit of a the restriction, which is again unnecessary, but to
+ determine, in 'reseat', whether the iterator has moved far enough
+ from its original position, and whether the start position of the
+ restriction must be computed anew.
+
+ This restriction is used in a single place:
+ 'get_visually_first_element', with the 'SET_WITH_NARROWED_BEGV'
+ macro.
+
+ (2.3) 'get_large_narrowing_begv' and 'get_large_narrowing_zv' are
+ used to create a restriction which starts a few hundred thousand
+ characters before point and ends a few hundred thousand characters
+ after point. The size of that restriction depends on the variable
+ 'long-line-optimizations-region-size', whose default value is
+ 500000 (characters); it can be adjusted by a few hundred characters
+ depending on 'long-line-optimizations-bol-search-limit', whose
+ default value is 128 (characters).
+
+ For performance reasons again, the return values of these functions
+ are stored in the 'large_narrowing_begv' and 'large_narrowing_zv'
+ fields in 'struct it'.
+
+ The restriction defined by these values is used around three
+ low-level hooks: around 'fontification-functions', in
+ 'handle_fontified_prop', and around 'pre-command-hook' and
+ 'post-command-hook', in 'safe_run_hooks_maybe_narrowed', which is
+ called in 'command_loop_1'. These restrictions are set around
+ these hooks with 'labeled_narrow_to_region'; the restrictions are
+ labeled, and cannot be removed with a call to 'widen', but can be
+ removed with 'without-restriction' with a :label argument.
+*/
static int
get_narrowed_width (struct window *w)
@@ -3513,28 +3595,28 @@ get_narrowed_len (struct window *w)
}
ptrdiff_t
-get_narrowed_begv (struct window *w, ptrdiff_t pos)
+get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
{
int len = get_narrowed_len (w);
return max ((pos / len - 1) * len, BEGV);
}
ptrdiff_t
-get_narrowed_zv (struct window *w, ptrdiff_t pos)
+get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
{
int len = get_narrowed_len (w);
return min ((pos / len + 1) * len, ZV);
}
ptrdiff_t
-get_closer_narrowed_begv (struct window *w, ptrdiff_t pos)
+get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
{
int len = get_narrowed_width (w);
return max ((pos / len - 1) * len, BEGV);
}
ptrdiff_t
-get_locked_narrowing_begv (ptrdiff_t pos)
+get_large_narrowing_begv (ptrdiff_t pos)
{
if (long_line_optimizations_region_size <= 0)
return BEGV;
@@ -3552,7 +3634,7 @@ get_locked_narrowing_begv (ptrdiff_t pos)
}
ptrdiff_t
-get_locked_narrowing_zv (ptrdiff_t pos)
+get_large_narrowing_zv (ptrdiff_t pos)
{
if (long_line_optimizations_region_size <= 0)
return ZV;
@@ -3571,7 +3653,7 @@ unwind_narrowed_begv (Lisp_Object point_min)
#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
do { \
- if (IT->narrowed_begv) \
+ if (IT->medium_narrowing_begv) \
{ \
specpdl_ref count = SPECPDL_INDEX (); \
record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
@@ -4396,17 +4478,17 @@ handle_fontified_prop (struct it *it)
if (current_buffer->long_line_optimizations_p
&& long_line_optimizations_region_size > 0)
{
- ptrdiff_t begv = it->locked_narrowing_begv;
- ptrdiff_t zv = it->locked_narrowing_zv;
+ ptrdiff_t begv = it->large_narrowing_begv;
+ ptrdiff_t zv = it->large_narrowing_zv;
ptrdiff_t charpos = IT_CHARPOS (*it);
if (charpos < begv || charpos > zv)
{
- begv = get_locked_narrowing_begv (charpos);
- zv = get_locked_narrowing_zv (charpos);
+ begv = get_large_narrowing_begv (charpos);
+ zv = get_large_narrowing_zv (charpos);
}
if (begv != BEG || zv != Z)
- narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
- Qlong_line_optimizations_in_fontification_functions);
+ labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
+ Qlong_line_optimizations_in_fontification_functions);
}
/* Don't allow Lisp that runs from 'fontification-functions'
@@ -7041,7 +7123,7 @@ back_to_previous_line_start (struct it *it)
dec_both (&cp, &bp);
SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
- get_closer_narrowed_begv (it->w, IT_CHARPOS (*it)));
+ get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
}
/* Find in the current buffer the first display or overlay string
@@ -7345,7 +7427,7 @@ back_to_previous_visible_line_start (struct it *it)
it->continuation_lines_width = 0;
eassert (IT_CHARPOS (*it) >= BEGV);
- eassert (it->narrowed_begv > 0 /* long-line optimizations: all bets off */
+ eassert (it->medium_narrowing_begv > 0 /* long-line optimizations: all bets off */
|| IT_CHARPOS (*it) == BEGV
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
CHECK_IT (it);
@@ -7463,24 +7545,29 @@ reseat (struct it *it, struct text_pos pos, bool force_p)
if (current_buffer->long_line_optimizations_p)
{
- if (!it->narrowed_begv)
+ if (!it->medium_narrowing_begv)
{
- it->narrowed_begv = get_narrowed_begv (it->w, window_point (it->w));
- it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w));
- it->locked_narrowing_begv
- = get_locked_narrowing_begv (window_point (it->w));
- it->locked_narrowing_zv
- = get_locked_narrowing_zv (window_point (it->w));
+ it->medium_narrowing_begv
+ = get_medium_narrowing_begv (it->w, window_point (it->w));
+ it->medium_narrowing_zv
+ = get_medium_narrowing_zv (it->w, window_point (it->w));
+ it->large_narrowing_begv
+ = get_large_narrowing_begv (window_point (it->w));
+ it->large_narrowing_zv
+ = get_large_narrowing_zv (window_point (it->w));
}
- else if ((pos.charpos < it->narrowed_begv || pos.charpos > it->narrowed_zv)
+ else if ((pos.charpos < it->medium_narrowing_begv
+ || pos.charpos > it->medium_narrowing_zv)
&& (!redisplaying_p || it->line_wrap == TRUNCATE))
{
- it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos);
- it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos);
- it->locked_narrowing_begv
- = get_locked_narrowing_begv (window_point (it->w));
- it->locked_narrowing_zv
- = get_locked_narrowing_zv (window_point (it->w));
+ it->medium_narrowing_begv
+ = get_medium_narrowing_begv (it->w, pos.charpos);
+ it->medium_narrowing_zv
+ = get_medium_narrowing_zv (it->w, pos.charpos);
+ it->large_narrowing_begv
+ = get_large_narrowing_begv (window_point (it->w));
+ it->large_narrowing_zv
+ = get_large_narrowing_zv (window_point (it->w));
}
}
@@ -8789,7 +8876,7 @@ get_visually_first_element (struct it *it)
SET_WITH_NARROWED_BEGV (it, bob,
string_p ? 0 :
IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
- it->narrowed_begv);
+ it->medium_narrowing_begv);
if (STRINGP (it->string))
{
@@ -8833,7 +8920,7 @@ get_visually_first_element (struct it *it)
find_newline_no_quit (IT_CHARPOS (*it),
IT_BYTEPOS (*it), -1,
&it->bidi_it.bytepos),
- it->narrowed_begv);
+ it->medium_narrowing_begv);
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
do
{
@@ -10722,7 +10809,7 @@ move_it_vertically_backward (struct it *it, int dy)
dec_both (&cp, &bp);
SET_WITH_NARROWED_BEGV (it, cp,
find_newline_no_quit (cp, bp, -1, NULL),
- get_closer_narrowed_begv (it->w, IT_CHARPOS (*it)));
+ get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
}
bidi_unshelve_cache (it3data, true);
@@ -16394,7 +16481,7 @@ redisplay_internal (void)
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->already_hscrolled_p = false;
- reset_outermost_narrowings ();
+ reset_outermost_restrictions ();
retry:
/* Remember the currently selected window. */