aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values/strings.xml2
-rw-r--r--java/res/xml/method.xml44
-rw-r--r--java/src/com/android/inputmethod/compat/SharedPreferencesCompat.java (renamed from java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java)2
-rw-r--r--java/src/com/android/inputmethod/deprecated/VoiceProxy.java2
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java2
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java2
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/Hints.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java7
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java14
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java25
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java162
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java18
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java16
-rw-r--r--native/src/correction.cpp85
-rw-r--r--native/src/correction.h8
-rw-r--r--native/src/correction_state.h7
-rw-r--r--native/src/defines.h7
-rw-r--r--native/src/proximity_info.cpp64
-rw-r--r--native/src/proximity_info.h33
-rw-r--r--native/src/unigram_dictionary.cpp6
21 files changed, 373 insertions, 146 deletions
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index a1c1a9ffd..9b3829f74 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -99,7 +99,7 @@
<!-- Option to decide the auto correction threshold score -->
<!-- Option to enable auto correction [CHAR LIMIT=20]-->
<string name="auto_correction">Auto correction</string>
- <!-- Description for auto correction [CHAR LIMIT=35] -->
+ <!-- Description for auto correction [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
<string name="auto_correction_summary">Spacebar and punctuation automatically correct mistyped words</string>
<!-- Option to disable auto correction. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_off">Off</string>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index f2f3178de..6184add4d 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -31,141 +31,145 @@
android:label="@string/subtype_en_US"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable"
+ android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_en_GB"
android:imeSubtypeLocale="en_GB"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable"
+ android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="ar"
android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="cs"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="da"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="de"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_de_qwerty"
android:imeSubtypeLocale="de"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ"
+ android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="es"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="fi"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="fr"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="fr_CA"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="fr_CH"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="hr"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="hu"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="it"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. -->
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="iw"
android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="nb"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="nl"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="pl"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="pt"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="ru"
android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="sr"
android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="sv"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
<subtype android:icon="@drawable/ic_subtype_keyboard"
android:label="@string/subtype_generic"
android:imeSubtypeLocale="tr"
android:imeSubtypeMode="keyboard"
- android:imeSubtypeExtraValue="AsciiCapable"
+ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
/>
</input-method>
diff --git a/java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java b/java/src/com/android/inputmethod/compat/SharedPreferencesCompat.java
index 1d36c0b98..38736f3a1 100644
--- a/java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java
+++ b/java/src/com/android/inputmethod/compat/SharedPreferencesCompat.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.latin;
+package com.android.inputmethod.compat;
import android.content.SharedPreferences;
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
index a4dfa10d2..3f8c2ef8f 100644
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.deprecated;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
+import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.deprecated.voice.FieldContext;
import com.android.inputmethod.deprecated.voice.Hints;
import com.android.inputmethod.deprecated.voice.SettingsUtil;
@@ -28,7 +29,6 @@ import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinIME.UIHandler;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.Utils;
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
index b6e0ec9cf..dbe7aec6a 100644
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
+++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
@@ -16,12 +16,12 @@
package com.android.inputmethod.deprecated.languageswitcher;
+import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Settings;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
import com.android.inputmethod.latin.Utils;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java
index 8070942d0..7e2627c81 100644
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java
+++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java
@@ -16,11 +16,11 @@
package com.android.inputmethod.deprecated.languageswitcher;
+import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.Settings;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
diff --git a/java/src/com/android/inputmethod/deprecated/voice/Hints.java b/java/src/com/android/inputmethod/deprecated/voice/Hints.java
index 06b234381..17a19bf23 100644
--- a/java/src/com/android/inputmethod/deprecated/voice/Hints.java
+++ b/java/src/com/android/inputmethod/deprecated/voice/Hints.java
@@ -16,8 +16,8 @@
package com.android.inputmethod.deprecated.voice;
+import com.android.inputmethod.compat.SharedPreferencesCompat;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 13e8ba13c..837a53391 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -106,16 +106,12 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
- public class KeyboardLayoutState {
+ private class KeyboardLayoutState {
private boolean mIsValid;
private boolean mIsAlphabetMode;
private boolean mIsShiftLocked;
private boolean mIsShifted;
- public boolean isValid() {
- return mIsValid;
- }
-
public void save() {
if (mCurrentId == null) {
return;
@@ -210,14 +206,15 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
mLayoutSwitchBackSymbols = mResources.getString(R.string.layout_switch_back_symbols);
setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId()));
+ mSavedKeyboardState.restore();
} catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e);
LatinImeLogger.logOnException(mMainKeyboardId.toString(), e);
}
}
- public KeyboardLayoutState getKeyboardState() {
- return mSavedKeyboardState;
+ public void saveKeyboardState() {
+ mSavedKeyboardState.save();
}
public void onFinishInputView() {
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index d35b1a939..cc6feeb4a 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard;
import android.graphics.Rect;
import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;
@@ -31,6 +32,8 @@ public class ProximityInfo {
/** Number of key widths from current touch point to search for nearest keys. */
private static float SEARCH_DISTANCE = 1.2f;
private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private static final String SUPPORT_TOUCH_POSITION_CORRECTION =
+ "SupportTouchPositionCorrection";
private final int mKeyHeight;
private final int mGridWidth;
@@ -120,8 +123,10 @@ public class ProximityInfo {
keyCharCodes[i] = key.mCode;
}
+ final SubtypeSwitcher switcher = SubtypeSwitcher.getInstance();
final boolean hasTouchPositionCorrectionData =
- mTouchPositionCorrectionXs != null
+ switcher.currentSubtypeContainsExtraValueKey(SUPPORT_TOUCH_POSITION_CORRECTION)
+ && mTouchPositionCorrectionXs != null
&& mTouchPositionCorrectionYs != null
&& mTouchPositionCorrectionRadii != null
&& mTouchPositionCorrectionXs.length > 0
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index ab9edb110..18a9e3ab1 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -61,16 +61,26 @@ public class BinaryDictionary extends Dictionary {
public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING =
new Flag(R.bool.config_require_umlaut_processing, 0x1);
+ // FULL_EDIT_DISTANCE is a flag that forces the dictionary to use full words
+ // when computing edit distance, instead of the default behavior of stopping
+ // the evaluation at the size the user typed.
public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2);
// Can create a new flag from extravalue :
// public static final Flag FLAG_MYFLAG =
// new Flag("my_flag", 0x02);
- private static final Flag[] ALL_FLAGS = {
+ // ALL_CONFIG_FLAGS is a collection of flags that enable reading all flags from configuration.
+ // This is but a mask - it does not mean the flags will be on, only that the configuration
+ // will be read for this particular flag.
+ public static final Flag[] ALL_CONFIG_FLAGS = {
// Here should reside all flags that trigger some special processing
// These *must* match the definition in UnigramDictionary enum in
// unigram_dictionary.h so please update both at the same time.
+ // Please note that flags created with a resource are of type CONFIG while flags
+ // created with a string are of type EXTRAVALUE. These behave like masks, and the
+ // actual value will be read from the configuration/extra value at run time for
+ // the configuration at dictionary creation time.
FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING,
};
@@ -93,7 +103,7 @@ public class BinaryDictionary extends Dictionary {
// the Suggest class knows everything about every single dictionary.
mDicTypeId = Suggest.DIC_MAIN;
// TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter
- mFlags = Flag.initFlags(null == flagArray ? ALL_FLAGS : flagArray, context,
+ mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context,
SubtypeSwitcher.getInstance());
loadDictionary(filename, offset, length);
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index dfaad26bc..1607f86a8 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -34,7 +34,7 @@ public class DictionaryFactory {
private static String TAG = DictionaryFactory.class.getSimpleName();
/**
- * Initializes a dictionary from a dictionary pack.
+ * Initializes a dictionary from a dictionary pack, with explicit flags.
*
* This searches for a content provider providing a dictionary pack for the specified
* locale. If none is found, it falls back to using the resource passed as fallBackResId
@@ -42,10 +42,11 @@ public class DictionaryFactory {
* @param context application context for reading resources
* @param locale the locale for which to create the dictionary
* @param fallbackResId the id of the resource to use as a fallback if no pack is found
+ * @param flagArray an array of flags to use
* @return an initialized instance of DictionaryCollection
*/
- public static DictionaryCollection createDictionaryFromManager(Context context, Locale locale,
- int fallbackResId) {
+ public static DictionaryCollection createDictionaryFromManager(final Context context,
+ final Locale locale, final int fallbackResId, final Flag[] flagArray) {
if (null == locale) {
Log.e(TAG, "No locale defined for dictionary");
return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale));
@@ -57,7 +58,7 @@ public class DictionaryFactory {
if (null != assetFileList) {
for (final AssetFileAddress f : assetFileList) {
final BinaryDictionary binaryDictionary =
- new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null);
+ new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, flagArray);
if (binaryDictionary.isValidDictionary()) {
dictList.add(binaryDictionary);
}
@@ -71,6 +72,22 @@ public class DictionaryFactory {
}
/**
+ * Initializes a dictionary from a dictionary pack, with default flags.
+ *
+ * This searches for a content provider providing a dictionary pack for the specified
+ * locale. If none is found, it falls back to using the resource passed as fallBackResId
+ * as a dictionary.
+ * @param context application context for reading resources
+ * @param locale the locale for which to create the dictionary
+ * @param fallbackResId the id of the resource to use as a fallback if no pack is found
+ * @return an initialized instance of DictionaryCollection
+ */
+ public static DictionaryCollection createDictionaryFromManager(final Context context,
+ final Locale locale, final int fallbackResId) {
+ return createDictionaryFromManager(context, locale, fallbackResId, null);
+ }
+
+ /**
* Initializes a dictionary from a raw resource file
* @param context application context for reading resources
* @param resId the resource containing the raw binary dictionary
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index cf1cb8f25..dfb4d0622 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -65,7 +65,6 @@ import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.KeyboardSwitcher.KeyboardLayoutState;
import com.android.inputmethod.keyboard.KeyboardView;
import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView;
@@ -132,9 +131,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200;
- private static final int START_INPUT_VIEW_DELAY_WHEN_SCREEN_ORIENTATION_STARTED = 10;
- private static final int ACCUMULATE_START_INPUT_VIEW_DELAY = 20;
- private static final int RESTORE_KEYBOARD_STATE_DELAY = 500;
+ private static final int PENDING_IMS_CALLBACK_DURATION = 800;
/**
* The name of the scheme used by the Package Manager to warn of a new package installation,
@@ -239,10 +236,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
private static final int MSG_SPACE_TYPED = 6;
private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
- private static final int MSG_START_ORIENTATION_CHANGE = 8;
- private static final int MSG_START_INPUT_VIEW = 9;
- private static final int MSG_DISPLAY_COMPLETIONS = 10;
- private static final int MSG_RESTORE_KEYBOARD_LAYOUT = 11;
+ private static final int MSG_PENDING_IMS_CALLBACK = 8;
public UIHandler(LatinIME outerInstance) {
super(outerInstance);
@@ -291,16 +285,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
(LatinKeyboard)msg.obj);
}
break;
- case MSG_START_INPUT_VIEW:
- latinIme.onStartInputView((EditorInfo)msg.obj, false);
- break;
- case MSG_DISPLAY_COMPLETIONS:
- latinIme.onDisplayCompletions((CompletionInfo[])msg.obj);
- break;
- case MSG_RESTORE_KEYBOARD_LAYOUT:
- removeMessages(MSG_UPDATE_SHIFT_STATE);
- ((KeyboardLayoutState)msg.obj).restore();
- break;
}
}
@@ -391,47 +375,89 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return hasMessages(MSG_SPACE_TYPED);
}
- public void postRestoreKeyboardLayout() {
- final LatinIME latinIme = getOuterInstance();
- final KeyboardLayoutState state = latinIme.mKeyboardSwitcher.getKeyboardState();
- if (state.isValid()) {
- removeMessages(MSG_RESTORE_KEYBOARD_LAYOUT);
- sendMessageDelayed(
- obtainMessage(MSG_RESTORE_KEYBOARD_LAYOUT, state),
- RESTORE_KEYBOARD_STATE_DELAY);
- }
- }
+ // Working variables for the following methods.
+ private boolean mIsOrientationChanging;
+ private boolean mPendingSuccesiveImsCallback;
+ private boolean mHasPendingStartInput;
+ private boolean mHasPendingFinishInputView;
+ private boolean mHasPendingFinishInput;
public void startOrientationChanging() {
- sendMessageDelayed(obtainMessage(MSG_START_ORIENTATION_CHANGE),
- START_INPUT_VIEW_DELAY_WHEN_SCREEN_ORIENTATION_STARTED);
+ mIsOrientationChanging = true;
final LatinIME latinIme = getOuterInstance();
- latinIme.mKeyboardSwitcher.getKeyboardState().save();
- postRestoreKeyboardLayout();
+ latinIme.mKeyboardSwitcher.saveKeyboardState();
}
- public boolean postStartInputView(EditorInfo attribute) {
- if (hasMessages(MSG_START_ORIENTATION_CHANGE) || hasMessages(MSG_START_INPUT_VIEW)) {
- removeMessages(MSG_START_INPUT_VIEW);
- // Postpone onStartInputView by ACCUMULATE_START_INPUT_VIEW_DELAY and see if
- // orientation change has finished.
- sendMessageDelayed(obtainMessage(MSG_START_INPUT_VIEW, attribute),
- ACCUMULATE_START_INPUT_VIEW_DELAY);
- return true;
+ private void resetPendingImsCallback() {
+ mHasPendingFinishInputView = false;
+ mHasPendingFinishInput = false;
+ mHasPendingStartInput = false;
+ }
+
+ private void executePendingImsCallback(LatinIME latinIme, EditorInfo attribute,
+ boolean restarting) {
+ if (mHasPendingFinishInputView)
+ latinIme.onFinishInputViewInternal(mHasPendingFinishInput);
+ if (mHasPendingFinishInput)
+ latinIme.onFinishInputInternal();
+ if (mHasPendingStartInput)
+ latinIme.onStartInputInternal(attribute, restarting);
+ resetPendingImsCallback();
+ }
+
+ public void onStartInput(EditorInfo attribute, boolean restarting) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the second onStartInput after orientation changed.
+ mHasPendingStartInput = true;
+ } else {
+ if (mIsOrientationChanging && restarting) {
+ // This is the first onStartInput after orientation changed.
+ mIsOrientationChanging = false;
+ mPendingSuccesiveImsCallback = true;
+ }
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, attribute, restarting);
+ latinIme.onStartInputInternal(attribute, restarting);
}
- return false;
}
- public boolean postDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) {
- if (hasMessages(MSG_START_INPUT_VIEW) || hasMessages(MSG_DISPLAY_COMPLETIONS)) {
- removeMessages(MSG_DISPLAY_COMPLETIONS);
- // Postpone onDisplayCompletions by ACCUMULATE_START_INPUT_VIEW_DELAY.
- sendMessageDelayed(
- obtainMessage(MSG_DISPLAY_COMPLETIONS, applicationSpecifiedCompletions),
- ACCUMULATE_START_INPUT_VIEW_DELAY);
- return true;
+ public void onStartInputView(EditorInfo attribute, boolean restarting) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the second onStartInputView after orientation changed.
+ resetPendingImsCallback();
+ } else {
+ if (mPendingSuccesiveImsCallback) {
+ // This is the first onStartInputView after orientation changed.
+ mPendingSuccesiveImsCallback = false;
+ resetPendingImsCallback();
+ sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
+ PENDING_IMS_CALLBACK_DURATION);
+ }
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, attribute, restarting);
+ latinIme.onStartInputViewInternal(attribute, restarting);
+ }
+ }
+
+ public void onFinishInputView(boolean finishingInput) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the first onFinishInputView after orientation changed.
+ mHasPendingFinishInputView = true;
+ } else {
+ final LatinIME latinIme = getOuterInstance();
+ latinIme.onFinishInputViewInternal(finishingInput);
+ }
+ }
+
+ public void onFinishInput() {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the first onFinishInput after orientation changed.
+ mHasPendingFinishInput = true;
+ } else {
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, null, false);
+ latinIme.onFinishInputInternal();
}
- return false;
}
}
@@ -646,12 +672,31 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
@Override
+ public void onStartInput(EditorInfo attribute, boolean restarting) {
+ mHandler.onStartInput(attribute, restarting);
+ }
+
+ @Override
public void onStartInputView(EditorInfo attribute, boolean restarting) {
- mHandler.postRestoreKeyboardLayout();
- if (mHandler.postStartInputView(attribute)) {
- return;
- }
+ mHandler.onStartInputView(attribute, restarting);
+ }
+ @Override
+ public void onFinishInputView(boolean finishingInput) {
+ mHandler.onFinishInputView(finishingInput);
+ }
+
+ @Override
+ public void onFinishInput() {
+ mHandler.onFinishInput();
+ }
+
+ private void onStartInputInternal(EditorInfo attribute, boolean restarting) {
+ super.onStartInput(attribute, restarting);
+ }
+
+ private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
+ super.onStartInputView(attribute, restarting);
final KeyboardSwitcher switcher = mKeyboardSwitcher;
LatinKeyboardView inputView = switcher.getKeyboardView();
@@ -785,8 +830,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (inputView != null) inputView.closing();
}
- @Override
- public void onFinishInput() {
+ private void onFinishInputInternal() {
super.onFinishInput();
LatinImeLogger.commit();
@@ -799,8 +843,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites();
}
- @Override
- public void onFinishInputView(boolean finishingInput) {
+ private void onFinishInputViewInternal(boolean finishingInput) {
super.onFinishInputView(finishingInput);
mKeyboardSwitcher.onFinishInputView();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
@@ -939,9 +982,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onDisplayCompletions(CompletionInfo[] applicationSpecifiedCompletions) {
- if (mHandler.postDisplayCompletions(applicationSpecifiedCompletions)) {
- return;
- }
if (DEBUG) {
Log.i(TAG, "Received completions:");
if (applicationSpecifiedCompletions != null) {
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index a2e896619..bd94bab34 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -328,6 +328,7 @@ public class Settings extends InputMethodSettingsActivity
}
private PreferenceScreen mInputLanguageSelection;
+ private PreferenceScreen mVibrationDurationSettingsPref;
private ListPreference mVoicePreference;
private CheckBoxPreference mShowSettingsKeyPreference;
private ListPreference mShowCorrectionSuggestionsPreference;
@@ -483,10 +484,10 @@ public class Settings extends InputMethodSettingsActivity
}
}
- final PreferenceScreen vibrationSettingsPref =
+ mVibrationDurationSettingsPref =
(PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
- if (vibrationSettingsPref != null) {
- vibrationSettingsPref.setOnPreferenceClickListener(
+ if (mVibrationDurationSettingsPref != null) {
+ mVibrationDurationSettingsPref.setOnPreferenceClickListener(
new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
@@ -494,6 +495,7 @@ public class Settings extends InputMethodSettingsActivity
return true;
}
});
+ updateVibrationDurationSettingsSummary(prefs, res);
}
}
@@ -642,9 +644,18 @@ public class Settings extends InputMethodSettingsActivity
}
}
+ private void updateVibrationDurationSettingsSummary(SharedPreferences sp, Resources res) {
+ if (mVibrationDurationSettingsPref != null) {
+ mVibrationDurationSettingsPref.setSummary(
+ Utils.getCurrentVibrationDuration(sp, res)
+ + res.getString(R.string.settings_ms));
+ }
+ }
+
private void showVibrationSettingsDialog() {
final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
final Activity context = getActivityInternal();
+ final Resources res = context.getResources();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.prefs_vibration_duration_settings);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -652,6 +663,7 @@ public class Settings extends InputMethodSettingsActivity
public void onClick(DialogInterface dialog, int whichButton) {
final int ms = Integer.valueOf(mVibrationSettingsTextView.getText().toString());
sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
+ updateVibrationDurationSettingsSummary(sp, res);
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 1d5986ef9..9e030eb90 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -28,11 +28,13 @@ import android.text.TextUtils;
import com.android.inputmethod.compat.ArraysCompatUtils;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.BinaryDictionary;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.Dictionary.DataType;
import com.android.inputmethod.latin.Dictionary.WordCallback;
import com.android.inputmethod.latin.DictionaryCollection;
import com.android.inputmethod.latin.DictionaryFactory;
+import com.android.inputmethod.latin.Flag;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
@@ -65,6 +67,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private final static SuggestionsInfo IN_DICT_EMPTY_SUGGESTIONS =
new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY,
EMPTY_STRING_ARRAY);
+ private final static Flag[] USE_FULL_EDIT_DISTANCE_FLAG_ARRAY;
+ static {
+ // See BinaryDictionary.java for an explanation of these flags
+ // Specifially, ALL_CONFIG_FLAGS means that we want to consider all flags with the
+ // current dictionary configuration - for example, consider the UMLAUT flag
+ // so that it will be turned on for German dictionaries and off for others.
+ USE_FULL_EDIT_DISTANCE_FLAG_ARRAY = Arrays.copyOf(BinaryDictionary.ALL_CONFIG_FLAGS,
+ BinaryDictionary.ALL_CONFIG_FLAGS.length + 1);
+ USE_FULL_EDIT_DISTANCE_FLAG_ARRAY[BinaryDictionary.ALL_CONFIG_FLAGS.length] =
+ BinaryDictionary.FLAG_USE_FULL_EDIT_DISTANCE;
+ }
private Map<String, DictionaryPool> mDictionaryPools =
Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
private Map<String, Dictionary> mUserDictionaries =
@@ -263,7 +276,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final Resources resources = getResources();
final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
final DictionaryCollection dictionaryCollection =
- DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId);
+ DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId,
+ USE_FULL_EDIT_DISTANCE_FLAG_ARRAY);
final String localeStr = locale.toString();
Dictionary userDict = mUserDictionaries.get(localeStr);
if (null == userDict) {
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index 9a7e5f35d..5128c2e5c 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -115,6 +115,9 @@ bool Correction::initProcessState(const int outputIndex) {
mInputIndex = mCorrectionStates[outputIndex].mInputIndex;
mNeedsToTraverseAllNodes = mCorrectionStates[outputIndex].mNeedsToTraverseAllNodes;
+ mEquivalentCharStrongCount = mCorrectionStates[outputIndex].mEquivalentCharStrongCount;
+ mEquivalentCharNormalCount = mCorrectionStates[outputIndex].mEquivalentCharNormalCount;
+ mEquivalentCharWeakCount = mCorrectionStates[outputIndex].mEquivalentCharWeakCount;
mProximityCount = mCorrectionStates[outputIndex].mProximityCount;
mTransposedCount = mCorrectionStates[outputIndex].mTransposedCount;
mExcessiveCount = mCorrectionStates[outputIndex].mExcessiveCount;
@@ -169,6 +172,9 @@ void Correction::incrementOutputIndex() {
mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex;
mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes;
+ mCorrectionStates[mOutputIndex].mEquivalentCharStrongCount = mEquivalentCharStrongCount;
+ mCorrectionStates[mOutputIndex].mEquivalentCharNormalCount = mEquivalentCharNormalCount;
+ mCorrectionStates[mOutputIndex].mEquivalentCharWeakCount = mEquivalentCharWeakCount;
mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount;
mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount;
mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount;
@@ -210,6 +216,12 @@ Correction::CorrectionType Correction::processSkipChar(
}
}
+inline bool isEquivalentChar(ProximityInfo::ProximityType type) {
+ // 'type ProximityInfo::EQUIVALENT_CHAR_WEAK' means that
+ // type == ..._WEAK or type == ..._NORMAL or type == ..._STRONG.
+ return type <= ProximityInfo::EQUIVALENT_CHAR_WEAK;
+}
+
Correction::CorrectionType Correction::processCharAndCalcState(
const int32_t c, const bool isTerminal) {
const int correctionCount = (mSkippedCount + mExcessiveCount + mTransposedCount);
@@ -221,8 +233,9 @@ Correction::CorrectionType Correction::processCharAndCalcState(
bool incremented = false;
if (mLastCharExceeded && mInputIndex == mInputLength - 1) {
// TODO: Do not check the proximity if EditDistance exceeds the threshold
- const int matchId = mProximityInfo->getMatchedProximityId(mInputIndex, c, true);
- if (matchId == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ const ProximityInfo::ProximityType matchId =
+ mProximityInfo->getMatchedProximityId(mInputIndex, c, true);
+ if (isEquivalentChar(matchId)) {
mLastCharExceeded = false;
--mExcessiveCount;
} else if (matchId == ProximityInfo::NEAR_PROXIMITY_CHAR) {
@@ -266,8 +279,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
bool secondTransposing = false;
if (mTransposedCount % 2 == 1) {
- if (mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ if (isEquivalentChar(mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
++mTransposedCount;
secondTransposing = true;
} else if (mCorrectionStates[mOutputIndex].mExceeding) {
@@ -288,8 +300,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
// TODO: Change the limit if we'll allow two or more proximity chars with corrections
const bool checkProximityChars = noCorrectionsHappenedSoFar || mProximityCount == 0;
- const int matchedProximityCharId = secondTransposing
- ? ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR
+ const ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
+ ? ProximityInfo::EQUIVALENT_CHAR_NORMAL
: mProximityInfo->getMatchedProximityId(mInputIndex, c, checkProximityChars);
if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
@@ -299,19 +311,18 @@ Correction::CorrectionType Correction::processCharAndCalcState(
// here refers to the previous state.
if (canTryCorrection && mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mExceeding
- && mProximityInfo->getMatchedProximityId(mInputIndex, mWord[mOutputIndex], false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+ mInputIndex, mWord[mOutputIndex], false))) {
// Conversion p->e
++mExcessiveCount;
--mProximityCount;
} else if (mInputIndex < mInputLength - 1 && mOutputIndex > 0 && mTransposedCount > 0
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
- && mProximityInfo->getMatchedProximityId(
- mInputIndex, mWord[mOutputIndex - 1], false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR
- && mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+ mInputIndex, mWord[mOutputIndex - 1], false))
+ && isEquivalentChar(
+ mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
// Conversion t->e
// Example:
// occaisional -> occa sional
@@ -322,8 +333,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
} else if (mOutputIndex > 0 && mInputIndex > 0 && mTransposedCount > 0
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
- && mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ && isEquivalentChar(
+ mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
// Conversion t->s
// Example:
// chcolate -> chocolate
@@ -334,8 +345,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
} else if (canTryCorrection && mInputIndex > 0
&& mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mSkipping
- && mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ && isEquivalentChar(
+ mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
// Conversion p->s
// Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
// proximity chars of "s", but it should rather be handled as a skipped char.
@@ -343,8 +354,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
--mProximityCount;
return processSkipChar(c, isTerminal, false);
} else if ((mExceeding || mTransposing) && mInputIndex - 1 < mInputLength
- && mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false)
- == ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR) {
+ && isEquivalentChar(
+ mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
// 1.2. Excessive or transpose correction
if (mTransposing) {
++mTransposedCount;
@@ -364,14 +375,28 @@ Correction::CorrectionType Correction::processCharAndCalcState(
}
return UNRELATED;
}
- } else if (secondTransposing
- || ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
+ } else if (secondTransposing) {
// If inputIndex is greater than mInputLength, that means there is no
// proximity chars. So, we don't need to check proximity.
mMatching = true;
+ } else if (isEquivalentChar(matchedProximityCharId)) {
+ mMatching = true;
+ switch (matchedProximityCharId) {
+ case ProximityInfo::EQUIVALENT_CHAR_STRONG:
+ ++mEquivalentCharStrongCount;
+ break;
+ case ProximityInfo::EQUIVALENT_CHAR_NORMAL:
+ ++mEquivalentCharNormalCount;
+ break;
+ case ProximityInfo::EQUIVALENT_CHAR_WEAK:
+ ++mEquivalentCharWeakCount;
+ break;
+ default:
+ assert(false);
+ }
} else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
mProximityMatching = true;
- incrementProximityCount();
+ ++mProximityCount;
}
mWord[mOutputIndex] = c;
@@ -530,6 +555,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
const int transposedCount = correction->mTransposedCount / 2;
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
const int proximityMatchedCount = correction->mProximityCount;
+ const int equivalentCharStrongCount = correction->mEquivalentCharStrongCount;
+ const int equivalentCharWeakCount = correction->mEquivalentCharWeakCount;
const bool lastCharExceeded = correction->mLastCharExceeded;
const bool useFullEditDistance = correction->mUseFullEditDistance;
const int outputLength = outputIndex + 1;
@@ -639,6 +666,20 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
}
+ for (int i = 0; i < equivalentCharStrongCount; ++i) {
+ if (DEBUG_DICT_FULL) {
+ LOGI("equivalent char strong");
+ }
+ multiplyRate(WORDS_WITH_EQUIVALENT_CHAR_STRONG_PROMOTION_RATE, &finalFreq);
+ }
+
+ for (int i = 0; i < equivalentCharWeakCount; ++i) {
+ if (DEBUG_DICT_FULL) {
+ LOGI("equivalent char weak");
+ }
+ multiplyRate(WORDS_WITH_EQUIVALENT_CHAR_WEAK_DEMOTION_RATE, &finalFreq);
+ }
+
const int errorCount = adjustedProximityMatchedCount > 0
? adjustedProximityMatchedCount
: (proximityMatchedCount + transposedCount);
diff --git a/native/src/correction.h b/native/src/correction.h
index ddb98b9d8..84e075266 100644
--- a/native/src/correction.h
+++ b/native/src/correction.h
@@ -102,11 +102,6 @@ private:
inline CorrectionType processSkipChar(
const int32_t c, const bool isTerminal, const bool inputIndexIncremented);
- // TODO: remove
- inline void incrementProximityCount() {
- ++mProximityCount;
- }
-
const int TYPED_LETTER_MULTIPLIER;
const int FULL_WORD_MULTIPLIER;
const ProximityInfo *mProximityInfo;
@@ -131,6 +126,9 @@ private:
int mOutputIndex;
int mInputIndex;
+ int mEquivalentCharStrongCount;
+ int mEquivalentCharNormalCount;
+ int mEquivalentCharWeakCount;
int mProximityCount;
int mExcessiveCount;
int mTransposedCount;
diff --git a/native/src/correction_state.h b/native/src/correction_state.h
index 93f8a8aab..a8ee82acd 100644
--- a/native/src/correction_state.h
+++ b/native/src/correction_state.h
@@ -29,6 +29,9 @@ struct CorrectionState {
uint16_t mChildCount;
uint8_t mInputIndex;
+ uint8_t mEquivalentCharStrongCount;
+ uint8_t mEquivalentCharNormalCount;
+ uint8_t mEquivalentCharWeakCount;
uint8_t mProximityCount;
uint8_t mTransposedCount;
uint8_t mExcessiveCount;
@@ -63,7 +66,9 @@ inline static void initCorrectionState(CorrectionState *state, const int rootPos
state->mExcessivePos = -1;
state->mSkipPos = -1;
-
+ state->mEquivalentCharStrongCount = 0;
+ state->mEquivalentCharNormalCount = 0;
+ state->mEquivalentCharWeakCount = 0;
state->mProximityCount = 0;
state->mTransposedCount = 0;
state->mExcessiveCount = 0;
diff --git a/native/src/defines.h b/native/src/defines.h
index 55469a788..dab862924 100644
--- a/native/src/defines.h
+++ b/native/src/defines.h
@@ -165,6 +165,8 @@ static void dumpWord(const unsigned short* word, const int length) {
#define KEYCODE_SPACE ' '
+#define CALIBRATE_SCORE_BY_TOUCH_COORDINATES false
+
#define SUGGEST_WORDS_WITH_MISSING_CHARACTER true
#define SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER true
#define SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER true
@@ -178,6 +180,8 @@ static void dumpWord(const unsigned short* word, const int length) {
#define WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE 75
#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
+#define WORDS_WITH_EQUIVALENT_CHAR_STRONG_PROMOTION_RATE 105
+#define WORDS_WITH_EQUIVALENT_CHAR_WEAK_DEMOTION_RATE 95
#define FULL_MATCHED_WORDS_PROMOTION_RATE 120
#define WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE 90
#define WORDS_WITH_MATCH_SKIP_PROMOTION_RATE 105
@@ -204,4 +208,7 @@ static void dumpWord(const unsigned short* word, const int length) {
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
+// The ratio of neutral area radius to sweet spot radius.
+#define NEUTRAL_AREA_RADIUS_RATIO 1.3f
+
#endif // LATINIME_DEFINES_H
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index 4ff6e0ac0..081cb61c3 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -43,7 +43,8 @@ ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboard
KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight),
CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
- KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)) {
+ KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
+ mInputXCoordinates(NULL), mInputYCoordinates(NULL) {
const int len = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
mProximityCharsArray = new uint32_t[len];
if (DEBUG_PROXIMITY_INFO) {
@@ -103,8 +104,11 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
}
// TODO: Calculate nearby codes here.
-void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength) {
+void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength,
+ const int* xCoordinates, const int* yCoordinates) {
mInputCodes = inputCodes;
+ mInputXCoordinates = xCoordinates;
+ mInputYCoordinates = yCoordinates;
mInputLength = inputLength;
for (int i = 0; i < inputLength; ++i) {
mPrimaryInputWord[i] = getPrimaryCharAt(i);
@@ -158,19 +162,37 @@ bool ProximityInfo::existsAdjacentProximityChars(const int index) const {
ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(
const int index, const unsigned short c, const bool checkProximityChars) const {
const int *currentChars = getProximityCharsAt(index);
+ const int firstChar = currentChars[0];
const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c);
// The first char in the array is what user typed. If it matches right away,
// that means the user typed that same char for this pos.
- if (currentChars[0] == baseLowerC || currentChars[0] == c)
- return SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR;
+ if (firstChar == baseLowerC || firstChar == c) {
+ if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES) {
+ const SweetSpotType result = calculateSweetSpotType(index, baseLowerC);
+ switch (result) {
+ case UNKNOWN:
+ return EQUIVALENT_CHAR_NORMAL;
+ case IN_SWEET_SPOT:
+ return EQUIVALENT_CHAR_STRONG;
+ case IN_NEUTRAL_AREA:
+ return EQUIVALENT_CHAR_NORMAL;
+ case OUT_OF_NEUTRAL_AREA:
+ return EQUIVALENT_CHAR_WEAK;
+ default:
+ assert(false);
+ }
+ } else {
+ return EQUIVALENT_CHAR_NORMAL;
+ }
+ }
if (!checkProximityChars) return UNRELATED_CHAR;
// If the non-accented, lowercased version of that first character matches c,
// then we have a non-accented version of the accented character the user
// typed. Treat it as a close char.
- if (Dictionary::toBaseLowerCase(currentChars[0]) == baseLowerC)
+ if (Dictionary::toBaseLowerCase(firstChar) == baseLowerC)
return NEAR_PROXIMITY_CHAR;
// Not an exact nor an accent-alike match: search the list of close keys
@@ -185,6 +207,38 @@ ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(
return UNRELATED_CHAR;
}
+inline float square(const float x) { return x * x; }
+
+ProximityInfo::SweetSpotType ProximityInfo::calculateSweetSpotType(
+ int index, unsigned short baseLowerC) const {
+ if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates
+ || baseLowerC > MAX_CHAR_CODE) {
+ return UNKNOWN;
+ }
+ const int keyIndex = mCodeToKeyIndex[baseLowerC];
+ if (keyIndex < 0) {
+ return UNKNOWN;
+ }
+ const float sweetSpotRadius = mSweetSpotRadii[keyIndex];
+ if (sweetSpotRadius <= 0.0) {
+ return UNKNOWN;
+ }
+ const float sweetSpotCenterX = mSweetSpotCenterXs[keyIndex];
+ const float sweetSpotCenterY = mSweetSpotCenterXs[keyIndex];
+ const float inputX = (float)mInputXCoordinates[index];
+ const float inputY = (float)mInputYCoordinates[index];
+ const float squaredDistance =
+ square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
+ const float squaredSweetSpotRadius = square(sweetSpotRadius);
+ if (squaredDistance <= squaredSweetSpotRadius) {
+ return IN_SWEET_SPOT;
+ }
+ if (squaredDistance <= square(NEUTRAL_AREA_RADIUS_RATIO) * squaredSweetSpotRadius) {
+ return IN_NEUTRAL_AREA;
+ }
+ return OUT_OF_NEUTRAL_AREA;
+}
+
bool ProximityInfo::sameAsTyped(const unsigned short *word, int length) const {
if (length != mInputLength) {
return false;
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index b1e8236d3..a705d0cf6 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -27,10 +27,18 @@ class Correction;
class ProximityInfo {
public:
- typedef enum { // Used as a return value for character comparison
- SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR, // Same char, possibly with different case or accent
- NEAR_PROXIMITY_CHAR, // It is a char located nearby on the keyboard
- UNRELATED_CHAR // It is an unrelated char
+ // Used as a return value for character comparison
+ typedef enum {
+ // Same char, possibly with different case or accent, and in the sweet spot of the char
+ EQUIVALENT_CHAR_STRONG,
+ // Same char, possibly with different case or accent, and in the outer sweet spot
+ EQUIVALENT_CHAR_NORMAL,
+ // Same char, possibly with different case or accent, and in the hit box of the char
+ EQUIVALENT_CHAR_WEAK,
+ // It is a char located nearby on the keyboard
+ NEAR_PROXIMITY_CHAR,
+ // It is an unrelated char
+ UNRELATED_CHAR
} ProximityType;
ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
@@ -41,7 +49,8 @@ public:
const float *sweetSpotCenterYs, const float *sweetSpotRadii);
~ProximityInfo();
bool hasSpaceProximity(const int x, const int y) const;
- void setInputParams(const int* inputCodes, const int inputLength);
+ void setInputParams(const int* inputCodes, const int inputLength,
+ const int *xCoordinates, const int *yCoordinates);
const int* getProximityCharsAt(const int index) const;
unsigned short getPrimaryCharAt(const int index) const;
bool existsCharInProximityAt(const int index, const int c) const;
@@ -59,8 +68,20 @@ private:
// The upper limit of the char code in mCodeToKeyIndex
static const int MAX_CHAR_CODE = 127;
+ typedef enum {
+ // cannot figure out the sweet spot type
+ UNKNOWN,
+ // touch position is out of neutral area of the given char
+ OUT_OF_NEUTRAL_AREA,
+ // touch position is in the neutral area of the given char
+ IN_NEUTRAL_AREA,
+ // touch position is in the sweet spot of the given char
+ IN_SWEET_SPOT
+ } SweetSpotType;
+
int getStartIndexFromCoordinates(const int x, const int y) const;
void initializeCodeToKeyIndex();
+ SweetSpotType calculateSweetSpotType(int index, unsigned short baseLowerC) const;
const int MAX_PROXIMITY_CHARS_SIZE;
const int KEYBOARD_WIDTH;
const int KEYBOARD_HEIGHT;
@@ -70,6 +91,8 @@ private:
const int CELL_HEIGHT;
const int KEY_COUNT;
const int *mInputCodes;
+ const int *mInputXCoordinates;
+ const int *mInputYCoordinates;
uint32_t *mProximityCharsArray;
int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 1b798a8f1..f23bd3208 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -240,8 +240,8 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
PROF_END(6);
}
-void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
- const int *ycoordinates, const int *codes, const int codesSize,
+void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xCoordinates,
+ const int *yCoordinates, const int *codes, const int codesSize,
unsigned short *outWords, int *frequencies) {
if (DEBUG_DICT) {
LOGI("initSuggest");
@@ -249,7 +249,7 @@ void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int
mFrequencies = frequencies;
mOutputChars = outWords;
mInputLength = codesSize;
- proximityInfo->setInputParams(codes, codesSize);
+ proximityInfo->setInputParams(codes, codesSize, xCoordinates, yCoordinates);
mProximityInfo = proximityInfo;
}