Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91779477 authored by Gilles Debunne's avatar Gilles Debunne Committed by Android (Google) Code Review
Browse files

Merge "Fixed SSB. Correct broadcast of removed spans' positions"

parents 376011e8 90985286
Loading
Loading
Loading
Loading
+35 −17
Original line number Original line Diff line number Diff line
@@ -130,14 +130,15 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
    private void resizeFor(int size) {
    private void resizeFor(int size) {
        final int oldLength = mText.length;
        final int oldLength = mText.length;
        final int newLength = ArrayUtils.idealCharArraySize(size + 1);
        final int newLength = ArrayUtils.idealCharArraySize(size + 1);
        final int after = oldLength - (mGapStart + mGapLength);
        final int delta = newLength - oldLength;
        if (delta == 0) return;


        char[] newText = new char[newLength];
        char[] newText = new char[newLength];
        System.arraycopy(mText, 0, newText, 0, mGapStart);
        System.arraycopy(mText, 0, newText, 0, mGapStart);
        final int after = oldLength - (mGapStart + mGapLength);
        System.arraycopy(mText, oldLength - after, newText, newLength - after, after);
        System.arraycopy(mText, oldLength - after, newText, newLength - after, after);
        mText = newText;
        mText = newText;


        final int delta = newLength - oldLength;
        mGapLength += delta;
        mGapLength += delta;
        if (mGapLength < 1)
        if (mGapLength < 1)
            new Exception("mGapLength < 1").printStackTrace();
            new Exception("mGapLength < 1").printStackTrace();
@@ -305,6 +306,26 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
            resizeFor(mText.length + nbNewChars - mGapLength);
            resizeFor(mText.length + nbNewChars - mGapLength);
        }
        }


        // The removal pass needs to be done before the gap is updated in order to broadcast the
        // correct previous positions to the correct intersecting SpanWatchers
        if (end > start) { // no need for span fixup on pure insertion
            // A for loop will not work because the array is being modified
            // Do not iterate in reverse to keep the SpanWatchers notified in ordering
            // Also, a removed SpanWatcher should not get notified of removed spans located
            // further in the span array.
            int i = 0;
            while (i < mSpanCount) {
                if ((mSpanFlags[i] & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
                mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
                mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
                    removeSpan(i);
                } else {
                    i++;
                }
            }
        }

        mGapStart += nbNewChars;
        mGapStart += nbNewChars;
        mGapLength -= nbNewChars;
        mGapLength -= nbNewChars;


@@ -313,11 +334,10 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable


        TextUtils.getChars(cs, csStart, csEnd, mText, start);
        TextUtils.getChars(cs, csStart, csEnd, mText, start);


        if (end > start) {
        if (end > start) { // no need for span fixup on pure insertion
            // no need for span fixup on pure insertion
            final boolean atEnd = (mGapStart + mGapLength == mText.length);
            boolean atEnd = (mGapStart + mGapLength == mText.length);


            for (int i = mSpanCount - 1; i >= 0; i--) {
            for (int i = 0; i < mSpanCount; i++) {
                if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) {
                if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) {
                    int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
                    int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;


@@ -331,16 +351,11 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
                if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
                if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
                    int flag = (mSpanFlags[i] & END_MASK);
                    int flag = (mSpanFlags[i] & END_MASK);


                    if (flag == POINT || (flag == PARAGRAPH && atEnd))
                    if (flag == POINT || (flag == PARAGRAPH && atEnd)) {
                        mSpanEnds[i] = mGapStart + mGapLength;
                        mSpanEnds[i] = mGapStart + mGapLength;
                    else
                    } else {
                        mSpanEnds[i] = start;
                        mSpanEnds[i] = start;
                    }
                    }

                // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE, which are POINT_MARK and could
                // get their boundaries swapped by the above code
                if (mSpanEnds[i] < mSpanStarts[i]) {
                    removeSpan(i);
                }
                }
            }
            }
        }
        }
@@ -359,7 +374,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
                if (en > csEnd) en = csEnd;
                if (en > csEnd) en = csEnd;


                // Add span only if this object is not yet used as a span in this string
                // Add span only if this object is not yet used as a span in this string
                if (getSpanStart(spans[i]) < 0 && !(spans[i] instanceof SpanWatcher)) {
                if (getSpanStart(spans[i]) < 0) {
                    setSpan(false, spans[i], st - csStart + start, en - csStart + start,
                    setSpan(false, spans[i], st - csStart + start, en - csStart + start,
                            sp.getSpanFlags(spans[i]));
                            sp.getSpanFlags(spans[i]));
                }
                }
@@ -465,6 +480,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable


            int newReplaceEnd = replaceEnd + nbNewChars;
            int newReplaceEnd = replaceEnd + nbNewChars;
            boolean spanChanged = false;
            boolean spanChanged = false;

            int previousSpanStart = spanStart;
            int previousSpanStart = spanStart;
            if (spanStart > newReplaceEnd) {
            if (spanStart > newReplaceEnd) {
                if (nbNewChars != 0) {
                if (nbNewChars != 0) {
@@ -477,11 +493,13 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
                        ((spanFlags & SPAN_START_AT_START) != SPAN_START_AT_START)) &&
                        ((spanFlags & SPAN_START_AT_START) != SPAN_START_AT_START)) &&
                        (spanStart != newReplaceEnd ||
                        (spanStart != newReplaceEnd ||
                        ((spanFlags & SPAN_START_AT_END) != SPAN_START_AT_END))) {
                        ((spanFlags & SPAN_START_AT_END) != SPAN_START_AT_END))) {
                    // TODO previousSpanStart is incorrect, but we would need to save all the
                    // TODO A correct previousSpanStart cannot be computed at this point.
                    // previous spans' positions before replace to provide it
                    // It would require to save all the previous spans' positions before the replace
                    // Using an invalid -1 value to convey this would break the broacast range
                    spanChanged = true;
                    spanChanged = true;
                }
                }
            }
            }

            int previousSpanEnd = spanEnd;
            int previousSpanEnd = spanEnd;
            if (spanEnd > newReplaceEnd) {
            if (spanEnd > newReplaceEnd) {
                if (nbNewChars != 0) {
                if (nbNewChars != 0) {