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

Commit e1fc4f6c authored by Gilles Debunne's avatar Gilles Debunne
Browse files

Optimisations and bugs in SpellChecker

A bug was introduced in a recent refactoring: correct words didn't have their
SpellCheckSpan removed, leaving a lot of useless spans.

SPAN_EXCLUSIVE_EXCLUSIVE should never have a 0-length. With Japanese characters
wordStart could be equal to wordEnd when parsing the text: skip these.

Using toString().substring(...) instead of subSequence(...).toString() which
is more efficient.

Change-Id: I670870a34565939b676400091f4852152a7f7124
parent f00b4dec
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ public class SpellChecker implements SpellCheckerSessionListener {

    @Override
    public void onGetSuggestions(SuggestionsInfo[] results) {
        final Editable editable = (Editable) mTextView.getText();
        for (int i = 0; i < results.length; i++) {
            SuggestionsInfo suggestionsInfo = results[i];
            if (suggestionsInfo.getCookie() != mCookie) continue;
@@ -178,18 +179,19 @@ public class SpellChecker implements SpellCheckerSessionListener {
                    boolean looksLikeTypo =
                            ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);

                    SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
                    if (!isInDictionary && looksLikeTypo) {
                        createMisspelledSuggestionSpan(suggestionsInfo, mSpellCheckSpans[j]);
                        createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan);
                    }
                    editable.removeSpan(spellCheckSpan);
                    break;
                }
            }
        }
    }

    private void createMisspelledSuggestionSpan(SuggestionsInfo suggestionsInfo,
    private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo,
            SpellCheckSpan spellCheckSpan) {
        final Editable editable = (Editable) mTextView.getText();
        final int start = editable.getSpanStart(spellCheckSpan);
        final int end = editable.getSpanEnd(spellCheckSpan);

@@ -251,6 +253,5 @@ public class SpellChecker implements SpellCheckerSessionListener {

        // TODO limit to the word rectangle region
        mTextView.invalidate();
        editable.removeSpan(spellCheckSpan);
    }
}
+10 −9
Original line number Diff line number Diff line
@@ -7780,7 +7780,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        // Iterate over the newly added text and schedule new SpellCheckSpans
        while (wordStart <= shiftedEnd) {
            if (wordEnd >= shiftedStart) {
            if (wordEnd >= shiftedStart && wordEnd > wordStart) {
                // A new word has been created across the interval boundaries. Remove previous spans
                if (wordStart < shiftedStart && wordEnd > shiftedStart) {
                    removeSpansAt(start, spellCheckSpans, text);
@@ -9946,8 +9946,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    suggestionInfo.text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            // Add the text before and after the span.
            suggestionInfo.text.insert(0, mText.subSequence(unionStart, spanStart).toString());
            suggestionInfo.text.append(mText.subSequence(spanEnd, unionEnd).toString());
            suggestionInfo.text.insert(0, mText.toString().substring(unionStart, spanStart));
            suggestionInfo.text.append(mText.toString().substring(spanEnd, unionEnd));
        }

        @Override
@@ -9979,7 +9979,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                hide();
                return;
            }
            final String originalText = mText.subSequence(spanStart, spanEnd).toString();
            final String originalText = mText.toString().substring(spanStart, spanEnd);

            if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) {
                Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
@@ -10016,9 +10016,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                if (!TextUtils.isEmpty(
                        suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
                    InputMethodManager imm = InputMethodManager.peekInstance();
                    if (imm != null) {
                        imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
                                suggestionInfo.suggestionIndex);
                    }
                }

                // Swap text content between actual text and Suggestion span
                String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
@@ -10037,7 +10039,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    }
                }

                // Move cursor at the end of the replacement word
                // Move cursor at the end of the replaced word
                Selection.setSelection(editable, spanEnd + lengthDifference);
            }

@@ -10166,8 +10168,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        if (!hasSelection()) {
            // There may already be a selection on device rotation
            boolean currentWordSelected = selectCurrentWord();
            if (!currentWordSelected) {
            if (!selectCurrentWord()) {
                // No word found under cursor or text selection not permitted.
                return false;
            }