diff options
| author | Gregory Heytings | 2022-07-21 12:37:45 +0200 |
|---|---|---|
| committer | Gregory Heytings | 2022-07-21 12:37:45 +0200 |
| commit | 616da8fa8efa9023f56fa731072d877e2150afbc (patch) | |
| tree | cabef8906fe8186c67899936e8b28640daeadb06 /src | |
| parent | 51f8e86374a57efe5b8e5c31d96078e63c023da4 (diff) | |
| parent | e09c056a440e78afd0e1920250714bc6de6ccf4f (diff) | |
| download | emacs-616da8fa8efa9023f56fa731072d877e2150afbc.tar.gz emacs-616da8fa8efa9023f56fa731072d877e2150afbc.zip | |
Merge branch 'feature/fix-the-long-lines-display-bug'
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 26 | ||||
| -rw-r--r-- | src/buffer.h | 11 | ||||
| -rw-r--r-- | src/composite.c | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 5 | ||||
| -rw-r--r-- | src/insdel.c | 18 | ||||
| -rw-r--r-- | src/lisp.h | 14 | ||||
| -rw-r--r-- | src/search.c | 2 | ||||
| -rw-r--r-- | src/textprop.c | 2 | ||||
| -rw-r--r-- | src/window.c | 2 | ||||
| -rw-r--r-- | src/window.h | 1 | ||||
| -rw-r--r-- | src/xdisp.c | 103 |
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 (¤t_buffer->text->modiff); | 2470 | modiff_incr (¤t_buffer->text->modiff, 1); |
| 2469 | modiff_incr (&other_buffer->text->modiff); | 2471 | modiff_incr (&other_buffer->text->modiff, 1); |
| 2470 | modiff_incr (¤t_buffer->text->chars_modiff); | 2472 | modiff_incr (¤t_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 (¤t_buffer->text->overlay_modiff); | 2474 | modiff_incr (¤t_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 | |||
| 6427 | will run for `clone-indirect-buffer' calls as well. */); | 6429 | will 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. | ||
| 6434 | Display optimizations for long lines will automatically be enabled in | ||
| 6435 | buffers which contain one or more lines whose length is above that | ||
| 6436 | threshold. | ||
| 6437 | When 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); | |||
| 3396 | void redisplay_preserve_echo_area (int); | 3400 | void redisplay_preserve_echo_area (int); |
| 3397 | void init_iterator (struct it *, struct window *, ptrdiff_t, | 3401 | void 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); |
| 3403 | ptrdiff_t get_narrowed_begv (struct window *w); | ||
| 3399 | void init_iterator_to_row_start (struct it *, struct window *, | 3404 | void init_iterator_to_row_start (struct it *, struct window *, |
| 3400 | struct glyph_row *); | 3405 | struct glyph_row *); |
| 3401 | void start_display (struct it *, struct window *, struct text_pos); | 3406 | void 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) | |||
| 3911 | typedef intmax_t modiff_count; | 3911 | typedef intmax_t modiff_count; |
| 3912 | 3912 | ||
| 3913 | INLINE modiff_count | 3913 | INLINE modiff_count |
| 3914 | modiff_incr (modiff_count *a) | 3914 | modiff_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); |
| 4763 | extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t, | 4767 | extern 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); |
| 4769 | extern ptrdiff_t find_newline1 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, | ||
| 4770 | ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool); | ||
| 4765 | extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, | 4771 | extern 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); |
| 4767 | extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, | 4773 | extern 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. */ |
| 3195 | static ptrdiff_t | 3195 | ptrdiff_t |
| 3196 | find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end, | 3196 | find_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. */ |
| 1031 | static int | 1031 | int |
| 1032 | window_body_height (struct window *w, enum window_body_unit pixelwise) | 1032 | window_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 | }; |
| 1195 | extern int window_body_width (struct window *w, enum window_body_unit); | 1195 | extern int window_body_width (struct window *w, enum window_body_unit); |
| 1196 | extern int window_body_height (struct window *w, enum window_body_unit); | ||
| 1196 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; | 1197 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; |
| 1197 | extern int window_scroll_margin (struct window *, enum margin_unit); | 1198 | extern int window_scroll_margin (struct window *, enum margin_unit); |
| 1198 | extern void temp_output_buffer_show (Lisp_Object); | 1199 | extern 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 | |||
| 3501 | ptrdiff_t | ||
| 3502 | get_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 | |||
| 3514 | static void | ||
| 3515 | unwind_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; |