aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-08-23 18:33:11 +0300
committerEli Zaretskii2014-08-23 18:33:11 +0300
commitd9abb2814d772b1efe89a9e665157d322d690d18 (patch)
tree5c65149c5d9594bf944b9c2069d43d308be8f126 /src
parent8ccc6fa95c75e22f26cf147d23df4a15d7a4bd7f (diff)
downloademacs-d9abb2814d772b1efe89a9e665157d322d690d18.tar.gz
emacs-d9abb2814d772b1efe89a9e665157d322d690d18.zip
Finished coding of explicit directional format characters.
Refactored part of bidi_paragraph_init into find_first_strong_char. Removed old kludges from bidi_it and the code. sor is now sos.
Diffstat (limited to 'src')
-rw-r--r--src/bidi.c277
-rw-r--r--src/dispextern.h4
2 files changed, 163 insertions, 118 deletions
diff --git a/src/bidi.c b/src/bidi.c
index 379350969ff..ca5b950d6d3 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -394,32 +394,24 @@ bidi_mirror_char (int c)
394 return c; 394 return c;
395} 395}
396 396
397/* Determine the start-of-run (sor) directional type given the two 397/* Determine the start-of-sequence (sos) directional type given the two
398 embedding levels on either side of the run boundary. Also, update 398 embedding levels on either side of the run boundary. Also, update
399 the saved info about previously seen characters, since that info is 399 the saved info about previously seen characters, since that info is
400 generally valid for a single level run. */ 400 generally valid for a single level run. */
401static void 401static void
402bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after) 402bidi_set_sos_type (struct bidi_it *bidi_it, int level_before, int level_after)
403{ 403{
404 int higher_level = (level_before > level_after ? level_before : level_after); 404 int higher_level = (level_before > level_after ? level_before : level_after);
405 405
406 /* The prev_was_pdf gork is required for when we have several PDFs 406 if (level_before < level_after)
407 in a row. In that case, we want to compute the sor type for the 407 /* FIXME: should the default sos direction be user selectable? */
408 next level run only once: when we see the first PDF. That's 408 bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R);
409 because the sor type depends only on the higher of the two levels
410 that we find on the two sides of the level boundary (see UAX#9,
411 clause X10), and so we don't need to know the final embedding
412 level to which we descend after processing all the PDFs. */
413 if (!bidi_it->prev_was_pdf || level_before < level_after)
414 /* FIXME: should the default sor direction be user selectable? */
415 bidi_it->sor = ((higher_level & 1) != 0 ? R2L : L2R);
416 if (level_before > level_after)
417 bidi_it->prev_was_pdf = 1;
418 409
410 /* FIXME: This needs to be reviewed!! */
419 bidi_it->prev.type = UNKNOWN_BT; 411 bidi_it->prev.type = UNKNOWN_BT;
420 bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 412 bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1
421 = bidi_it->last_strong.orig_type = UNKNOWN_BT; 413 = bidi_it->last_strong.orig_type = UNKNOWN_BT;
422 bidi_it->prev_for_neutral.type = (bidi_it->sor == R2L ? STRONG_R : STRONG_L); 414 bidi_it->prev_for_neutral.type = (bidi_it->sos == R2L ? STRONG_R : STRONG_L);
423 bidi_it->prev_for_neutral.charpos = bidi_it->charpos; 415 bidi_it->prev_for_neutral.charpos = bidi_it->charpos;
424 bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; 416 bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos;
425 bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 417 bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1
@@ -431,12 +423,13 @@ bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after)
431 current level to LEVEL and the current override status to OVERRIDE. */ 423 current level to LEVEL and the current override status to OVERRIDE. */
432static void 424static void
433bidi_push_embedding_level (struct bidi_it *bidi_it, 425bidi_push_embedding_level (struct bidi_it *bidi_it,
434 int level, bidi_dir_t override) 426 int level, bidi_dir_t override, bool isolate_status)
435{ 427{
436 bidi_it->stack_idx++; 428 bidi_it->stack_idx++;
437 eassert (bidi_it->stack_idx < BIDI_MAXDEPTH+2+1); 429 eassert (bidi_it->stack_idx < BIDI_MAXDEPTH+2+1);
438 bidi_it->level_stack[bidi_it->stack_idx].level = level; 430 bidi_it->level_stack[bidi_it->stack_idx].level = level;
439 bidi_it->level_stack[bidi_it->stack_idx].override = override; 431 bidi_it->level_stack[bidi_it->stack_idx].override = override;
432 bidi_it->level_stack[bidi_it->stack_idx].isolate_status = isolate_status;
440} 433}
441 434
442/* Pop the embedding level and directional override status from the 435/* Pop the embedding level and directional override status from the
@@ -722,7 +715,6 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
722 else 715 else
723 bidi_cache[idx].resolved_level = -1; 716 bidi_cache[idx].resolved_level = -1;
724 bidi_cache[idx].invalid_levels = bidi_it->invalid_levels; 717 bidi_cache[idx].invalid_levels = bidi_it->invalid_levels;
725 bidi_cache[idx].invalid_rl_levels = bidi_it->invalid_rl_levels;
726 bidi_cache[idx].next_for_neutral = bidi_it->next_for_neutral; 718 bidi_cache[idx].next_for_neutral = bidi_it->next_for_neutral;
727 bidi_cache[idx].next_for_ws = bidi_it->next_for_ws; 719 bidi_cache[idx].next_for_ws = bidi_it->next_for_ws;
728 bidi_cache[idx].ignore_bn_limit = bidi_it->ignore_bn_limit; 720 bidi_cache[idx].ignore_bn_limit = bidi_it->ignore_bn_limit;
@@ -962,7 +954,6 @@ static void
962bidi_set_paragraph_end (struct bidi_it *bidi_it) 954bidi_set_paragraph_end (struct bidi_it *bidi_it)
963{ 955{
964 bidi_it->invalid_levels = 0; 956 bidi_it->invalid_levels = 0;
965 bidi_it->invalid_rl_levels = -1;
966 bidi_it->stack_idx = 0; 957 bidi_it->stack_idx = 0;
967 bidi_it->resolved_level = bidi_it->level_stack[0].level; 958 bidi_it->resolved_level = bidi_it->level_stack[0].level;
968} 959}
@@ -987,7 +978,7 @@ bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p,
987 bidi_it->type = NEUTRAL_B; 978 bidi_it->type = NEUTRAL_B;
988 bidi_it->type_after_w1 = NEUTRAL_B; 979 bidi_it->type_after_w1 = NEUTRAL_B;
989 bidi_it->orig_type = NEUTRAL_B; 980 bidi_it->orig_type = NEUTRAL_B;
990 bidi_it->prev_was_pdf = 0; 981 /* FIXME: Review this!!! */
991 bidi_it->prev.type = bidi_it->prev.type_after_w1 982 bidi_it->prev.type = bidi_it->prev.type_after_w1
992 = bidi_it->prev.orig_type = UNKNOWN_BT; 983 = bidi_it->prev.orig_type = UNKNOWN_BT;
993 bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 984 bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1
@@ -1000,7 +991,7 @@ bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p,
1000 bidi_it->prev_for_neutral.type 991 bidi_it->prev_for_neutral.type
1001 = bidi_it->prev_for_neutral.type_after_w1 992 = bidi_it->prev_for_neutral.type_after_w1
1002 = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; 993 = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
1003 bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ 994 bidi_it->sos = L2R; /* FIXME: should it be user-selectable? */
1004 bidi_it->disp_pos = -1; /* invalid/unknown */ 995 bidi_it->disp_pos = -1; /* invalid/unknown */
1005 bidi_it->disp_prop = 0; 996 bidi_it->disp_prop = 0;
1006 /* We can only shrink the cache if we are at the bottom level of its 997 /* We can only shrink the cache if we are at the bottom level of its
@@ -1016,16 +1007,20 @@ static void
1016bidi_line_init (struct bidi_it *bidi_it) 1007bidi_line_init (struct bidi_it *bidi_it)
1017{ 1008{
1018 bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */ 1009 bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */
1010 bidi_it->stack_idx = 0;
1019 bidi_it->resolved_level = bidi_it->level_stack[0].level; 1011 bidi_it->resolved_level = bidi_it->level_stack[0].level;
1020 bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */ 1012 bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */
1013 bidi_it->level_stack[0].isolate_status = false; /* X1 */
1021 bidi_it->invalid_levels = 0; 1014 bidi_it->invalid_levels = 0;
1022 bidi_it->invalid_rl_levels = -1; 1015 bidi_it->isolate_level = 0; /* X1 */
1016 bidi_it->invalid_isolates = 0; /* X1 */
1023 /* Setting this to zero will force its recomputation the first time 1017 /* Setting this to zero will force its recomputation the first time
1024 we need it for W5. */ 1018 we need it for W5. */
1019 /* FIXME: Review this!!! */
1025 bidi_it->next_en_pos = 0; 1020 bidi_it->next_en_pos = 0;
1026 bidi_it->next_en_type = UNKNOWN_BT; 1021 bidi_it->next_en_type = UNKNOWN_BT;
1027 bidi_it->next_for_ws.type = UNKNOWN_BT; 1022 bidi_it->next_for_ws.type = UNKNOWN_BT;
1028 bidi_set_sor_type (bidi_it, 1023 bidi_set_sos_type (bidi_it,
1029 (bidi_it->paragraph_dir == R2L ? 1 : 0), 1024 (bidi_it->paragraph_dir == R2L ? 1 : 0),
1030 bidi_it->level_stack[0].level); /* X10 */ 1025 bidi_it->level_stack[0].level); /* X10 */
1031 1026
@@ -1403,6 +1398,50 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
1403 bidi_paragraph_init to less than 10 ms even on slow machines. */ 1398 bidi_paragraph_init to less than 10 ms even on slow machines. */
1404#define MAX_STRONG_CHAR_SEARCH 100000 1399#define MAX_STRONG_CHAR_SEARCH 100000
1405 1400
1401static bidi_type_t
1402find_first_strong_char (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t end,
1403 ptrdiff_t *disp_pos, int *disp_prop,
1404 struct bidi_string_data *string, struct window *w,
1405 bool string_p, bool frame_window_p,
1406 ptrdiff_t *ch_len, ptrdiff_t *nchars)
1407{
1408 ptrdiff_t pos1;
1409 bidi_type_t type;
1410 const unsigned char *s;
1411 int ch;
1412
1413 ch = bidi_fetch_char_skip_isolates (pos, bytepos, disp_pos, disp_prop, string,
1414 w, frame_window_p, ch_len, nchars);
1415 type = bidi_get_type (ch, NEUTRAL_DIR);
1416
1417 pos1 = pos;
1418 for (pos += *nchars, bytepos += *ch_len;
1419 bidi_get_category (type) != STRONG
1420 /* Stop when searched too far into an abnormally large
1421 paragraph full of weak or neutral characters. */
1422 && pos - pos1 < MAX_STRONG_CHAR_SEARCH;
1423 type = bidi_get_type (ch, NEUTRAL_DIR))
1424 {
1425 if (pos >= end)
1426 {
1427 /* Pretend there's a paragraph separator at end of
1428 buffer/string. */
1429 type = NEUTRAL_B;
1430 break;
1431 }
1432 if (!string_p
1433 && type == NEUTRAL_B
1434 && bidi_at_paragraph_end (pos, bytepos) >= -1)
1435 break;
1436 /* Fetch next character and advance to get past it. */
1437 ch = bidi_fetch_char_skip_isolates (pos, bytepos, disp_pos, disp_prop,
1438 string, w, frame_window_p,
1439 ch_len, nchars);
1440 pos += *nchars;
1441 bytepos += *ch_len;
1442 }
1443}
1444
1406/* Determine the base direction, a.k.a. base embedding level, of the 1445/* Determine the base direction, a.k.a. base embedding level, of the
1407 paragraph we are about to iterate through. If DIR is either L2R or 1446 paragraph we are about to iterate through. If DIR is either L2R or
1408 R2L, just use that. Otherwise, determine the paragraph direction 1447 R2L, just use that. Otherwise, determine the paragraph direction
@@ -1503,40 +1542,10 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
1503 bytepos = pstartbyte; 1542 bytepos = pstartbyte;
1504 if (!string_p) 1543 if (!string_p)
1505 pos = BYTE_TO_CHAR (bytepos); 1544 pos = BYTE_TO_CHAR (bytepos);
1506 ch = bidi_fetch_char_skip_isolates (pos, bytepos, &disp_pos, &disp_prop, 1545 type = find_first_strong_char (pos, bytepos, end, &disp_pos, &disp_prop,
1507 &bidi_it->string, bidi_it->w, 1546 &bidi_it->string, bidi_it->w,
1508 bidi_it->frame_window_p, &ch_len, 1547 string_p, bidi_it->frame_window_p,
1509 &nchars); 1548 &ch_len, &nchars);
1510 type = bidi_get_type (ch, NEUTRAL_DIR);
1511
1512 pos1 = pos;
1513 for (pos += nchars, bytepos += ch_len;
1514 bidi_get_category (type) != STRONG
1515 /* Stop when searched too far into an abnormally large
1516 paragraph full of weak or neutral characters. */
1517 && pos - pos1 < MAX_STRONG_CHAR_SEARCH;
1518 type = bidi_get_type (ch, NEUTRAL_DIR))
1519 {
1520 if (pos >= end)
1521 {
1522 /* Pretend there's a paragraph separator at end of
1523 buffer/string. */
1524 type = NEUTRAL_B;
1525 break;
1526 }
1527 if (!string_p
1528 && type == NEUTRAL_B
1529 && bidi_at_paragraph_end (pos, bytepos) >= -1)
1530 break;
1531 /* Fetch next character and advance to get past it. */
1532 ch = bidi_fetch_char_skip_isolates (pos, bytepos, &disp_pos,
1533 &disp_prop, &bidi_it->string,
1534 bidi_it->w,
1535 bidi_it->frame_window_p,
1536 &ch_len, &nchars);
1537 pos += nchars;
1538 bytepos += ch_len;
1539 }
1540 if (type == STRONG_R || type == STRONG_AL) /* P3 */ 1549 if (type == STRONG_R || type == STRONG_AL) /* P3 */
1541 bidi_it->paragraph_dir = R2L; 1550 bidi_it->paragraph_dir = R2L;
1542 else if (type == STRONG_L) 1551 else if (type == STRONG_L)
@@ -1614,7 +1623,10 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1614 int current_level; 1623 int current_level;
1615 int new_level; 1624 int new_level;
1616 bidi_dir_t override; 1625 bidi_dir_t override;
1626 bool isolate_status;
1617 bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring); 1627 bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring);
1628 ptrdiff_t ch_len, nchars, disp_pos, end;
1629 int disp_prop;
1618 1630
1619 /* If reseat()'ed, don't advance, so as to start iteration from the 1631 /* If reseat()'ed, don't advance, so as to start iteration from the
1620 position where we were reseated. bidi_it->bytepos can be less 1632 position where we were reseated. bidi_it->bytepos can be less
@@ -1661,7 +1673,9 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1661 1673
1662 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */ 1674 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */
1663 override = bidi_it->level_stack[bidi_it->stack_idx].override; 1675 override = bidi_it->level_stack[bidi_it->stack_idx].override;
1676 isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
1664 new_level = current_level; 1677 new_level = current_level;
1678 bidi_it->resolved_level = new_level;
1665 1679
1666 if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) 1680 if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV))
1667 { 1681 {
@@ -1692,9 +1706,6 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1692 bidi_it->orig_type = type; 1706 bidi_it->orig_type = type;
1693 bidi_check_type (bidi_it->orig_type); 1707 bidi_check_type (bidi_it->orig_type);
1694 1708
1695 if (type != PDF)
1696 bidi_it->prev_was_pdf = 0;
1697
1698 bidi_it->type_after_w1 = UNKNOWN_BT; 1709 bidi_it->type_after_w1 = UNKNOWN_BT;
1699 1710
1700 switch (type) 1711 switch (type)
@@ -1706,7 +1717,9 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1706 type = WEAK_BN; /* X9/Retaining */ 1717 type = WEAK_BN; /* X9/Retaining */
1707 if (bidi_it->ignore_bn_limit <= -1) 1718 if (bidi_it->ignore_bn_limit <= -1)
1708 { 1719 {
1709 if (current_level < BIDI_MAXDEPTH) 1720 if (current_level < BIDI_MAXDEPTH
1721 && bidi_it->invalid_levels == 0
1722 && bidi_it->invalid_isolates == 0)
1710 { 1723 {
1711 /* Compute the least odd embedding level greater than 1724 /* Compute the least odd embedding level greater than
1712 the current level. */ 1725 the current level. */
@@ -1715,17 +1728,13 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1715 override = NEUTRAL_DIR; 1728 override = NEUTRAL_DIR;
1716 else 1729 else
1717 override = R2L; 1730 override = R2L;
1718 if (current_level == BIDI_MAXDEPTH - 1) 1731 bidi_push_embedding_level (bidi_it, new_level, override, false);
1719 bidi_it->invalid_rl_levels = 0; 1732 bidi_it->resolved_level = new_level;
1720 bidi_push_embedding_level (bidi_it, new_level, override);
1721 } 1733 }
1722 else 1734 else
1723 { 1735 {
1724 bidi_it->invalid_levels++; 1736 if (bidi_it->invalid_isolates == 0)
1725 /* See the commentary about invalid_rl_levels below. */ 1737 bidi_it->invalid_levels++;
1726 if (bidi_it->invalid_rl_levels < 0)
1727 bidi_it->invalid_rl_levels = 0;
1728 bidi_it->invalid_rl_levels++;
1729 } 1738 }
1730 } 1739 }
1731 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ 1740 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
@@ -1740,7 +1749,9 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1740 type = WEAK_BN; /* X9/Retaining */ 1749 type = WEAK_BN; /* X9/Retaining */
1741 if (bidi_it->ignore_bn_limit <= -1) 1750 if (bidi_it->ignore_bn_limit <= -1)
1742 { 1751 {
1743 if (current_level < BIDI_MAXDEPTH - 1) 1752 if (current_level < BIDI_MAXDEPTH - 1
1753 && bidi_it->invalid_levels == 0
1754 && bidi_it->invalid_isolates == 0)
1744 { 1755 {
1745 /* Compute the least even embedding level greater than 1756 /* Compute the least even embedding level greater than
1746 the current level. */ 1757 the current level. */
@@ -1749,20 +1760,13 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1749 override = NEUTRAL_DIR; 1760 override = NEUTRAL_DIR;
1750 else 1761 else
1751 override = L2R; 1762 override = L2R;
1752 bidi_push_embedding_level (bidi_it, new_level, override); 1763 bidi_push_embedding_level (bidi_it, new_level, override, false);
1764 bidi_it->resolved_level = new_level;
1753 } 1765 }
1754 else 1766 else
1755 { 1767 {
1756 bidi_it->invalid_levels++; 1768 if (bidi_it->invalid_isolates == 0)
1757 /* invalid_rl_levels counts invalid levels encountered 1769 bidi_it->invalid_levels++;
1758 while the embedding level was already too high for
1759 LRE/LRO, but not for RLE/RLO. That is because
1760 there may be exactly one PDF which we should not
1761 ignore even though invalid_levels is non-zero.
1762 invalid_rl_levels helps to know what PDF is
1763 that. */
1764 if (bidi_it->invalid_rl_levels >= 0)
1765 bidi_it->invalid_rl_levels++;
1766 } 1770 }
1767 } 1771 }
1768 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ 1772 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
@@ -1770,32 +1774,80 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1770 && bidi_it->next_en_type == WEAK_EN)) 1774 && bidi_it->next_en_type == WEAK_EN))
1771 type = WEAK_EN; 1775 type = WEAK_EN;
1772 break; 1776 break;
1777 case FSI: /* X5c */
1778 bidi_it->type_after_w1 = type;
1779 end = string_p ? bidi_it->string.schars : ZV;
1780 disp_pos = bidi_it->disp_pos;
1781 disp_prop = bidi_it->disp_prop;
1782 type = find_first_strong_char (bidi_it->charpos, bidi_it->bytepos, end,
1783 &disp_pos, &disp_prop, &bidi_it->string,
1784 bidi_it->w, string_p, bidi_it->frame_window_p,
1785 &ch_len, &nchars);
1786 if (type != STRONG_R && type != STRONG_AL)
1787 goto fsi_as_lri;
1788 /* FALLTHROUGH */
1789 case RLI: /* X5a */
1790 bidi_it->type_after_w1 = type;
1791 bidi_check_type (bidi_it->type_after_w1);
1792 if (current_level < BIDI_MAXDEPTH
1793 && bidi_it->invalid_levels == 0
1794 && bidi_it->invalid_isolates == 0)
1795 {
1796 new_level = ((current_level + 1) & ~1) + 1;
1797 bidi_it->isolate_level++;
1798 bidi_push_embedding_level (bidi_it, new_level, NEUTRAL_DIR, true);
1799 }
1800 else
1801 bidi_it->invalid_isolates++;
1802 break;
1803 case LRI: /* X5b */
1804 fsi_as_lri:
1805 bidi_it->type_after_w1 = type;
1806 bidi_check_type (bidi_it->type_after_w1);
1807 if (current_level < BIDI_MAXDEPTH - 1
1808 && bidi_it->invalid_levels == 0
1809 && bidi_it->invalid_isolates == 0)
1810 {
1811 new_level = ((current_level + 2) & ~1);
1812 bidi_it->isolate_level++;
1813 bidi_push_embedding_level (bidi_it, new_level, NEUTRAL_DIR, true);
1814 }
1815 else
1816 bidi_it->invalid_isolates++;
1817 break;
1818 case PDI: /* X6a */
1819 if (bidi_it->invalid_isolates)
1820 bidi_it->invalid_isolates--;
1821 else if (bidi_it->isolate_level > 0)
1822 {
1823 bidi_it->invalid_levels = 0;
1824 while (!bidi_it->level_stack[bidi_it->stack_idx].isolate_status)
1825 bidi_pop_embedding_level (bidi_it);
1826 eassert (bidi_it->stack_idx > 0);
1827 new_level = bidi_pop_embedding_level (bidi_it);
1828 bidi_it->resolved_level = new_level;
1829 bidi_it->isolate_level--;
1830 }
1831 break;
1773 case PDF: /* X7 */ 1832 case PDF: /* X7 */
1774 bidi_it->type_after_w1 = type; 1833 bidi_it->type_after_w1 = type;
1775 bidi_check_type (bidi_it->type_after_w1); 1834 bidi_check_type (bidi_it->type_after_w1);
1776 type = WEAK_BN; /* X9/Retaining */ 1835 type = WEAK_BN; /* X9/Retaining */
1777 if (bidi_it->ignore_bn_limit <= -1) 1836 if (bidi_it->ignore_bn_limit <= -1)
1778 { 1837 {
1779 if (!bidi_it->invalid_rl_levels) 1838 if (!bidi_it->invalid_isolates)
1780 { 1839 {
1781 new_level = bidi_pop_embedding_level (bidi_it);
1782 bidi_it->invalid_rl_levels = -1;
1783 if (bidi_it->invalid_levels) 1840 if (bidi_it->invalid_levels)
1784 bidi_it->invalid_levels--; 1841 bidi_it->invalid_levels--;
1785 /* else nothing: UAX#9 says to ignore invalid PDFs */ 1842 else if (!isolate_status && bidi_it->stack_idx > 1)
1786 } 1843 new_level = bidi_pop_embedding_level (bidi_it);
1787 if (!bidi_it->invalid_levels)
1788 new_level = bidi_pop_embedding_level (bidi_it);
1789 else
1790 {
1791 bidi_it->invalid_levels--;
1792 bidi_it->invalid_rl_levels--;
1793 } 1844 }
1794 } 1845 }
1795 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */ 1846 else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
1796 || (bidi_it->next_en_pos > bidi_it->charpos 1847 || (bidi_it->next_en_pos > bidi_it->charpos
1797 && bidi_it->next_en_type == WEAK_EN)) 1848 && bidi_it->next_en_type == WEAK_EN))
1798 type = WEAK_EN; 1849 type = WEAK_EN;
1850 bidi_it->resolved_level = new_level;
1799 break; 1851 break;
1800 default: 1852 default:
1801 /* Nothing. */ 1853 /* Nothing. */
@@ -1805,7 +1857,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1805 bidi_it->type = type; 1857 bidi_it->type = type;
1806 bidi_check_type (bidi_it->type); 1858 bidi_check_type (bidi_it->type);
1807 1859
1808 return new_level; 1860 return bidi_it->resolved_level;
1809} 1861}
1810 1862
1811/* Given an iterator state in BIDI_IT, advance one character position 1863/* Given an iterator state in BIDI_IT, advance one character position
@@ -1816,7 +1868,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
1816static int 1868static int
1817bidi_resolve_explicit (struct bidi_it *bidi_it) 1869bidi_resolve_explicit (struct bidi_it *bidi_it)
1818{ 1870{
1819 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 1871 int prev_level = bidi_it->resolved_level;
1820 int new_level = bidi_resolve_explicit_1 (bidi_it); 1872 int new_level = bidi_resolve_explicit_1 (bidi_it);
1821 ptrdiff_t eob = bidi_it->string.s ? bidi_it->string.schars : ZV; 1873 ptrdiff_t eob = bidi_it->string.s ? bidi_it->string.schars : ZV;
1822 const unsigned char *s 1874 const unsigned char *s
@@ -1824,6 +1876,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1824 ? SDATA (bidi_it->string.lstring) 1876 ? SDATA (bidi_it->string.lstring)
1825 : bidi_it->string.s); 1877 : bidi_it->string.s);
1826 1878
1879 eassert (prev_level >= 0);
1827 if (prev_level < new_level 1880 if (prev_level < new_level
1828 && bidi_it->type == WEAK_BN 1881 && bidi_it->type == WEAK_BN
1829 && bidi_it->ignore_bn_limit == -1 /* only if not already known */ 1882 && bidi_it->ignore_bn_limit == -1 /* only if not already known */
@@ -1866,20 +1919,10 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1866 if (bidi_it->ignore_bn_limit > -1) 1919 if (bidi_it->ignore_bn_limit > -1)
1867 { 1920 {
1868 /* We pushed a level, but we shouldn't have. Undo that. */ 1921 /* We pushed a level, but we shouldn't have. Undo that. */
1869 if (!bidi_it->invalid_rl_levels)
1870 {
1871 new_level = bidi_pop_embedding_level (bidi_it);
1872 bidi_it->invalid_rl_levels = -1;
1873 if (bidi_it->invalid_levels)
1874 bidi_it->invalid_levels--;
1875 }
1876 if (!bidi_it->invalid_levels) 1922 if (!bidi_it->invalid_levels)
1877 new_level = bidi_pop_embedding_level (bidi_it); 1923 new_level = bidi_pop_embedding_level (bidi_it);
1878 else 1924 else
1879 { 1925 bidi_it->invalid_levels--;
1880 bidi_it->invalid_levels--;
1881 bidi_it->invalid_rl_levels--;
1882 }
1883 } 1926 }
1884 } 1927 }
1885 1928
@@ -1901,7 +1944,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1901{ 1944{
1902 bidi_type_t type; 1945 bidi_type_t type;
1903 bidi_dir_t override; 1946 bidi_dir_t override;
1904 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 1947 int prev_level = bidi_it->resolved_level;
1905 int new_level = bidi_resolve_explicit (bidi_it); 1948 int new_level = bidi_resolve_explicit (bidi_it);
1906 int next_char; 1949 int next_char;
1907 bidi_type_t type_of_next; 1950 bidi_type_t type_of_next;
@@ -1921,13 +1964,14 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1921 || type == PDF) 1964 || type == PDF)
1922 emacs_abort (); 1965 emacs_abort ();
1923 1966
1967 eassert (prev_level >= 0);
1924 if (new_level != prev_level 1968 if (new_level != prev_level
1925 || bidi_it->type == NEUTRAL_B) 1969 || bidi_it->type == NEUTRAL_B)
1926 { 1970 {
1927 /* We've got a new embedding level run, compute the directional 1971 /* We've got a new embedding level run, compute the directional
1928 type of sor and initialize per-run variables (UAX#9, clause 1972 type of sos and initialize per-run variables (UAX#9, clause
1929 X10). */ 1973 X10). */
1930 bidi_set_sor_type (bidi_it, prev_level, new_level); 1974 bidi_set_sos_type (bidi_it, prev_level, new_level);
1931 } 1975 }
1932 else if (type == NEUTRAL_S || type == NEUTRAL_WS 1976 else if (type == NEUTRAL_S || type == NEUTRAL_WS
1933 || type == WEAK_BN || type == STRONG_AL) 1977 || type == WEAK_BN || type == STRONG_AL)
@@ -1952,12 +1996,12 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
1952 This is why NSM gets the type_after_w1 of the previous 1996 This is why NSM gets the type_after_w1 of the previous
1953 character. */ 1997 character. */
1954 if (bidi_it->prev.type_after_w1 != UNKNOWN_BT 1998 if (bidi_it->prev.type_after_w1 != UNKNOWN_BT
1955 /* if type_after_w1 is NEUTRAL_B, this NSM is at sor */ 1999 /* if type_after_w1 is NEUTRAL_B, this NSM is at sos */
1956 && bidi_it->prev.type_after_w1 != NEUTRAL_B) 2000 && bidi_it->prev.type_after_w1 != NEUTRAL_B)
1957 type = bidi_it->prev.type_after_w1; 2001 type = bidi_it->prev.type_after_w1;
1958 else if (bidi_it->sor == R2L) 2002 else if (bidi_it->sos == R2L)
1959 type = STRONG_R; 2003 type = STRONG_R;
1960 else if (bidi_it->sor == L2R) 2004 else if (bidi_it->sos == L2R)
1961 type = STRONG_L; 2005 type = STRONG_L;
1962 else /* shouldn't happen! */ 2006 else /* shouldn't happen! */
1963 emacs_abort (); 2007 emacs_abort ();
@@ -2106,7 +2150,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2106 if (type == WEAK_EN) /* W7 */ 2150 if (type == WEAK_EN) /* W7 */
2107 { 2151 {
2108 if ((bidi_it->last_strong.type_after_w1 == STRONG_L) 2152 if ((bidi_it->last_strong.type_after_w1 == STRONG_L)
2109 || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sor == L2R)) 2153 || (bidi_it->last_strong.type == UNKNOWN_BT && bidi_it->sos == L2R))
2110 type = STRONG_L; 2154 type = STRONG_L;
2111 } 2155 }
2112 2156
@@ -2137,9 +2181,9 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
2137static bidi_type_t 2181static bidi_type_t
2138bidi_resolve_neutral (struct bidi_it *bidi_it) 2182bidi_resolve_neutral (struct bidi_it *bidi_it)
2139{ 2183{
2140 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2184 int prev_level = bidi_it->resolved_level;
2141 bidi_type_t type = bidi_resolve_weak (bidi_it); 2185 bidi_type_t type = bidi_resolve_weak (bidi_it);
2142 int current_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2186 int current_level = bidi_it->resolved_level;
2143 2187
2144 if (!(type == STRONG_R 2188 if (!(type == STRONG_R
2145 || type == STRONG_L 2189 || type == STRONG_L
@@ -2152,6 +2196,8 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2152 || type == NEUTRAL_ON)) 2196 || type == NEUTRAL_ON))
2153 emacs_abort (); 2197 emacs_abort ();
2154 2198
2199 eassert (prev_level >= 0);
2200 eassert (current_level >= 0);
2155 if ((type != NEUTRAL_B /* Don't risk entering the long loop below if 2201 if ((type != NEUTRAL_B /* Don't risk entering the long loop below if
2156 we are already at paragraph end. */ 2202 we are already at paragraph end. */
2157 && bidi_get_category (type) == NEUTRAL) 2203 && bidi_get_category (type) == NEUTRAL)
@@ -2260,7 +2306,7 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2260 case NEUTRAL_B: 2306 case NEUTRAL_B:
2261 /* Marched all the way to the end of this level run. 2307 /* Marched all the way to the end of this level run.
2262 We need to use the eor type, whose information is 2308 We need to use the eor type, whose information is
2263 stored by bidi_set_sor_type in the prev_for_neutral 2309 stored by bidi_set_sos_type in the prev_for_neutral
2264 member. */ 2310 member. */
2265 if (saved_it.type != WEAK_BN 2311 if (saved_it.type != WEAK_BN
2266 || bidi_get_category (bidi_it->prev.type_after_w1) == NEUTRAL) 2312 || bidi_get_category (bidi_it->prev.type_after_w1) == NEUTRAL)
@@ -2369,7 +2415,8 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
2369 state must be already cached, so there's no need to know the 2415 state must be already cached, so there's no need to know the
2370 embedding level of the previous character, since we will be 2416 embedding level of the previous character, since we will be
2371 returning to our caller shortly. */ 2417 returning to our caller shortly. */
2372 prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2418 prev_level = bidi_it->resolved_level;
2419 eassert (prev_level >= 0);
2373 } 2420 }
2374 next_for_neutral = bidi_it->next_for_neutral; 2421 next_for_neutral = bidi_it->next_for_neutral;
2375 2422
diff --git a/src/dispextern.h b/src/dispextern.h
index 9e6d27db1c1..a5b78a6f952 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1945,7 +1945,6 @@ struct bidi_it {
1945 char resolved_level; /* final resolved level of this character */ 1945 char resolved_level; /* final resolved level of this character */
1946 char isolate_level; /* count of isolate initiators unmatched by PDI */ 1946 char isolate_level; /* count of isolate initiators unmatched by PDI */
1947 ptrdiff_t invalid_levels; /* how many PDFs to ignore */ 1947 ptrdiff_t invalid_levels; /* how many PDFs to ignore */
1948 ptrdiff_t invalid_rl_levels; /* how many PDFs from RLE/RLO to ignore */
1949 ptrdiff_t invalid_isolates; /* how many PDIs to ignore */ 1948 ptrdiff_t invalid_isolates; /* how many PDIs to ignore */
1950 struct bidi_saved_info prev; /* info about previous character */ 1949 struct bidi_saved_info prev; /* info about previous character */
1951 struct bidi_saved_info last_strong; /* last-seen strong directional char */ 1950 struct bidi_saved_info last_strong; /* last-seen strong directional char */
@@ -1955,7 +1954,7 @@ struct bidi_it {
1955 ptrdiff_t next_en_pos; /* pos. of next char for determining ET type */ 1954 ptrdiff_t next_en_pos; /* pos. of next char for determining ET type */
1956 bidi_type_t next_en_type; /* type of char at next_en_pos */ 1955 bidi_type_t next_en_type; /* type of char at next_en_pos */
1957 ptrdiff_t ignore_bn_limit; /* position until which to ignore BNs */ 1956 ptrdiff_t ignore_bn_limit; /* position until which to ignore BNs */
1958 bidi_dir_t sor; /* direction of start-of-run in effect */ 1957 bidi_dir_t sos; /* direction of start-of-sequence in effect */
1959 int scan_dir; /* direction of text scan, 1: forw, -1: back */ 1958 int scan_dir; /* direction of text scan, 1: forw, -1: back */
1960 ptrdiff_t disp_pos; /* position of display string after ch */ 1959 ptrdiff_t disp_pos; /* position of display string after ch */
1961 int disp_prop; /* if non-zero, there really is a 1960 int disp_prop; /* if non-zero, there really is a
@@ -1970,7 +1969,6 @@ struct bidi_it {
1970 struct window *w; /* the window being displayed */ 1969 struct window *w; /* the window being displayed */
1971 bidi_dir_t paragraph_dir; /* current paragraph direction */ 1970 bidi_dir_t paragraph_dir; /* current paragraph direction */
1972 ptrdiff_t separator_limit; /* where paragraph separator should end */ 1971 ptrdiff_t separator_limit; /* where paragraph separator should end */
1973 bool_bf prev_was_pdf : 1; /* if true, previous char was PDF */
1974 bool_bf first_elt : 1; /* if true, examine current char first */ 1972 bool_bf first_elt : 1; /* if true, examine current char first */
1975 bool_bf new_paragraph : 1; /* if true, we expect a new paragraph */ 1973 bool_bf new_paragraph : 1; /* if true, we expect a new paragraph */
1976 bool_bf frame_window_p : 1; /* true if displaying on a GUI frame */ 1974 bool_bf frame_window_p : 1; /* true if displaying on a GUI frame */