diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index fc9771065..485ec511f 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -82,14 +82,16 @@ public class AutoCorrection { return false; } - public static boolean isValidWordForAutoCorrection( + public static boolean allowsToBeAutoCorrected( Map dictionaries, CharSequence word, boolean ignoreCase) { - final Dictionary whiteList = dictionaries.get(Suggest.DICT_KEY_WHITELIST); + final WhitelistDictionary whitelistDictionary = + (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST); // If "word" is in the whitelist dictionary, it should not be auto corrected. - if (whiteList != null && whiteList.isValidWord(word)) { - return false; + if (whitelistDictionary != null + && whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) { + return true; } - return isValidWord(dictionaries, word, ignoreCase); + return !isValidWord(dictionaries, word, ignoreCase); } private static boolean hasAutoCorrectionForWhitelistedWord(CharSequence whiteListedWord) { @@ -100,8 +102,8 @@ public class AutoCorrection { WordComposer wordComposer, ArrayList suggestions, CharSequence typedWord, int correctionMode) { if (TextUtils.isEmpty(typedWord)) return false; - boolean isValidWord = isValidWordForAutoCorrection(dictionaries, typedWord, false); - return wordComposer.size() > 1 && suggestions.size() > 0 && isValidWord + boolean allowsAutoCorrect = allowsToBeAutoCorrected(dictionaries, typedWord, false); + return wordComposer.size() > 1 && suggestions.size() > 0 && !allowsAutoCorrect && (correctionMode == Suggest.CORRECTION_FULL || correctionMode == Suggest.CORRECTION_FULL_BIGRAM); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 892e5f558..3b311377b 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1635,11 +1635,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); final CharSequence typedWord = wordComposer.getTypedWord(); // Here, we want to promote a whitelisted word if exists. - final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( + // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" + // but still autocorrected from - in the case the whitelist only capitalizes the word. + // The whitelist should be case-insensitive, so it's not possible to be consistent with + // a boolean flag. Right now this is handled with a slight hack in + // WhitelistDictionary#shouldForciblyAutoCorrectFrom. + final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); if (mCorrectionMode == Suggest.CORRECTION_FULL || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { - autoCorrectionAvailable |= typedWordValid; + autoCorrectionAvailable |= (!allowsToBeAutoCorrected); } // Don't auto-correct words with multiple capital letter autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); @@ -1652,9 +1657,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // need to clear the previous state when the user starts typing a word (i.e. typed word's // length == 1). if (typedWord != null) { - if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid + if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) || mSuggestionsView.isShowingAddToDictionaryHint()) { - builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion( + builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( autoCorrectionAvailable); } else { SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index 93474b654..96241a340 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -93,4 +93,20 @@ public class WhitelistDictionary extends Dictionary { if (TextUtils.isEmpty(word)) return false; return !TextUtils.isEmpty(getWhiteListedWord(word.toString())); } + + // See LatinIME#updateSuggestions. This breaks in the (queer) case that the whitelist + // lists that word a should autocorrect to word b, and word c would autocorrect to + // an upper-cased version of a. In this case, the way this return value is used would + // remove the first candidate when the user typed the upper-cased version of A. + // Example : abc -> def and xyz -> Abc + // A user typing Abc would experience it being autocorrected to something else (not + // necessarily def). + // There is no such combination in the whitelist at the time and there probably won't + // ever be - it doesn't make sense. But still. + public boolean shouldForciblyAutoCorrectFrom(CharSequence word) { + if (TextUtils.isEmpty(word)) return false; + final String correction = getWhiteListedWord(word.toString()); + if (TextUtils.isEmpty(correction)) return false; + return !correction.equals(word); + } } diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java index a08933539..464930f4c 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java +++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java @@ -89,7 +89,7 @@ public class SuggestHelper { } public boolean isValidWord(CharSequence typed) { - return AutoCorrection.isValidWordForAutoCorrection(mSuggest.getUnigramDictionaries(), + return AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), typed, false); }