1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-13 06:50:39 -08:00

Merge branch 'feature/long-lines-improvements'

This commit is contained in:
Gregory Heytings 2022-08-04 21:19:36 +02:00
commit 5a79bb2aed
6 changed files with 88 additions and 30 deletions

View file

@ -6431,12 +6431,15 @@ will run for `clone-indirect-buffer' calls as well. */);
DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold,
doc: /* Line length above which to use redisplay shortcuts.
The value should be a positive integer or nil.
If the value is an integer, shortcuts in the display code intended
to speed up redisplay for long lines will automatically be enabled
in buffers which contain one or more lines whose length is above
this threshold.
If nil, these display shortcuts will always remain disabled. */);
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);
defsubr (&Sbuffer_live_p);

View file

@ -1021,7 +1021,11 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
/* But we don't know where to stop the searching. */
endpos = NILP (string) ? BEGV - 1 : -1;
/* Usually we don't reach ENDPOS because we stop searching
at an uncomposable character (NL, LRE, etc). */
at an uncomposable character (NL, LRE, etc). In buffers
with long lines, however, NL might be far away, so
pretend that the buffer is smaller. */
if (current_buffer->long_line_optimizations_p)
endpos = get_closer_narrowed_begv (cmp_it->parent_it->w, charpos);
}
}
cmp_it->id = -1;
@ -1580,7 +1584,6 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
Lisp_Object window;
struct window *w;
bool need_adjustment = 0;
ptrdiff_t narrowed_begv;
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
if (NILP (window))
@ -1597,11 +1600,14 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
}
else
head = backlim;
/* In buffers with very long lines, this function becomes very
slow. Pretend that the buffer is narrowed to make it fast. */
narrowed_begv = get_narrowed_begv (w, window_point (w));
if (narrowed_begv && pos > narrowed_begv)
head = narrowed_begv;
if (current_buffer->long_line_optimizations_p)
{
/* In buffers with very long lines, this function becomes very
slow. Pretend that the buffer is narrowed to make it fast. */
ptrdiff_t begv = get_closer_narrowed_begv (w, window_point (w));
if (pos > begv)
head = begv;
}
tail = ZV;
stop = GPT;
cur.pos_byte = CHAR_TO_BYTE (cur.pos);

View file

@ -2287,6 +2287,8 @@ struct composition_it
reverse order, and thus the grapheme clusters must be rendered
from the last to the first. */
bool reversed_p;
/* Parent iterator. */
struct it *parent_it;
/** The following members contain information about the current
grapheme cluster. */

View file

@ -1295,7 +1295,8 @@ command_loop_1 (void)
/* Note that the value cell will never directly contain nil
if the symbol is a local variable. */
if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpost_command_hook);
safe_run_hooks_maybe_narrowed (Qpost_command_hook,
XWINDOW (selected_window));
/* If displaying a message, resize the echo area window to fit
that message's size exactly. */
@ -1461,7 +1462,9 @@ command_loop_1 (void)
}
Vthis_command = cmd;
Vreal_this_command = cmd;
safe_run_hooks (Qpre_command_hook);
safe_run_hooks_maybe_narrowed (Qpre_command_hook,
XWINDOW (selected_window));
already_adjusted = 0;
@ -1513,7 +1516,8 @@ command_loop_1 (void)
}
kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg);
safe_run_hooks (Qpost_command_hook);
safe_run_hooks_maybe_narrowed (Qpost_command_hook,
XWINDOW (selected_window));
/* If displaying a message, resize the echo area window to fit
that message's size exactly. Do this only if the echo area
@ -1895,6 +1899,22 @@ safe_run_hooks (Lisp_Object hook)
unbind_to (count, Qnil);
}
void
safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
{
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
if (current_buffer->long_line_optimizations_p)
narrow_to_region_internal (make_fixnum (get_narrowed_begv (w, PT)),
make_fixnum (get_narrowed_zv (w, PT)),
true);
run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), safe_run_hook_funcall);
unbind_to (count, Qnil);
}
/* Nonzero means polling for input is temporarily suppressed. */
@ -12622,23 +12642,39 @@ Buffer modification stores t in this variable. */);
DEFVAR_LISP ("pre-command-hook", Vpre_command_hook,
doc: /* Normal hook run before each command is executed.
If an unhandled error happens in running this hook,
the function in which the error occurred is unconditionally removed, since
otherwise the error might happen repeatedly and make Emacs nonfunctional.
If an unhandled error happens in running this hook, the function in
which the error occurred is unconditionally removed, since otherwise
the error might happen repeatedly and make Emacs nonfunctional.
Note that, when the current buffer contains one or more lines whose
length is above `long-line-threshold', these hook functions are called
with the buffer narrowed to a small portion around point, and the
narrowing is locked (see `narrow-to-region'), so that these hook
functions cannot use `widen' to gain access to other portions of
buffer text.
See also `post-command-hook'. */);
Vpre_command_hook = Qnil;
DEFVAR_LISP ("post-command-hook", Vpost_command_hook,
doc: /* Normal hook run after each command is executed.
If an unhandled error happens in running this hook,
the function in which the error occurred is unconditionally removed, since
otherwise the error might happen repeatedly and make Emacs nonfunctional.
If an unhandled error happens in running this hook, the function in
which the error occurred is unconditionally removed, since otherwise
the error might happen repeatedly and make Emacs nonfunctional.
It is a bad idea to use this hook for expensive processing. If
unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to
avoid making Emacs unresponsive while the user types.
Note that, when the current buffer contains one or more lines whose
length is above `long-line-threshold', these hook functions are called
with the buffer narrowed to a small portion around point, and the
narrowing is locked (see `narrow-to-region'), so that these hook
functions cannot use `widen' to gain access to other portions of
buffer text.
See also `pre-command-hook'. */);
Vpost_command_hook = Qnil;

View file

@ -4830,6 +4830,7 @@ extern bool detect_input_pending (void);
extern bool detect_input_pending_ignore_squeezables (void);
extern bool detect_input_pending_run_timers (bool);
extern void safe_run_hooks (Lisp_Object);
extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
extern void cmd_error_internal (Lisp_Object, const char *);
extern Lisp_Object command_loop_2 (Lisp_Object);
extern Lisp_Object read_menu_command (void);

View file

@ -3229,6 +3229,7 @@ init_iterator (struct it *it, struct window *w,
it->f = XFRAME (w->frame);
it->cmp_it.id = -1;
it->cmp_it.parent_it = it;
if (max_redisplay_ticks > 0)
update_redisplay_ticks (0, w);
@ -3413,12 +3414,6 @@ init_iterator (struct it *it, struct window *w,
}
}
if (current_buffer->long_line_optimizations_p)
{
it->narrowed_begv = get_narrowed_begv (w, window_point (w));
it->narrowed_zv = get_narrowed_zv (w, window_point (w));
}
/* If a buffer position was specified, set the iterator there,
getting overlays and face properties from that position. */
if (charpos >= BUF_BEG (current_buffer))
@ -3478,6 +3473,9 @@ init_iterator (struct it *it, struct window *w,
&it->bidi_it);
}
if (current_buffer->long_line_optimizations_p)
it->narrowed_begv = 0;
/* Compute faces etc. */
reseat (it, it->current.pos, true);
}
@ -3510,9 +3508,7 @@ ptrdiff_t
get_narrowed_begv (struct window *w, ptrdiff_t pos)
{
int len = get_narrowed_len (w);
ptrdiff_t begv;
begv = max ((pos / len - 1) * len, BEGV);
return begv == BEGV ? 0 : begv;
return max ((pos / len - 1) * len, BEGV);
}
ptrdiff_t
@ -4397,13 +4393,12 @@ handle_fontified_prop (struct it *it)
if (current_buffer->long_line_optimizations_p)
{
ptrdiff_t begv = it->narrowed_begv ? it->narrowed_begv : BEGV;
ptrdiff_t begv = it->narrowed_begv;
ptrdiff_t zv = it->narrowed_zv;
ptrdiff_t charpos = IT_CHARPOS (*it);
if (charpos < begv || charpos > zv)
{
begv = get_narrowed_begv (it->w, charpos);
if (!begv) begv = BEGV;
zv = get_narrowed_zv (it->w, charpos);
}
narrow_to_region_internal (make_fixnum (begv), make_fixnum (zv), true);
@ -7533,6 +7528,21 @@ reseat (struct it *it, struct text_pos pos, bool force_p)
reseat_1 (it, pos, false);
if (current_buffer->long_line_optimizations_p)
{
if (!it->narrowed_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));
}
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);
}
}
/* Determine where to check text properties. Avoid doing it
where possible because text property lookup is very expensive. */
if (force_p
@ -8838,7 +8848,7 @@ get_visually_first_element (struct it *it)
SET_WITH_NARROWED_BEGV (it, bob,
string_p ? 0 :
IT_BYTEPOS (*it) < BEGV ? obegv : BEGV,
IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
it->narrowed_begv);
if (STRINGP (it->string))
@ -10773,7 +10783,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),
it->narrowed_begv);
get_closer_narrowed_begv (it->w, IT_CHARPOS (*it)));
move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
}
bidi_unshelve_cache (it3data, true);