diff options
| author | Eli Zaretskii | 2013-12-16 20:09:36 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-12-16 20:09:36 +0200 |
| commit | 397e886f3470343dc6bb9bb14776c2de5254e0a9 (patch) | |
| tree | 9b60c43ee507fa10cf35a9d4384e43587cde96bc | |
| parent | 32779713e1a809d0e85efcc90677b7a029fbf69b (diff) | |
| download | emacs-397e886f3470343dc6bb9bb14776c2de5254e0a9.tar.gz emacs-397e886f3470343dc6bb9bb14776c2de5254e0a9.zip | |
A better fix for bug #16148 and related issues.
src/xdisp.c (Fmove_point_visually): Fix subtle bugs in the fallback
code, revealed in presence of R2L characters, character
compositions, and display vectors.
src/dispextern.h (struct composition_it): Correct a comment for the
'width' member.
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/dispextern.h | 5 | ||||
| -rw-r--r-- | src/xdisp.c | 81 |
3 files changed, 64 insertions, 31 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index f71e4dcbb80..ae154994da1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2013-12-16 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (Fmove_point_visually): Fix subtle bugs in the fallback | ||
| 4 | code, revealed in presence of R2L characters, character | ||
| 5 | compositions, and display vectors. A better fix for Bug#16148. | ||
| 6 | |||
| 7 | * dispextern.h (struct composition_it): Correct a comment for the | ||
| 8 | 'width' member. | ||
| 9 | |||
| 1 | 2013-12-16 Paul Eggert <eggert@cs.ucla.edu> | 10 | 2013-12-16 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 11 | ||
| 3 | * font.h (valid_font_driver) [!ENABLE_CHECKING]: Define a dummy. | 12 | * font.h (valid_font_driver) [!ENABLE_CHECKING]: Define a dummy. |
diff --git a/src/dispextern.h b/src/dispextern.h index d3ee2472dc6..06177af1e3d 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -2190,9 +2190,8 @@ struct composition_it | |||
| 2190 | int nchars, nbytes; | 2190 | int nchars, nbytes; |
| 2191 | /* Indices of the glyphs for the current grapheme cluster. */ | 2191 | /* Indices of the glyphs for the current grapheme cluster. */ |
| 2192 | int from, to; | 2192 | int from, to; |
| 2193 | /* Width of the current grapheme cluster in units of pixels on a | 2193 | /* Width of the current grapheme cluster in units of columns it will |
| 2194 | graphic display and in units of canonical characters on a | 2194 | occupy on display; see CHAR_WIDTH. */ |
| 2195 | terminal display. */ | ||
| 2196 | int width; | 2195 | int width; |
| 2197 | }; | 2196 | }; |
| 2198 | 2197 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index 450bf5c62dc..a0332a16503 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -20589,23 +20589,37 @@ Value is the new character position of point. */) | |||
| 20589 | SET_TEXT_POS (pt, PT, PT_BYTE); | 20589 | SET_TEXT_POS (pt, PT, PT_BYTE); |
| 20590 | start_display (&it, w, pt); | 20590 | start_display (&it, w, pt); |
| 20591 | 20591 | ||
| 20592 | if ((it.cmp_it.id < 0 | 20592 | if (it.cmp_it.id < 0 |
| 20593 | && it.method == GET_FROM_STRING | 20593 | && it.method == GET_FROM_STRING |
| 20594 | && it.area == TEXT_AREA | 20594 | && it.area == TEXT_AREA |
| 20595 | && it.string_from_display_prop_p | 20595 | && it.string_from_display_prop_p |
| 20596 | && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER)) | 20596 | && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER)) |
| 20597 | || it.method == GET_FROM_DISPLAY_VECTOR) | ||
| 20598 | overshoot_expected = true; | 20597 | overshoot_expected = true; |
| 20599 | 20598 | ||
| 20600 | /* Find the X coordinate of point. We start from the beginning | 20599 | /* Find the X coordinate of point. We start from the beginning |
| 20601 | of this or previous line to make sure we are before point in | 20600 | of this or previous line to make sure we are before point in |
| 20602 | the logical order (since the move_it_* functions can only | 20601 | the logical order (since the move_it_* functions can only |
| 20603 | move forward). */ | 20602 | move forward). */ |
| 20603 | reseat: | ||
| 20604 | reseat_at_previous_visible_line_start (&it); | 20604 | reseat_at_previous_visible_line_start (&it); |
| 20605 | it.current_x = it.hpos = it.current_y = it.vpos = 0; | 20605 | it.current_x = it.hpos = it.current_y = it.vpos = 0; |
| 20606 | if (IT_CHARPOS (it) != PT) | 20606 | if (IT_CHARPOS (it) != PT) |
| 20607 | move_it_to (&it, overshoot_expected ? PT - 1 : PT, | 20607 | { |
| 20608 | -1, -1, -1, MOVE_TO_POS); | 20608 | move_it_to (&it, overshoot_expected ? PT - 1 : PT, |
| 20609 | -1, -1, -1, MOVE_TO_POS); | ||
| 20610 | /* If we missed point because the character there is | ||
| 20611 | displayed out of a display vector that has more than one | ||
| 20612 | glyph, retry expecting overshoot. */ | ||
| 20613 | if (it.method == GET_FROM_DISPLAY_VECTOR | ||
| 20614 | && it.current.dpvec_index > 0 | ||
| 20615 | && !overshoot_expected) | ||
| 20616 | { | ||
| 20617 | overshoot_expected = true; | ||
| 20618 | goto reseat; | ||
| 20619 | } | ||
| 20620 | else if (IT_CHARPOS (it) != PT && !overshoot_expected) | ||
| 20621 | move_it_in_display_line (&it, PT, -1, MOVE_TO_POS); | ||
| 20622 | } | ||
| 20609 | pt_x = it.current_x; | 20623 | pt_x = it.current_x; |
| 20610 | pt_vpos = it.vpos; | 20624 | pt_vpos = it.vpos; |
| 20611 | if (dir > 0 || overshoot_expected) | 20625 | if (dir > 0 || overshoot_expected) |
| @@ -20634,9 +20648,9 @@ Value is the new character position of point. */) | |||
| 20634 | else if (pixel_width <= 0) | 20648 | else if (pixel_width <= 0) |
| 20635 | pixel_width = 1; | 20649 | pixel_width = 1; |
| 20636 | 20650 | ||
| 20637 | /* If there's a display string at point, we are actually at the | 20651 | /* If there's a display string (or something similar) at point, |
| 20638 | glyph to the left of point, so we need to correct the X | 20652 | we are actually at the glyph to the left of point, so we need |
| 20639 | coordinate. */ | 20653 | to correct the X coordinate. */ |
| 20640 | if (overshoot_expected) | 20654 | if (overshoot_expected) |
| 20641 | { | 20655 | { |
| 20642 | if (it.bidi_p) | 20656 | if (it.bidi_p) |
| @@ -20699,15 +20713,37 @@ Value is the new character position of point. */) | |||
| 20699 | character at point. */ | 20713 | character at point. */ |
| 20700 | if (FRAME_WINDOW_P (it.f) && dir < 0) | 20714 | if (FRAME_WINDOW_P (it.f) && dir < 0) |
| 20701 | { | 20715 | { |
| 20702 | struct text_pos new_pos = it.current.pos; | 20716 | struct text_pos new_pos; |
| 20703 | enum move_it_result rc = MOVE_X_REACHED; | 20717 | enum move_it_result rc = MOVE_X_REACHED; |
| 20704 | 20718 | ||
| 20719 | if (it.current_x == 0) | ||
| 20720 | get_next_display_element (&it); | ||
| 20721 | if (it.what == IT_COMPOSITION) | ||
| 20722 | { | ||
| 20723 | new_pos.charpos = it.cmp_it.charpos; | ||
| 20724 | new_pos.bytepos = -1; | ||
| 20725 | } | ||
| 20726 | else | ||
| 20727 | new_pos = it.current.pos; | ||
| 20728 | |||
| 20705 | while (it.current_x + it.pixel_width <= target_x | 20729 | while (it.current_x + it.pixel_width <= target_x |
| 20706 | && rc == MOVE_X_REACHED) | 20730 | && rc == MOVE_X_REACHED) |
| 20707 | { | 20731 | { |
| 20708 | int new_x = it.current_x + it.pixel_width; | 20732 | int new_x = it.current_x + it.pixel_width; |
| 20709 | 20733 | ||
| 20710 | new_pos = it.current.pos; | 20734 | /* For composed characters, we want the position of the |
| 20735 | first character in the grapheme cluster (usually, the | ||
| 20736 | composition's base character), whereas it.current | ||
| 20737 | might give us the position of the _last_ one, e.g. if | ||
| 20738 | the composition is rendered in reverse due to bidi | ||
| 20739 | reordering. */ | ||
| 20740 | if (it.what == IT_COMPOSITION) | ||
| 20741 | { | ||
| 20742 | new_pos.charpos = it.cmp_it.charpos; | ||
| 20743 | new_pos.bytepos = -1; | ||
| 20744 | } | ||
| 20745 | else | ||
| 20746 | new_pos = it.current.pos; | ||
| 20711 | if (new_x == it.current_x) | 20747 | if (new_x == it.current_x) |
| 20712 | new_x++; | 20748 | new_x++; |
| 20713 | rc = move_it_in_display_line_to (&it, ZV, new_x, | 20749 | rc = move_it_in_display_line_to (&it, ZV, new_x, |
| @@ -20715,21 +20751,10 @@ Value is the new character position of point. */) | |||
| 20715 | if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p) | 20751 | if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p) |
| 20716 | break; | 20752 | break; |
| 20717 | } | 20753 | } |
| 20718 | /* If we ended up on a composed character inside | 20754 | /* The previous position we saw in the loop is the one we |
| 20719 | bidi-reordered text (e.g., Hebrew text with diacritics), | 20755 | want. */ |
| 20720 | the iterator gives us the buffer position of the last (in | 20756 | if (new_pos.bytepos == -1) |
| 20721 | logical order) character of the composed grapheme cluster, | 20757 | new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos); |
| 20722 | which is not what we want. So we cheat: we compute the | ||
| 20723 | character position of the character that follows (in the | ||
| 20724 | logical order) the one where the above loop stopped. That | ||
| 20725 | character will appear on display to the left of point. */ | ||
| 20726 | if (it.bidi_p | ||
| 20727 | && it.bidi_it.scan_dir == -1 | ||
| 20728 | && new_pos.charpos - IT_CHARPOS (it) > 1) | ||
| 20729 | { | ||
| 20730 | new_pos.charpos = IT_CHARPOS (it) + 1; | ||
| 20731 | new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos); | ||
| 20732 | } | ||
| 20733 | it.current.pos = new_pos; | 20758 | it.current.pos = new_pos; |
| 20734 | } | 20759 | } |
| 20735 | else | 20760 | else |