aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java45
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java27
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java23
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java2
-rw-r--r--java/src/com/android/inputmethod/latin/AutoCorrection.java16
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java31
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java6
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java13
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestionsView.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java4
-rw-r--r--java/src/com/android/inputmethod/latin/WhitelistDictionary.java40
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java24
12 files changed, 170 insertions, 71 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 7e71b5f36..4a2542dec 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -19,15 +19,19 @@ package com.android.inputmethod.accessibility;
import android.content.Context;
import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
+import android.media.AudioManager;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.view.inputmethod.EditorInfo;
-import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
import com.android.inputmethod.compat.AccessibilityManagerCompatWrapper;
+import com.android.inputmethod.compat.AudioManagerCompatWrapper;
+import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
+import com.android.inputmethod.latin.R;
public class AccessibilityUtils {
private static final String TAG = AccessibilityUtils.class.getSimpleName();
@@ -37,8 +41,10 @@ public class AccessibilityUtils {
private static final AccessibilityUtils sInstance = new AccessibilityUtils();
+ private Context mContext;
private AccessibilityManager mAccessibilityManager;
private AccessibilityManagerCompatWrapper mCompatManager;
+ private AudioManagerCompatWrapper mAudioManager;
/*
* Setting this constant to {@code false} will disable all keyboard
@@ -67,9 +73,14 @@ public class AccessibilityUtils {
}
private void initInternal(Context context, SharedPreferences prefs) {
+ mContext = context;
mAccessibilityManager = (AccessibilityManager) context
.getSystemService(Context.ACCESSIBILITY_SERVICE);
mCompatManager = new AccessibilityManagerCompatWrapper(mAccessibilityManager);
+
+ final AudioManager audioManager = (AudioManager) context
+ .getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = new AudioManagerCompatWrapper(audioManager);
}
/**
@@ -102,6 +113,22 @@ public class AccessibilityUtils {
}
/**
+ * @return {@code true} if the device should not speak text (eg.
+ * non-control) characters
+ */
+ public boolean shouldObscureInput(EditorInfo attribute) {
+ if (attribute == null)
+ return false;
+
+ // Always speak if the user is listening through headphones.
+ if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn())
+ return false;
+
+ // Don't speak if the IME is connected to a password field.
+ return InputTypeCompatUtils.isPasswordInputType(attribute.inputType);
+ }
+
+ /**
* Sends the specified text to the {@link AccessibilityManager} to be
* spoken.
*
@@ -117,7 +144,7 @@ public class AccessibilityUtils {
// class. Instead, we're just forcing a fake AccessibilityEvent into
// the screen reader to make it speak.
final AccessibilityEvent event = AccessibilityEvent
- .obtain(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER);
+ .obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED);
event.setPackageName(PACKAGE);
event.setClassName(CLASS);
@@ -127,4 +154,18 @@ public class AccessibilityUtils {
mAccessibilityManager.sendAccessibilityEvent(event);
}
+
+ /**
+ * Handles speaking the "connect a headset to hear passwords" notification
+ * when connecting to a password field.
+ *
+ * @param attribute The input connection's editor info attribute.
+ * @param restarting Whether the connection is being restarted.
+ */
+ public void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
+ if (shouldObscureInput(attribute)) {
+ final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
+ speak(text);
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index e1b778126..4c109c708 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -21,7 +21,6 @@ import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Paint;
import android.inputmethodservice.InputMethodService;
-import android.media.AudioManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
@@ -29,8 +28,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
-import com.android.inputmethod.compat.AudioManagerCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
@@ -48,7 +45,6 @@ public class AccessibleKeyboardViewProxy {
private FlickGestureDetector mGestureDetector;
private LatinKeyboardView mView;
private AccessibleKeyboardActionListener mListener;
- private AudioManagerCompatWrapper mAudioManager;
private int mScaledEdgeSlop;
private int mLastHoverKeyIndex = KeyDetector.NOT_A_KEY;
@@ -82,26 +78,6 @@ public class AccessibleKeyboardViewProxy {
mInputMethod = inputMethod;
mGestureDetector = new KeyboardFlickGestureDetector(inputMethod);
mScaledEdgeSlop = ViewConfiguration.get(inputMethod).getScaledEdgeSlop();
-
- final AudioManager audioManager = (AudioManager) inputMethod
- .getSystemService(Context.AUDIO_SERVICE);
- mAudioManager = new AudioManagerCompatWrapper(audioManager);
- }
-
- /**
- * @return {@code true} if the device should not speak text (eg. non-control) characters
- */
- private boolean shouldObscureInput() {
- // Always speak if the user is listening through headphones.
- if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn())
- return false;
-
- final EditorInfo info = mInputMethod.getCurrentInputEditorInfo();
- if (info == null)
- return false;
-
- // Don't speak if the IME is connected to a password field.
- return InputTypeCompatUtils.isPasswordInputType(info.inputType);
}
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event,
@@ -118,7 +94,8 @@ public class AccessibleKeyboardViewProxy {
if (key == null)
break;
- final boolean shouldObscure = shouldObscureInput();
+ final EditorInfo info = mInputMethod.getCurrentInputEditorInfo();
+ final boolean shouldObscure = AccessibilityUtils.getInstance().shouldObscureInput(info);
final CharSequence description = KeyCodeDescriptionMapper.getInstance()
.getDescriptionForKey(mView.getContext(), mView.getKeyboard(), key,
shouldObscure);
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 5c54fa548..876bd65f6 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -24,18 +24,22 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
+import android.util.Log;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Locale;
public class SuggestionSpanUtils {
+ private static final String TAG = SuggestionSpanUtils.class.getSimpleName();
// TODO: Use reflection to get field values
public static final String ACTION_SUGGESTION_PICKED =
"android.text.style.SUGGESTION_PICKED";
public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
+ // TODO: Use the API constant after it gets public.
+ public static final int FLAG_AUTO_CORRECTION = 0x0004;
public static final int SUGGESTION_MAX_SIZE = 5;
public static final boolean SUGGESTION_SPAN_IS_SUPPORTED;
@@ -50,6 +54,25 @@ public class SuggestionSpanUtils {
CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null;
}
+ public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
+ Context context, CharSequence text) {
+ if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null) {
+ return text;
+ }
+ final Spannable spannable = text instanceof Spannable
+ ? (Spannable) text : new SpannableString(text);
+ final Object[] args =
+ { context, null, new String[] {}, FLAG_AUTO_CORRECTION,
+ (Class<?>) SuggestionSpanPickedNotificationReceiver.class };
+ final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args);
+ if (ss == null) {
+ Log.w(TAG, "Suggestion span was not created.");
+ return text;
+ }
+ spannable.setSpan(ss, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return spannable;
+ }
+
public static CharSequence getTextWithSuggestionSpan(Context context,
CharSequence pickedWord, SuggestedWords suggestedWords) {
if (TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 49e92fd2b..83871a602 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -649,7 +649,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
public boolean isVibrateAndSoundFeedbackRequired() {
- return mKeyboardView == null || !mKeyboardView.isInSlidingKeyInput();
+ return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
}
private int getPointerCount() {
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<String, Dictionary> 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<CharSequence> 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 36e97af11..958092bc7 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -693,6 +693,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return;
}
+ // Forward this event to the accessibility utilities, if enabled.
+ final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
+ if (accessUtils.isTouchExplorationEnabled()) {
+ accessUtils.onStartInputViewInternal(attribute, restarting);
+ }
+
mSubtypeSwitcher.updateParametersOnStartInputView();
TextEntryState.reset();
@@ -1259,6 +1265,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
break;
case Keyboard.CODE_CAPSLOCK:
switcher.toggleCapsLock();
+ vibrate();
break;
case Keyboard.CODE_SHORTCUT:
mSubtypeSwitcher.switchToShortcutIME();
@@ -1601,6 +1608,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mKeyboardSwitcher.onAutoCorrectionStateChanged(
words.hasWordAboveAutoCorrectionScoreThreshold());
}
+
+ // Put a blue underline to a word in TextView which will be auto-corrected.
+ final InputConnection ic = getCurrentInputConnection();
+ if (ic != null && Utils.willAutoCorrect(words)) {
+ final CharSequence textWithUnderline =
+ SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
+ this, mComposingStringBuilder);
+ if (!TextUtils.isEmpty(textWithUnderline)) {
+ ic.setComposingText(textWithUnderline, 1);
+ }
+ }
}
public void updateSuggestions() {
@@ -1634,11 +1652,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();
@@ -1651,9 +1674,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/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index f6f55819d..caa5aac51 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -67,10 +67,10 @@ public class Suggest implements Dictionary.WordCallback {
public static final int DIC_USER_UNIGRAM = 3;
public static final int DIC_CONTACTS = 4;
public static final int DIC_USER_BIGRAM = 5;
+ public static final int DIC_WHITELIST = 6;
// If you add a type of dictionary, increment DIC_TYPE_LAST_ID
// TODO: this value seems unused. Remove it?
- public static final int DIC_TYPE_LAST_ID = 5;
-
+ public static final int DIC_TYPE_LAST_ID = 6;
public static final String DICT_KEY_MAIN = "main";
public static final String DICT_KEY_CONTACTS = "contacts";
// User dictionary, the system-managed one.
@@ -360,7 +360,7 @@ public class Suggest implements Dictionary.WordCallback {
final String typedWordString = typedWord == null ? null : typedWord.toString();
CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase, mIsFirstCharCapitalized,
- mWhiteListDictionary.getWhiteListedWord(typedWordString));
+ mWhiteListDictionary.getWhitelistedWord(typedWordString));
mAutoCorrection.updateAutoCorrectionStatus(mUnigramDictionaries, wordComposer,
mSuggestions, mScores, typedWord, mAutoCorrectionThreshold, mCorrectionMode,
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index b177d144a..005db36bd 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -175,6 +175,19 @@ public class SuggestedWords {
public CharSequence getWord(int pos) {
return mWords.get(pos);
}
+
+ public String toString() {
+ // Pretty-print method to help debug
+ final StringBuilder sb = new StringBuilder("StringBuilder: mTypedWordValid = "
+ + mTypedWordValid + " ; mHasMinimalSuggestion = " + mHasMinimalSuggestion
+ + " ; mIsPunctuationSuggestions = " + mIsPunctuationSuggestions
+ + " --- ");
+ for (CharSequence s : mWords) {
+ sb.append(s);
+ sb.append(" ; ");
+ }
+ return sb.toString();
+ }
}
public static class SuggestedWordInfo {
diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/SuggestionsView.java
index fe54f4ae1..3271b8253 100644
--- a/java/src/com/android/inputmethod/latin/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/SuggestionsView.java
@@ -260,7 +260,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private CharSequence getStyledSuggestionWord(SuggestedWords suggestions, int pos) {
final CharSequence word = suggestions.getWord(pos);
- final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
+ final boolean isAutoCorrect = pos == 1 && Utils.willAutoCorrect(suggestions);
final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid;
if (!isAutoCorrect && !isTypedWordValid)
return word;
@@ -278,14 +278,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
return spannedWord;
}
- private static boolean willAutoCorrect(SuggestedWords suggestions) {
- return !suggestions.mTypedWordValid && suggestions.mHasMinimalSuggestion;
- }
-
private int getWordPosition(int index, SuggestedWords suggestions) {
// TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
// suggestions.
- final int centerPos = willAutoCorrect(suggestions) ? 1 : 0;
+ final int centerPos = Utils.willAutoCorrect(suggestions) ? 1 : 0;
if (index == mCenterSuggestionIndex) {
return centerPos;
} else if (index == centerPos) {
@@ -300,7 +296,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
final boolean isSuggested = (pos != 0);
final int color;
- if (index == mCenterSuggestionIndex && willAutoCorrect(suggestions)) {
+ if (index == mCenterSuggestionIndex && Utils.willAutoCorrect(suggestions)) {
color = mColorAutoCorrect;
} else if (isSuggested) {
color = mColorSuggested;
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 771276567..de2930460 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -790,4 +790,8 @@ public class Utils {
}
return -1;
}
+
+ public static boolean willAutoCorrect(SuggestedWords suggestions) {
+ return !suggestions.mTypedWordValid && suggestions.mHasMinimalSuggestion;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
index 93474b654..a90ef290b 100644
--- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
+++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
@@ -22,12 +22,10 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
-import com.android.inputmethod.keyboard.ProximityInfo;
-
import java.util.HashMap;
import java.util.Locale;
-public class WhitelistDictionary extends Dictionary {
+public class WhitelistDictionary extends ExpandableDictionary {
private static final boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = WhitelistDictionary.class.getSimpleName();
@@ -35,12 +33,12 @@ public class WhitelistDictionary extends Dictionary {
private final HashMap<String, Pair<Integer, String>> mWhitelistWords =
new HashMap<String, Pair<Integer, String>>();
+ // TODO: Conform to the async load contact of ExpandableDictionary
public WhitelistDictionary(final Context context, final Locale locale) {
+ super(context, Suggest.DIC_WHITELIST);
final Resources res = context.getResources();
final Locale previousLocale = LocaleUtils.setSystemLocale(res, locale);
- if (context != null) {
- initWordlist(context.getResources().getStringArray(R.array.wordlist_whitelist));
- }
+ initWordlist(res.getStringArray(R.array.wordlist_whitelist));
LocaleUtils.setSystemLocale(res, previousLocale);
}
@@ -61,6 +59,7 @@ public class WhitelistDictionary extends Dictionary {
if (before != null && after != null) {
mWhitelistWords.put(
before.toLowerCase(), new Pair<Integer, String>(score, after));
+ addWord(after, score);
}
}
} catch (NumberFormatException e) {
@@ -70,27 +69,34 @@ public class WhitelistDictionary extends Dictionary {
}
}
- public String getWhiteListedWord(String before) {
+ public String getWhitelistedWord(String before) {
if (before == null) return null;
final String lowerCaseBefore = before.toLowerCase();
if(mWhitelistWords.containsKey(lowerCaseBefore)) {
if (DBG) {
- Log.d(TAG, "--- found whiteListedWord: " + lowerCaseBefore);
+ Log.d(TAG, "--- found whitelistedWord: " + lowerCaseBefore);
}
return mWhitelistWords.get(lowerCaseBefore).second;
}
return null;
}
- // Not used for WhitelistDictionary. We use getWhitelistedWord() in Suggest.java instead
- @Override
- public void getWords(final WordComposer composer, final WordCallback callback,
- final ProximityInfo proximityInfo) {
- }
-
- @Override
- public boolean isValidWord(CharSequence word) {
+ // 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;
- return !TextUtils.isEmpty(getWhiteListedWord(word.toString()));
+ final String correction = getWhitelistedWord(word.toString());
+ if (TextUtils.isEmpty(correction)) return false;
+ return !correction.equals(word);
}
+
+ // Leave implementation of getWords and isValidWord to the superclass.
+ // The words have been added to the ExpandableDictionary with addWord() inside initWordlist.
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 4d569b808..f9e6a5e68 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -37,6 +37,7 @@ import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.WhitelistDictionary;
import com.android.inputmethod.latin.WordComposer;
import java.util.ArrayList;
@@ -79,6 +80,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
private Map<String, Dictionary> mUserDictionaries =
Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ private Map<String, Dictionary> mWhitelistDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, Dictionary>());
// The threshold for a candidate to be offered as a suggestion.
private double mSuggestionThreshold;
@@ -253,12 +256,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
final Map<String, Dictionary> oldUserDictionaries = mUserDictionaries;
mUserDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ final Map<String, Dictionary> oldWhitelistDictionaries = mWhitelistDictionaries;
+ mWhitelistDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
for (DictionaryPool pool : oldPools.values()) {
pool.close();
}
for (Dictionary dict : oldUserDictionaries.values()) {
dict.close();
}
+ for (Dictionary dict : oldWhitelistDictionaries.values()) {
+ dict.close();
+ }
return false;
}
@@ -280,12 +288,18 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId,
USE_FULL_EDIT_DISTANCE_FLAG_ARRAY);
final String localeStr = locale.toString();
- Dictionary userDict = mUserDictionaries.get(localeStr);
- if (null == userDict) {
- userDict = new SynchronouslyLoadedUserDictionary(this, localeStr, true);
- mUserDictionaries.put(localeStr, userDict);
+ Dictionary userDictionary = mUserDictionaries.get(localeStr);
+ if (null == userDictionary) {
+ userDictionary = new SynchronouslyLoadedUserDictionary(this, localeStr, true);
+ mUserDictionaries.put(localeStr, userDictionary);
+ }
+ dictionaryCollection.addDictionary(userDictionary);
+ Dictionary whitelistDictionary = mWhitelistDictionaries.get(localeStr);
+ if (null == whitelistDictionary) {
+ whitelistDictionary = new WhitelistDictionary(this, locale);
+ mWhitelistDictionaries.put(localeStr, whitelistDictionary);
}
- dictionaryCollection.addDictionary(userDict);
+ dictionaryCollection.addDictionary(whitelistDictionary);
return new DictAndProximity(dictionaryCollection, proximityInfo);
}