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

Commit 0eaa25e0 authored by Jean Chalard's avatar Jean Chalard Committed by Android Git Automerger
Browse files

am 914078fd: Fix a bug where recorrection would stop on connectors

* commit '914078fd':
  Fix a bug where recorrection would stop on connectors
parents 56c7ceb4 914078fd
Loading
Loading
Loading
Loading
+14 −6
Original line number Original line Diff line number Diff line
@@ -623,14 +623,24 @@ public final class RichInputConnection {
        return Arrays.binarySearch(sortedSeparators, code) >= 0;
        return Arrays.binarySearch(sortedSeparators, code) >= 0;
    }
    }


    private static boolean isPartOfCompositionForScript(final int codePoint,
            final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
        // We always consider word connectors part of compositions.
        return spacingAndPunctuations.isWordConnector(codePoint)
                // Otherwise, it's part of composition if it's part of script and not a separator.
                || (!spacingAndPunctuations.isWordSeparator(codePoint)
                        && ScriptUtils.isLetterPartOfScript(codePoint, scriptId));
    }

    /**
    /**
     * Returns the text surrounding the cursor.
     * Returns the text surrounding the cursor.
     *
     *
     * @param sortedSeparators a sorted array of code points that split words.
     * @param spacingAndPunctuations the rules for spacing and punctuation
     * @param scriptId the script we consider to be writing words, as one of ScriptUtils.SCRIPT_*
     * @param scriptId the script we consider to be writing words, as one of ScriptUtils.SCRIPT_*
     * @return a range containing the text surrounding the cursor
     * @return a range containing the text surrounding the cursor
     */
     */
    public TextRange getWordRangeAtCursor(final int[] sortedSeparators, final int scriptId) {
    public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations,
            final int scriptId) {
        mIC = mParent.getCurrentInputConnection();
        mIC = mParent.getCurrentInputConnection();
        if (mIC == null) {
        if (mIC == null) {
            return null;
            return null;
@@ -647,8 +657,7 @@ public final class RichInputConnection {
        int startIndexInBefore = before.length();
        int startIndexInBefore = before.length();
        while (startIndexInBefore > 0) {
        while (startIndexInBefore > 0) {
            final int codePoint = Character.codePointBefore(before, startIndexInBefore);
            final int codePoint = Character.codePointBefore(before, startIndexInBefore);
            if (isSeparator(codePoint, sortedSeparators)
            if (!isPartOfCompositionForScript(codePoint, spacingAndPunctuations, scriptId)) {
                    || !ScriptUtils.isLetterPartOfScript(codePoint, scriptId)) {
                break;
                break;
            }
            }
            --startIndexInBefore;
            --startIndexInBefore;
@@ -661,8 +670,7 @@ public final class RichInputConnection {
        int endIndexInAfter = -1;
        int endIndexInAfter = -1;
        while (++endIndexInAfter < after.length()) {
        while (++endIndexInAfter < after.length()) {
            final int codePoint = Character.codePointAt(after, endIndexInAfter);
            final int codePoint = Character.codePointAt(after, endIndexInAfter);
            if (isSeparator(codePoint, sortedSeparators)
            if (!isPartOfCompositionForScript(codePoint, spacingAndPunctuations, scriptId)) {
                    || !ScriptUtils.isLetterPartOfScript(codePoint, scriptId)) {
                break;
                break;
            }
            }
            if (Character.isSupplementaryCodePoint(codePoint)) {
            if (Character.isSupplementaryCodePoint(codePoint)) {
+1 −2
Original line number Original line Diff line number Diff line
@@ -1478,8 +1478,7 @@ public final class InputLogic {
            return;
            return;
        }
        }
        final TextRange range = mConnection.getWordRangeAtCursor(
        final TextRange range = mConnection.getWordRangeAtCursor(
                settingsValues.mSpacingAndPunctuations.mSortedWordSeparators,
                settingsValues.mSpacingAndPunctuations, currentKeyboardScriptId);
                currentKeyboardScriptId);
        if (null == range) return; // Happens if we don't have an input connection at all
        if (null == range) return; // Happens if we don't have an input connection at all
        if (range.length() <= 0) {
        if (range.length() <= 0) {
            // Race condition, or touching a word in a non-supported script.
            // Race condition, or touching a word in a non-supported script.
+17 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin.settings;


import android.content.res.Resources;
import android.content.res.Resources;


import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.internal.MoreKeySpec;
import com.android.inputmethod.keyboard.internal.MoreKeySpec;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.PunctuationSuggestions;
import com.android.inputmethod.latin.PunctuationSuggestions;
@@ -68,6 +69,22 @@ public final class SpacingAndPunctuations {
        mSuggestPuncList = PunctuationSuggestions.newPunctuationSuggestions(suggestPuncsSpec);
        mSuggestPuncList = PunctuationSuggestions.newPunctuationSuggestions(suggestPuncsSpec);
    }
    }


    @UsedForTesting
    public SpacingAndPunctuations(final SpacingAndPunctuations model,
            final int[] overrideSortedWordSeparators) {
        mSortedSymbolsPrecededBySpace = model.mSortedSymbolsPrecededBySpace;
        mSortedSymbolsFollowedBySpace = model.mSortedSymbolsFollowedBySpace;
        mSortedSymbolsClusteringTogether = model.mSortedSymbolsClusteringTogether;
        mSortedWordConnectors = model.mSortedWordConnectors;
        mSortedWordSeparators = overrideSortedWordSeparators;
        mSuggestPuncList = model.mSuggestPuncList;
        mSentenceSeparator = model.mSentenceSeparator;
        mSentenceSeparatorAndSpace = model.mSentenceSeparatorAndSpace;
        mCurrentLanguageHasSpaces = model.mCurrentLanguageHasSpaces;
        mUsesAmericanTypography = model.mUsesAmericanTypography;
        mUsesGermanRules = model.mUsesGermanRules;
    }

    public boolean isWordSeparator(final int code) {
    public boolean isWordSeparator(final int code) {
        return Arrays.binarySearch(mSortedWordSeparators, code) >= 0;
        return Arrays.binarySearch(mSortedWordSeparators, code) >= 0;
    }
    }
+22 −18
Original line number Original line Diff line number Diff line
@@ -215,18 +215,23 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
                "abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
                "abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
    }
    }


    public void testGetWordRangeAtCursor() {
        /**
        /**
         * Test logic in getting the word range at the cursor.
         * Test logic in getting the word range at the cursor.
         */
         */
    private static final int[] SPACE = { Constants.CODE_SPACE };
        final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(
    static final int[] TAB = { Constants.CODE_TAB };
                mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
    private static final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
        final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
                mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
        final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
        // A character that needs surrogate pair to represent its code point (U+2008A).
        // A character that needs surrogate pair to represent its code point (U+2008A).
    private static final String SUPPLEMENTARY_CHAR = "\uD840\uDC8A";
        final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
    private static final String HIRAGANA_WORD = "\u3042\u3044\u3046\u3048\u304A"; // あいうえお
        final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
    private static final String GREEK_WORD = "\u03BA\u03B1\u03B9"; // και
                mSpacingAndPunctuations, StringUtils.toSortedCodePointArray(
                        SUPPLEMENTARY_CHAR_STRING));
        final String HIRAGANA_WORD = "\u3042\u3044\u3046\u3048\u304A"; // あいうえお
        final String GREEK_WORD = "\u03BA\u03B1\u03B9"; // και


    public void testGetWordRangeAtCursor() {
        ExtractedText et = new ExtractedText();
        ExtractedText et = new ExtractedText();
        final MockInputMethodService mockInputMethodService = new MockInputMethodService();
        final MockInputMethodService mockInputMethodService = new MockInputMethodService();
        final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
        final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
@@ -249,10 +254,9 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {


        // splitting on supplementary character
        // splitting on supplementary character
        mockInputMethodService.setInputConnection(
        mockInputMethodService.setInputConnection(
                new MockConnection("one word" + SUPPLEMENTARY_CHAR + "wo", "rd", et));
                new MockConnection("one word" + SUPPLEMENTARY_CHAR_STRING + "wo", "rd", et));
        ic.beginBatchEdit();
        ic.beginBatchEdit();
        r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
        r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
                ScriptUtils.SCRIPT_LATIN);
        ic.endBatchEdit();
        ic.endBatchEdit();
        assertTrue(TextUtils.equals("word", r.mWord));
        assertTrue(TextUtils.equals("word", r.mWord));


@@ -260,8 +264,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
        mockInputMethodService.setInputConnection(
        mockInputMethodService.setInputConnection(
                new MockConnection(HIRAGANA_WORD + "wo", "rd" + GREEK_WORD, et));
                new MockConnection(HIRAGANA_WORD + "wo", "rd" + GREEK_WORD, et));
        ic.beginBatchEdit();
        ic.beginBatchEdit();
        r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
        r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
                ScriptUtils.SCRIPT_LATIN);
        ic.endBatchEdit();
        ic.endBatchEdit();
        assertTrue(TextUtils.equals("word", r.mWord));
        assertTrue(TextUtils.equals("word", r.mWord));


@@ -269,8 +272,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
        mockInputMethodService.setInputConnection(
        mockInputMethodService.setInputConnection(
                new MockConnection("text" + GREEK_WORD, "text", et));
                new MockConnection("text" + GREEK_WORD, "text", et));
        ic.beginBatchEdit();
        ic.beginBatchEdit();
        r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
        r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_GREEK);
                ScriptUtils.SCRIPT_GREEK);
        ic.endBatchEdit();
        ic.endBatchEdit();
        assertTrue(TextUtils.equals(GREEK_WORD, r.mWord));
        assertTrue(TextUtils.equals(GREEK_WORD, r.mWord));
    }
    }
@@ -286,6 +288,8 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
    }
    }


    private void helpTestGetSuggestionSpansAtWord(final int cursorPos) {
    private void helpTestGetSuggestionSpansAtWord(final int cursorPos) {
        final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(
                mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
        final MockInputMethodService mockInputMethodService = new MockInputMethodService();
        final MockInputMethodService mockInputMethodService = new MockInputMethodService();
        final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
        final RichInputConnection ic = new RichInputConnection(mockInputMethodService);