aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-10-18 13:23:29 +0300
committerEli Zaretskii2014-10-18 13:23:29 +0300
commit1c396384998d74133fe13efda416f7a0afa53405 (patch)
treeabc80bd80f9b428586299eebcdd3c57760ba4a85 /src
parent022309033e752101a509a475ee4d7b65d35838d1 (diff)
downloademacs-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.c150
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. */
808static bidi_type_t 807static bidi_type_t
809bidi_cache_find (ptrdiff_t charpos, bool neutrals_ok, struct bidi_it *bidi_it) 808bidi_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
2532static void 2528static void
2533bidi_record_prev_for_neutral (struct bidi_saved_info *info, int level) 2529bidi_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
2553static bidi_type_t 2550static 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