Merge "Enable auto-correction only if there is a significant size main dictionary."

main
Amith Yamasani 2010-01-07 13:08:29 -08:00 committed by Android (Google) Code Review
commit a052b69b47
6 changed files with 73 additions and 28 deletions

View File

@ -38,6 +38,7 @@ using namespace android;
static jfieldID sDescriptorField; static jfieldID sDescriptorField;
static jfieldID sAssetManagerNativeField; static jfieldID sAssetManagerNativeField;
static jmethodID sAddWordMethod; static jmethodID sAddWordMethod;
static jfieldID sDictLength;
// //
// helper function to throw an exception // helper function to throw an exception
@ -79,6 +80,7 @@ static jint latinime_BinaryDictionary_open
} }
Dictionary *dictionary = new Dictionary(dict, typedLetterMultiplier, fullWordMultiplier); Dictionary *dictionary = new Dictionary(dict, typedLetterMultiplier, fullWordMultiplier);
dictionary->setAsset(dictAsset); dictionary->setAsset(dictAsset);
env->SetIntField(object, sDictLength, (jint) dictAsset->getLength());
env->ReleaseStringUTFChars(resourceString, resourcePath); env->ReleaseStringUTFChars(resourceString, resourcePath);
return (jint) dictionary; return (jint) dictionary;
@ -176,6 +178,14 @@ static int registerNatives(JNIEnv *env)
} }
sAssetManagerNativeField = env->GetFieldID(clazz, "mObject", "I"); sAssetManagerNativeField = env->GetFieldID(clazz, "mObject", "I");
// Get the field pointer for the dictionary length
clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
LOGE("Can't find %s", kClassPathName);
return -1;
}
sDictLength = env->GetFieldID(clazz, "mDictLength", "I");
return registerNativeMethods(env, return registerNativeMethods(env,
kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0])); kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
} }

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2009 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.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="english_ime_name" msgid="7252517407088836577">"Clavier Android"</string>
</resources>

View File

@ -31,7 +31,9 @@
<Key android:keyLabel="ц"/> <Key android:keyLabel="ц"/>
<Key android:keyLabel="у"/> <Key android:keyLabel="у"/>
<Key android:keyLabel="к"/> <Key android:keyLabel="к"/>
<Key android:keyLabel="е"/> <Key android:keyLabel="е"
android:popupKeyboard="@xml/kbd_popup_template"
android:popupCharacters="ё" />
<Key android:keyLabel="н"/> <Key android:keyLabel="н"/>
<Key android:keyLabel="г"/> <Key android:keyLabel="г"/>
<Key android:keyLabel="ш"/> <Key android:keyLabel="ш"/>
@ -40,7 +42,7 @@
<Key android:keyLabel="х" <Key android:keyLabel="х"
android:keyEdgeFlags="right"/> android:keyEdgeFlags="right"/>
</Row> </Row>
<Row> <Row>
<Key android:keyLabel="ф" <Key android:keyLabel="ф"
android:keyEdgeFlags="left"/> android:keyEdgeFlags="left"/>

View File

@ -35,6 +35,7 @@ public class BinaryDictionary extends Dictionary {
private static final boolean ENABLE_MISSED_CHARACTERS = true; private static final boolean ENABLE_MISSED_CHARACTERS = true;
private int mNativeDict; private int mNativeDict;
private int mDictLength; // This value is set from native code, don't change the name!!!!
private int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_ALTERNATIVES]; private int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_ALTERNATIVES];
private char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private int[] mFrequencies = new int[MAX_WORDS]; private int[] mFrequencies = new int[MAX_WORDS];
@ -125,6 +126,10 @@ public class BinaryDictionary extends Dictionary {
return isValidWordNative(mNativeDict, chars, chars.length); return isValidWordNative(mNativeDict, chars, chars.length);
} }
public int getSize() {
return mDictLength; // This value is initialized on the call to openNative()
}
@Override @Override
public synchronized void close() { public synchronized void close() {
if (mNativeDict != 0) { if (mNativeDict != 0) {

View File

@ -126,7 +126,9 @@ public class LatinIME extends InputMethodService
private CharSequence mBestWord; private CharSequence mBestWord;
private boolean mPredictionOn; private boolean mPredictionOn;
private boolean mCompletionOn; private boolean mCompletionOn;
private boolean mHasDictionary;
private boolean mAutoSpace; private boolean mAutoSpace;
private boolean mAutoCorrectEnabled;
private boolean mAutoCorrectOn; private boolean mAutoCorrectOn;
private boolean mCapsLock; private boolean mCapsLock;
private boolean mVibrateOn; private boolean mVibrateOn;
@ -224,7 +226,6 @@ public class LatinIME extends InputMethodService
mSuggest.close(); mSuggest.close();
} }
mSuggest = new Suggest(this, R.raw.main); mSuggest = new Suggest(this, R.raw.main);
mSuggest.setCorrectionMode(mCorrectionMode);
mUserDictionary = new UserDictionary(this); mUserDictionary = new UserDictionary(this);
if (mContactsDictionary == null) { if (mContactsDictionary == null) {
mContactsDictionary = new ContactsDictionary(this); mContactsDictionary = new ContactsDictionary(this);
@ -236,7 +237,7 @@ public class LatinIME extends InputMethodService
mSuggest.setUserDictionary(mUserDictionary); mSuggest.setUserDictionary(mUserDictionary);
mSuggest.setContactsDictionary(mContactsDictionary); mSuggest.setContactsDictionary(mContactsDictionary);
mSuggest.setAutoDictionary(mAutoDictionary); mSuggest.setAutoDictionary(mAutoDictionary);
updateCorrectionMode();
mWordSeparators = mResources.getString(R.string.word_separators); mWordSeparators = mResources.getString(R.string.word_separators);
mSentenceSeparators = mResources.getString(R.string.sentence_separators); mSentenceSeparators = mResources.getString(R.string.sentence_separators);
@ -304,7 +305,7 @@ public class LatinIME extends InputMethodService
TextEntryState.newSession(this); TextEntryState.newSession(this);
boolean disableAutoCorrect = false; mInputTypeNoAutoCorrect = false;
mPredictionOn = false; mPredictionOn = false;
mCompletionOn = false; mCompletionOn = false;
mCompletions = null; mCompletions = null;
@ -353,19 +354,19 @@ public class LatinIME extends InputMethodService
// If it's a browser edit field and auto correct is not ON explicitly, then // If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on. // disable auto correction, but keep suggestions on.
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
disableAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
} }
// If NO_SUGGESTIONS is set, don't do prediction. // If NO_SUGGESTIONS is set, don't do prediction.
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
mPredictionOn = false; mPredictionOn = false;
disableAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
// If it's not multiline and the autoCorrect flag is not set, then don't correct // If it's not multiline and the autoCorrect flag is not set, then don't correct
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
(attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
disableAutoCorrect = true; mInputTypeNoAutoCorrect = true;
} }
if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
mPredictionOn = false; mPredictionOn = false;
@ -385,17 +386,13 @@ public class LatinIME extends InputMethodService
setCandidatesViewShown(false); setCandidatesViewShown(false);
if (mCandidateView != null) mCandidateView.setSuggestions(null, false, false, false); if (mCandidateView != null) mCandidateView.setSuggestions(null, false, false, false);
loadSettings(); loadSettings();
// Override auto correct
if (disableAutoCorrect) { // If the dictionary is not big enough, don't auto correct
mAutoCorrectOn = false; mHasDictionary = mSuggest.hasMainDictionary();
if (mCorrectionMode == Suggest.CORRECTION_FULL) {
mCorrectionMode = Suggest.CORRECTION_BASIC; updateCorrectionMode();
}
}
mInputView.setProximityCorrectionEnabled(true); mInputView.setProximityCorrectionEnabled(true);
if (mSuggest != null) {
mSuggest.setCorrectionMode(mCorrectionMode);
}
mPredictionOn = mPredictionOn && mCorrectionMode > 0; mPredictionOn = mPredictionOn && mCorrectionMode > 0;
checkTutorial(attribute.privateImeOptions); checkTutorial(attribute.privateImeOptions);
if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
@ -1150,6 +1147,18 @@ public class LatinIME extends InputMethodService
mUserDictionary.addWord(word, frequency); mUserDictionary.addWord(word, frequency);
} }
private void updateCorrectionMode() {
mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false;
mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes)
&& !mInputTypeNoAutoCorrect && mHasDictionary;
mCorrectionMode = mAutoCorrectOn
? Suggest.CORRECTION_FULL
: (mQuickFixes ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
if (mSuggest != null) {
mSuggest.setCorrectionMode(mCorrectionMode);
}
}
private void launchSettings() { private void launchSettings() {
handleClose(); handleClose();
Intent intent = new Intent(); Intent intent = new Intent();
@ -1169,12 +1178,9 @@ public class LatinIME extends InputMethodService
// will continue to work // will continue to work
if (AutoText.getSize(mInputView) < 1) mQuickFixes = true; if (AutoText.getSize(mInputView) < 1) mQuickFixes = true;
mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes; mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true) & mQuickFixes;
boolean autoComplete = sp.getBoolean(PREF_AUTO_COMPLETE, mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions; mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
mAutoCorrectOn = mSuggest != null && (autoComplete || mQuickFixes); updateCorrectionMode();
mCorrectionMode = autoComplete
? Suggest.CORRECTION_FULL
: (mQuickFixes ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
String languageList = sp.getString(PREF_SELECTED_LANGUAGES, null); String languageList = sp.getString(PREF_SELECTED_LANGUAGES, null);
updateSelectedLanguages(languageList); updateSelectedLanguages(languageList);
} }
@ -1274,6 +1280,7 @@ public class LatinIME extends InputMethodService
private static final int CPS_BUFFER_SIZE = 16; private static final int CPS_BUFFER_SIZE = 16;
private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
private int mCpsIndex; private int mCpsIndex;
private boolean mInputTypeNoAutoCorrect;
private void measureCps() { private void measureCps() {
if (!LatinIME.PERF_DEBUG) return; if (!LatinIME.PERF_DEBUG) return;

View File

@ -37,7 +37,9 @@ public class Suggest implements Dictionary.WordCallback {
public static final int CORRECTION_BASIC = 1; public static final int CORRECTION_BASIC = 1;
public static final int CORRECTION_FULL = 2; public static final int CORRECTION_FULL = 2;
private Dictionary mMainDict; private static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000;
private BinaryDictionary mMainDict;
private Dictionary mUserDictionary; private Dictionary mUserDictionary;
@ -49,9 +51,7 @@ public class Suggest implements Dictionary.WordCallback {
private int[] mPriorities = new int[mPrefMaxSuggestions]; private int[] mPriorities = new int[mPrefMaxSuggestions];
private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>(); private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
private boolean mIncludeTypedWordIfValid;
private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>(); private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
private Context mContext;
private boolean mHaveCorrection; private boolean mHaveCorrection;
private CharSequence mOriginalWord; private CharSequence mOriginalWord;
private String mLowerOriginalWord; private String mLowerOriginalWord;
@ -60,7 +60,6 @@ public class Suggest implements Dictionary.WordCallback {
public Suggest(Context context, int dictionaryResId) { public Suggest(Context context, int dictionaryResId) {
mContext = context;
mMainDict = new BinaryDictionary(context, dictionaryResId); mMainDict = new BinaryDictionary(context, dictionaryResId);
for (int i = 0; i < mPrefMaxSuggestions; i++) { for (int i = 0; i < mPrefMaxSuggestions; i++) {
StringBuilder sb = new StringBuilder(32); StringBuilder sb = new StringBuilder(32);
@ -76,6 +75,10 @@ public class Suggest implements Dictionary.WordCallback {
mCorrectionMode = mode; mCorrectionMode = mode;
} }
public boolean hasMainDictionary() {
return mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD;
}
/** /**
* Sets an optional user dictionary resource to be loaded. The user dictionary is consulted * Sets an optional user dictionary resource to be loaded. The user dictionary is consulted
* before the main dictionary, if set. * before the main dictionary, if set.
@ -155,7 +158,6 @@ public class Suggest implements Dictionary.WordCallback {
mHaveCorrection = false; mHaveCorrection = false;
collectGarbage(); collectGarbage();
Arrays.fill(mPriorities, 0); Arrays.fill(mPriorities, 0);
mIncludeTypedWordIfValid = includeTypedWordIfValid;
// Save a lowercase version of the original word // Save a lowercase version of the original word
mOriginalWord = wordComposer.getTypedWord(); mOriginalWord = wordComposer.getTypedWord();