aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-09-18 13:59:53 +0200
committerEli Zaretskii2010-09-18 13:59:53 +0200
commitbea4f10c834af9eee873e16913897bbf8065b52e (patch)
tree78a59c0d087cb1c5f0f1e27baeaa557656b286ad /src
parent88ed5ce8a653a870fd4f723ee550ffbb0f90626b (diff)
downloademacs-bea4f10c834af9eee873e16913897bbf8065b52e.tar.gz
emacs-bea4f10c834af9eee873e16913897bbf8065b52e.zip
Fix bug #7038 with cursor motion in paragraphs w/o strong characters.
xdisp.c (Fcurrent_bidi_paragraph_direction): Call bidi_paragraph_init with NO_DEFAULT_P non-zero. bidi.c (bidi_paragraph_init): Accept an additional argument NO_DEFAULT_P; all callers changed. If NO_DEFAULT_P is non-zero, search back until a paragraph with a strong directional character is found, and use that to determine paragraph's base direction. dispextern.h (bidi_paragraph_init): Update prototype.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/bidi.c114
-rw-r--r--src/dispextern.h2
-rw-r--r--src/xdisp.c16
4 files changed, 96 insertions, 48 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 66735cd5f4e..88030b7b4ce 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
12010-09-18 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (Fcurrent_bidi_paragraph_direction): Call
4 bidi_paragraph_init with NO_DEFAULT_P non-zero. (Bug#7038)
5
6 * bidi.c (bidi_paragraph_init): Accept an additional argument
7 NO_DEFAULT_P; all callers changed. If NO_DEFAULT_P is non-zero,
8 search back until a paragraph with a strong directional character
9 is found, and use that to determine paragraph's base direction.
10
11 * dispextern.h (bidi_paragraph_init): Update prototype.
12
12010-09-17 Eli Zaretskii <eliz@gnu.org> 132010-09-17 Eli Zaretskii <eliz@gnu.org>
2 14
3 * w32.c (_PROCESS_MEMORY_COUNTERS_EX): Don't define with versions 15 * w32.c (_PROCESS_MEMORY_COUNTERS_EX): Don't define with versions
diff --git a/src/bidi.c b/src/bidi.c
index a6d4d1b2506..224ed552a6d 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -583,18 +583,26 @@ bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
583 return pos_byte; 583 return pos_byte;
584} 584}
585 585
586/* Determine the direction, a.k.a. base embedding level, of the 586/* Determine the base direction, a.k.a. base embedding level, of the
587 paragraph we are about to iterate through. If DIR is either L2R or 587 paragraph we are about to iterate through. If DIR is either L2R or
588 R2L, just use that. Otherwise, determine the paragraph direction 588 R2L, just use that. Otherwise, determine the paragraph direction
589 from the first strong character of the paragraph. 589 from the first strong directional character of the paragraph.
590 590
591 Note that this gives the paragraph separator the same direction as 591 NO_DEFAULT_P non-nil means don't default to L2R if the paragraph
592 the preceding paragraph, even though Emacs generally views the 592 has no strong directional characters and both DIR and
593 separartor as not belonging to any paragraph. */ 593 bidi_it->paragraph_dir are NEUTRAL_DIR. In that case, search back
594 in the buffer until a paragraph is found with a strong character,
595 or until hitting BEGV. In the latter case, fall back to L2R. This
596 flag is used in current-bidi-paragraph-direction.
597
598 Note that this function gives the paragraph separator the same
599 direction as the preceding paragraph, even though Emacs generally
600 views the separartor as not belonging to any paragraph. */
594void 601void
595bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it) 602bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
596{ 603{
597 EMACS_INT bytepos = bidi_it->bytepos; 604 EMACS_INT bytepos = bidi_it->bytepos;
605 EMACS_INT pstartbyte;
598 606
599 /* Special case for an empty buffer. */ 607 /* Special case for an empty buffer. */
600 if (bytepos == BEGV_BYTE && bytepos == ZV_BYTE) 608 if (bytepos == BEGV_BYTE && bytepos == ZV_BYTE)
@@ -643,49 +651,75 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it)
643 651
644 /* We are either at the beginning of a paragraph or in the 652 /* We are either at the beginning of a paragraph or in the
645 middle of it. Find where this paragraph starts. */ 653 middle of it. Find where this paragraph starts. */
646 bytepos = bidi_find_paragraph_start (pos, bytepos); 654 pstartbyte = bidi_find_paragraph_start (pos, bytepos);
647
648 bidi_it->separator_limit = -1; 655 bidi_it->separator_limit = -1;
649 bidi_it->new_paragraph = 0; 656 bidi_it->new_paragraph = 0;
650 ch = FETCH_CHAR (bytepos); 657
651 ch_len = CHAR_BYTES (ch); 658 /* The following loop is run more than once only if NO_DEFAULT_P
652 pos = BYTE_TO_CHAR (bytepos); 659 is non-zero. */
653 type = bidi_get_type (ch, NEUTRAL_DIR); 660 do {
654 661 bytepos = pstartbyte;
655 for (pos++, bytepos += ch_len; 662 ch = FETCH_CHAR (bytepos);
656 /* NOTE: UAX#9 says to search only for L, AL, or R types of 663 ch_len = CHAR_BYTES (ch);
657 characters, and ignore RLE, RLO, LRE, and LRO. However, 664 pos = BYTE_TO_CHAR (bytepos);
658 I'm not sure it makes sense to omit those 4; should try 665 type = bidi_get_type (ch, NEUTRAL_DIR);
659 with and without that to see the effect. */ 666
660 (bidi_get_category (type) != STRONG) 667 for (pos++, bytepos += ch_len;
661 || (bidi_ignore_explicit_marks_for_paragraph_level 668 /* NOTE: UAX#9 says to search only for L, AL, or R types
662 && (type == RLE || type == RLO 669 of characters, and ignore RLE, RLO, LRE, and LRO.
663 || type == LRE || type == LRO)); 670 However, I'm not sure it makes sense to omit those 4;
664 type = bidi_get_type (ch, NEUTRAL_DIR)) 671 should try with and without that to see the effect. */
665 { 672 (bidi_get_category (type) != STRONG)
666 if (type == NEUTRAL_B && bidi_at_paragraph_end (pos, bytepos) >= -1) 673 || (bidi_ignore_explicit_marks_for_paragraph_level
667 break; 674 && (type == RLE || type == RLO
668 if (bytepos >= ZV_BYTE) 675 || type == LRE || type == LRO));
669 { 676 type = bidi_get_type (ch, NEUTRAL_DIR))
670 /* Pretend there's a paragraph separator at end of buffer. */ 677 {
671 type = NEUTRAL_B; 678 if (type == NEUTRAL_B && bidi_at_paragraph_end (pos, bytepos) >= -1)
672 break; 679 break;
673 } 680 if (bytepos >= ZV_BYTE)
674 FETCH_CHAR_ADVANCE (ch, pos, bytepos); 681 {
675 } 682 /* Pretend there's a paragraph separator at end of
676 if (type == STRONG_R || type == STRONG_AL) /* P3 */ 683 buffer. */
677 bidi_it->paragraph_dir = R2L; 684 type = NEUTRAL_B;
678 else if (type == STRONG_L) 685 break;
679 bidi_it->paragraph_dir = L2R; 686 }
687 FETCH_CHAR_ADVANCE (ch, pos, bytepos);
688 }
689 if (type == STRONG_R || type == STRONG_AL) /* P3 */
690 bidi_it->paragraph_dir = R2L;
691 else if (type == STRONG_L)
692 bidi_it->paragraph_dir = L2R;
693 if (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR)
694 {
695 /* If this paragraph is at BEGV, default to L2R. */
696 if (pstartbyte == BEGV_BYTE)
697 bidi_it->paragraph_dir = L2R; /* P3 and HL1 */
698 else
699 {
700 EMACS_INT prevpbyte = pstartbyte;
701 EMACS_INT p = BYTE_TO_CHAR (pstartbyte), pbyte = pstartbyte;
702
703 /* Find the beginning of the previous paragraph, if any. */
704 while (pbyte > BEGV_BYTE && prevpbyte >= pstartbyte)
705 {
706 p--;
707 pbyte = CHAR_TO_BYTE (p);
708 prevpbyte = bidi_find_paragraph_start (p, pbyte);
709 }
710 pstartbyte = prevpbyte;
711 }
712 }
713 } while (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR);
680 } 714 }
681 else 715 else
682 abort (); 716 abort ();
683 717
684 /* Contrary to UAX#9 clause P3, we only default the paragraph 718 /* Contrary to UAX#9 clause P3, we only default the paragraph
685 direction to L2R if we have no previous usable paragraph 719 direction to L2R if we have no previous usable paragraph
686 direction. */ 720 direction. This is allowed by the HL1 clause. */
687 if (bidi_it->paragraph_dir != L2R && bidi_it->paragraph_dir != R2L) 721 if (bidi_it->paragraph_dir != L2R && bidi_it->paragraph_dir != R2L)
688 bidi_it->paragraph_dir = L2R; /* P3 and ``higher protocols'' */ 722 bidi_it->paragraph_dir = L2R; /* P3 and HL1 ``higher-level protocols'' */
689 if (bidi_it->paragraph_dir == R2L) 723 if (bidi_it->paragraph_dir == R2L)
690 bidi_it->level_stack[0].level = 1; 724 bidi_it->level_stack[0].level = 1;
691 else 725 else
diff --git a/src/dispextern.h b/src/dispextern.h
index 5138958b6db..6fd92ba940d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2896,7 +2896,7 @@ extern EMACS_INT tool_bar_button_relief;
2896 2896
2897extern void bidi_init_it (EMACS_INT, EMACS_INT, struct bidi_it *); 2897extern void bidi_init_it (EMACS_INT, EMACS_INT, struct bidi_it *);
2898extern void bidi_move_to_visually_next (struct bidi_it *); 2898extern void bidi_move_to_visually_next (struct bidi_it *);
2899extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *); 2899extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int);
2900extern int bidi_mirror_char (int); 2900extern int bidi_mirror_char (int);
2901 2901
2902/* Defined in xdisp.c */ 2902/* Defined in xdisp.c */
diff --git a/src/xdisp.c b/src/xdisp.c
index 2ec271cdb6b..7b49eed4b2c 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3821,7 +3821,8 @@ handle_invisible_prop (struct it *it)
3821 not have a chance to do it, if we are going to 3821 not have a chance to do it, if we are going to
3822 skip any text at the beginning, which resets the 3822 skip any text at the beginning, which resets the
3823 FIRST_ELT flag. */ 3823 FIRST_ELT flag. */
3824 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 3824 bidi_paragraph_init (it->paragraph_embedding,
3825 &it->bidi_it, 0);
3825 } 3826 }
3826 do 3827 do
3827 { 3828 {
@@ -5143,7 +5144,7 @@ iterate_out_of_display_property (struct it *it)
5143 of a new paragraph, next_element_from_buffer may not have a 5144 of a new paragraph, next_element_from_buffer may not have a
5144 chance to do that. */ 5145 chance to do that. */
5145 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV) 5146 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5146 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 5147 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 0);
5147 /* prev_stop can be zero, so check against BEGV as well. */ 5148 /* prev_stop can be zero, so check against BEGV as well. */
5148 while (it->bidi_it.charpos >= BEGV 5149 while (it->bidi_it.charpos >= BEGV
5149 && it->prev_stop <= it->bidi_it.charpos 5150 && it->prev_stop <= it->bidi_it.charpos
@@ -6201,7 +6202,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
6201 /* If this is a new paragraph, determine its base 6202 /* If this is a new paragraph, determine its base
6202 direction (a.k.a. its base embedding level). */ 6203 direction (a.k.a. its base embedding level). */
6203 if (it->bidi_it.new_paragraph) 6204 if (it->bidi_it.new_paragraph)
6204 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 6205 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 0);
6205 bidi_move_to_visually_next (&it->bidi_it); 6206 bidi_move_to_visually_next (&it->bidi_it);
6206 IT_BYTEPOS (*it) = it->bidi_it.bytepos; 6207 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
6207 IT_CHARPOS (*it) = it->bidi_it.charpos; 6208 IT_CHARPOS (*it) = it->bidi_it.charpos;
@@ -6673,7 +6674,7 @@ next_element_from_buffer (struct it *it)
6673 { 6674 {
6674 /* If we are at the beginning of a line, we can produce the 6675 /* If we are at the beginning of a line, we can produce the
6675 next element right away. */ 6676 next element right away. */
6676 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 6677 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 0);
6677 bidi_move_to_visually_next (&it->bidi_it); 6678 bidi_move_to_visually_next (&it->bidi_it);
6678 } 6679 }
6679 else 6680 else
@@ -6687,7 +6688,7 @@ next_element_from_buffer (struct it *it)
6687 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it)); 6688 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
6688 it->bidi_it.charpos = IT_CHARPOS (*it); 6689 it->bidi_it.charpos = IT_CHARPOS (*it);
6689 it->bidi_it.bytepos = IT_BYTEPOS (*it); 6690 it->bidi_it.bytepos = IT_BYTEPOS (*it);
6690 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 6691 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 0);
6691 do 6692 do
6692 { 6693 {
6693 /* Now return to buffer position where we were asked to 6694 /* Now return to buffer position where we were asked to
@@ -6910,7 +6911,7 @@ next_element_from_composition (struct it *it)
6910 if (it->bidi_p) 6911 if (it->bidi_p)
6911 { 6912 {
6912 if (it->bidi_it.new_paragraph) 6913 if (it->bidi_it.new_paragraph)
6913 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it); 6914 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 0);
6914 /* Resync the bidi iterator with IT's new position. 6915 /* Resync the bidi iterator with IT's new position.
6915 FIXME: this doesn't support bidirectional text. */ 6916 FIXME: this doesn't support bidirectional text. */
6916 while (it->bidi_it.charpos < IT_CHARPOS (*it)) 6917 while (it->bidi_it.charpos < IT_CHARPOS (*it))
@@ -17992,8 +17993,9 @@ See also `bidi-paragraph-direction'. */)
17992 itb.bytepos = bytepos; 17993 itb.bytepos = bytepos;
17993 itb.first_elt = 1; 17994 itb.first_elt = 1;
17994 itb.separator_limit = -1; 17995 itb.separator_limit = -1;
17996 itb.paragraph_dir = NEUTRAL_DIR;
17995 17997
17996 bidi_paragraph_init (NEUTRAL_DIR, &itb); 17998 bidi_paragraph_init (NEUTRAL_DIR, &itb, 1);
17997 if (buf != current_buffer) 17999 if (buf != current_buffer)
17998 set_buffer_temp (old); 18000 set_buffer_temp (old);
17999 switch (itb.paragraph_dir) 18001 switch (itb.paragraph_dir)