aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-10-15 13:22:15 +0300
committerEli Zaretskii2014-10-15 13:22:15 +0300
commit4669732cc0923dacddbd31c67378746822a69673 (patch)
tree2261ad27ddea0c430d096b438afad1f8c1a60f86 /src
parente3060a0c4d2f418ac786775109d71e5843ccf42e (diff)
downloademacs-4669732cc0923dacddbd31c67378746822a69673.tar.gz
emacs-4669732cc0923dacddbd31c67378746822a69673.zip
Rewrote bracket resolution to match subtleties of Reference Implementation.
Diffstat (limited to 'src')
-rw-r--r--src/bidi.c253
-rw-r--r--src/dispextern.h3
2 files changed, 146 insertions, 110 deletions
diff --git a/src/bidi.c b/src/bidi.c
index c324914d2f8..b61fac1f03c 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -76,6 +76,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
76 bidi_fetch_char -- fetch next character 76 bidi_fetch_char -- fetch next character
77 bidi_resolve_explicit -- resolve explicit levels and directions 77 bidi_resolve_explicit -- resolve explicit levels and directions
78 bidi_resolve_weak -- resolve weak types 78 bidi_resolve_weak -- resolve weak types
79 bidi_resolve_brackets -- resolve "paired brackets" neutral types
79 bidi_resolve_neutral -- resolve neutral types 80 bidi_resolve_neutral -- resolve neutral types
80 bidi_level_of_next_char -- resolve implicit levels 81 bidi_level_of_next_char -- resolve implicit levels
81 82
@@ -788,7 +789,8 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved,
788 bidi_cache[idx].next_for_ws = bidi_it->next_for_ws; 789 bidi_cache[idx].next_for_ws = bidi_it->next_for_ws;
789 bidi_cache[idx].disp_pos = bidi_it->disp_pos; 790 bidi_cache[idx].disp_pos = bidi_it->disp_pos;
790 bidi_cache[idx].disp_prop = bidi_it->disp_prop; 791 bidi_cache[idx].disp_prop = bidi_it->disp_prop;
791 bidi_cache[idx].bracket_resolved = bidi_it->bracket_resolved; 792 bidi_cache[idx].bracket_pairing_pos = bidi_it->bracket_pairing_pos;
793 bidi_cache[idx].bracket_enclosed_type = bidi_it->bracket_enclosed_type;
792 } 794 }
793 795
794 bidi_cache_last_idx = idx; 796 bidi_cache_last_idx = idx;
@@ -1743,7 +1745,6 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1743 correction to N0, as implemented in bidi_resolve_weak/W1 1745 correction to N0, as implemented in bidi_resolve_weak/W1
1744 below. */ 1746 below. */
1745 if (bidi_it->type_after_wn == NEUTRAL_ON 1747 if (bidi_it->type_after_wn == NEUTRAL_ON
1746 && bidi_it->bracket_resolved
1747 && bidi_get_category (bidi_it->type) == STRONG 1748 && bidi_get_category (bidi_it->type) == STRONG
1748 && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE) 1749 && bidi_paired_bracket_type (bidi_it->ch) == BIDI_BRACKET_CLOSE)
1749 bidi_remember_char (&bidi_it->prev, bidi_it, 1); 1750 bidi_remember_char (&bidi_it->prev, bidi_it, 1);
@@ -1769,8 +1770,9 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1769 bidi_it->next_en_type = UNKNOWN_BT; 1770 bidi_it->next_en_type = UNKNOWN_BT;
1770 } 1771 }
1771 1772
1772 /* Reset the bracket_resolved flag. */ 1773 /* Reset the bracket resolution info. */
1773 bidi_it->bracket_resolved = 0; 1774 bidi_it->bracket_pairing_pos = -1;
1775 bidi_it->bracket_enclosed_type = UNKNOWN_BT;
1774 1776
1775 /* If reseat()'ed, don't advance, so as to start iteration from the 1777 /* If reseat()'ed, don't advance, so as to start iteration from the
1776 position where we were reseated. bidi_it->bytepos can be less 1778 position where we were reseated. bidi_it->bytepos can be less
@@ -2324,18 +2326,16 @@ bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
2324 2326
2325#define FLAG_EMBEDDING_INSIDE 1 2327#define FLAG_EMBEDDING_INSIDE 1
2326#define FLAG_OPPOSITE_INSIDE 2 2328#define FLAG_OPPOSITE_INSIDE 2
2327#define FLAG_EMBEDDING_OUTSIDE 4
2328#define FLAG_OPPOSITE_OUTSIDE 8
2329 2329
2330/* A data type used in the stack maintained by 2330/* A data type used in the stack maintained by
2331 bidi_resolve_bracket_pairs below. */ 2331 bidi_find_bracket_pairs below. */
2332typedef struct bpa_stack_entry { 2332typedef struct bpa_stack_entry {
2333 int close_bracket_char; 2333 int close_bracket_char;
2334 int open_bracket_idx; 2334 int open_bracket_idx;
2335#ifdef ENABLE_CHECKING 2335#ifdef ENABLE_CHECKING
2336 ptrdiff_t open_bracket_pos; 2336 ptrdiff_t open_bracket_pos;
2337#endif 2337#endif
2338 unsigned flags : 4; 2338 unsigned flags : 2;
2339} bpa_stack_entry; 2339} bpa_stack_entry;
2340 2340
2341/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the 2341/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the
@@ -2349,7 +2349,7 @@ typedef struct bpa_stack_entry {
2349# define STORE_BRACKET_CHARPOS /* nothing */ 2349# define STORE_BRACKET_CHARPOS /* nothing */
2350#endif 2350#endif
2351 2351
2352#define PUSH_BPA_STACK(EMBEDDING_LEVEL, LAST_STRONG) \ 2352#define PUSH_BPA_STACK \
2353 do { \ 2353 do { \
2354 bpa_sp++; \ 2354 bpa_sp++; \
2355 if (bpa_sp >= MAX_BPA_STACK) \ 2355 if (bpa_sp >= MAX_BPA_STACK) \
@@ -2360,24 +2360,22 @@ typedef struct bpa_stack_entry {
2360 bpa_stack[bpa_sp].close_bracket_char = bidi_mirror_char (bidi_it->ch); \ 2360 bpa_stack[bpa_sp].close_bracket_char = bidi_mirror_char (bidi_it->ch); \
2361 bpa_stack[bpa_sp].open_bracket_idx = bidi_cache_last_idx; \ 2361 bpa_stack[bpa_sp].open_bracket_idx = bidi_cache_last_idx; \
2362 STORE_BRACKET_CHARPOS; \ 2362 STORE_BRACKET_CHARPOS; \
2363 if (((EMBEDDING_LEVEL) & 1) == 0) \
2364 bpa_stack[bpa_sp].flags = ((LAST_STRONG) == STRONG_L \
2365 ? FLAG_EMBEDDING_OUTSIDE \
2366 : FLAG_OPPOSITE_OUTSIDE); \
2367 else \
2368 bpa_stack[bpa_sp].flags = ((LAST_STRONG) == STRONG_L \
2369 ? FLAG_OPPOSITE_OUTSIDE \
2370 : FLAG_EMBEDDING_OUTSIDE); \
2371 } while (0) 2363 } while (0)
2372 2364
2373 2365
2374/* This function implements BPA, the Bidi Parenthesis Algorithm, 2366/* This function implements BPA, the Bidi Parenthesis Algorithm,
2375 described in BD16 and N0 of UAX#9. */ 2367 described in BD16 and N0 of UAX#9. It finds all the bracket pairs
2376static bidi_type_t 2368 in the current isolating sequence, and records the enclosed type
2377bidi_resolve_bracket_pairs (struct bidi_it *bidi_it) 2369 and the position of the matching bracket in the cache. It returns
2370 non-zero if called with the iterator on the opening bracket which
2371 has a matching closing bracket in the current isolating sequence,
2372 zero otherwise. */
2373static bool
2374bidi_find_bracket_pairs (struct bidi_it *bidi_it)
2378{ 2375{
2379 bidi_bracket_type_t btype; 2376 bidi_bracket_type_t btype;
2380 bidi_type_t type = bidi_it->type; 2377 bidi_type_t type = bidi_it->type;
2378 bool retval = false;
2381 2379
2382 /* When scanning backwards, we don't expect any unresolved bidi 2380 /* When scanning backwards, we don't expect any unresolved bidi
2383 bracket characters. */ 2381 bracket characters. */
@@ -2390,13 +2388,12 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2390 bpa_stack_entry bpa_stack[MAX_BPA_STACK]; 2388 bpa_stack_entry bpa_stack[MAX_BPA_STACK];
2391 int bpa_sp = -1; 2389 int bpa_sp = -1;
2392 struct bidi_it saved_it; 2390 struct bidi_it saved_it;
2393 bidi_type_t last_strong;
2394 int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2391 int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2392 bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L;
2395 struct bidi_it tem_it; 2393 struct bidi_it tem_it;
2396 2394
2397 eassert (MAX_BPA_STACK >= 100); 2395 eassert (MAX_BPA_STACK >= 100);
2398 bidi_copy_it (&saved_it, bidi_it); 2396 bidi_copy_it (&saved_it, bidi_it);
2399 last_strong = bidi_it->prev_for_neutral.type;
2400 /* bidi_cache_iterator_state refuses to cache on backward scans, 2397 /* bidi_cache_iterator_state refuses to cache on backward scans,
2401 and bidi_cache_fetch_state doesn't bring scan_dir from the 2398 and bidi_cache_fetch_state doesn't bring scan_dir from the
2402 cache, so we must initialize this explicitly. */ 2399 cache, so we must initialize this explicitly. */
@@ -2409,7 +2406,7 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2409 2406
2410 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); 2407 bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0);
2411 if (btype == BIDI_BRACKET_OPEN) 2408 if (btype == BIDI_BRACKET_OPEN)
2412 PUSH_BPA_STACK (embedding_level, last_strong); 2409 PUSH_BPA_STACK;
2413 else if (btype == BIDI_BRACKET_CLOSE) 2410 else if (btype == BIDI_BRACKET_CLOSE)
2414 { 2411 {
2415 int sp = bpa_sp; 2412 int sp = bpa_sp;
@@ -2420,62 +2417,49 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2420 sp--; 2417 sp--;
2421 if (sp >= 0) 2418 if (sp >= 0)
2422 { 2419 {
2423 /* Resolve the bracket type according to N0. */
2424 if (bpa_stack[sp].flags & FLAG_EMBEDDING_INSIDE) /* N0b */
2425 type = ((embedding_level & 1) ? STRONG_R : STRONG_L);
2426 else if ((bpa_stack[sp].flags /* N0c1 */
2427 & (FLAG_OPPOSITE_INSIDE | FLAG_OPPOSITE_OUTSIDE))
2428 == (FLAG_OPPOSITE_INSIDE | FLAG_OPPOSITE_OUTSIDE))
2429 type = ((embedding_level & 1) ? STRONG_L : STRONG_R);
2430 else if (bpa_stack[sp].flags & FLAG_OPPOSITE_INSIDE) /*N0c2*/
2431 type = ((embedding_level & 1) ? STRONG_R : STRONG_L);
2432
2433 /* Update the type of the closing bracket. */
2434 bidi_it->type = type;
2435 /* Update and cache the corresponding opening bracket. */ 2420 /* Update and cache the corresponding opening bracket. */
2436 bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx, 2421 bidi_cache_fetch_state (bpa_stack[sp].open_bracket_idx,
2437 &tem_it); 2422 &tem_it);
2438#ifdef ENABLE_CHECKING 2423#ifdef ENABLE_CHECKING
2439 eassert (bpa_stack[sp].open_bracket_pos == tem_it.charpos); 2424 eassert (bpa_stack[sp].open_bracket_pos == tem_it.charpos);
2440#endif 2425#endif
2441 tem_it.type = type; 2426 /* Determine the enclosed type for this bracket
2442 tem_it.bracket_resolved = 1; 2427 pair's type resolution according to N0. */
2443 bidi_cache_iterator_state (&tem_it, 0, 0); 2428 if (bpa_stack[sp].flags & FLAG_EMBEDDING_INSIDE)
2444 /* Mark as resolved the unmatched brackets we are 2429 tem_it.bracket_enclosed_type = embedding_type; /* N0b */
2445 about to pop from the stack. */ 2430 else if (bpa_stack[sp].flags & FLAG_OPPOSITE_INSIDE)
2446 while (bpa_sp > sp) 2431 tem_it.bracket_enclosed_type /* N0c */
2447 { 2432 = (embedding_type == STRONG_L ? STRONG_R : STRONG_L);
2448 bidi_cache_fetch_state 2433 else /* N0d */
2449 (bpa_stack[bpa_sp].open_bracket_idx, &tem_it); 2434 tem_it.bracket_enclosed_type = UNKNOWN_BT;
2450#ifdef ENABLE_CHECKING 2435
2451 eassert (bpa_stack[bpa_sp].open_bracket_pos 2436 /* Record the position of the matching closing
2452 == tem_it.charpos); 2437 bracket, and update the cache. */
2453#endif 2438 tem_it.bracket_pairing_pos = bidi_it->charpos;
2454 tem_it.bracket_resolved = 1; 2439 bidi_cache_iterator_state (&tem_it, 0, 1);
2455 bidi_cache_iterator_state (&tem_it, 0, 0); 2440
2456 bpa_sp--;
2457 }
2458 /* Pop the BPA stack. */ 2441 /* Pop the BPA stack. */
2459 bpa_sp = sp - 1; 2442 bpa_sp = sp - 1;
2460 } 2443 }
2461 bidi_it->bracket_resolved = 1;
2462 bidi_cache_iterator_state (bidi_it, 0, 0);
2463 if (bpa_sp < 0) 2444 if (bpa_sp < 0)
2464 break; 2445 {
2446 retval = true;
2447 break;
2448 }
2465 } 2449 }
2466 else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL) 2450 else if (bidi_get_category (bidi_it->type_after_wn) != NEUTRAL)
2467 { 2451 {
2468 unsigned flag; 2452 unsigned flag;
2469 int sp; 2453 int sp;
2470 2454
2471 /* Update the "inside" flags of all the slots on the stack. */ 2455 /* Whenever we see a strong type, update the flags of
2456 all the slots on the stack. */
2472 switch (bidi_it->type) 2457 switch (bidi_it->type)
2473 { 2458 {
2474 case STRONG_L: 2459 case STRONG_L:
2475 flag = ((embedding_level & 1) == 0 2460 flag = ((embedding_level & 1) == 0
2476 ? FLAG_EMBEDDING_INSIDE 2461 ? FLAG_EMBEDDING_INSIDE
2477 : FLAG_OPPOSITE_INSIDE); 2462 : FLAG_OPPOSITE_INSIDE);
2478 last_strong = STRONG_L;
2479 break; 2463 break;
2480 case STRONG_R: 2464 case STRONG_R:
2481 case WEAK_EN: 2465 case WEAK_EN:
@@ -2483,7 +2467,6 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2483 flag = ((embedding_level & 1) == 1 2467 flag = ((embedding_level & 1) == 1
2484 ? FLAG_EMBEDDING_INSIDE 2468 ? FLAG_EMBEDDING_INSIDE
2485 : FLAG_OPPOSITE_INSIDE); 2469 : FLAG_OPPOSITE_INSIDE);
2486 last_strong = STRONG_R;
2487 break; 2470 break;
2488 default: 2471 default:
2489 break; 2472 break;
@@ -2514,23 +2497,8 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2514 bpa_give_up: 2497 bpa_give_up:
2515 /* We've marched all the way to the end of this 2498 /* We've marched all the way to the end of this
2516 isolating run sequence, and didn't find matching 2499 isolating run sequence, and didn't find matching
2517 closing brackets for some opening brackets. Unwind 2500 closing brackets for some opening brackets. Leave
2518 whatever is left on the BPA stack, and mark each 2501 their type unchanged. */
2519 bracket there as BPA-resolved, leaving their type
2520 unchanged. */
2521 while (bpa_sp >= 0)
2522 {
2523 bidi_cache_fetch_state (bpa_stack[bpa_sp].open_bracket_idx,
2524 &tem_it);
2525#ifdef ENABLE_CHECKING
2526 eassert (bpa_stack[bpa_sp].open_bracket_pos
2527 == tem_it.charpos);
2528#endif
2529 tem_it.bracket_resolved = 1;
2530 bidi_cache_iterator_state (&tem_it, 0, 0);
2531 bpa_sp--;
2532 }
2533 type = saved_it.type;
2534 break; 2502 break;
2535 } 2503 }
2536 if (bidi_it->type_after_wn == NEUTRAL_ON) /* Unicode 8.0 correction */ 2504 if (bidi_it->type_after_wn == NEUTRAL_ON) /* Unicode 8.0 correction */
@@ -2538,31 +2506,117 @@ bidi_resolve_bracket_pairs (struct bidi_it *bidi_it)
2538 else 2506 else
2539 btype = BIDI_BRACKET_NONE; 2507 btype = BIDI_BRACKET_NONE;
2540 } 2508 }
2541 bidi_check_type (type);
2542 2509
2543 bidi_copy_it (bidi_it, &saved_it); 2510 /* Restore bidi_it from the cache, which should have the bracket
2544 bidi_it->type = type; 2511 resolution members set as determined by the above loop. */
2545 bidi_it->bracket_resolved = 1; 2512 type = bidi_cache_find (saved_it.charpos, 1, bidi_it);
2513 eassert (type == NEUTRAL_ON);
2546 } 2514 }
2547 2515
2548 return type; 2516 return retval;
2549} 2517}
2550 2518
2551static bidi_type_t 2519static bidi_type_t
2552bidi_resolve_brackets (struct bidi_it *bidi_it) 2520bidi_resolve_brackets (struct bidi_it *bidi_it)
2553{ 2521{
2554 bidi_type_t type = bidi_resolve_weak (bidi_it); 2522 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2555 int ch = bidi_it->ch; 2523 bool resolve_bracket = false;
2524 bidi_type_t type = UNKNOWN_BT;
2525 int ch;
2526 struct bidi_saved_info tem_info;
2527
2528 bidi_remember_char (&tem_info, bidi_it, 1);
2529 if (!bidi_it->first_elt)
2530 {
2531 type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 1, bidi_it);
2532 ch = bidi_it->ch;
2533 }
2534 if (type == UNKNOWN_BT)
2535 {
2536 type = bidi_resolve_weak (bidi_it);
2537 if (type == NEUTRAL_ON && bidi_find_bracket_pairs (bidi_it))
2538 resolve_bracket = true;
2539 }
2540 else
2541 {
2542 if (type == NEUTRAL_ON
2543 && bidi_paired_bracket_type (ch) == BIDI_BRACKET_OPEN)
2544 {
2545 if (bidi_it->level_stack[bidi_it->stack_idx].level == prev_level)
2546 {
2547 if (bidi_it->bracket_pairing_pos > 0)
2548 {
2549 /* A cached opening bracket that wasn't completely
2550 resolved yet. */
2551 resolve_bracket = true;
2552 }
2553 }
2554 else
2555 {
2556 /* Higher levels were not BPA-resolved yet, even if
2557 cached by bidi_find_bracket_pairs. Lower levels were
2558 probably processed by bidi_find_bracket_pairs, but we
2559 have no easy way of retaining the prev_for_neutral
2560 from the previous level run of the isolating
2561 sequence. Force application of BPA now. */
2562 if (bidi_find_bracket_pairs (bidi_it))
2563 resolve_bracket = true;
2564 }
2565 }
2566 /* Keep track of the prev_for_neutral type, needed for resolving
2567 brackets below and for resolving neutrals in bidi_resolve_neutral. */
2568 if (bidi_it->level_stack[bidi_it->stack_idx].level == prev_level
2569 && (tem_info.type == STRONG_L || tem_info.type == STRONG_R
2570 || tem_info.type == WEAK_AN || tem_info.type == WEAK_EN))
2571 bidi_it->prev_for_neutral = tem_info;
2572 }
2556 2573
2557 if (type == NEUTRAL_ON 2574 /* If needed, resolve the bracket type according to N0. */
2558 && bidi_paired_bracket_type (ch) != BIDI_BRACKET_NONE) 2575 if (resolve_bracket)
2559 { 2576 {
2560 if (bidi_cache_idx > bidi_cache_start 2577 int embedding_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2561 && bidi_cache_find (bidi_it->charpos, 1, bidi_it) != UNKNOWN_BT 2578 bidi_type_t embedding_type = (embedding_level & 1) ? STRONG_R : STRONG_L;
2562 && bidi_it->bracket_resolved) 2579
2563 type = bidi_it->type; 2580 eassert (bidi_it->prev_for_neutral.type != UNKNOWN_BT);
2581 eassert (bidi_it->bracket_pairing_pos > bidi_it->charpos);
2582 if (bidi_it->bracket_enclosed_type == embedding_type) /* N0b */
2583 type = embedding_type;
2564 else 2584 else
2565 type = bidi_resolve_bracket_pairs (bidi_it); 2585 {
2586 switch (bidi_it->prev_for_neutral.type)
2587 {
2588 case STRONG_R:
2589 case WEAK_EN:
2590 case WEAK_AN:
2591 type =
2592 (bidi_it->bracket_enclosed_type == STRONG_R) /* N0c */
2593 ? STRONG_R /* N0c1 */
2594 : embedding_type; /* N0c2 */
2595 break;
2596 case STRONG_L:
2597 type =
2598 (bidi_it->bracket_enclosed_type == STRONG_L) /* N0c */
2599 ? STRONG_L /* N0c1 */
2600 : embedding_type; /* N0c2 */
2601 break;
2602 default:
2603 /* N0d: Do not set the type for that bracket pair. */
2604 break;
2605 }
2606 }
2607 eassert (type == STRONG_L || type == STRONG_R || type == NEUTRAL_ON);
2608
2609 /* Update the type of the paired closing bracket to the same
2610 type as for the resolved opening bracket. */
2611 if (type != NEUTRAL_ON)
2612 {
2613 ptrdiff_t idx = bidi_cache_search (bidi_it->bracket_pairing_pos,
2614 -1, 1);
2615
2616 if (idx < bidi_cache_start)
2617 emacs_abort ();
2618 bidi_cache[idx].type = type;
2619 }
2566 } 2620 }
2567 2621
2568 return type; 2622 return type;
@@ -2571,28 +2625,10 @@ bidi_resolve_brackets (struct bidi_it *bidi_it)
2571static bidi_type_t 2625static bidi_type_t
2572bidi_resolve_neutral (struct bidi_it *bidi_it) 2626bidi_resolve_neutral (struct bidi_it *bidi_it)
2573{ 2627{
2574 bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring); 2628 bidi_type_t type = bidi_resolve_brackets (bidi_it);
2575 int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2576 bidi_type_t type = UNKNOWN_BT;
2577 int current_level; 2629 int current_level;
2578 bool is_neutral; 2630 bool is_neutral;
2579 2631
2580 if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
2581 {
2582 struct bidi_it tem_it;
2583
2584 if (bidi_it->nchars <= 0)
2585 emacs_abort ();
2586 bidi_copy_it (&tem_it, bidi_it);
2587 type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 1, bidi_it);
2588 if (type != UNKNOWN_BT
2589 && (tem_it.type == STRONG_R || tem_it.type == STRONG_L
2590 || tem_it.type == WEAK_EN || tem_it.type == WEAK_AN))
2591 bidi_remember_char (&bidi_it->prev_for_neutral, &tem_it, 1);
2592 }
2593 if (type == UNKNOWN_BT)
2594 type = bidi_resolve_brackets (bidi_it);
2595
2596 eassert (type == STRONG_R 2632 eassert (type == STRONG_R
2597 || type == STRONG_L 2633 || type == STRONG_L
2598 || type == WEAK_BN 2634 || type == WEAK_BN
@@ -2606,7 +2642,6 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2606 || type == RLI 2642 || type == RLI
2607 || type == PDI); 2643 || type == PDI);
2608 2644
2609 eassert (prev_level >= 0);
2610 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; 2645 current_level = bidi_it->level_stack[bidi_it->stack_idx].level;
2611 eassert (current_level >= 0); 2646 eassert (current_level >= 0);
2612 is_neutral = bidi_get_category (type) == NEUTRAL; 2647 is_neutral = bidi_get_category (type) == NEUTRAL;
diff --git a/src/dispextern.h b/src/dispextern.h
index c75eb27d635..0dd0887c7e6 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1966,6 +1966,8 @@ struct bidi_it {
1966 struct bidi_saved_info next_for_neutral; /* surrounding characters for... */ 1966 struct bidi_saved_info next_for_neutral; /* surrounding characters for... */
1967 struct bidi_saved_info prev_for_neutral; /* ...resolving neutrals */ 1967 struct bidi_saved_info prev_for_neutral; /* ...resolving neutrals */
1968 struct bidi_saved_info next_for_ws; /* character after sequence of ws */ 1968 struct bidi_saved_info next_for_ws; /* character after sequence of ws */
1969 ptrdiff_t bracket_pairing_pos; /* position of pairing bracket */
1970 bidi_type_t bracket_enclosed_type; /* type for bracket resolution */
1969 ptrdiff_t next_en_pos; /* pos. of next char for determining ET type */ 1971 ptrdiff_t next_en_pos; /* pos. of next char for determining ET type */
1970 bidi_type_t next_en_type; /* type of char at next_en_pos */ 1972 bidi_type_t next_en_type; /* type of char at next_en_pos */
1971 bidi_dir_t sos; /* direction of start-of-sequence in effect */ 1973 bidi_dir_t sos; /* direction of start-of-sequence in effect */
@@ -1974,7 +1976,6 @@ struct bidi_it {
1974 int disp_prop; /* if non-zero, there really is a 1976 int disp_prop; /* if non-zero, there really is a
1975 `display' property/string at disp_pos; 1977 `display' property/string at disp_pos;
1976 if 2, the property is a `space' spec */ 1978 if 2, the property is a `space' spec */
1977 bool_bf bracket_resolved : 1; /* if 1, this bracket's type is BPA-resolved */
1978 int stack_idx; /* index of current data on the stack */ 1979 int stack_idx; /* index of current data on the stack */
1979 /* Note: Everything from here on is not copied/saved when the bidi 1980 /* Note: Everything from here on is not copied/saved when the bidi
1980 iterator state is saved, pushed, or popped. So only put here 1981 iterator state is saved, pushed, or popped. So only put here