diff options
| author | Eli Zaretskii | 2011-09-27 20:18:31 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-09-27 20:18:31 +0300 |
| commit | 88652fd58c34b494ef5e7139e317e0d8b0980200 (patch) | |
| tree | 25f5a0c60e5360c934a14b776f7b57deb4dd4b64 /src | |
| parent | aa97fd08e3b8d6a218b977ffba668f9cc63e0c17 (diff) | |
| download | emacs-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/ChangeLog | 8 | ||||
| -rw-r--r-- | src/xdisp.c | 99 |
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 @@ | |||
| 1 | 2011-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 | |||
| 1 | 2011-09-27 Andreas Schwab <schwab@linux-m68k.org> | 9 | 2011-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 |