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
|
||||
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
|
||||
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.
|
||||
|
|
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". */
|
||||
b->clip_changed = 0;
|
||||
b->prevent_redisplay_optimizations_p = 1;
|
||||
b->long_line_optimizations_p = 0;
|
||||
bset_backed_up (b, Qnil);
|
||||
bset_local_minor_modes (b, Qnil);
|
||||
BUF_AUTOSAVE_MODIFF (b) = 0;
|
||||
|
@ -2445,6 +2446,7 @@ results, see Info node `(elisp)Swapping Text'. */)
|
|||
swapfield (bidi_paragraph_cache, struct region_cache *);
|
||||
current_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_after, struct Lisp_Overlay *);
|
||||
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. */);
|
||||
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_list);
|
||||
defsubr (&Sget_buffer);
|
||||
|
|
|
@ -681,6 +681,10 @@ struct buffer
|
|||
defined, as well as by with-temp-buffer, for example. */
|
||||
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,
|
||||
in order of end-position. */
|
||||
struct Lisp_Overlay *overlays_before;
|
||||
|
|
|
@ -2332,8 +2332,8 @@ struct it
|
|||
with which display_string was called. */
|
||||
ptrdiff_t end_charpos;
|
||||
|
||||
/* Alternate begin position of the buffer, which is used to optimize
|
||||
display (see the WITH_NARROWED_BEGV macro below). */
|
||||
/* Alternate begin position of the buffer that may be used to
|
||||
optimize display (see the WITH_NARROWED_BEGV macro below). */
|
||||
ptrdiff_t narrowed_begv;
|
||||
|
||||
/* C string to iterate over. Non-null means get characters from
|
||||
|
@ -2817,18 +2817,6 @@ struct it
|
|||
reset_box_start_end_flags ((IT)); \
|
||||
} 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. */
|
||||
|
||||
enum move_operation_enum
|
||||
|
|
|
@ -4761,6 +4761,8 @@ extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
|
|||
ptrdiff_t);
|
||||
extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
|
||||
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,
|
||||
ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
|
||||
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. */
|
||||
static ptrdiff_t
|
||||
ptrdiff_t
|
||||
find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
|
||||
ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
|
||||
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,
|
||||
getting overlays and face properties from that position. */
|
||||
|
@ -3493,20 +3494,43 @@ init_iterator (struct it *it, struct window *w,
|
|||
CHECK_IT (it);
|
||||
}
|
||||
|
||||
/* Compute a suitable value for BEGV that can be used temporarily, to
|
||||
optimize display, for the buffer in window W. */
|
||||
/* Compute a suitable alternate value for BEGV that may be used
|
||||
temporarily to optimize display if the buffer in window W contains
|
||||
long lines. */
|
||||
|
||||
ptrdiff_t
|
||||
get_narrowed_begv (struct window *w)
|
||||
{
|
||||
int len; ptrdiff_t begv;
|
||||
len = (1 + ((window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
|
||||
window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS)) /
|
||||
10000)) * 10000;
|
||||
begv = max ((PT / len - 2) * len, BEGV);
|
||||
len = 3 * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
|
||||
window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
|
||||
begv = max ((window_point (w) / len - 1) * len, 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. */
|
||||
|
||||
void
|
||||
|
@ -7007,8 +7031,8 @@ back_to_previous_line_start (struct it *it)
|
|||
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
||||
|
||||
dec_both (&cp, &bp);
|
||||
WITH_NARROWED_BEGV (IT_CHARPOS (*it) =
|
||||
find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
|
||||
SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*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 bob;
|
||||
|
||||
WITH_NARROWED_BEGV (bob = (string_p ? 0 : BEGV));
|
||||
SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : BEGV);
|
||||
|
||||
if (STRINGP (it->string))
|
||||
{
|
||||
|
@ -8682,10 +8706,10 @@ get_visually_first_element (struct it *it)
|
|||
if (string_p)
|
||||
it->bidi_it.charpos = it->bidi_it.bytepos = 0;
|
||||
else
|
||||
WITH_NARROWED_BEGV (it->bidi_it.charpos =
|
||||
find_newline_no_quit (IT_CHARPOS (*it),
|
||||
IT_BYTEPOS (*it), -1,
|
||||
&it->bidi_it.bytepos));
|
||||
SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
|
||||
find_newline_no_quit (IT_CHARPOS (*it),
|
||||
IT_BYTEPOS (*it), -1,
|
||||
&it->bidi_it.bytepos));
|
||||
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
|
||||
do
|
||||
{
|
||||
|
@ -10603,7 +10627,8 @@ move_it_vertically_backward (struct it *it, int dy)
|
|||
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
|
||||
|
||||
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);
|
||||
}
|
||||
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 (XMARKER (w->start)->buffer != current_buffer)
|
||||
goto recenter;
|
||||
|
|
Loading…
Add table
Reference in a new issue