Improvements to long lines handling.
* src/buffer.h (struct buffer): New field 'long_line_optimizations_p'. * src/buffer.c (syms_of_buffer): New variable 'long-line-threshold'. (reset_buffer): Initialize the 'long_line_optimizations_p' field. (Fbuffer_swap_text): Handle it. * src/xdisp.c (redisplay_window): Set 'long_line_optimizations_p' when a buffer contains long lines. (init_iterator): Use 'long_line_optimizations_p'. (get_narrowed_begv): Update. (SET_WITH_NARROWED_BEGV): New macro. (unwind_narrowed_begv): New internal function used by the new macro. (back_to_previous_line_start, get_visually_first_element, move_it_vertically_backward): Use the new macro. * src/search.c (find_newline1): Make it externally visible. * src/lisp.h: Make 'find_newline1' externally visible. * src/dispextern.h (struct it): Update comment. Remove the 'WITH_NARROWED_BEGV' macro. * etc/NEWS: Mention the 'long-line-threshold' variable.
This commit is contained in:
parent
9de00e5fda
commit
e7b5912b23
7 changed files with 79 additions and 31 deletions
4
etc/NEWS
4
etc/NEWS
|
@ -332,7 +332,9 @@ experience slowdowns while editing files with long lines, this is
|
||||||
either due to font locking, which you can turn off with M-x
|
either due to font locking, which you can turn off with M-x
|
||||||
font-lock-mode, or to the current major mode or one of the enabled
|
font-lock-mode, or to the current major mode or one of the enabled
|
||||||
minor modes, in which case you should open the the file with M-x
|
minor modes, in which case you should open the the file with M-x
|
||||||
find-file-literally instead of C-x C-f.
|
find-file-literally instead of C-x C-f. The variable
|
||||||
|
'long-line-threshold' controls whether and when these display
|
||||||
|
optimizations are used.
|
||||||
|
|
||||||
+++
|
+++
|
||||||
** New command to change the font size globally.
|
** New command to change the font size globally.
|
||||||
|
|
10
src/buffer.c
10
src/buffer.c
|
@ -984,6 +984,7 @@ reset_buffer (register struct buffer *b)
|
||||||
/* It is more conservative to start out "changed" than "unchanged". */
|
/* It is more conservative to start out "changed" than "unchanged". */
|
||||||
b->clip_changed = 0;
|
b->clip_changed = 0;
|
||||||
b->prevent_redisplay_optimizations_p = 1;
|
b->prevent_redisplay_optimizations_p = 1;
|
||||||
|
b->long_line_optimizations_p = 0;
|
||||||
bset_backed_up (b, Qnil);
|
bset_backed_up (b, Qnil);
|
||||||
bset_local_minor_modes (b, Qnil);
|
bset_local_minor_modes (b, Qnil);
|
||||||
BUF_AUTOSAVE_MODIFF (b) = 0;
|
BUF_AUTOSAVE_MODIFF (b) = 0;
|
||||||
|
@ -2445,6 +2446,7 @@ results, see Info node `(elisp)Swapping Text'. */)
|
||||||
swapfield (bidi_paragraph_cache, struct region_cache *);
|
swapfield (bidi_paragraph_cache, struct region_cache *);
|
||||||
current_buffer->prevent_redisplay_optimizations_p = 1;
|
current_buffer->prevent_redisplay_optimizations_p = 1;
|
||||||
other_buffer->prevent_redisplay_optimizations_p = 1;
|
other_buffer->prevent_redisplay_optimizations_p = 1;
|
||||||
|
swapfield (long_line_optimizations_p, bool_bf);
|
||||||
swapfield (overlays_before, struct Lisp_Overlay *);
|
swapfield (overlays_before, struct Lisp_Overlay *);
|
||||||
swapfield (overlays_after, struct Lisp_Overlay *);
|
swapfield (overlays_after, struct Lisp_Overlay *);
|
||||||
swapfield (overlay_center, ptrdiff_t);
|
swapfield (overlay_center, ptrdiff_t);
|
||||||
|
@ -6423,6 +6425,14 @@ Since `clone-indirect-buffer' calls `make-indirect-buffer', this hook
|
||||||
will run for `clone-indirect-buffer' calls as well. */);
|
will run for `clone-indirect-buffer' calls as well. */);
|
||||||
Vclone_indirect_buffer_hook = Qnil;
|
Vclone_indirect_buffer_hook = Qnil;
|
||||||
|
|
||||||
|
DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold,
|
||||||
|
doc: /* Line length above which specific display optimizations are used.
|
||||||
|
Display optimizations for long lines will automatically be enabled in
|
||||||
|
buffers which contain one or more lines whose length is above that
|
||||||
|
threshold.
|
||||||
|
When nil, these display optimizations are disabled. */);
|
||||||
|
XSETFASTINT (Vlong_line_threshold, 10000);
|
||||||
|
|
||||||
defsubr (&Sbuffer_live_p);
|
defsubr (&Sbuffer_live_p);
|
||||||
defsubr (&Sbuffer_list);
|
defsubr (&Sbuffer_list);
|
||||||
defsubr (&Sget_buffer);
|
defsubr (&Sget_buffer);
|
||||||
|
|
|
@ -681,6 +681,10 @@ struct buffer
|
||||||
defined, as well as by with-temp-buffer, for example. */
|
defined, as well as by with-temp-buffer, for example. */
|
||||||
bool_bf inhibit_buffer_hooks : 1;
|
bool_bf inhibit_buffer_hooks : 1;
|
||||||
|
|
||||||
|
/* Non-zero when the buffer contains long lines and specific
|
||||||
|
display optimizations must be used. */
|
||||||
|
bool_bf long_line_optimizations_p : 1;
|
||||||
|
|
||||||
/* List of overlays that end at or before the current center,
|
/* List of overlays that end at or before the current center,
|
||||||
in order of end-position. */
|
in order of end-position. */
|
||||||
struct Lisp_Overlay *overlays_before;
|
struct Lisp_Overlay *overlays_before;
|
||||||
|
|
|
@ -2332,8 +2332,8 @@ struct it
|
||||||
with which display_string was called. */
|
with which display_string was called. */
|
||||||
ptrdiff_t end_charpos;
|
ptrdiff_t end_charpos;
|
||||||
|
|
||||||
/* Alternate begin position of the buffer, which is used to optimize
|
/* Alternate begin position of the buffer that may be used to
|
||||||
display (see the WITH_NARROWED_BEGV macro below). */
|
optimize display (see the WITH_NARROWED_BEGV macro below). */
|
||||||
ptrdiff_t narrowed_begv;
|
ptrdiff_t narrowed_begv;
|
||||||
|
|
||||||
/* C string to iterate over. Non-null means get characters from
|
/* C string to iterate over. Non-null means get characters from
|
||||||
|
@ -2817,18 +2817,6 @@ struct it
|
||||||
reset_box_start_end_flags ((IT)); \
|
reset_box_start_end_flags ((IT)); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
/* Execute STATEMENT with a temporarily narrowed buffer. */
|
|
||||||
|
|
||||||
#define WITH_NARROWED_BEGV(STATEMENT) \
|
|
||||||
do { \
|
|
||||||
ptrdiff_t obegv = BEGV; \
|
|
||||||
if (it->narrowed_begv) \
|
|
||||||
SET_BUF_BEGV (current_buffer, it->narrowed_begv); \
|
|
||||||
STATEMENT; \
|
|
||||||
if (it->narrowed_begv) \
|
|
||||||
SET_BUF_BEGV (current_buffer, obegv); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Bit-flags indicating what operation move_it_to should perform. */
|
/* Bit-flags indicating what operation move_it_to should perform. */
|
||||||
|
|
||||||
enum move_operation_enum
|
enum move_operation_enum
|
||||||
|
|
|
@ -4761,6 +4761,8 @@ extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
|
||||||
ptrdiff_t);
|
ptrdiff_t);
|
||||||
extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
|
extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
|
||||||
ptrdiff_t, ptrdiff_t, Lisp_Object);
|
ptrdiff_t, ptrdiff_t, Lisp_Object);
|
||||||
|
extern ptrdiff_t find_newline1 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||||
|
ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
|
||||||
extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||||
ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
|
ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
|
||||||
extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||||
|
|
|
@ -3192,7 +3192,7 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like find_newline, but doesn't use the cache, and only searches forward. */
|
/* Like find_newline, but doesn't use the cache, and only searches forward. */
|
||||||
static ptrdiff_t
|
ptrdiff_t
|
||||||
find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
||||||
ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
|
ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
|
||||||
ptrdiff_t *bytepos, bool allow_quit)
|
ptrdiff_t *bytepos, bool allow_quit)
|
||||||
|
|
72
src/xdisp.c
72
src/xdisp.c
|
@ -3425,7 +3425,8 @@ init_iterator (struct it *it, struct window *w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it->narrowed_begv = get_narrowed_begv (w);
|
if (current_buffer->long_line_optimizations_p)
|
||||||
|
it->narrowed_begv = get_narrowed_begv (w);
|
||||||
|
|
||||||
/* If a buffer position was specified, set the iterator there,
|
/* If a buffer position was specified, set the iterator there,
|
||||||
getting overlays and face properties from that position. */
|
getting overlays and face properties from that position. */
|
||||||
|
@ -3493,20 +3494,43 @@ init_iterator (struct it *it, struct window *w,
|
||||||
CHECK_IT (it);
|
CHECK_IT (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute a suitable value for BEGV that can be used temporarily, to
|
/* Compute a suitable alternate value for BEGV that may be used
|
||||||
optimize display, for the buffer in window W. */
|
temporarily to optimize display if the buffer in window W contains
|
||||||
|
long lines. */
|
||||||
|
|
||||||
ptrdiff_t
|
ptrdiff_t
|
||||||
get_narrowed_begv (struct window *w)
|
get_narrowed_begv (struct window *w)
|
||||||
{
|
{
|
||||||
int len; ptrdiff_t begv;
|
int len; ptrdiff_t begv;
|
||||||
len = (1 + ((window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
|
len = 3 * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
|
||||||
window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS)) /
|
window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
|
||||||
10000)) * 10000;
|
begv = max ((window_point (w) / len - 1) * len, BEGV);
|
||||||
begv = max ((PT / len - 2) * len, BEGV);
|
|
||||||
return begv == BEGV ? 0 : begv;
|
return begv == BEGV ? 0 : begv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unwind_narrowed_begv (Lisp_Object point_min)
|
||||||
|
{
|
||||||
|
SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set DST to EXPR. When IT indicates that BEGV should temporarily be
|
||||||
|
updated to optimize display, evaluate EXPR with an updated BEGV. */
|
||||||
|
|
||||||
|
#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR) \
|
||||||
|
do { \
|
||||||
|
if (IT->narrowed_begv) \
|
||||||
|
{ \
|
||||||
|
specpdl_ref count = SPECPDL_INDEX (); \
|
||||||
|
record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
|
||||||
|
SET_BUF_BEGV (current_buffer, IT->narrowed_begv); \
|
||||||
|
DST = EXPR; \
|
||||||
|
unbind_to (count, Qnil); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
DST = EXPR; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Initialize IT for the display of window W with window start POS. */
|
/* Initialize IT for the display of window W with window start POS. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -7007,8 +7031,8 @@ back_to_previous_line_start (struct it *it)
|
||||||
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
||||||
|
|
||||||
dec_both (&cp, &bp);
|
dec_both (&cp, &bp);
|
||||||
WITH_NARROWED_BEGV (IT_CHARPOS (*it) =
|
SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
|
||||||
find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
|
find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8642,7 +8666,7 @@ get_visually_first_element (struct it *it)
|
||||||
ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
|
ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
|
||||||
ptrdiff_t bob;
|
ptrdiff_t bob;
|
||||||
|
|
||||||
WITH_NARROWED_BEGV (bob = (string_p ? 0 : BEGV));
|
SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : BEGV);
|
||||||
|
|
||||||
if (STRINGP (it->string))
|
if (STRINGP (it->string))
|
||||||
{
|
{
|
||||||
|
@ -8682,10 +8706,10 @@ get_visually_first_element (struct it *it)
|
||||||
if (string_p)
|
if (string_p)
|
||||||
it->bidi_it.charpos = it->bidi_it.bytepos = 0;
|
it->bidi_it.charpos = it->bidi_it.bytepos = 0;
|
||||||
else
|
else
|
||||||
WITH_NARROWED_BEGV (it->bidi_it.charpos =
|
SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
|
||||||
find_newline_no_quit (IT_CHARPOS (*it),
|
find_newline_no_quit (IT_CHARPOS (*it),
|
||||||
IT_BYTEPOS (*it), -1,
|
IT_BYTEPOS (*it), -1,
|
||||||
&it->bidi_it.bytepos));
|
&it->bidi_it.bytepos));
|
||||||
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
|
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -10603,7 +10627,8 @@ move_it_vertically_backward (struct it *it, int dy)
|
||||||
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
||||||
|
|
||||||
dec_both (&cp, &bp);
|
dec_both (&cp, &bp);
|
||||||
WITH_NARROWED_BEGV (cp = find_newline_no_quit (cp, bp, -1, NULL));
|
SET_WITH_NARROWED_BEGV (it, cp,
|
||||||
|
find_newline_no_quit (cp, bp, -1, NULL));
|
||||||
move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
|
move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
|
||||||
}
|
}
|
||||||
bidi_unshelve_cache (it3data, true);
|
bidi_unshelve_cache (it3data, true);
|
||||||
|
@ -19245,6 +19270,23 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether the buffer to be displayed contains long lines. */
|
||||||
|
if (!NILP (Vlong_line_threshold)
|
||||||
|
&& !current_buffer->long_line_optimizations_p
|
||||||
|
&& MODIFF != UNCHANGED_MODIFIED)
|
||||||
|
{
|
||||||
|
ptrdiff_t cur, next, found, max = 0;
|
||||||
|
for (cur = 1; cur < Z; cur = next)
|
||||||
|
{
|
||||||
|
next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
|
||||||
|
&found, NULL, true);
|
||||||
|
if (next - cur > max) max = next - cur;
|
||||||
|
if (!found || max > XFIXNUM (Vlong_line_threshold)) break;
|
||||||
|
}
|
||||||
|
if (max > XFIXNUM (Vlong_line_threshold))
|
||||||
|
current_buffer->long_line_optimizations_p = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* If window-start is screwed up, choose a new one. */
|
/* If window-start is screwed up, choose a new one. */
|
||||||
if (XMARKER (w->start)->buffer != current_buffer)
|
if (XMARKER (w->start)->buffer != current_buffer)
|
||||||
goto recenter;
|
goto recenter;
|
||||||
|
|
Loading…
Add table
Reference in a new issue