aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-09-27 20:18:31 +0300
committerEli Zaretskii2011-09-27 20:18:31 +0300
commit88652fd58c34b494ef5e7139e317e0d8b0980200 (patch)
tree25f5a0c60e5360c934a14b776f7b57deb4dd4b64 /src
parentaa97fd08e3b8d6a218b977ffba668f9cc63e0c17 (diff)
downloademacs-88652fd58c34b494ef5e7139e317e0d8b0980200.tar.gz
emacs-88652fd58c34b494ef5e7139e317e0d8b0980200.zip
Fix bug #9610 with slow cursor motion in buffers with invisible text.
src/xdisp.c (handle_invisible_prop): If invisible text ends on a newline, reseat the iterator instead of bidi-iterating there one character at a time. (Bug#9610) (BUFFER_POS_REACHED_P, move_it_in_display_line_to): Bail when past TO_CHARPOS if the bidi iterator is at base embedding level.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/xdisp.c99
2 files changed, 75 insertions, 32 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 59169bdcf9f..dd2e7256476 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12011-09-27 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (handle_invisible_prop): If invisible text ends on a
4 newline, reseat the iterator instead of bidi-iterating there one
5 character at a time. (Bug#9610)
6 (BUFFER_POS_REACHED_P, move_it_in_display_line_to): Bail when past
7 TO_CHARPOS if the bidi iterator is at base embedding level.
8
12011-09-27 Andreas Schwab <schwab@linux-m68k.org> 92011-09-27 Andreas Schwab <schwab@linux-m68k.org>
2 10
3 * lread.c (readevalloop): Use correct code for NBSP. 11 * lread.c (readevalloop): Use correct code for NBSP.
diff --git a/src/xdisp.c b/src/xdisp.c
index a556236835c..75f266ff739 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -4056,40 +4056,67 @@ handle_invisible_prop (struct it *it)
4056 /* The position newpos is now either ZV or on visible text. */ 4056 /* The position newpos is now either ZV or on visible text. */
4057 if (it->bidi_p && newpos < ZV) 4057 if (it->bidi_p && newpos < ZV)
4058 { 4058 {
4059 /* With bidi iteration, the region of invisible text 4059 EMACS_INT bpos = CHAR_TO_BYTE (newpos);
4060 could start and/or end in the middle of a non-base 4060
4061 embedding level. Therefore, we need to skip 4061 if (FETCH_BYTE (bpos) == '\n'
4062 invisible text using the bidi iterator, starting at 4062 || (newpos > BEGV && FETCH_BYTE (bpos - 1) == '\n'))
4063 IT's current position, until we find ourselves
4064 outside the invisible text. Skipping invisible text
4065 _after_ bidi iteration avoids affecting the visual
4066 order of the displayed text when invisible properties
4067 are added or removed. */
4068 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
4069 { 4063 {
4070 /* If we were `reseat'ed to a new paragraph, 4064 /* If the invisible text ends on a newline or the
4071 determine the paragraph base direction. We need 4065 character after a newline, we can avoid the
4072 to do it now because next_element_from_buffer may 4066 costly, character by character, bidi iteration to
4073 not have a chance to do it, if we are going to 4067 newpos, and instead simply reseat the iterator
4074 skip any text at the beginning, which resets the 4068 there. That's because all bidi reordering
4075 FIRST_ELT flag. */ 4069 information is tossed at the newline. This is a
4076 bidi_paragraph_init (it->paragraph_embedding, 4070 big win for modes that hide complete lines, like
4077 &it->bidi_it, 1); 4071 Outline, Org, etc. (Implementation note: the
4072 call to reseat_1 is necessary, because it signals
4073 to the bidi iterator that it needs to reinit its
4074 internal information when the next element for
4075 display is requested. */
4076 struct text_pos tpos;
4077
4078 SET_TEXT_POS (tpos, newpos, bpos);
4079 reseat_1 (it, tpos, 0);
4078 } 4080 }
4079 do 4081 else /* Must use the slow method. */
4080 { 4082 {
4081 bidi_move_to_visually_next (&it->bidi_it); 4083 /* With bidi iteration, the region of invisible text
4084 could start and/or end in the middle of a
4085 non-base embedding level. Therefore, we need to
4086 skip invisible text using the bidi iterator,
4087 starting at IT's current position, until we find
4088 ourselves outside the invisible text. Skipping
4089 invisible text _after_ bidi iteration avoids
4090 affecting the visual order of the displayed text
4091 when invisible properties are added or
4092 removed. */
4093 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
4094 {
4095 /* If we were `reseat'ed to a new paragraph,
4096 determine the paragraph base direction. We
4097 need to do it now because
4098 next_element_from_buffer may not have a
4099 chance to do it, if we are going to skip any
4100 text at the beginning, which resets the
4101 FIRST_ELT flag. */
4102 bidi_paragraph_init (it->paragraph_embedding,
4103 &it->bidi_it, 1);
4104 }
4105 do
4106 {
4107 bidi_move_to_visually_next (&it->bidi_it);
4108 }
4109 while (it->stop_charpos <= it->bidi_it.charpos
4110 && it->bidi_it.charpos < newpos);
4111 IT_CHARPOS (*it) = it->bidi_it.charpos;
4112 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
4113 /* If we overstepped NEWPOS, record its position in
4114 the iterator, so that we skip invisible text if
4115 later the bidi iteration lands us in the
4116 invisible region again. */
4117 if (IT_CHARPOS (*it) >= newpos)
4118 it->prev_stop = newpos;
4082 } 4119 }
4083 while (it->stop_charpos <= it->bidi_it.charpos
4084 && it->bidi_it.charpos < newpos);
4085 IT_CHARPOS (*it) = it->bidi_it.charpos;
4086 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
4087 /* If we overstepped NEWPOS, record its position in the
4088 iterator, so that we skip invisible text if later the
4089 bidi iteration lands us in the invisible region
4090 again. */
4091 if (IT_CHARPOS (*it) >= newpos)
4092 it->prev_stop = newpos;
4093 } 4120 }
4094 else 4121 else
4095 { 4122 {
@@ -7880,7 +7907,9 @@ move_it_in_display_line_to (struct it *it,
7880 ((op & MOVE_TO_POS) != 0 \ 7907 ((op & MOVE_TO_POS) != 0 \
7881 && BUFFERP (it->object) \ 7908 && BUFFERP (it->object) \
7882 && (IT_CHARPOS (*it) == to_charpos \ 7909 && (IT_CHARPOS (*it) == to_charpos \
7883 || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos) \ 7910 || ((!it->bidi_p \
7911 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
7912 && IT_CHARPOS (*it) > to_charpos) \
7884 || (it->what == IT_COMPOSITION \ 7913 || (it->what == IT_COMPOSITION \
7885 && ((IT_CHARPOS (*it) > to_charpos \ 7914 && ((IT_CHARPOS (*it) > to_charpos \
7886 && to_charpos >= it->cmp_it.charpos) \ 7915 && to_charpos >= it->cmp_it.charpos) \
@@ -7912,7 +7941,13 @@ move_it_in_display_line_to (struct it *it,
7912 if ((op & MOVE_TO_POS) != 0 7941 if ((op & MOVE_TO_POS) != 0
7913 && BUFFERP (it->object) 7942 && BUFFERP (it->object)
7914 && it->method == GET_FROM_BUFFER 7943 && it->method == GET_FROM_BUFFER
7915 && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos) 7944 && (((!it->bidi_p
7945 /* When the iterator is at base embedding level, we
7946 are guaranteed that characters are delivered for
7947 display in strictly increasing order of their
7948 buffer positions. */
7949 || BIDI_AT_BASE_LEVEL (it->bidi_it))
7950 && IT_CHARPOS (*it) > to_charpos)
7916 || (it->bidi_p 7951 || (it->bidi_p
7917 && (prev_method == GET_FROM_IMAGE 7952 && (prev_method == GET_FROM_IMAGE
7918 || prev_method == GET_FROM_STRETCH 7953 || prev_method == GET_FROM_STRETCH