Fix a bug where recorrection would stop on connectors
Bug: 16733686 Change-Id: I7a9f79a81e33a1f5bf5f3daf0b78d0f1e4447e7amain
parent
42665f0ee2
commit
914078fd91
|
@ -623,14 +623,24 @@ public final class RichInputConnection {
|
|||
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.
|
||||
*
|
||||
* @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_*
|
||||
* @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();
|
||||
if (mIC == null) {
|
||||
return null;
|
||||
|
@ -647,8 +657,7 @@ public final class RichInputConnection {
|
|||
int startIndexInBefore = before.length();
|
||||
while (startIndexInBefore > 0) {
|
||||
final int codePoint = Character.codePointBefore(before, startIndexInBefore);
|
||||
if (isSeparator(codePoint, sortedSeparators)
|
||||
|| !ScriptUtils.isLetterPartOfScript(codePoint, scriptId)) {
|
||||
if (!isPartOfCompositionForScript(codePoint, spacingAndPunctuations, scriptId)) {
|
||||
break;
|
||||
}
|
||||
--startIndexInBefore;
|
||||
|
@ -661,8 +670,7 @@ public final class RichInputConnection {
|
|||
int endIndexInAfter = -1;
|
||||
while (++endIndexInAfter < after.length()) {
|
||||
final int codePoint = Character.codePointAt(after, endIndexInAfter);
|
||||
if (isSeparator(codePoint, sortedSeparators)
|
||||
|| !ScriptUtils.isLetterPartOfScript(codePoint, scriptId)) {
|
||||
if (!isPartOfCompositionForScript(codePoint, spacingAndPunctuations, scriptId)) {
|
||||
break;
|
||||
}
|
||||
if (Character.isSupplementaryCodePoint(codePoint)) {
|
||||
|
|
|
@ -1478,8 +1478,7 @@ public final class InputLogic {
|
|||
return;
|
||||
}
|
||||
final TextRange range = mConnection.getWordRangeAtCursor(
|
||||
settingsValues.mSpacingAndPunctuations.mSortedWordSeparators,
|
||||
currentKeyboardScriptId);
|
||||
settingsValues.mSpacingAndPunctuations, currentKeyboardScriptId);
|
||||
if (null == range) return; // Happens if we don't have an input connection at all
|
||||
if (range.length() <= 0) {
|
||||
// Race condition, or touching a word in a non-supported script.
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.inputmethod.latin.settings;
|
|||
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.keyboard.internal.MoreKeySpec;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
import com.android.inputmethod.latin.PunctuationSuggestions;
|
||||
|
@ -68,6 +69,22 @@ public final class SpacingAndPunctuations {
|
|||
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) {
|
||||
return Arrays.binarySearch(mSortedWordSeparators, code) >= 0;
|
||||
}
|
||||
|
|
|
@ -215,18 +215,23 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
"abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test logic in getting the word range at the cursor.
|
||||
*/
|
||||
private static final int[] SPACE = { Constants.CODE_SPACE };
|
||||
static final int[] TAB = { Constants.CODE_TAB };
|
||||
private static final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
|
||||
// A character that needs surrogate pair to represent its code point (U+2008A).
|
||||
private static final String SUPPLEMENTARY_CHAR = "\uD840\uDC8A";
|
||||
private static final String HIRAGANA_WORD = "\u3042\u3044\u3046\u3048\u304A"; // あいうえお
|
||||
private static final String GREEK_WORD = "\u03BA\u03B1\u03B9"; // και
|
||||
|
||||
public void testGetWordRangeAtCursor() {
|
||||
/**
|
||||
* Test logic in getting the word range at the cursor.
|
||||
*/
|
||||
final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(
|
||||
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
|
||||
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).
|
||||
final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
|
||||
final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
|
||||
mSpacingAndPunctuations, StringUtils.toSortedCodePointArray(
|
||||
SUPPLEMENTARY_CHAR_STRING));
|
||||
final String HIRAGANA_WORD = "\u3042\u3044\u3046\u3048\u304A"; // あいうえお
|
||||
final String GREEK_WORD = "\u03BA\u03B1\u03B9"; // και
|
||||
|
||||
ExtractedText et = new ExtractedText();
|
||||
final MockInputMethodService mockInputMethodService = new MockInputMethodService();
|
||||
final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
|
||||
|
@ -249,10 +254,9 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
|
||||
// splitting on supplementary character
|
||||
mockInputMethodService.setInputConnection(
|
||||
new MockConnection("one word" + SUPPLEMENTARY_CHAR + "wo", "rd", et));
|
||||
new MockConnection("one word" + SUPPLEMENTARY_CHAR_STRING + "wo", "rd", et));
|
||||
ic.beginBatchEdit();
|
||||
r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
|
||||
ScriptUtils.SCRIPT_LATIN);
|
||||
r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
|
||||
ic.endBatchEdit();
|
||||
assertTrue(TextUtils.equals("word", r.mWord));
|
||||
|
||||
|
@ -260,8 +264,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
mockInputMethodService.setInputConnection(
|
||||
new MockConnection(HIRAGANA_WORD + "wo", "rd" + GREEK_WORD, et));
|
||||
ic.beginBatchEdit();
|
||||
r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
|
||||
ScriptUtils.SCRIPT_LATIN);
|
||||
r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_LATIN);
|
||||
ic.endBatchEdit();
|
||||
assertTrue(TextUtils.equals("word", r.mWord));
|
||||
|
||||
|
@ -269,8 +272,7 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
mockInputMethodService.setInputConnection(
|
||||
new MockConnection("text" + GREEK_WORD, "text", et));
|
||||
ic.beginBatchEdit();
|
||||
r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR),
|
||||
ScriptUtils.SCRIPT_GREEK);
|
||||
r = ic.getWordRangeAtCursor(SUPPLEMENTARY_CHAR, ScriptUtils.SCRIPT_GREEK);
|
||||
ic.endBatchEdit();
|
||||
assertTrue(TextUtils.equals(GREEK_WORD, r.mWord));
|
||||
}
|
||||
|
@ -286,6 +288,8 @@ public class RichInputConnectionAndTextRangeTests extends AndroidTestCase {
|
|||
}
|
||||
|
||||
private void helpTestGetSuggestionSpansAtWord(final int cursorPos) {
|
||||
final SpacingAndPunctuations SPACE = new SpacingAndPunctuations(
|
||||
mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
|
||||
final MockInputMethodService mockInputMethodService = new MockInputMethodService();
|
||||
final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
|
||||
|
||||
|
|
Loading…
Reference in New Issue