diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
10 files changed, 385 insertions, 160 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index af08742d3..b6035e15e 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -42,6 +42,7 @@ public class BinaryDictionary extends Dictionary { private static final int TYPED_LETTER_MULTIPLIER = 2; + private static final BinaryDictionary sInstance = new BinaryDictionary(); private int mDicTypeId; private int mNativeDict; private long mDictLength; @@ -59,16 +60,24 @@ public class BinaryDictionary extends Dictionary { } } + private BinaryDictionary() { + } + /** - * Create a dictionary from a raw resource file + * Initialize a dictionary from a raw resource file * @param context application context for reading resources * @param resId the resource containing the raw binary dictionary + * @return initialized instance of BinaryDictionary */ - public BinaryDictionary(Context context, int resId, int dicTypeId) { - if (resId != 0) { - loadDictionary(context, resId); + public static BinaryDictionary initDictionary(Context context, int resId, int dicTypeId) { + synchronized (sInstance) { + sInstance.closeInternal(); + if (resId != 0) { + sInstance.loadDictionary(context, resId); + sInstance.mDicTypeId = dicTypeId; + } } - mDicTypeId = dicTypeId; + return sInstance; } private native int openNative(String sourceDir, long dictOffset, long dictSize, @@ -104,6 +113,8 @@ public class BinaryDictionary extends Dictionary { @Override public void getBigrams(final WordComposer codes, final CharSequence previousWord, final WordCallback callback, int[] nextLettersFrequencies) { + if (mNativeDict == 0) return; + char[] chars = previousWord.toString().toCharArray(); Arrays.fill(mOutputChars_bigrams, (char) 0); Arrays.fill(mFrequencies_bigrams, 0); @@ -135,6 +146,8 @@ public class BinaryDictionary extends Dictionary { @Override public void getWords(final WordComposer codes, final WordCallback callback, int[] nextLettersFrequencies) { + if (mNativeDict == 0) return; + final int codesSize = codes.size(); // Won't deal with really long words. if (codesSize > MAX_WORD_LENGTH - 1) return; @@ -179,6 +192,10 @@ public class BinaryDictionary extends Dictionary { @Override public synchronized void close() { + closeInternal(); + } + + private void closeInternal() { if (mNativeDict != 0) { closeNative(mNativeDict); mNativeDict = 0; @@ -188,7 +205,10 @@ public class BinaryDictionary extends Dictionary { @Override protected void finalize() throws Throwable { - close(); - super.finalize(); + try { + closeInternal(); + } finally { + super.finalize(); + } } } diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index 30f4a59f9..d2d1f22dd 100644 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -45,23 +45,22 @@ import android.widget.TextView; import java.util.ArrayList; public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener { - private LatinIME mService; - private final ArrayList<View> mWords = new ArrayList<View>(); - private final TextView mPreviewText; - private final PopupWindow mPreviewPopup; - + private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); + private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); private static final int MAX_SUGGESTIONS = 16; + private final ArrayList<View> mWords = new ArrayList<View>(); private final boolean mConfigCandidateHighlightFontColorEnabled; + private final CharacterStyle mInvertedForegroundColorSpan; + private final CharacterStyle mInvertedBackgroundColorSpan; private final int mColorNormal; private final int mColorRecommended; private final int mColorOther; - private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); - private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); - private final CharacterStyle mInvertedForegroundColorSpan; - private final CharacterStyle mInvertedBackgroundColorSpan; + private final PopupWindow mPreviewPopup; + private final TextView mPreviewText; + private LatinIME mService; private SuggestedWords mSuggestions = SuggestedWords.EMPTY; private boolean mShowingAutoCorrectionInverted; private boolean mShowingAddToDictionary; @@ -186,9 +185,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final TextView tv = (TextView)v.findViewById(R.id.candidate_word); final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info); tv.setTextColor(mColorNormal); + // TODO: Needs safety net? if (suggestions.mHasMinimalSuggestion - && ((i == 1 && !suggestions.mTypedWordValid) || - (i == 0 && suggestions.mTypedWordValid))) { + && ((i == 1 && !suggestions.mTypedWordValid) + || (i == 0 && suggestions.mTypedWordValid))) { final CharacterStyle style; if (mConfigCandidateHighlightFontColorEnabled) { style = BOLD_SPAN; @@ -329,7 +329,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mService.pickSuggestionManually(index, word); } } - + @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java index faee38eda..a9f2c2c22 100644 --- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java @@ -107,7 +107,7 @@ public class InputLanguageSelection extends PreferenceActivity { res.updateConfiguration(conf, res.getDisplayMetrics()); int mainDicResId = LatinIME.getMainDictionaryResourceId(res); - BinaryDictionary bd = new BinaryDictionary(this, mainDicResId, Suggest.DIC_MAIN); + BinaryDictionary bd = BinaryDictionary.initDictionary(this, mainDicResId, Suggest.DIC_MAIN); // Is the dictionary larger than a placeholder? Arbitrarily chose a lower limit of // 4000-5000 words, whereas the LARGE_DICTIONARY is about 20000+ words. diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index ad7e4708a..b6042c769 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -22,6 +22,7 @@ import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.LatinKeyboard; import com.android.inputmethod.keyboard.LatinKeyboardView; import com.android.inputmethod.latin.Utils.RingCharBuffer; import com.android.inputmethod.voice.VoiceIMEConnector; @@ -132,14 +133,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private Resources mResources; private SharedPreferences mPrefs; + // These variables are initialized according to the {@link EditorInfo#inputType}. + private boolean mAutoSpace; + private boolean mInputTypeNoAutoCorrect; + private boolean mIsSettingsSuggestionStripOn; + private boolean mApplicationSpecifiedCompletionOn; + private final StringBuilder mComposing = new StringBuilder(); private WordComposer mWord = new WordComposer(); private CharSequence mBestWord; private boolean mHasValidSuggestions; - private boolean mIsSettingsSuggestionStripOn; - private boolean mApplicationSpecifiedCompletionOn; private boolean mHasDictionary; - private boolean mAutoSpace; private boolean mJustAddedAutoSpace; private boolean mAutoCorrectEnabled; private boolean mReCorrectionEnabled; @@ -151,6 +155,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean mAutoCap; private boolean mQuickFixes; private boolean mConfigSwipeDownDismissKeyboardEnabled; + private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; + private int mConfigDurationOfFadeoutLanguageOnSpacebar; + private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; private int mCorrectionMode; private int mCommittedLength; @@ -160,9 +167,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private int mLastSelectionEnd; private SuggestedWords mSuggestPuncList; - // Input type is such that we should not auto-correct - private boolean mInputTypeNoAutoCorrect; - // Indicates whether the suggestion strip is to be on in landscape private boolean mJustAccepted; private boolean mJustReverted; @@ -241,9 +245,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1; private static final int MSG_UPDATE_SHIFT_STATE = 2; private static final int MSG_VOICE_RESULTS = 3; + private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; + private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; @Override public void handleMessage(Message msg) { + final KeyboardSwitcher switcher = mKeyboardSwitcher; + final LatinKeyboardView inputView = switcher.getInputView(); switch (msg.what) { case MSG_UPDATE_SUGGESTIONS: updateSuggestions(); @@ -252,12 +260,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen setOldSuggestions(); break; case MSG_UPDATE_SHIFT_STATE: - mKeyboardSwitcher.updateShiftState(); + switcher.updateShiftState(); break; case MSG_VOICE_RESULTS: mVoiceConnector.handleVoiceResults(preferCapitalization() - || (mKeyboardSwitcher.isAlphabetMode() - && mKeyboardSwitcher.isShiftedOrShiftLocked())); + || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); + break; + case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: + if (inputView != null) + inputView.setSpacebarTextFadeFactor( + (1.0f + mConfigFinalFadeoutFactorOfLanguageOnSpacebar) / 2, + (LatinKeyboard)msg.obj); + sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), + mConfigDurationOfFadeoutLanguageOnSpacebar); + break; + case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: + if (inputView != null) + inputView.setSpacebarTextFadeFactor( + mConfigFinalFadeoutFactorOfLanguageOnSpacebar, (LatinKeyboard)msg.obj); break; } } @@ -297,6 +317,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void updateVoiceResults() { sendMessage(obtainMessage(MSG_VOICE_RESULTS)); } + + public void startDisplayLanguageOnSpacebar(boolean localeChanged) { + removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); + removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); + final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + if (inputView != null) { + final LatinKeyboard keyboard = inputView.getLatinKeyboard(); + // The language is never displayed when the delay is zero. + if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0) + inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f + : mConfigFinalFadeoutFactorOfLanguageOnSpacebar, keyboard); + // The language is always displayed when the delay is negative. + if (localeChanged && mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) { + sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), + mConfigDelayBeforeFadeoutLanguageOnSpacebar); + } + } + } } @Override @@ -315,10 +353,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Resources res = getResources(); mResources = res; - mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, - res.getBoolean(R.bool.default_recorrection_enabled)); + + // If the option should not be shown, do not read the recorrection preference + // but always use the default setting defined in the resources. + if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) { + mReCorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED, + res.getBoolean(R.bool.default_recorrection_enabled)); + } else { + mReCorrectionEnabled = res.getBoolean(R.bool.default_recorrection_enabled); + } + mConfigSwipeDownDismissKeyboardEnabled = res.getBoolean( R.bool.config_swipe_down_dismiss_keyboard_enabled); + mConfigDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( + R.integer.config_delay_before_fadeout_language_on_spacebar); + mConfigDurationOfFadeoutLanguageOnSpacebar = res.getInteger( + R.integer.config_duration_of_fadeout_language_on_spacebar); + mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( + R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; Utils.GCUtils.getInstance().reset(); boolean tryGC = true; @@ -360,7 +412,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSuggest.close(); } final SharedPreferences prefs = mPrefs; - mQuickFixes = prefs.getBoolean(Settings.PREF_QUICK_FIXES, true); + mQuickFixes = isQuickFixesEnabled(prefs); final Resources res = mResources; int mainDicResId = getMainDictionaryResourceId(res); @@ -402,27 +454,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void onConfigurationChanged(Configuration conf) { mSubtypeSwitcher.onConfigurationChanged(conf); - if (mSubtypeSwitcher.isKeyboardMode()) - onKeyboardLanguageChanged(); - updateAutoTextEnabled(); - // If orientation changed while predicting, commit the change if (conf.orientation != mOrientation) { InputConnection ic = getCurrentInputConnection(); commitTyped(ic); if (ic != null) ic.finishComposingText(); // For voice input mOrientation = conf.orientation; - final int mode = mKeyboardSwitcher.getKeyboardMode(); - final EditorInfo attribute = getCurrentInputEditorInfo(); - final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; - mKeyboardSwitcher.loadKeyboard(mode, imeOptions, - mVoiceConnector.isVoiceButtonEnabled(), - mVoiceConnector.isVoiceButtonOnPrimary()); } mConfigurationChanging = true; super.onConfigurationChanged(conf); - mVoiceConnector.onConfigurationChanged(mConfigurationChanging); + mVoiceConnector.onConfigurationChanged(conf); mConfigurationChanging = false; } @@ -473,24 +515,62 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mRefreshKeyboardRequired) { mRefreshKeyboardRequired = false; - onKeyboardLanguageChanged(); + onRefreshKeyboard(); } TextEntryState.newSession(this); - // Most such things we decide below in the switch statement, but we need to know - // now whether this is a password text field, because we need to know now (before - // the switch statement) whether we want to enable the voice button. - int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION; - mVoiceConnector.resetVoiceStates(isPasswordVariation(variation)); + // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to + // know now whether this is a password text field, because we need to know now whether we + // want to enable the voice button. + mVoiceConnector.resetVoiceStates(isPasswordVariation( + attribute.inputType & InputType.TYPE_MASK_VARIATION)); + + final int mode = initializeInputAttributesAndGetMode(attribute.inputType); + + inputView.closing(); + mEnteredText = null; + mComposing.setLength(0); + mHasValidSuggestions = false; + mDeleteCount = 0; + mJustAddedAutoSpace = false; + + loadSettings(attribute); + if (mSubtypeSwitcher.isKeyboardMode()) { + switcher.loadKeyboard(mode, attribute.imeOptions, + mVoiceConnector.isVoiceButtonEnabled(), + mVoiceConnector.isVoiceButtonOnPrimary()); + switcher.updateShiftState(); + } + + setCandidatesViewShownInternal(isCandidateStripVisible(), + false /* needsInputViewShown */ ); + // Delay updating suggestions because keyboard input view may not be shown at this point. + mHandler.postUpdateSuggestions(); + + updateCorrectionMode(); + + inputView.setPreviewEnabled(mPopupOn); + inputView.setProximityCorrectionEnabled(true); + // If we just entered a text field, maybe it has some old text that requires correction + checkReCorrectionOnStart(); + inputView.setForeground(true); + + mVoiceConnector.onStartInputView(inputView.getWindowToken()); + + if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); + } + + private int initializeInputAttributesAndGetMode(int inputType) { + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + mAutoSpace = false; mInputTypeNoAutoCorrect = false; mIsSettingsSuggestionStripOn = false; mApplicationSpecifiedCompletionOn = false; mApplicationSpecifiedCompletions = null; - mEnteredText = null; final int mode; - switch (attribute.inputType & InputType.TYPE_MASK_CLASS) { + switch (inputType & InputType.TYPE_MASK_CLASS) { case InputType.TYPE_CLASS_NUMBER: case InputType.TYPE_CLASS_DATETIME: mode = KeyboardId.MODE_NUMBER; @@ -525,7 +605,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mode = KeyboardId.MODE_WEB; // If it's a browser edit field and auto correct is not ON explicitly, then // disable auto correction, but keep suggestions on. - if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { mInputTypeNoAutoCorrect = true; } } else { @@ -533,16 +613,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // If NO_SUGGESTIONS is set, don't do prediction. - if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { + if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { mIsSettingsSuggestionStripOn = false; mInputTypeNoAutoCorrect = true; } // If it's not multiline and the autoCorrect flag is not set, then don't correct - if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && - (attribute.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && + (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { mInputTypeNoAutoCorrect = true; } - if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { + if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { mIsSettingsSuggestionStripOn = false; mApplicationSpecifiedCompletionOn = isFullscreenMode(); } @@ -551,40 +631,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mode = KeyboardId.MODE_TEXT; break; } - inputView.closing(); - mComposing.setLength(0); - mHasValidSuggestions = false; - mDeleteCount = 0; - mJustAddedAutoSpace = false; - - loadSettings(attribute); - if (mSubtypeSwitcher.isKeyboardMode()) { - switcher.loadKeyboard(mode, attribute.imeOptions, - mVoiceConnector.isVoiceButtonEnabled(), - mVoiceConnector.isVoiceButtonOnPrimary()); - switcher.updateShiftState(); - } - - setCandidatesViewShownInternal(isCandidateStripVisible(), - false /* needsInputViewShown */ ); - // Delay updating suggestions because keyboard input view may not be shown at this point. - mHandler.postUpdateSuggestions(); - - // If the dictionary is not big enough, don't auto correct - mHasDictionary = mSuggest.hasMainDictionary(); - - updateCorrectionMode(); - - inputView.setPreviewEnabled(mPopupOn); - inputView.setProximityCorrectionEnabled(true); - mIsSettingsSuggestionStripOn &= (mCorrectionMode > 0 || isShowingSuggestionsStrip()); - // If we just entered a text field, maybe it has some old text that requires correction - checkReCorrectionOnStart(); - inputView.setForeground(true); - - mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken()); - - if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); + return mode; } private void checkReCorrectionOnStart() { @@ -1106,14 +1153,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void handleBackspace() { if (mVoiceConnector.logAndRevertVoiceInput()) return; - boolean deleteChar = false; - InputConnection ic = getCurrentInputConnection(); - if (ic == null) return; + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; ic.beginBatchEdit(); mVoiceConnector.handleBackspace(); + boolean deleteChar = false; if (mHasValidSuggestions) { final int length = mComposing.length(); if (length > 0) { @@ -1131,12 +1178,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen deleteChar = true; } mHandler.postUpdateShiftKeyState(); + TextEntryState.backspace(); if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) { revertLastWord(deleteChar); ic.endBatchEdit(); return; - } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { + } + + if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { ic.deleteSurroundingText(mEnteredText.length(), 0); } else if (deleteChar) { if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { @@ -1355,7 +1405,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private boolean isSuggestionsRequested() { - return mIsSettingsSuggestionStripOn; + return mIsSettingsSuggestionStripOn + && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); } private boolean isShowingPunctuationList() { @@ -1491,7 +1542,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { setSuggestions(suggestedWords); if (suggestedWords.size() > 0) { - if (suggestedWords.hasAutoCorrectionWord()) { + if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords)) { + mBestWord = typedWord; + } else if (suggestedWords.hasAutoCorrectionWord()) { mBestWord = suggestedWords.getWord(1); } else { mBestWord = typedWord; @@ -1773,18 +1826,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int length = mComposing.length(); if (!mHasValidSuggestions && length > 0) { final InputConnection ic = getCurrentInputConnection(); - mHasValidSuggestions = true; mJustReverted = true; + final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); if (deleteChar) ic.deleteSurroundingText(1, 0); int toDelete = mCommittedLength; - CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); - if (toTheLeft != null && toTheLeft.length() > 0 - && isWordSeparator(toTheLeft.charAt(0))) { + final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); + if (!TextUtils.isEmpty(toTheLeft) && isWordSeparator(toTheLeft.charAt(0))) { toDelete--; } ic.deleteSurroundingText(toDelete, 0); - ic.setComposingText(mComposing, 1); - TextEntryState.backspace(); + // Re-insert punctuation only when the deleted character was word separator and the + // composing text wasn't equal to the auto-corrected text. + if (deleteChar + && !TextUtils.isEmpty(punctuation) && isWordSeparator(punctuation.charAt(0)) + && !TextUtils.equals(mComposing, toTheLeft)) { + ic.commitText(mComposing, 1); + TextEntryState.acceptedTyped(mComposing); + ic.commitText(punctuation, 1); + TextEntryState.typedCharacter(punctuation.charAt(0), true); + // Clear composing text + mComposing.setLength(0); + } else { + mHasValidSuggestions = true; + ic.setComposingText(mComposing, 1); + TextEntryState.backspace(); + } mHandler.postUpdateSuggestions(); } else { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); @@ -1814,21 +1880,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return mWord.isFirstCharCapitalized(); } - // Notify that Language has been changed and toggleLanguage will update KeyboaredID according - // to new Language. - public void onKeyboardLanguageChanged() { + // Notify that language or mode have been changed and toggleLanguage will update KeyboaredID + // according to new language or mode. + public void onRefreshKeyboard() { toggleLanguage(true, true); } // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. private void toggleLanguage(boolean reset, boolean next) { - if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) { mSubtypeSwitcher.toggleLanguage(reset, next); } // Reload keyboard because the current language has been changed. KeyboardSwitcher switcher = mKeyboardSwitcher; - final int mode = switcher.getKeyboardMode(); final EditorInfo attribute = getCurrentInputEditorInfo(); + final int mode = initializeInputAttributesAndGetMode((attribute != null) + ? attribute.inputType : 0); final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; switcher.loadKeyboard(mode, imeOptions, mVoiceConnector.isVoiceButtonEnabled(), mVoiceConnector.isVoiceButtonOnPrimary()); @@ -2016,7 +2083,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mPopupOn = prefs.getBoolean(Settings.PREF_POPUP_ON, mResources.getBoolean(R.bool.config_default_popup_preview)); mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); - mQuickFixes = prefs.getBoolean(Settings.PREF_QUICK_FIXES, true); + mQuickFixes = isQuickFixesEnabled(prefs); mAutoCorrectEnabled = isAutoCorrectEnabled(prefs); mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs); @@ -2065,6 +2132,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mSuggest.setAutoCorrectionThreshold(autoCorrectionThreshold); } + private boolean isQuickFixesEnabled(SharedPreferences sp) { + final boolean showQuickFixesOption = mResources.getBoolean( + R.bool.config_enable_quick_fixes_option); + if (!showQuickFixesOption) { + return isAutoCorrectEnabled(sp); + } + return sp.getBoolean(Settings.PREF_QUICK_FIXES, mResources.getBoolean( + R.bool.config_default_quick_fixes)); + } + private boolean isAutoCorrectEnabled(SharedPreferences sp) { final String currentAutoCorrectionSetting = sp.getString( Settings.PREF_AUTO_CORRECTION_THRESHOLD, @@ -2075,8 +2152,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } private boolean isBigramSuggestionEnabled(SharedPreferences sp) { - // TODO: Define default value instead of 'true'. - return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, true); + final boolean showBigramSuggestionsOption = mResources.getBoolean( + R.bool.config_enable_bigram_suggestions_option); + if (!showBigramSuggestionsOption) { + return isAutoCorrectEnabled(sp); + } + return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, mResources.getBoolean( + R.bool.config_default_bigram_suggestions)); } private void initSuggestPuncList() { diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index d3fb23baf..c78e6dd07 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at @@ -48,6 +48,7 @@ public class Settings extends PreferenceActivity DialogInterface.OnDismissListener, OnPreferenceClickListener { private static final String TAG = "Settings"; + public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings"; public static final String PREF_VIBRATE_ON = "vibrate_on"; public static final String PREF_SOUND_ON = "sound_on"; public static final String PREF_POPUP_ON = "popup_on"; @@ -65,6 +66,8 @@ public class Settings extends PreferenceActivity public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; + public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + // Dialog ids private static final int VOICE_INPUT_CONFIRM_DIALOG = 0; @@ -111,30 +114,64 @@ public class Settings extends PreferenceActivity mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS); ensureConsistencyOfAutoCorrectionSettings(); + final PreferenceGroup generalSettings = + (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY); + final PreferenceGroup textCorrectionGroup = + (PreferenceGroup) findPreference(PREF_PREDICTION_SETTINGS_KEY); + final boolean showSettingsKeyOption = getResources().getBoolean( R.bool.config_enable_show_settings_key_option); if (!showSettingsKeyOption) { - getPreferenceScreen().removePreference(mSettingsKeyPreference); + generalSettings.removePreference(mSettingsKeyPreference); } final boolean showVoiceKeyOption = getResources().getBoolean( R.bool.config_enable_show_voice_key_option); if (!showVoiceKeyOption) { - getPreferenceScreen().removePreference(mVoicePreference); + generalSettings.removePreference(mVoicePreference); } Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); if (vibrator == null // @@@ || !vibrator.hasVibrator() ) { - getPreferenceScreen().removePreference( - getPreferenceScreen().findPreference(PREF_VIBRATE_ON)); + generalSettings.removePreference(findPreference(PREF_VIBRATE_ON)); } final boolean showSubtypeSettings = getResources().getBoolean( R.bool.config_enable_show_subtype_settings); if (!showSubtypeSettings) { - getPreferenceScreen().removePreference(findPreference(PREF_SUBTYPES)); + generalSettings.removePreference(findPreference(PREF_SUBTYPES)); + } + + final boolean showPopupOption = getResources().getBoolean( + R.bool.config_enable_show_popup_on_keypress_option); + if (!showPopupOption) { + generalSettings.removePreference(findPreference(PREF_POPUP_ON)); + } + + final boolean showRecorrectionOption = getResources().getBoolean( + R.bool.config_enable_show_recorrection_option); + if (!showRecorrectionOption) { + generalSettings.removePreference(findPreference(PREF_RECORRECTION_ENABLED)); + } + + final boolean showQuickFixesOption = getResources().getBoolean( + R.bool.config_enable_quick_fixes_option); + if (!showQuickFixesOption) { + textCorrectionGroup.removePreference(findPreference(PREF_QUICK_FIXES)); + } + + final boolean showBigramSuggestionsOption = getResources().getBoolean( + R.bool.config_enable_bigram_suggestions_option); + if (!showBigramSuggestionsOption) { + textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_SUGGESTIONS)); + } + + final boolean showUsabilityModeStudyOption = getResources().getBoolean( + R.bool.config_enable_usability_study_mode_option); + if (!showUsabilityModeStudyOption) { + getPreferenceScreen().removePreference(findPreference(PREF_USABILITY_STUDY_MODE)); } } @@ -184,7 +221,7 @@ public class Settings extends PreferenceActivity if (pref == mInputLanguageSelection) { final String action; if (android.os.Build.VERSION.SDK_INT - >= /* android.os.Build.VERSION_CODES.HONEYCOMB */ 10) { + >= /* android.os.Build.VERSION_CODES.HONEYCOMB */ 11) { action = "android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER"; } else { action = "com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION"; diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java new file mode 100644 index 000000000..917521c40 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.content.Context; +import android.content.res.Resources; + +import java.util.Locale; + +public class SubtypeLocale { + private static String[] sExceptionKeys; + private static String[] sExceptionValues; + + private SubtypeLocale() { + // Intentional empty constructor for utility class. + } + + public static void init(Context context) { + final Resources res = context.getResources(); + sExceptionKeys = res.getStringArray(R.array.subtype_locale_exception_keys); + sExceptionValues = res.getStringArray(R.array.subtype_locale_exception_values); + } + + public static String getFullDisplayName(Locale locale) { + String localeCode = locale.toString(); + for (int index = 0; index < sExceptionKeys.length; index++) { + if (sExceptionKeys[index].equals(localeCode)) + return sExceptionValues[index]; + } + return locale.getDisplayName(locale); + } +} diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index cb676fa00..6666c8e15 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -41,11 +41,6 @@ import java.util.Locale; import java.util.Map; public class SubtypeSwitcher { - // TODO: This should be configurable by resource - // This flag indicates if we support language switching by swipe on space bar. - // We may or may not draw the current language on space bar regardless of this flag. - // @@@ - public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = true; private static final boolean DBG = false; private static final String TAG = "SubtypeSwitcher"; @@ -64,6 +59,8 @@ public class SubtypeSwitcher { new ArrayList<InputMethodSubtype>(); private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>(); + private boolean mConfigUseSpacebarLanguageSwitcher; + /*-----------------------------------------------------------*/ // Variants which should be changed only by reload functions. private boolean mNeedsToDisplayLanguage; @@ -85,11 +82,9 @@ public class SubtypeSwitcher { public static void init(LatinIME service, SharedPreferences prefs) { sInstance.mPrefs = prefs; sInstance.resetParams(service); - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - sInstance.initLanguageSwitcher(service); - } - sInstance.updateAllParameters(); + + SubtypeLocale.init(service); } private SubtypeSwitcher() { @@ -110,6 +105,10 @@ public class SubtypeSwitcher { mAllEnabledSubtypesOfCurrentInputMethod = null; // TODO: Voice input should be created here mVoiceInput = null; + mConfigUseSpacebarLanguageSwitcher = mResources.getBoolean( + R.bool.config_use_spacebar_language_switcher); + if (mConfigUseSpacebarLanguageSwitcher) + initLanguageSwitcher(service); } // Update all parameters stored in SubtypeSwitcher. @@ -123,8 +122,8 @@ public class SubtypeSwitcher { // Update parameters which are changed outside LatinIME. This parameters affect UI so they // should be updated every time onStartInputview. public void updateParametersOnStartInputView() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - updateForSpaceBarLanguageSwitch(); + if (mConfigUseSpacebarLanguageSwitcher) { + updateForSpacebarLanguageSwitch(); } else { updateEnabledSubtypes(); } @@ -135,7 +134,7 @@ public class SubtypeSwitcher { private void updateEnabledSubtypes() { boolean foundCurrentSubtypeBecameDisabled = true; // @@@ mAllEnabledSubtypesOfCurrentInputMethod = mImm.getEnabledInputMethodSubtypeList( - //null, false); + // null, true); mEnabledLanguagesOfCurrentInputMethod.clear(); mEnabledKeyboardSubtypesOfCurrentInputMethod.clear(); for (InputMethodSubtype ims: mAllEnabledSubtypesOfCurrentInputMethod) { @@ -156,6 +155,7 @@ public class SubtypeSwitcher { && mIsSystemLanguageSameAsInputLanguage); if (foundCurrentSubtypeBecameDisabled) { if (DBG) { + Log.w(TAG, "Current subtype: " + mInputLocaleStr + ", " + mMode); Log.w(TAG, "Last subtype was disabled. Update to the current one."); } // @@@ updateSubtype(mImm.getCurrentInputMethodSubtype()); @@ -189,7 +189,7 @@ public class SubtypeSwitcher { // fallback to the default locale and mode. Log.w(TAG, "Couldn't get the current subtype."); newLocale = "en_US"; - newMode =KEYBOARD_MODE; + newMode = KEYBOARD_MODE; } else { newLocale = newSubtype.getLocale(); newMode = newSubtype.getMode(); @@ -219,8 +219,8 @@ public class SubtypeSwitcher { mVoiceInput.cancel(); } } - if (languageChanged) { - mService.onKeyboardLanguageChanged(); + if (modeChanged || languageChanged) { + mService.onRefreshKeyboard(); } } else if (isVoiceMode()) { // If needsToShowWarningDialog is true, voice input need to show warning before @@ -312,19 +312,23 @@ public class SubtypeSwitcher { ////////////////////////////////// public int getEnabledKeyboardLocaleCount() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return mLanguageSwitcher.getLocaleCount(); } else { return mEnabledKeyboardSubtypesOfCurrentInputMethod.size(); } } + public boolean useSpacebarLanguageSwitcher() { + return mConfigUseSpacebarLanguageSwitcher; + } + public boolean needsToDisplayLanguage() { return mNeedsToDisplayLanguage; } public Locale getInputLocale() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return mLanguageSwitcher.getInputLocale(); } else { return mInputLocale; @@ -332,7 +336,7 @@ public class SubtypeSwitcher { } public String getInputLocaleStr() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { String inputLanguage = null; inputLanguage = mLanguageSwitcher.getInputLanguage(); // Should return system locale if there is no Language available. @@ -346,7 +350,7 @@ public class SubtypeSwitcher { } public String[] getEnabledLanguages() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return mLanguageSwitcher.getEnabledLanguages(); } else { return mEnabledLanguagesOfCurrentInputMethod.toArray( @@ -355,7 +359,7 @@ public class SubtypeSwitcher { } public Locale getSystemLocale() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return mLanguageSwitcher.getSystemLocale(); } else { return mSystemLocale; @@ -363,7 +367,7 @@ public class SubtypeSwitcher { } public boolean isSystemLanguageSameAsInputLanguage() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return getSystemLocale().getLanguage().equalsIgnoreCase( getInputLocaleStr().substring(0, 2)); } else { @@ -375,7 +379,7 @@ public class SubtypeSwitcher { final Locale systemLocale = conf.locale; // If system configuration was changed, update all parameters. if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { // If the system locale changes and is different from the saved // locale (mSystemLocale), then reload the input locale list from the // latin ime settings (shared prefs) and reset the input locale @@ -389,7 +393,7 @@ public class SubtypeSwitcher { } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { if (Settings.PREF_SELECTED_LANGUAGES.equals(key)) { mLanguageSwitcher.loadLocales(sharedPreferences); } @@ -439,18 +443,18 @@ public class SubtypeSwitcher { private void triggerVoiceIME() { if (!mService.isInputViewShown()) return; VoiceIMEConnector.getInstance().startListening(false, - KeyboardSwitcher.getInstance().getInputView().getWindowToken(), false); + KeyboardSwitcher.getInstance().getInputView().getWindowToken()); } ////////////////////////////////////// - // SpaceBar Language Switch support // + // Spacebar Language Switch support // ////////////////////////////////////// private LanguageSwitcher mLanguageSwitcher; public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { if (returnsNameInThisLocale) { - return toTitleCase(locale.getDisplayName(locale)); + return toTitleCase(SubtypeLocale.getFullDisplayName(locale)); } else { return toTitleCase(locale.getDisplayName()); } @@ -471,7 +475,7 @@ public class SubtypeSwitcher { return Character.toUpperCase(s.charAt(0)) + s.substring(1); } - private void updateForSpaceBarLanguageSwitch() { + private void updateForSpacebarLanguageSwitch() { // We need to update mNeedsToDisplayLanguage in onStartInputView because // getEnabledKeyboardLocaleCount could have been changed. mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1 @@ -484,7 +488,7 @@ public class SubtypeSwitcher { } public String getNextInputLanguageName() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return getDisplayLanguage(mLanguageSwitcher.getNextInputLocale()); } else { return ""; @@ -492,7 +496,7 @@ public class SubtypeSwitcher { } public String getPreviousInputLanguageName() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { return getDisplayLanguage(mLanguageSwitcher.getPrevInputLocale()); } else { return ""; @@ -529,13 +533,13 @@ public class SubtypeSwitcher { } public void loadSettings() { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { mLanguageSwitcher.loadLocales(mPrefs); } } public void toggleLanguage(boolean reset, boolean next) { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (mConfigUseSpacebarLanguageSwitcher) { if (reset) { mLanguageSwitcher.reset(); } else { diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 9ea9c2f3e..24c73e8ea 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -31,7 +31,7 @@ import java.util.Arrays; */ public class Suggest implements Dictionary.WordCallback { - public static final String TAG = "Suggest"; + public static final String TAG = Suggest.class.getSimpleName(); public static final int APPROX_MAX_WORD_LENGTH = 32; @@ -64,6 +64,8 @@ public class Suggest implements Dictionary.WordCallback { static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000; + private static boolean DBG = LatinImeLogger.sDBG; + private BinaryDictionary mMainDict; private Dictionary mUserDictionary; @@ -93,7 +95,7 @@ public class Suggest implements Dictionary.WordCallback { private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>(); ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>(); - private boolean mHaveCorrection; + private boolean mHaveAutoCorrection; private String mLowerOriginalWord; // TODO: Remove these member variables by passing more context to addWord() callback method @@ -103,7 +105,7 @@ public class Suggest implements Dictionary.WordCallback { private int mCorrectionMode = CORRECTION_BASIC; public Suggest(Context context, int dictionaryResId) { - mMainDict = new BinaryDictionary(context, dictionaryResId, DIC_MAIN); + mMainDict = BinaryDictionary.initDictionary(context, dictionaryResId, DIC_MAIN); initPool(); } @@ -127,7 +129,7 @@ public class Suggest implements Dictionary.WordCallback { } public boolean hasMainDictionary() { - return mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD; + return mMainDict != null && mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD; } public int getApproxMaxWordLength() { @@ -198,7 +200,7 @@ public class Suggest implements Dictionary.WordCallback { public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer, CharSequence prevWordForBigram) { LatinImeLogger.onStartSuggestion(prevWordForBigram); - mHaveCorrection = false; + mHaveAutoCorrection = false; mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); mIsAllUpperCase = wordComposer.isAllUpperCase(); collectGarbage(mSuggestions, mPrefMaxSuggestions); @@ -273,10 +275,13 @@ public class Suggest implements Dictionary.WordCallback { if (mSuggestions.size() > 0 && isValidWord(typedWord) && (mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM)) { - mHaveCorrection = true; + if (DBG) { + Log.d(TAG, "Auto corrected by CORRECTION_FULL."); + } + mHaveAutoCorrection = true; } } - mMainDict.getWords(wordComposer, this, mNextLettersFrequencies); + if (mMainDict != null) mMainDict.getWords(wordComposer, this, mNextLettersFrequencies); if ((mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM) && mSuggestions.size() > 0 && mPriorities.length > 0) { // TODO: when the normalized score of the first suggestion is nearly equals to @@ -289,7 +294,10 @@ public class Suggest implements Dictionary.WordCallback { + "(" + mAutoCorrectionThreshold + ")"); } if (normalizedScore >= mAutoCorrectionThreshold) { - mHaveCorrection = true; + if (DBG) { + Log.d(TAG, "Auto corrected by S-threthhold."); + } + mHaveAutoCorrection = true; } } } @@ -331,7 +339,10 @@ public class Suggest implements Dictionary.WordCallback { canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i + 1)); } if (canAdd) { - mHaveCorrection = true; + if (DBG) { + Log.d(TAG, "Auto corrected by AUTOTEXT."); + } + mHaveAutoCorrection = true; mSuggestions.add(i + 1, autoText); i++; } @@ -374,7 +385,7 @@ public class Suggest implements Dictionary.WordCallback { } public boolean hasMinimalCorrection() { - return mHaveCorrection; + return mHaveAutoCorrection; } private boolean compareCaseInsensitive(final String mLowerOriginalWord, @@ -496,7 +507,7 @@ public class Suggest implements Dictionary.WordCallback { } public boolean isValidWord(final CharSequence word) { - if (word == null || word.length() == 0) { + if (word == null || word.length() == 0 || mMainDict == null) { return false; } return mMainDict.isValidWord(word) diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 5398b77b2..0fbbcdd91 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -124,7 +124,7 @@ public class SuggestedWords { addWord(previousSuggestions.getWord(pos)); mIsCompletions = false; mTypedWordValid = false; - mHasMinimalSuggestion = (previousSize > 1); + mHasMinimalSuggestion = false; return this; } diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 56ad6c7aa..160948507 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -36,6 +36,8 @@ import java.text.SimpleDateFormat; import java.util.Date; public class Utils { + private static final String TAG = Utils.class.getSimpleName(); + private static boolean DBG = LatinImeLogger.sDBG; /** * Cancel an {@link AsyncTask}. @@ -96,6 +98,29 @@ public class Utils { // || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1; } + + public static boolean shouldBlockedBySafetyNetForAutoCorrection(SuggestedWords suggestions) { + // Safety net for auto correction. + // Actually if we hit this safety net, it's actually a bug. + if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false; + CharSequence typedWord = suggestions.getWord(0); + CharSequence candidateWord = suggestions.getWord(1); + final int typedWordLength = typedWord.length(); + final int maxEditDistanceOfNativeDictionary = typedWordLength < 5 ? 2 : typedWordLength / 2; + final int distance = Utils.editDistance(typedWord, candidateWord); + if (DBG) { + Log.d(TAG, "Autocorrected edit distance = " + distance + + ", " + maxEditDistanceOfNativeDictionary); + } + if (distance > maxEditDistanceOfNativeDictionary) { + Log.w(TAG, "(Error) The edit distance of this correction exceeds limit. " + + "Turning off auto-correction."); + return true; + } else { + return false; + } + } + /* package */ static class RingCharBuffer { private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; |