aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-06-13 21:35:20 +0300
committerEli Zaretskii2011-06-13 21:35:20 +0300
commit9f2573525cdb8fa7b2995a850380a4e267a544b7 (patch)
tree0c5deccc0e5449f4efdfe97188a00d763344914b /src
parentf23590ccc9bb0b6d335fb098b56ea07f4de6c91c (diff)
downloademacs-9f2573525cdb8fa7b2995a850380a4e267a544b7.tar.gz
emacs-9f2573525cdb8fa7b2995a850380a4e267a544b7.zip
Fix string handling to avoid data relocation gotcha.
Bugs in mode-line display still there. src/xdisp.c (compute_display_string_pos) (compute_display_string_end, reseat_to_string): Don't assume it->bidi_it.string.s always points to string.lstring's data. src/bidi.c (bidi_fetch_char, bidi_paragraph_init) (bidi_resolve_explicit_1, bidi_resolve_explicit) (bidi_resolve_weak, bidi_level_of_next_char): Don't assume string.s always points to string.lstring's data.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/bidi.c77
-rw-r--r--src/xdisp.c10
3 files changed, 73 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 071bcb23a03..5dc1c62266d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
12011-06-13 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (compute_display_string_pos)
4 (compute_display_string_end, reseat_to_string): Don't assume
5 it->bidi_it.string.s always points to string.lstring's data.
6
7 * bidi.c (bidi_fetch_char, bidi_paragraph_init)
8 (bidi_resolve_explicit_1, bidi_resolve_explicit)
9 (bidi_resolve_weak, bidi_level_of_next_char): Don't assume
10 string.s always points to string.lstring's data.
11
12011-06-11 Eli Zaretskii <eliz@gnu.org> 122011-06-11 Eli Zaretskii <eliz@gnu.org>
2 13
3 * xdisp.c (set_iterator_to_next): Advance string position 14 * xdisp.c (set_iterator_to_next): Advance string position
diff --git a/src/bidi.c b/src/bidi.c
index ffa2c771ed3..169a3cb01f6 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -615,15 +615,17 @@ bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s)
615 character position of the next display string, or -1 if not yet 615 character position of the next display string, or -1 if not yet
616 computed. When the next character is at or beyond that position, 616 computed. When the next character is at or beyond that position,
617 the function updates DISP_POS with the position of the next display 617 the function updates DISP_POS with the position of the next display
618 string. STRING->s is the string to iterate, or NULL if iterating over 618 string. STRING->s is the C string to iterate, or NULL if iterating
619 a buffer. */ 619 over a buffer or a Lisp string; in the latter case, STRING->lstring
620 is the Lisp string. */
620static inline int 621static inline int
621bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, 622bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
622 struct bidi_string_data *string, 623 struct bidi_string_data *string,
623 int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars) 624 int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars)
624{ 625{
625 int ch; 626 int ch;
626 EMACS_INT endpos = string->s ? string->schars : ZV; 627 EMACS_INT endpos =
628 (string->s || STRINGP (string->lstring)) ? string->schars : ZV;
627 struct text_pos pos; 629 struct text_pos pos;
628 630
629 /* If we got past the last known position of display string, compute 631 /* If we got past the last known position of display string, compute
@@ -658,6 +660,9 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
658 if (string->s) 660 if (string->s)
659 *ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos, 661 *ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos,
660 disp_end_pos); 662 disp_end_pos);
663 else if (STRINGP (string->lstring))
664 *ch_len = bidi_count_bytes (SDATA (string->lstring), *disp_pos,
665 bytepos, disp_end_pos);
661 else 666 else
662 *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos; 667 *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos;
663 } 668 }
@@ -670,6 +675,13 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
670 ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len); 675 ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len);
671 *ch_len = len; 676 *ch_len = len;
672 } 677 }
678 else if (STRINGP (string->lstring))
679 {
680 EMACS_INT len;
681
682 ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos, len);
683 *ch_len = len;
684 }
673 else 685 else
674 { 686 {
675 ch = FETCH_MULTIBYTE_CHAR (bytepos); 687 ch = FETCH_MULTIBYTE_CHAR (bytepos);
@@ -729,7 +741,7 @@ void
729bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) 741bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
730{ 742{
731 EMACS_INT bytepos = bidi_it->bytepos; 743 EMACS_INT bytepos = bidi_it->bytepos;
732 int string_p = bidi_it->string.s != NULL; 744 int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring);
733 EMACS_INT pstartbyte; 745 EMACS_INT pstartbyte;
734 /* Note that begbyte is a byte position, while end is a character 746 /* Note that begbyte is a byte position, while end is a character
735 position. Yes, this is ugly, but we are trying to avoid costly 747 position. Yes, this is ugly, but we are trying to avoid costly
@@ -760,6 +772,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
760 EMACS_INT ch_len, nchars; 772 EMACS_INT ch_len, nchars;
761 EMACS_INT pos, disp_pos = -1; 773 EMACS_INT pos, disp_pos = -1;
762 bidi_type_t type; 774 bidi_type_t type;
775 const unsigned char *s;
763 776
764 if (!bidi_initialized) 777 if (!bidi_initialized)
765 bidi_initialize (); 778 bidi_initialize ();
@@ -777,8 +790,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
777 we are potentially in a new paragraph that doesn't yet 790 we are potentially in a new paragraph that doesn't yet
778 exist. */ 791 exist. */
779 pos = bidi_it->charpos; 792 pos = bidi_it->charpos;
780 if (bytepos > begbyte 793 s = STRINGP (bidi_it->string.lstring) ?
781 && bidi_char_at_pos (bytepos, bidi_it->string.s) == '\n') 794 SDATA (bidi_it->string.lstring) : bidi_it->string.s;
795 if (bytepos > begbyte && bidi_char_at_pos (bytepos, s) == '\n')
782 { 796 {
783 bytepos++; 797 bytepos++;
784 pos++; 798 pos++;
@@ -1017,7 +1031,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1017 int current_level; 1031 int current_level;
1018 int new_level; 1032 int new_level;
1019 bidi_dir_t override; 1033 bidi_dir_t override;
1020 int string_p = bidi_it->string.s != NULL; 1034 int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring);
1021 1035
1022 /* If reseat()'ed, don't advance, so as to start iteration from the 1036 /* If reseat()'ed, don't advance, so as to start iteration from the
1023 position where we were reseated. bidi_it->bytepos can be less 1037 position where we were reseated. bidi_it->bytepos can be less
@@ -1028,10 +1042,13 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1028 bidi_it->first_elt = 0; 1042 bidi_it->first_elt = 0;
1029 if (string_p) 1043 if (string_p)
1030 { 1044 {
1045 const unsigned char *p =
1046 STRINGP (bidi_it->string.lstring)
1047 ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
1048
1031 if (bidi_it->charpos < 0) 1049 if (bidi_it->charpos < 0)
1032 bidi_it->charpos = 0; 1050 bidi_it->charpos = 0;
1033 bidi_it->bytepos = bidi_count_bytes (bidi_it->string.s, 0, 0, 1051 bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos);
1034 bidi_it->charpos);
1035 } 1052 }
1036 else 1053 else
1037 { 1054 {
@@ -1208,14 +1225,15 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1208 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 1225 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
1209 int new_level = bidi_resolve_explicit_1 (bidi_it); 1226 int new_level = bidi_resolve_explicit_1 (bidi_it);
1210 EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV; 1227 EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV;
1228 const unsigned char *s = STRINGP (bidi_it->string.lstring)
1229 ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
1211 1230
1212 if (prev_level < new_level 1231 if (prev_level < new_level
1213 && bidi_it->type == WEAK_BN 1232 && bidi_it->type == WEAK_BN
1214 && bidi_it->ignore_bn_limit == -1 /* only if not already known */ 1233 && bidi_it->ignore_bn_limit == -1 /* only if not already known */
1215 && bidi_it->charpos < eob /* not already at EOB */ 1234 && bidi_it->charpos < eob /* not already at EOB */
1216 && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos 1235 && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
1217 + bidi_it->ch_len, 1236 + bidi_it->ch_len, s)))
1218 bidi_it->string.s)))
1219 { 1237 {
1220 /* Avoid pushing and popping embedding levels if the level run 1238 /* Avoid pushing and popping embedding levels if the level run
1221 is empty, as this breaks level runs where it shouldn't. 1239 is empty, as this breaks level runs where it shouldn't.
@@ -1228,12 +1246,15 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1228 bidi_copy_it (&saved_it, bidi_it); 1246 bidi_copy_it (&saved_it, bidi_it);
1229 1247
1230 while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos 1248 while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
1231 + bidi_it->ch_len, 1249 + bidi_it->ch_len, s)))
1232 bidi_it->string.s)))
1233 { 1250 {
1234 /* This advances to the next character, skipping any 1251 /* This advances to the next character, skipping any
1235 characters covered by display strings. */ 1252 characters covered by display strings. */
1236 level = bidi_resolve_explicit_1 (bidi_it); 1253 level = bidi_resolve_explicit_1 (bidi_it);
1254 /* If string.lstring was relocated inside bidi_resolve_explicit_1,
1255 a pointer to its data is no longer valid. */
1256 if (STRINGP (bidi_it->string.lstring))
1257 s = SDATA (bidi_it->string.lstring);
1237 } 1258 }
1238 1259
1239 if (bidi_it->nchars <= 0) 1260 if (bidi_it->nchars <= 0)
@@ -1287,7 +1308,9 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1287 int next_char; 1308 int next_char;
1288 bidi_type_t type_of_next; 1309 bidi_type_t type_of_next;
1289 struct bidi_it saved_it; 1310 struct bidi_it saved_it;
1290 EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV; 1311 EMACS_INT eob =
1312 (STRINGP (bidi_it->string.lstring) || bidi_it->string.s)
1313 ? bidi_it->string.schars : ZV;
1291 1314
1292 type = bidi_it->type; 1315 type = bidi_it->type;
1293 override = bidi_it->level_stack[bidi_it->stack_idx].override; 1316 override = bidi_it->level_stack[bidi_it->stack_idx].override;
@@ -1354,11 +1377,14 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1354 && bidi_it->prev.orig_type == WEAK_EN) 1377 && bidi_it->prev.orig_type == WEAK_EN)
1355 || bidi_it->prev.type_after_w1 == WEAK_AN))) 1378 || bidi_it->prev.type_after_w1 == WEAK_AN)))
1356 { 1379 {
1380 const unsigned char *s =
1381 STRINGP (bidi_it->string.lstring)
1382 ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
1383
1357 next_char = 1384 next_char =
1358 bidi_it->charpos + bidi_it->nchars >= eob 1385 bidi_it->charpos + bidi_it->nchars >= eob
1359 ? BIDI_EOB 1386 ? BIDI_EOB
1360 : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, 1387 : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
1361 bidi_it->string.s);
1362 type_of_next = bidi_get_type (next_char, override); 1388 type_of_next = bidi_get_type (next_char, override);
1363 1389
1364 if (type_of_next == WEAK_BN 1390 if (type_of_next == WEAK_BN
@@ -1407,14 +1433,16 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1407 else /* W5: ET/BN with EN after it. */ 1433 else /* W5: ET/BN with EN after it. */
1408 { 1434 {
1409 EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars; 1435 EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars;
1436 const unsigned char *s =
1437 STRINGP (bidi_it->string.lstring)
1438 ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
1410 1439
1411 if (bidi_it->nchars <= 0) 1440 if (bidi_it->nchars <= 0)
1412 abort (); 1441 abort ();
1413 next_char = 1442 next_char =
1414 bidi_it->charpos + bidi_it->nchars >= eob 1443 bidi_it->charpos + bidi_it->nchars >= eob
1415 ? BIDI_EOB 1444 ? BIDI_EOB
1416 : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, 1445 : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
1417 bidi_it->string.s);
1418 type_of_next = bidi_get_type (next_char, override); 1446 type_of_next = bidi_get_type (next_char, override);
1419 1447
1420 if (type_of_next == WEAK_ET 1448 if (type_of_next == WEAK_ET
@@ -1636,8 +1664,12 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
1636 1664
1637 if (bidi_it->scan_dir == 1) 1665 if (bidi_it->scan_dir == 1)
1638 { 1666 {
1667 EMACS_INT eob =
1668 (bidi_it->string.s || STRINGP (bidi_it->string.lstring))
1669 ? bidi_it->string.schars : ZV;
1670
1639 /* There's no sense in trying to advance if we hit end of text. */ 1671 /* There's no sense in trying to advance if we hit end of text. */
1640 if (bidi_it->charpos >= (bidi_it->string.s ? bidi_it->string.schars : ZV)) 1672 if (bidi_it->charpos >= eob)
1641 return bidi_it->resolved_level; 1673 return bidi_it->resolved_level;
1642 1674
1643 /* Record the info about the previous character. */ 1675 /* Record the info about the previous character. */
@@ -1679,13 +1711,16 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
1679 UNKNOWN_BT. */ 1711 UNKNOWN_BT. */
1680 if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) 1712 if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
1681 { 1713 {
1714 int bob =
1715 (bidi_it->string.s || STRINGP (bidi_it->string.lstring)) ? 0 : 1;
1716
1682 if (bidi_it->scan_dir > 0) 1717 if (bidi_it->scan_dir > 0)
1683 { 1718 {
1684 if (bidi_it->nchars <= 0) 1719 if (bidi_it->nchars <= 0)
1685 abort (); 1720 abort ();
1686 next_char_pos = bidi_it->charpos + bidi_it->nchars; 1721 next_char_pos = bidi_it->charpos + bidi_it->nchars;
1687 } 1722 }
1688 else if (bidi_it->charpos >= (bidi_it->string.s ? 0 : 1)) 1723 else if (bidi_it->charpos >= bob)
1689 /* Implementation note: we allow next_char_pos to be as low as 1724 /* Implementation note: we allow next_char_pos to be as low as
1690 0 for buffers or -1 for strings, and that is okay because 1725 0 for buffers or -1 for strings, and that is okay because
1691 that's the "position" of the sentinel iterator state we 1726 that's the "position" of the sentinel iterator state we
@@ -1990,7 +2025,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
1990 separator limit to the end of the string prevents 2025 separator limit to the end of the string prevents
1991 bidi_paragraph_init from being called automatically on this 2026 bidi_paragraph_init from being called automatically on this
1992 string. */ 2027 string. */
1993 if (bidi_it->string.s) 2028 if (bidi_it->string.s || STRINGP (bidi_it->string.lstring))
1994 bidi_it->separator_limit = bidi_it->string.schars; 2029 bidi_it->separator_limit = bidi_it->string.schars;
1995 else if (bidi_it->bytepos < ZV_BYTE) 2030 else if (bidi_it->bytepos < ZV_BYTE)
1996 { 2031 {
diff --git a/src/xdisp.c b/src/xdisp.c
index 7494d5c5e48..c293dbeaade 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3117,7 +3117,8 @@ compute_display_string_pos (struct text_pos *position,
3117 struct bidi_string_data *string, int frame_window_p) 3117 struct bidi_string_data *string, int frame_window_p)
3118{ 3118{
3119 /* OBJECT = nil means current buffer. */ 3119 /* OBJECT = nil means current buffer. */
3120 Lisp_Object object = (string && string->s) ? string->lstring : Qnil; 3120 Lisp_Object object =
3121 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
3121 Lisp_Object pos, spec; 3122 Lisp_Object pos, spec;
3122 EMACS_INT eob = STRINGP (object) ? string->schars : ZV; 3123 EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
3123 EMACS_INT begb = STRINGP (object) ? 0 : BEGV; 3124 EMACS_INT begb = STRINGP (object) ? 0 : BEGV;
@@ -3178,11 +3179,12 @@ EMACS_INT
3178compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string) 3179compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
3179{ 3180{
3180 /* OBJECT = nil means current buffer. */ 3181 /* OBJECT = nil means current buffer. */
3181 Lisp_Object object = (string && string->s) ? string->lstring : Qnil; 3182 Lisp_Object object =
3183 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
3182 Lisp_Object pos = make_number (charpos); 3184 Lisp_Object pos = make_number (charpos);
3183 EMACS_INT eob = STRINGP (object) ? string->schars : ZV; 3185 EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
3184 3186
3185 if (charpos >= eob) 3187 if (charpos >= eob || (string->s && !STRINGP (object)))
3186 return eob; 3188 return eob;
3187 3189
3188 if (NILP (Fget_char_property (pos, Qdisplay, object))) 3190 if (NILP (Fget_char_property (pos, Qdisplay, object)))
@@ -5607,7 +5609,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
5607 { 5609 {
5608 it->paragraph_embedding = NEUTRAL_DIR; 5610 it->paragraph_embedding = NEUTRAL_DIR;
5609 it->bidi_it.string.lstring = string; 5611 it->bidi_it.string.lstring = string;
5610 it->bidi_it.string.s = SDATA (string); 5612 it->bidi_it.string.s = NULL;
5611 it->bidi_it.string.schars = it->end_charpos; 5613 it->bidi_it.string.schars = it->end_charpos;
5612 it->bidi_it.string.bufpos = 0; 5614 it->bidi_it.string.bufpos = 0;
5613 it->bidi_it.string.from_disp_str = 0; 5615 it->bidi_it.string.from_disp_str = 0;