diff options
-rw-r--r-- | doc/lispref/display.texi | 6 | ||||
-rw-r--r-- | doc/lispref/positions.texi | 11 | ||||
-rw-r--r-- | etc/NEWS | 27 | ||||
-rw-r--r-- | src/bytecode.c | 2 | ||||
-rw-r--r-- | src/dispextern.h | 8 | ||||
-rw-r--r-- | src/editfns.c | 75 | ||||
-rw-r--r-- | src/indent.c | 5 | ||||
-rw-r--r-- | src/lread.c | 2 | ||||
-rw-r--r-- | src/process.c | 2 | ||||
-rw-r--r-- | src/xdisp.c | 256 |
10 files changed, 339 insertions, 55 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 86f490677d1..d2e075c54ec 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -3480,6 +3480,12 @@ function finishes are the ones that really matter. For efficiency, we recommend writing these functions so that they usually assign faces to around 400 to 600 characters at each call. + +When the buffer text includes very long lines, these functions are +called with the buffer narrowed to a relatively small region around +@var{pos}, and with narrowing locked, so the functions cannot use +@code{widen} to gain access to the rest of the buffer. +@xref{Narrowing}. @end defvar @node Basic Faces diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index ca1166caac4..3a9a152f8dd 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -995,13 +995,18 @@ the entire buffer regardless of any narrowing. types of text, consider using an alternative facility described in @ref{Swapping Text}. -@deffn Command narrow-to-region start end +@deffn Command narrow-to-region start end &optional lock This function sets the accessible portion of the current buffer to start at @var{start} and end at @var{end}. Both arguments should be character positions. In an interactive call, @var{start} and @var{end} are set to the bounds of the current region (point and the mark, with the smallest first). + +When @var{lock} is non-@code{nil}, calls to @code{widen}, or to +@code{narrow-to-region} with an optional argument @var{lock} +@code{nil}, do not produce any effect until the end of the current +body form. @end deffn @deffn Command narrow-to-page &optional move-count @@ -1027,6 +1032,10 @@ It is equivalent to the following expression: @end example @end deffn +However, when @code{widen} is called inside a body form in which +@code{narrow-to-region} was called with an optional argument +@code{lock} non-@code{nil}, it does not produce any effect. + @defun buffer-narrowed-p This function returns non-@code{nil} if the buffer is narrowed, and @code{nil} otherwise. @@ -357,14 +357,20 @@ option) and can be set to nil to disable Just-in-time Lock mode. --- ** Emacs is now capable of editing files with arbitrarily long lines. The display of long lines has been optimized, and Emacs no longer -chokes when a buffer on display contains long lines. If you still -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 'C-u C-x x f', 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'. The variable +chokes when a buffer on display contains long lines. The variable 'long-line-threshold' controls whether and when these display -optimizations are used. +optimizations are in effect. + +If you still experience slowdowns while editing files with long lines, +this is due to line truncation, or to one of the enabled minor modes, +or to the current major mode. Try turning off line truncation with +'C-x x t', or try disabling all known slow minor modes with 'M-x +so-long-minor-mode', or try disabling all known slow minor modes and +the major mode with 'M-x so-long-mode', or visit the file with 'M-x +find-file-literally' instead of the usual 'C-x C-f'. + +Note that the display optimizations in these cases may cause the +buffer to be occasionally mis-fontified. +++ ** New command to change the font size globally. @@ -2520,6 +2526,13 @@ things to be saved. ** New function 'string-equal-ignore-case'. This compares strings ignoring case differences. ++++ +** New argument LOCK of 'narrow-to-region'. +If 'narrow-to-region' is called from Lisp with the new optional +argument LOCK non-nil, then calls to 'widen' and calls to +'narrow-to-region' with the optional argument LOCK nil or omitted do +not produce any effect until the end of the current body form. + ** Themes --- diff --git a/src/bytecode.c b/src/bytecode.c index d75767bb0c5..241cbaf04f6 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1481,7 +1481,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, CASE (Bnarrow_to_region): { Lisp_Object v1 = POP; - TOP = Fnarrow_to_region (TOP, v1); + TOP = Fnarrow_to_region (TOP, v1, Qnil); NEXT; } diff --git a/src/dispextern.h b/src/dispextern.h index 1cdfdca74c0..2772e8cda8d 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2336,6 +2336,10 @@ struct it optimize display (see the SET_WITH_NARROWED_BEGV macro). */ ptrdiff_t narrowed_begv; + /* Alternate end position of the buffer that may be used to + optimize display. */ + ptrdiff_t narrowed_zv; + /* C string to iterate over. Non-null means get characters from this string, otherwise characters are read from current_buffer or it->string. */ @@ -3400,7 +3404,9 @@ void mark_window_display_accurate (Lisp_Object, bool); void redisplay_preserve_echo_area (int); void init_iterator (struct it *, struct window *, ptrdiff_t, ptrdiff_t, struct glyph_row *, enum face_id); -ptrdiff_t get_narrowed_begv (struct window *w); +ptrdiff_t get_narrowed_begv (struct window *); +ptrdiff_t get_narrowed_zv (struct window *); +ptrdiff_t get_closer_narrowed_begv (struct window *, 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 4587b1132b1..d15d4dc68b9 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -2658,9 +2658,15 @@ DEFUN ("delete-and-extract-region", Fdelete_and_extract_region, DEFUN ("widen", Fwiden, Swiden, 0, 0, "", doc: /* Remove restrictions (narrowing) from current buffer. -This allows the buffer's full text to be seen and edited. */) +This allows the buffer's full text to be seen and edited. + +When called from Lisp inside a body form in which `narrow-to-region' +was called with an optional argument LOCK non-nil, this function does +not produce any effect. */) (void) { + if (! NILP (Vrestrictions_locked)) + return Qnil; if (BEG != BEGV || Z != ZV) current_buffer->clip_changed = 1; BEGV = BEG; @@ -2671,7 +2677,19 @@ This allows the buffer's full text to be seen and edited. */) return Qnil; } -DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r", +static void +unwind_locked_begv (Lisp_Object point_min) +{ + SET_BUF_BEGV (current_buffer, XFIXNUM (point_min)); +} + +static void +unwind_locked_zv (Lisp_Object point_max) +{ + SET_BUF_ZV (current_buffer, XFIXNUM (point_max)); +} + +DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 3, "r", doc: /* Restrict editing in this buffer to the current region. The rest of the text becomes temporarily invisible and untouchable but is not deleted; if you save the buffer in a file, the invisible @@ -2680,8 +2698,13 @@ See also `save-restriction'. When calling from Lisp, pass two arguments START and END: positions (integers or markers) bounding the text that should -remain visible. */) - (Lisp_Object start, Lisp_Object end) +remain visible. + +When called from Lisp with the optional argument LOCK non-nil, +calls to `widen', or to `narrow-to-region' with an optional +argument LOCK nil, do not produce any effect until the end of +the current body form. */) + (Lisp_Object start, Lisp_Object end, Lisp_Object lock) { EMACS_INT s = fix_position (start), e = fix_position (end); @@ -2690,14 +2713,37 @@ remain visible. */) EMACS_INT tem = s; s = e; e = tem; } - if (!(BEG <= s && s <= e && e <= Z)) - args_out_of_range (start, end); + if (! NILP (lock)) + { + if (!(BEGV <= s && s <= e && e <= ZV)) + args_out_of_range (start, end); - if (BEGV != s || ZV != e) - current_buffer->clip_changed = 1; + if (BEGV != s || ZV != e) + current_buffer->clip_changed = 1; + + record_unwind_protect (unwind_locked_begv, Fpoint_min ()); + record_unwind_protect (unwind_locked_zv, Fpoint_max ()); + + SET_BUF_BEGV (current_buffer, s); + SET_BUF_ZV (current_buffer, e); + + specbind (Qrestrictions_locked, Qt); + } + else + { + if (! NILP (Vrestrictions_locked)) + return Qnil; + + if (!(BEG <= s && s <= e && e <= Z)) + args_out_of_range (start, end); + + if (BEGV != s || ZV != e) + current_buffer->clip_changed = 1; + + SET_BUF_BEGV (current_buffer, s); + SET_BUF_ZV (current_buffer, e); + } - SET_BUF_BEGV (current_buffer, s); - SET_BUF_ZV (current_buffer, e); if (PT < s) SET_PT (s); if (e < PT) @@ -4517,6 +4563,15 @@ This variable is experimental; email 32252@debbugs.gnu.org if you need it to be non-nil. */); binary_as_unsigned = false; + DEFSYM (Qrestrictions_locked, "restrictions-locked"); + DEFVAR_LISP ("restrictions-locked", Vrestrictions_locked, + doc: /* If non-nil, restrictions are currently locked. + +This happens when `narrow-to-region', which see, is called from Lisp +with an optional argument LOCK non-nil. */); + Vrestrictions_locked = Qnil; + Funintern (Qrestrictions_locked, Qnil); + defsubr (&Spropertize); defsubr (&Schar_equal); defsubr (&Sgoto_char); diff --git a/src/indent.c b/src/indent.c index d4ef075f001..e90e3fde203 100644 --- a/src/indent.c +++ b/src/indent.c @@ -306,6 +306,8 @@ and point (e.g., control characters will have a width of 2 or 4, tabs will have a variable width). Ignores finite width of frame, which means that this function may return values greater than (frame-width). +In a buffer with very long lines, the value can be zero, because calculating +the exact number is very expensive. Whether the line is visible (if `selective-display' is t) has no effect; however, ^M is treated as end of line when `selective-display' is t. Text that has an invisible property is considered as having width 0, unless @@ -313,6 +315,9 @@ Text that has an invisible property is considered as having width 0, unless (void) { Lisp_Object temp; + + if (current_buffer->long_line_optimizations_p) + return make_fixnum (0); XSETFASTINT (temp, current_column ()); return temp; } diff --git a/src/lread.c b/src/lread.c index 0b46a2e4ee5..0720774db2b 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2261,7 +2261,7 @@ readevalloop (Lisp_Object readcharfun, /* Set point and ZV around stuff to be read. */ Fgoto_char (start); if (!NILP (end)) - Fnarrow_to_region (make_fixnum (BEGV), end); + Fnarrow_to_region (make_fixnum (BEGV), end, Qnil); /* Just for cleanliness, convert END to a marker if it is an integer. */ diff --git a/src/process.c b/src/process.c index 1ac5a509e56..a15efa39bd1 100644 --- a/src/process.c +++ b/src/process.c @@ -6339,7 +6339,7 @@ Otherwise it discards the output. */) /* If the restriction isn't what it should be, set it. */ if (old_begv != BEGV || old_zv != ZV) - Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv)); + Fnarrow_to_region (make_fixnum (old_begv), make_fixnum (old_zv), Qnil); bset_read_only (current_buffer, old_read_only); SET_PT_BOTH (opoint, opoint_byte); diff --git a/src/xdisp.c b/src/xdisp.c index e998df32a6a..2c889586cd6 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3426,7 +3426,10 @@ init_iterator (struct it *it, struct window *w, } if (current_buffer->long_line_optimizations_p) - it->narrowed_begv = get_narrowed_begv (w); + { + it->narrowed_begv = get_narrowed_begv (w); + it->narrowed_zv = get_narrowed_zv (w); + } /* If a buffer position was specified, set the iterator there, getting overlays and face properties from that position. */ @@ -3494,23 +3497,50 @@ init_iterator (struct it *it, struct window *w, CHECK_IT (it); } -/* Compute a suitable alternate value for BEGV that may be used +/* Compute a suitable alternate value for BEGV and ZV 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) +static int +get_narrowed_width (struct window *w) { - int len, fact; ptrdiff_t begv; + int fact; /* In a character-only terminal, only one font size is used, so we can use a smaller factor. */ fact = EQ (Fterminal_live_p (Qnil), Qt) ? 2 : 3; - len = fact * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) * - window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS)); + return fact * window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS); +} + +static int +get_narrowed_len (struct window *w) +{ + return get_narrowed_width (w) * + window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS); +} + +ptrdiff_t +get_narrowed_begv (struct window *w) +{ + int len = get_narrowed_len (w); + ptrdiff_t begv; begv = max ((window_point (w) / len - 1) * len, BEGV); return begv == BEGV ? 0 : begv; } +ptrdiff_t +get_narrowed_zv (struct window *w) +{ + int len = get_narrowed_len (w); + return min ((window_point (w) / len + 1) * len, ZV); +} + +ptrdiff_t +get_closer_narrowed_begv (struct window *w, ptrdiff_t pos) +{ + int len = get_narrowed_width (w); + return max ((pos / len - 1) * len, BEGV); +} + static void unwind_narrowed_begv (Lisp_Object point_min) { @@ -3518,15 +3548,15 @@ unwind_narrowed_begv (Lisp_Object point_min) } /* Set DST to EXPR. When IT indicates that BEGV should temporarily be - updated to optimize display, evaluate EXPR with an updated BEGV. */ + updated to optimize display, evaluate EXPR with BEGV set to BV. */ -#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR) \ +#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \ 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); \ + SET_BUF_BEGV (current_buffer, BV); \ DST = EXPR; \ unbind_to (count, Qnil); \ } \ @@ -4377,6 +4407,10 @@ handle_fontified_prop (struct it *it) eassert (it->end_charpos == ZV); + if (it->narrowed_begv) + Fnarrow_to_region (make_fixnum (it->narrowed_begv), + make_fixnum (it->narrowed_zv), Qt); + /* Don't allow Lisp that runs from 'fontification-functions' clear our face and image caches behind our back. */ it->f->inhibit_clear_image_cache = true; @@ -7035,7 +7069,108 @@ back_to_previous_line_start (struct it *it) dec_both (&cp, &bp); 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))); +} + +/* Find in the current buffer the first display or overlay string + between STARTPOS and ENDPOS that includes embedded newlines. + Consider only overlays that apply to window W. + Value is non-zero if such a display/overlay string is found. */ +static bool +strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w) +{ + /* Process overlays before the overlay center. */ + for (struct Lisp_Overlay *ov = current_buffer->overlays_before; + ov; ov = ov->next) + { + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); + eassert (OVERLAYP (overlay)); + + /* Skip this overlay if it doesn't apply to our window. */ + Lisp_Object window = Foverlay_get (overlay, Qwindow); + if (WINDOWP (window) && XWINDOW (window) != w) + continue; + + ptrdiff_t ostart = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t oend = OVERLAY_POSITION (OVERLAY_END (overlay)); + + /* Due to the order of overlays in overlays_before, once we get + to an overlay whose end position is before STARTPOS, all the + rest also end before STARTPOS, and thus are of no concern to us. */ + if (oend < startpos) + break; + + /* Skip overlays that don't overlap the range. */ + if (!((startpos < oend && ostart < endpos) + || (ostart == oend + && (startpos == oend || (endpos == ZV && oend == endpos))))) + continue; + + Lisp_Object str; + str = Foverlay_get (overlay, Qbefore_string); + if (STRINGP (str) && SCHARS (str) + && memchr (SDATA (str), '\n', SBYTES (str))) + return true; + str = Foverlay_get (overlay, Qafter_string); + if (STRINGP (str) && SCHARS (str) + && memchr (SDATA (str), '\n', SBYTES (str))) + return true; + } + + /* Process overlays after the overlay center. */ + for (struct Lisp_Overlay *ov = current_buffer->overlays_after; + ov; ov = ov->next) + { + Lisp_Object overlay = make_lisp_ptr (ov, Lisp_Vectorlike); + eassert (OVERLAYP (overlay)); + + /* Skip this overlay if it doesn't apply to our window. */ + Lisp_Object window = Foverlay_get (overlay, Qwindow); + if (WINDOWP (window) && XWINDOW (window) != w) + continue; + + ptrdiff_t ostart = OVERLAY_POSITION (OVERLAY_START (overlay)); + ptrdiff_t oend = OVERLAY_POSITION (OVERLAY_END (overlay)); + + /* Due to the order of overlays in overlays_after, once we get + to an overlay whose start position is after ENDPOS, all the + rest also start after ENDPOS, and thus are of no concern to us. */ + if (ostart > endpos) + break; + + /* Skip overlays that don't overlap the range. */ + if (!((startpos < oend && ostart < endpos) + || (ostart == oend + && (startpos == oend || (endpos == ZV && oend == endpos))))) + continue; + + Lisp_Object str; + str = Foverlay_get (overlay, Qbefore_string); + if (STRINGP (str) && SCHARS (str) + && memchr (SDATA (str), '\n', SBYTES (str))) + return true; + str = Foverlay_get (overlay, Qafter_string); + if (STRINGP (str) && SCHARS (str) + && memchr (SDATA (str), '\n', SBYTES (str))) + return true; + } + + /* Check for 'display' properties whose values include strings. */ + Lisp_Object cpos = make_fixnum (startpos); + Lisp_Object limpos = make_fixnum (endpos); + + while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos), + !(NILP (cpos) || XFIXNAT (cpos) >= endpos))) + { + Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); + Lisp_Object string = string_from_display_spec (spec); + if (STRINGP (string) + && memchr (SDATA (string), '\n', SBYTES (string))) + return true; + } + + return false; } @@ -7090,7 +7225,8 @@ forward_to_next_line_start (struct it *it, bool *skipped_p, it->selective = 0; /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements - from buffer text. */ + from buffer text, or till the end of the string if iterating a + string. */ for (n = 0; !newline_found_p && n < MAX_NEWLINE_DISTANCE; n += !STRINGP (it->string)) @@ -7110,27 +7246,55 @@ forward_to_next_line_start (struct it *it, bool *skipped_p, ptrdiff_t bytepos, start = IT_CHARPOS (*it); ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it), 1, &bytepos); - Lisp_Object pos; - eassert (!STRINGP (it->string)); - /* If there isn't any `display' property in sight, and no - overlays, we can just use the position of the newline in - buffer text. */ - if (it->stop_charpos >= limit - || ((pos = Fnext_single_property_change (make_fixnum (start), - Qdisplay, Qnil, - make_fixnum (limit)), - NILP (pos)) - && next_overlay_change (start) == ZV)) + /* it->stop_charpos >= limit means we already know there's no + stop position up until the newline at LIMIT, so there's no + need for any further checks. */ + bool no_strings_with_newlines = it->stop_charpos >= limit; + + if (!no_strings_with_newlines) { - if (!it->bidi_p) + if (!(current_buffer->long_line_optimizations_p + && it->line_wrap == TRUNCATE)) + { + /* Quick-and-dirty check: if there isn't any `display' + property in sight, and no overlays, we're done. */ + Lisp_Object pos = + Fnext_single_property_change (make_fixnum (start), + Qdisplay, Qnil, + make_fixnum (limit)); + no_strings_with_newlines = + (NILP (pos) || XFIXNAT (pos) == limit) /* no 'display' props */ + && next_overlay_change (start) == ZV; /* no overlays */ + } + else + { + /* For buffers with very long and truncated lines we try + harder, because it's worth our while to spend some + time looking into the overlays and 'display' properties + if we can then avoid iterating through all of them. */ + no_strings_with_newlines = + !strings_with_newlines (start, limit, it->w); + } + } + + /* If there's no display or overlay strings with embedded + newlines until the position of the newline in buffer text, we + can just use that position. */ + if (no_strings_with_newlines) + { + if (!it->bidi_p || !bidi_it_prev) { + /* The optimal case: just jump there. */ IT_CHARPOS (*it) = limit; IT_BYTEPOS (*it) = bytepos; } else { + /* The less optimal case: need to bidi-walk there, but + this is still cheaper that the full iteration using + get_next_display_element and set_iterator_to_next. */ struct bidi_it bprev; /* Help bidi.c avoid expensive searches for display @@ -7154,6 +7318,7 @@ forward_to_next_line_start (struct it *it, bool *skipped_p, } else { + /* The slow case. */ while (!newline_found_p) { if (!get_next_display_element (it)) @@ -7287,7 +7452,8 @@ reseat_at_next_visible_line_start (struct it *it, bool on_newline_p) bool skipped_p = false; struct bidi_it bidi_it_prev; bool newline_found_p - = forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); + = forward_to_next_line_start (it, &skipped_p, + on_newline_p ? &bidi_it_prev : NULL); /* Skip over lines that are invisible because they are indented more than the value of IT->selective. */ @@ -7299,7 +7465,8 @@ reseat_at_next_visible_line_start (struct it *it, bool on_newline_p) eassert (IT_BYTEPOS (*it) == BEGV || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); newline_found_p = - forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); + forward_to_next_line_start (it, &skipped_p, + on_newline_p ? &bidi_it_prev : NULL); } /* Position on the newline if that's what's requested. */ @@ -8672,7 +8839,8 @@ get_visually_first_element (struct it *it) SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : - IT_BYTEPOS (*it) < BEGV ? obegv : BEGV); + IT_BYTEPOS (*it) < BEGV ? obegv : BEGV, + it->narrowed_begv); if (STRINGP (it->string)) { @@ -8715,7 +8883,8 @@ get_visually_first_element (struct it *it) SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos, find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it), -1, - &it->bidi_it.bytepos)); + &it->bidi_it.bytepos), + it->narrowed_begv); bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); do { @@ -10634,7 +10803,8 @@ 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)); + find_newline_no_quit (cp, bp, -1, NULL), + it->narrowed_begv); move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); } bidi_unshelve_cache (it3data, true); @@ -12964,7 +13134,8 @@ mode_line_update_needed (struct window *w) { return (w->column_number_displayed != -1 && !(PT == w->last_point && !window_outdated (w)) - && (w->column_number_displayed != current_column ())); + && (!current_buffer->long_line_optimizations_p + && w->column_number_displayed != current_column ())); } /* True if window start of W is frozen and may not be changed during @@ -18936,8 +19107,9 @@ set_vertical_scroll_bar (struct window *w) end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf); /* If w->window_end_pos cannot be trusted, recompute it "the - hard way". */ - if (!MINI_WINDOW_P (w)) + hard way". But don't bother to be too accurate when + long-line shortcuts are in effect. */ + if (!w->window_end_valid && !buf->long_line_optimizations_p) { struct it it; struct text_pos start_pos; @@ -20086,6 +20258,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) || w->base_line_pos > 0 /* Column number is displayed and different from the one displayed. */ || (w->column_number_displayed != -1 + && !current_buffer->long_line_optimizations_p && (w->column_number_displayed != current_column ()))) /* This means that the window has a mode line. */ && (window_wants_mode_line (w) @@ -27587,6 +27760,17 @@ decode_mode_spec (struct window *w, register int c, int field_width, even crash emacs.) */ if (mode_line_target == MODE_LINE_TITLE) return ""; + else if (b->long_line_optimizations_p) + { + char *p = decode_mode_spec_buf; + int pad = width - 2; + while (pad-- > 0) + *p++ = ' '; + *p++ = '?'; + *p++ = '?'; + *p = '\0'; + return decode_mode_spec_buf; + } else { ptrdiff_t col = current_column (); @@ -36473,7 +36657,13 @@ The tool bar style must also show labels for this to have any effect, see doc: /* List of functions to call to fontify regions of text. Each function is called with one argument POS. Functions must fontify a region starting at POS in the current buffer, and give -fontified regions the property `fontified'. */); +fontified regions the property `fontified' with a non-nil value. + +Note that, when the buffer contains one or more lines whose length is +above `long-line-threshold', these functions only have access to a +small portion of the buffer around POS, and cannot use `widen' to gain +access to other portions of buffer text because the narrowing of the +buffer is locked (see `narrow-to-region'). */); Vfontification_functions = Qnil; Fmake_variable_buffer_local (Qfontification_functions); |