Code cleanup for long line optimizations
This commit does not change any code, it merely renames functions and clarifies the documentation, to make the code hopefully easier to grasp. * src/dispextern.h (struct it): Rename the 'narrowed_begv', 'narrowed_zv', 'locked_narrowing_begv', 'locked_narrowing_zv' to 'medium_narrowing_begv', 'medium_narrowing_zv', 'large_narrowing_begv', 'large_narrowing_zv'. Clarify the comments. Update the prototypes of the functions renamed in xdisp.c. * src/lisp.h: Update the prototypes of the functions renamed in editfns.c. Remove the prototype of 'safe_run_hooks_maybe_narrowed', which is used only in keyboard.c. * src/xdisp.c (get_small_narrowing_begv): Renamed from 'get_closer_narrowed_begv'. (get_medium_narrowing_begv): Renamed from 'get_narrowed_begv'. (get_medium_narrowing_zv): Renamed from 'get_narrowed_zv'. (get_large_narrowing_begv): Renamed from 'get_locked_narrowing_begv'. (get_large_narrowing_zv): Renamed from 'get_locked_narrowing_zv'. (SET_WITH_NARROWED_BEGV): Use the new field names. (handle_fontified_prop): Use the new function and new field names. (back_to_previous_line_start): Use the new field name. (back_to_previous_visible_line_start): Use the new field name. (reseat): Use the new function and new field names. (get_visually_first_element): Use the new field name. (move_it_vertically_backward): Use the new function name. (redisplay_internal): Use the new function name. Also add a large comment to explain how Emacs deals with long lines. * src/keyboard.c: (safe_run_hooks_maybe_narrowed): Use the new function names from xdisp.c and editfns.c. Make the function static, and add a prototype. * src/editfns.c: (labeled_restrictions): Renamed from 'narrowing_locks'. (labeled_restrictions_add): Renamed from 'narrowing_locks_add'. (labeled_restrictions_remove): Renamed from 'narrowing_locks_remove'. (labeled_restrictions_get_bound): Renamed from 'narrowing_lock_get_bound'. (labeled_restrictions_peek_label): Renamed from 'narrowing_lock_peek_tag'. (labeled_restrictions_push): Renamed from 'narrowing_lock_push'. (labeled_restrictions_pop): Renamed from 'narrowing_lock_pop'. (unwind_reset_outermost_restriction): Renamed from 'unwind_reset_outermost_narrowing'. (reset_outermost_restrictions): Renamed from 'reset_outermost_narrowings'. (labeled_restrictions_save): Renamed from 'narrowing_locks_save'. (labeled_restrictions_restore): Renamed from 'narrowing_locks_restore'. (unwind_labeled_narrow_to_region): Renamed from 'unwind_narrow_to_region_locked'. (labeled_narrow_to_region): Renamed from 'narrow_to_region_locked'. (Finternal__label_restriction): Renamed from 'Finternal__lock_narrowing'. (Finternal__unlabel_restriction): Renamed from 'Finternal__unlock_narrowing'. (Fwiden): Use the new function names. (Fnarrow_to_region): Use the new function names. (save_restriction_save): Use the new function names. (syms_of_editfns): Use the new function names. <outermost-restriction>: Renamed from 'outermost-narrowing'. * lisp/subr.el (internal--with-restriction): Use the new internal function name. (internal--without-restriction): Use the new internal function name. * src/composite.c (composition_compute_stop_pos): (find_automatic_composition): Use the new function name. * doc/lispref/positions.texi (Narrowing): Add index entry.
This commit is contained in:
parent
3965c65d5e
commit
85ed1c9ca6
8 changed files with 314 additions and 207 deletions
|
@ -1154,6 +1154,7 @@ saved bounds. In that case it is equivalent to
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@cindex labeled narrowing
|
@cindex labeled narrowing
|
||||||
|
@cindex labeled restriction
|
||||||
When the optional argument @var{label}, a symbol, is present, the
|
When the optional argument @var{label}, a symbol, is present, the
|
||||||
narrowing is @dfn{labeled}. A labeled narrowing differs from a
|
narrowing is @dfn{labeled}. A labeled narrowing differs from a
|
||||||
non-labeled one in several ways:
|
non-labeled one in several ways:
|
||||||
|
|
|
@ -3975,7 +3975,7 @@ same LABEL argument.
|
||||||
"Helper function for `with-restriction', which see."
|
"Helper function for `with-restriction', which see."
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(narrow-to-region start end)
|
(narrow-to-region start end)
|
||||||
(if label (internal--lock-narrowing label))
|
(if label (internal--label-restriction label))
|
||||||
(funcall body)))
|
(funcall body)))
|
||||||
|
|
||||||
(defmacro without-restriction (&rest rest)
|
(defmacro without-restriction (&rest rest)
|
||||||
|
@ -3997,7 +3997,7 @@ are lifted.
|
||||||
(defun internal--without-restriction (body &optional label)
|
(defun internal--without-restriction (body &optional label)
|
||||||
"Helper function for `without-restriction', which see."
|
"Helper function for `without-restriction', which see."
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(if label (internal--unlock-narrowing label))
|
(if label (internal--unlabel-restriction label))
|
||||||
(widen)
|
(widen)
|
||||||
(funcall body)))
|
(funcall body)))
|
||||||
|
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
|
||||||
with long lines, however, NL might be far away, so
|
with long lines, however, NL might be far away, so
|
||||||
pretend that the buffer is smaller. */
|
pretend that the buffer is smaller. */
|
||||||
if (current_buffer->long_line_optimizations_p)
|
if (current_buffer->long_line_optimizations_p)
|
||||||
endpos = get_closer_narrowed_begv (cmp_it->parent_it->w, charpos);
|
endpos = get_small_narrowing_begv (cmp_it->parent_it->w, charpos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmp_it->id = -1;
|
cmp_it->id = -1;
|
||||||
|
@ -1654,7 +1654,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
|
||||||
{
|
{
|
||||||
/* In buffers with very long lines, this function becomes very
|
/* In buffers with very long lines, this function becomes very
|
||||||
slow. Pretend that the buffer is narrowed to make it fast. */
|
slow. Pretend that the buffer is narrowed to make it fast. */
|
||||||
ptrdiff_t begv = get_closer_narrowed_begv (w, window_point (w));
|
ptrdiff_t begv = get_small_narrowing_begv (w, window_point (w));
|
||||||
if (pos > begv)
|
if (pos > begv)
|
||||||
head = begv;
|
head = begv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2334,21 +2334,20 @@ 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 that may be used to
|
/* Alternate begin and end positions of the buffer that are used to
|
||||||
optimize display (see the SET_WITH_NARROWED_BEGV macro). */
|
optimize display of buffers with long lines. These two fields
|
||||||
ptrdiff_t narrowed_begv;
|
hold the return value of the 'get_medium_narrowing_begv' and
|
||||||
|
'get_medium_narrowing_zv' functions. */
|
||||||
|
ptrdiff_t medium_narrowing_begv;
|
||||||
|
ptrdiff_t medium_narrowing_zv;
|
||||||
|
|
||||||
/* Alternate end position of the buffer that may be used to
|
/* Alternate begin and end positions of the buffer that are used for
|
||||||
optimize display. */
|
labeled narrowings around low-level hooks in buffers with long
|
||||||
ptrdiff_t narrowed_zv;
|
lines. These two fields hold the return value of the
|
||||||
|
'get_large_narrowing_begv' and 'get_large_narrowing_zv'
|
||||||
/* Begin position of the buffer for the locked narrowing around
|
functions. */
|
||||||
low-level hooks. */
|
ptrdiff_t large_narrowing_begv;
|
||||||
ptrdiff_t locked_narrowing_begv;
|
ptrdiff_t large_narrowing_zv;
|
||||||
|
|
||||||
/* 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
|
/* C string to iterate over. Non-null means get characters from
|
||||||
this string, otherwise characters are read from current_buffer
|
this string, otherwise characters are read from current_buffer
|
||||||
|
@ -3410,11 +3409,11 @@ void mark_window_display_accurate (Lisp_Object, bool);
|
||||||
void redisplay_preserve_echo_area (int);
|
void redisplay_preserve_echo_area (int);
|
||||||
void init_iterator (struct it *, struct window *, ptrdiff_t,
|
void init_iterator (struct it *, struct window *, ptrdiff_t,
|
||||||
ptrdiff_t, struct glyph_row *, enum face_id);
|
ptrdiff_t, struct glyph_row *, enum face_id);
|
||||||
ptrdiff_t get_narrowed_begv (struct window *, ptrdiff_t);
|
ptrdiff_t get_medium_narrowing_begv (struct window *, ptrdiff_t);
|
||||||
ptrdiff_t get_narrowed_zv (struct window *, ptrdiff_t);
|
ptrdiff_t get_medium_narrowing_zv (struct window *, ptrdiff_t);
|
||||||
ptrdiff_t get_closer_narrowed_begv (struct window *, ptrdiff_t);
|
ptrdiff_t get_small_narrowing_begv (struct window *, ptrdiff_t);
|
||||||
ptrdiff_t get_locked_narrowing_begv (ptrdiff_t);
|
ptrdiff_t get_large_narrowing_begv (ptrdiff_t);
|
||||||
ptrdiff_t get_locked_narrowing_zv (ptrdiff_t);
|
ptrdiff_t get_large_narrowing_zv (ptrdiff_t);
|
||||||
void init_iterator_to_row_start (struct it *, struct window *,
|
void init_iterator_to_row_start (struct it *, struct window *,
|
||||||
struct glyph_row *);
|
struct glyph_row *);
|
||||||
void start_display (struct it *, struct window *, struct text_pos);
|
void start_display (struct it *, struct window *, struct text_pos);
|
||||||
|
|
299
src/editfns.c
299
src/editfns.c
|
@ -2653,182 +2653,197 @@ DEFUN ("delete-and-extract-region", Fdelete_and_extract_region,
|
||||||
return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
|
return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alist of buffers in which locked narrowing is used. The car of
|
/* Alist of buffers in which labeled restrictions are used. The car
|
||||||
each list element is a buffer, the cdr is a list of triplets (tag
|
of each list element is a buffer, the cdr is a list of triplets
|
||||||
begv-marker zv-marker). The last element of that list always uses
|
(label begv-marker zv-marker). The last triplet of that list
|
||||||
the (uninterned) Qoutermost_narrowing tag and records the narrowing
|
always uses the (uninterned) Qoutermost_restriction label, and
|
||||||
bounds that were set by the user and that are visible on display.
|
records the restriction bounds that were current when the first
|
||||||
This alist is used internally by narrow-to-region, widen,
|
labeled restriction was entered (which may be a narrowing that was
|
||||||
internal--lock-narrowing, internal--unlock-narrowing and
|
set by the user and is visible on display). This alist is used
|
||||||
save-restriction. For efficiency reasons, an alist is used instead
|
internally by narrow-to-region, widen, internal--label-restriction,
|
||||||
of a buffer-local variable: otherwise reset_outermost_narrowings,
|
internal--unlabel-restriction and save-restriction. For efficiency
|
||||||
which is called during each redisplay cycle, would have to loop
|
reasons, an alist is used instead of a buffer-local variable:
|
||||||
through all live buffers. */
|
otherwise reset_outermost_restrictions, which is called during each
|
||||||
static Lisp_Object narrowing_locks;
|
redisplay cycle, would have to loop through all live buffers. */
|
||||||
|
static Lisp_Object labeled_restrictions;
|
||||||
|
|
||||||
/* Add BUF with its LOCKS in the narrowing_locks alist. */
|
/* Add BUF with its list of labeled RESTRICTIONS in the
|
||||||
|
labeled_restrictions alist. */
|
||||||
static void
|
static void
|
||||||
narrowing_locks_add (Lisp_Object buf, Lisp_Object locks)
|
labeled_restrictions_add (Lisp_Object buf, Lisp_Object restrictions)
|
||||||
{
|
{
|
||||||
narrowing_locks = nconc2 (list1 (list2 (buf, locks)), narrowing_locks);
|
labeled_restrictions = nconc2 (list1 (list2 (buf, restrictions)),
|
||||||
|
labeled_restrictions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove BUF and its locks from the narrowing_locks alist. Do
|
/* Remove BUF and its list of labeled restrictions from the
|
||||||
nothing if BUF is not present in narrowing_locks. */
|
labeled_restrictions alist. Do nothing if BUF is not present in
|
||||||
|
labeled_restrictions. */
|
||||||
static void
|
static void
|
||||||
narrowing_locks_remove (Lisp_Object buf)
|
labeled_restrictions_remove (Lisp_Object buf)
|
||||||
{
|
{
|
||||||
narrowing_locks = Fdelq (Fassoc (buf, narrowing_locks, Qnil),
|
labeled_restrictions = Fdelq (Fassoc (buf, labeled_restrictions, Qnil),
|
||||||
narrowing_locks);
|
labeled_restrictions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve one of the BEGV/ZV bounds of a narrowing in BUF from the
|
/* Retrieve one of the labeled restriction bounds in BUF from the
|
||||||
narrowing_locks alist, as a pointer to a struct Lisp_Marker, or
|
labeled_restrictions alist, as a pointer to a struct Lisp_Marker,
|
||||||
NULL if BUF is not in narrowing_locks or is a killed buffer. When
|
or return NULL if BUF is not in labeled_restrictions or is a killed
|
||||||
OUTERMOST is true, the bounds that were set by the user and that
|
buffer. When OUTERMOST is true, the restriction bounds that were
|
||||||
are visible on display are returned. Otherwise the innermost
|
current when the first labeled restriction was entered are
|
||||||
locked narrowing bounds are returned. */
|
returned. Otherwise the bounds of the innermost labeled
|
||||||
|
restriction are returned. */
|
||||||
static struct Lisp_Marker *
|
static struct Lisp_Marker *
|
||||||
narrowing_lock_get_bound (Lisp_Object buf, bool begv, bool outermost)
|
labeled_restrictions_get_bound (Lisp_Object buf, bool begv, bool outermost)
|
||||||
{
|
{
|
||||||
if (NILP (Fbuffer_live_p (buf)))
|
if (NILP (Fbuffer_live_p (buf)))
|
||||||
return NULL;
|
return NULL;
|
||||||
Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
|
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
|
||||||
if (NILP (buffer_locks))
|
if (NILP (restrictions))
|
||||||
return NULL;
|
return NULL;
|
||||||
buffer_locks = XCAR (XCDR (buffer_locks));
|
restrictions = XCAR (XCDR (restrictions));
|
||||||
Lisp_Object bounds
|
Lisp_Object bounds
|
||||||
= outermost
|
= outermost
|
||||||
? XCDR (assq_no_quit (Qoutermost_narrowing, buffer_locks))
|
? XCDR (assq_no_quit (Qoutermost_restriction, restrictions))
|
||||||
: XCDR (XCAR (buffer_locks));
|
: XCDR (XCAR (restrictions));
|
||||||
eassert (! NILP (bounds));
|
eassert (! NILP (bounds));
|
||||||
Lisp_Object marker = begv ? XCAR (bounds) : XCAR (XCDR (bounds));
|
Lisp_Object marker = begv ? XCAR (bounds) : XCAR (XCDR (bounds));
|
||||||
eassert (EQ (Fmarker_buffer (marker), buf));
|
eassert (EQ (Fmarker_buffer (marker), buf));
|
||||||
return XMARKER (marker);
|
return XMARKER (marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the tag of the innermost narrowing in BUF. Return nil if
|
/* Retrieve the label of the innermost labeled restriction in BUF.
|
||||||
BUF is not in narrowing_locks or is a killed buffer. */
|
Return nil if BUF is not in labeled_restrictions or is a killed
|
||||||
|
buffer. */
|
||||||
static Lisp_Object
|
static Lisp_Object
|
||||||
narrowing_lock_peek_tag (Lisp_Object buf)
|
labeled_restrictions_peek_label (Lisp_Object buf)
|
||||||
{
|
{
|
||||||
if (NILP (Fbuffer_live_p (buf)))
|
if (NILP (Fbuffer_live_p (buf)))
|
||||||
return Qnil;
|
return Qnil;
|
||||||
Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
|
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
|
||||||
if (NILP (buffer_locks))
|
if (NILP (restrictions))
|
||||||
return Qnil;
|
return Qnil;
|
||||||
Lisp_Object tag = XCAR (XCAR (XCAR (XCDR (buffer_locks))));
|
Lisp_Object label = XCAR (XCAR (XCAR (XCDR (restrictions))));
|
||||||
eassert (! NILP (tag));
|
eassert (! NILP (label));
|
||||||
return tag;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a LOCK for BUF in the narrowing_locks alist. */
|
/* Add a labeled RESTRICTION for BUF in the labeled_restrictions
|
||||||
|
alist. */
|
||||||
static void
|
static void
|
||||||
narrowing_lock_push (Lisp_Object buf, Lisp_Object lock)
|
labeled_restrictions_push (Lisp_Object buf, Lisp_Object restriction)
|
||||||
{
|
{
|
||||||
Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
|
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
|
||||||
if (NILP (buffer_locks))
|
if (NILP (restrictions))
|
||||||
narrowing_locks_add (buf, list1 (lock));
|
labeled_restrictions_add (buf, list1 (restriction));
|
||||||
else
|
else
|
||||||
XSETCDR (buffer_locks, list1 (nconc2 (list1 (lock),
|
XSETCDR (restrictions, list1 (nconc2 (list1 (restriction),
|
||||||
XCAR (XCDR (buffer_locks)))));
|
XCAR (XCDR (restrictions)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the innermost lock in BUF from the narrowing_locks alist.
|
/* Remove the innermost labeled restriction in BUF from the
|
||||||
Do nothing if BUF is not present in narrowing_locks. */
|
labeled_restrictions alist. Do nothing if BUF is not present in
|
||||||
|
labeled_restrictions. */
|
||||||
static void
|
static void
|
||||||
narrowing_lock_pop (Lisp_Object buf)
|
labeled_restrictions_pop (Lisp_Object buf)
|
||||||
{
|
{
|
||||||
Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
|
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
|
||||||
if (NILP (buffer_locks))
|
if (NILP (restrictions))
|
||||||
return;
|
return;
|
||||||
if (EQ (narrowing_lock_peek_tag (buf), Qoutermost_narrowing))
|
if (EQ (labeled_restrictions_peek_label (buf), Qoutermost_restriction))
|
||||||
narrowing_locks_remove (buf);
|
labeled_restrictions_remove (buf);
|
||||||
else
|
else
|
||||||
XSETCDR (buffer_locks, list1 (XCDR (XCAR (XCDR (buffer_locks)))));
|
XSETCDR (restrictions, list1 (XCDR (XCAR (XCDR (restrictions)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unwind_reset_outermost_narrowing (Lisp_Object buf)
|
unwind_reset_outermost_restriction (Lisp_Object buf)
|
||||||
{
|
{
|
||||||
struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
|
struct Lisp_Marker *begv
|
||||||
struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
|
= labeled_restrictions_get_bound (buf, true, false);
|
||||||
|
struct Lisp_Marker *zv
|
||||||
|
= labeled_restrictions_get_bound (buf, false, false);
|
||||||
if (begv != NULL && zv != NULL)
|
if (begv != NULL && zv != NULL)
|
||||||
{
|
{
|
||||||
SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
|
SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
|
||||||
SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
|
SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
narrowing_locks_remove (buf);
|
labeled_restrictions_remove (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the narrowing bounds that were set by the user, and restore
|
/* Restore the restriction bounds that were current when the first
|
||||||
the bounds of the locked narrowing upon return.
|
labeled restriction was entered, and restore the bounds of the
|
||||||
|
innermost labeled restriction upon return.
|
||||||
In particular, this function is called when redisplay starts, so
|
In particular, this function is called when redisplay starts, so
|
||||||
that if a Lisp function executed during redisplay calls (redisplay)
|
that if a Lisp function executed during redisplay calls (redisplay)
|
||||||
while a locked narrowing is in effect, the locked narrowing will
|
while labeled restrictions are in effect, these restrictions will
|
||||||
not be visible on display.
|
not become visible on display.
|
||||||
See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and
|
See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and
|
||||||
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example
|
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example
|
||||||
recipes that demonstrate why this is necessary. */
|
recipes that demonstrate why this is necessary. */
|
||||||
void
|
void
|
||||||
reset_outermost_narrowings (void)
|
reset_outermost_restrictions (void)
|
||||||
{
|
{
|
||||||
Lisp_Object val, buf;
|
Lisp_Object val, buf;
|
||||||
for (val = narrowing_locks; CONSP (val); val = XCDR (val))
|
for (val = labeled_restrictions; CONSP (val); val = XCDR (val))
|
||||||
{
|
{
|
||||||
buf = XCAR (XCAR (val));
|
buf = XCAR (XCAR (val));
|
||||||
eassert (BUFFERP (buf));
|
eassert (BUFFERP (buf));
|
||||||
struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, true);
|
struct Lisp_Marker *begv
|
||||||
struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, true);
|
= labeled_restrictions_get_bound (buf, true, true);
|
||||||
|
struct Lisp_Marker *zv
|
||||||
|
= labeled_restrictions_get_bound (buf, false, true);
|
||||||
if (begv != NULL && zv != NULL)
|
if (begv != NULL && zv != NULL)
|
||||||
{
|
{
|
||||||
SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
|
SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
|
||||||
SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
|
SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
|
||||||
record_unwind_protect (unwind_reset_outermost_narrowing, buf);
|
record_unwind_protect (unwind_reset_outermost_restriction, buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
narrowing_locks_remove (buf);
|
labeled_restrictions_remove (buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper functions to save and restore the narrowing locks of the
|
/* Helper functions to save and restore the labeled restrictions of
|
||||||
current buffer in Fsave_restriction. */
|
the current buffer in Fsave_restriction. */
|
||||||
static Lisp_Object
|
static Lisp_Object
|
||||||
narrowing_locks_save (void)
|
labeled_restrictions_save (void)
|
||||||
{
|
{
|
||||||
Lisp_Object buf = Fcurrent_buffer ();
|
Lisp_Object buf = Fcurrent_buffer ();
|
||||||
Lisp_Object locks = assq_no_quit (buf, narrowing_locks);
|
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
|
||||||
if (!NILP (locks))
|
if (! NILP (restrictions))
|
||||||
locks = XCAR (XCDR (locks));
|
restrictions = XCAR (XCDR (restrictions));
|
||||||
return Fcons (buf, Fcopy_sequence (locks));
|
return Fcons (buf, Fcopy_sequence (restrictions));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
narrowing_locks_restore (Lisp_Object buf_and_saved_locks)
|
labeled_restrictions_restore (Lisp_Object buf_and_restrictions)
|
||||||
{
|
{
|
||||||
Lisp_Object buf = XCAR (buf_and_saved_locks);
|
Lisp_Object buf = XCAR (buf_and_restrictions);
|
||||||
Lisp_Object saved_locks = XCDR (buf_and_saved_locks);
|
Lisp_Object restrictions = XCDR (buf_and_restrictions);
|
||||||
narrowing_locks_remove (buf);
|
labeled_restrictions_remove (buf);
|
||||||
if (!NILP (saved_locks))
|
if (! NILP (restrictions))
|
||||||
narrowing_locks_add (buf, saved_locks);
|
labeled_restrictions_add (buf, restrictions);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unwind_narrow_to_region_locked (Lisp_Object tag)
|
unwind_labeled_narrow_to_region (Lisp_Object label)
|
||||||
{
|
{
|
||||||
Finternal__unlock_narrowing (tag);
|
Finternal__unlabel_restriction (label);
|
||||||
Fwiden ();
|
Fwiden ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Narrow current_buffer to BEGV-ZV with a narrowing locked with TAG. */
|
/* Narrow current_buffer to BEGV-ZV with a restriction labeled with
|
||||||
|
LABEL. */
|
||||||
void
|
void
|
||||||
narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag)
|
labeled_narrow_to_region (Lisp_Object begv, Lisp_Object zv,
|
||||||
|
Lisp_Object label)
|
||||||
{
|
{
|
||||||
Fnarrow_to_region (begv, zv);
|
Fnarrow_to_region (begv, zv);
|
||||||
Finternal__lock_narrowing (tag);
|
Finternal__label_restriction (label);
|
||||||
record_unwind_protect (restore_point_unwind, Fpoint_marker ());
|
record_unwind_protect (restore_point_unwind, Fpoint_marker ());
|
||||||
record_unwind_protect (unwind_narrow_to_region_locked, tag);
|
record_unwind_protect (unwind_labeled_narrow_to_region, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
|
DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
|
||||||
|
@ -2842,11 +2857,11 @@ To gain access to other portions of the buffer, use
|
||||||
`without-restriction' with the same label. */)
|
`without-restriction' with the same label. */)
|
||||||
(void)
|
(void)
|
||||||
{
|
{
|
||||||
Fset (Qoutermost_narrowing, Qnil);
|
Fset (Qoutermost_restriction, Qnil);
|
||||||
Lisp_Object buf = Fcurrent_buffer ();
|
Lisp_Object buf = Fcurrent_buffer ();
|
||||||
Lisp_Object tag = narrowing_lock_peek_tag (buf);
|
Lisp_Object label = labeled_restrictions_peek_label (buf);
|
||||||
|
|
||||||
if (NILP (tag))
|
if (NILP (label))
|
||||||
{
|
{
|
||||||
if (BEG != BEGV || Z != ZV)
|
if (BEG != BEGV || Z != ZV)
|
||||||
current_buffer->clip_changed = 1;
|
current_buffer->clip_changed = 1;
|
||||||
|
@ -2856,19 +2871,21 @@ To gain access to other portions of the buffer, use
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
|
struct Lisp_Marker *begv
|
||||||
struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
|
= labeled_restrictions_get_bound (buf, true, false);
|
||||||
|
struct Lisp_Marker *zv
|
||||||
|
= labeled_restrictions_get_bound (buf, false, false);
|
||||||
eassert (begv != NULL && zv != NULL);
|
eassert (begv != NULL && zv != NULL);
|
||||||
if (begv->charpos != BEGV || zv->charpos != ZV)
|
if (begv->charpos != BEGV || zv->charpos != ZV)
|
||||||
current_buffer->clip_changed = 1;
|
current_buffer->clip_changed = 1;
|
||||||
SET_BUF_BEGV_BOTH (current_buffer, begv->charpos, begv->bytepos);
|
SET_BUF_BEGV_BOTH (current_buffer, begv->charpos, begv->bytepos);
|
||||||
SET_BUF_ZV_BOTH (current_buffer, zv->charpos, zv->bytepos);
|
SET_BUF_ZV_BOTH (current_buffer, zv->charpos, zv->bytepos);
|
||||||
/* If the only remaining bounds in narrowing_locks for
|
/* If the only remaining bounds in labeled_restrictions for
|
||||||
current_buffer are the bounds that were set by the user, no
|
current_buffer are the bounds that were set by the user, no
|
||||||
locked narrowing is in effect in current_buffer anymore:
|
labeled restriction is in effect in current_buffer anymore:
|
||||||
remove it from the narrowing_locks alist. */
|
remove it from the labeled_restrictions alist. */
|
||||||
if (EQ (tag, Qoutermost_narrowing))
|
if (EQ (label, Qoutermost_restriction))
|
||||||
narrowing_lock_pop (buf);
|
labeled_restrictions_pop (buf);
|
||||||
}
|
}
|
||||||
/* Changing the buffer bounds invalidates any recorded current column. */
|
/* Changing the buffer bounds invalidates any recorded current column. */
|
||||||
invalidate_current_column ();
|
invalidate_current_column ();
|
||||||
|
@ -2905,13 +2922,15 @@ argument. To gain access to other portions of the buffer, use
|
||||||
args_out_of_range (start, end);
|
args_out_of_range (start, end);
|
||||||
|
|
||||||
Lisp_Object buf = Fcurrent_buffer ();
|
Lisp_Object buf = Fcurrent_buffer ();
|
||||||
if (! NILP (narrowing_lock_peek_tag (buf)))
|
if (! NILP (labeled_restrictions_peek_label (buf)))
|
||||||
{
|
{
|
||||||
struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
|
/* Limit the start and end positions to those of the innermost
|
||||||
struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
|
labeled restriction. */
|
||||||
|
struct Lisp_Marker *begv
|
||||||
|
= labeled_restrictions_get_bound (buf, true, false);
|
||||||
|
struct Lisp_Marker *zv
|
||||||
|
= labeled_restrictions_get_bound (buf, false, false);
|
||||||
eassert (begv != NULL && zv != NULL);
|
eassert (begv != NULL && zv != NULL);
|
||||||
/* Limit the start and end positions to those of the locked
|
|
||||||
narrowing. */
|
|
||||||
if (s < begv->charpos) s = begv->charpos;
|
if (s < begv->charpos) s = begv->charpos;
|
||||||
if (s > zv->charpos) s = zv->charpos;
|
if (s > zv->charpos) s = zv->charpos;
|
||||||
if (e < begv->charpos) e = begv->charpos;
|
if (e < begv->charpos) e = begv->charpos;
|
||||||
|
@ -2919,11 +2938,11 @@ argument. To gain access to other portions of the buffer, use
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the accessible range of the buffer when narrow-to-region
|
/* Record the accessible range of the buffer when narrow-to-region
|
||||||
is called, that is, before applying the narrowing. It is used
|
is called, that is, before applying the narrowing. That
|
||||||
only by internal--lock-narrowing. */
|
information is used only by internal--label-restriction. */
|
||||||
Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing,
|
Fset (Qoutermost_restriction, list3 (Qoutermost_restriction,
|
||||||
Fpoint_min_marker (),
|
Fpoint_min_marker (),
|
||||||
Fpoint_max_marker ()));
|
Fpoint_max_marker ()));
|
||||||
|
|
||||||
if (BEGV != s || ZV != e)
|
if (BEGV != s || ZV != e)
|
||||||
current_buffer->clip_changed = 1;
|
current_buffer->clip_changed = 1;
|
||||||
|
@ -2940,38 +2959,38 @@ argument. To gain access to other portions of the buffer, use
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("internal--lock-narrowing", Finternal__lock_narrowing,
|
DEFUN ("internal--label-restriction", Finternal__label_restriction,
|
||||||
Sinternal__lock_narrowing, 1, 1, 0,
|
Sinternal__label_restriction, 1, 1, 0,
|
||||||
doc: /* Lock the current narrowing with LABEL.
|
doc: /* Label the current restriction with LABEL.
|
||||||
|
|
||||||
This is an internal function used by `with-restriction'. */)
|
This is an internal function used by `with-restriction'. */)
|
||||||
(Lisp_Object tag)
|
(Lisp_Object label)
|
||||||
{
|
{
|
||||||
Lisp_Object buf = Fcurrent_buffer ();
|
Lisp_Object buf = Fcurrent_buffer ();
|
||||||
Lisp_Object outermost_narrowing
|
Lisp_Object outermost_restriction
|
||||||
= buffer_local_value (Qoutermost_narrowing, buf);
|
= buffer_local_value (Qoutermost_restriction, buf);
|
||||||
/* If internal--lock-narrowing is ever called without being preceded
|
/* If internal--label-restriction is ever called without being
|
||||||
by narrow-to-region, do nothing. */
|
preceded by narrow-to-region, do nothing. */
|
||||||
if (NILP (outermost_narrowing))
|
if (NILP (outermost_restriction))
|
||||||
return Qnil;
|
return Qnil;
|
||||||
if (NILP (narrowing_lock_peek_tag (buf)))
|
if (NILP (labeled_restrictions_peek_label (buf)))
|
||||||
narrowing_lock_push (buf, outermost_narrowing);
|
labeled_restrictions_push (buf, outermost_restriction);
|
||||||
narrowing_lock_push (buf, list3 (tag,
|
labeled_restrictions_push (buf, list3 (label,
|
||||||
Fpoint_min_marker (),
|
Fpoint_min_marker (),
|
||||||
Fpoint_max_marker ()));
|
Fpoint_max_marker ()));
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("internal--unlock-narrowing", Finternal__unlock_narrowing,
|
DEFUN ("internal--unlabel-restriction", Finternal__unlabel_restriction,
|
||||||
Sinternal__unlock_narrowing, 1, 1, 0,
|
Sinternal__unlabel_restriction, 1, 1, 0,
|
||||||
doc: /* Unlock a narrowing locked with LABEL.
|
doc: /* If the current restriction is labeled with LABEL, remove its label.
|
||||||
|
|
||||||
This is an internal function used by `without-restriction'. */)
|
This is an internal function used by `without-restriction'. */)
|
||||||
(Lisp_Object tag)
|
(Lisp_Object label)
|
||||||
{
|
{
|
||||||
Lisp_Object buf = Fcurrent_buffer ();
|
Lisp_Object buf = Fcurrent_buffer ();
|
||||||
if (EQ (narrowing_lock_peek_tag (buf), tag))
|
if (EQ (labeled_restrictions_peek_label (buf), label))
|
||||||
narrowing_lock_pop (buf);
|
labeled_restrictions_pop (buf);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3071,15 +3090,15 @@ save_restriction_restore_1 (Lisp_Object data)
|
||||||
Lisp_Object
|
Lisp_Object
|
||||||
save_restriction_save (void)
|
save_restriction_save (void)
|
||||||
{
|
{
|
||||||
Lisp_Object restr = save_restriction_save_1 ();
|
Lisp_Object restriction = save_restriction_save_1 ();
|
||||||
Lisp_Object locks = narrowing_locks_save ();
|
Lisp_Object labeled_restrictions = labeled_restrictions_save ();
|
||||||
return Fcons (restr, locks);
|
return Fcons (restriction, labeled_restrictions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
save_restriction_restore (Lisp_Object data)
|
save_restriction_restore (Lisp_Object data)
|
||||||
{
|
{
|
||||||
narrowing_locks_restore (XCDR (data));
|
labeled_restrictions_restore (XCDR (data));
|
||||||
save_restriction_restore_1 (XCAR (data));
|
save_restriction_restore_1 (XCAR (data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4748,7 +4767,7 @@ syms_of_editfns (void)
|
||||||
DEFSYM (Qwall, "wall");
|
DEFSYM (Qwall, "wall");
|
||||||
DEFSYM (Qpropertize, "propertize");
|
DEFSYM (Qpropertize, "propertize");
|
||||||
|
|
||||||
staticpro (&narrowing_locks);
|
staticpro (&labeled_restrictions);
|
||||||
|
|
||||||
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
|
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
|
||||||
doc: /* Non-nil means text motion commands don't notice fields. */);
|
doc: /* Non-nil means text motion commands don't notice fields. */);
|
||||||
|
@ -4809,12 +4828,12 @@ This variable is experimental; email 32252@debbugs.gnu.org if you need
|
||||||
it to be non-nil. */);
|
it to be non-nil. */);
|
||||||
binary_as_unsigned = false;
|
binary_as_unsigned = false;
|
||||||
|
|
||||||
DEFVAR_LISP ("outermost-narrowing", Voutermost_narrowing,
|
DEFVAR_LISP ("outermost-restriction", Voutermost_restriction,
|
||||||
doc: /* Outermost narrowing bounds, if any. Internal use only. */);
|
doc: /* Outermost narrowing bounds, if any. Internal use only. */);
|
||||||
Voutermost_narrowing = Qnil;
|
Voutermost_restriction = Qnil;
|
||||||
Fmake_variable_buffer_local (Qoutermost_narrowing);
|
Fmake_variable_buffer_local (Qoutermost_restriction);
|
||||||
DEFSYM (Qoutermost_narrowing, "outermost-narrowing");
|
DEFSYM (Qoutermost_restriction, "outermost-restriction");
|
||||||
Funintern (Qoutermost_narrowing, Qnil);
|
Funintern (Qoutermost_restriction, Qnil);
|
||||||
|
|
||||||
defsubr (&Spropertize);
|
defsubr (&Spropertize);
|
||||||
defsubr (&Schar_equal);
|
defsubr (&Schar_equal);
|
||||||
|
@ -4907,8 +4926,8 @@ it to be non-nil. */);
|
||||||
defsubr (&Sdelete_and_extract_region);
|
defsubr (&Sdelete_and_extract_region);
|
||||||
defsubr (&Swiden);
|
defsubr (&Swiden);
|
||||||
defsubr (&Snarrow_to_region);
|
defsubr (&Snarrow_to_region);
|
||||||
defsubr (&Sinternal__lock_narrowing);
|
defsubr (&Sinternal__label_restriction);
|
||||||
defsubr (&Sinternal__unlock_narrowing);
|
defsubr (&Sinternal__unlabel_restriction);
|
||||||
defsubr (&Ssave_restriction);
|
defsubr (&Ssave_restriction);
|
||||||
defsubr (&Stranspose_regions);
|
defsubr (&Stranspose_regions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,8 @@ static Lisp_Object command_loop (void);
|
||||||
static void echo_now (void);
|
static void echo_now (void);
|
||||||
static ptrdiff_t echo_length (void);
|
static ptrdiff_t echo_length (void);
|
||||||
|
|
||||||
|
static void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
|
||||||
|
|
||||||
/* Incremented whenever a timer is run. */
|
/* Incremented whenever a timer is run. */
|
||||||
unsigned timers_run;
|
unsigned timers_run;
|
||||||
|
|
||||||
|
@ -1909,7 +1911,7 @@ safe_run_hooks (Lisp_Object hook)
|
||||||
unbind_to (count, Qnil);
|
unbind_to (count, Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
|
safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
|
||||||
{
|
{
|
||||||
specpdl_ref count = SPECPDL_INDEX ();
|
specpdl_ref count = SPECPDL_INDEX ();
|
||||||
|
@ -1919,11 +1921,11 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
|
||||||
if (current_buffer->long_line_optimizations_p
|
if (current_buffer->long_line_optimizations_p
|
||||||
&& long_line_optimizations_region_size > 0)
|
&& long_line_optimizations_region_size > 0)
|
||||||
{
|
{
|
||||||
ptrdiff_t begv = get_locked_narrowing_begv (PT);
|
ptrdiff_t begv = get_large_narrowing_begv (PT);
|
||||||
ptrdiff_t zv = get_locked_narrowing_zv (PT);
|
ptrdiff_t zv = get_large_narrowing_zv (PT);
|
||||||
if (begv != BEG || zv != Z)
|
if (begv != BEG || zv != Z)
|
||||||
narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
|
labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
|
||||||
Qlong_line_optimizations_in_command_hooks);
|
Qlong_line_optimizations_in_command_hooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
run_hook_with_args (2, ((Lisp_Object []) {hook, hook}),
|
run_hook_with_args (2, ((Lisp_Object []) {hook, hook}),
|
||||||
|
|
|
@ -4687,8 +4687,8 @@ extern void save_restriction_restore (Lisp_Object);
|
||||||
extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
|
extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
|
||||||
extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||||
ptrdiff_t, bool);
|
ptrdiff_t, bool);
|
||||||
extern void narrow_to_region_locked (Lisp_Object, Lisp_Object, Lisp_Object);
|
extern void labeled_narrow_to_region (Lisp_Object, Lisp_Object, Lisp_Object);
|
||||||
extern void reset_outermost_narrowings (void);
|
extern void reset_outermost_restrictions (void);
|
||||||
extern void init_editfns (void);
|
extern void init_editfns (void);
|
||||||
extern void syms_of_editfns (void);
|
extern void syms_of_editfns (void);
|
||||||
|
|
||||||
|
@ -4857,7 +4857,6 @@ extern bool detect_input_pending (void);
|
||||||
extern bool detect_input_pending_ignore_squeezables (void);
|
extern bool detect_input_pending_ignore_squeezables (void);
|
||||||
extern bool detect_input_pending_run_timers (bool);
|
extern bool detect_input_pending_run_timers (bool);
|
||||||
extern void safe_run_hooks (Lisp_Object);
|
extern void safe_run_hooks (Lisp_Object);
|
||||||
extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
|
|
||||||
extern void safe_run_hooks_2 (Lisp_Object, Lisp_Object, Lisp_Object);
|
extern void safe_run_hooks_2 (Lisp_Object, Lisp_Object, Lisp_Object);
|
||||||
extern void cmd_error_internal (Lisp_Object, const char *);
|
extern void cmd_error_internal (Lisp_Object, const char *);
|
||||||
extern Lisp_Object command_loop_2 (Lisp_Object);
|
extern Lisp_Object command_loop_2 (Lisp_Object);
|
||||||
|
|
159
src/xdisp.c
159
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
|
/* This is set only when long_line_optimizations_p is non-zero
|
||||||
for the current buffer. */
|
for the current buffer. */
|
||||||
it->narrowed_begv = 0;
|
it->medium_narrowing_begv = 0;
|
||||||
|
|
||||||
/* Compute faces etc. */
|
/* Compute faces etc. */
|
||||||
reseat (it, it->current.pos, true);
|
reseat (it, it->current.pos, true);
|
||||||
|
@ -3491,9 +3491,91 @@ init_iterator (struct it *it, struct window *w,
|
||||||
CHECK_IT (it);
|
CHECK_IT (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute a suitable alternate value for BEGV and ZV that may be used
|
/* How Emacs deals with long lines.
|
||||||
temporarily to optimize display if the buffer in window W contains
|
|
||||||
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
|
static int
|
||||||
get_narrowed_width (struct window *w)
|
get_narrowed_width (struct window *w)
|
||||||
|
@ -3513,28 +3595,28 @@ get_narrowed_len (struct window *w)
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t
|
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);
|
int len = get_narrowed_len (w);
|
||||||
return max ((pos / len - 1) * len, BEGV);
|
return max ((pos / len - 1) * len, BEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t
|
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);
|
int len = get_narrowed_len (w);
|
||||||
return min ((pos / len + 1) * len, ZV);
|
return min ((pos / len + 1) * len, ZV);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t
|
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);
|
int len = get_narrowed_width (w);
|
||||||
return max ((pos / len - 1) * len, BEGV);
|
return max ((pos / len - 1) * len, BEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t
|
ptrdiff_t
|
||||||
get_locked_narrowing_begv (ptrdiff_t pos)
|
get_large_narrowing_begv (ptrdiff_t pos)
|
||||||
{
|
{
|
||||||
if (long_line_optimizations_region_size <= 0)
|
if (long_line_optimizations_region_size <= 0)
|
||||||
return BEGV;
|
return BEGV;
|
||||||
|
@ -3552,7 +3634,7 @@ get_locked_narrowing_begv (ptrdiff_t pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrdiff_t
|
ptrdiff_t
|
||||||
get_locked_narrowing_zv (ptrdiff_t pos)
|
get_large_narrowing_zv (ptrdiff_t pos)
|
||||||
{
|
{
|
||||||
if (long_line_optimizations_region_size <= 0)
|
if (long_line_optimizations_region_size <= 0)
|
||||||
return ZV;
|
return ZV;
|
||||||
|
@ -3571,7 +3653,7 @@ unwind_narrowed_begv (Lisp_Object point_min)
|
||||||
|
|
||||||
#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
|
#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
|
||||||
do { \
|
do { \
|
||||||
if (IT->narrowed_begv) \
|
if (IT->medium_narrowing_begv) \
|
||||||
{ \
|
{ \
|
||||||
specpdl_ref count = SPECPDL_INDEX (); \
|
specpdl_ref count = SPECPDL_INDEX (); \
|
||||||
record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
|
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
|
if (current_buffer->long_line_optimizations_p
|
||||||
&& long_line_optimizations_region_size > 0)
|
&& long_line_optimizations_region_size > 0)
|
||||||
{
|
{
|
||||||
ptrdiff_t begv = it->locked_narrowing_begv;
|
ptrdiff_t begv = it->large_narrowing_begv;
|
||||||
ptrdiff_t zv = it->locked_narrowing_zv;
|
ptrdiff_t zv = it->large_narrowing_zv;
|
||||||
ptrdiff_t charpos = IT_CHARPOS (*it);
|
ptrdiff_t charpos = IT_CHARPOS (*it);
|
||||||
if (charpos < begv || charpos > zv)
|
if (charpos < begv || charpos > zv)
|
||||||
{
|
{
|
||||||
begv = get_locked_narrowing_begv (charpos);
|
begv = get_large_narrowing_begv (charpos);
|
||||||
zv = get_locked_narrowing_zv (charpos);
|
zv = get_large_narrowing_zv (charpos);
|
||||||
}
|
}
|
||||||
if (begv != BEG || zv != Z)
|
if (begv != BEG || zv != Z)
|
||||||
narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
|
labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
|
||||||
Qlong_line_optimizations_in_fontification_functions);
|
Qlong_line_optimizations_in_fontification_functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't allow Lisp that runs from '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);
|
dec_both (&cp, &bp);
|
||||||
SET_WITH_NARROWED_BEGV (it, 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)),
|
||||||
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
|
/* 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;
|
it->continuation_lines_width = 0;
|
||||||
|
|
||||||
eassert (IT_CHARPOS (*it) >= BEGV);
|
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
|
|| IT_CHARPOS (*it) == BEGV
|
||||||
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
|
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
|
||||||
CHECK_IT (it);
|
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 (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->medium_narrowing_begv
|
||||||
it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w));
|
= get_medium_narrowing_begv (it->w, window_point (it->w));
|
||||||
it->locked_narrowing_begv
|
it->medium_narrowing_zv
|
||||||
= get_locked_narrowing_begv (window_point (it->w));
|
= get_medium_narrowing_zv (it->w, window_point (it->w));
|
||||||
it->locked_narrowing_zv
|
it->large_narrowing_begv
|
||||||
= get_locked_narrowing_zv (window_point (it->w));
|
= 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))
|
&& (!redisplaying_p || it->line_wrap == TRUNCATE))
|
||||||
{
|
{
|
||||||
it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos);
|
it->medium_narrowing_begv
|
||||||
it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos);
|
= get_medium_narrowing_begv (it->w, pos.charpos);
|
||||||
it->locked_narrowing_begv
|
it->medium_narrowing_zv
|
||||||
= get_locked_narrowing_begv (window_point (it->w));
|
= get_medium_narrowing_zv (it->w, pos.charpos);
|
||||||
it->locked_narrowing_zv
|
it->large_narrowing_begv
|
||||||
= get_locked_narrowing_zv (window_point (it->w));
|
= 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,
|
SET_WITH_NARROWED_BEGV (it, bob,
|
||||||
string_p ? 0 :
|
string_p ? 0 :
|
||||||
IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
|
IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
|
||||||
it->narrowed_begv);
|
it->medium_narrowing_begv);
|
||||||
|
|
||||||
if (STRINGP (it->string))
|
if (STRINGP (it->string))
|
||||||
{
|
{
|
||||||
|
@ -8833,7 +8920,7 @@ get_visually_first_element (struct it *it)
|
||||||
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),
|
||||||
it->narrowed_begv);
|
it->medium_narrowing_begv);
|
||||||
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
|
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -10722,7 +10809,7 @@ move_it_vertically_backward (struct it *it, int dy)
|
||||||
dec_both (&cp, &bp);
|
dec_both (&cp, &bp);
|
||||||
SET_WITH_NARROWED_BEGV (it, cp,
|
SET_WITH_NARROWED_BEGV (it, cp,
|
||||||
find_newline_no_quit (cp, bp, -1, NULL),
|
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);
|
move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
|
||||||
}
|
}
|
||||||
bidi_unshelve_cache (it3data, true);
|
bidi_unshelve_cache (it3data, true);
|
||||||
|
@ -16394,7 +16481,7 @@ redisplay_internal (void)
|
||||||
FOR_EACH_FRAME (tail, frame)
|
FOR_EACH_FRAME (tail, frame)
|
||||||
XFRAME (frame)->already_hscrolled_p = false;
|
XFRAME (frame)->already_hscrolled_p = false;
|
||||||
|
|
||||||
reset_outermost_narrowings ();
|
reset_outermost_restrictions ();
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* Remember the currently selected window. */
|
/* Remember the currently selected window. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue