[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/fix-the-long-lines-display-bug 1792cbaddc: Actually fix the long
From: |
Gregory Heytings |
Subject: |
feature/fix-the-long-lines-display-bug 1792cbaddc: Actually fix the long lines display bug (bug#56393). |
Date: |
Fri, 8 Jul 2022 17:37:20 -0400 (EDT) |
branch: feature/fix-the-long-lines-display-bug
commit 1792cbaddc33772c344e45fb9478bee85fee66e7
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>
Actually fix the long lines display bug (bug#56393).
* src/dispextern.h (struct it): New 'narrowed_begv' field.
* src/dispextern.h (WITH_NARROWED_BEGV): New macro.
* src/xdisp.c (get_narrowed_begv): New function.
(init_iterator): Initilize the 'narrowed_begv' field.
(back_to_previous_line_start, get_visually_first_element,
move_it_vertically_backward): Use the new macro.
* src/dispextern.h: Prototype of 'get_narrowed_begv'.
* src/window.c (window_body_height): Make it externally visible.
* src/window.h: Prototype of 'window_body_height'.
* src/composite.c (find_automatic_composition): Optimize display in buffers
with very long lines with 'get_narrowed_begv'.
* lisp/obsolete/longlines.el: Reobsolete longlines-mode.
* etc/NEWS: Announce the new minor mode, and remove the unobsoletion
indication for 'longlines-mode'.
* doc/emacs/trouble.texi (Long Lines): Remove the section.
(Lossage): Remove the entry for the Long Lines section.
* doc/emacs/emacs.texi (Top): Remove the entry for the Long Lines section.
---
doc/emacs/emacs.texi | 1 -
doc/emacs/trouble.texi | 59 ----------------------------------------
etc/NEWS | 22 ++++++++-------
lisp/{ => obsolete}/longlines.el | 1 +
src/composite.c | 6 ++++
src/dispextern.h | 17 ++++++++++++
src/window.c | 2 +-
src/window.h | 1 +
src/xdisp.c | 31 +++++++++++++++++----
9 files changed, 63 insertions(+), 77 deletions(-)
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 5e72699bbe..b43c966f87 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -1190,7 +1190,6 @@ Dealing with Emacs Trouble
* Crashing:: What Emacs does when it crashes.
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
-* Long Lines:: Mitigating slowness due to extremely long lines.
* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
Reporting Bugs
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index f06b93759d..887e5c6170 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -158,7 +158,6 @@ Emacs.
* Crashing:: What Emacs does when it crashes.
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
-* Long Lines:: Mitigating slowness due to extremely long lines.
* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
@end menu
@@ -433,64 +432,6 @@ program.
emergency escape---but there are cases where it won't work, when a
system call hangs or when Emacs is stuck in a tight loop in C code.
-@node Long Lines
-@subsection Long Lines
-@cindex long lines
-
- For a variety of reasons (some of which are fundamental to the Emacs
-redisplay code and the complex range of possibilities it handles;
-others of which are due to modes and features which do not scale well
-in unusual circumstances), Emacs can perform poorly when extremely
-long lines are present (where ``extremely long'' usually means at
-least many thousands of characters).
-
-@cindex @code{so-long} mode
-@findex global-so-long-mode
-@vindex so-long-action
- A particular problem is that Emacs may ``hang'' for a long time at
-the point of visiting a file with extremely long lines. This can be
-mitigated by enabling the @file{so-long} library, which detects when a
-visited file contains abnormally long lines, and takes steps to
-disable features which are liable to cause slowness in that situation.
-To enable this library, type @kbd{M-x global-so-long-mode @key{RET}},
-or turn on the @code{global-so-long-mode} in your init file
-(@pxref{Init File}), or customize the @code{global-so-long-mode}
-option. You can tailor this mode's operation by customizing the
-variable @code{so-long-action}.
-
- The @file{so-long} library can also significantly improve
-performance when moving and editing in a buffer with long lines.
-Performance is still likely to degrade as you get deeper into the long
-lines, but the improvements from using this library can nevertheless
-be substantial.
-
-@findex so-long-commentary
- Use @kbd{M-x so-long-commentary} to view the documentation for this
-library and learn more about how to enable and configure it.
-
-@vindex max-redisplay-ticks
- If even @code{so-long-mode} doesn't help making Emacs responsive
-enough, or if you'd rather not disable the display-related features
-that @code{so-long-mode} turns off, you can instead customize the
-variable @code{max-redisplay-ticks} to a non-zero value. Then Emacs
-will abort redisplay of a window and commands, like @kbd{C-n} and
-@kbd{M-v}, which use the display code to do their job, if processing a
-window needs more low-level display operations than the value of this
-variable. The display of the offending window will then remain
-outdated, and possibly incomplete, on the screen, but Emacs should
-otherwise be responsive, and you could then switch to another buffer,
-or kill the problematic buffer, or turn on @code{so-long-mode} or
-@code{so-long-minor-mode} in that buffer. When the display of a
-window is aborted due to this reason, the buffer shown in that window
-will not have any of its windows redisplayed until the buffer is
-modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of
-that buffer's windows.
-
- If you decide to customize this variable to a non-zero value, we
-recommend to use a value between 100,000 and 1,000,000, depending on
-your patience and the speed of your system. The default value is
-zero, which disables this feature.
-
@node DEL Does Not Delete
@subsection If @key{DEL} Fails to Delete
@cindex @key{DEL} vs @key{BACKSPACE}
diff --git a/etc/NEWS b/etc/NEWS
index 7a1b7a856a..223e6dd761 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -325,7 +325,14 @@ startup. Previously, these functions ignored
* Changes in Emacs 29.1
---
-** 'longlines-mode' is no longer obsolete.
+** Emacs is now capable of editing files with arbitarily 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 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.
+++
** New command to change the font size globally.
@@ -347,10 +354,10 @@ Get the parent directory of a file.
This variable is used by some operations (mostly syntax-propertization
and font-locking) to treat lines longer than this variable as if they
were made up of various smaller lines. This can help reduce the
-pathological slowdowns seen in buffers made of a single long line, but
-can also cause misbehavior in the presence of such long lines (tho
-most of that misbehavior should usually be limited to mis-highlighting).
-You can recover the previous behavior with:
+slowdowns seen in buffers made of a single long line, but can also
+cause misbehavior in the presence of such long lines (tho most of that
+misbehavior should usually be limited to mis-highlighting). You can
+recover the previous behavior with:
(setq syntax-wholeline-max most-positive-fixnum)
@@ -462,11 +469,6 @@ including those typed in response to passwords prompt
(this was the
previous behavior). The default is nil, which inhibits recording of
passwords.
-+++
-** New user option 'longlines-breakpoint-chars'.
-This is a string containing chars that could be used as breakpoint in
-longlines mode.
-
+++
** New function 'command-query'.
This function makes its argument command prompt the user for
diff --git a/lisp/longlines.el b/lisp/obsolete/longlines.el
similarity index 99%
rename from lisp/longlines.el
rename to lisp/obsolete/longlines.el
index a6cf93a039..d44a634e2e 100644
--- a/lisp/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -6,6 +6,7 @@
;; Alex Schroeder <alex@gnu.org>
;; Chong Yidong <cyd@stupidchicken.com>
;; Maintainer: emacs-devel@gnu.org
+;; Obsolete-since: 24.4
;; Keywords: convenience, wp
;; This file is part of GNU Emacs.
diff --git a/src/composite.c b/src/composite.c
index 4d69702171..d8998b5a1f 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1576,6 +1576,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t
limit, ptrdiff_t backlim,
Lisp_Object window;
struct window *w;
bool need_adjustment = 0;
+ ptrdiff_t narrowed_begv;
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
if (NILP (window))
@@ -1586,6 +1587,11 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t
limit, ptrdiff_t backlim,
if (NILP (string))
{
head = backlim < 0 ? BEGV : backlim, tail = ZV, stop = GPT;
+ /* In buffers with very long lines, this function becomes very
+ slow. Pretend that the buffer is narrowed to make it fast. */
+ narrowed_begv = get_narrowed_begv (w);
+ if (pos > narrowed_begv)
+ head = narrowed_begv;
cur.pos_byte = CHAR_TO_BYTE (cur.pos);
cur.p = BYTE_POS_ADDR (cur.pos_byte);
}
diff --git a/src/dispextern.h b/src/dispextern.h
index ca7834dec5..2edf4b73f8 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2332,6 +2332,10 @@ 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). */
+ ptrdiff_t narrowed_begv;
+
/* C string to iterate over. Non-null means get characters from
this string, otherwise characters are read from current_buffer
or it->string. */
@@ -2813,6 +2817,18 @@ 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
@@ -3396,6 +3412,7 @@ 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);
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/window.c b/src/window.c
index af463b90ce..61ca9feb64 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1028,7 +1028,7 @@ window_body_unit_from_symbol (Lisp_Object unit)
/* Return the number of lines/pixels of W's body. Don't count any mode
or header line or horizontal divider of W. Rounds down to nearest
integer when not working pixelwise. */
-static int
+int
window_body_height (struct window *w, enum window_body_unit pixelwise)
{
int height = (w->pixel_height
diff --git a/src/window.h b/src/window.h
index 298a80a536..c63b1b24d4 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1193,6 +1193,7 @@ enum window_body_unit
WINDOW_BODY_IN_REMAPPED_CHARS
};
extern int window_body_width (struct window *w, enum window_body_unit);
+extern int window_body_height (struct window *w, enum window_body_unit);
enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
extern int window_scroll_margin (struct window *, enum margin_unit);
extern void temp_output_buffer_show (Lisp_Object);
diff --git a/src/xdisp.c b/src/xdisp.c
index 4089525e10..e130b23d9a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3425,6 +3425,8 @@ init_iterator (struct it *it, struct window *w,
}
}
+ 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. */
if (charpos >= BUF_BEG (current_buffer))
@@ -3491,6 +3493,19 @@ 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. */
+
+ptrdiff_t
+get_narrowed_begv (struct window *w)
+{
+ int len, 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);
+ return begv == BEGV ? 0 : begv;
+}
/* Initialize IT for the display of window W with window start POS. */
@@ -6992,7 +7007,8 @@ back_to_previous_line_start (struct it *it)
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
dec_both (&cp, &bp);
- IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it));
+ WITH_NARROWED_BEGV (IT_CHARPOS (*it) =
+ find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
}
@@ -8623,7 +8639,9 @@ get_visually_first_element (struct it *it)
{
bool string_p = STRINGP (it->string) || it->s;
ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
- ptrdiff_t bob = (string_p ? 0 : BEGV);
+ ptrdiff_t bob;
+
+ WITH_NARROWED_BEGV (bob = (string_p ? 0 : BEGV));
if (STRINGP (it->string))
{
@@ -8663,9 +8681,10 @@ get_visually_first_element (struct it *it)
if (string_p)
it->bidi_it.charpos = it->bidi_it.bytepos = 0;
else
- it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it),
- IT_BYTEPOS (*it), -1,
- &it->bidi_it.bytepos);
+ WITH_NARROWED_BEGV (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
{
@@ -10583,7 +10602,7 @@ move_it_vertically_backward (struct it *it, int dy)
ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
dec_both (&cp, &bp);
- cp = find_newline_no_quit (cp, bp, -1, NULL);
+ WITH_NARROWED_BEGV (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);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- feature/fix-the-long-lines-display-bug 1792cbaddc: Actually fix the long lines display bug (bug#56393).,
Gregory Heytings <=