diff options
| author | Eli Zaretskii | 2014-10-18 13:23:29 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-10-18 13:23:29 +0300 |
| commit | 1c396384998d74133fe13efda416f7a0afa53405 (patch) | |
| tree | abc80bd80f9b428586299eebcdd3c57760ba4a85 /src | |
| parent | 022309033e752101a509a475ee4d7b65d35838d1 (diff) | |
| download | emacs-1c396384998d74133fe13efda416f7a0afa53405.tar.gz emacs-1c396384998d74133fe13efda416f7a0afa53405.zip | |
Move cache retrieval on forwards scans to bidi_resolve_brackets.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bidi.c | 150 |
1 files changed, 61 insertions, 89 deletions
diff --git a/src/bidi.c b/src/bidi.c index abcfa2a9b90..8f996eb6539 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -800,26 +800,22 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, | |||
| 800 | 800 | ||
| 801 | /* Look for a cached iterator state that corresponds to CHARPOS. If | 801 | /* Look for a cached iterator state that corresponds to CHARPOS. If |
| 802 | found, copy the cached state into BIDI_IT and return the type of | 802 | found, copy the cached state into BIDI_IT and return the type of |
| 803 | the cached entry. If not found, return UNKNOWN_BT. NEUTRALS_OK | 803 | the cached entry. If not found, return UNKNOWN_BT. RESOLVED_ONLY |
| 804 | non-zero means it is OK to return cached state for neutral | 804 | zero means it is OK to return cached states tyhat were not fully |
| 805 | characters that have no valid next_for_neutral member, and | 805 | resolved yet. This can happen if the state was cached before it |
| 806 | therefore cannot be resolved. This can happen if the state was | 806 | was resolved in bidi_resolve_neutral. */ |
| 807 | cached before it was resolved in bidi_resolve_neutral. */ | ||
| 808 | static bidi_type_t | 807 | static bidi_type_t |
| 809 | bidi_cache_find (ptrdiff_t charpos, bool neutrals_ok, struct bidi_it *bidi_it) | 808 | bidi_cache_find (ptrdiff_t charpos, bool resolved_only, struct bidi_it *bidi_it) |
| 810 | { | 809 | { |
| 811 | ptrdiff_t i = bidi_cache_search (charpos, -1, bidi_it->scan_dir); | 810 | ptrdiff_t i = bidi_cache_search (charpos, -1, bidi_it->scan_dir); |
| 812 | 811 | ||
| 813 | if (i >= bidi_cache_start | 812 | if (i >= bidi_cache_start |
| 814 | && (neutrals_ok | 813 | && (!resolved_only |
| 815 | /* Callers that don't want to resolve neutrals (and set | 814 | /* Callers that want only fully resolved states (and set |
| 816 | neutrals_ok = false) need to be sure that there's enough | 815 | resolved_only = true) need to be sure that there's enough |
| 817 | info in the cached state to resolve the neutrals and | 816 | info in the cached state to return the state as final, |
| 818 | isolates, and if not, they don't want the cached state. */ | 817 | and if not, they don't want the cached state. */ |
| 819 | || !(bidi_cache[i].resolved_level == -1 | 818 | || bidi_cache[i].resolved_level >= 0)) |
| 820 | && (bidi_get_category (bidi_cache[i].type) == NEUTRAL | ||
| 821 | || bidi_isolate_fmt_char (bidi_cache[i].type)) | ||
| 822 | && bidi_cache[i].next_for_neutral.type == UNKNOWN_BT))) | ||
| 823 | { | 819 | { |
| 824 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; | 820 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; |
| 825 | 821 | ||
| @@ -2522,7 +2518,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) | |||
| 2522 | 2518 | ||
| 2523 | /* Restore bidi_it from the cache, which should have the bracket | 2519 | /* Restore bidi_it from the cache, which should have the bracket |
| 2524 | resolution members set as determined by the above loop. */ | 2520 | resolution members set as determined by the above loop. */ |
| 2525 | type = bidi_cache_find (saved_it.charpos, 1, bidi_it); | 2521 | type = bidi_cache_find (saved_it.charpos, 0, bidi_it); |
| 2526 | eassert (type == NEUTRAL_ON); | 2522 | eassert (type == NEUTRAL_ON); |
| 2527 | } | 2523 | } |
| 2528 | 2524 | ||
| @@ -2530,7 +2526,8 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) | |||
| 2530 | } | 2526 | } |
| 2531 | 2527 | ||
| 2532 | static void | 2528 | static void |
| 2533 | bidi_record_prev_for_neutral (struct bidi_saved_info *info, int level) | 2529 | bidi_record_type_for_neutral (struct bidi_saved_info *info, int level, |
| 2530 | bool nextp) | ||
| 2534 | { | 2531 | { |
| 2535 | int idx; | 2532 | int idx; |
| 2536 | 2533 | ||
| @@ -2538,16 +2535,16 @@ bidi_record_prev_for_neutral (struct bidi_saved_info *info, int level) | |||
| 2538 | { | 2535 | { |
| 2539 | int lev = bidi_cache[idx].level_stack[bidi_cache[idx].stack_idx].level; | 2536 | int lev = bidi_cache[idx].level_stack[bidi_cache[idx].stack_idx].level; |
| 2540 | 2537 | ||
| 2541 | if (bidi_cache[idx].type_after_wn == NEUTRAL_B) | ||
| 2542 | return; /* no cache slot to update */ | ||
| 2543 | if (lev <= level) | 2538 | if (lev <= level) |
| 2544 | { | 2539 | { |
| 2545 | eassert (lev == level); | 2540 | eassert (lev == level); |
| 2546 | bidi_cache[idx].prev_for_neutral = *info; | 2541 | if (nextp) |
| 2542 | bidi_cache[idx].next_for_neutral = *info; | ||
| 2543 | else | ||
| 2544 | bidi_cache[idx].prev_for_neutral = *info; | ||
| 2547 | break; | 2545 | break; |
| 2548 | } | 2546 | } |
| 2549 | } | 2547 | } |
| 2550 | eassert (idx < bidi_cache_idx); | ||
| 2551 | } | 2548 | } |
| 2552 | 2549 | ||
| 2553 | static bidi_type_t | 2550 | static bidi_type_t |
| @@ -2557,19 +2554,24 @@ bidi_resolve_brackets (struct bidi_it *bidi_it) | |||
| 2557 | bool resolve_bracket = false; | 2554 | bool resolve_bracket = false; |
| 2558 | bidi_type_t type = UNKNOWN_BT; | 2555 | bidi_type_t type = UNKNOWN_BT; |
| 2559 | int ch; | 2556 | int ch; |
| 2560 | struct bidi_saved_info tem_info; | 2557 | struct bidi_saved_info prev_for_neutral, next_for_neutral; |
| 2561 | 2558 | ||
| 2562 | /* Record the prev_for_neutral type either from the previous | 2559 | /* Record the prev_for_neutral type either from the previous |
| 2563 | character, if it was a strong or AN/EN, or from the | 2560 | character, if it was a strong or AN/EN, or from the |
| 2564 | prev_for_neutral information recorded previously. */ | 2561 | prev_for_neutral information recorded previously. */ |
| 2565 | if (bidi_it->type == STRONG_L || bidi_it->type == STRONG_R | 2562 | if (bidi_it->type == STRONG_L || bidi_it->type == STRONG_R |
| 2566 | || bidi_it->type == WEAK_AN || bidi_it->type == WEAK_EN) | 2563 | || bidi_it->type == WEAK_AN || bidi_it->type == WEAK_EN) |
| 2567 | bidi_remember_char (&tem_info, bidi_it, 1); | 2564 | bidi_remember_char (&prev_for_neutral, bidi_it, 1); |
| 2565 | else | ||
| 2566 | prev_for_neutral = bidi_it->prev_for_neutral; | ||
| 2567 | /* Record the next_for_neutral type information. */ | ||
| 2568 | if (bidi_it->next_for_neutral.charpos > bidi_it->charpos) | ||
| 2569 | next_for_neutral = bidi_it->next_for_neutral; | ||
| 2568 | else | 2570 | else |
| 2569 | tem_info = bidi_it->prev_for_neutral; | 2571 | next_for_neutral.charpos = -1; |
| 2570 | if (!bidi_it->first_elt) | 2572 | if (!bidi_it->first_elt) |
| 2571 | { | 2573 | { |
| 2572 | type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 1, bidi_it); | 2574 | type = bidi_cache_find (bidi_it->charpos + bidi_it->nchars, 0, bidi_it); |
| 2573 | ch = bidi_it->ch; | 2575 | ch = bidi_it->ch; |
| 2574 | } | 2576 | } |
| 2575 | if (type == UNKNOWN_BT) | 2577 | if (type == UNKNOWN_BT) |
| @@ -2580,14 +2582,18 @@ bidi_resolve_brackets (struct bidi_it *bidi_it) | |||
| 2580 | } | 2582 | } |
| 2581 | else | 2583 | else |
| 2582 | { | 2584 | { |
| 2585 | eassert (bidi_it->resolved_level == -1); | ||
| 2583 | /* If the cached state shows an increase of embedding level due | 2586 | /* If the cached state shows an increase of embedding level due |
| 2584 | to an isolate initiator, we need to update the 1st cached | 2587 | to an isolate initiator, we need to update the 1st cached |
| 2585 | state of the next run of the current isolating sequence with | 2588 | state of the next run of the current isolating sequence with |
| 2586 | the prev_for_neutral information, so that it will be picked | 2589 | the prev_for_neutral and next_for_neutral information, so |
| 2587 | up when we advance to that next run. */ | 2590 | that it will be picked up when we advance to that next run. */ |
| 2588 | if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level | 2591 | if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level |
| 2589 | && bidi_it->level_stack[bidi_it->stack_idx].isolate_status) | 2592 | && bidi_it->level_stack[bidi_it->stack_idx].isolate_status) |
| 2590 | bidi_record_prev_for_neutral (&tem_info, prev_level); | 2593 | { |
| 2594 | bidi_record_type_for_neutral (&prev_for_neutral, prev_level, 0); | ||
| 2595 | bidi_record_type_for_neutral (&next_for_neutral, prev_level, 1); | ||
| 2596 | } | ||
| 2591 | if (type == NEUTRAL_ON | 2597 | if (type == NEUTRAL_ON |
| 2592 | && bidi_paired_bracket_type (ch) == BIDI_BRACKET_OPEN) | 2598 | && bidi_paired_bracket_type (ch) == BIDI_BRACKET_OPEN) |
| 2593 | { | 2599 | { |
| @@ -2606,10 +2612,15 @@ bidi_resolve_brackets (struct bidi_it *bidi_it) | |||
| 2606 | resolve_bracket = true; | 2612 | resolve_bracket = true; |
| 2607 | } | 2613 | } |
| 2608 | } | 2614 | } |
| 2609 | /* Keep track of the prev_for_neutral type, needed for resolving | 2615 | /* Keep track of the prev_for_neutral and next_for_neutral |
| 2610 | brackets below and for resolving neutrals in bidi_resolve_neutral. */ | 2616 | types, needed for resolving brackets below and for resolving |
| 2617 | neutrals in bidi_resolve_neutral. */ | ||
| 2611 | if (bidi_it->level_stack[bidi_it->stack_idx].level == prev_level) | 2618 | if (bidi_it->level_stack[bidi_it->stack_idx].level == prev_level) |
| 2612 | bidi_it->prev_for_neutral = tem_info; | 2619 | { |
| 2620 | bidi_it->prev_for_neutral = prev_for_neutral; | ||
| 2621 | if (next_for_neutral.charpos > 0) | ||
| 2622 | bidi_it->next_for_neutral = next_for_neutral; | ||
| 2623 | } | ||
| 2613 | } | 2624 | } |
| 2614 | 2625 | ||
| 2615 | /* If needed, resolve the bracket type according to N0. */ | 2626 | /* If needed, resolve the bracket type according to N0. */ |
| @@ -2694,9 +2705,18 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) | |||
| 2694 | || (type == WEAK_BN && bidi_explicit_dir_char (bidi_it->ch))) | 2705 | || (type == WEAK_BN && bidi_explicit_dir_char (bidi_it->ch))) |
| 2695 | { | 2706 | { |
| 2696 | if (bidi_it->next_for_neutral.type != UNKNOWN_BT) | 2707 | if (bidi_it->next_for_neutral.type != UNKNOWN_BT) |
| 2697 | type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, | 2708 | { |
| 2698 | bidi_it->next_for_neutral.type, | 2709 | /* Make sure the data for resolving neutrals we are |
| 2699 | current_level); | 2710 | about to use is valid. */ |
| 2711 | eassert (bidi_it->next_for_neutral.charpos > bidi_it->charpos | ||
| 2712 | /* PDI defines an eos, so it's OK for it to | ||
| 2713 | serve as its own next_for_neutral. */ | ||
| 2714 | || (bidi_it->next_for_neutral.charpos == bidi_it->charpos | ||
| 2715 | && bidi_it->type == PDI)); | ||
| 2716 | type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, | ||
| 2717 | bidi_it->next_for_neutral.type, | ||
| 2718 | current_level); | ||
| 2719 | } | ||
| 2700 | /* The next two "else if" clauses are shortcuts for the | 2720 | /* The next two "else if" clauses are shortcuts for the |
| 2701 | important special case when we have a long sequence of | 2721 | important special case when we have a long sequence of |
| 2702 | neutral or WEAK_BN characters, such as whitespace or nulls or | 2722 | neutral or WEAK_BN characters, such as whitespace or nulls or |
| @@ -2892,16 +2912,13 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 2892 | } | 2912 | } |
| 2893 | } | 2913 | } |
| 2894 | 2914 | ||
| 2895 | /* Perhaps the character we want is already cached. If it is, the | 2915 | /* Perhaps the character we want is already cached s fully resolved. |
| 2896 | call to bidi_cache_find below will return a type other than | 2916 | If it is, the call to bidi_cache_find below will return a type |
| 2897 | UNKNOWN_BT. */ | 2917 | other than UNKNOWN_BT. */ |
| 2898 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) | 2918 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) |
| 2899 | { | 2919 | { |
| 2900 | int bob = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring)) | 2920 | int bob = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring)) |
| 2901 | ? 0 : 1); | 2921 | ? 0 : 1); |
| 2902 | bidi_type_t prev_type = bidi_it->type; | ||
| 2903 | bidi_type_t type_for_neutral = bidi_it->next_for_neutral.type; | ||
| 2904 | ptrdiff_t pos_for_neutral = bidi_it->next_for_neutral.charpos; | ||
| 2905 | 2922 | ||
| 2906 | if (bidi_it->scan_dir > 0) | 2923 | if (bidi_it->scan_dir > 0) |
| 2907 | { | 2924 | { |
| @@ -2916,57 +2933,12 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 2916 | cached at the beginning of the iteration. */ | 2933 | cached at the beginning of the iteration. */ |
| 2917 | next_char_pos = bidi_it->charpos - 1; | 2934 | next_char_pos = bidi_it->charpos - 1; |
| 2918 | if (next_char_pos >= bob - 1) | 2935 | if (next_char_pos >= bob - 1) |
| 2919 | type = bidi_cache_find (next_char_pos, 0, bidi_it); | 2936 | type = bidi_cache_find (next_char_pos, 1, bidi_it); |
| 2920 | |||
| 2921 | /* For a sequence of BN and NI, copy the type from the previous | ||
| 2922 | character. This is because the loop in bidi_resolve_neutral | ||
| 2923 | that handles such sequences caches the characters it | ||
| 2924 | traverses, but does not (and cannot) store the | ||
| 2925 | next_for_neutral member for them, because it is only known | ||
| 2926 | when the loop ends. So when we find them in the cache, their | ||
| 2927 | type needs to be updated, but we don't have next_for_neutral | ||
| 2928 | to do that. However, whatever type is resolved as result of | ||
| 2929 | that loop, it will be the same for all the traversed | ||
| 2930 | characters, by virtue of N1 and N2. */ | ||
| 2931 | if (type == WEAK_BN && bidi_it->scan_dir > 0 | ||
| 2932 | && bidi_explicit_dir_char (bidi_it->ch) | ||
| 2933 | && type_for_neutral != UNKNOWN_BT | ||
| 2934 | && bidi_it->charpos < pos_for_neutral) | ||
| 2935 | { | ||
| 2936 | type = prev_type; | ||
| 2937 | eassert (type != UNKNOWN_BT); | ||
| 2938 | } | ||
| 2939 | if (type != UNKNOWN_BT) | 2937 | if (type != UNKNOWN_BT) |
| 2940 | { | 2938 | { |
| 2941 | /* If resolved_level is -1, it means this state was cached | 2939 | /* We asked the cache for fully resolved states. */ |
| 2942 | before it was completely resolved, so we cannot return | 2940 | eassert (bidi_it->resolved_level >= 0); |
| 2943 | it. */ | 2941 | return bidi_it->resolved_level; |
| 2944 | if (bidi_it->resolved_level != -1) | ||
| 2945 | { | ||
| 2946 | eassert (bidi_it->resolved_level >= 0); | ||
| 2947 | return bidi_it->resolved_level; | ||
| 2948 | } | ||
| 2949 | else | ||
| 2950 | { | ||
| 2951 | level = bidi_it->level_stack[bidi_it->stack_idx].level; | ||
| 2952 | if (bidi_get_category (type) == NEUTRAL | ||
| 2953 | || bidi_isolate_fmt_char (type)) | ||
| 2954 | { | ||
| 2955 | /* Make sure the data for resolving neutrals we are | ||
| 2956 | about to use is valid. */ | ||
| 2957 | if (bidi_it->next_for_neutral.charpos < bidi_it->charpos | ||
| 2958 | /* PDI defines an eos, so it's OK for it to | ||
| 2959 | serve as its own next_for_neutral. */ | ||
| 2960 | || (bidi_it->next_for_neutral.charpos == bidi_it->charpos | ||
| 2961 | && bidi_it->type != PDI) | ||
| 2962 | || bidi_it->next_for_neutral.type == UNKNOWN_BT) | ||
| 2963 | emacs_abort (); | ||
| 2964 | |||
| 2965 | type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, | ||
| 2966 | bidi_it->next_for_neutral.type, | ||
| 2967 | level); | ||
| 2968 | } | ||
| 2969 | } | ||
| 2970 | } | 2942 | } |
| 2971 | } | 2943 | } |
| 2972 | 2944 | ||