From 558084c7f736bebcb3cffc2bf4f617158d92357f Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Sat, 26 Nov 2022 14:09:41 +0000 Subject: [PATCH] Improve locked narrowing around low-level hooks. * src/buffer.c (syms_of_buffer): Two new variables, 'long-line-locked-narrowing-region-size' and 'long-line-locked-narrowing-bol-search-limit', to make the locked narrowing around low-level hooks configurable. Increase the default value of 'long-line-threshold'. After carefully considering the (few) bug reports about long line optimizations, I concluded that the previous default value was too low. * src/xdisp.c (get_locked_narrowing_begv) (get_locked_narrowing_zv): Two new functions. (handle_fontified_prop, reseat): Use them. * src/keyboard.c (safe_run_hooks_maybe_narrowed): Use them. * src/dispextern.h (struct it): Add two new fields to store the values returned by these functions. Make them externally visible. * src/editfns.c: (Fsave_restriction): Update docstring. --- src/buffer.c | 35 ++++++++++++++++++++++++++++++++++- src/dispextern.h | 10 ++++++++++ src/editfns.c | 11 ++++++----- src/keyboard.c | 4 ++-- src/xdisp.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index d948aaa2662..ef7e6f18340 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5882,7 +5882,40 @@ this threshold. If nil, these display shortcuts will always remain disabled. There is no reason to change that value except for debugging purposes. */); - XSETFASTINT (Vlong_line_threshold, 10000); + XSETFASTINT (Vlong_line_threshold, 50000); + + DEFVAR_INT ("long-line-locked-narrowing-region-size", + long_line_locked_narrowing_region_size, + doc: /* Region size for locked narrowing in buffers with long lines. + +This variable has effect only in buffers which contain one or more +lines whose length is above `long-line-threshold', which see. For +performance reasons, in such buffers, low-level hooks such as +`fontification-functions' or `post-command-hook' are executed on a +narrowed buffer, with a narrowing locked with `narrowing-lock'. This +variable specifies the size of the narrowed region around point. + +To disable that narrowing, set this variable to 0. + +There is no reason to change that value except for debugging purposes. */); + long_line_locked_narrowing_region_size = 500000; + + DEFVAR_INT ("long-line-locked-narrowing-bol-search-limit", + long_line_locked_narrowing_bol_search_limit, + doc: /* Limit for beginning of line search in buffers with long lines. + +This variable has effect only in buffers which contain one or more +lines whose length is above `long-line-threshold', which see. For +performance reasons, in such buffers, low-level hooks such as +`fontification-functions' or `post-command-hook' are executed on a +narrowed buffer, with a narrowing locked with `narrowing-lock'. The +variable `long-line-locked-narrowing-region-size' specifies the size +of the narrowed region around point. This variable, which should be a +small integer, specifies the number of characters by which that region +can be extended backwards to start it at the beginning of a line. + +There is no reason to change that value except for debugging purposes. */); + long_line_locked_narrowing_bol_search_limit = 128; DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold, doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts. diff --git a/src/dispextern.h b/src/dispextern.h index 2afbdeabaab..df6134e68f0 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2342,6 +2342,14 @@ struct it optimize display. */ ptrdiff_t narrowed_zv; + /* Begin position of the buffer for the locked narrowing around + low-level hooks. */ + ptrdiff_t locked_narrowing_begv; + + /* End position of the buffer for the locked narrowing around + low-level hooks. */ + ptrdiff_t locked_narrowing_zv; + /* C string to iterate over. Non-null means get characters from this string, otherwise characters are read from current_buffer or it->string. */ @@ -3405,6 +3413,8 @@ void init_iterator (struct it *, struct window *, ptrdiff_t, ptrdiff_t get_narrowed_begv (struct window *, ptrdiff_t); ptrdiff_t get_narrowed_zv (struct window *, ptrdiff_t); ptrdiff_t get_closer_narrowed_begv (struct window *, ptrdiff_t); +ptrdiff_t get_locked_narrowing_begv (ptrdiff_t); +ptrdiff_t get_locked_narrowing_zv (ptrdiff_t); void init_iterator_to_row_start (struct it *, struct window *, struct glyph_row *); void start_display (struct it *, struct window *, struct text_pos); diff --git a/src/editfns.c b/src/editfns.c index f73331fb53c..e6b66209b8b 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2659,7 +2659,7 @@ DEFUN ("delete-and-extract-region", Fdelete_and_extract_region, the (uninterned) Qoutermost_narrowing tag and records the narrowing bounds that were set by the user and that are visible on display. This alist is used internally by narrow-to-region, widen, - narrowing-lock and narrowing-unlock. */ + narrowing-lock, narrowing-unlock and save-restriction. */ static Lisp_Object narrowing_locks; /* Retrieve one of the BEGV/ZV bounds of a narrowing in BUF from the @@ -3061,11 +3061,12 @@ DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0 doc: /* Execute BODY, saving and restoring current buffer's restrictions. The buffer's restrictions make parts of the beginning and end invisible. \(They are set up with `narrow-to-region' and eliminated with `widen'.) -This special form, `save-restriction', saves the current buffer's restrictions -when it is entered, and restores them when it is exited. +This special form, `save-restriction', saves the current buffer's +restrictions, as well as their locks if they have been locked with +`narrowing-lock', when it is entered, and restores them when it is exited. So any `narrow-to-region' within BODY lasts only until the end of the form. -The old restrictions settings are restored -even in case of abnormal exit (throw or error). +The old restrictions settings are restored even in case of abnormal exit +\(throw or error). The value returned is the value of the last form in BODY. diff --git a/src/keyboard.c b/src/keyboard.c index 4b35a044eb0..cb308f5bfc1 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1911,8 +1911,8 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w) specbind (Qinhibit_quit, Qt); if (current_buffer->long_line_optimizations_p) - narrow_to_region_locked (make_fixnum (get_narrowed_begv (w, PT)), - make_fixnum (get_narrowed_zv (w, PT)), + narrow_to_region_locked (make_fixnum (get_locked_narrowing_begv (PT)), + make_fixnum (get_locked_narrowing_zv (PT)), hook); run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), diff --git a/src/xdisp.c b/src/xdisp.c index 658ce57b7ea..430201874c3 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3533,6 +3533,34 @@ get_closer_narrowed_begv (struct window *w, ptrdiff_t pos) return max ((pos / len - 1) * len, BEGV); } +ptrdiff_t +get_locked_narrowing_begv (ptrdiff_t pos) +{ + if (long_line_locked_narrowing_region_size == 0) + return BEGV; + int begv; + int len = long_line_locked_narrowing_region_size / 2; + begv = max (pos - len, BEGV); + int limit = long_line_locked_narrowing_bol_search_limit; + while (limit) + { + if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n') + return begv; + begv--; + limit--; + } + return begv; +} + +ptrdiff_t +get_locked_narrowing_zv (ptrdiff_t pos) +{ + if (long_line_locked_narrowing_region_size == 0) + return ZV; + int len = long_line_locked_narrowing_region_size / 2; + return min (pos + len, ZV); +} + static void unwind_narrowed_begv (Lisp_Object point_min) { @@ -4368,13 +4396,13 @@ handle_fontified_prop (struct it *it) if (current_buffer->long_line_optimizations_p) { - ptrdiff_t begv = it->narrowed_begv; - ptrdiff_t zv = it->narrowed_zv; + ptrdiff_t begv = it->locked_narrowing_begv; + ptrdiff_t zv = it->locked_narrowing_zv; ptrdiff_t charpos = IT_CHARPOS (*it); if (charpos < begv || charpos > zv) { - begv = get_narrowed_begv (it->w, charpos); - zv = get_narrowed_zv (it->w, charpos); + begv = get_locked_narrowing_begv (charpos); + zv = get_locked_narrowing_zv (charpos); } narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), Qfontification_functions); @@ -7435,12 +7463,20 @@ reseat (struct it *it, struct text_pos pos, bool force_p) { 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)); } else if ((pos.charpos < it->narrowed_begv || pos.charpos > it->narrowed_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)); } }