aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGregory Heytings2022-07-21 12:37:45 +0200
committerGregory Heytings2022-07-21 12:37:45 +0200
commit616da8fa8efa9023f56fa731072d877e2150afbc (patch)
treecabef8906fe8186c67899936e8b28640daeadb06 /src
parent51f8e86374a57efe5b8e5c31d96078e63c023da4 (diff)
parente09c056a440e78afd0e1920250714bc6de6ccf4f (diff)
downloademacs-616da8fa8efa9023f56fa731072d877e2150afbc.tar.gz
emacs-616da8fa8efa9023f56fa731072d877e2150afbc.zip
Merge branch 'feature/fix-the-long-lines-display-bug'
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c26
-rw-r--r--src/buffer.h11
-rw-r--r--src/composite.c6
-rw-r--r--src/dispextern.h5
-rw-r--r--src/insdel.c18
-rw-r--r--src/lisp.h14
-rw-r--r--src/search.c2
-rw-r--r--src/textprop.c2
-rw-r--r--src/window.c2
-rw-r--r--src/window.h1
-rw-r--r--src/xdisp.c103
11 files changed, 153 insertions, 37 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 4994a310438..a55af906e26 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -985,6 +985,7 @@ reset_buffer (register struct buffer *b)
985 /* It is more conservative to start out "changed" than "unchanged". */ 985 /* It is more conservative to start out "changed" than "unchanged". */
986 b->clip_changed = 0; 986 b->clip_changed = 0;
987 b->prevent_redisplay_optimizations_p = 1; 987 b->prevent_redisplay_optimizations_p = 1;
988 b->long_line_optimizations_p = 0;
988 bset_backed_up (b, Qnil); 989 bset_backed_up (b, Qnil);
989 bset_local_minor_modes (b, Qnil); 990 bset_local_minor_modes (b, Qnil);
990 BUF_AUTOSAVE_MODIFF (b) = 0; 991 BUF_AUTOSAVE_MODIFF (b) = 0;
@@ -1501,7 +1502,7 @@ state of the current buffer. Use with care. */)
1501 decrease SAVE_MODIFF and auto_save_modified or increase 1502 decrease SAVE_MODIFF and auto_save_modified or increase
1502 MODIFF. */ 1503 MODIFF. */
1503 if (SAVE_MODIFF >= MODIFF) 1504 if (SAVE_MODIFF >= MODIFF)
1504 SAVE_MODIFF = modiff_incr (&MODIFF); 1505 SAVE_MODIFF = modiff_incr (&MODIFF, 1);
1505 if (EQ (flag, Qautosaved)) 1506 if (EQ (flag, Qautosaved))
1506 BUF_AUTOSAVE_MODIFF (b) = MODIFF; 1507 BUF_AUTOSAVE_MODIFF (b) = MODIFF;
1507 } 1508 }
@@ -2446,6 +2447,7 @@ results, see Info node `(elisp)Swapping Text'. */)
2446 swapfield (bidi_paragraph_cache, struct region_cache *); 2447 swapfield (bidi_paragraph_cache, struct region_cache *);
2447 current_buffer->prevent_redisplay_optimizations_p = 1; 2448 current_buffer->prevent_redisplay_optimizations_p = 1;
2448 other_buffer->prevent_redisplay_optimizations_p = 1; 2449 other_buffer->prevent_redisplay_optimizations_p = 1;
2450 swapfield (long_line_optimizations_p, bool_bf);
2449 swapfield (overlays_before, struct Lisp_Overlay *); 2451 swapfield (overlays_before, struct Lisp_Overlay *);
2450 swapfield (overlays_after, struct Lisp_Overlay *); 2452 swapfield (overlays_after, struct Lisp_Overlay *);
2451 swapfield (overlay_center, ptrdiff_t); 2453 swapfield (overlay_center, ptrdiff_t);
@@ -2465,12 +2467,12 @@ results, see Info node `(elisp)Swapping Text'. */)
2465 bset_point_before_scroll (current_buffer, Qnil); 2467 bset_point_before_scroll (current_buffer, Qnil);
2466 bset_point_before_scroll (other_buffer, Qnil); 2468 bset_point_before_scroll (other_buffer, Qnil);
2467 2469
2468 modiff_incr (&current_buffer->text->modiff); 2470 modiff_incr (&current_buffer->text->modiff, 1);
2469 modiff_incr (&other_buffer->text->modiff); 2471 modiff_incr (&other_buffer->text->modiff, 1);
2470 modiff_incr (&current_buffer->text->chars_modiff); 2472 modiff_incr (&current_buffer->text->chars_modiff, 1);
2471 modiff_incr (&other_buffer->text->chars_modiff); 2473 modiff_incr (&other_buffer->text->chars_modiff, 1);
2472 modiff_incr (&current_buffer->text->overlay_modiff); 2474 modiff_incr (&current_buffer->text->overlay_modiff, 1);
2473 modiff_incr (&other_buffer->text->overlay_modiff); 2475 modiff_incr (&other_buffer->text->overlay_modiff, 1);
2474 current_buffer->text->beg_unchanged = current_buffer->text->gpt; 2476 current_buffer->text->beg_unchanged = current_buffer->text->gpt;
2475 current_buffer->text->end_unchanged = current_buffer->text->gpt; 2477 current_buffer->text->end_unchanged = current_buffer->text->gpt;
2476 other_buffer->text->beg_unchanged = other_buffer->text->gpt; 2478 other_buffer->text->beg_unchanged = other_buffer->text->gpt;
@@ -4009,7 +4011,7 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
4009 4011
4010 bset_redisplay (buf); 4012 bset_redisplay (buf);
4011 4013
4012 modiff_incr (&BUF_OVERLAY_MODIFF (buf)); 4014 modiff_incr (&BUF_OVERLAY_MODIFF (buf), 1);
4013} 4015}
4014 4016
4015/* Remove OVERLAY from LIST. */ 4017/* Remove OVERLAY from LIST. */
@@ -6427,6 +6429,14 @@ Since `clone-indirect-buffer' calls `make-indirect-buffer', this hook
6427will run for `clone-indirect-buffer' calls as well. */); 6429will run for `clone-indirect-buffer' calls as well. */);
6428 Vclone_indirect_buffer_hook = Qnil; 6430 Vclone_indirect_buffer_hook = Qnil;
6429 6431
6432 DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold,
6433 doc: /* Line length above which specific display optimizations are used.
6434Display optimizations for long lines will automatically be enabled in
6435buffers which contain one or more lines whose length is above that
6436threshold.
6437When nil, these display optimizations are disabled. */);
6438 XSETFASTINT (Vlong_line_threshold, 10000);
6439
6430 defsubr (&Sbuffer_live_p); 6440 defsubr (&Sbuffer_live_p);
6431 defsubr (&Sbuffer_list); 6441 defsubr (&Sbuffer_list);
6432 defsubr (&Sget_buffer); 6442 defsubr (&Sget_buffer);
diff --git a/src/buffer.h b/src/buffer.h
index 135eaf72d30..47b4bdf749b 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -237,9 +237,10 @@ struct buffer_text
237 ptrdiff_t z_byte; /* Byte pos of end of buffer. */ 237 ptrdiff_t z_byte; /* Byte pos of end of buffer. */
238 ptrdiff_t gap_size; /* Size of buffer's gap. */ 238 ptrdiff_t gap_size; /* Size of buffer's gap. */
239 modiff_count modiff; /* This counts buffer-modification events 239 modiff_count modiff; /* This counts buffer-modification events
240 for this buffer. It is incremented for 240 for this buffer. It is increased
241 each such event, and never otherwise 241 logarithmically to the extent of the
242 changed. */ 242 modification for each such event,
243 and never otherwise changed. */
243 modiff_count chars_modiff; /* This is modified with character change 244 modiff_count chars_modiff; /* This is modified with character change
244 events for this buffer. It is set to 245 events for this buffer. It is set to
245 modiff for each such event, and never 246 modiff for each such event, and never
@@ -681,6 +682,10 @@ struct buffer
681 defined, as well as by with-temp-buffer, for example. */ 682 defined, as well as by with-temp-buffer, for example. */
682 bool_bf inhibit_buffer_hooks : 1; 683 bool_bf inhibit_buffer_hooks : 1;
683 684
685 /* Non-zero when the buffer contains long lines and specific
686 display optimizations must be used. */
687 bool_bf long_line_optimizations_p : 1;
688
684 /* List of overlays that end at or before the current center, 689 /* List of overlays that end at or before the current center,
685 in order of end-position. */ 690 in order of end-position. */
686 struct Lisp_Overlay *overlays_before; 691 struct Lisp_Overlay *overlays_before;
diff --git a/src/composite.c b/src/composite.c
index 2dee42b5503..b04d34337b4 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1580,6 +1580,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
1580 Lisp_Object window; 1580 Lisp_Object window;
1581 struct window *w; 1581 struct window *w;
1582 bool need_adjustment = 0; 1582 bool need_adjustment = 0;
1583 ptrdiff_t narrowed_begv;
1583 1584
1584 window = Fget_buffer_window (Fcurrent_buffer (), Qnil); 1585 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1585 if (NILP (window)) 1586 if (NILP (window))
@@ -1596,6 +1597,11 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit, ptrdiff_t backlim,
1596 } 1597 }
1597 else 1598 else
1598 head = backlim; 1599 head = backlim;
1600 /* In buffers with very long lines, this function becomes very
1601 slow. Pretend that the buffer is narrowed to make it fast. */
1602 narrowed_begv = get_narrowed_begv (w);
1603 if (narrowed_begv && pos > narrowed_begv)
1604 head = narrowed_begv;
1599 tail = ZV; 1605 tail = ZV;
1600 stop = GPT; 1606 stop = GPT;
1601 cur.pos_byte = CHAR_TO_BYTE (cur.pos); 1607 cur.pos_byte = CHAR_TO_BYTE (cur.pos);
diff --git a/src/dispextern.h b/src/dispextern.h
index 916dba53198..1cdfdca74c0 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2332,6 +2332,10 @@ struct it
2332 with which display_string was called. */ 2332 with which display_string was called. */
2333 ptrdiff_t end_charpos; 2333 ptrdiff_t end_charpos;
2334 2334
2335 /* Alternate begin position of the buffer that may be used to
2336 optimize display (see the SET_WITH_NARROWED_BEGV macro). */
2337 ptrdiff_t narrowed_begv;
2338
2335 /* C string to iterate over. Non-null means get characters from 2339 /* C string to iterate over. Non-null means get characters from
2336 this string, otherwise characters are read from current_buffer 2340 this string, otherwise characters are read from current_buffer
2337 or it->string. */ 2341 or it->string. */
@@ -3396,6 +3400,7 @@ void mark_window_display_accurate (Lisp_Object, bool);
3396void redisplay_preserve_echo_area (int); 3400void redisplay_preserve_echo_area (int);
3397void init_iterator (struct it *, struct window *, ptrdiff_t, 3401void init_iterator (struct it *, struct window *, ptrdiff_t,
3398 ptrdiff_t, struct glyph_row *, enum face_id); 3402 ptrdiff_t, struct glyph_row *, enum face_id);
3403ptrdiff_t get_narrowed_begv (struct window *w);
3399void init_iterator_to_row_start (struct it *, struct window *, 3404void init_iterator_to_row_start (struct it *, struct window *,
3400 struct glyph_row *); 3405 struct glyph_row *);
3401void start_display (struct it *, struct window *, struct text_pos); 3406void start_display (struct it *, struct window *, struct text_pos);
diff --git a/src/insdel.c b/src/insdel.c
index 9b292398537..38d5fbda002 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -909,7 +909,7 @@ insert_1_both (const char *string,
909 the insertion. This, together with recording the insertion, 909 the insertion. This, together with recording the insertion,
910 will add up to the right stuff in the undo list. */ 910 will add up to the right stuff in the undo list. */
911 record_insert (PT, nchars); 911 record_insert (PT, nchars);
912 modiff_incr (&MODIFF); 912 modiff_incr (&MODIFF, nchars);
913 CHARS_MODIFF = MODIFF; 913 CHARS_MODIFF = MODIFF;
914 914
915 memcpy (GPT_ADDR, string, nbytes); 915 memcpy (GPT_ADDR, string, nbytes);
@@ -1037,7 +1037,7 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1037#endif 1037#endif
1038 1038
1039 record_insert (PT, nchars); 1039 record_insert (PT, nchars);
1040 modiff_incr (&MODIFF); 1040 modiff_incr (&MODIFF, nchars);
1041 CHARS_MODIFF = MODIFF; 1041 CHARS_MODIFF = MODIFF;
1042 1042
1043 GAP_SIZE -= outgoing_nbytes; 1043 GAP_SIZE -= outgoing_nbytes;
@@ -1122,7 +1122,7 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1122 of this dance. */ 1122 of this dance. */
1123 invalidate_buffer_caches (current_buffer, GPT, GPT); 1123 invalidate_buffer_caches (current_buffer, GPT, GPT);
1124 record_insert (GPT, nchars); 1124 record_insert (GPT, nchars);
1125 modiff_incr (&MODIFF); 1125 modiff_incr (&MODIFF, nchars);
1126 CHARS_MODIFF = MODIFF; 1126 CHARS_MODIFF = MODIFF;
1127 1127
1128 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail); 1128 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail);
@@ -1251,7 +1251,7 @@ insert_from_buffer_1 (struct buffer *buf,
1251#endif 1251#endif
1252 1252
1253 record_insert (PT, nchars); 1253 record_insert (PT, nchars);
1254 modiff_incr (&MODIFF); 1254 modiff_incr (&MODIFF, nchars);
1255 CHARS_MODIFF = MODIFF; 1255 CHARS_MODIFF = MODIFF;
1256 1256
1257 GAP_SIZE -= outgoing_nbytes; 1257 GAP_SIZE -= outgoing_nbytes;
@@ -1352,7 +1352,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1352 1352
1353 if (len == 0) 1353 if (len == 0)
1354 evaporate_overlays (from); 1354 evaporate_overlays (from);
1355 modiff_incr (&MODIFF); 1355 modiff_incr (&MODIFF, nchars_del + len);
1356 CHARS_MODIFF = MODIFF; 1356 CHARS_MODIFF = MODIFF;
1357} 1357}
1358 1358
@@ -1547,7 +1547,7 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1547 1547
1548 check_markers (); 1548 check_markers ();
1549 1549
1550 modiff_incr (&MODIFF); 1550 modiff_incr (&MODIFF, nchars_del + inschars);
1551 CHARS_MODIFF = MODIFF; 1551 CHARS_MODIFF = MODIFF;
1552 1552
1553 if (adjust_match_data) 1553 if (adjust_match_data)
@@ -1681,7 +1681,7 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1681 1681
1682 check_markers (); 1682 check_markers ();
1683 1683
1684 modiff_incr (&MODIFF); 1684 modiff_incr (&MODIFF, nchars_del + inschars);
1685 CHARS_MODIFF = MODIFF; 1685 CHARS_MODIFF = MODIFF;
1686} 1686}
1687 1687
@@ -1856,7 +1856,7 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1856 at the end of the text before the gap. */ 1856 at the end of the text before the gap. */
1857 adjust_markers_for_delete (from, from_byte, to, to_byte); 1857 adjust_markers_for_delete (from, from_byte, to, to_byte);
1858 1858
1859 modiff_incr (&MODIFF); 1859 modiff_incr (&MODIFF, nchars_del);
1860 CHARS_MODIFF = MODIFF; 1860 CHARS_MODIFF = MODIFF;
1861 1861
1862 /* Relocate point as if it were a marker. */ 1862 /* Relocate point as if it were a marker. */
@@ -1910,7 +1910,7 @@ modify_text (ptrdiff_t start, ptrdiff_t end)
1910 BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end); 1910 BUF_COMPUTE_UNCHANGED (current_buffer, start - 1, end);
1911 if (MODIFF <= SAVE_MODIFF) 1911 if (MODIFF <= SAVE_MODIFF)
1912 record_first_change (); 1912 record_first_change ();
1913 modiff_incr (&MODIFF); 1913 modiff_incr (&MODIFF, end - start);
1914 CHARS_MODIFF = MODIFF; 1914 CHARS_MODIFF = MODIFF;
1915 1915
1916 bset_point_before_scroll (current_buffer, Qnil); 1916 bset_point_before_scroll (current_buffer, Qnil);
diff --git a/src/lisp.h b/src/lisp.h
index dc496cc1658..2afe135674d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3911,10 +3911,14 @@ integer_to_uintmax (Lisp_Object num, uintmax_t *n)
3911typedef intmax_t modiff_count; 3911typedef intmax_t modiff_count;
3912 3912
3913INLINE modiff_count 3913INLINE modiff_count
3914modiff_incr (modiff_count *a) 3914modiff_incr (modiff_count *a, ptrdiff_t len)
3915{ 3915{
3916 modiff_count a0 = *a; 3916 modiff_count a0 = *a; int incr = len ? 1 : 0;
3917 bool modiff_overflow = INT_ADD_WRAPV (a0, 1, a); 3917 /* Increase the counter more for a large modification and less for a
3918 small modification. Increase it logarithmically to avoid
3919 increasing it too much. */
3920 while (len >>= 1) incr++;
3921 bool modiff_overflow = INT_ADD_WRAPV (a0, incr, a);
3918 eassert (!modiff_overflow && *a >> 30 >> 30 == 0); 3922 eassert (!modiff_overflow && *a >> 30 >> 30 == 0);
3919 return a0; 3923 return a0;
3920} 3924}
@@ -4762,6 +4766,8 @@ extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
4762 ptrdiff_t); 4766 ptrdiff_t);
4763extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, 4767extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
4764 ptrdiff_t, ptrdiff_t, Lisp_Object); 4768 ptrdiff_t, ptrdiff_t, Lisp_Object);
4769extern ptrdiff_t find_newline1 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
4770 ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
4765extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, 4771extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
4766 ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool); 4772 ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
4767extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, 4773extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
diff --git a/src/search.c b/src/search.c
index 9d6bd074e1b..b5d6a442c0f 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3192,7 +3192,7 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
3192} 3192}
3193 3193
3194/* Like find_newline, but doesn't use the cache, and only searches forward. */ 3194/* Like find_newline, but doesn't use the cache, and only searches forward. */
3195static ptrdiff_t 3195ptrdiff_t
3196find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, 3196find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
3197 ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted, 3197 ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
3198 ptrdiff_t *bytepos, bool allow_quit) 3198 ptrdiff_t *bytepos, bool allow_quit)
diff --git a/src/textprop.c b/src/textprop.c
index 96d07b44be8..c91a2b729c6 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -88,7 +88,7 @@ modify_text_properties (Lisp_Object buffer, Lisp_Object start, Lisp_Object end)
88 BUF_COMPUTE_UNCHANGED (buf, b - 1, e); 88 BUF_COMPUTE_UNCHANGED (buf, b - 1, e);
89 if (MODIFF <= SAVE_MODIFF) 89 if (MODIFF <= SAVE_MODIFF)
90 record_first_change (); 90 record_first_change ();
91 modiff_incr (&MODIFF); 91 modiff_incr (&MODIFF, 1);
92 92
93 bset_point_before_scroll (current_buffer, Qnil); 93 bset_point_before_scroll (current_buffer, Qnil);
94 94
diff --git a/src/window.c b/src/window.c
index 10373f8a2bf..8f889585582 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1028,7 +1028,7 @@ window_body_unit_from_symbol (Lisp_Object unit)
1028/* Return the number of lines/pixels of W's body. Don't count any mode 1028/* Return the number of lines/pixels of W's body. Don't count any mode
1029 or header line or horizontal divider of W. Rounds down to nearest 1029 or header line or horizontal divider of W. Rounds down to nearest
1030 integer when not working pixelwise. */ 1030 integer when not working pixelwise. */
1031static int 1031int
1032window_body_height (struct window *w, enum window_body_unit pixelwise) 1032window_body_height (struct window *w, enum window_body_unit pixelwise)
1033{ 1033{
1034 int height = (w->pixel_height 1034 int height = (w->pixel_height
diff --git a/src/window.h b/src/window.h
index 298a80a5366..c63b1b24d4f 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1193,6 +1193,7 @@ enum window_body_unit
1193 WINDOW_BODY_IN_REMAPPED_CHARS 1193 WINDOW_BODY_IN_REMAPPED_CHARS
1194 }; 1194 };
1195extern int window_body_width (struct window *w, enum window_body_unit); 1195extern int window_body_width (struct window *w, enum window_body_unit);
1196extern int window_body_height (struct window *w, enum window_body_unit);
1196enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; 1197enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
1197extern int window_scroll_margin (struct window *, enum margin_unit); 1198extern int window_scroll_margin (struct window *, enum margin_unit);
1198extern void temp_output_buffer_show (Lisp_Object); 1199extern void temp_output_buffer_show (Lisp_Object);
diff --git a/src/xdisp.c b/src/xdisp.c
index b693df4adb8..ebeaf2a3dab 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3425,6 +3425,9 @@ init_iterator (struct it *it, struct window *w,
3425 } 3425 }
3426 } 3426 }
3427 3427
3428 if (current_buffer->long_line_optimizations_p)
3429 it->narrowed_begv = get_narrowed_begv (w);
3430
3428 /* If a buffer position was specified, set the iterator there, 3431 /* If a buffer position was specified, set the iterator there,
3429 getting overlays and face properties from that position. */ 3432 getting overlays and face properties from that position. */
3430 if (charpos >= BUF_BEG (current_buffer)) 3433 if (charpos >= BUF_BEG (current_buffer))
@@ -3491,6 +3494,45 @@ init_iterator (struct it *it, struct window *w,
3491 CHECK_IT (it); 3494 CHECK_IT (it);
3492} 3495}
3493 3496
3497/* Compute a suitable alternate value for BEGV that may be used
3498 temporarily to optimize display if the buffer in window W contains
3499 long lines. */
3500
3501ptrdiff_t
3502get_narrowed_begv (struct window *w)
3503{
3504 int len, fact; ptrdiff_t begv;
3505 /* In a character-only terminal, only one font size is used, so we
3506 can use a smaller factor. */
3507 fact = EQ (Fterminal_live_p (Qnil), Qt) ? 2 : 3;
3508 len = fact * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
3509 window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
3510 begv = max ((window_point (w) / len - 1) * len, BEGV);
3511 return begv == BEGV ? 0 : begv;
3512}
3513
3514static void
3515unwind_narrowed_begv (Lisp_Object point_min)
3516{
3517 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3518}
3519
3520/* Set DST to EXPR. When IT indicates that BEGV should temporarily be
3521 updated to optimize display, evaluate EXPR with an updated BEGV. */
3522
3523#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR) \
3524 do { \
3525 if (IT->narrowed_begv) \
3526 { \
3527 specpdl_ref count = SPECPDL_INDEX (); \
3528 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3529 SET_BUF_BEGV (current_buffer, IT->narrowed_begv); \
3530 DST = EXPR; \
3531 unbind_to (count, Qnil); \
3532 } \
3533 else \
3534 DST = EXPR; \
3535 } while (0)
3494 3536
3495/* Initialize IT for the display of window W with window start POS. */ 3537/* Initialize IT for the display of window W with window start POS. */
3496 3538
@@ -6992,7 +7034,8 @@ back_to_previous_line_start (struct it *it)
6992 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); 7034 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
6993 7035
6994 dec_both (&cp, &bp); 7036 dec_both (&cp, &bp);
6995 IT_CHARPOS (*it) = find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)); 7037 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7038 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
6996} 7039}
6997 7040
6998 7041
@@ -7210,7 +7253,8 @@ back_to_previous_visible_line_start (struct it *it)
7210 it->continuation_lines_width = 0; 7253 it->continuation_lines_width = 0;
7211 7254
7212 eassert (IT_CHARPOS (*it) >= BEGV); 7255 eassert (IT_CHARPOS (*it) >= BEGV);
7213 eassert (IT_CHARPOS (*it) == BEGV 7256 eassert (it->narrowed_begv > BEGV
7257 || IT_CHARPOS (*it) == BEGV
7214 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); 7258 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7215 CHECK_IT (it); 7259 CHECK_IT (it);
7216} 7260}
@@ -8623,7 +8667,12 @@ get_visually_first_element (struct it *it)
8623{ 8667{
8624 bool string_p = STRINGP (it->string) || it->s; 8668 bool string_p = STRINGP (it->string) || it->s;
8625 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV); 8669 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8626 ptrdiff_t bob = (string_p ? 0 : BEGV); 8670 ptrdiff_t bob;
8671 ptrdiff_t obegv = BEGV;
8672
8673 SET_WITH_NARROWED_BEGV (it, bob,
8674 string_p ? 0 :
8675 IT_BYTEPOS (*it) < BEGV ? obegv : BEGV);
8627 8676
8628 if (STRINGP (it->string)) 8677 if (STRINGP (it->string))
8629 { 8678 {
@@ -8663,9 +8712,10 @@ get_visually_first_element (struct it *it)
8663 if (string_p) 8712 if (string_p)
8664 it->bidi_it.charpos = it->bidi_it.bytepos = 0; 8713 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8665 else 8714 else
8666 it->bidi_it.charpos = find_newline_no_quit (IT_CHARPOS (*it), 8715 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8667 IT_BYTEPOS (*it), -1, 8716 find_newline_no_quit (IT_CHARPOS (*it),
8668 &it->bidi_it.bytepos); 8717 IT_BYTEPOS (*it), -1,
8718 &it->bidi_it.bytepos));
8669 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); 8719 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8670 do 8720 do
8671 { 8721 {
@@ -10583,7 +10633,8 @@ move_it_vertically_backward (struct it *it, int dy)
10583 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it); 10633 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10584 10634
10585 dec_both (&cp, &bp); 10635 dec_both (&cp, &bp);
10586 cp = find_newline_no_quit (cp, bp, -1, NULL); 10636 SET_WITH_NARROWED_BEGV (it, cp,
10637 find_newline_no_quit (cp, bp, -1, NULL));
10587 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS); 10638 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10588 } 10639 }
10589 bidi_unshelve_cache (it3data, true); 10640 bidi_unshelve_cache (it3data, true);
@@ -18879,11 +18930,25 @@ set_vertical_scroll_bar (struct window *w)
18879 && NILP (echo_area_buffer[0]))) 18930 && NILP (echo_area_buffer[0])))
18880 { 18931 {
18881 struct buffer *buf = XBUFFER (w->contents); 18932 struct buffer *buf = XBUFFER (w->contents);
18933 ptrdiff_t window_end_pos = w->window_end_pos;
18934
18935 /* If w->window_end_pos cannot be trusted, recompute it "the
18936 hard way". */
18937 if (!w->window_end_valid)
18938 {
18939 struct it it;
18940 struct text_pos start_pos;
18941
18942 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18943 start_display (&it, w, start_pos);
18944 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
18945 MOVE_TO_X | MOVE_TO_Y);
18946 window_end_pos = BUF_Z (buf) - IT_CHARPOS (it);
18947 }
18948
18882 whole = BUF_ZV (buf) - BUF_BEGV (buf); 18949 whole = BUF_ZV (buf) - BUF_BEGV (buf);
18883 start = marker_position (w->start) - BUF_BEGV (buf); 18950 start = marker_position (w->start) - BUF_BEGV (buf);
18884 /* I don't think this is guaranteed to be right. For the 18951 end = BUF_Z (buf) - window_end_pos - BUF_BEGV (buf);
18885 moment, we'll pretend it is. */
18886 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
18887 18952
18888 if (end < start) 18953 if (end < start)
18889 end = start; 18954 end = start;
@@ -19232,6 +19297,24 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19232 } 19297 }
19233 } 19298 }
19234 19299
19300 /* Check whether the buffer to be displayed contains long lines. */
19301 if (!NILP (Vlong_line_threshold)
19302 && !current_buffer->long_line_optimizations_p
19303 && MODIFF - UNCHANGED_MODIFIED > 8)
19304 {
19305 ptrdiff_t cur, next, found, max = 0, threshold;
19306 threshold = XFIXNUM (Vlong_line_threshold);
19307 for (cur = 1; cur < Z; cur = next)
19308 {
19309 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19310 &found, NULL, true);
19311 if (next - cur > max) max = next - cur;
19312 if (!found || max > threshold) break;
19313 }
19314 if (max > threshold)
19315 current_buffer->long_line_optimizations_p = true;
19316 }
19317
19235 /* If window-start is screwed up, choose a new one. */ 19318 /* If window-start is screwed up, choose a new one. */
19236 if (XMARKER (w->start)->buffer != current_buffer) 19319 if (XMARKER (w->start)->buffer != current_buffer)
19237 goto recenter; 19320 goto recenter;