aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-09-17 18:18:56 +0300
committerEli Zaretskii2011-09-17 18:18:56 +0300
commit1137e8b8eb6fbae76880b814d516377de30eddd3 (patch)
tree51e82ce03063d5940d0e9e27fff0f10f2587634b /src
parent8d5ed89901195abc4a5d660371ea26e849292ea6 (diff)
downloademacs-1137e8b8eb6fbae76880b814d516377de30eddd3.tar.gz
emacs-1137e8b8eb6fbae76880b814d516377de30eddd3.zip
Fix bug #9470 with slow redisplay in huge single-paragraph buffers.
src/bidi.c (MAX_PARAGRAPH_SEARCH): New macro. (bidi_find_paragraph_start): Search back for paragraph beginning at most MAX_PARAGRAPH_SEARCH lines; if not found, return BEGV_BYTE. (bidi_move_to_visually_next): Only trigger paragraph-related computations when the last character is a newline or at EOB, not just any NEUTRAL_B. src/xdisp.c (reseat_at_next_visible_line_start): Keep information about the current paragraph and restore it after the call to reseat.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/bidi.c20
-rw-r--r--src/xdisp.c42
3 files changed, 69 insertions, 4 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d09c970bc03..a6d890cd149 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,16 @@
12011-09-17 Eli Zaretskii <eliz@gnu.org> 12011-09-17 Eli Zaretskii <eliz@gnu.org>
2 2
3 * xdisp.c (reseat_at_next_visible_line_start): Keep information
4 about the current paragraph and restore it after the call to
5 reseat.
6
7 * bidi.c (MAX_PARAGRAPH_SEARCH): New macro.
8 (bidi_find_paragraph_start): Search back for paragraph beginning
9 at most MAX_PARAGRAPH_SEARCH lines; if not found, return BEGV_BYTE.
10 (bidi_move_to_visually_next): Only trigger paragraph-related
11 computations when the last character is a newline or at EOB, not
12 just any NEUTRAL_B. (Bug#9470)
13
3 * xdisp.c (set_cursor_from_row): Don't invoke special treatment of 14 * xdisp.c (set_cursor_from_row): Don't invoke special treatment of
4 truncated lines if point is covered by a display string. (Bug#9524) 15 truncated lines if point is covered by a display string. (Bug#9524)
5 16
diff --git a/src/bidi.c b/src/bidi.c
index bb29647ea88..3efdc1590df 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -1071,15 +1071,25 @@ bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos)
1071 return val; 1071 return val;
1072} 1072}
1073 1073
1074/* On my 2005-vintage machine, searching back for paragraph start
1075 takes ~1 ms per line. And bidi_paragraph_init is called 4 times
1076 when user types C-p. The number below limits each call to
1077 bidi_paragraph_init to about 10 ms. */
1078#define MAX_PARAGRAPH_SEARCH 7500
1079
1074/* Find the beginning of this paragraph by looking back in the buffer. 1080/* Find the beginning of this paragraph by looking back in the buffer.
1075 Value is the byte position of the paragraph's beginning. */ 1081 Value is the byte position of the paragraph's beginning, or
1082 BEGV_BYTE if paragraph_start_re is still not found after looking
1083 back MAX_PARAGRAPH_SEARCH lines in the buffer. */
1076static EMACS_INT 1084static EMACS_INT
1077bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte) 1085bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
1078{ 1086{
1079 Lisp_Object re = paragraph_start_re; 1087 Lisp_Object re = paragraph_start_re;
1080 EMACS_INT limit = ZV, limit_byte = ZV_BYTE; 1088 EMACS_INT limit = ZV, limit_byte = ZV_BYTE;
1089 EMACS_INT n = 0;
1081 1090
1082 while (pos_byte > BEGV_BYTE 1091 while (pos_byte > BEGV_BYTE
1092 && n++ < MAX_PARAGRAPH_SEARCH
1083 && fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0) 1093 && fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0)
1084 { 1094 {
1085 /* FIXME: What if the paragraph beginning is covered by a 1095 /* FIXME: What if the paragraph beginning is covered by a
@@ -1089,6 +1099,8 @@ bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
1089 pos = find_next_newline_no_quit (pos - 1, -1); 1099 pos = find_next_newline_no_quit (pos - 1, -1);
1090 pos_byte = CHAR_TO_BYTE (pos); 1100 pos_byte = CHAR_TO_BYTE (pos);
1091 } 1101 }
1102 if (n >= MAX_PARAGRAPH_SEARCH)
1103 pos_byte = BEGV_BYTE;
1092 return pos_byte; 1104 return pos_byte;
1093} 1105}
1094 1106
@@ -2239,7 +2251,8 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
2239 GCPRO1 (bidi_it->string.lstring); 2251 GCPRO1 (bidi_it->string.lstring);
2240 2252
2241 /* If we just passed a newline, initialize for the next line. */ 2253 /* If we just passed a newline, initialize for the next line. */
2242 if (!bidi_it->first_elt && bidi_it->orig_type == NEUTRAL_B) 2254 if (!bidi_it->first_elt
2255 && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
2243 bidi_line_init (bidi_it); 2256 bidi_line_init (bidi_it);
2244 2257
2245 /* Prepare the sentinel iterator state, and cache it. When we bump 2258 /* Prepare the sentinel iterator state, and cache it. When we bump
@@ -2320,7 +2333,8 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
2320 reordering, whereas we _must_ know the paragraph base direction 2333 reordering, whereas we _must_ know the paragraph base direction
2321 _before_ we process the paragraph's text, since the base 2334 _before_ we process the paragraph's text, since the base
2322 direction affects the reordering. */ 2335 direction affects the reordering. */
2323 if (bidi_it->scan_dir == 1 && bidi_it->orig_type == NEUTRAL_B) 2336 if (bidi_it->scan_dir == 1
2337 && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
2324 { 2338 {
2325 /* The paragraph direction of the entire string, once 2339 /* The paragraph direction of the entire string, once
2326 determined, is in effect for the entire string. Setting the 2340 determined, is in effect for the entire string. Setting the
diff --git a/src/xdisp.c b/src/xdisp.c
index 864734d4b20..3cb9f301bb2 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -5722,6 +5722,9 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p)
5722{ 5722{
5723 int newline_found_p, skipped_p = 0; 5723 int newline_found_p, skipped_p = 0;
5724 struct bidi_it bidi_it_prev; 5724 struct bidi_it bidi_it_prev;
5725 int new_paragraph, first_elt, disp_prop;
5726 EMACS_INT paragraph_end, disp_pos;
5727 bidi_dir_t paragraph_dir;
5725 5728
5726 newline_found_p = forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); 5729 newline_found_p = forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
5727 5730
@@ -5738,6 +5741,23 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p)
5738 forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); 5741 forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
5739 } 5742 }
5740 5743
5744 /* Under bidi iteration, save the attributes of the paragraph we are
5745 in, to be restored after the call to `reseat' below. That's
5746 because `reseat' overwrites them, which requires unneeded and
5747 potentially expensive backward search for paragraph beginning.
5748 This search is unnecessary because we will be `reseat'ed to the
5749 same position where we are now, for which we already have all the
5750 information we need in the bidi iterator. */
5751 if (it->bidi_p && !STRINGP (it->string))
5752 {
5753 new_paragraph = it->bidi_it.new_paragraph;
5754 first_elt = it->bidi_it.first_elt;
5755 paragraph_end = it->bidi_it.separator_limit;
5756 paragraph_dir = it->bidi_it.paragraph_dir;
5757 disp_pos = it->bidi_it.disp_pos;
5758 disp_prop = it->bidi_it.disp_prop;
5759 }
5760
5741 /* Position on the newline if that's what's requested. */ 5761 /* Position on the newline if that's what's requested. */
5742 if (on_newline_p && newline_found_p) 5762 if (on_newline_p && newline_found_p)
5743 { 5763 {
@@ -5777,10 +5797,30 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p)
5777 IT_BYTEPOS (*it) = it->bidi_it.bytepos; 5797 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5778 } 5798 }
5779 reseat (it, it->current.pos, 0); 5799 reseat (it, it->current.pos, 0);
5800 if (it->bidi_p)
5801 {
5802 it->bidi_it.new_paragraph = new_paragraph;
5803 it->bidi_it.first_elt = first_elt;
5804 it->bidi_it.separator_limit = paragraph_end;
5805 it->bidi_it.paragraph_dir = paragraph_dir;
5806 it->bidi_it.disp_pos = disp_pos;
5807 it->bidi_it.disp_prop = disp_prop;
5808 }
5780 } 5809 }
5781 } 5810 }
5782 else if (skipped_p) 5811 else if (skipped_p)
5783 reseat (it, it->current.pos, 0); 5812 {
5813 reseat (it, it->current.pos, 0);
5814 if (it->bidi_p)
5815 {
5816 it->bidi_it.new_paragraph = new_paragraph;
5817 it->bidi_it.first_elt = first_elt;
5818 it->bidi_it.separator_limit = paragraph_end;
5819 it->bidi_it.paragraph_dir = paragraph_dir;
5820 it->bidi_it.disp_pos = disp_pos;
5821 it->bidi_it.disp_prop = disp_prop;
5822 }
5823 }
5784 5824
5785 CHECK_IT (it); 5825 CHECK_IT (it);
5786} 5826}