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.
This commit is contained in:
parent
60e51595c8
commit
1792cbaddc
9 changed files with 63 additions and 77 deletions
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
22
etc/NEWS
22
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
|
||||
|
|
|
@ -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.
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
31
src/xdisp.c
31
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue