aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2013-12-16 20:09:36 +0200
committerEli Zaretskii2013-12-16 20:09:36 +0200
commit397e886f3470343dc6bb9bb14776c2de5254e0a9 (patch)
tree9b60c43ee507fa10cf35a9d4384e43587cde96bc
parent32779713e1a809d0e85efcc90677b7a029fbf69b (diff)
downloademacs-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/ChangeLog9
-rw-r--r--src/dispextern.h5
-rw-r--r--src/xdisp.c81
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 @@
12013-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
12013-12-16 Paul Eggert <eggert@cs.ucla.edu> 102013-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